From 73450a17c1f81364f76af1fc6023844d23750806 Mon Sep 17 00:00:00 2001 From: Edwin Noorlander Date: Tue, 11 Aug 2026 17:22:41 +0200 Subject: [PATCH] Plugin system: content vs system types, sidebar-aware UI, arrow visibility - plugin.json type field: 'content' (sidebar) or 'system' (API only) - Content-edit: label 'Plugins', hide section if layout has no sidebar - Content-edit: disable checkboxes when no sidebar layout selected - Content-edit: hide up arrow on first item, down arrow on last item - PluginManager: isPluginViewable() checks type=system -> not viewable - Admin plugins page: show Content/Systeem type badge - HTMLBlock: add plugin.json with type=content - Navigation: add type=content to config --- .../default/views/pages/content-edit.twig | 55 +++++++++++++------ admin/theme/default/views/pages/plugins.twig | 9 ++- cms/core/plugin/PluginManager.php | 8 ++- plugins/HTMLBlock/plugin.json | 7 +++ plugins/Navigation/Navigation.php | 1 + plugins/Navigation/plugin.json | 3 +- public/admin.php | 21 ++++++- 7 files changed, 80 insertions(+), 24 deletions(-) create mode 100644 plugins/HTMLBlock/plugin.json diff --git a/admin/theme/default/views/pages/content-edit.twig b/admin/theme/default/views/pages/content-edit.twig index c379d89..0fe0726 100644 --- a/admin/theme/default/views/pages/content-edit.twig +++ b/admin/theme/default/views/pages/content-edit.twig @@ -28,16 +28,16 @@ {% if availablePlugins is not empty %} -
- +
+
    {% for plugin in selectedPlugins %}
  • - +
    -
    +
    @@ -47,10 +47,10 @@ {% if plugin not in selectedPlugins %}
  • - +
    -
    +
    @@ -88,8 +88,10 @@ document.addEventListener('DOMContentLoaded', function () { var backBtn = document.getElementById('back-btn'); var filenameInput = document.getElementById('filename'); var layoutSelect = document.getElementById('layout'); + var pluginSection = document.getElementById('plugin-section'); if (!backBtn) return; + var sidebarLayouts = {{ sidebarLayouts|json_encode|raw }}; var changed = false; function markChanged() { @@ -104,11 +106,36 @@ 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 + 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' : ''; + }); + } + // 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(); + if (!editor) return; var cm = window.codeMirrorEditor; @@ -117,7 +144,6 @@ document.addEventListener('DOMContentLoaded', function () { // Check if frontmatter exists var fmMatch = content.match(/^---\n([\s\S]*?)\n---/); if (fmMatch) { - // Update existing layout line in frontmatter var frontmatter = fmMatch[1]; if (/^layout:\s*.+$/m.test(frontmatter)) { frontmatter = frontmatter.replace(/^layout:\s*.+$/m, 'layout: ' + newLayout); @@ -126,7 +152,6 @@ document.addEventListener('DOMContentLoaded', function () { } content = content.replace(/^---\n([\s\S]*?)\n---/, '---\n' + frontmatter + '\n---'); } else { - // No frontmatter yet — add one content = '---\nlayout: ' + newLayout + '\n---\n\n' + content; } @@ -160,17 +185,13 @@ document.addEventListener('DOMContentLoaded', function () { pluginList.insertBefore(item, item.nextElementSibling.nextElementSibling); markChanged(); } + updateArrows(); }); - - // On form submit, reorder the checkboxes to match the visual order - var form = document.getElementById('editor-form'); - if (form) { - form.addEventListener('submit', function () { - // The DOM order of the
  • elements already determines the form submission order - // because the checkboxes are inside the
  • elements - }); - } } + + // Initialize + updatePluginVisibility(); + updateArrows(); }); {% endblock %} diff --git a/admin/theme/default/views/pages/plugins.twig b/admin/theme/default/views/pages/plugins.twig index 94b0204..83f5657 100644 --- a/admin/theme/default/views/pages/plugins.twig +++ b/admin/theme/default/views/pages/plugins.twig @@ -16,13 +16,16 @@
    {{ plugin.name|default(plugin.name) }} - {{ plugin.enabled ? 'Actief' : 'Inactief' }} + + {% if plugin.type == 'system' %}Systeem{% else %}Content{% endif %} + {{ plugin.enabled ? 'Actief' : 'Inactief' }} +

    {{ plugin.description|default('Geen beschrijving') }}

    - {% if plugin.version %}v{{ plugin.version }}{% endif %} - {% if plugin.author %}{{ plugin.author }}{% endif %} + {% if plugin.version %}v{{ plugin.version }}{% endif %} + {% if plugin.author %}{{ plugin.author }}{% endif %}