init
This commit is contained in:
148
user/plugins/admin/themes/grav/app/pages/filter.js
Normal file
148
user/plugins/admin/themes/grav/app/pages/filter.js
Normal file
@@ -0,0 +1,148 @@
|
||||
import $ from 'jquery';
|
||||
import { config, translations } from 'grav-config';
|
||||
import request from '../utils/request';
|
||||
import debounce from 'debounce';
|
||||
import { Instance as pagesTree } from './tree';
|
||||
import 'selectize';
|
||||
import '../utils/selectize-required-fix.js';
|
||||
import '../utils/storage';
|
||||
|
||||
/* @formatter:off */
|
||||
/* eslint-disable */
|
||||
const options = [
|
||||
{ flag: translations.PLUGIN_ADMIN.MODULE, key: 'Module', cat: 'mode' },
|
||||
{ flag: translations.PLUGIN_ADMIN.VISIBLE, key: 'Visible', cat: 'mode' },
|
||||
{ flag: translations.PLUGIN_ADMIN.ROUTABLE, key: 'Routable', cat: 'mode' },
|
||||
{ flag: translations.PLUGIN_ADMIN.PUBLISHED, key: 'Published', cat: 'mode' },
|
||||
{ flag: translations.PLUGIN_ADMIN.NON_MODULE, key: 'NonModule', cat: 'mode' },
|
||||
{ flag: translations.PLUGIN_ADMIN.NON_VISIBLE, key: 'NonVisible', cat: 'mode' },
|
||||
{ flag: translations.PLUGIN_ADMIN.NON_ROUTABLE, key: 'NonRoutable', cat: 'mode' },
|
||||
{ flag: translations.PLUGIN_ADMIN.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;
|
||||
let storage = JSON.parse(localStorage.getItem('grav:admin:pages:filter') || '{}');
|
||||
|
||||
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());
|
||||
|
||||
// restore state
|
||||
if (storage.flags || storage.query) {
|
||||
this.setValues(storage);
|
||||
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) {
|
||||
let selectize = this.filters.data('selectize');
|
||||
this.filters[selectize ? 'setValue' : 'val'](flagsArray, silent);
|
||||
}
|
||||
if (this.search.val() !== query) { this.search.val(query); }
|
||||
|
||||
localStorage.setItem('grav:admin:pages:filter', JSON.stringify({ flags, 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', 'required-fix']
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let Instance = new PagesFilter('input[name="page-filter"]', 'input[name="page-search"]');
|
||||
export { Instance };
|
||||
53
user/plugins/admin/themes/grav/app/pages/index.js
Normal file
53
user/plugins/admin/themes/grav/app/pages/index.js
Normal file
@@ -0,0 +1,53 @@
|
||||
import $ from 'jquery';
|
||||
import Sortable from 'sortablejs';
|
||||
import PageFilters, { Instance as PageFiltersInstance } from './filter';
|
||||
import Page from './page';
|
||||
|
||||
const pad = (n, s) => (`000${n}`).substr(-s);
|
||||
|
||||
// Pages Ordering
|
||||
let Ordering = null;
|
||||
let orderingElement = $('#ordering');
|
||||
if (orderingElement.length) {
|
||||
Ordering = new Sortable(orderingElement.get(0), {
|
||||
filter: '.ignore',
|
||||
onUpdate: function() {
|
||||
/* Old single page index behavior
|
||||
|
||||
let item = $(event.item);
|
||||
let index = orderingElement.children().index(item) + 1;
|
||||
$('[data-order]').val(index);
|
||||
*/
|
||||
|
||||
let indexes = [];
|
||||
const children = orderingElement.children();
|
||||
const padZero = (children.length + '').split('').length;
|
||||
children.each((index, item) => {
|
||||
item = $(item);
|
||||
indexes.push(item.data('id'));
|
||||
item.find('.page-order').text(`${pad(index + 1, padZero)}.`);
|
||||
});
|
||||
|
||||
$('[data-order]').val(indexes.join(','));
|
||||
}
|
||||
});
|
||||
|
||||
$(document).on('input', '[name="data[folder]"]', (event) => {
|
||||
const target = $(event.currentTarget);
|
||||
const activeOrder = $('[data-id][data-active-id]');
|
||||
|
||||
activeOrder.data('id', target.val());
|
||||
|
||||
Ordering.options.onUpdate();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
export default {
|
||||
Ordering,
|
||||
Page,
|
||||
PageFilters: {
|
||||
PageFilters,
|
||||
Instance: PageFiltersInstance
|
||||
}
|
||||
};
|
||||
69
user/plugins/admin/themes/grav/app/pages/page/add.js
Normal file
69
user/plugins/admin/themes/grav/app/pages/page/add.js
Normal file
@@ -0,0 +1,69 @@
|
||||
import $ from 'jquery';
|
||||
import '../../utils/jquery-utils';
|
||||
import request from '../../utils/request';
|
||||
import { config } from 'grav-config';
|
||||
|
||||
let custom = false;
|
||||
let folder = $('[data-remodal-id="modal"] input[name="data[folder]"], [data-remodal-id="module"] input[name="data[folder]"], [data-remodal-id="modal-page-copy"] input[name="data[folder]"]');
|
||||
let title = $('[data-remodal-id="modal"] input[name="data[title]"], [data-remodal-id="module"] input[name="data[title]"], [data-remodal-id="modal-page-copy"] input[name="data[title]"]');
|
||||
let getFields = (type, target) => {
|
||||
target = $(target);
|
||||
let query = `[data-remodal-id="${target.closest('[data-remodal-id]').data('remodal-id')}"]`;
|
||||
|
||||
return {
|
||||
title: type === 'title' ? $(target) : $(`${query} input[name="data[title]"]`),
|
||||
folder: type === 'folder' ? $(target) : $(`${query} input[name="data[folder]"]`)
|
||||
};
|
||||
};
|
||||
|
||||
title.on('input focus blur', (event) => {
|
||||
if (custom) { return true; }
|
||||
let elements = getFields('title', event.currentTarget);
|
||||
|
||||
let slug = $.slugify(elements.title.val(), {custom: { "'": '', '‘': '', '’': '' }});
|
||||
elements.folder.val(slug);
|
||||
});
|
||||
|
||||
folder.on('input', (event) => {
|
||||
let elements = getFields('folder', event.currentTarget);
|
||||
|
||||
let input = elements.folder.get(0);
|
||||
let value = elements.folder.val();
|
||||
let selection = {
|
||||
start: input.selectionStart,
|
||||
end: input.selectionEnd
|
||||
};
|
||||
|
||||
value = value.toLowerCase().replace(/\s/g, '-').replace(/[^a-z0-9_\-]/g, '');
|
||||
elements.folder.val(value);
|
||||
custom = !!value;
|
||||
|
||||
// restore cursor position
|
||||
input.setSelectionRange(selection.start, selection.end);
|
||||
|
||||
});
|
||||
|
||||
folder.on('focus blur', (event) => {
|
||||
getFields('title').title.trigger('input');
|
||||
});
|
||||
|
||||
$(document).on('change', '[name="data[route]"]', (event) => {
|
||||
const rawroute = $(event.currentTarget).val();
|
||||
const pageTemplate = $('[name="data[name]"]');
|
||||
const URI = `${config.base_url_relative}/ajax.json/task${config.param_sep}getChildTypes`;
|
||||
|
||||
if (pageTemplate.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
request(URI, {
|
||||
method: 'post',
|
||||
body: { rawroute }
|
||||
}, (response) => {
|
||||
const type = response.child_type;
|
||||
if (type !== '' && type !== 'default') {
|
||||
pageTemplate.val(type);
|
||||
pageTemplate.data('selectize').setValue(type);
|
||||
}
|
||||
});
|
||||
});
|
||||
15
user/plugins/admin/themes/grav/app/pages/page/delete.js
Normal file
15
user/plugins/admin/themes/grav/app/pages/page/delete.js
Normal file
@@ -0,0 +1,15 @@
|
||||
import $ from 'jquery';
|
||||
|
||||
$(document).on('click', '[data-remodal-target="delete"]', function() {
|
||||
let confirm = $('[data-remodal-id="delete"] [data-delete-action]');
|
||||
let link = $(this).data('delete-url');
|
||||
|
||||
confirm.data('delete-action', link);
|
||||
});
|
||||
|
||||
$(document).on('click', '[data-delete-action]', function() {
|
||||
let remodal = $.remodal.lookup[$('[data-remodal-id="delete"]').data('remodal')];
|
||||
|
||||
global.location.href = $(this).data('delete-action');
|
||||
remodal.close();
|
||||
});
|
||||
@@ -0,0 +1,5 @@
|
||||
import $ from 'jquery';
|
||||
|
||||
$('.disable-after-click').on('click', function() {
|
||||
$(this).addClass('pointer-events-disabled');
|
||||
});
|
||||
47
user/plugins/admin/themes/grav/app/pages/page/index.js
Normal file
47
user/plugins/admin/themes/grav/app/pages/page/index.js
Normal file
@@ -0,0 +1,47 @@
|
||||
import $ from 'jquery';
|
||||
import './add';
|
||||
import './move';
|
||||
import './delete';
|
||||
import './unset';
|
||||
import './disable-buttons';
|
||||
import PageMedia, { Instance as PageMediaInstances } from './media';
|
||||
import './multilang';
|
||||
|
||||
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', () => {
|
||||
$(global).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);
|
||||
});
|
||||
}
|
||||
|
||||
export default {
|
||||
Media: {
|
||||
PageMedia,
|
||||
PageMediaInstances
|
||||
}
|
||||
};
|
||||
293
user/plugins/admin/themes/grav/app/pages/page/media.js
Normal file
293
user/plugins/admin/themes/grav/app/pages/page/media.js
Normal file
@@ -0,0 +1,293 @@
|
||||
import $ from 'jquery';
|
||||
import Cookies from '../../utils/cookies.js';
|
||||
import request from '../../utils/request';
|
||||
import FilesField, { UriToMarkdown } from '../../forms/fields/files';
|
||||
import { config, translations } from 'grav-config';
|
||||
import { Instance as Editor } from '../../forms/fields/editor';
|
||||
import Sortable from 'sortablejs';
|
||||
|
||||
const 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" title="${translations.PLUGIN_ADMIN.DELETE}" href="javascript:undefined;" data-dz-remove>${translations.PLUGIN_ADMIN.DELETE}</a>
|
||||
<a class="dz-metadata" title="${translations.PLUGIN_ADMIN.METADATA}" href="#" target="_blank" data-dz-metadata>${translations.PLUGIN_ADMIN.METADATA}</a>
|
||||
<a class="dz-view" title="${translations.PLUGIN_ADMIN.VIEW}" href="#" target="_blank" data-dz-view>${translations.PLUGIN_ADMIN.VIEW}</a>
|
||||
<a class="dz-insert" title="${translations.PLUGIN_ADMIN.INSERT}" href="javascript:undefined;" data-dz-insert>${translations.PLUGIN_ADMIN.INSERT}</a>
|
||||
</div>`.trim();
|
||||
|
||||
export default class PageMedia extends FilesField {
|
||||
constructor({ container = '#grav-dropzone', options = {} } = {}) {
|
||||
options = Object.assign(options, { previewTemplate });
|
||||
super({ container, options });
|
||||
if (!this.container.length) { return; }
|
||||
|
||||
this.urls = {
|
||||
fetch: `${this.container.data('media-url')}/task${config.param_sep}listmedia`,
|
||||
add: `${this.container.data('media-url')}/task${config.param_sep}addmedia`,
|
||||
delete: `${this.container.data('media-url')}/task${config.param_sep}delmedia`
|
||||
};
|
||||
|
||||
this.dropzone.options.url = this.urls.add;
|
||||
|
||||
if (typeof this.options.fetchMedia === 'undefined' || this.options.fetchMedia) {
|
||||
this.fetchMedia();
|
||||
}
|
||||
|
||||
if (typeof this.options.attachDragDrop === 'undefined' || this.options.attachDragDrop) {
|
||||
this.attachDragDrop();
|
||||
}
|
||||
|
||||
const field = $(`[name="${this.container.data('dropzone-field')}"]`);
|
||||
|
||||
if (field.length) {
|
||||
this.sortable = new Sortable(this.container.get(0), {
|
||||
animation: 150,
|
||||
// forceFallback: true,
|
||||
setData: (dataTransfer, target) => {
|
||||
target = $(target);
|
||||
let uri = encodeURI(target.find('.dz-filename').text());
|
||||
let shortcode = UriToMarkdown(uri);
|
||||
this.dropzone.disable();
|
||||
target.addClass('hide-backface');
|
||||
dataTransfer.effectAllowed = 'copy';
|
||||
dataTransfer.setData('text', shortcode);
|
||||
},
|
||||
onSort: () => {
|
||||
let names = [];
|
||||
this.container.find('[data-dz-name]').each((index, file) => {
|
||||
file = $(file);
|
||||
const name = file.text().trim();
|
||||
names.push(name);
|
||||
});
|
||||
|
||||
field.val(names.join(','));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fetchMedia() {
|
||||
const order = this.container.closest('.form-field').find('[name="data[header][media_order]"]').val();
|
||||
const body = { uri: this.getURI(), order };
|
||||
let url = this.urls.fetch;
|
||||
|
||||
request(url, { method: 'post', body }, (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);
|
||||
this.dropzone.options.thumbnail.call(this.dropzone, mock, data.url);
|
||||
});
|
||||
|
||||
this.updateThumbsSize();
|
||||
this.container.find('.dz-preview').prop('draggable', 'true');
|
||||
});
|
||||
}
|
||||
|
||||
onDropzoneSending(file, xhr, formData) {
|
||||
/*
|
||||
// Cannot call super because Safari and IE API don't implement `delete`
|
||||
super.onDropzoneSending(file, xhr, formData);
|
||||
formData.delete('task');
|
||||
*/
|
||||
|
||||
formData.append('name', this.options.dotNotation || file.name);
|
||||
formData.append('admin-nonce', config.admin_nonce);
|
||||
formData.append('uri', this.getURI());
|
||||
}
|
||||
|
||||
onDropzoneComplete(file) {
|
||||
super.onDropzoneComplete(file);
|
||||
if (this.sortable) {
|
||||
this.sortable.options.onSort();
|
||||
}
|
||||
|
||||
// accepted
|
||||
this.updateThumbsSize();
|
||||
this.updateMediaCount();
|
||||
$('.dz-preview').prop('draggable', 'true');
|
||||
}
|
||||
|
||||
onDropzoneAddedFile(file, ...extra) {
|
||||
super.onDropzoneAddedFile(file, extra);
|
||||
|
||||
this.updateThumbsSize();
|
||||
}
|
||||
|
||||
onDropzoneRemovedFile(file, ...extra) {
|
||||
super.onDropzoneRemovedFile(file, ...extra);
|
||||
|
||||
this.updateMediaCount();
|
||||
if (this.sortable) {
|
||||
this.sortable.options.onSort();
|
||||
}
|
||||
}
|
||||
|
||||
updateThumbsSize() {
|
||||
const status = JSON.parse(Cookies.get('grav-admin-pagemedia') || '{}');
|
||||
|
||||
if (status.width) {
|
||||
const input = this.container.closest('.pagemedia-field').find('.media-resizer');
|
||||
updateMediaSizes(input[0], status.width, false);
|
||||
}
|
||||
}
|
||||
|
||||
updateMediaCount() {
|
||||
const element = this.container.closest('.pagemedia-field').find('[data-pagemedia-count]');
|
||||
element.text(`(${this.dropzone.files.length})`);
|
||||
}
|
||||
|
||||
attachDragDrop() {
|
||||
this.container.delegate('[data-dz-insert]', 'click', (e) => {
|
||||
let target = $(e.currentTarget).parent('.dz-preview').find('.dz-filename');
|
||||
let editor = Editor.editors.filter((index, editor) => $(editor).attr('name') === 'data[content]');
|
||||
|
||||
if (editor.length) {
|
||||
editor = editor.data('codemirror');
|
||||
editor.focus();
|
||||
|
||||
let filename = encodeURI(target.text());
|
||||
let shortcode = UriToMarkdown(filename);
|
||||
editor.doc.replaceSelection(shortcode);
|
||||
}
|
||||
});
|
||||
|
||||
this.container.delegate('[data-dz-view]', 'mouseenter', (e) => {
|
||||
let target = $(e.currentTarget);
|
||||
let file = target.parent('.dz-preview').find('.dz-filename');
|
||||
let filename = encodeURI(file.text());
|
||||
let URL = target.closest('[data-media-path]').data('media-path');
|
||||
let original = this.dropzone.files.filter((file) => encodeURI(file.name) === filename).shift();
|
||||
|
||||
original = original && ((original.extras && original.extras.original) || encodeURI(original.name));
|
||||
|
||||
target.attr('href', `${URL}/${original}`);
|
||||
});
|
||||
|
||||
this.container.delegate('[data-dz-metadata]', 'click', (e) => {
|
||||
e.preventDefault();
|
||||
const target = $(e.currentTarget);
|
||||
const file = target.parent('.dz-preview').find('.dz-filename');
|
||||
const filename = encodeURI(file.text());
|
||||
const cleanName = file.text().replace('<', '<').replace('>', '>');
|
||||
|
||||
let fileObj = this.dropzone.files.filter((file) => file.name === global.decodeURI(filename)).shift() || {};
|
||||
|
||||
if (!fileObj.extras) {
|
||||
fileObj.extras = { metadata: [] };
|
||||
}
|
||||
|
||||
if (Array.isArray(fileObj.extras.metadata) && !fileObj.extras.metadata.length) {
|
||||
fileObj.extras.metadata = { '': `${cleanName}.meta.yaml doesn't exist` };
|
||||
}
|
||||
|
||||
fileObj = fileObj.extras;
|
||||
|
||||
const modal_element = $('body').find('[data-remodal-id="metadata"]');
|
||||
const modal = $.remodal.lookup[modal_element.data('remodal')];
|
||||
|
||||
modal_element.find('h1 strong').html(cleanName);
|
||||
if (fileObj.url) {
|
||||
modal_element.find('.meta-preview').html(`<img src="${fileObj.url}" />`);
|
||||
}
|
||||
|
||||
const container = modal_element.find('.meta-content').html('<ul />').find('ul');
|
||||
Object.keys(fileObj.metadata).forEach((meta) => {
|
||||
const cleanMeta = fileObj.metadata[meta].replace('<', '<').replace('>', '>');
|
||||
container.append(`<li><strong>${meta ? meta + ':' : ''}</strong> ${cleanMeta}</li>`);
|
||||
});
|
||||
|
||||
modal.open();
|
||||
});
|
||||
|
||||
this.container.delegate('.dz-preview', 'dragstart', (e) => {
|
||||
let target = $(e.currentTarget);
|
||||
let uri = encodeURI(target.find('.dz-filename').text());
|
||||
let shortcode = UriToMarkdown(uri);
|
||||
this.dropzone.disable();
|
||||
target.addClass('hide-backface');
|
||||
e.originalEvent.dataTransfer.effectAllowed = 'copy';
|
||||
e.originalEvent.dataTransfer.setData('text', shortcode);
|
||||
});
|
||||
|
||||
this.container.delegate('.dz-preview', 'dragend', (e) => {
|
||||
let target = $(e.currentTarget);
|
||||
this.dropzone.enable();
|
||||
target.removeClass('hide-backface');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export const updateMediaSizes = (input, width, store = true) => {
|
||||
const storageLocation = input.dataset.storageLocation || 'grav-admin-pagemedia';
|
||||
const status = JSON.parse(Cookies.get(storageLocation) || '{}');
|
||||
|
||||
const height = 150 * width / 200;
|
||||
const media = $(input).closest('.pagemedia-field').find('.dz-details, [data-dz-thumbnail]');
|
||||
|
||||
media.css({ width, height });
|
||||
|
||||
if (store) {
|
||||
const data = Object.assign({}, status, { width });
|
||||
Cookies.set(storageLocation, JSON.stringify(data), { expires: Infinity });
|
||||
}
|
||||
};
|
||||
|
||||
export const updateMediaCollapseStatus = (element, store = true) => {
|
||||
const storageLocation = element.dataset.storageLocation || 'grav-admin-pagemedia';
|
||||
const status = JSON.parse(Cookies.get(storageLocation) || '{}');
|
||||
|
||||
element = $(element);
|
||||
const icon = element.find('i.fa');
|
||||
const container = element.closest('.pagemedia-field');
|
||||
const panel = container.find('.form-data');
|
||||
const slider = container.find('.media-resizer').parent();
|
||||
|
||||
const isCollapsed = !icon.hasClass('fa-chevron-down');
|
||||
const collapsed = !isCollapsed;
|
||||
|
||||
icon.removeClass('fa-chevron-down fa-chevron-right').addClass(isCollapsed ? 'fa-chevron-down' : 'fa-chevron-right');
|
||||
slider[isCollapsed ? 'removeClass' : 'addClass']('hidden');
|
||||
panel[isCollapsed ? 'slideDown' : 'slideUp']();
|
||||
|
||||
if (store) {
|
||||
const data = Object.assign({}, status, { collapsed });
|
||||
Cookies.set(storageLocation, JSON.stringify(data), { expires: Infinity });
|
||||
}
|
||||
};
|
||||
|
||||
$(document).on('input', '.media-resizer', (event) => {
|
||||
const target = $(event.currentTarget);
|
||||
const width = target.val();
|
||||
|
||||
updateMediaSizes(event.currentTarget, width);
|
||||
});
|
||||
|
||||
$(document).on('click', '.media-collapser', (event) => {
|
||||
updateMediaCollapseStatus(event.currentTarget);
|
||||
});
|
||||
|
||||
$(document).ready(() => {
|
||||
$('.media-resizer').each((index, input) => {
|
||||
const storageLocation = input.dataset.storageLocation || 'grav-admin-pagemedia';
|
||||
const status = JSON.parse(Cookies.get(storageLocation) || '{}');
|
||||
|
||||
if (status.width) {
|
||||
updateMediaSizes(input, status.width, false);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
export let Instance = new PageMedia();
|
||||
63
user/plugins/admin/themes/grav/app/pages/page/move.js
Normal file
63
user/plugins/admin/themes/grav/app/pages/page/move.js
Normal file
@@ -0,0 +1,63 @@
|
||||
import $ from 'jquery';
|
||||
|
||||
$(document).on('click', '[data-page-move] button[name="task"][value="save"]', (event) => {
|
||||
/* let route = $('form#blueprints:first select[name="data[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);
|
||||
}*/
|
||||
|
||||
const modal = $(event.currentTarget).closest('[data-remodal-id]');
|
||||
const parents = modal.data('parents') || {};
|
||||
const finder = parents.finder;
|
||||
|
||||
if (!parents || !finder) { return true; }
|
||||
|
||||
const field = parents.field;
|
||||
const parentLabel = parents.parentLabel;
|
||||
const parentName = parents.parentName;
|
||||
const selection = finder.findLastActive().item[0];
|
||||
const value = selection._item[finder.config.valueKey];
|
||||
const name = selection._item[finder.config.labelKey];
|
||||
|
||||
field.val(value);
|
||||
parentLabel.text(value);
|
||||
parentName.text(name);
|
||||
finder.config.defaultPath = value;
|
||||
|
||||
$('<div />').css({
|
||||
backgroundColor: 'rgba(255, 255, 255, 0.1)',
|
||||
position: 'fixed',
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: '100vw',
|
||||
height: '100vh',
|
||||
zIndex: 15000
|
||||
}).appendTo($('body'));
|
||||
});
|
||||
|
||||
/*
|
||||
$(document).on('click', '[data-remodal-id="parents"] [data-parents-select]', (event) => {
|
||||
const modal = $(event.currentTarget).closest('[data-remodal-id]');
|
||||
const parents = modal.data('parents');
|
||||
const finder = parents.finder;
|
||||
const field = parents.field;
|
||||
const parentLabel = parents.parentLabel;
|
||||
const parentName = parents.parentName;
|
||||
const selection = finder.findLastActive().item[0];
|
||||
const value = selection._item[finder.config.valueKey];
|
||||
const name = selection._item[finder.config.labelKey];
|
||||
|
||||
field.val(value);
|
||||
parentLabel.text(value);
|
||||
parentName.text(name);
|
||||
finder.config.defaultPath = value;
|
||||
|
||||
const remodal = $.remodal.lookup[$(`[data-remodal-id="${modal.data('remodalId')}"]`).data('remodal')];
|
||||
remodal.close();
|
||||
});
|
||||
*/
|
||||
22
user/plugins/admin/themes/grav/app/pages/page/multilang.js
Normal file
22
user/plugins/admin/themes/grav/app/pages/page/multilang.js
Normal file
@@ -0,0 +1,22 @@
|
||||
import $ from 'jquery';
|
||||
|
||||
$('[name="task"][value="saveas"], [name="task"][value="switchlanguage"]').on('mousedown touchstart', (event) => {
|
||||
let fields = ['lang', 'redirect'];
|
||||
let element = $(event.currentTarget);
|
||||
let form = $(`#${element.attr('form')}`);
|
||||
|
||||
if (!form.length) { return; }
|
||||
fields.forEach((field) => {
|
||||
let value = element.attr(field);
|
||||
if (!value) { return; }
|
||||
let input = form.find(`[name="data[${field}]"]`);
|
||||
if (!input.length) {
|
||||
input = $(`<input type="hidden" name="data[${field}]" value="" />`);
|
||||
form.append(input);
|
||||
}
|
||||
|
||||
input.val(value);
|
||||
});
|
||||
|
||||
return true;
|
||||
});
|
||||
18
user/plugins/admin/themes/grav/app/pages/page/unset.js
Normal file
18
user/plugins/admin/themes/grav/app/pages/page/unset.js
Normal file
@@ -0,0 +1,18 @@
|
||||
import $ from 'jquery';
|
||||
|
||||
$(document).on('click', '.dz-unset', function() {
|
||||
|
||||
const file_upload = $(this).closest('.files-upload');
|
||||
$(this).closest('.dz-image-preview').remove();
|
||||
const unset_image = $(this).closest('.dz-image-preview').find('[data-dz-name]').text().trim();
|
||||
const images = JSON.parse(file_upload.find('input[data-grav-field="hidden"]').val()) || {};
|
||||
let image_array = {};
|
||||
|
||||
$.each(images, function(ind, obj) {
|
||||
if (!ind.endsWith(unset_image)) {
|
||||
image_array[ind] = obj;
|
||||
}
|
||||
});
|
||||
|
||||
file_upload.find('input[data-grav-field="hidden"]').val(JSON.stringify(image_array));
|
||||
});
|
||||
125
user/plugins/admin/themes/grav/app/pages/tree.js
Normal file
125
user/plugins/admin/themes/grav/app/pages/tree.js
Normal file
@@ -0,0 +1,125 @@
|
||||
import $ from 'jquery';
|
||||
import '../utils/storage';
|
||||
|
||||
const sessionKey = 'grav:admin:pages';
|
||||
|
||||
if (!sessionStorage.getItem(sessionKey)) {
|
||||
sessionStorage.setItem(sessionKey, '{}');
|
||||
}
|
||||
|
||||
export default class PagesTree {
|
||||
constructor(query, elements = undefined) {
|
||||
this.query = query;
|
||||
this.elements = $(elements !== undefined ? elements : this.query);
|
||||
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));
|
||||
this.elements.data('tree_init', 1);
|
||||
|
||||
$('[data-page-toggleall]').on('click', (event) => {
|
||||
let element = $(event.target).closest('[data-page-toggleall]');
|
||||
let action = element.data('page-toggleall');
|
||||
|
||||
this[action]();
|
||||
});
|
||||
}
|
||||
|
||||
reload() {
|
||||
const elements = $(this.query).filter((index, element) => !$(element).data('tree_init'));
|
||||
if (!elements.length) { return; }
|
||||
this.constructor(this.query, elements);
|
||||
}
|
||||
|
||||
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 };
|
||||
Reference in New Issue
Block a user