@atlashub/smartstack-cli 4.29.0 → 4.30.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/.documentation/business-analyse.html +217 -0
- package/package.json +1 -1
- package/templates/skills/ba-generate-html/html/ba-interactive.html +207 -199
- package/templates/skills/ba-generate-html/html/src/partials/cadrage-context.html +9 -9
- package/templates/skills/ba-generate-html/html/src/partials/cadrage-scope.html +15 -15
- package/templates/skills/ba-generate-html/html/src/partials/cadrage-stakeholders.html +7 -7
- package/templates/skills/ba-generate-html/html/src/partials/cadrage-success.html +13 -13
- package/templates/skills/ba-generate-html/html/src/partials/consol-datamodel.html +4 -4
- package/templates/skills/ba-generate-html/html/src/partials/consol-flows.html +5 -5
- package/templates/skills/ba-generate-html/html/src/partials/consol-interactions.html +2 -2
- package/templates/skills/ba-generate-html/html/src/partials/consol-permissions.html +4 -4
- package/templates/skills/ba-generate-html/html/src/partials/decomp-dependencies.html +11 -11
- package/templates/skills/ba-generate-html/html/src/partials/decomp-modules.html +9 -9
- package/templates/skills/ba-generate-html/html/src/partials/handoff-summary.html +5 -5
- package/templates/skills/ba-generate-html/html/src/scripts/01-data-init.js +10 -2
- package/templates/skills/ba-generate-html/html/src/scripts/02-navigation.js +10 -10
- package/templates/skills/ba-generate-html/html/src/scripts/03-render-cadrage.js +1 -1
- package/templates/skills/ba-generate-html/html/src/scripts/04-render-modules.js +4 -4
- package/templates/skills/ba-generate-html/html/src/scripts/05-render-specs.js +57 -57
- package/templates/skills/ba-generate-html/html/src/scripts/06-render-consolidation.js +4 -4
- package/templates/skills/ba-generate-html/html/src/scripts/06-render-mockups.js +5 -5
- package/templates/skills/ba-generate-html/html/src/scripts/07-render-handoff.js +8 -8
- package/templates/skills/ba-generate-html/html/src/scripts/08-editing.js +3 -3
- package/templates/skills/ba-generate-html/html/src/scripts/09-export.js +2 -2
- package/templates/skills/ba-generate-html/html/src/scripts/10-comments.js +2 -2
- package/templates/skills/ba-generate-html/html/src/scripts/11-review-panel.js +8 -8
- package/templates/skills/ba-generate-html/html/src/styles/03-navigation.css +1 -1
- package/templates/skills/ba-generate-html/html/src/template.html +92 -92
- package/templates/skills/ba-generate-html/steps/step-02-build-data.md +5 -1
|
@@ -28,13 +28,13 @@ function renderModuleSpecSection(mod) {
|
|
|
28
28
|
return `
|
|
29
29
|
<div class="section" id="module-spec-${code}" style="display:none;">
|
|
30
30
|
<h2 class="section-title">${mod.name}</h2>
|
|
31
|
-
<p class="section-subtitle">${mod.description || '
|
|
31
|
+
<p class="section-subtitle">${mod.description || 'Spécification détaillée de ce domaine fonctionnel.'}</p>
|
|
32
32
|
|
|
33
33
|
<div class="tab-bar">
|
|
34
34
|
<button class="tab-btn active" onclick="switchTab('${code}', 'uc')">Cas d'utilisation</button>
|
|
35
|
-
<button class="tab-btn" onclick="switchTab('${code}', 'br')">
|
|
36
|
-
<button class="tab-btn" onclick="switchTab('${code}', 'ent')">
|
|
37
|
-
<button class="tab-btn" onclick="switchTab('${code}', 'perm')">Droits d'
|
|
35
|
+
<button class="tab-btn" onclick="switchTab('${code}', 'br')">Règles métier</button>
|
|
36
|
+
<button class="tab-btn" onclick="switchTab('${code}', 'ent')">Données</button>
|
|
37
|
+
<button class="tab-btn" onclick="switchTab('${code}', 'perm')">Droits d'accès</button>
|
|
38
38
|
<button class="tab-btn" onclick="switchTab('${code}', 'mock')">Maquettes</button>
|
|
39
39
|
<button class="tab-btn" onclick="switchTab('${code}', 'notes')">Notes</button>
|
|
40
40
|
<button class="tab-btn" onclick="switchTab('${code}', 'struct')">Structure</button>
|
|
@@ -42,7 +42,7 @@ function renderModuleSpecSection(mod) {
|
|
|
42
42
|
|
|
43
43
|
<!-- TAB: Cas d'utilisation -->
|
|
44
44
|
<div class="tab-panel active" id="tab-${code}-uc">
|
|
45
|
-
<p style="font-size:0.85rem;color:var(--text-muted);margin-bottom:1rem;">
|
|
45
|
+
<p style="font-size:0.85rem;color:var(--text-muted);margin-bottom:1rem;">Décrivez ce que chaque type d'utilisateur peut faire dans ce domaine. Un cas d'utilisation = une action concrète.</p>
|
|
46
46
|
<div id="ucList-${code}" class="uc-list">
|
|
47
47
|
${spec.useCases.map((uc, i) => renderUseCase(code, uc, i)).join('')}
|
|
48
48
|
</div>
|
|
@@ -50,20 +50,20 @@ function renderModuleSpecSection(mod) {
|
|
|
50
50
|
<div class="inline-form" id="addUcForm-${code}">
|
|
51
51
|
<div class="inline-form-title">Nouveau cas d'utilisation</div>
|
|
52
52
|
<div class="form-group">
|
|
53
|
-
<label class="form-label">Que fait l'utilisateur ? (exemple :
|
|
54
|
-
<input type="text" class="form-input" id="uc-name-${code}" placeholder="Action
|
|
53
|
+
<label class="form-label">Que fait l'utilisateur ? (exemple : Créer une commande)</label>
|
|
54
|
+
<input type="text" class="form-input" id="uc-name-${code}" placeholder="Action concrète de l'utilisateur">
|
|
55
55
|
</div>
|
|
56
56
|
<div class="form-group">
|
|
57
|
-
<label class="form-label">Qui
|
|
57
|
+
<label class="form-label">Qui réalise cette action ? (profil utilisateur)</label>
|
|
58
58
|
<input type="text" class="form-input" id="uc-actor-${code}" placeholder="Exemple : Responsable de production">
|
|
59
59
|
</div>
|
|
60
60
|
<div class="form-group">
|
|
61
|
-
<label class="form-label">
|
|
62
|
-
<textarea class="form-textarea" id="uc-steps-${code}" placeholder="1. L'utilisateur ouvre la page de
|
|
61
|
+
<label class="form-label">Déroulement normal, étape par étape (une par ligne)</label>
|
|
62
|
+
<textarea class="form-textarea" id="uc-steps-${code}" placeholder="1. L'utilisateur ouvre la page de création 2. Il remplit les champs obligatoires 3. Il valide le formulaire 4. Le système enregistre et confirme"></textarea>
|
|
63
63
|
</div>
|
|
64
64
|
<div class="form-group">
|
|
65
65
|
<label class="form-label">Que se passe-t-il si quelque chose ne va pas ? (optionnel)</label>
|
|
66
|
-
<textarea class="form-textarea" id="uc-alt-${code}" placeholder="Exemple : Si les
|
|
66
|
+
<textarea class="form-textarea" id="uc-alt-${code}" placeholder="Exemple : Si les données sont incorrectes, le système affiche un message d'erreur" style="min-height:50px;"></textarea>
|
|
67
67
|
</div>
|
|
68
68
|
<div class="form-actions">
|
|
69
69
|
<button class="btn" onclick="toggleForm('addUcForm-${code}')">Annuler</button>
|
|
@@ -72,36 +72,36 @@ function renderModuleSpecSection(mod) {
|
|
|
72
72
|
</div>
|
|
73
73
|
</div>
|
|
74
74
|
|
|
75
|
-
<!-- TAB:
|
|
75
|
+
<!-- TAB: Règles métier -->
|
|
76
76
|
<div class="tab-panel" id="tab-${code}-br">
|
|
77
|
-
<p style="font-size:0.85rem;color:var(--text-muted);margin-bottom:1rem;">Les
|
|
77
|
+
<p style="font-size:0.85rem;color:var(--text-muted);margin-bottom:1rem;">Les règles que le système doit respecter. Formulez-les sous forme de conditions : "Si... alors... sinon..."</p>
|
|
78
78
|
<div id="brList-${code}">
|
|
79
79
|
${spec.businessRules.map((br, i) => renderBusinessRule(code, br, i)).join('')}
|
|
80
80
|
</div>
|
|
81
|
-
<button class="add-btn" onclick="toggleForm('addBrForm-${code}')">+ Ajouter une
|
|
81
|
+
<button class="add-btn" onclick="toggleForm('addBrForm-${code}')">+ Ajouter une règle métier</button>
|
|
82
82
|
<div class="inline-form" id="addBrForm-${code}">
|
|
83
|
-
<div class="inline-form-title">Nouvelle
|
|
83
|
+
<div class="inline-form-title">Nouvelle règle métier</div>
|
|
84
84
|
<div class="form-group">
|
|
85
|
-
<label class="form-label">Nom court de la
|
|
86
|
-
<input type="text" class="form-input" id="br-name-${code}" placeholder="Exemple :
|
|
85
|
+
<label class="form-label">Nom court de la règle</label>
|
|
86
|
+
<input type="text" class="form-input" id="br-name-${code}" placeholder="Exemple : Vérification du budget disponible">
|
|
87
87
|
</div>
|
|
88
88
|
<div class="form-group">
|
|
89
|
-
<label class="form-label">
|
|
89
|
+
<label class="form-label">Catégorie</label>
|
|
90
90
|
<select class="form-select" id="br-cat-${code}">
|
|
91
|
-
<option value="validation">
|
|
92
|
-
<option value="calculation">Calcul (le
|
|
91
|
+
<option value="validation">Vérification (le système vérifie que...)</option>
|
|
92
|
+
<option value="calculation">Calcul (le système calcule...)</option>
|
|
93
93
|
<option value="workflow">Processus (quand X se produit, alors...)</option>
|
|
94
|
-
<option value="security">
|
|
95
|
-
<option value="data">
|
|
94
|
+
<option value="security">Sécurité (seul... peut...)</option>
|
|
95
|
+
<option value="data">Données (les données doivent...)</option>
|
|
96
96
|
</select>
|
|
97
97
|
</div>
|
|
98
98
|
<div class="form-group">
|
|
99
|
-
<label class="form-label">Formulation de la
|
|
100
|
-
<textarea class="form-textarea" id="br-statement-${code}" placeholder="Si le montant de la commande
|
|
99
|
+
<label class="form-label">Formulation de la règle (Si... alors... sinon...)</label>
|
|
100
|
+
<textarea class="form-textarea" id="br-statement-${code}" placeholder="Si le montant de la commande dépasse le budget du client, alors la commande est refusée et un message d'erreur s'affiche"></textarea>
|
|
101
101
|
</div>
|
|
102
102
|
<div class="form-group">
|
|
103
103
|
<label class="form-label">Exemple concret (optionnel)</label>
|
|
104
|
-
<input type="text" class="form-input" id="br-example-${code}" placeholder="Exemple : Commande de 5000 CHF, budget de 2000 CHF ->
|
|
104
|
+
<input type="text" class="form-input" id="br-example-${code}" placeholder="Exemple : Commande de 5000 CHF, budget de 2000 CHF -> refusée">
|
|
105
105
|
</div>
|
|
106
106
|
<div class="form-actions">
|
|
107
107
|
<button class="btn" onclick="toggleForm('addBrForm-${code}')">Annuler</button>
|
|
@@ -110,34 +110,34 @@ function renderModuleSpecSection(mod) {
|
|
|
110
110
|
</div>
|
|
111
111
|
</div>
|
|
112
112
|
|
|
113
|
-
<!-- TAB:
|
|
113
|
+
<!-- TAB: Données (Entités) -->
|
|
114
114
|
<div class="tab-panel" id="tab-${code}-ent">
|
|
115
|
-
<p style="font-size:0.85rem;color:var(--text-muted);margin-bottom:1rem;">Les types de
|
|
115
|
+
<p style="font-size:0.85rem;color:var(--text-muted);margin-bottom:1rem;">Les types de données que ce domaine gère. Décrivez les informations importantes à enregistrer pour chaque type.</p>
|
|
116
116
|
<div id="entList-${code}">
|
|
117
117
|
${spec.entities.length > 0
|
|
118
118
|
? spec.entities.map((ent, i) => renderEntity(code, ent, i)).join('')
|
|
119
119
|
: (mod.entities || []).length > 0
|
|
120
|
-
? '<div class="card" style="color:var(--text-muted);padding:1.5rem;"><p style="margin-bottom:0.75rem;">Les
|
|
120
|
+
? '<div class="card" style="color:var(--text-muted);padding:1.5rem;"><p style="margin-bottom:0.75rem;">Les schémas détaillés ne sont pas encore disponibles. Entités identifiées :</p><ul style="list-style:disc;padding-left:1.5rem;">' + mod.entities.map(e => '<li>' + e + '</li>').join('') + '</ul><p style="font-size:0.8rem;margin-top:0.75rem;font-style:italic;">Utilisez le bouton ci-dessous pour ajouter les schémas détaillés.</p></div>'
|
|
121
121
|
: ''
|
|
122
122
|
}
|
|
123
123
|
</div>
|
|
124
|
-
<button class="add-btn" onclick="toggleForm('addEntForm-${code}')">+ Ajouter un type de
|
|
124
|
+
<button class="add-btn" onclick="toggleForm('addEntForm-${code}')">+ Ajouter un type de données</button>
|
|
125
125
|
<div class="inline-form" id="addEntForm-${code}">
|
|
126
|
-
<div class="inline-form-title">Nouveau type de
|
|
126
|
+
<div class="inline-form-title">Nouveau type de données</div>
|
|
127
127
|
<div class="form-group">
|
|
128
128
|
<label class="form-label">Nom (exemple : Commande, Client, Facture)</label>
|
|
129
|
-
<input type="text" class="form-input" id="ent-name-${code}" placeholder="Nom du type de
|
|
129
|
+
<input type="text" class="form-input" id="ent-name-${code}" placeholder="Nom du type de données">
|
|
130
130
|
</div>
|
|
131
131
|
<div class="form-group">
|
|
132
|
-
<label class="form-label">Description :
|
|
133
|
-
<textarea class="form-textarea" id="ent-desc-${code}" placeholder="En une ou deux phrases,
|
|
132
|
+
<label class="form-label">Description : à quoi sert cette donnée ?</label>
|
|
133
|
+
<textarea class="form-textarea" id="ent-desc-${code}" placeholder="En une ou deux phrases, décrivez ce que représente cette donnée dans votre activité" style="min-height:50px;"></textarea>
|
|
134
134
|
</div>
|
|
135
135
|
<div class="form-group">
|
|
136
|
-
<label class="form-label">Informations
|
|
137
|
-
<textarea class="form-textarea" id="ent-attrs-${code}" placeholder="Numero - Identifiant unique de la commande Date - Date de
|
|
136
|
+
<label class="form-label">Informations à enregistrer (une par ligne : Nom - Description)</label>
|
|
137
|
+
<textarea class="form-textarea" id="ent-attrs-${code}" placeholder="Numero - Identifiant unique de la commande Date - Date de création de la commande Montant total - Somme des lignes Statut - Brouillon, Envoyée, Validée, Refusée"></textarea>
|
|
138
138
|
</div>
|
|
139
139
|
<div class="form-group">
|
|
140
|
-
<label class="form-label">Relations avec d'autres
|
|
140
|
+
<label class="form-label">Relations avec d'autres données (optionnel, une par ligne)</label>
|
|
141
141
|
<textarea class="form-textarea" id="ent-rels-${code}" placeholder="Client - Chaque commande appartient a un client Ligne de commande - Une commande contient plusieurs lignes" style="min-height:50px;"></textarea>
|
|
142
142
|
</div>
|
|
143
143
|
<div class="form-actions">
|
|
@@ -147,20 +147,20 @@ function renderModuleSpecSection(mod) {
|
|
|
147
147
|
</div>
|
|
148
148
|
</div>
|
|
149
149
|
|
|
150
|
-
<!-- TAB: Droits d'
|
|
150
|
+
<!-- TAB: Droits d'accès -->
|
|
151
151
|
<div class="tab-panel" id="tab-${code}-perm">
|
|
152
|
-
<p style="font-size:0.85rem;color:var(--text-muted);margin-bottom:1rem;">
|
|
152
|
+
<p style="font-size:0.85rem;color:var(--text-muted);margin-bottom:1rem;">Définissez qui peut faire quoi dans ce domaine. Cochez les actions autorisées pour chaque profil.</p>
|
|
153
153
|
<div id="permGrid-${code}">
|
|
154
154
|
${renderPermissionGrid(code)}
|
|
155
155
|
</div>
|
|
156
156
|
<div style="display:flex;gap:0.75rem;margin-top:1rem;flex-wrap:wrap;">
|
|
157
|
-
<button class="add-btn" onclick="toggleForm('addRoleForm-${code}')" style="flex:1;min-width:200px;">+ Ajouter un
|
|
157
|
+
<button class="add-btn" onclick="toggleForm('addRoleForm-${code}')" style="flex:1;min-width:200px;">+ Ajouter un rôle</button>
|
|
158
158
|
<button class="add-btn" onclick="toggleForm('addActionForm-${code}')" style="flex:1;min-width:200px;">+ Ajouter une action</button>
|
|
159
159
|
</div>
|
|
160
160
|
<div class="inline-form" id="addRoleForm-${code}">
|
|
161
|
-
<div class="inline-form-title">Nouveau
|
|
161
|
+
<div class="inline-form-title">Nouveau rôle</div>
|
|
162
162
|
<div class="form-group">
|
|
163
|
-
<label class="form-label">Nom du
|
|
163
|
+
<label class="form-label">Nom du rôle</label>
|
|
164
164
|
<input type="text" class="form-input" id="role-name-${code}" placeholder="Exemple : Superviseur, Auditeur...">
|
|
165
165
|
</div>
|
|
166
166
|
<div class="form-actions">
|
|
@@ -183,7 +183,7 @@ function renderModuleSpecSection(mod) {
|
|
|
183
183
|
|
|
184
184
|
<!-- TAB: Maquettes -->
|
|
185
185
|
<div class="tab-panel" id="tab-${code}-mock">
|
|
186
|
-
<p style="font-size:0.85rem;color:var(--text-muted);margin-bottom:1rem;">Maquettes
|
|
186
|
+
<p style="font-size:0.85rem;color:var(--text-muted);margin-bottom:1rem;">Maquettes validées lors de l'analyse. Ces wireframes montrent la structure exacte des écrans de ce domaine.</p>
|
|
187
187
|
<div id="mockupContainer-${code}">
|
|
188
188
|
${renderModuleMockups(code)}
|
|
189
189
|
</div>
|
|
@@ -191,15 +191,15 @@ function renderModuleSpecSection(mod) {
|
|
|
191
191
|
|
|
192
192
|
<!-- TAB: Notes -->
|
|
193
193
|
<div class="tab-panel" id="tab-${code}-notes">
|
|
194
|
-
<p style="font-size:0.85rem;color:var(--text-muted);margin-bottom:1rem;">Notes libres, questions en suspens,
|
|
194
|
+
<p style="font-size:0.85rem;color:var(--text-muted);margin-bottom:1rem;">Notes libres, questions en suspens, éléments à clarifier pour ce domaine.</p>
|
|
195
195
|
<div class="card">
|
|
196
|
-
<div class="editable" contenteditable="true" data-module-code="${code}" data-module-field="notes" data-placeholder="Notez ici tout ce qui concerne ce domaine : questions,
|
|
196
|
+
<div class="editable" contenteditable="true" data-module-code="${code}" data-module-field="notes" data-placeholder="Notez ici tout ce qui concerne ce domaine : questions, précisions, contraintes particulières...">${spec.notes || ''}</div>
|
|
197
197
|
</div>
|
|
198
198
|
</div>
|
|
199
199
|
|
|
200
200
|
<!-- TAB: Structure (sections/resources) -->
|
|
201
201
|
<div class="tab-panel" id="tab-${code}-struct">
|
|
202
|
-
<p style="font-size:0.85rem;color:var(--text-muted);margin-bottom:1rem;">Organisation des
|
|
202
|
+
<p style="font-size:0.85rem;color:var(--text-muted);margin-bottom:1rem;">Organisation des écrans et ressources de ce domaine. Structure hiérarchique : sections regroupant des ressources.</p>
|
|
203
203
|
<div id="structContainer-${code}">
|
|
204
204
|
${renderModuleStructure(code)}
|
|
205
205
|
</div>
|
|
@@ -218,8 +218,8 @@ function renderUseCase(code, uc, index) {
|
|
|
218
218
|
</div>
|
|
219
219
|
</div>
|
|
220
220
|
<div class="uc-actors"><div class="uc-actor">${uc.actor}</div></div>
|
|
221
|
-
${uc.steps ? `<div class="uc-detail-label">
|
|
222
|
-
${uc.alternative ? `<div class="uc-detail-label">En cas de
|
|
221
|
+
${uc.steps ? `<div class="uc-detail-label">Déroulement</div><div class="uc-detail">${uc.steps.replace(/\n/g, '<br>')}</div>` : ''}
|
|
222
|
+
${uc.alternative ? `<div class="uc-detail-label">En cas de problème</div><div class="uc-detail" style="color:var(--warning);">${uc.alternative}</div>` : ''}
|
|
223
223
|
<div style="padding:0.5rem 0.75rem;border-top:1px solid var(--border);background:var(--bg-input);border-radius:0 0 8px 8px;">
|
|
224
224
|
<label style="font-size:0.75rem;color:var(--text-muted);display:block;margin-bottom:0.25rem;">Commentaire / Feedback :</label>
|
|
225
225
|
<textarea class="form-textarea" placeholder="Ajouter un commentaire sur ce cas d'utilisation..."
|
|
@@ -255,7 +255,7 @@ function removeUseCase(code, index) {
|
|
|
255
255
|
|
|
256
256
|
function renderBusinessRule(code, br, index) {
|
|
257
257
|
const catColors = { validation: 'br-cat-validation', calculation: 'br-cat-calculation', workflow: 'br-cat-workflow', security: 'br-cat-security', data: 'br-cat-data' };
|
|
258
|
-
const catLabels = { validation: '
|
|
258
|
+
const catLabels = { validation: 'Vérification', calculation: 'Calcul', workflow: 'Processus', security: 'Sécurité', data: 'Données' };
|
|
259
259
|
return `
|
|
260
260
|
<div style="margin-bottom:0.5rem;">
|
|
261
261
|
<div class="br-item" style="margin-bottom:0;border-radius:8px 8px 0 0;">
|
|
@@ -268,7 +268,7 @@ function renderBusinessRule(code, br, index) {
|
|
|
268
268
|
<button class="btn btn-sm" onclick="removeBusinessRule('${code}',${index})" style="opacity:0.5;flex-shrink:0;">✕</button>
|
|
269
269
|
</div>
|
|
270
270
|
<div style="padding:0.4rem 0.75rem 0.6rem;background:var(--bg-input);border:1px solid var(--border);border-top:0;border-radius:0 0 8px 8px;">
|
|
271
|
-
<textarea class="form-textarea" placeholder="Commentaire sur cette
|
|
271
|
+
<textarea class="form-textarea" placeholder="Commentaire sur cette règle..."
|
|
272
272
|
onblur="updateSpecComment('${code}','br',${index},this.value)"
|
|
273
273
|
style="min-height:35px;font-size:0.8rem;resize:vertical;">${getSpecComment(code, 'br', index)}</textarea>
|
|
274
274
|
</div>
|
|
@@ -323,7 +323,7 @@ function renderEntity(code, ent, index) {
|
|
|
323
323
|
</div>` : ''}
|
|
324
324
|
<div style="padding:0.4rem 0.75rem 0.6rem;background:var(--bg-input);border-top:1px solid var(--border);border-radius:0 0 8px 8px;">
|
|
325
325
|
<label style="font-size:0.75rem;color:var(--text-muted);display:block;margin-bottom:0.25rem;">Commentaire :</label>
|
|
326
|
-
<textarea class="form-textarea" placeholder="Commentaire sur cette
|
|
326
|
+
<textarea class="form-textarea" placeholder="Commentaire sur cette entité..."
|
|
327
327
|
onblur="updateSpecComment('${code}','ent',${index},this.value)"
|
|
328
328
|
style="min-height:35px;font-size:0.8rem;resize:vertical;">${getSpecComment(code, 'ent', index)}</textarea>
|
|
329
329
|
</div>
|
|
@@ -416,7 +416,7 @@ function renderModuleMockups(code) {
|
|
|
416
416
|
return `
|
|
417
417
|
<div class="card" style="text-align:center;padding:2rem;color:var(--text-muted);">
|
|
418
418
|
<p>Aucune maquette disponible pour ce module.</p>
|
|
419
|
-
<p style="font-size:0.85rem;margin-top:0.5rem;">Les maquettes seront
|
|
419
|
+
<p style="font-size:0.85rem;margin-top:0.5rem;">Les maquettes seront générées lors de la spécification détaillée.</p>
|
|
420
420
|
</div>`;
|
|
421
421
|
}
|
|
422
422
|
|
|
@@ -465,7 +465,7 @@ function renderWireframeMockup(code, wf, i) {
|
|
|
465
465
|
<details class="wireframe-details">
|
|
466
466
|
<summary>Mapping composants SmartStack</summary>
|
|
467
467
|
<table class="mapping-table">
|
|
468
|
-
<thead><tr><th
|
|
468
|
+
<thead><tr><th>Élément maquette</th><th>Composant React</th></tr></thead>
|
|
469
469
|
<tbody>
|
|
470
470
|
${mappings.map(m =>
|
|
471
471
|
'<tr><td>' + (m.wireframeElement || '') + '</td><td><code>' + (m.reactComponent || '') + '</code></td></tr>'
|
|
@@ -479,7 +479,7 @@ function renderWireframeMockup(code, wf, i) {
|
|
|
479
479
|
<textarea class="form-textarea"
|
|
480
480
|
data-module="${code}"
|
|
481
481
|
data-screen="${wf.screen}"
|
|
482
|
-
placeholder="Ajouter un commentaire sur cette maquette (ex:
|
|
482
|
+
placeholder="Ajouter un commentaire sur cette maquette (ex: déplacer ce bouton, ajouter une colonne...)"
|
|
483
483
|
onblur="updateWireframeComment('${code}', '${wf.screen}', this.value)"
|
|
484
484
|
style="min-height:60px;font-size:0.85rem;resize:vertical;"
|
|
485
485
|
>${getWireframeComment(code, wf.screen)}</textarea>
|
|
@@ -527,7 +527,7 @@ function getPermRoles() {
|
|
|
527
527
|
}
|
|
528
528
|
|
|
529
529
|
function getPermActions() {
|
|
530
|
-
const baseActions = ['Consulter', '
|
|
530
|
+
const baseActions = ['Consulter', 'Créer', 'Modifier', 'Supprimer', 'Valider', 'Exporter'];
|
|
531
531
|
return [...baseActions, ...(data.customActions || [])];
|
|
532
532
|
}
|
|
533
533
|
|
|
@@ -548,7 +548,7 @@ function renderPermissionGrid(code) {
|
|
|
548
548
|
<tbody>
|
|
549
549
|
${roles.map((role, ri) => `
|
|
550
550
|
<tr>
|
|
551
|
-
<td style="font-weight:500;color:var(--text-bright);">${role}${ri >= baseRolesCount ? ' <span onclick="removeCustomRole('+`'${code}','${role}'`+')" style="cursor:pointer;color:var(--danger);font-size:0.7rem;" title="Supprimer ce
|
|
551
|
+
<td style="font-weight:500;color:var(--text-bright);">${role}${ri >= baseRolesCount ? ' <span onclick="removeCustomRole('+`'${code}','${role}'`+')" style="cursor:pointer;color:var(--danger);font-size:0.7rem;" title="Supprimer ce rôle">✕</span>' : ''}</td>
|
|
552
552
|
${actions.map(action => {
|
|
553
553
|
const key = role + '|' + action;
|
|
554
554
|
const wildcardKey = role + '|*';
|
|
@@ -635,8 +635,8 @@ function renderModuleStructure(code) {
|
|
|
635
635
|
|
|
636
636
|
if (sections.length === 0) {
|
|
637
637
|
return '<div class="card" style="text-align:center;padding:2rem;color:var(--text-muted);">' +
|
|
638
|
-
'<p>Aucune section
|
|
639
|
-
'<p style="font-size:0.85rem;margin-top:0.5rem;">Les sections et ressources seront
|
|
638
|
+
'<p>Aucune section définie pour ce module.</p>' +
|
|
639
|
+
'<p style="font-size:0.85rem;margin-top:0.5rem;">Les sections et ressources seront identifiées lors de l\'analyse approfondie.</p>' +
|
|
640
640
|
'</div>';
|
|
641
641
|
}
|
|
642
642
|
|
|
@@ -24,7 +24,7 @@ function renderDataModel() {
|
|
|
24
24
|
});
|
|
25
25
|
|
|
26
26
|
if (allEntities.length === 0) {
|
|
27
|
-
container.innerHTML = '<p style="color:var(--text-muted);text-align:center;padding:2rem;">Aucune
|
|
27
|
+
container.innerHTML = '<p style="color:var(--text-muted);text-align:center;padding:2rem;">Aucune entité définie. Spécifiez les données dans chaque domaine (Phase 3 > onglet Données).</p>';
|
|
28
28
|
return;
|
|
29
29
|
}
|
|
30
30
|
|
|
@@ -40,7 +40,7 @@ function renderDataModel() {
|
|
|
40
40
|
const relCount = allEntities.reduce((sum, e) => sum + (e.relationships || []).length, 0);
|
|
41
41
|
html += `
|
|
42
42
|
<div class="dm-summary">
|
|
43
|
-
<div class="dm-summary-item"><span class="dm-summary-value">${allEntities.length}</span><span class="dm-summary-label">
|
|
43
|
+
<div class="dm-summary-item"><span class="dm-summary-value">${allEntities.length}</span><span class="dm-summary-label">Entités</span></div>
|
|
44
44
|
<div class="dm-summary-item"><span class="dm-summary-value">${moduleCount}</span><span class="dm-summary-label">Domaines</span></div>
|
|
45
45
|
<div class="dm-summary-item"><span class="dm-summary-value">${relCount}</span><span class="dm-summary-label">Relations</span></div>
|
|
46
46
|
</div>`;
|
|
@@ -54,7 +54,7 @@ function renderDataModel() {
|
|
|
54
54
|
html += `<div class="dm-module-group">`;
|
|
55
55
|
html += `<div class="dm-module-header">
|
|
56
56
|
<span class="dm-module-name">${m.name || m.code}</span>
|
|
57
|
-
<span class="dm-module-count">${entities.length}
|
|
57
|
+
<span class="dm-module-count">${entities.length} entité${entities.length > 1 ? 's' : ''}</span>
|
|
58
58
|
</div>`;
|
|
59
59
|
|
|
60
60
|
html += `<div class="dm-entity-grid">`;
|
|
@@ -103,7 +103,7 @@ function renderConsolInteractions() {
|
|
|
103
103
|
<span style="font-weight:600;color:var(--text-bright);">${fromName}</span>
|
|
104
104
|
<span class="interaction-arrow">→</span>
|
|
105
105
|
<span style="font-weight:600;color:var(--text-bright);">${toName}</span>
|
|
106
|
-
<span class="interaction-type">
|
|
106
|
+
<span class="interaction-type">Dépendance</span>
|
|
107
107
|
<span style="flex:1;font-size:0.8rem;color:var(--text-muted);">${d.description || ''}</span>
|
|
108
108
|
</div>`;
|
|
109
109
|
}).join('');
|
|
@@ -87,7 +87,7 @@ function renderResourceMockup(code, sectionCode, res, index) {
|
|
|
87
87
|
/* ---------- SmartTable ---------- */
|
|
88
88
|
function renderSmartTableMockup(res) {
|
|
89
89
|
var columns = res.columns || [];
|
|
90
|
-
if (columns.length === 0) return '<div style="padding:2rem;text-align:center;color:var(--text-muted);">Table sans colonnes
|
|
90
|
+
if (columns.length === 0) return '<div style="padding:2rem;text-align:center;color:var(--text-muted);">Table sans colonnes définies</div>';
|
|
91
91
|
|
|
92
92
|
var html = '';
|
|
93
93
|
|
|
@@ -144,7 +144,7 @@ function renderSmartTableMockup(res) {
|
|
|
144
144
|
|
|
145
145
|
// Pagination
|
|
146
146
|
html += '<div style="display:flex;justify-content:space-between;align-items:center;padding:0.75rem 0;font-size:0.8rem;color:var(--text-muted);">';
|
|
147
|
-
html += '<span>1-4 sur 24
|
|
147
|
+
html += '<span>1-4 sur 24 résultats</span>';
|
|
148
148
|
html += '<div style="display:flex;gap:0.3rem;">';
|
|
149
149
|
html += '<span class="mock-btn" style="background:var(--primary);font-size:0.75rem;padding:0.2rem 0.5rem;">1</span>';
|
|
150
150
|
html += '<span class="mock-btn" style="background:var(--bg-hover);font-size:0.75rem;padding:0.2rem 0.5rem;">2</span>';
|
|
@@ -160,7 +160,7 @@ function renderSmartFormMockup(res) {
|
|
|
160
160
|
if (tabs.length === 0 && res.fields) {
|
|
161
161
|
tabs = [{ label: 'Informations', fields: res.fields }];
|
|
162
162
|
}
|
|
163
|
-
if (tabs.length === 0) return '<div style="padding:2rem;text-align:center;color:var(--text-muted);">Formulaire sans champs
|
|
163
|
+
if (tabs.length === 0) return '<div style="padding:2rem;text-align:center;color:var(--text-muted);">Formulaire sans champs définis</div>';
|
|
164
164
|
|
|
165
165
|
var html = '';
|
|
166
166
|
|
|
@@ -268,7 +268,7 @@ function renderSmartCardMockup(res) {
|
|
|
268
268
|
|
|
269
269
|
/* ---------- SmartKanban ---------- */
|
|
270
270
|
function renderSmartKanbanMockup(res) {
|
|
271
|
-
var options = res.options || res.columns || ['
|
|
271
|
+
var options = res.options || res.columns || ['À faire', 'En cours', 'Terminé'];
|
|
272
272
|
var html = '<div class="mock-header"><span class="mock-title">' + (res.label || 'Kanban') + '</span></div>';
|
|
273
273
|
html += '<div style="display:flex;gap:1rem;overflow-x:auto;padding-bottom:0.5rem;">';
|
|
274
274
|
|
|
@@ -280,7 +280,7 @@ function renderSmartKanbanMockup(res) {
|
|
|
280
280
|
html += '</div>';
|
|
281
281
|
for (var j = 0; j < Math.max(1, 3 - ci); j++) {
|
|
282
282
|
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;">';
|
|
283
|
-
html += '<div style="color:var(--text-bright);font-weight:500;"
|
|
283
|
+
html += '<div style="color:var(--text-bright);font-weight:500;">Élément ' + (j + 1) + '</div>';
|
|
284
284
|
html += '<div style="color:var(--text-muted);font-size:0.7rem;margin-top:0.25rem;">Description...</div>';
|
|
285
285
|
html += '</div>';
|
|
286
286
|
}
|
|
@@ -19,10 +19,10 @@ function renderHandoffStats() {
|
|
|
19
19
|
container.innerHTML = `
|
|
20
20
|
<div class="stat-card"><div class="stat-value">${data.modules.length}</div><div class="stat-label">Domaines fonctionnels</div></div>
|
|
21
21
|
<div class="stat-card"><div class="stat-value">${totalUCs}</div><div class="stat-label">Cas d'utilisation</div></div>
|
|
22
|
-
<div class="stat-card"><div class="stat-value">${totalBRs}</div><div class="stat-label">
|
|
23
|
-
<div class="stat-card"><div class="stat-value">${totalEnts}</div><div class="stat-label">Types de
|
|
22
|
+
<div class="stat-card"><div class="stat-value">${totalBRs}</div><div class="stat-label">Règles métier</div></div>
|
|
23
|
+
<div class="stat-card"><div class="stat-value">${totalEnts}</div><div class="stat-label">Types de données</div></div>
|
|
24
24
|
<div class="stat-card"><div class="stat-value">${totalStakeholders}</div><div class="stat-label">Profils utilisateurs</div></div>
|
|
25
|
-
<div class="stat-card"><div class="stat-value">${data.dependencies.length}</div><div class="stat-label">
|
|
25
|
+
<div class="stat-card"><div class="stat-value">${data.dependencies.length}</div><div class="stat-label">Dépendances</div></div>
|
|
26
26
|
<div class="stat-card"><div class="stat-value">${data.consolidation.e2eFlows.length}</div><div class="stat-label">Parcours bout en bout</div></div>
|
|
27
27
|
`;
|
|
28
28
|
}
|
|
@@ -48,8 +48,8 @@ function renderHandoffModules() {
|
|
|
48
48
|
</div>
|
|
49
49
|
<div style="display:flex;gap:1rem;font-size:0.75rem;color:var(--text-muted);">
|
|
50
50
|
<span>${(spec.useCases || []).length} cas d'utilisation</span>
|
|
51
|
-
<span>${(spec.businessRules || []).length}
|
|
52
|
-
<span>${(spec.entities || []).length}
|
|
51
|
+
<span>${(spec.businessRules || []).length} règles</span>
|
|
52
|
+
<span>${(spec.entities || []).length} données</span>
|
|
53
53
|
</div>
|
|
54
54
|
<span class="priority priority-${m.priority === 'must' ? 'vital' : m.priority === 'should' ? 'important' : 'optional'}">${formatModulePriority(m.priority)}</span>
|
|
55
55
|
</div>
|
|
@@ -66,18 +66,18 @@ function renderCoverageMatrix() {
|
|
|
66
66
|
);
|
|
67
67
|
|
|
68
68
|
if (allScope.length === 0) {
|
|
69
|
-
container.innerHTML = '<p style="color:var(--text-muted);font-style:italic;">Aucun
|
|
69
|
+
container.innerHTML = '<p style="color:var(--text-muted);font-style:italic;">Aucun élément de périmètre défini dans le cadrage.</p>';
|
|
70
70
|
return;
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
container.innerHTML = `
|
|
74
74
|
<table class="mock-table" style="background:var(--bg-card);border-radius:8px;overflow:hidden;">
|
|
75
|
-
<thead><tr><th>Besoin</th><th>
|
|
75
|
+
<thead><tr><th>Besoin</th><th>Priorité</th><th>Domaine</th><th>Couvert</th></tr></thead>
|
|
76
76
|
<tbody>
|
|
77
77
|
${allScope.map(item => {
|
|
78
78
|
const moduleName = item.module
|
|
79
79
|
? (data.modules.find(m => m.code === item.module)?.name || item.module)
|
|
80
|
-
: (data.modules.length > 0 ? data.modules.map(m => m.name).join(', ') : '
|
|
80
|
+
: (data.modules.length > 0 ? data.modules.map(m => m.name).join(', ') : 'À définir');
|
|
81
81
|
return `
|
|
82
82
|
<tr>
|
|
83
83
|
<td>${item.name}</td>
|
|
@@ -8,11 +8,11 @@ function autoSave() {
|
|
|
8
8
|
|
|
9
9
|
function saveToLocalStorage() {
|
|
10
10
|
autoSave();
|
|
11
|
-
showNotification('Modifications
|
|
11
|
+
showNotification('Modifications sauvegardées');
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
function resetToEmbedded() {
|
|
15
|
-
if (!confirm('
|
|
15
|
+
if (!confirm('Réinitialiser toutes les données depuis la version d\'origine ? Vos modifications locales (commentaires, notes) seront perdues.')) return;
|
|
16
16
|
localStorage.removeItem(APP_KEY);
|
|
17
17
|
// Restore data from ORIGINAL_DATA
|
|
18
18
|
Object.keys(data).forEach(k => delete data[k]);
|
|
@@ -30,7 +30,7 @@ function resetToEmbedded() {
|
|
|
30
30
|
renderE2EFlows();
|
|
31
31
|
updateCounts();
|
|
32
32
|
renderReviewPanel();
|
|
33
|
-
showNotification('
|
|
33
|
+
showNotification('Données réinitialisées depuis la version d\'origine');
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
function loadFromLocalStorage() {
|
|
@@ -61,7 +61,7 @@ function exportJSON() {
|
|
|
61
61
|
a.download = (data.metadata.applicationId || 'analyse') + '-export.json';
|
|
62
62
|
a.click();
|
|
63
63
|
URL.revokeObjectURL(url);
|
|
64
|
-
showNotification('Export JSON
|
|
64
|
+
showNotification('Export JSON téléchargé');
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
/* ============================================
|
|
@@ -164,5 +164,5 @@ function saveReviewJSON() {
|
|
|
164
164
|
a.download = 'ba-review.json';
|
|
165
165
|
a.click();
|
|
166
166
|
URL.revokeObjectURL(url);
|
|
167
|
-
showNotification('ba-review.json
|
|
167
|
+
showNotification('ba-review.json téléchargé — sauvegardez-le à côté du HTML');
|
|
168
168
|
}
|
|
@@ -121,11 +121,11 @@ function renderCommentItems(sectionId, cardIndex) {
|
|
|
121
121
|
<span class="comment-author">${c.author || 'Utilisateur'}</span>
|
|
122
122
|
<span class="comment-date">${date}</span>
|
|
123
123
|
<span class="comment-category comment-category-${c.category}">${c.category}</span>
|
|
124
|
-
<span class="comment-status comment-status-${c.status}">${c.status === 'validated' ? '
|
|
124
|
+
<span class="comment-status comment-status-${c.status}">${c.status === 'validated' ? 'Validé' : 'À revoir'}</span>
|
|
125
125
|
</div>
|
|
126
126
|
<div class="comment-text">${c.content}</div>
|
|
127
127
|
<div class="comment-actions">
|
|
128
|
-
<button class="comment-action-btn" onclick="toggleCommentStatus(${globalIndex})">${c.status === 'validated' ? 'Remettre
|
|
128
|
+
<button class="comment-action-btn" onclick="toggleCommentStatus(${globalIndex})">${c.status === 'validated' ? 'Remettre à revoir' : 'Valider'}</button>
|
|
129
129
|
<button class="comment-action-btn" onclick="deleteComment(${globalIndex})" style="color:var(--error);">Supprimer</button>
|
|
130
130
|
</div>
|
|
131
131
|
</div>
|
|
@@ -83,8 +83,8 @@ function renderReviewPanel() {
|
|
|
83
83
|
<div class="review-comment-actions">
|
|
84
84
|
<button class="review-action-btn ${c.status === 'validated' ? 'reject' : 'validate'}"
|
|
85
85
|
onclick="event.stopPropagation();toggleCommentStatus(${globalIndex})"
|
|
86
|
-
title="${c.status === 'validated' ? 'Remettre
|
|
87
|
-
${c.status === 'validated' ? '
|
|
86
|
+
title="${c.status === 'validated' ? 'Remettre à revoir' : 'Valider'}">
|
|
87
|
+
${c.status === 'validated' ? 'À revoir' : 'Valider'}
|
|
88
88
|
</button>
|
|
89
89
|
<button class="review-action-btn delete"
|
|
90
90
|
onclick="event.stopPropagation();deleteComment(${globalIndex})"
|
|
@@ -102,14 +102,14 @@ function getSectionLabel(sectionId) {
|
|
|
102
102
|
const labels = {
|
|
103
103
|
'cadrage-context': 'Contexte',
|
|
104
104
|
'cadrage-stakeholders': 'Parties prenantes',
|
|
105
|
-
'cadrage-scope': '
|
|
106
|
-
'cadrage-success': '
|
|
105
|
+
'cadrage-scope': 'Périmètre',
|
|
106
|
+
'cadrage-success': 'Critères',
|
|
107
107
|
'decomp-modules': 'Domaines',
|
|
108
|
-
'decomp-dependencies': '
|
|
108
|
+
'decomp-dependencies': 'Dépendances',
|
|
109
109
|
'consol-interactions': 'Interactions',
|
|
110
|
-
'consol-permissions': '
|
|
110
|
+
'consol-permissions': 'Accès',
|
|
111
111
|
'consol-flows': 'Parcours',
|
|
112
|
-
'handoff-summary': '
|
|
112
|
+
'handoff-summary': 'Synthèse'
|
|
113
113
|
};
|
|
114
114
|
if (labels[sectionId]) return labels[sectionId];
|
|
115
115
|
if (sectionId.startsWith('module-spec-')) {
|
|
@@ -127,7 +127,7 @@ function getSectionLabel(sectionId) {
|
|
|
127
127
|
// Handle list-based sectionIds (ucList-*, brList-*, entList-*)
|
|
128
128
|
const listMatch = sectionId.match(/^(uc|br|ent)List-(.+)$/);
|
|
129
129
|
if (listMatch) {
|
|
130
|
-
const tabLabels = { uc: 'Cas d\'utilisation', br: '
|
|
130
|
+
const tabLabels = { uc: 'Cas d\'utilisation', br: 'Règles métier', ent: 'Données' };
|
|
131
131
|
const mod = data.modules.find(m => m.code === listMatch[2]);
|
|
132
132
|
const modName = mod ? mod.name : listMatch[2];
|
|
133
133
|
return modName + ' > ' + (tabLabels[listMatch[1]] || listMatch[1]);
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
text-overflow: ellipsis;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
/* Nav groups (top-level: Cadrage, Modules, Consolidation,
|
|
21
|
+
/* Nav groups (top-level: Cadrage, Modules, Consolidation, Synthèse) */
|
|
22
22
|
.nav-group { padding: 0.4rem 0; }
|
|
23
23
|
.nav-group + .nav-group { border-top: 1px solid var(--border); }
|
|
24
24
|
|