delete code migrated from constants/fields to components/fields

This commit is contained in:
Sidney Alcantara
2021-01-25 15:34:32 +11:00
parent acdc74c092
commit bbbc11da69
18 changed files with 59 additions and 576 deletions

View File

@@ -1,118 +0,0 @@
import React, { useState, useEffect } from "react";
import _camelCase from "lodash/camelCase";
import makeStyles from "@material-ui/core/styles/makeStyles";
import createStyles from "@material-ui/core/styles/createStyles";
import Drawer from "@material-ui/core/Drawer";
import List from "@material-ui/core/List";
import Divider from "@material-ui/core/Divider";
import ListItem from "@material-ui/core/ListItem";
import ListItemIcon from "@material-ui/core/ListItemIcon";
import ListItemText from "@material-ui/core/ListItemText";
import IconButton from "@material-ui/core/IconButton";
import TextField from "@material-ui/core/TextField";
import AddIcon from "@material-ui/icons/Add";
import { FIELDS } from "constants/fields";
const useStyles = makeStyles(() =>
createStyles({
list: {
width: 250,
},
fields: {
paddingLeft: 15,
paddingRight: 15,
},
fullList: {
width: "auto",
},
})
);
// TODO: Create an interface for props
export default function ColumnDrawer(props: any) {
const { addColumn, columns } = props;
const classes = useStyles();
const [drawerState, toggleDrawer] = useState(false);
const [columnName, setColumnName] = useState("");
const [fieldName, setFieldName] = useState("");
useEffect(() => {
setFieldName(_camelCase(columnName));
}, [columnName]);
const drawer = () => (
<div
className={classes.list}
role="presentation"
onClick={() => {
// toggleDrawer(false);
}}
>
<List className={classes.fields}>
<TextField
autoFocus
onChange={(e) => {
setColumnName(e.target.value);
}}
margin="dense"
id="name"
label="Column Name"
type="text"
fullWidth
/>
<TextField
value={fieldName}
onChange={(e) => {
setFieldName(e.target.value);
}}
margin="dense"
id="field"
label="Field Name"
type="text"
fullWidth
/>
</List>
<Divider />
<List>
{FIELDS.map((field: any) => (
<ListItem
button
onClick={() => {
addColumn(columnName, fieldName, field.type);
}}
key={field.type}
>
<ListItemIcon>{field.icon}</ListItemIcon>
<ListItemText primary={field.name} />
</ListItem>
))}
</List>
</div>
);
return (
<div>
<IconButton
aria-label="add"
onClick={() => {
toggleDrawer(true);
}}
>
<AddIcon />
</IconButton>
<Drawer
anchor="right"
open={drawerState}
onClose={() => {
toggleDrawer(false);
}}
>
{drawer()}
</Drawer>
</div>
);
}

View File

@@ -1,8 +0,0 @@
import React, { useContext } from "react";
import { IDatePicker, DATE_PICKER_EMPTY_STATE } from "./props";
const DatePickerContext = React.createContext<IDatePicker>(
DATE_PICKER_EMPTY_STATE
);
export default DatePickerContext;
export const useDatePicker = () => useContext(DatePickerContext);

View File

