mirror of
https://github.com/docmost/docmost.git
synced 2026-08-29 18:14:58 +08:00
feat(base): route toolbar sort/filter changes through local draft
This commit is contained in:
@@ -7,6 +7,10 @@ import { arrayMove } from "@dnd-kit/sortable";
|
|||||||
import { generateJitteredKeyBetween } from "fractional-indexing-jittered";
|
import { generateJitteredKeyBetween } from "fractional-indexing-jittered";
|
||||||
import { useBaseQuery } from "@/features/base/queries/base-query";
|
import { useBaseQuery } from "@/features/base/queries/base-query";
|
||||||
import { useBaseSocket } from "@/features/base/hooks/use-base-socket";
|
import { useBaseSocket } from "@/features/base/hooks/use-base-socket";
|
||||||
|
import {
|
||||||
|
FilterGroup,
|
||||||
|
ViewSortConfig,
|
||||||
|
} from "@/features/base/types/base.types";
|
||||||
import {
|
import {
|
||||||
useBaseRowsQuery,
|
useBaseRowsQuery,
|
||||||
flattenRows,
|
flattenRows,
|
||||||
@@ -179,6 +183,20 @@ export function BaseTable({ baseId }: BaseTableProps) {
|
|||||||
persistViewConfig();
|
persistViewConfig();
|
||||||
}, [persistViewConfig]);
|
}, [persistViewConfig]);
|
||||||
|
|
||||||
|
const handleDraftSortsChange = useCallback(
|
||||||
|
(sorts: ViewSortConfig[] | undefined) => {
|
||||||
|
setDraftSorts(sorts && sorts.length > 0 ? sorts : undefined);
|
||||||
|
},
|
||||||
|
[setDraftSorts],
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleDraftFiltersChange = useCallback(
|
||||||
|
(filter: FilterGroup | undefined) => {
|
||||||
|
setDraftFilter(filter);
|
||||||
|
},
|
||||||
|
[setDraftFilter],
|
||||||
|
);
|
||||||
|
|
||||||
const handleRowReorder = useCallback(
|
const handleRowReorder = useCallback(
|
||||||
(rowId: string, targetRowId: string, dropPosition: "above" | "below") => {
|
(rowId: string, targetRowId: string, dropPosition: "above" | "below") => {
|
||||||
const remainingRows = rows.filter((r) => r.id !== rowId);
|
const remainingRows = rows.filter((r) => r.id !== rowId);
|
||||||
@@ -235,12 +253,14 @@ export function BaseTable({ baseId }: BaseTableProps) {
|
|||||||
<div style={{ display: "flex", flexDirection: "column", height: "100%" }}>
|
<div style={{ display: "flex", flexDirection: "column", height: "100%" }}>
|
||||||
<BaseToolbar
|
<BaseToolbar
|
||||||
base={base}
|
base={base}
|
||||||
activeView={activeView}
|
activeView={effectiveView}
|
||||||
views={views}
|
views={views}
|
||||||
table={table}
|
table={table}
|
||||||
onViewChange={handleViewChange}
|
onViewChange={handleViewChange}
|
||||||
onAddView={handleAddView}
|
onAddView={handleAddView}
|
||||||
onPersistViewConfig={persistViewConfig}
|
onPersistViewConfig={persistViewConfig}
|
||||||
|
onDraftSortsChange={handleDraftSortsChange}
|
||||||
|
onDraftFiltersChange={handleDraftFiltersChange}
|
||||||
/>
|
/>
|
||||||
<GridContainer
|
<GridContainer
|
||||||
table={table}
|
table={table}
|
||||||
|
|||||||
@@ -16,8 +16,6 @@ import {
|
|||||||
FilterCondition,
|
FilterCondition,
|
||||||
FilterGroup,
|
FilterGroup,
|
||||||
} from "@/features/base/types/base.types";
|
} from "@/features/base/types/base.types";
|
||||||
import { useUpdateViewMutation } from "@/features/base/queries/base-view-query";
|
|
||||||
import { buildViewConfigFromTable } from "@/features/base/hooks/use-base-table";
|
|
||||||
import { exportBaseToCsv } from "@/features/base/services/base-service";
|
import { exportBaseToCsv } from "@/features/base/services/base-service";
|
||||||
import { ViewTabs } from "@/features/base/components/views/view-tabs";
|
import { ViewTabs } from "@/features/base/components/views/view-tabs";
|
||||||
import { ViewSortConfigPopover } from "@/features/base/components/views/view-sort-config";
|
import { ViewSortConfigPopover } from "@/features/base/components/views/view-sort-config";
|
||||||
@@ -28,12 +26,18 @@ import classes from "@/features/base/styles/grid.module.css";
|
|||||||
|
|
||||||
type BaseToolbarProps = {
|
type BaseToolbarProps = {
|
||||||
base: IBase;
|
base: IBase;
|
||||||
|
// Effective view — baseline merged with any local draft. Badge counts
|
||||||
|
// and sort/filter popover seed data read from this. The real baseline
|
||||||
|
// only enters via `onDraftSortsChange` / `onDraftFiltersChange`
|
||||||
|
// callbacks defined by the parent.
|
||||||
activeView: IBaseView | undefined;
|
activeView: IBaseView | undefined;
|
||||||
views: IBaseView[];
|
views: IBaseView[];
|
||||||
table: Table<IBaseRow>;
|
table: Table<IBaseRow>;
|
||||||
onViewChange: (viewId: string) => void;
|
onViewChange: (viewId: string) => void;
|
||||||
onAddView?: () => void;
|
onAddView?: () => void;
|
||||||
onPersistViewConfig: () => void;
|
onPersistViewConfig: () => void;
|
||||||
|
onDraftSortsChange: (sorts: ViewSortConfig[] | undefined) => void;
|
||||||
|
onDraftFiltersChange: (filter: FilterGroup | undefined) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function BaseToolbar({
|
export function BaseToolbar({
|
||||||
@@ -44,6 +48,8 @@ export function BaseToolbar({
|
|||||||
onViewChange,
|
onViewChange,
|
||||||
onAddView,
|
onAddView,
|
||||||
onPersistViewConfig,
|
onPersistViewConfig,
|
||||||
|
onDraftSortsChange,
|
||||||
|
onDraftFiltersChange,
|
||||||
}: BaseToolbarProps) {
|
}: BaseToolbarProps) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [sortOpened, setSortOpened] = useState(false);
|
const [sortOpened, setSortOpened] = useState(false);
|
||||||
@@ -113,8 +119,6 @@ export function BaseToolbar({
|
|||||||
setFieldsOpened(panel === "fields" ? (v) => !v : false);
|
setFieldsOpened(panel === "fields" ? (v) => !v : false);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const updateViewMutation = useUpdateViewMutation();
|
|
||||||
|
|
||||||
const sorts = activeView?.config?.sorts ?? [];
|
const sorts = activeView?.config?.sorts ?? [];
|
||||||
// Stored view config uses the engine's filter tree. The popover edits
|
// Stored view config uses the engine's filter tree. The popover edits
|
||||||
// an AND-only flat list; we unwrap the top-level group's children when
|
// an AND-only flat list; we unwrap the top-level group's children when
|
||||||
@@ -134,38 +138,24 @@ export function BaseToolbar({
|
|||||||
|
|
||||||
const handleSortsChange = useCallback(
|
const handleSortsChange = useCallback(
|
||||||
(newSorts: ViewSortConfig[]) => {
|
(newSorts: ViewSortConfig[]) => {
|
||||||
if (!activeView) return;
|
// Normalize empty to undefined so the draft hook can drop the `sorts`
|
||||||
const config = buildViewConfigFromTable(table, activeView.config, {
|
// axis (and remove its localStorage entry when both axes go clean).
|
||||||
sorts: newSorts,
|
onDraftSortsChange(newSorts.length > 0 ? newSorts : undefined);
|
||||||
});
|
|
||||||
updateViewMutation.mutate({
|
|
||||||
viewId: activeView.id,
|
|
||||||
baseId: base.id,
|
|
||||||
config,
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
[activeView, base.id, table, updateViewMutation],
|
[onDraftSortsChange],
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleFiltersChange = useCallback(
|
const handleFiltersChange = useCallback(
|
||||||
(newConditions: FilterCondition[]) => {
|
(newConditions: FilterCondition[]) => {
|
||||||
if (!activeView) return;
|
// Wrap the AND-flat popover output into the engine's FilterGroup shape.
|
||||||
|
// Pass `undefined` to drop the filter axis from the draft entirely.
|
||||||
const filter: FilterGroup | undefined =
|
const filter: FilterGroup | undefined =
|
||||||
newConditions.length > 0
|
newConditions.length > 0
|
||||||
? { op: "and", children: newConditions }
|
? { op: "and", children: newConditions }
|
||||||
: undefined;
|
: undefined;
|
||||||
// `filter: undefined` in overrides removes the filter key; the helper's
|
onDraftFiltersChange(filter);
|
||||||
// spread-then-overrides order means `undefined` wins over any base filter.
|
|
||||||
const config = buildViewConfigFromTable(table, activeView.config, {
|
|
||||||
filter,
|
|
||||||
});
|
|
||||||
updateViewMutation.mutate({
|
|
||||||
viewId: activeView.id,
|
|
||||||
baseId: base.id,
|
|
||||||
config,
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
[activeView, base.id, table, updateViewMutation],
|
[onDraftFiltersChange],
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
Reference in New Issue
Block a user