diff --git a/README.md b/README.md index 7185d3f1..e88496df 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,8 @@ Cloud. ![Commit](https://img.shields.io/github/last-commit/AntlerVC/firetable?color=%23ed4747) +[![Discord Shield](https://discordapp.com/api/guilds/746329234720686132/widget.png?style=shield)](https://discord.gg/Vdshr9E) + ### Firetable UI Supports fields such as images, files, single/multi select, in addition to diff --git a/cli/index.js b/cli/index.js index 23f8112a..85ffb452 100755 --- a/cli/index.js +++ b/cli/index.js @@ -16,7 +16,7 @@ program.version("0.4.0"); const systemHealthCheck = async () => { const versions = await terminal.getRequiredVersions(); const requiredApps = ["node", "git", "yarn", "firebase"]; - requiredApps.forEach((app) => { + requiredApps.forEach(app => { if (versions[app] === "") { throw new Error( chalk.red( diff --git a/cli/lib/terminal.js b/cli/lib/terminal.js index 1bc2a891..c0d1e7d5 100644 --- a/cli/lib/terminal.js +++ b/cli/lib/terminal.js @@ -5,7 +5,7 @@ const Spinner = CLI.Spinner; // firetable app Regex │ firetable-app.* function execute(command, callback) { - exec(command, function (error, stdout, stderr) { + exec(command, function(error, stdout, stderr) { //console.log({ error, stdout, stderr }); callback(stdout); }); @@ -17,10 +17,10 @@ module.exports.getRequiredVersions = () => "Checking the versions of required system packages, please wait..." ); checkingVersionsStatus.start(); - execute("git --version", function (git) { - execute("node --version", function (node) { - execute("yarn --version", function (yarn) { - execute("firebase --version", function (firebase) { + execute("git --version", function(git) { + execute("node --version", function(node) { + execute("yarn --version", function(yarn) { + execute("firebase --version", function(firebase) { checkingVersionsStatus.stop(); resolve({ node: node ? node.match(/[0-9]*\.[0-9]*\.[0-9]/)[0] : "", @@ -36,9 +36,9 @@ module.exports.getRequiredVersions = () => }); }); -module.exports.getGitUser = function (callback) { - execute("git config --global user.name", function (name) { - execute("git config --global user.email", function (email) { +module.exports.getGitUser = function(callback) { + execute("git config --global user.name", function(name) { + execute("git config --global user.email", function(email) { callback({ name: name.replace("\n", ""), email: email.replace("\n", ""), @@ -53,23 +53,23 @@ module.exports.cloneFiretable = () => "cloning the firetable repository, please wait..." ); cloningStatus.start(); - execute("git clone https://github.com/AntlerVC/firetable.git", function () { + execute("git clone https://github.com/AntlerVC/firetable.git", function() { cloningStatus.stop(); const installingPackagesStatus = new Spinner("installing packages"); installingPackagesStatus.start(); - execute("cd firetable/www;yarn;", function (results) { + execute("cd firetable/www;yarn;", function(results) { installingPackagesStatus.stop(); resolve(results); }); }); }); -module.exports.setFiretableENV = (envVariables) => +module.exports.setFiretableENV = envVariables => new Promise((resolve, reject) => { const status = new Spinner("setting environment variables, please wait..."); status.start(); const command = `cd firetable/www;node createDotEnv ${envVariables.projectId} ${envVariables.firebaseWebApiKey} ${envVariables.algoliaAppId} ${envVariables.algoliaSearchKey}`; - execute(command, function () { + execute(command, function() { status.stop(); resolve(true); }); @@ -85,8 +85,8 @@ module.exports.setFirebaseHostingTarget = ( status.start(); const command = `cd ${directory};echo '{}' > .firebaserc;yarn target ${hostingTarget} --project ${projectId}`; - execute(command, function () { - execute(`firebase use ${projectId}`, function () { + execute(command, function() { + execute(`firebase use ${projectId}`, function() { status.stop(); resolve(true); }); @@ -101,7 +101,7 @@ module.exports.deployToFirebaseHosting = ( const status = new Spinner("deploying to firebase hosting, please wait..."); status.start(); const command = `cd ${directory};firebase deploy --project ${projectId} --only hosting`; - execute(command, function (results) { + execute(command, function(results) { if (results.includes("Error:")) { throw new Error(results); } @@ -110,20 +110,20 @@ module.exports.deployToFirebaseHosting = ( }); }); -module.exports.startFiretableLocally = (directory) => +module.exports.startFiretableLocally = directory => new Promise((resolve, reject) => { const status = new Spinner("Starting firetable locally, please wait..."); status.start(); - execute(`cd ${directory};yarn local`, function () { + execute(`cd ${directory};yarn local`, function() { status.stop(); resolve(true); }); }); -module.exports.installFiretableAppPackages = (directory) => +module.exports.installFiretableAppPackages = directory => new Promise((resolve, reject) => { const status = new Spinner("Installing firetable app packages..."); status.start(); - execute(`cd ${directory};yarn`, function () { + execute(`cd ${directory};yarn`, function() { status.stop(); resolve(true); }); @@ -134,7 +134,7 @@ module.exports.buildFiretable = (directory = "firetable/www") => "Building firetable, this one might take a while \u{1F602}..." ); status.start(); - execute(`cd ${directory};yarn build`, function () { + execute(`cd ${directory};yarn build`, function() { status.stop(); resolve(true); }); @@ -144,7 +144,7 @@ module.exports.getFirebaseProjects = () => new Promise((resolve, reject) => { const status = new Spinner("Getting your firebase projects..."); status.start(); - execute(`firebase projects:list`, function (results) { + execute(`firebase projects:list`, function(results) { status.stop(); //console.log(results); if (results.includes("Failed to authenticate")) { @@ -155,13 +155,11 @@ module.exports.getFirebaseProjects = () => }); }); -module.exports.getExistingFiretableApp = (projectId) => +module.exports.getExistingFiretableApp = projectId => new Promise((resolve, reject) => { const status = new Spinner("Checking for existing firetable web app..."); status.start(); - execute(`firebase apps:list WEB --project ${projectId}`, function ( - results - ) { + execute(`firebase apps:list WEB --project ${projectId}`, function(results) { status.stop(); const firetableApp = results.match(/│ firetable-app.*/); if (firetableApp) { @@ -172,31 +170,31 @@ module.exports.getExistingFiretableApp = (projectId) => }); }); -module.exports.createFiretableWebApp = (projectId) => +module.exports.createFiretableWebApp = projectId => new Promise((resolve, reject) => { const status = new Spinner(`Creating a firetable web app in ${projectId}`); status.start(); execute( `firebase apps:create --project ${projectId} web firetable-app`, - function (results) { + function(results) { status.stop(); resolve(results.match(/(?<=ID: ).*/)[0]); } ); }); -module.exports.getFiretableWebAppConfig = (webAppId) => +module.exports.getFiretableWebAppConfig = webAppId => new Promise((resolve, reject) => { const status = new Spinner(`getting your web app config`); status.start(); - execute(`firebase apps:sdkconfig WEB ${webAppId}`, function (results) { + execute(`firebase apps:sdkconfig WEB ${webAppId}`, function(results) { status.stop(); const config = results.match(/{(.*)([\s\S]*)}/)[0]; resolve(config); }); }); -module.exports.createFirebaseAppConfigFile = (config) => +module.exports.createFirebaseAppConfigFile = config => new Promise((resolve, reject) => { const status = new Spinner(`creatING firebase config file.`); status.start(); @@ -205,7 +203,7 @@ module.exports.createFirebaseAppConfigFile = (config) => /\n/g, "" )}' > config.ts`, - function (results) { + function(results) { status.stop(); resolve(results); } diff --git a/cloud_functions/functions/src/compressedThumbnail/index.ts b/cloud_functions/functions/src/compressedThumbnail/index.ts index fed505fe..836abd70 100644 --- a/cloud_functions/functions/src/compressedThumbnail/index.ts +++ b/cloud_functions/functions/src/compressedThumbnail/index.ts @@ -30,7 +30,7 @@ const excludePaths = export const FT_compressedThumbnail = functions.storage .object() - .onFinalize(async (object) => { + .onFinalize(async object => { // Log file name, size, and content type for monitoring console.log(object.name, object.size, object.contentType); diff --git a/cloud_functions/functions/src/snapshotSync/index.ts b/cloud_functions/functions/src/snapshotSync/index.ts index 4dd686b3..fbae3af5 100644 --- a/cloud_functions/functions/src/snapshotSync/index.ts +++ b/cloud_functions/functions/src/snapshotSync/index.ts @@ -74,7 +74,7 @@ const syncDocSnapshot = async ( const snapshotDocPath = snapshot.ref.path; const oldSnapshot = _.find(oldSnapshotsArray, { docPath: snapshotDocPath }); - const updatedSnapshotsArray = oldSnapshotsArray.filter((item) => { + const updatedSnapshotsArray = oldSnapshotsArray.filter(item => { console.log({ snapshotDocPath, item }); return item.docPath !== snapshotDocPath; }); @@ -155,7 +155,7 @@ const syncDocOnUpdate = (config: { * returns 2 different trigger functions (onCreate,onUpdate) in an object * @param config configuration object */ -const snapshotSyncFnsGenerator = (config) => +const snapshotSyncFnsGenerator = config => Object.entries({ onUpdate: config.onUpdate ? functions.firestore diff --git a/www/package.json b/www/package.json index 9535ebdc..caef8d6b 100644 --- a/www/package.json +++ b/www/package.json @@ -3,28 +3,16 @@ "version": "0.1.0", "private": true, "dependencies": { + "@antlerengineering/components": "^0.4.1", "@antlerengineering/multiselect": "^0.3.14", "@date-io/date-fns": "1.x", - "@material-ui/core": "^4.9.13", + "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", - "@material-ui/lab": "^4.0.0-alpha.52", + "@material-ui/lab": "^4.0.0-alpha.56", "@material-ui/pickers": "^3.2.10", "@mdi/js": "^4.9.95", "@monaco-editor/react": "^3.5.5", "@tinymce/tinymce-react": "^3.4.0", - "@types/backbone": "^1.4.1", - "@types/cash": "^0.0.3", - "@types/chroma-js": "^2.0.0", - "@types/dompurify": "^2.0.1", - "@types/file-saver": "^2.0.1", - "@types/lodash": "^4.14.138", - "@types/node": "12.7.4", - "@types/ramda": "^0.26.21", - "@types/react": "^16.9.2", - "@types/react-color": "^3.0.1", - "@types/react-div-100vh": "^0.3.0", - "@types/react-dom": "16.9.0", - "@types/react-router-dom": "^4.3.5", "ace-builds": "^1.4.11", "algoliasearch": "^4.1.0", "chroma-js": "^2.1.0", @@ -33,9 +21,6 @@ "dompurify": "^2.0.8", "file-saver": "^2.0.2", "firebase": "^6.6.0", - "formik": "^2.1.4", - "formik-material-ui": "^2.0.0-beta.1", - "formik-material-ui-pickers": "^0.0.8", "grapesjs-react": "^2.0.2", "hotkeys-js": "^3.7.2", "json-format": "^1.0.1", @@ -51,6 +36,7 @@ "react-div-100vh": "^0.3.8", "react-dom": "^16.9.0", "react-dropzone": "^10.1.8", + "react-hook-form": "^6.5.0", "react-image": "^4.0.3", "react-json-view": "^1.19.1", "react-router-dom": "^5.0.1", @@ -93,7 +79,16 @@ ] }, "devDependencies": { - "@material-ui/codemod": "^4.3.0", + "@types/chroma-js": "^2.0.0", + "@types/dompurify": "^2.0.1", + "@types/file-saver": "^2.0.1", + "@types/lodash": "^4.14.138", + "@types/ramda": "^0.26.21", + "@types/react": "^16.9.2", + "@types/react-color": "^3.0.1", + "@types/react-div-100vh": "^0.3.0", + "@types/react-dom": "16.9.0", + "@types/react-router-dom": "^4.3.5", "firebase-tools": "^7.16.1", "husky": "^3.0.5", "prettier": "^1.18.2", diff --git a/www/src/components/SideDrawer/Form/Autosave.tsx b/www/src/components/SideDrawer/Form/Autosave.tsx index 49597eb1..7e32c69f 100644 --- a/www/src/components/SideDrawer/Form/Autosave.tsx +++ b/www/src/components/SideDrawer/Form/Autosave.tsx @@ -4,22 +4,30 @@ import _isEqual from "lodash/isEqual"; import _pick from "lodash/pick"; import _omitBy from "lodash/omitBy"; import _isUndefined from "lodash/isUndefined"; +import _reduce from "lodash/reduce"; -import { FormikErrors } from "formik"; -import { Values } from "."; +import { Control, useWatch } from "react-hook-form"; +import { Values } from "./utils"; import { useAppContext } from "contexts/appContext"; import { useFiretableContext, firetableUser } from "contexts/firetableContext"; export interface IAutosaveProps { - values: Values; - errors: FormikErrors; + control: Control; + defaultValues: Values; + docRef: firebase.firestore.DocumentReference; } -export default function Autosave({ values, errors }: IAutosaveProps) { +export default function Autosave({ + control, + defaultValues, + docRef, +}: IAutosaveProps) { const { currentUser } = useAppContext(); const { tableState, sideDrawerRef } = useFiretableContext(); + const values = useWatch({ control }); + const getEditables = value => _pick( value, @@ -41,21 +49,29 @@ export default function Autosave({ values, errors }: IAutosaveProps) { useEffect(() => { if (!row || !row.ref) return; - if (_isEqual(getEditables(row), debouncedValue)) return; - if (row.ref.id !== values.ref.id) return; + if (row.ref.id !== docRef.id) return; + // Get only fields that have changed and // Remove undefined value to prevent Firestore crash - const updatedValues = _omitBy(debouncedValue, _isUndefined); + const updatedValues = _omitBy( + _omitBy(debouncedValue, _isUndefined), + (value, key) => _isEqual(value, row[key]) + ); + console.log(updatedValues); + + if (Object.keys(updatedValues).length === 0) return; const _ft_updatedAt = new Date(); const _ft_updatedBy = firetableUser(currentUser); - row.ref.update({ - ...updatedValues, - _ft_updatedAt, - updatedAt: _ft_updatedAt, - _ft_updatedBy, - updatedBy: _ft_updatedBy, - }); + row.ref + .update({ + ...updatedValues, + _ft_updatedAt, + updatedAt: _ft_updatedAt, + _ft_updatedBy, + updatedBy: _ft_updatedBy, + }) + .then(() => console.log("Updated row", row.ref.id, updatedValues)); }, [debouncedValue]); return null; diff --git a/www/src/components/SideDrawer/Form/ErrorMessage.tsx b/www/src/components/SideDrawer/Form/ErrorMessage.tsx deleted file mode 100644 index 24605c1d..00000000 --- a/www/src/components/SideDrawer/Form/ErrorMessage.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import React from "react"; -import { ErrorMessage as FormikErrorMessage, ErrorMessageProps } from "formik"; - -import { makeStyles, createStyles, FormHelperText } from "@material-ui/core"; - -const useStyles = makeStyles(theme => - createStyles({ - root: { marginTop: theme.spacing(0.5) }, - }) -); - -export default function ErrorMessage(props: ErrorMessageProps) { - const classes = useStyles(); - - return ( - - {msg => ( - - {msg} - - )} - - ); -} diff --git a/www/src/components/SideDrawer/Form/FieldWrapper.tsx b/www/src/components/SideDrawer/Form/FieldWrapper.tsx index 2292b242..3e5df0a9 100644 --- a/www/src/components/SideDrawer/Form/FieldWrapper.tsx +++ b/www/src/components/SideDrawer/Form/FieldWrapper.tsx @@ -96,7 +96,7 @@ export default function FieldWrapper({ component="a" href={`https://console.firebase.google.com/project/${ process.env.REACT_APP_FIREBASE_PROJECT_ID - }/database/firestore/data~2F${(debugText as string).replace( + }/firestore/data~2F${(debugText as string).replace( /\//g, "~2F" )}`} diff --git a/www/src/components/SideDrawer/Form/Fields/Action.tsx b/www/src/components/SideDrawer/Form/Fields/Action.tsx index 537d9e5a..c5bcd570 100644 --- a/www/src/components/SideDrawer/Form/Fields/Action.tsx +++ b/www/src/components/SideDrawer/Form/Fields/Action.tsx @@ -1,5 +1,6 @@ import React, { useContext, useState } from "react"; -import { FieldProps } from "formik"; +import { Controller, useWatch } from "react-hook-form"; +import { IFieldProps } from "../utils"; import { createStyles, @@ -40,85 +41,104 @@ const useStyles = makeStyles(theme => }) ); -function Action({ - field, - form, - editable, - config, -}: FieldProps & { config: { callableName: string }; editable?: boolean }) { +export interface IActionProps extends IFieldProps { + config: { callableName: string }; +} + +function Action({ control, name, docRef, editable, config }: IActionProps) { const classes = useStyles(); - const { ref, ...docData } = form.values; + const docData = useWatch({ control }); const [isRunning, setIsRunning] = useState(false); const snack = useContext(SnackContext); - const handleRun = () => { - setIsRunning(true); - cloudFunction( - config.callableName, - { - ref: { path: ref.path, id: ref.id }, - row: sanitiseRowData(Object.assign({}, docData)), - }, - response => { - const { message, cellValue } = response.data; - setIsRunning(false); - snack.open({ message, severity: "success" }); - if (cellValue) form.setFieldValue(field.name, cellValue); - }, - error => { - console.error("ERROR", config.callableName, error); - setIsRunning(false); - snack.open({ message: JSON.stringify(error), severity: "error" }); - } - ); - }; - - const hasRan = field.value && field.value.status; const disabled = editable === false; - return ( - - - - - {hasRan && isUrl(field.value.status) ? ( - - {field.value.status} - - ) : hasRan ? ( - field.value.status - ) : ( - sanitiseCallableName(config.callableName) - )} - - - - - - {isRunning ? ( - - ) : hasRan ? ( - - ) : ( - - )} - - - + return ( + { + const handleRun = () => { + setIsRunning(true); + console.log("RUN"); + + cloudFunction( + config.callableName, + { + ref: { path: docRef.path, id: docRef.id }, + row: sanitiseRowData(Object.assign({}, docData)), + }, + response => { + const { message, cellValue } = response.data; + setIsRunning(false); + snack.open({ message, severity: "success" }); + if (cellValue) onChange(cellValue); + }, + error => { + console.error("ERROR", config.callableName, error); + setIsRunning(false); + snack.open({ message: JSON.stringify(error), severity: "error" }); + } + ); + }; + + const hasRan = value && value.status; + + return ( + + + + + {hasRan && isUrl(value.status) ? ( + + {value.status} + + ) : hasRan ? ( + value.status + ) : ( + sanitiseCallableName(config.callableName) + )} + + + + + + + {isRunning ? ( + + ) : hasRan ? ( + + ) : ( + + )} + + + + ); + }} + /> ); } diff --git a/www/src/components/SideDrawer/Form/Fields/Checkbox.tsx b/www/src/components/SideDrawer/Form/Fields/Checkbox.tsx index 3f30aa40..ffee1758 100644 --- a/www/src/components/SideDrawer/Form/Fields/Checkbox.tsx +++ b/www/src/components/SideDrawer/Form/Fields/Checkbox.tsx @@ -1,15 +1,15 @@ import React from "react"; -import { Field } from "formik"; +import { Controller } from "react-hook-form"; +import { IFieldProps } from "../utils"; import { makeStyles, createStyles, ButtonBase, FormControlLabel, + Switch, SwitchProps as MuiSwitchProps, } from "@material-ui/core"; -import { Switch } from "formik-material-ui"; -import ErrorMessage from "../ErrorMessage"; const useStyles = makeStyles(theme => createStyles({ @@ -39,33 +39,54 @@ const useStyles = makeStyles(theme => }) ); -export interface ICheckboxProps extends MuiSwitchProps { - name: string; +export interface ICheckboxProps + extends IFieldProps, + Omit { label?: React.ReactNode; + editable?: boolean; } -export default function Checkbox({ label, ...props }: ICheckboxProps) { +export default function Checkbox({ + control, + docRef, + label, + name, + editable, + ...props +}: ICheckboxProps) { const classes = useStyles(); return ( - <> - - - } - label={label} - labelPlacement="start" - classes={{ root: classes.formControlLabel, label: classes.label }} - /> - + { + const handleChange = (event: React.ChangeEvent) => { + onChange(event.target.checked); + }; - - + const handleClick = () => onChange(!value); + + return ( + + + } + label={label} + labelPlacement="start" + classes={{ root: classes.formControlLabel, label: classes.label }} + /> + + ); + }} + /> ); } diff --git a/www/src/components/SideDrawer/Form/Fields/Code.tsx b/www/src/components/SideDrawer/Form/Fields/Code.tsx index 5fa167a4..dced6179 100644 --- a/www/src/components/SideDrawer/Form/Fields/Code.tsx +++ b/www/src/components/SideDrawer/Form/Fields/Code.tsx @@ -1,12 +1,12 @@ import React, { useState, useEffect, useRef } from "react"; -import { FieldProps } from "formik"; +import { Controller } from "react-hook-form"; +import { IFieldProps } from "../utils"; import AceEditor from "react-ace"; import "ace-builds/src-noconflict/mode-javascript"; -import "ace-builds/src-noconflict/theme-monokai"; +import "ace-builds/src-noconflict/theme-github"; import { makeStyles, createStyles, Button } from "@material-ui/core"; -import ErrorMessage from "../ErrorMessage"; import CornerResizeIcon from "assets/icons/CornerResize"; const useStyles = makeStyles(theme => @@ -35,17 +35,23 @@ const useStyles = makeStyles(theme => }) ); -export default function Code({ form, field }: FieldProps) { +export interface IControlledCodeProps { + onChange: (...event: any[]) => void; + onBlur: () => void; + value: any; +} + +function ControlledCode({ onChange, onBlur, value }: IControlledCodeProps) { const classes = useStyles(); - const [localValue, setLocalValue] = useState(field.value); + const [localValue, setLocalValue] = useState(value); useEffect(() => { - if (field.value !== localValue) setLocalValue(field.value); - }, [field.value]); + if (value !== localValue) setLocalValue(value); + }, [value]); const autoSave = false; const handleChange = autoSave - ? value => form.setFieldValue(field.name, value) + ? value => onChange(value) : value => setLocalValue(value); const editor = useRef(null); @@ -58,11 +64,9 @@ export default function Code({ form, field }: FieldProps) { <>
- {!autoSave && field.value !== localValue && ( + {!autoSave && value !== localValue && ( )} - - ); } + +export default function Code({ control, docRef, name, ...props }: IFieldProps) { + return ( + } + /> + ); +} diff --git a/www/src/components/SideDrawer/Form/Fields/Color.tsx b/www/src/components/SideDrawer/Form/Fields/Color.tsx index a2b290d7..24c8bb40 100644 --- a/www/src/components/SideDrawer/Form/Fields/Color.tsx +++ b/www/src/components/SideDrawer/Form/Fields/Color.tsx @@ -1,5 +1,6 @@ import React, { useState } from "react"; -import { FieldProps } from "formik"; +import { Controller } from "react-hook-form"; +import { IFieldProps } from "../utils"; import { ChromePicker } from "react-color"; import { @@ -18,7 +19,16 @@ const useStyles = makeStyles(theme => cursor: "pointer", textAlign: "left", borderRadius: theme.shape.borderRadius, + + backgroundColor: + theme.palette.type === "light" + ? "rgba(0, 0, 0, 0.09)" + : "rgba(255, 255, 255, 0.09)", + margin: 0, + width: "100%", + padding: theme.spacing(0, 0.75), }, + colorIndicator: { width: 20, height: 20, @@ -30,51 +40,52 @@ const useStyles = makeStyles(theme => }) ); -export interface IColorProps extends FieldProps {} - -export default function Color({ field, form }: IColorProps) { +export default function Color({ control, name }: IFieldProps) { const classes = useStyles(); const [showPicker, setShowPicker] = useState(false); const toggleOpen = () => setShowPicker(s => !s); - const handleChangeComplete = color => { - form.setFieldValue(field.name, color); - }; - return ( - <> - - -
- - - - ( + <> + { + toggleOpen(); + onBlur(); + }} + component={ButtonBase} + focusRipple > - {field.value.hex ?? "Choose a color…"} - - - + +
+ - - - - + + + {value?.hex ?? "Choose a color…"} + + + + + + + + + )} + /> ); } diff --git a/www/src/components/SideDrawer/Form/Fields/ConnectTable.tsx b/www/src/components/SideDrawer/Form/Fields/ConnectTable.tsx index ee9e457a..39a848fb 100644 --- a/www/src/components/SideDrawer/Form/Fields/ConnectTable.tsx +++ b/www/src/components/SideDrawer/Form/Fields/ConnectTable.tsx @@ -1,63 +1,76 @@ import React from "react"; -import { FieldProps } from "formik"; +import { Controller } from "react-hook-form"; +import { IFieldProps } from "../utils"; import { useTheme, Grid, Chip } from "@material-ui/core"; import ConnectTableSelect, { - ConnectTableValue, IConnectTableSelectProps, } from "components/ConnectTableSelect"; +export interface IConnectTableProps + extends IFieldProps, + Partial {} + export default function ConnectTable({ - field, - form, + control, + docRef, + name, editable, ...props -}: FieldProps & IConnectTableSelectProps) { +}: IConnectTableProps) { const theme = useTheme(); - const handleDelete = (hit: any) => () => { - // if (multiple) - form.setFieldValue( - field.name, - field.value.filter(v => v.snapshot.objectID !== hit.objectID) - ); - // else form.setFieldValue(field.name, []); - }; const disabled = editable === false; - return ( - <> - {!disabled && ( - form.setFieldValue(field.name, value)} - TextFieldProps={{ - fullWidth: true, - error: !!(form.touched[field.name] && form.errors[field.name]), - helperText: - (form.touched[field.name] && form.errors[field.name]) || "", - onBlur: () => form.setFieldTouched(field.name), - }} - /> - )} - {Array.isArray(field.value) && ( - - {field.value.map(({ snapshot }) => ( - - snapshot[key]) - .join(" ")} - onDelete={disabled ? undefined : handleDelete(snapshot)} + return ( + { + const handleDelete = (hit: any) => () => { + // if (multiple) + onChange(value.filter(v => v.snapshot.objectID !== hit.objectID)); + // else form.setFieldValue(field.name, []); + }; + + return ( + <> + {!disabled && ( + - - ))} - - )} - + )} + + {Array.isArray(value) && ( + + {value.map(({ snapshot }) => ( + + snapshot[key]) + .join(" ")} + onDelete={disabled ? undefined : handleDelete(snapshot)} + /> + + ))} + + )} + + ); + }} + /> ); } diff --git a/www/src/components/SideDrawer/Form/Fields/DatePicker.tsx b/www/src/components/SideDrawer/Form/Fields/DatePicker.tsx index ab62ef27..ac9a8170 100644 --- a/www/src/components/SideDrawer/Form/Fields/DatePicker.tsx +++ b/www/src/components/SideDrawer/Form/Fields/DatePicker.tsx @@ -1,42 +1,66 @@ import React from "react"; +import { Controller } from "react-hook-form"; +import { IFieldProps } from "../utils"; import { useTheme } from "@material-ui/core"; -import { KeyboardDatePicker } from "@material-ui/pickers"; import { - fieldToKeyboardDatePicker, + KeyboardDatePicker, KeyboardDatePickerProps, -} from "formik-material-ui-pickers"; +} from "@material-ui/pickers"; import { DATE_FORMAT } from "constants/dates"; -export default function DatePicker(props: KeyboardDatePickerProps) { +import { MuiPickersUtilsProvider } from "@material-ui/pickers"; +import DateFnsUtils from "@date-io/date-fns"; + +export interface IDatePickerProps + extends IFieldProps, + Omit {} + +export default function DatePicker({ + control, + docRef, + name, + ...props +}: IDatePickerProps) { const theme = useTheme(); - let transformedValue = null; - if (props.field.value && "toDate" in props.field.value) - transformedValue = props.field.value.toDate(); - else if (props.field.value !== undefined) - transformedValue = props.field.value; - - const handleChange = (date: Date | null) => { - if (isNaN(date?.valueOf() ?? 0)) return; - props.form.setFieldValue(props.field.name, date); - }; - return ( - + + { + let transformedValue = null; + if (value && "toDate" in value) transformedValue = value.toDate(); + else if (value !== undefined) transformedValue = value; + + const handleChange = (date: Date | null) => { + if (isNaN(date?.valueOf() ?? 0)) return; + onChange(date); + }; + + return ( + + ); + }} + /> + ); } diff --git a/www/src/components/SideDrawer/Form/Fields/DateTimePicker.tsx b/www/src/components/SideDrawer/Form/Fields/DateTimePicker.tsx index e7fe1d4a..3d8247f4 100644 --- a/www/src/components/SideDrawer/Form/Fields/DateTimePicker.tsx +++ b/www/src/components/SideDrawer/Form/Fields/DateTimePicker.tsx @@ -1,45 +1,69 @@ import React from "react"; +import { Controller } from "react-hook-form"; +import { IFieldProps } from "../utils"; import { useTheme } from "@material-ui/core"; -import { KeyboardDateTimePicker } from "@material-ui/pickers"; import { - fieldToKeyboardDateTimePicker, + KeyboardDateTimePicker, KeyboardDateTimePickerProps, -} from "formik-material-ui-pickers"; +} from "@material-ui/pickers"; import { DATE_TIME_FORMAT } from "constants/dates"; import AccessTimeIcon from "@material-ui/icons/AccessTime"; -export default function DateTimePicker(props: KeyboardDateTimePickerProps) { +import { MuiPickersUtilsProvider } from "@material-ui/pickers"; +import DateFnsUtils from "@date-io/date-fns"; + +export interface IDateTimePickerProps + extends IFieldProps, + Omit {} + +export default function DateTimePicker({ + control, + docRef, + name, + ...props +}: IDateTimePickerProps) { const theme = useTheme(); - let transformedValue = null; - if (props.field.value && "toDate" in props.field.value) - transformedValue = props.field.value.toDate(); - else if (props.field.value !== undefined) - transformedValue = props.field.value; - - const handleChange = (date: Date | null) => { - if (isNaN(date?.valueOf() ?? 0)) return; - props.form.setFieldValue(props.field.name, date); - }; - return ( - } - {...fieldToKeyboardDateTimePicker(props)} - value={transformedValue} - onChange={handleChange} - label="" - hiddenLabel - id={`sidedrawer-field-${props.field.name}`} - /> + + { + let transformedValue = null; + if (value && "toDate" in value) transformedValue = value.toDate(); + else if (value !== undefined) transformedValue = value; + + const handleChange = (date: Date | null) => { + if (isNaN(date?.valueOf() ?? 0)) return; + onChange(date); + }; + + return ( + } + {...props} + value={transformedValue} + onChange={handleChange} + onBlur={onBlur} + label="" + hiddenLabel + id={`sidedrawer-field-${name}`} + /> + ); + }} + /> + ); } diff --git a/www/src/components/SideDrawer/Form/Fields/FileUploader.tsx b/www/src/components/SideDrawer/Form/Fields/FileUploader.tsx index 7eb59de4..f3581734 100644 --- a/www/src/components/SideDrawer/Form/Fields/FileUploader.tsx +++ b/www/src/components/SideDrawer/Form/Fields/FileUploader.tsx @@ -1,6 +1,7 @@ import React, { useCallback, useState } from "react"; import clsx from "clsx"; -import { FieldProps } from "formik"; +import { Controller } from "react-hook-form"; +import { IFieldProps } from "../utils"; import { useDropzone } from "react-dropzone"; import useUploader, { FileValue } from "hooks/useFiretable/useUploader"; @@ -19,7 +20,6 @@ import { import UploadIcon from "assets/icons/Upload"; import { FileIcon } from "constants/fields"; -import ErrorMessage from "../ErrorMessage"; import Confirmation from "components/Confirmation"; const useStyles = makeStyles(theme => @@ -55,17 +55,21 @@ const useStyles = makeStyles(theme => }) ); -export interface IFileUploaderProps extends FieldProps { - editable?: boolean; - docRef?: firebase.firestore.DocumentReference; +export interface IControlledFileUploaderProps + extends Pick { + onChange: (...event: any[]) => void; + onBlur: () => void; + value: any; } -export default function FileUploader({ - form, - field, +export function ControlledFileUploader({ + onChange, + onBlur, + value, + name, docRef, editable, -}: IFileUploaderProps) { +}: IControlledFileUploaderProps) { const classes = useStyles(); const { uploaderState, upload, deleteUpload } = useUploader(); @@ -81,25 +85,25 @@ export default function FileUploader({ if (docRef && file) { upload({ docRef, - fieldName: field.name, + fieldName: name, files: [file], - previousValue: field.value ?? [], + previousValue: value ?? [], onComplete: newValue => { - form.setFieldValue(field.name, newValue); + onChange(newValue); setLocalFile(""); }, }); setLocalFile(file.name); } }, - [docRef, field.value] + [docRef, value] ); const handleDelete = (index: number) => { - const newValue = [...field.value]; + const newValue = [...value]; const toBeDeleted = newValue.splice(index, 1); toBeDeleted.length && deleteUpload(toBeDeleted[0]); - form.setFieldValue(field.name, newValue); + onChange(newValue); }; const { getRootProps, getInputProps, isDragActive } = useDropzone({ @@ -117,7 +121,7 @@ export default function FileUploader({ )} {...getRootProps()} > - + Upload file @@ -126,8 +130,8 @@ export default function FileUploader({ )} - {Array.isArray(field.value) && - field.value.map((file: FileValue, i) => ( + {Array.isArray(value) && + value.map((file: FileValue, i) => ( )} - - ); } + +export default function FileUploader({ control, name, ...props }: IFieldProps) { + return ( + ( + + )} + /> + ); +} diff --git a/www/src/components/SideDrawer/Form/Fields/ImageUploader.tsx b/www/src/components/SideDrawer/Form/Fields/ImageUploader.tsx index 17972f34..0972676a 100644 --- a/www/src/components/SideDrawer/Form/Fields/ImageUploader.tsx +++ b/www/src/components/SideDrawer/Form/Fields/ImageUploader.tsx @@ -1,6 +1,7 @@ import React, { useCallback, useState } from "react"; import clsx from "clsx"; -import { FieldProps } from "formik"; +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"; import Thumbnail from "components/Thumbnail"; @@ -110,17 +110,21 @@ const useStyles = makeStyles(theme => }) ); -export interface IImageUploaderProps extends FieldProps { - docRef?: firebase.firestore.DocumentReference; - editable?: boolean; +export interface IControlledImageUploaderProps + extends Pick { + onChange: (...event: any[]) => void; + onBlur: () => void; + value: any; } -export default function ImageUploader({ - form, - field, +export function ControlledImageUploader({ + onChange, + onBlur, + value, + name, editable, docRef, -}: IImageUploaderProps) { +}: IControlledImageUploaderProps) { const disabled = editable === false; const classes = useStyles(); @@ -137,25 +141,25 @@ export default function ImageUploader({ if (docRef && imageFile) { upload({ docRef, - fieldName: field.name, + fieldName: name, files: [imageFile], - previousValue: field.value ?? [], + previousValue: value ?? [], onComplete: newValue => { - form.setFieldValue(field.name, newValue); + onChange(newValue); setLocalImage(""); }, }); setLocalImage(URL.createObjectURL(imageFile)); } }, - [docRef, field.value] + [docRef, value] ); const handleDelete = (index: number) => { - const newValue = [...field.value]; + const newValue = [...value]; const toBeDeleted = newValue.splice(index, 1); toBeDeleted.length && deleteUpload(toBeDeleted[0]); - form.setFieldValue(field.name, newValue); + onChange(newValue); }; const { getRootProps, getInputProps, isDragActive } = useDropzone({ @@ -174,7 +178,7 @@ export default function ImageUploader({ )} {...getRootProps()} > - + {isDragActive ? "Drop your image here" : "Upload image"} @@ -183,8 +187,8 @@ export default function ImageUploader({ )} - {Array.isArray(field.value) && - field.value.map((image, i) => ( + {Array.isArray(value) && + value.map((image, i) => ( {disabled ? ( @@ -271,8 +275,21 @@ export default function ImageUploader({ )} - - ); } +export default function ImageUploader({ + control, + name, + ...props +}: IFieldProps) { + return ( + ( + + )} + /> + ); +} diff --git a/www/src/components/SideDrawer/Form/Fields/JsonEditor.tsx b/www/src/components/SideDrawer/Form/Fields/JsonEditor.tsx index 2681261d..089ef355 100644 --- a/www/src/components/SideDrawer/Form/Fields/JsonEditor.tsx +++ b/www/src/components/SideDrawer/Form/Fields/JsonEditor.tsx @@ -1,5 +1,6 @@ import React from "react"; -import { FieldProps } from "formik"; +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,45 +33,54 @@ const isValidJson = (val: any) => { return true; }; -export default function JsonEditor({ form, field }: FieldProps) { +export default function JsonEditor({ control, name }: IFieldProps) { const classes = useStyles(); const theme = useTheme(); - const handleEdit = edit => { - form.setFieldValue(field.name, edit.updated_src); - }; - return ( -
- -
+ { + const handleEdit = edit => { + onChange(edit.updated_src); + }; + + return ( +
+ +
+ ); + }} + /> ); } diff --git a/www/src/components/SideDrawer/Form/Fields/MultiSelect.tsx b/www/src/components/SideDrawer/Form/Fields/MultiSelect.tsx index 45f94936..431426c5 100644 --- a/www/src/components/SideDrawer/Form/Fields/MultiSelect.tsx +++ b/www/src/components/SideDrawer/Form/Fields/MultiSelect.tsx @@ -1,67 +1,84 @@ import React from "react"; -import { FieldProps } from "formik"; +import { Controller } from "react-hook-form"; +import { IFieldProps } from "../utils"; import { useTheme, Grid } from "@material-ui/core"; -import MultiSelectA, { MultiSelectProps } from "@antlerengineering/multiselect"; +import MultiSelect_, { MultiSelectProps } from "@antlerengineering/multiselect"; import FormattedChip from "components/FormattedChip"; +export type IMultiSelectProps = IFieldProps & + Omit< + MultiSelectProps, + "name" | "multiple" | "value" | "onChange" | "options" + > & { + config?: { options: string[] }; + }; + export default function MultiSelect({ - field, - form, + control, + name, + docRef, editable, config, ...props -}: FieldProps & - MultiSelectProps & { - config: { options: string[] }; - editable?: boolean; - }) { +}: IMultiSelectProps) { const theme = useTheme(); - const handleDelete = (index: number) => () => { - const newValues = [...field.value]; - newValues.splice(index, 1); - form.setFieldValue(field.name, newValues); - }; - return ( - <> - form.setFieldValue(field.name, value)} - disabled={editable === false} - TextFieldProps={{ - label: "", - hiddenLabel: true, - error: !!(form.touched[field.name] && form.errors[field.name]), - helperText: - (form.touched[field.name] && form.errors[field.name]) || "", - onBlur: () => form.setFieldTouched(field.name), - }} - searchable - freeText={false} - /> + { + const handleDelete = (index: number) => () => { + const newValues = [...value]; + newValues.splice(index, 1); + onChange(newValues); + }; - {field.value && Array.isArray(field.value) && ( - - {field.value.map( - (item, i) => - item?.length > 0 && ( - - - - ) - )} - - )} - + return ( + <> + + + {value && Array.isArray(value) && ( + + {value.map( + (item, i) => + item?.length > 0 && ( + + + + ) + )} + + )} + + ); + }} + /> ); } diff --git a/www/src/components/SideDrawer/Form/Fields/Percentage.tsx b/www/src/components/SideDrawer/Form/Fields/Percentage.tsx index d0bca0d9..64248978 100644 --- a/www/src/components/SideDrawer/Form/Fields/Percentage.tsx +++ b/www/src/components/SideDrawer/Form/Fields/Percentage.tsx @@ -1,5 +1,6 @@ import React from "react"; -import { FieldProps } from "formik"; +import { Controller } from "react-hook-form"; +import { IFieldProps } from "../utils"; import { makeStyles, createStyles, Typography } from "@material-ui/core"; import { resultColorsScale } from "util/color"; @@ -41,27 +42,35 @@ const useStyles = makeStyles(theme => }) ); -export default function Percentage({ field }: FieldProps) { +export default function Percentage({ control, name }: IFieldProps) { const classes = useStyles(); - if (!field.value) - return ( -
-
-
- ); - return ( -
-
- - {Math.round(field.value * 100)}% - -
+ { + if (!value) + return ( +
+
+
+ ); + + return ( +
+
+ + {Math.round(value * 100)}% + +
+ ); + }} + /> ); } diff --git a/www/src/components/SideDrawer/Form/Fields/Radio.tsx b/www/src/components/SideDrawer/Form/Fields/Radio.tsx deleted file mode 100644 index fde558b5..00000000 --- a/www/src/components/SideDrawer/Form/Fields/Radio.tsx +++ /dev/null @@ -1,82 +0,0 @@ -import React from "react"; - -import { - makeStyles, - createStyles, - FormControl, - FormControlLabel, - Radio as MuiRadio, - Divider, -} from "@material-ui/core"; -import { RadioGroup, RadioGroupProps } from "formik-material-ui"; - -import Label from "../Label"; -import ErrorMessage from "../ErrorMessage"; - -const useStyles = makeStyles(theme => - createStyles({ - root: { display: "flex" }, - - formControlLabel: { - padding: theme.spacing(1.25, 0), - marginLeft: theme.spacing(1), - }, - - divider: { marginLeft: theme.spacing(5) }, - }) -); - -export interface IRadioProps extends RadioGroupProps { - options: (string | { value: string; label: React.ReactNode })[]; - label?: React.ReactNode; -} - -export default function Radio({ options, label, ...props }: IRadioProps) { - const classes = useStyles(); - - return ( - - - - - {options.map(item => { - let option: { label: React.ReactNode; value: string } = { - label: "", - value: "", - }; - if (typeof item === "object") option = item; - if (typeof item === "string") option = { label: item, value: item }; - - return ( - - - } - classes={{ label: classes.formControlLabel }} - //disabled={isSubmitting} - /> - - - ); - })} - - - - - ); -} diff --git a/www/src/components/SideDrawer/Form/Fields/Rating.tsx b/www/src/components/SideDrawer/Form/Fields/Rating.tsx index dc7a7ce7..8e3c73a3 100644 --- a/www/src/components/SideDrawer/Form/Fields/Rating.tsx +++ b/www/src/components/SideDrawer/Form/Fields/Rating.tsx @@ -1,12 +1,11 @@ import React from "react"; -import { FieldProps } from "formik"; +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"; import StarBorderIcon from "@material-ui/icons/StarBorder"; -import ErrorMessage from "../ErrorMessage"; - const useStyles = makeStyles(theme => createStyles({ root: { @@ -27,32 +26,30 @@ const useStyles = makeStyles(theme => }) ); -export interface IRatingProps extends FieldProps { - editable?: boolean; -} - -export default function Rating(props: IRatingProps) { +export default function Rating({ control, name, editable }: IFieldProps) { const classes = useStyles(); return ( - <> - - { - props.form.setFieldValue(props.field.name, newValue); - }} - emptyIcon={} - classes={{ root: classes.rating, iconEmpty: classes.iconEmpty }} - // TODO: Make this customisable in column settings - max={4} - /> - - - - + ( + + { + onChange(newValue); + }} + emptyIcon={} + classes={{ root: classes.rating, iconEmpty: classes.iconEmpty }} + // TODO: Make this customisable in column settings + max={4} + /> + + )} + /> ); } diff --git a/www/src/components/SideDrawer/Form/Fields/RichText.tsx b/www/src/components/SideDrawer/Form/Fields/RichText.tsx index ecaf2f72..7c16c1dc 100644 --- a/www/src/components/SideDrawer/Form/Fields/RichText.tsx +++ b/www/src/components/SideDrawer/Form/Fields/RichText.tsx @@ -1,16 +1,17 @@ import React from "react"; -import { FieldProps } from "formik"; +import { Controller } from "react-hook-form"; +import { IFieldProps } from "../utils"; import _RichText from "components/RichText"; -import ErrorMessage from "../ErrorMessage"; - -export default function RichText({ form, field }: FieldProps) { - const handleChange = value => form.setFieldValue(field.name, value); +export default function RichText({ control, name }: IFieldProps) { return ( - <> - <_RichText value={field.value} onChange={handleChange} /> - - + ( + <_RichText value={value} onChange={onChange} /> + )} + /> ); } diff --git a/www/src/components/SideDrawer/Form/Fields/SingleSelect.tsx b/www/src/components/SideDrawer/Form/Fields/SingleSelect.tsx index 99a459b4..4d242f94 100644 --- a/www/src/components/SideDrawer/Form/Fields/SingleSelect.tsx +++ b/www/src/components/SideDrawer/Form/Fields/SingleSelect.tsx @@ -1,56 +1,63 @@ import React from "react"; -import { FieldProps } from "formik"; +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 = IFieldProps & + Omit< + MultiSelectProps, + "name" | "multiple" | "value" | "onChange" | "options" + > & { + config?: { options: string[] }; + }; + /** * Uses the MultiSelect UI, but writes values as a string, * not an array of strings */ export default function SingleSelect({ - field, - form, + control, + docRef, + name, editable, config, ...props -}: FieldProps & - MultiSelectProps & { - config: { options: string[] }; - editable: boolean; - }) { +}: ISingleSelectProps) { const theme = useTheme(); - const handleChange = value => form.setFieldValue(field.name, value); - return ( - <> - form.setFieldTouched(field.name), - }} - searchable - freeText={false} - /> + ( + <> + - {field.value?.length > 0 && ( -
- -
+ {value?.length > 0 && ( +
+ +
+ )} + )} - + /> ); } diff --git a/www/src/components/SideDrawer/Form/Fields/Slider.tsx b/www/src/components/SideDrawer/Form/Fields/Slider.tsx index b53a47d3..ae450822 100644 --- a/www/src/components/SideDrawer/Form/Fields/Slider.tsx +++ b/www/src/components/SideDrawer/Form/Fields/Slider.tsx @@ -1,5 +1,6 @@ import React from "react"; -import { FieldProps } from "formik"; +import { Controller } from "react-hook-form"; +import { IFieldProps } from "../utils"; import { makeStyles, @@ -11,8 +12,6 @@ import { Typography, } from "@material-ui/core"; -import ErrorMessage from "../ErrorMessage"; - const useStyles = makeStyles(theme => createStyles({ root: { display: "flex" }, @@ -45,17 +44,16 @@ const useStyles = makeStyles(theme => }) ); -export interface ISliderProps extends FieldProps, SliderProps { - label: React.ReactNode; +export interface ISliderProps extends IFieldProps, Omit { units?: string; minLabel?: React.ReactNode; maxLabel?: React.ReactNode; } export default function Slider({ - field, - form, - label, + control, + docRef, + name, units, minLabel, maxLabel, @@ -65,54 +63,67 @@ export default function Slider({ }: ISliderProps) { const classes = useStyles(); - const handleClick = () => form.setFieldTouched(field.name); - const handleChange = (event: any, value: number | number[]) => { - form.setFieldValue(field.name, value); - form.setFieldTouched(field.name); - }; - - const getAriaValueText = (value: number) => - `${value}${units ? " " + units : ""}`; - - const getValueLabelFormat = (value: number) => - `${value}${units ? " " + units : ""}`; - return ( - - - - - {minLabel ?? `${min}${units ? " " + units : ""}`} - - + { + const handleChange = (_: any, value: number | number[]) => { + onChange(value); + onBlur(); + }; - - - + const getAriaValueText = (value: number) => + `${value}${units ? " " + units : ""}`; - - - {maxLabel ?? `${max}${units ? " " + units : ""}`} - - - + const getValueLabelFormat = (value: number) => + `${value}${units ? " " + units : ""}`; - - + return ( + + + + + {minLabel ?? `${min}${units ? " " + units : ""}`} + + + + + + + + + + {maxLabel ?? `${max}${units ? " " + units : ""}`} + + + + + ); + }} + /> ); } diff --git a/www/src/components/SideDrawer/Form/Fields/SubTable.tsx b/www/src/components/SideDrawer/Form/Fields/SubTable.tsx index d86b2743..d83e6591 100644 --- a/www/src/components/SideDrawer/Form/Fields/SubTable.tsx +++ b/www/src/components/SideDrawer/Form/Fields/SubTable.tsx @@ -1,5 +1,6 @@ import React from "react"; -import { FieldProps } from "formik"; +import { Controller, useWatch } from "react-hook-form"; +import { IFieldProps } from "../utils"; import { Link } from "react-router-dom"; import queryString from "query-string"; @@ -31,30 +32,38 @@ const useStyles = makeStyles(theme => }) ); +export interface ISubTableProps extends IFieldProps { + config: { parentLabel?: string[] }; + label: string; +} + export default function SubTable({ - form, - field, + control, + name, + docRef, label, config, -}: FieldProps & { config: { parentLabel?: string[] }; label: string }) { +}: ISubTableProps) { const classes = useStyles(); + const values = useWatch({ control }); + const router = useRouter(); const parentLabels = queryString.parse(router.location.search).parentLabel; const _label = config?.parentLabel ? config.parentLabel.reduce((acc, curr) => { - if (acc !== "") return `${acc} - ${form.values[curr]}`; - else return form.values[curr]; + if (acc !== "") return `${acc} - ${values[curr]}`; + else return values[curr]; }, "") : ""; let subTablePath = ""; if (parentLabels) subTablePath = - encodeURIComponent(`${form.values.ref.path}/${field.name}`) + + encodeURIComponent(`${docRef.path}/${name}`) + `?parentLabel=${parentLabels},${label}`; else subTablePath = - encodeURIComponent(`${form.values.ref.path}/${field.name}`) + + encodeURIComponent(`${docRef.path}/${name}`) + `?parentLabel=${encodeURIComponent(_label)}`; return ( diff --git a/www/src/components/SideDrawer/Form/Fields/Text.tsx b/www/src/components/SideDrawer/Form/Fields/Text.tsx index 04bf34e0..25fd4ab8 100644 --- a/www/src/components/SideDrawer/Form/Fields/Text.tsx +++ b/www/src/components/SideDrawer/Form/Fields/Text.tsx @@ -1,7 +1,13 @@ import React from "react"; +import { Controller } from "react-hook-form"; +import { IFieldProps } from "../utils"; -import { makeStyles, createStyles } from "@material-ui/core"; -import { TextField, TextFieldProps } from "formik-material-ui"; +import { + makeStyles, + createStyles, + TextField, + FilledTextFieldProps, +} from "@material-ui/core"; const useStyles = makeStyles(theme => createStyles({ @@ -9,11 +15,20 @@ const useStyles = makeStyles(theme => }) ); -export interface ITextProps extends TextFieldProps { +export interface ITextProps + extends IFieldProps, + Omit { fieldVariant?: "short" | "long" | "email" | "phone" | "number" | "url"; } -export default function Text({ fieldVariant = "short", ...props }: ITextProps) { +export default function Text({ + control, + name, + docRef, + fieldVariant = "short", + editable, + ...props +}: ITextProps) { const classes = useStyles(); let variantProps = {}; @@ -27,7 +42,10 @@ export default function Text({ fieldVariant = "short", ...props }: ITextProps) { break; case "email": - variantProps = { type: "email", inputProps: { autoComplete: "email" } }; + variantProps = { + // type: "email", + inputProps: { autoComplete: "email" }, + }; break; case "phone": @@ -36,26 +54,42 @@ export default function Text({ fieldVariant = "short", ...props }: ITextProps) { break; case "number": - variantProps = { type: "number" }; + variantProps = { inputMode: "numeric", pattern: "[0-9]*" }; break; case "short": default: break; } + return ( - { + const handleChange = e => { + if (fieldVariant === "number") onChange(parseInt(e.target.value, 10)); + else onChange(e.target.value); + }; + + return ( + + ); + }} /> ); } diff --git a/www/src/components/SideDrawer/Form/Fields/TextMulti.tsx b/www/src/components/SideDrawer/Form/Fields/TextMulti.tsx deleted file mode 100644 index a819c77d..00000000 --- a/www/src/components/SideDrawer/Form/Fields/TextMulti.tsx +++ /dev/null @@ -1,124 +0,0 @@ -import React, { useState } from "react"; -import { FieldProps } from "formik"; - -import { - makeStyles, - createStyles, - FormControl, - Grid, - TextField, - IconButton, - List, - ListItem, - ListItemText, - ListItemSecondaryAction, - Divider, -} from "@material-ui/core"; -import AddIcon from "@material-ui/icons/Add"; -import DeleteIcon from "@material-ui/icons/Cancel"; - -import Label from "../Label"; -import ErrorMessage from "../ErrorMessage"; - -const useStyles = makeStyles(theme => - createStyles({ - root: { display: "flex" }, - list: { marginBottom: theme.spacing(2) }, - }) -); - -export interface ITextMultiProps extends FieldProps { - label: React.ReactNode; - addItemLabel?: string; - addItemPlaceholder?: string; -} - -export default function TextMulti({ - form, - field, - label, - addItemLabel, - addItemPlaceholder, -}: ITextMultiProps) { - const classes = useStyles(); - const [itemToAdd, setItemToAdd] = useState(""); - - const handleAddToList = () => { - if (Array.isArray(field.value)) - form.setFieldValue(field.name, [...field.value, itemToAdd]); - else form.setFieldValue(field.name, [itemToAdd]); - setItemToAdd(""); - }; - const handleDeleteFromList = (i: number) => { - if (!Array.isArray(field.value)) form.setFieldValue(field.name, []); - const newValues = [...field.value]; - newValues.splice(i, 1); - form.setFieldValue(field.name, newValues); - }; - - return ( - - - - - {Array.isArray(field.value) && - field.value.map((item: string, i: number) => ( - - - - - { - handleDeleteFromList(i); - form.setFieldTouched(field.name); - }} - size="small" - > - - - - - - - ))} - - - - - { - handleAddToList(); - form.setFieldTouched(field.name); - }} - > - - - - - - setItemToAdd(e.target.value)} - variant="filled" - fullWidth - value={itemToAdd} - label={addItemLabel || `Add ${label}`} - placeholder={addItemPlaceholder} - onKeyPress={e => { - if (e.key === "Enter") handleAddToList(); - }} - // NOTE: Field is not automatically touched, has to be set here - onBlur={() => form.setFieldTouched(field.name)} - /> - - - - - - ); -} diff --git a/www/src/components/SideDrawer/Form/Fields/Url.tsx b/www/src/components/SideDrawer/Form/Fields/Url.tsx index 1eca7d69..ae7015f5 100644 --- a/www/src/components/SideDrawer/Form/Fields/Url.tsx +++ b/www/src/components/SideDrawer/Form/Fields/Url.tsx @@ -1,34 +1,54 @@ import React from "react"; +import { Controller } from "react-hook-form"; +import { IFieldProps } from "../utils"; -import { Grid, IconButton } from "@material-ui/core"; -import { TextField, TextFieldProps } from "formik-material-ui"; - +import { + Grid, + TextField, + FilledTextFieldProps, + IconButton, +} from "@material-ui/core"; import LaunchIcon from "@material-ui/icons/Launch"; -export default function Url(props: TextFieldProps) { +export interface IUrlProps + extends IFieldProps, + Omit {} + +export default function Url({ control, name, docRef, ...props }: IUrlProps) { return ( - ( + <> + + + + + + )} /> - - - ); } diff --git a/www/src/components/SideDrawer/Form/index.tsx b/www/src/components/SideDrawer/Form/index.tsx index b4e3e0e1..4acd8065 100644 --- a/www/src/components/SideDrawer/Form/index.tsx +++ b/www/src/components/SideDrawer/Form/index.tsx @@ -1,26 +1,18 @@ -import React, { lazy, useEffect } from "react"; -import { Formik, Form as FormikForm, Field } from "formik"; -import { MuiPickersUtilsProvider } from "@material-ui/pickers"; -import DateFnsUtils from "@date-io/date-fns"; +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" */) ); -const Percentage = lazy(() => - import("./Fields/Percentage" /* webpackChunkName: "SideDrawer-Percentage" */) -); const SingleSelect = lazy(() => import( "./Fields/SingleSelect" /* webpackChunkName: "SideDrawer-SingleSelect" */ @@ -45,6 +37,9 @@ const Checkbox = lazy(() => const Rating = lazy(() => import("./Fields/Rating" /* webpackChunkName: "SideDrawer-Rating" */) ); +const Percentage = lazy(() => + import("./Fields/Percentage" /* webpackChunkName: "SideDrawer-Percentage" */) +); const Color = lazy(() => import("./Fields/Color" /* webpackChunkName: "SideDrawer-Color" */) ); @@ -82,61 +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?: React.ReactNode; - [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 {}; - break; - - 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; @@ -144,8 +84,21 @@ export interface IFormProps { export default function Form({ fields, values }: IFormProps) { const initialValues = getInitialValues(fields); + const { ref: docRef, ...rowValues } = values; + const defaultValues = { ...initialValues, ...rowValues }; - const { sideDrawerRef } = useFiretableContext(); + const { register, control } = useForm({ + mode: "onBlur", + defaultValues, + }); + + // Update field values when Firestore document updates + // useEffect(() => { + // console.log("RESET", defaultValues); + // reset(defaultValues); + // }, [reset, JSON.stringify(rowValues)]); + + // const { sideDrawerRef } = useFiretableContext(); // useEffect(() => { // const column = sideDrawerRef?.current?.cell?.column; // if (!column) return; @@ -158,206 +111,146 @@ export default function Form({ fields, values }: IFormProps) { // }, [sideDrawerRef?.current]); return ( - - { - // Mark as submitted. We use Autosave instead. - actions.setSubmitting(false); - }} - > - {({ values, errors }) => ( - - +
+ - - {fields.map((_field, i) => { - // Call the field function with values if necessary - // Otherwise, just use the field object - const field: Field = _isFunction(_field) - ? _field(values) - : _field; - const { type, ...fieldProps } = field; - let _type = type; - if (field.config && field.config.renderFieldType) { - _type = field.config.renderFieldType; - } - // TODO: handle get initial field value for when a field is later - // shown to prevent uncontrolled components becoming controlled + + {fields.map((_field, i) => { + // Call the field function with values if necessary + // Otherwise, just use the field object + const field: Field = _isFunction(_field) ? _field(values) : _field; + const { type, ...fieldProps } = field; + let _type = type; - let renderedField: React.ReactNode = null; + // Derivative field support + if (field.config && field.config.renderFieldType) { + _type = field.config.renderFieldType; + } - switch (_type) { - case FieldType.shortText: - case FieldType.longText: - case FieldType.email: - case FieldType.phone: - case FieldType.number: - renderedField = ( - - ); - break; + let fieldComponent: React.ComponentType | null = null; - case FieldType.url: - renderedField = ( - - ); - break; + switch (_type) { + case FieldType.shortText: + case FieldType.longText: + case FieldType.email: + case FieldType.phone: + case FieldType.number: + fieldComponent = Text; + break; - case FieldType.percentage: - renderedField = ( - - ); - break; + case FieldType.url: + fieldComponent = Url; + break; - case FieldType.singleSelect: - renderedField = ( - - ); - break; + case FieldType.singleSelect: + fieldComponent = SingleSelect; + break; - case FieldType.multiSelect: - renderedField = ( - - ); - break; + case FieldType.multiSelect: + fieldComponent = MultiSelect; + break; - case FieldType.date: - renderedField = ( - - ); - break; + case FieldType.date: + fieldComponent = DatePicker; + break; - case FieldType.dateTime: - renderedField = ( - - ); - break; + case FieldType.dateTime: + fieldComponent = DateTimePicker; + break; - case FieldType.checkbox: - renderedField = ( - - ); - break; + case FieldType.checkbox: + fieldComponent = Checkbox; + break; - case FieldType.color: - renderedField = ; - break; + case FieldType.color: + fieldComponent = Color; + break; - case FieldType.slider: - renderedField = ( - - ); - break; + case FieldType.slider: + fieldComponent = Slider; + break; - case FieldType.richText: - renderedField = ( - - ); - break; + case FieldType.richText: + fieldComponent = RichText; + break; - case FieldType.image: - renderedField = ( - - ); - break; + case FieldType.image: + fieldComponent = ImageUploader; + break; - case FieldType.file: - renderedField = ( - - ); - break; + case FieldType.file: + fieldComponent = FileUploader; + break; - case FieldType.rating: - renderedField = ( - - ); - break; + case FieldType.rating: + fieldComponent = Rating; + break; - case FieldType.connectTable: - renderedField = ( - - ); - break; + case FieldType.percentage: + fieldComponent = Percentage; + break; - case FieldType.subTable: - renderedField = ( - - ); - break; + case FieldType.connectTable: + fieldComponent = ConnectTable; + break; - case FieldType.action: - renderedField = ( - - ); - break; + case FieldType.subTable: + fieldComponent = SubTable; + break; - case FieldType.json: - renderedField = ( - - ); - break; - case FieldType.code: - renderedField = ; - break; - case undefined: - return null; + case FieldType.action: + fieldComponent = Action; + break; - default: - break; - } + case FieldType.json: + fieldComponent = JsonEditor; + break; - return ( - - {renderedField} - - ); + case FieldType.code: + fieldComponent = Code; + break; + + case undefined: + // default: + return null; + + default: + break; + } + + // Should not reach this state + if (fieldComponent === null) { + console.error("`fieldComponent` is null"); + return null; + } + + return ( + + {React.createElement(fieldComponent, { + ...fieldProps, + control, + docRef, })} + + ); + })} - - - - )} - - + + + ); } diff --git a/www/src/components/SideDrawer/Form/utils.ts b/www/src/components/SideDrawer/Form/utils.ts new file mode 100644 index 00000000..66ff555c --- /dev/null +++ b/www/src/components/SideDrawer/Form/utils.ts @@ -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 }; + }, {}); diff --git a/www/src/components/SideDrawer/index.tsx b/www/src/components/SideDrawer/index.tsx index 893399e6..77fff889 100644 --- a/www/src/components/SideDrawer/index.tsx +++ b/www/src/components/SideDrawer/index.tsx @@ -2,14 +2,14 @@ import React, { useState, useEffect } from "react"; import clsx from "clsx"; import _isNil from "lodash/isNil"; import _sortBy from "lodash/sortBy"; -import _findIndex from "lodash/findIndex"; import { Drawer, Fab } from "@material-ui/core"; 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"; @@ -49,7 +49,7 @@ export default function SideDrawer() { setCell!(cell => ({ column: cell!.column, row })); - const idx = _findIndex(tableState?.columns, ["key", cell!.column]); + const idx = tableState?.columns[cell!.column]?.index; dataGridRef?.current?.selectCell({ rowIdx: row, idx }); }; @@ -116,7 +116,11 @@ export default function SideDrawer() {
{open && fields && cell && ( -
+ )}
diff --git a/www/src/components/Table/ColumnMenu/NewColumn.tsx b/www/src/components/Table/ColumnMenu/NewColumn.tsx index 45a6b297..d30dab14 100644 --- a/www/src/components/Table/ColumnMenu/NewColumn.tsx +++ b/www/src/components/Table/ColumnMenu/NewColumn.tsx @@ -63,7 +63,7 @@ export default function FormDialog({ label="Column Header" type="text" fullWidth - onChange={(e) => { + onChange={e => { setColumnLabel(e.target.value); }} /> @@ -75,7 +75,7 @@ export default function FormDialog({ label="Field Key" type="text" fullWidth - onChange={(e) => { + onChange={e => { setFieldKey(e.target.value); }} /> diff --git a/www/src/components/Table/Settings/Webhooks.tsx b/www/src/components/Table/Settings/Webhooks.tsx index 493633a4..4d9824c2 100644 --- a/www/src/components/Table/Settings/Webhooks.tsx +++ b/www/src/components/Table/Settings/Webhooks.tsx @@ -62,7 +62,7 @@ export default function WebhooksDialog({ open, handleClose }) { const fullWidth = true; const maxWidth: DialogProps["maxWidth"] = "xl"; const handleChange = (key: string) => (value: any) => { - setState((s) => ({ ...s, [key]: value })); + setState(s => ({ ...s, [key]: value })); }; const initializeWebhooksConfig = () => { const secret = makeId(32); @@ -122,7 +122,7 @@ export default function WebhooksDialog({ open, handleClose }) { labelPlacement="end" checked={state.enabled} onChange={ - (e) => { + e => { handleChange("enabled")(!state.enabled); } // handleChange("isCollectionGroup", !formState.isCollectionGroup) @@ -161,7 +161,7 @@ export default function WebhooksDialog({ open, handleClose }) { please set the question reference in typeform to the following field keys :{" "} - {tableFields.map((key) => ( + {tableFields.map(key => ( <> {" "} {key}, diff --git a/www/src/components/Table/editors/TextEditor.tsx b/www/src/components/Table/editors/TextEditor.tsx index ab414d8e..5632ef7c 100644 --- a/www/src/components/Table/editors/TextEditor.tsx +++ b/www/src/components/Table/editors/TextEditor.tsx @@ -10,7 +10,7 @@ import { import { FieldType } from "constants/fields"; -const styles = (theme) => +const styles = theme => createStyles({ root: { width: "calc(100% - 1px)", diff --git a/www/src/components/Table/formatters/index.tsx b/www/src/components/Table/formatters/index.tsx index 8c7fcc87..e19f1b07 100644 --- a/www/src/components/Table/formatters/index.tsx +++ b/www/src/components/Table/formatters/index.tsx @@ -48,9 +48,8 @@ const Percentage = lazy(() => */ export const getFormatter = (column: any) => { let _type = column.type; - if (column.config.renderFieldType) { - _type = column.config.renderFieldType; - } + if (column.config?.renderFieldType) _type = column.config.renderFieldType; + switch (_type) { case FieldType.date: case FieldType.dateTime: diff --git a/www/src/components/Table/formatters/withCustomCell.tsx b/www/src/components/Table/formatters/withCustomCell.tsx index d20dc676..fecdc4a0 100644 --- a/www/src/components/Table/formatters/withCustomCell.tsx +++ b/www/src/components/Table/formatters/withCustomCell.tsx @@ -6,7 +6,7 @@ import { makeStyles, createStyles } from "@material-ui/core"; import ErrorBoundary from "components/ErrorBoundary"; import { useFiretableContext } from "../../../contexts/firetableContext"; import _get from "lodash/get"; -const useStyles = makeStyles((theme) => +const useStyles = makeStyles(theme => createStyles({ "@global": { ".rdg-cell-mask.rdg-selected": { diff --git a/www/src/components/Table/index.tsx b/www/src/components/Table/index.tsx index 4852a82c..b38d8baf 100644 --- a/www/src/components/Table/index.tsx +++ b/www/src/components/Table/index.tsx @@ -58,7 +58,7 @@ export default function Table() { } = useFiretableContext(); const { userDoc } = useAppContext(); const userDocHiddenFields = - userDoc.state.doc?.tables[`${tableState?.tablePath}`]?.hiddenFields ?? []; + userDoc.state.doc?.tables?.[`${tableState?.tablePath}`]?.hiddenFields ?? []; const rowsContainerRef = useRef(null); // Gets more rows when scrolled down. @@ -108,7 +108,7 @@ export default function Table() { ...column, width: column.width ? (column.width > 380 ? 380 : column.width) : 150, })) - .filter((column) => !userDocHiddenFields.includes(column.key)); + .filter(column => !userDocHiddenFields.includes(column.key)); columns.push({ isNew: true, key: "new", @@ -167,7 +167,7 @@ export default function Table() { rowGetter={rowGetter} rowsCount={rows.length} rowKey={"id" as "id"} - onGridRowsUpdated={(event) => { + onGridRowsUpdated={event => { const { action, cellKey, updated } = event; if (action === "CELL_UPDATE" && updated !== null) updateCell!(rows[event.toRow].ref, cellKey as string, updated); @@ -199,7 +199,7 @@ export default function Table() { enableCellSelect onScroll={handleScroll} ref={dataGridRef} - RowsContainer={(props) => ( + RowsContainer={props => ( <>
>( ); export default firetableContext; -export const firetableUser = (currentUser) => { +export const firetableUser = currentUser => { const { displayName, email, @@ -102,10 +102,10 @@ export const FiretableContextProvider: React.FC = ({ children }) => { if (tables && userRoles && !sections) { const filteredTables = _sortBy(tables, "name") .filter( - (table) => - !table.roles || table.roles.some((role) => userRoles.includes(role)) + table => + !table.roles || table.roles.some(role => userRoles.includes(role)) ) - .map((table) => ({ + .map(table => ({ ...table, section: table.section ? table.section.toUpperCase().trim() : "OTHER", })); @@ -118,7 +118,7 @@ export const FiretableContextProvider: React.FC = ({ children }) => { useEffect(() => { if (currentUser && !userClaims) { - currentUser.getIdTokenResult(true).then((results) => { + currentUser.getIdTokenResult(true).then(results => { setUserRoles(results.claims.roles || []); setUserClaims(results.claims); }); @@ -145,10 +145,10 @@ export const FiretableContextProvider: React.FC = ({ children }) => { updatedBy: _ft_updatedBy, }) .then( - (success) => { + success => { console.log("successful update"); }, - (error) => { + error => { if (error.code === "permission-denied") { open({ message: `You don't have permissions to make this change`, diff --git a/www/src/hooks/useFiretable/useUploader.ts b/www/src/hooks/useFiretable/useUploader.ts index 9f03a410..f4aac9d4 100644 --- a/www/src/hooks/useFiretable/useUploader.ts +++ b/www/src/hooks/useFiretable/useUploader.ts @@ -112,7 +112,7 @@ const useUploader = () => { if (docRef && docRef.update) docRef.update({ [fieldName]: newValue }); // Also call callback if it exists - // IMPORTANT: Formik may not update its local values after this + // IMPORTANT: SideDrawer form may not update its local values after this // function updates the doc, so you MUST update it manually // using this callback if (onComplete) onComplete(newValue); diff --git a/www/yarn.lock b/www/yarn.lock index 972f4c08..b084f85d 100644 --- a/www/yarn.lock +++ b/www/yarn.lock @@ -106,6 +106,15 @@ "@algolia/logger-common" "4.1.0" "@algolia/requester-common" "4.1.0" +"@antlerengineering/components@^0.4.1": + version "0.4.1" + resolved "https://registry.yarnpkg.com/@antlerengineering/components/-/components-0.4.1.tgz#68955a5eebac4f3022442f6c148ed5aa0d7b6e48" + integrity sha512-7MMP75dMrfx/OrQk3lL4/3wWhYCvTeyGuhqTbohpWG7FSS513YBoh7Q7wly0XASB0Shz5gzuFrDZ5s4WfpSf9Q== + dependencies: + dompurify "^2.0.10" + lodash "^4.17.15" + lodash-es "^4.17.15" + "@antlerengineering/multiselect@^0.3.14": version "0.3.14" resolved "https://registry.yarnpkg.com/@antlerengineering/multiselect/-/multiselect-0.3.14.tgz#d24c983913ba1a2272bfe4dd5afbb081aedc95dc" @@ -148,7 +157,7 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/core@^7.1.0", "@babel/core@^7.1.6", "@babel/core@^7.4.5": +"@babel/core@^7.1.0", "@babel/core@^7.4.5": version "7.8.7" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.8.7.tgz#b69017d221ccdeb203145ae9da269d72cf102f3b" integrity sha512-rBlqF3Yko9cynC5CCFy6+K/w2N+Sq/ff2BPy+Krp7rHlABIr5epbA7OxVeKoMHB39LZOp1UY5SuLjy6uWi35yA== @@ -393,7 +402,7 @@ esutils "^2.0.2" js-tokens "^4.0.0" -"@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.1.6", "@babel/parser@^7.4.3", "@babel/parser@^7.8.4", "@babel/parser@^7.8.6", "@babel/parser@^7.8.7": +"@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.4.3", "@babel/parser@^7.8.4", "@babel/parser@^7.8.6", "@babel/parser@^7.8.7": version "7.8.8" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.8.8.tgz#4c3b7ce36db37e0629be1f0d50a571d2f86f6cd4" integrity sha512-mO5GWzBPsPf6865iIbzNE0AvkKF3NE+2S3eRUpE+FE07BOAkXh6G+GW/Pj01hhXjve1WScbaIO4UlY1JKeqCcA== @@ -407,7 +416,7 @@ "@babel/helper-remap-async-to-generator" "^7.8.3" "@babel/plugin-syntax-async-generators" "^7.8.0" -"@babel/plugin-proposal-class-properties@7.8.3", "@babel/plugin-proposal-class-properties@^7.1.0": +"@babel/plugin-proposal-class-properties@7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.8.3.tgz#5e06654af5cd04b608915aada9b2a6788004464e" integrity sha512-EqFhbo7IosdgPgZggHaNObkmO1kNUe3slaKu54d5OWvy+p9QIKOzK1GAEpAIsZtWVtPXUHSMcT4smvDrCfY4AA== @@ -456,7 +465,7 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-numeric-separator" "^7.8.3" -"@babel/plugin-proposal-object-rest-spread@^7.0.0", "@babel/plugin-proposal-object-rest-spread@^7.8.3": +"@babel/plugin-proposal-object-rest-spread@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.8.3.tgz#eb5ae366118ddca67bed583b53d7554cad9951bb" integrity sha512-8qvuPwU/xxUCt78HocNlv0mXXo0wdh9VT1R04WU8HGOfaOob26pF+9P5/lYjN/q7DHOX1bvX60hnhOvuQUJdbA== @@ -661,7 +670,7 @@ "@babel/helper-builder-binary-assignment-operator-visitor" "^7.8.3" "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-flow-strip-types@7.8.3", "@babel/plugin-transform-flow-strip-types@^7.8.3": +"@babel/plugin-transform-flow-strip-types@7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.8.3.tgz#da705a655466b2a9b36046b57bf0cbcd53551bd4" integrity sha512-g/6WTWG/xbdd2exBBzMfygjX/zw4eyNC4X8pRaq7aRHRoDUCzAIu3kGYIXviOv8BjCuWm8vDBwjHcjiRNgXrPA== @@ -954,7 +963,7 @@ levenary "^1.1.1" semver "^5.5.0" -"@babel/preset-env@^7.1.6", "@babel/preset-env@^7.4.5": +"@babel/preset-env@^7.4.5": version "7.8.7" resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.8.7.tgz#1fc7d89c7f75d2d70c2b6768de6c2e049b3cb9db" integrity sha512-BYftCVOdAYJk5ASsznKAUl53EMhfBbr8CJ1X+AJLfGPscQkwJFiaV/Wn9DPH/7fzm2v6iRYJKYHSqyynTGw0nw== @@ -1017,14 +1026,6 @@ levenary "^1.1.1" semver "^5.5.0" -"@babel/preset-flow@^7.0.0": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/preset-flow/-/preset-flow-7.8.3.tgz#52af74c6a4e80d889bd9436e8e278d0fecac6e18" - integrity sha512-iCXFk+T4demnq+dNLLvlGOgvYF6sPZ/hS1EmswugOqh1Ysp2vuiqJzpgsnp5rW8+6dLJT/0CXDzye28ZH6BAfQ== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-transform-flow-strip-types" "^7.8.3" - "@babel/preset-react@7.8.3", "@babel/preset-react@^7.0.0": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.8.3.tgz#23dc63f1b5b0751283e04252e78cf1d6589273d2" @@ -1036,7 +1037,7 @@ "@babel/plugin-transform-react-jsx-self" "^7.8.3" "@babel/plugin-transform-react-jsx-source" "^7.8.3" -"@babel/preset-typescript@7.8.3", "@babel/preset-typescript@^7.1.0": +"@babel/preset-typescript@7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.8.3.tgz#90af8690121beecd9a75d0cc26c6be39d1595d13" integrity sha512-qee5LgPGui9zQ0jR1TeU5/fP9L+ovoArklEqY12ek8P/wV5ZeM/VYSQYwICeoT6FfpJTekG9Ilay5PhwsOpMHA== @@ -1044,17 +1045,6 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-transform-typescript" "^7.8.3" -"@babel/register@^7.0.0": - version "7.8.6" - resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.8.6.tgz#a1066aa6168a73a70c35ef28cc5865ccc087ea69" - integrity sha512-7IDO93fuRsbyml7bAafBQb3RcBGlCpU4hh5wADA2LJEEcYk92WkwFZ0pHyIi2fb5Auoz1714abETdZKCOxN0CQ== - dependencies: - find-cache-dir "^2.0.0" - lodash "^4.17.13" - make-dir "^2.1.0" - pirates "^4.0.0" - source-map-support "^0.5.16" - "@babel/runtime@7.8.4": version "7.8.4" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.8.4.tgz#d79f5a2040f7caa24d53e563aad49cbc05581308" @@ -1062,7 +1052,7 @@ dependencies: regenerator-runtime "^0.13.2" -"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.3.1", "@babel/runtime@^7.3.4", "@babel/runtime@^7.4.0", "@babel/runtime@^7.4.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.0", "@babel/runtime@^7.6.2", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.1", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7": +"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.3.4", "@babel/runtime@^7.4.0", "@babel/runtime@^7.4.5", "@babel/runtime@^7.7.1", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7": version "7.8.7" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.8.7.tgz#8fefce9802db54881ba59f90bb28719b4996324d" integrity sha512-+AATMUFppJDw6aiR5NVPHqIQBlV/Pj8wY/EZH+lmvRdUo9xBaz/rF3alAwFJQavvKfeOlPE7oaaDHVbcySbCsg== @@ -1076,6 +1066,13 @@ dependencies: regenerator-runtime "^0.13.4" +"@babel/runtime@^7.3.1", "@babel/runtime@^7.4.4", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.0", "@babel/runtime@^7.8.3": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.10.5.tgz#303d8bd440ecd5a491eae6117fd3367698674c5c" + integrity sha512-otddXKhdNn7d0ptoFRHtMLa8LqDxLYwTjB4nYgM1yy5N6gU/MUf8zqyyLltCH3yAVitBzmwK4us+DD0l/MauAg== + dependencies: + regenerator-runtime "^0.13.4" + "@babel/template@^7.4.0", "@babel/template@^7.8.3", "@babel/template@^7.8.6": version "7.8.6" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.8.6.tgz#86b22af15f828dfb086474f964dcc3e39c43ce2b" @@ -1085,7 +1082,7 @@ "@babel/parser" "^7.8.6" "@babel/types" "^7.8.6" -"@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.4.3", "@babel/traverse@^7.4.5", "@babel/traverse@^7.6.2", "@babel/traverse@^7.8.3", "@babel/traverse@^7.8.4", "@babel/traverse@^7.8.6": +"@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.4.3", "@babel/traverse@^7.8.3", "@babel/traverse@^7.8.4", "@babel/traverse@^7.8.6": version "7.8.6" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.8.6.tgz#acfe0c64e1cd991b3e32eae813a6eb564954b5ff" integrity sha512-2B8l0db/DPi8iinITKuo7cbPznLCEk0kCxDoB9/N6gGNg/gxOXiR/IcymAFPiBwk5w6TtQ27w4wpElgp9btR9A== @@ -1558,14 +1555,23 @@ "@types/istanbul-reports" "^1.1.1" "@types/yargs" "^13.0.0" -"@material-ui/codemod@^4.3.0": - version "4.5.0" - resolved "https://registry.yarnpkg.com/@material-ui/codemod/-/codemod-4.5.0.tgz#e258a4865a7d68506579e046a6170fd742ffdf4f" - integrity sha512-qgx6I1T+kTL6TkbtTu+Bn4NIi5AgQ8SR8R/bXpivKPkrSADCsoanfJrS3atyCi8Sykl0DZiLdXxQOAcjP1rh4w== +"@material-ui/core@^4.11.0": + version "4.11.0" + resolved "https://registry.yarnpkg.com/@material-ui/core/-/core-4.11.0.tgz#b69b26e4553c9e53f2bfaf1053e216a0af9be15a" + integrity sha512-bYo9uIub8wGhZySHqLQ833zi4ZML+XCBE1XwJ8EuUVSpTWWG57Pm+YugQToJNFsEyiKFhPh8DPD0bgupz8n01g== dependencies: - "@babel/core" "^7.4.5" - "@babel/traverse" "^7.6.2" - jscodeshift-add-imports "^1.0.1" + "@babel/runtime" "^7.4.4" + "@material-ui/styles" "^4.10.0" + "@material-ui/system" "^4.9.14" + "@material-ui/types" "^5.1.0" + "@material-ui/utils" "^4.10.2" + "@types/react-transition-group" "^4.2.0" + clsx "^1.0.4" + hoist-non-react-statics "^3.3.2" + popper.js "1.16.1-lts" + prop-types "^15.7.2" + react-is "^16.8.0" + react-transition-group "^4.4.0" "@material-ui/core@^4.7.1": version "4.9.7" @@ -1585,25 +1591,6 @@ react-is "^16.8.0" react-transition-group "^4.3.0" -"@material-ui/core@^4.9.13": - version "4.9.13" - resolved "https://registry.yarnpkg.com/@material-ui/core/-/core-4.9.13.tgz#024962bcdda05139e1bad17a1815bf4088702b15" - integrity sha512-GEXNwUr+laZ0N+F1efmHB64Fyg+uQIRXLqbSejg3ebSXgLYNpIjnMOPRfWdu4rICq0dAIgvvNXGkKDMcf3AMpA== - dependencies: - "@babel/runtime" "^7.4.4" - "@material-ui/react-transition-group" "^4.3.0" - "@material-ui/styles" "^4.9.13" - "@material-ui/system" "^4.9.13" - "@material-ui/types" "^5.0.1" - "@material-ui/utils" "^4.9.12" - "@types/react-transition-group" "^4.2.0" - clsx "^1.0.4" - hoist-non-react-statics "^3.3.2" - popper.js "^1.16.1-lts" - prop-types "^15.7.2" - react-is "^16.8.0" - react-transition-group "^4.3.0" - "@material-ui/icons@^4.5.1", "@material-ui/icons@^4.9.1": version "4.9.1" resolved "https://registry.yarnpkg.com/@material-ui/icons/-/icons-4.9.1.tgz#fdeadf8cb3d89208945b33dbc50c7c616d0bd665" @@ -1611,13 +1598,13 @@ dependencies: "@babel/runtime" "^7.4.4" -"@material-ui/lab@^4.0.0-alpha.52": - version "4.0.0-alpha.52" - resolved "https://registry.yarnpkg.com/@material-ui/lab/-/lab-4.0.0-alpha.52.tgz#a868d8c772a90db091a6bfc89aed21a0e2c486bf" - integrity sha512-aDoRWA+q3/T2spvvQrxPz8qjtf9l8NhaG9ZISBy9zD3cJ05s3KfEP2nrsoBOBgonlSMFQQzUTnxAwThwsJfllw== +"@material-ui/lab@^4.0.0-alpha.56": + version "4.0.0-alpha.56" + resolved "https://registry.yarnpkg.com/@material-ui/lab/-/lab-4.0.0-alpha.56.tgz#ff63080949b55b40625e056bbda05e130d216d34" + integrity sha512-xPlkK+z/6y/24ka4gVJgwPfoCF4RCh8dXb1BNE7MtF9bXEBLN/lBxNTK8VAa0qm3V2oinA6xtUIdcRh0aeRtVw== dependencies: "@babel/runtime" "^7.4.4" - "@material-ui/utils" "^4.9.6" + "@material-ui/utils" "^4.10.2" clsx "^1.0.4" prop-types "^15.7.2" react-is "^16.8.0" @@ -1634,24 +1621,14 @@ react-transition-group "^4.0.0" rifm "^0.7.0" -"@material-ui/react-transition-group@^4.3.0": - version "4.3.0" - resolved "https://registry.yarnpkg.com/@material-ui/react-transition-group/-/react-transition-group-4.3.0.tgz#92529142addb5cc179dbf42d246c7e3fe4d6104b" - integrity sha512-CwQ0aXrlUynUTY6sh3UvKuvye1o92en20VGAs6TORnSxUYeRmkX8YeTUN3lAkGiBX1z222FxLFO36WWh6q73rQ== - dependencies: - "@babel/runtime" "^7.5.5" - dom-helpers "^5.0.1" - loose-envify "^1.4.0" - prop-types "^15.6.2" - -"@material-ui/styles@^4.9.13": - version "4.9.13" - resolved "https://registry.yarnpkg.com/@material-ui/styles/-/styles-4.9.13.tgz#08b3976bdd21c38bc076693d95834f97539f3b15" - integrity sha512-lWlXJanBdHQ18jW/yphedRokHcvZD1GdGzUF/wQxKDsHwDDfO45ZkAxuSBI202dG+r1Ph483Z3pFykO2obeSRA== +"@material-ui/styles@^4.10.0": + version "4.10.0" + resolved "https://registry.yarnpkg.com/@material-ui/styles/-/styles-4.10.0.tgz#2406dc23aa358217aa8cc772e6237bd7f0544071" + integrity sha512-XPwiVTpd3rlnbfrgtEJ1eJJdFCXZkHxy8TrdieaTvwxNYj42VnnCyFzxYeNW9Lhj4V1oD8YtQ6S5Gie7bZDf7Q== dependencies: "@babel/runtime" "^7.4.4" "@emotion/hash" "^0.8.0" - "@material-ui/types" "^5.0.1" + "@material-ui/types" "^5.1.0" "@material-ui/utils" "^4.9.6" clsx "^1.0.4" csstype "^2.5.2" @@ -1688,13 +1665,14 @@ jss-plugin-vendor-prefixer "^10.0.3" prop-types "^15.7.2" -"@material-ui/system@^4.9.13": - version "4.9.13" - resolved "https://registry.yarnpkg.com/@material-ui/system/-/system-4.9.13.tgz#adefb3b6a5ddf0b00fe4e82ac63bb48276e9749d" - integrity sha512-6AlpvdW6KJJ5bF1Xo2OD13sCN8k+nlL36412/bWnWZOKIfIMo/Lb8c8d1DOIaT/RKWxTEUaWnKZjabVnA3eZjA== +"@material-ui/system@^4.9.14": + version "4.9.14" + resolved "https://registry.yarnpkg.com/@material-ui/system/-/system-4.9.14.tgz#4b00c48b569340cefb2036d0596b93ac6c587a5f" + integrity sha512-oQbaqfSnNlEkXEziDcJDDIy8pbvwUmZXWNqlmIwDqr/ZdCK8FuV3f4nxikUh7hvClKV2gnQ9djh5CZFTHkZj3w== dependencies: "@babel/runtime" "^7.4.4" "@material-ui/utils" "^4.9.6" + csstype "^2.5.2" prop-types "^15.7.2" "@material-ui/system@^4.9.6": @@ -1711,24 +1689,15 @@ resolved "https://registry.yarnpkg.com/@material-ui/types/-/types-5.0.0.tgz#26d6259dc6b39f4c2e1e9aceff7a11e031941741" integrity sha512-UeH2BuKkwDndtMSS0qgx1kCzSMw+ydtj0xx/XbFtxNSTlXydKwzs5gVW5ZKsFlAkwoOOQ9TIsyoCC8hq18tOwg== -"@material-ui/types@^5.0.1": - version "5.0.1" - resolved "https://registry.yarnpkg.com/@material-ui/types/-/types-5.0.1.tgz#c4954063cdc196eb327ee62c041368b1aebb6d61" - integrity sha512-wURPSY7/3+MAtng3i26g+WKwwNE3HEeqa/trDBR5+zWKmcjO+u9t7Npu/J1r+3dmIa/OeziN9D/18IrBKvKffw== +"@material-ui/types@^5.1.0": + version "5.1.0" + resolved "https://registry.yarnpkg.com/@material-ui/types/-/types-5.1.0.tgz#efa1c7a0b0eaa4c7c87ac0390445f0f88b0d88f2" + integrity sha512-7cqRjrY50b8QzRSYyhSpx4WRw2YuO0KKIGQEVk5J8uoz2BanawykgZGoWEqKm7pVIbzFDN0SpPcVV4IhOFkl8A== -"@material-ui/utils@^4.9.12": - version "4.9.12" - resolved "https://registry.yarnpkg.com/@material-ui/utils/-/utils-4.9.12.tgz#0d639f1c1ed83fffb2ae10c21d15a938795d9e65" - integrity sha512-/0rgZPEOcZq5CFA4+4n6Q6zk7fi8skHhH2Bcra8R3epoJEYy5PL55LuMazPtPH1oKeRausDV/Omz4BbgFsn1HQ== - dependencies: - "@babel/runtime" "^7.4.4" - prop-types "^15.7.2" - react-is "^16.8.0" - -"@material-ui/utils@^4.9.6": - version "4.9.6" - resolved "https://registry.yarnpkg.com/@material-ui/utils/-/utils-4.9.6.tgz#5f1f9f6e4df9c8b6a263293b68c94834248ff157" - integrity sha512-gqlBn0JPPTUZeAktn1rgMcy9Iczrr74ecx31tyZLVGdBGGzsxzM6PP6zeS7FuoLS6vG4hoZP7hWnOoHtkR0Kvw== +"@material-ui/utils@^4.10.2", "@material-ui/utils@^4.9.6": + version "4.10.2" + resolved "https://registry.yarnpkg.com/@material-ui/utils/-/utils-4.10.2.tgz#3fd5470ca61b7341f1e0468ac8f29a70bf6df321" + integrity sha512-eg29v74P7W5r6a4tWWDAAfZldXIzfyO1am2fIsC39hdUUHm/33k6pGOKPbgDjg/U/4ifmgAePy/1OjkKN6rFRw== dependencies: "@babel/runtime" "^7.4.4" prop-types "^15.7.2" @@ -1955,14 +1924,6 @@ dependencies: "@babel/types" "^7.3.0" -"@types/backbone@^1.4.1": - version "1.4.1" - resolved "https://registry.yarnpkg.com/@types/backbone/-/backbone-1.4.1.tgz#aa03f9f69994bd96646c50cfc70b5f30d38aafaa" - integrity sha512-KYfGuQy4d2vvYXbn0uHFZ6brFLndatTMomxBlljpbWf4kFpA3BG/6LA3ec+J9iredrX6eAVI7sm9SVAvwiIM6g== - dependencies: - "@types/jquery" "*" - "@types/underscore" "*" - "@types/bytebuffer@^5.0.40": version "5.0.40" resolved "https://registry.yarnpkg.com/@types/bytebuffer/-/bytebuffer-5.0.40.tgz#d6faac40dcfb09cd856cdc4c01d3690ba536d3ee" @@ -1971,11 +1932,6 @@ "@types/long" "*" "@types/node" "*" -"@types/cash@^0.0.3": - version "0.0.3" - resolved "https://registry.yarnpkg.com/@types/cash/-/cash-0.0.3.tgz#770d6382c605bb4f8572f17cea6f40cec5832496" - integrity sha512-gS24kdFuVwfo5h7IlStnXyBSIH4e9aFIhNHb4w+o5DwbYDeQJv+i9heh7u7nSvqnOP3v34tQMTe7VoJp2US08w== - "@types/chroma-js@^2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@types/chroma-js/-/chroma-js-2.0.0.tgz#b0fc98c8625d963f14e8138e0a7961103303ab22" @@ -2056,13 +2012,6 @@ "@types/istanbul-lib-coverage" "*" "@types/istanbul-lib-report" "*" -"@types/jquery@*": - version "3.3.33" - resolved "https://registry.yarnpkg.com/@types/jquery/-/jquery-3.3.33.tgz#61d9cbd4004ffcdf6cf7e34720a87a5625a7d8e9" - integrity sha512-U6IdXYGkfUI42SR79vB2Spj+h1Ly3J3UZjpd8mi943lh126TK7CB+HZOxGh2nM3IySor7wqVQdemD/xtydsBKA== - dependencies: - "@types/sizzle" "*" - "@types/js-yaml@^3.12.2": version "3.12.3" resolved "https://registry.yarnpkg.com/@types/js-yaml/-/js-yaml-3.12.3.tgz#abf383c5b639d0aa8b8c4a420d6a85f703357d6c" @@ -2093,11 +2042,6 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-13.9.2.tgz#ace1880c03594cc3e80206d96847157d8e7fa349" integrity sha512-bnoqK579sAYrQbp73wwglccjJ4sfRdKU7WNEZ5FW4K2U6Kc0/eZ5kvXG0JKsEKFB50zrFmfFt52/cvBbZa7eXg== -"@types/node@12.7.4": - version "12.7.4" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.7.4.tgz#64db61e0359eb5a8d99b55e05c729f130a678b04" - integrity sha512-W0+n1Y+gK/8G2P/piTkBBN38Qc5Q1ZSO6B5H3QmPCUewaiXOo2GCAWZ4ElZCcNhjJuBSUSLGFUJnmlCn5+nxOQ== - "@types/node@^10.1.0": version "10.17.17" resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.17.tgz#7a183163a9e6ff720d86502db23ba4aade5999b8" @@ -2169,13 +2113,21 @@ "@types/react" "*" "@types/react-transition-group@^4.2.0": - version "4.2.4" - resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.2.4.tgz#c7416225987ccdb719262766c1483da8f826838d" - integrity sha512-8DMUaDqh0S70TjkqU0DxOu80tFUiiaS9rxkWip/nb7gtvAsbqOXm02UCmR8zdcjWujgeYPiPNTVpVpKzUDotwA== + version "4.4.0" + resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.0.tgz#882839db465df1320e4753e6e9f70ca7e9b4d46d" + integrity sha512-/QfLHGpu+2fQOqQaXh8MG9q03bFENooTb/it4jr5kKaZlDQfWvjqWZg48AwzPVMBHlRuTRAY7hRHCEOXz5kV6w== dependencies: "@types/react" "*" -"@types/react@*", "@types/react@^16.9.2": +"@types/react@*": + version "16.9.43" + resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.43.tgz#c287f23f6189666ee3bebc2eb8d0f84bcb6cdb6b" + integrity sha512-PxshAFcnJqIWYpJbLPriClH53Z2WlJcVZE+NP2etUtWQs2s7yIMj3/LDKZT/5CHJ/F62iyjVCDu2H3jHEXIxSg== + dependencies: + "@types/prop-types" "*" + csstype "^2.2.0" + +"@types/react@^16.9.2": version "16.9.23" resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.23.tgz#1a66c6d468ba11a8943ad958a8cb3e737568271c" integrity sha512-SsGVT4E7L2wLN3tPYLiF20hmZTPGuzaayVunfgXzUn1x4uHVsKH6QDJQ/TdpHqwsTLd4CwrmQ2vOgxN7gE24gw== @@ -2183,11 +2135,6 @@ "@types/prop-types" "*" csstype "^2.2.0" -"@types/sizzle@*": - version "2.3.2" - resolved "https://registry.yarnpkg.com/@types/sizzle/-/sizzle-2.3.2.tgz#a811b8c18e2babab7d542b3365887ae2e4d9de47" - integrity sha512-7EJYyKTL7tFR8+gDbB6Wwz/arpGa0Mywk1TJbNzKzHtzbwVmY4HR9WqS5VV7dsBUKQmPNr192jHr/VpBluj/hg== - "@types/stack-utils@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e" @@ -2205,11 +2152,6 @@ resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-1.0.4.tgz#922d092c84a776a59acb0bd6785fd82b59b9bad5" integrity sha512-6jtHrHpmiXOXoJ31Cg9R+iEVwuEKPf0XHwFUI93eEPXx492/J2JHyafkleKE2EYzZprayk9FSjTyK1GDqcwDng== -"@types/underscore@*": - version "1.9.4" - resolved "https://registry.yarnpkg.com/@types/underscore/-/underscore-1.9.4.tgz#22d1a3e6b494608e430221ec085fa0b7ccee7f33" - integrity sha512-CjHWEMECc2/UxOZh0kpiz3lEyX2Px3rQS9HzD20lxMvx571ivOBQKeLnqEjxUY0BMgp6WJWo/pQLRBwMW5v4WQ== - "@types/yargs-parser@*": version "15.0.0" resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-15.0.0.tgz#cb3f9f741869e20cce330ffbeb9271590483882d" @@ -2894,11 +2836,6 @@ ast-types-flow@0.0.7, ast-types-flow@^0.0.7: resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad" integrity sha1-9wtzXGvKGlycItmCw+Oef+ujva0= -ast-types@0.11.7: - version "0.11.7" - resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.11.7.tgz#f318bf44e339db6a320be0009ded64ec1471f46c" - integrity sha512-2mP3TwtkY/aTv5X3ZsMpNAbOnyoC/aMJwJSoaELPkHId0nSQgFcnU4dRW3isxiz7+zBexk0ym3WNVjMiQBnJSw== - astral-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" @@ -2996,11 +2933,6 @@ babel-code-frame@^6.22.0: esutils "^2.0.2" js-tokens "^3.0.2" -babel-core@^7.0.0-bridge.0: - version "7.0.0-bridge.0" - resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-7.0.0-bridge.0.tgz#95a492ddd90f9b4e9a4a1da14eb335b87b634ece" - integrity sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg== - babel-eslint@10.0.3: version "10.0.3" resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-10.0.3.tgz#81a2c669be0f205e19462fed2482d33e4687a88a" @@ -3970,9 +3902,9 @@ clone@^1.0.2: integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4= clsx@^1.0.2, clsx@^1.0.4: - version "1.1.0" - resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.1.0.tgz#62937c6adfea771247c34b54d320fb99624f5702" - integrity sha512-3avwM37fSK5oP6M5rQ9CNe99lwxhXDOeSWVPAOYF6OazUTgZCMb0yWlJpmdD74REy1gkEaFiub2ULv4fq9GUhA== + version "1.1.1" + resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.1.1.tgz#98b3134f9abbdf23b2663491ace13c5c03a73188" + integrity sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA== co@^4.6.0: version "4.6.0" @@ -4056,11 +3988,6 @@ colors@1.0.3, colors@1.0.x: resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b" integrity sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs= -colors@^1.1.2: - version "1.4.0" - resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" - integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== - colour@~0.7.1: version "0.7.1" resolved "https://registry.yarnpkg.com/colour/-/colour-0.7.1.tgz#9cb169917ec5d12c0736d3e8685746df1cadf778" @@ -4555,12 +4482,12 @@ css-tree@1.0.0-alpha.37: mdn-data "2.0.4" source-map "^0.6.1" -css-vendor@^2.0.7: - version "2.0.7" - resolved "https://registry.yarnpkg.com/css-vendor/-/css-vendor-2.0.7.tgz#4e6d53d953c187981576d6a542acc9fb57174bda" - integrity sha512-VS9Rjt79+p7M0WkPqcAza4Yq1ZHrsHrwf7hPL/bjQB+c1lwmAI+1FXxYTYt818D/50fFVflw0XKleiBN5RITkg== +css-vendor@^2.0.8: + version "2.0.8" + resolved "https://registry.yarnpkg.com/css-vendor/-/css-vendor-2.0.8.tgz#e47f91d3bd3117d49180a3c935e62e3d9f7f449d" + integrity sha512-x9Aq0XTInxrkuFeHKbYC7zWY8ai7qJ04Kxd9MnvbC1uO5DagxoHQjm4JvG+vCdXOoFtCjbL2XSZfxmoYa9uQVQ== dependencies: - "@babel/runtime" "^7.6.2" + "@babel/runtime" "^7.8.3" is-in-browser "^1.0.2" css-what@2.1: @@ -4686,9 +4613,9 @@ cssstyle@^1.0.0, cssstyle@^1.1.1: cssom "0.3.x" csstype@^2.2.0, csstype@^2.5.2, csstype@^2.6.5, csstype@^2.6.7: - version "2.6.9" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.9.tgz#05141d0cd557a56b8891394c1911c40c8a98d098" - integrity sha512-xz39Sb4+OaTsULgUERcCk+TJj8ylkL4aSVDQiX/ksxbELSqwkgt4d4RD7fovIdgJGSuNYqwZEiVjYY5l0ask+Q== + version "2.6.11" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.11.tgz#452f4d024149ecf260a852b025e36562a253ffc5" + integrity sha512-l8YyEC9NBkSm783PFTvh0FmJy7s5pFKrDp49ZL7zBGX3fWkO+N4EEyan1qqp8cwPLDcD0OSdyY6hAMoxp34JFw== csv-parse@^4.4.6: version "4.8.8" @@ -4826,11 +4753,6 @@ deep-is@^0.1.3, deep-is@~0.1.3: resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= -deepmerge@^2.1.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-2.2.1.tgz#5d3ff22a01c00f645405a2fbc17d0778a1801170" - integrity sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA== - default-gateway@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-4.2.0.tgz#167104c7500c2115f6dd69b0a536bb8ed720552b" @@ -5041,11 +4963,11 @@ dom-converter@^0.2: utila "~0.4" dom-helpers@^5.0.1: - version "5.1.3" - resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-5.1.3.tgz#7233248eb3a2d1f74aafca31e52c5299cc8ce821" - integrity sha512-nZD1OtwfWGRBWlpANxacBEZrEuLa16o1nh7YopFWeoF68Zt8GGEmzHu6Xv4F3XaFIC+YXtTLrzgqKxFgLEe4jw== + version "5.1.4" + resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-5.1.4.tgz#4609680ab5c79a45f2531441f1949b79d6587f4b" + integrity sha512-TjMyeVUvNEnOnhzs6uAn9Ya47GmMo3qq7m+Lr/3ON0Rs5kHvb8I+SQYjLUSYn7qhEm0QjW0yrBkvz9yOrwwz1A== dependencies: - "@babel/runtime" "^7.6.3" + "@babel/runtime" "^7.8.7" csstype "^2.6.7" dom-serializer@0, dom-serializer@^0.2.1: @@ -5105,6 +5027,11 @@ domhandler@^3.0.0: dependencies: domelementtype "^2.0.1" +dompurify@^2.0.10: + version "2.0.12" + resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.0.12.tgz#284a2b041e1c60b8e72d7b4d2fadad36141254ae" + integrity sha512-Fl8KseK1imyhErHypFPA8qpq9gPzlsJ/EukA6yk9o0gX23p1TzC+rh9LqNg1qvErRTc0UNMYlKxEGSfSh43NDg== + dompurify@^2.0.8: version "2.0.8" resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.0.8.tgz#6ef89d2d227d041af139c7b01d9f67ed59c2eb3c" @@ -6172,11 +6099,6 @@ flatten@^1.0.2: resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.3.tgz#c1283ac9f27b368abc1e36d1ff7b04501a30356b" integrity sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg== -flow-parser@0.*: - version "0.121.0" - resolved "https://registry.yarnpkg.com/flow-parser/-/flow-parser-0.121.0.tgz#9f9898eaec91a9f7c323e9e992d81ab5c58e618f" - integrity sha512-1gIBiWJNR0tKUNv8gZuk7l9rVX06OuLzY9AoGio7y/JT4V1IZErEMEq2TJS+PFcw/y0RshZ1J/27VfK1UQzYVg== - flush-write-stream@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.1.1.tgz#8dd7d873a1babc207d94ead0c2e0e44276ebf2e8" @@ -6257,30 +6179,6 @@ form-data@~2.3.2: combined-stream "^1.0.6" mime-types "^2.1.12" -formik-material-ui-pickers@^0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/formik-material-ui-pickers/-/formik-material-ui-pickers-0.0.8.tgz#203e602b71eff4a1f28ef40c4c7989a63fc5ff07" - integrity sha512-4/5Fcxe+Bi/6g0nA+ZE1U/D+W8s8yEiictA5w/vLPDab9P9uoktXFjEy2TfKQhfeUP4krYIt6U2tNNZuhRwoIg== - -formik-material-ui@^2.0.0-beta.1: - version "2.0.0-beta.1" - resolved "https://registry.yarnpkg.com/formik-material-ui/-/formik-material-ui-2.0.0-beta.1.tgz#adf6321c97f8617aff00ed717daba8b66d436fd7" - integrity sha512-Zt2pHQzaU2f9reXLS0E85ddeU8aFFtVJV42IPfVdC3lLY+kf+PUdzSiyCHFbRFVniG7SGisEoOwOZFMpkA85Qw== - -formik@^2.1.4: - version "2.1.4" - resolved "https://registry.yarnpkg.com/formik/-/formik-2.1.4.tgz#8deef07ec845ea98f75e03da4aad7aab4ac46570" - integrity sha512-oKz8S+yQBzuQVSEoxkqqJrKQS5XJASWGVn6mrs+oTWrBoHgByVwwI1qHiVc9GKDpZBU9vAxXYAKz2BvujlwunA== - dependencies: - deepmerge "^2.1.1" - hoist-non-react-statics "^3.3.0" - lodash "^4.17.14" - lodash-es "^4.17.14" - react-fast-compare "^2.0.1" - scheduler "^0.18.0" - tiny-warning "^1.0.2" - tslib "^1.10.0" - forwarded@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" @@ -7049,7 +6947,7 @@ hoist-non-react-statics@^2.1.0: resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz#c5903cf409c0dfd908f388e619d86b9c1174cb47" integrity sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw== -hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2: +hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== @@ -7269,9 +7167,9 @@ husky@^3.0.5: slash "^3.0.0" hyphenate-style-name@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/hyphenate-style-name/-/hyphenate-style-name-1.0.3.tgz#097bb7fa0b8f1a9cf0bd5c734cf95899981a9b48" - integrity sha512-EcuixamT82oplpoJ2XU4pDtKGWQ7b00CD9f1ug9IaQ3p1bkHMiKCZ9ut9QDI6qsa6cpUuB+A/I+zLtdNK4n2DQ== + version "1.0.4" + resolved "https://registry.yarnpkg.com/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz#691879af8e220aea5750e8827db4ef62a54e361d" + integrity sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ== iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4, iconv-lite@~0.4.13: version "0.4.24" @@ -8420,45 +8318,6 @@ jsbn@~0.1.0: resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= -jscodeshift-add-imports@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/jscodeshift-add-imports/-/jscodeshift-add-imports-1.0.3.tgz#1e27ee28e284b3be3db22853738b5bcb04a6bf79" - integrity sha512-h7zZ6HS+k2hlXYtx3sFoMAOZq0yGnDfCAHudZqw0KnF1qV30wcXwN9bO5v8zRLUhoUibli8xx3wbT2QDGc+ung== - dependencies: - "@babel/traverse" "^7.4.5" - jscodeshift-find-imports "^1.0.2" - -jscodeshift-find-imports@^1.0.2: - version "1.1.1" - resolved "https://registry.yarnpkg.com/jscodeshift-find-imports/-/jscodeshift-find-imports-1.1.1.tgz#2d4c0a96f1068dded688a8f59fa9470795fd8944" - integrity sha512-vjhUZbVRajqE5F1lonyZ0vy5ux/P+eHWTgdhAawDtsSvxPfwQAsygdBjvhEZZao0zF0gBJ3MPOZlXYEmT9UypQ== - dependencies: - jscodeshift "^0.6.4" - -jscodeshift@^0.6.4: - version "0.6.4" - resolved "https://registry.yarnpkg.com/jscodeshift/-/jscodeshift-0.6.4.tgz#e19ab86214edac86a75c4557fc88b3937d558a8e" - integrity sha512-+NF/tlNbc2WEhXUuc4WEJLsJumF84tnaMUZW2hyJw3jThKKRvsPX4sPJVgO1lPE28z0gNL+gwniLG9d8mYvQCQ== - dependencies: - "@babel/core" "^7.1.6" - "@babel/parser" "^7.1.6" - "@babel/plugin-proposal-class-properties" "^7.1.0" - "@babel/plugin-proposal-object-rest-spread" "^7.0.0" - "@babel/preset-env" "^7.1.6" - "@babel/preset-flow" "^7.0.0" - "@babel/preset-typescript" "^7.1.0" - "@babel/register" "^7.0.0" - babel-core "^7.0.0-bridge.0" - colors "^1.1.2" - flow-parser "0.*" - graceful-fs "^4.1.11" - micromatch "^3.1.10" - neo-async "^2.5.0" - node-dir "^0.1.17" - recast "^0.16.1" - temp "^0.8.1" - write-file-atomic "^2.3.0" - jsdom@^11.5.1: version "11.12.0" resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-11.12.0.tgz#1a80d40ddd378a1de59656e9e6dc5a3ba8657bc8" @@ -8668,68 +8527,69 @@ jsprim@^1.2.2: verror "1.10.0" jss-plugin-camel-case@^10.0.3: - version "10.1.1" - resolved "https://registry.yarnpkg.com/jss-plugin-camel-case/-/jss-plugin-camel-case-10.1.1.tgz#8e73ecc4f1d0f8dfe4dd31f6f9f2782588970e78" - integrity sha512-MDIaw8FeD5uFz1seQBKz4pnvDLnj5vIKV5hXSVdMaAVq13xR6SVTVWkIV/keyTs5txxTvzGJ9hXoxgd1WTUlBw== + version "10.3.0" + resolved "https://registry.yarnpkg.com/jss-plugin-camel-case/-/jss-plugin-camel-case-10.3.0.tgz#ae4da53b39a6e3ea94b70a20fc41c11f0b87386a" + integrity sha512-tadWRi/SLWqLK3EUZEdDNJL71F3ST93Zrl9JYMjV0QDqKPAl0Liue81q7m/nFUpnSTXczbKDy4wq8rI8o7WFqA== dependencies: "@babel/runtime" "^7.3.1" hyphenate-style-name "^1.0.3" - jss "10.1.1" + jss "^10.3.0" jss-plugin-default-unit@^10.0.3: - version "10.1.1" - resolved "https://registry.yarnpkg.com/jss-plugin-default-unit/-/jss-plugin-default-unit-10.1.1.tgz#2df86016dfe73085eead843f5794e3890e9c5c47" - integrity sha512-UkeVCA/b3QEA4k0nIKS4uWXDCNmV73WLHdh2oDGZZc3GsQtlOCuiH3EkB/qI60v2MiCq356/SYWsDXt21yjwdg== + version "10.3.0" + resolved "https://registry.yarnpkg.com/jss-plugin-default-unit/-/jss-plugin-default-unit-10.3.0.tgz#cd74cf5088542620a82591f76c62c6b43a7e50a6" + integrity sha512-tT5KkIXAsZOSS9WDSe8m8lEHIjoEOj4Pr0WrG0WZZsMXZ1mVLFCSsD2jdWarQWDaRNyMj/I4d7czRRObhOxSuw== dependencies: "@babel/runtime" "^7.3.1" - jss "10.1.1" + jss "^10.3.0" jss-plugin-global@^10.0.3: - version "10.1.1" - resolved "https://registry.yarnpkg.com/jss-plugin-global/-/jss-plugin-global-10.1.1.tgz#36b0d6d9facb74dfd99590643708a89260747d14" - integrity sha512-VBG3wRyi3Z8S4kMhm8rZV6caYBegsk+QnQZSVmrWw6GVOT/Z4FA7eyMu5SdkorDlG/HVpHh91oFN56O4R9m2VA== + version "10.3.0" + resolved "https://registry.yarnpkg.com/jss-plugin-global/-/jss-plugin-global-10.3.0.tgz#6b883e74900bb71f65ac2b19bea78f7d1e85af3f" + integrity sha512-etYTG/y3qIR/vxZnKY+J3wXwObyBDNhBiB3l/EW9/pE3WHE//BZdK8LFvQcrCO48sZW1Z6paHo6klxUPP7WbzA== dependencies: "@babel/runtime" "^7.3.1" - jss "10.1.1" + jss "^10.3.0" jss-plugin-nested@^10.0.3: - version "10.1.1" - resolved "https://registry.yarnpkg.com/jss-plugin-nested/-/jss-plugin-nested-10.1.1.tgz#5c3de2b8bda344de1ebcef3a4fd30870a29a8a8c" - integrity sha512-ozEu7ZBSVrMYxSDplPX3H82XHNQk2DQEJ9TEyo7OVTPJ1hEieqjDFiOQOxXEj9z3PMqkylnUbvWIZRDKCFYw5Q== + version "10.3.0" + resolved "https://registry.yarnpkg.com/jss-plugin-nested/-/jss-plugin-nested-10.3.0.tgz#ae8aceac95e09c3d40c991ea32403fb647d9e0a8" + integrity sha512-qWiEkoXNEkkZ+FZrWmUGpf+zBsnEOmKXhkjNX85/ZfWhH9dfGxUCKuJFuOWFM+rjQfxV4csfesq4hY0jk8Qt0w== dependencies: "@babel/runtime" "^7.3.1" - jss "10.1.1" + jss "^10.3.0" tiny-warning "^1.0.2" jss-plugin-props-sort@^10.0.3: - version "10.1.1" - resolved "https://registry.yarnpkg.com/jss-plugin-props-sort/-/jss-plugin-props-sort-10.1.1.tgz#34bddcbfaf9430ec8ccdf92729f03bb10caf1785" - integrity sha512-g/joK3eTDZB4pkqpZB38257yD4LXB0X15jxtZAGbUzcKAVUHPl9Jb47Y7lYmiGsShiV4YmQRqG1p2DHMYoK91g== + version "10.3.0" + resolved "https://registry.yarnpkg.com/jss-plugin-props-sort/-/jss-plugin-props-sort-10.3.0.tgz#5b0625f87b6431a7969c56b0d8c696525969bfe4" + integrity sha512-boetORqL/lfd7BWeFD3K+IyPqyIC+l3CRrdZr+NPq7Noqp+xyg/0MR7QisgzpxCEulk+j2CRcEUoZsvgPC4nTg== dependencies: "@babel/runtime" "^7.3.1" - jss "10.1.1" + jss "^10.3.0" jss-plugin-rule-value-function@^10.0.3: - version "10.1.1" - resolved "https://registry.yarnpkg.com/jss-plugin-rule-value-function/-/jss-plugin-rule-value-function-10.1.1.tgz#be00dac6fc394aaddbcef5860b9eca6224d96382" - integrity sha512-ClV1lvJ3laU9la1CUzaDugEcwnpjPTuJ0yGy2YtcU+gG/w9HMInD5vEv7xKAz53Bk4WiJm5uLOElSEshHyhKNw== + version "10.3.0" + resolved "https://registry.yarnpkg.com/jss-plugin-rule-value-function/-/jss-plugin-rule-value-function-10.3.0.tgz#498b0e2bae16cb316a6bdb73fd783cf9604ba747" + integrity sha512-7WiMrKIHH3rwxTuJki9+7nY11r1UXqaUZRhHvqTD4/ZE+SVhvtD5Tx21ivNxotwUSleucA/8boX+NF21oXzr5Q== dependencies: "@babel/runtime" "^7.3.1" - jss "10.1.1" + jss "^10.3.0" + tiny-warning "^1.0.2" jss-plugin-vendor-prefixer@^10.0.3: - version "10.1.1" - resolved "https://registry.yarnpkg.com/jss-plugin-vendor-prefixer/-/jss-plugin-vendor-prefixer-10.1.1.tgz#8348b20749f790beebab3b6a8f7075b07c2cfcfd" - integrity sha512-09MZpQ6onQrhaVSF6GHC4iYifQ7+4YC/tAP6D4ZWeZotvCMq1mHLqNKRIaqQ2lkgANjlEot2JnVi1ktu4+L4pw== + version "10.3.0" + resolved "https://registry.yarnpkg.com/jss-plugin-vendor-prefixer/-/jss-plugin-vendor-prefixer-10.3.0.tgz#b09c13a4d05a055429d8a24e19cc01ce049f0ed4" + integrity sha512-sZQbrcZyP5V0ADjCLwUA1spVWoaZvM7XZ+2fSeieZFBj31cRsnV7X70FFDerMHeiHAXKWzYek+67nMDjhrZAVQ== dependencies: "@babel/runtime" "^7.3.1" - css-vendor "^2.0.7" - jss "10.1.1" + css-vendor "^2.0.8" + jss "^10.3.0" -jss@10.1.1, jss@^10.0.3: - version "10.1.1" - resolved "https://registry.yarnpkg.com/jss/-/jss-10.1.1.tgz#450b27d53761af3e500b43130a54cdbe157ea332" - integrity sha512-Xz3qgRUFlxbWk1czCZibUJqhVPObrZHxY3FPsjCXhDld4NOj1BgM14Ir5hVm+Qr6OLqVljjGvoMcCdXNOAbdkQ== +jss@^10.0.3, jss@^10.3.0: + version "10.3.0" + resolved "https://registry.yarnpkg.com/jss/-/jss-10.3.0.tgz#2cf7be265f72b59c1764d816fdabff1c5dd18326" + integrity sha512-B5sTRW9B6uHaUVzSo9YiMEOEp3UX8lWevU0Fsv+xtRnsShmgCfIYX44bTH8bPJe6LQKqEXku3ulKuHLbxBS97Q== dependencies: "@babel/runtime" "^7.3.1" csstype "^2.6.5" @@ -9016,7 +8876,7 @@ locate-path@^5.0.0: dependencies: p-locate "^4.1.0" -lodash-es@^4.17.14, lodash-es@^4.2.1: +lodash-es@^4.17.15, lodash-es@^4.2.1: version "4.17.15" resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.15.tgz#21bd96839354412f23d7a10340e5eac6ee455d78" integrity sha512-rlrc3yU3+JNOpZ9zj5pQtxnx2THmvRykwL4Xlxoa8I9lHBlVbbyPhgyPMioxVZ4NqyxaVVtaJnzsyOidQIhyyQ== @@ -9604,7 +9464,7 @@ minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= -minimatch@3.0.4, minimatch@^3.0.2, minimatch@^3.0.4: +minimatch@3.0.4, minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== @@ -9873,13 +9733,6 @@ no-case@^3.0.3: lower-case "^2.0.1" tslib "^1.10.0" -node-dir@^0.1.17: - version "0.1.17" - resolved "https://registry.yarnpkg.com/node-dir/-/node-dir-0.1.17.tgz#5f5665d93351335caabef8f1c554516cf5f1e4e5" - integrity sha1-X1Zl2TNRM1yqvvjxxVRRbPXx5OU= - dependencies: - minimatch "^3.0.2" - node-emoji@^1.4.1: version "1.10.0" resolved "https://registry.yarnpkg.com/node-emoji/-/node-emoji-1.10.0.tgz#8886abd25d9c7bb61802a658523d1f8d2a89b2da" @@ -10695,7 +10548,7 @@ pinkie@^2.0.0: resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= -pirates@^4.0.0, pirates@^4.0.1: +pirates@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.1.tgz#643a92caf894566f91b2b986d2c66950a8e2fb87" integrity sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA== @@ -10770,7 +10623,12 @@ pnp-webpack-plugin@1.6.0: dependencies: ts-pnp "^1.1.2" -popper.js@^1.14.1, popper.js@^1.16.1-lts: +popper.js@1.16.1-lts: + version "1.16.1-lts" + resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.16.1-lts.tgz#cf6847b807da3799d80ee3d6d2f90df8a3f50b05" + integrity sha512-Kjw8nKRl1m+VrSFCoVGPph93W/qrSO7ZkqPpTf7F4bk/sqcfWK019dWBUpE/fBOsOQY1dks/Bmcbfn1heM/IsA== + +popper.js@^1.14.1: version "1.16.1" resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.16.1.tgz#2a223cb3dc7b6213d740e40372be40de43e65b1b" integrity sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ== @@ -11500,7 +11358,7 @@ pretty-quick@^2.0.1: mri "^1.1.4" multimatch "^4.0.0" -private@^0.1.8, private@~0.1.5: +private@^0.1.8: version "0.1.8" resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg== @@ -11941,10 +11799,10 @@ react-error-overlay@^6.0.6: resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.6.tgz#ac4d9dc4c1b5c536c2c312bf66aa2b09bfa384e2" integrity sha512-Yzpno3enVzSrSCnnljmr4b/2KUQSMZaPuqmS26t9k4nW7uwJk6STWmH9heNjPuvqUTO3jOSPkHoKgO4+Dw7uIw== -react-fast-compare@^2.0.1: - version "2.0.4" - resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-2.0.4.tgz#e84b4d455b0fec113e0402c329352715196f81f9" - integrity sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw== +react-hook-form@^6.5.0: + version "6.5.0" + resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-6.5.0.tgz#9442797f9f05644829125772b2656d3da19f732e" + integrity sha512-DRziWoDvmwNIwBk6tkBN/fPeCgbtYHr1tIlVVd0ihmQg9Fv+gjOs0BU0D3o7HrKDeKwDA8pnp4tuEwxe8qg9TA== react-image@^4.0.3: version "4.0.3" @@ -11958,11 +11816,16 @@ react-input-autosize@^2.1.2: dependencies: prop-types "^15.5.8" -react-is@^16.12.0, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.0, react-is@^16.8.1, react-is@^16.8.4: +react-is@^16.12.0, react-is@^16.6.0, react-is@^16.8.4: version "16.13.0" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.0.tgz#0f37c3613c34fe6b37cd7f763a0d6293ab15c527" integrity sha512-GFMtL0vHkiBv9HluwNZTggSn/sCyEt9n02aM0dSAjGGyqyNlAyftYm4phPxdvCigG15JreC5biwxCgTAJZ7yAA== +react-is@^16.7.0, react-is@^16.8.0, react-is@^16.8.1: + version "16.13.1" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" + integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== + react-json-view@^1.19.1: version "1.19.1" resolved "https://registry.yarnpkg.com/react-json-view/-/react-json-view-1.19.1.tgz#95d8e59e024f08a25e5dc8f076ae304eed97cf5c" @@ -12083,10 +11946,10 @@ react-textarea-autosize@^6.1.0: dependencies: prop-types "^15.6.0" -react-transition-group@^4.0.0, react-transition-group@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.3.0.tgz#fea832e386cf8796c58b61874a3319704f5ce683" - integrity sha512-1qRV1ZuVSdxPlPf4O8t7inxUGpdyO5zG9IoNfJxSO0ImU2A1YWkEQvFPuIPZmMLkg5hYs7vv5mMOyfgSkvAwvw== +react-transition-group@^4.0.0, react-transition-group@^4.3.0, react-transition-group@^4.4.0: + version "4.4.1" + resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.1.tgz#63868f9325a38ea5ee9535d828327f85773345c9" + integrity sha512-Djqr7OQ2aPUiYurhPalTrVy9ddmFCCzwhqQmtN+J3+3DzLO209Fdr70QrN8Z3DsglWql6iY1lDWAfpFiBtuKGw== dependencies: "@babel/runtime" "^7.5.5" dom-helpers "^5.0.1" @@ -12210,16 +12073,6 @@ realpath-native@^1.1.0: dependencies: util.promisify "^1.0.0" -recast@^0.16.1: - version "0.16.2" - resolved "https://registry.yarnpkg.com/recast/-/recast-0.16.2.tgz#3796ebad5fe49ed85473b479cd6df554ad725dc2" - integrity sha512-O/7qXi51DPjRVdbrpNzoBQH5dnAPQNbfoOFyRiUwreTMJfIHYOEBzwuH+c0+/BTSJ3CQyKs6ILSWXhESH6Op3A== - dependencies: - ast-types "0.11.7" - esprima "~4.0.0" - private "~0.1.5" - source-map "~0.6.1" - recursive-readdir@2.2.2: version "2.2.2" resolved "https://registry.yarnpkg.com/recursive-readdir/-/recursive-readdir-2.2.2.tgz#9946fb3274e1628de6e36b2f6714953b4845094f" @@ -12580,7 +12433,7 @@ rimraf@2, rimraf@^2.2.8, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.3, rimraf@^2. dependencies: glob "^7.1.3" -rimraf@2.6.3, rimraf@~2.6.2: +rimraf@2.6.3: version "2.6.3" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== @@ -12716,14 +12569,6 @@ saxes@^3.1.9: dependencies: xmlchars "^2.1.1" -scheduler@^0.18.0: - version "0.18.0" - resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.18.0.tgz#5901ad6659bc1d8f3fdaf36eb7a67b0d6746b1c4" - integrity sha512-agTSHR1Nbfi6ulI0kYNK0203joW2Y5W4po4l+v03tOoiJKpTBbxpNhWDvqc/4IcOw+KLmSiQLTasZ4cab2/UWQ== - dependencies: - loose-envify "^1.1.0" - object-assign "^4.1.1" - scheduler@^0.19.0: version "0.19.0" resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.19.0.tgz#a715d56302de403df742f4a9be11975b32f5698d" @@ -13053,7 +12898,7 @@ source-map-resolve@^0.5.0, source-map-resolve@^0.5.2: source-map-url "^0.4.0" urix "^0.1.0" -source-map-support@^0.5.16, source-map-support@^0.5.6, source-map-support@~0.5.12: +source-map-support@^0.5.6, source-map-support@~0.5.12: version "0.5.16" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.16.tgz#0ae069e7fe3ba7538c64c98515e35339eac5a042" integrity sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ== @@ -13588,13 +13433,6 @@ tcp-port-used@^1.0.1: debug "4.1.0" is2 "2.0.1" -temp@^0.8.1: - version "0.8.4" - resolved "https://registry.yarnpkg.com/temp/-/temp-0.8.4.tgz#8c97a33a4770072e0a05f919396c7665a7dd59f2" - integrity sha512-s0ZZzd0BzYv5tLSptZooSjK8oj6C+c19p7Vqta9+6NPOf7r+fxq0cJe6/oN4LTC79sy5NY8ucOJNgwsKCSbfqg== - dependencies: - rimraf "~2.6.2" - term-size@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/term-size/-/term-size-1.2.0.tgz#458b83887f288fc56d6fffbfad262e26638efa69" @@ -14742,7 +14580,7 @@ write-file-atomic@2.4.1: imurmurhash "^0.1.4" signal-exit "^3.0.2" -write-file-atomic@^2.0.0, write-file-atomic@^2.3.0: +write-file-atomic@^2.0.0: version "2.4.3" resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.4.3.tgz#1fd2e9ae1df3e75b8d8c367443c692d4ca81f481" integrity sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==