@bongos/core 1.17.2 → 1.18.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/.bongos-core.json +426 -96
- package/.devcontainer/healthcheck.sh +0 -0
- package/.devcontainer/init-firewall.sh +0 -0
- package/.devcontainer/post-create.sh +0 -0
- package/GOVERNANCE.md +1 -1
- package/README.md +26 -22
- package/bin/bongos.js +0 -0
- package/clients/bongos-client/README.md +1 -1
- package/clients/bongos-client/bongos-client.global.js +2 -0
- package/clients/bongos-client/index.cjs +2 -0
- package/clients/bongos-client/index.d.ts +4 -2
- package/clients/bongos-client/index.mjs +2 -0
- package/docker-entrypoint.sh +0 -0
- package/docs/adr/0139-platform-history-migration-to-cloudbongos.md +94 -0
- package/docs/adr/0140-cloudbongos-standalone-reprovision.md +43 -0
- package/docs/adr/README.md +3 -0
- package/docs/api/openapi.json +68 -370
- package/docs/api-reference.md +7 -18
- package/docs/file-map.md +7 -25
- package/docs/onboarding/diagrams/05-versioning.mmd +4 -6
- package/docs/onboarding/diagrams/assertions.json +5 -9
- package/modules/hall-ui/public/builders.js +132 -645
- package/modules/hall-ui/public/goal-inbox.js +67 -26
- package/modules/hall-ui/public/goals-page.js +102 -177
- package/modules/hall-ui/public/goals.css +183 -0
- package/modules/hall-ui/public/goals.html +35 -253
- package/modules/hall-ui/public/goals.js +7 -2
- package/modules/hall-ui/public/hall-kit.js +474 -0
- package/modules/hall-ui/public/hall-widgets.js +24 -20
- package/modules/hall-ui/public/instances-panel.js +24 -3
- package/modules/hall-ui/public/new-project-wizard.js +6 -5
- package/modules/hall-ui/public/settings.css +355 -0
- package/modules/hall-ui/public/settings.html +86 -414
- package/modules/hall-ui/public/settings.js +96 -35
- package/modules/hall-ui/public/style.css +156 -0
- package/modules/hall-ui/public/watch.css +184 -0
- package/modules/hall-ui/public/watch.html +111 -285
- package/modules/hall-ui/public/watch.js +59 -21
- package/modules/hall-ui/public/work.css +194 -0
- package/modules/hall-ui/public/work.html +46 -374
- package/modules/hall-ui/public/work.js +137 -102
- package/modules/lifecycle/criterion-suggest.js +80 -0
- package/modules/lifecycle/db.js +42 -5
- package/modules/lifecycle/routes/goals.js +26 -0
- package/modules/lifecycle/routes/tasks.js +21 -0
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/public-landing/create.html +83 -7
- package/public-landing/index.html +11 -76
- package/scripts/cron/style_guide_audit.sh +0 -0
- package/scripts/gds/api.js +0 -0
- package/scripts/gds/architect-audit.js +0 -0
- package/scripts/gds/audit-authorship.sh +0 -0
- package/scripts/gds/audit-replay.sh +0 -0
- package/scripts/gds/box.js +0 -0
- package/scripts/gds/capture.js +0 -0
- package/scripts/gds/conductor-dispatch.js +0 -0
- package/scripts/gds/coreB-carve-proof.sh +0 -0
- package/scripts/gds/db-backup-nightly.sh +0 -0
- package/scripts/gds/db-backup-offsite.sh +0 -0
- package/scripts/gds/doctor.js +0 -0
- package/scripts/gds/grade-smoke.js +0 -0
- package/scripts/gds/hooks/pre-push.js +0 -0
- package/scripts/gds/install-git-hooks.js +0 -0
- package/scripts/gds/main-audit.js +0 -0
- package/scripts/gds/oauth-secret.js +0 -0
- package/scripts/gds/onboarding-analyze.js +0 -0
- package/scripts/gds/onboarding-ship.js +0 -0
- package/scripts/gds/paste-token.js +0 -0
- package/scripts/gds/portability-smoke-art.sh +0 -0
- package/scripts/gds/portability-smoke-memory.sh +0 -0
- package/scripts/gds/provision.js +125 -4
- package/scripts/gds/push-main.js +0 -0
- package/scripts/gds/render-ideas.js +0 -0
- package/scripts/gds/security-baseline-check.sh +0 -0
- package/scripts/gds/session.js +0 -0
- package/scripts/gds/ship.js +11 -1
- package/scripts/gds/smoke-batch-claim.sh +0 -0
- package/scripts/gds/smoke-batch-release.sh +0 -0
- package/scripts/gds/smoke-box.sh +0 -0
- package/scripts/gds/smoke-claim-consistency.sh +0 -0
- package/scripts/gds/smoke-dependencies.sh +0 -0
- package/scripts/gds/smoke-write.sh +0 -0
- package/scripts/hall-preview/README.md +103 -0
- package/scripts/hall-preview/fixtures/access-requests.json +20 -0
- package/scripts/hall-preview/fixtures/achievements.json +76 -0
- package/scripts/hall-preview/fixtures/analytics__builder.json +251 -0
- package/scripts/hall-preview/fixtures/audit-log.json +68 -0
- package/scripts/hall-preview/fixtures/blockers__detail.json +12 -0
- package/scripts/hall-preview/fixtures/box__me.json +5 -0
- package/scripts/hall-preview/fixtures/boxes__cost-ledger.json +69 -0
- package/scripts/hall-preview/fixtures/builders__active-claims.json +1 -0
- package/scripts/hall-preview/fixtures/builders__directory.json +81 -0
- package/scripts/hall-preview/fixtures/builders__roster.json +48 -0
- package/scripts/hall-preview/fixtures/goals.json +502 -0
- package/scripts/hall-preview/fixtures/goals__25.json +96 -0
- package/scripts/hall-preview/fixtures/goals__26.json +67 -0
- package/scripts/hall-preview/fixtures/goals__3.json +103 -0
- package/scripts/hall-preview/fixtures/goals__35.json +49 -0
- package/scripts/hall-preview/fixtures/goals__conflicts.json +154 -0
- package/scripts/hall-preview/fixtures/goals__detail.json +96 -0
- package/scripts/hall-preview/fixtures/goals__inbox.json +5 -0
- package/scripts/hall-preview/fixtures/goals__requests.json +3 -0
- package/scripts/hall-preview/fixtures/grades__by-builder.json +32 -0
- package/scripts/hall-preview/fixtures/inbox.json +330 -0
- package/scripts/hall-preview/fixtures/inbox__detail.json +15 -0
- package/scripts/hall-preview/fixtures/instance.json +124 -0
- package/scripts/hall-preview/fixtures/leaderboard.json +184 -0
- package/scripts/hall-preview/fixtures/me.json +476 -0
- package/scripts/hall-preview/fixtures/me__art-key__own.json +6 -0
- package/scripts/hall-preview/fixtures/me__event-sound-prefs.json +209 -0
- package/scripts/hall-preview/fixtures/me__recent-ships.json +304 -0
- package/scripts/hall-preview/fixtures/me__render.json +5 -0
- package/scripts/hall-preview/fixtures/me__skill-prefs.json +143 -0
- package/scripts/hall-preview/fixtures/me__sound-prefs.json +67 -0
- package/scripts/hall-preview/fixtures/me__wandering.json +43 -0
- package/scripts/hall-preview/fixtures/override-requests.json +15 -0
- package/scripts/hall-preview/fixtures/provisioning__fleet.json +1 -0
- package/scripts/hall-preview/fixtures/provisioning__fleet__cost-ledger.json +1 -0
- package/scripts/hall-preview/fixtures/provisioning__instances.json +1 -0
- package/scripts/hall-preview/fixtures/public__analytics__ecosystem.json +516 -0
- package/scripts/hall-preview/fixtures/public__bounty-table.json +37 -0
- package/scripts/hall-preview/fixtures/public__cost-summary.json +742 -0
- package/scripts/hall-preview/fixtures/public__estimation-drift.json +41 -0
- package/scripts/hall-preview/fixtures/public__grades.json +50 -0
- package/scripts/hall-preview/fixtures/public__progress.json +124 -0
- package/scripts/hall-preview/fixtures/public__recent-shipped.json +426 -0
- package/scripts/hall-preview/fixtures/public__repo-health.json +160 -0
- package/scripts/hall-preview/fixtures/public__repo-info.json +5 -0
- package/scripts/hall-preview/fixtures/security__docs.json +10 -0
- package/scripts/hall-preview/fixtures/security__reports.json +31 -0
- package/scripts/hall-preview/fixtures/sessions__search.json +9 -0
- package/scripts/hall-preview/fixtures/tasks.json +2420 -0
- package/scripts/hall-preview/fixtures/tasks__claimable.json +2555 -0
- package/scripts/hall-preview/fixtures/tasks__detail.json +111 -0
- package/scripts/hall-preview/fixtures/tasks__peer-votes__feed.json +330 -0
- package/scripts/hall-preview/fixtures/versions.json +89 -0
- package/scripts/hall-preview/refresh-fixtures.js +77 -0
- package/scripts/hall-preview/server.js +195 -0
- package/scripts/migrate.sh +29 -4
- package/scripts/migrate_cost_ledger.sh +0 -0
- package/scripts/render-diagrams.sh +0 -0
- package/scripts/security/dep-audit.js +0 -0
- package/scripts/setup-builder.js +0 -0
- package/scripts/setup-builder.sh +0 -0
- package/scripts/snapshots/maybe-render-on-deploy.sh +0 -0
- package/src/bongos/optimizer.js +37 -2
- package/src/module-api.js +20 -1
- package/tests/criterion_suggest.mjs +106 -0
- package/tests/migrate_root_resolution.mjs +97 -0
- package/tests/provision.mjs +69 -0
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
/* goals.css — page-local styles for the Goals page (task 2171; extracted from
|
|
2
|
+
goals.html's old inline <style> per the hall placement rules). Only what the
|
|
3
|
+
shared kit doesn't carry lives here: goal cards, the detail band, criteria /
|
|
4
|
+
member / conflict lists, the invite + pending panels. Shared pieces —
|
|
5
|
+
.pager--paged, .count-pill, .kit-tabs, .filters, .empty-state, .kit-skel —
|
|
6
|
+
are in style.css's hall-kit section. Everything derives from the shared
|
|
7
|
+
design tokens so instance packs reskin this page along with the rest. */
|
|
8
|
+
|
|
9
|
+
/* ---- goal-card grid (list view) ----
|
|
10
|
+
task 2171 density pass: minmax 300→230 (four across at desktop width),
|
|
11
|
+
tighter gaps/padding/type — the grid holds ~26 goals, so card height is
|
|
12
|
+
what sets the page height. */
|
|
13
|
+
.goal-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 10px; }
|
|
14
|
+
.goal-card {
|
|
15
|
+
display: flex; flex-direction: column; gap: 7px;
|
|
16
|
+
background: var(--surface); border: 1px solid var(--border);
|
|
17
|
+
border-radius: var(--radius); padding: 10px 12px;
|
|
18
|
+
color: var(--ink);
|
|
19
|
+
}
|
|
20
|
+
a.goal-card:hover { text-decoration: none; border-color: var(--border-strong); background: var(--surface-2); }
|
|
21
|
+
.goal-card__head { display: flex; align-items: flex-start; gap: 9px; }
|
|
22
|
+
/* task 1760 — priority (visible once narrowed to one version) + Archon
|
|
23
|
+
drag-to-reorder handle (server enforces the write; this is the affordance). */
|
|
24
|
+
.goal-card__handle { flex: none; cursor: grab; color: var(--ink-faint); font-size: 14px; line-height: 1.2; touch-action: none; }
|
|
25
|
+
.goal-card__handle:active { cursor: grabbing; }
|
|
26
|
+
.goal-card__priority {
|
|
27
|
+
flex: none; min-width: 1.4em; text-align: center;
|
|
28
|
+
font-size: 11.5px; font-weight: 600; color: var(--ink-faint);
|
|
29
|
+
font-variant-numeric: tabular-nums;
|
|
30
|
+
}
|
|
31
|
+
.goal-card--dragging { opacity: 0.45; }
|
|
32
|
+
/* task 1761: a goal blocked by an unachieved prerequisite is dimmed + hue-shifted. */
|
|
33
|
+
.goal-card--blocked { opacity: 0.62; border-style: dashed; }
|
|
34
|
+
.goal-card--blocked:hover { opacity: 0.85; }
|
|
35
|
+
.goal-deps { color: var(--ink-faint); }
|
|
36
|
+
.goal-deps--blocked { color: var(--warn); font-weight: 600; }
|
|
37
|
+
.goal-card__title { font-weight: 650; font-size: 13px; line-height: 1.35; flex: 1; min-width: 0; }
|
|
38
|
+
.goal-card__meta { display: flex; flex-wrap: wrap; gap: 4px 6px; align-items: center; font-size: 11.5px; color: var(--ink-faint); }
|
|
39
|
+
/* task 2163 — the real goal id, shown as a monospace #NNN token so it reads as
|
|
40
|
+
an identifier and never gets confused with the priority ordinal on the left. */
|
|
41
|
+
.goal-card__id, .goal-detail__id {
|
|
42
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
43
|
+
font-variant-numeric: tabular-nums; font-weight: 600; color: var(--ink-faint);
|
|
44
|
+
}
|
|
45
|
+
.goal-card__id { padding: 0 5px; border: 1px solid var(--rule-soft); border-radius: 5px; }
|
|
46
|
+
.goal-detail__id { font-size: 0.72em; vertical-align: 0.12em; margin-right: 4px; }
|
|
47
|
+
.goal-card__foot { display: flex; flex-wrap: wrap; gap: 4px 10px; font-size: 11.5px; color: var(--ink-soft); }
|
|
48
|
+
.goal-card__foot strong { font-variant-numeric: tabular-nums; }
|
|
49
|
+
/* boot skeleton — goal-card-shaped shimmer placeholders (kit .kit-skel bars)
|
|
50
|
+
so the grid doesn't jump when data lands. */
|
|
51
|
+
.goal-card--skel { pointer-events: none; }
|
|
52
|
+
.goal-card--skel .kit-skel { width: 80%; }
|
|
53
|
+
.goal-card--skel .kit-skel + .kit-skel { width: 55%; }
|
|
54
|
+
|
|
55
|
+
/* ---- detail view ---- */
|
|
56
|
+
.goal-detail__head { display: flex; align-items: flex-start; gap: 20px; flex-wrap: wrap; }
|
|
57
|
+
.goal-detail__title { font-size: 19px; font-weight: 650; letter-spacing: -0.01em; margin: 0; }
|
|
58
|
+
.goal-detail__desc { color: var(--ink-soft); font-size: 13.5px; max-width: 72ch; margin: 6px 0 0; }
|
|
59
|
+
.goal-detail__actions { margin-left: auto; display: flex; gap: 8px; align-items: center; }
|
|
60
|
+
/* task 1888/1828 — Completion | Members | Conflicts share ONE card. Wide:
|
|
61
|
+
three columns split by vertical rules. Narrow: they stack, split by
|
|
62
|
+
horizontal rules. The .scroll gives the outer frame; columns own padding
|
|
63
|
+
(the .scroll padding is zeroed here). Conflicts live up here so a long
|
|
64
|
+
work list can no longer push them off the bottom of the page. */
|
|
65
|
+
.goal-band { padding: 0; margin-top: 20px; display: grid; grid-template-columns: 1fr; }
|
|
66
|
+
.goal-band__col { padding: 14px 18px; min-width: 0; }
|
|
67
|
+
.goal-band__col + .goal-band__col { border-top: 1px solid var(--rule-soft); }
|
|
68
|
+
@media (min-width: 900px) {
|
|
69
|
+
.goal-band { grid-template-columns: repeat(3, minmax(0, 1fr)); }
|
|
70
|
+
.goal-band__col + .goal-band__col { border-top: none; border-left: 1px solid var(--rule-soft); }
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/* Live conflicts: the band COLUMN can't own the card border, so it gets a
|
|
74
|
+
subtle amber wash; the standalone full-view card keeps the amber border.
|
|
75
|
+
(Count pills on these headers are the shared .count-pill.) */
|
|
76
|
+
.goal-conflicts-card--live { background: color-mix(in srgb, var(--warn) 6%, transparent); }
|
|
77
|
+
.goal-conflicts-card--live .count-pill { background: var(--warn-weak); color: var(--warn); }
|
|
78
|
+
#goal-conflicts-view-card.goal-conflicts-card--live { background: var(--surface); border-color: color-mix(in srgb, var(--warn) 40%, var(--border)); }
|
|
79
|
+
|
|
80
|
+
/* task 1828 — inline Claim on a ready To-do row + the conflicts "view all". */
|
|
81
|
+
.goal-claim-btn {
|
|
82
|
+
display: inline-flex; align-items: center; justify-content: center;
|
|
83
|
+
height: 24px; padding: 0 12px; border-radius: var(--radius-sm);
|
|
84
|
+
border: 1px solid var(--accent); background: var(--accent); color: #fff;
|
|
85
|
+
font-size: 12px; font-weight: 600; cursor: pointer; white-space: nowrap;
|
|
86
|
+
}
|
|
87
|
+
.goal-claim-btn:hover:not(:disabled) { background: var(--accent-deep); }
|
|
88
|
+
.goal-claim-btn:disabled { opacity: 0.55; cursor: default; }
|
|
89
|
+
/* task 1828 — Release on the viewer's OWN active claim (ghost, not accent —
|
|
90
|
+
it's the undo of a claim); a muted label for another builder's claim. */
|
|
91
|
+
.goal-release-btn {
|
|
92
|
+
display: inline-flex; align-items: center; justify-content: center;
|
|
93
|
+
height: 24px; padding: 0 12px; border-radius: var(--radius-sm);
|
|
94
|
+
border: 1px solid var(--border-strong); background: var(--surface); color: var(--ink-soft);
|
|
95
|
+
font-size: 12px; font-weight: 600; cursor: pointer; white-space: nowrap;
|
|
96
|
+
}
|
|
97
|
+
.goal-release-btn:hover:not(:disabled) { background: var(--surface-2); color: var(--ink); }
|
|
98
|
+
.goal-release-btn:disabled { opacity: 0.55; cursor: default; }
|
|
99
|
+
.ledger__claimed { font-size: 12px; color: var(--ink-faint); white-space: nowrap; }
|
|
100
|
+
.ledger__action { text-align: right; white-space: nowrap; }
|
|
101
|
+
/* task 1828 — shared "View all N →" foot under a capped band column. */
|
|
102
|
+
.goal-col__foot { margin-top: 10px; }
|
|
103
|
+
|
|
104
|
+
/* task 2171 density pass — the Work tables were the airiest surface on the
|
|
105
|
+
page (12px cells): tighter cells + type lift rows-per-screen ~40%. */
|
|
106
|
+
#goal-todo th, #goal-todo td, #goal-done th, #goal-done td { padding: 7px 10px; }
|
|
107
|
+
#goal-todo td, #goal-done td { font-size: 12.5px; }
|
|
108
|
+
|
|
109
|
+
/* task 1828 — full completion view: each criterion's detail shown inline. */
|
|
110
|
+
.crit-list--full .crit { align-items: start; }
|
|
111
|
+
.crit__col { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
|
|
112
|
+
.crit__detail { font-size: 12px; color: var(--ink-faint); line-height: 1.45; }
|
|
113
|
+
|
|
114
|
+
/* task 1828 — full members view: goal-level aggregate + per-member stats. */
|
|
115
|
+
.goal-mstats { display: flex; flex-wrap: wrap; gap: 8px 20px; margin: 0 0 16px; font-size: 13px; color: var(--ink-soft); }
|
|
116
|
+
.mstat strong { color: var(--ink); font-variant-numeric: tabular-nums; font-weight: 650; }
|
|
117
|
+
.member--stat { gap: 12px; }
|
|
118
|
+
.member__stats { font-size: 12.5px; color: var(--ink-soft); white-space: nowrap; font-variant-numeric: tabular-nums; }
|
|
119
|
+
.member__stats strong { color: var(--ink); font-weight: 600; }
|
|
120
|
+
.member__stats--pending { color: var(--ink-faint); }
|
|
121
|
+
|
|
122
|
+
/* task 1888 — the single Work card: header row with the to-do/completed tab
|
|
123
|
+
toggle (kit tabs), paginated tables underneath. */
|
|
124
|
+
.goal-work__head { display: flex; align-items: center; justify-content: space-between; gap: 10px 14px; flex-wrap: wrap; margin: 0 0 12px; }
|
|
125
|
+
.goal-work__head .scroll__h { margin: 0; }
|
|
126
|
+
.goal-work__tabs .kit-tabs { margin: 0; }
|
|
127
|
+
.conflict__sev {
|
|
128
|
+
display: inline-flex; align-items: center; height: 18px; padding: 0 7px; margin-left: 8px;
|
|
129
|
+
border-radius: 999px; font-size: 10.5px; font-weight: 600; vertical-align: 1px;
|
|
130
|
+
background: var(--surface-2); color: var(--ink-soft);
|
|
131
|
+
}
|
|
132
|
+
.conflict__sev--high { background: var(--danger-weak); color: var(--danger); }
|
|
133
|
+
.conflict__sev--medium { background: var(--warn-weak); color: var(--warn); }
|
|
134
|
+
|
|
135
|
+
.crit-list { list-style: none; margin: 10px 0 0; padding: 0; display: flex; flex-direction: column; }
|
|
136
|
+
.crit { display: grid; grid-template-columns: 22px minmax(0,1fr); gap: 10px; padding: 6px 0; border-bottom: 1px solid var(--rule-soft); font-size: 13px; }
|
|
137
|
+
.crit:last-child { border-bottom: none; }
|
|
138
|
+
.crit__mark { width: 18px; height: 18px; border-radius: 50%; border: 1.5px solid var(--border-strong); display: flex; align-items: center; justify-content: center; font-size: 11px; color: var(--ink-faint); }
|
|
139
|
+
.crit--done .crit__mark { background: var(--ok); border-color: var(--ok); color: #fff; }
|
|
140
|
+
.crit--done .crit__text { color: var(--ink-soft); }
|
|
141
|
+
/* BV1.R79: per-criterion expand in the capped band — short label, full text on
|
|
142
|
+
click (matches the Roadmap page's .vbar__crit-d pattern). */
|
|
143
|
+
.crit-d { min-width: 0; }
|
|
144
|
+
.crit-d > summary { cursor: pointer; list-style: none; text-decoration: underline dotted var(--border-strong); text-underline-offset: 3px; }
|
|
145
|
+
.crit-d > summary::-webkit-details-marker { display: none; }
|
|
146
|
+
.crit-d[open] > summary { text-decoration: none; font-weight: 500; }
|
|
147
|
+
.crit-d .crit__detail { margin-top: 4px; }
|
|
148
|
+
|
|
149
|
+
.member-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
|
|
150
|
+
.member { display: flex; align-items: center; gap: 10px; padding: 6px 0; border-bottom: 1px solid var(--rule-soft); font-size: 13px; }
|
|
151
|
+
.member:last-child { border-bottom: none; }
|
|
152
|
+
.member__avatar { width: 24px; height: 24px; border-radius: 50%; background: var(--accent-weak); color: var(--accent-text); font-size: 10px; font-weight: 600; display: flex; align-items: center; justify-content: center; overflow: hidden; flex-shrink: 0; }
|
|
153
|
+
.member__avatar img { width: 100%; height: 100%; object-fit: cover; border-radius: 50%; }
|
|
154
|
+
.member__name { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
155
|
+
.member__name small { color: var(--ink-faint); }
|
|
156
|
+
.role-pill { display: inline-flex; align-items: center; height: 20px; padding: 0 9px; border-radius: 999px; font-size: 11px; font-weight: 600; background: var(--surface-2); color: var(--ink-soft); }
|
|
157
|
+
.role-pill--lead { background: var(--accent-weak); color: var(--accent-text); }
|
|
158
|
+
|
|
159
|
+
/* task 1762/1877 — owner/manager invite control (goal member admission),
|
|
160
|
+
collapsed behind "+ Invite" (disclosure, closed by default — task 2171). */
|
|
161
|
+
.goal-invite { margin: 4px 0 10px; }
|
|
162
|
+
.goal-invite__form { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
|
|
163
|
+
.goal-invite__form select#goal-invite-builder { flex: 1; min-width: 180px; }
|
|
164
|
+
|
|
165
|
+
/* task 1953 — private goals: the lock badge (meta line) + the goal's own
|
|
166
|
+
pending invite/join-request queue (manager view, next to the invite box). */
|
|
167
|
+
.goal-badge--locked { background: var(--warn-weak); color: var(--warn); }
|
|
168
|
+
.goal-pending { margin: 4px 0 10px; display: flex; flex-direction: column; gap: 10px; }
|
|
169
|
+
.pending-group__h { font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.02em; color: var(--ink-faint); margin: 0 0 4px; display: flex; align-items: center; gap: 6px; }
|
|
170
|
+
.pending-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
|
|
171
|
+
.pending-row { display: flex; align-items: center; gap: 8px; padding: 6px 0; border-bottom: 1px solid var(--rule-soft); font-size: 13px; flex-wrap: wrap; }
|
|
172
|
+
.pending-row:last-child { border-bottom: none; }
|
|
173
|
+
.pending-row__who { font-weight: 600; }
|
|
174
|
+
.pending-row__note { color: var(--ink-faint); font-size: 12px; flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
175
|
+
.pending-row__actions { display: flex; gap: 6px; margin-left: auto; }
|
|
176
|
+
|
|
177
|
+
.conflict { border: 1px solid color-mix(in srgb, var(--warn) 30%, var(--border)); background: var(--warn-weak); border-radius: var(--radius-sm); padding: 8px 12px; font-size: 12.5px; margin: 8px 0 0; }
|
|
178
|
+
.conflict__pair { font-weight: 600; }
|
|
179
|
+
.conflict__paths { font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace; font-size: 11.5px; color: var(--ink-soft); margin-top: 4px; word-break: break-all; }
|
|
180
|
+
.conflict-note { font-size: 12px; color: var(--ink-faint); margin: 10px 0 0; }
|
|
181
|
+
|
|
182
|
+
/* Filtered-count line under the kit filter bar (list view). */
|
|
183
|
+
.goals-count-line { margin: -4px 0 12px; font-size: 12.5px; color: var(--ink-faint); }
|
|
@@ -10,175 +10,10 @@
|
|
|
10
10
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
11
11
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
|
|
12
12
|
<link rel="stylesheet" href="/builders/style.css?v=2026-07-03-goals1">
|
|
13
|
-
<style>
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
display: flex; flex-direction: column; gap: 10px;
|
|
18
|
-
background: var(--surface); border: 1px solid var(--border);
|
|
19
|
-
border-radius: var(--radius); padding: 16px 18px;
|
|
20
|
-
color: var(--ink);
|
|
21
|
-
}
|
|
22
|
-
a.goal-card:hover { text-decoration: none; border-color: var(--border-strong); background: var(--surface-2); }
|
|
23
|
-
.goal-card__head { display: flex; align-items: flex-start; gap: 12px; }
|
|
24
|
-
/* task 1760 — priority (visible once narrowed to one version) + Archon
|
|
25
|
-
drag-to-reorder handle (server enforces the write; this is the affordance). */
|
|
26
|
-
.goal-card__handle { flex: none; cursor: grab; color: var(--ink-faint); font-size: 14px; line-height: 1.2; touch-action: none; }
|
|
27
|
-
.goal-card__handle:active { cursor: grabbing; }
|
|
28
|
-
.goal-card__priority {
|
|
29
|
-
flex: none; min-width: 1.4em; text-align: center;
|
|
30
|
-
font-size: 11.5px; font-weight: 600; color: var(--ink-faint);
|
|
31
|
-
font-variant-numeric: tabular-nums;
|
|
32
|
-
}
|
|
33
|
-
.goal-card--dragging { opacity: 0.45; }
|
|
34
|
-
/* task 1761: a goal blocked by an unachieved prerequisite is dimmed + hue-shifted. */
|
|
35
|
-
.goal-card--blocked { opacity: 0.62; border-style: dashed; }
|
|
36
|
-
.goal-card--blocked:hover { opacity: 0.85; }
|
|
37
|
-
.goal-deps { color: var(--ink-faint); }
|
|
38
|
-
.goal-deps--blocked { color: var(--warn); font-weight: 600; }
|
|
39
|
-
.goal-card__title { font-weight: 650; font-size: 14px; flex: 1; min-width: 0; }
|
|
40
|
-
.goal-card__meta { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; font-size: 12px; color: var(--ink-faint); }
|
|
41
|
-
.goal-card__foot { display: flex; gap: 14px; font-size: 12.5px; color: var(--ink-soft); }
|
|
42
|
-
.goal-card__foot strong { font-variant-numeric: tabular-nums; }
|
|
43
|
-
|
|
44
|
-
.goal-detail__head { display: flex; align-items: flex-start; gap: 20px; flex-wrap: wrap; }
|
|
45
|
-
.goal-detail__title { font-size: 19px; font-weight: 650; letter-spacing: -0.01em; margin: 0; }
|
|
46
|
-
.goal-detail__desc { color: var(--ink-soft); font-size: 13.5px; max-width: 72ch; margin: 6px 0 0; }
|
|
47
|
-
.goal-detail__actions { margin-left: auto; display: flex; gap: 8px; align-items: center; }
|
|
48
|
-
/* task 1888/1828 — Completion | Members | Conflicts share ONE card. Wide:
|
|
49
|
-
three columns split by vertical rules. Narrow: they stack, split by
|
|
50
|
-
horizontal rules. The .scroll gives the outer frame; columns own padding
|
|
51
|
-
(the .scroll padding is zeroed here). Conflicts live up here so a long
|
|
52
|
-
work list can no longer push them off the bottom of the page. */
|
|
53
|
-
.goal-band { padding: 0; margin-top: 20px; display: grid; grid-template-columns: 1fr; }
|
|
54
|
-
.goal-band__col { padding: 18px 22px; min-width: 0; }
|
|
55
|
-
.goal-band__col + .goal-band__col { border-top: 1px solid var(--rule-soft); }
|
|
56
|
-
@media (min-width: 900px) {
|
|
57
|
-
.goal-band { grid-template-columns: repeat(3, minmax(0, 1fr)); }
|
|
58
|
-
.goal-band__col + .goal-band__col { border-top: none; border-left: 1px solid var(--rule-soft); }
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/* task 1888 — count pill on card/tab headers + the live-conflicts accent. */
|
|
62
|
-
.goal-count {
|
|
63
|
-
display: inline-flex; align-items: center; justify-content: center;
|
|
64
|
-
min-width: 20px; height: 18px; padding: 0 6px; margin-left: 8px;
|
|
65
|
-
border-radius: 999px; background: var(--surface-2); color: var(--ink-soft);
|
|
66
|
-
font-size: 11px; font-weight: 600; font-variant-numeric: tabular-nums;
|
|
67
|
-
}
|
|
68
|
-
/* Live conflicts: the band COLUMN can't own the card border, so it gets a
|
|
69
|
-
subtle amber wash; the standalone full-view card keeps the amber border. */
|
|
70
|
-
.goal-conflicts-card--live { background: color-mix(in srgb, var(--warn) 6%, transparent); }
|
|
71
|
-
.goal-conflicts-card--live .goal-count { background: var(--warn-weak); color: var(--warn); }
|
|
72
|
-
#goal-conflicts-view-card.goal-conflicts-card--live { background: var(--surface); border-color: color-mix(in srgb, var(--warn) 40%, var(--border)); }
|
|
73
|
-
|
|
74
|
-
/* task 1828 — inline Claim on a ready To-do row + the conflicts "view all". */
|
|
75
|
-
.goal-claim-btn {
|
|
76
|
-
display: inline-flex; align-items: center; justify-content: center;
|
|
77
|
-
height: 26px; padding: 0 12px; border-radius: var(--radius-sm);
|
|
78
|
-
border: 1px solid var(--accent); background: var(--accent); color: #fff;
|
|
79
|
-
font-size: 12px; font-weight: 600; cursor: pointer; white-space: nowrap;
|
|
80
|
-
}
|
|
81
|
-
.goal-claim-btn:hover:not(:disabled) { background: var(--accent-deep); }
|
|
82
|
-
.goal-claim-btn:disabled { opacity: 0.55; cursor: default; }
|
|
83
|
-
/* task 1828 — Release on the viewer's OWN active claim (ghost, not accent —
|
|
84
|
-
it's the undo of a claim); a muted label for another builder's claim. */
|
|
85
|
-
.goal-release-btn {
|
|
86
|
-
display: inline-flex; align-items: center; justify-content: center;
|
|
87
|
-
height: 26px; padding: 0 12px; border-radius: var(--radius-sm);
|
|
88
|
-
border: 1px solid var(--border-strong); background: var(--surface); color: var(--ink-soft);
|
|
89
|
-
font-size: 12px; font-weight: 600; cursor: pointer; white-space: nowrap;
|
|
90
|
-
}
|
|
91
|
-
.goal-release-btn:hover:not(:disabled) { background: var(--surface-2); color: var(--ink); }
|
|
92
|
-
.goal-release-btn:disabled { opacity: 0.55; cursor: default; }
|
|
93
|
-
.ledger__claimed { font-size: 12px; color: var(--ink-faint); white-space: nowrap; }
|
|
94
|
-
.ledger__action { text-align: right; white-space: nowrap; }
|
|
95
|
-
/* task 1828 — shared "View all N →" foot under a capped band column. */
|
|
96
|
-
.goal-col__foot { margin-top: 12px; }
|
|
97
|
-
|
|
98
|
-
/* task 1828 — full completion view: each criterion's detail shown inline. */
|
|
99
|
-
.crit-list--full .crit { align-items: start; }
|
|
100
|
-
.crit__col { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
|
|
101
|
-
.crit__detail { font-size: 12px; color: var(--ink-faint); line-height: 1.45; }
|
|
102
|
-
|
|
103
|
-
/* task 1828 — full members view: goal-level aggregate + per-member stats. */
|
|
104
|
-
.goal-mstats { display: flex; flex-wrap: wrap; gap: 8px 20px; margin: 0 0 16px; font-size: 13px; color: var(--ink-soft); }
|
|
105
|
-
.mstat strong { color: var(--ink); font-variant-numeric: tabular-nums; font-weight: 650; }
|
|
106
|
-
.member--stat { gap: 12px; }
|
|
107
|
-
.member__stats { font-size: 12.5px; color: var(--ink-soft); white-space: nowrap; font-variant-numeric: tabular-nums; }
|
|
108
|
-
.member__stats strong { color: var(--ink); font-weight: 600; }
|
|
109
|
-
.member__stats--pending { color: var(--ink-faint); }
|
|
110
|
-
|
|
111
|
-
/* task 1888 — the single Work card: header row with the to-do/completed tab
|
|
112
|
-
toggle (house .setup__tab pattern), capped tables + pager underneath. */
|
|
113
|
-
.goal-work__head { display: flex; align-items: center; justify-content: space-between; gap: 10px 14px; flex-wrap: wrap; margin: 0 0 12px; }
|
|
114
|
-
.goal-work__head .scroll__h { margin: 0; }
|
|
115
|
-
.goal-work__tabs { margin: 0; }
|
|
116
|
-
.conflict__sev {
|
|
117
|
-
display: inline-flex; align-items: center; height: 18px; padding: 0 7px; margin-left: 8px;
|
|
118
|
-
border-radius: 999px; font-size: 10.5px; font-weight: 600; vertical-align: 1px;
|
|
119
|
-
background: var(--surface-2); color: var(--ink-soft);
|
|
120
|
-
}
|
|
121
|
-
.conflict__sev--high { background: var(--danger-weak); color: var(--danger); }
|
|
122
|
-
.conflict__sev--medium { background: var(--warn-weak); color: var(--warn); }
|
|
123
|
-
|
|
124
|
-
.crit-list { list-style: none; margin: 10px 0 0; padding: 0; display: flex; flex-direction: column; }
|
|
125
|
-
.crit { display: grid; grid-template-columns: 22px minmax(0,1fr); gap: 10px; padding: 8px 0; border-bottom: 1px solid var(--rule-soft); font-size: 13px; }
|
|
126
|
-
.crit:last-child { border-bottom: none; }
|
|
127
|
-
.crit__mark { width: 18px; height: 18px; border-radius: 50%; border: 1.5px solid var(--border-strong); display: flex; align-items: center; justify-content: center; font-size: 11px; color: var(--ink-faint); }
|
|
128
|
-
.crit--done .crit__mark { background: var(--ok); border-color: var(--ok); color: #fff; }
|
|
129
|
-
.crit--done .crit__text { color: var(--ink-soft); }
|
|
130
|
-
/* BV1.R79: per-criterion expand in the capped band — short label, full text on
|
|
131
|
-
click (matches the Roadmap page's .vbar__crit-d pattern). */
|
|
132
|
-
.crit-d { min-width: 0; }
|
|
133
|
-
.crit-d > summary { cursor: pointer; list-style: none; text-decoration: underline dotted var(--border-strong); text-underline-offset: 3px; }
|
|
134
|
-
.crit-d > summary::-webkit-details-marker { display: none; }
|
|
135
|
-
.crit-d[open] > summary { text-decoration: none; font-weight: 500; }
|
|
136
|
-
.crit-d .crit__detail { margin-top: 4px; }
|
|
137
|
-
|
|
138
|
-
.member-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
|
|
139
|
-
.member { display: flex; align-items: center; gap: 10px; padding: 8px 0; border-bottom: 1px solid var(--rule-soft); font-size: 13.5px; }
|
|
140
|
-
.member:last-child { border-bottom: none; }
|
|
141
|
-
.member__avatar { width: 26px; height: 26px; border-radius: 50%; background: var(--accent-weak); color: var(--accent-text); font-size: 10.5px; font-weight: 600; display: flex; align-items: center; justify-content: center; overflow: hidden; flex-shrink: 0; }
|
|
142
|
-
.member__avatar img { width: 100%; height: 100%; object-fit: cover; border-radius: 50%; }
|
|
143
|
-
.member__name { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
144
|
-
.member__name small { color: var(--ink-faint); }
|
|
145
|
-
.role-pill { display: inline-flex; align-items: center; height: 20px; padding: 0 9px; border-radius: 999px; font-size: 11px; font-weight: 600; background: var(--surface-2); color: var(--ink-soft); }
|
|
146
|
-
.role-pill--lead { background: var(--accent-weak); color: var(--accent-text); }
|
|
147
|
-
|
|
148
|
-
/* task 1762/1877 — owner/manager invite control (goal member admission). */
|
|
149
|
-
.goal-invite { margin: 4px 0 10px; }
|
|
150
|
-
.goal-invite__form { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
|
|
151
|
-
.goal-invite__form select#goal-invite-builder { flex: 1; min-width: 180px; }
|
|
152
|
-
|
|
153
|
-
/* task 1953 — private goals: the lock badge (meta line) + the goal's own
|
|
154
|
-
pending invite/join-request queue (manager view, next to the invite box). */
|
|
155
|
-
.goal-badge--locked { background: var(--warn-weak); color: var(--warn); }
|
|
156
|
-
.goal-pending { margin: 4px 0 10px; display: flex; flex-direction: column; gap: 10px; }
|
|
157
|
-
.pending-group__h { font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.02em; color: var(--ink-faint); margin: 0 0 4px; display: flex; align-items: center; gap: 6px; }
|
|
158
|
-
.pending-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
|
|
159
|
-
.pending-row { display: flex; align-items: center; gap: 8px; padding: 6px 0; border-bottom: 1px solid var(--rule-soft); font-size: 13px; flex-wrap: wrap; }
|
|
160
|
-
.pending-row:last-child { border-bottom: none; }
|
|
161
|
-
.pending-row__who { font-weight: 600; }
|
|
162
|
-
.pending-row__note { color: var(--ink-faint); font-size: 12px; flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
163
|
-
.pending-row__actions { display: flex; gap: 6px; margin-left: auto; }
|
|
164
|
-
|
|
165
|
-
.conflict { border: 1px solid color-mix(in srgb, var(--warn) 30%, var(--border)); background: var(--warn-weak); border-radius: var(--radius-sm); padding: 10px 14px; font-size: 13px; margin: 10px 0 0; }
|
|
166
|
-
.conflict__pair { font-weight: 600; }
|
|
167
|
-
.conflict__paths { font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace; font-size: 11.5px; color: var(--ink-soft); margin-top: 4px; word-break: break-all; }
|
|
168
|
-
.conflict-note { font-size: 12px; color: var(--ink-faint); margin: 10px 0 0; }
|
|
169
|
-
|
|
170
|
-
.goal-filters { display: flex; gap: 10px 14px; flex-wrap: wrap; align-items: flex-end; margin: 0 0 16px; }
|
|
171
|
-
|
|
172
|
-
/* task 1932: paginated goal grid (Per-page dropdown + Prev/Next). .pager /
|
|
173
|
-
.pager__range / .btn-ghost come from the shared style.css; these extend
|
|
174
|
-
that pager into a two-sided bar (range left, controls right). */
|
|
175
|
-
.pager--paged { justify-content: space-between; flex-wrap: wrap; gap: 10px 16px; }
|
|
176
|
-
.pager__nav { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
|
|
177
|
-
.pager__perpage { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--ink-faint); }
|
|
178
|
-
.pager__perpage select { height: 30px; padding: 2px 8px; font-size: 13px; }
|
|
179
|
-
.pager__page { font-size: 12.5px; color: var(--ink-soft); font-variant-numeric: tabular-nums; min-width: 6.5em; text-align: center; }
|
|
180
|
-
.pager__nav .pager__btn:disabled { opacity: 0.4; cursor: default; }
|
|
181
|
-
</style>
|
|
13
|
+
<!-- Page-local styles (task 2171) — extracted from the old inline <style>
|
|
14
|
+
block per the hall placement rules; shared pager/filter/tab/count-pill
|
|
15
|
+
styles now live in style.css's hall-kit section. -->
|
|
16
|
+
<link rel="stylesheet" href="/builders/goals.css">
|
|
182
17
|
</head>
|
|
183
18
|
<body data-page="goals" data-page-title="Goals">
|
|
184
19
|
|
|
@@ -196,39 +31,16 @@
|
|
|
196
31
|
<!-- LIST view -->
|
|
197
32
|
<section id="goals-list-view" aria-labelledby="goals-list-h">
|
|
198
33
|
<h2 id="goals-list-h" class="sr-only">All goals</h2>
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
<option value="">All goals</option>
|
|
210
|
-
<option value="mine">My goals</option>
|
|
211
|
-
</select></label>
|
|
212
|
-
<span class="filter__count" id="goals-count" aria-live="polite"></span>
|
|
213
|
-
</div>
|
|
214
|
-
<div class="goal-grid" id="goal-grid"><div class="profile__placeholder">…</div></div>
|
|
215
|
-
<div class="pager pager--paged" id="goals-pager" hidden>
|
|
216
|
-
<span class="pager__range" id="goals-range"></span>
|
|
217
|
-
<div class="pager__nav">
|
|
218
|
-
<label class="pager__perpage">
|
|
219
|
-
<span>Per page</span>
|
|
220
|
-
<select id="goals-per-page" aria-label="Goals per page">
|
|
221
|
-
<option value="10">10</option>
|
|
222
|
-
<option value="25">25</option>
|
|
223
|
-
<option value="50">50</option>
|
|
224
|
-
<option value="100">100</option>
|
|
225
|
-
</select>
|
|
226
|
-
</label>
|
|
227
|
-
<button class="btn-ghost pager__btn" type="button" id="goals-prev" aria-label="Previous page">‹ Prev</button>
|
|
228
|
-
<span class="pager__page" id="goals-page-ind" aria-live="polite"></span>
|
|
229
|
-
<button class="btn-ghost pager__btn" type="button" id="goals-next" aria-label="Next page">Next ›</button>
|
|
230
|
-
</div>
|
|
231
|
-
</div>
|
|
34
|
+
<!-- task 2171: the filter bar is built by OTBKit.makeFilterBar —
|
|
35
|
+
Version / Status / Membership, all primary (no overflow). Control
|
|
36
|
+
ids are unchanged (f-goal-version, f-goal-status, f-goal-mine)
|
|
37
|
+
so goals-page.js reads stay stable. -->
|
|
38
|
+
<div id="goals-filters"></div>
|
|
39
|
+
<p class="goals-count-line" id="goals-count" aria-live="polite"></p>
|
|
40
|
+
<div class="goal-grid" id="goal-grid"></div>
|
|
41
|
+
<!-- task 2171: the grid's pager bar is stamped here by OTBKit
|
|
42
|
+
(pagerBarHtml('goals') — same ids, same otb.goals.perPage pref). -->
|
|
43
|
+
<div id="goals-pager-mount"></div>
|
|
232
44
|
</section>
|
|
233
45
|
|
|
234
46
|
<!-- DETAIL view (hash-routed: #/goal/N) -->
|
|
@@ -249,13 +61,13 @@
|
|
|
249
61
|
(three columns; stacks with horizontal dividers when narrow). -->
|
|
250
62
|
<div class="scroll goal-band">
|
|
251
63
|
<div class="goal-band__col">
|
|
252
|
-
<h2 class="scroll__h" id="goal-completion-h">Completion<span class="
|
|
253
|
-
<div id="goal-completion-body"
|
|
64
|
+
<h2 class="scroll__h" id="goal-completion-h">Completion<span class="count-pill" id="goal-completion-count" hidden></span></h2>
|
|
65
|
+
<div id="goal-completion-body"></div>
|
|
254
66
|
<!-- task 1828 — each column caps its (growing) list + clicks into a full view. -->
|
|
255
67
|
<div class="goal-col__foot" id="goal-completion-foot" hidden></div>
|
|
256
68
|
</div>
|
|
257
69
|
<div class="goal-band__col">
|
|
258
|
-
<h2 class="scroll__h">Members<span class="
|
|
70
|
+
<h2 class="scroll__h">Members<span class="count-pill" id="goal-members-count" hidden></span></h2>
|
|
259
71
|
<p class="scroll__lede" id="goal-members-lede"></p>
|
|
260
72
|
<div class="goal-invite" id="goal-invite" hidden></div>
|
|
261
73
|
<!-- task 1953 — the goal's own pending invite/join-request queue
|
|
@@ -266,9 +78,9 @@
|
|
|
266
78
|
<div class="goal-col__foot" id="goal-members-foot" hidden></div>
|
|
267
79
|
</div>
|
|
268
80
|
<div class="goal-band__col" id="goal-conflicts-card">
|
|
269
|
-
<h2 class="scroll__h">Conflicts<span class="
|
|
81
|
+
<h2 class="scroll__h">Conflicts<span class="count-pill" id="goal-conflicts-count" hidden></span></h2>
|
|
270
82
|
<p class="scroll__lede">Open tasks whose declared files overlap — sequence these before two builders collide.</p>
|
|
271
|
-
<div id="goal-conflicts"
|
|
83
|
+
<div id="goal-conflicts"></div>
|
|
272
84
|
<!-- task 1828 — replaces the show-all pager: click into a dedicated
|
|
273
85
|
full-width conflicts view instead of expanding this column. -->
|
|
274
86
|
<div class="goal-col__foot" id="goal-conflicts-foot" hidden></div>
|
|
@@ -278,12 +90,12 @@
|
|
|
278
90
|
<div class="scroll" style="margin-top:20px">
|
|
279
91
|
<div class="goal-work__head">
|
|
280
92
|
<h2 class="scroll__h">Work</h2>
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
93
|
+
<!-- task 2171: the To do / Completed toggle is built by
|
|
94
|
+
OTBKit.makeTabs (hash:false — the #/goal/N sub-route
|
|
95
|
+
namespace stays untouched; tabs key off in-page state). -->
|
|
96
|
+
<div class="goal-work__tabs" id="goal-work-tabs" aria-label="Goal tasks"></div>
|
|
285
97
|
</div>
|
|
286
|
-
<div id="goal-todo-pane" role="tabpanel" aria-labelledby="
|
|
98
|
+
<div id="goal-todo-pane" role="tabpanel" aria-labelledby="tab-todo">
|
|
287
99
|
<!-- task 1828 — Kind / Status / Credits headers sort the list (click
|
|
288
100
|
cycles desc → asc → natural); a ready row carries an inline Claim. -->
|
|
289
101
|
<table class="ledger" id="goal-todo"><thead><tr>
|
|
@@ -294,25 +106,9 @@
|
|
|
294
106
|
<th aria-label="Actions"></th>
|
|
295
107
|
</tr></thead>
|
|
296
108
|
<tbody><tr><td colspan="6" class="ledger__empty">…</td></tr></tbody></table>
|
|
297
|
-
<div
|
|
298
|
-
<span class="pager__range" id="goal-todo-range"></span>
|
|
299
|
-
<div class="pager__nav">
|
|
300
|
-
<label class="pager__perpage">
|
|
301
|
-
<span>Per page</span>
|
|
302
|
-
<select id="goal-todo-per-page" aria-label="To-do tasks per page">
|
|
303
|
-
<option value="10">10</option>
|
|
304
|
-
<option value="25">25</option>
|
|
305
|
-
<option value="50">50</option>
|
|
306
|
-
<option value="100">100</option>
|
|
307
|
-
</select>
|
|
308
|
-
</label>
|
|
309
|
-
<button class="btn-ghost pager__btn" type="button" id="goal-todo-prev" aria-label="Previous page">‹ Prev</button>
|
|
310
|
-
<span class="pager__page" id="goal-todo-page-ind" aria-live="polite"></span>
|
|
311
|
-
<button class="btn-ghost pager__btn" type="button" id="goal-todo-next" aria-label="Next page">Next ›</button>
|
|
312
|
-
</div>
|
|
313
|
-
</div>
|
|
109
|
+
<div id="goal-todo-pager-mount"></div>
|
|
314
110
|
</div>
|
|
315
|
-
<div id="goal-done-pane" role="tabpanel" aria-labelledby="
|
|
111
|
+
<div id="goal-done-pane" role="tabpanel" aria-labelledby="tab-done" hidden>
|
|
316
112
|
<table class="ledger" id="goal-done"><thead><tr>
|
|
317
113
|
<th>№</th><th>Task</th>
|
|
318
114
|
<th class="ledger__sortable" id="goal-done-sort-kind" role="button" tabindex="0" aria-sort="none">Kind</th>
|
|
@@ -320,23 +116,7 @@
|
|
|
320
116
|
<th class="ledger__sortable" id="goal-done-sort-shipped" role="button" tabindex="0" aria-sort="none">Shipped</th>
|
|
321
117
|
</tr></thead>
|
|
322
118
|
<tbody><tr><td colspan="5" class="ledger__empty">…</td></tr></tbody></table>
|
|
323
|
-
<div
|
|
324
|
-
<span class="pager__range" id="goal-done-range"></span>
|
|
325
|
-
<div class="pager__nav">
|
|
326
|
-
<label class="pager__perpage">
|
|
327
|
-
<span>Per page</span>
|
|
328
|
-
<select id="goal-done-per-page" aria-label="Completed tasks per page">
|
|
329
|
-
<option value="10">10</option>
|
|
330
|
-
<option value="25">25</option>
|
|
331
|
-
<option value="50">50</option>
|
|
332
|
-
<option value="100">100</option>
|
|
333
|
-
</select>
|
|
334
|
-
</label>
|
|
335
|
-
<button class="btn-ghost pager__btn" type="button" id="goal-done-prev" aria-label="Previous page">‹ Prev</button>
|
|
336
|
-
<span class="pager__page" id="goal-done-page-ind" aria-live="polite"></span>
|
|
337
|
-
<button class="btn-ghost pager__btn" type="button" id="goal-done-next" aria-label="Next page">Next ›</button>
|
|
338
|
-
</div>
|
|
339
|
-
</div>
|
|
119
|
+
<div id="goal-done-pager-mount"></div>
|
|
340
120
|
</div>
|
|
341
121
|
</div>
|
|
342
122
|
</section>
|
|
@@ -346,9 +126,9 @@
|
|
|
346
126
|
<section id="goal-conflicts-view" hidden aria-labelledby="goal-conflicts-view-h">
|
|
347
127
|
<p class="card-foot" style="margin:0 0 14px"><a href="#" id="goal-conflicts-back">← Back to goal</a></p>
|
|
348
128
|
<div class="scroll" style="margin:0" id="goal-conflicts-view-card">
|
|
349
|
-
<h2 class="scroll__h" id="goal-conflicts-view-h">Conflicts<span class="
|
|
129
|
+
<h2 class="scroll__h" id="goal-conflicts-view-h">Conflicts<span class="count-pill" id="goal-conflicts-view-count" hidden></span></h2>
|
|
350
130
|
<p class="scroll__lede">Open tasks whose declared files overlap — sequence these before two builders collide.</p>
|
|
351
|
-
<div id="goal-conflicts-full"
|
|
131
|
+
<div id="goal-conflicts-full"></div>
|
|
352
132
|
</div>
|
|
353
133
|
</section>
|
|
354
134
|
|
|
@@ -357,10 +137,10 @@
|
|
|
357
137
|
<section id="goal-members-view" hidden aria-labelledby="goal-members-view-h">
|
|
358
138
|
<p class="card-foot" style="margin:0 0 14px"><a href="#" id="goal-members-back">← Back to goal</a></p>
|
|
359
139
|
<div class="scroll" style="margin:0">
|
|
360
|
-
<h2 class="scroll__h" id="goal-members-view-h">Members<span class="
|
|
140
|
+
<h2 class="scroll__h" id="goal-members-view-h">Members<span class="count-pill" id="goal-members-view-count" hidden></span></h2>
|
|
361
141
|
<p class="scroll__lede">Who’s on this goal, and what they’ve contributed to it.</p>
|
|
362
142
|
<div class="goal-mstats" id="goal-members-stats"></div>
|
|
363
|
-
<div id="goal-members-full"
|
|
143
|
+
<div id="goal-members-full"></div>
|
|
364
144
|
</div>
|
|
365
145
|
</section>
|
|
366
146
|
|
|
@@ -371,7 +151,7 @@
|
|
|
371
151
|
<div class="scroll" style="margin:0">
|
|
372
152
|
<h2 class="scroll__h" id="goal-completion-view-h">Completion</h2>
|
|
373
153
|
<p class="scroll__lede">Every done-when criterion for this goal, with its full detail.</p>
|
|
374
|
-
<div id="goal-completion-full"
|
|
154
|
+
<div id="goal-completion-full"></div>
|
|
375
155
|
</div>
|
|
376
156
|
</section>
|
|
377
157
|
</main>
|
|
@@ -385,8 +165,10 @@
|
|
|
385
165
|
|
|
386
166
|
<script src="/builders/shell.js?v=2026-07-03-goals1"></script>
|
|
387
167
|
<script src="/builders/dom-utils.js?v=2026-06-14-domutils"></script>
|
|
168
|
+
<!-- shared component kit (window.OTBKit) — pager, filter bar, tabs, empty/skeleton (task 2166). -->
|
|
169
|
+
<script src="/builders/hall-kit.js"></script>
|
|
388
170
|
<script src="/builders/task-detail.js?v=2026-07-03-taskdetail"></script>
|
|
389
171
|
<script src="/builders/brand-apply.js?v=2026-06-27-r75"></script>
|
|
390
|
-
<script src="/builders/goals-page.js?v=2026-07-
|
|
172
|
+
<script src="/builders/goals-page.js?v=2026-07-10-goals5"></script>
|
|
391
173
|
</body>
|
|
392
174
|
</html>
|
|
@@ -74,14 +74,19 @@
|
|
|
74
74
|
</li>`;
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
+
// task 2184 (Home rule: a summary card never lists more than 5 rows): cap the
|
|
78
|
+
// joined-goals list; the overflow count rides the "All goals" foot link.
|
|
79
|
+
const MAX_HOME_ROWS = 5;
|
|
77
80
|
function render(joined) {
|
|
78
81
|
const body = host.querySelector('#goals-body');
|
|
79
82
|
if (!joined.length) {
|
|
80
83
|
body.innerHTML = '<p class="goal-empty">You haven’t joined any goals yet. <a href="/goals">Browse goals →</a></p>';
|
|
81
84
|
return;
|
|
82
85
|
}
|
|
83
|
-
|
|
84
|
-
|
|
86
|
+
const shown = joined.slice(0, MAX_HOME_ROWS);
|
|
87
|
+
const more = joined.length - shown.length;
|
|
88
|
+
body.innerHTML = `<ul class="goal-mine-list">${shown.map(row).join('')}</ul>` +
|
|
89
|
+
`<p class="goal-mine__foot card-foot"><a href="/goals">${more > 0 ? `All ${joined.length} goals →` : 'All goals →'}</a></p>`;
|
|
85
90
|
}
|
|
86
91
|
|
|
87
92
|
const SKELETON =
|