feat(web): upgrade lists to ReUI Table v9 and EventCalendar
quality / commitlint (push) Skipped
quality / changes (push) Successful in 9s
quality / docker-check (push) Skipped
quality / openapi (push) Successful in 39s
quality / web (push) Successful in 1m29s
quality / go (push) Successful in 1m3s
quality / bird2 (push) Successful in 15s
CD / quality (push) Successful in 3m43s
CD / publish (push) Failing after 8m29s
quality / commitlint (push) Skipped
quality / changes (push) Successful in 9s
quality / docker-check (push) Skipped
quality / openapi (push) Successful in 39s
quality / web (push) Successful in 1m29s
quality / go (push) Successful in 1m3s
quality / bird2 (push) Successful in 15s
CD / quality (push) Successful in 3m43s
CD / publish (push) Failing after 8m29s
Единый kitDataGridTableLayout и ResourcePage/FrameDataGrid на всех списках. Календарь задач переведён на EventCalendar, lookup — на cascader, у операций появился вид доски. Удалены settings-7 и самописные DataGridSection/toolbar. Co-authored-by: Cursor <[email protected]>
This commit is contained in:
@@ -0,0 +1,113 @@
|
||||
import { useMemo } from 'react'
|
||||
|
||||
import { DataGridMutedCell } from '@/components/data-grid-cell'
|
||||
import { StatusBadge } from '@/components/status-badge'
|
||||
import {
|
||||
Kanban,
|
||||
KanbanBoard,
|
||||
KanbanColumn,
|
||||
KanbanColumnContent,
|
||||
KanbanItem,
|
||||
} from '@/components/reui/kanban'
|
||||
import { Frame, FramePanel } from '@/components/reui/frame'
|
||||
import { jobKindRu } from '@/lib/ui-labels'
|
||||
import type { JobRow } from '@/types/api'
|
||||
|
||||
/**
|
||||
* Operations jobs board view — ReUI Kanban (read-only columns).
|
||||
* @see https://reui.io/docs/components/base/kanban
|
||||
* @see https://reui.io/docs/components/base/frame
|
||||
*/
|
||||
|
||||
const COLUMN_ORDER = ['queued', 'running', 'succeeded', 'failed'] as const
|
||||
|
||||
const COLUMN_LABELS: Record<(typeof COLUMN_ORDER)[number], string> = {
|
||||
queued: 'Очередь',
|
||||
running: 'Выполняются',
|
||||
succeeded: 'Успешные',
|
||||
failed: 'Ошибки',
|
||||
}
|
||||
|
||||
function columnForStatus(status: string): (typeof COLUMN_ORDER)[number] {
|
||||
const s = status.toLowerCase()
|
||||
if (s === 'queued') return 'queued'
|
||||
if (s === 'running') return 'running'
|
||||
if (s === 'succeeded') return 'succeeded'
|
||||
return 'failed'
|
||||
}
|
||||
|
||||
function emptyColumns(): Record<string, JobRow[]> {
|
||||
return {
|
||||
queued: [],
|
||||
running: [],
|
||||
succeeded: [],
|
||||
failed: [],
|
||||
}
|
||||
}
|
||||
|
||||
export function OperationsJobsKanban({
|
||||
items,
|
||||
nameById,
|
||||
}: {
|
||||
items: JobRow[]
|
||||
nameById: Map<string, string>
|
||||
}) {
|
||||
const columns = useMemo(() => {
|
||||
const next = emptyColumns()
|
||||
for (const job of items) {
|
||||
next[columnForStatus(job.status)].push(job)
|
||||
}
|
||||
return next
|
||||
}, [items])
|
||||
|
||||
return (
|
||||
<Frame dense spacing="sm" className="w-full min-w-0">
|
||||
<FramePanel className="p-4">
|
||||
<Kanban
|
||||
value={columns}
|
||||
onValueChange={() => undefined}
|
||||
getItemValue={(job) => job.job_id}
|
||||
>
|
||||
<KanbanBoard className="grid auto-rows-fr grid-cols-1 gap-4 sm:grid-cols-2 xl:grid-cols-4">
|
||||
{COLUMN_ORDER.map((columnId) => (
|
||||
<KanbanColumn
|
||||
key={columnId}
|
||||
value={columnId}
|
||||
disabled
|
||||
className="bg-muted/30 flex min-h-40 flex-col gap-3 rounded-lg border p-3"
|
||||
>
|
||||
<div className="flex items-center justify-between gap-2">
|
||||
<p className="text-sm font-medium">{COLUMN_LABELS[columnId]}</p>
|
||||
<span className="text-muted-foreground text-xs tabular-nums">
|
||||
{columns[columnId]?.length ?? 0}
|
||||
</span>
|
||||
</div>
|
||||
<KanbanColumnContent value={columnId}>
|
||||
{(columns[columnId] ?? []).map((job) => (
|
||||
<KanbanItem
|
||||
key={job.job_id}
|
||||
value={job.job_id}
|
||||
disabled
|
||||
className="bg-background flex flex-col gap-1 rounded-md border p-3"
|
||||
>
|
||||
<p className="text-sm leading-tight font-medium">
|
||||
{jobKindRu(job.kind)}
|
||||
</p>
|
||||
<StatusBadge status={job.status} />
|
||||
{job.meta?.module_id ? (
|
||||
<DataGridMutedCell>
|
||||
{nameById.get(String(job.meta.module_id)) ??
|
||||
String(job.meta.module_id)}
|
||||
</DataGridMutedCell>
|
||||
) : null}
|
||||
</KanbanItem>
|
||||
))}
|
||||
</KanbanColumnContent>
|
||||
</KanbanColumn>
|
||||
))}
|
||||
</KanbanBoard>
|
||||
</Kanban>
|
||||
</FramePanel>
|
||||
</Frame>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user