Ajout des dates calculés

This commit is contained in:
2026-05-30 07:38:08 +02:00
parent b1a114aaa8
commit fb0e853122
13 changed files with 386 additions and 15 deletions
+43
View File
@@ -21,6 +21,7 @@ export type IssueEntity = {
epic: string;
name: string;
startDate: string;
startDateMode: 'forced' | 'calculated';
endDate: string;
dueDate: string;
description: string;
@@ -68,6 +69,7 @@ export class IssuesStore {
const { id: _id, ...body } = normalized;
const created = this.normalizeIssue(await firstValueFrom(this.api.create(body)));
this.data.update((issues) => [...issues, created]);
this.recalculateCalculatedIssues();
return created;
} else {
const apiResult = await firstValueFrom(this.api.update(normalized.id, normalized));
@@ -80,6 +82,10 @@ export class IssuesStore {
return { ...c, linkedIssueIds: sent?.linkedIssueIds ?? [] };
});
}
// L'API ne retourne pas startDateMode : on le restaure depuis les données envoyées.
if (apiResult.startDateMode == null) {
apiResult.startDateMode = normalized.startDateMode;
}
const updated = this.normalizeIssue(apiResult);
this.data.update((issues) => {
const idx = issues.findIndex((i) => i.id === normalized.id);
@@ -88,6 +94,7 @@ export class IssuesStore {
copy[idx] = updated;
return copy;
});
this.recalculateCalculatedIssues();
return updated;
}
}
@@ -99,6 +106,41 @@ export class IssuesStore {
.filter((i) => i.id !== id)
.map((i) => ({ ...i, dependsOnIds: i.dependsOnIds.filter((d) => d !== id) })),
);
this.recalculateCalculatedIssues();
}
private recalculateCalculatedIssues(): void {
let anyChanged: boolean;
do {
anyChanged = false;
this.data.update((issues) => {
const result = issues.map((issue) => {
if (issue.startDateMode !== 'calculated') return issue;
const newStart = this.computeStartDate(issue, issues);
const newEnd = this.computeEndDate(newStart, issue.estimatedTime);
if (issue.startDate === newStart && issue.endDate === newEnd) return issue;
anyChanged = true;
return { ...issue, startDate: newStart, endDate: newEnd };
});
return anyChanged ? result : issues;
});
} while (anyChanged);
}
private computeStartDate(issue: IssueEntity, allIssues: IssueEntity[]): string {
const dates = issue.dependsOnIds
.map((id) => allIssues.find((i) => i.id === id)?.endDate)
.filter((d): d is string => !!d);
if (dates.length === 0) return '';
return dates.reduce((max, d) => (d > max ? d : max));
}
private computeEndDate(startDate: string, estimatedTime: number | null): string {
if (!startDate || estimatedTime === null || estimatedTime <= 0) return '';
const start = new Date(startDate);
const extraDays = Math.max(0, Math.ceil(estimatedTime / 8) - 1);
start.setDate(start.getDate() + extraDays);
return start.toISOString().split('T')[0];
}
private normalizeIssue(
@@ -113,6 +155,7 @@ export class IssuesStore {
...issue,
type: issue.type ?? 'Story',
startDate: issue.startDate ?? '',
startDateMode: issue.startDateMode === 'calculated' ? 'calculated' : 'forced',
endDate: issue.endDate ?? '',
estimatedTime: issue.estimatedTime ?? null,
dependsOnIds: normalizedDependencies,