From 33c778f5f321f939a69162ca9368086b6c1c7455 Mon Sep 17 00:00:00 2001 From: Kurt Hutten Date: Thu, 15 Oct 2020 08:05:35 +1100 Subject: [PATCH 1/6] Add basic styling to parts page --- web/src/components/Parts/Parts.js | 75 +++++++--------------- web/src/index.css | 5 ++ web/src/layouts/MainLayout/MainLayout.js | 11 +++- web/src/layouts/PartsLayout/PartsLayout.js | 18 +----- web/src/layouts/PostsLayout/PostsLayout.js | 2 +- 5 files changed, 41 insertions(+), 70 deletions(-) diff --git a/web/src/components/Parts/Parts.js b/web/src/components/Parts/Parts.js index c868554..21f66bc 100644 --- a/web/src/components/Parts/Parts.js +++ b/web/src/components/Parts/Parts.js @@ -1,6 +1,8 @@ import { useMutation, useFlash } from '@redwoodjs/web' import { Link, routes } from '@redwoodjs/router' +import avatar from 'src/assets/harold.jpg' + const DELETE_PART_MUTATION = gql` mutation DeletePartMutation($id: Int!) { deletePart(id: $id) { @@ -50,58 +52,27 @@ const PartsList = ({ parts }) => { } return ( -
- - - - - - - - - - - - - - {parts.map((part) => ( - - - - - - - - - - ))} - -
IdTitleDescriptionCodeMain imageCreated at 
{truncate(part.id)}{truncate(part.title)}{truncate(part.description)}{truncate(part.code)}{truncate(part.mainImage)}{timeTag(part.createdAt)} - -
+
+ {parts.map((part) => { + return ( + +
+
+
?
+
+

{part.title}

+
+
+ +
+
+ + )})}
) } diff --git a/web/src/index.css b/web/src/index.css index 9939187..862eccf 100644 --- a/web/src/index.css +++ b/web/src/index.css @@ -12,6 +12,11 @@ * END --- TAILWIND GENERATOR EDIT */ +body { + /* TODO can I use a tailwind class here? */ + background-color: #4a5568; +} + button, input, label, textarea { display: block; outline: none; diff --git a/web/src/layouts/MainLayout/MainLayout.js b/web/src/layouts/MainLayout/MainLayout.js index f5bdb7d..685985f 100644 --- a/web/src/layouts/MainLayout/MainLayout.js +++ b/web/src/layouts/MainLayout/MainLayout.js @@ -1,8 +1,10 @@ import { Link, routes } from '@redwoodjs/router' import { useAuth } from '@redwoodjs/auth' +import { Flash } from '@redwoodjs/web' +import Tooltip from '@material-ui/core/Tooltip'; + import avatar from 'src/assets/harold.jpg' import Svg from 'src/components/Svg' -import Tooltip from '@material-ui/core/Tooltip'; const MainLayout = ({ children }) => { const { logIn, logOut, isAuthenticated } = useAuth() @@ -28,11 +30,16 @@ const MainLayout = ({ children }) => { +
{children}
) diff --git a/web/src/layouts/PartsLayout/PartsLayout.js b/web/src/layouts/PartsLayout/PartsLayout.js index f0ecd0c..7234e1d 100644 --- a/web/src/layouts/PartsLayout/PartsLayout.js +++ b/web/src/layouts/PartsLayout/PartsLayout.js @@ -1,21 +1,9 @@ -import { Link, routes } from '@redwoodjs/router' -import { Flash } from '@redwoodjs/web' + const PartsLayout = (props) => { return ( -
- -
-

- - Parts - -

- -
+
New Part - -
-
{props.children}
+
+
{props.children}
) } diff --git a/web/src/layouts/PostsLayout/PostsLayout.js b/web/src/layouts/PostsLayout/PostsLayout.js index b08e8fa..45578ce 100644 --- a/web/src/layouts/PostsLayout/PostsLayout.js +++ b/web/src/layouts/PostsLayout/PostsLayout.js @@ -15,7 +15,7 @@ const PostsLayout = (props) => {
+
New Post -
{props.children}
+
{props.children}
) } From 2df4ac0d57ddb0979d749bd475a02296bc0bd145 Mon Sep 17 00:00:00 2001 From: Kurt Hutten Date: Fri, 16 Oct 2020 16:43:29 +1100 Subject: [PATCH 2/6] Add basic part page --- web/package.json | 2 + web/src/Routes.js | 1 + web/src/components/IdePartCell/IdePartCell.js | 46 ++ .../IdePartCell/IdePartCell.mock.js | 6 + .../IdePartCell/IdePartCell.stories.js | 20 + .../IdePartCell/IdePartCell.test.js | 26 ++ web/src/components/PartCell/PartCell.js | 62 ++- web/src/pages/IdePartPage/IdePartPage.js | 13 + .../pages/IdePartPage/IdePartPage.stories.js | 7 + web/src/pages/IdePartPage/IdePartPage.test.js | 11 + web/tailwind.config.js | 12 +- yarn.lock | 401 +++++++++++++++++- 12 files changed, 559 insertions(+), 48 deletions(-) create mode 100644 web/src/components/IdePartCell/IdePartCell.js create mode 100644 web/src/components/IdePartCell/IdePartCell.mock.js create mode 100644 web/src/components/IdePartCell/IdePartCell.stories.js create mode 100644 web/src/components/IdePartCell/IdePartCell.test.js create mode 100644 web/src/pages/IdePartPage/IdePartPage.js create mode 100644 web/src/pages/IdePartPage/IdePartPage.stories.js create mode 100644 web/src/pages/IdePartPage/IdePartPage.test.js diff --git a/web/package.json b/web/package.json index beb4868..db3c665 100644 --- a/web/package.json +++ b/web/package.json @@ -28,6 +28,8 @@ "prop-types": "^15.7.2", "react": "^16.13.1", "react-dom": "^16.13.1", + "rich-markdown-editor": "^11.0.2", + "styled-components": "^5.2.0", "three": "^0.118.3" }, "devDependencies": { diff --git a/web/src/Routes.js b/web/src/Routes.js index 9fa6d36..200ecb1 100644 --- a/web/src/Routes.js +++ b/web/src/Routes.js @@ -15,6 +15,7 @@ const Routes = () => { + diff --git a/web/src/components/IdePartCell/IdePartCell.js b/web/src/components/IdePartCell/IdePartCell.js new file mode 100644 index 0000000..3b95c0b --- /dev/null +++ b/web/src/components/IdePartCell/IdePartCell.js @@ -0,0 +1,46 @@ +import { useMutation, useFlash } from '@redwoodjs/web' +import { navigate, routes } from '@redwoodjs/router' +import Part from 'src/components/Part' + +export const QUERY = gql` + query FIND_PART_BY_ID($id: Int!) { + part: part(id: $id) { + id + title + description + code + mainImage + createdAt + } + } +` + +const UPDATE_PART_MUTATION = gql` + mutation UpdatePartMutation($id: Int!, $input: UpdatePartInput!) { + updatePart(id: $id, input: $input) { + id + } + } +` + +export const Loading = () =>
Loading...
+ +export const Empty = () =>
Part not found
+ +export const Success = ({ part }) => { + const { addMessage } = useFlash() + const [updatePart, { loading, error }] = useMutation(UPDATE_PART_MUTATION, { + onCompleted: () => { + // navigate(routes.part({id: updatePart.id})) + addMessage('Part updated.', { classes: 'rw-flash-success' }) + }, + }) + console.log({updatePart}) + + + const saveCode = (input, id) => { + console.log(id, input, 'wowow') + updatePart({ variables: { id, input } }) + } + return +} diff --git a/web/src/components/IdePartCell/IdePartCell.mock.js b/web/src/components/IdePartCell/IdePartCell.mock.js new file mode 100644 index 0000000..b267638 --- /dev/null +++ b/web/src/components/IdePartCell/IdePartCell.mock.js @@ -0,0 +1,6 @@ +// Define your own mock data here: +export const standard = (/* vars, { ctx, req } */) => ({ + idePart: { + id: 42, + }, +}) diff --git a/web/src/components/IdePartCell/IdePartCell.stories.js b/web/src/components/IdePartCell/IdePartCell.stories.js new file mode 100644 index 0000000..0a2b0d7 --- /dev/null +++ b/web/src/components/IdePartCell/IdePartCell.stories.js @@ -0,0 +1,20 @@ +import { Loading, Empty, Failure, Success } from './IdePartCell' +import { standard } from './IdePartCell.mock' + +export const loading = () => { + return Loading ? : null +} + +export const empty = () => { + return Empty ? : null +} + +export const failure = () => { + return Failure ? : null +} + +export const success = () => { + return Success ? : null +} + +export default { title: 'Cells/IdePartCell' } diff --git a/web/src/components/IdePartCell/IdePartCell.test.js b/web/src/components/IdePartCell/IdePartCell.test.js new file mode 100644 index 0000000..a5f77fc --- /dev/null +++ b/web/src/components/IdePartCell/IdePartCell.test.js @@ -0,0 +1,26 @@ +import { render, screen } from '@redwoodjs/testing' +import { Loading, Empty, Failure, Success } from './IdePartCell' +import { standard } from './IdePartCell.mock' + +describe('IdePartCell', () => { + test('Loading renders successfully', () => { + render() + // Use screen.debug() to see output + expect(screen.getByText('Loading...')).toBeInTheDocument() + }) + + test('Empty renders successfully', async () => { + render() + expect(screen.getByText('Empty')).toBeInTheDocument() + }) + + test('Failure renders successfully', async () => { + render() + expect(screen.getByText(/Oh no/i)).toBeInTheDocument() + }) + + test('Success renders successfully', async () => { + render() + expect(screen.getByText(/42/i)).toBeInTheDocument() + }) +}) diff --git a/web/src/components/PartCell/PartCell.js b/web/src/components/PartCell/PartCell.js index 3b95c0b..2efcdcc 100644 --- a/web/src/components/PartCell/PartCell.js +++ b/web/src/components/PartCell/PartCell.js @@ -1,46 +1,32 @@ -import { useMutation, useFlash } from '@redwoodjs/web' -import { navigate, routes } from '@redwoodjs/router' -import Part from 'src/components/Part' -export const QUERY = gql` - query FIND_PART_BY_ID($id: Int!) { - part: part(id: $id) { - id - title - description - code - mainImage - createdAt - } - } -` +import {QUERY as reExportQuery} from 'src/components/EditPartCell' +import Editor from "rich-markdown-editor"; -const UPDATE_PART_MUTATION = gql` - mutation UpdatePartMutation($id: Int!, $input: UpdatePartInput!) { - updatePart(id: $id, input: $input) { - id - } - } -` +export const QUERY = reExportQuery export const Loading = () =>
Loading...
-export const Empty = () =>
Part not found
+export const Empty = () =>
Empty
+ +export const Failure = ({ error }) =>
Error: {error.message}
export const Success = ({ part }) => { - const { addMessage } = useFlash() - const [updatePart, { loading, error }] = useMutation(UPDATE_PART_MUTATION, { - onCompleted: () => { - // navigate(routes.part({id: updatePart.id})) - addMessage('Part updated.', { classes: 'rw-flash-success' }) - }, - }) - console.log({updatePart}) - - - const saveCode = (input, id) => { - console.log(id, input, 'wowow') - updatePart({ variables: { id, input } }) - } - return + console.log(part) + return ( + <> +
+
+ +
+
+

{part.title}

+ +
+
+ + ) } diff --git a/web/src/pages/IdePartPage/IdePartPage.js b/web/src/pages/IdePartPage/IdePartPage.js new file mode 100644 index 0000000..7b33264 --- /dev/null +++ b/web/src/pages/IdePartPage/IdePartPage.js @@ -0,0 +1,13 @@ +import { Link, routes } from '@redwoodjs/router' +import MainLayout from 'src/layouts/MainLayout' +import IdePartCell from 'src/components/IdePartCell' + +const IdePartPage = ({id}) => { + return ( + + + + ) +} + +export default IdePartPage diff --git a/web/src/pages/IdePartPage/IdePartPage.stories.js b/web/src/pages/IdePartPage/IdePartPage.stories.js new file mode 100644 index 0000000..6bfa9a4 --- /dev/null +++ b/web/src/pages/IdePartPage/IdePartPage.stories.js @@ -0,0 +1,7 @@ +import IdePartPage from './IdePartPage' + +export const generated = () => { + return +} + +export default { title: 'Pages/IdePartPage' } diff --git a/web/src/pages/IdePartPage/IdePartPage.test.js b/web/src/pages/IdePartPage/IdePartPage.test.js new file mode 100644 index 0000000..e3a9b48 --- /dev/null +++ b/web/src/pages/IdePartPage/IdePartPage.test.js @@ -0,0 +1,11 @@ +import { render } from '@redwoodjs/testing' + +import IdePartPage from './IdePartPage' + +describe('IdePartPage', () => { + it('renders successfully', () => { + expect(() => { + render() + }).not.toThrow() + }) +}) diff --git a/web/tailwind.config.js b/web/tailwind.config.js index 2eb9e2b..a0a2d0a 100644 --- a/web/tailwind.config.js +++ b/web/tailwind.config.js @@ -7,7 +7,17 @@ module.exports = { }, purge: [], theme: { - extend: {} + extend: { + maxWidth: { + '7xl': '80rem', + '8xl': '96rem', + '9xl': '110rem', + }, + minHeight: { + 'md': '28rem' + }, + + } }, variants: {}, plugins: [] diff --git a/yarn.lock b/yarn.lock index ff37166..6f2eb0a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -223,7 +223,16 @@ jsesc "^2.5.1" source-map "^0.5.0" -"@babel/helper-annotate-as-pure@^7.10.4": +"@babel/generator@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.12.1.tgz#0d70be32bdaa03d7c51c8597dda76e0df1f15468" + integrity sha512-DB+6rafIdc9o72Yc3/Ph5h+6hUjeOp66pF0naQBgUFFuPqzQwIlPTm3xZR7YNvduIMtkDIj2t21LSQwnbCrXvg== + dependencies: + "@babel/types" "^7.12.1" + jsesc "^2.5.1" + source-map "^0.5.0" + +"@babel/helper-annotate-as-pure@^7.0.0", "@babel/helper-annotate-as-pure@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.10.4.tgz#5bf0d495a3f757ac3bda48b5bf3b3ba309c72ba3" integrity sha512-XQlqKQP4vXFB7BN8fEEerrmYvHp3fK/rBkRFz9jaJbzK0B1DSfej9Kc7ZzE8Z/OnId1jpJdNAZ3BFQjWG68rcA== @@ -473,6 +482,11 @@ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.11.0.tgz#a9d7e11aead25d3b422d17b2c6502c8dddef6a5d" integrity sha512-qvRvi4oI8xii8NllyEc4MDJjuZiNaRzyb7Y7lup1NqJV8TZHF4O27CcP+72WPn/k1zkgJ6WJfnIbk4jTsVAZHw== +"@babel/parser@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.12.1.tgz#dc03f543a0ed51396d4081463df66ecb3a2efa53" + integrity sha512-xjZsx0sBjb6J2+QkoHI69UeD2EWbsyUW0WyZKOoJ9sBrQLxfOApWEefR9dIVOYJVj97VRXnLKLDvnn3dPDNgww== + "@babel/plugin-proposal-async-generator-functions@^7.10.4": version "7.10.5" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.10.5.tgz#3491cabf2f7c179ab820606cec27fed15e0e8558" @@ -1309,6 +1323,21 @@ globals "^11.1.0" lodash "^4.17.19" +"@babel/traverse@^7.4.5": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.12.1.tgz#941395e0c5cc86d5d3e75caa095d3924526f0c1e" + integrity sha512-MA3WPoRt1ZHo2ZmoGKNqi20YnPt0B1S0GTZEPhhd+hw2KGUzBlHuVunj6K4sNuK+reEvyiPwtp0cpaqLzJDmAw== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/generator" "^7.12.1" + "@babel/helper-function-name" "^7.10.4" + "@babel/helper-split-export-declaration" "^7.11.0" + "@babel/parser" "^7.12.1" + "@babel/types" "^7.12.1" + debug "^4.1.0" + globals "^11.1.0" + lodash "^4.17.19" + "@babel/types@7.11.5", "@babel/types@^7.11.5": version "7.11.5" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.11.5.tgz#d9de577d01252d77c6800cee039ee64faf75662d" @@ -1327,6 +1356,15 @@ lodash "^4.17.19" to-fast-properties "^2.0.0" +"@babel/types@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.12.1.tgz#e109d9ab99a8de735be287ee3d6a9947a190c4ae" + integrity sha512-BzSY3NJBKM4kyatSOWh3D/JJ2O3CVzBybHWxtgxnggaxEuaSTTDqeiSb/xk9lrkw2Tbqyivw5ZU4rT+EfznQsA== + dependencies: + "@babel/helper-validator-identifier" "^7.10.4" + lodash "^4.17.19" + to-fast-properties "^2.0.0" + "@bcoe/v8-coverage@^0.2.3": version "0.2.3" resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" @@ -1384,7 +1422,7 @@ resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.8.0.tgz#bbbff68978fefdbe68ccb533bc8cbe1d1afb5413" integrity sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow== -"@emotion/is-prop-valid@0.8.8": +"@emotion/is-prop-valid@0.8.8", "@emotion/is-prop-valid@^0.8.8": version "0.8.8" resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz#db28b1c4368a259b60a97311d6a952d4fd01ac1a" integrity sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA== @@ -1430,12 +1468,12 @@ "@emotion/styled-base" "^10.0.27" babel-plugin-emotion "^10.0.27" -"@emotion/stylis@0.8.5": +"@emotion/stylis@0.8.5", "@emotion/stylis@^0.8.4": version "0.8.5" resolved "https://registry.yarnpkg.com/@emotion/stylis/-/stylis-0.8.5.tgz#deacb389bd6ee77d1e7fcaccce9e16c5c7e78e04" integrity sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ== -"@emotion/unitless@0.7.5": +"@emotion/unitless@0.7.5", "@emotion/unitless@^0.7.4": version "0.7.5" resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.7.5.tgz#77211291c1900a700b8a78cfafda3160d76949ed" integrity sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg== @@ -3152,6 +3190,13 @@ "@types/koa" "*" graphql "^14.5.3" +"@types/hast@^2.0.0": + version "2.3.1" + resolved "https://registry.yarnpkg.com/@types/hast/-/hast-2.3.1.tgz#b16872f2a6144c7025f296fb9636a667ebb79cd9" + integrity sha512-viwwrB+6xGzw+G1eWpF9geV3fnsDgXqHG+cqgiHrvQfDUW5hzhCyV7Sy3UJxhfRFBsgky2SSW33qi/YrIkjX5Q== + dependencies: + "@types/unist" "*" + "@types/history@*": version "4.7.7" resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.7.tgz#613957d900fab9ff84c8dfb24fa3eef0c2a40896" @@ -3440,6 +3485,11 @@ dependencies: source-map "^0.6.1" +"@types/unist@*": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.3.tgz#9c088679876f374eb5983f150d4787aa6fb32d7e" + integrity sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ== + "@types/webpack-env@^1.15.0": version "1.15.2" resolved "https://registry.yarnpkg.com/@types/webpack-env/-/webpack-env-1.15.2.tgz#927997342bb9f4a5185a86e6579a0a18afc33b0a" @@ -4795,6 +4845,16 @@ babel-plugin-react-docgen@^4.0.0: react-docgen "^5.0.0" recast "^0.14.7" +"babel-plugin-styled-components@>= 1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/babel-plugin-styled-components/-/babel-plugin-styled-components-1.11.1.tgz#5296a9e557d736c3186be079fff27c6665d63d76" + integrity sha512-YwrInHyKUk1PU3avIRdiLyCpM++18Rs1NgyMXEAQC33rIXs/vro0A+stf4sT0Gf22Got+xRWB8Cm0tw+qkRzBA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.0.0" + "@babel/helper-module-imports" "^7.0.0" + babel-plugin-syntax-jsx "^6.18.0" + lodash "^4.17.11" + babel-plugin-syntax-jsx@^6.18.0: version "6.18.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz#0af32a9a6e13ca7a3fd5069e62d7b0f58d0d8946" @@ -5453,6 +5513,11 @@ camelcase@^6.0.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.0.0.tgz#5259f7c30e35e278f1bdc2a4d91230b37cad981e" integrity sha512-8KMDF1Vz2gzOq54ONPJS65IvTUaB1cHJ2DMM7MbPmLZljDH1qpzzLsWdiN9pHh6qvkRVDTi/07+eNGch/oLU4w== +camelize@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/camelize/-/camelize-1.0.0.tgz#164a5483e630fa4321e5af07020e531831b2609b" + integrity sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs= + can-use-dom@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/can-use-dom/-/can-use-dom-0.1.0.tgz#22cc4a34a0abc43950f42c6411024a3f6366b45a" @@ -5936,6 +6001,11 @@ compression@^1.7.4: safe-buffer "5.1.2" vary "~1.1.2" +compute-scroll-into-view@^1.0.16: + version "1.0.16" + resolved "https://registry.yarnpkg.com/compute-scroll-into-view/-/compute-scroll-into-view-1.0.16.tgz#5b7bf4f7127ea2c19b750353d7ce6776a90ee088" + integrity sha512-a85LHKY81oQnikatZYA90pufpZ6sQx++BoCxOEMsjpZx+ZnaKGQnCyCehTRr/1p9GBIAHTjcU9k71kSYWloLiQ== + concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -6254,6 +6324,11 @@ crypto-random-string@^2.0.0: resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5" integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA== +css-color-keywords@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/css-color-keywords/-/css-color-keywords-1.0.0.tgz#fea2616dc676b2962686b3af8dbdbe180b244e05" + integrity sha1-/qJhbcZ2spYmhrOvjb2+GAskTgU= + css-loader@^3.0.0: version "3.6.0" resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-3.6.0.tgz#2e4b2c7e6e2d27f8c8f28f61bffcd2e6c91ef645" @@ -6316,6 +6391,15 @@ css-select@^2.0.0: domutils "^1.7.0" nth-check "^1.0.2" +css-to-react-native@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/css-to-react-native/-/css-to-react-native-3.0.0.tgz#62dbe678072a824a689bcfee011fc96e02a7d756" + integrity sha512-Ro1yETZA813eoyUp2GDBhG2j+YggidUmzO1/v9eYBKR2EHVEniE2MI/NqpTQ954BMpTPZFsGNPm46qFB9dpaPQ== + dependencies: + camelize "^1.0.0" + css-color-keywords "^1.0.0" + postcss-value-parser "^4.0.2" + css-tree@1.0.0-alpha.37: version "1.0.0-alpha.37" resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.37.tgz#98bebd62c4c1d9f960ec340cf9f7522e30709a22" @@ -7063,7 +7147,7 @@ entities@^1.1.1, entities@^1.1.2: resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56" integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w== -entities@^2.0.0: +entities@^2.0.0, entities@~2.0.0: version "2.0.3" resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.3.tgz#5c487e5742ab93c15abb5da22759b8590ec03b7f" integrity sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ== @@ -8675,6 +8759,17 @@ hastscript@^5.0.0: property-information "^5.0.0" space-separated-tokens "^1.0.0" +hastscript@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/hastscript/-/hastscript-6.0.0.tgz#e8768d7eac56c3fdeac8a92830d58e811e5bf640" + integrity sha512-nDM6bvd7lIqDUiYEiu5Sl/+6ReP0BMk/2f4U/Rooccxkj0P5nm+acM5PrGJ/t5I8qPGiqZSE6hVAwZEdZIvP4w== + dependencies: + "@types/hast" "^2.0.0" + comma-separated-tokens "^1.0.0" + hast-util-parse-selector "^2.0.0" + property-information "^5.0.0" + space-separated-tokens "^1.0.0" + he@^1.1.0, he@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" @@ -8699,7 +8794,7 @@ hmac-drbg@^1.0.0: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.1" -hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2: +hoist-non-react-statics@^3.0.0, hoist-non-react-statics@^3.3.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== @@ -10527,6 +10622,13 @@ lines-and-columns@^1.1.6: resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA= +linkify-it@^2.0.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" + listr-silent-renderer@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz#924b5a3757153770bf1a8e3fbf74b8bbf3f9242e" @@ -10899,6 +11001,22 @@ map-visit@^1.0.0: dependencies: object-visit "^1.0.0" +markdown-it-container@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/markdown-it-container/-/markdown-it-container-3.0.0.tgz#1d19b06040a020f9a827577bb7dbf67aa5de9a5b" + integrity sha512-y6oKTq4BB9OQuY/KLfk/O3ysFhB3IMYoIWhGJEidXt1NQFocFK2sA2t0NYZAMyMShAGL6x5OPIbrmXPIqaN9rw== + +markdown-it@^10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-10.0.0.tgz#abfc64f141b1722d663402044e43927f1f50a8dc" + integrity sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg== + dependencies: + argparse "^1.0.7" + entities "~2.0.0" + linkify-it "^2.0.0" + mdurl "^1.0.1" + uc.micro "^1.0.5" + markdown-to-jsx@^6.11.4: version "6.11.4" resolved "https://registry.yarnpkg.com/markdown-to-jsx/-/markdown-to-jsx-6.11.4.tgz#b4528b1ab668aef7fe61c1535c27e837819392c5" @@ -10926,6 +11044,11 @@ mdn-data@2.0.6: resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.6.tgz#852dc60fcaa5daa2e8cf6c9189c440ed3e042978" integrity sha512-rQvjv71olwNHgiTbfPZFkJtjNMciWgswYeciZhtvWLO8bmX3TnhyA62I6sTWOyZssWHJJjY6/KiWwqQsWWsqOA== +mdurl@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" + integrity sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4= + media-typer@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" @@ -11807,6 +11930,11 @@ optionator@^0.9.1: type-check "^0.4.0" word-wrap "^1.2.3" +orderedmap@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/orderedmap/-/orderedmap-1.1.1.tgz#c618e77611b3b21d0fe3edc92586265e0059c789" + integrity sha512-3Ux8um0zXbVacKUkcytc0u3HgC0b0bBLT+I60r2J/En72cI0nZffqrA7Xtf2Hqs27j1g82llR5Mhbd0Z1XW4AQ== + original@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/original/-/original-1.0.2.tgz#e442a61cffe1c5fd20a65f3261c26663b303f25f" @@ -11824,6 +11952,11 @@ os-tmpdir@~1.0.2: resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= +outline-icons@^1.21.0-3: + version "1.21.0-6" + resolved "https://registry.yarnpkg.com/outline-icons/-/outline-icons-1.21.0-6.tgz#bbf63fe6cc88ca2fe391e6ba6cc8b62a948607e3" + integrity sha512-iEVK2zTEZ3sLFLsko/V6z3AEiM2EAjEUyLIOzAT2cqRglIbaIWdyitotKVMb2hWZo66bSvHxA/Rdvv51sw5RhA== + p-each-series@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/p-each-series/-/p-each-series-2.1.0.tgz#961c8dd3f195ea96c747e636b262b800a6b1af48" @@ -11995,6 +12128,18 @@ parse-entities@^1.1.2: is-decimal "^1.0.0" is-hexadecimal "^1.0.0" +parse-entities@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-2.0.0.tgz#53c6eb5b9314a1f4ec99fa0fdf7ce01ecda0cbe8" + integrity sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ== + dependencies: + character-entities "^1.0.0" + character-entities-legacy "^1.0.0" + character-reference-invalid "^1.0.0" + is-alphanumerical "^1.0.0" + is-decimal "^1.0.0" + is-hexadecimal "^1.0.0" + parse-json@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" @@ -12364,7 +12509,7 @@ postcss-value-parser@^3.3.0: resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281" integrity sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ== -postcss-value-parser@^4.1.0: +postcss-value-parser@^4.0.2, postcss-value-parser@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz#443f6a20ced6481a2bda4fa8532a6e55d789a2cb" integrity sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ== @@ -12476,6 +12621,13 @@ prettysize@^2.0.0: resolved "https://registry.yarnpkg.com/prettysize/-/prettysize-2.0.0.tgz#902c02480d865d9cc0813011c9feb4fa02ce6996" integrity sha512-VVtxR7sOh0VsG8o06Ttq5TrI1aiZKmC+ClSn4eBPaNf4SHr5lzbYW+kYGX3HocBL/MfpVrRfFZ9V3vCbLaiplg== +prismjs@^1.19.0, prismjs@~1.22.0: + version "1.22.0" + resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.22.0.tgz#73c3400afc58a823dd7eed023f8e1ce9fd8977fa" + integrity sha512-lLJ/Wt9yy0AiSYBf212kK3mM5L8ycwlyTlSxHBAneXLR0nzFMlZ5y7riFPF3E33zXOF2IH95xdY5jIyZbM9z/w== + optionalDependencies: + clipboard "^2.0.0" + prismjs@^1.8.4: version "1.20.0" resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.20.0.tgz#9b685fc480a3514ee7198eac6a3bf5024319ff03" @@ -12550,7 +12702,7 @@ prompts@^2.0.1: kleur "^3.0.3" sisteransi "^1.0.4" -prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2: +prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1, 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" integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== @@ -12571,6 +12723,129 @@ proptypes@^1.1.0: resolved "https://registry.yarnpkg.com/proptypes/-/proptypes-1.1.0.tgz#78b3828a5aa6bb1308939e0de3c6044dfd4bd239" integrity sha1-eLOCilqmuxMIk54N48YETf1L0jk= +prosemirror-commands@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/prosemirror-commands/-/prosemirror-commands-1.1.4.tgz#991563e67623acab4f8c510fad1570f8b4693780" + integrity sha512-kj4Qi+8h3EpJtZuuEDwZ9h2/QNGWDsIX/CzjmClxi9GhxWyBUMVUvIFk0mgdqHyX20lLeGmOpc0TLA5aPzgpWg== + dependencies: + prosemirror-model "^1.0.0" + prosemirror-state "^1.0.0" + prosemirror-transform "^1.0.0" + +prosemirror-dropcursor@^1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/prosemirror-dropcursor/-/prosemirror-dropcursor-1.3.2.tgz#28738c4ed7102e814d7a8a26d70018523fc7cd6d" + integrity sha512-4c94OUGyobGnwcQI70OXyMhE/9T4aTgjU+CHxkd5c7D+jH/J0mKM/lk+jneFVKt7+E4/M0D9HzRPifu8U28Thw== + dependencies: + prosemirror-state "^1.0.0" + prosemirror-transform "^1.1.0" + prosemirror-view "^1.1.0" + +prosemirror-gapcursor@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/prosemirror-gapcursor/-/prosemirror-gapcursor-1.1.5.tgz#0c37fd6cbb1d7c46358c2e7397f8da9a8b5c6246" + integrity sha512-SjbUZq5pgsBDuV3hu8GqgIpZR5eZvGLM+gPQTqjVVYSMUCfKW3EGXTEYaLHEl1bGduwqNC95O3bZflgtAb4L6w== + dependencies: + prosemirror-keymap "^1.0.0" + prosemirror-model "^1.0.0" + prosemirror-state "^1.0.0" + prosemirror-view "^1.0.0" + +prosemirror-history@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/prosemirror-history/-/prosemirror-history-1.1.3.tgz#4f76a1e71db4ef7cdf0e13dec6d8da2aeaecd489" + integrity sha512-zGDotijea+vnfnyyUGyiy1wfOQhf0B/b6zYcCouBV8yo6JmrE9X23M5q7Nf/nATywEZbgRLG70R4DmfSTC+gfg== + dependencies: + prosemirror-state "^1.2.2" + prosemirror-transform "^1.0.0" + rope-sequence "^1.3.0" + +prosemirror-inputrules@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/prosemirror-inputrules/-/prosemirror-inputrules-1.1.3.tgz#93f9199ca02473259c30d7e352e4c14022d54638" + integrity sha512-ZaHCLyBtvbyIHv0f5p6boQTIJjlD6o2NPZiEaZWT2DA+j591zS29QQEMT4lBqwcLW3qRSf7ZvoKNbf05YrsStw== + dependencies: + prosemirror-state "^1.0.0" + prosemirror-transform "^1.0.0" + +prosemirror-keymap@^1.0.0, prosemirror-keymap@^1.1.2, prosemirror-keymap@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/prosemirror-keymap/-/prosemirror-keymap-1.1.4.tgz#8b481bf8389a5ac40d38dbd67ec3da2c7eac6a6d" + integrity sha512-Al8cVUOnDFL4gcI5IDlG6xbZ0aOD/i3B17VT+1JbHWDguCgt/lBHVTHUBcKvvbSg6+q/W4Nj1Fu6bwZSca3xjg== + dependencies: + prosemirror-state "^1.0.0" + w3c-keyname "^2.2.0" + +prosemirror-markdown@^1.4.4: + version "1.5.0" + resolved "https://registry.yarnpkg.com/prosemirror-markdown/-/prosemirror-markdown-1.5.0.tgz#1c0129640c33e23217fbf80ebb24486a40a759c1" + integrity sha512-ugTyZfTu1l2E3EI6+DwD917mz2Sk5E4R01Nh67yMffGg4S9ZetC81g1VIKGCaak4jnoP4BMUIOUJyXAS6xFLaA== + dependencies: + markdown-it "^10.0.0" + prosemirror-model "^1.0.0" + +prosemirror-model@^1.0.0, prosemirror-model@^1.1.0, prosemirror-model@^1.11.2, prosemirror-model@^1.8.1: + version "1.12.0" + resolved "https://registry.yarnpkg.com/prosemirror-model/-/prosemirror-model-1.12.0.tgz#deb6acbce5c62ea35ef3d59c7d4c54f65d6d9fba" + integrity sha512-B5syrXluQwEPfih8PqZcVg2VWRUf8Rj97K/VNSkQtjUPL1BCoTUgdLERIlxdWHkwqvujFsT3Pw5ubc4/ofF1jQ== + dependencies: + orderedmap "^1.1.0" + +prosemirror-schema-list@^1.1.2: + version "1.1.4" + resolved "https://registry.yarnpkg.com/prosemirror-schema-list/-/prosemirror-schema-list-1.1.4.tgz#471f9caf2d2bed93641d2e490434c0d2d4330df1" + integrity sha512-pNTuZflacFOBlxrTcWSdWhjoB8BaucwfJVp/gJNxztOwaN3wQiC65axclXyplf6TKgXD/EkWfS/QAov3/Znadw== + dependencies: + prosemirror-model "^1.0.0" + prosemirror-transform "^1.0.0" + +prosemirror-state@^1.0.0, prosemirror-state@^1.2.2, prosemirror-state@^1.3.1, prosemirror-state@^1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/prosemirror-state/-/prosemirror-state-1.3.3.tgz#b2862866b14dec2b3ae1ab18229f2bd337651a2c" + integrity sha512-PLXh2VJsIgvlgSTH6I2Yg6vk1CzPDp21DFreVpQtDMY2S6WaMmrQgDTLRcsrD8X38v8Yc873H7+ogdGzyIPn+w== + dependencies: + prosemirror-model "^1.0.0" + prosemirror-transform "^1.0.0" + +prosemirror-tables@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/prosemirror-tables/-/prosemirror-tables-1.1.1.tgz#ad66300cc49500455cf1243bb129c9e7d883321e" + integrity sha512-LmCz4jrlqQZRsYRDzCRYf/pQ5CUcSOyqZlAj5kv67ZWBH1SVLP2U9WJEvQfimWgeRlIz0y0PQVqO1arRm1+woA== + dependencies: + prosemirror-keymap "^1.1.2" + prosemirror-model "^1.8.1" + prosemirror-state "^1.3.1" + prosemirror-transform "^1.2.1" + prosemirror-view "^1.13.3" + +prosemirror-transform@1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/prosemirror-transform/-/prosemirror-transform-1.2.5.tgz#7a3e2c61fcdbaf1d0844a2a3bc34fc3524e9809c" + integrity sha512-eqeIaxWtUfOnpA1ERrXCuSIMzqIJtL9Qrs5uJMCjY5RMSaH5o4pc390SAjn/IDPeIlw6auh0hCCXs3wRvGnQug== + dependencies: + prosemirror-model "^1.0.0" + +prosemirror-transform@^1.0.0, prosemirror-transform@^1.1.0, prosemirror-transform@^1.2.1: + version "1.2.8" + resolved "https://registry.yarnpkg.com/prosemirror-transform/-/prosemirror-transform-1.2.8.tgz#4b86544fa43637fe381549fb7b019f4fb71fe65c" + integrity sha512-hKqceqv9ZmMQXNQkhFjr0KFGPvkhygaWND+uIM0GxRpALrKfxP97SsgHTBs3OpJhDmh5N+mB4D/CksB291Eavg== + dependencies: + prosemirror-model "^1.0.0" + +prosemirror-utils@^0.9.6: + version "0.9.6" + resolved "https://registry.yarnpkg.com/prosemirror-utils/-/prosemirror-utils-0.9.6.tgz#3d97bd85897e3b535555867dc95a51399116a973" + integrity sha512-UC+j9hQQ1POYfMc5p7UFxBTptRiGPR7Kkmbl3jVvU8VgQbkI89tR/GK+3QYC8n+VvBZrtAoCrJItNhWSxX3slA== + +prosemirror-view@^1.0.0, prosemirror-view@^1.1.0, prosemirror-view@^1.13.3, prosemirror-view@^1.15.7: + version "1.16.0" + resolved "https://registry.yarnpkg.com/prosemirror-view/-/prosemirror-view-1.16.0.tgz#024440a8e9acbbb5826572eef58c21c11cd1e454" + integrity sha512-iFtStCw2byF0yLc3mm1ezGdFSd6SWM4pnJod+ZaJiU5ju36QdYM4Xwa+qNm/AaI2/MgxpJqi8jsGWOJNkeBQ/Q== + dependencies: + prosemirror-model "^1.1.0" + prosemirror-state "^1.0.0" + prosemirror-transform "^1.1.0" + proxy-addr@~2.0.5: version "2.0.6" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.6.tgz#fdc2336505447d3f2f2c638ed272caf614bbb2bf" @@ -12876,6 +13151,11 @@ react-lifecycles-compat@^3.0.4: resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA== +react-medium-image-zoom@^3.0.16: + version "3.1.2" + resolved "https://registry.yarnpkg.com/react-medium-image-zoom/-/react-medium-image-zoom-3.1.2.tgz#5ac4441f1d424bd9680a25bfc2591be3d7704a42" + integrity sha512-werjufn5o4ytdyvJNzfqXCilovDhMyREH0qeJhCjV5brNAyfV7anZmvpFc3FApbuVXwBkzHMuQkV2z/GyEQatg== + react-popper-tooltip@^2.8.3: version "2.11.1" resolved "https://registry.yarnpkg.com/react-popper-tooltip/-/react-popper-tooltip-2.11.1.tgz#3c4bdfd8bc10d1c2b9a162e859bab8958f5b2644" @@ -12897,6 +13177,13 @@ react-popper@^1.3.7: typed-styles "^0.0.7" warning "^4.0.2" +react-portal@^4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/react-portal/-/react-portal-4.2.1.tgz#12c1599238c06fb08a9800f3070bea2a3f78b1a6" + integrity sha512-fE9kOBagwmTXZ3YGRYb4gcMy+kSA+yLO0xnPankjRlfBv4uCpFXqKPfkpsGQQR15wkZ9EssnvTOl1yMzbkxhPQ== + dependencies: + prop-types "^15.5.8" + react-sizeme@^2.6.7: version "2.6.12" resolved "https://registry.yarnpkg.com/react-sizeme/-/react-sizeme-2.6.12.tgz#ed207be5476f4a85bf364e92042520499455453e" @@ -13077,6 +13364,15 @@ refractor@^2.4.1: parse-entities "^1.1.2" prismjs "~1.17.0" +refractor@^3.1.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/refractor/-/refractor-3.2.0.tgz#bc46f7cfbb6adbf45cd304e8e299b7fa854804e0" + integrity sha512-hSo+EyMIZTLBvNNgIU5lW4yjCzNYMZ4dcEhBq/3nReGfqzd2JfVhdlPDfU9rEsgcAyWx+OimIIUoL4ZU7NtYHQ== + dependencies: + hastscript "^6.0.0" + parse-entities "^2.0.0" + prismjs "~1.22.0" + regenerate-unicode-properties@^8.2.0: version "8.2.0" resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz#e5de7111d655e7ba60c057dbe9ff37c87e65cdec" @@ -13371,6 +13667,38 @@ reusify@^1.0.4: resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== +rich-markdown-editor@^11.0.2: + version "11.0.2" + resolved "https://registry.yarnpkg.com/rich-markdown-editor/-/rich-markdown-editor-11.0.2.tgz#281bca9670a30f6b528ace71a4ee06a24210a464" + integrity sha512-b9WigUymZA8BucrduIngBB+jrDuCHjwBdKa4aP6aehS5JQqKnTY++sjiHOvaFDnD75GJGUw/4wsNt76KdYAyCw== + dependencies: + copy-to-clipboard "^3.0.8" + lodash "^4.17.11" + markdown-it-container "^3.0.0" + outline-icons "^1.21.0-3" + prismjs "^1.19.0" + prosemirror-commands "^1.1.4" + prosemirror-dropcursor "^1.3.2" + prosemirror-gapcursor "^1.1.5" + prosemirror-history "^1.1.3" + prosemirror-inputrules "^1.1.3" + prosemirror-keymap "^1.1.4" + prosemirror-markdown "^1.4.4" + prosemirror-model "^1.11.2" + prosemirror-schema-list "^1.1.2" + prosemirror-state "^1.3.3" + prosemirror-tables "^1.1.1" + prosemirror-transform "1.2.5" + prosemirror-utils "^0.9.6" + prosemirror-view "^1.15.7" + react-medium-image-zoom "^3.0.16" + react-portal "^4.2.1" + refractor "^3.1.0" + resize-observer-polyfill "^1.5.1" + slugify "^1.4.0" + smooth-scroll-into-view-if-needed "^1.1.27" + typescript "3.7.5" + rimraf@2.6.3: version "2.6.3" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" @@ -13400,6 +13728,11 @@ ripemd160@^2.0.0, ripemd160@^2.0.1: hash-base "^3.0.0" inherits "^2.0.1" +rope-sequence@^1.3.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/rope-sequence/-/rope-sequence-1.3.2.tgz#a19e02d72991ca71feb6b5f8a91154e48e3c098b" + integrity sha512-ku6MFrwEVSVmXLvy3dYph3LAMNS0890K7fabn+0YIRQ2T96T9F4gkFf0vf0WW0JUraNWwGRtInEpH7yO4tbQZg== + rsvp@^4.8.4: version "4.8.5" resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734" @@ -13523,6 +13856,13 @@ schema-utils@^2.7.1: ajv "^6.12.4" ajv-keywords "^3.5.2" +scroll-into-view-if-needed@^2.2.26: + version "2.2.26" + resolved "https://registry.yarnpkg.com/scroll-into-view-if-needed/-/scroll-into-view-if-needed-2.2.26.tgz#e4917da0c820135ff65ad6f7e4b7d7af568c4f13" + integrity sha512-SQ6AOKfABaSchokAmmaxVnL9IArxEnLEX9j4wAZw+x4iUTb40q7irtHG3z4GtAWz5veVZcCnubXDBRyLVQaohw== + dependencies: + compute-scroll-into-view "^1.0.16" + select-hose@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" @@ -13838,6 +14178,18 @@ slice-ansi@^3.0.0: astral-regex "^2.0.0" is-fullwidth-code-point "^3.0.0" +slugify@^1.4.0: + version "1.4.5" + resolved "https://registry.yarnpkg.com/slugify/-/slugify-1.4.5.tgz#a7517acf5f4c02a4df41e735354b660a4ed1efcf" + integrity sha512-WpECLAgYaxHoEAJ8Q1Lo8HOs1ngn7LN7QjXgOLbmmfkcWvosyk4ZTXkTzKyhngK640USTZUlgoQJfED1kz5fnQ== + +smooth-scroll-into-view-if-needed@^1.1.27: + version "1.1.29" + resolved "https://registry.yarnpkg.com/smooth-scroll-into-view-if-needed/-/smooth-scroll-into-view-if-needed-1.1.29.tgz#4f532d9f0353dbca122e546fb062e7b5e0643734" + integrity sha512-UxvIEbmMEqwbw0aZI4SOAtwwkMaLYVION20bDQmazVp3sNb1+WIA5koukqoJizRuAAUANRmcBcrTnodcB7maqw== + dependencies: + scroll-into-view-if-needed "^2.2.26" + snapdragon-node@^2.0.1: version "2.1.1" resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" @@ -14312,6 +14664,22 @@ style-loader@^1.0.0, style-loader@^1.1.3: loader-utils "^2.0.0" schema-utils "^2.6.6" +styled-components@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/styled-components/-/styled-components-5.2.0.tgz#6dcb5aa8a629c84b8d5ab34b7167e3e0c6f7ed74" + integrity sha512-9qE8Vgp8C5cpGAIdFaQVAl89Zgx1TDM4Yf4tlHbO9cPijtpSXTMLHy9lmP0lb+yImhgPFb1AmZ1qMUubmg3HLg== + dependencies: + "@babel/helper-module-imports" "^7.0.0" + "@babel/traverse" "^7.4.5" + "@emotion/is-prop-valid" "^0.8.8" + "@emotion/stylis" "^0.8.4" + "@emotion/unitless" "^0.7.4" + babel-plugin-styled-components ">= 1" + css-to-react-native "^3.0.0" + hoist-non-react-statics "^3.0.0" + shallowequal "^1.1.0" + supports-color "^5.5.0" + subscriptions-transport-ws@0.9.18: version "0.9.18" resolved "https://registry.yarnpkg.com/subscriptions-transport-ws/-/subscriptions-transport-ws-0.9.18.tgz#bcf02320c911fbadb054f7f928e51c6041a37b97" @@ -14339,7 +14707,7 @@ supports-color@^2.0.0: resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= -supports-color@^5.3.0, supports-color@^5.4.0: +supports-color@^5.3.0, supports-color@^5.4.0, supports-color@^5.5.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== @@ -14939,6 +15307,11 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= +typescript@3.7.5: + version "3.7.5" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.5.tgz#0692e21f65fd4108b9330238aac11dd2e177a1ae" + integrity sha512-/P5lkRXkWHNAbcJIiHPfRoKqyd7bsyCma1hZNUGfn20qm64T6ZBlrzprymeu918H+mB/0rIg2gGK/BXkhhYgBw== + typescript@^4.0.2, typescript@~4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.0.2.tgz#7ea7c88777c723c681e33bf7988be5d008d05ac2" @@ -14949,6 +15322,11 @@ ua-parser-js@^0.7.18: resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.21.tgz#853cf9ce93f642f67174273cc34565ae6f308777" integrity sha512-+O8/qh/Qj8CgC6eYBVBykMrNtp5Gebn4dlGD/kKXVkJNDwyrAwSIqwz8CDf+tsAIWVycKcku6gIXJ0qwx/ZXaQ== +uc.micro@^1.0.1, uc.micro@^1.0.5: + 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== + unc-path-regex@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/unc-path-regex/-/unc-path-regex-0.1.2.tgz#e73dd3d7b0d7c5ed86fbac6b0ae7d8c6a69d50fa" @@ -15298,6 +15676,11 @@ w3c-hr-time@^1.0.2: dependencies: browser-process-hrtime "^1.0.0" +w3c-keyname@^2.2.0: + version "2.2.4" + resolved "https://registry.yarnpkg.com/w3c-keyname/-/w3c-keyname-2.2.4.tgz#4ade6916f6290224cdbd1db8ac49eab03d0eef6b" + integrity sha512-tOhfEwEzFLJzf6d1ZPkYfGj+FWhIpBux9ppoP3rlclw3Z0BZv3N7b7030Z1kYth+6rDuAsXUFr+d0VE6Ed1ikw== + w3c-xmlserializer@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz#3e7104a05b75146cc60f564380b7f683acf1020a" From b28d1677afab00f616e2fc73056209a9c81bfe3e Mon Sep 17 00:00:00 2001 From: Kurt Hutten Date: Sat, 17 Oct 2020 06:01:22 +1100 Subject: [PATCH 3/6] Add okay styles to edit part page --- .../components/EditPartCell/EditPartCell.js | 9 +-- web/src/components/PartCell/PartCell.js | 2 +- web/src/components/PartForm/PartForm.js | 61 ++++++++----------- web/src/index.css | 19 ++++++ web/src/pages/EditPartPage/EditPartPage.js | 6 +- 5 files changed, 49 insertions(+), 48 deletions(-) diff --git a/web/src/components/EditPartCell/EditPartCell.js b/web/src/components/EditPartCell/EditPartCell.js index ca617e4..3ba7344 100644 --- a/web/src/components/EditPartCell/EditPartCell.js +++ b/web/src/components/EditPartCell/EditPartCell.js @@ -39,13 +39,6 @@ export const Success = ({ part }) => { } return ( -
-
-

Edit Part {part.id}

-
-
- -
-
+ ) } diff --git a/web/src/components/PartCell/PartCell.js b/web/src/components/PartCell/PartCell.js index 2efcdcc..22044f0 100644 --- a/web/src/components/PartCell/PartCell.js +++ b/web/src/components/PartCell/PartCell.js @@ -21,7 +21,7 @@ export const Success = ({ part }) => {

{part.title}

diff --git a/web/src/components/PartForm/PartForm.js b/web/src/components/PartForm/PartForm.js index 433987b..64d8fbb 100644 --- a/web/src/components/PartForm/PartForm.js +++ b/web/src/components/PartForm/PartForm.js @@ -7,14 +7,21 @@ import { TextAreaField, Submit, } from '@redwoodjs/forms' +import { useState } from 'react'; + +import Editor from "rich-markdown-editor"; const PartForm = (props) => { + const [description, setDescription] = useState(props?.part?.description) const onSubmit = (data) => { - props.onSave(data, props?.part?.id) + props.onSave({ + ...data, + description, + }, props?.part?.id) } return ( -
+
{
From 4db2195b1d2e4ad11c0e2f43963ad245b8e7320a Mon Sep 17 00:00:00 2001 From: Kurt Hutten Date: Mon, 19 Oct 2020 07:21:54 +1100 Subject: [PATCH 5/6] Fix flash after new routing --- web/src/components/EditPartCell/EditPartCell.js | 10 ++-------- web/src/components/PartForm/PartForm.js | 3 +++ 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/web/src/components/EditPartCell/EditPartCell.js b/web/src/components/EditPartCell/EditPartCell.js index 70c8a68..b434a62 100644 --- a/web/src/components/EditPartCell/EditPartCell.js +++ b/web/src/components/EditPartCell/EditPartCell.js @@ -1,5 +1,4 @@ -import { useMutation, useFlash } from '@redwoodjs/web' -import { navigate, routes } from '@redwoodjs/router' +import { useMutation } from '@redwoodjs/web' import PartForm from 'src/components/PartForm' export const QUERY = gql` @@ -26,12 +25,7 @@ const UPDATE_PART_MUTATION = gql` export const Loading = () =>
Loading...
export const Success = ({ part }) => { - const { addMessage } = useFlash() - const [updatePart, { loading, error }] = useMutation(UPDATE_PART_MUTATION, { - onCompleted: () => { - addMessage('Part updated.', { classes: 'rw-flash-success' }) - }, - }) + const [updatePart, { loading, error }] = useMutation(UPDATE_PART_MUTATION) const onSave = (input, id) => updatePart({ variables: { id, input } }) diff --git a/web/src/components/PartForm/PartForm.js b/web/src/components/PartForm/PartForm.js index 17126e3..c300d8c 100644 --- a/web/src/components/PartForm/PartForm.js +++ b/web/src/components/PartForm/PartForm.js @@ -9,10 +9,12 @@ import { } from '@redwoodjs/forms' import { useState } from 'react'; import { navigate, routes } from '@redwoodjs/router' +import { useFlash } from '@redwoodjs/web' import Editor from "rich-markdown-editor"; const PartForm = (props) => { + const { addMessage } = useFlash() const [description, setDescription] = useState(props?.part?.description) const onSubmit = async (data, e) => { @@ -26,6 +28,7 @@ const PartForm = (props) => { } else { navigate(routes.part({id: props?.part?.id})) } + addMessage('Part updated.', { classes: 'rw-flash-success' }) } return ( From f4e16dc2097ed2a5fd03513db03f8ac8eab3ead7 Mon Sep 17 00:00:00 2001 From: Kurt Hutten Date: Mon, 19 Oct 2020 19:33:08 +1100 Subject: [PATCH 6/6] Add simple user model --- .../README.md | 65 +++++++ .../schema.prisma | 48 +++++ .../steps.json | 179 ++++++++++++++++++ .../README.md | 61 ++++++ .../schema.prisma | 48 +++++ .../steps.json | 15 ++ api/prisma/migrations/migrate.lock | 4 +- api/prisma/schema.prisma | 13 ++ api/src/functions/identity-signup.js | 35 ++++ api/src/graphql/users.sdl.js | 35 ++++ api/src/services/users/users.js | 38 ++++ api/src/services/users/users.test.js | 9 + web/src/Routes.js | 9 + .../components/EditUserCell/EditUserCell.js | 50 +++++ web/src/components/NewUser/NewUser.js | 38 ++++ web/src/components/User/User.js | 103 ++++++++++ web/src/components/UserCell/UserCell.js | 22 +++ web/src/components/UserForm/UserForm.js | 81 ++++++++ web/src/components/Users/Users.js | 109 +++++++++++ web/src/components/UsersCell/UsersCell.js | 33 ++++ web/src/layouts/MainLayout/MainLayout.js | 7 +- web/src/pages/EditUserPage/EditUserPage.js | 12 ++ web/src/pages/NewUserPage/NewUserPage.js | 12 ++ web/src/pages/UserPage/UserPage.js | 12 ++ web/src/pages/UsersPage/UsersPage.js | 12 ++ 25 files changed, 1048 insertions(+), 2 deletions(-) create mode 100644 api/prisma/migrations/20201018233330-add-simple-user-model/README.md create mode 100644 api/prisma/migrations/20201018233330-add-simple-user-model/schema.prisma create mode 100644 api/prisma/migrations/20201018233330-add-simple-user-model/steps.json create mode 100644 api/prisma/migrations/20201019072122-add-simplify-user-model/README.md create mode 100644 api/prisma/migrations/20201019072122-add-simplify-user-model/schema.prisma create mode 100644 api/prisma/migrations/20201019072122-add-simplify-user-model/steps.json create mode 100644 api/src/functions/identity-signup.js create mode 100644 api/src/graphql/users.sdl.js create mode 100644 api/src/services/users/users.js create mode 100644 api/src/services/users/users.test.js create mode 100644 web/src/components/EditUserCell/EditUserCell.js create mode 100644 web/src/components/NewUser/NewUser.js create mode 100644 web/src/components/User/User.js create mode 100644 web/src/components/UserCell/UserCell.js create mode 100644 web/src/components/UserForm/UserForm.js create mode 100644 web/src/components/Users/Users.js create mode 100644 web/src/components/UsersCell/UsersCell.js create mode 100644 web/src/pages/EditUserPage/EditUserPage.js create mode 100644 web/src/pages/NewUserPage/NewUserPage.js create mode 100644 web/src/pages/UserPage/UserPage.js create mode 100644 web/src/pages/UsersPage/UsersPage.js diff --git a/api/prisma/migrations/20201018233330-add-simple-user-model/README.md b/api/prisma/migrations/20201018233330-add-simple-user-model/README.md new file mode 100644 index 0000000..c8ec755 --- /dev/null +++ b/api/prisma/migrations/20201018233330-add-simple-user-model/README.md @@ -0,0 +1,65 @@ +# Migration `20201018233330-add-simple-user-model` + +This migration has been generated by Kurt Hutten at 10/19/2020, 10:33:30 AM. +You can check out the [state of the schema](./schema.prisma) after the migration. + +## Database Steps + +```sql +CREATE TABLE "User" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "userName" TEXT NOT NULL, + "email" TEXT NOT NULL, + "issuer" TEXT NOT NULL, + "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" DATETIME NOT NULL, + "image" TEXT, + "bio" TEXT +) + +CREATE UNIQUE INDEX "User.userName_unique" ON "User"("userName") + +CREATE UNIQUE INDEX "User.email_unique" ON "User"("email") + +CREATE UNIQUE INDEX "User.issuer_unique" ON "User"("issuer") +``` + +## Changes + +```diff +diff --git schema.prisma schema.prisma +migration 20201011095227-create-contact..20201018233330-add-simple-user-model +--- datamodel.dml ++++ datamodel.dml +@@ -1,9 +1,7 @@ + datasource DS { +- // optionally set multiple providers +- // example: provider = ["sqlite", "postgresql"] +- provider = "sqlite" +- url = "***" ++ provider = ["sqlite", "postgresql"] ++ url = "***" + } + generator client { + provider = "prisma-client-js" +@@ -34,4 +32,17 @@ + email String + message String + createdAt DateTime @default(now()) + } ++ ++model User { ++ id Int @id @default(autoincrement()) ++ userName String @unique ++ email String @unique ++ issuer String @unique ++ ++ createdAt DateTime @default(now()) ++ updatedAt DateTime @updatedAt ++ ++ image String? // url maybe id or file storage service? cloudinary? ++ bio String? //mark down ++} +``` + + diff --git a/api/prisma/migrations/20201018233330-add-simple-user-model/schema.prisma b/api/prisma/migrations/20201018233330-add-simple-user-model/schema.prisma new file mode 100644 index 0000000..15e3468 --- /dev/null +++ b/api/prisma/migrations/20201018233330-add-simple-user-model/schema.prisma @@ -0,0 +1,48 @@ +datasource DS { + provider = ["sqlite", "postgresql"] + url = "***" +} + +generator client { + provider = "prisma-client-js" + binaryTargets = "native" +} + +model Post { + id Int @id @default(autoincrement()) + title String + body String + createdAt DateTime @default(now()) +} + +model Part { + id Int @id @default(autoincrement()) + title String + description String // markdown string + code String @default("// Welcome to Cascade Studio! Here are some useful functions:\n// Translate(), Rotate(), Scale(), Union(), Difference(), Intersection()\n// Box(), Sphere(), Cylinder(), Cone(), Text3D(), Polygon()\n// Offset(), Extrude(), RotatedExtrude(), Revolve(), Pipe(), Loft(),\n// FilletEdges(), ChamferEdges(),\n// Slider(), Button(), Checkbox()\nlet holeRadius = Slider(\"Radius\", 30 , 20 , 40);\nlet sphere = Sphere(50);\nlet cylinderZ = Cylinder(holeRadius, 200, true);\nlet cylinderY = Rotate([0,1,0], 90, Cylinder(holeRadius, 200, true));\nlet cylinderX = Rotate([1,0,0], 90, Cylinder(holeRadius, 200, true));\nTranslate([0, 0, 50], Difference(sphere, [cylinderX, cylinderY, cylinderZ]));\n\nTranslate([-25, 0, 40], Text3D(\"Hi!\"));\n// Don't forget to push imported or oc-defined shapes into sceneShapes to add them to the workspace!") + mainImage String // link to cloudinary + createdAt DateTime @default(now()) + // userId + //likes, comments, reactions +} + +model Contact { + id Int @id @default(autoincrement()) + name String + email String + message String + createdAt DateTime @default(now()) +} + +model User { + id Int @id @default(autoincrement()) + userName String @unique + email String @unique + issuer String @unique + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + image String? // url maybe id or file storage service? cloudinary? + bio String? //mark down +} diff --git a/api/prisma/migrations/20201018233330-add-simple-user-model/steps.json b/api/prisma/migrations/20201018233330-add-simple-user-model/steps.json new file mode 100644 index 0000000..8ea741d --- /dev/null +++ b/api/prisma/migrations/20201018233330-add-simple-user-model/steps.json @@ -0,0 +1,179 @@ +{ + "version": "0.3.14-fixed", + "steps": [ + { + "tag": "UpdateArgument", + "location": { + "tag": "Source", + "source": "DS" + }, + "argument": "provider", + "newValue": "[\"sqlite\", \"postgresql\"]" + }, + { + "tag": "CreateModel", + "model": "User" + }, + { + "tag": "CreateField", + "model": "User", + "field": "id", + "type": "Int", + "arity": "Required" + }, + { + "tag": "CreateDirective", + "location": { + "path": { + "tag": "Field", + "model": "User", + "field": "id" + }, + "directive": "id" + } + }, + { + "tag": "CreateDirective", + "location": { + "path": { + "tag": "Field", + "model": "User", + "field": "id" + }, + "directive": "default" + } + }, + { + "tag": "CreateArgument", + "location": { + "tag": "Directive", + "path": { + "tag": "Field", + "model": "User", + "field": "id" + }, + "directive": "default" + }, + "argument": "", + "value": "autoincrement()" + }, + { + "tag": "CreateField", + "model": "User", + "field": "userName", + "type": "String", + "arity": "Required" + }, + { + "tag": "CreateDirective", + "location": { + "path": { + "tag": "Field", + "model": "User", + "field": "userName" + }, + "directive": "unique" + } + }, + { + "tag": "CreateField", + "model": "User", + "field": "email", + "type": "String", + "arity": "Required" + }, + { + "tag": "CreateDirective", + "location": { + "path": { + "tag": "Field", + "model": "User", + "field": "email" + }, + "directive": "unique" + } + }, + { + "tag": "CreateField", + "model": "User", + "field": "issuer", + "type": "String", + "arity": "Required" + }, + { + "tag": "CreateDirective", + "location": { + "path": { + "tag": "Field", + "model": "User", + "field": "issuer" + }, + "directive": "unique" + } + }, + { + "tag": "CreateField", + "model": "User", + "field": "createdAt", + "type": "DateTime", + "arity": "Required" + }, + { + "tag": "CreateDirective", + "location": { + "path": { + "tag": "Field", + "model": "User", + "field": "createdAt" + }, + "directive": "default" + } + }, + { + "tag": "CreateArgument", + "location": { + "tag": "Directive", + "path": { + "tag": "Field", + "model": "User", + "field": "createdAt" + }, + "directive": "default" + }, + "argument": "", + "value": "now()" + }, + { + "tag": "CreateField", + "model": "User", + "field": "updatedAt", + "type": "DateTime", + "arity": "Required" + }, + { + "tag": "CreateDirective", + "location": { + "path": { + "tag": "Field", + "model": "User", + "field": "updatedAt" + }, + "directive": "updatedAt" + } + }, + { + "tag": "CreateField", + "model": "User", + "field": "image", + "type": "String", + "arity": "Optional" + }, + { + "tag": "CreateField", + "model": "User", + "field": "bio", + "type": "String", + "arity": "Optional" + } + ] +} \ No newline at end of file diff --git a/api/prisma/migrations/20201019072122-add-simplify-user-model/README.md b/api/prisma/migrations/20201019072122-add-simplify-user-model/README.md new file mode 100644 index 0000000..29d4e11 --- /dev/null +++ b/api/prisma/migrations/20201019072122-add-simplify-user-model/README.md @@ -0,0 +1,61 @@ +# Migration `20201019072122-add-simplify-user-model` + +This migration has been generated by Kurt Hutten at 10/19/2020, 6:21:22 PM. +You can check out the [state of the schema](./schema.prisma) after the migration. + +## Database Steps + +```sql +DROP INDEX "User.issuer_unique" + +DROP INDEX "User.userName_unique" + +PRAGMA foreign_keys=OFF; +CREATE TABLE "new_User" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "email" TEXT NOT NULL, + "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" DATETIME NOT NULL, + "image" TEXT, + "bio" TEXT +); +INSERT INTO "new_User" ("id", "email", "createdAt", "updatedAt", "image", "bio") SELECT "id", "email", "createdAt", "updatedAt", "image", "bio" FROM "User"; +DROP TABLE "User"; +ALTER TABLE "new_User" RENAME TO "User"; +CREATE UNIQUE INDEX "User.email_unique" ON "User"("email"); +PRAGMA foreign_key_check; +PRAGMA foreign_keys=ON +``` + +## Changes + +```diff +diff --git schema.prisma schema.prisma +migration 20201018233330-add-simple-user-model..20201019072122-add-simplify-user-model +--- datamodel.dml ++++ datamodel.dml +@@ -1,7 +1,7 @@ + datasource DS { + provider = ["sqlite", "postgresql"] +- url = "***" ++ url = "***" + } + generator client { + provider = "prisma-client-js" +@@ -34,12 +34,12 @@ + createdAt DateTime @default(now()) + } + model User { +- id Int @id @default(autoincrement()) +- userName String @unique +- email String @unique +- issuer String @unique ++ id Int @id @default(autoincrement()) ++ email String @unique ++ // userName String @unique ++ // issuer String @unique + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt +``` + + diff --git a/api/prisma/migrations/20201019072122-add-simplify-user-model/schema.prisma b/api/prisma/migrations/20201019072122-add-simplify-user-model/schema.prisma new file mode 100644 index 0000000..24140d8 --- /dev/null +++ b/api/prisma/migrations/20201019072122-add-simplify-user-model/schema.prisma @@ -0,0 +1,48 @@ +datasource DS { + provider = ["sqlite", "postgresql"] + url = "***" +} + +generator client { + provider = "prisma-client-js" + binaryTargets = "native" +} + +model Post { + id Int @id @default(autoincrement()) + title String + body String + createdAt DateTime @default(now()) +} + +model Part { + id Int @id @default(autoincrement()) + title String + description String // markdown string + code String @default("// Welcome to Cascade Studio! Here are some useful functions:\n// Translate(), Rotate(), Scale(), Union(), Difference(), Intersection()\n// Box(), Sphere(), Cylinder(), Cone(), Text3D(), Polygon()\n// Offset(), Extrude(), RotatedExtrude(), Revolve(), Pipe(), Loft(),\n// FilletEdges(), ChamferEdges(),\n// Slider(), Button(), Checkbox()\nlet holeRadius = Slider(\"Radius\", 30 , 20 , 40);\nlet sphere = Sphere(50);\nlet cylinderZ = Cylinder(holeRadius, 200, true);\nlet cylinderY = Rotate([0,1,0], 90, Cylinder(holeRadius, 200, true));\nlet cylinderX = Rotate([1,0,0], 90, Cylinder(holeRadius, 200, true));\nTranslate([0, 0, 50], Difference(sphere, [cylinderX, cylinderY, cylinderZ]));\n\nTranslate([-25, 0, 40], Text3D(\"Hi!\"));\n// Don't forget to push imported or oc-defined shapes into sceneShapes to add them to the workspace!") + mainImage String // link to cloudinary + createdAt DateTime @default(now()) + // userId + //likes, comments, reactions +} + +model Contact { + id Int @id @default(autoincrement()) + name String + email String + message String + createdAt DateTime @default(now()) +} + +model User { + id Int @id @default(autoincrement()) + email String @unique + // userName String @unique + // issuer String @unique + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + image String? // url maybe id or file storage service? cloudinary? + bio String? //mark down +} diff --git a/api/prisma/migrations/20201019072122-add-simplify-user-model/steps.json b/api/prisma/migrations/20201019072122-add-simplify-user-model/steps.json new file mode 100644 index 0000000..0285263 --- /dev/null +++ b/api/prisma/migrations/20201019072122-add-simplify-user-model/steps.json @@ -0,0 +1,15 @@ +{ + "version": "0.3.14-fixed", + "steps": [ + { + "tag": "DeleteField", + "model": "User", + "field": "userName" + }, + { + "tag": "DeleteField", + "model": "User", + "field": "issuer" + } + ] +} \ No newline at end of file diff --git a/api/prisma/migrations/migrate.lock b/api/prisma/migrations/migrate.lock index 086c06b..dddc03e 100644 --- a/api/prisma/migrations/migrate.lock +++ b/api/prisma/migrations/migrate.lock @@ -4,4 +4,6 @@ 20201011043647-create-parts 20201011052155-add-code-to-part 20201011082558-add-code-not-needed-upon-create -20201011095227-create-contact \ No newline at end of file +20201011095227-create-contact +20201018233330-add-simple-user-model +20201019072122-add-simplify-user-model \ No newline at end of file diff --git a/api/prisma/schema.prisma b/api/prisma/schema.prisma index e11b1c6..baecb2a 100644 --- a/api/prisma/schema.prisma +++ b/api/prisma/schema.prisma @@ -33,3 +33,16 @@ model Contact { message String createdAt DateTime @default(now()) } + +model User { + id Int @id @default(autoincrement()) + email String @unique + // userName String @unique + // issuer String @unique + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + image String? // url maybe id or file storage service? cloudinary? + bio String? //mark down +} diff --git a/api/src/functions/identity-signup.js b/api/src/functions/identity-signup.js new file mode 100644 index 0000000..9524495 --- /dev/null +++ b/api/src/functions/identity-signup.js @@ -0,0 +1,35 @@ +import { createUser } from 'src/services/users/users.js' + +export const handler = async (req, _context) => { + const body = JSON.parse(req.body) + console.log(body) + console.log(_context) + + const eventType = body.event + const user = body.user + const email = user.email + + let roles = [] + + if (eventType === 'signup') { + roles.push('user') + const hi = { + email: 'kurt.hutten@gmail.com', + image: '', + bio: '' + } + const input = { + email, + } + createUser({input}) + + return { + statusCode: 200, + body: JSON.stringify({ app_metadata: { roles: roles } }), + } + } else { + return { + statusCode: 200, + } + } +} diff --git a/api/src/graphql/users.sdl.js b/api/src/graphql/users.sdl.js new file mode 100644 index 0000000..52c3411 --- /dev/null +++ b/api/src/graphql/users.sdl.js @@ -0,0 +1,35 @@ +export const schema = gql` + type User { + id: Int! + email: String! + createdAt: DateTime! + updatedAt: DateTime! + image: String + bio: String + } + + type Query { + users: [User!]! + user(id: Int!): User + } + + input CreateUserInput { + email: String! + issuer: String! + image: String + bio: String + } + + input UpdateUserInput { + email: String + issuer: String + image: String + bio: String + } + + type Mutation { + createUser(input: CreateUserInput!): User! + updateUser(id: Int!, input: UpdateUserInput!): User! + deleteUser(id: Int!): User! + } +` diff --git a/api/src/services/users/users.js b/api/src/services/users/users.js new file mode 100644 index 0000000..f3875f8 --- /dev/null +++ b/api/src/services/users/users.js @@ -0,0 +1,38 @@ +import { db } from 'src/lib/db' +import { requireAuth } from 'src/lib/auth' + +export const users = () => { + requireAuth({ role: 'admin' }) + return db.user.findMany() +} + +export const user = ({ id }) => { + requireAuth() + return db.user.findOne({ + where: { id }, + }) +} + +export const createUser = ({ input }) => { + console.log(input) + console.log(JSON.stringify(input)) + requireAuth({ role: 'admin' }) + return db.user.create({ + data: input, + }) +} + +export const updateUser = ({ id, input }) => { + requireAuth() + return db.user.update({ + data: input, + where: { id }, + }) +} + +export const deleteUser = ({ id }) => { + requireAuth({ role: 'admin' }) + return db.user.delete({ + where: { id }, + }) +} diff --git a/api/src/services/users/users.test.js b/api/src/services/users/users.test.js new file mode 100644 index 0000000..bac7cb4 --- /dev/null +++ b/api/src/services/users/users.test.js @@ -0,0 +1,9 @@ +/* +import { users } from './users' +*/ + +describe('users', () => { + it('returns true', () => { + expect(true).toBe(true) + }) +}) diff --git a/web/src/Routes.js b/web/src/Routes.js index 200ecb1..8255681 100644 --- a/web/src/Routes.js +++ b/web/src/Routes.js @@ -12,6 +12,15 @@ import { Router, Route, Private } from '@redwoodjs/router' const Routes = () => { return ( + {/* TODO add add min role to users and users/new */} + + + + + + + + diff --git a/web/src/components/EditUserCell/EditUserCell.js b/web/src/components/EditUserCell/EditUserCell.js new file mode 100644 index 0000000..34f940c --- /dev/null +++ b/web/src/components/EditUserCell/EditUserCell.js @@ -0,0 +1,50 @@ +import { useMutation, useFlash } from '@redwoodjs/web' +import { navigate, routes } from '@redwoodjs/router' +import UserForm from 'src/components/UserForm' + +export const QUERY = gql` + query FIND_USER_BY_ID($id: Int!) { + user: user(id: $id) { + id + email + createdAt + updatedAt + image + bio + } + } +` +const UPDATE_USER_MUTATION = gql` + mutation UpdateUserMutation($id: Int!, $input: UpdateUserInput!) { + updateUser(id: $id, input: $input) { + id + } + } +` + +export const Loading = () =>
Loading...
+ +export const Success = ({ user }) => { + const { addMessage } = useFlash() + const [updateUser, { loading, error }] = useMutation(UPDATE_USER_MUTATION, { + onCompleted: () => { + navigate(routes.users()) + addMessage('User updated.', { classes: 'rw-flash-success' }) + }, + }) + + const onSave = (input, id) => { + updateUser({ variables: { id, input } }) + } + + return ( +
+
+

Edit User {user.id}

+
+
+ +
+
+ ) +} diff --git a/web/src/components/NewUser/NewUser.js b/web/src/components/NewUser/NewUser.js new file mode 100644 index 0000000..6f89a18 --- /dev/null +++ b/web/src/components/NewUser/NewUser.js @@ -0,0 +1,38 @@ +import { useMutation, useFlash } from '@redwoodjs/web' +import { navigate, routes } from '@redwoodjs/router' +import UserForm from 'src/components/UserForm' + +const CREATE_USER_MUTATION = gql` + mutation CreateUserMutation($input: CreateUserInput!) { + createUser(input: $input) { + id + } + } +` + +const NewUser = () => { + const { addMessage } = useFlash() + const [createUser, { loading, error }] = useMutation(CREATE_USER_MUTATION, { + onCompleted: () => { + navigate(routes.users()) + addMessage('User created.', { classes: 'rw-flash-success' }) + }, + }) + + const onSave = (input) => { + createUser({ variables: { input } }) + } + + return ( +
+
+

New User

+
+
+ +
+
+ ) +} + +export default NewUser diff --git a/web/src/components/User/User.js b/web/src/components/User/User.js new file mode 100644 index 0000000..2b50035 --- /dev/null +++ b/web/src/components/User/User.js @@ -0,0 +1,103 @@ +import { useMutation, useFlash } from '@redwoodjs/web' +import { Link, routes, navigate } from '@redwoodjs/router' + +const DELETE_USER_MUTATION = gql` + mutation DeleteUserMutation($id: Int!) { + deleteUser(id: $id) { + id + } + } +` + +const jsonDisplay = (obj) => { + return ( +
+      {JSON.stringify(obj, null, 2)}
+    
+ ) +} + +const timeTag = (datetime) => { + return ( + + ) +} + +const checkboxInputTag = (checked) => { + return +} + +const User = ({ user }) => { + const { addMessage } = useFlash() + const [deleteUser] = useMutation(DELETE_USER_MUTATION, { + onCompleted: () => { + navigate(routes.users()) + addMessage('User deleted.', { classes: 'rw-flash-success' }) + }, + }) + + const onDeleteClick = (id) => { + if (confirm('Are you sure you want to delete user ' + id + '?')) { + deleteUser({ variables: { id } }) + } + } + + return ( + <> +
+
+

+ User {user.id} Detail +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Id{user.id}
Email{user.email}
Created at{timeTag(user.createdAt)}
Updated at{timeTag(user.updatedAt)}
Image{user.image}
Bio{user.bio}
+
+ + + ) +} + +export default User diff --git a/web/src/components/UserCell/UserCell.js b/web/src/components/UserCell/UserCell.js new file mode 100644 index 0000000..f89a7fd --- /dev/null +++ b/web/src/components/UserCell/UserCell.js @@ -0,0 +1,22 @@ +import User from 'src/components/User' + +export const QUERY = gql` + query FIND_USER_BY_ID($id: Int!) { + user: user(id: $id) { + id + email + createdAt + updatedAt + image + bio + } + } +` + +export const Loading = () =>
Loading...
+ +export const Empty = () =>
User not found
+ +export const Success = ({ user }) => { + return +} diff --git a/web/src/components/UserForm/UserForm.js b/web/src/components/UserForm/UserForm.js new file mode 100644 index 0000000..2527758 --- /dev/null +++ b/web/src/components/UserForm/UserForm.js @@ -0,0 +1,81 @@ +import { + Form, + FormError, + FieldError, + Label, + TextField, + Submit, +} from '@redwoodjs/forms' + +const UserForm = (props) => { + const onSubmit = (data) => { + props.onSave(data, props?.user?.id) + } + + return ( +
+
+ + + + + + + + + + + + + + +
+ + Save + +
+ +
+ ) +} + +export default UserForm diff --git a/web/src/components/Users/Users.js b/web/src/components/Users/Users.js new file mode 100644 index 0000000..427139e --- /dev/null +++ b/web/src/components/Users/Users.js @@ -0,0 +1,109 @@ +import { useMutation, useFlash } from '@redwoodjs/web' +import { Link, routes } from '@redwoodjs/router' + +const DELETE_USER_MUTATION = gql` + mutation DeleteUserMutation($id: Int!) { + deleteUser(id: $id) { + id + } + } +` + +const MAX_STRING_LENGTH = 150 + +const truncate = (text) => { + let output = text + if (text && text.length > MAX_STRING_LENGTH) { + output = output.substring(0, MAX_STRING_LENGTH) + '...' + } + return output +} + +const jsonTruncate = (obj) => { + return truncate(JSON.stringify(obj, null, 2)) +} + +const timeTag = (datetime) => { + return ( + + ) +} + +const checkboxInputTag = (checked) => { + return +} + +const UsersList = ({ users }) => { + const { addMessage } = useFlash() + const [deleteUser] = useMutation(DELETE_USER_MUTATION, { + onCompleted: () => { + addMessage('User deleted.', { classes: 'rw-flash-success' }) + }, + }) + + const onDeleteClick = (id) => { + if (confirm('Are you sure you want to delete user ' + id + '?')) { + deleteUser({ variables: { id }, refetchQueries: ['USERS'] }) + } + } + + return ( +
+ + + + + + + + + + + + + + {users.map((user) => ( + + + + + + + + + + ))} + +
IdEmailCreated atUpdated atImageBio 
{truncate(user.id)}{truncate(user.email)}{timeTag(user.createdAt)}{timeTag(user.updatedAt)}{truncate(user.image)}{truncate(user.bio)} + +
+
+ ) +} + +export default UsersList diff --git a/web/src/components/UsersCell/UsersCell.js b/web/src/components/UsersCell/UsersCell.js new file mode 100644 index 0000000..9fb8655 --- /dev/null +++ b/web/src/components/UsersCell/UsersCell.js @@ -0,0 +1,33 @@ +import { Link, routes } from '@redwoodjs/router' + +import Users from 'src/components/Users' + +export const QUERY = gql` + query USERS { + users { + id + email + createdAt + updatedAt + image + bio + } + } +` + +export const Loading = () =>
Loading...
+ +export const Empty = () => { + return ( +
+ {'No users yet. '} + + {'Create one?'} + +
+ ) +} + +export const Success = ({ users }) => { + return +} diff --git a/web/src/layouts/MainLayout/MainLayout.js b/web/src/layouts/MainLayout/MainLayout.js index 685985f..5d5dcba 100644 --- a/web/src/layouts/MainLayout/MainLayout.js +++ b/web/src/layouts/MainLayout/MainLayout.js @@ -35,7 +35,12 @@ const MainLayout = ({ children }) => { -
  • +
  • + + {isAuthenticated ? 'Log Out' : 'Log In'} + + +
  • diff --git a/web/src/pages/EditUserPage/EditUserPage.js b/web/src/pages/EditUserPage/EditUserPage.js new file mode 100644 index 0000000..5c8fa8d --- /dev/null +++ b/web/src/pages/EditUserPage/EditUserPage.js @@ -0,0 +1,12 @@ +import MainLayout from 'src/layouts/MainLayout' +import EditUserCell from 'src/components/EditUserCell' + +const EditUserPage = ({ id }) => { + return ( + + + + ) +} + +export default EditUserPage diff --git a/web/src/pages/NewUserPage/NewUserPage.js b/web/src/pages/NewUserPage/NewUserPage.js new file mode 100644 index 0000000..0368b02 --- /dev/null +++ b/web/src/pages/NewUserPage/NewUserPage.js @@ -0,0 +1,12 @@ +import MainLayout from 'src/layouts/MainLayout' +import NewUser from 'src/components/NewUser' + +const NewUserPage = () => { + return ( + + + + ) +} + +export default NewUserPage diff --git a/web/src/pages/UserPage/UserPage.js b/web/src/pages/UserPage/UserPage.js new file mode 100644 index 0000000..cf81dc9 --- /dev/null +++ b/web/src/pages/UserPage/UserPage.js @@ -0,0 +1,12 @@ +import MainLayout from 'src/layouts/MainLayout' +import UserCell from 'src/components/UserCell' + +const UserPage = ({ id }) => { + return ( + + + + ) +} + +export default UserPage diff --git a/web/src/pages/UsersPage/UsersPage.js b/web/src/pages/UsersPage/UsersPage.js new file mode 100644 index 0000000..7331b05 --- /dev/null +++ b/web/src/pages/UsersPage/UsersPage.js @@ -0,0 +1,12 @@ +import MainLayout from 'src/layouts/MainLayout' +import UsersCell from 'src/components/UsersCell' + +const UsersPage = () => { + return ( + + + + ) +} + +export default UsersPage