- Content bestanden met dezelfde naam maar ander type (md/php/html) worden correct geserveerd: URL met extensie opent dat bestand, URL zonder extensie valt terug op md > php > html (resolveContentByType helper) - Admin content editor accepteert bestanden met dezelfde naam (ander type); preview-knop linkt per extensie - Frontend navigatie/directory listing/search tonen elk bestandstype apart - getAllPages() array structuur gewijzigd naar list van ['path','title','type'] met type 'md'/'php'/'html'/'folder' - Verberg-prefix logica: _ is geen verberg-prefix meer, alleen . (en -); admin toont wél alle . bestanden/mappen - ContentAPI getPage()/pageExists() respecteren expliciete extensie - Handleiding content-api.md (NL+EN) herschreven - File-tree unificatie: _file-tree.twig + _editor-styles.twig includes - Versie verhoogd naar 2.6.3
164 lines
9.0 KiB
Twig
164 lines
9.0 KiB
Twig
{% extends "layouts/admin.twig" %}
|
|
|
|
{% block title %}{{ ta.theme_edit|default('Thema bewerken: ') }}{{ themeName }} - {{ ta.admin_title|default('CodePress Admin') }}{% endblock %}
|
|
|
|
{% block extra_css %}
|
|
<link rel="stylesheet" href="/admin/assets/codemirror/codemirror.min.css">
|
|
<link rel="stylesheet" href="/admin/assets/css/editor.css">
|
|
{% include 'pages/_editor-styles.twig' %}
|
|
<style>
|
|
.theme-scss-status { font-size: .75rem; }
|
|
</style>
|
|
{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="d-flex justify-content-between align-items-center mb-4 flex-wrap gap-2">
|
|
<h2 class="mb-0"><i class="bi bi-pencil"></i> {{ ta.theme_edit|default('Thema bewerken: ') }}{{ themeName }}</h2>
|
|
<div class="d-flex gap-2 flex-wrap">
|
|
{% if hasScss %}
|
|
<form method="POST" action="/admin/theme-scss" class="d-inline" onsubmit="return confirm('{{ ta.compile_scss_confirm|default('SCSS compileren? Dit overschrijft assets/css_compiled/theme.css.') }}')">
|
|
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
|
|
<input type="hidden" name="theme" value="{{ themeName }}">
|
|
<button type="submit" class="btn btn-outline-success btn-sm" title="{{ ta.compile_scss|default('SCSS compileren') }}">
|
|
<i class="bi bi-palette"></i> {{ ta.compile_scss|default('SCSS compileren') }}
|
|
{% if scssCompiled %}<span class="badge bg-success ms-1">{{ ta.scss_ok|default('up-to-date') }}</span>{% else %}<span class="badge bg-warning text-dark ms-1">{{ ta.scss_stale|default('verouderd') }}</span>{% endif %}
|
|
</button>
|
|
</form>
|
|
{% endif %}
|
|
<button type="button" class="btn btn-outline-success btn-sm" data-bs-toggle="collapse" data-bs-target="#themeUploadForm">
|
|
<i class="bi bi-cloud-upload"></i> {{ ta.upload|default('Upload') }}
|
|
</button>
|
|
<button type="button" class="btn btn-outline-primary btn-sm" data-bs-toggle="modal" data-bs-target="#newFileModal">
|
|
<i class="bi bi-file-earmark-plus"></i> {{ ta.theme_new_file|default('Nieuw bestand') }}
|
|
</button>
|
|
<a href="/admin/theme" class="btn btn-outline-secondary btn-sm">
|
|
<i class="bi bi-arrow-left"></i> {{ ta.back|default('Terug') }}
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
{# Upload form (collapsed by default) #}
|
|
<div class="collapse mb-3" id="themeUploadForm">
|
|
<div class="card shadow-sm">
|
|
<div class="card-body">
|
|
<form method="POST" action="/admin/theme-file-upload" enctype="multipart/form-data">
|
|
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
|
|
<input type="hidden" name="theme" value="{{ themeName }}">
|
|
<input type="hidden" name="dir" value="" id="themeUploadDir">
|
|
<div class="mb-3">
|
|
<label for="themeUploadFile" class="form-label">{{ ta.select_files|default('Bestanden selecteren') }}</label>
|
|
<input type="file" class="form-control" id="themeUploadFile" name="file[]" multiple accept="image/jpeg,image/png,image/gif,image/webp,image/svg+xml,application/pdf,application/zip,video/mp4,video/webm,audio/mpeg,audio/wav,.css,.scss,.js,.json,.html,.md,.twig,.woff,.woff2,.ttf">
|
|
<small class="form-text text-muted">{{ ta.theme_upload_help|default('Bestanden worden geüpload naar assets/ van dit thema. Toegestaan: afbeeldingen, video, audio, PDF, ZIP, CSS, SCSS, JS, JSON, HTML, MD, TWIG, fonts.') }}</small>
|
|
</div>
|
|
<button type="submit" class="btn btn-success">
|
|
<i class="bi bi-cloud-upload"></i> {{ ta.upload_to_folder|default('Uploaden') }}
|
|
</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="editor-layout">
|
|
{# File tree sidebar (shared partial) #}
|
|
{% include 'pages/_file-tree.twig' with {
|
|
'files': files,
|
|
'relFile': relFile,
|
|
'editableExts': editableExts,
|
|
'csrf_token': csrf_token,
|
|
'treeIdPrefix': 'theme-tree',
|
|
'treeHeader': ta.theme_files|default('Thema bestanden'),
|
|
'treeEmptyText': ta.theme_no_files|default('Geen bestanden gevonden.'),
|
|
'treeRouteBase': '/admin/theme-edit',
|
|
'treeRouteParams': 'theme=' ~ themeName|url_encode ~ '&',
|
|
'treeDeleteRoute': '/admin/theme-file-delete',
|
|
'treeDeleteName': 'theme',
|
|
'treeDeleteValue': themeName,
|
|
'treeMoveRoute': '/admin/theme-file-move',
|
|
'treeMoveParams': 'theme=' ~ themeName|url_encode ~ '&',
|
|
'treeDirActions': false,
|
|
'treeHideActionsFor': ['theme.json'],
|
|
} %}
|
|
|
|
{# Editor main panel #}
|
|
<div class="editor-main">
|
|
{% if relFile %}
|
|
<nav aria-label="breadcrumb" class="mb-2">
|
|
<ol class="breadcrumb mb-0">
|
|
<li class="breadcrumb-item"><i class="bi bi-folder2-open"></i> {{ themeName }}</li>
|
|
{% set crumbPath = '' %}
|
|
{% set parts = relFile|split('/') %}
|
|
{% for part in parts %}
|
|
{% set crumbPath = crumbPath ? crumbPath ~ '/' ~ part : part %}
|
|
{% if loop.last %}
|
|
<li class="breadcrumb-item active" aria-current="page">{{ part }}</li>
|
|
{% else %}
|
|
<li class="breadcrumb-item"><a href="/admin/theme-edit?theme={{ themeName|url_encode }}&file={{ crumbPath|url_encode }}">{{ part }}</a></li>
|
|
{% endif %}
|
|
{% endfor %}
|
|
</ol>
|
|
</nav>
|
|
{% endif %}
|
|
|
|
{% if isEditable %}
|
|
<form method="POST" action="/admin/theme-edit?theme={{ themeName|url_encode }}&file={{ relFile|url_encode }}" id="editor-form">
|
|
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
|
|
<div class="card shadow-sm">
|
|
<div class="card-body">
|
|
<div class="editor-toolbar" id="editor-toolbar"></div>
|
|
<div class="editor-wrapper">
|
|
<textarea name="content" id="editor-textarea" data-ext="{{ fileExt }}">{{ fileContent }}</textarea>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="d-flex gap-2 mt-3">
|
|
<button type="submit" class="btn btn-primary">
|
|
<i class="bi bi-check-lg"></i> {{ ta.save|default('Opslaan') }}
|
|
</button>
|
|
<a href="/admin/theme" class="btn btn-outline-secondary">{{ ta.cancel|default('Annuleren') }}</a>
|
|
</div>
|
|
</form>
|
|
{% else %}
|
|
<div class="card shadow-sm">
|
|
<div class="card-body text-center py-5 text-muted">
|
|
<i class="bi bi-file-earmark-slash display-6 d-block mb-2"></i>
|
|
{% if relFile %}
|
|
{{ ta.theme_not_editable|default('Dit bestandstype kan niet in de editor bewerkt worden.') }}
|
|
{% else %}
|
|
{{ ta.theme_select_file|default('Selecteer een bestand uit de zijbalk om te bewerken.') }}
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
|
|
{# New file modal #}
|
|
<div class="modal fade" id="newFileModal" tabindex="-1" aria-labelledby="newFileModalLabel" aria-hidden="true">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content">
|
|
<form method="POST" action="/admin/theme-edit?theme={{ themeName|url_encode }}">
|
|
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
|
|
<input type="hidden" name="action" value="new_file">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title" id="newFileModalLabel"><i class="bi bi-file-earmark-plus"></i> {{ ta.theme_new_file_title|default('Nieuw bestand aanmaken') }}</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="mb-3">
|
|
<label for="newFilenameInput" class="form-label">{{ ta.theme_file_path|default('Bestandspad binnen thema') }}</label>
|
|
<input type="text" class="form-control" id="newFilenameInput" name="new_filename" placeholder="Bijv. partials/header.twig of assets/scss/_variables.scss" required autofocus>
|
|
<div class="form-text">{{ ta.theme_file_path_help|default('Alleen letters, cijfers, punten, underscores, streepjes en slashes. Submappen worden automatisch aangemaakt. Toegestaan: twig, json, scss, css, js, html, md, php.') }}</div>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">{{ ta.cancel|default('Annuleren') }}</button>
|
|
<button type="submit" class="btn btn-primary"><i class="bi bi-check-lg"></i> {{ ta.create|default('Aanmaken') }}</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endblock %}
|
|
|
|
{% block extra_js %}
|
|
{% endblock %} |