39 lines
1.8 KiB
TypeScript
39 lines
1.8 KiB
TypeScript
import type { Project } from "../../../api/types.ts";
|
||
import { PageHeader } from "../../../ui/index.ts";
|
||
import { RefreshButton } from "../RefreshButton.tsx";
|
||
import { AgileGate } from "./AgileGate.tsx";
|
||
import { BoardColumns } from "./BoardColumns.tsx";
|
||
import { columnsOf } from "./columns.ts";
|
||
import { AgileIssueRow } from "./IssueRow.tsx";
|
||
import "./agile.css";
|
||
|
||
// «Kanban» (spec web-app): колонки доски; при включённом бэклоге Jira первая колонка не рисуется, её задачи — в «Бэклог (N)» (R-18)
|
||
export function KanbanPage({ project }: { project: Project }) {
|
||
return (
|
||
<div data-testid="page-kanban" className="agile agile--wide">
|
||
<PageHeader title="Kanban" actions={<RefreshButton />} />
|
||
<AgileGate project={project} kind="kanban">
|
||
{(d) => {
|
||
const withBacklog = d.board?.kanban_backlog === true;
|
||
const cols = d.board?.columns ?? null;
|
||
// задачи первой колонки уходят в «Бэклог», а не в «Без колонки»
|
||
const first = new Set(withBacklog && cols ? cols[0]?.statuses ?? [] : []);
|
||
const issues = (d.board_issues ?? []).filter((i) => i.status === null || !first.has(i.status));
|
||
const backlog = d.backlog ?? [];
|
||
return (
|
||
<>
|
||
{withBacklog && (
|
||
<details className="agile-past">
|
||
<summary>{`Бэклог (${backlog.length})`}</summary>
|
||
<ul className="agile-list">{backlog.map((i) => <AgileIssueRow key={i.key} issue={i} />)}</ul>
|
||
</details>
|
||
)}
|
||
<BoardColumns columns={columnsOf(withBacklog && cols ? cols.slice(1) : cols, issues)} lastCaption="за 14 дней" />
|
||
</>
|
||
);
|
||
}}
|
||
</AgileGate>
|
||
</div>
|
||
);
|
||
}
|