@unbrained/pm-web 2026.8.7 → 2026.8.14
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/CHANGELOG.md +16 -0
- package/dist/app.d.ts +16 -0
- package/dist/app.js +16 -0
- package/dist/app.js.map +1 -1
- package/dist/auth.d.ts +5 -0
- package/dist/auth.js.map +1 -1
- package/dist/board.d.ts +53 -0
- package/dist/board.js +48 -0
- package/dist/board.js.map +1 -1
- package/dist/crypto.d.ts +23 -0
- package/dist/crypto.js +32 -0
- package/dist/crypto.js.map +1 -1
- package/dist/db.d.ts +19 -0
- package/dist/db.js +19 -0
- package/dist/db.js.map +1 -1
- package/dist/ical.d.ts +72 -0
- package/dist/ical.js +73 -0
- package/dist/ical.js.map +1 -1
- package/dist/index.d.ts +11 -0
- package/dist/index.js +52 -1
- package/dist/index.js.map +1 -1
- package/dist/middleware/auth.d.ts +8 -0
- package/dist/middleware/auth.js.map +1 -1
- package/dist/oidc.d.ts +87 -0
- package/dist/oidc.js +113 -0
- package/dist/oidc.js.map +1 -1
- package/dist/routes/admin.js +15 -0
- package/dist/routes/admin.js.map +1 -1
- package/dist/routes/github.js +13 -0
- package/dist/routes/github.js.map +1 -1
- package/dist/routes/oidc.d.ts +10 -0
- package/dist/routes/oidc.js +51 -0
- package/dist/routes/oidc.js.map +1 -1
- package/dist/routes/pm.js +132 -1
- package/dist/routes/pm.js.map +1 -1
- package/dist/routes/sharing.js +8 -0
- package/dist/routes/sharing.js.map +1 -1
- package/dist/services/mutation-event-watcher.js +13 -0
- package/dist/services/mutation-event-watcher.js.map +1 -1
- package/dist/services/pm-runner.d.ts +82 -0
- package/dist/services/pm-runner.js +121 -0
- package/dist/services/pm-runner.js.map +1 -1
- package/dist/services/project-watcher.d.ts +22 -0
- package/dist/services/project-watcher.js +51 -0
- package/dist/services/project-watcher.js.map +1 -1
- package/dist/services/realtime-bus.d.ts +46 -0
- package/dist/services/realtime-bus.js +59 -0
- package/dist/services/realtime-bus.js.map +1 -1
- package/dist/services/sse.d.ts +134 -0
- package/dist/services/sse.js +145 -0
- package/dist/services/sse.js.map +1 -1
- package/manifest.json +1 -1
- package/package.json +5 -3
- package/public/src/app.js +44 -1
- package/public/src/app.js.map +1 -1
- package/public/src/app.ts +44 -1
- package/public/src/components/modals.js +11 -0
- package/public/src/components/modals.js.map +1 -1
- package/public/src/components/modals.ts +11 -0
- package/public/src/components/toast.js +2 -0
- package/public/src/components/toast.js.map +1 -1
- package/public/src/components/toast.ts +2 -0
- package/public/src/constants.js +21 -4
- package/public/src/constants.js.map +1 -1
- package/public/src/constants.ts +21 -4
- package/public/src/filters.js +10 -7
- package/public/src/filters.js.map +1 -1
- package/public/src/filters.ts +10 -7
- package/public/src/i18n.js +11 -1
- package/public/src/i18n.js.map +1 -1
- package/public/src/i18n.ts +13 -1
- package/public/src/state.js +3 -0
- package/public/src/state.js.map +1 -1
- package/public/src/state.ts +3 -0
- package/public/src/sw.ts +71 -7
- package/public/src/theme.js +13 -1
- package/public/src/theme.js.map +1 -1
- package/public/src/theme.ts +15 -1
- package/public/src/types.ts +2 -0
- package/public/src/utils.js +26 -1
- package/public/src/utils.js.map +1 -1
- package/public/src/utils.ts +26 -1
- package/public/src/views/activity.js +1 -0
- package/public/src/views/activity.js.map +1 -1
- package/public/src/views/activity.ts +1 -0
- package/public/src/views/admin.js +134 -0
- package/public/src/views/admin.js.map +1 -1
- package/public/src/views/admin.ts +134 -0
- package/public/src/views/auth.js +31 -0
- package/public/src/views/auth.js.map +1 -1
- package/public/src/views/auth.ts +31 -0
- package/public/src/views/calendar.js +3 -0
- package/public/src/views/calendar.js.map +1 -1
- package/public/src/views/calendar.ts +3 -0
- package/public/src/views/comments-audit.js +1 -0
- package/public/src/views/comments-audit.js.map +1 -1
- package/public/src/views/comments-audit.ts +1 -0
- package/public/src/views/config.js +67 -0
- package/public/src/views/config.js.map +1 -1
- package/public/src/views/config.ts +67 -0
- package/public/src/views/context.js +2 -0
- package/public/src/views/context.js.map +1 -1
- package/public/src/views/context.ts +2 -0
- package/public/src/views/create.js +3 -0
- package/public/src/views/create.js.map +1 -1
- package/public/src/views/create.ts +3 -0
- package/public/src/views/dedupe.js +1 -0
- package/public/src/views/dedupe.js.map +1 -1
- package/public/src/views/dedupe.ts +1 -0
- package/public/src/views/export.js +6 -0
- package/public/src/views/export.js.map +1 -1
- package/public/src/views/export.ts +6 -0
- package/public/src/views/github.js +58 -0
- package/public/src/views/github.js.map +1 -1
- package/public/src/views/github.ts +58 -0
- package/public/src/views/graph-canvas.js +18 -0
- package/public/src/views/graph-canvas.js.map +1 -1
- package/public/src/views/graph-canvas.ts +20 -0
- package/public/src/views/graph.js +41 -0
- package/public/src/views/graph.js.map +1 -1
- package/public/src/views/graph.ts +42 -1
- package/public/src/views/groups.js +45 -0
- package/public/src/views/groups.js.map +1 -1
- package/public/src/views/groups.ts +45 -0
- package/public/src/views/guide.js +3 -0
- package/public/src/views/guide.js.map +1 -1
- package/public/src/views/guide.ts +3 -0
- package/public/src/views/health.js +3 -0
- package/public/src/views/health.js.map +1 -1
- package/public/src/views/health.ts +3 -0
- package/public/src/views/items.js +196 -6
- package/public/src/views/items.js.map +1 -1
- package/public/src/views/items.ts +196 -6
- package/public/src/views/normalize.js +2 -0
- package/public/src/views/normalize.js.map +1 -1
- package/public/src/views/normalize.ts +2 -0
- package/public/src/views/packages.js +41 -0
- package/public/src/views/packages.js.map +1 -1
- package/public/src/views/packages.ts +41 -0
- package/public/src/views/plan-execution.js +6 -0
- package/public/src/views/plan-execution.js.map +1 -1
- package/public/src/views/plan-execution.ts +8 -0
- package/public/src/views/plan.js +145 -0
- package/public/src/views/plan.js.map +1 -1
- package/public/src/views/plan.ts +146 -1
- package/public/src/views/projects.js +60 -0
- package/public/src/views/projects.js.map +1 -1
- package/public/src/views/projects.ts +60 -0
- package/public/src/views/router.js +43 -0
- package/public/src/views/router.js.map +1 -1
- package/public/src/views/router.ts +43 -0
- package/public/src/views/search.js +5 -0
- package/public/src/views/search.js.map +1 -1
- package/public/src/views/search.ts +5 -0
- package/public/src/views/settings.js +36 -0
- package/public/src/views/settings.js.map +1 -1
- package/public/src/views/settings.ts +36 -0
- package/public/src/views/shared.js +1 -0
- package/public/src/views/shared.js.map +1 -1
- package/public/src/views/shared.ts +1 -0
- package/public/src/views/sharing.js +32 -0
- package/public/src/views/sharing.js.map +1 -1
- package/public/src/views/sharing.ts +32 -0
- package/public/src/views/stats.js +1 -0
- package/public/src/views/stats.js.map +1 -1
- package/public/src/views/stats.ts +1 -0
- package/public/src/views/templates.js +4 -0
- package/public/src/views/templates.js.map +1 -1
- package/public/src/views/templates.ts +4 -0
- package/public/src/views/validate.js +1 -0
- package/public/src/views/validate.js.map +1 -1
- package/public/src/views/validate.ts +1 -0
- package/public/sw.js +60 -5
|
@@ -43,9 +43,11 @@ interface BulkClosePayload {
|
|
|
43
43
|
reason: string;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
46
|
+
/**
|
|
47
|
+
* Mirrors the current item filters into the page URL query string when the
|
|
48
|
+
* items view is active, using history.replaceState so the filtered view is
|
|
49
|
+
* shareable without adding back/forward entries. Does nothing on other views.
|
|
50
|
+
*/
|
|
49
51
|
function syncFiltersToUrl(): void {
|
|
50
52
|
if (state.currentView !== 'items') return;
|
|
51
53
|
const qs = filtersToQueryString(state.itemFilters);
|
|
@@ -53,8 +55,12 @@ function syncFiltersToUrl(): void {
|
|
|
53
55
|
try { history.replaceState(history.state, '', url); } catch { /* ignore */ }
|
|
54
56
|
}
|
|
55
57
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
+
/**
|
|
59
|
+
* Reads item filters from the current URL query string into state. Only
|
|
60
|
+
* replaces the in-memory filters when the URL actually carries filter
|
|
61
|
+
* parameters, so navigating to /items without a query string preserves the
|
|
62
|
+
* existing filters.
|
|
63
|
+
*/
|
|
58
64
|
export function loadFiltersFromUrl(): void {
|
|
59
65
|
const params = new URLSearchParams(window.location.search);
|
|
60
66
|
// Only override when the URL actually carries filter params, so navigating
|
|
@@ -86,6 +92,12 @@ const DEP_REL_OPTIONS = [
|
|
|
86
92
|
{ value: 'related', label: 'Related' },
|
|
87
93
|
] as const;
|
|
88
94
|
|
|
95
|
+
/**
|
|
96
|
+
* Normalizes a raw dependency relationship label to a canonical value by
|
|
97
|
+
* trimming, lowercasing, and converting dashes to underscores, then applying a
|
|
98
|
+
* known-alias map (e.g. blockedby → blocked_by). Returns the alias when one
|
|
99
|
+
* exists, otherwise the normalized input unchanged.
|
|
100
|
+
*/
|
|
89
101
|
function normalizeDepRelation(raw?: string): string {
|
|
90
102
|
const aliases: Record<string, string> = {
|
|
91
103
|
blockedby: 'blocked_by',
|
|
@@ -107,6 +119,11 @@ function normalizeDepRelation(raw?: string): string {
|
|
|
107
119
|
return aliases[normalized] ?? normalized;
|
|
108
120
|
}
|
|
109
121
|
|
|
122
|
+
/**
|
|
123
|
+
* Builds the HTML <option> elements for a dependency relationship dropdown from
|
|
124
|
+
* the fixed DEP_REL_OPTIONS list, marking the option that matches the
|
|
125
|
+
* normalized selected value as selected.
|
|
126
|
+
*/
|
|
110
127
|
function renderDependencyOptions(selected?: string): string {
|
|
111
128
|
const current = normalizeDepRelation(selected);
|
|
112
129
|
return DEP_REL_OPTIONS
|
|
@@ -114,6 +131,11 @@ function renderDependencyOptions(selected?: string): string {
|
|
|
114
131
|
.join('');
|
|
115
132
|
}
|
|
116
133
|
|
|
134
|
+
/**
|
|
135
|
+
* Returns a human-readable display label for a dependency relationship by
|
|
136
|
+
* looking up its normalized value in a fixed label map, falling back to the
|
|
137
|
+
* original relationship string when no label is defined.
|
|
138
|
+
*/
|
|
117
139
|
function depLabel(rel: string): string {
|
|
118
140
|
const labels: Record<string, string> = {
|
|
119
141
|
blocked_by: 'Blocked by',
|
|
@@ -136,6 +158,11 @@ function depRelation(dep: RawDependency): string {
|
|
|
136
158
|
// ═══════════════════════════════════════════════════════════════
|
|
137
159
|
// BULK UPDATE
|
|
138
160
|
// ═══════════════════════════════════════════════════════════════
|
|
161
|
+
/**
|
|
162
|
+
* Opens the Bulk Update Items modal, which lets the user filter items and
|
|
163
|
+
* choose fields to change across many items at once. Shows an info toast and
|
|
164
|
+
* returns early when no project is currently selected.
|
|
165
|
+
*/
|
|
139
166
|
export function showBulkUpdateModal(): void {
|
|
140
167
|
if (!state.currentProject) { toast('Select a project first', 'info'); return; }
|
|
141
168
|
createModal('bulk-update-modal', 'Bulk Update Items', `
|
|
@@ -208,6 +235,12 @@ export function showBulkUpdateModal(): void {
|
|
|
208
235
|
showModal('bulk-update-modal');
|
|
209
236
|
}
|
|
210
237
|
|
|
238
|
+
/**
|
|
239
|
+
* Runs a dry-run bulk update and renders a preview of the matched items and
|
|
240
|
+
* their field changes inside the modal. Requires at least one field to update,
|
|
241
|
+
* and stashes the actual (non-dry-run) payload on the Apply button so
|
|
242
|
+
* applyBulkUpdate can run without re-reading the form.
|
|
243
|
+
*/
|
|
211
244
|
export async function previewBulkUpdate(): Promise<void> {
|
|
212
245
|
const pid = state.currentProject?.id;
|
|
213
246
|
if (!pid) return;
|
|
@@ -281,6 +314,12 @@ export async function previewBulkUpdate(): Promise<void> {
|
|
|
281
314
|
}
|
|
282
315
|
}
|
|
283
316
|
|
|
317
|
+
/**
|
|
318
|
+
* Applies the bulk update payload stashed on the Apply button by
|
|
319
|
+
* previewBulkUpdate, posting to the update-many endpoint. Reports the updated
|
|
320
|
+
* and failed counts via toast, closes the bulk update modal, and refreshes the
|
|
321
|
+
* items list and project badge.
|
|
322
|
+
*/
|
|
284
323
|
export async function applyBulkUpdate(): Promise<void> {
|
|
285
324
|
const pid = state.currentProject?.id;
|
|
286
325
|
if (!pid) return;
|
|
@@ -309,6 +348,11 @@ export async function applyBulkUpdate(): Promise<void> {
|
|
|
309
348
|
// ═══════════════════════════════════════════════════════════════
|
|
310
349
|
// BULK CLOSE
|
|
311
350
|
// ═══════════════════════════════════════════════════════════════
|
|
351
|
+
/**
|
|
352
|
+
* Opens the Bulk Close Items modal, which lets the user filter items and close
|
|
353
|
+
* or cancel many of them at once with a required reason. Shows an info toast
|
|
354
|
+
* and returns early when no project is currently selected.
|
|
355
|
+
*/
|
|
312
356
|
export function showBulkCloseModal(): void {
|
|
313
357
|
if (!state.currentProject) { toast('Select a project first', 'info'); return; }
|
|
314
358
|
createModal('bulk-close-modal', 'Bulk Close Items', `
|
|
@@ -364,6 +408,12 @@ export function showBulkCloseModal(): void {
|
|
|
364
408
|
showModal('bulk-close-modal');
|
|
365
409
|
}
|
|
366
410
|
|
|
411
|
+
/**
|
|
412
|
+
* Previews the items that would be closed or canceled by running an
|
|
413
|
+
* update-many dry-run, and renders the matched count and first few items
|
|
414
|
+
* inside the modal. Requires a close reason, and stashes the close payload on
|
|
415
|
+
* the Apply button for applyBulkClose to use.
|
|
416
|
+
*/
|
|
367
417
|
export async function previewBulkClose(): Promise<void> {
|
|
368
418
|
const pid = state.currentProject?.id;
|
|
369
419
|
if (!pid) return;
|
|
@@ -423,6 +473,13 @@ export async function previewBulkClose(): Promise<void> {
|
|
|
423
473
|
}
|
|
424
474
|
}
|
|
425
475
|
|
|
476
|
+
/**
|
|
477
|
+
* Applies the bulk close payload stashed on the Apply button by
|
|
478
|
+
* previewBulkClose, posting to the close-many endpoint which closes or cancels
|
|
479
|
+
* each matched item with the chosen reason. Reports the closed and failed
|
|
480
|
+
* counts via toast, closes the modal, and refreshes the items list and project
|
|
481
|
+
* badge.
|
|
482
|
+
*/
|
|
426
483
|
export async function applyBulkClose(): Promise<void> {
|
|
427
484
|
const pid = state.currentProject?.id;
|
|
428
485
|
if (!pid) return;
|
|
@@ -460,6 +517,12 @@ export async function applyBulkClose(): Promise<void> {
|
|
|
460
517
|
}
|
|
461
518
|
}
|
|
462
519
|
|
|
520
|
+
/**
|
|
521
|
+
* Renders the Items view into the page: a header with refresh and bulk
|
|
522
|
+
* actions, the status filter tabs, the multi-field filter bar, and a loading
|
|
523
|
+
* list placeholder, then fetches and renders the items. Shows an empty state
|
|
524
|
+
* and returns when no project is selected.
|
|
525
|
+
*/
|
|
463
526
|
export async function renderItemsView(): Promise<void> {
|
|
464
527
|
const el = document.getElementById('content-items');
|
|
465
528
|
if (!el) return;
|
|
@@ -512,6 +575,12 @@ export async function renderItemsView(): Promise<void> {
|
|
|
512
575
|
await fetchAndRenderItems();
|
|
513
576
|
}
|
|
514
577
|
|
|
578
|
+
/**
|
|
579
|
+
* Fetches items for the current project using the active filters (capped at
|
|
580
|
+
* 200, with tags filtered client-side because the list endpoint has no tag
|
|
581
|
+
* flag), stores them in state, updates the count subtitle, and renders the
|
|
582
|
+
* list. Shows an error state in the list element if the request fails.
|
|
583
|
+
*/
|
|
515
584
|
export async function fetchAndRenderItems(): Promise<void> {
|
|
516
585
|
const pid = state.currentProject?.id;
|
|
517
586
|
if (!pid) return;
|
|
@@ -545,6 +614,10 @@ export async function fetchAndRenderItems(): Promise<void> {
|
|
|
545
614
|
}
|
|
546
615
|
}
|
|
547
616
|
|
|
617
|
+
/**
|
|
618
|
+
* Renders the items list element from state.items, showing an empty-state
|
|
619
|
+
* placeholder when there are no items or the mapped item rows otherwise.
|
|
620
|
+
*/
|
|
548
621
|
function renderItemsList(): void {
|
|
549
622
|
const el = document.getElementById('items-list');
|
|
550
623
|
if (!el) return;
|
|
@@ -559,6 +632,11 @@ function renderItemsList(): void {
|
|
|
559
632
|
el.innerHTML = `<div class="item-list">${state.items.map(item => renderItemRow(item)).join('')}</div>`;
|
|
560
633
|
}
|
|
561
634
|
|
|
635
|
+
/**
|
|
636
|
+
* Returns the HTML markup for a single items-list row: a clickable card
|
|
637
|
+
* showing the item's type icon, id, title, tags, priority dot, and status
|
|
638
|
+
* badge that opens the item detail modal when clicked.
|
|
639
|
+
*/
|
|
562
640
|
export function renderItemRow(item: Item): string {
|
|
563
641
|
const tags = (item.tags||[]).map(t=>`<span class="tag">${escHtml(t)}</span>`).join('');
|
|
564
642
|
return `<div class="item-row" onclick="window.__app.openItemDetail('${escHtml(item.id)}')">
|
|
@@ -573,6 +651,11 @@ export function renderItemRow(item: Item): string {
|
|
|
573
651
|
</div>`;
|
|
574
652
|
}
|
|
575
653
|
|
|
654
|
+
/**
|
|
655
|
+
* Reads the current values from every items filter-bar control into
|
|
656
|
+
* state.itemFilters, mirrors them to the URL, and re-fetches and renders the
|
|
657
|
+
* list.
|
|
658
|
+
*/
|
|
576
659
|
export function applyItemFilters(): void {
|
|
577
660
|
const fs = document.getElementById('filter-status') as HTMLSelectElement | null;
|
|
578
661
|
const ft = document.getElementById('filter-type') as HTMLSelectElement | null;
|
|
@@ -592,6 +675,10 @@ export function applyItemFilters(): void {
|
|
|
592
675
|
fetchAndRenderItems();
|
|
593
676
|
}
|
|
594
677
|
|
|
678
|
+
/**
|
|
679
|
+
* Resets the item filters to empty, clears every filter-bar control in the
|
|
680
|
+
* DOM, mirrors the cleared filters to the URL, and re-renders the items list.
|
|
681
|
+
*/
|
|
595
682
|
export function clearFilters(): void {
|
|
596
683
|
state.itemFilters = { ...EMPTY_FILTERS };
|
|
597
684
|
const ids = ['filter-status','filter-type','filter-priority','filter-sprint','filter-release','filter-assignee','filter-tag'];
|
|
@@ -603,7 +690,11 @@ export function clearFilters(): void {
|
|
|
603
690
|
fetchAndRenderItems();
|
|
604
691
|
}
|
|
605
692
|
|
|
606
|
-
|
|
693
|
+
/**
|
|
694
|
+
* Builds a shareable URL for the current filtered items view and copies it to
|
|
695
|
+
* the clipboard, toasting success or, if the clipboard write fails, toasting
|
|
696
|
+
* the URL itself for manual copy.
|
|
697
|
+
*/
|
|
607
698
|
export async function copyFilterLink(): Promise<void> {
|
|
608
699
|
const qs = filtersToQueryString(state.itemFilters);
|
|
609
700
|
const url = `${window.location.origin}/items${qs ? `?${qs}` : ''}`;
|
|
@@ -615,6 +706,10 @@ export async function copyFilterLink(): Promise<void> {
|
|
|
615
706
|
}
|
|
616
707
|
}
|
|
617
708
|
|
|
709
|
+
/**
|
|
710
|
+
* Sets the status filter to the provided value, mirrors it to the URL, and
|
|
711
|
+
* re-renders the entire items view.
|
|
712
|
+
*/
|
|
618
713
|
export function setStatusFilter(status: string): void {
|
|
619
714
|
state.itemFilters.status = status;
|
|
620
715
|
syncFiltersToUrl();
|
|
@@ -624,6 +719,12 @@ export function setStatusFilter(status: string): void {
|
|
|
624
719
|
// ═══════════════════════════════════════════════════════════════
|
|
625
720
|
// ITEM DETAIL MODAL
|
|
626
721
|
// ═══════════════════════════════════════════════════════════════
|
|
722
|
+
/**
|
|
723
|
+
* Opens the item detail modal and renders it. Fetches the item together with
|
|
724
|
+
* its comments, history, dependencies, learnings, notes, tests, and linked
|
|
725
|
+
* files in parallel (each detail call falls back to empty on failure) and
|
|
726
|
+
* builds the full tabbed detail view.
|
|
727
|
+
*/
|
|
627
728
|
export async function openItemDetail(itemId: string): Promise<void> {
|
|
628
729
|
const pid = state.currentProject?.id;
|
|
629
730
|
if (!pid) return;
|
|
@@ -966,6 +1067,11 @@ export async function openItemDetail(itemId: string): Promise<void> {
|
|
|
966
1067
|
}
|
|
967
1068
|
}
|
|
968
1069
|
|
|
1070
|
+
/**
|
|
1071
|
+
* Formats a timestamp as a human-readable relative age string (just now,
|
|
1072
|
+
* Nm/Nh/Nd ago) for recent times, or a localized date for anything older than
|
|
1073
|
+
* a week. Returns an empty string when the timestamp is missing.
|
|
1074
|
+
*/
|
|
969
1075
|
function relTime(ts: string | undefined | null): string {
|
|
970
1076
|
if (!ts) return '';
|
|
971
1077
|
const d = new Date(ts);
|
|
@@ -983,6 +1089,12 @@ function fmtDate(ts: string | undefined | null): string {
|
|
|
983
1089
|
return new Date(ts).toLocaleDateString('en-US', { year:'numeric', month:'short', day:'numeric' });
|
|
984
1090
|
}
|
|
985
1091
|
|
|
1092
|
+
/**
|
|
1093
|
+
* Switches the item detail modal to the selected tab: toggles the active class
|
|
1094
|
+
* on the tabs, shows the target tab panel while hiding the others, tears down
|
|
1095
|
+
* the local graph when leaving the graph tab, and initializes the graph along
|
|
1096
|
+
* with its depth-slider listener when entering the graph tab with a nodeId.
|
|
1097
|
+
*/
|
|
986
1098
|
export function switchDetailTab(tabEl: HTMLElement, targetId: string, nodeId?: string): void {
|
|
987
1099
|
const allTabs = tabEl.parentElement?.querySelectorAll('.tab');
|
|
988
1100
|
allTabs?.forEach(t => t.classList.remove('active'));
|
|
@@ -1008,6 +1120,11 @@ export function switchDetailTab(tabEl: HTMLElement, targetId: string, nodeId?: s
|
|
|
1008
1120
|
}
|
|
1009
1121
|
}
|
|
1010
1122
|
|
|
1123
|
+
/**
|
|
1124
|
+
* Posts the comment typed into the detail modal's comment box to the item,
|
|
1125
|
+
* requiring non-empty text. On success it clears the box, toasts confirmation,
|
|
1126
|
+
* and reopens the item detail to refresh the comments tab.
|
|
1127
|
+
*/
|
|
1011
1128
|
export async function addComment(itemId: string): Promise<void> {
|
|
1012
1129
|
const el = document.getElementById('new-comment') as HTMLTextAreaElement | null;
|
|
1013
1130
|
if (!el) return;
|
|
@@ -1021,6 +1138,10 @@ export async function addComment(itemId: string): Promise<void> {
|
|
|
1021
1138
|
} catch(err: unknown) { toast(err instanceof Error ? err.message : String(err),'error'); }
|
|
1022
1139
|
}
|
|
1023
1140
|
|
|
1141
|
+
/**
|
|
1142
|
+
* Posts the note typed into the detail modal's note box to the item, requiring
|
|
1143
|
+
* non-empty text. On success it clears the box and toasts confirmation.
|
|
1144
|
+
*/
|
|
1024
1145
|
export async function addNote(itemId: string): Promise<void> {
|
|
1025
1146
|
const el = document.getElementById('new-note') as HTMLTextAreaElement | null;
|
|
1026
1147
|
if (!el) return;
|
|
@@ -1033,6 +1154,11 @@ export async function addNote(itemId: string): Promise<void> {
|
|
|
1033
1154
|
} catch(err: unknown) { toast(err instanceof Error ? err.message : String(err),'error'); }
|
|
1034
1155
|
}
|
|
1035
1156
|
|
|
1157
|
+
/**
|
|
1158
|
+
* Appends the text from the detail modal's append box to the item's
|
|
1159
|
+
* description, requiring non-empty text. On success it clears the box and
|
|
1160
|
+
* toasts confirmation.
|
|
1161
|
+
*/
|
|
1036
1162
|
export async function appendItem(itemId: string): Promise<void> {
|
|
1037
1163
|
const el = document.getElementById('new-append') as HTMLTextAreaElement | null;
|
|
1038
1164
|
if (!el) return;
|
|
@@ -1045,6 +1171,11 @@ export async function appendItem(itemId: string): Promise<void> {
|
|
|
1045
1171
|
} catch(err: unknown) { toast(err instanceof Error ? err.message : String(err),'error'); }
|
|
1046
1172
|
}
|
|
1047
1173
|
|
|
1174
|
+
/**
|
|
1175
|
+
* Saves the item detail's Update form: reads every edit field, requires a
|
|
1176
|
+
* title, and PATCHes the changed fields to the backend. On success it reopens
|
|
1177
|
+
* the item detail and refreshes the items list and project badge.
|
|
1178
|
+
*/
|
|
1048
1179
|
export async function updateItem(itemId: string): Promise<void> {
|
|
1049
1180
|
const titleEl = document.getElementById('edit-title') as HTMLInputElement | null;
|
|
1050
1181
|
const statusEl = document.getElementById('edit-status') as HTMLSelectElement | null;
|
|
@@ -1093,6 +1224,12 @@ export async function updateItem(itemId: string): Promise<void> {
|
|
|
1093
1224
|
} catch(err: unknown) { toast(err instanceof Error ? err.message : String(err),'error'); }
|
|
1094
1225
|
}
|
|
1095
1226
|
|
|
1227
|
+
/**
|
|
1228
|
+
* Closes or cancels the item with a required reason. For canceled it first
|
|
1229
|
+
* sets the status to canceled via the update endpoint before posting the close
|
|
1230
|
+
* reason; for closed it posts the close reason directly. Reports the outcome,
|
|
1231
|
+
* hides the detail modal, and refreshes the items list and project badge.
|
|
1232
|
+
*/
|
|
1096
1233
|
export async function closeItem(itemId: string, targetStatus: string): Promise<void> {
|
|
1097
1234
|
const reasonEl = document.getElementById('close-reason') as HTMLTextAreaElement | null;
|
|
1098
1235
|
const reason = reasonEl?.value?.trim();
|
|
@@ -1111,6 +1248,10 @@ export async function closeItem(itemId: string, targetStatus: string): Promise<v
|
|
|
1111
1248
|
} catch(err: unknown) { toast(err instanceof Error ? err.message : String(err),'error'); }
|
|
1112
1249
|
}
|
|
1113
1250
|
|
|
1251
|
+
/**
|
|
1252
|
+
* Shows a confirmation dialog and, on confirm, DELETEs the item, hides the
|
|
1253
|
+
* detail modal, and refreshes the items list and project badge.
|
|
1254
|
+
*/
|
|
1114
1255
|
export function confirmDeleteItem(itemId: string): void {
|
|
1115
1256
|
confirmDialog('Delete Item?', 'This action cannot be undone. The item and all its data will be permanently removed.', async () => {
|
|
1116
1257
|
try {
|
|
@@ -1126,6 +1267,12 @@ export function confirmDeleteItem(itemId: string): void {
|
|
|
1126
1267
|
// ═══════════════════════════════════════════════════════════════
|
|
1127
1268
|
// CLAIM / RELEASE / START / PAUSE
|
|
1128
1269
|
// ═══════════════════════════════════════════════════════════════
|
|
1270
|
+
/**
|
|
1271
|
+
* Claims the item for the current user via the claim endpoint, dimming the
|
|
1272
|
+
* matching list row optimistically. On success it reopens the detail and
|
|
1273
|
+
* refreshes the list; on failure it restores the row opacity and toasts the
|
|
1274
|
+
* error.
|
|
1275
|
+
*/
|
|
1129
1276
|
export async function claimItem(itemId: string): Promise<void> {
|
|
1130
1277
|
const row = document.querySelector(`.item-row[onclick*="${itemId}"]`) as HTMLElement | null;
|
|
1131
1278
|
if (row) row.style.opacity = '0.6';
|
|
@@ -1137,6 +1284,10 @@ export async function claimItem(itemId: string): Promise<void> {
|
|
|
1137
1284
|
} catch(err: unknown) { toast(err instanceof Error ? err.message : String(err),'error'); if (row) row.style.opacity = ''; }
|
|
1138
1285
|
}
|
|
1139
1286
|
|
|
1287
|
+
/**
|
|
1288
|
+
* Releases the current user's claim on the item via the release endpoint, then
|
|
1289
|
+
* reopens the detail and refreshes the items list.
|
|
1290
|
+
*/
|
|
1140
1291
|
export async function releaseItem(itemId: string): Promise<void> {
|
|
1141
1292
|
try {
|
|
1142
1293
|
await api('POST',`/projects/${state.currentProject!.id}/pm/release/${itemId}`,{});
|
|
@@ -1146,6 +1297,10 @@ export async function releaseItem(itemId: string): Promise<void> {
|
|
|
1146
1297
|
} catch(err: unknown) { toast(err instanceof Error ? err.message : String(err),'error'); }
|
|
1147
1298
|
}
|
|
1148
1299
|
|
|
1300
|
+
/**
|
|
1301
|
+
* Starts the item (moving it into in_progress) via the start-task endpoint,
|
|
1302
|
+
* then reopens the detail and refreshes the items list and project badge.
|
|
1303
|
+
*/
|
|
1149
1304
|
export async function startItem(itemId: string): Promise<void> {
|
|
1150
1305
|
try {
|
|
1151
1306
|
await api('POST',`/projects/${state.currentProject!.id}/pm/start-task/${itemId}`,{});
|
|
@@ -1156,6 +1311,10 @@ export async function startItem(itemId: string): Promise<void> {
|
|
|
1156
1311
|
} catch(err: unknown) { toast(err instanceof Error ? err.message : String(err),'error'); }
|
|
1157
1312
|
}
|
|
1158
1313
|
|
|
1314
|
+
/**
|
|
1315
|
+
* Pauses the in-progress item via the pause-task endpoint, then reopens the
|
|
1316
|
+
* detail and refreshes the items list and project badge.
|
|
1317
|
+
*/
|
|
1159
1318
|
export async function pauseItem(itemId: string): Promise<void> {
|
|
1160
1319
|
try {
|
|
1161
1320
|
await api('POST',`/projects/${state.currentProject!.id}/pm/pause-task/${itemId}`,{});
|
|
@@ -1169,6 +1328,12 @@ export async function pauseItem(itemId: string): Promise<void> {
|
|
|
1169
1328
|
// ═══════════════════════════════════════════════════════════════
|
|
1170
1329
|
// DEPS / LEARNINGS / TESTS / FILES
|
|
1171
1330
|
// ═══════════════════════════════════════════════════════════════
|
|
1331
|
+
/**
|
|
1332
|
+
* Adds a dependency to the item from the detail modal's dependency inputs:
|
|
1333
|
+
* reads and normalizes the target id and relationship, rejects an empty or
|
|
1334
|
+
* self-referential target, and posts to the deps endpoint. On success it
|
|
1335
|
+
* reopens the item detail.
|
|
1336
|
+
*/
|
|
1172
1337
|
export async function addDep(itemId: string): Promise<void> {
|
|
1173
1338
|
const targetIdEl = document.getElementById('dep-target-id') as HTMLInputElement | null;
|
|
1174
1339
|
const relEl = document.getElementById('dep-rel') as HTMLSelectElement | null;
|
|
@@ -1186,6 +1351,11 @@ export async function addDep(itemId: string): Promise<void> {
|
|
|
1186
1351
|
} catch(err: unknown) { toast(err instanceof Error ? err.message : String(err),'error'); }
|
|
1187
1352
|
}
|
|
1188
1353
|
|
|
1354
|
+
/**
|
|
1355
|
+
* Removes a dependency from the item after confirming with the user. Normalizes
|
|
1356
|
+
* the relationship, requires a target id, and DELETEs the dependency from the
|
|
1357
|
+
* deps endpoint; on success it reopens the item detail.
|
|
1358
|
+
*/
|
|
1189
1359
|
export async function removeDep(itemId: string, targetId: string, relation: string): Promise<void> {
|
|
1190
1360
|
const rel = normalizeDepRelation(relation);
|
|
1191
1361
|
if (!targetId) { toast('Target item ID is required','error'); return; }
|
|
@@ -1203,6 +1373,11 @@ export async function removeDep(itemId: string, targetId: string, relation: stri
|
|
|
1203
1373
|
);
|
|
1204
1374
|
}
|
|
1205
1375
|
|
|
1376
|
+
/**
|
|
1377
|
+
* Records a learning typed into the detail modal on the item, requiring
|
|
1378
|
+
* non-empty text. On success it toasts confirmation and reopens the item
|
|
1379
|
+
* detail.
|
|
1380
|
+
*/
|
|
1206
1381
|
export async function addLearning(itemId: string): Promise<void> {
|
|
1207
1382
|
const el = document.getElementById('new-learning') as HTMLTextAreaElement | null;
|
|
1208
1383
|
const text = el?.value?.trim() || '';
|
|
@@ -1214,6 +1389,11 @@ export async function addLearning(itemId: string): Promise<void> {
|
|
|
1214
1389
|
} catch(err: unknown) { toast(err instanceof Error ? err.message : String(err),'error'); }
|
|
1215
1390
|
}
|
|
1216
1391
|
|
|
1392
|
+
/**
|
|
1393
|
+
* Adds a test command (required) with an optional description to the item via
|
|
1394
|
+
* the tests endpoint. On success it toasts confirmation and reopens the item
|
|
1395
|
+
* detail.
|
|
1396
|
+
*/
|
|
1217
1397
|
export async function addTest(itemId: string): Promise<void> {
|
|
1218
1398
|
const cmdEl = document.getElementById('new-test-cmd') as HTMLInputElement | null;
|
|
1219
1399
|
const descEl = document.getElementById('new-test-desc') as HTMLInputElement | null;
|
|
@@ -1227,6 +1407,10 @@ export async function addTest(itemId: string): Promise<void> {
|
|
|
1227
1407
|
} catch(err: unknown) { toast(err instanceof Error ? err.message : String(err),'error'); }
|
|
1228
1408
|
}
|
|
1229
1409
|
|
|
1410
|
+
/**
|
|
1411
|
+
* Links a file path (required) to the item via the files endpoint. On success
|
|
1412
|
+
* it toasts confirmation and reopens the item detail.
|
|
1413
|
+
*/
|
|
1230
1414
|
export async function addFileLink(itemId: string): Promise<void> {
|
|
1231
1415
|
const el = document.getElementById('file-path-input') as HTMLInputElement | null;
|
|
1232
1416
|
const filePath = el?.value?.trim() || '';
|
|
@@ -1241,6 +1425,12 @@ export async function addFileLink(itemId: string): Promise<void> {
|
|
|
1241
1425
|
// ═══════════════════════════════════════════════════════════════
|
|
1242
1426
|
// USE ITEM AS TEMPLATE
|
|
1243
1427
|
// ═══════════════════════════════════════════════════════════════
|
|
1428
|
+
/**
|
|
1429
|
+
* Closes the item detail modal and opens the create view pre-filled from the
|
|
1430
|
+
* given item's fields, prefixing the title with "Copy of" and focusing and
|
|
1431
|
+
* selecting it so the user can immediately edit. The form is filled after a
|
|
1432
|
+
* short delay to let the create view render.
|
|
1433
|
+
*/
|
|
1244
1434
|
export function useItemAsTemplate(item: Record<string, unknown>): void {
|
|
1245
1435
|
// Close the item detail modal and navigate to create view
|
|
1246
1436
|
hideModal('item-detail-modal');
|
|
@@ -5,6 +5,7 @@ import { state } from '../state.js';
|
|
|
5
5
|
import { api } from '../api.js';
|
|
6
6
|
import { escHtml } from '../utils.js';
|
|
7
7
|
import { toast } from '../components/toast.js';
|
|
8
|
+
/** Renders a dry-run preview of lifecycle metadata normalization for the current project, listing each suggested change with an item link and an apply button that only advises using the CLI. */
|
|
8
9
|
export async function renderNormalizeView() {
|
|
9
10
|
const el = document.getElementById('content-normalize');
|
|
10
11
|
if (!el)
|
|
@@ -59,6 +60,7 @@ export async function renderNormalizeView() {
|
|
|
59
60
|
el2.innerHTML = `<div class="empty-state"><div class="empty-state-text">Error: ${escHtml(err instanceof Error ? err.message : String(err))}</div></div>`;
|
|
60
61
|
}
|
|
61
62
|
}
|
|
63
|
+
/** Notifies the user that normalization in the web UI is a dry-run and that applying changes requires the CLI with the --apply flag. */
|
|
62
64
|
export function applyNormalize() {
|
|
63
65
|
if (!state.currentProject)
|
|
64
66
|
return;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"normalize.js","sourceRoot":"","sources":["normalize.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,iBAAiB;AACjB,kEAAkE;AAClE,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACpC,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAChC,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AACtC,OAAO,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAC;AAG/C,MAAM,CAAC,KAAK,UAAU,mBAAmB;IACvC,MAAM,EAAE,GAAG,QAAQ,CAAC,cAAc,CAAC,mBAAmB,CAAC,CAAC;IACxD,IAAI,CAAC,EAAE;QAAE,OAAO;IAChB,IAAI,CAAC,KAAK,CAAC,cAAc,EAAE,CAAC;QAAC,EAAE,CAAC,SAAS,GAAG,wFAAwF,CAAC;QAAC,OAAO;IAAC,CAAC;IAC/I,EAAE,CAAC,SAAS,GAAG;;oHAEmG,OAAO,CAAC,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC;;;2GAG3C,CAAC;IAC1G,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,GAAG,CAAoB,MAAM,EAAE,aAAa,KAAK,CAAC,cAAc,CAAC,EAAE,eAAe,CAAC,CAAC;QACvG,MAAM,IAAI,GAAkB,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC;QACpE,MAAM,KAAK,GAAsB,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC;QAClE,MAAM,GAAG,GAAG,QAAQ,CAAC,cAAc,CAAC,mBAAmB,CAAC,CAAC;QACzD,IAAI,CAAC,GAAG;YAAE,OAAO;QACjB,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC/C,GAAG,CAAC,SAAS,GAAG,mKAAmK,CAAC;QACtL,CAAC;aAAM,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACpD,GAAG,CAAC,SAAS,GAAG;;gFAE0D,KAAK,CAAC,MAAM;;cAE9E,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;;;;gDAIiB,OAAO,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,WAAW,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;oBACpF,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,wHAAwH,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,gDAAgD,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE;;qBAEzN,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;;;;;;eAMhB,CAAC;QACZ,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,SAAS,GAAG,yHAAyH,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,oBAAoB,CAAC;QACtM,CAAC;IACH,CAAC;IAAC,OAAM,GAAY,EAAE,CAAC;QACrB,MAAM,GAAG,GAAG,QAAQ,CAAC,cAAc,CAAC,mBAAmB,CAAC,CAAC;QACzD,IAAI,GAAG;YAAE,GAAG,CAAC,SAAS,GAAG,iEAAiE,OAAO,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,cAAc,CAAC;IACpK,CAAC;AACH,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,IAAI,CAAC,KAAK,CAAC,cAAc;QAAE,OAAO;IAClC,KAAK,CAAC,wEAAwE,EAAE,MAAM,CAAC,CAAC;AAC1F,CAAC"}
|
|
1
|
+
{"version":3,"file":"normalize.js","sourceRoot":"","sources":["normalize.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,iBAAiB;AACjB,kEAAkE;AAClE,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACpC,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAChC,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AACtC,OAAO,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAC;AAG/C,kMAAkM;AAClM,MAAM,CAAC,KAAK,UAAU,mBAAmB;IACvC,MAAM,EAAE,GAAG,QAAQ,CAAC,cAAc,CAAC,mBAAmB,CAAC,CAAC;IACxD,IAAI,CAAC,EAAE;QAAE,OAAO;IAChB,IAAI,CAAC,KAAK,CAAC,cAAc,EAAE,CAAC;QAAC,EAAE,CAAC,SAAS,GAAG,wFAAwF,CAAC;QAAC,OAAO;IAAC,CAAC;IAC/I,EAAE,CAAC,SAAS,GAAG;;oHAEmG,OAAO,CAAC,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC;;;2GAG3C,CAAC;IAC1G,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,GAAG,CAAoB,MAAM,EAAE,aAAa,KAAK,CAAC,cAAc,CAAC,EAAE,eAAe,CAAC,CAAC;QACvG,MAAM,IAAI,GAAkB,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC;QACpE,MAAM,KAAK,GAAsB,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC;QAClE,MAAM,GAAG,GAAG,QAAQ,CAAC,cAAc,CAAC,mBAAmB,CAAC,CAAC;QACzD,IAAI,CAAC,GAAG;YAAE,OAAO;QACjB,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC/C,GAAG,CAAC,SAAS,GAAG,mKAAmK,CAAC;QACtL,CAAC;aAAM,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACpD,GAAG,CAAC,SAAS,GAAG;;gFAE0D,KAAK,CAAC,MAAM;;cAE9E,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;;;;gDAIiB,OAAO,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,WAAW,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;oBACpF,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,wHAAwH,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,gDAAgD,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE;;qBAEzN,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;;;;;;eAMhB,CAAC;QACZ,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,SAAS,GAAG,yHAAyH,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,oBAAoB,CAAC;QACtM,CAAC;IACH,CAAC;IAAC,OAAM,GAAY,EAAE,CAAC;QACrB,MAAM,GAAG,GAAG,QAAQ,CAAC,cAAc,CAAC,mBAAmB,CAAC,CAAC;QACzD,IAAI,GAAG;YAAE,GAAG,CAAC,SAAS,GAAG,iEAAiE,OAAO,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,cAAc,CAAC;IACpK,CAAC;AACH,CAAC;AAED,wIAAwI;AACxI,MAAM,UAAU,cAAc;IAC5B,IAAI,CAAC,KAAK,CAAC,cAAc;QAAE,OAAO;IAClC,KAAK,CAAC,wEAAwE,EAAE,MAAM,CAAC,CAAC;AAC1F,CAAC"}
|
|
@@ -7,6 +7,7 @@ import { escHtml } from '../utils.js';
|
|
|
7
7
|
import { toast } from '../components/toast.js';
|
|
8
8
|
import type { NormalizeChange, NormalizePlan, NormalizeResponse } from '../api-types.js';
|
|
9
9
|
|
|
10
|
+
/** Renders a dry-run preview of lifecycle metadata normalization for the current project, listing each suggested change with an item link and an apply button that only advises using the CLI. */
|
|
10
11
|
export async function renderNormalizeView(): Promise<void> {
|
|
11
12
|
const el = document.getElementById('content-normalize');
|
|
12
13
|
if (!el) return;
|
|
@@ -53,6 +54,7 @@ export async function renderNormalizeView(): Promise<void> {
|
|
|
53
54
|
}
|
|
54
55
|
}
|
|
55
56
|
|
|
57
|
+
/** Notifies the user that normalization in the web UI is a dry-run and that applying changes requires the CLI with the --apply flag. */
|
|
56
58
|
export function applyNormalize(): void {
|
|
57
59
|
if (!state.currentProject) return;
|
|
58
60
|
toast('Normalization applied (dry-run — use CLI with --apply to make changes)', 'info');
|
|
@@ -30,6 +30,12 @@ let currentPackages = [];
|
|
|
30
30
|
* own response if a newer fetch has begun since.
|
|
31
31
|
*/
|
|
32
32
|
let packagesFetchToken = 0;
|
|
33
|
+
/**
|
|
34
|
+
* Mounts the packages view into the #content-packages element. Wires the
|
|
35
|
+
* action handler, shows an empty state when no project is selected, otherwise
|
|
36
|
+
* renders the header and a loading placeholder, then fetches and renders the
|
|
37
|
+
* package cards.
|
|
38
|
+
*/
|
|
33
39
|
export async function renderPackagesView() {
|
|
34
40
|
ensureActionsWired();
|
|
35
41
|
const el = document.getElementById('content-packages');
|
|
@@ -52,6 +58,12 @@ export async function renderPackagesView() {
|
|
|
52
58
|
<div id="packages-content"><div class="loading-state"><div class="loading-spinner"></div></div></div>`;
|
|
53
59
|
await fetchAndRenderPackages();
|
|
54
60
|
}
|
|
61
|
+
/**
|
|
62
|
+
* Fetches the project's package catalog from the extensions endpoint and
|
|
63
|
+
* renders the package cards into the content container, or an empty/error
|
|
64
|
+
* state. Uses a fetch token to discard stale responses that resolve after a
|
|
65
|
+
* project switch or a newer refresh.
|
|
66
|
+
*/
|
|
55
67
|
async function fetchAndRenderPackages() {
|
|
56
68
|
const pid = state.currentProject?.id;
|
|
57
69
|
if (!pid)
|
|
@@ -85,6 +97,14 @@ async function fetchAndRenderPackages() {
|
|
|
85
97
|
target.innerHTML = `<div class="empty-state"><div class="empty-state-text">${escHtml(t('packages.loadError', { error: msg }))}</div></div>`;
|
|
86
98
|
}
|
|
87
99
|
}
|
|
100
|
+
/**
|
|
101
|
+
* Renders one package as a card showing its title, install status and
|
|
102
|
+
* version, a template badge for authoring scaffolds, honest gating notes for
|
|
103
|
+
* required services or credentials, its capabilities, and action buttons
|
|
104
|
+
* appropriate to its installed/active state.
|
|
105
|
+
* @param row - The package catalog row to render.
|
|
106
|
+
* @returns The card markup string.
|
|
107
|
+
*/
|
|
88
108
|
function renderPackageCard(row) {
|
|
89
109
|
const statusChip = row.installed
|
|
90
110
|
? `<span style="font-size:11px;color:var(--text-muted);background:var(--bg-input);padding:2px 8px;border-radius:4px">${escHtml(t('packages.installed'))}${row.version ? ' · ' + escHtml(t('packages.version', { version: row.version })) : ''}</span>`
|
|
@@ -150,6 +170,13 @@ function renderPackageCard(row) {
|
|
|
150
170
|
// Delegate clicks on package action buttons so each card stays simple and the
|
|
151
171
|
// handler resolves the action + name from data attributes, then calls the
|
|
152
172
|
// server-validated extensions route.
|
|
173
|
+
/**
|
|
174
|
+
* Installs a delegated click handler on the given container that routes
|
|
175
|
+
* package action button clicks (install/activate/deactivate/uninstall) to the
|
|
176
|
+
* package action handler, reading the action and package name from data
|
|
177
|
+
* attributes.
|
|
178
|
+
* @param root - The container element capturing the clicks.
|
|
179
|
+
*/
|
|
153
180
|
function wirePackageActions(root) {
|
|
154
181
|
root.addEventListener('click', (ev) => {
|
|
155
182
|
const btn = ev.target.closest('[data-pkg-action]');
|
|
@@ -162,6 +189,16 @@ function wirePackageActions(root) {
|
|
|
162
189
|
void handlePackageAction(name, action, btn);
|
|
163
190
|
});
|
|
164
191
|
}
|
|
192
|
+
/**
|
|
193
|
+
* Performs a package action against the extensions route for the current
|
|
194
|
+
* project. Disables and marks the clicked button while in flight, confirms
|
|
195
|
+
* before uninstalling, picks the HTTP method and URL suffix from the action,
|
|
196
|
+
* toasts the result, and re-renders the package list. Restores the button on
|
|
197
|
+
* failure.
|
|
198
|
+
* @param name - The catalog name of the target package.
|
|
199
|
+
* @param action - One of install, activate, deactivate, or uninstall.
|
|
200
|
+
* @param btn - The button element that triggered the action.
|
|
201
|
+
*/
|
|
165
202
|
async function handlePackageAction(name, action, btn) {
|
|
166
203
|
const pid = state.currentProject?.id;
|
|
167
204
|
if (!pid)
|
|
@@ -198,6 +235,10 @@ async function handlePackageAction(name, action, btn) {
|
|
|
198
235
|
}
|
|
199
236
|
// Wire the delegated action handler once the view container exists.
|
|
200
237
|
let actionsWired = false;
|
|
238
|
+
/**
|
|
239
|
+
* Wires the delegated package action handler onto the #content-packages
|
|
240
|
+
* container exactly once, guarded by the actionsWired flag.
|
|
241
|
+
*/
|
|
201
242
|
function ensureActionsWired() {
|
|
202
243
|
if (actionsWired)
|
|
203
244
|
return;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"packages.js","sourceRoot":"","sources":["packages.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"packages.js","sourceRoot":"","sources":["packages.ts"],"names":[],"mappings":"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"}
|