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>
This commit is contained in:
kantarciandClaude Fable 5.2 committed 2026-11-10 11:41:05 +01:00
1 parent 0d61aa0f22
commit ead47cc924
25 files changed
+437 -72

No files matched your search

+1 -1
View File
@@ -57,7 +57,7 @@
<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">
<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>