mirror of
https://github.com/getgrav/grav-plugin-admin.git
synced 2025-11-09 06:46:04 +01:00
Reworked Admin JS with ES6
This commit is contained in:
18
.editorconfig
Normal file
18
.editorconfig
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# EditorConfig is awesome: http://EditorConfig.org
|
||||||
|
|
||||||
|
# top-most EditorConfig file
|
||||||
|
root = true
|
||||||
|
|
||||||
|
# Unix-style newlines with a newline ending every file
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
end_of_line = lf
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
insert_final_newline = true
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
|
|
||||||
|
# 2 space indentation
|
||||||
|
[*.yaml, *.yml]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,2 +1,5 @@
|
|||||||
themes/grav/.sass-cache
|
themes/grav/.sass-cache
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
|
# Node Modules
|
||||||
|
**/node_modules/**
|
||||||
|
|||||||
@@ -571,7 +571,7 @@ class AdminPlugin extends Plugin
|
|||||||
$this->theme = $this->config->get('plugins.admin.theme', 'grav');
|
$this->theme = $this->config->get('plugins.admin.theme', 'grav');
|
||||||
|
|
||||||
$assets = $this->grav['assets'];
|
$assets = $this->grav['assets'];
|
||||||
$translations = 'if (!window.translations) window.translations = {}; ' . PHP_EOL . 'window.translations.PLUGIN_ADMIN = {};' . PHP_EOL;
|
$translations = 'this.GravAdmin = this.GravAdmin || {}; if (!this.GravAdmin.translations) this.GravAdmin.translations = {}; ' . PHP_EOL . 'this.GravAdmin.translations.PLUGIN_ADMIN = {';
|
||||||
|
|
||||||
// Enable language translations
|
// Enable language translations
|
||||||
$translations_actual_state = $this->config->get('system.languages.translations');
|
$translations_actual_state = $this->config->get('system.languages.translations');
|
||||||
@@ -597,13 +597,16 @@ class AdminPlugin extends Plugin
|
|||||||
'DAYS',
|
'DAYS',
|
||||||
'PAGE_MODES',
|
'PAGE_MODES',
|
||||||
'PAGE_TYPES',
|
'PAGE_TYPES',
|
||||||
'ACCESS_LEVELS'
|
'ACCESS_LEVELS',
|
||||||
|
'NOTHING_TO_SAVE'
|
||||||
];
|
];
|
||||||
|
|
||||||
foreach($strings as $string) {
|
foreach($strings as $string) {
|
||||||
$translations .= 'translations.PLUGIN_ADMIN.' . $string .' = "' . $this->admin->translate('PLUGIN_ADMIN.' . $string) . '"; ' . PHP_EOL;;
|
$separator = (end($strings) === $string) ? '' : ',';
|
||||||
|
$translations .= '"' . $string .'": "' . $this->admin->translate('PLUGIN_ADMIN.' . $string) . '"' . $separator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$translations .= '};';
|
||||||
// set the actual translations state back
|
// set the actual translations state back
|
||||||
$this->config->set('system.languages.translations', $translations_actual_state);
|
$this->config->set('system.languages.translations', $translations_actual_state);
|
||||||
|
|
||||||
|
|||||||
@@ -447,6 +447,7 @@ class AdminController
|
|||||||
'message' => $this->admin->translate('PLUGIN_ADMIN.YOUR_BACKUP_IS_READY_FOR_DOWNLOAD') . '. <a href="'.$url.'" class="button">' . $this->admin->translate('PLUGIN_ADMIN.DOWNLOAD_BACKUP') .'</a>',
|
'message' => $this->admin->translate('PLUGIN_ADMIN.YOUR_BACKUP_IS_READY_FOR_DOWNLOAD') . '. <a href="'.$url.'" class="button">' . $this->admin->translate('PLUGIN_ADMIN.DOWNLOAD_BACKUP') .'</a>',
|
||||||
'toastr' => [
|
'toastr' => [
|
||||||
'timeOut' => 0,
|
'timeOut' => 0,
|
||||||
|
'extendedTimeOut' => 0,
|
||||||
'closeButton' => true
|
'closeButton' => true
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
@@ -576,7 +577,7 @@ class AdminController
|
|||||||
foreach ($page->media()->all() as $name => $media) {
|
foreach ($page->media()->all() as $name => $media) {
|
||||||
$media_list[$name] = ['url' => $media->cropZoom(150, 100)->url(), 'size' => $media->get('size')];
|
$media_list[$name] = ['url' => $media->cropZoom(150, 100)->url(), 'size' => $media->get('size')];
|
||||||
}
|
}
|
||||||
$this->admin->json_response = ['status' => 'ok', 'results' => $media_list];
|
$this->admin->json_response = ['status' => 'success', 'results' => $media_list];
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -646,6 +647,7 @@ class AdminController
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Cache::clearCache();
|
||||||
$this->admin->json_response = ['status' => 'success', 'message' => $this->admin->translate('PLUGIN_ADMIN.FILE_UPLOADED_SUCCESSFULLY')];
|
$this->admin->json_response = ['status' => 'success', 'message' => $this->admin->translate('PLUGIN_ADMIN.FILE_UPLOADED_SUCCESSFULLY')];
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -675,6 +677,7 @@ class AdminController
|
|||||||
|
|
||||||
if (file_exists($targetPath)) {
|
if (file_exists($targetPath)) {
|
||||||
if (unlink($targetPath)) {
|
if (unlink($targetPath)) {
|
||||||
|
Cache::clearCache();
|
||||||
$this->admin->json_response = ['status' => 'success', 'message' => $this->admin->translate('PLUGIN_ADMIN.FILE_DELETED') . ': '.$filename];
|
$this->admin->json_response = ['status' => 'success', 'message' => $this->admin->translate('PLUGIN_ADMIN.FILE_DELETED') . ': '.$filename];
|
||||||
} else {
|
} else {
|
||||||
$this->admin->json_response = ['status' => 'error', 'message' => $this->admin->translate('PLUGIN_ADMIN.FILE_COULD_NOT_BE_DELETED') . ': '.$filename];
|
$this->admin->json_response = ['status' => 'error', 'message' => $this->admin->translate('PLUGIN_ADMIN.FILE_COULD_NOT_BE_DELETED') . ': '.$filename];
|
||||||
@@ -701,6 +704,7 @@ class AdminController
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($deletedResponsiveImage) {
|
if ($deletedResponsiveImage) {
|
||||||
|
Cache::clearCache();
|
||||||
$this->admin->json_response = ['status' => 'success', 'message' => $this->admin->translate('PLUGIN_ADMIN.FILE_DELETED') . ': '.$filename];
|
$this->admin->json_response = ['status' => 'success', 'message' => $this->admin->translate('PLUGIN_ADMIN.FILE_DELETED') . ': '.$filename];
|
||||||
} else {
|
} else {
|
||||||
$this->admin->json_response = ['status' => 'error', 'message' => $this->admin->translate('PLUGIN_ADMIN.FILE_NOT_FOUND') . ': '.$filename];
|
$this->admin->json_response = ['status' => 'error', 'message' => $this->admin->translate('PLUGIN_ADMIN.FILE_NOT_FOUND') . ': '.$filename];
|
||||||
@@ -887,9 +891,9 @@ class AdminController
|
|||||||
$result = \Grav\Plugin\Admin\Gpm::selfupgrade();
|
$result = \Grav\Plugin\Admin\Gpm::selfupgrade();
|
||||||
|
|
||||||
if ($result) {
|
if ($result) {
|
||||||
$this->admin->json_response = ['status' => 'success', 'message' => $this->admin->translate('PLUGIN_ADMIN.GRAV_WAS_SUCCESSFULLY_UPDATED_TO') . ' '];
|
$this->admin->json_response = ['status' => 'success', 'type' => 'updategrav', 'version' => GRAV_VERSION, 'message' => $this->admin->translate('PLUGIN_ADMIN.GRAV_WAS_SUCCESSFULLY_UPDATED_TO') . ' ' . GRAV_VERSION];
|
||||||
} else {
|
} else {
|
||||||
$this->admin->json_response = ['status' => 'error', 'message' => $this->admin->translate('PLUGIN_ADMIN.GRAV_UPDATE_FAILED') . ' <br>' . Installer::lastErrorMsg()];
|
$this->admin->json_response = ['status' => 'error', 'type' => 'updategrav', 'version' => GRAV_VERSION, 'message' => $this->admin->translate('PLUGIN_ADMIN.GRAV_UPDATE_FAILED') . ' <br>' . Installer::lastErrorMsg()];
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -935,9 +939,9 @@ class AdminController
|
|||||||
if ($this->view === 'update') {
|
if ($this->view === 'update') {
|
||||||
|
|
||||||
if ($result) {
|
if ($result) {
|
||||||
$this->admin->json_response = ['status' => 'success', 'message' => $this->admin->translate('PLUGIN_ADMIN.EVERYTHING_UPDATED')];
|
$this->admin->json_response = ['status' => 'success', 'type' => 'update', 'message' => $this->admin->translate('PLUGIN_ADMIN.EVERYTHING_UPDATED')];
|
||||||
} else {
|
} else {
|
||||||
$this->admin->json_response = ['status' => 'error', 'message' => $this->admin->translate('PLUGIN_ADMIN.UPDATES_FAILED')];
|
$this->admin->json_response = ['status' => 'error', 'type' => 'update', 'message' => $this->admin->translate('PLUGIN_ADMIN.UPDATES_FAILED')];
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -130,7 +130,7 @@ class Popularity
|
|||||||
$data[] = $count;
|
$data[] = $count;
|
||||||
}
|
}
|
||||||
|
|
||||||
return array('labels' => json_encode($labels), 'data' => json_encode($data));
|
return array('labels' => $labels, 'data' => $data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -475,3 +475,5 @@ PLUGIN_ADMIN:
|
|||||||
REVERSE_PROXY: "Reverse Proxy"
|
REVERSE_PROXY: "Reverse Proxy"
|
||||||
REVERSE_PROXY_HELP: "Enable this if you are behind a reverse proxy and you are having trouble with URLs containing incorrect ports"
|
REVERSE_PROXY_HELP: "Enable this if you are behind a reverse proxy and you are having trouble with URLs containing incorrect ports"
|
||||||
INVALID_FRONTMATTER_COULD_NOT_SAVE: "Invalid frontmatter, could not save"
|
INVALID_FRONTMATTER_COULD_NOT_SAVE: "Invalid frontmatter, could not save"
|
||||||
|
NOTHING_TO_SAVE: "Nothing to Save"
|
||||||
|
|
||||||
|
|||||||
181
themes/grav/.eslintrc
Normal file
181
themes/grav/.eslintrc
Normal file
@@ -0,0 +1,181 @@
|
|||||||
|
{
|
||||||
|
"env": {
|
||||||
|
"browser": true,
|
||||||
|
"node": true
|
||||||
|
},
|
||||||
|
|
||||||
|
"ecmaFeatures": {
|
||||||
|
"arrowFunctions": true,
|
||||||
|
"destructuring": true,
|
||||||
|
"classes": true,
|
||||||
|
"defaultParams": true,
|
||||||
|
"blockBindings": true,
|
||||||
|
"modules": true,
|
||||||
|
"objectLiteralComputedProperties": true,
|
||||||
|
"objectLiteralShorthandMethods": true,
|
||||||
|
"objectLiteralShorthandProperties": true,
|
||||||
|
"restParams": true,
|
||||||
|
"spread": true,
|
||||||
|
"forOf": true,
|
||||||
|
"generators": true,
|
||||||
|
"templateStrings": true,
|
||||||
|
"superInFunctions": true,
|
||||||
|
"experimentalObjectRestSpread": true
|
||||||
|
},
|
||||||
|
|
||||||
|
"rules": {
|
||||||
|
"accessor-pairs": 2,
|
||||||
|
"array-bracket-spacing": 0,
|
||||||
|
"block-scoped-var": 0,
|
||||||
|
"brace-style": [2, "1tbs", { "allowSingleLine": true }],
|
||||||
|
"camelcase": 0,
|
||||||
|
"comma-dangle": [2, "never"],
|
||||||
|
"comma-spacing": [2, { "before": false, "after": true }],
|
||||||
|
"comma-style": [2, "last"],
|
||||||
|
"complexity": 0,
|
||||||
|
"computed-property-spacing": 0,
|
||||||
|
"consistent-return": 0,
|
||||||
|
"consistent-this": 0,
|
||||||
|
"constructor-super": 2,
|
||||||
|
"curly": [2, "multi-line"],
|
||||||
|
"default-case": 0,
|
||||||
|
"dot-location": [2, "property"],
|
||||||
|
"dot-notation": 0,
|
||||||
|
"eol-last": 2,
|
||||||
|
"eqeqeq": [2, "allow-null"],
|
||||||
|
"func-names": 0,
|
||||||
|
"func-style": 0,
|
||||||
|
"generator-star-spacing": [2, { "before": true, "after": true }],
|
||||||
|
"guard-for-in": 0,
|
||||||
|
"handle-callback-err": [2, "^(err|error)$" ],
|
||||||
|
"indent": [2, 4, { "SwitchCase": 1 }],
|
||||||
|
"key-spacing": [2, { "beforeColon": false, "afterColon": true }],
|
||||||
|
"linebreak-style": 0,
|
||||||
|
"lines-around-comment": 0,
|
||||||
|
"max-nested-callbacks": 0,
|
||||||
|
"new-cap": [2, { "newIsCap": true, "capIsNew": false }],
|
||||||
|
"new-parens": 2,
|
||||||
|
"newline-after-var": 0,
|
||||||
|
"no-alert": 0,
|
||||||
|
"no-array-constructor": 2,
|
||||||
|
"no-caller": 2,
|
||||||
|
"no-catch-shadow": 0,
|
||||||
|
"no-cond-assign": 2,
|
||||||
|
"no-console": 0,
|
||||||
|
"no-constant-condition": 0,
|
||||||
|
"no-continue": 0,
|
||||||
|
"no-control-regex": 2,
|
||||||
|
"no-debugger": 2,
|
||||||
|
"no-delete-var": 2,
|
||||||
|
"no-div-regex": 0,
|
||||||
|
"no-dupe-args": 2,
|
||||||
|
"no-dupe-keys": 2,
|
||||||
|
"no-duplicate-case": 2,
|
||||||
|
"no-else-return": 0,
|
||||||
|
"no-empty": 0,
|
||||||
|
"no-empty-character-class": 2,
|
||||||
|
"no-empty-label": 2,
|
||||||
|
"no-eq-null": 0,
|
||||||
|
"no-eval": 2,
|
||||||
|
"no-ex-assign": 2,
|
||||||
|
"no-extend-native": 2,
|
||||||
|
"no-extra-bind": 2,
|
||||||
|
"no-extra-boolean-cast": 2,
|
||||||
|
"no-extra-parens": 0,
|
||||||
|
"no-extra-semi": 0,
|
||||||
|
"no-fallthrough": 2,
|
||||||
|
"no-floating-decimal": 2,
|
||||||
|
"no-func-assign": 2,
|
||||||
|
"no-implied-eval": 2,
|
||||||
|
"no-inline-comments": 0,
|
||||||
|
"no-inner-declarations": [2, "functions"],
|
||||||
|
"no-invalid-regexp": 2,
|
||||||
|
"no-irregular-whitespace": 2,
|
||||||
|
"no-iterator": 2,
|
||||||
|
"no-label-var": 2,
|
||||||
|
"no-labels": 2,
|
||||||
|
"no-lone-blocks": 2,
|
||||||
|
"no-lonely-if": 0,
|
||||||
|
"no-loop-func": 0,
|
||||||
|
"no-mixed-requires": 0,
|
||||||
|
"no-mixed-spaces-and-tabs": 2,
|
||||||
|
"no-multi-spaces": 2,
|
||||||
|
"no-multi-str": 2,
|
||||||
|
"no-multiple-empty-lines": [2, { "max": 1 }],
|
||||||
|
"no-native-reassign": 2,
|
||||||
|
"no-negated-in-lhs": 2,
|
||||||
|
"no-nested-ternary": 0,
|
||||||
|
"no-new": 2,
|
||||||
|
"no-new-func": 0,
|
||||||
|
"no-new-object": 2,
|
||||||
|
"no-new-require": 2,
|
||||||
|
"no-new-wrappers": 2,
|
||||||
|
"no-obj-calls": 2,
|
||||||
|
"no-octal": 2,
|
||||||
|
"no-octal-escape": 2,
|
||||||
|
"no-param-reassign": 0,
|
||||||
|
"no-path-concat": 0,
|
||||||
|
"no-process-env": 0,
|
||||||
|
"no-process-exit": 0,
|
||||||
|
"no-proto": 0,
|
||||||
|
"no-redeclare": 2,
|
||||||
|
"no-regex-spaces": 2,
|
||||||
|
"no-restricted-modules": 0,
|
||||||
|
"no-return-assign": 2,
|
||||||
|
"no-script-url": 0,
|
||||||
|
"no-self-compare": 2,
|
||||||
|
"no-sequences": 2,
|
||||||
|
"no-shadow": 0,
|
||||||
|
"no-shadow-restricted-names": 2,
|
||||||
|
"no-spaced-func": 2,
|
||||||
|
"no-sparse-arrays": 2,
|
||||||
|
"no-sync": 0,
|
||||||
|
"no-ternary": 0,
|
||||||
|
"no-this-before-super": 2,
|
||||||
|
"no-throw-literal": 2,
|
||||||
|
"no-trailing-spaces": 2,
|
||||||
|
"no-undef": 2,
|
||||||
|
"no-undef-init": 2,
|
||||||
|
"no-undefined": 0,
|
||||||
|
"no-underscore-dangle": 0,
|
||||||
|
"no-unexpected-multiline": 2,
|
||||||
|
"no-unneeded-ternary": 2,
|
||||||
|
"no-unreachable": 2,
|
||||||
|
"no-unused-expressions": 0,
|
||||||
|
"no-unused-vars": [2, { "vars": "all", "args": "none" }],
|
||||||
|
"no-use-before-define": 0,
|
||||||
|
"no-var": 0,
|
||||||
|
"no-void": 0,
|
||||||
|
"no-warning-comments": 0,
|
||||||
|
"no-with": 2,
|
||||||
|
"object-curly-spacing": 0,
|
||||||
|
"object-shorthand": 0,
|
||||||
|
"one-var": [2, { "initialized": "never" }],
|
||||||
|
"operator-assignment": 0,
|
||||||
|
"operator-linebreak": [2, "after", { "overrides": { "?": "before", ":": "before" } }],
|
||||||
|
"padded-blocks": 0,
|
||||||
|
"prefer-const": 0,
|
||||||
|
"quote-props": 0,
|
||||||
|
"quotes": [2, "single", "avoid-escape"],
|
||||||
|
"radix": 2,
|
||||||
|
"semi": [2, "always"],
|
||||||
|
"semi-spacing": 0,
|
||||||
|
"sort-vars": 0,
|
||||||
|
"space-after-keywords": [2, "always"],
|
||||||
|
"space-before-blocks": [2, "always"],
|
||||||
|
"space-before-function-paren": [2, "never"],
|
||||||
|
"space-in-parens": [2, "never"],
|
||||||
|
"space-infix-ops": 2,
|
||||||
|
"space-return-throw-case": 2,
|
||||||
|
"space-unary-ops": [2, { "words": true, "nonwords": false }],
|
||||||
|
"spaced-comment": [2, "always", { "markers": ["global", "globals", "eslint", "eslint-disable", "*package", "!"] }],
|
||||||
|
"strict": 0,
|
||||||
|
"use-isnan": 2,
|
||||||
|
"valid-jsdoc": 0,
|
||||||
|
"valid-typeof": 2,
|
||||||
|
"vars-on-top": 0,
|
||||||
|
"wrap-iife": [2, "any"],
|
||||||
|
"wrap-regex": 0,
|
||||||
|
"yoda": [2, "never"]
|
||||||
|
}
|
||||||
|
}
|
||||||
24
themes/grav/app/dashboard/backup.js
Normal file
24
themes/grav/app/dashboard/backup.js
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
import $ from 'jquery';
|
||||||
|
import { translations } from 'grav-config';
|
||||||
|
import request from '../utils/request';
|
||||||
|
import { Instances as Charts } from './chart';
|
||||||
|
|
||||||
|
$('[data-ajax*="task:backup"]').on('click', function() {
|
||||||
|
let element = $(this);
|
||||||
|
let url = element.data('ajax');
|
||||||
|
|
||||||
|
element
|
||||||
|
.attr('disabled', 'disabled')
|
||||||
|
.find('> .fa').removeClass('fa-database').addClass('fa-spin fa-refresh');
|
||||||
|
|
||||||
|
request(url, (/* response */) => {
|
||||||
|
if (Charts && Charts.backups) {
|
||||||
|
Charts.backups.updateData({ series: [0, 100] });
|
||||||
|
Charts.backups.element.find('.numeric').html(`0 <em>${translations.PLUGIN_ADMIN.DAYS.toLowerCase()}</em>`);
|
||||||
|
}
|
||||||
|
|
||||||
|
element
|
||||||
|
.removeAttr('disabled')
|
||||||
|
.find('> .fa').removeClass('fa-spin fa-refresh').addClass('fa-database');
|
||||||
|
});
|
||||||
|
});
|
||||||
49
themes/grav/app/dashboard/cache.js
Normal file
49
themes/grav/app/dashboard/cache.js
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
import $ from 'jquery';
|
||||||
|
import { config } from 'grav-config';
|
||||||
|
import request from '../utils/request';
|
||||||
|
|
||||||
|
const getUrl = (type = '') => {
|
||||||
|
if (type) {
|
||||||
|
type = `cleartype:${type}/`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return `${config.base_url_relative}/cache.json/task:clearCache/${type}admin-nonce:${config.admin_nonce}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default class Cache {
|
||||||
|
constructor() {
|
||||||
|
this.element = $('[data-clear-cache]');
|
||||||
|
$('body').on('click', '[data-clear-cache]', (event) => this.clear(event, event.target));
|
||||||
|
}
|
||||||
|
|
||||||
|
clear(event, element) {
|
||||||
|
let type = '';
|
||||||
|
|
||||||
|
if (event && event.preventDefault) { event.preventDefault(); }
|
||||||
|
if (typeof event === 'string') { type = event; }
|
||||||
|
|
||||||
|
element = element ? $(element) : $(`[data-clear-cache-type="${type}"]`);
|
||||||
|
type = type || $(element).data('clear-cache-type') || '';
|
||||||
|
let url = element.data('clearCache') || getUrl(event);
|
||||||
|
|
||||||
|
this.disable();
|
||||||
|
|
||||||
|
request(url, () => this.enable());
|
||||||
|
}
|
||||||
|
|
||||||
|
enable() {
|
||||||
|
this.element
|
||||||
|
.removeAttr('disabled')
|
||||||
|
.find('> .fa').removeClass('fa-refresh fa-spin').addClass('fa-trash');
|
||||||
|
}
|
||||||
|
|
||||||
|
disable() {
|
||||||
|
this.element
|
||||||
|
.attr('disabled', 'disabled')
|
||||||
|
.find('> .fa').removeClass('fa-trash').addClass('fa-refresh fa-spin');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let Instance = new Cache();
|
||||||
|
|
||||||
|
export { Instance };
|
||||||
124
themes/grav/app/dashboard/chart.js
Normal file
124
themes/grav/app/dashboard/chart.js
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
import $ from 'jquery';
|
||||||
|
import chartist from 'chartist';
|
||||||
|
import { translations } from 'grav-config';
|
||||||
|
import { Instance as gpm } from '../utils/gpm';
|
||||||
|
import { Instance as updates } from '../updates';
|
||||||
|
|
||||||
|
let isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
|
||||||
|
|
||||||
|
export const defaults = {
|
||||||
|
data: {
|
||||||
|
series: [100, 0]
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
Pie: {
|
||||||
|
donut: true,
|
||||||
|
donutWidth: 10,
|
||||||
|
startAngle: 0,
|
||||||
|
total: 100,
|
||||||
|
showLabel: false,
|
||||||
|
height: 150,
|
||||||
|
chartPadding: !isFirefox ? 10 : 25
|
||||||
|
},
|
||||||
|
Bar: {
|
||||||
|
height: 164,
|
||||||
|
chartPadding: !isFirefox ? 5 : 25,
|
||||||
|
|
||||||
|
axisX: {
|
||||||
|
showGrid: false,
|
||||||
|
labelOffset: {
|
||||||
|
x: 0,
|
||||||
|
y: 5
|
||||||
|
}
|
||||||
|
},
|
||||||
|
axisY: {
|
||||||
|
offset: 15,
|
||||||
|
showLabel: true,
|
||||||
|
showGrid: true,
|
||||||
|
labelOffset: {
|
||||||
|
x: 5,
|
||||||
|
y: 5
|
||||||
|
},
|
||||||
|
scaleMinSpace: 20
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default class Chart {
|
||||||
|
constructor(element, options = {}, data = {}) {
|
||||||
|
this.element = $(element) || [];
|
||||||
|
if (!this.element[0]) { return; }
|
||||||
|
|
||||||
|
let type = (this.element.data('chart-type') || 'pie').toLowerCase();
|
||||||
|
this.type = type.charAt(0).toUpperCase() + type.substr(1).toLowerCase();
|
||||||
|
|
||||||
|
options = Object.assign({}, defaults.options[this.type], options);
|
||||||
|
data = Object.assign({}, defaults.data, data);
|
||||||
|
Object.assign(this, {
|
||||||
|
options,
|
||||||
|
data
|
||||||
|
});
|
||||||
|
this.chart = chartist[this.type](this.element.find('.ct-chart')[0], this.data, this.options);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateData(data) {
|
||||||
|
Object.assign(this.data, data);
|
||||||
|
this.chart.update(this.data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export class UpdatesChart extends Chart {
|
||||||
|
constructor(element, options = {}, data = {}) {
|
||||||
|
super(element, options, data);
|
||||||
|
|
||||||
|
this.chart.on('draw', (data) => this.draw(data));
|
||||||
|
|
||||||
|
gpm.on('fetched', (response) => {
|
||||||
|
let payload = response.payload.grav;
|
||||||
|
let missing = (response.payload.resources.total + (payload.isUpdatable ? 1 : 0)) * 100 / (response.payload.installed + (payload.isUpdatable ? 1 : 0));
|
||||||
|
let updated = 100 - missing;
|
||||||
|
|
||||||
|
this.updateData({ series: [updated, missing] });
|
||||||
|
|
||||||
|
if (response.payload.resources.total) {
|
||||||
|
updates.maintenance('show');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
draw(data) {
|
||||||
|
if (data.index) { return; }
|
||||||
|
|
||||||
|
let notice = translations.PLUGIN_ADMIN[data.value === 100 ? 'FULLY_UPDATED' : 'UPDATES_AVAILABLE'];
|
||||||
|
this.element.find('.numeric span').text(`${Math.round(data.value)}%`);
|
||||||
|
this.element.find('.js__updates-available-description').html(notice);
|
||||||
|
this.element.find('.hidden').removeClass('hidden');
|
||||||
|
}
|
||||||
|
|
||||||
|
updateData(data) {
|
||||||
|
super.updateData(data);
|
||||||
|
|
||||||
|
// missing updates
|
||||||
|
if (this.data.series[0] < 100) {
|
||||||
|
this.element.closest('#updates').find('[data-maintenance-update]').fadeIn();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let charts = {};
|
||||||
|
|
||||||
|
$('[data-chart-name]').each(function() {
|
||||||
|
let element = $(this);
|
||||||
|
let name = element.data('chart-name') || '';
|
||||||
|
let options = element.data('chart-options') || {};
|
||||||
|
let data = element.data('chart-data') || {};
|
||||||
|
|
||||||
|
if (name === 'updates') {
|
||||||
|
charts[name] = new UpdatesChart(element, options, data);
|
||||||
|
} else {
|
||||||
|
charts[name] = new Chart(element, options, data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export let Instances = charts;
|
||||||
12
themes/grav/app/dashboard/index.js
Normal file
12
themes/grav/app/dashboard/index.js
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import Chart, { UpdatesChart, Instances } from './chart';
|
||||||
|
import { Instance as Cache } from './cache';
|
||||||
|
import './backup';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
Chart: {
|
||||||
|
Chart,
|
||||||
|
UpdatesChart,
|
||||||
|
Instances
|
||||||
|
},
|
||||||
|
Cache
|
||||||
|
};
|
||||||
1
themes/grav/app/dashboard/update.js
Normal file
1
themes/grav/app/dashboard/update.js
Normal file
@@ -0,0 +1 @@
|
|||||||
|
// See ../updates/update.js
|
||||||
146
themes/grav/app/forms/fields/array.js
Normal file
146
themes/grav/app/forms/fields/array.js
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
import $ from 'jquery';
|
||||||
|
|
||||||
|
let body = $('body');
|
||||||
|
|
||||||
|
class Template {
|
||||||
|
constructor(container) {
|
||||||
|
this.container = $(container);
|
||||||
|
|
||||||
|
if (this.getName() === undefined) {
|
||||||
|
this.container = this.container.closest('[data-grav-array-name]');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getName() {
|
||||||
|
return this.container.data('grav-array-name') || '';
|
||||||
|
}
|
||||||
|
|
||||||
|
getKeyPlaceholder() {
|
||||||
|
return this.container.data('grav-array-keyname') || 'Key';
|
||||||
|
}
|
||||||
|
|
||||||
|
getValuePlaceholder() {
|
||||||
|
return this.container.data('grav-array-valuename') || 'Value';
|
||||||
|
}
|
||||||
|
|
||||||
|
isValueOnly() {
|
||||||
|
return this.container.find('[data-grav-array-mode="value_only"]:first').length || false;
|
||||||
|
}
|
||||||
|
|
||||||
|
shouldBeDisabled() {
|
||||||
|
// check for toggleables, if field is toggleable and it's not enabled, render disabled
|
||||||
|
let toggle = this.container.closest('.form-field').find('[data-grav-field="toggleable"] input[type="checkbox"]');
|
||||||
|
return toggle.length && toggle.is(':not(:checked)');
|
||||||
|
}
|
||||||
|
|
||||||
|
getNewRow() {
|
||||||
|
let tpl = '';
|
||||||
|
|
||||||
|
if (this.isValueOnly()) {
|
||||||
|
tpl += `
|
||||||
|
<div class="form-row array-field-value_only" data-grav-array-type="row">
|
||||||
|
<input ${this.shouldBeDisabled() ? 'disabled="disabled"' : ''} data-grav-array-type="value" type="text" value="" placeholder="${this.getValuePlaceholder()}" />
|
||||||
|
`;
|
||||||
|
} else {
|
||||||
|
tpl += `
|
||||||
|
<div class="form-row" data-grav-array-type="row">
|
||||||
|
<input ${this.shouldBeDisabled() ? 'disabled="disabled"' : ''} data-grav-array-type="key" type="text" value="" placeholder="${this.getKeyPlaceholder()}" />
|
||||||
|
<input ${this.shouldBeDisabled() ? 'disabled="disabled"' : ''} data-grav-array-type="value" type="text" name="" value="" placeholder="${this.getValuePlaceholder()}" />
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
tpl += `
|
||||||
|
<span data-grav-array-action="rem" class="fa fa-minus"></span>
|
||||||
|
<span data-grav-array-action="add" class="fa fa-plus"></span>
|
||||||
|
</div>`;
|
||||||
|
|
||||||
|
return tpl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class ArrayField {
|
||||||
|
constructor() {
|
||||||
|
body.on('input', '[data-grav-array-type="key"], [data-grav-array-type="value"]', (event) => this.actionInput(event));
|
||||||
|
body.on('click touch', '[data-grav-array-action]', (event) => this.actionEvent(event));
|
||||||
|
}
|
||||||
|
|
||||||
|
actionInput(event) {
|
||||||
|
let element = $(event.target);
|
||||||
|
let type = element.data('grav-array-type');
|
||||||
|
|
||||||
|
this._setTemplate(element);
|
||||||
|
|
||||||
|
let template = element.data('array-template');
|
||||||
|
let keyElement = type === 'key' ? element : element.siblings('[data-grav-array-type="key"]:first');
|
||||||
|
let valueElement = type === 'value' ? element : element.siblings('[data-grav-array-type="value"]:first');
|
||||||
|
|
||||||
|
let name = `${template.getName()}[${!template.isValueOnly() ? keyElement.val() : this.getIndexFor(element)}]`;
|
||||||
|
valueElement.attr('name', !valueElement.val() ? template.getName() : name);
|
||||||
|
|
||||||
|
this.refreshNames(template);
|
||||||
|
}
|
||||||
|
|
||||||
|
actionEvent(event) {
|
||||||
|
let element = $(event.target);
|
||||||
|
let action = element.data('grav-array-action');
|
||||||
|
|
||||||
|
this._setTemplate(element);
|
||||||
|
|
||||||
|
this[`${action}Action`](element);
|
||||||
|
}
|
||||||
|
|
||||||
|
addAction(element) {
|
||||||
|
let template = element.data('array-template');
|
||||||
|
let row = element.closest('[data-grav-array-type="row"]');
|
||||||
|
|
||||||
|
row.after(template.getNewRow());
|
||||||
|
}
|
||||||
|
|
||||||
|
remAction(element) {
|
||||||
|
let template = element.data('array-template');
|
||||||
|
let row = element.closest('[data-grav-array-type="row"]');
|
||||||
|
let isLast = !row.siblings().length;
|
||||||
|
|
||||||
|
if (isLast) {
|
||||||
|
let newRow = $(template.getNewRow());
|
||||||
|
row.after(newRow);
|
||||||
|
newRow.find('[data-grav-array-type="value"]:last').attr('name', template.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
row.remove();
|
||||||
|
this.refreshNames(template);
|
||||||
|
}
|
||||||
|
|
||||||
|
refreshNames(template) {
|
||||||
|
if (!template.isValueOnly()) { return; }
|
||||||
|
|
||||||
|
let row = template.container.find('> div > [data-grav-array-type="row"]');
|
||||||
|
let inputs = row.find('[name]:not([name=""])');
|
||||||
|
|
||||||
|
inputs.each((index, input) => {
|
||||||
|
input = $(input);
|
||||||
|
let name = input.attr('name');
|
||||||
|
name = name.replace(/\[\d+\]$/, `[${index}]`);
|
||||||
|
input.attr('name', name);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!inputs.length) {
|
||||||
|
row.find('[data-grav-array-type="value"]').attr('name', template.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getIndexFor(element) {
|
||||||
|
let template = element.data('array-template');
|
||||||
|
let row = element.closest('[data-grav-array-type="row"]');
|
||||||
|
|
||||||
|
return template.container.find(`${template.isValueOnly() ? '> div ' : ''} > [data-grav-array-type="row"]`).index(row);
|
||||||
|
}
|
||||||
|
|
||||||
|
_setTemplate(element) {
|
||||||
|
if (!element.data('array-template')) {
|
||||||
|
element.data('array-template', new Template(element.closest('[data-grav-array-name]')));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export let Instance = new ArrayField();
|
||||||
98
themes/grav/app/forms/fields/collections.js
Normal file
98
themes/grav/app/forms/fields/collections.js
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
import $ from 'jquery';
|
||||||
|
import Sortable from 'sortablejs';
|
||||||
|
import '../../utils/jquery-utils';
|
||||||
|
|
||||||
|
export default class CollectionsField {
|
||||||
|
constructor() {
|
||||||
|
this.lists = $();
|
||||||
|
|
||||||
|
$('[data-type="collection"]').each((index, list) => this.addList(list));
|
||||||
|
$('body').on('mutation._grav', this._onAddedNodes.bind(this));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
addList(list) {
|
||||||
|
list = $(list);
|
||||||
|
this.lists = this.lists.add(list);
|
||||||
|
|
||||||
|
list.on('click', '> .collection-actions [data-action="add"]', (event) => this.addItem(event));
|
||||||
|
list.on('click', '> ul > li > .item-actions [data-action="delete"]', (event) => this.removeItem(event));
|
||||||
|
|
||||||
|
list.find('[data-collection-holder]').each((index, container) => {
|
||||||
|
container = $(container);
|
||||||
|
if (container.data('collection-sort')) { return; }
|
||||||
|
|
||||||
|
container.data('collection-sort', new Sortable(container.get(0), {
|
||||||
|
forceFallback: true,
|
||||||
|
animation: 150,
|
||||||
|
onUpdate: () => this.reindex(container)
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
addItem(event) {
|
||||||
|
let button = $(event.currentTarget);
|
||||||
|
let list = button.closest('[data-type="collection"]');
|
||||||
|
let template = $(list.find('> [data-collection-template="new"]').data('collection-template-html'));
|
||||||
|
|
||||||
|
list.find('> [data-collection-holder]').append(template);
|
||||||
|
this.reindex(list);
|
||||||
|
// button.data('key-index', keyIndex + 1);
|
||||||
|
|
||||||
|
// process markdown editors
|
||||||
|
/* var field = template.find('[name]').filter('textarea');
|
||||||
|
if (field.length && field.data('grav-mdeditor') && typeof MDEditors !== 'undefined') {
|
||||||
|
MDEditors.add(field);
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
|
||||||
|
removeItem(event) {
|
||||||
|
let button = $(event.currentTarget);
|
||||||
|
let item = button.closest('[data-collection-item]');
|
||||||
|
let list = button.closest('[data-type="collection"]');
|
||||||
|
|
||||||
|
item.remove();
|
||||||
|
this.reindex(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
reindex(list) {
|
||||||
|
list = $(list).closest('[data-type="collection"]');
|
||||||
|
|
||||||
|
let items = list.find('> ul > [data-collection-item]');
|
||||||
|
|
||||||
|
items.each((index, item) => {
|
||||||
|
item = $(item);
|
||||||
|
item.attr('data-collection-key', index);
|
||||||
|
|
||||||
|
['name', 'data-grav-field-name', 'id', 'for'].forEach((prop) => {
|
||||||
|
item.find('[' + prop + ']').each(function() {
|
||||||
|
let element = $(this);
|
||||||
|
let indexes = [];
|
||||||
|
element.parents('[data-collection-key]').map((idx, parent) => indexes.push($(parent).attr('data-collection-key')));
|
||||||
|
indexes.reverse();
|
||||||
|
|
||||||
|
let replaced = element.attr(prop).replace(/\[(\d+|\*)\]/g, (/* str, p1, offset */) => {
|
||||||
|
return `[${indexes.shift()}]`;
|
||||||
|
});
|
||||||
|
|
||||||
|
element.attr(prop, replaced);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
_onAddedNodes(event, target/* , record, instance */) {
|
||||||
|
let collections = $(target).find('[data-type="collection"]');
|
||||||
|
if (!collections.length) { return; }
|
||||||
|
|
||||||
|
collections.each((index, collection) => {
|
||||||
|
collection = $(collection);
|
||||||
|
if (!~this.lists.index(collection)) {
|
||||||
|
this.addList(collection);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export let Instance = new CollectionsField();
|
||||||
18
themes/grav/app/forms/fields/index.js
Normal file
18
themes/grav/app/forms/fields/index.js
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import SelectizeField, { Instance as SelectizeFieldInstance } from './selectize';
|
||||||
|
import ArrayField, { Instance as ArrayFieldInstance } from './array';
|
||||||
|
import CollectionsField, { Instance as CollectionsFieldInstance } from './collections';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
SelectizeField: {
|
||||||
|
SelectizeField,
|
||||||
|
Instance: SelectizeFieldInstance
|
||||||
|
},
|
||||||
|
ArrayField: {
|
||||||
|
ArrayField,
|
||||||
|
Instance: ArrayFieldInstance
|
||||||
|
},
|
||||||
|
CollectionsField: {
|
||||||
|
CollectionsField,
|
||||||
|
Instance: CollectionsFieldInstance
|
||||||
|
}
|
||||||
|
};
|
||||||
35
themes/grav/app/forms/fields/selectize.js
Normal file
35
themes/grav/app/forms/fields/selectize.js
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
import $ from 'jquery';
|
||||||
|
import 'selectize';
|
||||||
|
|
||||||
|
export default class SelectizeField {
|
||||||
|
constructor(options = {}) {
|
||||||
|
this.options = Object.assign({}, options);
|
||||||
|
this.elements = [];
|
||||||
|
|
||||||
|
$('[data-grav-selectize]').each((index, element) => this.add(element));
|
||||||
|
$('body').on('mutation._grav', this._onAddedNodes.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
add(element) {
|
||||||
|
element = $(element);
|
||||||
|
let tag = element.prop('tagName').toLowerCase();
|
||||||
|
let isInput = tag === 'input' || tag === 'select';
|
||||||
|
|
||||||
|
let data = (isInput ? element.closest('[data-grav-selectize]') : element).data('grav-selectize') || {};
|
||||||
|
let field = (isInput ? element : element.find('input, select'));
|
||||||
|
|
||||||
|
if (!field.length || field.get(0).selectize) { return; }
|
||||||
|
field.selectize(data);
|
||||||
|
|
||||||
|
this.elements.push(field.data('selectize'));
|
||||||
|
}
|
||||||
|
|
||||||
|
_onAddedNodes(event, target/* , record, instance */) {
|
||||||
|
let fields = $(target).find('select.fancy, input.fancy');
|
||||||
|
if (!fields.length) { return; }
|
||||||
|
|
||||||
|
fields.each((index, field) => this.add(field));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export let Instance = new SelectizeField();
|
||||||
104
themes/grav/app/forms/form.js
Normal file
104
themes/grav/app/forms/form.js
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
import $ from 'jquery';
|
||||||
|
import toastr from '../utils/toastr';
|
||||||
|
import { translations } from 'grav-config';
|
||||||
|
import { Instance as FormState } from './state';
|
||||||
|
|
||||||
|
export default class Form {
|
||||||
|
constructor(form) {
|
||||||
|
this.form = $(form);
|
||||||
|
if (!this.form.length || this.form.prop('tagName').toLowerCase() !== 'form') { return; }
|
||||||
|
|
||||||
|
this.form.on('submit', (event) => {
|
||||||
|
if (FormState.equals()) {
|
||||||
|
event.preventDefault();
|
||||||
|
toastr.info(translations.PLUGIN_ADMIN.NOTHING_TO_SAVE);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this._attachShortcuts();
|
||||||
|
this._attachToggleables();
|
||||||
|
this._attachDisabledFields();
|
||||||
|
|
||||||
|
this.observer = new MutationObserver(this.addedNodes);
|
||||||
|
this.form.each((index, form) => this.observer.observe(form, { subtree: true, childList: true }));
|
||||||
|
}
|
||||||
|
|
||||||
|
_attachShortcuts() {
|
||||||
|
// CTRL + S / CMD + S - shortcut for [Save] when available
|
||||||
|
let saveTask = $('[name="task"][value="save"]').filter(function(index, element) {
|
||||||
|
element = $(element);
|
||||||
|
return !(element.parents('.remodal-overlay').length);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (saveTask.length) {
|
||||||
|
$(window).on('keydown', function(event) {
|
||||||
|
var key = String.fromCharCode(event.which).toLowerCase();
|
||||||
|
if ((event.ctrlKey || event.metaKey) && key === 's') {
|
||||||
|
event.preventDefault();
|
||||||
|
saveTask.click();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_attachToggleables() {
|
||||||
|
let query = '[data-grav-field="toggleable"] input[type="checkbox"]';
|
||||||
|
|
||||||
|
this.form.on('change', query, (event) => {
|
||||||
|
let toggle = $(event.target);
|
||||||
|
let enabled = toggle.is(':checked');
|
||||||
|
let parent = toggle.parents('.form-field');
|
||||||
|
let label = parent.find('label.toggleable');
|
||||||
|
let fields = parent.find('.form-data');
|
||||||
|
let inputs = fields.find('input, select, textarea');
|
||||||
|
|
||||||
|
label.add(fields).css('opacity', enabled ? '' : 0.7);
|
||||||
|
inputs.map((index, input) => {
|
||||||
|
let isSelectize = input.selectize;
|
||||||
|
input = $(input);
|
||||||
|
|
||||||
|
if (isSelectize) {
|
||||||
|
isSelectize[enabled ? 'enable' : 'disable']();
|
||||||
|
} else {
|
||||||
|
input.prop('disabled', !enabled);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
this.form.find(query).trigger('change');
|
||||||
|
}
|
||||||
|
|
||||||
|
_attachDisabledFields() {
|
||||||
|
let prefix = '.form-field-toggleable .form-data';
|
||||||
|
let query = [];
|
||||||
|
|
||||||
|
['input', 'select', 'label[for]', 'textarea', '.selectize-control'].forEach((item) => {
|
||||||
|
query.push(`${prefix} ${item}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.form.on('mousedown', query.join(', '), (event) => {
|
||||||
|
let target = $(event.target);
|
||||||
|
let input = target;
|
||||||
|
let isFor = input.prop('for');
|
||||||
|
let isSelectize = (input.hasClass('selectize-control') || input.parents('.selectize-control')).length;
|
||||||
|
|
||||||
|
if (isFor) { input = $(`[id="${isFor}"]`); }
|
||||||
|
if (isSelectize) { input = input.closest('.selectize-control').siblings('select[name]'); }
|
||||||
|
|
||||||
|
if (!input.prop('disabled')) { return true; }
|
||||||
|
|
||||||
|
let toggle = input.closest('.form-field').find('[data-grav-field="toggleable"] input[type="checkbox"]');
|
||||||
|
toggle.trigger('click');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
addedNodes(mutations) {
|
||||||
|
mutations.forEach((mutation) => {
|
||||||
|
if (mutation.type !== 'childList' || !mutation.addedNodes) { return; }
|
||||||
|
|
||||||
|
$('body').trigger('mutation._grav', mutation.target, mutation, this);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export let Instance = new Form('form#blueprints');
|
||||||
16
themes/grav/app/forms/index.js
Normal file
16
themes/grav/app/forms/index.js
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import FormState, { Instance as FormStateInstance } from './state';
|
||||||
|
import Form, { Instance as FormInstance } from './form';
|
||||||
|
|
||||||
|
import Fields from './fields';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
Form: {
|
||||||
|
Form,
|
||||||
|
Instance: FormInstance
|
||||||
|
},
|
||||||
|
Fields,
|
||||||
|
FormState: {
|
||||||
|
FormState,
|
||||||
|
Instance: FormStateInstance
|
||||||
|
}
|
||||||
|
};
|
||||||
122
themes/grav/app/forms/state.js
Normal file
122
themes/grav/app/forms/state.js
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
import $ from 'jquery';
|
||||||
|
import Immutable from 'immutable';
|
||||||
|
import '../utils/jquery-utils';
|
||||||
|
|
||||||
|
let FormLoadState = {};
|
||||||
|
|
||||||
|
const DOMBehaviors = {
|
||||||
|
attach() {
|
||||||
|
this.preventUnload();
|
||||||
|
this.preventClickAway();
|
||||||
|
},
|
||||||
|
|
||||||
|
preventUnload() {
|
||||||
|
if ($._data(window, 'events') && ($._data(window, 'events').beforeunload || []).filter((event) => event.namespace === '_grav')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Catch browser uri change / refresh attempt and stop it if the form state is dirty
|
||||||
|
$(window).on('beforeunload._grav', () => {
|
||||||
|
if (Instance.equals() === false) {
|
||||||
|
return `You have made changes on this page that you have not yet confirmed. If you navigate away from this page you will lose your unsaved changes.`;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
preventClickAway() {
|
||||||
|
let selector = 'a[href]:not([href^=#])';
|
||||||
|
|
||||||
|
if ($._data($(selector).get(0), 'events') && ($._data($(selector).get(0), 'events').click || []).filter((event) => event.namespace === '_grav')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prevent clicking away if the form state is dirty
|
||||||
|
// instead, display a confirmation before continuing
|
||||||
|
$(selector).on('click._grav', function(event) {
|
||||||
|
let isClean = Instance.equals();
|
||||||
|
if (isClean === null || isClean) { return true; }
|
||||||
|
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
let destination = $(this).attr('href');
|
||||||
|
let modal = $('[data-remodal-id="changes"]');
|
||||||
|
let lookup = $.remodal.lookup[modal.data('remodal')];
|
||||||
|
let buttons = $('a.button', modal);
|
||||||
|
|
||||||
|
let handler = function(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
let action = $(this).data('leave-action');
|
||||||
|
|
||||||
|
buttons.off('click', handler);
|
||||||
|
lookup.close();
|
||||||
|
|
||||||
|
if (action === 'continue') {
|
||||||
|
$(window).off('beforeunload');
|
||||||
|
window.location.href = destination;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
buttons.on('click', handler);
|
||||||
|
lookup.open();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default class FormState {
|
||||||
|
constructor(options = {
|
||||||
|
ignore: [],
|
||||||
|
form_id: 'blueprints'
|
||||||
|
}) {
|
||||||
|
this.options = options;
|
||||||
|
this.refresh();
|
||||||
|
|
||||||
|
if (!this.form || !this.fields.length) { return; }
|
||||||
|
FormLoadState = this.collect();
|
||||||
|
DOMBehaviors.attach();
|
||||||
|
}
|
||||||
|
|
||||||
|
refresh() {
|
||||||
|
this.form = $(`form#${this.options.form_id}`).filter(':noparents(.remodal)');
|
||||||
|
this.fields = $(`form#${this.options.form_id} *, [form="${this.options.form_id}"]`).filter(':input:not(.no-form)').filter(':noparents(.remodal)');
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
collect() {
|
||||||
|
if (!this.form || !this.fields.length) { return; }
|
||||||
|
|
||||||
|
let values = {};
|
||||||
|
this.refresh().fields.each((index, field) => {
|
||||||
|
field = $(field);
|
||||||
|
let name = field.prop('name');
|
||||||
|
let type = field.prop('type');
|
||||||
|
let value;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case 'checkbox':
|
||||||
|
case 'radio':
|
||||||
|
value = field.is(':checked');
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
value = field.val();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name && !~this.options.ignore.indexOf(name)) {
|
||||||
|
values[name] = value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return Immutable.OrderedMap(values);
|
||||||
|
}
|
||||||
|
|
||||||
|
// When the form doesn't exist or there are no fields, `equals` returns `null`
|
||||||
|
// for this reason, _NEVER_ check with !Instance.equals(), use Instance.equals() === false
|
||||||
|
equals() {
|
||||||
|
if (!this.form || !this.fields.length) { return null; }
|
||||||
|
return Immutable.is(FormLoadState, this.collect());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export let Instance = new FormState();
|
||||||
|
|
||||||
|
export { DOMBehaviors };
|
||||||
29
themes/grav/app/main.js
Normal file
29
themes/grav/app/main.js
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import GPM, { Instance as gpm } from './utils/gpm';
|
||||||
|
import KeepAlive from './utils/keepalive';
|
||||||
|
import Updates, { Instance as updates } from './updates';
|
||||||
|
import Dashboard from './dashboard';
|
||||||
|
import Pages from './pages';
|
||||||
|
import Forms from './forms';
|
||||||
|
import './plugins';
|
||||||
|
import './themes';
|
||||||
|
|
||||||
|
// bootstrap jQuery extensions
|
||||||
|
import 'bootstrap/js/dropdown';
|
||||||
|
|
||||||
|
// starts the keep alive, auto runs every X seconds
|
||||||
|
KeepAlive.start();
|
||||||
|
|
||||||
|
export default {
|
||||||
|
GPM: {
|
||||||
|
GPM,
|
||||||
|
Instance: gpm
|
||||||
|
},
|
||||||
|
KeepAlive,
|
||||||
|
Dashboard,
|
||||||
|
Pages,
|
||||||
|
Forms,
|
||||||
|
Updates: {
|
||||||
|
Updates,
|
||||||
|
Instance: updates
|
||||||
|
}
|
||||||
|
};
|
||||||
134
themes/grav/app/pages/filter.js
Normal file
134
themes/grav/app/pages/filter.js
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
import $ from 'jquery';
|
||||||
|
import { config } from 'grav-config';
|
||||||
|
import request from '../utils/request';
|
||||||
|
import debounce from 'debounce';
|
||||||
|
import { Instance as pagesTree } from './tree';
|
||||||
|
import 'selectize';
|
||||||
|
|
||||||
|
/* @formatter:off */
|
||||||
|
/* eslint-disable */
|
||||||
|
const options = [
|
||||||
|
{ flag: 'Modular', key: 'Modular', cat: 'mode' },
|
||||||
|
{ flag: 'Visible', key: 'Visible', cat: 'mode' },
|
||||||
|
{ flag: 'Routable', key: 'Routable', cat: 'mode' },
|
||||||
|
{ flag: 'Published', key: 'Published', cat: 'mode' },
|
||||||
|
{ flag: 'Non-Modular', key: 'NonModular', cat: 'mode' },
|
||||||
|
{ flag: 'Non-Visible', key: 'NonVisible', cat: 'mode' },
|
||||||
|
{ flag: 'Non-Routable', key: 'NonRoutable', cat: 'mode' },
|
||||||
|
{ flag: 'Non-Published', key: 'NonPublished', cat: 'mode' }
|
||||||
|
];
|
||||||
|
/* @formatter:on */
|
||||||
|
/* eslint-enable */
|
||||||
|
|
||||||
|
export default class PagesFilter {
|
||||||
|
constructor(filters, search) {
|
||||||
|
this.filters = $(filters);
|
||||||
|
this.search = $(search);
|
||||||
|
this.options = options;
|
||||||
|
this.tree = pagesTree;
|
||||||
|
|
||||||
|
if (!this.filters.length || !this.search.length) { return; }
|
||||||
|
|
||||||
|
this.labels = this.filters.data('filter-labels');
|
||||||
|
|
||||||
|
this.search.on('input', debounce(() => this.filter(), 250));
|
||||||
|
this.filters.on('change', () => this.filter());
|
||||||
|
|
||||||
|
this._initSelectize();
|
||||||
|
}
|
||||||
|
|
||||||
|
filter(value) {
|
||||||
|
let data = { flags: '', query: '' };
|
||||||
|
|
||||||
|
if (typeof value === 'object') {
|
||||||
|
Object.assign(data, value);
|
||||||
|
}
|
||||||
|
if (typeof value === 'string') {
|
||||||
|
data.query = value;
|
||||||
|
}
|
||||||
|
if (typeof value === 'undefined') {
|
||||||
|
data.flags = this.filters.val();
|
||||||
|
data.query = this.search.val();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Object.keys(data).filter((key) => data[key] !== '').length) {
|
||||||
|
this.resetValues();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
data.flags = data.flags.replace(/(\s{1,})?,(\s{1,})?/g, ',');
|
||||||
|
this.setValues({ flags: data.flags, query: data.query }, 'silent');
|
||||||
|
|
||||||
|
request(`${config.base_url_relative}/pages-filter.json/task${config.param_sep}filterPages`, {
|
||||||
|
method: 'post',
|
||||||
|
body: data
|
||||||
|
}, (response) => {
|
||||||
|
this.refreshDOM(response);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
refreshDOM(response) {
|
||||||
|
let items = $('[data-nav-id]');
|
||||||
|
|
||||||
|
if (!response) {
|
||||||
|
items.removeClass('search-match').show();
|
||||||
|
this.tree.restore();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
items.removeClass('search-match').hide();
|
||||||
|
|
||||||
|
response.results.forEach((page) => {
|
||||||
|
let match = items.filter(`[data-nav-id="${page}"]`).addClass('search-match').show();
|
||||||
|
match.parents('[data-nav-id]').addClass('search-match').show();
|
||||||
|
|
||||||
|
this.tree.expand(page, 'no-store');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
setValues({ flags = '', query = ''}, silent) {
|
||||||
|
let flagsArray = flags.replace(/(\s{1,})?,(\s{1,})?/g, ',').split(',');
|
||||||
|
if (this.filters.val() !== flags) { this.filters[0].selectize.setValue(flagsArray, silent); }
|
||||||
|
if (this.search.val() !== query) { this.search.val(query); }
|
||||||
|
}
|
||||||
|
|
||||||
|
resetValues() {
|
||||||
|
this.setValues('', 'silent');
|
||||||
|
this.refreshDOM();
|
||||||
|
}
|
||||||
|
|
||||||
|
_initSelectize() {
|
||||||
|
let extras = {
|
||||||
|
type: this.filters.data('filter-types') || {},
|
||||||
|
access: this.filters.data('filter-access-levels') || {}
|
||||||
|
};
|
||||||
|
|
||||||
|
Object.keys(extras).forEach((cat) => {
|
||||||
|
Object.keys(extras[cat]).forEach((key) => {
|
||||||
|
this.options.push({
|
||||||
|
cat,
|
||||||
|
key,
|
||||||
|
flag: extras[cat][key]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
this.filters.selectize({
|
||||||
|
maxItems: null,
|
||||||
|
valueField: 'key',
|
||||||
|
labelField: 'flag',
|
||||||
|
searchField: ['flag', 'key'],
|
||||||
|
options: this.options,
|
||||||
|
optgroups: this.labels,
|
||||||
|
optgroupField: 'cat',
|
||||||
|
optgroupLabelField: 'name',
|
||||||
|
optgroupValueField: 'id',
|
||||||
|
optgroupOrder: this.labels.map((item) => item.id),
|
||||||
|
plugins: ['optgroup_columns']
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let Instance = new PagesFilter('input[name="page-filter"]', 'input[name="page-search"]');
|
||||||
|
export { Instance };
|
||||||
26
themes/grav/app/pages/index.js
Normal file
26
themes/grav/app/pages/index.js
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import $ from 'jquery';
|
||||||
|
import Sortable from 'sortablejs';
|
||||||
|
import PageFilters, { Instance as PageFiltersInstance } from './filter';
|
||||||
|
import './page';
|
||||||
|
|
||||||
|
// Pages Ordering
|
||||||
|
let Ordering = null;
|
||||||
|
let orderingElement = $('#ordering');
|
||||||
|
if (orderingElement.length) {
|
||||||
|
Ordering = new Sortable(orderingElement.get(0), {
|
||||||
|
filter: '.ignore',
|
||||||
|
onUpdate: function(event) {
|
||||||
|
let item = $(event.item);
|
||||||
|
let index = orderingElement.children().index(item) + 1;
|
||||||
|
$('[data-order]').val(index);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
Ordering,
|
||||||
|
PageFilters: {
|
||||||
|
PageFilters,
|
||||||
|
Instance: PageFiltersInstance
|
||||||
|
}
|
||||||
|
};
|
||||||
31
themes/grav/app/pages/page/add.js
Normal file
31
themes/grav/app/pages/page/add.js
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import $ from 'jquery';
|
||||||
|
|
||||||
|
let custom = false;
|
||||||
|
let folder = $('input[name="folder"]');
|
||||||
|
let title = $('input[name="title"]');
|
||||||
|
|
||||||
|
title.on('input focus blur', () => {
|
||||||
|
if (custom) { return true; }
|
||||||
|
|
||||||
|
let slug = $.slugify(title.val());
|
||||||
|
folder.val(slug);
|
||||||
|
});
|
||||||
|
|
||||||
|
folder.on('input', () => {
|
||||||
|
let input = folder.get(0);
|
||||||
|
let value = folder.val();
|
||||||
|
let selection = {
|
||||||
|
start: input.selectionStart,
|
||||||
|
end: input.selectionEnd
|
||||||
|
};
|
||||||
|
|
||||||
|
value = value.toLowerCase().replace(/\s/g, '-').replace(/[^a-z0-9_\-]/g, '');
|
||||||
|
folder.val(value);
|
||||||
|
custom = !!value;
|
||||||
|
|
||||||
|
// restore cursor position
|
||||||
|
input.setSelectionRange(selection.start, selection.end);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
folder.on('focus blur', () => title.trigger('input'));
|
||||||
15
themes/grav/app/pages/page/delete.js
Normal file
15
themes/grav/app/pages/page/delete.js
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import $ from 'jquery';
|
||||||
|
|
||||||
|
$('[data-remodal-target="delete"]').on('click', function() {
|
||||||
|
let confirm = $('[data-remodal-id="delete"] [data-delete-action]');
|
||||||
|
let link = $(this).data('delete-url');
|
||||||
|
|
||||||
|
confirm.data('delete-action', link);
|
||||||
|
});
|
||||||
|
|
||||||
|
$('[data-delete-action]').on('click', function() {
|
||||||
|
let remodal = $.remodal.lookup[$('[data-remodal-id="delete"]').data('remodal')];
|
||||||
|
|
||||||
|
window.location.href = $(this).data('delete-action');
|
||||||
|
remodal.close();
|
||||||
|
});
|
||||||
37
themes/grav/app/pages/page/index.js
Normal file
37
themes/grav/app/pages/page/index.js
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
import $ from 'jquery';
|
||||||
|
import './add';
|
||||||
|
import './move';
|
||||||
|
import './delete';
|
||||||
|
import './media';
|
||||||
|
|
||||||
|
const switcher = $('input[type="radio"][name="mode-switch"]');
|
||||||
|
|
||||||
|
if (switcher) {
|
||||||
|
let link = switcher.closest(':checked').data('leave-url');
|
||||||
|
let fakeLink = $(`<a href="${link}" />`);
|
||||||
|
|
||||||
|
switcher.parent().append(fakeLink);
|
||||||
|
|
||||||
|
switcher.siblings('label').on('mousedown touchdown', (event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
// let remodal = $.remodal.lookup[$('[data-remodal-id="changes"]').data('remodal')];
|
||||||
|
let confirm = $('[data-remodal-id="changes"] [data-leave-action="continue"]');
|
||||||
|
|
||||||
|
confirm.one('click', () => {
|
||||||
|
$(window).on('beforeunload._grav');
|
||||||
|
fakeLink.off('click._grav');
|
||||||
|
|
||||||
|
$(event.target).trigger('click');
|
||||||
|
});
|
||||||
|
|
||||||
|
fakeLink.trigger('click._grav');
|
||||||
|
});
|
||||||
|
|
||||||
|
switcher.on('change', (event) => {
|
||||||
|
let radio = $(event.target);
|
||||||
|
link = radio.data('leave-url');
|
||||||
|
|
||||||
|
setTimeout(() => fakeLink.attr('href', link).get(0).click(), 5);
|
||||||
|
});
|
||||||
|
}
|
||||||
380
themes/grav/app/pages/page/media.js
Normal file
380
themes/grav/app/pages/page/media.js
Normal file
@@ -0,0 +1,380 @@
|
|||||||
|
import $ from 'jquery';
|
||||||
|
import Dropzone from 'dropzone';
|
||||||
|
import request from '../../utils/request';
|
||||||
|
import { config } from 'grav-config';
|
||||||
|
|
||||||
|
Dropzone.autoDiscover = false;
|
||||||
|
Dropzone.options.gravPageDropzone = {};
|
||||||
|
Dropzone.confirm = (question, accepted, rejected) => {
|
||||||
|
let doc = $(document);
|
||||||
|
let modalSelector = '[data-remodal-id="delete-media"]';
|
||||||
|
|
||||||
|
let removeEvents = () => {
|
||||||
|
doc.off('confirm', modalSelector, accept);
|
||||||
|
doc.off('cancel', modalSelector, reject);
|
||||||
|
};
|
||||||
|
|
||||||
|
let accept = () => {
|
||||||
|
accepted && accepted();
|
||||||
|
removeEvents();
|
||||||
|
};
|
||||||
|
|
||||||
|
let reject = () => {
|
||||||
|
rejected && rejected();
|
||||||
|
removeEvents();
|
||||||
|
};
|
||||||
|
|
||||||
|
$.remodal.lookup[$(modalSelector).data('remodal')].open();
|
||||||
|
doc.on('confirmation', modalSelector, accept);
|
||||||
|
doc.on('cancellation', modalSelector, reject);
|
||||||
|
};
|
||||||
|
|
||||||
|
const DropzoneMediaConfig = {
|
||||||
|
createImageThumbnails: { thumbnailWidth: 150 },
|
||||||
|
addRemoveLinks: false,
|
||||||
|
dictRemoveFileConfirmation: '[placeholder]',
|
||||||
|
previewTemplate: `
|
||||||
|
<div class="dz-preview dz-file-preview">
|
||||||
|
<div class="dz-details">
|
||||||
|
<div class="dz-filename"><span data-dz-name></span></div>
|
||||||
|
<div class="dz-size" data-dz-size></div>
|
||||||
|
<img data-dz-thumbnail />
|
||||||
|
</div>
|
||||||
|
<div class="dz-progress"><span class="dz-upload" data-dz-uploadprogress></span></div>
|
||||||
|
<div class="dz-success-mark"><span>✔</span></div>
|
||||||
|
<div class="dz-error-mark"><span>✘</span></div>
|
||||||
|
<div class="dz-error-message"><span data-dz-errormessage></span></div>
|
||||||
|
<a class="dz-remove" href="javascript:undefined;" data-dz-remove>Delete</a>
|
||||||
|
<a class="dz-insert" href="javascript:undefined;" data-dz-insert>Insert</a>
|
||||||
|
</div>`.trim()
|
||||||
|
};
|
||||||
|
|
||||||
|
export default class PageMedia {
|
||||||
|
constructor({form = '[data-media-url]', container = '#grav-dropzone', options = {}} = {}) {
|
||||||
|
this.form = $(form);
|
||||||
|
this.container = $(container);
|
||||||
|
if (!this.form.length || !this.container.length) { return; }
|
||||||
|
|
||||||
|
this.options = Object.assign({}, DropzoneMediaConfig, {
|
||||||
|
url: `${this.form.data('media-url')}/task${config.param_sep}addmedia`,
|
||||||
|
acceptedFiles: this.form.data('media-types')
|
||||||
|
}, options);
|
||||||
|
|
||||||
|
this.dropzone = new Dropzone(container, this.options);
|
||||||
|
this.dropzone.on('complete', this.onDropzoneComplete.bind(this));
|
||||||
|
this.dropzone.on('success', this.onDropzoneSuccess.bind(this));
|
||||||
|
this.dropzone.on('removedfile', this.onDropzoneRemovedFile.bind(this));
|
||||||
|
this.dropzone.on('sending', this.onDropzoneSending.bind(this));
|
||||||
|
|
||||||
|
this.fetchMedia();
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchMedia() {
|
||||||
|
let url = `${this.form.data('media-url')}/task${config.param_sep}listmedia/admin-nonce${config.param_sep}${config.admin_nonce}`;
|
||||||
|
|
||||||
|
request(url, (response) => {
|
||||||
|
let results = response.results;
|
||||||
|
|
||||||
|
Object.keys(results).forEach((name) => {
|
||||||
|
let data = results[name];
|
||||||
|
let mock = { name, size: data.size, accepted: true, extras: data };
|
||||||
|
|
||||||
|
this.dropzone.files.push(mock);
|
||||||
|
this.dropzone.options.addedfile.call(this.dropzone, mock);
|
||||||
|
|
||||||
|
if (name.match(/\.(jpg|jpeg|png|gif)$/i)) {
|
||||||
|
this.dropzone.options.thumbnail.call(this.dropzone, mock, data.url);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.container.find('.dz-preview').prop('draggable', 'true');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onDropzoneSending(file, xhr, formData) {
|
||||||
|
formData.append('admin-nonce', config.admin_nonce);
|
||||||
|
}
|
||||||
|
|
||||||
|
onDropzoneSuccess(file, response, xhr) {
|
||||||
|
return this.handleError({
|
||||||
|
file,
|
||||||
|
data: response,
|
||||||
|
mode: 'removeFile',
|
||||||
|
msg: `<p>An error occurred while trying to upload the file <strong>${file.name}</strong></p>
|
||||||
|
<pre>${response.message}</pre>`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onDropzoneComplete(file) {
|
||||||
|
if (!file.accepted) {
|
||||||
|
let data = {
|
||||||
|
status: 'error',
|
||||||
|
message: `Unsupported file type: ${file.name.match(/\..+/).join('')}`
|
||||||
|
};
|
||||||
|
|
||||||
|
return this.handleError({
|
||||||
|
file,
|
||||||
|
data,
|
||||||
|
mode: 'removeFile',
|
||||||
|
msg: `<p>An error occurred while trying to add the file <strong>${file.name}</strong></p>
|
||||||
|
<pre>${data.message}</pre>`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// accepted
|
||||||
|
$('.dz-preview').prop('draggable', 'true');
|
||||||
|
}
|
||||||
|
|
||||||
|
onDropzoneRemovedFile(file, ...extra) {
|
||||||
|
if (!file.accepted || file.rejected) { return; }
|
||||||
|
let url = `${this.form.data('media-url')}/task${config.param_sep}delmedia`;
|
||||||
|
|
||||||
|
request(url, {
|
||||||
|
method: 'post',
|
||||||
|
body: {
|
||||||
|
filename: file.name
|
||||||
|
}
|
||||||
|
}, (response) => {
|
||||||
|
return this.handleError({
|
||||||
|
file,
|
||||||
|
data: response,
|
||||||
|
mode: 'addBack',
|
||||||
|
msg: `<p>An error occurred while trying to remove the file <strong>${file.name}</strong></p>
|
||||||
|
<pre>${response.message}</pre>`
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
handleError(options) {
|
||||||
|
let { file, data, mode, msg } = options;
|
||||||
|
if (data.status !== 'error' && data.status !== 'unauthorized') { return ; }
|
||||||
|
|
||||||
|
switch (mode) {
|
||||||
|
case 'addBack':
|
||||||
|
if (file instanceof File) {
|
||||||
|
this.dropzone.addFile(file);
|
||||||
|
} else {
|
||||||
|
this.dropzone.files.push(file);
|
||||||
|
this.dropzone.options.addedfile.call(this, file);
|
||||||
|
this.dropzone.options.thumbnail.call(this, file, file.extras.url);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 'removeFile':
|
||||||
|
file.rejected = true;
|
||||||
|
this.dropzone.removeFile(file);
|
||||||
|
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
|
let modal = $('[data-remodal-id="generic"]');
|
||||||
|
modal.find('.error-content').html(msg);
|
||||||
|
$.remodal.lookup[modal.data('remodal')].open();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export let Instance = new PageMedia();
|
||||||
|
|
||||||
|
// let container = $('[data-media-url]');
|
||||||
|
|
||||||
|
// if (container.length) {
|
||||||
|
/* let URI = container.data('media-url');
|
||||||
|
let dropzone = new Dropzone('#grav-dropzone', {
|
||||||
|
url: `${URI}/task${config.param_sep}addmedia`,
|
||||||
|
createImageThumbnails: { thumbnailWidth: 150 },
|
||||||
|
addRemoveLinks: false,
|
||||||
|
dictRemoveFileConfirmation: '[placeholder]',
|
||||||
|
acceptedFiles: container.data('media-types'),
|
||||||
|
previewTemplate: `
|
||||||
|
<div class="dz-preview dz-file-preview">
|
||||||
|
<div class="dz-details">
|
||||||
|
<div class="dz-filename"><span data-dz-name></span></div>
|
||||||
|
<div class="dz-size" data-dz-size></div>
|
||||||
|
<img data-dz-thumbnail />
|
||||||
|
</div>
|
||||||
|
<div class="dz-progress"><span class="dz-upload" data-dz-uploadprogress></span></div>
|
||||||
|
<div class="dz-success-mark"><span>✔</span></div>
|
||||||
|
<div class="dz-error-mark"><span>✘</span></div>
|
||||||
|
<div class="dz-error-message"><span data-dz-errormessage></span></div>
|
||||||
|
<a class="dz-remove" href="javascript:undefined;" data-dz-remove>Delete</a>
|
||||||
|
<a class="dz-insert" href="javascript:undefined;" data-dz-insert>Insert</a>
|
||||||
|
</div>`
|
||||||
|
});*/
|
||||||
|
|
||||||
|
/* $.get(URI + '/task{{ config.system.param_sep }}listmedia/admin-nonce{{ config.system.param_sep }}' + GravAdmin.config.admin_nonce, function(data) {
|
||||||
|
|
||||||
|
$.proxy(modalError, this, {
|
||||||
|
data: data,
|
||||||
|
msg: '<p>An error occurred while trying to list files</p><pre>'+data.message+'</pre>'
|
||||||
|
})();
|
||||||
|
|
||||||
|
if (data.results) {
|
||||||
|
$.each(data.results, function(filename, data){
|
||||||
|
var mockFile = { name: filename, size: data.size, accepted: true, extras: data };
|
||||||
|
thisDropzone.files.push(mockFile);
|
||||||
|
thisDropzone.options.addedfile.call(thisDropzone, mockFile);
|
||||||
|
|
||||||
|
if (filename.toLowerCase().match(/\.(jpg|jpeg|png|gif)$/)) {
|
||||||
|
thisDropzone.options.thumbnail.call(thisDropzone, mockFile, data.url);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
$('.dz-preview').prop('draggable', 'true');
|
||||||
|
});*/
|
||||||
|
|
||||||
|
// console.log(dropzone);
|
||||||
|
// }
|
||||||
|
|
||||||
|
/*
|
||||||
|
<script>
|
||||||
|
$(function(){
|
||||||
|
var URI = $('[data-media-url]').data('media-url'), thisDropzone,
|
||||||
|
modalError = function(args){
|
||||||
|
if (args.data.status == 'error' || args.data.status == 'unauthorized'){
|
||||||
|
|
||||||
|
if (args.mode == 'addBack'){
|
||||||
|
// let's add back the file
|
||||||
|
if (args.file instanceof File) this.addFile(args.file);
|
||||||
|
else {
|
||||||
|
this.files.push(args.file);
|
||||||
|
this.options.addedfile.call(this, args.file);
|
||||||
|
this.options.thumbnail.call(this, args.file, args.file.extras.url);
|
||||||
|
}
|
||||||
|
} else if (args.mode == 'removeFile') {
|
||||||
|
args.file.rejected = true;
|
||||||
|
this.removeFile(args.file);
|
||||||
|
}
|
||||||
|
|
||||||
|
// fire up the modal
|
||||||
|
var modalContainer = $('[data-remodal-id=generic]');
|
||||||
|
modalContainer.find('.error-content').html(args.msg);
|
||||||
|
$.remodal.lookup[modalContainer.data('remodal')].open();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Dropzone.autoDiscover = false;
|
||||||
|
Dropzone.confirm = function(question, accepted, rejected) {
|
||||||
|
var modalContainer = $('[data-remodal-id=delete-media]'),
|
||||||
|
acceptHandler = function () {
|
||||||
|
if (accepted) {
|
||||||
|
accepted();
|
||||||
|
}
|
||||||
|
$(document).off('confirm', '[data-remodal-id=delete-media]', acceptHandler);
|
||||||
|
$(document).off('cancel', '[data-remodal-id=delete-media]', rejectHandler);
|
||||||
|
},
|
||||||
|
rejectHandler = function () {
|
||||||
|
if (rejected) {
|
||||||
|
rejected();
|
||||||
|
}
|
||||||
|
$(document).off('confirm', '[data-remodal-id=delete-media]', acceptHandler);
|
||||||
|
$(document).off('cancel', '[data-remodal-id=delete-media]', rejectHandler);
|
||||||
|
};
|
||||||
|
|
||||||
|
$.remodal.lookup[modalContainer.data('remodal')].open();
|
||||||
|
$(document).on('confirm', '[data-remodal-id=delete-media]', acceptHandler);
|
||||||
|
$(document).on('cancel', '[data-remodal-id=delete-media]', rejectHandler);
|
||||||
|
};
|
||||||
|
Dropzone.options.gravDropzone = {
|
||||||
|
addRemoveLinks: false,
|
||||||
|
dictRemoveFileConfirmation: '[placeholder]',
|
||||||
|
acceptedFiles: $('[data-media-types]').data('media-types'),
|
||||||
|
previewTemplate: "<div class=\"dz-preview dz-file-preview\">\n <div class=\"dz-details\">\n " +
|
||||||
|
"<div class=\"dz-filename\"><span data-dz-name></span></div>\n " +
|
||||||
|
"<div class=\"dz-size\" data-dz-size></div>\n <img data-dz-thumbnail />\n </div>\n " +
|
||||||
|
"<div class=\"dz-progress\"><span class=\"dz-upload\" data-dz-uploadprogress></span></div>\n "+
|
||||||
|
"<div class=\"dz-success-mark\"><span>✔</span></div>\n <div class=\"dz-error-mark\"><span>✘</span></div>\n " +
|
||||||
|
"<div class=\"dz-error-message\"><span data-dz-errormessage></span></div>\n" +
|
||||||
|
"<a class=\"dz-remove\" href=\"javascript:undefined;\" data-dz-remove>Delete</a>\n" +
|
||||||
|
"<a class=\"dz-insert\" href=\"javascript:undefined;\" data-dz-insert>Insert</a>\n</div>",
|
||||||
|
init: function() {
|
||||||
|
thisDropzone = this;
|
||||||
|
$.get(URI + '/task{{ config.system.param_sep }}listmedia/admin-nonce{{ config.system.param_sep }}' + GravAdmin.config.admin_nonce, function(data) {
|
||||||
|
|
||||||
|
$.proxy(modalError, this, {
|
||||||
|
data: data,
|
||||||
|
msg: '<p>An error occurred while trying to list files</p><pre>'+data.message+'</pre>'
|
||||||
|
})();
|
||||||
|
|
||||||
|
if (data.results) {
|
||||||
|
$.each(data.results, function(filename, data){
|
||||||
|
var mockFile = { name: filename, size: data.size, accepted: true, extras: data };
|
||||||
|
thisDropzone.files.push(mockFile);
|
||||||
|
thisDropzone.options.addedfile.call(thisDropzone, mockFile);
|
||||||
|
|
||||||
|
if (filename.toLowerCase().match(/\.(jpg|jpeg|png|gif)$/)) {
|
||||||
|
thisDropzone.options.thumbnail.call(thisDropzone, mockFile, data.url);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
$('.dz-preview').prop('draggable', 'true');
|
||||||
|
});
|
||||||
|
|
||||||
|
this.on("complete", function(file) {
|
||||||
|
if (file.accepted) {
|
||||||
|
$('.dz-preview').prop('draggable', 'true');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var data = {status: 'error', message: 'Unsupported file type: ' + file.name.match(/\..+/).join('')};
|
||||||
|
$.proxy(modalError, this, {
|
||||||
|
file: file,
|
||||||
|
data: data,
|
||||||
|
mode: 'removeFile',
|
||||||
|
msg: '<p>An error occurred while trying to add the file <strong>'+file.name+'</strong></p><pre>'+data.message+'</pre>'
|
||||||
|
})();
|
||||||
|
});
|
||||||
|
|
||||||
|
this.on('success', function(file, response){
|
||||||
|
thisDropzone = this;
|
||||||
|
$.proxy(modalError, this, {
|
||||||
|
file: file,
|
||||||
|
data: response,
|
||||||
|
mode: 'removeFile',
|
||||||
|
msg: '<p>An error occurred while trying to upload the file <strong>'+file.name+'</strong></p><pre>'+response.message+'</pre>'
|
||||||
|
})();
|
||||||
|
});
|
||||||
|
|
||||||
|
this.on('removedfile', function(file) {
|
||||||
|
if (!file.accepted || file.rejected) return;
|
||||||
|
thisDropzone = this;
|
||||||
|
$.post(URI + '/task{{ config.system.param_sep }}delmedia', {filename: file.name, 'admin-nonce': GravAdmin.config.admin_nonce}, function(data){
|
||||||
|
$.proxy(modalError, thisDropzone, {
|
||||||
|
file: file,
|
||||||
|
data: data,
|
||||||
|
mode: 'addBack',
|
||||||
|
msg: '<p>An error occurred while trying to remove the file <strong>'+file.name+'</strong></p><pre>'+data.message+'</pre>'
|
||||||
|
})();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
this.on('sending', function(file, xhr, formData){
|
||||||
|
formData.append('admin-nonce', GravAdmin.config.admin_nonce);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var dropzone = new Dropzone("#gravDropzone", { url: URI + '/task{{ config.system.param_sep }}addmedia', createImageThumbnails: { thumbnailWidth: 150} });
|
||||||
|
|
||||||
|
$("#gravDropzone").delegate('.dz-preview', 'dragstart', function(e){
|
||||||
|
var uri = encodeURI($(this).find('.dz-filename').text());
|
||||||
|
uri = uri.replace(/\(/g, '%28');
|
||||||
|
uri = uri.replace(/\)/g, '%29');
|
||||||
|
|
||||||
|
var shortcode = '';
|
||||||
|
if (!uri.match(/\.(jpg|jpeg|png|gif)$/)) {
|
||||||
|
shortcode = '[' + decodeURI(uri) + '](' + uri + ')';
|
||||||
|
}
|
||||||
|
|
||||||
|
dropzone.disable();
|
||||||
|
$(this).addClass('hide-backface');
|
||||||
|
e.originalEvent.dataTransfer.effectAllowed = 'copy';
|
||||||
|
e.originalEvent.dataTransfer.setData('text', shortcode);
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#gravDropzone").delegate('.dz-preview', 'dragend', function(e){
|
||||||
|
dropzone.enable();
|
||||||
|
$(this).removeClass('hide-backface');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>*/
|
||||||
13
themes/grav/app/pages/page/move.js
Normal file
13
themes/grav/app/pages/page/move.js
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import $ from 'jquery';
|
||||||
|
|
||||||
|
$('[data-page-move] button[name="task"][value="save"]').on('click', function() {
|
||||||
|
let route = $('form#blueprints:first select[name="route"]');
|
||||||
|
let moveTo = $('[data-page-move] select').val();
|
||||||
|
|
||||||
|
if (route.length && route.val() !== moveTo) {
|
||||||
|
let selectize = route.data('selectize');
|
||||||
|
route.val(moveTo);
|
||||||
|
|
||||||
|
if (selectize) selectize.setValue(moveTo);
|
||||||
|
}
|
||||||
|
});
|
||||||
116
themes/grav/app/pages/tree.js
Normal file
116
themes/grav/app/pages/tree.js
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
import $ from 'jquery';
|
||||||
|
|
||||||
|
const sessionKey = 'grav:admin:pages';
|
||||||
|
|
||||||
|
if (!sessionStorage.getItem(sessionKey)) {
|
||||||
|
sessionStorage.setItem(sessionKey, '{}');
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class PagesTree {
|
||||||
|
constructor(elements) {
|
||||||
|
this.elements = $(elements);
|
||||||
|
this.session = JSON.parse(sessionStorage.getItem(sessionKey));
|
||||||
|
|
||||||
|
if (!this.elements.length) { return; }
|
||||||
|
|
||||||
|
this.restore();
|
||||||
|
|
||||||
|
this.elements.find('.page-icon').on('click', (event) => this.toggle(event.target));
|
||||||
|
|
||||||
|
$('[data-page-toggleall]').on('click', (event) => {
|
||||||
|
let element = $(event.target).closest('[data-page-toggleall]');
|
||||||
|
let action = element.data('page-toggleall');
|
||||||
|
|
||||||
|
this[action]();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
toggle(elements, dontStore = false) {
|
||||||
|
if (typeof elements === 'string') {
|
||||||
|
elements = $(`[data-nav-id="${elements}"]`).find('[data-toggle="children"]');
|
||||||
|
}
|
||||||
|
|
||||||
|
elements = $(elements || this.elements);
|
||||||
|
elements.each((index, element) => {
|
||||||
|
element = $(element);
|
||||||
|
let state = this.getState(element.closest('[data-toggle="children"]'));
|
||||||
|
this[state.isOpen ? 'collapse' : 'expand'](state.id, dontStore);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
collapse(elements, dontStore = false) {
|
||||||
|
if (typeof elements === 'string') {
|
||||||
|
elements = $(`[data-nav-id="${elements}"]`).find('[data-toggle="children"]');
|
||||||
|
}
|
||||||
|
|
||||||
|
elements = $(elements || this.elements);
|
||||||
|
elements.each((index, element) => {
|
||||||
|
element = $(element);
|
||||||
|
let state = this.getState(element);
|
||||||
|
|
||||||
|
if (state.isOpen) {
|
||||||
|
state.children.hide();
|
||||||
|
state.icon.removeClass('children-open').addClass('children-closed');
|
||||||
|
if (!dontStore) { delete this.session[state.id]; }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!dontStore) { this.save(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
expand(elements, dontStore = false) {
|
||||||
|
if (typeof elements === 'string') {
|
||||||
|
let element = $(`[data-nav-id="${elements}"]`);
|
||||||
|
let parents = element.parents('[data-nav-id]');
|
||||||
|
|
||||||
|
// loop back through parents, we don't want to expand an hidden child
|
||||||
|
if (parents.length) {
|
||||||
|
parents = parents.find('[data-toggle="children"]:first');
|
||||||
|
parents = parents.add(element.find('[data-toggle="children"]:first'));
|
||||||
|
return this.expand(parents, dontStore);
|
||||||
|
}
|
||||||
|
|
||||||
|
elements = element.find('[data-toggle="children"]:first');
|
||||||
|
}
|
||||||
|
|
||||||
|
elements = $(elements || this.elements);
|
||||||
|
elements.each((index, element) => {
|
||||||
|
element = $(element);
|
||||||
|
let state = this.getState(element);
|
||||||
|
|
||||||
|
if (!state.isOpen) {
|
||||||
|
state.children.show();
|
||||||
|
state.icon.removeClass('children-closed').addClass('children-open');
|
||||||
|
if (!dontStore) { this.session[state.id] = 1; }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!dontStore) { this.save(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
restore() {
|
||||||
|
this.collapse(null, true);
|
||||||
|
|
||||||
|
Object.keys(this.session).forEach((key) => {
|
||||||
|
this.expand(key, 'no-store');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
save() {
|
||||||
|
return sessionStorage.setItem(sessionKey, JSON.stringify(this.session));
|
||||||
|
}
|
||||||
|
|
||||||
|
getState(element) {
|
||||||
|
element = $(element);
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: element.closest('[data-nav-id]').data('nav-id'),
|
||||||
|
children: element.closest('li.page-item').find('ul:first'),
|
||||||
|
icon: element.find('.page-icon'),
|
||||||
|
get isOpen() { return this.icon.hasClass('children-open'); }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let Instance = new PagesTree('[data-toggle="children"]');
|
||||||
|
export { Instance };
|
||||||
24
themes/grav/app/plugins/index.js
Normal file
24
themes/grav/app/plugins/index.js
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
import $ from 'jquery';
|
||||||
|
|
||||||
|
// Plugins sliders details
|
||||||
|
$('.gpm-name, .gpm-actions').on('click', function(e) {
|
||||||
|
let element = $(this);
|
||||||
|
let target = $(e.target);
|
||||||
|
let tag = target.prop('tagName').toLowerCase();
|
||||||
|
|
||||||
|
if (tag === 'a' || element.parent('a').length) { return true; }
|
||||||
|
|
||||||
|
let wrapper = element.siblings('.gpm-details').find('.table-wrapper');
|
||||||
|
|
||||||
|
wrapper.slideToggle({
|
||||||
|
duration: 350,
|
||||||
|
complete: () => {
|
||||||
|
let visible = wrapper.is(':visible');
|
||||||
|
wrapper
|
||||||
|
.closest('tr')
|
||||||
|
.find('.gpm-details-expand i')
|
||||||
|
.removeClass('fa-chevron-' + (visible ? 'down' : 'up'))
|
||||||
|
.addClass('fa-chevron-' + (visible ? 'up' : 'down'));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
10
themes/grav/app/themes/index.js
Normal file
10
themes/grav/app/themes/index.js
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import $ from 'jquery';
|
||||||
|
|
||||||
|
// Themes Switcher Warning
|
||||||
|
$(document).on('mousedown', '[data-remodal-target="theme-switch-warn"]', (event) => {
|
||||||
|
let name = $(event.target).closest('[data-gpm-theme]').find('.gpm-name a:first').text();
|
||||||
|
let remodal = $('.remodal.theme-switcher');
|
||||||
|
|
||||||
|
remodal.find('strong').text(name);
|
||||||
|
remodal.find('.button.continue').attr('href', $(event.target).attr('href'));
|
||||||
|
});
|
||||||
26
themes/grav/app/updates/check.js
Normal file
26
themes/grav/app/updates/check.js
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import $ from 'jquery';
|
||||||
|
import { Instance as gpm } from '../utils/gpm';
|
||||||
|
import { translations } from 'grav-config';
|
||||||
|
import toastr from '../utils/toastr';
|
||||||
|
|
||||||
|
// Check for updates trigger
|
||||||
|
$('[data-gpm-checkupdates]').on('click', function() {
|
||||||
|
let element = $(this);
|
||||||
|
element.find('i').addClass('fa-spin');
|
||||||
|
|
||||||
|
gpm.fetch((response) => {
|
||||||
|
element.find('i').removeClass('fa-spin');
|
||||||
|
let payload = response.payload;
|
||||||
|
|
||||||
|
if (!payload) { return; }
|
||||||
|
if (!payload.grav.isUpdatable && !payload.resources.total) {
|
||||||
|
toastr.success(translations.PLUGIN_ADMIN.EVERYTHING_UP_TO_DATE);
|
||||||
|
} else {
|
||||||
|
var grav = payload.grav.isUpdatable ? 'Grav v' + payload.grav.available : '';
|
||||||
|
var resources = payload.resources.total ? payload.resources.total + ' ' + translations.PLUGIN_ADMIN.UPDATES_ARE_AVAILABLE : '';
|
||||||
|
|
||||||
|
if (!resources) { grav += ' ' + translations.PLUGIN_ADMIN.IS_AVAILABLE_FOR_UPDATE; }
|
||||||
|
toastr.info(grav + (grav && resources ? ' ' + translations.PLUGIN_ADMIN.AND + ' ' : '') + resources);
|
||||||
|
}
|
||||||
|
}, true);
|
||||||
|
});
|
||||||
134
themes/grav/app/updates/index.js
Normal file
134
themes/grav/app/updates/index.js
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
import $ from 'jquery';
|
||||||
|
import { config, translations } from 'grav-config';
|
||||||
|
import formatBytes from '../utils/formatbytes';
|
||||||
|
import { Instance as gpm } from '../utils/gpm';
|
||||||
|
import './check';
|
||||||
|
import './update';
|
||||||
|
|
||||||
|
export default class Updates {
|
||||||
|
constructor(payload = {}) {
|
||||||
|
this.setPayload(payload);
|
||||||
|
this.task = `task${config.param_sep}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
setPayload(payload = {}) {
|
||||||
|
this.payload = payload;
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
fetch(force = false) {
|
||||||
|
gpm.fetch((response) => this.setPayload(response), force);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
maintenance(mode = 'hide') {
|
||||||
|
let element = $('#updates [data-maintenance-update]');
|
||||||
|
|
||||||
|
element[mode === 'show' ? 'fadeIn' : 'fadeOut']();
|
||||||
|
|
||||||
|
if (mode === 'hide') {
|
||||||
|
$('.badges.with-updates').removeClass('with-updates').find('.badge.updates').remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
grav() {
|
||||||
|
let payload = this.payload.grav;
|
||||||
|
|
||||||
|
if (payload.isUpdatable) {
|
||||||
|
let task = this.task;
|
||||||
|
let bar = `
|
||||||
|
<i class="fa fa-bullhorn"></i>
|
||||||
|
Grav <b>v${payload.available}</b> ${translations.PLUGIN_ADMIN.IS_NOW_AVAILABLE}! <span class="less">(${translations.PLUGIN_ADMIN.CURRENT}v${payload.version})</span>
|
||||||
|
`;
|
||||||
|
|
||||||
|
if (!payload.isSymlink) {
|
||||||
|
bar += `<button data-maintenance-update="${config.base_url_relative}/update.json/${task}updategrav/admin-nonce${config.param_sep}${config.admin_nonce}" class="button button-small secondary" id="grav-update-button">${translations.PLUGIN_ADMIN.UPDATE_GRAV_NOW}</button>`;
|
||||||
|
} else {
|
||||||
|
bar += `<span class="hint--left" style="float: right;" data-hint="${translations.PLUGIN_ADMIN.GRAV_SYMBOLICALLY_LINKED}"><i class="fa fa-fw fa-link"></i></span>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
$('[data-gpm-grav]').addClass('grav').html(`<p>${bar}</p>`);
|
||||||
|
}
|
||||||
|
|
||||||
|
$('#grav-update-button').on('click', function() {
|
||||||
|
$(this).html(`${translations.PLUGIN_ADMIN.UPDATING_PLEASE_WAIT} ${formatBytes(payload.assets['grav-update'].size)}..`);
|
||||||
|
});
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
resources() {
|
||||||
|
if (!this.payload.resources.total) { return this.maintenance('hide'); }
|
||||||
|
|
||||||
|
let map = ['plugins', 'themes'];
|
||||||
|
let singles = ['plugin', 'theme'];
|
||||||
|
let task = this.task;
|
||||||
|
let { plugins, themes } = this.payload.resources;
|
||||||
|
|
||||||
|
if (!this.payload.resources.total) { return this; }
|
||||||
|
|
||||||
|
[plugins, themes].forEach(function(resources, index) {
|
||||||
|
if (!resources || Array.isArray(resources)) { return; }
|
||||||
|
let length = Object.keys(resources).length;
|
||||||
|
let type = map[index];
|
||||||
|
|
||||||
|
// sidebar
|
||||||
|
$(`#admin-menu a[href$="/${map[index]}"]`)
|
||||||
|
.find('.badges')
|
||||||
|
.addClass('with-updates')
|
||||||
|
.find('.badge.updates').text(length);
|
||||||
|
|
||||||
|
// update all
|
||||||
|
let title = type.charAt(0).toUpperCase() + type.substr(1).toLowerCase();
|
||||||
|
let updateAll = $(`.grav-update.${type}`);
|
||||||
|
updateAll.html(`
|
||||||
|
<p>
|
||||||
|
<i class="fa fa-bullhorn"></i>
|
||||||
|
${length} ${translations.PLUGIN_ADMIN.OF_YOUR} ${type} ${translations.PLUGIN_ADMIN.HAVE_AN_UPDATE_AVAILABLE}
|
||||||
|
<a href="${config.base_url_relative}/${type}/${task}update/admin-nonce${config.param_sep}${config.admin_nonce}" class="button button-small secondary">${translations.PLUGIN_ADMIN.UPDATE} All ${title}</a>
|
||||||
|
</p>
|
||||||
|
`);
|
||||||
|
|
||||||
|
Object.keys(resources).forEach(function(item) {
|
||||||
|
// listing page
|
||||||
|
let element = $(`[data-gpm-${singles[index]}="${item}"] .gpm-name`);
|
||||||
|
let url = element.find('a');
|
||||||
|
|
||||||
|
if (type === 'plugins' && !element.find('.badge.update').length) {
|
||||||
|
element.append(`<a class="plugin-update-button" href="${url.attr('href')}"><span class="badge update">${translations.PLUGIN_ADMIN.UPDATE_AVAILABLE}!</span></a>`);
|
||||||
|
} else if (type === 'themes') {
|
||||||
|
element.append(`<div class="gpm-ribbon"><a href="${url.attr('href')}">${translations.PLUGIN_ADMIN.UPDATE.toUpperCase()}</a></div>`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// details page
|
||||||
|
let details = $(`.grav-update.${singles[index]}`);
|
||||||
|
if (details.length) {
|
||||||
|
details.html(`
|
||||||
|
<p>
|
||||||
|
<i class="fa fa-bullhorn"></i>
|
||||||
|
<strong>v${resources[item].available}</strong> ${translations.PLUGIN_ADMIN.OF_THIS} ${singles[index]} ${translations.PLUGIN_ADMIN.IS_NOW_AVAILABLE}!
|
||||||
|
<a href="${config.base_url_relative}/${type}/${item}/${task}update/admin-nonce${config.param_sep}${config.admin_nonce}" class="button button-small secondary">${translations.PLUGIN_ADMIN.UPDATE} ${singles[index].charAt(0).toUpperCase() + singles[index].substr(1).toLowerCase()}</a>
|
||||||
|
</p>
|
||||||
|
`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let Instance = new Updates();
|
||||||
|
export { Instance };
|
||||||
|
|
||||||
|
// automatically refresh UI for updates (graph, sidebar, plugin/themes pages) after every fetch
|
||||||
|
gpm.on('fetched', (response, raw) => {
|
||||||
|
Instance.setPayload(response.payload || {});
|
||||||
|
Instance.grav().resources();
|
||||||
|
});
|
||||||
|
|
||||||
|
if (config.enable_auto_updates_check === '1') {
|
||||||
|
gpm.fetch();
|
||||||
|
}
|
||||||
19
themes/grav/app/updates/update.js
Normal file
19
themes/grav/app/updates/update.js
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import $ from 'jquery';
|
||||||
|
import request from '../utils/request';
|
||||||
|
|
||||||
|
// Dashboard update and Grav update
|
||||||
|
$('body').on('click', '[data-maintenance-update]', function() {
|
||||||
|
let element = $(this);
|
||||||
|
let url = element.data('maintenanceUpdate');
|
||||||
|
|
||||||
|
element.attr('disabled', 'disabled').find('> .fa').removeClass('fa-cloud-download').addClass('fa-refresh fa-spin');
|
||||||
|
|
||||||
|
request(url, (response) => {
|
||||||
|
if (response.type === 'updategrav') {
|
||||||
|
$('[data-gpm-grav]').remove();
|
||||||
|
$('#footer .grav-version').html(response.version);
|
||||||
|
}
|
||||||
|
|
||||||
|
element.removeAttr('disabled').find('> .fa').removeClass('fa-refresh fa-spin').addClass('fa-cloud-download');
|
||||||
|
});
|
||||||
|
});
|
||||||
11
themes/grav/app/utils/formatbytes.js
Normal file
11
themes/grav/app/utils/formatbytes.js
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
|
||||||
|
|
||||||
|
export default function formatBytes(bytes, decimals) {
|
||||||
|
if (bytes === 0) return '0 Byte';
|
||||||
|
|
||||||
|
let k = 1000;
|
||||||
|
let value = Math.floor(Math.log(bytes) / Math.log(k));
|
||||||
|
let decimal = decimals + 1 || 3;
|
||||||
|
|
||||||
|
return (bytes / Math.pow(k, value)).toPrecision(decimal) + ' ' + sizes[value];
|
||||||
|
}
|
||||||
58
themes/grav/app/utils/gpm.js
Normal file
58
themes/grav/app/utils/gpm.js
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
import { parseJSON, parseStatus, userFeedbackError } from './response';
|
||||||
|
import { config } from 'grav-config';
|
||||||
|
import { EventEmitter } from 'events';
|
||||||
|
|
||||||
|
export default class GPM extends EventEmitter {
|
||||||
|
constructor(action = 'getUpdates') {
|
||||||
|
super();
|
||||||
|
this.payload = {};
|
||||||
|
this.raw = {};
|
||||||
|
this.action = action;
|
||||||
|
}
|
||||||
|
|
||||||
|
setPayload(payload = {}) {
|
||||||
|
this.payload = payload;
|
||||||
|
this.emit('payload', payload);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
setAction(action = 'getUpdates') {
|
||||||
|
this.action = action;
|
||||||
|
this.emit('action', action);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
fetch(callback = () => true, flush = false) {
|
||||||
|
let data = new FormData();
|
||||||
|
data.append('task', 'GPM');
|
||||||
|
data.append('action', this.action);
|
||||||
|
|
||||||
|
if (flush) {
|
||||||
|
data.append('flush', true);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.emit('fetching', this);
|
||||||
|
|
||||||
|
fetch(config.base_url_relative, {
|
||||||
|
credentials: 'same-origin',
|
||||||
|
method: 'post',
|
||||||
|
body: data
|
||||||
|
}).then((response) => { this.raw = response; return response; })
|
||||||
|
.then(parseStatus)
|
||||||
|
.then(parseJSON)
|
||||||
|
.then((response) => this.response(response))
|
||||||
|
.then((response) => callback(response, this.raw))
|
||||||
|
.then((response) => this.emit('fetched', this.payload, this.raw, this))
|
||||||
|
.catch(userFeedbackError);
|
||||||
|
}
|
||||||
|
|
||||||
|
response(response) {
|
||||||
|
this.payload = response;
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export let Instance = new GPM();
|
||||||
4
themes/grav/app/utils/jquery-utils.js
vendored
Normal file
4
themes/grav/app/utils/jquery-utils.js
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
import $ from 'jquery';
|
||||||
|
|
||||||
|
// jQuery no parents filter
|
||||||
|
$.expr[':']['noparents'] = $.expr.createPseudo((text) => (element) => $(element).parents(text).length < 1);
|
||||||
32
themes/grav/app/utils/keepalive.js
Normal file
32
themes/grav/app/utils/keepalive.js
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import { config } from 'grav-config';
|
||||||
|
import { userFeedbackError } from './response';
|
||||||
|
|
||||||
|
class KeepAlive {
|
||||||
|
constructor() {
|
||||||
|
this.active = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
start() {
|
||||||
|
let timeout = config.admin_timeout / 1.5 * 1000;
|
||||||
|
this.timer = setInterval(() => this.fetch(), timeout);
|
||||||
|
this.active = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
stop() {
|
||||||
|
clearInterval(this.timer);
|
||||||
|
this.active = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fetch() {
|
||||||
|
let data = new FormData();
|
||||||
|
data.append('admin-nonce', config.admin_nonce);
|
||||||
|
|
||||||
|
fetch(`${config.base_url_relative}/task${config.param_sep}keepAlive`, {
|
||||||
|
credentials: 'same-origin',
|
||||||
|
method: 'post',
|
||||||
|
body: data
|
||||||
|
}).catch(userFeedbackError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default new KeepAlive();
|
||||||
38
themes/grav/app/utils/request.js
Normal file
38
themes/grav/app/utils/request.js
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
import { parseStatus, parseJSON, userFeedback, userFeedbackError } from './response';
|
||||||
|
import { config } from 'grav-config';
|
||||||
|
|
||||||
|
let raw;
|
||||||
|
let request = function(url, options = {}, callback = () => true) {
|
||||||
|
if (typeof options === 'function') {
|
||||||
|
callback = options;
|
||||||
|
options = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.method && options.method === 'post' && options.body) {
|
||||||
|
let data = new FormData();
|
||||||
|
|
||||||
|
options.body = Object.assign({ 'admin-nonce': config.admin_nonce }, options.body);
|
||||||
|
Object.keys(options.body).map((key) => data.append(key, options.body[key]));
|
||||||
|
options.body = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
options = Object.assign({
|
||||||
|
credentials: 'same-origin',
|
||||||
|
headers: {
|
||||||
|
'Accept': 'application/json'
|
||||||
|
}
|
||||||
|
}, options);
|
||||||
|
|
||||||
|
return fetch(url, options)
|
||||||
|
.then((response) => {
|
||||||
|
raw = response;
|
||||||
|
return response;
|
||||||
|
})
|
||||||
|
.then(parseStatus)
|
||||||
|
.then(parseJSON)
|
||||||
|
.then(userFeedback)
|
||||||
|
.then((response) => callback(response, raw))
|
||||||
|
.catch(userFeedbackError);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default request;
|
||||||
68
themes/grav/app/utils/response.js
Normal file
68
themes/grav/app/utils/response.js
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
import toastr from './toastr';
|
||||||
|
import { config } from 'grav-config';
|
||||||
|
|
||||||
|
let error = function(response) {
|
||||||
|
let error = new Error(response.statusText || response || '');
|
||||||
|
error.response = response;
|
||||||
|
|
||||||
|
return error;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function parseStatus(response) {
|
||||||
|
if (response.status >= 200 && response.status < 300) {
|
||||||
|
return response;
|
||||||
|
} else {
|
||||||
|
throw error(response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function parseJSON(response) {
|
||||||
|
return response.json();
|
||||||
|
}
|
||||||
|
|
||||||
|
export function userFeedback(response) {
|
||||||
|
let status = response.status;
|
||||||
|
let message = response.message || null;
|
||||||
|
let settings = response.toastr || null;
|
||||||
|
let backup;
|
||||||
|
|
||||||
|
switch (status) {
|
||||||
|
case 'unauthenticated':
|
||||||
|
document.location.href = config.base_url_relative;
|
||||||
|
throw error('Logged out');
|
||||||
|
case 'unauthorized':
|
||||||
|
status = 'error';
|
||||||
|
message = message || 'Unauthorized.';
|
||||||
|
break;
|
||||||
|
case 'error':
|
||||||
|
status = 'error';
|
||||||
|
message = message || 'Unknown error.';
|
||||||
|
break;
|
||||||
|
case 'success':
|
||||||
|
status = 'success';
|
||||||
|
message = message || '';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
status = 'error';
|
||||||
|
message = message || 'Invalid AJAX response.';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (settings) {
|
||||||
|
backup = Object.assign({}, toastr.options);
|
||||||
|
Object.keys(settings).forEach((key) => toastr.options[key] = settings[key]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (message) { toastr[status === 'success' ? 'success' : 'error'](message); }
|
||||||
|
|
||||||
|
if (settings) {
|
||||||
|
toastr.options = backup;
|
||||||
|
}
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function userFeedbackError(error) {
|
||||||
|
toastr.error(`Fetch Failed: <br /> ${error.message} <pre><code>${error.stack}</code></pre>`);
|
||||||
|
console.error(`${error.message} at ${error.stack}`);
|
||||||
|
}
|
||||||
6
themes/grav/app/utils/toastr.js
Normal file
6
themes/grav/app/utils/toastr.js
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
import toastr from 'toastr';
|
||||||
|
|
||||||
|
toastr.options.positionClass = 'toast-top-right';
|
||||||
|
toastr.options.preventDuplicates = true;
|
||||||
|
|
||||||
|
export default toastr;
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
73
themes/grav/gulpfile.js
Normal file
73
themes/grav/gulpfile.js
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var gulp = require('gulp'),
|
||||||
|
path = require('path'),
|
||||||
|
immutable = require('immutable'),
|
||||||
|
merge = require('merge-stream'),
|
||||||
|
gulpWebpack = require('gulp-webpack'),
|
||||||
|
webpack = require('webpack');
|
||||||
|
|
||||||
|
var plugins = {
|
||||||
|
'Promise': 'imports?this=>global!exports?global.Promise!babel-polyfill',
|
||||||
|
'fetch': 'imports?this=>global!exports?global.fetch!whatwg-fetch'
|
||||||
|
},
|
||||||
|
base = immutable.fromJS(require('./webpack.conf.js')),
|
||||||
|
options = {
|
||||||
|
dev: base.mergeDeep({
|
||||||
|
devtool: 'source-map',
|
||||||
|
plugins: [
|
||||||
|
new webpack.DefinePlugin({
|
||||||
|
'process.env': { NODE_ENV: '"development"' }
|
||||||
|
}),
|
||||||
|
new webpack.ProvidePlugin(plugins),
|
||||||
|
new webpack.optimize.CommonsChunkPlugin("vendor", "vendor.js", Infinity)
|
||||||
|
],
|
||||||
|
output: {
|
||||||
|
filename: 'admin.js'
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
|
||||||
|
prod: base.mergeDeep({
|
||||||
|
plugins: [
|
||||||
|
new webpack.DefinePlugin({
|
||||||
|
'process.env': { NODE_ENV: '"production"' }
|
||||||
|
}),
|
||||||
|
new webpack.optimize.UglifyJsPlugin({
|
||||||
|
sourceMap: false,
|
||||||
|
compress: {
|
||||||
|
warnings: false
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
new webpack.ProvidePlugin(plugins),
|
||||||
|
new webpack.optimize.CommonsChunkPlugin("vendor", "vendor.min.js", Infinity)
|
||||||
|
],
|
||||||
|
output: {
|
||||||
|
filename: 'admin.min.js'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
var compileJS = function(watch) {
|
||||||
|
var devOpts = options.dev.set('watch', watch),
|
||||||
|
prodOpts = options.prod.set('watch', watch);
|
||||||
|
|
||||||
|
var prod = gulp.src('app/main.js')
|
||||||
|
.pipe(gulpWebpack(prodOpts.toJS()))
|
||||||
|
.pipe(gulp.dest('js/'));
|
||||||
|
|
||||||
|
var dev = gulp.src('app/main.js')
|
||||||
|
.pipe(gulpWebpack(devOpts.toJS()))
|
||||||
|
.pipe(gulp.dest('js/'));
|
||||||
|
|
||||||
|
return merge(prod, dev);
|
||||||
|
};
|
||||||
|
|
||||||
|
gulp.task('js', function() {
|
||||||
|
compileJS(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
gulp.task('watch', function() {
|
||||||
|
compileJS(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
gulp.task('default', ['js']);
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
var getState = function(){
|
/*var getState = function(){
|
||||||
var loadValues = [],
|
var loadValues = [],
|
||||||
ignoreNames = ['page-filter', 'page-search'];
|
ignoreNames = ['page-filter', 'page-search'];
|
||||||
$('input, select, textarea').each(function(index, element){
|
$('input, select, textarea').each(function(index, element){
|
||||||
@@ -9,37 +9,37 @@ var getState = function(){
|
|||||||
});
|
});
|
||||||
|
|
||||||
return loadValues.toString();
|
return loadValues.toString();
|
||||||
};
|
};*/
|
||||||
|
|
||||||
var bytesToSize = function(bytes) {
|
/*var bytesToSize = function(bytes) {
|
||||||
var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
|
var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
|
||||||
if (bytes == 0) return '0 Byte';
|
if (bytes == 0) return '0 Byte';
|
||||||
var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
|
var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
|
||||||
return Math.round(bytes / Math.pow(1024, i), 2) + ' ' + sizes[i];
|
return Math.round(bytes / Math.pow(1024, i), 2) + ' ' + sizes[i];
|
||||||
};
|
};*/
|
||||||
|
|
||||||
var isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
|
/*var isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
|
||||||
|
|
||||||
var keepAlive = function keepAlive() {
|
var keepAlive = function keepAlive() {
|
||||||
$.post(GravAdmin.config.base_url_relative + '/task' + GravAdmin.config.param_sep + 'keepAlive', {
|
$.post(GravAdmin.config.base_url_relative + '/task' + GravAdmin.config.param_sep + 'keepAlive', {
|
||||||
'admin-nonce': GravAdmin.config.admin_nonce
|
'admin-nonce': GravAdmin.config.admin_nonce
|
||||||
});
|
});
|
||||||
};
|
};*/
|
||||||
|
|
||||||
$(function () {
|
$(function () {
|
||||||
jQuery.substitute = function(str, sub) {
|
/*jQuery.substitute = function(str, sub) {
|
||||||
return str.replace(/\{(.+?)\}/g, function($0, $1) {
|
return str.replace(/\{(.+?)\}/g, function($0, $1) {
|
||||||
return $1 in sub ? sub[$1] : $0;
|
return $1 in sub ? sub[$1] : $0;
|
||||||
});
|
});
|
||||||
};
|
};*/
|
||||||
|
|
||||||
// Set Toastr defaults
|
// Set Toastr defaults
|
||||||
toastr.options = {
|
/*toastr.options = {
|
||||||
"positionClass": "toast-top-right"
|
"positionClass": "toast-top-right"
|
||||||
}
|
}*/
|
||||||
|
|
||||||
// dashboard
|
// dashboard
|
||||||
var chart = $('.updates-chart'), UpdatesChart;
|
/*var chart = $('.updates-chart'), UpdatesChart;
|
||||||
if (chart.length) {
|
if (chart.length) {
|
||||||
var data = {
|
var data = {
|
||||||
series: [100, 0]
|
series: [100, 0]
|
||||||
@@ -60,17 +60,17 @@ $(function () {
|
|||||||
if (data.index) { return; }
|
if (data.index) { return; }
|
||||||
chart.find('.numeric span').text(Math.round(data.value) + '%');
|
chart.find('.numeric span').text(Math.round(data.value) + '%');
|
||||||
|
|
||||||
var text = translations.PLUGIN_ADMIN.UPDATES_AVAILABLE;
|
var text = GravAdmin.translations.PLUGIN_ADMIN.UPDATES_AVAILABLE;
|
||||||
if (data.value == 100) {
|
if (data.value == 100) {
|
||||||
text = translations.PLUGIN_ADMIN.FULLY_UPDATED;
|
text = GravAdmin.translations.PLUGIN_ADMIN.FULLY_UPDATED;
|
||||||
}
|
}
|
||||||
$('.js__updates-available-description').html(text)
|
$('.js__updates-available-description').html(text)
|
||||||
$('.updates-chart .hidden').removeClass('hidden');
|
$('.updates-chart .hidden').removeClass('hidden');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
// Cache Clear
|
// Cache Clear
|
||||||
$('[data-clear-cache]').on('click', function(e) {
|
/*$('[data-clear-cache]').on('click', function(e) {
|
||||||
|
|
||||||
$(this).attr('disabled','disabled').find('> .fa').removeClass('fa-trash').addClass('fa-refresh fa-spin');
|
$(this).attr('disabled','disabled').find('> .fa').removeClass('fa-trash').addClass('fa-refresh fa-spin');
|
||||||
var url = $(this).data('clearCache');
|
var url = $(this).data('clearCache');
|
||||||
@@ -85,10 +85,10 @@ $(function () {
|
|||||||
}).always(function() {
|
}).always(function() {
|
||||||
$('[data-clear-cache]').removeAttr('disabled').find('> .fa').removeClass('fa-refresh fa-spin').addClass('fa-trash');
|
$('[data-clear-cache]').removeAttr('disabled').find('> .fa').removeClass('fa-refresh fa-spin').addClass('fa-trash');
|
||||||
});
|
});
|
||||||
});
|
});*/
|
||||||
|
|
||||||
// Plugins list details sliders
|
// Plugins list details sliders
|
||||||
$('.gpm-name, .gpm-actions').on('click', function(e){
|
/*$('.gpm-name, .gpm-actions').on('click', function(e){
|
||||||
var target = $(e.target);
|
var target = $(e.target);
|
||||||
|
|
||||||
if (target.prop('tagName') == 'A' || target.parent('a').length) { return true; }
|
if (target.prop('tagName') == 'A' || target.parent('a').length) { return true; }
|
||||||
@@ -105,10 +105,10 @@ $(function () {
|
|||||||
.addClass('fa-chevron-' + (isVisible ? 'up' : 'down'));
|
.addClass('fa-chevron-' + (isVisible ? 'up' : 'down'));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});*/
|
||||||
|
|
||||||
// Update plugins/themes
|
// Update plugins/themes
|
||||||
$(document).on('click', '[data-maintenance-update]', function(e) {
|
/*$(document).on('click', '[data-maintenance-update]', function(e) {
|
||||||
|
|
||||||
$(this).attr('disabled','disabled').find('> .fa').removeClass('fa-cloud-download').addClass('fa-refresh fa-spin');
|
$(this).attr('disabled','disabled').find('> .fa').removeClass('fa-cloud-download').addClass('fa-refresh fa-spin');
|
||||||
var url = $(this).data('maintenanceUpdate');
|
var url = $(this).data('maintenanceUpdate');
|
||||||
@@ -125,9 +125,9 @@ $(function () {
|
|||||||
toastr.success(result.message + window.grav_available_version);
|
toastr.success(result.message + window.grav_available_version);
|
||||||
$('#footer .grav-version').html(window.grav_available_version);
|
$('#footer .grav-version').html(window.grav_available_version);
|
||||||
|
|
||||||
/*// hide the update button after successfull update and update the badges
|
/!*!// hide the update button after successfull update and update the badges
|
||||||
$('[data-maintenance-update]').fadeOut();
|
$('[data-maintenance-update]').fadeOut();
|
||||||
$('.badges.with-updates').removeClass('with-updates').find('.badge.updates').remove();*/
|
$('.badges.with-updates').removeClass('with-updates').find('.badge.updates').remove();*!/
|
||||||
} else {
|
} else {
|
||||||
toastr.success(result.message);
|
toastr.success(result.message);
|
||||||
}
|
}
|
||||||
@@ -139,10 +139,10 @@ $(function () {
|
|||||||
GPMRefresh();
|
GPMRefresh();
|
||||||
$('[data-maintenance-update]').removeAttr('disabled').find('> .fa').removeClass('fa-refresh fa-spin').addClass('fa-cloud-download');
|
$('[data-maintenance-update]').removeAttr('disabled').find('> .fa').removeClass('fa-refresh fa-spin').addClass('fa-cloud-download');
|
||||||
});
|
});
|
||||||
});
|
});*/
|
||||||
|
|
||||||
// Update plugins/themes
|
// Update plugins/themes
|
||||||
$('[data-ajax]').on('click', function(e) {
|
/*$('[data-ajax]').on('click', function(e) {
|
||||||
|
|
||||||
var button = $(this),
|
var button = $(this),
|
||||||
icon = button.find('> .fa'),
|
icon = button.find('> .fa'),
|
||||||
@@ -182,7 +182,7 @@ $(function () {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
toastr.success(result.message || translations.PLUGIN_ADMIN.TASK_COMPLETED);
|
toastr.success(result.message || GravAdmin.translations.PLUGIN_ADMIN.TASK_COMPLETED);
|
||||||
|
|
||||||
for (var setting in toastrBackup) { if (toastrBackup.hasOwnProperty(setting)) {
|
for (var setting in toastrBackup) { if (toastrBackup.hasOwnProperty(setting)) {
|
||||||
toastr.options[setting] = toastrBackup[setting];
|
toastr.options[setting] = toastrBackup[setting];
|
||||||
@@ -191,7 +191,7 @@ $(function () {
|
|||||||
|
|
||||||
if (url.indexOf(task + 'backup') !== -1) {
|
if (url.indexOf(task + 'backup') !== -1) {
|
||||||
//Reset backup days count
|
//Reset backup days count
|
||||||
$('.backups-chart .numeric').html("0 <em>" + translations.PLUGIN_ADMIN.DAYS + "</em>");
|
$('.backups-chart .numeric').html("0 <em>" + GravAdmin.translations.PLUGIN_ADMIN.DAYS + "</em>");
|
||||||
|
|
||||||
var data = {
|
var data = {
|
||||||
series: [0,100]
|
series: [0,100]
|
||||||
@@ -214,9 +214,9 @@ $(function () {
|
|||||||
button.removeAttr('disabled');
|
button.removeAttr('disabled');
|
||||||
icon.removeClass('fa-refresh fa-spin').addClass(iconClasses.join(' '));
|
icon.removeClass('fa-refresh fa-spin').addClass(iconClasses.join(' '));
|
||||||
});
|
});
|
||||||
});
|
});*/
|
||||||
|
|
||||||
$('[data-gpm-checkupdates]').on('click', function(){
|
/*$('[data-gpm-checkupdates]').on('click', function(){
|
||||||
var element = $(this);
|
var element = $(this);
|
||||||
element.find('i').addClass('fa-spin');
|
element.find('i').addClass('fa-spin');
|
||||||
GPMRefresh({
|
GPMRefresh({
|
||||||
@@ -227,21 +227,21 @@ $(function () {
|
|||||||
|
|
||||||
if (payload) {
|
if (payload) {
|
||||||
if (!payload.grav.isUpdatable && !payload.resources.total) {
|
if (!payload.grav.isUpdatable && !payload.resources.total) {
|
||||||
toastr.success(translations.PLUGIN_ADMIN.EVERYTHING_UP_TO_DATE);
|
toastr.success(GravAdmin.translations.PLUGIN_ADMIN.EVERYTHING_UP_TO_DATE);
|
||||||
} else {
|
} else {
|
||||||
var grav = payload.grav.isUpdatable ? 'Grav v' + payload.grav.available : '';
|
var grav = payload.grav.isUpdatable ? 'Grav v' + payload.grav.available : '';
|
||||||
var resources = payload.resources.total ? payload.resources.total + ' ' + translations.PLUGIN_ADMIN.UPDATES_ARE_AVAILABLE: '';
|
var resources = payload.resources.total ? payload.resources.total + ' ' + GravAdmin.translations.PLUGIN_ADMIN.UPDATES_ARE_AVAILABLE: '';
|
||||||
|
|
||||||
if (!resources) { grav += ' ' + translations.PLUGIN_ADMIN.IS_AVAILABLE_FOR_UPDATE }
|
if (!resources) { grav += ' ' + GravAdmin.translations.PLUGIN_ADMIN.IS_AVAILABLE_FOR_UPDATE }
|
||||||
toastr.info(grav + (grav && resources ? ' ' + translations.PLUGIN_ADMIN.AND + ' ' : '') + resources);
|
toastr.info(grav + (grav && resources ? ' ' + GravAdmin.translations.PLUGIN_ADMIN.AND + ' ' : '') + resources);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});*/
|
||||||
|
|
||||||
var GPMRefresh = function (options) {
|
var GPMRefresh = function (options) {
|
||||||
options = options || {};
|
/*options = options || {};
|
||||||
|
|
||||||
var data = {
|
var data = {
|
||||||
task: 'GPM',
|
task: 'GPM',
|
||||||
@@ -261,19 +261,19 @@ $(function () {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var grav = response.payload.grav,
|
/!*var grav = response.payload.grav,
|
||||||
installed = response.payload.installed,
|
installed = response.payload.installed,
|
||||||
resources = response.payload.resources,
|
resources = response.payload.resources,
|
||||||
task = 'task' + GravAdmin.config.param_sep;
|
task = 'task' + GravAdmin.config.param_sep;
|
||||||
|
*!/
|
||||||
// grav updatable
|
// grav updatable
|
||||||
if (grav.isUpdatable) {
|
/!*if (grav.isUpdatable) {
|
||||||
var icon = '<i class="fa fa-bullhorn"></i> ';
|
var icon = '<i class="fa fa-bullhorn"></i> ';
|
||||||
content = 'Grav <b>v{available}</b> ' + translations.PLUGIN_ADMIN.IS_NOW_AVAILABLE + '! <span class="less">(' + translations.PLUGIN_ADMIN.CURRENT + ': v{version})</span> ',
|
content = 'Grav <b>v{available}</b> ' + GravAdmin.translations.PLUGIN_ADMIN.IS_NOW_AVAILABLE + '! <span class="less">(' + GravAdmin.translations.PLUGIN_ADMIN.CURRENT + ': v{version})</span> ',
|
||||||
button = '<button data-maintenance-update="' + GravAdmin.config.base_url_relative + '/update.json/' + task + 'updategrav/admin-nonce' + GravAdmin.config.param_sep + GravAdmin.config.admin_nonce + '" class="button button-small secondary" id="grav-update-button">' + translations.PLUGIN_ADMIN.UPDATE_GRAV_NOW + '</button>';
|
button = '<button data-maintenance-update="' + GravAdmin.config.base_url_relative + '/update.json/' + task + 'updategrav/admin-nonce' + GravAdmin.config.param_sep + GravAdmin.config.admin_nonce + '" class="button button-small secondary" id="grav-update-button">' + GravAdmin.translations.PLUGIN_ADMIN.UPDATE_GRAV_NOW + '</button>';
|
||||||
|
|
||||||
if (grav.isSymlink) {
|
if (grav.isSymlink) {
|
||||||
button = '<span class="hint--left" style="float: right;" data-hint="' + translations.PLUGIN_ADMIN.GRAV_SYMBOLICALLY_LINKED + '"><i class="fa fa-fw fa-link"></i></span>';
|
button = '<span class="hint--left" style="float: right;" data-hint="' + GravAdmin.translations.PLUGIN_ADMIN.GRAV_SYMBOLICALLY_LINKED + '"><i class="fa fa-fw fa-link"></i></span>';
|
||||||
}
|
}
|
||||||
|
|
||||||
content = jQuery.substitute(content, {available: grav.available, version: grav.version});
|
content = jQuery.substitute(content, {available: grav.available, version: grav.version});
|
||||||
@@ -282,33 +282,33 @@ $(function () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$('#grav-update-button').on('click', function() {
|
$('#grav-update-button').on('click', function() {
|
||||||
$(this).html(translations.PLUGIN_ADMIN.UPDATING_PLEASE_WAIT + ' ' + bytesToSize(grav.assets['grav-update'].size) + '..');
|
$(this).html(GravAdmin.translations.PLUGIN_ADMIN.UPDATING_PLEASE_WAIT + ' ' + bytesToSize(grav.assets['grav-update'].size) + '..');
|
||||||
});
|
});*!/
|
||||||
|
|
||||||
// dashboard
|
// dashboard
|
||||||
if ($('.updates-chart').length) {
|
/!*if ($('.updates-chart').length) {
|
||||||
var missing = (resources.total + (grav.isUpdatable ? 1 : 0)) * 100 / (installed + (grav.isUpdatable ? 1 : 0)),
|
var missing = (resources.total + (grav.isUpdatable ? 1 : 0)) * 100 / (installed + (grav.isUpdatable ? 1 : 0)),
|
||||||
updated = 100 - missing;
|
updated = 100 - missing;
|
||||||
UpdatesChart.update({series: [updated, missing]});
|
UpdatesChart.update({series: [updated, missing]});
|
||||||
if (resources.total) {
|
if (resources.total) {
|
||||||
$('#updates [data-maintenance-update]').fadeIn();
|
$('#updates [data-maintenance-update]').fadeIn();
|
||||||
}
|
}
|
||||||
}
|
}*!/
|
||||||
|
|
||||||
if (!resources.total) {
|
/!*if (!resources.total) {
|
||||||
$('#updates [data-maintenance-update]').fadeOut();
|
$('#updates [data-maintenance-update]').fadeOut();
|
||||||
$('.badges.with-updates').removeClass('with-updates').find('.badge.updates').remove();
|
$('.badges.with-updates').removeClass('with-updates').find('.badge.updates').remove();
|
||||||
} else {
|
} else {
|
||||||
var length,
|
var length,
|
||||||
icon = '<i class="fa fa-bullhorn"></i>',
|
icon = '<i class="fa fa-bullhorn"></i>',
|
||||||
content = '{updates} ' + translations.PLUGIN_ADMIN.OF_YOUR + ' {type} ' + translations.PLUGIN_ADMIN.HAVE_AN_UPDATE_AVAILABLE,
|
content = '{updates} ' + GravAdmin.translations.PLUGIN_ADMIN.OF_YOUR + ' {type} ' + GravAdmin.translations.PLUGIN_ADMIN.HAVE_AN_UPDATE_AVAILABLE,
|
||||||
button = '<a href="{location}/' + task + 'update/admin-nonce' + GravAdmin.config.param_sep + GravAdmin.config.admin_nonce + '" class="button button-small secondary">' + translations.PLUGIN_ADMIN.UPDATE + ' {Type}</a>',
|
button = '<a href="{location}/' + task + 'update/admin-nonce' + GravAdmin.config.param_sep + GravAdmin.config.admin_nonce + '" class="button button-small secondary">' + GravAdmin.translations.PLUGIN_ADMIN.UPDATE + ' {Type}</a>',
|
||||||
plugins = $('.grav-update.plugins'),
|
plugins = $('.grav-update.plugins'),
|
||||||
themes = $('.grav-update.themes'),
|
themes = $('.grav-update.themes'),
|
||||||
sidebar = {plugins: $('#admin-menu a[href$="/plugins"]'), themes: $('#admin-menu a[href$="/themes"]')};
|
sidebar = {plugins: $('#admin-menu a[href$="/plugins"]'), themes: $('#admin-menu a[href$="/themes"]')};
|
||||||
|
|
||||||
// sidebar
|
// sidebar
|
||||||
if (sidebar.plugins.length || sidebar.themes.length) {
|
/!*if (sidebar.plugins.length || sidebar.themes.length) {
|
||||||
var length, badges;
|
var length, badges;
|
||||||
if (sidebar.plugins.length && (length = Object.keys(resources.plugins).length)) {
|
if (sidebar.plugins.length && (length = Object.keys(resources.plugins).length)) {
|
||||||
badges = sidebar.plugins.find('.badges');
|
badges = sidebar.plugins.find('.badges');
|
||||||
@@ -321,7 +321,7 @@ $(function () {
|
|||||||
badges.addClass('with-updates');
|
badges.addClass('with-updates');
|
||||||
badges.find('.badge.updates').text(length);
|
badges.find('.badge.updates').text(length);
|
||||||
}
|
}
|
||||||
}
|
}*!/
|
||||||
|
|
||||||
// list page
|
// list page
|
||||||
if (plugins[0] && (length = Object.keys(resources.plugins).length)) {
|
if (plugins[0] && (length = Object.keys(resources.plugins).length)) {
|
||||||
@@ -334,7 +334,7 @@ $(function () {
|
|||||||
plugin = $('[data-gpm-plugin="' + key + '"] .gpm-name');
|
plugin = $('[data-gpm-plugin="' + key + '"] .gpm-name');
|
||||||
url = plugin.find('a');
|
url = plugin.find('a');
|
||||||
if (!plugin.find('.badge.update').length) {
|
if (!plugin.find('.badge.update').length) {
|
||||||
plugin.append('<a class="plugin-update-button" href="' + url.attr('href') + '"><span class="badge update">' + translations.PLUGIN_ADMIN.UPDATE_AVAILABLE + '!</span></a>');
|
plugin.append('<a class="plugin-update-button" href="' + url.attr('href') + '"><span class="badge update">' + GravAdmin.translations.PLUGIN_ADMIN.UPDATE_AVAILABLE + '!</span></a>');
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
@@ -349,12 +349,12 @@ $(function () {
|
|||||||
$.each(resources.themes, function (key, value) {
|
$.each(resources.themes, function (key, value) {
|
||||||
theme = $('[data-gpm-theme="' + key + '"]');
|
theme = $('[data-gpm-theme="' + key + '"]');
|
||||||
url = theme.find('.gpm-name a');
|
url = theme.find('.gpm-name a');
|
||||||
theme.append('<div class="gpm-ribbon"><a href="' + url.attr('href') + '">' + translations.PLUGIN_ADMIN.UPDATE.toUpperCase() + '</a></div>');
|
theme.append('<div class="gpm-ribbon"><a href="' + url.attr('href') + '">' + GravAdmin.translations.PLUGIN_ADMIN.UPDATE.toUpperCase() + '</a></div>');
|
||||||
});
|
});
|
||||||
}
|
}*!/
|
||||||
|
|
||||||
// details page
|
// details page
|
||||||
var type = 'plugin',
|
/!*var type = 'plugin',
|
||||||
details = $('.grav-update.plugin')[0];
|
details = $('.grav-update.plugin')[0];
|
||||||
|
|
||||||
if (!details) {
|
if (!details) {
|
||||||
@@ -368,7 +368,7 @@ $(function () {
|
|||||||
resource = resources[type + 's'][slug];
|
resource = resources[type + 's'][slug];
|
||||||
|
|
||||||
if (resource) {
|
if (resource) {
|
||||||
content = '<strong>v{available}</strong> ' + translations.PLUGIN_ADMIN.OF_THIS + ' ' + type + ' ' + translations.PLUGIN_ADMIN.IS_NOW_AVAILABLE + '!';
|
content = '<strong>v{available}</strong> ' + GravAdmin.translations.PLUGIN_ADMIN.OF_THIS + ' ' + type + ' ' + GravAdmin.translations.PLUGIN_ADMIN.IS_NOW_AVAILABLE + '!';
|
||||||
content = jQuery.substitute(content, { available: resource.available });
|
content = jQuery.substitute(content, { available: resource.available });
|
||||||
button = jQuery.substitute(button, {
|
button = jQuery.substitute(button, {
|
||||||
Type: Type,
|
Type: Type,
|
||||||
@@ -376,21 +376,21 @@ $(function () {
|
|||||||
});
|
});
|
||||||
$(details).html('<p>' + icon + content + button + '</p>');
|
$(details).html('<p>' + icon + content + button + '</p>');
|
||||||
}
|
}
|
||||||
}
|
}*!/
|
||||||
}
|
//}
|
||||||
|
|
||||||
if (options.callback && typeof options.callback == 'function') options.callback(response);
|
if (options.callback && typeof options.callback == 'function') options.callback(response);
|
||||||
}
|
}
|
||||||
}).always(function() {
|
}).always(function() {
|
||||||
$('[data-gpm-checkupdates]').find('i').removeClass('fa-spin');
|
$('[data-gpm-checkupdates]').find('i').removeClass('fa-spin');
|
||||||
});
|
});*/
|
||||||
};
|
};
|
||||||
|
|
||||||
if (GravAdmin.config.enable_auto_updates_check === '1') {
|
/*if (GravAdmin.config.enable_auto_updates_check === '1') {
|
||||||
GPMRefresh();
|
GPMRefresh();
|
||||||
}
|
}*/
|
||||||
|
|
||||||
function reIndex (collection) {
|
/*function reIndex (collection) {
|
||||||
var holder = collection.find('[data-collection-holder]'),
|
var holder = collection.find('[data-collection-holder]'),
|
||||||
addBtn = collection.find('[data-action="add"]'),
|
addBtn = collection.find('[data-action="add"]'),
|
||||||
prefix = holder.data('collection-holder'),
|
prefix = holder.data('collection-holder'),
|
||||||
@@ -469,10 +469,10 @@ $(function () {
|
|||||||
MDEditors.add(field);
|
MDEditors.add(field);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});*/
|
||||||
|
|
||||||
// enable the toggleable checkbox when typing in the corresponding textarea/input element
|
// enable the toggleable checkbox when typing in the corresponding textarea/input element
|
||||||
jQuery(document).on('input propertychange click', '.form-data textarea, .form-data input, .form-data label, .form-data .selectize-input', function() {
|
/*jQuery(document).on('input propertychange click', '.form-data textarea, .form-data input, .form-data label, .form-data .selectize-input', function() {
|
||||||
var item = this;
|
var item = this;
|
||||||
|
|
||||||
var checkbox = $(item).parents('.form-field').find('.toggleable input[type="checkbox"]');
|
var checkbox = $(item).parents('.form-field').find('.toggleable input[type="checkbox"]');
|
||||||
@@ -501,26 +501,26 @@ $(function () {
|
|||||||
input.siblings('label').css('opacity', on ? 1 : 0.7);
|
input.siblings('label').css('opacity', on ? 1 : 0.7);
|
||||||
$(this).parents('.form-label').siblings('.form-data').css('opacity', on ? 1 : 0.7);
|
$(this).parents('.form-label').siblings('.form-data').css('opacity', on ? 1 : 0.7);
|
||||||
|
|
||||||
});
|
});*/
|
||||||
|
|
||||||
// Themes Switcher Warning
|
// Themes Switcher Warning
|
||||||
$(document).on('mousedown', '[data-remodal-target="theme-switch-warn"]', function(e){
|
/*$(document).on('mousedown', '[data-remodal-target="theme-switch-warn"]', function(e){
|
||||||
var name = $(e.target).closest('[data-gpm-theme]').find('.gpm-name a').text(),
|
var name = $(e.target).closest('[data-gpm-theme]').find('.gpm-name a').text(),
|
||||||
remodal = $('.remodal.theme-switcher');
|
remodal = $('.remodal.theme-switcher');
|
||||||
|
|
||||||
remodal.find('strong').text(name);
|
remodal.find('strong').text(name);
|
||||||
remodal.find('.button.continue').attr('href', $(e.target).attr('href'));
|
remodal.find('.button.continue').attr('href', $(e.target).attr('href'));
|
||||||
});
|
});*/
|
||||||
|
|
||||||
// Setup keep-alive on pages that have at least one element with data-grav-keepalive="true" set
|
// Setup keep-alive on pages that have at least one element with data-grav-keepalive="true" set
|
||||||
if ($(document).find('[data-grav-keepalive="true"]').length > 0) {
|
/*if ($(document).find('[data-grav-keepalive="true"]').length > 0) {
|
||||||
setInterval(function() {
|
setInterval(function() {
|
||||||
keepAlive();
|
keepAlive();
|
||||||
}, (GravAdmin.config.admin_timeout/2)*1000);
|
}, (GravAdmin.config.admin_timeout/2)*1000);
|
||||||
}
|
}*/
|
||||||
|
|
||||||
// CTRL + S / CMD + S - shortcut for [Save] when available
|
// CTRL + S / CMD + S - shortcut for [Save] when available
|
||||||
var saveTask = $('[name="task"][value="save"]').filter(function(index, element) {
|
/*var saveTask = $('[name="task"][value="save"]').filter(function(index, element) {
|
||||||
return !($(element).parents('.remodal-overlay').length);
|
return !($(element).parents('.remodal-overlay').length);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -532,5 +532,5 @@ $(function () {
|
|||||||
saveTask.click();
|
saveTask.click();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}*/
|
||||||
});
|
});
|
||||||
|
|||||||
13993
themes/grav/js/admin.js
Normal file
13993
themes/grav/js/admin.js
Normal file
File diff suppressed because it is too large
Load Diff
1
themes/grav/js/admin.js.map
Normal file
1
themes/grav/js/admin.js.map
Normal file
File diff suppressed because one or more lines are too long
6
themes/grav/js/admin.min.js
vendored
Normal file
6
themes/grav/js/admin.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -204,7 +204,7 @@
|
|||||||
this.scanned = true;
|
this.scanned = true;
|
||||||
|
|
||||||
//Refresh root.currentValues as toggleables have been initialized
|
//Refresh root.currentValues as toggleables have been initialized
|
||||||
root.currentValues = getState();
|
// root.currentValues = getState();
|
||||||
};
|
};
|
||||||
|
|
||||||
Form.factories = {};
|
Form.factories = {};
|
||||||
|
|||||||
@@ -78,7 +78,21 @@
|
|||||||
markdown: false,
|
markdown: false,
|
||||||
autocomplete: true,
|
autocomplete: true,
|
||||||
height: 500,
|
height: 500,
|
||||||
codemirror : { mode: 'htmlmixed', theme: 'paper', lineWrapping: true, dragDrop: true, autoCloseTags: true, matchTags: true, autoCloseBrackets: true, matchBrackets: true, indentUnit: 4, indentWithTabs: false, tabSize: 4, hintOptions: {completionSingle:false}, extraKeys: {"Enter": "newlineAndIndentContinueMarkdownList"} },
|
codemirror: {
|
||||||
|
mode: 'htmlmixed',
|
||||||
|
theme: 'paper',
|
||||||
|
lineWrapping: true,
|
||||||
|
dragDrop: true,
|
||||||
|
autoCloseTags: true,
|
||||||
|
matchTags: true,
|
||||||
|
autoCloseBrackets: true,
|
||||||
|
matchBrackets: true,
|
||||||
|
indentUnit: 4,
|
||||||
|
indentWithTabs: false,
|
||||||
|
tabSize: 4,
|
||||||
|
hintOptions: { completionSingle: false },
|
||||||
|
extraKeys: { "Enter": "newlineAndIndentContinueMarkdownList" }
|
||||||
|
},
|
||||||
toolbar: toolbarIdentifiers,
|
toolbar: toolbarIdentifiers,
|
||||||
lblPreview: '<i class="fa fa-fw fa-eye"></i>',
|
lblPreview: '<i class="fa fa-fw fa-eye"></i>',
|
||||||
lblCodeview: '<i class="fa fa-fw fa-code"></i>',
|
lblCodeview: '<i class="fa fa-fw fa-code"></i>',
|
||||||
@@ -361,7 +375,13 @@
|
|||||||
var curWord = start != end && curLine.slice(start, end);
|
var curWord = start != end && curLine.slice(start, end);
|
||||||
|
|
||||||
if (curWord) {
|
if (curWord) {
|
||||||
this.editor.setSelection({ line: cur.line, ch: start}, { line: cur.line, ch: end });
|
this.editor.setSelection({
|
||||||
|
line: cur.line,
|
||||||
|
ch: start
|
||||||
|
}, {
|
||||||
|
line: cur.line,
|
||||||
|
ch: end
|
||||||
|
});
|
||||||
text = curWord;
|
text = curWord;
|
||||||
} else {
|
} else {
|
||||||
indexOf = replace.indexOf('$1');
|
indexOf = replace.indexOf('$1');
|
||||||
@@ -372,10 +392,16 @@
|
|||||||
|
|
||||||
this.editor.replaceSelection(html, 'end');
|
this.editor.replaceSelection(html, 'end');
|
||||||
if (indexOf !== -1) {
|
if (indexOf !== -1) {
|
||||||
this.editor.setCursor({ line: cur.line, ch: start + indexOf });
|
this.editor.setCursor({
|
||||||
|
line: cur.line,
|
||||||
|
ch: start + indexOf
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
if (action == 'link' || action == 'image') {
|
if (action == 'link' || action == 'image') {
|
||||||
this.editor.setCursor({ line: cur.line, ch: html.length -1 });
|
this.editor.setCursor({
|
||||||
|
line: cur.line,
|
||||||
|
ch: html.length - 1
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -387,8 +413,17 @@
|
|||||||
text = this.editor.getLine(pos.line),
|
text = this.editor.getLine(pos.line),
|
||||||
html = replace.replace('$1', text);
|
html = replace.replace('$1', text);
|
||||||
|
|
||||||
this.editor.replaceRange(html , { line: pos.line, ch: 0 }, { line: pos.line, ch: text.length });
|
this.editor.replaceRange(html, {
|
||||||
this.editor.setCursor({ line: pos.line, ch: html.length });
|
line: pos.line,
|
||||||
|
ch: 0
|
||||||
|
}, {
|
||||||
|
line: pos.line,
|
||||||
|
ch: text.length
|
||||||
|
});
|
||||||
|
this.editor.setCursor({
|
||||||
|
line: pos.line,
|
||||||
|
ch: html.length
|
||||||
|
});
|
||||||
this.editor.focus();
|
this.editor.focus();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -415,10 +450,19 @@
|
|||||||
posend = cm.getDoc().getCursor(false);
|
posend = cm.getDoc().getCursor(false);
|
||||||
|
|
||||||
for (var i = pos.line; i < (posend.line + 1); i++) {
|
for (var i = pos.line; i < (posend.line + 1); i++) {
|
||||||
cm.replaceRange('* '+cm.getLine(i), { line: i, ch: 0 }, { line: i, ch: cm.getLine(i).length });
|
cm.replaceRange('* ' + cm.getLine(i), {
|
||||||
|
line: i,
|
||||||
|
ch: 0
|
||||||
|
}, {
|
||||||
|
line: i,
|
||||||
|
ch: cm.getLine(i).length
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
cm.setCursor({ line: posend.line, ch: cm.getLine(posend.line).length });
|
cm.setCursor({
|
||||||
|
line: posend.line,
|
||||||
|
ch: cm.getLine(posend.line).length
|
||||||
|
});
|
||||||
cm.focus();
|
cm.focus();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -441,11 +485,20 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (var i = pos.line; i < (posend.line + 1); i++) {
|
for (var i = pos.line; i < (posend.line + 1); i++) {
|
||||||
cm.replaceRange(prefix+'. '+cm.getLine(i), { line: i, ch: 0 }, { line: i, ch: cm.getLine(i).length });
|
cm.replaceRange(prefix + '. ' + cm.getLine(i), {
|
||||||
|
line: i,
|
||||||
|
ch: 0
|
||||||
|
}, {
|
||||||
|
line: i,
|
||||||
|
ch: cm.getLine(i).length
|
||||||
|
});
|
||||||
prefix++;
|
prefix++;
|
||||||
}
|
}
|
||||||
|
|
||||||
cm.setCursor({ line: posend.line, ch: cm.getLine(posend.line).length });
|
cm.setCursor({
|
||||||
|
line: posend.line,
|
||||||
|
ch: cm.getLine(posend.line).length
|
||||||
|
});
|
||||||
cm.focus();
|
cm.focus();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -501,7 +554,12 @@
|
|||||||
|
|
||||||
if (editor.mdeditor.hasClass('grav-mdeditor-fullscreen')) {
|
if (editor.mdeditor.hasClass('grav-mdeditor-fullscreen')) {
|
||||||
|
|
||||||
editor.editor.state.fullScreenRestore = {scrollTop: window.pageYOffset, scrollLeft: window.pageXOffset, width: wrap.style.width, height: wrap.style.height};
|
editor.editor.state.fullScreenRestore = {
|
||||||
|
scrollTop: window.pageYOffset,
|
||||||
|
scrollLeft: window.pageXOffset,
|
||||||
|
width: wrap.style.width,
|
||||||
|
height: wrap.style.height
|
||||||
|
};
|
||||||
wrap.style.width = '';
|
wrap.style.width = '';
|
||||||
wrap.style.height = editor.content.height() + 'px';
|
wrap.style.height = editor.content.height() + 'px';
|
||||||
document.documentElement.style.overflow = 'hidden';
|
document.documentElement.style.overflow = 'hidden';
|
||||||
@@ -510,7 +568,8 @@
|
|||||||
|
|
||||||
document.documentElement.style.overflow = '';
|
document.documentElement.style.overflow = '';
|
||||||
var info = editor.editor.state.fullScreenRestore;
|
var info = editor.editor.state.fullScreenRestore;
|
||||||
wrap.style.width = info.width; wrap.style.height = info.height;
|
wrap.style.width = info.width;
|
||||||
|
wrap.style.height = info.height;
|
||||||
window.scrollTo(info.scrollLeft, info.scrollTop);
|
window.scrollTo(info.scrollLeft, info.scrollTop);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -553,15 +612,19 @@
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
add: function(editor) {
|
add: function(editors) {
|
||||||
|
editors = $(editors);
|
||||||
|
|
||||||
|
var mdeditor = [];
|
||||||
|
|
||||||
|
editors.each(function(index, editor) {
|
||||||
editor = $(editor);
|
editor = $(editor);
|
||||||
|
|
||||||
var mdeditor;
|
|
||||||
if (!editor.data('mdeditor_initialized')) {
|
if (!editor.data('mdeditor_initialized')) {
|
||||||
mdeditor = new MDEditor(editor, JSON.parse(editor.attr('data-grav-mdeditor') || '{}'));
|
mdeditor.push(new MDEditor(editor, JSON.parse(editor.attr('data-grav-mdeditor') || '{}')));
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return mdeditor || MDEditors.editors[editor.attr('name')];
|
return mdeditor || MDEditors.editors[editors.attr('name')];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
4
themes/grav/js/modernizr.custom.71422.js
vendored
4
themes/grav/js/modernizr.custom.71422.js
vendored
File diff suppressed because one or more lines are too long
@@ -3,11 +3,11 @@ $(function(){
|
|||||||
root = root.GravJS = root.GravJS || {};
|
root = root.GravJS = root.GravJS || {};
|
||||||
|
|
||||||
//Make it global because used by ./forms/form.js
|
//Make it global because used by ./forms/form.js
|
||||||
root.currentValues = getState();
|
//root.currentValues = getState();
|
||||||
var clickedLink;
|
//var clickedLink;
|
||||||
|
|
||||||
// selectize
|
// selectize
|
||||||
var pageFilter = $('input.page-filter'),
|
/*var pageFilter = $('input.page-filter'),
|
||||||
pageTypes = pageFilter.data('template-types'),
|
pageTypes = pageFilter.data('template-types'),
|
||||||
accessLevels = pageFilter.data('template-access-levels'),
|
accessLevels = pageFilter.data('template-access-levels'),
|
||||||
options = [
|
options = [
|
||||||
@@ -175,17 +175,17 @@ $(function(){
|
|||||||
$(item).hide();
|
$(item).hide();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};*/
|
||||||
|
|
||||||
// selectize
|
// selectize
|
||||||
$('input[name="page-search"]').on('input', startFilterPages);
|
/*$('input[name="page-search"]').on('input', startFilterPages);
|
||||||
$('input[name="page-filter"]').on('change', startFilterPages);
|
$('input[name="page-filter"]').on('change', startFilterPages);*/
|
||||||
|
|
||||||
|
|
||||||
// auto generate folder based on title
|
// auto generate folder based on title
|
||||||
// on user input on folder, autogeneration stops
|
// on user input on folder, autogeneration stops
|
||||||
// if user empties the folder, autogeneration restarts
|
// if user empties the folder, autogeneration restarts
|
||||||
$('input[name="folder"]').on('input', function(){
|
/*$('input[name="folder"]').on('input', function(){
|
||||||
$(this).data('user-custom-folder', true);
|
$(this).data('user-custom-folder', true);
|
||||||
if (!$(this).val()) $(this).data('user-custom-folder', false);
|
if (!$(this).val()) $(this).data('user-custom-folder', false);
|
||||||
});
|
});
|
||||||
@@ -209,9 +209,9 @@ $(function(){
|
|||||||
|
|
||||||
// restore cursor position
|
// restore cursor position
|
||||||
this.setSelectionRange(start, end);
|
this.setSelectionRange(start, end);
|
||||||
});
|
});*/
|
||||||
|
|
||||||
childrenToggles.on('click', function () {
|
/* childrenToggles.on('click', function () {
|
||||||
var icon = $(this).find('.page-icon'),
|
var icon = $(this).find('.page-icon'),
|
||||||
open = icon.hasClass('children-open'),
|
open = icon.hasClass('children-open'),
|
||||||
key = $(this).closest('[data-nav-id]').data('nav-id'),
|
key = $(this).closest('[data-nav-id]').data('nav-id'),
|
||||||
@@ -229,22 +229,24 @@ $(function(){
|
|||||||
|
|
||||||
sessionStorage.setItem('grav:admin:pages', JSON.stringify(storage));
|
sessionStorage.setItem('grav:admin:pages', JSON.stringify(storage));
|
||||||
});
|
});
|
||||||
|
*/
|
||||||
$('[data-page-toggleall]').on('click', function() {
|
/*$('[data-page-toggleall]').on('click', function() {
|
||||||
var state = $(this).data('page-toggleall');
|
var state = $(this).data('page-toggleall');
|
||||||
if (state == 'collapse') collapseAll(true);
|
if (state == 'collapse') collapseAll(true);
|
||||||
else expandAll(true);
|
else expandAll(true);
|
||||||
});
|
});
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
UNKNOWN
|
||||||
$('#admin-main button').on('click', function(){
|
$('#admin-main button').on('click', function(){
|
||||||
$(window).off('beforeunload');
|
$(window).off('beforeunload');
|
||||||
});
|
});
|
||||||
|
|
||||||
$('[data-remodal-id] form').on('submit', function(){
|
$('[data-remodal-id] form').on('submit', function(){
|
||||||
$(window).off('beforeunload');
|
$(window).off('beforeunload');
|
||||||
});
|
});*/
|
||||||
|
|
||||||
$("#admin-mode-toggle input[name=mode-switch]").on('change', function(e){
|
/*$("#admin-mode-toggle input[name=mode-switch]").on('change', function(e){
|
||||||
var value = $(this).val(),
|
var value = $(this).val(),
|
||||||
uri = $(this).data('leave-url');
|
uri = $(this).data('leave-url');
|
||||||
|
|
||||||
@@ -278,9 +280,9 @@ $(function(){
|
|||||||
});
|
});
|
||||||
|
|
||||||
confirm.open();
|
confirm.open();
|
||||||
});
|
});*/
|
||||||
|
|
||||||
$('a[href]:not([href^="#"])').on('click', function(e){
|
/*$('a[href]:not([href^=#])').on('click', function(e){
|
||||||
if (root.currentValues != getState()){
|
if (root.currentValues != getState()){
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
@@ -305,9 +307,10 @@ $(function(){
|
|||||||
|
|
||||||
confirm.open();
|
confirm.open();
|
||||||
}
|
}
|
||||||
});
|
});*/
|
||||||
|
|
||||||
// deletion
|
// deletion
|
||||||
|
/*
|
||||||
$('[data-remodal-target="delete"]').on('click', function(){
|
$('[data-remodal-target="delete"]').on('click', function(){
|
||||||
var okdelete = $('[data-remodal-id=delete] a.button');
|
var okdelete = $('[data-remodal-id=delete] a.button');
|
||||||
|
|
||||||
@@ -320,13 +323,13 @@ $(function(){
|
|||||||
|
|
||||||
window.location.href = okdelete;
|
window.location.href = okdelete;
|
||||||
confirm.close();
|
confirm.close();
|
||||||
});
|
});*/
|
||||||
|
|
||||||
$(window).on('beforeunload', function(){
|
/*$(window).on('beforeunload', function(){
|
||||||
if (root.currentValues != getState()){
|
if (root.currentValues != getState()){
|
||||||
return "You have made changes on this page that you have not yet confirmed. If you navigate away from this page you will lose your unsaved changes";
|
return "You have made changes on this page that you have not yet confirmed. If you navigate away from this page you will lose your unsaved changes";
|
||||||
}
|
}
|
||||||
});
|
});*/
|
||||||
|
|
||||||
// Move dropdown sync (on dropdown change)
|
// Move dropdown sync (on dropdown change)
|
||||||
/*$('body').on('change', '[data-page-move] select', function(){
|
/*$('body').on('change', '[data-page-move] select', function(){
|
||||||
@@ -339,7 +342,7 @@ $(function(){
|
|||||||
});*/
|
});*/
|
||||||
|
|
||||||
// Move dropdown sync (on continue)
|
// Move dropdown sync (on continue)
|
||||||
$('[data-page-move] button').on('click', function(){
|
/*$('[data-page-move] button').on('click', function(){
|
||||||
var route = jQuery('form#blueprints').first().find('select[name="route"]'),
|
var route = jQuery('form#blueprints').first().find('select[name="route"]'),
|
||||||
value = $('[data-page-move] select').val();
|
value = $('[data-page-move] select').val();
|
||||||
if (route.length && route.val() !== value) {
|
if (route.length && route.val() !== value) {
|
||||||
@@ -347,5 +350,5 @@ $(function(){
|
|||||||
route.val(value);
|
route.val(value);
|
||||||
if (selectize) selectize.setValue(value);
|
if (selectize) selectize.setValue(value);
|
||||||
}
|
}
|
||||||
});
|
});*/
|
||||||
});
|
});
|
||||||
|
|||||||
14642
themes/grav/js/vendor.js
Normal file
14642
themes/grav/js/vendor.js
Normal file
File diff suppressed because it is too large
Load Diff
1
themes/grav/js/vendor.js.map
Normal file
1
themes/grav/js/vendor.js.map
Normal file
File diff suppressed because one or more lines are too long
13
themes/grav/js/vendor.min.js
vendored
Normal file
13
themes/grav/js/vendor.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
43
themes/grav/package.json
Normal file
43
themes/grav/package.json
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
{
|
||||||
|
"name": "grav-admin",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "Grav Admin",
|
||||||
|
"repository": "https://github.com/getgrav/grav-admin",
|
||||||
|
"main": "app/main.js",
|
||||||
|
"scripts": {
|
||||||
|
"watch": "webpack --watch --progress --colors --config webpack.conf.js",
|
||||||
|
"dev": "webpack --progress --colors --config webpack.conf.js",
|
||||||
|
"prod": "NODE_ENV=production webpack -p --config webpack.conf.js",
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"author": "RocketTheme, LLC",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"bootstrap": "^3.3.6",
|
||||||
|
"chartist": "^0.9.5",
|
||||||
|
"debounce": "^1.0.0",
|
||||||
|
"dropzone": "^4.2.0",
|
||||||
|
"eonasdan-bootstrap-datetimepicker": "^4.15.35",
|
||||||
|
"immutable": "^3.7.6",
|
||||||
|
"jquery-slugify": "^1.2.3",
|
||||||
|
"remodal": "^1.0.6",
|
||||||
|
"selectize": "^0.12.1",
|
||||||
|
"sortablejs": "^1.4.2",
|
||||||
|
"toastr": "^2.1.2",
|
||||||
|
"whatwg-fetch": "^0.10.1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"babel-core": "^6.3.26",
|
||||||
|
"babel-loader": "^6.2.0",
|
||||||
|
"babel-polyfill": "^6.3.14",
|
||||||
|
"babel-preset-es2015": "^6.3.13",
|
||||||
|
"eslint": "^1.10.3",
|
||||||
|
"eslint-loader": "^1.1.1",
|
||||||
|
"exports-loader": "^0.6.2",
|
||||||
|
"gulp": "^3.9.0",
|
||||||
|
"gulp-webpack": "^1.5.0",
|
||||||
|
"imports-loader": "^0.6.5",
|
||||||
|
"merge-stream": "^1.0.0",
|
||||||
|
"webpack": "^1.12.9"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,101 +13,146 @@
|
|||||||
|
|
||||||
/* Hide scroll bar */
|
/* Hide scroll bar */
|
||||||
|
|
||||||
html.remodal_lock, body.remodal_lock {
|
html.remodal-is-locked {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
|
touch-action: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Anti FOUC */
|
/* Anti FOUC */
|
||||||
|
|
||||||
.remodal, [data-remodal-id] {
|
.remodal, [data-remodal-id] {
|
||||||
visibility: hidden;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Overlay necessary styles */
|
/* Overlay necessary styles */
|
||||||
|
|
||||||
.remodal-overlay {
|
.remodal-overlay {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
|
z-index: 99999;
|
||||||
|
top: -5000px;
|
||||||
|
right: -5000px;
|
||||||
|
bottom: -5000px;
|
||||||
|
left: -5000px;
|
||||||
|
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Necessary styles of the wrapper */
|
||||||
|
|
||||||
|
.remodal-wrapper {
|
||||||
|
position: fixed;
|
||||||
|
z-index: 100000;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
|
||||||
right: 0;
|
right: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
z-index: 10000;
|
left: 0;
|
||||||
|
|
||||||
display: none;
|
display: none;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
-webkit-overflow-scrolling: touch;
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
|
|
||||||
&:after {
|
&:after {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
|
||||||
height: 100%;
|
height: 100%;
|
||||||
margin-left: -0.05em;
|
margin-left: -0.05em;
|
||||||
|
|
||||||
content: '';
|
content: '';
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Fix iPad, iPhone glitches */
|
/* Fix iPad, iPhone glitches */
|
||||||
> * {
|
|
||||||
-webkit-transform: translateZ(0px);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
.remodal-overlay,
|
||||||
|
.remodal-wrapper {
|
||||||
|
backface-visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
/* Modal dialog necessary styles */
|
/* Modal dialog necessary styles */
|
||||||
.remodal {
|
.remodal {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
outline: none;
|
||||||
|
text-size-adjust: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.remodal-is-initialized {
|
||||||
|
/* Disable Anti-FOUC */
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
text-align: left;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Background for effects */
|
/* ==========================================================================
|
||||||
|
Remodal's default mobile first theme
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
.remodal-bg {
|
/* Default theme styles for the background */
|
||||||
@include transition-property (filter);
|
|
||||||
@include transition-duration(0.2s);
|
.remodal-bg.remodal-is-opening,
|
||||||
@include transition-timing-function(linear);
|
.remodal-bg.remodal-is-opened {
|
||||||
|
@include filter(blur(3px));
|
||||||
}
|
}
|
||||||
|
|
||||||
// body.remodal_active .remodal-bg {
|
/* Default theme styles of the overlay */
|
||||||
// @include filter(blur(5px));
|
|
||||||
// }
|
|
||||||
|
|
||||||
/* Overlay default theme styles */
|
|
||||||
|
|
||||||
.remodal-overlay {
|
.remodal-overlay {
|
||||||
opacity: 0;
|
background: rgba(43, 46, 56, 0.9);
|
||||||
background: rgba(33, 36, 46, 0.8);
|
|
||||||
@include transition(opacity 0.2s linear);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
body.remodal_active .remodal-overlay {
|
.remodal-overlay.remodal-is-opening,
|
||||||
opacity: 1;
|
.remodal-overlay.remodal-is-closing {
|
||||||
|
animation-duration: 0.3s;
|
||||||
|
animation-fill-mode: forwards;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Modal dialog default theme styles */
|
.remodal-overlay.remodal-is-opening {
|
||||||
|
animation-name: remodal-overlay-opening-keyframes;
|
||||||
|
}
|
||||||
|
|
||||||
|
.remodal-overlay.remodal-is-closing {
|
||||||
|
animation-name: remodal-overlay-closing-keyframes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Default theme styles of the wrapper */
|
||||||
|
|
||||||
|
.remodal-wrapper {
|
||||||
|
padding: 10px 10px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Default theme styles of the modal dialog */
|
||||||
|
|
||||||
.remodal {
|
.remodal {
|
||||||
|
box-sizing: border-box;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
min-height: 100%;
|
margin-bottom: 10px;
|
||||||
padding-top: 2rem;
|
padding: 35px;
|
||||||
@include box-sizing(border-box);
|
|
||||||
font-size: 16px;
|
|
||||||
background: $content-bg;
|
|
||||||
background-clip: padding-box;
|
|
||||||
color: $content-fg;
|
|
||||||
box-shadow: 0 10px 20px rgba(0,0,0,0.5);
|
|
||||||
@include transform(scale(0.95));
|
|
||||||
@include transition-property (transform);
|
|
||||||
@include transition-duration(0.2s);
|
|
||||||
@include transition-timing-function(linear);
|
|
||||||
|
|
||||||
|
transform: translate3d(0, 0, 0);
|
||||||
|
|
||||||
|
color: #2b2e38;
|
||||||
|
background: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
body.remodal_active .remodal {
|
.remodal.remodal-is-opening,
|
||||||
@include transform(scale(1));
|
.remodal.remodal-is-closing {
|
||||||
|
animation-duration: 0.3s;
|
||||||
|
animation-fill-mode: forwards;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Modal dialog vertical align */
|
.remodal.remodal-is-opening {
|
||||||
.remodal, .remodal-overlay:after {
|
animation-name: remodal-opening-keyframes;
|
||||||
|
}
|
||||||
|
|
||||||
|
.remodal.remodal-is-closing {
|
||||||
|
animation-name: remodal-closing-keyframes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Vertical align of the modal dialog */
|
||||||
|
|
||||||
|
.remodal,
|
||||||
|
.remodal-wrapper:after {
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,42 +160,174 @@ body.remodal_active .remodal {
|
|||||||
|
|
||||||
.remodal-close {
|
.remodal-close {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 10px;
|
top: 0;
|
||||||
right: 10px;
|
left: 0;
|
||||||
color: $content-fg;
|
|
||||||
|
|
||||||
text-decoration: none;
|
|
||||||
text-align: center;
|
|
||||||
|
|
||||||
@include transition(background 0.2s linear);
|
|
||||||
}
|
|
||||||
|
|
||||||
.remodal-close:after {
|
|
||||||
display: block;
|
display: block;
|
||||||
font-family: FontAwesome;
|
overflow: visible;
|
||||||
content: "\f00d";
|
|
||||||
|
width: 35px;
|
||||||
|
height: 35px;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
font-size: 28px;
|
|
||||||
line-height: 28px;
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
transition: color 0.2s;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
|
||||||
|
color: #95979c;
|
||||||
|
border: 0;
|
||||||
|
outline: 0;
|
||||||
|
background: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
.remodal-close:hover, .remodal-close:active {
|
.remodal-close:hover,
|
||||||
color: darken($content-fg, 20%);
|
.remodal-close:focus {
|
||||||
|
color: #2b2e38;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.remodal-close:before {
|
||||||
|
font-family: Arial, "Helvetica CY", "Nimbus Sans L", sans-serif !important;
|
||||||
|
font-size: 25px;
|
||||||
|
line-height: 35px;
|
||||||
|
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
|
||||||
|
display: block;
|
||||||
|
|
||||||
|
width: 35px;
|
||||||
|
|
||||||
|
content: "\00d7";
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dialog buttons */
|
||||||
|
|
||||||
|
/*.remodal-confirm,
|
||||||
|
.remodal-cancel {
|
||||||
|
font: inherit;
|
||||||
|
|
||||||
|
display: inline-block;
|
||||||
|
overflow: visible;
|
||||||
|
|
||||||
|
min-width: 110px;
|
||||||
|
margin: 0;
|
||||||
|
padding: 12px 0;
|
||||||
|
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background 0.2s;
|
||||||
|
text-align: center;
|
||||||
|
vertical-align: middle;
|
||||||
|
text-decoration: none;
|
||||||
|
|
||||||
|
border: 0;
|
||||||
|
outline: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.remodal-confirm {
|
||||||
|
color: #fff;
|
||||||
|
background: #81c784;
|
||||||
|
}
|
||||||
|
|
||||||
|
.remodal-confirm:hover,
|
||||||
|
.remodal-confirm:focus {
|
||||||
|
background: #66bb6a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.remodal-cancel {
|
||||||
|
color: #fff;
|
||||||
|
background: #e57373;
|
||||||
|
}
|
||||||
|
|
||||||
|
.remodal-cancel:hover,
|
||||||
|
.remodal-cancel:focus {
|
||||||
|
background: #ef5350;
|
||||||
|
}
|
||||||
|
|
||||||
|
!* Remove inner padding and border in Firefox 4+ for the button tag. *!
|
||||||
|
|
||||||
|
.remodal-confirm::-moz-focus-inner,
|
||||||
|
.remodal-cancel::-moz-focus-inner,
|
||||||
|
.remodal-close::-moz-focus-inner {
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
|
border: 0;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
/* Keyframes
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
@keyframes remodal-opening-keyframes {
|
||||||
|
from {
|
||||||
|
transform: scale(1.05);
|
||||||
|
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
transform: none;
|
||||||
|
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes remodal-closing-keyframes {
|
||||||
|
from {
|
||||||
|
transform: scale(1);
|
||||||
|
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
transform: scale(0.95);
|
||||||
|
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes remodal-overlay-opening-keyframes {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes remodal-overlay-closing-keyframes {
|
||||||
|
from {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Media queries
|
/* Media queries
|
||||||
========================================================================== */
|
========================================================================== */
|
||||||
|
|
||||||
@media only screen and (min-width: 40.063em) /* min-width 641px */ {
|
@media only screen and (min-width: 641px) {
|
||||||
.remodal {
|
.remodal {
|
||||||
max-width: 700px;
|
max-width: 700px;
|
||||||
margin: 20px auto;
|
|
||||||
min-height: 0;
|
|
||||||
border-radius: 6px;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* IE8
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
.lt-ie9 .remodal-overlay {
|
||||||
|
background: #2b2e38;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lt-ie9 .remodal {
|
||||||
|
width: 700px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/********* GRAV CUSTOM ********/
|
||||||
|
|
||||||
|
.remodal {
|
||||||
|
padding: 35px 0 0;
|
||||||
|
text-align: left;
|
||||||
|
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.3);
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|||||||
@@ -15,8 +15,8 @@
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block javascripts %}
|
{% block javascripts %}
|
||||||
{% do assets.addJs(theme_url~'/js/codemirror-compressed.js') %}
|
{#{% do assets.addJs(theme_url~'/js/codemirror-compressed.js') %}
|
||||||
{% do assets.addJs(theme_url~'/js/mdeditor.js') %}
|
{% do assets.addJs(theme_url~'/js/mdeditor.js') %}#}
|
||||||
{{ parent() }}
|
{{ parent() }}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
@@ -69,5 +69,19 @@
|
|||||||
{% else %}
|
{% else %}
|
||||||
{% include 'partials/blueprints.html.twig' with { blueprints: data.blueprints, data: data } %}
|
{% include 'partials/blueprints.html.twig' with { blueprints: data.blueprints, data: data } %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
<div class="remodal" data-remodal-id="changes">
|
||||||
|
<form>
|
||||||
|
<h1>{{ "PLUGIN_ADMIN.MODAL_CHANGED_DETECTED_TITLE"|tu }}</h1>
|
||||||
|
<p class="bigger">
|
||||||
|
{{ "PLUGIN_ADMIN.MODAL_CHANGED_DETECTED_DESC"|tu }}
|
||||||
|
</p>
|
||||||
|
<br>
|
||||||
|
<div class="button-bar">
|
||||||
|
<a class="button secondary" data-leave-action="cancel" href="#"><i class="fa fa-fw fa-close"></i> {{ "PLUGIN_ADMIN.CANCEL"|tu }}</a>
|
||||||
|
<a class="button" data-leave-action="continue" href="#"><i class="fa fa-fw fa-check"></i> {{ "PLUGIN_ADMIN.CONTINUE"|tu }}</a>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
|||||||
@@ -6,15 +6,15 @@
|
|||||||
<div class="button-bar">
|
<div class="button-bar">
|
||||||
{% if authorize(['admin.maintenance', 'admin.super']) %}
|
{% if authorize(['admin.maintenance', 'admin.super']) %}
|
||||||
<div class="button-group">
|
<div class="button-group">
|
||||||
<button data-clear-cache="{{ uri.addNonce(base_url_relative ~ '/cache.json/task' ~ config.system.param_sep ~ 'clearCache', 'admin-form', 'admin-nonce') }}" class="button"><i class="fa fa-trash"></i> {{ "PLUGIN_ADMIN.CLEAR_CACHE"|tu }}</button>
|
<button data-clear-cache-type="" data-clear-cache="{{ uri.addNonce(base_url_relative ~ '/cache.json/task' ~ config.system.param_sep ~ 'clearCache', 'admin-form', 'admin-nonce') }}" class="button"><i class="fa fa-trash"></i> {{ "PLUGIN_ADMIN.CLEAR_CACHE"|tu }}</button>
|
||||||
<button type="button" class="button dropdown-toggle" data-toggle="dropdown">
|
<button type="button" class="button dropdown-toggle" data-toggle="dropdown">
|
||||||
<i class="fa fa-caret-down"></i>
|
<i class="fa fa-caret-down"></i>
|
||||||
</button>
|
</button>
|
||||||
<ul class="dropdown-menu">
|
<ul class="dropdown-menu">
|
||||||
<li><a data-clear-cache="{{ uri.addNonce(base_url_relative ~ '/cache.json/task' ~ config.system.param_sep ~ 'clearCache/cleartype' ~ config.system.param_sep ~ 'all', 'admin-form', 'admin-nonce') }}" href="#">{{ "PLUGIN_ADMIN.CLEAR_CACHE_ALL_CACHE"|tu }}</a></li>
|
<li><a data-clear-cache-type="all" data-clear-cache="{{ uri.addNonce(base_url_relative ~ '/cache.json/task' ~ config.system.param_sep ~ 'clearCache/cleartype' ~ config.system.param_sep ~ 'all', 'admin-form', 'admin-nonce') }}" href="#">{{ "PLUGIN_ADMIN.CLEAR_CACHE_ALL_CACHE"|tu }}</a></li>
|
||||||
<li><a data-clear-cache="{{ uri.addNonce(base_url_relative ~ '/cache.json/task' ~ config.system.param_sep ~ 'clearCache/cleartype' ~ config.system.param_sep ~ 'assets-only', 'admin-form', 'admin-nonce') }}" href="#">{{ "PLUGIN_ADMIN.CLEAR_CACHE_ASSETS_ONLY"|tu }}</a></li>
|
<li><a data-clear-cache-type="assets-only" data-clear-cache="{{ uri.addNonce(base_url_relative ~ '/cache.json/task' ~ config.system.param_sep ~ 'clearCache/cleartype' ~ config.system.param_sep ~ 'assets-only', 'admin-form', 'admin-nonce') }}" href="#">{{ "PLUGIN_ADMIN.CLEAR_CACHE_ASSETS_ONLY"|tu }}</a></li>
|
||||||
<li><a data-clear-cache="{{ uri.addNonce(base_url_relative ~ '/cache.json/task' ~ config.system.param_sep ~ 'clearCache/cleartype' ~ config.system.param_sep ~ 'images-only', 'admin-form', 'admin-nonce') }}" href="#">{{ "PLUGIN_ADMIN.CLEAR_CACHE_IMAGES_ONLY"|tu }}</a></li>
|
<li><a data-clear-cache-type="images-only" data-clear-cache="{{ uri.addNonce(base_url_relative ~ '/cache.json/task' ~ config.system.param_sep ~ 'clearCache/cleartype' ~ config.system.param_sep ~ 'images-only', 'admin-form', 'admin-nonce') }}" href="#">{{ "PLUGIN_ADMIN.CLEAR_CACHE_IMAGES_ONLY"|tu }}</a></li>
|
||||||
<li><a data-clear-cache="{{ uri.addNonce(base_url_relative ~ '/cache.json/task' ~ config.system.param_sep ~ 'clearCache/cleartype' ~ config.system.param_sep ~ 'cache-only', 'admin-form', 'admin-nonce') }}" href="#">{{ "PLUGIN_ADMIN.CLEAR_CACHE_CACHE_ONLY"|tu }}</a></li>
|
<li><a data-clear-cache-type="cache-only" data-clear-cache="{{ uri.addNonce(base_url_relative ~ '/cache.json/task' ~ config.system.param_sep ~ 'clearCache/cleartype' ~ config.system.param_sep ~ 'cache-only', 'admin-form', 'admin-nonce') }}" href="#">{{ "PLUGIN_ADMIN.CLEAR_CACHE_CACHE_ONLY"|tu }}</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
{% set originalValue = originalValue is defined ? originalValue : value %}
|
{% set originalValue = originalValue is defined ? originalValue : value %}
|
||||||
|
{% set toggleableChecked = field.toggleable and (originalValue is not null and originalValue is not empty) %}
|
||||||
|
{% set isDisabledToggleable = field.toggleable and not toggleableChecked %}
|
||||||
{% set value = (value is null ? field.default : value) %}
|
{% set value = (value is null ? field.default : value) %}
|
||||||
{% set vertical = field.style == 'vertical' %}
|
{% set vertical = field.style == 'vertical' %}
|
||||||
|
|
||||||
@@ -7,21 +9,21 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% block field %}
|
{% block field %}
|
||||||
<div class="form-field grid{% if vertical %} vertical{% endif %}">
|
<div class="form-field grid{% if vertical %} vertical{% endif %}{% if field.toggleable %} form-field-toggleable{% endif %}">
|
||||||
{% block contents %}
|
{% block contents %}
|
||||||
<div class="form-label{% if not vertical %} block size-1-3{% endif %}">
|
<div class="form-label{% if not vertical %} block size-1-3{% endif %}">
|
||||||
{% if field.toggleable %}
|
{% if field.toggleable %}
|
||||||
<span class="checkboxes toggleable" data-grav-field="toggleable" data-grav-field-name="{{ field.name|fieldName }}">
|
<span class="checkboxes toggleable" data-grav-field="toggleable" data-grav-field-name="{{ field.name|fieldName }}">
|
||||||
<input type="checkbox"
|
<input type="checkbox"
|
||||||
id="toggleable_{{ field.name }}"
|
id="toggleable_{{ field.name }}"
|
||||||
{% if originalValue is not null and originalValue is not empty %}value="1"{% endif %}
|
{% if toggleableChecked %}value="1"{% endif %}
|
||||||
name="toggleable_{{ (scope ~ field.name)|fieldName }}"
|
name="toggleable_{{ (scope ~ field.name)|fieldName }}"
|
||||||
{% if originalValue is not null and originalValue is not empty %}checked="checked"{% endif %}
|
{% if toggleableChecked %}checked="checked"{% endif %}
|
||||||
>
|
>
|
||||||
<label for="toggleable_{{ field.name }}"></label>
|
<label for="toggleable_{{ field.name }}"></label>
|
||||||
</span>
|
</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<label class="{{ field.toggleable ? 'toggleable' : '' }}">
|
<label class="{{ field.toggleable ? 'toggleable' : '' }}"{{ field.toggleable ? 'for="toggleable_' ~ field.name ~'"' : ''}}>
|
||||||
{% block label %}
|
{% block label %}
|
||||||
{% if field.help %}
|
{% if field.help %}
|
||||||
<span class="hint--bottom" data-hint="{{ field.help|e|tu }}">{{ field.label|tu }}</span>
|
<span class="hint--bottom" data-hint="{{ field.help|e|tu }}">{{ field.label|tu }}</span>
|
||||||
@@ -35,7 +37,7 @@
|
|||||||
<div class="form-data{% if not vertical %} block size-2-3{% endif %}"
|
<div class="form-data{% if not vertical %} block size-2-3{% endif %}"
|
||||||
{% block global_attributes %}
|
{% block global_attributes %}
|
||||||
data-grav-field="{{ field.type }}"
|
data-grav-field="{{ field.type }}"
|
||||||
data-grav-disabled="{{ originalValue is null ? 'true' : 'false' }}"
|
data-grav-disabled="{{ toggleableChecked }}"
|
||||||
data-grav-default="{{ field.default|json_encode()|e('html_attr') }}"
|
data-grav-default="{{ field.default|json_encode()|e('html_attr') }}"
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
>
|
>
|
||||||
@@ -51,7 +53,7 @@
|
|||||||
{% if field.classes is defined %}class="{{ field.classes }}" {% endif %}
|
{% if field.classes is defined %}class="{{ field.classes }}" {% endif %}
|
||||||
{% if field.id is defined %}id="{{ field.id|e }}" {% endif %}
|
{% if field.id is defined %}id="{{ field.id|e }}" {% endif %}
|
||||||
{% if field.style is defined %}style="{{ field.style|e }}" {% endif %}
|
{% if field.style is defined %}style="{{ field.style|e }}" {% endif %}
|
||||||
{% if field.disabled %}disabled="disabled"{% endif %}
|
{% if field.disabled or isDisabledToggleable %}disabled="disabled"{% endif %}
|
||||||
{% if field.placeholder %}placeholder="{{ field.placeholder|tu }}"{% endif %}
|
{% if field.placeholder %}placeholder="{{ field.placeholder|tu }}"{% endif %}
|
||||||
{% if field.autofocus in ['on', 'true', 1] %}autofocus="autofocus"{% endif %}
|
{% if field.autofocus in ['on', 'true', 1] %}autofocus="autofocus"{% endif %}
|
||||||
{% if field.novalidate in ['on', 'true', 1] %}novalidate="novalidate"{% endif %}
|
{% if field.novalidate in ['on', 'true', 1] %}novalidate="novalidate"{% endif %}
|
||||||
|
|||||||
@@ -7,55 +7,62 @@
|
|||||||
{{ parent() }}
|
{{ parent() }}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block input %}
|
{% macro renderer(key, text, field) %}
|
||||||
<div data-grav-array-type="container"{% if field.value_only %} data-grav-array-mode="value_only"{% endif %}>
|
<div class="form-row{% if field.value_only %} array-field-value_only{% endif %}"
|
||||||
{% if value|length %}
|
data-grav-array-type="row">
|
||||||
{% for key, text in value -%}
|
|
||||||
<div class="form-row{% if field.value_only %} array-field-value_only{% endif %}" data-grav-array-type="row">
|
|
||||||
|
|
||||||
{% if text is iterable %}
|
|
||||||
<div class="grid" style="display: flex">
|
|
||||||
<div class="block size-1-4">
|
|
||||||
<input data-grav-array-type="keyArray" type="text" value="{{ key }}" placeholder="{{ field.placeholder_key|e|tu }}" style="float: none; width: 90%" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="block size-3-4">
|
|
||||||
{% for subkey, subtext in text -%}
|
|
||||||
<div class="form-row" data-grav-array-type="subrow">
|
|
||||||
<input data-grav-array-type="keyArraySubelement" type="text" value="{{ subkey }}" />
|
|
||||||
<input data-grav-array-type="value" type="text" subkey="{{ subkey }}" name="{{ (field.name|fieldName) ~ '[' ~ key ~ '][' ~ subkey ~ ']' }}" value="{{ subtext|join(', ')|e }}" />
|
|
||||||
|
|
||||||
<span data-grav-array-action="remArrayItem" class="fa fa-minus-square"></span>
|
|
||||||
<span data-grav-array-action="addArrayItem" class="fa fa-plus-square"></span>
|
|
||||||
</div>
|
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
<div class="form-row{% if field.value_only %} array-field-value_only{% endif %}" data-grav-array-type="subrow">
|
|
||||||
<span data-grav-array-action="rem" class="fa fa-minus"></span>
|
|
||||||
<span data-grav-array-action="add" class="fa fa-plus"></span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% else %}
|
|
||||||
{% if field.value_only != true %}
|
{% if field.value_only != true %}
|
||||||
{% if key == '0' and text == '' %}
|
{% if key == '0' and text == '' %}
|
||||||
{% set key = '' %}
|
{% set key = '' %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<input data-grav-array-type="key" type="text" value="{{ key }}" placeholder="{{ field.placeholder_key|e|tu }}" />
|
<input
|
||||||
|
data-grav-array-type="key"
|
||||||
|
type="text" value="{{ key }}"
|
||||||
|
{% if field.disabled or isDisabledToggleable %}disabled="disabled"{% endif %}
|
||||||
|
placeholder="{{ field.placeholder_key|e|tu }}" />
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<input data-grav-array-type="value" type="text" name="{{ (field.name|fieldName) ~ '[' ~ key ~ ']' }}" value={% if text == 'true' %}true{% elseif text == 'false' %}false{% else %}"{{ text|join(', ')|e }}"{% endif %} placeholder="{{ field.placeholder_value|e|tu }}" />
|
<input
|
||||||
|
data-grav-array-type="value"
|
||||||
|
type="text"
|
||||||
|
name="{{ (field.name|fieldName) ~ '[' ~ key ~ ']' }}"
|
||||||
|
placeholder="{{ field.placeholder_value|e|tu }}"
|
||||||
|
{% if field.disabled or isDisabledToggleable %}disabled="disabled"{% endif %}
|
||||||
|
value={% if text == 'true' %}true{% elseif text == 'false' %}false{% else %}"{{ text|join(', ')|e }}"{% endif %} />
|
||||||
|
|
||||||
<span data-grav-array-action="rem" class="fa fa-minus"></span>
|
<span data-grav-array-action="rem" class="fa fa-minus"></span>
|
||||||
<span data-grav-array-action="add" class="fa fa-plus"></span>
|
<span data-grav-array-action="add" class="fa fa-plus"></span>
|
||||||
{% endif %}
|
|
||||||
</div>
|
</div>
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
{% block input %}
|
||||||
|
{% import _self as array_field %}
|
||||||
|
<div data-grav-array-type="container"{% if field.value_only %} data-grav-array-mode="value_only"{% endif %}>
|
||||||
|
{% if value|length %}
|
||||||
|
{% for key, text in value -%}
|
||||||
|
{% if text is not iterable %}
|
||||||
|
{{ array_field.renderer(key, text, field) }}
|
||||||
|
{% else %}
|
||||||
|
{# Backward compatibility for nested arrays (metas) which are not supported anymore #}
|
||||||
|
{% for subkey, subtext in text -%}
|
||||||
|
{{ array_field.renderer(key ~ ':' ~ subkey, subtext, field) }}
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{%- else -%}
|
{%- else -%}
|
||||||
|
{# Empty value, mock the entry field#}
|
||||||
<div class="form-row" data-grav-array-type="row">
|
<div class="form-row" data-grav-array-type="row">
|
||||||
<input data-grav-array-type="key" type="text" placeholder="{{ field.placeholder_key|e|tu }}" />
|
<input
|
||||||
<input data-grav-array-type="value" type="text" placeholder="{{ field.placeholder_value|e|tu }}" />
|
data-grav-array-type="key"
|
||||||
|
type="text"
|
||||||
|
{% if field.disabled or isDisabledToggleable %}disabled="disabled"{% endif %}
|
||||||
|
placeholder="{{ field.placeholder_key|e|tu }}" />
|
||||||
|
<input
|
||||||
|
data-grav-array-type="value"
|
||||||
|
type="text"
|
||||||
|
name="{{ field.name|fieldName }}"
|
||||||
|
{% if field.disabled or isDisabledToggleable %}disabled="disabled"{% endif %}
|
||||||
|
placeholder="{{ field.placeholder_value|e|tu }}" />
|
||||||
<span data-grav-array-action="rem" class="fa fa-minus"></span>
|
<span data-grav-array-action="rem" class="fa fa-minus"></span>
|
||||||
<span data-grav-array-action="add" class="fa fa-plus"></span>
|
<span data-grav-array-action="add" class="fa fa-plus"></span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1 +1,8 @@
|
|||||||
<input data-grav-field="hidden" data-grav-disabled="false" type="hidden" class="input" name="{{ (scope ~ field.name)|fieldName }}" value="{{ blueprints.name }}" />
|
<input
|
||||||
|
data-grav-field="hidden"
|
||||||
|
data-grav-disabled="false"
|
||||||
|
type="hidden"
|
||||||
|
class="input"
|
||||||
|
{% if field.disabled or isDisabledToggleable %}disabled="disabled"{% endif %}
|
||||||
|
name="{{ (scope ~ field.name)|fieldName }}"
|
||||||
|
value="{{ blueprints.name }}" />
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
{% if field.novalidate in ['on', 'true', 1] %}novalidate="novalidate"{% endif %}
|
{% if field.novalidate in ['on', 'true', 1] %}novalidate="novalidate"{% endif %}
|
||||||
{% if field.validate.required in ['on', 'true', 1] %}required="required"{% endif %}
|
{% if field.validate.required in ['on', 'true', 1] %}required="required"{% endif %}
|
||||||
{% if field.multiple in ['on', 'true', 1] %}multiple="multiple"{% endif %}
|
{% if field.multiple in ['on', 'true', 1] %}multiple="multiple"{% endif %}
|
||||||
|
{% if field.disabled or isDisabledToggleable %}disabled="disabled"{% endif %}
|
||||||
{% if field.form %}form="{{ field.form }}"{% endif %}
|
{% if field.form %}form="{{ field.form }}"{% endif %}
|
||||||
>
|
>
|
||||||
{% for key, text in field.options %}
|
{% for key, text in field.options %}
|
||||||
|
|||||||
@@ -27,6 +27,7 @@
|
|||||||
{% block input_attributes %}
|
{% block input_attributes %}
|
||||||
type="file"
|
type="file"
|
||||||
{% if files.accept %}accept="{{ files.accept|join(',') }}"{% endif %}
|
{% if files.accept %}accept="{{ files.accept|join(',') }}"{% endif %}
|
||||||
|
{% if field.disabled or isDisabledToggleable %}disabled="disabled"{% endif %}
|
||||||
{{ parent() }}
|
{{ parent() }}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -13,7 +13,10 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="form-data">
|
<div class="form-data">
|
||||||
<div class="form-frontmatter-wrapper {{ field.size }}">
|
<div class="form-frontmatter-wrapper {{ field.size }}">
|
||||||
<textarea name="{{ (scope ~ field.name)|fieldName }}" id="frontmatter">{{ value|join("\n") }}</textarea>
|
<textarea
|
||||||
|
{% if field.disabled or isDisabledToggleable %}disabled="disabled"{% endif %}
|
||||||
|
name="{{ (scope ~ field.name)|fieldName }}"
|
||||||
|
id="frontmatter">{{ value|join("\n") }}</textarea>
|
||||||
<div class="dragbar"></div>
|
<div class="dragbar"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
{% set value = (value is null ? field.default : value) %}
|
{% set value = (value is null ? field.default : value) %}
|
||||||
{% set name = scope ~ field.name %}
|
{% set name = scope ~ field.name %}
|
||||||
{% set array = field.array is defined ? field.array : true %}
|
|
||||||
{% set lastKey = null %}
|
|
||||||
|
|
||||||
<div class="form-field grid pure-g">
|
<div class="form-field grid pure-g BLABLA">
|
||||||
<div class="form-label block size-1-4 pure-u-1-4">
|
<div class="form-label block size-1-4 pure-u-1-4">
|
||||||
<label>
|
<label>
|
||||||
{% if field.help %}
|
{% if field.help %}
|
||||||
@@ -19,12 +17,6 @@
|
|||||||
<ul data-collection-holder="{{ name }}">
|
<ul data-collection-holder="{{ name }}">
|
||||||
{% if field.fields %}
|
{% if field.fields %}
|
||||||
{% for key, val in value %}
|
{% for key, val in value %}
|
||||||
{% if array and (key matches '/^\\d+$/') == 0 %}
|
|
||||||
{% set array = false %}
|
|
||||||
{% set lastKey = -1 %}
|
|
||||||
{% elseif array %}
|
|
||||||
{% set lastKey = key %}
|
|
||||||
{% endif %}
|
|
||||||
{% set itemName = name ~ '.' ~ key %}
|
{% set itemName = name ~ '.' ~ key %}
|
||||||
<li data-collection-item="{{ itemName }}" data-collection-key="{{ key }}">
|
<li data-collection-item="{{ itemName }}" data-collection-key="{{ key }}">
|
||||||
{% for childName, child in field.fields %}
|
{% for childName, child in field.fields %}
|
||||||
@@ -63,48 +55,47 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</ul>
|
</ul>
|
||||||
<div class="collection-actions">
|
<div class="collection-actions">
|
||||||
{% set lastKey = lastKey + 1 %}
|
<button class="button" type="button" data-action="add"><i class="fa fa-plus"></i> Add item</button>
|
||||||
<button class="button" type="button" data-action="add" data-key-index="{{ lastKey }}"><i class="fa fa-plus"></i> Add item</button>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script type="text/html" data-collection-template="new">
|
<div style="display: none;" data-collection-template="new" data-collection-template-html="{%- filter replace({' ': ' ', '\n': ' '})|e('html_attr') -%}
|
||||||
<li data-collection-item="{{ name ~ '.*' }}">
|
<li data-collection-item="{{ name ~ '.*' }}">
|
||||||
{% if field.fields %}
|
{%- if field.fields -%}
|
||||||
{% set itemName = name ~ '.*' %}
|
{%- set itemName = name ~ '.*' -%}
|
||||||
{% for childName, child in field.fields %}
|
{%- for childName, child in field.fields -%}
|
||||||
{% if childName starts with '.' %}
|
{%- if childName starts with '.' -%}
|
||||||
{% set childKey = childName|trim('.') %}
|
{%- set childKey = childName|trim('.') -%}
|
||||||
{% set childName = itemName ~ childName %}
|
{%- set childName = itemName ~ childName -%}
|
||||||
{% else %}
|
{%- else %}
|
||||||
{% set childKey = childName %}
|
{%- set childKey = childName -%}
|
||||||
{% set childName = childName|replace({'*': key}) %}
|
{%- set childName = childName|replace({'*': key}) -%}
|
||||||
{% endif %}
|
{%- endif %}
|
||||||
{% set child = child|merge({ name: childName }) %}
|
{%- set child = child|merge({ name: childName }) -%}
|
||||||
|
|
||||||
{% if child.type == 'key' %}
|
{%- if child.type == 'key' -%}
|
||||||
{%
|
{%-
|
||||||
include 'forms/fields/text/text.html.twig'
|
include 'forms/fields/text/text.html.twig'
|
||||||
with { field: child, value: null }
|
with { field: child, value: null }
|
||||||
%}
|
-%}
|
||||||
{% elseif child.type %}
|
{%- elseif child.type -%}
|
||||||
{%
|
{%-
|
||||||
include [
|
include [
|
||||||
"forms/fields/#{child.type}/#{child.type}.html.twig",
|
"forms/fields/#{child.type}/#{child.type}.html.twig",
|
||||||
'forms/fields/text/text.html.twig'
|
'forms/fields/text/text.html.twig'
|
||||||
] with { field: child, value: null }
|
] with { field: child, value: null }
|
||||||
%}
|
-%}
|
||||||
{% endif %}
|
{%- endif -%}
|
||||||
{% endfor %}
|
{%- endfor %}
|
||||||
<div class="item-actions">
|
<div class="item-actions">
|
||||||
<i class="fa fa-bars"></i>
|
<i class="fa fa-bars"></i>
|
||||||
<br />
|
<br />
|
||||||
<i class="fa fa-trash-o" data-action="delete"></i>
|
<i class="fa fa-trash-o" data-action="delete"></i>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{%- endif -%}
|
||||||
</li>
|
</li>
|
||||||
</script>
|
{%- endfilter -%}"></div>
|
||||||
|
|
||||||
<div style="display: none;" data-collection-config="{{ name }}" data-collection-array="{{ array ? 'true' : 'false' }}"></div>
|
<div style="display: none;" data-collection-config="{{ name }}"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -9,7 +9,12 @@
|
|||||||
{% block field %}
|
{% block field %}
|
||||||
<div class="form-field">
|
<div class="form-field">
|
||||||
<div class="form-data form-markdown-wrapper cm-s-paper">
|
<div class="form-data form-markdown-wrapper cm-s-paper">
|
||||||
<textarea data-grav-mdeditor="{{ { 'markdown': true }|json_encode|e('html_attr') }}" name="{{ (scope ~ field.name)|fieldName }}" {% if field.showPreview %}data-grav-preview-enabled="true"{% endif %} data-grav-urlpreview="{{ base_url }}/media/{{ admin.route|trim('/') }}.json">{{ value|join("\n")|e('html') }}</textarea>
|
<textarea
|
||||||
|
data-grav-mdeditor="{{ { 'markdown': true }|json_encode|e('html_attr') }}"
|
||||||
|
name="{{ (scope ~ field.name)|fieldName }}"
|
||||||
|
{% if field.disabled or isDisabledToggleable %}disabled="disabled"{% endif %}
|
||||||
|
{% if field.showPreview %}data-grav-preview-enabled="true"{% endif %}
|
||||||
|
data-grav-urlpreview="{{ base_url }}/media/{{ admin.route|trim('/') }}.json">{{ value|join("\n")|e('html') }}</textarea>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -15,7 +15,12 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="form-data block size-2-3 pure-u-2-3">
|
<div class="form-data block size-2-3 pure-u-2-3">
|
||||||
<div class="form-order-wrapper {{ field.size }}">
|
<div class="form-order-wrapper {{ field.size }}">
|
||||||
<input type="hidden" data-order name="{{ (scope ~ field.name)|fieldName }}" value="{{ value }}" />
|
<input
|
||||||
|
type="hidden"
|
||||||
|
data-order
|
||||||
|
{% if field.disabled or isDisabledToggleable %}disabled="disabled"{% endif %}
|
||||||
|
name="{{ (scope ~ field.name)|fieldName }}"
|
||||||
|
value="{{ value }}" />
|
||||||
{% if data.parent.header.content.items %}
|
{% if data.parent.header.content.items %}
|
||||||
<span class="note">Parent setting order, ordering disabled</span>
|
<span class="note">Parent setting order, ordering disabled</span>
|
||||||
{% elseif not data.visible %}
|
{% elseif not data.visible %}
|
||||||
@@ -33,17 +38,4 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script>
|
|
||||||
jQuery(function(){
|
|
||||||
var el = jQuery('#ordering');
|
|
||||||
new Sortable(el[0], {
|
|
||||||
filter: ".ignore",
|
|
||||||
onUpdate: function(evt){
|
|
||||||
var index = el.children().index(jQuery(evt.item)) + 1;
|
|
||||||
jQuery('[data-order]').val(index);
|
|
||||||
}
|
|
||||||
// draggable: ".drag-handle"
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -4,158 +4,8 @@
|
|||||||
<div class="form-field">
|
<div class="form-field">
|
||||||
<div class="form-data form-uploads-wrapper">
|
<div class="form-data form-uploads-wrapper">
|
||||||
<h3>{{ field.label|tu }}</h3>
|
<h3>{{ field.label|tu }}</h3>
|
||||||
<div id="gravDropzone" class="dropzone"></div>
|
<div id="grav-dropzone" class="dropzone"></div>
|
||||||
<span>{{ value|join("\n") }}</span>
|
<span>{{ value|join("\n") }}</span>
|
||||||
<script>
|
|
||||||
$(function(){
|
|
||||||
var URI = $('[data-media-url]').data('media-url'), thisDropzone,
|
|
||||||
modalError = function(args){
|
|
||||||
if (args.data.status == 'error' || args.data.status == 'unauthorized'){
|
|
||||||
|
|
||||||
if (args.mode == 'addBack'){
|
|
||||||
// let's add back the file
|
|
||||||
if (args.file instanceof File) this.addFile(args.file);
|
|
||||||
else {
|
|
||||||
this.files.push(args.file);
|
|
||||||
this.options.addedfile.call(this, args.file);
|
|
||||||
this.options.thumbnail.call(this, args.file, args.file.extras.url);
|
|
||||||
}
|
|
||||||
} else if (args.mode == 'removeFile') {
|
|
||||||
args.file.rejected = true;
|
|
||||||
this.removeFile(args.file);
|
|
||||||
}
|
|
||||||
|
|
||||||
// fire up the modal
|
|
||||||
var modalContainer = $('[data-remodal-id=generic]');
|
|
||||||
modalContainer.find('.error-content').html(args.msg);
|
|
||||||
$.remodal.lookup[modalContainer.data('remodal')].open();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Dropzone.autoDiscover = false;
|
|
||||||
Dropzone.confirm = function(question, accepted, rejected) {
|
|
||||||
var modalContainer = $('[data-remodal-id=delete-media]'),
|
|
||||||
acceptHandler = function () {
|
|
||||||
if (accepted) {
|
|
||||||
accepted();
|
|
||||||
}
|
|
||||||
$(document).off('confirm', '[data-remodal-id=delete-media]', acceptHandler);
|
|
||||||
$(document).off('cancel', '[data-remodal-id=delete-media]', rejectHandler);
|
|
||||||
},
|
|
||||||
rejectHandler = function () {
|
|
||||||
if (rejected) {
|
|
||||||
rejected();
|
|
||||||
}
|
|
||||||
$(document).off('confirm', '[data-remodal-id=delete-media]', acceptHandler);
|
|
||||||
$(document).off('cancel', '[data-remodal-id=delete-media]', rejectHandler);
|
|
||||||
};
|
|
||||||
|
|
||||||
$.remodal.lookup[modalContainer.data('remodal')].open();
|
|
||||||
$(document).on('confirm', '[data-remodal-id=delete-media]', acceptHandler);
|
|
||||||
$(document).on('cancel', '[data-remodal-id=delete-media]', rejectHandler);
|
|
||||||
};
|
|
||||||
Dropzone.options.gravDropzone = {
|
|
||||||
addRemoveLinks: false,
|
|
||||||
dictRemoveFileConfirmation: '[placeholder]',
|
|
||||||
acceptedFiles: $('[data-media-types]').data('media-types'),
|
|
||||||
previewTemplate: "<div class=\"dz-preview dz-file-preview\">\n <div class=\"dz-details\">\n " +
|
|
||||||
"<div class=\"dz-filename\"><span data-dz-name></span></div>\n " +
|
|
||||||
"<div class=\"dz-size\" data-dz-size></div>\n <img data-dz-thumbnail />\n </div>\n " +
|
|
||||||
"<div class=\"dz-progress\"><span class=\"dz-upload\" data-dz-uploadprogress></span></div>\n "+
|
|
||||||
"<div class=\"dz-success-mark\"><span>✔</span></div>\n <div class=\"dz-error-mark\"><span>✘</span></div>\n " +
|
|
||||||
"<div class=\"dz-error-message\"><span data-dz-errormessage></span></div>\n" +
|
|
||||||
"<a class=\"dz-remove\" href=\"javascript:undefined;\" data-dz-remove>Delete</a>\n" +
|
|
||||||
"<a class=\"dz-insert\" href=\"javascript:undefined;\" data-dz-insert>Insert</a>\n</div>",
|
|
||||||
init: function() {
|
|
||||||
thisDropzone = this;
|
|
||||||
$.get(URI + '/task{{ config.system.param_sep }}listmedia/admin-nonce{{ config.system.param_sep }}' + GravAdmin.config.admin_nonce, function(data) {
|
|
||||||
|
|
||||||
$.proxy(modalError, this, {
|
|
||||||
data: data,
|
|
||||||
msg: '<p>An error occurred while trying to list files</p><pre>'+data.message+'</pre>'
|
|
||||||
})();
|
|
||||||
|
|
||||||
if (data.results) {
|
|
||||||
$.each(data.results, function(filename, data){
|
|
||||||
var mockFile = { name: filename, size: data.size, accepted: true, extras: data };
|
|
||||||
thisDropzone.files.push(mockFile);
|
|
||||||
thisDropzone.options.addedfile.call(thisDropzone, mockFile);
|
|
||||||
|
|
||||||
if (filename.toLowerCase().match(/\.(jpg|jpeg|png|gif)$/)) {
|
|
||||||
thisDropzone.options.thumbnail.call(thisDropzone, mockFile, data.url);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
$('.dz-preview').prop('draggable', 'true');
|
|
||||||
});
|
|
||||||
|
|
||||||
this.on("complete", function(file) {
|
|
||||||
if (file.accepted) {
|
|
||||||
$('.dz-preview').prop('draggable', 'true');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var data = {status: 'error', message: 'Unsupported file type: ' + file.name.match(/\..+/).join('')};
|
|
||||||
$.proxy(modalError, this, {
|
|
||||||
file: file,
|
|
||||||
data: data,
|
|
||||||
mode: 'removeFile',
|
|
||||||
msg: '<p>An error occurred while trying to add the file <strong>'+file.name+'</strong></p><pre>'+data.message+'</pre>'
|
|
||||||
})();
|
|
||||||
});
|
|
||||||
|
|
||||||
this.on('success', function(file, response){
|
|
||||||
thisDropzone = this;
|
|
||||||
$.proxy(modalError, this, {
|
|
||||||
file: file,
|
|
||||||
data: response,
|
|
||||||
mode: 'removeFile',
|
|
||||||
msg: '<p>An error occurred while trying to upload the file <strong>'+file.name+'</strong></p><pre>'+response.message+'</pre>'
|
|
||||||
})();
|
|
||||||
});
|
|
||||||
|
|
||||||
this.on('removedfile', function(file) {
|
|
||||||
if (!file.accepted || file.rejected) return;
|
|
||||||
thisDropzone = this;
|
|
||||||
$.post(URI + '/task{{ config.system.param_sep }}delmedia', {filename: file.name, 'admin-nonce': GravAdmin.config.admin_nonce}, function(data){
|
|
||||||
$.proxy(modalError, thisDropzone, {
|
|
||||||
file: file,
|
|
||||||
data: data,
|
|
||||||
mode: 'addBack',
|
|
||||||
msg: '<p>An error occurred while trying to remove the file <strong>'+file.name+'</strong></p><pre>'+data.message+'</pre>'
|
|
||||||
})();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
this.on('sending', function(file, xhr, formData){
|
|
||||||
formData.append('admin-nonce', GravAdmin.config.admin_nonce);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var dropzone = new Dropzone("#gravDropzone", { url: URI + '/task{{ config.system.param_sep }}addmedia', createImageThumbnails: { thumbnailWidth: 150} });
|
|
||||||
|
|
||||||
$("#gravDropzone").delegate('.dz-preview', 'dragstart', function(e){
|
|
||||||
var uri = encodeURI($(this).find('.dz-filename').text());
|
|
||||||
uri = uri.replace(/\(/g, '%28');
|
|
||||||
uri = uri.replace(/\)/g, '%29');
|
|
||||||
|
|
||||||
var shortcode = '';
|
|
||||||
if (!uri.match(/\.(jpg|jpeg|png|gif)$/)) {
|
|
||||||
shortcode = '[' + decodeURI(uri) + '](' + uri + ')';
|
|
||||||
}
|
|
||||||
|
|
||||||
dropzone.disable();
|
|
||||||
$(this).addClass('hide-backface');
|
|
||||||
e.originalEvent.dataTransfer.effectAllowed = 'copy';
|
|
||||||
e.originalEvent.dataTransfer.setData('text', shortcode);
|
|
||||||
});
|
|
||||||
|
|
||||||
$("#gravDropzone").delegate('.dz-preview', 'dragend', function(e){
|
|
||||||
dropzone.enable();
|
|
||||||
$(this).removeClass('hide-backface');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
{% if field.classes is defined %}class="{{ field.classes }}" {% endif %}
|
{% if field.classes is defined %}class="{{ field.classes }}" {% endif %}
|
||||||
{% if field.id is defined %}id="{{ field.id|e }}" {% endif %}
|
{% if field.id is defined %}id="{{ field.id|e }}" {% endif %}
|
||||||
{% if field.style is defined %}style="{{ field.style|e }}" {% endif %}
|
{% if field.style is defined %}style="{{ field.style|e }}" {% endif %}
|
||||||
{% if field.disabled or files is empty %}disabled="disabled"{% endif %}
|
{% if field.disabled or files is empty or isDisabledToggleable %}disabled="disabled"{% endif %}
|
||||||
{% if field.autofocus in ['on', 'true', 1] %}autofocus="autofocus"{% endif %}
|
{% if field.autofocus in ['on', 'true', 1] %}autofocus="autofocus"{% endif %}
|
||||||
{% if field.novalidate in ['on', 'true', 1] %}novalidate="novalidate"{% endif %}
|
{% if field.novalidate in ['on', 'true', 1] %}novalidate="novalidate"{% endif %}
|
||||||
{% if field.validate.required in ['on', 'true', 1] %}required="required"{% endif %}
|
{% if field.validate.required in ['on', 'true', 1] %}required="required"{% endif %}
|
||||||
|
|||||||
@@ -43,6 +43,7 @@
|
|||||||
{% if field.novalidate in ['on', 'true', 1] %}novalidate="novalidate"{% endif %}
|
{% if field.novalidate in ['on', 'true', 1] %}novalidate="novalidate"{% endif %}
|
||||||
{% if field.validate.required in ['on', 'true', 1] %}required="required"{% endif %}
|
{% if field.validate.required in ['on', 'true', 1] %}required="required"{% endif %}
|
||||||
{% if field.multiple in ['on', 'true', 1] %}multiple="multiple"{% endif %}
|
{% if field.multiple in ['on', 'true', 1] %}multiple="multiple"{% endif %}
|
||||||
|
{% if field.disabled or isDisabledToggleable %}disabled="disabled"{% endif %}
|
||||||
>
|
>
|
||||||
{{ _self.options(field,pages,value, 0) }}
|
{{ _self.options(field,pages,value, 0) }}
|
||||||
</select>
|
</select>
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if field.fields %}
|
{% if field.fields %}
|
||||||
{% for tab in field.fields %}<input type="radio" name="tab" id="tab{{ loop.index }}" class="tab-head" {{ active == loop.index ? 'checked="checked"' : '' }}/><label for="tab{{ loop.index }}">{% if grav.twig.twig.filters['tu'] is defined %}{{ tab.title|tu }}{% else %}{{ tab.title|t }}{% endif %}</label>{% endfor %}
|
{% for tab in field.fields %}<input type="radio" name="tab" id="tab{{ loop.index }}" class="tab-head no-form" {{ active == loop.index ? 'checked="checked"' : '' }}/><label for="tab{{ loop.index }}">{% if grav.twig.twig.filters['tu'] is defined %}{{ tab.title|tu }}{% else %}{{ tab.title|t }}{% endif %}</label>{% endfor %}
|
||||||
<div class="tab-body-wrapper">
|
<div class="tab-body-wrapper">
|
||||||
{% for field in field.fields %}
|
{% for field in field.fields %}
|
||||||
{% set value = data.value(field.name) %}
|
{% set value = data.value(field.name) %}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
{% if field.novalidate in ['on', 'true', 1] %}novalidate="novalidate"{% endif %}
|
{% if field.novalidate in ['on', 'true', 1] %}novalidate="novalidate"{% endif %}
|
||||||
{% if field.validate.required in ['on', 'true', 1] %}required="required"{% endif %}
|
{% if field.validate.required in ['on', 'true', 1] %}required="required"{% endif %}
|
||||||
{% if field.multiple in ['on', 'true', 1] %}multiple="multiple"{% endif %}
|
{% if field.multiple in ['on', 'true', 1] %}multiple="multiple"{% endif %}
|
||||||
>
|
{% if field.disabled or isDisabledToggleable %}disabled="disabled"{% endif %}>
|
||||||
{% for key, text in options %}
|
{% for key, text in options %}
|
||||||
<option {% if key == value or text in value %}selected="selected"{% endif %} value="{{ field.multiple ? text : key }}">{{ text }}</option>
|
<option {% if key == value or text in value %}selected="selected"{% endif %} value="{{ field.multiple ? text : key }}">{{ text }}</option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|||||||
@@ -39,6 +39,7 @@
|
|||||||
{% if field.highlight is defined %}
|
{% if field.highlight is defined %}
|
||||||
class="{{ field.highlight == '' ~ key ? 'highlight' : '' }}"
|
class="{{ field.highlight == '' ~ key ? 'highlight' : '' }}"
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if field.disabled or isDisabledToggleable %}disabled="disabled"{% endif %}
|
||||||
{% if field.toggleable %}
|
{% if field.toggleable %}
|
||||||
{% if '' ~ key == '' ~ value %}checked="checked" {% endif %}
|
{% if '' ~ key == '' ~ value %}checked="checked" {% endif %}
|
||||||
{% if value is defined and (key == 1 or key == '1') %}checked="checked" {% endif %}
|
{% if value is defined and (key == 1 or key == '1') %}checked="checked" {% endif %}
|
||||||
|
|||||||
@@ -40,14 +40,14 @@
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block javascripts %}
|
{% block javascripts %}
|
||||||
{% do assets.addJs(theme_url~'/js/pages-all.js') %}
|
{#{% do assets.addJs(theme_url~'/js/pages-all.js') %}
|
||||||
{% do assets.addJs(theme_url~'/js/speakingurl.min.js') %}
|
{% do assets.addJs(theme_url~'/js/speakingurl.min.js') %}
|
||||||
{% do assets.addJs(theme_url~'/js/slugify.min.js') %}
|
{% do assets.addJs(theme_url~'/js/slugify.min.js') %}
|
||||||
{% if mode == 'edit' %}
|
{% if mode == 'edit' %}
|
||||||
{% do assets.addJs(theme_url~'/js/codemirror-compressed.js') %}
|
{% do assets.addJs(theme_url~'/js/codemirror-compressed.js') %}
|
||||||
{% do assets.addJs(theme_url~'/js/mdeditor.js') %}
|
{% do assets.addJs(theme_url~'/js/mdeditor.js') %}
|
||||||
{% do assets.addJs(theme_url~'/js/dropzone.min.js') %}
|
{% do assets.addJs(theme_url~'/js/dropzone.min.js') %}
|
||||||
{% endif %}
|
{% endif %}#}
|
||||||
{{ parent() }}
|
{{ parent() }}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
@@ -260,7 +260,7 @@
|
|||||||
{% else %}
|
{% else %}
|
||||||
<form id="page-filtering">
|
<form id="page-filtering">
|
||||||
<div class="page-filters">
|
<div class="page-filters">
|
||||||
<input type="text" data-template-types="{{ admin.types|merge(admin.modularTypes)|json_encode|e('html_attr') }}" data-template-access-levels="{{ admin.accessLevels|json_encode|e('html_attr') }}" placeholder="{{ "PLUGIN_ADMIN.ADD_FILTERS"|tu }}" class="page-filter" name="page-filter" />
|
<input type="text" data-filter-labels="{{ [{'id': 'mode', 'name': 'PLUGIN_ADMIN.PAGE_MODES'|tu}, {'id': 'type', 'name': 'PLUGIN_ADMIN.PAGE_TYPES'|tu}, {'id': 'access', 'name': 'PLUGIN_ADMIN.PAGE_ACCESS_LEVELS'|tu}] |json_encode|e('html_attr')}}" data-filter-types="{{ admin.types|merge(admin.modularTypes)|json_encode|e('html_attr') }}" data-filter-access-levels="{{ admin.accessLevels|json_encode|e('html_attr') }}" placeholder="{{ "PLUGIN_ADMIN.ADD_FILTERS"|tu }}" class="page-filter" name="page-filter" />
|
||||||
</div>
|
</div>
|
||||||
<div class="page-search">
|
<div class="page-search">
|
||||||
<input type="text" placeholder="{{ "PLUGIN_ADMIN.SEARCH_PAGES"|tu }}" name="page-search" />
|
<input type="text" placeholder="{{ "PLUGIN_ADMIN.SEARCH_PAGES"|tu }}" name="page-search" />
|
||||||
@@ -314,7 +314,7 @@
|
|||||||
</p>
|
</p>
|
||||||
<br>
|
<br>
|
||||||
<div class="button-bar">
|
<div class="button-bar">
|
||||||
<a class="button secondary remodal-cancel" href="#"><i class="fa fa-fw fa-close"></i> {{ "PLUGIN_ADMIN.CANCEL"|tu }}</a>
|
<button data-remodal-action="cancel" class="button secondary remodal-cancel"><i class="fa fa-fw fa-close"></i> {{ "PLUGIN_ADMIN.CANCEL"|tu }}</button>
|
||||||
<a class="button" data-delete-action href="#"><i class="fa fa-fw fa-check"></i> {{ "PLUGIN_ADMIN.CONTINUE"|tu }}</a>
|
<a class="button" data-delete-action href="#"><i class="fa fa-fw fa-check"></i> {{ "PLUGIN_ADMIN.CONTINUE"|tu }}</a>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
@@ -343,8 +343,8 @@
|
|||||||
</p>
|
</p>
|
||||||
<br>
|
<br>
|
||||||
<div class="button-bar">
|
<div class="button-bar">
|
||||||
<a class="button secondary remodal-cancel" href="#"><i class="fa fa-fw fa-close"></i> {{ "PLUGIN_ADMIN.CANCEL"|tu }}</a>
|
<button data-remodal-action="cancel" class="button secondary remodal-cancel"><i class="fa fa-fw fa-close"></i> {{ "PLUGIN_ADMIN.CANCEL"|tu }}</button>
|
||||||
<a class="button remodal-confirm" href="#"><i class="fa fa-fw fa-check"></i> {{ "PLUGIN_ADMIN.CONTINUE"|tu }}</a>
|
<button data-remodal-action="confirm" class="button remodal-confirm"><i class="fa fa-fw fa-check"></i> {{ "PLUGIN_ADMIN.CONTINUE"|tu }}</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -37,7 +37,9 @@
|
|||||||
{% include 'partials/javascript-config.html.twig' %}
|
{% include 'partials/javascript-config.html.twig' %}
|
||||||
{% block javascripts %}
|
{% block javascripts %}
|
||||||
{% do assets.add('jquery',101) %}
|
{% do assets.add('jquery',101) %}
|
||||||
{% do assets.addJs(theme_url~'/js/modernizr.custom.71422.js') %}
|
{% do assets.addJs(theme_url~'/js/vendor.js', { 'loading':'defer' }) %}
|
||||||
|
{% do assets.addJs(theme_url~'/js/admin.js' , { 'loading':'defer' }) %}
|
||||||
|
{#{% do assets.addJs(theme_url~'/js/modernizr.custom.71422.js') %}
|
||||||
{% do assets.addJs(theme_url~'/js/chartist.min.js') %}
|
{% do assets.addJs(theme_url~'/js/chartist.min.js') %}
|
||||||
{% do assets.addJs(theme_url~'/js/selectize.min.js') %}
|
{% do assets.addJs(theme_url~'/js/selectize.min.js') %}
|
||||||
{% do assets.addJS(theme_url~'/js/sortable.min.js') %}
|
{% do assets.addJS(theme_url~'/js/sortable.min.js') %}
|
||||||
@@ -58,11 +60,11 @@
|
|||||||
{% do assets.addJs(theme_url~'/js/forms/fields/selectize.js') %}
|
{% do assets.addJs(theme_url~'/js/forms/fields/selectize.js') %}
|
||||||
{% do assets.addJs(theme_url~'/js/forms/fields/checkboxes.js') %}
|
{% do assets.addJs(theme_url~'/js/forms/fields/checkboxes.js') %}
|
||||||
{% do assets.addJs(theme_url~'/js/forms/fields/toggle.js') %}
|
{% do assets.addJs(theme_url~'/js/forms/fields/toggle.js') %}
|
||||||
{% do assets.addJs(theme_url~'/js/forms.js') %}
|
{% do assets.addJs(theme_url~'/js/forms.js') %}#}
|
||||||
|
|
||||||
{% if browser.getBrowser == 'msie' or browser.getBrowser == 'edge' %}
|
{#{% if browser.getBrowser == 'msie' or browser.getBrowser == 'edge' %}
|
||||||
{% do assets.addJs(theme_url~'/js/form-attr.polyfill.js') %}
|
{% do assets.addJs(theme_url~'/js/form-attr.polyfill.js') %}
|
||||||
{% endif %}
|
{% endif %}#}
|
||||||
|
|
||||||
{{ assets.js() }}
|
{{ assets.js() }}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
{{ dump(data.extra) }}
|
||||||
{% if data.extra %}
|
{% if data.extra %}
|
||||||
{% for name, value in data.extra %}
|
{% for name, value in data.extra %}
|
||||||
{% if name not in ['_json','task','admin-nonce'] %}
|
{% if name not in ['_json','task','admin-nonce'] %}
|
||||||
|
|||||||
@@ -5,38 +5,23 @@
|
|||||||
<div class="tertiary-accent default-box-shadow">
|
<div class="tertiary-accent default-box-shadow">
|
||||||
<h1>{{ "PLUGIN_ADMIN.MAINTENANCE"|tu }}</h1>
|
<h1>{{ "PLUGIN_ADMIN.MAINTENANCE"|tu }}</h1>
|
||||||
<div class="admin-update-charts">
|
<div class="admin-update-charts">
|
||||||
<div class="updates-chart">
|
<div class="updates-chart" data-chart-name="updates" data-chart-type="pie" data-chart-data="{{ {'series': [100, 0]}|json_encode|e('html_attr') }}">
|
||||||
<div class="chart-wrapper">
|
<div class="chart-wrapper">
|
||||||
<div class="ct-chart"></div>
|
<div class="ct-chart"></div>
|
||||||
<span class="numeric hidden"><span>-</span><em>{{ "PLUGIN_ADMIN.UPDATED"|tu|lower }}</em></span>
|
<span class="numeric hidden"><span>-</span><em>{{ "PLUGIN_ADMIN.UPDATED"|tu|lower }}</em></span>
|
||||||
</div>
|
</div>
|
||||||
<p class="js__updates-available-description"> </p>
|
<p class="js__updates-available-description"> </p>
|
||||||
</div>
|
</div>
|
||||||
<div class="backups-chart">
|
<div class="backups-chart" data-chart-name="backups" data-chart-type="pie" data-chart-data="{{ {'series': [backup.chart_fill, backup.chart_empty]}|json_encode|e('html_attr') }}">
|
||||||
<div class="chart-wrapper">
|
<div class="chart-wrapper">
|
||||||
<div class="ct-chart"></div>
|
<div class="ct-chart"></div>
|
||||||
<script>
|
|
||||||
var data = {
|
|
||||||
series: [{{ backup.chart_fill }}, {{ backup.chart_empty }}]
|
|
||||||
};
|
|
||||||
var options = {
|
|
||||||
donut: true,
|
|
||||||
donutWidth: 10,
|
|
||||||
startAngle: 0,
|
|
||||||
total: 100,
|
|
||||||
showLabel: false,
|
|
||||||
height: 150,
|
|
||||||
chartPadding: !isFirefox ? 5 : 10
|
|
||||||
};
|
|
||||||
Chartist.Pie('.backups-chart .ct-chart', data, options);
|
|
||||||
</script>
|
|
||||||
<span class="numeric">{{ backup.days }}<em>{{ "PLUGIN_ADMIN.DAYS"|tu|lower }}</em></span>
|
<span class="numeric">{{ backup.days }}<em>{{ "PLUGIN_ADMIN.DAYS"|tu|lower }}</em></span>
|
||||||
</div>
|
</div>
|
||||||
<p>{{ "PLUGIN_ADMIN.LAST_BACKUP"|tu }}</p>
|
<p>{{ "PLUGIN_ADMIN.LAST_BACKUP"|tu }}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flush-bottom button-bar">
|
<div class="flush-bottom button-bar">
|
||||||
<button data-maintenance-update="{{ uri.addNonce(base_url_relative ~ '/update.json/task' ~ config.system.param_sep ~ 'update', 'admin-form', 'admin-nonce') }}" class="button" style="display: none"><i class="fa fa-cloud-download"></i> {{ "PLUGIN_ADMIN.UPDATE"|tu }}</button>
|
<button data-maintenance-update="{{ uri.addNonce(base_url_relative ~ '/update.json/task' ~ config.system.param_sep ~ 'update', 'admin-form', 'admin-nonce') }}" class="button"><i class="fa fa-cloud-download"></i> {{ "PLUGIN_ADMIN.UPDATE"|tu }}</button>
|
||||||
<button data-ajax="{{ uri.addNonce(base_url_relative ~ '/backup.json/task' ~ config.system.param_sep ~ 'backup', 'admin-form', 'admin-nonce') }}" class="button"><i class="fa fa-database"></i> {{ "PLUGIN_ADMIN.BACKUP"|tu }}</button>
|
<button data-ajax="{{ uri.addNonce(base_url_relative ~ '/backup.json/task' ~ config.system.param_sep ~ 'backup', 'admin-form', 'admin-nonce') }}" class="button"><i class="fa fa-database"></i> {{ "PLUGIN_ADMIN.BACKUP"|tu }}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,39 +1,8 @@
|
|||||||
{% if authorize(['admin.statistics', 'admin.super']) %}
|
{% if authorize(['admin.statistics', 'admin.super']) %}
|
||||||
<div id="popularity" class="dashboard-item dashboard-right">
|
<div id="popularity" class="dashboard-item dashboard-right" data-chart-name="popularity" data-chart-type="bar" data-chart-data="{{ {'series': [popularity.getDailyChartData['data']], 'labels': popularity.getDailyChartData['labels']}|json_encode|e('html_attr') }}">
|
||||||
<div class="secondary-accent default-box-shadow">
|
<div class="secondary-accent default-box-shadow">
|
||||||
<h1>{{ "PLUGIN_ADMIN.STATISTICS"|tu }}</h1>
|
<h1>{{ "PLUGIN_ADMIN.STATISTICS"|tu }}</h1>
|
||||||
<div class="ct-chart"></div>
|
<div class="ct-chart"></div>
|
||||||
<script>
|
|
||||||
var data = {
|
|
||||||
labels: {{ popularity.getDailyChartData['labels'] }},
|
|
||||||
series: [
|
|
||||||
{{ popularity.getDailyChartData['data'] }}
|
|
||||||
]
|
|
||||||
};
|
|
||||||
var options = {
|
|
||||||
height: 164,
|
|
||||||
chartPadding: !isFirefox ? 5 : 25,
|
|
||||||
|
|
||||||
axisX: {
|
|
||||||
showGrid: false,
|
|
||||||
labelOffset: {
|
|
||||||
x: 0,
|
|
||||||
y: 5
|
|
||||||
}
|
|
||||||
},
|
|
||||||
axisY: {
|
|
||||||
offset: 15,
|
|
||||||
showLabel: true,
|
|
||||||
showGrid: true,
|
|
||||||
labelOffset: {
|
|
||||||
x: 5,
|
|
||||||
y: 5
|
|
||||||
},
|
|
||||||
scaleMinSpace: 20
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Chartist.Bar('#popularity .ct-chart', data, options);
|
|
||||||
</script>
|
|
||||||
<div class="flush-bottom button-bar stats-bar">
|
<div class="flush-bottom button-bar stats-bar">
|
||||||
<span class="stat">
|
<span class="stat">
|
||||||
<b>{{ popularity.getDailyTotal }}</b>
|
<b>{{ popularity.getDailyTotal }}</b>
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
<div class="button-bar">
|
<div class="button-bar">
|
||||||
<a class="button secondary remodal-cancel" href="#"><i class="fa fa-fw fa-close"></i> {{ "PLUGIN_ADMIN.CANCEL"|tu }}</a>
|
<button data-remodal-action="cancel" class="button secondary remodal-cancel"><i class="fa fa-fw fa-close"></i> {{ "PLUGIN_ADMIN.CANCEL"|tu }}</button>
|
||||||
<button class="button primary" name="task" value="save" form="blueprints">{{ "PLUGIN_ADMIN.CONTINUE"|tu }}</button>
|
<button class="button primary" name="task" value="save" form="blueprints">{{ "PLUGIN_ADMIN.CONTINUE"|tu }}</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -42,3 +42,17 @@
|
|||||||
<a class="button" href="{{ uri.addNonce(base_url_relative ~ '/plugins/' ~ plugin.slug ~ '/task' ~ config.system.param_sep ~ 'install', 'admin-form', 'admin-nonce') }}"><i class="fa fa-fw fa-plus"></i>{{ "PLUGIN_ADMIN.INSTALL_PLUGIN"|tu }}</a>
|
<a class="button" href="{{ uri.addNonce(base_url_relative ~ '/plugins/' ~ plugin.slug ~ '/task' ~ config.system.param_sep ~ 'install', 'admin-form', 'admin-nonce') }}"><i class="fa fa-fw fa-plus"></i>{{ "PLUGIN_ADMIN.INSTALL_PLUGIN"|tu }}</a>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
<div class="remodal" data-remodal-id="changes">
|
||||||
|
<form>
|
||||||
|
<h1>{{ "PLUGIN_ADMIN.MODAL_CHANGED_DETECTED_TITLE"|tu }}</h1>
|
||||||
|
<p class="bigger">
|
||||||
|
{{ "PLUGIN_ADMIN.MODAL_CHANGED_DETECTED_DESC"|tu }}
|
||||||
|
</p>
|
||||||
|
<br>
|
||||||
|
<div class="button-bar">
|
||||||
|
<a class="button secondary" data-leave-action="cancel" href="#"><i class="fa fa-fw fa-close"></i> {{ "PLUGIN_ADMIN.CANCEL"|tu }}</a>
|
||||||
|
<a class="button" data-leave-action="continue" href="#"><i class="fa fa-fw fa-check"></i> {{ "PLUGIN_ADMIN.CONTINUE"|tu }}</a>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|||||||
@@ -111,6 +111,16 @@
|
|||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
<div class="remodal" data-remodal-id="changes">
|
||||||
|
<form>
|
||||||
|
<h1>{{ "PLUGIN_ADMIN.MODAL_CHANGED_DETECTED_TITLE"|tu }}</h1>
|
||||||
|
<p class="bigger">
|
||||||
|
{{ "PLUGIN_ADMIN.MODAL_CHANGED_DETECTED_DESC"|tu }}
|
||||||
|
</p>
|
||||||
|
<br>
|
||||||
|
<div class="button-bar">
|
||||||
|
<a class="button secondary" data-leave-action="cancel" href="#"><i class="fa fa-fw fa-close"></i> {{ "PLUGIN_ADMIN.CANCEL"|tu }}</a>
|
||||||
|
<a class="button" data-leave-action="continue" href="#"><i class="fa fa-fw fa-check"></i> {{ "PLUGIN_ADMIN.CONTINUE"|tu }}</a>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|||||||
@@ -58,7 +58,7 @@
|
|||||||
</p>
|
</p>
|
||||||
<br>
|
<br>
|
||||||
<div class="button-bar">
|
<div class="button-bar">
|
||||||
<a class="button secondary remodal-cancel" href="#"><i class="fa fa-fw fa-close"></i> {{ "PLUGIN_ADMIN.CANCEL"|tu }}</a>
|
<button data-remodal-action="cancel" class="button secondary remodal-cancel"><i class="fa fa-fw fa-close"></i> {{ "PLUGIN_ADMIN.CANCEL"|tu }}</button>
|
||||||
<a class="button continue" href="#"><i class="fa fa-fw fa-check"></i>{{ "PLUGIN_ADMIN.CONTINUE"|tu }}</a>
|
<a class="button continue" href="#"><i class="fa fa-fw fa-check"></i>{{ "PLUGIN_ADMIN.CONTINUE"|tu }}</a>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -24,8 +24,8 @@
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block javascripts %}
|
{% block javascripts %}
|
||||||
{% do assets.addJs(theme_url~'/js/codemirror-compressed.js') %}
|
{#{% do assets.addJs(theme_url~'/js/codemirror-compressed.js') %}
|
||||||
{% do assets.addJs(theme_url~'/js/mdeditor.js') %}
|
{% do assets.addJs(theme_url~'/js/mdeditor.js') %}#}
|
||||||
{{ parent() }}
|
{{ parent() }}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
@@ -24,8 +24,8 @@
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block javascripts %}
|
{% block javascripts %}
|
||||||
{% do assets.addJs(theme_url~'/js/codemirror-compressed.js') %}
|
{#{% do assets.addJs(theme_url~'/js/codemirror-compressed.js') %}
|
||||||
{% do assets.addJs(theme_url~'/js/mdeditor.js') %}
|
{% do assets.addJs(theme_url~'/js/mdeditor.js') %}#}
|
||||||
{{ parent() }}
|
{{ parent() }}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
44
themes/grav/webpack.conf.js
Normal file
44
themes/grav/webpack.conf.js
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
var path = require('path'),
|
||||||
|
webpack = require('webpack');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
entry: {
|
||||||
|
app: './app/main.js',
|
||||||
|
vendor: [
|
||||||
|
'chartist',
|
||||||
|
'selectize',
|
||||||
|
'remodal',
|
||||||
|
'toastr',
|
||||||
|
'bootstrap',
|
||||||
|
'sortablejs',
|
||||||
|
'jquery-slugify',
|
||||||
|
'dropzone',
|
||||||
|
'eonasdan-bootstrap-datetimepicker'
|
||||||
|
]
|
||||||
|
},
|
||||||
|
output: {
|
||||||
|
path: path.resolve(__dirname, 'js'),
|
||||||
|
library: 'Grav'
|
||||||
|
},
|
||||||
|
externals: {
|
||||||
|
jquery: 'jQuery',
|
||||||
|
'grav-config': 'GravAdmin'
|
||||||
|
},
|
||||||
|
module: {
|
||||||
|
preLoaders: [
|
||||||
|
{
|
||||||
|
test: /\.js$/,
|
||||||
|
loader: 'eslint',
|
||||||
|
exclude: /node_modules/
|
||||||
|
}
|
||||||
|
],
|
||||||
|
loaders: [
|
||||||
|
{
|
||||||
|
test: /\.js$/,
|
||||||
|
loader: 'babel',
|
||||||
|
exclude: /node_modules/,
|
||||||
|
query: { presets: ['es2015'] }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user