Lien Gantt
This commit is contained in:
@@ -324,15 +324,28 @@ export class IssueDetail {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const child of this.composedIssues) {
|
const taskIds = new Set(tasks.map((t) => t.id));
|
||||||
|
const sortedChildren = [...this.composedIssues].sort((a, b) => {
|
||||||
|
if (!a.startDate && !b.startDate) return 0;
|
||||||
|
if (!a.startDate) return 1;
|
||||||
|
if (!b.startDate) return -1;
|
||||||
|
return a.startDate.localeCompare(b.startDate);
|
||||||
|
});
|
||||||
|
for (const child of sortedChildren) {
|
||||||
if (!child.startDate || !child.endDate) continue;
|
if (!child.startDate || !child.endDate) continue;
|
||||||
|
const deps = child.dependsOnIds
|
||||||
|
.map((id) => `issue-${id}`)
|
||||||
|
.filter((id) => taskIds.has(id))
|
||||||
|
.join(',');
|
||||||
tasks.push({
|
tasks.push({
|
||||||
id: `issue-${child.id}`,
|
id: `issue-${child.id}`,
|
||||||
name: `#${child.id} ${child.name}`,
|
name: `#${child.id} ${child.name}`,
|
||||||
start: child.startDate,
|
start: child.startDate,
|
||||||
end: child.endDate,
|
end: child.endDate,
|
||||||
progress: child.progress,
|
progress: child.progress,
|
||||||
|
...(deps ? { dependencies: deps } : {}),
|
||||||
});
|
});
|
||||||
|
taskIds.add(`issue-${child.id}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return tasks;
|
return tasks;
|
||||||
|
|||||||
@@ -140,15 +140,28 @@ export class MilestoneDetail {
|
|||||||
|
|
||||||
protected get milestoneGanttTasks(): GanttTask[] {
|
protected get milestoneGanttTasks(): GanttTask[] {
|
||||||
const tasks: GanttTask[] = [];
|
const tasks: GanttTask[] = [];
|
||||||
for (const issue of this.linkedIssues) {
|
const taskIds = new Set<string>();
|
||||||
|
const sorted = [...this.linkedIssues].sort((a, b) => {
|
||||||
|
if (!a.startDate && !b.startDate) return 0;
|
||||||
|
if (!a.startDate) return 1;
|
||||||
|
if (!b.startDate) return -1;
|
||||||
|
return a.startDate.localeCompare(b.startDate);
|
||||||
|
});
|
||||||
|
for (const issue of sorted) {
|
||||||
if (!issue.startDate || !issue.endDate) continue;
|
if (!issue.startDate || !issue.endDate) continue;
|
||||||
|
const deps = issue.dependsOnIds
|
||||||
|
.map((id) => `issue-${id}`)
|
||||||
|
.filter((id) => taskIds.has(id))
|
||||||
|
.join(',');
|
||||||
tasks.push({
|
tasks.push({
|
||||||
id: `issue-${issue.id}`,
|
id: `issue-${issue.id}`,
|
||||||
name: `#${issue.id} ${issue.name}`,
|
name: `#${issue.id} ${issue.name}`,
|
||||||
start: issue.startDate,
|
start: issue.startDate,
|
||||||
end: issue.endDate,
|
end: issue.endDate,
|
||||||
progress: issue.progress,
|
progress: issue.progress,
|
||||||
|
...(deps ? { dependencies: deps } : {}),
|
||||||
});
|
});
|
||||||
|
taskIds.add(`issue-${issue.id}`);
|
||||||
}
|
}
|
||||||
return tasks;
|
return tasks;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,8 +28,16 @@ export class Milestones {
|
|||||||
protected get ganttTasks(): GanttTask[] {
|
protected get ganttTasks(): GanttTask[] {
|
||||||
const today = new Date().toISOString().slice(0, 10);
|
const today = new Date().toISOString().slice(0, 10);
|
||||||
const tasks: GanttTask[] = [];
|
const tasks: GanttTask[] = [];
|
||||||
|
const taskIds = new Set<string>();
|
||||||
|
|
||||||
for (const milestone of this.milestones()) {
|
const sorted = [...this.milestones()].sort((a, b) => {
|
||||||
|
if (!a.startDate && !b.startDate) return 0;
|
||||||
|
if (!a.startDate) return 1;
|
||||||
|
if (!b.startDate) return -1;
|
||||||
|
return a.startDate.localeCompare(b.startDate);
|
||||||
|
});
|
||||||
|
|
||||||
|
for (const milestone of sorted) {
|
||||||
const end = milestone.endDate || milestone.dueDate;
|
const end = milestone.endDate || milestone.dueDate;
|
||||||
if (!end) continue;
|
if (!end) continue;
|
||||||
|
|
||||||
@@ -45,13 +53,19 @@ export class Milestones {
|
|||||||
}
|
}
|
||||||
const clampedEnd = end < start ? start : end;
|
const clampedEnd = end < start ? start : end;
|
||||||
|
|
||||||
|
const deps = milestone.dependsOnIds
|
||||||
|
.map((id) => `milestone-${id}`)
|
||||||
|
.filter((id) => taskIds.has(id))
|
||||||
|
.join(',');
|
||||||
tasks.push({
|
tasks.push({
|
||||||
id: `milestone-${milestone.id}`,
|
id: `milestone-${milestone.id}`,
|
||||||
name: milestone.name,
|
name: milestone.name,
|
||||||
start,
|
start,
|
||||||
end: clampedEnd,
|
end: clampedEnd,
|
||||||
progress: this.getProgress(milestone),
|
progress: this.getProgress(milestone),
|
||||||
|
...(deps ? { dependencies: deps } : {}),
|
||||||
});
|
});
|
||||||
|
taskIds.add(`milestone-${milestone.id}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return tasks;
|
return tasks;
|
||||||
@@ -59,8 +73,15 @@ export class Milestones {
|
|||||||
|
|
||||||
protected get filteredMilestones(): MilestoneEntity[] {
|
protected get filteredMilestones(): MilestoneEntity[] {
|
||||||
const q = this.searchQuery.trim().toLowerCase();
|
const q = this.searchQuery.trim().toLowerCase();
|
||||||
if (!q) return this.milestones();
|
const list = q
|
||||||
return this.milestones().filter((m) => m.name.toLowerCase().includes(q));
|
? this.milestones().filter((m) => m.name.toLowerCase().includes(q))
|
||||||
|
: this.milestones();
|
||||||
|
return [...list].sort((a, b) => {
|
||||||
|
if (!a.startDate && !b.startDate) return 0;
|
||||||
|
if (!a.startDate) return 1;
|
||||||
|
if (!b.startDate) return -1;
|
||||||
|
return a.startDate.localeCompare(b.startDate);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected getProgress(milestone: MilestoneEntity): number {
|
protected getProgress(milestone: MilestoneEntity): number {
|
||||||
|
|||||||
Reference in New Issue
Block a user