mirror of
https://github.com/umami-software/umami.git
synced 2026-02-15 10:05:36 +01:00
145 lines
4.4 KiB
TypeScript
145 lines
4.4 KiB
TypeScript
import { Button, Column, Icon, Tooltip, TooltipTrigger } from '@umami/react-zen';
|
|
import { produce } from 'immer';
|
|
import { Fragment } from 'react';
|
|
import {
|
|
Group,
|
|
type GroupImperativeHandle,
|
|
Panel as ResizeablePanel,
|
|
Separator,
|
|
} from 'react-resizable-panels';
|
|
import { v4 as uuid } from 'uuid';
|
|
import { useBoard } from '@/components/hooks';
|
|
import { ChevronDown, Minus, Plus } from '@/components/icons';
|
|
import type { BoardColumn as BoardColumnType, BoardComponentConfig } from '@/lib/types';
|
|
import { BoardColumn } from './BoardColumn';
|
|
import { MAX_COLUMNS, MIN_COLUMN_WIDTH } from './boardConstants';
|
|
|
|
export function BoardRow({
|
|
rowId,
|
|
rowIndex,
|
|
rowCount,
|
|
columns,
|
|
editing = false,
|
|
onRemove,
|
|
onMoveUp,
|
|
onMoveDown,
|
|
onRegisterRef,
|
|
}: {
|
|
rowId: string;
|
|
rowIndex: number;
|
|
rowCount: number;
|
|
columns: BoardColumnType[];
|
|
editing?: boolean;
|
|
onRemove?: (id: string) => void;
|
|
onMoveUp?: (id: string) => void;
|
|
onMoveDown?: (id: string) => void;
|
|
onRegisterRef?: (rowId: string, ref: GroupImperativeHandle | null) => void;
|
|
}) {
|
|
const { board, updateBoard } = useBoard();
|
|
|
|
const handleGroupRef = (ref: GroupImperativeHandle | null) => {
|
|
onRegisterRef?.(rowId, ref);
|
|
};
|
|
|
|
const handleAddColumn = () => {
|
|
updateBoard({
|
|
parameters: produce(board.parameters, draft => {
|
|
const rowIndex = draft.rows.findIndex(row => row.id === rowId);
|
|
const row = draft.rows[rowIndex];
|
|
|
|
if (!row) {
|
|
draft.rows[rowIndex] = { id: uuid(), columns: [] };
|
|
}
|
|
row.columns.push({ id: uuid(), component: null });
|
|
}),
|
|
});
|
|
};
|
|
|
|
const handleRemoveColumn = (columnId: string) => {
|
|
updateBoard({
|
|
parameters: produce(board.parameters, draft => {
|
|
const row = draft.rows.find(row => row.id === rowId);
|
|
if (row) {
|
|
row.columns = row.columns.filter(col => col.id !== columnId);
|
|
}
|
|
}),
|
|
});
|
|
};
|
|
|
|
const handleSetComponent = (columnId: string, config: BoardComponentConfig | null) => {
|
|
updateBoard({
|
|
parameters: produce(board.parameters, draft => {
|
|
const row = draft.rows.find(row => row.id === rowId);
|
|
if (row) {
|
|
const col = row.columns.find(col => col.id === columnId);
|
|
if (col) {
|
|
col.component = config;
|
|
}
|
|
}
|
|
}),
|
|
});
|
|
};
|
|
|
|
return (
|
|
<Group groupRef={handleGroupRef} style={{ height: '100%' }}>
|
|
{columns?.map((column, index) => (
|
|
<Fragment key={column.id}>
|
|
<ResizeablePanel id={column.id} minSize={MIN_COLUMN_WIDTH} defaultSize={column.size}>
|
|
<BoardColumn
|
|
{...column}
|
|
editing={editing}
|
|
onRemove={handleRemoveColumn}
|
|
onSetComponent={handleSetComponent}
|
|
canRemove={columns?.length > 1}
|
|
/>
|
|
</ResizeablePanel>
|
|
{index < columns?.length - 1 && <Separator />}
|
|
</Fragment>
|
|
))}
|
|
{editing && (
|
|
<Column alignSelf="center" padding="3" gap="1">
|
|
<TooltipTrigger delay={0}>
|
|
<Button variant="outline" onPress={() => onMoveUp?.(rowId)} isDisabled={rowIndex === 0}>
|
|
<Icon rotate={180}>
|
|
<ChevronDown />
|
|
</Icon>
|
|
</Button>
|
|
<Tooltip placement="top">Move row up</Tooltip>
|
|
</TooltipTrigger>
|
|
<TooltipTrigger delay={0}>
|
|
<Button
|
|
variant="outline"
|
|
onPress={handleAddColumn}
|
|
isDisabled={columns?.length >= MAX_COLUMNS}
|
|
>
|
|
<Icon>
|
|
<Plus />
|
|
</Icon>
|
|
</Button>
|
|
<Tooltip placement="left">Add column</Tooltip>
|
|
</TooltipTrigger>
|
|
<TooltipTrigger delay={0}>
|
|
<Button variant="outline" onPress={() => onRemove?.(rowId)}>
|
|
<Icon>
|
|
<Minus />
|
|
</Icon>
|
|
</Button>
|
|
<Tooltip placement="left">Remove row</Tooltip>
|
|
</TooltipTrigger>
|
|
<TooltipTrigger delay={0}>
|
|
<Button
|
|
variant="outline"
|
|
onPress={() => onMoveDown?.(rowId)}
|
|
isDisabled={rowIndex === rowCount - 1}
|
|
>
|
|
<Icon>
|
|
<ChevronDown />
|
|
</Icon>
|
|
</Button>
|
|
<Tooltip placement="bottom">Move row down</Tooltip>
|
|
</TooltipTrigger>
|
|
</Column>
|
|
)}
|
|
</Group>
|
|
);
|
|
}
|