mirror of
https://github.com/umami-software/umami.git
synced 2026-02-15 18:15:35 +01:00
Split board view/edit rendering and isolate edit interactions
This commit is contained in:
parent
b09694ddb6
commit
d8c41ac8a6
15 changed files with 249 additions and 111 deletions
|
|
@ -99,7 +99,7 @@ export function BoardProvider({
|
|||
const saveBoard = useCallback(async () => {
|
||||
const defaultName = t(labels.untitled);
|
||||
|
||||
// Get current layout sizes from BoardBody if registered
|
||||
// Get current layout sizes from BoardEditBody if registered
|
||||
const layoutData = layoutGetterRef.current?.();
|
||||
const parameters = sanitizeBoardParameters(
|
||||
layoutData ? { ...board.parameters, ...layoutData } : board.parameters,
|
||||
|
|
|
|||
18
src/app/(main)/boards/[boardId]/BoardControls.tsx
Normal file
18
src/app/(main)/boards/[boardId]/BoardControls.tsx
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
import { Box } from '@umami/react-zen';
|
||||
import { WebsiteControls } from '@/app/(main)/websites/[websiteId]/WebsiteControls';
|
||||
import { useBoard } from '@/components/hooks';
|
||||
|
||||
export function BoardControls() {
|
||||
const { board } = useBoard();
|
||||
const websiteId = board?.parameters?.websiteId;
|
||||
|
||||
if (!websiteId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Box marginBottom="4">
|
||||
<WebsiteControls websiteId={websiteId} allowCompare={true} />
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
|
@ -4,16 +4,16 @@ import { Fragment, useEffect, useRef } from 'react';
|
|||
import { Group, type GroupImperativeHandle, Panel, Separator } from 'react-resizable-panels';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
import { useBoard } from '@/components/hooks';
|
||||
import { Plus } from '@/components/icons';
|
||||
import { BoardRow } from './BoardRow';
|
||||
import { GripHorizontal, Plus } from '@/components/icons';
|
||||
import styles from './BoardEditLayout.module.css';
|
||||
import { BoardEditRow } from './BoardEditRow';
|
||||
import { BUTTON_ROW_HEIGHT, MAX_ROW_HEIGHT, MIN_ROW_HEIGHT } from './boardConstants';
|
||||
|
||||
export function BoardBody() {
|
||||
const { board, editing, updateBoard, saveBoard, isPending, registerLayoutGetter } = useBoard();
|
||||
export function BoardEditBody() {
|
||||
const { board, updateBoard, registerLayoutGetter } = useBoard();
|
||||
const rowGroupRef = useRef<GroupImperativeHandle>(null);
|
||||
const columnGroupRefs = useRef<Map<string, GroupImperativeHandle>>(new Map());
|
||||
|
||||
// Register a function to get current layout sizes on save
|
||||
useEffect(() => {
|
||||
registerLayoutGetter(() => {
|
||||
const rows = board?.parameters?.rows;
|
||||
|
|
@ -104,9 +104,8 @@ export function BoardBody() {
|
|||
};
|
||||
|
||||
const websiteId = board?.parameters?.websiteId;
|
||||
const canEdit = editing && !!websiteId;
|
||||
const rows = board?.parameters?.rows ?? [];
|
||||
const minHeight = (rows?.length || 1) * MAX_ROW_HEIGHT + BUTTON_ROW_HEIGHT;
|
||||
const minHeight = (rows.length || 1) * MAX_ROW_HEIGHT + BUTTON_ROW_HEIGHT;
|
||||
|
||||
return (
|
||||
<Group groupRef={rowGroupRef} orientation="vertical" style={{ minHeight }}>
|
||||
|
|
@ -118,22 +117,30 @@ export function BoardBody() {
|
|||
maxSize={MAX_ROW_HEIGHT}
|
||||
defaultSize={row.size}
|
||||
>
|
||||
<BoardRow
|
||||
<BoardEditRow
|
||||
{...row}
|
||||
rowId={row.id}
|
||||
rowIndex={index}
|
||||
rowCount={rows?.length}
|
||||
editing={canEdit}
|
||||
rowCount={rows.length}
|
||||
canEdit={!!websiteId}
|
||||
onRemove={handleRemoveRow}
|
||||
onMoveUp={handleMoveRowUp}
|
||||
onMoveDown={handleMoveRowDown}
|
||||
onRegisterRef={registerColumnGroupRef}
|
||||
/>
|
||||
</Panel>
|
||||
{index < rows?.length - 1 && <Separator />}
|
||||
{index < rows.length - 1 && (
|
||||
<Separator className={styles.rowSeparator}>
|
||||
<span className={styles.separatorHandle}>
|
||||
<Icon size="sm">
|
||||
<GripHorizontal />
|
||||
</Icon>
|
||||
</span>
|
||||
</Separator>
|
||||
)}
|
||||
</Fragment>
|
||||
))}
|
||||
{canEdit && (
|
||||
{!!websiteId && (
|
||||
<Panel minSize={BUTTON_ROW_HEIGHT}>
|
||||
<Row padding="3">
|
||||
<TooltipTrigger delay={0}>
|
||||
|
|
@ -1,34 +1,27 @@
|
|||
import {
|
||||
Box,
|
||||
Button,
|
||||
Column,
|
||||
Dialog,
|
||||
Icon,
|
||||
Modal,
|
||||
Tooltip,
|
||||
TooltipTrigger,
|
||||
} from '@umami/react-zen';
|
||||
import { Box, Button, Dialog, Icon, Modal, Tooltip, TooltipTrigger } from '@umami/react-zen';
|
||||
import { useMemo, useState } from 'react';
|
||||
import { Panel } from '@/components/common/Panel';
|
||||
import { useBoard, useMessages } from '@/components/hooks';
|
||||
import { Pencil, Plus, X } from '@/components/icons';
|
||||
import type { BoardComponentConfig } from '@/lib/types';
|
||||
import { getComponentDefinition } from '../boardComponentRegistry';
|
||||
import styles from './BoardColumn.module.css';
|
||||
import { BoardComponentRenderer } from './BoardComponentRenderer';
|
||||
import { BoardComponentSelect } from './BoardComponentSelect';
|
||||
|
||||
export function BoardColumn({
|
||||
export function BoardEditColumn({
|
||||
id,
|
||||
component,
|
||||
editing = false,
|
||||
canEdit,
|
||||
onRemove,
|
||||
onSetComponent,
|
||||
canRemove = true,
|
||||
}: {
|
||||
id: string;
|
||||
component?: BoardComponentConfig;
|
||||
editing?: boolean;
|
||||
onRemove?: (id: string) => void;
|
||||
onSetComponent?: (id: string, config: BoardComponentConfig | null) => void;
|
||||
canEdit: boolean;
|
||||
onRemove: (id: string) => void;
|
||||
onSetComponent: (id: string, config: BoardComponentConfig | null) => void;
|
||||
canRemove?: boolean;
|
||||
}) {
|
||||
const [showSelect, setShowSelect] = useState(false);
|
||||
|
|
@ -44,32 +37,33 @@ export function BoardColumn({
|
|||
}, [component, websiteId]);
|
||||
|
||||
const handleSelect = (config: BoardComponentConfig) => {
|
||||
onSetComponent?.(id, config);
|
||||
onSetComponent(id, config);
|
||||
setShowSelect(false);
|
||||
};
|
||||
|
||||
const hasComponent = !!component;
|
||||
const canRemoveAction = hasComponent || canRemove;
|
||||
const title = component ? getComponentDefinition(component.type)?.name : undefined;
|
||||
|
||||
const handleRemove = () => {
|
||||
if (hasComponent) {
|
||||
onSetComponent?.(id, null);
|
||||
onSetComponent(id, null);
|
||||
} else {
|
||||
onRemove?.(id);
|
||||
onRemove(id);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Column
|
||||
<Panel
|
||||
title={title}
|
||||
width="100%"
|
||||
height="100%"
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
backgroundColor="surface-sunken"
|
||||
position="relative"
|
||||
className={styles.column}
|
||||
>
|
||||
{editing && canRemoveAction && (
|
||||
{canEdit && canRemoveAction && (
|
||||
<Box
|
||||
className={styles.columnAction}
|
||||
position="absolute"
|
||||
|
|
@ -92,7 +86,7 @@ export function BoardColumn({
|
|||
<Box width="100%" height="100%" overflow="auto">
|
||||
{renderedComponent}
|
||||
</Box>
|
||||
{editing && (
|
||||
{canEdit && (
|
||||
<Box
|
||||
className={styles.columnAction}
|
||||
position="absolute"
|
||||
|
|
@ -112,7 +106,7 @@ export function BoardColumn({
|
|||
)}
|
||||
</>
|
||||
) : (
|
||||
editing && (
|
||||
canEdit && (
|
||||
<Button variant="outline" onPress={() => setShowSelect(true)}>
|
||||
<Icon>
|
||||
<Plus />
|
||||
|
|
@ -139,6 +133,6 @@ export function BoardColumn({
|
|||
)}
|
||||
</Dialog>
|
||||
</Modal>
|
||||
</Column>
|
||||
</Panel>
|
||||
);
|
||||
}
|
||||
46
src/app/(main)/boards/[boardId]/BoardEditLayout.module.css
Normal file
46
src/app/(main)/boards/[boardId]/BoardEditLayout.module.css
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
.columnSeparator {
|
||||
width: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: col-resize;
|
||||
}
|
||||
|
||||
.rowSeparator {
|
||||
height: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: row-resize;
|
||||
}
|
||||
|
||||
.separatorHandle {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: var(--gray-9);
|
||||
}
|
||||
|
||||
.rowGroup {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.rowActions {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: 12px;
|
||||
transform: translateY(-50%);
|
||||
z-index: 20;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
pointer-events: none;
|
||||
transition: opacity 120ms ease;
|
||||
}
|
||||
|
||||
.rowGroup:hover .rowActions,
|
||||
.rowGroup:focus-within .rowActions {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
pointer-events: auto;
|
||||
}
|
||||
21
src/app/(main)/boards/[boardId]/BoardEditPage.tsx
Normal file
21
src/app/(main)/boards/[boardId]/BoardEditPage.tsx
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
'use client';
|
||||
import { Column } from '@umami/react-zen';
|
||||
import { BoardProvider } from '@/app/(main)/boards/BoardProvider';
|
||||
import { PageBody } from '@/components/common/PageBody';
|
||||
import { BoardControls } from './BoardControls';
|
||||
import { BoardEditBody } from './BoardEditBody';
|
||||
import { BoardEditHeader } from './BoardEditHeader';
|
||||
|
||||
export function BoardEditPage({ boardId }: { boardId?: string }) {
|
||||
return (
|
||||
<BoardProvider boardId={boardId} editing>
|
||||
<PageBody>
|
||||
<Column>
|
||||
<BoardEditHeader />
|
||||
<BoardControls />
|
||||
<BoardEditBody />
|
||||
</Column>
|
||||
</PageBody>
|
||||
</BoardProvider>
|
||||
);
|
||||
}
|
||||
|
|
@ -4,22 +4,23 @@ import { Fragment } from 'react';
|
|||
import {
|
||||
Group,
|
||||
type GroupImperativeHandle,
|
||||
Panel as ResizeablePanel,
|
||||
Panel as ResizablePanel,
|
||||
Separator,
|
||||
} from 'react-resizable-panels';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
import { useBoard } from '@/components/hooks';
|
||||
import { ChevronDown, Minus, Plus } from '@/components/icons';
|
||||
import { ChevronDown, GripVertical, Minus, Plus } from '@/components/icons';
|
||||
import type { BoardColumn as BoardColumnType, BoardComponentConfig } from '@/lib/types';
|
||||
import { BoardColumn } from './BoardColumn';
|
||||
import { BoardEditColumn } from './BoardEditColumn';
|
||||
import styles from './BoardEditLayout.module.css';
|
||||
import { MAX_COLUMNS, MIN_COLUMN_WIDTH } from './boardConstants';
|
||||
|
||||
export function BoardRow({
|
||||
export function BoardEditRow({
|
||||
rowId,
|
||||
rowIndex,
|
||||
rowCount,
|
||||
columns,
|
||||
editing = false,
|
||||
canEdit,
|
||||
onRemove,
|
||||
onMoveUp,
|
||||
onMoveDown,
|
||||
|
|
@ -29,16 +30,16 @@ export function BoardRow({
|
|||
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;
|
||||
canEdit: 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);
|
||||
onRegisterRef(rowId, ref);
|
||||
};
|
||||
|
||||
const handleAddColumn = () => {
|
||||
|
|
@ -81,25 +82,33 @@ export function BoardRow({
|
|||
};
|
||||
|
||||
return (
|
||||
<Group groupRef={handleGroupRef} style={{ height: '100%' }}>
|
||||
<Group groupRef={handleGroupRef} className={styles.rowGroup}>
|
||||
{columns?.map((column, index) => (
|
||||
<Fragment key={column.id}>
|
||||
<ResizeablePanel id={column.id} minSize={MIN_COLUMN_WIDTH} defaultSize={column.size}>
|
||||
<BoardColumn
|
||||
<ResizablePanel id={column.id} minSize={MIN_COLUMN_WIDTH} defaultSize={column.size}>
|
||||
<BoardEditColumn
|
||||
{...column}
|
||||
editing={editing}
|
||||
canEdit={canEdit}
|
||||
onRemove={handleRemoveColumn}
|
||||
onSetComponent={handleSetComponent}
|
||||
canRemove={columns?.length > 1}
|
||||
canRemove={columns.length > 1}
|
||||
/>
|
||||
</ResizeablePanel>
|
||||
{index < columns?.length - 1 && <Separator />}
|
||||
</ResizablePanel>
|
||||
{index < columns.length - 1 && (
|
||||
<Separator className={styles.columnSeparator}>
|
||||
<span className={styles.separatorHandle}>
|
||||
<Icon size="sm">
|
||||
<GripVertical />
|
||||
</Icon>
|
||||
</span>
|
||||
</Separator>
|
||||
)}
|
||||
</Fragment>
|
||||
))}
|
||||
{editing && (
|
||||
<Column alignSelf="center" padding="3" gap="1">
|
||||
{canEdit && (
|
||||
<Column className={styles.rowActions} padding="3" gap="1">
|
||||
<TooltipTrigger delay={0}>
|
||||
<Button variant="outline" onPress={() => onMoveUp?.(rowId)} isDisabled={rowIndex === 0}>
|
||||
<Button variant="outline" onPress={() => onMoveUp(rowId)} isDisabled={rowIndex === 0}>
|
||||
<Icon rotate={180}>
|
||||
<ChevronDown />
|
||||
</Icon>
|
||||
|
|
@ -110,7 +119,7 @@ export function BoardRow({
|
|||
<Button
|
||||
variant="outline"
|
||||
onPress={handleAddColumn}
|
||||
isDisabled={columns?.length >= MAX_COLUMNS}
|
||||
isDisabled={columns.length >= MAX_COLUMNS}
|
||||
>
|
||||
<Icon>
|
||||
<Plus />
|
||||
|
|
@ -119,7 +128,7 @@ export function BoardRow({
|
|||
<Tooltip placement="left">Add column</Tooltip>
|
||||
</TooltipTrigger>
|
||||
<TooltipTrigger delay={0}>
|
||||
<Button variant="outline" onPress={() => onRemove?.(rowId)}>
|
||||
<Button variant="outline" onPress={() => onRemove(rowId)}>
|
||||
<Icon>
|
||||
<Minus />
|
||||
</Icon>
|
||||
|
|
@ -129,7 +138,7 @@ export function BoardRow({
|
|||
<TooltipTrigger delay={0}>
|
||||
<Button
|
||||
variant="outline"
|
||||
onPress={() => onMoveDown?.(rowId)}
|
||||
onPress={() => onMoveDown(rowId)}
|
||||
isDisabled={rowIndex === rowCount - 1}
|
||||
>
|
||||
<Icon>
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
import { useBoard } from '@/components/hooks';
|
||||
import { BoardEditHeader } from './BoardEditHeader';
|
||||
import { BoardViewHeader } from './BoardViewHeader';
|
||||
|
||||
export function BoardHeader() {
|
||||
const { board, editing } = useBoard();
|
||||
|
||||
if (editing) {
|
||||
return <BoardEditHeader />;
|
||||
}
|
||||
|
||||
return <BoardViewHeader />;
|
||||
}
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
'use client';
|
||||
import { Column } from '@umami/react-zen';
|
||||
import { BoardBody } from '@/app/(main)/boards/[boardId]/BoardBody';
|
||||
import { BoardHeader } from '@/app/(main)/boards/[boardId]/BoardHeader';
|
||||
import { BoardProvider } from '@/app/(main)/boards/BoardProvider';
|
||||
import { WebsiteControls } from '@/app/(main)/websites/[websiteId]/WebsiteControls';
|
||||
import { PageBody } from '@/components/common/PageBody';
|
||||
import { useBoard } from '@/components/hooks';
|
||||
|
||||
export function BoardPage({ boardId, editing = false }: { boardId?: string; editing?: boolean }) {
|
||||
return (
|
||||
<BoardProvider boardId={boardId} editing={editing}>
|
||||
<PageBody>
|
||||
<Column>
|
||||
<BoardHeader />
|
||||
<BoardControls />
|
||||
<BoardBody />
|
||||
</Column>
|
||||
</PageBody>
|
||||
</BoardProvider>
|
||||
);
|
||||
}
|
||||
|
||||
function BoardControls() {
|
||||
const { board } = useBoard();
|
||||
const websiteId = board?.parameters?.websiteId;
|
||||
|
||||
if (!websiteId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return <WebsiteControls websiteId={websiteId} allowCompare={true} />;
|
||||
}
|
||||
15
src/app/(main)/boards/[boardId]/BoardViewBody.tsx
Normal file
15
src/app/(main)/boards/[boardId]/BoardViewBody.tsx
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
import { useBoard } from '@/components/hooks';
|
||||
import { BoardViewRow } from './BoardViewRow';
|
||||
|
||||
export function BoardViewBody() {
|
||||
const { board } = useBoard();
|
||||
const rows = board?.parameters?.rows ?? [];
|
||||
|
||||
return (
|
||||
<div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
|
||||
{rows.map(row => (
|
||||
<BoardViewRow key={row.id} columns={row.columns} />
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
27
src/app/(main)/boards/[boardId]/BoardViewColumn.tsx
Normal file
27
src/app/(main)/boards/[boardId]/BoardViewColumn.tsx
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
import { Box, Column } from '@umami/react-zen';
|
||||
import { Panel } from '@/components/common/Panel';
|
||||
import { useBoard } from '@/components/hooks';
|
||||
import type { BoardComponentConfig } from '@/lib/types';
|
||||
import { getComponentDefinition } from '../boardComponentRegistry';
|
||||
import { BoardComponentRenderer } from './BoardComponentRenderer';
|
||||
|
||||
export function BoardViewColumn({ component }: { component?: BoardComponentConfig }) {
|
||||
const { board } = useBoard();
|
||||
const websiteId = board?.parameters?.websiteId;
|
||||
|
||||
if (!component || !websiteId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const title = getComponentDefinition(component.type)?.name;
|
||||
|
||||
return (
|
||||
<Panel title={title} height="100%">
|
||||
<Column width="100%" height="100%">
|
||||
<Box width="100%" overflow="auto">
|
||||
<BoardComponentRenderer config={component} websiteId={websiteId} />
|
||||
</Box>
|
||||
</Column>
|
||||
</Panel>
|
||||
);
|
||||
}
|
||||
21
src/app/(main)/boards/[boardId]/BoardViewPage.tsx
Normal file
21
src/app/(main)/boards/[boardId]/BoardViewPage.tsx
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
'use client';
|
||||
import { Column } from '@umami/react-zen';
|
||||
import { BoardProvider } from '@/app/(main)/boards/BoardProvider';
|
||||
import { PageBody } from '@/components/common/PageBody';
|
||||
import { BoardControls } from './BoardControls';
|
||||
import { BoardViewBody } from './BoardViewBody';
|
||||
import { BoardViewHeader } from './BoardViewHeader';
|
||||
|
||||
export function BoardViewPage({ boardId }: { boardId: string }) {
|
||||
return (
|
||||
<BoardProvider boardId={boardId}>
|
||||
<PageBody>
|
||||
<Column>
|
||||
<BoardViewHeader />
|
||||
<BoardControls />
|
||||
<BoardViewBody />
|
||||
</Column>
|
||||
</PageBody>
|
||||
</BoardProvider>
|
||||
);
|
||||
}
|
||||
21
src/app/(main)/boards/[boardId]/BoardViewRow.tsx
Normal file
21
src/app/(main)/boards/[boardId]/BoardViewRow.tsx
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
import type { BoardColumn } from '@/lib/types';
|
||||
import { BoardViewColumn } from './BoardViewColumn';
|
||||
import { MIN_COLUMN_WIDTH } from './boardConstants';
|
||||
|
||||
export function BoardViewRow({ columns }: { columns: BoardColumn[] }) {
|
||||
return (
|
||||
<div style={{ display: 'flex', gap: 12, width: '100%', overflowX: 'auto' }}>
|
||||
{columns.map(column => (
|
||||
<div
|
||||
key={column.id}
|
||||
style={{
|
||||
flex: `${column.size ?? 1} 1 0%`,
|
||||
minWidth: MIN_COLUMN_WIDTH,
|
||||
}}
|
||||
>
|
||||
<BoardViewColumn component={column.component} />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
import type { Metadata } from 'next';
|
||||
import { BoardPage } from '../BoardPage';
|
||||
import { BoardEditPage } from '../BoardEditPage';
|
||||
|
||||
export default async function ({ params }: { params: Promise<{ boardId: string }> }) {
|
||||
const { boardId } = await params;
|
||||
|
||||
return <BoardPage boardId={boardId} editing />;
|
||||
return <BoardEditPage boardId={boardId} />;
|
||||
}
|
||||
|
||||
export const metadata: Metadata = {
|
||||
|
|
|
|||
|
|
@ -1,11 +1,16 @@
|
|||
import type { Metadata } from 'next';
|
||||
import { BoardPage } from './BoardPage';
|
||||
import { BoardEditPage } from './BoardEditPage';
|
||||
import { BoardViewPage } from './BoardViewPage';
|
||||
|
||||
export default async function ({ params }: { params: Promise<{ boardId: string }> }) {
|
||||
const { boardId } = await params;
|
||||
const isCreate = boardId === 'create';
|
||||
|
||||
return <BoardPage boardId={isCreate ? undefined : boardId} editing={isCreate} />;
|
||||
if (isCreate) {
|
||||
return <BoardEditPage />;
|
||||
}
|
||||
|
||||
return <BoardViewPage boardId={boardId} />;
|
||||
}
|
||||
|
||||
export const metadata: Metadata = {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue