Public: anyone can read this; the crew can change it.

A board view's manage controls draw §5's bar and btn, and .bmanage leaves the markup #4287

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

scout/forge:scout/4199-a-board-view-s-manage-controls-draw-5-s → main 2 commits fork 2 threads · 2 unresolved

  • Merged. scout/4199-a-board-view-s-manage-controls-draw-5-s was merged into main as e4184d7.

Review

Sign in to review this change.
2 files changed +31 −14
src/web/pages/boards-view.ts +16 −14
@@ -140,24 +140,26 @@ function pinForm(slug: string, title: string, pinned: boolean): Html {
140140 }
141141
142142 function manage(slug: string, board: Board, adding: Html, pins: ReturnType<typeof listPins>): Html {
143 const one = (p: Panel, i: number) => html`<li class="row bmanage">
144 <details>
145 <summary><strong>${p.title}</strong> <span class="muted small">${CHART_NAMES[p.chart]} · ${String(p.w)}×${String(p.h)}</span></summary>
143 const one = (p: Panel, i: number) => html`<li class="row">
144 <details class="row-main">
145 <summary><strong class="break">${p.title}</strong> <span class="muted small">${CHART_NAMES[p.chart]} · ${String(p.w)}×${String(p.h)}</span></summary>
146146 ${panelForm(slug, "edit", p, i, queryFields(paramsOf(p.query, p.chart)))}
147147 </details>
148 ${pinForm(slug, p.title, isPinned(pins, slug, p.title))}
149 <form method="post" action="/boards/${slug}/move" class="row-actions">
150 <input type="hidden" name="index" value="${String(i)}" />
151 ${btn("Up", { size: "sm", name: "by", value: "-1", label: `Move ${p.title} up` })}
152 ${btn("Down", { size: "sm", name: "by", value: "1", label: `Move ${p.title} down` })}
153 </form>
154 <form method="post" action="/boards/${slug}/remove">
155 <input type="hidden" name="index" value="${String(i)}" />
156 ${btn("Remove", { size: "sm", variant: "danger", label: `Remove ${p.title}` })}
157 </form>
148 <div class="row-trail bar">

This .row-trail.bar is flex:none inside a nowrap .row, so at 360px it keeps ~330px and crushes .row-main (title and edit form). Add the .setting-list-style rule (flex-basis:100% for the trail under 640px, main with flex:1 1 18rem) so the controls drop below the title.

149 ${pinForm(slug, p.title, isPinned(pins, slug, p.title))}
150 <form method="post" action="/boards/${slug}/move" class="row-actions">
151 <input type="hidden" name="index" value="${String(i)}" />
152 ${btn("Up", { size: "sm", name: "by", value: "-1", label: `Move ${p.title} up` })}
153 ${btn("Down", { size: "sm", name: "by", value: "1", label: `Move ${p.title} down` })}
154 </form>
155 <form method="post" action="/boards/${slug}/remove">
156 <input type="hidden" name="index" value="${String(i)}" />
157 ${btn("Remove", { size: "sm", variant: "danger", label: `Remove ${p.title}` })}
158 </form>
159 </div>
158160 </li>`;
159161 return html`${card(
160 html`<ul class="list">${board.panels.map(one)}</ul>`,
162 html`<ul class="list setting-list">${board.panels.map(one)}</ul>`,
161163 { head: html`<h2>Panels</h2>`, pad: false },
162164 )}
163165 ${when(
test/boards-store.test.ts +15
@@ -168,6 +168,21 @@ describe("/boards", () => {
168168 expect(body).not.toContain('data-live-src="/boards');
169169 });
170170
171 test("manage controls draw §5's row and bar, not .bmanage, and keep every form", async () => {
172 const body = await (await asAdmin("/boards/fleet-health")).text();
173 expect(body).not.toContain("bmanage");
174 expect(body).toContain('class="row-trail bar"');
175 expect(body).toContain('class="list setting-list"');
176 expect(body).toContain('action="/boards/pin-panel"');
outdated

Simplify: the ternary builds one odd path. Assert the pin-panel action separately and the board-scoped ones in the loop. Add an assertion tied to the wrapping rule once it exists.

177 for (const op of ["move", "remove", "rename", "settings", "duplicate", "delete"]) {
178 expect(body).toContain(`action="/boards/fleet-health/${op}"`);
179 }
180 for (const word of ["Panels", "Add a panel", "Up", "Down", "Remove", "Pin to home", "Save settings", "Duplicate", "Delete this board"]) {
181 expect(body).toContain(word);
182 }
183 expect(body).toContain('<strong class="break">');
184 });
185
171186 test("settings turn on refresh, and the grid answers alone with an etag", async () => {
172187 const saved = await post("/boards/fleet-health/settings", { range: "24h", refresh: "10s" });
173188 expect(saved.status).toBe(303);

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs