@atlashub/smartstack-cli 4.18.0 → 4.19.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/package.json +1 -1
- package/templates/agents/ba-reader.md +86 -80
- package/templates/agents/ba-writer.md +318 -415
- package/templates/agents/docs-context-reader.md +3 -3
- package/templates/mcp-scaffolding/frontend/nav-routes.ts.hbs +133 -0
- package/templates/mcp-scaffolding/frontend/routes.tsx.hbs +126 -0
- package/templates/skills/apex/SKILL.md +29 -16
- package/templates/skills/apex/_shared.md +62 -9
- package/templates/skills/apex/references/analysis-methods.md +8 -6
- package/templates/skills/apex/references/challenge-questions.md +5 -5
- package/templates/skills/apex/references/core-seed-data.md +68 -45
- package/templates/skills/apex/references/frontend-route-wiring-app-tsx.md +26 -21
- package/templates/skills/apex/references/parallel-execution.md +156 -0
- package/templates/skills/apex/references/person-extension-pattern.md +12 -12
- package/templates/skills/apex/references/post-checks.md +1748 -1726
- package/templates/skills/apex/references/smartstack-api.md +63 -57
- package/templates/skills/apex/references/smartstack-frontend-compliance.md +594 -0
- package/templates/skills/apex/references/smartstack-frontend.md +1246 -1842
- package/templates/skills/apex/references/smartstack-layers.md +98 -145
- package/templates/skills/apex/steps/step-00-init.md +30 -6
- package/templates/skills/apex/steps/step-01-analyze.md +27 -23
- package/templates/skills/apex/steps/step-02-plan.md +12 -12
- package/templates/skills/apex/steps/step-03-execute.md +198 -143
- package/templates/skills/apex/steps/step-04-examine.md +24 -93
- package/templates/skills/apex/steps/step-05-deep-review.md +16 -16
- package/templates/skills/apex/steps/step-06-resolve.md +9 -9
- package/templates/skills/apex/steps/step-07-tests.md +3 -1
- package/templates/skills/apex/steps/step-08-run-tests.md +1 -1
- package/templates/skills/business-analyse/SKILL.md +182 -301
- package/templates/skills/business-analyse/_shared.md +119 -336
- package/templates/skills/business-analyse/html/ba-interactive.html +703 -82
- package/templates/skills/business-analyse/html/build-html.js +41 -3
- package/templates/skills/business-analyse/html/src/partials/cadrage-context.html +34 -0
- package/templates/skills/business-analyse/html/src/partials/cadrage-risks.html +48 -0
- package/templates/skills/business-analyse/html/src/partials/cadrage-scope.html +49 -0
- package/templates/skills/business-analyse/html/src/partials/cadrage-stakeholders.html +55 -0
- package/templates/skills/business-analyse/html/src/partials/cadrage-success.html +34 -0
- package/templates/skills/business-analyse/html/src/partials/consol-datamodel.html +8 -0
- package/templates/skills/business-analyse/html/src/partials/consol-flows.html +29 -0
- package/templates/skills/business-analyse/html/src/partials/consol-interactions.html +8 -0
- package/templates/skills/business-analyse/html/src/partials/consol-permissions.html +8 -0
- package/templates/skills/business-analyse/html/src/partials/decomp-dependencies.html +38 -0
- package/templates/skills/business-analyse/html/src/partials/decomp-modules.html +51 -0
- package/templates/skills/business-analyse/html/src/partials/handoff-summary.html +24 -0
- package/templates/skills/business-analyse/html/src/partials/module-spec-container.html +4 -0
- package/templates/skills/business-analyse/html/src/scripts/01-data-init.js +17 -1
- package/templates/skills/business-analyse/html/src/scripts/02-navigation.js +31 -5
- package/templates/skills/business-analyse/html/src/scripts/05-render-specs.js +100 -63
- package/templates/skills/business-analyse/html/src/scripts/06-render-mockups.js +372 -0
- package/templates/skills/business-analyse/html/src/scripts/10-comments.js +41 -13
- package/templates/skills/business-analyse/html/src/styles/09-mockups-html.css +136 -0
- package/templates/skills/business-analyse/patterns/suggestion-catalog.md +7 -5
- package/templates/skills/business-analyse/questionnaire/02-stakeholders-scope.md +142 -0
- package/templates/skills/business-analyse/questionnaire/03-data-ui.md +94 -0
- package/templates/skills/business-analyse/questionnaire/04-risks-metrics.md +150 -0
- package/templates/skills/business-analyse/questionnaire/05-cross-module.md +69 -0
- package/templates/skills/business-analyse/questionnaire.md +23 -280
- package/templates/skills/business-analyse/react/application-viewer.md +2 -2
- package/templates/skills/business-analyse/react/components.md +4 -4
- package/templates/skills/business-analyse/react/i18n-template.md +1 -1
- package/templates/skills/business-analyse/react/schema.md +14 -14
- package/templates/skills/business-analyse/references/acceptance-criteria.md +21 -21
- package/templates/skills/business-analyse/references/analysis-semantic-checks.md +3 -3
- package/templates/skills/business-analyse/references/compilation-structure-cards.md +1 -1
- package/templates/skills/business-analyse/references/consolidation-structural-checks.md +5 -5
- package/templates/skills/business-analyse/references/deploy-data-build.md +12 -11
- package/templates/skills/business-analyse/references/deploy-modes.md +10 -10
- package/templates/skills/business-analyse/references/detection-strategies.md +6 -6
- package/templates/skills/business-analyse/references/html-data-mapping.md +15 -15
- package/templates/skills/business-analyse/references/naming-conventions.md +4 -4
- package/templates/skills/business-analyse/references/review-data-mapping.md +29 -29
- package/templates/skills/business-analyse/references/robustness-checks.md +36 -36
- package/templates/skills/business-analyse/references/spec-auto-inference.md +2 -2
- package/templates/skills/business-analyse/references/ui-dashboard-spec.md +1 -1
- package/templates/skills/business-analyse/references/ui-resource-cards.md +1 -1
- package/templates/skills/business-analyse/references/validation-checklist.md +3 -3
- package/templates/skills/business-analyse/references/wireframe-svg-style-guide.md +2 -2
- package/templates/skills/business-analyse/schemas/application-schema.json +8 -8
- package/templates/skills/business-analyse/schemas/feature-schema.json +3 -3
- package/templates/skills/business-analyse/schemas/index-schema.json +47 -0
- package/templates/skills/business-analyse/schemas/project-schema.json +6 -6
- package/templates/skills/business-analyse/schemas/sections/analysis-schema.json +1 -1
- package/templates/skills/business-analyse/schemas/sections/handoff-schema.json +5 -3
- package/templates/skills/business-analyse/schemas/sections/metadata-schema.json +4 -4
- package/templates/skills/business-analyse/schemas/sections/specification-schema.json +1 -1
- package/templates/skills/business-analyse/schemas/shared/common-defs.json +4 -4
- package/templates/skills/business-analyse/steps/step-00-init.md +68 -77
- package/templates/skills/business-analyse/steps/step-01-cadrage.md +54 -180
- package/templates/skills/business-analyse/steps/step-02-structure.md +175 -0
- package/templates/skills/business-analyse/steps/step-03-specify.md +198 -0
- package/templates/skills/business-analyse/steps/step-04-consolidate.md +478 -0
- package/templates/skills/business-analyse/steps/step-05-deploy.md +220 -0
- package/templates/skills/business-analyse/steps/step-06-review.md +51 -69
- package/templates/skills/business-analyse/templates/tpl-frd.md +1 -1
- package/templates/skills/business-analyse/templates/tpl-handoff.md +20 -17
- package/templates/skills/business-analyse/templates/tpl-launch-displays.md +2 -2
- package/templates/skills/business-analyse/templates-react.md +2 -2
- package/templates/skills/derive-prd/SKILL.md +92 -0
- package/templates/skills/derive-prd/references/acceptance-criteria.md +169 -0
- package/templates/skills/derive-prd/references/entity-domain-mapping.md +115 -0
- package/templates/skills/{business-analyse → derive-prd}/references/handoff-file-templates.md +131 -120
- package/templates/skills/{business-analyse → derive-prd}/references/handoff-mappings.md +95 -95
- package/templates/skills/{business-analyse → derive-prd}/references/handoff-seeddata-generation.md +312 -312
- package/templates/skills/{business-analyse → derive-prd}/references/prd-generation.md +262 -263
- package/templates/skills/derive-prd/references/readiness-scoring.md +104 -0
- package/templates/skills/derive-prd/schemas/handoff-schema.json +95 -0
- package/templates/skills/derive-prd/steps/step-00-validate.md +130 -0
- package/templates/skills/derive-prd/steps/step-01-transform.md +206 -0
- package/templates/skills/derive-prd/steps/step-02-export.md +181 -0
- package/templates/skills/{business-analyse → derive-prd}/templates/tpl-progress.md +172 -172
- package/templates/skills/ralph-loop/SKILL.md +2 -1
- package/templates/skills/ralph-loop/references/init-resume-recovery.md +1 -1
- package/templates/skills/ralph-loop/steps/step-01-task.md +2 -2
- package/templates/skills/apex/references/agent-teams-protocol.md +0 -203
- package/templates/skills/business-analyse/_architecture.md +0 -124
- package/templates/skills/business-analyse/_elicitation.md +0 -206
- package/templates/skills/business-analyse/_module-loop.md +0 -115
- package/templates/skills/business-analyse/_rules.md +0 -142
- package/templates/skills/business-analyse/_suggestions.md +0 -34
- package/templates/skills/business-analyse/questionnaire/00-application.md +0 -160
- package/templates/skills/business-analyse/questionnaire/00b-project.md +0 -85
- package/templates/skills/business-analyse/questionnaire/02-stakeholders.md +0 -189
- package/templates/skills/business-analyse/questionnaire/03-scope.md +0 -164
- package/templates/skills/business-analyse/questionnaire/04-data.md +0 -88
- package/templates/skills/business-analyse/questionnaire/05-integrations.md +0 -58
- package/templates/skills/business-analyse/questionnaire/06-security.md +0 -68
- package/templates/skills/business-analyse/questionnaire/07-ui.md +0 -76
- package/templates/skills/business-analyse/questionnaire/08-performance.md +0 -42
- package/templates/skills/business-analyse/questionnaire/09-constraints.md +0 -45
- package/templates/skills/business-analyse/questionnaire/10-documentation.md +0 -58
- package/templates/skills/business-analyse/questionnaire/11-data-lifecycle.md +0 -59
- package/templates/skills/business-analyse/questionnaire/12-migration.md +0 -58
- package/templates/skills/business-analyse/questionnaire/13-cross-module.md +0 -69
- package/templates/skills/business-analyse/questionnaire/14-risk-assumptions.md +0 -135
- package/templates/skills/business-analyse/questionnaire/15-success-metrics.md +0 -136
- package/templates/skills/business-analyse/references/agent-module-prompt.md +0 -366
- package/templates/skills/business-analyse/references/agent-pooling-best-practices.md +0 -557
- package/templates/skills/business-analyse/references/cache-warming-strategy.md +0 -566
- package/templates/skills/business-analyse/references/cadrage-challenge-patterns.md +0 -41
- package/templates/skills/business-analyse/references/cadrage-coverage-matrix.md +0 -74
- package/templates/skills/business-analyse/references/cadrage-pre-analysis.md +0 -115
- package/templates/skills/business-analyse/references/cadrage-shared-modules.md +0 -68
- package/templates/skills/business-analyse/references/cadrage-structure-cards.md +0 -85
- package/templates/skills/business-analyse/references/team-orchestration.md +0 -1093
- package/templates/skills/business-analyse/references/validate-incremental-html.md +0 -121
- package/templates/skills/business-analyse/steps/step-01b-applications.md +0 -419
- package/templates/skills/business-analyse/steps/step-02-decomposition.md +0 -387
- package/templates/skills/business-analyse/steps/step-03a-data.md +0 -16
- package/templates/skills/business-analyse/steps/step-03a1-setup.md +0 -486
- package/templates/skills/business-analyse/steps/step-03a2-analysis.md +0 -300
- package/templates/skills/business-analyse/steps/step-03b-ui.md +0 -405
- package/templates/skills/business-analyse/steps/step-03c-compile.md +0 -516
- package/templates/skills/business-analyse/steps/step-03d-validate.md +0 -691
- package/templates/skills/business-analyse/steps/step-04-consolidation.md +0 -17
- package/templates/skills/business-analyse/steps/step-04a-collect.md +0 -415
- package/templates/skills/business-analyse/steps/step-04b-analyze.md +0 -163
- package/templates/skills/business-analyse/steps/step-04c-decide.md +0 -186
- package/templates/skills/business-analyse/steps/step-05a-handoff.md +0 -937
- package/templates/skills/business-analyse/steps/step-05b-deploy.md +0 -522
- package/templates/skills/business-analyse/steps/step-05c-ralph-readiness.md +0 -703
|
@@ -1633,6 +1633,145 @@ body {
|
|
|
1633
1633
|
box-shadow: -4px 0 20px rgba(0,0,0,0.3);
|
|
1634
1634
|
}
|
|
1635
1635
|
}
|
|
1636
|
+
|
|
1637
|
+
|
|
1638
|
+
/* --- 09-mockups-html.css --- */
|
|
1639
|
+
/* ============================================
|
|
1640
|
+
HTML MOCKUPS - Realistic component previews
|
|
1641
|
+
============================================ */
|
|
1642
|
+
|
|
1643
|
+
/* Screen section container */
|
|
1644
|
+
.screen-section {
|
|
1645
|
+
margin-bottom: 2rem;
|
|
1646
|
+
}
|
|
1647
|
+
|
|
1648
|
+
.screen-section h3 {
|
|
1649
|
+
display: flex;
|
|
1650
|
+
align-items: center;
|
|
1651
|
+
gap: 0.4rem;
|
|
1652
|
+
}
|
|
1653
|
+
|
|
1654
|
+
/* Mockup frame enhancements for HTML mockups */
|
|
1655
|
+
.mockup-frame .mock-header {
|
|
1656
|
+
margin-bottom: 1rem;
|
|
1657
|
+
}
|
|
1658
|
+
|
|
1659
|
+
/* SmartTable inside mockups */
|
|
1660
|
+
.mockup-content .mock-table {
|
|
1661
|
+
border: 1px solid var(--border);
|
|
1662
|
+
border-radius: 6px;
|
|
1663
|
+
overflow: hidden;
|
|
1664
|
+
}
|
|
1665
|
+
|
|
1666
|
+
.mockup-content .mock-table th {
|
|
1667
|
+
background: var(--bg-hover);
|
|
1668
|
+
}
|
|
1669
|
+
|
|
1670
|
+
/* SmartForm tabs */
|
|
1671
|
+
.mockup-content .form-tab-bar {
|
|
1672
|
+
display: flex;
|
|
1673
|
+
gap: 0;
|
|
1674
|
+
border-bottom: 1px solid var(--border);
|
|
1675
|
+
margin-bottom: 1.5rem;
|
|
1676
|
+
}
|
|
1677
|
+
|
|
1678
|
+
.mockup-content .form-tab {
|
|
1679
|
+
padding: 0.5rem 1rem;
|
|
1680
|
+
font-size: 0.85rem;
|
|
1681
|
+
cursor: pointer;
|
|
1682
|
+
border-bottom: 2px solid transparent;
|
|
1683
|
+
color: var(--text-muted);
|
|
1684
|
+
}
|
|
1685
|
+
|
|
1686
|
+
.mockup-content .form-tab.active {
|
|
1687
|
+
border-bottom-color: var(--primary);
|
|
1688
|
+
color: var(--primary-light);
|
|
1689
|
+
}
|
|
1690
|
+
|
|
1691
|
+
/* SmartKanban columns */
|
|
1692
|
+
.mockup-content .kanban-board {
|
|
1693
|
+
display: flex;
|
|
1694
|
+
gap: 1rem;
|
|
1695
|
+
overflow-x: auto;
|
|
1696
|
+
padding-bottom: 0.5rem;
|
|
1697
|
+
}
|
|
1698
|
+
|
|
1699
|
+
.mockup-content .kanban-column {
|
|
1700
|
+
min-width: 200px;
|
|
1701
|
+
flex: 1;
|
|
1702
|
+
background: var(--bg-hover);
|
|
1703
|
+
border-radius: 8px;
|
|
1704
|
+
padding: 0.75rem;
|
|
1705
|
+
}
|
|
1706
|
+
|
|
1707
|
+
.mockup-content .kanban-column-header {
|
|
1708
|
+
font-weight: 600;
|
|
1709
|
+
font-size: 0.85rem;
|
|
1710
|
+
color: var(--text-bright);
|
|
1711
|
+
margin-bottom: 0.75rem;
|
|
1712
|
+
display: flex;
|
|
1713
|
+
justify-content: space-between;
|
|
1714
|
+
}
|
|
1715
|
+
|
|
1716
|
+
.mockup-content .kanban-card {
|
|
1717
|
+
background: var(--bg-card);
|
|
1718
|
+
border: 1px solid var(--border);
|
|
1719
|
+
border-radius: 6px;
|
|
1720
|
+
padding: 0.5rem;
|
|
1721
|
+
margin-bottom: 0.5rem;
|
|
1722
|
+
font-size: 0.8rem;
|
|
1723
|
+
}
|
|
1724
|
+
|
|
1725
|
+
/* SmartDashboard KPI */
|
|
1726
|
+
.mockup-content .mock-kpi-grid {
|
|
1727
|
+
margin-bottom: 1.5rem;
|
|
1728
|
+
}
|
|
1729
|
+
|
|
1730
|
+
/* SmartFilter pills */
|
|
1731
|
+
.mockup-content .filter-pill {
|
|
1732
|
+
padding: 0.3rem 0.7rem;
|
|
1733
|
+
border-radius: 16px;
|
|
1734
|
+
font-size: 0.8rem;
|
|
1735
|
+
cursor: pointer;
|
|
1736
|
+
transition: all var(--transition-fast);
|
|
1737
|
+
}
|
|
1738
|
+
|
|
1739
|
+
.mockup-content .filter-pill:hover {
|
|
1740
|
+
background: var(--bg-hover);
|
|
1741
|
+
border-color: var(--primary);
|
|
1742
|
+
}
|
|
1743
|
+
|
|
1744
|
+
.mockup-content .filter-pill.active {
|
|
1745
|
+
background: var(--primary);
|
|
1746
|
+
color: #fff;
|
|
1747
|
+
border-color: var(--primary);
|
|
1748
|
+
}
|
|
1749
|
+
|
|
1750
|
+
/* Subtable in forms */
|
|
1751
|
+
.mockup-content .subtable-container {
|
|
1752
|
+
margin: 1rem 0;
|
|
1753
|
+
border: 1px solid var(--border);
|
|
1754
|
+
border-radius: 8px;
|
|
1755
|
+
overflow: hidden;
|
|
1756
|
+
}
|
|
1757
|
+
|
|
1758
|
+
.mockup-content .subtable-header {
|
|
1759
|
+
display: flex;
|
|
1760
|
+
justify-content: space-between;
|
|
1761
|
+
align-items: center;
|
|
1762
|
+
padding: 0.5rem 0.75rem;
|
|
1763
|
+
background: var(--bg-hover);
|
|
1764
|
+
}
|
|
1765
|
+
|
|
1766
|
+
/* Permission annotation in mockup toolbar */
|
|
1767
|
+
.mockup-toolbar .permission-badge {
|
|
1768
|
+
margin-left: auto;
|
|
1769
|
+
font-size: 0.65rem;
|
|
1770
|
+
color: var(--text-muted);
|
|
1771
|
+
background: var(--bg-dark);
|
|
1772
|
+
padding: 0.15rem 0.5rem;
|
|
1773
|
+
border-radius: 4px;
|
|
1774
|
+
}
|
|
1636
1775
|
|
|
1637
1776
|
</style>
|
|
1638
1777
|
</head>
|
|
@@ -2147,6 +2286,9 @@ let data = {{FEATURE_DATA}};
|
|
|
2147
2286
|
const ORIGINAL_DATA = JSON.parse(JSON.stringify(data));
|
|
2148
2287
|
const EMBEDDED_ARTIFACTS = {{EMBEDDED_ARTIFACTS}};
|
|
2149
2288
|
|
|
2289
|
+
// Initialize applications array (multi-app support)
|
|
2290
|
+
data.applications = data.applications || [];
|
|
2291
|
+
|
|
2150
2292
|
// Initialize optional data structures
|
|
2151
2293
|
data.wireframeComments = data.wireframeComments || {};
|
|
2152
2294
|
data.specComments = data.specComments || {};
|
|
@@ -2173,7 +2315,7 @@ data.cadrage.context = data.cadrage.context || { problem: '', trigger: '', curre
|
|
|
2173
2315
|
// Initialize comments array
|
|
2174
2316
|
data.comments = data.comments || [];
|
|
2175
2317
|
|
|
2176
|
-
// Defensive mapping: globalScope (
|
|
2318
|
+
// Defensive mapping: globalScope (JSON format) -> scope (HTML format)
|
|
2177
2319
|
// Handles cases where FEATURE_DATA contains raw globalScope instead of pre-mapped scope
|
|
2178
2320
|
if (!data.cadrage.scope || (!data.cadrage.scope.vital?.length && data.cadrage.globalScope)) {
|
|
2179
2321
|
const gs = data.cadrage.globalScope || {};
|
|
@@ -2186,6 +2328,14 @@ if (!data.cadrage.scope || (!data.cadrage.scope.vital?.length && data.cadrage.gl
|
|
|
2186
2328
|
}
|
|
2187
2329
|
data.cadrage.scope = data.cadrage.scope || { vital: [], important: [], optional: [], excluded: [] };
|
|
2188
2330
|
|
|
2331
|
+
// Backward compat: mustHave/shouldHave/couldHave/wontHave → vital/important/optional/excluded
|
|
2332
|
+
if (data.cadrage.scope.mustHave && !data.cadrage.scope.vital?.length) {
|
|
2333
|
+
data.cadrage.scope.vital = data.cadrage.scope.mustHave;
|
|
2334
|
+
data.cadrage.scope.important = data.cadrage.scope.shouldHave || data.cadrage.scope.important || [];
|
|
2335
|
+
data.cadrage.scope.optional = data.cadrage.scope.couldHave || data.cadrage.scope.optional || [];
|
|
2336
|
+
data.cadrage.scope.excluded = data.cadrage.scope.wontHave || data.cadrage.scope.excluded || [];
|
|
2337
|
+
}
|
|
2338
|
+
|
|
2189
2339
|
// Defensive init: moduleSpecs (may be missing if LLM didn't follow mapping)
|
|
2190
2340
|
data.moduleSpecs = data.moduleSpecs || {};
|
|
2191
2341
|
// Ensure ALL modules have a moduleSpecs entry (prevents missing schemas)
|
|
@@ -2195,6 +2345,11 @@ data.moduleSpecs = data.moduleSpecs || {};
|
|
|
2195
2345
|
}
|
|
2196
2346
|
// Ensure anticipatedSections array exists
|
|
2197
2347
|
m.anticipatedSections = m.anticipatedSections || [];
|
|
2348
|
+
m.applicationCode = m.applicationCode || '';
|
|
2349
|
+
// Initialize screens array for interface specs
|
|
2350
|
+
if (!data.moduleSpecs[m.code].screens) {
|
|
2351
|
+
data.moduleSpecs[m.code].screens = [];
|
|
2352
|
+
}
|
|
2198
2353
|
});
|
|
2199
2354
|
|
|
2200
2355
|
// Vibe coding mode: hide non-relevant sections
|
|
@@ -2345,12 +2500,38 @@ function buildNavTree() {
|
|
|
2345
2500
|
const nav = document.getElementById('sidebarNav');
|
|
2346
2501
|
if (!nav) return;
|
|
2347
2502
|
|
|
2348
|
-
|
|
2349
|
-
renderNavGroup('cadrage', 'Cadrage', buildCadrageItems()) +
|
|
2350
|
-
renderNavGroup('modules', 'Modules (' + data.modules.length + ')', buildModuleItems()) +
|
|
2351
|
-
renderNavGroup('consolidation', 'Consolidation', buildConsolidationItems()) +
|
|
2352
|
-
renderNavGroup('synthese', 'Synthese', buildSyntheseItems());
|
|
2503
|
+
var html = renderNavGroup('cadrage', 'Cadrage', buildCadrageItems());
|
|
2353
2504
|
|
|
2505
|
+
// Multi-app: group modules by application
|
|
2506
|
+
if (data.applications && data.applications.length > 1) {
|
|
2507
|
+
data.applications.forEach(function(app) {
|
|
2508
|
+
var appModules = data.modules.filter(function(m) { return m.applicationCode === app.code; });
|
|
2509
|
+
var appModuleItems = '';
|
|
2510
|
+
appModules.forEach(function(mod) {
|
|
2511
|
+
appModuleItems += renderModuleNavItem(mod);
|
|
2512
|
+
});
|
|
2513
|
+
// Global views at bottom of each app group
|
|
2514
|
+
appModuleItems += renderNavItem('decomp-modules', 'Vue d\'ensemble', data.modules.length);
|
|
2515
|
+
html += renderNavGroup('app-' + app.code, app.name || app.code, appModuleItems);
|
|
2516
|
+
});
|
|
2517
|
+
// Modules without applicationCode
|
|
2518
|
+
var orphanModules = data.modules.filter(function(m) { return !m.applicationCode; });
|
|
2519
|
+
if (orphanModules.length > 0) {
|
|
2520
|
+
var orphanItems = '';
|
|
2521
|
+
orphanModules.forEach(function(mod) {
|
|
2522
|
+
orphanItems += renderModuleNavItem(mod);
|
|
2523
|
+
});
|
|
2524
|
+
html += renderNavGroup('modules-other', 'Autres modules (' + orphanModules.length + ')', orphanItems);
|
|
2525
|
+
}
|
|
2526
|
+
html += renderNavItem('decomp-dependencies', 'Dependances', data.dependencies.length);
|
|
2527
|
+
} else {
|
|
2528
|
+
html += renderNavGroup('modules', 'Modules (' + data.modules.length + ')', buildModuleItems());
|
|
2529
|
+
}
|
|
2530
|
+
|
|
2531
|
+
html += renderNavGroup('consolidation', 'Consolidation', buildConsolidationItems());
|
|
2532
|
+
html += renderNavGroup('synthese', 'Synthese', buildSyntheseItems());
|
|
2533
|
+
|
|
2534
|
+
nav.innerHTML = html;
|
|
2354
2535
|
restoreNavState();
|
|
2355
2536
|
highlightActiveNavItem();
|
|
2356
2537
|
}
|
|
@@ -3247,7 +3428,10 @@ function renderEntity(code, ent, index) {
|
|
|
3247
3428
|
<tbody>
|
|
3248
3429
|
${ent.attributes.map(a => `<tr><td style="font-weight:500;color:var(--text-bright);">${a.name}</td><td>${a.description || ''}</td></tr>`).join('')}
|
|
3249
3430
|
</tbody>
|
|
3250
|
-
</table
|
|
3431
|
+
</table>
|
|
3432
|
+
<div style="padding:0.3rem 0.75rem;">
|
|
3433
|
+
<button class="add-btn" style="font-size:0.75rem;padding:0.4rem;" onclick="addEntityAttribute('${code}',${index})">+ Ajouter un attribut</button>
|
|
3434
|
+
</div>` : ''}
|
|
3251
3435
|
${(ent.relationships || []).length > 0 ? `
|
|
3252
3436
|
<div style="padding:0.5rem 0.75rem;font-size:0.8rem;color:var(--text-muted);border-top:1px solid var(--border);">
|
|
3253
3437
|
Relations : ${ent.relationships.map(r => `<span style="color:var(--accent);">${r}</span>`).join(', ')}
|
|
@@ -3289,6 +3473,19 @@ function removeEntity(code, index) {
|
|
|
3289
3473
|
autoSave();
|
|
3290
3474
|
}
|
|
3291
3475
|
|
|
3476
|
+
function addEntityAttribute(code, entityIndex) {
|
|
3477
|
+
var attrName = prompt('Nom de l\'attribut :');
|
|
3478
|
+
if (!attrName) return;
|
|
3479
|
+
var attrDesc = prompt('Description (optionnel) :') || '';
|
|
3480
|
+
if (!data.moduleSpecs[code]?.entities?.[entityIndex]) return;
|
|
3481
|
+
if (!data.moduleSpecs[code].entities[entityIndex].attributes) {
|
|
3482
|
+
data.moduleSpecs[code].entities[entityIndex].attributes = [];
|
|
3483
|
+
}
|
|
3484
|
+
data.moduleSpecs[code].entities[entityIndex].attributes.push({ name: attrName, description: attrDesc });
|
|
3485
|
+
renderAllModuleSpecs();
|
|
3486
|
+
autoSave();
|
|
3487
|
+
}
|
|
3488
|
+
|
|
3292
3489
|
function getSpecComment(code, type, index) {
|
|
3293
3490
|
const key = code + '.' + type + '.' + index;
|
|
3294
3491
|
return data.specComments[key] || '';
|
|
@@ -3311,8 +3508,25 @@ function updateWireframeComment(code, screen, value) {
|
|
|
3311
3508
|
}
|
|
3312
3509
|
|
|
3313
3510
|
function renderModuleMockups(code) {
|
|
3314
|
-
|
|
3511
|
+
var spec = data.moduleSpecs[code] || {};
|
|
3512
|
+
var screens = spec.screens || [];
|
|
3513
|
+
var wireframes = EMBEDDED_ARTIFACTS?.wireframes?.[code] || [];
|
|
3514
|
+
|
|
3515
|
+
// Priority 1: HTML mockups from screens[] specs
|
|
3516
|
+
if (screens.length > 0) {
|
|
3517
|
+
var html = '';
|
|
3518
|
+
if (typeof renderScreenMockups === 'function') {
|
|
3519
|
+
html = renderScreenMockups(code);
|
|
3520
|
+
}
|
|
3521
|
+
// Also show wireframes below if available
|
|
3522
|
+
if (wireframes.length > 0) {
|
|
3523
|
+
html += '<h3 style="color:var(--text-bright);font-size:1rem;margin:2rem 0 1rem;">Wireframes</h3>';
|
|
3524
|
+
html += wireframes.map(function(wf, i) { return renderWireframeMockup(code, wf, i); }).join('');
|
|
3525
|
+
}
|
|
3526
|
+
return html;
|
|
3527
|
+
}
|
|
3315
3528
|
|
|
3529
|
+
// Priority 2: Wireframes from EMBEDDED_ARTIFACTS
|
|
3316
3530
|
if (wireframes.length === 0) {
|
|
3317
3531
|
return `
|
|
3318
3532
|
<div class="card" style="text-align:center;padding:2rem;color:var(--text-muted);">
|
|
@@ -3321,69 +3535,73 @@ function renderModuleMockups(code) {
|
|
|
3321
3535
|
</div>`;
|
|
3322
3536
|
}
|
|
3323
3537
|
|
|
3324
|
-
return wireframes.map((wf, i)
|
|
3325
|
-
|
|
3326
|
-
const wireframeId = `wf-${code}-${i}`;
|
|
3538
|
+
return wireframes.map(function(wf, i) { return renderWireframeMockup(code, wf, i); }).join('');
|
|
3539
|
+
}
|
|
3327
3540
|
|
|
3328
|
-
|
|
3329
|
-
|
|
3330
|
-
|
|
3331
|
-
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
|
|
3335
|
-
|
|
3336
|
-
|
|
3337
|
-
|
|
3338
|
-
|
|
3339
|
-
|
|
3340
|
-
|
|
3341
|
-
|
|
3342
|
-
${
|
|
3343
|
-
? `<div class="svg-wireframe wireframe-view active" data-view="svg">${wf.svgContent}</div>
|
|
3344
|
-
<pre class="ascii-wireframe wireframe-view" data-view="ascii" style="display:none;">${wf.content || ''}</pre>`
|
|
3345
|
-
: (wf.format === 'ascii'
|
|
3346
|
-
? `<pre class="ascii-wireframe">${wf.content || ''}</pre>`
|
|
3347
|
-
: `<div class="svg-wireframe">${wf.content || ''}</div>`)}
|
|
3348
|
-
</div>
|
|
3349
|
-
${wf.description ? `
|
|
3350
|
-
<div class="wireframe-description">
|
|
3351
|
-
<strong>Description:</strong> ${wf.description}
|
|
3352
|
-
</div>` : ''}
|
|
3353
|
-
${(wf.elements || []).length > 0 ? `
|
|
3354
|
-
<div class="wireframe-metadata">
|
|
3355
|
-
<div><strong>Elements:</strong> ${wf.elements.map(e => typeof e === 'string' ? e : (e.type || e.label || e.id || '')).filter(Boolean).join(', ')}</div>
|
|
3541
|
+
function renderWireframeMockup(code, wf, i) {
|
|
3542
|
+
const hasSvg = !!wf.svgContent;
|
|
3543
|
+
const wireframeId = `wf-${code}-${i}`;
|
|
3544
|
+
|
|
3545
|
+
return `
|
|
3546
|
+
<div class="mockup-frame" style="${i > 0 ? 'margin-top:1.5rem;' : ''}">
|
|
3547
|
+
<div class="mockup-toolbar">
|
|
3548
|
+
<div class="mockup-dot mockup-dot-red"></div>
|
|
3549
|
+
<div class="mockup-dot mockup-dot-yellow"></div>
|
|
3550
|
+
<div class="mockup-dot mockup-dot-green"></div>
|
|
3551
|
+
<span class="mockup-title">${wf.screen || wf.section}</span>
|
|
3552
|
+
${hasSvg ? `
|
|
3553
|
+
<div class="wireframe-toggle">
|
|
3554
|
+
<button class="wireframe-toggle-btn active" data-target="${wireframeId}" data-view="svg" onclick="toggleWireframeView('${wireframeId}', 'svg')">SVG</button>
|
|
3555
|
+
<button class="wireframe-toggle-btn" data-target="${wireframeId}" data-view="ascii" onclick="toggleWireframeView('${wireframeId}', 'ascii')">ASCII</button>
|
|
3356
3556
|
</div>` : ''}
|
|
3357
|
-
${(() => {
|
|
3358
|
-
const cm = wf.componentMapping;
|
|
3359
|
-
const mappings = Array.isArray(cm) ? cm
|
|
3360
|
-
: (typeof cm === 'object' && cm !== null) ? Object.entries(cm).map(([k,v]) => ({wireframeElement: k, reactComponent: v}))
|
|
3361
|
-
: [];
|
|
3362
|
-
return mappings.length > 0 ? `
|
|
3363
|
-
<details class="wireframe-details">
|
|
3364
|
-
<summary>Mapping composants SmartStack</summary>
|
|
3365
|
-
<table class="mapping-table">
|
|
3366
|
-
<thead><tr><th>Element maquette</th><th>Composant React</th></tr></thead>
|
|
3367
|
-
<tbody>
|
|
3368
|
-
${mappings.map(m =>
|
|
3369
|
-
'<tr><td>' + (m.wireframeElement || '') + '</td><td><code>' + (m.reactComponent || '') + '</code></td></tr>'
|
|
3370
|
-
).join('')}
|
|
3371
|
-
</tbody>
|
|
3372
|
-
</table>
|
|
3373
|
-
</details>` : '';
|
|
3374
|
-
})()}
|
|
3375
|
-
<div class="wireframe-comment">
|
|
3376
|
-
<label style="font-size:0.8rem;color:var(--text-muted);display:block;margin-bottom:0.3rem;">Commentaire / Feedback :</label>
|
|
3377
|
-
<textarea class="form-textarea"
|
|
3378
|
-
data-module="${code}"
|
|
3379
|
-
data-screen="${wf.screen}"
|
|
3380
|
-
placeholder="Ajouter un commentaire sur cette maquette (ex: deplacer ce bouton, ajouter une colonne...)"
|
|
3381
|
-
onblur="updateWireframeComment('${code}', '${wf.screen}', this.value)"
|
|
3382
|
-
style="min-height:60px;font-size:0.85rem;resize:vertical;"
|
|
3383
|
-
>${getWireframeComment(code, wf.screen)}</textarea>
|
|
3384
|
-
</div>
|
|
3385
3557
|
</div>
|
|
3386
|
-
|
|
3558
|
+
<div class="mockup-content" id="${wireframeId}">
|
|
3559
|
+
${hasSvg
|
|
3560
|
+
? `<div class="svg-wireframe wireframe-view active" data-view="svg">${wf.svgContent}</div>
|
|
3561
|
+
<pre class="ascii-wireframe wireframe-view" data-view="ascii" style="display:none;">${wf.content || ''}</pre>`
|
|
3562
|
+
: (wf.format === 'ascii'
|
|
3563
|
+
? `<pre class="ascii-wireframe">${wf.content || ''}</pre>`
|
|
3564
|
+
: `<div class="svg-wireframe">${wf.content || ''}</div>`)}
|
|
3565
|
+
</div>
|
|
3566
|
+
${wf.description ? `
|
|
3567
|
+
<div class="wireframe-description">
|
|
3568
|
+
<strong>Description:</strong> ${wf.description}
|
|
3569
|
+
</div>` : ''}
|
|
3570
|
+
${(wf.elements || []).length > 0 ? `
|
|
3571
|
+
<div class="wireframe-metadata">
|
|
3572
|
+
<div><strong>Elements:</strong> ${wf.elements.map(e => typeof e === 'string' ? e : (e.type || e.label || e.id || '')).filter(Boolean).join(', ')}</div>
|
|
3573
|
+
</div>` : ''}
|
|
3574
|
+
${(() => {
|
|
3575
|
+
const cm = wf.componentMapping;
|
|
3576
|
+
const mappings = Array.isArray(cm) ? cm
|
|
3577
|
+
: (typeof cm === 'object' && cm !== null) ? Object.entries(cm).map(([k,v]) => ({wireframeElement: k, reactComponent: v}))
|
|
3578
|
+
: [];
|
|
3579
|
+
return mappings.length > 0 ? `
|
|
3580
|
+
<details class="wireframe-details">
|
|
3581
|
+
<summary>Mapping composants SmartStack</summary>
|
|
3582
|
+
<table class="mapping-table">
|
|
3583
|
+
<thead><tr><th>Element maquette</th><th>Composant React</th></tr></thead>
|
|
3584
|
+
<tbody>
|
|
3585
|
+
${mappings.map(m =>
|
|
3586
|
+
'<tr><td>' + (m.wireframeElement || '') + '</td><td><code>' + (m.reactComponent || '') + '</code></td></tr>'
|
|
3587
|
+
).join('')}
|
|
3588
|
+
</tbody>
|
|
3589
|
+
</table>
|
|
3590
|
+
</details>` : '';
|
|
3591
|
+
})()}
|
|
3592
|
+
<div class="wireframe-comment">
|
|
3593
|
+
<label style="font-size:0.8rem;color:var(--text-muted);display:block;margin-bottom:0.3rem;">Commentaire / Feedback :</label>
|
|
3594
|
+
<textarea class="form-textarea"
|
|
3595
|
+
data-module="${code}"
|
|
3596
|
+
data-screen="${wf.screen}"
|
|
3597
|
+
placeholder="Ajouter un commentaire sur cette maquette (ex: deplacer ce bouton, ajouter une colonne...)"
|
|
3598
|
+
onblur="updateWireframeComment('${code}', '${wf.screen}', this.value)"
|
|
3599
|
+
style="min-height:60px;font-size:0.85rem;resize:vertical;"
|
|
3600
|
+
>${getWireframeComment(code, wf.screen)}</textarea>
|
|
3601
|
+
</div>
|
|
3602
|
+
</div>
|
|
3603
|
+
`;
|
|
3604
|
+
}
|
|
3387
3605
|
}
|
|
3388
3606
|
|
|
3389
3607
|
function toggleWireframeView(wireframeId, view) {
|
|
@@ -3407,7 +3625,7 @@ function toggleWireframeView(wireframeId, view) {
|
|
|
3407
3625
|
}
|
|
3408
3626
|
|
|
3409
3627
|
function getPermRoles() {
|
|
3410
|
-
// Extract roles from actual permission data (handles English role names from
|
|
3628
|
+
// Extract roles from actual permission data (handles English role names from JSON data)
|
|
3411
3629
|
const rolesFromPerms = [];
|
|
3412
3630
|
const seen = new Set();
|
|
3413
3631
|
data.modules.forEach(m => {
|
|
@@ -3779,6 +3997,381 @@ function renderE2EFlows() {
|
|
|
3779
3997
|
}
|
|
3780
3998
|
|
|
3781
3999
|
|
|
4000
|
+
/* --- 06-render-mockups.js --- */
|
|
4001
|
+
/* ============================================
|
|
4002
|
+
HTML MOCKUP RENDERER
|
|
4003
|
+
Generates realistic HTML mockups from screens[] specs
|
|
4004
|
+
============================================ */
|
|
4005
|
+
|
|
4006
|
+
function renderScreenMockups(code) {
|
|
4007
|
+
var spec = data.moduleSpecs[code] || {};
|
|
4008
|
+
var screens = spec.screens || [];
|
|
4009
|
+
|
|
4010
|
+
if (screens.length === 0) return '';
|
|
4011
|
+
|
|
4012
|
+
return screens.map(function(screen, si) {
|
|
4013
|
+
var resources = screen.resources || [];
|
|
4014
|
+
return '<div class="screen-section" style="margin-bottom:2rem;">' +
|
|
4015
|
+
'<h3 style="color:var(--text-bright);font-size:1rem;margin-bottom:1rem;">' +
|
|
4016
|
+
'<span style="color:var(--accent);">▸</span> ' + (screen.sectionLabel || screen.sectionCode) +
|
|
4017
|
+
'</h3>' +
|
|
4018
|
+
resources.map(function(res, ri) {
|
|
4019
|
+
return renderResourceMockup(code, screen.sectionCode, res, ri);
|
|
4020
|
+
}).join('') +
|
|
4021
|
+
'</div>';
|
|
4022
|
+
}).join('');
|
|
4023
|
+
}
|
|
4024
|
+
|
|
4025
|
+
function renderResourceMockup(code, sectionCode, res, index) {
|
|
4026
|
+
var mockupId = 'mockup-' + code + '-' + sectionCode + '-' + index;
|
|
4027
|
+
var html = '<div class="mockup-frame" style="margin-bottom:1.5rem;">';
|
|
4028
|
+
|
|
4029
|
+
// Browser chrome
|
|
4030
|
+
html += '<div class="mockup-toolbar">';
|
|
4031
|
+
html += '<div class="mockup-dot mockup-dot-red"></div>';
|
|
4032
|
+
html += '<div class="mockup-dot mockup-dot-yellow"></div>';
|
|
4033
|
+
html += '<div class="mockup-dot mockup-dot-green"></div>';
|
|
4034
|
+
html += '<span class="mockup-title">' + (res.label || res.code) + ' (' + res.type + ')</span>';
|
|
4035
|
+
if (res.permission) {
|
|
4036
|
+
html += '<span style="margin-left:auto;font-size:0.65rem;color:var(--text-muted);background:var(--bg-dark);padding:0.15rem 0.5rem;border-radius:4px;">' + res.permission + '</span>';
|
|
4037
|
+
}
|
|
4038
|
+
html += '</div>';
|
|
4039
|
+
|
|
4040
|
+
// Mockup content
|
|
4041
|
+
html += '<div class="mockup-content" id="' + mockupId + '">';
|
|
4042
|
+
switch (res.type) {
|
|
4043
|
+
case 'SmartTable':
|
|
4044
|
+
html += renderSmartTableMockup(res);
|
|
4045
|
+
break;
|
|
4046
|
+
case 'SmartForm':
|
|
4047
|
+
html += renderSmartFormMockup(res);
|
|
4048
|
+
break;
|
|
4049
|
+
case 'SmartCard':
|
|
4050
|
+
html += renderSmartCardMockup(res);
|
|
4051
|
+
break;
|
|
4052
|
+
case 'SmartKanban':
|
|
4053
|
+
html += renderSmartKanbanMockup(res);
|
|
4054
|
+
break;
|
|
4055
|
+
case 'SmartDashboard':
|
|
4056
|
+
html += renderSmartDashboardMockup(res);
|
|
4057
|
+
break;
|
|
4058
|
+
case 'SmartFilter':
|
|
4059
|
+
html += renderSmartFilterMockup(res);
|
|
4060
|
+
break;
|
|
4061
|
+
default:
|
|
4062
|
+
html += '<div style="padding:2rem;text-align:center;color:var(--text-muted);">Composant ' + res.type + ' - maquette non disponible</div>';
|
|
4063
|
+
}
|
|
4064
|
+
html += '</div>';
|
|
4065
|
+
|
|
4066
|
+
// Notes
|
|
4067
|
+
if (res.notes) {
|
|
4068
|
+
html += '<div style="padding:0.5rem 1rem;font-size:0.8rem;color:var(--text-muted);border-top:1px solid var(--border);background:var(--bg-input);">';
|
|
4069
|
+
html += '<strong>Notes:</strong> ' + res.notes;
|
|
4070
|
+
html += '</div>';
|
|
4071
|
+
}
|
|
4072
|
+
|
|
4073
|
+
// Comment area
|
|
4074
|
+
html += '<div class="wireframe-comment">';
|
|
4075
|
+
html += '<label style="font-size:0.8rem;color:var(--text-muted);display:block;margin-bottom:0.3rem;">Commentaire :</label>';
|
|
4076
|
+
html += '<textarea class="form-textarea" placeholder="Commentaire sur cette maquette..."';
|
|
4077
|
+
html += ' onblur="updateWireframeComment(\'' + code + '\', \'' + (res.code || sectionCode + '-' + index) + '\', this.value)"';
|
|
4078
|
+
html += ' style="min-height:50px;font-size:0.85rem;resize:vertical;">';
|
|
4079
|
+
html += getWireframeComment(code, res.code || sectionCode + '-' + index);
|
|
4080
|
+
html += '</textarea>';
|
|
4081
|
+
html += '</div>';
|
|
4082
|
+
|
|
4083
|
+
html += '</div>';
|
|
4084
|
+
return html;
|
|
4085
|
+
}
|
|
4086
|
+
|
|
4087
|
+
/* ---------- SmartTable ---------- */
|
|
4088
|
+
function renderSmartTableMockup(res) {
|
|
4089
|
+
var columns = res.columns || [];
|
|
4090
|
+
if (columns.length === 0) return '<div style="padding:2rem;text-align:center;color:var(--text-muted);">Table sans colonnes definies</div>';
|
|
4091
|
+
|
|
4092
|
+
var html = '';
|
|
4093
|
+
|
|
4094
|
+
// Header with actions
|
|
4095
|
+
html += '<div class="mock-header">';
|
|
4096
|
+
html += '<span class="mock-title">' + (res.label || 'Liste') + '</span>';
|
|
4097
|
+
html += '<div style="display:flex;gap:0.4rem;">';
|
|
4098
|
+
(res.actions || []).forEach(function(action) {
|
|
4099
|
+
var isPrimary = action === 'create' || action === 'export';
|
|
4100
|
+
html += '<span class="mock-btn' + (isPrimary ? '' : '" style="background:var(--bg-hover);color:var(--text)') + '">' + formatActionLabel(action) + '</span>';
|
|
4101
|
+
});
|
|
4102
|
+
html += '</div></div>';
|
|
4103
|
+
|
|
4104
|
+
// Filters
|
|
4105
|
+
if (res.filters && res.filters.length > 0) {
|
|
4106
|
+
html += '<div style="display:flex;gap:0.5rem;margin-bottom:1rem;">';
|
|
4107
|
+
res.filters.forEach(function(f) {
|
|
4108
|
+
html += '<span class="mock-input" style="width:auto;min-width:120px;font-size:0.8rem;color:var(--text-muted);">' + f + ' ▾</span>';
|
|
4109
|
+
});
|
|
4110
|
+
html += '<span class="mock-input" style="width:auto;min-width:200px;font-size:0.8rem;color:var(--text-muted);">Rechercher...</span>';
|
|
4111
|
+
html += '</div>';
|
|
4112
|
+
}
|
|
4113
|
+
|
|
4114
|
+
// Table
|
|
4115
|
+
html += '<table class="mock-table">';
|
|
4116
|
+
html += '<thead><tr>';
|
|
4117
|
+
columns.forEach(function(col) {
|
|
4118
|
+
html += '<th>' + (col.label || col.field);
|
|
4119
|
+
if (col.sortable) html += ' <span style="font-size:0.6rem;color:var(--text-muted);">▲▼</span>';
|
|
4120
|
+
html += '</th>';
|
|
4121
|
+
});
|
|
4122
|
+
html += '<th style="width:80px;">Actions</th>';
|
|
4123
|
+
html += '</tr></thead>';
|
|
4124
|
+
|
|
4125
|
+
// Sample rows
|
|
4126
|
+
html += '<tbody>';
|
|
4127
|
+
var sampleData = generateSampleRows(columns, 4);
|
|
4128
|
+
sampleData.forEach(function(row) {
|
|
4129
|
+
html += '<tr>';
|
|
4130
|
+
columns.forEach(function(col) {
|
|
4131
|
+
var val = row[col.field] || '';
|
|
4132
|
+
if (col.type === 'badge') {
|
|
4133
|
+
html += '<td><span class="mock-status mock-status-active">' + val + '</span></td>';
|
|
4134
|
+
} else if (col.type === 'lookup') {
|
|
4135
|
+
html += '<td style="color:var(--accent);">' + val + '</td>';
|
|
4136
|
+
} else {
|
|
4137
|
+
html += '<td>' + val + '</td>';
|
|
4138
|
+
}
|
|
4139
|
+
});
|
|
4140
|
+
html += '<td style="text-align:center;"><span style="cursor:pointer;color:var(--text-muted);">✎ 🗑</span></td>';
|
|
4141
|
+
html += '</tr>';
|
|
4142
|
+
});
|
|
4143
|
+
html += '</tbody></table>';
|
|
4144
|
+
|
|
4145
|
+
// Pagination
|
|
4146
|
+
html += '<div style="display:flex;justify-content:space-between;align-items:center;padding:0.75rem 0;font-size:0.8rem;color:var(--text-muted);">';
|
|
4147
|
+
html += '<span>1-4 sur 24 resultats</span>';
|
|
4148
|
+
html += '<div style="display:flex;gap:0.3rem;">';
|
|
4149
|
+
html += '<span class="mock-btn" style="background:var(--primary);font-size:0.75rem;padding:0.2rem 0.5rem;">1</span>';
|
|
4150
|
+
html += '<span class="mock-btn" style="background:var(--bg-hover);font-size:0.75rem;padding:0.2rem 0.5rem;">2</span>';
|
|
4151
|
+
html += '<span class="mock-btn" style="background:var(--bg-hover);font-size:0.75rem;padding:0.2rem 0.5rem;">3</span>';
|
|
4152
|
+
html += '</div></div>';
|
|
4153
|
+
|
|
4154
|
+
return html;
|
|
4155
|
+
}
|
|
4156
|
+
|
|
4157
|
+
/* ---------- SmartForm ---------- */
|
|
4158
|
+
function renderSmartFormMockup(res) {
|
|
4159
|
+
var tabs = res.tabs || [];
|
|
4160
|
+
if (tabs.length === 0 && res.fields) {
|
|
4161
|
+
tabs = [{ label: 'Informations', fields: res.fields }];
|
|
4162
|
+
}
|
|
4163
|
+
if (tabs.length === 0) return '<div style="padding:2rem;text-align:center;color:var(--text-muted);">Formulaire sans champs definis</div>';
|
|
4164
|
+
|
|
4165
|
+
var html = '';
|
|
4166
|
+
|
|
4167
|
+
// Header
|
|
4168
|
+
html += '<div class="mock-header">';
|
|
4169
|
+
html += '<span class="mock-title">' + (res.label || 'Formulaire') + '</span>';
|
|
4170
|
+
html += '<div style="display:flex;gap:0.4rem;">';
|
|
4171
|
+
(res.actions || ['save', 'cancel']).forEach(function(action) {
|
|
4172
|
+
var isPrimary = action === 'save';
|
|
4173
|
+
html += '<span class="mock-btn' + (isPrimary ? '' : '" style="background:var(--bg-hover);color:var(--text)') + '">' + formatActionLabel(action) + '</span>';
|
|
4174
|
+
});
|
|
4175
|
+
html += '</div></div>';
|
|
4176
|
+
|
|
4177
|
+
// Tabs
|
|
4178
|
+
if (tabs.length > 1) {
|
|
4179
|
+
html += '<div style="display:flex;gap:0;border-bottom:1px solid var(--border);margin-bottom:1.5rem;">';
|
|
4180
|
+
tabs.forEach(function(tab, i) {
|
|
4181
|
+
html += '<span style="padding:0.5rem 1rem;font-size:0.85rem;cursor:pointer;border-bottom:2px solid ' + (i === 0 ? 'var(--primary)' : 'transparent') + ';color:' + (i === 0 ? 'var(--primary-light)' : 'var(--text-muted)') + ';">' + tab.label + '</span>';
|
|
4182
|
+
});
|
|
4183
|
+
html += '</div>';
|
|
4184
|
+
}
|
|
4185
|
+
|
|
4186
|
+
// Fields (first tab only)
|
|
4187
|
+
var fields = tabs[0].fields || [];
|
|
4188
|
+
var rows = [];
|
|
4189
|
+
for (var i = 0; i < fields.length; i += 2) {
|
|
4190
|
+
rows.push(fields.slice(i, i + 2));
|
|
4191
|
+
}
|
|
4192
|
+
|
|
4193
|
+
rows.forEach(function(row) {
|
|
4194
|
+
if (row.length === 1 && row[0].type === 'subtable') {
|
|
4195
|
+
html += renderSubtableMockup(row[0]);
|
|
4196
|
+
} else {
|
|
4197
|
+
html += '<div class="mock-form-row">';
|
|
4198
|
+
row.forEach(function(field) {
|
|
4199
|
+
html += '<div class="mock-form-group">';
|
|
4200
|
+
html += '<label class="mock-label">' + (field.label || field.field);
|
|
4201
|
+
if (field.required) html += ' <span style="color:var(--error);">*</span>';
|
|
4202
|
+
html += '</label>';
|
|
4203
|
+
html += renderFormFieldMockup(field);
|
|
4204
|
+
html += '</div>';
|
|
4205
|
+
});
|
|
4206
|
+
html += '</div>';
|
|
4207
|
+
}
|
|
4208
|
+
});
|
|
4209
|
+
|
|
4210
|
+
return html;
|
|
4211
|
+
}
|
|
4212
|
+
|
|
4213
|
+
function renderFormFieldMockup(field) {
|
|
4214
|
+
var val = generateSampleValue(field);
|
|
4215
|
+
switch (field.type) {
|
|
4216
|
+
case 'select':
|
|
4217
|
+
return '<span class="mock-input" style="display:block;">' + val + ' ▾</span>';
|
|
4218
|
+
case 'lookup':
|
|
4219
|
+
return '<span class="mock-input" style="display:block;color:var(--accent);">' + val + ' 🔍</span>';
|
|
4220
|
+
case 'date':
|
|
4221
|
+
return '<span class="mock-input" style="display:block;">' + val + ' 📅</span>';
|
|
4222
|
+
case 'textarea':
|
|
4223
|
+
return '<span class="mock-input" style="display:block;min-height:60px;">' + val + '</span>';
|
|
4224
|
+
case 'checkbox':
|
|
4225
|
+
return '<div style="display:flex;align-items:center;gap:0.5rem;"><input type="checkbox" checked disabled style="width:16px;height:16px;"><span style="font-size:0.85rem;color:var(--text);">' + val + '</span></div>';
|
|
4226
|
+
default:
|
|
4227
|
+
return '<span class="mock-input" style="display:block;' + (field.readonly ? 'opacity:0.6;' : '') + '">' + val + '</span>';
|
|
4228
|
+
}
|
|
4229
|
+
}
|
|
4230
|
+
|
|
4231
|
+
function renderSubtableMockup(field) {
|
|
4232
|
+
var cols = field.columns || [];
|
|
4233
|
+
var entity = field.entity || 'Element';
|
|
4234
|
+
var html = '<div style="margin:1rem 0;border:1px solid var(--border);border-radius:8px;overflow:hidden;">';
|
|
4235
|
+
html += '<div style="display:flex;justify-content:space-between;align-items:center;padding:0.5rem 0.75rem;background:var(--bg-hover);">';
|
|
4236
|
+
html += '<span style="font-weight:500;color:var(--text-bright);font-size:0.85rem;">' + entity + '</span>';
|
|
4237
|
+
html += '<span class="mock-btn" style="font-size:0.75rem;padding:0.2rem 0.5rem;">+ Ajouter</span>';
|
|
4238
|
+
html += '</div>';
|
|
4239
|
+
html += '<table class="mock-table"><thead><tr>';
|
|
4240
|
+
cols.forEach(function(c) { html += '<th>' + c + '</th>'; });
|
|
4241
|
+
html += '</tr></thead><tbody>';
|
|
4242
|
+
html += '<tr>' + cols.map(function() { return '<td style="color:var(--text-muted);font-style:italic;">...</td>'; }).join('') + '</tr>';
|
|
4243
|
+
html += '</tbody></table></div>';
|
|
4244
|
+
return html;
|
|
4245
|
+
}
|
|
4246
|
+
|
|
4247
|
+
/* ---------- SmartCard ---------- */
|
|
4248
|
+
function renderSmartCardMockup(res) {
|
|
4249
|
+
var columns = res.columns || res.fields || [];
|
|
4250
|
+
var html = '<div class="mock-header"><span class="mock-title">' + (res.label || 'Cartes') + '</span></div>';
|
|
4251
|
+
html += '<div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:1rem;">';
|
|
4252
|
+
|
|
4253
|
+
for (var i = 0; i < 4; i++) {
|
|
4254
|
+
html += '<div style="background:var(--bg-hover);border:1px solid var(--border);border-radius:8px;padding:1rem;">';
|
|
4255
|
+
columns.forEach(function(col, ci) {
|
|
4256
|
+
var label = col.label || col.field || col;
|
|
4257
|
+
if (ci === 0) {
|
|
4258
|
+
html += '<div style="font-weight:600;color:var(--text-bright);margin-bottom:0.5rem;">' + label + ' #' + (i + 1) + '</div>';
|
|
4259
|
+
} else {
|
|
4260
|
+
html += '<div style="font-size:0.8rem;color:var(--text-muted);margin-bottom:0.25rem;">' + label + ': <span style="color:var(--text);">valeur</span></div>';
|
|
4261
|
+
}
|
|
4262
|
+
});
|
|
4263
|
+
html += '</div>';
|
|
4264
|
+
}
|
|
4265
|
+
html += '</div>';
|
|
4266
|
+
return html;
|
|
4267
|
+
}
|
|
4268
|
+
|
|
4269
|
+
/* ---------- SmartKanban ---------- */
|
|
4270
|
+
function renderSmartKanbanMockup(res) {
|
|
4271
|
+
var options = res.options || res.columns || ['A faire', 'En cours', 'Termine'];
|
|
4272
|
+
var html = '<div class="mock-header"><span class="mock-title">' + (res.label || 'Kanban') + '</span></div>';
|
|
4273
|
+
html += '<div style="display:flex;gap:1rem;overflow-x:auto;padding-bottom:0.5rem;">';
|
|
4274
|
+
|
|
4275
|
+
options.forEach(function(col, ci) {
|
|
4276
|
+
var colLabel = typeof col === 'string' ? col : (col.label || col.field || 'Colonne');
|
|
4277
|
+
html += '<div style="min-width:200px;flex:1;background:var(--bg-hover);border-radius:8px;padding:0.75rem;">';
|
|
4278
|
+
html += '<div style="font-weight:600;font-size:0.85rem;color:var(--text-bright);margin-bottom:0.75rem;display:flex;justify-content:space-between;">';
|
|
4279
|
+
html += colLabel + ' <span style="font-size:0.7rem;background:var(--bg-card);padding:0.1rem 0.4rem;border-radius:4px;color:var(--text-muted);">' + (3 - ci) + '</span>';
|
|
4280
|
+
html += '</div>';
|
|
4281
|
+
for (var j = 0; j < Math.max(1, 3 - ci); j++) {
|
|
4282
|
+
html += '<div style="background:var(--bg-card);border:1px solid var(--border);border-radius:6px;padding:0.5rem;margin-bottom:0.5rem;font-size:0.8rem;">';
|
|
4283
|
+
html += '<div style="color:var(--text-bright);font-weight:500;">Element ' + (j + 1) + '</div>';
|
|
4284
|
+
html += '<div style="color:var(--text-muted);font-size:0.7rem;margin-top:0.25rem;">Description...</div>';
|
|
4285
|
+
html += '</div>';
|
|
4286
|
+
}
|
|
4287
|
+
html += '</div>';
|
|
4288
|
+
});
|
|
4289
|
+
html += '</div>';
|
|
4290
|
+
return html;
|
|
4291
|
+
}
|
|
4292
|
+
|
|
4293
|
+
/* ---------- SmartDashboard ---------- */
|
|
4294
|
+
function renderSmartDashboardMockup(res) {
|
|
4295
|
+
var html = '<div class="mock-header"><span class="mock-title">' + (res.label || 'Tableau de bord') + '</span></div>';
|
|
4296
|
+
|
|
4297
|
+
// KPI cards
|
|
4298
|
+
html += '<div class="mock-kpi-grid">';
|
|
4299
|
+
var kpis = res.kpis || [
|
|
4300
|
+
{ label: 'Total', value: '1,234' },
|
|
4301
|
+
{ label: 'Actifs', value: '987' },
|
|
4302
|
+
{ label: 'En attente', value: '156' },
|
|
4303
|
+
{ label: 'Taux', value: '80%' }
|
|
4304
|
+
];
|
|
4305
|
+
kpis.forEach(function(kpi) {
|
|
4306
|
+
html += '<div class="mock-kpi"><div class="mock-kpi-value">' + (kpi.value || '0') + '</div><div class="mock-kpi-label">' + (kpi.label || '') + '</div></div>';
|
|
4307
|
+
});
|
|
4308
|
+
html += '</div>';
|
|
4309
|
+
|
|
4310
|
+
// Chart placeholder
|
|
4311
|
+
html += '<div class="mock-chart-placeholder">Graphique</div>';
|
|
4312
|
+
|
|
4313
|
+
return html;
|
|
4314
|
+
}
|
|
4315
|
+
|
|
4316
|
+
/* ---------- SmartFilter ---------- */
|
|
4317
|
+
function renderSmartFilterMockup(res) {
|
|
4318
|
+
var options = res.options || [];
|
|
4319
|
+
var html = '<div style="display:flex;gap:0.4rem;flex-wrap:wrap;padding:0.5rem 0;">';
|
|
4320
|
+
html += '<span style="padding:0.3rem 0.7rem;border-radius:16px;font-size:0.8rem;background:var(--primary);color:#fff;cursor:pointer;">Tous</span>';
|
|
4321
|
+
options.forEach(function(opt) {
|
|
4322
|
+
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;">' + opt + '</span>';
|
|
4323
|
+
});
|
|
4324
|
+
html += '</div>';
|
|
4325
|
+
return html;
|
|
4326
|
+
}
|
|
4327
|
+
|
|
4328
|
+
/* ---------- Helpers ---------- */
|
|
4329
|
+
function formatActionLabel(action) {
|
|
4330
|
+
var labels = {
|
|
4331
|
+
create: 'Nouveau', edit: 'Modifier', delete: 'Supprimer',
|
|
4332
|
+
export: 'Exporter', save: 'Enregistrer', cancel: 'Annuler',
|
|
4333
|
+
validate: 'Valider', archive: 'Archiver', print: 'Imprimer'
|
|
4334
|
+
};
|
|
4335
|
+
return labels[action] || action;
|
|
4336
|
+
}
|
|
4337
|
+
|
|
4338
|
+
function generateSampleRows(columns, count) {
|
|
4339
|
+
var rows = [];
|
|
4340
|
+
for (var i = 0; i < count; i++) {
|
|
4341
|
+
var row = {};
|
|
4342
|
+
columns.forEach(function(col) {
|
|
4343
|
+
row[col.field] = generateSampleValue(col, i);
|
|
4344
|
+
});
|
|
4345
|
+
rows.push(row);
|
|
4346
|
+
}
|
|
4347
|
+
return rows;
|
|
4348
|
+
}
|
|
4349
|
+
|
|
4350
|
+
function generateSampleValue(field, index) {
|
|
4351
|
+
var idx = (index || 0) + 1;
|
|
4352
|
+
var t = field.type || 'text';
|
|
4353
|
+
var f = field.field || '';
|
|
4354
|
+
|
|
4355
|
+
if (field.options && field.options.length > 0) {
|
|
4356
|
+
return field.options[idx % field.options.length];
|
|
4357
|
+
}
|
|
4358
|
+
|
|
4359
|
+
if (t === 'date') return '0' + idx + '/03/2026';
|
|
4360
|
+
if (t === 'badge' || t === 'select') return 'Actif';
|
|
4361
|
+
if (t === 'lookup') return f.replace(/Id$/, '') + ' #' + idx;
|
|
4362
|
+
if (t === 'number') return String(idx * 100);
|
|
4363
|
+
if (t === 'checkbox') return idx % 2 === 0 ? 'Oui' : 'Non';
|
|
4364
|
+
|
|
4365
|
+
if (f.toLowerCase().includes('code')) return 'CODE-' + String(idx).padStart(3, '0');
|
|
4366
|
+
if (f.toLowerCase().includes('name') || f.toLowerCase().includes('nom')) return 'Nom ' + idx;
|
|
4367
|
+
if (f.toLowerCase().includes('email')) return 'user' + idx + '@example.com';
|
|
4368
|
+
if (f.toLowerCase().includes('date')) return '0' + idx + '/03/2026';
|
|
4369
|
+
if (f.toLowerCase().includes('status') || f.toLowerCase().includes('statut')) return 'Actif';
|
|
4370
|
+
|
|
4371
|
+
return f + ' ' + idx;
|
|
4372
|
+
}
|
|
4373
|
+
|
|
4374
|
+
|
|
3782
4375
|
/* --- 07-render-handoff.js --- */
|
|
3783
4376
|
/* ============================================
|
|
3784
4377
|
HANDOFF / SYNTHESE
|
|
@@ -4199,20 +4792,48 @@ function saveReviewJSON() {
|
|
|
4199
4792
|
*/
|
|
4200
4793
|
|
|
4201
4794
|
function initInlineComments() {
|
|
4202
|
-
//
|
|
4203
|
-
document.querySelectorAll('.section').forEach(
|
|
4204
|
-
|
|
4205
|
-
|
|
4206
|
-
|
|
4207
|
-
|
|
4208
|
-
|
|
4795
|
+
// Cadrage sections: direct card children
|
|
4796
|
+
document.querySelectorAll('.section > .card, .section > .stakeholder-card, .section > .uc-item, .section > .risk-item').forEach(function(card) {
|
|
4797
|
+
if (card.dataset.commentInitialized) return;
|
|
4798
|
+
card.dataset.commentInitialized = 'true';
|
|
4799
|
+
var section = card.closest('.section');
|
|
4800
|
+
var sectionId = section ? section.id : 'unknown';
|
|
4801
|
+
var siblings = Array.from(section.querySelectorAll(':scope > .card, :scope > .stakeholder-card, :scope > .uc-item, :scope > .risk-item'));
|
|
4802
|
+
var index = siblings.indexOf(card);
|
|
4803
|
+
card.appendChild(createCommentUI(sectionId, index));
|
|
4804
|
+
});
|
|
4805
|
+
|
|
4806
|
+
// Module spec lists: nested items in ucList, brList, entList containers
|
|
4807
|
+
document.querySelectorAll('[id^="ucList-"] > .uc-item, [id^="brList-"] > div, [id^="entList-"] > .entity-block').forEach(function(item) {
|
|
4808
|
+
if (item.dataset.commentInitialized) return;
|
|
4809
|
+
item.dataset.commentInitialized = 'true';
|
|
4810
|
+
var list = item.parentElement;
|
|
4811
|
+
var listId = list.id;
|
|
4812
|
+
var siblings = Array.from(list.children);
|
|
4813
|
+
var index = siblings.indexOf(item);
|
|
4814
|
+
item.appendChild(createCommentUI(listId, index));
|
|
4209
4815
|
});
|
|
4210
|
-
|
|
4211
|
-
|
|
4212
|
-
|
|
4213
|
-
|
|
4214
|
-
|
|
4215
|
-
|
|
4816
|
+
|
|
4817
|
+
// Stakeholder cards in grid
|
|
4818
|
+
document.querySelectorAll('.stakeholder-grid > .stakeholder-card').forEach(function(card) {
|
|
4819
|
+
if (card.dataset.commentInitialized) return;
|
|
4820
|
+
card.dataset.commentInitialized = 'true';
|
|
4821
|
+
var grid = card.parentElement;
|
|
4822
|
+
var section = card.closest('.section');
|
|
4823
|
+
var sectionId = section ? section.id : 'stakeholders';
|
|
4824
|
+
var siblings = Array.from(grid.children);
|
|
4825
|
+
var index = siblings.indexOf(card);
|
|
4826
|
+
card.appendChild(createCommentUI(sectionId, index));
|
|
4827
|
+
});
|
|
4828
|
+
|
|
4829
|
+
// Scope items
|
|
4830
|
+
['scopeVital', 'scopeImportant', 'scopeOptional', 'scopeExcluded'].forEach(function(containerId) {
|
|
4831
|
+
var container = document.getElementById(containerId);
|
|
4832
|
+
if (!container) return;
|
|
4833
|
+
container.querySelectorAll('.uc-item').forEach(function(item, index) {
|
|
4834
|
+
if (item.dataset.commentInitialized) return;
|
|
4835
|
+
item.dataset.commentInitialized = 'true';
|
|
4836
|
+
item.appendChild(createCommentUI(containerId, index));
|
|
4216
4837
|
});
|
|
4217
4838
|
});
|
|
4218
4839
|
}
|