@@ -1,105 +0,0 @@
import React from "react";
import clsx from "clsx";
import { useDebouncedCallback } from "use-debounce";
import { makeStyles, createStyles } from "@material-ui/core";
import DateRangeIcon from "@material-ui/icons/DateRange";
import TimeIcon from "@material-ui/icons/Schedule";
import { FieldType, DateIcon, DateTimeIcon } from "constants/fields";
import { DATE_FORMAT, DATE_TIME_FORMAT } from "constants/dates";
import DateFnsUtils from "@date-io/date-fns";
import {
MuiPickersUtilsProvider,
KeyboardDatePicker,
KeyboardDateTimePicker,
DatePickerProps,
} from "@material-ui/pickers";
import { useFiretableContext } from "contexts/FiretableContext";
const useStyles = makeStyles((theme) =>
createStyles({
root: {
height: "100%",
},
inputBase: { height: "100%" },
inputAdornment: {
height: "100%",
marginLeft: theme.spacing(1) + 1,
marginRight: theme.spacing(0.25),
},
input: {
...theme.typography.body2,
fontSize: "0.75rem",
color: theme.palette.text.secondary,
height: "100%",
padding: theme.spacing(1.5, 0),
},
dateTabIcon: {
color: theme.palette.primary.contrastText,
},
})
);
export default function Date({ rowIdx, column, value, onSubmit }: any) {
const classes = useStyles();
const { dataGridRef } = useFiretableContext();
const transformedValue =
value && typeof value !== "number" && "toDate" in value
? value.toDate()
: null;
const fieldType = (column as any).type;
const Picker =
fieldType === FieldType.date ? KeyboardDatePicker : KeyboardDateTimePicker;
const Icon = fieldType === FieldType.date ? DateIcon : DateTimeIcon;
const [handleDateChange] = useDebouncedCallback<DatePickerProps["onChange"]>(
(date) => {
if (isNaN(date?.valueOf() ?? 0)) return;
onSubmit(date);
if (dataGridRef?.current?.selectCell)
dataGridRef.current.selectCell({ rowIdx, idx: column.idx });
},
500
);
return (
<MuiPickersUtilsProvider utils={DateFnsUtils}>
<Picker
value={transformedValue}
onChange={handleDateChange}
onClick={(e) => e.stopPropagation()}
format={fieldType === FieldType.date ? DATE_FORMAT : DATE_TIME_FORMAT}
fullWidth
clearable
keyboardIcon={<Icon />}
className={clsx("cell-collapse-padding", classes.root)}
inputVariant="standard"
InputProps={{
disableUnderline: true,
classes: { root: classes.inputBase, input: classes.input },
}}
InputAdornmentProps={{
position: "start",
classes: { root: classes.inputAdornment },
}}
KeyboardButtonProps={{
size: "small",
classes: { root: "row-hover-iconButton" },
}}
DialogProps={{ onClick: (e) => e.stopPropagation() }}
dateRangeIcon={<DateRangeIcon className={classes.dateTabIcon} />}
timeIcon={<TimeIcon className={classes.dateTabIcon} />}
/>
</MuiPickersUtilsProvider>
);
}

View File

@@ -1,43 +0,0 @@
import React, { useState, lazy, Suspense } from "react";
import { datePickerProps } from "./props";
const Dialog = lazy(
() => import("./Dialog" /* webpackChunkName: "DatePickerDialog" */)
);
import ConfirmationContext from "./Context";
interface IConfirmationProviderProps {
children: React.ReactNode;
}
const ConfirmationProvider: React.FC<IConfirmationProviderProps> = ({
children,
}) => {
const [state, setState] = useState<datePickerProps>();
const [open, setOpen] = useState(false);
const handleClose = () => {
setState(undefined);
setOpen(false);
};
const setDate = (props: datePickerProps) => {
setState(props);
setOpen(true);
};
return (
<ConfirmationContext.Provider
value={{
props: state,
open,
handleClose,
setDate,
}}
>
{children}
<Suspense fallback={null}>
<Dialog {...state} open={open} handleClose={handleClose} />
</Suspense>
</ConfirmationContext.Provider>
);
};
export default ConfirmationProvider;

View File

@@ -1 +0,0 @@
export { useDatePicker } from "./Context";

View File

@@ -1,24 +0,0 @@
export type datePickerProps =
| {
title?: string;
customBody?: string;
body?: string;
cancel?: string;
confirm?: string | JSX.Element;
confirmationCommand?: string;
handleConfirm: () => void;
open?: Boolean;
}
| undefined;
export interface IDatePicker {
props?: datePickerProps;
handleClose: () => void;
open: boolean;
setDate: (props: datePickerProps) => void;
}
export const DATE_PICKER_EMPTY_STATE = {
props: undefined,
open: false,
handleClose: () => {},
setDate: () => {},
};

