sprint
This commit is contained in:
@ -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 n’utiliser que la variable d’environnement, ou saisissez l’ID exact du
|
||||
champ Sprint de votre projet Scrum.
|
||||
</p>
|
||||
</div>
|
||||
<p className="mt-2 text-[10px] text-slate-500">
|
||||
La date d’atterrissage 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"
|
||||
|
||||
Reference in New Issue
Block a user