Files
komp_ac/web/templates/pages/admin/ecb/status.html
2026-08-14 20:35:37 +02:00

103 lines
4.6 KiB
HTML

{#
The health card — crate::pages::admin::ecb::ui::StatusFragment, and what
ecb.html embeds on first load.
It carries its own poll trigger rather than the page carrying it, so the
trigger travels with each swap: while a batch is running the card asks for
itself every few seconds, and the card that comes back after the batch
finishes has no trigger, which is what stops the polling.
#}
<section class="panel status-card {{ page.health_class() }}"
{% if page.should_poll() %}hx-get="/admin/ecb/status" hx-trigger="every 3s" hx-target="#ecb-status" hx-swap="outerHTML"{% endif %}
id="ecb-status">
<h2>
{{ page.headline() }}
{% if page.import_running %}<span class="tag">{{ nav.tr("ecb-import-running") }}</span>{% endif %}
</h2>
<p class="hint">{{ page.explanation() }}</p>
{# The question a reader came with. Coverage is a publication date, and
turning it into "which transaction dates will post" means applying the
rule the backend applies -- so the backend applies it and sends both
bounds, rather than the page inviting the reader to do it in their head. #}
<div class="postable">
<p class="postable-lead">{{ nav.tr("ecb-postable-lead") }}</p>
{% if let Some(through) = page.transactions_postable_through %}
<dl class="postable-grid">
<div>
<dt>{{ nav.tr("ecb-ordinary-transactions") }}</dt>
<dd>{{ nav.tr("ecb-dated-up-to") }} <strong>{{ through }}</strong></dd>
<dd class="hint">{{ nav.tr("ecb-ordinary-rate-hint") }}</dd>
</div>
<div>
<dt>{{ nav.tr("ecb-statements-title") }}</dt>
<dd>{{ nav.tr("ecb-dated-up-to") }} <strong>{{ page.statements_postable_through.as_deref().unwrap_or("—") }}</strong></dd>
<dd class="hint">{{ nav.tr("ecb-statements-rate-hint") }}</dd>
</div>
</dl>
<p class="hint">{{ nav.tr("ecb-postable-limit-hint") }}</p>
{% else %}
<p>
<strong>{{ nav.tr("ecb-nothing") }}</strong> {{ nav.tr("ecb-no-publication-hint") }}
</p>
{% endif %}
</div>
{# Coverage first and on its own line: the two dates and the gap between
them are the whole answer, and burying them in a four-column grid made
them read as trivia. #}
<div class="coverage">
<div class="coverage-point">
<span class="coverage-label">{{ nav.tr("ecb-verified-through") }}</span>
<span class="coverage-date">
{%- if let Some(date) = page.verified_through_date %}{{ date }}
{%- else %}{{ nav.tr("ecb-never") }}{% endif -%}
</span>
</div>
<div class="coverage-gap">
{%- if page.healthy %}<span class="tag tag-ok">{{ nav.tr("ecb-up-to-date") }}</span>
{%- else if page.days_behind > 0 %}<span class="tag tag-bad">{{ page.behind_label() }}</span>
{%- else %}<span class="tag tag-bad">{{ nav.tr("ecb-no-coverage") }}</span>{% endif -%}
</div>
<div class="coverage-point">
<span class="coverage-label">{{ nav.tr("ecb-should-reach") }}</span>
<span class="coverage-date">{{ page.latest_verifiable_date }}</span>
</div>
</div>
<dl class="status-grid">
<div>
<dt>{{ nav.tr("ecb-last-attempt") }}</dt>
<dd>{% if let Some(when) = page.last_attempt() %}{{ when }}{% else %}<span class="hint">{{ nav.tr("ecb-none-recorded") }}</span>{% endif %}</dd>
</div>
<div>
<dt>{{ nav.tr("ecb-last-success") }}</dt>
<dd>{% if let Some(when) = page.last_success() %}{{ when }}{% else %}<span class="hint">{{ nav.tr("ecb-none") }}</span>{% endif %}</dd>
</div>
<div>
<dt>{{ nav.tr("ecb-next-import") }}</dt>
<dd>{{ page.next_import() }}</dd>
</div>
<div>
<dt>{% if let Some(date) = page.verified_through_date %}{{ nav.tr_args("ecb-currencies-on", [("date", date.clone())]) }}{% else %}{{ nav.tr("ecb-the-covered-day") }}{% endif %}</dt>
<dd>
{%- if page.covered_currencies.is_empty() %}<span class="hint">{{ nav.tr("ecb-none") }}</span>
{%- else %}{{ page.covered_currencies.len() }}{% endif -%}
</dd>
</div>
</dl>
{% if !page.covered_currencies.is_empty() %}
<div class="currency-list">
{% for currency in page.currencies() %}<span class="tag">{{ currency }}</span>{% endfor %}
</div>
{% endif %}
{% if let Some(failure) = page.last_failure() %}
<p class="hint failure-note">
{{ nav.tr_args("ecb-most-recent-failure", [("batch", failure.batch_id.to_string()), ("started", failure.started())]) }}
{% if let Some(message) = failure.error_message %}{{ message }}{% else %}{{ nav.tr("ecb-no-reason-recorded") }}{% endif %}
</p>
{% endif %}
</section>