mirror of
https://github.com/fabro-sh/fabro.git
synced 2026-08-28 05:27:41 +00:00
Populate repo and workflow filters in runs list view
The Repo and Workflow dropdowns on the runs page derived their options from the board query, which is disabled in list view. With ?view=list, the options were always empty even when runs were visible. Derive the options from whichever data source the current view loads: the board query in columns view, or the current page of the paginated list query in list view. Extract the option-building into an exported buildFilterOptions helper that also keeps the active selection in the options when no loaded run matches it, so the filter button never renders an undefined label while paginating. A future change will replace page-derived options with a facets endpoint plus server-side repo/workflow query params. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
0abf2297c0
commit
57547ed7b6
2 changed files with 57 additions and 11 deletions
|
|
@ -3,6 +3,7 @@ import type { BoardColumn, Run } from "@qltysh/fabro-api-client";
|
|||
|
||||
import {
|
||||
buildBoardColumns,
|
||||
buildFilterOptions,
|
||||
loadStoredRunsWorkspaceSearchParams,
|
||||
placeArchivedColumnLast,
|
||||
persistRunsWorkspacePreferences,
|
||||
|
|
@ -11,6 +12,7 @@ import {
|
|||
shouldRefreshBoardForEvent,
|
||||
} from "./runs";
|
||||
import { summarizeBatchLifecycleAction } from "../components/runs-list/batch-lifecycle";
|
||||
import { mapRunListItem } from "../data/runs";
|
||||
import { TEST_PRINCIPAL } from "../lib/test-fixtures";
|
||||
|
||||
function boardRun(id: string, column: BoardColumn, questionText?: string): Run {
|
||||
|
|
@ -217,6 +219,38 @@ describe("runs route board mapping", () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe("runs route filter options", () => {
|
||||
function runWith(id: string, repoName: string, workflowName: string): Run {
|
||||
const run = boardRun(id, "running");
|
||||
return {
|
||||
...run,
|
||||
repository: { ...run.repository, name: repoName },
|
||||
workflow: { ...run.workflow, name: workflowName },
|
||||
};
|
||||
}
|
||||
|
||||
test("derives sorted unique options from run items", () => {
|
||||
const items = [
|
||||
runWith("a", "qlty/beta", "release"),
|
||||
runWith("b", "qlty/alpha", "hello"),
|
||||
runWith("c", "qlty/beta", "release"),
|
||||
].map(mapRunListItem);
|
||||
|
||||
expect(buildFilterOptions(items, (item) => item.repo, "all")).toEqual(["alpha", "beta"]);
|
||||
expect(buildFilterOptions(items, (item) => item.workflow, "all")).toEqual([
|
||||
"hello",
|
||||
"release",
|
||||
]);
|
||||
});
|
||||
|
||||
test("keeps the active selection when no loaded run matches it", () => {
|
||||
const items = [runWith("a", "qlty/beta", "release")].map(mapRunListItem);
|
||||
|
||||
expect(buildFilterOptions(items, (item) => item.repo, "gamma")).toEqual(["beta", "gamma"]);
|
||||
expect(buildFilterOptions([], (item) => item.workflow, "release")).toEqual(["release"]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("runs route workspace preferences", () => {
|
||||
class MemoryStorage {
|
||||
values = new Map<string, string>();
|
||||
|
|
|
|||
|
|
@ -140,6 +140,18 @@ export function buildBoardColumns(
|
|||
});
|
||||
}
|
||||
|
||||
export function buildFilterOptions(
|
||||
items: RunItem[],
|
||||
pick: (item: RunItem) => string,
|
||||
selected: string,
|
||||
): string[] {
|
||||
const values = new Set(items.map(pick));
|
||||
// Keep the active selection visible even when no loaded run matches it,
|
||||
// e.g. a stored repo filter while paginating the list view.
|
||||
if (selected !== "all") values.add(selected);
|
||||
return Array.from(values).sort();
|
||||
}
|
||||
|
||||
export function placeArchivedColumnLast(columns: Column[], includeArchived: boolean): Column[] {
|
||||
if (!includeArchived) return columns;
|
||||
const archived = columns.find((column) => column.id === "archived");
|
||||
|
|
@ -771,18 +783,18 @@ export default function Runs() {
|
|||
);
|
||||
const hasGitHubAuth = authConfig.data?.methods.includes("github") === true;
|
||||
const serverUrl = systemInfo.data?.server_url;
|
||||
const allRepos = Array.from(
|
||||
new Set(
|
||||
initialColumns.flatMap((col: Column) => col.items.map((item: RunItem) => String(item.repo))),
|
||||
),
|
||||
// Filter options come from the loaded runs: all runs in columns view, the
|
||||
// current page in list view (until a facets endpoint provides the full set).
|
||||
const filterSourceItems: RunItem[] =
|
||||
view === "list"
|
||||
? (listRunsPage.data?.data ?? []).map(mapRunListItem)
|
||||
: initialColumns.flatMap((col: Column) => col.items);
|
||||
const allRepos = buildFilterOptions(filterSourceItems, (item) => item.repo, repoFilter);
|
||||
const allWorkflows = buildFilterOptions(
|
||||
filterSourceItems,
|
||||
(item) => item.workflow,
|
||||
workflowFilter,
|
||||
);
|
||||
allRepos.sort();
|
||||
const allWorkflows = Array.from(
|
||||
new Set(
|
||||
initialColumns.flatMap((col: Column) => col.items.map((item: RunItem) => String(item.workflow))),
|
||||
),
|
||||
);
|
||||
allWorkflows.sort();
|
||||
const [columnsState, setColumnsState] = useState(() => ({
|
||||
base: initialColumns,
|
||||
columns: initialColumns,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue