mirror of
https://github.com/avecms/AVE.cms.git
synced 2026-08-01 08:45:44 +00:00
701 lines
32 KiB
JavaScript
701 lines
32 KiB
JavaScript
/**
|
|
* JS раздела «Настройки»: tabs, conditional fields, ajax-save и запуск
|
|
* и операций обслуживания нативной схемы.
|
|
*/
|
|
(function (window, document) {
|
|
'use strict';
|
|
|
|
var Adminx = window.Adminx || (window.Adminx = {});
|
|
|
|
Adminx.Settings = {
|
|
root: null,
|
|
form: null,
|
|
dirty: false,
|
|
layoutDrag: null,
|
|
sectionDrag: null,
|
|
|
|
init: function () {
|
|
this.root = document.querySelector('[data-settings-page]');
|
|
this.form = document.getElementById('settingsForm');
|
|
if (!this.root) { return; }
|
|
|
|
var self = this;
|
|
document.addEventListener('click', function (e) {
|
|
var tab = e.target.closest('[data-settings-tab]');
|
|
if (tab) { self.openTab(tab.getAttribute('data-settings-tab')); }
|
|
|
|
if (e.target.closest('[data-settings-reset]')) { window.location.reload(); }
|
|
if (e.target.closest('[data-pagination-new]')) { self.fillPaginationNew(); }
|
|
var paginationEdit = e.target.closest('[data-pagination-edit]');
|
|
if (paginationEdit) { self.fillPaginationEdit(paginationEdit.closest('[data-pagination-row]')); }
|
|
var paginationDelete = e.target.closest('[data-pagination-delete]');
|
|
if (paginationDelete) { self.deletePagination(paginationDelete.closest('[data-pagination-row]')); }
|
|
var cacheClear = e.target.closest('[data-cache-clear]');
|
|
if (cacheClear) { self.clearCache(cacheClear.getAttribute('data-cache-clear')); }
|
|
var maintenanceClear = e.target.closest('[data-maintenance-clear]');
|
|
if (maintenanceClear) { self.clearMaintenance(maintenanceClear.getAttribute('data-maintenance-clear')); }
|
|
var systemFile = e.target.closest('[data-system-file-edit]');
|
|
if (systemFile) { self.openSystemFile(systemFile.getAttribute('data-system-file-edit')); }
|
|
if (e.target.closest('[data-constant-new]')) { self.fillConstantNew(); }
|
|
var constantEditorTab = e.target.closest('[data-constant-editor-tab]');
|
|
if (constantEditorTab) { self.openConstantEditorTab(constantEditorTab.getAttribute('data-constant-editor-tab')); }
|
|
var constantBool = e.target.closest('[data-constant-bool]');
|
|
if (constantBool) { self.setConstantBool(constantBool.getAttribute('data-constant-bool')); }
|
|
var constantEdit = e.target.closest('[data-constant-edit]');
|
|
if (constantEdit) { self.fillConstantEdit(constantEdit.closest('[data-constant-row]')); }
|
|
var constantDelete = e.target.closest('[data-constant-delete]');
|
|
if (constantDelete) { self.deleteConstant(constantDelete.closest('[data-constant-row]')); }
|
|
if (e.target.closest('[data-thumbnail-preset-scan]')) { self.scanThumbnailPresets(); }
|
|
var layoutMove = e.target.closest('[data-layout-move]');
|
|
if (layoutMove) { self.moveLayout(layoutMove); }
|
|
var sectionMove = e.target.closest('[data-section-order-move]');
|
|
if (sectionMove) { self.moveSection(sectionMove); }
|
|
});
|
|
|
|
if (this.form) {
|
|
this.form.addEventListener('input', function () { self.markDirty(); self.applyDependencies(); });
|
|
this.form.addEventListener('change', function (e) {
|
|
self.markDirty(); self.applyDependencies(); self.updateSwitchLabels();
|
|
if (e.target.matches('[data-section-order-visible]')) {
|
|
e.target.closest('[data-section-order-item]').classList.toggle('is-disabled', !e.target.checked);
|
|
self.syncSectionOrder(e.target.closest('[data-section-order]'));
|
|
}
|
|
});
|
|
this.form.addEventListener('submit', function (e) { e.preventDefault(); self.save(); });
|
|
this.form.addEventListener('dragstart', function (e) { self.sectionDragStart(e); });
|
|
this.form.addEventListener('dragover', function (e) { self.sectionDragOver(e); });
|
|
this.form.addEventListener('drop', function (e) { if (self.sectionDrag) { e.preventDefault(); } });
|
|
this.form.addEventListener('dragend', function () { self.sectionDragEnd(); });
|
|
}
|
|
|
|
var paginationForm = document.getElementById('paginationForm');
|
|
if (paginationForm) {
|
|
paginationForm.addEventListener('submit', function (e) {
|
|
e.preventDefault();
|
|
self.savePagination(paginationForm);
|
|
});
|
|
}
|
|
|
|
var constantForm = document.getElementById('constantForm');
|
|
if (constantForm) {
|
|
constantForm.addEventListener('submit', function (e) {
|
|
e.preventDefault();
|
|
self.syncConstantValue();
|
|
self.saveConstant(constantForm);
|
|
});
|
|
constantForm.addEventListener('input', function (e) {
|
|
if (e.target.matches('[data-constant-input]')) { self.syncConstantValue(e.target); }
|
|
if (e.target.matches('[data-constant-options]')) { self.updateConstantEditor(); }
|
|
});
|
|
constantForm.addEventListener('change', function (e) {
|
|
if (e.target.matches('[data-constant-type]')) { self.updateConstantEditor(); }
|
|
if (e.target.matches('[data-constant-input]')) { self.syncConstantValue(e.target); }
|
|
});
|
|
}
|
|
|
|
var systemFileForm = document.querySelector('[data-system-file-form]');
|
|
if (systemFileForm) {
|
|
systemFileForm.addEventListener('submit', function (e) {
|
|
e.preventDefault();
|
|
self.saveSystemFile(systemFileForm);
|
|
});
|
|
}
|
|
|
|
var interfaceForm = document.querySelector('[data-interface-layout-form]');
|
|
if (interfaceForm) {
|
|
interfaceForm.addEventListener('submit', function (e) { e.preventDefault(); self.saveInterface(interfaceForm); });
|
|
interfaceForm.addEventListener('change', function (e) {
|
|
if (e.target.matches('[data-layout-visible]')) {
|
|
e.target.closest('[data-layout-item]').classList.toggle('is-disabled', !e.target.checked);
|
|
}
|
|
});
|
|
interfaceForm.addEventListener('dragstart', function (e) { self.layoutDragStart(e); });
|
|
interfaceForm.addEventListener('dragover', function (e) { self.layoutDragOver(e); });
|
|
interfaceForm.addEventListener('drop', function (e) { if (self.layoutDrag) { e.preventDefault(); } });
|
|
interfaceForm.addEventListener('dragend', function () { self.layoutDragEnd(); });
|
|
}
|
|
|
|
if (this.form) { this.applyDependencies(); this.updateSwitchLabels(); }
|
|
},
|
|
|
|
base: function () {
|
|
return (this.root ? this.root.getAttribute('data-base') : '') || Adminx.base();
|
|
},
|
|
|
|
layoutDragStart: function (event) {
|
|
var handle = event.target.closest('[data-layout-handle]');
|
|
var row = handle ? handle.closest('[data-layout-item]') : null;
|
|
if (!row || handle.getAttribute('draggable') !== 'true') { event.preventDefault(); return; }
|
|
this.layoutDrag = row;
|
|
row.classList.add('is-dragging');
|
|
if (event.dataTransfer) {
|
|
event.dataTransfer.effectAllowed = 'move';
|
|
event.dataTransfer.setData('text/plain', row.getAttribute('data-code') || '');
|
|
}
|
|
},
|
|
|
|
layoutDragOver: function (event) {
|
|
if (!this.layoutDrag) { return; }
|
|
var target = event.target.closest('[data-layout-item]');
|
|
var list = event.target.closest('[data-layout-list]');
|
|
if (!target || !list || target === this.layoutDrag || this.layoutDrag.parentNode !== list) { return; }
|
|
event.preventDefault();
|
|
var rect = target.getBoundingClientRect();
|
|
list.insertBefore(this.layoutDrag, event.clientY < rect.top + rect.height / 2 ? target : target.nextSibling);
|
|
},
|
|
|
|
layoutDragEnd: function () {
|
|
if (this.layoutDrag) { this.layoutDrag.classList.remove('is-dragging'); }
|
|
this.layoutDrag = null;
|
|
},
|
|
|
|
moveLayout: function (button) {
|
|
var row = button.closest('[data-layout-item]');
|
|
if (!row || button.disabled) { return; }
|
|
if (button.getAttribute('data-layout-move') === 'up' && row.previousElementSibling) {
|
|
row.parentNode.insertBefore(row, row.previousElementSibling);
|
|
} else if (button.getAttribute('data-layout-move') === 'down' && row.nextElementSibling) {
|
|
row.parentNode.insertBefore(row.nextElementSibling, row);
|
|
}
|
|
},
|
|
|
|
sectionDragStart: function (event) {
|
|
var handle = event.target.closest('[data-section-order-handle]');
|
|
var row = handle ? handle.closest('[data-section-order-item]') : null;
|
|
if (!row || row.getAttribute('draggable') !== 'true') { event.preventDefault(); return; }
|
|
this.sectionDrag = row;
|
|
row.classList.add('is-dragging');
|
|
if (event.dataTransfer) {
|
|
event.dataTransfer.effectAllowed = 'move';
|
|
event.dataTransfer.setData('text/plain', row.getAttribute('data-code') || '');
|
|
}
|
|
},
|
|
|
|
sectionDragOver: function (event) {
|
|
if (!this.sectionDrag) { return; }
|
|
var target = event.target.closest('[data-section-order-item]');
|
|
var list = event.target.closest('[data-section-order]');
|
|
if (!target || !list || target === this.sectionDrag || this.sectionDrag.parentNode !== list) { return; }
|
|
event.preventDefault();
|
|
var rect = target.getBoundingClientRect();
|
|
list.insertBefore(this.sectionDrag, event.clientY < rect.top + rect.height / 2 ? target : target.nextSibling);
|
|
this.syncSectionOrder(list);
|
|
},
|
|
|
|
sectionDragEnd: function () {
|
|
if (this.sectionDrag) {
|
|
var list = this.sectionDrag.closest('[data-section-order]');
|
|
this.sectionDrag.classList.remove('is-dragging');
|
|
this.syncSectionOrder(list);
|
|
}
|
|
this.sectionDrag = null;
|
|
},
|
|
|
|
moveSection: function (button) {
|
|
var row = button.closest('[data-section-order-item]');
|
|
if (!row || button.disabled) { return; }
|
|
if (button.getAttribute('data-section-order-move') === 'up' && row.previousElementSibling) {
|
|
row.parentNode.insertBefore(row, row.previousElementSibling);
|
|
} else if (button.getAttribute('data-section-order-move') === 'down' && row.nextElementSibling) {
|
|
row.parentNode.insertBefore(row.nextElementSibling, row);
|
|
}
|
|
this.syncSectionOrder(row.parentNode);
|
|
this.markDirty();
|
|
},
|
|
|
|
syncSectionOrder: function (list) {
|
|
if (!list) { return; }
|
|
var input = list.parentNode.querySelector('[data-section-order-value]');
|
|
if (!input) { return; }
|
|
input.value = JSON.stringify(Array.prototype.map.call(list.querySelectorAll('[data-section-order-item]'), function (row) {
|
|
var toggle = row.querySelector('[data-section-order-visible]');
|
|
return { code: row.getAttribute('data-code') || '', visible: !!(toggle && toggle.checked) };
|
|
}));
|
|
},
|
|
|
|
layoutValues: function (scope) {
|
|
var list = document.querySelector('[data-layout-list="' + scope + '"]');
|
|
if (!list) { return []; }
|
|
return Array.prototype.map.call(list.querySelectorAll('[data-layout-item]'), function (row) {
|
|
var toggle = row.querySelector('[data-layout-visible]');
|
|
return { code: row.getAttribute('data-code') || '', visible: !!(toggle && toggle.checked) };
|
|
});
|
|
},
|
|
|
|
saveInterface: function (form) {
|
|
var data = new FormData(form);
|
|
data.set('navigation', JSON.stringify(this.layoutValues('navigation')));
|
|
data.set('dashboard', JSON.stringify(this.layoutValues('dashboard')));
|
|
Adminx.Loader.show();
|
|
Adminx.Ajax.post(this.base() + '/settings/interface', data).then(function (payload) {
|
|
Adminx.Loader.hide();
|
|
var result = payload.data || {};
|
|
if (!result.success) {
|
|
Adminx.Toast.show(result.message || 'Не удалось сохранить интерфейс', 'error');
|
|
return;
|
|
}
|
|
Adminx.Toast.show(result.message || 'Интерфейс обновлен', 'success');
|
|
window.setTimeout(function () { window.location.reload(); }, 250);
|
|
}).catch(function () {
|
|
Adminx.Loader.hide();
|
|
Adminx.Toast.show('Ошибка сети', 'error');
|
|
});
|
|
},
|
|
|
|
openTab: function (code) {
|
|
document.querySelectorAll('[data-settings-tab]').forEach(function (tab) {
|
|
tab.setAttribute('aria-selected', tab.getAttribute('data-settings-tab') === code ? 'true' : 'false');
|
|
});
|
|
document.querySelectorAll('[data-settings-panel]').forEach(function (panel) {
|
|
panel.classList.toggle('active', panel.getAttribute('data-settings-panel') === code);
|
|
});
|
|
},
|
|
|
|
openInitialTab: function () {
|
|
var hash = (window.location.hash || '').replace(/^#/, '');
|
|
if (hash && document.querySelector('[data-settings-tab="' + hash + '"]')) {
|
|
this.openTab(hash);
|
|
}
|
|
},
|
|
|
|
markDirty: function () {
|
|
this.dirty = true;
|
|
var bar = document.getElementById('settingsSavebar');
|
|
if (bar) { bar.hidden = false; }
|
|
},
|
|
|
|
clearErrors: function () {
|
|
this.form.querySelectorAll('[data-error]').forEach(function (s) { s.textContent = ''; });
|
|
this.form.querySelectorAll('.input, .select, .textarea').forEach(function (el) { el.classList.remove('is-invalid'); });
|
|
},
|
|
|
|
save: function () {
|
|
var self = this;
|
|
this.clearErrors();
|
|
Adminx.Loader.show();
|
|
Adminx.Ajax.post(this.base() + '/settings', new FormData(this.form)).then(function (payload) {
|
|
Adminx.Loader.hide();
|
|
var d = payload.data || {};
|
|
if (d.success) {
|
|
self.dirty = false;
|
|
var bar = document.getElementById('settingsSavebar');
|
|
if (bar) { bar.hidden = true; }
|
|
Adminx.Toast.show(d.message || 'Настройки сохранены', 'success');
|
|
return;
|
|
}
|
|
var errors = d.errors || {};
|
|
Object.keys(errors).forEach(function (field) {
|
|
var span = self.form.querySelector('[data-error="' + field + '"]');
|
|
if (span) { span.textContent = errors[field]; }
|
|
var input = self.form.querySelector('[name="' + field + '"]');
|
|
if (input) { input.classList.add('is-invalid'); }
|
|
});
|
|
Adminx.Toast.show(d.message || 'Не удалось сохранить', 'error');
|
|
}).catch(function () {
|
|
Adminx.Loader.hide();
|
|
Adminx.Toast.show('Ошибка сети', 'error');
|
|
});
|
|
},
|
|
|
|
paginationForm: function () {
|
|
return document.getElementById('paginationForm');
|
|
},
|
|
|
|
fillPaginationNew: function () {
|
|
var form = this.paginationForm();
|
|
if (!form) { return; }
|
|
form.reset();
|
|
form.querySelector('[name="id"]').value = '';
|
|
document.getElementById('paginationDrawerTitle').textContent = 'Новый шаблон пагинации';
|
|
},
|
|
|
|
fillPaginationEdit: function (row) {
|
|
var form = this.paginationForm();
|
|
if (!form || !row) { return; }
|
|
var id = row.getAttribute('data-id');
|
|
this.fillPaginationNew();
|
|
document.getElementById('paginationDrawerTitle').textContent = 'Изменение: ' + row.getAttribute('data-name');
|
|
Adminx.Loader.show();
|
|
Adminx.Ajax.request(this.base() + '/settings/paginations/' + id).then(function (payload) {
|
|
Adminx.Loader.hide();
|
|
var d = payload.data || {};
|
|
if (!d.success) {
|
|
Adminx.Toast.show(d.message || 'Шаблон не найден', 'error');
|
|
return;
|
|
}
|
|
var data = d.data || {};
|
|
Object.keys(data).forEach(function (key) {
|
|
var el = form.querySelector('[name="' + key + '"]');
|
|
if (el) { el.value = data[key] == null ? '' : data[key]; }
|
|
});
|
|
}).catch(function () {
|
|
Adminx.Loader.hide();
|
|
Adminx.Toast.show('Ошибка сети', 'error');
|
|
});
|
|
},
|
|
|
|
savePagination: function (form) {
|
|
var id = (form.querySelector('[name="id"]').value || '').trim();
|
|
var url = this.base() + '/settings/paginations' + (id ? '/' + id : '');
|
|
Adminx.Loader.show();
|
|
Adminx.Ajax.post(url, new FormData(form)).then(function (payload) {
|
|
Adminx.Loader.hide();
|
|
var d = payload.data || {};
|
|
if (d.success) {
|
|
Adminx.Ajax.handle(payload);
|
|
if (!d.redirect) { window.location.reload(); }
|
|
} else {
|
|
Adminx.Toast.show(d.message || 'Не удалось сохранить шаблон', 'error');
|
|
}
|
|
}).catch(function () {
|
|
Adminx.Loader.hide();
|
|
Adminx.Toast.show('Ошибка сети', 'error');
|
|
});
|
|
},
|
|
|
|
deletePagination: function (row) {
|
|
if (!row) { return; }
|
|
var self = this;
|
|
Adminx.Confirm.open({
|
|
kind: 'error',
|
|
title: 'Удалить шаблон пагинации?',
|
|
message: '«' + row.getAttribute('data-name') + '» будет удалён.',
|
|
confirmLabel: 'Удалить',
|
|
confirmClass: 'btn-danger',
|
|
onConfirm: function () {
|
|
Adminx.Loader.show();
|
|
Adminx.Ajax.post(self.base() + '/settings/paginations/' + row.getAttribute('data-id') + '/delete').then(function (payload) {
|
|
Adminx.Loader.hide();
|
|
var d = payload.data || {};
|
|
if (d.success) {
|
|
row.remove();
|
|
Adminx.Toast.show(d.message || 'Шаблон удалён', 'success');
|
|
} else {
|
|
Adminx.Toast.show(d.message || 'Не удалось удалить', 'error');
|
|
}
|
|
}).catch(function () {
|
|
Adminx.Loader.hide();
|
|
Adminx.Toast.show('Ошибка сети', 'error');
|
|
});
|
|
}
|
|
});
|
|
},
|
|
|
|
clearCache: function (source) {
|
|
var self = this;
|
|
Adminx.Confirm.open({
|
|
kind: 'warning',
|
|
title: 'Очистить кеш?',
|
|
message: 'Будет очищен источник «' + source + '».',
|
|
confirmLabel: 'Очистить',
|
|
onConfirm: function () {
|
|
Adminx.Loader.show();
|
|
Adminx.Ajax.post(self.base() + '/settings/cache/' + encodeURIComponent(source) + '/clear').then(function (payload) {
|
|
Adminx.Loader.hide();
|
|
var d = payload.data || {};
|
|
if (d.success) {
|
|
var row = document.querySelector('[data-cache-row="' + source + '"]');
|
|
if (row && d.data && d.data.size) {
|
|
var cell = row.querySelector('[data-cache-size]');
|
|
if (cell) { cell.textContent = d.data.size; }
|
|
}
|
|
Adminx.Toast.show(d.message || 'Кеш очищен', 'success');
|
|
} else {
|
|
Adminx.Toast.show(d.message || 'Не удалось очистить кеш', 'error');
|
|
}
|
|
}).catch(function () {
|
|
Adminx.Loader.hide();
|
|
Adminx.Toast.show('Ошибка сети', 'error');
|
|
});
|
|
}
|
|
});
|
|
},
|
|
|
|
clearMaintenance: function (target) {
|
|
var self = this;
|
|
var label = target === 'revisions'
|
|
? 'все ревизии документов, блоков, шаблонов, рубрик, тем, представлений и оформления каталога'
|
|
: 'всю подневную статистику просмотров';
|
|
Adminx.Confirm.open({
|
|
kind: 'danger',
|
|
title: 'Очистить служебные данные?',
|
|
message: 'Будут удалены ' + label + '. Действие необратимо.',
|
|
confirmLabel: 'Очистить',
|
|
onConfirm: function () {
|
|
Adminx.Loader.show();
|
|
Adminx.Ajax.post(self.base() + '/settings/maintenance/' + encodeURIComponent(target) + '/clear').then(function (payload) {
|
|
Adminx.Loader.hide();
|
|
var d = payload.data || {};
|
|
Adminx.Toast.show(d.message || (d.success ? 'Данные очищены' : 'Не удалось очистить данные'), d.success ? 'success' : 'error');
|
|
if (d.success) { window.location.reload(); }
|
|
}).catch(function () { Adminx.Loader.hide(); Adminx.Toast.show('Ошибка сети', 'error'); });
|
|
}
|
|
});
|
|
},
|
|
|
|
openSystemFile: function (code) {
|
|
var form = document.querySelector('[data-system-file-form]');
|
|
if (!form) { return; }
|
|
Adminx.Loader.show();
|
|
Adminx.Ajax.request(this.base() + '/settings/files/' + encodeURIComponent(code)).then(function (payload) {
|
|
Adminx.Loader.hide();
|
|
var d = payload.data || {};
|
|
if (!d.success) { Adminx.Toast.show(d.message || 'Файл не найден', 'error'); return; }
|
|
var file = d.data || {};
|
|
form.elements.code.value = file.code || code;
|
|
var textarea = form.elements.content;
|
|
textarea.value = file.content || '';
|
|
textarea.setAttribute('data-code-mode', file.mode || 'text/plain');
|
|
if (textarea._adminxCodeMirror) {
|
|
textarea._adminxCodeMirror.setOption('mode', file.mode || 'text/plain');
|
|
textarea._adminxCodeMirror.setValue(file.content || '');
|
|
textarea._adminxCodeMirror.setSize('100%', '100%');
|
|
setTimeout(function () { textarea._adminxCodeMirror.refresh(); }, 80);
|
|
}
|
|
var title = document.getElementById('systemFileDrawerTitle');
|
|
var path = document.querySelector('[data-system-file-path]');
|
|
if (title) { title.textContent = file.label || 'Системный файл'; }
|
|
if (path) { path.textContent = file.path || ''; }
|
|
}).catch(function () { Adminx.Loader.hide(); Adminx.Toast.show('Ошибка сети', 'error'); });
|
|
},
|
|
|
|
saveSystemFile: function (form) {
|
|
var code = form.elements.code.value || '';
|
|
var textarea = form.elements.content;
|
|
if (textarea._adminxCodeMirror) { textarea._adminxCodeMirror.save(); }
|
|
Adminx.Loader.show();
|
|
Adminx.Ajax.post(this.base() + '/settings/files/' + encodeURIComponent(code), new FormData(form)).then(function (payload) {
|
|
Adminx.Loader.hide();
|
|
var d = payload.data || {};
|
|
Adminx.Toast.show(d.message || (d.success ? 'Файл сохранён' : 'Не удалось сохранить файл'), d.success ? 'success' : 'error');
|
|
}).catch(function () { Adminx.Loader.hide(); Adminx.Toast.show('Ошибка сети', 'error'); });
|
|
},
|
|
|
|
constantForm: function () {
|
|
return document.getElementById('constantForm');
|
|
},
|
|
|
|
fillConstantNew: function () {
|
|
var form = this.constantForm();
|
|
if (!form) { return; }
|
|
form.reset();
|
|
form.querySelector('[name="name"]').readOnly = false;
|
|
form.querySelector('[name="is_system"]').value = '0';
|
|
form.querySelector('[name="sort_order"]').value = '100';
|
|
form.querySelector('[data-constant-value]').value = '';
|
|
var presetResult = form.querySelector('[data-thumbnail-preset-result]');
|
|
if (presetResult) { presetResult.hidden = true; presetResult.textContent = ''; }
|
|
this.openConstantEditorTab('value');
|
|
this.updateConstantEditor();
|
|
document.getElementById('constantDrawerTitle').textContent = 'Новая константа';
|
|
},
|
|
|
|
fillConstantEdit: function (row) {
|
|
var form = this.constantForm();
|
|
if (!form || !row) { return; }
|
|
var self = this;
|
|
this.fillConstantNew();
|
|
var name = row.getAttribute('data-name');
|
|
document.getElementById('constantDrawerTitle').textContent = 'Изменение: ' + name;
|
|
Adminx.Loader.show();
|
|
Adminx.Ajax.request(this.base() + '/settings/constants/' + encodeURIComponent(name)).then(function (payload) {
|
|
Adminx.Loader.hide();
|
|
var d = payload.data || {};
|
|
if (!d.success) {
|
|
Adminx.Toast.show(d.message || 'Константа не найдена', 'error');
|
|
return;
|
|
}
|
|
var data = d.data || {};
|
|
Object.keys(data).forEach(function (key) {
|
|
var el = form.querySelector('[name="' + key + '"]');
|
|
if (el) { el.value = data[key] == null ? '' : data[key]; }
|
|
});
|
|
form.querySelector('[name="name"]').readOnly = true;
|
|
if (Array.isArray(data.options_array)) {
|
|
form.querySelector('[name="options"]').value = data.options_array.join('\n');
|
|
}
|
|
self.updateConstantEditor();
|
|
self.openConstantEditorTab('value');
|
|
}).catch(function () {
|
|
Adminx.Loader.hide();
|
|
Adminx.Toast.show('Ошибка сети', 'error');
|
|
});
|
|
},
|
|
|
|
saveConstant: function (form) {
|
|
Adminx.Loader.show();
|
|
Adminx.Ajax.post(this.base() + '/settings/constants', new FormData(form)).then(function (payload) {
|
|
Adminx.Loader.hide();
|
|
var d = payload.data || {};
|
|
if (d.success) {
|
|
Adminx.Ajax.handle(payload);
|
|
if (!d.redirect) { window.location.reload(); }
|
|
} else {
|
|
Adminx.Toast.show(d.message || 'Не удалось сохранить константу', 'error');
|
|
}
|
|
}).catch(function () {
|
|
Adminx.Loader.hide();
|
|
Adminx.Toast.show('Ошибка сети', 'error');
|
|
});
|
|
},
|
|
|
|
openConstantEditorTab: function (code) {
|
|
var form = this.constantForm(); if (!form) { return; }
|
|
form.querySelectorAll('[data-constant-editor-tab]').forEach(function (tab) {
|
|
var active = tab.getAttribute('data-constant-editor-tab') === code;
|
|
tab.classList.toggle('is-active', active); tab.setAttribute('aria-selected', active ? 'true' : 'false');
|
|
});
|
|
form.querySelectorAll('[data-constant-editor-panel]').forEach(function (panel) {
|
|
panel.hidden = panel.getAttribute('data-constant-editor-panel') !== code;
|
|
});
|
|
},
|
|
|
|
constantOptions: function () {
|
|
var form = this.constantForm(); if (!form) { return []; }
|
|
var raw = form.querySelector('[data-constant-options]').value || '', seen = {};
|
|
return raw.split(/[\r\n,]+/).map(function (item) { return item.trim(); }).filter(function (item) {
|
|
if (!item || seen[item]) { return false; } seen[item] = true; return true;
|
|
});
|
|
},
|
|
|
|
updateConstantEditor: function () {
|
|
var form = this.constantForm(); if (!form) { return; }
|
|
var type = form.querySelector('[data-constant-type]').value || 'string';
|
|
var value = form.querySelector('[data-constant-value]').value || '';
|
|
var name = (form.querySelector('[name="name"]').value || '').trim().toUpperCase();
|
|
var thumbnailTools = form.querySelector('[data-thumbnail-preset-tools]');
|
|
if (thumbnailTools) { thumbnailTools.hidden = name !== 'THUMBNAIL_SIZES'; }
|
|
form.querySelectorAll('[data-constant-control]').forEach(function (control) { control.hidden = control.getAttribute('data-constant-control') !== type; });
|
|
var optionsField = form.querySelector('[data-constant-options-field]');
|
|
optionsField.hidden = type !== 'select' && type !== 'tags';
|
|
var hints = { string: 'Обычная текстовая строка.', path: 'Путь относительно корня проекта или абсолютный путь.', int: 'Только целое число.', bool: 'Выберите одно из двух состояний.', select: 'Выберите один из настроенных вариантов.', tags: 'Введите значения по одному на строку.' };
|
|
form.querySelector('[data-constant-value-hint]').textContent = hints[type] || '';
|
|
if (type === 'bool') {
|
|
this.setConstantBool(value === '1' || value === 'true' ? '1' : '0'); return;
|
|
}
|
|
if (type === 'select') {
|
|
var select = form.querySelector('[data-constant-input="select"]'), options = this.constantOptions();
|
|
select.innerHTML = '';
|
|
options.forEach(function (option) { var node = document.createElement('option'); node.value = option; node.textContent = option; select.appendChild(node); });
|
|
if (options.indexOf(value) < 0 && value !== '') { var current = document.createElement('option'); current.value = value; current.textContent = value + ' (текущее)'; select.insertBefore(current, select.firstChild); }
|
|
select.value = value; select.disabled = options.length === 0 && value === '';
|
|
form.querySelector('[data-constant-select-empty]').hidden = !select.disabled;
|
|
return;
|
|
}
|
|
var input = form.querySelector('[data-constant-input="' + type + '"]');
|
|
if (input) {
|
|
input.value = type === 'tags' && name === 'THUMBNAIL_SIZES'
|
|
? value.split(/[\s,;]+/).filter(Boolean).join('\n')
|
|
: value;
|
|
}
|
|
},
|
|
|
|
scanThumbnailPresets: function () {
|
|
var form = this.constantForm();
|
|
if (!form) { return; }
|
|
var self = this;
|
|
var button = form.querySelector('[data-thumbnail-preset-scan]');
|
|
if (button) { button.disabled = true; }
|
|
Adminx.Loader.show();
|
|
Adminx.Ajax.post(this.base() + '/settings/constants/thumbnail-sizes/scan').then(function (payload) {
|
|
Adminx.Loader.hide();
|
|
if (button) { button.disabled = false; }
|
|
var response = payload.data || {};
|
|
if (!response.success) {
|
|
Adminx.Toast.show(response.message || 'Не удалось собрать размеры', 'error');
|
|
return;
|
|
}
|
|
var data = response.data || {};
|
|
var sizes = Array.isArray(data.sizes) ? data.sizes : [];
|
|
form.querySelector('[data-constant-type]').value = 'tags';
|
|
form.querySelector('[data-constant-value]').value = sizes.join(',');
|
|
self.updateConstantEditor();
|
|
var input = form.querySelector('[data-constant-input="tags"]');
|
|
if (input) { input.value = sizes.join('\n'); }
|
|
self.syncConstantValue(input);
|
|
var result = form.querySelector('[data-thumbnail-preset-result]');
|
|
if (result) {
|
|
result.hidden = false;
|
|
result.textContent = 'Найдено: ' + sizes.length + ' · файлов: ' + (data.files_scanned || 0)
|
|
+ ' · таблиц БД: ' + (data.database_tables_scanned || 0)
|
|
+ (Array.isArray(data.warnings) && data.warnings.length ? ' · предупреждений: ' + data.warnings.length : '');
|
|
}
|
|
Adminx.Toast.show(response.message || 'Размеры собраны', 'success');
|
|
}).catch(function () {
|
|
Adminx.Loader.hide();
|
|
if (button) { button.disabled = false; }
|
|
Adminx.Toast.show('Ошибка сети', 'error');
|
|
});
|
|
},
|
|
|
|
setConstantBool: function (value, sync) {
|
|
var form = this.constantForm(); if (!form) { return; }
|
|
value = String(value) === '1' ? '1' : '0';
|
|
form.querySelectorAll('[data-constant-bool]').forEach(function (button) { button.setAttribute('aria-pressed', button.getAttribute('data-constant-bool') === value ? 'true' : 'false'); });
|
|
if (sync !== false) { form.querySelector('[data-constant-value]').value = value; }
|
|
},
|
|
|
|
syncConstantValue: function (control) {
|
|
var form = this.constantForm(); if (!form) { return; }
|
|
var type = form.querySelector('[data-constant-type]').value || 'string';
|
|
if (type === 'bool') { return; }
|
|
control = control || form.querySelector('[data-constant-input="' + type + '"]');
|
|
if (control) { form.querySelector('[data-constant-value]').value = control.value; }
|
|
},
|
|
|
|
deleteConstant: function (row) {
|
|
if (!row) { return; }
|
|
var self = this;
|
|
var name = row.getAttribute('data-name');
|
|
Adminx.Confirm.open({
|
|
kind: 'error',
|
|
title: 'Удалить константу?',
|
|
message: name + ' будет удалена из управляемой БД. PHP-файл изменится только после сборки.',
|
|
confirmLabel: 'Удалить',
|
|
confirmClass: 'btn-danger',
|
|
onConfirm: function () {
|
|
Adminx.Loader.show();
|
|
Adminx.Ajax.post(self.base() + '/settings/constants/' + encodeURIComponent(name) + '/delete').then(function (payload) {
|
|
Adminx.Loader.hide();
|
|
var d = payload.data || {};
|
|
if (d.success) {
|
|
row.remove();
|
|
Adminx.Toast.show(d.message || 'Константа удалена', 'success');
|
|
} else {
|
|
Adminx.Toast.show(d.message || 'Не удалось удалить', 'error');
|
|
}
|
|
}).catch(function () {
|
|
Adminx.Loader.hide();
|
|
Adminx.Toast.show('Ошибка сети', 'error');
|
|
});
|
|
}
|
|
});
|
|
},
|
|
|
|
applyDependencies: function () {
|
|
var self = this;
|
|
this.form.querySelectorAll('[data-depends-key]').forEach(function (field) {
|
|
var key = field.getAttribute('data-depends-key');
|
|
var value = field.getAttribute('data-depends-value');
|
|
var control = self.form.querySelector('[name="' + key + '"]');
|
|
var visible = control && control.value === value;
|
|
field.hidden = !visible;
|
|
});
|
|
},
|
|
|
|
updateSwitchLabels: function () {
|
|
this.form.querySelectorAll('.settings-switch-line').forEach(function (line) {
|
|
var input = line.querySelector('input[type="checkbox"]');
|
|
var label = line.querySelector('span b');
|
|
if (input && label) { label.textContent = input.checked ? 'Включено' : 'Выключено'; }
|
|
});
|
|
}
|
|
};
|
|
|
|
if (document.readyState === 'loading') {
|
|
document.addEventListener('DOMContentLoaded', function () { Adminx.Settings.init(); });
|
|
} else {
|
|
Adminx.Settings.init();
|
|
}
|
|
})(window, document);
|