mirror of
https://github.com/docmost/docmost.git
synced 2026-08-28 17:27:06 +08:00
refactor(bases): guard kanban column drag from menu clicks; polish hidden chips strip
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
import { useCallback, useMemo } from "react";
|
import { useCallback, useMemo } from "react";
|
||||||
import { Badge } from "@mantine/core";
|
import { Badge } from "@mantine/core";
|
||||||
import { IconPlus } from "@tabler/icons-react";
|
import { IconPlus } from "@tabler/icons-react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
import {
|
import {
|
||||||
IBase,
|
IBase,
|
||||||
IBaseRow,
|
IBaseRow,
|
||||||
@@ -36,6 +37,7 @@ export function BaseKanban({
|
|||||||
effectiveView,
|
effectiveView,
|
||||||
onCardClick,
|
onCardClick,
|
||||||
}: BaseKanbanProps) {
|
}: BaseKanbanProps) {
|
||||||
|
const { t } = useTranslation();
|
||||||
const groupByPropertyId = effectiveView?.config?.groupByPropertyId;
|
const groupByPropertyId = effectiveView?.config?.groupByPropertyId;
|
||||||
const property = useMemo(
|
const property = useMemo(
|
||||||
() =>
|
() =>
|
||||||
@@ -211,13 +213,13 @@ export function BaseKanban({
|
|||||||
return hiddenIds
|
return hiddenIds
|
||||||
.map((id) =>
|
.map((id) =>
|
||||||
id === NO_VALUE_CHOICE_ID
|
id === NO_VALUE_CHOICE_ID
|
||||||
? { id, name: "No value", color: null as string | null }
|
? { id, name: t("No value"), color: null as string | null }
|
||||||
: byId.get(id)
|
: byId.get(id)
|
||||||
? { id, name: byId.get(id)!.name, color: byId.get(id)!.color as string | null }
|
? { id, name: byId.get(id)!.name, color: byId.get(id)!.color as string | null }
|
||||||
: null,
|
: null,
|
||||||
)
|
)
|
||||||
.filter((c): c is { id: string; name: string; color: string | null } => c !== null);
|
.filter((c): c is { id: string; name: string; color: string | null } => c !== null);
|
||||||
}, [hiddenIds, isGroupable, property]);
|
}, [hiddenIds, isGroupable, property, t]);
|
||||||
|
|
||||||
if (!isGroupable) {
|
if (!isGroupable) {
|
||||||
return <KanbanEmptyState base={base} onPick={handlePickProperty} />;
|
return <KanbanEmptyState base={base} onPick={handlePickProperty} />;
|
||||||
@@ -226,13 +228,13 @@ export function BaseKanban({
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{hiddenChoices.length > 0 && (
|
{hiddenChoices.length > 0 && (
|
||||||
<div style={{ padding: "6px 12px", display: "flex", gap: 6, flexWrap: "wrap" }}>
|
<div className={classes.hiddenStrip}>
|
||||||
{hiddenChoices.map((c) => (
|
{hiddenChoices.map((c) => (
|
||||||
<Badge
|
<Badge
|
||||||
key={c.id}
|
key={c.id}
|
||||||
color={c.color ?? "gray"}
|
color={c.color ?? "gray"}
|
||||||
variant="outline"
|
variant="outline"
|
||||||
style={{ cursor: "pointer" }}
|
className={classes.hiddenChip}
|
||||||
onClick={() => handleShowColumn(c.id)}
|
onClick={() => handleShowColumn(c.id)}
|
||||||
rightSection={<IconPlus size={12} />}
|
rightSection={<IconPlus size={12} />}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ export function KanbanColumnHeader({
|
|||||||
</div>
|
</div>
|
||||||
<Menu shadow="md" width={160} position="bottom-end">
|
<Menu shadow="md" width={160} position="bottom-end">
|
||||||
<Menu.Target>
|
<Menu.Target>
|
||||||
<ActionIcon variant="subtle" size="sm" color="gray">
|
<ActionIcon variant="subtle" size="sm" color="gray" data-no-drag>
|
||||||
<IconDots size={14} />
|
<IconDots size={14} />
|
||||||
</ActionIcon>
|
</ActionIcon>
|
||||||
</Menu.Target>
|
</Menu.Target>
|
||||||
|
|||||||
@@ -36,6 +36,16 @@ export function useKanbanColumnReorder({
|
|||||||
return combine(
|
return combine(
|
||||||
draggable({
|
draggable({
|
||||||
element: el,
|
element: el,
|
||||||
|
canDrag: ({ input }) => {
|
||||||
|
// Don't start a drag when the user is interacting with a marked
|
||||||
|
// "no-drag" subtree (e.g. the column header's menu trigger).
|
||||||
|
const target = document.elementFromPoint(
|
||||||
|
input.clientX,
|
||||||
|
input.clientY,
|
||||||
|
) as HTMLElement | null;
|
||||||
|
if (target?.closest("[data-no-drag]")) return false;
|
||||||
|
return true;
|
||||||
|
},
|
||||||
getInitialData: () => ({ type: "base-kanban-column", columnKey }),
|
getInitialData: () => ({ type: "base-kanban-column", columnKey }),
|
||||||
onDragStart: () => setIsDragging(true),
|
onDragStart: () => setIsDragging(true),
|
||||||
onDrop: () => setIsDragging(false),
|
onDrop: () => setIsDragging(false),
|
||||||
|
|||||||
@@ -91,3 +91,14 @@
|
|||||||
font-size: var(--mantine-font-size-xs);
|
font-size: var(--mantine-font-size-xs);
|
||||||
color: var(--mantine-color-dimmed);
|
color: var(--mantine-color-dimmed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.hiddenStrip {
|
||||||
|
padding: 6px 12px;
|
||||||
|
display: flex;
|
||||||
|
gap: 6px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hiddenChip {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user