mirror of
https://github.com/rowyio/rowy.git
synced 2025-12-29 00:16:39 +01:00
remove contextMenuRef and replace with jotai
This commit is contained in:
18
src/atoms/ContextMenu.ts
Normal file
18
src/atoms/ContextMenu.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { atomWithReset } from "jotai/utils";
|
||||
|
||||
export type SelectedCell = {
|
||||
rowIndex: number;
|
||||
colIndex: number;
|
||||
};
|
||||
|
||||
export interface IContextMenuAtom {
|
||||
selectedCell: SelectedCell | null;
|
||||
anchorEl: HTMLElement | null;
|
||||
}
|
||||
|
||||
const INIT_VALUE = {
|
||||
selectedCell: null,
|
||||
anchorEl: null,
|
||||
};
|
||||
|
||||
export const contextMenuAtom = atomWithReset<IContextMenuAtom>(INIT_VALUE);
|
||||
@@ -1,55 +1,32 @@
|
||||
import React from "react";
|
||||
import _find from "lodash/find";
|
||||
import { PopoverProps } from "@mui/material";
|
||||
|
||||
import { getFieldProp } from "@src/components/fields";
|
||||
import { useProjectContext } from "@src/contexts/ProjectContext";
|
||||
|
||||
import useContextMenuAtom from "@src/hooks/useContextMenuAtom";
|
||||
import { MenuContents } from "./MenuContent";
|
||||
|
||||
export type SelectedCell = {
|
||||
rowIndex: number;
|
||||
colIndex: number;
|
||||
};
|
||||
|
||||
export type ContextMenuRef = {
|
||||
selectedCell: SelectedCell;
|
||||
setSelectedCell: React.Dispatch<React.SetStateAction<SelectedCell | null>>;
|
||||
anchorEl: HTMLElement | null;
|
||||
setAnchorEl: React.Dispatch<
|
||||
React.SetStateAction<PopoverProps["anchorEl"] | null>
|
||||
>;
|
||||
};
|
||||
|
||||
export default function ContextMenu() {
|
||||
const { contextMenuRef, tableState }: any = useProjectContext();
|
||||
const [anchorEl, setAnchorEl] = React.useState<any | null>(null);
|
||||
const [selectedCell, setSelectedCell] = React.useState<any | null>();
|
||||
const open = Boolean(anchorEl);
|
||||
const handleClose = () => setAnchorEl(null);
|
||||
|
||||
if (contextMenuRef)
|
||||
contextMenuRef.current = {
|
||||
anchorEl,
|
||||
setAnchorEl,
|
||||
selectedCell,
|
||||
setSelectedCell,
|
||||
} as {};
|
||||
|
||||
const { tableState }: any = useProjectContext();
|
||||
const { contextMenu, resetContextMenu } = useContextMenuAtom();
|
||||
const { anchorEl, selectedCell } = contextMenu;
|
||||
const selectedColIndex = selectedCell?.colIndex;
|
||||
const selectedCol = _find(tableState?.columns, { index: selectedColIndex });
|
||||
const getActions =
|
||||
const columns = tableState?.columns;
|
||||
|
||||
const selectedCol = _find(columns, { index: selectedColIndex });
|
||||
const configActions =
|
||||
getFieldProp("contextMenuActions", selectedCol?.type) ||
|
||||
function empty() {};
|
||||
const actions = getActions() || [];
|
||||
const hasNoActions = Boolean(actions.length === 0);
|
||||
const actions = configActions(selectedCell, resetContextMenu) || [];
|
||||
|
||||
if (!contextMenuRef.current || !open || hasNoActions) return <></>;
|
||||
const hasAnchorEle = Boolean(contextMenu.anchorEl);
|
||||
const hasNoActions = Boolean(actions.length === 0);
|
||||
const notOpen = Boolean(!anchorEl || !hasAnchorEle || hasNoActions);
|
||||
|
||||
if (notOpen) return <></>;
|
||||
return (
|
||||
<MenuContents
|
||||
anchorEl={anchorEl}
|
||||
open={open}
|
||||
handleClose={handleClose}
|
||||
anchorEl={anchorEl as HTMLElement}
|
||||
open={hasAnchorEle}
|
||||
handleClose={resetContextMenu}
|
||||
items={actions}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { useProjectContext } from "@src/contexts/ProjectContext";
|
||||
import useContextMenuAtom from "@src/hooks/useContextMenuAtom";
|
||||
import { Fragment } from "react";
|
||||
import { Row, RowRendererProps } from "react-data-grid";
|
||||
import { IContextMenuActions } from "../fields/_BasicCell/BasicCellContextMenuActions";
|
||||
|
||||
import OutOfOrderIndicator from "./OutOfOrderIndicator";
|
||||
|
||||
@@ -23,13 +25,14 @@ export default function TableRow(props: RowRendererProps<any>) {
|
||||
}
|
||||
|
||||
const ContextMenu = (props: any) => {
|
||||
const { contextMenuRef }: any = useProjectContext();
|
||||
const { setContextMenu } = useContextMenuAtom();
|
||||
function handleClick(e: any) {
|
||||
e.preventDefault();
|
||||
const input = e?.target as HTMLElement;
|
||||
if (contextMenuRef?.current) {
|
||||
contextMenuRef?.current?.setAnchorEl(input);
|
||||
}
|
||||
if (setContextMenu)
|
||||
setContextMenu((prev) => ({
|
||||
...prev,
|
||||
anchorEl: e?.target as HTMLElement,
|
||||
}));
|
||||
}
|
||||
return <span onContextMenu={(e) => handleClick(e)}>{props.children}</span>;
|
||||
};
|
||||
|
||||
@@ -32,6 +32,7 @@ import { formatSubTableName } from "@src/utils/fns";
|
||||
import { useAppContext } from "@src/contexts/AppContext";
|
||||
import { useProjectContext } from "@src/contexts/ProjectContext";
|
||||
import useWindowSize from "@src/hooks/useWindowSize";
|
||||
import useContextMenuAtom from "@src/hooks/useContextMenuAtom";
|
||||
|
||||
export type TableColumn = Column<any> & {
|
||||
isNew?: boolean;
|
||||
@@ -49,11 +50,11 @@ export default function Table() {
|
||||
tableState,
|
||||
tableActions,
|
||||
dataGridRef,
|
||||
contextMenuRef,
|
||||
sideDrawerRef,
|
||||
updateCell,
|
||||
} = useProjectContext();
|
||||
const { userDoc, userClaims } = useAppContext();
|
||||
const { setContextMenu } = useContextMenuAtom();
|
||||
|
||||
const userDocHiddenFields =
|
||||
userDoc.state.doc?.tables?.[formatSubTableName(tableState?.config.id)]
|
||||
@@ -265,10 +266,13 @@ export default function Table() {
|
||||
}
|
||||
}}
|
||||
onSelectedCellChange={({ rowIdx, idx }) => {
|
||||
contextMenuRef?.current?.setSelectedCell({
|
||||
rowIndex: rowIdx,
|
||||
colIndex: idx,
|
||||
});
|
||||
setContextMenu((prev) => ({
|
||||
...prev,
|
||||
selectedCell: {
|
||||
rowIndex: rowIdx,
|
||||
colIndex: idx,
|
||||
},
|
||||
}));
|
||||
}}
|
||||
/>
|
||||
</DndProvider>
|
||||
|
||||
@@ -4,6 +4,7 @@ import Cut from "@src/assets/icons/Cut";
|
||||
import Paste from "@src/assets/icons/Paste";
|
||||
import { useProjectContext } from "@src/contexts/ProjectContext";
|
||||
import { useSnackbar } from "notistack";
|
||||
import { SelectedCell } from "@src/atoms/ContextMenu";
|
||||
|
||||
export interface IContextMenuActions {
|
||||
label: string;
|
||||
@@ -11,22 +12,20 @@ export interface IContextMenuActions {
|
||||
onClick: () => void;
|
||||
}
|
||||
|
||||
export default function BasicContextMenuActions(): IContextMenuActions[] {
|
||||
const { contextMenuRef, tableState, deleteCell, updateCell } =
|
||||
useProjectContext();
|
||||
export default function BasicContextMenuActions(
|
||||
selectedCell: SelectedCell,
|
||||
reset: () => void | Promise<void>
|
||||
): IContextMenuActions[] {
|
||||
const { tableState, deleteCell, updateCell } = useProjectContext();
|
||||
const { enqueueSnackbar } = useSnackbar();
|
||||
const columns = tableState?.columns;
|
||||
const rows = tableState?.rows;
|
||||
const selectedRowIndex = contextMenuRef?.current?.selectedCell
|
||||
.rowIndex as number;
|
||||
const selectedColIndex = contextMenuRef?.current?.selectedCell?.colIndex;
|
||||
const selectedRowIndex = selectedCell.rowIndex as number;
|
||||
const selectedColIndex = selectedCell?.colIndex;
|
||||
const selectedCol = _find(columns, { index: selectedColIndex });
|
||||
const selectedRow = rows?.[selectedRowIndex];
|
||||
|
||||
const handleClose = () => {
|
||||
contextMenuRef?.current?.setSelectedCell(null);
|
||||
contextMenuRef?.current?.setAnchorEl(null);
|
||||
};
|
||||
const handleClose = () => reset?.();
|
||||
|
||||
const handleCopy = () => {
|
||||
const cell = selectedRow?.[selectedCol.key];
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { FieldType } from "@src/constants/fields";
|
||||
|
||||
import { FormatterProps, EditorProps } from "react-data-grid";
|
||||
import { Control, UseFormReturn } from "react-hook-form";
|
||||
import { PopoverProps } from "@mui/material";
|
||||
import { SelectedCell } from "@src/atoms/ContextMenu";
|
||||
import { IContextMenuActions } from "./_BasicCell/BasicCellContextMenuActions";
|
||||
|
||||
export { FieldType };
|
||||
@@ -18,7 +18,10 @@ export interface IFieldConfig {
|
||||
icon?: React.ReactNode;
|
||||
description?: string;
|
||||
setupGuideLink?: string;
|
||||
contextMenuActions?: () => IContextMenuActions[];
|
||||
contextMenuActions?: (
|
||||
selectedCell: SelectedCell,
|
||||
reset: () => void | Promise<void>
|
||||
) => IContextMenuActions[];
|
||||
TableCell: React.ComponentType<FormatterProps<any>>;
|
||||
TableEditor: React.ComponentType<EditorProps<any, any>>;
|
||||
SideDrawerField: React.ComponentType<ISideDrawerFieldProps>;
|
||||
|
||||
@@ -14,7 +14,6 @@ import useSettings from "@src/hooks/useSettings";
|
||||
import { useAppContext } from "./AppContext";
|
||||
import { SideDrawerRef } from "@src/components/SideDrawer";
|
||||
import { ColumnMenuRef } from "@src/components/Table/ColumnMenu";
|
||||
import { ContextMenuRef } from "@src/components/Table/ContextMenu";
|
||||
import { ImportWizardRef } from "@src/components/Wizards/ImportWizard";
|
||||
|
||||
import { rowyRun, IRowyRunRequestProps } from "@src/utils/rowyRun";
|
||||
@@ -105,8 +104,6 @@ export interface IProjectContext {
|
||||
dataGridRef: React.RefObject<DataGridHandle>;
|
||||
// A ref to the side drawer state. Prevents unnecessary re-renders
|
||||
sideDrawerRef: React.MutableRefObject<SideDrawerRef | undefined>;
|
||||
//A ref to the cell menu. Prevents unnecessary re-render
|
||||
contextMenuRef: React.MutableRefObject<ContextMenuRef | undefined>;
|
||||
// A ref to the column menu. Prevents unnecessary re-renders
|
||||
columnMenuRef: React.MutableRefObject<ColumnMenuRef | undefined>;
|
||||
// A ref ot the import wizard. Prevents unnecessary re-renders
|
||||
@@ -401,7 +398,6 @@ export const ProjectContextProvider: React.FC = ({ children }) => {
|
||||
// A ref to the data grid. Contains data grid functions
|
||||
const dataGridRef = useRef<DataGridHandle>(null);
|
||||
const sideDrawerRef = useRef<SideDrawerRef>();
|
||||
const contextMenuRef = useRef<ContextMenuRef>();
|
||||
const columnMenuRef = useRef<ColumnMenuRef>();
|
||||
const importWizardRef = useRef<ImportWizardRef>();
|
||||
|
||||
@@ -422,7 +418,6 @@ export const ProjectContextProvider: React.FC = ({ children }) => {
|
||||
table,
|
||||
dataGridRef,
|
||||
sideDrawerRef,
|
||||
contextMenuRef,
|
||||
columnMenuRef,
|
||||
importWizardRef,
|
||||
rowyRun: _rowyRun,
|
||||
|
||||
14
src/hooks/useContextMenuAtom.ts
Normal file
14
src/hooks/useContextMenuAtom.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { useAtom } from "jotai";
|
||||
import { useResetAtom } from "jotai/utils";
|
||||
import { contextMenuAtom } from "@src/atoms/ContextMenu";
|
||||
|
||||
export default function useContextMenuAtom() {
|
||||
const [contextMenu, setContextMenu] = useAtom(contextMenuAtom);
|
||||
const resetContextMenu = useResetAtom(contextMenuAtom);
|
||||
|
||||
return {
|
||||
contextMenu,
|
||||
setContextMenu,
|
||||
resetContextMenu,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user