This commit is contained in:
Bastien COIGNOUX
2026-04-24 15:23:23 +02:00
parent ca4c64bbb0
commit 19af51160a
14 changed files with 1026 additions and 78 deletions

View File

@ -5,8 +5,10 @@ import {
type DashboardConfig,
type LaneLabelsConfig,
type Milestone,
type MilestoneKind,
type StatusBucketConfig,
} from '../lib/dashboardConfig'
import { MILESTONE_KIND_OPTIONS } from '../lib/milestoneKinds'
function parseBucketLines(raw: string): string[] {
return raw
@ -68,6 +70,8 @@ function newMilestone(): Milestone {
date: new Date().toISOString().slice(0, 10),
linkedStoryKeys: [],
critical: false,
kind: 'generic',
expectedActions: undefined,
}
}
@ -199,6 +203,26 @@ export function DashboardSettingsModal({ open, config, onClose, onSave }: Props)
/>
</div>
</div>
<div className="mt-3">
<label className="text-[10px] uppercase text-slate-500">
Champ Sprint Jira (ID customfield)
</label>
<input
className="mt-1 w-full rounded-lg border border-white/10 bg-black/30 px-2 py-1.5 font-mono text-xs outline-none"
value={draft.sprintFieldId ?? ''}
onChange={(e) =>
setDraft((d) => ({
...d,
sprintFieldId: e.target.value.trim() || undefined,
}))
}
placeholder="ex. customfield_10020 (vide = utiliser VITE_JIRA_SPRINT_FIELD ou désactiver)"
/>
<p className="mt-1 text-[10px] text-slate-600">
Laissez vide pour nutiliser que la variable denvironnement, ou saisissez lID exact du
champ Sprint de votre projet Scrum.
</p>
</div>
<p className="mt-2 text-[10px] text-slate-500">
La date datterrissage utilise : vélocité × (effectif / baseline). WIP = créneaux
nominaux pour la jauge « Ressources ».
@ -323,6 +347,37 @@ export function DashboardSettingsModal({ open, config, onClose, onSave }: Props)
onChange={(e) => updateMilestone(m.id, { title: e.target.value })}
placeholder="ex. Fin design"
/>
<div className="mb-2">
<label className="text-[10px] uppercase text-slate-500">Type de jalon</label>
<select
className="mt-1 w-full rounded border border-white/10 bg-black/30 px-2 py-1 text-xs text-slate-200 outline-none"
value={m.kind ?? 'generic'}
onChange={(e) =>
updateMilestone(m.id, { kind: e.target.value as MilestoneKind })
}
>
{MILESTONE_KIND_OPTIONS.map((opt) => (
<option key={opt.value} value={opt.value}>
{opt.label} {opt.hint}
</option>
))}
</select>
</div>
<div className="mb-2">
<label className="text-[10px] uppercase text-slate-500">Actions attendues à cette date</label>
<textarea
rows={2}
spellCheck={false}
className="mt-1 w-full resize-y rounded border border-white/10 bg-black/30 px-2 py-1 text-xs text-slate-200 outline-none"
value={m.expectedActions ?? ''}
onChange={(e) =>
updateMilestone(m.id, {
expectedActions: e.target.value.trim() ? e.target.value : undefined,
})
}
placeholder="Ex. Recette signée, doc runbook, passage en prod…"
/>
</div>
<label className="mt-2 flex cursor-pointer items-center gap-2 text-[11px] text-amber-100/90">
<input
type="checkbox"
@ -350,7 +405,7 @@ export function DashboardSettingsModal({ open, config, onClose, onSave }: Props)
.filter(Boolean),
})
}
placeholder="Stories liées (DCC-1, DCC-2) — vide = toutes"
placeholder="Stories (DCC-1, DCC-2) — vide = toutes les stories chargées"
/>
<button
type="button"