Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions src/app/dashboard/maintainer/PipelineBoard.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,38 @@ function makeBounty(overrides: Partial<Bounty> = {}): Bounty {
};
}

describe("PipelineBoard — 'View all N' link carries the column's status (#693)", () => {
function manyBounties(status: BountyStatus, count: number): Bounty[] {
return Array.from({ length: count }, (_, i) =>
makeBounty({ id: `${status}-${i}`, status }),
);
}

it("links to /issues?status=<column status> when a column overflows", () => {
render(<PipelineBoard bounties={manyBounties("funded", 10)} />);

const link = screen.getByRole("link", { name: /View all 10/ });
expect(link).toHaveAttribute("href", "/issues?status=funded");
});

it("carries the status for every pipeline column, not just the default facet values", () => {
const bounties = [
...manyBounties("claimed", 9),
...manyBounties("merged", 9),
];
render(<PipelineBoard bounties={bounties} />);

const claimedLink = screen
.getAllByRole("link", { name: /View all 9/ })
.find((link) => link.getAttribute("href") === "/issues?status=claimed");
const mergedLink = screen
.getAllByRole("link", { name: /View all 9/ })
.find((link) => link.getAttribute("href") === "/issues?status=merged");
expect(claimedLink).toBeDefined();
expect(mergedLink).toBeDefined();
});
});

describe("PipelineBoard — merged column (#88)", () => {
it("renders a bounty with status 'merged' in a visible pipeline column", () => {
const merged = makeBounty({ id: "merged-1", title: "Merged, awaiting payout", status: "merged" });
Expand Down
5 changes: 4 additions & 1 deletion src/app/dashboard/maintainer/PipelineBoard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,11 @@ export const ESCROW_LOCKED_EXCLUDED_STATUSES: BountyStatus[] = [
const MAX_VISIBLE_PER_COLUMN = 8;

function PipelineColumn({
status,
label,
bounties,
}: {
status: BountyStatus;
label: string;
bounties: Bounty[];
}) {
Expand Down Expand Up @@ -94,7 +96,7 @@ function PipelineColumn({
)}
{hiddenCount > 0 && (
<Link
href="/issues"
href={`/issues?status=${status}`}
className="block rounded-xl border border-dashed border-slate-200 px-3 py-2 text-center text-xs font-medium text-indigo-600 transition-colors hover:border-indigo-300 dark:border-slate-800 dark:text-indigo-400 dark:hover:border-indigo-700"
>
View all {bounties.length} in Bounty pipeline
Expand Down Expand Up @@ -128,6 +130,7 @@ export function PipelineBoard({ bounties }: { bounties: Bounty[] }) {
{pipelineStages.map((stage) => (
<PipelineColumn
key={stage.status}
status={stage.status}
label={stage.label}
bounties={byStatus.get(stage.status) ?? []}
/>
Expand Down
12 changes: 11 additions & 1 deletion src/lib/bounty-query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,17 @@ import type { Bounty } from "@/types";

export const PAGE_SIZE = 10;

export const STATUS_VALUES = ["all", "open", "in_review"] as const;
// Includes every status PipelineBoard renders a column for (#693) — a
// maintainer following a column's "View all N" link needs the facet to
// actually filter to that status, not silently fall back to "all".
export const STATUS_VALUES = [
"all",
"open",
"in_review",
"funded",
"claimed",
"merged",
] as const;
export type StatusFilter = (typeof STATUS_VALUES)[number];

export const DIFFICULTY_VALUES = [
Expand Down