prepare updated SideDrawer without react-hook-form

This commit is contained in:
Sidney Alcantara
2022-06-03 12:34:18 +10:00
parent 3a1a84ed4a
commit 109960d757
30 changed files with 312 additions and 57 deletions

View File

@@ -7,7 +7,7 @@ import FormControlLabel from "@mui/material/FormControlLabel";
import { Typography, TextField, MenuItem, ListItemText } from "@mui/material";
import { getFieldProp } from "@src/components/fields";
import FieldSkeleton from "@src/components/SideDrawer/Form/FieldSkeleton";
import FieldSkeleton from "@src/components/SideDrawer/FieldSkeleton";
import CodeEditorHelper from "@src/components/CodeEditor/CodeEditorHelper";
import FormAutosave from "./FormAutosave";
import { FieldType } from "@src/constants/fields";

View File

@@ -0,0 +1,113 @@
import { Suspense } from "react";
import { useAtom } from "jotai";
import { ErrorBoundary } from "react-error-boundary";
import { Stack, InputLabel, Typography, IconButton } from "@mui/material";
import { DocumentPath as DocumentPathIcon } from "@src/assets/icons";
import LaunchIcon from "@mui/icons-material/Launch";
import LockIcon from "@mui/icons-material/LockOutlined";
import { InlineErrorFallback } from "@src/components/ErrorFallback";
import FieldSkeleton from "./FieldSkeleton";
import { globalScope, projectIdAtom } from "@src/atoms/globalScope";
import { FieldType } from "@src/constants/fields";
import { getFieldProp } from "@src/components/fields";
export interface IFieldWrapperProps {
children?: React.ReactNode;
type: FieldType | "debug";
name?: string;
label?: React.ReactNode;
debugText?: React.ReactNode;
disabled?: boolean;
}
export default function FieldWrapper({
children,
type,
name,
label,
debugText,
disabled,
}: IFieldWrapperProps) {
const [projectId] = useAtom(projectIdAtom, globalScope);
return (
<div>
<Stack
direction="row"
alignItems="center"
sx={{
color: "text.primary",
height: 24,
scrollMarginTop: 24,
"& svg": {
display: "block",
color: "action.active",
fontSize: `${18 / 16}rem`,
},
}}
>
{type === "debug" ? <DocumentPathIcon /> : getFieldProp("icon", type)}
<InputLabel
id={`sidedrawer-label-${name}`}
htmlFor={`sidedrawer-field-${name}`}
sx={{ flexGrow: 1, lineHeight: "18px", ml: 0.75 }}
>
{label}
</InputLabel>
{disabled && <LockIcon />}
</Stack>
<ErrorBoundary FallbackComponent={InlineErrorFallback}>
<Suspense fallback={<FieldSkeleton />}>
{children ??
(!debugText && (
<Typography
variant="body2"
color="text.secondary"
sx={{ paddingLeft: 18 / 8 + 0.75 }}
>
This field cannot be edited here.
</Typography>
))}
</Suspense>
</ErrorBoundary>
{debugText && (
<Stack direction="row" alignItems="center">
<Typography
variant="body2"
color="text.secondary"
sx={{
flexGrow: 1,
paddingLeft: 18 / 8 + 0.75,
fontFamily: "mono",
whiteSpace: "normal",
wordBreak: "break-all",
userSelect: "all",
}}
>
{debugText}
</Typography>
<IconButton
href={`https://console.firebase.google.com/project/${projectId}/firestore/data/~2F${(
debugText as string
).replace(/\//g, "~2F")}`}
target="_blank"
rel="noopener"
aria-label="Open in Firebase Console"
size="small"
edge="end"
sx={{ ml: 1 }}
>
<LaunchIcon />
</IconButton>
</Stack>
)}
</div>
);
}

View File

