Files
komp_ac/web/templates/pages/add_table/builder.html
2026-08-07 22:39:59 +02:00

244 lines
11 KiB
HTML

{#
POST /admin/tables/builder — crate::pages::add_table::ui::BuilderFragment.
The whole builder, which is also what `add_table.html` embeds on first load.
Every control posts the entire draft back to /admin/tables/builder and swaps
this markup in again, so the rules live on the server exactly as they do in
the TUI client. The hidden inputs in the columns, relations and display
sections are what carry the draft across requests.
#}
{% import "ui/alert.html" as alert %}
{% import "ui/dialog.html" as dialog %}
{% import "ui/toast.html" as toast %}
{#
A failure is a dialog, not an inline alert: the builder is taller than the
viewport, so an alert at the top is off screen for anyone who has scrolled
down to the column list or the Create table button. The alert stays too, as
what is left on the page after the dialog is dismissed.
#}
{%- if let Some(message) = page.error %}{% call alert::error("Could not continue", message) %}{% endcall %}{% endif -%}
{%- if let Some(message) = page.status %}{% call toast::success("Draft updated", message) %}{% endcall %}{% endif -%}
{%- if let Some(message) = page.error %}{% call dialog::error("Could not continue", message) %}{% endcall %}{% endif -%}
<section class="builder-section">
<h2>Table</h2>
<div class="form-grid">
<label>Profile
<select name="profile_name" hx-post="/admin/tables/builder" hx-trigger="change"
hx-include="#table-form" hx-target="#builder" hx-swap="innerHTML"
hx-vals='{"action": "refresh"}'>
<option value="">Choose a profile</option>
{% for profile in page.profiles %}
<option value="{{ profile }}" {% if page.selected_profile() == profile.as_str() %}selected{% endif %}>{{ profile }}</option>
{% endfor %}
<option value="__new__" {% if page.draft.creating_new_profile %}selected{% endif %}>+ New profile…</option>
</select>
</label>
{% if page.draft.show_profile_name_input() %}
<label>New profile name
<input name="profile_name_input" value="{{ page.draft.profile_name_input }}" placeholder="bookkeeping">
</label>
{% endif %}
{% if page.draft.show_accounting_currency() %}
<label>Accounting currency
<input name="accounting_currency" value="{{ page.draft.accounting_currency }}" list="currency-codes"
maxlength="3" placeholder="EUR">
</label>
{% else %}
<input type="hidden" name="accounting_currency" value="{{ page.draft.accounting_currency }}">
{% endif %}
<label>Table name
<input name="table_name" value="{{ page.draft.table_name }}" placeholder="invoice"
hx-post="/admin/tables/builder" hx-trigger="change" hx-include="#table-form"
hx-target="#builder" hx-swap="innerHTML" hx-vals='{"action": "refresh"}'>
</label>
</div>
</section>
<section class="builder-section">
<h2>Add a column</h2>
<div class="form-grid">
<label>Column name
<input name="column_name_input" value="{{ page.draft.columns.name_input }}" placeholder="number">
</label>
<label>Column type
<select name="column_type_input" hx-post="/admin/tables/builder" hx-trigger="change"
hx-include="#table-form" hx-target="#builder" hx-swap="innerHTML"
hx-vals='{"action": "refresh"}'>
<option value="">Choose a type</option>
{% for column_type in column_types %}
<option value="{{ column_type }}" {% if page.draft.columns.type_input == *column_type %}selected{% endif %}>{{ column_type }}</option>
{% endfor %}
</select>
</label>
{% if page.draft.columns.show_temporal_type() %}
<label>Temporal type
<select name="temporal_type_input">
<option value="">Choose a temporal type</option>
{% for temporal_type in temporal_types %}
<option value="{{ temporal_type }}" {% if page.draft.columns.temporal_type_input == *temporal_type %}selected{% endif %}>{{ temporal_type }}</option>
{% endfor %}
</select>
</label>
{% endif %}
{% if page.draft.columns.show_gtin_type() %}
<label>GTIN type
<select name="gtin_type_input">
<option value="">Choose a GTIN length</option>
{% for gtin_type in gtin_types %}
<option value="{{ gtin_type }}" {% if page.draft.columns.gtin_type_input == *gtin_type %}selected{% endif %}>GTIN-{{ gtin_type }}</option>
{% endfor %}
</select>
</label>
{% endif %}
{% if page.draft.columns.show_decimal_arguments() %}
<label>Precision
<input name="decimal_precision_input" value="{{ page.draft.columns.decimal_precision_input }}"
inputmode="numeric" placeholder="12">
<small>Total digits stored, at least 1.</small>
</label>
<label>Scale
<input name="decimal_scale_input" value="{{ page.draft.columns.decimal_scale_input }}"
inputmode="numeric" placeholder="3">
<small>Digits after the point, no more than the precision.</small>
</label>
{% endif %}
{% if page.draft.columns.show_money_options() %}
<label>Currency
<input name="column_currency_input" value="{{ page.draft.columns.currency_input }}" list="currency-codes"
maxlength="3" placeholder="EUR">
</label>
<label>Rounding
<select name="column_rounding_input">
<option value="none" {% if page.draft.columns.rounding_input != "half-up" %}selected{% endif %}>none</option>
<option value="half-up" {% if page.draft.columns.rounding_input == "half-up" %}selected{% endif %}>half-up</option>
</select>
</label>
{% endif %}
<label>Indexing
<select name="column_indexing_input">
<option value="no" {% if page.draft.columns.indexing_input != "yes" %}selected{% endif %}>no</option>
<option value="yes" {% if page.draft.columns.indexing_input == "yes" %}selected{% endif %}>yes</option>
</select>
</label>
<label>Quantity ledger
<select name="column_quantity_ledger_input">
<option value="no" {% if page.draft.columns.quantity_ledger_input != "yes" %}selected{% endif %}>no</option>
<option value="yes" {% if page.draft.columns.quantity_ledger_input == "yes" %}selected{% endif %}>yes</option>
</select>
<small>{{ page.draft.columns.quantity_ledger_types() }} only.</small>
</label>
</div>
<button type="button" class="secondary" hx-post="/admin/tables/builder" hx-include="#table-form"
hx-target="#builder" hx-swap="innerHTML" hx-vals='{"action": "add-column"}'>Add column</button>
</section>
<section class="builder-section">
<h2>Columns <span class="count">{{ page.draft.columns.added.len() }}</span></h2>
{% if page.draft.columns.is_empty() %}
<p class="hint">No columns yet. Describe one above and press <em>Add column</em>.</p>
{% else %}
<table class="builder-table">
<thead><tr><th>Name</th><th>Type</th><th>Indexed</th><th>Options</th><th></th></tr></thead>
<tbody>
{% for column in page.draft.columns.added %}
<tr>
<td><code>{{ column.name }}</code></td>
<td>{{ column.data_type }}</td>
<td>
{# A compound column expands into schema-managed companions, so
there is no column of its own name to index. #}
{% if page.draft.columns.is_indexable(*loop.index0) %}
<button type="button" class="toggle" hx-post="/admin/tables/builder" hx-include="#table-form"
hx-target="#builder" hx-swap="innerHTML"
hx-vals='{"action": "toggle-index", "index": "{{ loop.index0 }}"}'>
{% if column.indexed %}[x]{% else %}[ ]{% endif %}
</button>
{% else %}
<span class="hint"></span>
{% endif %}
</td>
<td>
{% if column.quantity_ledger %}<span class="tag">quantity ledger</span>{% endif %}
{% if !column.option_label().is_empty() %}<span class="tag">{{ column.option_label() }}</span>{% endif %}
</td>
<td>
<button type="button" class="danger" hx-post="/admin/tables/builder" hx-include="#table-form"
hx-target="#builder" hx-swap="innerHTML"
hx-vals='{"action": "remove-column", "index": "{{ loop.index0 }}"}'>Remove</button>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
{# The draft itself: one set of fields per column, in order. #}
{% for column in page.draft.columns.added %}
<input type="hidden" name="column_names" value="{{ column.name }}">
<input type="hidden" name="column_types" value="{{ column.data_type }}">
<input type="hidden" name="column_indexed" value="{% if column.indexed %}yes{% else %}no{% endif %}">
<input type="hidden" name="column_quantity_ledger" value="{% if column.quantity_ledger %}yes{% else %}no{% endif %}">
<input type="hidden" name="column_rounding" value="{{ column.money_mode.label() }}">
<input type="hidden" name="column_currencies" value="{{ column.currency }}">
{% endfor %}
</section>
<section class="builder-section">
{% for table in page.draft.relation_tables %}
<input type="hidden" name="relation_tables" value="{{ table }}">
{% endfor %}
</section>
<section class="builder-section">
<h2>Row display columns</h2>
<p class="hint">What identifies a row to users, in the order chosen. Pick <code>id</code> to clear the list.</p>
<ul class="builder-list">
{% for candidate in page.row_display_candidates() %}
<li>
<button type="button" class="toggle" hx-post="/admin/tables/builder" hx-include="#table-form"
hx-target="#builder" hx-swap="innerHTML"
hx-vals='{"action": "toggle-display", "index": "{{ candidate.index }}"}'>{{ candidate.mark() }}</button>
<code>{{ candidate.name }}</code>
</li>
{% endfor %}
</ul>
{% for display in page.draft.row_display_columns %}
<input type="hidden" name="row_display_columns" value="{{ display }}">
{% endfor %}
</section>
<section class="builder-section">
<h2>Table definition preview</h2>
<table class="builder-table preview">
<thead><tr><th></th><th>Column</th><th>Type</th><th>Options</th><th>Source</th></tr></thead>
<tbody>
{% for row in page.draft.preview_rows() %}
<tr class="source-{{ row.source }}">
<td class="mark">{{ row.mark }}</td>
<td><code>{{ row.column }}</code></td>
<td>{{ row.data_type }}</td>
<td>{{ row.option }}</td>
<td>{{ row.source }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</section>
<div class="form-actions">
<a href="/admin">Cancel</a>
<button type="submit">Create table</button>
</div>