diff --git a/www/package.json b/www/package.json index 63e04b29..29f7b707 100644 --- a/www/package.json +++ b/www/package.json @@ -30,6 +30,7 @@ "hotkeys-js": "^3.7.2", "lodash": "^4.17.15", "query-string": "^6.8.3", + "quill-delta": "^4.2.1", "ramda": "^0.26.1", "react": "^16.9.0", "react-color": "^2.17.3", @@ -37,6 +38,7 @@ "react-data-grid-addons": "^6.1.0", "react-dom": "^16.9.0", "react-dropzone": "^10.1.8", + "react-quill": "^1.3.3", "react-router-dom": "^5.0.1", "react-scripts": "3.1.2", "start": "^5.1.0", diff --git a/www/src/components/Fields/LongText.tsx b/www/src/components/Fields/LongText.tsx index ece3b11b..160dd352 100644 --- a/www/src/components/Fields/LongText.tsx +++ b/www/src/components/Fields/LongText.tsx @@ -8,6 +8,7 @@ import Paper from "@material-ui/core/Paper"; import TextareaAutosize from "@material-ui/core/TextareaAutosize"; import ClickAwayListener from "@material-ui/core/ClickAwayListener"; import EditorContext from "contexts/editorContext"; +import { FieldType } from "."; const useStyles = makeStyles((theme: Theme) => createStyles({ @@ -38,7 +39,7 @@ const LongText = (props: Props) => {
{ - editorContext.open(props); + editorContext.open(props, FieldType.longText); }} > diff --git a/www/src/components/Fields/RichText.tsx b/www/src/components/Fields/RichText.tsx new file mode 100644 index 00000000..6c936604 --- /dev/null +++ b/www/src/components/Fields/RichText.tsx @@ -0,0 +1,47 @@ +import React, { useContext } from "react"; +import ExpandIcon from "@material-ui/icons/AspectRatio"; +import IconButton from "@material-ui/core/IconButton"; +import Typography from "@material-ui/core/Typography"; +import { createStyles, makeStyles, Theme } from "@material-ui/core/styles"; +import EditorContext from "contexts/editorContext"; +import { FieldType } from "."; + +const useStyles = makeStyles((theme: Theme) => + createStyles({ + root: { + position: "relative", + display: "flex", + flexWrap: "wrap", + }, + typography: { + position: "relative", + marginTop: 15, + maxWidth: "calc(100% - 80px)", + wordWrap: "break-word", + }, + }) +); +interface Props { + value: any; + row: { ref: firebase.firestore.DocumentReference; id: string }; + onSubmit: Function; +} + +const RichText = (props: Props) => { + const editorContext = useContext(EditorContext); + const { value } = props; + const classes = useStyles(); + return ( +
+ { + editorContext.open(props, FieldType.richText); + }} + > + + + {value} +
+ ); +}; +export default RichText; diff --git a/www/src/components/Fields/index.tsx b/www/src/components/Fields/index.tsx index d22d1018..6e89c9ee 100644 --- a/www/src/components/Fields/index.tsx +++ b/www/src/components/Fields/index.tsx @@ -20,6 +20,7 @@ import MenuItem from "@material-ui/core/MenuItem"; export enum FieldType { simpleText = "SIMPLE_TEXT", longText = "LONG_TEXT", + richText = "RICH_TEXT", email = "EMAIL", PhoneNumber = "PHONE_NUMBER", checkBox = "CHECK_BOX", @@ -55,6 +56,7 @@ export const FIELDS = [ { icon: , name: "Multi Select", type: FieldType.multiSelect }, { icon: , name: "Doc Select", type: FieldType.documentSelect }, { icon: , name: "Action", type: FieldType.action }, + { icon: , name: "Rich Text", type: FieldType.richText }, { icon: , name: "Color", type: FieldType.color }, ]; diff --git a/www/src/components/LongTextEditor.tsx b/www/src/components/LongTextEditor.tsx index 2a16252d..02677bc4 100644 --- a/www/src/components/LongTextEditor.tsx +++ b/www/src/components/LongTextEditor.tsx @@ -6,6 +6,7 @@ import Fade from "@material-ui/core/Fade"; import TextareaAutosize from "@material-ui/core/TextareaAutosize"; import Paper from "@material-ui/core/Paper"; import Typography from "@material-ui/core/Typography"; +import { FieldType } from "./Fields"; const useStyles = makeStyles((theme: Theme) => createStyles({ test: { position: "absolute", top: 10, left: 10 }, @@ -37,6 +38,7 @@ interface Props {} const LongTextEditor = (props: Props) => { const classes = useStyles(); const editorContext = useContext(EditorContext); + if (editorContext.fieldType !== FieldType.longText) return <>; const isOpen = editorContext.editorValue !== null; return ( + createStyles({ + test: { position: "absolute", top: 10, left: 10 }, + modal: { + display: "flex", + alignItems: "center", + justifyContent: "center", + maxWidth: 600, + width: "100%", + }, + paper: { padding: theme.spacing(2) }, + root: { + margin: `${theme.spacing(1)}px 0`, + + "&:focus-within $sectionTitle": { + color: + theme.palette.type === "dark" + ? theme.palette.primary.dark + : theme.palette.primary.main, + }, + }, + typography: { + padding: theme.spacing(2), + }, + textArea: { + fontSize: 16, + minWidth: 230, + width: "100%", + }, + quillEditor: { + minHeight: 100, + + // match styling + "& .ql-toolbar": { + borderRadius: `${theme.shape.borderRadius}px ${theme.shape.borderRadius}px 0 0`, + transition: theme.transitions.create("border-color", { + duration: theme.transitions.duration.shortest, + }), + }, + "& .ql-container": { + borderRadius: `0 0 ${theme.shape.borderRadius}px ${theme.shape.borderRadius}px`, + transition: theme.transitions.create("border-color", { + duration: theme.transitions.duration.shortest, + }), + }, + "& .ql-editor": { + minHeight: 100, + fontFamily: theme.typography.fontFamily, + fontSize: ".875rem", + color: theme.palette.text.primary, + "&.ql-blank::before": { + fontStyle: "normal", + color: theme.palette.text.disabled, + }, + }, + + // highlight border on focus + "&:focus-within .ql-toolbar.ql-snow, &:focus-within .ql-container.ql-snow": { + borderColor: theme.palette.primary.main, + }, + + // buttons stroke/fill colour matching + "& .ql-snow.ql-toolbar button, & .ql-snow .ql-picker-label": { + borderRadius: theme.shape.borderRadius / 2, + transition: theme.transitions.create("background-color", { + duration: theme.transitions.duration.shortest, + }), + }, + "& .ql-snow .ql-stroke": { + stroke: theme.palette.text.primary, + transition: theme.transitions.create("stroke", { + duration: theme.transitions.duration.shortest, + }), + }, + "& .ql-snow .ql-fill": { + fill: theme.palette.text.primary, + transition: theme.transitions.create("fill", { + duration: theme.transitions.duration.shortest, + }), + }, + + // colour buttons on hover + "& button:hover .ql-stroke": { + stroke: `${theme.palette.primary.main} !important`, + }, + "& button:hover .ql-fill": { + fill: `${theme.palette.primary.main} !important`, + }, + + // highlight buttons when selected/active + "& .ql-snow.ql-toolbar .ql-active": { + backgroundColor: theme.palette.primary.light, + "& .ql-stroke": { + stroke: `${theme.palette.primary.main} !important`, + }, + "& .ql-fill": { + fill: `${theme.palette.primary.main} !important`, + }, + }, + + // dropdown styling + "& .ql-snow.ql-toolbar button:hover, & .ql-snow .ql-toolbar button:hover, & .ql-snow.ql-toolbar button:focus, & .ql-snow .ql-toolbar button:focus, & .ql-snow.ql-toolbar button.ql-active, & .ql-snow .ql-toolbar button.ql-active, & .ql-snow.ql-toolbar .ql-picker-label:hover, & .ql-snow .ql-toolbar .ql-picker-label:hover, & .ql-snow.ql-toolbar .ql-picker-label.ql-active, & .ql-snow .ql-toolbar .ql-picker-label.ql-active, & .ql-snow.ql-toolbar .ql-picker-item:hover, & .ql-snow .ql-toolbar .ql-picker-item:hover, & .ql-snow.ql-toolbar .ql-picker-item.ql-selected, & .ql-snow .ql-toolbar .ql-picker-item.ql-selected": { + color: theme.palette.primary.main, + + "& polygon": { stroke: theme.palette.primary.main + " !important" }, + }, + }, + }) +); +interface Props {} + +async function asyncUploader(ref: any, file: File) { + const documentRef = bucket.ref("test").child(ref); + const snapShot = await documentRef.put(file); + const downloadUrl = await bucket + .ref("test") + .child(snapShot.metadata.fullPath) + .getDownloadURL(); + return downloadUrl; +} +const imageHandler = (quillRef: any) => () => { + const now = new Date(); + + const quill = quillRef.current.getEditor(); + let fileInput: any = document.body.querySelector("input.ql-image[type=file]"); + if (fileInput == null) { + fileInput = document.createElement("input"); + fileInput.setAttribute("type", "file"); + fileInput.setAttribute( + "accept", + "image/png, image/gif, image/jpeg, image/bmp, image/x-icon" + ); + fileInput.classList.add("ql-image"); + fileInput.addEventListener("change", async () => { + if (fileInput.files != null && fileInput.files[0] != null) { + const ref = `quill-images/${now.getTime()}/${fileInput.files[0].name}`; + const downloadUrl = await asyncUploader(ref, fileInput.files[0]); + let range = quill.getSelection(true); + quill.updateContents( + new Delta() + .retain(range.index) + .delete(range.length) + .insert({ image: downloadUrl }), + "user" + ); + + fileInput.value = ""; + document.body.removeChild(fileInput); + } + }); + document.body.appendChild(fileInput); + } + fileInput.click(); +}; + +const RichTextEditor = (props: Props) => { + const classes = useStyles(); + const editorContext = useContext(EditorContext); + const quillRef = useRef(null); + useEffect(() => { + if (quillRef !== null && quillRef.current) { + // quillRef.current + // .getEditor() + // .getModule("toolbar") + // .addHandler("image", imageHandler(quillRef)); + } + }, [quillRef]); + if (editorContext.fieldType !== FieldType.richText) return <>; + const isOpen = editorContext.editorValue !== null; + return ( + { + editorContext.close(); + }} + > + + + { + // const dataURLregEx = /"data:.*?"/; + // let matches = val.match(dataURLregEx); + // delete matches.index; + // delete matches.input; + // delete matches.groups; + // console.log(matches); + editorContext.setEditorValue(val); + }} + theme="snow" + className={classes.quillEditor} + // preserveWhiteSpace + modules={{ + toolbar: { + container: [ + ["bold", "italic", "underline"], + [{ header: [1, 2, 3, 4, false] }], + + [{ list: "bullet" }, { list: "ordered" }], + [{ indent: "-1" }, { indent: "+1" }], + ["blockquote", "code-block", "video"], + ["link"], + ], + }, + clipboard: { + matchVisual: false, + }, + }} + /> + + click away or press escape to save + + + + + ); +}; +export default RichTextEditor; diff --git a/www/src/components/Table/grid-fns.tsx b/www/src/components/Table/grid-fns.tsx index a89710ca..94b6f344 100644 --- a/www/src/components/Table/grid-fns.tsx +++ b/www/src/components/Table/grid-fns.tsx @@ -13,6 +13,7 @@ const UrlLink = lazy(() => import("../Fields/UrlLink")); const Image = lazy(() => import("../Fields/Image")); const File = lazy(() => import("../Fields/File")); const LongText = lazy(() => import("../Fields/LongText")); +const RichText = lazy(() => import("../Fields/RichText")); const Color = lazy(() => import("../Fields/Color")); const Action = lazy(() => import("../Fields/Action")); @@ -26,6 +27,7 @@ export const editable = (fieldType: FieldType) => { case FieldType.image: case FieldType.file: case FieldType.longText: + case FieldType.richText: case FieldType.documentSelect: case FieldType.color: case FieldType.action: @@ -164,7 +166,18 @@ export const cellFormatter = (column: any) => { ); }; - + case FieldType.richText: + return (props: any) => { + return ( + }> + + + ); + }; default: return false; } diff --git a/www/src/components/Table/index.tsx b/www/src/components/Table/index.tsx index 2ed8936f..ef9723a4 100644 --- a/www/src/components/Table/index.tsx +++ b/www/src/components/Table/index.tsx @@ -27,6 +27,7 @@ import Grid from "./Grid"; import Tooltip from "@material-ui/core/Tooltip"; import { EditorProvider } from "../../util/EditorProvider"; import LongTextEditor from "../LongTextEditor"; +import RichTextEditor from "../RichTextEditor"; const Hotkeys = lazy(() => import("./HotKeys")); const TableHeader = lazy(() => import("./TableHeader")); @@ -297,6 +298,7 @@ function Table(props: Props) { /> + diff --git a/www/src/contexts/editorContext.ts b/www/src/contexts/editorContext.ts index bb51b8be..e7145885 100644 --- a/www/src/contexts/editorContext.ts +++ b/www/src/contexts/editorContext.ts @@ -1,4 +1,5 @@ import React from "react"; +import { FieldType } from "../components/Fields"; export interface EditorContextInterface { // row: any; @@ -9,6 +10,7 @@ export interface EditorContextInterface { open: any; close: any; setEditorValue: any; + fieldType: FieldType | null; } const EditorContext = React.createContext({ @@ -20,6 +22,7 @@ const EditorContext = React.createContext({ close: undefined, editorValue: undefined, setEditorValue: undefined, + fieldType: null, }); export default EditorContext; diff --git a/www/src/util/EditorProvider.tsx b/www/src/util/EditorProvider.tsx index fe96b4dc..87bd8457 100644 --- a/www/src/util/EditorProvider.tsx +++ b/www/src/util/EditorProvider.tsx @@ -1,5 +1,6 @@ import React, { useState } from "react"; import EditorContext from "../contexts/editorContext"; +import { FieldType } from "../components/Fields"; interface IEditorProviderProps { children: React.ReactNode; @@ -7,6 +8,7 @@ interface IEditorProviderProps { export const EditorProvider: React.FC = ({ children, }) => { + const [fieldType, setFieldType] = useState(null); const [props, setProps] = useState(); const [editorValue, setEditorValue] = useState(null); const close = () => { @@ -14,14 +16,19 @@ export const EditorProvider: React.FC = ({ props.onSubmit(editorValue); } setEditorValue(null); + setFieldType(null); }; - const open = (props: { - row: any; - onSubmit: any; - fieldName: string; - value: string; - anchorEl: any; - }) => { + const open = ( + props: { + row: any; + onSubmit: any; + fieldName: string; + value: string; + anchorEl: any; + }, + type: FieldType + ) => { + setFieldType(type); setProps(props); setEditorValue(props.value); }; @@ -30,6 +37,7 @@ export const EditorProvider: React.FC = ({ value={{ close, open, + fieldType, editorValue, setEditorValue, }} diff --git a/www/yarn.lock b/www/yarn.lock index 213b5091..14a9ec20 100644 --- a/www/yarn.lock +++ b/www/yarn.lock @@ -1653,6 +1653,13 @@ resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.2.tgz#690a1475b84f2a884fd07cd797c00f5f31356ea8" integrity sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw== +"@types/quill@1.3.10": + version "1.3.10" + resolved "https://registry.yarnpkg.com/@types/quill/-/quill-1.3.10.tgz#dc1f7b6587f7ee94bdf5291bc92289f6f0497613" + integrity sha512-IhW3fPW+bkt9MLNlycw8u8fWb7oO7W5URC9MfZYHBlA24rex9rs23D5DETChu1zvgVdc5ka64ICjJOgQMr6Shw== + dependencies: + parchment "^1.1.2" + "@types/ramda@^0.26.21": version "0.26.21" resolved "https://registry.yarnpkg.com/@types/ramda/-/ramda-0.26.21.tgz#cfd552c679453d153a9e2fd89ffc5dd5aa93d2c9" @@ -2240,7 +2247,7 @@ arrify@^1.0.1: resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= -asap@^2.0.6, asap@~2.0.6: +asap@^2.0.6, asap@~2.0.3, asap@~2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY= @@ -3233,6 +3240,11 @@ clone-deep@^4.0.1: kind-of "^6.0.2" shallow-clone "^3.0.0" +clone@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" + integrity sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18= + clsx@^1.0.2, clsx@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.0.4.tgz#0c0171f6d5cb2fe83848463c15fcc26b4df8c2ec" @@ -3538,6 +3550,11 @@ core-js@3.2.1: resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.2.1.tgz#cd41f38534da6cc59f7db050fe67307de9868b09" integrity sha512-Qa5XSVefSVPRxy2XfUC13WbvqkxhkwB3ve+pgCQveNgYzbM/UxZeu1dcOX/xr4UmfUd+muuvsaxilQzCyUurMw== +core-js@^1.0.0: + version "1.2.7" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636" + integrity sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY= + core-js@^2.4.0, core-js@^2.5.0: version "2.6.9" resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.9.tgz#6b4b214620c834152e179323727fc19741b084f2" @@ -3589,6 +3606,15 @@ create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: safe-buffer "^5.0.1" sha.js "^2.4.8" +create-react-class@^15.6.0: + version "15.6.3" + resolved "https://registry.yarnpkg.com/create-react-class/-/create-react-class-15.6.3.tgz#2d73237fb3f970ae6ebe011a9e66f46dbca80036" + integrity sha512-M+/3Q6E6DLO6Yx3OwrWjwHBnvfXXYA7W+dFjt/ZDBemHO1DDZhsalX/NUtnTYclN6GfnBDRh4qRHjcDHmlJBJg== + dependencies: + fbjs "^0.8.9" + loose-envify "^1.3.1" + object-assign "^4.1.1" + cross-spawn@6.0.5, cross-spawn@^6.0.0, cross-spawn@^6.0.5: version "6.0.5" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" @@ -4812,6 +4838,11 @@ eventemitter3@1.x.x: resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-1.2.0.tgz#1c86991d816ad1e504750e73874224ecf3bec508" integrity sha1-HIaZHYFq0eUEdQ5zh0Ik7PO+xQg= +eventemitter3@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-2.0.3.tgz#b5e1079b59fb5e1ba2771c0a993be060a58c99ba" + integrity sha1-teEHm1n7XhuidxwKmTvgYKWMmbo= + eventemitter3@^3.0.0: version "3.1.2" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.1.2.tgz#2d3d48f9c346698fce83a85d7d664e98535df6e7" @@ -4954,7 +4985,7 @@ extend-shallow@^3.0.0, extend-shallow@^3.0.2: assign-symbols "^1.0.0" is-extendable "^1.0.1" -extend@~3.0.2: +extend@^3.0.2, extend@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== @@ -4997,6 +5028,16 @@ fast-deep-equal@^2.0.1: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= +fast-diff@1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.1.2.tgz#4b62c42b8e03de3f848460b639079920695d0154" + integrity sha512-KaJUt+M9t1qaIteSvjc6P3RbMdXsNhK61GRftR6SNxqmhthcd9MGIi4T+o0jD8LUSpSnSKXE20nLtJ3fOHxQig== + +fast-diff@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" + integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== + fast-glob@^2.0.2: version "2.2.7" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-2.2.7.tgz#6953857c3afa475fff92ee6015d52da70a4cd39d" @@ -5040,6 +5081,19 @@ fb-watchman@^2.0.0: dependencies: bser "^2.0.0" +fbjs@^0.8.9: + version "0.8.17" + resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.17.tgz#c4d598ead6949112653d6588b01a5cdcd9f90fdd" + integrity sha1-xNWY6taUkRJlPWWIsBpc3Nn5D90= + dependencies: + core-js "^1.0.0" + isomorphic-fetch "^2.1.1" + loose-envify "^1.0.0" + object-assign "^4.1.0" + promise "^7.1.1" + setimmediate "^1.0.5" + ua-parser-js "^0.7.18" + figgy-pudding@^3.5.1: version "3.5.1" resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.1.tgz#862470112901c727a0e495a80744bd5baa1d6790" @@ -6619,7 +6673,7 @@ isobject@^4.0.0: resolved "https://registry.yarnpkg.com/isobject/-/isobject-4.0.0.tgz#3f1c9155e73b192022a80819bacd0343711697b0" integrity sha512-S/2fF5wH8SJA/kmwr6HYhK/RI/OkhD84k8ntalo0iJjZikgq1XFvR5M8NPT1x5F7fBwCG3qHfnzeP/Vh/ZxCUA== -isomorphic-fetch@2.2.1: +isomorphic-fetch@2.2.1, isomorphic-fetch@^2.1.1: version "2.2.1" resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9" integrity sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk= @@ -7702,7 +7756,7 @@ lodash.uniq@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= -"lodash@>=3.5 <5", lodash@^4.0.1, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.5, lodash@^4.2.0, lodash@^4.2.1: +"lodash@>=3.5 <5", lodash@^4.0.1, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.0, lodash@^4.2.1: version "4.17.15" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== @@ -8778,6 +8832,11 @@ param-case@2.1.x: dependencies: no-case "^2.2.0" +parchment@^1.1.2, parchment@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/parchment/-/parchment-1.1.4.tgz#aeded7ab938fe921d4c34bc339ce1168bc2ffde5" + integrity sha512-J5FBQt/pM2inLzg4hEWmzQx/8h8D0CiDxaG3vyp9rKrQRSDgBlhjdP5jQGgosEajXPSQouXGHOmVdgo7QmJuOg== + parent-module@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" @@ -9823,6 +9882,13 @@ promise@8.0.3: dependencies: asap "~2.0.6" +promise@^7.1.1: + version "7.3.1" + resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf" + integrity sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg== + dependencies: + asap "~2.0.3" + prompts@^2.0.1: version "2.2.1" resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.2.1.tgz#f901dd2a2dfee080359c0e20059b24188d75ad35" @@ -10001,6 +10067,36 @@ querystringify@^2.1.1: resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.1.1.tgz#60e5a5fd64a7f8bfa4d2ab2ed6fdf4c85bad154e" integrity sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA== +quill-delta@^3.6.2: + version "3.6.3" + resolved "https://registry.yarnpkg.com/quill-delta/-/quill-delta-3.6.3.tgz#b19fd2b89412301c60e1ff213d8d860eac0f1032" + integrity sha512-wdIGBlcX13tCHOXGMVnnTVFtGRLoP0imqxM696fIPwIf5ODIYUHIvHbZcyvGlZFiFhK5XzDC2lpjbxRhnM05Tg== + dependencies: + deep-equal "^1.0.1" + extend "^3.0.2" + fast-diff "1.1.2" + +quill-delta@^4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/quill-delta/-/quill-delta-4.2.1.tgz#ad4f191cdf3be5079c5dc3991b9603a5cc0db69a" + integrity sha512-Y2nksOj6Q+4hizre8n0dml76vLNGK4/y86EoI1d7rv6EL1bx7DPDYRmqQMPu1UqFQO/uQuVHQ3fOmm4ZSzWrfA== + dependencies: + deep-equal "^1.0.1" + extend "^3.0.2" + fast-diff "1.2.0" + +quill@^1.2.6: + version "1.3.7" + resolved "https://registry.yarnpkg.com/quill/-/quill-1.3.7.tgz#da5b2f3a2c470e932340cdbf3668c9f21f9286e8" + integrity sha512-hG/DVzh/TiknWtE6QmWAF/pxoZKYxfe3J/d/+ShUWkDvvkZQVTPeVmUJVu1uE6DDooC4fWTiCLh84ul89oNz5g== + dependencies: + clone "^2.1.1" + deep-equal "^1.0.1" + eventemitter3 "^2.0.3" + extend "^3.0.2" + parchment "^1.1.4" + quill-delta "^3.6.2" + raf@3.4.1: version "3.4.1" resolved "https://registry.yarnpkg.com/raf/-/raf-3.4.1.tgz#0742e99a4a6552f445d73e3ee0328af0ff1ede39" @@ -10166,6 +10262,11 @@ react-dnd@^2.6.0: lodash "^4.2.0" prop-types "^15.5.10" +react-dom-factories@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/react-dom-factories/-/react-dom-factories-1.0.2.tgz#eb7705c4db36fb501b3aa38ff759616aa0ff96e0" + integrity sha1-63cFxNs2+1AbOqOP91lhaqD/luA= + react-dom@^16.9.0: version "16.9.0" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.9.0.tgz#5e65527a5e26f22ae3701131bcccaee9fb0d3962" @@ -10207,6 +10308,19 @@ react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.4, react-is resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.9.0.tgz#21ca9561399aad0ff1a7701c01683e8ca981edcb" integrity sha512-tJBzzzIgnnRfEm046qRcURvwQnZVXmuCbscxUO5RWrGTXpon2d4c8mI0D8WE6ydVIm29JiLB6+RslkIvym9Rjw== +react-quill@^1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/react-quill/-/react-quill-1.3.3.tgz#95b8e088ad4e4acc6c79c2f85bdc0460eebe08eb" + integrity sha512-T9RubLaWJ8gCfp7sOqmFupjiTiEp/EdGqhCG+PWGKc5UHiK6xIWNKWYsOHHEhQ+sZCKs8u/DPx47gc1VfFmcLg== + dependencies: + "@types/quill" "1.3.10" + "@types/react" "*" + create-react-class "^15.6.0" + lodash "^4.17.4" + prop-types "^15.5.10" + quill "^1.2.6" + react-dom-factories "^1.0.0" + react-router-dom@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.0.1.tgz#ee66f4a5d18b6089c361958e443489d6bab714be" @@ -11054,7 +11168,7 @@ set-value@^2.0.0, set-value@^2.0.1: is-plain-object "^2.0.3" split-string "^3.0.1" -setimmediate@^1.0.4: +setimmediate@^1.0.4, setimmediate@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= @@ -12087,6 +12201,11 @@ ua-parser-js@0.7.17: resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.17.tgz#e9ec5f9498b9ec910e7ae3ac626a805c4d09ecac" integrity sha512-uRdSdu1oA1rncCQL7sCj8vSyZkgtL7faaw9Tc9rZ3mGgraQ7+Pdx7w5mnOSF3gw9ZNG6oc+KXfkon3bKuROm0g== +ua-parser-js@^0.7.18: + version "0.7.20" + resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.20.tgz#7527178b82f6a62a0f243d1f94fd30e3e3c21098" + integrity sha512-8OaIKfzL5cpx8eCMAhhvTlft8GYF8b2eQr6JkCyVdrgjcytyOmPCXrqXFcUnhonRpLlh5yxEZVohm6mzaowUOw== + uglify-js@3.4.x: version "3.4.10" resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.4.10.tgz#9ad9563d8eb3acdfb8d38597d2af1d815f6a755f"