@@ -1,7 +1,7 @@
import { useEffect } from "react";
import clsx from "clsx";
import { useAtom } from "jotai";
import { findIndex } from "lodash-es";
import { find, findIndex } from "lodash-es";
import { ErrorBoundary } from "react-error-boundary";
import { DataGridHandle } from "react-data-grid";
@@ -12,6 +12,7 @@ import ChevronDownIcon from "@mui/icons-material/KeyboardArrowDown";
import ErrorFallback from "@src/components/ErrorFallback";
import StyledDrawer from "./StyledDrawer";
import SideDrawerFields from "./SideDrawerFields";
// import Form from "./Form";
import { globalScope, userSettingsAtom } from "@src/atoms/globalScope";
@@ -44,6 +45,7 @@ export default function SideDrawer({
const [cell, setCell] = useAtom(selectedCellAtom, tableScope);
const [open, setOpen] = useAtom(sideDrawerOpenAtom, tableScope);
const selectedRow = find(tableRows, ["_rowy_ref.path", cell?.path]);
const selectedCellRowIndex = findIndex(tableRows, [
"_rowy_ref.path",
cell?.path,
@@ -109,17 +111,9 @@ export default function SideDrawer({
>
<ErrorBoundary FallbackComponent={ErrorFallback}>
<div className="sidedrawer-contents">
{cell?.path}
{/* {open &&
(urlDocState.doc || cell) &&
!isEmpty(tableState?.columns) && (
<Form
key={`${cell?.row}-${urlDocState.path}`}
values={
urlDocState.doc ?? tableState?.rows[cell?.row ?? -1] ?? {}
}
/>
)} */}
{open && cell && selectedRow && (
<SideDrawerFields key={cell.path} row={selectedRow} />
)}
</div>
</ErrorBoundary>

View File

@@ -0,0 +1,143 @@
import { useEffect, createElement } from "react";
import { useAtom } from "jotai";
import { isEmpty, get } from "lodash-es";
import { Stack, FormControlLabel, Switch } from "@mui/material";
import FieldWrapper from "./FieldWrapper";
import {
globalScope,
userRolesAtom,
userSettingsAtom,
sideDrawerShowHiddenFieldsAtom,
} from "@src/atoms/globalScope";
import {
tableScope,
tableIdAtom,
tableSettingsAtom,
tableColumnsOrderedAtom,
selectedCellAtom,
} from "@src/atoms/tableScope";
import { formatSubTableName } from "@src/utils/table";
import { getFieldProp } from "@src/components/fields";
import { TableRow } from "@src/types/table";
import { IFieldConfig } from "@src/components/fields/types";
export interface ISideDrawerFieldsProps {
row: TableRow;
}
export default function SideDrawerFields({ row }: ISideDrawerFieldsProps) {
const [userRoles] = useAtom(userRolesAtom, globalScope);
const [userSettings] = useAtom(userSettingsAtom, globalScope);
const [tableId] = useAtom(tableIdAtom, tableScope);
const [tableSettings] = useAtom(tableSettingsAtom, tableScope);
const [tableColumnsOrdered] = useAtom(tableColumnsOrderedAtom, tableScope);
const [selectedCell] = useAtom(selectedCellAtom, tableScope);
const [showHiddenFields, setShowHiddenFields] = useAtom(
sideDrawerShowHiddenFieldsAtom,
globalScope
);
const userDocHiddenFields =
userSettings.tables?.[formatSubTableName(tableId)]?.hiddenFields ?? [];
const fields = showHiddenFields
? tableColumnsOrdered
: tableColumnsOrdered.filter((f) => !userDocHiddenFields.includes(f.key));
// Scroll to selected column
const selectedColumnKey = selectedCell?.columnKey;
useEffect(() => {
if (!selectedColumnKey) return;
const labelElem = document.getElementById(
`sidedrawer-label-${selectedColumnKey}`
)?.parentElement;
const fieldElem = document.getElementById(
`sidedrawer-field-${selectedColumnKey}`
);
// Time out for double-clicking on cells, which can open the null editor
setTimeout(() => {
if (labelElem) labelElem.scrollIntoView({ behavior: "smooth" });
if (fieldElem) fieldElem.focus({ preventScroll: true });
}, 200);
}, [selectedColumnKey]);
return (
<Stack spacing={3}>
{fields.map((field, i) => {
// Derivative/aggregate field support
let type = field.type;
if (field.config && field.config.renderFieldType) {
type = field.config.renderFieldType;
}
const fieldComponent: IFieldConfig["SideDrawerField"] = getFieldProp(
"SideDrawerField",
type
);
// Should not reach this state
if (isEmpty(fieldComponent)) {
// console.error('Could not find SideDrawerField component', field);
return null;
}
// Disable field if locked, or if table is read-only
const disabled = Boolean(
field.editable === false ||
(tableSettings.readOnly && !userRoles.includes("ADMIN"))
);
return (
<FieldWrapper
key={field.key ?? i}
type={field.type}
name={field.key}
label={field.name}
disabled={disabled}
>
{createElement(fieldComponent, {
column: field as any,
control: {} as any,
docRef: row._rowy_ref,
disabled,
value: get(row, field.fieldName),
onSubmit: console.log,
useFormMethods: {} as any,
})}
</FieldWrapper>
);
})}
<FieldWrapper
type="debug"
name="_debug_path"
label="Document path"
debugText={row._rowy_ref.path ?? row._rowy_ref.id ?? "No ref"}
/>
{userDocHiddenFields.length > 0 && (
<FormControlLabel
label={`Show ${userDocHiddenFields.length} hidden field${
userDocHiddenFields.length === 1 ? "" : "s"
}`}
control={
<Switch
checked={showHiddenFields}
onChange={(e) => setShowHiddenFields(e.target.checked)}
/>
}
sx={{
borderTop: 1,
borderColor: "divider",
pt: 3,
"& .MuiSwitch-root": { ml: -0.5 },
}}
/>
)}
</Stack>
);
}

View File

@@ -1,25 +1,25 @@
import { Control } from "react-hook-form";
// import { Control } from "react-hook-form";
import { colord } from "colord";
import type { SystemStyleObject, Theme } from "@mui/system";
import { FieldType } from "@src/constants/fields";
import { TableRowRef } from "@src/types/table";
// import { FieldType } from "@src/constants/fields";
// import { TableRowRef } from "@src/types/table";
export interface IFieldProps {
control: Control;
name: string;
docRef: TableRowRef;
editable?: boolean;
}
// export interface ISideDrawerFieldProps {
// control: Control;
// name: string;
// docRef: TableRowRef;
// editable?: boolean;
// }
export type Values = Record<string, any>;
export type Field = {
type?: FieldType;
name: string;
label?: string;
[key: string]: any;
};
export type Fields = (Field | ((values: Values) => Field))[];
// export type Values = Record<string, any>;
// export type Field = {
// type?: FieldType;
// name: string;
// label?: string;
// [key: string]: any;
// };
// export type Fields = (Field | ((values: Values) => Field))[];
export const fieldSx: SystemStyleObject<Theme> = {
borderRadius: 1,

View File

@@ -94,7 +94,7 @@ export function ColumnItem({
<Stack
direction="row"
alignItems="center"
gap={1}
spacing={1}
{...props}
sx={[
{ color: "text.secondary", width: "100%" },

View File

@@ -3,7 +3,7 @@ import { IExtensionModalStepProps } from "./ExtensionModal";
import useStateRef from "react-usestateref";
import { Typography } from "@mui/material";
import FieldSkeleton from "@src/components/SideDrawer/Form/FieldSkeleton";
import FieldSkeleton from "@src/components/SideDrawer/FieldSkeleton";
import CodeEditorHelper from "@src/components/CodeEditor/CodeEditorHelper";
import { WIKI_LINKS } from "@src/constants/externalLinks";

View File

@@ -3,7 +3,7 @@ import { IExtensionModalStepProps } from "./ExtensionModal";
import { upperFirst } from "lodash-es";
import useStateRef from "react-usestateref";
import FieldSkeleton from "@src/components/SideDrawer/Form/FieldSkeleton";
import FieldSkeleton from "@src/components/SideDrawer/FieldSkeleton";
import CodeEditorHelper from "@src/components/CodeEditor/CodeEditorHelper";
import { WIKI_LINKS } from "@src/constants/externalLinks";

View File

@@ -6,7 +6,7 @@ import { Grid, MenuItem, TextField, InputLabel } from "@mui/material";
import MultiSelect from "@rowy/multiselect";
import ColumnSelect from "@src/components/TableToolbar/ColumnSelect";
import FormAutosave from "@src/components/ColumnModals/ColumnConfigModal/FormAutosave";
import FieldSkeleton from "@src/components/SideDrawer/Form/FieldSkeleton";
import FieldSkeleton from "@src/components/SideDrawer/FieldSkeleton";
import type { useFilterInputs } from "./useFilterInputs";
import { getFieldType, getFieldProp } from "@src/components/fields";

View File

@@ -26,7 +26,7 @@ import UndoIcon from "@mui/icons-material/Undo";
import SteppedAccordion from "@src/components/SteppedAccordion";
import MultiSelect from "@rowy/multiselect";
import FieldSkeleton from "@src/components/SideDrawer/Form/FieldSkeleton";
import FieldSkeleton from "@src/components/SideDrawer/FieldSkeleton";
import CodeEditorHelper from "@src/components/CodeEditor/CodeEditorHelper";
import InlineOpenInNewIcon from "@src/components/InlineOpenInNewIcon";
import FormFieldSnippets from "./FormFieldSnippets";

View File

@@ -4,7 +4,7 @@ import { ISideDrawerFieldProps } from "@src/components/fields/types";
import { Box, Stack, Link } from "@mui/material";
import ActionFab from "./ActionFab";
import { fieldSx } from "@src/components/SideDrawer/Form/utils";
import { fieldSx } from "@src/components/SideDrawer/utils";
import { sanitiseCallableName, isUrl } from "./utils";
export default function Action({

View File

@@ -3,7 +3,7 @@ import { ISideDrawerFieldProps } from "@src/components/fields/types";
import { ButtonBase, FormControlLabel, Switch } from "@mui/material";
import { fieldSx } from "@src/components/SideDrawer/Form/utils";
import { fieldSx } from "@src/components/SideDrawer/utils";
export default function Checkbox({
column,

View File

@@ -6,7 +6,7 @@ import "react-color-palette/lib/css/styles.css";
import { ButtonBase, Box, Collapse } from "@mui/material";
import { fieldSx } from "@src/components/SideDrawer/Form/utils";
import { fieldSx } from "@src/components/SideDrawer/utils";
export default function Color({
column,

View File

@@ -12,7 +12,7 @@ import {
} from "@mui/material";
import SteppedAccordion from "@src/components/SteppedAccordion";
import FieldSkeleton from "@src/components/SideDrawer/Form/FieldSkeleton";
import FieldSkeleton from "@src/components/SideDrawer/FieldSkeleton";
import CodeEditorHelper from "@src/components/CodeEditor/CodeEditorHelper";
import InlineOpenInNewIcon from "@src/components/InlineOpenInNewIcon";
/* eslint-disable import/no-webpack-loader-syntax */

View File

@@ -3,7 +3,7 @@ import { useAtom } from "jotai";
import { ISideDrawerFieldProps } from "@src/components/fields/types";
import { Box } from "@mui/material";
import { fieldSx } from "@src/components/SideDrawer/Form/utils";
import { fieldSx } from "@src/components/SideDrawer/utils";
import { format } from "date-fns";
import { DATE_TIME_FORMAT } from "@src/constants/dates";

View File

@@ -3,7 +3,7 @@ import { useAtom } from "jotai";
import { ISideDrawerFieldProps } from "@src/components/fields/types";
import { Box, Stack, Typography, Avatar } from "@mui/material";
import { fieldSx } from "@src/components/SideDrawer/Form/utils";
import { fieldSx } from "@src/components/SideDrawer/utils";
import { format } from "date-fns";
import { DATE_TIME_FORMAT } from "@src/constants/dates";

View File

@@ -4,7 +4,7 @@ import { useAtom, useSetAtom } from "jotai";
import { Grid, InputLabel, FormHelperText } from "@mui/material";
import MultiSelect from "@rowy/multiselect";
import FieldSkeleton from "@src/components/SideDrawer/Form/FieldSkeleton";
import FieldSkeleton from "@src/components/SideDrawer/FieldSkeleton";
import FieldsDropdown from "@src/components/ColumnModals/FieldsDropdown";
import CodeEditorHelper from "@src/components/CodeEditor/CodeEditorHelper";

View File

@@ -2,7 +2,7 @@ import { Controller } from "react-hook-form";
import { ISideDrawerFieldProps } from "@src/components/fields/types";
import { Box } from "@mui/material";
import { fieldSx } from "@src/components/SideDrawer/Form/utils";
import { fieldSx } from "@src/components/SideDrawer/utils";
import { getDurationString } from "./utils";
export default function Duration({ column, control }: ISideDrawerFieldProps) {

View File

@@ -21,7 +21,7 @@ import { FileIcon } from ".";
import CircularProgressOptical from "@src/components/CircularProgressOptical";
import { DATE_TIME_FORMAT } from "@src/constants/dates";
import { fieldSx } from "@src/components/SideDrawer/Form/utils";
import { fieldSx } from "@src/components/SideDrawer/utils";
import { globalScope, confirmDialogAtom } from "@src/atoms/globalScope";
import { tableScope, updateFieldAtom } from "@src/atoms/tableScope";
import { FileValue } from "@src/types/table";

View File

@@ -1,7 +1,7 @@
import { ISideDrawerFieldProps } from "@src/components/fields/types";
import { Box } from "@mui/material";
import { fieldSx } from "@src/components/SideDrawer/Form/utils";
import { fieldSx } from "@src/components/SideDrawer/utils";
export default function Id({ docRef }: ISideDrawerFieldProps) {
return (

View File

@@ -25,7 +25,7 @@ import CircularProgressOptical from "@src/components/CircularProgressOptical";
import { globalScope, confirmDialogAtom } from "@src/atoms/globalScope";
import { tableScope, updateFieldAtom } from "@src/atoms/tableScope";
import { IMAGE_MIME_TYPES } from ".";
import { fieldSx } from "@src/components/SideDrawer/Form/utils";
import { fieldSx } from "@src/components/SideDrawer/utils";
const imgSx = {
position: "relative",

View File

@@ -12,7 +12,7 @@ import TabContext from "@mui/lab/TabContext";
import TabList from "@mui/lab/TabList";
import TabPanel from "@mui/lab/TabPanel";
import { fieldSx } from "@src/components/SideDrawer/Form/utils";
import { fieldSx } from "@src/components/SideDrawer/utils";
import { globalScope, jsonEditorAtom } from "@src/atoms/globalScope";
const isValidJson = (val: any) => {

View File

@@ -6,7 +6,7 @@ import { Rating as MuiRating } from "@mui/material";
import "@mui/lab";
import StarBorderIcon from "@mui/icons-material/StarBorder";
import { fieldSx } from "@src/components/SideDrawer/Form/utils";
import { fieldSx } from "@src/components/SideDrawer/utils";
export default function Rating({
control,

View File

@@ -2,7 +2,7 @@ import { Controller } from "react-hook-form";
import { ISideDrawerFieldProps } from "@src/components/fields/types";
import { Slider as MuiSlider, Stack, Typography } from "@mui/material";
import { fieldSx } from "@src/components/SideDrawer/Form/utils";
import { fieldSx } from "@src/components/SideDrawer/utils";
export default function Slider({
control,

View File

@@ -5,7 +5,7 @@ import { Link } from "react-router-dom";
import { Box, Stack, IconButton } from "@mui/material";
import LaunchIcon from "@mui/icons-material/Launch";
import { fieldSx } from "@src/components/SideDrawer/Form/utils";
import { fieldSx } from "@src/components/SideDrawer/utils";
import { useSubTableData } from "./utils";
export default function SubTable({

View File

@@ -3,7 +3,7 @@ import { useAtom } from "jotai";
import { ISideDrawerFieldProps } from "@src/components/fields/types";
import { Box } from "@mui/material";
import { fieldSx } from "@src/components/SideDrawer/Form/utils";
import { fieldSx } from "@src/components/SideDrawer/utils";
import { format } from "date-fns";
import { DATE_TIME_FORMAT } from "@src/constants/dates";

View File

@@ -3,7 +3,7 @@ import { useAtom } from "jotai";
import { ISideDrawerFieldProps } from "@src/components/fields/types";
import { Box, Stack, Typography, Avatar } from "@mui/material";
import { fieldSx } from "@src/components/SideDrawer/Form/utils";
import { fieldSx } from "@src/components/SideDrawer/utils";
import { format } from "date-fns";
import { DATE_TIME_FORMAT } from "@src/constants/dates";

View File

@@ -2,7 +2,7 @@ import { Controller } from "react-hook-form";
import { ISideDrawerFieldProps } from "@src/components/fields/types";
import { Box, Stack, Typography, Avatar } from "@mui/material";
import { fieldSx } from "@src/components/SideDrawer/Form/utils";
import { fieldSx } from "@src/components/SideDrawer/utils";
import { format } from "date-fns";
import { DATE_TIME_FORMAT } from "@src/constants/dates";

View File

@@ -3,8 +3,8 @@ import { FormatterProps, EditorProps } from "react-data-grid";
import { Control, UseFormReturn } from "react-hook-form";
import { PopoverProps } from "@mui/material";
import { WhereFilterOp } from "firebase/firestore";
import { TableRow, TableRowRef } from "@src/types/table";
// import { SelectedCell } from "@src/atoms/ContextMenu";
import { ColumnConfig, TableRow, TableRowRef } from "@src/types/table";
import { selectedCellAtom } from "@src/atoms/tableScope";
import { IContextMenuActions } from "./_BasicCell/BasicCellContextMenuActions";
export { FieldType };
@@ -21,7 +21,7 @@ export interface IFieldConfig {
description?: string;
setupGuideLink?: string;
contextMenuActions?: (
selectedCell: any, // FIXME: SelectedCell,
selectedCell: ReturnType<typeof selectedCellAtom["read"]>,
reset: () => Promise<void>
) => IContextMenuActions[];
TableCell: React.ComponentType<FormatterProps<TableRow>>;
@@ -62,10 +62,15 @@ export interface IPopoverCellProps extends IPopoverInlineCellProps {
}
export interface ISideDrawerFieldProps {
column: FormatterProps<TableRow>["column"] & { config?: Record<string, any> };
column: FormatterProps<TableRow>["column"] & ColumnConfig;
control: Control;
docRef: TableRowRef;
disabled: boolean;
value: any;
onSubmit: (value: any) => void;
/** @deprecated */
useFormMethods: UseFormReturn;
}