diff --git a/.eslintrc b/.eslintrc deleted file mode 100644 index 114c006570569acecebc42facdfc2c94eb16545a..0000000000000000000000000000000000000000 --- a/.eslintrc +++ /dev/null @@ -1,16 +0,0 @@ -{ - "env": { - "commonjs": true, - "es6": true, - "node": true - }, - "parserOptions": { - "ecmaVersion": 2018 - }, - "plugins": ["prettier", "react-hooks"], - "extends": "react-app", - "rules": { - "react-hooks/rules-of-hooks": "error", - "react-hooks/exhaustive-deps": "warn" - } -} diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000000000000000000000000000000000000..9ee663d8322105e701fe4e730495be6adf0d5d6e --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,16 @@ +module.exports = { + env: { + commonjs: true, + es6: true, + node: true, + }, + parserOptions: { + ecmaVersion: 2018, + }, + plugins: ['prettier', 'react-hooks'], + extends: 'react-app', + rules: { + 'react-hooks/rules-of-hooks': 'error', + 'react-hooks/exhaustive-deps': 'warn', + }, +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000000000000000000000000000000000000..dce69f3f9103eb3972f0ff533a6a9738c41b49f3 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,8 @@ +{ + "editor.formatOnSave": true, + "eslint.format.enable": true, + "editor.codeActionsOnSave": { + "source.fixAll.eslint": true + }, + "editor.defaultFormatter": "esbenp.prettier-vscode" +} diff --git a/README.md b/README.md index cfd87aae98207723472c18c48b315da0f2adcccd..9b0c93ba0aa38b8b9b753139872d8b553b24461d 100644 --- a/README.md +++ b/README.md @@ -2,18 +2,70 @@ Projet client du backoffice LLLE +## Install + +In order to install the project, make sure you have installed the followings : + +- NodeJS +- Yarn +- Docker / Docker Compose +- VSCode Editor (or the one you prefer), with at least ESLint and Prettier extensions + +You can then clone the app repository and install dependencies: + +```sh +$ git clone https://forge.grandlyon.com/web-et-numerique/llle_project/backoffice-client.git +$ cd backoffice-client +``` + ## Local usage +Before launching the application, ensure you've properly filled the .env file according to the template. If needed please refer to a team member. + In order to launch the projet in local with the backend working launch the following command ```bash -yarn docker-local-up +yarn local-up ``` +This command will launch the app from the _docker-compose.local.yml_ file, which will launch 3 docker images and start the react app with _yarn start_ + +- The backend Go app, from the image located on its GitLab repository +- The mongo Database, from the DockerHub image +- The Ngnix server with a local configuration located in nginx/site.conf + To stop it properly use ```bash -yarn docker-local-down +yarn local-down ``` -The nginx server handles https request and responses from the backend +This app runs in https, such as the backend, to access it go on https://localhost/ +Also make sure you have HTTPS env variable set to true. +Do not use the app with the port 3000, you won't be able to login. + +## Backend and Database + +In order to get Backend documentation, please refer directly to the [backend project](https://forge.grandlyon.com/web-et-numerique/llle_project/backoffice-server) + +## Nginx + +The nginx server redirects https requests from frontend to the backend on port 1443. + +It has two configuration files : + +- nginx/site.conf, used for local development +- nginx/site.prod.conf, used for production + +The nginx server needs local ssl certificates in order to run an interact with backend, these certificates are present in the project. + +## CI/CD + +This app has a gitlab CI/CD pipeline you can find in the _.gitlab-ci.yml_ file. +On the dev branch and on merge requests, the pipeline will run a build stage and a quality stage, which is a Sonarqube quality check. +On dev and master branches, the pipeline will run a docker image build that you can find in the GitLab container registry. + +### Editor + +This app uses Draft.js Wysiwyg editor for more information checkout its (documentation page)[https://draftjs.org/docs/getting-started] +For more advanced documentation about editor customization, please checkout the (react draft wysiwig page)[https://jpuri.github.io/react-draft-wysiwyg/#/docs?_k=jjqinp] diff --git a/docker-compose.local.yml b/docker-compose.local.yml index 52af81ba486596cf34bcd15dc81d40a8952b364f..e598070da4096621b4e3a18dddfd99e293998998 100644 --- a/docker-compose.local.yml +++ b/docker-compose.local.yml @@ -2,6 +2,9 @@ version: '3.7' services: nginx: image: nginx:1.16 + depends_on: + - front + - backend volumes: - ./nginx/nginx.conf:/etc/nginx/nginx.conf - ./nginx/site.conf:/etc/nginx/conf.d/default.conf diff --git a/package.json b/package.json index 59d91c87490f848dac0785068ddd1f18697f1303..e8a7c9e485a14068ec00d92b2e0d40018a3c8f1d 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,6 @@ "@types/jest": "^26.0.15", "@types/node": "^12.0.0", "@types/react": "^17.0.0", - "@types/react-datepicker": "^4.1.3", "@types/react-dom": "^17.0.0", "@types/react-router-dom": "^5.1.8", "@typescript-eslint/eslint-plugin": "^4.28.4", @@ -48,17 +47,23 @@ "eslint-plugin-jest": "^24.4.0", "eslint-plugin-prettier": "^3.4.0", "eslint-plugin-react": "^7.24.0", - "eslint-plugin-react-hooks": "^4.2.0", + "eslint-plugin-react-hooks": "^4.2.1-alpha-e4e8226c6-20210812", "prettier": "^2.3.2" }, "dependencies": { "@testing-library/jest-dom": "^5.11.4", "@testing-library/react": "^11.1.0", "@testing-library/user-event": "^12.1.10", - "@tinymce/tinymce-react": "^3.3.1", + "@types/draft-js": "^0.11.4", + "@types/html-to-draftjs": "^1.4.0", + "@types/react-draft-wysiwyg": "^1.13.3", "axios": "^0.21.1", + "draft-js": "^0.11.7", + "draft-js-export-html": "^1.4.1", + "html-to-draftjs": "^1.5.0", "react": "^17.0.2", "react-dom": "^17.0.2", + "react-draft-wysiwyg": "^1.14.7", "react-router-dom": "^5.2.0", "react-scripts": "4.0.3", "react-toastify": "^7.0.4", diff --git a/src/components/Editing/CustomEditor.tsx b/src/components/Editing/CustomEditor.tsx new file mode 100644 index 0000000000000000000000000000000000000000..b1ad0b14c83d17637ec11ab9be5cbba99a5453b7 --- /dev/null +++ b/src/components/Editing/CustomEditor.tsx @@ -0,0 +1,40 @@ +// import { } from 'draft-js' +import { stateToHTML } from 'draft-js-export-html' +import { useState } from 'react' +import { Editor, EditorState } from 'react-draft-wysiwyg' +import CustomLink from './CustomLink' +import './customEditor.scss' + +interface CustomEditorProps { + baseState: EditorState + editorType: 'header' | 'quote' | 'question' | 'link' + handleChange: ( + value: string, + type: 'header' | 'quote' | 'question' | 'link' + ) => void +} + +const CustomEditor: React.FC<CustomEditorProps> = ({ + baseState, + handleChange, + editorType, +}: CustomEditorProps) => { + const [editorState, setEditorState] = useState<EditorState>(baseState) + + const handleStateChange = (state: EditorState) => { + setEditorState(state) + handleChange(stateToHTML(editorState.getCurrentContent()), editorType) + } + + return ( + <Editor + editorState={editorState} + onEditorStateChange={(state) => handleStateChange(state)} + wrapperClassName="wrapper-class" + editorClassName="editor-class" + toolbarClassName="toolbar-class" + toolbarCustomButtons={[<CustomLink editorState={editorState} />]} + /> + ) +} +export default CustomEditor diff --git a/src/components/Editing/CustomLink.tsx b/src/components/Editing/CustomLink.tsx new file mode 100644 index 0000000000000000000000000000000000000000..408b56da6013a2c4034d8afac40d8adf20efb0cb --- /dev/null +++ b/src/components/Editing/CustomLink.tsx @@ -0,0 +1,101 @@ +import { EditorState, Modifier, ContentState } from 'draft-js' +import htmlToDraft from 'html-to-draftjs' +import { useState } from 'react' + +interface EcolyoLinkProps { + onChange?: (editorState: EditorState) => void + editorState: EditorState +} +interface LinkState { + displayTitle: string + link: string +} + +const CustomLink: React.FC<EcolyoLinkProps> = ({ + onChange, + editorState, +}: EcolyoLinkProps) => { + const [open, setOpen] = useState<boolean>(false) + const links: LinkState[] = [ + { + displayTitle: 'Consommation', + link: 'consumption', + }, + { + displayTitle: 'Ecogestes', + link: 'ecogestures', + }, + { + displayTitle: 'Analyse', + link: 'analysis', + }, + { + displayTitle: 'Options', + link: 'options', + }, + ] + const appendLink = (link: LinkState) => { + const data = `<a href="{cozyUrl}${ + link.link + }">${link.displayTitle.toLowerCase()}</a>` + let { contentBlocks, entityMap } = htmlToDraft(data) + + const contentState = Modifier.replaceWithFragment( + editorState.getCurrentContent(), + editorState.getSelection(), + ContentState.createFromBlockArray(contentBlocks, entityMap).getBlockMap() + ) + const result = EditorState.push( + editorState, + contentState, + 'insert-fragment' + ) + if (onChange) { + onChange(result) + } + } + return ( + <div + onClick={() => setOpen(!open)} + className="rdw-block-wrapper" + aria-label="rdw-block-control" + role="button" + tabIndex={0} + aria-expanded={false} + > + <div + className="rdw-dropdown-wrapper rdw-block-dropdown" + aria-label="rdw-dropdown" + style={{ width: 200 }} + > + <div className="rdw-dropdown-selectedtext"> + <span>Lien Ecolyo</span> + <div className={`rdw-dropdown-caretto${open ? 'close' : 'open'}`} /> + </div> + {open && ( + <ul + className={ + open + ? 'rdw-dropdown-optionwrapper' + : 'rdw-dropdown-optionwrapper placeholder-ul' + } + > + {links.map((item: LinkState) => { + return ( + <li + className="rdw-dropdownoption-default placeholder-li" + onClick={() => appendLink(item)} + key={item.link} + > + {item.displayTitle} + </li> + ) + })} + </ul> + )} + </div> + </div> + ) +} + +export default CustomLink diff --git a/src/components/Editing/Editing.tsx b/src/components/Editing/Editing.tsx index 43634f7fa6238fab3b0fb9e5d02089c821373a29..bf45f16d263e2ca57d84f170297ec9fd01ee42cf 100644 --- a/src/components/Editing/Editing.tsx +++ b/src/components/Editing/Editing.tsx @@ -1,6 +1,5 @@ import React, { useCallback, useContext, useEffect, useState } from 'react' import DateSelector from '../DateSelector/DateSelector' -import './editing.scss' import { MonthlyNewsService } from '../../services/monthlyNews.service' import { UserContext, UserContextProps } from '../../hooks/userContext' import { IMonthlyNews } from '../../models/monthlyNews.model' @@ -9,6 +8,7 @@ import MonthlyNews from '../MonthlyNews/MonthlyNews' import { IPoll } from '../../models/poll.model' import Loader from '../Loader/Loader' import Modal from '../Modal/Modal' +import './editing.scss' export type ContentItems = 'poll' | 'monthlyNews' | '' @@ -83,7 +83,10 @@ const Editing: React.FC = () => { } const isEmpty = (): boolean => { - if ((quote !== '' || header !== '') && isTouched) { + if ( + (quote !== '' || header !== '' || question !== '' || link !== '') && + isTouched + ) { return false } else return true } diff --git a/src/components/Editing/customEditor.scss b/src/components/Editing/customEditor.scss new file mode 100644 index 0000000000000000000000000000000000000000..133604b2aaed841161c482d5acad3c7b644495af --- /dev/null +++ b/src/components/Editing/customEditor.scss @@ -0,0 +1,16 @@ +@import '../../styles/config/colors'; + +.toolbar-class { + span, + li { + color: black; + } +} +.editor-class { + background: white; + padding: 0rem 1rem; + min-height: 100px; + span { + color: black; + } +} diff --git a/src/components/MonthlyNews/MonthlyNews.tsx b/src/components/MonthlyNews/MonthlyNews.tsx index 0d9c5ac6ab0c75665ef74e741339129eaa543fbf..921e698a7035054f514effec29e380683f39a9b7 100644 --- a/src/components/MonthlyNews/MonthlyNews.tsx +++ b/src/components/MonthlyNews/MonthlyNews.tsx @@ -1,6 +1,7 @@ -import { Editor } from '@tinymce/tinymce-react' import React from 'react' import { ContentItems } from '../Editing/Editing' +import { convertStringToEditorState } from '../../utils/editorStateManagment' +import CustomEditor from '../Editing/CustomEditor' interface MonthlyNewsProps { onSave: () => Promise<void> @@ -27,87 +28,21 @@ const MonthlyNews: React.FC<MonthlyNewsProps> = ({ <p className="title">Informations du mois</p> </div> <div> - <Editor - apiKey="2abhh1p06eeeybqtiohaz5u6pvqjk6kg3mh25acw56cknqeg" - init={{ - menubar: false, - toolbar: - 'undo redo | bold italic underline | alignleft aligncenter alignright | code | ecolyoLink', - }} - value={header} - onEditorChange={(newHeader: string) => - handleChange(newHeader, 'header') - } + <CustomEditor + baseState={convertStringToEditorState(header)} + handleChange={handleChange} + editorType="header" /> <div className="subtitle"> <p className="title">Citation du mois</p> </div> - - <Editor - apiKey="2abhh1p06eeeybqtiohaz5u6pvqjk6kg3mh25acw56cknqeg" - init={{ - menubar: false, - toolbar: - 'undo redo | bold italic underline | alignleft aligncenter alignright | code | ecolyoLink', - setup: function (editor) { - editor.ui.registry.addMenuButton('ecolyoLink', { - text: 'Lien Ecolyo', - fetch: function (callback) { - var items: any = [ - { - type: 'menuitem', - text: 'consumption', - onAction: function () { - editor.insertContent( - ' <a href="https://ecolyo.{cozyUrl}/consumption">page de consommation</a>' - ) - }, - }, - { - type: 'menuitem', - text: 'challenges', - onAction: function () { - editor.insertContent( - ' <a href="https://ecolyo.{cozyUrl}/challenges">page challenges</a>' - ) - }, - }, - { - type: 'menuitem', - text: 'ecogestures', - onAction: function () { - editor.insertContent( - ' <a href="https://ecolyo.{cozyUrl}/ecogestures">page ecogestures</a>' - ) - }, - }, - { - type: 'menuitem', - text: 'analysis', - onAction: function () { - editor.insertContent( - ' <a href="https://ecolyo.{cozyUrl}/analysis">page analyse</a>' - ) - }, - }, - { - type: 'menuitem', - text: 'options', - onAction: function () { - editor.insertContent( - ' <a href="https://ecolyo.{cozyUrl}/options">page options</a>' - ) - }, - }, - ] - callback(items) - }, - }) - }, - }} - value={quote} - onEditorChange={(newQuote: string) => handleChange(newQuote, 'quote')} - /> + <div> + <CustomEditor + baseState={convertStringToEditorState(quote)} + handleChange={handleChange} + editorType="quote" + /> + </div> <div className="buttons"> <button className="btnCancel" onClick={onCancel}> Annuler diff --git a/src/components/Poll/Poll.tsx b/src/components/Poll/Poll.tsx index 910860997d5cc3acc2b2a601536eaaa0c7b4258c..04e65e5bf973a5f53bc17342bf1438634bc3d016 100644 --- a/src/components/Poll/Poll.tsx +++ b/src/components/Poll/Poll.tsx @@ -1,6 +1,8 @@ -import { Editor } from '@tinymce/tinymce-react' import React, { ChangeEvent } from 'react' import { ContentItems } from '../Editing/Editing' +import CustomEditor from '../Editing/CustomEditor' +import { convertStringToEditorState } from '../../utils/editorStateManagment' +import 'react-draft-wysiwyg/dist/react-draft-wysiwyg.css' import './poll.scss' interface PollProps { @@ -14,6 +16,7 @@ interface PollProps { onCancel: () => void onDelete: (target: ContentItems) => void } + const Poll: React.FC<PollProps> = ({ question, link, @@ -38,19 +41,14 @@ const Poll: React.FC<PollProps> = ({ /> <div> <p className="title">Question</p> + <div> + <CustomEditor + baseState={convertStringToEditorState(question)} + handleChange={handleChange} + editorType="question" + /> + </div> - <Editor - apiKey="2abhh1p06eeeybqtiohaz5u6pvqjk6kg3mh25acw56cknqeg" - init={{ - menubar: false, - toolbar: - 'undo redo | bold italic underline | alignleft aligncenter alignright | code | ecolyoLink', - }} - value={question} - onEditorChange={(newQuestion: string) => - handleChange(newQuestion, 'question') - } - /> <div className="buttons"> <button className="btnCancel" onClick={onCancel}> Annuler diff --git a/src/utils/editorStateManagment.ts b/src/utils/editorStateManagment.ts new file mode 100644 index 0000000000000000000000000000000000000000..2102519ec5f6e3c72880c9e1aa3390767c5b2edb --- /dev/null +++ b/src/utils/editorStateManagment.ts @@ -0,0 +1,11 @@ +import { EditorState, convertFromHTML, ContentState } from 'draft-js' + +export const convertStringToEditorState = (string: string): EditorState => { + const blocksFromHTML = convertFromHTML(string) + const state = ContentState.createFromBlockArray( + blocksFromHTML.contentBlocks, + blocksFromHTML.entityMap + ) + const editorState = EditorState.createWithContent(state) + return editorState +} diff --git a/yarn.lock b/yarn.lock index 3dee9ec0ee0fe4530fe104b7fa88de773296ca30..6f5c6a82f04326b898136b33c2eb40b6bab6b21a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1534,6 +1534,14 @@ dependencies: "@babel/types" "^7.3.0" +"@types/draft-js@*", "@types/draft-js@^0.11.4": + version "0.11.4" + resolved "https://registry.yarnpkg.com/@types/draft-js/-/draft-js-0.11.4.tgz#96637c1d29dff1dcd6394d9ea0192867354691a1" + integrity sha512-T/z+wlf7rVloFdUsrNJV15DVbKvJbq44Lkf9WPTuS1g3Lqaqw83MzeFFZntPrKcsiCNBlHZQw+14PGW2rYN+fg== + dependencies: + "@types/react" "*" + immutable "~3.7.4" + "@types/eslint@^7.2.6": version "7.2.6" resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-7.2.6.tgz#5e9aff555a975596c03a98b59ecd103decc70c3c" @@ -1570,6 +1578,13 @@ version "5.1.1" resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-5.1.1.tgz#3c9ee980f1a10d6021ae6632ca3e79ca2ec4fb50" +"@types/html-to-draftjs@^1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@types/html-to-draftjs/-/html-to-draftjs-1.4.0.tgz#bfd712d3c5993e0644b76d2654adeae214678fae" + integrity sha512-w7Te62TAk2xkl+f/PRepVfaVbsArRYRACqH7Rv9H97gKqglQye3Cf8EArsKuSsN7vW6/zf1kTCsm/jnSR0gDQA== + dependencies: + "@types/draft-js" "*" + "@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": version "2.0.3" resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz#4ba8ddb720221f432e443bd5f9117fd22cfd4762" @@ -1637,13 +1652,12 @@ version "1.5.4" resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.4.tgz#15925414e0ad2cd765bfef58842f7e26a7accb24" -"@types/react-datepicker@^4.1.3": - version "4.1.3" - resolved "https://registry.yarnpkg.com/@types/react-datepicker/-/react-datepicker-4.1.3.tgz#bd9dad23cf2a7842c818af128b62c678e15790a7" +"@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: - "@types/react" "*" - date-fns "^2.0.1" - popper.js "^1.14.1" + parchment "^1.1.2" "@types/react-dom@^17.0.0": version "17.0.9" @@ -1651,6 +1665,14 @@ dependencies: "@types/react" "*" +"@types/react-draft-wysiwyg@^1.13.3": + version "1.13.3" + resolved "https://registry.yarnpkg.com/@types/react-draft-wysiwyg/-/react-draft-wysiwyg-1.13.3.tgz#044806edfcd3302c1039dd767bcc06e1467f7d26" + integrity sha512-njzkDqwIrEDUWz7Xzn2grlghu2PLlNf9PfOyGjQpUMOw5hwMEI3aQ6D4GUXBfGXaMv2nuheO4lu7Gu0cak5vmw== + dependencies: + "@types/draft-js" "*" + "@types/react" "*" + "@types/react-router-dom@^5.1.8": version "5.1.8" resolved "https://registry.yarnpkg.com/@types/react-router-dom/-/react-router-dom-5.1.8.tgz#bf3e1c8149b3d62eaa206d58599de82df0241192" @@ -2274,7 +2296,7 @@ arrify@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/arrify/-/arrify-2.0.1.tgz#c9655e9331e0abcd588d2a7cad7e9956f66701fa" -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" @@ -3022,6 +3044,11 @@ class-utils@^0.3.5: isobject "^3.0.0" static-extend "^0.1.1" +classnames@^2.2.6: + version "2.3.1" + resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.3.1.tgz#dfcfa3891e306ec1dad105d0e88f4417b8535e8e" + integrity sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA== + clean-css@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.2.3.tgz#507b5de7d97b48ee53d84adb0160ff6216380f78" @@ -3048,6 +3075,11 @@ cliui@^6.0.0: strip-ansi "^6.0.0" wrap-ansi "^6.2.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.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.1.1.tgz#98b3134f9abbdf23b2663491ace13c5c03a73188" @@ -3255,6 +3287,11 @@ core-js@^2.4.0: version "2.6.12" resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec" +core-js@^3.6.4: + version "3.16.1" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.16.1.tgz#f4485ce5c9f3c6a7cb18fa80488e08d362097249" + integrity sha512-AAkP8i35EbefU+JddyWi12AWE9f2N/qr/pwnDtWz4nyUIBGMJPX99ANFFRSw6FefM374lDujdtLDyhN2A/btHw== + core-js@^3.6.5: version "3.9.0" resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.9.0.tgz#790b1bb11553a2272b36e2625c7179db345492f8" @@ -3320,6 +3357,21 @@ create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: safe-buffer "^5.0.1" sha.js "^2.4.8" +create-react-class@^15.6.0: + version "15.7.0" + resolved "https://registry.yarnpkg.com/create-react-class/-/create-react-class-15.7.0.tgz#7499d7ca2e69bb51d13faf59bd04f0c65a1d6c1e" + integrity sha512-QZv4sFWG9S5RUvkTYWbflxeZX+JG7Cz0Tn33rQBJ+WFQTqTfUTjMjiv9tnfXazjsO5r0KhPs+AqCjyrQX6h2ng== + dependencies: + loose-envify "^1.3.1" + object-assign "^4.1.1" + +cross-fetch@^3.0.4: + version "3.1.4" + resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.4.tgz#9723f3a3a247bf8b89039f3a380a9244e8fa2f39" + integrity sha512-1eAtFWdIubi6T4XPy6ei9iUFoKpUkIF971QLN8lIvvvwueI65+Nw5haMNKUwfJxabqlIIDODJKGrQ66gxC0PbQ== + dependencies: + node-fetch "2.6.1" + cross-spawn@7.0.3, cross-spawn@^7.0.0, cross-spawn@^7.0.2: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" @@ -3584,10 +3636,6 @@ data-urls@^2.0.0: whatwg-mimetype "^2.3.0" whatwg-url "^8.0.0" -date-fns@^2.0.1: - version "2.23.0" - resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.23.0.tgz#4e886c941659af0cf7b30fafdd1eaa37e88788a9" - debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" @@ -3848,6 +3896,32 @@ dotenv@8.2.0: version "8.2.0" resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.2.0.tgz#97e619259ada750eea3e4ea3e26bceea5424b16a" +draft-js-export-html@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/draft-js-export-html/-/draft-js-export-html-1.4.1.tgz#7cdad970c6f7f2cdd19ce4c1f5073fdf0f313b4d" + integrity sha512-G4VGBSalPowktIE4wp3rFbhjs+Ln9IZ2FhXeHjsZDSw0a2+h+BjKu5Enq+mcsyVb51RW740GBK8Xbf7Iic51tw== + dependencies: + draft-js-utils "^1.4.0" + +draft-js-utils@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/draft-js-utils/-/draft-js-utils-1.4.0.tgz#c60af198108f69b0f1df3572555b23836819d1cf" + integrity sha512-8s9FFuKC+lOWGwJ0b3om2PF+uXrqQPaEQlPJI7UxdzxTYGMeKouMPA9+YlPn52zcAVElIZtd2tXj6eQmvlKelw== + +draft-js@^0.11.7: + version "0.11.7" + resolved "https://registry.yarnpkg.com/draft-js/-/draft-js-0.11.7.tgz#be293aaa255c46d8a6647f3860aa4c178484a206" + integrity sha512-ne7yFfN4sEL82QPQEn80xnADR8/Q6ALVworbC5UOSzOvjffmYfFsr3xSZtxbIirti14R7Y33EZC5rivpLgIbsg== + dependencies: + fbjs "^2.0.0" + immutable "~3.7.4" + object-assign "^4.1.1" + +draftjs-utils@^0.10.2: + version "0.10.2" + resolved "https://registry.yarnpkg.com/draftjs-utils/-/draftjs-utils-0.10.2.tgz#a7f16d2c1c174ac38ba3bbf700c256f176b2699c" + integrity sha512-EstHqr3R3JVcilJrBaO/A+01GvwwKmC7e4TCjC7S94ZeMh4IVmf60OuQXtHHpwItK8C2JCi3iljgN5KHkJboUg== + duplexer@^0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" @@ -4198,6 +4272,11 @@ eslint-plugin-react-hooks@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.2.0.tgz#8c229c268d468956334c943bb45fc860280f5556" +eslint-plugin-react-hooks@^4.2.1-alpha-e4e8226c6-20210812: + version "4.2.1-alpha-e4e8226c6-20210812" + resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.2.1-alpha-e4e8226c6-20210812.tgz#f6c8f3f35499007c6bd717a9dd443f3a95bd42d3" + integrity sha512-iONSu3S3H6L15EDmQGby+oEE7Qsrh8WLjeeDKhmoLWdIDXTDuDF0S3CXUBcFqMWQONdjZQvqn6Cl1XTbRQd8RQ== + eslint-plugin-react@^7.21.5: version "7.22.0" resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.22.0.tgz#3d1c542d1d3169c45421c1215d9470e341707269" @@ -4416,6 +4495,11 @@ etag@~1.8.1: version "1.8.1" resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" +eventemitter3@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-2.0.3.tgz#b5e1079b59fb5e1ba2771c0a993be060a58c99ba" + integrity sha1-teEHm1n7XhuidxwKmTvgYKWMmbo= + eventemitter3@^4.0.0: version "4.0.7" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" @@ -4548,7 +4632,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" @@ -4577,6 +4661,11 @@ fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" +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.1.2: version "1.2.0" resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" @@ -4618,6 +4707,25 @@ fb-watchman@^2.0.0: dependencies: bser "2.1.1" +fbjs-css-vars@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz#216551136ae02fe255932c3ec8775f18e2c078b8" + integrity sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ== + +fbjs@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-2.0.0.tgz#01fb812138d7e31831ed3e374afe27b9169ef442" + integrity sha512-8XA8ny9ifxrAWlyhAbexXcs3rRMtxWcs3M0lctLfB49jRDHiaxj+Mo0XxbwE7nKZYzgCFoq64FS+WFd4IycPPQ== + dependencies: + core-js "^3.6.4" + cross-fetch "^3.0.4" + fbjs-css-vars "^1.0.0" + 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.2" resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.2.tgz#b4eee8148abb01dcf1d1ac34367d59e12fa61d6e" @@ -5187,6 +5295,11 @@ html-minifier-terser@^5.0.1: relateurl "^0.2.7" terser "^4.6.3" +html-to-draftjs@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/html-to-draftjs/-/html-to-draftjs-1.5.0.tgz#0df0eabf429deaedb63f5c859889e2c983606e86" + integrity sha512-kggLXBNciKDwKf+KYsuE+V5gw4dZ7nHyGMX9m0wy7urzWjKGWyNFetmArRLvRV0VrxKN70WylFsJvMTJx02OBQ== + html-webpack-plugin@4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-4.5.0.tgz#625097650886b97ea5dae331c320e3238f6c121c" @@ -5320,6 +5433,11 @@ immer@8.0.1: version "8.0.1" resolved "https://registry.yarnpkg.com/immer/-/immer-8.0.1.tgz#9c73db683e2b3975c424fb0572af5889877ae656" +immutable@~3.7.4: + version "3.7.6" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-3.7.6.tgz#13b4d3cb12befa15482a26fe1b2ebae640071e4b" + integrity sha1-E7TTyxK++hVIKib+Gy665kAHHks= + import-cwd@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/import-cwd/-/import-cwd-2.1.0.tgz#aa6cf36e722761285cb371ec6519f53e2435b0a9" @@ -6399,6 +6517,13 @@ lines-and-columns@^1.1.6: version "1.1.6" resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" +linkify-it@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-2.2.0.tgz#e3b54697e78bf915c70a38acd78fd09e0058b1cf" + integrity sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw== + dependencies: + uc.micro "^1.0.1" + load-json-file@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8" @@ -6506,7 +6631,7 @@ lodash.uniq@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" -"lodash@>=3.5 <5", lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.5: +"lodash@>=3.5 <5", lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.4, lodash@^4.17.5: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" @@ -6514,7 +6639,7 @@ loglevel@^1.6.8: version "1.7.1" resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.7.1.tgz#005fde2f5e6e47068f935ff28573e125ef72f197" -loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3.1, loose-envify@^1.4.0: +loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3.1, loose-envify@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" dependencies: @@ -6881,6 +7006,11 @@ no-case@^3.0.4: lower-case "^2.0.2" tslib "^2.0.3" +node-fetch@2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" + integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== + node-forge@^0.10.0: version "0.10.0" resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.10.0.tgz#32dea2afb3e9926f02ee5ce8794902691a676bf3" @@ -7270,6 +7400,11 @@ param-case@^3.0.3: dot-case "^3.0.4" tslib "^2.0.3" +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" @@ -7471,10 +7606,6 @@ pnp-webpack-plugin@1.6.4: dependencies: ts-pnp "^1.1.6" -popper.js@^1.14.1: - version "1.16.1" - resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.16.1.tgz#2a223cb3dc7b6213d740e40372be40de43e65b1b" - portfinder@^1.0.26: version "1.0.28" resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.28.tgz#67c4622852bd5374dd1dd900f779f53462fac778" @@ -8140,6 +8271,13 @@ promise-inflight@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" +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" + promise@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/promise/-/promise-8.1.0.tgz#697c25c3dfe7435dd79fcd58c38a135888eaf05e" @@ -8153,7 +8291,7 @@ prompts@2.4.0, prompts@^2.0.1: kleur "^3.0.3" sisteransi "^1.0.5" -prop-types@^15.6.2, prop-types@^15.7.2: +prop-types@^15.5.10, prop-types@^15.6.2, prop-types@^15.7.2: version "15.7.2" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" dependencies: @@ -8260,6 +8398,27 @@ queue-microtask@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.2.tgz#abf64491e6ecf0f38a6502403d4cda04f372dfd3" +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@^1.3.7: + 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" @@ -8332,6 +8491,11 @@ react-dev-utils@^11.0.3: strip-ansi "6.0.0" text-table "0.2.0" +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@^17.0.2: version "17.0.2" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.2.tgz#ecffb6845e3ad8dbfcdc498f0d0a939736502c23" @@ -8340,6 +8504,17 @@ react-dom@^17.0.2: object-assign "^4.1.1" scheduler "^0.20.2" +react-draft-wysiwyg@^1.14.7: + version "1.14.7" + resolved "https://registry.yarnpkg.com/react-draft-wysiwyg/-/react-draft-wysiwyg-1.14.7.tgz#5d27fe8ad87de7c692dad739b8787f3ac1f3c24e" + integrity sha512-D4X8F/ourvQZuqHzCQ6Vs6Tnt6TbGH58kvHQxC+aZGq+45ko2EyatL6G5C/paMaNKDZq2JRe7yAzykneMLpNOg== + dependencies: + classnames "^2.2.6" + draftjs-utils "^0.10.2" + html-to-draftjs "^1.5.0" + linkify-it "^2.2.0" + prop-types "^15.7.2" + react-error-overlay@^6.0.9: version "6.0.9" resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.9.tgz#3c743010c9359608c375ecd6bc76f35d93995b0a" @@ -8354,6 +8529,18 @@ react-is@^17.0.1: resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.1.tgz#5b3531bd76a645a4c9fb6e693ed36419e3301339" integrity sha512-NAnt2iGDXohE5LI7uBnLnqvLQMtzhkiAOLXTmv+qnF9Ky7xAPcX8Up/xWIhxvLVGJvuLiNc4xQLtuqDRzb4fSA== +react-quill@^1.3.5: + version "1.3.5" + resolved "https://registry.yarnpkg.com/react-quill/-/react-quill-1.3.5.tgz#8c4ad759da03365b17c79c6c52afa9772259844e" + integrity sha512-/W/rNCW+6QpGz8yQ9tFK5Ka/h/No1RqrcOOvCIOR092OiKzRFlU2xbPEwiP3Wgy/Dx13pi1YhjReDMX/5uotJg== + dependencies: + "@types/quill" "1.3.10" + create-react-class "^15.6.0" + lodash "^4.17.4" + prop-types "^15.5.10" + quill "^1.3.7" + react-dom-factories "^1.0.0" + react-refresh@^0.8.3: version "0.8.3" resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.8.3.tgz#721d4657672d400c5e3c75d063c4a85fb2d5d68f" @@ -9072,7 +9259,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" @@ -9938,6 +10125,16 @@ typescript@^4.1.2: version "4.3.5" resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.3.5.tgz#4d1c37cc16e893973c45a06886b7113234f119f4" +ua-parser-js@^0.7.18: + version "0.7.28" + resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.28.tgz#8ba04e653f35ce210239c64661685bf9121dec31" + integrity sha512-6Gurc1n//gjp9eQNXjD9O3M/sMwVtN5S8Lv9bvOYBfKfDNiIIhqiyi01vMBO45u4zkDE420w/e0se7Vs+sIg+g== + +uc.micro@^1.0.1: + version "1.0.6" + resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.6.tgz#9c411a802a409a91fc6cf74081baba34b24499ac" + integrity sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA== + unbox-primitive@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.1.tgz#085e215625ec3162574dc8859abee78a59b14471"