From 0bce921f69b54dd6aaf0edd97ede91df3a1c3328 Mon Sep 17 00:00:00 2001 From: Allan Carr Date: Tue, 13 Aug 2024 16:00:17 -0700 Subject: [PATCH 001/478] IO-2876 Filtered Search Sorters correction Signed-off-by: Allan Carr --- .../jobs-list-paginated.component.jsx | 20 +++++++++---------- client/src/graphql/jobs.queries.js | 2 +- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/client/src/components/jobs-list-paginated/jobs-list-paginated.component.jsx b/client/src/components/jobs-list-paginated/jobs-list-paginated.component.jsx index 59e7dbd80..fe3799c49 100644 --- a/client/src/components/jobs-list-paginated/jobs-list-paginated.component.jsx +++ b/client/src/components/jobs-list-paginated/jobs-list-paginated.component.jsx @@ -11,6 +11,7 @@ import { createStructuredSelector } from "reselect"; import { selectBodyshop } from "../../redux/user/user.selectors"; import CurrencyFormatter from "../../utils/CurrencyFormatter"; import { pageLimit } from "../../utils/config"; +import { alphaSort, statusSort } from "../../utils/sorters"; import useLocalStorage from "../../utils/useLocalStorage"; import StartChatButton from "../chat-open-button/chat-open-button.component"; import OwnerNameDisplay from "../owner-name-display/owner-name-display.component"; @@ -37,7 +38,10 @@ export function JobsList({ bodyshop, refetch, loading, jobs, total }) { title: t("jobs.fields.ro_number"), dataIndex: "ro_number", key: "ro_number", - sorter: true, //(a, b) => alphaSort(a.ro_number, b.ro_number), + sorter: search?.search + ? (a, b) => + parseInt((a.ro_number || "0").replace(/\D/g, "")) - parseInt((b.ro_number || "0").replace(/\D/g, "")) + : true, sortOrder: sortcolumn === "ro_number" && sortorder, render: (text, record) => ( {record.ro_number || t("general.labels.na")} @@ -49,7 +53,6 @@ export function JobsList({ bodyshop, refetch, loading, jobs, total }) { key: "ownr_ln", ellipsis: true, //sorter: true, // (a, b) => alphaSort(a.ownr_ln, b.ownr_ln), - //sortOrder: sortcolumn === "ownr_ln" && sortorder, render: (text, record) => { return record.ownerid ? ( @@ -67,7 +70,6 @@ export function JobsList({ bodyshop, refetch, loading, jobs, total }) { title: t("jobs.fields.ownr_ph1"), dataIndex: "ownr_ph1", key: "ownr_ph1", - ellipsis: true, render: (text, record) => }, @@ -75,7 +77,6 @@ export function JobsList({ bodyshop, refetch, loading, jobs, total }) { title: t("jobs.fields.ownr_ph2"), dataIndex: "ownr_ph2", key: "ownr_ph2", - ellipsis: true, render: (text, record) => }, @@ -85,7 +86,7 @@ export function JobsList({ bodyshop, refetch, loading, jobs, total }) { key: "status", ellipsis: true, - sorter: true, // (a, b) => alphaSort(a.status, b.status), + sorter: search?.search ? (a, b) => statusSort(a.status, b.status, bodyshop.md_ro_statuses.active_statuses) : true, sortOrder: sortcolumn === "status" && sortorder, render: (text, record) => { return record.status || t("general.labels.na"); @@ -100,7 +101,6 @@ export function JobsList({ bodyshop, refetch, loading, jobs, total }) { title: t("jobs.fields.vehicle"), dataIndex: "vehicle", key: "vehicle", - ellipsis: true, render: (text, record) => { return record.vehicleid ? ( @@ -117,7 +117,7 @@ export function JobsList({ bodyshop, refetch, loading, jobs, total }) { dataIndex: "plate_no", key: "plate_no", ellipsis: true, - sorter: true, //(a, b) => alphaSort(a.plate_no, b.plate_no), + sorter: search?.search ? (a, b) => alphaSort(a.plate_no, b.plate_no) : true, sortOrder: sortcolumn === "plate_no" && sortorder, render: (text, record) => { return record.plate_no ? record.plate_no : ""; @@ -128,7 +128,7 @@ export function JobsList({ bodyshop, refetch, loading, jobs, total }) { dataIndex: "clm_no", key: "clm_no", ellipsis: true, - sorter: true, //(a, b) => alphaSort(a.clm_no, b.clm_no), + sorter: search?.search ? (a, b) => alphaSort(a.clm_no, b.clm_no) : true, sortOrder: sortcolumn === "clm_no" && sortorder, render: (text, record) => `${record.clm_no || ""}${record.po_number ? ` (PO: ${record.po_number})` : ""}` }, @@ -142,8 +142,7 @@ export function JobsList({ bodyshop, refetch, loading, jobs, total }) { title: t("jobs.fields.clm_total"), dataIndex: "clm_total", key: "clm_total", - - sorter: true, //(a, b) => a.clm_total - b.clm_total, + sorter: search?.search ? (a, b) => a.clm_total - b.clm_total : true, sortOrder: sortcolumn === "clm_total" && sortorder, render: (text, record) => { return record.clm_total ? ( @@ -157,7 +156,6 @@ export function JobsList({ bodyshop, refetch, loading, jobs, total }) { title: t("jobs.fields.owner_owing"), dataIndex: "owner_owing", key: "owner_owing", - render: (text, record) => {record.owner_owing} }, { diff --git a/client/src/graphql/jobs.queries.js b/client/src/graphql/jobs.queries.js index 51ff6927c..87961e152 100644 --- a/client/src/graphql/jobs.queries.js +++ b/client/src/graphql/jobs.queries.js @@ -1,7 +1,7 @@ import { gql } from "@apollo/client"; export const QUERY_ALL_ACTIVE_JOBS_PAGINATED = gql` - query QUERY_ALL_JOBS_PAGINATED_STATUS_FILTERED( + query QUERY_ALL_ACTIVE_JOBS_PAGINATED( $offset: Int $limit: Int $order: [jobs_order_by!] From b1cda41f56dba27eb49b8ff52edc2b5db93536ed Mon Sep 17 00:00:00 2001 From: Patrick Fic Date: Tue, 27 Feb 2024 20:29:09 -0500 Subject: [PATCH 002/478] - Remove Joyride and its cause - Package updates (front + back) Signed-off-by: Dave Richer --- client/package-lock.json | 1280 ++++++++--------- client/package.json | 55 +- .../scheduled-out-today.component.jsx | 3 - .../jobs-list/jobs-list.component.jsx | 7 +- .../update-alert/update-alert.component.jsx | 56 +- .../pages/manage/manage.page.component.jsx | 28 +- .../redux/application/application.actions.js | 8 - .../redux/application/application.reducer.js | 10 +- .../application/application.selectors.js | 2 - .../redux/application/application.types.js | 4 +- client/vite.config.js | 13 +- package-lock.json | 613 ++++---- package.json | 22 +- 13 files changed, 958 insertions(+), 1143 deletions(-) diff --git a/client/package-lock.json b/client/package-lock.json index 371e2177e..bf0a5afcd 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -8,22 +8,22 @@ "name": "bodyshop", "version": "0.2.1", "dependencies": { - "@ant-design/pro-layout": "^7.19.11", - "@apollo/client": "^3.10.8", + "@ant-design/pro-layout": "^7.19.12", + "@apollo/client": "^3.11.4", "@emotion/is-prop-valid": "^1.3.0", "@fingerprintjs/fingerprintjs": "^4.4.3", "@jsreport/browser-client": "^3.1.0", - "@reduxjs/toolkit": "^2.2.6", - "@sentry/cli": "^2.32.2", + "@reduxjs/toolkit": "^2.2.7", + "@sentry/cli": "^2.33.1", "@sentry/react": "^7.114.0", - "@splitsoftware/splitio-react": "^1.12.0", + "@splitsoftware/splitio-react": "^1.12.1", "@tanem/react-nprogress": "^5.0.51", "@vitejs/plugin-react": "^4.3.1", - "antd": "^5.19.3", + "antd": "^5.20.1", "apollo-link-logger": "^2.0.1", "apollo-link-sentry": "^3.3.0", "autosize": "^6.0.1", - "axios": "^1.6.8", + "axios": "^1.7.4", "classnames": "^2.5.1", "css-box-model": "^1.2.1", "dayjs": "^1.11.12", @@ -32,45 +32,44 @@ "dotenv": "^16.4.5", "env-cmd": "^10.1.0", "exifr": "^7.1.3", - "firebase": "^10.12.4", + "firebase": "^10.12.5", "graphql": "^16.9.0", - "i18next": "^23.12.2", + "i18next": "^23.12.3", "i18next-browser-languagedetector": "^8.0.0", "immutability-helper": "^3.1.1", - "libphonenumber-js": "^1.11.4", - "logrocket": "^8.1.1", + "libphonenumber-js": "^1.11.5", + "logrocket": "^8.1.2", "markerjs2": "^2.32.1", "memoize-one": "^6.0.0", "normalize-url": "^8.0.1", "object-hash": "^3.0.0", "prop-types": "^15.8.1", - "query-string": "^9.0.0", + "query-string": "^9.1.0", "raf-schd": "^4.0.3", "react": "^18.3.1", - "react-big-calendar": "^1.13.1", + "react-big-calendar": "^1.13.2", "react-color": "^2.19.3", - "react-cookie": "^7.1.4", + "react-cookie": "^7.2.0", "react-dom": "^18.3.1", "react-drag-listview": "^2.0.0", "react-grid-gallery": "^1.0.1", "react-grid-layout": "1.3.4", "react-i18next": "^14.1.3", - "react-icons": "^5.2.1", + "react-icons": "^5.3.0", "react-image-lightbox": "^5.1.4", - "react-joyride": "^2.8.2", "react-markdown": "^9.0.1", "react-number-format": "^5.4.0", "react-popopo": "^2.1.9", "react-product-fruits": "^2.2.6", "react-redux": "^9.1.2", "react-resizable": "^3.0.5", - "react-router-dom": "^6.25.1", + "react-router-dom": "^6.26.0", "react-sticky": "^6.0.3", "react-virtualized": "^9.22.5", - "react-virtuoso": "^4.7.12", + "react-virtuoso": "^4.10.1", "recharts": "^2.12.7", "redux": "^5.0.1", - "redux-actions": "^3.0.0", + "redux-actions": "^3.0.3", "redux-persist": "^6.0.0", "redux-saga": "^1.3.0", "redux-state-sync": "^3.1.4", @@ -80,36 +79,36 @@ "styled-components": "^6.1.12", "subscriptions-transport-ws": "^0.11.0", "use-memo-one": "^1.1.3", - "userpilot": "^1.3.2", + "userpilot": "^1.3.5", "vite-plugin-ejs": "^1.7.0", "web-vitals": "^3.5.2" }, "devDependencies": { "@babel/plugin-proposal-private-property-in-object": "^7.21.11", "@babel/preset-react": "^7.24.7", - "@dotenvx/dotenvx": "^1.6.4", + "@dotenvx/dotenvx": "^1.7.0", "@emotion/babel-plugin": "^11.12.0", - "@emotion/react": "^11.12.0", - "@sentry/webpack-plugin": "^2.21.1", + "@emotion/react": "^11.13.0", + "@sentry/webpack-plugin": "^2.22.2", "@testing-library/cypress": "^10.0.2", - "browserslist": "^4.23.2", + "browserslist": "^4.23.3", "browserslist-to-esbuild": "^2.1.1", "cross-env": "^7.0.3", - "cypress": "^13.13.1", + "cypress": "^13.13.3", "eslint": "^8.57.0", "eslint-config-react-app": "^7.0.1", "eslint-plugin-cypress": "^2.15.1", - "memfs": "^4.9.3", + "memfs": "^4.11.1", "os-browserify": "^0.3.0", "react-error-overlay": "6.0.11", "redux-logger": "^3.0.6", "source-map-explorer": "^2.5.3", - "vite": "^5.3.4", + "vite": "^5.4.0", "vite-plugin-babel": "^1.2.0", "vite-plugin-eslint": "^1.8.1", "vite-plugin-legacy": "^2.1.0", "vite-plugin-node-polyfills": "^0.22.0", - "vite-plugin-pwa": "^0.20.0", + "vite-plugin-pwa": "^0.20.1", "vite-plugin-style-import": "^2.0.0" }, "engines": { @@ -157,14 +156,42 @@ "react-dom": ">=16.0.0" } }, + "node_modules/@ant-design/cssinjs-utils": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@ant-design/cssinjs-utils/-/cssinjs-utils-1.0.3.tgz", + "integrity": "sha512-BrztZZKuoYcJK8uEH40ylBemf/Mu/QPiDos56g2bv6eUoniQkgQHOCOvA3+pncoFO1TaS8xcUCIqGzDA0I+ZVQ==", + "license": "MIT", + "dependencies": { + "@ant-design/cssinjs": "^1.21.0", + "@babel/runtime": "^7.23.2", + "rc-util": "^5.38.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@ant-design/fast-color": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@ant-design/fast-color/-/fast-color-2.0.6.tgz", + "integrity": "sha512-y2217gk4NqL35giHl72o6Zzqji9O7vHh9YmhUVkPtAOpoTCH4uWxo/pr4VE8t0+ChEPs0qo4eJRC5Q1eXWo3vA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.24.7" + }, + "engines": { + "node": ">=8.x" + } + }, "node_modules/@ant-design/icons": { - "version": "5.3.7", - "resolved": "https://registry.npmjs.org/@ant-design/icons/-/icons-5.3.7.tgz", - "integrity": "sha512-bCPXTAg66f5bdccM4TT21SQBDO1Ek2gho9h3nO9DAKXJP4sq+5VBjrQMSxMVXSB3HyEz+cUbHQ5+6ogxCOpaew==", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@ant-design/icons/-/icons-5.4.0.tgz", + "integrity": "sha512-QZbWC5xQYexCI5q4/fehSEkchJr5UGtvAJweT743qKUQQGs9IH2DehNLP49DJ3Ii9m9CijD2HN6fNy3WKhIFdA==", + "license": "MIT", "dependencies": { "@ant-design/colors": "^7.0.0", "@ant-design/icons-svg": "^4.4.0", - "@babel/runtime": "^7.11.2", + "@babel/runtime": "^7.24.8", "classnames": "^2.2.6", "rc-util": "^5.31.1" }, @@ -182,18 +209,19 @@ "integrity": "sha512-vHbT+zJEVzllwP+CM+ul7reTEfBR0vgxFe7+lREAsAA7YGsYpboiq2sQNeQeRvh09GfQgs/GyFEvZpJ9cLXpXA==" }, "node_modules/@ant-design/pro-layout": { - "version": "7.19.11", - "resolved": "https://registry.npmjs.org/@ant-design/pro-layout/-/pro-layout-7.19.11.tgz", - "integrity": "sha512-KTnHYO/J5cF3MvMr9Skgg/G07GgzLw3Zj0vkKBFHS5ByjSh2eX1dBu5f3g9aDOB3e9XFrkfiVwkGLHvcgiAxpg==", + "version": "7.19.12", + "resolved": "https://registry.npmjs.org/@ant-design/pro-layout/-/pro-layout-7.19.12.tgz", + "integrity": "sha512-JSWkhY/GcDKc+c8t7Pbzv1XdK2zhLxg/BupW/JfXk0FHpMs08J+yq64Gqu5fMo2bP1V/8xpwWR5Ik7LHj/Z31Q==", + "license": "MIT", "dependencies": { "@ant-design/icons": "^5.0.0", "@ant-design/pro-provider": "2.14.9", - "@ant-design/pro-utils": "2.15.16", + "@ant-design/pro-utils": "2.15.17", "@babel/runtime": "^7.18.0", "@umijs/route-utils": "^4.0.0", "@umijs/use-params": "^1.0.9", "classnames": "^2.3.2", - "lodash.merge": "^4.6.2", + "lodash-es": "^4.17.21", "omit.js": "^2.0.2", "path-to-regexp": "2.4.0", "rc-resize-observer": "^1.1.0", @@ -216,6 +244,7 @@ "version": "2.14.9", "resolved": "https://registry.npmjs.org/@ant-design/pro-provider/-/pro-provider-2.14.9.tgz", "integrity": "sha512-4UJr6AHyWKsrhx2KfdkpRQCgjc75oDUDhMHGA2OWqQVI16sMQfeZf6KYfmeiG3Dal1QKFOtSibCdH5G2CDvWlg==", + "license": "MIT", "dependencies": { "@ant-design/cssinjs": "^1.11.1", "@babel/runtime": "^7.18.0", @@ -230,16 +259,17 @@ } }, "node_modules/@ant-design/pro-utils": { - "version": "2.15.16", - "resolved": "https://registry.npmjs.org/@ant-design/pro-utils/-/pro-utils-2.15.16.tgz", - "integrity": "sha512-WSyE6dSZOY3aBSdfqzu3HSfV6XbZNQoHOhh6ankEZMgDRiKn1JiDG1CvgjdzFN2N5RULCoCcAHqU784fTEhggA==", + "version": "2.15.17", + "resolved": "https://registry.npmjs.org/@ant-design/pro-utils/-/pro-utils-2.15.17.tgz", + "integrity": "sha512-8uF1evCxI3YsEFugP5MY7Oy8HGIKL7tajXkpIRTOZmH9Az/yTX/7cAo1FnwJ1vliLm6aBPpfwNh5qRHjZQOj3g==", + "license": "MIT", "dependencies": { "@ant-design/icons": "^5.0.0", "@ant-design/pro-provider": "2.14.9", "@babel/runtime": "^7.18.0", "classnames": "^2.3.2", "dayjs": "^1.11.10", - "lodash.merge": "^4.6.2", + "lodash-es": "^4.17.21", "rc-util": "^5.0.6", "safe-stable-stringify": "^2.4.3", "swr": "^2.0.0" @@ -283,9 +313,10 @@ } }, "node_modules/@apollo/client": { - "version": "3.10.8", - "resolved": "https://registry.npmjs.org/@apollo/client/-/client-3.10.8.tgz", - "integrity": "sha512-UaaFEitRrPRWV836wY2L7bd3HRCfbMie1jlYMcmazFAK23MVhz/Uq7VG1nwbotPb5xzFsw5RF4Wnp2G3dWPM3g==", + "version": "3.11.4", + "resolved": "https://registry.npmjs.org/@apollo/client/-/client-3.11.4.tgz", + "integrity": "sha512-bmgYKkULpym8wt8aXlAZ1heaYo0skLJ5ru0qJ+JCRoo03Pe+yIDbBCnqlDw6Mjj76hFkDw3HwFMgZC2Hxp30Mg==", + "license": "MIT", "dependencies": { "@graphql-typed-document-node/core": "^3.1.1", "@wry/caches": "^1.0.0", @@ -305,8 +336,8 @@ "peerDependencies": { "graphql": "^15.0.0 || ^16.0.0", "graphql-ws": "^5.5.5", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0", "subscriptions-transport-ws": "^0.9.0 || ^0.11.0" }, "peerDependenciesMeta": { @@ -2681,14 +2712,14 @@ } }, "node_modules/@dotenvx/dotenvx": { - "version": "1.6.4", - "resolved": "https://registry.npmjs.org/@dotenvx/dotenvx/-/dotenvx-1.6.4.tgz", - "integrity": "sha512-2jbcxpqbJDafeZo9i2ha38qGyB0KISgCht6KDTyvR4LlWK922pflm9t8M1jY97uYgW3PNZZjCmQjzQ+IB/V4rQ==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@dotenvx/dotenvx/-/dotenvx-1.7.0.tgz", + "integrity": "sha512-WPkSNS060+GwNoWHHBRjJxBR9KhsWyoNyevD8I2x8LffWPdbVvRJqJI72fF1H+KYpDWGBQ4xdX++xO2GS37XUQ==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "chalk": "^4.1.2", "commander": "^11.1.0", - "conf": "^10.2.0", "diff": "^5.2.0", "dotenv": "^16.4.5", "eciesjs": "^0.4.6", @@ -2792,14 +2823,15 @@ "dev": true }, "node_modules/@emotion/cache": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.12.0.tgz", - "integrity": "sha512-VFo/F1PthkxHwWDCcXkidyXw70eAkdiNiCzthMI2rRQjFiTvmXt8UDlv/VE1DTsd4CIEY2wQf5AnL2QiPgphlw==", + "version": "11.13.1", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.13.1.tgz", + "integrity": "sha512-iqouYkuEblRcXmylXIwwOodiEK5Ifl7JcX7o6V4jI3iW4mLXX3dmt5xwBtIkJiQEXFAI+pC8X0i67yiPkH9Ucw==", "dev": true, + "license": "MIT", "dependencies": { "@emotion/memoize": "^0.9.0", - "@emotion/sheet": "^1.3.0", - "@emotion/utils": "^1.3.0", + "@emotion/sheet": "^1.4.0", + "@emotion/utils": "^1.4.0", "@emotion/weak-memoize": "^0.4.0", "stylis": "4.2.0" } @@ -2808,13 +2840,15 @@ "version": "0.9.0", "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz", "integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@emotion/cache/node_modules/stylis": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@emotion/hash": { "version": "0.8.0", @@ -2840,17 +2874,18 @@ "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==" }, "node_modules/@emotion/react": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.12.0.tgz", - "integrity": "sha512-kTktYMpG8mHjLi8u6XOTMfDmQvUve/un2ZVj4khcU2KTn17ElMV8BK6QFzT8V/v2QW8013rf07Yc0ayQL3tp3w==", + "version": "11.13.0", + "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.13.0.tgz", + "integrity": "sha512-WkL+bw1REC2VNV1goQyfxjx1GYJkcc23CRQkXX+vZNLINyfI7o+uUn/rTGPt/xJ3bJHd5GcljgnxHf4wRw5VWQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/runtime": "^7.18.3", "@emotion/babel-plugin": "^11.12.0", - "@emotion/cache": "^11.12.0", - "@emotion/serialize": "^1.2.0", - "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1", - "@emotion/utils": "^1.3.0", + "@emotion/cache": "^11.13.0", + "@emotion/serialize": "^1.3.0", + "@emotion/use-insertion-effect-with-fallbacks": "^1.1.0", + "@emotion/utils": "^1.4.0", "@emotion/weak-memoize": "^0.4.0", "hoist-non-react-statics": "^3.3.1" }, @@ -2864,15 +2899,16 @@ } }, "node_modules/@emotion/serialize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.2.0.tgz", - "integrity": "sha512-X5UWpZAhGGp5LOn7OAI9k9JjRtz7nSFhZypatADcuEd/0bECZ0DzVjPdL8hljTrAku8+TjFvWIYHMOCO/0v/Ng==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.0.tgz", + "integrity": "sha512-jACuBa9SlYajnpIVXB+XOXnfJHyckDfe6fOpORIM6yhBDlqGuExvDdZYHDQGoDf3bZXGv7tNr+LpLjJqiEQ6EA==", "dev": true, + "license": "MIT", "dependencies": { "@emotion/hash": "^0.9.2", "@emotion/memoize": "^0.9.0", "@emotion/unitless": "^0.9.0", - "@emotion/utils": "^1.3.0", + "@emotion/utils": "^1.4.0", "csstype": "^3.0.2" } }, @@ -2895,10 +2931,11 @@ "dev": true }, "node_modules/@emotion/sheet": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.3.0.tgz", - "integrity": "sha512-vOPwbKw8fj/oSEa7CWqiKCvLZ1AeLIAApmboGP34xUyUjXalFyf+tMtgMDqP7VMevLPhUa+YWJS46cQUA+tr9A==", - "dev": true + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz", + "integrity": "sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==", + "dev": true, + "license": "MIT" }, "node_modules/@emotion/unitless": { "version": "0.7.5", @@ -2906,25 +2943,28 @@ "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==" }, "node_modules/@emotion/use-insertion-effect-with-fallbacks": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.1.tgz", - "integrity": "sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.1.0.tgz", + "integrity": "sha512-+wBOcIV5snwGgI2ya3u99D7/FJquOIniQT1IKyDsBmEgwvpxMNeS65Oib7OnE2d2aY+3BU4OiH+0Wchf8yk3Hw==", "dev": true, + "license": "MIT", "peerDependencies": { "react": ">=16.8.0" } }, "node_modules/@emotion/utils": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.3.0.tgz", - "integrity": "sha512-+M7u4EaX5t4bCunKTltAdGis3NFHQniikLVEQ+rPQccsX/xV4v5Etwg12paioZ9DsO+CTvimtmnjZbW85kbF8Q==", - "dev": true + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.0.tgz", + "integrity": "sha512-spEnrA1b6hDR/C68lC2M7m6ALPUHZC0lIY7jAS/B/9DuuO1ZP04eov8SMv/6fwRd8pzmsn2AuJEznRREWlQrlQ==", + "dev": true, + "license": "MIT" }, "node_modules/@emotion/weak-memoize": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz", "integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@esbuild/aix-ppc64": { "version": "0.21.5", @@ -3420,15 +3460,15 @@ } }, "node_modules/@firebase/analytics": { - "version": "0.10.6", - "resolved": "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.10.6.tgz", - "integrity": "sha512-sB59EwcAvLt0fINGfMWmcRKcdUiYhE4AJNdDXSCSDo4D/ZXFRmb6qwX9YesKHXFB59XTLT03mAjqQcDrdym9qA==", + "version": "0.10.7", + "resolved": "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.10.7.tgz", + "integrity": "sha512-GE29uTT6y/Jv2EP0OjpTezeTQZ5FTCTaZXKrrdVGjb/t35AU4u/jiU+hUwUPpuK8fqhhiHkS/AawE3a3ZK/a9Q==", + "license": "Apache-2.0", "dependencies": { "@firebase/component": "0.6.8", "@firebase/installations": "0.6.8", "@firebase/logger": "0.4.2", "@firebase/util": "1.9.7", - "safevalues": "0.6.0", "tslib": "^2.1.0" }, "peerDependencies": { @@ -3436,11 +3476,12 @@ } }, "node_modules/@firebase/analytics-compat": { - "version": "0.2.12", - "resolved": "https://registry.npmjs.org/@firebase/analytics-compat/-/analytics-compat-0.2.12.tgz", - "integrity": "sha512-rXWnOAdEHbvBPLNjFLu3U0yDZVIAi+C0DL+RkUEOirfSqAeQaKzBCATeBw6+K7FVpEnknhm4tZrvVUVtJjShMw==", + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/@firebase/analytics-compat/-/analytics-compat-0.2.13.tgz", + "integrity": "sha512-aZ4wGfNDMsCxhKzDbK2g1aV0JKsdQ9FbeIsjpNJPzhahV0XYj+z36Y4RNLPpG/6hHU4gxnezxs+yn3HhHkNL8w==", + "license": "Apache-2.0", "dependencies": { - "@firebase/analytics": "0.10.6", + "@firebase/analytics": "0.10.7", "@firebase/analytics-types": "0.8.2", "@firebase/component": "0.6.8", "@firebase/util": "1.9.7", @@ -3453,12 +3494,14 @@ "node_modules/@firebase/analytics-types": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/@firebase/analytics-types/-/analytics-types-0.8.2.tgz", - "integrity": "sha512-EnzNNLh+9/sJsimsA/FGqzakmrAUKLeJvjRHlg8df1f97NLUlFidk9600y0ZgWOp3CAxn6Hjtk+08tixlUOWyw==" + "integrity": "sha512-EnzNNLh+9/sJsimsA/FGqzakmrAUKLeJvjRHlg8df1f97NLUlFidk9600y0ZgWOp3CAxn6Hjtk+08tixlUOWyw==", + "license": "Apache-2.0" }, "node_modules/@firebase/app": { - "version": "0.10.7", - "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.10.7.tgz", - "integrity": "sha512-7OCd53B+wnk/onbMLn/vM10pDjw97zzWUD8m3swtLYKJIrL+gDZ7HZ4xcbBLw7OB8ikzu8k1ORNjRe2itgAy4g==", + "version": "0.10.8", + "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.10.8.tgz", + "integrity": "sha512-xSLmW0/RShcnUEXH7l+wC0AFWaUtty4tUFF2loIgbtXTRmra0UH/SqYDf/IcfreUninRrCsusNmvoTidGkXJPw==", + "license": "Apache-2.0", "dependencies": { "@firebase/component": "0.6.8", "@firebase/logger": "0.4.2", @@ -3468,14 +3511,14 @@ } }, "node_modules/@firebase/app-check": { - "version": "0.8.6", - "resolved": "https://registry.npmjs.org/@firebase/app-check/-/app-check-0.8.6.tgz", - "integrity": "sha512-uSzl0/SDw54hwuORWHDtldb9kK/QEVZOcoPn2mlIjMrJOLDug/6kcqnIN3IHzwmPyf23Epg0AGBktvG2FugW4w==", + "version": "0.8.7", + "resolved": "https://registry.npmjs.org/@firebase/app-check/-/app-check-0.8.7.tgz", + "integrity": "sha512-EkOeJcMKVR0zZ6z/jqcFTqHb/xq+TVIRIuBNGHdpcIuFU1czhSlegvqv2+nC+nFrkD8M6Xvd3tAlUOkdbMeS6A==", + "license": "Apache-2.0", "dependencies": { "@firebase/component": "0.6.8", "@firebase/logger": "0.4.2", "@firebase/util": "1.9.7", - "safevalues": "0.6.0", "tslib": "^2.1.0" }, "peerDependencies": { @@ -3483,11 +3526,12 @@ } }, "node_modules/@firebase/app-check-compat": { - "version": "0.3.13", - "resolved": "https://registry.npmjs.org/@firebase/app-check-compat/-/app-check-compat-0.3.13.tgz", - "integrity": "sha512-1sbS5Apq7dLys1KYdNQsmZLFIjJoFP9Mv4bzIcdXuTkWQjr3X2qAvwiTslC6prVAUMiTV0eM9eicdQIXVsiSRw==", + "version": "0.3.14", + "resolved": "https://registry.npmjs.org/@firebase/app-check-compat/-/app-check-compat-0.3.14.tgz", + "integrity": "sha512-kK3bPfojAfXE53W+20rxMqIxrloFswXG9vh4kEdYL6Wa2IB3sD5++2dPiK3yGxl8oQiqS8qL2wcKB5/xLpEVEg==", + "license": "Apache-2.0", "dependencies": { - "@firebase/app-check": "0.8.6", + "@firebase/app-check": "0.8.7", "@firebase/app-check-types": "0.5.2", "@firebase/component": "0.6.8", "@firebase/logger": "0.4.2", @@ -3506,14 +3550,16 @@ "node_modules/@firebase/app-check-types": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/@firebase/app-check-types/-/app-check-types-0.5.2.tgz", - "integrity": "sha512-FSOEzTzL5bLUbD2co3Zut46iyPWML6xc4x+78TeaXMSuJap5QObfb+rVvZJtla3asN4RwU7elaQaduP+HFizDA==" + "integrity": "sha512-FSOEzTzL5bLUbD2co3Zut46iyPWML6xc4x+78TeaXMSuJap5QObfb+rVvZJtla3asN4RwU7elaQaduP+HFizDA==", + "license": "Apache-2.0" }, "node_modules/@firebase/app-compat": { - "version": "0.2.37", - "resolved": "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.2.37.tgz", - "integrity": "sha512-yiQLYT9LYQHuJGu/msuBLFtdWWTJ3Pz04E9gSeWykSB+8s0XXJJqfqQlghH7CcQ3KnJZR+Wuc3zSMcY3a+dn6Q==", + "version": "0.2.38", + "resolved": "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.2.38.tgz", + "integrity": "sha512-36ZrSvkYLW7QR01Sii2X+IY18ErMpRg6e2B2f/DVTtJBolthwXOnNBps+wvaVBvegdvdVPspgDXZUV0ppqh45w==", + "license": "Apache-2.0", "dependencies": { - "@firebase/app": "0.10.7", + "@firebase/app": "0.10.8", "@firebase/component": "0.6.8", "@firebase/logger": "0.4.2", "@firebase/util": "1.9.7", @@ -3523,12 +3569,14 @@ "node_modules/@firebase/app-types": { "version": "0.9.2", "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.9.2.tgz", - "integrity": "sha512-oMEZ1TDlBz479lmABwWsWjzHwheQKiAgnuKxE0pz0IXCVx7/rtlkx1fQ6GfgK24WCrxDKMplZrT50Kh04iMbXQ==" + "integrity": "sha512-oMEZ1TDlBz479lmABwWsWjzHwheQKiAgnuKxE0pz0IXCVx7/rtlkx1fQ6GfgK24WCrxDKMplZrT50Kh04iMbXQ==", + "license": "Apache-2.0" }, "node_modules/@firebase/auth": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-1.7.5.tgz", - "integrity": "sha512-DMFR1OA/f1/voeuFbSORg9AP36pMgOoSb/DRgiDalLmIJsDTlQNMCu+givjMP4s/XL85+tBk2MerYnK/AscJjw==", + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-1.7.6.tgz", + "integrity": "sha512-T+lA5xoug9CByGYkD5WkfTh2ujEYq/frGZPbk0H+fNU6fNl7nqg88KcsmzsC6Fsqbjm3LLEb/i6wJvF6NSNEig==", + "license": "Apache-2.0", "dependencies": { "@firebase/component": "0.6.8", "@firebase/logger": "0.4.2", @@ -3547,11 +3595,12 @@ } }, "node_modules/@firebase/auth-compat": { - "version": "0.5.10", - "resolved": "https://registry.npmjs.org/@firebase/auth-compat/-/auth-compat-0.5.10.tgz", - "integrity": "sha512-epDhgNIXmhl9DPuTW9Ec5NDJJKMFIdXBXiQI9O0xNHveow/ETtBCY86srzF7iCacqsd30CcpLwwXlhk8Y19Olg==", + "version": "0.5.11", + "resolved": "https://registry.npmjs.org/@firebase/auth-compat/-/auth-compat-0.5.11.tgz", + "integrity": "sha512-7rE3MkQDoWwI2qd8qsra4/QZCO2GzQSbCL6AVQpult9+Nbimg+5A+YeHxpLTcYAxUV6HDg2CqTDQreFLhcm1CQ==", + "license": "Apache-2.0", "dependencies": { - "@firebase/auth": "1.7.5", + "@firebase/auth": "1.7.6", "@firebase/auth-types": "0.12.2", "@firebase/component": "0.6.8", "@firebase/util": "1.9.7", @@ -3571,6 +3620,7 @@ "version": "0.12.2", "resolved": "https://registry.npmjs.org/@firebase/auth-types/-/auth-types-0.12.2.tgz", "integrity": "sha512-qsEBaRMoGvHO10unlDJhaKSuPn4pyoTtlQuP1ghZfzB6rNQPuhp/N/DcFZxm9i4v0SogjCbf9reWupwIvfmH6w==", + "license": "Apache-2.0", "peerDependencies": { "@firebase/app-types": "0.x", "@firebase/util": "1.x" @@ -3586,9 +3636,10 @@ } }, "node_modules/@firebase/database": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@firebase/database/-/database-1.0.6.tgz", - "integrity": "sha512-nrexUEG/fpVlHtWKkyfhTC3834kZ1WS7voNyqbBsBCqHXQOvznN5Z0L3nxBqdXSJyltNAf4ndFlQqm5gZiEczQ==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@firebase/database/-/database-1.0.7.tgz", + "integrity": "sha512-wjXr5AO8RPxVVg7rRCYffT7FMtBjHRfJ9KMwi19MbOf0vBf0H9YqW3WCgcnLpXI6ehiUcU3z3qgPnnU0nK6SnA==", + "license": "Apache-2.0", "dependencies": { "@firebase/app-check-interop-types": "0.3.2", "@firebase/auth-interop-types": "0.2.3", @@ -3600,12 +3651,13 @@ } }, "node_modules/@firebase/database-compat": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-1.0.6.tgz", - "integrity": "sha512-1OGA0sLY47mkXjhICCrUTXEYFnSSXoiXWm1SHsN62b+Lzs5aKA3aWTjTUmYIoK93kDAMPkYpulSv8jcbH4Hwew==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-1.0.7.tgz", + "integrity": "sha512-R/3B+VVzEFN5YcHmfWns3eitA8fHLTL03io+FIoMcTYkajFnrBdS3A+g/KceN9omP7FYYYGTQWF9lvbEx6eMEg==", + "license": "Apache-2.0", "dependencies": { "@firebase/component": "0.6.8", - "@firebase/database": "1.0.6", + "@firebase/database": "1.0.7", "@firebase/database-types": "1.0.4", "@firebase/logger": "0.4.2", "@firebase/util": "1.9.7", @@ -3616,15 +3668,17 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-1.0.4.tgz", "integrity": "sha512-mz9ZzbH6euFXbcBo+enuJ36I5dR5w+enJHHjy9Y5ThCdKUseqfDjW3vCp1YxE9zygFCSjJJ/z1cQ+zodvUcwPQ==", + "license": "Apache-2.0", "dependencies": { "@firebase/app-types": "0.9.2", "@firebase/util": "1.9.7" } }, "node_modules/@firebase/firestore": { - "version": "4.6.4", - "resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-4.6.4.tgz", - "integrity": "sha512-vk2MoH5HxYEhiNg1l+yBXq1Fkhue/11bFg4HdlTv6BJHcTnnAj2a+/afPpatcW4MOdYA3Tv+d5nGzWbbOC1SHw==", + "version": "4.6.5", + "resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-4.6.5.tgz", + "integrity": "sha512-0+Ascaht4qUzj4pCopMPWmoAujk8HKjwCpaNYOOjbYMZ65RVfZPsfZwwbWi/zWMXj6xvPsai5oBiErUUkrLwNw==", + "license": "Apache-2.0", "dependencies": { "@firebase/component": "0.6.8", "@firebase/logger": "0.4.2", @@ -3643,12 +3697,13 @@ } }, "node_modules/@firebase/firestore-compat": { - "version": "0.3.33", - "resolved": "https://registry.npmjs.org/@firebase/firestore-compat/-/firestore-compat-0.3.33.tgz", - "integrity": "sha512-i42a2l31N95CwYEB7zmfK0FS1mrO6pwOLwxavCrwu1BCFrVVVQhUheTPIda/iGguK/2Nog0RaIR1bo7QkZEz3g==", + "version": "0.3.34", + "resolved": "https://registry.npmjs.org/@firebase/firestore-compat/-/firestore-compat-0.3.34.tgz", + "integrity": "sha512-OBP2F/Ccydl2U2j8XIfpKBxf0EnQHEhbZ4LTwbSS2QlG9+8TwhvKFkKk/ZljWYqaype+qFKPuXZ5flCqYEETeA==", + "license": "Apache-2.0", "dependencies": { "@firebase/component": "0.6.8", - "@firebase/firestore": "4.6.4", + "@firebase/firestore": "4.6.5", "@firebase/firestore-types": "3.0.2", "@firebase/util": "1.9.7", "tslib": "^2.1.0" @@ -3661,6 +3716,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/@firebase/firestore-types/-/firestore-types-3.0.2.tgz", "integrity": "sha512-wp1A+t5rI2Qc/2q7r2ZpjUXkRVPtGMd6zCLsiWurjsQpqPgFin3AhNibKcIzoF2rnToNa/XYtyWXuifjOOwDgg==", + "license": "Apache-2.0", "peerDependencies": { "@firebase/app-types": "0.x", "@firebase/util": "1.x" @@ -3923,12 +3979,8 @@ "node_modules/@firebase/webchannel-wrapper": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@firebase/webchannel-wrapper/-/webchannel-wrapper-1.0.1.tgz", - "integrity": "sha512-jmEnr/pk0yVkA7mIlHNnxCi+wWzOFUg0WyIotgkKAb2u1J7fAeDBcVNSTjTihbAYNusCLQdW5s9IJ5qwnEufcQ==" - }, - "node_modules/@gilbarbara/deep-equal": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@gilbarbara/deep-equal/-/deep-equal-0.3.1.tgz", - "integrity": "sha512-I7xWjLs2YSVMc5gGx1Z3ZG1lgFpITPndpi8Ku55GeEIKpACCPQNS/OTqQbxgTCfq0Ncvcc+CrFov96itVh6Qvw==" + "integrity": "sha512-jmEnr/pk0yVkA7mIlHNnxCi+wWzOFUg0WyIotgkKAb2u1J7fAeDBcVNSTjTihbAYNusCLQdW5s9IJ5qwnEufcQ==", + "license": "Apache-2.0" }, "node_modules/@graphql-typed-document-node/core": { "version": "3.2.0", @@ -3942,6 +3994,7 @@ "version": "1.9.15", "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.9.15.tgz", "integrity": "sha512-nqE7Hc0AzI+euzUwDAy0aY5hCp10r734gMGRdU+qOPX0XSceI2ULrcXB5U2xSc5VkWwalCj4M7GzCAygZl2KoQ==", + "license": "Apache-2.0", "dependencies": { "@grpc/proto-loader": "^0.7.8", "@types/node": ">=12.12.47" @@ -3954,6 +4007,7 @@ "version": "0.7.13", "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.13.tgz", "integrity": "sha512-AiXO/bfe9bmxBjxxtYxFAXGZvMaN5s8kO+jBHAJCON8rJoB5YS/D6X7ZNc6XQkuHNmyl4CYaMI1fJ/Gn27RGGw==", + "license": "Apache-2.0", "dependencies": { "lodash.camelcase": "^4.3.0", "long": "^5.0.0", @@ -4122,10 +4176,11 @@ } }, "node_modules/@jsonjoy.com/util": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/util/-/util-1.1.3.tgz", - "integrity": "sha512-g//kkF4kOwUjemValCtOc/xiYzmwMRmWq3Bn+YnzOzuZLHq2PpMOxxIayN3cKbo7Ko2Np65t6D9H81IvXbXhqg==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/util/-/util-1.3.0.tgz", + "integrity": "sha512-Cebt4Vk7k1xHy87kHY7KSPLT77A7Ev7IfOblyLZhtYEhrdQ6fX4EoLq3xOQ3O/DRMEh2ok5nyC180E+ABS8Wmw==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=10.0" }, @@ -4279,27 +4334,32 @@ "node_modules/@protobufjs/aspromise": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", - "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", + "license": "BSD-3-Clause" }, "node_modules/@protobufjs/base64": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", - "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", + "license": "BSD-3-Clause" }, "node_modules/@protobufjs/codegen": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", - "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==", + "license": "BSD-3-Clause" }, "node_modules/@protobufjs/eventemitter": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", - "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==", + "license": "BSD-3-Clause" }, "node_modules/@protobufjs/fetch": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "license": "BSD-3-Clause", "dependencies": { "@protobufjs/aspromise": "^1.1.1", "@protobufjs/inquire": "^1.1.0" @@ -4308,32 +4368,38 @@ "node_modules/@protobufjs/float": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", - "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", + "license": "BSD-3-Clause" }, "node_modules/@protobufjs/inquire": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", - "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==", + "license": "BSD-3-Clause" }, "node_modules/@protobufjs/path": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", - "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", + "license": "BSD-3-Clause" }, "node_modules/@protobufjs/pool": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", - "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", + "license": "BSD-3-Clause" }, "node_modules/@protobufjs/utf8": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", - "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", + "license": "BSD-3-Clause" }, "node_modules/@rc-component/async-validator": { "version": "5.0.4", "resolved": "https://registry.npmjs.org/@rc-component/async-validator/-/async-validator-5.0.4.tgz", "integrity": "sha512-qgGdcVIF604M9EqjNF0hbUTz42bz/RDtxWdWuU5EQe3hi7M8ob54B6B35rOsvX5eSvIHIzT9iH1R3n+hk3CGfg==", + "license": "MIT", "dependencies": { "@babel/runtime": "^7.24.4" }, @@ -4342,12 +4408,13 @@ } }, "node_modules/@rc-component/color-picker": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/@rc-component/color-picker/-/color-picker-1.5.3.tgz", - "integrity": "sha512-+tGGH3nLmYXTalVe0L8hSZNs73VTP5ueSHwUlDC77KKRaN7G4DS4wcpG5DTDzdcV/Yas+rzA6UGgIyzd8fS4cw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@rc-component/color-picker/-/color-picker-2.0.1.tgz", + "integrity": "sha512-WcZYwAThV/b2GISQ8F+7650r5ZZJ043E57aVBFkQ+kSY4C6wdofXgB0hBx+GPGpIU0Z81eETNoDUJMr7oy/P8Q==", + "license": "MIT", "dependencies": { + "@ant-design/fast-color": "^2.0.6", "@babel/runtime": "^7.23.6", - "@ctrl/tinycolor": "^3.6.1", "classnames": "^2.2.6", "rc-util": "^5.38.1" }, @@ -4373,6 +4440,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/@rc-component/mini-decimal/-/mini-decimal-1.1.0.tgz", "integrity": "sha512-jS4E7T9Li2GuYwI6PyiVXmxTiM6b07rlD9Ge8uGZSCz3WlzcG5ZK7g5bbuKNeZ9pgUuPK/5guV781ujdVpm4HQ==", + "license": "MIT", "dependencies": { "@babel/runtime": "^7.18.0" }, @@ -4451,9 +4519,10 @@ } }, "node_modules/@rc-component/trigger": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@rc-component/trigger/-/trigger-2.2.0.tgz", - "integrity": "sha512-QarBCji02YE9aRFhZgRZmOpXBj0IZutRippsVBv85sxvG4FGk/vRxwAlkn3MS9zK5mwbETd86mAVg2tKqTkdJA==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@rc-component/trigger/-/trigger-2.2.1.tgz", + "integrity": "sha512-fuU11J8pOt6+U/tU6/CAv8wjCwGaNeRk9f5k8HQth7JBbJ6MMH62WhGycVW75VnXfBZgL/7kO+wbiO2Xc9U9sQ==", + "license": "MIT", "dependencies": { "@babel/runtime": "^7.23.2", "@rc-component/portal": "^1.1.0", @@ -4521,9 +4590,10 @@ "integrity": "sha512-1dgmkh+3so0+LlBWRhGA33ua4MYr7tUOj+a9Si28vUi0IUFNbff1T3sgpeDJI/LaC75bBYnQ0A3wXjn0OrRNBA==" }, "node_modules/@reduxjs/toolkit": { - "version": "2.2.6", - "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.2.6.tgz", - "integrity": "sha512-kH0r495c5z1t0g796eDQAkYbEQ3a1OLYN9o8jQQVZyKyw367pfRGS+qZLkHYvFHiUUdafpoSlQ2QYObIApjPWA==", + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.2.7.tgz", + "integrity": "sha512-faI3cZbSdFb8yv9dhDTmGwclW0vk0z5o1cia+kf7gCbaCwHI5e+7tP57mJUv22pNcNbeA62GSrPpfrUfdXcQ6g==", + "license": "MIT", "dependencies": { "immer": "^10.0.3", "redux": "^5.0.1", @@ -4544,9 +4614,10 @@ } }, "node_modules/@remix-run/router": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.18.0.tgz", - "integrity": "sha512-L3jkqmqoSVBVKHfpGZmLrex0lxR5SucGA0sUfFzGctehw+S/ggL9L/0NnC5mw6P8HUWpFZ3nQw3cRApjjWx9Sw==", + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.19.0.tgz", + "integrity": "sha512-zDICCLKEwbVYTS6TjYaWtHXxkdoUvD/QXvyVZjGCsWz5vyH7aFeONlPffPdW+Y/t6KT0MgXb2Mfjun9YpWN1dA==", + "license": "MIT", "engines": { "node": ">=14.0.0" } @@ -5147,10 +5218,11 @@ } }, "node_modules/@sentry/babel-plugin-component-annotate": { - "version": "2.21.1", - "resolved": "https://registry.npmjs.org/@sentry/babel-plugin-component-annotate/-/babel-plugin-component-annotate-2.21.1.tgz", - "integrity": "sha512-u1L8gZ4He0WdyiIsohYkA/YOY1b6Oa5yIMRtfZZ9U5TiWYLgOfMWyb88X0GotZeghSbgxrse/yI4WeHnhAUQDQ==", + "version": "2.22.2", + "resolved": "https://registry.npmjs.org/@sentry/babel-plugin-component-annotate/-/babel-plugin-component-annotate-2.22.2.tgz", + "integrity": "sha512-6kFAHGcs0npIC4HTt4ULs8uOfEucvMI7VW4hoyk17jhRaW8CbxzxfWCfIeRbDkE8pYwnARaq83tu025Hrk2zgA==", "dev": true, + "license": "MIT", "engines": { "node": ">= 14" } @@ -5174,14 +5246,15 @@ } }, "node_modules/@sentry/bundler-plugin-core": { - "version": "2.21.1", - "resolved": "https://registry.npmjs.org/@sentry/bundler-plugin-core/-/bundler-plugin-core-2.21.1.tgz", - "integrity": "sha512-F8FdL/bS8cy1SY1Gw0Mfo3ROTqlrq9Lvt5QGvhXi22dpVcDkWmoTWE2k+sMEnXOa8SdThMc/gyC8lMwHGd3kFQ==", + "version": "2.22.2", + "resolved": "https://registry.npmjs.org/@sentry/bundler-plugin-core/-/bundler-plugin-core-2.22.2.tgz", + "integrity": "sha512-TwEEW4FeEJ5Mamp4fGnktfVjzN77KAW0xFQsEPuxZtOAPG17zX/PGvdyRX/TE1jkZWhTzqUDIdgzqlNLjyEnUw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/core": "^7.18.5", - "@sentry/babel-plugin-component-annotate": "2.21.1", - "@sentry/cli": "^2.22.3", + "@sentry/babel-plugin-component-annotate": "2.22.2", + "@sentry/cli": "^2.33.1", "dotenv": "^16.3.1", "find-up": "^5.0.0", "glob": "^9.3.2", @@ -5193,10 +5266,11 @@ } }, "node_modules/@sentry/cli": { - "version": "2.32.2", - "resolved": "https://registry.npmjs.org/@sentry/cli/-/cli-2.32.2.tgz", - "integrity": "sha512-m/6Z3FWu+rTd8jepVlJPKQhvbT8vCjt0N7BSWZiEUVW/8mhwAYJiwO0b+Ch/u4IqbBg1dp3805q5TFPl4AdrNw==", + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli/-/cli-2.33.1.tgz", + "integrity": "sha512-dUlZ4EFh98VFRPJ+f6OW3JEYQ7VvqGNMa0AMcmvk07ePNeK/GicAWmSQE4ZfJTTl80ul6HZw1kY01fGQOQlVRA==", "hasInstallScript": true, + "license": "BSD-3-Clause", "dependencies": { "https-proxy-agent": "^5.0.0", "node-fetch": "^2.6.7", @@ -5211,19 +5285,20 @@ "node": ">= 10" }, "optionalDependencies": { - "@sentry/cli-darwin": "2.32.2", - "@sentry/cli-linux-arm": "2.32.2", - "@sentry/cli-linux-arm64": "2.32.2", - "@sentry/cli-linux-i686": "2.32.2", - "@sentry/cli-linux-x64": "2.32.2", - "@sentry/cli-win32-i686": "2.32.2", - "@sentry/cli-win32-x64": "2.32.2" + "@sentry/cli-darwin": "2.33.1", + "@sentry/cli-linux-arm": "2.33.1", + "@sentry/cli-linux-arm64": "2.33.1", + "@sentry/cli-linux-i686": "2.33.1", + "@sentry/cli-linux-x64": "2.33.1", + "@sentry/cli-win32-i686": "2.33.1", + "@sentry/cli-win32-x64": "2.33.1" } }, "node_modules/@sentry/cli-darwin": { - "version": "2.32.2", - "resolved": "https://registry.npmjs.org/@sentry/cli-darwin/-/cli-darwin-2.32.2.tgz", - "integrity": "sha512-GDtePIavx3FKSRowdPdtIssahn46MfFFYNN+s7a9MjlhFwJtvC9A1bSDw7ksEtDaQolepUwmLPHaVe19y0T/zw==", + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-darwin/-/cli-darwin-2.33.1.tgz", + "integrity": "sha512-+4/VIx/E1L2hChj5nGf5MHyEPHUNHJ/HoG5RY+B+vyEutGily1c1+DM2bum7RbD0xs6wKLIyup5F02guzSzG8A==", + "license": "BSD-3-Clause", "optional": true, "os": [ "darwin" @@ -5233,12 +5308,13 @@ } }, "node_modules/@sentry/cli-linux-arm": { - "version": "2.32.2", - "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm/-/cli-linux-arm-2.32.2.tgz", - "integrity": "sha512-u9s08wr8bDDqsAl6pk9iGGlOHtU+T8btU6voNKy71QzeIBpV9c8VVk/OnmP9aswp/ea4NY416yjnzcTvCrFKAw==", + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm/-/cli-linux-arm-2.33.1.tgz", + "integrity": "sha512-zbxEvQju+tgNvzTOt635le4kS/Fbm2XC2RtYbCTs034Vb8xjrAxLnK0z1bQnStUV8BkeBHtsNVrG+NSQDym2wg==", "cpu": [ "arm" ], + "license": "BSD-3-Clause", "optional": true, "os": [ "linux", @@ -5249,12 +5325,13 @@ } }, "node_modules/@sentry/cli-linux-arm64": { - "version": "2.32.2", - "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm64/-/cli-linux-arm64-2.32.2.tgz", - "integrity": "sha512-VECLVC1rLyvXk6rTVUfmfs4vhANjMgm4BVKGlA3rydmf2PJw2/NfipH3KeyijdE2vEoyLri+/6HH883pP0iniQ==", + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm64/-/cli-linux-arm64-2.33.1.tgz", + "integrity": "sha512-DbGV56PRKOLsAZJX27Jt2uZ11QfQEMmWB4cIvxkKcFVE+LJP4MVA+MGGRUL6p+Bs1R9ZUuGbpKGtj0JiG6CoXw==", "cpu": [ "arm64" ], + "license": "BSD-3-Clause", "optional": true, "os": [ "linux", @@ -5265,13 +5342,14 @@ } }, "node_modules/@sentry/cli-linux-i686": { - "version": "2.32.2", - "resolved": "https://registry.npmjs.org/@sentry/cli-linux-i686/-/cli-linux-i686-2.32.2.tgz", - "integrity": "sha512-XhofQz32OqLrQK1DEOsryhT7d29Df6VkccvxueGoIt2gpXEXtgRczsUwZjZqquDdkNCt+HPj9eUGcj8pY8JkmQ==", + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-i686/-/cli-linux-i686-2.33.1.tgz", + "integrity": "sha512-g2LS4oPXkPWOfKWukKzYp4FnXVRRSwBxhuQ9eSw2peeb58ZIObr4YKGOA/8HJRGkooBJIKGaAR2mH2Pk1TKaiA==", "cpu": [ "x86", "ia32" ], + "license": "BSD-3-Clause", "optional": true, "os": [ "linux", @@ -5282,12 +5360,13 @@ } }, "node_modules/@sentry/cli-linux-x64": { - "version": "2.32.2", - "resolved": "https://registry.npmjs.org/@sentry/cli-linux-x64/-/cli-linux-x64-2.32.2.tgz", - "integrity": "sha512-anyng4Qqt7zX4ZY4IzDH1RJWAVZNBe6sUHcuciNy7giCU3B4/XnxAHlwYmBSN5txpaumsWdstPgRKEUJG6AOSA==", + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-x64/-/cli-linux-x64-2.33.1.tgz", + "integrity": "sha512-IV3dcYV/ZcvO+VGu9U6kuxSdbsV2kzxaBwWUQxtzxJ+cOa7J8Hn1t0koKGtU53JVZNBa06qJWIcqgl4/pCuKIg==", "cpu": [ "x64" ], + "license": "BSD-3-Clause", "optional": true, "os": [ "linux", @@ -5298,13 +5377,14 @@ } }, "node_modules/@sentry/cli-win32-i686": { - "version": "2.32.2", - "resolved": "https://registry.npmjs.org/@sentry/cli-win32-i686/-/cli-win32-i686-2.32.2.tgz", - "integrity": "sha512-/auqx7QXG7F556fNK7vaB26pX7Far1CQMfI65iV4u/VWg6gV2WfvJWXB4iowhjqkYv56sZ+zOymLkEVF0R8wtg==", + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-win32-i686/-/cli-win32-i686-2.33.1.tgz", + "integrity": "sha512-F7cJySvkpzIu7fnLKNHYwBzZYYwlhoDbAUnaFX0UZCN+5DNp/5LwTp37a5TWOsmCaHMZT4i9IO4SIsnNw16/zQ==", "cpu": [ "x86", "ia32" ], + "license": "BSD-3-Clause", "optional": true, "os": [ "win32" @@ -5314,12 +5394,13 @@ } }, "node_modules/@sentry/cli-win32-x64": { - "version": "2.32.2", - "resolved": "https://registry.npmjs.org/@sentry/cli-win32-x64/-/cli-win32-x64-2.32.2.tgz", - "integrity": "sha512-w7hW2sEWVYQquqdILBSFhcVW+HdoyLqVPPkLPAXRSLTwBnuni9nQEIdXr0h/7db+K3cm7PvWndp5ixVyswLHZA==", + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-win32-x64/-/cli-win32-x64-2.33.1.tgz", + "integrity": "sha512-8VyRoJqtb2uQ8/bFRKNuACYZt7r+Xx0k2wXRGTyH05lCjAiVIXn7DiS2BxHFty7M1QEWUCMNsb/UC/x/Cu2wuA==", "cpu": [ "x64" ], + "license": "BSD-3-Clause", "optional": true, "os": [ "win32" @@ -5406,12 +5487,13 @@ } }, "node_modules/@sentry/webpack-plugin": { - "version": "2.21.1", - "resolved": "https://registry.npmjs.org/@sentry/webpack-plugin/-/webpack-plugin-2.21.1.tgz", - "integrity": "sha512-mhKWQq7/eC35qrhhD8oXm/37vZ1BQqmCD8dUngFIr4D24rc7dwlGwPGOYv59yiBqjTS0fGJ+o0xC5PTRKljGQQ==", + "version": "2.22.2", + "resolved": "https://registry.npmjs.org/@sentry/webpack-plugin/-/webpack-plugin-2.22.2.tgz", + "integrity": "sha512-zVPs3BLClHM8jIjr2FChux16GMLel8OjXBjd4V8/r1Kf2fGiQDXo72GxsrW8AdVlIHgQApLzubuQ2kpcFVK4Sw==", "dev": true, + "license": "MIT", "dependencies": { - "@sentry/bundler-plugin-core": "2.21.1", + "@sentry/bundler-plugin-core": "2.22.2", "unplugin": "1.0.1", "uuid": "^9.0.0" }, @@ -5428,11 +5510,12 @@ "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==" }, "node_modules/@splitsoftware/splitio": { - "version": "10.26.0", - "resolved": "https://registry.npmjs.org/@splitsoftware/splitio/-/splitio-10.26.0.tgz", - "integrity": "sha512-sACjAcov/Zn1gYaN6m0qQb9G/LDk43c8rEzFaabhlnWOsH0W22ImVHGx8iU3I/DyC1S2wrsjXTSnW1GQlbb7+Q==", + "version": "10.27.0", + "resolved": "https://registry.npmjs.org/@splitsoftware/splitio/-/splitio-10.27.0.tgz", + "integrity": "sha512-nl1pf44Rlhne0StFIURmLZqINN4vi/wqbxXT0Q4EFGG4/F5rzC8k/RmfJPONNf2b803qsj+XQ0U8O9cnhVBW1A==", + "license": "Apache-2.0", "dependencies": { - "@splitsoftware/splitio-commons": "1.14.0", + "@splitsoftware/splitio-commons": "1.16.0", "@types/google.analytics": "0.0.40", "@types/ioredis": "^4.28.0", "bloom-filters": "^3.0.0", @@ -5445,15 +5528,13 @@ "engines": { "node": ">=6", "npm": ">=3" - }, - "optionalDependencies": { - "eventsource": "^1.1.2" } }, "node_modules/@splitsoftware/splitio-commons": { - "version": "1.14.0", - "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-1.14.0.tgz", - "integrity": "sha512-ANP0NRPAMehi4bUQsb19kP5W5NVuCYUKRsDC5Nl78xHIu6cskAej1rXkjsocLnWerz2rO0H9kMjRKZj9lVsvKA==", + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-1.16.0.tgz", + "integrity": "sha512-k16cCWJOWut/NB5W1d9hQEYPxFrZXO66manp+8d6RjZYH4r+Q6lu82NYjDcfh5E93H9v+TVKcQLAmpVofbjcvg==", + "license": "Apache-2.0", "dependencies": { "tslib": "^2.3.1" }, @@ -5467,11 +5548,12 @@ } }, "node_modules/@splitsoftware/splitio-react": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-react/-/splitio-react-1.12.0.tgz", - "integrity": "sha512-AwvQh+i4Z8EGiv9ZVAiLLvqwh9Y72x7PmZZSFwQHm+srRd3Ji4xObVpLe9fSAHqxFwTpzvU88BHZlKK/HDhqVA==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-react/-/splitio-react-1.12.1.tgz", + "integrity": "sha512-fIWz9s8StUaq7V+8K4W4C5aa5fS1rzQRCdojH3Z59yfinDAOnAVwq/qufITzT4bH5nIjfDSBZAs2yctDXxGJDQ==", + "license": "Apache-2.0", "dependencies": { - "@splitsoftware/splitio": "10.26.0", + "@splitsoftware/splitio": "10.27.0", "memoize-one": "^5.1.1", "shallowequal": "^1.1.0", "tslib": "^2.3.1" @@ -5686,7 +5768,8 @@ "node_modules/@types/google.analytics": { "version": "0.0.40", "resolved": "https://registry.npmjs.org/@types/google.analytics/-/google.analytics-0.0.40.tgz", - "integrity": "sha512-R3HpnLkqmKxhUAf8kIVvDVGJqPtaaZlW4yowNwjOZUTmYUQEgHh8Nh5wkSXKMroNAuQM8gbXJHmNbbgA8tdb7Q==" + "integrity": "sha512-R3HpnLkqmKxhUAf8kIVvDVGJqPtaaZlW4yowNwjOZUTmYUQEgHh8Nh5wkSXKMroNAuQM8gbXJHmNbbgA8tdb7Q==", + "license": "MIT" }, "node_modules/@types/hast": { "version": "3.0.4", @@ -5709,6 +5792,7 @@ "version": "4.28.10", "resolved": "https://registry.npmjs.org/@types/ioredis/-/ioredis-4.28.10.tgz", "integrity": "sha512-69LyhUgrXdgcNDv7ogs1qXZomnfOEnSmrmMFqKgt1XMJxmoOSG/u3wYy13yACIfKuMJ8IhKgHafDO3sx19zVQQ==", + "license": "MIT", "dependencies": { "@types/node": "*" } @@ -6202,45 +6286,6 @@ "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/ajv-formats": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", - "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", - "dev": true, - "dependencies": { - "ajv": "^8.0.0" - }, - "peerDependencies": { - "ajv": "^8.0.0" - }, - "peerDependenciesMeta": { - "ajv": { - "optional": true - } - } - }, - "node_modules/ajv-formats/node_modules/ajv": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.14.0.tgz", - "integrity": "sha512-oYs1UUtO97ZO2lJ4bwnWeQW8/zvOIQLGKcvPTsWmvc2SYgBb+upuNS5NxoLaMU4h8Ju3Nbj6Cq8mD2LQoqVKFA==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.3", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.4.1" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ajv-formats/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, "node_modules/ansi-colors": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", @@ -6288,21 +6333,23 @@ } }, "node_modules/antd": { - "version": "5.19.3", - "resolved": "https://registry.npmjs.org/antd/-/antd-5.19.3.tgz", - "integrity": "sha512-rhGI6yyZ4dA2MWl9bfO0MZjtNwWdzITpp3u7pKLiQpTjJYFlpF5wDFgGaG1or3sqyBihvqcO/OF1hSggmWczbQ==", + "version": "5.20.1", + "resolved": "https://registry.npmjs.org/antd/-/antd-5.20.1.tgz", + "integrity": "sha512-YjVCYAfBjrTyNKsg+heAOR0Gm4qJNJoBZQcV1h1BX/ufwoLx0PC5RGs75g6gQFy/1nv8OrJH7DXUGdtwPMB3Vg==", + "license": "MIT", "dependencies": { "@ant-design/colors": "^7.1.0", "@ant-design/cssinjs": "^1.21.0", - "@ant-design/icons": "^5.3.7", + "@ant-design/cssinjs-utils": "^1.0.3", + "@ant-design/icons": "^5.4.0", "@ant-design/react-slick": "~1.1.2", "@babel/runtime": "^7.24.8", "@ctrl/tinycolor": "^3.6.1", - "@rc-component/color-picker": "~1.5.3", + "@rc-component/color-picker": "~2.0.1", "@rc-component/mutate-observer": "^1.1.0", "@rc-component/qrcode": "~1.0.0", "@rc-component/tour": "~1.15.0", - "@rc-component/trigger": "^2.2.0", + "@rc-component/trigger": "^2.2.1", "classnames": "^2.5.1", "copy-to-clipboard": "^3.3.3", "dayjs": "^1.11.11", @@ -6312,27 +6359,27 @@ "rc-dialog": "~9.5.2", "rc-drawer": "~7.2.0", "rc-dropdown": "~4.2.0", - "rc-field-form": "~2.2.1", + "rc-field-form": "~2.3.0", "rc-image": "~7.9.0", - "rc-input": "~1.5.1", - "rc-input-number": "~9.1.0", - "rc-mentions": "~2.14.0", + "rc-input": "~1.6.3", + "rc-input-number": "~9.2.0", + "rc-mentions": "~2.15.0", "rc-menu": "~9.14.1", "rc-motion": "^2.9.2", "rc-notification": "~5.6.0", "rc-pagination": "~4.2.0", - "rc-picker": "~4.6.9", + "rc-picker": "~4.6.12", "rc-progress": "~4.0.0", "rc-rate": "~2.13.0", "rc-resize-observer": "^1.4.0", "rc-segmented": "~2.3.0", "rc-select": "~14.15.1", - "rc-slider": "~10.6.2", + "rc-slider": "~11.1.5", "rc-steps": "~6.0.1", "rc-switch": "~4.1.0", "rc-table": "~7.45.7", "rc-tabs": "~15.1.1", - "rc-textarea": "~1.7.0", + "rc-textarea": "~1.8.1", "rc-tooltip": "~6.2.0", "rc-tree": "~5.8.8", "rc-tree-select": "~5.22.1", @@ -6693,15 +6740,6 @@ "node": ">= 4.0.0" } }, - "node_modules/atomically": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/atomically/-/atomically-1.7.0.tgz", - "integrity": "sha512-Xcz9l0z7y9yQ9rdDaxlmaI4uJHf/T8g9hOEzJcsEqX2SjCj4J20uK7+ldkDHMbpJDK76wF7xEIgxc/vSlsfw5w==", - "dev": true, - "engines": { - "node": ">=10.12.0" - } - }, "node_modules/autosize": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/autosize/-/autosize-6.0.1.tgz", @@ -6747,9 +6785,10 @@ } }, "node_modules/axios": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.2.tgz", - "integrity": "sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw==", + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.4.tgz", + "integrity": "sha512-DukmaFRnY6AzAALSH4J2M3k6PkaC+MfaAGdEERRWcC9q3/TWQwLpHR8ZRLKTdQ3aBDL64EdluRDjJqKw+BPZEw==", + "license": "MIT", "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.0", @@ -6895,6 +6934,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", "integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==", + "license": "MIT", "engines": { "node": ">= 0.6.0" } @@ -6954,9 +6994,10 @@ "dev": true }, "node_modules/bloom-filters": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/bloom-filters/-/bloom-filters-3.0.1.tgz", - "integrity": "sha512-rU9IU6bgZ1jmqcLWhlKSidrFjbIGjB89CJBsQqUj1+3/11tAJDwn+f7iRu4bbQ2srTjGgNeoWNwcnelumqdi0g==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/bloom-filters/-/bloom-filters-3.0.2.tgz", + "integrity": "sha512-QPKiokjBy16SrBh8T/FAWo74VuNwACnJ9t+q15a+9w5CDaOqHTPPBrDUy70U7YE4+DmENRodtlEdeeq1pB4DZQ==", + "license": "MIT", "dependencies": { "base64-arraybuffer": "^1.0.2", "is-buffer": "^2.0.5", @@ -7222,9 +7263,9 @@ } }, "node_modules/browserslist": { - "version": "4.23.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.2.tgz", - "integrity": "sha512-qkqSyistMYdxAcw+CzbZwlBy8AGmS/eEWs+sEV5TnLRGDOL+C5M2EnH6tlZyg0YoAxGJAFKh61En9BR941GnHA==", + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz", + "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==", "funding": [ { "type": "opencollective", @@ -7239,10 +7280,11 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001640", - "electron-to-chromium": "^1.4.820", - "node-releases": "^2.0.14", + "caniuse-lite": "^1.0.30001646", + "electron-to-chromium": "^1.5.4", + "node-releases": "^2.0.18", "update-browserslist-db": "^1.1.0" }, "bin": { @@ -7401,9 +7443,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001641", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001641.tgz", - "integrity": "sha512-Phv5thgl67bHYo1TtMY/MurjkHhV4EDaCosezRXgZ8jzA/Ub+wjxAvbGvjoFENStinwi5kCyOYV3mi5tOGykwA==", + "version": "1.0.30001651", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001651.tgz", + "integrity": "sha512-9Cf+Xv1jJNe1xPZLGuUXLNkE1BoDkqRqYyFJ9TDYSqhduqA4hu4oR9HluGoWYQC/aj8WHjsGVV+bwkh0+tegRg==", "funding": [ { "type": "opencollective", @@ -7417,7 +7459,8 @@ "type": "github", "url": "https://github.com/sponsors/ai" } - ] + ], + "license": "CC-BY-4.0" }, "node_modules/capital-case": { "version": "1.0.4", @@ -7665,12 +7708,14 @@ "node_modules/client-only": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", - "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==" + "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", + "license": "MIT" }, "node_modules/cliui": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "license": "ISC", "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", @@ -7692,6 +7737,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz", "integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==", + "license": "Apache-2.0", "engines": { "node": ">=0.10.0" } @@ -7822,52 +7868,6 @@ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, - "node_modules/conf": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/conf/-/conf-10.2.0.tgz", - "integrity": "sha512-8fLl9F04EJqjSqH+QjITQfJF8BrOVaYr1jewVgSRAEWePfxT0sku4w2hrGQ60BC/TNLGQ2pgxNlTbWQmMPFvXg==", - "dev": true, - "dependencies": { - "ajv": "^8.6.3", - "ajv-formats": "^2.1.1", - "atomically": "^1.7.0", - "debounce-fn": "^4.0.0", - "dot-prop": "^6.0.1", - "env-paths": "^2.2.1", - "json-schema-typed": "^7.0.3", - "onetime": "^5.1.2", - "pkg-up": "^3.1.0", - "semver": "^7.3.5" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/conf/node_modules/ajv": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.14.0.tgz", - "integrity": "sha512-oYs1UUtO97ZO2lJ4bwnWeQW8/zvOIQLGKcvPTsWmvc2SYgBb+upuNS5NxoLaMU4h8Ju3Nbj6Cq8mD2LQoqVKFA==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.3", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.4.1" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/conf/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, "node_modules/confusing-browser-globals": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz", @@ -8107,13 +8107,14 @@ "integrity": "sha512-d4ZVpCW31eWwCMe1YT3ur7mUDnTXbgwyzaL320DrcRT45rfjYxkt5QWLrmOJ+/UEAI2+fQgKe/fCjR8l4TpRgw==" }, "node_modules/cypress": { - "version": "13.13.1", - "resolved": "https://registry.npmjs.org/cypress/-/cypress-13.13.1.tgz", - "integrity": "sha512-8F9UjL5MDUdgC/S5hr8CGLHbS5gGht5UOV184qc2pFny43fnkoaKxlzH/U6//zmGu/xRTaKimNfjknLT8+UDFg==", + "version": "13.13.3", + "resolved": "https://registry.npmjs.org/cypress/-/cypress-13.13.3.tgz", + "integrity": "sha512-hUxPrdbJXhUOTzuML+y9Av7CKoYznbD83pt8g3klgpioEha0emfx4WNIuVRx0C76r0xV2MIwAW9WYiXfVJYFQw==", "dev": true, "hasInstallScript": true, + "license": "MIT", "dependencies": { - "@cypress/request": "^3.0.0", + "@cypress/request": "^3.0.1", "@cypress/xvfb": "^1.2.4", "@types/sinonjs__fake-timers": "8.1.1", "@types/sizzle": "^2.3.2", @@ -8464,21 +8465,6 @@ "dayjs": "^1.11.10" } }, - "node_modules/debounce-fn": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/debounce-fn/-/debounce-fn-4.0.0.tgz", - "integrity": "sha512-8pYCQiL9Xdcg0UPSD3d+0KMlOjp+KGU5EPwYddgzQ7DATsg4fuUDjQtsYLmWjnk2obnNHgV3vE2Y4jejSOJVBQ==", - "dev": true, - "dependencies": { - "mimic-fn": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -8531,11 +8517,6 @@ "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==", "dev": true }, - "node_modules/deep-diff": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/deep-diff/-/deep-diff-1.0.2.tgz", - "integrity": "sha512-aWS3UIVH+NPGCD1kki+DCU9Dua032iSsO43LqQpcs4R3+dVv7tX0qBGjiVHJHjplsoUM2XRO/KB92glqc68awg==" - }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -8596,6 +8577,7 @@ "version": "1.5.1", "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.1.tgz", "integrity": "sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw==", + "license": "Apache-2.0", "engines": { "node": ">=0.10" } @@ -8800,9 +8782,10 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.825", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.825.tgz", - "integrity": "sha512-OCcF+LwdgFGcsYPYC5keEEFC2XT0gBhrYbeGzHCx7i9qRFbzO/AqTmc/C/1xNhJj+JA7rzlN7mpBuStshh96Cg==" + "version": "1.5.7", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.7.tgz", + "integrity": "sha512-6FTNWIWMxMy/ZY6799nBlPtF1DFDQ6VQJ7yyDP27SJNt5lwtQ5ufqVvHylb3fdQefvRcgA3fKcFMJi9OLwBRNw==", + "license": "ISC" }, "node_modules/elliptic": { "version": "6.5.5", @@ -8901,15 +8884,6 @@ "node": ">= 6" } }, - "node_modules/env-paths": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", - "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -9785,6 +9759,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "license": "BSD-2-Clause", "bin": { "esparse": "bin/esparse.js", "esvalidate": "bin/esvalidate.js" @@ -9870,15 +9845,6 @@ "node": ">=0.8.x" } }, - "node_modules/eventsource": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-1.1.2.tgz", - "integrity": "sha512-xAH3zWhgO2/3KIniEKYPr8plNSzlGINOUqYj0m0u7AB81iRw8b/3E73W6AuU+6klLbaSFmZnaETQ2lXPfAydrA==", - "optional": true, - "engines": { - "node": ">=0.12.0" - } - }, "node_modules/evp_bytestokey": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", @@ -10056,6 +10022,7 @@ "version": "0.11.4", "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "license": "Apache-2.0", "dependencies": { "websocket-driver": ">=0.5.1" }, @@ -10073,12 +10040,13 @@ } }, "node_modules/fdir": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.1.1.tgz", - "integrity": "sha512-QfKBVg453Dyn3mr0Q0O+Tkr1r79lOTAKSi9f/Ot4+qVEwxWhav2Z+SudrG9vQjM2aYRMQQZ2/Q1zdA8ACM1pDg==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.2.0.tgz", + "integrity": "sha512-9XaWcDl0riOX5j2kYfy0kKdg7skw3IY6kA4LFT8Tk2yF9UdrADUy8D6AJuBLtf7ISm/MksumwAHE3WVbMRyCLw==", "dev": true, + "license": "MIT", "peerDependencies": { - "picomatch": "3.x" + "picomatch": "^3 || ^4" }, "peerDependenciesMeta": { "picomatch": { @@ -10181,23 +10149,24 @@ } }, "node_modules/firebase": { - "version": "10.12.4", - "resolved": "https://registry.npmjs.org/firebase/-/firebase-10.12.4.tgz", - "integrity": "sha512-SQz49NMpwG4MLTPZ9C8jBp7IyS2haTvsIvjclgu+v/jvzNtjZoxIcoF6A13EIfBHmJ5eiuVlvttxElOf7LnJew==", + "version": "10.12.5", + "resolved": "https://registry.npmjs.org/firebase/-/firebase-10.12.5.tgz", + "integrity": "sha512-J0yL3yh12CfFprTkSOQ9HqBugERyqvWwOuOoo1j1QHmYe9cYLKnBmtNCvGIYInDcsVUnJoRXCM+hxbGf48oVhg==", + "license": "Apache-2.0", "dependencies": { - "@firebase/analytics": "0.10.6", - "@firebase/analytics-compat": "0.2.12", - "@firebase/app": "0.10.7", - "@firebase/app-check": "0.8.6", - "@firebase/app-check-compat": "0.3.13", - "@firebase/app-compat": "0.2.37", + "@firebase/analytics": "0.10.7", + "@firebase/analytics-compat": "0.2.13", + "@firebase/app": "0.10.8", + "@firebase/app-check": "0.8.7", + "@firebase/app-check-compat": "0.3.14", + "@firebase/app-compat": "0.2.38", "@firebase/app-types": "0.9.2", - "@firebase/auth": "1.7.5", - "@firebase/auth-compat": "0.5.10", - "@firebase/database": "1.0.6", - "@firebase/database-compat": "1.0.6", - "@firebase/firestore": "4.6.4", - "@firebase/firestore-compat": "0.3.33", + "@firebase/auth": "1.7.6", + "@firebase/auth-compat": "0.5.11", + "@firebase/database": "1.0.7", + "@firebase/database-compat": "1.0.7", + "@firebase/firestore": "4.6.5", + "@firebase/firestore-compat": "0.3.34", "@firebase/functions": "0.11.6", "@firebase/functions-compat": "0.3.12", "@firebase/installations": "0.6.8", @@ -10496,6 +10465,7 @@ "resolved": "https://registry.npmjs.org/glob/-/glob-9.3.5.tgz", "integrity": "sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==", "dev": true, + "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", "minimatch": "^8.0.2", @@ -10526,6 +10496,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-8.0.4.tgz", "integrity": "sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -10851,7 +10822,8 @@ "node_modules/http-parser-js": { "version": "0.5.8", "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", - "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==" + "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==", + "license": "MIT" }, "node_modules/https-browserify": { "version": "1.0.0", @@ -10890,9 +10862,9 @@ } }, "node_modules/i18next": { - "version": "23.12.2", - "resolved": "https://registry.npmjs.org/i18next/-/i18next-23.12.2.tgz", - "integrity": "sha512-XIeh5V+bi8SJSWGL3jqbTEBW5oD6rbP5L+E7dVQh1MNTxxYef0x15rhJVcRb7oiuq4jLtgy2SD8eFlf6P2cmqg==", + "version": "23.12.3", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-23.12.3.tgz", + "integrity": "sha512-DyigQmrR10V9U2N6pjhbfahW13GY7n8BQD9swN09JuRRropgsksWVi4vRLeex0Qf7zCPnBfIqQfhcBzdZBQBYw==", "funding": [ { "type": "individual", @@ -10907,6 +10879,7 @@ "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project" } ], + "license": "MIT", "dependencies": { "@babel/runtime": "^7.23.2" } @@ -11073,6 +11046,7 @@ "version": "4.28.5", "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-4.28.5.tgz", "integrity": "sha512-3GYo0GJtLqgNXj4YhrisLaNNvWSNwSS2wS4OELGfGxH8I69+XfNdnmV1AyN+ZqMh0i7eX+SWjrwFKDBDgfBC1A==", + "license": "MIT", "dependencies": { "cluster-key-slot": "^1.1.0", "debug": "^4.3.1", @@ -11234,6 +11208,7 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "engines": { "node": ">=4" } @@ -11422,11 +11397,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-lite": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-lite/-/is-lite-1.2.1.tgz", - "integrity": "sha512-pgF+L5bxC+10hLBgf6R2P4ZZUBOQIIacbdo8YvuCP8/JvsWxG7aZ9p10DYuLtifFci4l3VITphhMlMV4Y+urPw==" - }, "node_modules/is-map": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", @@ -11807,6 +11777,7 @@ "version": "3.14.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "license": "MIT", "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" @@ -11819,6 +11790,7 @@ "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "license": "MIT", "dependencies": { "sprintf-js": "~1.0.2" } @@ -11864,12 +11836,6 @@ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true }, - "node_modules/json-schema-typed": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/json-schema-typed/-/json-schema-typed-7.0.3.tgz", - "integrity": "sha512-7DE8mpG+/fVw+dTpjbxnx47TaMnDfOI1jwft9g1VybltZCduyRQPJPvc+zzKY9WPHxhPWczyFuYa6I8Mw4iU5A==", - "dev": true - }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", @@ -11982,9 +11948,10 @@ } }, "node_modules/libphonenumber-js": { - "version": "1.11.4", - "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.11.4.tgz", - "integrity": "sha512-F/R50HQuWWYcmU/esP5jrH5LiWYaN7DpN0a/99U8+mnGGtnx8kmRE+649dQh3v+CowXXZc8vpkf5AmYkO0AQ7Q==" + "version": "1.11.5", + "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.11.5.tgz", + "integrity": "sha512-TwHR5BZxGRODtAfz03szucAkjT5OArXr+94SMtAM2pYXIlQNVMrxvb6uSCbnaJJV6QXEyICk7+l6QPgn72WHhg==", + "license": "MIT" }, "node_modules/lie": { "version": "3.1.1", @@ -12078,7 +12045,8 @@ "node_modules/lodash.camelcase": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", - "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==" + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", + "license": "MIT" }, "node_modules/lodash.debounce": { "version": "4.0.8", @@ -12089,27 +12057,32 @@ "node_modules/lodash.defaults": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", - "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==" + "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==", + "license": "MIT" }, "node_modules/lodash.eq": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/lodash.eq/-/lodash.eq-4.0.0.tgz", - "integrity": "sha512-vbrJpXL6kQNG6TkInxX12DZRfuYVllSxhwYqjYB78g2zF3UI15nFO/0AgmZnZRnaQ38sZtjCiVjGr2rnKt4v0g==" + "integrity": "sha512-vbrJpXL6kQNG6TkInxX12DZRfuYVllSxhwYqjYB78g2zF3UI15nFO/0AgmZnZRnaQ38sZtjCiVjGr2rnKt4v0g==", + "license": "MIT" }, "node_modules/lodash.flatten": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", - "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==" + "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==", + "license": "MIT" }, "node_modules/lodash.indexof": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/lodash.indexof/-/lodash.indexof-4.0.5.tgz", - "integrity": "sha512-t9wLWMQsawdVmf6/IcAgVGqAJkNzYVcn4BHYZKTPW//l7N5Oq7Bq138BaVk19agcsPZePcidSgTTw4NqS1nUAw==" + "integrity": "sha512-t9wLWMQsawdVmf6/IcAgVGqAJkNzYVcn4BHYZKTPW//l7N5Oq7Bq138BaVk19agcsPZePcidSgTTw4NqS1nUAw==", + "license": "MIT" }, "node_modules/lodash.isarguments": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", - "integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==" + "integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==", + "license": "MIT" }, "node_modules/lodash.isequal": { "version": "4.5.0", @@ -12119,7 +12092,8 @@ "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true }, "node_modules/lodash.once": { "version": "4.1.1", @@ -12216,14 +12190,16 @@ } }, "node_modules/logrocket": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/logrocket/-/logrocket-8.1.1.tgz", - "integrity": "sha512-7k2ZZPe35GwdJssk2+xWYfFOi7/EpIwvGHxZHvilWfqkRfEoe/Ntx0DUVfkzn0V+/l7rg1VPQwAlystLMeqCwA==" + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/logrocket/-/logrocket-8.1.2.tgz", + "integrity": "sha512-9D9ZiDkRkoDqjY/vV5L31Ry7dtNRDGiEFniPWmDUILBRdrCX/kPTMjXlD/RdHd/mUbRYM827lXJBIuoVHpShtA==", + "license": "MIT" }, "node_modules/long": { "version": "5.2.3", "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", - "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==" + "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==", + "license": "Apache-2.0" }, "node_modules/longest-streak": { "version": "3.1.0", @@ -12462,13 +12438,14 @@ } }, "node_modules/memfs": { - "version": "4.9.3", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.9.3.tgz", - "integrity": "sha512-bsYSSnirtYTWi1+OPMFb0M048evMKyUYe0EbtuGQgq6BVQM1g1W8/KIUJCCvjgI/El0j6Q4WsmMiBwLUBSw8LA==", + "version": "4.11.1", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.11.1.tgz", + "integrity": "sha512-LZcMTBAgqUUKNXZagcZxvXXfgF1bHX7Y7nQ0QyEiNbRJgE29GhgPd8Yna1VQcLlPiHt/5RFJMWYN9Uv/VPNvjQ==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@jsonjoy.com/json-pack": "^1.0.3", - "@jsonjoy.com/util": "^1.1.2", + "@jsonjoy.com/util": "^1.3.0", "tree-dump": "^1.0.1", "tslib": "^2.0.0" }, @@ -12989,15 +12966,6 @@ "node": ">= 0.6" } }, - "node_modules/mimic-fn": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-3.1.0.tgz", - "integrity": "sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/minimalistic-assert": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", @@ -13035,6 +13003,7 @@ "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.8.tgz", "integrity": "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==", "dev": true, + "license": "ISC", "engines": { "node": ">=8" } @@ -13143,9 +13112,10 @@ } }, "node_modules/node-releases": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", - "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==" + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", + "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", + "license": "MIT" }, "node_modules/node-stdlib-browser": { "version": "1.2.0", @@ -13544,15 +13514,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", - "engines": { - "node": ">=6" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -13726,6 +13688,7 @@ "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", "dev": true, + "license": "BlueOak-1.0.0", "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" @@ -13741,13 +13704,15 @@ "version": "10.4.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/path-scurry/node_modules/minipass": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", "dev": true, + "license": "ISC", "engines": { "node": ">=16 || 14 >=14.17" } @@ -13819,89 +13784,6 @@ "node": ">=0.10.0" } }, - "node_modules/pkg-up": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz", - "integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==", - "dev": true, - "dependencies": { - "find-up": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-up/node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "dependencies": { - "locate-path": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/pkg-up/node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/pkg-up/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pkg-up/node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "dependencies": { - "p-limit": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/pkg-up/node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/popper.js": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz", - "integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==", - "deprecated": "You can find the new Popper v2 at @popperjs/core, this package is dedicated to the legacy v1", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/popperjs" - } - }, "node_modules/possible-typed-array-names": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", @@ -14039,6 +13921,7 @@ "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.3.2.tgz", "integrity": "sha512-RXyHaACeqXeqAKGLDl68rQKbmObRsTIn4TYVUUug1KfS47YWCo5MacGITEryugIgZqORCvJWEk4l449POg5Txg==", "hasInstallScript": true, + "license": "BSD-3-Clause", "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", @@ -14108,9 +13991,10 @@ } }, "node_modules/query-string": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/query-string/-/query-string-9.0.0.tgz", - "integrity": "sha512-4EWwcRGsO2H+yzq6ddHcVqkCQ2EFUSfDMEjF8ryp8ReymyZhIuaFRGLomeOQLkrzacMHoyky2HW0Qe30UbzkKw==", + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-9.1.0.tgz", + "integrity": "sha512-t6dqMECpCkqfyv2FfwVS1xcB6lgXW/0XZSaKdsCNGYkqMO76AFiJEg4vINzoDKcZa6MS7JX+OHIjwh06K5vczw==", + "license": "MIT", "dependencies": { "decode-uri-component": "^0.4.1", "filter-obj": "^5.1.0", @@ -14284,9 +14168,10 @@ } }, "node_modules/rc-field-form": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/rc-field-form/-/rc-field-form-2.2.1.tgz", - "integrity": "sha512-uoNqDoR7A4tn4QTSqoWPAzrR7ZwOK5I+vuZ/qdcHtbKx+ZjEsTg7QXm2wk/jalDiSksAQmATxL0T5LJkRREdIA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/rc-field-form/-/rc-field-form-2.3.0.tgz", + "integrity": "sha512-QyiYrE3uweGGi21MJpxHFmDW+Tb1yt5hitM1k0EbWc5hKDiSf5imOBc6NLLHrYk+sdelrw2Ju/fD4uRQdhSqNg==", + "license": "MIT", "dependencies": { "@babel/runtime": "^7.18.0", "@rc-component/async-validator": "^5.0.3", @@ -14318,9 +14203,10 @@ } }, "node_modules/rc-input": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/rc-input/-/rc-input-1.5.1.tgz", - "integrity": "sha512-+nOzQJDeIfIpNP/SgY45LXSKbuMlp4Yap2y8c+ZpU7XbLmNzUd6+d5/S75sA/52jsVE6S/AkhkkDEAOjIu7i6g==", + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/rc-input/-/rc-input-1.6.3.tgz", + "integrity": "sha512-wI4NzuqBS8vvKr8cljsvnTUqItMfG1QbJoxovCgL+DX4eVUcHIjVwharwevIxyy7H/jbLryh+K7ysnJr23aWIA==", + "license": "MIT", "dependencies": { "@babel/runtime": "^7.11.1", "classnames": "^2.2.1", @@ -14332,14 +14218,15 @@ } }, "node_modules/rc-input-number": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/rc-input-number/-/rc-input-number-9.1.0.tgz", - "integrity": "sha512-NqJ6i25Xn/AgYfVxynlevIhX3FuKlMwIFpucGG1h98SlK32wQwDK0zhN9VY32McOmuaqzftduNYWWooWz8pXQA==", + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/rc-input-number/-/rc-input-number-9.2.0.tgz", + "integrity": "sha512-5XZFhBCV5f9UQ62AZ2hFbEY8iZT/dm23Q1kAg0H8EvOgD3UDbYYJAayoVIkM3lQaCqYAW5gV0yV3vjw1XtzWHg==", + "license": "MIT", "dependencies": { "@babel/runtime": "^7.10.1", "@rc-component/mini-decimal": "^1.0.1", "classnames": "^2.2.5", - "rc-input": "~1.5.0", + "rc-input": "~1.6.0", "rc-util": "^5.40.1" }, "peerDependencies": { @@ -14348,16 +14235,17 @@ } }, "node_modules/rc-mentions": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/rc-mentions/-/rc-mentions-2.14.0.tgz", - "integrity": "sha512-qKR59FMuF8PK4ZqsbWX3UuA5P1M/snzyqV6Yt3y1DCFbCEdqUGIBgQp6vEfLCO6Z0RoRFlzXtCeSlBTcDDpg1A==", + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/rc-mentions/-/rc-mentions-2.15.0.tgz", + "integrity": "sha512-f5v5i7VdqvBDXbphoqcQWmXDif2Msd2arritVoWybrVDuHE6nQ7XCYsybHbV//WylooK52BFDouFvyaRDtXZEw==", + "license": "MIT", "dependencies": { "@babel/runtime": "^7.22.5", "@rc-component/trigger": "^2.0.0", "classnames": "^2.2.6", - "rc-input": "~1.5.0", + "rc-input": "~1.6.0", "rc-menu": "~9.14.0", - "rc-textarea": "~1.7.0", + "rc-textarea": "~1.8.0", "rc-util": "^5.34.1" }, "peerDependencies": { @@ -14444,9 +14332,10 @@ } }, "node_modules/rc-picker": { - "version": "4.6.9", - "resolved": "https://registry.npmjs.org/rc-picker/-/rc-picker-4.6.9.tgz", - "integrity": "sha512-kwQq5xDNJ1VcX7pauLlVBiuQorpZGUwA/YczVJTO1e33YsTyDuVjaQkYAiAupXbEPUBCU3doGZo0J25HGq2ZOQ==", + "version": "4.6.13", + "resolved": "https://registry.npmjs.org/rc-picker/-/rc-picker-4.6.13.tgz", + "integrity": "sha512-yi4JWPGjm420Q8rHjZ6YNy2c5IfV+9EAzx2pewVRPOjJqfg7uifO/Z0uqxdl/h6AhBocuvRvtlyz6ehrAvTq7A==", + "license": "MIT", "dependencies": { "@babel/runtime": "^7.24.7", "@rc-component/trigger": "^2.0.0", @@ -14564,9 +14453,10 @@ } }, "node_modules/rc-slider": { - "version": "10.6.2", - "resolved": "https://registry.npmjs.org/rc-slider/-/rc-slider-10.6.2.tgz", - "integrity": "sha512-FjkoFjyvUQWcBo1F3RgSglky3ar0+qHLM41PlFVYB4Bj3RD8E/Mv7kqMouLFBU+3aFglMzzctAIWRwajEuueSw==", + "version": "11.1.5", + "resolved": "https://registry.npmjs.org/rc-slider/-/rc-slider-11.1.5.tgz", + "integrity": "sha512-b77H5PbjMKsvkYXAYIkn50QuFX6ICQmCTibDinI9q+BHx65/TV4TeU25+oadhSRzykxs0/vBWeKBwRyySOeWlg==", + "license": "MIT", "dependencies": { "@babel/runtime": "^7.10.1", "classnames": "^2.2.5", @@ -14653,13 +14543,14 @@ } }, "node_modules/rc-textarea": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/rc-textarea/-/rc-textarea-1.7.0.tgz", - "integrity": "sha512-UxizYJkWkmxP3zofXgc487QiGyDmhhheDLLjIWbFtDmiru1ls30KpO8odDaPyqNUIy9ugj5djxTEuezIn6t3Jg==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/rc-textarea/-/rc-textarea-1.8.1.tgz", + "integrity": "sha512-bm36N2ZqwZAP60ZQg2OY9mPdqWC+m6UTjHc+CqEZOxb3Ia29BGHazY/s5bI8M4113CkqTzhtFUDNA078ZiOx3Q==", + "license": "MIT", "dependencies": { "@babel/runtime": "^7.10.1", "classnames": "^2.2.1", - "rc-input": "~1.5.0", + "rc-input": "~1.6.0", "rc-resize-observer": "^1.0.0", "rc-util": "^5.27.0" }, @@ -14779,9 +14670,10 @@ } }, "node_modules/react-big-calendar": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/react-big-calendar/-/react-big-calendar-1.13.1.tgz", - "integrity": "sha512-6qg2ivBPnGPE+iJTJ6nNG/Kol0XElNzywWkwjjN0GtXjooHcS+9/UnpiCDuKzbele3iB6fWeobkSHWhI6xxKYw==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/react-big-calendar/-/react-big-calendar-1.13.2.tgz", + "integrity": "sha512-yzeVRM1I+JloeJXytrZx2lJWKUfLAi5bsgGuBjh3aFSHZrdFcGnfA7LE6pBacdyOG+NGP+332m2MziszkmQWcw==", + "license": "MIT", "dependencies": { "@babel/runtime": "^7.20.7", "clsx": "^1.2.1", @@ -14823,9 +14715,10 @@ } }, "node_modules/react-cookie": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/react-cookie/-/react-cookie-7.1.4.tgz", - "integrity": "sha512-wDxxa/HYaSXSMlyWJvJ5uZTzIVtQTPf1gMksFgwAz/2/W3lCtY8r4OChCXMPE7wax0PAdMY97UkNJedGv7KnDw==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/react-cookie/-/react-cookie-7.2.0.tgz", + "integrity": "sha512-mqhPERUyfOljq5yJ4woDFI33bjEtigsl8JDJdPPeNhr0eSVZmBc/2Vdf8mFxOUktQxhxTR1T+uF0/FRTZyBEgw==", + "license": "MIT", "dependencies": { "@types/hoist-non-react-statics": "^3.3.5", "hoist-non-react-statics": "^3.3.2", @@ -14875,41 +14768,6 @@ "integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg==", "dev": true }, - "node_modules/react-floater": { - "version": "0.7.9", - "resolved": "https://registry.npmjs.org/react-floater/-/react-floater-0.7.9.tgz", - "integrity": "sha512-NXqyp9o8FAXOATOEo0ZpyaQ2KPb4cmPMXGWkx377QtJkIXHlHRAGer7ai0r0C1kG5gf+KJ6Gy+gdNIiosvSicg==", - "dependencies": { - "deepmerge": "^4.3.1", - "is-lite": "^0.8.2", - "popper.js": "^1.16.0", - "prop-types": "^15.8.1", - "tree-changes": "^0.9.1" - }, - "peerDependencies": { - "react": "15 - 18", - "react-dom": "15 - 18" - } - }, - "node_modules/react-floater/node_modules/@gilbarbara/deep-equal": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@gilbarbara/deep-equal/-/deep-equal-0.1.2.tgz", - "integrity": "sha512-jk+qzItoEb0D0xSSmrKDDzf9sheQj/BAPxlgNxgmOaA3mxpUa6ndJLYGZKsJnIVEQSD8zcTbyILz7I0HcnBCRA==" - }, - "node_modules/react-floater/node_modules/is-lite": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/is-lite/-/is-lite-0.8.2.tgz", - "integrity": "sha512-JZfH47qTsslwaAsqbMI3Q6HNNjUuq6Cmzzww50TdP5Esb6e1y2sK2UAaZZuzfAzpoI2AkxoPQapZdlDuP6Vlsw==" - }, - "node_modules/react-floater/node_modules/tree-changes": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/tree-changes/-/tree-changes-0.9.3.tgz", - "integrity": "sha512-vvvS+O6kEeGRzMglTKbc19ltLWNtmNt1cpBoSYLj/iEcPVvpJasemKOlxBrmZaCtDJoF+4bwv3m01UKYi8mukQ==", - "dependencies": { - "@gilbarbara/deep-equal": "^0.1.1", - "is-lite": "^0.8.2" - } - }, "node_modules/react-grid-gallery": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/react-grid-gallery/-/react-grid-gallery-1.0.1.tgz", @@ -14956,9 +14814,10 @@ } }, "node_modules/react-icons": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.2.1.tgz", - "integrity": "sha512-zdbW5GstTzXaVKvGSyTaBalt7HSfuK5ovrzlpyiWHAFXndXTdd/1hdDHI4xBM1Mn7YriT6aqESucFl9kEXzrdw==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.3.0.tgz", + "integrity": "sha512-DnUk8aFbTyQPSkCfF8dbX6kQjXA9DktMeJqfjrg6cK9vwQVMxmcA3BfP4QoiztVmEHtwlTgLFsPuH2NskKT6eg==", + "license": "MIT", "peerDependencies": { "react": "*" } @@ -14977,53 +14836,11 @@ "react-dom": "16.x || 17.x" } }, - "node_modules/react-innertext": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/react-innertext/-/react-innertext-1.1.5.tgz", - "integrity": "sha512-PWAqdqhxhHIv80dT9znP2KvS+hfkbRovFp4zFYHFFlOoQLRiawIic81gKb3U1wEyJZgMwgs3JoLtwryASRWP3Q==", - "peerDependencies": { - "@types/react": ">=0.0.0 <=99", - "react": ">=0.0.0 <=99" - } - }, "node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, - "node_modules/react-joyride": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/react-joyride/-/react-joyride-2.8.2.tgz", - "integrity": "sha512-2QY8HB1G0I2OT0PKMUz7gg2HAjdkG2Bqi13r0Bb1V16PAwfb9khn4wWBTOJsGsjulbAWiQ3/0YrgNUHGFmuifw==", - "dependencies": { - "@gilbarbara/deep-equal": "^0.3.1", - "deep-diff": "^1.0.2", - "deepmerge": "^4.3.1", - "is-lite": "^1.2.1", - "react-floater": "^0.7.9", - "react-innertext": "^1.1.5", - "react-is": "^16.13.1", - "scroll": "^3.0.1", - "scrollparent": "^2.1.0", - "tree-changes": "^0.11.2", - "type-fest": "^4.18.2" - }, - "peerDependencies": { - "react": "15 - 18", - "react-dom": "15 - 18" - } - }, - "node_modules/react-joyride/node_modules/type-fest": { - "version": "4.18.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.18.3.tgz", - "integrity": "sha512-Q08/0IrpvM+NMY9PA2rti9Jb+JejTddwmwmVQGskAlhtcrw1wsRzoR6ode6mR+OAabNa75w/dxedSUY2mlphaQ==", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/react-lifecycles-compat": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", @@ -15175,11 +14992,12 @@ } }, "node_modules/react-router": { - "version": "6.25.1", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.25.1.tgz", - "integrity": "sha512-u8ELFr5Z6g02nUtpPAggP73Jigj1mRePSwhS/2nkTrlPU5yEkH1vYzWNyvSnSzeeE2DNqWdH+P8OhIh9wuXhTw==", + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.26.0.tgz", + "integrity": "sha512-wVQq0/iFYd3iZ9H2l3N3k4PL8EEHcb0XlU2Na8nEwmiXgIUElEH6gaJDtUQxJ+JFzmIXaQjfdpcGWaM6IoQGxg==", + "license": "MIT", "dependencies": { - "@remix-run/router": "1.18.0" + "@remix-run/router": "1.19.0" }, "engines": { "node": ">=14.0.0" @@ -15189,12 +15007,13 @@ } }, "node_modules/react-router-dom": { - "version": "6.25.1", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.25.1.tgz", - "integrity": "sha512-0tUDpbFvk35iv+N89dWNrJp+afLgd+y4VtorJZuOCXK0kkCWjEvb3vTJM++SYvMEpbVwXKf3FjeVveVEb6JpDQ==", + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.26.0.tgz", + "integrity": "sha512-RRGUIiDtLrkX3uYcFiCIxKFWMcWQGMojpYZfcstc63A1+sSnVgILGIm9gNUA6na3Fm1QuPGSBQH2EMbAZOnMsQ==", + "license": "MIT", "dependencies": { - "@remix-run/router": "1.18.0", - "react-router": "6.25.1" + "@remix-run/router": "1.19.0", + "react-router": "6.26.0" }, "engines": { "node": ">=14.0.0" @@ -15264,9 +15083,10 @@ } }, "node_modules/react-virtuoso": { - "version": "4.7.12", - "resolved": "https://registry.npmjs.org/react-virtuoso/-/react-virtuoso-4.7.12.tgz", - "integrity": "sha512-q8yaykkVJGJbPNQH2Hgm82ik0LsbNGJpHMEjAGz5ibEsTVHKObs5WtEELAd1A99OKFHs091W1M+HN+1sasL08Q==", + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/react-virtuoso/-/react-virtuoso-4.10.1.tgz", + "integrity": "sha512-vDBt9AarmCjPNshw3VxPXW355ZQKSO0p9vrAJ0pi04TB6aXk+qHWTu8NuaQ3ppcd/Ub1r5ryRA4fJ2QGuH0H0g==", + "license": "MIT", "engines": { "node": ">=10" }, @@ -15349,12 +15169,14 @@ "node_modules/redis-commands": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.7.0.tgz", - "integrity": "sha512-nJWqw3bTFy21hX/CPKHth6sfhZbdiHP6bTawSgQBlKOVRG7EZkfHbbHwQJnrE4vsQf0CMNE+3gJ4Fmm16vdVlQ==" + "integrity": "sha512-nJWqw3bTFy21hX/CPKHth6sfhZbdiHP6bTawSgQBlKOVRG7EZkfHbbHwQJnrE4vsQf0CMNE+3gJ4Fmm16vdVlQ==", + "license": "MIT" }, "node_modules/redis-errors": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", "integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==", + "license": "MIT", "engines": { "node": ">=4" } @@ -15363,6 +15185,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", "integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==", + "license": "MIT", "dependencies": { "redis-errors": "^1.0.0" }, @@ -15381,9 +15204,10 @@ "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==" }, "node_modules/redux-actions": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/redux-actions/-/redux-actions-3.0.0.tgz", - "integrity": "sha512-5r+G8JizsTfyfWolVDkCLL2SpZA0Sk9ao2MXwfdXkG5+72s0PcO9qEqpo51D2o8dZY2gXLjNmY5yoRB+BuizRw==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/redux-actions/-/redux-actions-3.0.3.tgz", + "integrity": "sha512-ca+ySXmXWrxDqtauRA6lQtjmRO8Z9Ruog3wbb8wDq4RVW9Y677Nl/AXoJPlxJqH0mpY9QGkg03NkAJwTcyN2pQ==", + "license": "MIT", "dependencies": { "just-curry-it": "5.3.0", "reduce-reducers": "1.0.4" @@ -15439,7 +15263,8 @@ "node_modules/reflect-metadata": { "version": "0.1.14", "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.14.tgz", - "integrity": "sha512-ZhYeb6nRaXCfhnndflDK8qI6ZQ/YcWZCISRAWICW9XYqMUwjZM9Z0DveWX/ABN01oxSHwVxKQmxeYZSsm0jh5A==" + "integrity": "sha512-ZhYeb6nRaXCfhnndflDK8qI6ZQ/YcWZCISRAWICW9XYqMUwjZM9Z0DveWX/ABN01oxSHwVxKQmxeYZSsm0jh5A==", + "license": "Apache-2.0" }, "node_modules/reflect.getprototypeof": { "version": "1.0.6", @@ -15910,11 +15735,6 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true }, - "node_modules/safevalues": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/safevalues/-/safevalues-0.6.0.tgz", - "integrity": "sha512-MZ7DcTOcIoPXN36/UONVE9BT0pmwlCr9WcS7Pj/q4FxOwr33FkWC0CUWj/THQXYWxf/F7urbhaHaOeFPSqGqHA==" - }, "node_modules/sass": { "version": "1.77.8", "resolved": "https://registry.npmjs.org/sass/-/sass-1.77.8.tgz", @@ -15939,11 +15759,6 @@ "loose-envify": "^1.1.0" } }, - "node_modules/scroll": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/scroll/-/scroll-3.0.1.tgz", - "integrity": "sha512-pz7y517OVls1maEzlirKO5nPYle9AXsFzTMNJrRGmT951mzpIBy7sNHOg5o/0MQd/NqliCiWnAi0kZneMPFLcg==" - }, "node_modules/scroll-into-view-if-needed": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-3.1.0.tgz", @@ -15952,15 +15767,11 @@ "compute-scroll-into-view": "^3.0.2" } }, - "node_modules/scrollparent": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/scrollparent/-/scrollparent-2.1.0.tgz", - "integrity": "sha512-bnnvJL28/Rtz/kz2+4wpBjHzWoEzXhVg/TE8BeVGJHUqE8THNIRnDxDWMktwM+qahvlRdvlLdsQfYe+cuqfZeA==" - }, "node_modules/seedrandom": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-3.0.5.tgz", - "integrity": "sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==" + "integrity": "sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==", + "license": "MIT" }, "node_modules/semver": { "version": "7.5.4", @@ -16337,7 +16148,8 @@ "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "license": "BSD-3-Clause" }, "node_modules/sshpk": { "version": "1.18.0", @@ -16376,7 +16188,8 @@ "node_modules/standard-as-callback": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz", - "integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==" + "integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==", + "license": "MIT" }, "node_modules/stream-browserify": { "version": "3.0.0", @@ -16747,6 +16560,7 @@ "version": "2.2.5", "resolved": "https://registry.npmjs.org/swr/-/swr-2.2.5.tgz", "integrity": "sha512-QtxqyclFeAsxEUeZIYmsaQ0UjimSq1RZ9Un7I68/0ClKK/U3LoyQunwkQfJZr2fc22DfIXLNDc2wFyTEikCUpg==", + "license": "MIT", "dependencies": { "client-only": "^0.0.1", "use-sync-external-store": "^1.2.0" @@ -16962,6 +16776,33 @@ "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.6.0.tgz", "integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==" }, + "node_modules/tinyglobby": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.2.tgz", + "integrity": "sha512-mZ2sDMaySvi1PkTp4lTo1In2zjU+cY8OvZsfwrDrx3YGRbXPX1/cbPwCR9zkm3O/Fz9Jo0F1HNgIQ1b8BepqyQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "fdir": "^6.2.0", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/tmp": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", @@ -17000,15 +16841,6 @@ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" }, - "node_modules/tree-changes": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/tree-changes/-/tree-changes-0.11.2.tgz", - "integrity": "sha512-4gXlUthrl+RabZw6lLvcCDl6KfJOCmrC16BC5CRdut1EAH509Omgg0BfKLY+ViRlzrvYOTWR0FMS2SQTwzumrw==", - "dependencies": { - "@gilbarbara/deep-equal": "^0.3.1", - "is-lite": "^1.2.0" - } - }, "node_modules/tree-dump": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/tree-dump/-/tree-dump-1.0.1.tgz", @@ -17299,7 +17131,8 @@ "node_modules/unfetch": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/unfetch/-/unfetch-4.2.0.tgz", - "integrity": "sha512-F9p7yYCn6cIW9El1zi0HI6vqpeIvBsr3dSuRO6Xuppb1u5rXpCPmMvLSyECLhybr9isec8Ohl0hPekMVrEinDA==" + "integrity": "sha512-F9p7yYCn6cIW9El1zi0HI6vqpeIvBsr3dSuRO6Xuppb1u5rXpCPmMvLSyECLhybr9isec8Ohl0hPekMVrEinDA==", + "license": "MIT" }, "node_modules/unicode-canonical-property-names-ecmascript": { "version": "2.0.0", @@ -17483,6 +17316,7 @@ "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.0.1.tgz", "integrity": "sha512-aqrHaVBWW1JVKBHmGo33T5TxeL0qWzfvjWokObHA9bYmN7eNDkwOxmLjhioHl9878qDFMAaT51XNroRyuz7WxA==", "dev": true, + "license": "MIT", "dependencies": { "acorn": "^8.8.1", "chokidar": "^3.5.3", @@ -17623,9 +17457,10 @@ } }, "node_modules/userpilot": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/userpilot/-/userpilot-1.3.2.tgz", - "integrity": "sha512-J+PZGWZbINDrnSlFMNRoAuUA9Lxp4V+wy4tQs0fINnLwlDYcfW86gL3NnF2fYK7eOzWFmBPl4xmUf9XPNRlUMw==", + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/userpilot/-/userpilot-1.3.5.tgz", + "integrity": "sha512-YW0Yiexm/P+eDZG9PJZ0nw1gS80uqJ+UlPeD4/Y0BAR/N7Ib9xQW5TGmUYeSM8Ltw2wUAWkRkAwsheWd2NwCjA==", + "license": "MIT", "dependencies": { "@ndhoule/includes": "^2.0.1", "@ndhoule/pick": "^2.0.0", @@ -17716,13 +17551,14 @@ } }, "node_modules/vite": { - "version": "5.3.4", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.3.4.tgz", - "integrity": "sha512-Cw+7zL3ZG9/NZBB8C+8QbQZmR54GwqIz+WMI4b3JgdYJvX+ny9AjJXqkGQlDXSXRP9rP0B4tbciRMOVEKulVOA==", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.0.tgz", + "integrity": "sha512-5xokfMX0PIiwCMCMb9ZJcMyh5wbBun0zUzKib+L65vAZ8GY9ePZMXxFrHbr/Kyll2+LSCY7xtERPpxkBDKngwg==", "dev": true, + "license": "MIT", "dependencies": { "esbuild": "^0.21.3", - "postcss": "^8.4.39", + "postcss": "^8.4.40", "rollup": "^4.13.0" }, "bin": { @@ -17742,6 +17578,7 @@ "less": "*", "lightningcss": "^1.21.0", "sass": "*", + "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.4.0" @@ -17759,6 +17596,9 @@ "sass": { "optional": true }, + "sass-embedded": { + "optional": true + }, "stylus": { "optional": true }, @@ -17891,14 +17731,15 @@ } }, "node_modules/vite-plugin-pwa": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/vite-plugin-pwa/-/vite-plugin-pwa-0.20.0.tgz", - "integrity": "sha512-/kDZyqF8KqoXRpMUQtR5Atri/7BWayW8Gp7Kz/4bfstsV6zSFTxjREbXZYL7zSuRL40HGA+o2hvUAFRmC+bL7g==", + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/vite-plugin-pwa/-/vite-plugin-pwa-0.20.1.tgz", + "integrity": "sha512-M6Pk4b18i5ryrhKgiIF8Zud0HGphYiCbEfLsCdlvmwn/CEnS6noVwfIDG/+3V7r6yxpPV/gLiKw+rIlCCiCCoQ==", "dev": true, + "license": "MIT", "dependencies": { "debug": "^4.3.4", - "fast-glob": "^3.3.2", "pretty-bytes": "^6.1.1", + "tinyglobby": "^0.2.0", "workbox-build": "^7.1.0", "workbox-window": "^7.1.0" }, @@ -17995,9 +17836,9 @@ } }, "node_modules/vite/node_modules/postcss": { - "version": "8.4.39", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.39.tgz", - "integrity": "sha512-0vzE+lAiG7hZl1/9I8yzKLx3aR9Xbof3fBHKunvMfOCYAtMhrsnccJY2iTURb9EZd5+pLuiNV9/c/GZJOHsgIw==", + "version": "8.4.41", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.41.tgz", + "integrity": "sha512-TesUflQ0WKZqAvg52PWL6kHgLKP6xB6heTOdoYM0Wt2UHyxNa4K25EZZMgKns3BH1RLVbZCREPpLY0rhnNoHVQ==", "dev": true, "funding": [ { @@ -18013,6 +17854,7 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { "nanoid": "^3.3.7", "picocolors": "^1.0.1", @@ -18059,6 +17901,7 @@ "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", "dev": true, + "license": "MIT", "engines": { "node": ">=10.13.0" } @@ -18067,12 +17910,14 @@ "version": "0.5.0", "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.5.0.tgz", "integrity": "sha512-kyDivFZ7ZM0BVOUteVbDFhlRt7Ah/CSPwJdi8hBpkK7QLumUqdLtVfm/PX/hkcnrvr0i77fO5+TjZ94Pe+C9iw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/websocket-driver": { "version": "0.7.4", "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "license": "Apache-2.0", "dependencies": { "http-parser-js": ">=0.5.1", "safe-buffer": ">=5.1.0", @@ -18086,6 +17931,7 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "license": "Apache-2.0", "engines": { "node": ">=0.8.0" } @@ -18681,6 +18527,7 @@ "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "license": "MIT", "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", @@ -18698,6 +18545,7 @@ "version": "21.1.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "license": "ISC", "engines": { "node": ">=12" } diff --git a/client/package.json b/client/package.json index 892ac7bf4..42f26736d 100644 --- a/client/package.json +++ b/client/package.json @@ -8,22 +8,22 @@ "private": true, "proxy": "http://localhost:4000", "dependencies": { - "@ant-design/pro-layout": "^7.19.11", - "@apollo/client": "^3.10.8", + "@ant-design/pro-layout": "^7.19.12", + "@apollo/client": "^3.11.4", "@emotion/is-prop-valid": "^1.3.0", "@fingerprintjs/fingerprintjs": "^4.4.3", "@jsreport/browser-client": "^3.1.0", - "@reduxjs/toolkit": "^2.2.6", - "@sentry/cli": "^2.32.2", + "@reduxjs/toolkit": "^2.2.7", + "@sentry/cli": "^2.33.1", "@sentry/react": "^7.114.0", - "@splitsoftware/splitio-react": "^1.12.0", + "@splitsoftware/splitio-react": "^1.12.1", "@tanem/react-nprogress": "^5.0.51", "@vitejs/plugin-react": "^4.3.1", - "antd": "^5.19.3", + "antd": "^5.20.1", "apollo-link-logger": "^2.0.1", "apollo-link-sentry": "^3.3.0", "autosize": "^6.0.1", - "axios": "^1.6.8", + "axios": "^1.7.4", "classnames": "^2.5.1", "css-box-model": "^1.2.1", "dayjs": "^1.11.12", @@ -32,45 +32,44 @@ "dotenv": "^16.4.5", "env-cmd": "^10.1.0", "exifr": "^7.1.3", - "firebase": "^10.12.4", + "firebase": "^10.12.5", "graphql": "^16.9.0", - "i18next": "^23.12.2", + "i18next": "^23.12.3", "i18next-browser-languagedetector": "^8.0.0", "immutability-helper": "^3.1.1", - "libphonenumber-js": "^1.11.4", - "logrocket": "^8.1.1", + "libphonenumber-js": "^1.11.5", + "logrocket": "^8.1.2", "markerjs2": "^2.32.1", "memoize-one": "^6.0.0", "normalize-url": "^8.0.1", "object-hash": "^3.0.0", "prop-types": "^15.8.1", - "query-string": "^9.0.0", + "query-string": "^9.1.0", "raf-schd": "^4.0.3", "react": "^18.3.1", - "react-big-calendar": "^1.13.1", + "react-big-calendar": "^1.13.2", "react-color": "^2.19.3", - "react-cookie": "^7.1.4", + "react-cookie": "^7.2.0", "react-dom": "^18.3.1", "react-drag-listview": "^2.0.0", "react-grid-gallery": "^1.0.1", "react-grid-layout": "1.3.4", "react-i18next": "^14.1.3", - "react-icons": "^5.2.1", + "react-icons": "^5.3.0", "react-image-lightbox": "^5.1.4", - "react-joyride": "^2.8.2", "react-markdown": "^9.0.1", "react-number-format": "^5.4.0", "react-popopo": "^2.1.9", "react-product-fruits": "^2.2.6", "react-redux": "^9.1.2", "react-resizable": "^3.0.5", - "react-router-dom": "^6.25.1", + "react-router-dom": "^6.26.0", "react-sticky": "^6.0.3", "react-virtualized": "^9.22.5", - "react-virtuoso": "^4.7.12", + "react-virtuoso": "^4.10.1", "recharts": "^2.12.7", "redux": "^5.0.1", - "redux-actions": "^3.0.0", + "redux-actions": "^3.0.3", "redux-persist": "^6.0.0", "redux-saga": "^1.3.0", "redux-state-sync": "^3.1.4", @@ -80,7 +79,7 @@ "styled-components": "^6.1.12", "subscriptions-transport-ws": "^0.11.0", "use-memo-one": "^1.1.3", - "userpilot": "^1.3.2", + "userpilot": "^1.3.5", "vite-plugin-ejs": "^1.7.0", "web-vitals": "^3.5.2" }, @@ -131,29 +130,29 @@ "devDependencies": { "@babel/plugin-proposal-private-property-in-object": "^7.21.11", "@babel/preset-react": "^7.24.7", - "@dotenvx/dotenvx": "^1.6.4", + "@dotenvx/dotenvx": "^1.7.0", "@emotion/babel-plugin": "^11.12.0", - "@emotion/react": "^11.12.0", - "@sentry/webpack-plugin": "^2.21.1", + "@emotion/react": "^11.13.0", + "@sentry/webpack-plugin": "^2.22.2", "@testing-library/cypress": "^10.0.2", - "browserslist": "^4.23.2", + "browserslist": "^4.23.3", "browserslist-to-esbuild": "^2.1.1", "cross-env": "^7.0.3", - "cypress": "^13.13.1", + "cypress": "^13.13.3", "eslint": "^8.57.0", "eslint-config-react-app": "^7.0.1", "eslint-plugin-cypress": "^2.15.1", - "memfs": "^4.9.3", + "memfs": "^4.11.1", "os-browserify": "^0.3.0", "react-error-overlay": "6.0.11", "redux-logger": "^3.0.6", "source-map-explorer": "^2.5.3", - "vite": "^5.3.4", + "vite": "^5.4.0", "vite-plugin-babel": "^1.2.0", "vite-plugin-eslint": "^1.8.1", "vite-plugin-legacy": "^2.1.0", "vite-plugin-node-polyfills": "^0.22.0", - "vite-plugin-pwa": "^0.20.0", + "vite-plugin-pwa": "^0.20.1", "vite-plugin-style-import": "^2.0.0" } } diff --git a/client/src/components/dashboard-components/scheduled-out-today/scheduled-out-today.component.jsx b/client/src/components/dashboard-components/scheduled-out-today/scheduled-out-today.component.jsx index 53291552b..f83e2df5d 100644 --- a/client/src/components/dashboard-components/scheduled-out-today/scheduled-out-today.component.jsx +++ b/client/src/components/dashboard-components/scheduled-out-today/scheduled-out-today.component.jsx @@ -36,9 +36,6 @@ export default function DashboardScheduledOutToday({ data, ...cardProps }) { }; }); - console.log("Scheduled Out Today"); - console.dir(scheduledOutToday); - const tvFontSize = 18; const tvFontWeight = "bold"; diff --git a/client/src/components/jobs-list/jobs-list.component.jsx b/client/src/components/jobs-list/jobs-list.component.jsx index 6082055d7..004addbad 100644 --- a/client/src/components/jobs-list/jobs-list.component.jsx +++ b/client/src/components/jobs-list/jobs-list.component.jsx @@ -16,18 +16,15 @@ import useLocalStorage from "../../utils/useLocalStorage"; import AlertComponent from "../alert/alert.component"; import ChatOpenButton from "../chat-open-button/chat-open-button.component"; import OwnerNameDisplay from "../owner-name-display/owner-name-display.component"; -import { setJoyRideSteps } from "../../redux/application/application.actions"; import { OwnerNameDisplayFunction } from "./../owner-name-display/owner-name-display.component"; const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop }); -const mapDispatchToProps = (dispatch) => ({ - setJoyRideSteps: (steps) => dispatch(setJoyRideSteps(steps)) -}); +const mapDispatchToProps = (dispatch) => ({}); -export function JobsList({ bodyshop, setJoyRideSteps }) { +export function JobsList({ bodyshop }) { const searchParams = queryString.parse(useLocation().search); const { selected } = searchParams; const selectedBreakpoint = Object.entries(Grid.useBreakpoint()) diff --git a/client/src/components/update-alert/update-alert.component.jsx b/client/src/components/update-alert/update-alert.component.jsx index 909512c23..70159adda 100644 --- a/client/src/components/update-alert/update-alert.component.jsx +++ b/client/src/components/update-alert/update-alert.component.jsx @@ -1,7 +1,7 @@ import { AlertOutlined } from "@ant-design/icons"; import { Alert, Button, Col, Row, Space } from "antd"; import i18n from "i18next"; -import React from "react"; +import React, { useEffect } from "react"; import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; import { createStructuredSelector } from "reselect"; @@ -12,39 +12,42 @@ import InstanceRenderManager from "../../utils/instanceRenderMgr"; const mapStateToProps = createStructuredSelector({ updateAvailable: selectUpdateAvailable }); + const mapDispatchToProps = (dispatch) => ({ - //setUserLanguage: language => dispatch(setUserLanguage(language)) + // setUserLanguage: language => dispatch(setUserLanguage(language)) }); -export default connect(mapStateToProps, mapDispatchToProps)(UpdateAlert); -const intervalMS = 10 * 60 * 1000; + export function UpdateAlert({ updateAvailable }) { const { t } = useTranslation(); - const { - offlineReady: [ - offlineReady //setOfflineReady - ], - needRefresh: [ - needRefresh //setNeedRefresh - ], + offlineReady: [offlineReady], + needRefresh: [needRefresh], updateServiceWorker } = useRegisterSW({ onRegistered(r) { - // eslint-disable-next-line prefer-template - console.log("SW Registered: " + r); - r && - setInterval(() => { - r.update(); - }, intervalMS); + console.log("SW Registered:", r); + if (r) { + setInterval( + () => { + r.update(); + }, + 10 * 60 * 1000 + ); + } }, onRegisterError(error) { - console.log("SW registration error", error); + console.error("SW registration error", error); } }); - if (import.meta.env.DEV) console.log(`SW Status => Refresh? ${needRefresh} - offlineReady? ${offlineReady}`); + useEffect(() => { + if (import.meta.env.DEV) { + console.log(`SW Status => Refresh? ${needRefresh} - offlineReady? ${offlineReady}`); + } + }, [needRefresh, offlineReady]); if (!needRefresh) return null; + return ( - - @@ -93,3 +87,5 @@ export function UpdateAlert({ updateAvailable }) { /> ); } + +export default connect(mapStateToProps, mapDispatchToProps)(UpdateAlert); diff --git a/client/src/pages/manage/manage.page.component.jsx b/client/src/pages/manage/manage.page.component.jsx index 1fe0a053b..db7146e15 100644 --- a/client/src/pages/manage/manage.page.component.jsx +++ b/client/src/pages/manage/manage.page.component.jsx @@ -12,7 +12,6 @@ import ErrorBoundary from "../../components/error-boundary/error-boundary.compon //import FooterComponent from "../../components/footer/footer.component"; //Component Imports import * as Sentry from "@sentry/react"; -import Joyride from "react-joyride"; import TestComponent from "../../components/_test/test.page"; import HeaderContainer from "../../components/header/header.container"; import LoadingSpinner from "../../components/loading-spinner/loading-spinner.component"; @@ -23,8 +22,6 @@ import { requestForToken } from "../../firebase/firebase.utils"; import { selectBodyshop, selectInstanceConflict } from "../../redux/user/user.selectors"; import UpdateAlert from "../../components/update-alert/update-alert.component"; -import { setJoyRideFinished } from "../../redux/application/application.actions.js"; -import { selectEnableJoyRide, selectJoyRideSteps } from "../../redux/application/application.selectors.js"; import InstanceRenderManager from "../../utils/instanceRenderMgr.js"; import "./manage.page.styles.scss"; @@ -105,16 +102,12 @@ const { Content, Footer } = Layout; const mapStateToProps = createStructuredSelector({ conflict: selectInstanceConflict, - bodyshop: selectBodyshop, - enableJoyRide: selectEnableJoyRide, - joyRideSteps: selectJoyRideSteps + bodyshop: selectBodyshop }); -const mapDispatchToProps = (dispatch) => ({ - setJoyRideFinished: (steps) => dispatch(setJoyRideFinished(steps)) -}); +const mapDispatchToProps = (dispatch) => ({}); -export function Manage({ conflict, bodyshop, enableJoyRide, joyRideSteps, setJoyRideFinished }) { +export function Manage({ conflict, bodyshop }) { const { t } = useTranslation(); const [chatVisible] = useState(false); @@ -583,21 +576,6 @@ export function Manage({ conflict, bodyshop, enableJoyRide, joyRideSteps, setJoy - { - if (props.action === "reset") { - setJoyRideFinished(); - } - }} - /> } showDialog> {PageContent} diff --git a/client/src/redux/application/application.actions.js b/client/src/redux/application/application.actions.js index 89826ea30..7c5485ac5 100644 --- a/client/src/redux/application/application.actions.js +++ b/client/src/redux/application/application.actions.js @@ -67,11 +67,3 @@ export const setUpdateAvailable = (isUpdateAvailable) => ({ type: ApplicationActionTypes.SET_UPDATE_AVAILABLE, payload: isUpdateAvailable }); -export const setJoyRideSteps = (steps) => ({ - type: ApplicationActionTypes.SET_JOYRIDE_STEPS, - payload: steps -}); -export const setJoyRideFinished = () => ({ - type: ApplicationActionTypes.SET_JOYRIDE_FINISHED - //payload: isUpdateAvailable, -}); diff --git a/client/src/redux/application/application.reducer.js b/client/src/redux/application/application.reducer.js index 62090cc1f..421403f19 100644 --- a/client/src/redux/application/application.reducer.js +++ b/client/src/redux/application/application.reducer.js @@ -14,9 +14,7 @@ const INITIAL_STATE = { error: null }, jobReadOnly: false, - partnerVersion: null, - enableJoyRide: false, - joyRideSteps: [] + partnerVersion: null }; const applicationReducer = (state = INITIAL_STATE, action) => { @@ -89,12 +87,6 @@ const applicationReducer = (state = INITIAL_STATE, action) => { case ApplicationActionTypes.SET_PROBLEM_JOBS: { return { ...state, problemJobs: action.payload }; } - case ApplicationActionTypes.SET_JOYRIDE_STEPS: { - return { ...state, enableJoyRide: true, joyRideSteps: action.payload }; - } - case ApplicationActionTypes.SET_JOYRIDE_FINISHED: { - return { ...state, enableJoyRide: false, joyRideSteps: [] }; - } default: return state; } diff --git a/client/src/redux/application/application.selectors.js b/client/src/redux/application/application.selectors.js index f5c1e0770..d81699522 100644 --- a/client/src/redux/application/application.selectors.js +++ b/client/src/redux/application/application.selectors.js @@ -22,5 +22,3 @@ export const selectJobReadOnly = createSelector([selectApplication], (applicatio export const selectOnline = createSelector([selectApplication], (application) => application.online); export const selectProblemJobs = createSelector([selectApplication], (application) => application.problemJobs); export const selectUpdateAvailable = createSelector([selectApplication], (application) => application.updateAvailable); -export const selectEnableJoyRide = createSelector([selectApplication], (application) => application.enableJoyRide); -export const selectJoyRideSteps = createSelector([selectApplication], (application) => application.joyRideSteps); diff --git a/client/src/redux/application/application.types.js b/client/src/redux/application/application.types.js index 3d8e0763b..9b95dd6ee 100644 --- a/client/src/redux/application/application.types.js +++ b/client/src/redux/application/application.types.js @@ -12,8 +12,6 @@ const ApplicationActionTypes = { SET_ONLINE_STATUS: "SET_ONLINE_STATUS", INSERT_AUDIT_TRAIL: "INSERT_AUDIT_TRAIL", SET_PROBLEM_JOBS: "SET_PROBLEM_JOBS", - SET_UPDATE_AVAILABLE: "SET_UPDATE_AVAILABLE", - SET_JOYRIDE_STEPS: "SET_JOYRIDE_STEPS", - SET_JOYRIDE_FINISHED: "SET_JOYRIDE_FINISHED" + SET_UPDATE_AVAILABLE: "SET_UPDATE_AVAILABLE" }; export default ApplicationActionTypes; diff --git a/client/vite.config.js b/client/vite.config.js index 9208812a0..1e935bdf5 100644 --- a/client/vite.config.js +++ b/client/vite.config.js @@ -6,8 +6,6 @@ import * as url from "url"; import { defineConfig } from "vite"; import { ViteEjsPlugin } from "vite-plugin-ejs"; import eslint from "vite-plugin-eslint"; - -//import CompressionPlugin from 'vite-plugin-compression'; import { VitePWA } from "vite-plugin-pwa"; import InstanceRenderManager from "./src/utils/instanceRenderMgr"; @@ -16,7 +14,8 @@ process.env.VITE_APP_GIT_SHA_DATE = new Date().toLocaleString("en-US", { }); const WRONG_CODE = `import { bpfrpt_proptype_WindowScroller } from "../WindowScroller.js";`; -function reactVirtualized() { + +function reactVirtualizedFix() { return { name: "flat:react-virtualized", configResolved: async () => { @@ -37,10 +36,7 @@ function reactVirtualized() { export default defineConfig({ base: "/", plugins: [ - ViteEjsPlugin((viteConfig) => { - // viteConfig is the current Vite resolved config - return { env: viteConfig.env }; - }), + ViteEjsPlugin((viteConfig) => ({ env: viteConfig.env })), VitePWA({ injectRegister: "auto", registerType: "prompt", @@ -60,7 +56,6 @@ export default defineConfig({ description: "The ultimate bodyshop management system.", icons: [ { - //TODO:AIO Ensure that these are correct for Rome and IO. src: InstanceRenderManager({ instance: process.env.VITE_APP_INSTANCE, imex: "favicon.png", @@ -101,7 +96,7 @@ export default defineConfig({ gcm_sender_id: "103953800507" } }), - reactVirtualized(), + reactVirtualizedFix(), react(), eslint() // CompressionPlugin(), //Cloudfront already compresses assets, so not needed. diff --git a/package-lock.json b/package-lock.json index edb487b26..968cc0ac0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,18 +9,18 @@ "version": "0.2.0", "license": "UNLICENSED", "dependencies": { - "@aws-sdk/client-secrets-manager": "^3.616.0", - "@aws-sdk/client-ses": "^3.616.0", - "@aws-sdk/credential-provider-node": "^3.616.0", - "@opensearch-project/opensearch": "^2.10.0", - "aws4": "^1.13.0", - "axios": "^1.7.2", + "@aws-sdk/client-secrets-manager": "^3.629.0", + "@aws-sdk/client-ses": "^3.629.0", + "@aws-sdk/credential-provider-node": "^3.629.0", + "@opensearch-project/opensearch": "^2.11.0", + "aws4": "^1.13.1", + "axios": "^1.7.4", "better-queue": "^3.8.12", "bluebird": "^3.7.2", "body-parser": "^1.20.2", "canvas": "^2.11.2", "chart.js": "^4.4.3", - "cloudinary": "^2.3.0", + "cloudinary": "^2.4.0", "compression": "^1.7.4", "cookie-parser": "^1.4.6", "cors": "2.8.5", @@ -28,24 +28,24 @@ "dinero.js": "^1.9.1", "dotenv": "^16.4.5", "express": "^4.19.2", - "firebase-admin": "^12.2.0", + "firebase-admin": "^12.3.1", "graphql": "^16.9.0", "graphql-request": "^6.1.0", "graylog2": "^0.2.1", "inline-css": "^4.0.2", "intuit-oauth": "^4.1.2", - "json-2-csv": "^5.5.4", + "json-2-csv": "^5.5.5", "lodash": "^4.17.21", "moment": "^2.30.1", "moment-timezone": "^0.5.45", "multer": "^1.4.5-lts.1", "node-mailjet": "^6.0.5", - "node-persist": "^4.0.2", + "node-persist": "^4.0.3", "nodemailer": "^6.9.14", "phone": "^3.1.49", "recursive-diff": "^1.0.9", "rimraf": "^6.0.1", - "soap": "^1.1.0", + "soap": "^1.1.1", "socket.io": "^4.7.5", "ssh2-sftp-client": "^10.0.3", "twilio": "^4.23.0", @@ -180,46 +180,47 @@ } }, "node_modules/@aws-sdk/client-secrets-manager": { - "version": "3.616.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-secrets-manager/-/client-secrets-manager-3.616.0.tgz", - "integrity": "sha512-V8WRJ7eGBm01Y9nYg4KrQJ6fpXZkAfGTR9rtjMOdPSBcAD4hOJ6gisufxAKl9MSfTPLfzqSCb5/wWkIviobRZA==", + "version": "3.629.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-secrets-manager/-/client-secrets-manager-3.629.0.tgz", + "integrity": "sha512-ZZKI9uTQ3WIdbCZK6sveccalLTWgyOZeebi+Gnwl5ztKMk4OfwZKxyhry1DXB8gMrlISniREDb3ZxUZdFNwqfQ==", + "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/client-sso-oidc": "3.616.0", - "@aws-sdk/client-sts": "3.616.0", - "@aws-sdk/core": "3.616.0", - "@aws-sdk/credential-provider-node": "3.616.0", - "@aws-sdk/middleware-host-header": "3.616.0", + "@aws-sdk/client-sso-oidc": "3.629.0", + "@aws-sdk/client-sts": "3.629.0", + "@aws-sdk/core": "3.629.0", + "@aws-sdk/credential-provider-node": "3.629.0", + "@aws-sdk/middleware-host-header": "3.620.0", "@aws-sdk/middleware-logger": "3.609.0", - "@aws-sdk/middleware-recursion-detection": "3.616.0", - "@aws-sdk/middleware-user-agent": "3.616.0", + "@aws-sdk/middleware-recursion-detection": "3.620.0", + "@aws-sdk/middleware-user-agent": "3.620.0", "@aws-sdk/region-config-resolver": "3.614.0", "@aws-sdk/types": "3.609.0", "@aws-sdk/util-endpoints": "3.614.0", "@aws-sdk/util-user-agent-browser": "3.609.0", "@aws-sdk/util-user-agent-node": "3.614.0", "@smithy/config-resolver": "^3.0.5", - "@smithy/core": "^2.2.7", - "@smithy/fetch-http-handler": "^3.2.2", + "@smithy/core": "^2.3.2", + "@smithy/fetch-http-handler": "^3.2.4", "@smithy/hash-node": "^3.0.3", "@smithy/invalid-dependency": "^3.0.3", - "@smithy/middleware-content-length": "^3.0.4", - "@smithy/middleware-endpoint": "^3.0.5", - "@smithy/middleware-retry": "^3.0.10", + "@smithy/middleware-content-length": "^3.0.5", + "@smithy/middleware-endpoint": "^3.1.0", + "@smithy/middleware-retry": "^3.0.14", "@smithy/middleware-serde": "^3.0.3", "@smithy/middleware-stack": "^3.0.3", "@smithy/node-config-provider": "^3.1.4", - "@smithy/node-http-handler": "^3.1.3", - "@smithy/protocol-http": "^4.0.4", - "@smithy/smithy-client": "^3.1.8", + "@smithy/node-http-handler": "^3.1.4", + "@smithy/protocol-http": "^4.1.0", + "@smithy/smithy-client": "^3.1.12", "@smithy/types": "^3.3.0", "@smithy/url-parser": "^3.0.3", "@smithy/util-base64": "^3.0.0", "@smithy/util-body-length-browser": "^3.0.0", "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.10", - "@smithy/util-defaults-mode-node": "^3.0.10", + "@smithy/util-defaults-mode-browser": "^3.0.14", + "@smithy/util-defaults-mode-node": "^3.0.14", "@smithy/util-endpoints": "^2.0.5", "@smithy/util-middleware": "^3.0.3", "@smithy/util-retry": "^3.0.3", @@ -244,46 +245,47 @@ } }, "node_modules/@aws-sdk/client-ses": { - "version": "3.616.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-ses/-/client-ses-3.616.0.tgz", - "integrity": "sha512-GrN5zWLE3gBb9UqSlOkRO/a2NOKODqM8MblGBIRiuLm/thdvzvlUuZOXGzEydhOHq0CqgCiFudYc37ahIKrDWQ==", + "version": "3.629.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-ses/-/client-ses-3.629.0.tgz", + "integrity": "sha512-KreCdUAO/gIzWCgnPV1/dGUvLDDTdXI3fZzjjHUWFa1bE4wENjenNnWGw0qZgc8xB8pgiMdgPn7N+JvxJ7c/ZQ==", + "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/client-sso-oidc": "3.616.0", - "@aws-sdk/client-sts": "3.616.0", - "@aws-sdk/core": "3.616.0", - "@aws-sdk/credential-provider-node": "3.616.0", - "@aws-sdk/middleware-host-header": "3.616.0", + "@aws-sdk/client-sso-oidc": "3.629.0", + "@aws-sdk/client-sts": "3.629.0", + "@aws-sdk/core": "3.629.0", + "@aws-sdk/credential-provider-node": "3.629.0", + "@aws-sdk/middleware-host-header": "3.620.0", "@aws-sdk/middleware-logger": "3.609.0", - "@aws-sdk/middleware-recursion-detection": "3.616.0", - "@aws-sdk/middleware-user-agent": "3.616.0", + "@aws-sdk/middleware-recursion-detection": "3.620.0", + "@aws-sdk/middleware-user-agent": "3.620.0", "@aws-sdk/region-config-resolver": "3.614.0", "@aws-sdk/types": "3.609.0", "@aws-sdk/util-endpoints": "3.614.0", "@aws-sdk/util-user-agent-browser": "3.609.0", "@aws-sdk/util-user-agent-node": "3.614.0", "@smithy/config-resolver": "^3.0.5", - "@smithy/core": "^2.2.7", - "@smithy/fetch-http-handler": "^3.2.2", + "@smithy/core": "^2.3.2", + "@smithy/fetch-http-handler": "^3.2.4", "@smithy/hash-node": "^3.0.3", "@smithy/invalid-dependency": "^3.0.3", - "@smithy/middleware-content-length": "^3.0.4", - "@smithy/middleware-endpoint": "^3.0.5", - "@smithy/middleware-retry": "^3.0.10", + "@smithy/middleware-content-length": "^3.0.5", + "@smithy/middleware-endpoint": "^3.1.0", + "@smithy/middleware-retry": "^3.0.14", "@smithy/middleware-serde": "^3.0.3", "@smithy/middleware-stack": "^3.0.3", "@smithy/node-config-provider": "^3.1.4", - "@smithy/node-http-handler": "^3.1.3", - "@smithy/protocol-http": "^4.0.4", - "@smithy/smithy-client": "^3.1.8", + "@smithy/node-http-handler": "^3.1.4", + "@smithy/protocol-http": "^4.1.0", + "@smithy/smithy-client": "^3.1.12", "@smithy/types": "^3.3.0", "@smithy/url-parser": "^3.0.3", "@smithy/util-base64": "^3.0.0", "@smithy/util-body-length-browser": "^3.0.0", "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.10", - "@smithy/util-defaults-mode-node": "^3.0.10", + "@smithy/util-defaults-mode-browser": "^3.0.14", + "@smithy/util-defaults-mode-node": "^3.0.14", "@smithy/util-endpoints": "^2.0.5", "@smithy/util-middleware": "^3.0.3", "@smithy/util-retry": "^3.0.3", @@ -296,43 +298,44 @@ } }, "node_modules/@aws-sdk/client-sso": { - "version": "3.616.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.616.0.tgz", - "integrity": "sha512-hwW0u1f8U4dSloAe61/eupUiGd5Q13B72BuzGxvRk0cIpYX/2m0KBG8DDl7jW1b2QQ+CflTLpG2XUf2+vRJxGA==", + "version": "3.629.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.629.0.tgz", + "integrity": "sha512-2w8xU4O0Grca5HmT2dXZ5fF0g39RxODtmoqHJDsK5DSt750LqDG4w3ktmBvQs3+SrpkkJOjlX5v/hb2PCxVbww==", + "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.616.0", - "@aws-sdk/middleware-host-header": "3.616.0", + "@aws-sdk/core": "3.629.0", + "@aws-sdk/middleware-host-header": "3.620.0", "@aws-sdk/middleware-logger": "3.609.0", - "@aws-sdk/middleware-recursion-detection": "3.616.0", - "@aws-sdk/middleware-user-agent": "3.616.0", + "@aws-sdk/middleware-recursion-detection": "3.620.0", + "@aws-sdk/middleware-user-agent": "3.620.0", "@aws-sdk/region-config-resolver": "3.614.0", "@aws-sdk/types": "3.609.0", "@aws-sdk/util-endpoints": "3.614.0", "@aws-sdk/util-user-agent-browser": "3.609.0", "@aws-sdk/util-user-agent-node": "3.614.0", "@smithy/config-resolver": "^3.0.5", - "@smithy/core": "^2.2.7", - "@smithy/fetch-http-handler": "^3.2.2", + "@smithy/core": "^2.3.2", + "@smithy/fetch-http-handler": "^3.2.4", "@smithy/hash-node": "^3.0.3", "@smithy/invalid-dependency": "^3.0.3", - "@smithy/middleware-content-length": "^3.0.4", - "@smithy/middleware-endpoint": "^3.0.5", - "@smithy/middleware-retry": "^3.0.10", + "@smithy/middleware-content-length": "^3.0.5", + "@smithy/middleware-endpoint": "^3.1.0", + "@smithy/middleware-retry": "^3.0.14", "@smithy/middleware-serde": "^3.0.3", "@smithy/middleware-stack": "^3.0.3", "@smithy/node-config-provider": "^3.1.4", - "@smithy/node-http-handler": "^3.1.3", - "@smithy/protocol-http": "^4.0.4", - "@smithy/smithy-client": "^3.1.8", + "@smithy/node-http-handler": "^3.1.4", + "@smithy/protocol-http": "^4.1.0", + "@smithy/smithy-client": "^3.1.12", "@smithy/types": "^3.3.0", "@smithy/url-parser": "^3.0.3", "@smithy/util-base64": "^3.0.0", "@smithy/util-body-length-browser": "^3.0.0", "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.10", - "@smithy/util-defaults-mode-node": "^3.0.10", + "@smithy/util-defaults-mode-browser": "^3.0.14", + "@smithy/util-defaults-mode-node": "^3.0.14", "@smithy/util-endpoints": "^2.0.5", "@smithy/util-middleware": "^3.0.3", "@smithy/util-retry": "^3.0.3", @@ -344,44 +347,45 @@ } }, "node_modules/@aws-sdk/client-sso-oidc": { - "version": "3.616.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.616.0.tgz", - "integrity": "sha512-YY1hpYS/G1uRGjQf88dL8VLHkP/IjGxKeXdhy+JnzMdCkAWl3V9j0fEALw40NZe0x79gr6R2KUOUH/IKYQfUmg==", + "version": "3.629.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.629.0.tgz", + "integrity": "sha512-3if0LauNJPqubGYf8vnlkp+B3yAeKRuRNxfNbHlE6l510xWGcKK/ZsEmiFmfePzKKSRrDh/cxMFMScgOrXptNg==", + "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.616.0", - "@aws-sdk/credential-provider-node": "3.616.0", - "@aws-sdk/middleware-host-header": "3.616.0", + "@aws-sdk/core": "3.629.0", + "@aws-sdk/credential-provider-node": "3.629.0", + "@aws-sdk/middleware-host-header": "3.620.0", "@aws-sdk/middleware-logger": "3.609.0", - "@aws-sdk/middleware-recursion-detection": "3.616.0", - "@aws-sdk/middleware-user-agent": "3.616.0", + "@aws-sdk/middleware-recursion-detection": "3.620.0", + "@aws-sdk/middleware-user-agent": "3.620.0", "@aws-sdk/region-config-resolver": "3.614.0", "@aws-sdk/types": "3.609.0", "@aws-sdk/util-endpoints": "3.614.0", "@aws-sdk/util-user-agent-browser": "3.609.0", "@aws-sdk/util-user-agent-node": "3.614.0", "@smithy/config-resolver": "^3.0.5", - "@smithy/core": "^2.2.7", - "@smithy/fetch-http-handler": "^3.2.2", + "@smithy/core": "^2.3.2", + "@smithy/fetch-http-handler": "^3.2.4", "@smithy/hash-node": "^3.0.3", "@smithy/invalid-dependency": "^3.0.3", - "@smithy/middleware-content-length": "^3.0.4", - "@smithy/middleware-endpoint": "^3.0.5", - "@smithy/middleware-retry": "^3.0.10", + "@smithy/middleware-content-length": "^3.0.5", + "@smithy/middleware-endpoint": "^3.1.0", + "@smithy/middleware-retry": "^3.0.14", "@smithy/middleware-serde": "^3.0.3", "@smithy/middleware-stack": "^3.0.3", "@smithy/node-config-provider": "^3.1.4", - "@smithy/node-http-handler": "^3.1.3", - "@smithy/protocol-http": "^4.0.4", - "@smithy/smithy-client": "^3.1.8", + "@smithy/node-http-handler": "^3.1.4", + "@smithy/protocol-http": "^4.1.0", + "@smithy/smithy-client": "^3.1.12", "@smithy/types": "^3.3.0", "@smithy/url-parser": "^3.0.3", "@smithy/util-base64": "^3.0.0", "@smithy/util-body-length-browser": "^3.0.0", "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.10", - "@smithy/util-defaults-mode-node": "^3.0.10", + "@smithy/util-defaults-mode-browser": "^3.0.14", + "@smithy/util-defaults-mode-node": "^3.0.14", "@smithy/util-endpoints": "^2.0.5", "@smithy/util-middleware": "^3.0.3", "@smithy/util-retry": "^3.0.3", @@ -392,49 +396,50 @@ "node": ">=16.0.0" }, "peerDependencies": { - "@aws-sdk/client-sts": "^3.616.0" + "@aws-sdk/client-sts": "^3.629.0" } }, "node_modules/@aws-sdk/client-sts": { - "version": "3.616.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.616.0.tgz", - "integrity": "sha512-FP7i7hS5FpReqnysQP1ukQF1OUWy8lkomaOnbu15H415YUrfCp947SIx6+BItjmx+esKxPkEjh/fbCVzw2D6hQ==", + "version": "3.629.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.629.0.tgz", + "integrity": "sha512-RjOs371YwnSVGxhPjuluJKaxl4gcPYTAky0nPjwBime0i9/iS9nI8R8l5j7k7ec9tpFWjBPvNnThCU07pvjdzw==", + "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/client-sso-oidc": "3.616.0", - "@aws-sdk/core": "3.616.0", - "@aws-sdk/credential-provider-node": "3.616.0", - "@aws-sdk/middleware-host-header": "3.616.0", + "@aws-sdk/client-sso-oidc": "3.629.0", + "@aws-sdk/core": "3.629.0", + "@aws-sdk/credential-provider-node": "3.629.0", + "@aws-sdk/middleware-host-header": "3.620.0", "@aws-sdk/middleware-logger": "3.609.0", - "@aws-sdk/middleware-recursion-detection": "3.616.0", - "@aws-sdk/middleware-user-agent": "3.616.0", + "@aws-sdk/middleware-recursion-detection": "3.620.0", + "@aws-sdk/middleware-user-agent": "3.620.0", "@aws-sdk/region-config-resolver": "3.614.0", "@aws-sdk/types": "3.609.0", "@aws-sdk/util-endpoints": "3.614.0", "@aws-sdk/util-user-agent-browser": "3.609.0", "@aws-sdk/util-user-agent-node": "3.614.0", "@smithy/config-resolver": "^3.0.5", - "@smithy/core": "^2.2.7", - "@smithy/fetch-http-handler": "^3.2.2", + "@smithy/core": "^2.3.2", + "@smithy/fetch-http-handler": "^3.2.4", "@smithy/hash-node": "^3.0.3", "@smithy/invalid-dependency": "^3.0.3", - "@smithy/middleware-content-length": "^3.0.4", - "@smithy/middleware-endpoint": "^3.0.5", - "@smithy/middleware-retry": "^3.0.10", + "@smithy/middleware-content-length": "^3.0.5", + "@smithy/middleware-endpoint": "^3.1.0", + "@smithy/middleware-retry": "^3.0.14", "@smithy/middleware-serde": "^3.0.3", "@smithy/middleware-stack": "^3.0.3", "@smithy/node-config-provider": "^3.1.4", - "@smithy/node-http-handler": "^3.1.3", - "@smithy/protocol-http": "^4.0.4", - "@smithy/smithy-client": "^3.1.8", + "@smithy/node-http-handler": "^3.1.4", + "@smithy/protocol-http": "^4.1.0", + "@smithy/smithy-client": "^3.1.12", "@smithy/types": "^3.3.0", "@smithy/url-parser": "^3.0.3", "@smithy/util-base64": "^3.0.0", "@smithy/util-body-length-browser": "^3.0.0", "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.10", - "@smithy/util-defaults-mode-node": "^3.0.10", + "@smithy/util-defaults-mode-browser": "^3.0.14", + "@smithy/util-defaults-mode-node": "^3.0.14", "@smithy/util-endpoints": "^2.0.5", "@smithy/util-middleware": "^3.0.3", "@smithy/util-retry": "^3.0.3", @@ -446,16 +451,20 @@ } }, "node_modules/@aws-sdk/core": { - "version": "3.616.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.616.0.tgz", - "integrity": "sha512-O/urkh2kECs/IqZIVZxyeyHZ7OR2ZWhLNK7btsVQBQvJKrEspLrk/Fp20Qfg5JDerQfBN83ZbyRXLJOOucdZpw==", + "version": "3.629.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.629.0.tgz", + "integrity": "sha512-+/ShPU/tyIBM3oY1cnjgNA/tFyHtlWq+wXF9xEKRv19NOpYbWQ+xzNwVjGq8vR07cCRqy/sDQLWPhxjtuV/FiQ==", + "license": "Apache-2.0", "dependencies": { - "@smithy/core": "^2.2.7", - "@smithy/protocol-http": "^4.0.4", - "@smithy/signature-v4": "^4.0.0", - "@smithy/smithy-client": "^3.1.8", + "@smithy/core": "^2.3.2", + "@smithy/node-config-provider": "^3.1.4", + "@smithy/property-provider": "^3.1.3", + "@smithy/protocol-http": "^4.1.0", + "@smithy/signature-v4": "^4.1.0", + "@smithy/smithy-client": "^3.1.12", "@smithy/types": "^3.3.0", - "fast-xml-parser": "4.2.5", + "@smithy/util-middleware": "^3.0.3", + "fast-xml-parser": "4.4.1", "tslib": "^2.6.2" }, "engines": { @@ -463,9 +472,10 @@ } }, "node_modules/@aws-sdk/credential-provider-env": { - "version": "3.609.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.609.0.tgz", - "integrity": "sha512-v69ZCWcec2iuV9vLVJMa6fAb5xwkzN4jYIT8yjo2c4Ia/j976Q+TPf35Pnz5My48Xr94EFcaBazrWedF+kwfuQ==", + "version": "3.620.1", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.620.1.tgz", + "integrity": "sha512-ExuILJ2qLW5ZO+rgkNRj0xiAipKT16Rk77buvPP8csR7kkCflT/gXTyzRe/uzIiETTxM7tr8xuO9MP/DQXqkfg==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.609.0", "@smithy/property-provider": "^3.1.3", @@ -477,18 +487,19 @@ } }, "node_modules/@aws-sdk/credential-provider-http": { - "version": "3.616.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.616.0.tgz", - "integrity": "sha512-1rgCkr7XvEMBl7qWCo5BKu3yAxJs71dRaZ55Xnjte/0ZHH6Oc93ZrHzyYy6UH6t0nZrH+FAuw7Yko2YtDDwDeg==", + "version": "3.622.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.622.0.tgz", + "integrity": "sha512-VUHbr24Oll1RK3WR8XLUugLpgK9ZuxEm/NVeVqyFts1Ck9gsKpRg1x4eH7L7tW3SJ4TDEQNMbD7/7J+eoL2svg==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.609.0", - "@smithy/fetch-http-handler": "^3.2.2", - "@smithy/node-http-handler": "^3.1.3", + "@smithy/fetch-http-handler": "^3.2.4", + "@smithy/node-http-handler": "^3.1.4", "@smithy/property-provider": "^3.1.3", - "@smithy/protocol-http": "^4.0.4", - "@smithy/smithy-client": "^3.1.8", + "@smithy/protocol-http": "^4.1.0", + "@smithy/smithy-client": "^3.1.12", "@smithy/types": "^3.3.0", - "@smithy/util-stream": "^3.1.0", + "@smithy/util-stream": "^3.1.3", "tslib": "^2.6.2" }, "engines": { @@ -496,17 +507,18 @@ } }, "node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.616.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.616.0.tgz", - "integrity": "sha512-5gQdMr9cca3xV7FF2SxpxWGH2t6+t4o+XBGiwsHm8muEjf4nUmw7Ij863x25Tjt2viPYV0UStczSb5Sihp7bkA==", + "version": "3.629.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.629.0.tgz", + "integrity": "sha512-r9fI7BABARvVDp77DBUImQzYdvarAIdhbvpCEZib0rlpvfWu3zxE9KZcapCAAi0MPjxeDfb7RMehFQIkAP7mYw==", + "license": "Apache-2.0", "dependencies": { - "@aws-sdk/credential-provider-env": "3.609.0", - "@aws-sdk/credential-provider-http": "3.616.0", - "@aws-sdk/credential-provider-process": "3.614.0", - "@aws-sdk/credential-provider-sso": "3.616.0", - "@aws-sdk/credential-provider-web-identity": "3.609.0", + "@aws-sdk/credential-provider-env": "3.620.1", + "@aws-sdk/credential-provider-http": "3.622.0", + "@aws-sdk/credential-provider-process": "3.620.1", + "@aws-sdk/credential-provider-sso": "3.629.0", + "@aws-sdk/credential-provider-web-identity": "3.621.0", "@aws-sdk/types": "3.609.0", - "@smithy/credential-provider-imds": "^3.1.4", + "@smithy/credential-provider-imds": "^3.2.0", "@smithy/property-provider": "^3.1.3", "@smithy/shared-ini-file-loader": "^3.1.4", "@smithy/types": "^3.3.0", @@ -516,22 +528,23 @@ "node": ">=16.0.0" }, "peerDependencies": { - "@aws-sdk/client-sts": "^3.616.0" + "@aws-sdk/client-sts": "^3.629.0" } }, "node_modules/@aws-sdk/credential-provider-node": { - "version": "3.616.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.616.0.tgz", - "integrity": "sha512-Se+u6DAxjDPjKE3vX1X2uxjkWgGq69BTo0uTB0vDUiWwBVgh16s9BsBhSAlKEH1CCbbJHvOg4YdTrzjwzqyClg==", + "version": "3.629.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.629.0.tgz", + "integrity": "sha512-868hnVOLlXOBHk91Rl0jZIRgr/M4WJCa0nOrW9A9yidsQxuZp9P0vshDmm4hMvNZadmPIfo0Rra2MpA4RELoCw==", + "license": "Apache-2.0", "dependencies": { - "@aws-sdk/credential-provider-env": "3.609.0", - "@aws-sdk/credential-provider-http": "3.616.0", - "@aws-sdk/credential-provider-ini": "3.616.0", - "@aws-sdk/credential-provider-process": "3.614.0", - "@aws-sdk/credential-provider-sso": "3.616.0", - "@aws-sdk/credential-provider-web-identity": "3.609.0", + "@aws-sdk/credential-provider-env": "3.620.1", + "@aws-sdk/credential-provider-http": "3.622.0", + "@aws-sdk/credential-provider-ini": "3.629.0", + "@aws-sdk/credential-provider-process": "3.620.1", + "@aws-sdk/credential-provider-sso": "3.629.0", + "@aws-sdk/credential-provider-web-identity": "3.621.0", "@aws-sdk/types": "3.609.0", - "@smithy/credential-provider-imds": "^3.1.4", + "@smithy/credential-provider-imds": "^3.2.0", "@smithy/property-provider": "^3.1.3", "@smithy/shared-ini-file-loader": "^3.1.4", "@smithy/types": "^3.3.0", @@ -542,9 +555,10 @@ } }, "node_modules/@aws-sdk/credential-provider-process": { - "version": "3.614.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.614.0.tgz", - "integrity": "sha512-Q0SI0sTRwi8iNODLs5+bbv8vgz8Qy2QdxbCHnPk/6Cx6LMf7i3dqmWquFbspqFRd8QiqxStrblwxrUYZi09tkA==", + "version": "3.620.1", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.620.1.tgz", + "integrity": "sha512-hWqFMidqLAkaV9G460+1at6qa9vySbjQKKc04p59OT7lZ5cO5VH5S4aI05e+m4j364MBROjjk2ugNvfNf/8ILg==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.609.0", "@smithy/property-provider": "^3.1.3", @@ -557,11 +571,12 @@ } }, "node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.616.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.616.0.tgz", - "integrity": "sha512-3rsWs9GBi8Z8Gps5ROwqguxtw+J6OIg1vawZMLRNMqqZoBvbOToe9wEnpid8ylU+27+oG8uibJNlNuRyXApUjw==", + "version": "3.629.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.629.0.tgz", + "integrity": "sha512-Lf4XOuj6jamxgGZGrVojERh5S+NS2t2S4CUOnAu6tJ5U0GPlpjhINUKlcVxJBpsIXudMGW1nkumAd3+kazCPig==", + "license": "Apache-2.0", "dependencies": { - "@aws-sdk/client-sso": "3.616.0", + "@aws-sdk/client-sso": "3.629.0", "@aws-sdk/token-providers": "3.614.0", "@aws-sdk/types": "3.609.0", "@smithy/property-provider": "^3.1.3", @@ -574,9 +589,10 @@ } }, "node_modules/@aws-sdk/credential-provider-web-identity": { - "version": "3.609.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.609.0.tgz", - "integrity": "sha512-U+PG8NhlYYF45zbr1km3ROtBMYqyyj/oK8NRp++UHHeuavgrP+4wJ4wQnlEaKvJBjevfo3+dlIBcaeQ7NYejWg==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.621.0.tgz", + "integrity": "sha512-w7ASSyfNvcx7+bYGep3VBgC3K6vEdLmlpjT7nSIHxxQf+WSdvy+HynwJosrpZax0sK5q0D1Jpn/5q+r5lwwW6w==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.609.0", "@smithy/property-provider": "^3.1.3", @@ -587,16 +603,17 @@ "node": ">=16.0.0" }, "peerDependencies": { - "@aws-sdk/client-sts": "^3.609.0" + "@aws-sdk/client-sts": "^3.621.0" } }, "node_modules/@aws-sdk/middleware-host-header": { - "version": "3.616.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.616.0.tgz", - "integrity": "sha512-mhNfHuGhCDZwYCABebaOvTgOM44UCZZRq2cBpgPZLVKP0ydAv5aFHXv01goexxXHqgHoEGx0uXWxlw0s2EpFDg==", + "version": "3.620.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.620.0.tgz", + "integrity": "sha512-VMtPEZwqYrII/oUkffYsNWY9PZ9xpNJpMgmyU0rlDQ25O1c0Hk3fJmZRe6pEkAJ0omD7kLrqGl1DUjQVxpd/Rg==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.609.0", - "@smithy/protocol-http": "^4.0.4", + "@smithy/protocol-http": "^4.1.0", "@smithy/types": "^3.3.0", "tslib": "^2.6.2" }, @@ -618,12 +635,13 @@ } }, "node_modules/@aws-sdk/middleware-recursion-detection": { - "version": "3.616.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.616.0.tgz", - "integrity": "sha512-LQKAcrZRrR9EGez4fdCIVjdn0Ot2HMN12ChnoMGEU6oIxnQ2aSC7iASFFCV39IYfeMh7iSCPj7Wopqw8rAouzg==", + "version": "3.620.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.620.0.tgz", + "integrity": "sha512-nh91S7aGK3e/o1ck64sA/CyoFw+gAYj2BDOnoNa6ouyCrVJED96ZXWbhye/fz9SgmNUZR2g7GdVpiLpMKZoI5w==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.609.0", - "@smithy/protocol-http": "^4.0.4", + "@smithy/protocol-http": "^4.1.0", "@smithy/types": "^3.3.0", "tslib": "^2.6.2" }, @@ -632,13 +650,14 @@ } }, "node_modules/@aws-sdk/middleware-user-agent": { - "version": "3.616.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.616.0.tgz", - "integrity": "sha512-iMcAb4E+Z3vuEcrDsG6T2OBNiqWAquwahP9qepHqfmnmJqHr1mSHtXDYTGBNid31+621sUQmneUQ+fagpGAe4w==", + "version": "3.620.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.620.0.tgz", + "integrity": "sha512-bvS6etn+KsuL32ubY5D3xNof1qkenpbJXf/ugGXbg0n98DvDFQ/F+SMLxHgbnER5dsKYchNnhmtI6/FC3HFu/A==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.609.0", "@aws-sdk/util-endpoints": "3.614.0", - "@smithy/protocol-http": "^4.0.4", + "@smithy/protocol-http": "^4.1.0", "@smithy/types": "^3.3.0", "tslib": "^2.6.2" }, @@ -666,6 +685,7 @@ "version": "3.614.0", "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.614.0.tgz", "integrity": "sha512-okItqyY6L9IHdxqs+Z116y5/nda7rHxLvROxtAJdLavWTYDydxrZstImNgGWTeVdmc0xX2gJCI77UYUTQWnhRw==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.609.0", "@smithy/property-provider": "^3.1.3", @@ -1164,12 +1184,10 @@ } }, "node_modules/@fastify/busboy": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", - "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", - "engines": { - "node": ">=14" - } + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-3.0.0.tgz", + "integrity": "sha512-83rnH2nCvclWaPQQKvkJ2pdOjG4TZyEVuFDnlOF6KP08lDaaceVyw/W63mDuafQT+MKHCvXIPpE5uYWeM0rT4w==", + "license": "MIT" }, "node_modules/@firebase/app-check-interop-types": { "version": "0.3.0", @@ -1321,28 +1339,6 @@ "node": ">=14" } }, - "node_modules/@google-cloud/storage/node_modules/fast-xml-parser": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.3.3.tgz", - "integrity": "sha512-coV/D1MhrShMvU6D0I+VAK3umz6hUaxxhL0yp/9RjfiYUfAv14rDhGQL+PLForhMdr0wq3PiV07WtkkNjJjNHg==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/NaturalIntelligence" - }, - { - "type": "paypal", - "url": "https://paypal.me/naturalintelligence" - } - ], - "optional": true, - "dependencies": { - "strnum": "^1.0.5" - }, - "bin": { - "fxparser": "src/cli/cli.js" - } - }, "node_modules/@google-cloud/storage/node_modules/uuid": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", @@ -1667,9 +1663,10 @@ } }, "node_modules/@opensearch-project/opensearch": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@opensearch-project/opensearch/-/opensearch-2.10.0.tgz", - "integrity": "sha512-I3Ko09HvA50zyDi92fgEZfFFaNHhpvXcYLImdKTSL6eEwKqQmszqkLF2g5NTgEyb4Jh9uD2RGX8EYr9PO9zenQ==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@opensearch-project/opensearch/-/opensearch-2.11.0.tgz", + "integrity": "sha512-G+SZwtWRDv90IrtTSNnCt0MQjHVyqrcIXcpwN68vjHnfbun2+RHn+ux4K7dnG+s/KwWzVKIpPFoRjg2gfFX0Mw==", + "license": "Apache-2.0", "dependencies": { "aws4": "^1.11.0", "debug": "^4.3.1", @@ -1784,15 +1781,16 @@ } }, "node_modules/@smithy/core": { - "version": "2.2.8", - "resolved": "https://registry.npmjs.org/@smithy/core/-/core-2.2.8.tgz", - "integrity": "sha512-1Y0XX0Ucyg0LWTfTVLWpmvSRtFRniykUl3dQ0os1sTd03mKDudR6mVyX+2ak1phwPXx2aEWMAAdW52JNi0mc3A==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-2.3.2.tgz", + "integrity": "sha512-in5wwt6chDBcUv1Lw1+QzZxN9fBffi+qOixfb65yK4sDuKG7zAUO9HAFqmVzsZM3N+3tTyvZjtnDXePpvp007Q==", + "license": "Apache-2.0", "dependencies": { - "@smithy/middleware-endpoint": "^3.0.5", - "@smithy/middleware-retry": "^3.0.11", + "@smithy/middleware-endpoint": "^3.1.0", + "@smithy/middleware-retry": "^3.0.14", "@smithy/middleware-serde": "^3.0.3", - "@smithy/protocol-http": "^4.0.4", - "@smithy/smithy-client": "^3.1.9", + "@smithy/protocol-http": "^4.1.0", + "@smithy/smithy-client": "^3.1.12", "@smithy/types": "^3.3.0", "@smithy/util-middleware": "^3.0.3", "tslib": "^2.6.2" @@ -1802,9 +1800,10 @@ } }, "node_modules/@smithy/credential-provider-imds": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-3.1.4.tgz", - "integrity": "sha512-NKyH01m97Xa5xf3pB2QOF3lnuE8RIK0hTVNU5zvZAwZU8uspYO4DHQVlK+Y5gwSrujTfHvbfd1D9UFJAc0iYKQ==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-3.2.0.tgz", + "integrity": "sha512-0SCIzgd8LYZ9EJxUjLXBmEKSZR/P/w6l7Rz/pab9culE/RWuqelAKGJvn5qUOl8BgX8Yj5HWM50A5hiB/RzsgA==", + "license": "Apache-2.0", "dependencies": { "@smithy/node-config-provider": "^3.1.4", "@smithy/property-provider": "^3.1.3", @@ -1817,11 +1816,12 @@ } }, "node_modules/@smithy/fetch-http-handler": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-3.2.2.tgz", - "integrity": "sha512-3LaWlBZObyGrOOd7e5MlacnAKEwFBmAeiW/TOj2eR9475Vnq30uS2510+tnKbxrGjROfNdOhQqGo5j3sqLT6bA==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-3.2.4.tgz", + "integrity": "sha512-kBprh5Gs5h7ug4nBWZi1FZthdqSM+T7zMmsZxx0IBvWUn7dK3diz2SHn7Bs4dQGFDk8plDv375gzenDoNwrXjg==", + "license": "Apache-2.0", "dependencies": { - "@smithy/protocol-http": "^4.0.4", + "@smithy/protocol-http": "^4.1.0", "@smithy/querystring-builder": "^3.0.3", "@smithy/types": "^3.3.0", "@smithy/util-base64": "^3.0.0", @@ -1863,11 +1863,12 @@ } }, "node_modules/@smithy/middleware-content-length": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-3.0.4.tgz", - "integrity": "sha512-wySGje/KfhsnF8YSh9hP16pZcl3C+X6zRsvSfItQGvCyte92LliilU3SD0nR7kTlxnAJwxY8vE/k4Eoezj847Q==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-3.0.5.tgz", + "integrity": "sha512-ILEzC2eyxx6ncej3zZSwMpB5RJ0zuqH7eMptxC4KN3f+v9bqT8ohssKbhNR78k/2tWW+KS5Spw+tbPF4Ejyqvw==", + "license": "Apache-2.0", "dependencies": { - "@smithy/protocol-http": "^4.0.4", + "@smithy/protocol-http": "^4.1.0", "@smithy/types": "^3.3.0", "tslib": "^2.6.2" }, @@ -1876,9 +1877,10 @@ } }, "node_modules/@smithy/middleware-endpoint": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-3.0.5.tgz", - "integrity": "sha512-V4acqqrh5tDxUEGVTOgf2lYMZqPQsoGntCrjrJZEeBzEzDry2d2vcI1QCXhGltXPPY+BMc6eksZMguA9fIY8vA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-3.1.0.tgz", + "integrity": "sha512-5y5aiKCEwg9TDPB4yFE7H6tYvGFf1OJHNczeY10/EFF8Ir8jZbNntQJxMWNfeQjC1mxPsaQ6mR9cvQbf+0YeMw==", + "license": "Apache-2.0", "dependencies": { "@smithy/middleware-serde": "^3.0.3", "@smithy/node-config-provider": "^3.1.4", @@ -1893,14 +1895,15 @@ } }, "node_modules/@smithy/middleware-retry": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-3.0.11.tgz", - "integrity": "sha512-/TIRWmhwMpv99JCGuMhJPnH7ggk/Lah7s/uNDyr7faF02BxNsyD/fz9Tw7pgCf9tYOKgjimm2Qml1Aq1pbkt6g==", + "version": "3.0.14", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-3.0.14.tgz", + "integrity": "sha512-7ZaWZJOjUxa5hgmuMspyt8v/zVsh0GXYuF7OvCmdcbVa/xbnKQoYC+uYKunAqRGTkxjOyuOCw9rmFUFOqqC0eQ==", + "license": "Apache-2.0", "dependencies": { "@smithy/node-config-provider": "^3.1.4", - "@smithy/protocol-http": "^4.0.4", + "@smithy/protocol-http": "^4.1.0", "@smithy/service-error-classification": "^3.0.3", - "@smithy/smithy-client": "^3.1.9", + "@smithy/smithy-client": "^3.1.12", "@smithy/types": "^3.3.0", "@smithy/util-middleware": "^3.0.3", "@smithy/util-retry": "^3.0.3", @@ -1919,6 +1922,7 @@ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" ], + "license": "MIT", "bin": { "uuid": "dist/bin/uuid" } @@ -1962,12 +1966,13 @@ } }, "node_modules/@smithy/node-http-handler": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-3.1.3.tgz", - "integrity": "sha512-UiKZm8KHb/JeOPzHZtRUfyaRDO1KPKPpsd7iplhiwVGOeVdkiVJ5bVe7+NhWREMOKomrDIDdSZyglvMothLg0Q==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-3.1.4.tgz", + "integrity": "sha512-+UmxgixgOr/yLsUxcEKGH0fMNVteJFGkmRltYFHnBMlogyFdpzn2CwqWmxOrfJELhV34v0WSlaqG1UtE1uXlJg==", + "license": "Apache-2.0", "dependencies": { "@smithy/abort-controller": "^3.1.1", - "@smithy/protocol-http": "^4.0.4", + "@smithy/protocol-http": "^4.1.0", "@smithy/querystring-builder": "^3.0.3", "@smithy/types": "^3.3.0", "tslib": "^2.6.2" @@ -1989,9 +1994,10 @@ } }, "node_modules/@smithy/protocol-http": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-4.0.4.tgz", - "integrity": "sha512-fAA2O4EFyNRyYdFLVIv5xMMeRb+3fRKc/Rt2flh5k831vLvUmNFXcydeg7V3UeEhGURJI4c1asmGJBjvmF6j8Q==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-4.1.0.tgz", + "integrity": "sha512-dPVoHYQ2wcHooGXg3LQisa1hH0e4y0pAddPMeeUPipI1tEOqL6A4N0/G7abeq+K8wrwSgjk4C0wnD1XZpJm5aA==", + "license": "Apache-2.0", "dependencies": { "@smithy/types": "^3.3.0", "tslib": "^2.6.2" @@ -2004,6 +2010,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-3.0.3.tgz", "integrity": "sha512-vyWckeUeesFKzCDaRwWLUA1Xym9McaA6XpFfAK5qI9DKJ4M33ooQGqvM4J+LalH4u/Dq9nFiC8U6Qn1qi0+9zw==", + "license": "Apache-2.0", "dependencies": { "@smithy/types": "^3.3.0", "@smithy/util-uri-escape": "^3.0.0", @@ -2049,11 +2056,13 @@ } }, "node_modules/@smithy/signature-v4": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-4.0.0.tgz", - "integrity": "sha512-ervYjQ+ZvmNG51Ui77IOTPri7nOyo8Kembzt9uwwlmtXJPmFXvslOahbA1blvAVs7G0KlYMiOBog1rAt7RVXxg==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-4.1.0.tgz", + "integrity": "sha512-aRryp2XNZeRcOtuJoxjydO6QTaVhxx/vjaR+gx7ZjaFgrgPRyZ3HCTbfwqYj6ZWEBHkCSUfcaymKPURaByukag==", + "license": "Apache-2.0", "dependencies": { "@smithy/is-array-buffer": "^3.0.0", + "@smithy/protocol-http": "^4.1.0", "@smithy/types": "^3.3.0", "@smithy/util-hex-encoding": "^3.0.0", "@smithy/util-middleware": "^3.0.3", @@ -2066,15 +2075,16 @@ } }, "node_modules/@smithy/smithy-client": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.1.9.tgz", - "integrity": "sha512-My2RaInZ4gSwJUPMaiLR/Nk82+c4LlvqpXA+n7lonGYgCZq23Tg+/xFhgmiejJ6XPElYJysTPyV90vKyp17+1g==", + "version": "3.1.12", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.1.12.tgz", + "integrity": "sha512-wtm8JtsycthkHy1YA4zjIh2thJgIQ9vGkoR639DBx5lLlLNU0v4GARpQZkr2WjXue74nZ7MiTSWfVrLkyD8RkA==", + "license": "Apache-2.0", "dependencies": { - "@smithy/middleware-endpoint": "^3.0.5", + "@smithy/middleware-endpoint": "^3.1.0", "@smithy/middleware-stack": "^3.0.3", - "@smithy/protocol-http": "^4.0.4", + "@smithy/protocol-http": "^4.1.0", "@smithy/types": "^3.3.0", - "@smithy/util-stream": "^3.1.1", + "@smithy/util-stream": "^3.1.3", "tslib": "^2.6.2" }, "engines": { @@ -2158,12 +2168,13 @@ } }, "node_modules/@smithy/util-defaults-mode-browser": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-3.0.11.tgz", - "integrity": "sha512-O3s9DGb3bmRvEKmT8RwvSWK4A9r6svfd+MnJB+UMi9ZcCkAnoRtliulOnGF0qCMkKF9mwk2tkopBBstalPY/vg==", + "version": "3.0.14", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-3.0.14.tgz", + "integrity": "sha512-0iwTgKKmAIf+vFLV8fji21Jb2px11ktKVxbX6LIDPAUJyWQqGqBVfwba7xwa1f2FZUoolYQgLvxQEpJycXuQ5w==", + "license": "Apache-2.0", "dependencies": { "@smithy/property-provider": "^3.1.3", - "@smithy/smithy-client": "^3.1.9", + "@smithy/smithy-client": "^3.1.12", "@smithy/types": "^3.3.0", "bowser": "^2.11.0", "tslib": "^2.6.2" @@ -2173,15 +2184,16 @@ } }, "node_modules/@smithy/util-defaults-mode-node": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-3.0.11.tgz", - "integrity": "sha512-qd4a9qtyOa/WY14aHHOkMafhh9z8D2QTwlcBoXMTPnEwtcY+xpe1JyFm9vya7VsB8hHsfn3XodEtwqREiu4ygQ==", + "version": "3.0.14", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-3.0.14.tgz", + "integrity": "sha512-e9uQarJKfXApkTMMruIdxHprhcXivH1flYCe8JRDTzkkLx8dA3V5J8GZlST9yfDiRWkJpZJlUXGN9Rc9Ade3OQ==", + "license": "Apache-2.0", "dependencies": { "@smithy/config-resolver": "^3.0.5", - "@smithy/credential-provider-imds": "^3.1.4", + "@smithy/credential-provider-imds": "^3.2.0", "@smithy/node-config-provider": "^3.1.4", "@smithy/property-provider": "^3.1.3", - "@smithy/smithy-client": "^3.1.9", + "@smithy/smithy-client": "^3.1.12", "@smithy/types": "^3.3.0", "tslib": "^2.6.2" }, @@ -2206,6 +2218,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-3.0.0.tgz", "integrity": "sha512-eFndh1WEK5YMUYvy3lPlVmYY/fZcQE1D8oSf41Id2vCeIkKJXPcYDCZD+4+xViI6b1XSd7tE+s5AmXzz5ilabQ==", + "license": "Apache-2.0", "dependencies": { "tslib": "^2.6.2" }, @@ -2239,12 +2252,13 @@ } }, "node_modules/@smithy/util-stream": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-3.1.1.tgz", - "integrity": "sha512-EhRnVvl3AhoHAT2rGQ5o+oSDRM/BUSMPLZZdRJZLcNVUsFAjOs4vHaPdNQivTSzRcFxf5DA4gtO46WWU2zimaw==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-3.1.3.tgz", + "integrity": "sha512-FIv/bRhIlAxC0U7xM1BCnF2aDRPq0UaelqBHkM2lsCp26mcBbgI0tCVTv+jGdsQLUmAMybua/bjDsSu8RQHbmw==", + "license": "Apache-2.0", "dependencies": { - "@smithy/fetch-http-handler": "^3.2.2", - "@smithy/node-http-handler": "^3.1.3", + "@smithy/fetch-http-handler": "^3.2.4", + "@smithy/node-http-handler": "^3.1.4", "@smithy/types": "^3.3.0", "@smithy/util-base64": "^3.0.0", "@smithy/util-buffer-from": "^3.0.0", @@ -2260,6 +2274,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-3.0.0.tgz", "integrity": "sha512-LqR7qYLgZTD7nWLBecUi4aqolw8Mhza9ArpNEQ881MJJIU2sE5iHCK6TdyqqzcDLy0OPe10IY4T8ctVdtynubg==", + "license": "Apache-2.0", "dependencies": { "tslib": "^2.6.2" }, @@ -2411,11 +2426,12 @@ "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==" }, "node_modules/@types/node": { - "version": "20.11.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.7.tgz", - "integrity": "sha512-GPmeN1C3XAyV5uybAf4cMLWT9fDWcmQhZVtMFu7OR32WjrqGG+Wnk2V1d0bmtUyE/Zy1QJ9BxyiTih9z8Oks8A==", + "version": "22.3.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.3.0.tgz", + "integrity": "sha512-nrWpWVaDZuaVc5X84xJ0vNrLvomM205oQyLsRt7OHNZbSHslcWsvgFR7O7hire2ZonjLrWBbedmotmIlJDVd6g==", + "license": "MIT", "dependencies": { - "undici-types": "~5.26.4" + "undici-types": "~6.18.2" } }, "node_modules/@types/qs": { @@ -2673,14 +2689,16 @@ } }, "node_modules/aws4": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.13.0.tgz", - "integrity": "sha512-3AungXC4I8kKsS9PuS4JH2nc+0bVY/mjgrephHTIi8fpEeGsTHBUJeosp0Wc1myYMElmD0B3Oc4XL/HVJ4PV2g==" + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.13.1.tgz", + "integrity": "sha512-u5w79Rd7SU4JaIlA/zFqG+gOiuq25q5VLyZ8E+ijJeILuTxVzZgp2CaGw/UTw6pXYN9XMO9yiqj/nEHmhTG5CA==", + "license": "MIT" }, "node_modules/axios": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.2.tgz", - "integrity": "sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw==", + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.4.tgz", + "integrity": "sha512-DukmaFRnY6AzAALSH4J2M3k6PkaC+MfaAGdEERRWcC9q3/TWQwLpHR8ZRLKTdQ3aBDL64EdluRDjJqKw+BPZEw==", + "license": "MIT", "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.0", @@ -3013,9 +3031,10 @@ } }, "node_modules/cloudinary": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/cloudinary/-/cloudinary-2.3.0.tgz", - "integrity": "sha512-QBa/ePVVfVcVOB1Vut236rjAbTZAArzOm0e2IWUkQJSZFS65Sjf+i3DyRGen4QX8GZzrcbzvKI9b8BTHAv1zqQ==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/cloudinary/-/cloudinary-2.4.0.tgz", + "integrity": "sha512-5HA9VffeaR3MKiHpRo9A5SWgZFPxzlEDep0O4KzL3TIDi1hmQC9gjA4dHpVmdeFC0ZD1Xr5fGsWRKVDK9Ay9PQ==", + "license": "MIT", "dependencies": { "lodash": "^4.17.21", "q": "^1.5.1" @@ -3995,19 +4014,20 @@ "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==" }, "node_modules/fast-xml-parser": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.2.5.tgz", - "integrity": "sha512-B9/wizE4WngqQftFPmdaMYlXoJlJOYxGQOanC77fq9k8+Z0v5dDSVh+3glErdIROP//s/jgb7ZuxKfB8nVyo0g==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz", + "integrity": "sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw==", "funding": [ - { - "type": "paypal", - "url": "https://paypal.me/naturalintelligence" - }, { "type": "github", "url": "https://github.com/sponsors/NaturalIntelligence" + }, + { + "type": "paypal", + "url": "https://paypal.me/naturalintelligence" } ], + "license": "MIT", "dependencies": { "strnum": "^1.0.5" }, @@ -4087,18 +4107,18 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, "node_modules/firebase-admin": { - "version": "12.2.0", - "resolved": "https://registry.npmjs.org/firebase-admin/-/firebase-admin-12.2.0.tgz", - "integrity": "sha512-R9xxENvPA/19XJ3mv0Kxfbz9kPXd9/HrM4083LZWOO0qAQGheRzcCQamYRe+JSrV2cdKXP3ZsfFGTYMrFM0pJg==", + "version": "12.3.1", + "resolved": "https://registry.npmjs.org/firebase-admin/-/firebase-admin-12.3.1.tgz", + "integrity": "sha512-vEr3s3esl8nPIA9r/feDT4nzIXCfov1CyyCSpMQWp6x63Q104qke0MEGZlrHUZVROtl8FLus6niP/M9I1s4VBA==", + "license": "Apache-2.0", "dependencies": { - "@fastify/busboy": "^2.1.0", + "@fastify/busboy": "^3.0.0", "@firebase/database-compat": "^1.0.2", "@firebase/database-types": "^1.0.0", - "@types/node": "^20.10.3", + "@types/node": "^22.0.1", "farmhash-modern": "^1.1.0", "jsonwebtoken": "^9.0.0", "jwks-rsa": "^3.1.0", - "long": "^5.2.3", "node-forge": "^1.3.1", "uuid": "^10.0.0" }, @@ -4974,9 +4994,10 @@ } }, "node_modules/json-2-csv": { - "version": "5.5.4", - "resolved": "https://registry.npmjs.org/json-2-csv/-/json-2-csv-5.5.4.tgz", - "integrity": "sha512-gB24IF5SvZn7QhEh6kp9QwFhRnI3FVEEXAGyq0xtPxqOQ4odYU3PU9pFKRoR1SGABxunQlBP6VFv0c8EnLbsLQ==", + "version": "5.5.5", + "resolved": "https://registry.npmjs.org/json-2-csv/-/json-2-csv-5.5.5.tgz", + "integrity": "sha512-xLeiOE+jtDMX4SMn9JlD6BVI9c5SYVFmtlsNBSelGlq9iUHdVmwlxQ/uUI/BEVQuKDVLlxNrsOfwlI3rfYy1zA==", + "license": "MIT", "dependencies": { "deeks": "3.1.0", "doc-path": "4.1.1" @@ -5187,7 +5208,8 @@ "node_modules/long": { "version": "5.2.3", "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", - "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==" + "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==", + "optional": true }, "node_modules/lru-cache": { "version": "6.0.0", @@ -5502,9 +5524,10 @@ } }, "node_modules/node-persist": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/node-persist/-/node-persist-4.0.2.tgz", - "integrity": "sha512-J/xDWS6Tn7kNn3ErAvz2kOVul94s7IKhIQLX24mw2eViLqTCfuIOywBT5kSrOy7vF2HfCWGJtSx7z6OiFXmnzQ==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/node-persist/-/node-persist-4.0.3.tgz", + "integrity": "sha512-0gDy86TNShzfbpUKFbH8KJFjoovuUgVh/FqL4jrJWYz0cET76Uohl118utG/Ft6wl4sHOPXdRSY7eXH5kVY06w==", + "license": "MIT", "engines": { "node": ">=10.12.0" } @@ -6348,9 +6371,10 @@ } }, "node_modules/soap": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/soap/-/soap-1.1.0.tgz", - "integrity": "sha512-5C9PT00v9KygPviQCSuwCobeERV+zQV0t0qUPW6kAw3Vs69UmG64h2zJhMcK/NNOMmUnVEOnHevMfCXc68O2Vw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/soap/-/soap-1.1.1.tgz", + "integrity": "sha512-Mxj/nQ9oO+zYiVZqk9AiXgeHkX/xj8EAnbri9BkxGoMrWw3fKtQulaquSbIO+kgoZfm7g08xddtmpOG2H+Z0zQ==", + "license": "MIT", "dependencies": { "axios": "^1.7.2", "axios-ntlm": "^1.4.2", @@ -7137,9 +7161,10 @@ } }, "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + "version": "6.18.2", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.18.2.tgz", + "integrity": "sha512-5ruQbENj95yDYJNS3TvcaxPMshV7aizdv/hWYjGIKoANWKjhWNBsr2YEuYZKodQulB1b8l7ILOuDQep3afowQQ==", + "license": "MIT" }, "node_modules/universalify": { "version": "0.1.2", diff --git a/package.json b/package.json index 05271c380..25980e09b 100644 --- a/package.json +++ b/package.json @@ -19,18 +19,18 @@ "makeitpretty": "prettier --write \"**/*.{css,js,json,jsx,scss}\"" }, "dependencies": { - "@aws-sdk/client-secrets-manager": "^3.616.0", - "@aws-sdk/client-ses": "^3.616.0", - "@aws-sdk/credential-provider-node": "^3.616.0", - "@opensearch-project/opensearch": "^2.10.0", - "aws4": "^1.13.0", - "axios": "^1.7.2", + "@aws-sdk/client-secrets-manager": "^3.629.0", + "@aws-sdk/client-ses": "^3.629.0", + "@aws-sdk/credential-provider-node": "^3.629.0", + "@opensearch-project/opensearch": "^2.11.0", + "aws4": "^1.13.1", + "axios": "^1.7.4", "better-queue": "^3.8.12", "bluebird": "^3.7.2", "body-parser": "^1.20.2", "canvas": "^2.11.2", "chart.js": "^4.4.3", - "cloudinary": "^2.3.0", + "cloudinary": "^2.4.0", "compression": "^1.7.4", "cookie-parser": "^1.4.6", "cors": "2.8.5", @@ -38,24 +38,24 @@ "dinero.js": "^1.9.1", "dotenv": "^16.4.5", "express": "^4.19.2", - "firebase-admin": "^12.2.0", + "firebase-admin": "^12.3.1", "graphql": "^16.9.0", "graphql-request": "^6.1.0", "graylog2": "^0.2.1", "inline-css": "^4.0.2", "intuit-oauth": "^4.1.2", - "json-2-csv": "^5.5.4", + "json-2-csv": "^5.5.5", "lodash": "^4.17.21", "moment": "^2.30.1", "moment-timezone": "^0.5.45", "multer": "^1.4.5-lts.1", "node-mailjet": "^6.0.5", - "node-persist": "^4.0.2", + "node-persist": "^4.0.3", "nodemailer": "^6.9.14", "phone": "^3.1.49", "recursive-diff": "^1.0.9", "rimraf": "^6.0.1", - "soap": "^1.1.0", + "soap": "^1.1.1", "socket.io": "^4.7.5", "ssh2-sftp-client": "^10.0.3", "twilio": "^4.23.0", From 730a7a233d00dbaeefa76c7d551df11bd0803810 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Wed, 14 Aug 2024 13:29:35 -0400 Subject: [PATCH 003/478] - Improve handle beta code (AIO Version) Signed-off-by: Dave Richer --- client/src/App/App.jsx | 2 +- .../components/header/header.component.jsx | 2 +- client/src/utils/betaHandler.js | 36 ------------------- client/src/utils/handleBeta.js | 26 ++++++++------ 4 files changed, 18 insertions(+), 48 deletions(-) delete mode 100644 client/src/utils/betaHandler.js diff --git a/client/src/App/App.jsx b/client/src/App/App.jsx index 441359097..6fe558910 100644 --- a/client/src/App/App.jsx +++ b/client/src/App/App.jsx @@ -18,7 +18,7 @@ import { checkUserSession } from "../redux/user/user.actions"; import { selectBodyshop, selectCurrentEula, selectCurrentUser } from "../redux/user/user.selectors"; import PrivateRoute from "../components/PrivateRoute"; import "./App.styles.scss"; -import handleBeta from "../utils/betaHandler"; +import handleBeta from "../utils/handleBeta"; import Eula from "../components/eula/eula.component"; import InstanceRenderMgr from "../utils/instanceRenderMgr"; import ProductFruitsWrapper from "./ProductFruitsWrapper.jsx"; diff --git a/client/src/components/header/header.component.jsx b/client/src/components/header/header.component.jsx index 47b59a309..f0de7f403 100644 --- a/client/src/components/header/header.component.jsx +++ b/client/src/components/header/header.component.jsx @@ -43,7 +43,7 @@ import { selectRecentItems, selectSelectedHeader } from "../../redux/application import { setModalContext } from "../../redux/modals/modals.actions"; import { signOutStart } from "../../redux/user/user.actions"; import { selectBodyshop, selectCurrentUser } from "../../redux/user/user.selectors"; -import { checkBeta, handleBeta, setBeta } from "../../utils/betaHandler"; +import { checkBeta, handleBeta, setBeta } from "../../utils/handleBeta"; import InstanceRenderManager from "../../utils/instanceRenderMgr"; import { HasFeatureAccess } from "../feature-wrapper/feature-wrapper.component"; diff --git a/client/src/utils/betaHandler.js b/client/src/utils/betaHandler.js deleted file mode 100644 index 804b38b7d..000000000 --- a/client/src/utils/betaHandler.js +++ /dev/null @@ -1,36 +0,0 @@ -export const BETA_KEY = "betaSwitchImex"; - -export const checkBeta = () => { - const cookie = document.cookie.split("; ").find((row) => row.startsWith(BETA_KEY)); - return cookie ? cookie.split("=")[1] === "true" : false; -}; - -export const setBeta = (value) => { - const domain = window.location.hostname.split(".").slice(-2).join("."); - document.cookie = `${BETA_KEY}=${value}; path=/; domain=.${domain}`; -}; - -export const handleBeta = () => { - // If the current host name does not start with beta or test, then we don't need to do anything. - if (window.location.hostname.startsWith("localhost")) { - console.log("Not on beta or test, so no need to handle beta."); - return; - } - - const isBeta = checkBeta(); - - const currentHostName = window.location.hostname; - - // Beta is enabled, but the current host name does start with beta. - if (isBeta && !currentHostName.startsWith("beta")) { - const href = `${window.location.protocol}//beta.${currentHostName}${window.location.pathname}${window.location.search}${window.location.hash}`; - window.location.replace(href); - } - - // Beta is not enabled, but the current host name does start with beta. - else if (!isBeta && currentHostName.startsWith("beta")) { - const href = `${window.location.protocol}//${currentHostName.replace("beta.", "")}${window.location.pathname}${window.location.search}${window.location.hash}`; - window.location.replace(href); - } -}; -export default handleBeta; diff --git a/client/src/utils/handleBeta.js b/client/src/utils/handleBeta.js index 804b38b7d..34bdab626 100644 --- a/client/src/utils/handleBeta.js +++ b/client/src/utils/handleBeta.js @@ -11,26 +11,32 @@ export const setBeta = (value) => { }; export const handleBeta = () => { - // If the current host name does not start with beta or test, then we don't need to do anything. if (window.location.hostname.startsWith("localhost")) { console.log("Not on beta or test, so no need to handle beta."); return; } const isBeta = checkBeta(); - const currentHostName = window.location.hostname; - // Beta is enabled, but the current host name does start with beta. - if (isBeta && !currentHostName.startsWith("beta")) { - const href = `${window.location.protocol}//beta.${currentHostName}${window.location.pathname}${window.location.search}${window.location.hash}`; - window.location.replace(href); - } + // Determine if the host name starts with "beta" or "www.beta" + const isBetaHost = currentHostName.startsWith("beta"); + const isBetaHostWithWWW = currentHostName.startsWith("www.beta"); - // Beta is not enabled, but the current host name does start with beta. - else if (!isBeta && currentHostName.startsWith("beta")) { - const href = `${window.location.protocol}//${currentHostName.replace("beta.", "")}${window.location.pathname}${window.location.search}${window.location.hash}`; + // Handle beta redirection + if (isBeta && !isBetaHost && !isBetaHostWithWWW) { + // From non-beta to beta + const newHostName = currentHostName.startsWith("www.") + ? `www.beta.${currentHostName.replace(/^www\./, "")}` + : `beta.${currentHostName}`; + const href = `${window.location.protocol}//${newHostName}${window.location.pathname}${window.location.search}${window.location.hash}`; + window.location.replace(href); + } else if (!isBeta && (isBetaHost || isBetaHostWithWWW)) { + // From beta to non-beta + const newHostName = currentHostName.replace(/^www\./, "").replace(/^beta\./, "www."); + const href = `${window.location.protocol}//${newHostName}${window.location.pathname}${window.location.search}${window.location.hash}`; window.location.replace(href); } }; + export default handleBeta; From df93357cec0156ad9ff2d0022084f2c3265db9ee Mon Sep 17 00:00:00 2001 From: Allan Carr Date: Wed, 14 Aug 2024 11:38:35 -0700 Subject: [PATCH 004/478] IO-2856 Mark Exported Button Signed-off-by: Allan Carr --- ...accounting-receivables-table.component.jsx | 24 ++-- .../jobs-mark-selected-exported.jsx | 105 ++++++++++++++++++ ...yable-mark-selected-exported.component.jsx | 2 +- ...yment-mark-selected-exported.component.jsx | 2 +- 4 files changed, 124 insertions(+), 9 deletions(-) create mode 100644 client/src/components/jobs-mark-selected-exported/jobs-mark-selected-exported.jsx diff --git a/client/src/components/accounting-receivables-table/accounting-receivables-table.component.jsx b/client/src/components/accounting-receivables-table/accounting-receivables-table.component.jsx index 83b139827..fb2681623 100644 --- a/client/src/components/accounting-receivables-table/accounting-receivables-table.component.jsx +++ b/client/src/components/accounting-receivables-table/accounting-receivables-table.component.jsx @@ -13,6 +13,7 @@ import { createStructuredSelector } from "reselect"; import { selectBodyshop } from "../../redux/user/user.selectors"; import { DateFormatter } from "../../utils/DateFormatter"; import ExportLogsCountDisplay from "../export-logs-count-display/export-logs-count-display.component"; +import JobMarkSelectedExported from "../jobs-mark-selected-exported/jobs-mark-selected-exported"; import OwnerNameDisplay, { OwnerNameDisplayFunction } from "../owner-name-display/owner-name-display.component"; import QboAuthorizeComponent from "../qbo-authorize/qbo-authorize.component"; @@ -170,13 +171,22 @@ export function AccountingReceivablesTableComponent({ bodyshop, loading, jobs, r extra={ {!bodyshop.cdk_dealerid && !bodyshop.pbs_serialnumber && ( - + <> + + + )} {bodyshop.accountingconfig && bodyshop.accountingconfig.qbo && } ({ + insertAuditTrail: ({ jobid, operation, type }) => dispatch(insertAuditTrail({ jobid, operation, type })) +}); + +export default connect(mapStateToProps, mapDispatchToProps)(JobMarkSelectedExported); + +export function JobMarkSelectedExported({ + bodyshop, + currentUser, + jobIds, + disabled, + loadingCallback, + completedCallback, + refetch, + insertAuditTrail +}) { + const { t } = useTranslation(); + const [loading, setLoading] = useState(false); + const [open, setOpen] = useState(false); + const [insertExportLog] = useMutation(INSERT_EXPORT_LOG); + + const [updateJob] = useMutation(UPDATE_JOBS); + const handleUpdate = async () => { + setLoading(true); + loadingCallback(true); + const result = await updateJob({ + variables: { + jobIds: jobIds, + fields: { + status: bodyshop.md_ro_statuses.default_exported || "Exported*", + date_exported: new Date() + } + }, + update(cache) {} + }); + + await insertExportLog({ + variables: { + logs: jobIds.map((id) => { + return { + bodyshopid: bodyshop.id, + jobid: id, + successful: true, + message: JSON.stringify([t("general.labels.markedexported")]), + useremail: currentUser.email + }; + }) + } + }); + + if (!result.errors) { + notification["success"]({ message: t("jobs.successes.save") }); + result.data.update_jobs.returning.forEach((job) => { + console.log("results job", job.id, "audit: ", AuditTrailMapping.admin_jobmarkexported()); + insertAuditTrail({ + jobid: job.id, + operation: AuditTrailMapping.admin_jobmarkexported(), + type: "admin_jobmarkexported" + }); + }); + } else { + notification["error"]({ + message: t("jobs.errors.saving", { + error: JSON.stringify(result.errors) + }) + }); + } + loadingCallback(false); + completedCallback && completedCallback([]); + setLoading(false); + refetch && refetch(); + setOpen(false); + }; + + return ( + setOpen(false)} + onConfirm={handleUpdate} + disabled={disabled} + > + + + ); +} diff --git a/client/src/components/payable-mark-selected-exported/payable-mark-selected-exported.component.jsx b/client/src/components/payable-mark-selected-exported/payable-mark-selected-exported.component.jsx index 08cd00b43..ccd480547 100644 --- a/client/src/components/payable-mark-selected-exported/payable-mark-selected-exported.component.jsx +++ b/client/src/components/payable-mark-selected-exported/payable-mark-selected-exported.component.jsx @@ -90,7 +90,7 @@ export function BillMarkSelectedExported({ onConfirm={handleUpdate} disabled={disabled} > - diff --git a/client/src/components/payment-mark-selected-exported/payment-mark-selected-exported.component.jsx b/client/src/components/payment-mark-selected-exported/payment-mark-selected-exported.component.jsx index 3727e23eb..8dbd2ae45 100644 --- a/client/src/components/payment-mark-selected-exported/payment-mark-selected-exported.component.jsx +++ b/client/src/components/payment-mark-selected-exported/payment-mark-selected-exported.component.jsx @@ -90,7 +90,7 @@ export function PaymentMarkSelectedExported({ onConfirm={handleUpdate} disabled={disabled} > - From 5a36cb7cf1df4d5c7d8bb6badd85742281946248 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Thu, 15 Aug 2024 11:19:59 -0400 Subject: [PATCH 005/478] - Improve handle beta code (AIO Version) Signed-off-by: Dave Richer --- client/src/utils/handleBeta.js | 35 +++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/client/src/utils/handleBeta.js b/client/src/utils/handleBeta.js index 34bdab626..dcb0d18d1 100644 --- a/client/src/utils/handleBeta.js +++ b/client/src/utils/handleBeta.js @@ -20,22 +20,27 @@ export const handleBeta = () => { const currentHostName = window.location.hostname; // Determine if the host name starts with "beta" or "www.beta" - const isBetaHost = currentHostName.startsWith("beta"); - const isBetaHostWithWWW = currentHostName.startsWith("www.beta"); + const isBetaHost = currentHostName.startsWith("beta."); + const isBetaHostWithWWW = currentHostName.startsWith("www.beta."); - // Handle beta redirection - if (isBeta && !isBetaHost && !isBetaHostWithWWW) { - // From non-beta to beta - const newHostName = currentHostName.startsWith("www.") - ? `www.beta.${currentHostName.replace(/^www\./, "")}` - : `beta.${currentHostName}`; - const href = `${window.location.protocol}//${newHostName}${window.location.pathname}${window.location.search}${window.location.hash}`; - window.location.replace(href); - } else if (!isBeta && (isBetaHost || isBetaHostWithWWW)) { - // From beta to non-beta - const newHostName = currentHostName.replace(/^www\./, "").replace(/^beta\./, "www."); - const href = `${window.location.protocol}//${newHostName}${window.location.pathname}${window.location.search}${window.location.hash}`; - window.location.replace(href); + if (isBeta) { + // If beta is on and we are not on a beta domain, redirect to the beta version + if (!isBetaHost && !isBetaHostWithWWW) { + const newHostName = currentHostName.startsWith("www.") + ? `www.beta.${currentHostName.replace(/^www\./, "")}` + : `beta.${currentHostName}`; + const href = `${window.location.protocol}//${newHostName}${window.location.pathname}${window.location.search}${window.location.hash}`; + window.location.replace(href); + } + // Otherwise, if beta is on and we're already on a beta domain, stay there + } else { + // If beta is off and we are on a beta domain, redirect to the non-beta version + if (isBetaHost || isBetaHostWithWWW) { + const newHostName = currentHostName.replace(/^www\.beta\./, "www.").replace(/^beta\./, ""); + const href = `${window.location.protocol}//${newHostName}${window.location.pathname}${window.location.search}${window.location.hash}`; + window.location.replace(href); + } + // Otherwise, if beta is off and we're not on a beta domain, stay there } }; From 3ce2b1ab19f972be1a763f66774b6890b7599348 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Thu, 15 Aug 2024 13:35:18 -0400 Subject: [PATCH 006/478] - revert (put back in) zoho change Signed-off-by: Dave Richer --- client/index.html | 109 ++++++++++++---------------------------------- 1 file changed, 29 insertions(+), 80 deletions(-) diff --git a/client/index.html b/client/index.html index e75f91325..9d415aaf6 100644 --- a/client/index.html +++ b/client/index.html @@ -1,20 +1,20 @@ - + <% if (env.VITE_APP_INSTANCE === 'IMEX') { %> - + <% } %> <% if (env.VITE_APP_INSTANCE === 'ROME') { %> - + <% } %> <% if (env.VITE_APP_INSTANCE === 'PROMANAGER') { %> - + <% } %> - - + + - + <% if (env.VITE_APP_INSTANCE === 'IMEX') { %> - + ImEX Online <% } %> <% if (env.VITE_APP_INSTANCE === 'ROME') { %> - + Rome Online - - - - - - - - - - - - + <% } %> <% if (env.VITE_APP_INSTANCE === 'PROMANAGER') { %> ProManager - + <% } %> + + + + + + + + + + + <% } %> <% if (env.VITE_APP_INSTANCE === 'PROMANAGER') { %> ProManager From 3498fbc8f1fdcc152fa4aa3fed12f7bf35f303fd Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Fri, 16 Aug 2024 11:14:32 -0400 Subject: [PATCH 012/478] - Add Alert Filter to visual production board Signed-off-by: Dave Richer --- .../production-board-filters.component.jsx | 25 ++++++++++++++++--- .../production-board-kanban.utils.js | 7 +++++- client/src/translations/en_us/common.json | 3 ++- client/src/translations/es/common.json | 3 ++- client/src/translations/fr/common.json | 3 ++- 5 files changed, 33 insertions(+), 8 deletions(-) diff --git a/client/src/components/production-board-filters/production-board-filters.component.jsx b/client/src/components/production-board-filters/production-board-filters.component.jsx index 421759534..90afb4fe7 100644 --- a/client/src/components/production-board-filters/production-board-filters.component.jsx +++ b/client/src/components/production-board-filters/production-board-filters.component.jsx @@ -1,22 +1,32 @@ -import { Input, Space, Spin } from "antd"; -import React from "react"; +import { Button, Input, Space, Spin } from "antd"; +import React, { useState } from "react"; import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; import { createStructuredSelector } from "reselect"; +import { ExclamationCircleFilled, ExclamationCircleOutlined } from "@ant-design/icons"; import { selectBodyshop } from "../../redux/user/user.selectors"; import EmployeeSearchSelectComponent from "../employee-search-select/employee-search-select.component"; const mapStateToProps = createStructuredSelector({ - //currentUser: selectCurrentUser bodyshop: selectBodyshop }); + const mapDispatchToProps = (dispatch) => ({ //setUserLanguage: language => dispatch(setUserLanguage(language)) }); + export default connect(mapStateToProps, mapDispatchToProps)(ProductionBoardFilters); export function ProductionBoardFilters({ bodyshop, filter, setFilter, loading }) { const { t } = useTranslation(); + const [alertFilter, setAlertFilter] = useState(false); + + const toggleAlertFilter = () => { + const newAlertFilter = !alertFilter; + setAlertFilter(newAlertFilter); + setFilter({ ...filter, alert: newAlertFilter }); + }; + return ( {loading && } @@ -31,10 +41,17 @@ export function ProductionBoardFilters({ bodyshop, filter, setFilter, loading }) style={{ minWidth: "20rem" }} options={bodyshop.employees.filter((e) => e.active)} value={filter.employeeId} - placeholder={t("production.labels.employeesearch")} + placeholder={t("production.labels.alerts")} onChange={(emp) => setFilter({ ...filter, employeeId: emp })} allowClear /> + ); } diff --git a/client/src/components/production-board-kanban/production-board-kanban.utils.js b/client/src/components/production-board-kanban/production-board-kanban.utils.js index fed3d12db..ba3974c1a 100644 --- a/client/src/components/production-board-kanban/production-board-kanban.utils.js +++ b/client/src/components/production-board-kanban/production-board-kanban.utils.js @@ -29,7 +29,7 @@ const sortByParentId = (arr) => { // Function to create board data based on statuses and jobs, with optional filtering export const createBoardData = ({ statuses, data, filter, cardSettings }) => { - const { search, employeeId } = filter; + const { search, employeeId, alert } = filter; const lanes = statuses.map((status) => ({ id: status, @@ -52,6 +52,11 @@ export const createBoardData = ({ statuses, data, filter, cardSettings }) => { ); } + // Filter jobs by alert if alert filter is true + if (alert) { + filteredJobs = filteredJobs.filter((job) => job.production_vars?.alert); + } + const DataGroupedByStatus = groupBy(filteredJobs, "status"); Object.keys(DataGroupedByStatus).forEach((statusGroupKey) => { diff --git a/client/src/translations/en_us/common.json b/client/src/translations/en_us/common.json index 4dd123fd8..c2d776fbf 100644 --- a/client/src/translations/en_us/common.json +++ b/client/src/translations/en_us/common.json @@ -2833,7 +2833,8 @@ "sublets": "Sublets", "totalhours": "Total Hrs ", "touchtime": "T/T", - "viewname": "View Name" + "viewname": "View Name", + "alerts": "Alerts" }, "successes": { "removed": "Job removed from production." diff --git a/client/src/translations/es/common.json b/client/src/translations/es/common.json index bafe9ced5..c2da8510a 100644 --- a/client/src/translations/es/common.json +++ b/client/src/translations/es/common.json @@ -2833,7 +2833,8 @@ "sublets": "", "totalhours": "", "touchtime": "", - "viewname": "" + "viewname": "", + "alerts": "" }, "successes": { "removed": "" diff --git a/client/src/translations/fr/common.json b/client/src/translations/fr/common.json index 5fd0c1280..005accb1c 100644 --- a/client/src/translations/fr/common.json +++ b/client/src/translations/fr/common.json @@ -2833,7 +2833,8 @@ "sublets": "", "totalhours": "", "touchtime": "", - "viewname": "" + "viewname": "", + "alerts": "" }, "successes": { "removed": "" From 134ce05d27b1616a0eadcf168f84641341ae3b26 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Fri, 16 Aug 2024 11:16:20 -0400 Subject: [PATCH 013/478] - Add Alert Filter to visual production board Signed-off-by: Dave Richer --- .../production-board-filters.component.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/components/production-board-filters/production-board-filters.component.jsx b/client/src/components/production-board-filters/production-board-filters.component.jsx index 90afb4fe7..eea1fc3d9 100644 --- a/client/src/components/production-board-filters/production-board-filters.component.jsx +++ b/client/src/components/production-board-filters/production-board-filters.component.jsx @@ -41,7 +41,7 @@ export function ProductionBoardFilters({ bodyshop, filter, setFilter, loading }) style={{ minWidth: "20rem" }} options={bodyshop.employees.filter((e) => e.active)} value={filter.employeeId} - placeholder={t("production.labels.alerts")} + placeholder={t("production.labels.employeesearch")} onChange={(emp) => setFilter({ ...filter, employeeId: emp })} allowClear /> From f691aca2417323a2626deba6d66197132eac5f43 Mon Sep 17 00:00:00 2001 From: Allan Carr Date: Fri, 16 Aug 2024 09:11:29 -0700 Subject: [PATCH 014/478] IO-2884 Production List Board Filter Signed-off-by: Allan Carr --- .../production-list-columns.data.jsx | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/client/src/components/production-list-columns/production-list-columns.data.jsx b/client/src/components/production-list-columns/production-list-columns.data.jsx index 2c7b349e3..fbc9236a5 100644 --- a/client/src/components/production-list-columns/production-list-columns.data.jsx +++ b/client/src/components/production-list-columns/production-list-columns.data.jsx @@ -2,10 +2,13 @@ import { BranchesOutlined, PauseCircleOutlined } from "@ant-design/icons"; import { Checkbox, Space, Tooltip } from "antd"; import i18n from "i18next"; import { Link } from "react-router-dom"; +import { setModalContext } from "../../redux/modals/modals.actions"; +import { store } from "../../redux/store"; import CurrencyFormatter from "../../utils/CurrencyFormatter"; import { TimeFormatter } from "../../utils/DateFormatter"; import PhoneFormatter from "../../utils/PhoneFormatter"; import { onlyUnique } from "../../utils/arrayHelper"; +import InstanceRenderManager from "../../utils/instanceRenderMgr"; import { alphaSort, dateSort, statusSort } from "../../utils/sorters"; import JobAltTransportChange from "../job-at-change/job-at-change.component"; import JobPartsQueueCount from "../job-parts-queue-count/job-parts-queue-count.component"; @@ -24,9 +27,6 @@ import ProductionListColumnNote from "./production-list-columns.productionnote.c import ProductionListColumnCategory from "./production-list-columns.status.category"; import ProductionListColumnStatus from "./production-list-columns.status.component"; import ProductionListColumnTouchTime from "./prodution-list-columns.touchtime.component"; -import { store } from "../../redux/store"; -import { setModalContext } from "../../redux/modals/modals.actions"; -import InstanceRenderManager from "../../utils/instanceRenderMgr"; const r = ({ technician, state, activeStatuses, data, bodyshop, refetch, treatments }) => { const { Enhanced_Payroll } = treatments; @@ -258,7 +258,7 @@ const r = ({ technician, state, activeStatuses, data, bodyshop, refetch, treatme { text: "True", value: true }, { text: "False", value: false } ], - onFilter: (value, record) => value.includes(record.special_coverage_policy), + onFilter: (value, record) => value === record.special_coverage_policy, render: (text, record) => }, @@ -349,6 +349,11 @@ const r = ({ technician, state, activeStatuses, data, bodyshop, refetch, treatme key: "alert", sorter: (a, b) => Number(a.production_vars?.alert || false) - Number(b.production_vars?.alert || false), sortOrder: state.sortedInfo.columnKey === "alert" && state.sortedInfo.order, + filters: [ + { text: "True", value: true }, + { text: "False", value: false } + ], + onFilter: (value, record) => value === (record.production_vars?.alert || false), render: (text, record) => ( ) From 01cbdf14a9192d81a28b29af2353303053645d5e Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Fri, 16 Aug 2024 12:14:52 -0400 Subject: [PATCH 015/478] - Add Alert Filter to visual production board Signed-off-by: Dave Richer --- .../production-board-kanban.component.jsx | 12 +++++------- .../settings/defaultKanbanSettings.js | 4 +++- .../production-board-kanban.settings.component.jsx | 9 ++++++++- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/client/src/components/production-board-kanban/production-board-kanban.component.jsx b/client/src/components/production-board-kanban/production-board-kanban.component.jsx index 62917e9bd..0c515132b 100644 --- a/client/src/components/production-board-kanban/production-board-kanban.component.jsx +++ b/client/src/components/production-board-kanban/production-board-kanban.component.jsx @@ -21,7 +21,7 @@ import { createBoardData } from "./production-board-kanban.utils.js"; import ProductionBoardKanbanSettings from "./settings/production-board-kanban.settings.component.jsx"; import cloneDeep from "lodash/cloneDeep"; import isEqual from "lodash/isEqual"; -import { mergeWithDefaults } from "./settings/defaultKanbanSettings.js"; +import { defaultFilters, mergeWithDefaults } from "./settings/defaultKanbanSettings.js"; import NoteUpsertModal from "../../components/note-upsert-modal/note-upsert-modal.container"; const mapStateToProps = createStructuredSelector({ @@ -41,7 +41,7 @@ const mapDispatchToProps = (dispatch) => ({ function ProductionBoardKanbanComponent({ data, bodyshop, refetch, insertAuditTrail, associationSettings, statuses }) { const [boardLanes, setBoardLanes] = useState({ lanes: [] }); - const [filter, setFilter] = useState({ search: "", employeeId: null }); + const [filter, setFilter] = useState(defaultFilters); const [loading, setLoading] = useState(true); const [isMoving, setIsMoving] = useState(false); const [orientation, setOrientation] = useState("vertical"); @@ -187,11 +187,9 @@ function ProductionBoardKanbanComponent({ data, bodyshop, refetch, insertAuditTr return mergeWithDefaults(kanbanSettings); }, [associationSettings]); - const handleSettingsChange = useCallback((newSettings) => { - setLoading(true); - setOrientation(newSettings.orientation ? "vertical" : "horizontal"); - setLoading(false); - }, []); + const handleSettingsChange = () => { + setFilter(defaultFilters); + }; if (loading) { return ; diff --git a/client/src/components/production-board-kanban/settings/defaultKanbanSettings.js b/client/src/components/production-board-kanban/settings/defaultKanbanSettings.js index 0d10e4e39..87b364ea2 100644 --- a/client/src/components/production-board-kanban/settings/defaultKanbanSettings.js +++ b/client/src/components/production-board-kanban/settings/defaultKanbanSettings.js @@ -48,6 +48,8 @@ const defaultKanbanSettings = { selectedEstimators: [] }; +const defaultFilters = { search: "", employeeId: null, alert: false }; + const mergeWithDefaults = (settings) => { // Create a new object that starts with the default settings const mergedSettings = { ...defaultKanbanSettings }; @@ -64,4 +66,4 @@ const mergeWithDefaults = (settings) => { return mergedSettings; }; -export { defaultKanbanSettings, statisticsItems, mergeWithDefaults }; +export { defaultKanbanSettings, statisticsItems, mergeWithDefaults, defaultFilters }; diff --git a/client/src/components/production-board-kanban/settings/production-board-kanban.settings.component.jsx b/client/src/components/production-board-kanban/settings/production-board-kanban.settings.component.jsx index 23da13412..0d78416f8 100644 --- a/client/src/components/production-board-kanban/settings/production-board-kanban.settings.component.jsx +++ b/client/src/components/production-board-kanban/settings/production-board-kanban.settings.component.jsx @@ -9,8 +9,9 @@ import InformationSettings from "./InformationSettings.jsx"; import StatisticsSettings from "./StatisticsSettings.jsx"; import FilterSettings from "./FilterSettings.jsx"; import PropTypes from "prop-types"; +import { isFunction } from "lodash"; -function ProductionBoardKanbanSettings({ associationSettings, parentLoading, bodyshop, data }) { +function ProductionBoardKanbanSettings({ associationSettings, parentLoading, bodyshop, data, onSettingsChange }) { const [form] = Form.useForm(); const [open, setOpen] = useState(false); const [loading, setLoading] = useState(false); @@ -61,6 +62,11 @@ function ProductionBoardKanbanSettings({ associationSettings, parentLoading, bod setOpen(false); setLoading(false); parentLoading(false); + + if (onSettingsChange && isFunction(onSettingsChange)) { + onSettingsChange(values); + } + setHasChanges(false); }; @@ -156,6 +162,7 @@ ProductionBoardKanbanSettings.propTypes = { associationSettings: PropTypes.object, parentLoading: PropTypes.func.isRequired, bodyshop: PropTypes.object.isRequired, + onSettingsChange: PropTypes.func, data: PropTypes.array }; From e628b1364c3914a01f5859093774542c937e38a5 Mon Sep 17 00:00:00 2001 From: Allan Carr Date: Fri, 16 Aug 2024 12:27:26 -0700 Subject: [PATCH 016/478] IO-2879 Adjust placement of variable Signed-off-by: Allan Carr --- server/accounting/qb-receivables-lines.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/server/accounting/qb-receivables-lines.js b/server/accounting/qb-receivables-lines.js index 40b5bec9c..0dedb4472 100644 --- a/server/accounting/qb-receivables-lines.js +++ b/server/accounting/qb-receivables-lines.js @@ -20,7 +20,6 @@ exports.default = function ({ bodyshop, jobs_by_pk, qbo = false, items, taxCodes //Otherwise, calculate them and add them to the default MAPA and MASH centers. let hasMapaLine = false; let hasMashLine = false; - let isTowingLine = false; //Create the invoice lines mapping. jobs_by_pk.joblines.map((jobline) => { @@ -31,6 +30,9 @@ exports.default = function ({ bodyshop, jobs_by_pk, qbo = false, items, taxCodes if (jobline.db_ref === "936007") { hasMashLine = true; } + + //Check if the line is a Towing Line and flag as such. + let isTowingLine = false; if (jobline.db_ref === "936001" && jobline.line_desc.includes("Towing")) { isTowingLine = true; } From 0054b00d01cbab149ff8cd024ce8a86dc767ba86 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Mon, 19 Aug 2024 17:45:36 -0400 Subject: [PATCH 017/478] - Improve profile handling in product list view Signed-off-by: Dave Richer --- ...tion-list-save-config-button.component.jsx | 93 ----- ...oduction-list-config-manager.component.jsx | 347 ++++++++++++++++++ ...ction-list-table-view-select.component.jsx | 172 --------- .../production-list-table.component.jsx | 27 +- client/src/translations/en_us/common.json | 15 +- client/src/translations/es/common.json | 17 +- client/src/translations/fr/common.json | 15 +- 7 files changed, 397 insertions(+), 289 deletions(-) delete mode 100644 client/src/components/production-list-save-config-button/production-list-save-config-button.component.jsx create mode 100644 client/src/components/production-list-table/production-list-config-manager.component.jsx delete mode 100644 client/src/components/production-list-table/production-list-table-view-select.component.jsx diff --git a/client/src/components/production-list-save-config-button/production-list-save-config-button.component.jsx b/client/src/components/production-list-save-config-button/production-list-save-config-button.component.jsx deleted file mode 100644 index a5f0b0f40..000000000 --- a/client/src/components/production-list-save-config-button/production-list-save-config-button.component.jsx +++ /dev/null @@ -1,93 +0,0 @@ -import { useMutation } from "@apollo/client"; -import React, { useState } from "react"; -import { connect } from "react-redux"; -import { createStructuredSelector } from "reselect"; -import { selectBodyshop } from "../../redux/user/user.selectors"; -import { Button, Form, Input, notification, Popover, Space } from "antd"; -import { useTranslation } from "react-i18next"; -import { UPDATE_SHOP } from "../../graphql/bodyshop.queries"; -import { logImEXEvent } from "../../firebase/firebase.utils"; -import { isFunction } from "lodash"; - -const mapStateToProps = createStructuredSelector({ - //currentUser: selectCurrentUser - bodyshop: selectBodyshop -}); -const mapDispatchToProps = (dispatch) => ({ - //setUserLanguage: language => dispatch(setUserLanguage(language)) -}); - -export function ProductionListSaveConfigButton({ columns, bodyshop, tableState, onSave }) { - const [updateShop] = useMutation(UPDATE_SHOP); - const [loading, setLoading] = useState(false); - const [open, setOpen] = useState(false); - const [form] = Form.useForm(); - - const { t } = useTranslation(); - - const handleSaveConfig = async (values) => { - logImEXEvent("production_save_config"); - setLoading(true); - const result = await updateShop({ - variables: { - id: bodyshop.id, - shop: { - production_config: [ - ...bodyshop.production_config.filter((b) => b.name !== values.name), - //Assign it to the name - { - name: values.name, - columns: { - columnKeys: columns.map((i) => { - return { key: i.key, width: i.width }; - }), - tableState - } - } - ] - } - } - }); - if (!!!result.errors) { - notification["success"]({ message: t("bodyshop.successes.save") }); - if (onSave && isFunction(onSave)) { - onSave(); - } - } else { - notification["error"]({ - message: t("bodyshop.errors.saving", { - error: JSON.stringify(result.errors) - }) - }); - } - form.resetFields(); - setOpen(false); - setLoading(false); - }; - const popMenu = ( -
-
- - - - - - - - -
-
- ); - - return ( - - - - ); -} - -export default connect(mapStateToProps, mapDispatchToProps)(ProductionListSaveConfigButton); diff --git a/client/src/components/production-list-table/production-list-config-manager.component.jsx b/client/src/components/production-list-table/production-list-config-manager.component.jsx new file mode 100644 index 000000000..08d2773bc --- /dev/null +++ b/client/src/components/production-list-table/production-list-config-manager.component.jsx @@ -0,0 +1,347 @@ +import { DeleteOutlined, ExclamationCircleOutlined, PlusOutlined } from "@ant-design/icons"; +import { useMutation } from "@apollo/client"; +import { Button, Form, Input, Modal, notification, Popconfirm, Popover, Select, Space } from "antd"; +import React, { useEffect, useState } from "react"; +import { useTranslation } from "react-i18next"; +import { UPDATE_ACTIVE_PROD_LIST_VIEW } from "../../graphql/associations.queries"; +import { UPDATE_SHOP } from "../../graphql/bodyshop.queries"; +import ProductionListColumns from "../production-list-columns/production-list-columns.data"; +import { useSplitTreatments } from "@splitsoftware/splitio-react"; +import { logImEXEvent } from "../../firebase/firebase.utils"; +import { isFunction } from "lodash"; + +const { confirm } = Modal; + +export function ProductionListConfigManager({ + refetch, + bodyshop, + technician, + currentUser, + state, + data, + columns, + setColumns, + setState, + onSave, + defaultView, + hasUnsavedChanges, + setHasUnsavedChanges +}) { + const { t } = useTranslation(); + const [updateDefaultProdView] = useMutation(UPDATE_ACTIVE_PROD_LIST_VIEW); + const [updateShop] = useMutation(UPDATE_SHOP); + const [loading, setLoading] = useState(false); + const [open, setOpen] = useState(false); + const [isAddingNewProfile, setIsAddingNewProfile] = useState(false); + const [form] = Form.useForm(); + const [activeView, setActiveView] = useState(() => { + const assoc = bodyshop.associations.find((a) => a.useremail === currentUser.email); + return assoc && assoc.default_prod_list_view; + }); + + const defaultState = { + sortedInfo: { + columnKey: "ro_number", + order: null + }, + filteredInfo: {} + }; + + const ensureDefaultState = (state) => { + return { + sortedInfo: state?.sortedInfo || defaultState.sortedInfo, + filteredInfo: state?.filteredInfo || defaultState.filteredInfo, + ...state + }; + }; + + const createDefaultView = async () => { + const defaultConfig = { + name: t("production.constants.main_profile"), + columns: { + columnKeys: columns.map((i) => ({ key: i.key, width: i.width })), + tableState: ensureDefaultState(state) + } + }; + + const result = await updateShop({ + variables: { + id: bodyshop.id, + shop: { + production_config: [defaultConfig] + } + } + }); + + if (!result.errors) { + await updateActiveProdView(t("production.constants.main_profile")); + setColumns(defaultConfig.columns.columnKeys); + setState(defaultConfig.columns.tableState); + notification.success({ message: t("bodyshop.successes.defaultviewcreated") }); + } else { + notification.error({ + message: t("bodyshop.errors.creatingdefaultview", { + error: JSON.stringify(result.errors) + }) + }); + } + }; + + const { + treatments: { Enhanced_Payroll } + } = useSplitTreatments({ + attributes: {}, + names: ["Enhanced_Payroll"], + splitKey: bodyshop.imexshopid + }); + + const updateActiveProdView = async (viewName) => { + const assoc = bodyshop.associations.find((a) => a.useremail === currentUser.email); + if (assoc) { + await updateDefaultProdView({ + variables: { assocId: assoc.id, view: viewName }, + update(cache) { + cache.modify({ + id: cache.identify(bodyshop), + fields: { + associations(existingAssociations) { + return existingAssociations.map((a) => { + if (a.useremail !== currentUser.email) return a; + return { ...a, default_prod_list_view: viewName }; + }); + } + } + }); + } + }); + setActiveView(viewName); + setHasUnsavedChanges(false); + } + }; + + const handleSelect = async (value) => { + if (hasUnsavedChanges) { + confirm({ + title: t("general.labels.unsavedchanges"), + icon: , + content: t("general.messages.unsavedchangespopup"), + onOk: () => proceedWithSelect(value), + onCancel() { + // Do nothing if canceled + } + }); + } else { + await proceedWithSelect(value); + } + }; + + const proceedWithSelect = async (value) => { + if (value === "add_new") { + setIsAddingNewProfile(true); + setOpen(true); + return; + } + + const selectedConfig = bodyshop.production_config.find((pc) => pc.name === value); + + if (selectedConfig) { + const newColumns = selectedConfig.columns.columnKeys.map((k) => { + return { + ...ProductionListColumns({ + bodyshop, + refetch, + technician, + state: ensureDefaultState(state), + data: data, + activeStatuses: bodyshop.md_ro_statuses.active_statuses, + treatments: { Enhanced_Payroll } + }).find((e) => e.key === k.key), + width: k.width + }; + }); + setColumns(newColumns); + const newState = ensureDefaultState(selectedConfig.columns.tableState); + setState(newState); + + await updateActiveProdView(value); + if (onSave && isFunction(onSave)) { + onSave(); + } + } + }; + + const handleTrash = async (name) => { + if (name === t("production.constants.main_profile")) return; + + const remainingConfigs = bodyshop.production_config.filter((b) => b.name !== name); + await updateShop({ + variables: { + id: bodyshop.id, + shop: { + production_config: remainingConfigs + } + }, + awaitRefetchQueries: true + }); + + if (name === activeView) { + if (remainingConfigs.length > 0) { + const nextConfig = remainingConfigs[0]; + await updateActiveProdView(nextConfig.name); + setColumns( + nextConfig.columns.columnKeys.map((k) => { + return { + ...ProductionListColumns({ + technician, + state: ensureDefaultState(state), + refetch, + data: data, + activeStatuses: bodyshop.md_ro_statuses.active_statuses, + treatments: { Enhanced_Payroll } + }).find((e) => e.key === k.key), + width: k.width + }; + }) + ); + setState(ensureDefaultState(nextConfig.columns.tableState)); + } else { + await updateActiveProdView(null); + setColumns([]); + setState(defaultState); // Reset to default state if no configs are left + } + } + }; + + const handleSaveConfig = async (values) => { + logImEXEvent("production_save_config"); + setLoading(true); + + const profileName = isAddingNewProfile ? values.name : activeView; + + const result = await updateShop({ + variables: { + id: bodyshop.id, + shop: { + production_config: [ + ...bodyshop.production_config.filter((b) => b.name !== profileName), + { + name: profileName, + columns: { + columnKeys: columns.map((i) => ({ key: i.key, width: i.width })), + tableState: ensureDefaultState(state) + } + } + ] + } + } + }); + + if (!result.errors) { + notification.success({ message: t("bodyshop.successes.save") }); + if (isAddingNewProfile) { + await updateActiveProdView(profileName); + } + if (onSave && isFunction(onSave)) { + onSave(); + } + setHasUnsavedChanges(false); + } else { + notification.error({ + message: t("bodyshop.errors.saving", { + error: JSON.stringify(result.errors) + }) + }); + } + + form.resetFields(); + setOpen(false); + setLoading(false); + setIsAddingNewProfile(false); + }; + + useEffect(() => { + if (!bodyshop.production_config || bodyshop.production_config.length === 0) { + createDefaultView().catch((e) => { + console.error("Something went wrong saving the production list view Config."); + }); + } else { + setActiveView(defaultView); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [defaultView, bodyshop.production_config]); + + const popMenu = ( +
+
+ {isAddingNewProfile && ( + + + + )} + + + + +
+
+ ); + + return ( + + + + + + + ); +} diff --git a/client/src/components/production-list-table/production-list-table-view-select.component.jsx b/client/src/components/production-list-table/production-list-table-view-select.component.jsx deleted file mode 100644 index f8297fe02..000000000 --- a/client/src/components/production-list-table/production-list-table-view-select.component.jsx +++ /dev/null @@ -1,172 +0,0 @@ -import { DeleteOutlined } from "@ant-design/icons"; -import { useMutation } from "@apollo/client"; -import { Popconfirm, Select } from "antd"; -import React from "react"; -import { useTranslation } from "react-i18next"; -import { connect } from "react-redux"; -import { createStructuredSelector } from "reselect"; -import { UPDATE_ACTIVE_PROD_LIST_VIEW } from "../../graphql/associations.queries"; -import { UPDATE_SHOP } from "../../graphql/bodyshop.queries"; -import { selectTechnician } from "../../redux/tech/tech.selectors"; -import { selectBodyshop, selectCurrentUser } from "../../redux/user/user.selectors"; -import ProductionListColumns from "../production-list-columns/production-list-columns.data"; -import { useSplitTreatments } from "@splitsoftware/splitio-react"; -import { isFunction } from "lodash"; - -const mapStateToProps = createStructuredSelector({ - bodyshop: selectBodyshop, - technician: selectTechnician, - currentUser: selectCurrentUser -}); - -export function ProductionListTable({ - refetch, - bodyshop, - technician, - currentUser, - state, - data, - setColumns, - setState, - onProfileChange -}) { - const { t } = useTranslation(); - const [updateDefaultProdView] = useMutation(UPDATE_ACTIVE_PROD_LIST_VIEW); - const [updateShop] = useMutation(UPDATE_SHOP); - - const { - treatments: { Enhanced_Payroll } - } = useSplitTreatments({ - attributes: {}, - names: ["Enhanced_Payroll"], - splitKey: bodyshop.imexshopid - }); - - const handleSelect = async (value, option) => { - const newColumns = bodyshop.production_config - .filter((pc) => pc.name === value)[0] - .columns.columnKeys.map((k) => { - return { - ...ProductionListColumns({ - bodyshop, - refetch, - technician, - state, - data: data, - activeStatuses: bodyshop.md_ro_statuses.active_statuses, - treatments: { Enhanced_Payroll } - }).find((e) => e.key === k.key), - width: k.width - }; - }); - setColumns(newColumns); - const newState = bodyshop.production_config.filter((pc) => pc.name === value)[0].columns.tableState; - setState(newState); - - const assoc = bodyshop.associations.find((a) => a.useremail === currentUser.email); - - if (assoc) { - await updateDefaultProdView({ - variables: { assocId: assoc.id, view: value }, - update(cache) { - cache.modify({ - id: cache.identify(bodyshop), - fields: { - associations(existingAssociations, { readField }) { - return existingAssociations.map((a) => { - if (a.useremail !== currentUser.email) return a; - return { ...a, default_prod_list_view: value }; - }); - } - } - }); - } - }); - } - - if (onProfileChange && isFunction(onProfileChange)) { - onProfileChange({ value, option, newColumns, newState, assoc }); - } - }; - - const handleTrash = async (name) => { - await updateShop({ - variables: { - id: bodyshop.id, - shop: { - production_config: bodyshop.production_config.filter((b) => b.name !== name) - } - }, - awaitRefetchQueries: true - }); - - setColumns( - bodyshop.production_config[0].columns.columnKeys.map((k) => { - return { - ...ProductionListColumns({ - technician, - state, - refetch, - data: data, - activeStatuses: bodyshop.md_ro_statuses.active_statuses, - treatments: { Enhanced_Payroll } - }).find((e) => e.key === k.key), - width: k.width - }; - }) - ); - - setState(bodyshop.production_config[0].columns.tableState); - }; - const assoc = bodyshop.associations.find((a) => a.useremail === currentUser.email); - - const defaultView = assoc && assoc.default_prod_list_view; - return ( -
- -
- ); -} - -export default connect(mapStateToProps, null)(ProductionListTable); diff --git a/client/src/components/production-list-table/production-list-table.component.jsx b/client/src/components/production-list-table/production-list-table.component.jsx index 6e9e1f918..728330ece 100644 --- a/client/src/components/production-list-table/production-list-table.component.jsx +++ b/client/src/components/production-list-table/production-list-table.component.jsx @@ -10,15 +10,14 @@ import { selectBodyshop, selectCurrentUser } from "../../redux/user/user.selecto import ProductionListColumnsAdd from "../production-list-columns/production-list-columns.add.component"; import ProductionListColumns from "../production-list-columns/production-list-columns.data"; import ProductionListDetail from "../production-list-detail/production-list-detail.component"; -import ProductionListSaveConfigButton from "../production-list-save-config-button/production-list-save-config-button.component"; import ProductionListPrint from "./production-list-print.component"; -import ProductionListTableViewSelect from "./production-list-table-view-select.component"; import ResizeableTitle from "./production-list-table.resizeable.component"; import { useSplitTreatments } from "@splitsoftware/splitio-react"; import { SyncOutlined } from "@ant-design/icons"; import Prompt from "../../utils/prompt.js"; import _ from "lodash"; import AlertComponent from "../alert/alert.component.jsx"; +import { ProductionListConfigManager } from "./production-list-config-manager.component.jsx"; const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop, @@ -270,23 +269,23 @@ export function ProductionListTable({ loading, data, refetch, bodyshop, technici data={data} onColumnAdd={addColumn} /> - { - setHasUnsavedChanges(false); - }} - /> - { - initialStateRef.current = state; - setHasUnsavedChanges(false); - }} + setState={setState} refetch={refetch} data={data} + bodyshop={bodyshop} + technician={technician} + currentUser={currentUser} + defaultView={defaultView} + setHasUnsavedChanges={setHasUnsavedChanges} + hasUnsavedChanges={hasUnsavedChanges} + onSave={() => { + setHasUnsavedChanges(false); + initialStateRef.current = state; + }} /> setSearchText(e.target.value)} diff --git a/client/src/translations/en_us/common.json b/client/src/translations/en_us/common.json index c2d776fbf..79e208d91 100644 --- a/client/src/translations/en_us/common.json +++ b/client/src/translations/en_us/common.json @@ -271,7 +271,8 @@ }, "errors": { "loading": "Unable to load shop details. Please call technical support.", - "saving": "Error encountered while saving. {{message}}" + "saving": "Error encountered while saving. {{message}}", + "creatingdefaultview": "Error creating default view." }, "fields": { "ReceivableCustomField": "QBO Receivable Custom Field {{number}}", @@ -699,7 +700,10 @@ "workingdays": "Working Days" }, "successes": { - "save": "Shop configuration saved successfully. " + "save": "Shop configuration saved successfully. ", + "unsavedchanges": "Unsaved changes will be lost. Are you sure you want to continue?", + "areyousure": "Are you sure you want to continue?", + "defaultviewcreated": "Default view created successfully." }, "validation": { "centermustexist": "The chosen responsibility center does not exist.", @@ -1176,6 +1180,7 @@ "vehicle": "Vehicle" }, "labels": { + "unsavedchanges": "Unsaved change.", "actions": "Actions", "areyousure": "Are you sure?", "barcode": "Barcode", @@ -2731,6 +2736,9 @@ } }, "production": { + "constants":{ + "main_profile": "Main" + }, "options": { "small": "Small", "medium": "Medium", @@ -2834,7 +2842,8 @@ "totalhours": "Total Hrs ", "touchtime": "T/T", "viewname": "View Name", - "alerts": "Alerts" + "alerts": "Alerts", + "addnewprofile": "Add New Profile" }, "successes": { "removed": "Job removed from production." diff --git a/client/src/translations/es/common.json b/client/src/translations/es/common.json index c2da8510a..76f537e61 100644 --- a/client/src/translations/es/common.json +++ b/client/src/translations/es/common.json @@ -271,7 +271,8 @@ }, "errors": { "loading": "No se pueden cargar los detalles de la tienda. Por favor llame al soporte técnico.", - "saving": "" + "saving": "", + "creatingdefaultview": "" }, "fields": { "ReceivableCustomField": "", @@ -699,8 +700,11 @@ "workingdays": "" }, "successes": { - "save": "" - }, + "save": "", + "unsavedchanges": "", + "areyousure": "", + "defaultviewcreated": "" + }, "validation": { "centermustexist": "", "larsplit": "", @@ -1176,6 +1180,7 @@ "vehicle": "" }, "labels": { + "unsavedchanges": "", "actions": "Comportamiento", "areyousure": "", "barcode": "código de barras", @@ -2731,6 +2736,9 @@ } }, "production": { + "constants":{ + "main_profile": "" + }, "options": { "small": "", "medium": "", @@ -2834,7 +2842,8 @@ "totalhours": "", "touchtime": "", "viewname": "", - "alerts": "" + "alerts": "", + "addnewprofile": "" }, "successes": { "removed": "" diff --git a/client/src/translations/fr/common.json b/client/src/translations/fr/common.json index 005accb1c..fccb1ce65 100644 --- a/client/src/translations/fr/common.json +++ b/client/src/translations/fr/common.json @@ -271,7 +271,8 @@ }, "errors": { "loading": "Impossible de charger les détails de la boutique. Veuillez appeler le support technique.", - "saving": "" + "saving": "", + "creatingdefaultview": "" }, "fields": { "ReceivableCustomField": "", @@ -699,7 +700,10 @@ "workingdays": "" }, "successes": { - "save": "" + "save": "", + "unsavedchanges": "", + "areyousure": "", + "defaultviewcreated": "" }, "validation": { "centermustexist": "", @@ -1176,6 +1180,7 @@ "vehicle": "" }, "labels": { + "unsavedchanges": "", "actions": "actes", "areyousure": "", "barcode": "code à barre", @@ -2731,6 +2736,9 @@ } }, "production": { + "constants":{ + "main_profile": "" + }, "options": { "small": "", "medium": "", @@ -2834,7 +2842,8 @@ "totalhours": "", "touchtime": "", "viewname": "", - "alerts": "" + "alerts": "", + "addnewprofile": "" }, "successes": { "removed": "" From f3e43334c4019a5a8153f3d3618038b0a3c25b34 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Tue, 20 Aug 2024 10:44:38 -0400 Subject: [PATCH 018/478] - Improve profile handling in product list view Signed-off-by: Dave Richer --- .../production-list-config-manager.component.jsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/client/src/components/production-list-table/production-list-config-manager.component.jsx b/client/src/components/production-list-table/production-list-config-manager.component.jsx index 08d2773bc..c16f8e40f 100644 --- a/client/src/components/production-list-table/production-list-config-manager.component.jsx +++ b/client/src/components/production-list-table/production-list-config-manager.component.jsx @@ -302,6 +302,9 @@ export function ProductionListConfigManager({ - + - + - + - + @@ -228,7 +224,7 @@ export default function CourtesyCarCreateFormComponent({
- + p.nextservicedate !== c.nextservicedate}> {() => { @@ -260,7 +256,7 @@ export default function CourtesyCarCreateFormComponent({
- + p.registrationexpires !== c.registrationexpires}> {() => { @@ -293,7 +289,7 @@ export default function CourtesyCarCreateFormComponent({ } ]} > - + p.insuranceexpires !== c.insuranceexpires}> {() => { diff --git a/client/src/components/courtesy-car-return-modal/courtesy-car-return-modal.component.jsx b/client/src/components/courtesy-car-return-modal/courtesy-car-return-modal.component.jsx index 589c97ad4..3a7ec4c6b 100644 --- a/client/src/components/courtesy-car-return-modal/courtesy-car-return-modal.component.jsx +++ b/client/src/components/courtesy-car-return-modal/courtesy-car-return-modal.component.jsx @@ -2,7 +2,7 @@ import { Form, InputNumber } from "antd"; import React from "react"; import { useTranslation } from "react-i18next"; import CourtesyCarFuelSlider from "../courtesy-car-fuel-select/courtesy-car-fuel-select.component"; -import FormDatePicker from "../form-date-picker/form-date-picker.component"; +import DateTimePicker from "../form-date-time-picker/form-date-time-picker.component.jsx"; export default function CourtesyCarReturnModalComponent() { const { t } = useTranslation(); @@ -19,7 +19,7 @@ export default function CourtesyCarReturnModalComponent() { } ]} > - + - + diff --git a/client/src/components/eula/eula.component.jsx b/client/src/components/eula/eula.component.jsx index 7399c279b..8d2227e02 100644 --- a/client/src/components/eula/eula.component.jsx +++ b/client/src/components/eula/eula.component.jsx @@ -4,7 +4,6 @@ import Markdown from "react-markdown"; import { createStructuredSelector } from "reselect"; import { selectCurrentEula, selectCurrentUser } from "../../redux/user/user.selectors"; import { connect } from "react-redux"; -import { FormDatePicker } from "../form-date-picker/form-date-picker.component"; import { INSERT_EULA_ACCEPTANCE } from "../../graphql/user.queries"; import { useMutation } from "@apollo/client"; import { acceptEula } from "../../redux/user/user.actions"; @@ -12,6 +11,7 @@ import { useTranslation } from "react-i18next"; import day from "../../utils/day"; import "./eula.styles.scss"; +import DateTimePicker from "../form-date-time-picker/form-date-time-picker.component.jsx"; const Eula = ({ currentEula, currentUser, acceptEula }) => { const [formReady, setFormReady] = useState(false); @@ -216,7 +216,7 @@ const EulaFormComponent = ({ form, handleChange, onFinish, t }) => ( } ]} > - + diff --git a/client/src/components/form-date-picker/form-date-picker.component.jsx b/client/src/components/form-date-picker/form-date-picker.component.jsx deleted file mode 100644 index 500e22d45..000000000 --- a/client/src/components/form-date-picker/form-date-picker.component.jsx +++ /dev/null @@ -1,123 +0,0 @@ -import { DatePicker } from "antd"; -import dayjs from "../../utils/day"; -import React, { useRef } from "react"; - -import { connect } from "react-redux"; -import { createStructuredSelector } from "reselect"; -import { selectBodyshop } from "../../redux/user/user.selectors"; - -const mapStateToProps = createStructuredSelector({ - bodyshop: selectBodyshop -}); -const mapDispatchToProps = (dispatch) => ({ - //setUserLanguage: language => dispatch(setUserLanguage(language)) -}); -export default connect(mapStateToProps, mapDispatchToProps)(FormDatePicker); - -const dateFormat = "MM/DD/YYYY"; - -export function FormDatePicker({ - bodyshop, - value, - onChange, - onBlur, - onlyFuture, - onlyToday, - isDateOnly = true, - ...restProps -}) { - const ref = useRef(); - - const handleChange = (newDate) => { - if (value !== newDate && onChange) { - onChange(isDateOnly ? newDate && newDate.format("YYYY-MM-DD") : newDate); - } - }; - - const handleKeyDown = (e) => { - if (e.key.toLowerCase() === "t") { - if (onChange) { - onChange(isDateOnly ? dayjs().format("YYYY-MM-DD") : dayjs()); - } - } else if (e.key.toLowerCase() === "enter") { - if (ref.current && ref.current.blur) ref.current.blur(); - } - }; - - const handleBlur = (e) => { - const v = e.target.value; - if (!v) return; - - const formats = [ - "MMDDYY", - "MMDDYYYY", - "MM/DD/YY", - "MM/DD/YYYY", - "M/DD/YY", - "M/DD/YYYY", - "MM/D/YY", - "MM/D/YYYY", - "M/D/YY", - "M/D/YYYY", - "D/MM/YY", - "D/MM/YYYY", - "DD/M/YY", - "DD/M/YYYY", - "D/M/YY", - "D/M/YYYY" - ]; - - let _a; - - // Iterate through formats to find the correct one - for (let format of formats) { - _a = dayjs(v, format); - if (v === _a.format(format)) { - break; - } - } - - if (_a.isValid() && value && value.isValid && value.isValid()) { - _a.set({ - hours: value.hours(), - minutes: value.minutes(), - seconds: value.seconds(), - milliseconds: value.milliseconds() - }); - } - - if (_a.isValid() && onChange) { - if (onlyFuture) { - if (dayjs().subtract(1, "day").isBefore(_a)) { - onChange(isDateOnly ? _a.format("YYYY-MM-DD") : _a); - } else { - onChange(isDateOnly ? dayjs().format("YYYY-MM-DD") : dayjs()); - } - } else { - onChange(isDateOnly ? _a.format("YYYY-MM-DD") : _a); - } - } - }; - - return ( -
- { - if (onlyToday) { - return !dayjs().isSame(d, "day"); - } else if (onlyFuture) { - return dayjs().subtract(1, "day").isAfter(d); - } - }} - {...restProps} - /> -
- ); -} diff --git a/client/src/components/form-date-time-picker-enhanced/form-date-time-picker-enhanced.component.jsx b/client/src/components/form-date-time-picker-enhanced/form-date-time-picker-enhanced.component.jsx index 5d41fc5e3..cdabfdfb5 100644 --- a/client/src/components/form-date-time-picker-enhanced/form-date-time-picker-enhanced.component.jsx +++ b/client/src/components/form-date-time-picker-enhanced/form-date-time-picker-enhanced.component.jsx @@ -12,7 +12,6 @@ const mapStateToProps = createStructuredSelector({ const mapDispatchToProps = (dispatch) => ({ //setUserLanguage: language => dispatch(setUserLanguage(language)) }); -export default connect(mapStateToProps, mapDispatchToProps)(FormDateTimePickerEnhanced); const dateFormat = "MM/DD/YYYY h:mm a"; @@ -46,3 +45,5 @@ export function FormDateTimePickerEnhanced({
); } + +export default connect(mapStateToProps, mapDispatchToProps)(FormDateTimePickerEnhanced); diff --git a/client/src/components/form-date-time-picker/form-date-time-picker.component.jsx b/client/src/components/form-date-time-picker/form-date-time-picker.component.jsx index 23af7008a..c1bf6f749 100644 --- a/client/src/components/form-date-time-picker/form-date-time-picker.component.jsx +++ b/client/src/components/form-date-time-picker/form-date-time-picker.component.jsx @@ -1,45 +1,204 @@ -import React, { forwardRef } from "react"; -//import DatePicker from "react-datepicker"; -//import "react-datepicker/src/stylesheets/datepicker.scss"; -import { Space, TimePicker } from "antd"; +import React, { forwardRef, useState } from "react"; +import { DatePicker } from "antd"; import dayjs from "../../utils/day"; -import FormDatePicker from "../form-date-picker/form-date-picker.component"; -//To be used as a form element only. -const DateTimePicker = ({ value, onChange, onBlur, id, onlyFuture, ...restProps }, ref) => { - // const handleChange = (newDate) => { - // if (value !== newDate && onChange) { - // onChange(newDate); - // } - // }; +// To be used as a form element only. + +const DateTimePicker = ( + { value, onChange, onBlur, id, onlyFuture, onlyToday, isDateOnly = false, ...restProps }, + ref +) => { + const [isManualInput, setIsManualInput] = useState(false); + + const handleChange = (newDate) => { + if (newDate && onChange) { + onChange(newDate); + } + setIsManualInput(false); // Reset the manual input flag when using GUI + }; + + const handleKeyDown = (e) => { + setIsManualInput(true); // User is typing, so set the manual input flag + + if (e.key.toLowerCase() === "t") { + if (onChange) { + onChange(dayjs()); + } + } else if (e.key.toLowerCase() === "enter") { + handleBlur(e); + } + }; + + const handleBlur = (e) => { + if (!isManualInput) { + // If the input is not manual, skip the format processing + return; + } + + setIsManualInput(false); // Reset the flag after processing + + const v = e.target.value; + if (!v) return; + + // Convert input to uppercase to handle 'am/pm' as well as 'AM/PM' + const upperV = v.toUpperCase(); + + let _a; + + // Handling common shorthand datetime inputs + const shorthandFormats = [ + "M/D/YY hA", + "M/D/YY h:mmA", + "M/D/YYYY hA", + "M/D/YYYY h:mmA", + "M/D/YY ha", + "M/D/YY h:mma", + "M/D/YYYY ha", + "M/D/YYYY h:mma" + ]; + + for (let format of shorthandFormats) { + _a = dayjs(upperV, format); + if (_a.isValid()) break; + } + + // If shorthand parsing didn't work, fall back to existing formats + if (!_a || !_a.isValid()) { + const formats = [ + "MMDDYY", + "MMDDYYYY", + "MM/DD/YY", + "MM/DD/YYYY", + "M/DD/YY", + "M/DD/YYYY", + "MM/D/YY", + "MM/D/YYYY", + "M/D/YY", + "M/D/YYYY", + "D/MM/YY", + "D/MM/YYYY", + "DD/M/YY", + "DD/M/YYYY", + "D/M/YY", + "D/M/YYYY", + "MMDDYY hh:mm A", + "MMDDYYYY hh:mm A", + "MM/DD/YY hh:mm A", + "MM/DD/YYYY hh:mm A", + "M/DD/YY hh:mm A", + "M/DD/YYYY hh:mm A", + "MM/D/YY hh:mm A", + "MM/D/YYYY hh:mm A", + "M/D/YY hh:mm A", + "M/D/YYYY hh:mm A", + "D/MM/YY hh:mm A", + "D/MM/YYYY hh:mm A", + "DD/M/YY hh:mm A", + "DD/M/YYYY hh:mm A", + "D/M/YY hh:mm A", + "D/M/YYYY hh:mm A", + "MMDDYY hh:mm:ss A", + "MMDDYYYY hh:mm:ss A", + "MM/DD/YY hh:mm:ss A", + "MM/DD/YYYY hh:mm:ss A", + "M/DD/YY hh:mm:ss A", + "M/DD/YYYY hh:mm:ss A", + "MM/D/YY hh:mm:ss A", + "MM/D/YYYY hh:mm:ss A", + "M/D/YY hh:mm:ss A", + "M/D/YYYY hh:mm:ss A", + "D/MM/YY hh:mm:ss A", + "D/MM/YYYY hh:mm:ss A", + "DD/M/YY hh:mm:ss A", + "DD/M/YYYY hh:mm:ss A", + "D/M/YY hh:mm:ss A", + "D/M/YYYY hh:mm:ss A", + "MMDDYY HH:mm", + "MMDDYYYY HH:mm", + "MM/DD/YY HH:mm", + "MM/DD/YYYY HH:mm", + "M/DD/YY HH:mm", + "M/DD/YYYY HH:mm", + "MM/D/YY HH:mm", + "MM/D/YYYY HH:mm", + "M/D/YY HH:mm", + "M/D/YYYY HH:mm", + "D/MM/YY HH:mm", + "D/MM/YYYY HH:mm", + "DD/M/YY HH:mm", + "DD/M/YYYY HH:mm", + "D/M/YY HH:mm", + "D/M/YYYY HH:mm", + "MMDDYY HH:mm:ss", + "MMDDYYYY HH:mm:ss", + "MM/DD/YY HH:mm:ss", + "MM/DD/YYYY HH:mm:ss", + "M/DD/YY HH:mm:ss", + "M/DD/YYYY HH:mm:ss", + "MM/D/YY HH:mm:ss", + "MM/D/YYYY HH:mm:ss", + "M/D/YY HH:mm:ss", + "M/D/YYYY HH:mm:ss", + "D/MM/YY HH:mm:ss", + "D/MM/YYYY HH:mm:ss", + "DD/M/YY HH:mm:ss", + "DD/M/YYYY HH:mm:ss", + "D/M/YY HH:mm:ss", + "D/M/YYYY HH:mm:ss" + ]; + + for (let format of formats) { + _a = dayjs(upperV, format); + if (_a.isValid()) break; + } + } + + if (_a && _a.isValid()) { + if (isDateOnly) { + _a = _a.startOf("day"); // Only apply startOf("day") when isDateOnly is true + } + + if (value && value.isValid && value.isValid()) { + _a.set({ + hours: value.hours(), + minutes: value.minutes(), + seconds: value.seconds(), + milliseconds: value.milliseconds() + }); + } + + if (onlyFuture) { + if (dayjs().subtract(1, "day").isBefore(_a)) { + onChange(_a); + } else { + onChange(dayjs().startOf("day")); + } + } else { + onChange(_a); + } + } + }; return ( - - dayjs().subtract(1, "day").isAfter(d) - })} - value={value} - onBlur={onBlur} - onChange={onChange} - onlyFuture={onlyFuture} - isDateOnly={false} - /> - - + dayjs().isAfter(d) - })} - onChange={onChange} - disableSeconds={true} - minuteStep={15} - onBlur={onBlur} - format="hh:mm a" + onChange={handleChange} + onBlur={onBlur || handleBlur} + disabledDate={(d) => { + if (onlyToday) { + return !dayjs().isSame(d, "day"); + } else if (onlyFuture) { + return dayjs().subtract(1, "day").isAfter(d); + } + return false; + }} {...restProps} /> - +
); }; diff --git a/client/src/components/job-scoreboard-add-button/job-scoreboard-add-button.component.jsx b/client/src/components/job-scoreboard-add-button/job-scoreboard-add-button.component.jsx index a8c673552..e17368ed9 100644 --- a/client/src/components/job-scoreboard-add-button/job-scoreboard-add-button.component.jsx +++ b/client/src/components/job-scoreboard-add-button/job-scoreboard-add-button.component.jsx @@ -10,8 +10,8 @@ import { QUERY_SCOREBOARD_ENTRY, UPDATE_SCOREBOARD_ENTRY } from "../../graphql/scoreboard.queries"; -import FormDatePicker from "../form-date-picker/form-date-picker.component"; import LoadingSpinner from "../loading-spinner/loading-spinner.component"; +import DateTimePicker from "../form-date-time-picker/form-date-time-picker.component.jsx"; export default function ScoreboardAddButton({ job, disabled, ...otherBtnProps }) { const { t } = useTranslation(); @@ -86,7 +86,7 @@ export default function ScoreboardAddButton({ job, disabled, ...otherBtnProps }) } ]} > - + ({ - insertAuditTrail: ({ jobid, operation, type }) => dispatch(insertAuditTrail({ jobid, operation, type })) + insertAuditTrail: ({ jobid, operation, type }) => + dispatch( + insertAuditTrail({ + jobid, + operation, + type + }) + ) }); export default connect(mapStateToProps, mapDispatchToProps)(JobsAdminDatesChange); @@ -87,7 +93,7 @@ export function JobsAdminDatesChange({ insertAuditTrail, job }) { - + diff --git a/client/src/components/jobs-create-jobs-info/jobs-create-jobs-info.component.jsx b/client/src/components/jobs-create-jobs-info/jobs-create-jobs-info.component.jsx index 54708449b..c50894005 100644 --- a/client/src/components/jobs-create-jobs-info/jobs-create-jobs-info.component.jsx +++ b/client/src/components/jobs-create-jobs-info/jobs-create-jobs-info.component.jsx @@ -1,18 +1,9 @@ -import { - Collapse, - Form, - Input, - InputNumber, - Select, - Space, - Switch, -} from "antd"; +import { Collapse, Form, Input, InputNumber, Select, Space, Switch } from "antd"; import React from "react"; import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; import { createStructuredSelector } from "reselect"; import { selectBodyshop } from "../../redux/user/user.selectors"; -import FormDatePicker from "../form-date-picker/form-date-picker.component"; import CurrencyInput from "../form-items-formatted/currency-form-item.component"; import FormItemEmail from "../form-items-formatted/email-form-item.component"; import FormItemPhone, { PhoneItemFormatterValidation } from "../form-items-formatted/phone-form-item.component"; @@ -29,6 +20,7 @@ import JobsDetailRatesTaxes from "../jobs-detail-rates/jobs-detail-rates.taxes.c import JobsMarkPstExempt from "../jobs-mark-pst-exempt/jobs-mark-pst-exempt.component"; import LayoutFormRow from "../layout-form-row/layout-form-row.component"; import InstanceRenderManager from "../../utils/instanceRenderMgr"; +import DateTimePicker from "../form-date-time-picker/form-date-time-picker.component.jsx"; const mapStateToProps = createStructuredSelector({ //currentUser: selectCurrentUser @@ -61,10 +53,7 @@ export function JobsCreateJobsInfo({ bodyshop, form, selected }) { - + @@ -116,7 +105,7 @@ export function JobsCreateJobsInfo({ bodyshop, form, selected }) { - + diff --git a/client/src/components/jobs-create-vehicle-info/jobs-create-vehicle-info.new.component.jsx b/client/src/components/jobs-create-vehicle-info/jobs-create-vehicle-info.new.component.jsx index d3026676d..e38c2f28d 100644 --- a/client/src/components/jobs-create-vehicle-info/jobs-create-vehicle-info.new.component.jsx +++ b/client/src/components/jobs-create-vehicle-info/jobs-create-vehicle-info.new.component.jsx @@ -2,9 +2,9 @@ import { Form, Input } from "antd"; import React, { useContext } from "react"; import { useTranslation } from "react-i18next"; import JobCreateContext from "../../pages/jobs-create/jobs-create.context"; -import FormDatePicker from "../form-date-picker/form-date-picker.component"; import LayoutFormRow from "../layout-form-row/layout-form-row.component"; import JobsCreateVehicleInfoPredefined from "./jobs-create-vehicle-info.predefined.component"; +import DateTimePicker from "../form-date-time-picker/form-date-time-picker.component.jsx"; export default function JobsCreateVehicleInfoNewComponent({ form }) { const [state] = useContext(JobCreateContext); @@ -113,7 +113,7 @@ export default function JobsCreateVehicleInfoNewComponent({ form }) { - + diff --git a/client/src/components/jobs-detail-dates/jobs-detail-dates.component.jsx b/client/src/components/jobs-detail-dates/jobs-detail-dates.component.jsx index 80598717e..f32f1b94d 100644 --- a/client/src/components/jobs-detail-dates/jobs-detail-dates.component.jsx +++ b/client/src/components/jobs-detail-dates/jobs-detail-dates.component.jsx @@ -5,7 +5,6 @@ import { connect } from "react-redux"; import { createStructuredSelector } from "reselect"; import { selectJobReadOnly } from "../../redux/application/application.selectors"; import { selectBodyshop } from "../../redux/user/user.selectors"; -import FormDatePicker from "../form-date-picker/form-date-picker.component"; import DateTimePicker from "../form-date-time-picker/form-date-time-picker.component"; import FormRow from "../layout-form-row/layout-form-row.component"; @@ -30,7 +29,7 @@ export function JobsDetailDatesComponent({ jobRO, job, bodyshop }) {
- + @@ -45,7 +44,7 @@ export function JobsDetailDatesComponent({ jobRO, job, bodyshop }) { - + @@ -85,7 +84,6 @@ export function JobsDetailDatesComponent({ jobRO, job, bodyshop }) { rules={[ { required: jobInPostProduction - //message: t("general.validation.required"), } ]} > diff --git a/client/src/components/jobs-detail-general/jobs-detail-general.component.jsx b/client/src/components/jobs-detail-general/jobs-detail-general.component.jsx index df2b43cd0..1fee1a6b5 100644 --- a/client/src/components/jobs-detail-general/jobs-detail-general.component.jsx +++ b/client/src/components/jobs-detail-general/jobs-detail-general.component.jsx @@ -5,7 +5,6 @@ import { connect } from "react-redux"; import { createStructuredSelector } from "reselect"; import { selectJobReadOnly } from "../../redux/application/application.selectors"; import { selectBodyshop } from "../../redux/user/user.selectors"; -import FormDatePicker from "../form-date-picker/form-date-picker.component"; import CurrencyInput from "../form-items-formatted/currency-form-item.component"; import FormItemEmail from "../form-items-formatted/email-form-item.component"; import FormItemPhone, { PhoneItemFormatterValidation } from "../form-items-formatted/phone-form-item.component"; @@ -13,6 +12,7 @@ import Car from "../job-damage-visual/job-damage-visual.component"; import JobsDetailChangeEstimator from "../jobs-detail-change-estimator/jobs-detail-change-estimator.component"; import JobsDetailChangeFileHandler from "../jobs-detail-change-filehandler/jobs-detail-change-filehandler.component"; import FormRow from "../layout-form-row/layout-form-row.component"; +import DateTimePicker from "../form-date-time-picker/form-date-time-picker.component.jsx"; const mapStateToProps = createStructuredSelector({ jobRO: selectJobReadOnly, @@ -152,7 +152,7 @@ export function JobsDetailGeneral({ bodyshop, jobRO, job, form }) { - + diff --git a/client/src/components/parts-order-backorder-eta/parts-order-backorder-eta.component.jsx b/client/src/components/parts-order-backorder-eta/parts-order-backorder-eta.component.jsx index dc27b3601..db0d49f70 100644 --- a/client/src/components/parts-order-backorder-eta/parts-order-backorder-eta.component.jsx +++ b/client/src/components/parts-order-backorder-eta/parts-order-backorder-eta.component.jsx @@ -8,8 +8,8 @@ import { logImEXEvent } from "../../firebase/firebase.utils"; import { MUTATION_UPDATE_BO_ETA } from "../../graphql/parts-orders.queries"; import { selectBodyshop } from "../../redux/user/user.selectors"; import { DateFormatter } from "../../utils/DateFormatter"; -import FormDatePicker from "../form-date-picker/form-date-picker.component"; import { CalendarFilled } from "@ant-design/icons"; +import DateTimePicker from "../form-date-time-picker/form-date-time-picker.component.jsx"; const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop @@ -62,7 +62,7 @@ export function PartsOrderBackorderEta({
- + diff --git a/client/src/components/report-center-modal/report-center-modal-filters-sorters-component.jsx b/client/src/components/report-center-modal/report-center-modal-filters-sorters-component.jsx index ace62cf27..a696ab5c6 100644 --- a/client/src/components/report-center-modal/report-center-modal-filters-sorters-component.jsx +++ b/client/src/components/report-center-modal/report-center-modal-filters-sorters-component.jsx @@ -6,7 +6,7 @@ import { useTranslation } from "react-i18next"; import { getOrderOperatorsByType, getWhereOperatorsByType } from "../../utils/graphQLmodifier"; import LoadingSkeleton from "../loading-skeleton/loading-skeleton.component"; import { generateInternalReflections } from "./report-center-modal-utils"; -import { FormDatePicker } from "../form-date-picker/form-date-picker.component.jsx"; +import DateTimePicker from "../form-date-time-picker/form-date-time-picker.component.jsx"; export default function ReportCenterModalFiltersSortersComponent({ form, bodyshop }) { return ( @@ -196,7 +196,8 @@ function FiltersSection({ filters, form, bodyshop }) { // We have a type of date, so we will use a date picker if (type === "date") { return ( - form.setFieldValue(fieldPath, date)} /> diff --git a/client/src/components/scoreboard-entry-edit/scoreboard-entry-edit.component.jsx b/client/src/components/scoreboard-entry-edit/scoreboard-entry-edit.component.jsx index 4c099a13c..9d09dedcd 100644 --- a/client/src/components/scoreboard-entry-edit/scoreboard-entry-edit.component.jsx +++ b/client/src/components/scoreboard-entry-edit/scoreboard-entry-edit.component.jsx @@ -4,7 +4,7 @@ import dayjs from "../../utils/day"; import React, { useState } from "react"; import { useTranslation } from "react-i18next"; import { UPDATE_SCOREBOARD_ENTRY } from "../../graphql/scoreboard.queries"; -import FormDatePicker from "../form-date-picker/form-date-picker.component"; +import DateTimePicker from "../form-date-time-picker/form-date-time-picker.component.jsx"; export default function ScoreboardEntryEdit({ entry }) { const [open, setOpen] = useState(false); @@ -52,7 +52,7 @@ export default function ScoreboardEntryEdit({ entry }) { } ]} > - + - + - + - + - - + diff --git a/client/src/components/time-ticket-modal/time-ticket-modal.component.jsx b/client/src/components/time-ticket-modal/time-ticket-modal.component.jsx index b05c9658e..7a86d0d56 100644 --- a/client/src/components/time-ticket-modal/time-ticket-modal.component.jsx +++ b/client/src/components/time-ticket-modal/time-ticket-modal.component.jsx @@ -7,8 +7,8 @@ import { createStructuredSelector } from "reselect"; import { GET_LINE_TICKET_BY_PK } from "../../graphql/jobs-lines.queries"; import { selectAuthLevel, selectBodyshop } from "../../redux/user/user.selectors"; import EmployeeSearchSelect from "../employee-search-select/employee-search-select.component"; -import FormDatePicker from "../form-date-picker/form-date-picker.component"; import FormDateTimePicker from "../form-date-time-picker/form-date-time-picker.component"; +import DateTimePicker from "../form-date-time-picker/form-date-time-picker.component"; import JobSearchSelect from "../job-search-select/job-search-select.component"; import LaborAllocationsTable from "../labor-allocations-table/labor-allocations-table.component"; import { CalculateAllocationsTotals } from "../labor-allocations-table/labor-allocations-table.utility"; @@ -60,8 +60,8 @@ export function TimeTicketModalComponent({ {item.cost_center === "timetickets.labels.shift" ? t(item.cost_center) : bodyshop.cdk_dealerid || bodyshop.pbs_serialnumber || Enhanced_Payroll.treatment === "on" - ? t(`joblines.fields.lbr_types.${item.cost_center.toUpperCase()}`) - : item.cost_center} + ? t(`joblines.fields.lbr_types.${item.cost_center.toUpperCase()}`) + : item.cost_center} ))} @@ -111,7 +111,7 @@ export function TimeTicketModalComponent({ } ]} > - + - + From 1e7c285fefb281278f366e38a09659b38fedc320 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Tue, 20 Aug 2024 13:46:35 -0400 Subject: [PATCH 021/478] - Address changes to profile from call Signed-off-by: Dave Richer --- ...oduction-list-config-manager.component.jsx | 25 ++++++++++++++++--- client/src/translations/en_us/common.json | 2 +- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/client/src/components/production-list-table/production-list-config-manager.component.jsx b/client/src/components/production-list-table/production-list-config-manager.component.jsx index c16f8e40f..ebe001c3e 100644 --- a/client/src/components/production-list-table/production-list-config-manager.component.jsx +++ b/client/src/components/production-list-table/production-list-config-manager.component.jsx @@ -59,11 +59,30 @@ export function ProductionListConfigManager({ const defaultConfig = { name: t("production.constants.main_profile"), columns: { - columnKeys: columns.map((i) => ({ key: i.key, width: i.width })), + columnKeys: [ + { key: "ro_number", width: 100 }, + { key: "ownr", width: 100 }, + { key: "vehicle", width: 100 }, + { key: "ins_co_nm", width: 100 }, + { key: "actual_in", width: 100 }, + { key: "scheduled_completion", width: 100 }, + { key: "labhrs", width: 100 }, + { key: "employee_body", width: 100 }, + { key: "larhrs", width: 100 }, + { key: "employee_refinish", width: 100 }, + { key: "tt", width: 100 }, + { key: "status", width: 100 }, + { key: "sublets", width: 100 }, + { key: "viewdetail", width: 100 } + ], tableState: ensureDefaultState(state) } }; + // Immediately update the columns and state to reflect the new default view + setColumns(defaultConfig.columns.columnKeys); + setState(defaultConfig.columns.tableState); + const result = await updateShop({ variables: { id: bodyshop.id, @@ -75,9 +94,7 @@ export function ProductionListConfigManager({ if (!result.errors) { await updateActiveProdView(t("production.constants.main_profile")); - setColumns(defaultConfig.columns.columnKeys); - setState(defaultConfig.columns.tableState); - notification.success({ message: t("bodyshop.successes.defaultviewcreated") }); + window.location.reload(); // Reload the page } else { notification.error({ message: t("bodyshop.errors.creatingdefaultview", { diff --git a/client/src/translations/en_us/common.json b/client/src/translations/en_us/common.json index 79e208d91..ff93baff8 100644 --- a/client/src/translations/en_us/common.json +++ b/client/src/translations/en_us/common.json @@ -2737,7 +2737,7 @@ }, "production": { "constants":{ - "main_profile": "Main" + "main_profile": "Default" }, "options": { "small": "Small", From 8018daa2dca4ca5cb968e9a07312376d1fe31941 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Tue, 20 Aug 2024 14:12:19 -0400 Subject: [PATCH 022/478] - Address changes to profile from call Signed-off-by: Dave Richer --- ...oduction-list-config-manager.component.jsx | 83 +++++++++++++++++-- 1 file changed, 77 insertions(+), 6 deletions(-) diff --git a/client/src/components/production-list-table/production-list-config-manager.component.jsx b/client/src/components/production-list-table/production-list-config-manager.component.jsx index ebe001c3e..c33b164ff 100644 --- a/client/src/components/production-list-table/production-list-config-manager.component.jsx +++ b/client/src/components/production-list-table/production-list-config-manager.component.jsx @@ -79,10 +79,6 @@ export function ProductionListConfigManager({ } }; - // Immediately update the columns and state to reflect the new default view - setColumns(defaultConfig.columns.columnKeys); - setState(defaultConfig.columns.tableState); - const result = await updateShop({ variables: { id: bodyshop.id, @@ -161,6 +157,41 @@ export function ProductionListConfigManager({ const selectedConfig = bodyshop.production_config.find((pc) => pc.name === value); + // If the selected profile doesn't exist, revert to the main profile + if (!selectedConfig) { + const mainProfileConfig = bodyshop.production_config.find( + (pc) => pc.name === t("production.constants.main_profile") + ); + + if (mainProfileConfig) { + await updateActiveProdView(t("production.constants.main_profile")); + setColumns( + mainProfileConfig.columns.columnKeys.map((k) => { + return { + ...ProductionListColumns({ + bodyshop, + refetch, + technician, + state: ensureDefaultState(state), + data: data, + activeStatuses: bodyshop.md_ro_statuses.active_statuses, + treatments: { Enhanced_Payroll } + }).find((e) => e.key === k.key), + width: k.width + }; + }) + ); + const newState = ensureDefaultState(mainProfileConfig.columns.tableState); + setState(newState); + + if (onSave && isFunction(onSave)) { + onSave(); + } + return; + } + } + + // If the selected profile exists, proceed as normal if (selectedConfig) { const newColumns = selectedConfig.columns.columnKeys.map((k) => { return { @@ -191,6 +222,7 @@ export function ProductionListConfigManager({ if (name === t("production.constants.main_profile")) return; const remainingConfigs = bodyshop.production_config.filter((b) => b.name !== name); + await updateShop({ variables: { id: bodyshop.id, @@ -202,6 +234,7 @@ export function ProductionListConfigManager({ }); if (name === activeView) { + // Only switch profiles if the deleted profile was the active profile if (remainingConfigs.length > 0) { const nextConfig = remainingConfigs[0]; await updateActiveProdView(nextConfig.name); @@ -277,12 +310,50 @@ export function ProductionListConfigManager({ }; useEffect(() => { + const validateAndSetDefaultView = () => { + const configExists = bodyshop.production_config.some((pc) => pc.name === defaultView); + + if (!configExists) { + // If the default view doesn't exist, revert to the main profile + const mainProfileConfig = bodyshop.production_config.find( + (pc) => pc.name === t("production.constants.main_profile") + ); + + if (mainProfileConfig) { + setActiveView(t("production.constants.main_profile")); + + setColumns( + mainProfileConfig.columns.columnKeys.map((k) => { + return { + ...ProductionListColumns({ + bodyshop, + refetch, + technician, + state: ensureDefaultState(state), + data: data, + activeStatuses: bodyshop.md_ro_statuses.active_statuses, + treatments: { Enhanced_Payroll } + }).find((e) => e.key === k.key), + width: k.width + }; + }) + ); + setState(ensureDefaultState(mainProfileConfig.columns.tableState)); + + updateActiveProdView(t("production.constants.main_profile")); + } + } else { + // If the default view exists, set it as active + setActiveView(defaultView); + } + }; + if (!bodyshop.production_config || bodyshop.production_config.length === 0) { createDefaultView().catch((e) => { console.error("Something went wrong saving the production list view Config."); }); } else { - setActiveView(defaultView); + validateAndSetDefaultView(); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [defaultView, bodyshop.production_config]); @@ -326,7 +397,7 @@ export function ProductionListConfigManager({ placeholder={t("production.labels.selectview")} optionLabelProp="label" popupMatchSelectWidth={false} - value={activeView} + value={activeView} // Ensure this only changes when appropriate > {bodyshop.production_config .slice() From 46da3285f846a44aecb46201736fefc3f865f464 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Tue, 20 Aug 2024 14:20:58 -0400 Subject: [PATCH 023/478] - Revert ZOHO (put back in) Signed-off-by: Dave Richer --- client/index.html | 88 +++++++++-------------------------------------- 1 file changed, 17 insertions(+), 71 deletions(-) diff --git a/client/index.html b/client/index.html index 7e4aa27db..9d415aaf6 100644 --- a/client/index.html +++ b/client/index.html @@ -46,77 +46,23 @@ <% } %> <% if (env.VITE_APP_INSTANCE === 'ROME') { %> Rome Online - - - - - - - - - - - + <% } %> <% if (env.VITE_APP_INSTANCE === 'PROMANAGER') { %> ProManager From 1c186f7fa5eedd09b23ce6f49707ca3b8ad5b04f Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Tue, 20 Aug 2024 14:27:28 -0400 Subject: [PATCH 024/478] - fix missed FormDatePicker reference Signed-off-by: Dave Richer --- .../shop-employees/shop-employees-add-vacation.component.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/components/shop-employees/shop-employees-add-vacation.component.jsx b/client/src/components/shop-employees/shop-employees-add-vacation.component.jsx index dd69b3115..a60a91d21 100644 --- a/client/src/components/shop-employees/shop-employees-add-vacation.component.jsx +++ b/client/src/components/shop-employees/shop-employees-add-vacation.component.jsx @@ -90,7 +90,7 @@ export default function ShopEmployeeAddVacation({ employee }) { }) ]} > - + From 9058aca16e53e273d7f34906ceb8c5bc62ff3e0c Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Tue, 20 Aug 2024 14:44:28 -0400 Subject: [PATCH 025/478] - only load chataffix in prod, no more annoying messages / alert dismissals in dev Signed-off-by: Dave Richer --- client/src/pages/manage/manage.page.component.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/pages/manage/manage.page.component.jsx b/client/src/pages/manage/manage.page.component.jsx index db7146e15..dc81b0b0c 100644 --- a/client/src/pages/manage/manage.page.component.jsx +++ b/client/src/pages/manage/manage.page.component.jsx @@ -571,7 +571,7 @@ export function Manage({ conflict, bodyshop }) { return ( <> - + {import.meta.env.PROD && } From cc2d474fdae00f7a76ff88d30f48317858d74401 Mon Sep 17 00:00:00 2001 From: Allan Carr Date: Tue, 20 Aug 2024 17:12:11 -0700 Subject: [PATCH 026/478] IO-2887 Null out BillData if returnfrombill is not available Signed-off-by: Allan Carr --- .../parts-order-list-table-drawer.component.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/components/parts-order-list-table/parts-order-list-table-drawer.component.jsx b/client/src/components/parts-order-list-table/parts-order-list-table-drawer.component.jsx index 5dde61a72..168f7687e 100644 --- a/client/src/components/parts-order-list-table/parts-order-list-table-drawer.component.jsx +++ b/client/src/components/parts-order-list-table/parts-order-list-table-drawer.component.jsx @@ -103,7 +103,7 @@ export function PartsOrderListTableDrawerComponent({ } catch (error) { console.error("Error fetching bill data:", error); } - } + } else setBillData(null); }; fetchData(); }, [selectedPartsOrderRecord, billQuery]); From 678ca591c16020e21a6eab1b01689448dd3fcbe2 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Wed, 21 Aug 2024 12:50:11 -0400 Subject: [PATCH 027/478] - enhancements / improvements / stuff Signed-off-by: Dave Richer --- ...rm-date-time-picker-enhanced.component.jsx | 49 ---- .../form-date-time-picker.component.jsx | 276 +++++++----------- .../form-date-time-picker/formats.js | 93 ++++++ .../task-upsert-modal.component.jsx | 8 +- 4 files changed, 197 insertions(+), 229 deletions(-) delete mode 100644 client/src/components/form-date-time-picker-enhanced/form-date-time-picker-enhanced.component.jsx create mode 100644 client/src/components/form-date-time-picker/formats.js diff --git a/client/src/components/form-date-time-picker-enhanced/form-date-time-picker-enhanced.component.jsx b/client/src/components/form-date-time-picker-enhanced/form-date-time-picker-enhanced.component.jsx deleted file mode 100644 index cdabfdfb5..000000000 --- a/client/src/components/form-date-time-picker-enhanced/form-date-time-picker-enhanced.component.jsx +++ /dev/null @@ -1,49 +0,0 @@ -import { DatePicker } from "antd"; -import dayjs from "../../utils/day.js"; -import React, { useRef } from "react"; - -import { connect } from "react-redux"; -import { createStructuredSelector } from "reselect"; -import { selectBodyshop } from "../../redux/user/user.selectors.js"; - -const mapStateToProps = createStructuredSelector({ - bodyshop: selectBodyshop -}); -const mapDispatchToProps = (dispatch) => ({ - //setUserLanguage: language => dispatch(setUserLanguage(language)) -}); - -const dateFormat = "MM/DD/YYYY h:mm a"; - -export function FormDateTimePickerEnhanced({ - bodyshop, - value, - onBlur, - onlyFuture, - onlyToday, - isDateOnly = true, - ...restProps -}) { - const ref = useRef(); - return ( -
- { - if (onlyToday) { - return !dayjs().isSame(d, "day"); - } else if (onlyFuture) { - return dayjs().subtract(1, "day").isAfter(d); - } - }} - {...restProps} - /> -
- ); -} - -export default connect(mapStateToProps, mapDispatchToProps)(FormDateTimePickerEnhanced); diff --git a/client/src/components/form-date-time-picker/form-date-time-picker.component.jsx b/client/src/components/form-date-time-picker/form-date-time-picker.component.jsx index c1bf6f749..90f5fc16d 100644 --- a/client/src/components/form-date-time-picker/form-date-time-picker.component.jsx +++ b/client/src/components/form-date-time-picker/form-date-time-picker.component.jsx @@ -1,205 +1,135 @@ -import React, { forwardRef, useState } from "react"; +import React, { useCallback, useState } from "react"; import { DatePicker } from "antd"; import dayjs from "../../utils/day"; +import { formats, shorthandFormats } from "./formats.js"; +import PropTypes from "prop-types"; -// To be used as a form element only. - -const DateTimePicker = ( - { value, onChange, onBlur, id, onlyFuture, onlyToday, isDateOnly = false, ...restProps }, - ref -) => { +const DateTimePicker = ({ value, onChange, onBlur, id, onlyFuture, onlyToday, isDateOnly = false, ...restProps }) => { const [isManualInput, setIsManualInput] = useState(false); - const handleChange = (newDate) => { - if (newDate && onChange) { - onChange(newDate); - } - setIsManualInput(false); // Reset the manual input flag when using GUI - }; - - const handleKeyDown = (e) => { - setIsManualInput(true); // User is typing, so set the manual input flag - - if (e.key.toLowerCase() === "t") { - if (onChange) { - onChange(dayjs()); + const handleChange = useCallback( + (newDate) => { + if (newDate === null && onChange) { + onChange(null); + } else if (newDate && onChange) { + onChange(newDate); } - } else if (e.key.toLowerCase() === "enter") { - handleBlur(e); - } - }; + setIsManualInput(false); + }, + [onChange] + ); - const handleBlur = (e) => { - if (!isManualInput) { - // If the input is not manual, skip the format processing - return; - } + const handleBlur = useCallback( + (e) => { + if (!isManualInput) { + return; + } - setIsManualInput(false); // Reset the flag after processing + setIsManualInput(false); - const v = e.target.value; - if (!v) return; + const v = e.target.value; + if (!v) return; - // Convert input to uppercase to handle 'am/pm' as well as 'AM/PM' - const upperV = v.toUpperCase(); + const upperV = v.toUpperCase(); - let _a; + let _a; - // Handling common shorthand datetime inputs - const shorthandFormats = [ - "M/D/YY hA", - "M/D/YY h:mmA", - "M/D/YYYY hA", - "M/D/YYYY h:mmA", - "M/D/YY ha", - "M/D/YY h:mma", - "M/D/YYYY ha", - "M/D/YYYY h:mma" - ]; - - for (let format of shorthandFormats) { - _a = dayjs(upperV, format); - if (_a.isValid()) break; - } - - // If shorthand parsing didn't work, fall back to existing formats - if (!_a || !_a.isValid()) { - const formats = [ - "MMDDYY", - "MMDDYYYY", - "MM/DD/YY", - "MM/DD/YYYY", - "M/DD/YY", - "M/DD/YYYY", - "MM/D/YY", - "MM/D/YYYY", - "M/D/YY", - "M/D/YYYY", - "D/MM/YY", - "D/MM/YYYY", - "DD/M/YY", - "DD/M/YYYY", - "D/M/YY", - "D/M/YYYY", - "MMDDYY hh:mm A", - "MMDDYYYY hh:mm A", - "MM/DD/YY hh:mm A", - "MM/DD/YYYY hh:mm A", - "M/DD/YY hh:mm A", - "M/DD/YYYY hh:mm A", - "MM/D/YY hh:mm A", - "MM/D/YYYY hh:mm A", - "M/D/YY hh:mm A", - "M/D/YYYY hh:mm A", - "D/MM/YY hh:mm A", - "D/MM/YYYY hh:mm A", - "DD/M/YY hh:mm A", - "DD/M/YYYY hh:mm A", - "D/M/YY hh:mm A", - "D/M/YYYY hh:mm A", - "MMDDYY hh:mm:ss A", - "MMDDYYYY hh:mm:ss A", - "MM/DD/YY hh:mm:ss A", - "MM/DD/YYYY hh:mm:ss A", - "M/DD/YY hh:mm:ss A", - "M/DD/YYYY hh:mm:ss A", - "MM/D/YY hh:mm:ss A", - "MM/D/YYYY hh:mm:ss A", - "M/D/YY hh:mm:ss A", - "M/D/YYYY hh:mm:ss A", - "D/MM/YY hh:mm:ss A", - "D/MM/YYYY hh:mm:ss A", - "DD/M/YY hh:mm:ss A", - "DD/M/YYYY hh:mm:ss A", - "D/M/YY hh:mm:ss A", - "D/M/YYYY hh:mm:ss A", - "MMDDYY HH:mm", - "MMDDYYYY HH:mm", - "MM/DD/YY HH:mm", - "MM/DD/YYYY HH:mm", - "M/DD/YY HH:mm", - "M/DD/YYYY HH:mm", - "MM/D/YY HH:mm", - "MM/D/YYYY HH:mm", - "M/D/YY HH:mm", - "M/D/YYYY HH:mm", - "D/MM/YY HH:mm", - "D/MM/YYYY HH:mm", - "DD/M/YY HH:mm", - "DD/M/YYYY HH:mm", - "D/M/YY HH:mm", - "D/M/YYYY HH:mm", - "MMDDYY HH:mm:ss", - "MMDDYYYY HH:mm:ss", - "MM/DD/YY HH:mm:ss", - "MM/DD/YYYY HH:mm:ss", - "M/DD/YY HH:mm:ss", - "M/DD/YYYY HH:mm:ss", - "MM/D/YY HH:mm:ss", - "MM/D/YYYY HH:mm:ss", - "M/D/YY HH:mm:ss", - "M/D/YYYY HH:mm:ss", - "D/MM/YY HH:mm:ss", - "D/MM/YYYY HH:mm:ss", - "DD/M/YY HH:mm:ss", - "DD/M/YYYY HH:mm:ss", - "D/M/YY HH:mm:ss", - "D/M/YYYY HH:mm:ss" - ]; - - for (let format of formats) { + for (const format of shorthandFormats) { _a = dayjs(upperV, format); if (_a.isValid()) break; } - } - if (_a && _a.isValid()) { - if (isDateOnly) { - _a = _a.startOf("day"); // Only apply startOf("day") when isDateOnly is true - } - - if (value && value.isValid && value.isValid()) { - _a.set({ - hours: value.hours(), - minutes: value.minutes(), - seconds: value.seconds(), - milliseconds: value.milliseconds() - }); - } - - if (onlyFuture) { - if (dayjs().subtract(1, "day").isBefore(_a)) { - onChange(_a); - } else { - onChange(dayjs().startOf("day")); + if (!_a || !_a.isValid()) { + for (const format of formats) { + _a = dayjs(upperV, format); + if (_a.isValid()) break; } - } else { - onChange(_a); } - } - }; + + if (_a && _a.isValid()) { + if (isDateOnly) { + _a = _a.startOf("day"); + } + + if (value && value.isValid && value.isValid()) { + _a.set({ + hours: value.hours(), + minutes: value.minutes(), + seconds: value.seconds(), + milliseconds: value.milliseconds() + }); + } + + if (onlyFuture) { + if (dayjs().subtract(1, "day").isBefore(_a)) { + onChange(_a); + } else { + onChange(dayjs().startOf("day")); + } + } else { + onChange(_a); + } + } + }, + [isManualInput, isDateOnly, onlyFuture, onChange, value] + ); + + const handleKeyDown = useCallback( + (e) => { + setIsManualInput(true); + + if (e.key.toLowerCase() === "t" && onChange) { + onChange(dayjs()); + } else if (e.key.toLowerCase() === "enter") { + handleBlur(e); + } + }, + [onChange, handleBlur] + ); + + const handleDisabledDate = useCallback( + (current) => { + if (onlyToday) { + return !dayjs().isSame(current, "day"); + } else if (onlyFuture) { + return dayjs().subtract(1, "day").isAfter(current); + } + return false; + }, + [onlyToday, onlyFuture] + ); return (
{ - if (onlyToday) { - return !dayjs().isSame(d, "day"); - } else if (onlyFuture) { - return dayjs().subtract(1, "day").isAfter(d); - } - return false; - }} + disabledDate={handleDisabledDate} {...restProps} />
); }; -export default forwardRef(DateTimePicker); +DateTimePicker.propTypes = { + value: PropTypes.any, + onChange: PropTypes.func, + onBlur: PropTypes.func, + id: PropTypes.string, + onlyFuture: PropTypes.bool, + onlyToday: PropTypes.bool, + isDateOnly: PropTypes.bool +}; + +export default React.memo(DateTimePicker); diff --git a/client/src/components/form-date-time-picker/formats.js b/client/src/components/form-date-time-picker/formats.js new file mode 100644 index 000000000..7683f9990 --- /dev/null +++ b/client/src/components/form-date-time-picker/formats.js @@ -0,0 +1,93 @@ +export const shorthandFormats = [ + "M/D/YY hA", + "M/D/YY h:mmA", + "M/D/YYYY hA", + "M/D/YYYY h:mmA", + "M/D/YY ha", + "M/D/YY h:mma", + "M/D/YYYY ha", + "M/D/YYYY h:mma" +]; + +export const formats = [ + "MMDDYY", + "MMDDYYYY", + "MM/DD/YY", + "MM/DD/YYYY", + "M/DD/YY", + "M/DD/YYYY", + "MM/D/YY", + "MM/D/YYYY", + "M/D/YY", + "M/D/YYYY", + "D/MM/YY", + "D/MM/YYYY", + "DD/M/YY", + "DD/M/YYYY", + "D/M/YY", + "D/M/YYYY", + "MMDDYY hh:mm A", + "MMDDYYYY hh:mm A", + "MM/DD/YY hh:mm A", + "MM/DD/YYYY hh:mm A", + "M/DD/YY hh:mm A", + "M/DD/YYYY hh:mm A", + "MM/D/YY hh:mm A", + "MM/D/YYYY hh:mm A", + "M/D/YY hh:mm A", + "M/D/YYYY hh:mm A", + "D/MM/YY hh:mm A", + "D/MM/YYYY hh:mm A", + "DD/M/YY hh:mm A", + "DD/M/YYYY hh:mm A", + "D/M/YY hh:mm A", + "D/M/YYYY hh:mm A", + "MMDDYY hh:mm:ss A", + "MMDDYYYY hh:mm:ss A", + "MM/DD/YY hh:mm:ss A", + "MM/DD/YYYY hh:mm:ss A", + "M/DD/YY hh:mm:ss A", + "M/DD/YYYY hh:mm:ss A", + "MM/D/YY hh:mm:ss A", + "MM/D/YYYY hh:mm:ss A", + "M/D/YY hh:mm:ss A", + "M/D/YYYY hh:mm:ss A", + "D/MM/YY hh:mm:ss A", + "D/MM/YYYY hh:mm:ss A", + "DD/M/YY hh:mm:ss A", + "DD/M/YYYY hh:mm:ss A", + "D/M/YY hh:mm:ss A", + "D/M/YYYY hh:mm:ss A", + "MMDDYY HH:mm", + "MMDDYYYY HH:mm", + "MM/DD/YY HH:mm", + "MM/DD/YYYY HH:mm", + "M/DD/YY HH:mm", + "M/DD/YYYY HH:mm", + "MM/D/YY HH:mm", + "MM/D/YYYY HH:mm", + "M/D/YY HH:mm", + "M/D/YYYY HH:mm", + "D/MM/YY HH:mm", + "D/MM/YYYY HH:mm", + "DD/M/YY HH:mm", + "DD/M/YYYY HH:mm", + "D/M/YY HH:mm", + "D/M/YYYY HH:mm", + "MMDDYY HH:mm:ss", + "MMDDYYYY HH:mm:ss", + "MM/DD/YY HH:mm:ss", + "MM/DD/YYYY HH:mm:ss", + "M/DD/YY HH:mm:ss", + "M/DD/YYYY HH:mm:ss", + "MM/D/YY HH:mm:ss", + "MM/D/YYYY HH:mm:ss", + "M/D/YY HH:mm:ss", + "M/D/YYYY HH:mm:ss", + "D/MM/YY HH:mm:ss", + "D/MM/YYYY HH:mm:ss", + "DD/M/YY HH:mm:ss", + "DD/M/YYYY HH:mm:ss", + "D/M/YY HH:mm:ss", + "D/M/YYYY HH:mm:ss" +]; diff --git a/client/src/components/task-upsert-modal/task-upsert-modal.component.jsx b/client/src/components/task-upsert-modal/task-upsert-modal.component.jsx index 7d498efc3..562141a40 100644 --- a/client/src/components/task-upsert-modal/task-upsert-modal.component.jsx +++ b/client/src/components/task-upsert-modal/task-upsert-modal.component.jsx @@ -7,7 +7,6 @@ import dayjs from "../../utils/day"; import { connect } from "react-redux"; import LoadingSkeleton from "../loading-skeleton/loading-skeleton.component.jsx"; import JobSearchSelectComponent from "../job-search-select/job-search-select.component.jsx"; -import { FormDateTimePickerEnhanced } from "../form-date-time-picker-enhanced/form-date-time-picker-enhanced.component.jsx"; import DateTimePicker from "../form-date-time-picker/form-date-time-picker.component.jsx"; const mapStateToProps = createStructuredSelector({ @@ -279,12 +278,7 @@ export function TaskUpsertModalComponent({ } ]} > - + From a567d0d6dd4e5ee62f45d74034ce6e14e3998441 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Wed, 21 Aug 2024 13:46:08 -0400 Subject: [PATCH 028/478] - enhancements / improvements / stuff Signed-off-by: Dave Richer --- client/src/components/partner-ping/partner-ping.component.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/components/partner-ping/partner-ping.component.jsx b/client/src/components/partner-ping/partner-ping.component.jsx index f40566fa1..aa0366e5c 100644 --- a/client/src/components/partner-ping/partner-ping.component.jsx +++ b/client/src/components/partner-ping/partner-ping.component.jsx @@ -23,7 +23,7 @@ export function PartnerPingComponent({ bodyshop }) { // Execute the created function directly checkPartnerStatus(bodyshop); // eslint-disable-next-line react-hooks/exhaustive-deps - }, [bodyshop]); + }, [bodyshop?.id]); return <>; } From 153cf6a84044e1145b313ca8fa86599758f40bae Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Wed, 21 Aug 2024 13:53:43 -0400 Subject: [PATCH 029/478] - enhancements / improvements / stuff Signed-off-by: Dave Richer --- .../form-date-time-picker/form-date-time-picker.component.jsx | 1 + 1 file changed, 1 insertion(+) diff --git a/client/src/components/form-date-time-picker/form-date-time-picker.component.jsx b/client/src/components/form-date-time-picker/form-date-time-picker.component.jsx index 90f5fc16d..20388a740 100644 --- a/client/src/components/form-date-time-picker/form-date-time-picker.component.jsx +++ b/client/src/components/form-date-time-picker/form-date-time-picker.component.jsx @@ -79,6 +79,7 @@ const DateTimePicker = ({ value, onChange, onBlur, id, onlyFuture, onlyToday, is setIsManualInput(true); if (e.key.toLowerCase() === "t" && onChange) { + setIsManualInput(false); onChange(dayjs()); } else if (e.key.toLowerCase() === "enter") { handleBlur(e); From ad1ce7b22069f5e35285def1e077386547ea7302 Mon Sep 17 00:00:00 2001 From: Allan Carr Date: Wed, 21 Aug 2024 11:00:59 -0700 Subject: [PATCH 030/478] IO-2888 Production List Employee Sort Enhacement Signed-off-by: Allan Carr --- .../production-list-columns.data.jsx | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/client/src/components/production-list-columns/production-list-columns.data.jsx b/client/src/components/production-list-columns/production-list-columns.data.jsx index fbc9236a5..16a450dab 100644 --- a/client/src/components/production-list-columns/production-list-columns.data.jsx +++ b/client/src/components/production-list-columns/production-list-columns.data.jsx @@ -28,6 +28,11 @@ import ProductionListColumnCategory from "./production-list-columns.status.categ import ProductionListColumnStatus from "./production-list-columns.status.component"; import ProductionListColumnTouchTime from "./prodution-list-columns.touchtime.component"; +const getEmployeeName = (employeeId, employees) => { + const employee = employees.find((e) => e.id === employeeId); + return employee ? `${employee.first_name} ${employee.last_name}` : ""; +}; + const r = ({ technician, state, activeStatuses, data, bodyshop, refetch, treatments }) => { const { Enhanced_Payroll } = treatments; return [ @@ -426,8 +431,8 @@ const r = ({ technician, state, activeStatuses, data, bodyshop, refetch, treatme sortOrder: state.sortedInfo.columnKey === "employee_body" && state.sortedInfo.order, sorter: (a, b) => alphaSort( - bodyshop.employees?.find((e) => e.id === a.employee_body)?.first_name, - bodyshop.employees?.find((e) => e.id === b.employee_body)?.first_name + getEmployeeName(a.employee_body, bodyshop.employees), + getEmployeeName(b.employee_body, bodyshop.employees) ), render: (text, record) => ( @@ -440,8 +445,8 @@ const r = ({ technician, state, activeStatuses, data, bodyshop, refetch, treatme sortOrder: state.sortedInfo.columnKey === "employee_prep" && state.sortedInfo.order, sorter: (a, b) => alphaSort( - bodyshop.employees?.find((e) => e.id === a.employee_prep)?.first_name, - bodyshop.employees?.find((e) => e.id === b.employee_prep)?.first_name + getEmployeeName(a.employee_prep, bodyshop.employees), + getEmployeeName(b.employee_prep, bodyshop.employees) ), render: (text, record) => ( @@ -460,8 +465,8 @@ const r = ({ technician, state, activeStatuses, data, bodyshop, refetch, treatme sortOrder: state.sortedInfo.columnKey === "employee_csr" && state.sortedInfo.order, sorter: (a, b) => alphaSort( - bodyshop.employees?.find((e) => e.id === a.employee_csr)?.first_name, - bodyshop.employees?.find((e) => e.id === b.employee_csr)?.first_name + getEmployeeName(a.employee_csr, bodyshop.employees), + getEmployeeName(b.employee_csr, bodyshop.employees) ), render: (text, record) => ( @@ -474,8 +479,8 @@ const r = ({ technician, state, activeStatuses, data, bodyshop, refetch, treatme sortOrder: state.sortedInfo.columnKey === "employee_refinish" && state.sortedInfo.order, sorter: (a, b) => alphaSort( - bodyshop.employees?.find((e) => e.id === a.employee_refinish)?.first_name, - bodyshop.employees?.find((e) => e.id === b.employee_refinish)?.first_name + getEmployeeName(a.employee_refinish, bodyshop.employees), + getEmployeeName(b.employee_refinish, bodyshop.employees) ), render: (text, record) => ( From c3e6d3dc48bb15b6c8a7a4ffbc6ca19d453d6e51 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Wed, 21 Aug 2024 15:09:13 -0400 Subject: [PATCH 031/478] - Checkpoint Signed-off-by: Dave Richer --- ...oduction-list-config-manager.component.jsx | 105 ++++++++++-------- 1 file changed, 56 insertions(+), 49 deletions(-) diff --git a/client/src/components/production-list-table/production-list-config-manager.component.jsx b/client/src/components/production-list-table/production-list-config-manager.component.jsx index c33b164ff..95f4ceccf 100644 --- a/client/src/components/production-list-table/production-list-config-manager.component.jsx +++ b/client/src/components/production-list-table/production-list-config-manager.component.jsx @@ -376,7 +376,14 @@ export function ProductionListConfigManager({ > {t("general.actions.save")} - +
@@ -384,55 +391,55 @@ export function ProductionListConfigManager({ return ( - - + + + - ); } From c89e4f1b414e2f8f41263f144aff90186c5ed619 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Wed, 21 Aug 2024 15:14:33 -0400 Subject: [PATCH 032/478] - Checkpoint Signed-off-by: Dave Richer --- client/src/translations/en_us/common.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/translations/en_us/common.json b/client/src/translations/en_us/common.json index ff93baff8..1304eff5f 100644 --- a/client/src/translations/en_us/common.json +++ b/client/src/translations/en_us/common.json @@ -1180,7 +1180,7 @@ "vehicle": "Vehicle" }, "labels": { - "unsavedchanges": "Unsaved change.", + "unsavedchanges": "Unsaved changes.", "actions": "Actions", "areyousure": "Are you sure?", "barcode": "Barcode", From cc9979ff4b80cd25786a680cbcc4f4f459d1af4b Mon Sep 17 00:00:00 2001 From: Allan Carr Date: Wed, 21 Aug 2024 12:25:38 -0700 Subject: [PATCH 033/478] IO-2834 Split Date and DateTime formats, remove shorthand and checks Signed-off-by: Allan Carr --- .../form-date-time-picker.component.jsx | 18 +- .../form-date-time-picker/formats.js | 200 ++++++++++-------- 2 files changed, 122 insertions(+), 96 deletions(-) diff --git a/client/src/components/form-date-time-picker/form-date-time-picker.component.jsx b/client/src/components/form-date-time-picker/form-date-time-picker.component.jsx index 20388a740..85349ff06 100644 --- a/client/src/components/form-date-time-picker/form-date-time-picker.component.jsx +++ b/client/src/components/form-date-time-picker/form-date-time-picker.component.jsx @@ -1,8 +1,8 @@ -import React, { useCallback, useState } from "react"; import { DatePicker } from "antd"; -import dayjs from "../../utils/day"; -import { formats, shorthandFormats } from "./formats.js"; import PropTypes from "prop-types"; +import React, { useCallback, useState } from "react"; +import dayjs from "../../utils/day"; +import { formats } from "./formats.js"; const DateTimePicker = ({ value, onChange, onBlur, id, onlyFuture, onlyToday, isDateOnly = false, ...restProps }) => { const [isManualInput, setIsManualInput] = useState(false); @@ -34,18 +34,14 @@ const DateTimePicker = ({ value, onChange, onBlur, id, onlyFuture, onlyToday, is let _a; - for (const format of shorthandFormats) { + for (const format of formats) { + console.log("format",format); _a = dayjs(upperV, format); + console.log("🚀 ~ DateTimePicker ~ _a:", _a) + console.log("isvalid",_a.isValid()); if (_a.isValid()) break; } - if (!_a || !_a.isValid()) { - for (const format of formats) { - _a = dayjs(upperV, format); - if (_a.isValid()) break; - } - } - if (_a && _a.isValid()) { if (isDateOnly) { _a = _a.startOf("day"); diff --git a/client/src/components/form-date-time-picker/formats.js b/client/src/components/form-date-time-picker/formats.js index 7683f9990..0ca0d52c6 100644 --- a/client/src/components/form-date-time-picker/formats.js +++ b/client/src/components/form-date-time-picker/formats.js @@ -1,93 +1,123 @@ -export const shorthandFormats = [ - "M/D/YY hA", - "M/D/YY h:mmA", - "M/D/YYYY hA", - "M/D/YYYY h:mmA", - "M/D/YY ha", +export const dateTimeFormats = [ + "MMDDYY h:mma", + "MMDDYYYY h:mma", "M/D/YY h:mma", - "M/D/YYYY ha", - "M/D/YYYY h:mma" + "M/DD/YY h:mma", + "MM/D/YY h:mma", + "MM/DD/YY h:mma", + "M/D/YYYY h:mma", + "M/DD/YYYY h:mma", + "MM/D/YYYY h:mma", + "MM/DD/YYYY h:mma", + + "MMDDYY h:mmA", + "MMDDYYYY h:mmA", + "M/D/YY h:mmA", + "M/DD/YY h:mmA", + "MM/D/YY h:mmA", + "MM/DD/YY h:mmA", + "M/D/YYYY h:mmA", + "M/DD/YYYY h:mmA", + "MM/D/YYYY h:mmA", + "MM/DD/YYYY h:mmA", + + "MMDDYY h:mm a", + "MMDDYYYY h:mm a", + "M/D/YY h:mm a", + "M/DD/YY h:mm a", + "MM/D/YY h:mm a", + "MM/DD/YY h:mm a", + "M/D/YYYY h:mm a", + "M/DD/YYYY h:mm a", + "MM/D/YYYY h:mm a", + "MM/DD/YYYY h:mm a", + + "MMDDYY h:mm A", + "MMDDYYYY h:mm A", + "M/D/YY h:mm A", + "M/DD/YY h:mm A", + "MM/D/YY h:mm A", + "MM/DD/YY h:mm A", + "M/D/YYYY h:mm A", + "M/DD/YYYY h:mm A", + "MM/D/YYYY h:mm A", + "MM/DD/YYYY h:mm A", + + "MMDDYY h:mm:ssa", + "MMDDYYYY h:mm:ssa", + "M/D/YY h:mm:ssa", + "M/DD/YY h:mm:ssa", + "MM/D/YY h:mm:ssa", + "MM/DD/YY h:mm:ssa", + "M/D/YYYY h:mm:ssa", + "M/DD/YYYY h:mm:ssa", + "MM/D/YYYY h:mm:ssa", + "MM/DD/YYYY h:mm:ssa", + + "MMDDYY h:mm:ssA", + "MMDDYYYY h:mm:ssA", + "M/D/YY h:mm:ssA", + "M/DD/YY h:mm:ssA", + "MM/D/YY h:mm:ssA", + "MM/DD/YY h:mm:ssA", + "M/D/YYYY h:mm:ssA", + "M/DD/YYYY h:mm:ssA", + "MM/D/YYYY h:mm:ssA", + "MM/DD/YYYY h:mm:ssA", + + "MMDDYY h:mm:ss a", + "MMDDYYYY h:mm:ss a", + "M/D/YY h:mm:ss a", + "M/DD/YY h:mm:ss a", + "MM/D/YY h:mm:ss a", + "MM/DD/YY h:mm:ss a", + "M/D/YYYY h:mm:ss a", + "M/DD/YYYY h:mm:ss a", + "MM/D/YYYY h:mm:ss a", + "MM/DD/YYYY h:mm:ss a", + + "MMDDYY h:mm:ss A", + "MMDDYYYY h:mm:ss A", + "M/D/YY h:mm:ss A", + "M/DD/YY h:mm:ss A", + "MM/D/YY h:mm:ss A", + "MM/DD/YY h:mm:ss A", + "M/D/YYYY h:mm:ss A", + "M/DD/YYYY h:mm:ss A", + "MM/D/YYYY h:mm:ss A", + "MM/DD/YYYY h:mm:ss A", + + "MMDDYY H:mm", + "MMDDYYYY H:mm", + "M/D/YY H:mm", + "M/DD/YY H:mm", + "MM/D/YY H:mm", + "MM/DD/YY H:mm", + "M/D/YYYY H:mm", + "M/DD/YYYY H:mm", + "MM/D/YYYY H:mm", + "MM/DD/YYYY H:mm", + + "MMDDYY H:mm:ss", + "MMDDYYYY H:mm:ss", + "M/D/YY H:mm:ss", + "M/DD/YY H:mm:ss", + "MM/D/YY H:mm:ss", + "MM/DD/YY H:mm:ss", + "M/D/YYYY H:mm:ss", + "MM/D/YYYY H:mm:ss", + "MM/DD/YYYY H:mm:ss" ]; -export const formats = [ +export const dateFormats = [ "MMDDYY", "MMDDYYYY", - "MM/DD/YY", - "MM/DD/YYYY", - "M/DD/YY", - "M/DD/YYYY", - "MM/D/YY", - "MM/D/YYYY", "M/D/YY", + "M/DD/YY", + "MM/D/YY", + "MM/DD/YY", "M/D/YYYY", - "D/MM/YY", - "D/MM/YYYY", - "DD/M/YY", - "DD/M/YYYY", - "D/M/YY", - "D/M/YYYY", - "MMDDYY hh:mm A", - "MMDDYYYY hh:mm A", - "MM/DD/YY hh:mm A", - "MM/DD/YYYY hh:mm A", - "M/DD/YY hh:mm A", - "M/DD/YYYY hh:mm A", - "MM/D/YY hh:mm A", - "MM/D/YYYY hh:mm A", - "M/D/YY hh:mm A", - "M/D/YYYY hh:mm A", - "D/MM/YY hh:mm A", - "D/MM/YYYY hh:mm A", - "DD/M/YY hh:mm A", - "DD/M/YYYY hh:mm A", - "D/M/YY hh:mm A", - "D/M/YYYY hh:mm A", - "MMDDYY hh:mm:ss A", - "MMDDYYYY hh:mm:ss A", - "MM/DD/YY hh:mm:ss A", - "MM/DD/YYYY hh:mm:ss A", - "M/DD/YY hh:mm:ss A", - "M/DD/YYYY hh:mm:ss A", - "MM/D/YY hh:mm:ss A", - "MM/D/YYYY hh:mm:ss A", - "M/D/YY hh:mm:ss A", - "M/D/YYYY hh:mm:ss A", - "D/MM/YY hh:mm:ss A", - "D/MM/YYYY hh:mm:ss A", - "DD/M/YY hh:mm:ss A", - "DD/M/YYYY hh:mm:ss A", - "D/M/YY hh:mm:ss A", - "D/M/YYYY hh:mm:ss A", - "MMDDYY HH:mm", - "MMDDYYYY HH:mm", - "MM/DD/YY HH:mm", - "MM/DD/YYYY HH:mm", - "M/DD/YY HH:mm", - "M/DD/YYYY HH:mm", - "MM/D/YY HH:mm", - "MM/D/YYYY HH:mm", - "M/D/YY HH:mm", - "M/D/YYYY HH:mm", - "D/MM/YY HH:mm", - "D/MM/YYYY HH:mm", - "DD/M/YY HH:mm", - "DD/M/YYYY HH:mm", - "D/M/YY HH:mm", - "D/M/YYYY HH:mm", - "MMDDYY HH:mm:ss", - "MMDDYYYY HH:mm:ss", - "MM/DD/YY HH:mm:ss", - "MM/DD/YYYY HH:mm:ss", - "M/DD/YY HH:mm:ss", - "M/DD/YYYY HH:mm:ss", - "MM/D/YY HH:mm:ss", - "MM/D/YYYY HH:mm:ss", - "M/D/YY HH:mm:ss", - "M/D/YYYY HH:mm:ss", - "D/MM/YY HH:mm:ss", - "D/MM/YYYY HH:mm:ss", - "DD/M/YY HH:mm:ss", - "DD/M/YYYY HH:mm:ss", - "D/M/YY HH:mm:ss", - "D/M/YYYY HH:mm:ss" + "M/DD/YYYY", + "MM/D/YYYY", + "MM/DD/YYYY" ]; From 90532427b67f3833f54ad8df71190a8801533206 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Wed, 21 Aug 2024 15:32:22 -0400 Subject: [PATCH 034/478] - Checkpoint Signed-off-by: Dave Richer --- ...oduction-list-config-manager.component.jsx | 40 +++++++++++++++++-- client/src/translations/en_us/common.json | 7 +++- client/src/translations/es/common.json | 7 +++- client/src/translations/fr/common.json | 7 +++- 4 files changed, 52 insertions(+), 9 deletions(-) diff --git a/client/src/components/production-list-table/production-list-config-manager.component.jsx b/client/src/components/production-list-table/production-list-config-manager.component.jsx index 95f4ceccf..80c32985f 100644 --- a/client/src/components/production-list-table/production-list-config-manager.component.jsx +++ b/client/src/components/production-list-table/production-list-config-manager.component.jsx @@ -362,7 +362,25 @@ export function ProductionListConfigManager({
{isAddingNewProfile && ( - + { + if (!value) { + return Promise.resolve(); + } + const nameExists = bodyshop.production_config.some((pc) => pc.name === value); + if (nameExists) { + return Promise.reject(new Error(t("production.errors.name_exists"))); + } + return Promise.resolve(); + } + } + ]} + > )} @@ -376,13 +394,22 @@ export function ProductionListConfigManager({ > {t("general.actions.save")} + @@ -417,7 +444,14 @@ export function ProductionListConfigManager({ .map((config) => (
- + {config.name} {config.name !== t("production.constants.main_profile") && ( diff --git a/client/src/translations/en_us/common.json b/client/src/translations/en_us/common.json index 1304eff5f..98d9418ec 100644 --- a/client/src/translations/en_us/common.json +++ b/client/src/translations/en_us/common.json @@ -1165,7 +1165,8 @@ "tryagain": "Try Again", "view": "View", "viewreleasenotes": "See What's Changed", - "remove_alert": "Are you sure you want to dismiss the alert?" + "remove_alert": "Are you sure you want to dismiss the alert?", + "saveas": "Save As" }, "errors": { "fcm": "You must allow notification permissions to have real time messaging. Click to try again.", @@ -2788,7 +2789,9 @@ "errors": { "boardupdate": "Error encountered updating Job. {{message}}", "removing": "Error removing from production board. {{error}}", - "settings": "Error saving board settings: {{error}}" + "settings": "Error saving board settings: {{error}}", + "name_exists": "A Profile with this name already exists. Please choose a different name.", + "name_required": "Profile name is required." }, "labels": { "kiosk_mode": "Kiosk Mode", diff --git a/client/src/translations/es/common.json b/client/src/translations/es/common.json index 76f537e61..18edcbeeb 100644 --- a/client/src/translations/es/common.json +++ b/client/src/translations/es/common.json @@ -1165,7 +1165,8 @@ "tryagain": "", "view": "", "viewreleasenotes": "", - "remove_alert": "" + "remove_alert": "", + "saveas": "" }, "errors": { "fcm": "", @@ -2788,7 +2789,9 @@ "errors": { "boardupdate": "", "removing": "", - "settings": "" + "settings": "", + "name_exists": "", + "name_required": "" }, "labels": { "kiosk_mode": "", diff --git a/client/src/translations/fr/common.json b/client/src/translations/fr/common.json index fccb1ce65..adc23a1a0 100644 --- a/client/src/translations/fr/common.json +++ b/client/src/translations/fr/common.json @@ -1165,7 +1165,8 @@ "tryagain": "", "view": "", "viewreleasenotes": "", - "remove_alert": "" + "remove_alert": "", + "saveas": "" }, "errors": { "fcm": "", @@ -2788,7 +2789,9 @@ "errors": { "boardupdate": "", "removing": "", - "settings": "" + "settings": "", + "name_exists": "", + "name_required": "" }, "labels": { "kiosk_mode": "", From 11785f3b862af6a3145fc1c46f92049e6d2b0715 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Wed, 21 Aug 2024 15:39:16 -0400 Subject: [PATCH 035/478] - Checkpoint Signed-off-by: Dave Richer --- ...oduction-list-config-manager.component.jsx | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/client/src/components/production-list-table/production-list-config-manager.component.jsx b/client/src/components/production-list-table/production-list-config-manager.component.jsx index 80c32985f..26fc45511 100644 --- a/client/src/components/production-list-table/production-list-config-manager.component.jsx +++ b/client/src/components/production-list-table/production-list-config-manager.component.jsx @@ -394,15 +394,17 @@ export function ProductionListConfigManager({ > {t("general.actions.save")} - + {!isAddingNewProfile && ( + + )} + +
+ + + + + From 70d857bfec308fbc64b385c2fa0e4d0ea0b5fe80 Mon Sep 17 00:00:00 2001 From: Patrick Fic Date: Fri, 20 Sep 2024 13:14:15 -0700 Subject: [PATCH 122/478] IO-2933 resolve missing account details on --- .../card-payment-modal/card-payment-modal.component..jsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/client/src/components/card-payment-modal/card-payment-modal.component..jsx b/client/src/components/card-payment-modal/card-payment-modal.component..jsx index 29a95b87b..fcdbd417c 100644 --- a/client/src/components/card-payment-modal/card-payment-modal.component..jsx +++ b/client/src/components/card-payment-modal/card-payment-modal.component..jsx @@ -45,7 +45,7 @@ const CardPaymentModalComponent = ({ const [, { data, refetch, queryLoading }] = useLazyQuery(QUERY_RO_AND_OWNER_BY_JOB_PKS, { variables: { jobids: [context.jobid] }, - skip: true + skip: !context?.jobid }); //Initialize the intellipay window. @@ -244,7 +244,8 @@ const CardPaymentModalComponent = ({ - prevValues.payments?.map((p) => p?.jobid).join() !== curValues.payments?.map((p) => p?.jobid).join() + prevValues.payments?.map((p) => p?.jobid + p?.amount).join() !== + curValues.payments?.map((p) => p?.jobid + p?.amount).join() } > {() => { From f018a2b2a6e7168b755df8843159105a456dddf3 Mon Sep 17 00:00:00 2001 From: Patrick Fic Date: Fri, 20 Sep 2024 14:57:31 -0700 Subject: [PATCH 123/478] Add additional Hasura Indexes --- hasura/migrations/1726868398933_run_sql_migration/down.sql | 3 +++ hasura/migrations/1726868398933_run_sql_migration/up.sql | 1 + .../1726868654375_create_index_idx_jobs_vehicleid/down.sql | 1 + .../1726868654375_create_index_idx_jobs_vehicleid/up.sql | 2 ++ 4 files changed, 7 insertions(+) create mode 100644 hasura/migrations/1726868398933_run_sql_migration/down.sql create mode 100644 hasura/migrations/1726868398933_run_sql_migration/up.sql create mode 100644 hasura/migrations/1726868654375_create_index_idx_jobs_vehicleid/down.sql create mode 100644 hasura/migrations/1726868654375_create_index_idx_jobs_vehicleid/up.sql diff --git a/hasura/migrations/1726868398933_run_sql_migration/down.sql b/hasura/migrations/1726868398933_run_sql_migration/down.sql new file mode 100644 index 000000000..20f7cb64f --- /dev/null +++ b/hasura/migrations/1726868398933_run_sql_migration/down.sql @@ -0,0 +1,3 @@ +-- Could not auto-generate a down migration. +-- Please write an appropriate down migration for the SQL below: +-- CREATE INDEX idx_jobs_created_at_desc ON jobs (created_at DESC); diff --git a/hasura/migrations/1726868398933_run_sql_migration/up.sql b/hasura/migrations/1726868398933_run_sql_migration/up.sql new file mode 100644 index 000000000..e68cba2a2 --- /dev/null +++ b/hasura/migrations/1726868398933_run_sql_migration/up.sql @@ -0,0 +1 @@ +CREATE INDEX idx_jobs_created_at_desc ON jobs (created_at DESC); diff --git a/hasura/migrations/1726868654375_create_index_idx_jobs_vehicleid/down.sql b/hasura/migrations/1726868654375_create_index_idx_jobs_vehicleid/down.sql new file mode 100644 index 000000000..edec33bc5 --- /dev/null +++ b/hasura/migrations/1726868654375_create_index_idx_jobs_vehicleid/down.sql @@ -0,0 +1 @@ +DROP INDEX IF EXISTS "public"."idx_jobs_vehicleid"; diff --git a/hasura/migrations/1726868654375_create_index_idx_jobs_vehicleid/up.sql b/hasura/migrations/1726868654375_create_index_idx_jobs_vehicleid/up.sql new file mode 100644 index 000000000..0027bbc21 --- /dev/null +++ b/hasura/migrations/1726868654375_create_index_idx_jobs_vehicleid/up.sql @@ -0,0 +1,2 @@ +CREATE INDEX "idx_jobs_vehicleid" on + "public"."jobs" using btree ("vehicleid"); From da7b97042ea45388792ba8252a71536180270fd1 Mon Sep 17 00:00:00 2001 From: Allan Carr Date: Fri, 20 Sep 2024 15:19:24 -0700 Subject: [PATCH 124/478] IO-2928 Adjust accumulator in reducer for tax Signed-off-by: Allan Carr --- server/accounting/qbo/qbo-payables.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/accounting/qbo/qbo-payables.js b/server/accounting/qbo/qbo-payables.js index 30f5b1f62..c0673cbc5 100644 --- a/server/accounting/qbo/qbo-payables.js +++ b/server/accounting/qbo/qbo-payables.js @@ -221,7 +221,7 @@ async function InsertBill(oauthClient, qbo_realmId, req, bill, vendor, bodyshop) Amount: Dinero({ amount: Math.round( bill.billlines.reduce((acc, val) => { - return acc + val.applicable_taxes?.federal ? (val.actual_cost * val.quantity ?? 0) : 0; + return acc + (val.applicable_taxes?.federal ? (val.actual_cost * val.quantity ?? 0) : 0); }, 0) * 100 ) }) From efc1157653cbb4e3bc03d97bb2a175dc8ec21ee3 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Fri, 20 Sep 2024 18:53:33 -0400 Subject: [PATCH 125/478] IO-2782 - Fix query Signed-off-by: Dave Richer --- server/firebase/firebase-handler.js | 1 - 1 file changed, 1 deletion(-) diff --git a/server/firebase/firebase-handler.js b/server/firebase/firebase-handler.js index e47eeffc1..2590e6f57 100644 --- a/server/firebase/firebase-handler.js +++ b/server/firebase/firebase-handler.js @@ -214,7 +214,6 @@ const getUser = (req, res) => { query GET_USER_BY_AUTHID($authid: String!) { users(where: { authid: { _eq: $authid } }) { email - displayName validemail associations { id From 464f7044f0dd3aadb18c770213a77bb16488cc5a Mon Sep 17 00:00:00 2001 From: Patrick Fic Date: Fri, 20 Sep 2024 15:56:42 -0700 Subject: [PATCH 126/478] Further index changes. --- .../1726871373784_run_sql_migration/down.sql | 34 +++++++++++++++++++ .../1726871373784_run_sql_migration/up.sql | 32 +++++++++++++++++ .../1726871384601_run_sql_migration/down.sql | 34 +++++++++++++++++++ .../1726871384601_run_sql_migration/up.sql | 32 +++++++++++++++++ .../down.sql | 1 + .../up.sql | 2 ++ .../down.sql | 1 + .../up.sql | 2 ++ .../down.sql | 1 + .../up.sql | 2 ++ .../down.sql | 1 + .../up.sql | 2 ++ .../1726872195945_run_sql_migration/down.sql | 3 ++ .../1726872195945_run_sql_migration/up.sql | 1 + .../1726872572029_run_sql_migration/down.sql | 3 ++ .../1726872572029_run_sql_migration/up.sql | 1 + .../1726872872872_run_sql_migration/down.sql | 3 ++ .../1726872872872_run_sql_migration/up.sql | 1 + .../down.sql | 2 ++ .../up.sql | 1 + .../down.sql | 2 ++ .../up.sql | 1 + 22 files changed, 162 insertions(+) create mode 100644 hasura/migrations/1726871373784_run_sql_migration/down.sql create mode 100644 hasura/migrations/1726871373784_run_sql_migration/up.sql create mode 100644 hasura/migrations/1726871384601_run_sql_migration/down.sql create mode 100644 hasura/migrations/1726871384601_run_sql_migration/up.sql create mode 100644 hasura/migrations/1726871425044_create_index_idx_bill_invoice_number/down.sql create mode 100644 hasura/migrations/1726871425044_create_index_idx_bill_invoice_number/up.sql create mode 100644 hasura/migrations/1726871466395_create_index_idx_payments_paymentnum/down.sql create mode 100644 hasura/migrations/1726871466395_create_index_idx_payments_paymentnum/up.sql create mode 100644 hasura/migrations/1726871529961_create_index_exportlog_useremail/down.sql create mode 100644 hasura/migrations/1726871529961_create_index_exportlog_useremail/up.sql create mode 100644 hasura/migrations/1726871632920_create_index_available_jobs_jobid/down.sql create mode 100644 hasura/migrations/1726871632920_create_index_available_jobs_jobid/up.sql create mode 100644 hasura/migrations/1726872195945_run_sql_migration/down.sql create mode 100644 hasura/migrations/1726872195945_run_sql_migration/up.sql create mode 100644 hasura/migrations/1726872572029_run_sql_migration/down.sql create mode 100644 hasura/migrations/1726872572029_run_sql_migration/up.sql create mode 100644 hasura/migrations/1726872872872_run_sql_migration/down.sql create mode 100644 hasura/migrations/1726872872872_run_sql_migration/up.sql create mode 100644 hasura/migrations/1726872925447_drop_index_joblines_idx_removed/down.sql create mode 100644 hasura/migrations/1726872925447_drop_index_joblines_idx_removed/up.sql create mode 100644 hasura/migrations/1726872944447_drop_index_joblines_idx_line_no/down.sql create mode 100644 hasura/migrations/1726872944447_drop_index_joblines_idx_line_no/up.sql diff --git a/hasura/migrations/1726871373784_run_sql_migration/down.sql b/hasura/migrations/1726871373784_run_sql_migration/down.sql new file mode 100644 index 000000000..9268ff591 --- /dev/null +++ b/hasura/migrations/1726871373784_run_sql_migration/down.sql @@ -0,0 +1,34 @@ +-- Could not auto-generate a down migration. +-- Please write an appropriate down migration for the SQL below: +-- CREATE OR REPLACE FUNCTION public.search_exportlog(search text) +-- RETURNS SETOF exportlog +-- LANGUAGE plpgsql +-- STABLE +-- AS $function$ BEGIN IF search = '' THEN RETURN query +-- SELECT +-- * +-- FROM +-- exportlog e; +-- ELSE RETURN query +-- SELECT +-- e.* +-- FROM +-- exportlog e +-- LEFT JOIN jobs j on j.id = e.jobid +-- LEFT JOIN payments p +-- ON p.id = e.paymentid +-- LEFT JOIN bills b +-- ON e.billid = b.id +-- WHERE +-- ( +-- j.ro_number ILIKE '%' || search +-- OR b.invoice_number ILIKE '%' || search +-- OR p.paymentnum ILIKE '%' || search +-- OR e.useremail ILIKE '%' || search +-- ) +-- AND (e.jobid = j.id +-- or e.paymentid = p.id +-- or e.billid = b.id) +-- ; +-- END IF; +-- END $function$; diff --git a/hasura/migrations/1726871373784_run_sql_migration/up.sql b/hasura/migrations/1726871373784_run_sql_migration/up.sql new file mode 100644 index 000000000..eb8c0b69d --- /dev/null +++ b/hasura/migrations/1726871373784_run_sql_migration/up.sql @@ -0,0 +1,32 @@ +CREATE OR REPLACE FUNCTION public.search_exportlog(search text) + RETURNS SETOF exportlog + LANGUAGE plpgsql + STABLE +AS $function$ BEGIN IF search = '' THEN RETURN query +SELECT + * +FROM + exportlog e; + ELSE RETURN query +SELECT + e.* +FROM + exportlog e + LEFT JOIN jobs j on j.id = e.jobid +LEFT JOIN payments p + ON p.id = e.paymentid +LEFT JOIN bills b + ON e.billid = b.id +WHERE + ( + j.ro_number ILIKE '%' || search + OR b.invoice_number ILIKE '%' || search + OR p.paymentnum ILIKE '%' || search + OR e.useremail ILIKE '%' || search + ) + AND (e.jobid = j.id + or e.paymentid = p.id + or e.billid = b.id) +; +END IF; +END $function$; diff --git a/hasura/migrations/1726871384601_run_sql_migration/down.sql b/hasura/migrations/1726871384601_run_sql_migration/down.sql new file mode 100644 index 000000000..9268ff591 --- /dev/null +++ b/hasura/migrations/1726871384601_run_sql_migration/down.sql @@ -0,0 +1,34 @@ +-- Could not auto-generate a down migration. +-- Please write an appropriate down migration for the SQL below: +-- CREATE OR REPLACE FUNCTION public.search_exportlog(search text) +-- RETURNS SETOF exportlog +-- LANGUAGE plpgsql +-- STABLE +-- AS $function$ BEGIN IF search = '' THEN RETURN query +-- SELECT +-- * +-- FROM +-- exportlog e; +-- ELSE RETURN query +-- SELECT +-- e.* +-- FROM +-- exportlog e +-- LEFT JOIN jobs j on j.id = e.jobid +-- LEFT JOIN payments p +-- ON p.id = e.paymentid +-- LEFT JOIN bills b +-- ON e.billid = b.id +-- WHERE +-- ( +-- j.ro_number ILIKE '%' || search +-- OR b.invoice_number ILIKE '%' || search +-- OR p.paymentnum ILIKE '%' || search +-- OR e.useremail ILIKE '%' || search +-- ) +-- AND (e.jobid = j.id +-- or e.paymentid = p.id +-- or e.billid = b.id) +-- ; +-- END IF; +-- END $function$; diff --git a/hasura/migrations/1726871384601_run_sql_migration/up.sql b/hasura/migrations/1726871384601_run_sql_migration/up.sql new file mode 100644 index 000000000..eb8c0b69d --- /dev/null +++ b/hasura/migrations/1726871384601_run_sql_migration/up.sql @@ -0,0 +1,32 @@ +CREATE OR REPLACE FUNCTION public.search_exportlog(search text) + RETURNS SETOF exportlog + LANGUAGE plpgsql + STABLE +AS $function$ BEGIN IF search = '' THEN RETURN query +SELECT + * +FROM + exportlog e; + ELSE RETURN query +SELECT + e.* +FROM + exportlog e + LEFT JOIN jobs j on j.id = e.jobid +LEFT JOIN payments p + ON p.id = e.paymentid +LEFT JOIN bills b + ON e.billid = b.id +WHERE + ( + j.ro_number ILIKE '%' || search + OR b.invoice_number ILIKE '%' || search + OR p.paymentnum ILIKE '%' || search + OR e.useremail ILIKE '%' || search + ) + AND (e.jobid = j.id + or e.paymentid = p.id + or e.billid = b.id) +; +END IF; +END $function$; diff --git a/hasura/migrations/1726871425044_create_index_idx_bill_invoice_number/down.sql b/hasura/migrations/1726871425044_create_index_idx_bill_invoice_number/down.sql new file mode 100644 index 000000000..ba25d24f4 --- /dev/null +++ b/hasura/migrations/1726871425044_create_index_idx_bill_invoice_number/down.sql @@ -0,0 +1 @@ +DROP INDEX IF EXISTS "public"."idx_bill_invoice_number"; diff --git a/hasura/migrations/1726871425044_create_index_idx_bill_invoice_number/up.sql b/hasura/migrations/1726871425044_create_index_idx_bill_invoice_number/up.sql new file mode 100644 index 000000000..9048c0824 --- /dev/null +++ b/hasura/migrations/1726871425044_create_index_idx_bill_invoice_number/up.sql @@ -0,0 +1,2 @@ +CREATE INDEX "idx_bill_invoice_number" on + "public"."bills" using btree ("invoice_number"); diff --git a/hasura/migrations/1726871466395_create_index_idx_payments_paymentnum/down.sql b/hasura/migrations/1726871466395_create_index_idx_payments_paymentnum/down.sql new file mode 100644 index 000000000..7e7d6a7e3 --- /dev/null +++ b/hasura/migrations/1726871466395_create_index_idx_payments_paymentnum/down.sql @@ -0,0 +1 @@ +DROP INDEX IF EXISTS "public"."idx_payments_paymentnum"; diff --git a/hasura/migrations/1726871466395_create_index_idx_payments_paymentnum/up.sql b/hasura/migrations/1726871466395_create_index_idx_payments_paymentnum/up.sql new file mode 100644 index 000000000..e5df914da --- /dev/null +++ b/hasura/migrations/1726871466395_create_index_idx_payments_paymentnum/up.sql @@ -0,0 +1,2 @@ +CREATE INDEX "idx_payments_paymentnum" on + "public"."payments" using btree ("paymentnum"); diff --git a/hasura/migrations/1726871529961_create_index_exportlog_useremail/down.sql b/hasura/migrations/1726871529961_create_index_exportlog_useremail/down.sql new file mode 100644 index 000000000..a2c72a3b7 --- /dev/null +++ b/hasura/migrations/1726871529961_create_index_exportlog_useremail/down.sql @@ -0,0 +1 @@ +DROP INDEX IF EXISTS "public"."exportlog_useremail"; diff --git a/hasura/migrations/1726871529961_create_index_exportlog_useremail/up.sql b/hasura/migrations/1726871529961_create_index_exportlog_useremail/up.sql new file mode 100644 index 000000000..d5b7f3c91 --- /dev/null +++ b/hasura/migrations/1726871529961_create_index_exportlog_useremail/up.sql @@ -0,0 +1,2 @@ +CREATE INDEX "exportlog_useremail" on + "public"."exportlog" using btree ("useremail"); diff --git a/hasura/migrations/1726871632920_create_index_available_jobs_jobid/down.sql b/hasura/migrations/1726871632920_create_index_available_jobs_jobid/down.sql new file mode 100644 index 000000000..ef5073c55 --- /dev/null +++ b/hasura/migrations/1726871632920_create_index_available_jobs_jobid/down.sql @@ -0,0 +1 @@ +DROP INDEX IF EXISTS "public"."available_jobs_jobid"; diff --git a/hasura/migrations/1726871632920_create_index_available_jobs_jobid/up.sql b/hasura/migrations/1726871632920_create_index_available_jobs_jobid/up.sql new file mode 100644 index 000000000..2f6285f05 --- /dev/null +++ b/hasura/migrations/1726871632920_create_index_available_jobs_jobid/up.sql @@ -0,0 +1,2 @@ +CREATE INDEX "available_jobs_jobid" on + "public"."available_jobs" using btree ("jobid"); diff --git a/hasura/migrations/1726872195945_run_sql_migration/down.sql b/hasura/migrations/1726872195945_run_sql_migration/down.sql new file mode 100644 index 000000000..ef22d98bc --- /dev/null +++ b/hasura/migrations/1726872195945_run_sql_migration/down.sql @@ -0,0 +1,3 @@ +-- Could not auto-generate a down migration. +-- Please write an appropriate down migration for the SQL below: +-- CREATE INDEX idx_jobslines_ordering ON joblines (jobid, removed, line_no asc) where removed=false; diff --git a/hasura/migrations/1726872195945_run_sql_migration/up.sql b/hasura/migrations/1726872195945_run_sql_migration/up.sql new file mode 100644 index 000000000..77ed0f842 --- /dev/null +++ b/hasura/migrations/1726872195945_run_sql_migration/up.sql @@ -0,0 +1 @@ +CREATE INDEX idx_jobslines_ordering ON joblines (jobid, removed, line_no asc) where removed=false; diff --git a/hasura/migrations/1726872572029_run_sql_migration/down.sql b/hasura/migrations/1726872572029_run_sql_migration/down.sql new file mode 100644 index 000000000..d1c5e8254 --- /dev/null +++ b/hasura/migrations/1726872572029_run_sql_migration/down.sql @@ -0,0 +1,3 @@ +-- Could not auto-generate a down migration. +-- Please write an appropriate down migration for the SQL below: +-- CREATE INDEX idx_joblines_types ON joblines (jobid, mod_lbr_ty, removed) where removed=false; diff --git a/hasura/migrations/1726872572029_run_sql_migration/up.sql b/hasura/migrations/1726872572029_run_sql_migration/up.sql new file mode 100644 index 000000000..e1ddd1a7f --- /dev/null +++ b/hasura/migrations/1726872572029_run_sql_migration/up.sql @@ -0,0 +1 @@ +CREATE INDEX idx_joblines_types ON joblines (jobid, mod_lbr_ty, removed) where removed=false; diff --git a/hasura/migrations/1726872872872_run_sql_migration/down.sql b/hasura/migrations/1726872872872_run_sql_migration/down.sql new file mode 100644 index 000000000..9fe48a789 --- /dev/null +++ b/hasura/migrations/1726872872872_run_sql_migration/down.sql @@ -0,0 +1,3 @@ +-- Could not auto-generate a down migration. +-- Please write an appropriate down migration for the SQL below: +-- CREATE INDEX idx_exportlog_created_at_desc ON exportlog (created_at desc); diff --git a/hasura/migrations/1726872872872_run_sql_migration/up.sql b/hasura/migrations/1726872872872_run_sql_migration/up.sql new file mode 100644 index 000000000..71dae5805 --- /dev/null +++ b/hasura/migrations/1726872872872_run_sql_migration/up.sql @@ -0,0 +1 @@ +CREATE INDEX idx_exportlog_created_at_desc ON exportlog (created_at desc); diff --git a/hasura/migrations/1726872925447_drop_index_joblines_idx_removed/down.sql b/hasura/migrations/1726872925447_drop_index_joblines_idx_removed/down.sql new file mode 100644 index 000000000..dae8a4574 --- /dev/null +++ b/hasura/migrations/1726872925447_drop_index_joblines_idx_removed/down.sql @@ -0,0 +1,2 @@ +CREATE INDEX "joblines_idx_removed" on + "public"."joblines" using btree ("removed"); diff --git a/hasura/migrations/1726872925447_drop_index_joblines_idx_removed/up.sql b/hasura/migrations/1726872925447_drop_index_joblines_idx_removed/up.sql new file mode 100644 index 000000000..8ede82ff5 --- /dev/null +++ b/hasura/migrations/1726872925447_drop_index_joblines_idx_removed/up.sql @@ -0,0 +1 @@ +DROP INDEX IF EXISTS "public"."joblines_idx_removed"; diff --git a/hasura/migrations/1726872944447_drop_index_joblines_idx_line_no/down.sql b/hasura/migrations/1726872944447_drop_index_joblines_idx_line_no/down.sql new file mode 100644 index 000000000..a55c69d5b --- /dev/null +++ b/hasura/migrations/1726872944447_drop_index_joblines_idx_line_no/down.sql @@ -0,0 +1,2 @@ +CREATE INDEX "joblines_idx_line_no" on + "public"."joblines" using btree ("jobid", "line_no"); diff --git a/hasura/migrations/1726872944447_drop_index_joblines_idx_line_no/up.sql b/hasura/migrations/1726872944447_drop_index_joblines_idx_line_no/up.sql new file mode 100644 index 000000000..a07804c70 --- /dev/null +++ b/hasura/migrations/1726872944447_drop_index_joblines_idx_line_no/up.sql @@ -0,0 +1 @@ +DROP INDEX IF EXISTS "public"."joblines_idx_line_no"; From 646754732dd9bf0dc33be2af8c674aafad19f100 Mon Sep 17 00:00:00 2001 From: Allan Carr Date: Fri, 20 Sep 2024 16:45:48 -0700 Subject: [PATCH 127/478] IO-2782 Adjust to Object for items Signed-off-by: Allan Carr --- server/email/sendemail.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/email/sendemail.js b/server/email/sendemail.js index 65b5a60ce..5dea4a075 100644 --- a/server/email/sendemail.js +++ b/server/email/sendemail.js @@ -96,7 +96,7 @@ const sendServerEmail = async ({ subject, text }) => { } }; -const sendProManagerWelcomeEmail = async (to, subject, html) => { +const sendProManagerWelcomeEmail = async ({to, subject, html}) => { try { await transporter.sendMail({ from: `ProManager `, From 6a7005299a8e9c70fa712421d0462f6dc9380b0f Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Mon, 23 Sep 2024 16:41:06 -0400 Subject: [PATCH 128/478] IO-2931-Visual-Production-Board-Drag-and-Drop-on-Touch-Devices - Fix Drag and Drop on Android and IOS devices. Signed-off-by: Dave Richer --- .../production-board-kanban.styles.scss | 6 +++++- .../find-closest-draggable-id-from-event.js | 2 +- .../sensors/use-touch-sensor.js | 13 +++++++----- .../use-sensor-marshal/use-sensor-marshal.js | 20 ++++++++++++++++--- 4 files changed, 31 insertions(+), 10 deletions(-) diff --git a/client/src/components/production-board-kanban/production-board-kanban.styles.scss b/client/src/components/production-board-kanban/production-board-kanban.styles.scss index 6e7ee63ce..8b04aaa5d 100644 --- a/client/src/components/production-board-kanban/production-board-kanban.styles.scss +++ b/client/src/components/production-board-kanban/production-board-kanban.styles.scss @@ -17,7 +17,6 @@ border-radius: 5px 5px 0 0; } - .production-alert { background: transparent; border: none; @@ -70,3 +69,8 @@ } } } + +.clone.is-dragging .ant-card { + border: #1890ff 2px solid !important; + border-radius: 12px; +} diff --git a/client/src/components/production-board-kanban/trello-board/dnd/lib/view/use-sensor-marshal/find-closest-draggable-id-from-event.js b/client/src/components/production-board-kanban/trello-board/dnd/lib/view/use-sensor-marshal/find-closest-draggable-id-from-event.js index 60285d2a4..f17be1759 100644 --- a/client/src/components/production-board-kanban/trello-board/dnd/lib/view/use-sensor-marshal/find-closest-draggable-id-from-event.js +++ b/client/src/components/production-board-kanban/trello-board/dnd/lib/view/use-sensor-marshal/find-closest-draggable-id-from-event.js @@ -8,7 +8,7 @@ function getSelector(contextId) { return `[${attributes.dragHandle.contextId}="${contextId}"]`; } -function findClosestDragHandleFromEvent(contextId, event) { +export function findClosestDragHandleFromEvent(contextId, event) { const target = event.target; if (!isElement(target)) { warning("event.target must be a Element"); diff --git a/client/src/components/production-board-kanban/trello-board/dnd/lib/view/use-sensor-marshal/sensors/use-touch-sensor.js b/client/src/components/production-board-kanban/trello-board/dnd/lib/view/use-sensor-marshal/sensors/use-touch-sensor.js index 3210e2188..d679f7442 100644 --- a/client/src/components/production-board-kanban/trello-board/dnd/lib/view/use-sensor-marshal/sensors/use-touch-sensor.js +++ b/client/src/components/production-board-kanban/trello-board/dnd/lib/view/use-sensor-marshal/sensors/use-touch-sensor.js @@ -240,11 +240,14 @@ export default function useTouchSensor(api) { y: clientY }; + const handle = api.findClosestDragHandle(event); + invariant(handle, "Touch sensor unable to find drag handle"); + // unbind this event handler unbindEventsRef.current(); // eslint-disable-next-line no-use-before-define - startPendingDrag(actions, point); + startPendingDrag(actions, point, handle); } }), // not including stop or startPendingDrag as it is not defined initially @@ -288,7 +291,7 @@ export default function useTouchSensor(api) { } }, [stop]); const bindCapturingEvents = useCallback( - function bindCapturingEvents() { + function bindCapturingEvents(target) { const options = { capture: true, passive: false @@ -307,7 +310,7 @@ export default function useTouchSensor(api) { // Old behaviour: // https://gist.github.com/parris/dda613e3ae78f14eb2dc9fa0f4bfce3d // https://stackoverflow.com/questions/33298828/touch-move-event-dont-fire-after-touch-start-target-is-removed - const unbindTarget = bindEvents(window, getHandleBindings(args), options); + const unbindTarget = bindEvents(target, getHandleBindings(args), options); const unbindWindow = bindEvents(window, getWindowBindings(args), options); unbindEventsRef.current = function unbindAll() { unbindTarget(); @@ -330,7 +333,7 @@ export default function useTouchSensor(api) { [getPhase, setPhase] ); const startPendingDrag = useCallback( - function startPendingDrag(actions, point) { + function startPendingDrag(actions, point, target) { invariant(getPhase().type === "IDLE", "Expected to move from IDLE to PENDING drag"); const longPressTimerId = setTimeout(startDragging, timeForLongPress); setPhase({ @@ -339,7 +342,7 @@ export default function useTouchSensor(api) { actions, longPressTimerId }); - bindCapturingEvents(); + bindCapturingEvents(target); }, [bindCapturingEvents, getPhase, setPhase, startDragging] ); diff --git a/client/src/components/production-board-kanban/trello-board/dnd/lib/view/use-sensor-marshal/use-sensor-marshal.js b/client/src/components/production-board-kanban/trello-board/dnd/lib/view/use-sensor-marshal/use-sensor-marshal.js index 17f84ee6b..c559a56ab 100644 --- a/client/src/components/production-board-kanban/trello-board/dnd/lib/view/use-sensor-marshal/use-sensor-marshal.js +++ b/client/src/components/production-board-kanban/trello-board/dnd/lib/view/use-sensor-marshal/use-sensor-marshal.js @@ -23,7 +23,9 @@ import getBorderBoxCenterPosition from "../get-border-box-center-position"; import { warning } from "../../dev-warning"; import useLayoutEffect from "../use-isomorphic-layout-effect"; import { noop } from "../../empty"; -import findClosestDraggableIdFromEvent from "./find-closest-draggable-id-from-event"; +import findClosestDraggableIdFromEvent, { + findClosestDragHandleFromEvent +} from "./find-closest-draggable-id-from-event"; import findDraggable from "../get-elements/find-draggable"; import bindEvents from "../event-bindings/bind-events"; @@ -339,6 +341,9 @@ export default function useSensorMarshal({ contextId, store, registry, customSen }), [contextId, lockAPI, registry, store] ); + + const findClosestDragHandle = useCallback((event) => findClosestDragHandleFromEvent(contextId, event), [contextId]); + const findClosestDraggableId = useCallback((event) => findClosestDraggableIdFromEvent(contextId, event), [contextId]); const findOptionsForDraggable = useCallback( (id) => { @@ -370,9 +375,18 @@ export default function useSensorMarshal({ contextId, store, registry, customSen findClosestDraggableId, findOptionsForDraggable, tryReleaseLock, - isLockClaimed + isLockClaimed, + findClosestDragHandle }), - [canGetLock, tryGetLock, findClosestDraggableId, findOptionsForDraggable, tryReleaseLock, isLockClaimed] + [ + canGetLock, + tryGetLock, + findClosestDraggableId, + findOptionsForDraggable, + tryReleaseLock, + isLockClaimed, + findClosestDragHandle + ] ); // Bad ass From 3c85de3e34d0eb9ba35928b030a9bc6498111d0c Mon Sep 17 00:00:00 2001 From: Patrick Fic Date: Mon, 23 Sep 2024 15:04:51 -0700 Subject: [PATCH 129/478] IO-2945 Resolve no success being sent to intellipay creating triple posting. --- server/intellipay/intellipay.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/server/intellipay/intellipay.js b/server/intellipay/intellipay.js index f798bc0bd..60319ed29 100644 --- a/server/intellipay/intellipay.js +++ b/server/intellipay/intellipay.js @@ -200,7 +200,7 @@ exports.postback = async (req, res) => { } })) }); - logger.log("intellipay-postback-app-success", "DEBUG", req.user?.email, null, { + logger.log("intellipay-postback-app-success", "DEBUG", req.user?.email, JSON.stringify(jobs), { iprequest: values, paymentResult }); @@ -223,8 +223,8 @@ exports.postback = async (req, res) => { .join("
") }) }); - res.sendStatus(200); } + res.sendStatus(200); } else if (values.invoice) { //This is a link email that's been sent out. const job = await gqlClient.request(queries.GET_JOB_BY_PK, { @@ -255,7 +255,7 @@ exports.postback = async (req, res) => { } }); - logger.log("intellipay-postback-link-success", "DEBUG", req.user?.email, null, { + logger.log("intellipay-postback-link-success", "DEBUG", req.user?.email, values.invoice, { iprequest: values, responseResults, paymentResult @@ -263,7 +263,7 @@ exports.postback = async (req, res) => { res.sendStatus(200); } } catch (error) { - logger.log("intellipay-postback-error", "ERROR", req.user?.email, null, { + logger.log("intellipay-postback-total-error", "ERROR", req.user?.email, null, { error: JSON.stringify(error), body: req.body }); From 4dffbfe6fafd55e6a5b75629386a7283a2ece360 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Mon, 23 Sep 2024 19:26:40 -0400 Subject: [PATCH 130/478] IO-2931-Visual-Production-Board-Drag-and-Drop-on-Touch-Devices - Add additional fixes / optimizations, from parent repo Signed-off-by: Dave Richer --- .../trello-board/dnd/lib/state/get-droppable-over.js | 4 ++-- .../use-droppable-publisher/get-closest-scrollable.js | 3 ++- .../dnd/lib/view/use-style-marshal/get-styles.js | 8 +++++++- .../dnd/lib/view/use-style-marshal/use-style-marshal.js | 4 +++- 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/client/src/components/production-board-kanban/trello-board/dnd/lib/state/get-droppable-over.js b/client/src/components/production-board-kanban/trello-board/dnd/lib/state/get-droppable-over.js index dcf0cf04c..cb7f7c75b 100644 --- a/client/src/components/production-board-kanban/trello-board/dnd/lib/state/get-droppable-over.js +++ b/client/src/components/production-board-kanban/trello-board/dnd/lib/state/get-droppable-over.js @@ -25,8 +25,8 @@ function getFurthestAway({ pageBorderBox, draggable, candidates }) { const axis = candidate.axis; const target = patch( candidate.axis.line, - // use the current center of the dragging item on the main axis - pageBorderBox.center[axis.line], + // use the center of the list on the main axis + candidate.page.borderBox.center[axis.line], // use the center of the list on the cross axis candidate.page.borderBox.center[axis.crossAxisLine] ); diff --git a/client/src/components/production-board-kanban/trello-board/dnd/lib/view/use-droppable-publisher/get-closest-scrollable.js b/client/src/components/production-board-kanban/trello-board/dnd/lib/view/use-droppable-publisher/get-closest-scrollable.js index 923622788..0b069cce5 100644 --- a/client/src/components/production-board-kanban/trello-board/dnd/lib/view/use-droppable-publisher/get-closest-scrollable.js +++ b/client/src/components/production-board-kanban/trello-board/dnd/lib/view/use-droppable-publisher/get-closest-scrollable.js @@ -5,6 +5,7 @@ import getBodyElement from "../get-body-element"; const isEqual = (base) => (value) => base === value; const isScroll = isEqual("scroll"); const isAuto = isEqual("auto"); +const isOverlay = isEqual("overlay"); const isVisible = isEqual("visible"); const isEither = (overflow, fn) => fn(overflow.overflowX) || fn(overflow.overflowY); const isBoth = (overflow, fn) => fn(overflow.overflowX) && fn(overflow.overflowY); @@ -14,7 +15,7 @@ const isElementScrollable = (el) => { overflowX: style.overflowX, overflowY: style.overflowY }; - return isEither(overflow, isScroll) || isEither(overflow, isAuto); + return isEither(overflow, isScroll) || isEither(overflow, isAuto) || isEither(overflow, isOverlay); }; // Special case for a body element diff --git a/client/src/components/production-board-kanban/trello-board/dnd/lib/view/use-style-marshal/get-styles.js b/client/src/components/production-board-kanban/trello-board/dnd/lib/view/use-style-marshal/get-styles.js index 418acb50b..f62947525 100644 --- a/client/src/components/production-board-kanban/trello-board/dnd/lib/view/use-style-marshal/get-styles.js +++ b/client/src/components/production-board-kanban/trello-board/dnd/lib/view/use-style-marshal/get-styles.js @@ -83,7 +83,13 @@ const getFinalStyles = (contextId) => { return { selector: getSelector(attributes.draggable.contextId), styles: { - dragging: transition, + dragging: ` + ${transition} + user-select: none; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + `, dropAnimating: transition, userCancel: transition } diff --git a/client/src/components/production-board-kanban/trello-board/dnd/lib/view/use-style-marshal/use-style-marshal.js b/client/src/components/production-board-kanban/trello-board/dnd/lib/view/use-style-marshal/use-style-marshal.js index 19457b312..b27b4d534 100644 --- a/client/src/components/production-board-kanban/trello-board/dnd/lib/view/use-style-marshal/use-style-marshal.js +++ b/client/src/components/production-board-kanban/trello-board/dnd/lib/view/use-style-marshal/use-style-marshal.js @@ -67,7 +67,9 @@ export default function useStyleMarshal(contextId, nonce) { const remove = (ref) => { const current = ref.current; invariant(current, "Cannot unmount ref as it is not set"); - getHead().removeChild(current); + if (getHead().contains(current)) { + getHead().removeChild(current); + } ref.current = null; }; remove(alwaysRef); From cafca35500dde29d69c0d392e134983b2e46a7c9 Mon Sep 17 00:00:00 2001 From: Patrick Fic Date: Mon, 23 Sep 2024 18:02:17 -0700 Subject: [PATCH 131/478] IO-2957 Resolve task reminders not sending with incorrect references. --- server/email/tasksEmails.js | 12 +++++----- server/intellipay/intellipay.js | 40 ++++++++++++++++++++------------- 2 files changed, 30 insertions(+), 22 deletions(-) diff --git a/server/email/tasksEmails.js b/server/email/tasksEmails.js index a106085f7..1f508be31 100644 --- a/server/email/tasksEmails.js +++ b/server/email/tasksEmails.js @@ -95,11 +95,11 @@ const formatPriority = (priority) => { * @returns {{header, body: string, subHeader: string}} */ -const getEndpoints = () => +const getEndpoints = (bodyshop) => InstanceManager({ imex: process.env?.NODE_ENV === "test" ? "https://test.imex.online" : "https://imex.online", rome: - bodyshop.convenient_company === "promanager" + bodyshop?.convenient_company === "promanager" ? process.env?.NODE_ENV === "test" ? "https//test.promanager.web-est.com" : "https://promanager.web-est.com" @@ -109,7 +109,7 @@ const getEndpoints = () => }); const generateTemplateArgs = (title, priority, description, dueDate, bodyshop, job, taskId) => { - const endPoints = getEndpoints(); + const endPoints = getEndpoints(bodyshop); return { header: title, subHeader: `Body Shop: ${bodyshop.shopname} | Priority: ${formatPriority(priority)} ${formatDate(dueDate)}`, @@ -247,7 +247,7 @@ const tasksRemindEmail = async (req, res) => { const fromEmails = InstanceManager({ imex: "ImEX Online ", rome: - onlyTask.bodyshop.convenient_company === "promanager" + tasksRequest?.tasks[0].bodyshop.convenient_company === "promanager" ? "ProManager " : "Rome Online " }); @@ -283,7 +283,7 @@ const tasksRemindEmail = async (req, res) => { const endPoints = InstanceManager({ imex: process.env?.NODE_ENV === "test" ? "https://test.imex.online" : "https://imex.online", rome: - allTasks[0].bodyshop.convenient_company === "promanager" + tasksRequest?.tasks[0].bodyshop.convenient_company === "promanager" ? process.env?.NODE_ENV === "test" ? "https//test.promanager.web-est.com" : "https://promanager.web-est.com" @@ -320,7 +320,7 @@ const tasksRemindEmail = async (req, res) => { tasksEmailQueue.push(taskId); } }, - allTasks[0].bodyshop.convenient_company + tasksRequest?.tasks[0].bodyshop.convenient_company ); } }); diff --git a/server/intellipay/intellipay.js b/server/intellipay/intellipay.js index 60319ed29..3c6289b9b 100644 --- a/server/intellipay/intellipay.js +++ b/server/intellipay/intellipay.js @@ -207,22 +207,30 @@ exports.postback = async (req, res) => { if (values.origin === "OneLink" && parsedComment.userEmail) { //Send an email, it was a text to pay link. - const endPoints = getEndpoints(); - sendTaskEmail({ - to: parsedComment.userEmail, - subject: `New Payment(s) Received - RO ${jobs.jobs.map((j) => j.ro_number).join(", ")}`, - type: "html", - html: generateEmailTemplate({ - header: "New Payment(s) Received", - subHeader: "", - body: jobs.jobs - .map( - (job) => - `Reference: ${job.ro_number || "N/A"} | ${job.ownr_co_nm ? job.ownr_co_nm : `${job.ownr_fn || ""} ${job.ownr_ln || ""}`.trim()} | ${`${job.v_model_yr || ""} ${job.v_make_desc || ""} ${job.v_model_desc || ""}`.trim()} | $${partialPayments.find((p) => p.jobid === job.id).amount}` - ) - .join("
") - }) - }); + try { + const endPoints = getEndpoints(); + sendTaskEmail({ + to: parsedComment.userEmail, + subject: `New Payment(s) Received - RO ${jobs.jobs.map((j) => j.ro_number).join(", ")}`, + type: "html", + html: generateEmailTemplate({ + header: "New Payment(s) Received", + subHeader: "", + body: jobs.jobs + .map( + (job) => + `Reference: ${job.ro_number || "N/A"} | ${job.ownr_co_nm ? job.ownr_co_nm : `${job.ownr_fn || ""} ${job.ownr_ln || ""}`.trim()} | ${`${job.v_model_yr || ""} ${job.v_make_desc || ""} ${job.v_model_desc || ""}`.trim()} | $${partialPayments.find((p) => p.jobid === job.id).amount}` + ) + .join("
") + }) + }); + } catch (error) { + logger.log("intellipay-postback-app-email-error", "DEBUG", req.user?.email, JSON.stringify(jobs), { + iprequest: values, + paymentResult, + error: error.message + }); + } } res.sendStatus(200); } else if (values.invoice) { From f287ba2dac8d5d2401badab2d4a40ce247739c9a Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Tue, 24 Sep 2024 10:35:46 -0400 Subject: [PATCH 132/478] IO-2931-Visual-Production-Board-Drag-and-Drop-on-Touch-Devices - Remove reference to /public on apple-touch-icon Signed-off-by: Dave Richer --- client/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/index.html b/client/index.html index 2ba9559dc..0d1e9bcfe 100644 --- a/client/index.html +++ b/client/index.html @@ -17,7 +17,7 @@ - + - - - - + + + + - - <% if (env.VITE_APP_INSTANCE === 'IMEX') { %> - - ImEX Online - - <% } %> <% if (env.VITE_APP_INSTANCE === 'ROME') { %> - - Rome Online - + <% if (env.VITE_APP_INSTANCE === 'IMEX') { %> + + ImEX Online + + <% } %> <% if (env.VITE_APP_INSTANCE === 'ROME') { %> + + Rome Online + - <% } %> <% if (env.VITE_APP_INSTANCE === 'PROMANAGER') { %> - ProManager - + <% } %> + - - - -
- - + !(function () { + for (var o = 0; o < e.length; o++) { + var r = e[o]; + n[r] = t(r); + } + })(), + (function () { + var e = document.createElement("script"); + (e.async = !0), (e.src = "https://sdk.noticeable.io/l.js"); + var n = document.head; + n.insertBefore(e, n.firstChild); + })(); + } + })(); + + + + +
+ + + diff --git a/client/package.json b/client/package.json index 38d148706..e362eade1 100644 --- a/client/package.json +++ b/client/package.json @@ -90,16 +90,12 @@ "build": "dotenvx run --env-file=.env.development.imex -- vite build", "start:imex": "dotenvx run --env-file=.env.development.imex -- vite", "start:rome": "dotenvx run --env-file=.env.development.rome -- vite", - "start:promanager": "dotenvx run --env-file=.env.development.promanager -- vite", "preview:imex": "dotenvx run --env-file=.env.development.imex -- vite preview", "preview:rome": "dotenvx run --env-file=.env.development.rome -- vite preview", - "preview:promanager": "dotenvx run --env-file=.env.development.promanager -- vite preview", "build:test:imex": "env-cmd -f .env.test.imex npm run build", "build:test:rome": "env-cmd -f .env.test.rome npm run build", - "build:test:promanager": "env-cmd -f .env.test.promanager npm run build", "build:production:imex": "env-cmd -f .env.production.imex npm run build", "build:production:rome": "env-cmd -f .env.production.rome npm run build", - "build:production:promanager": "env-cmd -f .env.production.promanager npm run build", "test": "cypress open", "eject": "react-scripts eject", "madge": "madge --image ./madge-graph.svg --extensions js,jsx,ts,tsx --circular .", diff --git a/client/public/pm/pm-apple-touch-icon.png b/client/public/pm/pm-apple-touch-icon.png deleted file mode 100644 index 87d00f76f8b0abc9dbc1b2e70bf8f587804efa2b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5558 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 Hw}|*ZDsY!z diff --git a/client/public/pm/pm-favicon.ico b/client/public/pm/pm-favicon.ico deleted file mode 100644 index f0c442ef97fe1e2dc54328eea998418c112f1d03..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5238 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 AuK)l5 diff --git a/client/public/pm/pm-icon-512-maskable.png b/client/public/pm/pm-icon-512-maskable.png deleted file mode 100644 index d507e778bd3adb88190078e8f492e50ac5b89922..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18465 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 UcVkrXK)|28jEZ!*q>11E1%?$?aR2}S diff --git a/client/public/pm/pm-icon-512.png b/client/public/pm/pm-icon-512.png deleted file mode 100644 index bef51903227340583a0ed98d2c41bbcb250fb187..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 29139 zcmYhiWmr`2_dPr_49L(7CEX#7q~u6g)h$B=Z?Miz4lt`L~3g);p0%@fIuL86=iu{5C{VN7Xre@0{$HPj9vnN z!0x(AvY_$-noSUh0i+`TRNv>tcBZ$5e#dE7%MTbWbd!}jDhGwsbwDy%fT2mnQx-~p z6yK6NkYbWTag!gsVn&mEa3CdyLO;AvAd-LdPKc2@|BUWq=0e8mrWQ*A&)M$$VP??v z4V~au|AGG9sh@)D*e(em*u#w0)}IFhO%hx^lFy_y^BPIN)8upDE?Tt^*+8!gz^2d$ zT{s6L5}v?8z!>$kCy$5&lEV)Y=1XR=*lK&u+6_I$`pqDgS14Cou}-)tU+fWW2hC_Xn%`>h7TBIvsi zs4@cHHCDWfb1aJE&p~TPchDEiJs>tWPpFF zU^~QodN1Oju~joNV6hhcqXl^hUA~y{!LMA*f!yi%R<7 z8@Mqa!}!x4&%eRdj|W;_T}A9pS*rb$g);=VVDp0)+Yt~;B4r;dhk$T%p+sF%)`CV= zY*(q#2JbjqA~Cjt>!;WU(L{$7Epp|3bW;JILZo^RV8)Rk5)hZdr{)b=2F8;g(+LL? zIGfIpr8@F`QK-DDS)z_@D)gUg>o@q{7ImC1w}@GrsW)eiIC>9LJ|KC3*H$W|Zob@y z<}0iBJFGoO$654MMwy?Y`RT$hu(y$|gz)n=uzz+^a@9kkzy3}`R`8*4;Ee%wy2a11 z@jg>$*S&s?d%mgxa!N$}xHC%=jDAoh=mU8IH~t4AZ(}5XX@HWL`<4G*q7brFU@}84!`R8{W$ONZ?0;+`#qC%|A!R@^ue5KN*+}RER?n zi=T|JDz5#Rn8%aff*)#2x-CAy3~aRW1xcuNJ<;Jzsn7(|M@Dc7u?57UI%0Z^-hkJ8 zBJLDvOV}-OYxH!mTxg^A6zT=B;$&z!FepC6A0)6POoe~ZLc$QoX?kB2p`20@h4Q)9 z?|0#{^O%tmVA3&Vp^k*s_t>99TVFov$RAtn1LpB*{LmMIODC>~-WPlA5@{jhEXRd6+CjG{9ooT$f89lDO12 zd1HL%VyNFwe-RV%^kkhm0i*i>dH#3ZH9$k1#li!k4vL{;q@M9!W5{l#AUaE}W6p|Y zwzZ!)1G#-BT6U*ns5)`Cuw73BJrtKb6)ZL4LEX4mO)UI zPkJR@XYM=qIz8=Up8MUz&#cDNQt#hpy4fJ`%!vej4clYuEnN z{3>yzsVv!NekBq_v~f!b(N%xf8swjq|3_XHGR)EnWk|1bEG-$gUQx~V`gckMiC0~G zO#LNiizR^%48CS#mFE5ze`ni^ate=#gdVfCLJ`itL{hT%e@|ZiqCb0>@BeF!V?!DS z)j~vk`1?VW)9>ZkSR3E6IvhI|n8J{ct5*W_b5ZsJ*0~-7Mu)GMG7|cWk%6DsCI9O0 zZYJ@7TRCGeE)XHD>vDP!*sgjCNEbY%uGdDY2oYgp2;Ku91lF+svA4$aFtY{@KnTmu z$aNqQPc(D`bJ4Bgan1q@5hi4dVHMll_d7dIJ?hso5Yfhxt@ZU^#rJn+4_KgC(8W;$ ziua#DuBUS2WD)?dzWM7w*&2MYpn0Z%XngvB-XGps)eCzD+m!4UvIzkNdEdU2>YOF z_460G`+-Oj4l`wMWkV)Cy5|Y8NkG(HGHp9MCkqcO7?9sZIuR2pt>w^DH4BTHF5zG0 zpzU2z;2CM~Kw``c<8Lldd3ElUM;fp$2S_i&YH#!Lzdh{E7xyKIV}8sxR>S3=I2MLa ztD@700Z_9SvHj8UXJ-r2d466lBTss_fd^Bi-aVb(^YF_C=QLkOWBv>s0XAV68JFShgA6mRb>7{3^-7fT61hI zKiW;YbDk~ogS6f-#y+;T@$w6!eP zr6)D&EA4@^TI9=+G(~q{e%z`E?3bj6>(W1-+}zHQdk&L334r-sQ!|U^S(FVD-1+(!D&81{sV2MGcsJjJid$ z%i=-lnVEg81B)X@D(K<$BW2}&A9>{urweY)@9~{D`C3?WDKqN*82Ko}24A^9 zt=UP2w##4+g~Bzb#O60Fie1R=F{k>h!_>1`h!PYL#ZYGg`O_*^0bME|8Afr{L_nHf3Im(~eEM%R^>z=Lum32-0onU%}#A;alD zF*XnuPMx5zI}|8z2)1F;`=N&7kVMP@Z&aG9NR(AR5LrNoU{bN;Z1sY6DiL@4i7kqV zM`2Lq)^6w;Zg=<($v@9y9P()$tRX}z9PEWLj(qP|NJI`IT^UeW03u3xGsLw!3@^SJFjc8bxI>?GN{5R}0^)tH3d_wecloX2JPn@3x4DLJWJ-_-s z(%>kXA51PB1w)WxWTc`UcT*m6A<;VeY6d{auvqv2^=6G|BP(gmNz8VZl?8e z6Q^o^3?52#`$b~C)xP(Tods>joxc3vJ|;u+TYbf@=e{d>nLDb1#Gmv-5ptFHB?9aZ z%Xt@O^(g9o*2VF!waGoe)=#W0We}qLF1ZM2GdA6yNO|1VCC|mNKg#TSy%F)_* zDL~o*Cl@M<=+VEwv=UiA`-uQyNi0dMS$jqaYG)>DEBN25mPj^sj_T$Kf_^p`JqBY7 z-fDU)nj`RF?oU#HG6W1_D~mWidi&9QL_V=U6u4@b7bA-(F$zdAei`?${%;H_5+YfG z9#u6u)HmbaXdoJ`A~GM%w-IenEI-y{2Qm!^>`%zwMCSD+Em@qUY#A^FHnC@YlU+uU z7Pgug&;bA&!{7@IyOb<%9@cy9q@fOa7en829RlrmbN>pW=MZ(syMKdF25jxwQ$h&* zD=@JHqz?AJCqny!1wjezN>uKJt@->F~J4Xw*Txtr12yIDts9{}l!`q!E;l zl$s5+p4-kO(|Pl$(B{9=WyCoL&HHc>VX5q{6}^3RAMjz#4@_%3Aqg9&aVdz`4OrQM|BaOi!(J@m zjxUKeqns20yA-~PLndlX3hy6h{C7Tx8$9y=O4D}tuVfhFf7v)12mU(vzjeJPA%X{d z|7+I1-Pz#8lgq>aXUgn_A1Z$$&C2+L#JQ%yvLfPPdiA823BR04{?mTTs9B|FM1SG*g}IDF3!b z1q7d)e*(9C^P6Fa4R~UO2=(k6DcX=HBt1!W>7^ze0gc4_lNmy*xzmtNfse@>iU^SV z56N=F`bYc;7SCBgk&otebQg6nT)#d7R)WR2NCc@hGr%XTsv}J?cocg`LDoOks`;&NDR5PZ#OS0wnw(!isQt3ja$H;EPOV@7)*w~wU z2}$!e)GN;lV-=D$fc>DXX8ElPTCIMnaK9u&25p&d+?|s1kX6;ymNEMBc&?i5j;&9D zZHN7S30o;kQA^_106Ji(=sjd{7D#?JZEQUSZQVRArn=*)YLoxp7(YVX|0oLS#V` zW91Qp*>;$o8+=sOcf)!W8&?I*< zo95(HSwaP01o;((?El;-VxAY0^UyvYxLD3ksQj4%T-_SJ7;05m<;nSEN{zQ zDP^@lEs{F);beD>g0+0-u}#7!wj@~s%b_`^VpJAWLNBWp6oYlgp0U_ zIeqIW3^|hd1ey>K5>56RxHgQF5bvX-tU4;=lHHw;2HKS`Y>7p7B=HQqQrm5zzwM>9 zbY;FgBP*3E1fq2|yOwNU3wK;+003o`Y~ZnGZ^f1x?Y-MFvC$Hcr+dzNcyvw=zWc*y zWat;OdvF+QW8gBL`WTG5oJ?GHbyW%izuZ}z{l^VtKNnnk>_%Fp35K3)84DMOR|eb( zG(NE*W4oz~eGSDUaryR$ui~FUPz>6lzJ#Vw{l0h*vJSQLAADs5QbmW|<@G1D&zGxe zju&Fm=z8lim#r-3ZsR)GU0Q9h!h0*)7{R1<>7K(nI$`7^#x#q1Xloi;<6WpI3*Qr< z>uA-5?mGIyUNn9EW>b3;f|JICfU- z^G@R}G=I5#l=sgch8-MJDrDsSV^Kf@l92lGZ8oV}%(K?Nn!pzBVE^uVvTs-0soeZw zJusvIZB_+iF06R(tI?V++ol`spOvtDTY8*7$dr=b0@Y&y{a;IB1X?{&lEnw6pva`n zF&|7w=NR`KZ6x^dS>ZRE;mgd8lkB~3cax9UAj6T<^CJfbM%y&Qj#?h0?<+b;fe6~6 z#a|5GpZli@OhOQ@?S1vN*++u6Om{kFjk@!df&9kVoKnK^Jk7Sa$1i@bXOjt9K)DG~ zJR95xt|Plw6pvO@6d$Nu0e4Lmt9G$5qq_g8Vc>;*gaIq0cuBiuFva@fRr?)cZ0Kks z8ZPV6uc}5xAJE@sFXREyZkVWI`szklhVin0(F~v#7{EVBP`<9NFOTga)i}*xdKuxp zX%Q#cw?73p%B&dq|6uA(5J_L)IPm*${x`*$YIrwMCqTdhvgqNr0Nzj3SsE_?0Ykmw zPBGw#?Xii<)!np08P^-<2&jGg4al)qIu7cT zp6Fs^??sE>c;(lBL~ z<|3ddGtab-=enVV@T9wbxr^oh?WN!#wr%{CS$5Y+)u~nW2ir-YI_)?zBHvEesXQ_v z;V^4-SyV#=ESVcL(Uh0#kPCArMk&W${?evbY;l;07k+kyVa}4_MYkNTE3eONUJ9@C z!Y3I%8m~t^uU6NFj9sk_k~{oPBzwl#;|bc25AT%CB9=~%F(o%DAmTnFHY$&(@jh2g&lYww9ZA~25NzNWV z)<{GdVVpHfJm_*C;4v!6`XOS(&TuolmcH>#A4`N8N0D{xC9_6YEYb}rL{CrrE^ zKKU7lclS!TlV|E(fReEp|F6`u)3>J1N*r=Wt6^%Od%k(G+tUHmN`XudmkeH>#EpOSPHV(*r`#3$l)eoU;KsI-Lc@KI!` zSuEucpkCzW^V(`=4YZF9YMgIH=X+mWo*T{hhFviQI4%!96t=&4OZd2$WwU;ojQ?<{ zux5(5yZ^|#tv=J|dZj~>nP}cTe8~>uAt!(~U(OOR7KV2vmoPErn3SCE_;@aweVq#P z72Y3DH0U;MoN_3n?s?&AlbM(@gS^U7nn9yv>9WG_>e#hDK zcl8}PUcG3EUaS2k4eh}qK2a%ac$7oZ@0+?egqMN0){CbEO4!hRhZQxgTi#HzdQD+N z$l@t4rbS~D!c30n`I23RH)<~2Sa^Nf504S2n6wt+k)Q#BCvU%tX9r!f2M5{snKH*L)-uA8Ch@Uc0ph&gxXAB{ zNGnh3QLnq+OlmBg6Jt-5chXIr0;Rr>fk5^Xz6HyfUlM4BHx*jR7N_W)rw2G*y0Smv zK2@G(9`!X?`g3>^F*X^ei&KNiR=|zvK(29lj3hZIpwhlqop-GH5_9P8hlwRU$*ZWe-W*^ZKx=U3zB&`_>uZST&8SK zc(g}=qAEF0=nKaRJQj!-$_YiVK7X->S9(Irf9y`Lx03JQm6BCj-q7XoTN3=A{_3Ah>eJa@p-;@%nY?Qq^%{n~78@rFvMd`NzO@H_4;y0Svt9gg( z^Zl?>J5pA5&7M%<%sRIoKdcF4PCB8c=Q*!W- z+F6LGc~r0&_0yZn$|LPssG-wbw5D_aGGjrD6gHY-6UiIvaAJ!xk`pC3XImTF8Qtx* zG3bSIGN28-8Iywzg4`X$1F5TNlZ`K_YMhqp=2E=&Vk#$;>i7#6a0W>C{IO?Aa|ulY z=^%q%wnTNw`Q;q0pBXD{Z!~9R+~}OKulItr&82s!#2t@(P+WPngcsxh(9#K0h1wbM z#s<$(Ko10!(8v@m*N}QgJ0{jy!QOu)ju7N6&vHsITwfIze>rG|KRiEHVt!N zc6KNTek<16j-rvh12|KlPTQDrRVV3UcKy4(6Qv7A*{UAkTPs=4WI zuA*j-x$rvx}Um9GtW6Dc}7}N@=JmE z0WYPUV@bia2P0P~PMp)mRkzuhQu5EM$8SdSDe^yzOf1L#Y1|B8Y=%!J@3@W)abc~0 zqCNqzDxeVr*XHe@l1_^F?));$-dUF019RtXF50r7eQ`%X?e)8nBZc>tjAgV3*825G zbQ!p3DMDL4?#fm1WX8(rKCh~!E_)58$T&RR6DaP-?ZSj9OKz!oU}YO)n7Om?M{; z)a6;twLJHrLMbUanp&Lr{Ibh2SQ?iGlZa^2K;SIGy#tl?^-Bk5@&8c|LM8)KPvg-j zksm?N)r5~D6=n?`rlRAV`(xgtQ_)pckeoorIP?0B#Jy{|fQO@G=40**O-k;jZ-%^n z)AyOgGm;pFq0@QRaU-RlZI)XOyGh%@5IZkMqCWRXrQ+xKSAG6bPiHW5HzVz+-SGX} zbaDEJ22RTB{&GI7GFvBuXZATuv-+<>;+;HQ6q6kc6m(;M_ps%t^&~j?3(Yi<_BxoV ziNCG#?05CSp~E9X70~Dk1=$wp|9JtnsLzz59WPez2G{dmb?DaZ6^hs06^e)1D*3M< zA5GS*qv+x*SZx&DDHz0I_j*38!OMXHp`fP7jip&+vRoWRU2^>f*Zf3S%hx;35shKY z2-c2$opt>Z)_kSl$nSQol4CNp9K01mSW`!8qx!p$_5kQnF+4$H@7NiF=cba1_1jyM zf3{WNIKR?|gR-s(`NY@dXvG)APAoSOGh%Svb@Ro5!5I{3a98EWl*r<_?A?|_kc=WJ=b>~gkP`NV z=}YL95dL5T6{l&fFa4-|vu;@uu1s;~mZjHE%4ZNc)6Z zjEPyh){e6APFZiX*yF>iNTl8Ov87l_<1GoIG*{E6fpu52Ty`uo5|G#Rh=>R0^K8+a zrrqb>(fb^TC1>z}#XKb0wX0NaQsk&1=x~LL=qRS053lNKyxvEI z7Ee5O4A<-`mt$x8*xvCPdt>gA_Byn+0l?gpecdpixvPA+pNZ11H~#mFgOLN$K$zKj za>MrQQW2R32LT;oo#TFOO?@HdXh`ueizizSx`TD7q@OH!1|zqTN;_P@obryO@H)|^ zH!7X#Jp;Xf)wjVMsRD zS6CBO%>Haq)R$tO1BDJ8W?s$3{euzhaQ?BUGI1P4M5!BU?w)_;KJmg3_iTQ&WO%iN z>jrV`QMW#(R5D&OR}@tdS_|?vFf!vofc2E>D@85Ps7B1|u4{|U3I1z)=HPeO|Azx8 zg!o2-CRqQEGYz%FTVK~gB%RQ>Ig^YmKJgSMoVtozT0Efn-2DgNVTL>|Uhd$RD~C=M z(dSiF1R1+PZ|YAw37|KyB6pYje$<{N8YU!@{;7+1HncfSMp2K|^8-=|rF)$0>(J8TdB*&~h^Ml%p2B*rxtkUUqaEA=l1ZO~CnLTdL|!VH2!z1K-}4QrJkH2tqh!i&4>yTQk3xqf7K z>S6mi;sc?m_0bm;aeO8d8|a(0R{t8)eWj-}V&y3vX8{9#qHU&vYhBzBj+Hx@df=^y zsbhlUz6=2kp-^Y!>3RGW+pKPjN!6IHc_NG-9P!wtSP-DZKj$I&(fs91olMQFelDkP5g z&=mrR$*z&Eu0O{eQ^>!xmT0rL=@B&SB*E|L^CDQeMo{rkO}|fA`zEDkP;ozv!*G z+1S7I7N~9KkYEycV5tMh?#4ou9$ZvVaX{6pXup>&6Fz{kjl@)c7Fs~erAMeH#^M4j zJNg?4zO3dPFet&gJmj+U&TNT)p?m-0}_|sM*5Xd=a?+O}TJjcimO3I?u%iI5U z-VQo<=hmNQ>=(1jVfk9Zf8**-YEggX+l+v2} zQV2sB$uMy?w>mZluCWv1<@?DpxGvuqD;Ly_eeCVyx28{1)bTGzlFEXhN}g=Ottl1km0LrhvTulK?iu9Q1mKtEB!~QEeSe#6vNkHyEZ?%@rR|0N>EB5af2r9*NOIq@5b=T!(g8fi zmpazQ4thk%#UTI1BGfHT1R6ye)z0VaC42Cz^O{xC_FC)QV;&2I@$LhG=j1_WeUgB9 zHD<-N0?tVO))>WI_>T$e$$ayK42p)oBWxW?KU5a+z>k6s3)n>ou#~i6i2g3Y;`Ph- zr!r^nz74Ip|D}5qb{b29uV#5q?+rKLO_m_HM{i;Z>@qjvZOt!(QOk?jHp z@t=PCFHcXtUj~n8yJeZ1c&V94nJdy3pXY%@wZVte!~Z4X<@aWus$L`V4vUE*56=EVD62Rr`{*^ z4THd>a@{>NmwP zw2-n!<;M6G7ZBETAHRYz#=NDRQ(V&TaDCPC+YD(NCdob#|NKQ}Seakm0;YgTU^**U zTT=hIT{Vfz@xM*mrEdjUx*a%6xfy&NO&WYp0g4gx@qJ6xd~Jz)d$VJ*E#q6@FT3M*8%=KxmildmnRG8q$2HFs#3|mWDv@DTgo5q z-SmW{Ibb|aLnuqa09j&K5bbgo>$$Jpt0t`T#Ev}r$s33+2IDVAr$4?jn~h&>`96c{ znnGCizhil6hhjlT>9fZ%d>>7A@K zbnFWni?iyFDi~VdEy=ZuwUr7B`a#9~wc>rfY%j3{a`pUgPE% zZ1;U#yT&f1oTsE9<5CwBCl>qgDZGFP4~>;gMpmM9>1Rul~cjfh*d;U?>6ya00V{0!M!H242|h4x=A8 z&c1h~JjUsj+8gNnh~IDmcjox{N)wa{4L#*BGiqRx_9=bRlgL5C(Nl1yEhX#Z|5kNz z7E7rQ``@{wiURnYZoX+b19yLZ$3Ot5E-YZ1qNMiUk|0C% z_l{(jJwFPu1>ZM3MSSy4lbXSu`CgVKqir(PCl$@w+mA~VK-WJ>_FJ!x4p!ErykK*f zH{2#1yxLM#y(hvtWe#md7sv0sB-trWe1mMJWKDcsM|8_ceHbPBPZR?m4`$rw9tp#+ zj+z{Y+H=U+g8qY$J;%HNs(m>zauE{9bJK}@K-(3uDf8OCvm5W7ol!G3`oYt)yIYP3qs&@7q502^ zIDonXSxOy~mzLtkG<7-lahi@Y1)+@{vQCuM!8WhH4P+>4&*L(ox! zbzh%nl#e-~0?|+ICW}l*_oU_xZ`R8`gHW#vwASLgjeQ0P>80qI=U(1jbjScVA7_%t zU|jYXwcRGU3lFB+MI4{hMH*1uz1Nr!A|tvoHk)b)vn@xzYLd-(kqM&@9R(#^YF^^l zwg9Wj$2y-;gSDq_W{qYy@?7=XYTnY$i@2Enj+c2ZC@DCRmfms^OA!r#4EJW5!vIX+ zil@PlKjw=~&vsLn(pEuo?xeYGtqN4P_w^XaeNyC`{DPAcHB#a14J$c_PO~a?@1p@wYhke`?Dy?qow@2k5qP@* zMogq^=cTfkpv_2!hnKcoH1gIKpy;=slyX`=_fz-16%i`c8JO0*9h5lfknvhl#Cur# zD`8y{-jmcyQfnUEP+nx&Q+9hz$3zDb8puv2It(tY`X>-nyYczniA3Ok>qE2sFKYp7x??;PlXr(@|e>d7JOE~nGUJ31Vi^Hm&FPrTy86O!KLrR0>n zBTwO2i?~7&j{rZBWT)>+=J*lbccAKHyl-t_p^-mu04RBL5`5 zIDBfL7J#0x`jNuU?3Z0loi;m`FRmy#tFPu!n6PTr_@t5~$IH)3K;Njj#6D53Lc}P~ zpvm99>h~{h4Nu-%M~aX08DEOjad5MdiEdtAzK1-RJ0O72Zde{(y6Q?=2ZYWCLE~Gm zW*koJP8d+$ooK4GB&D(FXzO7vS|a+_EmZJN$yFu^5+>%BbJC$*z#V!{cz+VLz2^cUQuQSMiaD*ng9959^!iU@%kWe z{gim_uJ}{Hxad>a;@a4R^YOa1k?+bd)We64{^4Yj%`+!g0R^+_^Rx=mge5S+Y(F8b+Vq zwTc0~?CU^ix6-eqe$O=~?Iu|j^?(B}lpus=oxRek_l1YQePIDH85d3X-h&0348D@< zcSTgPMJ$UR&{_;t3ceVy8P(D_)>zK1vjpBrltcILY)6BqBaN%=JS zE@&I%W58AQz0*5{+)e=j=tnHbm0wW*tGK)=H9hY5BGt6z)bZNbatUx|*dR`$?$6D` zo?xyBiWCkjj`EpP8ikbF*On8xB$(3$=`K=#(T}Tsis!ceG)&ED-WdCtO8BZQWSVk? zpEmdg_zt3?$2^D?B&^$IF!1T;_-&+hz44}VC7QG57--CVquotY5&!FaPWb*L@;rl5 zHkmA|u6LwM!_juB;@Ur7w%<{N>4-~fI9k@3oJkO7A-*mN9+hF_+8vue|7w+ET0uE| zU`H%ZCQ*$ca$b@&>6);2UTs0eMd`}a+%sO~B$0I6B7Kq>|9TeMl1k6@1tsbQ?UZp> zTa1Ety@vrzt6bCTE~VqRN$wZ}>GRw6en^W0^W0xUg`}DtDY)31?1k}q&R~hviy7_m z#Bb>NJqb5B?R@Hi5nMZ8n}%wPJN%5!0mn0=lVGLwo8I|pi^^UrU(h?d#12a^gkb8| zS)kjZ-H16*J?uJ}WuxM`7wOEfKOkzU?J!MZ-AL72Rc}^tPs!_;a`8GP1Ko2TX^1t* z7yq62TPW}7-n8dKY0{=X=SMXyy?8(){UKx~T%AyV=jganE8HV#yZNS{)1TiyfIl9# zo*IE91zhDOhh2Bdphmg(zoXd>LkjKW7eDq;Snl?E+p_deTa5;{mSkrW9Wn|C>ghb6 zPwFA*P}Gz<-jz1V000`SRF4bXExqv7aIXcTqC4-0ZPH0ozC zN)Jl6Gbo8t9xM0P$%(DxWcBA1C6pkb=>nW@)?2&GVlLbd!sFIM#~_AdsPpSThPG}n za}|Z7H&frQuzlk%z$M>LkD_JL7p?Qu{5OwSJg<}>i)I8luIk&le^W_(^7@l}ZZ)sS z-@#Zx#iMVc!3&6+p4Fi&Bxl~yE`}(yeAIPA&0-*3h94lIQFalHJzx3kF;vW#j_T5{ z1;LAC2n+>|>B4>Zs~F@7517br=``jq0_{#?)SfYUq` zudGHLVgxuiN+1BG*fV*mD^_a0)@P?PI+?9jlGxdIyVIJEXbUkQTS<1DCb@&s<&VS8HX^rPo4xMIB`(9mP=Zq>b8jm3&TX&;xuh~Cs3WW}uk zaHrkm$nZ7l&JC)x7#`a&ypuWArm1}Sm$kc3s0?@B8&7F8 z39#-L4X*g^t3wjdnc&Fh)^-F*)bEg-I8~=RynyL*p6E2S4Z9k59}wst*1n9U?5hrq z9qUO(bhen}8FuI<@3ZT(j~X<`C}i;a&SN=DzZDx@{p{=wfd~e?DWAEW1#8>%`%HB1 z5_a5O8?71}n1SLJVcXIk5RFTJTHrWhQjzGF7j4%4!>Csm5jJTG$oihM;q8<2>#P3B z=4`WzKDa2x^v}+9*ReZ6uy$AK&XLi}R@;Yv^5=mFQ<-lfc*0T%_AY zO$Q#k&^WHY)<^VdJp`r@U8@uFp`7d~YU>B?GmjQS% zwF|}9R$8q9Q^&aE&-8=y@ZafVh8%8;yv0DTHh&8sI+X;F z>R~lT5*p@RvP}y{=GSs;rN3vZ8+#}Y+Mj|iNFqqape3Ng&F=WtjJb+-DGhsK&4j@B-v8>pKt8-{-y1g63Se=00f8@j zE_uB60ez6wWJ#b0pKKKwG!=)E048pZjRx~c4i0tybRI6FVvgpwOCl)vui=M)Dwkce z{l1>Or`&&-L6bI@Bw>>i+zkrlI_@yFeDHtL3a#l_N0)FjhONxDgvguW_fEF5xE&Jw zB|#FSqu+uMn&tHOOcg~_ukja|s(lx)QJ8WCAWnP&dqmVbaSCAuqsdgQmKdbzK0wvX zVERTFPhy^0m}HBf)*FrWtTop!zgf%?9ACQ->%&{0Lf9Di704jzJV-+}{$#e!h*qGA z=FER_3sq{Z-Q!4a5@K!aFfDijHV}3>519Be;wj9OTvmP&RB6nvgew$knRFAp+48Cm{5uEzS_Jzt0oMo~lPPaBB= z^aX#6=b5A>9F$)38229UHD=-7E2+siucN%lplIsWhv^pD5F<9z80V`R0hH$&{}zBq z>d-%7Yy9JihRM7y9`aO_zFXgG#DT5iNHd&Y?J@_yAUq11Yb)^=@zvzsEdFf=9Fr6D zrK6g-@>e0odxT@yJWpJF!l`r)9W|%~uNa2%A-O!6bHvTZ%M7uM#yG++2cj{Iu*L?E zs{0rbJAEX~w>Q^{f<}9M%L>Z$5NJ0oqXH3nekeR>Ip84J$J2K_S5;FGm zTS-=St9hIv4vr%uxB;HfZTK4Gg@Lj#!a9}^gBYHt#){C4N>^<+Z zsd`%G2vBIo)s8Js%f37VTsC8Qh;qJ)Hq2oot0Bo!n#Kq-+9$mdTsfD=$!w ze$sl%Kq7OL@K)p}XupU|{3N|iUrfCnckvtE>w;ZYFyu$)ScqQIjz~+uJtenoxZEkY z+v3?t@vLj^*q3MAiLCx1-%bS`sc}*27$vcQY5&L4&5j575{&)NB%yp5%))v%?fEDn z2H`~}ieb)>3$G&Xv8w@6pHKKcOB^q3MwM1bolA-fYkFaD7R*=!P+OUV#EcF@;qsDc zFFIjsSJ?CmBkeanB)67qOqx_X{-uJVt;sCH*ruNClOfF%*~|MUFqL(WuC>wxpAH>6 z&%OM2G(5rz)r!&1PT<3D>tz*Q(-QsQqD@+TGupcNca+uJ)ZetQF`n(GPeC6V;)k})4dLmRCBrukn#V5* zIsT3(CKslYac3X@epi_(!8R2FYPTTVH>L>&+c~n6r>?MUiJJ0~jNm9OcR)4r z-~k4qC+A|t%;1KLQqaCOL(SUh=niNEcacX3%L<1#WR>MEx-YY5xU=ScE-^x!m=KFJ z7+NSv_Kg9TNu2_ShBb?)ev{>W+zBL!U5e5y?KhGfah`iN@+Rbw-kYUtn{!{(cnAvi<1m2Ug6_~rp7>m_*C zc?%R}d#lpiyc*P}Cy@ZgAozdqCuiKZygKO#lgV}0U-LI{ewVVNT&2wLHX!mMc0rvS z6)FN%!p0gS7q&0Sz$+w3->>tS);KUfH8+vQ0c>M8sPnw}dsHuk>&PzRxn!s)z!?*k zYV$(p&7DwY{|_~ln*es65cLSrvVJxU)LN+S$R+@w2~Z}$%#DIF?b;9zZUo{*UO}=a zfQAxf1(?eDFAx3oNF$5G(ZoW&lM(GFdjHDVb*BBX6)&~@X9%!7vhV-w}%p#k+66mV?gW>weWt5J^&42T8)_+8IV(_qd&;L>5Nx7-~KB7tsqaPYswY|Q8V1XN9;`#NptYvgm8+$eqff5*AKFIVxJo-wT`6_f0 zNBoC{HIz@#W(LBjfUa9u@k%udIZ}gJF%atMvrA)5(S!Jpyvq6wG;gsZvOeai4@>a$s+0>Y#jKQ@5UeR21B zV%Wz3mO5G3fAqqk^HBD`jEl$hXP>Q8Xv)6gP9HSC1fHVal}5F31Dd7)M+t=uWjAAJ zI}@Q#!2U~>d=CSYJW;+RvGQh?hqCq)9Sbs-IO;d{68vQhfjR4HWB2k|$r)qd$VLgU zC*$tWbVu(?Tpev+QCf3NzF{7`?%!|*8p6ui!s51o4FrwmN9rv^Oq z8cY?Wr9A`L|M*R|h{KX_mI%~qmAW7ovSG0TxG*ya570wYgK%z@R6|R$4ccUf(FEnK zdC4FC2vw?dt{lzz$&BXXmth%BB9a2LNJm*;T*Q+aP-t>QxW9NP^--H_jzR^|>bv)n z0zT$JMgDX16Jsd2xi@lNFt-wx@Pgao`H>rZ&WktCAa`WGjqU|-1CDVhkpXl zMH{s1fD!IAD^t90exrv?4-OK>Jb-pfpcU3*qsboJS!$W=>iLv&l9^lQo4F4BfdD!p z2rVgfZ-5e1@r6;f=dnTjkEtsomzroF$g$?;ihFz}Ukgfve0WYj}$+?4v2B-Zwji?+ugdzYa%FabT)}Je%^PDQ$a= ze4a920({jk?$W|m=gvs*H{>PhU7hSP%;B0I@}ju+Yb1MNvu{6-&Vl(N2qcCx|JPEW z2mvL$_&lgegF9@p){FS==@l)o|9R(86^diY`NM;w)z>8c5?Ks?ltNKz_584`aw z*eSvM|G^CYzD6ePmjDK=Mt24g6wkeeIvW2Q%H<+PsaxvGhG@=S{NW4t_x~ZT9?`tM z<<7C32;{GIHI+eM%+Dwu^&(mTulkHm2`*Re)yM=fWQcIYwvW*$X0aB7_r&_9Hdw*wC3{Hw?+GXfVK!`wh}#{LI3j zKo#KOskHf2gvu02^DCTuT{ru=asXjiLqSf&lUz&Bp1m}<0#orhf2b4}GIWu`El z=*(Yxbx0)a0stk0*qwVKK>A%8@g_)&EWZIfLJ*w^8{QNGK$b0rD@%KO$xn_INtGcm zG+reRRXCW7h(z0uWxk3+$ltT_2-l1OSJ3GYjY8V9~X!!pidG@H!$rC^yby%~K zL3u(*k?Ay&jG24u%rJ5f~R%|Q;ls+%`Y^oU|zD7T8Fu+K{c>pbZ@;QoD97cS+ zj{9P6GJ-wk$qTySkVXNfre89A{y9qL%*q1;?45~_S-Ec=vX^~0fysX*JD&(=#E0LN6lTM0T^IyX3?=NXydDRAd);@~LQ_s1{-UL6>;O?^q^(qA6Rd^oT zTS?20Oi)*u{NQPIFI>T;TkgA`&<)92;kg7u6a_t;Duz%4}+Sp62wKUWv> zDRWj70@UpJ=+PW947dz+HV@2Yb2f*5xRSmSPW4h^+Q+;S3u?z8SRn#>?&OMr5yR^w zBnxz$5=E^v35wSN_mixY%CtO_&q`Jx#+r#~;U$ZHz+;r~lMnEk)_TZ!GJRZ$# zV+dan+zj~M3;-82FwPVr8T)s0|3X;}o_tm#f@oaV72e5V{WH2ix`N$o>}_n;Tl622 ztXY)!{wtcCg>hyOS^xaxO-}zINF?$X+&nJye-QIhiwKOkUx`BqJ^w~bH&cx;{ueSu z@(Mz7VO3j+N~G@I%Jrro#|peu(M=(&9BB9mV4-t7<(D%-H=Xjw*NRf?bY1BtlQAI( z^}t0Za=QBiM+On#9A0oq|K&@BBaVy+y7wbAg-6zBpcdsfVnPl}Lp5pb}8?sWuuu&!^ zKhVf7x%t%PQ3QrF^&erznp6KQ5EwQow#c20yZ5zRj(S<@ULm@Uyts0?f2+k(+#E<< z{B{uoJ#)NgbEmn8@Uyi1bk7VI+~ej=A;(0Vz~)5oUs^5lB?57q@4M85`#Bf5;Y|UW zj0jwJW0&uwr&RU0Dy(d0s`XvzlK0Q_TE`SINesF^$lxURn1(!&B&&q~`D~pSEV#ls zdp=VS{)yj2Or~of&2*08=FNI(zT&~L0p^5L-;Uq6R(5f|0&qof*2fI5P-%2(5geaZ z1kq!Yq6UFFH+sLRi#s3kN_y5INo?eT855Izk&IM%`b5i@BuGeAuBEHjr|R9bRUd5} zadK!bMpwQ+vL&h!%TVfz{F5joiYF9rQSe(g~HFoE156U8c;h$}%H)jkc3Pp&+< z0UZSn4zfrWn`A{`oD`S}D21D2bR^4Rl?80wv{&B0r=Q0*Hah5FtfgCCSxQ%X`@9@* z&|q#*iRJ1fu+<(b#7i9eZDmrWi$2ZD(wn9!p6=khQr>7FN5ge0-RIuI-mmX_XEzR2 z7gmDQ5BncK_ThknmOt7r=9u^8Zmprwa9YUB4|b~XE2O3#^`h<5JS7LTd%IgujPwMe zz%3MPT{Ff9_O44h&Mt@B_&fJ+%Z4lqDR<1($;tW$ibc%R!I#%J|n11?e)`I&qP!WvYo%? zPaup6vZZH3+Tmd6AfNQRY&|_aK?i-Z0VpZxBuA^ytBJm3M<__aog z^Vy&2mV7GQjlj#z=W>2tCKELErs~ukwq=CfMdFsa7#_y<8V6I(Ije>WfWTE{& z&iEcp|1S%^35f_?c|82o{X-ZxYy4;3QDF+qne|!uc`(zh+)&oJb0&So>yC#ho>iMeX5E0InDVZ^ zwgj8qQs~j?)x&uH=l0?&e$W~lP`xQ@1b$xFMuJJvet}C&U-`my!_2~8hL|VnZ zPa6R%){TGtaM8S0e7R#NzMVr5PW&}rA1*R2!3gueGKQ938-hsh&b*J60*|&_kO2KJ zT=Fgqgu0adDDRb+s;_5;5iAW)nQ<_Y8coAno6b?-3`ZSgT9C5P)TwfpFXkk{Wt#xm z%sIcg@eD|I#}retc>{X=7+TV#r-P&~B&tn`5FzYLw`TR;{3Yq%2PS?&(QgM(P_Uq= z#>cD@(v&SV1#XSi;kN=<|CCa5f~#e4p!kCOfbl{c3Q}2z2f>JkS|=h$XJjEIHCqMe zGH^cm;n7`Hpis3cdS zEjWmY3s+mlSbBJyF2Tt+w>eMGX57J8)jblTfMh695i;O*bhS~c*aGpWRj4)+q`=UN zKNg>rB63}%Xe{TYg0f0_tgkU+Ay3DoqwRd6+Oo}of2idTzhlW1M0;4*hDXPibsP+B z`@`vp6WE~)Icl>C6Hr=Yr}LfkDVXiQs)%hevLyMDfEL>>srq{#H8 zbCYS_H*e&5-|~g5WIb0NR;QNoBDSN_beTqzIU##x{}!HdaA}HuQMpSq4(W6IZXY~P zesaQmOuCqZ2XallyB(ifQ*rA8<(W2VDk!=1<+RN)Fx5K^aXZ2ShB5DJW=^O`&KAZo zLMrMgQX?$0Rhk3J#4L%kxtQW$1Rac`k>a}IpV4}2X6O^$!?&)r<{>oL60S*IrE9WK z#L~buvARYufp4{uThZE!sae!2Pco#h>p&R?VgwK0@|byhLY`41EwNsCKdfv zRP+yNJf0!vpz81QuDx#tsyCR-H=5{G2Ld>u7h|7n*}$Vq@`Ozz>6O9#2XRlYazU@!c7F5s|THp+gB*8Dhr0z zzgBY*{~4$#dmqOtspWT~Q?u1OFv3#yi^`^$Jowb>PZ|hQ6$%Vfg-tSCMheJrtfWJh zzrXv|!M2Rs`osZb^3r%WKFG@acGEp3jj=(9DMDhh2pr~YE$oVAV36Jiq-Z|qYpZc=nRw6W=38S@w5|956N+q->A1Kg=6%bK3d)X zr2>^6crV-E;A0~|lqZjy;E(RfO$O)nsC~QC?h`7O{P@Kc_$;XpH$_b;hJm59WeCLg z%Qn;H8<}U>p%Qh}Dj!e8m+z}GoR;8!O>poD+Ni3NjvZ808#kU%Wz#`s{J0@%&oyhu zbL0UEnCg!9jsi7(6d+#*-A|GqUqep1UOk@1*>|lx!umzuzEcWxt{&`nAz%2H(n7&cgMXjF=HPno z7rRY5S5AY(E33ffrWaTU8MKjs8SEScBW>&Z?R`~byXPKxm?Z{zyA^%-L5nAq5#+o>WG#~m)#(?Rkk z>e5QR{V})9$a|+v9C`g~qL6O}m`YK!S?fjo-ULO@4f3Ix5T#(SF7tt6W53GEgO2Ds z5HYE~Wo)2t4|cL5@1fo$@IC=Y0sne_DVnve#OEE}Hq(`V9tIIR=f@+BM5en$V+u1_ zJ{tVn+*BMYWZd#`(2ocC#aUGnvnxP)AlKYC%P(mi-yL3t8iRJ1z5hL$Mm+9bd1P_V zap<>G>ah@cI!I*zh!oJ$v}oodj#k0HD~mvzn3AM`1#?FRaz3M^AQ}mt&pGXVqT;*7 zQt2!B-#sLF!HgFy+Pe;SUm5%UprgXgeVQIoY&X~O@ba1c76TT5QKi)WtL5&fcI0*4 zqQc#@xfCqO8Rc*TrGeB1W; zbr08(}|J5r02XaNNYkvaj?U?;XyPjUmWn zCF0U!%{7I0J$HBqU;dlM3A`kjhVY1+`(zCrL_ZMAPk^1|Jx>;-AlT8C2QeE)fK^TB z|574o$nqMI|D6stzw2T37)H2$3TH>>29GNxFBz$iv)jMLkOm{1RooN}yZB=33|X?f zP@AP8Z@o`JXCyBlD&ZJuT{YrM$ui(_1;_aFCO!d1pzNG34|4O2#i{0y*L4~m)ah~B zwIll_G<=Gm$d3Gp>lG$Xc1)beemF+coc@vn`sLOA=rYX$75c+ylFfsE`*p00I6C_C zyj`d?Efo~XU219Igo>rKqQIub_j`-~y=G90SY1)JVXg3kbHHL8DRtGI_x`!5Y5r8s zlzaKdJDW%337n)f-<0$pAN<~zdw7F}$z+rcf)NM5UJG_n$N#p}s6sjA{ z%KkPh+vIDOoykymnF>cpNq^XUXP_#`6u(E+OgTxu{GhHDhJSBJ$1!9+*m^WRCx0yK^ZmQhYB0q2*X0ax|(xF#%a=xK}6Vl|i(hI$AY9V)$*va%{ z*^)frhwLWUaM4w9r_rwuWhN5g;3-~*1`oFy(bRENHplmgS@QaEiE#L=#d!BS?=GLh zL`r3AHVTY(_}Z!@T{-DnRLe@s-%l|y_0abOwNFOb+gl95VtRq zr9>H)NNf1MW=Q)orqj;}it<0=34U2x=C26L;Peuo%_Z-&6?~~+obmV%HNS{v{=Iwk zz|VtS*3olv=+abY#MZ->>k#B)(?C@nTaAoqTaOHzjkvXO4F|(+=;rf0kEFV<`!-Gt zgBL^Wd*+Fa?X`+h;7pe?0t!i2;B+vO8(kKCe?CN+dEA6DpucT9?qV&GHJF{m$GKo| z)viwPw0D)JB}}PhXS@{-4gs%Exz4)UU|)0CrC&+nV8ns8P7{lU(2p+*k|^uqKNL5pk|+E}rtYH7VgLK}p~P+*;OqG~ z|Il>gSz)s+wy+tpqp^}bnWhf|i(*`1t2O=;#^yx!@YV9JRTw(z%1~^x#GZF52isGH z`1t)&&DVEU&2CKlroVBgg-XC7C{aWEM9^QVe_CdG?cyPT3vF0PX6n7Ki1-zH(*=HFW*6vRCsw$X)Z>ZZuckb>W zajI(feDQ9;hdnM^34jlz{KndPPav_?^9Oe2_~Ciyo>3a$_WNJ+CHuB9p;X&Q>X{pc zU^mL(-|LV^B^hh&Qe*CIS4iLj<5~3@pNHX9oZYHb?+N4Lb&VD?(_-tp?;8T+f#WT3Net? z^>MBQP7vu6h(affpJ%JnpGuvY3sr#|DIxNJmXDCB8#dgTW<*hX=DVE(~ganRnA z>@P8IzgYm8uGL=WO&DOK3h{$gL7S)iIvkwY2mk_;Yl77|o6cKgq6*x>#j|_t?YRpo zcZVYsw`iiW*?mwg#`t|?neC{p`=5_mS~R&)8L%_Ygm|ur zjw>daCO$ic%`KE_kU}Ym5{Oi$ze_K5sjS%exb-T6#}>rqY{kYew?e$q5sOSuR2==- z>Z~xE92NV%;(1+ti_%sB`e1VW8Xa|S>z`ImKk=uwC4|xLPhV#j>Eq>Q;b8BvXsj@{ zyR$IdKofajF9`#|0wU_`mv_zV^zK>y-#aTvsxYUHY0<+1+-EpSbzQvXed%w~t^F6g zqot0v!F154x81ohmb0n)?(@FVh!wd0dov};V%!c~Sgc0!?b&VRDy4e+U`01H3y@y@ zskxb^T}O>5I!I~y>G~8ie`v8pvu?Iwp%ly>QNz>c*R;}OKsRy z%8$1x8-AV5tNwAi@irB7dc{82!iHyXG+@7#_`ny;wwNcx%1s-aD zjpAem97c=W%&Tb4f125vDDxTgOzt-ZS7}odc@3S)87#`i7q)sc-(!$o9Gi*jTVo39 zO8I(_d9%2l_X&`z+1%QZIpOrUP8;p{+OWo-s<1-6p2eW!Wxqr0*c8jYyj`}Kd$x7& zp0pmm9mH>6>=!jOX#d_(i|x%C%(Pt*jBhRwr}$h7_z(C5(3s;I&l z`mWv;NVsEM!&E_3BG|DdUX6Xf-EQLd$q8IDAdE(0yvM6C5@!DF1ViX74^e%@^5vYk zY&B5<<3ZtYQ9S)fB2En34s6P2R{P)%B=-?MYq$E_lZ`;t)j&2gM$Yg0+IS>o1w5!2 z_0xN?ZROdoUUv2UponJATc|TaL}-|aolyahH{<8LF^8wuN)6UlB4YgDQH+sjKX&xu*2}Es3elKedx&P?_==_ijk)=qYJcy`cUTr?S|xsa zC>$HI79XwvL1JZ?>cVY2$Wkh|xY<6e=qg8@WWh3rI=SrW+Z7zRqpE)3?reUf?z!SK z@x3v~+4=3OFHBgdj3PR++W=Es7`nYLv8fB2hkCdm?h~T0$bdP-^LV!XMCw_yfxC0` zQOaX{SMxE3;DSqSZGBWi3LRdS!HGO#t?pu2ITAj<~-MK zU!M2A`#B)+i*xb+Qf%w1I1Jf;tCgrVO}$+CrBbKpZYc?(wrFI}EK}+btmHCLwbkzQ! zwG&RYsNfl;?^9&RXvx~M5TTj2v!oHvd#G+88|aB8=O3oD+(#o>3^i^!BOh)yYw?Rm zr6Yj;iPR|V3bG0;_%KlR)y?~l7nH?6h3F~7xkXs^!vU^ZQpCwkO5J;nI?v79Jy#co zY68}3SO9HYiXp+9LC++Q-0EcI#*1=hI)6AMnj<-Xn_7ItYV4q)P-HJ2#f@&>5D?pq z>f2!e9*su5(fqiDxzhQqoqSW~% w{>Y1Sq$_aByv_ch6l#B&Q9eE&;|u>oePBX=`n^MK4+Q=g=oo3&Xkx?uA6FMA761SM diff --git a/client/src/App/App.jsx b/client/src/App/App.jsx index c2bfc0a7d..8099b09bb 100644 --- a/client/src/App/App.jsx +++ b/client/src/App/App.jsx @@ -96,8 +96,7 @@ export function App({ bodyshop, checkUserSession, currentUser, online, setOnline LogRocket.init( InstanceRenderMgr({ imex: "gvfvfw/bodyshopapp", - rome: "rome-online/rome-online", - promanager: "" // TODO: AIO Add in log rocket for promanager instances. + rome: "rome-online/rome-online" }) ); } @@ -134,8 +133,7 @@ export function App({ bodyshop, checkUserSession, currentUser, online, setOnline } @@ -144,8 +142,7 @@ export function App({ bodyshop, checkUserSession, currentUser, online, setOnline currentUser={currentUser} workspaceCode={InstanceRenderMgr({ imex: null, - rome: "9BkbEseqNqxw8jUH", - promanager: "aoJoEifvezYI0Z0P" + rome: "9BkbEseqNqxw8jUH" })} /> diff --git a/client/src/App/themeProvider.js b/client/src/App/themeProvider.js index 18bcaaa1c..5aaaef4cf 100644 --- a/client/src/App/themeProvider.js +++ b/client/src/App/themeProvider.js @@ -26,13 +26,11 @@ const defaultTheme = { token: { colorPrimary: InstanceRenderMgr({ imex: "#1890ff", - rome: "#326ade", - promanager: "#1d69a6" + rome: "#326ade" }), colorInfo: InstanceRenderMgr({ imex: "#1890ff", - rome: "#326ade", - promanager: "#1d69a6" + rome: "#326ade" }) } }; diff --git a/client/src/components/bill-form/bill-form.lines.component.jsx b/client/src/components/bill-form/bill-form.lines.component.jsx index b9576670c..ae0840cc1 100644 --- a/client/src/components/bill-form/bill-form.lines.component.jsx +++ b/client/src/components/bill-form/bill-form.lines.component.jsx @@ -228,7 +228,6 @@ export function BillEnterModalLinesComponent({ }}
) - //Do not need to set for promanager as it will default to Rome. }) }, { @@ -462,7 +461,6 @@ export function BillEnterModalLinesComponent({ ...InstanceRenderManager({ rome: [], - promanager: [], imex: [ { title: t("billlines.fields.federal_tax_applicable"), @@ -476,7 +474,6 @@ export function BillEnterModalLinesComponent({ initialValue: InstanceRenderManager({ imex: true, rome: false, - promanager: false }), name: [field.name, "applicable_taxes", "federal"] }; @@ -503,7 +500,6 @@ export function BillEnterModalLinesComponent({ ...InstanceRenderManager({ rome: [], - promanager: [], imex: [ { title: t("billlines.fields.local_tax_applicable"), diff --git a/client/src/components/conflict/conflict.component.jsx b/client/src/components/conflict/conflict.component.jsx index 659e64080..a14209f8b 100644 --- a/client/src/components/conflict/conflict.component.jsx +++ b/client/src/components/conflict/conflict.component.jsx @@ -16,8 +16,7 @@ export default function ConflictComponent() { {t("general.labels.instanceconflictext", { app: InstanceRenderManager({ imex: "$t(titles.imexonline)", - rome: "$t(titles.romeonline)", - promanager: "$t(titles.promanager)" + rome: "$t(titles.romeonline)" }) })}
diff --git a/client/src/components/error-boundary/error-boundary.component.jsx b/client/src/components/error-boundary/error-boundary.component.jsx index d4683aab3..027a3caae 100644 --- a/client/src/components/error-boundary/error-boundary.component.jsx +++ b/client/src/components/error-boundary/error-boundary.component.jsx @@ -108,8 +108,7 @@ class ErrorBoundary extends React.Component { subTitle={t("general.messages.exception", { app: InstanceRenderManager({ imex: "$t(titles.imexonline)", - rome: "$t(titles.romeonline)", - promanager: "$t(titles.promanager)" + rome: "$t(titles.romeonline)" }) })} extra={ diff --git a/client/src/components/feature-wrapper/feature-wrapper.component.jsx b/client/src/components/feature-wrapper/feature-wrapper.component.jsx index 4b71318b7..8f2336369 100644 --- a/client/src/components/feature-wrapper/feature-wrapper.component.jsx +++ b/client/src/components/feature-wrapper/feature-wrapper.component.jsx @@ -22,8 +22,7 @@ function FeatureWrapper({ bodyshop, featureName, noauth, children, ...restProps message={t("general.messages.nofeatureaccess", { app: InstanceRenderManager({ imex: "$t(titles.imexonline)", - rome: "$t(titles.romeonline)", - promanager: "$t(titles.promanager)" + rome: "$t(titles.romeonline)" }) })} type="warning" diff --git a/client/src/components/header/header.component.jsx b/client/src/components/header/header.component.jsx index 341e19ba0..6457de46d 100644 --- a/client/src/components/header/header.component.jsx +++ b/client/src/components/header/header.component.jsx @@ -130,9 +130,8 @@ function Header({ if ( InstanceRenderManager({ - imex: true, - rome: true, - promanager: HasFeatureAccess({ featureName: "bills", bodyshop }) + imex: HasFeatureAccess({ featureName: "bills", bodyshop }), + rome: "USE_IMEX" }) ) { accountingChildren.push( @@ -172,9 +171,8 @@ function Header({ } if ( InstanceRenderManager({ - imex: true, - rome: true, - promanager: HasFeatureAccess({ featureName: "payments", bodyshop }) + imex: HasFeatureAccess({ featureName: "payments", bodyshop }), + rome: "USE_IMEX" }) ) { accountingChildren.push( @@ -219,9 +217,8 @@ function Header({ if ( InstanceRenderManager({ - imex: true, - rome: true, - promanager: HasFeatureAccess({ featureName: "timetickets", bodyshop }) + imex: HasFeatureAccess({ featureName: "timetickets", bodyshop }), + rome: "USE_IMEX" }) ) { accountingChildren.push( @@ -304,9 +301,8 @@ function Header({ if ( InstanceRenderManager({ - imex: true, - rome: true, - promanager: HasFeatureAccess({ featureName: "export", bodyshop }) + imex: HasFeatureAccess({ featureName: "export", bodyshop }), + rome: "USE_IMEX" }) ) { accountingChildren.push({ @@ -386,9 +382,8 @@ function Header({ label: {t("menus.header.productionlist")} }, ...(InstanceRenderManager({ - imex: true, - rome: true, - promanager: HasFeatureAccess({ featureName: "visualboard", bodyshop }) + imex: HasFeatureAccess({ featureName: "visualboard", bodyshop }), + rome: "USE_IMEX" }) ? [ { @@ -401,9 +396,8 @@ function Header({ : []), ...(InstanceRenderManager({ - imex: true, - rome: true, - promanager: HasFeatureAccess({ featureName: "scoreboard", bodyshop }) + imex: HasFeatureAccess({ featureName: "scoreboard", bodyshop }), + rome: "USE_IMEX" }) ? [ { @@ -440,9 +434,8 @@ function Header({ ] }, ...(InstanceRenderManager({ - imex: true, - rome: true, - promanager: false // HasFeatureAccess({ featureName: 'courtesycars', bodyshop }), + imex: HasFeatureAccess({ featureName: "courtesycars", bodyshop }), + rome: "USE_IMEX" }) ? [ { @@ -492,9 +485,8 @@ function Header({ label: {t("menus.header.phonebook")} }, ...(InstanceRenderManager({ - imex: true, - rome: true, - promanager: HasFeatureAccess({ featureName: "media", bodyshop }) + imex: HasFeatureAccess({ featureName: "media", bodyshop }), + rome: "USE_IMEX" }) ? [ { @@ -571,9 +563,8 @@ function Header({ label: {t("menus.header.shop_vendors")} }, ...(InstanceRenderManager({ - imex: true, - rome: true, - promanager: HasFeatureAccess({ featureName: "csi", bodyshop }) + imex: HasFeatureAccess({ featureName: "csi", bodyshop }), + rome: "USE_IMEX" }) ? [ { @@ -607,8 +598,7 @@ function Header({ window.open( InstanceRenderManager({ imex: "https://help.imex.online/", - rome: "https://rometech.com//", - promanager: "https://web-est.com" + rome: "https://rometech.com//" }), "_blank" @@ -617,8 +607,7 @@ function Header({ }, ...(InstanceRenderManager({ imex: true, - rome: false, - promanager: false + rome: false }) ? [ { @@ -633,9 +622,8 @@ function Header({ : []), ...(InstanceRenderManager({ - imex: true, - rome: true, - promanager: HasFeatureAccess({ featureName: "timetickets", bodyshop }) + imex: HasFeatureAccess({ featureName: "timetickets", bodyshop }), + rome: "USE_IMEX" }) ? [ { diff --git a/client/src/components/job-bills-total/job-bills-total.component.jsx b/client/src/components/job-bills-total/job-bills-total.component.jsx index d38e9781e..ed123fa9c 100644 --- a/client/src/components/job-bills-total/job-bills-total.component.jsx +++ b/client/src/components/job-bills-total/job-bills-total.component.jsx @@ -98,7 +98,6 @@ export default function JobBillsTotalComponent({ InstanceRenderManager({ imex: Dinero(), rome: Dinero(totals.additional.additionalCosts), - promanager: "USE_ROME" }) ); // Additional costs were captured for Rome, but not imex. diff --git a/client/src/components/job-detail-lines/job-lines-part-price-change.component.jsx b/client/src/components/job-detail-lines/job-lines-part-price-change.component.jsx index a7548542c..34b82ade8 100644 --- a/client/src/components/job-detail-lines/job-lines-part-price-change.component.jsx +++ b/client/src/components/job-detail-lines/job-lines-part-price-change.component.jsx @@ -60,24 +60,21 @@ export function JobLinesPartPriceChange({ job, line, refetch, technician }) { } }; - const popcontent = !technician && InstanceRenderManager({ - imex: null, - rome: ( -
- - - - -
- ), - promanager: null - }); + const popcontent = + !technician && + InstanceRenderManager({ + imex: null, + rome: ( +
+ + + + +
+ ) + }); return ( diff --git a/client/src/components/job-employee-assignments/job-employee-assignments.component.jsx b/client/src/components/job-employee-assignments/job-employee-assignments.component.jsx index bfa226edb..85e037e86 100644 --- a/client/src/components/job-employee-assignments/job-employee-assignments.component.jsx +++ b/client/src/components/job-employee-assignments/job-employee-assignments.component.jsx @@ -158,8 +158,7 @@ export function JobEmployeeAssignments({ label={t( InstanceRenderManager({ imex: "jobs.fields.employee_csr", - rome: "jobs.fields.employee_csr_writer", - promanager: "USE_ROME" + rome: "jobs.fields.employee_csr_writer" }) )} > diff --git a/client/src/components/job-totals-table/job-totals.table.labor.component.jsx b/client/src/components/job-totals-table/job-totals.table.labor.component.jsx index 5725bf6ef..e643f3e7f 100644 --- a/client/src/components/job-totals-table/job-totals.table.labor.component.jsx +++ b/client/src/components/job-totals-table/job-totals.table.labor.component.jsx @@ -96,8 +96,7 @@ export default function JobTotalsTableLabor({ job }) { sortOrder: state.sortedInfo.columnKey === "total" && state.sortedInfo.order, render: (text, record) => Dinero(record.total).toFormat() } - ], - promanager: "USE_ROME" + ] }) ]; @@ -131,8 +130,7 @@ export default function JobTotalsTableLabor({ job }) { - ), - promanager: "USE_ROME" + ) })} {Dinero(job.job_totals.rates.rates_subtotal).toFormat()} @@ -185,8 +183,7 @@ export default function JobTotalsTableLabor({ job }) { {Dinero(job.job_totals.rates.mapa.total).toFormat()} - ), - promanager: "USE_ROME" + ) })} @@ -236,8 +233,7 @@ export default function JobTotalsTableLabor({ job }) { {Dinero(job.job_totals.rates.mash.total).toFormat()} - ), - promanager: "USE_ROME" + ) })} @@ -253,8 +249,7 @@ export default function JobTotalsTableLabor({ job }) { - ), - promanager: "USE_ROME" + ) })} {Dinero(job.job_totals.rates.subtotal).toFormat()} diff --git a/client/src/components/job-totals-table/job-totals.table.totals.component.jsx b/client/src/components/job-totals-table/job-totals.table.totals.component.jsx index 301fec91f..891867fbb 100644 --- a/client/src/components/job-totals-table/job-totals.table.totals.component.jsx +++ b/client/src/components/job-totals-table/job-totals.table.totals.component.jsx @@ -50,7 +50,6 @@ export function JobTotalsTableTotals({ bodyshop, job }) { total: job.job_totals.totals.federal_tax } ], - promanager: "USE_ROME", rome: job.job_totals.totals.us_sales_tax_breakdown ? [ { @@ -149,7 +148,6 @@ export function JobTotalsTableTotals({ bodyshop, job }) { } ], rome: [], - promanager: "USE_ROME" }), { key: t("jobs.fields.other_amount_payable"), diff --git a/client/src/components/jobs-admin-delete-intake/jobs-admin-delete-intake.component.jsx b/client/src/components/jobs-admin-delete-intake/jobs-admin-delete-intake.component.jsx index 70e1b9ad3..3277375a8 100644 --- a/client/src/components/jobs-admin-delete-intake/jobs-admin-delete-intake.component.jsx +++ b/client/src/components/jobs-admin-delete-intake/jobs-admin-delete-intake.component.jsx @@ -51,7 +51,6 @@ export default function JobAdminDeleteIntake({ job }) { const InstanceRender = InstanceRenderManager({ imex: true, rome: "USE_IMEX", - promanager: false }); return InstanceRender ? ( diff --git a/client/src/components/jobs-available-table/jobs-available-table.container.jsx b/client/src/components/jobs-available-table/jobs-available-table.container.jsx index d9964d090..27f76ad82 100644 --- a/client/src/components/jobs-available-table/jobs-available-table.container.jsx +++ b/client/src/components/jobs-available-table/jobs-available-table.container.jsx @@ -110,8 +110,7 @@ export function JobsAvailableContainer({ bodyshop, currentUser, insertAuditTrail InstanceRenderManager({ executeFunction: true, rome: ResolveCCCLineIssues, - args: [estData.est_data, bodyshop], - promanager: ResolveCCCLineIssues + args: [estData.est_data, bodyshop] }); // } else { @@ -121,7 +120,7 @@ export function JobsAvailableContainer({ bodyshop, currentUser, insertAuditTrail executeFunction: true, imex: CheckTaxRates, rome: CheckTaxRatesUSA, - promanager: CheckTaxRatesUSA, + args: [estData.est_data, bodyshop] }); @@ -236,7 +235,7 @@ export function JobsAvailableContainer({ bodyshop, currentUser, insertAuditTrail await InstanceRenderManager({ executeFunction: true, rome: ResolveCCCLineIssues, - promanager: ResolveCCCLineIssues, + args: [supp, bodyshop] }); @@ -244,7 +243,7 @@ export function JobsAvailableContainer({ bodyshop, currentUser, insertAuditTrail executeFunction: true, imex: CheckTaxRates, rome: CheckTaxRatesUSA, - promanager: CheckTaxRatesUSA, + args: [supp, bodyshop] }); @@ -585,14 +584,13 @@ function ResolveCCCLineIssues(estData, bodyshop) { // line.notes += ` | ET/UT Update (prev = ${line.mod_lbr_ty})`; line.mod_lbr_ty = "LAR"; } - }, - promanager: "USE_ROME" + } }); }); //Group by line no // For everything but the first one, strip out the price number in - + //TODO: How do we merge these 2 functions together and have it function properly for Rome? InstanceRenderManager({ executeFunction: true, args: [], diff --git a/client/src/components/jobs-close-auto-allocate/jobs-close-auto-allocate.component.jsx b/client/src/components/jobs-close-auto-allocate/jobs-close-auto-allocate.component.jsx index f90e75d32..16477501c 100644 --- a/client/src/components/jobs-close-auto-allocate/jobs-close-auto-allocate.component.jsx +++ b/client/src/components/jobs-close-auto-allocate/jobs-close-auto-allocate.component.jsx @@ -33,7 +33,6 @@ export function JobsCloseAutoAllocate({ bodyshop, joblines, form, disabled }) { InstanceRenderManager({ imex: !jl.part_type && !jl.mod_lbr_ty, rome: !ret.profitcenter_part, - promanager: "USE_ROME" }) ) { const lineDesc = jl.line_desc ? jl.line_desc.toLowerCase() : ""; diff --git a/client/src/components/jobs-convert-button/jobs-convert-button.component.jsx b/client/src/components/jobs-convert-button/jobs-convert-button.component.jsx index 833594604..941de644b 100644 --- a/client/src/components/jobs-convert-button/jobs-convert-button.component.jsx +++ b/client/src/components/jobs-convert-button/jobs-convert-button.component.jsx @@ -151,8 +151,7 @@ export function JobsConvertButton({ bodyshop, job, refetch, jobRO, insertAuditTr label={t( InstanceRenderManager({ imex: "jobs.fields.employee_csr", - rome: "jobs.fields.employee_csr_writer", - promanager: "USE_ROME" + rome: "jobs.fields.employee_csr_writer" }) )} rules={[ diff --git a/client/src/components/jobs-detail-header-actions/jobs-detail-header-actions.component.jsx b/client/src/components/jobs-detail-header-actions/jobs-detail-header-actions.component.jsx index c9c3b8fb7..3aca43488 100644 --- a/client/src/components/jobs-detail-header-actions/jobs-detail-header-actions.component.jsx +++ b/client/src/components/jobs-detail-header-actions/jobs-detail-header-actions.component.jsx @@ -670,48 +670,50 @@ export function JobsDetailHeaderActions({ }, ...InstanceRenderManager({ imex: [ - { - key: "intake", - id: "job-actions-intake", - disabled: !!job.intakechecklist || !jobInPreProduction || !job.converted || jobRO, - label: - !!job.intakechecklist || !jobInPreProduction || !job.converted || jobRO ? ( - t("jobs.actions.intake") - ) : ( - {t("jobs.actions.intake")} - ) - }, - { - key: "deliver", - id: "job-actions-deliver", - disabled: !jobInProduction || jobRO, - label: !jobInProduction ? ( - t("jobs.actions.deliver") - ) : ( - {t("jobs.actions.deliver")} - ) - }, - { - key: "checklist", - id: "job-actions-checklist", - disabled: !job.converted, - label: {t("jobs.actions.viewchecklist")} - } + ...(HasFeatureAccess({ featureName: "checklist", bodyshop }) + ? [ + { + key: "intake", + id: "job-actions-intake", + disabled: !!job.intakechecklist || !jobInPreProduction || !job.converted || jobRO, + label: + !!job.intakechecklist || !jobInPreProduction || !job.converted || jobRO ? ( + t("jobs.actions.intake") + ) : ( + {t("jobs.actions.intake")} + ) + }, + { + key: "deliver", + id: "job-actions-deliver", + disabled: !jobInProduction || jobRO, + label: !jobInProduction ? ( + t("jobs.actions.deliver") + ) : ( + {t("jobs.actions.deliver")} + ) + }, + { + key: "checklist", + id: "job-actions-checklist", + disabled: !job.converted, + label: {t("jobs.actions.viewchecklist")} + } + ] + : [ + { + key: "toggleproduction", + id: "job-actions-toggleproduction", + disabled: !job.converted || jobRO, + label: + } + ]) ], - rome: "USE_IMEX", - promanager: [ - { - key: "toggleproduction", - id: "job-actions-toggleproduction", - disabled: !job.converted || jobRO, - label: - } - ] + rome: "USE_IMEX" }), ...(InstanceRenderManager({ - imex: true, - rome: "USE_IMEX", - promanager: HasFeatureAccess({ featureName: "timetickets", bodyshop }) + imex: HasFeatureAccess({ featureName: "timetickets", bodyshop }), + rome: "USE_IMEX" }) ? [ { @@ -881,9 +883,8 @@ export function JobsDetailHeaderActions({ ] }, ...(InstanceRenderManager({ - imex: true, - rome: true, - promanager: HasFeatureAccess({ featureName: "bills", bodyshop }) + imex: HasFeatureAccess({ featureName: "bills", bodyshop }), + rome: "USE_IMEX" }) ? [ { @@ -964,9 +965,8 @@ export function JobsDetailHeaderActions({ if ( InstanceRenderManager({ - imex: true, - rome: true, - promanager: HasFeatureAccess({ featureName: "export", bodyshop }) + imex: HasFeatureAccess({ featureName: "export", bodyshop }), + rome: "USE_IMEX" }) ) { menuItems.push({ diff --git a/client/src/components/jobs-detail-rates/jobs-detail-rates.component.jsx b/client/src/components/jobs-detail-rates/jobs-detail-rates.component.jsx index f056f603d..98a76f7b5 100644 --- a/client/src/components/jobs-detail-rates/jobs-detail-rates.component.jsx +++ b/client/src/components/jobs-detail-rates/jobs-detail-rates.component.jsx @@ -194,8 +194,7 @@ export function JobsDetailRates({ jobRO, form, job, bodyshop }) { - ), - promanager: "USE_ROME" + ) })}
); diff --git a/client/src/components/jobs-detail-rates/jobs-detail-rates.parts.component.jsx b/client/src/components/jobs-detail-rates/jobs-detail-rates.parts.component.jsx index 825958cfb..d4d39c6a2 100644 --- a/client/src/components/jobs-detail-rates/jobs-detail-rates.parts.component.jsx +++ b/client/src/components/jobs-detail-rates/jobs-detail-rates.parts.component.jsx @@ -989,7 +989,7 @@ export function JobsDetailRatesParts({ jobRO, expanded, required = true, form }) - {InstanceRenderManager({ imex: true, rome: false, promanager: "USE_ROME" }) ? ( + {InstanceRenderManager({ imex: true, rome: false }) ? ( <> @@ -1002,7 +1002,7 @@ export function JobsDetailRatesParts({ jobRO, expanded, required = true, form }) - {InstanceRenderManager({ imex: true, rome: false, promanager: "USE_ROME" }) ? ( + {InstanceRenderManager({ imex: true, rome: false }) ? ( diff --git a/client/src/components/production-board-kanban/settings/defaultKanbanSettings.js b/client/src/components/production-board-kanban/settings/defaultKanbanSettings.js index c9a8c59c6..ff48e00ba 100644 --- a/client/src/components/production-board-kanban/settings/defaultKanbanSettings.js +++ b/client/src/components/production-board-kanban/settings/defaultKanbanSettings.js @@ -12,8 +12,7 @@ const statisticsItems = [ name: "totalHrsOnBoard", label: InstanceRenderManager({ imex: "total_hours_in_view", - rome: "total_hours_on_board", - promanager: "total_hours_on_board" + rome: "total_hours_on_board" }) }, { @@ -21,8 +20,7 @@ const statisticsItems = [ name: "totalAmountOnBoard", label: InstanceRenderManager({ imex: "total_amount_in_view", - rome: "total_amount_on_board", - promanager: "total_amount_on_board" + rome: "total_amount_on_board" }) }, { @@ -30,8 +28,7 @@ const statisticsItems = [ name: "totalLABOnBoard", label: InstanceRenderManager({ imex: "total_lab_in_view", - rome: "total_lab_on_board", - promanager: "total_lab_on_board" + rome: "total_lab_on_board" }) }, { @@ -39,8 +36,7 @@ const statisticsItems = [ name: "totalLAROnBoard", label: InstanceRenderManager({ imex: "total_lar_in_view", - rome: "total_lar_on_board", - promanager: "total_lar_on_board" + rome: "total_lar_on_board" }) }, { @@ -48,8 +44,7 @@ const statisticsItems = [ name: "jobsOnBoard", label: InstanceRenderManager({ imex: "total_jobs_in_view", - rome: "total_jobs_on_board", - promanager: "total_jobs_on_board" + rome: "total_jobs_on_board" }) }, { @@ -57,8 +52,7 @@ const statisticsItems = [ name: "tasksOnBoard", label: InstanceRenderManager({ imex: "tasks_in_view", - rome: "tasks_on_board", - promanager: "tasks_on_board" + rome: "tasks_on_board" }) }, { id: 11, name: "tasksInProduction", label: "tasks_in_production" } diff --git a/client/src/components/production-list-columns/production-list-columns.data.jsx b/client/src/components/production-list-columns/production-list-columns.data.jsx index 950d956af..d120e6ce2 100644 --- a/client/src/components/production-list-columns/production-list-columns.data.jsx +++ b/client/src/components/production-list-columns/production-list-columns.data.jsx @@ -466,8 +466,7 @@ const r = ({ technician, state, activeStatuses, data, bodyshop, refetch, treatme title: i18n.t( InstanceRenderManager({ imex: "jobs.fields.employee_csr", - rome: "jobs.fields.employee_csr_writer", - promanager: "USE_ROME" + rome: "jobs.fields.employee_csr_writer" }) ), dataIndex: "employee_csr", diff --git a/client/src/components/schedule-calendar-wrapper/schedule-calendar-header.component.jsx b/client/src/components/schedule-calendar-wrapper/schedule-calendar-header.component.jsx index 9a83f7cae..c77cd9ce6 100644 --- a/client/src/components/schedule-calendar-wrapper/schedule-calendar-header.component.jsx +++ b/client/src/components/schedule-calendar-wrapper/schedule-calendar-header.component.jsx @@ -17,6 +17,7 @@ import OwnerNameDisplay from "../owner-name-display/owner-name-display.component import ScheduleBlockDay from "../schedule-block-day/schedule-block-day.component"; import ScheduleCalendarHeaderGraph from "./schedule-calendar-header-graph.component"; import InstanceRenderMgr from "../../utils/instanceRenderMgr"; +import { HasFeatureAccess } from "../feature-wrapper/feature-wrapper.component"; const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop, @@ -60,8 +61,7 @@ export function ScheduleCalendarHeaderComponent({ loadData.allJobsOut.map((j) => ( - {j.ro_number} ( - {j.status}) + {j.ro_number} ({j.status}) @@ -69,23 +69,18 @@ export function ScheduleCalendarHeaderComponent({ {`(${j.labhrs?.aggregate?.sum?.mod_lb_hrs?.toFixed(1) || 0}/${ j.larhrs?.aggregate?.sum?.mod_lb_hrs?.toFixed(1) || 0 - }/${( - j.labhrs.aggregate?.sum?.mod_lb_hrs + - j.larhrs.aggregate?.sum?.mod_lb_hrs - ).toFixed(1)} ${t("general.labels.hours")})`} + }/${(j.labhrs.aggregate?.sum?.mod_lb_hrs + j.larhrs.aggregate?.sum?.mod_lb_hrs).toFixed( + 1 + )} ${t("general.labels.hours")})`} - - {j.scheduled_completion} - + {j.scheduled_completion} )) ) : ( - - {t("appointments.labels.nocompletingjobs")} - + {t("appointments.labels.nocompletingjobs")} )} @@ -109,10 +104,9 @@ export function ScheduleCalendarHeaderComponent({ {`(${j.labhrs?.aggregate?.sum.mod_lb_hrs?.toFixed(1) || 0}/${ j.larhrs?.aggregate?.sum?.mod_lb_hrs?.toFixed(1) || 0 - }/${( - j.labhrs?.aggregate?.sum?.mod_lb_hrs + - j.larhrs?.aggregate?.sum?.mod_lb_hrs - ).toFixed(1)} ${t("general.labels.hours")})`} + }/${(j.labhrs?.aggregate?.sum?.mod_lb_hrs + j.larhrs?.aggregate?.sum?.mod_lb_hrs).toFixed( + 1 + )} ${t("general.labels.hours")})`} {j.scheduled_in} @@ -121,9 +115,7 @@ export function ScheduleCalendarHeaderComponent({ )) ) : ( - - {t("appointments.labels.noarrivingjobs")} - + {t("appointments.labels.noarrivingjobs")} )} @@ -133,33 +125,30 @@ export function ScheduleCalendarHeaderComponent({ const LoadComponent = loadData ? (
- - - - {(loadData.allHoursInBody || 0) && - loadData.allHoursInBody.toFixed(1)} - / - {(loadData.allHoursInRefinish || 0) && - loadData.allHoursInRefinish.toFixed(1)} - /{(loadData.allHoursIn || 0) && loadData.allHoursIn.toFixed(1)} - - - - {(loadData.allHoursOut || 0) && loadData.allHoursOut.toFixed(1)} - - - - + + + + {(loadData.allHoursInBody || 0) && loadData.allHoursInBody.toFixed(1)}/ + {(loadData.allHoursInRefinish || 0) && loadData.allHoursInRefinish.toFixed(1)}/ + {(loadData.allHoursIn || 0) && loadData.allHoursIn.toFixed(1)} + + + + {(loadData.allHoursOut || 0) && loadData.allHoursOut.toFixed(1)} + + + +
    {Object.keys(ATSToday).map((key, idx) => ( @@ -208,9 +197,16 @@ export function ScheduleCalendarHeaderComponent({
    {label} {InstanceRenderMgr({ - imex: calculating ? : LoadComponent, - rome: "USE_IMEX", - promanager: <> + imex: HasFeatureAccess({ featureName: "smartscheduling", bodyshop }) ? ( + calculating ? ( + + ) : ( + LoadComponent + ) + ) : ( + <> + ), + rome: "USE_IMEX" })}
    diff --git a/client/src/components/schedule-calendar-wrapper/scheduler-calendar-wrapper.component.jsx b/client/src/components/schedule-calendar-wrapper/scheduler-calendar-wrapper.component.jsx index 4d6f8fe78..50cbdd8de 100644 --- a/client/src/components/schedule-calendar-wrapper/scheduler-calendar-wrapper.component.jsx +++ b/client/src/components/schedule-calendar-wrapper/scheduler-calendar-wrapper.component.jsx @@ -15,6 +15,7 @@ import { Alert, Collapse, Space } from "antd"; import { Trans, useTranslation } from "react-i18next"; import InstanceRenderManager from "../../utils/instanceRenderMgr"; import local from "./localizer"; +import { HasFeatureAccess } from "../feature-wrapper/feature-wrapper.component"; const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop, @@ -54,58 +55,58 @@ export function ScheduleCalendarWrapperComponent({ return ( <> - {InstanceRenderManager({ - imex: - problemJobs && problemJobs.length > 2 ? ( - - {t("appointments.labels.severalerrorsfound")}} - > - - {problemJobs.map((problem) => ( - ]} - values={{ - ro_number: problem.ro_number, - code: problem.code - }} - /> - } - /> - ))} - - - - ) : ( - - {problemJobs.map((problem) => ( - ]} - values={{ - ro_number: problem.ro_number, - code: problem.code - }} - /> - } - /> - ))} - - ), + {HasFeatureAccess({ featureName: "smartscheduling", bodyshop }) && + InstanceRenderManager({ + imex: + problemJobs && problemJobs.length > 2 ? ( + + {t("appointments.labels.severalerrorsfound")}} + > + + {problemJobs.map((problem) => ( + ]} + values={{ + ro_number: problem.ro_number, + code: problem.code + }} + /> + } + /> + ))} + + + + ) : ( + + {problemJobs.map((problem) => ( + ]} + values={{ + ro_number: problem.ro_number, + code: problem.code + }} + /> + } + /> + ))} + + ), - rome: "USE_IMEX", - promanager: - })} + rome: "USE_IMEX" + })} - {InstanceRenderManager({ - imex: ( - <> - {t("appointments.labels.smartscheduling")} - - + {smartOptions.map((d, idx) => ( + - {smartOptions.map((d, idx) => ( - - ))} - - - ), - rome: "USE_IMEX", - promanager: <> - })} - + ))} + + + )} + , diff --git a/client/src/components/shop-info/shop-info.component.jsx b/client/src/components/shop-info/shop-info.component.jsx index fe09d2220..4903348ca 100644 --- a/client/src/components/shop-info/shop-info.component.jsx +++ b/client/src/components/shop-info/shop-info.component.jsx @@ -21,6 +21,7 @@ import queryString from "query-string"; import InstanceRenderManager from "../../utils/instanceRenderMgr"; import ShopInfoRoGuard from "./shop-info.roguard.component"; import ShopInfoIntellipay from "./shop-intellipay-config.component"; +import { HasFeatureAccess } from "../feature-wrapper/feature-wrapper.component"; const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop @@ -87,18 +88,16 @@ export function ShopInfoComponent({ bodyshop, form, saveLoading }) { children: , id: "tab-shop-responsibilitycenters" }, - ...InstanceRenderManager({ - imex: [ - { - key: "checklists", - label: t("bodyshop.labels.checklists"), - children: , - id: "tab-shop-checklists" - } - ], - rome: "USE_IMEX", - promanager: [] - }), + ...(HasFeatureAccess({ featureName: "checklists", bodyshop }) + ? [ + { + key: "checklists", + label: t("bodyshop.labels.checklists"), + children: , + id: "tab-shop-checklists" + } + ] + : []), { key: "laborrates", label: t("bodyshop.labels.laborrates"), @@ -125,29 +124,22 @@ export function ShopInfoComponent({ bodyshop, form, saveLoading }) { } ] : []), - ...InstanceRenderManager({ - imex: [ - { - key: "roguard", - label: t("bodyshop.labels.roguard.title"), - children: , - id: "tab-shop-roguard" - } - ], - rome: "USE_IMEX", - promanager: [] - }), - ...InstanceRenderManager({ - imex: [], - rome: [ - { - key: "intellipay", - label: InstanceRenderManager({ rome: t("bodyshop.labels.romepay"), imex: t("bodyshop.labels.imexpay") }), - children: - } - ], - promanager: [] - }) + ...(HasFeatureAccess({ featureName: "roguard", bodyshop }) + ? [ + { + key: "roguard", + label: t("bodyshop.labels.roguard.title"), + children: , + id: "tab-shop-roguard" + } + ] + : []), + + { + key: "intellipay", + label: InstanceRenderManager({ rome: t("bodyshop.labels.romepay"), imex: t("bodyshop.labels.imexpay") }), + children: + } ]; return ( - ), - promanager: "USE_ROME" + ) })} {/**/} diff --git a/client/src/components/shop-info/shop-info.responsibilitycenters.taxes.component.jsx b/client/src/components/shop-info/shop-info.responsibilitycenters.taxes.component.jsx index b587deb5a..de3832311 100644 --- a/client/src/components/shop-info/shop-info.responsibilitycenters.taxes.component.jsx +++ b/client/src/components/shop-info/shop-info.responsibilitycenters.taxes.component.jsx @@ -2034,7 +2034,7 @@ export function ShopInfoResponsibilityCenters({ bodyshop, form }) { - {InstanceRenderManager({ imex: true, rome: false, promanager: "USE_ROME" }) ? ( + {InstanceRenderManager({ imex: true, rome: false }) ? ( <> - {InstanceRenderManager({ imex: true, rome: false, promanager: "USE_ROME" }) ? ( + {InstanceRenderManager({ imex: true, rome: false }) ? ( diff --git a/client/src/components/shop-info/shop-info.scheduling.component.jsx b/client/src/components/shop-info/shop-info.scheduling.component.jsx index b441db818..36fd0e6d1 100644 --- a/client/src/components/shop-info/shop-info.scheduling.component.jsx +++ b/client/src/components/shop-info/shop-info.scheduling.component.jsx @@ -2,13 +2,23 @@ import { DeleteFilled } from "@ant-design/icons"; import { Button, Divider, Form, Input, InputNumber, Select, Space, Switch, TimePicker } from "antd"; import React from "react"; import { useTranslation } from "react-i18next"; +import { HasFeatureAccess } from "../feature-wrapper/feature-wrapper.component"; import ColorpickerFormItemComponent from "../form-items-formatted/colorpicker-form-item.component"; import FormListMoveArrows from "../form-list-move-arrows/form-list-move-arrows.component"; import LayoutFormRow from "../layout-form-row/layout-form-row.component"; import { ColorPicker } from "./shop-info.rostatus.component"; -import InstanceRenderManager from "../../utils/instanceRenderMgr"; -export default function ShopInfoSchedulingComponent({ form }) { +import { connect } from "react-redux"; +import { createStructuredSelector } from "reselect"; +import { selectBodyshop } from "../../redux/user/user.selectors"; +const mapStateToProps = createStructuredSelector({ + bodyshop: selectBodyshop +}); +const mapDispatchToProps = (dispatch) => ({ + //setUserLanguage: language => dispatch(setUserLanguage(language)) +}); + +export function ShopInfoSchedulingComponent({ form, bodyshop }) { const { t } = useTranslation(); return ( @@ -167,138 +177,136 @@ export default function ShopInfoSchedulingComponent({ form }) { }} - {InstanceRenderManager({ - imex: ( - - - {(fields, { add, remove, move }) => { - return ( -
    - {fields.map((field, index) => ( - - - - - - - - + {HasFeatureAccess({ featureName: "smartscheduling", bodyshop }) && ( + + + {(fields, { add, remove, move }) => { + return ( +
    + {fields.map((field, index) => ( + + + + + + + + + + + + + + + + + + + + + + {t("bodyshop.fields.ssbuckets.color")} + + + } + key={`${index}color`} + name={[field.name, "color"]} > - + - - - - - - - - - - - - {t("bodyshop.fields.ssbuckets.color")} - - - } - key={`${index}color`} - name={[field.name, "color"]} - > - - - - { - remove(field.name); - }} - /> - - + + { + remove(field.name); + }} + /> + - - - ))} - - + + -
    - ); - }} -
    -
    - ), - rome: "USE_IMEX", - promanager: null - })} + ))} + + + +
    + ); + }} +
    +
    + )}
); } + +export default connect(mapStateToProps, mapDispatchToProps)(ShopInfoSchedulingComponent); diff --git a/client/src/components/sign-in-form/sign-in-form.component.jsx b/client/src/components/sign-in-form/sign-in-form.component.jsx index 0319cff6a..d39128af4 100644 --- a/client/src/components/sign-in-form/sign-in-form.component.jsx +++ b/client/src/components/sign-in-form/sign-in-form.component.jsx @@ -8,10 +8,9 @@ import { Link, useLocation, useNavigate } from "react-router-dom"; import { createStructuredSelector } from "reselect"; import RomeLogo from "../../assets/RomeOnlineBlue.png"; import ImEXOnlineLogo from "../../assets/logo192.png"; -import ProManagerLogo from "../../assets/promanager/ProManagerLogo.gif"; -import InstanceRenderManager from "../../utils/instanceRenderMgr"; import { emailSignInStart, sendPasswordReset } from "../../redux/user/user.actions"; import { selectCurrentUser, selectLoginLoading, selectSignInError } from "../../redux/user/user.selectors"; +import InstanceRenderManager from "../../utils/instanceRenderMgr"; import AlertComponent from "../alert/alert.component"; import "./sign-in-form.styles.scss"; @@ -49,21 +48,18 @@ export function SignInComponent({ emailSignInStart, currentUser, signInError, se {InstanceRenderManager({ {InstanceRenderManager({ imex: t("titles.imexonline"), - rome: t("titles.romeonline"), - promanager: null + rome: t("titles.romeonline") })}
diff --git a/client/src/components/tech-login/tech-login.component.jsx b/client/src/components/tech-login/tech-login.component.jsx index 4ebcc34e4..da3ad7b32 100644 --- a/client/src/components/tech-login/tech-login.component.jsx +++ b/client/src/components/tech-login/tech-login.component.jsx @@ -37,8 +37,7 @@ export function TechLogin({ technician, loginError, loginLoading, techLoginStart document.title = t("titles.techconsole", { app: InstanceRenderManager({ imex: "$t(titles.imexonline)", - rome: "$t(titles.romeonline)", - promanager: "$t(titles.promanager)" + rome: "$t(titles.romeonline)" }) }); }, [t]); diff --git a/client/src/components/update-alert/update-alert.component.jsx b/client/src/components/update-alert/update-alert.component.jsx index 32f80ea79..1f525a479 100644 --- a/client/src/components/update-alert/update-alert.component.jsx +++ b/client/src/components/update-alert/update-alert.component.jsx @@ -76,8 +76,7 @@ export function UpdateAlert({ updateAvailable }) { time: (timeLeft / 1000).toFixed(0), app: InstanceRenderManager({ imex: "$t(titles.imexonline)", - rome: "$t(titles.romeonline)", - promanager: "$t(titles.promanager)" + rome: "$t(titles.romeonline)" }) }), placement: "bottomRight" @@ -95,8 +94,7 @@ export function UpdateAlert({ updateAvailable }) { message={t("general.messages.newversiontitle", { app: InstanceRenderManager({ imex: "$t(titles.imexonline)", - rome: "$t(titles.romeonline)", - promanager: "$t(titles.promanager)" + rome: "$t(titles.romeonline)" }) })} showIcon @@ -107,8 +105,7 @@ export function UpdateAlert({ updateAvailable }) { {t("general.messages.newversionmessage", { app: InstanceRenderManager({ imex: "$t(titles.imexonline)", - rome: "$t(titles.romeonline)", - promanager: "$t(titles.promanager)" + rome: "$t(titles.romeonline)" }) })} diff --git a/client/src/components/user-request-pw-reset/user-request-reset-pw.component.jsx b/client/src/components/user-request-pw-reset/user-request-reset-pw.component.jsx index ce888ed64..38abe4936 100644 --- a/client/src/components/user-request-pw-reset/user-request-reset-pw.component.jsx +++ b/client/src/components/user-request-pw-reset/user-request-reset-pw.component.jsx @@ -55,15 +55,13 @@ export function UserRequestResetPw({ passwordReset, sendPasswordReset, sendPassw width="100" alt={InstanceRenderManager({ imex: t("titles.imexonline"), - rome: t("titles.romeonline"), - promanager: t("titles.promanager") + rome: t("titles.romeonline") })} /> {InstanceRenderManager({ imex: t("titles.imexonline"), - rome: t("titles.romeonline"), - promanager: t("titles.promanager") + rome: t("titles.romeonline") })}
diff --git a/client/src/components/user-validate-pw-reset/user-validate-pw-reset.component.jsx b/client/src/components/user-validate-pw-reset/user-validate-pw-reset.component.jsx index 4ea899d01..9512a5668 100644 --- a/client/src/components/user-validate-pw-reset/user-validate-pw-reset.component.jsx +++ b/client/src/components/user-validate-pw-reset/user-validate-pw-reset.component.jsx @@ -75,16 +75,14 @@ export function UserValidatePwReset({ passwordReset, validatePasswordReset, oobC width={100} alt={InstanceRenderManager({ imex: t("titles.imexonline"), - rome: t("titles.romeonline"), - promanager: t("titles.promanager") + rome: t("titles.romeonline") })} /> {InstanceRenderManager({ imex: t("titles.imexonline"), - rome: t("titles.romeonline"), - promanager: t("titles.promanager") + rome: t("titles.romeonline") })} diff --git a/client/src/index.jsx b/client/src/index.jsx index a5a4149cb..9f864272f 100644 --- a/client/src/index.jsx +++ b/client/src/index.jsx @@ -31,8 +31,7 @@ if (import.meta.env.PROD) { Sentry.init({ dsn: InstanceRenderManager({ imex: "https://fd7e89369b6b4bdc9c6c4c9f22fa4ee4@o492140.ingest.sentry.io/5651027", - rome: "https://a6acc91c073e414196014b8484627a61@o492140.ingest.sentry.io/4504561071161344", - promanager: "" //TODO:AIO Add in the sentry tracker for proman. + rome: "https://a6acc91c073e414196014b8484627a61@o492140.ingest.sentry.io/4504561071161344" //TODO:AIO Add in the sentry tracker for proman. }), ignoreErrors: [ diff --git a/client/src/pages/accounting-payables/accounting-payables.container.jsx b/client/src/pages/accounting-payables/accounting-payables.container.jsx index 1055b21af..0a9e53ba8 100644 --- a/client/src/pages/accounting-payables/accounting-payables.container.jsx +++ b/client/src/pages/accounting-payables/accounting-payables.container.jsx @@ -31,8 +31,7 @@ export function AccountingPayablesContainer({ bodyshop, setBreadcrumbs, setSelec document.title = t("titles.accounting-payables", { app: InstanceRenderManager({ imex: "$t(titles.imexonline)", - rome: "$t(titles.romeonline)", - promanager: "$t(titles.promanager)" + rome: "$t(titles.romeonline)" }) }); setSelectedHeader("payables"); diff --git a/client/src/pages/accounting-payments/accounting-payments.container.jsx b/client/src/pages/accounting-payments/accounting-payments.container.jsx index 77c6157fa..b89c05a09 100644 --- a/client/src/pages/accounting-payments/accounting-payments.container.jsx +++ b/client/src/pages/accounting-payments/accounting-payments.container.jsx @@ -31,8 +31,7 @@ export function AccountingPaymentsContainer({ bodyshop, setBreadcrumbs, setSelec document.title = t("titles.accounting-payments", { app: InstanceRenderManager({ imex: "$t(titles.imexonline)", - rome: "$t(titles.romeonline)", - promanager: "$t(titles.promanager)" + rome: "$t(titles.romeonline)" }) }); setSelectedHeader("payments"); diff --git a/client/src/pages/accounting-receivables/accounting-receivables.container.jsx b/client/src/pages/accounting-receivables/accounting-receivables.container.jsx index e1485a3a9..67f70837c 100644 --- a/client/src/pages/accounting-receivables/accounting-receivables.container.jsx +++ b/client/src/pages/accounting-receivables/accounting-receivables.container.jsx @@ -31,8 +31,7 @@ export function AccountingReceivablesContainer({ bodyshop, setBreadcrumbs, setSe document.title = t("titles.accounting-receivables", { app: InstanceRenderManager({ imex: "$t(titles.imexonline)", - rome: "$t(titles.romeonline)", - promanager: "$t(titles.promanager)" + rome: "$t(titles.romeonline)" }) }); setSelectedHeader("receivables"); diff --git a/client/src/pages/bills/bills.page.container.jsx b/client/src/pages/bills/bills.page.container.jsx index bf2dde4d5..fe4a6d26c 100644 --- a/client/src/pages/bills/bills.page.container.jsx +++ b/client/src/pages/bills/bills.page.container.jsx @@ -28,8 +28,7 @@ export function BillsPageContainer({ setBreadcrumbs, setSelectedHeader }) { document.title = t("titles.bills-list", { app: InstanceRenderManager({ imex: "$t(titles.imexonline)", - rome: "$t(titles.romeonline)", - promanager: "$t(titles.promanager)" + rome: "$t(titles.romeonline)" }) }); setSelectedHeader("bills"); diff --git a/client/src/pages/contract-create/contract-create.page.container.jsx b/client/src/pages/contract-create/contract-create.page.container.jsx index 7487780ab..57b06a7aa 100644 --- a/client/src/pages/contract-create/contract-create.page.container.jsx +++ b/client/src/pages/contract-create/contract-create.page.container.jsx @@ -5,14 +5,14 @@ import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; import { useLocation, useNavigate } from "react-router-dom"; import { createStructuredSelector } from "reselect"; +import FeatureWrapperComponent from "../../components/feature-wrapper/feature-wrapper.component"; import RbacWrapper from "../../components/rbac-wrapper/rbac-wrapper.component"; import { INSERT_NEW_CONTRACT } from "../../graphql/cccontracts.queries"; import { UPDATE_JOB } from "../../graphql/jobs.queries"; import { setBreadcrumbs, setSelectedHeader } from "../../redux/application/application.actions"; import { selectBodyshop } from "../../redux/user/user.selectors"; -import ContractCreatePageComponent from "./contract-create.page.component"; import InstanceRenderManager from "../../utils/instanceRenderMgr"; -import FeatureWrapperComponent from "../../components/feature-wrapper/feature-wrapper.component"; +import ContractCreatePageComponent from "./contract-create.page.component"; const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop @@ -102,8 +102,7 @@ export function ContractCreatePageContainer({ bodyshop, setBreadcrumbs, setSelec document.title = t("titles.contracts-create", { app: InstanceRenderManager({ imex: "$t(titles.imexonline)", - rome: "$t(titles.romeonline)", - promanager: "$t(titles.promanager)" + rome: "$t(titles.romeonline)" }) }); setSelectedHeader("newcontract"); diff --git a/client/src/pages/contract-detail/contract-detail.page.container.jsx b/client/src/pages/contract-detail/contract-detail.page.container.jsx index 4b6bd8d84..d4234f76d 100644 --- a/client/src/pages/contract-detail/contract-detail.page.container.jsx +++ b/client/src/pages/contract-detail/contract-detail.page.container.jsx @@ -41,14 +41,12 @@ export function ContractDetailPageContainer({ setBreadcrumbs, addRecentItem, set document.title = loading ? InstanceRenderManager({ imex: t("titles.imexonline"), - rome: t("titles.romeonline"), - promanager: t("titles.promanager") + rome: t("titles.romeonline") }) : error ? InstanceRenderManager({ imex: t("titles.imexonline"), - rome: t("titles.romeonline"), - promanager: t("titles.promanager") + rome: t("titles.romeonline") }) : t("titles.contracts-detail", { id: (data && data.cccontracts_by_pk && data.cccontracts_by_pk.agreementnumber) || "" diff --git a/client/src/pages/contracts/contracts.page.container.jsx b/client/src/pages/contracts/contracts.page.container.jsx index 4653f654d..9865220d1 100644 --- a/client/src/pages/contracts/contracts.page.container.jsx +++ b/client/src/pages/contracts/contracts.page.container.jsx @@ -41,8 +41,7 @@ export function ContractsPageContainer({ setBreadcrumbs, setSelectedHeader }) { document.title = t("titles.contracts", { app: InstanceRenderManager({ imex: "$t(titles.imexonline)", - rome: "$t(titles.romeonline)", - promanager: "$t(titles.promanager)" + rome: "$t(titles.romeonline)" }) }); setSelectedHeader("contracts"); diff --git a/client/src/pages/courtesy-car-create/courtesy-car-create.page.container.jsx b/client/src/pages/courtesy-car-create/courtesy-car-create.page.container.jsx index 105d001c2..9d85dc62a 100644 --- a/client/src/pages/courtesy-car-create/courtesy-car-create.page.container.jsx +++ b/client/src/pages/courtesy-car-create/courtesy-car-create.page.container.jsx @@ -55,8 +55,7 @@ export function CourtesyCarCreateContainer({ bodyshop, setBreadcrumbs, setSelect document.title = t("titles.courtesycars-create", { app: InstanceRenderManager({ imex: "$t(titles.imexonline)", - rome: "$t(titles.romeonline)", - promanager: "$t(titles.promanager)" + rome: "$t(titles.romeonline)" }) }); setBreadcrumbs([ @@ -72,11 +71,7 @@ export function CourtesyCarCreateContainer({ bodyshop, setBreadcrumbs, setSelect
- +
diff --git a/client/src/pages/courtesy-car-detail/courtesy-car-detail.page.container.jsx b/client/src/pages/courtesy-car-detail/courtesy-car-detail.page.container.jsx index 8fc7efe6b..5fd1dc4b0 100644 --- a/client/src/pages/courtesy-car-detail/courtesy-car-detail.page.container.jsx +++ b/client/src/pages/courtesy-car-detail/courtesy-car-detail.page.container.jsx @@ -54,20 +54,17 @@ export function CourtesyCarDetailPageContainer({ setBreadcrumbs, addRecentItem, document.title = loading ? InstanceRenderManager({ imex: t("titles.imexonline"), - rome: t("titles.romeonline"), - promanager: t("titles.promanager") + rome: t("titles.romeonline") }) : error ? InstanceRenderManager({ imex: t("titles.imexonline"), - rome: t("titles.romeonline"), - promanager: t("titles.promanager") + rome: t("titles.romeonline") }) : t("titles.courtesycars-detail", { app: InstanceRenderManager({ imex: "$t(titles.imexonline)", - rome: "$t(titles.romeonline)", - promanager: "$t(titles.promanager)" + rome: "$t(titles.romeonline)" }), id: (data && data.courtesycars_by_pk && data.courtesycars_by_pk.fleet_number) || "" }); diff --git a/client/src/pages/courtesy-cars/courtesy-cars.page.container.jsx b/client/src/pages/courtesy-cars/courtesy-cars.page.container.jsx index 607242570..953bf952e 100644 --- a/client/src/pages/courtesy-cars/courtesy-cars.page.container.jsx +++ b/client/src/pages/courtesy-cars/courtesy-cars.page.container.jsx @@ -25,8 +25,7 @@ export function CourtesyCarsPageContainer({ setBreadcrumbs, setSelectedHeader }) document.title = t("titles.courtesycars", { app: InstanceRenderManager({ imex: "$t(titles.imexonline)", - rome: "$t(titles.romeonline)", - promanager: "$t(titles.promanager)" + rome: "$t(titles.romeonline)" }) }); setSelectedHeader("courtesycarsall"); diff --git a/client/src/pages/csi/csi.container.page.jsx b/client/src/pages/csi/csi.container.page.jsx index 7e4857d1b..e3240ad38 100644 --- a/client/src/pages/csi/csi.container.page.jsx +++ b/client/src/pages/csi/csi.container.page.jsx @@ -70,15 +70,13 @@ export function CsiContainerPage({ currentUser }) { title={t("csi.labels.nologgedinuser", { app: InstanceRenderManager({ imex: "$t(titles.imexonline)", - rome: "$t(titles.romeonline)", - promanager: "$t(titles.promanager)" + rome: "$t(titles.romeonline)" }) })} subTitle={t("csi.labels.nologgedinuser_sub", { app: InstanceRenderManager({ imex: "$t(titles.imexonline)", - rome: "$t(titles.romeonline)", - promanager: "$t(titles.promanager)" + rome: "$t(titles.romeonline)" }) })} /> diff --git a/client/src/pages/dashboard/dashboard.container.jsx b/client/src/pages/dashboard/dashboard.container.jsx index 6094d678d..b608019ad 100644 --- a/client/src/pages/dashboard/dashboard.container.jsx +++ b/client/src/pages/dashboard/dashboard.container.jsx @@ -19,8 +19,7 @@ export function ExportsLogPageContainer({ setBreadcrumbs, setSelectedHeader }) { document.title = t("titles.dashboard", { app: InstanceRenderManager({ imex: "$t(titles.imexonline)", - rome: "$t(titles.romeonline)", - promanager: "$t(titles.promanager)" + rome: "$t(titles.romeonline)" }) }); setSelectedHeader("dashboard"); diff --git a/client/src/pages/disclaimer/disclaimer.page.jsx b/client/src/pages/disclaimer/disclaimer.page.jsx index c6315e3d4..14593ac4d 100644 --- a/client/src/pages/disclaimer/disclaimer.page.jsx +++ b/client/src/pages/disclaimer/disclaimer.page.jsx @@ -9,9 +9,8 @@ export default function AboutPage() {
{`${InstanceRenderMgr({ imex: t("titles.imexonline"), - rome: t("titles.romeonline"), - promanager: t("titles.promanager") - })}Rome Online V.${import.meta.env.MODE}-${import.meta.env.VITE_APP_GIT_SHA}`} + rome: t("titles.romeonline") + })} V.${import.meta.env.MODE}-${import.meta.env.VITE_APP_GIT_SHA}`} Third Party Notices Application diff --git a/client/src/pages/dms-payables/dms-payables.container.jsx b/client/src/pages/dms-payables/dms-payables.container.jsx index 4fa92b9fb..21fd0f19e 100644 --- a/client/src/pages/dms-payables/dms-payables.container.jsx +++ b/client/src/pages/dms-payables/dms-payables.container.jsx @@ -46,8 +46,7 @@ export function DmsContainer({ bodyshop, setBreadcrumbs, setSelectedHeader }) { document.title = t("titles.dms", { app: InstanceRenderManager({ imex: "$t(titles.imexonline)", - rome: "$t(titles.romeonline)", - promanager: "$t(titles.promanager)" + rome: "$t(titles.romeonline)" }) }); setSelectedHeader("dms"); diff --git a/client/src/pages/dms/dms.container.jsx b/client/src/pages/dms/dms.container.jsx index 3a8ac77b0..3b9fe6e42 100644 --- a/client/src/pages/dms/dms.container.jsx +++ b/client/src/pages/dms/dms.container.jsx @@ -65,8 +65,7 @@ export function DmsContainer({ bodyshop, setBreadcrumbs, setSelectedHeader, inse document.title = t("titles.dms", { app: InstanceRenderManager({ imex: "$t(titles.imexonline)", - rome: "$t(titles.romeonline)", - promanager: "$t(titles.promanager)" + rome: "$t(titles.romeonline)" }) }); setSelectedHeader("dms"); diff --git a/client/src/pages/export-logs/export-logs.page.container.jsx b/client/src/pages/export-logs/export-logs.page.container.jsx index 885577b95..0d0845c99 100644 --- a/client/src/pages/export-logs/export-logs.page.container.jsx +++ b/client/src/pages/export-logs/export-logs.page.container.jsx @@ -19,8 +19,7 @@ export function ExportsLogPageContainer({ setBreadcrumbs, setSelectedHeader }) { document.title = t("titles.export-logs", { app: InstanceRenderManager({ imex: "$t(titles.imexonline)", - rome: "$t(titles.romeonline)", - promanager: "$t(titles.promanager)" + rome: "$t(titles.romeonline)" }) }); setSelectedHeader("export-logs"); diff --git a/client/src/pages/inventory/inventory.page.jsx b/client/src/pages/inventory/inventory.page.jsx index a6a1f128c..2b74e608d 100644 --- a/client/src/pages/inventory/inventory.page.jsx +++ b/client/src/pages/inventory/inventory.page.jsx @@ -19,8 +19,7 @@ export function InventoryPage({ setBreadcrumbs, setSelectedHeader }) { document.title = t("titles.inventory", { app: InstanceRenderManager({ imex: "$t(titles.imexonline)", - rome: "$t(titles.romeonline)", - promanager: "$t(titles.promanager)" + rome: "$t(titles.romeonline)" }) }); setSelectedHeader("inventory"); diff --git a/client/src/pages/jobs-admin/jobs-admin.page.jsx b/client/src/pages/jobs-admin/jobs-admin.page.jsx index 03d726efd..c7c78ec95 100644 --- a/client/src/pages/jobs-admin/jobs-admin.page.jsx +++ b/client/src/pages/jobs-admin/jobs-admin.page.jsx @@ -52,8 +52,7 @@ export function JobsCloseContainer({ setBreadcrumbs, setSelectedHeader }) { document.title = t("titles.jobs-admin", { app: InstanceRenderManager({ imex: "$t(titles.imexonline)", - rome: "$t(titles.romeonline)", - promanager: "$t(titles.promanager)" + rome: "$t(titles.romeonline)" }), ro_number: data ? data.jobs_by_pk && data.jobs_by_pk.ro_number : null }); diff --git a/client/src/pages/jobs-all/jobs-all.container.jsx b/client/src/pages/jobs-all/jobs-all.container.jsx index 88adc7921..d6c75544b 100644 --- a/client/src/pages/jobs-all/jobs-all.container.jsx +++ b/client/src/pages/jobs-all/jobs-all.container.jsx @@ -47,8 +47,7 @@ export function AllJobs({ setBreadcrumbs, setSelectedHeader }) { document.title = t("titles.jobs-all", { app: InstanceRenderManager({ imex: "$t(titles.imexonline)", - rome: "$t(titles.romeonline)", - promanager: "$t(titles.promanager)" + rome: "$t(titles.romeonline)" }) }); setSelectedHeader("alljobs"); diff --git a/client/src/pages/jobs-available/jobs-available.page.container.jsx b/client/src/pages/jobs-available/jobs-available.page.container.jsx index bb17df1bf..9cbd509de 100644 --- a/client/src/pages/jobs-available/jobs-available.page.container.jsx +++ b/client/src/pages/jobs-available/jobs-available.page.container.jsx @@ -29,8 +29,7 @@ export function JobsAvailablePageContainer({ partnerVersion, setBreadcrumbs, set document.title = t("titles.jobsavailable", { app: InstanceRenderManager({ imex: "$t(titles.imexonline)", - rome: "$t(titles.romeonline)", - promanager: "$t(titles.promanager)" + rome: "$t(titles.romeonline)" }) }); setSelectedHeader("availablejobs"); @@ -55,8 +54,7 @@ export function JobsAvailablePageContainer({ partnerVersion, setBreadcrumbs, set @@ -66,7 +64,6 @@ export function JobsAvailablePageContainer({ partnerVersion, setBreadcrumbs, set app: InstanceRenderManager({ imex: "$t(titles.imexonline)", rome: "$t(titles.romeonline)", - promanager: "$t(titles.promanager)" }) })} /> diff --git a/client/src/pages/jobs-checklist-view/jobs-checklist-view.page.jsx b/client/src/pages/jobs-checklist-view/jobs-checklist-view.page.jsx index f25bace38..c9eda5480 100644 --- a/client/src/pages/jobs-checklist-view/jobs-checklist-view.page.jsx +++ b/client/src/pages/jobs-checklist-view/jobs-checklist-view.page.jsx @@ -37,8 +37,7 @@ export function JobsChecklistViewContainer({ bodyshop, setBreadcrumbs, setSelect document.title = t("titles.jobs-checklist", { app: InstanceRenderManager({ imex: "$t(titles.imexonline)", - rome: "$t(titles.romeonline)", - promanager: "$t(titles.promanager)" + rome: "$t(titles.romeonline)" }) }); setSelectedHeader("activejobs"); diff --git a/client/src/pages/jobs-close/jobs-close.container.jsx b/client/src/pages/jobs-close/jobs-close.container.jsx index ad47ae676..e237fab9f 100644 --- a/client/src/pages/jobs-close/jobs-close.container.jsx +++ b/client/src/pages/jobs-close/jobs-close.container.jsx @@ -39,8 +39,7 @@ export function JobsCloseContainer({ setBreadcrumbs, setSelectedHeader, setJobRe document.title = t("titles.jobs-close", { app: InstanceRenderManager({ imex: "$t(titles.imexonline)", - rome: "$t(titles.romeonline)", - promanager: "$t(titles.promanager)" + rome: "$t(titles.romeonline)" }), number: data ? data.jobs_by_pk && data.jobs_by_pk.ro_number : null }); diff --git a/client/src/pages/jobs-create/jobs-create.container.jsx b/client/src/pages/jobs-create/jobs-create.container.jsx index 2347f8f9a..9602a2f94 100644 --- a/client/src/pages/jobs-create/jobs-create.container.jsx +++ b/client/src/pages/jobs-create/jobs-create.container.jsx @@ -56,8 +56,7 @@ function JobsCreateContainer({ bodyshop, setBreadcrumbs, setSelectedHeader }) { document.title = t("titles.jobs-create", { app: InstanceRenderManager({ imex: "$t(titles.imexonline)", - rome: "$t(titles.romeonline)", - promanager: "$t(titles.promanager)" + rome: "$t(titles.romeonline)" }) }); setSelectedHeader("newjob"); @@ -280,8 +279,7 @@ function JobsCreateContainer({ bodyshop, setBreadcrumbs, setSelectedHeader }) { tax_sub_rt: bodyshop.md_responsibility_centers.tax_sub_rt, tax_lbr_rt: bodyshop.md_responsibility_centers.tax_lbr_rt, tax_levies_rt: bodyshop.md_responsibility_centers.tax_levies_rt - }, - promanager: "USE_ROME" + } }) }} > diff --git a/client/src/pages/jobs-deliver/jobs-delivery.page.container.jsx b/client/src/pages/jobs-deliver/jobs-delivery.page.container.jsx index 1535936e9..44f82fd21 100644 --- a/client/src/pages/jobs-deliver/jobs-delivery.page.container.jsx +++ b/client/src/pages/jobs-deliver/jobs-delivery.page.container.jsx @@ -35,8 +35,7 @@ export function JobsDeliverContainer({ bodyshop, setBreadcrumbs, setSelectedHead document.title = t("titles.jobs-deliver", { app: InstanceRenderManager({ imex: "$t(titles.imexonline)", - rome: "$t(titles.romeonline)", - promanager: "$t(titles.promanager)" + rome: "$t(titles.romeonline)" }) }); setSelectedHeader("activejobs"); diff --git a/client/src/pages/jobs-detail/jobs-detail.page.component.jsx b/client/src/pages/jobs-detail/jobs-detail.page.component.jsx index a82da973c..3592b46ad 100644 --- a/client/src/pages/jobs-detail/jobs-detail.page.component.jsx +++ b/client/src/pages/jobs-detail/jobs-detail.page.component.jsx @@ -390,9 +390,8 @@ export function JobsDetailPage({ ) }, ...(InstanceRenderManager({ - imex: true, - rome: true, - promanager: HasFeatureAccess({ featureName: "timetickets", bodyshop }) + rome: "USE_IMEX", + imex: HasFeatureAccess({ featureName: "timetickets", bodyshop }) }) ? [ { @@ -420,9 +419,8 @@ export function JobsDetailPage({ children: }, ...(InstanceRenderManager({ - imex: true, - rome: true, - promanager: HasFeatureAccess({ featureName: "media", bodyshop }) + rome: "USE_IMEX", + imex: HasFeatureAccess({ featureName: "media", bodyshop }) }) ? [ { diff --git a/client/src/pages/jobs-detail/jobs-detail.page.container.jsx b/client/src/pages/jobs-detail/jobs-detail.page.container.jsx index 5ac3cfc74..814e0208a 100644 --- a/client/src/pages/jobs-detail/jobs-detail.page.container.jsx +++ b/client/src/pages/jobs-detail/jobs-detail.page.container.jsx @@ -18,9 +18,9 @@ import { } from "../../redux/application/application.actions"; import { selectBodyshop } from "../../redux/user/user.selectors"; import { CreateRecentItem } from "../../utils/create-recent-item"; +import InstanceRenderManager from "../../utils/instanceRenderMgr"; import IsJobReadOnly from "../../utils/jobReadOnly"; import JobsDetailPage from "./jobs-detail.page.component"; -import InstanceRenderManager from "../../utils/instanceRenderMgr"; const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop @@ -49,20 +49,17 @@ function JobsDetailPageContainer({ setBreadcrumbs, addRecentItem, setSelectedHea document.title = loading ? InstanceRenderManager({ imex: t("titles.imexonline"), - rome: t("titles.romeonline"), - promanager: t("titles.promanager") + rome: t("titles.romeonline") }) : error ? InstanceRenderManager({ imex: t("titles.imexonline"), - rome: t("titles.romeonline"), - promanager: t("titles.promanager") + rome: t("titles.romeonline") }) : t("titles.jobsdetail", { app: InstanceRenderManager({ imex: "$t(titles.imexonline)", - rome: "$t(titles.romeonline)", - promanager: "$t(titles.promanager)" + rome: "$t(titles.romeonline)" }), ro_number: (data.jobs_by_pk && data.jobs_by_pk.ro_number) || t("general.labels.na") }); diff --git a/client/src/pages/jobs-intake/jobs-intake.page.container.jsx b/client/src/pages/jobs-intake/jobs-intake.page.container.jsx index a0a5bae84..507a23cf7 100644 --- a/client/src/pages/jobs-intake/jobs-intake.page.container.jsx +++ b/client/src/pages/jobs-intake/jobs-intake.page.container.jsx @@ -37,8 +37,7 @@ export function JobsIntakeContainer({ bodyshop, setBreadcrumbs, setSelectedHeade document.title = t("titles.jobs-intake", { app: InstanceRenderManager({ imex: "$t(titles.imexonline)", - rome: "$t(titles.romeonline)", - promanager: "$t(titles.promanager)" + rome: "$t(titles.romeonline)" }) }); setSelectedHeader("activejobs"); diff --git a/client/src/pages/jobs-ready/jobs-ready.page.jsx b/client/src/pages/jobs-ready/jobs-ready.page.jsx index d1b1a58f9..ad8d1950c 100644 --- a/client/src/pages/jobs-ready/jobs-ready.page.jsx +++ b/client/src/pages/jobs-ready/jobs-ready.page.jsx @@ -19,8 +19,7 @@ export function JobsReadyPage({ setBreadcrumbs, setSelectedHeader }) { document.title = t("titles.readyjobs", { app: InstanceRenderManager({ imex: "$t(titles.imexonline)", - rome: "$t(titles.romeonline)", - promanager: "$t(titles.promanager)" + rome: "$t(titles.romeonline)" }) }); setSelectedHeader("readyjobs"); diff --git a/client/src/pages/jobs/jobs.page.jsx b/client/src/pages/jobs/jobs.page.jsx index f330bb2f0..08dbb2985 100644 --- a/client/src/pages/jobs/jobs.page.jsx +++ b/client/src/pages/jobs/jobs.page.jsx @@ -19,8 +19,7 @@ export function JobsPage({ setBreadcrumbs, setSelectedHeader }) { document.title = t("titles.jobs", { app: InstanceRenderManager({ imex: "$t(titles.imexonline)", - rome: "$t(titles.romeonline)", - promanager: "$t(titles.promanager)" + rome: "$t(titles.romeonline)" }) }); setSelectedHeader("activejobs"); diff --git a/client/src/pages/manage-root/manage-root.page.container.jsx b/client/src/pages/manage-root/manage-root.page.container.jsx index 1763dcb6b..c8b795618 100644 --- a/client/src/pages/manage-root/manage-root.page.container.jsx +++ b/client/src/pages/manage-root/manage-root.page.container.jsx @@ -21,8 +21,7 @@ export function ManageRootPageContainer({ setBreadcrumbs, bodyshop }) { document.title = t("titles.manageroot", { app: InstanceRenderManager({ imex: "$t(titles.imexonline)", - rome: "$t(titles.romeonline)", - promanager: "$t(titles.promanager)" + rome: "$t(titles.romeonline)" }) }); setBreadcrumbs([]); diff --git a/client/src/pages/manage/manage.page.component.jsx b/client/src/pages/manage/manage.page.component.jsx index 6dfd8af6e..c08f86556 100644 --- a/client/src/pages/manage/manage.page.component.jsx +++ b/client/src/pages/manage/manage.page.component.jsx @@ -193,8 +193,7 @@ export function Manage({ conflict, bodyshop, alerts, setAlerts }) { useEffect(() => { document.title = InstanceRenderManager({ imex: t("titles.imexonline"), - rome: t("titles.romeonline"), - promanager: t("titles.promanager") + rome: t("titles.romeonline") }); }, [t]); @@ -205,8 +204,7 @@ export function Manage({ conflict, bodyshop, alerts, setAlerts }) { message={t("general.labels.loadingapp", { app: InstanceRenderManager({ imex: "$t(titles.imexonline)", - rome: "$t(titles.romeonline)", - promanager: "$t(titles.promanager)" + rome: "$t(titles.romeonline)" }) })} /> @@ -674,8 +672,7 @@ export function Manage({ conflict, bodyshop, alerts, setAlerts }) {
{`${InstanceRenderManager({ imex: t("titles.imexonline"), - rome: t("titles.romeonline"), - promanager: t("titles.promanager") + rome: t("titles.romeonline") })} - ${import.meta.env.VITE_APP_GIT_SHA_DATE}`}
diff --git a/client/src/pages/owners-detail/owners-detail.page.container.jsx b/client/src/pages/owners-detail/owners-detail.page.container.jsx index 95904c01a..f10792fba 100644 --- a/client/src/pages/owners-detail/owners-detail.page.container.jsx +++ b/client/src/pages/owners-detail/owners-detail.page.container.jsx @@ -34,8 +34,7 @@ export function OwnersDetailContainer({ setBreadcrumbs, addRecentItem, setSelect document.title = t("titles.owners-detail", { app: InstanceRenderManager({ imex: "$t(titles.imexonline)", - rome: "$t(titles.romeonline)", - promanager: "$t(titles.promanager)" + rome: "$t(titles.romeonline)" }), name: data ? OwnerNameDisplayFunction(data.owners_by_pk) : "" }); diff --git a/client/src/pages/owners/owners.page.container.jsx b/client/src/pages/owners/owners.page.container.jsx index 0729e2d84..ab380db42 100644 --- a/client/src/pages/owners/owners.page.container.jsx +++ b/client/src/pages/owners/owners.page.container.jsx @@ -17,8 +17,7 @@ export function OwnersPageContainer({ setBreadcrumbs, setSelectedHeader }) { document.title = t("titles.owners", { app: InstanceRenderManager({ imex: "$t(titles.imexonline)", - rome: "$t(titles.romeonline)", - promanager: "$t(titles.promanager)" + rome: "$t(titles.romeonline)" }) }); setSelectedHeader("owners"); diff --git a/client/src/pages/parts-queue/parts-queue.page.container.jsx b/client/src/pages/parts-queue/parts-queue.page.container.jsx index 91572e276..a4ed6d442 100644 --- a/client/src/pages/parts-queue/parts-queue.page.container.jsx +++ b/client/src/pages/parts-queue/parts-queue.page.container.jsx @@ -19,8 +19,7 @@ export function PartsQueuePageContainer({ setBreadcrumbs, setSelectedHeader }) { document.title = t("titles.parts-queue", { app: InstanceRenderManager({ imex: "$t(titles.imexonline)", - rome: "$t(titles.romeonline)", - promanager: "$t(titles.promanager)" + rome: "$t(titles.romeonline)" }) }); setSelectedHeader("parts-queue"); diff --git a/client/src/pages/payments-all/payments-all.container.page.jsx b/client/src/pages/payments-all/payments-all.container.page.jsx index 9e63b8dfd..2aa77422e 100644 --- a/client/src/pages/payments-all/payments-all.container.page.jsx +++ b/client/src/pages/payments-all/payments-all.container.page.jsx @@ -49,8 +49,7 @@ export function AllJobs({ bodyshop, setBreadcrumbs, setSelectedHeader }) { document.title = t("titles.payments-all", { app: InstanceRenderManager({ imex: "$t(titles.imexonline)", - rome: "$t(titles.romeonline)", - promanager: "$t(titles.promanager)" + rome: "$t(titles.romeonline)" }) }); setSelectedHeader("allpayments"); diff --git a/client/src/pages/phonebook/phonebook.page.container.jsx b/client/src/pages/phonebook/phonebook.page.container.jsx index fe407cec3..b71e06bf4 100644 --- a/client/src/pages/phonebook/phonebook.page.container.jsx +++ b/client/src/pages/phonebook/phonebook.page.container.jsx @@ -22,8 +22,7 @@ export function PhonebookContainer({ setBreadcrumbs, setSelectedHeader }) { document.title = t("titles.phonebook", { app: InstanceRenderManager({ imex: "$t(titles.imexonline)", - rome: "$t(titles.romeonline)", - promanager: "$t(titles.promanager)" + rome: "$t(titles.romeonline)" }) }); setSelectedHeader("phonebook"); diff --git a/client/src/pages/production-board/production-board.container.jsx b/client/src/pages/production-board/production-board.container.jsx index f646d16c1..711f9fdc0 100644 --- a/client/src/pages/production-board/production-board.container.jsx +++ b/client/src/pages/production-board/production-board.container.jsx @@ -25,8 +25,7 @@ export function ProductionBoardContainer({ setBreadcrumbs, bodyshop, setSelected document.title = t("titles.productionboard", { app: InstanceRenderManager({ imex: "$t(titles.imexonline)", - rome: "$t(titles.romeonline)", - promanager: "$t(titles.promanager)" + rome: "$t(titles.romeonline)" }) }); setSelectedHeader("productionboard"); diff --git a/client/src/pages/production-list/production-list.container.jsx b/client/src/pages/production-list/production-list.container.jsx index 9c7cc4892..f87364e7d 100644 --- a/client/src/pages/production-list/production-list.container.jsx +++ b/client/src/pages/production-list/production-list.container.jsx @@ -22,8 +22,7 @@ export function ProductionListContainer({ document.title = t("titles.productionlist", { app: InstanceRenderManager({ imex: "$t(titles.imexonline)", - rome: "$t(titles.romeonline)", - promanager: "$t(titles.promanager)" + rome: "$t(titles.romeonline)" }) }); setSelectedHeader("productionlist"); diff --git a/client/src/pages/profile/profile.container.page.jsx b/client/src/pages/profile/profile.container.page.jsx index 3ab67ec65..05f4172ba 100644 --- a/client/src/pages/profile/profile.container.page.jsx +++ b/client/src/pages/profile/profile.container.page.jsx @@ -19,7 +19,7 @@ export function ProfileContainerPage({ setBreadcrumbs, setSelectedHeader }) { app: InstanceRenderManager({ imex: "$t(titles.imexonline)", rome: "$t(titles.romeonline)", - promanager: "$t(titles.promanager)" + }) }); }, [t, setBreadcrumbs, setSelectedHeader]); diff --git a/client/src/pages/schedule/schedule.page.container.jsx b/client/src/pages/schedule/schedule.page.container.jsx index 9ee7ff34c..cfb6fafdb 100644 --- a/client/src/pages/schedule/schedule.page.container.jsx +++ b/client/src/pages/schedule/schedule.page.container.jsx @@ -18,8 +18,7 @@ export function SchedulePageContainer({ setBreadcrumbs, setSelectedHeader }) { document.title = t("titles.schedule", { app: InstanceRenderManager({ imex: "$t(titles.imexonline)", - rome: "$t(titles.romeonline)", - promanager: "$t(titles.promanager)" + rome: "$t(titles.romeonline)" }) }); setSelectedHeader("schedule"); diff --git a/client/src/pages/scoreboard/scoreboard.page.container.jsx b/client/src/pages/scoreboard/scoreboard.page.container.jsx index 693a1b977..3072b7bb4 100644 --- a/client/src/pages/scoreboard/scoreboard.page.container.jsx +++ b/client/src/pages/scoreboard/scoreboard.page.container.jsx @@ -50,8 +50,7 @@ export function ScoreboardContainer({ setBreadcrumbs, setSelectedHeader }) { document.title = t("titles.scoreboard", { app: InstanceRenderManager({ imex: "$t(titles.imexonline)", - rome: "$t(titles.romeonline)", - promanager: "$t(titles.promanager)" + rome: "$t(titles.romeonline)" }) }); setSelectedHeader("scoreboard"); diff --git a/client/src/pages/shop-csi/shop-csi.container.page.jsx b/client/src/pages/shop-csi/shop-csi.container.page.jsx index 4adcaf6cd..67f9e2ef2 100644 --- a/client/src/pages/shop-csi/shop-csi.container.page.jsx +++ b/client/src/pages/shop-csi/shop-csi.container.page.jsx @@ -34,8 +34,7 @@ export function ShopCsiContainer({ bodyshop, setBreadcrumbs, setSelectedHeader } document.title = t("titles.shop-csi", { app: InstanceRenderManager({ imex: "$t(titles.imexonline)", - rome: "$t(titles.romeonline)", - promanager: "$t(titles.promanager)" + rome: "$t(titles.romeonline)" }) }); setSelectedHeader("shop-csi"); diff --git a/client/src/pages/shop-vendor/shop-vendor.page.container.jsx b/client/src/pages/shop-vendor/shop-vendor.page.container.jsx index 5f41d3438..20c4da53c 100644 --- a/client/src/pages/shop-vendor/shop-vendor.page.container.jsx +++ b/client/src/pages/shop-vendor/shop-vendor.page.container.jsx @@ -23,8 +23,7 @@ export function ShopVendorPageContainer({ bodyshop, setBreadcrumbs, setSelectedH document.title = t("titles.shop_vendors", { app: InstanceRenderManager({ imex: "$t(titles.imexonline)", - rome: "$t(titles.romeonline)", - promanager: "$t(titles.promanager)" + rome: "$t(titles.romeonline)" }) }); setSelectedHeader("shop-vendors"); diff --git a/client/src/pages/shop/shop.page.component.jsx b/client/src/pages/shop/shop.page.component.jsx index 328d07247..b4b354b1d 100644 --- a/client/src/pages/shop/shop.page.component.jsx +++ b/client/src/pages/shop/shop.page.component.jsx @@ -34,8 +34,7 @@ export function ShopPage({ bodyshop, setSelectedHeader, setBreadcrumbs }) { document.title = t("titles.shop", { app: InstanceRenderManager({ imex: "$t(titles.imexonline)", - rome: "$t(titles.romeonline)", - promanager: "$t(titles.promanager)" + rome: "$t(titles.romeonline)" }) }); setSelectedHeader("shop"); diff --git a/client/src/pages/tasks/allTasksPageContainer.jsx b/client/src/pages/tasks/allTasksPageContainer.jsx index e85dc5b46..107143786 100644 --- a/client/src/pages/tasks/allTasksPageContainer.jsx +++ b/client/src/pages/tasks/allTasksPageContainer.jsx @@ -26,8 +26,7 @@ export function AllTasksPageContainer({ setBreadcrumbs, setSelectedHeader, setTa document.title = t("titles.all_tasks", { app: InstanceRenderManager({ imex: "$t(titles.imexonline)", - rome: "$t(titles.romeonline)", - promanager: "$t(titles.promanager)" + rome: "$t(titles.romeonline)" }) }); setSelectedHeader("all_tasks"); diff --git a/client/src/pages/tasks/myTasksPageContainer.jsx b/client/src/pages/tasks/myTasksPageContainer.jsx index 52b4b0fbf..4477e3878 100644 --- a/client/src/pages/tasks/myTasksPageContainer.jsx +++ b/client/src/pages/tasks/myTasksPageContainer.jsx @@ -21,8 +21,7 @@ export function MyTasksPageContainer({ setBreadcrumbs, setSelectedHeader }) { document.title = t("titles.my_tasks", { app: InstanceRenderManager({ imex: "$t(titles.imexonline)", - rome: "$t(titles.romeonline)", - promanager: "$t(titles.promanager)" + rome: "$t(titles.romeonline)" }) }); setSelectedHeader("my_tasks"); diff --git a/client/src/pages/tech-job-clock/tech-job-clock.component.jsx b/client/src/pages/tech-job-clock/tech-job-clock.component.jsx index f9c120be3..98b4e9bf2 100644 --- a/client/src/pages/tech-job-clock/tech-job-clock.component.jsx +++ b/client/src/pages/tech-job-clock/tech-job-clock.component.jsx @@ -13,8 +13,7 @@ export default function TechClockComponent() { document.title = t("titles.techjobclock", { app: InstanceRenderManager({ imex: "$t(titles.imexonline)", - rome: "$t(titles.romeonline)", - promanager: "$t(titles.promanager)" + rome: "$t(titles.romeonline)" }) }); }, [t]); diff --git a/client/src/pages/tech-lookup/tech-lookup.container.jsx b/client/src/pages/tech-lookup/tech-lookup.container.jsx index a209777ba..74cbd1300 100644 --- a/client/src/pages/tech-lookup/tech-lookup.container.jsx +++ b/client/src/pages/tech-lookup/tech-lookup.container.jsx @@ -12,8 +12,7 @@ export default function TechLookupContainer() { document.title = t("titles.techjoblookup", { app: InstanceRenderManager({ imex: "$t(titles.imexonline)", - rome: "$t(titles.romeonline)", - promanager: "$t(titles.promanager)" + rome: "$t(titles.romeonline)" }) }); }, [t]); diff --git a/client/src/pages/tech-shift-clock/tech-shift-clock.component.jsx b/client/src/pages/tech-shift-clock/tech-shift-clock.component.jsx index bdc9f8b32..85237280e 100644 --- a/client/src/pages/tech-shift-clock/tech-shift-clock.component.jsx +++ b/client/src/pages/tech-shift-clock/tech-shift-clock.component.jsx @@ -10,8 +10,7 @@ export default function TechShiftClock() { document.title = t("titles.techshiftclock", { app: InstanceRenderManager({ imex: "$t(titles.imexonline)", - rome: "$t(titles.romeonline)", - promanager: "$t(titles.promanager)" + rome: "$t(titles.romeonline)" }) }); }, [t]); diff --git a/client/src/pages/tech/tech.page.component.jsx b/client/src/pages/tech/tech.page.component.jsx index 2be9f0a2a..f8be46b4a 100644 --- a/client/src/pages/tech/tech.page.component.jsx +++ b/client/src/pages/tech/tech.page.component.jsx @@ -50,8 +50,7 @@ export function TechPage({ technician }) { useEffect(() => { document.title = InstanceRenderManager({ imex: t("titles.imexonline"), - rome: t("titles.romeonline"), - promanager: t("titles.promanager") + rome: t("titles.romeonline") }); }, [t]); @@ -77,8 +76,7 @@ export function TechPage({ technician }) { message={t("general.labels.loadingapp", { app: InstanceRenderManager({ imex: "$t(titles.imexonline)", - rome: "$t(titles.romeonline)", - promanager: "$t(titles.promanager)" + rome: "$t(titles.romeonline)" }) })} /> diff --git a/client/src/pages/temporary-docs/temporary-docs.container.jsx b/client/src/pages/temporary-docs/temporary-docs.container.jsx index bb8785838..2960a9bba 100644 --- a/client/src/pages/temporary-docs/temporary-docs.container.jsx +++ b/client/src/pages/temporary-docs/temporary-docs.container.jsx @@ -25,8 +25,7 @@ export function TempDocumentsContainer({ setBreadcrumbs, setSelectedHeader }) { document.title = t("titles.temporarydocs", { app: InstanceRenderManager({ imex: "$t(titles.imexonline)", - rome: "$t(titles.romeonline)", - promanager: "$t(titles.promanager)" + rome: "$t(titles.romeonline)" }) }); setSelectedHeader("temporarydocs"); diff --git a/client/src/pages/time-tickets/time-tickets.container.jsx b/client/src/pages/time-tickets/time-tickets.container.jsx index 766bd62e0..a14c150c1 100644 --- a/client/src/pages/time-tickets/time-tickets.container.jsx +++ b/client/src/pages/time-tickets/time-tickets.container.jsx @@ -58,8 +58,7 @@ export function TimeTicketsContainer({ bodyshop, setBreadcrumbs, setSelectedHead document.title = t("titles.timetickets", { app: InstanceRenderManager({ imex: "$t(titles.imexonline)", - rome: "$t(titles.romeonline)", - promanager: "$t(titles.promanager)" + rome: "$t(titles.romeonline)" }) }); setSelectedHeader("timetickets"); diff --git a/client/src/pages/tt-approvals/tt-approvals.page.container.jsx b/client/src/pages/tt-approvals/tt-approvals.page.container.jsx index 6f30c0727..d96734eac 100644 --- a/client/src/pages/tt-approvals/tt-approvals.page.container.jsx +++ b/client/src/pages/tt-approvals/tt-approvals.page.container.jsx @@ -25,8 +25,7 @@ export function TtApprovalsPage({ setBreadcrumbs, setSelectedHeader }) { document.title = t("titles.ttapprovals", { app: InstanceRenderManager({ imex: "$t(titles.imexonline)", - rome: "$t(titles.romeonline)", - promanager: "$t(titles.promanager)" + rome: "$t(titles.romeonline)" }) }); setSelectedHeader("ttapprovals"); diff --git a/client/src/pages/vehicles-detail/vehicles-detail.page.container.jsx b/client/src/pages/vehicles-detail/vehicles-detail.page.container.jsx index ac3be0137..1f2917f4f 100644 --- a/client/src/pages/vehicles-detail/vehicles-detail.page.container.jsx +++ b/client/src/pages/vehicles-detail/vehicles-detail.page.container.jsx @@ -32,8 +32,7 @@ export function VehicleDetailContainer({ setBreadcrumbs, addRecentItem, setSelec document.title = t("titles.vehicledetail", { app: InstanceRenderManager({ imex: "$t(titles.imexonline)", - rome: "$t(titles.romeonline)", - promanager: "$t(titles.promanager)" + rome: "$t(titles.romeonline)" }), vehicle: data && data.vehicles_by_pk diff --git a/client/src/pages/vehicles/vehicles.page.container.jsx b/client/src/pages/vehicles/vehicles.page.container.jsx index 96a0af2b7..539c09dbb 100644 --- a/client/src/pages/vehicles/vehicles.page.container.jsx +++ b/client/src/pages/vehicles/vehicles.page.container.jsx @@ -18,8 +18,7 @@ export function VehiclesPageContainer({ setBreadcrumbs, setSelectedHeader }) { document.title = t("titles.vehicles", { app: InstanceRenderManager({ imex: "$t(titles.imexonline)", - rome: "$t(titles.romeonline)", - promanager: "$t(titles.promanager)" + rome: "$t(titles.romeonline)" }) }); setSelectedHeader("vehicles"); diff --git a/client/src/redux/email/email.reducer.js b/client/src/redux/email/email.reducer.js index 86582d98d..bd9485d97 100644 --- a/client/src/redux/email/email.reducer.js +++ b/client/src/redux/email/email.reducer.js @@ -8,8 +8,7 @@ const INITIAL_STATE = { name: "ShopName", address: InstanceRenderManager({ imex: "noreply@iemx.online", - rome: "noreply@romeonline.io", - promanager: "noreply@promanager.web-est.com" + rome: "noreply@romeonline.io" }) }, to: null, diff --git a/client/src/redux/user/user.sagas.js b/client/src/redux/user/user.sagas.js index 423b40283..8cd70c480 100644 --- a/client/src/redux/user/user.sagas.js +++ b/client/src/redux/user/user.sagas.js @@ -15,7 +15,6 @@ import { getToken } from "firebase/messaging"; import i18next from "i18next"; import LogRocket from "logrocket"; import { all, call, delay, put, select, takeLatest } from "redux-saga/effects"; -import { Userpilot } from "userpilot"; import { factory } from "../../App/App.container"; import { analytics, @@ -245,12 +244,6 @@ export function* signInSuccessSaga({ payload }) { rome: () => { window.$zoho.salesiq.visitor.name(payload.displayName || payload.email); window.$zoho.salesiq.visitor.email(payload.email); - }, - promanager: () => { - Userpilot.identify(payload.email, { - email: payload.email - }); - console.log("*** Userpilot identified."); } }); } catch (error) { @@ -281,8 +274,7 @@ export function* sendPasswordResetEmailSaga({ payload }) { yield sendPasswordResetEmail(auth, payload, { url: InstanceRenderManager({ imex: "https://imex.online/passwordreset", - rome: "https://romeonline.io/passwordreset", - promanager: "https:promanager.web-est.com/passwordreset" + rome: "https://romeonline.io/passwordreset" }) }); @@ -330,41 +322,10 @@ export function* SetAuthLevelFromShopDetails({ payload }) { const user = yield select((state) => state.user.currentUser); if (payload.features.singleDeviceOnly) { - if ( - !( - user.email.includes("@imex.") || - user.email.includes("@rome.") || - user.email.includes("@rometech.") || - user.email.includes("@promanager.") - ) - ) + if (!(user.email.includes("@imex.") || user.email.includes("@rome.") || user.email.includes("@rometech."))) yield put(setInstanceId(user.uid)); } - //For Rome, check to make sure it's not a PM shop. - try { - InstanceRenderManager({ - executeFunction: true, - args: [], - rome: () => { - if ( - payload.imexshopid.toLowerCase().startsWith("pm_") && - !( - user.email.includes("@imex.") || - user.email.includes("@rome.") || - user.email.includes("@rometech.") || - user.email.includes("@promanager.") - ) - ) { - throw new Error("You are not authorized to use this application."); - } - }, - promanager: () => {} - }); - } catch (error) { - yield put(setInstanceConflict()); - } - try { InstanceRenderManager({ executeFunction: true, diff --git a/client/src/translations/en_us/common.json b/client/src/translations/en_us/common.json index b743b209a..f3e4d30bf 100644 --- a/client/src/translations/en_us/common.json +++ b/client/src/translations/en_us/common.json @@ -1257,7 +1257,7 @@ "sunday": "Sunday", "text": "Text", "thursday": "Thursday", - "time": "Select Time", + "time": "Select Time", "total": "Total", "totals": "Totals", "tuesday": "Tuesday", @@ -1342,8 +1342,8 @@ }, "job_lifecycle": { "columns": { - "average_human_readable": "Average Human Readable", - "average_value": "Average Value", + "average_human_readable": "Average Human Readable", + "average_value": "Average Value", "duration": "Duration", "end": "End", "human_readable": "Human Readable", @@ -1877,7 +1877,7 @@ "tax_str_rt": "Storage Tax Rate", "tax_sub_rt": "Sublet Tax Rate", "tax_tow_rt": "Towing Tax Rate", - "tlos_ind": "Total Loss Indicator", + "tlos_ind": "Total Loss Indicator", "towin": "Tow In", "towing_payable": "Towing Payable", "unitnumber": "Unit #", @@ -3432,7 +3432,6 @@ "productionboard": "Production Board - Visual | {{app}}", "productionlist": "Production Board - List | {{app}}", "profile": "My Profile | {{app}}", - "promanager": "ProManager", "readyjobs": "Ready Jobs | {{app}}", "resetpassword": "Reset Password", "resetpasswordvalidate": "Enter New Password", diff --git a/client/src/translations/es/common.json b/client/src/translations/es/common.json index 4a5a39a9f..8c5cd5f38 100644 --- a/client/src/translations/es/common.json +++ b/client/src/translations/es/common.json @@ -1257,7 +1257,7 @@ "sunday": "", "text": "", "thursday": "", - "time": "", + "time": "", "total": "", "totals": "", "tuesday": "", @@ -1342,8 +1342,8 @@ }, "job_lifecycle": { "columns": { - "average_human_readable": "", - "average_value": "", + "average_human_readable": "", + "average_value": "", "duration": "", "end": "", "human_readable": "", @@ -1877,7 +1877,7 @@ "tax_str_rt": "", "tax_sub_rt": "", "tax_tow_rt": "", - "tlos_ind": "", + "tlos_ind": "", "towin": "", "towing_payable": "Remolque a pagar", "unitnumber": "Unidad #", @@ -3432,7 +3432,6 @@ "productionboard": "", "productionlist": "", "profile": "Mi perfil | {{app}}", - "promanager": "", "readyjobs": "", "resetpassword": "", "resetpasswordvalidate": "", diff --git a/client/src/translations/fr/common.json b/client/src/translations/fr/common.json index df418a823..67e3f9369 100644 --- a/client/src/translations/fr/common.json +++ b/client/src/translations/fr/common.json @@ -1257,7 +1257,7 @@ "sunday": "", "text": "", "thursday": "", - "time": "", + "time": "", "total": "", "totals": "", "tuesday": "", @@ -1342,8 +1342,8 @@ }, "job_lifecycle": { "columns": { - "average_human_readable": "", - "average_value": "", + "average_human_readable": "", + "average_value": "", "duration": "", "end": "", "human_readable": "", @@ -1877,7 +1877,7 @@ "tax_str_rt": "", "tax_sub_rt": "", "tax_tow_rt": "", - "tlos_ind": "", + "tlos_ind": "", "towin": "", "towing_payable": "Remorquage à payer", "unitnumber": "Unité #", @@ -3432,7 +3432,6 @@ "productionboard": "", "productionlist": "", "profile": "Mon profil | {{app}}", - "promanager": "", "readyjobs": "", "resetpassword": "", "resetpasswordvalidate": "", diff --git a/client/src/utils/CleanAxios.js b/client/src/utils/CleanAxios.js index cfdb2134e..cf4737482 100644 --- a/client/src/utils/CleanAxios.js +++ b/client/src/utils/CleanAxios.js @@ -1,6 +1,5 @@ import axios from "axios"; import { auth } from "../firebase/firebase.utils"; -import InstanceRenderManager from "./instanceRenderMgr"; axios.defaults.baseURL = import.meta.env.DEV ? "/api/" @@ -13,15 +12,6 @@ export const axiosAuthInterceptorId = axios.interceptors.request.use( if (token) { config.headers.Authorization = `Bearer ${token}`; } - InstanceRenderManager({ - executeFunction: true, - args: [], - promanager: () => { - if (!config.url.startsWith("http://localhost:1337")) { - config.headers["Convenient-Company"] = "promanager"; - } - } - }); } return config; diff --git a/client/src/utils/RegisterSw.js b/client/src/utils/RegisterSw.js index 3f0c5712c..ad701bcc4 100644 --- a/client/src/utils/RegisterSw.js +++ b/client/src/utils/RegisterSw.js @@ -49,15 +49,13 @@ const onServiceWorkerUpdate = (registration) => { message: i18n.t("general.messages.newversiontitle", { app: InstanceRenderManager({ imex: "$t(titles.imexonline)", - rome: "$t(titles.romeonline)", - promanager: "$t(titles.promanager)" + rome: "$t(titles.romeonline)" }) }), description: i18n.t("general.messages.newversionmessage", { app: InstanceRenderManager({ imex: "$t(titles.imexonline)", - rome: "$t(titles.romeonline)", - promanager: "$t(titles.promanager)" + rome: "$t(titles.romeonline)" }) }), duration: 0, diff --git a/client/src/utils/RenderTemplate.js b/client/src/utils/RenderTemplate.js index 1deb8e76d..fd6eb6e44 100644 --- a/client/src/utils/RenderTemplate.js +++ b/client/src/utils/RenderTemplate.js @@ -72,8 +72,8 @@ export default async function RenderTemplate( ...contextData, ...templateObject.variables, ...templateObject.context, - headerpath: `/${InstanceRenderManager({ imex: bodyshop.imexshopid, rome: bodyshop.imexshopid, promanager: "GENERIC" })}/header.html`, - footerpath: `/${InstanceRenderManager({ imex: bodyshop.imexshopid, rome: bodyshop.imexshopid, promanager: "GENERIC" })}/footer.html`, + headerpath: `/${InstanceRenderManager({ imex: bodyshop.imexshopid, rome: bodyshop.imexshopid })}/header.html`, + footerpath: `/${InstanceRenderManager({ imex: bodyshop.imexshopid, rome: bodyshop.imexshopid })}/footer.html`, bodyshop: bodyshop, filters: templateObject?.filters, sorters: templateObject?.sorters, diff --git a/client/src/utils/TemplateConstants.js b/client/src/utils/TemplateConstants.js index 9f80986d2..fcf10422d 100644 --- a/client/src/utils/TemplateConstants.js +++ b/client/src/utils/TemplateConstants.js @@ -5,13 +5,11 @@ import InstanceRenderManager from "./instanceRenderMgr"; export const EmailSettings = { fromNameDefault: InstanceRenderManager({ imex: "ImEX Online", - rome: "Rome Online", - promanager: "ProManager" + rome: "Rome Online" }), fromAddress: InstanceRenderManager({ imex: "noreply@imex.online", - rome: "noreply@romeonline.io", - promanager: "noreply@promanager.web-est.com" + rome: "noreply@romeonline.io" }) }; diff --git a/client/src/utils/instanceRenderMgr.js b/client/src/utils/instanceRenderMgr.js index cb436dd0d..4ee0f204e 100644 --- a/client/src/utils/instanceRenderMgr.js +++ b/client/src/utils/instanceRenderMgr.js @@ -12,6 +12,11 @@ export default function InstanceRenderManager({ executeFunction, rome, promanager, imex, debug, instance, args }) { let propToReturn = null; + //TODO: Remove after debugging. + if (promanager) { + console.trace("ProManager Prop was used"); + } + switch (instance || import.meta.env.VITE_APP_INSTANCE) { case "IMEX": propToReturn = imex; diff --git a/client/vite.config.js b/client/vite.config.js index 03f56c538..edc9d5683 100644 --- a/client/vite.config.js +++ b/client/vite.config.js @@ -57,13 +57,13 @@ export default defineConfig({ instance: process.env.VITE_APP_INSTANCE, imex: "ImEX Online", rome: "Rome Online", - promanager: "ProManager" + }), name: InstanceRenderManager({ instance: process.env.VITE_APP_INSTANCE, imex: "ImEX Online", rome: "Rome Online", - promanager: "ProManager" + }), description: "The ultimate bodyshop management system.", icons: [ @@ -72,7 +72,6 @@ export default defineConfig({ instance: process.env.VITE_APP_INSTANCE, imex: "favicon.png", rome: "ro-favicon.png", - promanager: "/pm/pm-favicon.ico" }), sizes: "64x64 32x32 24x24 16x16", type: "image/x-icon" @@ -82,7 +81,6 @@ export default defineConfig({ instance: process.env.VITE_APP_INSTANCE, imex: "logo192.png", rome: "logo192.png", - promanager: "/pm/pm-icon-192.png" }), type: "image/png", sizes: "192x192" @@ -92,7 +90,6 @@ export default defineConfig({ instance: process.env.VITE_APP_INSTANCE, imex: "logo512.png", rome: "ro-favicon.png", - promanager: "/pm/pm-icon-512.png" }), type: "image/png", sizes: "512x512" @@ -102,7 +99,6 @@ export default defineConfig({ instance: process.env.VITE_APP_INSTANCE, imex: "#1890ff", rome: "#fff", - promanager: "#1d69a6" }), background_color: "#fff", gcm_sender_id: "103953800507" diff --git a/package-lock.json b/package-lock.json index d95191db5..648b3eae6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -63,8 +63,12 @@ "xmlbuilder2": "^3.1.1" }, "devDependencies": { + "@eslint/js": "^9.15.0", "@trivago/prettier-plugin-sort-imports": "^4.3.0", "concurrently": "^8.2.2", + "eslint": "^9.15.0", + "eslint-plugin-react": "^7.37.2", + "globals": "^15.12.0", "prettier": "^3.3.3", "source-map-explorer": "^2.5.2" }, @@ -2703,6 +2707,16 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/traverse/node_modules/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, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/types": { "version": "7.17.0", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", @@ -2735,6 +2749,241 @@ "kuler": "^2.0.0" } }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", + "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.0.tgz", + "integrity": "sha512-zdHg2FPIFNKPdcHWtiNT+jEFCHYVplAXRDlQDyqy0zGx/q2parwh7brGJSiTxRk/TSMkbM//zt/f5CHgyTyaSQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.4", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/core": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.9.0.tgz", + "integrity": "sha512-7ATR9F0e4W85D/0w7cU0SNj7qkAexMG+bAHEZOjo9akvGuhHE2m7umzWzfnpa0XAg5Kxc1BWmtPMV67jJ+9VUg==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.2.0.tgz", + "integrity": "sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/eslintrc/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/js": { + "version": "9.15.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.15.0.tgz", + "integrity": "sha512-tMTqrY+EzbXmKJR5ToI8lxu7jaN5EdmrBFJpQk5JmSlyLsx6o4t27r883K5xsLuCYCpfKBCGswMSWXsM+jB7lg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", + "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.3.tgz", + "integrity": "sha512-2b/g5hRmpbb1o4GnTZax9N9m0FXzz9OV42ZzI4rDDMDuHUqigAiQCEWChBWCY4ztAGVRjoWT19v0yMmc5/L5kA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit/node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/@eslint/plugin-kit/node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/@eslint/plugin-kit/node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/@fastify/busboy": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-3.0.0.tgz", @@ -2939,6 +3188,72 @@ "node": ">=6" } }, + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", + "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.3.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.1.tgz", + "integrity": "sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, "node_modules/@ioredis/commands": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.2.0.tgz", @@ -4191,6 +4506,13 @@ "@types/node": "*" } }, + "node_modules/@types/estree": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/express": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", @@ -4218,6 +4540,13 @@ "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==" }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/jsonwebtoken": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.5.tgz", @@ -4364,9 +4693,10 @@ } }, "node_modules/acorn": { - "version": "8.11.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", - "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", + "license": "MIT", "bin": { "acorn": "bin/acorn" }, @@ -4374,6 +4704,16 @@ "node": ">=0.4.0" } }, + "node_modules/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, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, "node_modules/acorn-walk": { "version": "8.3.0", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.0.tgz", @@ -4393,6 +4733,23 @@ "node": ">= 6.0.0" } }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -4438,11 +4795,155 @@ "node": ">=10" } }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, + "node_modules/array-includes": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", + "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", + "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", + "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.tosorted": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", + "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/arrify": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", @@ -4506,6 +5007,22 @@ "node": ">= 4.5.0" } }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/aws4": { "version": "1.13.2", "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.13.2.tgz", @@ -4775,6 +5292,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/canvas": { "version": "2.11.2", "resolved": "https://registry.npmjs.org/canvas/-/canvas-2.11.2.tgz", @@ -5236,9 +5763,10 @@ } }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -5308,6 +5836,60 @@ "node": ">= 6" } }, + "node_modules/data-view-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", + "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", + "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", + "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/date-fns": { "version": "2.30.0", "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", @@ -5395,6 +5977,24 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/degenerator": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-3.0.4.tgz", @@ -5495,6 +6095,19 @@ "node": ">=16" } }, + "node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/dom-serializer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", @@ -5688,6 +6301,67 @@ "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==" }, + "node_modules/es-abstract": { + "version": "1.23.5", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.5.tgz", + "integrity": "sha512-vlmniQ0WNPwXqA0BnmwV3Ng7HxiGlh6r5U6JcTMNx8OilcAGqVJBHJcPjqOMaczU9fRuRK5Px2BdVyPRnKMMVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "arraybuffer.prototype.slice": "^1.0.3", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "data-view-buffer": "^1.0.1", + "data-view-byte-length": "^1.0.1", + "data-view-byte-offset": "^1.0.0", + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.0.3", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.4", + "get-symbol-description": "^1.0.2", + "globalthis": "^1.0.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "hasown": "^2.0.2", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.1", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.3", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.13", + "is-weakref": "^1.0.2", + "object-inspect": "^1.13.3", + "object-keys": "^1.1.1", + "object.assign": "^4.1.5", + "regexp.prototype.flags": "^1.5.3", + "safe-array-concat": "^1.1.2", + "safe-regex-test": "^1.0.3", + "string.prototype.trim": "^1.2.9", + "string.prototype.trimend": "^1.0.8", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-length": "^1.0.1", + "typed-array-byte-offset": "^1.0.2", + "typed-array-length": "^1.0.6", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.15" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/es-define-property": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", @@ -5709,6 +6383,89 @@ "node": ">= 0.4" } }, + "node_modules/es-iterator-helpers": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.2.0.tgz", + "integrity": "sha512-tpxqxncxnpw3c93u8n3VOzACmRFoVmWJqbWXvX/JfKbkhBw1oslgPrUfeSt2psuqyEJFD6N/9lg5i7bsKpoq+Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.0.3", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "globalthis": "^1.0.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.7", + "iterator.prototype": "^1.1.3", + "safe-array-concat": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", + "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.0" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", @@ -5761,6 +6518,273 @@ "node": ">=4.0" } }, + "node_modules/eslint": { + "version": "9.15.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.15.0.tgz", + "integrity": "sha512-7CrWySmIibCgT1Os28lUU6upBshZ+GxybLOrmRzi08kS8MBuO8QA7pXEgYgY5W8vK3e74xv0lpjo9DbaGU9Rkw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.19.0", + "@eslint/core": "^0.9.0", + "@eslint/eslintrc": "^3.2.0", + "@eslint/js": "9.15.0", + "@eslint/plugin-kit": "^0.2.3", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.1", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.5", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.2.0", + "eslint-visitor-keys": "^4.2.0", + "espree": "^10.3.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-react": { + "version": "7.37.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.2.tgz", + "integrity": "sha512-EsTAnj9fLVr/GZleBLFbj/sSuXeWmp1eXIN60ceYnZveqEaUCyW4X+Vh4WTdUhCkW4xutXYqTXCUSyqD4rB75w==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-includes": "^3.1.8", + "array.prototype.findlast": "^1.2.5", + "array.prototype.flatmap": "^1.3.2", + "array.prototype.tosorted": "^1.1.4", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.1.0", + "estraverse": "^5.3.0", + "hasown": "^2.0.2", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.8", + "object.fromentries": "^2.0.8", + "object.values": "^1.2.0", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.5", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.11", + "string.prototype.repeat": "^1.0.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" + } + }, + "node_modules/eslint-plugin-react/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint-plugin-react/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint-plugin-react/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-scope": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz", + "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint/node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/eslint/node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/eslint/node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/espree": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", + "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.14.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", @@ -5773,6 +6797,42 @@ "node": ">=4" } }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", @@ -5919,7 +6979,14 @@ "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==", - "optional": true + "devOptional": true + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" }, "node_modules/fast-levenshtein": { "version": "2.0.6", @@ -5970,6 +7037,19 @@ "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==", "license": "MIT" }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/file-uri-to-path": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-2.0.0.tgz", @@ -6028,6 +7108,23 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "license": "MIT" }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/firebase-admin": { "version": "12.6.0", "resolved": "https://registry.npmjs.org/firebase-admin/-/firebase-admin-12.6.0.tgz", @@ -6052,11 +7149,32 @@ "@google-cloud/storage": "^7.7.0" } }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/flat-util": { "version": "1.1.9", "resolved": "https://registry.npmjs.org/flat-util/-/flat-util-1.1.9.tgz", "integrity": "sha512-BOTMw/6rbbxVjv5JQvwgGMc2/6wWGd2VeyTvnzvvE49VRjS0tTxLbry/QVP1yPw8SaAOBYsnixmzruXoqjdUHA==" }, + "node_modules/flatted": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.2.tgz", + "integrity": "sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==", + "dev": true, + "license": "ISC" + }, "node_modules/fn.name": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", @@ -6081,6 +7199,16 @@ } } }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.1.3" + } + }, "node_modules/foreground-child": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.2.1.tgz", @@ -6221,12 +7349,41 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/function.prototype.name": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/functional-red-black-tree": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==", "optional": true }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/gauge": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", @@ -6353,6 +7510,24 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/get-symbol-description": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", + "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/get-uri": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-3.0.2.tgz", @@ -6391,6 +7566,19 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/glob/node_modules/minimatch": { "version": "10.0.1", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz", @@ -6406,12 +7594,33 @@ } }, "node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "version": "15.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.12.0.tgz", + "integrity": "sha512-1+gLErljJFhbOVyaetcwJiJ4+eLe45S2E7P5UiZ9xGfeq3ATQf5DOv9G7MH3gGbKQLkzmNh2DxfZwLdw+j6oTQ==", "dev": true, + "license": "MIT", "engines": { - "node": ">=4" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/google-auth-library": { @@ -6532,6 +7741,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -6576,6 +7795,22 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/has-unicode": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", @@ -6711,6 +7946,43 @@ ], "license": "BSD-3-Clause" }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -6742,6 +8014,21 @@ "node": ">=8" } }, + "node_modules/internal-slot": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.0", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/intuit-oauth": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/intuit-oauth/-/intuit-oauth-4.1.2.tgz", @@ -6796,11 +8083,135 @@ "node": ">= 0.10" } }, + "node_modules/is-array-buffer": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "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/is-async-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", + "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", + "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", + "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-docker": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", @@ -6816,6 +8227,29 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-finalizationregistry": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz", + "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -6824,6 +8258,123 @@ "node": ">=8" } }, + "node_modules/is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", @@ -6835,6 +8386,97 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "which-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.3.tgz", + "integrity": "sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-wsl": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", @@ -6857,6 +8499,23 @@ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" }, + "node_modules/iterator.prototype": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.3.tgz", + "integrity": "sha512-FW5iMbeQ6rBGm/oKgzq2aW4KvAGpxPzYES8N4g4xNXUKpL1mclMvOe+76AcLDTvD+Ze+sOpVhgdAQEKF4L9iGQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.2.1", + "get-intrinsic": "^1.2.1", + "has-symbols": "^1.0.3", + "reflect.getprototypeof": "^1.0.4", + "set-function-name": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/jackspeak": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.0.1.tgz", @@ -6992,6 +8651,27 @@ "bignumber.js": "^9.0.0" } }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, "node_modules/json11": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/json11/-/json11-1.1.2.tgz", @@ -7048,6 +8728,22 @@ "safe-buffer": "^5.0.1" } }, + "node_modules/jsx-ast-utils": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" + }, + "engines": { + "node": ">=4.0" + } + }, "node_modules/jwa": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz", @@ -7085,6 +8781,16 @@ "safe-buffer": "^5.0.1" } }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, "node_modules/kuler": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", @@ -7116,6 +8822,22 @@ "pick-util": "^1.1.5" } }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", @@ -7198,6 +8920,13 @@ "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, "node_modules/lodash.once": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", @@ -7226,6 +8955,19 @@ "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==", "optional": true }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, "node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -7471,6 +9213,13 @@ "resolved": "https://registry.npmjs.org/nan/-/nan-2.18.0.tgz", "integrity": "sha512-W7tfG7vMOGtD30sHoZSSc/JVYiyDPEyQVso/Zz+/uQd0B0L46gtC+pHha5FFMRpil6fm/AoEcRWyOVi4+E/f8w==" }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, "node_modules/negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", @@ -7624,9 +9373,9 @@ } }, "node_modules/object-inspect": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", - "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", + "version": "1.13.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz", + "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==", "license": "MIT", "engines": { "node": ">= 0.4" @@ -7635,6 +9384,87 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.entries": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz", + "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.values": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", + "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", @@ -7706,7 +9536,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "optional": true, + "devOptional": true, "dependencies": { "yocto-queue": "^0.1.0" }, @@ -7717,6 +9547,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/pac-proxy-agent": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-5.0.0.tgz", @@ -7754,6 +9600,19 @@ "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==" }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/parse5": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", @@ -7786,6 +9645,16 @@ "node": ">= 0.8" } }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", @@ -7802,6 +9671,13 @@ "node": ">=8" } }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, "node_modules/path-scurry": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz", @@ -7848,6 +9724,16 @@ "@jonkemp/package-utils": "^1.0.8" } }, + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", @@ -7905,6 +9791,18 @@ "node": ">= 4" } }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dev": true, + "license": "MIT", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, "node_modules/proto3-json-serializer": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/proto3-json-serializer/-/proto3-json-serializer-2.0.2.tgz", @@ -7994,6 +9892,16 @@ "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==" }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/q": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", @@ -8071,6 +9979,13 @@ "node": ">= 0.8" } }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true, + "license": "MIT" + }, "node_modules/readable-stream": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", @@ -8127,12 +10042,53 @@ "node": ">=4" } }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz", + "integrity": "sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.1", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "globalthis": "^1.0.3", + "which-builtin-type": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/regenerator-runtime": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz", "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==", "dev": true }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.3.tgz", + "integrity": "sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/remote-content": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/remote-content/-/remote-content-3.0.1.tgz", @@ -8157,6 +10113,34 @@ "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" }, + "node_modules/resolve": { + "version": "2.0.0-next.5", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", + "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/retry": { "version": "0.13.1", "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", @@ -8217,11 +10201,55 @@ "tslib": "^2.1.0" } }, + "node_modules/safe-array-concat": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", + "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-array-concat/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true, + "license": "MIT" + }, "node_modules/safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, + "node_modules/safe-regex-test": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", + "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-regex": "^1.1.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/safe-stable-stringify": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", @@ -8362,6 +10390,22 @@ "node": ">= 0.4" } }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -8877,6 +10921,96 @@ "node": ">=8" } }, + "node_modules/string.prototype.matchall": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz", + "integrity": "sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.7", + "regexp.prototype.flags": "^1.5.2", + "set-function-name": "^2.0.2", + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.repeat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", + "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", + "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", + "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -8908,6 +11042,19 @@ "node": ">=4" } }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/strnum": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", @@ -9004,6 +11151,19 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/tar": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", @@ -9262,6 +11422,83 @@ "node": ">= 0.6" } }, + "node_modules/typed-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", + "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", + "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", @@ -9287,6 +11524,22 @@ "node": ">= 4.0.0" } }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/undici-types": { "version": "6.18.2", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.18.2.tgz", @@ -9309,6 +11562,16 @@ "node": ">= 0.8" } }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, "node_modules/url-join": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", @@ -9429,6 +11692,96 @@ "node": ">= 8" } }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.4.tgz", + "integrity": "sha512-bppkmBSsHFmIMSl8BO9TbsyzsvGjVoppt8xUiGzwiu/bhDCGxnpOKCxgqj6GuyHE0mINMDecBFPlOm2hzY084w==", + "dev": true, + "license": "MIT", + "dependencies": { + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.0.5", + "is-finalizationregistry": "^1.0.2", + "is-generator-function": "^1.0.10", + "is-regex": "^1.1.4", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.15" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true, + "license": "MIT" + }, + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/wide-align": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", @@ -9700,7 +12053,7 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "optional": true, + "devOptional": true, "engines": { "node": ">=10" }, diff --git a/package.json b/package.json index f51af45b5..39ee7592b 100644 --- a/package.json +++ b/package.json @@ -73,8 +73,12 @@ "xmlbuilder2": "^3.1.1" }, "devDependencies": { + "@eslint/js": "^9.15.0", "@trivago/prettier-plugin-sort-imports": "^4.3.0", "concurrently": "^8.2.2", + "eslint": "^9.15.0", + "eslint-plugin-react": "^7.37.2", + "globals": "^15.12.0", "prettier": "^3.3.3", "source-map-explorer": "^2.5.2" } diff --git a/server.js b/server.js index f98ec67da..cd4a8064f 100644 --- a/server.js +++ b/server.js @@ -48,10 +48,6 @@ const SOCKETIO_CORS_ORIGIN = [ "https://www.beta.test.imex.online", "https://beta.imex.online", "https://www.beta.imex.online", - "https://www.test.promanager.web-est.com", - "https://test.promanager.web-est.com", - "https://www.promanager.web-est.com", - "https://promanager.web-est.com", "https://old.imex.online", "https://www.old.imex.online", "https://wsadmin.imex.online", diff --git a/server/accounting/qb-receivables-lines.js b/server/accounting/qb-receivables-lines.js index 043dc8e89..df653e07f 100644 --- a/server/accounting/qb-receivables-lines.js +++ b/server/accounting/qb-receivables-lines.js @@ -4,8 +4,7 @@ const Dinero = require("dinero.js"); const InstanceManager = require("../utils/instanceMgr").default; const { DiscountNotAlreadyCounted } = InstanceManager({ imex: require("../job/job-totals"), - rome: require("../job/job-totals-USA"), - promanager: "USE_ROME" + rome: require("../job/job-totals-USA") }); const logger = require("../utils/logger"); @@ -554,7 +553,7 @@ exports.default = function ({ bodyshop, jobs_by_pk, qbo = false, items, taxCodes const state_tax = Dinero(job_totals.totals.state_tax); const local_tax = Dinero(job_totals.totals.local_tax); - const RulesetToUse = InstanceManager({ imex: "CANADA", rome: "US", promanager: "US" }); + const RulesetToUse = InstanceManager({ imex: "CANADA", rome: "US" }); if (RulesetToUse === "CANADA") { if (federal_tax.getAmount() > 0) { diff --git a/server/cdk/cdk-calculate-allocations.js b/server/cdk/cdk-calculate-allocations.js index f78c48b91..6f66d4c6f 100644 --- a/server/cdk/cdk-calculate-allocations.js +++ b/server/cdk/cdk-calculate-allocations.js @@ -12,8 +12,7 @@ const _ = require("lodash"); const InstanceManager = require("../utils/instanceMgr").default; const { DiscountNotAlreadyCounted } = InstanceManager({ imex: require("../job/job-totals"), - rome: require("../job/job-totals-USA"), - promanager: "USE_ROME" + rome: require("../job/job-totals-USA") }); exports.defaultRoute = async function (req, res) { diff --git a/server/email/generateTemplate.js b/server/email/generateTemplate.js index 7168d435e..9d2815851 100644 --- a/server/email/generateTemplate.js +++ b/server/email/generateTemplate.js @@ -14,8 +14,7 @@ const { header, end, start } = require("./html"); const defaultFooter = () => { return RenderInstanceManager({ imex: "ImEX Online Collision Repair Management System", - rome: "Rome Technologies", - promanager: "ProManager" + rome: "Rome Technologies" }); }; diff --git a/server/email/sendemail.js b/server/email/sendemail.js index 9d103ef81..48fa94968 100644 --- a/server/email/sendemail.js +++ b/server/email/sendemail.js @@ -53,8 +53,7 @@ const sendServerEmail = async ({ subject, text }) => { { from: InstanceManager({ imex: `ImEX Online API - ${process.env.NODE_ENV} `, - rome: `Rome Online API - ${process.env.NODE_ENV} `, - promanager: `ProManager API - ${process.env.NODE_ENV} ` + rome: `Rome Online API - ${process.env.NODE_ENV} ` }), to: ["patrick@imexsystems.ca", "support@thinkimex.com"], subject: subject, @@ -78,27 +77,13 @@ const sendServerEmail = async ({ subject, text }) => { } }; -const sendProManagerWelcomeEmail = async ({ to, subject, html }) => { - try { - await mailer.sendMail({ - from: `ProManager `, - to, - subject, - html - }); - } catch (error) { - logger.log("server-email-failure", "error", null, null, { error }); - } -}; - const sendTaskEmail = async ({ to, subject, type = "text", html, text, attachments }) => { try { mailer.sendMail( { from: InstanceManager({ imex: `ImEX Online `, - rome: `Rome Online `, - promanager: `ProManager ` + rome: `Rome Online ` }), to: to, subject: subject, @@ -247,8 +232,7 @@ const emailBounce = async (req, res) => { replyTo === InstanceManager({ imex: "noreply@imex.online", - rome: "noreply@romeonline.io", - promanager: "noreply@promanager.web-est.com" + rome: "noreply@romeonline.io" }) ) { res.sendStatus(200); @@ -270,13 +254,11 @@ const emailBounce = async (req, res) => { //bcc: "patrick@snapt.ca", subject: `${InstanceMgr({ imex: "ImEX Online", - rome: "Rome Online", - promanager: "ProManager" + rome: "Rome Online" })} Bounced Email - RE: ${subject}`, text: `${InstanceMgr({ imex: "ImEX Online", - rome: "Rome Online", - promanager: "ProManager" + rome: "Rome Online" })} has tried to deliver an email with the subject: ${subject} to the intended recipients but encountered an error. ${body.bounce?.bouncedRecipients.map( @@ -305,6 +287,5 @@ module.exports = { sendEmail, sendServerEmail, sendTaskEmail, - sendProManagerWelcomeEmail, emailBounce }; diff --git a/server/email/tasksEmails.js b/server/email/tasksEmails.js index c05185b6b..6d787811a 100644 --- a/server/email/tasksEmails.js +++ b/server/email/tasksEmails.js @@ -87,14 +87,7 @@ const formatPriority = (priority) => { const getEndpoints = (bodyshop) => InstanceManager({ imex: process.env?.NODE_ENV === "test" ? "https://test.imex.online" : "https://imex.online", - rome: - bodyshop?.convenient_company === "promanager" - ? process.env?.NODE_ENV === "test" - ? "https//test.promanager.web-est.com" - : "https://promanager.web-est.com" - : process.env?.NODE_ENV === "test" - ? "https//test.romeonline.io" - : "https://romeonline.io" + rome: process.env?.NODE_ENV === "test" ? "https//test.romeonline.io" : "https://romeonline.io" }); const generateTemplateArgs = (title, priority, description, dueDate, bodyshop, job, taskId, dateLine, createdBy) => { @@ -120,10 +113,7 @@ const generateTemplateArgs = (title, priority, description, dueDate, bodyshop, j const sendMail = (type, to, subject, html, taskIds, successCallback, requestInstance) => { const fromEmails = InstanceManager({ imex: "ImEX Online ", - rome: - requestInstance === "promanager" - ? "ProManager " - : "Rome Online " + rome: "Rome Online " }); mailer.sendMail( @@ -239,10 +229,7 @@ const tasksRemindEmail = async (req, res) => { recipientCounts.forEach((recipient) => { const fromEmails = InstanceManager({ imex: "ImEX Online ", - rome: - tasksRequest?.tasks[0].bodyshop.convenient_company === "promanager" - ? "ProManager " - : "Rome Online " + rome: "Rome Online " }); const emailData = { @@ -279,14 +266,7 @@ const tasksRemindEmail = async (req, res) => { else { const endPoints = InstanceManager({ imex: process.env?.NODE_ENV === "test" ? "https://test.imex.online" : "https://imex.online", - rome: - tasksRequest?.tasks[0].bodyshop.convenient_company === "promanager" - ? process.env?.NODE_ENV === "test" - ? "https//test.promanager.web-est.com" - : "https://promanager.web-est.com" - : process.env?.NODE_ENV === "test" - ? "https//test.romeonline.io" - : "https://romeonline.io" + rome: process.env?.NODE_ENV === "test" ? "https//test.romeonline.io" : "https://romeonline.io" }); const allTasks = groupedTasks[recipient.email]; diff --git a/server/firebase/firebase-handler.js b/server/firebase/firebase-handler.js index e24c86174..60b864413 100644 --- a/server/firebase/firebase-handler.js +++ b/server/firebase/firebase-handler.js @@ -57,108 +57,108 @@ const createUser = async (req, res) => { } }; -const sendPromanagerWelcomeEmail = (req, res) => { - const { authid, email } = req.body; +// const sendPromanagerWelcomeEmail = (req, res) => { +// const { authid, email } = req.body; - // Fetch user from Firebase - admin - .auth() - .getUser(authid) - .then((userRecord) => { - if (!userRecord) { - return Promise.reject({ status: 404, message: "User not found in Firebase." }); - } +// // Fetch user from Firebase +// admin +// .auth() +// .getUser(authid) +// .then((userRecord) => { +// if (!userRecord) { +// return Promise.reject({ status: 404, message: "User not found in Firebase." }); +// } - // Fetch user data from the database using GraphQL - return client.request( - ` - query GET_USER_BY_EMAIL($email: String!) { - users(where: { email: { _eq: $email } }) { - email - validemail - associations { - id - shopid - bodyshop { - id - convenient_company - } - } - } - }`, - { email: email.toLowerCase() } - ); - }) - .then((dbUserResult) => { - const dbUser = dbUserResult?.users?.[0]; - if (!dbUser) { - return Promise.reject({ status: 404, message: "User not found in database." }); - } +// // Fetch user data from the database using GraphQL +// return client.request( +// ` +// query GET_USER_BY_EMAIL($email: String!) { +// users(where: { email: { _eq: $email } }) { +// email +// validemail +// associations { +// id +// shopid +// bodyshop { +// id +// convenient_company +// } +// } +// } +// }`, +// { email: email.toLowerCase() } +// ); +// }) +// .then((dbUserResult) => { +// const dbUser = dbUserResult?.users?.[0]; +// if (!dbUser) { +// return Promise.reject({ status: 404, message: "User not found in database." }); +// } - // Validate email before proceeding - if (!dbUser.validemail) { - logger.log("admin-send-welcome-email-skip", "debug", req.user.email, null, { - message: "User email is not valid, skipping email.", - email - }); - return res.status(200).json({ message: "User email is not valid, email not sent." }); - } +// // Validate email before proceeding +// if (!dbUser.validemail) { +// logger.log("admin-send-welcome-email-skip", "debug", req.user.email, null, { +// message: "User email is not valid, skipping email.", +// email +// }); +// return res.status(200).json({ message: "User email is not valid, email not sent." }); +// } - // Check if the user's company is ProManager - const convenientCompany = dbUser.associations?.[0]?.bodyshop?.convenient_company; - if (convenientCompany !== "promanager") { - logger.log("admin-send-welcome-email-skip", "debug", req.user.email, null, { - message: 'convenient_company is not "promanager", skipping email.', - convenientCompany - }); - return res.status(200).json({ message: `convenient_company is not "promanager", email not sent.` }); - } +// // Check if the user's company is ProManager +// const convenientCompany = dbUser.associations?.[0]?.bodyshop?.convenient_company; +// if (convenientCompany !== "promanager") { +// logger.log("admin-send-welcome-email-skip", "debug", req.user.email, null, { +// message: 'convenient_company is not "promanager", skipping email.', +// convenientCompany +// }); +// return res.status(200).json({ message: `convenient_company is not "promanager", email not sent.` }); +// } - // Generate password reset link - return admin - .auth() - .generatePasswordResetLink(dbUser.email) - .then((resetLink) => ({ dbUser, resetLink })); - }) - .then(({ dbUser, resetLink }) => { - // Send welcome email (replace with your actual email-sending service) - return sendProManagerWelcomeEmail({ - to: dbUser.email, - subject: "Welcome to the ProManager platform.", - html: generateEmailTemplate({ - header: "", - subHeader: "", - body: ` -

Welcome to the ProManager platform. Please click the link below to reset your password:

-

Reset your password

-

User Details:

-
    -
  • Email: ${dbUser.email}
  • -
- ` - }) - }); - }) - .then(() => { - // Log success and return response - logger.log("admin-send-welcome-email", "debug", req.user.email, null, { - request: req.body, - ioadmin: true, - emailSentTo: email - }); - res.status(200).json({ message: "Welcome email sent successfully." }); - }) - .catch((error) => { - logger.log("admin-send-welcome-email-error", "ERROR", req.user.email, null, { error }); +// // Generate password reset link +// return admin +// .auth() +// .generatePasswordResetLink(dbUser.email) +// .then((resetLink) => ({ dbUser, resetLink })); +// }) +// .then(({ dbUser, resetLink }) => { +// // Send welcome email (replace with your actual email-sending service) +// return sendProManagerWelcomeEmail({ +// to: dbUser.email, +// subject: "Welcome to the ProManager platform.", +// html: generateEmailTemplate({ +// header: "", +// subHeader: "", +// body: ` +//

Welcome to the ProManager platform. Please click the link below to reset your password:

+//

Reset your password

+//

User Details:

+//
    +//
  • Email: ${dbUser.email}
  • +//
+// ` +// }) +// }); +// }) +// .then(() => { +// // Log success and return response +// logger.log("admin-send-welcome-email", "debug", req.user.email, null, { +// request: req.body, +// ioadmin: true, +// emailSentTo: email +// }); +// res.status(200).json({ message: "Welcome email sent successfully." }); +// }) +// .catch((error) => { +// logger.log("admin-send-welcome-email-error", "ERROR", req.user.email, null, { error }); - if (!res.headersSent) { - res.status(error.status || 500).json({ - message: error.message || "Error sending welcome email.", - error - }); - } - }); -}; +// if (!res.headersSent) { +// res.status(error.status || 500).json({ +// message: error.message || "Error sending welcome email.", +// error +// }); +// } +// }); +// }; const updateUser = (req, res) => { logger.log("admin-update-user", "debug", req.user.email, null, { diff --git a/server/utils/instanceMgr.js b/server/utils/instanceMgr.js index 6a01e6904..fceb2c786 100644 --- a/server/utils/instanceMgr.js +++ b/server/utils/instanceMgr.js @@ -10,7 +10,11 @@ function InstanceManager({ args, instance, debug, executeFunction, rome, promanager, imex }) { let propToReturn = null; - + + //TODO: Remove after debugging. + if (promanager) { + console.trace("ProManager Prop was used"); + } switch (instance || process.env.INSTANCE) { case "IMEX": propToReturn = imex; From 8ad1dd83c6e21936580475a616ace4d875679292 Mon Sep 17 00:00:00 2001 From: Allan Carr Date: Thu, 21 Nov 2024 14:24:31 -0800 Subject: [PATCH 305/478] IO-3027 Datapump Refactor Remove Batch and sftp transfer for each shop during processing Signed-off-by: Allan Carr --- server/data/autohouse.js | 99 ++++++++++++++++++++------------------- server/data/claimscorp.js | 99 ++++++++++++++++++++------------------- server/data/kaizen.js | 98 +++++++++++++++++++------------------- 3 files changed, 152 insertions(+), 144 deletions(-) diff --git a/server/data/autohouse.js b/server/data/autohouse.js index 1384771e6..19078c274 100644 --- a/server/data/autohouse.js +++ b/server/data/autohouse.js @@ -25,17 +25,15 @@ const ftpSetup = { port: process.env.AUTOHOUSE_PORT, username: process.env.AUTOHOUSE_USER, password: process.env.AUTOHOUSE_PASSWORD, - debug: process.env.NODE_ENV !== "production" - ? (message, ...data) => logger.log(message, "DEBUG", "api", null, data) - : () => {}, + debug: + process.env.NODE_ENV !== "production" + ? (message, ...data) => logger.log(message, "DEBUG", "api", null, data) + : () => {}, algorithms: { serverHostKey: ["ssh-rsa", "ssh-dss", "rsa-sha2-256", "rsa-sha2-512", "ecdsa-sha2-nistp256", "ecdsa-sha2-nistp384"] } }; -const allxmlsToUpload = []; -const allErrors = []; - exports.default = async (req, res) => { // Only process if in production environment. if (process.env.NODE_ENV !== "production") { @@ -57,12 +55,13 @@ exports.default = async (req, res) => { try { logger.log("autohouse-start", "DEBUG", "api", null, null); + const allXMLResults = []; + const allErrors = []; + const { bodyshops } = await client.request(queries.GET_AUTOHOUSE_SHOPS); //Query for the List of Bodyshop Clients. const specificShopIds = req.body.bodyshopIds; // ['uuid]; const { start, end, skipUpload } = req.body; //YYYY-MM-DD - const batchSize = 10; - const shopsToProcess = specificShopIds?.length > 0 ? bodyshops.filter((shop) => specificShopIds.includes(shop.id)) : bodyshops; logger.log("autohouse-shopsToProcess-generated", "DEBUG", "api", null, null); @@ -71,27 +70,18 @@ exports.default = async (req, res) => { logger.log("autohouse-shopsToProcess-empty", "DEBUG", "api", null, null); return; } - const batchPromises = []; - for (let i = 0; i < shopsToProcess.length; i += batchSize) { - const batch = shopsToProcess.slice(i, i + batchSize); - const batchPromise = (async () => { - await processBatch(batch, start, end); - if (skipUpload) { - for (const xmlObj of allxmlsToUpload) { - fs.writeFileSync(`./logs/${xmlObj.filename}`, xmlObj.xml); - } - } else { - await uploadViaSFTP(allxmlsToUpload); - } - })(); - batchPromises.push(batchPromise); - } - await Promise.all(batchPromises); + await processShopData(shopsToProcess, start, end, skipUpload, allXMLResults, allErrors); + await sendServerEmail({ subject: `Autohouse Report ${moment().format("MM-DD-YY")}`, text: `Errors:\n${JSON.stringify(allErrors, null, 2)}\n\nUploaded:\n${JSON.stringify( - allxmlsToUpload.map((x) => ({ filename: x.filename, count: x.count, result: x.result })), + allXMLResults.map((x) => ({ + imexshopid: x.imexshopid, + filename: x.filename, + count: x.count, + result: x.result + })), null, 2 )}` @@ -103,8 +93,8 @@ exports.default = async (req, res) => { } }; -async function processBatch(batch, start, end) { - for (const bodyshop of batch) { +async function processShopData(shopsToProcess, start, end, skipUpload, allXMLResults, allErrors) { + for (const bodyshop of shopsToProcess) { const erroredJobs = []; try { logger.log("autohouse-start-shop-extract", "DEBUG", "api", bodyshop.id, { @@ -134,12 +124,26 @@ async function processBatch(batch, start, end) { }); } - const ret = builder.create({}, autoHouseObject).end({ allowEmptyTags: true }); + const xmlObj = { + imexshopid: bodyshop.imexshopid, + xml: builder.create({}, autoHouseObject).end({ allowEmptyTags: true }), + filename: `IM_${bodyshop.autohouseid}_${moment().format("DDMMYYYY_HHMMss")}.xml`, + count: autoHouseObject.AutoHouseExport.RepairOrder.length + }; - allxmlsToUpload.push({ - count: autoHouseObject.AutoHouseExport.RepairOrder.length, - xml: ret, - filename: `IM_${bodyshop.autohouseid}_${moment().format("DDMMYYYY_HHMMss")}.xml` + if (skipUpload) { + fs.writeFileSync(`./logs/${xmlObj.filename}`, xmlObj.xml); + } else { + await uploadViaSFTP(xmlObj); + } + + allXMLResults.push({ + bodyshopid: bodyshop.id, + imexshopid: bodyshop.imexshopid, + autohouseid: bodyshop.autohouseid, + count: xmlObj.count, + filename: xmlObj.filename, + result: xmlObj.result }); logger.log("autohouse-end-shop-extract", "DEBUG", "api", bodyshop.id, { @@ -171,7 +175,7 @@ async function processBatch(batch, start, end) { } } -async function uploadViaSFTP(allxmlsToUpload) { +async function uploadViaSFTP(xmlObj) { const sftp = new Client(); sftp.on("error", (errors) => logger.log("autohouse-sftp-connection-error", "ERROR", "api", null, { error: errors.message, stack: errors.stack }) @@ -180,21 +184,20 @@ async function uploadViaSFTP(allxmlsToUpload) { //Connect to the FTP and upload all. await sftp.connect(ftpSetup); - for (const xmlObj of allxmlsToUpload) { - try { - xmlObj.result = await sftp.put(Buffer.from(xmlObj.xml), `${xmlObj.filename}`); - logger.log("autohouse-sftp-upload", "DEBUG", "api", null, { - filename: xmlObj.filename, - result: xmlObj.result - }); - } catch (error) { - logger.log("autohouse-sftp-upload-error", "ERROR", "api", null, { - filename: xmlObj.filename, - error: error.message, - stack: error.stack - }); - throw error; - } + try { + xmlObj.result = await sftp.put(Buffer.from(xmlObj.xml), `${xmlObj.filename}`); + logger.log("autohouse-sftp-upload", "DEBUG", "api", null, { + imexshopid: xmlObj.imexshopid, + filename: xmlObj.filename, + result: xmlObj.result + }); + } catch (error) { + logger.log("autohouse-sftp-upload-error", "ERROR", "api", null, { + filename: xmlObj.filename, + error: error.message, + stack: error.stack + }); + throw error; } } catch (error) { logger.log("autohouse-sftp-error", "ERROR", "api", null, { error: error.message, stack: error.stack }); diff --git a/server/data/claimscorp.js b/server/data/claimscorp.js index b8c77a018..3db09cbcf 100644 --- a/server/data/claimscorp.js +++ b/server/data/claimscorp.js @@ -24,17 +24,15 @@ const ftpSetup = { port: process.env.CLAIMSCORP_PORT, username: process.env.CLAIMSCORP_USER, password: process.env.CLAIMSCORP_PASSWORD, - debug: process.env.NODE_ENV !== "production" - ? (message, ...data) => logger.log(message, "DEBUG", "api", null, data) - : () => {}, + debug: + process.env.NODE_ENV !== "production" + ? (message, ...data) => logger.log(message, "DEBUG", "api", null, data) + : () => {}, algorithms: { serverHostKey: ["ssh-rsa", "ssh-dss", "rsa-sha2-256", "rsa-sha2-512", "ecdsa-sha2-nistp256", "ecdsa-sha2-nistp384"] } }; -const allxmlsToUpload = []; -const allErrors = []; - exports.default = async (req, res) => { // Only process if in production environment. if (process.env.NODE_ENV !== "production") { @@ -56,12 +54,13 @@ exports.default = async (req, res) => { try { logger.log("claimscorp-start", "DEBUG", "api", null, null); + const allXMLResults = []; + const allErrors = []; + const { bodyshops } = await client.request(queries.GET_CLAIMSCORP_SHOPS); //Query for the List of Bodyshop Clients. const specificShopIds = req.body.bodyshopIds; // ['uuid]; const { start, end, skipUpload } = req.body; //YYYY-MM-DD - const batchSize = 10; - const shopsToProcess = specificShopIds?.length > 0 ? bodyshops.filter((shop) => specificShopIds.includes(shop.id)) : bodyshops; logger.log("claimscorp-shopsToProcess-generated", "DEBUG", "api", null, null); @@ -70,27 +69,18 @@ exports.default = async (req, res) => { logger.log("claimscorp-shopsToProcess-empty", "DEBUG", "api", null, null); return; } - const batchPromises = []; - for (let i = 0; i < shopsToProcess.length; i += batchSize) { - const batch = shopsToProcess.slice(i, i + batchSize); - const batchPromise = (async () => { - await processBatch(batch, start, end); - if (skipUpload) { - for (const xmlObj of allxmlsToUpload) { - fs.writeFileSync(`./logs/${xmlObj.filename}`, xmlObj.xml); - } - } else { - await uploadViaSFTP(allxmlsToUpload); - } - })(); - batchPromises.push(batchPromise); - } - await Promise.all(batchPromises); + await processShopData(shopsToProcess, start, end, skipUpload, allXMLResults, allErrors); + await sendServerEmail({ subject: `ClaimsCorp Report ${moment().format("MM-DD-YY")}`, text: `Errors:\n${JSON.stringify(allErrors, null, 2)}\n\nUploaded:\n${JSON.stringify( - allxmlsToUpload.map((x) => ({ filename: x.filename, count: x.count, result: x.result })), + allXMLResults.map((x) => ({ + imexshopid: x.imexshopid, + filename: x.filename, + count: x.count, + result: x.result + })), null, 2 )}` @@ -102,8 +92,8 @@ exports.default = async (req, res) => { } }; -async function processBatch(batch, start, end) { - for (const bodyshop of batch) { +async function processShopData(shopsToProcess, start, end, skipUpload, allXMLResults, allErrors) { + for (const bodyshop of shopsToProcess) { const erroredJobs = []; try { logger.log("claimscorp-start-shop-extract", "DEBUG", "api", bodyshop.id, { @@ -137,12 +127,26 @@ async function processBatch(batch, start, end) { }); } - const ret = builder.create({}, claimsCorpObject).end({ allowEmptyTags: true }); + const xmlObj = { + imexshopid: bodyshop.imexshopid, + xml: builder.create({}, claimsCorpObject).end({ allowEmptyTags: true }), + filename: `${bodyshop.claimscorpid}-${moment().format("YYYYMMDDTHHMMss")}.xml`, + count: claimsCorpObject.DataFeed.ShopInfo.RO.length + }; - allxmlsToUpload.push({ - count: claimsCorpObject.DataFeed.ShopInfo.RO.length, - xml: ret, - filename: `${bodyshop.claimscorpid}-${moment().format("YYYYMMDDTHHMMss")}.xml` + if (skipUpload) { + fs.writeFileSync(`./logs/${xmlObj.filename}`, xmlObj.xml); + } else { + await uploadViaSFTP(xmlObj); + } + + allXMLResults.push({ + bodyshopid: bodyshop.id, + imexshopid: bodyshop.imexshopid, + claimscorpid: bodyshop.claimscorpid, + count: xmlObj.count, + filename: xmlObj.filename, + result: xmlObj.result }); logger.log("claimscorp-end-shop-extract", "DEBUG", "api", bodyshop.id, { @@ -174,7 +178,7 @@ async function processBatch(batch, start, end) { } } -async function uploadViaSFTP(allxmlsToUpload) { +async function uploadViaSFTP(xmlObj) { const sftp = new Client(); sftp.on("error", (errors) => logger.log("claimscorp-sftp-connection-error", "ERROR", "api", null, { error: errors.message, stack: errors.stack }) @@ -183,21 +187,20 @@ async function uploadViaSFTP(allxmlsToUpload) { //Connect to the FTP and upload all. await sftp.connect(ftpSetup); - for (const xmlObj of allxmlsToUpload) { - try { - xmlObj.result = await sftp.put(Buffer.from(xmlObj.xml), `${xmlObj.filename}`); - logger.log("claimscorp-sftp-upload", "DEBUG", "api", null, { - filename: xmlObj.filename, - result: xmlObj.result - }); - } catch (error) { - logger.log("claimscorp-sftp-upload-error", "ERROR", "api", null, { - filename: xmlObj.filename, - error: error.message, - stack: error.stack - }); - throw error; - } + try { + xmlObj.result = await sftp.put(Buffer.from(xmlObj.xml), `${xmlObj.filename}`); + logger.log("claimscorp-sftp-upload", "DEBUG", "api", null, { + imexshopid: xmlObj.imexshopid, + filename: xmlObj.filename, + result: xmlObj.result + }); + } catch (error) { + logger.log("claimscorp-sftp-upload-error", "ERROR", "api", null, { + filename: xmlObj.filename, + error: error.message, + stack: error.stack + }); + throw error; } } catch (error) { logger.log("claimscorp-sftp-error", "ERROR", "api", null, { error: error.message, stack: error.stack }); diff --git a/server/data/kaizen.js b/server/data/kaizen.js index bbb758a93..eb6abc056 100644 --- a/server/data/kaizen.js +++ b/server/data/kaizen.js @@ -23,17 +23,15 @@ const ftpSetup = { port: process.env.KAIZEN_PORT, username: process.env.KAIZEN_USER, password: process.env.KAIZEN_PASSWORD, - debug: process.env.NODE_ENV !== "production" - ? (message, ...data) => logger.log(message, "DEBUG", "api", null, data) - : () => {}, + debug: + process.env.NODE_ENV !== "production" + ? (message, ...data) => logger.log(message, "DEBUG", "api", null, data) + : () => {}, algorithms: { serverHostKey: ["ssh-rsa", "ssh-dss", "rsa-sha2-256", "rsa-sha2-512", "ecdsa-sha2-nistp256", "ecdsa-sha2-nistp384"] } }; -const allxmlsToUpload = []; -const allErrors = []; - exports.default = async (req, res) => { // Only process if in production environment. if (process.env.NODE_ENV !== "production") { @@ -55,12 +53,13 @@ exports.default = async (req, res) => { try { logger.log("kaizen-start", "DEBUG", "api", null, null); + const allXMLResults = []; + const allErrors = []; + const { bodyshops } = await client.request(queries.GET_KAIZEN_SHOPS, { imexshopid: kaizenShopsIDs }); //Query for the List of Bodyshop Clients. const specificShopIds = req.body.bodyshopIds; // ['uuid]; const { start, end, skipUpload } = req.body; //YYYY-MM-DD - const batchSize = 10; - const shopsToProcess = specificShopIds?.length > 0 ? bodyshops.filter((shop) => specificShopIds.includes(shop.id)) : bodyshops; logger.log("kaizen-shopsToProcess-generated", "DEBUG", "api", null, null); @@ -69,27 +68,18 @@ exports.default = async (req, res) => { logger.log("kaizen-shopsToProcess-empty", "DEBUG", "api", null, null); return; } - const batchPromises = []; - for (let i = 0; i < shopsToProcess.length; i += batchSize) { - const batch = shopsToProcess.slice(i, i + batchSize); - const batchPromise = (async () => { - await processBatch(batch, start, end); - if (skipUpload) { - for (const xmlObj of allxmlsToUpload) { - fs.writeFileSync(`./logs/${xmlObj.filename}`, xmlObj.xml); - } - } else { - await uploadViaSFTP(allxmlsToUpload); - } - })(); - batchPromises.push(batchPromise); - } - await Promise.all(batchPromises); + await processShopData(shopsToProcess, start, end, skipUpload, allXMLResults, allErrors); + await sendServerEmail({ subject: `Kaizen Report ${moment().format("MM-DD-YY")}`, text: `Errors:\n${JSON.stringify(allErrors, null, 2)}\n\nUploaded:\n${JSON.stringify( - allxmlsToUpload.map((x) => ({ filename: x.filename, count: x.count, result: x.result })), + allXMLResults.map((x) => ({ + imexshopid: x.imexshopid, + filename: x.filename, + count: x.count, + result: x.result + })), null, 2 )}` @@ -101,8 +91,8 @@ exports.default = async (req, res) => { } }; -async function processBatch(batch, start, end) { - for (const bodyshop of batch) { +async function processShopData(shopsToProcess, start, end, skipUpload, allXMLResults, allErrors) { + for (const bodyshop of shopsToProcess) { const erroredJobs = []; try { logger.log("kaizen-start-shop-extract", "DEBUG", "api", bodyshop.id, { @@ -135,12 +125,25 @@ async function processBatch(batch, start, end) { }); } - const ret = builder.create({}, kaizenObject).end({ allowEmptyTags: true }); + const xmlObj = { + imexshopid: bodyshop.imexshopid, + xml: builder.create({}, kaizenObject).end({ allowEmptyTags: true }), + filename: `${bodyshop.shopname}-${moment().format("YYYYMMDDTHHMMss")}.xml`, + count: kaizenObject.DataFeed.ShopInfo.Jobs.length + }; - allxmlsToUpload.push({ - count: kaizenObject.DataFeed.ShopInfo.Jobs.length, - xml: ret, - filename: `${bodyshop.shopname}-${moment().format("YYYYMMDDTHHMMss")}.xml` + if (skipUpload) { + fs.writeFileSync(`./logs/${xmlObj.filename}`, xmlObj.xml); + } else { + await uploadViaSFTP(xmlObj); + } + + allXMLResults.push({ + bodyshopid: bodyshop.id, + imexshopid: bodyshop.imexshopid, + count: xmlObj.count, + filename: xmlObj.filename, + result: xmlObj.result }); logger.log("kaizen-end-shop-extract", "DEBUG", "api", bodyshop.id, { @@ -172,7 +175,7 @@ async function processBatch(batch, start, end) { } } -async function uploadViaSFTP(allxmlsToUpload) { +async function uploadViaSFTP(xmlObj) { const sftp = new Client(); sftp.on("error", (errors) => logger.log("kaizen-sftp-connection-error", "ERROR", "api", null, { error: errors.message, stack: errors.stack }) @@ -181,21 +184,20 @@ async function uploadViaSFTP(allxmlsToUpload) { //Connect to the FTP and upload all. await sftp.connect(ftpSetup); - for (const xmlObj of allxmlsToUpload) { - try { - xmlObj.result = await sftp.put(Buffer.from(xmlObj.xml), `${xmlObj.filename}`); - logger.log("kaizen-sftp-upload", "DEBUG", "api", null, { - filename: xmlObj.filename, - result: xmlObj.result - }); - } catch (error) { - logger.log("kaizen-sftp-upload-error", "ERROR", "api", null, { - filename: xmlObj.filename, - error: error.message, - stack: error.stack - }); - throw error; - } + try { + xmlObj.result = await sftp.put(Buffer.from(xmlObj.xml), `${xmlObj.filename}`); + logger.log("kaizen-sftp-upload", "DEBUG", "api", null, { + imexshopid: xmlObj.imexshopid, + filename: xmlObj.filename, + result: xmlObj.result + }); + } catch (error) { + logger.log("kaizen-sftp-upload-error", "ERROR", "api", null, { + filename: xmlObj.filename, + error: error.message, + stack: error.stack + }); + throw error; } } catch (error) { logger.log("kaizen-sftp-error", "ERROR", "api", null, { error: error.message, stack: error.stack }); From dd4ba8a467ccc01f88426dcbc6f3a9949d09fd0a Mon Sep 17 00:00:00 2001 From: Allan Carr Date: Thu, 21 Nov 2024 14:40:36 -0800 Subject: [PATCH 306/478] IO-2921 Chatter Datapump Adjustment Signed-off-by: Allan Carr --- server/data/chatter.js | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/server/data/chatter.js b/server/data/chatter.js index 282ff6421..8c3f8e634 100644 --- a/server/data/chatter.js +++ b/server/data/chatter.js @@ -17,15 +17,15 @@ const ftpSetup = { port: process.env.CHATTER_PORT, username: process.env.CHATTER_USER, privateKey: null, - debug: (message, ...data) => logger.log(message, "DEBUG", "api", null, data), + debug: + process.env.NODE_ENV !== "production" + ? (message, ...data) => logger.log(message, "DEBUG", "api", null, data) + : () => {}, algorithms: { serverHostKey: ["ssh-rsa", "ssh-dss", "rsa-sha2-256", "rsa-sha2-512", "ecdsa-sha2-nistp256", "ecdsa-sha2-nistp384"] } }; -const allChatterObjects = []; -const allErrors = []; - exports.default = async (req, res) => { // Only process if in production environment. if (process.env.NODE_ENV !== "production") { @@ -47,12 +47,13 @@ exports.default = async (req, res) => { try { logger.log("chatter-start", "DEBUG", "api", null, null); + const allChatterObjects = []; + const allErrors = []; + const { bodyshops } = await client.request(queries.GET_CHATTER_SHOPS); //Query for the List of Bodyshop Clients. const specificShopIds = req.body.bodyshopIds; // ['uuid]; const { start, end, skipUpload } = req.body; //YYYY-MM-DD - const batchSize = 10; - const shopsToProcess = specificShopIds?.length > 0 ? bodyshops.filter((shop) => specificShopIds.includes(shop.id)) : bodyshops; logger.log("chatter-shopsToProcess-generated", "DEBUG", "api", null, null); @@ -62,16 +63,14 @@ exports.default = async (req, res) => { return; } - for (let i = 0; i < shopsToProcess.length; i += batchSize) { - const batch = shopsToProcess.slice(i, i + batchSize); - await processBatch(batch, start, end); - } + await processBatch(shopsToProcess, start, end, allChatterObjects, allErrors); const csvToUpload = { count: allChatterObjects.length, csv: converter.json2csv(allChatterObjects, { emptyFieldValue: "" }), filename: `IMEX_ONLINE_solicitation_${moment().format("YYYYMMDD")}.csv` }; + if (skipUpload) { await fs.promises.writeFile(`./logs/${csvToUpload.filename}`, csvToUpload.csv); } else { @@ -90,8 +89,8 @@ exports.default = async (req, res) => { } }; -async function processBatch(batch, start, end) { - for (const bodyshop of batch) { +async function processBatch(shopsToProcess, start, end, allChatterObjects, allErrors) { + for (const bodyshop of shopsToProcess) { try { logger.log("chatter-start-shop-extract", "DEBUG", "api", bodyshop.id, { shopname: bodyshop.shopname From cd592b671c68370c1017ff7f415d031b643944b9 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Thu, 21 Nov 2024 15:05:52 -0800 Subject: [PATCH 307/478] feature/IO-3000-messaging-sockets-migrations2 - - Checkpoint, Signed-off-by: Dave Richer --- .../registerMessagingSocketHandlers.js | 10 +++++++++- client/src/graphql/conversations.queries.js | 18 +++++++++++++++++- server/sms/receive.js | 3 ++- 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/client/src/components/chat-affix/registerMessagingSocketHandlers.js b/client/src/components/chat-affix/registerMessagingSocketHandlers.js index 325770541..b50d02c8a 100644 --- a/client/src/components/chat-affix/registerMessagingSocketHandlers.js +++ b/client/src/components/chat-affix/registerMessagingSocketHandlers.js @@ -22,6 +22,7 @@ export const registerMessagingHandlers = ({ socket, client }) => { query: CONVERSATION_LIST_QUERY, variables: { offset: 0 } }); + client.cache.writeQuery({ query: CONVERSATION_LIST_QUERY, variables: { offset: 0 }, @@ -49,7 +50,14 @@ export const registerMessagingHandlers = ({ socket, client }) => { id: conversationId }), fields: { - updated_at: () => new Date(), + updated_at: () => new Date().toISOString(), + archived(cached) { + // Unarchive the conversation if it was previously marked as archived + if (cached) { + return false; + } + return cached; + }, messages_aggregate(cached) { // Increment unread count only if the message is inbound if (!isoutbound) { diff --git a/client/src/graphql/conversations.queries.js b/client/src/graphql/conversations.queries.js index e05a474ab..03bc0426b 100644 --- a/client/src/graphql/conversations.queries.js +++ b/client/src/graphql/conversations.queries.js @@ -90,9 +90,25 @@ export const CONVERSATION_ID_BY_PHONE = gql` query CONVERSATION_ID_BY_PHONE($phone: String!) { conversations(where: { phone_num: { _eq: $phone } }) { id + phone_num + archived + label + unreadcnt job_conversations { jobid - id + conversationid + job { + id + ownr_fn + ownr_ln + ownr_co_nm + ro_number + } + } + messages_aggregate(where: { read: { _eq: false }, isoutbound: { _eq: false } }) { + aggregate { + count + } } } } diff --git a/server/sms/receive.js b/server/sms/receive.js index 3fb721eec..f7f41652e 100644 --- a/server/sms/receive.js +++ b/server/sms/receive.js @@ -54,7 +54,8 @@ exports.receive = async (req, res) => { newMessage.conversation = { data: { bodyshopid: bodyshop.id, - phone_num: phone(req.body.From).phoneNumber + phone_num: phone(req.body.From).phoneNumber, + archived: false } }; From e202bf9a8966626cdf050d96c94ded2ab2a17e87 Mon Sep 17 00:00:00 2001 From: Allan Carr Date: Thu, 21 Nov 2024 16:18:23 -0800 Subject: [PATCH 308/478] IO-3027 Add in bodyshop.id to logging in SFTP Signed-off-by: Allan Carr --- server/data/autohouse.js | 12 ++++++++---- server/data/claimscorp.js | 15 +++++++++++---- server/data/kaizen.js | 12 ++++++++---- 3 files changed, 27 insertions(+), 12 deletions(-) diff --git a/server/data/autohouse.js b/server/data/autohouse.js index 19078c274..81679522b 100644 --- a/server/data/autohouse.js +++ b/server/data/autohouse.js @@ -125,6 +125,7 @@ async function processShopData(shopsToProcess, start, end, skipUpload, allXMLRes } const xmlObj = { + bodyshopid: bodyshop.id, imexshopid: bodyshop.imexshopid, xml: builder.create({}, autoHouseObject).end({ allowEmptyTags: true }), filename: `IM_${bodyshop.autohouseid}_${moment().format("DDMMYYYY_HHMMss")}.xml`, @@ -178,7 +179,10 @@ async function processShopData(shopsToProcess, start, end, skipUpload, allXMLRes async function uploadViaSFTP(xmlObj) { const sftp = new Client(); sftp.on("error", (errors) => - logger.log("autohouse-sftp-connection-error", "ERROR", "api", null, { error: errors.message, stack: errors.stack }) + logger.log("autohouse-sftp-connection-error", "ERROR", "api", xmlObj.bodyshopid, { + error: errors.message, + stack: errors.stack + }) ); try { //Connect to the FTP and upload all. @@ -186,13 +190,13 @@ async function uploadViaSFTP(xmlObj) { try { xmlObj.result = await sftp.put(Buffer.from(xmlObj.xml), `${xmlObj.filename}`); - logger.log("autohouse-sftp-upload", "DEBUG", "api", null, { + logger.log("autohouse-sftp-upload", "DEBUG", "api", xmlObj.bodyshopid, { imexshopid: xmlObj.imexshopid, filename: xmlObj.filename, result: xmlObj.result }); } catch (error) { - logger.log("autohouse-sftp-upload-error", "ERROR", "api", null, { + logger.log("autohouse-sftp-upload-error", "ERROR", "api", xmlObj.bodyshopid, { filename: xmlObj.filename, error: error.message, stack: error.stack @@ -200,7 +204,7 @@ async function uploadViaSFTP(xmlObj) { throw error; } } catch (error) { - logger.log("autohouse-sftp-error", "ERROR", "api", null, { error: error.message, stack: error.stack }); + logger.log("autohouse-sftp-error", "ERROR", "api", xmlObj.bodyshopid, { error: error.message, stack: error.stack }); throw error; } finally { sftp.end(); diff --git a/server/data/claimscorp.js b/server/data/claimscorp.js index 3db09cbcf..70737bd03 100644 --- a/server/data/claimscorp.js +++ b/server/data/claimscorp.js @@ -128,6 +128,7 @@ async function processShopData(shopsToProcess, start, end, skipUpload, allXMLRes } const xmlObj = { + bodyshopid: bodyshop.id, imexshopid: bodyshop.imexshopid, xml: builder.create({}, claimsCorpObject).end({ allowEmptyTags: true }), filename: `${bodyshop.claimscorpid}-${moment().format("YYYYMMDDTHHMMss")}.xml`, @@ -181,7 +182,10 @@ async function processShopData(shopsToProcess, start, end, skipUpload, allXMLRes async function uploadViaSFTP(xmlObj) { const sftp = new Client(); sftp.on("error", (errors) => - logger.log("claimscorp-sftp-connection-error", "ERROR", "api", null, { error: errors.message, stack: errors.stack }) + logger.log("claimscorp-sftp-connection-error", "ERROR", "api", xmlObj.bodyshopid, { + error: errors.message, + stack: errors.stack + }) ); try { //Connect to the FTP and upload all. @@ -189,13 +193,13 @@ async function uploadViaSFTP(xmlObj) { try { xmlObj.result = await sftp.put(Buffer.from(xmlObj.xml), `${xmlObj.filename}`); - logger.log("claimscorp-sftp-upload", "DEBUG", "api", null, { + logger.log("claimscorp-sftp-upload", "DEBUG", "api", xmlObj.bodyshopid, { imexshopid: xmlObj.imexshopid, filename: xmlObj.filename, result: xmlObj.result }); } catch (error) { - logger.log("claimscorp-sftp-upload-error", "ERROR", "api", null, { + logger.log("claimscorp-sftp-upload-error", "ERROR", "api", xmlObj.bodyshopid, { filename: xmlObj.filename, error: error.message, stack: error.stack @@ -203,7 +207,10 @@ async function uploadViaSFTP(xmlObj) { throw error; } } catch (error) { - logger.log("claimscorp-sftp-error", "ERROR", "api", null, { error: error.message, stack: error.stack }); + logger.log("claimscorp-sftp-error", "ERROR", "api", xmlObj.bodyshopid, { + error: error.message, + stack: error.stack + }); throw error; } finally { sftp.end(); diff --git a/server/data/kaizen.js b/server/data/kaizen.js index eb6abc056..a7a6aaf91 100644 --- a/server/data/kaizen.js +++ b/server/data/kaizen.js @@ -126,6 +126,7 @@ async function processShopData(shopsToProcess, start, end, skipUpload, allXMLRes } const xmlObj = { + bodyshopid: bodyshop.id, imexshopid: bodyshop.imexshopid, xml: builder.create({}, kaizenObject).end({ allowEmptyTags: true }), filename: `${bodyshop.shopname}-${moment().format("YYYYMMDDTHHMMss")}.xml`, @@ -178,7 +179,10 @@ async function processShopData(shopsToProcess, start, end, skipUpload, allXMLRes async function uploadViaSFTP(xmlObj) { const sftp = new Client(); sftp.on("error", (errors) => - logger.log("kaizen-sftp-connection-error", "ERROR", "api", null, { error: errors.message, stack: errors.stack }) + logger.log("kaizen-sftp-connection-error", "ERROR", "api", xmlObj.bodyshopid, { + error: errors.message, + stack: errors.stack + }) ); try { //Connect to the FTP and upload all. @@ -186,13 +190,13 @@ async function uploadViaSFTP(xmlObj) { try { xmlObj.result = await sftp.put(Buffer.from(xmlObj.xml), `${xmlObj.filename}`); - logger.log("kaizen-sftp-upload", "DEBUG", "api", null, { + logger.log("kaizen-sftp-upload", "DEBUG", "api", xmlObj.bodyshopid, { imexshopid: xmlObj.imexshopid, filename: xmlObj.filename, result: xmlObj.result }); } catch (error) { - logger.log("kaizen-sftp-upload-error", "ERROR", "api", null, { + logger.log("kaizen-sftp-upload-error", "ERROR", "api", xmlObj.bodyshopid, { filename: xmlObj.filename, error: error.message, stack: error.stack @@ -200,7 +204,7 @@ async function uploadViaSFTP(xmlObj) { throw error; } } catch (error) { - logger.log("kaizen-sftp-error", "ERROR", "api", null, { error: error.message, stack: error.stack }); + logger.log("kaizen-sftp-error", "ERROR", "api", xmlObj.bodyshopid, { error: error.message, stack: error.stack }); throw error; } finally { sftp.end(); From d2e1b32557a57bbe6b62124bd9dce281eed8608a Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Thu, 21 Nov 2024 17:35:04 -0800 Subject: [PATCH 309/478] feature/IO-3000-messaging-sockets-migrations2 - - Checkpoint, Signed-off-by: Dave Richer --- .../registerMessagingSocketHandlers.js | 140 ++++++++++++++---- .../chat-new-conversation.component.jsx | 7 +- .../chat-open-button.component.jsx | 7 +- .../schedule-event.component.jsx | 8 +- .../job-payments/job-payments.component.jsx | 24 ++- .../jobs-detail-header-actions.component.jsx | 10 +- .../payments-generate-link.component.jsx | 10 +- client/src/firebase/firebase.utils.js | 1 - client/src/graphql/conversations.queries.js | 22 +++ client/src/redux/messaging/messaging.sagas.js | 116 +++++++++++++-- 10 files changed, 272 insertions(+), 73 deletions(-) diff --git a/client/src/components/chat-affix/registerMessagingSocketHandlers.js b/client/src/components/chat-affix/registerMessagingSocketHandlers.js index b50d02c8a..e19c56a93 100644 --- a/client/src/components/chat-affix/registerMessagingSocketHandlers.js +++ b/client/src/components/chat-affix/registerMessagingSocketHandlers.js @@ -142,14 +142,47 @@ export const registerMessagingHandlers = ({ socket, client }) => { }); }; - const handleConversationChanged = (data) => { + const handleConversationChanged = async (data) => { if (!data) return; const { conversationId, type, job_conversations, ...fields } = data; - logLocal("handleConversationChanged", data); - // Identify the conversation in the Apollo cache + const updatedAt = new Date().toISOString(); + + const updateConversationList = (newConversation) => { + try { + const existingList = client.cache.readQuery({ + query: CONVERSATION_LIST_QUERY, + variables: { offset: 0 } + }); + + const updatedList = existingList?.conversations + ? [ + newConversation, + ...existingList.conversations.filter( + (conv) => conv.id !== newConversation.id // Prevent duplicates + ) + ] + : [newConversation]; + + client.cache.writeQuery({ + query: CONVERSATION_LIST_QUERY, + variables: { offset: 0 }, + data: { + conversations: updatedList + } + }); + } catch (error) { + console.error("Error updating conversation list in the cache:", error); + } + }; + + if (type === "conversation-created") { + updateConversationList({ ...fields, job_conversations, updated_at: updatedAt }); + return; + } + const cacheId = client.cache.identify({ __typename: "conversations", id: conversationId @@ -161,20 +194,20 @@ export const registerMessagingHandlers = ({ socket, client }) => { } if (type === "conversation-archived") { - // Remove all messages associated with this conversation - const messageRefs = client.cache.readFragment({ - id: cacheId, - fragment: gql` - fragment ConversationMessages on conversations { - messages { - id + try { + // Evict messages associated with the conversation + const messageRefs = client.cache.readFragment({ + id: cacheId, + fragment: gql` + fragment ConversationMessages on conversations { + messages { + id + } } - } - ` - }); + ` + }); - if (messageRefs?.messages) { - messageRefs.messages.forEach((message) => { + messageRefs?.messages?.forEach((message) => { const messageCacheId = client.cache.identify({ __typename: "messages", id: message.id @@ -183,39 +216,84 @@ export const registerMessagingHandlers = ({ socket, client }) => { client.cache.evict({ id: messageCacheId }); } }); + + // Evict the conversation itself + client.cache.evict({ id: cacheId }); + client.cache.gc(); // Trigger garbage collection + } catch (error) { + console.error("Error archiving conversation:", error); } - - // Evict the conversation itself - client.cache.evict({ id: cacheId }); - client.cache.gc(); // Trigger garbage collection to clean up unused entries - return; } + if (type === "conversation-unarchived") { + try { + // Fetch the conversation from the database if not already in the cache + const existingConversation = client.cache.readQuery({ + query: GET_CONVERSATION_DETAILS, + variables: { conversationId } + }); + + if (!existingConversation) { + const { data: fetchedData } = await client.query({ + query: GET_CONVERSATION_DETAILS, + variables: { conversationId }, + fetchPolicy: "network-only" + }); + + if (fetchedData?.conversations_by_pk) { + const conversationData = fetchedData.conversations_by_pk; + + // Enrich conversation data + const enrichedConversation = { + ...conversationData, + messages_aggregate: { + __typename: "messages_aggregate", + aggregate: { + __typename: "messages_aggregate_fields", + count: conversationData.messages.filter((message) => !message.read && !message.isoutbound).length + } + }, + updated_at: updatedAt + }; + + updateConversationList(enrichedConversation); + } + } + + // Mark the conversation as unarchived in the cache + client.cache.modify({ + id: cacheId, + fields: { + archived: () => false, + updated_at: () => updatedAt + } + }); + } catch (error) { + console.error("Error unarchiving conversation:", error); + } + return; + } + + // Handle other types of updates (e.g., marked read, tags added/removed) client.cache.modify({ id: cacheId, fields: { - // This is a catch-all for just sending it fields off conversation ...Object.fromEntries( - Object.entries(fields).map(([key, value]) => [ - key, - (cached) => (value !== undefined ? value : cached) // Update with new value or keep existing - ]) + Object.entries(fields).map(([key, value]) => [key, (cached) => (value !== undefined ? value : cached)]) ), ...(type === "conversation-marked-read" && { messages_aggregate: () => ({ - aggregate: { count: 0 } // Reset unread count + __typename: "messages_aggregate", + aggregate: { __typename: "messages_aggregate_fields", count: 0 } }) }), ...(type === "tag-added" && { - job_conversations: (existing = []) => { - // Merge existing job_conversations with new ones - return [...existing, ...job_conversations]; - } + job_conversations: (existing = []) => [...existing, ...job_conversations] }), ...(type === "tag-removed" && { job_conversations: (existing = [], { readField }) => - existing.filter((jobConversationRef) => readField("jobid", jobConversationRef) !== data.jobId) + existing.filter((jobRef) => readField("jobid", jobRef) !== data.jobId) }) } }); diff --git a/client/src/components/chat-new-conversation/chat-new-conversation.component.jsx b/client/src/components/chat-new-conversation/chat-new-conversation.component.jsx index b0b6054e4..e45ffb9b6 100644 --- a/client/src/components/chat-new-conversation/chat-new-conversation.component.jsx +++ b/client/src/components/chat-new-conversation/chat-new-conversation.component.jsx @@ -1,11 +1,12 @@ import { PlusCircleFilled } from "@ant-design/icons"; import { Button, Form, Popover } from "antd"; -import React from "react"; +import React, { useContext } from "react"; import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; import { createStructuredSelector } from "reselect"; import { openChatByPhone } from "../../redux/messaging/messaging.actions"; import PhoneFormItem, { PhoneItemFormatterValidation } from "../form-items-formatted/phone-form-item.component"; +import SocketContext from "../../contexts/SocketIO/socketContext.jsx"; const mapStateToProps = createStructuredSelector({ //currentUser: selectCurrentUser @@ -17,8 +18,10 @@ const mapDispatchToProps = (dispatch) => ({ export function ChatNewConversation({ openChatByPhone }) { const { t } = useTranslation(); const [form] = Form.useForm(); + const { socket } = useContext(SocketContext); + const handleFinish = (values) => { - openChatByPhone({ phone_num: values.phoneNumber }); + openChatByPhone({ phone_num: values.phoneNumber, socket }); form.resetFields(); }; diff --git a/client/src/components/chat-open-button/chat-open-button.component.jsx b/client/src/components/chat-open-button/chat-open-button.component.jsx index d2f0de528..dcd41c041 100644 --- a/client/src/components/chat-open-button/chat-open-button.component.jsx +++ b/client/src/components/chat-open-button/chat-open-button.component.jsx @@ -1,6 +1,6 @@ import { notification } from "antd"; import parsePhoneNumber from "libphonenumber-js"; -import React from "react"; +import React, { useContext } from "react"; import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; import { openChatByPhone } from "../../redux/messaging/messaging.actions"; @@ -9,6 +9,7 @@ import PhoneNumberFormatter from "../../utils/PhoneFormatter"; import { createStructuredSelector } from "reselect"; import { selectBodyshop } from "../../redux/user/user.selectors"; import { searchingForConversation } from "../../redux/messaging/messaging.selectors"; +import SocketContext from "../../contexts/SocketIO/socketContext.jsx"; const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop, @@ -21,6 +22,8 @@ const mapDispatchToProps = (dispatch) => ({ export function ChatOpenButton({ bodyshop, searchingForConversation, phone, jobid, openChatByPhone }) { const { t } = useTranslation(); + const { socket } = useContext(SocketContext); + if (!phone) return <>; if (!bodyshop.messagingservicesid) return {phone}; @@ -33,7 +36,7 @@ export function ChatOpenButton({ bodyshop, searchingForConversation, phone, jobi const p = parsePhoneNumber(phone, "CA"); if (searchingForConversation) return; //This is to prevent finding the same thing twice. if (p && p.isValid()) { - openChatByPhone({ phone_num: p.formatInternational(), jobid: jobid }); + openChatByPhone({ phone_num: p.formatInternational(), jobid: jobid, socket }); } else { notification["error"]({ message: t("messaging.error.invalidphone") }); } diff --git a/client/src/components/job-at-change/schedule-event.component.jsx b/client/src/components/job-at-change/schedule-event.component.jsx index e7f70ff65..bdf5f1a85 100644 --- a/client/src/components/job-at-change/schedule-event.component.jsx +++ b/client/src/components/job-at-change/schedule-event.component.jsx @@ -3,7 +3,7 @@ import { Button, Divider, Dropdown, Form, Input, notification, Popover, Select, import parsePhoneNumber from "libphonenumber-js"; import dayjs from "../../utils/day"; import queryString from "query-string"; -import React, { useState } from "react"; +import React, { useContext, useState } from "react"; import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; import { Link, useLocation, useNavigate } from "react-router-dom"; @@ -24,6 +24,7 @@ import ScheduleEventNote from "./schedule-event.note.component"; import { useMutation } from "@apollo/client"; import { UPDATE_APPOINTMENT } from "../../graphql/appointments.queries"; import ProductionListColumnComment from "../production-list-columns/production-list-columns.comment.component"; +import SocketContext from "../../contexts/SocketIO/socketContext.jsx"; const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop @@ -49,6 +50,8 @@ export function ScheduleEventComponent({ const searchParams = queryString.parse(useLocation().search); const [updateAppointment] = useMutation(UPDATE_APPOINTMENT); const [title, setTitle] = useState(event.title); + const { socket } = useContext(SocketContext); + const blockContent = ( ({ setPaymentContext: (context) => dispatch(setModalContext({ context: context, modal: "payment" })), - setCardPaymentContext: (context) => dispatch(setModalContext({ context: context, modal: "cardPayment" })), - openChatByPhone: (phone) => dispatch(openChatByPhone(phone)), - setMessage: (text) => dispatch(setMessage(text)) + setCardPaymentContext: (context) => + dispatch( + setModalContext({ + context: context, + modal: "cardPayment" + }) + ) }); -export function JobPayments({ - job, - jobRO, - bodyshop, - setMessage, - openChatByPhone, - setPaymentContext, - setCardPaymentContext, - refetch -}) { +export function JobPayments({ job, jobRO, bodyshop, setPaymentContext, setCardPaymentContext, refetch }) { const { treatments: { ImEXPay } } = useSplitTreatments({ @@ -133,7 +127,7 @@ export function JobPayments({ } ]; - //Same as in RO guard. If changed, update in both. + //Same as in RO guard. If changed, update in both. const total = useMemo(() => { return ( job.payments && diff --git a/client/src/components/jobs-detail-header-actions/jobs-detail-header-actions.component.jsx b/client/src/components/jobs-detail-header-actions/jobs-detail-header-actions.component.jsx index c9c3b8fb7..1fdeeec61 100644 --- a/client/src/components/jobs-detail-header-actions/jobs-detail-header-actions.component.jsx +++ b/client/src/components/jobs-detail-header-actions/jobs-detail-header-actions.component.jsx @@ -4,7 +4,7 @@ import { useSplitTreatments } from "@splitsoftware/splitio-react"; import { Button, Card, Dropdown, Form, Input, Modal, notification, Popconfirm, Popover, Select, Space } from "antd"; import axios from "axios"; import parsePhoneNumber from "libphonenumber-js"; -import React, { useMemo, useState } from "react"; +import React, { useContext, useMemo, useState } from "react"; import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; import { Link, useNavigate } from "react-router-dom"; @@ -30,6 +30,7 @@ import RbacWrapper from "../rbac-wrapper/rbac-wrapper.component"; import AddToProduction from "./jobs-detail-header-actions.addtoproduction.util"; import DuplicateJob from "./jobs-detail-header-actions.duplicate.util"; import JobsDetailHeaderActionsToggleProduction from "./jobs-detail-header-actions.toggle-production"; +import SocketContext from "../../contexts/SocketIO/socketContext.jsx"; const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop, @@ -126,6 +127,7 @@ export function JobsDetailHeaderActions({ const [updateJob] = useMutation(UPDATE_JOB); const [voidJob] = useMutation(VOID_JOB); const [cancelAllAppointments] = useMutation(CANCEL_APPOINTMENTS_BY_JOB_ID); + const { socket } = useContext(SocketContext); const { treatments: { ImEXPay } @@ -299,7 +301,8 @@ export function JobsDetailHeaderActions({ if (p && p.isValid()) { openChatByPhone({ phone_num: p.formatInternational(), - jobid: job.id + jobid: job.id, + socket }); setMessage( `${window.location.protocol}//${window.location.host}/csi/${result.data.insert_csi.returning[0].id}` @@ -342,7 +345,8 @@ export function JobsDetailHeaderActions({ if (p && p.isValid()) { openChatByPhone({ phone_num: p.formatInternational(), - jobid: job.id + jobid: job.id, + socket }); setMessage(`${window.location.protocol}//${window.location.host}/csi/${job.csiinvites[0].id}`); } else { diff --git a/client/src/components/payments-generate-link/payments-generate-link.component.jsx b/client/src/components/payments-generate-link/payments-generate-link.component.jsx index b0f4b26b9..f9d84d10f 100644 --- a/client/src/components/payments-generate-link/payments-generate-link.component.jsx +++ b/client/src/components/payments-generate-link/payments-generate-link.component.jsx @@ -3,13 +3,14 @@ import { Button, Form, message, Popover, Space } from "antd"; import axios from "axios"; import Dinero from "dinero.js"; import { parsePhoneNumber } from "libphonenumber-js"; -import React, { useState } from "react"; +import React, { useContext, useState } from "react"; import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; import { createStructuredSelector } from "reselect"; import { openChatByPhone, setMessage } from "../../redux/messaging/messaging.actions"; import { selectBodyshop, selectCurrentUser } from "../../redux/user/user.selectors"; import CurrencyFormItemComponent from "../form-items-formatted/currency-form-item.component"; +import SocketContext from "../../contexts/SocketIO/socketContext.jsx"; const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop, @@ -28,6 +29,7 @@ export function PaymentsGenerateLink({ bodyshop, currentUser, callback, job, ope const [open, setOpen] = useState(false); const [loading, setLoading] = useState(false); const [paymentLink, setPaymentLink] = useState(null); + const { socket } = useContext(SocketContext); const handleFinish = async ({ amount }) => { setLoading(true); @@ -50,7 +52,8 @@ export function PaymentsGenerateLink({ bodyshop, currentUser, callback, job, ope if (p) { openChatByPhone({ phone_num: p.formatInternational(), - jobid: job.id + jobid: job.id, + socket }); setMessage( t("payments.labels.smspaymentreminder", { @@ -106,7 +109,8 @@ export function PaymentsGenerateLink({ bodyshop, currentUser, callback, job, ope const p = parsePhoneNumber(job.ownr_ph1, "CA"); openChatByPhone({ phone_num: p.formatInternational(), - jobid: job.id + jobid: job.id, + socket }); setMessage( t("payments.labels.smspaymentreminder", { diff --git a/client/src/firebase/firebase.utils.js b/client/src/firebase/firebase.utils.js index 46a460525..33da2eeac 100644 --- a/client/src/firebase/firebase.utils.js +++ b/client/src/firebase/firebase.utils.js @@ -4,7 +4,6 @@ import { getAuth, updatePassword, updateProfile } from "firebase/auth"; import { getFirestore } from "firebase/firestore"; import { getMessaging, getToken, onMessage } from "firebase/messaging"; import { store } from "../redux/store"; -import axios from "axios"; const config = JSON.parse(import.meta.env.VITE_APP_FIREBASE_CONFIG); initializeApp(config); diff --git a/client/src/graphql/conversations.queries.js b/client/src/graphql/conversations.queries.js index 03bc0426b..373d70691 100644 --- a/client/src/graphql/conversations.queries.js +++ b/client/src/graphql/conversations.queries.js @@ -59,6 +59,8 @@ export const GET_CONVERSATION_DETAILS = gql` id phone_num archived + updated_at + unreadcnt label job_conversations { jobid @@ -119,6 +121,26 @@ export const CREATE_CONVERSATION = gql` insert_conversations(objects: $conversation) { returning { id + phone_num + archived + label + unreadcnt + job_conversations { + jobid + conversationid + job { + id + ownr_fn + ownr_ln + ownr_co_nm + ro_number + } + } + messages_aggregate(where: { read: { _eq: false }, isoutbound: { _eq: false } }) { + aggregate { + count + } + } } } } diff --git a/client/src/redux/messaging/messaging.sagas.js b/client/src/redux/messaging/messaging.sagas.js index 86757a427..fa17c6db5 100644 --- a/client/src/redux/messaging/messaging.sagas.js +++ b/client/src/redux/messaging/messaging.sagas.js @@ -2,7 +2,13 @@ import axios from "axios"; import parsePhoneNumber from "libphonenumber-js"; import { all, call, put, select, takeLatest } from "redux-saga/effects"; import { logImEXEvent } from "../../firebase/firebase.utils"; -import { CONVERSATION_ID_BY_PHONE, CREATE_CONVERSATION } from "../../graphql/conversations.queries"; +import { + CONVERSATION_ID_BY_PHONE, + CONVERSATION_LIST_QUERY, + CREATE_CONVERSATION, + GET_CONVERSATION_DETAILS, + TOGGLE_CONVERSATION_ARCHIVE +} from "../../graphql/conversations.queries"; import { INSERT_CONVERSATION_TAG } from "../../graphql/job-conversations.queries"; import client from "../../utils/GraphQLClient"; import { selectBodyshop } from "../user/user.selectors"; @@ -27,23 +33,24 @@ export function* onOpenChatByPhone() { export function* openChatByPhone({ payload }) { logImEXEvent("messaging_open_by_phone"); - const { phone_num, jobid } = payload; - + const { socket, phone_num, jobid } = payload; const p = parsePhoneNumber(phone_num, "CA"); const bodyshop = yield select(selectBodyshop); + try { const { data: { conversations } } = yield client.query({ query: CONVERSATION_ID_BY_PHONE, variables: { phone: p.number }, - fetchPolicy: 'no-cache' + fetchPolicy: "no-cache" }); if (conversations.length === 0) { + // No conversation exists, create a new one const { data: { - insert_conversations: { returning: newConversationsId } + insert_conversations: { returning: newConversations } } } = yield client.mutate({ mutation: CREATE_CONVERSATION, @@ -57,26 +64,107 @@ export function* openChatByPhone({ payload }) { ] } }); - yield put(setSelectedConversation(newConversationsId[0].id)); - } else if (conversations.length === 1) { - //got the ID. Open it. - yield put(setSelectedConversation(conversations[0].id)); - //Check to see if this job ID is already a child of it. If not add the tag. - if (jobid && !conversations[0].job_conversations.find((jc) => jc.jobid === jobid)) + const createdConversation = newConversations[0]; // Get the newly created conversation + + // Emit event for new conversation with full details + if (socket) { + socket.emit("conversation-modified", { + bodyshopId: bodyshop.id, + type: "conversation-created", + ...createdConversation + }); + } + + // Set the newly created conversation as selected + yield put(setSelectedConversation(createdConversation.id)); + } else if (conversations.length === 1) { + const conversation = conversations[0]; + + if (conversation.archived) { + // Conversation is archived, unarchive it in the DB + const { + data: { update_conversations_by_pk: updatedConversation } + } = yield client.mutate({ + mutation: TOGGLE_CONVERSATION_ARCHIVE, + variables: { + id: conversation.id, + archived: false + } + }); + + if (socket) { + socket.emit("conversation-modified", { + type: "conversation-unarchived", + conversationId: updatedConversation.id, + bodyshopId: bodyshop.id, + archived: false + }); + } + + // Update the conversation list in the cache + const existingConversations = client.cache.readQuery({ + query: CONVERSATION_LIST_QUERY, + variables: { offset: 0 } + }); + + client.cache.writeQuery({ + query: CONVERSATION_LIST_QUERY, + variables: { offset: 0 }, + data: { + conversations: [ + { + ...conversation, + archived: false, + updated_at: new Date().toISOString() + }, + ...(existingConversations?.conversations || []) + ] + } + }); + } + + // Check if the conversation exists in the cache + const cacheId = client.cache.identify({ + __typename: "conversations", + id: conversation.id + }); + + if (!cacheId) { + // Fetch the conversation details from the database + const { data } = yield client.query({ + query: GET_CONVERSATION_DETAILS, + variables: { conversationId: conversation.id } + }); + + // Write fetched data to the cache + client.cache.writeQuery({ + query: GET_CONVERSATION_DETAILS, + variables: { conversationId: conversation.id }, + data + }); + } + + // Open the conversation + yield put(setSelectedConversation(conversation.id)); + + // Check and add job tag if needed + if (jobid && !conversation.job_conversations.find((jc) => jc.jobid === jobid)) { yield client.mutate({ mutation: INSERT_CONVERSATION_TAG, variables: { - conversationId: conversations[0].id, + conversationId: conversation.id, jobId: jobid } }); + } } else { - console.log("ERROR: Multiple conversations found. "); + // Multiple conversations found + console.error("ERROR: Multiple conversations found."); yield put(setSelectedConversation(null)); } } catch (error) { - console.log("Error in sendMessage saga.", error); + console.error("Error in openChatByPhone saga.", error); } } From 8229e3593ca6afc6c43b5d960af520059e17e9d9 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Thu, 21 Nov 2024 17:39:05 -0800 Subject: [PATCH 310/478] feature/IO-3000-messaging-sockets-migrations2 - - remove unused query, Signed-off-by: Dave Richer --- client/src/graphql/conversations.queries.js | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/client/src/graphql/conversations.queries.js b/client/src/graphql/conversations.queries.js index 373d70691..33009ffbe 100644 --- a/client/src/graphql/conversations.queries.js +++ b/client/src/graphql/conversations.queries.js @@ -163,22 +163,3 @@ export const UPDATE_CONVERSATION_LABEL = gql` } } `; - -export const GET_CONVERSATION_MESSAGES = gql` - query GET_CONVERSATION_MESSAGES($conversationId: uuid!) { - conversation: conversations_by_pk(id: $conversationId) { - id - phone_num - updated_at - label - } - messages: messages(where: { conversationid: { _eq: $conversationId } }, order_by: { created_at: asc }) { - id - text - created_at - read - isoutbound - userid - } - } -`; From 38f13346e5efa2feee36e435dca4bb6e7d3f07ed Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Thu, 21 Nov 2024 18:44:38 -0800 Subject: [PATCH 311/478] feature/IO-3000-messaging-sockets-migrations2 - - testing and edge cases Signed-off-by: Dave Richer --- .../registerMessagingSocketHandlers.js | 201 ++++++++++---- .../chat-conversation-list.component.jsx | 11 +- .../chat-popup/chat-popup.component.jsx | 16 +- server/graphql-client/queries.js | 62 +---- server/sms/receive.js | 251 ++++++++---------- 5 files changed, 270 insertions(+), 271 deletions(-) diff --git a/client/src/components/chat-affix/registerMessagingSocketHandlers.js b/client/src/components/chat-affix/registerMessagingSocketHandlers.js index e19c56a93..49bce2ff8 100644 --- a/client/src/components/chat-affix/registerMessagingSocketHandlers.js +++ b/client/src/components/chat-affix/registerMessagingSocketHandlers.js @@ -12,61 +12,164 @@ const logLocal = (message, ...args) => { export const registerMessagingHandlers = ({ socket, client }) => { if (!(socket && client)) return; - const handleNewMessageSummary = (message) => { + const handleNewMessageSummary = async (message) => { const { conversationId, newConversation, existingConversation, isoutbound } = message; - logLocal("handleNewMessageSummary", message); - if (!existingConversation && newConversation?.phone_num) { - const queryResults = client.cache.readQuery({ - query: CONVERSATION_LIST_QUERY, - variables: { offset: 0 } - }); + const queryVariables = { offset: 0 }; - client.cache.writeQuery({ - query: CONVERSATION_LIST_QUERY, - variables: { offset: 0 }, - data: { - conversations: [ - { - ...newConversation, - updated_at: newConversation.updated_at || new Date().toISOString(), - unreadcnt: newConversation.unreadcnt || 0, - archived: newConversation.archived || false, - label: newConversation.label || null, - job_conversations: newConversation.job_conversations || [], - messages_aggregate: newConversation.messages_aggregate || { - aggregate: { count: isoutbound ? 0 : 1 } - } - }, - ...(queryResults?.conversations || []) - ] - } - }); - } else { - client.cache.modify({ - id: client.cache.identify({ - __typename: "conversations", - id: conversationId - }), - fields: { - updated_at: () => new Date().toISOString(), - archived(cached) { - // Unarchive the conversation if it was previously marked as archived - if (cached) { - return false; + // Handle new conversation + if (!existingConversation && newConversation?.phone_num) { + try { + const queryResults = client.cache.readQuery({ + query: CONVERSATION_LIST_QUERY, + variables: queryVariables + }); + + const enrichedConversation = { + ...newConversation, + updated_at: newConversation.updated_at || new Date().toISOString(), + unreadcnt: newConversation.unreadcnt || 0, + archived: newConversation.archived || false, + label: newConversation.label || null, + job_conversations: newConversation.job_conversations || [], + messages_aggregate: newConversation.messages_aggregate || { + __typename: "messages_aggregate", + aggregate: { + __typename: "messages_aggregate_fields", + count: isoutbound ? 0 : 1 } - return cached; }, - messages_aggregate(cached) { - // Increment unread count only if the message is inbound - if (!isoutbound) { - return { aggregate: { count: cached.aggregate.count + 1 } }; - } - return cached; + __typename: "conversations" + }; + + client.cache.writeQuery({ + query: CONVERSATION_LIST_QUERY, + variables: queryVariables, + data: { + conversations: [enrichedConversation, ...(queryResults?.conversations || [])] } + }); + } catch (error) { + console.error("Error updating cache for new conversation:", error); + } + return; + } + + // Handle existing conversation + if (existingConversation) { + let conversationDetails; + + // Fetch or read the conversation details + try { + conversationDetails = client.cache.readFragment({ + id: client.cache.identify({ + __typename: "conversations", + id: conversationId + }), + fragment: gql` + fragment ExistingConversation on conversations { + id + phone_num + updated_at + archived + label + unreadcnt + job_conversations { + jobid + conversationid + } + messages_aggregate { + aggregate { + count + } + } + __typename + } + ` + }); + } catch (error) { + console.warn("Conversation not found in cache, querying server..."); + } + + if (!conversationDetails) { + try { + const { data } = await client.query({ + query: GET_CONVERSATION_DETAILS, + variables: { conversationId }, + fetchPolicy: "network-only" + }); + conversationDetails = data?.conversations_by_pk; + } catch (error) { + console.error("Failed to fetch conversation details from server:", error); + return; } - }); + } + + if (!conversationDetails) { + console.error("Unable to retrieve conversation details. Skipping cache update."); + return; + } + + try { + const queryResults = client.cache.readQuery({ + query: CONVERSATION_LIST_QUERY, + variables: queryVariables + }); + + const isAlreadyInCache = queryResults?.conversations.some((conv) => conv.id === conversationId); + + if (!isAlreadyInCache) { + const enrichedConversation = { + ...conversationDetails, + archived: false, + __typename: "conversations", + messages_aggregate: { + __typename: "messages_aggregate", + aggregate: { + __typename: "messages_aggregate_fields", + count: + conversationDetails.messages?.filter( + (message) => !message.read && !message.isoutbound // Count unread, inbound messages + ).length || 0 + } + } + }; + + client.cache.writeQuery({ + query: CONVERSATION_LIST_QUERY, + variables: queryVariables, + data: { + conversations: [enrichedConversation, ...(queryResults?.conversations || [])] + } + }); + } + // Update existing conversation fields + client.cache.modify({ + id: client.cache.identify({ + __typename: "conversations", + id: conversationId + }), + fields: { + updated_at: () => new Date().toISOString(), + archived: () => false, + messages_aggregate(cached) { + if (!isoutbound) { + return { + __typename: "messages_aggregate", + aggregate: { + __typename: "messages_aggregate_fields", + count: cached.aggregate.count + 1 + } + }; + } + return cached; + } + } + }); + } catch (error) { + console.error("Error updating cache for existing conversation:", error); + } } }; @@ -300,7 +403,7 @@ export const registerMessagingHandlers = ({ socket, client }) => { }; const handleNewMessage = ({ conversationId, message }) => { - if (!conversationId || !message.id || !message.text) { + if (!conversationId || !message?.id || !message?.text) { return; } @@ -359,9 +462,9 @@ export const registerMessagingHandlers = ({ socket, client }) => { }); }; - socket.on("new-message", handleNewMessage); socket.on("new-message-summary", handleNewMessageSummary); socket.on("new-message-detailed", handleNewMessageDetailed); + socket.on("new-message", handleNewMessage); socket.on("message-changed", handleMessageChanged); socket.on("conversation-changed", handleConversationChanged); }; diff --git a/client/src/components/chat-conversation-list/chat-conversation-list.component.jsx b/client/src/components/chat-conversation-list/chat-conversation-list.component.jsx index 38221085d..a8f95f59d 100644 --- a/client/src/components/chat-conversation-list/chat-conversation-list.component.jsx +++ b/client/src/components/chat-conversation-list/chat-conversation-list.component.jsx @@ -19,12 +19,7 @@ const mapDispatchToProps = (dispatch) => ({ setSelectedConversation: (conversationId) => dispatch(setSelectedConversation(conversationId)) }); -function ChatConversationListComponent({ - conversationList, - selectedConversation, - setSelectedConversation, - loadMoreConversations -}) { +function ChatConversationListComponent({ conversationList, selectedConversation, setSelectedConversation }) { const renderConversation = (index) => { const item = conversationList[index]; const cardContentRight = {item.updated_at}; @@ -69,13 +64,15 @@ function ChatConversationListComponent({ ); }; + // TODO: Can go back into virtuoso for additional fetch + // endReached={loadMoreConversations} // Calls loadMoreConversations when scrolled to the bottom + return (
renderConversation(index)} style={{ height: "100%", width: "100%" }} - endReached={loadMoreConversations} // Calls loadMoreConversations when scrolled to the bottom />
); diff --git a/client/src/components/chat-popup/chat-popup.component.jsx b/client/src/components/chat-popup/chat-popup.component.jsx index b2625261d..e67929d11 100644 --- a/client/src/components/chat-popup/chat-popup.component.jsx +++ b/client/src/components/chat-popup/chat-popup.component.jsx @@ -77,17 +77,6 @@ export function ChatPopupComponent({ chatVisible, selectedConversation, toggleCh }); }, [chatVisible, getConversations]); - const loadMoreConversations = useCallback(() => { - if (data) - fetchMore({ - variables: { - offset: data.conversations.length - } - }).catch((err) => { - console.error(`Error fetching more conversations: ${(err, err.message || "")}`); - }); - }, [data, fetchMore]); - const unreadCount = unreadData?.messages_aggregate?.aggregate?.count || 0; return ( @@ -114,10 +103,7 @@ export function ChatPopupComponent({ chatVisible, selectedConversation, toggleCh {loading ? ( ) : ( - + )} {selectedConversation ? : null} diff --git a/server/graphql-client/queries.js b/server/graphql-client/queries.js index 0a2b6a853..72224dfb6 100644 --- a/server/graphql-client/queries.js +++ b/server/graphql-client/queries.js @@ -1515,7 +1515,8 @@ exports.GET_JOB_BY_PK = `query GET_JOB_BY_PK($id: uuid!) { }`; //TODO:AIO The above query used to have parts order lines in it. Validate that this doesn't need it. -exports.QUERY_JOB_COSTING_DETAILS = ` query QUERY_JOB_COSTING_DETAILS($id: uuid!) { +exports.QUERY_JOB_COSTING_DETAILS = ` +query QUERY_JOB_COSTING_DETAILS($id: uuid!) { jobs_by_pk(id: $id) { ro_number clm_total @@ -2566,68 +2567,9 @@ exports.GET_JOBS_BY_PKS = `query GET_JOBS_BY_PKS($ids: [uuid!]!) { } `; -exports.GET_CONVERSATIONS = `query GET_CONVERSATIONS($bodyshopId: uuid!) { - conversations( - where: { bodyshopid: { _eq: $bodyshopId }, archived: { _eq: false } }, - order_by: { updated_at: desc }, - limit: 50 - ) { - phone_num - id - updated_at - unreadcnt - archived - label - messages_aggregate(where: { read: { _eq: false }, isoutbound: { _eq: false } }) { - aggregate { - count - } - } - job_conversations { - job { - id - ro_number - ownr_fn - ownr_ln - ownr_co_nm - } - } - } -} -`; - exports.MARK_MESSAGES_AS_READ = `mutation MARK_MESSAGES_AS_READ($conversationId: uuid!) { update_messages(where: { conversationid: { _eq: $conversationId } }, _set: { read: true }) { affected_rows } } `; - -exports.GET_CONVERSATION_DETAILS = ` - query GET_CONVERSATION_DETAILS($conversationId: uuid!) { - conversation: conversations_by_pk(id: $conversationId) { - id - phone_num - updated_at - label - job_conversations { - job { - id - ro_number - ownr_fn - ownr_ln - ownr_co_nm - } - } - } - messages: messages(where: { conversationid: { _eq: $conversationId } }, order_by: { created_at: asc }) { - id - text - created_at - read - isoutbound - userid - image_path - } - } -`; diff --git a/server/sms/receive.js b/server/sms/receive.js index f7f41652e..63c11a260 100644 --- a/server/sms/receive.js +++ b/server/sms/receive.js @@ -16,23 +16,21 @@ exports.receive = async (req, res) => { ioHelpers: { getBodyshopRoom, getBodyshopConversationRoom } } = req; - logger.log("sms-inbound", "DEBUG", "api", null, { + const loggerData = { msid: req.body.SmsMessageSid, text: req.body.Body, image: !!req.body.MediaUrl0, image_path: generateMediaArray(req.body) - }); + }; + + logger.log("sms-inbound", "DEBUG", "api", null, loggerData); if (!req.body || !req.body.MessagingServiceSid || !req.body.SmsMessageSid) { logger.log("sms-inbound-error", "ERROR", "api", null, { - msid: req.body.SmsMessageSid, - text: req.body.Body, - image: !!req.body.MediaUrl0, - image_path: generateMediaArray(req.body), + ...loggerData, type: "malformed-request" }); - res.status(400).json({ success: false, error: "Malformed Request" }); - return; + return res.status(400).json({ success: false, error: "Malformed Request" }); } try { @@ -41,6 +39,14 @@ exports.receive = async (req, res) => { phone: phone(req.body.From).phoneNumber }); + if (!response.bodyshops[0]) { + return res.status(400).json({ success: false, error: "No matching bodyshop" }); + } + + const bodyshop = response.bodyshops[0]; + const isNewConversation = bodyshop.conversations.length === 0; + const isDuplicate = bodyshop.conversations.length > 1; + let newMessage = { msid: req.body.SmsMessageSid, text: req.body.Body, @@ -48,140 +54,105 @@ exports.receive = async (req, res) => { image_path: generateMediaArray(req.body) }; - if (response.bodyshops[0]) { - const bodyshop = response.bodyshops[0]; - if (bodyshop.conversations.length === 0) { - newMessage.conversation = { - data: { - bodyshopid: bodyshop.id, - phone_num: phone(req.body.From).phoneNumber, - archived: false - } - }; - - try { - const insertresp = await client.request(queries.RECEIVE_MESSAGE, { msg: newMessage }); - const createdConversation = insertresp?.insert_messages?.returning?.[0]?.conversation || null; - const message = insertresp?.insert_messages?.returning?.[0]; - - if (!createdConversation) { - throw new Error("Conversation data is missing from the response."); - } - - const broadcastRoom = getBodyshopRoom(createdConversation.bodyshop.id); - const conversationRoom = getBodyshopConversationRoom({ - bodyshopId: message.conversation.bodyshop.id, - conversationId: message.conversation.id - }); - - ioRedis.to(broadcastRoom).emit("new-message-summary", { - isoutbound: false, - existingConversation: false, - newConversation: createdConversation, - conversationId: createdConversation.id, - updated_at: message.updated_at, - msid: message.sid, - summary: true - }); - - ioRedis.to(conversationRoom).emit("new-message-detailed", { - newMessage: message, - isoutbound: false, - newConversation: createdConversation, - existingConversation: false, - conversationId: createdConversation.id, - summary: false - }); - - logger.log("sms-inbound-success", "DEBUG", "api", null, { - newMessage, - createdConversation - }); - - res.status(200).send(""); - return; - } catch (e) { - handleError(req, e, res, "RECEIVE_MESSAGE"); - return; - } - } else if (bodyshop.conversations.length === 1) { - newMessage.conversationid = bodyshop.conversations[0].id; - } else { - logger.log("sms-inbound-error", "ERROR", "api", null, { - msid: req.body.SmsMessageSid, - text: req.body.Body, - image: !!req.body.MediaUrl0, - image_path: generateMediaArray(req.body), - messagingServiceSid: req.body.MessagingServiceSid, - type: "duplicate-phone" - }); - res.status(400).json({ success: false, error: "Duplicate phone number" }); - return; - } - - try { - const insertresp = await client.request(queries.INSERT_MESSAGE, { - msg: newMessage, - conversationid: newMessage.conversationid - }); - - const message = insertresp.insert_messages.returning[0]; - const data = { - type: "messaging-inbound", - conversationid: message.conversationid || "", - text: message.text || "", - messageid: message.id || "", - phone_num: message.conversation.phone_num || "" - }; - - const fcmresp = await admin.messaging().send({ - topic: `${message.conversation.bodyshop.imexshopid}-messaging`, - notification: { - title: InstanceManager({ - imex: `ImEX Online Message - ${data.phone_num}`, - rome: `Rome Online Message - ${data.phone_num}`, - promanager: `ProManager Message - ${data.phone_num}` - }), - body: message.image_path ? `Image ${message.text}` : message.text - }, - data - }); - - logger.log("sms-inbound-success", "DEBUG", "api", null, { - newMessage, - fcmresp - }); - - const broadcastRoom = getBodyshopRoom(message.conversation.bodyshop.id); - const conversationRoom = getBodyshopConversationRoom({ - bodyshopId: message.conversation.bodyshop.id, - conversationId: message.conversation.id - }); - - ioRedis.to(broadcastRoom).emit("new-message-summary", { - isoutbound: false, - existingConversation: true, - conversationId: message.conversationid, - updated_at: message.updated_at, - msid: message.sid, - summary: true - }); - - ioRedis.to(conversationRoom).emit("new-message-detailed", { - newMessage: message, - isoutbound: false, - existingConversation: true, - conversationId: message.conversationid, - summary: false - }); - - res.status(200).send(""); - } catch (e) { - handleError(req, e, res, "INSERT_MESSAGE"); - } + if (isDuplicate) { + logger.log("sms-inbound-error", "ERROR", "api", null, { + ...loggerData, + messagingServiceSid: req.body.MessagingServiceSid, + type: "duplicate-phone" + }); + return res.status(400).json({ success: false, error: "Duplicate phone number" }); } + + if (isNewConversation) { + newMessage.conversation = { + data: { + bodyshopid: bodyshop.id, + phone_num: phone(req.body.From).phoneNumber, + archived: false + } + }; + } else { + const existingConversation = bodyshop.conversations[0]; + + // Update the conversation to unarchive it + if (existingConversation.archived) { + await client.request(queries.UNARCHIVE_CONVERSATION, { + id: existingConversation.id, + archived: false + }); + } + + newMessage.conversationid = existingConversation.id; + } + + const query = isNewConversation ? queries.RECEIVE_MESSAGE : queries.INSERT_MESSAGE; + const variables = isNewConversation + ? { msg: newMessage } + : { msg: newMessage, conversationid: newMessage.conversationid }; + + const insertresp = await client.request(query, variables); + const message = insertresp?.insert_messages?.returning?.[0]; + const conversation = message?.conversation || null; + + if (!conversation) { + throw new Error("Conversation data is missing from the response."); + } + + const broadcastRoom = getBodyshopRoom(conversation.bodyshop.id); + const conversationRoom = getBodyshopConversationRoom({ + bodyshopId: conversation.bodyshop.id, + conversationId: conversation.id + }); + + const commonPayload = { + isoutbound: false, + conversationId: conversation.id, + updated_at: message.updated_at, + msid: message.sid + }; + + ioRedis.to(broadcastRoom).emit("new-message-summary", { + ...commonPayload, + existingConversation: !isNewConversation, + newConversation: isNewConversation ? conversation : null, + summary: true + }); + + ioRedis.to(conversationRoom).emit("new-message-detailed", { + newMessage: message, + ...commonPayload, + newConversation: isNewConversation ? conversation : null, + existingConversation: !isNewConversation, + summary: false + }); + + const fcmresp = await admin.messaging().send({ + topic: `${message.conversation.bodyshop.imexshopid}-messaging`, + notification: { + title: InstanceManager({ + imex: `ImEX Online Message - ${message.conversation.phone_num}`, + rome: `Rome Online Message - ${message.conversation.phone_num}`, + promanager: `ProManager Message - ${message.conversation.phone_num}` + }), + body: message.image_path ? `Image ${message.text}` : message.text + }, + data: { + type: "messaging-inbound", + conversationid: message.conversationid || "", + text: message.text || "", + messageid: message.id || "", + phone_num: message.conversation.phone_num || "" + } + }); + + logger.log("sms-inbound-success", "DEBUG", "api", null, { + newMessage, + fcmresp + }); + + res.status(200).send(""); } catch (e) { - handleError(req, e, res, "FIND_BODYSHOP_BY_MESSAGING_SERVICE_SID"); + handleError(req, e, res, "RECEIVE_MESSAGE"); } }; From 525f795ce0d500620db09b1d266d16ec65f804e4 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Thu, 21 Nov 2024 19:17:42 -0800 Subject: [PATCH 312/478] feature/IO-3000-messaging-sockets-migrations2 - - dumb down archive/unarchive Signed-off-by: Dave Richer --- .../registerMessagingSocketHandlers.js | 84 ++----------------- client/src/redux/messaging/messaging.sagas.js | 3 +- 2 files changed, 11 insertions(+), 76 deletions(-) diff --git a/client/src/components/chat-affix/registerMessagingSocketHandlers.js b/client/src/components/chat-affix/registerMessagingSocketHandlers.js index 49bce2ff8..8034353c8 100644 --- a/client/src/components/chat-affix/registerMessagingSocketHandlers.js +++ b/client/src/components/chat-affix/registerMessagingSocketHandlers.js @@ -250,6 +250,7 @@ export const registerMessagingHandlers = ({ socket, client }) => { const { conversationId, type, job_conversations, ...fields } = data; logLocal("handleConversationChanged", data); + console.log(`--------------${type}-----------------`); const updatedAt = new Date().toISOString(); @@ -296,85 +297,18 @@ export const registerMessagingHandlers = ({ socket, client }) => { return; } - if (type === "conversation-archived") { + if (type === "conversation-unarchived" || type === "conversation-archived") { try { - // Evict messages associated with the conversation - const messageRefs = client.cache.readFragment({ - id: cacheId, - fragment: gql` - fragment ConversationMessages on conversations { - messages { - id - } - } - ` - }); - - messageRefs?.messages?.forEach((message) => { - const messageCacheId = client.cache.identify({ - __typename: "messages", - id: message.id - }); - if (messageCacheId) { - client.cache.evict({ id: messageCacheId }); - } - }); - - // Evict the conversation itself - client.cache.evict({ id: cacheId }); - client.cache.gc(); // Trigger garbage collection - } catch (error) { - console.error("Error archiving conversation:", error); - } - return; - } - - if (type === "conversation-unarchived") { - try { - // Fetch the conversation from the database if not already in the cache - const existingConversation = client.cache.readQuery({ - query: GET_CONVERSATION_DETAILS, - variables: { conversationId } - }); - - if (!existingConversation) { - const { data: fetchedData } = await client.query({ - query: GET_CONVERSATION_DETAILS, - variables: { conversationId }, - fetchPolicy: "network-only" - }); - - if (fetchedData?.conversations_by_pk) { - const conversationData = fetchedData.conversations_by_pk; - - // Enrich conversation data - const enrichedConversation = { - ...conversationData, - messages_aggregate: { - __typename: "messages_aggregate", - aggregate: { - __typename: "messages_aggregate_fields", - count: conversationData.messages.filter((message) => !message.read && !message.isoutbound).length - } - }, - updated_at: updatedAt - }; - - updateConversationList(enrichedConversation); - } - } - - // Mark the conversation as unarchived in the cache - client.cache.modify({ - id: cacheId, - fields: { - archived: () => false, - updated_at: () => updatedAt - } + // Refetch the conversation list query to update the UI + const queryVariables = { offset: 0 }; + await client.refetchQueries({ + include: [CONVERSATION_LIST_QUERY], + variables: queryVariables }); } catch (error) { - console.error("Error unarchiving conversation:", error); + console.error("Error refetching conversation list after unarchiving:", error); } + return; } diff --git a/client/src/redux/messaging/messaging.sagas.js b/client/src/redux/messaging/messaging.sagas.js index fa17c6db5..2ee7a8bac 100644 --- a/client/src/redux/messaging/messaging.sagas.js +++ b/client/src/redux/messaging/messaging.sagas.js @@ -34,6 +34,7 @@ export function* onOpenChatByPhone() { export function* openChatByPhone({ payload }) { logImEXEvent("messaging_open_by_phone"); const { socket, phone_num, jobid } = payload; + if (!socket || !phone_num) return; const p = parsePhoneNumber(phone_num, "CA"); const bodyshop = yield select(selectBodyshop); @@ -67,7 +68,7 @@ export function* openChatByPhone({ payload }) { const createdConversation = newConversations[0]; // Get the newly created conversation - // Emit event for new conversation with full details + // // Emit event for new conversation with full details if (socket) { socket.emit("conversation-modified", { bodyshopId: bodyshop.id, From 12ed8d3830534aed4cdb946d5b9e0997d689ae8b Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Thu, 21 Nov 2024 19:21:51 -0800 Subject: [PATCH 313/478] feature/IO-3000-messaging-sockets-migrations2 - - dumb down archive/unarchive Signed-off-by: Dave Richer --- .../registerMessagingSocketHandlers.js | 33 ++++++++++--------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/client/src/components/chat-affix/registerMessagingSocketHandlers.js b/client/src/components/chat-affix/registerMessagingSocketHandlers.js index 8034353c8..a20781dec 100644 --- a/client/src/components/chat-affix/registerMessagingSocketHandlers.js +++ b/client/src/components/chat-affix/registerMessagingSocketHandlers.js @@ -250,7 +250,6 @@ export const registerMessagingHandlers = ({ socket, client }) => { const { conversationId, type, job_conversations, ...fields } = data; logLocal("handleConversationChanged", data); - console.log(`--------------${type}-----------------`); const updatedAt = new Date().toISOString(); @@ -287,6 +286,23 @@ export const registerMessagingHandlers = ({ socket, client }) => { return; } + if (type === "conversation-unarchived" || type === "conversation-archived") { + try { + // Refetch the conversation list and details queries + await client.refetchQueries({ + include: [CONVERSATION_LIST_QUERY, GET_CONVERSATION_DETAILS], + variables: [ + { query: CONVERSATION_LIST_QUERY, variables: { offset: 0 } }, + { query: GET_CONVERSATION_DETAILS, variables: { conversationId } } + ] + }); + } catch (error) { + console.error("Error refetching queries after conversation state change:", error); + } + + return; + } + const cacheId = client.cache.identify({ __typename: "conversations", id: conversationId @@ -297,21 +313,6 @@ export const registerMessagingHandlers = ({ socket, client }) => { return; } - if (type === "conversation-unarchived" || type === "conversation-archived") { - try { - // Refetch the conversation list query to update the UI - const queryVariables = { offset: 0 }; - await client.refetchQueries({ - include: [CONVERSATION_LIST_QUERY], - variables: queryVariables - }); - } catch (error) { - console.error("Error refetching conversation list after unarchiving:", error); - } - - return; - } - // Handle other types of updates (e.g., marked read, tags added/removed) client.cache.modify({ id: cacheId, From 141deff41eb19dc2016b0be7065811d1fc228e41 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Thu, 21 Nov 2024 19:37:25 -0800 Subject: [PATCH 314/478] feature/IO-3000-messaging-sockets-migrations2 - - harden openMessageByPhone Signed-off-by: Dave Richer --- .../registerMessagingSocketHandlers.js | 38 +++++---- client/src/redux/messaging/messaging.sagas.js | 78 +++++-------------- 2 files changed, 39 insertions(+), 77 deletions(-) diff --git a/client/src/components/chat-affix/registerMessagingSocketHandlers.js b/client/src/components/chat-affix/registerMessagingSocketHandlers.js index a20781dec..76cc2c741 100644 --- a/client/src/components/chat-affix/registerMessagingSocketHandlers.js +++ b/client/src/components/chat-affix/registerMessagingSocketHandlers.js @@ -286,23 +286,6 @@ export const registerMessagingHandlers = ({ socket, client }) => { return; } - if (type === "conversation-unarchived" || type === "conversation-archived") { - try { - // Refetch the conversation list and details queries - await client.refetchQueries({ - include: [CONVERSATION_LIST_QUERY, GET_CONVERSATION_DETAILS], - variables: [ - { query: CONVERSATION_LIST_QUERY, variables: { offset: 0 } }, - { query: GET_CONVERSATION_DETAILS, variables: { conversationId } } - ] - }); - } catch (error) { - console.error("Error refetching queries after conversation state change:", error); - } - - return; - } - const cacheId = client.cache.identify({ __typename: "conversations", id: conversationId @@ -313,6 +296,27 @@ export const registerMessagingHandlers = ({ socket, client }) => { return; } + if (type === "conversation-unarchived" || type === "conversation-archived") { + try { + const listQueryVariables = { offset: 0 }; + const detailsQueryVariables = { conversationId }; + + // Refetch the conversation list and details queries + await client.refetchQueries({ + include: [CONVERSATION_LIST_QUERY, GET_CONVERSATION_DETAILS], + variables: [ + { query: CONVERSATION_LIST_QUERY, variables: listQueryVariables }, + { query: GET_CONVERSATION_DETAILS, variables: detailsQueryVariables } + ] + }); + + console.log("Refetched conversation list and details after state change."); + } catch (error) { + console.error("Error refetching queries after conversation state change:", error); + } + + return; + } // Handle other types of updates (e.g., marked read, tags added/removed) client.cache.modify({ id: cacheId, diff --git a/client/src/redux/messaging/messaging.sagas.js b/client/src/redux/messaging/messaging.sagas.js index 2ee7a8bac..d2b428e1f 100644 --- a/client/src/redux/messaging/messaging.sagas.js +++ b/client/src/redux/messaging/messaging.sagas.js @@ -68,24 +68,23 @@ export function* openChatByPhone({ payload }) { const createdConversation = newConversations[0]; // Get the newly created conversation - // // Emit event for new conversation with full details - if (socket) { - socket.emit("conversation-modified", { - bodyshopId: bodyshop.id, - type: "conversation-created", - ...createdConversation - }); - } + // Emit event for new conversation with full details + socket.emit("conversation-modified", { + bodyshopId: bodyshop.id, + type: "conversation-created", + ...createdConversation + }); // Set the newly created conversation as selected yield put(setSelectedConversation(createdConversation.id)); } else if (conversations.length === 1) { const conversation = conversations[0]; + let updatedConversation = conversation; if (conversation.archived) { // Conversation is archived, unarchive it in the DB const { - data: { update_conversations_by_pk: updatedConversation } + data: { update_conversations_by_pk: unarchivedConversation } } = yield client.mutate({ mutation: TOGGLE_CONVERSATION_ARCHIVE, variables: { @@ -94,67 +93,26 @@ export function* openChatByPhone({ payload }) { } }); - if (socket) { - socket.emit("conversation-modified", { - type: "conversation-unarchived", - conversationId: updatedConversation.id, - bodyshopId: bodyshop.id, - archived: false - }); - } + updatedConversation = unarchivedConversation; - // Update the conversation list in the cache - const existingConversations = client.cache.readQuery({ - query: CONVERSATION_LIST_QUERY, - variables: { offset: 0 } - }); - - client.cache.writeQuery({ - query: CONVERSATION_LIST_QUERY, - variables: { offset: 0 }, - data: { - conversations: [ - { - ...conversation, - archived: false, - updated_at: new Date().toISOString() - }, - ...(existingConversations?.conversations || []) - ] - } - }); - } - - // Check if the conversation exists in the cache - const cacheId = client.cache.identify({ - __typename: "conversations", - id: conversation.id - }); - - if (!cacheId) { - // Fetch the conversation details from the database - const { data } = yield client.query({ - query: GET_CONVERSATION_DETAILS, - variables: { conversationId: conversation.id } - }); - - // Write fetched data to the cache - client.cache.writeQuery({ - query: GET_CONVERSATION_DETAILS, - variables: { conversationId: conversation.id }, - data + // Emit the unarchived event only once + socket.emit("conversation-modified", { + type: "conversation-unarchived", + conversationId: unarchivedConversation.id, + bodyshopId: bodyshop.id, + archived: false }); } // Open the conversation - yield put(setSelectedConversation(conversation.id)); + yield put(setSelectedConversation(updatedConversation.id)); // Check and add job tag if needed - if (jobid && !conversation.job_conversations.find((jc) => jc.jobid === jobid)) { + if (jobid && !updatedConversation.job_conversations.find((jc) => jc.jobid === jobid)) { yield client.mutate({ mutation: INSERT_CONVERSATION_TAG, variables: { - conversationId: conversation.id, + conversationId: updatedConversation.id, jobId: jobid } }); From 6504b27eca8d5d52193e2796fa16fa56aaa57831 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Thu, 21 Nov 2024 22:14:39 -0800 Subject: [PATCH 315/478] feature/IO-3000-messaging-sockets-migrations2 - - A lot of a lot of testing.... Signed-off-by: Dave Richer --- .../registerMessagingSocketHandlers.js | 453 ++++++++++-------- .../chat-conversation.container.jsx | 114 ++++- client/src/utils/GraphQLClient.js | 16 + server/graphql-client/queries.js | 3 + server/sms/status.js | 39 +- 5 files changed, 376 insertions(+), 249 deletions(-) diff --git a/client/src/components/chat-affix/registerMessagingSocketHandlers.js b/client/src/components/chat-affix/registerMessagingSocketHandlers.js index 76cc2c741..5b4f34ea1 100644 --- a/client/src/components/chat-affix/registerMessagingSocketHandlers.js +++ b/client/src/components/chat-affix/registerMessagingSocketHandlers.js @@ -14,40 +14,46 @@ export const registerMessagingHandlers = ({ socket, client }) => { const handleNewMessageSummary = async (message) => { const { conversationId, newConversation, existingConversation, isoutbound } = message; - logLocal("handleNewMessageSummary", message); + logLocal("handleNewMessageSummary - Start", { message, isNew: !existingConversation }); const queryVariables = { offset: 0 }; + // Utility function to enrich conversation data + const enrichConversation = (conversation, isOutbound) => ({ + ...conversation, + updated_at: conversation.updated_at || new Date().toISOString(), + unreadcnt: conversation.unreadcnt || 0, + archived: conversation.archived || false, + label: conversation.label || null, + job_conversations: conversation.job_conversations || [], + messages_aggregate: conversation.messages_aggregate || { + __typename: "messages_aggregate", + aggregate: { + __typename: "messages_aggregate_fields", + count: isOutbound ? 0 : 1 + } + }, + __typename: "conversations" + }); + // Handle new conversation if (!existingConversation && newConversation?.phone_num) { + logLocal("handleNewMessageSummary - New Conversation", newConversation); + try { const queryResults = client.cache.readQuery({ query: CONVERSATION_LIST_QUERY, variables: queryVariables }); - const enrichedConversation = { - ...newConversation, - updated_at: newConversation.updated_at || new Date().toISOString(), - unreadcnt: newConversation.unreadcnt || 0, - archived: newConversation.archived || false, - label: newConversation.label || null, - job_conversations: newConversation.job_conversations || [], - messages_aggregate: newConversation.messages_aggregate || { - __typename: "messages_aggregate", - aggregate: { - __typename: "messages_aggregate_fields", - count: isoutbound ? 0 : 1 - } - }, - __typename: "conversations" - }; + const enrichedConversation = enrichConversation(newConversation, isoutbound); - client.cache.writeQuery({ - query: CONVERSATION_LIST_QUERY, - variables: queryVariables, - data: { - conversations: [enrichedConversation, ...(queryResults?.conversations || [])] + client.cache.modify({ + id: "ROOT_QUERY", + fields: { + conversations(existingConversations = []) { + return [enrichedConversation, ...existingConversations]; + } } }); } catch (error) { @@ -60,13 +66,10 @@ export const registerMessagingHandlers = ({ socket, client }) => { if (existingConversation) { let conversationDetails; - // Fetch or read the conversation details + // Attempt to read existing conversation details from cache try { conversationDetails = client.cache.readFragment({ - id: client.cache.identify({ - __typename: "conversations", - id: conversationId - }), + id: client.cache.identify({ __typename: "conversations", id: conversationId }), fragment: gql` fragment ExistingConversation on conversations { id @@ -89,9 +92,10 @@ export const registerMessagingHandlers = ({ socket, client }) => { ` }); } catch (error) { - console.warn("Conversation not found in cache, querying server..."); + logLocal("handleNewMessageSummary - Cache miss for conversation, fetching from server", { conversationId }); } + // Fetch conversation details from server if not in cache if (!conversationDetails) { try { const { data } = await client.query({ @@ -106,12 +110,14 @@ export const registerMessagingHandlers = ({ socket, client }) => { } } + // Validate that conversation details were retrieved if (!conversationDetails) { console.error("Unable to retrieve conversation details. Skipping cache update."); return; } try { + // Check if the conversation is already in the cache const queryResults = client.cache.readQuery({ query: CONVERSATION_LIST_QUERY, variables: queryVariables @@ -120,46 +126,32 @@ export const registerMessagingHandlers = ({ socket, client }) => { const isAlreadyInCache = queryResults?.conversations.some((conv) => conv.id === conversationId); if (!isAlreadyInCache) { - const enrichedConversation = { - ...conversationDetails, - archived: false, - __typename: "conversations", - messages_aggregate: { - __typename: "messages_aggregate", - aggregate: { - __typename: "messages_aggregate_fields", - count: - conversationDetails.messages?.filter( - (message) => !message.read && !message.isoutbound // Count unread, inbound messages - ).length || 0 - } - } - }; + const enrichedConversation = enrichConversation(conversationDetails, isoutbound); - client.cache.writeQuery({ - query: CONVERSATION_LIST_QUERY, - variables: queryVariables, - data: { - conversations: [enrichedConversation, ...(queryResults?.conversations || [])] + client.cache.modify({ + id: "ROOT_QUERY", + fields: { + conversations(existingConversations = []) { + return [enrichedConversation, ...existingConversations]; + } } }); } - // Update existing conversation fields + + // Update fields for the existing conversation in the cache client.cache.modify({ - id: client.cache.identify({ - __typename: "conversations", - id: conversationId - }), + id: client.cache.identify({ __typename: "conversations", id: conversationId }), fields: { updated_at: () => new Date().toISOString(), archived: () => false, - messages_aggregate(cached) { + messages_aggregate(cached = { aggregate: { count: 0 } }) { + const currentCount = cached.aggregate?.count || 0; if (!isoutbound) { return { __typename: "messages_aggregate", aggregate: { __typename: "messages_aggregate_fields", - count: cached.aggregate.count + 1 + count: currentCount + 1 } }; } @@ -176,80 +168,107 @@ export const registerMessagingHandlers = ({ socket, client }) => { const handleNewMessageDetailed = (message) => { const { conversationId, newMessage } = message; - logLocal("handleNewMessageDetailed", message); + logLocal("handleNewMessageDetailed - Start", message); - // Append the new message to the conversation's message list - const queryResults = client.cache.readQuery({ - query: GET_CONVERSATION_DETAILS, - variables: { conversationId } - }); - - if (queryResults) { - client.cache.writeQuery({ + try { + // Check if the conversation exists in the cache + const queryResults = client.cache.readQuery({ query: GET_CONVERSATION_DETAILS, - variables: { conversationId }, - data: { - ...queryResults, - conversations_by_pk: { - ...queryResults.conversations_by_pk, - messages: [...queryResults.conversations_by_pk.messages, newMessage] + variables: { conversationId } + }); + + if (!queryResults?.conversations_by_pk) { + console.warn("Conversation not found in cache:", { conversationId }); + return; + } + + // Append the new message to the conversation's message list using cache.modify + client.cache.modify({ + id: client.cache.identify({ __typename: "conversations", id: conversationId }), + fields: { + messages(existingMessages = []) { + return [...existingMessages, newMessage]; } } }); + + logLocal("handleNewMessageDetailed - Message appended successfully", { conversationId, newMessage }); + } catch (error) { + console.error("Error updating conversation messages in cache:", error); } }; const handleMessageChanged = (message) => { - if (!message) return; + if (!message) { + logLocal("handleMessageChanged - No message provided", message); + return; + } - logLocal("handleMessageChanged", message); + logLocal("handleMessageChanged - Start", message); - client.cache.modify({ - id: client.cache.identify({ __typename: "conversations", id: message.conversationid }), - fields: { - ...(message.type === "status-changed" && { - messages(existing = [], { readField }) { - return existing.map((messageRef) => { - // Match the message by ID + try { + client.cache.modify({ + id: client.cache.identify({ __typename: "conversations", id: message.conversationid }), + fields: { + messages(existingMessages = [], { readField }) { + return existingMessages.map((messageRef) => { + // Check if this is the message to update if (readField("id", messageRef) === message.id) { const currentStatus = readField("status", messageRef); - // Prevent overwriting if the current status is already "delivered" - if (currentStatus === "delivered") { - return messageRef; - } - - // Update the existing message fields - return client.cache.writeFragment({ - id: messageRef.__ref, - fragment: gql` - fragment UpdatedMessage on messages { - id - status - conversationid - __typename + // Handle known types of message changes + switch (message.type) { + case "status-changed": + // Prevent overwriting if the current status is already "delivered" + if (currentStatus === "delivered") { + logLocal("handleMessageChanged - Status already delivered, skipping update", { + messageId: message.id + }); + return messageRef; } - `, - data: { - __typename: "messages", - ...message // Only update the fields provided in the message object - } - }); + + // Update the status field + return { + ...messageRef, + status: message.status + }; + + case "text-updated": + // Handle changes to the message text + return { + ...messageRef, + text: message.text + }; + + // Add cases for other known message types as needed + + default: + // Log a warning for unhandled message types + logLocal("handleMessageChanged - Unhandled message type", { type: message.type }); + return messageRef; + } } return messageRef; // Keep other messages unchanged }); } - }) - } - }); + } + }); + + logLocal("handleMessageChanged - Message updated successfully", { messageId: message.id, type: message.type }); + } catch (error) { + console.error("handleMessageChanged - Error modifying cache:", error); + } }; const handleConversationChanged = async (data) => { - if (!data) return; + if (!data) { + logLocal("handleConversationChanged - No data provided", data); + return; + } - const { conversationId, type, job_conversations, ...fields } = data; - logLocal("handleConversationChanged", data); + const { conversationId, type, job_conversations, messageIds, ...fields } = data; + logLocal("handleConversationChanged - Start", data); const updatedAt = new Date().toISOString(); @@ -263,9 +282,7 @@ export const registerMessagingHandlers = ({ socket, client }) => { const updatedList = existingList?.conversations ? [ newConversation, - ...existingList.conversations.filter( - (conv) => conv.id !== newConversation.id // Prevent duplicates - ) + ...existingList.conversations.filter((conv) => conv.id !== newConversation.id) // Prevent duplicates ] : [newConversation]; @@ -276,129 +293,149 @@ export const registerMessagingHandlers = ({ socket, client }) => { conversations: updatedList } }); + + logLocal("handleConversationChanged - Conversation list updated successfully", newConversation); } catch (error) { console.error("Error updating conversation list in the cache:", error); } }; - if (type === "conversation-created") { - updateConversationList({ ...fields, job_conversations, updated_at: updatedAt }); - return; - } + // Handle specific types + try { + switch (type) { + case "conversation-marked-read": + if (conversationId && messageIds?.length > 0) { + client.cache.modify({ + id: client.cache.identify({ __typename: "conversations", id: conversationId }), + fields: { + messages(existingMessages = [], { readField }) { + return existingMessages.map((message) => { + if (messageIds.includes(readField("id", message))) { + return { ...message, read: true }; + } + return message; + }); + }, + messages_aggregate: () => ({ + __typename: "messages_aggregate", + aggregate: { __typename: "messages_aggregate_fields", count: 0 } + }) + } + }); + } + break; - const cacheId = client.cache.identify({ - __typename: "conversations", - id: conversationId - }); + case "conversation-created": + updateConversationList({ ...fields, job_conversations, updated_at: updatedAt }); + break; - if (!cacheId) { - console.error(`Could not find conversation with id: ${conversationId}`); - return; - } + case "conversation-unarchived": + case "conversation-archived": + // Would like to someday figure out how to get this working without refetch queries, + // But I have but a solid 4 hours into it, and there are just too many weird occurrences + try { + const listQueryVariables = { offset: 0 }; + const detailsQueryVariables = { conversationId }; - if (type === "conversation-unarchived" || type === "conversation-archived") { - try { - const listQueryVariables = { offset: 0 }; - const detailsQueryVariables = { conversationId }; + // Refetch conversation list and details + await client.refetchQueries({ + include: [CONVERSATION_LIST_QUERY, GET_CONVERSATION_DETAILS], + variables: [ + { query: CONVERSATION_LIST_QUERY, variables: listQueryVariables }, + { query: GET_CONVERSATION_DETAILS, variables: detailsQueryVariables } + ] + }); - // Refetch the conversation list and details queries - await client.refetchQueries({ - include: [CONVERSATION_LIST_QUERY, GET_CONVERSATION_DETAILS], - variables: [ - { query: CONVERSATION_LIST_QUERY, variables: listQueryVariables }, - { query: GET_CONVERSATION_DETAILS, variables: detailsQueryVariables } - ] - }); + logLocal("handleConversationChanged - Refetched queries after state change", { conversationId, type }); + } catch (error) { + console.error("Error refetching queries after conversation state change:", error); + } + break; - console.log("Refetched conversation list and details after state change."); - } catch (error) { - console.error("Error refetching queries after conversation state change:", error); + case "tag-added": + client.cache.modify({ + id: client.cache.identify({ __typename: "conversations", id: conversationId }), + fields: { + job_conversations: (existing = []) => [...existing, ...job_conversations] + } + }); + break; + + case "tag-removed": + client.cache.modify({ + id: client.cache.identify({ __typename: "conversations", id: conversationId }), + fields: { + job_conversations: (existing = [], { readField }) => + existing.filter((jobRef) => readField("jobid", jobRef) !== fields.jobId) + } + }); + break; + + default: + logLocal("handleConversationChanged - Unhandled type", { type }); + client.cache.modify({ + id: client.cache.identify({ __typename: "conversations", id: conversationId }), + fields: { + ...Object.fromEntries( + Object.entries(fields).map(([key, value]) => [key, (cached) => (value !== undefined ? value : cached)]) + ) + } + }); } - - return; + } catch (error) { + console.error("Error handling conversation changes:", { type, error }); } - // Handle other types of updates (e.g., marked read, tags added/removed) - client.cache.modify({ - id: cacheId, - fields: { - ...Object.fromEntries( - Object.entries(fields).map(([key, value]) => [key, (cached) => (value !== undefined ? value : cached)]) - ), - ...(type === "conversation-marked-read" && { - messages_aggregate: () => ({ - __typename: "messages_aggregate", - aggregate: { __typename: "messages_aggregate_fields", count: 0 } - }) - }), - ...(type === "tag-added" && { - job_conversations: (existing = []) => [...existing, ...job_conversations] - }), - ...(type === "tag-removed" && { - job_conversations: (existing = [], { readField }) => - existing.filter((jobRef) => readField("jobid", jobRef) !== data.jobId) - }) - } - }); }; const handleNewMessage = ({ conversationId, message }) => { if (!conversationId || !message?.id || !message?.text) { + logLocal("handleNewMessage - Missing conversationId or message details", { conversationId, message }); return; } - logLocal("handleNewMessage", { conversationId, message }); + logLocal("handleNewMessage - Start", { conversationId, message }); - client.cache.modify({ - id: client.cache.identify({ __typename: "conversations", id: conversationId }), - fields: { - messages(existing = []) { - // Ensure that the `message` object matches the schema - const newMessageRef = client.cache.writeFragment({ - data: { - __typename: "messages", - id: message.id, - body: message.text, - selectedMedia: message.image_path || [], - imexshopid: message.userid, - status: message.status, - created_at: message.created_at, - read: message.read - }, - fragment: gql` - fragment NewMessage on messages { - id - body - selectedMedia - imexshopid - status - created_at - read - } - ` - }); + try { + // Add the new message to the cache + client.cache.modify({ + id: client.cache.identify({ __typename: "conversations", id: conversationId }), + fields: { + messages(existing = []) { + // Write the new message to the cache + const newMessageRef = client.cache.writeFragment({ + data: { + __typename: "messages", + id: message.id, + text: message.text, + selectedMedia: message.image_path || [], + imexshopid: message.userid, + status: message.status, + created_at: message.created_at, + read: message.read + }, + fragment: gql` + fragment NewMessage on messages { + id + text + selectedMedia + imexshopid + status + created_at + read + } + ` + }); - // Prevent duplicates by checking if the message already exists - const isDuplicate = existing.some( - (msgRef) => - client.cache.readFragment({ - id: msgRef.__ref, - fragment: gql` - fragment CheckMessage on messages { - id - } - ` - })?.id === message.id - ); - - // We already have it, so return the existing list - if (isDuplicate) { - return existing; + // The merge function defined in the cache will handle deduplication + return [...existing, newMessageRef]; } - - return [...existing, newMessageRef]; // Add the new message reference } - } - }); + }); + + logLocal("handleNewMessage - Message added to cache", { conversationId, messageId: message.id }); + } catch (error) { + console.error("handleNewMessage - Error modifying cache:", error); + } }; socket.on("new-message-summary", handleNewMessageSummary); diff --git a/client/src/components/chat-conversation/chat-conversation.container.jsx b/client/src/components/chat-conversation/chat-conversation.container.jsx index 613d96288..3b7f8385b 100644 --- a/client/src/components/chat-conversation/chat-conversation.container.jsx +++ b/client/src/components/chat-conversation/chat-conversation.container.jsx @@ -1,4 +1,4 @@ -import { useQuery } from "@apollo/client"; +import { useApolloClient, useQuery } from "@apollo/client"; import axios from "axios"; import React, { useContext, useEffect, useState } from "react"; import { connect } from "react-redux"; @@ -17,19 +17,73 @@ const mapStateToProps = createStructuredSelector({ export default connect(mapStateToProps, null)(ChatConversationContainer); export function ChatConversationContainer({ bodyshop, selectedConversation }) { + const client = useApolloClient(); + const { socket } = useContext(SocketContext); + const [markingAsReadInProgress, setMarkingAsReadInProgress] = useState(false); + const { loading: convoLoading, error: convoError, data: convoData } = useQuery(GET_CONVERSATION_DETAILS, { variables: { conversationId: selectedConversation }, - fetchPolicy: "network-only", - nextFetchPolicy: "network-only" + fetchPolicy: "network-only" }); - const { socket } = useContext(SocketContext); + // Utility to update Apollo cache + const updateCacheWithReadMessages = (conversationId, messageIds) => { + if (!conversationId || !messageIds || messageIds.length === 0) return; + + messageIds.forEach((messageId) => { + client.cache.modify({ + id: client.cache.identify({ __typename: "messages", id: messageId }), + fields: { + read() { + return true; // Mark message as read + } + } + }); + }); + + // Optionally update aggregate unread count + client.cache.modify({ + id: client.cache.identify({ __typename: "conversations", id: conversationId }), + fields: { + messages_aggregate(existingAggregate) { + const updatedAggregate = { + ...existingAggregate, + aggregate: { + ...existingAggregate.aggregate, + count: 0 // No unread messages remaining + } + }; + return updatedAggregate; + } + } + }); + }; + + // Handle WebSocket events + useEffect(() => { + if (!socket || !socket.connected) return; + + const handleConversationChange = (data) => { + if (data.type === "conversation-marked-read") { + const { conversationId, messageIds } = data; + console.log("Conversation change received:", data); + updateCacheWithReadMessages(conversationId, messageIds); + } + }; + + socket.on("conversation-changed", handleConversationChange); + + return () => { + socket.off("conversation-changed", handleConversationChange); + }; + }, [socket, client]); + + // Handle joining/leaving conversation useEffect(() => { - // Early gate, we have no socket, bail. if (!socket || !socket.connected) return; socket.emit("join-bodyshop-conversation", { @@ -45,25 +99,41 @@ export function ChatConversationContainer({ bodyshop, selectedConversation }) { }; }, [selectedConversation, bodyshop, socket]); - const [markingAsReadInProgress, setMarkingAsReadInProgress] = useState(false); - - const unreadCount = - convoData && - convoData.conversations_by_pk && - convoData.conversations_by_pk.messages && - convoData.conversations_by_pk.messages.reduce((acc, val) => { - return !val.read && !val.isoutbound ? acc + 1 : acc; - }, 0); - + // Handle marking conversation as read const handleMarkConversationAsRead = async () => { - if (unreadCount > 0 && !!selectedConversation && !markingAsReadInProgress) { + if (!convoData || !selectedConversation || markingAsReadInProgress) return; + + const conversation = convoData.conversations_by_pk; + if (!conversation) { + console.warn(`No data found for conversation ID: ${selectedConversation}`); + return; + } + + const unreadMessageIds = conversation.messages + ?.filter((message) => !message.read && !message.isoutbound) + .map((message) => message.id); + + if (unreadMessageIds?.length > 0) { setMarkingAsReadInProgress(true); - await axios.post("/sms/markConversationRead", { - conversationid: selectedConversation, - imexshopid: bodyshop.imexshopid, - bodyshopid: bodyshop.id - }); - setMarkingAsReadInProgress(false); + + try { + const payload = { + conversation, + imexshopid: bodyshop?.imexshopid, + bodyshopid: bodyshop?.id + }; + + console.log("Marking conversation as read:", payload); + + await axios.post("/sms/markConversationRead", payload); + + // Update local cache + updateCacheWithReadMessages(selectedConversation, unreadMessageIds); + } catch (error) { + console.error("Error marking conversation as read:", error.response?.data || error.message); + } finally { + setMarkingAsReadInProgress(false); + } } }; diff --git a/client/src/utils/GraphQLClient.js b/client/src/utils/GraphQLClient.js index e0d409bd7..423c38e54 100644 --- a/client/src/utils/GraphQLClient.js +++ b/client/src/utils/GraphQLClient.js @@ -162,6 +162,22 @@ const cache = new InMemoryCache({ (incomingItem) => !existing.some((existingItem) => existingItem.__ref === incomingItem.__ref) ) ]; + return merged; + } + }, + messages: { + keyArgs: false, // Ignore arguments when determining uniqueness (like `order_by`). + merge(existing = [], incoming = [], { readField }) { + const existingIds = new Set(existing.map((message) => readField("id", message))); + + // Merge incoming messages, avoiding duplicates + const merged = [...existing]; + incoming.forEach((message) => { + if (!existingIds.has(readField("id", message))) { + merged.push(message); + } + }); + return merged; } } diff --git a/server/graphql-client/queries.js b/server/graphql-client/queries.js index 72224dfb6..e70144775 100644 --- a/server/graphql-client/queries.js +++ b/server/graphql-client/queries.js @@ -2569,6 +2569,9 @@ exports.GET_JOBS_BY_PKS = `query GET_JOBS_BY_PKS($ids: [uuid!]!) { exports.MARK_MESSAGES_AS_READ = `mutation MARK_MESSAGES_AS_READ($conversationId: uuid!) { update_messages(where: { conversationid: { _eq: $conversationId } }, _set: { read: true }) { + returning { + id + } affected_rows } } diff --git a/server/sms/status.js b/server/sms/status.js index 51d2f7ecb..0e29bbf8f 100644 --- a/server/sms/status.js +++ b/server/sms/status.js @@ -58,48 +58,49 @@ exports.status = async (req, res) => { logger.log("sms-status-update-error", "ERROR", "api", null, { msid: SmsSid, fields: { status: SmsStatus }, - error + stack: error.stack, + message: error.message }); res.status(500).json({ error: "Failed to update message status." }); } }; exports.markConversationRead = async (req, res) => { - const { conversationid, imexshopid, bodyshopid } = req.body; const { ioRedis, ioHelpers: { getBodyshopRoom, getBodyshopConversationRoom } } = req; + const { conversation, imexshopid, bodyshopid } = req.body; + + // Alternatively, support both payload formats + const conversationId = conversation?.id || req.body.conversationId; + + if (!conversationId || !imexshopid || !bodyshopid) { + return res.status(400).json({ error: "Invalid conversation data provided." }); + } try { - // Mark messages in the conversation as read const response = await client.request(queries.MARK_MESSAGES_AS_READ, { - conversationId: conversationid + conversationId }); - const updatedMessages = response.update_messages.affected_rows; - - logger.log("conversation-mark-read", "DEBUG", "api", null, { - conversationid, - imexshopid, - bodyshopid, - updatedMessages - }); + const updatedMessageIds = response.update_messages.returning.map((message) => message.id); const broadcastRoom = getBodyshopRoom(bodyshopid); ioRedis.to(broadcastRoom).emit("conversation-changed", { type: "conversation-marked-read", - conversationId: conversationid + conversationId, + affectedMessages: response.update_messages.affected_rows, + messageIds: updatedMessageIds }); - res.status(200).json({ success: true, message: "Conversation marked as read." }); - } catch (error) { - logger.log("conversation-mark-read-error", "ERROR", "api", null, { - conversationid, - imexshopid, - error + res.status(200).json({ + success: true, + message: "Conversation marked as read." }); + } catch (error) { + console.error("Error marking conversation as read:", error); res.status(500).json({ error: "Failed to mark conversation as read." }); } }; From 3ab471e6297626aaf658cd63bd32b8bba5f9a3d9 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Fri, 22 Nov 2024 08:23:24 -0800 Subject: [PATCH 316/478] feature/IO-3000-messaging-sockets-migrations2 - - Final fix of unread messagages Signed-off-by: Dave Richer --- .../chat-popup/chat-popup.component.jsx | 37 ++++++++++++++----- client/src/redux/messaging/messaging.sagas.js | 2 - 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/client/src/components/chat-popup/chat-popup.component.jsx b/client/src/components/chat-popup/chat-popup.component.jsx index e67929d11..f99738cb1 100644 --- a/client/src/components/chat-popup/chat-popup.component.jsx +++ b/client/src/components/chat-popup/chat-popup.component.jsx @@ -1,11 +1,11 @@ import { InfoCircleOutlined, MessageOutlined, ShrinkOutlined, SyncOutlined } from "@ant-design/icons"; -import { useLazyQuery, useQuery } from "@apollo/client"; +import { useApolloClient, useLazyQuery } from "@apollo/client"; import { Badge, Card, Col, Row, Space, Tag, Tooltip, Typography } from "antd"; -import React, { useCallback, useContext, useEffect, useState } from "react"; +import React, { useContext, useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; import { createStructuredSelector } from "reselect"; -import { CONVERSATION_LIST_QUERY, UNREAD_CONVERSATION_COUNT } from "../../graphql/conversations.queries"; +import { CONVERSATION_LIST_QUERY } from "../../graphql/conversations.queries"; import { toggleChatVisible } from "../../redux/messaging/messaging.actions"; import { selectChatVisible, selectSelectedConversation } from "../../redux/messaging/messaging.selectors"; import ChatConversationListComponent from "../chat-conversation-list/chat-conversation-list.component"; @@ -28,13 +28,9 @@ export function ChatPopupComponent({ chatVisible, selectedConversation, toggleCh const { t } = useTranslation(); const [pollInterval, setPollInterval] = useState(0); const { socket } = useContext(SocketContext); + const client = useApolloClient(); // Apollo Client instance for cache operations - const { data: unreadData } = useQuery(UNREAD_CONVERSATION_COUNT, { - fetchPolicy: "network-only", - nextFetchPolicy: "network-only", - ...(pollInterval > 0 ? { pollInterval } : {}) - }); - + // Lazy query for conversations const [getConversations, { loading, data, refetch, fetchMore }] = useLazyQuery(CONVERSATION_LIST_QUERY, { fetchPolicy: "network-only", nextFetchPolicy: "network-only", @@ -42,6 +38,7 @@ export function ChatPopupComponent({ chatVisible, selectedConversation, toggleCh ...(pollInterval > 0 ? { pollInterval } : {}) }); + // Socket connection status useEffect(() => { const handleSocketStatus = () => { if (socket?.connected) { @@ -66,6 +63,7 @@ export function ChatPopupComponent({ chatVisible, selectedConversation, toggleCh }; }, [socket]); + // Fetch conversations when chat becomes visible useEffect(() => { if (chatVisible) getConversations({ @@ -77,7 +75,26 @@ export function ChatPopupComponent({ chatVisible, selectedConversation, toggleCh }); }, [chatVisible, getConversations]); - const unreadCount = unreadData?.messages_aggregate?.aggregate?.count || 0; + // Get unread count from the cache + const unreadCount = (() => { + try { + const cachedData = client.readQuery({ + query: CONVERSATION_LIST_QUERY, + variables: { offset: 0 } + }); + + if (!cachedData?.conversations) return 0; + + // Aggregate unread message count + return cachedData.conversations.reduce((total, conversation) => { + const unread = conversation.messages_aggregate?.aggregate?.count || 0; + return total + unread; + }, 0); + } catch (error) { + console.warn("Unread count not found in cache:", error); + return 0; // Fallback if not in cache + } + })(); return ( diff --git a/client/src/redux/messaging/messaging.sagas.js b/client/src/redux/messaging/messaging.sagas.js index d2b428e1f..012c05618 100644 --- a/client/src/redux/messaging/messaging.sagas.js +++ b/client/src/redux/messaging/messaging.sagas.js @@ -4,9 +4,7 @@ import { all, call, put, select, takeLatest } from "redux-saga/effects"; import { logImEXEvent } from "../../firebase/firebase.utils"; import { CONVERSATION_ID_BY_PHONE, - CONVERSATION_LIST_QUERY, CREATE_CONVERSATION, - GET_CONVERSATION_DETAILS, TOGGLE_CONVERSATION_ARCHIVE } from "../../graphql/conversations.queries"; import { INSERT_CONVERSATION_TAG } from "../../graphql/job-conversations.queries"; From eacadc01bd15f05affa838de9d8d47247800445f Mon Sep 17 00:00:00 2001 From: Patrick Fic Date: Fri, 22 Nov 2024 08:26:46 -0800 Subject: [PATCH 317/478] IO-3020 IO-3036 Resolve Linting Issues and implement ES9 --- .vscode/settings.json | 3 +- client/eslint.config.js | 12 ++ client/package-lock.json | 217 +++++++++++++++++----------- client/package.json | 12 +- eslint.config.mjs | 10 ++ server/firebase/firebase-handler.js | 7 +- server/job/job-costing.js | 5 +- 7 files changed, 167 insertions(+), 99 deletions(-) create mode 100644 client/eslint.config.js create mode 100644 eslint.config.mjs diff --git a/.vscode/settings.json b/.vscode/settings.json index 74b58f715..b8f4d4e1c 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -38,5 +38,6 @@ "smartscheduling", "timetickets", "touchtime" - ] + ], + "eslint.workingDirectories": ["./", "./client"] } diff --git a/client/eslint.config.js b/client/eslint.config.js new file mode 100644 index 000000000..b1f7dd1c2 --- /dev/null +++ b/client/eslint.config.js @@ -0,0 +1,12 @@ +import globals from "globals"; +import pluginJs from "@eslint/js"; +import pluginReact from "eslint-plugin-react"; + +/** @type {import('eslint').Linter.Config[]} */ +export default [ + { files: ["**/*.{js,mjs,cjs,jsx}"] }, + { languageOptions: { globals: globals.browser } }, + pluginJs.configs.recommended, + pluginReact.configs.flat.recommended, // This is not a plugin object, but a shareable config object + pluginReact.configs.flat["jsx-runtime"] // Add this if you are using React 17+ +]; diff --git a/client/package-lock.json b/client/package-lock.json index 93b492582..43093f1d5 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -90,6 +90,7 @@ "@dotenvx/dotenvx": "^1.14.1", "@emotion/babel-plugin": "^11.12.0", "@emotion/react": "^11.13.3", + "@eslint/js": "^9.15.0", "@sentry/webpack-plugin": "^2.22.4", "@testing-library/cypress": "^10.0.2", "browserslist": "^4.23.3", @@ -97,9 +98,11 @@ "chalk": "^5.3.0", "cross-env": "^7.0.3", "cypress": "^13.14.2", - "eslint": "^8.57.0", + "eslint": "^8.57.1", "eslint-config-react-app": "^7.0.1", "eslint-plugin-cypress": "^2.15.1", + "eslint-plugin-react": "^7.37.2", + "globals": "^15.12.0", "memfs": "^4.12.0", "os-browserify": "^0.3.0", "react-error-overlay": "6.0.11", @@ -1524,6 +1527,16 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-transform-classes/node_modules/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, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/plugin-transform-computed-properties": { "version": "7.24.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.6.tgz", @@ -2536,6 +2549,15 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/traverse/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/types": { "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.7.tgz", @@ -3429,12 +3451,13 @@ } }, "node_modules/@eslint/js": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", - "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "version": "9.15.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.15.0.tgz", + "integrity": "sha512-tMTqrY+EzbXmKJR5ToI8lxu7jaN5EdmrBFJpQk5JmSlyLsx6o4t27r883K5xsLuCYCpfKBCGswMSWXsM+jB7lg==", "dev": true, + "license": "MIT", "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@fingerprintjs/fingerprintjs": { @@ -4033,12 +4056,14 @@ } }, "node_modules/@humanwhocodes/config-array": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", - "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", + "deprecated": "Use @eslint/config-array instead", "dev": true, + "license": "Apache-2.0", "dependencies": { - "@humanwhocodes/object-schema": "^2.0.2", + "@humanwhocodes/object-schema": "^2.0.3", "debug": "^4.3.1", "minimatch": "^3.0.5" }, @@ -4051,6 +4076,7 @@ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -4061,6 +4087,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -4085,7 +4112,9 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "dev": true + "deprecated": "Use @eslint/object-schema instead", + "dev": true, + "license": "BSD-3-Clause" }, "node_modules/@icons/material": { "version": "0.2.4", @@ -6547,29 +6576,21 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/array.prototype.toreversed": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/array.prototype.toreversed/-/array.prototype.toreversed-1.1.2.tgz", - "integrity": "sha512-wwDCoT4Ck4Cz7sLtgUmzR5UV3YF5mFHUlbChCzZBQZ+0m2cl/DH3tKgvphv1nKgFsJ48oCSg6p91q2Vm0I/ZMA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" - } - }, "node_modules/array.prototype.tosorted": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.3.tgz", - "integrity": "sha512-/DdH4TiTmOKzyQbp/eadcCVexiCb36xJg7HshYOYJnNZFDj33GEv0P7GxsynpShhq4OLYJzbGcBDkLsDt7MnNg==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", + "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.5", + "call-bind": "^1.0.7", "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.1.0", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" } }, "node_modules/arraybuffer.prototype.slice": { @@ -8859,10 +8880,11 @@ } }, "node_modules/es-iterator-helpers": { - "version": "1.0.19", - "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.19.tgz", - "integrity": "sha512-zoMwbCcH5hwUkKJkT8kDIBZSz9I6mVG//+lDCinLCGov4+r7NIy0ld8o03M0cJxl2spVf6ESYVS6/gpIfq1FFw==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.2.0.tgz", + "integrity": "sha512-tpxqxncxnpw3c93u8n3VOzACmRFoVmWJqbWXvX/JfKbkhBw1oslgPrUfeSt2psuqyEJFD6N/9lg5i7bsKpoq+Q==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -8871,12 +8893,13 @@ "es-set-tostringtag": "^2.0.3", "function-bind": "^1.1.2", "get-intrinsic": "^1.2.4", - "globalthis": "^1.0.3", + "globalthis": "^1.0.4", + "gopd": "^1.0.1", "has-property-descriptors": "^1.0.2", "has-proto": "^1.0.3", "has-symbols": "^1.0.3", "internal-slot": "^1.0.7", - "iterator.prototype": "^1.1.2", + "iterator.prototype": "^1.1.3", "safe-array-concat": "^1.1.2" }, "engines": { @@ -9006,16 +9029,18 @@ } }, "node_modules/eslint": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", - "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", + "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", "dev": true, + "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.0", - "@humanwhocodes/config-array": "^0.11.14", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", "@ungap/structured-clone": "^1.2.0", @@ -9357,35 +9382,36 @@ } }, "node_modules/eslint-plugin-react": { - "version": "7.34.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.34.1.tgz", - "integrity": "sha512-N97CxlouPT1AHt8Jn0mhhN2RrADlUAsk1/atcT2KyA/l9Q/E6ll7OIGwNumFmWfZ9skV3XXccYS19h80rHtgkw==", + "version": "7.37.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.2.tgz", + "integrity": "sha512-EsTAnj9fLVr/GZleBLFbj/sSuXeWmp1eXIN60ceYnZveqEaUCyW4X+Vh4WTdUhCkW4xutXYqTXCUSyqD4rB75w==", "dev": true, + "license": "MIT", "dependencies": { - "array-includes": "^3.1.7", - "array.prototype.findlast": "^1.2.4", + "array-includes": "^3.1.8", + "array.prototype.findlast": "^1.2.5", "array.prototype.flatmap": "^1.3.2", - "array.prototype.toreversed": "^1.1.2", - "array.prototype.tosorted": "^1.1.3", + "array.prototype.tosorted": "^1.1.4", "doctrine": "^2.1.0", - "es-iterator-helpers": "^1.0.17", + "es-iterator-helpers": "^1.1.0", "estraverse": "^5.3.0", + "hasown": "^2.0.2", "jsx-ast-utils": "^2.4.1 || ^3.0.0", "minimatch": "^3.1.2", - "object.entries": "^1.1.7", - "object.fromentries": "^2.0.7", - "object.hasown": "^1.1.3", - "object.values": "^1.1.7", + "object.entries": "^1.1.8", + "object.fromentries": "^2.0.8", + "object.values": "^1.2.0", "prop-types": "^15.8.1", "resolve": "^2.0.0-next.5", "semver": "^6.3.1", - "string.prototype.matchall": "^4.0.10" + "string.prototype.matchall": "^4.0.11", + "string.prototype.repeat": "^1.0.0" }, "engines": { "node": ">=4" }, "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" } }, "node_modules/eslint-plugin-react-hooks": { @@ -9504,6 +9530,16 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint/node_modules/@eslint/js": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, "node_modules/eslint/node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -10426,11 +10462,16 @@ "integrity": "sha512-5e01v8eLGfuQSOvx2MsDMOWS0GFtCx1wPzQSmcHw4hkxFzrQDBO3Xwg/m8Hr/7qXMrHeOIE29qWVzyv06u1TZA==" }, "node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "version": "15.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.12.0.tgz", + "integrity": "sha512-1+gLErljJFhbOVyaetcwJiJ4+eLe45S2E7P5UiZ9xGfeq3ATQf5DOv9G7MH3gGbKQLkzmNh2DxfZwLdw+j6oTQ==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=4" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/globalthis": { @@ -11033,6 +11074,7 @@ "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", "dev": true, + "license": "MIT", "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -11226,6 +11268,7 @@ "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz", "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.2" }, @@ -11298,6 +11341,7 @@ "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -11421,6 +11465,7 @@ "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -11523,6 +11568,7 @@ "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -11547,6 +11593,7 @@ "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.3.tgz", "integrity": "sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "get-intrinsic": "^1.2.4" @@ -11602,16 +11649,20 @@ "integrity": "sha512-QZ9qOMdF+QLHxy1QIpUHUU1D5pS2CG2P69LF6L6CPjPYA/XMOmKV3PZpawHoAjHNyB0swdVTRxdYT4tbBbxqwg==" }, "node_modules/iterator.prototype": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz", - "integrity": "sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.3.tgz", + "integrity": "sha512-FW5iMbeQ6rBGm/oKgzq2aW4KvAGpxPzYES8N4g4xNXUKpL1mclMvOe+76AcLDTvD+Ze+sOpVhgdAQEKF4L9iGQ==", "dev": true, + "license": "MIT", "dependencies": { "define-properties": "^1.2.1", "get-intrinsic": "^1.2.1", "has-symbols": "^1.0.3", "reflect.getprototypeof": "^1.0.4", "set-function-name": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" } }, "node_modules/jake": { @@ -13270,23 +13321,6 @@ "node": ">= 0.4" } }, - "node_modules/object.hasown": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.4.tgz", - "integrity": "sha512-FZ9LZt9/RHzGySlBARE3VF+gE26TxR38SdmqOqliuTnl9wrKulaQs+4dee1V+Io8VfxqzAfHu6YuRgUy8OHoTg==", - "dev": true, - "dependencies": { - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/object.values": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", @@ -15218,6 +15252,7 @@ "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz", "integrity": "sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -16206,6 +16241,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/string.prototype.repeat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", + "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, "node_modules/string.prototype.trim": { "version": "1.2.9", "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", @@ -17865,13 +17911,14 @@ } }, "node_modules/which-builtin-type": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.3.tgz", - "integrity": "sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.4.tgz", + "integrity": "sha512-bppkmBSsHFmIMSl8BO9TbsyzsvGjVoppt8xUiGzwiu/bhDCGxnpOKCxgqj6GuyHE0mINMDecBFPlOm2hzY084w==", "dev": true, + "license": "MIT", "dependencies": { - "function.prototype.name": "^1.1.5", - "has-tostringtag": "^1.0.0", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", "is-async-function": "^2.0.0", "is-date-object": "^1.0.5", "is-finalizationregistry": "^1.0.2", @@ -17880,8 +17927,8 @@ "is-weakref": "^1.0.2", "isarray": "^2.0.5", "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.9" + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.15" }, "engines": { "node": ">= 0.4" @@ -17894,13 +17941,15 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/which-collection": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", "dev": true, + "license": "MIT", "dependencies": { "is-map": "^2.0.3", "is-set": "^2.0.3", diff --git a/client/package.json b/client/package.json index e362eade1..fa4a2b126 100644 --- a/client/package.json +++ b/client/package.json @@ -102,13 +102,6 @@ "eulaize": "node src/utils/eulaize.js", "sentry:sourcemaps:imex": "sentry-cli sourcemaps inject --org imex --project imexonline ./build && sentry-cli sourcemaps upload --org imex --project imexonline ./build" }, - "eslintConfig": { - "extends": [ - "react-app", - "react-app/jest", - "plugin:cypress/recommended" - ] - }, "browserslist": { "production": [ ">0.2%", @@ -133,6 +126,7 @@ "@dotenvx/dotenvx": "^1.14.1", "@emotion/babel-plugin": "^11.12.0", "@emotion/react": "^11.13.3", + "@eslint/js": "^9.15.0", "@sentry/webpack-plugin": "^2.22.4", "@testing-library/cypress": "^10.0.2", "browserslist": "^4.23.3", @@ -140,9 +134,11 @@ "chalk": "^5.3.0", "cross-env": "^7.0.3", "cypress": "^13.14.2", - "eslint": "^8.57.0", + "eslint": "^8.57.1", "eslint-config-react-app": "^7.0.1", "eslint-plugin-cypress": "^2.15.1", + "eslint-plugin-react": "^7.37.2", + "globals": "^15.12.0", "memfs": "^4.12.0", "os-browserify": "^0.3.0", "react-error-overlay": "6.0.11", diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 000000000..bdafeda31 --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,10 @@ +import globals from "globals"; +import pluginJs from "@eslint/js"; + + +/** @type {import('eslint').Linter.Config[]} */ +export default [ + {files: ["**/*.js"], languageOptions: {sourceType: "commonjs"}}, + {languageOptions: { globals: globals.node }}, + pluginJs.configs.recommended, +]; diff --git a/server/firebase/firebase-handler.js b/server/firebase/firebase-handler.js index 60b864413..998bc68f8 100644 --- a/server/firebase/firebase-handler.js +++ b/server/firebase/firebase-handler.js @@ -5,10 +5,10 @@ require("dotenv").config({ const admin = require("firebase-admin"); const logger = require("../utils/logger"); -const { sendProManagerWelcomeEmail } = require("../email/sendemail"); +//const { sendProManagerWelcomeEmail } = require("../email/sendemail"); const client = require("../graphql-client/graphql-client").client; const serviceAccount = require(process.env.FIREBASE_ADMINSDK_JSON); -const generateEmailTemplate = require("../email/generateTemplate"); +//const generateEmailTemplate = require("../email/generateTemplate"); admin.initializeApp({ credential: admin.credential.cert(serviceAccount), @@ -299,6 +299,7 @@ const unsubscribe = async (req, res) => { res.json(result); } catch (error) { + logger.log("admin-unsubscribe-error", "ERROR", req.user.email, null, { error: error.message }); res.sendStatus(500); } }; @@ -308,7 +309,7 @@ module.exports = { createUser, updateUser, getUser, - sendPromanagerWelcomeEmail, + //sendPromanagerWelcomeEmail, sendNotification, subscribe, unsubscribe diff --git a/server/job/job-costing.js b/server/job/job-costing.js index 668a35673..961178c77 100644 --- a/server/job/job-costing.js +++ b/server/job/job-costing.js @@ -5,8 +5,7 @@ const logger = require("../utils/logger"); const InstanceManager = require("../utils/instanceMgr").default; const { DiscountNotAlreadyCounted } = InstanceManager({ imex: require("../job/job-totals"), - rome: require("../job/job-totals-USA"), - promanager: "USE_ROME" + rome: require("../job/job-totals-USA") }); // Dinero.defaultCurrency = "USD"; @@ -406,7 +405,7 @@ function GenerateCostingData(job) { ) { const discountRate = Math.abs(job.parts_tax_rates[val.part_type.toUpperCase()].prt_discp) > 1 - ? parts_tajob.parts_tax_rates_rates[val.part_type.toUpperCase()].prt_discp + ? job.parts_tax_rates_rates[val.part_type.toUpperCase()].prt_discp : job.parts_tax_rates[val.part_type.toUpperCase()].prt_discp * 100; const disc = partsAmount.percentage(discountRate).multiply(-1); partsAmount = partsAmount.add(disc); From 11ab7cd67effde073eda08811a0a77fdc341516b Mon Sep 17 00:00:00 2001 From: Patrick Fic Date: Fri, 22 Nov 2024 09:18:09 -0800 Subject: [PATCH 318/478] IO-3001 Null Coalesce for some items for better handling. --- server/accounting/qb-receivables-lines.js | 18 +++++++++--------- server/job/job-costing.js | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/server/accounting/qb-receivables-lines.js b/server/accounting/qb-receivables-lines.js index c257cd944..bed94f1d7 100644 --- a/server/accounting/qb-receivables-lines.js +++ b/server/accounting/qb-receivables-lines.js @@ -548,7 +548,7 @@ exports.default = function ({ bodyshop, jobs_by_pk, qbo = false, items, taxCodes } } - if (jobs_by_pk.job_totals.totals.ttl_adjustment) { + if (jobs_by_pk.job_totals.totals?.ttl_adjustment) { // Do not need to check for ImEX or Rome because ImEX uses a different totals calculation that will never set this field. if (qbo) { const taxAccountCode = findTaxCode( @@ -571,11 +571,11 @@ exports.default = function ({ bodyshop, jobs_by_pk, qbo = false, items, taxCodes InvoiceLineAdd.push({ DetailType: "SalesItemLineDetail", - Amount: Dinero(jobs_by_pk.job_totals.totals.ttl_adjustment).toFormat(DineroQbFormat), + Amount: Dinero(jobs_by_pk.job_totals.totals?.ttl_adjustment).toFormat(DineroQbFormat), SalesItemLineDetail: { ...(jobs_by_pk.class ? { ClassRef: { value: classes[jobs_by_pk.class] } } : {}), ItemRef: { - value: items[responsibilityCenters.ttl_adjustment.accountitem] + value: items[responsibilityCenters.ttl_adjustment?.accountitem] }, TaxCodeRef: { value: QboTaxId @@ -586,11 +586,11 @@ exports.default = function ({ bodyshop, jobs_by_pk, qbo = false, items, taxCodes } else { InvoiceLineAdd.push({ ItemRef: { - FullName: responsibilityCenters.ttl_adjustment.accountitem + FullName: responsibilityCenters.ttl_adjustment?.accountitem }, Desc: "Adjustment", Quantity: 1, - Amount: Dinero(jobs_by_pk.job_totals.totals.ttl_adjustment).toFormat(DineroQbFormat), + Amount: Dinero(jobs_by_pk.job_totals.totals?.ttl_adjustment).toFormat(DineroQbFormat), SalesTaxCodeRef: InstanceManager({ imex: { FullName: "E" @@ -902,11 +902,11 @@ exports.default = function ({ bodyshop, jobs_by_pk, qbo = false, items, taxCodes InvoiceLineAdd.push({ DetailType: "SalesItemLineDetail", - Amount: Dinero(jobs_by_pk.job_totals.totals.ttl_tax_adjustment).toFormat(DineroQbFormat), + Amount: Dinero(jobs_by_pk.job_totals.totals?.ttl_tax_adjustment).toFormat(DineroQbFormat), SalesItemLineDetail: { ...(jobs_by_pk.class ? { ClassRef: { value: classes[jobs_by_pk.class] } } : {}), ItemRef: { - value: items[responsibilityCenters.ttl_tax_adjustment.accountitem] + value: items[responsibilityCenters.ttl_tax_adjustment?.accountitem] }, TaxCodeRef: { value: QboTaxId @@ -917,11 +917,11 @@ exports.default = function ({ bodyshop, jobs_by_pk, qbo = false, items, taxCodes } else { InvoiceLineAdd.push({ ItemRef: { - FullName: responsibilityCenters.ttl_tax_adjustment.accountitem + FullName: responsibilityCenters.ttl_tax_adjustment?.accountitem }, Desc: "Tax Adjustment", Quantity: 1, - Amount: Dinero(jobs_by_pk.job_totals.totals.ttl_tax_adjustment).toFormat(DineroQbFormat), + Amount: Dinero(jobs_by_pk.job_totals.totals?.ttl_tax_adjustment).toFormat(DineroQbFormat), SalesTaxCodeRef: InstanceManager({ imex: { FullName: "E" diff --git a/server/job/job-costing.js b/server/job/job-costing.js index 6c107ce8d..4e7af7f86 100644 --- a/server/job/job-costing.js +++ b/server/job/job-costing.js @@ -850,7 +850,7 @@ function GenerateCostingData(job) { }); } //Push adjustments to bottom line. - if (job.job_totals.totals.ttl_adjustment) { + if (job.job_totals?.totals?.ttl_adjustment) { //Add to totals. const Adjustment = Dinero(job.job_totals.totals.ttl_adjustment); //Need to invert, since this is being assigned as a cost. summaryData.totalAdditionalSales = summaryData.totalAdditionalSales.add(Adjustment); From 49044e566998cf28b1b277925e6176a2117e6db6 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Fri, 22 Nov 2024 10:03:41 -0800 Subject: [PATCH 319/478] feature/IO-3000-messaging-sockets-migrations2 - - Missed a check Signed-off-by: Dave Richer --- client/src/pages/manage/manage.page.component.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/pages/manage/manage.page.component.jsx b/client/src/pages/manage/manage.page.component.jsx index c1a8e561c..b39ee69c4 100644 --- a/client/src/pages/manage/manage.page.component.jsx +++ b/client/src/pages/manage/manage.page.component.jsx @@ -647,7 +647,7 @@ export function Manage({ conflict, bodyshop, alerts, setAlerts }) { return ( <> - {true && } + From 91de31135195aad9d0e9b5e3d8d10324aa3ca348 Mon Sep 17 00:00:00 2001 From: Allan Carr Date: Fri, 22 Nov 2024 10:55:19 -0800 Subject: [PATCH 320/478] IO-2921 Chatter Final mods and Cron Trigger Signed-off-by: Allan Carr --- hasura/metadata/cron_triggers.yaml | 9 +++++++++ server/data/chatter.js | 3 ++- server/graphql-client/queries.js | 1 + 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/hasura/metadata/cron_triggers.yaml b/hasura/metadata/cron_triggers.yaml index ff7aef8d1..95157adaa 100644 --- a/hasura/metadata/cron_triggers.yaml +++ b/hasura/metadata/cron_triggers.yaml @@ -6,6 +6,15 @@ headers: - name: x-imex-auth value_from_env: DATAPUMP_AUTH +- name: Chatter Data Pump + webhook: '{{HASURA_API_URL}}/data/chatter' + schedule: 45 5 * * * + include_in_metadata: true + payload: {} + headers: + - name: x-imex-auth + value_from_env: DATAPUMP_AUTH + comment: "" - name: Claimscorp Data Pump webhook: '{{HASURA_API_URL}}/data/cc' schedule: 30 6 * * * diff --git a/server/data/chatter.js b/server/data/chatter.js index 8c3f8e634..993707c41 100644 --- a/server/data/chatter.js +++ b/server/data/chatter.js @@ -109,7 +109,8 @@ async function processBatch(shopsToProcess, start, end, allChatterObjects, allEr lastname: j.ownr_co_nm ? j.ownr_co_nm : j.ownr_ln, transaction_id: j.ro_number, email: j.ownr_ea, - phone_number: j.ownr_ph1 + phone_number: j.ownr_ph1, + transaction_time: (j.actual_delivery && moment(j.actual_delivery).tz(bodyshop.timezone).format("YYYYMMDD-HHmm")) || "" }; }); allChatterObjects.push(...chatterObject); diff --git a/server/graphql-client/queries.js b/server/graphql-client/queries.js index 99e37bebe..66acc6baa 100644 --- a/server/graphql-client/queries.js +++ b/server/graphql-client/queries.js @@ -840,6 +840,7 @@ exports.CHATTER_QUERY = `query CHATTER_EXPORT($start: timestamptz, $bodyshopid: timezone } jobs(where: {_and: [{converted: {_eq: true}}, {actual_delivery: {_gt: $start}}, {actual_delivery: {_lte: $end}}, {shopid: {_eq: $bodyshopid}}, {_or: [{ownr_ph1: {_is_null: false}}, {ownr_ea: {_is_null: false}}]}]}) { + actual_delivery id created_at ro_number From cbc8665636e04243d821b3135fb6e58ef0cb5d63 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Mon, 25 Nov 2024 08:36:33 -0800 Subject: [PATCH 321/478] feature/IO-3000-messaging-sockets-migration2 - Handle some of the PR notes Signed-off-by: Dave Richer --- .../chat-archive-button.component.jsx | 13 +++- .../chat-conversation-list.component.jsx | 2 +- ...chat-conversation-title-tags.component.jsx | 13 +++- .../chat-conversation-title.component.jsx | 24 ++++--- .../chat-conversation.component.jsx | 13 +++- .../chat-conversation.container.jsx | 63 ++++++++++--------- .../chat-label/chat-label.component.jsx | 13 +++- .../chat-tag-ro/chat-tag-ro.container.jsx | 13 +++- 8 files changed, 109 insertions(+), 45 deletions(-) diff --git a/client/src/components/chat-archive-button/chat-archive-button.component.jsx b/client/src/components/chat-archive-button/chat-archive-button.component.jsx index 2b8bcd054..6572cbefc 100644 --- a/client/src/components/chat-archive-button/chat-archive-button.component.jsx +++ b/client/src/components/chat-archive-button/chat-archive-button.component.jsx @@ -4,8 +4,17 @@ import React, { useContext, useState } from "react"; import { useTranslation } from "react-i18next"; import { TOGGLE_CONVERSATION_ARCHIVE } from "../../graphql/conversations.queries"; import SocketContext from "../../contexts/SocketIO/socketContext.jsx"; +import { createStructuredSelector } from "reselect"; +import { selectBodyshop } from "../../redux/user/user.selectors.js"; +import { connect } from "react-redux"; -export default function ChatArchiveButton({ conversation, bodyshop }) { +const mapStateToProps = createStructuredSelector({ + bodyshop: selectBodyshop +}); + +const mapDispatchToProps = () => ({}); + +export function ChatArchiveButton({ conversation, bodyshop }) { const [loading, setLoading] = useState(false); const { t } = useTranslation(); const [updateConversation] = useMutation(TOGGLE_CONVERSATION_ARCHIVE); @@ -36,3 +45,5 @@ export default function ChatArchiveButton({ conversation, bodyshop }) { ); } + +export default connect(mapStateToProps, mapDispatchToProps)(ChatArchiveButton); diff --git a/client/src/components/chat-conversation-list/chat-conversation-list.component.jsx b/client/src/components/chat-conversation-list/chat-conversation-list.component.jsx index a8f95f59d..fe71ee46e 100644 --- a/client/src/components/chat-conversation-list/chat-conversation-list.component.jsx +++ b/client/src/components/chat-conversation-list/chat-conversation-list.component.jsx @@ -64,7 +64,7 @@ function ChatConversationListComponent({ conversationList, selectedConversation, ); }; - // TODO: Can go back into virtuoso for additional fetch + // CAN DO: Can go back into virtuoso for additional fetch // endReached={loadMoreConversations} // Calls loadMoreConversations when scrolled to the bottom return ( diff --git a/client/src/components/chat-conversation-title-tags/chat-conversation-title-tags.component.jsx b/client/src/components/chat-conversation-title-tags/chat-conversation-title-tags.component.jsx index 944ade8b0..821ad1603 100644 --- a/client/src/components/chat-conversation-title-tags/chat-conversation-title-tags.component.jsx +++ b/client/src/components/chat-conversation-title-tags/chat-conversation-title-tags.component.jsx @@ -6,8 +6,17 @@ import { logImEXEvent } from "../../firebase/firebase.utils"; import { REMOVE_CONVERSATION_TAG } from "../../graphql/job-conversations.queries"; import OwnerNameDisplay from "../owner-name-display/owner-name-display.component"; import SocketContext from "../../contexts/SocketIO/socketContext.jsx"; +import { createStructuredSelector } from "reselect"; +import { selectBodyshop } from "../../redux/user/user.selectors.js"; +import { connect } from "react-redux"; -export default function ChatConversationTitleTags({ jobConversations, bodyshop }) { +const mapStateToProps = createStructuredSelector({ + bodyshop: selectBodyshop +}); + +const mapDispatchToProps = () => ({}); + +export function ChatConversationTitleTags({ jobConversations, bodyshop }) { const [removeJobConversation] = useMutation(REMOVE_CONVERSATION_TAG); const { socket } = useContext(SocketContext); @@ -66,3 +75,5 @@ export default function ChatConversationTitleTags({ jobConversations, bodyshop }
); } + +export default connect(mapStateToProps, mapDispatchToProps)(ChatConversationTitleTags); diff --git a/client/src/components/chat-conversation-title/chat-conversation-title.component.jsx b/client/src/components/chat-conversation-title/chat-conversation-title.component.jsx index 7754ea347..7e5b045f5 100644 --- a/client/src/components/chat-conversation-title/chat-conversation-title.component.jsx +++ b/client/src/components/chat-conversation-title/chat-conversation-title.component.jsx @@ -6,19 +6,27 @@ import ChatConversationTitleTags from "../chat-conversation-title-tags/chat-conv import ChatLabelComponent from "../chat-label/chat-label.component"; import ChatPrintButton from "../chat-print-button/chat-print-button.component"; import ChatTagRoContainer from "../chat-tag-ro/chat-tag-ro.container"; +import { createStructuredSelector } from "reselect"; +import { selectBodyshop } from "../../redux/user/user.selectors.js"; +import { connect } from "react-redux"; -export default function ChatConversationTitle({ conversation, bodyshop }) { +const mapStateToProps = createStructuredSelector({ + bodyshop: selectBodyshop +}); + +const mapDispatchToProps = () => ({}); + +export function ChatConversationTitle({ conversation }) { return ( {conversation && conversation.phone_num} - + - - - + + + ); } + +export default connect(mapStateToProps, mapDispatchToProps)(ChatConversationTitle); diff --git a/client/src/components/chat-conversation/chat-conversation.component.jsx b/client/src/components/chat-conversation/chat-conversation.component.jsx index 4188fbabe..3334b5cbd 100644 --- a/client/src/components/chat-conversation/chat-conversation.component.jsx +++ b/client/src/components/chat-conversation/chat-conversation.component.jsx @@ -5,8 +5,17 @@ import ChatMessageListComponent from "../chat-messages-list/chat-message-list.co import ChatSendMessage from "../chat-send-message/chat-send-message.component"; import LoadingSkeleton from "../loading-skeleton/loading-skeleton.component.jsx"; import "./chat-conversation.styles.scss"; +import { createStructuredSelector } from "reselect"; +import { selectBodyshop } from "../../redux/user/user.selectors.js"; +import { connect } from "react-redux"; -export default function ChatConversationComponent({ +const mapStateToProps = createStructuredSelector({ + bodyshop: selectBodyshop +}); + +const mapDispatchToProps = () => ({}); + +export function ChatConversationComponent({ subState, conversation, messages, @@ -31,3 +40,5 @@ export default function ChatConversationComponent({
); } + +export default connect(mapStateToProps, mapDispatchToProps)(ChatConversationComponent); diff --git a/client/src/components/chat-conversation/chat-conversation.container.jsx b/client/src/components/chat-conversation/chat-conversation.container.jsx index 3b7f8385b..e2f7c6ae9 100644 --- a/client/src/components/chat-conversation/chat-conversation.container.jsx +++ b/client/src/components/chat-conversation/chat-conversation.container.jsx @@ -1,6 +1,6 @@ import { useApolloClient, useQuery } from "@apollo/client"; import axios from "axios"; -import React, { useContext, useEffect, useState } from "react"; +import React, { useCallback, useContext, useEffect, useState } from "react"; import { connect } from "react-redux"; import { createStructuredSelector } from "reselect"; import SocketContext from "../../contexts/SocketIO/socketContext"; @@ -14,8 +14,6 @@ const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop }); -export default connect(mapStateToProps, null)(ChatConversationContainer); - export function ChatConversationContainer({ bodyshop, selectedConversation }) { const client = useApolloClient(); const { socket } = useContext(SocketContext); @@ -30,38 +28,40 @@ export function ChatConversationContainer({ bodyshop, selectedConversation }) { fetchPolicy: "network-only" }); - // Utility to update Apollo cache - const updateCacheWithReadMessages = (conversationId, messageIds) => { - if (!conversationId || !messageIds || messageIds.length === 0) return; + const updateCacheWithReadMessages = useCallback( + (conversationId, messageIds) => { + if (!conversationId || !messageIds || messageIds.length === 0) return; - messageIds.forEach((messageId) => { + // Mark individual messages as read + messageIds.forEach((messageId) => { + client.cache.modify({ + id: client.cache.identify({ __typename: "messages", id: messageId }), + fields: { + read() { + return true; // Mark message as read + } + } + }); + }); + + // Update aggregate unread count for the conversation client.cache.modify({ - id: client.cache.identify({ __typename: "messages", id: messageId }), + id: client.cache.identify({ __typename: "conversations", id: conversationId }), fields: { - read() { - return true; // Mark message as read + messages_aggregate(existingAggregate) { + return { + ...existingAggregate, + aggregate: { + ...existingAggregate.aggregate, + count: 0 // No unread messages remaining + } + }; } } }); - }); - - // Optionally update aggregate unread count - client.cache.modify({ - id: client.cache.identify({ __typename: "conversations", id: conversationId }), - fields: { - messages_aggregate(existingAggregate) { - const updatedAggregate = { - ...existingAggregate, - aggregate: { - ...existingAggregate.aggregate, - count: 0 // No unread messages remaining - } - }; - return updatedAggregate; - } - } - }); - }; + }, + [client.cache] + ); // Handle WebSocket events useEffect(() => { @@ -80,7 +80,7 @@ export function ChatConversationContainer({ bodyshop, selectedConversation }) { return () => { socket.off("conversation-changed", handleConversationChange); }; - }, [socket, client]); + }, [socket, client, updateCacheWithReadMessages]); // Handle joining/leaving conversation useEffect(() => { @@ -143,7 +143,8 @@ export function ChatConversationContainer({ bodyshop, selectedConversation }) { conversation={convoData ? convoData.conversations_by_pk : {}} messages={convoData ? convoData.conversations_by_pk.messages : []} handleMarkConversationAsRead={handleMarkConversationAsRead} - bodyshop={bodyshop} /> ); } + +export default connect(mapStateToProps, null)(ChatConversationContainer); diff --git a/client/src/components/chat-label/chat-label.component.jsx b/client/src/components/chat-label/chat-label.component.jsx index e577bbf23..0764869ee 100644 --- a/client/src/components/chat-label/chat-label.component.jsx +++ b/client/src/components/chat-label/chat-label.component.jsx @@ -5,8 +5,17 @@ import React, { useContext, useState } from "react"; import { useTranslation } from "react-i18next"; import { UPDATE_CONVERSATION_LABEL } from "../../graphql/conversations.queries"; import SocketContext from "../../contexts/SocketIO/socketContext.jsx"; +import { createStructuredSelector } from "reselect"; +import { selectBodyshop } from "../../redux/user/user.selectors.js"; +import { connect } from "react-redux"; -export default function ChatLabel({ conversation, bodyshop }) { +const mapStateToProps = createStructuredSelector({ + bodyshop: selectBodyshop +}); + +const mapDispatchToProps = (dispatch) => ({}); + +export function ChatLabel({ conversation, bodyshop }) { const [loading, setLoading] = useState(false); const [editing, setEditing] = useState(false); const [value, setValue] = useState(conversation.label); @@ -67,3 +76,5 @@ export default function ChatLabel({ conversation, bodyshop }) { ); } } + +export default connect(mapStateToProps, mapDispatchToProps)(ChatLabel); diff --git a/client/src/components/chat-tag-ro/chat-tag-ro.container.jsx b/client/src/components/chat-tag-ro/chat-tag-ro.container.jsx index 6e01ea5ed..8d3476c7d 100644 --- a/client/src/components/chat-tag-ro/chat-tag-ro.container.jsx +++ b/client/src/components/chat-tag-ro/chat-tag-ro.container.jsx @@ -9,8 +9,17 @@ import { INSERT_CONVERSATION_TAG } from "../../graphql/job-conversations.queries import { SEARCH_FOR_JOBS } from "../../graphql/jobs.queries"; import ChatTagRo from "./chat-tag-ro.component"; import SocketContext from "../../contexts/SocketIO/socketContext.jsx"; +import { createStructuredSelector } from "reselect"; +import { selectBodyshop } from "../../redux/user/user.selectors.js"; +import { connect } from "react-redux"; -export default function ChatTagRoContainer({ conversation, bodyshop }) { +const mapStateToProps = createStructuredSelector({ + bodyshop: selectBodyshop +}); + +const mapDispatchToProps = () => ({}); + +export function ChatTagRoContainer({ conversation, bodyshop }) { const { t } = useTranslation(); const [open, setOpen] = useState(false); const { socket } = useContext(SocketContext); @@ -86,3 +95,5 @@ export default function ChatTagRoContainer({ conversation, bodyshop }) { ); } + +export default connect(mapStateToProps, mapDispatchToProps)(ChatTagRoContainer); From 5e2c0f9c4a00639566f99b4299932d2f67d058bf Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Mon, 25 Nov 2024 08:38:07 -0800 Subject: [PATCH 322/478] feature/IO-3000-messaging-sockets-migration2 - Handle some of the PR notes Signed-off-by: Dave Richer --- client/src/components/chat-popup/chat-popup.component.jsx | 2 +- client/src/redux/messaging/messaging.sagas.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/components/chat-popup/chat-popup.component.jsx b/client/src/components/chat-popup/chat-popup.component.jsx index f99738cb1..7c0711fbc 100644 --- a/client/src/components/chat-popup/chat-popup.component.jsx +++ b/client/src/components/chat-popup/chat-popup.component.jsx @@ -31,7 +31,7 @@ export function ChatPopupComponent({ chatVisible, selectedConversation, toggleCh const client = useApolloClient(); // Apollo Client instance for cache operations // Lazy query for conversations - const [getConversations, { loading, data, refetch, fetchMore }] = useLazyQuery(CONVERSATION_LIST_QUERY, { + const [getConversations, { loading, data, refetch }] = useLazyQuery(CONVERSATION_LIST_QUERY, { fetchPolicy: "network-only", nextFetchPolicy: "network-only", skip: !chatVisible, diff --git a/client/src/redux/messaging/messaging.sagas.js b/client/src/redux/messaging/messaging.sagas.js index 012c05618..7194ea4dc 100644 --- a/client/src/redux/messaging/messaging.sagas.js +++ b/client/src/redux/messaging/messaging.sagas.js @@ -42,7 +42,7 @@ export function* openChatByPhone({ payload }) { } = yield client.query({ query: CONVERSATION_ID_BY_PHONE, variables: { phone: p.number }, - fetchPolicy: "no-cache" + fetchPolicy: "network-only" }); if (conversations.length === 0) { From 457a3b2d7adec8a00a3a95ae491913bd71c52314 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Mon, 25 Nov 2024 08:42:02 -0800 Subject: [PATCH 323/478] feature/IO-3000-messaging-sockets-migration2 - Handle some of the PR notes Signed-off-by: Dave Richer --- .../chat-conversation-title.component.jsx | 5 +---- .../chat-conversation/chat-conversation.container.jsx | 3 ++- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/client/src/components/chat-conversation-title/chat-conversation-title.component.jsx b/client/src/components/chat-conversation-title/chat-conversation-title.component.jsx index 7e5b045f5..07b48716f 100644 --- a/client/src/components/chat-conversation-title/chat-conversation-title.component.jsx +++ b/client/src/components/chat-conversation-title/chat-conversation-title.component.jsx @@ -7,12 +7,9 @@ import ChatLabelComponent from "../chat-label/chat-label.component"; import ChatPrintButton from "../chat-print-button/chat-print-button.component"; import ChatTagRoContainer from "../chat-tag-ro/chat-tag-ro.container"; import { createStructuredSelector } from "reselect"; -import { selectBodyshop } from "../../redux/user/user.selectors.js"; import { connect } from "react-redux"; -const mapStateToProps = createStructuredSelector({ - bodyshop: selectBodyshop -}); +const mapStateToProps = createStructuredSelector({}); const mapDispatchToProps = () => ({}); diff --git a/client/src/components/chat-conversation/chat-conversation.container.jsx b/client/src/components/chat-conversation/chat-conversation.container.jsx index e2f7c6ae9..b477b436e 100644 --- a/client/src/components/chat-conversation/chat-conversation.container.jsx +++ b/client/src/components/chat-conversation/chat-conversation.container.jsx @@ -25,7 +25,8 @@ export function ChatConversationContainer({ bodyshop, selectedConversation }) { data: convoData } = useQuery(GET_CONVERSATION_DETAILS, { variables: { conversationId: selectedConversation }, - fetchPolicy: "network-only" + fetchPolicy: "network-only", + nextFetchPolicy: "network-only" }); const updateCacheWithReadMessages = useCallback( From 239c1502f90a5d077e736df348f0078dbb983931 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Mon, 25 Nov 2024 09:57:18 -0800 Subject: [PATCH 324/478] feature/IO-3000-messaging-sockets-migration2 - Fix console warn in archive/unarchive if one query is not existent Signed-off-by: Dave Richer --- .../chat-affix/registerMessagingSocketHandlers.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/client/src/components/chat-affix/registerMessagingSocketHandlers.js b/client/src/components/chat-affix/registerMessagingSocketHandlers.js index 5b4f34ea1..d0ab4baa5 100644 --- a/client/src/components/chat-affix/registerMessagingSocketHandlers.js +++ b/client/src/components/chat-affix/registerMessagingSocketHandlers.js @@ -337,12 +337,18 @@ export const registerMessagingHandlers = ({ socket, client }) => { const listQueryVariables = { offset: 0 }; const detailsQueryVariables = { conversationId }; - // Refetch conversation list and details + // Check if conversation details exist in the cache + const detailsExist = !!client.cache.readQuery({ + query: GET_CONVERSATION_DETAILS, + variables: detailsQueryVariables + }); + + // Refetch conversation list await client.refetchQueries({ - include: [CONVERSATION_LIST_QUERY, GET_CONVERSATION_DETAILS], + include: [CONVERSATION_LIST_QUERY, ...(detailsExist ? [GET_CONVERSATION_DETAILS] : [])], variables: [ { query: CONVERSATION_LIST_QUERY, variables: listQueryVariables }, - { query: GET_CONVERSATION_DETAILS, variables: detailsQueryVariables } + ...(detailsExist ? [{ query: GET_CONVERSATION_DETAILS, variables: detailsQueryVariables }] : []) ] }); From 268b1ba9c186485fc4bb92b6e1ee2a169721cabc Mon Sep 17 00:00:00 2001 From: Patrick Fic Date: Mon, 25 Nov 2024 10:51:48 -0800 Subject: [PATCH 325/478] IO-2920 Refactor fee discounting to use API to check. --- .../job-totals.table.totals.component.jsx | 11 +--- ...totals.cash-discount-display.component.jsx | 57 +++++++++++++++++++ server/intellipay/intellipay.js | 46 +++++++++++++++ server/routes/intellipayRoutes.js | 3 +- 4 files changed, 108 insertions(+), 9 deletions(-) create mode 100644 client/src/components/job-totals-table/jobs-totals.cash-discount-display.component.jsx diff --git a/client/src/components/job-totals-table/job-totals.table.totals.component.jsx b/client/src/components/job-totals-table/job-totals.table.totals.component.jsx index 301fec91f..eef6dfaf5 100644 --- a/client/src/components/job-totals-table/job-totals.table.totals.component.jsx +++ b/client/src/components/job-totals-table/job-totals.table.totals.component.jsx @@ -7,6 +7,7 @@ import { connect } from "react-redux"; import { createStructuredSelector } from "reselect"; import { selectBodyshop } from "../../redux/user/user.selectors"; import InstanceRenderManager from "../../utils/instanceRenderMgr"; +import JobTotalsCashDiscount from "./jobs-totals.cash-discount-display.component"; const mapStateToProps = createStructuredSelector({ //currentUser: selectCurrentUser @@ -169,13 +170,7 @@ export function JobTotalsTableTotals({ bodyshop, job }) { }, { key: t("jobs.labels.total_cust_payable"), - total: Dinero(job.job_totals.totals.custPayable.total) - .add( - Dinero(job.job_totals.totals.custPayable.total).percentage( - bodyshop.intellipay_config?.cash_discount_percentage || 0 - ) - ) - .toJSON(), + render: , bold: true } ] @@ -211,7 +206,7 @@ export function JobTotalsTableTotals({ bodyshop, job }) { dataIndex: "total", key: "total", align: "right", - render: (text, record) => Dinero(record.total).toFormat(), + render: (text, record) => (record.render ? record.render : Dinero(record.total).toFormat()), width: "20%", onCell: (record, rowIndex) => { return { style: { fontWeight: record.bold && "bold" } }; diff --git a/client/src/components/job-totals-table/jobs-totals.cash-discount-display.component.jsx b/client/src/components/job-totals-table/jobs-totals.cash-discount-display.component.jsx new file mode 100644 index 000000000..9a529866f --- /dev/null +++ b/client/src/components/job-totals-table/jobs-totals.cash-discount-display.component.jsx @@ -0,0 +1,57 @@ +import { notification, Spin } from "antd"; +import axios from "axios"; +import Dinero from "dinero.js"; +import React, { useCallback, useEffect, useState } from "react"; + +import { connect } from "react-redux"; +import { createStructuredSelector } from "reselect"; +import { selectBodyshop } from "../../redux/user/user.selectors"; +const mapStateToProps = createStructuredSelector({ + bodyshop: selectBodyshop +}); +const mapDispatchToProps = (dispatch) => ({ +}); +export default connect(mapStateToProps, mapDispatchToProps)(JobTotalsCashDiscount); + +export function JobTotalsCashDiscount({ bodyshop, amountDinero }) { + const [loading, setLoading] = useState(true); + const [fee, setFee] = useState(0); + + const fetchData = useCallback(async () => { + if (amountDinero && bodyshop) { + setLoading(true); + let response; + try { + response = await axios.post("/intellipay/checkfee", { + bodyshop: { id: bodyshop.id, imexshopid: bodyshop.imexshopid }, + amount: Dinero(amountDinero).toFormat("0.00") + }); + + if (response?.data?.error) { + notification.open({ + type: "error", + message: response.data?.error || "Error encountered contacting IntelliPay service." + }); + } else { + setFee(response.data?.fee || 0); + } + } catch (error) { + notification.open({ + type: "error", + message: error.response?.data?.error || "Error encountered contacting IntelliPay service." + }); + } finally { + setLoading(false); + } + } + }, [amountDinero, bodyshop]); + + useEffect(() => { + fetchData(); + }, [fetchData, bodyshop, amountDinero]); + + if (loading) return ; + return Dinero(amountDinero) + .add(Dinero({ amount: Math.round(fee * 100) })) + .toFormat(); +} diff --git a/server/intellipay/intellipay.js b/server/intellipay/intellipay.js index 080deec90..43758f97e 100644 --- a/server/intellipay/intellipay.js +++ b/server/intellipay/intellipay.js @@ -149,6 +149,52 @@ exports.generate_payment_url = async (req, res) => { } }; +//Reference: https://intellipay.com/dist/webapi26.html#operation/fee +exports.checkfee = async (req, res) => { + logger.log("intellipay-fee-check", "DEBUG", req.user?.email, null, null); + + //If there's no amount, there can't be a fee. Skip the call. + if (!req.body.amount || req.body.amount <= 0) { + res.json({ fee: 0 }); + return; + } + + const shopCredentials = await getShopCredentials(req.body.bodyshop); + + try { + const options = { + method: "POST", + headers: { "content-type": "application/x-www-form-urlencoded" }, + //TODO: Move these to environment variables/database. + data: qs.stringify( + { + method: "fee", + ...shopCredentials, + amount: req.body.amount, + paymenttype: `"CC"` + }, + { sort: false } //ColdFusion Query Strings depend on order. This preserves it. + ), + url: `https://${domain}.cpteller.com/api/26/webapi.cfc` + }; + + const response = await axios(options); + if (response.data?.error) { + res.status(400).json({ error: response.data.error }); + } else if (response.data < 0) { + res.json({ error: "Fee amount negative. Check API credentials & account configuration." }); + } else { + res.json({ fee: response.data }); + } + } catch (error) { + //console.log(error); + logger.log("intellipay-fee-check-error", "ERROR", req.user?.email, null, { + error: error.message + }); + res.status(400).json({ error }); + } +}; + exports.postback = async (req, res) => { try { logger.log("intellipay-postback", "DEBUG", req.user?.email, null, req.body); diff --git a/server/routes/intellipayRoutes.js b/server/routes/intellipayRoutes.js index 47f09ffb0..ad0b87323 100644 --- a/server/routes/intellipayRoutes.js +++ b/server/routes/intellipayRoutes.js @@ -1,11 +1,12 @@ const express = require("express"); const router = express.Router(); const validateFirebaseIdTokenMiddleware = require("../middleware/validateFirebaseIdTokenMiddleware"); -const { lightbox_credentials, payment_refund, generate_payment_url, postback } = require("../intellipay/intellipay"); +const { lightbox_credentials, payment_refund, generate_payment_url, postback, checkfee } = require("../intellipay/intellipay"); router.post("/lightbox_credentials", validateFirebaseIdTokenMiddleware, lightbox_credentials); router.post("/payment_refund", validateFirebaseIdTokenMiddleware, payment_refund); router.post("/generate_payment_url", validateFirebaseIdTokenMiddleware, generate_payment_url); +router.post("/checkfee", validateFirebaseIdTokenMiddleware, checkfee); router.post("/postback", postback); module.exports = router; From 62dd3d7e8ec823f5285d7bd1fff329784cf70005 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Mon, 25 Nov 2024 11:38:59 -0800 Subject: [PATCH 326/478] feature/IO-3000-messaging-sockets-migration2 - Final fixes around sync / archive / receive Signed-off-by: Dave Richer --- client/src/redux/messaging/messaging.sagas.js | 20 +++-- server/graphql-client/queries.js | 31 ++++++++ server/sms/receive.js | 73 ++++++++++--------- 3 files changed, 77 insertions(+), 47 deletions(-) diff --git a/client/src/redux/messaging/messaging.sagas.js b/client/src/redux/messaging/messaging.sagas.js index 7194ea4dc..fb519bcca 100644 --- a/client/src/redux/messaging/messaging.sagas.js +++ b/client/src/redux/messaging/messaging.sagas.js @@ -42,10 +42,13 @@ export function* openChatByPhone({ payload }) { } = yield client.query({ query: CONVERSATION_ID_BY_PHONE, variables: { phone: p.number }, - fetchPolicy: "network-only" + // THIS NEEDS TO REMAIN NO CACHE, IT CHECKS FOR NEW MESSAGES FOR SYNC + fetchPolicy: "no-cache" }); - if (conversations.length === 0) { + const existingConversation = conversations?.find((c) => c.phone_num === phone_num); + + if (!existingConversation) { // No conversation exists, create a new one const { data: { @@ -75,18 +78,17 @@ export function* openChatByPhone({ payload }) { // Set the newly created conversation as selected yield put(setSelectedConversation(createdConversation.id)); - } else if (conversations.length === 1) { - const conversation = conversations[0]; - let updatedConversation = conversation; + } else { + let updatedConversation = existingConversation; - if (conversation.archived) { + if (existingConversation.archived) { // Conversation is archived, unarchive it in the DB const { data: { update_conversations_by_pk: unarchivedConversation } } = yield client.mutate({ mutation: TOGGLE_CONVERSATION_ARCHIVE, variables: { - id: conversation.id, + id: existingConversation.id, archived: false } }); @@ -115,10 +117,6 @@ export function* openChatByPhone({ payload }) { } }); } - } else { - // Multiple conversations found - console.error("ERROR: Multiple conversations found."); - yield put(setSelectedConversation(null)); } } catch (error) { console.error("Error in openChatByPhone saga.", error); diff --git a/server/graphql-client/queries.js b/server/graphql-client/queries.js index 4d82f0025..cf5e2b016 100644 --- a/server/graphql-client/queries.js +++ b/server/graphql-client/queries.js @@ -2577,3 +2577,34 @@ exports.MARK_MESSAGES_AS_READ = `mutation MARK_MESSAGES_AS_READ($conversationId: } } `; + +exports.CREATE_CONVERSATION = `mutation CREATE_CONVERSATION($conversation: [conversations_insert_input!]!) { + insert_conversations(objects: $conversation) { + returning { + id + phone_num + archived + label + unreadcnt + job_conversations { + jobid + conversationid + job { + id + ro_number + ownr_fn + ownr_ln + ownr_co_nm + } + } + messages_aggregate(where: { read: { _eq: false }, isoutbound: { _eq: false } }) { + aggregate { + count + } + } + created_at + updated_at + } + } +} +`; diff --git a/server/sms/receive.js b/server/sms/receive.js index 63c11a260..fef921912 100644 --- a/server/sms/receive.js +++ b/server/sms/receive.js @@ -34,6 +34,7 @@ exports.receive = async (req, res) => { } try { + // Step 1: Find the bodyshop and existing conversation const response = await client.request(queries.FIND_BODYSHOP_BY_MESSAGING_SERVICE_SID, { mssid: req.body.MessagingServiceSid, phone: phone(req.body.From).phoneNumber @@ -44,53 +45,51 @@ exports.receive = async (req, res) => { } const bodyshop = response.bodyshops[0]; - const isNewConversation = bodyshop.conversations.length === 0; - const isDuplicate = bodyshop.conversations.length > 1; + const existingConversation = bodyshop.conversations[0]; // Expect only one conversation per phone number per bodyshop + let conversationid; let newMessage = { msid: req.body.SmsMessageSid, text: req.body.Body, image: !!req.body.MediaUrl0, - image_path: generateMediaArray(req.body) + image_path: generateMediaArray(req.body), + isoutbound: false, + userid: null // Add additional fields as necessary }; - if (isDuplicate) { - logger.log("sms-inbound-error", "ERROR", "api", null, { - ...loggerData, - messagingServiceSid: req.body.MessagingServiceSid, - type: "duplicate-phone" - }); - return res.status(400).json({ success: false, error: "Duplicate phone number" }); - } + if (existingConversation) { + // Use the existing conversation + conversationid = existingConversation.id; - if (isNewConversation) { - newMessage.conversation = { - data: { + // Unarchive the conversation if necessary + if (existingConversation.archived) { + await client.request(queries.UNARCHIVE_CONVERSATION, { + id: conversationid, + archived: false + }); + } + } else { + // Create a new conversation + const newConversationResponse = await client.request(queries.CREATE_CONVERSATION, { + conversation: { bodyshopid: bodyshop.id, phone_num: phone(req.body.From).phoneNumber, archived: false } - }; - } else { - const existingConversation = bodyshop.conversations[0]; - - // Update the conversation to unarchive it - if (existingConversation.archived) { - await client.request(queries.UNARCHIVE_CONVERSATION, { - id: existingConversation.id, - archived: false - }); - } - - newMessage.conversationid = existingConversation.id; + }); + const createdConversation = newConversationResponse.insert_conversations.returning[0]; + conversationid = createdConversation.id; } - const query = isNewConversation ? queries.RECEIVE_MESSAGE : queries.INSERT_MESSAGE; - const variables = isNewConversation - ? { msg: newMessage } - : { msg: newMessage, conversationid: newMessage.conversationid }; + // Ensure `conversationid` is added to the message + newMessage.conversationid = conversationid; + + // Step 3: Insert the message into the conversation + const insertresp = await client.request(queries.INSERT_MESSAGE, { + msg: newMessage, + conversationid: conversationid + }); - const insertresp = await client.request(query, variables); const message = insertresp?.insert_messages?.returning?.[0]; const conversation = message?.conversation || null; @@ -98,6 +97,7 @@ exports.receive = async (req, res) => { throw new Error("Conversation data is missing from the response."); } + // Step 4: Notify clients through Redis const broadcastRoom = getBodyshopRoom(conversation.bodyshop.id); const conversationRoom = getBodyshopConversationRoom({ bodyshopId: conversation.bodyshop.id, @@ -113,19 +113,20 @@ exports.receive = async (req, res) => { ioRedis.to(broadcastRoom).emit("new-message-summary", { ...commonPayload, - existingConversation: !isNewConversation, - newConversation: isNewConversation ? conversation : null, + existingConversation: !!existingConversation, + newConversation: !existingConversation ? conversation : null, summary: true }); ioRedis.to(conversationRoom).emit("new-message-detailed", { newMessage: message, ...commonPayload, - newConversation: isNewConversation ? conversation : null, - existingConversation: !isNewConversation, + newConversation: !existingConversation ? conversation : null, + existingConversation: !!existingConversation, summary: false }); + // Step 5: Send FCM notification const fcmresp = await admin.messaging().send({ topic: `${message.conversation.bodyshop.imexshopid}-messaging`, notification: { From 4433f0f57f9699c8c7c5acc3a8376069fe9fb17d Mon Sep 17 00:00:00 2001 From: Patrick Fic Date: Mon, 25 Nov 2024 12:29:09 -0800 Subject: [PATCH 327/478] IO-3020 IO-3036 Remove additional TODOs. --- client/index.html | 1 - .../jobs-available-table.container.jsx | 59 +++++++++---------- .../loading-spinner.component.jsx | 1 - .../shop-info/shop-info.rbac.component.jsx | 1 - client/src/index.jsx | 2 +- .../jobs-detail.page.component.jsx | 2 +- client/src/redux/store.js | 1 - server/job/job-totals-USA.js | 5 +- server/job/job.js | 6 +- server/routes/adminRoutes.js | 3 +- server/sms/receive.js | 3 +- server/utils/instanceMgr.js | 8 ++- 12 files changed, 43 insertions(+), 49 deletions(-) diff --git a/client/index.html b/client/index.html index d5010d03c..902f09472 100644 --- a/client/index.html +++ b/client/index.html @@ -14,7 +14,6 @@ -