Fix plugin arrows (grey/disable not hide) + live frontmatter update on plugin change
- Arrow buttons: opacity 0.4 + pointer-events none at first/last (not hidden) - updateFrontmatter(): updates both layout AND plugins in editor live - Plugin order change -> frontmatter updated immediately in CodeMirror - Plugin checkbox toggle -> frontmatter updated immediately - Label is 'Plugins' (not 'Zichtbare plugins') - Update AGENTS.md with plugin types (content vs system)
This commit is contained in:
@@ -271,6 +271,15 @@ Gedefinieerd in `AdminAuth::ROLE_PERMISSIONS` als een mapping van rol → toeges
|
||||
- `handlePluginsEdit` in `admin.php` moet `$pluginDir . '/' . $plugin . '.php'` gebruiken, NIET `$pluginDir . '/plugin.php'`.
|
||||
- `handlePluginsNew` moet het bestand aanmaken als `<PluginName>.php`, NIET `plugin.php`.
|
||||
|
||||
## CRITICAL: Plugin types (content vs systeem)
|
||||
- `plugin.json` heeft een `type` veld: `"type": "content"` of `"type": "system"`.
|
||||
- **Content plugins** (type=content): Verschijnen in de sidebar en in de plugin selectie op content-edit paginas.
|
||||
- **Systeem plugins** (type=system): Worden geladen door PluginManager (voor API/hooks) maar verschijnen NIET in de sidebar. Bieden functionaliteit aan via de CMSAPI.
|
||||
- `PluginManager::isPluginViewable()` checkt `type === 'system'` -> niet viewable in sidebar.
|
||||
- `handleContentEdit` toont alleen content-plugins in de plugin selectie.
|
||||
- De admin plugins pagina toont een "Content" of "Systeem" badge.
|
||||
- Bij geen `type` veld in plugin.json wordt default `content` aangenomen.
|
||||
|
||||
## CRITICAL: Essentiële plugins beschermen
|
||||
- Essentiële plugins gedefinieerd in `getProtectedPlugins()` in `public/admin.php` (huidige: `Navigation`).
|
||||
- Deze plugins kunnen NIET worden: gedeactiveerd (`handlePluginsToggle`), verwijderd (`handlePluginsDelete`), bewerkt (`handlePluginsEdit`).
|
||||
|
||||
@@ -89,6 +89,7 @@ document.addEventListener('DOMContentLoaded', function () {
|
||||
var filenameInput = document.getElementById('filename');
|
||||
var layoutSelect = document.getElementById('layout');
|
||||
var pluginSection = document.getElementById('plugin-section');
|
||||
var pluginList = document.getElementById('plugin-order-list');
|
||||
if (!backBtn) return;
|
||||
|
||||
var sidebarLayouts = {{ sidebarLayouts|json_encode|raw }};
|
||||
@@ -106,86 +107,138 @@ document.addEventListener('DOMContentLoaded', function () {
|
||||
filenameInput.addEventListener('input', markChanged);
|
||||
}
|
||||
|
||||
// Show/hide plugin section based on layout
|
||||
function updatePluginVisibility() {
|
||||
if (!layoutSelect || !pluginSection) return;
|
||||
var hasSidebar = sidebarLayouts.indexOf(layoutSelect.value) !== -1;
|
||||
pluginSection.style.display = hasSidebar ? '' : 'none';
|
||||
// Disable checkboxes if no sidebar
|
||||
pluginSection.querySelectorAll('.plugin-checkbox').forEach(function(cb) {
|
||||
cb.disabled = !hasSidebar;
|
||||
});
|
||||
}
|
||||
|
||||
// Update arrow visibility — hide up on first, down on last
|
||||
// Arrow state: grey out and disable at first/last position (not hidden)
|
||||
function updateArrows() {
|
||||
if (!pluginList) return;
|
||||
var items = pluginList.querySelectorAll('li[data-plugin]');
|
||||
items.forEach(function(item, i) {
|
||||
var upBtn = item.querySelector('.plugin-up');
|
||||
var downBtn = item.querySelector('.plugin-down');
|
||||
if (upBtn) upBtn.style.visibility = (i === 0) ? 'hidden' : '';
|
||||
if (downBtn) downBtn.style.visibility = (i === items.length - 1) ? 'hidden' : '';
|
||||
var upDisabled = (i === 0);
|
||||
var downDisabled = (i === items.length - 1);
|
||||
|
||||
if (upBtn) {
|
||||
upBtn.disabled = upDisabled;
|
||||
upBtn.style.opacity = upDisabled ? '0.4' : '';
|
||||
upBtn.style.pointerEvents = upDisabled ? 'none' : '';
|
||||
}
|
||||
if (downBtn) {
|
||||
downBtn.disabled = downDisabled;
|
||||
downBtn.style.opacity = downDisabled ? '0.4' : '';
|
||||
downBtn.style.pointerEvents = downDisabled ? 'none' : '';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Update the layout value in the editor's frontmatter when the select changes
|
||||
if (layoutSelect) {
|
||||
layoutSelect.addEventListener('change', function () {
|
||||
var newLayout = this.value;
|
||||
var editor = document.getElementById('editor-textarea');
|
||||
updatePluginVisibility();
|
||||
// Update frontmatter in the editor (layout and plugins together)
|
||||
function updateFrontmatter() {
|
||||
var editor = document.getElementById('editor-textarea');
|
||||
if (!editor) return;
|
||||
|
||||
if (!editor) return;
|
||||
var cm = window.codeMirrorEditor;
|
||||
var content = cm ? cm.getValue() : editor.value;
|
||||
var newLayout = layoutSelect ? layoutSelect.value : '';
|
||||
|
||||
var cm = window.codeMirrorEditor;
|
||||
var content = cm ? cm.getValue() : editor.value;
|
||||
// Get current plugin order (only checked, in DOM order)
|
||||
var pluginOrder = [];
|
||||
if (pluginList) {
|
||||
pluginList.querySelectorAll('li[data-plugin]').forEach(function(item) {
|
||||
var cb = item.querySelector('.plugin-checkbox');
|
||||
if (cb && cb.checked) {
|
||||
pluginOrder.push(item.getAttribute('data-plugin'));
|
||||
}
|
||||
});
|
||||
}
|
||||
var pluginsValue = pluginOrder.join(', ');
|
||||
|
||||
// Check if frontmatter exists
|
||||
var fmMatch = content.match(/^---\n([\s\S]*?)\n---/);
|
||||
if (fmMatch) {
|
||||
var frontmatter = fmMatch[1];
|
||||
var fmMatch = content.match(/^---\n([\s\S]*?)\n---/);
|
||||
if (fmMatch) {
|
||||
var frontmatter = fmMatch[1];
|
||||
|
||||
if (newLayout) {
|
||||
if (/^layout:\s*.+$/m.test(frontmatter)) {
|
||||
frontmatter = frontmatter.replace(/^layout:\s*.+$/m, 'layout: ' + newLayout);
|
||||
} else {
|
||||
frontmatter = 'layout: ' + newLayout + '\n' + frontmatter;
|
||||
}
|
||||
content = content.replace(/^---\n([\s\S]*?)\n---/, '---\n' + frontmatter + '\n---');
|
||||
} else {
|
||||
content = '---\nlayout: ' + newLayout + '\n---\n\n' + content;
|
||||
}
|
||||
|
||||
if (cm) {
|
||||
cm.setValue(content);
|
||||
} else {
|
||||
editor.value = content;
|
||||
if (/^plugins:\s*.+$/m.test(frontmatter)) {
|
||||
if (pluginsValue) {
|
||||
frontmatter = frontmatter.replace(/^plugins:\s*.+$/m, 'plugins: ' + pluginsValue);
|
||||
} else {
|
||||
frontmatter = frontmatter.replace(/^plugins:\s*.*\n?/m, '');
|
||||
}
|
||||
} else if (pluginsValue) {
|
||||
frontmatter = 'plugins: ' + pluginsValue + '\n' + frontmatter;
|
||||
}
|
||||
|
||||
content = content.replace(/^---\n([\s\S]*?)\n---/, '---\n' + frontmatter + '\n---');
|
||||
} else {
|
||||
var fm = '';
|
||||
if (newLayout) fm += 'layout: ' + newLayout + '\n';
|
||||
if (pluginsValue) fm += 'plugins: ' + pluginsValue + '\n';
|
||||
if (fm) {
|
||||
content = '---\n' + fm + '---\n\n' + content;
|
||||
}
|
||||
}
|
||||
|
||||
if (cm) {
|
||||
cm.setValue(content);
|
||||
} else {
|
||||
editor.value = content;
|
||||
}
|
||||
}
|
||||
|
||||
// Layout change
|
||||
if (layoutSelect) {
|
||||
layoutSelect.addEventListener('change', function () {
|
||||
updatePluginVisibility();
|
||||
updateFrontmatter();
|
||||
markChanged();
|
||||
});
|
||||
}
|
||||
|
||||
window.__onContentChange = markChanged;
|
||||
|
||||
// Plugin order: move list items up/down
|
||||
var pluginList = document.getElementById('plugin-order-list');
|
||||
// Plugin order: move up/down + checkbox change
|
||||
if (pluginList) {
|
||||
pluginList.addEventListener('click', function (e) {
|
||||
var upBtn = e.target.closest('.plugin-up');
|
||||
var downBtn = e.target.closest('.plugin-down');
|
||||
if (!upBtn && !downBtn) return;
|
||||
if (upBtn && upBtn.disabled) return;
|
||||
if (downBtn && downBtn.disabled) return;
|
||||
|
||||
var item = e.target.closest('li[data-plugin]');
|
||||
if (!item) return;
|
||||
|
||||
if (upBtn && item.previousElementSibling) {
|
||||
pluginList.insertBefore(item, item.previousElementSibling);
|
||||
markChanged();
|
||||
} else if (downBtn && item.nextElementSibling) {
|
||||
pluginList.insertBefore(item, item.nextElementSibling.nextElementSibling);
|
||||
}
|
||||
|
||||
updateArrows();
|
||||
updateFrontmatter();
|
||||
markChanged();
|
||||
});
|
||||
|
||||
// Plugin checkbox toggle
|
||||
pluginList.addEventListener('change', function (e) {
|
||||
if (e.target.classList.contains('plugin-checkbox')) {
|
||||
updateFrontmatter();
|
||||
markChanged();
|
||||
}
|
||||
updateArrows();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user