Rebuild DEEG as a fifth installation, add stepped forms and a plugin system, and clear the review backlog
Forms gained steps, conditions, image choices, number fields with units and a summary step; the DEEG price finder uses all of it. Plugins are manifest plus Twig: blocks, settings, containers, routes, presets and theme packs, switched per installation. The review backlog is done: archive pages render through the normal page pipeline, forms and post lists work inside areas and sections, repeated sections get their own ids, breakpoints and colours come from the palette, backup and update work on MySQL and lock each other out. The task worker no longer shortens a process that has no time limit: set_time_limit() sets the limit instead of extending it, which turned an unlimited CLI run into eighty seconds and killed the full test suite far away from the scheduler. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
66ff68abf8
commit
c8a8fa7460
74 files changed
+5352
-243
No files matched your search
@@ -40,19 +40,50 @@
|
||||
</div>
|
||||
<div data-field-options>
|
||||
<label for="{{ id }}-options">Optionen der Auswahl</label>
|
||||
<input id="{{ id }}-options" name="fields[{{ n }}][options]" maxlength="500" value="{{ row.options|join(', ') }}" placeholder="Beratung, Angebot, Sonstiges" data-field-options-input>
|
||||
<input id="{{ id }}-options" name="fields[{{ n }}][options]" maxlength="500" value="{{ row.options|default([])|join(', ') }}" placeholder="Beratung, Angebot, Sonstiges" data-field-options-input>
|
||||
<p class="field-help">Durch Komma trennen, mindestens zwei.</p>
|
||||
<div class="field-card-images" data-field-images>
|
||||
<label for="{{ id }}-images">Bild je Option</label>
|
||||
<textarea id="{{ id }}-images" name="fields[{{ n }}][images]" rows="2" data-field-images-input>{% for option, kennung in row.images|default({}) %}{{ option }} = {{ kennung }}
|
||||
{% endfor %}</textarea>
|
||||
<p class="field-help">Eine Zeile je Option: <code>Option = Kennung aus der Mediathek</code>. Sobald eine Option ein Bild hat, wird die Auswahl auf der Website zur Bildauswahl – anklickbare Karten statt Kästchen.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field-card-flags">
|
||||
<label class="check-label" for="{{ id }}-required"><input id="{{ id }}-required" type="checkbox" name="fields[{{ n }}][required]" value="1"{{ row.required ? ' checked' : '' }} data-field-required> Pflichtfeld</label>
|
||||
</div>
|
||||
<div class="field-card-number" data-field-number>
|
||||
<div>
|
||||
<label for="{{ id }}-min">Untergrenze</label>
|
||||
<input id="{{ id }}-min" name="fields[{{ n }}][min]" inputmode="decimal" value="{{ row.min|default('') }}" placeholder="0">
|
||||
</div>
|
||||
<div>
|
||||
<label for="{{ id }}-max">Obergrenze</label>
|
||||
<input id="{{ id }}-max" name="fields[{{ n }}][max]" inputmode="decimal" value="{{ row.max|default('') }}" placeholder="1000">
|
||||
</div>
|
||||
<div>
|
||||
<label for="{{ id }}-unit">Einheit</label>
|
||||
<input id="{{ id }}-unit" name="fields[{{ n }}][unit]" maxlength="12" value="{{ row.unit|default('') }}" placeholder="m²" data-field-unit>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field-card-condition" data-field-condition>
|
||||
<div>
|
||||
<label for="{{ id }}-showif">Nur zeigen, wenn das Feld</label>
|
||||
<input id="{{ id }}-showif" name="fields[{{ n }}][showIfField]" maxlength="32" value="{{ row.showIf.field|default('') }}" pattern="[a-z][a-z0-9_]*" placeholder="immobilienart" data-field-showif>
|
||||
</div>
|
||||
<div>
|
||||
<label for="{{ id }}-showvalues">… einen dieser Werte hat</label>
|
||||
<input id="{{ id }}-showvalues" name="fields[{{ n }}][showIfValues]" maxlength="500" value="{{ row.showIf.values|default([])|join(', ') }}" placeholder="Wohnung, Haus" data-field-showvalues>
|
||||
</div>
|
||||
<p class="field-help">Technischer Name eines Auswahlfeldes weiter oben, Werte durch Komma. Bei einem Schritt gilt die Bedingung für alle seine Felder. Leer: das Feld gilt immer.</p>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{% endmacro %}
|
||||
|
||||
{% block content %}
|
||||
{% import _self as karte %}
|
||||
<div class="form-screens" data-form-schema="{{ schema|json_encode|e('html_attr') }}">
|
||||
<div class="form-screens" data-form-schema="{{ schema|json_encode|e('html_attr') }}" data-form-images="{{ images|json_encode|e('html_attr') }}">
|
||||
{% for form in forms|merge([null]) %}
|
||||
{% set new = form is null %}
|
||||
{% set f = loop.index %}
|
||||
@@ -114,6 +145,10 @@
|
||||
<label for="success-{{ f }}">Meldung nach dem Absenden</label>
|
||||
<textarea id="success-{{ f }}" name="success" maxlength="300" rows="2" placeholder="Vielen Dank. Wir melden uns in Kürze bei dir.">{{ settings.success|default('') }}</textarea>
|
||||
</div>
|
||||
<div class="field-wide">
|
||||
<label class="check-label" for="summary-{{ f }}"><input id="summary-{{ f }}" type="checkbox" name="summary" value="1"{{ settings.summary|default(false) ? ' checked' : '' }}> Zusammenfassung vor dem Absenden zeigen</label>
|
||||
<p class="field-help">Wirkt bei Formularen mit Schritten: der letzte Schritt zeigt alle Angaben mit „Ändern“. Ohne Skript im Browser steht das Formular als Ganzes auf der Seite.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-fields-head">
|
||||
@@ -125,7 +160,7 @@
|
||||
{{ karte.field(f, rows|length, {name: '', type: 'text', label: '', required: false, help: '', options: []}, types) }}
|
||||
</ol>
|
||||
<template data-field-template>{{ karte.field(f, '__n__', {name: '', type: 'text', label: '', required: false, help: '', options: []}, types) }}</template>
|
||||
<p class="field-help" data-fields-help>Ein Feld ohne Beschriftung wird nicht gespeichert – so lässt sich ein Feld auch ohne Skript entfernen. Ein Einwilligungsfeld ist immer ein Pflichtfeld; der Zeitpunkt der Einwilligung wird mitgespeichert.</p>
|
||||
<p class="field-help" data-fields-help>Ein Feld ohne Beschriftung wird nicht gespeichert – so lässt sich ein Feld auch ohne Skript entfernen. Ein Einwilligungsfeld ist immer ein Pflichtfeld; der Zeitpunkt der Einwilligung wird mitgespeichert. Ein Feld vom Typ „Neuer Schritt“ eröffnet einen Abschnitt: seine Beschriftung ist der Titel, sein Hilfetext die Einleitung; alle Felder bis zum nächsten Schritt gehören dazu. Ein Feld oder ein Schritt kann von einer früheren Auswahl abhängen – dann verlangt der Server es nur, wenn die Bedingung zutrifft.</p>
|
||||
|
||||
<h3 class="form-part">Aussehen</h3>
|
||||
<div class="fields form-look">
|
||||
@@ -150,14 +185,22 @@
|
||||
<h3 class="form-part">Vorschau</h3>
|
||||
<div class="form-preview" data-form-preview>
|
||||
{% for row in rows %}
|
||||
<div class="form-preview-field">
|
||||
{% if row.type == 'step' %}
|
||||
<div class="form-preview-step"><span class="form-preview-step-title">{{ row.label }}</span>{% if row.help %}<span class="form-preview-help">{{ row.help }}</span>{% endif %}</div>
|
||||
{% else %}
|
||||
<div class="form-preview-field{{ row.showIf|default(null) ? ' form-preview-conditional' : '' }}">
|
||||
{% if row.type == 'consent' %}
|
||||
<span class="form-preview-check"><span class="form-preview-box" aria-hidden="true"></span>{{ row.label }} *</span>
|
||||
{% elseif row.type == 'radio' or row.type == 'checkboxes' %}
|
||||
<span class="form-preview-label">{{ row.label }}{% if row.required %} *{% endif %}</span>
|
||||
{% for option in row.options %}<span class="form-preview-check"><span class="form-preview-box{{ row.type == 'radio' ? ' form-preview-radio' : '' }}" aria-hidden="true"></span>{{ option }}{% if row.images[option]|default('') %} <span class="muted">(mit Bild)</span>{% endif %}</span>{% endfor %}
|
||||
{% else %}
|
||||
<span class="form-preview-label">{{ row.label }}{% if row.required %} *{% endif %}</span>
|
||||
<span class="form-preview-input{{ row.type == 'textarea' ? ' form-preview-area' : '' }}{{ row.type == 'select' ? ' form-preview-select' : '' }}" aria-hidden="true">{{ row.type == 'select' ? '— bitte wählen —' : '' }}</span>
|
||||
<span class="form-preview-input{{ row.type == 'textarea' ? ' form-preview-area' : '' }}{{ row.type == 'select' ? ' form-preview-select' : '' }}{{ row.type == 'number' ? ' form-preview-number' : '' }}" aria-hidden="true">{{ row.type == 'select' ? '— bitte wählen —' : (row.type == 'number' ? row.unit|default('') : '') }}</span>
|
||||
{% endif %}
|
||||
{% if row.showIf|default(null) %}<span class="form-preview-help">Nur wenn {{ row.showIf.field }} = {{ row.showIf.values|join(' oder ') }}</span>{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
<span class="cms-button b-desktop-shape-{{ schema.buttons.shape }} b-desktop-appearance-{{ schema.buttons.appearance }} b-desktop-size-{{ schema.buttons.size }}" data-preview-button>{{ settings.buttonLabel|default('Absenden') }}</span>
|
||||
</div>
|
||||
|
||||
Reference in new issue
Block a user