tabs: render schedules as a single table with tilted agent columns (closes #535)
Replaces the per-schedule card layout with one table:
| # | src | next | every | owner | body | …agents… | actions |
|---|-----|------|-------|-------|------|----------|---------|
| 5 | op | 5m | 10m | mara | "…" | ✓ ✓ . ✓ | ↯ ✎ ✕ |
Each schedule is one <tr> in the tbody. Agent columns are dynamic —
operator + manager + live containers + any "extra" name that appears
as a target on some schedule but isn't a current container (same
membership rule buildTargetChips uses, so the table + new/edit forms
agree on what's addressable). Per-agent cells:
- active target → <button>✓</button> that cancels just that target
on click (replaces the per-row ✕ from the old targets sub-table)
- cancelled target → muted ✕ glyph (no button; re-add flows through
the edit form's targets multi-select)
- not a target → empty cell
Agent column headers tilt -45° via CSS so each column reads as 28px
of horizontal real estate instead of the full word width. Standard
rotated-header pattern: 95px-tall <th> with position:relative, inner
<div> positioned absolute at bottom-left, transform rotates about
left-bottom.
Body cell truncates with ellipsis + full-text title. Description used
to be a separate visible block on the card layout; the table folds
it into the body cell's title to keep row height tight. If mara wants
description visible in-table it's a small follow-up — easier to
iterate on a rejection.
Edit form expands inline into a colspan'd row underneath the schedule
row it edits (instead of inside the card). Wrapper drops the form's
background so it reads as a row extension.
No backend changes; everything renders from existing schedulesState
+ containersState.
This commit is contained in:
parent
78a503d8b9
commit
42a2503834
2 changed files with 277 additions and 141 deletions
|
|
@ -1759,60 +1759,112 @@ body.flow-shell .tabbar .tab.active.tab-link {
|
|||
}
|
||||
.schedule-interval-preview-oneshot { color: var(--muted); font-style: italic; }
|
||||
|
||||
.schedules {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5em;
|
||||
}
|
||||
.schedule-row {
|
||||
padding: 0.6em 0.9em;
|
||||
background: rgba(24, 24, 37, 0.55);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.4em;
|
||||
}
|
||||
.schedule-row.schedule-cancelled { opacity: 0.55; }
|
||||
.schedule-head {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: 0.4em;
|
||||
}
|
||||
.schedule-description {
|
||||
color: var(--muted);
|
||||
font-style: italic;
|
||||
font-size: 0.95em;
|
||||
}
|
||||
.schedule-body {
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
background: var(--bg);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 3px;
|
||||
padding: 0.5em 0.7em;
|
||||
}
|
||||
.schedule-targets-table {
|
||||
/* #535 — schedules-as-table. One row per schedule, attribute columns
|
||||
on the left, one ✓/✕ column per agent in the middle, actions
|
||||
column on the right. Agent column headers tilt -45° so a stack of
|
||||
short agent names fits in ~28px each. */
|
||||
.schedules-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
.schedule-targets-table th,
|
||||
.schedule-targets-table td {
|
||||
padding: 0.25em 0.6em;
|
||||
.schedules-table thead th {
|
||||
vertical-align: bottom;
|
||||
padding: 0.3em 0.5em;
|
||||
text-align: left;
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
.schedule-targets-table th {
|
||||
color: var(--muted);
|
||||
font-weight: normal;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
font-size: 0.8em;
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
.schedules-table-id { width: 3em; }
|
||||
.schedules-table-body-th { min-width: 12em; }
|
||||
.schedules-table-actions-th { width: 7em; }
|
||||
/* Tilted agent column headers (#535). Header cell is narrow (~28px)
|
||||
and tall (~90px); the inner <div> rotates -45° about its bottom-left
|
||||
corner, with a translate to slide the text up alongside the cell
|
||||
border. The inner <span> carries the actual baseline so the
|
||||
underline (border-bottom on the cell) aligns with the rotated text. */
|
||||
.schedules-table-agent-th {
|
||||
width: 28px;
|
||||
min-width: 28px;
|
||||
height: 95px;
|
||||
padding: 0 !important;
|
||||
vertical-align: bottom;
|
||||
white-space: nowrap;
|
||||
text-transform: none !important;
|
||||
letter-spacing: 0 !important;
|
||||
position: relative;
|
||||
}
|
||||
.schedules-table-agent-th > div {
|
||||
position: absolute;
|
||||
bottom: 4px;
|
||||
left: 14px;
|
||||
transform-origin: left bottom;
|
||||
transform: rotate(-45deg);
|
||||
font-family: ui-monospace, 'JetBrains Mono', monospace;
|
||||
font-size: 0.9em;
|
||||
color: var(--fg);
|
||||
}
|
||||
.schedules-table-agent-th > div > span {
|
||||
display: inline-block;
|
||||
padding: 0 4px 1px;
|
||||
}
|
||||
.schedules-table tbody td {
|
||||
padding: 0.3em 0.5em;
|
||||
border-top: 1px solid var(--border);
|
||||
vertical-align: middle;
|
||||
}
|
||||
.schedules-table-row-cancelled td { opacity: 0.55; }
|
||||
.schedules-table-body-cell {
|
||||
max-width: 30em;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
font-family: ui-monospace, 'JetBrains Mono', monospace;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
.schedules-table-check {
|
||||
width: 28px;
|
||||
text-align: center;
|
||||
padding: 0.3em 0 !important;
|
||||
}
|
||||
.schedules-table-check-btn {
|
||||
background: transparent;
|
||||
border: 0;
|
||||
color: var(--green);
|
||||
cursor: pointer;
|
||||
padding: 0.1em 0.3em;
|
||||
font-family: inherit;
|
||||
font-size: 1em;
|
||||
}
|
||||
.schedules-table-check-btn:hover:not(:disabled) {
|
||||
color: var(--red);
|
||||
}
|
||||
.schedules-table-check-btn:disabled {
|
||||
cursor: default;
|
||||
}
|
||||
.schedules-table-check-cancelled {
|
||||
color: var(--muted);
|
||||
font-size: 0.9em;
|
||||
}
|
||||
.schedules-table-actions {
|
||||
text-align: right;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.schedules-table-actions .btn-inline-small {
|
||||
margin-left: 0.3em;
|
||||
}
|
||||
/* Edit form expands inline into a colspan'd row underneath the
|
||||
schedule it edits. Wrapper drops the form's normal background so it
|
||||
reads as "an extension of the row above" instead of a free-floating
|
||||
card. */
|
||||
.schedules-table-edit-row > td {
|
||||
padding: 0.5em 0.8em 0.8em !important;
|
||||
background: rgba(24, 24, 37, 0.4);
|
||||
}
|
||||
.schedule-targets-table tr:last-child td { border-bottom: 0; }
|
||||
.schedule-target-cancelled td { opacity: 0.5; }
|
||||
.btn-inline-small {
|
||||
font-size: 0.7em;
|
||||
padding: 0.1em 0.45em;
|
||||
|
|
|
|||
Loading…
Reference in a new issue