Files
FabledSteward/steward/templates/dashboard/_grid_item.html
T
bvandeusenandClaude Opus 5.5 4dcf958022
CI / lint (push) Successful in 4s
CI / integration (push) Successful in 55s
CI / unit (push) Successful in 1m18s
CI / publish (push) Successful in 1m28s
feat(dashboard): widgets fit their content; wide screens get more grid columns (#5249)
Each widget is as tall as its content, never taller than its saved height
(where it scrolls). The dashboard is capped at 2400px instead of 1400px.
Past 12 columns' worth of width it adds columns (one per 110px, up to 24)
and places widgets again in reading order at their saved widths, so more sit
side by side instead of stretching. Edit mode shows and saves the
12-column layout, so a layout doesn't depend on the screen it was edited on.

The share view uses the same layout code (static/dash-layout.js).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 13:10:42 -04:00

33 lines
1.9 KiB
HTML

{# One dashboard widget as a Gridstack item — shared by index.html (initial render)
and the add-widget endpoint (single-item insert). Edit chrome (drag handle +
remove) is in the DOM only for editors and shown via body.dash-editing CSS. #}
{# data-x/y/w/h are the saved 12-column layout; static/dash-layout.js fits
each widget to its content and adds columns on wide screens from them. #}
<div class="grid-stack-item" gs-id="{{ item.db.id }}"
gs-x="{{ item.db.grid_x }}" gs-y="{{ item.db.grid_y }}"
gs-w="{{ item.db.grid_w }}" gs-h="{{ item.db.grid_h }}"
data-x="{{ item.db.grid_x }}" data-y="{{ item.db.grid_y }}"
data-w="{{ item.db.grid_w }}" data-h="{{ item.db.grid_h }}">
<div class="grid-stack-item-content">
<div class="widget-header">
<span style="display:flex;align-items:center;gap:0.4rem;min-width:0;">
{% if can_edit %}<span class="panel-chrome panel-drag" title="Drag to move">⠿</span>{% endif %}
<span class="widget-title" title="{{ item.title }}">{{ item.title }}</span>
</span>
<span style="display:flex;align-items:center;gap:0.5rem;flex-shrink:0;">
<span class="widget-asof" aria-live="polite"></span>
<a href="{{ item.defn.detail_url }}" class="widget-link">Details →</a>
{% if can_edit %}<button type="button" class="panel-chrome btn btn-danger btn-sm"
data-remove="{{ item.db.id }}" title="Remove widget"
style="padding:0.05rem 0.4rem;line-height:1.3;">✕</button>{% endif %}
</span>
</div>
<div class="dash-cell-body" id="widget-{{ item.db.id }}"
hx-get="{{ item.hx_url }}"
hx-trigger="load, retry{% if item.defn.poll %}, every {{ item.defn.poll_seconds or poll_interval }}s{% endif %}"
hx-request='{"timeout": 20000}'
data-poll="{{ '1' if item.defn.poll else '0' }}"
hx-swap="innerHTML"><div class="cell-state">Loading…</div></div>
</div>
</div>