@atlashub/smartstack-cli 4.74.0 → 4.75.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/index.js +111 -36
- package/dist/index.js.map +1 -1
- package/dist/mcp-entry.mjs +14 -3
- package/dist/mcp-entry.mjs.map +1 -1
- package/package.json +1 -1
- package/templates/agents/ba-reader.md +17 -15
- package/templates/agents/ba-writer.md +49 -51
- package/templates/skills/apex/_shared.md +1 -1
- package/templates/skills/apex/references/checks/backend-checks.sh +21 -7
- package/templates/skills/apex/references/checks/infrastructure-checks.sh +47 -10
- package/templates/skills/apex/references/frontend-route-wiring-app-tsx.md +3 -0
- package/templates/skills/apex/references/post-checks.md +5 -2
- package/templates/skills/apex/references/smartstack-frontend.md +53 -7
- package/templates/skills/apex/steps/step-00-init.md +74 -0
- package/templates/skills/apex/steps/step-03-execute.md +16 -4
- package/templates/skills/apex/steps/step-03b-layer1-seed.md +39 -6
- package/templates/skills/apex/steps/step-03c-layer2-backend.md +50 -5
- package/templates/skills/apex/steps/step-03d-layer3-frontend.md +102 -2
- package/templates/skills/application/references/frontend-route-wiring-app-tsx.md +3 -0
- package/templates/skills/business-analyse/SKILL.md +14 -0
- package/templates/skills/business-analyse/_shared.md +27 -0
- package/templates/skills/business-analyse/patterns/suggestion-catalog.md +34 -26
- package/templates/skills/business-analyse/questionnaire/01-context.md +13 -9
- package/templates/skills/business-analyse/questionnaire/02-stakeholders-scope.md +20 -27
- package/templates/skills/business-analyse/questionnaire.md +86 -9
- package/templates/skills/business-analyse/references/03-json-schemas.md +213 -0
- package/templates/skills/business-analyse/references/03-post-check-validation.md +144 -0
- package/templates/skills/business-analyse/references/03-smartstack-entity-guards.md +32 -0
- package/templates/skills/business-analyse/references/04-cross-module-validation.md +95 -0
- package/templates/skills/business-analyse/references/04-file-allocation.md +162 -0
- package/templates/skills/business-analyse/references/04-naming-audit-checks.md +174 -0
- package/templates/skills/business-analyse/references/04-semantic-validation-matrix.md +118 -0
- package/templates/skills/business-analyse/references/domain-research-playbook.md +234 -0
- package/templates/skills/business-analyse/references/entity-sourcing-presentation.md +166 -0
- package/templates/skills/business-analyse/references/init-resume-logic.md +70 -0
- package/templates/skills/business-analyse/references/module-completeness-challenge.md +174 -0
- package/templates/skills/business-analyse/references/multi-app-detection.md +149 -0
- package/templates/skills/business-analyse/references/portal-classification.md +52 -0
- package/templates/skills/business-analyse/references/validation-checklist.md +30 -1
- package/templates/skills/business-analyse/schemas/sections/analysis-schema.json +37 -4
- package/templates/skills/business-analyse/steps/step-00-init.md +22 -190
- package/templates/skills/business-analyse/steps/step-01-cadrage.md +365 -269
- package/templates/skills/business-analyse/steps/step-02-structure.md +98 -20
- package/templates/skills/business-analyse/steps/step-03-specify.md +652 -229
- package/templates/skills/business-analyse/steps/step-04-consolidate.md +308 -287
- package/templates/skills/business-analyse-design/SKILL.md +10 -0
- package/templates/skills/business-analyse-design/references/screens-post-check.md +221 -0
- package/templates/skills/business-analyse-design/references/screens-type-mapping.md +138 -0
- package/templates/skills/business-analyse-design/references/smartcomponents-templates.md +225 -0
- package/templates/skills/{business-analyse → business-analyse-design}/references/spec-auto-inference.md +117 -117
- package/templates/skills/business-analyse-design/steps/step-01-screens.md +36 -162
- package/templates/skills/business-analyse-design/steps/step-02-wireframes.md +8 -7
- package/templates/skills/business-analyse-design/steps/step-03-navigation.md +89 -42
- package/templates/skills/business-analyse-develop/references/compact-loop.md +9 -0
- package/templates/skills/business-analyse-develop/references/handoff-quality-gate.md +132 -0
- package/templates/skills/business-analyse-develop/references/prd-v3-transformation.md +326 -0
- package/templates/skills/business-analyse-develop/references/report-reconciliation.md +140 -0
- package/templates/skills/business-analyse-develop/references/report-template.md +142 -0
- package/templates/skills/business-analyse-develop/steps/step-01-task.md +5 -177
- package/templates/skills/business-analyse-develop/steps/step-02-execute.md +17 -4
- package/templates/skills/business-analyse-develop/steps/step-03-commit.md +6 -2
- package/templates/skills/business-analyse-develop/steps/step-04-check.md +6 -0
- package/templates/skills/business-analyse-develop/steps/step-05-report.md +3 -269
- package/templates/skills/business-analyse-handoff/SKILL.md +10 -0
- package/templates/skills/business-analyse-handoff/references/agent-handoff-transform-prompt.md +208 -0
- package/templates/skills/business-analyse-handoff/references/context-isolation-pattern.md +47 -0
- package/templates/skills/business-analyse-handoff/references/handoff-file-inventory.md +49 -0
- package/templates/skills/business-analyse-handoff/references/handoff-global-validation.md +142 -0
- package/templates/skills/business-analyse-handoff/references/prd-validation-checks.md +125 -0
- package/templates/skills/business-analyse-handoff/references/project-index-update.md +98 -0
- package/templates/skills/business-analyse-handoff/steps/step-01-transform.md +9 -160
- package/templates/skills/business-analyse-handoff/steps/step-02-export.md +10 -99
- package/templates/skills/business-analyse-html/SKILL.md +10 -0
- package/templates/skills/business-analyse-html/html/ba-interactive.html +306 -81
- package/templates/skills/business-analyse-html/html/src/scripts/01-data-init.js +15 -2
- package/templates/skills/business-analyse-html/html/src/scripts/02-navigation.js +6 -46
- package/templates/skills/business-analyse-html/html/src/scripts/06-render-mockups.js +88 -33
- package/templates/skills/business-analyse-html/html/src/scripts/12-render-diagrams.js +116 -0
- package/templates/skills/business-analyse-html/html/src/styles/10-diagrams.css +73 -0
- package/templates/skills/business-analyse-html/html/src/template.html +2 -0
- package/templates/skills/business-analyse-html/references/02-embedded-artifacts-building.md +144 -0
- package/templates/skills/business-analyse-html/references/02-feature-data-building.md +141 -0
- package/templates/skills/business-analyse-html/references/02-mapping-tables.md +442 -0
- package/templates/skills/business-analyse-html/references/02-normalization-helpers.md +139 -0
- package/templates/skills/business-analyse-html/references/02-screen-format-detection.md +283 -0
- package/templates/skills/business-analyse-html/references/02-self-check-validation.md +199 -0
- package/templates/skills/business-analyse-html/references/data-build.md +22 -1
- package/templates/skills/business-analyse-html/references/data-mapping.md +40 -5
- package/templates/skills/business-analyse-html/steps/step-02-build-data.md +12 -555
- package/templates/skills/business-analyse-review/SKILL.md +10 -0
- package/templates/skills/business-analyse-status/SKILL.md +8 -0
- package/templates/skills/dev-start/SKILL.md +143 -307
- package/templates/skills/efcore/SKILL.md +13 -0
|
@@ -77,3 +77,13 @@ When launched, detect and select the target project:
|
|
|
77
77
|
## Entry Point
|
|
78
78
|
|
|
79
79
|
**FIRST ACTION:** Load `steps/step-01-collect.md`
|
|
80
|
+
|
|
81
|
+
<success_criteria>
|
|
82
|
+
- Sources JSON collectees (index, cadrage, modules, consolidation)
|
|
83
|
+
- FEATURE_DATA construit avec mapping correct des champs
|
|
84
|
+
- EMBEDDED_ARTIFACTS cree pour ERD, matrice permissions, wireframes
|
|
85
|
+
- ba-interactive.html template injecte et rendu
|
|
86
|
+
- Fichier HTML final > 100KB sans chaine [object Object]
|
|
87
|
+
- moduleSpecs a UNE entree par module avec resources peuplees
|
|
88
|
+
- Cles scope normalisees : inScope -> inscope, outOfScope -> outofscope
|
|
89
|
+
</success_criteria>
|
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
6
|
<title>{{APPLICATION_NAME}} - Analyse métier</title>
|
|
7
|
+
<script src="https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.min.js"></script>
|
|
8
|
+
<script>mermaid.initialize({ startOnLoad: false, theme: 'dark', securityLevel: 'loose' });</script>
|
|
7
9
|
<style>
|
|
8
10
|
/* --- 01-variables.css --- */
|
|
9
11
|
/* ============================================
|
|
@@ -2024,6 +2026,82 @@ body {
|
|
|
2024
2026
|
.mock-form-tab-content.active {
|
|
2025
2027
|
display: block;
|
|
2026
2028
|
}
|
|
2029
|
+
|
|
2030
|
+
|
|
2031
|
+
/* --- 10-diagrams.css --- */
|
|
2032
|
+
/* ==========================================
|
|
2033
|
+
MERMAID DIAGRAMS
|
|
2034
|
+
========================================== */
|
|
2035
|
+
|
|
2036
|
+
.diagram-container {
|
|
2037
|
+
margin: 1.5rem 0;
|
|
2038
|
+
padding: 1rem;
|
|
2039
|
+
background: var(--bg-card);
|
|
2040
|
+
border-radius: 8px;
|
|
2041
|
+
border: 1px solid var(--border);
|
|
2042
|
+
overflow-x: auto;
|
|
2043
|
+
}
|
|
2044
|
+
|
|
2045
|
+
.diagram-container h3,
|
|
2046
|
+
.diagram-container h4 {
|
|
2047
|
+
color: var(--text-bright);
|
|
2048
|
+
margin-bottom: 1rem;
|
|
2049
|
+
font-size: 1.1rem;
|
|
2050
|
+
}
|
|
2051
|
+
|
|
2052
|
+
.diagram-container .mermaid {
|
|
2053
|
+
display: flex;
|
|
2054
|
+
justify-content: center;
|
|
2055
|
+
min-height: 200px;
|
|
2056
|
+
}
|
|
2057
|
+
|
|
2058
|
+
.diagram-container .mermaid svg {
|
|
2059
|
+
max-width: 100%;
|
|
2060
|
+
height: auto;
|
|
2061
|
+
}
|
|
2062
|
+
|
|
2063
|
+
/* ERD specific */
|
|
2064
|
+
.diagram-erd {
|
|
2065
|
+
margin-bottom: 2rem;
|
|
2066
|
+
border-left: 3px solid var(--primary);
|
|
2067
|
+
}
|
|
2068
|
+
|
|
2069
|
+
/* State machine specific */
|
|
2070
|
+
.diagram-state-machine {
|
|
2071
|
+
border-left: 3px solid var(--accent);
|
|
2072
|
+
}
|
|
2073
|
+
|
|
2074
|
+
/* Sequence diagram specific */
|
|
2075
|
+
.diagram-sequence {
|
|
2076
|
+
border-left: 3px solid var(--success);
|
|
2077
|
+
}
|
|
2078
|
+
|
|
2079
|
+
/* Diagram section header */
|
|
2080
|
+
.diagram-section-header {
|
|
2081
|
+
display: flex;
|
|
2082
|
+
align-items: center;
|
|
2083
|
+
gap: 0.5rem;
|
|
2084
|
+
margin-bottom: 1rem;
|
|
2085
|
+
color: var(--text-bright);
|
|
2086
|
+
font-size: 1.2rem;
|
|
2087
|
+
font-weight: 600;
|
|
2088
|
+
}
|
|
2089
|
+
|
|
2090
|
+
.diagram-section-header::before {
|
|
2091
|
+
content: '';
|
|
2092
|
+
width: 4px;
|
|
2093
|
+
height: 1.2em;
|
|
2094
|
+
background: var(--primary);
|
|
2095
|
+
border-radius: 2px;
|
|
2096
|
+
}
|
|
2097
|
+
|
|
2098
|
+
/* No diagrams fallback */
|
|
2099
|
+
.diagram-empty {
|
|
2100
|
+
color: var(--text-muted);
|
|
2101
|
+
font-style: italic;
|
|
2102
|
+
padding: 1rem;
|
|
2103
|
+
text-align: center;
|
|
2104
|
+
}
|
|
2027
2105
|
|
|
2028
2106
|
</style>
|
|
2029
2107
|
</head>
|
|
@@ -2515,9 +2593,22 @@ if (!data.cadrage.scope || (!data.cadrage.scope.inscope?.length && data.cadrage.
|
|
|
2515
2593
|
outofscope: (gs.outOfScope || []).map(s => typeof s === 'string' ? { name: s, description: '' } : s)
|
|
2516
2594
|
};
|
|
2517
2595
|
} else {
|
|
2596
|
+
function normScopeItem(s) {
|
|
2597
|
+
if (typeof s === 'string') return { name: s, description: '' };
|
|
2598
|
+
if (s.name) return s;
|
|
2599
|
+
var nm = s.feature || s.label || s.title || JSON.stringify(s);
|
|
2600
|
+
var parts = [];
|
|
2601
|
+
if (s.priority) parts.push(s.priority.toUpperCase());
|
|
2602
|
+
if (s.module) parts.push('Module: ' + s.module);
|
|
2603
|
+
return { name: nm, description: parts.join(' — ') };
|
|
2604
|
+
}
|
|
2518
2605
|
data.cadrage.scope = {
|
|
2519
|
-
inscope: (gs.inScope || []).map(
|
|
2520
|
-
outofscope: (gs.outOfScope || []).map(s
|
|
2606
|
+
inscope: (gs.inScope || []).map(normScopeItem),
|
|
2607
|
+
outofscope: (gs.outOfScope || []).map(function(s) {
|
|
2608
|
+
if (typeof s === 'string') return { name: s, description: '' };
|
|
2609
|
+
if (s.name) return s;
|
|
2610
|
+
return { name: s.feature || s.reason || JSON.stringify(s), description: s.reason || '' };
|
|
2611
|
+
})
|
|
2521
2612
|
};
|
|
2522
2613
|
}
|
|
2523
2614
|
}
|
|
@@ -2851,54 +2942,14 @@ function renderModuleNavItem(mod) {
|
|
|
2851
2942
|
var ucCount = (spec.useCases || []).length;
|
|
2852
2943
|
var brCount = (spec.businessRules || []).length;
|
|
2853
2944
|
var entCount = (spec.entities || []).length;
|
|
2854
|
-
var sections = (mod.anticipatedSections || []).map(function(s) {
|
|
2855
|
-
return typeof s === 'string' ? { code: s, name: s, resources: [] } : s;
|
|
2856
|
-
});
|
|
2857
|
-
var groupId = 'mod-' + code;
|
|
2858
|
-
var collapsed = navCollapseState[groupId] === true;
|
|
2859
|
-
|
|
2860
|
-
var html = '<div class="nav-module" data-group-id="' + groupId + '">';
|
|
2861
|
-
|
|
2862
|
-
// Module header (clickable to expand + navigate to module spec)
|
|
2863
2945
|
var totalItems = ucCount + brCount + entCount;
|
|
2864
|
-
html += '<a class="nav-item nav-module-header" onclick="toggleNavGroup(\'' + groupId + '\');showSection(\'module-spec-' + code + '\')" data-section="module-spec-' + code + '">';
|
|
2865
|
-
html += '<span class="nav-chevron ' + (collapsed ? '' : 'expanded') + '">▸</span> ';
|
|
2866
|
-
html += (mod.name || mod.code);
|
|
2867
|
-
if (totalItems > 0) html += ' <span class="nav-badge">' + totalItems + '</span>';
|
|
2868
|
-
html += '</a>';
|
|
2869
|
-
|
|
2870
|
-
// Children: sections/resources (navigable sub-tree)
|
|
2871
|
-
// Tab-level items (UC, BR, Données, etc.) are NOT shown here — they are accessed
|
|
2872
|
-
// via the tab bar in the module content area to avoid redundancy.
|
|
2873
|
-
html += '<div class="nav-children"' + (collapsed ? ' style="display:none;"' : '') + '>';
|
|
2874
|
-
if (sections.length > 0) {
|
|
2875
|
-
sections.forEach(function(section) {
|
|
2876
|
-
var resources = section.resources || [];
|
|
2877
|
-
var sectionUCs = (section.useCases || []).length;
|
|
2878
|
-
var sectionBRs = (section.businessRules || []).length;
|
|
2879
|
-
var contentCount = sectionUCs + sectionBRs + resources.length;
|
|
2880
|
-
html += '<div class="nav-section-item">';
|
|
2881
|
-
html += '<a class="nav-item nav-section-link" onclick="showSection(\'module-spec-' + code + '\');switchTab(\'' + code + '\',\'struct\')" data-section="module-struct-' + code + '-' + section.code + '">';
|
|
2882
|
-
html += '<span class="nav-icon nav-icon-section">▷</span> ' + escapeHtml(section.code || section.name || '');
|
|
2883
|
-
if (contentCount > 0) html += ' <span class="nav-badge">' + contentCount + '</span>';
|
|
2884
|
-
html += '</a>';
|
|
2885
|
-
if (resources.length > 0) {
|
|
2886
|
-
html += '<div class="nav-children nav-resources">';
|
|
2887
|
-
resources.forEach(function(res) {
|
|
2888
|
-
var resName = typeof res === 'string' ? res : (res.code || res.name || '');
|
|
2889
|
-
html += '<a class="nav-item nav-resource-link" onclick="showSection(\'module-spec-' + code + '\');switchTab(\'' + code + '\',\'mock\');scrollToMockup(\'' + code + '\',\'' + section.code + '\')">';
|
|
2890
|
-
html += '<span class="nav-icon nav-icon-resource">•</span> ' + escapeHtml(resName);
|
|
2891
|
-
html += '</a>';
|
|
2892
|
-
});
|
|
2893
|
-
html += '</div>';
|
|
2894
|
-
}
|
|
2895
|
-
html += '</div>';
|
|
2896
|
-
});
|
|
2897
|
-
}
|
|
2898
2946
|
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2947
|
+
// Flat module link — sections/resources are accessible via tabs (Structure, Maquettes)
|
|
2948
|
+
return '<a class="nav-item nav-module-header" onclick="showSection(\'module-spec-' + code + '\')" data-section="module-spec-' + code + '">' +
|
|
2949
|
+
'<span class="nav-icon">●</span> ' +
|
|
2950
|
+
(mod.name || mod.code) +
|
|
2951
|
+
(totalItems > 0 ? ' <span class="nav-badge">' + totalItems + '</span>' : '') +
|
|
2952
|
+
'</a>';
|
|
2902
2953
|
}
|
|
2903
2954
|
|
|
2904
2955
|
function renderModuleTabNavItem(code, tabId, label, badge) {
|
|
@@ -4625,31 +4676,36 @@ function renderSmartFormMockup(res) {
|
|
|
4625
4676
|
html += '<div class="mock-form-tab-content' + (ti === 0 || isOnly ? ' active' : '') + '"';
|
|
4626
4677
|
html += ' data-mockup="' + mockupId + '" data-tab="' + ti + '">';
|
|
4627
4678
|
|
|
4628
|
-
|
|
4629
|
-
|
|
4630
|
-
|
|
4631
|
-
|
|
4632
|
-
|
|
4679
|
+
// Tab-level subtable: the entire tab is a subtable (type: "subtable", entity, columns)
|
|
4680
|
+
if (tab.type === 'subtable') {
|
|
4681
|
+
html += renderSubtableMockup(tab);
|
|
4682
|
+
} else {
|
|
4683
|
+
var fields = tab.fields || [];
|
|
4684
|
+
var rows = [];
|
|
4685
|
+
for (var i = 0; i < fields.length; i += 2) {
|
|
4686
|
+
rows.push(fields.slice(i, i + 2));
|
|
4687
|
+
}
|
|
4633
4688
|
|
|
4634
|
-
|
|
4635
|
-
|
|
4636
|
-
|
|
4637
|
-
|
|
4638
|
-
|
|
4639
|
-
|
|
4640
|
-
|
|
4641
|
-
|
|
4642
|
-
|
|
4643
|
-
|
|
4644
|
-
|
|
4689
|
+
rows.forEach(function(row) {
|
|
4690
|
+
if (row.length === 1 && row[0].type === 'subtable') {
|
|
4691
|
+
html += renderSubtableMockup(row[0]);
|
|
4692
|
+
} else {
|
|
4693
|
+
html += '<div class="mock-form-row">';
|
|
4694
|
+
row.forEach(function(field) {
|
|
4695
|
+
html += '<div class="mock-form-group">';
|
|
4696
|
+
html += '<label class="mock-label">' + escapeHtml(field.label || field.field);
|
|
4697
|
+
if (field.required) html += ' <span style="color:var(--error);">*</span>';
|
|
4698
|
+
html += '</label>';
|
|
4699
|
+
html += renderFormFieldMockup(field);
|
|
4700
|
+
html += '</div>';
|
|
4701
|
+
});
|
|
4645
4702
|
html += '</div>';
|
|
4646
|
-
}
|
|
4647
|
-
|
|
4648
|
-
}
|
|
4649
|
-
});
|
|
4703
|
+
}
|
|
4704
|
+
});
|
|
4650
4705
|
|
|
4651
|
-
|
|
4652
|
-
|
|
4706
|
+
if (fields.length === 0) {
|
|
4707
|
+
html += '<div style="padding:2rem;text-align:center;color:var(--text-muted);font-style:italic;">Contenu de l\'onglet « ' + escapeHtml(tab.label) + ' »</div>';
|
|
4708
|
+
}
|
|
4653
4709
|
}
|
|
4654
4710
|
|
|
4655
4711
|
html += '</div>';
|
|
@@ -4694,20 +4750,39 @@ function renderSubtableMockup(field) {
|
|
|
4694
4750
|
|
|
4695
4751
|
/* ---------- SmartCard ---------- */
|
|
4696
4752
|
function renderSmartCardMockup(res) {
|
|
4697
|
-
var
|
|
4753
|
+
var fields = res.fields || res.columns || [];
|
|
4698
4754
|
var html = '<div class="mock-header"><span class="mock-title">' + escapeHtml(res.label || 'Cartes') + '</span></div>';
|
|
4699
4755
|
html += '<div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:1rem;">';
|
|
4700
4756
|
|
|
4701
4757
|
for (var i = 0; i < 4; i++) {
|
|
4702
4758
|
html += '<div style="background:var(--bg-hover);border:1px solid var(--border);border-radius:8px;padding:1rem;">';
|
|
4703
|
-
|
|
4704
|
-
|
|
4705
|
-
|
|
4759
|
+
// Title/Subtitle pattern (SmartCard with title + subtitle + fields + actions)
|
|
4760
|
+
if (res.title) {
|
|
4761
|
+
html += '<div style="font-weight:600;color:var(--text-bright);margin-bottom:0.25rem;">' + escapeHtml(res.title) + ' #' + (i + 1) + '</div>';
|
|
4762
|
+
}
|
|
4763
|
+
if (res.subtitle) {
|
|
4764
|
+
html += '<div style="font-size:0.8rem;color:var(--accent);margin-bottom:0.5rem;">' + escapeHtml(res.subtitle) + '</div>';
|
|
4765
|
+
}
|
|
4766
|
+
// Fields
|
|
4767
|
+
fields.forEach(function(col, ci) {
|
|
4768
|
+
var label = col.label || col.field || (typeof col === 'string' ? col : '');
|
|
4769
|
+
var iconMap = { calendar: '📅 ', 'dollar-sign': '💰 ', 'alert-circle': '⚠ ', mail: '✉ ', building: '🏢 ', user: '👤 ' };
|
|
4770
|
+
var icon = col.icon ? (iconMap[col.icon] || '● ') : '';
|
|
4771
|
+
if (!res.title && ci === 0) {
|
|
4706
4772
|
html += '<div style="font-weight:600;color:var(--text-bright);margin-bottom:0.5rem;">' + escapeHtml(label) + ' #' + (i + 1) + '</div>';
|
|
4707
4773
|
} else {
|
|
4708
|
-
html += '<div style="font-size:0.8rem;color:var(--text-muted);margin-bottom:0.25rem;">' + escapeHtml(label) + ': <span style="color:var(--text);">valeur</span></div>';
|
|
4774
|
+
html += '<div style="font-size:0.8rem;color:var(--text-muted);margin-bottom:0.25rem;">' + icon + escapeHtml(label) + ': <span style="color:var(--text);">valeur</span></div>';
|
|
4709
4775
|
}
|
|
4710
4776
|
});
|
|
4777
|
+
// Actions
|
|
4778
|
+
if (res.actions && res.actions.length > 0) {
|
|
4779
|
+
html += '<div style="margin-top:0.75rem;display:flex;gap:0.4rem;">';
|
|
4780
|
+
res.actions.forEach(function(a) {
|
|
4781
|
+
var actionLabel = typeof a === 'string' ? a.replace(/-/g, ' ') : (a.label || a.action || '');
|
|
4782
|
+
html += '<span class="mock-btn" style="font-size:0.75rem;">' + escapeHtml(actionLabel) + '</span>';
|
|
4783
|
+
});
|
|
4784
|
+
html += '</div>';
|
|
4785
|
+
}
|
|
4711
4786
|
html += '</div>';
|
|
4712
4787
|
}
|
|
4713
4788
|
html += '</div>';
|
|
@@ -4716,7 +4791,7 @@ function renderSmartCardMockup(res) {
|
|
|
4716
4791
|
|
|
4717
4792
|
/* ---------- SmartKanban ---------- */
|
|
4718
4793
|
function renderSmartKanbanMockup(res) {
|
|
4719
|
-
var options = res.options
|
|
4794
|
+
var options = (res.options && res.options.length > 0) ? res.options : (res.columns && res.columns.length > 0) ? res.columns : ['À faire', 'En cours', 'Terminé'];
|
|
4720
4795
|
var html = '<div class="mock-header"><span class="mock-title">' + escapeHtml(res.label || 'Kanban') + '</span></div>';
|
|
4721
4796
|
html += '<div style="display:flex;gap:1rem;overflow-x:auto;padding-bottom:0.5rem;">';
|
|
4722
4797
|
|
|
@@ -4790,11 +4865,42 @@ function kpiDisplayValue(kpi) {
|
|
|
4790
4865
|
|
|
4791
4866
|
/* ---------- SmartFilter ---------- */
|
|
4792
4867
|
function renderSmartFilterMockup(res) {
|
|
4793
|
-
var
|
|
4794
|
-
|
|
4795
|
-
|
|
4796
|
-
|
|
4797
|
-
|
|
4868
|
+
var filters = res.filters || [];
|
|
4869
|
+
if (filters.length === 0) {
|
|
4870
|
+
// Fallback: legacy options[] format (tag pills)
|
|
4871
|
+
var options = res.options || [];
|
|
4872
|
+
if (options.length === 0) return '<div style="padding:1rem;text-align:center;color:var(--text-muted);">Aucun filtre défini</div>';
|
|
4873
|
+
var html = '<div style="display:flex;gap:0.4rem;flex-wrap:wrap;padding:0.5rem 0;">';
|
|
4874
|
+
html += '<span style="padding:0.3rem 0.7rem;border-radius:16px;font-size:0.8rem;background:var(--primary);color:#fff;cursor:pointer;">Tous</span>';
|
|
4875
|
+
options.forEach(function(opt) {
|
|
4876
|
+
html += '<span style="padding:0.3rem 0.7rem;border-radius:16px;font-size:0.8rem;background:var(--bg-hover);color:var(--text);border:1px solid var(--border);cursor:pointer;">' + escapeHtml(typeof opt === 'string' ? opt : opt.label || '') + '</span>';
|
|
4877
|
+
});
|
|
4878
|
+
html += '</div>';
|
|
4879
|
+
return html;
|
|
4880
|
+
}
|
|
4881
|
+
|
|
4882
|
+
// Rich filter bar: render each filter based on its type
|
|
4883
|
+
var html = '<div style="display:flex;gap:0.5rem;flex-wrap:wrap;align-items:flex-end;padding:0.5rem 0;">';
|
|
4884
|
+
filters.forEach(function(f) {
|
|
4885
|
+
var label = typeof f === 'string' ? f : (f.label || f.field || '');
|
|
4886
|
+
var type = typeof f === 'string' ? 'text' : (f.type || 'text');
|
|
4887
|
+
html += '<div style="display:flex;flex-direction:column;gap:0.2rem;">';
|
|
4888
|
+
html += '<span style="font-size:0.7rem;color:var(--text-muted);">' + escapeHtml(label) + '</span>';
|
|
4889
|
+
switch (type) {
|
|
4890
|
+
case 'select':
|
|
4891
|
+
var opts = f.options || ['Option 1', 'Option 2'];
|
|
4892
|
+
html += '<span class="mock-input" style="width:auto;min-width:130px;font-size:0.8rem;color:var(--text-muted);">' + escapeHtml(opts[0]) + ' ▾</span>';
|
|
4893
|
+
break;
|
|
4894
|
+
case 'lookup':
|
|
4895
|
+
html += '<span class="mock-input" style="width:auto;min-width:130px;font-size:0.8rem;color:var(--accent);">' + escapeHtml(f.entity || label) + ' 🔍</span>';
|
|
4896
|
+
break;
|
|
4897
|
+
case 'daterange':
|
|
4898
|
+
html += '<span class="mock-input" style="width:auto;min-width:180px;font-size:0.8rem;color:var(--text-muted);">01/01/2025 — 31/12/2025 📅</span>';
|
|
4899
|
+
break;
|
|
4900
|
+
default:
|
|
4901
|
+
html += '<span class="mock-input" style="width:auto;min-width:160px;font-size:0.8rem;color:var(--text-muted);">Rechercher... 🔍</span>';
|
|
4902
|
+
}
|
|
4903
|
+
html += '</div>';
|
|
4798
4904
|
});
|
|
4799
4905
|
html += '</div>';
|
|
4800
4906
|
return html;
|
|
@@ -5721,6 +5827,125 @@ function scrollToCommentThread(sectionId, safeElId) {
|
|
|
5721
5827
|
}
|
|
5722
5828
|
}, 100);
|
|
5723
5829
|
}
|
|
5830
|
+
|
|
5831
|
+
|
|
5832
|
+
/* --- 12-render-diagrams.js --- */
|
|
5833
|
+
/* ==========================================
|
|
5834
|
+
MERMAID DIAGRAM RENDERING
|
|
5835
|
+
Renders ERD, state machines, and sequence diagrams
|
|
5836
|
+
from consolidation.mermaidDiagrams data.
|
|
5837
|
+
========================================== */
|
|
5838
|
+
|
|
5839
|
+
function renderMermaidDiagrams() {
|
|
5840
|
+
const data = window.FEATURE_DATA;
|
|
5841
|
+
if (!data) return;
|
|
5842
|
+
|
|
5843
|
+
const diagrams = data.consolidation?.mermaidDiagrams;
|
|
5844
|
+
if (!diagrams) return;
|
|
5845
|
+
|
|
5846
|
+
// 1. ERD in consol-datamodel (prepend before entity cards)
|
|
5847
|
+
if (diagrams.erd) {
|
|
5848
|
+
const erdContainer = document.getElementById('dataModelContainer');
|
|
5849
|
+
if (erdContainer) {
|
|
5850
|
+
const erdDiv = document.createElement('div');
|
|
5851
|
+
erdDiv.className = 'diagram-container diagram-erd';
|
|
5852
|
+
erdDiv.innerHTML =
|
|
5853
|
+
'<div class="diagram-section-header">Diagramme Entit\u00e9-Relation (ERD)</div>' +
|
|
5854
|
+
'<div class="mermaid">' + escapeHtml(diagrams.erd) + '</div>';
|
|
5855
|
+
erdContainer.insertBefore(erdDiv, erdContainer.firstChild);
|
|
5856
|
+
}
|
|
5857
|
+
}
|
|
5858
|
+
|
|
5859
|
+
// 2. State machine diagrams — inject in module spec sections or consol-datamodel
|
|
5860
|
+
if (diagrams.stateMachines && Object.keys(diagrams.stateMachines).length > 0) {
|
|
5861
|
+
const smContainer = document.getElementById('dataModelContainer');
|
|
5862
|
+
if (smContainer) {
|
|
5863
|
+
const smSection = document.createElement('div');
|
|
5864
|
+
smSection.innerHTML = '<div class="diagram-section-header">Cycles de vie (State Machines)</div>';
|
|
5865
|
+
|
|
5866
|
+
Object.entries(diagrams.stateMachines).forEach(function(entry) {
|
|
5867
|
+
var entity = entry[0];
|
|
5868
|
+
var def = entry[1];
|
|
5869
|
+
var smDiv = document.createElement('div');
|
|
5870
|
+
smDiv.className = 'diagram-container diagram-state-machine';
|
|
5871
|
+
smDiv.innerHTML =
|
|
5872
|
+
'<h4>' + escapeHtml(entity) + '</h4>' +
|
|
5873
|
+
'<div class="mermaid">' + escapeHtml(def) + '</div>';
|
|
5874
|
+
smSection.appendChild(smDiv);
|
|
5875
|
+
});
|
|
5876
|
+
|
|
5877
|
+
smContainer.appendChild(smSection);
|
|
5878
|
+
}
|
|
5879
|
+
}
|
|
5880
|
+
|
|
5881
|
+
// 3. Sequence diagrams in consol-flows
|
|
5882
|
+
if (diagrams.sequences && Object.keys(diagrams.sequences).length > 0) {
|
|
5883
|
+
var flowsContainer = document.getElementById('consolFlowsContainer');
|
|
5884
|
+
// Fallback: try the consol-flows section
|
|
5885
|
+
if (!flowsContainer) {
|
|
5886
|
+
var consolFlows = document.getElementById('consol-flows');
|
|
5887
|
+
if (consolFlows) {
|
|
5888
|
+
flowsContainer = consolFlows.querySelector('.section-body') || consolFlows;
|
|
5889
|
+
}
|
|
5890
|
+
}
|
|
5891
|
+
|
|
5892
|
+
if (flowsContainer) {
|
|
5893
|
+
var seqSection = document.createElement('div');
|
|
5894
|
+
seqSection.innerHTML = '<div class="diagram-section-header">Diagrammes de s\u00e9quence</div>';
|
|
5895
|
+
|
|
5896
|
+
Object.entries(diagrams.sequences).forEach(function(entry) {
|
|
5897
|
+
var flowName = entry[0];
|
|
5898
|
+
var def = entry[1];
|
|
5899
|
+
var seqDiv = document.createElement('div');
|
|
5900
|
+
seqDiv.className = 'diagram-container diagram-sequence';
|
|
5901
|
+
seqDiv.innerHTML =
|
|
5902
|
+
'<h4>' + escapeHtml(flowName) + '</h4>' +
|
|
5903
|
+
'<div class="mermaid">' + escapeHtml(def) + '</div>';
|
|
5904
|
+
seqSection.appendChild(seqDiv);
|
|
5905
|
+
});
|
|
5906
|
+
|
|
5907
|
+
flowsContainer.appendChild(seqSection);
|
|
5908
|
+
}
|
|
5909
|
+
}
|
|
5910
|
+
|
|
5911
|
+
// 4. Render all mermaid elements
|
|
5912
|
+
try {
|
|
5913
|
+
if (typeof mermaid !== 'undefined' && mermaid.run) {
|
|
5914
|
+
mermaid.run({ querySelector: '.mermaid' });
|
|
5915
|
+
}
|
|
5916
|
+
} catch (e) {
|
|
5917
|
+
console.warn('Mermaid rendering failed:', e);
|
|
5918
|
+
// Fallback: show raw text
|
|
5919
|
+
document.querySelectorAll('.mermaid').forEach(function(el) {
|
|
5920
|
+
if (!el.querySelector('svg')) {
|
|
5921
|
+
el.style.whiteSpace = 'pre-wrap';
|
|
5922
|
+
el.style.fontFamily = 'monospace';
|
|
5923
|
+
el.style.fontSize = '0.85rem';
|
|
5924
|
+
el.style.color = 'var(--text-muted)';
|
|
5925
|
+
}
|
|
5926
|
+
});
|
|
5927
|
+
}
|
|
5928
|
+
}
|
|
5929
|
+
|
|
5930
|
+
// Escape HTML for safe injection
|
|
5931
|
+
function escapeHtml(text) {
|
|
5932
|
+
if (!text) return '';
|
|
5933
|
+
// For mermaid content, we need to preserve the syntax
|
|
5934
|
+
// Only escape actual HTML tags, not mermaid arrows
|
|
5935
|
+
return text.replace(/</g, '<').replace(/>/g, '>');
|
|
5936
|
+
}
|
|
5937
|
+
|
|
5938
|
+
// Auto-run after consolidation rendering
|
|
5939
|
+
(function() {
|
|
5940
|
+
// Wait for DOM and other render functions to complete
|
|
5941
|
+
if (document.readyState === 'loading') {
|
|
5942
|
+
document.addEventListener('DOMContentLoaded', function() {
|
|
5943
|
+
setTimeout(renderMermaidDiagrams, 500);
|
|
5944
|
+
});
|
|
5945
|
+
} else {
|
|
5946
|
+
setTimeout(renderMermaidDiagrams, 500);
|
|
5947
|
+
}
|
|
5948
|
+
})();
|
|
5724
5949
|
|
|
5725
5950
|
</script>
|
|
5726
5951
|
</body>
|
|
@@ -52,9 +52,22 @@ if (!data.cadrage.scope || (!data.cadrage.scope.inscope?.length && data.cadrage.
|
|
|
52
52
|
outofscope: (gs.outOfScope || []).map(s => typeof s === 'string' ? { name: s, description: '' } : s)
|
|
53
53
|
};
|
|
54
54
|
} else {
|
|
55
|
+
function normScopeItem(s) {
|
|
56
|
+
if (typeof s === 'string') return { name: s, description: '' };
|
|
57
|
+
if (s.name) return s;
|
|
58
|
+
var nm = s.feature || s.label || s.title || JSON.stringify(s);
|
|
59
|
+
var parts = [];
|
|
60
|
+
if (s.priority) parts.push(s.priority.toUpperCase());
|
|
61
|
+
if (s.module) parts.push('Module: ' + s.module);
|
|
62
|
+
return { name: nm, description: parts.join(' — ') };
|
|
63
|
+
}
|
|
55
64
|
data.cadrage.scope = {
|
|
56
|
-
inscope: (gs.inScope || []).map(
|
|
57
|
-
outofscope: (gs.outOfScope || []).map(s
|
|
65
|
+
inscope: (gs.inScope || []).map(normScopeItem),
|
|
66
|
+
outofscope: (gs.outOfScope || []).map(function(s) {
|
|
67
|
+
if (typeof s === 'string') return { name: s, description: '' };
|
|
68
|
+
if (s.name) return s;
|
|
69
|
+
return { name: s.feature || s.reason || JSON.stringify(s), description: s.reason || '' };
|
|
70
|
+
})
|
|
58
71
|
};
|
|
59
72
|
}
|
|
60
73
|
}
|
|
@@ -149,54 +149,14 @@ function renderModuleNavItem(mod) {
|
|
|
149
149
|
var ucCount = (spec.useCases || []).length;
|
|
150
150
|
var brCount = (spec.businessRules || []).length;
|
|
151
151
|
var entCount = (spec.entities || []).length;
|
|
152
|
-
var sections = (mod.anticipatedSections || []).map(function(s) {
|
|
153
|
-
return typeof s === 'string' ? { code: s, name: s, resources: [] } : s;
|
|
154
|
-
});
|
|
155
|
-
var groupId = 'mod-' + code;
|
|
156
|
-
var collapsed = navCollapseState[groupId] === true;
|
|
157
|
-
|
|
158
|
-
var html = '<div class="nav-module" data-group-id="' + groupId + '">';
|
|
159
|
-
|
|
160
|
-
// Module header (clickable to expand + navigate to module spec)
|
|
161
152
|
var totalItems = ucCount + brCount + entCount;
|
|
162
|
-
html += '<a class="nav-item nav-module-header" onclick="toggleNavGroup(\'' + groupId + '\');showSection(\'module-spec-' + code + '\')" data-section="module-spec-' + code + '">';
|
|
163
|
-
html += '<span class="nav-chevron ' + (collapsed ? '' : 'expanded') + '">▸</span> ';
|
|
164
|
-
html += (mod.name || mod.code);
|
|
165
|
-
if (totalItems > 0) html += ' <span class="nav-badge">' + totalItems + '</span>';
|
|
166
|
-
html += '</a>';
|
|
167
|
-
|
|
168
|
-
// Children: sections/resources (navigable sub-tree)
|
|
169
|
-
// Tab-level items (UC, BR, Données, etc.) are NOT shown here — they are accessed
|
|
170
|
-
// via the tab bar in the module content area to avoid redundancy.
|
|
171
|
-
html += '<div class="nav-children"' + (collapsed ? ' style="display:none;"' : '') + '>';
|
|
172
|
-
if (sections.length > 0) {
|
|
173
|
-
sections.forEach(function(section) {
|
|
174
|
-
var resources = section.resources || [];
|
|
175
|
-
var sectionUCs = (section.useCases || []).length;
|
|
176
|
-
var sectionBRs = (section.businessRules || []).length;
|
|
177
|
-
var contentCount = sectionUCs + sectionBRs + resources.length;
|
|
178
|
-
html += '<div class="nav-section-item">';
|
|
179
|
-
html += '<a class="nav-item nav-section-link" onclick="showSection(\'module-spec-' + code + '\');switchTab(\'' + code + '\',\'struct\')" data-section="module-struct-' + code + '-' + section.code + '">';
|
|
180
|
-
html += '<span class="nav-icon nav-icon-section">▷</span> ' + escapeHtml(section.code || section.name || '');
|
|
181
|
-
if (contentCount > 0) html += ' <span class="nav-badge">' + contentCount + '</span>';
|
|
182
|
-
html += '</a>';
|
|
183
|
-
if (resources.length > 0) {
|
|
184
|
-
html += '<div class="nav-children nav-resources">';
|
|
185
|
-
resources.forEach(function(res) {
|
|
186
|
-
var resName = typeof res === 'string' ? res : (res.code || res.name || '');
|
|
187
|
-
html += '<a class="nav-item nav-resource-link" onclick="showSection(\'module-spec-' + code + '\');switchTab(\'' + code + '\',\'mock\');scrollToMockup(\'' + code + '\',\'' + section.code + '\')">';
|
|
188
|
-
html += '<span class="nav-icon nav-icon-resource">•</span> ' + escapeHtml(resName);
|
|
189
|
-
html += '</a>';
|
|
190
|
-
});
|
|
191
|
-
html += '</div>';
|
|
192
|
-
}
|
|
193
|
-
html += '</div>';
|
|
194
|
-
});
|
|
195
|
-
}
|
|
196
153
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
154
|
+
// Flat module link — sections/resources are accessible via tabs (Structure, Maquettes)
|
|
155
|
+
return '<a class="nav-item nav-module-header" onclick="showSection(\'module-spec-' + code + '\')" data-section="module-spec-' + code + '">' +
|
|
156
|
+
'<span class="nav-icon">●</span> ' +
|
|
157
|
+
(mod.name || mod.code) +
|
|
158
|
+
(totalItems > 0 ? ' <span class="nav-badge">' + totalItems + '</span>' : '') +
|
|
159
|
+
'</a>';
|
|
200
160
|
}
|
|
201
161
|
|
|
202
162
|
function renderModuleTabNavItem(code, tabId, label, badge) {
|