mirror of
https://github.com/docmost/docmost.git
synced 2026-08-30 10:26:25 +08:00
feat(bases): add per-column '+ New' button to kanban
This commit is contained in:
@@ -3,9 +3,11 @@ import {
|
|||||||
IBase,
|
IBase,
|
||||||
IBaseRow,
|
IBaseRow,
|
||||||
IBaseView,
|
IBaseView,
|
||||||
|
NO_VALUE_CHOICE_ID,
|
||||||
} from "@/features/base/types/base.types";
|
} from "@/features/base/types/base.types";
|
||||||
import { useKanbanGroups } from "@/features/base/hooks/use-kanban-groups";
|
import { useKanbanGroups } from "@/features/base/hooks/use-kanban-groups";
|
||||||
import { useUpdateViewMutation } from "@/features/base/queries/base-view-query";
|
import { useUpdateViewMutation } from "@/features/base/queries/base-view-query";
|
||||||
|
import { useCreateRowMutation } from "@/features/base/queries/base-row-query";
|
||||||
import { KanbanColumn } from "./kanban-column";
|
import { KanbanColumn } from "./kanban-column";
|
||||||
import { KanbanEmptyState } from "./kanban-empty-state";
|
import { KanbanEmptyState } from "./kanban-empty-state";
|
||||||
import classes from "@/features/base/styles/kanban.module.css";
|
import classes from "@/features/base/styles/kanban.module.css";
|
||||||
@@ -37,6 +39,7 @@ export function BaseKanban({
|
|||||||
);
|
);
|
||||||
const isGroupable = property?.type === "select" || property?.type === "status";
|
const isGroupable = property?.type === "select" || property?.type === "status";
|
||||||
const updateViewMutation = useUpdateViewMutation();
|
const updateViewMutation = useUpdateViewMutation();
|
||||||
|
const createRowMutation = useCreateRowMutation();
|
||||||
|
|
||||||
// Rules of Hooks: call useKanbanGroups unconditionally with `undefined`
|
// Rules of Hooks: call useKanbanGroups unconditionally with `undefined`
|
||||||
// when not groupable; switch the render path on isGroupable below.
|
// when not groupable; switch the render path on isGroupable below.
|
||||||
@@ -56,6 +59,21 @@ export function BaseKanban({
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleAddCard = (columnKey: string) => {
|
||||||
|
if (!groupByPropertyId) return;
|
||||||
|
const cells =
|
||||||
|
columnKey === NO_VALUE_CHOICE_ID
|
||||||
|
? {}
|
||||||
|
: { [groupByPropertyId]: columnKey };
|
||||||
|
const column = columns.find((c) => c.key === columnKey);
|
||||||
|
const afterRowId = column?.rows[column.rows.length - 1]?.id;
|
||||||
|
createRowMutation.mutate({
|
||||||
|
pageId: base.id,
|
||||||
|
cells,
|
||||||
|
afterRowId,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
if (!isGroupable) {
|
if (!isGroupable) {
|
||||||
return <KanbanEmptyState base={base} onPick={handlePickProperty} />;
|
return <KanbanEmptyState base={base} onPick={handlePickProperty} />;
|
||||||
}
|
}
|
||||||
@@ -68,6 +86,7 @@ export function BaseKanban({
|
|||||||
column={column}
|
column={column}
|
||||||
primaryProperty={primaryProperty}
|
primaryProperty={primaryProperty}
|
||||||
onCardClick={onCardClick}
|
onCardClick={onCardClick}
|
||||||
|
onAddCard={handleAddCard}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
import { Button } from "@mantine/core";
|
||||||
|
import { IconPlus } from "@tabler/icons-react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import classes from "@/features/base/styles/kanban.module.css";
|
||||||
|
|
||||||
|
type KanbanAddCardButtonProps = {
|
||||||
|
onClick: () => void;
|
||||||
|
disabled?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function KanbanAddCardButton({
|
||||||
|
onClick,
|
||||||
|
disabled,
|
||||||
|
}: KanbanAddCardButtonProps) {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
variant="subtle"
|
||||||
|
color="gray"
|
||||||
|
size="xs"
|
||||||
|
className={classes.addCardButton}
|
||||||
|
leftSection={<IconPlus size={14} />}
|
||||||
|
onClick={onClick}
|
||||||
|
disabled={disabled}
|
||||||
|
>
|
||||||
|
{t("New")}
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -2,18 +2,21 @@ import { KanbanColumnData } from "@/features/base/hooks/use-kanban-groups";
|
|||||||
import { IBaseProperty } from "@/features/base/types/base.types";
|
import { IBaseProperty } from "@/features/base/types/base.types";
|
||||||
import { KanbanCard } from "./kanban-card";
|
import { KanbanCard } from "./kanban-card";
|
||||||
import { KanbanColumnHeader } from "./kanban-column-header";
|
import { KanbanColumnHeader } from "./kanban-column-header";
|
||||||
|
import { KanbanAddCardButton } from "./kanban-add-card-button";
|
||||||
import classes from "@/features/base/styles/kanban.module.css";
|
import classes from "@/features/base/styles/kanban.module.css";
|
||||||
|
|
||||||
type KanbanColumnProps = {
|
type KanbanColumnProps = {
|
||||||
column: KanbanColumnData;
|
column: KanbanColumnData;
|
||||||
primaryProperty: IBaseProperty | undefined;
|
primaryProperty: IBaseProperty | undefined;
|
||||||
onCardClick: (rowId: string) => void;
|
onCardClick: (rowId: string) => void;
|
||||||
|
onAddCard: (columnKey: string) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function KanbanColumn({
|
export function KanbanColumn({
|
||||||
column,
|
column,
|
||||||
primaryProperty,
|
primaryProperty,
|
||||||
onCardClick,
|
onCardClick,
|
||||||
|
onAddCard,
|
||||||
}: KanbanColumnProps) {
|
}: KanbanColumnProps) {
|
||||||
return (
|
return (
|
||||||
<div className={classes.column} data-column-key={column.key}>
|
<div className={classes.column} data-column-key={column.key}>
|
||||||
@@ -31,6 +34,7 @@ export function KanbanColumn({
|
|||||||
onClick={onCardClick}
|
onClick={onCardClick}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
|
<KanbanAddCardButton onClick={() => onAddCard(column.key)} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user