@gavin-hu/my-pi-agent 0.21.0 → 0.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +46 -31
- package/README.zh-CN.md +40 -26
- package/assets/screens/board.png +0 -0
- package/assets/screens/chrome.png +0 -0
- package/assets/screens/file-browse.png +0 -0
- package/assets/screens/plan-review.png +0 -0
- package/assets/screens/plan.png +0 -0
- package/docs/extensions/README.md +22 -24
- package/docs/extensions/board.md +361 -147
- package/docs/extensions/bytefly.md +152 -111
- package/docs/extensions/check.md +15 -17
- package/docs/extensions/context.md +35 -15
- package/docs/extensions/file-browse.md +30 -31
- package/docs/extensions/file-open.md +9 -11
- package/docs/extensions/file-read.md +12 -14
- package/docs/extensions/goal.md +15 -17
- package/docs/extensions/job.md +54 -42
- package/docs/extensions/memory.md +17 -19
- package/docs/extensions/plan.md +166 -126
- package/docs/extensions/question.md +16 -18
- package/docs/extensions/rewind.md +17 -19
- package/docs/extensions/serve.md +34 -18
- package/docs/extensions/session-bus.md +38 -16
- package/docs/extensions/subagent.md +23 -25
- package/docs/extensions/team.md +72 -33
- package/docs/extensions/todo.md +18 -18
- package/docs/extensions/watch.md +31 -31
- package/docs/extensions/web-access.md +2 -4
- package/docs/extensions/wechat.md +34 -35
- package/docs/extensions/worktree.md +56 -50
- package/extensions/board/commands.ts +56 -15
- package/extensions/board/format.ts +43 -24
- package/extensions/board/index.ts +5 -4
- package/extensions/board/input.ts +4 -9
- package/extensions/board/join.ts +4 -40
- package/extensions/board/lazy-page.ts +40 -0
- package/extensions/board/page.ts +13 -11
- package/extensions/board/result.ts +30 -16
- package/extensions/board/rows.ts +62 -25
- package/extensions/board/schema.ts +42 -10
- package/extensions/board/snapshot.ts +2 -1
- package/extensions/board/tone.ts +22 -0
- package/extensions/board/tools.ts +131 -44
- package/extensions/board/types.ts +36 -32
- package/extensions/board/view/card.ts +229 -0
- package/extensions/board/view/client.ts +33 -15
- package/extensions/board/view/dialog.ts +169 -6
- package/extensions/board/view/empty.ts +47 -0
- package/extensions/board/view/keys.ts +13 -2
- package/extensions/board/view/live.ts +89 -21
- package/extensions/board/view/names.ts +13 -4
- package/extensions/board/view/page.ts +23 -9
- package/extensions/board/view/render.ts +208 -271
- package/extensions/board/view/styles.ts +123 -31
- package/extensions/board/view/team.ts +297 -76
- package/extensions/bytefly/block/fallback.ts +1 -1
- package/extensions/bytefly/doctor/runtime.ts +5 -2
- package/extensions/bytefly/footer/collect/label.ts +60 -0
- package/extensions/bytefly/footer/collect/snapshot.ts +8 -1
- package/extensions/bytefly/footer/config.ts +4 -2
- package/extensions/bytefly/footer/register.ts +33 -4
- package/extensions/bytefly/footer/render/lines.ts +7 -4
- package/extensions/bytefly/footer/render/segments.ts +37 -10
- package/extensions/bytefly/footer/render/status.ts +0 -11
- package/extensions/bytefly/footer/types.ts +7 -0
- package/extensions/bytefly/header/config.ts +1 -1
- package/extensions/bytefly/index.ts +32 -6
- package/extensions/bytefly/mode/editor.ts +115 -0
- package/extensions/bytefly/panel/commands.ts +210 -120
- package/extensions/bytefly/panel/format.ts +4 -4
- package/extensions/bytefly/panel/settings.ts +73 -6
- package/extensions/bytefly/panel/tui/keys.ts +2 -6
- package/extensions/bytefly/update/cache.ts +1 -1
- package/extensions/bytefly/update/register.ts +4 -4
- package/extensions/bytefly/working/config.ts +5 -7
- package/extensions/bytefly/working/format.ts +10 -13
- package/extensions/bytefly/working/register.ts +22 -27
- package/extensions/check/commands.ts +3 -2
- package/extensions/check/{tui.ts → view/check-screens.ts} +14 -19
- package/extensions/context/commands.ts +2 -2
- package/extensions/context/{tui.ts → view/context-report.ts} +51 -19
- package/extensions/file-browse/index.ts +67 -36
- package/extensions/file-read/render.ts +4 -4
- package/extensions/goal/plan-route.ts +2 -2
- package/extensions/job/child.ts +527 -0
- package/extensions/job/clock.ts +142 -0
- package/extensions/job/commands.ts +4 -2
- package/extensions/job/config.ts +8 -1
- package/extensions/job/format.ts +22 -1
- package/extensions/job/log-writer.ts +13 -2
- package/extensions/job/registry.ts +63 -7
- package/extensions/job/render.ts +34 -0
- package/extensions/job/runtime.ts +296 -655
- package/extensions/job/session.ts +132 -19
- package/extensions/job/store.ts +7 -7
- package/extensions/job/tools.ts +3 -3
- package/extensions/job/types.ts +47 -0
- package/extensions/job/{tui.ts → view/jobs-screen.ts} +19 -73
- package/extensions/job/waiters.ts +44 -1
- package/extensions/memory/commands.ts +4 -2
- package/extensions/memory/{tui.ts → view/memory-picker.ts} +12 -12
- package/extensions/plan/commands.ts +12 -9
- package/extensions/plan/format.ts +8 -2
- package/extensions/plan/git-bash.ts +115 -16
- package/extensions/plan/index.ts +53 -52
- package/extensions/plan/plan-index.ts +4 -2
- package/extensions/plan/plans.ts +5 -54
- package/extensions/plan/policy.ts +8 -10
- package/extensions/plan/review-lazy.ts +85 -0
- package/extensions/plan/review.ts +2 -2
- package/extensions/plan/runtime.ts +49 -39
- package/extensions/plan/sections.ts +1 -1
- package/extensions/plan/steps.ts +3 -3
- package/extensions/plan/todos.ts +1 -1
- package/extensions/plan/tools/cancel.ts +27 -62
- package/extensions/plan/tools/enter.ts +55 -81
- package/extensions/plan/tools/exit.ts +221 -238
- package/extensions/plan/tools/refusal.ts +18 -0
- package/extensions/plan/tools/steps.ts +75 -92
- package/extensions/plan/tools/write.ts +77 -120
- package/extensions/plan/tools.ts +188 -30
- package/extensions/plan/tui.ts +5 -5
- package/extensions/plan/types.ts +48 -5
- package/extensions/plan/web-client.ts +3 -0
- package/extensions/plan/web-lazy.ts +53 -0
- package/extensions/plan/web-markdown.ts +9 -67
- package/extensions/plan/web-payload.ts +3 -3
- package/extensions/plan/web-router.ts +18 -9
- package/extensions/plan/web.ts +1 -12
- package/extensions/question/tools.ts +6 -2
- package/extensions/question/{tui.ts → view/question-screen.ts} +11 -11
- package/extensions/rewind/commands/commands.ts +6 -3
- package/extensions/rewind/state/runtime.ts +1 -1
- package/extensions/rewind/{view/status.ts → status.ts} +4 -4
- package/extensions/rewind/view/review-tui.ts +4 -4
- package/extensions/serve/config.ts +10 -8
- package/extensions/serve/index.ts +17 -3
- package/extensions/serve/registry.ts +26 -17
- package/extensions/session-bus/commands.ts +11 -6
- package/extensions/session-bus/join-request.ts +2 -1
- package/extensions/session-bus/mail-watch.ts +26 -17
- package/extensions/session-bus/protocol.ts +15 -3
- package/extensions/session-bus/resolve.ts +5 -7
- package/extensions/session-bus/runtime.ts +40 -12
- package/extensions/session-bus/store.ts +101 -19
- package/extensions/session-bus/types.ts +19 -0
- package/extensions/session-bus/{tui.ts → view/session-list.ts} +16 -16
- package/extensions/subagent/agents.ts +1 -1
- package/extensions/subagent/commands.ts +4 -2
- package/extensions/subagent/format.ts +15 -15
- package/extensions/subagent/index.ts +1 -1
- package/extensions/subagent/render.ts +3 -3
- package/extensions/subagent/{background-tui.ts → view/agents-board.ts} +11 -11
- package/extensions/team/commands.ts +24 -7
- package/extensions/team/dispatch.ts +18 -4
- package/extensions/team/format.ts +17 -2
- package/extensions/team/index.ts +9 -8
- package/extensions/team/schema.ts +6 -5
- package/extensions/team/tools.ts +107 -45
- package/extensions/team/types.ts +3 -2
- package/extensions/todo/commands.ts +4 -2
- package/extensions/todo/format.ts +11 -0
- package/extensions/todo/render.ts +57 -0
- package/extensions/todo/runtime.ts +1 -1
- package/extensions/todo/tools.ts +1 -1
- package/extensions/todo/view/todo-screen.ts +122 -0
- package/extensions/todo/widget.ts +47 -0
- package/extensions/watch/commands.ts +4 -2
- package/extensions/watch/format.ts +36 -7
- package/extensions/watch/render.ts +57 -0
- package/extensions/watch/runtime.ts +27 -22
- package/extensions/watch/tools.ts +4 -4
- package/extensions/watch/{tui.ts → view/watch-screen.ts} +18 -80
- package/extensions/web-access/fetch/tool.ts +12 -4
- package/extensions/wechat/commands/commands.ts +18 -14
- package/extensions/wechat/index.ts +72 -37
- package/extensions/wechat/state/credentials.ts +1 -1
- package/extensions/wechat/state/state.ts +1 -1
- package/extensions/wechat/text/status.ts +112 -0
- package/extensions/wechat/types.ts +2 -2
- package/extensions/wechat/view/status-screen.ts +4 -103
- package/extensions/worktree/commands.ts +11 -9
- package/extensions/worktree/enter.ts +2 -2
- package/extensions/worktree/exit.ts +2 -2
- package/extensions/worktree/index.ts +5 -5
- package/extensions/worktree/screen.ts +3 -3
- package/extensions/worktree/status.ts +2 -2
- package/extensions/worktree/tools.ts +113 -116
- package/lib/README.md +27 -13
- package/lib/board/actions.ts +111 -0
- package/lib/board/artifact.ts +149 -0
- package/lib/board/card.ts +163 -52
- package/lib/board/config.ts +58 -0
- package/lib/board/contract.ts +113 -0
- package/lib/board/join.ts +38 -0
- package/lib/board/lanes.ts +182 -0
- package/lib/board/lead.ts +130 -0
- package/lib/board/limits.ts +78 -0
- package/lib/board/links.ts +31 -10
- package/lib/board/page-pointer.ts +1 -1
- package/lib/board/read.ts +83 -0
- package/lib/board/reason.ts +102 -0
- package/lib/board/round-text.ts +68 -6
- package/lib/board/round.ts +31 -15
- package/lib/board/rules.ts +151 -307
- package/lib/board/seat.ts +35 -0
- package/lib/board/session.ts +136 -54
- package/lib/board/skipped.ts +22 -0
- package/lib/board/steps.ts +487 -0
- package/lib/board/store.ts +87 -30
- package/lib/board/tone.ts +92 -0
- package/lib/board/view.ts +70 -58
- package/{extensions/watch → lib}/child.ts +40 -21
- package/lib/env.ts +65 -7
- package/lib/format.ts +13 -0
- package/lib/http/index.ts +14 -12
- package/lib/http/port.ts +15 -10
- package/lib/lazy.ts +45 -0
- package/lib/plan-entry.ts +39 -10
- package/lib/plans/paths.ts +82 -0
- package/lib/policy.ts +9 -6
- package/lib/report.ts +3 -2
- package/lib/requirements.ts +8 -8
- package/lib/session-label.ts +111 -5
- package/lib/session-roster.ts +43 -1
- package/lib/session-tool.ts +5 -4
- package/lib/stray-fields.ts +7 -2
- package/lib/tool-names.ts +5 -10
- package/lib/tui/README.md +23 -8
- package/lib/tui/chrome.ts +16 -15
- package/lib/tui/cursor.ts +18 -3
- package/lib/tui/glyphs.ts +9 -7
- package/lib/tui/tokens.ts +33 -2
- package/lib/tui/tool.ts +3 -3
- package/lib/web/README.md +21 -0
- package/lib/web/components.ts +5 -1
- package/lib/web/index.ts +1 -0
- package/lib/web/markdown.ts +83 -0
- package/lib/web/markup.ts +2 -1
- package/lib/web/runtime.ts +9 -10
- package/package.json +6 -1
- package/skills/init/SKILL.md +5 -5
- package/skills/next/SKILL.md +3 -5
- package/extensions/board/seat.ts +0 -28
- package/extensions/todo/tui.ts +0 -212
- package/lib/tui/index.ts +0 -34
- package/skills/project-docs/SKILL.md +0 -133
- package/skills/project-docs/references/audit.md +0 -131
- package/skills/project-docs/references/changelog.md +0 -105
- package/skills/project-docs/references/discovery.md +0 -127
- package/skills/project-docs/references/readme.md +0 -80
- package/skills/project-docs/references/release.md +0 -84
- package/skills/project-docs/references/roadmap.md +0 -93
- package/skills/project-docs/scripts/state.ts +0 -316
|
@@ -3,8 +3,9 @@
|
|
|
3
3
|
*
|
|
4
4
|
* A frame is a whole snapshot, so every message repaints from it rather than patching
|
|
5
5
|
* it — the renderer decides what actually changed. The only client state is which tab
|
|
6
|
-
* is showing, the filter text, which lanes are collapsed,
|
|
7
|
-
*
|
|
6
|
+
* is showing, the filter text, which lanes are collapsed, which card's dialog is open,
|
|
7
|
+
* and where the reader is on the board — the card they are on and the ones they have
|
|
8
|
+
* read; none of it is authoritative, and none of it is sent anywhere.
|
|
8
9
|
*/
|
|
9
10
|
|
|
10
11
|
export const BOARD_LIVE_JS = String.raw`(function () {
|
|
@@ -28,7 +29,7 @@ export const BOARD_LIVE_JS = String.raw`(function () {
|
|
|
28
29
|
else node.textContent = "connecting…";
|
|
29
30
|
}
|
|
30
31
|
|
|
31
|
-
/** Show one tab: the panel,
|
|
32
|
+
/** Show one tab: the panel, the selected tab, and the address so a link is shareable. */
|
|
32
33
|
function showView(view) {
|
|
33
34
|
var team = view === "team";
|
|
34
35
|
document.documentElement.setAttribute("data-view", team ? "team" : "board");
|
|
@@ -37,14 +38,40 @@ export const BOARD_LIVE_JS = String.raw`(function () {
|
|
|
37
38
|
var tabs = document.querySelectorAll("[data-view][role='tab']");
|
|
38
39
|
for (var i = 0; i < tabs.length; i++) {
|
|
39
40
|
var current = tabs[i].getAttribute("data-view") === (team ? "team" : "board");
|
|
40
|
-
|
|
41
|
-
|
|
41
|
+
// A tablist is read through aria-selected, and a roving tabindex is what makes one
|
|
42
|
+
// Tab land on the strip rather than on each tab in turn. Both are the markup's own
|
|
43
|
+
// attributes: a state painted only in a class is a state a screen reader cannot read.
|
|
44
|
+
tabs[i].setAttribute("aria-selected", current ? "true" : "false");
|
|
45
|
+
tabs[i].setAttribute("tabindex", current ? "0" : "-1");
|
|
42
46
|
}
|
|
43
47
|
var url = new URL(window.location.href);
|
|
44
48
|
url.searchParams.set("view", team ? "team" : "board");
|
|
45
49
|
window.history.replaceState(null, "", url.toString());
|
|
46
50
|
}
|
|
47
51
|
|
|
52
|
+
/**
|
|
53
|
+
* Arrow keys move along the tab strip, the way a tablist is expected to behave.
|
|
54
|
+
*
|
|
55
|
+
* Automatic activation: the panels are both in the document already, so showing one is a
|
|
56
|
+
* hidden attribute rather than a request, and a reader who arrows across the strip sees
|
|
57
|
+
* each tab he lands on. Home and End are the ends of it.
|
|
58
|
+
*/
|
|
59
|
+
function bindTabKeys(tabs) {
|
|
60
|
+
for (var i = 0; i < tabs.length; i++) {
|
|
61
|
+
tabs[i].addEventListener("keydown", function (event) {
|
|
62
|
+
var names = ["ArrowLeft", "ArrowRight", "Home", "End"];
|
|
63
|
+
if (names.indexOf(event.key) === -1) return;
|
|
64
|
+
event.preventDefault();
|
|
65
|
+
var at = 0;
|
|
66
|
+
for (var j = 0; j < tabs.length; j++) if (tabs[j] === event.currentTarget) at = j;
|
|
67
|
+
var step = event.key === "ArrowLeft" ? -1 : 1;
|
|
68
|
+
var next = event.key === "Home" ? 0 : event.key === "End" ? tabs.length - 1 : (at + step + tabs.length) % tabs.length;
|
|
69
|
+
showView(tabs[next].getAttribute("data-view"));
|
|
70
|
+
tabs[next].focus();
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
48
75
|
board.viewName = function () {
|
|
49
76
|
return document.documentElement.getAttribute("data-view") === "team" ? "team" : "board";
|
|
50
77
|
};
|
|
@@ -54,27 +81,40 @@ export const BOARD_LIVE_JS = String.raw`(function () {
|
|
|
54
81
|
var narrow = window.matchMedia && window.matchMedia("(max-width: 860px)").matches;
|
|
55
82
|
var lanes = document.querySelectorAll(".board-lane");
|
|
56
83
|
for (var i = 0; i < lanes.length; i++) {
|
|
57
|
-
var selected = lanes[i].getAttribute("data-
|
|
84
|
+
var selected = lanes[i].getAttribute("data-lane") === board.shown;
|
|
58
85
|
lanes[i].hidden = narrow && !selected;
|
|
59
86
|
}
|
|
60
|
-
var items = document.querySelectorAll("#board-picker [data-lane]");
|
|
87
|
+
var items = document.querySelectorAll("#board-picker [data-picker-lane]");
|
|
61
88
|
for (var j = 0; j < items.length; j++) {
|
|
62
|
-
|
|
63
|
-
|
|
89
|
+
// A pressed button, because the picker shows one lane rather than joining a tablist:
|
|
90
|
+
// "true" is the lane a reader is looking at, and the kit paints it from this state.
|
|
91
|
+
items[j].setAttribute("aria-pressed", items[j].getAttribute("data-picker-lane") === board.shown ? "true" : "false");
|
|
64
92
|
}
|
|
65
93
|
}
|
|
66
94
|
|
|
67
95
|
board.applyLane = applyLane;
|
|
68
96
|
|
|
69
97
|
board.showLane = function (lane) {
|
|
70
|
-
board.
|
|
98
|
+
board.shown = lane;
|
|
71
99
|
applyLane();
|
|
72
100
|
};
|
|
73
101
|
|
|
74
|
-
/**
|
|
75
|
-
|
|
102
|
+
/**
|
|
103
|
+
* Fold one list away and leave its control standing.
|
|
104
|
+
*
|
|
105
|
+
* Three things on the page fold: a lane, the roster's tail of owners nothing answers to, and
|
|
106
|
+
* the Done strip. They share one map, and a key says which kind it is: a lane keeps its own
|
|
107
|
+
* name, and the two the Team tab owns are team-roster and team-done, because done is
|
|
108
|
+
* already a lane.
|
|
109
|
+
*
|
|
110
|
+
* The key is also recorded, because the panel a fold lives in is repainted: the element the
|
|
111
|
+
* reader clicked no longer exists when the frame lands, and the renderer focuses
|
|
112
|
+
* data-fold="<key>" to put the keyboard back where it was.
|
|
113
|
+
*/
|
|
114
|
+
board.toggleFold = function (key) {
|
|
76
115
|
board.collapsed = board.collapsed || {};
|
|
77
|
-
board.collapsed[
|
|
116
|
+
board.collapsed[key] = board.collapsed[key] !== true;
|
|
117
|
+
board.foldFocus = key;
|
|
78
118
|
if (board.view) board.render(board.view);
|
|
79
119
|
};
|
|
80
120
|
|
|
@@ -121,14 +161,14 @@ export const BOARD_LIVE_JS = String.raw`(function () {
|
|
|
121
161
|
* The grey cards a page shows while it waits for its first frame.
|
|
122
162
|
*
|
|
123
163
|
* They are marked as placeholders rather than given a lane status: the renderer
|
|
124
|
-
* looks lanes up by data-
|
|
164
|
+
* looks lanes up by data-lane, so a skeleton that carried one would be adopted
|
|
125
165
|
* as the real lane and the cards would never be drawn into it.
|
|
126
166
|
*/
|
|
127
167
|
function skeletons() {
|
|
128
168
|
var lanes = document.getElementById("board-lanes");
|
|
129
169
|
if (!lanes || lanes.childElementCount > 0) return;
|
|
130
170
|
lanes.setAttribute("data-skeleton", "1");
|
|
131
|
-
for (var i = 0; i <
|
|
171
|
+
for (var i = 0; i < board.laneCount; i++) {
|
|
132
172
|
var lane = board.el("section", N.lane);
|
|
133
173
|
for (var j = 0; j < 2; j++) lane.appendChild(board.el("div", N.skeleton));
|
|
134
174
|
lanes.appendChild(lane);
|
|
@@ -137,18 +177,18 @@ export const BOARD_LIVE_JS = String.raw`(function () {
|
|
|
137
177
|
|
|
138
178
|
/**
|
|
139
179
|
* The lane a narrow reader lands on: the first with a card in it, else the first
|
|
140
|
-
* lane. Opening on an empty
|
|
180
|
+
* lane. Opening on an empty Backlog while the only card sits in Blocked is a blank
|
|
141
181
|
* page with a picker nobody has a reason to press.
|
|
142
182
|
*/
|
|
143
183
|
function laneWithWork(view) {
|
|
144
|
-
for (var i = 0; i < view.lanes.length; i++) if (view.lanes[i].cards.length > 0) return view.lanes[i].
|
|
145
|
-
return view.lanes[0] ? view.lanes[0].
|
|
184
|
+
for (var i = 0; i < view.lanes.length; i++) if (view.lanes[i].cards.length > 0) return view.lanes[i].key;
|
|
185
|
+
return view.lanes[0] ? view.lanes[0].key : "backlog";
|
|
146
186
|
}
|
|
147
187
|
|
|
148
188
|
/** One frame: paint and record when it arrived. */
|
|
149
189
|
function paint(view) {
|
|
150
190
|
board.lastFrame = Date.now();
|
|
151
|
-
board.
|
|
191
|
+
board.shown = board.shown || laneWithWork(view);
|
|
152
192
|
badge("live", board.lastFrame);
|
|
153
193
|
board.render(view);
|
|
154
194
|
}
|
|
@@ -181,16 +221,36 @@ export const BOARD_LIVE_JS = String.raw`(function () {
|
|
|
181
221
|
board.applyFilter();
|
|
182
222
|
});
|
|
183
223
|
}
|
|
224
|
+
// The no-match state's one control: a view action, like the tab switch, and it puts the
|
|
225
|
+
// reader back in the field they were typing in.
|
|
226
|
+
var clear = document.getElementById("board-no-match-clear");
|
|
227
|
+
if (clear) {
|
|
228
|
+
clear.addEventListener("click", function () {
|
|
229
|
+
board.clearFilter();
|
|
230
|
+
board.focusFilter();
|
|
231
|
+
});
|
|
232
|
+
}
|
|
184
233
|
var tabs = document.querySelectorAll("[data-view][role='tab']");
|
|
185
234
|
for (var i = 0; i < tabs.length; i++) {
|
|
186
235
|
tabs[i].addEventListener("click", function (event) {
|
|
187
236
|
showView(event.currentTarget.getAttribute("data-view"));
|
|
188
237
|
});
|
|
189
238
|
}
|
|
239
|
+
bindTabKeys(tabs);
|
|
240
|
+
// A card's title button takes the keyboard from j/k, a Tab, or a click, and the mark
|
|
241
|
+
// follows focus rather than the key that moved it. A focus outside the cards leaves the
|
|
242
|
+
// last card marked, which is what a reader coming back from the filter expects.
|
|
243
|
+
document.addEventListener("focusin", function (event) {
|
|
244
|
+
var node = event.target;
|
|
245
|
+
var card = node && node.closest ? node.closest(".board-card") : null;
|
|
246
|
+
if (!card) return;
|
|
247
|
+
board.current = card.getAttribute("data-card");
|
|
248
|
+
board.markCards();
|
|
249
|
+
});
|
|
190
250
|
var picker = document.getElementById("board-picker");
|
|
191
251
|
if (picker) {
|
|
192
252
|
picker.addEventListener("click", function (event) {
|
|
193
|
-
var lane = event.target && event.target.getAttribute ? event.target.getAttribute("data-lane") : null;
|
|
253
|
+
var lane = event.target && event.target.getAttribute ? event.target.getAttribute("data-picker-lane") : null;
|
|
194
254
|
if (lane) board.showLane(lane);
|
|
195
255
|
});
|
|
196
256
|
}
|
|
@@ -212,10 +272,18 @@ export const BOARD_LIVE_JS = String.raw`(function () {
|
|
|
212
272
|
}
|
|
213
273
|
|
|
214
274
|
board.start = function () {
|
|
215
|
-
board.
|
|
275
|
+
board.shown = undefined;
|
|
216
276
|
board.openId = undefined;
|
|
217
277
|
board.query = "";
|
|
218
278
|
board.collapsed = {};
|
|
279
|
+
// The fold a reader just moved, and the panels' remembered signatures: both belong to the
|
|
280
|
+
// tab, and a fresh tab is a fresh read of what the store holds.
|
|
281
|
+
board.foldFocus = undefined;
|
|
282
|
+
board.teamPanels = undefined;
|
|
283
|
+
// Where the reader is and has been: the two marks a card face can wear, which live as
|
|
284
|
+
// long as the tab does and never reach the store.
|
|
285
|
+
board.current = undefined;
|
|
286
|
+
board.visited = {};
|
|
219
287
|
showView(new URLSearchParams(window.location.search).get("view") === "team" ? "team" : "board");
|
|
220
288
|
wireChrome();
|
|
221
289
|
skeletons();
|
|
@@ -35,16 +35,23 @@ export const BOARD_CLASS = {
|
|
|
35
35
|
laneList: "board-lane__list",
|
|
36
36
|
laneEmpty: "board-lane__empty",
|
|
37
37
|
|
|
38
|
-
// One card, and the two tones its reason line can take.
|
|
38
|
+
// One card, the facts its meta line carries, and the two tones its reason line can take.
|
|
39
39
|
card: "board-card",
|
|
40
40
|
cardHead: "board-card__head",
|
|
41
41
|
cardId: "board-card__id",
|
|
42
42
|
cardTitle: "board-card__title",
|
|
43
43
|
cardMeta: "board-card__meta",
|
|
44
|
+
cardNotes: "board-card__notes",
|
|
44
45
|
cardPaths: "board-card__paths",
|
|
45
46
|
cardReason: "board-card__reason",
|
|
46
|
-
|
|
47
|
-
|
|
47
|
+
// One class per tone, never per reason kind: the same tone is what the terminal paints.
|
|
48
|
+
cardReasonMuted: "board-card__reason--muted",
|
|
49
|
+
cardReasonDim: "board-card__reason--dim",
|
|
50
|
+
cardReasonWarn: "board-card__reason--warn",
|
|
51
|
+
cardReasonAccent: "board-card__reason--accent",
|
|
52
|
+
cardReasonDanger: "board-card__reason--danger",
|
|
53
|
+
cardReasonSuccess: "board-card__reason--success",
|
|
54
|
+
cardHolds: "board-card__holds",
|
|
48
55
|
|
|
49
56
|
// The card dialog: the record of one card, as a ladder of facts and its notes.
|
|
50
57
|
dialogPanel: "board-dialog__panel",
|
|
@@ -79,7 +86,6 @@ export const BOARD_CLASS = {
|
|
|
79
86
|
teamTitle: "board-team__title",
|
|
80
87
|
teamFoot: "board-team__foot",
|
|
81
88
|
teamWhy: "board-team__why",
|
|
82
|
-
teamWhyBlocked: "board-team__why--blocked",
|
|
83
89
|
teamRoster: "board-team__roster",
|
|
84
90
|
teamMate: "board-team__mate",
|
|
85
91
|
teamDot: "board-team__dot",
|
|
@@ -88,4 +94,7 @@ export const BOARD_CLASS = {
|
|
|
88
94
|
teamEmpty: "board-team__empty",
|
|
89
95
|
teamDone: "board-team__done",
|
|
90
96
|
teamId: "board-team__id",
|
|
97
|
+
teamDoneIds: "board-team__ids",
|
|
98
|
+
teamTail: "board-team__tail",
|
|
99
|
+
teamFold: "board-team__fold",
|
|
91
100
|
} as const satisfies Readonly<Record<string, string>>;
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
* contract test holds every class to the kit or to this page's stylesheet.
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
|
+
import { escapeHtml } from "../../../lib/escape.ts";
|
|
16
17
|
import {
|
|
17
18
|
baseAttribute,
|
|
18
19
|
brandLockup,
|
|
@@ -36,7 +37,14 @@ export type PageView = "board" | "team";
|
|
|
36
37
|
* shared link opens the tab it names. The document has no form and no write affordance:
|
|
37
38
|
* a page that cannot change a card cannot offer a button the server would refuse.
|
|
38
39
|
*/
|
|
39
|
-
export function renderBoardPage(input: {
|
|
40
|
+
export function renderBoardPage(input: {
|
|
41
|
+
view: PageView;
|
|
42
|
+
base?: string;
|
|
43
|
+
/** The repository this page is a board of, which its header names. */
|
|
44
|
+
repo: string;
|
|
45
|
+
/** The repository root, which is the header name's hover: a name alone cannot tell two clones apart. */
|
|
46
|
+
root: string;
|
|
47
|
+
}): string {
|
|
40
48
|
const team = input.view === "team";
|
|
41
49
|
// The page answers under the session's mount, so its own script and theme are named
|
|
42
50
|
// from that prefix rather than from the origin's root.
|
|
@@ -51,13 +59,13 @@ ${docHead({ title: tabTitle("board"), css: BOARD_CSS, base })}
|
|
|
51
59
|
<a class="skip" href="#main">Skip to the cards</a>
|
|
52
60
|
<header class="bf-app__header"><div class="bf-toolbar ${N.toolbar}">
|
|
53
61
|
${brandLockup("board")}
|
|
54
|
-
<span class="bf-chip bf-chip--
|
|
62
|
+
<span class="bf-chip bf-chip--outline" id="board-repo" title="${escapeHtml(input.root)}">${escapeHtml(input.repo)}</span>
|
|
55
63
|
<p class="bf-status ${N.status}" id="board-status" data-state="connecting" aria-live="polite">connecting…</p>
|
|
56
64
|
<span class="bf-spacer"></span>
|
|
57
65
|
<div class="${N.controls}">
|
|
58
66
|
<div class="bf-segmented" role="tablist" aria-label="View">
|
|
59
|
-
<button type="button" class="bf-segmented__item" role="tab" id="tab-board" data-view="board" aria-controls="panel-board"${team ? "" :
|
|
60
|
-
<button type="button" class="bf-segmented__item" role="tab" id="tab-team" data-view="team" aria-controls="panel-team"${team ?
|
|
67
|
+
<button type="button" class="bf-segmented__item" role="tab" id="tab-board" data-view="board" aria-controls="panel-board" aria-selected="${team ? "false" : "true"}" tabindex="${team ? "-1" : "0"}">Board</button>
|
|
68
|
+
<button type="button" class="bf-segmented__item" role="tab" id="tab-team" data-view="team" aria-controls="panel-team" aria-selected="${team ? "true" : "false"}" tabindex="${team ? "0" : "-1"}">Team</button>
|
|
61
69
|
</div>
|
|
62
70
|
<p class="bf-progress ${N.progress}" id="board-progress" hidden>
|
|
63
71
|
<span class="bf-progress__track"><span class="bf-progress__fill" id="board-progress-fill"></span></span>
|
|
@@ -72,12 +80,13 @@ ${docHead({ title: tabTitle("board"), css: BOARD_CSS, base })}
|
|
|
72
80
|
</div></header>
|
|
73
81
|
<main class="bf-app__main ${N.main}" id="main" tabindex="-1">
|
|
74
82
|
<section class="${N.panel}" id="panel-board" role="tabpanel" aria-labelledby="tab-board"${team ? " hidden" : ""}>
|
|
75
|
-
<div class="bf-segmented ${N.picker}" id="board-picker" role="
|
|
83
|
+
<div class="bf-segmented ${N.picker}" id="board-picker" role="group" aria-label="Lane"></div>
|
|
76
84
|
<div class="${N.lanes}" id="board-lanes"></div>
|
|
77
85
|
<div class="bf-empty ${N.noCards}" id="board-no-cards" hidden>
|
|
78
|
-
<p class="bf-empty__title">No cards yet</p>
|
|
79
|
-
<p class="bf-empty__sub">One card per feature: what it delivers, who holds it, and where to start.</p>
|
|
80
|
-
<p class="bf-empty__sub"><code>board add</code> makes one — this page reads, and the tools write.</p>
|
|
86
|
+
<p class="bf-empty__title" id="board-no-cards-title">No cards yet</p>
|
|
87
|
+
<p class="bf-empty__sub" id="board-no-cards-sub">One card per feature: what it delivers, who holds it, and where to start.</p>
|
|
88
|
+
<p class="bf-empty__sub" id="board-no-cards-hint"><code>board add</code> makes one — this page reads, and the tools write.</p>
|
|
89
|
+
<button type="button" class="bf-btn" id="board-no-match-clear" hidden>Clear filter</button>
|
|
81
90
|
</div>
|
|
82
91
|
</section>
|
|
83
92
|
<section class="${N.panel}" id="panel-team" role="tabpanel" aria-labelledby="tab-team"${team ? "" : " hidden"}>
|
|
@@ -109,6 +118,11 @@ ${docHead({ title: tabTitle("board"), css: BOARD_CSS, base })}
|
|
|
109
118
|
<dt id="card-dialog-depends-label" hidden>waits on</dt><dd class="${N.dialogValue}" id="card-dialog-depends" hidden></dd>
|
|
110
119
|
<dt id="card-dialog-dependents-label" hidden>waited on by</dt><dd class="${N.dialogValue}" id="card-dialog-dependents" hidden></dd>
|
|
111
120
|
<dt id="card-dialog-plan-label" hidden>plan</dt><dd class="${N.dialogValue} ${N.dialogPlan}" id="card-dialog-plan" hidden></dd>
|
|
121
|
+
<dt id="card-dialog-goal-label" hidden>goal</dt><dd class="${N.dialogValue}" id="card-dialog-goal" hidden></dd>
|
|
122
|
+
<dt id="card-dialog-acceptance-label" hidden>acceptance</dt><dd class="${N.dialogValue}" id="card-dialog-acceptance" hidden></dd>
|
|
123
|
+
<dt id="card-dialog-scope-out-label" hidden>scope out</dt><dd class="${N.dialogValue}" id="card-dialog-scope-out" hidden></dd>
|
|
124
|
+
<dt id="card-dialog-approved-label" hidden>approved</dt><dd class="${N.dialogValue}" id="card-dialog-approved" hidden></dd>
|
|
125
|
+
<dt id="card-dialog-reviewed-label" hidden>reviewed</dt><dd class="${N.dialogValue}" id="card-dialog-reviewed" hidden></dd>
|
|
112
126
|
<dt id="card-dialog-paths-label" hidden>paths</dt><dd id="card-dialog-paths" hidden><ul class="${N.dialogPaths}" id="card-dialog-path-list"></ul></dd>
|
|
113
127
|
</dl>
|
|
114
128
|
</section>
|
|
@@ -121,7 +135,7 @@ ${docHead({ title: tabTitle("board"), css: BOARD_CSS, base })}
|
|
|
121
135
|
</div>
|
|
122
136
|
</div>
|
|
123
137
|
|
|
124
|
-
${keysSheet(BOARD_KEYS)}
|
|
138
|
+
${keysSheet(BOARD_KEYS, "A card dialog keeps /, t, and ? for itself; Esc closes it.")}
|
|
125
139
|
<script src="${base}/app.js" defer></script>
|
|
126
140
|
</body>
|
|
127
141
|
</html>
|