FN-5822: wire shared branch-group visibility and merge controls
Add dashboard and API support for viewing shared branch groups and triggering group merge actions. - add branch-group API routes and register them in integrated routers - extend dashboard legacy API client with branch-group fetch and merge-control actions - add BranchGroupCard UI + styles and surface it in task/detail/subtask views - add dashboard/API test coverage for branch-group routes and UI integration points - document branch-group behavior and add a changeset for @runfusion/fusion Files changed: .changeset/fn-5822-branch-group-dashboard.md | 5 + docs/dashboard-guide.md | 31 ++++++ packages/dashboard/app/api/legacy.ts | 54 +++++++++ .../dashboard/app/components/BranchGroupCard.css | 83 ++++++++++++++ .../dashboard/app/components/BranchGroupCard.tsx | 123 +++++++++++++++++++++ .../app/components/SubtaskBreakdownModal.tsx | 3 + packages/dashboard/app/components/TaskCard.tsx | 19 ++++ .../dashboard/app/components/TaskDetailModal.tsx | 4 + .../components/__tests__/BranchGroupCard.test.tsx | 96 ++++++++++++++++ .../__tests__/SubtaskBreakdownModal.test.tsx | 1 + .../app/components/__tests__/TaskCard.test.tsx | 16 ++++ .../components/__tests__/TaskDetailModal.test.tsx | 22 ++++ .../src/__tests__/routes-branch-groups.test.ts | 119 ++++++++++++++++++++ .../src/routes/register-branch-groups-routes.ts | 118 ++++++++++++++++++++ .../src/routes/register-integrated-routers.ts | 13 +++ packages/dashboard/vitest.config.ts | 4 +- 16 files changed, 709 insertions(+), 2 deletions(-) Fusion-Task-Id: FN-5822 Fusion-Task-Lineage: 199c25b8-f6ec-43b4-8fab-509f23fb5ac7
This commit is contained in:
@@ -77,6 +77,8 @@ import type {
|
||||
ProjectNodePathMapping,
|
||||
ApprovalRequestStatus,
|
||||
TaskIdIntegrityReport,
|
||||
BranchGroup,
|
||||
BranchGroupPrState,
|
||||
} from "@fusion/core";
|
||||
import type { PlanningQuestion, PlanningSummary } from "@fusion/core";
|
||||
import type { GithubIssueAction, ScheduledTask, ScheduledTaskCreateInput, ScheduledTaskUpdateInput, AutomationRunResult, Routine, RoutineCreateInput, RoutineUpdateInput, RoutineExecutionResult } from "@fusion/core";
|
||||
@@ -564,6 +566,58 @@ export function mergeTask(id: string, projectId?: string): Promise<MergeResult>
|
||||
return api<MergeResult>(withProjectId(`/tasks/${id}/merge`, projectId), { method: "POST" });
|
||||
}
|
||||
|
||||
export interface BranchGroupMemberSummary {
|
||||
taskId: string;
|
||||
title: string;
|
||||
column: Task["column"];
|
||||
landed: boolean;
|
||||
}
|
||||
|
||||
export interface BranchGroupSummary extends BranchGroup {
|
||||
members: BranchGroupMemberSummary[];
|
||||
completion: {
|
||||
landed: number;
|
||||
total: number;
|
||||
complete: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
export interface PromoteBranchGroupResult {
|
||||
groupId: string;
|
||||
status?: BranchGroup["status"];
|
||||
prState?: BranchGroupPrState;
|
||||
prNumber?: number;
|
||||
prUrl?: string;
|
||||
}
|
||||
|
||||
export function apiListBranchGroups(projectId?: string, status?: BranchGroup["status"]): Promise<{ groups: BranchGroupSummary[] }> {
|
||||
const search = new URLSearchParams();
|
||||
if (status) search.set("status", status);
|
||||
const suffix = search.size > 0 ? `?${search.toString()}` : "";
|
||||
return api<{ groups: BranchGroupSummary[] }>(withProjectId(`/branch-groups${suffix}`, projectId));
|
||||
}
|
||||
|
||||
export function apiGetBranchGroup(id: string, projectId?: string): Promise<{ group: BranchGroupSummary }> {
|
||||
return api<{ group: BranchGroupSummary }>(withProjectId(`/branch-groups/${id}`, projectId));
|
||||
}
|
||||
|
||||
export function apiAssignTaskBranchGroup(
|
||||
payload: { taskId: string; groupId?: string | null; branchName?: string },
|
||||
projectId?: string,
|
||||
): Promise<{ taskId: string; groupId: string | null }> {
|
||||
return api<{ taskId: string; groupId: string | null }>(withProjectId("/branch-groups/assign", projectId), {
|
||||
method: "POST",
|
||||
body: JSON.stringify(payload),
|
||||
});
|
||||
}
|
||||
|
||||
export function apiPromoteBranchGroup(id: string, projectId?: string): Promise<PromoteBranchGroupResult> {
|
||||
return api<PromoteBranchGroupResult>(withProjectId(`/branch-groups/${id}/promote`, projectId), {
|
||||
method: "POST",
|
||||
body: JSON.stringify({}),
|
||||
});
|
||||
}
|
||||
|
||||
export type RecoverBranchBindingOutcome =
|
||||
| { taskId: string; result: "applied"; branch: string; aheadCount: number; integrationBase: string; previousBranch: string | null }
|
||||
| { taskId: string; result: "skipped"; reason: "binding-intact" | "no-live-branch" | "ambiguous-candidates" | "no-unique-work"; candidates?: Array<{ branch: string; aheadCount: number }> };
|
||||
|
||||
Reference in New Issue
Block a user