Fassung 1.7.0: verlässliche Installation, übersichtliche Verwaltung und bedienbare Bewegung
This commit is contained in:
1 parent
b164c4edfe
commit
495b26896e
55 files changed
+1632
-423
No files matched your search
@@ -1,14 +1,18 @@
|
||||
{% extends 'admin/shell.html.twig' %}
|
||||
{% set nav = 'pages' %}
|
||||
{% block title %}Seiten{% endblock %}
|
||||
{% block heading %}Seiten und Beiträge{% endblock %}
|
||||
{% block lead %}Wähle eine Seite, gestalte deinen Entwurf, veröffentliche, wenn alles passt. Entwürfe bleiben bis dahin privat.{% endblock %}
|
||||
{% set nav = contentType == 'post' ? 'posts' : 'pages' %}
|
||||
{% set plural = contentType == 'post' ? 'Beiträge' : 'Seiten' %}
|
||||
{% set singular = contentType == 'post' ? 'Beitrag' : 'Seite' %}
|
||||
{% block title %}{{ plural }}{% endblock %}
|
||||
{% block heading %}{{ plural }}{% endblock %}
|
||||
{% block scripts %}<script type="module" src="/assets/page-picker.js?v={{ kant_version() }}"></script>{% endblock %}
|
||||
{% block lead %}{{ plural }} suchen, bearbeiten und veröffentlichen. Entwürfe bleiben bis zur Veröffentlichung privat.{% endblock %}
|
||||
{% block content %}
|
||||
|
||||
{% if is_granted('ROLE_EDITOR') %}
|
||||
<details class="card"{% if app.flashes is not empty %} open{% endif %}>
|
||||
<summary>Neue Seite oder neuen Beitrag anlegen</summary>
|
||||
<summary>{{ contentType == 'post' ? 'Neuen Beitrag' : 'Neue Seite' }} anlegen</summary>
|
||||
<form action="{{ path('admin_create') }}" method="post" class="create-form card-body">
|
||||
<input type="hidden" name="_list_type" value="{{ contentType }}"><input type="hidden" name="_list_query" value="{{ query }}"><input type="hidden" name="_list_status" value="{{ status }}"><input type="hidden" name="_list_page" value="{{ result.page }}"><input type="hidden" name="_list_limit" value="{{ result.limit }}">
|
||||
<input type="hidden" name="_csrf_token" value="{{ csrf_token('pages') }}">
|
||||
<div class="fields">
|
||||
<div>
|
||||
@@ -21,36 +25,33 @@
|
||||
<input id="new-slug" name="slug" maxlength="80" pattern="[a-z0-9]+(-[a-z0-9]+)*" autocomplete="off" aria-describedby="new-slug-help">
|
||||
<p class="field-help" id="new-slug-help">Kleinbuchstaben, Ziffern und Bindestriche, zum Beispiel <code>ueber-uns</code>. Leer lassen, um sie aus dem Titel zu bilden.</p>
|
||||
</div>
|
||||
<input type="hidden" id="new-type" name="type" value="{{ contentType }}">
|
||||
{% if contentType == 'post' %}
|
||||
<div>
|
||||
<label for="new-type">Art</label>
|
||||
<select id="new-type" name="type">
|
||||
<option value="page">Seite</option>
|
||||
<option value="post">Beitrag</option>
|
||||
</select>
|
||||
<p class="field-help">Beiträge sind für Blogartikel gedacht und haben keine Unterseiten.</p>
|
||||
</div>
|
||||
<div>
|
||||
<label for="new-layout">Aufbau (nur für Beiträge)</label>
|
||||
<label for="new-layout">Beitragsvorlage</label>
|
||||
<select id="new-layout" name="layout">
|
||||
{% for key, layout in postLayouts %}<option value="{{ key }}"{{ key == 'bildkopf' ? ' selected' : '' }}>{{ layout.name }}</option>{% endfor %}
|
||||
</select>
|
||||
<p class="field-help">{% for key, layout in postLayouts %}<strong>{{ layout.name }}:</strong> {{ layout.description }}{% if not loop.last %} <br>{% endif %}{% endfor %} Jeder Block lässt sich danach ändern.</p>
|
||||
</div>
|
||||
<div>
|
||||
<label for="new-parent">Übergeordnete Seite</label>
|
||||
<select id="new-parent" name="parent_id">
|
||||
<option value="">— keine, direkt unter der Startseite —</option>
|
||||
{% for parent in parents %}<option value="{{ parent.id }}">{{ parent.title }} (/{{ parent.path }})</option>{% endfor %}
|
||||
</select>
|
||||
<p class="field-help">Bestimmt die Adresse, zum Beispiel <code>/leistungen/webdesign</code>.</p>
|
||||
</div>
|
||||
{% else %}
|
||||
{% include 'admin/content-picker.html.twig' with {id: 'new-parent', name: 'parent_id', label: 'Übergeordnete Seite (optional)', parents: true} %}
|
||||
{% endif %}
|
||||
</div>
|
||||
<button class="primary" type="submit">Anlegen und bearbeiten</button>
|
||||
</form>
|
||||
</details>
|
||||
{% endif %}
|
||||
|
||||
<div class="section-head"><h2>Alle Seiten <span class="count">{{ pages|length }}</span></h2><span class="muted">Untergeordnete Seiten stehen eingerückt.</span></div>
|
||||
<form method="get" action="{{ path(listRoute) }}" class="list-toolbar" role="search">
|
||||
<div class="list-search"><label for="page-search">{{ plural }} durchsuchen</label><input id="page-search" type="search" name="q" value="{{ query }}" placeholder="Titel, Adresse oder Inhalt …"></div>
|
||||
<div><label for="page-status">Status</label><select id="page-status" name="status">{% for value, label in {all: 'Alle aktiven', draft: 'Entwürfe', published: 'Veröffentlicht', changed: 'Entwurf geändert', trash: 'Papierkorb'} %}<option value="{{ value }}"{{ status == value ? ' selected' : '' }}>{{ label }}</option>{% endfor %}</select></div>
|
||||
<div><label for="page-limit">Pro Seite</label><select id="page-limit" name="limit">{% for size in [20, 50] %}<option value="{{ size }}"{{ result.limit == size ? ' selected' : '' }}>{{ size }}</option>{% endfor %}</select></div>
|
||||
<button class="secondary" type="submit">Anwenden</button>
|
||||
{% if query or status != 'all' %}<a class="text-button" href="{{ path(listRoute) }}">Zurücksetzen</a>{% endif %}
|
||||
</form>
|
||||
<div class="section-head"><h2>{{ status == 'trash' ? 'Papierkorb' : plural }} <span class="count">{{ result.total }}</span></h2><span class="muted">{{ result.total ? (result.page - 1) * result.limit + 1 : 0 }}–{{ min(result.page * result.limit, result.total) }} von {{ result.total }}</span></div>
|
||||
{% include 'admin/pager.html.twig' with {route: listRoute, params: {q: query, status: status, limit: result.limit}, previousLabel: 'Zurück', nextLabel: 'Weiter', label: 'Ergebnisseiten oben'} %}
|
||||
<div class="rows">
|
||||
{% for page in pages %}
|
||||
{# Indentation by class, not by style attribute: the administration forbids inline styles, so
|
||||
@@ -85,7 +86,8 @@
|
||||
<div class="sheet-part">
|
||||
<h4>{{ page.type == 'post' ? 'Beitragsdaten' : 'Seitendaten' }}</h4>
|
||||
<form action="{{ path('admin_post_meta', {id: page.id}) }}" method="post">
|
||||
<input type="hidden" name="_csrf_token" value="{{ csrf_token('pages') }}">
|
||||
<input type="hidden" name="_list_type" value="{{ contentType }}"><input type="hidden" name="_list_query" value="{{ query }}"><input type="hidden" name="_list_status" value="{{ status }}"><input type="hidden" name="_list_page" value="{{ result.page }}"><input type="hidden" name="_list_limit" value="{{ result.limit }}">
|
||||
<input type="hidden" name="_csrf_token" value="{{ csrf_token('pages') }}">
|
||||
<input type="hidden" name="expectedVersion" value="{{ page.version }}">
|
||||
<div class="fields">
|
||||
<div>
|
||||
@@ -143,7 +145,8 @@
|
||||
<div class="sheet-part">
|
||||
<h4>Adresse</h4>
|
||||
<form action="{{ path('admin_move', {id: page.id}) }}" method="post">
|
||||
<input type="hidden" name="_csrf_token" value="{{ csrf_token('pages') }}">
|
||||
<input type="hidden" name="_list_type" value="{{ contentType }}"><input type="hidden" name="_list_query" value="{{ query }}"><input type="hidden" name="_list_status" value="{{ status }}"><input type="hidden" name="_list_page" value="{{ result.page }}"><input type="hidden" name="_list_limit" value="{{ result.limit }}">
|
||||
<input type="hidden" name="_csrf_token" value="{{ csrf_token('pages') }}">
|
||||
<input type="hidden" name="expectedVersion" value="{{ page.version }}">
|
||||
<div class="fields">
|
||||
<div>
|
||||
@@ -151,13 +154,7 @@
|
||||
<input id="slug-{{ page.id }}" name="slug" maxlength="80" required value="{{ page.slug }}" pattern="[a-z0-9]+(-[a-z0-9]+)*">
|
||||
</div>
|
||||
<div>
|
||||
<label for="parent-{{ page.id }}">Übergeordnete Seite</label>
|
||||
<select id="parent-{{ page.id }}" name="parent_id">
|
||||
<option value="">— keine, direkt unter der Startseite —</option>
|
||||
{% for parent in parents|filter(candidate => candidate.id != page.id) %}
|
||||
<option value="{{ parent.id }}"{{ page.parent_id == parent.id ? ' selected' : '' }}>{{ parent.title }} (/{{ parent.path }})</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
{% include 'admin/content-picker.html.twig' with {id: 'parent-' ~ page.id, name: 'parent_id', label: 'Übergeordnete Seite (optional)', parents: true, selected: parentChoices[page.parent_id]|default(null)} %}
|
||||
<p class="field-help">Unterseiten ziehen mit. Von jeder alten Adresse wird dauerhaft weitergeleitet.</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -171,7 +168,8 @@
|
||||
<h4>Kopf- und Fußbereich</h4>
|
||||
<p>Standard ist der gemeinsame Bereich. „Kein Bereich“ liefert die Seite ohne Kopf beziehungsweise Fuß aus – für eine Landingpage ohne Navigation. Weitere Bereiche legst du unter Bereiche an.</p>
|
||||
<form action="{{ path('admin_page_areas', {id: page.id}) }}" method="post">
|
||||
<input type="hidden" name="_csrf_token" value="{{ csrf_token('pages') }}">
|
||||
<input type="hidden" name="_list_type" value="{{ contentType }}"><input type="hidden" name="_list_query" value="{{ query }}"><input type="hidden" name="_list_status" value="{{ status }}"><input type="hidden" name="_list_page" value="{{ result.page }}"><input type="hidden" name="_list_limit" value="{{ result.limit }}">
|
||||
<input type="hidden" name="_csrf_token" value="{{ csrf_token('pages') }}">
|
||||
<input type="hidden" name="expectedVersion" value="{{ page.version }}">
|
||||
<div class="fields">
|
||||
{% for kind, label in {header: 'Kopfbereich', footer: 'Fußbereich'} %}
|
||||
@@ -196,7 +194,8 @@
|
||||
<div class="sheet-part">
|
||||
<h4>Veröffentlichung planen</h4>
|
||||
<form action="{{ path('admin_schedule', {id: page.id}) }}" method="post">
|
||||
<input type="hidden" name="_csrf_token" value="{{ csrf_token('pages') }}">
|
||||
<input type="hidden" name="_list_type" value="{{ contentType }}"><input type="hidden" name="_list_query" value="{{ query }}"><input type="hidden" name="_list_status" value="{{ status }}"><input type="hidden" name="_list_page" value="{{ result.page }}"><input type="hidden" name="_list_limit" value="{{ result.limit }}">
|
||||
<input type="hidden" name="_csrf_token" value="{{ csrf_token('pages') }}">
|
||||
<input type="hidden" name="expectedVersion" value="{{ page.version }}">
|
||||
<div class="field">
|
||||
<label for="publish-{{ page.id }}">Veröffentlichen am</label>
|
||||
@@ -214,7 +213,8 @@
|
||||
<div class="sheet-actions">
|
||||
{% if is_granted('ROLE_EDITOR') and page.path != 'home' %}
|
||||
<form action="{{ path('admin_trash', {id: page.id}) }}" method="post">
|
||||
<input type="hidden" name="_csrf_token" value="{{ csrf_token('pages') }}">
|
||||
<input type="hidden" name="_list_type" value="{{ contentType }}"><input type="hidden" name="_list_query" value="{{ query }}"><input type="hidden" name="_list_status" value="{{ status }}"><input type="hidden" name="_list_page" value="{{ result.page }}"><input type="hidden" name="_list_limit" value="{{ result.limit }}">
|
||||
<input type="hidden" name="_csrf_token" value="{{ csrf_token('pages') }}">
|
||||
<input type="hidden" name="expectedVersion" value="{{ page.version }}">
|
||||
<button class="secondary" type="submit">In den Papierkorb</button>
|
||||
</form>
|
||||
@@ -224,7 +224,8 @@
|
||||
offered this. #}
|
||||
<div class="delete-panel">
|
||||
<form action="{{ path('admin_delete', {id: page.id}) }}" method="post">
|
||||
<input type="hidden" name="_csrf_token" value="{{ csrf_token('pages') }}">
|
||||
<input type="hidden" name="_list_type" value="{{ contentType }}"><input type="hidden" name="_list_query" value="{{ query }}"><input type="hidden" name="_list_status" value="{{ status }}"><input type="hidden" name="_list_page" value="{{ result.page }}"><input type="hidden" name="_list_limit" value="{{ result.limit }}">
|
||||
<input type="hidden" name="_csrf_token" value="{{ csrf_token('pages') }}">
|
||||
<input type="hidden" name="expectedVersion" value="{{ page.version }}">
|
||||
<button class="subtle danger-text" type="submit">Endgültig löschen</button>
|
||||
</form>
|
||||
@@ -239,12 +240,12 @@
|
||||
{% endif %}
|
||||
</article>
|
||||
{% else %}
|
||||
<div class="empty"><h3>Noch keine Seiten vorhanden.</h3><p>Lege oben deine erste Seite an.</p></div>
|
||||
{% if status != 'trash' %}<div class="empty"><h3>{{ result.total == 0 ? 'Keine passenden Einträge.' : '' }}</h3>{% if result.total == 0 %}<p>{{ query or status != 'all' ? 'Ändere die Suche oder den Statusfilter.' : 'Lege oben deinen ersten Inhalt an.' }}</p>{% endif %}</div>{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
{% if trash is not empty %}
|
||||
<div class="section-head"><h2>Papierkorb <span class="count">{{ trash|length }}</span></h2><span class="muted">Nicht öffentlich erreichbar, alle Fassungen erhalten.</span></div>
|
||||
|
||||
<div class="rows">
|
||||
{% for entry in trash %}
|
||||
<article class="row">
|
||||
@@ -256,7 +257,8 @@
|
||||
{% if is_granted('ROLE_EDITOR') %}
|
||||
<div class="row-actions">
|
||||
<form action="{{ path('admin_restore_page', {id: entry.id}) }}" method="post">
|
||||
<input type="hidden" name="_csrf_token" value="{{ csrf_token('pages') }}">
|
||||
<input type="hidden" name="_list_type" value="{{ contentType }}"><input type="hidden" name="_list_query" value="{{ query }}"><input type="hidden" name="_list_status" value="{{ status }}"><input type="hidden" name="_list_page" value="{{ result.page }}"><input type="hidden" name="_list_limit" value="{{ result.limit }}">
|
||||
<input type="hidden" name="_csrf_token" value="{{ csrf_token('pages') }}">
|
||||
<button class="secondary" type="submit">Wiederherstellen</button>
|
||||
</form>
|
||||
</div>
|
||||
@@ -266,5 +268,6 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<p class="footnote">KantSites · Arbeitsstand</p>
|
||||
{% if status == 'trash' and trash is empty %}<div class="empty"><h3>Der Papierkorb ist leer.</h3></div>{% endif %}
|
||||
{% include 'admin/pager.html.twig' with {route: listRoute, params: {q: query, status: status, limit: result.limit}, previousLabel: 'Zurück', nextLabel: 'Weiter', label: 'Ergebnisseiten unten'} %}
|
||||
{% endblock %}
|
||||
Reference in new issue
Block a user