mirror of
https://github.com/docmost/docmost.git
synced 2026-08-29 10:05:03 +08:00
feat(base): insert row below via Shift+Enter on the primary cell
This commit is contained in:
@@ -18,7 +18,7 @@ type BaseTableProps = {
|
|||||||
isFetchingNextPage: boolean;
|
isFetchingNextPage: boolean;
|
||||||
onFetchNextPage: () => void;
|
onFetchNextPage: () => void;
|
||||||
onCellUpdate: (rowId: string, propertyId: string, value: unknown) => void;
|
onCellUpdate: (rowId: string, propertyId: string, value: unknown) => void;
|
||||||
onAddRow: () => void;
|
onAddRow: (afterRowId?: string, focusPropertyId?: string) => void;
|
||||||
onColumnReorder: (columnId: string, finishIndex: number) => void;
|
onColumnReorder: (columnId: string, finishIndex: number) => void;
|
||||||
onResizeEnd: () => void;
|
onResizeEnd: () => void;
|
||||||
onRowReorder: (
|
onRowReorder: (
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import {
|
|||||||
FilterGroup,
|
FilterGroup,
|
||||||
ViewSortConfig,
|
ViewSortConfig,
|
||||||
EditingCell,
|
EditingCell,
|
||||||
|
FocusedCell,
|
||||||
IBaseProperty,
|
IBaseProperty,
|
||||||
} from "@/ee/base/types/base.types";
|
} from "@/ee/base/types/base.types";
|
||||||
import {
|
import {
|
||||||
@@ -25,6 +26,7 @@ import { useUpdateViewMutation } from "@/ee/base/queries/base-view-query";
|
|||||||
import {
|
import {
|
||||||
activeViewIdAtomFamily,
|
activeViewIdAtomFamily,
|
||||||
editingCellAtomFamily,
|
editingCellAtomFamily,
|
||||||
|
focusedCellAtomFamily,
|
||||||
} from "@/ee/base/atoms/base-atoms";
|
} from "@/ee/base/atoms/base-atoms";
|
||||||
import { useBaseTable } from "@/ee/base/hooks/use-base-table";
|
import { useBaseTable } from "@/ee/base/hooks/use-base-table";
|
||||||
import { isSystemPropertyType } from "@/ee/base/property-types/property-type.registry";
|
import { isSystemPropertyType } from "@/ee/base/property-types/property-type.registry";
|
||||||
@@ -89,6 +91,10 @@ export function BaseView({ pageId, embedded, editable = true, titleSlot }: BaseV
|
|||||||
editingCellAtomFamily(pageId),
|
editingCellAtomFamily(pageId),
|
||||||
) as unknown as [EditingCell, (val: EditingCell) => void];
|
) as unknown as [EditingCell, (val: EditingCell) => void];
|
||||||
|
|
||||||
|
const [, setFocusedCell] = useAtom(
|
||||||
|
focusedCellAtomFamily(pageId),
|
||||||
|
) as unknown as [FocusedCell, (val: FocusedCell) => void];
|
||||||
|
|
||||||
const views = useMemo(
|
const views = useMemo(
|
||||||
() =>
|
() =>
|
||||||
[...(base?.views ?? [])].sort((a, b) =>
|
[...(base?.views ?? [])].sort((a, b) =>
|
||||||
@@ -221,33 +227,42 @@ export function BaseView({ pageId, embedded, editable = true, titleSlot }: BaseV
|
|||||||
[editable, pageId, updateRow],
|
[editable, pageId, updateRow],
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleAddRow = useCallback(() => {
|
const handleAddRow = useCallback(
|
||||||
if (!editable) return;
|
(afterRowId?: string, focusPropertyId?: string) => {
|
||||||
createRowMutation.mutate(
|
if (!editable) return;
|
||||||
{ pageId },
|
createRowMutation.mutate(
|
||||||
{
|
{ pageId, ...(afterRowId ? { afterRowId } : {}) },
|
||||||
onSuccess: (newRow) => {
|
{
|
||||||
const firstEditable = table.getVisibleLeafColumns().find((col) => {
|
onSuccess: (newRow) => {
|
||||||
if (col.id === "__row_number") return false;
|
let propertyId = focusPropertyId;
|
||||||
const prop = col.columnDef.meta?.property as
|
if (!propertyId) {
|
||||||
| IBaseProperty
|
const firstEditable = table.getVisibleLeafColumns().find((col) => {
|
||||||
| undefined;
|
if (col.id === "__row_number") return false;
|
||||||
return (
|
const prop = col.columnDef.meta?.property as
|
||||||
!!prop &&
|
| IBaseProperty
|
||||||
prop.type !== "checkbox" &&
|
| undefined;
|
||||||
!isSystemPropertyType(prop.type)
|
return (
|
||||||
);
|
!!prop &&
|
||||||
});
|
prop.type !== "checkbox" &&
|
||||||
const propertyId = (
|
!isSystemPropertyType(prop.type)
|
||||||
firstEditable?.columnDef.meta?.property as IBaseProperty | undefined
|
);
|
||||||
)?.id;
|
});
|
||||||
if (propertyId) {
|
propertyId = (
|
||||||
setEditingCell({ rowId: newRow.id, propertyId });
|
firstEditable?.columnDef.meta?.property as
|
||||||
}
|
| IBaseProperty
|
||||||
|
| undefined
|
||||||
|
)?.id;
|
||||||
|
}
|
||||||
|
if (propertyId) {
|
||||||
|
setEditingCell({ rowId: newRow.id, propertyId });
|
||||||
|
setFocusedCell({ rowId: newRow.id, propertyId });
|
||||||
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
);
|
||||||
);
|
},
|
||||||
}, [editable, pageId, createRowMutation, table, setEditingCell]);
|
[editable, pageId, createRowMutation, table, setEditingCell, setFocusedCell],
|
||||||
|
);
|
||||||
|
|
||||||
const handleViewChange = useCallback(
|
const handleViewChange = useCallback(
|
||||||
(viewId: string) => {
|
(viewId: string) => {
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ type GridContainerProps = {
|
|||||||
table: Table<IBaseRow>;
|
table: Table<IBaseRow>;
|
||||||
properties: IBaseProperty[];
|
properties: IBaseProperty[];
|
||||||
onCellUpdate: (rowId: string, propertyId: string, value: unknown) => void;
|
onCellUpdate: (rowId: string, propertyId: string, value: unknown) => void;
|
||||||
onAddRow?: () => void;
|
onAddRow?: (afterRowId?: string, focusPropertyId?: string) => void;
|
||||||
pageId: string;
|
pageId: string;
|
||||||
onColumnReorder?: (columnId: string, finishIndex: number) => void;
|
onColumnReorder?: (columnId: string, finishIndex: number) => void;
|
||||||
onResizeEnd?: () => void;
|
onResizeEnd?: () => void;
|
||||||
@@ -378,6 +378,13 @@ export function GridContainer({
|
|||||||
[table, setFocusedCell],
|
[table, setFocusedCell],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const handleAddRowBelow = useCallback(
|
||||||
|
(afterRowId: string, focusPropertyId: string) => {
|
||||||
|
onAddRow?.(afterRowId, focusPropertyId);
|
||||||
|
},
|
||||||
|
[onAddRow],
|
||||||
|
);
|
||||||
|
|
||||||
useGridKeyboardNav({
|
useGridKeyboardNav({
|
||||||
table,
|
table,
|
||||||
properties,
|
properties,
|
||||||
@@ -395,6 +402,7 @@ export function GridContainer({
|
|||||||
deleteSelected,
|
deleteSelected,
|
||||||
toggleRowSelection,
|
toggleRowSelection,
|
||||||
expandRow,
|
expandRow,
|
||||||
|
addRow: handleAddRowBelow,
|
||||||
});
|
});
|
||||||
|
|
||||||
const activeCell = editingCell ?? focusedCell;
|
const activeCell = editingCell ?? focusedCell;
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ type ViewRendererProps = {
|
|||||||
isFetchingNextPage: boolean;
|
isFetchingNextPage: boolean;
|
||||||
onFetchNextPage: () => void;
|
onFetchNextPage: () => void;
|
||||||
onCellUpdate: (rowId: string, propertyId: string, value: unknown) => void;
|
onCellUpdate: (rowId: string, propertyId: string, value: unknown) => void;
|
||||||
onAddRow: () => void;
|
onAddRow: (afterRowId?: string, focusPropertyId?: string) => void;
|
||||||
onColumnReorder: (columnId: string, finishIndex: number) => void;
|
onColumnReorder: (columnId: string, finishIndex: number) => void;
|
||||||
onResizeEnd: () => void;
|
onResizeEnd: () => void;
|
||||||
onRowReorder: (
|
onRowReorder: (
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useCallback, useEffect } from "react";
|
import { useCallback, useEffect, useMemo } from "react";
|
||||||
import { Table } from "@tanstack/react-table";
|
import { Table } from "@tanstack/react-table";
|
||||||
import {
|
import {
|
||||||
IBaseRow,
|
IBaseRow,
|
||||||
@@ -26,6 +26,7 @@ type UseGridKeyboardNavOptions = {
|
|||||||
deleteSelected: () => void | Promise<void>;
|
deleteSelected: () => void | Promise<void>;
|
||||||
toggleRowSelection: (rowId: string) => void;
|
toggleRowSelection: (rowId: string) => void;
|
||||||
expandRow: (rowId: string) => void;
|
expandRow: (rowId: string) => void;
|
||||||
|
addRow: (afterRowId: string, focusPropertyId: string) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const isPrintableKey = (e: KeyboardEvent) =>
|
const isPrintableKey = (e: KeyboardEvent) =>
|
||||||
@@ -54,6 +55,7 @@ export function useGridKeyboardNav({
|
|||||||
deleteSelected,
|
deleteSelected,
|
||||||
toggleRowSelection,
|
toggleRowSelection,
|
||||||
expandRow,
|
expandRow,
|
||||||
|
addRow,
|
||||||
}: UseGridKeyboardNavOptions) {
|
}: UseGridKeyboardNavOptions) {
|
||||||
const getColIds = useCallback(
|
const getColIds = useCallback(
|
||||||
() =>
|
() =>
|
||||||
@@ -79,6 +81,11 @@ export function useGridKeyboardNav({
|
|||||||
[properties],
|
[properties],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const primaryPropertyId = useMemo(
|
||||||
|
() => properties.find((p) => p.isPrimary)?.id,
|
||||||
|
[properties],
|
||||||
|
);
|
||||||
|
|
||||||
const goEditing = useCallback(
|
const goEditing = useCallback(
|
||||||
(next: CellCoord) => {
|
(next: CellCoord) => {
|
||||||
(document.activeElement as HTMLElement | null)?.blur();
|
(document.activeElement as HTMLElement | null)?.blur();
|
||||||
@@ -142,6 +149,12 @@ export function useGridKeyboardNav({
|
|||||||
}
|
}
|
||||||
case "Enter": {
|
case "Enter": {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
if (e.shiftKey && editingCell.propertyId === primaryPropertyId) {
|
||||||
|
(document.activeElement as HTMLElement | null)?.blur();
|
||||||
|
setEditingCell(null);
|
||||||
|
addRow(editingCell.rowId, editingCell.propertyId);
|
||||||
|
break;
|
||||||
|
}
|
||||||
const next = computeNextCell(
|
const next = computeNextCell(
|
||||||
getRowIds(),
|
getRowIds(),
|
||||||
getColIds(),
|
getColIds(),
|
||||||
@@ -241,7 +254,13 @@ export function useGridKeyboardNav({
|
|||||||
case "Enter":
|
case "Enter":
|
||||||
case "F2":
|
case "F2":
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
if (focusedCell.propertyId === "__row_number") {
|
if (
|
||||||
|
e.key === "Enter" &&
|
||||||
|
e.shiftKey &&
|
||||||
|
focusedCell.propertyId === primaryPropertyId
|
||||||
|
) {
|
||||||
|
addRow(focusedCell.rowId, focusedCell.propertyId);
|
||||||
|
} else if (focusedCell.propertyId === "__row_number") {
|
||||||
toggleRowSelection(focusedCell.rowId);
|
toggleRowSelection(focusedCell.rowId);
|
||||||
} else {
|
} else {
|
||||||
openEditor(focusedCell);
|
openEditor(focusedCell);
|
||||||
@@ -284,6 +303,8 @@ export function useGridKeyboardNav({
|
|||||||
deleteSelected,
|
deleteSelected,
|
||||||
toggleRowSelection,
|
toggleRowSelection,
|
||||||
expandRow,
|
expandRow,
|
||||||
|
primaryPropertyId,
|
||||||
|
addRow,
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user