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