From 1a93e1de4144e9a53986422bd4996b9652b13bd9 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Wed, 17 Jan 2024 00:38:02 -0500 Subject: [PATCH 01/54] ### Eula V1 - Front end logic implemented Signed-off-by: Dave Richer --- client/package-lock.json | 1087 ++++++++++++++++- client/package.json | 1 + client/src/App/App.jsx | 14 +- client/src/components/eula/eula.component.jsx | 242 ++++ 4 files changed, 1339 insertions(+), 5 deletions(-) create mode 100644 client/src/components/eula/eula.component.jsx diff --git a/client/package-lock.json b/client/package-lock.json index 8a4397789..9c20a318a 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -59,6 +59,7 @@ "react-icons": "^5.0.1", "react-image-lightbox": "^5.1.4", "react-intersection-observer": "^9.5.3", + "react-markdown": "^9.0.1", "react-number-format": "^5.1.4", "react-redux": "^9.1.0", "react-resizable": "^3.0.5", @@ -5539,6 +5540,14 @@ "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz", "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==" }, + "node_modules/@types/debug": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "dependencies": { + "@types/ms": "*" + } + }, "node_modules/@types/eslint": { "version": "8.44.8", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.8.tgz", @@ -5562,6 +5571,14 @@ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==" }, + "node_modules/@types/estree-jsx": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.3.tgz", + "integrity": "sha512-pvQ+TKeRHeiUGRhvYwRrQ/ISnohKkSJR14fT2yqyZ4e9K5vqc7hrtY2Y1Dw0ZwAzQ6DQsxsaCUuSIIi8v0Cq6w==", + "dependencies": { + "@types/estree": "*" + } + }, "node_modules/@types/express": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", @@ -5597,6 +5614,14 @@ "@types/node": "*" } }, + "node_modules/@types/hast": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.3.tgz", + "integrity": "sha512-2fYGlaDy/qyLlhidX42wAH0KBi2TCjKMH8CHmBXgRlJ3Y+OXTiqsPQ6IWarZKwF1JoUcAJdPogv1d4b0COTpmQ==", + "dependencies": { + "@types/unist": "*" + } + }, "node_modules/@types/hoist-non-react-statics": { "version": "3.3.5", "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.5.tgz", @@ -5663,11 +5688,24 @@ "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==" }, + "node_modules/@types/mdast": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.3.tgz", + "integrity": "sha512-LsjtqsyF+d2/yFOYaN22dHZI1Cpwkrj+g06G8+qtUKlhovPW89YhqSnfKtMbkgmEtYpH2gydRNULd6y8mciAFg==", + "dependencies": { + "@types/unist": "*" + } + }, "node_modules/@types/mime": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==" }, + "node_modules/@types/ms": { + "version": "0.7.34", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.34.tgz", + "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==" + }, "node_modules/@types/node": { "version": "20.10.4", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.4.tgz", @@ -5828,6 +5866,11 @@ "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==" }, + "node_modules/@types/unist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==" + }, "node_modules/@types/use-sync-external-store": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz", @@ -7257,6 +7300,15 @@ "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", "integrity": "sha512-zj6Z6M7Eq+PBZ7PQxl5NT665MvJdAkzp0f60nAJ+sLaSCBPMwVak5ZegFbgVCzFcCJTKFoMizvM5Ld7+JrRJHA==" }, + "node_modules/bail": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", + "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -7714,6 +7766,15 @@ "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", "dev": true }, + "node_modules/ccount": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", + "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -7737,6 +7798,42 @@ "node": ">=10" } }, + "node_modules/character-entities": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", + "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-html4": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", + "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-legacy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", + "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-reference-invalid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz", + "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/check-more-types": { "version": "2.24.0", "resolved": "https://registry.npmjs.org/check-more-types/-/check-more-types-2.24.0.tgz", @@ -8050,6 +8147,15 @@ "node": ">= 0.8" } }, + "node_modules/comma-separated-tokens": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", + "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/commander": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", @@ -9031,6 +9137,18 @@ "resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz", "integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==" }, + "node_modules/decode-named-character-reference": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.0.2.tgz", + "integrity": "sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==", + "dependencies": { + "character-entities": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/decode-uri-component": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.4.1.tgz", @@ -9278,6 +9396,18 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, + "node_modules/devlop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", + "dependencies": { + "dequal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/didyoumean": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", @@ -10526,6 +10656,15 @@ "node": ">=4.0" } }, + "node_modules/estree-util-is-identifier-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-3.0.0.tgz", + "integrity": "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/estree-walker": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", @@ -10723,8 +10862,7 @@ "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" }, "node_modules/extract-zip": { "version": "2.0.1", @@ -11722,6 +11860,44 @@ "node": ">= 0.4" } }, + "node_modules/hast-util-to-jsx-runtime": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.0.tgz", + "integrity": "sha512-H/y0+IWPdsLLS738P8tDnrQ8Z+dj12zQQ6WC11TIM21C8WFVoIxcqWXf2H3hiTVZjF1AWqoimGwrTWecWrnmRQ==", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "property-information": "^6.0.0", + "space-separated-tokens": "^2.0.0", + "style-to-object": "^1.0.0", + "unist-util-position": "^5.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-whitespace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", + "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", @@ -11856,6 +12032,15 @@ "void-elements": "3.1.0" } }, + "node_modules/html-url-attributes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-url-attributes/-/html-url-attributes-3.0.0.tgz", + "integrity": "sha512-/sXbVCWayk6GDVg3ctOX6nxaVj7So40FcFAnWlWGNAB1LpYKcV5Cd10APjPjW80O7zYW2MsjBV4zZ7IZO5fVow==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/html-webpack-plugin": { "version": "5.5.4", "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.5.4.tgz", @@ -12200,6 +12385,11 @@ "node": ">=10" } }, + "node_modules/inline-style-parser": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.2.tgz", + "integrity": "sha512-EcKzdTHVe8wFVOGEYXiW9WmJXPjqi1T+234YpJr98RiFYKHV3cdy1+3mkTE+KHTHxFFLH51SfaGOoUdW+v7ViQ==" + }, "node_modules/internal-slot": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.6.tgz", @@ -12262,6 +12452,28 @@ "node": ">= 10" } }, + "node_modules/is-alphabetical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", + "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-alphanumerical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", + "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", + "dependencies": { + "is-alphabetical": "^2.0.0", + "is-decimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/is-arguments": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", @@ -12417,6 +12629,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-decimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", + "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/is-docker": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", @@ -12491,6 +12712,15 @@ "node": ">=0.10.0" } }, + "node_modules/is-hexadecimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", + "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/is-installed-globally": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", @@ -14638,6 +14868,15 @@ "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==" }, + "node_modules/longest-streak": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", + "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -14749,6 +14988,151 @@ "resolved": "https://registry.npmjs.org/material-colors/-/material-colors-1.2.6.tgz", "integrity": "sha512-6qE4B9deFBIa9YSpOc9O0Sgc43zTeVYbgDT5veRKSlB2+ZuHNoVVxA1L/ckMUayV9Ay9y7Z/SZCLcGteW9i7bg==" }, + "node_modules/mdast-util-from-markdown": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.0.tgz", + "integrity": "sha512-n7MTOr/z+8NAX/wmhhDji8O3bRvPTV/U0oTCaZJkjhPSKTPhS3xufVhKGF8s1pJ7Ox4QgoIU7KHseh09S+9rTA==", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark": "^4.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-expression": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.0.tgz", + "integrity": "sha512-fGCu8eWdKUKNu5mohVGkhBXCXGnOTLuFqOvGMvdikr+J1w7lDJgxThOKpwRWzzbyXAU2hhSwsmssOY4yTokluw==", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-jsx": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.0.0.tgz", + "integrity": "sha512-XZuPPzQNBPAlaqsTTgRrcJnyFbSOBovSadFgbFu8SnuNgm+6Bdx1K+IWoitsmj6Lq6MNtI+ytOqwN70n//NaBA==", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "parse-entities": "^4.0.0", + "stringify-entities": "^4.0.0", + "unist-util-remove-position": "^5.0.0", + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdxjs-esm": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz", + "integrity": "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-phrasing": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.0.0.tgz", + "integrity": "sha512-xadSsJayQIucJ9n053dfQwVu1kuXg7jCTdYsMK8rqzKZh52nLfSH/k0sAxE0u+pj/zKZX+o5wB+ML5mRayOxFA==", + "dependencies": { + "@types/mdast": "^4.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-hast": { + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.1.0.tgz", + "integrity": "sha512-/e2l/6+OdGp/FB+ctrJ9Avz71AN/GRH3oi/3KAx/kMnoUsD6q0woXlDT8lLEeViVKE7oZxE7RXzvO3T8kF2/sA==", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@ungap/structured-clone": "^1.0.0", + "devlop": "^1.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "trim-lines": "^3.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-markdown": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.0.tgz", + "integrity": "sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ==", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "longest-streak": "^3.0.0", + "mdast-util-phrasing": "^4.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark-util-decode-string": "^2.0.0", + "unist-util-visit": "^5.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", + "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", + "dependencies": { + "@types/mdast": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/mdn-data": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz", @@ -14804,6 +15188,427 @@ "node": ">= 0.6" } }, + "node_modules/micromark": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.0.tgz", + "integrity": "sha512-o/sd0nMof8kYff+TqcDx3VSrgBTcZpSvYcAHIfHhv5VAuNmisCxjhx6YmxS8PFEpb9z5WKWKPdzf0jM23ro3RQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "@types/debug": "^4.0.0", + "debug": "^4.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-core-commonmark": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.0.tgz", + "integrity": "sha512-jThOz/pVmAYUtkroV3D5c1osFXAMv9e0ypGDOIZuCeAe91/sD6BoE2Sjzt30yuXtwOYUmySOhMas/PVyh02itA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-destination": "^2.0.0", + "micromark-factory-label": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-factory-title": "^2.0.0", + "micromark-factory-whitespace": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-html-tag-name": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-destination": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.0.tgz", + "integrity": "sha512-j9DGrQLm/Uhl2tCzcbLhy5kXsgkHUrjJHg4fFAeoMRwJmJerT9aw4FEhIbZStWN8A3qMwOp1uzHr4UL8AInxtA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-label": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.0.tgz", + "integrity": "sha512-RR3i96ohZGde//4WSe/dJsxOX6vxIg9TimLAS3i4EhBAFx8Sm5SmqVfR8E87DPSR31nEAjZfbt91OMZWcNgdZw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-space": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", + "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-title": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.0.tgz", + "integrity": "sha512-jY8CSxmpWLOxS+t8W+FG3Xigc0RDQA9bKMY/EwILvsesiRniiVMejYTE4wumNc2f4UbAa4WsHqe3J1QS1sli+A==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-whitespace": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.0.tgz", + "integrity": "sha512-28kbwaBjc5yAI1XadbdPYHX/eDnqaUFVikLwrO7FDnKG7lpgxnvk/XGRhX/PN0mOZ+dBSZ+LgunHS+6tYQAzhA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-character": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.0.1.tgz", + "integrity": "sha512-3wgnrmEAJ4T+mGXAUfMvMAbxU9RDG43XmGce4j6CwPtVxB3vfwXSZ6KhFwDzZ3mZHhmPimMAXg71veiBGzeAZw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-chunked": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.0.tgz", + "integrity": "sha512-anK8SWmNphkXdaKgz5hJvGa7l00qmcaUQoMYsBwDlSKFKjc6gjGXPDw3FNL3Nbwq5L8gE+RCbGqTw49FK5Qyvg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-classify-character": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.0.tgz", + "integrity": "sha512-S0ze2R9GH+fu41FA7pbSqNWObo/kzwf8rN/+IGlW/4tC6oACOs8B++bh+i9bVyNnwCcuksbFwsBme5OCKXCwIw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-combine-extensions": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.0.tgz", + "integrity": "sha512-vZZio48k7ON0fVS3CUgFatWHoKbbLTK/rT7pzpJ4Bjp5JjkZeasRfrS9wsBdDJK2cJLHMckXZdzPSSr1B8a4oQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-chunked": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-numeric-character-reference": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.1.tgz", + "integrity": "sha512-bmkNc7z8Wn6kgjZmVHOX3SowGmVdhYS7yBpMnuMnPzDq/6xwVA604DuOXMZTO1lvq01g+Adfa0pE2UKGlxL1XQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.0.tgz", + "integrity": "sha512-r4Sc6leeUTn3P6gk20aFMj2ntPwn6qpDZqWvYmAG6NgvFTIlj4WtrAudLi65qYoaGdXYViXYw2pkmn7QnIFasA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-encode": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.0.tgz", + "integrity": "sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-util-html-tag-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.0.tgz", + "integrity": "sha512-xNn4Pqkj2puRhKdKTm8t1YHC/BAjx6CEwRFXntTaRf/x16aqka6ouVoutm+QdkISTlT7e2zU7U4ZdlDLJd2Mcw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-util-normalize-identifier": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.0.tgz", + "integrity": "sha512-2xhYT0sfo85FMrUPtHcPo2rrp1lwbDEEzpx7jiH2xXJLqBuy4H0GgXk5ToU8IEwoROtXuL8ND0ttVa4rNqYK3w==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-resolve-all": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.0.tgz", + "integrity": "sha512-6KU6qO7DZ7GJkaCgwBNtplXCvGkJToU86ybBAUdavvgsCiG8lSSvYxr9MhwmQ+udpzywHsl4RpGJsYWG1pDOcA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-sanitize-uri": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.0.tgz", + "integrity": "sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-subtokenize": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.0.0.tgz", + "integrity": "sha512-vc93L1t+gpR3p8jxeVdaYlbV2jTYteDje19rNSS/H5dlhxUYll5Fy6vJ2cDwP8RnsXi818yGty1ayP55y3W6fg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-util-types": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.0.tgz", + "integrity": "sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, "node_modules/micromatch": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", @@ -15532,6 +16337,30 @@ "node": ">=6" } }, + "node_modules/parse-entities": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.1.tgz", + "integrity": "sha512-SWzvYcSJh4d/SGLIOQfZ/CoNv6BTlI6YEQ7Nj82oDVnRpwe/Z/F1EMx42x3JAOwGBlCjeCH0BRJQbQ/opHL17w==", + "dependencies": { + "@types/unist": "^2.0.0", + "character-entities": "^2.0.0", + "character-entities-legacy": "^3.0.0", + "character-reference-invalid": "^2.0.0", + "decode-named-character-reference": "^1.0.0", + "is-alphanumerical": "^2.0.0", + "is-decimal": "^2.0.0", + "is-hexadecimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/parse-entities/node_modules/@types/unist": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", + "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==" + }, "node_modules/parse-json": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", @@ -17144,6 +17973,15 @@ "react-is": "^16.13.1" } }, + "node_modules/property-information": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.4.0.tgz", + "integrity": "sha512-9t5qARVofg2xQqKtytzt+lZ4d1Qvj8t5B8fEwXK6qOfgRLgH/b13QlgEyDh033NOS31nXeFbYv7CLUDG1CeifQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/protobufjs": { "version": "7.2.5", "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.5.tgz", @@ -18364,6 +19202,31 @@ "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" }, + "node_modules/react-markdown": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-9.0.1.tgz", + "integrity": "sha512-186Gw/vF1uRkydbsOIkcGXw7aHq0sZOCRFFjGrr7b9+nVZg4UfA4enXCaxm4fUzecU38sWfrNDitGhshuU7rdg==", + "dependencies": { + "@types/hast": "^3.0.0", + "devlop": "^1.0.0", + "hast-util-to-jsx-runtime": "^2.0.0", + "html-url-attributes": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "remark-parse": "^11.0.0", + "remark-rehype": "^11.0.0", + "unified": "^11.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + }, + "peerDependencies": { + "@types/react": ">=18", + "react": ">=18" + } + }, "node_modules/react-modal": { "version": "3.16.1", "resolved": "https://registry.npmjs.org/react-modal/-/react-modal-3.16.1.tgz", @@ -18981,6 +19844,37 @@ "node": ">= 0.10" } }, + "node_modules/remark-parse": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", + "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-rehype": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.0.tgz", + "integrity": "sha512-z3tJrAs2kIs1AqIIy6pzHmAHlF1hWQ+OdY4/hv+Wxe35EhyLKcajL33iUEn3ScxtFox9nUvRufR/Zre8Q08H/g==", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "mdast-util-to-hast": "^13.0.0", + "unified": "^11.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/renderkid": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", @@ -20028,6 +20922,15 @@ "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", "deprecated": "Please use @jridgewell/sourcemap-codec instead" }, + "node_modules/space-separated-tokens": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", + "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/spdy": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", @@ -20345,6 +21248,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/stringify-entities": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.3.tgz", + "integrity": "sha512-BP9nNHMhhfcMbiuQKCqMjhDP5yBCAxsPu4pHFFzJ6Alo9dZgY4VLDPutXqIjpRiMoKdp7Av85Gr73Q5uH9k7+g==", + "dependencies": { + "character-entities-html4": "^2.0.0", + "character-entities-legacy": "^3.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/stringify-object": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", @@ -20419,6 +21335,14 @@ "webpack": "^5.0.0" } }, + "node_modules/style-to-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.5.tgz", + "integrity": "sha512-rDRwHtoDD3UMMrmZ6BzOW0naTjMsVZLIjsGleSKS/0Oz+cgCfAPRspaqJuE8rDzpKha/nEvnM0IF4seEAZUTKQ==", + "dependencies": { + "inline-style-parser": "0.2.2" + } + }, "node_modules/style-utils": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/style-utils/-/style-utils-0.2.1.tgz", @@ -21253,6 +22177,24 @@ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" }, + "node_modules/trim-lines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", + "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/trough": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/trough/-/trough-2.1.0.tgz", + "integrity": "sha512-AqTiAOLcj85xS7vQ8QkAV41hPDIJ71XJB4RCUrzo/1GM2CQwhkJGaf9Hgr7BOugMRpgGUrqRg/DrBDl4H40+8g==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/tryer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/tryer/-/tryer-1.0.1.tgz", @@ -21646,6 +22588,35 @@ "node": ">=4" } }, + "node_modules/unified": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.4.tgz", + "integrity": "sha512-apMPnyLjAX+ty4OrNap7yumyVAMlKx5IWU2wlzzUdYJO9A8f1p9m/gywF/GM2ZDFcjQPrx59Mc90KwmxsoklxQ==", + "dependencies": { + "@types/unist": "^3.0.0", + "bail": "^2.0.0", + "devlop": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^4.0.0", + "trough": "^2.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unified/node_modules/is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/unique-string": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", @@ -21657,6 +22628,82 @@ "node": ">=8" } }, + "node_modules/unist-util-is": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", + "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", + "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-remove-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-5.0.0.tgz", + "integrity": "sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-visit": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-parents": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", + "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/universal-cookie": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/universal-cookie/-/universal-cookie-7.0.0.tgz", @@ -21902,6 +22949,33 @@ "extsprintf": "^1.2.0" } }, + "node_modules/vfile": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.1.tgz", + "integrity": "sha512-1bYqc7pt6NIADBJ98UiG0Bn/CHIVOoZ/IyEkqIruLg0mE1BKzkOXY2D6CSqQIcKqgadppE5lrxgWXJmXd7zZJw==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-message": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz", + "integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/victory-vendor": { "version": "36.7.0", "resolved": "https://registry.npmjs.org/victory-vendor/-/victory-vendor-36.7.0.tgz", @@ -23054,6 +24128,15 @@ "dependencies": { "zen-observable": "0.8.15" } + }, + "node_modules/zwitch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", + "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } } } } diff --git a/client/package.json b/client/package.json index f8d1b1c2e..e8e261b3e 100644 --- a/client/package.json +++ b/client/package.json @@ -55,6 +55,7 @@ "react-icons": "^5.0.1", "react-image-lightbox": "^5.1.4", "react-intersection-observer": "^9.5.3", + "react-markdown": "^9.0.1", "react-number-format": "^5.1.4", "react-redux": "^9.1.0", "react-resizable": "^3.0.5", diff --git a/client/src/App/App.jsx b/client/src/App/App.jsx index 4f8695240..a0f02e8cf 100644 --- a/client/src/App/App.jsx +++ b/client/src/App/App.jsx @@ -8,6 +8,7 @@ import {Route, Routes} from "react-router-dom"; import {createStructuredSelector} from "reselect"; import DocumentEditorContainer from "../components/document-editor/document-editor.container"; import ErrorBoundary from "../components/error-boundary/error-boundary.component"; + //Component Imports import LoadingSpinner from "../components/loading-spinner/loading-spinner.component"; import DisclaimerPage from "../pages/disclaimer/disclaimer.page"; @@ -20,6 +21,7 @@ import {selectBodyshop, selectCurrentUser,} from "../redux/user/user.selectors"; import PrivateRoute from "../components/PrivateRoute"; import "./App.styles.scss"; import handleBeta from "../utils/betaHandler"; +import Eula, {eulaIsApplicable} from "../components/eula/eula.component"; const ResetPassword = lazy(() => import("../pages/reset-password/reset-password.component") @@ -42,8 +44,8 @@ const mapDispatchToProps = (dispatch) => ({ }); export function App({bodyshop, checkUserSession, currentUser, online, setOnline}) { - const client = useSplitClient().client; + const [isAccepted, setIsAccepted] = useState(false); const [listenersAdded, setListenersAdded] = useState(false) const {t} = useTranslation(); @@ -123,6 +125,10 @@ export function App({bodyshop, checkUserSession, currentUser, online, setOnline} /> ); + if (eulaIsApplicable({currentUser, isAccepted})) { + return + } + // Any route that is not assigned and matched will default to the Landing Page component return ( }> @@ -133,10 +139,12 @@ export function App({bodyshop, checkUserSession, currentUser, online, setOnline} }/> }/> }/> - }> + }> }/> - }> + }> }/> }> diff --git a/client/src/components/eula/eula.component.jsx b/client/src/components/eula/eula.component.jsx new file mode 100644 index 000000000..6981fbe92 --- /dev/null +++ b/client/src/components/eula/eula.component.jsx @@ -0,0 +1,242 @@ +import React, {useState} from "react"; +import {Button, Card, Checkbox, Col, Form, Input, Modal, Row, Space} from "antd"; +import Markdown from "react-markdown"; + +const EULA = `# End User License Agreement (EULA) +## 1. Introduction + +This End User License Agreement ("EULA") governs your use of our website and any related services. By using our website, you agree to be bound by the terms of this EULA. + +## 2. License Grant + +We grant you a non-exclusive, non-transferable, revocable license to use our website for your personal, non-commercial use. + +## 3. Restrictions + +You agree not to: + +- Use our website for any illegal or unauthorized purpose +- Attempt to reverse engineer or otherwise derive the source code of our website + +## 4. Termination + +We reserve the right to terminate your license to use our website at any time and for any reason. + +## 5. Disclaimer of Warranties + +Our website is provided "as is" and without any warranty of any kind. + +## 6. Limitation of Liability + +We will not be liable for any damages or losses arising from your use of our website. + +## 7. Governing Law + +This EULA is governed by the laws of [Your Jurisdiction]. + +## 8. Changes to this EULA + +We reserve the right to modify this EULA at any time. Your continued use of our website after any such changes constitutes your acceptance of the new EULA. + +## 9. Contact Us + +If you have any questions about this EULA, please contact us at [Your Contact Information]. +## 1. Introduction + +This End User License Agreement ("EULA") governs your use of our website and any related services. By using our website, you agree to be bound by the terms of this EULA. + +## 2. License Grant + +We grant you a non-exclusive, non-transferable, revocable license to use our website for your personal, non-commercial use. + +## 3. Restrictions + +You agree not to: + +- Use our website for any illegal or unauthorized purpose +- Attempt to reverse engineer or otherwise derive the source code of our website + +## 4. Termination + +We reserve the right to terminate your license to use our website at any time and for any reason. + +## 5. Disclaimer of Warranties + +Our website is provided "as is" and without any warranty of any kind. + +## 6. Limitation of Liability + +We will not be liable for any damages or losses arising from your use of our website. + +## 7. Governing Law + +This EULA is governed by the laws of [Your Jurisdiction]. + +## 8. Changes to this EULA + +We reserve the right to modify this EULA at any time. Your continued use of our website after any such changes constitutes your acceptance of the new EULA. + +## 9. Contact Us + +If you have any questions about this EULA, please contact us at [Your Contact Information]. +## 1. Introduction + +This End User License Agreement ("EULA") governs your use of our website and any related services. By using our website, you agree to be bound by the terms of this EULA. + +## 2. License Grant + +We grant you a non-exclusive, non-transferable, revocable license to use our website for your personal, non-commercial use. + +## 3. Restrictions + +You agree not to: + +- Use our website for any illegal or unauthorized purpose +- Attempt to reverse engineer or otherwise derive the source code of our website + +## 4. Termination + +We reserve the right to terminate your license to use our website at any time and for any reason. + +## 5. Disclaimer of Warranties + +Our website is provided "as is" and without any warranty of any kind. + +## 6. Limitation of Liability + +We will not be liable for any damages or losses arising from your use of our website. + +## 7. Governing Law + +This EULA is governed by the laws of [Your Jurisdiction]. + +## 8. Changes to this EULA + +We reserve the right to modify this EULA at any time. Your continued use of our website after any such changes constitutes your acceptance of the new EULA. + +## 9. Contact Us + +If you have any questions about this EULA, please contact us at [Your Contact Information].` + +/** + * Returns true if the EULA is applicable to the current user. + * @param currentUser + * @param online + * @param bodyshop + * @param client + * @returns {boolean} + */ +export function eulaIsApplicable({currentUser, isAccepted}) { + return !isAccepted || currentUser.authorized === false; +} + +export default function Eula({setIsAccepted}) { + + const [isModalOpen, setIsModalOpen] = useState(true); + + const handleAccept = (values) => { + localStorage.setItem('termsAccepted', 'true'); + setIsAccepted(true); + setIsModalOpen(false); + }; + + return ( + <> + + + )} + closable={false} + > + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + value ? Promise.resolve() : Promise.reject(new Error('You must accept the terms and conditions')), + }, + ]} + > + I accept the terms and conditions + +
+
+
+
+} + From 4a9684ba87b3993c12dd1d1c2f82b182a7e741e8 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Wed, 17 Jan 2024 19:36:21 -0500 Subject: [PATCH 02/54] - progress Signed-off-by: Dave Richer --- client/src/App/App.jsx | 7 +- client/src/components/eula/eula.component.jsx | 134 ++---------------- client/src/components/eula/testData.json | 3 + client/src/graphql/bodyshop.queries.js | 15 ++ client/src/redux/user/user.actions.js | 6 + client/src/redux/user/user.reducer.js | 2 + client/src/redux/user/user.sagas.js | 19 +++ client/src/redux/user/user.selectors.js | 5 + client/src/redux/user/user.types.js | 1 + client/src/utils/day.js | 6 - hasura/metadata/tables.yaml | 74 ++++++++++ .../down.sql | 1 + .../up.sql | 18 +++ .../down.sql | 1 + .../up.sql | 18 +++ 15 files changed, 174 insertions(+), 136 deletions(-) create mode 100644 client/src/components/eula/testData.json create mode 100644 hasura/migrations/1705522419599_create_table_public_eulas/down.sql create mode 100644 hasura/migrations/1705522419599_create_table_public_eulas/up.sql create mode 100644 hasura/migrations/1705522869369_create_table_public_eula_acceptances/down.sql create mode 100644 hasura/migrations/1705522869369_create_table_public_eula_acceptances/up.sql diff --git a/client/src/App/App.jsx b/client/src/App/App.jsx index a0f02e8cf..ae69a9370 100644 --- a/client/src/App/App.jsx +++ b/client/src/App/App.jsx @@ -21,7 +21,7 @@ import {selectBodyshop, selectCurrentUser,} from "../redux/user/user.selectors"; import PrivateRoute from "../components/PrivateRoute"; import "./App.styles.scss"; import handleBeta from "../utils/betaHandler"; -import Eula, {eulaIsApplicable} from "../components/eula/eula.component"; +import Eula from "../components/eula/eula.component"; const ResetPassword = lazy(() => import("../pages/reset-password/reset-password.component") @@ -45,7 +45,6 @@ const mapDispatchToProps = (dispatch) => ({ export function App({bodyshop, checkUserSession, currentUser, online, setOnline}) { const client = useSplitClient().client; - const [isAccepted, setIsAccepted] = useState(false); const [listenersAdded, setListenersAdded] = useState(false) const {t} = useTranslation(); @@ -125,8 +124,8 @@ export function App({bodyshop, checkUserSession, currentUser, online, setOnline} /> ); - if (eulaIsApplicable({currentUser, isAccepted})) { - return + if (!currentUser.isEulaAccepted) { + return } // Any route that is not assigned and matched will default to the Landing Page component diff --git a/client/src/components/eula/eula.component.jsx b/client/src/components/eula/eula.component.jsx index 6981fbe92..af3bc819e 100644 --- a/client/src/components/eula/eula.component.jsx +++ b/client/src/components/eula/eula.component.jsx @@ -2,142 +2,24 @@ import React, {useState} from "react"; import {Button, Card, Checkbox, Col, Form, Input, Modal, Row, Space} from "antd"; import Markdown from "react-markdown"; -const EULA = `# End User License Agreement (EULA) -## 1. Introduction - -This End User License Agreement ("EULA") governs your use of our website and any related services. By using our website, you agree to be bound by the terms of this EULA. - -## 2. License Grant - -We grant you a non-exclusive, non-transferable, revocable license to use our website for your personal, non-commercial use. - -## 3. Restrictions - -You agree not to: - -- Use our website for any illegal or unauthorized purpose -- Attempt to reverse engineer or otherwise derive the source code of our website - -## 4. Termination - -We reserve the right to terminate your license to use our website at any time and for any reason. - -## 5. Disclaimer of Warranties - -Our website is provided "as is" and without any warranty of any kind. - -## 6. Limitation of Liability - -We will not be liable for any damages or losses arising from your use of our website. - -## 7. Governing Law - -This EULA is governed by the laws of [Your Jurisdiction]. - -## 8. Changes to this EULA - -We reserve the right to modify this EULA at any time. Your continued use of our website after any such changes constitutes your acceptance of the new EULA. - -## 9. Contact Us - -If you have any questions about this EULA, please contact us at [Your Contact Information]. -## 1. Introduction - -This End User License Agreement ("EULA") governs your use of our website and any related services. By using our website, you agree to be bound by the terms of this EULA. - -## 2. License Grant - -We grant you a non-exclusive, non-transferable, revocable license to use our website for your personal, non-commercial use. - -## 3. Restrictions - -You agree not to: - -- Use our website for any illegal or unauthorized purpose -- Attempt to reverse engineer or otherwise derive the source code of our website - -## 4. Termination - -We reserve the right to terminate your license to use our website at any time and for any reason. - -## 5. Disclaimer of Warranties - -Our website is provided "as is" and without any warranty of any kind. - -## 6. Limitation of Liability - -We will not be liable for any damages or losses arising from your use of our website. - -## 7. Governing Law - -This EULA is governed by the laws of [Your Jurisdiction]. - -## 8. Changes to this EULA - -We reserve the right to modify this EULA at any time. Your continued use of our website after any such changes constitutes your acceptance of the new EULA. - -## 9. Contact Us - -If you have any questions about this EULA, please contact us at [Your Contact Information]. -## 1. Introduction - -This End User License Agreement ("EULA") governs your use of our website and any related services. By using our website, you agree to be bound by the terms of this EULA. - -## 2. License Grant - -We grant you a non-exclusive, non-transferable, revocable license to use our website for your personal, non-commercial use. - -## 3. Restrictions - -You agree not to: - -- Use our website for any illegal or unauthorized purpose -- Attempt to reverse engineer or otherwise derive the source code of our website - -## 4. Termination - -We reserve the right to terminate your license to use our website at any time and for any reason. - -## 5. Disclaimer of Warranties - -Our website is provided "as is" and without any warranty of any kind. - -## 6. Limitation of Liability - -We will not be liable for any damages or losses arising from your use of our website. - -## 7. Governing Law - -This EULA is governed by the laws of [Your Jurisdiction]. - -## 8. Changes to this EULA - -We reserve the right to modify this EULA at any time. Your continued use of our website after any such changes constitutes your acceptance of the new EULA. - -## 9. Contact Us - -If you have any questions about this EULA, please contact us at [Your Contact Information].` +const EULA = require('./testData.json').eula; /** - * Returns true if the EULA is applicable to the current user. - * @param currentUser - * @param online - * @param bodyshop - * @param client - * @returns {boolean} + * Returns the EULA component. + * @returns {Element} + * @constructor */ -export function eulaIsApplicable({currentUser, isAccepted}) { - return !isAccepted || currentUser.authorized === false; -} -export default function Eula({setIsAccepted}) { +//REDUXY THIS +export default function Eula({eulaContentToShow}) { const [isModalOpen, setIsModalOpen] = useState(true); const handleAccept = (values) => { localStorage.setItem('termsAccepted', 'true'); - setIsAccepted(true); setIsModalOpen(false); + + //Insert and Dispatch the action to rechecuk force acceptance. }; return ({ type: UserActionTypes.SET_AUTH_LEVEL, payload: authlevel, }); + +export const setEulaContentToShow = (eulaContent) => ({ + type: UserActionTypes.SET_EULA_CONTENT, + payload: eulaContent, +}); + diff --git a/client/src/redux/user/user.reducer.js b/client/src/redux/user/user.reducer.js index f9e391e61..641d127c2 100644 --- a/client/src/redux/user/user.reducer.js +++ b/client/src/redux/user/user.reducer.js @@ -3,6 +3,7 @@ import UserActionTypes from "./user.types"; const INITIAL_STATE = { currentUser: { authorized: null, + eulaIsAccepted: false, //language: "en-US" }, bodyshop: null, @@ -17,6 +18,7 @@ const INITIAL_STATE = { loading: false, }, authLevel: 0, + eulaContentToShow:null }; const userReducer = (state = INITIAL_STATE, action) => { diff --git a/client/src/redux/user/user.sagas.js b/client/src/redux/user/user.sagas.js index 03c217df0..f8837865c 100644 --- a/client/src/redux/user/user.sagas.js +++ b/client/src/redux/user/user.sagas.js @@ -43,6 +43,10 @@ import { validatePasswordResetSuccess, } from "./user.actions"; import UserActionTypes from "./user.types"; +import client from "../../utils/GraphQLClient"; +import {QUERY_SCHEDULE_LOAD_DATA} from "../../graphql/appointments.queries"; +import {QUERY_EULA} from "../../graphql/bodyshop.queries"; +import day from "../../utils/day"; const fpPromise = FingerprintJS.load(); @@ -73,6 +77,8 @@ export function* signInWithEmail({ payload: { email, password } }) { export function* onCheckUserSession() { yield takeLatest(UserActionTypes.CHECK_USER_SESSION, isUserAuthenticated); } + + export function* isUserAuthenticated() { try { logImEXEvent("redux_auth_check"); @@ -85,6 +91,18 @@ export function* isUserAuthenticated() { LogRocket.identify(user.email); + // Get latest eula record and see if they have accepted + // if they have add isEulaAccepted true, if not, take eula text, display it and ask them to accept. + const eulaQuery = yield client.query({ + query: QUERY_EULA, + variables: { + now: day() + }, + }); +console.log("Query Data", eulaQuery) + + const isEulaAccepted = eulaQuery.data.eulas.length > 0 && eulaQuery.data.eulas[0].eula_acceptances.length > 0; + yield put( signInSuccess({ uid: user.uid, @@ -92,6 +110,7 @@ export function* isUserAuthenticated() { displayName: user.displayName, photoURL: user.photoURL, authorized: true, + isEulaAccepted, }) ); } catch (error) { diff --git a/client/src/redux/user/user.selectors.js b/client/src/redux/user/user.selectors.js index ba02c677b..c3d0fe572 100644 --- a/client/src/redux/user/user.selectors.js +++ b/client/src/redux/user/user.selectors.js @@ -36,3 +36,8 @@ export const selectLoginLoading = createSelector( [selectUser], (user) => user.loginLoading ); + +export const selectEulaContentToShow = createSelector( + [selectUser], + (user) => user.eulaContentToShow +); diff --git a/client/src/redux/user/user.types.js b/client/src/redux/user/user.types.js index 7728fcb53..cd4e952cd 100644 --- a/client/src/redux/user/user.types.js +++ b/client/src/redux/user/user.types.js @@ -32,5 +32,6 @@ const UserActionTypes = { CHECK_ACTION_CODE_START: "CHECK_ACTION_CODE_START", CHECK_ACTION_CODE_SUCCESS: "CHECK_ACTION_CODE_SUCCESS", CHECK_ACTION_CODE_FAILURE: "CHECK_ACTION_CODE_FAILURE", + SET_EULA_CONTENT: "SET_EULA_CONTENT" }; export default UserActionTypes; diff --git a/client/src/utils/day.js b/client/src/utils/day.js index b16e16262..0b29aac61 100644 --- a/client/src/utils/day.js +++ b/client/src/utils/day.js @@ -32,11 +32,6 @@ import objectSupport from 'dayjs/plugin/objectSupport'; import toArray from 'dayjs/plugin/toArray'; import toObject from 'dayjs/plugin/toObject'; -// import badMutable from 'dayjs/plugin/badMutable'; -// import preParsePostFormat from 'dayjs/plugin/preParsePostFormat'; - - -// dayjs.extend(badMutable); // TODO: Client Update - This is not advised, scoreboard page dayjs.extend(toObject); dayjs.extend(toArray); dayjs.extend(objectSupport); @@ -46,7 +41,6 @@ dayjs.extend(isToday); dayjs.extend(localeData); dayjs.extend(quarterOfYear); dayjs.extend(localizedFormat); -// dayjs.extend(preParsePostFormat); // TODO: This should not be needed dayjs.extend(isLeapYear); dayjs.extend(isoWeeksInYear); dayjs.extend(isoWeek); diff --git a/hasura/metadata/tables.yaml b/hasura/metadata/tables.yaml index 9867b3f8e..f4e4d99a7 100644 --- a/hasura/metadata/tables.yaml +++ b/hasura/metadata/tables.yaml @@ -2423,6 +2423,73 @@ _eq: X-Hasura-User-Id - active: _eq: true +- table: + name: eula_acceptances + schema: public + object_relationships: + - name: eula + using: + foreign_key_constraint_on: eulaid + - name: user + using: + foreign_key_constraint_on: useremail + insert_permissions: + - role: user + permission: + check: + user: + authid: + _eq: X-Hasura-User-Id + columns: + - address + - buisness_name + - date_accepted + - eulaid + - first_name + - last_name + - phone_number + - useremail + select_permissions: + - role: user + permission: + columns: + - address + - buisness_name + - first_name + - last_name + - phone_number + - useremail + - created_at + - date_accepted + - updated_at + - eulaid + - id + filter: + user: + authid: + _eq: X-Hasura-User-Id +- table: + name: eulas + schema: public + array_relationships: + - name: eula_acceptances + using: + foreign_key_constraint_on: + column: eulaid + table: + name: eula_acceptances + schema: public + select_permissions: + - role: user + permission: + columns: + - id + - created_at + - updated_at + - effective_date + - end_date + - content + filter: {} - table: name: exportlog schema: public @@ -5888,6 +5955,13 @@ table: name: email_audit_trail schema: public + - name: eula_acceptances + using: + foreign_key_constraint_on: + column: useremail + table: + name: eula_acceptances + schema: public - name: exportlogs using: foreign_key_constraint_on: diff --git a/hasura/migrations/1705522419599_create_table_public_eulas/down.sql b/hasura/migrations/1705522419599_create_table_public_eulas/down.sql new file mode 100644 index 000000000..bea9117e2 --- /dev/null +++ b/hasura/migrations/1705522419599_create_table_public_eulas/down.sql @@ -0,0 +1 @@ +DROP TABLE "public"."eulas"; diff --git a/hasura/migrations/1705522419599_create_table_public_eulas/up.sql b/hasura/migrations/1705522419599_create_table_public_eulas/up.sql new file mode 100644 index 000000000..31eaa5f8d --- /dev/null +++ b/hasura/migrations/1705522419599_create_table_public_eulas/up.sql @@ -0,0 +1,18 @@ +CREATE TABLE "public"."eulas" ("id" uuid NOT NULL DEFAULT gen_random_uuid(), "created_at" timestamptz NOT NULL DEFAULT now(), "updated_at" timestamptz NOT NULL DEFAULT now(), "effective_date" timestamptz NOT NULL, "end_date" timestamptz, "content" text NOT NULL, PRIMARY KEY ("id") ); +CREATE OR REPLACE FUNCTION "public"."set_current_timestamp_updated_at"() +RETURNS TRIGGER AS $$ +DECLARE + _new record; +BEGIN + _new := NEW; + _new."updated_at" = NOW(); + RETURN _new; +END; +$$ LANGUAGE plpgsql; +CREATE TRIGGER "set_public_eulas_updated_at" +BEFORE UPDATE ON "public"."eulas" +FOR EACH ROW +EXECUTE PROCEDURE "public"."set_current_timestamp_updated_at"(); +COMMENT ON TRIGGER "set_public_eulas_updated_at" ON "public"."eulas" +IS 'trigger to set value of column "updated_at" to current timestamp on row update'; +CREATE EXTENSION IF NOT EXISTS pgcrypto; diff --git a/hasura/migrations/1705522869369_create_table_public_eula_acceptances/down.sql b/hasura/migrations/1705522869369_create_table_public_eula_acceptances/down.sql new file mode 100644 index 000000000..29d08ee95 --- /dev/null +++ b/hasura/migrations/1705522869369_create_table_public_eula_acceptances/down.sql @@ -0,0 +1 @@ +DROP TABLE "public"."eula_acceptances"; diff --git a/hasura/migrations/1705522869369_create_table_public_eula_acceptances/up.sql b/hasura/migrations/1705522869369_create_table_public_eula_acceptances/up.sql new file mode 100644 index 000000000..18dc09e8e --- /dev/null +++ b/hasura/migrations/1705522869369_create_table_public_eula_acceptances/up.sql @@ -0,0 +1,18 @@ +CREATE TABLE "public"."eula_acceptances" ("id" uuid NOT NULL DEFAULT gen_random_uuid(), "created_at" timestamptz NOT NULL DEFAULT now(), "updated_at" timestamptz NOT NULL DEFAULT now(), "eulaid" uuid NOT NULL, "date_accepted" timestamptz NOT NULL, "first_name" text NOT NULL, "last_name" text NOT NULL, "address" text NOT NULL, "phone_number" Text NOT NULL, "buisness_name" Text NOT NULL, "useremail" text NOT NULL, PRIMARY KEY ("id") , FOREIGN KEY ("eulaid") REFERENCES "public"."eulas"("id") ON UPDATE restrict ON DELETE restrict, FOREIGN KEY ("useremail") REFERENCES "public"."users"("email") ON UPDATE restrict ON DELETE restrict); +CREATE OR REPLACE FUNCTION "public"."set_current_timestamp_updated_at"() +RETURNS TRIGGER AS $$ +DECLARE + _new record; +BEGIN + _new := NEW; + _new."updated_at" = NOW(); + RETURN _new; +END; +$$ LANGUAGE plpgsql; +CREATE TRIGGER "set_public_eula_acceptances_updated_at" +BEFORE UPDATE ON "public"."eula_acceptances" +FOR EACH ROW +EXECUTE PROCEDURE "public"."set_current_timestamp_updated_at"(); +COMMENT ON TRIGGER "set_public_eula_acceptances_updated_at" ON "public"."eula_acceptances" +IS 'trigger to set value of column "updated_at" to current timestamp on row update'; +CREATE EXTENSION IF NOT EXISTS pgcrypto; From 67e475ce21567ab703ebc1a05959facc05ad2284 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Wed, 17 Jan 2024 22:26:32 -0500 Subject: [PATCH 03/54] - Merge Release Signed-off-by: Dave Richer --- client/src/redux/user/user.sagas.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/client/src/redux/user/user.sagas.js b/client/src/redux/user/user.sagas.js index f8837865c..867c8e0cb 100644 --- a/client/src/redux/user/user.sagas.js +++ b/client/src/redux/user/user.sagas.js @@ -44,7 +44,6 @@ import { } from "./user.actions"; import UserActionTypes from "./user.types"; import client from "../../utils/GraphQLClient"; -import {QUERY_SCHEDULE_LOAD_DATA} from "../../graphql/appointments.queries"; import {QUERY_EULA} from "../../graphql/bodyshop.queries"; import day from "../../utils/day"; @@ -91,15 +90,12 @@ export function* isUserAuthenticated() { LogRocket.identify(user.email); - // Get latest eula record and see if they have accepted - // if they have add isEulaAccepted true, if not, take eula text, display it and ask them to accept. const eulaQuery = yield client.query({ query: QUERY_EULA, variables: { now: day() }, }); -console.log("Query Data", eulaQuery) const isEulaAccepted = eulaQuery.data.eulas.length > 0 && eulaQuery.data.eulas[0].eula_acceptances.length > 0; From 6937f331344f6e968799bba3063d0586e9d0b664 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Fri, 19 Jan 2024 20:55:15 -0500 Subject: [PATCH 04/54] - Eula Progress Signed-off-by: Dave Richer --- client/eulaize.js | 16 ++ client/package-lock.json | 46 ++--- client/package.json | 1 + client/src/App/App.jsx | 2 +- client/src/components/eula/eula.component.jsx | 159 +++++++++++++----- client/src/components/eula/testData.json | 3 - client/src/graphql/user.queries.js | 8 + client/src/redux/user/user.actions.js | 10 +- client/src/redux/user/user.reducer.js | 12 +- client/src/redux/user/user.sagas.js | 5 +- client/src/redux/user/user.selectors.js | 4 +- client/src/redux/user/user.types.js | 3 +- client/test.md | 31 ++++ hasura/metadata/functions.yaml | 3 + hasura/metadata/tables.yaml | 9 +- .../down.sql | 1 + .../up.sql | 1 + .../down.sql | 1 + .../up.sql | 1 + .../down.sql | 1 + .../up.sql | 1 + 21 files changed, 235 insertions(+), 83 deletions(-) create mode 100644 client/eulaize.js delete mode 100644 client/src/components/eula/testData.json create mode 100644 client/test.md create mode 100644 hasura/migrations/1705712927924_alter_table_public_eula_acceptances_alter_column_buisness_name/down.sql create mode 100644 hasura/migrations/1705712927924_alter_table_public_eula_acceptances_alter_column_buisness_name/up.sql create mode 100644 hasura/migrations/1705715500461_alter_table_public_eula_acceptances_alter_column_phone_number/down.sql create mode 100644 hasura/migrations/1705715500461_alter_table_public_eula_acceptances_alter_column_phone_number/up.sql create mode 100644 hasura/migrations/1705715523486_alter_table_public_eula_acceptances_alter_column_address/down.sql create mode 100644 hasura/migrations/1705715523486_alter_table_public_eula_acceptances_alter_column_address/up.sql diff --git a/client/eulaize.js b/client/eulaize.js new file mode 100644 index 000000000..26b972f15 --- /dev/null +++ b/client/eulaize.js @@ -0,0 +1,16 @@ +const fs = require('fs'); + + +const filename = process.argv[2]; + +fs.readFile(filename, 'utf8', (err, data) => { + if (err) { + console.error(`Error reading file ${filename}:`, err); + return; + } + const filteredData = JSON.stringify(data); + console.log('Select the content between the quotes below and paste it into the EULA Content field in the EULA Content table in the database.') + console.log('--------------------------------------------------') + console.log(filteredData); + console.log('--------------------------------------------------') +}); \ No newline at end of file diff --git a/client/package-lock.json b/client/package-lock.json index 1d2c454f9..11952eff4 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -19449,6 +19449,14 @@ "react-dom": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0" } }, + "node_modules/react-smooth/node_modules/dom-helpers": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-3.4.0.tgz", + "integrity": "sha512-LnuPJ+dwqKDIyotW1VzmOZ5TONUN7CwkCR5hrgawTUbkBGYdeoNLZo6nNfGkCrjtE1nXXaj7iMMpDa8/d9WoIA==", + "dependencies": { + "@babel/runtime": "^7.1.2" + } + }, "node_modules/react-smooth/node_modules/fast-equals": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-5.0.1.tgz", @@ -19457,6 +19465,21 @@ "node": ">=6.0.0" } }, + "node_modules/react-smooth/node_modules/react-transition-group": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-2.9.0.tgz", + "integrity": "sha512-+HzNTCHpeQyl4MJ/bdE0u6XRMe9+XG/+aL4mCxVN4DnPBQ0/5bfHWPDuOZUzYdMj94daZaZdCCc1Dzt9R/xSSg==", + "dependencies": { + "dom-helpers": "^3.4.0", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2", + "react-lifecycles-compat": "^3.0.4" + }, + "peerDependencies": { + "react": ">=15.0.0", + "react-dom": ">=15.0.0" + } + }, "node_modules/react-sticky": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/react-sticky/-/react-sticky-6.0.3.tgz", @@ -19497,29 +19520,6 @@ "resolved": "https://registry.npmjs.org/style-utils/-/style-utils-0.1.24.tgz", "integrity": "sha512-MVZSKubpU/vIfpmOsi8/0ckWxb0WmGBmyNoEDGWZM9cM8n8sCL6DJftl3lEf8Uy5zKQ9+O1XdJxscWTDosCQpQ==" }, - "node_modules/react-transition-group": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-2.9.0.tgz", - "integrity": "sha512-+HzNTCHpeQyl4MJ/bdE0u6XRMe9+XG/+aL4mCxVN4DnPBQ0/5bfHWPDuOZUzYdMj94daZaZdCCc1Dzt9R/xSSg==", - "dependencies": { - "dom-helpers": "^3.4.0", - "loose-envify": "^1.4.0", - "prop-types": "^15.6.2", - "react-lifecycles-compat": "^3.0.4" - }, - "peerDependencies": { - "react": ">=15.0.0", - "react-dom": ">=15.0.0" - } - }, - "node_modules/react-transition-group/node_modules/dom-helpers": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-3.4.0.tgz", - "integrity": "sha512-LnuPJ+dwqKDIyotW1VzmOZ5TONUN7CwkCR5hrgawTUbkBGYdeoNLZo6nNfGkCrjtE1nXXaj7iMMpDa8/d9WoIA==", - "dependencies": { - "@babel/runtime": "^7.1.2" - } - }, "node_modules/react-virtualized": { "version": "9.22.5", "resolved": "https://registry.npmjs.org/react-virtualized/-/react-virtualized-9.22.5.tgz", diff --git a/client/package.json b/client/package.json index c99eda9ef..be72ee257 100644 --- a/client/package.json +++ b/client/package.json @@ -93,6 +93,7 @@ "buildcra": "REACT_APP_GIT_SHA=`git rev-parse --short HEAD` craco build", "test": "cypress open", "eject": "react-scripts eject", + "eulaize": "node eulaize.js", "madge": "madge --image ./madge-graph.svg --extensions js,jsx,ts,tsx --circular ." }, "eslintConfig": { diff --git a/client/src/App/App.jsx b/client/src/App/App.jsx index 9e52ed9ed..caa5b94f2 100644 --- a/client/src/App/App.jsx +++ b/client/src/App/App.jsx @@ -122,7 +122,7 @@ export function App({bodyshop, checkUserSession, currentUser, online, setOnline} /> ); - if (!currentUser.isEulaAccepted) { + if (!currentUser.eulaIsAccepted) { return } diff --git a/client/src/components/eula/eula.component.jsx b/client/src/components/eula/eula.component.jsx index af3bc819e..63337d184 100644 --- a/client/src/components/eula/eula.component.jsx +++ b/client/src/components/eula/eula.component.jsx @@ -1,37 +1,89 @@ -import React, {useState} from "react"; +import React, {useCallback, useEffect, useRef, useState} from "react"; import {Button, Card, Checkbox, Col, Form, Input, Modal, Row, Space} from "antd"; import Markdown from "react-markdown"; +import {createStructuredSelector} from "reselect"; +import {selectCurrentEula, selectCurrentUser} from "../../redux/user/user.selectors"; +import {connect} from "react-redux"; +import {FormDatePicker} from "../form-date-picker/form-date-picker.component"; +import {INSERT_EULA_ACCEPTANCE} from "../../graphql/user.queries"; +import {useMutation} from "@apollo/client"; +import {acceptEula} from "../../redux/user/user.actions"; -const EULA = require('./testData.json').eula; -/** - * Returns the EULA component. - * @returns {Element} - * @constructor - */ +const mapStateToProps = createStructuredSelector({ + currentEula: selectCurrentEula, + currentUser: selectCurrentUser, +}); -//REDUXY THIS -export default function Eula({eulaContentToShow}) { - const [isModalOpen, setIsModalOpen] = useState(true); +const mapDispatchToProps = (dispatch) => ({ + acceptEula: () => dispatch(acceptEula()), +}); - const handleAccept = (values) => { - localStorage.setItem('termsAccepted', 'true'); - setIsModalOpen(false); +export function Eula({currentEula, currentUser, acceptEula}) { + const [formReady, setFormReady] = useState(false); // [formReady, setFormReady + const [hasEverScrolledToBottom, setHasEverScrolledToBottom] = useState(false); + const [insertEulaAcceptance] = useMutation(INSERT_EULA_ACCEPTANCE); + const [form] = Form.useForm(); + const markdownDivRef = useRef(null); - //Insert and Dispatch the action to rechecuk force acceptance. + const handleAccept = async ({acceptTerms, ...formValues}) => { + + const eulaId = currentEula.id; + const useremail = currentUser.email; + + try { + await insertEulaAcceptance({ + variables: { + eulaAcceptance: { + eulaid: eulaId, + useremail, + ...formValues, + date_accepted: new Date(), + } + } + }); + + acceptEula(); + } catch (err) { + // Pop notification with error, pop console + console.error(err); + } +//R + // setIsModalOpen(false); + //Insert and Dispatch the action to recheck force acceptance. }; + const handleScroll = (e) => { + const bottom = e.target.scrollHeight - 100 <= e.target.scrollTop + e.target.clientHeight; + if (bottom && !hasEverScrolledToBottom) { + setHasEverScrolledToBottom(true); + } + }; + + const handleChange = useCallback(() => { + form.validateFields({ + validateOnly: true, + }).then(() => { + setFormReady(hasEverScrolledToBottom); + }).catch(() => { + setFormReady(false); + }); + }, [form, hasEverScrolledToBottom]); + + + useEffect(() => { + handleChange(); + }, [handleChange, hasEverScrolledToBottom, form]); + return ( - <> - - + )} closable={false} > @@ -40,17 +92,20 @@ export default function Eula({eulaContentToShow}) { maxHeight: '50vh', overflowY: 'auto', backgroundColor: 'lightgray', - padding: '0 25px 0 25px' - }}> - + }} onScroll={handleScroll} ref={markdownDivRef}> +
+ +
-
+ @@ -59,7 +114,7 @@ export default function Eula({eulaContentToShow}) { @@ -70,7 +125,7 @@ export default function Eula({eulaContentToShow}) { @@ -79,7 +134,13 @@ export default function Eula({eulaContentToShow}) { @@ -97,28 +158,38 @@ export default function Eula({eulaContentToShow}) { - + + + + + + + + value ? Promise.resolve() : Promise.reject(new Error('You must accept the terms and conditions')), + }, + ]} + > + I accept the terms and conditions - - value ? Promise.resolve() : Promise.reject(new Error('You must accept the terms and conditions')), - }, - ]} - > - I accept the terms and conditions -
+ {!hasEverScrolledToBottom && ( + +

You must scroll to the bottom of the Terms and Conditions before accepting.

+
+ )}
} +export default connect(mapStateToProps, mapDispatchToProps)(Eula); \ No newline at end of file diff --git a/client/src/components/eula/testData.json b/client/src/components/eula/testData.json deleted file mode 100644 index 03827a783..000000000 --- a/client/src/components/eula/testData.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "eula": "# End User License Agreement (EULA)\n## 1. Introduction\n\nThis End User License Agreement (\"EULA\") governs your use of our website and any related services. By using our website, you agree to be bound by the terms of this EULA.\n\n## 2. License Grant\n\nWe grant you a non-exclusive, non-transferable, revocable license to use our website for your personal, non-commercial use.\n\n## 3. Restrictions\n\nYou agree not to:\n\n- Use our website for any illegal or unauthorized purpose\n- Attempt to reverse engineer or otherwise derive the source code of our website\n\n## 4. Termination\n\nWe reserve the right to terminate your license to use our website at any time and for any reason.\n\n## 5. Disclaimer of Warranties\n\nOur website is provided \"as is\" and without any warranty of any kind.\n\n## 6. Limitation of Liability\n\nWe will not be liable for any damages or losses arising from your use of our website.\n\n## 7. Governing Law\n\nThis EULA is governed by the laws of [Your Jurisdiction].\n\n## 8. Changes to this EULA\n\nWe reserve the right to modify this EULA at any time. Your continued use of our website after any such changes constitutes your acceptance of the new EULA.\n\n## 9. Contact Us\n\nIf you have any questions about this EULA, please contact us at [Your Contact Information].\n## 1. Introduction\n\nThis End User License Agreement (\"EULA\") governs your use of our website and any related services. By using our website, you agree to be bound by the terms of this EULA.\n\n## 2. License Grant\n\nWe grant you a non-exclusive, non-transferable, revocable license to use our website for your personal, non-commercial use.\n\n## 3. Restrictions\n\nYou agree not to:\n\n- Use our website for any illegal or unauthorized purpose\n- Attempt to reverse engineer or otherwise derive the source code of our website\n\n## 4. Termination\n\nWe reserve the right to terminate your license to use our website at any time and for any reason.\n\n## 5. Disclaimer of Warranties\n\nOur website is provided \"as is\" and without any warranty of any kind.\n\n## 6. Limitation of Liability\n\nWe will not be liable for any damages or losses arising from your use of our website.\n\n## 7. Governing Law\n\nThis EULA is governed by the laws of [Your Jurisdiction].\n\n## 8. Changes to this EULA\n\nWe reserve the right to modify this EULA at any time. Your continued use of our website after any such changes constitutes your acceptance of the new EULA.\n\n## 9. Contact Us\n\nIf you have any questions about this EULA, please contact us at [Your Contact Information].\n## 1. Introduction\n\nThis End User License Agreement (\"EULA\") governs your use of our website and any related services. By using our website, you agree to be bound by the terms of this EULA.\n\n## 2. License Grant\n\nWe grant you a non-exclusive, non-transferable, revocable license to use our website for your personal, non-commercial use.\n\n## 3. Restrictions\n\nYou agree not to:\n\n- Use our website for any illegal or unauthorized purpose\n- Attempt to reverse engineer or otherwise derive the source code of our website\n\n## 4. Termination\n\nWe reserve the right to terminate your license to use our website at any time and for any reason.\n\n## 5. Disclaimer of Warranties\n\nOur website is provided \"as is\" and without any warranty of any kind.\n\n## 6. Limitation of Liability\n\nWe will not be liable for any damages or losses arising from your use of our website.\n\n## 7. Governing Law\n\nThis EULA is governed by the laws of [Your Jurisdiction].\n\n## 8. Changes to this EULA\n\nWe reserve the right to modify this EULA at any time. Your continued use of our website after any such changes constitutes your acceptance of the new EULA.\n\n## 9. Contact Us\n\nIf you have any questions about this EULA, please contact us at [Your Contact Information]." -} \ No newline at end of file diff --git a/client/src/graphql/user.queries.js b/client/src/graphql/user.queries.js index 09ba53787..d69429ba5 100644 --- a/client/src/graphql/user.queries.js +++ b/client/src/graphql/user.queries.js @@ -31,6 +31,14 @@ export const UPDATE_ASSOCIATION = gql` } `; +export const INSERT_EULA_ACCEPTANCE = gql` + mutation INSERT_EULA_ACCEPTANCE($eulaAcceptance:eula_acceptances_insert_input!) { + insert_eula_acceptances_one(object: $eulaAcceptance){ + id + } + } +`; + export const UPSERT_USER = gql` mutation UPSERT_USER($authEmail: String!, $authToken: String!) { insert_users( diff --git a/client/src/redux/user/user.actions.js b/client/src/redux/user/user.actions.js index f5a9a2d4f..b5c62a73c 100644 --- a/client/src/redux/user/user.actions.js +++ b/client/src/redux/user/user.actions.js @@ -110,8 +110,12 @@ export const setAuthlevel = (authlevel) => ({ payload: authlevel, }); -export const setEulaContentToShow = (eulaContent) => ({ - type: UserActionTypes.SET_EULA_CONTENT, - payload: eulaContent, +export const setCurrentEula = (eula) => ({ + type: UserActionTypes.SET_CURRENT_EULA, + payload: eula, +}); + +export const acceptEula = () => ({ + type: UserActionTypes.EULA_ACCEPTED, }); diff --git a/client/src/redux/user/user.reducer.js b/client/src/redux/user/user.reducer.js index 641d127c2..5a1644f3b 100644 --- a/client/src/redux/user/user.reducer.js +++ b/client/src/redux/user/user.reducer.js @@ -18,7 +18,7 @@ const INITIAL_STATE = { loading: false, }, authLevel: 0, - eulaContentToShow:null + currentEula: null, }; const userReducer = (state = INITIAL_STATE, action) => { @@ -65,11 +65,19 @@ const userReducer = (state = INITIAL_STATE, action) => { loading: false, }, }; + case UserActionTypes.EULA_ACCEPTED: + return { + ...state, + currentUser:{...state.currentUser, eulaIsAccepted: true}, + currentEula: null, + }; case UserActionTypes.SIGN_IN_SUCCESS: + const{ currentEula,...currentUser} = action.payload return { ...state, loginLoading: false, - currentUser: action.payload, + currentUser: currentUser, + currentEula, error: null, }; case UserActionTypes.SIGN_OUT_SUCCESS: diff --git a/client/src/redux/user/user.sagas.js b/client/src/redux/user/user.sagas.js index 867c8e0cb..50201ba5d 100644 --- a/client/src/redux/user/user.sagas.js +++ b/client/src/redux/user/user.sagas.js @@ -97,7 +97,7 @@ export function* isUserAuthenticated() { }, }); - const isEulaAccepted = eulaQuery.data.eulas.length > 0 && eulaQuery.data.eulas[0].eula_acceptances.length > 0; + const eulaIsAccepted = eulaQuery.data.eulas.length > 0 && eulaQuery.data.eulas[0].eula_acceptances.length > 0; yield put( signInSuccess({ @@ -106,7 +106,8 @@ export function* isUserAuthenticated() { displayName: user.displayName, photoURL: user.photoURL, authorized: true, - isEulaAccepted, + eulaIsAccepted, + currentEula: eulaIsAccepted ? null : eulaQuery.data.eulas[0], }) ); } catch (error) { diff --git a/client/src/redux/user/user.selectors.js b/client/src/redux/user/user.selectors.js index c3d0fe572..6e2193a10 100644 --- a/client/src/redux/user/user.selectors.js +++ b/client/src/redux/user/user.selectors.js @@ -37,7 +37,7 @@ export const selectLoginLoading = createSelector( (user) => user.loginLoading ); -export const selectEulaContentToShow = createSelector( +export const selectCurrentEula = createSelector( [selectUser], - (user) => user.eulaContentToShow + (user) => user.currentEula ); diff --git a/client/src/redux/user/user.types.js b/client/src/redux/user/user.types.js index cd4e952cd..0e153b31a 100644 --- a/client/src/redux/user/user.types.js +++ b/client/src/redux/user/user.types.js @@ -32,6 +32,7 @@ const UserActionTypes = { CHECK_ACTION_CODE_START: "CHECK_ACTION_CODE_START", CHECK_ACTION_CODE_SUCCESS: "CHECK_ACTION_CODE_SUCCESS", CHECK_ACTION_CODE_FAILURE: "CHECK_ACTION_CODE_FAILURE", - SET_EULA_CONTENT: "SET_EULA_CONTENT" + SET_CURRENT_EULA: "SET_CURRENT_EULA", + EULA_ACCEPTED : "EULA_ACCEPTED", }; export default UserActionTypes; diff --git a/client/test.md b/client/test.md new file mode 100644 index 000000000..186553d61 --- /dev/null +++ b/client/test.md @@ -0,0 +1,31 @@ +# End User License Agreement (EULA) + +## 1. Introduction + +This End User License Agreement ("EULA") is a legal agreement between you and [Your Company Name] ("Company"). This EULA governs your acquisition and use of our [Software Name] ("Software") directly from [Your Company Name] or indirectly through a [Your Company Name] authorized reseller or distributor. + +By installing and/or using the [Software Name], you are confirming your acceptance of the Software and agreeing to become bound by the terms of this EULA agreement. + +## 2. License + +[Your Company Name] hereby grants you a personal, non-transferable, non-exclusive licence to use the [Software Name] on your devices in accordance with the terms of this EULA agreement. + +## 3. Restrictions + +You are not permitted to: + +- Edit, alter, modify, adapt, translate or otherwise change the whole or any part of the Software nor permit the whole or any part of the Software to be combined with or become incorporated in any other software, nor decompile, disassemble or reverse engineer the Software or attempt to do any such things. + +- Reproduce, copy, distribute, resell or otherwise use the Software for any commercial purpose. + +- Allow any third party to use the Software on behalf of or for the benefit of any third party. + +- Use the Software in any way which breaches any applicable local, national or international law. + +## 4. Termination + +This EULA agreement is effective from the date you first use the Software and shall continue until terminated. You may terminate it at any time upon written notice to [Your Company Name]. + +## 5. Governing Law + +This EULA agreement, and any dispute arising out of or in connection with this EULA agreement, shall be governed by and construed in accordance with the laws of [Your Country]. \ No newline at end of file diff --git a/hasura/metadata/functions.yaml b/hasura/metadata/functions.yaml index 3ef10184a..5dd1b8640 100644 --- a/hasura/metadata/functions.yaml +++ b/hasura/metadata/functions.yaml @@ -1,3 +1,6 @@ +- function: + name: jobs_ar_summary + schema: public - function: name: search_bills schema: public diff --git a/hasura/metadata/tables.yaml b/hasura/metadata/tables.yaml index f4e4d99a7..a8e271f93 100644 --- a/hasura/metadata/tables.yaml +++ b/hasura/metadata/tables.yaml @@ -2442,7 +2442,7 @@ _eq: X-Hasura-User-Id columns: - address - - buisness_name + - business_name - date_accepted - eulaid - first_name @@ -2454,7 +2454,7 @@ permission: columns: - address - - buisness_name + - business_name - first_name - last_name - phone_number @@ -2673,6 +2673,9 @@ - table: name: ioevents schema: public +- table: + name: job_ar_schema + schema: public - table: name: job_conversations schema: public @@ -3812,6 +3815,7 @@ - referral_source - referral_source_extra - regie_number + - remove_from_ar - ro_number - scheduled_completion - scheduled_delivery @@ -4093,6 +4097,7 @@ - referral_source - referral_source_extra - regie_number + - remove_from_ar - ro_number - scheduled_completion - scheduled_delivery diff --git a/hasura/migrations/1705712927924_alter_table_public_eula_acceptances_alter_column_buisness_name/down.sql b/hasura/migrations/1705712927924_alter_table_public_eula_acceptances_alter_column_buisness_name/down.sql new file mode 100644 index 000000000..8c4d38542 --- /dev/null +++ b/hasura/migrations/1705712927924_alter_table_public_eula_acceptances_alter_column_buisness_name/down.sql @@ -0,0 +1 @@ +alter table "public"."eula_acceptances" rename column "business_name" to "buisness_name"; diff --git a/hasura/migrations/1705712927924_alter_table_public_eula_acceptances_alter_column_buisness_name/up.sql b/hasura/migrations/1705712927924_alter_table_public_eula_acceptances_alter_column_buisness_name/up.sql new file mode 100644 index 000000000..7dc59b9f6 --- /dev/null +++ b/hasura/migrations/1705712927924_alter_table_public_eula_acceptances_alter_column_buisness_name/up.sql @@ -0,0 +1 @@ +alter table "public"."eula_acceptances" rename column "buisness_name" to "business_name"; diff --git a/hasura/migrations/1705715500461_alter_table_public_eula_acceptances_alter_column_phone_number/down.sql b/hasura/migrations/1705715500461_alter_table_public_eula_acceptances_alter_column_phone_number/down.sql new file mode 100644 index 000000000..08ab66099 --- /dev/null +++ b/hasura/migrations/1705715500461_alter_table_public_eula_acceptances_alter_column_phone_number/down.sql @@ -0,0 +1 @@ +alter table "public"."eula_acceptances" alter column "phone_number" set not null; diff --git a/hasura/migrations/1705715500461_alter_table_public_eula_acceptances_alter_column_phone_number/up.sql b/hasura/migrations/1705715500461_alter_table_public_eula_acceptances_alter_column_phone_number/up.sql new file mode 100644 index 000000000..de5721802 --- /dev/null +++ b/hasura/migrations/1705715500461_alter_table_public_eula_acceptances_alter_column_phone_number/up.sql @@ -0,0 +1 @@ +alter table "public"."eula_acceptances" alter column "phone_number" drop not null; diff --git a/hasura/migrations/1705715523486_alter_table_public_eula_acceptances_alter_column_address/down.sql b/hasura/migrations/1705715523486_alter_table_public_eula_acceptances_alter_column_address/down.sql new file mode 100644 index 000000000..fa66ebd58 --- /dev/null +++ b/hasura/migrations/1705715523486_alter_table_public_eula_acceptances_alter_column_address/down.sql @@ -0,0 +1 @@ +alter table "public"."eula_acceptances" alter column "address" set not null; diff --git a/hasura/migrations/1705715523486_alter_table_public_eula_acceptances_alter_column_address/up.sql b/hasura/migrations/1705715523486_alter_table_public_eula_acceptances_alter_column_address/up.sql new file mode 100644 index 000000000..d571c7cf3 --- /dev/null +++ b/hasura/migrations/1705715523486_alter_table_public_eula_acceptances_alter_column_address/up.sql @@ -0,0 +1 @@ +alter table "public"."eula_acceptances" alter column "address" drop not null; From 2ada4ac44b2d0cc81dd35d7c4aff0b884db159b1 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Fri, 19 Jan 2024 22:27:03 -0500 Subject: [PATCH 05/54] - Eula finished Signed-off-by: Dave Richer --- client/src/components/eula/eula.component.jsx | 371 ++++++++++-------- client/src/components/eula/eula.styles.scss | 21 + client/src/translations/en_us/common.json | 35 ++ client/src/translations/es/common.json | 35 ++ client/src/translations/fr/common.json | 35 ++ 5 files changed, 327 insertions(+), 170 deletions(-) create mode 100644 client/src/components/eula/eula.styles.scss diff --git a/client/src/components/eula/eula.component.jsx b/client/src/components/eula/eula.component.jsx index 63337d184..3dca72951 100644 --- a/client/src/components/eula/eula.component.jsx +++ b/client/src/components/eula/eula.component.jsx @@ -1,58 +1,27 @@ -import React, {useCallback, useEffect, useRef, useState} from "react"; -import {Button, Card, Checkbox, Col, Form, Input, Modal, Row, Space} from "antd"; +import React, { useCallback, useEffect, useRef, useState } from "react"; +import {Button, Card, Checkbox, Col, Form, Input, Modal, notification, Row, Space} from "antd"; import Markdown from "react-markdown"; -import {createStructuredSelector} from "reselect"; -import {selectCurrentEula, selectCurrentUser} from "../../redux/user/user.selectors"; -import {connect} from "react-redux"; -import {FormDatePicker} from "../form-date-picker/form-date-picker.component"; -import {INSERT_EULA_ACCEPTANCE} from "../../graphql/user.queries"; -import {useMutation} from "@apollo/client"; -import {acceptEula} from "../../redux/user/user.actions"; +import { createStructuredSelector } from "reselect"; +import { selectCurrentEula, selectCurrentUser } from "../../redux/user/user.selectors"; +import { connect } from "react-redux"; +import { FormDatePicker } from "../form-date-picker/form-date-picker.component"; +import { INSERT_EULA_ACCEPTANCE } from "../../graphql/user.queries"; +import { useMutation } from "@apollo/client"; +import { acceptEula } from "../../redux/user/user.actions"; +import { useTranslation } from "react-i18next"; +import day from '../../utils/day'; +import './eula.styles.scss'; -const mapStateToProps = createStructuredSelector({ - currentEula: selectCurrentEula, - currentUser: selectCurrentUser, -}); - - -const mapDispatchToProps = (dispatch) => ({ - acceptEula: () => dispatch(acceptEula()), -}); - -export function Eula({currentEula, currentUser, acceptEula}) { - const [formReady, setFormReady] = useState(false); // [formReady, setFormReady +const Eula = ({ currentEula, currentUser, acceptEula }) => { + const [formReady, setFormReady] = useState(false); const [hasEverScrolledToBottom, setHasEverScrolledToBottom] = useState(false); const [insertEulaAcceptance] = useMutation(INSERT_EULA_ACCEPTANCE); const [form] = Form.useForm(); - const markdownDivRef = useRef(null); + const markdownCardRef = useRef(null); + const { t } = useTranslation(); + const [api, contextHolder] = notification.useNotification(); - const handleAccept = async ({acceptTerms, ...formValues}) => { - - const eulaId = currentEula.id; - const useremail = currentUser.email; - - try { - await insertEulaAcceptance({ - variables: { - eulaAcceptance: { - eulaid: eulaId, - useremail, - ...formValues, - date_accepted: new Date(), - } - } - }); - - acceptEula(); - } catch (err) { - // Pop notification with error, pop console - console.error(err); - } -//R - // setIsModalOpen(false); - //Insert and Dispatch the action to recheck force acceptance. - }; const handleScroll = (e) => { const bottom = e.target.scrollHeight - 100 <= e.target.scrollTop + e.target.clientHeight; if (bottom && !hasEverScrolledToBottom) { @@ -61,135 +30,197 @@ export function Eula({currentEula, currentUser, acceptEula}) { }; const handleChange = useCallback(() => { - form.validateFields({ - validateOnly: true, - }).then(() => { - setFormReady(hasEverScrolledToBottom); - }).catch(() => { - setFormReady(false); - }); + form.validateFields({ validateOnly: true }) + .then(() => setFormReady(hasEverScrolledToBottom)) + .catch(() => setFormReady(false)); }, [form, hasEverScrolledToBottom]); - useEffect(() => { handleChange(); }, [handleChange, hasEverScrolledToBottom, form]); + const onFinish = async ({ acceptTerms, ...formValues }) => { + const eulaId = currentEula.id; + const useremail = currentUser.email; - return ( - - )} - closable={false} - > - - -
- -
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - value ? Promise.resolve() : Promise.reject(new Error('You must accept the terms and conditions')), - }, - ]} - > - I accept the terms and conditions - - - -
-
- {!hasEverScrolledToBottom && ( - -

You must scroll to the bottom of the Terms and Conditions before accepting.

-
- )} -
-
+ try { + const { accepted_terms, ...otherFormValues } = formValues; + await insertEulaAcceptance({ + variables: { + eulaAcceptance: { + eulaid: eulaId, + useremail, + ...otherFormValues, + date_accepted: new Date(), + } + } + }); + acceptEula(); + } catch (err) { + api.error({ + message: t('eula.errors.acceptance.message'), + description: t('eula.errors.acceptance.description'), + placement: 'bottomRight', + duration: 5000, + + }); + console.log(`${t('eula.errors.acceptance.message')}`); + console.dir({ + message: err.message, + stack: err.stack, + }); + } + }; + + return ( + <> + {contextHolder} + ( +