T5.3 - B4 surface: a pipeline strip, four server counts, four shareable links
Four cells on the launcher - Work packages, Release ready, On hold, Overdue -
every number from /api/wps/metrics, which T4.1 built. There is deliberately no
cache fallback anywhere in renderPipeline(): a remembered number sitting beside
three live ones is the failure B4 exists to remove, wearing a different hat.
The cells are the four the endpoint already computes and the dashboard already
filters on, so they map 1:1 onto its flags rather than inventing a fifth slice
nothing downstream understands. wp-creation-app.js now names them (DASH_FLAGS)
for the same reason: a cell linking to a filter the board does not recognise is
a dead link that still looks live.
"Links to a filtered view via a shareable URL" needed the filter to BE URL state,
which it was not - the dashboard kept its flag in a variable. So:
- dashToggleFlag pushes ?flag=<f>, and clears it on the way out of the board
- the creator applies ?flag= before its first render, not after (applying it
after paints the whole board and throws it away)
- Back and Forward move through filters like any other state
- work-package-suite-app.js forwards the flag ACROSS the iframe boundary, since
the creator's src carries only the project. B7/T7.1 dissolves that frame and
this hand-off goes with it; it is commented as such.
Zero is a real answer for one slice of a project that has work in it. Four zeros
on a project with none is not a reading, it is a strip that looks broken - that
case gets a sentence and a way into the creator instead. A failed request gets an
explicit error naming the failure, and no cells at all.
html/index.html the strip, its states, PIPE_CELLS
html/wp-creation-app.js flag as URL state; DASH_FLAGS; dashApplyFlag
html/work-package-suite-app.js forward the flag into the frame; clear on exit
tests/pipeline_check.py new - 43 checks
Done when
[x] every number comes from a server endpoint - proved by poisoning localStorage
with 99 fake packages and demanding the strip still read the server's 4
[x] each cell links to a filtered view via a shareable URL - and the probe
FOLLOWS the link and reads the filter inside the frame rather than trusting
that a correct-looking URL was built
[x] a project with zero work packages renders a sensible empty state
[x] the strip announces updates via aria-live (polite - a count is not an
interruption) and reports aria-busy while it is counting
What the probe caught
The link landed on "Complete the SOP Configuration first". Not the strip's
fault: browser_check.py's fixture stores a bare {governance: …} blob as the SOP
data, where production stores {sop, state}. restoreSavedSOP() needs `state` and
bails without it, so sopComplete stays false and the WP tab shows its gate.
pipeline_check seeds the production shape. The underlying wart is real and is
logged rather than fixed - see BL-018.
Verified one at a time
pipeline_check 43/43 new
launcher_check 58/58
stepper_check 70/70
url_state 23/23 the dashboard's new flag state did not disturb it
aggregates 16/16
browser_check 71/71
a11y 22/22
autosave 34/34
f_items F1-F5 FIXED, F6 REPRODUCES (T7.2)
No colour literal added: still 0 across all page sheets and inline blocks. The
four cells are told apart by a label, a sentence and an accent - three channels,
so colour is not carrying it alone (C1).
Raised, not fixed
BL-018 The WP tab's gate is the last localStorage-derived status in the app.
T4.1 moved the launcher's card to the server; the wizard page still
decides gate-or-creator from wp_suite_sop_complete plus a state blob.
pullProject refreshes both on load so a connected user is fine, but the
two answers come from different places and the fallback is silent.
Includes a second, sharper edge: project-data.js:210 writes that flag
for ANY row returned, including one with no `state` to restore - so the
flag is written and never read consistently. T7.1 owns it.
Question for the PR, per CLAUDE.md: the strip counts Overdue against `data.due`,
which is free text today. CR-004/CR-018 restructure location but not dates. If
"overdue" is going to drive anything beyond a launcher tile, that field needs a
type.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -519,8 +519,12 @@ function switchTool(tool, opts){
|
||||
// restoring because the user pressed Back - recording that as a new entry would
|
||||
// make Back appear to do nothing.
|
||||
if(typeof WPUrl !== 'undefined' && !(opts && opts.fromUrl)){
|
||||
// `flag` is the dashboard's filter (T5.3). It rides in the URL so a pipeline
|
||||
// cell is shareable, which also means it has to be cleared on the way out —
|
||||
// otherwise leaving the board and coming back re-applies a filter nobody asked
|
||||
// for a second time.
|
||||
WPUrl.push(tool === 'dashboard' ? { tab: 'wp', view: 'dashboard' }
|
||||
: { tab: tool, view: '' });
|
||||
: { tab: tool, view: '', flag: '' });
|
||||
}
|
||||
// 'dashboard' is a pseudo-tab: it reuses the WP tool's content (the embedded
|
||||
// creator) but opens it straight to the dashboard view.
|
||||
@@ -641,7 +645,16 @@ function renderWPTab(wantDash){
|
||||
if(wantWp && typeof cw.openWpById === 'function' && !cw.openWpById(wantWp)){
|
||||
if(typeof cw.toast === 'function') cw.toast('That work package is not on this project.');
|
||||
}
|
||||
if(dash && typeof cw.showDashboard === 'function') cw.showDashboard();
|
||||
if(dash && typeof cw.showDashboard === 'function'){
|
||||
// T5.3: the launcher's pipeline cells link to a filtered board. The
|
||||
// creator is an iframe child whose src carries only the project, so the
|
||||
// filter has to be handed across rather than read from the child's own
|
||||
// URL — and BEFORE showDashboard(), which renders. B7/T7.1 dissolves
|
||||
// this frame and this hand-off goes with it.
|
||||
const flag = new URLSearchParams(window.location.search).get('flag') || '';
|
||||
if(typeof cw.dashApplyFlag === 'function') cw.dashApplyFlag(flag);
|
||||
cw.showDashboard();
|
||||
}
|
||||
else if(!dash && typeof cw.showForm === 'function') cw.showForm();
|
||||
} catch(e){ /* cross-document timing; nothing useful to do */ }
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user