mirror of
https://github.com/rowyio/rowy.git
synced 2025-12-29 00:16:39 +01:00
Merge branch 'data-layer-rewrite' of https://github.com/rowyio/rowy into data-layer-rewrite
This commit is contained in:
9
src/assets/icons/Clear.tsx
Normal file
9
src/assets/icons/Clear.tsx
Normal file
@@ -0,0 +1,9 @@
|
||||
import SvgIcon, { SvgIconProps } from "@mui/material/SvgIcon";
|
||||
|
||||
export function Clear(props: SvgIconProps) {
|
||||
return (
|
||||
<SvgIcon {...props}>
|
||||
<path d="M20 6v12a2 2 0 0 1-2 2H7l-6-8 6-8h11a2 2 0 0 1 2 2Zm-2.001-.001h-10l-4.5 6 4.5 6h10v-12ZM9.12 7.71 7.71 9.12 10.59 12l-2.88 2.88 1.41 1.41L12 13.41l2.88 2.88 1.41-1.41L13.41 12l2.88-2.88-1.41-1.41L12 10.59" />
|
||||
</SvgIcon>
|
||||
);
|
||||
}
|
||||
@@ -83,6 +83,7 @@ import { CarBrakeAlert } from "mdi-material-ui";
|
||||
export { CarBrakeAlert as Critical };
|
||||
|
||||
export * from "./AddRow";
|
||||
export * from "./Clear";
|
||||
export * from "./ConnectTable";
|
||||
export * from "./Copy";
|
||||
export * from "./CopyCells";
|
||||
|
||||
@@ -100,11 +100,12 @@ export const tableModalAtom = atomWithHash<
|
||||
/** Store side drawer open state */
|
||||
export const sideDrawerOpenAtom = atom(false);
|
||||
|
||||
/** Store selected cell in table */
|
||||
export const selectedCellAtom = atom<{
|
||||
path: string;
|
||||
columnKey: string;
|
||||
} | null>(null);
|
||||
export type SelectedCell = { path: string; columnKey: string };
|
||||
/** Store selected cell in table. Used in side drawer and context menu */
|
||||
export const selectedCellAtom = atom<SelectedCell | null>(null);
|
||||
|
||||
/** Store context menu target atom for positioning. If not null, menu open. */
|
||||
export const contextMenuTargetAtom = atom<HTMLElement | null>(null);
|
||||
|
||||
export type CloudLogFilters = {
|
||||
type: "webhook" | "functions" | "audit" | "build";
|
||||
|
||||
34
src/components/Table/ContextMenu/ContextMenu.tsx
Normal file
34
src/components/Table/ContextMenu/ContextMenu.tsx
Normal file
@@ -0,0 +1,34 @@
|
||||
import { useAtom } from "jotai";
|
||||
|
||||
import { Menu } from "@mui/material";
|
||||
import MenuContents from "./MenuContents";
|
||||
|
||||
import { tableScope, contextMenuTargetAtom } from "@src/atoms/tableScope";
|
||||
|
||||
export default function ContextMenu() {
|
||||
const [contextMenuTarget, setContextMenuTarget] = useAtom(
|
||||
contextMenuTargetAtom,
|
||||
tableScope
|
||||
);
|
||||
|
||||
const handleClose = () => setContextMenuTarget(null);
|
||||
|
||||
return (
|
||||
<Menu
|
||||
id="cell-context-menu"
|
||||
aria-label="Cell context menu"
|
||||
anchorEl={contextMenuTarget as any}
|
||||
open={Boolean(contextMenuTarget)}
|
||||
onClose={handleClose}
|
||||
anchorOrigin={{ vertical: "bottom", horizontal: "left" }}
|
||||
transformOrigin={{ vertical: "top", horizontal: "left" }}
|
||||
// sx={{
|
||||
// "& .MuiMenu-paper": {
|
||||
// backgroundColor: "background.default",
|
||||
// },
|
||||
// }}
|
||||
>
|
||||
<MenuContents onClose={handleClose} />
|
||||
</Menu>
|
||||
);
|
||||
}
|
||||
160
src/components/Table/ContextMenu/MenuContents.tsx
Normal file
160
src/components/Table/ContextMenu/MenuContents.tsx
Normal file
@@ -0,0 +1,160 @@
|
||||
import { useAtom, useSetAtom } from "jotai";
|
||||
import { getFieldProp } from "@src/components/fields";
|
||||
import { find } from "lodash-es";
|
||||
|
||||
import { Divider } from "@mui/material";
|
||||
import {
|
||||
CopyCells as DuplicateIcon,
|
||||
Clear as ClearIcon,
|
||||
} from "@src/assets/icons";
|
||||
import DeleteIcon from "@mui/icons-material/DeleteOutlined";
|
||||
|
||||
import MenuItem from "./MenuItem";
|
||||
|
||||
import {
|
||||
globalScope,
|
||||
altPressAtom,
|
||||
tableAddRowIdTypeAtom,
|
||||
confirmDialogAtom,
|
||||
} from "@src/atoms/globalScope";
|
||||
import {
|
||||
tableScope,
|
||||
tableSettingsAtom,
|
||||
tableSchemaAtom,
|
||||
tableRowsAtom,
|
||||
selectedCellAtom,
|
||||
addRowAtom,
|
||||
deleteRowAtom,
|
||||
updateFieldAtom,
|
||||
} from "@src/atoms/tableScope";
|
||||
import { IContextMenuItem } from "./MenuItem";
|
||||
import { FieldType } from "@src/constants/fields";
|
||||
|
||||
interface IMenuContentsProps {
|
||||
onClose: () => void;
|
||||
}
|
||||
|
||||
export default function MenuContents({ onClose }: IMenuContentsProps) {
|
||||
const [altPress] = useAtom(altPressAtom, globalScope);
|
||||
const [addRowIdType] = useAtom(tableAddRowIdTypeAtom, globalScope);
|
||||
const confirm = useSetAtom(confirmDialogAtom, globalScope);
|
||||
const [tableSettings] = useAtom(tableSettingsAtom, tableScope);
|
||||
const [tableSchema] = useAtom(tableSchemaAtom, tableScope);
|
||||
const [tableRows] = useAtom(tableRowsAtom, tableScope);
|
||||
const [selectedCell] = useAtom(selectedCellAtom, tableScope);
|
||||
const addRow = useSetAtom(addRowAtom, tableScope);
|
||||
const deleteRow = useSetAtom(deleteRowAtom, tableScope);
|
||||
const updateField = useSetAtom(updateFieldAtom, tableScope);
|
||||
|
||||
if (!tableSchema.columns || !selectedCell) return null;
|
||||
|
||||
const selectedColumn = tableSchema.columns[selectedCell.columnKey];
|
||||
const menuActions = getFieldProp("contextMenuActions", selectedColumn.type);
|
||||
|
||||
const actionGroups: IContextMenuItem[][] = [];
|
||||
|
||||
// Field type actions
|
||||
const fieldTypeActions = menuActions
|
||||
? menuActions(selectedCell, onClose)
|
||||
: [];
|
||||
if (fieldTypeActions.length > 0) actionGroups.push(fieldTypeActions);
|
||||
|
||||
if (selectedColumn.type === FieldType.derivative) {
|
||||
const renderedFieldMenuActions = getFieldProp(
|
||||
"contextMenuActions",
|
||||
selectedColumn.config?.renderFieldType
|
||||
);
|
||||
if (renderedFieldMenuActions) {
|
||||
actionGroups.push(renderedFieldMenuActions(selectedCell, onClose));
|
||||
}
|
||||
}
|
||||
|
||||
// Cell actions
|
||||
// TODO: Add copy and paste here
|
||||
const handleClearValue = () =>
|
||||
updateField({
|
||||
path: selectedCell.path,
|
||||
fieldName: selectedColumn.fieldName,
|
||||
value: null,
|
||||
deleteField: true,
|
||||
});
|
||||
const cellActions = [
|
||||
{
|
||||
label: altPress ? "Clear value" : "Clear value…",
|
||||
color: "error",
|
||||
icon: <ClearIcon />,
|
||||
onClick: altPress
|
||||
? handleClearValue
|
||||
: () => {
|
||||
confirm({
|
||||
title: "Clear cell value?",
|
||||
body: "The cell’s value cannot be recovered after",
|
||||
confirm: "Delete",
|
||||
confirmColor: "error",
|
||||
handleConfirm: handleClearValue,
|
||||
});
|
||||
onClose();
|
||||
},
|
||||
},
|
||||
];
|
||||
actionGroups.push(cellActions);
|
||||
|
||||
// Row actions
|
||||
const row = find(tableRows, ["_rowy_ref.path", selectedCell.path]);
|
||||
if (row) {
|
||||
const handleDelete = () => deleteRow(row._rowy_ref.path);
|
||||
const rowActions = [
|
||||
{
|
||||
label: "Duplicate row",
|
||||
icon: <DuplicateIcon />,
|
||||
disabled: tableSettings.tableType === "collectionGroup",
|
||||
onClick: () => {
|
||||
addRow({
|
||||
row,
|
||||
setId: addRowIdType === "custom" ? "decrement" : addRowIdType,
|
||||
});
|
||||
onClose();
|
||||
},
|
||||
},
|
||||
{
|
||||
label: altPress ? "Delete row" : "Delete row…",
|
||||
color: "error",
|
||||
icon: <DeleteIcon />,
|
||||
onClick: altPress
|
||||
? handleDelete
|
||||
: () => {
|
||||
confirm({
|
||||
title: "Delete row?",
|
||||
body: (
|
||||
<>
|
||||
Row path:
|
||||
<br />
|
||||
<code style={{ userSelect: "all", wordBreak: "break-all" }}>
|
||||
{row._rowy_ref.path}
|
||||
</code>
|
||||
</>
|
||||
),
|
||||
confirm: "Delete",
|
||||
confirmColor: "error",
|
||||
handleConfirm: handleDelete,
|
||||
});
|
||||
onClose();
|
||||
},
|
||||
},
|
||||
];
|
||||
actionGroups.push(rowActions);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{actionGroups.map((items, groupIndex) => (
|
||||
<>
|
||||
{groupIndex > 0 && <Divider variant="middle" />}
|
||||
{items.map((item, index: number) => (
|
||||
<MenuItem key={`contextMenu-${groupIndex}-${index}`} {...item} />
|
||||
))}
|
||||
</>
|
||||
))}
|
||||
</>
|
||||
);
|
||||
}
|
||||
36
src/components/Table/ContextMenu/MenuItem.tsx
Normal file
36
src/components/Table/ContextMenu/MenuItem.tsx
Normal file
@@ -0,0 +1,36 @@
|
||||
import {
|
||||
ListItemIcon,
|
||||
ListItemText,
|
||||
MenuItem,
|
||||
MenuItemProps,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
|
||||
export interface IContextMenuItem extends Partial<MenuItemProps> {
|
||||
onClick: () => void;
|
||||
icon?: React.ReactNode;
|
||||
label: string;
|
||||
disabled?: boolean;
|
||||
hotkeyLabel?: string;
|
||||
}
|
||||
|
||||
export default function ContextMenuItem({
|
||||
onClick,
|
||||
icon,
|
||||
label,
|
||||
disabled,
|
||||
hotkeyLabel,
|
||||
...props
|
||||
}: IContextMenuItem) {
|
||||
return (
|
||||
<MenuItem {...props} disabled={disabled} onClick={onClick}>
|
||||
<ListItemIcon>{icon}</ListItemIcon>
|
||||
<ListItemText>{label}</ListItemText>
|
||||
{hotkeyLabel && (
|
||||
<Typography variant="body2" color="text.secondary">
|
||||
{hotkeyLabel}
|
||||
</Typography>
|
||||
)}
|
||||
</MenuItem>
|
||||
);
|
||||
}
|
||||
2
src/components/Table/ContextMenu/index.ts
Normal file
2
src/components/Table/ContextMenu/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export * from "./ContextMenu";
|
||||
export { default } from "./ContextMenu";
|
||||
@@ -13,7 +13,6 @@ import {
|
||||
import { APP_BAR_HEIGHT } from "@src/layouts/Navigation";
|
||||
|
||||
// FIXME:
|
||||
// import ColumnMenu from "./ColumnMenu";
|
||||
// import ImportWizard from "@src/components/Wizards/ImportWizard";
|
||||
// import ImportCSV from "@src/components/TableToolbar/ImportCsv";
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useMemo, useState } from "react";
|
||||
import React, { useMemo, useState, Suspense } from "react";
|
||||
import { useAtom, useSetAtom } from "jotai";
|
||||
import { useDebouncedCallback, useThrottledCallback } from "use-debounce";
|
||||
import { DndProvider } from "react-dnd";
|
||||
@@ -15,7 +15,6 @@ import { LinearProgress } from "@mui/material";
|
||||
|
||||
import TableContainer, { OUT_OF_ORDER_MARGIN } from "./TableContainer";
|
||||
import ColumnHeader, { COLUMN_HEADER_HEIGHT } from "./ColumnHeader";
|
||||
// import ContextMenu from "./ContextMenu";
|
||||
import FinalColumnHeader from "./FinalColumnHeader";
|
||||
import FinalColumn from "./formatters/FinalColumn";
|
||||
import TableRow from "./TableRow";
|
||||
@@ -23,6 +22,8 @@ import EmptyState from "@src/components/EmptyState";
|
||||
// import BulkActions from "./BulkActions";
|
||||
import AddRow from "@src/components/TableToolbar/AddRow";
|
||||
import { AddRow as AddRowIcon } from "@src/assets/icons";
|
||||
import Loading from "@src/components/Loading";
|
||||
import ContextMenu from "./ContextMenu";
|
||||
|
||||
import {
|
||||
globalScope,
|
||||
@@ -211,10 +212,8 @@ export default function Table({
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* <Suspense fallback={<Loading message="Loading header" />}>
|
||||
<Hotkeys selectedCell={selectedCell} />
|
||||
</Suspense> */}
|
||||
<Suspense fallback={<Loading message="Loading fields" />}>
|
||||
{/* <Hotkeys selectedCell={selectedCell} /> */}
|
||||
<TableContainer rowHeight={rowHeight}>
|
||||
<DndProvider backend={HTML5Backend}>
|
||||
{showLeftScrollDivider && <div className="left-scroll-divider" />}
|
||||
@@ -268,7 +267,7 @@ export default function Table({
|
||||
// onRowsChange={() => {
|
||||
//console.log('onRowsChange',rows)
|
||||
// }}
|
||||
// FIXME: onFill={(e) => {
|
||||
// TODO: onFill={(e) => {
|
||||
// console.log("onFill", e);
|
||||
// const { columnKey, sourceRow, targetRows } = e;
|
||||
// if (updateCell)
|
||||
@@ -277,7 +276,8 @@ export default function Table({
|
||||
// );
|
||||
// return [];
|
||||
// }}
|
||||
onPaste={(e) => {
|
||||
onPaste={(e, ...args) => {
|
||||
console.log("onPaste", e, ...args);
|
||||
const value = e.sourceRow[e.sourceColumnKey];
|
||||
updateField({
|
||||
path: e.targetRow._rowy_ref.path,
|
||||
@@ -324,7 +324,8 @@ export default function Table({
|
||||
{tableNextPage.loading && <LinearProgress />}
|
||||
</TableContainer>
|
||||
|
||||
{/* <ContextMenu />
|
||||
<ContextMenu />
|
||||
{/*
|
||||
<BulkActions
|
||||
selectedRows={selectedRows}
|
||||
columns={columns}
|
||||
@@ -333,6 +334,6 @@ export default function Table({
|
||||
setSelectedRows([]);
|
||||
}}
|
||||
/> */}
|
||||
</>
|
||||
</Suspense>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
// FIXME:
|
||||
// import { useSetAnchorEle } from "@src/atoms/ContextMenu";
|
||||
import { Fragment } from "react";
|
||||
import { useSetAtom } from "jotai";
|
||||
import { Row, RowRendererProps } from "react-data-grid";
|
||||
|
||||
import OutOfOrderIndicator from "./OutOfOrderIndicator";
|
||||
|
||||
import { tableScope, contextMenuTargetAtom } from "@src/atoms/tableScope";
|
||||
|
||||
export default function TableRow(props: RowRendererProps<any>) {
|
||||
// const { setAnchorEle } = useSetAnchorEle();
|
||||
const handleContextMenu = (
|
||||
e: React.MouseEvent<HTMLDivElement, MouseEvent>
|
||||
) => {
|
||||
const setContextMenuTarget = useSetAtom(contextMenuTargetAtom, tableScope);
|
||||
const handleContextMenu = (e: React.MouseEvent) => {
|
||||
e.preventDefault();
|
||||
// setAnchorEle?.(e?.target as HTMLElement);
|
||||
setContextMenuTarget(e?.target as HTMLElement);
|
||||
};
|
||||
|
||||
if (props.row._rowy_outOfOrder)
|
||||
|
||||
@@ -1,11 +1,19 @@
|
||||
import { useAtom } from "jotai";
|
||||
import { find, get } from "lodash-es";
|
||||
import { useSnackbar } from "notistack";
|
||||
|
||||
import ReEvalIcon from "@mui/icons-material/Replay";
|
||||
import EvalIcon from "@mui/icons-material/PlayCircle";
|
||||
|
||||
import { useProjectContext } from "@src/contexts/ProjectContext";
|
||||
import { useSnackbar } from "notistack";
|
||||
import { SelectedCell } from "@src/atoms/ContextMenu";
|
||||
import { globalScope, rowyRunAtom } from "@src/atoms/globalScope";
|
||||
import {
|
||||
tableScope,
|
||||
tableSettingsAtom,
|
||||
tableSchemaAtom,
|
||||
tableRowsAtom,
|
||||
} from "@src/atoms/tableScope";
|
||||
import { getTableSchemaPath } from "@src/utils/table";
|
||||
import { IFieldConfig } from "@src/components/fields/types";
|
||||
import { runRoutes } from "@src/constants/runRoutes";
|
||||
|
||||
export interface IContextMenuActions {
|
||||
@@ -14,40 +22,41 @@ export interface IContextMenuActions {
|
||||
onClick: () => void;
|
||||
}
|
||||
|
||||
export default function ContextMenuActions(
|
||||
selectedCell: SelectedCell,
|
||||
reset: () => void | Promise<void>
|
||||
): IContextMenuActions[] {
|
||||
const { tableState, rowyRun } = useProjectContext();
|
||||
export const ContextMenuActions: IFieldConfig["contextMenuActions"] = (
|
||||
selectedCell,
|
||||
reset
|
||||
) => {
|
||||
const [rowyRun] = useAtom(rowyRunAtom, globalScope);
|
||||
const [tableSettings] = useAtom(tableSettingsAtom, tableScope);
|
||||
const [tableSchema] = useAtom(tableSchemaAtom, tableScope);
|
||||
const [tableRows] = useAtom(tableRowsAtom, tableScope);
|
||||
const { enqueueSnackbar, closeSnackbar } = useSnackbar();
|
||||
const columns = tableState?.columns;
|
||||
const rows = tableState?.rows;
|
||||
const selectedRowIndex = selectedCell.rowIndex as number;
|
||||
const selectedColIndex = selectedCell?.colIndex;
|
||||
const selectedCol = find(columns, { index: selectedColIndex });
|
||||
|
||||
const selectedCol = tableSchema.columns?.[selectedCell.columnKey];
|
||||
if (!selectedCol) return [];
|
||||
// don't show evalute button if function has external dependency
|
||||
|
||||
const selectedRow = find(tableRows, ["_rowy_ref.path", selectedCell.path]);
|
||||
const cellValue = get(selectedRow, selectedCol.fieldName);
|
||||
|
||||
if (!selectedCol) return [];
|
||||
|
||||
// don't show evaluate button if function has external dependency
|
||||
const code =
|
||||
selectedCol.config.derivativeFn ?? selectedCol.config.script ?? "";
|
||||
selectedCol.config?.derivativeFn ?? selectedCol.config?.script ?? "";
|
||||
if (code.includes("require(")) return [];
|
||||
const selectedRow = rows?.[selectedRowIndex];
|
||||
const cellValue = get(selectedRow, selectedCol.key);
|
||||
const handleClose = async () => await reset?.();
|
||||
|
||||
const handleEvaluate = async () => {
|
||||
try {
|
||||
if (!selectedCol || !rowyRun || !selectedRow) return;
|
||||
handleClose();
|
||||
reset();
|
||||
const evaluatingSnackKey = enqueueSnackbar("Evaluating...", {
|
||||
variant: "info",
|
||||
});
|
||||
const result = await rowyRun({
|
||||
route: runRoutes.evaluateDerivative,
|
||||
body: {
|
||||
ref: {
|
||||
path: selectedRow.ref.path,
|
||||
},
|
||||
schemaDocPath: tableState?.config.tableConfig.path,
|
||||
ref: { path: selectedCell.path },
|
||||
schemaDocPath: getTableSchemaPath(tableSettings),
|
||||
columnKey: selectedCol.key,
|
||||
},
|
||||
});
|
||||
@@ -70,4 +79,6 @@ export default function ContextMenuActions(
|
||||
];
|
||||
|
||||
return contextMenuActions;
|
||||
}
|
||||
};
|
||||
|
||||
export default ContextMenuActions;
|
||||
@@ -5,7 +5,7 @@ import { Derivative as DerivativeIcon } from "@src/assets/icons";
|
||||
import BasicCell from "@src/components/fields/_BasicCell/BasicCellNull";
|
||||
import NullEditor from "@src/components/Table/editors/NullEditor";
|
||||
import Settings, { settingsValidator } from "./Settings";
|
||||
// import ContextMenuActions from "./ContextMenuActions";
|
||||
import ContextMenuActions from "./ContextMenuActions";
|
||||
|
||||
export const config: IFieldConfig = {
|
||||
type: FieldType.derivative,
|
||||
@@ -20,7 +20,7 @@ export const config: IFieldConfig = {
|
||||
TableCell: withBasicCell(BasicCell),
|
||||
TableEditor: NullEditor as any,
|
||||
SideDrawerField: BasicCell as any,
|
||||
// FIXME: contextMenuActions: ContextMenuActions,
|
||||
contextMenuActions: ContextMenuActions,
|
||||
settings: Settings,
|
||||
settingsValidator,
|
||||
requireConfiguration: true,
|
||||
|
||||
@@ -1,42 +1,36 @@
|
||||
import { useAtom, useSetAtom } from "jotai";
|
||||
import { get } from "lodash-es";
|
||||
import { useSnackbar } from "notistack";
|
||||
import { get, find } from "lodash-es";
|
||||
|
||||
import Cut from "@mui/icons-material/ContentCut";
|
||||
// import Cut from "@mui/icons-material/ContentCut";
|
||||
import { CopyCells } from "@src/assets/icons";
|
||||
import Paste from "@mui/icons-material/ContentPaste";
|
||||
|
||||
import {
|
||||
tableScope,
|
||||
tableColumnsOrderedAtom,
|
||||
tableSchemaAtom,
|
||||
tableRowsAtom,
|
||||
updateFieldAtom,
|
||||
} from "@src/atoms/tableScope";
|
||||
import { useSnackbar } from "notistack";
|
||||
// import { SelectedCell } from "@src/atoms/ContextMenu";
|
||||
import { getFieldProp, getFieldType } from "@src/components/fields";
|
||||
import { IFieldConfig } from "@src/components/fields/types";
|
||||
|
||||
export interface IContextMenuActions {
|
||||
label: string;
|
||||
icon: React.ReactNode;
|
||||
onClick: () => void;
|
||||
}
|
||||
|
||||
export default function BasicContextMenuActions(
|
||||
selectedCell: any,
|
||||
reset: () => void | Promise<void>
|
||||
): IContextMenuActions[] {
|
||||
// TODO: Remove this and add `handlePaste` function to column config
|
||||
export const BasicContextMenuActions: IFieldConfig["contextMenuActions"] = (
|
||||
selectedCell,
|
||||
reset
|
||||
) => {
|
||||
const { enqueueSnackbar } = useSnackbar();
|
||||
|
||||
// TODO: Remove these useAtom calls that cause re-render
|
||||
const [tableColumnsOrdered] = useAtom(tableColumnsOrderedAtom, tableScope);
|
||||
const [tableSchema] = useAtom(tableSchemaAtom, tableScope);
|
||||
const [tableRows] = useAtom(tableRowsAtom, tableScope);
|
||||
const updateField = useSetAtom(updateFieldAtom, tableScope);
|
||||
|
||||
const selectedCol = tableColumnsOrdered[selectedCell?.colIndex];
|
||||
const selectedCol = tableSchema.columns?.[selectedCell.columnKey];
|
||||
if (!selectedCol) return [];
|
||||
|
||||
const selectedRow = tableRows[selectedCell.rowIndex];
|
||||
const cellValue = get(selectedRow, selectedCol.key);
|
||||
const selectedRow = find(tableRows, ["_rowy_ref.path", selectedCell.path]);
|
||||
const cellValue = get(selectedRow, selectedCol.fieldName);
|
||||
|
||||
const handleClose = async () => await reset?.();
|
||||
|
||||
@@ -50,21 +44,21 @@ export default function BasicContextMenuActions(
|
||||
handleClose();
|
||||
};
|
||||
|
||||
const handleCut = async () => {
|
||||
try {
|
||||
await navigator.clipboard.writeText(cellValue);
|
||||
if (typeof cellValue !== "undefined")
|
||||
updateField({
|
||||
path: selectedRow._rowy_ref.path,
|
||||
fieldName: selectedCol.fieldName,
|
||||
value: undefined,
|
||||
deleteField: true,
|
||||
});
|
||||
} catch (error) {
|
||||
enqueueSnackbar(`Failed to cut: ${error}`, { variant: "error" });
|
||||
}
|
||||
handleClose();
|
||||
};
|
||||
// const handleCut = async () => {
|
||||
// try {
|
||||
// await navigator.clipboard.writeText(cellValue);
|
||||
// if (typeof cellValue !== "undefined")
|
||||
// updateField({
|
||||
// path: selectedCell.path,
|
||||
// fieldName: selectedCol.fieldName,
|
||||
// value: undefined,
|
||||
// deleteField: true,
|
||||
// });
|
||||
// } catch (error) {
|
||||
// enqueueSnackbar(`Failed to cut: ${error}`, { variant: "error" });
|
||||
// }
|
||||
// handleClose();
|
||||
// };
|
||||
|
||||
const handlePaste = async () => {
|
||||
try {
|
||||
@@ -85,7 +79,7 @@ export default function BasicContextMenuActions(
|
||||
break;
|
||||
}
|
||||
updateField({
|
||||
path: selectedRow._rowy_ref.path,
|
||||
path: selectedCell.path,
|
||||
fieldName: selectedCol.fieldName,
|
||||
value: parsed,
|
||||
});
|
||||
@@ -97,10 +91,12 @@ export default function BasicContextMenuActions(
|
||||
};
|
||||
|
||||
const contextMenuActions = [
|
||||
{ label: "Cut", icon: <Cut />, onClick: handleCut },
|
||||
// { label: "Cut", icon: <Cut />, onClick: handleCut },
|
||||
{ label: "Copy", icon: <CopyCells />, onClick: handleCopy },
|
||||
{ label: "Paste", icon: <Paste />, onClick: handlePaste },
|
||||
];
|
||||
|
||||
return contextMenuActions;
|
||||
}
|
||||
};
|
||||
|
||||
export default BasicContextMenuActions;
|
||||
|
||||
@@ -4,8 +4,8 @@ import { Control, UseFormReturn } from "react-hook-form";
|
||||
import { PopoverProps } from "@mui/material";
|
||||
import { WhereFilterOp } from "firebase/firestore";
|
||||
import { ColumnConfig, TableRow, TableRowRef } from "@src/types/table";
|
||||
import { selectedCellAtom } from "@src/atoms/tableScope";
|
||||
import { IContextMenuActions } from "./_BasicCell/BasicCellContextMenuActions";
|
||||
import { SelectedCell } from "@src/atoms/tableScope";
|
||||
import { IContextMenuItem } from "@src/components/Table/ContextMenu/MenuItem";
|
||||
|
||||
export { FieldType };
|
||||
|
||||
@@ -21,9 +21,9 @@ export interface IFieldConfig {
|
||||
description?: string;
|
||||
setupGuideLink?: string;
|
||||
contextMenuActions?: (
|
||||
selectedCell: ReturnType<typeof selectedCellAtom["read"]>,
|
||||
reset: () => Promise<void>
|
||||
) => IContextMenuActions[];
|
||||
selectedCell: SelectedCell,
|
||||
reset: () => void
|
||||
) => IContextMenuItem[];
|
||||
TableCell: React.ComponentType<FormatterProps<TableRow>>;
|
||||
TableEditor: React.ComponentType<EditorProps<TableRow, any>>;
|
||||
SideDrawerField: React.ComponentType<ISideDrawerFieldProps>;
|
||||
|
||||
@@ -8,11 +8,11 @@ import reportWebVitals from "./reportWebVitals";
|
||||
const container = document.getElementById("root")!;
|
||||
const root = createRoot(container);
|
||||
root.render(
|
||||
// <StrictMode>
|
||||
<Providers>
|
||||
<App />
|
||||
</Providers>
|
||||
// </StrictMode>
|
||||
<StrictMode>
|
||||
<Providers>
|
||||
<App />
|
||||
</Providers>
|
||||
</StrictMode>
|
||||
);
|
||||
|
||||
// If you want to start measuring performance in your app, pass a function
|
||||
|
||||
Reference in New Issue
Block a user