@planu/cli 0.55.0 → 0.57.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/config/license-plans.json +2 -0
- package/dist/engine/doc-generator/executive-summary/executive-summary-generator.d.ts +7 -1
- package/dist/engine/doc-generator/executive-summary/executive-summary-generator.d.ts.map +1 -1
- package/dist/engine/doc-generator/executive-summary/executive-summary-generator.js +16 -3
- package/dist/engine/doc-generator/executive-summary/executive-summary-generator.js.map +1 -1
- package/dist/engine/doc-generator/executive-summary/html-template.d.ts +5 -2
- package/dist/engine/doc-generator/executive-summary/html-template.d.ts.map +1 -1
- package/dist/engine/doc-generator/executive-summary/html-template.js +7 -3
- package/dist/engine/doc-generator/executive-summary/html-template.js.map +1 -1
- package/dist/engine/doc-generator/per-spec-report/html-wrapper.d.ts +5 -3
- package/dist/engine/doc-generator/per-spec-report/html-wrapper.d.ts.map +1 -1
- package/dist/engine/doc-generator/per-spec-report/html-wrapper.js +27 -6
- package/dist/engine/doc-generator/per-spec-report/html-wrapper.js.map +1 -1
- package/dist/engine/doc-generator/portal/analytics-page.d.ts +8 -0
- package/dist/engine/doc-generator/portal/analytics-page.d.ts.map +1 -0
- package/dist/engine/doc-generator/portal/analytics-page.js +265 -0
- package/dist/engine/doc-generator/portal/analytics-page.js.map +1 -0
- package/dist/engine/doc-generator/portal/architecture-page.d.ts +6 -0
- package/dist/engine/doc-generator/portal/architecture-page.d.ts.map +1 -0
- package/dist/engine/doc-generator/portal/architecture-page.js +250 -0
- package/dist/engine/doc-generator/portal/architecture-page.js.map +1 -0
- package/dist/engine/doc-generator/portal/changelog-page.d.ts +6 -0
- package/dist/engine/doc-generator/portal/changelog-page.d.ts.map +1 -0
- package/dist/engine/doc-generator/portal/changelog-page.js +204 -0
- package/dist/engine/doc-generator/portal/changelog-page.js.map +1 -0
- package/dist/engine/doc-generator/portal/data-aggregators/accuracy-aggregator.d.ts +11 -0
- package/dist/engine/doc-generator/portal/data-aggregators/accuracy-aggregator.d.ts.map +1 -0
- package/dist/engine/doc-generator/portal/data-aggregators/accuracy-aggregator.js +24 -0
- package/dist/engine/doc-generator/portal/data-aggregators/accuracy-aggregator.js.map +1 -0
- package/dist/engine/doc-generator/portal/data-aggregators/bottleneck-detector.d.ts +9 -0
- package/dist/engine/doc-generator/portal/data-aggregators/bottleneck-detector.d.ts.map +1 -0
- package/dist/engine/doc-generator/portal/data-aggregators/bottleneck-detector.js +31 -0
- package/dist/engine/doc-generator/portal/data-aggregators/bottleneck-detector.js.map +1 -0
- package/dist/engine/doc-generator/portal/data-aggregators/burndown-aggregator.d.ts +10 -0
- package/dist/engine/doc-generator/portal/data-aggregators/burndown-aggregator.d.ts.map +1 -0
- package/dist/engine/doc-generator/portal/data-aggregators/burndown-aggregator.js +77 -0
- package/dist/engine/doc-generator/portal/data-aggregators/burndown-aggregator.js.map +1 -0
- package/dist/engine/doc-generator/portal/data-aggregators/velocity-aggregator.d.ts +9 -0
- package/dist/engine/doc-generator/portal/data-aggregators/velocity-aggregator.d.ts.map +1 -0
- package/dist/engine/doc-generator/portal/data-aggregators/velocity-aggregator.js +31 -0
- package/dist/engine/doc-generator/portal/data-aggregators/velocity-aggregator.js.map +1 -0
- package/dist/engine/doc-generator/portal/decision-page.d.ts +6 -0
- package/dist/engine/doc-generator/portal/decision-page.d.ts.map +1 -0
- package/dist/engine/doc-generator/portal/decision-page.js +169 -0
- package/dist/engine/doc-generator/portal/decision-page.js.map +1 -0
- package/dist/engine/doc-generator/portal/decision-timeline-builder.d.ts +8 -0
- package/dist/engine/doc-generator/portal/decision-timeline-builder.d.ts.map +1 -0
- package/dist/engine/doc-generator/portal/decision-timeline-builder.js +131 -0
- package/dist/engine/doc-generator/portal/decision-timeline-builder.js.map +1 -0
- package/dist/engine/doc-generator/portal/index.d.ts +19 -0
- package/dist/engine/doc-generator/portal/index.d.ts.map +1 -0
- package/dist/engine/doc-generator/portal/index.js +21 -0
- package/dist/engine/doc-generator/portal/index.js.map +1 -0
- package/dist/engine/doc-generator/portal/kanban-view-builder.d.ts +8 -0
- package/dist/engine/doc-generator/portal/kanban-view-builder.d.ts.map +1 -0
- package/dist/engine/doc-generator/portal/kanban-view-builder.js +140 -0
- package/dist/engine/doc-generator/portal/kanban-view-builder.js.map +1 -0
- package/dist/engine/doc-generator/portal/portal-breadcrumbs.d.ts +27 -0
- package/dist/engine/doc-generator/portal/portal-breadcrumbs.d.ts.map +1 -0
- package/dist/engine/doc-generator/portal/portal-breadcrumbs.js +139 -0
- package/dist/engine/doc-generator/portal/portal-breadcrumbs.js.map +1 -0
- package/dist/engine/doc-generator/portal/portal-landing-cards.d.ts +8 -0
- package/dist/engine/doc-generator/portal/portal-landing-cards.d.ts.map +1 -0
- package/dist/engine/doc-generator/portal/portal-landing-cards.js +177 -0
- package/dist/engine/doc-generator/portal/portal-landing-cards.js.map +1 -0
- package/dist/engine/doc-generator/portal/portal-navbar.d.ts +15 -0
- package/dist/engine/doc-generator/portal/portal-navbar.d.ts.map +1 -0
- package/dist/engine/doc-generator/portal/portal-navbar.js +143 -0
- package/dist/engine/doc-generator/portal/portal-navbar.js.map +1 -0
- package/dist/engine/doc-generator/portal/portal-page-detector.d.ts +22 -0
- package/dist/engine/doc-generator/portal/portal-page-detector.d.ts.map +1 -0
- package/dist/engine/doc-generator/portal/portal-page-detector.js +58 -0
- package/dist/engine/doc-generator/portal/portal-page-detector.js.map +1 -0
- package/dist/engine/doc-generator/portal/portal-theme.d.ts +7 -0
- package/dist/engine/doc-generator/portal/portal-theme.d.ts.map +1 -0
- package/dist/engine/doc-generator/portal/portal-theme.js +53 -0
- package/dist/engine/doc-generator/portal/portal-theme.js.map +1 -0
- package/dist/engine/doc-generator/portal/risk-gauge-svg.d.ts +5 -0
- package/dist/engine/doc-generator/portal/risk-gauge-svg.d.ts.map +1 -0
- package/dist/engine/doc-generator/portal/risk-gauge-svg.js +80 -0
- package/dist/engine/doc-generator/portal/risk-gauge-svg.js.map +1 -0
- package/dist/engine/doc-generator/portal/risk-matrix-svg.d.ts +11 -0
- package/dist/engine/doc-generator/portal/risk-matrix-svg.d.ts.map +1 -0
- package/dist/engine/doc-generator/portal/risk-matrix-svg.js +181 -0
- package/dist/engine/doc-generator/portal/risk-matrix-svg.js.map +1 -0
- package/dist/engine/doc-generator/portal/risk-page.d.ts +7 -0
- package/dist/engine/doc-generator/portal/risk-page.d.ts.map +1 -0
- package/dist/engine/doc-generator/portal/risk-page.js +219 -0
- package/dist/engine/doc-generator/portal/risk-page.js.map +1 -0
- package/dist/engine/doc-generator/portal/roadmap-page.d.ts +7 -0
- package/dist/engine/doc-generator/portal/roadmap-page.d.ts.map +1 -0
- package/dist/engine/doc-generator/portal/roadmap-page.js +204 -0
- package/dist/engine/doc-generator/portal/roadmap-page.js.map +1 -0
- package/dist/engine/doc-generator/portal/svg-charts/bar-chart.d.ts +4 -0
- package/dist/engine/doc-generator/portal/svg-charts/bar-chart.d.ts.map +1 -0
- package/dist/engine/doc-generator/portal/svg-charts/bar-chart.js +50 -0
- package/dist/engine/doc-generator/portal/svg-charts/bar-chart.js.map +1 -0
- package/dist/engine/doc-generator/portal/svg-charts/chart-utils.d.ts +16 -0
- package/dist/engine/doc-generator/portal/svg-charts/chart-utils.d.ts.map +1 -0
- package/dist/engine/doc-generator/portal/svg-charts/chart-utils.js +45 -0
- package/dist/engine/doc-generator/portal/svg-charts/chart-utils.js.map +1 -0
- package/dist/engine/doc-generator/portal/svg-charts/line-chart.d.ts +16 -0
- package/dist/engine/doc-generator/portal/svg-charts/line-chart.d.ts.map +1 -0
- package/dist/engine/doc-generator/portal/svg-charts/line-chart.js +159 -0
- package/dist/engine/doc-generator/portal/svg-charts/line-chart.js.map +1 -0
- package/dist/engine/doc-generator/portal/svg-charts/pie-chart.d.ts +7 -0
- package/dist/engine/doc-generator/portal/svg-charts/pie-chart.d.ts.map +1 -0
- package/dist/engine/doc-generator/portal/svg-charts/pie-chart.js +52 -0
- package/dist/engine/doc-generator/portal/svg-charts/pie-chart.js.map +1 -0
- package/dist/engine/doc-generator/proposal/proposal-gantt-builder.d.ts +8 -0
- package/dist/engine/doc-generator/proposal/proposal-gantt-builder.d.ts.map +1 -0
- package/dist/engine/doc-generator/proposal/proposal-gantt-builder.js +126 -0
- package/dist/engine/doc-generator/proposal/proposal-gantt-builder.js.map +1 -0
- package/dist/engine/doc-generator/proposal/proposal-generator.d.ts +10 -0
- package/dist/engine/doc-generator/proposal/proposal-generator.d.ts.map +1 -0
- package/dist/engine/doc-generator/proposal/proposal-generator.js +93 -0
- package/dist/engine/doc-generator/proposal/proposal-generator.js.map +1 -0
- package/dist/engine/doc-generator/proposal/proposal-html-wrapper.d.ts +7 -0
- package/dist/engine/doc-generator/proposal/proposal-html-wrapper.d.ts.map +1 -0
- package/dist/engine/doc-generator/proposal/proposal-html-wrapper.js +31 -0
- package/dist/engine/doc-generator/proposal/proposal-html-wrapper.js.map +1 -0
- package/dist/engine/doc-generator/proposal/proposal-i18n.d.ts +12 -0
- package/dist/engine/doc-generator/proposal/proposal-i18n.d.ts.map +1 -0
- package/dist/engine/doc-generator/proposal/proposal-i18n.js +230 -0
- package/dist/engine/doc-generator/proposal/proposal-i18n.js.map +1 -0
- package/dist/engine/doc-generator/proposal/proposal-kpi-builder.d.ts +8 -0
- package/dist/engine/doc-generator/proposal/proposal-kpi-builder.d.ts.map +1 -0
- package/dist/engine/doc-generator/proposal/proposal-kpi-builder.js +32 -0
- package/dist/engine/doc-generator/proposal/proposal-kpi-builder.js.map +1 -0
- package/dist/engine/doc-generator/proposal/proposal-section-builders-advanced.d.ts +14 -0
- package/dist/engine/doc-generator/proposal/proposal-section-builders-advanced.d.ts.map +1 -0
- package/dist/engine/doc-generator/proposal/proposal-section-builders-advanced.js +248 -0
- package/dist/engine/doc-generator/proposal/proposal-section-builders-advanced.js.map +1 -0
- package/dist/engine/doc-generator/proposal/proposal-section-builders.d.ts +13 -0
- package/dist/engine/doc-generator/proposal/proposal-section-builders.d.ts.map +1 -0
- package/dist/engine/doc-generator/proposal/proposal-section-builders.js +423 -0
- package/dist/engine/doc-generator/proposal/proposal-section-builders.js.map +1 -0
- package/dist/engine/doc-generator/proposal/proposal-themes.d.ts +4 -0
- package/dist/engine/doc-generator/proposal/proposal-themes.d.ts.map +1 -0
- package/dist/engine/doc-generator/proposal/proposal-themes.js +194 -0
- package/dist/engine/doc-generator/proposal/proposal-themes.js.map +1 -0
- package/dist/engine/pdf/browser-finder.d.ts +5 -0
- package/dist/engine/pdf/browser-finder.d.ts.map +1 -0
- package/dist/engine/pdf/browser-finder.js +119 -0
- package/dist/engine/pdf/browser-finder.js.map +1 -0
- package/dist/engine/pdf/html-to-pdf.d.ts +3 -0
- package/dist/engine/pdf/html-to-pdf.d.ts.map +1 -0
- package/dist/engine/pdf/html-to-pdf.js +114 -0
- package/dist/engine/pdf/html-to-pdf.js.map +1 -0
- package/dist/engine/pdf/index.d.ts +6 -0
- package/dist/engine/pdf/index.d.ts.map +1 -0
- package/dist/engine/pdf/index.js +4 -0
- package/dist/engine/pdf/index.js.map +1 -0
- package/dist/engine/pdf/pdf-options.d.ts +6 -0
- package/dist/engine/pdf/pdf-options.d.ts.map +1 -0
- package/dist/engine/pdf/pdf-options.js +34 -0
- package/dist/engine/pdf/pdf-options.js.map +1 -0
- package/dist/engine/spec-summary-html.d.ts.map +1 -1
- package/dist/engine/spec-summary-html.js +17 -5
- package/dist/engine/spec-summary-html.js.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/tools/export-pdf.d.ts +3 -0
- package/dist/tools/export-pdf.d.ts.map +1 -0
- package/dist/tools/export-pdf.js +82 -0
- package/dist/tools/export-pdf.js.map +1 -0
- package/dist/tools/generate-proposal.d.ts +3 -0
- package/dist/tools/generate-proposal.d.ts.map +1 -0
- package/dist/tools/generate-proposal.js +166 -0
- package/dist/tools/generate-proposal.js.map +1 -0
- package/dist/types/docs.d.ts +41 -0
- package/dist/types/docs.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +1 -0
- package/dist/types/index.js.map +1 -1
- package/dist/types/pdf.d.ts +42 -0
- package/dist/types/pdf.d.ts.map +1 -0
- package/dist/types/pdf.js +3 -0
- package/dist/types/pdf.js.map +1 -0
- package/dist/types/portal.d.ts +128 -0
- package/dist/types/portal.d.ts.map +1 -0
- package/dist/types/portal.js +3 -0
- package/dist/types/portal.js.map +1 -0
- package/dist/types/proposal.d.ts +57 -0
- package/dist/types/proposal.d.ts.map +1 -0
- package/dist/types/proposal.js +2 -0
- package/dist/types/proposal.js.map +1 -0
- package/package.json +1 -1
- package/src/config/license-plans.json +2 -0
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/** All portal pages in display order */
|
|
2
|
+
export const NAV_ITEMS = [
|
|
3
|
+
{ key: 'dashboard', label: 'Dashboard', filename: 'index.html', icon: '📋' },
|
|
4
|
+
{ key: 'proposal', label: 'Proposal', filename: 'proposal.html', icon: '📝' },
|
|
5
|
+
{
|
|
6
|
+
key: 'executive-summary',
|
|
7
|
+
label: 'Executive Summary',
|
|
8
|
+
filename: 'executive-summary.html',
|
|
9
|
+
icon: '📊',
|
|
10
|
+
},
|
|
11
|
+
{ key: 'roadmap', label: 'Roadmap', filename: 'roadmap.html', icon: '🗺️' },
|
|
12
|
+
{ key: 'analytics', label: 'Analytics', filename: 'analytics.html', icon: '📈' },
|
|
13
|
+
{ key: 'risks', label: 'Risks', filename: 'risks.html', icon: '⚠️' },
|
|
14
|
+
{ key: 'decisions', label: 'Decisions', filename: 'decisions.html', icon: '🏛️' },
|
|
15
|
+
{ key: 'architecture', label: 'Architecture', filename: 'architecture.html', icon: '🔧' },
|
|
16
|
+
{ key: 'changelog', label: 'Changelog', filename: 'changelog.html', icon: '📝' },
|
|
17
|
+
];
|
|
18
|
+
const NAVBAR_CSS = `
|
|
19
|
+
.planu-nav {
|
|
20
|
+
background: var(--planu-primary, #1a1a2e);
|
|
21
|
+
color: white;
|
|
22
|
+
display: flex;
|
|
23
|
+
align-items: center;
|
|
24
|
+
gap: 0;
|
|
25
|
+
padding: 0 16px;
|
|
26
|
+
height: 52px;
|
|
27
|
+
position: relative;
|
|
28
|
+
margin-bottom: 24px;
|
|
29
|
+
border-radius: 8px;
|
|
30
|
+
font-size: 0.85rem;
|
|
31
|
+
}
|
|
32
|
+
.planu-nav-brand {
|
|
33
|
+
font-weight: 700;
|
|
34
|
+
font-size: 1rem;
|
|
35
|
+
color: white;
|
|
36
|
+
text-decoration: none;
|
|
37
|
+
white-space: nowrap;
|
|
38
|
+
margin-right: 16px;
|
|
39
|
+
flex-shrink: 0;
|
|
40
|
+
}
|
|
41
|
+
.planu-nav-links {
|
|
42
|
+
display: flex;
|
|
43
|
+
align-items: center;
|
|
44
|
+
gap: 2px;
|
|
45
|
+
flex: 1;
|
|
46
|
+
overflow: hidden;
|
|
47
|
+
}
|
|
48
|
+
.planu-nav-link {
|
|
49
|
+
color: rgba(255,255,255,0.75);
|
|
50
|
+
text-decoration: none;
|
|
51
|
+
padding: 6px 10px;
|
|
52
|
+
border-radius: 6px;
|
|
53
|
+
white-space: nowrap;
|
|
54
|
+
transition: background 0.15s, color 0.15s;
|
|
55
|
+
font-size: 0.82rem;
|
|
56
|
+
}
|
|
57
|
+
.planu-nav-link:hover {
|
|
58
|
+
background: rgba(255,255,255,0.1);
|
|
59
|
+
color: white;
|
|
60
|
+
}
|
|
61
|
+
.planu-nav-link.active {
|
|
62
|
+
background: var(--planu-accent, #e94560);
|
|
63
|
+
color: white;
|
|
64
|
+
font-weight: 600;
|
|
65
|
+
}
|
|
66
|
+
.planu-nav-link.unavailable {
|
|
67
|
+
color: rgba(255,255,255,0.3);
|
|
68
|
+
cursor: default;
|
|
69
|
+
pointer-events: none;
|
|
70
|
+
}
|
|
71
|
+
.planu-nav-toggle { display: none; }
|
|
72
|
+
.planu-nav-hamburger {
|
|
73
|
+
display: none;
|
|
74
|
+
background: none;
|
|
75
|
+
border: 1px solid rgba(255,255,255,0.3);
|
|
76
|
+
color: white;
|
|
77
|
+
border-radius: 6px;
|
|
78
|
+
padding: 4px 10px;
|
|
79
|
+
cursor: pointer;
|
|
80
|
+
font-size: 1.2rem;
|
|
81
|
+
line-height: 1;
|
|
82
|
+
margin-left: auto;
|
|
83
|
+
}
|
|
84
|
+
@media (max-width: 768px) {
|
|
85
|
+
.planu-nav { flex-wrap: wrap; height: auto; padding: 8px 16px; }
|
|
86
|
+
.planu-nav-hamburger { display: block; }
|
|
87
|
+
.planu-nav-links {
|
|
88
|
+
display: none;
|
|
89
|
+
flex-direction: column;
|
|
90
|
+
align-items: flex-start;
|
|
91
|
+
width: 100%;
|
|
92
|
+
padding: 8px 0;
|
|
93
|
+
gap: 4px;
|
|
94
|
+
}
|
|
95
|
+
.planu-nav-toggle:checked ~ .planu-nav-links { display: flex; }
|
|
96
|
+
.planu-nav-link { width: 100%; padding: 8px 12px; }
|
|
97
|
+
}
|
|
98
|
+
@media print { .planu-nav { display: none !important; } }`;
|
|
99
|
+
function getNavbarCss() {
|
|
100
|
+
return NAVBAR_CSS;
|
|
101
|
+
}
|
|
102
|
+
function escapeHtml(str) {
|
|
103
|
+
return str
|
|
104
|
+
.replace(/&/g, '&')
|
|
105
|
+
.replace(/</g, '<')
|
|
106
|
+
.replace(/>/g, '>')
|
|
107
|
+
.replace(/"/g, '"');
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Build a horizontal portal navbar.
|
|
111
|
+
*
|
|
112
|
+
* @param activePage - Key of the current page (e.g. 'dashboard', 'executive-summary').
|
|
113
|
+
* @param basePath - Relative path prefix to reach planu/ root (e.g. '' for index.html,
|
|
114
|
+
* '../../' for per-spec reports inside planu/specs/SPEC-XXX/).
|
|
115
|
+
* @param availablePages - List of page keys that exist on disk. Pages not in this list
|
|
116
|
+
* are rendered greyed-out and non-clickable. Defaults to all pages.
|
|
117
|
+
*/
|
|
118
|
+
export function buildNavbar(activePage, basePath, availablePages) {
|
|
119
|
+
const available = availablePages ?? NAV_ITEMS.map((n) => n.key);
|
|
120
|
+
// Dashboard is always available — it's the index.html that calls this function
|
|
121
|
+
const alwaysAvailable = new Set(['dashboard', ...available]);
|
|
122
|
+
const navId = `planu-nav-toggle-${Math.random().toString(36).slice(2, 8)}`;
|
|
123
|
+
const links = NAV_ITEMS.map((item) => {
|
|
124
|
+
const isActive = item.key === activePage;
|
|
125
|
+
const isAvailable = alwaysAvailable.has(item.key);
|
|
126
|
+
if (!isAvailable) {
|
|
127
|
+
return `<span class="planu-nav-link unavailable" title="${escapeHtml(item.label)} (not generated yet)">${item.icon} ${escapeHtml(item.label)}</span>`;
|
|
128
|
+
}
|
|
129
|
+
const href = `${basePath}${escapeHtml(item.filename)}`;
|
|
130
|
+
const activeClass = isActive ? ' active' : '';
|
|
131
|
+
return `<a href="${href}" class="planu-nav-link${activeClass}">${item.icon} ${escapeHtml(item.label)}</a>`;
|
|
132
|
+
}).join('\n ');
|
|
133
|
+
return `<style>${getNavbarCss()}</style>
|
|
134
|
+
<nav class="planu-nav" role="navigation" aria-label="Planu portal">
|
|
135
|
+
<a href="${basePath}index.html" class="planu-nav-brand">📋 Planu</a>
|
|
136
|
+
<input type="checkbox" class="planu-nav-toggle" id="${escapeHtml(navId)}" hidden>
|
|
137
|
+
<label for="${escapeHtml(navId)}" class="planu-nav-hamburger" aria-label="Toggle navigation">☰</label>
|
|
138
|
+
<div class="planu-nav-links">
|
|
139
|
+
${links}
|
|
140
|
+
</div>
|
|
141
|
+
</nav>`;
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=portal-navbar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"portal-navbar.js","sourceRoot":"","sources":["../../../../src/engine/doc-generator/portal/portal-navbar.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* All detectable portal page keys mapped to their filenames within planu/.
|
|
3
|
+
* Order matches the navbar display order.
|
|
4
|
+
*/
|
|
5
|
+
export declare const DETECTABLE_PAGES: Record<string, string>;
|
|
6
|
+
/**
|
|
7
|
+
* Detect which portal pages currently exist inside planu/.
|
|
8
|
+
* Returns an array of page keys (e.g. ['proposal', 'executive-summary']).
|
|
9
|
+
* The 'dashboard' (index.html) key is intentionally excluded — callers
|
|
10
|
+
* can always assume the dashboard exists.
|
|
11
|
+
*
|
|
12
|
+
* @param portalPath - Absolute path to the planu/ directory.
|
|
13
|
+
*/
|
|
14
|
+
export declare function detectAvailablePages(portalPath: string): Promise<string[]>;
|
|
15
|
+
/**
|
|
16
|
+
* Synchronous variant that accepts a pre-resolved set of existing filenames.
|
|
17
|
+
* Useful in tests or when the filesystem check has already been performed.
|
|
18
|
+
*
|
|
19
|
+
* @param existingFilenames - Set or array of filenames that exist (e.g. ['proposal.html']).
|
|
20
|
+
*/
|
|
21
|
+
export declare function detectAvailablePagesSync(existingFilenames: string[]): string[];
|
|
22
|
+
//# sourceMappingURL=portal-page-detector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"portal-page-detector.d.ts","sourceRoot":"","sources":["../../../../src/engine/doc-generator/portal/portal-page-detector.ts"],"names":[],"mappings":"AAKA;;;GAGG;AACH,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CASnD,CAAC;AAcF;;;;;;;GAOG;AACH,wBAAsB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAUhF;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,iBAAiB,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAK9E"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// Planu — Detects which portal pages exist on disk in planu/
|
|
2
|
+
import { access } from 'node:fs/promises';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
/**
|
|
5
|
+
* All detectable portal page keys mapped to their filenames within planu/.
|
|
6
|
+
* Order matches the navbar display order.
|
|
7
|
+
*/
|
|
8
|
+
export const DETECTABLE_PAGES = {
|
|
9
|
+
proposal: 'proposal.html',
|
|
10
|
+
'executive-summary': 'executive-summary.html',
|
|
11
|
+
roadmap: 'roadmap.html',
|
|
12
|
+
analytics: 'analytics.html',
|
|
13
|
+
risks: 'risks.html',
|
|
14
|
+
decisions: 'decisions.html',
|
|
15
|
+
architecture: 'architecture.html',
|
|
16
|
+
changelog: 'changelog.html',
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Check whether a single file exists on disk (non-throwing).
|
|
20
|
+
*/
|
|
21
|
+
async function fileExists(filePath) {
|
|
22
|
+
try {
|
|
23
|
+
await access(filePath);
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Detect which portal pages currently exist inside planu/.
|
|
32
|
+
* Returns an array of page keys (e.g. ['proposal', 'executive-summary']).
|
|
33
|
+
* The 'dashboard' (index.html) key is intentionally excluded — callers
|
|
34
|
+
* can always assume the dashboard exists.
|
|
35
|
+
*
|
|
36
|
+
* @param portalPath - Absolute path to the planu/ directory.
|
|
37
|
+
*/
|
|
38
|
+
export async function detectAvailablePages(portalPath) {
|
|
39
|
+
const checks = Object.entries(DETECTABLE_PAGES).map(async ([key, filename]) => {
|
|
40
|
+
const exists = await fileExists(join(portalPath, filename));
|
|
41
|
+
return exists ? key : null;
|
|
42
|
+
});
|
|
43
|
+
const results = await Promise.all(checks);
|
|
44
|
+
return results.filter((key) => key !== null);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Synchronous variant that accepts a pre-resolved set of existing filenames.
|
|
48
|
+
* Useful in tests or when the filesystem check has already been performed.
|
|
49
|
+
*
|
|
50
|
+
* @param existingFilenames - Set or array of filenames that exist (e.g. ['proposal.html']).
|
|
51
|
+
*/
|
|
52
|
+
export function detectAvailablePagesSync(existingFilenames) {
|
|
53
|
+
const filenameSet = new Set(existingFilenames);
|
|
54
|
+
return Object.entries(DETECTABLE_PAGES)
|
|
55
|
+
.filter(([, filename]) => filenameSet.has(filename))
|
|
56
|
+
.map(([key]) => key);
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=portal-page-detector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"portal-page-detector.js","sourceRoot":"","sources":["../../../../src/engine/doc-generator/portal/portal-page-detector.ts"],"names":[],"mappings":"AAAA,6DAA6D;AAE7D,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC;;;GAGG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAA2B;IACtD,QAAQ,EAAE,eAAe;IACzB,mBAAmB,EAAE,wBAAwB;IAC7C,OAAO,EAAE,cAAc;IACvB,SAAS,EAAE,gBAAgB;IAC3B,KAAK,EAAE,YAAY;IACnB,SAAS,EAAE,gBAAgB;IAC3B,YAAY,EAAE,mBAAmB;IACjC,SAAS,EAAE,gBAAgB;CAC5B,CAAC;AAEF;;GAEG;AACH,KAAK,UAAU,UAAU,CAAC,QAAgB;IACxC,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC;QACvB,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,UAAkB;IAC3D,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC,GAAG,CACjD,KAAK,EAAE,CAAC,GAAG,EAAE,QAAQ,CAAC,EAA0B,EAAE;QAChD,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC,CAAC;QAC5D,OAAO,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;IAC7B,CAAC,CACF,CAAC;IAEF,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAC1C,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,EAAiB,EAAE,CAAC,GAAG,KAAK,IAAI,CAAC,CAAC;AAC9D,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,wBAAwB,CAAC,iBAA2B;IAClE,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,iBAAiB,CAAC,CAAC;IAC/C,OAAO,MAAM,CAAC,OAAO,CAAC,gBAAgB,CAAC;SACpC,MAAM,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;SACnD,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC;AACzB,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns the shared CSS custom properties and base styles used across
|
|
3
|
+
* all Planu portal pages (index.html, executive-summary, per-spec reports).
|
|
4
|
+
* Inject inside a <style> tag before any page-specific CSS.
|
|
5
|
+
*/
|
|
6
|
+
export declare function getPortalThemeCSS(): string;
|
|
7
|
+
//# sourceMappingURL=portal-theme.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"portal-theme.d.ts","sourceRoot":"","sources":["../../../../src/engine/doc-generator/portal/portal-theme.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CA6C1C"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// Planu — Shared CSS variables + base styles for the portal theme system
|
|
2
|
+
/**
|
|
3
|
+
* Returns the shared CSS custom properties and base styles used across
|
|
4
|
+
* all Planu portal pages (index.html, executive-summary, per-spec reports).
|
|
5
|
+
* Inject inside a <style> tag before any page-specific CSS.
|
|
6
|
+
*/
|
|
7
|
+
export function getPortalThemeCSS() {
|
|
8
|
+
return `
|
|
9
|
+
:root {
|
|
10
|
+
--planu-primary: #1a1a2e;
|
|
11
|
+
--planu-secondary: #0f3460;
|
|
12
|
+
--planu-accent: #e94560;
|
|
13
|
+
--planu-bg: #f8f9fa;
|
|
14
|
+
--planu-text: #2d3436;
|
|
15
|
+
--planu-card-bg: white;
|
|
16
|
+
--planu-border: #e9ecef;
|
|
17
|
+
--planu-success: #27ae60;
|
|
18
|
+
--planu-warning: #f39c12;
|
|
19
|
+
--planu-danger: #e74c3c;
|
|
20
|
+
--planu-info: #3498db;
|
|
21
|
+
--planu-nav-height: 52px;
|
|
22
|
+
}
|
|
23
|
+
@media print {
|
|
24
|
+
:root {
|
|
25
|
+
--planu-bg: white;
|
|
26
|
+
--planu-text: black;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
.planu-badge {
|
|
30
|
+
display: inline-block;
|
|
31
|
+
padding: 2px 8px;
|
|
32
|
+
border-radius: 99px;
|
|
33
|
+
font-size: 0.72em;
|
|
34
|
+
font-weight: 600;
|
|
35
|
+
white-space: nowrap;
|
|
36
|
+
}
|
|
37
|
+
.planu-badge-success { background: #d1fae5; color: #065f46; }
|
|
38
|
+
.planu-badge-warning { background: #fef3c7; color: #92400e; }
|
|
39
|
+
.planu-badge-danger { background: #fee2e2; color: #991b1b; }
|
|
40
|
+
.planu-badge-info { background: #dbeafe; color: #1d4ed8; }
|
|
41
|
+
.planu-badge-muted { background: #f3f4f6; color: #6b7280; }
|
|
42
|
+
.planu-card {
|
|
43
|
+
background: var(--planu-card-bg);
|
|
44
|
+
border: 1px solid var(--planu-border);
|
|
45
|
+
border-radius: 10px;
|
|
46
|
+
padding: 18px;
|
|
47
|
+
box-shadow: 0 1px 3px rgba(0,0,0,0.06);
|
|
48
|
+
}
|
|
49
|
+
@media print {
|
|
50
|
+
.planu-nav, .planu-breadcrumbs, .planu-spec-nav { display: none !important; }
|
|
51
|
+
}`;
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=portal-theme.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"portal-theme.js","sourceRoot":"","sources":["../../../../src/engine/doc-generator/portal/portal-theme.ts"],"names":[],"mappings":"AAAA,yEAAyE;AAEzE;;;;GAIG;AACH,MAAM,UAAU,iBAAiB;IAC/B,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IA2CL,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"risk-gauge-svg.d.ts","sourceRoot":"","sources":["../../../../src/engine/doc-generator/portal/risk-gauge-svg.ts"],"names":[],"mappings":"AAkDA;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAwCvD"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
// Planu — Risk Gauge semicircle SVG (SPEC-143)
|
|
2
|
+
const W = 200;
|
|
3
|
+
const H = 120;
|
|
4
|
+
const CX = W / 2;
|
|
5
|
+
const CY = 105;
|
|
6
|
+
const R = 80;
|
|
7
|
+
/**
|
|
8
|
+
* Convert polar angle (in degrees, 0 = right) to SVG x,y on the gauge arc.
|
|
9
|
+
* Gauge goes from 180° (left) to 0° (right), i.e. the top semicircle.
|
|
10
|
+
*/
|
|
11
|
+
function polarToXY(angleDeg, radius) {
|
|
12
|
+
const rad = (angleDeg * Math.PI) / 180;
|
|
13
|
+
return {
|
|
14
|
+
x: CX + radius * Math.cos(rad),
|
|
15
|
+
y: CY - radius * Math.sin(rad),
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
function scoreToAngle(score) {
|
|
19
|
+
// Map 0→180°, 100→0° (left to right)
|
|
20
|
+
const clamped = Math.max(0, Math.min(100, score));
|
|
21
|
+
return 180 - clamped * 1.8;
|
|
22
|
+
}
|
|
23
|
+
function gaugeColor(score) {
|
|
24
|
+
if (score <= 30) {
|
|
25
|
+
return '#22c55e';
|
|
26
|
+
} // green
|
|
27
|
+
if (score <= 60) {
|
|
28
|
+
return '#f59e0b';
|
|
29
|
+
} // yellow
|
|
30
|
+
return '#ef4444'; // red
|
|
31
|
+
}
|
|
32
|
+
function buildArcPath(startAngle, endAngle, r, _strokeWidth) {
|
|
33
|
+
const start = polarToXY(startAngle, r);
|
|
34
|
+
const end = polarToXY(endAngle, r);
|
|
35
|
+
const largeArc = Math.abs(endAngle - startAngle) > 180 ? 1 : 0;
|
|
36
|
+
// Sweep: going from high angle to low angle means clockwise in SVG
|
|
37
|
+
const sweep = endAngle < startAngle ? 1 : 0;
|
|
38
|
+
return `M ${start.x.toFixed(1)} ${start.y.toFixed(1)} A ${r} ${r} 0 ${largeArc} ${sweep} ${end.x.toFixed(1)} ${end.y.toFixed(1)}`;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Build a semicircle gauge SVG for a risk score (0-100).
|
|
42
|
+
*/
|
|
43
|
+
export function buildRiskGaugeSvg(score) {
|
|
44
|
+
const clamped = Math.max(0, Math.min(100, score));
|
|
45
|
+
const color = gaugeColor(clamped);
|
|
46
|
+
const needleAngle = scoreToAngle(clamped);
|
|
47
|
+
const needle = polarToXY(needleAngle, R - 10);
|
|
48
|
+
// Background arc (grey, full 180°)
|
|
49
|
+
const bgPath = buildArcPath(180, 0, R, 14);
|
|
50
|
+
// Foreground arc (colored, proportional)
|
|
51
|
+
const fgPath = buildArcPath(180, needleAngle, R, 14);
|
|
52
|
+
// Zone arcs (thin overlay for green/yellow/red zones)
|
|
53
|
+
const greenEnd = scoreToAngle(30);
|
|
54
|
+
const yellowEnd = scoreToAngle(60);
|
|
55
|
+
const greenArc = buildArcPath(180, greenEnd, R, 14);
|
|
56
|
+
const yellowArc = buildArcPath(greenEnd, yellowEnd, R, 14);
|
|
57
|
+
const redArc = buildArcPath(yellowEnd, 0, R, 14);
|
|
58
|
+
return `<svg viewBox="0 0 ${W} ${H}" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Risk Score Gauge: ${clamped}">
|
|
59
|
+
<!-- Zone backgrounds -->
|
|
60
|
+
<path d="${greenArc}" fill="none" stroke="#d1fae5" stroke-width="14" stroke-linecap="butt"/>
|
|
61
|
+
<path d="${yellowArc}" fill="none" stroke="#fef3c7" stroke-width="14" stroke-linecap="butt"/>
|
|
62
|
+
<path d="${redArc}" fill="none" stroke="#fee2e2" stroke-width="14" stroke-linecap="butt"/>
|
|
63
|
+
<!-- Progress arc -->
|
|
64
|
+
<path d="${bgPath}" fill="none" stroke="#e5e7eb" stroke-width="10" stroke-linecap="round"/>
|
|
65
|
+
<path d="${fgPath}" fill="none" stroke="${color}" stroke-width="10" stroke-linecap="round"/>
|
|
66
|
+
<!-- Needle dot -->
|
|
67
|
+
<circle cx="${needle.x.toFixed(1)}" cy="${needle.y.toFixed(1)}" r="5" fill="${color}" stroke="white" stroke-width="2"/>
|
|
68
|
+
<!-- Center dot -->
|
|
69
|
+
<circle cx="${CX}" cy="${CY}" r="4" fill="#374151"/>
|
|
70
|
+
<!-- Score number -->
|
|
71
|
+
<text x="${CX}" y="${CY - 20}" text-anchor="middle" font-size="28" font-weight="700" fill="${color}">${clamped}</text>
|
|
72
|
+
<!-- Label -->
|
|
73
|
+
<text x="${CX}" y="${CY - 4}" text-anchor="middle" font-size="11" fill="#6b7280">Risk Score</text>
|
|
74
|
+
<!-- Scale labels -->
|
|
75
|
+
<text x="14" y="${CY + 16}" font-size="9" fill="#6b7280">0</text>
|
|
76
|
+
<text x="${CX - 4}" y="22" font-size="9" fill="#6b7280">50</text>
|
|
77
|
+
<text x="${W - 22}" y="${CY + 16}" font-size="9" fill="#6b7280">100</text>
|
|
78
|
+
</svg>`;
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=risk-gauge-svg.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"risk-gauge-svg.js","sourceRoot":"","sources":["../../../../src/engine/doc-generator/portal/risk-gauge-svg.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { SpecRisk, RiskCategory } from '../../../types/risk.js';
|
|
2
|
+
declare const IMPACT_LEVELS: readonly ["low", "medium", "high", "very_high", "critical"];
|
|
3
|
+
declare const PROB_LEVELS: readonly [20, 40, 60, 80, 100];
|
|
4
|
+
declare const CATEGORY_COLORS: Record<RiskCategory, string>;
|
|
5
|
+
/**
|
|
6
|
+
* Build a 5x5 risk matrix SVG.
|
|
7
|
+
* Returns empty string when risks array is empty.
|
|
8
|
+
*/
|
|
9
|
+
export declare function buildRiskMatrixSvg(risks: SpecRisk[]): string;
|
|
10
|
+
export { IMPACT_LEVELS, PROB_LEVELS, CATEGORY_COLORS };
|
|
11
|
+
//# sourceMappingURL=risk-matrix-svg.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"risk-matrix-svg.d.ts","sourceRoot":"","sources":["../../../../src/engine/doc-generator/portal/risk-matrix-svg.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAErE,QAAA,MAAM,aAAa,6DAA8D,CAAC;AAClF,QAAA,MAAM,WAAW,gCAAiC,CAAC;AAEnD,QAAA,MAAM,eAAe,EAAE,MAAM,CAAC,YAAY,EAAE,MAAM,CAOjD,CAAC;AA2LF;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,MAAM,CAc5D;AAED,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,eAAe,EAAE,CAAC"}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
const IMPACT_LEVELS = ['low', 'medium', 'high', 'very_high', 'critical'];
|
|
2
|
+
const PROB_LEVELS = [20, 40, 60, 80, 100];
|
|
3
|
+
const CATEGORY_COLORS = {
|
|
4
|
+
technical: '#3b82f6',
|
|
5
|
+
security: '#ef4444',
|
|
6
|
+
integration: '#f97316',
|
|
7
|
+
dependency: '#8b5cf6',
|
|
8
|
+
organizational: '#6b7280',
|
|
9
|
+
data: '#10b981',
|
|
10
|
+
};
|
|
11
|
+
const QUADRANT_COLORS = [
|
|
12
|
+
// Row 0 (prob 80-100) high prob
|
|
13
|
+
['#fef3c7', '#fde68a', '#fcd34d', '#f87171', '#ef4444'],
|
|
14
|
+
// Row 1 (prob 60-80)
|
|
15
|
+
['#d1fae5', '#fef3c7', '#fde68a', '#fcd34d', '#f87171'],
|
|
16
|
+
// Row 2 (prob 40-60)
|
|
17
|
+
['#d1fae5', '#d1fae5', '#fef3c7', '#fde68a', '#fcd34d'],
|
|
18
|
+
// Row 3 (prob 20-40)
|
|
19
|
+
['#d1fae5', '#d1fae5', '#d1fae5', '#fef3c7', '#fde68a'],
|
|
20
|
+
// Row 4 (prob 0-20) low prob
|
|
21
|
+
['#d1fae5', '#d1fae5', '#d1fae5', '#d1fae5', '#fef3c7'],
|
|
22
|
+
];
|
|
23
|
+
const CELL = 60;
|
|
24
|
+
const PADDING = 40;
|
|
25
|
+
const LABEL_PAD = 14;
|
|
26
|
+
const GRID_W = CELL * 5;
|
|
27
|
+
const GRID_H = CELL * 5;
|
|
28
|
+
const SVG_W = GRID_W + PADDING + LABEL_PAD;
|
|
29
|
+
const SVG_H = GRID_H + PADDING + LABEL_PAD;
|
|
30
|
+
function impactIndex(risk) {
|
|
31
|
+
// Map impactUsd ranges to 0-4
|
|
32
|
+
if (risk.impactUsd < 1000) {
|
|
33
|
+
return 0;
|
|
34
|
+
}
|
|
35
|
+
if (risk.impactUsd < 5000) {
|
|
36
|
+
return 1;
|
|
37
|
+
}
|
|
38
|
+
if (risk.impactUsd < 20000) {
|
|
39
|
+
return 2;
|
|
40
|
+
}
|
|
41
|
+
if (risk.impactUsd < 50000) {
|
|
42
|
+
return 3;
|
|
43
|
+
}
|
|
44
|
+
return 4;
|
|
45
|
+
}
|
|
46
|
+
function probIndex(risk) {
|
|
47
|
+
const p = risk.probability;
|
|
48
|
+
if (p <= 20) {
|
|
49
|
+
return 4;
|
|
50
|
+
} // row 4 = lowest
|
|
51
|
+
if (p <= 40) {
|
|
52
|
+
return 3;
|
|
53
|
+
}
|
|
54
|
+
if (p <= 60) {
|
|
55
|
+
return 2;
|
|
56
|
+
}
|
|
57
|
+
if (p <= 80) {
|
|
58
|
+
return 1;
|
|
59
|
+
}
|
|
60
|
+
return 0;
|
|
61
|
+
}
|
|
62
|
+
function circleSizeFromUsd(usd) {
|
|
63
|
+
if (usd < 1000) {
|
|
64
|
+
return 8;
|
|
65
|
+
}
|
|
66
|
+
if (usd < 5000) {
|
|
67
|
+
return 12;
|
|
68
|
+
}
|
|
69
|
+
if (usd < 20000) {
|
|
70
|
+
return 16;
|
|
71
|
+
}
|
|
72
|
+
if (usd < 50000) {
|
|
73
|
+
return 20;
|
|
74
|
+
}
|
|
75
|
+
return 24;
|
|
76
|
+
}
|
|
77
|
+
function escapeHtml(s) {
|
|
78
|
+
return s
|
|
79
|
+
.replace(/&/g, '&')
|
|
80
|
+
.replace(/</g, '<')
|
|
81
|
+
.replace(/>/g, '>')
|
|
82
|
+
.replace(/"/g, '"');
|
|
83
|
+
}
|
|
84
|
+
function buildGridCells() {
|
|
85
|
+
const cells = [];
|
|
86
|
+
for (let row = 0; row < 5; row++) {
|
|
87
|
+
for (let col = 0; col < 5; col++) {
|
|
88
|
+
const x = PADDING + col * CELL;
|
|
89
|
+
const y = LABEL_PAD + row * CELL;
|
|
90
|
+
cells.push(`<rect x="${x}" y="${y}" width="${CELL}" height="${CELL}" fill="${QUADRANT_COLORS[row]?.[col] ?? '#d1fae5'}" stroke="#e5e7eb" stroke-width="1"/>`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return cells.join('\n ');
|
|
94
|
+
}
|
|
95
|
+
function buildAxisLabels() {
|
|
96
|
+
const parts = [];
|
|
97
|
+
// X-axis (Impact) labels
|
|
98
|
+
const impactLabels = ['Low', 'Med', 'High', 'V.High', 'Crit'];
|
|
99
|
+
for (let i = 0; i < 5; i++) {
|
|
100
|
+
const x = PADDING + i * CELL + CELL / 2;
|
|
101
|
+
const y = LABEL_PAD + GRID_H + 14;
|
|
102
|
+
parts.push(`<text x="${x}" y="${y}" text-anchor="middle" font-size="10" fill="#6b7280">${impactLabels[i]}</text>`);
|
|
103
|
+
}
|
|
104
|
+
// X-axis title
|
|
105
|
+
parts.push(`<text x="${PADDING + GRID_W / 2}" y="${SVG_H - 2}" text-anchor="middle" font-size="11" font-weight="600" fill="#374151">Impact</text>`);
|
|
106
|
+
// Y-axis (Probability) labels
|
|
107
|
+
const probLabels = ['80-100%', '60-80%', '40-60%', '20-40%', '0-20%'];
|
|
108
|
+
for (let i = 0; i < 5; i++) {
|
|
109
|
+
const y = LABEL_PAD + i * CELL + CELL / 2 + 4;
|
|
110
|
+
parts.push(`<text x="${PADDING - 4}" y="${y}" text-anchor="end" font-size="10" fill="#6b7280">${probLabels[i]}</text>`);
|
|
111
|
+
}
|
|
112
|
+
// Y-axis title (rotated)
|
|
113
|
+
const cx = 10;
|
|
114
|
+
const cy = LABEL_PAD + GRID_H / 2;
|
|
115
|
+
parts.push(`<text x="${cx}" y="${cy}" text-anchor="middle" font-size="11" font-weight="600" fill="#374151" transform="rotate(-90,${cx},${cy})">Probability</text>`);
|
|
116
|
+
return parts.join('\n ');
|
|
117
|
+
}
|
|
118
|
+
function buildRiskDots(risks) {
|
|
119
|
+
// Group risks in same cell to offset them
|
|
120
|
+
const cellMap = new Map();
|
|
121
|
+
for (const r of risks) {
|
|
122
|
+
const key = `${probIndex(r)},${impactIndex(r)}`;
|
|
123
|
+
const arr = cellMap.get(key) ?? [];
|
|
124
|
+
arr.push(r);
|
|
125
|
+
cellMap.set(key, arr);
|
|
126
|
+
}
|
|
127
|
+
const dots = [];
|
|
128
|
+
for (const [key, cellRisks] of cellMap) {
|
|
129
|
+
const parts = key.split(',').map(Number);
|
|
130
|
+
const row = parts[0] ?? 0;
|
|
131
|
+
const col = parts[1] ?? 0;
|
|
132
|
+
const cx = PADDING + col * CELL + CELL / 2;
|
|
133
|
+
const cy = LABEL_PAD + row * CELL + CELL / 2;
|
|
134
|
+
cellRisks.forEach((r, idx) => {
|
|
135
|
+
const offset = (idx - (cellRisks.length - 1) / 2) * 10;
|
|
136
|
+
const rx = cx + (cellRisks.length > 1 ? offset : 0);
|
|
137
|
+
const size = circleSizeFromUsd(r.impactUsd);
|
|
138
|
+
const color = CATEGORY_COLORS[r.category];
|
|
139
|
+
const label = escapeHtml(r.id);
|
|
140
|
+
dots.push(`<circle cx="${rx}" cy="${cy}" r="${size / 2}" fill="${color}" fill-opacity="0.85" stroke="white" stroke-width="1.5">` +
|
|
141
|
+
`<title>${label}: ${escapeHtml(r.description)} ($${r.impactUsd.toLocaleString()})</title>` +
|
|
142
|
+
`</circle>`);
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
return dots.join('\n ');
|
|
146
|
+
}
|
|
147
|
+
function buildLegend(risks) {
|
|
148
|
+
const categories = [...new Set(risks.map((r) => r.category))];
|
|
149
|
+
const parts = [];
|
|
150
|
+
const startY = LABEL_PAD + 4;
|
|
151
|
+
const startX = PADDING + GRID_W + 10;
|
|
152
|
+
if (startX + 90 > SVG_W + 110) {
|
|
153
|
+
return '';
|
|
154
|
+
} // no room
|
|
155
|
+
categories.forEach((cat, i) => {
|
|
156
|
+
const y = startY + i * 18;
|
|
157
|
+
const color = CATEGORY_COLORS[cat];
|
|
158
|
+
parts.push(`<circle cx="${startX + 6}" cy="${y}" r="5" fill="${color}"/>`);
|
|
159
|
+
parts.push(`<text x="${startX + 14}" y="${y + 4}" font-size="10" fill="#374151">${escapeHtml(cat)}</text>`);
|
|
160
|
+
});
|
|
161
|
+
return parts.join('\n ');
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Build a 5x5 risk matrix SVG.
|
|
165
|
+
* Returns empty string when risks array is empty.
|
|
166
|
+
*/
|
|
167
|
+
export function buildRiskMatrixSvg(risks) {
|
|
168
|
+
if (risks.length === 0) {
|
|
169
|
+
return '';
|
|
170
|
+
}
|
|
171
|
+
const legendWidth = 90;
|
|
172
|
+
const totalW = SVG_W + legendWidth;
|
|
173
|
+
return `<svg viewBox="0 0 ${totalW} ${SVG_H}" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Risk Matrix">
|
|
174
|
+
${buildGridCells()}
|
|
175
|
+
${buildAxisLabels()}
|
|
176
|
+
${buildRiskDots(risks)}
|
|
177
|
+
${buildLegend(risks)}
|
|
178
|
+
</svg>`;
|
|
179
|
+
}
|
|
180
|
+
export { IMPACT_LEVELS, PROB_LEVELS, CATEGORY_COLORS };
|
|
181
|
+
//# sourceMappingURL=risk-matrix-svg.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"risk-matrix-svg.js","sourceRoot":"","sources":["../../../../src/engine/doc-generator/portal/risk-matrix-svg.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { RiskRegister } from '../../../types/risk.js';
|
|
2
|
+
import type { Spec } from '../../../types/spec/core.js';
|
|
3
|
+
/**
|
|
4
|
+
* Generate the risks.html portal page.
|
|
5
|
+
*/
|
|
6
|
+
export declare function generateRiskPage(risks: RiskRegister[], specs: Spec[]): string;
|
|
7
|
+
//# sourceMappingURL=risk-page.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"risk-page.d.ts","sourceRoot":"","sources":["../../../../src/engine/doc-generator/portal/risk-page.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAsC,MAAM,wBAAwB,CAAC;AAC/F,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,6BAA6B,CAAC;AAsMxD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,YAAY,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,MAAM,CA6C7E"}
|