View File

@@ -14,7 +14,8 @@ import LockIcon from "@material-ui/icons/Lock";
import ErrorBoundary from "components/ErrorBoundary";
import FieldSkeleton from "./FieldSkeleton";
import { FieldType, getFieldIcon } from "constants/fields";
import { FieldType } from "constants/fields";
import { getFieldProp } from "components/fields";
const useStyles = makeStyles((theme) =>
createStyles({
@@ -68,7 +69,7 @@ export default function FieldWrapper({
htmlFor={`sidedrawer-field-${name}`}
>
<Grid item className={classes.iconContainer}>
{type === "debug" ? <DebugIcon /> : getFieldIcon(type)}
{type === "debug" ? <DebugIcon /> : getFieldProp("icon", type)}
</Grid>
<Grid item xs>
<Typography variant="caption">{label}</Typography>

View File

@@ -24,11 +24,11 @@ import TypeChange from "./TypeChange";
import Settings from "./Settings";
import { useFiretableContext } from "contexts/FiretableContext";
import { FIELDS, FieldType } from "constants/fields";
import { FieldType } from "constants/fields";
import { getFieldProp } from "components/fields";
import _find from "lodash/find";
import { Column } from "react-data-grid";
import { PopoverProps } from "@material-ui/core";
import { getFieldProp } from "components/fields";
const INITIAL_MODAL = { type: "", data: {} };
@@ -218,7 +218,7 @@ export default function ColumnMenu() {
{
label: `Edit Type: ${getFieldProp("name", column.type)}`,
// This is based off the cell type
icon: _find(FIELDS, { type: column.type })?.icon,
icon: getFieldProp("icon", column.type),
onClick: () => {
setModal({ type: ModalStates.typeChange, data: { column } });
},

View File

@@ -10,7 +10,8 @@ import {
} from "@material-ui/core";
import { fade } from "@material-ui/core/styles";
import { FieldType, getFieldIcon } from "constants/fields";
import { FieldType } from "constants/fields";
import { getFieldProp } from "components/fields";
const useStyles = makeStyles((theme) =>
createStyles({
@@ -88,7 +89,7 @@ export default function Column({
{...props}
className={clsx(classes.root, active && classes.active, props.className)}
>
{type && <Grid item>{getFieldIcon(type)}</Grid>}
{type && <Grid item>{getFieldProp("icon", type)}</Grid>}
<Grid item xs className={classes.columnNameContainer}>
<Typography

View File

@@ -5,7 +5,7 @@ import { useDebouncedCallback } from "use-debounce";
import { makeStyles, createStyles } from "@material-ui/core";
import { DateIcon } from "constants/fields";
import { DateIcon } from ".";
import { DATE_FORMAT } from "constants/dates";
import { transformValue, sanitizeValue } from "./utils";

View File

@@ -7,7 +7,7 @@ import { makeStyles, createStyles } from "@material-ui/core";
import DateRangeIcon from "@material-ui/icons/DateRange";
import TimeIcon from "@material-ui/icons/Schedule";
import { DateTimeIcon } from "constants/fields";
import { DateTimeIcon } from ".";
import { DATE_TIME_FORMAT } from "constants/dates";
import { transformValue, sanitizeValue } from "../Date/utils";

View File

@@ -17,7 +17,7 @@ import {
CircularProgress,
} from "@material-ui/core";
import UploadIcon from "assets/icons/Upload";
import { FileIcon } from "constants/fields";
import { FileIcon } from ".";
import Confirmation from "components/Confirmation";

View File

@@ -18,7 +18,7 @@ import UploadIcon from "assets/icons/Upload";
import { useConfirmation } from "components/ConfirmationDialog";
import useUploader, { FileValue } from "hooks/useFiretable/useUploader";
import { FileIcon } from "constants/fields";
import { FileIcon } from ".";
const useStyles = makeStyles((theme) =>
createStyles({

View File

@@ -27,3 +27,5 @@ export const config: IFieldConfig = {
SideDrawerField,
};
export default config;
export { FileIcon };

View File

@@ -15,7 +15,7 @@ const SideDrawerField = lazy(
export const config: IFieldConfig = {
type: FieldType.id,
name: "Id",
name: "ID",
dataType: "undefined",
initialValue: undefined,
icon: <IdIcon />,

View File

@@ -21,7 +21,7 @@ import AddIcon from "@material-ui/icons/AddAPhoto";
import DeleteIcon from "@material-ui/icons/Delete";
import OpenIcon from "@material-ui/icons/OpenInNewOutlined";
import { IMAGE_MIME_TYPES } from "constants/fields";
import { IMAGE_MIME_TYPES } from ".";
import Thumbnail from "components/Thumbnail";
import { useConfirmation } from "components/ConfirmationDialog";

View File

@@ -0,0 +1,42 @@
// Define field type strings used in Firetable column config
export enum FieldType {
// TEXT
shortText = "SIMPLE_TEXT",
longText = "LONG_TEXT",
email = "EMAIL",
phone = "PHONE_NUMBER",
url = "URL",
// NUMERIC
checkbox = "CHECK_BOX",
number = "NUMBER",
percentage = "PERCENTAGE",
rating = "RATING",
slider = "SLIDER",
color = "COLOR",
// DATE & TIME
date = "DATE",
dateTime = "DATE_TIME",
duration = "DURATION",
// FILE
image = "IMAGE",
file = "FILE",
// SELECT
singleSelect = "SINGLE_SELECT",
multiSelect = "MULTI_SELECT",
// CONNECTION
subTable = "SUB_TABLE",
connectTable = "DOCUMENT_SELECT",
connectService = "SERVICE_SELECT",
// CODE
json = "JSON",
code = "CODE",
richText = "RICH_TEXT",
// CLOUD FUNCTION
action = "ACTION",
derivative = "DERIVATIVE",
aggregate = "AGGREGATE",
// FIRETABLE
user = "USER",
id = "ID",
last = "LAST",
}

View File

@@ -1,264 +0,0 @@
import React from "react";
import propEq from "ramda/es/propEq";
import find from "ramda/es/find";
import ShortTextIcon from "@material-ui/icons/ShortText";
import LongTextIcon from "@material-ui/icons/Notes";
import EmailIcon from "@material-ui/icons/Mail";
import PhoneIcon from "@material-ui/icons/Phone";
import CheckboxIcon from "@material-ui/icons/CheckBox";
import NumberIcon from "assets/icons/Number";
import PercentageIcon from "assets/icons/Percentage";
import DateIcon from "@material-ui/icons/Today";
import DateTimeIcon from "@material-ui/icons/AccessTime";
import DurationIcon from "@material-ui/icons/Timer";
import UrlIcon from "@material-ui/icons/Link";
import RatingIcon from "@material-ui/icons/StarBorder";
import ImageIcon from "@material-ui/icons/PhotoSizeSelectActual";
import FileIcon from "@material-ui/icons/AttachFile";
import SingleSelectIcon from "@material-ui/icons/FormatListBulleted";
import MultiSelectIcon from "assets/icons/MultiSelect";
import SubTableIcon from "assets/icons/SubTable";
import ConnectTableIcon from "assets/icons/ConnectTable";
import ConnectServiceIcon from "@material-ui/icons/Http";
import JsonIcon from "assets/icons/Json";
import CodeIcon from "@material-ui/icons/Code";
import RichTextIcon from "@material-ui/icons/TextFormat";
import ActionIcon from "assets/icons/Action";
import DerivativeIcon from "assets/icons/Derivative";
import AggregateIcon from "@material-ui/icons/Layers";
import ColorIcon from "@material-ui/icons/Colorize";
import SliderIcon from "assets/icons/Slider";
import UserIcon from "@material-ui/icons/Person";
import IdIcon from "assets/icons/Id";
export {
ShortTextIcon,
LongTextIcon,
EmailIcon,
PhoneIcon,
CheckboxIcon,
NumberIcon,
PercentageIcon,
DateIcon,
DateTimeIcon,
DurationIcon,
UrlIcon,
RatingIcon,
ImageIcon,
FileIcon,
SingleSelectIcon,
MultiSelectIcon,
SubTableIcon,
ConnectTableIcon,
ConnectServiceIcon,
JsonIcon,
CodeIcon,
RichTextIcon,
ActionIcon,
DerivativeIcon,
AggregateIcon,
ColorIcon,
SliderIcon,
UserIcon,
IdIcon,
};
// Define field type strings used in Firetable column config
export enum FieldType {
// TEXT
shortText = "SIMPLE_TEXT",
longText = "LONG_TEXT",
email = "EMAIL",
phone = "PHONE_NUMBER",
url = "URL",
// NUMERIC
checkbox = "CHECK_BOX",
number = "NUMBER",
percentage = "PERCENTAGE",
rating = "RATING",
slider = "SLIDER",
color = "COLOR",
// DATE & TIME
date = "DATE",
dateTime = "DATE_TIME",
duration = "DURATION",
// FILE
image = "IMAGE",
file = "FILE",
// SELECT
singleSelect = "SINGLE_SELECT",
multiSelect = "MULTI_SELECT",
// CONNECTION
subTable = "SUB_TABLE",
connectTable = "DOCUMENT_SELECT",
connectService = "SERVICE_SELECT",
// CODE
json = "JSON",
code = "CODE",
richText = "RICH_TEXT",
// CLOUD FUNCTION
action = "ACTION",
derivative = "DERIVATIVE",
aggregate = "AGGREGATE",
// FIRETABLE
user = "USER",
id = "ID",
last = "LAST",
}
export const FIELDS = [
{ icon: <ShortTextIcon />, name: "Short Text", type: FieldType.shortText },
{ icon: <LongTextIcon />, name: "Long Text", type: FieldType.longText },
{ icon: <EmailIcon />, name: "Email", type: FieldType.email },
{ icon: <PhoneIcon />, name: "Phone", type: FieldType.phone },
{ icon: <CheckboxIcon />, name: "Checkbox", type: FieldType.checkbox },
{ icon: <NumberIcon />, name: "Number", type: FieldType.number },
{ icon: <PercentageIcon />, name: "Percentage", type: FieldType.percentage },
{ icon: <DateIcon />, name: "Date", type: FieldType.date },
{ icon: <DateTimeIcon />, name: "Time & Date", type: FieldType.dateTime },
{ icon: <DurationIcon />, name: "Duration", type: FieldType.duration },
{ icon: <UrlIcon />, name: "URL", type: FieldType.url },
{ icon: <RatingIcon />, name: "Rating", type: FieldType.rating },
{ icon: <ImageIcon />, name: "Image", type: FieldType.image },
{ icon: <FileIcon />, name: "File", type: FieldType.file },
{
icon: <SingleSelectIcon />,
name: "Single Select",
type: FieldType.singleSelect,
},
{
icon: <MultiSelectIcon />,
name: "Multi Select",
type: FieldType.multiSelect,
},
{
icon: <SubTableIcon />,
name: "Sub-Table",
type: FieldType.subTable,
},
{
icon: <ConnectTableIcon />,
name: "Connect Table",
type: FieldType.connectTable,
},
{
icon: <ConnectServiceIcon />,
name: "Connect Service",
type: FieldType.connectService,
},
{ icon: <JsonIcon />, name: "JSON", type: FieldType.json },
{ icon: <CodeIcon />, name: "Code", type: FieldType.code },
{ icon: <RichTextIcon />, name: "Rich Text", type: FieldType.richText },
{ icon: <ActionIcon />, name: "Action", type: FieldType.action },
{ icon: <DerivativeIcon />, name: "Derivative", type: FieldType.derivative },
{ icon: <AggregateIcon />, name: "Aggregate", type: FieldType.aggregate },
{ icon: <ColorIcon />, name: "Color", type: FieldType.color },
{ icon: <SliderIcon />, name: "Slider", type: FieldType.slider },
{ icon: <UserIcon />, name: "User", type: FieldType.user },
{ icon: <IdIcon />, name: "ID", type: FieldType.id },
];
export const FIELD_TYPE_DESCRIPTIONS = {
[FieldType.shortText]: "Small amount of text, such as names and taglines.",
[FieldType.longText]:
"Large amount of text, such as sentences and paragraphs.",
[FieldType.email]: "Email address. Firetable does not validate emails.",
[FieldType.phone]:
"Phone numbers stored as text. Firetable does not validate phone numbers.",
[FieldType.checkbox]: "Either checked or unchecked. Unchecked by default.",
[FieldType.number]: "Numeric data.",
[FieldType.percentage]: "Percentage stored as a number between 0 and 1.",
[FieldType.date]:
"Date displayed and input as YYYY/MM/DD or input using a picker module.",
[FieldType.dateTime]:
"Time and Date can be written as YYYY/MM/DD hh:mm (am/pm) or input using a picker module.",
[FieldType.duration]: "Duration calculated from two timestamps.",
[FieldType.url]: "Web address. Firetable does not validate URLs.",
[FieldType.rating]:
"Rating displayed as stars from 0 to configurable number of stars. Default: 5 stars.",
[FieldType.image]:
"Image file uploaded to Firebase Storage. Supports JPEG, PNG, SVG, GIF, WebP.",
[FieldType.file]:
"File uploaded to Firebase Storage. Supports any file type.",
[FieldType.singleSelect]:
"Dropdown selector with searchable options and radio button behavior. Optionally allows users to input custom values. Max selection: 1 option.",
[FieldType.multiSelect]:
"Dropdown selector with searchable options and check box behavior. Optionally allows users to input custom values. Max selection: all options.",
[FieldType.subTable]:
"Creates a sub-table. Also displays number of rows inside the sub-table. Max sub-table levels: 100.",
[FieldType.connectTable]:
"Connects to an existing table to fetch a snapshot of values from a row. Requires Algolia integration.",
[FieldType.connectService]:
"Select a value from a list of external web service results.",
[FieldType.json]: "JSON object editable with a visual JSON editor.",
[FieldType.code]: "Raw code editable with Monaco Editor.",
[FieldType.richText]: "Rich text editor with predefined HTML text styles.",
[FieldType.action]:
"A button with a pre-defined action. Triggers a Cloud Function. 3 different states: Disabled, Enabled, Active (Clicked). Supports Undo and Redo.",
[FieldType.derivative]:
"Value derived from the rest of the rows values. Displayed using any other field type. Requires Cloud Function setup.",
[FieldType.aggregate]:
"Value aggregated from a specified sub-table of the row. Displayed using any other field type. Requires Cloud Function setup.",
[FieldType.color]: "Visual color picker. Supports Hex, RGBA, HSLA.",
[FieldType.slider]: "Slider with adjustable range. Returns a numeric value.",
[FieldType.user]: "Displays the _ft_updatedBy field for editing history.",
[FieldType.id]: "Displays the rows document ID. Cannot be sorted.",
[FieldType.last]: "Internally used to display last column with row actions.",
};
/**
* Returns icon associated with field type
* @param fieldType
*/
export const getFieldIcon = (fieldType: FieldType) => {
const field: any = find(propEq("type", fieldType))(FIELDS);
return field.icon;
};
/**
* Returns `true` if it receives an existing fieldType
* @param fieldType
*/
export const isFieldType = (fieldType: any) => {
const fieldTypes = FIELDS.map((field) => field.type);
return fieldTypes.includes(fieldType);
};
export const IMAGE_MIME_TYPES = [
"image/jpeg",
"image/png",
"image/svg+xml",
"image/gif",
"image/webp",
];