Files
FabledSteward/steward/templates/dashboard/share.html
T
bvandeusenandClaude Opus 5.5 e864cd4b6c feat(ui): share view on steward.css; breadcrumbs everywhere they belong; focus ring; tables scroll in their card (#5095)
#5095 "Share view on the shared stylesheet; breadcrumbs, focus-visible and
wide tables".

- dashboard/share_view.html loads theme.css and steward.css; its own copy of
  the old purple palette is gone. Only the read-only frame and the x/y/w/h
  grid stay inline, written in tokens. HEX_CEILING 75 -> 58.
- Breadcrumbs on settings/general, settings/thresholds, the dashboard share
  page and share-link-created. tests/test_breadcrumbs.py fails on any page
  extending base.html without a crumbs() trail, unless it is on the named
  list of section top pages, logged-out and error pages (rule 134).
- :focus-visible draws --fs-focus-ring on links, buttons, summaries, inputs
  and anything with tabindex.
- Any card holding a .table scrolls sideways (card:has(table.table)), so a
  wide table no longer widens the page at phone width; .card-flush scrolls
  too, main gets min-width:0, and .table-wrap covers a table outside a card.
- tests/test_share_view.py renders the share view: shared sheets, no hex
  colour, escaped name, widgets loading through the share token.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 14:37:39 -04:00

81 lines
3.8 KiB
HTML

{% extends "base.html" %}
{% from "_macros.html" import crumbs %}
{% block title %}Share: {{ dashboard.name }} — Steward{% endblock %}
{% block breadcrumb %}{{ crumbs([("Dashboard", "/"), (dashboard.name, "/d/" ~ dashboard.id), ("Share", "")]) }}{% endblock %}
{% block content %}
<div style="display:flex;align-items:baseline;justify-content:space-between;margin-bottom:1.5rem;">
<h1 class="page-title" style="margin-bottom:0;">Share: {{ dashboard.name }}</h1>
<a href="/d/{{ dashboard.id }}" class="btn btn-ghost btn-sm">Back to Dashboard</a>
</div>
<div style="display:grid;grid-template-columns:1fr 320px;gap:1.5rem;align-items:start;max-width:900px;">
{# ── Active tokens ─────────────────────────────────────────────────── #}
<div>
<div class="section-title" style="margin-bottom:0.75rem;">Active Share Links</div>
{% if tokens %}
<div style="display:grid;gap:0.5rem;">
{% for token in tokens %}
{% set expired = token.expires_at is not none and token.expires_at <= now %}
<div class="card" style="margin-bottom:0;padding:0.85rem 1rem;{% if expired %}opacity:0.5;{% endif %}">
<div style="display:flex;align-items:center;gap:0.75rem;">
<div style="flex:1;min-width:0;">
<div style="font-weight:600;font-size:0.875rem;">
{{ token.label or "Unnamed link" }}
{% if expired %}<span class="badge badge-red" style="font-size:0.68rem;">Expired</span>{% endif %}
</div>
<div style="font-size:0.77rem;color:var(--text-muted);margin-top:0.15rem;">
Created {{ token.created_at.strftime("%Y-%m-%d") }}
{% if token.expires_at %}
· Expires {{ token.expires_at.strftime("%Y-%m-%d") }}
{% else %}
· Never expires
{% endif %}
</div>
</div>
<form method="post" action="/d/{{ dashboard.id }}/share/revoke/{{ token.id }}"
style="margin:0;" data-confirm="Revoke this share link?">{{ csrf_field() }}
<button type="submit" class="btn btn-danger btn-sm">Revoke</button>
</form>
</div>
</div>
{% endfor %}
</div>
{% else %}
<div style="color:var(--text-muted);font-size:0.85rem;padding:0.5rem 0;">
No active share links. Create one on the right.
</div>
{% endif %}
</div>
{# ── Create new token ──────────────────────────────────────────────── #}
<div>
<div class="section-title" style="margin-bottom:0.75rem;">Create Share Link</div>
<div class="card" style="margin-bottom:0;">
<form method="post" action="/d/{{ dashboard.id }}/share/create">{{ csrf_field() }}
<div class="form-group" style="margin-bottom:0.75rem;">
<label>Label <span style="color:var(--text-muted);font-size:0.78rem;">(optional)</span></label>
<input type="text" name="label" placeholder="e.g. Public display screen">
</div>
<div class="form-group" style="margin-bottom:0.75rem;">
<label>Expires after</label>
<select name="expires_in">
<option value="">Never</option>
<option value="1">1 day</option>
<option value="7">7 days</option>
<option value="30">30 days</option>
<option value="90">90 days</option>
</select>
</div>
<button type="submit" class="btn">Generate Link</button>
</form>
</div>
<div style="font-size:0.78rem;color:var(--text-muted);margin-top:0.75rem;line-height:1.5;">
The link is shown <strong>once</strong> after creation.<br>
Revoke it at any time to cut off access immediately.
</div>
</div>
</div>
{% endblock %}