@webpieces/nx-webpieces-rules 0.4.875 → 0.4.876
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -7
- package/package.json +7 -7
- package/src/executors/generate/executor.js +4 -3
- package/src/executors/generate/executor.js.map +1 -1
- package/src/executors/visualize/executor.d.ts +8 -5
- package/src/executors/visualize/executor.js +10 -7
- package/src/executors/visualize/executor.js.map +1 -1
- package/src/lib/graph-color-modes.d.ts +3 -3
- package/src/lib/graph-color-modes.js +4 -4
- package/src/lib/graph-color-modes.js.map +1 -1
- package/src/lib/graph-impact.d.ts +168 -40
- package/src/lib/graph-impact.js +326 -74
- package/src/lib/graph-impact.js.map +1 -1
- package/src/lib/graph-legend.js +1 -1
- package/src/lib/graph-legend.js.map +1 -1
- package/src/lib/graph-page-shell.d.ts +6 -0
- package/src/lib/graph-page-shell.js +14 -3
- package/src/lib/graph-page-shell.js.map +1 -1
- package/src/lib/graph-page-styles.js +3 -0
- package/src/lib/graph-page-styles.js.map +1 -1
- package/src/lib/graph-visualizer.client.d.ts +24 -3
- package/src/lib/graph-visualizer.client.js +100 -15
- package/src/lib/graph-visualizer.client.js.map +1 -1
|
@@ -6,22 +6,63 @@
|
|
|
6
6
|
* one) and remembered per viewer in localStorage. Storage can be missing or throw (a private window,
|
|
7
7
|
* blocked site data, a file:// page in some browsers), so every access is wrapped and the page works
|
|
8
8
|
* without it.
|
|
9
|
+
*
|
|
10
|
+
* Impact can carry two scans (#1163): "Changed on this branch" (kind `branch`) and "Last commit"
|
|
11
|
+
* (kind `commit`). The ACTIVE one starts as the sidecar's `defaultKind` (or the viewer's remembered
|
|
12
|
+
* choice, when that scan exists and is available) and is what every Impact color, note and Filter
|
|
13
|
+
* set reads.
|
|
9
14
|
*/
|
|
10
15
|
class WpModeState {
|
|
11
16
|
static MODES = ['runtime', 'architecture', 'impact'];
|
|
12
17
|
static NAMES = ['Runtime', 'Architecture', 'Impact'];
|
|
13
|
-
static SUBTITLES = ['where the code can run', 'servers · clients · APIs', 'what
|
|
18
|
+
static SUBTITLES = ['where the code can run', 'servers · clients · APIs', 'what changed'];
|
|
14
19
|
static STORAGE_KEY = 'wp-architecture-graph-mode';
|
|
15
|
-
|
|
20
|
+
static KIND_STORAGE_KEY = 'wp-architecture-graph-impact-kind';
|
|
21
|
+
scans = window.__WP_IMPACT__?.scans ?? [];
|
|
22
|
+
kind = '';
|
|
16
23
|
mode = 'runtime';
|
|
17
24
|
constructor() {
|
|
25
|
+
this.kind = this.initialKind();
|
|
18
26
|
this.mode = this.initial();
|
|
19
27
|
}
|
|
28
|
+
/** The active scan; null when the page has no Impact data. */
|
|
29
|
+
get impact() {
|
|
30
|
+
return this.scans.find((scan) => scan.kind === this.kind) ?? null;
|
|
31
|
+
}
|
|
20
32
|
/** '' when Impact can be shown, else the one line the drawer and the Filter popover say instead. */
|
|
21
33
|
impactReason() {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
34
|
+
const impact = this.impact;
|
|
35
|
+
if (impact === null)
|
|
36
|
+
return 'No impact data here. Run pnpm arch:visualize (nx run architecture:visualize) to compute it — no full regenerate needed.';
|
|
37
|
+
return impact.available ? '' : `Impact unavailable (${impact.label}): ${impact.reason}.`;
|
|
38
|
+
}
|
|
39
|
+
/** Switch the active scan; false (and nothing changes) for a missing or unavailable one. */
|
|
40
|
+
setKind(kind) {
|
|
41
|
+
if (!this.kindAvailable(kind))
|
|
42
|
+
return false;
|
|
43
|
+
this.kind = kind;
|
|
44
|
+
// eslint-disable-next-line @webpieces/no-unmanaged-exceptions -- storage is a per-viewer convenience; a blocked store must not break the page
|
|
45
|
+
try {
|
|
46
|
+
localStorage.setItem(WpModeState.KIND_STORAGE_KEY, kind);
|
|
47
|
+
// webpieces-disable no-any-unknown -- browsers may throw any value from blocked storage
|
|
48
|
+
}
|
|
49
|
+
catch (err) {
|
|
50
|
+
//const error = toError(err);
|
|
51
|
+
void err;
|
|
52
|
+
}
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
kindAvailable(kind) {
|
|
56
|
+
return this.scans.some((scan) => scan.kind === kind && scan.available);
|
|
57
|
+
}
|
|
58
|
+
initialKind() {
|
|
59
|
+
const stored = this.read(WpModeState.KIND_STORAGE_KEY);
|
|
60
|
+
if (stored !== null && this.kindAvailable(stored))
|
|
61
|
+
return stored;
|
|
62
|
+
const preferred = window.__WP_IMPACT__?.defaultKind ?? '';
|
|
63
|
+
if (this.scans.some((scan) => scan.kind === preferred))
|
|
64
|
+
return preferred;
|
|
65
|
+
return this.scans[0]?.kind ?? '';
|
|
25
66
|
}
|
|
26
67
|
available(mode) {
|
|
27
68
|
return WpModeState.MODES.includes(mode) && (mode !== 'impact' || this.impactReason() === '');
|
|
@@ -50,13 +91,14 @@ class WpModeState {
|
|
|
50
91
|
}
|
|
51
92
|
return true;
|
|
52
93
|
}
|
|
53
|
-
/** Which impact shade a box gets. */
|
|
94
|
+
/** Which impact shade a box gets, from the ACTIVE scan. */
|
|
54
95
|
status(id) {
|
|
55
|
-
|
|
96
|
+
const impact = this.impact;
|
|
97
|
+
if (impact?.touched.includes(id))
|
|
56
98
|
return 'touched';
|
|
57
|
-
if (
|
|
99
|
+
if (impact?.affected.includes(id))
|
|
58
100
|
return 'affected';
|
|
59
|
-
if (
|
|
101
|
+
if (impact?.buildInputs.includes(id))
|
|
60
102
|
return 'buildInput';
|
|
61
103
|
return 'untouched';
|
|
62
104
|
}
|
|
@@ -64,15 +106,15 @@ class WpModeState {
|
|
|
64
106
|
const hashed = location.hash.slice(1);
|
|
65
107
|
if (this.available(hashed))
|
|
66
108
|
return hashed;
|
|
67
|
-
const stored = this.
|
|
109
|
+
const stored = this.read(WpModeState.STORAGE_KEY);
|
|
68
110
|
if (stored !== null && this.available(stored))
|
|
69
111
|
return stored;
|
|
70
112
|
return 'runtime';
|
|
71
113
|
}
|
|
72
|
-
|
|
114
|
+
read(key) {
|
|
73
115
|
// eslint-disable-next-line @webpieces/no-unmanaged-exceptions -- storage is a per-viewer convenience; a blocked store reads as "nothing stored"
|
|
74
116
|
try {
|
|
75
|
-
return localStorage.getItem(
|
|
117
|
+
return localStorage.getItem(key);
|
|
76
118
|
// webpieces-disable no-any-unknown -- browsers may throw any value from blocked storage
|
|
77
119
|
}
|
|
78
120
|
catch (err) {
|
|
@@ -299,6 +341,11 @@ class GraphFilterPopover {
|
|
|
299
341
|
isOpen() {
|
|
300
342
|
return this.byId('wp-filter-pop')?.hidden === false;
|
|
301
343
|
}
|
|
344
|
+
/** The active Impact scan changed: an open popover's counts and labels follow it. */
|
|
345
|
+
refresh() {
|
|
346
|
+
if (this.isOpen())
|
|
347
|
+
this.paint();
|
|
348
|
+
}
|
|
302
349
|
open() {
|
|
303
350
|
const pop = this.byId('wp-filter-pop');
|
|
304
351
|
if (pop === null)
|
|
@@ -360,6 +407,7 @@ class GraphDrawer {
|
|
|
360
407
|
wire() {
|
|
361
408
|
this.wireModeMenu();
|
|
362
409
|
this.popover.wire();
|
|
410
|
+
this.wireImpactKinds();
|
|
363
411
|
this.wireLock();
|
|
364
412
|
this.byId('wp-filter-toggle')?.addEventListener('click', () => this.page.toggleFilter());
|
|
365
413
|
this.toggles('wp-collapse', 'wp-shell', true);
|
|
@@ -402,6 +450,33 @@ class GraphDrawer {
|
|
|
402
450
|
});
|
|
403
451
|
});
|
|
404
452
|
}
|
|
453
|
+
/** The "Changed on this branch" / "Last commit" toggle, in the drawer and in the Filter popover. */
|
|
454
|
+
wireImpactKinds() {
|
|
455
|
+
document.querySelectorAll('[data-wp-impact-kind]').forEach((button) => {
|
|
456
|
+
button.addEventListener('click', (ev) => {
|
|
457
|
+
ev.stopPropagation();
|
|
458
|
+
this.page.setImpactKind(button.dataset['wpImpactKind'] ?? '');
|
|
459
|
+
this.popover.refresh();
|
|
460
|
+
});
|
|
461
|
+
});
|
|
462
|
+
}
|
|
463
|
+
/** Shown only when two scans exist; the drawer's copy only while Impact colors the graph. */
|
|
464
|
+
syncImpactKinds(modes) {
|
|
465
|
+
document.querySelectorAll('[data-wp-impact-kinds]').forEach((group) => {
|
|
466
|
+
const inDrawer = group.dataset['wpImpactKinds'] === 'drawer';
|
|
467
|
+
group.hidden = modes.scans.length < 2 || (inDrawer && modes.mode !== 'impact');
|
|
468
|
+
});
|
|
469
|
+
document.querySelectorAll('[data-wp-impact-kind]').forEach((button) => {
|
|
470
|
+
const kind = button.dataset['wpImpactKind'] ?? '';
|
|
471
|
+
button.setAttribute('aria-pressed', String(kind === modes.kind));
|
|
472
|
+
button.disabled = !modes.kindAvailable(kind);
|
|
473
|
+
const scan = modes.scans.find((candidate) => candidate.kind === kind);
|
|
474
|
+
button.title = scan === undefined ? '' : scan.available ? scan.label : scan.reason;
|
|
475
|
+
});
|
|
476
|
+
const legend = this.byId('wp-scope-legend');
|
|
477
|
+
if (legend !== null)
|
|
478
|
+
legend.textContent = modes.impact?.label ?? 'Changes on this branch';
|
|
479
|
+
}
|
|
405
480
|
closeModeMenu(returnFocus) {
|
|
406
481
|
const menu = this.byId('wp-mode-menu');
|
|
407
482
|
if (menu === null || menu.hidden)
|
|
@@ -515,6 +590,7 @@ class GraphDrawer {
|
|
|
515
590
|
document.querySelectorAll('[data-wp-impact-note]').forEach((note) => {
|
|
516
591
|
note.textContent = this.impactNote(modes);
|
|
517
592
|
});
|
|
593
|
+
this.syncImpactKinds(modes);
|
|
518
594
|
const title = this.byId('wp-legend-pop-title');
|
|
519
595
|
if (title !== null)
|
|
520
596
|
title.textContent = `Legend · ${modes.name(modes.mode)}`;
|
|
@@ -573,9 +649,11 @@ class GraphDrawer {
|
|
|
573
649
|
const impact = modes.impact;
|
|
574
650
|
if (impact === null || !impact.available)
|
|
575
651
|
return '';
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
`${impact.
|
|
652
|
+
// An available scan with a note is an EMPTY one, e.g. "Nothing changed on this branch yet".
|
|
653
|
+
if (impact.reason !== '')
|
|
654
|
+
return `${impact.label}: ${impact.reason}.`;
|
|
655
|
+
const stats = `${impact.label}: ${impact.touched.length} touched · ${impact.affected.length} affected · ` +
|
|
656
|
+
`${impact.buildInputs.length} build inputs — nx affected, ${impact.changedFiles} changed files.`;
|
|
579
657
|
const cause = this.globalCause(impact);
|
|
580
658
|
return cause === '' ? stats : `${cause}. ${stats}`;
|
|
581
659
|
}
|
|
@@ -700,6 +778,13 @@ class GraphPage extends WpFilterPage {
|
|
|
700
778
|
this.syncControls();
|
|
701
779
|
this.redraw();
|
|
702
780
|
}
|
|
781
|
+
/** Switch the active Impact scan: Impact recolours and an active change-scope filter re-applies. */
|
|
782
|
+
setImpactKind(kind) {
|
|
783
|
+
if (kind === this.modes.kind || !this.modes.setKind(kind))
|
|
784
|
+
return;
|
|
785
|
+
this.syncControls();
|
|
786
|
+
this.redraw();
|
|
787
|
+
}
|
|
703
788
|
/** The drawer's "Hide unconnected": filter to the locked box's chain, or turn the filter off. */
|
|
704
789
|
toggleFilter() {
|
|
705
790
|
if (this.anchor !== null)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"graph-visualizer.client.js","sourceRoot":"","sources":["../../../../../../packages/tooling/nx-webpieces-rules/src/lib/graph-visualizer.client.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The three color modes (graph-color-modes.ts), the viewer's remembered choice, and Impact's data.\n *\n * The mode is deep-linkable (`#runtime`, `#architecture`, `#impact`, which win over the remembered\n * one) and remembered per viewer in localStorage. Storage can be missing or throw (a private window,\n * blocked site data, a file:// page in some browsers), so every access is wrapped and the page works\n * without it.\n */\nclass WpModeState {\n static readonly MODES = ['runtime', 'architecture', 'impact'];\n static readonly NAMES = ['Runtime', 'Architecture', 'Impact'];\n static readonly SUBTITLES = ['where the code can run', 'servers · clients · APIs', 'what this branch touches'];\n static readonly STORAGE_KEY = 'wp-architecture-graph-mode';\n readonly impact: ImpactJson | null = window.__WP_IMPACT__ ?? null;\n mode = 'runtime';\n\n constructor() {\n this.mode = this.initial();\n }\n\n /** '' when Impact can be shown, else the one line the drawer and the Filter popover say instead. */\n impactReason(): string {\n if (this.impact === null)\n return 'No impact data for this branch. Run pnpm arch:visualize (nx run architecture:visualize) to compute it — no full regenerate needed.';\n return this.impact.available ? '' : `Impact unavailable: ${this.impact.reason}.`;\n }\n\n available(mode: string): boolean {\n return WpModeState.MODES.includes(mode) && (mode !== 'impact' || this.impactReason() === '');\n }\n\n name(mode: string): string {\n return WpModeState.NAMES[WpModeState.MODES.indexOf(mode)] ?? mode;\n }\n\n subtitle(mode: string): string {\n return WpModeState.SUBTITLES[WpModeState.MODES.indexOf(mode)] ?? '';\n }\n\n /** False (and nothing changes) for an unknown or unavailable mode. */\n set(mode: string): boolean {\n if (!this.available(mode)) return false;\n this.mode = mode;\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions -- storage is a per-viewer convenience; a blocked store must not break the page\n try {\n localStorage.setItem(WpModeState.STORAGE_KEY, mode);\n if (location.hash !== `#${mode}`) history.replaceState(null, '', `#${mode}`);\n // webpieces-disable no-any-unknown -- browsers may throw any value from blocked storage\n } catch (err: unknown) {\n //const error = toError(err);\n void err;\n }\n return true;\n }\n\n /** Which impact shade a box gets. */\n status(id: string): 'touched' | 'affected' | 'buildInput' | 'untouched' {\n if (this.impact?.touched.includes(id)) return 'touched';\n if (this.impact?.affected.includes(id)) return 'affected';\n if (this.impact?.buildInputs.includes(id)) return 'buildInput';\n return 'untouched';\n }\n\n private initial(): string {\n const hashed = location.hash.slice(1);\n if (this.available(hashed)) return hashed;\n const stored = this.stored();\n if (stored !== null && this.available(stored)) return stored;\n return 'runtime';\n }\n\n private stored(): string | null {\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions -- storage is a per-viewer convenience; a blocked store reads as \"nothing stored\"\n try {\n return localStorage.getItem(WpModeState.STORAGE_KEY);\n // webpieces-disable no-any-unknown -- browsers may throw any value from blocked storage\n } catch (err: unknown) {\n //const error = toError(err);\n void err;\n return null;\n }\n }\n}\n\n/**\n * One state of the Filter popover: a change scope plus the selected Runtime and Role chips. The page\n * holds the APPLIED one; the popover edits a copy until \"Show N projects\".\n */\nclass WpFilterChoice {\n scope = 'everything';\n readonly runtimes = new Set<string>();\n readonly roles = new Set<string>();\n\n copy(): WpFilterChoice {\n const copy = new WpFilterChoice();\n copy.scope = this.scope;\n for (const runtime of this.runtimes) copy.runtimes.add(runtime);\n for (const role of this.roles) copy.roles.add(role);\n return copy;\n }\n\n /** How many filters are active: the drawer button's badge. */\n count(): number {\n return (this.scope === 'everything' ? 0 : 1) + this.runtimes.size + this.roles.size;\n }\n}\n\n/**\n * The Filter popover's three groups, INTERSECTED: a box stays when it is in the change scope, AND has\n * any selected runtime chip (when one is selected), AND has any selected role chip (likewise).\n */\nclass WpProjectFilter {\n static readonly SCOPE_NAMES = new Map<string, string>([\n ['everything', 'Everything'],\n ['changed', 'Changed'],\n ['dependents', 'Changed + what uses them'],\n ['dependencies', 'Changed + what they use'],\n ['build', 'Whole build of this branch'],\n ]);\n\n constructor(\n private readonly model: RenderModelJson,\n private readonly modes: WpModeState,\n ) {}\n\n /** The node ids a change scope keeps; null for \"everything\" (and whenever Impact is unavailable). */\n scopeSet(scope: string): Set<string> | null {\n const impact = this.modes.impact;\n if (scope === 'everything' || impact === null || this.modes.impactReason() !== '') return null;\n const ids: string[] = [...impact.touched];\n if (scope === 'dependents' || scope === 'build') ids.push(...impact.affected);\n if (scope === 'dependencies') ids.push(...impact.dependencies);\n if (scope === 'build') ids.push(...impact.buildInputs);\n return new Set(ids);\n }\n\n /** How many drawn projects a scope keeps on its own: the count beside each option. */\n scopeCount(scope: string): number {\n const set = this.scopeSet(scope);\n return this.model.nodes.filter((node: RenderNodeJson): boolean => set === null || set.has(node.id)).length;\n }\n\n /** `base` (everything, or the Hide-unconnected chain) narrowed by `choice`. */\n apply(base: Set<string>, choice: WpFilterChoice): Set<string> {\n const scope = this.scopeSet(choice.scope);\n const kept = new Set<string>();\n for (const node of this.model.nodes) {\n if (!base.has(node.id)) continue;\n if (scope !== null && !scope.has(node.id)) continue;\n if (!this.anyOf(choice.runtimes, node.tags?.frameworks ?? [])) continue;\n if (!this.anyOf(choice.roles, node.tags === null ? [] : [node.tags.role])) continue;\n kept.add(node.id);\n }\n return kept;\n }\n\n /** An empty chip group matches every box; otherwise the box must carry one of the chips. */\n private anyOf(selected: Set<string>, carried: string[]): boolean {\n return selected.size === 0 || carried.some((value: string): boolean => selected.has(value));\n }\n}\n\n/** Architecture interactions bind to each new SVG; logical Lock/Filter state belongs to the page. */\nclass GraphHighlighter {\n private readonly nodeByName = new Map<string, SVGGElement>();\n private hovered: string | null = null;\n\n constructor(\n private readonly svg: SVGSVGElement,\n private readonly chain: WpGraphChain,\n private readonly model: RenderModelJson,\n private readonly page: GraphPage,\n ) {}\n\n wire(): void {\n this.svg.querySelectorAll<SVGGElement>('g.node').forEach((g: SVGGElement) => {\n if (g.classList.contains('wp-layout')) return;\n const name = g.querySelector('title')?.textContent;\n if (name !== null && name !== undefined) this.nodeByName.set(name, g);\n });\n this.wireHover();\n this.wireMenu();\n this.relight();\n }\n\n private clear(): void {\n this.svg.classList.remove('wp-dim');\n this.svg.querySelectorAll('.wp-focus, .wp-neighbor, .wp-hl, .wp-locked').forEach((el: Element) => {\n el.classList.remove('wp-focus', 'wp-neighbor', 'wp-hl', 'wp-locked');\n });\n }\n\n relight(): void {\n this.clear();\n const locked = this.page.lockSelection();\n if (locked !== null) this.nodeByName.get(locked)?.classList.add('wp-locked');\n // A filtered-out Lock is suspended, including its otherwise visible relatives.\n const anchors = [locked, this.hovered].filter(\n (name: string | null): name is string => name !== null && this.nodeByName.has(name),\n );\n if (anchors.length === 0) return;\n const lit = new Set<string>();\n for (const name of anchors) {\n this.nodeByName.get(name)?.classList.add('wp-focus');\n for (const id of this.chain.nodes(name)) {\n if (this.nodeByName.has(id)) lit.add(id);\n }\n }\n this.svg.classList.add('wp-dim');\n for (const id of lit) this.nodeByName.get(id)?.classList.add('wp-neighbor');\n for (const edge of this.model.edges) {\n if (lit.has(edge.from) && lit.has(edge.to)) {\n this.svg.querySelector(`[id=\"${edge.id}\"]`)?.classList.add('wp-hl');\n }\n }\n }\n\n private wireHover(): void {\n this.nodeByName.forEach((g: SVGGElement, name: string) => {\n g.addEventListener('mouseenter', () => {\n this.hovered = name;\n this.relight();\n });\n g.addEventListener('mouseleave', () => {\n this.hovered = null;\n this.relight();\n });\n });\n }\n\n private wireMenu(): void {\n const designs = new Map<string, string>();\n for (const link of __DESIGN_LINKS__) designs.set(link.nodeId, link.href);\n WpNodeMenu.wire(this.svg, (name: string): WpNodeMenuItem[] => {\n const items: WpNodeMenuItem[] = [];\n const href = designs.get(name);\n if (href !== undefined)\n items.push(new WpNodeMenuItem('View Design', () => window.open(href, '_blank')));\n const locked = this.page.lockSelection() === name;\n items.push(\n new WpNodeMenuItem(locked ? 'Unlock' : 'Lock', () =>\n this.page.setLock(locked ? null : name),\n ),\n );\n items.push(this.page.filterItem(name));\n return items;\n });\n }\n}\n\n/**\n * The Filter popover: edits a COPY of the page's applied filter, shows what each choice would keep,\n * and hands the copy to the page on \"Show N projects\". Closing it any other way discards the edit.\n */\nclass GraphFilterPopover {\n private draft = new WpFilterChoice();\n\n constructor(private readonly page: GraphPage) {}\n\n wire(): void {\n this.byId('wp-filter-open')?.addEventListener('click', (ev: MouseEvent) => {\n ev.stopPropagation();\n if (this.isOpen()) this.close();\n else this.open();\n });\n this.byId('wp-filter-close')?.addEventListener('click', () => this.close());\n this.byId('wp-filter-clear')?.addEventListener('click', () => {\n this.draft = new WpFilterChoice();\n this.paint();\n });\n this.byId('wp-filter-apply')?.addEventListener('click', () => {\n this.page.applyFilter(this.draft.copy());\n this.close();\n });\n document.querySelectorAll<HTMLInputElement>('input[name=\"wp-scope\"]').forEach((radio: HTMLInputElement) => {\n radio.addEventListener('change', () => {\n if (!radio.checked) return;\n this.draft.scope = radio.value;\n this.paint();\n });\n });\n document.querySelectorAll<HTMLButtonElement>('.wp-chip[data-wp-chip]').forEach((chip: HTMLButtonElement) => {\n chip.addEventListener('click', () => {\n const set = chip.dataset['wpChipGroup'] === 'role' ? this.draft.roles : this.draft.runtimes;\n const value = chip.dataset['wpChip'] ?? '';\n if (set.has(value)) set.delete(value);\n else set.add(value);\n this.paint();\n });\n });\n }\n\n isOpen(): boolean {\n return this.byId('wp-filter-pop')?.hidden === false;\n }\n\n open(): void {\n const pop = this.byId('wp-filter-pop');\n if (pop === null) return;\n this.draft = this.page.appliedFilter().copy();\n this.paint();\n pop.hidden = false;\n this.byId('wp-filter-open')?.setAttribute('aria-expanded', 'true');\n }\n\n close(): void {\n const pop = this.byId('wp-filter-pop');\n if (pop === null || pop.hidden) return;\n pop.hidden = true;\n this.byId('wp-filter-open')?.setAttribute('aria-expanded', 'false');\n }\n\n /** Repaint the controls from the draft: checked scope, pressed chips, counts and the footer. */\n private paint(): void {\n const reason = this.page.scopeReason();\n const group = this.byId('wp-scope-group') as HTMLFieldSetElement | null;\n if (group !== null) group.disabled = reason !== '';\n const reasonEl = this.byId('wp-scope-reason');\n if (reasonEl !== null) {\n reasonEl.textContent = reason;\n reasonEl.hidden = reason === '';\n }\n document.querySelectorAll<HTMLInputElement>('input[name=\"wp-scope\"]').forEach((radio: HTMLInputElement) => {\n radio.checked = radio.value === this.draft.scope;\n });\n document.querySelectorAll<HTMLElement>('[data-wp-scope-count]').forEach((count: HTMLElement) => {\n count.textContent = reason === '' ? String(this.page.scopeCount(count.dataset['wpScopeCount'] ?? '')) : '';\n });\n document.querySelectorAll<HTMLButtonElement>('.wp-chip[data-wp-chip]').forEach((chip: HTMLButtonElement) => {\n const set = chip.dataset['wpChipGroup'] === 'role' ? this.draft.roles : this.draft.runtimes;\n chip.setAttribute('aria-pressed', String(set.has(chip.dataset['wpChip'] ?? '')));\n });\n const apply = this.byId('wp-filter-apply');\n if (apply !== null) {\n const shown = this.page.preview(this.draft);\n apply.textContent = `Show ${shown} project${shown === 1 ? '' : 's'}`;\n }\n }\n\n private byId(id: string): HTMLElement | null {\n return document.getElementById(id);\n }\n}\n\n/**\n * The drawer and its floating panels: every control outside the graph itself. Holds no graph state —\n * each control calls back into the page, and `sync()` repaints the controls from the page's state.\n */\nclass GraphDrawer {\n readonly popover: GraphFilterPopover;\n\n constructor(private readonly page: GraphPage) {\n this.popover = new GraphFilterPopover(page);\n }\n\n wire(): void {\n this.wireModeMenu();\n this.popover.wire();\n this.wireLock();\n this.byId('wp-filter-toggle')?.addEventListener('click', () => this.page.toggleFilter());\n this.toggles('wp-collapse', 'wp-shell', true);\n this.toggles('wp-help-btn', 'wp-help', false);\n this.toggles('wp-help-close', 'wp-help', false);\n this.toggles('wp-legend-pop', 'wp-legend-popout', false);\n this.toggles('wp-legend-close', 'wp-legend-popout', false);\n this.toggles('wp-resp-open', 'wp-resp-panel', false);\n this.toggles('wp-resp-close', 'wp-resp-panel', false);\n this.toggles('wp-snapshot-open', 'wp-snapshot', false);\n window.addEventListener('keydown', (ev: KeyboardEvent) => this.onKey(ev), true);\n window.addEventListener('hashchange', () => this.page.setMode(location.hash.slice(1)));\n document.addEventListener('click', (ev: MouseEvent) => {\n const target = ev.target;\n if (target instanceof Node && this.byId('wp-mode-menu')?.parentElement?.contains(target)) return;\n this.closeModeMenu(false);\n });\n }\n\n /** \"Color by\": the pill trigger opens the menu of three; picking one switches and closes it. */\n private wireModeMenu(): void {\n this.byId('wp-mode-trigger')?.addEventListener('click', (ev: MouseEvent) => {\n ev.stopPropagation();\n const menu = this.byId('wp-mode-menu');\n if (menu === null) return;\n if (!menu.hidden) {\n this.closeModeMenu(false);\n return;\n }\n menu.hidden = false;\n this.byId('wp-mode-trigger')?.setAttribute('aria-expanded', 'true');\n menu.querySelector<HTMLButtonElement>('.wp-mode[aria-checked=\"true\"]')?.focus({ preventScroll: true });\n });\n document.querySelectorAll<HTMLButtonElement>('.wp-mode[data-wp-mode]').forEach((button: HTMLButtonElement) => {\n button.addEventListener('click', (ev: MouseEvent) => {\n ev.stopPropagation();\n this.closeModeMenu(true);\n this.page.setMode(button.dataset['wpMode'] ?? 'runtime');\n });\n });\n }\n\n private closeModeMenu(returnFocus: boolean): void {\n const menu = this.byId('wp-mode-menu');\n if (menu === null || menu.hidden) return;\n menu.hidden = true;\n const trigger = this.byId('wp-mode-trigger');\n trigger?.setAttribute('aria-expanded', 'false');\n if (returnFocus) trigger?.focus({ preventScroll: true });\n }\n\n /** Type-to-search lock: an exact project id (or a unique short name) locks, empty or Esc unlocks. */\n private wireLock(): void {\n const input = this.lockInput();\n if (input === null) return;\n input.addEventListener('input', () => {\n const value = input.value.trim();\n if (value === '') this.page.setLock(null);\n else if (this.page.hasNode(value)) this.page.setLock(value);\n });\n input.addEventListener('change', () => {\n const match = this.page.resolveName(input.value.trim());\n if (match !== null) this.page.setLock(match);\n else input.value = this.page.lockSelection() ?? '';\n });\n input.addEventListener('keydown', (ev: KeyboardEvent) => {\n if (ev.key !== 'Escape') return;\n ev.preventDefault();\n input.value = '';\n this.page.setLock(null);\n input.blur();\n });\n }\n\n /**\n * Page keys, in the CAPTURE phase so the open/closed state of the node menu is read before the\n * menu's own Escape handler closes it: Esc with a menu open only closes the menu. Esc closes an\n * open Color-by menu or Filter popover first, too.\n */\n private onKey(ev: KeyboardEvent): void {\n if (ev.altKey || ev.ctrlKey || ev.metaKey) return;\n if (ev.key === 'Escape' && this.byId('wp-mode-menu')?.hidden === false) {\n this.closeModeMenu(true);\n return;\n }\n if (ev.key === 'Escape' && this.popover.isOpen()) {\n this.popover.close();\n return;\n }\n const target = ev.target;\n if (target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement) return;\n const menuOpen = document.getElementById('wp-node-menu') !== null;\n if (ev.key === '/') {\n ev.preventDefault();\n this.lockInput()?.focus();\n return;\n }\n const index = ['1', '2', '3'].indexOf(ev.key);\n if (index >= 0 && !menuOpen) {\n this.page.setMode(WpModeState.MODES[index]);\n return;\n }\n if (ev.key === 'Escape' && !menuOpen && this.page.lockSelection() !== null) this.page.setLock(null);\n }\n\n /** `button` shows/hides `target`; for the drawer itself it toggles the collapsed class instead. */\n private toggles(buttonId: string, targetId: string, collapse: boolean): void {\n const button = this.byId(buttonId);\n const target = this.byId(targetId);\n if (button === null || target === null) return;\n button.addEventListener('click', (ev: MouseEvent) => {\n ev.stopPropagation();\n let expanded: boolean;\n if (collapse) {\n expanded = !target.classList.toggle('wp-collapsed');\n } else {\n target.hidden = !target.hidden;\n expanded = !target.hidden;\n }\n document.querySelectorAll(`[aria-controls=\"${targetId}\"], #${buttonId}[aria-expanded]`).forEach(\n (el: Element) => el.setAttribute('aria-expanded', String(expanded)),\n );\n });\n }\n\n /** Repaint every control from the page's state. */\n sync(modes: WpModeState, locked: string | null, filtering: boolean, filter: WpFilterChoice): void {\n const reason = modes.impactReason();\n document.querySelectorAll<HTMLButtonElement>('.wp-mode[data-wp-mode]').forEach((button: HTMLButtonElement) => {\n const mode = button.dataset['wpMode'] ?? '';\n button.setAttribute('aria-checked', String(mode === modes.mode));\n button.disabled = !modes.available(mode);\n if (mode === 'impact') button.title = reason === '' ? 'Key 3' : reason;\n });\n this.text('wp-mode-current', modes.name(modes.mode));\n this.text('wp-mode-current-sub', modes.subtitle(modes.mode));\n const reasonEl = this.byId('wp-impact-reason');\n if (reasonEl !== null) {\n reasonEl.textContent = reason;\n reasonEl.hidden = reason === '';\n }\n document.querySelectorAll<HTMLElement>('[data-wp-legend-mode]').forEach((section: HTMLElement) => {\n section.hidden = section.dataset['wpLegendMode'] !== modes.mode;\n });\n document.querySelectorAll<HTMLElement>('[data-wp-impact-note]').forEach((note: HTMLElement) => {\n note.textContent = this.impactNote(modes);\n });\n const title = this.byId('wp-legend-pop-title');\n if (title !== null) title.textContent = `Legend · ${modes.name(modes.mode)}`;\n const input = this.lockInput();\n if (input !== null && document.activeElement !== input) input.value = locked ?? '';\n this.syncFilterToggle(locked, filtering);\n this.syncFilter(filter);\n this.crumb(modes.name(modes.mode), locked);\n }\n\n private syncFilterToggle(locked: string | null, filtering: boolean): void {\n const toggle = this.byId('wp-filter-toggle') as HTMLButtonElement | null;\n if (toggle === null) return;\n toggle.setAttribute('aria-pressed', String(filtering));\n toggle.disabled = !filtering && locked === null;\n toggle.title = toggle.disabled ? 'Lock a project first' : '';\n }\n\n /** The drawer button's count badge, and one removable pill per active filter in the top bar. */\n private syncFilter(filter: WpFilterChoice): void {\n const badge = this.byId('wp-filter-badge');\n if (badge !== null) {\n badge.textContent = String(filter.count());\n badge.hidden = filter.count() === 0;\n }\n const pills = this.byId('wp-filter-pills');\n if (pills === null) return;\n const items: HTMLElement[] = [];\n if (filter.scope !== 'everything')\n items.push(this.pill(WpProjectFilter.SCOPE_NAMES.get(filter.scope) ?? filter.scope, 'scope', filter.scope));\n for (const runtime of filter.runtimes) items.push(this.pill(runtime, 'runtime', runtime));\n for (const role of filter.roles) items.push(this.pill(role, 'role', role));\n pills.replaceChildren(...items);\n }\n\n /** A pill, built with text nodes so no value is parsed as HTML. */\n private pill(label: string, group: string, value: string): HTMLElement {\n const pill = document.createElement('span');\n pill.className = 'wp-pill';\n pill.dataset['wpPill'] = `${group}:${value}`;\n pill.append(label);\n const remove = document.createElement('button');\n remove.type = 'button';\n remove.textContent = '✕';\n remove.setAttribute('aria-label', `Remove filter ${label}`);\n remove.addEventListener('click', (ev: MouseEvent) => {\n ev.stopPropagation();\n this.page.removeFilter(group, value);\n });\n pill.append(remove);\n return pill;\n }\n\n private impactNote(modes: WpModeState): string {\n const impact = modes.impact;\n if (impact === null || !impact.available) return '';\n const stats =\n `${impact.touched.length} touched · ${impact.affected.length} affected · ` +\n `${impact.buildInputs.length} build inputs — nx affected since fork point ${impact.base}, ` +\n `${impact.changedFiles} changed files.`;\n const cause = this.globalCause(impact);\n return cause === '' ? stats : `${cause}. ${stats}`;\n }\n\n /**\n * When files changed but no project owns one, everything nx affected is affected by a\n * workspace-global input (a lockfile, the workspace manifest). That is correct for CI, and\n * baffling on a graph, so the note names the cause.\n */\n private globalCause(impact: ImpactJson): string {\n if (impact.touched.length > 0 || impact.changedFiles === 0) return '';\n const affected = impact.affected.length;\n const who = affected >= this.page.projectCount() ? 'Every project affected' : `${affected} projects affected`;\n const files = impact.globalFiles;\n if (files.length === 0)\n return `${who}: ${impact.changedFiles} changed files that no project owns (workspace-global input)`;\n const named = files.slice(0, 2).join(', ') + (files.length > 2 ? ` and ${files.length - 2} more` : '');\n return `${who}: ${named} changed (workspace-global input${files.length > 1 ? 's' : ''})`;\n }\n\n /** \"Mode: <b>Runtime</b> · Locked: <b>x</b>\", built with text nodes so no name is parsed as HTML. */\n private crumb(mode: string, locked: string | null): void {\n const crumb = this.byId('wp-crumb');\n if (crumb === null) return;\n const bold = (text: string): HTMLElement => {\n const b = document.createElement('b');\n b.textContent = text;\n return b;\n };\n const parts: (string | Node)[] = ['Mode: ', bold(mode)];\n if (locked !== null) parts.push(' · Locked: ', bold(locked));\n crumb.replaceChildren(...parts);\n }\n\n private text(id: string, value: string): void {\n const el = this.byId(id);\n if (el !== null) el.textContent = value;\n }\n\n private lockInput(): HTMLInputElement | null {\n return document.getElementById('wp-lock') as HTMLInputElement | null;\n }\n\n private byId(id: string): HTMLElement | null {\n return document.getElementById(id);\n }\n}\n\nclass GraphPage extends WpFilterPage {\n private highlighter: GraphHighlighter | null = null;\n private readonly modes = new WpModeState();\n private readonly projects = new WpProjectFilter(this.model, this.modes);\n private applied = new WpFilterChoice();\n private readonly drawer = new GraphDrawer(this);\n\n protected override captureBinding(_svg: SVGSVGElement | null): () => void {\n const previous = this.highlighter;\n return (): void => {\n this.highlighter = previous;\n this.filterCards();\n this.syncControls();\n };\n }\n\n protected override wireControls(): void {\n this.drawer.wire();\n this.syncControls();\n }\n\n protected override nodeDot(node: RenderNodeJson): string {\n const modes = node.modes;\n if (modes === null) return node.dot;\n if (this.modes.mode === 'architecture') return modes.architecture;\n if (this.modes.mode === 'impact') return modes[this.modes.status(node.id)];\n return modes.runtime;\n }\n\n protected override usesFullDot(): boolean {\n return this.modes.mode === 'runtime' && this.applied.count() === 0;\n }\n\n protected override narrow(retained: Set<string>): Set<string> {\n return this.projects.apply(retained, this.applied);\n }\n\n /** Filtering keeps every box in its own L-row: an emptied level stays as a thin labeled band. */\n protected override keepsEmptyLevels(): boolean {\n return true;\n }\n\n protected wireSvg(svg: SVGSVGElement): void {\n this.highlighter = new GraphHighlighter(svg, this.chain, this.model, this);\n this.highlighter.wire();\n this.filterCards();\n this.syncControls();\n svg.querySelectorAll<SVGGElement>('g.node').forEach((node: SVGGElement) => {\n if (node.querySelector('title')?.textContent === this.anchor)\n node.classList.add('wp-filter-anchor');\n });\n }\n\n lockSelection(): string | null {\n return this.locked;\n }\n\n hasNode(id: string): boolean {\n return this.model.nodes.some((node: RenderNodeJson): boolean => node.id === id);\n }\n\n projectCount(): number {\n return this.model.nodes.length;\n }\n\n /** An exact id, else the one id whose short name (after any scope) is `text`; null if none or several. */\n resolveName(text: string): string | null {\n if (text === '') return null;\n if (this.hasNode(text)) return text;\n const matches = this.model.nodes.filter(\n (node: RenderNodeJson): boolean => node.id.split('/').pop() === text,\n );\n return matches.length === 1 ? matches[0].id : null;\n }\n\n setLock(name: string | null): void {\n this.locked = name;\n this.highlighter?.relight();\n this.filterCards();\n this.syncControls();\n }\n\n setMode(mode: string): void {\n if (mode === this.modes.mode || !this.modes.set(mode)) return;\n this.syncControls();\n this.redraw();\n }\n\n /** The drawer's \"Hide unconnected\": filter to the locked box's chain, or turn the filter off. */\n toggleFilter(): void {\n if (this.anchor !== null) this.filter(null);\n else if (this.locked !== null) this.filter(this.locked);\n }\n\n appliedFilter(): WpFilterChoice {\n return this.applied;\n }\n\n /** '' when the change-scope group can be used, else Impact's reason (the group is disabled). */\n scopeReason(): string {\n return this.modes.impactReason();\n }\n\n scopeCount(scope: string): number {\n return this.projects.scopeCount(scope);\n }\n\n /** How many boxes `choice` would show, with the current Hide-unconnected chain. */\n preview(choice: WpFilterChoice): number {\n const base =\n this.anchor === null\n ? new Set(this.model.nodes.map((node: RenderNodeJson): string => node.id))\n : this.chain.nodes(this.anchor);\n return this.projects.apply(base, choice).size;\n }\n\n applyFilter(choice: WpFilterChoice): void {\n if (this.scopeReason() !== '') choice.scope = 'everything';\n this.applied = choice;\n this.syncControls();\n this.redraw();\n }\n\n /** A top-bar pill's ✕. */\n removeFilter(group: string, value: string): void {\n const next = this.applied.copy();\n if (group === 'scope') next.scope = 'everything';\n else if (group === 'role') next.roles.delete(value);\n else next.runtimes.delete(value);\n this.applyFilter(next);\n }\n\n private syncControls(): void {\n this.drawer.sync(this.modes, this.locked, this.anchor !== null, this.applied);\n }\n\n private filterCards(): void {\n const lit = this.locked === null ? this.retained : this.chain.nodes(this.locked);\n document.querySelectorAll('.wp-resp-card').forEach((card: Element) => {\n const name = card.getAttribute('data-node');\n card.classList.toggle(\n 'wp-hidden',\n name === null || !this.retained.has(name) || !lit.has(name),\n );\n });\n }\n}\n\nnew GraphPage(__RENDER_MODEL__).render();\n"]}
|
|
1
|
+
{"version":3,"file":"graph-visualizer.client.js","sourceRoot":"","sources":["../../../../../../packages/tooling/nx-webpieces-rules/src/lib/graph-visualizer.client.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The three color modes (graph-color-modes.ts), the viewer's remembered choice, and Impact's data.\n *\n * The mode is deep-linkable (`#runtime`, `#architecture`, `#impact`, which win over the remembered\n * one) and remembered per viewer in localStorage. Storage can be missing or throw (a private window,\n * blocked site data, a file:// page in some browsers), so every access is wrapped and the page works\n * without it.\n *\n * Impact can carry two scans (#1163): \"Changed on this branch\" (kind `branch`) and \"Last commit\"\n * (kind `commit`). The ACTIVE one starts as the sidecar's `defaultKind` (or the viewer's remembered\n * choice, when that scan exists and is available) and is what every Impact color, note and Filter\n * set reads.\n */\nclass WpModeState {\n static readonly MODES = ['runtime', 'architecture', 'impact'];\n static readonly NAMES = ['Runtime', 'Architecture', 'Impact'];\n static readonly SUBTITLES = ['where the code can run', 'servers · clients · APIs', 'what changed'];\n static readonly STORAGE_KEY = 'wp-architecture-graph-mode';\n static readonly KIND_STORAGE_KEY = 'wp-architecture-graph-impact-kind';\n readonly scans: ImpactJson[] = window.__WP_IMPACT__?.scans ?? [];\n kind = '';\n mode = 'runtime';\n\n constructor() {\n this.kind = this.initialKind();\n this.mode = this.initial();\n }\n\n /** The active scan; null when the page has no Impact data. */\n get impact(): ImpactJson | null {\n return this.scans.find((scan: ImpactJson): boolean => scan.kind === this.kind) ?? null;\n }\n\n /** '' when Impact can be shown, else the one line the drawer and the Filter popover say instead. */\n impactReason(): string {\n const impact = this.impact;\n if (impact === null)\n return 'No impact data here. Run pnpm arch:visualize (nx run architecture:visualize) to compute it — no full regenerate needed.';\n return impact.available ? '' : `Impact unavailable (${impact.label}): ${impact.reason}.`;\n }\n\n /** Switch the active scan; false (and nothing changes) for a missing or unavailable one. */\n setKind(kind: string): boolean {\n if (!this.kindAvailable(kind)) return false;\n this.kind = kind;\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions -- storage is a per-viewer convenience; a blocked store must not break the page\n try {\n localStorage.setItem(WpModeState.KIND_STORAGE_KEY, kind);\n // webpieces-disable no-any-unknown -- browsers may throw any value from blocked storage\n } catch (err: unknown) {\n //const error = toError(err);\n void err;\n }\n return true;\n }\n\n kindAvailable(kind: string): boolean {\n return this.scans.some((scan: ImpactJson): boolean => scan.kind === kind && scan.available);\n }\n\n private initialKind(): string {\n const stored = this.read(WpModeState.KIND_STORAGE_KEY);\n if (stored !== null && this.kindAvailable(stored)) return stored;\n const preferred = window.__WP_IMPACT__?.defaultKind ?? '';\n if (this.scans.some((scan: ImpactJson): boolean => scan.kind === preferred)) return preferred;\n return this.scans[0]?.kind ?? '';\n }\n\n available(mode: string): boolean {\n return WpModeState.MODES.includes(mode) && (mode !== 'impact' || this.impactReason() === '');\n }\n\n name(mode: string): string {\n return WpModeState.NAMES[WpModeState.MODES.indexOf(mode)] ?? mode;\n }\n\n subtitle(mode: string): string {\n return WpModeState.SUBTITLES[WpModeState.MODES.indexOf(mode)] ?? '';\n }\n\n /** False (and nothing changes) for an unknown or unavailable mode. */\n set(mode: string): boolean {\n if (!this.available(mode)) return false;\n this.mode = mode;\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions -- storage is a per-viewer convenience; a blocked store must not break the page\n try {\n localStorage.setItem(WpModeState.STORAGE_KEY, mode);\n if (location.hash !== `#${mode}`) history.replaceState(null, '', `#${mode}`);\n // webpieces-disable no-any-unknown -- browsers may throw any value from blocked storage\n } catch (err: unknown) {\n //const error = toError(err);\n void err;\n }\n return true;\n }\n\n /** Which impact shade a box gets, from the ACTIVE scan. */\n status(id: string): 'touched' | 'affected' | 'buildInput' | 'untouched' {\n const impact = this.impact;\n if (impact?.touched.includes(id)) return 'touched';\n if (impact?.affected.includes(id)) return 'affected';\n if (impact?.buildInputs.includes(id)) return 'buildInput';\n return 'untouched';\n }\n\n private initial(): string {\n const hashed = location.hash.slice(1);\n if (this.available(hashed)) return hashed;\n const stored = this.read(WpModeState.STORAGE_KEY);\n if (stored !== null && this.available(stored)) return stored;\n return 'runtime';\n }\n\n private read(key: string): string | null {\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions -- storage is a per-viewer convenience; a blocked store reads as \"nothing stored\"\n try {\n return localStorage.getItem(key);\n // webpieces-disable no-any-unknown -- browsers may throw any value from blocked storage\n } catch (err: unknown) {\n //const error = toError(err);\n void err;\n return null;\n }\n }\n}\n\n/**\n * One state of the Filter popover: a change scope plus the selected Runtime and Role chips. The page\n * holds the APPLIED one; the popover edits a copy until \"Show N projects\".\n */\nclass WpFilterChoice {\n scope = 'everything';\n readonly runtimes = new Set<string>();\n readonly roles = new Set<string>();\n\n copy(): WpFilterChoice {\n const copy = new WpFilterChoice();\n copy.scope = this.scope;\n for (const runtime of this.runtimes) copy.runtimes.add(runtime);\n for (const role of this.roles) copy.roles.add(role);\n return copy;\n }\n\n /** How many filters are active: the drawer button's badge. */\n count(): number {\n return (this.scope === 'everything' ? 0 : 1) + this.runtimes.size + this.roles.size;\n }\n}\n\n/**\n * The Filter popover's three groups, INTERSECTED: a box stays when it is in the change scope, AND has\n * any selected runtime chip (when one is selected), AND has any selected role chip (likewise).\n */\nclass WpProjectFilter {\n static readonly SCOPE_NAMES = new Map<string, string>([\n ['everything', 'Everything'],\n ['changed', 'Changed'],\n ['dependents', 'Changed + what uses them'],\n ['dependencies', 'Changed + what they use'],\n ['build', 'Whole build of this branch'],\n ]);\n\n constructor(\n private readonly model: RenderModelJson,\n private readonly modes: WpModeState,\n ) {}\n\n /** The node ids a change scope keeps; null for \"everything\" (and whenever Impact is unavailable). */\n scopeSet(scope: string): Set<string> | null {\n const impact = this.modes.impact;\n if (scope === 'everything' || impact === null || this.modes.impactReason() !== '') return null;\n const ids: string[] = [...impact.touched];\n if (scope === 'dependents' || scope === 'build') ids.push(...impact.affected);\n if (scope === 'dependencies') ids.push(...impact.dependencies);\n if (scope === 'build') ids.push(...impact.buildInputs);\n return new Set(ids);\n }\n\n /** How many drawn projects a scope keeps on its own: the count beside each option. */\n scopeCount(scope: string): number {\n const set = this.scopeSet(scope);\n return this.model.nodes.filter((node: RenderNodeJson): boolean => set === null || set.has(node.id)).length;\n }\n\n /** `base` (everything, or the Hide-unconnected chain) narrowed by `choice`. */\n apply(base: Set<string>, choice: WpFilterChoice): Set<string> {\n const scope = this.scopeSet(choice.scope);\n const kept = new Set<string>();\n for (const node of this.model.nodes) {\n if (!base.has(node.id)) continue;\n if (scope !== null && !scope.has(node.id)) continue;\n if (!this.anyOf(choice.runtimes, node.tags?.frameworks ?? [])) continue;\n if (!this.anyOf(choice.roles, node.tags === null ? [] : [node.tags.role])) continue;\n kept.add(node.id);\n }\n return kept;\n }\n\n /** An empty chip group matches every box; otherwise the box must carry one of the chips. */\n private anyOf(selected: Set<string>, carried: string[]): boolean {\n return selected.size === 0 || carried.some((value: string): boolean => selected.has(value));\n }\n}\n\n/** Architecture interactions bind to each new SVG; logical Lock/Filter state belongs to the page. */\nclass GraphHighlighter {\n private readonly nodeByName = new Map<string, SVGGElement>();\n private hovered: string | null = null;\n\n constructor(\n private readonly svg: SVGSVGElement,\n private readonly chain: WpGraphChain,\n private readonly model: RenderModelJson,\n private readonly page: GraphPage,\n ) {}\n\n wire(): void {\n this.svg.querySelectorAll<SVGGElement>('g.node').forEach((g: SVGGElement) => {\n if (g.classList.contains('wp-layout')) return;\n const name = g.querySelector('title')?.textContent;\n if (name !== null && name !== undefined) this.nodeByName.set(name, g);\n });\n this.wireHover();\n this.wireMenu();\n this.relight();\n }\n\n private clear(): void {\n this.svg.classList.remove('wp-dim');\n this.svg.querySelectorAll('.wp-focus, .wp-neighbor, .wp-hl, .wp-locked').forEach((el: Element) => {\n el.classList.remove('wp-focus', 'wp-neighbor', 'wp-hl', 'wp-locked');\n });\n }\n\n relight(): void {\n this.clear();\n const locked = this.page.lockSelection();\n if (locked !== null) this.nodeByName.get(locked)?.classList.add('wp-locked');\n // A filtered-out Lock is suspended, including its otherwise visible relatives.\n const anchors = [locked, this.hovered].filter(\n (name: string | null): name is string => name !== null && this.nodeByName.has(name),\n );\n if (anchors.length === 0) return;\n const lit = new Set<string>();\n for (const name of anchors) {\n this.nodeByName.get(name)?.classList.add('wp-focus');\n for (const id of this.chain.nodes(name)) {\n if (this.nodeByName.has(id)) lit.add(id);\n }\n }\n this.svg.classList.add('wp-dim');\n for (const id of lit) this.nodeByName.get(id)?.classList.add('wp-neighbor');\n for (const edge of this.model.edges) {\n if (lit.has(edge.from) && lit.has(edge.to)) {\n this.svg.querySelector(`[id=\"${edge.id}\"]`)?.classList.add('wp-hl');\n }\n }\n }\n\n private wireHover(): void {\n this.nodeByName.forEach((g: SVGGElement, name: string) => {\n g.addEventListener('mouseenter', () => {\n this.hovered = name;\n this.relight();\n });\n g.addEventListener('mouseleave', () => {\n this.hovered = null;\n this.relight();\n });\n });\n }\n\n private wireMenu(): void {\n const designs = new Map<string, string>();\n for (const link of __DESIGN_LINKS__) designs.set(link.nodeId, link.href);\n WpNodeMenu.wire(this.svg, (name: string): WpNodeMenuItem[] => {\n const items: WpNodeMenuItem[] = [];\n const href = designs.get(name);\n if (href !== undefined)\n items.push(new WpNodeMenuItem('View Design', () => window.open(href, '_blank')));\n const locked = this.page.lockSelection() === name;\n items.push(\n new WpNodeMenuItem(locked ? 'Unlock' : 'Lock', () =>\n this.page.setLock(locked ? null : name),\n ),\n );\n items.push(this.page.filterItem(name));\n return items;\n });\n }\n}\n\n/**\n * The Filter popover: edits a COPY of the page's applied filter, shows what each choice would keep,\n * and hands the copy to the page on \"Show N projects\". Closing it any other way discards the edit.\n */\nclass GraphFilterPopover {\n private draft = new WpFilterChoice();\n\n constructor(private readonly page: GraphPage) {}\n\n wire(): void {\n this.byId('wp-filter-open')?.addEventListener('click', (ev: MouseEvent) => {\n ev.stopPropagation();\n if (this.isOpen()) this.close();\n else this.open();\n });\n this.byId('wp-filter-close')?.addEventListener('click', () => this.close());\n this.byId('wp-filter-clear')?.addEventListener('click', () => {\n this.draft = new WpFilterChoice();\n this.paint();\n });\n this.byId('wp-filter-apply')?.addEventListener('click', () => {\n this.page.applyFilter(this.draft.copy());\n this.close();\n });\n document.querySelectorAll<HTMLInputElement>('input[name=\"wp-scope\"]').forEach((radio: HTMLInputElement) => {\n radio.addEventListener('change', () => {\n if (!radio.checked) return;\n this.draft.scope = radio.value;\n this.paint();\n });\n });\n document.querySelectorAll<HTMLButtonElement>('.wp-chip[data-wp-chip]').forEach((chip: HTMLButtonElement) => {\n chip.addEventListener('click', () => {\n const set = chip.dataset['wpChipGroup'] === 'role' ? this.draft.roles : this.draft.runtimes;\n const value = chip.dataset['wpChip'] ?? '';\n if (set.has(value)) set.delete(value);\n else set.add(value);\n this.paint();\n });\n });\n }\n\n isOpen(): boolean {\n return this.byId('wp-filter-pop')?.hidden === false;\n }\n\n /** The active Impact scan changed: an open popover's counts and labels follow it. */\n refresh(): void {\n if (this.isOpen()) this.paint();\n }\n\n open(): void {\n const pop = this.byId('wp-filter-pop');\n if (pop === null) return;\n this.draft = this.page.appliedFilter().copy();\n this.paint();\n pop.hidden = false;\n this.byId('wp-filter-open')?.setAttribute('aria-expanded', 'true');\n }\n\n close(): void {\n const pop = this.byId('wp-filter-pop');\n if (pop === null || pop.hidden) return;\n pop.hidden = true;\n this.byId('wp-filter-open')?.setAttribute('aria-expanded', 'false');\n }\n\n /** Repaint the controls from the draft: checked scope, pressed chips, counts and the footer. */\n private paint(): void {\n const reason = this.page.scopeReason();\n const group = this.byId('wp-scope-group') as HTMLFieldSetElement | null;\n if (group !== null) group.disabled = reason !== '';\n const reasonEl = this.byId('wp-scope-reason');\n if (reasonEl !== null) {\n reasonEl.textContent = reason;\n reasonEl.hidden = reason === '';\n }\n document.querySelectorAll<HTMLInputElement>('input[name=\"wp-scope\"]').forEach((radio: HTMLInputElement) => {\n radio.checked = radio.value === this.draft.scope;\n });\n document.querySelectorAll<HTMLElement>('[data-wp-scope-count]').forEach((count: HTMLElement) => {\n count.textContent = reason === '' ? String(this.page.scopeCount(count.dataset['wpScopeCount'] ?? '')) : '';\n });\n document.querySelectorAll<HTMLButtonElement>('.wp-chip[data-wp-chip]').forEach((chip: HTMLButtonElement) => {\n const set = chip.dataset['wpChipGroup'] === 'role' ? this.draft.roles : this.draft.runtimes;\n chip.setAttribute('aria-pressed', String(set.has(chip.dataset['wpChip'] ?? '')));\n });\n const apply = this.byId('wp-filter-apply');\n if (apply !== null) {\n const shown = this.page.preview(this.draft);\n apply.textContent = `Show ${shown} project${shown === 1 ? '' : 's'}`;\n }\n }\n\n private byId(id: string): HTMLElement | null {\n return document.getElementById(id);\n }\n}\n\n/**\n * The drawer and its floating panels: every control outside the graph itself. Holds no graph state —\n * each control calls back into the page, and `sync()` repaints the controls from the page's state.\n */\nclass GraphDrawer {\n readonly popover: GraphFilterPopover;\n\n constructor(private readonly page: GraphPage) {\n this.popover = new GraphFilterPopover(page);\n }\n\n wire(): void {\n this.wireModeMenu();\n this.popover.wire();\n this.wireImpactKinds();\n this.wireLock();\n this.byId('wp-filter-toggle')?.addEventListener('click', () => this.page.toggleFilter());\n this.toggles('wp-collapse', 'wp-shell', true);\n this.toggles('wp-help-btn', 'wp-help', false);\n this.toggles('wp-help-close', 'wp-help', false);\n this.toggles('wp-legend-pop', 'wp-legend-popout', false);\n this.toggles('wp-legend-close', 'wp-legend-popout', false);\n this.toggles('wp-resp-open', 'wp-resp-panel', false);\n this.toggles('wp-resp-close', 'wp-resp-panel', false);\n this.toggles('wp-snapshot-open', 'wp-snapshot', false);\n window.addEventListener('keydown', (ev: KeyboardEvent) => this.onKey(ev), true);\n window.addEventListener('hashchange', () => this.page.setMode(location.hash.slice(1)));\n document.addEventListener('click', (ev: MouseEvent) => {\n const target = ev.target;\n if (target instanceof Node && this.byId('wp-mode-menu')?.parentElement?.contains(target)) return;\n this.closeModeMenu(false);\n });\n }\n\n /** \"Color by\": the pill trigger opens the menu of three; picking one switches and closes it. */\n private wireModeMenu(): void {\n this.byId('wp-mode-trigger')?.addEventListener('click', (ev: MouseEvent) => {\n ev.stopPropagation();\n const menu = this.byId('wp-mode-menu');\n if (menu === null) return;\n if (!menu.hidden) {\n this.closeModeMenu(false);\n return;\n }\n menu.hidden = false;\n this.byId('wp-mode-trigger')?.setAttribute('aria-expanded', 'true');\n menu.querySelector<HTMLButtonElement>('.wp-mode[aria-checked=\"true\"]')?.focus({ preventScroll: true });\n });\n document.querySelectorAll<HTMLButtonElement>('.wp-mode[data-wp-mode]').forEach((button: HTMLButtonElement) => {\n button.addEventListener('click', (ev: MouseEvent) => {\n ev.stopPropagation();\n this.closeModeMenu(true);\n this.page.setMode(button.dataset['wpMode'] ?? 'runtime');\n });\n });\n }\n\n /** The \"Changed on this branch\" / \"Last commit\" toggle, in the drawer and in the Filter popover. */\n private wireImpactKinds(): void {\n document.querySelectorAll<HTMLButtonElement>('[data-wp-impact-kind]').forEach((button: HTMLButtonElement) => {\n button.addEventListener('click', (ev: MouseEvent) => {\n ev.stopPropagation();\n this.page.setImpactKind(button.dataset['wpImpactKind'] ?? '');\n this.popover.refresh();\n });\n });\n }\n\n /** Shown only when two scans exist; the drawer's copy only while Impact colors the graph. */\n private syncImpactKinds(modes: WpModeState): void {\n document.querySelectorAll<HTMLElement>('[data-wp-impact-kinds]').forEach((group: HTMLElement) => {\n const inDrawer = group.dataset['wpImpactKinds'] === 'drawer';\n group.hidden = modes.scans.length < 2 || (inDrawer && modes.mode !== 'impact');\n });\n document.querySelectorAll<HTMLButtonElement>('[data-wp-impact-kind]').forEach((button: HTMLButtonElement) => {\n const kind = button.dataset['wpImpactKind'] ?? '';\n button.setAttribute('aria-pressed', String(kind === modes.kind));\n button.disabled = !modes.kindAvailable(kind);\n const scan = modes.scans.find((candidate: ImpactJson): boolean => candidate.kind === kind);\n button.title = scan === undefined ? '' : scan.available ? scan.label : scan.reason;\n });\n const legend = this.byId('wp-scope-legend');\n if (legend !== null) legend.textContent = modes.impact?.label ?? 'Changes on this branch';\n }\n\n private closeModeMenu(returnFocus: boolean): void {\n const menu = this.byId('wp-mode-menu');\n if (menu === null || menu.hidden) return;\n menu.hidden = true;\n const trigger = this.byId('wp-mode-trigger');\n trigger?.setAttribute('aria-expanded', 'false');\n if (returnFocus) trigger?.focus({ preventScroll: true });\n }\n\n /** Type-to-search lock: an exact project id (or a unique short name) locks, empty or Esc unlocks. */\n private wireLock(): void {\n const input = this.lockInput();\n if (input === null) return;\n input.addEventListener('input', () => {\n const value = input.value.trim();\n if (value === '') this.page.setLock(null);\n else if (this.page.hasNode(value)) this.page.setLock(value);\n });\n input.addEventListener('change', () => {\n const match = this.page.resolveName(input.value.trim());\n if (match !== null) this.page.setLock(match);\n else input.value = this.page.lockSelection() ?? '';\n });\n input.addEventListener('keydown', (ev: KeyboardEvent) => {\n if (ev.key !== 'Escape') return;\n ev.preventDefault();\n input.value = '';\n this.page.setLock(null);\n input.blur();\n });\n }\n\n /**\n * Page keys, in the CAPTURE phase so the open/closed state of the node menu is read before the\n * menu's own Escape handler closes it: Esc with a menu open only closes the menu. Esc closes an\n * open Color-by menu or Filter popover first, too.\n */\n private onKey(ev: KeyboardEvent): void {\n if (ev.altKey || ev.ctrlKey || ev.metaKey) return;\n if (ev.key === 'Escape' && this.byId('wp-mode-menu')?.hidden === false) {\n this.closeModeMenu(true);\n return;\n }\n if (ev.key === 'Escape' && this.popover.isOpen()) {\n this.popover.close();\n return;\n }\n const target = ev.target;\n if (target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement) return;\n const menuOpen = document.getElementById('wp-node-menu') !== null;\n if (ev.key === '/') {\n ev.preventDefault();\n this.lockInput()?.focus();\n return;\n }\n const index = ['1', '2', '3'].indexOf(ev.key);\n if (index >= 0 && !menuOpen) {\n this.page.setMode(WpModeState.MODES[index]);\n return;\n }\n if (ev.key === 'Escape' && !menuOpen && this.page.lockSelection() !== null) this.page.setLock(null);\n }\n\n /** `button` shows/hides `target`; for the drawer itself it toggles the collapsed class instead. */\n private toggles(buttonId: string, targetId: string, collapse: boolean): void {\n const button = this.byId(buttonId);\n const target = this.byId(targetId);\n if (button === null || target === null) return;\n button.addEventListener('click', (ev: MouseEvent) => {\n ev.stopPropagation();\n let expanded: boolean;\n if (collapse) {\n expanded = !target.classList.toggle('wp-collapsed');\n } else {\n target.hidden = !target.hidden;\n expanded = !target.hidden;\n }\n document.querySelectorAll(`[aria-controls=\"${targetId}\"], #${buttonId}[aria-expanded]`).forEach(\n (el: Element) => el.setAttribute('aria-expanded', String(expanded)),\n );\n });\n }\n\n /** Repaint every control from the page's state. */\n sync(modes: WpModeState, locked: string | null, filtering: boolean, filter: WpFilterChoice): void {\n const reason = modes.impactReason();\n document.querySelectorAll<HTMLButtonElement>('.wp-mode[data-wp-mode]').forEach((button: HTMLButtonElement) => {\n const mode = button.dataset['wpMode'] ?? '';\n button.setAttribute('aria-checked', String(mode === modes.mode));\n button.disabled = !modes.available(mode);\n if (mode === 'impact') button.title = reason === '' ? 'Key 3' : reason;\n });\n this.text('wp-mode-current', modes.name(modes.mode));\n this.text('wp-mode-current-sub', modes.subtitle(modes.mode));\n const reasonEl = this.byId('wp-impact-reason');\n if (reasonEl !== null) {\n reasonEl.textContent = reason;\n reasonEl.hidden = reason === '';\n }\n document.querySelectorAll<HTMLElement>('[data-wp-legend-mode]').forEach((section: HTMLElement) => {\n section.hidden = section.dataset['wpLegendMode'] !== modes.mode;\n });\n document.querySelectorAll<HTMLElement>('[data-wp-impact-note]').forEach((note: HTMLElement) => {\n note.textContent = this.impactNote(modes);\n });\n this.syncImpactKinds(modes);\n const title = this.byId('wp-legend-pop-title');\n if (title !== null) title.textContent = `Legend · ${modes.name(modes.mode)}`;\n const input = this.lockInput();\n if (input !== null && document.activeElement !== input) input.value = locked ?? '';\n this.syncFilterToggle(locked, filtering);\n this.syncFilter(filter);\n this.crumb(modes.name(modes.mode), locked);\n }\n\n private syncFilterToggle(locked: string | null, filtering: boolean): void {\n const toggle = this.byId('wp-filter-toggle') as HTMLButtonElement | null;\n if (toggle === null) return;\n toggle.setAttribute('aria-pressed', String(filtering));\n toggle.disabled = !filtering && locked === null;\n toggle.title = toggle.disabled ? 'Lock a project first' : '';\n }\n\n /** The drawer button's count badge, and one removable pill per active filter in the top bar. */\n private syncFilter(filter: WpFilterChoice): void {\n const badge = this.byId('wp-filter-badge');\n if (badge !== null) {\n badge.textContent = String(filter.count());\n badge.hidden = filter.count() === 0;\n }\n const pills = this.byId('wp-filter-pills');\n if (pills === null) return;\n const items: HTMLElement[] = [];\n if (filter.scope !== 'everything')\n items.push(this.pill(WpProjectFilter.SCOPE_NAMES.get(filter.scope) ?? filter.scope, 'scope', filter.scope));\n for (const runtime of filter.runtimes) items.push(this.pill(runtime, 'runtime', runtime));\n for (const role of filter.roles) items.push(this.pill(role, 'role', role));\n pills.replaceChildren(...items);\n }\n\n /** A pill, built with text nodes so no value is parsed as HTML. */\n private pill(label: string, group: string, value: string): HTMLElement {\n const pill = document.createElement('span');\n pill.className = 'wp-pill';\n pill.dataset['wpPill'] = `${group}:${value}`;\n pill.append(label);\n const remove = document.createElement('button');\n remove.type = 'button';\n remove.textContent = '✕';\n remove.setAttribute('aria-label', `Remove filter ${label}`);\n remove.addEventListener('click', (ev: MouseEvent) => {\n ev.stopPropagation();\n this.page.removeFilter(group, value);\n });\n pill.append(remove);\n return pill;\n }\n\n private impactNote(modes: WpModeState): string {\n const impact = modes.impact;\n if (impact === null || !impact.available) return '';\n // An available scan with a note is an EMPTY one, e.g. \"Nothing changed on this branch yet\".\n if (impact.reason !== '') return `${impact.label}: ${impact.reason}.`;\n const stats =\n `${impact.label}: ${impact.touched.length} touched · ${impact.affected.length} affected · ` +\n `${impact.buildInputs.length} build inputs — nx affected, ${impact.changedFiles} changed files.`;\n const cause = this.globalCause(impact);\n return cause === '' ? stats : `${cause}. ${stats}`;\n }\n\n /**\n * When files changed but no project owns one, everything nx affected is affected by a\n * workspace-global input (a lockfile, the workspace manifest). That is correct for CI, and\n * baffling on a graph, so the note names the cause.\n */\n private globalCause(impact: ImpactJson): string {\n if (impact.touched.length > 0 || impact.changedFiles === 0) return '';\n const affected = impact.affected.length;\n const who = affected >= this.page.projectCount() ? 'Every project affected' : `${affected} projects affected`;\n const files = impact.globalFiles;\n if (files.length === 0)\n return `${who}: ${impact.changedFiles} changed files that no project owns (workspace-global input)`;\n const named = files.slice(0, 2).join(', ') + (files.length > 2 ? ` and ${files.length - 2} more` : '');\n return `${who}: ${named} changed (workspace-global input${files.length > 1 ? 's' : ''})`;\n }\n\n /** \"Mode: <b>Runtime</b> · Locked: <b>x</b>\", built with text nodes so no name is parsed as HTML. */\n private crumb(mode: string, locked: string | null): void {\n const crumb = this.byId('wp-crumb');\n if (crumb === null) return;\n const bold = (text: string): HTMLElement => {\n const b = document.createElement('b');\n b.textContent = text;\n return b;\n };\n const parts: (string | Node)[] = ['Mode: ', bold(mode)];\n if (locked !== null) parts.push(' · Locked: ', bold(locked));\n crumb.replaceChildren(...parts);\n }\n\n private text(id: string, value: string): void {\n const el = this.byId(id);\n if (el !== null) el.textContent = value;\n }\n\n private lockInput(): HTMLInputElement | null {\n return document.getElementById('wp-lock') as HTMLInputElement | null;\n }\n\n private byId(id: string): HTMLElement | null {\n return document.getElementById(id);\n }\n}\n\nclass GraphPage extends WpFilterPage {\n private highlighter: GraphHighlighter | null = null;\n private readonly modes = new WpModeState();\n private readonly projects = new WpProjectFilter(this.model, this.modes);\n private applied = new WpFilterChoice();\n private readonly drawer = new GraphDrawer(this);\n\n protected override captureBinding(_svg: SVGSVGElement | null): () => void {\n const previous = this.highlighter;\n return (): void => {\n this.highlighter = previous;\n this.filterCards();\n this.syncControls();\n };\n }\n\n protected override wireControls(): void {\n this.drawer.wire();\n this.syncControls();\n }\n\n protected override nodeDot(node: RenderNodeJson): string {\n const modes = node.modes;\n if (modes === null) return node.dot;\n if (this.modes.mode === 'architecture') return modes.architecture;\n if (this.modes.mode === 'impact') return modes[this.modes.status(node.id)];\n return modes.runtime;\n }\n\n protected override usesFullDot(): boolean {\n return this.modes.mode === 'runtime' && this.applied.count() === 0;\n }\n\n protected override narrow(retained: Set<string>): Set<string> {\n return this.projects.apply(retained, this.applied);\n }\n\n /** Filtering keeps every box in its own L-row: an emptied level stays as a thin labeled band. */\n protected override keepsEmptyLevels(): boolean {\n return true;\n }\n\n protected wireSvg(svg: SVGSVGElement): void {\n this.highlighter = new GraphHighlighter(svg, this.chain, this.model, this);\n this.highlighter.wire();\n this.filterCards();\n this.syncControls();\n svg.querySelectorAll<SVGGElement>('g.node').forEach((node: SVGGElement) => {\n if (node.querySelector('title')?.textContent === this.anchor)\n node.classList.add('wp-filter-anchor');\n });\n }\n\n lockSelection(): string | null {\n return this.locked;\n }\n\n hasNode(id: string): boolean {\n return this.model.nodes.some((node: RenderNodeJson): boolean => node.id === id);\n }\n\n projectCount(): number {\n return this.model.nodes.length;\n }\n\n /** An exact id, else the one id whose short name (after any scope) is `text`; null if none or several. */\n resolveName(text: string): string | null {\n if (text === '') return null;\n if (this.hasNode(text)) return text;\n const matches = this.model.nodes.filter(\n (node: RenderNodeJson): boolean => node.id.split('/').pop() === text,\n );\n return matches.length === 1 ? matches[0].id : null;\n }\n\n setLock(name: string | null): void {\n this.locked = name;\n this.highlighter?.relight();\n this.filterCards();\n this.syncControls();\n }\n\n setMode(mode: string): void {\n if (mode === this.modes.mode || !this.modes.set(mode)) return;\n this.syncControls();\n this.redraw();\n }\n\n /** Switch the active Impact scan: Impact recolours and an active change-scope filter re-applies. */\n setImpactKind(kind: string): void {\n if (kind === this.modes.kind || !this.modes.setKind(kind)) return;\n this.syncControls();\n this.redraw();\n }\n\n /** The drawer's \"Hide unconnected\": filter to the locked box's chain, or turn the filter off. */\n toggleFilter(): void {\n if (this.anchor !== null) this.filter(null);\n else if (this.locked !== null) this.filter(this.locked);\n }\n\n appliedFilter(): WpFilterChoice {\n return this.applied;\n }\n\n /** '' when the change-scope group can be used, else Impact's reason (the group is disabled). */\n scopeReason(): string {\n return this.modes.impactReason();\n }\n\n scopeCount(scope: string): number {\n return this.projects.scopeCount(scope);\n }\n\n /** How many boxes `choice` would show, with the current Hide-unconnected chain. */\n preview(choice: WpFilterChoice): number {\n const base =\n this.anchor === null\n ? new Set(this.model.nodes.map((node: RenderNodeJson): string => node.id))\n : this.chain.nodes(this.anchor);\n return this.projects.apply(base, choice).size;\n }\n\n applyFilter(choice: WpFilterChoice): void {\n if (this.scopeReason() !== '') choice.scope = 'everything';\n this.applied = choice;\n this.syncControls();\n this.redraw();\n }\n\n /** A top-bar pill's ✕. */\n removeFilter(group: string, value: string): void {\n const next = this.applied.copy();\n if (group === 'scope') next.scope = 'everything';\n else if (group === 'role') next.roles.delete(value);\n else next.runtimes.delete(value);\n this.applyFilter(next);\n }\n\n private syncControls(): void {\n this.drawer.sync(this.modes, this.locked, this.anchor !== null, this.applied);\n }\n\n private filterCards(): void {\n const lit = this.locked === null ? this.retained : this.chain.nodes(this.locked);\n document.querySelectorAll('.wp-resp-card').forEach((card: Element) => {\n const name = card.getAttribute('data-node');\n card.classList.toggle(\n 'wp-hidden',\n name === null || !this.retained.has(name) || !lit.has(name),\n );\n });\n }\n}\n\nnew GraphPage(__RENDER_MODEL__).render();\n"]}
|