Files
KantSites/templates/admin/partials.html.twig
T
kantarciandClaude Fable 5.2 ead47cc924 Keep old pages readable, detect stale settings writes, make backups honest
- Own CSS is parsed on write only. A page whose stored CSS no longer
  passes a stricter rule answers 200 and opens in the editor; that one
  block loses its CSS. A document read several times in one request is
  validated once.
- Settings and theme refuse a write from an outdated form.
- A backup fails when a media file does not arrive completely and
  leaves no half directory behind; rotation counts intact backups only.
- The archive update takes its backup behind the maintenance page.
- A package import puts all media in place before removing the old
  ones, reports honestly when that fails and keeps a maintenance state
  that was already on.
- Restoring replaces the SQLite file in one move and points at pending
  migrations.
- Six irreversible actions ask first, in a dialog of the admin's own.
- Ctrl+S in the editor takes the field being typed in along; Delete
  no longer removes a block while a dialog is open.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
2026-11-10 11:41:05 +01:00

75 lines
4.6 KiB
Twig
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{% extends 'admin/shell.html.twig' %}
{% set nav = 'partials' %}
{% block title %}Bereiche{% endblock %}
{% block heading %}Kopf, Fuß und wiederverwendbare Sektionen{% endblock %}
{% block lead %}Alle drei sind Blockdokumente wie eine Seite und im selben Editor frei gestaltbar. Eine <strong>verknüpfte</strong> Sektion wird nicht kopiert: eine Änderung erreicht jede Seite, die sie einbindet.{% endblock %}
{% block content %}
{% if is_granted('ROLE_EDITOR') %}
<details class="card"{% if app.flashes is not empty %} open{% endif %}>
<summary>Neuen Bereich anlegen</summary>
<form action="{{ path('admin_partial_create') }}" method="post" class="create-form card-body">
<input type="hidden" name="_csrf_token" value="{{ csrf_token('partials') }}">
<div class="fields">
<div>
<label for="new-name">Name</label>
<input id="new-name" name="name" maxlength="120" required autocomplete="off">
</div>
<div>
<label for="new-kind">Art</label>
<select id="new-kind" name="kind">
{% for value, label in kinds %}<option value="{{ value }}"{{ value == 'section' ? ' selected' : '' }}>{{ label }}</option>{% endfor %}
</select>
<p class="field-help">Kopf- und Fußbereiche können je Seite zugewiesen werden. Sektionen lassen sich auf mehreren Seiten verknüpfen.</p>
</div>
<div>
<label for="new-slug">Adresse</label>
<input id="new-slug" name="slug" maxlength="80" pattern="[a-z0-9]+(-[a-z0-9]+)*" autocomplete="off">
<p class="field-help">Wird im Verknüpfungsblock eingetragen. Leer lassen, um sie aus dem Namen zu bilden.</p>
</div>
</div>
<button class="primary" type="submit">Anlegen und bearbeiten</button>
</form>
</details>
{% endif %}
<div class="section-head"><h2>Bereiche <span class="count">{{ partials|length }}</span></h2><span class="muted">Gespeicherte Änderungen sind sofort auf allen Seiten sichtbar.</span></div>
<div class="rows">
{% for partial in partials %}
<article class="row row-stack">
<div class="row-line">
<span class="row-icon" aria-hidden="true">{{ partial.kind == 'header' ? '▀' : (partial.kind == 'footer' ? '▄' : '▥') }}</span>
<div class="row-main">
<h3><a href="{{ path('admin_partial_editor', {id: partial.id}) }}">{{ partial.name }}</a></h3>
<p>{{ kinds[partial.kind] }}{% if partial.kind == 'section' %} · Adresse <code>{{ partial.slug }}</code>{% endif %}
{% if partial.kind == 'section' %}
· {% if partial.usedBy is empty %}<span>nirgends eingebunden</span>{% else %}eingebunden in {{ partial.usedBy|join(', ') }}{% endif %}
{% endif %}
</p>
</div>
<div class="row-actions">
<a class="secondary" href="{{ path('admin_partial_editor', {id: partial.id}) }}" aria-label="{{ partial.name }} bearbeiten">Bearbeiten <span aria-hidden="true">→</span></a>
</div>
</div>
{% if partial.kind == 'section' and is_granted('ROLE_EDITOR') %}
<details class="sheet">
<summary aria-label="Einstellungen von {{ partial.name }}">Einstellungen</summary>
<div class="sheet-body">
<div class="sheet-part">
<h4>Entfernen</h4>
<p>Entfernt „{{ partial.name }}“.{% if partial.usedBy is not empty %} <strong>Noch eingebunden in {{ partial.usedBy|join(', ') }}</strong> – dort erscheint danach nichts mehr.{% endif %}</p>
<form action="{{ path('admin_partial_delete', {id: partial.id}) }}" method="post" data-confirm-title="Sektion „{{ partial.name }}“ entfernen?" data-confirm-text="{% if partial.usedBy is not empty %}Sie ist noch eingebunden in {{ partial.usedBy|join(', ') }} – dort erscheint danach nichts mehr. {% endif %}Das lässt sich nicht rückgängig machen." data-confirm-label="Sektion entfernen" data-confirm-variant="danger">
<input type="hidden" name="_csrf_token" value="{{ csrf_token('partials') }}">
<button class="subtle danger-text" type="submit">Sektion entfernen</button>
</form>
</div>
</div>
</details>
{% endif %}
</article>
{% else %}
<div class="empty"><h3>Noch keine Bereiche.</h3><p>Ein frisches Setup legt Kopf- und Fußbereich automatisch an.</p></div>
{% endfor %}
</div>
<p class="footnote">KantSites · Arbeitsstand</p>
{% endblock %}