mirror of
https://github.com/rowyio/rowy.git
synced 2026-07-13 13:59:05 +02:00
consolidate all field props to IFieldProps
This commit is contained in:
@@ -7,7 +7,7 @@ import _isUndefined from "lodash/isUndefined";
|
||||
import _reduce from "lodash/reduce";
|
||||
|
||||
import { Control, useWatch } from "react-hook-form";
|
||||
import { Values } from ".";
|
||||
import { Values } from "./utils";
|
||||
|
||||
import { useAppContext } from "contexts/appContext";
|
||||
import { useFiretableContext, firetableUser } from "contexts/firetableContext";
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React, { useContext, useState } from "react";
|
||||
import { Control, Controller, useWatch } from "react-hook-form";
|
||||
import { Controller, useWatch } from "react-hook-form";
|
||||
import { IFieldProps } from "../utils";
|
||||
|
||||
import {
|
||||
createStyles,
|
||||
@@ -40,12 +41,8 @@ const useStyles = makeStyles(theme =>
|
||||
})
|
||||
);
|
||||
|
||||
export interface IActionProps {
|
||||
control: Control;
|
||||
name: string;
|
||||
docRef: firebase.firestore.DocumentReference;
|
||||
export interface IActionProps extends IFieldProps {
|
||||
config: { callableName: string };
|
||||
editable?: boolean;
|
||||
}
|
||||
|
||||
function Action({ control, name, docRef, editable, config }: IActionProps) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React from "react";
|
||||
import { Controller, Control } from "react-hook-form";
|
||||
import { Controller } from "react-hook-form";
|
||||
import { IFieldProps } from "../utils";
|
||||
|
||||
import {
|
||||
makeStyles,
|
||||
@@ -38,15 +39,16 @@ const useStyles = makeStyles(theme =>
|
||||
})
|
||||
);
|
||||
|
||||
export interface ICheckboxProps extends MuiSwitchProps {
|
||||
control: Control;
|
||||
name: string;
|
||||
export interface ICheckboxProps
|
||||
extends IFieldProps,
|
||||
Omit<MuiSwitchProps, "name"> {
|
||||
label?: React.ReactNode;
|
||||
editable?: boolean;
|
||||
}
|
||||
|
||||
export default function Checkbox({
|
||||
control,
|
||||
docRef,
|
||||
label,
|
||||
name,
|
||||
editable,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React, { useState, useEffect, useRef } from "react";
|
||||
import { Controller, Control } from "react-hook-form";
|
||||
import { Controller } from "react-hook-form";
|
||||
import { IFieldProps } from "../utils";
|
||||
|
||||
import AceEditor from "react-ace";
|
||||
import "ace-builds/src-noconflict/mode-javascript";
|
||||
@@ -101,12 +102,7 @@ function ControlledCode({ onChange, onBlur, value }: IControlledCodeProps) {
|
||||
);
|
||||
}
|
||||
|
||||
export interface ICodeProps {
|
||||
control: Control;
|
||||
name: string;
|
||||
}
|
||||
|
||||
export default function Code({ control, name, ...props }: ICodeProps) {
|
||||
export default function Code({ control, docRef, name, ...props }: IFieldProps) {
|
||||
return (
|
||||
<Controller
|
||||
control={control}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React, { useState } from "react";
|
||||
import { Controller, Control } from "react-hook-form";
|
||||
import { Controller } from "react-hook-form";
|
||||
import { IFieldProps } from "../utils";
|
||||
import { ChromePicker } from "react-color";
|
||||
|
||||
import {
|
||||
@@ -39,12 +40,7 @@ const useStyles = makeStyles(theme =>
|
||||
})
|
||||
);
|
||||
|
||||
export interface IColorProps {
|
||||
control: Control;
|
||||
name: string;
|
||||
}
|
||||
|
||||
export default function Color({ control, name }: IColorProps) {
|
||||
export default function Color({ control, name }: IFieldProps) {
|
||||
const classes = useStyles();
|
||||
|
||||
const [showPicker, setShowPicker] = useState(false);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React from "react";
|
||||
import { Control, Controller } from "react-hook-form";
|
||||
import { Controller } from "react-hook-form";
|
||||
import { IFieldProps } from "../utils";
|
||||
|
||||
import { useTheme, Grid, Chip } from "@material-ui/core";
|
||||
|
||||
@@ -7,13 +8,13 @@ import ConnectTableSelect, {
|
||||
IConnectTableSelectProps,
|
||||
} from "components/ConnectTableSelect";
|
||||
|
||||
export interface IConnectTableProps extends Partial<IConnectTableSelectProps> {
|
||||
control: Control;
|
||||
name: string;
|
||||
}
|
||||
export interface IConnectTableProps
|
||||
extends IFieldProps,
|
||||
Partial<IConnectTableSelectProps> {}
|
||||
|
||||
export default function ConnectTable({
|
||||
control,
|
||||
docRef,
|
||||
name,
|
||||
editable,
|
||||
...props
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React from "react";
|
||||
import { Controller, Control } from "react-hook-form";
|
||||
import { Controller } from "react-hook-form";
|
||||
import { IFieldProps } from "../utils";
|
||||
|
||||
import { useTheme } from "@material-ui/core";
|
||||
import {
|
||||
@@ -12,13 +13,12 @@ import { MuiPickersUtilsProvider } from "@material-ui/pickers";
|
||||
import DateFnsUtils from "@date-io/date-fns";
|
||||
|
||||
export interface IDatePickerProps
|
||||
extends Omit<KeyboardDatePickerProps, "onChange" | "value"> {
|
||||
control: Control;
|
||||
name: string;
|
||||
}
|
||||
extends IFieldProps,
|
||||
Omit<KeyboardDatePickerProps, "name" | "onChange" | "value"> {}
|
||||
|
||||
export default function DatePicker({
|
||||
control,
|
||||
docRef,
|
||||
name,
|
||||
...props
|
||||
}: IDatePickerProps) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React from "react";
|
||||
import { Controller, Control } from "react-hook-form";
|
||||
import { Controller } from "react-hook-form";
|
||||
import { IFieldProps } from "../utils";
|
||||
|
||||
import { useTheme } from "@material-ui/core";
|
||||
import {
|
||||
@@ -14,13 +15,12 @@ import { MuiPickersUtilsProvider } from "@material-ui/pickers";
|
||||
import DateFnsUtils from "@date-io/date-fns";
|
||||
|
||||
export interface IDateTimePickerProps
|
||||
extends Omit<KeyboardDateTimePickerProps, "onChange" | "value"> {
|
||||
control: Control;
|
||||
name: string;
|
||||
}
|
||||
extends IFieldProps,
|
||||
Omit<KeyboardDateTimePickerProps, "name" | "onChange" | "value"> {}
|
||||
|
||||
export default function DateTimePicker({
|
||||
control,
|
||||
docRef,
|
||||
name,
|
||||
...props
|
||||
}: IDateTimePickerProps) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React, { useCallback, useState } from "react";
|
||||
import clsx from "clsx";
|
||||
import { Controller, Control } from "react-hook-form";
|
||||
import { Controller } from "react-hook-form";
|
||||
import { IFieldProps } from "../utils";
|
||||
|
||||
import { useDropzone } from "react-dropzone";
|
||||
import useUploader, { FileValue } from "hooks/useFiretable/useUploader";
|
||||
@@ -55,7 +56,7 @@ const useStyles = makeStyles(theme =>
|
||||
);
|
||||
|
||||
export interface IControlledFileUploaderProps
|
||||
extends Pick<IFileUploaderProps, "editable" | "docRef" | "name"> {
|
||||
extends Pick<IFieldProps, "editable" | "docRef" | "name"> {
|
||||
onChange: (...event: any[]) => void;
|
||||
onBlur: () => void;
|
||||
value: any;
|
||||
@@ -173,19 +174,7 @@ export function ControlledFileUploader({
|
||||
);
|
||||
}
|
||||
|
||||
export interface IFileUploaderProps {
|
||||
control: Control;
|
||||
name: string;
|
||||
|
||||
editable?: boolean;
|
||||
docRef?: firebase.firestore.DocumentReference;
|
||||
}
|
||||
|
||||
export default function FileUploader({
|
||||
control,
|
||||
name,
|
||||
...props
|
||||
}: IFileUploaderProps) {
|
||||
export default function FileUploader({ control, name, ...props }: IFieldProps) {
|
||||
return (
|
||||
<Controller
|
||||
control={control}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React, { useCallback, useState } from "react";
|
||||
import clsx from "clsx";
|
||||
import { Controller, Control } from "react-hook-form";
|
||||
import { Controller } from "react-hook-form";
|
||||
import { IFieldProps } from "../utils";
|
||||
|
||||
import { useDropzone } from "react-dropzone";
|
||||
import useUploader from "hooks/useFiretable/useUploader";
|
||||
@@ -20,7 +21,6 @@ import AddIcon from "@material-ui/icons/AddAPhoto";
|
||||
import DeleteIcon from "@material-ui/icons/Delete";
|
||||
import OpenIcon from "@material-ui/icons/OpenInNewOutlined";
|
||||
|
||||
import ErrorMessage from "../ErrorMessage";
|
||||
import Confirmation from "components/Confirmation";
|
||||
import { IMAGE_MIME_TYPES } from "constants/fields";
|
||||
|
||||
@@ -92,7 +92,7 @@ const useStyles = makeStyles(theme =>
|
||||
);
|
||||
|
||||
export interface IControlledImageUploaderProps
|
||||
extends Pick<IImageUploaderProps, "docRef" | "editable" | "name"> {
|
||||
extends Pick<IFieldProps, "docRef" | "editable" | "name"> {
|
||||
onChange: (...event: any[]) => void;
|
||||
onBlur: () => void;
|
||||
value: any;
|
||||
@@ -253,19 +253,11 @@ export function ControlledImageUploader({
|
||||
</>
|
||||
);
|
||||
}
|
||||
export interface IImageUploaderProps {
|
||||
control: Control;
|
||||
name: string;
|
||||
|
||||
docRef?: firebase.firestore.DocumentReference;
|
||||
editable?: boolean;
|
||||
}
|
||||
|
||||
export default function ImageUploader({
|
||||
control,
|
||||
name,
|
||||
...props
|
||||
}: IImageUploaderProps) {
|
||||
}: IFieldProps) {
|
||||
return (
|
||||
<Controller
|
||||
control={control}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React from "react";
|
||||
import { Control, Controller } from "react-hook-form";
|
||||
import { Controller } from "react-hook-form";
|
||||
import { IFieldProps } from "../utils";
|
||||
import ReactJson from "react-json-view";
|
||||
|
||||
import { makeStyles, createStyles, useTheme } from "@material-ui/core";
|
||||
@@ -32,12 +33,7 @@ const isValidJson = (val: any) => {
|
||||
return true;
|
||||
};
|
||||
|
||||
export interface IJsonEditorProps {
|
||||
control: Control;
|
||||
name: string;
|
||||
}
|
||||
|
||||
export default function JsonEditor({ control, name }: IJsonEditorProps) {
|
||||
export default function JsonEditor({ control, name }: IFieldProps) {
|
||||
const classes = useStyles();
|
||||
const theme = useTheme();
|
||||
|
||||
|
||||
@@ -1,25 +1,24 @@
|
||||
import React from "react";
|
||||
import { Controller, Control } from "react-hook-form";
|
||||
import { Controller } from "react-hook-form";
|
||||
import { IFieldProps } from "../utils";
|
||||
|
||||
import { useTheme, Grid } from "@material-ui/core";
|
||||
|
||||
import MultiSelect_, { MultiSelectProps } from "@antlerengineering/multiselect";
|
||||
import FormattedChip from "components/FormattedChip";
|
||||
|
||||
export type IMultiSelectProps = Omit<
|
||||
MultiSelectProps<string>,
|
||||
"multiple" | "value" | "onChange" | "options"
|
||||
> & {
|
||||
control: Control;
|
||||
name: string;
|
||||
|
||||
config?: { options: string[] };
|
||||
editable?: boolean;
|
||||
};
|
||||
export type IMultiSelectProps = IFieldProps &
|
||||
Omit<
|
||||
MultiSelectProps<string>,
|
||||
"name" | "multiple" | "value" | "onChange" | "options"
|
||||
> & {
|
||||
config?: { options: string[] };
|
||||
};
|
||||
|
||||
export default function MultiSelect({
|
||||
control,
|
||||
name,
|
||||
docRef,
|
||||
editable,
|
||||
config,
|
||||
...props
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React from "react";
|
||||
import { Controller, Control } from "react-hook-form";
|
||||
import { Controller } from "react-hook-form";
|
||||
import { IFieldProps } from "../utils";
|
||||
|
||||
import { makeStyles, createStyles, Typography } from "@material-ui/core";
|
||||
import { resultColorsScale } from "util/color";
|
||||
@@ -41,15 +42,7 @@ const useStyles = makeStyles(theme =>
|
||||
})
|
||||
);
|
||||
|
||||
export interface IPercentageProps {
|
||||
control: Control;
|
||||
name: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: Fix cell not updating properly when switching between rows
|
||||
*/
|
||||
export default function Percentage({ control, name }: IPercentageProps) {
|
||||
export default function Percentage({ control, name }: IFieldProps) {
|
||||
const classes = useStyles();
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React from "react";
|
||||
import { Controller, Control } from "react-hook-form";
|
||||
import { Controller } from "react-hook-form";
|
||||
import { IFieldProps } from "../utils";
|
||||
|
||||
import { makeStyles, createStyles, Grid } from "@material-ui/core";
|
||||
import { Rating as MuiRating } from "@material-ui/lab";
|
||||
@@ -25,13 +26,7 @@ const useStyles = makeStyles(theme =>
|
||||
})
|
||||
);
|
||||
|
||||
export interface IRatingProps {
|
||||
control: Control;
|
||||
name: string;
|
||||
editable?: boolean;
|
||||
}
|
||||
|
||||
export default function Rating({ control, name, editable }: IRatingProps) {
|
||||
export default function Rating({ control, name, editable }: IFieldProps) {
|
||||
const classes = useStyles();
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
import React from "react";
|
||||
import { Control, Controller } from "react-hook-form";
|
||||
import { Controller } from "react-hook-form";
|
||||
import { IFieldProps } from "../utils";
|
||||
|
||||
import _RichText from "components/RichText";
|
||||
|
||||
export interface IRichTextProps {
|
||||
control: Control;
|
||||
name: string;
|
||||
}
|
||||
|
||||
export default function RichText({ control, name }: IRichTextProps) {
|
||||
export default function RichText({ control, name }: IFieldProps) {
|
||||
return (
|
||||
<Controller
|
||||
control={control}
|
||||
|
||||
@@ -1,21 +1,19 @@
|
||||
import React from "react";
|
||||
import { Controller, Control } from "react-hook-form";
|
||||
import { Controller } from "react-hook-form";
|
||||
import { IFieldProps } from "../utils";
|
||||
|
||||
import { useTheme } from "@material-ui/core";
|
||||
|
||||
import MultiSelect, { MultiSelectProps } from "@antlerengineering/multiselect";
|
||||
import FormattedChip from "components/FormattedChip";
|
||||
|
||||
export type ISingleSelectProps = Omit<
|
||||
MultiSelectProps<string>,
|
||||
"multiple" | "value" | "onChange" | "options"
|
||||
> & {
|
||||
control: Control;
|
||||
name: string;
|
||||
|
||||
config?: { options: string[] };
|
||||
editable?: boolean;
|
||||
};
|
||||
export type ISingleSelectProps = IFieldProps &
|
||||
Omit<
|
||||
MultiSelectProps<string>,
|
||||
"name" | "multiple" | "value" | "onChange" | "options"
|
||||
> & {
|
||||
config?: { options: string[] };
|
||||
};
|
||||
|
||||
/**
|
||||
* Uses the MultiSelect UI, but writes values as a string,
|
||||
@@ -23,6 +21,7 @@ export type ISingleSelectProps = Omit<
|
||||
*/
|
||||
export default function SingleSelect({
|
||||
control,
|
||||
docRef,
|
||||
name,
|
||||
editable,
|
||||
config,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React from "react";
|
||||
import { Controller, Control } from "react-hook-form";
|
||||
import { Controller } from "react-hook-form";
|
||||
import { IFieldProps } from "../utils";
|
||||
|
||||
import {
|
||||
makeStyles,
|
||||
@@ -43,9 +44,7 @@ const useStyles = makeStyles(theme =>
|
||||
})
|
||||
);
|
||||
|
||||
export interface ISliderProps extends SliderProps {
|
||||
control: Control;
|
||||
name: string;
|
||||
export interface ISliderProps extends IFieldProps, Omit<SliderProps, "name"> {
|
||||
units?: string;
|
||||
minLabel?: React.ReactNode;
|
||||
maxLabel?: React.ReactNode;
|
||||
@@ -53,6 +52,7 @@ export interface ISliderProps extends SliderProps {
|
||||
|
||||
export default function Slider({
|
||||
control,
|
||||
docRef,
|
||||
name,
|
||||
units,
|
||||
minLabel,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React from "react";
|
||||
import { Control, useWatch } from "react-hook-form";
|
||||
import { Controller, useWatch } from "react-hook-form";
|
||||
import { IFieldProps } from "../utils";
|
||||
|
||||
import { Link } from "react-router-dom";
|
||||
import queryString from "query-string";
|
||||
@@ -31,10 +32,7 @@ const useStyles = makeStyles(theme =>
|
||||
})
|
||||
);
|
||||
|
||||
export interface ISubTableProps {
|
||||
control: Control;
|
||||
name: string;
|
||||
docRef: firebase.firestore.DocumentReference;
|
||||
export interface ISubTableProps extends IFieldProps {
|
||||
config: { parentLabel?: string[] };
|
||||
label: string;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React from "react";
|
||||
import { Controller, Control } from "react-hook-form";
|
||||
import { Controller } from "react-hook-form";
|
||||
import { IFieldProps } from "../utils";
|
||||
|
||||
import {
|
||||
makeStyles,
|
||||
@@ -14,13 +15,6 @@ const useStyles = makeStyles(theme =>
|
||||
})
|
||||
);
|
||||
|
||||
export interface IFieldProps {
|
||||
control: Control;
|
||||
name: string;
|
||||
docRef: firebase.firestore.DocumentReference;
|
||||
editable?: boolean;
|
||||
}
|
||||
|
||||
export interface ITextProps
|
||||
extends IFieldProps,
|
||||
Omit<FilledTextFieldProps, "variant" | "name"> {
|
||||
@@ -60,7 +54,7 @@ export default function Text({
|
||||
break;
|
||||
|
||||
case "number":
|
||||
variantProps = { inputmode: "numeric", pattern: "[0-9]*" };
|
||||
variantProps = { inputMode: "numeric", pattern: "[0-9]*" };
|
||||
break;
|
||||
|
||||
case "short":
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React from "react";
|
||||
import { Controller, Control } from "react-hook-form";
|
||||
import { Controller } from "react-hook-form";
|
||||
import { IFieldProps } from "../utils";
|
||||
|
||||
import {
|
||||
Grid,
|
||||
@@ -9,12 +10,11 @@ import {
|
||||
} from "@material-ui/core";
|
||||
import LaunchIcon from "@material-ui/icons/Launch";
|
||||
|
||||
export interface IUrlProps extends Omit<FilledTextFieldProps, "variant"> {
|
||||
control: Control;
|
||||
name: string;
|
||||
}
|
||||
export interface IUrlProps
|
||||
extends IFieldProps,
|
||||
Omit<FilledTextFieldProps, "name" | "variant"> {}
|
||||
|
||||
export default function Url({ control, name, ...props }: IUrlProps) {
|
||||
export default function Url({ control, name, docRef, ...props }: IUrlProps) {
|
||||
return (
|
||||
<Grid container wrap="nowrap">
|
||||
<Controller
|
||||
|
||||
@@ -2,17 +2,14 @@ import React, { lazy } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import _isFunction from "lodash/isFunction";
|
||||
import _isEmpty from "lodash/isEmpty";
|
||||
|
||||
// import { useFiretableContext } from "contexts/firetableContext";
|
||||
|
||||
import { Grid } from "@material-ui/core";
|
||||
|
||||
import { Fields, Values, getInitialValues, Field } from "./utils";
|
||||
import { FieldType } from "constants/fields";
|
||||
import Autosave from "./Autosave";
|
||||
import FieldWrapper from "./FieldWrapper";
|
||||
|
||||
import Text from "./Fields/Text";
|
||||
|
||||
import { FieldType } from "constants/fields";
|
||||
|
||||
const Url = lazy(() =>
|
||||
import("./Fields/Url" /* webpackChunkName: "SideDrawer-Url" */)
|
||||
);
|
||||
@@ -80,60 +77,6 @@ const Action = lazy(() =>
|
||||
import("./Fields/Action" /* webpackChunkName: "SideDrawer-Action" */)
|
||||
);
|
||||
|
||||
export type Values = { [key: string]: any };
|
||||
export type Field = {
|
||||
type?: FieldType;
|
||||
name: string;
|
||||
label?: string;
|
||||
[key: string]: any;
|
||||
};
|
||||
export type Fields = (Field | ((values: Values) => Field))[];
|
||||
|
||||
const initializeValue = type => {
|
||||
switch (type) {
|
||||
case FieldType.singleSelect:
|
||||
case FieldType.multiSelect:
|
||||
case FieldType.image:
|
||||
case FieldType.file:
|
||||
return [];
|
||||
case FieldType.date:
|
||||
case FieldType.dateTime:
|
||||
return null;
|
||||
|
||||
case FieldType.checkbox:
|
||||
return false;
|
||||
|
||||
case FieldType.number:
|
||||
return 0;
|
||||
|
||||
case FieldType.json:
|
||||
return {};
|
||||
|
||||
case FieldType.shortText:
|
||||
case FieldType.longText:
|
||||
case FieldType.email:
|
||||
case FieldType.phone:
|
||||
case FieldType.url:
|
||||
case FieldType.code:
|
||||
case FieldType.richText:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
const getInitialValues = (fields: Fields): Values =>
|
||||
fields.reduce((acc, _field) => {
|
||||
const field = _isFunction(_field) ? _field({}) : _field;
|
||||
if (!field.name) return acc;
|
||||
let _type = field.type;
|
||||
if (field.config && field.config.renderFieldType) {
|
||||
_type = field.config.renderFieldType;
|
||||
}
|
||||
const value = initializeValue(_type);
|
||||
|
||||
return { ...acc, [field.name]: value };
|
||||
}, {});
|
||||
|
||||
export interface IFormProps {
|
||||
fields: Fields;
|
||||
values: Values;
|
||||
@@ -188,7 +131,7 @@ export default function Form({ fields, values }: IFormProps) {
|
||||
_type = field.config.renderFieldType;
|
||||
}
|
||||
|
||||
let renderedField: React.ReactNode = null;
|
||||
let fieldComponent: React.ComponentType<any> | null = null;
|
||||
|
||||
switch (_type) {
|
||||
case FieldType.shortText:
|
||||
@@ -196,111 +139,79 @@ export default function Form({ fields, values }: IFormProps) {
|
||||
case FieldType.email:
|
||||
case FieldType.phone:
|
||||
case FieldType.number:
|
||||
renderedField = (
|
||||
<Text {...fieldProps} control={control} docRef={docRef} />
|
||||
);
|
||||
fieldComponent = Text;
|
||||
break;
|
||||
|
||||
case FieldType.url:
|
||||
renderedField = <Url {...fieldProps} control={control} />;
|
||||
fieldComponent = Url;
|
||||
break;
|
||||
|
||||
case FieldType.singleSelect:
|
||||
renderedField = (
|
||||
<SingleSelect {...fieldProps} control={control} />
|
||||
);
|
||||
fieldComponent = SingleSelect;
|
||||
break;
|
||||
|
||||
case FieldType.multiSelect:
|
||||
renderedField = <MultiSelect {...fieldProps} control={control} />;
|
||||
fieldComponent = MultiSelect;
|
||||
break;
|
||||
|
||||
case FieldType.date:
|
||||
renderedField = <DatePicker {...fieldProps} control={control} />;
|
||||
fieldComponent = DatePicker;
|
||||
break;
|
||||
|
||||
case FieldType.dateTime:
|
||||
renderedField = (
|
||||
<DateTimePicker {...fieldProps} control={control} />
|
||||
);
|
||||
fieldComponent = DateTimePicker;
|
||||
break;
|
||||
|
||||
case FieldType.checkbox:
|
||||
renderedField = <Checkbox {...fieldProps} control={control} />;
|
||||
fieldComponent = Checkbox;
|
||||
break;
|
||||
|
||||
case FieldType.color:
|
||||
renderedField = <Color {...fieldProps} control={control} />;
|
||||
fieldComponent = Color;
|
||||
break;
|
||||
|
||||
case FieldType.slider:
|
||||
renderedField = <Slider {...fieldProps} control={control} />;
|
||||
fieldComponent = Slider;
|
||||
break;
|
||||
|
||||
case FieldType.richText:
|
||||
renderedField = <RichText {...fieldProps} control={control} />;
|
||||
fieldComponent = RichText;
|
||||
break;
|
||||
|
||||
case FieldType.image:
|
||||
renderedField = (
|
||||
<ImageUploader
|
||||
{...fieldProps}
|
||||
control={control}
|
||||
docRef={values.ref}
|
||||
/>
|
||||
);
|
||||
fieldComponent = ImageUploader;
|
||||
break;
|
||||
|
||||
case FieldType.file:
|
||||
renderedField = (
|
||||
<FileUploader
|
||||
{...fieldProps}
|
||||
control={control}
|
||||
docRef={values.ref}
|
||||
/>
|
||||
);
|
||||
fieldComponent = FileUploader;
|
||||
break;
|
||||
|
||||
case FieldType.rating:
|
||||
renderedField = <Rating {...fieldProps} control={control} />;
|
||||
fieldComponent = Rating;
|
||||
break;
|
||||
|
||||
case FieldType.percentage:
|
||||
renderedField = <Percentage {...fieldProps} control={control} />;
|
||||
fieldComponent = Percentage;
|
||||
break;
|
||||
|
||||
case FieldType.connectTable:
|
||||
renderedField = (
|
||||
<ConnectTable {...fieldProps} control={control} />
|
||||
);
|
||||
fieldComponent = ConnectTable;
|
||||
break;
|
||||
|
||||
case FieldType.subTable:
|
||||
renderedField = (
|
||||
<SubTable
|
||||
{...(fieldProps as any)}
|
||||
control={control}
|
||||
docRef={docRef}
|
||||
/>
|
||||
);
|
||||
fieldComponent = SubTable;
|
||||
break;
|
||||
|
||||
case FieldType.action:
|
||||
renderedField = (
|
||||
<Action
|
||||
{...(fieldProps as any)}
|
||||
control={control}
|
||||
docRef={docRef}
|
||||
/>
|
||||
);
|
||||
fieldComponent = Action;
|
||||
break;
|
||||
|
||||
case FieldType.json:
|
||||
renderedField = <JsonEditor {...fieldProps} control={control} />;
|
||||
fieldComponent = JsonEditor;
|
||||
break;
|
||||
|
||||
case FieldType.code:
|
||||
renderedField = <Code {...fieldProps} control={control} />;
|
||||
fieldComponent = Code;
|
||||
break;
|
||||
|
||||
case undefined:
|
||||
@@ -311,6 +222,12 @@ export default function Form({ fields, values }: IFormProps) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Should not reach this state
|
||||
if (fieldComponent === null) {
|
||||
console.error("`fieldComponent` is null");
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<FieldWrapper
|
||||
key={fieldProps.name ?? i}
|
||||
@@ -318,7 +235,11 @@ export default function Form({ fields, values }: IFormProps) {
|
||||
name={field.name}
|
||||
label={field.label}
|
||||
>
|
||||
{renderedField}
|
||||
{React.createElement(fieldComponent, {
|
||||
...fieldProps,
|
||||
control,
|
||||
docRef,
|
||||
})}
|
||||
</FieldWrapper>
|
||||
);
|
||||
})}
|
||||
|
||||
65
www/src/components/SideDrawer/Form/utils.ts
Normal file
65
www/src/components/SideDrawer/Form/utils.ts
Normal file
@@ -0,0 +1,65 @@
|
||||
import { Control } from "react-hook-form";
|
||||
import _isFunction from "lodash/isFunction";
|
||||
|
||||
import { FieldType } from "constants/fields";
|
||||
|
||||
export interface IFieldProps {
|
||||
control: Control;
|
||||
name: string;
|
||||
docRef: firebase.firestore.DocumentReference;
|
||||
editable?: boolean;
|
||||
}
|
||||
|
||||
export type Values = { [key: string]: any };
|
||||
export type Field = {
|
||||
type?: FieldType;
|
||||
name: string;
|
||||
label?: string;
|
||||
[key: string]: any;
|
||||
};
|
||||
export type Fields = (Field | ((values: Values) => Field))[];
|
||||
|
||||
export const initializeValue = type => {
|
||||
switch (type) {
|
||||
case FieldType.singleSelect:
|
||||
case FieldType.multiSelect:
|
||||
case FieldType.image:
|
||||
case FieldType.file:
|
||||
return [];
|
||||
case FieldType.date:
|
||||
case FieldType.dateTime:
|
||||
return null;
|
||||
|
||||
case FieldType.checkbox:
|
||||
return false;
|
||||
|
||||
case FieldType.number:
|
||||
return 0;
|
||||
|
||||
case FieldType.json:
|
||||
return {};
|
||||
|
||||
case FieldType.shortText:
|
||||
case FieldType.longText:
|
||||
case FieldType.email:
|
||||
case FieldType.phone:
|
||||
case FieldType.url:
|
||||
case FieldType.code:
|
||||
case FieldType.richText:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
export const getInitialValues = (fields: Fields): Values =>
|
||||
fields.reduce((acc, _field) => {
|
||||
const field = _isFunction(_field) ? _field({}) : _field;
|
||||
if (!field.name) return acc;
|
||||
let _type = field.type;
|
||||
if (field.config && field.config.renderFieldType) {
|
||||
_type = field.config.renderFieldType;
|
||||
}
|
||||
const value = initializeValue(_type);
|
||||
|
||||
return { ...acc, [field.name]: value };
|
||||
}, {});
|
||||
@@ -8,7 +8,8 @@ import ChevronIcon from "@material-ui/icons/KeyboardArrowLeft";
|
||||
import ChevronUpIcon from "@material-ui/icons/KeyboardArrowUp";
|
||||
import ChevronDownIcon from "@material-ui/icons/KeyboardArrowDown";
|
||||
|
||||
import Form, { Field } from "./Form";
|
||||
import Form from "./Form";
|
||||
import { Field } from "./Form/utils";
|
||||
import ErrorBoundary from "components/ErrorBoundary";
|
||||
|
||||
import { useStyles } from "./useStyles";
|
||||
|
||||
Reference in New Issue
Block a user