mirror of
https://github.com/fabro-sh/fabro.git
synced 2026-10-08 03:10:26 +00:00
Extend GET /api/v1/boards/runs with include_archived=true (matching the existing flag on listRuns), add an Archived BoardColumn that the server appends only when the flag is set, and surface a "Show archived" toggle on /runs that flips between request shapes. Default behavior is unchanged — archived runs stay hidden. Server: list_board_runs now takes ListRunsParams; board_column maps RunStatus::Archived to BoardColumn::Archived; board_columns(include_archived) appends the column conditionally. Two new handler tests cover the default and flag-on paths. Web: useBoardsRuns(includeArchived) keys requests so SWR refetches on toggle; columnStatuses + columnStatusDisplay + columnStyles get an "archived" entry; buildSkeletonColumns filters by the flag so the loading state matches the eventual response. Two new buildBoardColumns tests cover both column shapes. Touched generated TS client files include unrelated whitespace drift from openapi-generator-cli; including them keeps the working tree consistent with what `bun run generate` produces. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
200 lines
No EOL
5.1 KiB
TypeScript
200 lines
No EOL
5.1 KiB
TypeScript
import useSWR, { type SWRConfiguration } from "swr";
|
|
import type {
|
|
ApiQuestion,
|
|
EventEnvelope,
|
|
PaginatedBoardRunList,
|
|
PaginatedRunFileList,
|
|
PaginatedRunList,
|
|
PaginatedRunStageList,
|
|
CommandLogResponse,
|
|
CommandOutputStream,
|
|
RunBilling,
|
|
RunProjection,
|
|
ServerSettings,
|
|
RunSummary,
|
|
SystemInfoResponse,
|
|
WorkflowSettings,
|
|
} from "@qltysh/fabro-api-client";
|
|
|
|
import type { PaginatedWorkflowListResponse, WorkflowDetailResponse } from "./workflow-api";
|
|
import {
|
|
apiFetcher,
|
|
apiNullableFetcher,
|
|
apiNullableTextFetcher,
|
|
apiPaginatedFetcher,
|
|
apiTextFetcher,
|
|
fetchAllStageEvents,
|
|
type PaginatedEnvelope,
|
|
} from "./api-client";
|
|
import { queryKeys } from "./query-keys";
|
|
|
|
const immutableOptions: SWRConfiguration = {
|
|
revalidateIfStale: false,
|
|
revalidateOnFocus: false,
|
|
revalidateOnReconnect: false,
|
|
};
|
|
|
|
type BoardRunsEnvelope = PaginatedEnvelope<PaginatedBoardRunList["data"][number]> &
|
|
Pick<PaginatedBoardRunList, "columns">;
|
|
|
|
export function useAuthConfig() {
|
|
return useSWR<{ methods: string[] }>(queryKeys.auth.config(), apiFetcher, immutableOptions);
|
|
}
|
|
|
|
export function useAuthMe() {
|
|
return useSWR<{
|
|
user: {
|
|
login: string;
|
|
name: string;
|
|
email: string;
|
|
avatarUrl: string;
|
|
userUrl: string;
|
|
};
|
|
provider: string;
|
|
demoMode: boolean;
|
|
}>(queryKeys.auth.me(), apiFetcher, { dedupingInterval: 10_000 });
|
|
}
|
|
|
|
export function useSystemInfo() {
|
|
return useSWR<SystemInfoResponse>(
|
|
queryKeys.system.info(),
|
|
apiFetcher,
|
|
immutableOptions,
|
|
);
|
|
}
|
|
|
|
export function useBoardsRuns(includeArchived: boolean = false) {
|
|
return useSWR<BoardRunsEnvelope>(
|
|
queryKeys.boards.runs(includeArchived),
|
|
apiPaginatedFetcher,
|
|
);
|
|
}
|
|
|
|
export function useRun(id: string | undefined) {
|
|
return useSWR<RunSummary | null>(
|
|
id ? queryKeys.runs.detail(id) : null,
|
|
apiNullableFetcher,
|
|
);
|
|
}
|
|
|
|
export function useRunState(id: string | undefined) {
|
|
return useSWR<RunProjection | null>(
|
|
id ? queryKeys.runs.state(id) : null,
|
|
apiNullableFetcher,
|
|
);
|
|
}
|
|
|
|
export function useRunFiles(id: string | undefined) {
|
|
return useSWR<PaginatedRunFileList | null>(
|
|
id ? queryKeys.runs.files(id) : null,
|
|
apiNullableFetcher,
|
|
{ keepPreviousData: true },
|
|
);
|
|
}
|
|
|
|
export function useRunStages(id: string | undefined) {
|
|
return useSWR<PaginatedRunStageList | null>(
|
|
id ? queryKeys.runs.stages(id) : null,
|
|
apiNullableFetcher,
|
|
);
|
|
}
|
|
|
|
export function useRunGraph(id: string | undefined, direction?: "LR" | "TB") {
|
|
return useSWR<string | null>(
|
|
id ? queryKeys.runs.graph(id, direction) : null,
|
|
apiNullableTextFetcher,
|
|
);
|
|
}
|
|
|
|
export function useRunGraphSource(id: string | undefined, enabled: boolean) {
|
|
return useSWR<string | null>(
|
|
id && enabled ? queryKeys.runs.graphSource(id) : null,
|
|
apiNullableTextFetcher,
|
|
);
|
|
}
|
|
|
|
export function useRunLogs(id: string | undefined, refreshInterval?: number) {
|
|
return useSWR<string | null>(
|
|
id ? queryKeys.runs.logs(id) : null,
|
|
apiNullableTextFetcher,
|
|
refreshInterval ? { refreshInterval } : undefined,
|
|
);
|
|
}
|
|
|
|
export function useRunSettings<T = WorkflowSettings>(id: string | undefined) {
|
|
return useSWR<T>(
|
|
id ? queryKeys.runs.settings(id) : null,
|
|
apiFetcher,
|
|
immutableOptions,
|
|
);
|
|
}
|
|
|
|
export function useRunBilling(id: string | undefined) {
|
|
return useSWR<RunBilling>(id ? queryKeys.runs.billing(id) : null, apiFetcher);
|
|
}
|
|
|
|
export function useRunQuestions(id: string | undefined, enabled: boolean) {
|
|
return useSWR<ApiQuestion[]>(
|
|
id && enabled ? queryKeys.runs.questions(id, 25, 0) : null,
|
|
async (key) => {
|
|
const payload = await apiNullableFetcher<{ data: ApiQuestion[] }>(key);
|
|
return payload?.data ?? [];
|
|
},
|
|
);
|
|
}
|
|
|
|
export function useRunStageEvents(id: string | undefined, stageId: string | undefined) {
|
|
return useSWR<EventEnvelope[]>(
|
|
id && stageId ? queryKeys.runs.stageEvents(id, stageId) : null,
|
|
fetchAllStageEvents<EventEnvelope>,
|
|
);
|
|
}
|
|
|
|
export function fetchRunCommandLog(
|
|
id: string,
|
|
stageId: string,
|
|
stream: CommandOutputStream,
|
|
offset: number,
|
|
limit?: number,
|
|
) {
|
|
return apiFetcher<CommandLogResponse>(
|
|
queryKeys.runs.stageLog(id, stageId, stream, offset, limit),
|
|
);
|
|
}
|
|
|
|
export function useWorkflows() {
|
|
return useSWR<PaginatedWorkflowListResponse | null>(
|
|
queryKeys.workflows.list(),
|
|
apiNullableFetcher,
|
|
immutableOptions,
|
|
);
|
|
}
|
|
|
|
export function useWorkflow(name: string | undefined) {
|
|
return useSWR<WorkflowDetailResponse | null>(
|
|
name ? queryKeys.workflows.detail(name) : null,
|
|
apiNullableFetcher,
|
|
immutableOptions,
|
|
);
|
|
}
|
|
|
|
export function useWorkflowRuns(name: string | undefined) {
|
|
return useSWR<PaginatedRunList | null>(
|
|
name ? queryKeys.workflows.runs(name) : null,
|
|
apiNullableFetcher,
|
|
);
|
|
}
|
|
|
|
export function useInsightsQueries() {
|
|
return useSWR(queryKeys.insights.queries(), apiFetcher, immutableOptions);
|
|
}
|
|
|
|
export function useInsightsHistory() {
|
|
return useSWR(queryKeys.insights.history(), apiFetcher, immutableOptions);
|
|
}
|
|
|
|
export function useServerSettings() {
|
|
return useSWR<ServerSettings>(queryKeys.settings.server(), apiFetcher, immutableOptions);
|
|
}
|
|
|
|
export { apiTextFetcher }; |