270 lines
15 KiB
HTML
270 lines
15 KiB
HTML
{#
|
|
The append-columns panel —
|
|
crate::pages::admin::table_definition::ui::ColumnPanelFragment, and what
|
|
workspace.html embeds inside #column-form.
|
|
|
|
Staging a column writes nothing, so these buttons swap this panel alone.
|
|
Saving is the form's own submit, which swaps the whole workspace. The field
|
|
names are the ones crate::schema::ColumnForm declares — the same set the
|
|
Add-table builder posts, decoded by the same code.
|
|
#}
|
|
{#
|
|
Staging swaps this panel and nothing else, so a refused column has nowhere
|
|
else to be reported. When the workspace embeds the panel it reports the
|
|
outcome at the top instead, and this block stays out of the way.
|
|
#}
|
|
{% import "ui/alert.html" as panel_alert %}
|
|
{% import "ui/dialog.html" as panel_dialog %}
|
|
{% import "ui/toast.html" as panel_toast %}
|
|
{% if standalone_column_panel %}
|
|
{%- if let Some(message) = page.error %}{% call panel_alert::error(nav.locale, nav.tr("td-could-not-add-column"), message) %}{% endcall %}{% endif -%}
|
|
{%- if let Some(message) = page.status %}{% call panel_toast::success(nav.tr("td-staged"), message) %}{% endcall %}{% endif -%}
|
|
{%- if let Some(message) = page.error %}{% call panel_dialog::error(nav.locale, nav.tr("td-could-not-add-column"), message) %}{% endcall %}{% endif -%}
|
|
{% endif %}
|
|
|
|
<section class="builder-section">
|
|
<h2>{{ nav.tr("builder-add-column-heading") }}</h2>
|
|
<div class="form-grid">
|
|
<label>{% if page.columns.show_link_target() %}{{ nav.tr("td-link-alias") }}{% else %}{{ nav.tr("td-column-name") }}{% endif %}
|
|
<input name="column_name_input" value="{{ page.columns.name_input }}" placeholder="issued_on">
|
|
{% if page.columns.show_link_target() %}<small>{{ nav.tr("td-link-alias-hint") }}</small>{% endif %}
|
|
</label>
|
|
<label>{{ nav.tr("td-column-type") }}
|
|
<select name="column_type_input"
|
|
hx-post="/admin/tables/columns/add/builder{{ page.selection.query() }}"
|
|
hx-trigger="change" hx-include="#column-form"
|
|
hx-target="#column-panel" hx-swap="innerHTML"
|
|
hx-vals='{"action": "refresh"}'>
|
|
<option value="">{{ nav.tr("td-choose-type") }}</option>
|
|
{% for column_type in column_types %}
|
|
<option value="{{ column_type }}" {% if page.columns.type_input == *column_type %}selected{% endif %}>{% if *column_type == "link" %}{{ nav.tr("td-fk-link") }}{% else %}{{ column_type }}{% endif %}</option>
|
|
{% endfor %}
|
|
</select>
|
|
</label>
|
|
|
|
{% if page.columns.show_temporal_type() %}
|
|
<label>{{ nav.tr("td-temporal-type") }}
|
|
<select name="temporal_type_input">
|
|
<option value="">{{ nav.tr("td-choose-temporal-type") }}</option>
|
|
{% for temporal_type in temporal_types %}
|
|
<option value="{{ temporal_type }}" {% if page.columns.temporal_type_input == *temporal_type %}selected{% endif %}>{{ temporal_type }}</option>
|
|
{% endfor %}
|
|
</select>
|
|
</label>
|
|
{% endif %}
|
|
|
|
{% if page.columns.show_gtin_type() %}
|
|
<label>{{ nav.tr("td-gtin-type") }}
|
|
<select name="gtin_type_input">
|
|
<option value="">{{ nav.tr("td-choose-gtin-length") }}</option>
|
|
{% for gtin_type in gtin_types %}
|
|
<option value="{{ gtin_type }}" {% if page.columns.gtin_type_input == *gtin_type %}selected{% endif %}>GTIN-{{ gtin_type }}</option>
|
|
{% endfor %}
|
|
</select>
|
|
</label>
|
|
{% endif %}
|
|
|
|
{% if page.columns.show_link_target() %}
|
|
<label>{{ nav.tr("td-referenced-table") }}
|
|
<select name="link_table_input">
|
|
<option value="">{{ nav.tr("td-choose-table") }}</option>
|
|
{% if !page.global_link_target_tables().is_empty() %}
|
|
<optgroup label="{{ nav.tr("td-group-global") }}">
|
|
{% for table in page.global_link_target_tables() %}
|
|
<option value="{{ table }}" {% if page.columns.link_table_input == *table %}selected{% endif %}>{{ table }}</option>
|
|
{% endfor %}
|
|
</optgroup>
|
|
{% endif %}
|
|
{% if !page.user_link_target_tables().is_empty() %}
|
|
<optgroup label="{{ nav.tr("td-group-user") }}">
|
|
{% for table in page.user_link_target_tables() %}
|
|
<option value="{{ table }}" {% if page.columns.link_table_input == *table %}selected{% endif %}>{{ table }}</option>
|
|
{% endfor %}
|
|
</optgroup>
|
|
{% endif %}
|
|
{% if !page.system_link_target_tables().is_empty() %}
|
|
<optgroup label="{{ nav.tr("td-group-system") }}">
|
|
{% for table in page.system_link_target_tables() %}
|
|
<option value="{{ table }}" {% if page.columns.link_table_input == *table %}selected{% endif %}>{{ table }}</option>
|
|
{% endfor %}
|
|
</optgroup>
|
|
{% endif %}
|
|
</select>
|
|
{% if page.global_link_target_tables().is_empty() && page.user_link_target_tables().is_empty() && page.system_link_target_tables().is_empty() %}<small>{{ nav.tr("td-no-eligible-tables") }}</small>{% endif %}
|
|
</label>
|
|
{% endif %}
|
|
|
|
{% if page.columns.show_money_options() %}
|
|
<label>{{ nav.tr("td-currency") }}
|
|
<input name="column_currency_input" value="{{ page.columns.currency_input }}" list="currency-codes"
|
|
maxlength="3" placeholder="EUR">
|
|
</label>
|
|
<label>{{ nav.tr("td-rounding") }}
|
|
<select name="column_rounding_input">
|
|
<option value="none" {% if page.columns.rounding_input != "half-up" %}selected{% endif %}>{{ nav.tr("td-rounding-none") }}</option>
|
|
<option value="half-up" {% if page.columns.rounding_input == "half-up" %}selected{% endif %}>{{ nav.tr("td-rounding-half-up") }}</option>
|
|
</select>
|
|
</label>
|
|
{% endif %}
|
|
|
|
{#
|
|
A link is left out rather than defaulted to "no": the server builds an
|
|
index for every foreign key as it adds the column, and refuses a request
|
|
that asks for one on top.
|
|
#}
|
|
{% if page.columns.show_indexing() %}
|
|
<label>{{ nav.tr("td-indexing") }}
|
|
<select name="column_indexing_input">
|
|
<option value="no" {% if page.columns.indexing_input != "yes" %}selected{% endif %}>{{ nav.tr("common-no") }}</option>
|
|
<option value="yes" {% if page.columns.indexing_input == "yes" %}selected{% endif %}>{{ nav.tr("common-yes") }}</option>
|
|
</select>
|
|
</label>
|
|
{% else if page.columns.pending_is_auto_indexed() %}
|
|
<div class="field-note">
|
|
<span class="field-label">{{ nav.tr("td-indexing") }}</span>
|
|
<p class="hint">{{ nav.tr("td-indexed-automatically") }}</p>
|
|
</div>
|
|
{% endif %}
|
|
<label>{{ nav.tr("td-required") }}
|
|
<select name="column_required_input">
|
|
<option value="no" {% if page.columns.required_input != "yes" %}selected{% endif %}>{{ nav.tr("common-no") }}</option>
|
|
<option value="yes" {% if page.columns.required_input == "yes" %}selected{% endif %}>{{ nav.tr("common-yes") }}</option>
|
|
</select>
|
|
<small>{{ nav.tr("td-required-hint") }}</small>
|
|
</label>
|
|
{% if page.columns.show_quantity_ledger() %}
|
|
<label>{{ nav.tr("td-quantity-ledger") }}
|
|
<select name="column_quantity_ledger_input">
|
|
<option value="no" {% if page.columns.quantity_ledger_input != "yes" %}selected{% endif %}>{{ nav.tr("common-no") }}</option>
|
|
<option value="yes" {% if page.columns.quantity_ledger_input == "yes" %}selected{% endif %}>{{ nav.tr("common-yes") }}</option>
|
|
</select>
|
|
<small>{{ nav.tr_args("td-ql-only", [("types", page.columns.quantity_ledger_types())]) }}</small>
|
|
</label>
|
|
{% else %}
|
|
<p class="hint">{{ nav.tr("td-shared-no-quantity-ledger") }}</p>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<button type="button" class="secondary"
|
|
hx-post="/admin/tables/columns/add/builder{{ page.selection.query() }}"
|
|
hx-include="#column-form" hx-target="#column-panel" hx-swap="innerHTML"
|
|
hx-vals='{"action": "add-column"}'>{{ nav.tr("td-stage-column") }}</button>
|
|
</section>
|
|
|
|
{% let existing_count = page.existing_column_count() %}
|
|
<section class="builder-section">
|
|
<h2>{{ nav.tr("builder-columns-heading") }} <span class="count">{{ existing_count + page.columns.added.len() }}</span></h2>
|
|
{% if existing_count == 0 && page.columns.added.is_empty() %}
|
|
<p class="hint">{{ nav.tr("td-no-staged-columns") }} <em>{{ nav.tr("td-stage-column") }}</em>.</p>
|
|
{% else %}
|
|
{% if !page.columns.added.is_empty() %}<p class="hint">{{ nav.tr("builder-columns-order-hint") }}</p>{% endif %}
|
|
<table class="builder-table">
|
|
<thead><tr><th>{{ nav.tr("builder-th-order") }}</th><th>{{ nav.tr("builder-th-name") }}</th><th>{{ nav.tr("builder-th-type") }}</th><th>{{ nav.tr("builder-th-indexed") }}</th><th>{{ nav.tr("builder-th-options") }}</th><th></th></tr></thead>
|
|
<tbody>
|
|
{#
|
|
The table as it already exists, shown exactly the way the create
|
|
builder shows a generated companion: a locked row with nothing to
|
|
reorder. Unlike a freshly staged column, removing one is a checkbox
|
|
to tick rather than an action that fires immediately — the same
|
|
control as before, just carried into this column's own cell so the
|
|
row lines up with the staged ones below it.
|
|
#}
|
|
{% if let Some(detail) = page.detail %}
|
|
{% for column in detail.columns %}
|
|
<tr class="generated-row">
|
|
<td class="order"><span class="hint">—</span></td>
|
|
<td><code>{{ column.name }}</code></td>
|
|
<td>{{ column.field_type }}</td>
|
|
<td><span class="hint">—</span></td>
|
|
<td>
|
|
{% if column.generated %}<span class="tag">{{ nav.tr("column-flag-generated") }}</span>{% endif %}
|
|
{% if column.read_only %}<span class="tag">{{ nav.tr("column-flag-read-only") }}</span>{% endif %}
|
|
{% if !column.currency.is_empty() %}<span class="tag">{{ column.currency }}{% if column.rounded %}, {{ nav.tr("td-rounding-half-up") }}{% endif %}</span>{% endif %}
|
|
{% if column.quantity_ledger %}<span class="tag">{{ nav.tr("column-flag-quantity-ledger") }}</span>{% endif %}
|
|
</td>
|
|
<td>
|
|
{#
|
|
A normal button, styled and worded exactly like the create
|
|
builder's own remove button — but this one deletes a column
|
|
that already holds nothing but empty rows, so it carries a
|
|
confirm() the builder's has no need for. The checkbox itself
|
|
is what still travels with the save; only its default look
|
|
is hidden.
|
|
#}
|
|
{% if page.can_adjust_definition() && column.is_removal_choice() %}
|
|
<label class="danger"
|
|
onclick="if(!confirm('{{ nav.tr_args("td-remove-column-confirm", [("column", column.name.clone())]) }}')){event.preventDefault();}">
|
|
<input type="checkbox" name="remove_column_ids" value="{{ column.column_id }}"
|
|
aria-label="{{ nav.tr_args("td-remove-column-aria", [("column", column.name.clone())]) }}"
|
|
{% if page.column_is_selected_for_removal(column.column_id) %}checked{% endif %}>
|
|
{{ nav.tr("common-remove") }}
|
|
</label>
|
|
{% endif %}
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
{% endif %}
|
|
{% for column in page.columns.added %}
|
|
<tr>
|
|
<td class="order">
|
|
<button type="button" class="toggle move" aria-label="{{ nav.tr_args("builder-move-up", [("name", column.name.clone())]) }}"
|
|
{% if loop.first %}disabled{% else %}hx-post="/admin/tables/columns/add/builder{{ page.selection.query() }}"
|
|
hx-include="#column-form" hx-target="#column-panel" hx-swap="innerHTML"
|
|
hx-vals='{"action": "move-column-up", "index": "{{ loop.index0 }}"}'{% endif %}>↑</button>
|
|
<button type="button" class="toggle move" aria-label="{{ nav.tr_args("builder-move-down", [("name", column.name.clone())]) }}"
|
|
{% if loop.last %}disabled{% else %}hx-post="/admin/tables/columns/add/builder{{ page.selection.query() }}"
|
|
hx-include="#column-form" hx-target="#column-panel" hx-swap="innerHTML"
|
|
hx-vals='{"action": "move-column-down", "index": "{{ loop.index0 }}"}'{% endif %}>↓</button>
|
|
</td>
|
|
<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.columns.is_indexable(*loop.index0) %}
|
|
<button type="button" class="toggle"
|
|
hx-post="/admin/tables/columns/add/builder{{ page.selection.query() }}"
|
|
hx-include="#column-form" hx-target="#column-panel" hx-swap="innerHTML"
|
|
hx-vals='{"action": "toggle-index", "index": "{{ loop.index0 }}"}'>
|
|
{% if column.indexed %}[x]{% else %}[ ]{% endif %}
|
|
</button>
|
|
{% else if column.is_indexed() %}
|
|
<span class="tag">{{ nav.tr("td-indexed-automatically-tag") }}</span>
|
|
{% else %}
|
|
<span class="hint">—</span>
|
|
{% endif %}
|
|
</td>
|
|
<td>
|
|
{% if column.required %}<span class="tag">{{ nav.tr("column-flag-required") }}</span>{% endif %}
|
|
{% if column.quantity_ledger %}<span class="tag">{{ nav.tr("column-flag-quantity-ledger") }}</span>{% endif %}
|
|
{% if !column.currency.is_empty() %}<span class="tag">{{ column.currency }}, {{ column.money_mode.display_label(nav.locale) }}</span>{% endif %}
|
|
</td>
|
|
<td>
|
|
<button type="button" class="danger"
|
|
hx-post="/admin/tables/columns/add/builder{{ page.selection.query() }}"
|
|
hx-include="#column-form" hx-target="#column-panel" hx-swap="innerHTML"
|
|
hx-vals='{"action": "remove-column", "index": "{{ loop.index0 }}"}'>{{ nav.tr("common-remove") }}</button>
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
{% endif %}
|
|
|
|
{# The staged columns themselves: one set of fields per column, in order. #}
|
|
{% for column in page.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_required" value="{% if column.required %}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>
|
|
|
|
<div class="form-actions">
|
|
<a href="/admin{{ page.selection.query() }}">{{ nav.tr("common-cancel") }}</a>
|
|
<button type="submit">{% if page.can_adjust_definition() %}{{ nav.tr("td-save-definition") }}{% else %}{{ nav.tr("td-add-columns-title") }}{% endif %}</button>
|
|
</div>
|