- Thread workflow name lookup data from Board into Column, TaskCard, and WorktreeGroup components - Update unified task progress resolution to prefer workflow lookup names over raw workflow IDs - Keep fallback behavior for missing lookup entries so progress labels remain stable - Expand Board, Column, and TaskCard tests to cover lookup-based workflow name rendering
71 lines
2.1 KiB
TypeScript
71 lines
2.1 KiB
TypeScript
import type { Task, WorkflowStepResult, WorkflowStepPhase, StepStatus } from "@fusion/core";
|
|
|
|
export type UnifiedTaskProgressStatus = StepStatus | "failed";
|
|
|
|
export interface UnifiedTaskProgressItem {
|
|
id: string;
|
|
name: string;
|
|
status: UnifiedTaskProgressStatus;
|
|
source: "step" | "workflow";
|
|
phase: WorkflowStepPhase;
|
|
}
|
|
|
|
export interface UnifiedTaskProgress {
|
|
total: number;
|
|
completed: number;
|
|
items: UnifiedTaskProgressItem[];
|
|
}
|
|
|
|
function mapWorkflowStatus(status: WorkflowStepResult["status"]): UnifiedTaskProgressStatus {
|
|
switch (status) {
|
|
case "passed":
|
|
return "done";
|
|
case "failed":
|
|
return "failed";
|
|
case "skipped":
|
|
return "skipped";
|
|
case "pending":
|
|
default:
|
|
return "pending";
|
|
}
|
|
}
|
|
|
|
function isCompleted(status: UnifiedTaskProgressStatus): boolean {
|
|
return status === "done" || status === "skipped";
|
|
}
|
|
|
|
export function getUnifiedTaskProgress(
|
|
task: Pick<Task, "steps" | "enabledWorkflowSteps" | "workflowStepResults">,
|
|
workflowStepNameLookup?: ReadonlyMap<string, string>,
|
|
): UnifiedTaskProgress {
|
|
const stepItems: UnifiedTaskProgressItem[] = (task.steps ?? []).map((step, index) => ({
|
|
id: `step-${index}`,
|
|
name: step.name,
|
|
status: step.status,
|
|
source: "step",
|
|
phase: "pre-merge",
|
|
}));
|
|
|
|
const workflowResultsById = new Map(
|
|
(task.workflowStepResults ?? []).map((result) => [result.workflowStepId, result] as const),
|
|
);
|
|
|
|
const workflowItems: UnifiedTaskProgressItem[] = (task.enabledWorkflowSteps ?? []).map((workflowStepId) => {
|
|
const result = workflowResultsById.get(workflowStepId);
|
|
const lookupName = workflowStepNameLookup?.get(workflowStepId);
|
|
return {
|
|
id: `workflow-${workflowStepId}`,
|
|
name: lookupName ?? result?.workflowStepName ?? workflowStepId,
|
|
status: result ? mapWorkflowStatus(result.status) : "pending",
|
|
source: "workflow",
|
|
phase: result?.phase ?? "pre-merge",
|
|
};
|
|
});
|
|
|
|
const items = [...stepItems, ...workflowItems];
|
|
const total = items.length;
|
|
const completed = items.filter((item) => isCompleted(item.status)).length;
|
|
|
|
return { total, completed, items };
|
|
}
|