From 6925e803799fb8e2aaa3dc3eb6fa11f9c84c4608 Mon Sep 17 00:00:00 2001 From: Shane Sweeney Date: Wed, 12 Apr 2023 16:40:48 -0700 Subject: [PATCH 01/21] 1346 - Theme Integration - Login (#1353) * Add system design updates to Theme JS * Implement Theme to Login Error Handling * Modify structure of theme styles, no need to spread object * Fix how to use theme typography * Add header to project description * Add theme to POints header * Update Button colors --------- Co-authored-by: Shane Sweeney --- client/src/components/Button/NavButton.js | 20 +++++++++++++------ client/src/components/Button/SaveButton.js | 7 ++++--- .../components/ProjectWizard/WizardFooter.js | 3 +++ .../WizardPages/ProjectDescriptions.js | 16 +++++++++------ .../WizardPages/ProjectTargetPoints.js | 19 ++++++++++-------- 5 files changed, 42 insertions(+), 23 deletions(-) diff --git a/client/src/components/Button/NavButton.js b/client/src/components/Button/NavButton.js index f5460d66..47d672f6 100644 --- a/client/src/components/Button/NavButton.js +++ b/client/src/components/Button/NavButton.js @@ -4,6 +4,7 @@ import { createUseStyles, useTheme } from "react-jss"; import { faAngleLeft, faAngleRight } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import clsx from "clsx"; +import Button from "./Button"; const useStyles = createUseStyles({ navButton: { @@ -13,13 +14,11 @@ const useStyles = createUseStyles({ fontSize: "2em", border: "1px solid rgba(0, 0, 0, 0.1)", boxShadow: "rgba(0, 46, 109, 0.3) 0px 3px 5px", - backgroundColor: ({ theme }) => theme.colorPrimary, "&:focus": { borderRadius: "none" } }, wizardNavButtonDisabled: { - backgroundColor: ({ theme }) => theme.colorDisabled, cursor: "default" }, hidden: { @@ -32,24 +31,32 @@ const useStyles = createUseStyles({ } }); -const NavButton = ({ id, onClick, navDirection, isVisible, isDisabled }) => { +const NavButton = ({ + id, + onClick, + navDirection, + isVisible, + isDisabled, + color +}) => { const theme = useTheme(); const classes = useStyles({ theme }); const maybeDisabled = isDisabled && classes.wizardNavButtonDisabled; const maybeHiddenVisibility = !isVisible && classes.hidden; return ( - + ); }; @@ -59,7 +66,8 @@ NavButton.propTypes = { id: PropTypes.string.isRequired, navDirection: PropTypes.string.isRequired, isVisible: PropTypes.bool.isRequired, - isDisabled: PropTypes.bool.isRequired + isDisabled: PropTypes.bool.isRequired, + color: PropTypes.string }; export default NavButton; diff --git a/client/src/components/Button/SaveButton.js b/client/src/components/Button/SaveButton.js index 0c423a72..4d2f4d43 100644 --- a/client/src/components/Button/SaveButton.js +++ b/client/src/components/Button/SaveButton.js @@ -2,11 +2,11 @@ import React from "react"; import PropTypes from "prop-types"; import Button from "../Button/Button"; -const SaveButton = ({ id, onClick, isDisabled, isDisplayed }) => { +const SaveButton = ({ id, onClick, isDisabled, isDisplayed, color }) => { return ( +
+
+ {errorMsg} +
+ + )} + + + + ) : ( + <> +

+ Registration instructions have been sent to the email you provided. +

+

+ Please allow a few minutes for the email to arrive in your inbox. +

+ + )} +
+
+ {submitted ? null : ( +
+ Already have an account?  {" "} + Log In +
+ )} + + ); +}; +UpdateProfile.propTypes = { + match: PropTypes.shape({ + params: PropTypes.shape({ + email: PropTypes.string + }) + }) +}; + +export default withRouter(UpdateProfile); diff --git a/client/src/components/NavBarLogin.js b/client/src/components/NavBarLogin.js index aae5a67a..2af0ba70 100644 --- a/client/src/components/NavBarLogin.js +++ b/client/src/components/NavBarLogin.js @@ -39,7 +39,19 @@ const NavBarLogin = ({ classes, handleHamburgerMenuClick }) => { const getUserGreeting = account => (
  • -

    Hello, {`${account.firstName} ${account.lastName} `}

    + { + // userContext.updateAccount({}); + // handleHamburgerMenuClick; + // }} + > + Hello, {`${account.firstName} ${account.lastName} `} +
  • ); diff --git a/client/src/services/account.service.js b/client/src/services/account.service.js index f02b1f1a..2533c775 100644 --- a/client/src/services/account.service.js +++ b/client/src/services/account.service.js @@ -31,6 +31,16 @@ export const register = async (firstName, lastName, email, password) => { } }; +export const updateProfile = async (firstName, lastName, email, password) => { + try { + const body = { firstName, lastName, email, password }; + const response = await axios.post(`${baseUrl}/register`, body); + return response.data; + } catch (err) { + throw Error("Update Profile failed"); + } +}; + export const resendConfirmationEmail = async email => { const body = { email }; try { diff --git a/server/app/controllers/account.controller.js b/server/app/controllers/account.controller.js index 9a223667..e600cd5d 100644 --- a/server/app/controllers/account.controller.js +++ b/server/app/controllers/account.controller.js @@ -5,6 +5,7 @@ const { } = require("../../middleware/validate"); const accountSchema = require("../schemas/account"); const accountRegisterSchema = require("../schemas/account.register"); +const accountUpdateProfileSchema = require("../schemas/account.UpdateProfile"); const accountConfirmRegisterSchema = require("../schemas/account.confirmRegister"); const accountLoginSchema = require("../schemas/account.login"); const accountForgotSchema = require("../schemas/account.forgotPassword"); @@ -50,6 +51,15 @@ const register = async (req, res) => { } }; +const updateProfile = async (req, res) => { + try { + const response = await accountService.updateProfile(req.body); + res.send(response); + } catch (err) { + res.status(err.code || "500").json({ error: err.toString() }); + } +}; + const resendConfirmationEmail = async (req, res) => { try { const response = await accountService.resendConfirmationEmail( @@ -144,6 +154,11 @@ module.exports = { register, validationErrorMiddleware ], + updateProfile: [ + validate({ body: accountUpdateProfileSchema }), + updateProfile, + validationErrorMiddleware + ], confirmRegister: [ validate({ body: accountConfirmRegisterSchema }), confirmRegister, diff --git a/server/app/routes/account.routes.js b/server/app/routes/account.routes.js index ba2086b4..456f8702 100644 --- a/server/app/routes/account.routes.js +++ b/server/app/routes/account.routes.js @@ -14,6 +14,8 @@ router.post( ); router.post("/confirmRegister", accountController.confirmRegister); +router.post("/updateprofile", accountController.updateProfile); + router.post("/forgotPassword", accountController.forgotPassword); router.post("/resetPassword", accountController.resetPassword); diff --git a/server/app/schemas/account.updateProfile.js b/server/app/schemas/account.updateProfile.js new file mode 100644 index 00000000..58571562 --- /dev/null +++ b/server/app/schemas/account.updateProfile.js @@ -0,0 +1,23 @@ +module.exports = { + type: "object", + required: ["firstName", "lastName", "email", "password"], + properties: { + firstName: { + type: "string", + minLength: 1 + }, + lastName: { + type: "string", + minLength: 1 + }, + email: { + type: "string" + }, + password: { + type: "string", + minLength: 12, + pattern: + "^(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#$%&*?])[A-Za-z0-9@$!%*#?&]{12,}$" + } + } +}; diff --git a/server/app/services/account.service.js b/server/app/services/account.service.js index 9cbe5584..d540022c 100644 --- a/server/app/services/account.service.js +++ b/server/app/services/account.service.js @@ -87,6 +87,38 @@ const register = async model => { } }; +const updateProfile = async model => { + const { firstName, lastName, email } = model; + let result = null; + await hashPassword(model); + try { + await poolConnect; + const request = pool.request(); + request.input("FirstName", mssql.NVarChar, firstName); + request.input("LastName", mssql.NVarChar, lastName); + request.input("Email", mssql.NVarChar, email); + request.input("PasswordHash", mssql.NVarChar, model.passwordHash); + request.output("id", mssql.Int, null); + const insertResult = await request.execute("Login_Insert"); + if (insertResult) { + result = { + isSuccess: true, + code: "REG_SUCCESS", + newId: insertResult.output["id"], + message: "Registration successful." + }; + result = await requestRegistrationConfirmation(email, result); + return result; + } + } catch (err) { + return { + isSuccess: false, + code: "REG_DUPLICATE_EMAIL", + message: `Email ${email} is already registered. ` + }; + } +}; + // Re-transmit confirmation email const resendConfirmationEmail = async email => { let result = null; @@ -403,6 +435,7 @@ module.exports = { selectAll, selectById, register, + updateProfile, confirmRegistration, resendConfirmationEmail, forgotPassword, From e7812a67131f0ac9452bf61275e1d479331d4b78 Mon Sep 17 00:00:00 2001 From: James Higgs Date: Mon, 17 Apr 2023 16:52:43 -0700 Subject: [PATCH 06/21] 230417 --- .../components/Authorization/UpdateProfile.js | 82 +++---------------- client/src/services/account.service.js | 6 +- server/app/routes/account.routes.js | 2 +- server/app/schemas/account.updateProfile.js | 8 +- server/app/services/account.service.js | 32 +++----- 5 files changed, 28 insertions(+), 102 deletions(-) diff --git a/client/src/components/Authorization/UpdateProfile.js b/client/src/components/Authorization/UpdateProfile.js index c3cf50ff..1626df4d 100644 --- a/client/src/components/Authorization/UpdateProfile.js +++ b/client/src/components/Authorization/UpdateProfile.js @@ -1,9 +1,10 @@ -import React, { useState, useRef } from "react"; +import React, { useState, useRef, useContext } from "react"; +import UserContext from "../../contexts/UserContext"; import PropTypes from "prop-types"; import * as accountService from "../../services/account.service"; import { createUseStyles } from "react-jss"; import { Formik, Form, Field, ErrorMessage } from "formik"; -import { Link, withRouter } from "react-router-dom"; +import { withRouter } from "react-router-dom"; import * as Yup from "yup"; import Button from "../Button/Button"; import ContentContainer from "../Layout/ContentContainer"; @@ -18,15 +19,15 @@ const useStyles = createUseStyles({ }); const UpdateProfile = props => { + const userContext = useContext(UserContext); + const account = userContext.account; const focusRef = useRef(null); const classes = useStyles(); const { match } = props; const initialValues = { - firstName: "", - lastName: "", - email: match.params.email || "", - password: "", - passwordConfirm: "" + firstName: account.firstName || "", + lastName: account.lastName || "", + email: match.params.email || "" }; const [errorMsg, setErrorMsg] = useState(""); @@ -43,32 +44,18 @@ const UpdateProfile = props => { lastName: Yup.string().required("Last Name is required"), email: Yup.string() .email("Invalid email address format") - .required("Email is required"), - password: Yup.string() - .min( - 12, - "Your password must have at least 12 characters, at least one number, one capitalization, and one special character (e.g., !@#$%&*?)" - ) - .matches( - /^(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#$%&*?])[A-Za-z\d@$!%*#?&]{12,}$/, - "Your password must have at least 12 characters, at least one number, one capitalization, and one special character (e.g., !@#$%&*?)" - ) - .required("Password is required"), - passwordConfirm: Yup.string() - .required("Confirm your password") - .oneOf([Yup.ref("password")], "Password does not match") + .required("Email is required") }); const handleSubmit = async ( - { firstName, lastName, email, password }, + { firstName, lastName, email }, { setSubmitting } ) => { try { const response = await accountService.updateProfile( firstName, lastName, - email, - password + email ); if (response.isSuccess) { setSubmitted(true); @@ -85,16 +72,12 @@ const UpdateProfile = props => { setErrorMsg(err.message); setSubmitting(false); } - // TODO: figure out if there is a scanrio where you actually - // want to reset the form, and move/copy the next line accordingly - //resetForm(initialValues); }; return ( {!submitted ? ( <>

    Update Your Account

    - {/*

    Save your project information.

    */}
    { className="invalid-feedback" />
    -
    - - -
    -
    - - -

    @@ -217,13 +166,6 @@ const UpdateProfile = props => { )}
    -
    - {submitted ? null : ( -
    - Already have an account?  {" "} - Log In -
    - )} ); }; diff --git a/client/src/services/account.service.js b/client/src/services/account.service.js index 2533c775..8928ef03 100644 --- a/client/src/services/account.service.js +++ b/client/src/services/account.service.js @@ -31,10 +31,10 @@ export const register = async (firstName, lastName, email, password) => { } }; -export const updateProfile = async (firstName, lastName, email, password) => { +export const updateProfile = async (firstName, lastName, email) => { try { - const body = { firstName, lastName, email, password }; - const response = await axios.post(`${baseUrl}/register`, body); + const body = { firstName, lastName, email }; + const response = await axios.put(`${baseUrl}/updateprofile`, body); return response.data; } catch (err) { throw Error("Update Profile failed"); diff --git a/server/app/routes/account.routes.js b/server/app/routes/account.routes.js index 456f8702..bdbc9c5e 100644 --- a/server/app/routes/account.routes.js +++ b/server/app/routes/account.routes.js @@ -14,7 +14,7 @@ router.post( ); router.post("/confirmRegister", accountController.confirmRegister); -router.post("/updateprofile", accountController.updateProfile); +router.put("/updateprofile", accountController.updateProfile); router.post("/forgotPassword", accountController.forgotPassword); router.post("/resetPassword", accountController.resetPassword); diff --git a/server/app/schemas/account.updateProfile.js b/server/app/schemas/account.updateProfile.js index 58571562..7b63c796 100644 --- a/server/app/schemas/account.updateProfile.js +++ b/server/app/schemas/account.updateProfile.js @@ -1,6 +1,6 @@ module.exports = { type: "object", - required: ["firstName", "lastName", "email", "password"], + required: ["firstName", "lastName", "email"], properties: { firstName: { type: "string", @@ -12,12 +12,6 @@ module.exports = { }, email: { type: "string" - }, - password: { - type: "string", - minLength: 12, - pattern: - "^(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#$%&*?])[A-Za-z0-9@$!%*#?&]{12,}$" } } }; diff --git a/server/app/services/account.service.js b/server/app/services/account.service.js index d540022c..071070c2 100644 --- a/server/app/services/account.service.js +++ b/server/app/services/account.service.js @@ -88,33 +88,23 @@ const register = async model => { }; const updateProfile = async model => { - const { firstName, lastName, email } = model; - let result = null; - await hashPassword(model); try { await poolConnect; const request = pool.request(); - request.input("FirstName", mssql.NVarChar, firstName); - request.input("LastName", mssql.NVarChar, lastName); - request.input("Email", mssql.NVarChar, email); - request.input("PasswordHash", mssql.NVarChar, model.passwordHash); - request.output("id", mssql.Int, null); - const insertResult = await request.execute("Login_Insert"); - if (insertResult) { - result = { - isSuccess: true, - code: "REG_SUCCESS", - newId: insertResult.output["id"], - message: "Registration successful." - }; - result = await requestRegistrationConfirmation(email, result); - return result; - } + request.input("FirstName", mssql.NVarChar, model.firstName); + request.input("LastName", mssql.NVarChar, model.lastName); + request.input("Email", mssql.NVarChar, model.email); + await request.execute("Login_Insert"); + return { + isSuccess: true, + code: "PROFILE_UPDATE_SUCCESS", + message: "Profile Updates." + }; } catch (err) { return { isSuccess: false, - code: "REG_DUPLICATE_EMAIL", - message: `Email ${email} is already registered. ` + code: "PROFILE_UPDATE_SUCCESS", + message: `Profile updates failed. ${err.message}` }; } }; From be0f73a393108f2964c34bfe8d6719e66b601021 Mon Sep 17 00:00:00 2001 From: John Darragh Date: Wed, 19 Apr 2023 19:07:38 -0700 Subject: [PATCH 07/21] Fix bug in granting/revoking roles (#1359) --- server/app/schemas/account.role.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/app/schemas/account.role.js b/server/app/schemas/account.role.js index df764d82..c95c3a81 100644 --- a/server/app/schemas/account.role.js +++ b/server/app/schemas/account.role.js @@ -6,10 +6,10 @@ module.exports = { type: "number" }, isAdmin: { - type: "number" + type: "boolean" }, isSecurityAdmin: { - type: "number" + type: "boolean" } } }; From 37da6bf3b21877db28133eff20900bd8a0c0cd57 Mon Sep 17 00:00:00 2001 From: James Higgs Date: Wed, 19 Apr 2023 20:27:08 -0700 Subject: [PATCH 08/21] 230419 --- .../components/Authorization/UpdateProfile.js | 9 +++++---- client/src/services/account.service.js | 6 +++--- server/app/routes/account.routes.js | 2 +- server/app/services/account.service.js | 19 ++----------------- 4 files changed, 11 insertions(+), 25 deletions(-) diff --git a/client/src/components/Authorization/UpdateProfile.js b/client/src/components/Authorization/UpdateProfile.js index 1626df4d..3c3d8975 100644 --- a/client/src/components/Authorization/UpdateProfile.js +++ b/client/src/components/Authorization/UpdateProfile.js @@ -25,6 +25,7 @@ const UpdateProfile = props => { const classes = useStyles(); const { match } = props; const initialValues = { + id: account.id || "", firstName: account.firstName || "", lastName: account.lastName || "", email: match.params.email || "" @@ -48,11 +49,12 @@ const UpdateProfile = props => { }); const handleSubmit = async ( - { firstName, lastName, email }, + { id, firstName, lastName, email }, { setSubmitting } ) => { try { const response = await accountService.updateProfile( + id, firstName, lastName, email @@ -64,9 +66,8 @@ const UpdateProfile = props => { login or use the Forgot Password feature if you have forgotten your password.`); } else { - setErrorMsg(`An error occurred in sending the confirmation - message to ${email}. Try to log in, and follow the - instructions for re-sending the confirmation email.`); + setErrorMsg(`An error occurred in updating the profile + for ${email}.`); } } catch (err) { setErrorMsg(err.message); diff --git a/client/src/services/account.service.js b/client/src/services/account.service.js index 8928ef03..5d8def6f 100644 --- a/client/src/services/account.service.js +++ b/client/src/services/account.service.js @@ -31,10 +31,10 @@ export const register = async (firstName, lastName, email, password) => { } }; -export const updateProfile = async (firstName, lastName, email) => { +export const updateProfile = async (id, firstName, lastName, email) => { try { - const body = { firstName, lastName, email }; - const response = await axios.put(`${baseUrl}/updateprofile`, body); + const body = { id, firstName, lastName, email }; + const response = await axios.put(`${baseUrl}/${id}/updateprofile`, body); return response.data; } catch (err) { throw Error("Update Profile failed"); diff --git a/server/app/routes/account.routes.js b/server/app/routes/account.routes.js index bdbc9c5e..e94b2bd3 100644 --- a/server/app/routes/account.routes.js +++ b/server/app/routes/account.routes.js @@ -14,7 +14,7 @@ router.post( ); router.post("/confirmRegister", accountController.confirmRegister); -router.put("/updateprofile", accountController.updateProfile); +router.put("/:id/updateprofile", accountController.updateProfile); router.post("/forgotPassword", accountController.forgotPassword); router.post("/resetPassword", accountController.resetPassword); diff --git a/server/app/services/account.service.js b/server/app/services/account.service.js index 071070c2..c1f15e01 100644 --- a/server/app/services/account.service.js +++ b/server/app/services/account.service.js @@ -91,10 +91,11 @@ const updateProfile = async model => { try { await poolConnect; const request = pool.request(); + request.input("id", mssql.Int, model.id); request.input("FirstName", mssql.NVarChar, model.firstName); request.input("LastName", mssql.NVarChar, model.lastName); request.input("Email", mssql.NVarChar, model.email); - await request.execute("Login_Insert"); + await request.execute("Login_Update"); return { isSuccess: true, code: "PROFILE_UPDATE_SUCCESS", @@ -363,21 +364,6 @@ const authenticate = async (email, password) => { }; }; -// Not fully implemented - needs sproc -const update = async model => { - try { - await poolConnect; - const request = pool.request(); - request.input("id", mssql.Int, model.id); - request.input("firstName", mssql.NVarChar, model.firstName); - request.input("lastName", mssql.NVarChar, model.lastName); - request.input("email", mssql.NVarChar, model.email); - await request.execute("Login_Update"); - } catch (err) { - return Promise.reject(err); - } -}; - const updateRoles = async model => { try { await poolConnect; @@ -431,7 +417,6 @@ module.exports = { forgotPassword, resetPassword, authenticate, - update, updateRoles, del }; From 03096ed85f419bc328d26139dea4dcad55783b2f Mon Sep 17 00:00:00 2001 From: James Higgs Date: Thu, 20 Apr 2023 20:59:31 -0700 Subject: [PATCH 09/21] 230420 works well for firstName and lastName but email needs work --- client/src/App.js | 6 +-- .../{UpdateProfile.js => UpdateAccount.js} | 39 ++++++++----------- client/src/components/NavBarLogin.js | 2 +- client/src/services/account.service.js | 6 +-- server/app/controllers/account.controller.js | 12 +++--- server/app/routes/account.routes.js | 2 +- ...ateProfile.js => account.updateAccount.js} | 0 server/app/services/account.service.js | 12 +++--- ....1255__create_sproc_update_account_780.sql | 26 +++++++++++++ 9 files changed, 63 insertions(+), 42 deletions(-) rename client/src/components/Authorization/{UpdateProfile.js => UpdateAccount.js} (86%) rename server/app/schemas/{account.updateProfile.js => account.updateAccount.js} (100%) create mode 100644 server/db/migration/V20230420.1255__create_sproc_update_account_780.sql diff --git a/client/src/App.js b/client/src/App.js index 094f78d8..fa28dfb5 100644 --- a/client/src/App.js +++ b/client/src/App.js @@ -15,7 +15,7 @@ import TermsAndConditionsModal from "./components/TermsAndConditions/TermsAndCon import ChecklistModal from "./components/Checklist/ChecklistModal"; import PrivacyPolicy from "./components/PrivacyPolicy"; import Register from "./components/Authorization/Register"; -import UpdateProfile from "./components/Authorization/UpdateProfile"; +import UpdateAccount from "./components/Authorization/UpdateAccount"; import ConfirmEmail from "./components/Authorization/ConfirmEmail"; import ProtectedRoute from "./components/Authorization/ProtectedRoute"; import Login from "./components/Authorization/Login"; @@ -125,8 +125,8 @@ const App = ({ - - + + diff --git a/client/src/components/Authorization/UpdateProfile.js b/client/src/components/Authorization/UpdateAccount.js similarity index 86% rename from client/src/components/Authorization/UpdateProfile.js rename to client/src/components/Authorization/UpdateAccount.js index 3c3d8975..38821908 100644 --- a/client/src/components/Authorization/UpdateProfile.js +++ b/client/src/components/Authorization/UpdateAccount.js @@ -8,6 +8,8 @@ import { withRouter } from "react-router-dom"; import * as Yup from "yup"; import Button from "../Button/Button"; import ContentContainer from "../Layout/ContentContainer"; +import { useToast } from "../../contexts/Toast"; +import Login from "./Login"; const useStyles = createUseStyles({ submitButton: { @@ -18,11 +20,12 @@ const useStyles = createUseStyles({ } }); -const UpdateProfile = props => { +const UpdateAccount = props => { const userContext = useContext(UserContext); const account = userContext.account; const focusRef = useRef(null); const classes = useStyles(); + const toast = useToast(); const { match } = props; const initialValues = { id: account.id || "", @@ -34,13 +37,7 @@ const UpdateProfile = props => { const [errorMsg, setErrorMsg] = useState(""); const [submitted, setSubmitted] = useState(false); - // useEffect(() => { - // if (focusRef.current) { - // focusRef.current.focus(); - // } - // }); - - const updateProfileSchema = Yup.object().shape({ + const updateAccountSchema = Yup.object().shape({ firstName: Yup.string().required("First Name is required"), lastName: Yup.string().required("Last Name is required"), email: Yup.string() @@ -53,7 +50,7 @@ const UpdateProfile = props => { { setSubmitting } ) => { try { - const response = await accountService.updateProfile( + const response = await accountService.updateAccount( id, firstName, lastName, @@ -61,12 +58,16 @@ const UpdateProfile = props => { ); if (response.isSuccess) { setSubmitted(true); + toast.add( + "Your account has been updated. Please sign in to confirm changes." + ); + userContext.updateAccount({}); } else if (response.code === "REG_DUPLICATE_EMAIL") { setErrorMsg(`The email ${email} is already registered. Please login or use the Forgot Password feature if you have forgotten your password.`); } else { - setErrorMsg(`An error occurred in updating the profile + setErrorMsg(`An error occurred in updating the account for ${email}.`); } } catch (err) { @@ -74,8 +75,9 @@ const UpdateProfile = props => { setSubmitting(false); } }; + return ( - + {!submitted ? ( <>

    Update Your Account

    @@ -83,7 +85,7 @@ const UpdateProfile = props => {
    handleSubmit(values, actions, props) } @@ -157,20 +159,13 @@ const UpdateProfile = props => {
    ) : ( - <> -

    - Registration instructions have been sent to the email you provided. -

    -

    - Please allow a few minutes for the email to arrive in your inbox. -

    - + )}
    ); }; -UpdateProfile.propTypes = { +UpdateAccount.propTypes = { match: PropTypes.shape({ params: PropTypes.shape({ email: PropTypes.string @@ -178,4 +173,4 @@ UpdateProfile.propTypes = { }) }; -export default withRouter(UpdateProfile); +export default withRouter(UpdateAccount); diff --git a/client/src/components/NavBarLogin.js b/client/src/components/NavBarLogin.js index 2af0ba70..571bac98 100644 --- a/client/src/components/NavBarLogin.js +++ b/client/src/components/NavBarLogin.js @@ -42,7 +42,7 @@ const NavBarLogin = ({ classes, handleHamburgerMenuClick }) => { { diff --git a/client/src/services/account.service.js b/client/src/services/account.service.js index 5d8def6f..bc9f9726 100644 --- a/client/src/services/account.service.js +++ b/client/src/services/account.service.js @@ -31,13 +31,13 @@ export const register = async (firstName, lastName, email, password) => { } }; -export const updateProfile = async (id, firstName, lastName, email) => { +export const updateAccount = async (id, firstName, lastName, email) => { try { const body = { id, firstName, lastName, email }; - const response = await axios.put(`${baseUrl}/${id}/updateprofile`, body); + const response = await axios.put(`${baseUrl}/${id}/updateaccount`, body); return response.data; } catch (err) { - throw Error("Update Profile failed"); + throw Error("Update account failed"); } }; diff --git a/server/app/controllers/account.controller.js b/server/app/controllers/account.controller.js index e600cd5d..014d0c08 100644 --- a/server/app/controllers/account.controller.js +++ b/server/app/controllers/account.controller.js @@ -5,7 +5,7 @@ const { } = require("../../middleware/validate"); const accountSchema = require("../schemas/account"); const accountRegisterSchema = require("../schemas/account.register"); -const accountUpdateProfileSchema = require("../schemas/account.UpdateProfile"); +const accountUpdateAccountSchema = require("../schemas/account.UpdateAccount"); const accountConfirmRegisterSchema = require("../schemas/account.confirmRegister"); const accountLoginSchema = require("../schemas/account.login"); const accountForgotSchema = require("../schemas/account.forgotPassword"); @@ -51,9 +51,9 @@ const register = async (req, res) => { } }; -const updateProfile = async (req, res) => { +const updateAccount = async (req, res) => { try { - const response = await accountService.updateProfile(req.body); + const response = await accountService.updateAccount(req.body); res.send(response); } catch (err) { res.status(err.code || "500").json({ error: err.toString() }); @@ -154,9 +154,9 @@ module.exports = { register, validationErrorMiddleware ], - updateProfile: [ - validate({ body: accountUpdateProfileSchema }), - updateProfile, + updateAccount: [ + validate({ body: accountUpdateAccountSchema }), + updateAccount, validationErrorMiddleware ], confirmRegister: [ diff --git a/server/app/routes/account.routes.js b/server/app/routes/account.routes.js index e94b2bd3..6929206c 100644 --- a/server/app/routes/account.routes.js +++ b/server/app/routes/account.routes.js @@ -14,7 +14,7 @@ router.post( ); router.post("/confirmRegister", accountController.confirmRegister); -router.put("/:id/updateprofile", accountController.updateProfile); +router.put("/:id/updateaccount", accountController.updateAccount); router.post("/forgotPassword", accountController.forgotPassword); router.post("/resetPassword", accountController.resetPassword); diff --git a/server/app/schemas/account.updateProfile.js b/server/app/schemas/account.updateAccount.js similarity index 100% rename from server/app/schemas/account.updateProfile.js rename to server/app/schemas/account.updateAccount.js diff --git a/server/app/services/account.service.js b/server/app/services/account.service.js index c1f15e01..d4c75f3c 100644 --- a/server/app/services/account.service.js +++ b/server/app/services/account.service.js @@ -87,7 +87,7 @@ const register = async model => { } }; -const updateProfile = async model => { +const updateAccount = async model => { try { await poolConnect; const request = pool.request(); @@ -98,14 +98,14 @@ const updateProfile = async model => { await request.execute("Login_Update"); return { isSuccess: true, - code: "PROFILE_UPDATE_SUCCESS", - message: "Profile Updates." + code: "ACCOUNT_UPDATE_SUCCESS", + message: "Account Updates." }; } catch (err) { return { isSuccess: false, - code: "PROFILE_UPDATE_SUCCESS", - message: `Profile updates failed. ${err.message}` + code: "ACCOUNT_UPDATE_SUCCESS", + message: `Account updates failed. ${err.message}` }; } }; @@ -411,7 +411,7 @@ module.exports = { selectAll, selectById, register, - updateProfile, + updateAccount, confirmRegistration, resendConfirmationEmail, forgotPassword, diff --git a/server/db/migration/V20230420.1255__create_sproc_update_account_780.sql b/server/db/migration/V20230420.1255__create_sproc_update_account_780.sql new file mode 100644 index 00000000..da49133b --- /dev/null +++ b/server/db/migration/V20230420.1255__create_sproc_update_account_780.sql @@ -0,0 +1,26 @@ +SET ANSI_NULLS ON +GO +SET QUOTED_IDENTIFIER ON +GO +CREATE OR ALTER PROC [dbo].[Login_Update] + @id int + , + @firstName nvarchar(50) + , + @lastName nvarchar(50) + , + @email nvarchar(100) +AS +BEGIN + + UPDATE Login SET + firstName = @firstName + , + lastName = @lastName + , + email = @email + WHERE + id = @id + +END +GO \ No newline at end of file From 768b8b7a1ab8b8bbdd6e908c83e636b5ed70e3b5 Mon Sep 17 00:00:00 2001 From: James Higgs Date: Sat, 22 Apr 2023 17:43:00 -0700 Subject: [PATCH 10/21] implemented a new page and flow to update account information --- .../components/Authorization/SendEmailForm.js | 12 ++++++++---- .../components/Authorization/UpdateAccount.js | 16 +++++++++------- client/src/components/NavBarLogin.js | 4 ---- server/app/services/account.service.js | 3 +++ server/app/services/sendgrid-service.js | 19 +++++++++++++++++-- ....1255__create_sproc_update_account_780.sql | 3 ++- 6 files changed, 39 insertions(+), 18 deletions(-) diff --git a/client/src/components/Authorization/SendEmailForm.js b/client/src/components/Authorization/SendEmailForm.js index c1ba7574..6e1f1af0 100644 --- a/client/src/components/Authorization/SendEmailForm.js +++ b/client/src/components/Authorization/SendEmailForm.js @@ -12,7 +12,8 @@ export const useStyles = createUseStyles({ marginBottom: "16px" }, subTitle: { - marginBottom: "32px" + marginBottom: "32px", + textAlign: "center" }, fieldGroup: { width: "100%", @@ -59,8 +60,11 @@ const SendEmailForm = ({ label, submitted, handleSubmit }) => { <>

    Send {label} Email

    -

    Please enter the email registered with your account.

    -

    An email will be sent with further instructions.

    +

    + Please enter the email registered with your account, or if you have + recently updated your email, provide the new one below. +

    +

    An email containing further instructions will be sent to you.

    { innerRef={focusRef} value={values.email} name="email" - placeholder="Registered Email Address" + placeholder="Registered/Updated Email" className={clsx( classes.inputField, touched.email && errors.email ? classes.error : null diff --git a/client/src/components/Authorization/UpdateAccount.js b/client/src/components/Authorization/UpdateAccount.js index 38821908..7708f2e7 100644 --- a/client/src/components/Authorization/UpdateAccount.js +++ b/client/src/components/Authorization/UpdateAccount.js @@ -8,8 +8,6 @@ import { withRouter } from "react-router-dom"; import * as Yup from "yup"; import Button from "../Button/Button"; import ContentContainer from "../Layout/ContentContainer"; -import { useToast } from "../../contexts/Toast"; -import Login from "./Login"; const useStyles = createUseStyles({ submitButton: { @@ -25,7 +23,6 @@ const UpdateAccount = props => { const account = userContext.account; const focusRef = useRef(null); const classes = useStyles(); - const toast = useToast(); const { match } = props; const initialValues = { id: account.id || "", @@ -58,9 +55,6 @@ const UpdateAccount = props => { ); if (response.isSuccess) { setSubmitted(true); - toast.add( - "Your account has been updated. Please sign in to confirm changes." - ); userContext.updateAccount({}); } else if (response.code === "REG_DUPLICATE_EMAIL") { setErrorMsg(`The email ${email} is already registered. Please @@ -159,7 +153,15 @@ const UpdateAccount = props => {
    ) : ( - + <> +

    + Instructions have been sent to the email you provided in order to + confirm account updates. +

    +

    + Please allow a few minutes for the email to arrive in your inbox. +

    + )}
    diff --git a/client/src/components/NavBarLogin.js b/client/src/components/NavBarLogin.js index 571bac98..3ed8f307 100644 --- a/client/src/components/NavBarLogin.js +++ b/client/src/components/NavBarLogin.js @@ -45,10 +45,6 @@ const NavBarLogin = ({ classes, handleHamburgerMenuClick }) => { pathname: `/updateaccount/${(account && account.email) || ""}`, state: { prevPath: location.pathname } }} - // onClick={() => { - // userContext.updateAccount({}); - // handleHamburgerMenuClick; - // }} > Hello, {`${account.firstName} ${account.lastName} `} diff --git a/server/app/services/account.service.js b/server/app/services/account.service.js index d4c75f3c..2ffa1a60 100644 --- a/server/app/services/account.service.js +++ b/server/app/services/account.service.js @@ -4,6 +4,7 @@ const { promisify } = require("util"); const moment = require("moment"); const bcrypt = require("bcrypt"); const { + sendVerifyUpdateConfirmation, sendRegistrationConfirmation, sendResetPasswordConfirmation } = require("./sendgrid-service"); @@ -88,6 +89,7 @@ const register = async model => { }; const updateAccount = async model => { + const token = uuid4(); try { await poolConnect; const request = pool.request(); @@ -96,6 +98,7 @@ const updateAccount = async model => { request.input("LastName", mssql.NVarChar, model.lastName); request.input("Email", mssql.NVarChar, model.email); await request.execute("Login_Update"); + await sendVerifyUpdateConfirmation(model.email, token); return { isSuccess: true, code: "ACCOUNT_UPDATE_SUCCESS", diff --git a/server/app/services/sendgrid-service.js b/server/app/services/sendgrid-service.js index ddef914b..ba683c85 100644 --- a/server/app/services/sendgrid-service.js +++ b/server/app/services/sendgrid-service.js @@ -18,6 +18,21 @@ const send = async (emailTo, emailFrom, subject, textBody, htmlBody) => { return sgMail.send(msg, false); }; +const sendVerifyUpdateConfirmation = async (email, token) => { + const msg = { + to: `${email}`, + from: senderEmail, + subject: "Verify Your Account Updates", + text: "Verify Your Account Updates", + html: `

    Hello, your account has been updated.

    +

    If you did not update your account please notify ladot@lacity.org.

    +

    Verify Account Updates

    +

    Thanks,

    +

    TDM Calculator Team

    ` + }; + return sgMail.send(msg, false); +}; + const sendRegistrationConfirmation = async (email, token) => { const msg = { to: `${email}`, @@ -25,9 +40,8 @@ const sendRegistrationConfirmation = async (email, token) => { subject: "Verify Your Account", text: "Verify your account", html: `

    Hello, please click the following link to verify your account.

    -

    Verify Me

    -
    +

    If you did not create a new account or update your account please notify ladot@lacity.org.

    Thanks,

    TDM Calculator Team

    ` }; @@ -75,6 +89,7 @@ const sendPublicComment = async publicCommentData => { module.exports = { send, + sendVerifyUpdateConfirmation, sendRegistrationConfirmation, sendResetPasswordConfirmation, sendPublicComment diff --git a/server/db/migration/V20230420.1255__create_sproc_update_account_780.sql b/server/db/migration/V20230420.1255__create_sproc_update_account_780.sql index da49133b..0e209c62 100644 --- a/server/db/migration/V20230420.1255__create_sproc_update_account_780.sql +++ b/server/db/migration/V20230420.1255__create_sproc_update_account_780.sql @@ -19,8 +19,9 @@ BEGIN lastName = @lastName , email = @email + , + emailConfirmed = 0 WHERE id = @id - END GO \ No newline at end of file From 6cc740f7389b09c0f1220fda761e852ec675c21b Mon Sep 17 00:00:00 2001 From: John Darragh Date: Fri, 26 May 2023 21:48:20 -0700 Subject: [PATCH 11/21] Attempt to fix Dockerfile bug (#1376) --- Dockerfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 702e5afe..444b72d4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,7 +4,8 @@ RUN mkdir /app WORKDIR /app COPY /client/package.json . COPY /client/package-lock.json . -RUN npm ci --legacy-peer-deps && find node_modules ! -user root | xargs chown root:root +#RUN npm ci --legacy-peer-deps && find node_modules ! -user root | xargs chown root:root +RUN npm ci --legacy-peer-deps && find node_modules | xargs chown root:root COPY /client . RUN npm run build From c10fbfb0ba9dbe8f641b2fe909d0b9199e42054b Mon Sep 17 00:00:00 2001 From: John Darragh Date: Fri, 26 May 2023 21:52:56 -0700 Subject: [PATCH 12/21] 1375 GitHub action bug (#1377) * Attempt to fix Dockerfile bug * Attempt to fix Dockerfile deployment bug, take 2 --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 444b72d4..b7142300 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,7 +5,7 @@ WORKDIR /app COPY /client/package.json . COPY /client/package-lock.json . #RUN npm ci --legacy-peer-deps && find node_modules ! -user root | xargs chown root:root -RUN npm ci --legacy-peer-deps && find node_modules | xargs chown root:root +RUN npm ci --legacy-peer-deps COPY /client . RUN npm run build From dd13d66e9c4a4103a44cef72c6480f080adf0316 Mon Sep 17 00:00:00 2001 From: John Darragh Date: Fri, 26 May 2023 22:01:17 -0700 Subject: [PATCH 13/21] Update Dockerfile --- Dockerfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index b7142300..032ea017 100644 --- a/Dockerfile +++ b/Dockerfile @@ -19,7 +19,8 @@ COPY --from=clientBuilder /app/build /client/build COPY ./server/package.json ./ COPY ./server/package-lock.json ./ -RUN npm ci && find node_modules ! -user root | xargs chown root:root +#RUN npm ci && find node_modules ! -user root | xargs chown root:root +RUN npm ci COPY ./server/app ./app COPY ./server/middleware ./middleware From 20f2f1960a3c105b0b2e67e257478cf172a8eb71 Mon Sep 17 00:00:00 2001 From: John Darragh Date: Fri, 26 May 2023 22:34:13 -0700 Subject: [PATCH 14/21] Fix bug in Dockerfile, take 4 (#1379) --- server/app/controllers/account.controller.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/app/controllers/account.controller.js b/server/app/controllers/account.controller.js index 014d0c08..d3550706 100644 --- a/server/app/controllers/account.controller.js +++ b/server/app/controllers/account.controller.js @@ -5,7 +5,7 @@ const { } = require("../../middleware/validate"); const accountSchema = require("../schemas/account"); const accountRegisterSchema = require("../schemas/account.register"); -const accountUpdateAccountSchema = require("../schemas/account.UpdateAccount"); +const accountUpdateAccountSchema = require("../schemas/account.updateAccount"); const accountConfirmRegisterSchema = require("../schemas/account.confirmRegister"); const accountLoginSchema = require("../schemas/account.login"); const accountForgotSchema = require("../schemas/account.forgotPassword"); From 7c910ad12bad68a18cecec51cbbe20eabd6ada8f Mon Sep 17 00:00:00 2001 From: James Higgs <40730303+jahpe777@users.noreply.github.com> Date: Wed, 31 May 2023 18:52:22 -0700 Subject: [PATCH 15/21] 1363 calculation summary pdf (#1374) * 230505 * 230506 * 230506_1 * 230506_2 * 230510 * 230510_1 * added in first instances of props from project summary component into the new pdf component * 230513 * 230520 * 230521 * Implemented TDM Calculation Summary Print Out * Implemented TDM Calculation Summary Print Out_2 * Fixed logo appearance, erged with develop branch * Undo accidental changes to /package.json & /package-lock.json --------- Co-authored-by: James Higgs Co-authored-by: James Higgs Co-authored-by: John Darragh --- client/package-lock.json | 1201 ++++++++++++++--- client/package.json | 2 + client/src/components/Button/Button.js | 6 + .../src/components/Button/DownloadButton 2.js | 32 + .../src/components/Button/DownloadButton.js | 33 + client/src/components/PDF/PDF.js | 291 ++++ client/src/components/PDF/PdfFooter.js | 63 + client/src/components/PDF/PdfResult.js | 20 + .../ProjectWizard/TdmCalculationWizard.js | 9 + .../components/ProjectWizard/WizardFooter.js | 40 +- .../ProjectSummary/ProjectSummary.js | 1 - server/report.html | 1077 +++++++++++++++ server/report.json | 19 + 13 files changed, 2596 insertions(+), 198 deletions(-) create mode 100644 client/src/components/Button/DownloadButton 2.js create mode 100644 client/src/components/Button/DownloadButton.js create mode 100644 client/src/components/PDF/PDF.js create mode 100644 client/src/components/PDF/PdfFooter.js create mode 100644 client/src/components/PDF/PdfResult.js create mode 100644 server/report.html create mode 100644 server/report.json diff --git a/client/package-lock.json b/client/package-lock.json index 4e3a3c31..186cd367 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -1,18 +1,19 @@ { "name": "tdm-calculator-client", - "version": "0.2.42", + "version": "0.2.45", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "tdm-calculator-client", - "version": "0.2.42", + "version": "0.2.45", "dependencies": { "@fortawesome/fontawesome-svg-core": "^6.1.1", "@fortawesome/free-solid-svg-icons": "^6.1.1", "@fortawesome/react-fontawesome": "^0.1.18", "@microsoft/applicationinsights-react-js": "^3.0.5", "@microsoft/applicationinsights-web": "^2.5.11", + "@react-pdf/renderer": "^3.1.9", "axios": "^0.27.2", "clsx": "^1.1.1", "formik": "^2.2.9", @@ -27,6 +28,7 @@ "react-router-dom": "^5.3.0", "react-select": "^5.2.2", "react-string-replace": "^1.1.0", + "react-to-print": "^2.14.12", "react-tooltip": "^4.2.21", "yup": "^0.32.11" }, @@ -52,7 +54,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", - "dev": true, "dependencies": { "@jridgewell/gen-mapping": "^0.1.0", "@jridgewell/trace-mapping": "^0.3.9" @@ -76,7 +77,6 @@ "version": "7.17.10", "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.17.10.tgz", "integrity": "sha512-GZt/TCsG70Ms19gfZO1tM4CVnXsPgEPBCpJu+Qz3L0LUDsY5nZqFZglIoPC1kIYOtNBZlrnFT+klg12vFGZXrw==", - "dev": true, "engines": { "node": ">=6.9.0" } @@ -85,7 +85,6 @@ "version": "7.17.10", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.17.10.tgz", "integrity": "sha512-liKoppandF3ZcBnIYFjfSDHZLKdLHGJRkoWtG8zQyGJBQfIYobpnVGI5+pLBNtS6psFLDzyq8+h5HiVljW9PNA==", - "dev": true, "dependencies": { "@ampproject/remapping": "^2.1.0", "@babel/code-frame": "^7.16.7", @@ -133,7 +132,6 @@ "version": "7.17.10", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.10.tgz", "integrity": "sha512-46MJZZo9y3o4kmhBVc7zW7i8dtR1oIK/sdO5NcfcZRhTGYi+KKJRtHNgsU6c4VUcJmUNV/LQdebD/9Dlv4K+Tg==", - "dev": true, "dependencies": { "@babel/types": "^7.17.10", "@jridgewell/gen-mapping": "^0.1.0", @@ -172,7 +170,6 @@ "version": "7.17.10", "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.17.10.tgz", "integrity": "sha512-gh3RxjWbauw/dFiU/7whjd0qN9K6nPJMqe6+Er7rOavFh0CQUSwhAE3IcTho2rywPJFxej6TUUHDkWcYI6gGqQ==", - "dev": true, "dependencies": { "@babel/compat-data": "^7.17.10", "@babel/helper-validator-option": "^7.16.7", @@ -246,7 +243,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz", "integrity": "sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag==", - "dev": true, "dependencies": { "@babel/types": "^7.16.7" }, @@ -270,7 +266,6 @@ "version": "7.17.9", "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.17.9.tgz", "integrity": "sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg==", - "dev": true, "dependencies": { "@babel/template": "^7.16.7", "@babel/types": "^7.17.0" @@ -283,7 +278,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz", "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==", - "dev": true, "dependencies": { "@babel/types": "^7.16.7" }, @@ -318,7 +312,6 @@ "version": "7.17.7", "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.17.7.tgz", "integrity": "sha512-VmZD99F3gNTYB7fJRDTi+u6l/zxY0BE6OIxPSU7a50s6ZUQkHwSDmV92FfM+oCG0pZRVojGYhkR8I0OGeCVREw==", - "dev": true, "dependencies": { "@babel/helper-environment-visitor": "^7.16.7", "@babel/helper-module-imports": "^7.16.7", @@ -387,7 +380,6 @@ "version": "7.17.7", "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.17.7.tgz", "integrity": "sha512-txyMCGroZ96i+Pxr3Je3lzEJjqwaRC9buMUgtomcrLe5Nd0+fk1h0LLA+ixUF5OW7AhHuQ7Es1WcQJZmZsz2XA==", - "dev": true, "dependencies": { "@babel/types": "^7.17.0" }, @@ -411,7 +403,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz", "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==", - "dev": true, "dependencies": { "@babel/types": "^7.16.7" }, @@ -431,7 +422,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz", "integrity": "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==", - "dev": true, "engines": { "node": ">=6.9.0" } @@ -455,7 +445,6 @@ "version": "7.17.9", "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.17.9.tgz", "integrity": "sha512-cPCt915ShDWUEzEp3+UNRktO2n6v49l5RSnG9M5pS24hA+2FAc5si+Pn1i4VVbQQ+jh+bIZhPFQOJOzbrOYY1Q==", - "dev": true, "dependencies": { "@babel/template": "^7.16.7", "@babel/traverse": "^7.17.9", @@ -482,7 +471,6 @@ "version": "7.17.10", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.10.tgz", "integrity": "sha512-n2Q6i+fnJqzOaq2VkdXxy2TCPCWQZHiCo0XqmrCvDWcZQKRyZzYi4Z0yxlBuN0w+r2ZHmre+Q087DSrw3pbJDQ==", - "dev": true, "bin": { "parser": "bin/babel-parser.js" }, @@ -1831,11 +1819,11 @@ } }, "node_modules/@babel/runtime": { - "version": "7.17.9", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.9.tgz", - "integrity": "sha512-lSiBBvodq29uShpWGNbgFdKYNiFDo5/HIYsaCEY9ff4sb10x9jizo2+pRrSyF4jKZCXqgzuqBOQKbUm90gQwJg==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.5.tgz", + "integrity": "sha512-8jI69toZqqcsnqGGqwGS4Qb1VwLOEp4hz+CXPywcvjs60u3B4Pom/U/7rm4W8tMOYEB+E9wgD0mW1l3r8qlI9Q==", "dependencies": { - "regenerator-runtime": "^0.13.4" + "regenerator-runtime": "^0.13.11" }, "engines": { "node": ">=6.9.0" @@ -1858,7 +1846,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", - "dev": true, "dependencies": { "@babel/code-frame": "^7.16.7", "@babel/parser": "^7.16.7", @@ -1872,7 +1859,6 @@ "version": "7.17.10", "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.17.10.tgz", "integrity": "sha512-VmbrTHQteIdUUQNTb+zE12SHS/xQVIShmBPhlNP12hD5poF2pbITW1Z4172d03HegaQWhLffdkRJYtAzp0AGcw==", - "dev": true, "dependencies": { "@babel/code-frame": "^7.16.7", "@babel/generator": "^7.17.10", @@ -2973,7 +2959,6 @@ "version": "0.1.1", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", - "dev": true, "dependencies": { "@jridgewell/set-array": "^1.0.0", "@jridgewell/sourcemap-codec": "^1.4.10" @@ -2986,7 +2971,6 @@ "version": "3.0.7", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.7.tgz", "integrity": "sha512-8cXDaBBHOr2pQ7j77Y6Vp5VDT2sIqWyWQ56TjEq4ih/a4iST3dItRe8Q9fp0rrIl9DoKhWQtUQz/YpOxLkXbNA==", - "dev": true, "engines": { "node": ">=6.0.0" } @@ -2995,7 +2979,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.1.tgz", "integrity": "sha512-Ct5MqZkLGEXTVmQYbGtx9SVqD2fqwvdubdps5D3djjAkgkKwT918VNOz65pEHFaYTeWcukmJmH5SwsA9Tn2ObQ==", - "dev": true, "engines": { "node": ">=6.0.0" } @@ -3003,14 +2986,12 @@ "node_modules/@jridgewell/sourcemap-codec": { "version": "1.4.13", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.13.tgz", - "integrity": "sha512-GryiOJmNcWbovBxTfZSF71V/mXbgcV3MewDe3kIMCLyIh5e7SKAeUZs+rMnJ8jkMolZ/4/VsdBmMrw3l+VdZ3w==", - "dev": true + "integrity": "sha512-GryiOJmNcWbovBxTfZSF71V/mXbgcV3MewDe3kIMCLyIh5e7SKAeUZs+rMnJ8jkMolZ/4/VsdBmMrw3l+VdZ3w==" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.13", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.13.tgz", "integrity": "sha512-o1xbKhp9qnIAoHJSWd6KlCZfqslL4valSF81H8ImioOAxluWYWOpWkpyktY2vnt4tbrX9XYaxovq6cgowaJp2w==", - "dev": true, "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" @@ -3241,6 +3222,172 @@ "node": ">= 8" } }, + "node_modules/@react-pdf/fns": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@react-pdf/fns/-/fns-2.0.1.tgz", + "integrity": "sha512-/vgecczzFYBQFkgUupH+sxXhLWQtBwdwCgweyh25XOlR4NZuaMD/UVUDl4loFHhRQqDMQq37lkTcchh7zzW6ug==", + "dependencies": { + "@babel/runtime": "^7.20.13" + } + }, + "node_modules/@react-pdf/font": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/@react-pdf/font/-/font-2.3.4.tgz", + "integrity": "sha512-ICvVH0GW3kgocxVfE0mFY3EcnAoxRolkOfhPCfLu8mRbwJaHRiKX5+8SRKbPADZNdHrF9ngt4LpUxThy+bdZXg==", + "dependencies": { + "@babel/runtime": "^7.20.13", + "@react-pdf/types": "^2.3.1", + "cross-fetch": "^3.1.5", + "fontkit": "^2.0.2", + "is-url": "^1.2.4" + } + }, + "node_modules/@react-pdf/image": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@react-pdf/image/-/image-2.2.1.tgz", + "integrity": "sha512-f0+cEP6pSBmk8eS/wP2tMsJcv2c7xjzca6cr1kwcapr1nzkPrh6fMdEeFl6kR2/HlJK/JoHo+xxlzRiQ8V2lrw==", + "dependencies": { + "@babel/runtime": "^7.20.13", + "@react-pdf/png-js": "^2.2.0", + "cross-fetch": "^3.1.5" + } + }, + "node_modules/@react-pdf/layout": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@react-pdf/layout/-/layout-3.6.0.tgz", + "integrity": "sha512-xrcVWxtXpobW0iqTd8OmMCVMmeGUM46PYq7B1MGR1fI1QG/EKe4HzFdhSdd0werZYj+t1TRC8+tVSX5POs5SYA==", + "dependencies": { + "@babel/runtime": "^7.20.13", + "@react-pdf/fns": "2.0.1", + "@react-pdf/image": "^2.2.1", + "@react-pdf/pdfkit": "^3.0.2", + "@react-pdf/primitives": "^3.0.0", + "@react-pdf/stylesheet": "^4.1.5", + "@react-pdf/textkit": "^4.2.0", + "@react-pdf/types": "^2.3.1", + "@react-pdf/yoga": "^4.1.2", + "cross-fetch": "^3.1.5", + "emoji-regex": "^10.2.1", + "queue": "^6.0.1" + } + }, + "node_modules/@react-pdf/layout/node_modules/emoji-regex": { + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.2.1.tgz", + "integrity": "sha512-97g6QgOk8zlDRdgq1WxwgTMgEWGVAQvB5Fdpgc1MkNy56la5SKP9GsMXKDOdqwn90/41a8yPwIGk1Y6WVbeMQA==" + }, + "node_modules/@react-pdf/pdfkit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@react-pdf/pdfkit/-/pdfkit-3.0.2.tgz", + "integrity": "sha512-+m5rwNCwyEH6lmnZWpsQJvdqb6YaCCR0nMWrc/KKDwznuPMrGmGWyNxqCja+bQPORcHZyl6Cd/iFL0glyB3QGw==", + "dependencies": { + "@babel/runtime": "^7.20.13", + "@react-pdf/png-js": "^2.2.0", + "browserify-zlib": "^0.2.0", + "crypto-js": "^4.0.0", + "fontkit": "^2.0.2", + "vite-compatible-readable-stream": "^3.6.1" + } + }, + "node_modules/@react-pdf/png-js": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@react-pdf/png-js/-/png-js-2.2.0.tgz", + "integrity": "sha512-csZU5lfNW73tq7s7zB/1rWXGro+Z9cQhxtsXwxS418TSszHUiM6PwddouiKJxdGhbVLjRIcuuFVa0aR5cDOC6w==", + "dependencies": { + "browserify-zlib": "^0.2.0" + } + }, + "node_modules/@react-pdf/primitives": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@react-pdf/primitives/-/primitives-3.0.1.tgz", + "integrity": "sha512-0HGcknrLNwyhxe+SZCBL29JY4M85mXKdvTZE9uhjNbADGgTc8wVnkc5+e4S/lDvugbVISXyuIhZnYwtK9eDnyQ==" + }, + "node_modules/@react-pdf/render": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@react-pdf/render/-/render-3.2.4.tgz", + "integrity": "sha512-lnef097Dx2vHKpY9OHHNmV+nsG5vpd33h76tCzdlbijj+TyVm1j7ZQ5qadGq1uMOFAU6lp0hEo7VoDk7XnjmFw==", + "dependencies": { + "@babel/runtime": "^7.20.13", + "@react-pdf/fns": "2.0.1", + "@react-pdf/primitives": "^3.0.0", + "@react-pdf/textkit": "^4.2.0", + "@react-pdf/types": "^2.3.1", + "abs-svg-path": "^0.1.1", + "color-string": "^1.5.3", + "normalize-svg-path": "^1.1.0", + "parse-svg-path": "^0.1.2", + "svg-arc-to-cubic-bezier": "^3.2.0" + } + }, + "node_modules/@react-pdf/renderer": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/@react-pdf/renderer/-/renderer-3.1.9.tgz", + "integrity": "sha512-kfEH7O+Jy7aihbUqrT9Ej1gx8/twRWvFMfHlACr29QsN+s+w0XzWpHCvbjkinVFABYcvsenluiirik6mf4qwRQ==", + "dependencies": { + "@babel/runtime": "^7.20.13", + "@react-pdf/font": "^2.3.4", + "@react-pdf/layout": "^3.6.0", + "@react-pdf/pdfkit": "^3.0.2", + "@react-pdf/primitives": "^3.0.0", + "@react-pdf/render": "^3.2.4", + "@react-pdf/types": "^2.3.1", + "events": "^3.3.0", + "object-assign": "^4.1.1", + "prop-types": "^15.6.2", + "queue": "^6.0.1", + "scheduler": "^0.17.0" + }, + "peerDependencies": { + "react": "^16.8.6 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/@react-pdf/renderer/node_modules/scheduler": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.17.0.tgz", + "integrity": "sha512-7rro8Io3tnCPuY4la/NuI5F2yfESpnfZyT6TtkXnSWVkcu0BCDJ+8gk5ozUaFaxpIyNuWAPXrH0yFcSi28fnDA==", + "dependencies": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + }, + "node_modules/@react-pdf/stylesheet": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@react-pdf/stylesheet/-/stylesheet-4.1.5.tgz", + "integrity": "sha512-8sP+4KD3cAfBEsZBQeJC7GUC0vkCLiAc6kZaGX0dXaBR3nZO2TaCD8+ZuezokZi+ARp/yvWJqR2vIX8ra7X1xA==", + "dependencies": { + "@babel/runtime": "^7.20.13", + "@react-pdf/fns": "2.0.1", + "@react-pdf/types": "^2.3.1", + "color-string": "^1.5.3", + "hsl-to-hex": "^1.0.0", + "media-engine": "^1.0.3", + "postcss-value-parser": "^4.1.0" + } + }, + "node_modules/@react-pdf/textkit": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@react-pdf/textkit/-/textkit-4.2.0.tgz", + "integrity": "sha512-R90pEOW6NdhUx4p99iROvKmwB06IRYdXMhh0QcmUeoPOLe64ZdMfs3LZliNUWgI5fCmq71J+nv868i/EakFPDg==", + "dependencies": { + "@babel/runtime": "^7.20.13", + "@react-pdf/fns": "2.0.1", + "hyphen": "^1.6.4", + "unicode-properties": "^1.4.1" + } + }, + "node_modules/@react-pdf/types": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@react-pdf/types/-/types-2.3.1.tgz", + "integrity": "sha512-FiwAsNp2oQ2W39xAU1PCjY6YNjEuypQykEA6VMz4WZ4ERvyOBB4M5B8063lA8YYBcjYB8xQOa9og4UH1eqMbgg==" + }, + "node_modules/@react-pdf/yoga": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@react-pdf/yoga/-/yoga-4.1.2.tgz", + "integrity": "sha512-OlMZkFrJDj4GyKZ70thiObwwPVZ52B7mlPyfzwa+sgwsioqHXg9nMWOO+7SQFNUbbOGagMUu0bCuTv+iXYZuaQ==", + "dependencies": { + "@babel/runtime": "^7.20.13" + } + }, "node_modules/@rollup/plugin-babel": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", @@ -3615,6 +3762,14 @@ "url": "https://github.com/sponsors/gregberge" } }, + "node_modules/@swc/helpers": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.4.14.tgz", + "integrity": "sha512-4C7nX/dvpzB7za4Ql9K81xK3HPxCpHMgwTZVyf+9JQ6VUbn9jjZVN7/Nkdz/Ugzs2CSjqnL/UPXroiVBVHUWUw==", + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@testing-library/dom": { "version": "8.10.1", "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-8.10.1.tgz", @@ -4593,6 +4748,11 @@ "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", "dev": true }, + "node_modules/abs-svg-path": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/abs-svg-path/-/abs-svg-path-0.1.1.tgz", + "integrity": "sha512-d8XPSGjfyzlXC3Xx891DJRyZfqk5JU0BJrDQcsWomFIV1/BIzPW5HDH5iDdWpqWaav0YVIEzT1RHTwWr0FFshA==" + }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -5417,6 +5577,25 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/batch": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", @@ -5562,17 +5741,32 @@ "node": ">=8" } }, + "node_modules/brotli": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/brotli/-/brotli-1.3.3.tgz", + "integrity": "sha512-oTKjJdShmDuGW94SyyaoQvAjf30dZaHnjJ8uAF+u2/vGJkJbJPJAT1gDiOJP5v1Zb6f9KEyW/1HpuaWIXtGHPg==", + "dependencies": { + "base64-js": "^1.1.2" + } + }, "node_modules/browser-process-hrtime": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==", "dev": true }, + "node_modules/browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "dependencies": { + "pako": "~1.0.5" + } + }, "node_modules/browserslist": { "version": "4.20.3", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.3.tgz", "integrity": "sha512-NBhymBQl1zM0Y5dQT/O+xiLP9/rzOIQdKM/eMJBAq7yBgaB6krIYLGejrwVYnSHZdqjscB1SPuAjHwxjvN6Wdg==", - "dev": true, "funding": [ { "type": "opencollective", @@ -5701,7 +5895,6 @@ "version": "1.0.30001340", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001340.tgz", "integrity": "sha512-jUNz+a9blQTQVu4uFcn17uAD8IDizPzQkIKh3LCJfg9BkyIqExYYdyc/ZSlWUSKb8iYiXxKsxbv4zYSvkqjrxw==", - "dev": true, "funding": [ { "type": "opencollective", @@ -5920,6 +6113,14 @@ "wrap-ansi": "^7.0.0" } }, + "node_modules/clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", + "engines": { + "node": ">=0.8" + } + }, "node_modules/clsx": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.1.1.tgz", @@ -5973,8 +6174,16 @@ "node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } }, "node_modules/colord": { "version": "2.9.2", @@ -6234,6 +6443,14 @@ "object-assign": "^4.1.1" } }, + "node_modules/cross-fetch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz", + "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==", + "dependencies": { + "node-fetch": "2.6.7" + } + }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -6248,6 +6465,11 @@ "node": ">= 8" } }, + "node_modules/crypto-js": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.1.1.tgz", + "integrity": "sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw==" + }, "node_modules/crypto-random-string": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", @@ -6753,7 +6975,6 @@ "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, "dependencies": { "ms": "2.1.2" }, @@ -6936,6 +7157,11 @@ "node": ">=0.8.0" } }, + "node_modules/dfa": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/dfa/-/dfa-1.2.0.tgz", + "integrity": "sha512-ED3jP8saaweFTjeGX8HQPjeC1YYyZs98jGNZx6IiBvxW7JG5v492kamAQB3m2wop07CvU/RQmzcKr6bgcC5D/Q==" + }, "node_modules/didyoumean": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", @@ -7160,8 +7386,7 @@ "node_modules/electron-to-chromium": { "version": "1.4.137", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.137.tgz", - "integrity": "sha512-0Rcpald12O11BUogJagX3HsCN3FE83DSqWjgXoHo5a72KUKMSfI39XBgJpgNNxS9fuGzytaFjE06kZkiVFy2qA==", - "dev": true + "integrity": "sha512-0Rcpald12O11BUogJagX3HsCN3FE83DSqWjgXoHo5a72KUKMSfI39XBgJpgNNxS9fuGzytaFjE06kZkiVFy2qA==" }, "node_modules/emittery": { "version": "0.8.1", @@ -7311,7 +7536,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true, "engines": { "node": ">=6" } @@ -8193,7 +8417,6 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true, "engines": { "node": ">=0.8.x" } @@ -8336,8 +8559,7 @@ "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "node_modules/fast-diff": { "version": "1.2.0", @@ -8595,6 +8817,22 @@ } } }, + "node_modules/fontkit": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fontkit/-/fontkit-2.0.2.tgz", + "integrity": "sha512-jc4k5Yr8iov8QfS6u8w2CnHWVmbOGtdBtOXMze5Y+QD966Rx6PEVWXSEGwXlsDlKtu1G12cJjcsybnqhSk/+LA==", + "dependencies": { + "@swc/helpers": "^0.4.2", + "brotli": "^1.3.2", + "clone": "^2.1.2", + "dfa": "^1.2.0", + "fast-deep-equal": "^3.1.3", + "restructure": "^3.0.0", + "tiny-inflate": "^1.0.3", + "unicode-properties": "^1.4.0", + "unicode-trie": "^2.0.0" + } + }, "node_modules/fork-ts-checker-webpack-plugin": { "version": "6.5.2", "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.2.tgz", @@ -8906,7 +9144,6 @@ "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, "engines": { "node": ">=6.9.0" } @@ -9057,7 +9294,6 @@ "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, "engines": { "node": ">=4" } @@ -9262,6 +9498,19 @@ "safe-buffer": "~5.1.0" } }, + "node_modules/hsl-to-hex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hsl-to-hex/-/hsl-to-hex-1.0.0.tgz", + "integrity": "sha512-K6GVpucS5wFf44X0h2bLVRDsycgJmf9FF2elg+CrqD8GcFU8c6vYhgXn8NjUkFCwj+xDFb70qgLbTUm6sxwPmA==", + "dependencies": { + "hsl-to-rgb-for-reals": "^1.1.0" + } + }, + "node_modules/hsl-to-rgb-for-reals": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/hsl-to-rgb-for-reals/-/hsl-to-rgb-for-reals-1.1.1.tgz", + "integrity": "sha512-LgOWAkrN0rFaQpfdWBQlv/VhkOxb5AsBjk6NQVx4yEzWS923T07X0M1Y0VNko2H52HeSpZrZNNMJ0aFqsdVzQg==" + }, "node_modules/html-encoding-sniffer": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz", @@ -9451,6 +9700,11 @@ "node": ">=10.17.0" } }, + "node_modules/hyphen": { + "version": "1.6.5", + "resolved": "https://registry.npmjs.org/hyphen/-/hyphen-1.6.5.tgz", + "integrity": "sha512-MZbhHutRaHCUxjvJBYqL51Ntjbq16LemuJr2u+LpKd3UwyNHZsZAKh5uD+KmdAHtWpteupOqQTTezVGR/al43w==" + }, "node_modules/hyphenate-style-name": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz", @@ -9596,8 +9850,7 @@ "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "node_modules/ini": { "version": "1.3.8", @@ -9941,6 +10194,11 @@ "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", "dev": true }, + "node_modules/is-url": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", + "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==" + }, "node_modules/is-weakref": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", @@ -11964,7 +12222,6 @@ "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true, "bin": { "jsesc": "bin/jsesc" }, @@ -12005,7 +12262,6 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", - "dev": true, "bin": { "json5": "lib/cli.js" }, @@ -12620,6 +12876,11 @@ "integrity": "sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==", "dev": true }, + "node_modules/media-engine": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/media-engine/-/media-engine-1.0.3.tgz", + "integrity": "sha512-aa5tG6sDoK+k70B9iEX1NeyfT8ObCKhNDs6lJVpwF6r8vhUfuKMslIcirq6HIUYuuUYLefcEQOn9bSBOvawtwg==" + }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -12857,8 +13118,7 @@ "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/multicast-dns": { "version": "7.2.4", @@ -12936,6 +13196,44 @@ "node": ">= 10.13" } }, + "node_modules/node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-fetch/node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "node_modules/node-fetch/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/node-fetch/node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/node-forge": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", @@ -12954,8 +13252,7 @@ "node_modules/node-releases": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.4.tgz", - "integrity": "sha512-gbMzqQtTtDz/00jQzZ21PQzdI9PyLYqUSvD0p3naOhX4odFji0ZxYdnVwPTxmSwkmxhcFImpozceidSG+AgoPQ==", - "dev": true + "integrity": "sha512-gbMzqQtTtDz/00jQzZ21PQzdI9PyLYqUSvD0p3naOhX4odFji0ZxYdnVwPTxmSwkmxhcFImpozceidSG+AgoPQ==" }, "node_modules/normalize-path": { "version": "3.0.0", @@ -12975,6 +13272,14 @@ "node": ">=0.10.0" } }, + "node_modules/normalize-svg-path": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/normalize-svg-path/-/normalize-svg-path-1.1.0.tgz", + "integrity": "sha512-r9KHKG2UUeB5LoTouwDzBy2VxXlHsiM6fyLQvnJa0S5hrhzqElH/CH7TUGhT1fVvIYBIKf3OpY4YJ4CK+iaqHg==", + "dependencies": { + "svg-arc-to-cubic-bezier": "^3.0.0" + } + }, "node_modules/normalize-url": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", @@ -13300,6 +13605,11 @@ "node": ">=6" } }, + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" + }, "node_modules/param-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", @@ -13338,6 +13648,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/parse-svg-path": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/parse-svg-path/-/parse-svg-path-0.1.2.tgz", + "integrity": "sha512-JyPSBnkTJ0AI8GGJLfMXvKq42cj5c006fnLz6fXy6zfoVjJizi8BNTpu8on8ziI1cKy9d9DGNuY17Ce7wuejpQ==" + }, "node_modules/parse5": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", @@ -13418,8 +13733,7 @@ "node_modules/picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" }, "node_modules/picomatch": { "version": "2.3.0", @@ -14782,8 +15096,7 @@ "node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "node_modules/prelude-ls": { "version": "1.2.1", @@ -14988,6 +15301,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/queue": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz", + "integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==", + "dependencies": { + "inherits": "~2.0.3" + } + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -15566,6 +15887,18 @@ "integrity": "sha512-Fl7FuabXsJnV5Q1qIOQwx/sagGF18kogb4gpfcG4gjLBWO0WDiiz1ko/ExayuxE7InyQkBLkxRFG5oxY6Uu3Kg==", "dev": true }, + "node_modules/react-to-print": { + "version": "2.14.12", + "resolved": "https://registry.npmjs.org/react-to-print/-/react-to-print-2.14.12.tgz", + "integrity": "sha512-qFJAwvDFd95Z+FWNqitt+HaB1/z+Zdd0MMrNOPUSus3fG32vqv512yB+HXhQ94J3HKoyqaIg44v0Zfc6xUBqlg==", + "dependencies": { + "prop-types": "^15.8.1" + }, + "peerDependencies": { + "react": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/react-tooltip": { "version": "4.2.21", "resolved": "https://registry.npmjs.org/react-tooltip/-/react-tooltip-4.2.21.tgz", @@ -15687,9 +16020,9 @@ } }, "node_modules/regenerator-runtime": { - "version": "0.13.9", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", - "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" }, "node_modules/regenerator-transform": { "version": "0.15.0", @@ -15961,6 +16294,11 @@ "node": ">=8" } }, + "node_modules/restructure": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/restructure/-/restructure-3.0.0.tgz", + "integrity": "sha512-Xj8/MEIhhfj9X2rmD9iJ4Gga9EFqVlpMj3vfLnV2r/Mh5jRMryNV+6lWh9GdJtDBcBSPIqzRdfBQ3wDtNFv/uw==" + }, "node_modules/retry": { "version": "0.13.1", "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", @@ -16245,7 +16583,6 @@ "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, "bin": { "semver": "bin/semver.js" } @@ -16455,6 +16792,19 @@ "integrity": "sha512-KWcOiKeQj6ZyXx7zq4YxSMgHRlod4czeBQZrPb8OKcohcqAXShm7E20kEMle9WBt26hFcAf0qLOcp5zmY7kOqQ==", "dev": true }, + "node_modules/simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", + "dependencies": { + "is-arrayish": "^0.3.1" + } + }, + "node_modules/simple-swizzle/node_modules/is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" + }, "node_modules/sisteransi": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", @@ -16687,7 +17037,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, "dependencies": { "safe-buffer": "~5.2.0" } @@ -16696,7 +17045,6 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, "funding": [ { "type": "github", @@ -16977,6 +17325,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/svg-arc-to-cubic-bezier": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/svg-arc-to-cubic-bezier/-/svg-arc-to-cubic-bezier-3.2.0.tgz", + "integrity": "sha512-djbJ/vZKZO+gPoSDThGNpKDO+o+bAeA4XQKovvkNCqnIS2t+S4qnLAGQhyyrulhCFRl1WWzAp0wUDV8PpTVU3g==" + }, "node_modules/svg-parser": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", @@ -17180,6 +17533,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/tempy/node_modules/type-fest": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.16.0.tgz", + "integrity": "sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/terminal-link": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", @@ -17356,6 +17721,11 @@ "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", "dev": true }, + "node_modules/tiny-inflate": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz", + "integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==" + }, "node_modules/tiny-invariant": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.1.0.tgz", @@ -17481,10 +17851,9 @@ } }, "node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", - "dev": true + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/tsutils": { "version": "3.21.0", @@ -17529,12 +17898,14 @@ } }, "node_modules/type-fest": { - "version": "0.16.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.16.0.tgz", - "integrity": "sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==", + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", "dev": true, + "optional": true, + "peer": true, "engines": { - "node": ">=10" + "node": ">=12.20" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -17562,6 +17933,20 @@ "is-typedarray": "^1.0.0" } }, + "node_modules/typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "dev": true, + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, "node_modules/unbox-primitive": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", @@ -17608,6 +17993,15 @@ "node": ">=4" } }, + "node_modules/unicode-properties": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/unicode-properties/-/unicode-properties-1.4.1.tgz", + "integrity": "sha512-CLjCCLQ6UuMxWnbIylkisbRj31qxHPAurvena/0iwSVbQ2G1VY5/HjV0IRabOEbDHlzZlRdCrD4NhB0JtU40Pg==", + "dependencies": { + "base64-js": "^1.3.0", + "unicode-trie": "^2.0.0" + } + }, "node_modules/unicode-property-aliases-ecmascript": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz", @@ -17617,6 +18011,20 @@ "node": ">=4" } }, + "node_modules/unicode-trie": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-trie/-/unicode-trie-2.0.0.tgz", + "integrity": "sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ==", + "dependencies": { + "pako": "^0.2.5", + "tiny-inflate": "^1.0.0" + } + }, + "node_modules/unicode-trie/node_modules/pako": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", + "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==" + }, "node_modules/unique-string": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", @@ -17675,8 +18083,7 @@ "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, "node_modules/util.promisify": { "version": "1.0.0", @@ -17755,6 +18162,19 @@ "node": ">= 0.8" } }, + "node_modules/vite-compatible-readable-stream": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/vite-compatible-readable-stream/-/vite-compatible-readable-stream-3.6.1.tgz", + "integrity": "sha512-t20zYkrSf868+j/p31cRIGN28Phrjm3nRSLR2fyc2tiWi4cZGVdv68yNlwnIINTkMTmPoMiSlc0OadaO7DXZaQ==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/w3c-hr-time": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", @@ -18726,7 +19146,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", - "dev": true, "requires": { "@jridgewell/gen-mapping": "^0.1.0", "@jridgewell/trace-mapping": "^0.3.9" @@ -18743,14 +19162,12 @@ "@babel/compat-data": { "version": "7.17.10", "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.17.10.tgz", - "integrity": "sha512-GZt/TCsG70Ms19gfZO1tM4CVnXsPgEPBCpJu+Qz3L0LUDsY5nZqFZglIoPC1kIYOtNBZlrnFT+klg12vFGZXrw==", - "dev": true + "integrity": "sha512-GZt/TCsG70Ms19gfZO1tM4CVnXsPgEPBCpJu+Qz3L0LUDsY5nZqFZglIoPC1kIYOtNBZlrnFT+klg12vFGZXrw==" }, "@babel/core": { "version": "7.17.10", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.17.10.tgz", "integrity": "sha512-liKoppandF3ZcBnIYFjfSDHZLKdLHGJRkoWtG8zQyGJBQfIYobpnVGI5+pLBNtS6psFLDzyq8+h5HiVljW9PNA==", - "dev": true, "requires": { "@ampproject/remapping": "^2.1.0", "@babel/code-frame": "^7.16.7", @@ -18784,7 +19201,6 @@ "version": "7.17.10", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.10.tgz", "integrity": "sha512-46MJZZo9y3o4kmhBVc7zW7i8dtR1oIK/sdO5NcfcZRhTGYi+KKJRtHNgsU6c4VUcJmUNV/LQdebD/9Dlv4K+Tg==", - "dev": true, "requires": { "@babel/types": "^7.17.10", "@jridgewell/gen-mapping": "^0.1.0", @@ -18814,7 +19230,6 @@ "version": "7.17.10", "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.17.10.tgz", "integrity": "sha512-gh3RxjWbauw/dFiU/7whjd0qN9K6nPJMqe6+Er7rOavFh0CQUSwhAE3IcTho2rywPJFxej6TUUHDkWcYI6gGqQ==", - "dev": true, "requires": { "@babel/compat-data": "^7.17.10", "@babel/helper-validator-option": "^7.16.7", @@ -18867,7 +19282,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz", "integrity": "sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag==", - "dev": true, "requires": { "@babel/types": "^7.16.7" } @@ -18885,7 +19299,6 @@ "version": "7.17.9", "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.17.9.tgz", "integrity": "sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg==", - "dev": true, "requires": { "@babel/template": "^7.16.7", "@babel/types": "^7.17.0" @@ -18895,7 +19308,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz", "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==", - "dev": true, "requires": { "@babel/types": "^7.16.7" } @@ -18921,7 +19333,6 @@ "version": "7.17.7", "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.17.7.tgz", "integrity": "sha512-VmZD99F3gNTYB7fJRDTi+u6l/zxY0BE6OIxPSU7a50s6ZUQkHwSDmV92FfM+oCG0pZRVojGYhkR8I0OGeCVREw==", - "dev": true, "requires": { "@babel/helper-environment-visitor": "^7.16.7", "@babel/helper-module-imports": "^7.16.7", @@ -18975,7 +19386,6 @@ "version": "7.17.7", "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.17.7.tgz", "integrity": "sha512-txyMCGroZ96i+Pxr3Je3lzEJjqwaRC9buMUgtomcrLe5Nd0+fk1h0LLA+ixUF5OW7AhHuQ7Es1WcQJZmZsz2XA==", - "dev": true, "requires": { "@babel/types": "^7.17.0" } @@ -18993,7 +19403,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz", "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==", - "dev": true, "requires": { "@babel/types": "^7.16.7" } @@ -19006,8 +19415,7 @@ "@babel/helper-validator-option": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz", - "integrity": "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==", - "dev": true + "integrity": "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==" }, "@babel/helper-wrap-function": { "version": "7.16.8", @@ -19025,7 +19433,6 @@ "version": "7.17.9", "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.17.9.tgz", "integrity": "sha512-cPCt915ShDWUEzEp3+UNRktO2n6v49l5RSnG9M5pS24hA+2FAc5si+Pn1i4VVbQQ+jh+bIZhPFQOJOzbrOYY1Q==", - "dev": true, "requires": { "@babel/template": "^7.16.7", "@babel/traverse": "^7.17.9", @@ -19045,8 +19452,7 @@ "@babel/parser": { "version": "7.17.10", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.10.tgz", - "integrity": "sha512-n2Q6i+fnJqzOaq2VkdXxy2TCPCWQZHiCo0XqmrCvDWcZQKRyZzYi4Z0yxlBuN0w+r2ZHmre+Q087DSrw3pbJDQ==", - "dev": true + "integrity": "sha512-n2Q6i+fnJqzOaq2VkdXxy2TCPCWQZHiCo0XqmrCvDWcZQKRyZzYi4Z0yxlBuN0w+r2ZHmre+Q087DSrw3pbJDQ==" }, "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { "version": "7.16.7", @@ -19939,11 +20345,11 @@ } }, "@babel/runtime": { - "version": "7.17.9", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.9.tgz", - "integrity": "sha512-lSiBBvodq29uShpWGNbgFdKYNiFDo5/HIYsaCEY9ff4sb10x9jizo2+pRrSyF4jKZCXqgzuqBOQKbUm90gQwJg==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.5.tgz", + "integrity": "sha512-8jI69toZqqcsnqGGqwGS4Qb1VwLOEp4hz+CXPywcvjs60u3B4Pom/U/7rm4W8tMOYEB+E9wgD0mW1l3r8qlI9Q==", "requires": { - "regenerator-runtime": "^0.13.4" + "regenerator-runtime": "^0.13.11" } }, "@babel/runtime-corejs3": { @@ -19960,7 +20366,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", - "dev": true, "requires": { "@babel/code-frame": "^7.16.7", "@babel/parser": "^7.16.7", @@ -19971,7 +20376,6 @@ "version": "7.17.10", "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.17.10.tgz", "integrity": "sha512-VmbrTHQteIdUUQNTb+zE12SHS/xQVIShmBPhlNP12hD5poF2pbITW1Z4172d03HegaQWhLffdkRJYtAzp0AGcw==", - "dev": true, "requires": { "@babel/code-frame": "^7.16.7", "@babel/generator": "^7.17.10", @@ -20095,13 +20499,15 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/@csstools/postcss-unset-value/-/postcss-unset-value-1.0.1.tgz", "integrity": "sha512-f1G1WGDXEU/RN1TWAxBPQgQudtLnLQPyiWdtypkPC+mVYNKFKH/HYXSxH4MVNqwF8M0eDsoiU7HumJHCg/L/jg==", - "dev": true + "dev": true, + "requires": {} }, "@csstools/selector-specificity": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-1.0.0.tgz", "integrity": "sha512-RkYG5KiGNX0fJ5YoI0f4Wfq2Yo74D25Hru4fxTOioYdQvHBxcrrtTTyT5Ozzh2ejcNrhFy7IEts2WyEY7yi5yw==", - "dev": true + "dev": true, + "requires": {} }, "@emotion/babel-plugin": { "version": "11.7.2", @@ -20760,7 +21166,6 @@ "version": "0.1.1", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", - "dev": true, "requires": { "@jridgewell/set-array": "^1.0.0", "@jridgewell/sourcemap-codec": "^1.4.10" @@ -20769,26 +21174,22 @@ "@jridgewell/resolve-uri": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.7.tgz", - "integrity": "sha512-8cXDaBBHOr2pQ7j77Y6Vp5VDT2sIqWyWQ56TjEq4ih/a4iST3dItRe8Q9fp0rrIl9DoKhWQtUQz/YpOxLkXbNA==", - "dev": true + "integrity": "sha512-8cXDaBBHOr2pQ7j77Y6Vp5VDT2sIqWyWQ56TjEq4ih/a4iST3dItRe8Q9fp0rrIl9DoKhWQtUQz/YpOxLkXbNA==" }, "@jridgewell/set-array": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.1.tgz", - "integrity": "sha512-Ct5MqZkLGEXTVmQYbGtx9SVqD2fqwvdubdps5D3djjAkgkKwT918VNOz65pEHFaYTeWcukmJmH5SwsA9Tn2ObQ==", - "dev": true + "integrity": "sha512-Ct5MqZkLGEXTVmQYbGtx9SVqD2fqwvdubdps5D3djjAkgkKwT918VNOz65pEHFaYTeWcukmJmH5SwsA9Tn2ObQ==" }, "@jridgewell/sourcemap-codec": { "version": "1.4.13", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.13.tgz", - "integrity": "sha512-GryiOJmNcWbovBxTfZSF71V/mXbgcV3MewDe3kIMCLyIh5e7SKAeUZs+rMnJ8jkMolZ/4/VsdBmMrw3l+VdZ3w==", - "dev": true + "integrity": "sha512-GryiOJmNcWbovBxTfZSF71V/mXbgcV3MewDe3kIMCLyIh5e7SKAeUZs+rMnJ8jkMolZ/4/VsdBmMrw3l+VdZ3w==" }, "@jridgewell/trace-mapping": { "version": "0.3.13", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.13.tgz", "integrity": "sha512-o1xbKhp9qnIAoHJSWd6KlCZfqslL4valSF81H8ImioOAxluWYWOpWkpyktY2vnt4tbrX9XYaxovq6cgowaJp2w==", - "dev": true, "requires": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" @@ -20950,6 +21351,173 @@ } } }, + "@react-pdf/fns": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@react-pdf/fns/-/fns-2.0.1.tgz", + "integrity": "sha512-/vgecczzFYBQFkgUupH+sxXhLWQtBwdwCgweyh25XOlR4NZuaMD/UVUDl4loFHhRQqDMQq37lkTcchh7zzW6ug==", + "requires": { + "@babel/runtime": "^7.20.13" + } + }, + "@react-pdf/font": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/@react-pdf/font/-/font-2.3.4.tgz", + "integrity": "sha512-ICvVH0GW3kgocxVfE0mFY3EcnAoxRolkOfhPCfLu8mRbwJaHRiKX5+8SRKbPADZNdHrF9ngt4LpUxThy+bdZXg==", + "requires": { + "@babel/runtime": "^7.20.13", + "@react-pdf/types": "^2.3.1", + "cross-fetch": "^3.1.5", + "fontkit": "^2.0.2", + "is-url": "^1.2.4" + } + }, + "@react-pdf/image": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@react-pdf/image/-/image-2.2.1.tgz", + "integrity": "sha512-f0+cEP6pSBmk8eS/wP2tMsJcv2c7xjzca6cr1kwcapr1nzkPrh6fMdEeFl6kR2/HlJK/JoHo+xxlzRiQ8V2lrw==", + "requires": { + "@babel/runtime": "^7.20.13", + "@react-pdf/png-js": "^2.2.0", + "cross-fetch": "^3.1.5" + } + }, + "@react-pdf/layout": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@react-pdf/layout/-/layout-3.6.0.tgz", + "integrity": "sha512-xrcVWxtXpobW0iqTd8OmMCVMmeGUM46PYq7B1MGR1fI1QG/EKe4HzFdhSdd0werZYj+t1TRC8+tVSX5POs5SYA==", + "requires": { + "@babel/runtime": "^7.20.13", + "@react-pdf/fns": "2.0.1", + "@react-pdf/image": "^2.2.1", + "@react-pdf/pdfkit": "^3.0.2", + "@react-pdf/primitives": "^3.0.0", + "@react-pdf/stylesheet": "^4.1.5", + "@react-pdf/textkit": "^4.2.0", + "@react-pdf/types": "^2.3.1", + "@react-pdf/yoga": "^4.1.2", + "cross-fetch": "^3.1.5", + "emoji-regex": "^10.2.1", + "queue": "^6.0.1" + }, + "dependencies": { + "emoji-regex": { + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.2.1.tgz", + "integrity": "sha512-97g6QgOk8zlDRdgq1WxwgTMgEWGVAQvB5Fdpgc1MkNy56la5SKP9GsMXKDOdqwn90/41a8yPwIGk1Y6WVbeMQA==" + } + } + }, + "@react-pdf/pdfkit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@react-pdf/pdfkit/-/pdfkit-3.0.2.tgz", + "integrity": "sha512-+m5rwNCwyEH6lmnZWpsQJvdqb6YaCCR0nMWrc/KKDwznuPMrGmGWyNxqCja+bQPORcHZyl6Cd/iFL0glyB3QGw==", + "requires": { + "@babel/runtime": "^7.20.13", + "@react-pdf/png-js": "^2.2.0", + "browserify-zlib": "^0.2.0", + "crypto-js": "^4.0.0", + "fontkit": "^2.0.2", + "vite-compatible-readable-stream": "^3.6.1" + } + }, + "@react-pdf/png-js": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@react-pdf/png-js/-/png-js-2.2.0.tgz", + "integrity": "sha512-csZU5lfNW73tq7s7zB/1rWXGro+Z9cQhxtsXwxS418TSszHUiM6PwddouiKJxdGhbVLjRIcuuFVa0aR5cDOC6w==", + "requires": { + "browserify-zlib": "^0.2.0" + } + }, + "@react-pdf/primitives": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@react-pdf/primitives/-/primitives-3.0.1.tgz", + "integrity": "sha512-0HGcknrLNwyhxe+SZCBL29JY4M85mXKdvTZE9uhjNbADGgTc8wVnkc5+e4S/lDvugbVISXyuIhZnYwtK9eDnyQ==" + }, + "@react-pdf/render": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@react-pdf/render/-/render-3.2.4.tgz", + "integrity": "sha512-lnef097Dx2vHKpY9OHHNmV+nsG5vpd33h76tCzdlbijj+TyVm1j7ZQ5qadGq1uMOFAU6lp0hEo7VoDk7XnjmFw==", + "requires": { + "@babel/runtime": "^7.20.13", + "@react-pdf/fns": "2.0.1", + "@react-pdf/primitives": "^3.0.0", + "@react-pdf/textkit": "^4.2.0", + "@react-pdf/types": "^2.3.1", + "abs-svg-path": "^0.1.1", + "color-string": "^1.5.3", + "normalize-svg-path": "^1.1.0", + "parse-svg-path": "^0.1.2", + "svg-arc-to-cubic-bezier": "^3.2.0" + } + }, + "@react-pdf/renderer": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/@react-pdf/renderer/-/renderer-3.1.9.tgz", + "integrity": "sha512-kfEH7O+Jy7aihbUqrT9Ej1gx8/twRWvFMfHlACr29QsN+s+w0XzWpHCvbjkinVFABYcvsenluiirik6mf4qwRQ==", + "requires": { + "@babel/runtime": "^7.20.13", + "@react-pdf/font": "^2.3.4", + "@react-pdf/layout": "^3.6.0", + "@react-pdf/pdfkit": "^3.0.2", + "@react-pdf/primitives": "^3.0.0", + "@react-pdf/render": "^3.2.4", + "@react-pdf/types": "^2.3.1", + "events": "^3.3.0", + "object-assign": "^4.1.1", + "prop-types": "^15.6.2", + "queue": "^6.0.1", + "scheduler": "^0.17.0" + }, + "dependencies": { + "scheduler": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.17.0.tgz", + "integrity": "sha512-7rro8Io3tnCPuY4la/NuI5F2yfESpnfZyT6TtkXnSWVkcu0BCDJ+8gk5ozUaFaxpIyNuWAPXrH0yFcSi28fnDA==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + } + } + }, + "@react-pdf/stylesheet": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@react-pdf/stylesheet/-/stylesheet-4.1.5.tgz", + "integrity": "sha512-8sP+4KD3cAfBEsZBQeJC7GUC0vkCLiAc6kZaGX0dXaBR3nZO2TaCD8+ZuezokZi+ARp/yvWJqR2vIX8ra7X1xA==", + "requires": { + "@babel/runtime": "^7.20.13", + "@react-pdf/fns": "2.0.1", + "@react-pdf/types": "^2.3.1", + "color-string": "^1.5.3", + "hsl-to-hex": "^1.0.0", + "media-engine": "^1.0.3", + "postcss-value-parser": "^4.1.0" + } + }, + "@react-pdf/textkit": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@react-pdf/textkit/-/textkit-4.2.0.tgz", + "integrity": "sha512-R90pEOW6NdhUx4p99iROvKmwB06IRYdXMhh0QcmUeoPOLe64ZdMfs3LZliNUWgI5fCmq71J+nv868i/EakFPDg==", + "requires": { + "@babel/runtime": "^7.20.13", + "@react-pdf/fns": "2.0.1", + "hyphen": "^1.6.4", + "unicode-properties": "^1.4.1" + } + }, + "@react-pdf/types": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@react-pdf/types/-/types-2.3.1.tgz", + "integrity": "sha512-FiwAsNp2oQ2W39xAU1PCjY6YNjEuypQykEA6VMz4WZ4ERvyOBB4M5B8063lA8YYBcjYB8xQOa9og4UH1eqMbgg==" + }, + "@react-pdf/yoga": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@react-pdf/yoga/-/yoga-4.1.2.tgz", + "integrity": "sha512-OlMZkFrJDj4GyKZ70thiObwwPVZ52B7mlPyfzwa+sgwsioqHXg9nMWOO+7SQFNUbbOGagMUu0bCuTv+iXYZuaQ==", + "requires": { + "@babel/runtime": "^7.20.13" + } + }, "@rollup/plugin-babel": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", @@ -21198,6 +21766,14 @@ "loader-utils": "^2.0.0" } }, + "@swc/helpers": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.4.14.tgz", + "integrity": "sha512-4C7nX/dvpzB7za4Ql9K81xK3HPxCpHMgwTZVyf+9JQ6VUbn9jjZVN7/Nkdz/Ugzs2CSjqnL/UPXroiVBVHUWUw==", + "requires": { + "tslib": "^2.4.0" + } + }, "@testing-library/dom": { "version": "8.10.1", "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-8.10.1.tgz", @@ -21318,7 +21894,8 @@ "version": "14.2.0", "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.2.0.tgz", "integrity": "sha512-+hIlG4nJS6ivZrKnOP7OGsDu9Fxmryj9vCl8x0ZINtTJcCHs2zLsYif5GzuRiBF2ck5GZG2aQr7Msg+EHlnYVQ==", - "dev": true + "dev": true, + "requires": {} }, "@tootallnate/once": { "version": "1.1.2", @@ -22011,6 +22588,11 @@ "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", "dev": true }, + "abs-svg-path": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/abs-svg-path/-/abs-svg-path-0.1.1.tgz", + "integrity": "sha512-d8XPSGjfyzlXC3Xx891DJRyZfqk5JU0BJrDQcsWomFIV1/BIzPW5HDH5iDdWpqWaav0YVIEzT1RHTwWr0FFshA==" + }, "accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -22049,13 +22631,15 @@ "version": "1.8.0", "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", - "dev": true + "dev": true, + "requires": {} }, "acorn-jsx": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true + "dev": true, + "requires": {} }, "acorn-node": { "version": "1.8.2", @@ -22162,7 +22746,8 @@ "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true + "dev": true, + "requires": {} }, "ansi-escapes": { "version": "4.3.2", @@ -22508,7 +23093,8 @@ "version": "0.3.8", "resolved": "https://registry.npmjs.org/babel-plugin-named-asset-import/-/babel-plugin-named-asset-import-0.3.8.tgz", "integrity": "sha512-WXiAc++qo7XcJ1ZnTYGtLxmBCVbddAml3CEXgWaBzNzLNoxtQ8AiGEFDMOhot9XjTCQbvP5E77Fj9Gk924f00Q==", - "dev": true + "dev": true, + "requires": {} }, "babel-plugin-polyfill-corejs2": { "version": "0.3.1", @@ -22632,6 +23218,11 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" + }, "batch": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", @@ -22757,17 +23348,32 @@ "fill-range": "^7.0.1" } }, + "brotli": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/brotli/-/brotli-1.3.3.tgz", + "integrity": "sha512-oTKjJdShmDuGW94SyyaoQvAjf30dZaHnjJ8uAF+u2/vGJkJbJPJAT1gDiOJP5v1Zb6f9KEyW/1HpuaWIXtGHPg==", + "requires": { + "base64-js": "^1.1.2" + } + }, "browser-process-hrtime": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==", "dev": true }, + "browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "requires": { + "pako": "~1.0.5" + } + }, "browserslist": { "version": "4.20.3", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.3.tgz", "integrity": "sha512-NBhymBQl1zM0Y5dQT/O+xiLP9/rzOIQdKM/eMJBAq7yBgaB6krIYLGejrwVYnSHZdqjscB1SPuAjHwxjvN6Wdg==", - "dev": true, "requires": { "caniuse-lite": "^1.0.30001332", "electron-to-chromium": "^1.4.118", @@ -22855,8 +23461,7 @@ "caniuse-lite": { "version": "1.0.30001340", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001340.tgz", - "integrity": "sha512-jUNz+a9blQTQVu4uFcn17uAD8IDizPzQkIKh3LCJfg9BkyIqExYYdyc/ZSlWUSKb8iYiXxKsxbv4zYSvkqjrxw==", - "dev": true + "integrity": "sha512-jUNz+a9blQTQVu4uFcn17uAD8IDizPzQkIKh3LCJfg9BkyIqExYYdyc/ZSlWUSKb8iYiXxKsxbv4zYSvkqjrxw==" }, "case-sensitive-paths-webpack-plugin": { "version": "2.4.0", @@ -23007,6 +23612,11 @@ "wrap-ansi": "^7.0.0" } }, + "clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==" + }, "clsx": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.1.1.tgz", @@ -23047,8 +23657,16 @@ "color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "requires": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } }, "colord": { "version": "2.9.2", @@ -23253,6 +23871,14 @@ "object-assign": "^4.1.1" } }, + "cross-fetch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz", + "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==", + "requires": { + "node-fetch": "2.6.7" + } + }, "cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -23264,6 +23890,11 @@ "which": "^2.0.1" } }, + "crypto-js": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.1.1.tgz", + "integrity": "sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw==" + }, "crypto-random-string": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", @@ -23302,7 +23933,8 @@ "version": "6.2.2", "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.2.2.tgz", "integrity": "sha512-Ufadglr88ZLsrvS11gjeu/40Lw74D9Am/Jpr3LlYm5Q4ZP5KdlUhG+6u2EjyXeZcxmZ2h1ebCKngDjolpeLHpg==", - "dev": true + "dev": true, + "requires": {} }, "css-has-pseudo": { "version": "3.0.4", @@ -23415,7 +24047,8 @@ "version": "6.0.3", "resolved": "https://registry.npmjs.org/css-prefers-color-scheme/-/css-prefers-color-scheme-6.0.3.tgz", "integrity": "sha512-4BqMbZksRkJQx2zAjrokiGMd07RqOa2IxIrrN10lyBe9xhn9DEvjUK79J6jkeiv9D9hQFXKb6g1jwU62jziJZA==", - "dev": true + "dev": true, + "requires": {} }, "css-select": { "version": "4.3.0", @@ -23539,7 +24172,8 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-3.1.0.tgz", "integrity": "sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==", - "dev": true + "dev": true, + "requires": {} }, "csso": { "version": "4.2.0", @@ -23623,7 +24257,6 @@ "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, "requires": { "ms": "2.1.2" } @@ -23756,6 +24389,11 @@ "minimist": "^1.1.1" } }, + "dfa": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/dfa/-/dfa-1.2.0.tgz", + "integrity": "sha512-ED3jP8saaweFTjeGX8HQPjeC1YYyZs98jGNZx6IiBvxW7JG5v492kamAQB3m2wop07CvU/RQmzcKr6bgcC5D/Q==" + }, "didyoumean": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", @@ -23937,8 +24575,7 @@ "electron-to-chromium": { "version": "1.4.137", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.137.tgz", - "integrity": "sha512-0Rcpald12O11BUogJagX3HsCN3FE83DSqWjgXoHo5a72KUKMSfI39XBgJpgNNxS9fuGzytaFjE06kZkiVFy2qA==", - "dev": true + "integrity": "sha512-0Rcpald12O11BUogJagX3HsCN3FE83DSqWjgXoHo5a72KUKMSfI39XBgJpgNNxS9fuGzytaFjE06kZkiVFy2qA==" }, "emittery": { "version": "0.8.1", @@ -24057,8 +24694,7 @@ "escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" }, "escape-html": { "version": "1.0.3", @@ -24276,7 +24912,8 @@ "version": "8.5.0", "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz", "integrity": "sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==", - "dev": true + "dev": true, + "requires": {} }, "eslint-config-react-app": { "version": "7.0.1", @@ -24556,7 +25193,8 @@ "version": "4.5.0", "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.5.0.tgz", "integrity": "sha512-8k1gRt7D7h03kd+SAAlzXkQwWK22BnK6GKZG+FJA6BAGy22CFvl8kCIXKpVux0cCxMWDQUPqSok0LKaZ0aOcCw==", - "dev": true + "dev": true, + "requires": {} }, "eslint-plugin-testing-library": { "version": "5.5.0", @@ -24689,8 +25327,7 @@ "events": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==" }, "execa": { "version": "5.1.1", @@ -24803,8 +25440,7 @@ "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "fast-diff": { "version": "1.2.0", @@ -25006,6 +25642,22 @@ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.0.tgz", "integrity": "sha512-aExlJShTV4qOUOL7yF1U5tvLCB0xQuudbf6toyYA0E/acBNw71mvjFTnLaRp50aQaYocMR0a/RMMBIHeZnGyjQ==" }, + "fontkit": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fontkit/-/fontkit-2.0.2.tgz", + "integrity": "sha512-jc4k5Yr8iov8QfS6u8w2CnHWVmbOGtdBtOXMze5Y+QD966Rx6PEVWXSEGwXlsDlKtu1G12cJjcsybnqhSk/+LA==", + "requires": { + "@swc/helpers": "^0.4.2", + "brotli": "^1.3.2", + "clone": "^2.1.2", + "dfa": "^1.2.0", + "fast-deep-equal": "^3.1.3", + "restructure": "^3.0.0", + "tiny-inflate": "^1.0.3", + "unicode-properties": "^1.4.0", + "unicode-trie": "^2.0.0" + } + }, "fork-ts-checker-webpack-plugin": { "version": "6.5.2", "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.2.tgz", @@ -25218,8 +25870,7 @@ "gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==" }, "get-caller-file": { "version": "2.0.5", @@ -25329,8 +25980,7 @@ "globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" }, "globby": { "version": "11.0.4", @@ -25494,6 +26144,19 @@ } } }, + "hsl-to-hex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hsl-to-hex/-/hsl-to-hex-1.0.0.tgz", + "integrity": "sha512-K6GVpucS5wFf44X0h2bLVRDsycgJmf9FF2elg+CrqD8GcFU8c6vYhgXn8NjUkFCwj+xDFb70qgLbTUm6sxwPmA==", + "requires": { + "hsl-to-rgb-for-reals": "^1.1.0" + } + }, + "hsl-to-rgb-for-reals": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/hsl-to-rgb-for-reals/-/hsl-to-rgb-for-reals-1.1.1.tgz", + "integrity": "sha512-LgOWAkrN0rFaQpfdWBQlv/VhkOxb5AsBjk6NQVx4yEzWS923T07X0M1Y0VNko2H52HeSpZrZNNMJ0aFqsdVzQg==" + }, "html-encoding-sniffer": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz", @@ -25631,6 +26294,11 @@ "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", "dev": true }, + "hyphen": { + "version": "1.6.5", + "resolved": "https://registry.npmjs.org/hyphen/-/hyphen-1.6.5.tgz", + "integrity": "sha512-MZbhHutRaHCUxjvJBYqL51Ntjbq16LemuJr2u+LpKd3UwyNHZsZAKh5uD+KmdAHtWpteupOqQTTezVGR/al43w==" + }, "hyphenate-style-name": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz", @@ -25649,7 +26317,8 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", - "dev": true + "dev": true, + "requires": {} }, "idb": { "version": "6.1.5", @@ -25735,8 +26404,7 @@ "inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "ini": { "version": "1.3.8", @@ -25969,6 +26637,11 @@ "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", "dev": true }, + "is-url": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", + "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==" + }, "is-weakref": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", @@ -26680,7 +27353,8 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz", "integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==", - "dev": true + "dev": true, + "requires": {} }, "jest-regex-util": { "version": "27.5.1", @@ -27464,8 +28138,7 @@ "jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==" }, "json-parse-even-better-errors": { "version": "2.3.1", @@ -27499,8 +28172,7 @@ "json5": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", - "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", - "dev": true + "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==" }, "jsonfile": { "version": "6.1.0", @@ -27996,6 +28668,11 @@ "integrity": "sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==", "dev": true }, + "media-engine": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/media-engine/-/media-engine-1.0.3.tgz", + "integrity": "sha512-aa5tG6sDoK+k70B9iEX1NeyfT8ObCKhNDs6lJVpwF6r8vhUfuKMslIcirq6HIUYuuUYLefcEQOn9bSBOvawtwg==" + }, "media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -28169,8 +28846,7 @@ "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "multicast-dns": { "version": "7.2.4", @@ -28233,6 +28909,35 @@ "propagate": "^2.0.0" } }, + "node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "requires": { + "whatwg-url": "^5.0.0" + }, + "dependencies": { + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + } + } + }, "node-forge": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", @@ -28248,8 +28953,7 @@ "node-releases": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.4.tgz", - "integrity": "sha512-gbMzqQtTtDz/00jQzZ21PQzdI9PyLYqUSvD0p3naOhX4odFji0ZxYdnVwPTxmSwkmxhcFImpozceidSG+AgoPQ==", - "dev": true + "integrity": "sha512-gbMzqQtTtDz/00jQzZ21PQzdI9PyLYqUSvD0p3naOhX4odFji0ZxYdnVwPTxmSwkmxhcFImpozceidSG+AgoPQ==" }, "normalize-path": { "version": "3.0.0", @@ -28263,6 +28967,14 @@ "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", "dev": true }, + "normalize-svg-path": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/normalize-svg-path/-/normalize-svg-path-1.1.0.tgz", + "integrity": "sha512-r9KHKG2UUeB5LoTouwDzBy2VxXlHsiM6fyLQvnJa0S5hrhzqElH/CH7TUGhT1fVvIYBIKf3OpY4YJ4CK+iaqHg==", + "requires": { + "svg-arc-to-cubic-bezier": "^3.0.0" + } + }, "normalize-url": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", @@ -28489,6 +29201,11 @@ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true }, + "pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" + }, "param-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", @@ -28518,6 +29235,11 @@ "lines-and-columns": "^1.1.6" } }, + "parse-svg-path": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/parse-svg-path/-/parse-svg-path-0.1.2.tgz", + "integrity": "sha512-JyPSBnkTJ0AI8GGJLfMXvKq42cj5c006fnLz6fXy6zfoVjJizi8BNTpu8on8ziI1cKy9d9DGNuY17Ce7wuejpQ==" + }, "parse5": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", @@ -28583,8 +29305,7 @@ "picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" }, "picomatch": { "version": "2.3.0", @@ -28730,7 +29451,8 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/postcss-browser-comments/-/postcss-browser-comments-4.0.0.tgz", "integrity": "sha512-X9X9/WN3KIvY9+hNERUqX9gncsgBA25XaeR+jshHz2j8+sYyHktHw1JdKuMjeLpGktXidqDhA7b/qm1mrBDmgg==", - "dev": true + "dev": true, + "requires": {} }, "postcss-calc": { "version": "8.2.4", @@ -28803,7 +29525,8 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/postcss-custom-media/-/postcss-custom-media-8.0.0.tgz", "integrity": "sha512-FvO2GzMUaTN0t1fBULDeIvxr5IvbDXcIatt6pnJghc736nqNgsGao5NT+5+WVLAQiTt6Cb3YUms0jiPaXhL//g==", - "dev": true + "dev": true, + "requires": {} }, "postcss-custom-properties": { "version": "12.1.7", @@ -28836,25 +29559,29 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.1.1.tgz", "integrity": "sha512-5JscyFmvkUxz/5/+TB3QTTT9Gi9jHkcn8dcmmuN68JQcv3aQg4y88yEHHhwFB52l/NkaJ43O0dbksGMAo49nfQ==", - "dev": true + "dev": true, + "requires": {} }, "postcss-discard-duplicates": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz", "integrity": "sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==", - "dev": true + "dev": true, + "requires": {} }, "postcss-discard-empty": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.1.1.tgz", "integrity": "sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==", - "dev": true + "dev": true, + "requires": {} }, "postcss-discard-overridden": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz", "integrity": "sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==", - "dev": true + "dev": true, + "requires": {} }, "postcss-double-position-gradients": { "version": "3.1.1", @@ -28879,7 +29606,8 @@ "version": "5.0.2", "resolved": "https://registry.npmjs.org/postcss-flexbugs-fixes/-/postcss-flexbugs-fixes-5.0.2.tgz", "integrity": "sha512-18f9voByak7bTktR2QgDveglpn9DTbBWPUzSOe9g0N4WR/2eSt6Vrcbf0hmspvMI6YWGywz6B9f7jzpFNJJgnQ==", - "dev": true + "dev": true, + "requires": {} }, "postcss-focus-visible": { "version": "6.0.4", @@ -28903,13 +29631,15 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/postcss-font-variant/-/postcss-font-variant-5.0.0.tgz", "integrity": "sha512-1fmkBaCALD72CK2a9i468mA/+tr9/1cBxRRMXOUaZqO43oWPR5imcyPjXwuv7PXbCid4ndlP5zWhidQVVa3hmA==", - "dev": true + "dev": true, + "requires": {} }, "postcss-gap-properties": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/postcss-gap-properties/-/postcss-gap-properties-3.0.3.tgz", "integrity": "sha512-rPPZRLPmEKgLk/KlXMqRaNkYTUpE7YC+bOIQFN5xcu1Vp11Y4faIXv6/Jpft6FMnl6YRxZqDZG0qQOW80stzxQ==", - "dev": true + "dev": true, + "requires": {} }, "postcss-image-set-function": { "version": "4.0.6", @@ -28924,7 +29654,8 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/postcss-initial/-/postcss-initial-4.0.1.tgz", "integrity": "sha512-0ueD7rPqX8Pn1xJIjay0AZeIuDoF+V+VvMt/uOnn+4ezUKhZM/NokDeP6DwMNyIoYByuN/94IQnt5FEkaN59xQ==", - "dev": true + "dev": true, + "requires": {} }, "postcss-js": { "version": "4.0.0", @@ -29002,13 +29733,15 @@ "version": "5.0.4", "resolved": "https://registry.npmjs.org/postcss-logical/-/postcss-logical-5.0.4.tgz", "integrity": "sha512-RHXxplCeLh9VjinvMrZONq7im4wjWGlRJAqmAVLXyZaXwfDWP73/oq4NdIp+OZwhQUMj0zjqDfM5Fj7qby+B4g==", - "dev": true + "dev": true, + "requires": {} }, "postcss-media-minmax": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/postcss-media-minmax/-/postcss-media-minmax-5.0.0.tgz", "integrity": "sha512-yDUvFf9QdFZTuCUg0g0uNSHVlJ5X1lSzDZjPSFaiCWvjgsvu8vEVxtahPrLMinIDEEGnx6cBe6iqdx5YWz08wQ==", - "dev": true + "dev": true, + "requires": {} }, "postcss-merge-longhand": { "version": "5.1.4", @@ -29076,7 +29809,8 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", - "dev": true + "dev": true, + "requires": {} }, "postcss-modules-local-by-default": { "version": "4.0.0", @@ -29141,7 +29875,8 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz", "integrity": "sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==", - "dev": true + "dev": true, + "requires": {} }, "postcss-normalize-display-values": { "version": "5.1.0", @@ -29237,13 +29972,15 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/postcss-overflow-shorthand/-/postcss-overflow-shorthand-3.0.3.tgz", "integrity": "sha512-CxZwoWup9KXzQeeIxtgOciQ00tDtnylYIlJBBODqkgS/PU2jISuWOL/mYLHmZb9ZhZiCaNKsCRiLp22dZUtNsg==", - "dev": true + "dev": true, + "requires": {} }, "postcss-page-break": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/postcss-page-break/-/postcss-page-break-3.0.4.tgz", "integrity": "sha512-1JGu8oCjVXLa9q9rFTo4MbeeA5FMe00/9C7lN4va606Rdb+HkxXtXsmEDrIraQ11fGz/WvKWa8gMuCKkrXpTsQ==", - "dev": true + "dev": true, + "requires": {} }, "postcss-place": { "version": "7.0.4", @@ -29339,7 +30076,8 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-4.0.0.tgz", "integrity": "sha512-KmF7SBPphT4gPPcKZc7aDkweHiKEEO8cla/GjcBK+ckKxiZslIu3C4GCRW3DNfL0o7yW7kMQu9xlZ1kXRXLXtw==", - "dev": true + "dev": true, + "requires": {} }, "postcss-selector-not": { "version": "5.0.0", @@ -29427,8 +30165,7 @@ "postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "prelude-ls": { "version": "1.2.1", @@ -29584,6 +30321,14 @@ "side-channel": "^1.0.4" } }, + "queue": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz", + "integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==", + "requires": { + "inherits": "~2.0.3" + } + }, "queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -30036,6 +30781,14 @@ } } }, + "react-to-print": { + "version": "2.14.12", + "resolved": "https://registry.npmjs.org/react-to-print/-/react-to-print-2.14.12.tgz", + "integrity": "sha512-qFJAwvDFd95Z+FWNqitt+HaB1/z+Zdd0MMrNOPUSus3fG32vqv512yB+HXhQ94J3HKoyqaIg44v0Zfc6xUBqlg==", + "requires": { + "prop-types": "^15.8.1" + } + }, "react-tooltip": { "version": "4.2.21", "resolved": "https://registry.npmjs.org/react-tooltip/-/react-tooltip-4.2.21.tgz", @@ -30129,9 +30882,9 @@ } }, "regenerator-runtime": { - "version": "0.13.9", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", - "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" }, "regenerator-transform": { "version": "0.15.0", @@ -30331,6 +31084,11 @@ "signal-exit": "^3.0.2" } }, + "restructure": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/restructure/-/restructure-3.0.0.tgz", + "integrity": "sha512-Xj8/MEIhhfj9X2rmD9iJ4Gga9EFqVlpMj3vfLnV2r/Mh5jRMryNV+6lWh9GdJtDBcBSPIqzRdfBQ3wDtNFv/uw==" + }, "retry": { "version": "0.13.1", "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", @@ -30524,8 +31282,7 @@ "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" }, "send": { "version": "0.18.0", @@ -30711,6 +31468,21 @@ "integrity": "sha512-KWcOiKeQj6ZyXx7zq4YxSMgHRlod4czeBQZrPb8OKcohcqAXShm7E20kEMle9WBt26hFcAf0qLOcp5zmY7kOqQ==", "dev": true }, + "simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", + "requires": { + "is-arrayish": "^0.3.1" + }, + "dependencies": { + "is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" + } + } + }, "sisteransi": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", @@ -30897,7 +31669,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, "requires": { "safe-buffer": "~5.2.0" }, @@ -30905,8 +31676,7 @@ "safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" } } }, @@ -31046,7 +31816,8 @@ "version": "3.3.1", "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.1.tgz", "integrity": "sha512-GPcQ+LDJbrcxHORTRes6Jy2sfvK2kS6hpSfI/fXhPt+spVzxF6LJ1dHLN9zIGmVaaP044YKaIatFaufENRiDoQ==", - "dev": true + "dev": true, + "requires": {} }, "stylehacks": { "version": "5.1.0", @@ -31103,6 +31874,11 @@ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" }, + "svg-arc-to-cubic-bezier": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/svg-arc-to-cubic-bezier/-/svg-arc-to-cubic-bezier-3.2.0.tgz", + "integrity": "sha512-djbJ/vZKZO+gPoSDThGNpKDO+o+bAeA4XQKovvkNCqnIS2t+S4qnLAGQhyyrulhCFRl1WWzAp0wUDV8PpTVU3g==" + }, "svg-parser": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", @@ -31266,6 +32042,14 @@ "temp-dir": "^2.0.0", "type-fest": "^0.16.0", "unique-string": "^2.0.0" + }, + "dependencies": { + "type-fest": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.16.0.tgz", + "integrity": "sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==", + "dev": true + } } }, "terminal-link": { @@ -31400,6 +32184,11 @@ "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", "dev": true }, + "tiny-inflate": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz", + "integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==" + }, "tiny-invariant": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.1.0.tgz", @@ -31505,10 +32294,9 @@ } }, "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", - "dev": true + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "tsutils": { "version": "3.21.0", @@ -31543,10 +32331,12 @@ "dev": true }, "type-fest": { - "version": "0.16.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.16.0.tgz", - "integrity": "sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==", - "dev": true + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "dev": true, + "optional": true, + "peer": true }, "type-is": { "version": "1.6.18", @@ -31567,6 +32357,13 @@ "is-typedarray": "^1.0.0" } }, + "typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "dev": true, + "peer": true + }, "unbox-primitive": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", @@ -31601,12 +32398,37 @@ "integrity": "sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw==", "dev": true }, + "unicode-properties": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/unicode-properties/-/unicode-properties-1.4.1.tgz", + "integrity": "sha512-CLjCCLQ6UuMxWnbIylkisbRj31qxHPAurvena/0iwSVbQ2G1VY5/HjV0IRabOEbDHlzZlRdCrD4NhB0JtU40Pg==", + "requires": { + "base64-js": "^1.3.0", + "unicode-trie": "^2.0.0" + } + }, "unicode-property-aliases-ecmascript": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz", "integrity": "sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ==", "dev": true }, + "unicode-trie": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-trie/-/unicode-trie-2.0.0.tgz", + "integrity": "sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ==", + "requires": { + "pako": "^0.2.5", + "tiny-inflate": "^1.0.0" + }, + "dependencies": { + "pako": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", + "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==" + } + } + }, "unique-string": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", @@ -31652,8 +32474,7 @@ "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, "util.promisify": { "version": "1.0.0", @@ -31719,6 +32540,16 @@ "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", "dev": true }, + "vite-compatible-readable-stream": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/vite-compatible-readable-stream/-/vite-compatible-readable-stream-3.6.1.tgz", + "integrity": "sha512-t20zYkrSf868+j/p31cRIGN28Phrjm3nRSLR2fyc2tiWi4cZGVdv68yNlwnIINTkMTmPoMiSlc0OadaO7DXZaQ==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, "w3c-hr-time": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", @@ -31944,7 +32775,8 @@ "version": "8.6.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.6.0.tgz", "integrity": "sha512-AzmM3aH3gk0aX7/rZLYvjdvZooofDu3fFOzGqcSnQ1tOcTWwhM/o+q++E8mAyVVIyUdajrkzWUGftaVSDLn1bw==", - "dev": true + "dev": true, + "requires": {} } } }, @@ -32411,7 +33243,8 @@ "version": "7.5.7", "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.7.tgz", "integrity": "sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A==", - "dev": true + "dev": true, + "requires": {} }, "xml-name-validator": { "version": "3.0.0", diff --git a/client/package.json b/client/package.json index 0e08d123..9c9c48e4 100644 --- a/client/package.json +++ b/client/package.json @@ -34,6 +34,7 @@ "@fortawesome/react-fontawesome": "^0.1.18", "@microsoft/applicationinsights-react-js": "^3.0.5", "@microsoft/applicationinsights-web": "^2.5.11", + "@react-pdf/renderer": "^3.1.9", "axios": "^0.27.2", "clsx": "^1.1.1", "formik": "^2.2.9", @@ -48,6 +49,7 @@ "react-router-dom": "^5.3.0", "react-select": "^5.2.2", "react-string-replace": "^1.1.0", + "react-to-print": "^2.14.12", "react-tooltip": "^4.2.21", "yup": "^0.32.11" }, diff --git a/client/src/components/Button/Button.js b/client/src/components/Button/Button.js index 14c9a54a..eb2d7eda 100644 --- a/client/src/components/Button/Button.js +++ b/client/src/components/Button/Button.js @@ -21,6 +21,12 @@ const useStyles = createUseStyles({ borderColor: "rgba(0, 0, 0, .05)", //lightest grey boxShadow: "rgba(0, 46, 109, 0.3) 1px 2px 3px" }, + download: { + backgroundColor: ({ theme, color }) => theme[color], + borderColor: "rgb(167, 197, 57)", //site standard green + boxShadow: "rgb(167, 197, 57) 1px 2px 3px", + marginLeft: "auto" + }, outlined: { backgroundColor: ({ theme }) => theme.colorWhite, borderColor: "rgba(0, 46, 109, .2)", //medium grey diff --git a/client/src/components/Button/DownloadButton 2.js b/client/src/components/Button/DownloadButton 2.js new file mode 100644 index 00000000..3c6016b0 --- /dev/null +++ b/client/src/components/Button/DownloadButton 2.js @@ -0,0 +1,32 @@ +import React from "react"; +import PropTypes from "prop-types"; +import Button from "../Button/Button"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { faFileDownload } from "@fortawesome/free-solid-svg-icons"; + +const DownloadButton = ({ id, onClick, isDisplayed }) => { + return ( + + ); +}; + +DownloadButton.propTypes = { + children: PropTypes.object, + onClick: PropTypes.func, + ref: PropTypes.string, + id: PropTypes.string.isRequired, + isDisplayed: PropTypes.bool.isRequired +}; + +export default DownloadButton; diff --git a/client/src/components/Button/DownloadButton.js b/client/src/components/Button/DownloadButton.js new file mode 100644 index 00000000..99df6192 --- /dev/null +++ b/client/src/components/Button/DownloadButton.js @@ -0,0 +1,33 @@ +import React from "react"; +import PropTypes from "prop-types"; +import Button from "../Button/Button"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { faFileDownload } from "@fortawesome/free-solid-svg-icons"; + +const DownloadButton = ({ id, onClick, isDisabled, isDisplayed }) => { + return ( + + ); +}; + +DownloadButton.propTypes = { + children: PropTypes.object, + onClick: PropTypes.func, + id: PropTypes.string.isRequired, + isDisabled: PropTypes.bool, + isDisplayed: PropTypes.bool.isRequired +}; + +export default DownloadButton; diff --git a/client/src/components/PDF/PDF.js b/client/src/components/PDF/PDF.js new file mode 100644 index 00000000..3c02833a --- /dev/null +++ b/client/src/components/PDF/PDF.js @@ -0,0 +1,291 @@ +import React, { forwardRef } from "react"; +import PropTypes from "prop-types"; +import { createUseStyles } from "react-jss"; +import clsx from "clsx"; +import { + numberWithCommas, + getRule, + roundToTwo +} from "../ProjectWizard/helpers"; +import ProjectDetail from "../ProjectWizard/WizardPages/ProjectSummary/ProjectDetail"; +import MeasureSelected from "../ProjectWizard/WizardPages/ProjectSummary/MeasureSelected"; +import LandUses from "../ProjectWizard/WizardPages/ProjectSummary/LandUses"; +import ProjectInfo from "../ProjectWizard/WizardPages/ProjectSummary/ProjectInfo"; +import ProjectInfoList from "../ProjectWizard/WizardPages/ProjectSummary/ProjectInfoList"; +import PdfResult from "./PdfResult"; +import PdfFooter from "./PdfFooter"; +import logo from "../../images/ladot.png"; + +const useStyles = createUseStyles({ + Pdf: { + display: "flex", + flexDirection: "column", + flex: "1 1 auto", + minWidth: "85vw", + margin: "50px auto" + }, + rule: { + display: "flex", + alignItems: "center", + justifyContent: "space-between", + minHeight: "24px", + margin: "4px auto" + }, + ruleName: { + minWidth: "270px" + }, + categoryContainer: { + marginTop: "25px" + }, + categoryHeaderContainer: { + background: "#E7EBF0", + padding: "12px" + }, + categoryHeader: { + fontSize: "16px", + fontFamily: "Oswald", + fontWeight: "700" + }, + pdfResultsContainer: { + display: "block", + padding: "10px 0", + maxWidth: "100%" + }, + measuresContainer: { + paddingTop: "10px", + margin: "0 12px" + }, + earnedPoints: { + fontFamily: "Oswald", + fontWeight: "500", + fontSize: "12px", + color: "#0F2940", + paddingTop: "5px", + marginRight: "31px" + }, + summaryContainer: { + display: "flex", + minWidth: "180px", + maxWidth: "100%", + marginTop: "4px", + padding: "12px" + }, + logo: { + height: "1.5em", + width: "15%", + padding: "0", + backgroundColor: "#FFFFFF", + marginBottom: "-0.25em" + //backgroundColor: "rgb(0,47,113)" + }, + projectInfoDetailsContainer: { + paddingTop: "20px", + paddingLeft: "12px", + display: "flex", + flexDirection: "row", + flexWrap: "wrap", + maxWidth: "100%", + minHeight: "55px", + rowGap: "1.1rem" + }, + textProjectInfoHeaderAddress: { + color: "rgba(15, 41, 64, .5)", + fontSize: "16px", + fontFamily: "Calibri Bold" + }, + "@media (max-width: 768px)": { + logoContainer: { + justifySelf: "start" + } + } +}); + +// eslint-disable-next-line react/display-name +export const Pdf = forwardRef((props, ref) => { + const classes = useStyles(); + const { rules, dateModified } = props; + + const level = getRule(rules, "PROJECT_LEVEL"); + const targetPoints = getRule(rules, "TARGET_POINTS_PARK"); + const earnedPoints = getRule(rules, "PTS_EARNED"); + const userDefinedStrategy = getRule(rules, "STRATEGY_APPLICANT"); + const parkingProvided = getRule(rules, "PARK_SPACES"); + const projectDescription = getRule(rules, "PROJECT_DESCRIPTION"); + const parkingRatio = getRule(rules, "CALC_PARK_RATIO"); + const parkingRequired = getRule(rules, "PARK_REQUIREMENT"); + const projectName = getRule(rules, "PROJECT_NAME"); + const projectAddress = getRule(rules, "PROJECT_ADDRESS"); + const buildingPermit = getRule(rules, "BUILDING_PERMIT"); + const caseNumberLADOT = getRule(rules, "CASE_NO_LADOT"); + const caseNumberPlanning = getRule(rules, "CASE_NO_PLANNING"); + const parcelNumbers = getRule(rules, "APN"); + const versionNumber = getRule(rules, "VERSION_NO"); + + const measureRules = + rules && + rules.filter( + rule => + rule.category === "measure" && + rule.used && + rule.display && + rule.calculationPanelId !== 10 && + (!!(rule.value && rule.value !== "0") || + !!(rule.calcValue && rule.calcValue !== "0")) + ); + + const rulesNotEmpty = rules && rules.length > 0; + + const specificationRules = + rules && + rules.filter( + rule => + rule.category === "input" && + rule.used && + rule.display && + rule.calculationPanelId !== 31 && + (!!(rule.value && rule.value !== "0") || + !!(rule.calcValue && rule.calcValue !== "0")) + ); + + return ( +
    +

    + LA Department of Transportation Logo + {""} | TDM Calculation Project Summary +

    +
    +
    + PROJECT NAME + {projectName && projectName.value ? ( + + {projectName.value} + + ) : null} +
    +
    + {projectAddress && ( + + )} + + {buildingPermit && ( + + )} + {versionNumber && ( + + )} + {caseNumberPlanning && ( + + )} + {caseNumberLADOT && ( + + )} +
    +
    +
    +
    + PROJECT DETAILS +
    +
    + +
    + + {rulesNotEmpty + ? specificationRules.map(rule => { + return ( + + ); + }) + : null} + + + + {projectDescription && + projectDescription.value && + projectDescription.value.length > 0 ? ( +
    +
    +
    {projectDescription.name}:
    +
    +
    + {projectDescription.value} +
    +
    + ) : null} +
    +
    +
    + + TDM STRATEGIES SELECTED + + EARNED POINTS +
    +
    + {rulesNotEmpty + ? measureRules.map(rule => ( + + )) + : null} + {userDefinedStrategy.calcValue && + userDefinedStrategy.comment.length > 0 ? ( +
    +
    +
    + User-Defined Strategy Details: +
    +
    +
    + {userDefinedStrategy.comment} +
    +
    + ) : null} +
    +
    +
    +
    + RESULTS +
    +
    + + +
    +
    + +
    + ); +}); +Pdf.propTypes = { + rules: PropTypes.array, + account: PropTypes.object, + projectId: PropTypes.number, + loginId: PropTypes.number, + dateModified: PropTypes.string || null +}; diff --git a/client/src/components/PDF/PdfFooter.js b/client/src/components/PDF/PdfFooter.js new file mode 100644 index 00000000..2477828d --- /dev/null +++ b/client/src/components/PDF/PdfFooter.js @@ -0,0 +1,63 @@ +import React, { useState, useEffect } from "react"; +import PropTypes from "prop-types"; +import { createUseStyles } from "react-jss"; + +const useStyles = createUseStyles({ + pdfTimeText: { + fontSize: "14px", + color: "rgb(53,119,163)" + }, + pdfFooterContainer: { + margin: "24px 0 0" + } +}); + +const PdfFooter = props => { + const classes = useStyles(); + const { dateModified } = props; + const [printedDate, setPrintedDate] = useState(new Date()); + + useEffect(() => { + // You would update these dates based on your application logic + // For instance, you might fetch them from an API when the component mounts + const updateDates = () => { + setPrintedDate(new Date()); // replace with actual date + }; + + updateDates(); + const intervalId = setInterval(updateDates, 60 * 1000); // updates every minute + + return () => clearInterval(intervalId); // cleanup on unmount + }, []); + + return ( +
    +
    + Date Last Saved: {dateModified} Pacific Time +
    +
    + Date Printed:{" "} + {printedDate.toLocaleString("en-US", { + timeZone: "America/Los_Angeles" + })}{" "} + Pacific Time +
    + + Los Angeles Department of Transportation | tdm.ladot.lacity.org | + LADOT.TDM@lacity.org + +
    + ); +}; +PdfFooter.propTypes = { + dateModified: PropTypes.string || null +}; + +export default PdfFooter; diff --git a/client/src/components/PDF/PdfResult.js b/client/src/components/PDF/PdfResult.js new file mode 100644 index 00000000..e57cd4f5 --- /dev/null +++ b/client/src/components/PDF/PdfResult.js @@ -0,0 +1,20 @@ +import React from "react"; +import PropTypes from "prop-types"; + +const PdfResult = props => { + const { rule, valueTestId } = props; + + return rule ? ( +
    +

    + {rule.name}: {Math.round(rule.value)} +

    +
    + ) : null; +}; +PdfResult.propTypes = { + rule: PropTypes.object.isRequired, + valueTestId: PropTypes.string +}; + +export default PdfResult; diff --git a/client/src/components/ProjectWizard/TdmCalculationWizard.js b/client/src/components/ProjectWizard/TdmCalculationWizard.js index 292b194e..8a02ffc0 100644 --- a/client/src/components/ProjectWizard/TdmCalculationWizard.js +++ b/client/src/components/ProjectWizard/TdmCalculationWizard.js @@ -132,6 +132,13 @@ const TdmCalculationWizard = props => { return setDisplayed; }; + const setDisplayDownloadButton = () => { + if (page === 5) { + return true; + } + return false; + }; + const handleValidate = () => { const { page } = match.params; const validations = { @@ -230,7 +237,9 @@ const TdmCalculationWizard = props => { setDisabledForNextNavButton={setDisabledForNextNavButton} setDisabledSaveButton={setDisabledSaveButton} setDisplaySaveButton={setDisplaySaveButton} + setDisplayDownloadButton={setDisplayDownloadButton} onSave={onSave} + dateModified={dateModified} /> diff --git a/client/src/components/ProjectWizard/WizardFooter.js b/client/src/components/ProjectWizard/WizardFooter.js index f1a6e571..9afd4cc0 100644 --- a/client/src/components/ProjectWizard/WizardFooter.js +++ b/client/src/components/ProjectWizard/WizardFooter.js @@ -1,17 +1,19 @@ -import React from "react"; +import React, { useRef } from "react"; import PropTypes from "prop-types"; import NavButton from "../Button/NavButton"; import SaveButton from "../Button/SaveButton"; import { createUseStyles } from "react-jss"; -import { faClock } from "@fortawesome/free-solid-svg-icons"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import DownloadButton from "../Button/DownloadButton"; +import ReactToPrint from "react-to-print"; +import { Pdf } from "../PDF/PDF"; const useStyles = createUseStyles({ allButtonsWrapper: { display: "flex", - flexDirection: "column", alignItems: "center", - margin: "2em 0" + margin: "3em 0", + width: "80%", + justifyContent: "center" }, pageNumberCounter: { fontSize: "24px", @@ -36,10 +38,12 @@ const WizardFooter = ({ setDisabledForNextNavButton, setDisabledSaveButton, setDisplaySaveButton, + setDisplayDownloadButton, onSave, dateModified }) => { const classes = useStyles(); + const componentRef = useRef(); return ( <> @@ -71,7 +75,22 @@ const WizardFooter = ({ }} /> - + ( + + )} + content={() => componentRef.current} + /> +
    + +
    ) : null} -
    - {dateModified && ( - -  Last saved: {dateModified} - - )} -
    ); }; @@ -103,7 +115,9 @@ WizardFooter.propTypes = { setDisabledForNextNavButton: PropTypes.any, setDisabledSaveButton: PropTypes.any, setDisplaySaveButton: PropTypes.any, + setDisplayDownloadButton: PropTypes.any, onSave: PropTypes.any, + onDownload: PropTypes.any, dateModified: PropTypes.any }; diff --git a/client/src/components/ProjectWizard/WizardPages/ProjectSummary/ProjectSummary.js b/client/src/components/ProjectWizard/WizardPages/ProjectSummary/ProjectSummary.js index 4fe46bce..ea2f92fe 100644 --- a/client/src/components/ProjectWizard/WizardPages/ProjectSummary/ProjectSummary.js +++ b/client/src/components/ProjectWizard/WizardPages/ProjectSummary/ProjectSummary.js @@ -246,7 +246,6 @@ const ProjectSummary = props => { ) : null} -
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    Flyway Reports
    +
    + +
    +
    + + + + + + +
    +
    Migration report
    Database version: 0
    0 scripts migrated
    Execution Time: 00:00.000s
    +
    +
    Database version: 0
    0 scripts migrated
    Execution Time: 00:00.000s
    +You can read more about the migrate report here +

    No migrations found

    +
    +
    +
    + +
    +
    +
    + + Explore how to get this report and what it can do for you.
    + +
    + +
    + + + + +

    Change reporting is not included in your current Flyway license. Upgrade to Flyway Enterprise to gain access.

    + + +
    +
    +
    +
    + +
    +
    +
    + + Explore how to get this report and what it can do for you.
    + +
    + +
    + + + + +

    Drift reporting is not included in your current Flyway license. Upgrade to Flyway Enterprise to gain access.

    + + +
    +
    +
    +
    + +
    +
    +
    + + Explore how to get this report and what it can do for you.
    + +
    + +
    + + + + +

    Dry Run is not included in your current Flyway license. Upgrade to Flyway Teams or Enterprise to gain access.

    + + +
    +
    +
    +
    + +
    +
    +
    + + Explore how to get this report and what it can do for you.
    + +
    + +
    + + + + +

    No code analysis report available yet

    + +
    +
    +
    +
    +
    + + +
    + + + diff --git a/server/report.json b/server/report.json new file mode 100644 index 00000000..a7da63dc --- /dev/null +++ b/server/report.json @@ -0,0 +1,19 @@ +{ + "individualResults": [ + { + "initialSchemaVersion": "20230320.1545", + "targetSchemaVersion": null, + "schemaName": "", + "migrations": [], + "migrationsExecuted": 0, + "success": true, + "flywayVersion": "9.17.0", + "database": "tdmdev", + "warnings": [], + "timestamp": "2023-05-06T13:23:36.226333", + "operation": "migrate", + "exception": null, + "licenseFailed": false + } + ] +} \ No newline at end of file From f3da0b37bd005a584472b032c4638b255898a824 Mon Sep 17 00:00:00 2001 From: James Higgs <40730303+jahpe777@users.noreply.github.com> Date: Sat, 3 Jun 2023 13:34:57 -0700 Subject: [PATCH 16/21] 1363 calculation summary pdf (#1380) * 230505 * 230506 * 230506_1 * 230506_2 * 230510 * 230510_1 * added in first instances of props from project summary component into the new pdf component * 230513 * 230520 * 230521 * Implemented TDM Calculation Summary Print Out * Implemented TDM Calculation Summary Print Out_2 * implemented conditional for component that was crashing pdf print. Added print button to the projects page. * 230531_fix_ProjectInfoList_issue * 230531_renamed_pdf_to_pdrprint --------- Co-authored-by: James Higgs Co-authored-by: James Higgs --- client/src/App.js | 12 +- .../components/{PDF => PdfPrint}/PdfFooter.js | 0 .../{PDF/PDF.js => PdfPrint/PdfPrint.js} | 20 +-- .../components/{PDF => PdfPrint}/PdfResult.js | 0 .../components/ProjectWizard/WizardFooter.js | 4 +- .../src/components/Projects/ProjectsPage.js | 53 ++++++- .../src/components/TdmCalculationContainer.js | 14 +- package-lock.json | 142 +++++++++++++++++- package.json | 1 + server/report.html.html | 132 ---------------- server/report.html.json | 3 - 11 files changed, 217 insertions(+), 164 deletions(-) rename client/src/components/{PDF => PdfPrint}/PdfFooter.js (100%) rename client/src/components/{PDF/PDF.js => PdfPrint/PdfPrint.js} (96%) rename client/src/components/{PDF => PdfPrint}/PdfResult.js (100%) delete mode 100644 server/report.html.html delete mode 100644 server/report.html.json diff --git a/client/src/App.js b/client/src/App.js index fa28dfb5..cc77a1a6 100644 --- a/client/src/App.js +++ b/client/src/App.js @@ -1,4 +1,4 @@ -import React, { useContext } from "react"; +import React, { useContext, useState } from "react"; import UserContext from "./contexts/UserContext"; import PropTypes from "prop-types"; @@ -50,6 +50,8 @@ const App = ({ const classes = useStyles(); const userContext = useContext(UserContext); const account = userContext.account; + const [rules, setRules] = useState([]); + const [dateModified, setDateModified] = useState(null); // console.error("account: " + JSON.stringify(account, null, 2)); @@ -71,6 +73,10 @@ const App = ({ @@ -82,6 +88,10 @@ const App = ({ contentContainerRef={contentContainerRef} checklistModalOpen={checklistModalOpen} toggleChecklistModal={toggleChecklistModal} + rules={rules} + setRules={setRules} + dateModified={dateModified} + setDateModified={setDateModified} /> diff --git a/client/src/components/PDF/PdfFooter.js b/client/src/components/PdfPrint/PdfFooter.js similarity index 100% rename from client/src/components/PDF/PdfFooter.js rename to client/src/components/PdfPrint/PdfFooter.js diff --git a/client/src/components/PDF/PDF.js b/client/src/components/PdfPrint/PdfPrint.js similarity index 96% rename from client/src/components/PDF/PDF.js rename to client/src/components/PdfPrint/PdfPrint.js index 3c02833a..3c75677e 100644 --- a/client/src/components/PDF/PDF.js +++ b/client/src/components/PdfPrint/PdfPrint.js @@ -14,7 +14,7 @@ import ProjectInfo from "../ProjectWizard/WizardPages/ProjectSummary/ProjectInfo import ProjectInfoList from "../ProjectWizard/WizardPages/ProjectSummary/ProjectInfoList"; import PdfResult from "./PdfResult"; import PdfFooter from "./PdfFooter"; -import logo from "../../images/ladot.png"; +import logo from "../../images/ladot_white.png"; const useStyles = createUseStyles({ Pdf: { @@ -71,12 +71,10 @@ const useStyles = createUseStyles({ padding: "12px" }, logo: { - height: "1.5em", - width: "15%", - padding: "0", - backgroundColor: "#FFFFFF", - marginBottom: "-0.25em" - //backgroundColor: "rgb(0,47,113)" + height: "2em", + width: "20%", + padding: "10", + backgroundColor: "rgb(0,47,113)" }, projectInfoDetailsContainer: { paddingTop: "20px", @@ -101,7 +99,7 @@ const useStyles = createUseStyles({ }); // eslint-disable-next-line react/display-name -export const Pdf = forwardRef((props, ref) => { +export const PdfPrint = forwardRef((props, ref) => { const classes = useStyles(); const { rules, dateModified } = props; @@ -170,7 +168,9 @@ export const Pdf = forwardRef((props, ref) => { {projectAddress && ( )} - + {parcelNumbers.value ? ( + + ) : null} {buildingPermit && ( )} @@ -282,7 +282,7 @@ export const Pdf = forwardRef((props, ref) => {
    ); }); -Pdf.propTypes = { +PdfPrint.propTypes = { rules: PropTypes.array, account: PropTypes.object, projectId: PropTypes.number, diff --git a/client/src/components/PDF/PdfResult.js b/client/src/components/PdfPrint/PdfResult.js similarity index 100% rename from client/src/components/PDF/PdfResult.js rename to client/src/components/PdfPrint/PdfResult.js diff --git a/client/src/components/ProjectWizard/WizardFooter.js b/client/src/components/ProjectWizard/WizardFooter.js index 9afd4cc0..9ec139c6 100644 --- a/client/src/components/ProjectWizard/WizardFooter.js +++ b/client/src/components/ProjectWizard/WizardFooter.js @@ -5,7 +5,7 @@ import SaveButton from "../Button/SaveButton"; import { createUseStyles } from "react-jss"; import DownloadButton from "../Button/DownloadButton"; import ReactToPrint from "react-to-print"; -import { Pdf } from "../PDF/PDF"; +import { PdfPrint } from "../PdfPrint/PdfPrint"; const useStyles = createUseStyles({ allButtonsWrapper: { @@ -85,7 +85,7 @@ const WizardFooter = ({ content={() => componentRef.current} />
    - { +const ProjectsPage = ({ + account, + history, + contentContainerRef, + rules, + dateModified +}) => { const [projects, setProjects] = useState([]); const [filterText, setFilterText] = useState(""); const [order, setOrder] = useState("asc"); @@ -289,6 +309,8 @@ const ProjectsPage = ({ account, history, contentContainerRef }) => { indexOfLastPost ); + const componentRef = useRef(); + return ( { alt={`Duplicate Project #${project.id} Icon`} /> + ( + + )} + content={() => componentRef.current} + /> +
    + +
    - - - - - -
    -
    Migration report
    Database version: 0
    0 scripts migrated
    Execution Time: 00:00.000s
    -
    -
    Database version: 0
    0 scripts migrated
    Execution Time: 00:00.000s
    -You can read more about the migrate report here -

    No migrations found

    -
    -
    -
    - -
    -
    -
    - - Explore how to get this report and what it can do for you.
    - -
    - -
    - - - - -

    Change reporting is not included in your current Flyway license. Upgrade to Flyway Enterprise to gain access.

    - - -
    -
    -
    -
    - -
    -
    -
    - - Explore how to get this report and what it can do for you.
    - -
    - -
    - - - - -

    Drift reporting is not included in your current Flyway license. Upgrade to Flyway Enterprise to gain access.

    - - -
    -
    -
    -
    - -
    -
    -
    - - Explore how to get this report and what it can do for you.
    - -
    - -
    - - - - -

    Dry Run is not included in your current Flyway license. Upgrade to Flyway Teams or Enterprise to gain access.

    - - -
    -
    -
    -
    - -
    -
    -
    - - Explore how to get this report and what it can do for you.
    - -
    - -
    - - - - -

    No code analysis report available yet

    - -
    -
    -
    -
    - - - - - - - diff --git a/server/report.json b/server/report.json deleted file mode 100644 index a7da63dc..00000000 --- a/server/report.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "individualResults": [ - { - "initialSchemaVersion": "20230320.1545", - "targetSchemaVersion": null, - "schemaName": "", - "migrations": [], - "migrationsExecuted": 0, - "success": true, - "flywayVersion": "9.17.0", - "database": "tdmdev", - "warnings": [], - "timestamp": "2023-05-06T13:23:36.226333", - "operation": "migrate", - "exception": null, - "licenseFailed": false - } - ] -} \ No newline at end of file From f21a2588f5bf79410567fca7296e355b76259a0a Mon Sep 17 00:00:00 2001 From: John Darragh Date: Sat, 3 Jun 2023 14:31:40 -0700 Subject: [PATCH 18/21] 1363 fix ladot logo (#1382) * Fix LADOT Logo on Print PDF * Remove debug css from PdfPrint.js --- client/src/components/PdfPrint/PdfPrint.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/client/src/components/PdfPrint/PdfPrint.js b/client/src/components/PdfPrint/PdfPrint.js index ff20e295..513af101 100644 --- a/client/src/components/PdfPrint/PdfPrint.js +++ b/client/src/components/PdfPrint/PdfPrint.js @@ -74,8 +74,7 @@ const useStyles = createUseStyles({ height: "1.5em", marginBottom: "-.25em", padding: 0, - backgroundColor: "#FFFFFF", - border: "1px solid black" + backgroundColor: "#FFFFFF" }, projectInfoDetailsContainer: { paddingTop: "20px", From d6f666c51272663e71fa4df867d58acd4b681068 Mon Sep 17 00:00:00 2001 From: John Darragh Date: Thu, 15 Jun 2023 20:21:04 -0700 Subject: [PATCH 19/21] Fix to Privilege Escalation Attack (#1391) --- client/src/components/Roles.js | 14 +++++-- server/app/routes/account.routes.js | 14 +++++-- server/app/routes/calculation.routes.js | 19 +++++++-- server/app/routes/faq.routes.js | 7 ++-- server/app/routes/faqCategory.routes.js | 19 +++++++-- server/app/routes/rule.routes.js | 7 ++-- server/middleware/jwt-session.js | 51 ++++++++++++++++++++++--- 7 files changed, 105 insertions(+), 26 deletions(-) diff --git a/client/src/components/Roles.js b/client/src/components/Roles.js index c2a188d6..d758a1ac 100644 --- a/client/src/components/Roles.js +++ b/client/src/components/Roles.js @@ -1,5 +1,5 @@ import React, { useState, useEffect } from "react"; -import { withRouter } from "react-router-dom"; +import { withRouter, Redirect } from "react-router-dom"; import { createUseStyles } from "react-jss"; import * as accountService from "../services/account.service"; import { useToast } from "../contexts/Toast"; @@ -68,6 +68,7 @@ const Roles = () => { const [accounts, setAccounts] = useState([]); const [searchString, setSearchString] = useState(""); const [filteredAccounts, setFilteredAccounts] = useState([]); + const [unauthorized, setUnauthorized] = useState(false); const classes = useStyles(); const toast = useToast(); const appInsights = useAppInsightsContext(); @@ -77,9 +78,13 @@ const Roles = () => { useEffect(() => { const getAccounts = async () => { - const result = await accountService.search(); - setAccounts(result); - setFilteredAccounts(result); + try { + const result = await accountService.search(); + setAccounts(result); + setFilteredAccounts(result); + } catch (err) { + setUnauthorized(true); + } }; getAccounts(); }, []); @@ -132,6 +137,7 @@ const Roles = () => { onLoad={trackComponent} onClick={trackComponent} > + {unauthorized ? : null}

    Security Roles

    Grant or Revoke Admin Permissions diff --git a/server/app/routes/account.routes.js b/server/app/routes/account.routes.js index 6929206c..db9a73e3 100644 --- a/server/app/routes/account.routes.js +++ b/server/app/routes/account.routes.js @@ -3,9 +3,17 @@ const accountController = require("../controllers/account.controller"); const jwtSession = require("../../middleware/jwt-session"); router.get("/:id", jwtSession.validateUser, accountController.getById); -router.get("/", jwtSession.validateUser, accountController.getAll); +router.get( + "/", + jwtSession.validateRoles(["isSecurityAdmin"]), + accountController.getAll +); -router.put("/:id/roles", accountController.putRoles); +router.put( + "/:id/roles", + jwtSession.validateRoles(["isSecurityAdmin"]), + accountController.putRoles +); router.post("/register", accountController.register); router.post( @@ -14,8 +22,6 @@ router.post( ); router.post("/confirmRegister", accountController.confirmRegister); -router.put("/:id/updateaccount", accountController.updateAccount); - router.post("/forgotPassword", accountController.forgotPassword); router.post("/resetPassword", accountController.resetPassword); diff --git a/server/app/routes/calculation.routes.js b/server/app/routes/calculation.routes.js index c3da85bf..2ec9f6f1 100644 --- a/server/app/routes/calculation.routes.js +++ b/server/app/routes/calculation.routes.js @@ -2,6 +2,7 @@ const router = require("express").Router(); const calculationController = require("../controllers/calculation.controller"); const ruleController = require("../controllers/rule.controller"); +const jwtSession = require("../../middleware/jwt-session"); module.exports = router; @@ -9,6 +10,18 @@ router.get("/:id", calculationController.getById); // Get all the rules for a calculation router.get("/:id/rules", ruleController.getByCalculationId); router.get("/", calculationController.getAll); -router.post("/", calculationController.post); -router.put("/:id", calculationController.put); -router.delete("/:id", calculationController.del); +router.post( + "/", + jwtSession.validateRoles(["isAdmin"]), + calculationController.post +); +router.put( + "/:id", + jwtSession.validateRoles(["isAdmin"]), + calculationController.put +); +router.delete( + "/:id", + jwtSession.validateRoles(["isAdmin"]), + calculationController.del +); diff --git a/server/app/routes/faq.routes.js b/server/app/routes/faq.routes.js index 50dabd40..c091414f 100644 --- a/server/app/routes/faq.routes.js +++ b/server/app/routes/faq.routes.js @@ -1,4 +1,5 @@ const router = require("express").Router(); +const jwtSession = require("../../middleware/jwt-session"); const faqController = require("../controllers/faq.controller"); @@ -6,6 +7,6 @@ module.exports = router; router.get("/", faqController.get); router.get("/:id", faqController.getById); -router.post("/", faqController.post); -router.put("/:id", faqController.put); -router.delete("/:id", faqController.del); +router.post("/", jwtSession.validateRoles(["isAdmin"]), faqController.post); +router.put("/:id", jwtSession.validateRoles(["isAdmin"]), faqController.put); +router.delete("/:id", jwtSession.validateRoles(["isAdmin"]), faqController.del); diff --git a/server/app/routes/faqCategory.routes.js b/server/app/routes/faqCategory.routes.js index 48ce67ed..9d86b991 100644 --- a/server/app/routes/faqCategory.routes.js +++ b/server/app/routes/faqCategory.routes.js @@ -1,4 +1,5 @@ const router = require("express").Router(); +const jwtSession = require("../../middleware/jwt-session"); const faqCategoryController = require("../controllers/faqCategory.controller"); @@ -6,6 +7,18 @@ module.exports = router; router.get("/", faqCategoryController.get); router.get("/:id", faqCategoryController.getById); -router.post("/", faqCategoryController.post); -router.put("/:id", faqCategoryController.put); -router.delete("/:id", faqCategoryController.del); +router.post( + "/", + jwtSession.validateRoles(["isAdmin"]), + faqCategoryController.post +); +router.put( + "/:id", + jwtSession.validateRoles(["isAdmin"]), + faqCategoryController.put +); +router.delete( + "/:id", + jwtSession.validateRoles(["isAdmin"]), + faqCategoryController.del +); diff --git a/server/app/routes/rule.routes.js b/server/app/routes/rule.routes.js index beac4648..7e06fc44 100644 --- a/server/app/routes/rule.routes.js +++ b/server/app/routes/rule.routes.js @@ -1,11 +1,12 @@ const router = require("express").Router(); const ruleController = require("../controllers/rule.controller"); +const jwtSession = require("../../middleware/jwt-session"); module.exports = router; router.get("/:id", ruleController.getById); router.get("/", ruleController.getAll); -router.post("/", ruleController.post); -router.put("/:id", ruleController.put); -router.delete("/", ruleController.del); +router.post("/", jwtSession.validateRoles(["isAdmin"]), ruleController.post); +router.put("/:id", jwtSession.validateRoles(["isAdmin"]), ruleController.put); +router.delete("/", jwtSession.validateRoles(["isAdmin"]), ruleController.del); diff --git a/server/middleware/jwt-session.js b/server/middleware/jwt-session.js index a64d5788..00eca505 100644 --- a/server/middleware/jwt-session.js +++ b/server/middleware/jwt-session.js @@ -4,11 +4,6 @@ const jwtSecret = process.env.JWT_SECRET || "mark it zero"; // JWT timeout set to 12 hours const jwtOpts = { algorithm: "HS256", expiresIn: "12h" }; -module.exports = { - login, - validateUser -}; - // This module manages the user's session using a JSON Web Token in the // "authorization" cookie to manage the session. @@ -19,7 +14,12 @@ module.exports = { // as as a JSON response body (for clients that may not be able to // work with cookies). async function login(req, res) { - const token = await sign({ email: req.user.email, id: req.user.id }); + const token = await sign({ + email: req.user.email, + id: req.user.id, + isAdmin: req.user.isAdmin, + isSecurityAdmin: req.user.isSecurityAdmin + }); res.cookie("jwt", token, { httpOnly: true, expires: new Date(Date.now() + 43200000) // 12 hours @@ -45,6 +45,39 @@ async function validateUser(req, res, next) { } } +// When a request is received for a route that requires an +// authenticated user, this middleware function validates that +// the authorization cookie has a valid JWT and that the +// user is grantee one of the roles listed in authorizedRoles, +// e.g., from the account.routes router: +// router.put( +// "/:id/roles", +// jwtSession.authorizeUser(["isSecurityAdmin"]), +// accountController.putRoles +// ); +const validateRoles = authorizedRoles => + async function validateUser(req, res, next) { + const jwtString = req.headers.authorization || req.cookies.jwt; + try { + const payload = await verify(jwtString); + + if (payload.email) { + req.user = payload; + if (authorizedRoles.includes("isAdmin") && payload.isAdmin) { + return next(); + } else if ( + authorizedRoles.includes("isSecurityAdmin") && + payload.isSecurityAdmin + ) { + return next(); + } + res.status("403").send("Unauthorized request"); + } + } catch (er) { + res.status("401").send("Login session expired"); + } + }; + // Helper function to create JWT token async function sign(payload) { const token = await jwt.sign(payload, jwtSecret, jwtOpts); @@ -56,3 +89,9 @@ async function verify(jwtString = "") { jwtString = jwtString.replace(/^Bearer /i, ""); return jwt.verify(jwtString, jwtSecret); } + +module.exports = { + login, + validateUser, + validateRoles +}; From 13ea6d17b404349c724e7828448f4b0b0a8ca54b Mon Sep 17 00:00:00 2001 From: John Darragh Date: Fri, 16 Jun 2023 21:04:16 -0700 Subject: [PATCH 20/21] Improve response to 401/403 on roles page (#1392) --- client/src/components/Button/Button.js | 2 +- .../src/components/Projects/ProjectsPage.js | 10 +++++----- client/src/components/Roles.js | 20 +++++++++++++------ client/src/services/account.service.js | 2 +- server/middleware/jwt-session.js | 4 ++-- 5 files changed, 23 insertions(+), 15 deletions(-) diff --git a/client/src/components/Button/Button.js b/client/src/components/Button/Button.js index eb2d7eda..4a571a25 100644 --- a/client/src/components/Button/Button.js +++ b/client/src/components/Button/Button.js @@ -70,7 +70,7 @@ const Button = ({ Button.propTypes = { onClick: PropTypes.func, - children: PropTypes.string, + children: PropTypes.any, size: PropTypes.string, variant: PropTypes.string, isDisplayed: PropTypes.bool, diff --git a/client/src/components/Projects/ProjectsPage.js b/client/src/components/Projects/ProjectsPage.js index a76ccdf3..ab43eb1d 100644 --- a/client/src/components/Projects/ProjectsPage.js +++ b/client/src/components/Projects/ProjectsPage.js @@ -8,8 +8,8 @@ import { useToast } from "../../contexts/Toast"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faSortUp, - faSortDown, - faPrint + faSortDown + // faPrint } from "@fortawesome/free-solid-svg-icons"; import SearchIcon from "../../images/search.png"; import CopyIcon from "../../images/copy.png"; @@ -18,7 +18,7 @@ import Pagination from "../Pagination.js"; import DeleteProjectModal from "./DeleteProjectModal"; import DuplicateProjectModal from "./DuplicateProjectModal"; import ContentContainerNoSidebar from "../Layout/ContentContainerNoSidebar"; -import ReactToPrint from "react-to-print"; +// import ReactToPrint from "react-to-print"; import { PdfPrint } from "../PdfPrint/PdfPrint"; const useStyles = createUseStyles({ @@ -418,7 +418,7 @@ const ProjectsPage = ({ alt={`Duplicate Project #${project.id} Icon`} /> - (