webs unified

This commit is contained in:
Priec
2026-08-03 13:32:25 +02:00
parent 35d85de556
commit c8afe99d79
59 changed files with 1991 additions and 952 deletions

View File

@@ -0,0 +1,32 @@
{# GET /admin/validation/new — crate::pages::add_validation::ui::FieldValidationPage #}
{% extends "ui/form_page.html" %}
{% import "ui/alert.html" as alert %}
{% block title %}Add field validation{% endblock %}
{% block eyebrow %}Validation{% endblock %}
{% block heading %}Add field validation{% endblock %}
{% block lead %}<p>Attach validation to one column of one table.</p>{% endblock %}
{% block form %}
<form hx-post="/admin/validation" hx-target="#submission-status" hx-swap="innerHTML">
<div class="form-grid">
<label>Profile<input name="profile_name" list="profiles" value="{{ page.form.profile_name }}" required></label>
<label>Table<input name="table_name" list="tables" value="{{ page.form.table_name }}" required></label>
<label>Column<input name="data_key" value="{{ page.form.data_key }}" required></label>
<label class="wide">Apply named validation set instead
<input name="validation_set_name" value="{{ page.form.validation_set_name }}"
placeholder="Leave empty to save the rules below">
</label>
{% include "pages/add_validation/shared_fields.html" %}
</div>
<datalist id="profiles">{% for profile in page.profiles %}<option value="{{ profile }}"></option>{% endfor %}</datalist>
<datalist id="tables">{% for table in page.tables %}<option value="{{ table }}"></option>{% endfor %}</datalist>
<div id="submission-status" aria-live="polite">
{%- if let Some(message) = page.error %}{% call alert::error("Could not save validation", message) %}{% endcall %}{% endif -%}
</div>
<div class="form-actions">
<a href="/admin">Cancel</a>
<button type="submit">Save validation</button>
</div>
</form>
{% endblock %}

View File

@@ -0,0 +1,25 @@
{# GET /admin/validation/rules/new — crate::pages::add_validation::ui::ValidationRulePage #}
{% extends "ui/form_page.html" %}
{% import "ui/alert.html" as alert %}
{% block title %}Add reusable validation rule{% endblock %}
{% block eyebrow %}Global validation library{% endblock %}
{% block heading %}Add reusable validation rule{% endblock %}
{% block lead %}<p>A named rule that validation sets can compose, independent of any table.</p>{% endblock %}
{% block form %}
<form hx-post="/admin/validation/rules" hx-target="#submission-status" hx-swap="innerHTML">
<div class="form-grid">
<label>Rule name<input name="rule_name" value="{{ page.form.rule_name }}" required></label>
<label>Description<input name="description" value="{{ page.form.description }}"></label>
{% include "pages/add_validation/shared_fields.html" %}
</div>
<div id="submission-status" aria-live="polite">
{%- if let Some(message) = page.error %}{% call alert::error("Could not save validation", message) %}{% endcall %}{% endif -%}
</div>
<div class="form-actions">
<a href="/admin">Cancel</a>
<button type="submit">Save rule</button>
</div>
</form>
{% endblock %}

View File

@@ -0,0 +1,28 @@
{# GET /admin/validation/sets/new — crate::pages::add_validation::ui::ValidationSetPage #}
{% extends "ui/form_page.html" %}
{% import "ui/alert.html" as alert %}
{% block title %}Add validation set{% endblock %}
{% block eyebrow %}Global validation library{% endblock %}
{% block heading %}Add validation set{% endblock %}
{% block lead %}<p>Compose an ordered set from existing reusable rule names.</p>{% endblock %}
{% block form %}
<form hx-post="/admin/validation/sets" hx-target="#submission-status" hx-swap="innerHTML">
<div class="form-grid">
<label>Set name<input name="name" value="{{ form.name }}" required></label>
<label>Description<input name="description" value="{{ form.description }}"></label>
<label class="wide">Reusable rules
<input name="global_rules" value="{{ form.global_rules }}" required placeholder="required, invoice-number, max-length">
<small>Comma-separated and applied in this order.</small>
</label>
</div>
<div id="submission-status" aria-live="polite">
{%- if let Some(message) = error %}{% call alert::error("Could not save validation", message) %}{% endcall %}{% endif -%}
</div>
<div class="form-actions">
<a href="/admin">Cancel</a>
<button type="submit">Save set</button>
</div>
</form>
{% endblock %}

View File

@@ -0,0 +1,34 @@
{#
Validation inputs shared by the field-validation and reusable-rule pages.
Reads `page.form` (crate::pages::add_validation::state::ValidationForm).
#}
<label class="wide">Position rules
<textarea name="pattern_rules" rows="6"
placeholder="0-3 | alphabetic&#10;4,5 | one-of=-,+&#10;6+ | regex=[0-9]">{{ page.form.pattern_rules }}</textarea>
<small>One per line: position | constraint. Positions: 0, 0-3, 4+, or 1,3,5.
Constraints: alphabetic, numeric, alphanumeric, exact=x, one-of=a,b, regex=…</small>
</label>
<label class="wide">Pattern description<input name="pattern_description" value="{{ page.form.pattern_description }}"></label>
<label>Minimum length<input name="minimum" type="number" min="0" value="{{ page.form.minimum }}"></label>
<label>Maximum length<input name="maximum" type="number" min="0" value="{{ page.form.maximum }}"></label>
<label>Warning threshold<input name="warn_at" type="number" min="0" value="{{ page.form.warn_at }}"></label>
<label>Count mode
<select name="count_mode">
<option value="chars">Characters</option>
<option value="bytes" {% if page.form.count_mode == "bytes" %}selected{% endif %}>Bytes</option>
<option value="display-width" {% if page.form.count_mode == "display-width" %}selected{% endif %}>Display width</option>
</select>
</label>
<label class="wide">Allowed values<input name="allowed_values" value="{{ page.form.allowed_values }}" placeholder="draft, issued, paid"></label>
<label>Display mask<input name="mask_pattern" value="{{ page.form.mask_pattern }}" placeholder="####-##-##"></label>
<label>Mask input character<input name="mask_input_char" value="{{ page.form.mask_input_char }}" placeholder="#"></label>
<label>Mask template character<input name="mask_template_char" value="{{ page.form.mask_template_char }}" placeholder="_"></label>
<div class="check-group">
<label class="check"><input type="checkbox" name="required" value="true" {% if page.form.required %}checked{% endif %}>Required</label>
<label class="check"><input type="checkbox" name="allow_empty" value="true" {% if page.form.allow_empty %}checked{% endif %}>Allow empty</label>
<label class="check"><input type="checkbox" name="case_insensitive" value="true" {% if page.form.case_insensitive %}checked{% endif %}>Case insensitive</label>
<label class="check"><input type="checkbox" name="external_validation_enabled" value="true" {% if page.form.external_validation_enabled %}checked{% endif %}>External validation</label>
<label class="check"><input type="checkbox" name="locked" value="true" {% if page.form.locked %}checked{% endif %}>Lock configuration</label>
</div>