Umut hat den Namen festgelegt: aus dem Arbeitstitel "Kant CMS" wird KantSites. Geändert in allen Seitentiteln der Verwaltung, im Wortmarken-Schriftzug von Anmeldung und Seitenleiste, in den Fußzeilen, in den Demoinhalten für eine frische Installation, in package.json, .claude/launch.json und der Dokumentation. Die Bezeichnung der Website in der Datenbank heißt jetzt ebenfalls KantSites. Nicht angefasst: die bereits gespeicherten Demoinhalte der lokalen Installation. Titel wie "Die Grundlage · Kant CMS" und der Text im Kopfbereich sind Inhalt, nicht Systemname - die gehören in den Editor, nicht in ein Skript, das Revisionen umschreibt. 219 PHP-Tests / 881 Assertions grün, Playwright-Editortest grün. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
95 lines
6.2 KiB
Twig
95 lines
6.2 KiB
Twig
{% extends 'admin/shell.html.twig' %}
|
||
{% set nav = 'forms' %}
|
||
{% block title %}Formulare{% endblock %}
|
||
{% block heading %}Formulare{% endblock %}
|
||
{% block lead %}Felder, Empfänger und Einwilligungstext werden hier gepflegt. Auf einer Seite steht nur ein Formularblock mit der Adresse – so kann ein gespeicherter Seiteninhalt niemals ändern, wohin eine Anfrage geht.{% endblock %}
|
||
{% block content %}
|
||
{% for form in forms|merge([null]) %}
|
||
{% set new = form is null %}
|
||
{% set rows = new ? [] : form.fields %}
|
||
<section class="stack-section">
|
||
<div class="section-head">
|
||
<h2>{{ new ? 'Neues Formular' : form.name }}{% if not new %} <span class="count">{{ form.fields|length }} Felder</span>{% endif %}</h2>
|
||
{% if not new %}<span class="muted">Block-Adresse <code>{{ form.slug }}</code></span>{% endif %}
|
||
</div>
|
||
<form action="{{ path('admin_form_save', {slug: new ? 'neu' : form.slug}) }}" method="post" class="form-def card card-body">
|
||
<input type="hidden" name="_csrf_token" value="{{ csrf_token('forms') }}">
|
||
<input type="hidden" name="expectedVersion" value="{{ new ? 0 : form.version }}">
|
||
<div class="fields">
|
||
<div>
|
||
<label for="name-{{ loop.index }}">Name</label>
|
||
<input id="name-{{ loop.index }}" name="name" maxlength="120" required value="{{ new ? '' : form.name }}">
|
||
</div>
|
||
{% if new %}
|
||
<div>
|
||
<label for="slug-new">Adresse</label>
|
||
<input id="slug-new" name="slug" maxlength="80" pattern="[a-z0-9]+(-[a-z0-9]+)*" required placeholder="kontakt">
|
||
<p class="field-help">Wird im Formularblock eingetragen.</p>
|
||
</div>
|
||
{% endif %}
|
||
<div>
|
||
<label for="recipient-{{ loop.index }}">Empfänger</label>
|
||
<input id="recipient-{{ loop.index }}" name="recipient" type="email" required value="{{ new ? '' : form.settings.recipient }}">
|
||
</div>
|
||
<div>
|
||
<label for="subject-{{ loop.index }}">Betreff</label>
|
||
<input id="subject-{{ loop.index }}" name="subject" maxlength="160" value="{{ new ? '' : form.settings.subject }}">
|
||
</div>
|
||
<div>
|
||
<label for="reply-{{ loop.index }}">Antwortadresse aus Feld</label>
|
||
<input id="reply-{{ loop.index }}" name="replyToField" maxlength="32" value="{{ new ? '' : form.settings.replyToField }}" placeholder="email">
|
||
<p class="field-help">Technischer Name eines E-Mail-Feldes. Dann lässt sich direkt antworten.</p>
|
||
</div>
|
||
<div>
|
||
<label for="success-{{ loop.index }}">Meldung nach dem Absenden</label>
|
||
<input id="success-{{ loop.index }}" name="success" maxlength="300" value="{{ new ? '' : form.settings.success }}">
|
||
</div>
|
||
</div>
|
||
|
||
<table class="table field-table">
|
||
<caption class="visually-hidden">Felder des Formulars. Eine Beschriftung zu leeren entfernt das Feld.</caption>
|
||
<thead><tr><th scope="col">Technischer Name</th><th scope="col">Typ</th><th scope="col">Beschriftung</th><th scope="col">Pflicht</th><th scope="col">Hilfetext</th><th scope="col">Optionen</th></tr></thead>
|
||
<tbody>
|
||
{% for row in rows|merge([{name: '', type: 'text', label: '', required: false, help: '', options: []}, {name: '', type: 'text', label: '', required: false, help: '', options: []}]) %}
|
||
{% set n = loop.index0 %}
|
||
<tr{% if row.label == '' %} class="table-new"{% endif %}>
|
||
<td><input name="fields[{{ n }}][name]" maxlength="32" value="{{ row.name }}" pattern="[a-z][a-z0-9_]*" aria-label="Technischer Name von Feld {{ n + 1 }}" placeholder="vorname"></td>
|
||
<td>
|
||
<select name="fields[{{ n }}][type]" aria-label="Typ von Feld {{ n + 1 }}">
|
||
{% for value, label in types %}<option value="{{ value }}"{{ row.type == value ? ' selected' : '' }}>{{ label }}</option>{% endfor %}
|
||
</select>
|
||
</td>
|
||
<td><input name="fields[{{ n }}][label]" maxlength="120" value="{{ row.label }}" aria-label="Beschriftung von Feld {{ n + 1 }}"></td>
|
||
<td class="check-cell"><input type="checkbox" name="fields[{{ n }}][required]" value="1"{{ row.required ? ' checked' : '' }} aria-label="Feld {{ n + 1 }} ist ein Pflichtfeld"></td>
|
||
<td><input name="fields[{{ n }}][help]" maxlength="200" value="{{ row.help }}" aria-label="Hilfetext von Feld {{ n + 1 }}"></td>
|
||
<td><input name="fields[{{ n }}][options]" maxlength="500" value="{{ row.options|join(', ') }}" aria-label="Optionen von Feld {{ n + 1 }}" placeholder="nur bei Auswahl"></td>
|
||
</tr>
|
||
{% endfor %}
|
||
</tbody>
|
||
</table>
|
||
<p class="field-help">Ein Einwilligungsfeld ist immer ein Pflichtfeld; der Zeitpunkt der Einwilligung wird mitgespeichert. Optionen einer Auswahl durch Komma trennen. Die letzten beiden Zeilen sind für neue Felder.</p>
|
||
<button class="primary" type="submit">{{ new ? 'Formular anlegen' : 'Formular speichern' }}</button>
|
||
</form>
|
||
</section>
|
||
{% endfor %}
|
||
|
||
<div class="section-head"><h2>Einsendungen <span class="count">{{ submissions|length }}</span></h2><span class="muted">Die neuesten 50.</span></div>
|
||
{% if submissions is empty %}
|
||
<div class="empty"><h3>Noch keine Einsendungen.</h3><p>Hier erscheinen eingegangene Nachrichten, auch wenn der E-Mail-Versand fehlschlägt.</p></div>
|
||
{% else %}
|
||
<div class="rows">
|
||
{% for entry in submissions %}
|
||
<article class="row row-top">
|
||
<div class="row-main">
|
||
<h3>{{ entry.form }}</h3>
|
||
<p>{{ entry.createdAt|date('d.m.Y H:i') }} UTC{% if entry.consentAt %} · Einwilligung {{ entry.consentAt|date('d.m.Y H:i') }}{% endif %}</p>
|
||
<dl class="submission-data">{% for key, value in entry.data %}<dt>{{ key }}</dt><dd>{{ value }}</dd>{% endfor %}</dl>
|
||
</div>
|
||
<span class="pill {{ entry.delivered ? 'pill-live' : 'pill-off' }}">{{ entry.delivered ? 'Versendet' : 'Nicht versendet' }}</span>
|
||
</article>
|
||
{% endfor %}
|
||
</div>
|
||
{% endif %}
|
||
<p class="footnote">KantSites · Arbeitsstand</p>
|
||
{% endblock %}
|