conversions web + put table definition
This commit is contained in:
@@ -18,7 +18,7 @@
|
||||
{% if page.can_manage_validations %}<a href="/admin/validation/sets/new">{{ nav.tr("admin-add-rule") }}</a>{% endif %}
|
||||
{% if page.can_import %}<a href="/admin/import">{{ nav.tr("admin-import") }}</a>{% endif %}
|
||||
{% if page.can_export %}<a href="/admin/export">{{ nav.tr("admin-export") }}</a>{% endif %}
|
||||
{% if page.can_exchange_rates %}<a href="/admin/ecb">{{ nav.tr("admin-exchange-rates") }}</a>{% endif %}
|
||||
{% if page.can_exchange_rates %}<a href="/admin/exchange-rates">{{ nav.tr("admin-exchange-rates") }}</a>{% endif %}
|
||||
</div>
|
||||
</section>
|
||||
<div id="admin-workspace">{% include "pages/admin/admin/workspace.html" %}</div>
|
||||
|
||||
58
web/templates/pages/admin/ecb/attempts.html
Normal file
58
web/templates/pages/admin/ecb/attempts.html
Normal file
@@ -0,0 +1,58 @@
|
||||
<section class="panel">
|
||||
<h2>
|
||||
{{ nav.tr("ecb-import-attempts") }} <span class="count">{{ page.batches.len() }}</span>
|
||||
{%- if page.failure_count() > 0 %}<span class="tag tag-bad">{{ page.failed_count_label() }}</span>{% endif -%}
|
||||
</h2>
|
||||
{% if page.batches.is_empty() %}
|
||||
<p class="hint">{{ nav.tr("ecb-no-attempts-hint") }}</p>
|
||||
{% else %}
|
||||
<div class="table-scroll">
|
||||
<table class="builder-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="mark">#</th><th>{{ nav.tr("ecb-th-result") }}</th><th>{{ nav.tr("ecb-th-started") }}</th><th>{{ nav.tr("ecb-th-finished") }}</th>
|
||||
<th>{{ nav.tr("ecb-th-took") }}</th><th>{{ nav.tr("ecb-th-window") }}</th><th class="numeric">{{ nav.tr("ecb-th-observations") }}</th>
|
||||
<th>{{ nav.tr("ecb-th-verified-through") }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for batch in page.batches %}
|
||||
<tr{% if batch.failed() %} class="attempt-failed"{% endif %}>
|
||||
<td class="mark">{{ batch.batch_id }}</td>
|
||||
<td>
|
||||
{%- if batch.succeeded() %}<span class="tag tag-ok">{{ nav.tr("ecb-batch-succeeded") }}</span>
|
||||
{%- else if batch.running() %}<span class="tag">{{ nav.tr("ecb-batch-running") }}</span>
|
||||
{%- else %}<span class="tag tag-bad">{{ nav.tr("ecb-batch-failed") }}</span>{% endif -%}
|
||||
</td>
|
||||
<td class="moment">{{ batch.started() }}</td>
|
||||
<td class="moment">
|
||||
{%- if let Some(finished) = batch.finished() %}{{ finished }}
|
||||
{%- else %}<span class="hint">{{ nav.tr("ecb-still-running") }}</span>{% endif -%}
|
||||
</td>
|
||||
<td class="numeric">
|
||||
{%- if let Some(took) = batch.took(nav.locale) %}{{ took }}
|
||||
{%- else %}<span class="hint">—</span>{% endif -%}
|
||||
</td>
|
||||
<td>
|
||||
{{ batch.window() }}
|
||||
<div class="hint endpoint" title="{{ batch.endpoint }}"><code>{{ batch.endpoint }}</code></div>
|
||||
</td>
|
||||
<td class="numeric">{{ batch.observations(nav.locale) }}</td>
|
||||
<td class="moment">
|
||||
{%- if let Some(date) = batch.verified_through_date %}{{ date }}
|
||||
{%- else %}<span class="hint">—</span>{% endif -%}
|
||||
</td>
|
||||
</tr>
|
||||
{% if let Some(message) = batch.error_message %}
|
||||
<tr class="attempt-error">
|
||||
<td class="mark"></td>
|
||||
<td colspan="7">{{ message }}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<p class="hint">{{ nav.tr("ecb-audit-hint") }}</p>
|
||||
{% endif %}
|
||||
</section>
|
||||
208
web/templates/pages/admin/ecb/workspace.html
Normal file
208
web/templates/pages/admin/ecb/workspace.html
Normal file
@@ -0,0 +1,208 @@
|
||||
{% extends "ui/base.html" %}
|
||||
{% import "ui/alert.html" as alert %}
|
||||
{% import "ui/toast.html" as toast %}
|
||||
|
||||
{% block title %}{{ nav.tr("rates-title") }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<main>
|
||||
<section class="heading">
|
||||
<div>
|
||||
<p class="eyebrow">{{ nav.tr("rates-eyebrow") }}</p>
|
||||
<h1>{{ nav.tr("rates-title") }}</h1>
|
||||
<p>{{ nav.tr("rates-description") }}</p>
|
||||
</div>
|
||||
<div class="actions"><a href="/admin">{{ nav.tr("ui-back-to-admin-panel") }}</a></div>
|
||||
</section>
|
||||
|
||||
{%- if let Some(message) = page.status %}{% call toast::success(nav.tr("rates-updated"), message) %}{% endcall %}{% endif -%}
|
||||
{%- if let Some(message) = page.error %}{% call alert::error(nav.locale, nav.tr("rates-could-not-continue"), message) %}{% endcall %}{% endif -%}
|
||||
|
||||
<nav class="tabs" aria-label="{{ nav.tr("rates-sections") }}">
|
||||
<a class="tab" href="#configuration"><span>{{ nav.tr("rates-tab-configuration") }}</span><small>{{ nav.tr("rates-tab-configuration-sub") }}</small></a>
|
||||
<a class="tab" href="#preview"><span>{{ nav.tr("rates-tab-preview") }}</span><small>{{ nav.tr("rates-tab-preview-sub") }}</small></a>
|
||||
<a class="tab" href="#evidence"><span>{{ nav.tr("rates-tab-evidence") }}</span><small>{{ nav.tr("rates-tab-evidence-sub") }}</small></a>
|
||||
<a class="tab" href="#providers"><span>{{ nav.tr("rates-tab-providers") }}</span><small>{{ nav.tr("rates-tab-providers-sub") }}</small></a>
|
||||
</nav>
|
||||
|
||||
<section class="panel" id="configuration">
|
||||
<h2>{{ nav.tr("rates-profile-configuration") }}</h2>
|
||||
{% if page.profiles.is_empty() %}
|
||||
<p class="hint">{{ nav.tr("rates-no-profiles") }}</p>
|
||||
{% else %}
|
||||
<form method="get" action="/admin/exchange-rates" class="form-grid">
|
||||
<label>{{ nav.tr("rates-profile") }}
|
||||
<select name="profile" onchange="this.form.submit()">
|
||||
{% for profile in page.profiles %}
|
||||
<option value="{{ profile }}" {% if page.is_selected_profile(profile) %}selected{% endif %}>{{ profile }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</label>
|
||||
</form>
|
||||
|
||||
{% if let Some(settings) = page.settings %}
|
||||
<dl class="status-grid">
|
||||
<div><dt>{{ nav.tr("rates-accounting-currency") }}</dt><dd><strong>{{ settings.accounting_currency }}</strong> · {{ nav.tr("rates-immutable") }}</dd></div>
|
||||
<div><dt>{{ nav.tr("rates-configured-currencies") }}</dt><dd>{{ settings.foreign_currencies.len() }}</dd></div>
|
||||
<div><dt>{{ nav.tr("rates-registered-providers") }}</dt><dd>{% if page.providers.is_empty() %}—{% else %}{{ page.providers|join(", ") }}{% endif %}</dd></div>
|
||||
</dl>
|
||||
|
||||
{% if settings.foreign_currencies.is_empty() %}
|
||||
<p class="hint">{{ nav.tr("rates-no-foreign-currencies") }}</p>
|
||||
{% else %}
|
||||
<div class="table-scroll">
|
||||
<table class="builder-table">
|
||||
<thead><tr><th>{{ nav.tr("rates-foreign-currency") }}</th><th>{{ nav.tr("rates-default-provider") }}</th><th>{{ nav.tr("rates-providers") }}</th><th>{{ nav.tr("rates-coverage") }}</th><th></th></tr></thead>
|
||||
<tbody>
|
||||
{% for currency in settings.foreign_currencies %}
|
||||
<tr>
|
||||
<td><strong>{{ currency.currency }}</strong></td>
|
||||
<td><span class="tag">{{ currency.default_source_id }}</span></td>
|
||||
<td>{% for source in currency.sources %}<span class="tag">{{ source.source_id }}</span> {% endfor %}</td>
|
||||
<td>
|
||||
{% for source in currency.sources %}
|
||||
<div>
|
||||
<span class="tag {{ source.coverage_class() }}">{% if source.coverage_complete %}{{ nav.tr("rates-ready") }}{% else %}{{ nav.tr("rates-importing") }}{% endif %}</span>
|
||||
<span class="hint">{{ source.source_id }}{% if let Some(from) = source.verified_from_date %} · {{ from }}{% endif %}{% if let Some(through) = source.verified_through_date %} → {{ through }}{% endif %}</span>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</td>
|
||||
<td>
|
||||
{% if page.can_configure %}
|
||||
{% for source in currency.sources %}
|
||||
{% if source.source_id != currency.default_source_id %}
|
||||
<form method="post" action="/admin/exchange-rates/configuration">
|
||||
<input type="hidden" name="profile" value="{{ page.selected_profile }}">
|
||||
<input type="hidden" name="currency" value="{{ currency.currency }}">
|
||||
<input type="hidden" name="source_id" value="{{ source.source_id }}">
|
||||
<input type="hidden" name="make_default" value="true">
|
||||
<button type="submit" class="secondary">{{ nav.tr("rates-make-default") }}</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if page.can_configure %}
|
||||
<h3>{{ nav.tr("rates-add-binding") }}</h3>
|
||||
<p class="hint">{{ nav.tr("rates-append-only-hint") }}</p>
|
||||
<form method="post" action="/admin/exchange-rates/configuration">
|
||||
<input type="hidden" name="profile" value="{{ page.selected_profile }}">
|
||||
<div class="form-grid">
|
||||
<label>{{ nav.tr("rates-foreign-currency") }}
|
||||
<input name="currency" value="{{ page.configuration.currency }}" list="currency-codes" maxlength="3" placeholder="CZK" required>
|
||||
</label>
|
||||
<label>{{ nav.tr("rates-provider") }}
|
||||
<select name="source_id" required>
|
||||
<option value="">{{ nav.tr("rates-choose-provider") }}</option>
|
||||
{% for provider in page.providers %}<option value="{{ provider }}" {% if page.configuration.source_id == *provider %}selected{% endif %}>{{ provider }}</option>{% endfor %}
|
||||
</select>
|
||||
</label>
|
||||
<label class="check"><input type="checkbox" name="make_default" value="true" {% if page.configuration.make_default %}checked{% endif %}>{{ nav.tr("rates-make-default-now") }}</label>
|
||||
</div>
|
||||
<div class="form-actions"><button type="submit">{{ nav.tr("rates-add-binding") }}</button></div>
|
||||
</form>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</section>
|
||||
|
||||
<section class="panel" id="preview" x-data="{ method: '{{ page.preview_form.method }}' }">
|
||||
<h2>{{ nav.tr("rates-conversion-preview") }}</h2>
|
||||
<p class="hint">{{ nav.tr("rates-preview-hint") }}</p>
|
||||
<form method="post" action="/admin/exchange-rates/preview">
|
||||
<input type="hidden" name="profile" value="{{ page.selected_profile }}">
|
||||
<div class="form-grid">
|
||||
<label>{{ nav.tr("rates-amount") }}<input name="original_amount" value="{{ page.preview_form.original_amount }}" inputmode="decimal" placeholder="2415.30" required></label>
|
||||
<label>{{ nav.tr("rates-currency") }}<input name="original_currency" value="{{ page.preview_form.original_currency }}" list="currency-codes" maxlength="3" placeholder="CZK" required></label>
|
||||
<label>{{ nav.tr("rates-basis-date") }}<input type="date" name="conversion_basis_date" value="{{ page.preview_form.conversion_basis_date }}" required></label>
|
||||
<label>{{ nav.tr("rates-rate-method") }}
|
||||
<select name="method" x-model="method">
|
||||
<option value="automatic-official" {% if page.preview_form.method == "automatic-official" %}selected{% endif %}>{{ nav.tr("rates-method-automatic") }}</option>
|
||||
<option value="official-specific" {% if page.preview_form.method == "official-specific" %}selected{% endif %}>{{ nav.tr("rates-method-specific") }}</option>
|
||||
<option value="saved-custom" {% if page.preview_form.method == "saved-custom" %}selected{% endif %}>{{ nav.tr("rates-method-saved") }}</option>
|
||||
<option value="manual" {% if page.preview_form.method == "manual" %}selected{% endif %}>{{ nav.tr("rates-method-manual") }}</option>
|
||||
</select>
|
||||
</label>
|
||||
<label x-show="method !== 'official-specific' && method !== 'manual'">{{ nav.tr("rates-date-context") }}
|
||||
<select name="context">
|
||||
<option value="ordinary" {% if page.preview_form.context == "ordinary" %}selected{% endif %}>{{ nav.tr("rates-context-ordinary") }}</option>
|
||||
<option value="statement" {% if page.preview_form.context == "statement" %}selected{% endif %}>{{ nav.tr("rates-context-statement") }}</option>
|
||||
</select>
|
||||
</label>
|
||||
<label x-show="method === 'official-specific' || method === 'manual'">{{ nav.tr("rates-specific-date") }}<input type="date" name="specific_rate_date" value="{{ page.preview_form.specific_rate_date }}"></label>
|
||||
<label x-show="method === 'manual'">{{ nav.tr("rates-manual-foreign-units") }}<input name="manual_foreign_units" value="{{ page.preview_form.manual_foreign_units }}" inputmode="decimal" placeholder="24.153"></label>
|
||||
<label>{{ nav.tr("rates-provider-override") }}
|
||||
<select name="rate_source_id"><option value="">{{ nav.tr("rates-use-default-provider") }}</option>{% for provider in page.providers %}<option value="{{ provider }}" {% if page.preview_form.rate_source_id == *provider %}selected{% endif %}>{{ provider }}</option>{% endfor %}</select>
|
||||
</label>
|
||||
<label>{{ nav.tr("rates-reason") }}<input name="reason" value="{{ page.preview_form.reason }}" maxlength="1000"><small>{{ nav.tr("rates-reason-hint") }}</small></label>
|
||||
</div>
|
||||
<div class="form-actions"><button type="submit">{{ nav.tr("rates-preview-action") }}</button></div>
|
||||
</form>
|
||||
|
||||
{% if let Some(preview) = page.preview %}
|
||||
<h3>{{ nav.tr("rates-preview-result") }}</h3>
|
||||
<p><strong>{{ preview.response.original_amount }} {{ preview.response.original_currency }} = {{ preview.response.converted_amount }} {{ preview.response.accounting_currency }}</strong></p>
|
||||
<dl class="status-grid">
|
||||
<div><dt>{{ nav.tr("rates-provider") }}</dt><dd>{{ preview.response.source_id }}</dd></div>
|
||||
<div><dt>{{ nav.tr("rates-rate-method") }}</dt><dd>{{ preview.applied_method }}</dd></div>
|
||||
<div><dt>{{ nav.tr("rates-date-rule") }}</dt><dd>{{ preview.applied_date_rule }}</dd></div>
|
||||
<div><dt>{{ nav.tr("rates-rate-date") }}</dt><dd>{{ preview.response.rate_date.as_deref().unwrap_or("—") }}</dd></div>
|
||||
</dl>
|
||||
<details><summary>{{ nav.tr("rates-audit-details") }}</summary>
|
||||
<dl class="status-grid">
|
||||
<div><dt>{{ nav.tr("rates-exact-quote") }}</dt><dd>{{ preview.quote() }}</dd></div>
|
||||
<div><dt>{{ nav.tr("rates-determination") }}</dt><dd>{{ preview.response.determination_method }}</dd></div>
|
||||
<div><dt>{{ nav.tr("rates-rounding") }}</dt><dd>{{ preview.response.rounding_method }}</dd></div>
|
||||
<div><dt>{{ nav.tr("rates-reason") }}</dt><dd>{{ preview.response.selection_reason }}</dd></div>
|
||||
<div><dt>{{ nav.tr("rates-observation") }}</dt><dd>{{ preview.observation_id() }}</dd></div>
|
||||
<div><dt>{{ nav.tr("rates-import-batch") }}</dt><dd>{{ preview.import_batch_id() }}</dd></div>
|
||||
</dl>
|
||||
</details>
|
||||
{% endif %}
|
||||
</section>
|
||||
|
||||
<section class="panel" id="evidence">
|
||||
<h2>{{ nav.tr("rates-evidence-lookup") }}</h2>
|
||||
<p class="hint">{{ nav.tr("rates-evidence-hint") }}</p>
|
||||
<form method="post" action="/admin/exchange-rates/evidence">
|
||||
<input type="hidden" name="profile" value="{{ page.selected_profile }}">
|
||||
<div class="form-grid">
|
||||
<label>{{ nav.tr("rates-table") }}<input name="table_name" value="{{ page.evidence_form.table_name }}" required></label>
|
||||
<label>{{ nav.tr("rates-record-id") }}<input name="record_id" value="{{ page.evidence_form.record_id }}" inputmode="numeric" required></label>
|
||||
<label>{{ nav.tr("rates-column") }}<input name="column_name" value="{{ page.evidence_form.column_name }}" required></label>
|
||||
</div>
|
||||
<div class="form-actions"><button type="submit">{{ nav.tr("rates-find-evidence") }}</button></div>
|
||||
</form>
|
||||
{% if let Some(has_exchange) = page.evidence_has_exchange %}
|
||||
{% if !has_exchange %}<p class="hint">{{ nav.tr("rates-no-exchange") }}</p>
|
||||
{% else if page.evidence.is_empty() %}<p class="hint">{{ nav.tr("rates-no-evidence") }}</p>
|
||||
{% else %}
|
||||
<div class="table-scroll"><table class="builder-table">
|
||||
<thead><tr><th>#</th><th>{{ nav.tr("rates-revision") }}</th><th>{{ nav.tr("rates-conversion") }}</th><th>{{ nav.tr("rates-provider") }}</th><th>{{ nav.tr("rates-rate-date") }}</th><th>{{ nav.tr("rates-created") }}</th><th>{{ nav.tr("rates-reason") }}</th></tr></thead>
|
||||
<tbody>{% for item in page.evidence %}<tr>
|
||||
<td>{{ item.evidence.evidence_id }}</td><td>{{ item.evidence.row_revision }}</td>
|
||||
<td>{{ item.evidence.original_amount }} {{ item.evidence.original_currency }} → {{ item.evidence.converted_amount }} {{ item.evidence.accounting_currency }}</td>
|
||||
<td>{{ item.evidence.source_id }}</td><td>{{ item.evidence.rate_date.as_deref().unwrap_or("—") }}</td><td>{{ item.evidence.evidence_created_at }}</td><td>{{ item.evidence.selection_reason }}</td>
|
||||
</tr>{% endfor %}</tbody>
|
||||
</table></div>
|
||||
{% if page.evidence_has_more %}<p class="hint">{{ nav.tr("rates-more-evidence") }}</p>{% endif %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</section>
|
||||
|
||||
<section id="providers">
|
||||
<div class="heading"><div><p class="eyebrow">{{ nav.tr("rates-provider-operations") }}</p><h2>{{ nav.tr("rates-provider-health") }}</h2><p>{{ nav.tr("rates-provider-health-hint") }}</p></div></div>
|
||||
{{ provider_status|safe }}
|
||||
{{ provider_attempts|safe }}
|
||||
</section>
|
||||
|
||||
<datalist id="currency-codes">{% for code in currency_codes %}<option value="{{ code }}"></option>{% endfor %}</datalist>
|
||||
</main>
|
||||
{% endblock %}
|
||||
@@ -2,48 +2,24 @@
|
||||
{% include "pages/admin/table_definition/feedback.html" %}
|
||||
|
||||
{% if page.table_is_writable() %}
|
||||
<section class="panel">
|
||||
{% if page.can_adjust_definition() %}
|
||||
<h2>{{ nav.tr("td-adjust-table-of") }} <code>{{ page.selection.table }}</code></h2>
|
||||
<p class="hint">{{ nav.tr("td-adjust-table-hint") }}</p>
|
||||
{% else %}
|
||||
<h2>{{ nav.tr("td-add-columns-to") }} <code>{{ page.selection.table }}</code></h2>
|
||||
<p class="hint">{{ nav.tr("td-append-hint") }}</p>
|
||||
{% endif %}
|
||||
<form id="column-form"
|
||||
hx-post="/admin/tables/columns/add{{ page.selection.query() }}"
|
||||
hx-target="#table-panel" hx-swap="innerHTML"
|
||||
hx-disabled-elt="button[type=submit]">
|
||||
{% if page.can_adjust_definition() %}{% if let Some(detail) = page.detail %}
|
||||
<input type="hidden" name="expected_row_version" value="{{ detail.row_version }}">
|
||||
<h3>{{ nav.tr("td-existing-columns") }}</h3>
|
||||
<table class="builder-table">
|
||||
<thead><tr><th>{{ nav.tr("td-remove-column") }}</th><th>{{ nav.tr("td-col-name") }}</th><th>{{ nav.tr("td-col-type") }}</th><th>{{ nav.tr("td-col-notes") }}</th></tr></thead>
|
||||
<tbody>
|
||||
{% for column in detail.columns %}
|
||||
<tr>
|
||||
<td>
|
||||
{% if column.is_removal_choice() %}
|
||||
<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 %}>
|
||||
{% else %}<span class="hint">—</span>{% endif %}
|
||||
</td>
|
||||
<td><code>{{ column.name }}</code></td>
|
||||
<td>{{ column.field_type }}</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 %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% endif %}{% endif %}
|
||||
<h3>{{ nav.tr("td-new-columns") }}</h3>
|
||||
<div id="column-panel">
|
||||
{% include "pages/admin/table_definition/column_panel.html" %}
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
<form id="column-form"
|
||||
hx-post="/admin/tables/columns/add{{ page.selection.query() }}"
|
||||
hx-target="#table-panel" hx-swap="innerHTML"
|
||||
hx-disabled-elt="button[type=submit]">
|
||||
<section class="builder-section">
|
||||
{% if page.can_adjust_definition() %}
|
||||
<h2>{{ nav.tr("td-adjust-table-of") }} <code>{{ page.selection.table }}</code></h2>
|
||||
<p class="hint">{{ nav.tr("td-adjust-table-hint") }}</p>
|
||||
{% else %}
|
||||
<h2>{{ nav.tr("td-add-columns-to") }} <code>{{ page.selection.table }}</code></h2>
|
||||
<p class="hint">{{ nav.tr("td-append-hint") }}</p>
|
||||
{% endif %}
|
||||
</section>
|
||||
{% if page.can_adjust_definition() %}{% if let Some(detail) = page.detail %}
|
||||
<input type="hidden" name="expected_row_version" value="{{ detail.row_version }}">
|
||||
{% endif %}{% endif %}
|
||||
<div id="column-panel">
|
||||
{% include "pages/admin/table_definition/column_panel.html" %}
|
||||
</div>
|
||||
</form>
|
||||
{% endif %}
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
{%- 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">
|
||||
@@ -160,15 +162,73 @@
|
||||
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>
|
||||
|
||||
{% if page.columns.added.is_empty() %}
|
||||
{% 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("td-col-name") }}</th><th>{{ nav.tr("td-col-type") }}</th><th>{{ nav.tr("td-col-indexed") }}</th><th>{{ nav.tr("td-col-options") }}</th><th></th></tr></thead>
|
||||
<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>
|
||||
@@ -214,7 +274,9 @@
|
||||
<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>
|
||||
|
||||
Reference in New Issue
Block a user