Compare commits
57 Commits
feature/IO
...
feature/IO
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b0dcd3618e | ||
|
|
e015d3574a | ||
|
|
60140902d4 | ||
|
|
84f41b2c11 | ||
|
|
282fa787a9 | ||
|
|
037efff81c | ||
|
|
e26eb17d09 | ||
|
|
fbea9fde27 | ||
|
|
ce7cf6bdbe | ||
|
|
2c47e5d852 | ||
|
|
a6f809b20a | ||
|
|
2bcad68351 | ||
|
|
6b1b393804 | ||
|
|
c5181d1c5d | ||
|
|
e33ff2a45d | ||
|
|
9eb77964db | ||
|
|
0a68d2791d | ||
|
|
11928d9a7e | ||
|
|
c169bb5d5d | ||
|
|
3cc4f1c63e | ||
|
|
5237b1d535 | ||
|
|
cd56c50cf9 | ||
|
|
a18ce18d72 | ||
|
|
3691d32aaa | ||
|
|
5f66488410 | ||
|
|
d1be7f6e09 | ||
|
|
44f02f28a6 | ||
|
|
6d33622b4e | ||
|
|
f8b8e23ef4 | ||
|
|
db09d09428 | ||
|
|
451820a67c | ||
|
|
ba0ce5027e | ||
|
|
f777d26cc1 | ||
|
|
1463037878 | ||
|
|
7ddec0bb0f | ||
|
|
51c2d3351a | ||
|
|
8323fa6696 | ||
|
|
27a3932c08 | ||
|
|
add88659a4 | ||
|
|
320ad065d0 | ||
|
|
a9bc51949a | ||
|
|
39d1397221 | ||
|
|
b44b71072f | ||
|
|
f3e2a83bab | ||
|
|
0ef030bb89 | ||
|
|
3e9e6baf32 | ||
|
|
c03d45b3fc | ||
|
|
0a9b583c4b | ||
|
|
7e741e4af9 | ||
|
|
24d47ae1c5 | ||
|
|
1b8be56c15 | ||
|
|
2b26db78eb | ||
|
|
c2d96922c8 | ||
|
|
70b4ec7948 | ||
|
|
a3ec364034 | ||
|
|
e1728b275b | ||
|
|
10d55df461 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -127,4 +127,6 @@ vitest-report*/
|
||||
vitest-coverage/
|
||||
*.vitest.log
|
||||
test-output.txt
|
||||
server/job/test/fixtures
|
||||
|
||||
.github
|
||||
|
||||
@@ -56,4 +56,5 @@ COPY . .
|
||||
EXPOSE 4000 9229
|
||||
|
||||
# Start the application
|
||||
CMD ["nodemon", "--legacy-watch", "--inspect=0.0.0.0:9229", "server.js"]
|
||||
RUN echo "Starting the application..."
|
||||
CMD ["nodemon", "--ignore", "./server/job/test/fixtures", "--legacy-watch", "--inspect=0.0.0.0:9229", "server.js"]
|
||||
|
||||
235
client/package-lock.json
generated
235
client/package-lock.json
generated
@@ -10,7 +10,7 @@
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"@ant-design/pro-layout": "^7.22.4",
|
||||
"@apollo/client": "^3.13.5",
|
||||
"@apollo/client": "^3.13.6",
|
||||
"@emotion/is-prop-valid": "^1.3.1",
|
||||
"@fingerprintjs/fingerprintjs": "^4.6.1",
|
||||
"@firebase/analytics": "^0.10.12",
|
||||
@@ -21,9 +21,9 @@
|
||||
"@jsreport/browser-client": "^3.1.0",
|
||||
"@reduxjs/toolkit": "^2.6.1",
|
||||
"@sentry/cli": "^2.43.0",
|
||||
"@sentry/react": "^9.10.1",
|
||||
"@sentry/vite-plugin": "^3.2.4",
|
||||
"@splitsoftware/splitio-react": "^2.1.0",
|
||||
"@sentry/react": "^9.11.0",
|
||||
"@sentry/vite-plugin": "^3.3.1",
|
||||
"@splitsoftware/splitio-react": "^2.1.1",
|
||||
"@tanem/react-nprogress": "^5.0.53",
|
||||
"antd": "^5.24.6",
|
||||
"apollo-link-logger": "^2.0.1",
|
||||
@@ -58,7 +58,7 @@
|
||||
"react-dom": "^18.3.1",
|
||||
"react-drag-listview": "^2.0.0",
|
||||
"react-grid-gallery": "^1.0.1",
|
||||
"react-grid-layout": "1.3.4",
|
||||
"react-grid-layout": "^1.3.4",
|
||||
"react-i18next": "^15.4.1",
|
||||
"react-icons": "^5.5.0",
|
||||
"react-image-lightbox": "^5.1.4",
|
||||
@@ -70,17 +70,17 @@
|
||||
"react-resizable": "^3.0.5",
|
||||
"react-router-dom": "^6.30.0",
|
||||
"react-sticky": "^6.0.3",
|
||||
"react-virtuoso": "^4.12.6",
|
||||
"recharts": "^2.15.0",
|
||||
"react-virtuoso": "^4.12.5",
|
||||
"recharts": "^2.15.2",
|
||||
"redux": "^5.0.1",
|
||||
"redux-actions": "^3.0.3",
|
||||
"redux-persist": "^6.0.0",
|
||||
"redux-saga": "^1.3.0",
|
||||
"redux-state-sync": "^3.1.4",
|
||||
"reselect": "^5.1.1",
|
||||
"sass": "^1.86.1",
|
||||
"sass": "^1.86.3",
|
||||
"socket.io-client": "^4.8.1",
|
||||
"styled-components": "^6.1.16",
|
||||
"styled-components": "^6.1.17",
|
||||
"subscriptions-transport-ws": "^0.11.0",
|
||||
"use-memo-one": "^1.1.3",
|
||||
"vite-plugin-ejs": "^1.7.0",
|
||||
@@ -90,22 +90,22 @@
|
||||
"@ant-design/icons": "^6.0.0",
|
||||
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
|
||||
"@babel/preset-react": "^7.26.3",
|
||||
"@dotenvx/dotenvx": "^1.39.0",
|
||||
"@dotenvx/dotenvx": "^1.39.1",
|
||||
"@emotion/babel-plugin": "^11.13.5",
|
||||
"@emotion/react": "^11.14.0",
|
||||
"@eslint/js": "^9.23.0",
|
||||
"@eslint/js": "^9.24.0",
|
||||
"@playwright/test": "^1.51.1",
|
||||
"@sentry/webpack-plugin": "^3.2.4",
|
||||
"@sentry/webpack-plugin": "^3.3.1",
|
||||
"@testing-library/dom": "^10.4.0",
|
||||
"@testing-library/jest-dom": "^6.6.3",
|
||||
"@testing-library/react": "^16.2.0",
|
||||
"@testing-library/react": "^16.3.0",
|
||||
"@vitejs/plugin-react": "^4.3.4",
|
||||
"browserslist": "^4.24.4",
|
||||
"browserslist-to-esbuild": "^2.1.1",
|
||||
"chalk": "^5.4.1",
|
||||
"eslint": "^8.57.1",
|
||||
"eslint-config-react-app": "^7.0.1",
|
||||
"eslint-plugin-react": "^7.37.4",
|
||||
"eslint-plugin-react": "^7.37.5",
|
||||
"globals": "^15.15.0",
|
||||
"jsdom": "^26.0.0",
|
||||
"memfs": "^4.17.0",
|
||||
@@ -114,7 +114,7 @@
|
||||
"react-error-overlay": "^6.1.0",
|
||||
"redux-logger": "^3.0.6",
|
||||
"source-map-explorer": "^2.5.3",
|
||||
"vite": "^6.2.4",
|
||||
"vite": "^6.2.5",
|
||||
"vite-plugin-babel": "^1.3.0",
|
||||
"vite-plugin-eslint": "^1.8.1",
|
||||
"vite-plugin-node-polyfills": "^0.23.0",
|
||||
@@ -396,9 +396,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@apollo/client": {
|
||||
"version": "3.13.5",
|
||||
"resolved": "https://registry.npmjs.org/@apollo/client/-/client-3.13.5.tgz",
|
||||
"integrity": "sha512-ceHa1lApLAiGmUur4V+G/CrjwVwHYujfB7U5HM++poCgHpfGn6eet8YGM93fgeWjYX85SaqwdZbQk18IVwhRHg==",
|
||||
"version": "3.13.6",
|
||||
"resolved": "https://registry.npmjs.org/@apollo/client/-/client-3.13.6.tgz",
|
||||
"integrity": "sha512-G6A8uNb13V/Tv4TJQOs5PnxuE5Rf5D2dMnBQcg9mng1Eo4YBecwFEJ0L022mraq/dLB0jD5tiAESOD2bTyJ6gg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@graphql-typed-document-node/core": "^3.1.1",
|
||||
@@ -2566,9 +2566,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@dotenvx/dotenvx": {
|
||||
"version": "1.39.0",
|
||||
"resolved": "https://registry.npmjs.org/@dotenvx/dotenvx/-/dotenvx-1.39.0.tgz",
|
||||
"integrity": "sha512-qGfDpL/3S17MQYXpR3HkBS5xNQ7wiFlqLdpr+iIQzv17aMRcSlgL4EjMIsYFZ540Dq17J+y5FVElA1AkVoXiUA==",
|
||||
"version": "1.39.1",
|
||||
"resolved": "https://registry.npmjs.org/@dotenvx/dotenvx/-/dotenvx-1.39.1.tgz",
|
||||
"integrity": "sha512-FIjEB/s3TSQBYnYA64GPkXJrOR6w5J52SSnl6gSoq1tp+4r9zLjaAsf65AgDv5emA4ypm90gVWv1XX0/bfHA/A==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
@@ -2891,9 +2891,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@eslint/js": {
|
||||
"version": "9.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.23.0.tgz",
|
||||
"integrity": "sha512-35MJ8vCPU0ZMxo7zfev2pypqTwWTofFZO6m4KAtdoFhRpLJUpHTZZ+KB3C7Hb1d7bULYwO4lJXGCi5Se+8OMbw==",
|
||||
"version": "9.24.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.24.0.tgz",
|
||||
"integrity": "sha512-uIY/y3z0uvOGX8cp1C2fiC4+ZmBhp6yZWkojtHL1YEMnRt1Y63HB9TM17proGEmeG7HeUY+UP36F0aknKYTpYA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
@@ -4178,88 +4178,88 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@sentry-internal/browser-utils": {
|
||||
"version": "9.10.1",
|
||||
"resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-9.10.1.tgz",
|
||||
"integrity": "sha512-O/ibpHbKfpG+xtZuEzbLNtLcbanRcDYGxT+QbslVItmcS9GjMSwvMpp1jnD9Y7/LIFtv7O1gJZ9Hrz///lLprw==",
|
||||
"version": "9.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-9.11.0.tgz",
|
||||
"integrity": "sha512-XS71kRf7lw5St/Jc9G2Viy1cKgqGoPHqUAykXEtFt38JVXdf1TY/dSbKv/PAgNqMvC1xvdTsN0HF/81o7DNUEA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@sentry/core": "9.10.1"
|
||||
"@sentry/core": "9.11.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry-internal/feedback": {
|
||||
"version": "9.10.1",
|
||||
"resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-9.10.1.tgz",
|
||||
"integrity": "sha512-DM32eAzRvXk36iGBWtlLZA88QzOFBODd+kbz55X4Py+1bDNdRc3Vl6214uuAr7iweHcOQy1rIvmAeO8Xusp7tQ==",
|
||||
"version": "9.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-9.11.0.tgz",
|
||||
"integrity": "sha512-50KiRmrF1Ldr+KoRawqcCYVk7TAVP8K/I81Jk9YWwlp1+Pu1ArpYDmTNCLXTgoyiyO38aHefKGZJX6AKFuSsUQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@sentry/core": "9.10.1"
|
||||
"@sentry/core": "9.11.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry-internal/replay": {
|
||||
"version": "9.10.1",
|
||||
"resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-9.10.1.tgz",
|
||||
"integrity": "sha512-nqG33NwojtteL8e3Qg/SOu0BsTJ9R7AjpmQIlOpFGL007nzKgcJHOngewd7FEHyB+F3iOI0MoI9iEWhRFEGRLw==",
|
||||
"version": "9.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-9.11.0.tgz",
|
||||
"integrity": "sha512-0k24h58O/2VQw1dwT/zQiWvUzLNQxpxbrVN/MYPT7czSEhI+1bX8fxMHXZORl2JqhetImMXzxH3XkuHQPEqQMg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@sentry-internal/browser-utils": "9.10.1",
|
||||
"@sentry/core": "9.10.1"
|
||||
"@sentry-internal/browser-utils": "9.11.0",
|
||||
"@sentry/core": "9.11.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry-internal/replay-canvas": {
|
||||
"version": "9.10.1",
|
||||
"resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-9.10.1.tgz",
|
||||
"integrity": "sha512-fxrpqElqdsAQrzVly0V/XaljhAlwwMk+iGyf+wZeK6RwEPVxtoxXVfx7fEEtPn+gortqQR09N/zH179hefjuaw==",
|
||||
"version": "9.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-9.11.0.tgz",
|
||||
"integrity": "sha512-ZcRg8TWfF0ucjK2i+4TY/blRNJ7YKrgMpx19pFj6eCOJ1K8geSkAFPIfDHcQEwIU1ZTN+HiCwx0JvTI9YZxjfg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@sentry-internal/replay": "9.10.1",
|
||||
"@sentry/core": "9.10.1"
|
||||
"@sentry-internal/replay": "9.11.0",
|
||||
"@sentry/core": "9.11.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/babel-plugin-component-annotate": {
|
||||
"version": "3.2.4",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/babel-plugin-component-annotate/-/babel-plugin-component-annotate-3.2.4.tgz",
|
||||
"integrity": "sha512-yBzRn3GEUSv1RPtE4xB4LnuH74ZxtdoRJ5cmQ9i6mzlmGDxlrnKuvem5++AolZTE9oJqAD3Tx2rd1PqmpWnLoA==",
|
||||
"version": "3.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/babel-plugin-component-annotate/-/babel-plugin-component-annotate-3.3.1.tgz",
|
||||
"integrity": "sha512-5GOxGT7lZN+I8A7Vp0rWY+726FDKEw8HnFiebe51rQrMbfGfCu2Aw9uSM0nT9OG6xhV6WvGccIcCszTPs4fUZQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 14"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/browser": {
|
||||
"version": "9.10.1",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-9.10.1.tgz",
|
||||
"integrity": "sha512-9RWjcyskhnDK2Q6LntFR90EqZD5+DXcXNqeTlE+mpVf65y7wz+9SIuVjAMP7qiDBwfxNbmTxiVCXeCuQnnATsQ==",
|
||||
"version": "9.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-9.11.0.tgz",
|
||||
"integrity": "sha512-DSDj8wQJoiLqqOcntl+7phjd8l8KN9A0vaV7mZNHWbrHU3MVwXqTyLyERRLC6wi0t7F5kqczqa3xLmKjK/fMZg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@sentry-internal/browser-utils": "9.10.1",
|
||||
"@sentry-internal/feedback": "9.10.1",
|
||||
"@sentry-internal/replay": "9.10.1",
|
||||
"@sentry-internal/replay-canvas": "9.10.1",
|
||||
"@sentry/core": "9.10.1"
|
||||
"@sentry-internal/browser-utils": "9.11.0",
|
||||
"@sentry-internal/feedback": "9.11.0",
|
||||
"@sentry-internal/replay": "9.11.0",
|
||||
"@sentry-internal/replay-canvas": "9.11.0",
|
||||
"@sentry/core": "9.11.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/bundler-plugin-core": {
|
||||
"version": "3.2.4",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/bundler-plugin-core/-/bundler-plugin-core-3.2.4.tgz",
|
||||
"integrity": "sha512-YMj9XW5W2JA89EeweE7CPKLDz245LBsI1JhCmqpt/bjSvmsSIAAPsLYnvIJBS3LQFm0OhtG8NB54PTi96dAcMA==",
|
||||
"version": "3.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/bundler-plugin-core/-/bundler-plugin-core-3.3.1.tgz",
|
||||
"integrity": "sha512-Dd6xaWb293j9otEJ1yJqG2Ra6zB49OPzMNdIkdP8wdY+S9UFQE5PyKTyredmPY7hqCc005OrUQZolIIo9Zl13A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.18.5",
|
||||
"@sentry/babel-plugin-component-annotate": "3.2.4",
|
||||
"@sentry/babel-plugin-component-annotate": "3.3.1",
|
||||
"@sentry/cli": "2.42.2",
|
||||
"dotenv": "^16.3.1",
|
||||
"find-up": "^5.0.0",
|
||||
@@ -4619,22 +4619,22 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/core": {
|
||||
"version": "9.10.1",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-9.10.1.tgz",
|
||||
"integrity": "sha512-TE2zZV3Od4131mZNgFo2Mv4aKU8FXxL0s96yqRvmV+8AU57mJoycMXBnmNSYfWuDICbPJTVAp+3bYMXwX7N5YA==",
|
||||
"version": "9.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-9.11.0.tgz",
|
||||
"integrity": "sha512-qfb4ahGZubbrNh1MnbEqyHFp87rIwQIZapyQLCaYpudXrP1biEpLOV3mMDvDJWCdX460hoOwQ3SkwipV3We/7w==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/react": {
|
||||
"version": "9.10.1",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/react/-/react-9.10.1.tgz",
|
||||
"integrity": "sha512-DYBs3F+F2elWEhWvp3HmBmORhAlTBbY0KsRj+Lt2mOSEfiz8WWrS3Ibe+9QmErVdjQZy68ic9Yt84MHL/rlmkQ==",
|
||||
"version": "9.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/react/-/react-9.11.0.tgz",
|
||||
"integrity": "sha512-sH/3KnDsLxBFRoxPyIpab7OewkfStdZQQwgpfv8R0yDKpGg4lU7KdTccryFvWL123UpHC7ydPWjdcfC8YV/EPQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@sentry/browser": "9.10.1",
|
||||
"@sentry/core": "9.10.1",
|
||||
"@sentry/browser": "9.11.0",
|
||||
"@sentry/core": "9.11.0",
|
||||
"hoist-non-react-statics": "^3.3.2"
|
||||
},
|
||||
"engines": {
|
||||
@@ -4645,12 +4645,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/vite-plugin": {
|
||||
"version": "3.2.4",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/vite-plugin/-/vite-plugin-3.2.4.tgz",
|
||||
"integrity": "sha512-ZRn5TLlq5xtwKOqaWP+XqS1PYVfbBCgsbMk7wW2Ly6EgF9wYePvtLqKgYnE3hwPg2LpBnRPR2ti1ohlUkR+wXA==",
|
||||
"version": "3.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/vite-plugin/-/vite-plugin-3.3.1.tgz",
|
||||
"integrity": "sha512-eIIIHqVOTO0m7+3aTg//gVi11XNpKi4G0xA45hjz46UmRiToVfqgBH7Dsn1qRrDxa7YPYCdREQkyGEINlElT2A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@sentry/bundler-plugin-core": "3.2.4",
|
||||
"@sentry/bundler-plugin-core": "3.3.1",
|
||||
"unplugin": "1.0.1"
|
||||
},
|
||||
"engines": {
|
||||
@@ -4658,13 +4658,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/webpack-plugin": {
|
||||
"version": "3.2.4",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/webpack-plugin/-/webpack-plugin-3.2.4.tgz",
|
||||
"integrity": "sha512-LCuNu5LXPSCq2BNke1zvEW8CXL4SPBsCjYexAx51PZ6Lp87VxWcCxGqXhr37MGpYwY10A1r31/XOe69iXHJjGA==",
|
||||
"version": "3.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/webpack-plugin/-/webpack-plugin-3.3.1.tgz",
|
||||
"integrity": "sha512-AFRnGNUnlIvq3M+ADdfWb+DIXWKK6yYEkVPAyOppkjO+cL/19gjXMdvAwv+CMFts28YCFKF8Kr3pamUiCmwodA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@sentry/bundler-plugin-core": "3.2.4",
|
||||
"@sentry/bundler-plugin-core": "3.3.1",
|
||||
"unplugin": "1.0.1",
|
||||
"uuid": "^9.0.0"
|
||||
},
|
||||
@@ -4718,9 +4718,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@splitsoftware/splitio-react": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@splitsoftware/splitio-react/-/splitio-react-2.1.0.tgz",
|
||||
"integrity": "sha512-iAGXl/qadHVFUQA/+asX8UGwDPpNi6WCKhNIzLZ6NSvt38+M8Bpc3CMnkYNEXsNsz1J+C26ICsMZ067YQ96k6g==",
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@splitsoftware/splitio-react/-/splitio-react-2.1.1.tgz",
|
||||
"integrity": "sha512-cUMyIdsgzDEFgUZxoV/PyjQR0OXt+Ffqqjh2LVcADsVDpTGUf95ydEVYaszZRVoYYj+hMw9xMw6Yfr0b+uejIQ==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@splitsoftware/splitio": "11.2.0",
|
||||
@@ -4865,9 +4865,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@testing-library/react": {
|
||||
"version": "16.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.2.0.tgz",
|
||||
"integrity": "sha512-2cSskAvA1QNtKc8Y9VJQRv0tm3hLVgxRGDB+KYhIaPQJ1I+RHbhIXcM+zClKXzMes/wshsMVzf4B9vS4IZpqDQ==",
|
||||
"version": "16.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.3.0.tgz",
|
||||
"integrity": "sha512-kFSyxiEDwv1WLl2fgsq6pPBbw5aWKrsY2/noi1Id0TK0UParSF62oFQFGHXIyaG4pp2tEub/Zlel+fjjZILDsw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -6770,9 +6770,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/call-bind-apply-helpers": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz",
|
||||
"integrity": "sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==",
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
|
||||
"integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -6784,14 +6784,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/call-bound": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz",
|
||||
"integrity": "sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==",
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
|
||||
"integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bind-apply-helpers": "^1.0.1",
|
||||
"get-intrinsic": "^1.2.6"
|
||||
"call-bind-apply-helpers": "^1.0.2",
|
||||
"get-intrinsic": "^1.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
@@ -8671,9 +8671,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-react": {
|
||||
"version": "7.37.4",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.4.tgz",
|
||||
"integrity": "sha512-BGP0jRmfYyvOyvMoRX/uoUeW+GqNj9y16bPQzqAHf3AYII/tDs+jMN0dBVkl88/OZwNGwrVFxE7riHsXVfy/LQ==",
|
||||
"version": "7.37.5",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz",
|
||||
"integrity": "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -8687,7 +8687,7 @@
|
||||
"hasown": "^2.0.2",
|
||||
"jsx-ast-utils": "^2.4.1 || ^3.0.0",
|
||||
"minimatch": "^3.1.2",
|
||||
"object.entries": "^1.1.8",
|
||||
"object.entries": "^1.1.9",
|
||||
"object.fromentries": "^2.0.8",
|
||||
"object.values": "^1.2.1",
|
||||
"prop-types": "^15.8.1",
|
||||
@@ -9403,18 +9403,18 @@
|
||||
}
|
||||
},
|
||||
"node_modules/get-intrinsic": {
|
||||
"version": "1.2.7",
|
||||
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.7.tgz",
|
||||
"integrity": "sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==",
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
|
||||
"integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bind-apply-helpers": "^1.0.1",
|
||||
"call-bind-apply-helpers": "^1.0.2",
|
||||
"es-define-property": "^1.0.1",
|
||||
"es-errors": "^1.3.0",
|
||||
"es-object-atoms": "^1.0.0",
|
||||
"es-object-atoms": "^1.1.1",
|
||||
"function-bind": "^1.1.2",
|
||||
"get-proto": "^1.0.0",
|
||||
"get-proto": "^1.0.1",
|
||||
"gopd": "^1.2.0",
|
||||
"has-symbols": "^1.1.0",
|
||||
"hasown": "^2.0.2",
|
||||
@@ -12486,15 +12486,16 @@
|
||||
}
|
||||
},
|
||||
"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==",
|
||||
"version": "1.1.9",
|
||||
"resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.9.tgz",
|
||||
"integrity": "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bind": "^1.0.7",
|
||||
"call-bind": "^1.0.8",
|
||||
"call-bound": "^1.0.4",
|
||||
"define-properties": "^1.2.1",
|
||||
"es-object-atoms": "^1.0.0"
|
||||
"es-object-atoms": "^1.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
@@ -14374,9 +14375,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/react-virtuoso": {
|
||||
"version": "4.12.6",
|
||||
"resolved": "https://registry.npmjs.org/react-virtuoso/-/react-virtuoso-4.12.6.tgz",
|
||||
"integrity": "sha512-bfvS6aCL1ehXmq39KRiz/vxznGUbtA27I5I24TYCe1DhMf84O3aVNCIwrSjYQjkJGJGzY46ihdN8WkYlemuhMQ==",
|
||||
"version": "4.12.5",
|
||||
"resolved": "https://registry.npmjs.org/react-virtuoso/-/react-virtuoso-4.12.5.tgz",
|
||||
"integrity": "sha512-YeCbRRsC9CLf0buD0Rct7WsDbzf+yBU1wGbo05/XjbcN2nJuhgh040m3y3+6HVogTZxEqVm45ac9Fpae4/MxRQ==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"react": ">=16 || >=17 || >= 18 || >= 19",
|
||||
@@ -14421,9 +14422,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/recharts": {
|
||||
"version": "2.15.1",
|
||||
"resolved": "https://registry.npmjs.org/recharts/-/recharts-2.15.1.tgz",
|
||||
"integrity": "sha512-v8PUTUlyiDe56qUj82w/EDVuzEFXwEHp9/xOowGAZwfLjB9uAy3GllQVIYMWF6nU+qibx85WF75zD7AjqoT54Q==",
|
||||
"version": "2.15.2",
|
||||
"resolved": "https://registry.npmjs.org/recharts/-/recharts-2.15.2.tgz",
|
||||
"integrity": "sha512-xv9lVztv3ingk7V3Jf05wfAZbM9Q2umJzu5t/cfnAK7LUslNrGT7LPBr74G+ok8kSCeFMaePmWMg0rcYOnczTw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"clsx": "^2.0.0",
|
||||
@@ -15070,9 +15071,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/sass": {
|
||||
"version": "1.86.1",
|
||||
"resolved": "https://registry.npmjs.org/sass/-/sass-1.86.1.tgz",
|
||||
"integrity": "sha512-Yaok4XELL1L9Im/ZUClKu//D2OP1rOljKj0Gf34a+GzLbMveOzL7CfqYo+JUa5Xt1nhTCW+OcKp/FtR7/iqj1w==",
|
||||
"version": "1.86.3",
|
||||
"resolved": "https://registry.npmjs.org/sass/-/sass-1.86.3.tgz",
|
||||
"integrity": "sha512-iGtg8kus4GrsGLRDLRBRHY9dNVA78ZaS7xr01cWnS7PEMQyFtTqBiyCrfpTYTZXRWM94akzckYjh8oADfFNTzw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"chokidar": "^4.0.0",
|
||||
@@ -15945,9 +15946,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/styled-components": {
|
||||
"version": "6.1.16",
|
||||
"resolved": "https://registry.npmjs.org/styled-components/-/styled-components-6.1.16.tgz",
|
||||
"integrity": "sha512-KpWB6ORAWGmbWM10cDJfEV6sXc/uVkkkQV3SLwTNQ/E/PqWgNHIoMSLh1Lnk2FkB9+JHK7uuMq1i+9ArxDD7iQ==",
|
||||
"version": "6.1.17",
|
||||
"resolved": "https://registry.npmjs.org/styled-components/-/styled-components-6.1.17.tgz",
|
||||
"integrity": "sha512-97D7DwWanI7nN24v0D4SvbfjLE9656umNSJZkBkDIWL37aZqG/wRQ+Y9pWtXyBIM/NSfcBzHLErEsqHmJNSVUg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@emotion/is-prop-valid": "1.2.2",
|
||||
@@ -17118,9 +17119,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/vite": {
|
||||
"version": "6.2.4",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-6.2.4.tgz",
|
||||
"integrity": "sha512-veHMSew8CcRzhL5o8ONjy8gkfmFJAd5Ac16oxBUjlwgX3Gq2Wqr+qNC3TjPIpy7TPV/KporLga5GT9HqdrCizw==",
|
||||
"version": "6.2.5",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-6.2.5.tgz",
|
||||
"integrity": "sha512-j023J/hCAa4pRIUH6J9HemwYfjB5llR2Ps0CWeikOtdR8+pAURAk0DoJC5/mm9kd+UgdnIy7d6HE4EAvlYhPhA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
"proxy": "http://localhost:4000",
|
||||
"dependencies": {
|
||||
"@ant-design/pro-layout": "^7.22.4",
|
||||
"@apollo/client": "^3.13.5",
|
||||
"@apollo/client": "^3.13.6",
|
||||
"@emotion/is-prop-valid": "^1.3.1",
|
||||
"@fingerprintjs/fingerprintjs": "^4.6.1",
|
||||
"@firebase/analytics": "^0.10.12",
|
||||
@@ -20,9 +20,9 @@
|
||||
"@jsreport/browser-client": "^3.1.0",
|
||||
"@reduxjs/toolkit": "^2.6.1",
|
||||
"@sentry/cli": "^2.43.0",
|
||||
"@sentry/react": "^9.10.1",
|
||||
"@sentry/vite-plugin": "^3.2.4",
|
||||
"@splitsoftware/splitio-react": "^2.1.0",
|
||||
"@sentry/react": "^9.11.0",
|
||||
"@sentry/vite-plugin": "^3.3.1",
|
||||
"@splitsoftware/splitio-react": "^2.1.1",
|
||||
"@tanem/react-nprogress": "^5.0.53",
|
||||
"antd": "^5.24.6",
|
||||
"apollo-link-logger": "^2.0.1",
|
||||
@@ -57,7 +57,7 @@
|
||||
"react-dom": "^18.3.1",
|
||||
"react-drag-listview": "^2.0.0",
|
||||
"react-grid-gallery": "^1.0.1",
|
||||
"react-grid-layout": "1.3.4",
|
||||
"react-grid-layout": "^1.3.4",
|
||||
"react-i18next": "^15.4.1",
|
||||
"react-icons": "^5.5.0",
|
||||
"react-image-lightbox": "^5.1.4",
|
||||
@@ -69,17 +69,17 @@
|
||||
"react-resizable": "^3.0.5",
|
||||
"react-router-dom": "^6.30.0",
|
||||
"react-sticky": "^6.0.3",
|
||||
"react-virtuoso": "^4.12.6",
|
||||
"recharts": "^2.15.0",
|
||||
"react-virtuoso": "^4.12.5",
|
||||
"recharts": "^2.15.2",
|
||||
"redux": "^5.0.1",
|
||||
"redux-actions": "^3.0.3",
|
||||
"redux-persist": "^6.0.0",
|
||||
"redux-saga": "^1.3.0",
|
||||
"redux-state-sync": "^3.1.4",
|
||||
"reselect": "^5.1.1",
|
||||
"sass": "^1.86.1",
|
||||
"sass": "^1.86.3",
|
||||
"socket.io-client": "^4.8.1",
|
||||
"styled-components": "^6.1.16",
|
||||
"styled-components": "^6.1.17",
|
||||
"subscriptions-transport-ws": "^0.11.0",
|
||||
"use-memo-one": "^1.1.3",
|
||||
"vite-plugin-ejs": "^1.7.0",
|
||||
@@ -130,22 +130,22 @@
|
||||
"@ant-design/icons": "^6.0.0",
|
||||
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
|
||||
"@babel/preset-react": "^7.26.3",
|
||||
"@dotenvx/dotenvx": "^1.39.0",
|
||||
"@dotenvx/dotenvx": "^1.39.1",
|
||||
"@emotion/babel-plugin": "^11.13.5",
|
||||
"@emotion/react": "^11.14.0",
|
||||
"@eslint/js": "^9.23.0",
|
||||
"@eslint/js": "^9.24.0",
|
||||
"@playwright/test": "^1.51.1",
|
||||
"@sentry/webpack-plugin": "^3.2.4",
|
||||
"@sentry/webpack-plugin": "^3.3.1",
|
||||
"@testing-library/dom": "^10.4.0",
|
||||
"@testing-library/jest-dom": "^6.6.3",
|
||||
"@testing-library/react": "^16.2.0",
|
||||
"@testing-library/react": "^16.3.0",
|
||||
"@vitejs/plugin-react": "^4.3.4",
|
||||
"browserslist": "^4.24.4",
|
||||
"browserslist-to-esbuild": "^2.1.1",
|
||||
"chalk": "^5.4.1",
|
||||
"eslint": "^8.57.1",
|
||||
"eslint-config-react-app": "^7.0.1",
|
||||
"eslint-plugin-react": "^7.37.4",
|
||||
"eslint-plugin-react": "^7.37.5",
|
||||
"globals": "^15.15.0",
|
||||
"jsdom": "^26.0.0",
|
||||
"memfs": "^4.17.0",
|
||||
@@ -154,7 +154,7 @@
|
||||
"react-error-overlay": "^6.1.0",
|
||||
"redux-logger": "^3.0.6",
|
||||
"source-map-explorer": "^2.5.3",
|
||||
"vite": "^6.2.4",
|
||||
"vite": "^6.2.5",
|
||||
"vite-plugin-babel": "^1.3.0",
|
||||
"vite-plugin-eslint": "^1.8.1",
|
||||
"vite-plugin-node-polyfills": "^0.23.0",
|
||||
|
||||
@@ -21,8 +21,8 @@ import "./App.styles.scss";
|
||||
import Eula from "../components/eula/eula.component";
|
||||
import InstanceRenderMgr from "../utils/instanceRenderMgr";
|
||||
import ProductFruitsWrapper from "./ProductFruitsWrapper.jsx";
|
||||
import { SocketProvider } from "../contexts/SocketIO/useSocket.jsx";
|
||||
import { NotificationProvider } from "../contexts/Notifications/notificationContext.jsx";
|
||||
import SocketProvider from "../contexts/SocketIO/socketProvider.jsx";
|
||||
|
||||
const ResetPassword = lazy(() => import("../pages/reset-password/reset-password.component"));
|
||||
const ManagePage = lazy(() => import("../pages/manage/manage.page.container"));
|
||||
@@ -142,11 +142,10 @@ export function App({ bodyshop, checkUserSession, currentUser, online, setOnline
|
||||
>
|
||||
<ProductFruitsWrapper
|
||||
currentUser={currentUser}
|
||||
workspaceCode={InstanceRenderMgr({
|
||||
imex: null,
|
||||
rome: "9BkbEseqNqxw8jUH"
|
||||
})}
|
||||
bodyshop={bodyshop}
|
||||
workspaceCode={bodyshop?.tours_enabled ? "9BkbEseqNqxw8jUH" : ""}
|
||||
/>
|
||||
|
||||
<NotificationProvider>
|
||||
<Routes>
|
||||
<Route
|
||||
|
||||
@@ -1,8 +1,16 @@
|
||||
import React from "react";
|
||||
import { ProductFruits } from "react-product-fruits";
|
||||
import PropTypes from "prop-types";
|
||||
import { ProductFruits } from "react-product-fruits";
|
||||
import dayjs from "dayjs";
|
||||
|
||||
const ProductFruitsWrapper = React.memo(({ currentUser, bodyshop, workspaceCode }) => {
|
||||
const featureProps = bodyshop?.features
|
||||
? Object.entries(bodyshop.features).reduce((acc, [key, value]) => {
|
||||
acc[key] = value === true || (typeof value === "string" && dayjs(value).isAfter(dayjs()));
|
||||
return acc;
|
||||
}, {})
|
||||
: {};
|
||||
|
||||
const ProductFruitsWrapper = React.memo(({ currentUser, workspaceCode }) => {
|
||||
return (
|
||||
workspaceCode &&
|
||||
currentUser?.authorized === true &&
|
||||
@@ -14,7 +22,8 @@ const ProductFruitsWrapper = React.memo(({ currentUser, workspaceCode }) => {
|
||||
language="en"
|
||||
user={{
|
||||
email: currentUser.email,
|
||||
username: currentUser.email
|
||||
username: currentUser.email,
|
||||
props: featureProps
|
||||
}}
|
||||
/>
|
||||
)
|
||||
@@ -28,5 +37,6 @@ ProductFruitsWrapper.propTypes = {
|
||||
authorized: PropTypes.bool,
|
||||
email: PropTypes.string
|
||||
}),
|
||||
workspaceCode: PropTypes.string
|
||||
workspaceCode: PropTypes.string,
|
||||
bodyshop: PropTypes.object
|
||||
};
|
||||
|
||||
@@ -3,11 +3,11 @@ import { getToken } from "@firebase/messaging";
|
||||
import axios from "axios";
|
||||
import { useEffect } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useSocket } from "../../contexts/SocketIO/useSocket.jsx";
|
||||
import { messaging, requestForToken } from "../../firebase/firebase.utils";
|
||||
import ChatPopupComponent from "../chat-popup/chat-popup.component";
|
||||
import "./chat-affix.styles.scss";
|
||||
import { registerMessagingHandlers, unregisterMessagingHandlers } from "./registerMessagingSocketHandlers";
|
||||
import { useSocket } from "../../contexts/SocketIO/useSocket.js";
|
||||
|
||||
export function ChatAffixContainer({ bodyshop, chatVisible }) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
@@ -3,10 +3,10 @@ import { Button } from "antd";
|
||||
import { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { TOGGLE_CONVERSATION_ARCHIVE } from "../../graphql/conversations.queries";
|
||||
import { useSocket } from "../../contexts/SocketIO/useSocket.jsx";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { selectBodyshop } from "../../redux/user/user.selectors.js";
|
||||
import { connect } from "react-redux";
|
||||
import { useSocket } from "../../contexts/SocketIO/useSocket.js";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
bodyshop: selectBodyshop
|
||||
|
||||
@@ -4,10 +4,10 @@ import { Link } from "react-router-dom";
|
||||
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 { useSocket } from "../../contexts/SocketIO/useSocket.jsx";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { selectBodyshop } from "../../redux/user/user.selectors.js";
|
||||
import { connect } from "react-redux";
|
||||
import { useSocket } from "../../contexts/SocketIO/useSocket.js";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
bodyshop: selectBodyshop
|
||||
|
||||
@@ -3,11 +3,11 @@ import axios from "axios";
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { useSocket } from "../../contexts/SocketIO/useSocket.jsx";
|
||||
import { CONVERSATION_SUBSCRIPTION_BY_PK, GET_CONVERSATION_DETAILS } from "../../graphql/conversations.queries";
|
||||
import { selectSelectedConversation } from "../../redux/messaging/messaging.selectors";
|
||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||
import ChatConversationComponent from "./chat-conversation.component";
|
||||
import { useSocket } from "../../contexts/SocketIO/useSocket.js";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
selectedConversation: selectSelectedConversation,
|
||||
|
||||
@@ -4,11 +4,11 @@ import { Input, Spin, Tag, Tooltip } from "antd";
|
||||
import { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { UPDATE_CONVERSATION_LABEL } from "../../graphql/conversations.queries";
|
||||
import { useSocket } from "../../contexts/SocketIO/useSocket.jsx";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { selectBodyshop } from "../../redux/user/user.selectors.js";
|
||||
import { connect } from "react-redux";
|
||||
import { useNotification } from "../../contexts/Notifications/notificationContext.jsx";
|
||||
import { useSocket } from "../../contexts/SocketIO/useSocket.js";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
bodyshop: selectBodyshop
|
||||
|
||||
@@ -5,7 +5,7 @@ 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 { useSocket } from "../../contexts/SocketIO/useSocket.jsx";
|
||||
import { useSocket } from "../../contexts/SocketIO/useSocket.js";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
//currentUser: selectCurrentUser
|
||||
|
||||
@@ -7,7 +7,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 { useSocket } from "../../contexts/SocketIO/useSocket.jsx";
|
||||
import { useSocket } from "../../contexts/SocketIO/useSocket.js";
|
||||
import { useNotification } from "../../contexts/Notifications/notificationContext.jsx";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
|
||||
@@ -12,9 +12,9 @@ import ChatConversationListComponent from "../chat-conversation-list/chat-conver
|
||||
import ChatConversationContainer from "../chat-conversation/chat-conversation.container";
|
||||
import ChatNewConversation from "../chat-new-conversation/chat-new-conversation.component";
|
||||
import LoadingSpinner from "../loading-spinner/loading-spinner.component";
|
||||
import { useSocket } from "../../contexts/SocketIO/useSocket.jsx";
|
||||
|
||||
import "./chat-popup.styles.scss";
|
||||
import { useSocket } from "../../contexts/SocketIO/useSocket.js";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
selectedConversation: selectSelectedConversation,
|
||||
|
||||
@@ -8,10 +8,10 @@ import { logImEXEvent } from "../../firebase/firebase.utils";
|
||||
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 { useSocket } from "../../contexts/SocketIO/useSocket.jsx";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { selectBodyshop } from "../../redux/user/user.selectors.js";
|
||||
import { connect } from "react-redux";
|
||||
import { useSocket } from "../../contexts/SocketIO/useSocket.js";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
bodyshop: selectBodyshop
|
||||
|
||||
@@ -20,6 +20,7 @@ function FeatureWrapper({
|
||||
children,
|
||||
upsellComponent,
|
||||
bypass,
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
...restProps
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
@@ -78,7 +79,11 @@ export function HasFeatureAccess({ featureName, bodyshop, bypass, debug = false
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return bodyshop?.features?.allAccess || dayjs(bodyshop?.features[featureName]).isAfter(dayjs());
|
||||
return (
|
||||
bodyshop?.features?.allAccess ||
|
||||
bodyshop?.features?.[featureName] ||
|
||||
dayjs(bodyshop?.features[featureName]).isAfter(dayjs())
|
||||
);
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, null)(FeatureWrapper);
|
||||
|
||||
@@ -40,7 +40,6 @@ import { RiSurveyLine } from "react-icons/ri";
|
||||
import { connect } from "react-redux";
|
||||
import { Link } from "react-router-dom";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { useSocket } from "../../contexts/SocketIO/useSocket.jsx";
|
||||
import { GET_UNREAD_COUNT } from "../../graphql/notifications.queries.js";
|
||||
import { selectRecentItems, selectSelectedHeader } from "../../redux/application/application.selectors";
|
||||
import { setModalContext } from "../../redux/modals/modals.actions";
|
||||
@@ -51,6 +50,7 @@ import InstanceRenderManager from "../../utils/instanceRenderMgr";
|
||||
import { HasFeatureAccess } from "../feature-wrapper/feature-wrapper.component";
|
||||
import LockWrapper from "../lock-wrapper/lock-wrapper.component";
|
||||
import NotificationCenterContainer from "../notification-center/notification-center.container.jsx";
|
||||
import { useSocket } from "../../contexts/SocketIO/useSocket.js";
|
||||
|
||||
// Redux mappings
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { AlertFilled } from "@ant-design/icons";
|
||||
import { useMutation } from "@apollo/client";
|
||||
import { useLazyQuery, useMutation } from "@apollo/client";
|
||||
import { Button, Divider, Dropdown, Form, Input, Popover, Select, Space } from "antd";
|
||||
import parsePhoneNumber from "libphonenumber-js";
|
||||
import queryString from "query-string";
|
||||
@@ -8,24 +8,30 @@ import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
import { Link, useLocation, useNavigate } from "react-router-dom";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { useSocket } from "../../contexts/SocketIO/useSocket.jsx";
|
||||
import { useNotification } from "../../contexts/Notifications/notificationContext.jsx";
|
||||
import { useSocket } from "../../contexts/SocketIO/useSocket.js";
|
||||
import { UPDATE_APPOINTMENT } from "../../graphql/appointments.queries";
|
||||
import { GET_JOB_BY_PK_QUICK_INTAKE, JOB_PRODUCTION_TOGGLE } from "../../graphql/jobs.queries";
|
||||
import { insertAuditTrail } from "../../redux/application/application.actions";
|
||||
import { openChatByPhone, setMessage } from "../../redux/messaging/messaging.actions";
|
||||
import { setModalContext } from "../../redux/modals/modals.actions";
|
||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||
import AuditTrailMapping from "../../utils/AuditTrailMappings";
|
||||
import CurrencyFormatter from "../../utils/CurrencyFormatter";
|
||||
import { DateTimeFormatterFunction } from "../../utils/DateFormatter";
|
||||
import dayjs from "../../utils/day";
|
||||
import { GenerateDocument } from "../../utils/RenderTemplate";
|
||||
import { TemplateList } from "../../utils/TemplateConstants";
|
||||
import ChatOpenButton from "../chat-open-button/chat-open-button.component";
|
||||
import DataLabel from "../data-label/data-label.component";
|
||||
import FormDateTimePickerComponent from "../form-date-time-picker/form-date-time-picker.component";
|
||||
import OwnerNameDisplay from "../owner-name-display/owner-name-display.component";
|
||||
import ProductionListColumnComment from "../production-list-columns/production-list-columns.comment.component";
|
||||
import ScheduleManualEvent from "../schedule-manual-event/schedule-manual-event.component";
|
||||
import { HasFeatureAccess } from "./../feature-wrapper/feature-wrapper.component";
|
||||
import ScheduleAtChange from "./job-at-change.component";
|
||||
import ScheduleEventColor from "./schedule-event.color.component";
|
||||
import ScheduleEventNote from "./schedule-event.note.component";
|
||||
import { useNotification } from "../../contexts/Notifications/notificationContext.jsx";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
bodyshop: selectBodyshop
|
||||
@@ -33,7 +39,8 @@ const mapStateToProps = createStructuredSelector({
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
setScheduleContext: (context) => dispatch(setModalContext({ context: context, modal: "schedule" })),
|
||||
openChatByPhone: (phone) => dispatch(openChatByPhone(phone)),
|
||||
setMessage: (text) => dispatch(setMessage(text))
|
||||
setMessage: (text) => dispatch(setMessage(text)),
|
||||
insertAuditTrail: ({ jobid, operation }) => dispatch(insertAuditTrail({ jobid, operation }))
|
||||
});
|
||||
|
||||
export function ScheduleEventComponent({
|
||||
@@ -43,16 +50,36 @@ export function ScheduleEventComponent({
|
||||
event,
|
||||
refetch,
|
||||
handleCancel,
|
||||
setScheduleContext
|
||||
setScheduleContext,
|
||||
insertAuditTrail
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
const [open, setOpen] = useState(false);
|
||||
const history = useNavigate();
|
||||
const searchParams = queryString.parse(useLocation().search);
|
||||
const [updateAppointment] = useMutation(UPDATE_APPOINTMENT);
|
||||
const [mutationUpdateJob] = useMutation(JOB_PRODUCTION_TOGGLE);
|
||||
const [title, setTitle] = useState(event.title);
|
||||
const { socket } = useSocket();
|
||||
const notification = useNotification();
|
||||
const [form] = Form.useForm();
|
||||
const [popOverVisible, setPopOverVisible] = useState(false);
|
||||
|
||||
const [getJobDetails] = useLazyQuery(GET_JOB_BY_PK_QUICK_INTAKE, {
|
||||
variables: { id: event.job.id },
|
||||
onCompleted: (data) => {
|
||||
if (data?.jobs_by_pk) {
|
||||
form.setFieldsValue({
|
||||
actual_in: data.jobs_by_pk.actual_in ? data.jobs_by_pk.actual_in : dayjs(),
|
||||
scheduled_completion: data.jobs_by_pk.scheduled_completion,
|
||||
actual_completion: data.jobs_by_pk.actual_completion,
|
||||
scheduled_delivery: data.jobs_by_pk.scheduled_delivery,
|
||||
actual_delivery: data.jobs_by_pk.actual_delivery
|
||||
});
|
||||
}
|
||||
},
|
||||
fetchPolicy: "network-only"
|
||||
});
|
||||
|
||||
const blockContent = (
|
||||
<Space direction="vertical" wrap>
|
||||
@@ -89,6 +116,74 @@ export function ScheduleEventComponent({
|
||||
</Space>
|
||||
);
|
||||
|
||||
const handleConvert = async (values) => {
|
||||
const res = await mutationUpdateJob({
|
||||
variables: {
|
||||
jobId: event.job.id,
|
||||
job: {
|
||||
...values,
|
||||
status: bodyshop.md_ro_statuses.default_arrived,
|
||||
inproduction: true
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (!res.errors) {
|
||||
notification["success"]({
|
||||
message: t("jobs.successes.converted")
|
||||
});
|
||||
insertAuditTrail({
|
||||
jobid: event.job.id,
|
||||
operation: AuditTrailMapping.jobintake(
|
||||
res.data.update_jobs.returning[0].status,
|
||||
DateTimeFormatterFunction(values.scheduled_completion)
|
||||
)
|
||||
});
|
||||
setPopOverVisible(false);
|
||||
refetch();
|
||||
}
|
||||
};
|
||||
|
||||
const popMenu = (
|
||||
<div onClick={(e) => e.stopPropagation()}>
|
||||
<Form layout="vertical" form={form} onFinish={handleConvert}>
|
||||
<Form.Item
|
||||
name={["actual_in"]}
|
||||
label={t("jobs.fields.actual_in")}
|
||||
rules={[
|
||||
{
|
||||
required: true
|
||||
//message: t("general.validation.required"),
|
||||
}
|
||||
]}
|
||||
>
|
||||
<FormDateTimePickerComponent disabled={event.ro_number} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name={["scheduled_completion"]}
|
||||
label={t("jobs.fields.scheduled_completion")}
|
||||
rules={[
|
||||
{
|
||||
required: true
|
||||
//message: t("general.validation.required"),
|
||||
}
|
||||
]}
|
||||
>
|
||||
<FormDateTimePickerComponent disabled={event.ro_number} />
|
||||
</Form.Item>
|
||||
<Form.Item name={["scheduled_delivery"]} label={t("jobs.fields.scheduled_delivery")}>
|
||||
<FormDateTimePickerComponent disabled={event.ro_number} />
|
||||
</Form.Item>
|
||||
|
||||
<Space wrap>
|
||||
<Button type="primary" onClick={() => form.submit()}>
|
||||
{t("general.actions.save")}
|
||||
</Button>
|
||||
</Space>
|
||||
</Form>
|
||||
</div>
|
||||
);
|
||||
|
||||
const popoverContent = (
|
||||
<div style={{ maxWidth: "40vw" }}>
|
||||
{!event.isintake ? (
|
||||
@@ -294,7 +389,7 @@ export function ScheduleEventComponent({
|
||||
) : (
|
||||
<ScheduleManualEvent event={event} />
|
||||
)}
|
||||
{event.isintake ? (
|
||||
{event.isintake && HasFeatureAccess({ featureName: "checklist", bodyshop }) ? (
|
||||
<Link
|
||||
to={{
|
||||
pathname: `/manage/jobs/${event.job && event.job.id}/intake`,
|
||||
@@ -303,7 +398,21 @@ export function ScheduleEventComponent({
|
||||
>
|
||||
<Button disabled={event.arrived}>{t("appointments.actions.intake")}</Button>
|
||||
</Link>
|
||||
) : null}
|
||||
) : (
|
||||
<Popover //open={open}
|
||||
content={popMenu}
|
||||
open={popOverVisible}
|
||||
onOpenChange={setPopOverVisible}
|
||||
onClick={(e) => {
|
||||
getJobDetails();
|
||||
e.stopPropagation();
|
||||
}}
|
||||
getPopupContainer={(trigger) => trigger.parentNode}
|
||||
trigger="click"
|
||||
>
|
||||
<Button disabled={event.arrived}>{t("jobs.actions.intake_quick")}</Button>
|
||||
</Popover>
|
||||
)}
|
||||
</Space>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -6,7 +6,8 @@ import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
import { Link, useLocation, useNavigate } from "react-router-dom";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { useSocket } from "../../contexts/SocketIO/useSocket.jsx";
|
||||
import { useSocket } from "../../contexts/SocketIO/useSocket.js";
|
||||
|
||||
import { logImEXEvent } from "../../firebase/firebase.utils";
|
||||
import { QUERY_JOB_CARD_DETAILS, UPDATE_JOB } from "../../graphql/jobs.queries";
|
||||
import { insertAuditTrail } from "../../redux/application/application.actions.js";
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Col, Row } from "antd";
|
||||
import React, { useState } from "react";
|
||||
import { useState } from "react";
|
||||
import InstanceRenderManager from "../../utils/instanceRenderMgr";
|
||||
import JobReconciliationBillsTable from "../job-reconciliation-bills-table/job-reconciliation-bills-table.component";
|
||||
import JobReconciliationPartsTable from "../job-reconciliation-parts-table/job-reconciliation-parts-table.component";
|
||||
import JobReconciliationTotals from "../job-reconciliation-totals/job-reconciliation-totals.component";
|
||||
import InstanceRenderManager from "../../utils/instanceRenderMgr";
|
||||
|
||||
export default function JobReconciliationModalComponent({ job, bills }) {
|
||||
const jobLineState = useState([]);
|
||||
@@ -20,7 +20,7 @@ export default function JobReconciliationModalComponent({ job, bills }) {
|
||||
|
||||
const filterFunction = InstanceRenderManager({
|
||||
imex: (j) =>
|
||||
(j.part_type !== null && j.part_type !== "PAE") ||
|
||||
(j.part_type !== null && j.part_type !== "PAE" && j.act_price !== 0 && j.part_qty !== 0) ||
|
||||
(j.line_desc && j.line_desc.toLowerCase().includes("towing") && j.lbr_op === "OP13") ||
|
||||
j.db_ref === "936004", //ADD SHIPPING LINE.
|
||||
rome: (j) =>
|
||||
|
||||
@@ -9,7 +9,7 @@ import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
import { Link, useNavigate } from "react-router-dom";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { useSocket } from "../../contexts/SocketIO/useSocket.jsx";
|
||||
import { useSocket } from "../../contexts/SocketIO/useSocket.js";
|
||||
import { auth, logImEXEvent } from "../../firebase/firebase.utils";
|
||||
import { CANCEL_APPOINTMENTS_BY_JOB_ID, INSERT_MANUAL_APPT } from "../../graphql/appointments.queries";
|
||||
import { GET_CURRENT_QUESTIONSET_ID, INSERT_CSI } from "../../graphql/csi.queries";
|
||||
@@ -133,6 +133,16 @@ export function JobsDetailHeaderActions({
|
||||
const { socket } = useSocket();
|
||||
const notification = useNotification();
|
||||
|
||||
const isDevEnv = import.meta.env.DEV;
|
||||
const isProdEnv = import.meta.env.PROD;
|
||||
const userEmail = currentUser?.email || "";
|
||||
|
||||
const devEmails = ["imex.dev", "rome.dev"];
|
||||
const prodEmails = ["imex.prod", "rome.prod", "imex.test", "rome.test"];
|
||||
|
||||
const hasValidEmail = (emails) => emails.some((email) => userEmail.endsWith(email));
|
||||
const canSubmitForTesting = (isDevEnv && hasValidEmail(devEmails)) || (isProdEnv && hasValidEmail(prodEmails));
|
||||
|
||||
const {
|
||||
treatments: { ImEXPay }
|
||||
} = useSplitTreatments({
|
||||
@@ -171,7 +181,7 @@ export function JobsDetailHeaderActions({
|
||||
{ defaultOpenStatus: bodyshop.md_ro_statuses.default_imported },
|
||||
(newJobId) => {
|
||||
history(`/manage/jobs/${newJobId}`);
|
||||
notification["success"]({
|
||||
notification.success({
|
||||
message: t("jobs.successes.duplicated")
|
||||
});
|
||||
},
|
||||
@@ -181,7 +191,7 @@ export function JobsDetailHeaderActions({
|
||||
const handleDuplicateConfirm = () =>
|
||||
DuplicateJob(client, job.id, { defaultOpenStatus: bodyshop.md_ro_statuses.default_imported }, (newJobId) => {
|
||||
history(`/manage/jobs/${newJobId}`);
|
||||
notification["success"]({
|
||||
notification.success({
|
||||
message: t("jobs.successes.duplicated")
|
||||
});
|
||||
});
|
||||
@@ -217,13 +227,13 @@ export function JobsDetailHeaderActions({
|
||||
const result = await deleteJob({ variables: { id: job.id } });
|
||||
|
||||
if (!result.errors) {
|
||||
notification["success"]({
|
||||
notification.success({
|
||||
message: t("jobs.successes.delete")
|
||||
});
|
||||
//go back to jobs list.
|
||||
history(`/manage/`);
|
||||
} else {
|
||||
notification["error"]({
|
||||
notification.error({
|
||||
message: t("jobs.errors.deleted", {
|
||||
error: JSON.stringify(result.errors)
|
||||
})
|
||||
@@ -275,9 +285,9 @@ export function JobsDetailHeaderActions({
|
||||
});
|
||||
|
||||
if (!result.errors) {
|
||||
notification["success"]({ message: t("csi.successes.created") });
|
||||
notification.success({ message: t("csi.successes.created") });
|
||||
} else {
|
||||
notification["error"]({
|
||||
notification.error({
|
||||
message: t("csi.errors.creating", {
|
||||
message: JSON.stringify(result.errors)
|
||||
})
|
||||
@@ -316,7 +326,7 @@ export function JobsDetailHeaderActions({
|
||||
`${window.location.protocol}//${window.location.host}/csi/${result.data.insert_csi.returning[0].id}`
|
||||
);
|
||||
} else {
|
||||
notification["error"]({
|
||||
notification.error({
|
||||
message: t("messaging.error.invalidphone")
|
||||
});
|
||||
}
|
||||
@@ -328,7 +338,7 @@ export function JobsDetailHeaderActions({
|
||||
);
|
||||
}
|
||||
} else {
|
||||
notification["error"]({
|
||||
notification.error({
|
||||
message: t("csi.errors.notconfigured")
|
||||
});
|
||||
}
|
||||
@@ -358,7 +368,7 @@ export function JobsDetailHeaderActions({
|
||||
});
|
||||
setMessage(`${window.location.protocol}//${window.location.host}/csi/${job.csiinvites[0].id}`);
|
||||
} else {
|
||||
notification["error"]({
|
||||
notification.error({
|
||||
message: t("messaging.error.invalidphone")
|
||||
});
|
||||
}
|
||||
@@ -398,7 +408,7 @@ export function JobsDetailHeaderActions({
|
||||
});
|
||||
|
||||
if (!result.errors) {
|
||||
notification["success"]({
|
||||
notification.success({
|
||||
message: t("jobs.successes.voided")
|
||||
});
|
||||
insertAuditTrail({
|
||||
@@ -409,7 +419,7 @@ export function JobsDetailHeaderActions({
|
||||
//go back to jobs list.
|
||||
history(`/manage/`);
|
||||
} else {
|
||||
notification["error"]({
|
||||
notification.error({
|
||||
message: t("jobs.errors.voiding", {
|
||||
error: JSON.stringify(result.errors)
|
||||
})
|
||||
@@ -442,7 +452,7 @@ export function JobsDetailHeaderActions({
|
||||
console.log("handle -> XML", QbXmlResponse);
|
||||
} catch (error) {
|
||||
console.log("Error getting QBXML from Server.", error);
|
||||
notification["error"]({
|
||||
notification.error({
|
||||
message: t("jobs.errors.exporting", {
|
||||
error: "Unable to retrieve QBXML. " + JSON.stringify(error.message)
|
||||
})
|
||||
@@ -460,7 +470,7 @@ export function JobsDetailHeaderActions({
|
||||
});
|
||||
} catch (error) {
|
||||
console.log("Error connecting to quickbooks or partner.", error);
|
||||
notification["error"]({
|
||||
notification.error({
|
||||
message: t("jobs.errors.exporting-partner")
|
||||
});
|
||||
|
||||
@@ -556,7 +566,7 @@ export function JobsDetailHeaderActions({
|
||||
}
|
||||
});
|
||||
if (!jobUpdate.errors) {
|
||||
notification["success"]({
|
||||
notification.success({
|
||||
message: t("appointments.successes.canceled")
|
||||
});
|
||||
insertAuditTrail({
|
||||
@@ -931,11 +941,11 @@ export function JobsDetailHeaderActions({
|
||||
});
|
||||
|
||||
if (!result.errors) {
|
||||
notification["success"]({
|
||||
notification.success({
|
||||
message: t("jobs.successes.partsqueue")
|
||||
});
|
||||
} else {
|
||||
notification["error"]({
|
||||
notification.error({
|
||||
message: t("jobs.errors.saving", {
|
||||
error: JSON.stringify(result.errors)
|
||||
})
|
||||
@@ -1111,6 +1121,27 @@ export function JobsDetailHeaderActions({
|
||||
});
|
||||
}
|
||||
|
||||
if (canSubmitForTesting) {
|
||||
menuItems.push({
|
||||
key: "submitfortesting",
|
||||
id: "job-actions-submitfortesting",
|
||||
label: t("menus.jobsactions.submit-for-testing"),
|
||||
onClick: async () => {
|
||||
try {
|
||||
await axios.post("/job/totals-recorder", { id: job.id });
|
||||
notification.success({
|
||||
message: t("general.messages.submit-for-testing")
|
||||
});
|
||||
} catch (err) {
|
||||
console.error(`Error submitting job for testing: ${err?.message}`);
|
||||
notification.error({
|
||||
message: t("general.errors.submit-for-testing-error")
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const menu = {
|
||||
items: menuItems,
|
||||
key: "popovermenu"
|
||||
|
||||
@@ -3,10 +3,10 @@ import { useQuery } from "@apollo/client";
|
||||
import { connect } from "react-redux";
|
||||
import NotificationCenterComponent from "./notification-center.component";
|
||||
import { GET_NOTIFICATIONS } from "../../graphql/notifications.queries";
|
||||
import { INITIAL_NOTIFICATIONS, useSocket } from "../../contexts/SocketIO/useSocket.jsx";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { selectBodyshop } from "../../redux/user/user.selectors.js";
|
||||
import day from "../../utils/day.js";
|
||||
import { INITIAL_NOTIFICATIONS, useSocket } from "../../contexts/SocketIO/useSocket.js";
|
||||
|
||||
// This will be used to poll for notifications when the socket is disconnected
|
||||
const NOTIFICATION_POLL_INTERVAL_SECONDS = 60;
|
||||
|
||||
@@ -10,7 +10,7 @@ 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 { useSocket } from "../../contexts/SocketIO/useSocket.jsx";
|
||||
import { useSocket } from "../../contexts/SocketIO/useSocket.js";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
bodyshop: selectBodyshop,
|
||||
|
||||
@@ -12,7 +12,7 @@ import { QUERY_KANBAN_SETTINGS } from "../../graphql/user.queries";
|
||||
import { selectBodyshop, selectCurrentUser } from "../../redux/user/user.selectors";
|
||||
import ProductionBoardKanbanComponent from "./production-board-kanban.component";
|
||||
import { useSplitTreatments } from "@splitsoftware/splitio-react";
|
||||
import { useSocket } from "../../contexts/SocketIO/useSocket.jsx";
|
||||
import { useSocket } from "../../contexts/SocketIO/useSocket.js";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
bodyshop: selectBodyshop,
|
||||
|
||||
@@ -7,7 +7,7 @@ import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
import { useLocation, useNavigate } from "react-router-dom";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { useSocket } from "../../contexts/SocketIO/useSocket.jsx";
|
||||
import { useSocket } from "../../contexts/SocketIO/useSocket.js";
|
||||
import { logImEXEvent } from "../../firebase/firebase.utils.js";
|
||||
import { QUERY_JOB_CARD_DETAILS, UPDATE_JOB } from "../../graphql/jobs.queries";
|
||||
import { insertAuditTrail } from "../../redux/application/application.actions.js";
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
import ProductionListTable from "./production-list-table.component";
|
||||
import _ from "lodash";
|
||||
import { useSplitTreatments } from "@splitsoftware/splitio-react";
|
||||
import { useSocket } from "../../contexts/SocketIO/useSocket.jsx";
|
||||
import { useSocket } from "../../contexts/SocketIO/useSocket.js";
|
||||
|
||||
export default function ProductionListTableContainer({ bodyshop, subscriptionType = "direct" }) {
|
||||
const client = useApolloClient();
|
||||
|
||||
@@ -8,7 +8,7 @@ import { selectCurrentUser } from "../../redux/user/user.selectors";
|
||||
import { logImEXEvent, updateCurrentPassword } from "../../firebase/firebase.utils";
|
||||
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
|
||||
import { useNotification } from "../../contexts/Notifications/notificationContext.jsx";
|
||||
import { useSocket } from "../../contexts/SocketIO/useSocket.jsx";
|
||||
import { useSocket } from "../../contexts/SocketIO/useSocket.js";
|
||||
import NotificationSettingsForm from "../notification-settings/notification-settings-form.component.jsx";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { createContext, useContext, useEffect, useRef, useState } from "react";
|
||||
// SocketProvider.js
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import SocketIO from "socket.io-client";
|
||||
import { auth } from "../../firebase/firebase.utils";
|
||||
import { store } from "../../redux/store";
|
||||
@@ -15,10 +16,7 @@ import {
|
||||
import { useMutation } from "@apollo/client";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useSplitTreatments } from "@splitsoftware/splitio-react";
|
||||
|
||||
const SocketContext = createContext(null);
|
||||
|
||||
const INITIAL_NOTIFICATIONS = 10;
|
||||
import { SocketContext, INITIAL_NOTIFICATIONS } from "./useSocket.js";
|
||||
|
||||
/**
|
||||
* Socket Provider - Scenario Notifications / Web Socket related items
|
||||
@@ -216,7 +214,6 @@ const SocketProvider = ({ children, bodyshop, navigate, currentUser }) => {
|
||||
};
|
||||
|
||||
const handleNotification = (data) => {
|
||||
// Scenario Notifications have been disabled, bail.
|
||||
if (Realtime_Notifications_UI?.treatment !== "on") {
|
||||
return;
|
||||
}
|
||||
@@ -336,7 +333,6 @@ const SocketProvider = ({ children, bodyshop, navigate, currentUser }) => {
|
||||
};
|
||||
|
||||
const handleSyncNotificationRead = ({ notificationId, timestamp }) => {
|
||||
// Scenario Notifications have been disabled, bail.
|
||||
if (Realtime_Notifications_UI?.treatment !== "on") {
|
||||
return;
|
||||
}
|
||||
@@ -378,7 +374,6 @@ const SocketProvider = ({ children, bodyshop, navigate, currentUser }) => {
|
||||
};
|
||||
|
||||
const handleSyncAllNotificationsRead = ({ timestamp }) => {
|
||||
// Scenario Notifications have been disabled, bail.
|
||||
if (Realtime_Notifications_UI?.treatment !== "on") {
|
||||
return;
|
||||
}
|
||||
@@ -490,11 +485,4 @@ const SocketProvider = ({ children, bodyshop, navigate, currentUser }) => {
|
||||
);
|
||||
};
|
||||
|
||||
const useSocket = () => {
|
||||
const context = useContext(SocketContext);
|
||||
// NOTE: Not sure if we absolutely require this, does cause slipups on dev env
|
||||
if (!context) throw new Error("useSocket must be used within a SocketProvider");
|
||||
return context;
|
||||
};
|
||||
|
||||
export { SocketContext, SocketProvider, INITIAL_NOTIFICATIONS, useSocket };
|
||||
export default SocketProvider;
|
||||
13
client/src/contexts/SocketIO/useSocket.js
Normal file
13
client/src/contexts/SocketIO/useSocket.js
Normal file
@@ -0,0 +1,13 @@
|
||||
import { createContext, useContext } from "react";
|
||||
|
||||
const SocketContext = createContext(null);
|
||||
|
||||
const INITIAL_NOTIFICATIONS = 10;
|
||||
|
||||
const useSocket = () => {
|
||||
const context = useContext(SocketContext);
|
||||
if (!context) throw new Error("useSocket must be used within a SocketProvider");
|
||||
return context;
|
||||
};
|
||||
|
||||
export { SocketContext, INITIAL_NOTIFICATIONS, useSocket };
|
||||
@@ -57,6 +57,7 @@ export const QUERY_BODYSHOP = gql`
|
||||
logo_img_path
|
||||
md_ro_statuses
|
||||
md_order_statuses
|
||||
tours_enabled
|
||||
md_functionality_toggles
|
||||
shopname
|
||||
state
|
||||
@@ -186,6 +187,7 @@ export const UPDATE_SHOP = gql`
|
||||
phone
|
||||
federal_tax_id
|
||||
id
|
||||
tours_enabled
|
||||
insurance_vendor_id
|
||||
logo_img_path
|
||||
md_ro_statuses
|
||||
|
||||
@@ -78,6 +78,9 @@ export const QUERY_PARTS_ORDER_OEC = gql`
|
||||
}
|
||||
ro_number
|
||||
clm_no
|
||||
cieca_stl
|
||||
cieca_ttl
|
||||
cieca_pfl
|
||||
asgn_no
|
||||
asgn_date
|
||||
state_tax_rate
|
||||
@@ -164,6 +167,7 @@ export const QUERY_PARTS_ORDER_OEC = gql`
|
||||
loss_desc
|
||||
loss_of_use
|
||||
loss_type
|
||||
materials
|
||||
ownr_addr1
|
||||
ownr_addr2
|
||||
ownr_city
|
||||
|
||||
@@ -56,7 +56,7 @@ import { DateTimeFormat } from "../../utils/DateFormatter";
|
||||
import dayjs from "../../utils/day";
|
||||
import UndefinedToNull from "../../utils/undefinedtonull";
|
||||
import { useNotification } from "../../contexts/Notifications/notificationContext.jsx";
|
||||
import { useSocket } from "../../contexts/SocketIO/useSocket.jsx";
|
||||
import { useSocket } from "../../contexts/SocketIO/useSocket.js";
|
||||
import JobWatcherToggleContainer from "../../components/job-watcher-toggle/job-watcher-toggle.container.jsx";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
|
||||
@@ -20,7 +20,6 @@ import PartnerPingComponent from "../../components/partner-ping/partner-ping.com
|
||||
import PrintCenterModalContainer from "../../components/print-center-modal/print-center-modal.container";
|
||||
import ShopSubStatusComponent from "../../components/shop-sub-status/shop-sub-status.component";
|
||||
import { requestForToken } from "../../firebase/firebase.utils";
|
||||
import { useSocket } from "../../contexts/SocketIO/useSocket.jsx";
|
||||
import { selectBodyshop, selectInstanceConflict } from "../../redux/user/user.selectors";
|
||||
import UpdateAlert from "../../components/update-alert/update-alert.component";
|
||||
import InstanceRenderManager from "../../utils/instanceRenderMgr.js";
|
||||
@@ -29,6 +28,7 @@ import WssStatusDisplayComponent from "../../components/wss-status-display/wss-s
|
||||
import { selectAlerts } from "../../redux/application/application.selectors.js";
|
||||
import { addAlerts } from "../../redux/application/application.actions.js";
|
||||
import { useNotification } from "../../contexts/Notifications/notificationContext.jsx";
|
||||
import { useSocket } from "../../contexts/SocketIO/useSocket.js";
|
||||
|
||||
const JobsPage = lazy(() => import("../jobs/jobs.page"));
|
||||
|
||||
|
||||
@@ -1220,7 +1220,8 @@
|
||||
"errors": {
|
||||
"fcm": "You must allow notification permissions to have real time messaging. Click to try again.",
|
||||
"notfound": "No record was found.",
|
||||
"sizelimit": "The selected items exceed the size limit."
|
||||
"sizelimit": "The selected items exceed the size limit.",
|
||||
"submit-for-testing": "Error submitting Job for testing."
|
||||
},
|
||||
"itemtypes": {
|
||||
"contract": "CC Contract",
|
||||
@@ -1322,7 +1323,8 @@
|
||||
"partnernotrunning": "{{app}} has detected that the partner is not running. Please ensure it is running to enable full functionality.",
|
||||
"rbacunauth": "You are not authorized to view this content. Please reach out to your shop manager to change your access level.",
|
||||
"unsavedchanges": "You have unsaved changes.",
|
||||
"unsavedchangespopup": "You have unsaved changes. Are you sure you want to leave?"
|
||||
"unsavedchangespopup": "You have unsaved changes. Are you sure you want to leave?",
|
||||
"submit-for-testing": "Submitted Job for testing successfully."
|
||||
},
|
||||
"validation": {
|
||||
"dateRangeExceeded": "The date range has been exceeded.",
|
||||
@@ -2314,7 +2316,8 @@
|
||||
"duplicate": "Duplicate this Job",
|
||||
"duplicatenolines": "Duplicate this Job without Repair Data",
|
||||
"newcccontract": "Create Courtesy Car Contract",
|
||||
"void": "Void Job"
|
||||
"void": "Void Job",
|
||||
"submit-for-testing": "Submit for Testing"
|
||||
},
|
||||
"jobsdetail": {
|
||||
"claimdetail": "Claim Details",
|
||||
|
||||
@@ -1220,7 +1220,8 @@
|
||||
"errors": {
|
||||
"fcm": "",
|
||||
"notfound": "",
|
||||
"sizelimit": ""
|
||||
"sizelimit": "",
|
||||
"submit-for-testing": ""
|
||||
},
|
||||
"itemtypes": {
|
||||
"contract": "",
|
||||
@@ -1322,7 +1323,8 @@
|
||||
"partnernotrunning": "",
|
||||
"rbacunauth": "",
|
||||
"unsavedchanges": "Usted tiene cambios no guardados.",
|
||||
"unsavedchangespopup": ""
|
||||
"unsavedchangespopup": "",
|
||||
"submit-for-testing": ""
|
||||
},
|
||||
"validation": {
|
||||
"dateRangeExceeded": "",
|
||||
@@ -2314,7 +2316,8 @@
|
||||
"duplicate": "",
|
||||
"duplicatenolines": "",
|
||||
"newcccontract": "",
|
||||
"void": ""
|
||||
"void": "",
|
||||
"submit-for-testing": ""
|
||||
},
|
||||
"jobsdetail": {
|
||||
"claimdetail": "Detalles de la reclamación",
|
||||
|
||||
@@ -1220,7 +1220,8 @@
|
||||
"errors": {
|
||||
"fcm": "",
|
||||
"notfound": "",
|
||||
"sizelimit": ""
|
||||
"sizelimit": "",
|
||||
"submit-for-testing": ""
|
||||
},
|
||||
"itemtypes": {
|
||||
"contract": "",
|
||||
@@ -1322,7 +1323,9 @@
|
||||
"partnernotrunning": "",
|
||||
"rbacunauth": "",
|
||||
"unsavedchanges": "Vous avez des changements non enregistrés.",
|
||||
"unsavedchangespopup": ""
|
||||
"unsavedchangespopup": "",
|
||||
"submit-for-testing": ""
|
||||
|
||||
},
|
||||
"validation": {
|
||||
"dateRangeExceeded": "",
|
||||
@@ -2314,7 +2317,8 @@
|
||||
"duplicate": "",
|
||||
"duplicatenolines": "",
|
||||
"newcccontract": "",
|
||||
"void": ""
|
||||
"void": "",
|
||||
"submit-for-testing": ""
|
||||
},
|
||||
"jobsdetail": {
|
||||
"claimdetail": "Détails de la réclamation",
|
||||
|
||||
@@ -15,8 +15,8 @@ const AuditTrailMapping = {
|
||||
jobchecklist: (type, inproduction, status) =>
|
||||
i18n.t("audit_trail.messages.jobchecklist", { type, inproduction, status }),
|
||||
jobconverted: (ro_number) => i18n.t("audit_trail.messages.jobconverted", { ro_number }),
|
||||
jobintake: (status, email, scheduled_completion) =>
|
||||
i18n.t("audit_trail.messages.jobintake", { status, email, scheduled_completion }),
|
||||
jobintake: (status, scheduled_completion) =>
|
||||
i18n.t("audit_trail.messages.jobintake", { status, scheduled_completion }),
|
||||
jobdelivery: (status, email, actual_completion) =>
|
||||
i18n.t("audit_trail.messages.jobdelivery", { status, email, actual_completion }),
|
||||
jobexported: () => i18n.t("audit_trail.messages.jobexported"),
|
||||
|
||||
@@ -117,6 +117,7 @@ services:
|
||||
aws --endpoint-url=http://localstack:4566 secretsmanager create-secret --name CHATTER_PRIVATE_KEY --secret-string file:///tmp/certs/io-ftp-test.key
|
||||
aws --endpoint-url=http://localstack:4566 logs create-log-group --log-group-name development --region ca-central-1
|
||||
aws --endpoint-url=http://localstack:4566 s3api create-bucket --bucket imex-large-log --create-bucket-configuration LocationConstraint=ca-central-1
|
||||
aws --endpoint-url=http://localstack:4566 s3api create-bucket --bucket imex-job-totals --create-bucket-configuration LocationConstraint=ca-central-1
|
||||
"
|
||||
# Node App: The Main IMEX API
|
||||
node-app:
|
||||
|
||||
77
download-job-totals-fixtures.js
Normal file
77
download-job-totals-fixtures.js
Normal file
@@ -0,0 +1,77 @@
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const logger = require("./server/utils/logger"); // Assuming same logger utility
|
||||
const s3Client = require("./server/utils/s3"); // Using the S3 client utilities with LocalStack support
|
||||
|
||||
// Set bucket name for development with LocalStack
|
||||
const S3_BUCKET_NAME = "imex-job-totals";
|
||||
|
||||
// Set fixtures directory path
|
||||
const FIXTURES_DIR = path.join(__dirname, "server", "job", "test", "fixtures", "job-totals");
|
||||
|
||||
const ensureFixturesDirectory = () => {
|
||||
if (!fs.existsSync(FIXTURES_DIR)) {
|
||||
fs.mkdirSync(FIXTURES_DIR, { recursive: true });
|
||||
logger.log(`Created fixtures directory: ${FIXTURES_DIR}`, "info");
|
||||
}
|
||||
};
|
||||
|
||||
const downloadJsonFiles = async (userInfo = { email: "system" }) => {
|
||||
logger.log(`Starting download of JSON files from bucket: ${S3_BUCKET_NAME}`, "debug", userInfo.email);
|
||||
|
||||
try {
|
||||
ensureFixturesDirectory();
|
||||
const contents = await s3Client.listFilesInS3Bucket(S3_BUCKET_NAME);
|
||||
|
||||
if (!contents.length) {
|
||||
logger.log("No files found in bucket", "info", userInfo.email);
|
||||
return;
|
||||
}
|
||||
|
||||
logger.log(`Found ${contents.length} files in bucket`, "info", userInfo.email);
|
||||
|
||||
for (const item of contents) {
|
||||
if (!item.Key.endsWith(".json")) {
|
||||
logger.log(`Skipping non-JSON file: ${item.Key}`, "debug", userInfo.email);
|
||||
continue;
|
||||
}
|
||||
|
||||
logger.log(`Downloading: ${item.Key}`, "debug", userInfo.email);
|
||||
const fileData = await s3Client.downloadFileFromS3({
|
||||
bucketName: S3_BUCKET_NAME,
|
||||
key: item.Key
|
||||
});
|
||||
|
||||
const fileContent = await fileData.transformToString();
|
||||
const fileName = path.basename(item.Key);
|
||||
const filePath = path.join(FIXTURES_DIR, fileName);
|
||||
|
||||
fs.writeFileSync(filePath, fileContent);
|
||||
logger.log(`Saved: ${filePath}`, "info", userInfo.email);
|
||||
}
|
||||
|
||||
logger.log("Download completed successfully", "info", userInfo.email);
|
||||
} catch (error) {
|
||||
logger.log("Failed to download JSON files", "error", userInfo.email, null, {
|
||||
error: error?.message,
|
||||
stack: error?.stack
|
||||
});
|
||||
throw error; // Re-throw to trigger process exit with error code
|
||||
}
|
||||
};
|
||||
|
||||
// Run the download if script is executed directly
|
||||
if (require.main === module) {
|
||||
(async () => {
|
||||
try {
|
||||
await downloadJsonFiles();
|
||||
console.log("Script completed successfully");
|
||||
process.exit(0); // Explicitly exit with success code
|
||||
} catch (error) {
|
||||
console.error("Fatal error downloading files:", error);
|
||||
process.exit(1); // Explicitly exit with error code
|
||||
}
|
||||
})();
|
||||
}
|
||||
|
||||
module.exports = downloadJsonFiles;
|
||||
@@ -965,6 +965,7 @@
|
||||
- insurance_vendor_id
|
||||
- intakechecklist
|
||||
- intellipay_config
|
||||
- intellipay_merchant_id
|
||||
- jc_hourly_rates
|
||||
- jobsizelimit
|
||||
- last_name_first
|
||||
@@ -1023,6 +1024,7 @@
|
||||
- template_header
|
||||
- textid
|
||||
- timezone
|
||||
- tours_enabled
|
||||
- tt_allow_post_to_invoiced
|
||||
- tt_enforce_hours_for_tech_console
|
||||
- updated_at
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
-- Could not auto-generate a down migration.
|
||||
-- Please write an appropriate down migration for the SQL below:
|
||||
-- alter table "public"."bodyshops" add column "tours_enabled" boolean
|
||||
-- not null default 'true';
|
||||
@@ -0,0 +1,2 @@
|
||||
alter table "public"."bodyshops" add column "tours_enabled" boolean
|
||||
not null default 'true';
|
||||
293
package-lock.json
generated
293
package-lock.json
generated
@@ -9,14 +9,14 @@
|
||||
"version": "0.2.0",
|
||||
"license": "UNLICENSED",
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-cloudwatch-logs": "^3.777.0",
|
||||
"@aws-sdk/client-elasticache": "^3.777.0",
|
||||
"@aws-sdk/client-s3": "^3.779.0",
|
||||
"@aws-sdk/client-secrets-manager": "^3.777.0",
|
||||
"@aws-sdk/client-ses": "^3.777.0",
|
||||
"@aws-sdk/credential-provider-node": "^3.777.0",
|
||||
"@aws-sdk/lib-storage": "^3.779.0",
|
||||
"@aws-sdk/s3-request-presigner": "^3.779.0",
|
||||
"@aws-sdk/client-cloudwatch-logs": "^3.782.0",
|
||||
"@aws-sdk/client-elasticache": "^3.782.0",
|
||||
"@aws-sdk/client-s3": "^3.782.0",
|
||||
"@aws-sdk/client-secrets-manager": "^3.782.0",
|
||||
"@aws-sdk/client-ses": "^3.782.0",
|
||||
"@aws-sdk/credential-provider-node": "^3.782.0",
|
||||
"@aws-sdk/lib-storage": "^3.782.0",
|
||||
"@aws-sdk/s3-request-presigner": "^3.782.0",
|
||||
"@opensearch-project/opensearch": "^2.13.0",
|
||||
"@socket.io/admin-ui": "^0.5.1",
|
||||
"@socket.io/redis-adapter": "^8.3.0",
|
||||
@@ -26,7 +26,7 @@
|
||||
"bee-queue": "^1.7.1",
|
||||
"better-queue": "^3.8.12",
|
||||
"bluebird": "^3.7.2",
|
||||
"bullmq": "^5.45.2",
|
||||
"bullmq": "^5.48.0",
|
||||
"chart.js": "^4.4.8",
|
||||
"cloudinary": "^2.6.0",
|
||||
"compression": "^1.8.0",
|
||||
@@ -62,7 +62,7 @@
|
||||
"socket.io": "^4.8.1",
|
||||
"socket.io-adapter": "^2.5.5",
|
||||
"ssh2-sftp-client": "^11.0.0",
|
||||
"twilio": "^5.5.1",
|
||||
"twilio": "^5.5.2",
|
||||
"uuid": "^11.1.0",
|
||||
"winston": "^3.17.0",
|
||||
"winston-cloudwatch": "^6.3.0",
|
||||
@@ -70,10 +70,10 @@
|
||||
"xmlbuilder2": "^3.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.23.0",
|
||||
"@eslint/js": "^9.24.0",
|
||||
"@trivago/prettier-plugin-sort-imports": "^5.2.2",
|
||||
"eslint": "^9.23.0",
|
||||
"eslint-plugin-react": "^7.37.4",
|
||||
"eslint": "^9.24.0",
|
||||
"eslint-plugin-react": "^7.37.5",
|
||||
"globals": "^15.15.0",
|
||||
"mock-require": "^3.0.3",
|
||||
"p-limit": "^3.1.0",
|
||||
@@ -290,24 +290,24 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/client-cloudwatch-logs": {
|
||||
"version": "3.777.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/client-cloudwatch-logs/-/client-cloudwatch-logs-3.777.0.tgz",
|
||||
"integrity": "sha512-ebrO1ZlgSKEYERegcKnyjC0VkvLnxDm2HES78N54MiMQCfFCUJ3W6xx2aoKVSVWaUrGUaY13Cd67h/X0RhuU6g==",
|
||||
"version": "3.782.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/client-cloudwatch-logs/-/client-cloudwatch-logs-3.782.0.tgz",
|
||||
"integrity": "sha512-hUyMYWebb1HRCSK9jynWRQfNJoRhPaScvbePTPkNJybrVAo+7q2D5/nFP6burroRSWfYEaJXRNgr1besLjZZBA==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@aws-crypto/sha256-browser": "5.2.0",
|
||||
"@aws-crypto/sha256-js": "5.2.0",
|
||||
"@aws-sdk/core": "3.775.0",
|
||||
"@aws-sdk/credential-provider-node": "3.777.0",
|
||||
"@aws-sdk/credential-provider-node": "3.782.0",
|
||||
"@aws-sdk/middleware-host-header": "3.775.0",
|
||||
"@aws-sdk/middleware-logger": "3.775.0",
|
||||
"@aws-sdk/middleware-recursion-detection": "3.775.0",
|
||||
"@aws-sdk/middleware-user-agent": "3.775.0",
|
||||
"@aws-sdk/middleware-user-agent": "3.782.0",
|
||||
"@aws-sdk/region-config-resolver": "3.775.0",
|
||||
"@aws-sdk/types": "3.775.0",
|
||||
"@aws-sdk/util-endpoints": "3.775.0",
|
||||
"@aws-sdk/util-endpoints": "3.782.0",
|
||||
"@aws-sdk/util-user-agent-browser": "3.775.0",
|
||||
"@aws-sdk/util-user-agent-node": "3.775.0",
|
||||
"@aws-sdk/util-user-agent-node": "3.782.0",
|
||||
"@smithy/config-resolver": "^4.1.0",
|
||||
"@smithy/core": "^3.2.0",
|
||||
"@smithy/eventstream-serde-browser": "^4.0.2",
|
||||
@@ -358,24 +358,24 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/client-elasticache": {
|
||||
"version": "3.777.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/client-elasticache/-/client-elasticache-3.777.0.tgz",
|
||||
"integrity": "sha512-6MzXEyUwVIxJqNQh4rvSE32OweJtG9PYdp3UxXfoiuslJnuHgPxWMRpvJIkF/hLeAjfQf4cPii5pBYrfHDbz+g==",
|
||||
"version": "3.782.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/client-elasticache/-/client-elasticache-3.782.0.tgz",
|
||||
"integrity": "sha512-brN4paoCUMtGrt4rm23B0/9V6jdKzlc/630u8AJtTeeKCHLMQhzl4O1TJKh0jPvEs2xXt4uNLquKpIxKPQcMVQ==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@aws-crypto/sha256-browser": "5.2.0",
|
||||
"@aws-crypto/sha256-js": "5.2.0",
|
||||
"@aws-sdk/core": "3.775.0",
|
||||
"@aws-sdk/credential-provider-node": "3.777.0",
|
||||
"@aws-sdk/credential-provider-node": "3.782.0",
|
||||
"@aws-sdk/middleware-host-header": "3.775.0",
|
||||
"@aws-sdk/middleware-logger": "3.775.0",
|
||||
"@aws-sdk/middleware-recursion-detection": "3.775.0",
|
||||
"@aws-sdk/middleware-user-agent": "3.775.0",
|
||||
"@aws-sdk/middleware-user-agent": "3.782.0",
|
||||
"@aws-sdk/region-config-resolver": "3.775.0",
|
||||
"@aws-sdk/types": "3.775.0",
|
||||
"@aws-sdk/util-endpoints": "3.775.0",
|
||||
"@aws-sdk/util-endpoints": "3.782.0",
|
||||
"@aws-sdk/util-user-agent-browser": "3.775.0",
|
||||
"@aws-sdk/util-user-agent-node": "3.775.0",
|
||||
"@aws-sdk/util-user-agent-node": "3.782.0",
|
||||
"@smithy/config-resolver": "^4.1.0",
|
||||
"@smithy/core": "^3.2.0",
|
||||
"@smithy/fetch-http-handler": "^5.0.2",
|
||||
@@ -409,16 +409,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/client-s3": {
|
||||
"version": "3.779.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.779.0.tgz",
|
||||
"integrity": "sha512-Lagz+ersQaLNYkpOU9V12PYspT//lGvhPXlKU3OXDj3whDchdqUdtRKY8rmV+jli4KXe+udx/hj2yqrFRfKGvQ==",
|
||||
"version": "3.782.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.782.0.tgz",
|
||||
"integrity": "sha512-V6JR2JAGYQY7J8wk5un5n/ja2nfCUyyoRCF8Du8JL91NGI8i41Mdr/TzuOGwTgFl6RSXb/ge1K1jk30OH4MugQ==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@aws-crypto/sha1-browser": "5.2.0",
|
||||
"@aws-crypto/sha256-browser": "5.2.0",
|
||||
"@aws-crypto/sha256-js": "5.2.0",
|
||||
"@aws-sdk/core": "3.775.0",
|
||||
"@aws-sdk/credential-provider-node": "3.777.0",
|
||||
"@aws-sdk/credential-provider-node": "3.782.0",
|
||||
"@aws-sdk/middleware-bucket-endpoint": "3.775.0",
|
||||
"@aws-sdk/middleware-expect-continue": "3.775.0",
|
||||
"@aws-sdk/middleware-flexible-checksums": "3.775.0",
|
||||
@@ -428,13 +428,13 @@
|
||||
"@aws-sdk/middleware-recursion-detection": "3.775.0",
|
||||
"@aws-sdk/middleware-sdk-s3": "3.775.0",
|
||||
"@aws-sdk/middleware-ssec": "3.775.0",
|
||||
"@aws-sdk/middleware-user-agent": "3.775.0",
|
||||
"@aws-sdk/middleware-user-agent": "3.782.0",
|
||||
"@aws-sdk/region-config-resolver": "3.775.0",
|
||||
"@aws-sdk/signature-v4-multi-region": "3.775.0",
|
||||
"@aws-sdk/types": "3.775.0",
|
||||
"@aws-sdk/util-endpoints": "3.775.0",
|
||||
"@aws-sdk/util-endpoints": "3.782.0",
|
||||
"@aws-sdk/util-user-agent-browser": "3.775.0",
|
||||
"@aws-sdk/util-user-agent-node": "3.775.0",
|
||||
"@aws-sdk/util-user-agent-node": "3.782.0",
|
||||
"@aws-sdk/xml-builder": "3.775.0",
|
||||
"@smithy/config-resolver": "^4.1.0",
|
||||
"@smithy/core": "^3.2.0",
|
||||
@@ -476,24 +476,24 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/client-secrets-manager": {
|
||||
"version": "3.777.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/client-secrets-manager/-/client-secrets-manager-3.777.0.tgz",
|
||||
"integrity": "sha512-HqBGQPFUZMTOkQJB6JLv7Jopfz+cBP4spzjpBlZ/JeJShMAXw9To2mxi22jU5qGGWPGH5y4tVXnw4aVf2TOPhQ==",
|
||||
"version": "3.782.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/client-secrets-manager/-/client-secrets-manager-3.782.0.tgz",
|
||||
"integrity": "sha512-j2n8717Q7HeQgyXjdiUwuE0Pk80nOaDacWvEmmMr2w+DYXLvdXrOThbyy3jItt5XQw8mhaC8KZ4RfK6dqUlwGA==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@aws-crypto/sha256-browser": "5.2.0",
|
||||
"@aws-crypto/sha256-js": "5.2.0",
|
||||
"@aws-sdk/core": "3.775.0",
|
||||
"@aws-sdk/credential-provider-node": "3.777.0",
|
||||
"@aws-sdk/credential-provider-node": "3.782.0",
|
||||
"@aws-sdk/middleware-host-header": "3.775.0",
|
||||
"@aws-sdk/middleware-logger": "3.775.0",
|
||||
"@aws-sdk/middleware-recursion-detection": "3.775.0",
|
||||
"@aws-sdk/middleware-user-agent": "3.775.0",
|
||||
"@aws-sdk/middleware-user-agent": "3.782.0",
|
||||
"@aws-sdk/region-config-resolver": "3.775.0",
|
||||
"@aws-sdk/types": "3.775.0",
|
||||
"@aws-sdk/util-endpoints": "3.775.0",
|
||||
"@aws-sdk/util-endpoints": "3.782.0",
|
||||
"@aws-sdk/util-user-agent-browser": "3.775.0",
|
||||
"@aws-sdk/util-user-agent-node": "3.775.0",
|
||||
"@aws-sdk/util-user-agent-node": "3.782.0",
|
||||
"@smithy/config-resolver": "^4.1.0",
|
||||
"@smithy/core": "^3.2.0",
|
||||
"@smithy/fetch-http-handler": "^5.0.2",
|
||||
@@ -541,24 +541,24 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/client-ses": {
|
||||
"version": "3.777.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/client-ses/-/client-ses-3.777.0.tgz",
|
||||
"integrity": "sha512-COZ6Yb5qt/JLmWtJG1rGXhvTFnaWHt0X8r9j0uGFuSRhLcguItxYlOnIskYePz/NJ0u/OXYbad0uG1M4V5IJ/w==",
|
||||
"version": "3.782.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/client-ses/-/client-ses-3.782.0.tgz",
|
||||
"integrity": "sha512-ZfnbiRwW9CnmwIgKChPVT06PB0GOjVoUXu2SZHW/PZbgFuLokkqAbRScEVnwtBLF6NR1k5Msg74HH4HRimRDtA==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@aws-crypto/sha256-browser": "5.2.0",
|
||||
"@aws-crypto/sha256-js": "5.2.0",
|
||||
"@aws-sdk/core": "3.775.0",
|
||||
"@aws-sdk/credential-provider-node": "3.777.0",
|
||||
"@aws-sdk/credential-provider-node": "3.782.0",
|
||||
"@aws-sdk/middleware-host-header": "3.775.0",
|
||||
"@aws-sdk/middleware-logger": "3.775.0",
|
||||
"@aws-sdk/middleware-recursion-detection": "3.775.0",
|
||||
"@aws-sdk/middleware-user-agent": "3.775.0",
|
||||
"@aws-sdk/middleware-user-agent": "3.782.0",
|
||||
"@aws-sdk/region-config-resolver": "3.775.0",
|
||||
"@aws-sdk/types": "3.775.0",
|
||||
"@aws-sdk/util-endpoints": "3.775.0",
|
||||
"@aws-sdk/util-endpoints": "3.782.0",
|
||||
"@aws-sdk/util-user-agent-browser": "3.775.0",
|
||||
"@aws-sdk/util-user-agent-node": "3.775.0",
|
||||
"@aws-sdk/util-user-agent-node": "3.782.0",
|
||||
"@smithy/config-resolver": "^4.1.0",
|
||||
"@smithy/core": "^3.2.0",
|
||||
"@smithy/fetch-http-handler": "^5.0.2",
|
||||
@@ -592,9 +592,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/client-sso": {
|
||||
"version": "3.777.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.777.0.tgz",
|
||||
"integrity": "sha512-0+z6CiAYIQa7s6FJ+dpBYPi9zr9yY5jBg/4/FGcwYbmqWPXwL9Thdtr0FearYRZgKl7bhL3m3dILCCfWqr3teQ==",
|
||||
"version": "3.782.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.782.0.tgz",
|
||||
"integrity": "sha512-5GlJBejo8wqMpSSEKb45WE82YxI2k73YuebjLH/eWDNQeE6VI5Bh9lA1YQ7xNkLLH8hIsb0pSfKVuwh0VEzVrg==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@aws-crypto/sha256-browser": "5.2.0",
|
||||
@@ -603,12 +603,12 @@
|
||||
"@aws-sdk/middleware-host-header": "3.775.0",
|
||||
"@aws-sdk/middleware-logger": "3.775.0",
|
||||
"@aws-sdk/middleware-recursion-detection": "3.775.0",
|
||||
"@aws-sdk/middleware-user-agent": "3.775.0",
|
||||
"@aws-sdk/middleware-user-agent": "3.782.0",
|
||||
"@aws-sdk/region-config-resolver": "3.775.0",
|
||||
"@aws-sdk/types": "3.775.0",
|
||||
"@aws-sdk/util-endpoints": "3.775.0",
|
||||
"@aws-sdk/util-endpoints": "3.782.0",
|
||||
"@aws-sdk/util-user-agent-browser": "3.775.0",
|
||||
"@aws-sdk/util-user-agent-node": "3.775.0",
|
||||
"@aws-sdk/util-user-agent-node": "3.782.0",
|
||||
"@smithy/config-resolver": "^4.1.0",
|
||||
"@smithy/core": "^3.2.0",
|
||||
"@smithy/fetch-http-handler": "^5.0.2",
|
||||
@@ -700,18 +700,18 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/credential-provider-ini": {
|
||||
"version": "3.777.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.777.0.tgz",
|
||||
"integrity": "sha512-1X9mCuM9JSQPmQ+D2TODt4THy6aJWCNiURkmKmTIPRdno7EIKgAqrr/LLN++K5mBf54DZVKpqcJutXU2jwo01A==",
|
||||
"version": "3.782.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.782.0.tgz",
|
||||
"integrity": "sha512-wd4KdRy2YjLsE4Y7pz00470Iip06GlRHkG4dyLW7/hFMzEO2o7ixswCWp6J2VGZVAX64acknlv2Q0z02ebjmhw==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@aws-sdk/core": "3.775.0",
|
||||
"@aws-sdk/credential-provider-env": "3.775.0",
|
||||
"@aws-sdk/credential-provider-http": "3.775.0",
|
||||
"@aws-sdk/credential-provider-process": "3.775.0",
|
||||
"@aws-sdk/credential-provider-sso": "3.777.0",
|
||||
"@aws-sdk/credential-provider-web-identity": "3.777.0",
|
||||
"@aws-sdk/nested-clients": "3.777.0",
|
||||
"@aws-sdk/credential-provider-sso": "3.782.0",
|
||||
"@aws-sdk/credential-provider-web-identity": "3.782.0",
|
||||
"@aws-sdk/nested-clients": "3.782.0",
|
||||
"@aws-sdk/types": "3.775.0",
|
||||
"@smithy/credential-provider-imds": "^4.0.2",
|
||||
"@smithy/property-provider": "^4.0.2",
|
||||
@@ -724,17 +724,17 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/credential-provider-node": {
|
||||
"version": "3.777.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.777.0.tgz",
|
||||
"integrity": "sha512-ZD66ywx1Q0KyUSuBXZIQzBe3Q7MzX8lNwsrCU43H3Fww+Y+HB3Ncws9grhSdNhKQNeGmZ+MgKybuZYaaeLwJEQ==",
|
||||
"version": "3.782.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.782.0.tgz",
|
||||
"integrity": "sha512-HZiAF+TCEyKjju9dgysjiPIWgt/+VerGaeEp18mvKLNfgKz1d+/82A2USEpNKTze7v3cMFASx3CvL8yYyF7mJw==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@aws-sdk/credential-provider-env": "3.775.0",
|
||||
"@aws-sdk/credential-provider-http": "3.775.0",
|
||||
"@aws-sdk/credential-provider-ini": "3.777.0",
|
||||
"@aws-sdk/credential-provider-ini": "3.782.0",
|
||||
"@aws-sdk/credential-provider-process": "3.775.0",
|
||||
"@aws-sdk/credential-provider-sso": "3.777.0",
|
||||
"@aws-sdk/credential-provider-web-identity": "3.777.0",
|
||||
"@aws-sdk/credential-provider-sso": "3.782.0",
|
||||
"@aws-sdk/credential-provider-web-identity": "3.782.0",
|
||||
"@aws-sdk/types": "3.775.0",
|
||||
"@smithy/credential-provider-imds": "^4.0.2",
|
||||
"@smithy/property-provider": "^4.0.2",
|
||||
@@ -764,14 +764,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/credential-provider-sso": {
|
||||
"version": "3.777.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.777.0.tgz",
|
||||
"integrity": "sha512-9mPz7vk9uE4PBVprfINv4tlTkyq1OonNevx2DiXC1LY4mCUCNN3RdBwAY0BTLzj0uyc3k5KxFFNbn3/8ZDQP7w==",
|
||||
"version": "3.782.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.782.0.tgz",
|
||||
"integrity": "sha512-1y1ucxTtTIGDSNSNxriQY8msinilhe9gGvQpUDYW9gboyC7WQJPDw66imy258V6osdtdi+xoHzVCbCz3WhosMQ==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-sso": "3.777.0",
|
||||
"@aws-sdk/client-sso": "3.782.0",
|
||||
"@aws-sdk/core": "3.775.0",
|
||||
"@aws-sdk/token-providers": "3.777.0",
|
||||
"@aws-sdk/token-providers": "3.782.0",
|
||||
"@aws-sdk/types": "3.775.0",
|
||||
"@smithy/property-provider": "^4.0.2",
|
||||
"@smithy/shared-ini-file-loader": "^4.0.2",
|
||||
@@ -783,13 +783,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/credential-provider-web-identity": {
|
||||
"version": "3.777.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.777.0.tgz",
|
||||
"integrity": "sha512-uGCqr47fnthkqwq5luNl2dksgcpHHjSXz2jUra7TXtFOpqvnhOW8qXjoa1ivlkq8qhqlaZwCzPdbcN0lXpmLzQ==",
|
||||
"version": "3.782.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.782.0.tgz",
|
||||
"integrity": "sha512-xCna0opVPaueEbJoclj5C6OpDNi0Gynj+4d7tnuXGgQhTHPyAz8ZyClkVqpi5qvHTgxROdUEDxWqEO5jqRHZHQ==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@aws-sdk/core": "3.775.0",
|
||||
"@aws-sdk/nested-clients": "3.777.0",
|
||||
"@aws-sdk/nested-clients": "3.782.0",
|
||||
"@aws-sdk/types": "3.775.0",
|
||||
"@smithy/property-provider": "^4.0.2",
|
||||
"@smithy/types": "^4.2.0",
|
||||
@@ -800,9 +800,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/lib-storage": {
|
||||
"version": "3.779.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/lib-storage/-/lib-storage-3.779.0.tgz",
|
||||
"integrity": "sha512-AZfykrCgfnhlb5d5uyThHsqIwt41PYgnUTMyDuk4hbuKbiY8pfOiPdg8BYsC59iD2T4Iw9NujYhWUD+l8zNKcw==",
|
||||
"version": "3.782.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/lib-storage/-/lib-storage-3.782.0.tgz",
|
||||
"integrity": "sha512-UQYnIzpBReLko2XhDgG/rWpoHTWv4/zqUNl4XJXZRo9akLzrxGKtPrp5nJ4OLUkH3tIm1cvmI3XlSjHUW/OxWw==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@smithy/abort-controller": "^4.0.2",
|
||||
@@ -817,7 +817,7 @@
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@aws-sdk/client-s3": "^3.779.0"
|
||||
"@aws-sdk/client-s3": "^3.782.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/lib-storage/node_modules/buffer": {
|
||||
@@ -985,14 +985,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/middleware-user-agent": {
|
||||
"version": "3.775.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.775.0.tgz",
|
||||
"integrity": "sha512-7Lffpr1ptOEDE1ZYH1T78pheEY1YmeXWBfFt/amZ6AGsKSLG+JPXvof3ltporTGR2bhH/eJPo7UHCglIuXfzYg==",
|
||||
"version": "3.782.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.782.0.tgz",
|
||||
"integrity": "sha512-i32H2R6IItX+bQ2p4+v2gGO2jA80jQoJO2m1xjU9rYWQW3+ErWy4I5YIuQHTBfb6hSdAHbaRfqPDgbv9J2rjEg==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@aws-sdk/core": "3.775.0",
|
||||
"@aws-sdk/types": "3.775.0",
|
||||
"@aws-sdk/util-endpoints": "3.775.0",
|
||||
"@aws-sdk/util-endpoints": "3.782.0",
|
||||
"@smithy/core": "^3.2.0",
|
||||
"@smithy/protocol-http": "^5.1.0",
|
||||
"@smithy/types": "^4.2.0",
|
||||
@@ -1003,9 +1003,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/nested-clients": {
|
||||
"version": "3.777.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.777.0.tgz",
|
||||
"integrity": "sha512-bmmVRsCjuYlStYPt06hr+f8iEyWg7+AklKCA8ZLDEJujXhXIowgUIqXmqpTkXwkVvDQ9tzU7hxaONjyaQCGybA==",
|
||||
"version": "3.782.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.782.0.tgz",
|
||||
"integrity": "sha512-QOYC8q7luzHFXrP0xYAqBctoPkynjfV0r9dqntFu4/IWMTyC1vlo1UTxFAjIPyclYw92XJyEkVCVg9v/nQnsUA==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@aws-crypto/sha256-browser": "5.2.0",
|
||||
@@ -1014,12 +1014,12 @@
|
||||
"@aws-sdk/middleware-host-header": "3.775.0",
|
||||
"@aws-sdk/middleware-logger": "3.775.0",
|
||||
"@aws-sdk/middleware-recursion-detection": "3.775.0",
|
||||
"@aws-sdk/middleware-user-agent": "3.775.0",
|
||||
"@aws-sdk/middleware-user-agent": "3.782.0",
|
||||
"@aws-sdk/region-config-resolver": "3.775.0",
|
||||
"@aws-sdk/types": "3.775.0",
|
||||
"@aws-sdk/util-endpoints": "3.775.0",
|
||||
"@aws-sdk/util-endpoints": "3.782.0",
|
||||
"@aws-sdk/util-user-agent-browser": "3.775.0",
|
||||
"@aws-sdk/util-user-agent-node": "3.775.0",
|
||||
"@aws-sdk/util-user-agent-node": "3.782.0",
|
||||
"@smithy/config-resolver": "^4.1.0",
|
||||
"@smithy/core": "^3.2.0",
|
||||
"@smithy/fetch-http-handler": "^5.0.2",
|
||||
@@ -1069,9 +1069,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/s3-request-presigner": {
|
||||
"version": "3.779.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/s3-request-presigner/-/s3-request-presigner-3.779.0.tgz",
|
||||
"integrity": "sha512-L3mGSh6/9gf3FBVrQziCkuLbaRJMeNbLr6tg9ZSymJcDRzRqAiCWnHrenAavTnAAnm+Lu62Fg/A4g3T+YT+gEg==",
|
||||
"version": "3.782.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/s3-request-presigner/-/s3-request-presigner-3.782.0.tgz",
|
||||
"integrity": "sha512-Er8hdjc9zkxTh15MjdnMYggtUrGknDiuD1FwdW035kn/kwWop587G9rnRa1crhmyKRjLMn0Ki3fsyFUm/943XA==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@aws-sdk/signature-v4-multi-region": "3.775.0",
|
||||
@@ -1105,12 +1105,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/token-providers": {
|
||||
"version": "3.777.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.777.0.tgz",
|
||||
"integrity": "sha512-Yc2cDONsHOa4dTSGOev6Ng2QgTKQUEjaUnsyKd13pc/nLLz/WLqHiQ/o7PcnKERJxXGs1g1C6l3sNXiX+kbnFQ==",
|
||||
"version": "3.782.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.782.0.tgz",
|
||||
"integrity": "sha512-4tPuk/3+THPrzKaXW4jE2R67UyGwHLFizZ47pcjJWbhb78IIJAy94vbeqEQ+veS84KF5TXcU7g5jGTXC0D70Wg==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@aws-sdk/nested-clients": "3.777.0",
|
||||
"@aws-sdk/nested-clients": "3.782.0",
|
||||
"@aws-sdk/types": "3.775.0",
|
||||
"@smithy/property-provider": "^4.0.2",
|
||||
"@smithy/shared-ini-file-loader": "^4.0.2",
|
||||
@@ -1147,9 +1147,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/util-endpoints": {
|
||||
"version": "3.775.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.775.0.tgz",
|
||||
"integrity": "sha512-yjWmUgZC9tUxAo8Uaplqmq0eUh0zrbZJdwxGRKdYxfm4RG6fMw1tj52+KkatH7o+mNZvg1GDcVp/INktxonJLw==",
|
||||
"version": "3.782.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.782.0.tgz",
|
||||
"integrity": "sha512-/RJOAO7o7HI6lEa4ASbFFLHGU9iPK876BhsVfnl54MvApPVYWQ9sHO0anOUim2S5lQTwd/6ghuH3rFYSq/+rdw==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@aws-sdk/types": "3.775.0",
|
||||
@@ -1201,12 +1201,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/util-user-agent-node": {
|
||||
"version": "3.775.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.775.0.tgz",
|
||||
"integrity": "sha512-N9yhTevbizTOMo3drH7Eoy6OkJ3iVPxhV7dwb6CMAObbLneS36CSfA6xQXupmHWcRvZPTz8rd1JGG3HzFOau+g==",
|
||||
"version": "3.782.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.782.0.tgz",
|
||||
"integrity": "sha512-dMFkUBgh2Bxuw8fYZQoH/u3H4afQ12VSkzEi//qFiDTwbKYq+u+RYjc8GLDM6JSK1BShMu5AVR7HD4ap1TYUnA==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@aws-sdk/middleware-user-agent": "3.775.0",
|
||||
"@aws-sdk/middleware-user-agent": "3.782.0",
|
||||
"@aws-sdk/types": "3.775.0",
|
||||
"@smithy/node-config-provider": "^4.0.2",
|
||||
"@smithy/types": "^4.2.0",
|
||||
@@ -1953,9 +1953,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@eslint/config-array": {
|
||||
"version": "0.19.2",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.2.tgz",
|
||||
"integrity": "sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w==",
|
||||
"version": "0.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.20.0.tgz",
|
||||
"integrity": "sha512-fxlS1kkIjx8+vy2SjuCB94q3htSNrufYTXubwiBFeaQHbH6Ipi43gFJq2zCMt6PHhImH3Xmr0NksKDvchWlpQQ==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
@@ -2028,9 +2028,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@eslint/js": {
|
||||
"version": "9.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.23.0.tgz",
|
||||
"integrity": "sha512-35MJ8vCPU0ZMxo7zfev2pypqTwWTofFZO6m4KAtdoFhRpLJUpHTZZ+KB3C7Hb1d7bULYwO4lJXGCi5Se+8OMbw==",
|
||||
"version": "9.24.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.24.0.tgz",
|
||||
"integrity": "sha512-uIY/y3z0uvOGX8cp1C2fiC4+ZmBhp6yZWkojtHL1YEMnRt1Y63HB9TM17proGEmeG7HeUY+UP36F0aknKYTpYA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
@@ -5139,9 +5139,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/bullmq": {
|
||||
"version": "5.45.2",
|
||||
"resolved": "https://registry.npmjs.org/bullmq/-/bullmq-5.45.2.tgz",
|
||||
"integrity": "sha512-wHZfcD4z4aLolxREmwNNDSbfh7USeq2e3yu5W2VGkzHMUcrH0fzZuRuCMsjD0XKS9ViK1U854oM9yWR6ftPeDA==",
|
||||
"version": "5.48.0",
|
||||
"resolved": "https://registry.npmjs.org/bullmq/-/bullmq-5.48.0.tgz",
|
||||
"integrity": "sha512-fUtQrkefr6VAYYPjLXKHR6scWhwGI/0ok1wfAEPyhq8aRnJK8PJGEXUSssTEzDShadgLLXCmIOsVyhbs5/XWWg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"cron-parser": "^4.9.0",
|
||||
@@ -5215,9 +5215,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/call-bind-apply-helpers": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz",
|
||||
"integrity": "sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==",
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
|
||||
"integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"es-errors": "^1.3.0",
|
||||
@@ -5228,13 +5228,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/call-bound": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz",
|
||||
"integrity": "sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==",
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
|
||||
"integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bind-apply-helpers": "^1.0.1",
|
||||
"get-intrinsic": "^1.2.6"
|
||||
"call-bind-apply-helpers": "^1.0.2",
|
||||
"get-intrinsic": "^1.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
@@ -6626,9 +6626,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"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==",
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
|
||||
"integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"es-errors": "^1.3.0"
|
||||
@@ -6762,19 +6762,19 @@
|
||||
}
|
||||
},
|
||||
"node_modules/eslint": {
|
||||
"version": "9.23.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.23.0.tgz",
|
||||
"integrity": "sha512-jV7AbNoFPAY1EkFYpLq5bslU9NLNO8xnEeQXwErNibVryjk67wHVmddTBilc5srIttJDBrB0eMHKZBFbSIABCw==",
|
||||
"version": "9.24.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.24.0.tgz",
|
||||
"integrity": "sha512-eh/jxIEJyZrvbWRe4XuVclLPDYSYYYgLy5zXGGxD6j8zjSAxFEzI2fL/8xNq6O2yKqVt+eF2YhV+hxjV6UKXwQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@eslint-community/eslint-utils": "^4.2.0",
|
||||
"@eslint-community/regexpp": "^4.12.1",
|
||||
"@eslint/config-array": "^0.19.2",
|
||||
"@eslint/config-array": "^0.20.0",
|
||||
"@eslint/config-helpers": "^0.2.0",
|
||||
"@eslint/core": "^0.12.0",
|
||||
"@eslint/eslintrc": "^3.3.1",
|
||||
"@eslint/js": "9.23.0",
|
||||
"@eslint/js": "9.24.0",
|
||||
"@eslint/plugin-kit": "^0.2.7",
|
||||
"@humanfs/node": "^0.16.6",
|
||||
"@humanwhocodes/module-importer": "^1.0.1",
|
||||
@@ -6823,9 +6823,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-react": {
|
||||
"version": "7.37.4",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.4.tgz",
|
||||
"integrity": "sha512-BGP0jRmfYyvOyvMoRX/uoUeW+GqNj9y16bPQzqAHf3AYII/tDs+jMN0dBVkl88/OZwNGwrVFxE7riHsXVfy/LQ==",
|
||||
"version": "7.37.5",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz",
|
||||
"integrity": "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -6839,7 +6839,7 @@
|
||||
"hasown": "^2.0.2",
|
||||
"jsx-ast-utils": "^2.4.1 || ^3.0.0",
|
||||
"minimatch": "^3.1.2",
|
||||
"object.entries": "^1.1.8",
|
||||
"object.entries": "^1.1.9",
|
||||
"object.fromentries": "^2.0.8",
|
||||
"object.values": "^1.2.1",
|
||||
"prop-types": "^15.8.1",
|
||||
@@ -7653,17 +7653,17 @@
|
||||
}
|
||||
},
|
||||
"node_modules/get-intrinsic": {
|
||||
"version": "1.2.7",
|
||||
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.7.tgz",
|
||||
"integrity": "sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==",
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
|
||||
"integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bind-apply-helpers": "^1.0.1",
|
||||
"call-bind-apply-helpers": "^1.0.2",
|
||||
"es-define-property": "^1.0.1",
|
||||
"es-errors": "^1.3.0",
|
||||
"es-object-atoms": "^1.0.0",
|
||||
"es-object-atoms": "^1.1.1",
|
||||
"function-bind": "^1.1.2",
|
||||
"get-proto": "^1.0.0",
|
||||
"get-proto": "^1.0.1",
|
||||
"gopd": "^1.2.0",
|
||||
"has-symbols": "^1.1.0",
|
||||
"hasown": "^2.0.2",
|
||||
@@ -9919,15 +9919,16 @@
|
||||
}
|
||||
},
|
||||
"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==",
|
||||
"version": "1.1.9",
|
||||
"resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.9.tgz",
|
||||
"integrity": "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bind": "^1.0.7",
|
||||
"call-bind": "^1.0.8",
|
||||
"call-bound": "^1.0.4",
|
||||
"define-properties": "^1.2.1",
|
||||
"es-object-atoms": "^1.0.0"
|
||||
"es-object-atoms": "^1.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
@@ -12315,9 +12316,9 @@
|
||||
"license": "Unlicense"
|
||||
},
|
||||
"node_modules/twilio": {
|
||||
"version": "5.5.1",
|
||||
"resolved": "https://registry.npmjs.org/twilio/-/twilio-5.5.1.tgz",
|
||||
"integrity": "sha512-b1gLd2eMsCSCHRerp3GQUedVlz0nCTt5FbyPxDPmMvk5cm6eIPk4ZTp5JNpgucARZgpCB2uUACJbdcidEHAUBA==",
|
||||
"version": "5.5.2",
|
||||
"resolved": "https://registry.npmjs.org/twilio/-/twilio-5.5.2.tgz",
|
||||
"integrity": "sha512-yrRh6immcL5xEVX7VmHsl3vU01x/fmqxf38kvxMrrtvEtAkYARYOPor9lt5T7964zC7l31k5sTrnLJmd2jjeOA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"axios": "^1.7.8",
|
||||
|
||||
29
package.json
29
package.json
@@ -12,17 +12,18 @@
|
||||
"start": "node server.js",
|
||||
"makeitpretty": "prettier --write \"**/*.{css,js,json,jsx,scss}\"",
|
||||
"test:unit": "vitest run",
|
||||
"test:watch": "vitest"
|
||||
"test:watch": "vitest",
|
||||
"job-totals-fixtures:local": "docker exec node-app /usr/bin/node /app/download-job-totals-fixtures.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-cloudwatch-logs": "^3.777.0",
|
||||
"@aws-sdk/client-elasticache": "^3.777.0",
|
||||
"@aws-sdk/client-s3": "^3.779.0",
|
||||
"@aws-sdk/client-secrets-manager": "^3.777.0",
|
||||
"@aws-sdk/client-ses": "^3.777.0",
|
||||
"@aws-sdk/credential-provider-node": "^3.777.0",
|
||||
"@aws-sdk/lib-storage": "^3.779.0",
|
||||
"@aws-sdk/s3-request-presigner": "^3.779.0",
|
||||
"@aws-sdk/client-cloudwatch-logs": "^3.782.0",
|
||||
"@aws-sdk/client-elasticache": "^3.782.0",
|
||||
"@aws-sdk/client-s3": "^3.782.0",
|
||||
"@aws-sdk/client-secrets-manager": "^3.782.0",
|
||||
"@aws-sdk/client-ses": "^3.782.0",
|
||||
"@aws-sdk/credential-provider-node": "^3.782.0",
|
||||
"@aws-sdk/lib-storage": "^3.782.0",
|
||||
"@aws-sdk/s3-request-presigner": "^3.782.0",
|
||||
"@opensearch-project/opensearch": "^2.13.0",
|
||||
"@socket.io/admin-ui": "^0.5.1",
|
||||
"@socket.io/redis-adapter": "^8.3.0",
|
||||
@@ -32,7 +33,7 @@
|
||||
"bee-queue": "^1.7.1",
|
||||
"better-queue": "^3.8.12",
|
||||
"bluebird": "^3.7.2",
|
||||
"bullmq": "^5.45.2",
|
||||
"bullmq": "^5.48.0",
|
||||
"chart.js": "^4.4.8",
|
||||
"cloudinary": "^2.6.0",
|
||||
"compression": "^1.8.0",
|
||||
@@ -68,7 +69,7 @@
|
||||
"socket.io": "^4.8.1",
|
||||
"socket.io-adapter": "^2.5.5",
|
||||
"ssh2-sftp-client": "^11.0.0",
|
||||
"twilio": "^5.5.1",
|
||||
"twilio": "^5.5.2",
|
||||
"uuid": "^11.1.0",
|
||||
"winston": "^3.17.0",
|
||||
"winston-cloudwatch": "^6.3.0",
|
||||
@@ -76,10 +77,10 @@
|
||||
"xmlbuilder2": "^3.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.23.0",
|
||||
"@eslint/js": "^9.24.0",
|
||||
"@trivago/prettier-plugin-sort-imports": "^5.2.2",
|
||||
"eslint": "^9.23.0",
|
||||
"eslint-plugin-react": "^7.37.4",
|
||||
"eslint": "^9.24.0",
|
||||
"eslint-plugin-react": "^7.37.5",
|
||||
"globals": "^15.15.0",
|
||||
"mock-require": "^3.0.3",
|
||||
"p-limit": "^3.1.0",
|
||||
|
||||
@@ -16,7 +16,6 @@ const cors = require("cors");
|
||||
const http = require("http");
|
||||
const Redis = require("ioredis");
|
||||
const express = require("express");
|
||||
const bodyParser = require("body-parser");
|
||||
const compression = require("compression");
|
||||
const cookieParser = require("cookie-parser");
|
||||
const { Server } = require("socket.io");
|
||||
|
||||
@@ -55,7 +55,12 @@ exports.default = async (req, res) => {
|
||||
const csv = converter.json2csv(shopList, { emptyFieldValue: "" });
|
||||
emailer
|
||||
.sendTaskEmail({
|
||||
to: ["patrick.fic@convenient-brands.com", "bradley.rhoades@convenient-brands.com", "jrome@rometech.com"],
|
||||
to: [
|
||||
"patrick.fic@convenient-brands.com",
|
||||
"bradley.rhoades@convenient-brands.com",
|
||||
"jrome@rometech.com",
|
||||
"ivana@imexsystems.ca"
|
||||
],
|
||||
subject: `RO Usage Report - ${moment().format("MM/DD/YYYY")}`,
|
||||
text: `
|
||||
Usage Report for ${moment().format("MM/DD/YYYY")} for Rome Online Customers.
|
||||
|
||||
@@ -2841,6 +2841,15 @@ query GET_JOBID_BY_MERCHANTID_RONUMBER($merchantID: String!, $roNumber: String!)
|
||||
bodyshop {
|
||||
id
|
||||
intellipay_config
|
||||
email
|
||||
}
|
||||
}
|
||||
}`;
|
||||
|
||||
exports.GET_BODYSHOP_BY_MERCHANT_ID = `
|
||||
query GET_BODYSHOP_BY_MERCHANTID($merchantID: String!) {
|
||||
bodyshops(where: {intellipay_merchant_id: {_eq: $merchantID}}) {
|
||||
id
|
||||
email
|
||||
}
|
||||
}`;
|
||||
|
||||
@@ -2,8 +2,11 @@ const handlePaymentValidationError = require("./handlePaymentValidationError");
|
||||
const {
|
||||
GET_JOBID_BY_MERCHANTID_RONUMBER,
|
||||
INSERT_PAYMENT_RESPONSE,
|
||||
INSERT_NEW_PAYMENT
|
||||
INSERT_NEW_PAYMENT,
|
||||
GET_BODYSHOP_BY_MERCHANT_ID
|
||||
} = require("../../graphql-client/queries");
|
||||
|
||||
const { sendTaskEmail } = require("../../email/sendemail");
|
||||
const getPaymentType = require("./getPaymentType");
|
||||
const moment = require("moment");
|
||||
|
||||
@@ -36,7 +39,34 @@ const handleInvoiceBasedPayment = async (values, logger, logMeta, res) => {
|
||||
});
|
||||
|
||||
if (!result?.jobs?.length) {
|
||||
return handlePaymentValidationError(res, logger, "intellipay-postback-job-not-found", "Job not found", logMeta);
|
||||
// Fetch bodyshop data
|
||||
const bodyshop = await gqlClient.request(GET_BODYSHOP_BY_MERCHANT_ID, {
|
||||
merchantID: values.merchantid
|
||||
});
|
||||
|
||||
if (bodyshop?.bodyshops?.[0]) {
|
||||
// Note: changed bodyshops to bodyshop to match query name
|
||||
const email = bodyshop.bodyshops[0].email;
|
||||
|
||||
await sendTaskEmail({
|
||||
to: email,
|
||||
subject: `Failed to Insert Payment`,
|
||||
text: `The system has attempted to insert a payment that was generated by your merchant terminal but could not find an associated invoice. Transaction details are below. Please input this payment to your system manually.\n\n${Object.keys(
|
||||
values
|
||||
)
|
||||
.map((key) => `${key}: ${values[key]}`)
|
||||
.join("\n")}`
|
||||
});
|
||||
}
|
||||
|
||||
return handlePaymentValidationError(
|
||||
res,
|
||||
logger,
|
||||
"intellipay-postback-job-not-found",
|
||||
"Job not found",
|
||||
logMeta,
|
||||
200
|
||||
);
|
||||
}
|
||||
|
||||
const job = result.jobs[0];
|
||||
|
||||
@@ -5,14 +5,15 @@
|
||||
* @param logCode
|
||||
* @param message
|
||||
* @param logMeta
|
||||
* @param returnCode
|
||||
* @returns {*}
|
||||
*/
|
||||
const handlePaymentValidationError = (res, logger, logCode, message, logMeta) => {
|
||||
const handlePaymentValidationError = (res, logger, logCode, message, logMeta, returnCode) => {
|
||||
logger.log(logCode, "ERROR", "api", null, {
|
||||
message,
|
||||
...logMeta
|
||||
});
|
||||
return res.status(400).send(`Bad Request: ${message}`);
|
||||
return res.status(returnCode || 400).send(`Bad Request: ${message}`);
|
||||
};
|
||||
|
||||
module.exports = handlePaymentValidationError;
|
||||
|
||||
@@ -96,7 +96,8 @@ describe("handleInvoiceBasedPayment", () => {
|
||||
mockLogger,
|
||||
"intellipay-postback-job-not-found",
|
||||
"Job not found",
|
||||
logMeta
|
||||
logMeta,
|
||||
200
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
const Dinero = require("dinero.js");
|
||||
const queries = require("../graphql-client/queries");
|
||||
// const adminClient = require("../graphql-client/graphql-client").client;
|
||||
// const _ = require("lodash");
|
||||
const logger = require("../utils/logger");
|
||||
const InstanceMgr = require("../utils/instanceMgr").default;
|
||||
|
||||
@@ -45,9 +43,11 @@ exports.totalsSsu = async function (req, res) {
|
||||
}
|
||||
});
|
||||
|
||||
if (result) {
|
||||
res.status(200).send();
|
||||
if (!result) {
|
||||
throw new Error("Failed to update job totals");
|
||||
}
|
||||
|
||||
res.status(200).send();
|
||||
} catch (error) {
|
||||
logger.log("job-totals-ssu-USA-error", "ERROR", req?.user?.email, id, {
|
||||
jobid: id,
|
||||
@@ -58,7 +58,7 @@ exports.totalsSsu = async function (req, res) {
|
||||
}
|
||||
};
|
||||
|
||||
//IMPORTANT*** These two functions MUST be mirrrored.
|
||||
//IMPORTANT*** These two functions MUST be mirrored.
|
||||
async function TotalsServerSide(req, res) {
|
||||
const { job, client } = req.body;
|
||||
await AtsAdjustmentsIfRequired({ job: job, client: client, user: req?.user });
|
||||
@@ -133,6 +133,9 @@ async function TotalsServerSide(req, res) {
|
||||
}
|
||||
}
|
||||
|
||||
// Exported for testing purposes.
|
||||
exports.TotalsServerSide = TotalsServerSide;
|
||||
|
||||
async function Totals(req, res) {
|
||||
const { job, id } = req.body;
|
||||
|
||||
|
||||
139
server/job/job-totals-recorder.js
Normal file
139
server/job/job-totals-recorder.js
Normal file
@@ -0,0 +1,139 @@
|
||||
const logger = require("../utils/logger");
|
||||
const queries = require("../graphql-client/queries");
|
||||
const moment = require("moment");
|
||||
const { captureFixture } = require("./utils/seralizeHelper");
|
||||
const { TotalsServerSide: totalsServerSideCA } = require("./job-totals"); // Canadian version (imex)
|
||||
const { TotalsServerSide: totalsServerSideUS } = require("./job-totals-USA");
|
||||
const InstanceMgr = require("../utils/instanceMgr").default;
|
||||
const { uploadFileToS3 } = require("../utils/s3");
|
||||
|
||||
// requires two buckets be made per env, job-totals-test, job-totals-production, locally it will
|
||||
// use `job-totals` in the owncloud stack
|
||||
|
||||
/**
|
||||
* Returns the environment prefix based on NODE_ENV
|
||||
* @returns {string}
|
||||
*/
|
||||
const getEnvPrefix = () => {
|
||||
switch (process.env?.NODE_ENV) {
|
||||
case "test":
|
||||
return "test";
|
||||
case "production":
|
||||
return "production";
|
||||
default:
|
||||
return "test";
|
||||
}
|
||||
};
|
||||
|
||||
const envPrefix = getEnvPrefix();
|
||||
|
||||
const S3_BUCKET_NAME =
|
||||
process.env?.NODE_ENV === "development"
|
||||
? "imex-job-totals"
|
||||
: InstanceMgr({
|
||||
imex: `job-totals-${envPrefix}`,
|
||||
rome: `job-totals-${envPrefix}-rome`
|
||||
});
|
||||
|
||||
/**
|
||||
* Generates a unique S3 key for the job totals file
|
||||
* @param {string} jobId - The job ID
|
||||
* @returns {string} - S3 key with timestamp
|
||||
*/
|
||||
const generateS3Key = (jobId) => `${jobId}-${moment().toISOString()}.json`;
|
||||
|
||||
/**
|
||||
* Uploads job totals data to S3
|
||||
* @param {object} data - The data to upload
|
||||
* @param {string} jobId - The job ID
|
||||
* @param {object} userInfo - User information for logging
|
||||
* @returns {Promise<string>} - The S3 key
|
||||
*/
|
||||
const uploadJobTotalsToS3 = async (data, jobId, userInfo) => {
|
||||
const key = generateS3Key(jobId);
|
||||
|
||||
try {
|
||||
await uploadFileToS3({
|
||||
bucketName: S3_BUCKET_NAME,
|
||||
key: key,
|
||||
content: JSON.stringify(data, null, 2),
|
||||
contentType: "application/json"
|
||||
});
|
||||
|
||||
logger.log(`Job totals uploaded successfully to ${key}`, "info", userInfo.email, jobId);
|
||||
return key;
|
||||
} catch (error) {
|
||||
logger.log("Failed to upload job totals to S3", "error", userInfo.email, jobId, {
|
||||
error: error?.message,
|
||||
stack: error?.stack
|
||||
});
|
||||
throw error; // Re-throw for the main handler to catch
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Fetches job data using GraphQL
|
||||
* @param {object} client - GraphQL client
|
||||
* @param {string} token - Bearer token
|
||||
* @param {string} jobId - Job ID to fetch
|
||||
* @returns {Promise<object>} - Job data
|
||||
*/
|
||||
const fetchJobData = async (client, token, jobId) => {
|
||||
return client
|
||||
.setHeaders({ Authorization: token })
|
||||
.request(queries.GET_JOB_BY_PK, { id: jobId })
|
||||
.then((response) => response.jobs_by_pk);
|
||||
};
|
||||
|
||||
/**
|
||||
* This function is used to capture job totals json files.
|
||||
* @param {object} req - Express request
|
||||
* @param {object} res - Express response
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
const jobTotalsRecorder = async (req, res) => {
|
||||
const { id: jobId } = req.body;
|
||||
const bearerToken = req.BearerToken;
|
||||
const client = req.userGraphQLClient;
|
||||
const userEmail = req?.user?.email;
|
||||
|
||||
logger.log("Starting job totals recording", "debug", userEmail, jobId);
|
||||
|
||||
try {
|
||||
// Fetch job data
|
||||
const jobData = await fetchJobData(client, bearerToken, jobId);
|
||||
|
||||
// Get the appropriate totals function based on instance
|
||||
const totalsFunction = InstanceMgr({
|
||||
imex: totalsServerSideCA,
|
||||
rome: totalsServerSideUS
|
||||
});
|
||||
|
||||
// Calculate the totals
|
||||
const calculatedTotals = await totalsFunction({ body: { job: jobData, client }, req }, res, true);
|
||||
|
||||
// Prepare data for storage
|
||||
const dataToSave = captureFixture(jobData, calculatedTotals);
|
||||
|
||||
// Upload to S3
|
||||
await uploadJobTotalsToS3(dataToSave, jobId, { email: userEmail });
|
||||
|
||||
res.status(200).json({ success: true, message: "Job totals recorded successfully" });
|
||||
} catch (error) {
|
||||
logger.log("Failed to record job totals", "error", userEmail, jobId, {
|
||||
error: error?.message,
|
||||
stack: error?.stack
|
||||
});
|
||||
|
||||
// Avoid sending response if it's already been sent
|
||||
if (!res.headersSent) {
|
||||
res.status(503).json({
|
||||
success: false,
|
||||
message: "Error processing job totals",
|
||||
error: error.message
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = jobTotalsRecorder;
|
||||
@@ -30,6 +30,7 @@ exports.totalsSsu = async function (req, res) {
|
||||
id: id
|
||||
});
|
||||
|
||||
// Capture the output of TotalsServerSide
|
||||
const newTotals = await TotalsServerSide({ body: { job: job.jobs_by_pk, client: client } }, res, true);
|
||||
|
||||
const result = await client.setHeaders({ Authorization: BearerToken }).request(queries.UPDATE_JOB, {
|
||||
@@ -57,7 +58,7 @@ exports.totalsSsu = async function (req, res) {
|
||||
}
|
||||
};
|
||||
|
||||
//IMPORTANT*** These two functions MUST be mirrrored.
|
||||
//IMPORTANT*** These two functions MUST be mirrored.
|
||||
async function TotalsServerSide(req, res) {
|
||||
const { job, client } = req.body;
|
||||
await AtsAdjustmentsIfRequired({ job: job, client: client, user: req?.user });
|
||||
@@ -81,6 +82,9 @@ async function TotalsServerSide(req, res) {
|
||||
}
|
||||
}
|
||||
|
||||
// Exported for testing purposes
|
||||
exports.TotalsServerSide = TotalsServerSide;
|
||||
|
||||
async function Totals(req, res) {
|
||||
const { job, id } = req.body;
|
||||
|
||||
|
||||
72
server/job/test/job-totals.test.js
Normal file
72
server/job/test/job-totals.test.js
Normal file
@@ -0,0 +1,72 @@
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import { describe, it, expect } from "vitest";
|
||||
import { TotalsServerSide as TotalsServerSideCA } from "../job-totals"; // Canadian version (imex)
|
||||
import { TotalsServerSide as TotalsServerSideUS } from "../job-totals-USA";
|
||||
import { isFunction } from "lodash"; // US version (rome)
|
||||
|
||||
/**
|
||||
* This function is used to replace the values in the object with their toObject() representation.
|
||||
* @param key
|
||||
* @param value
|
||||
* @returns {*}
|
||||
*/
|
||||
const dineroReplacer = (key, value) => {
|
||||
if (isFunction(value)) {
|
||||
return value.toObject();
|
||||
}
|
||||
return value;
|
||||
};
|
||||
|
||||
/**
|
||||
* Normalizes the output of the TotalsServerSide function by converting
|
||||
* @param obj
|
||||
* @returns {any}
|
||||
*/
|
||||
const normalizeOutput = (obj) => {
|
||||
return JSON.parse(JSON.stringify(obj, dineroReplacer));
|
||||
};
|
||||
|
||||
/**
|
||||
* This test suite is designed to validate the functionality of the TotalsServerSide function
|
||||
*/
|
||||
describe("TotalsServerSide fixture tests", () => {
|
||||
const fixturesDir = path.join(__dirname, "fixtures", "job-totals");
|
||||
|
||||
const fixtureFiles = fs.readdirSync(fixturesDir).filter((f) => f.endsWith(".json"));
|
||||
|
||||
const dummyClient = {
|
||||
request: async () => {
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
const dummyRes = {
|
||||
status: () => ({ send: () => {} })
|
||||
};
|
||||
|
||||
fixtureFiles.forEach((file) => {
|
||||
it(`should produce matching output for fixture file ${file}`, async () => {
|
||||
const fixturePath = path.join(fixturesDir, file);
|
||||
const fixtureData = JSON.parse(fs.readFileSync(fixturePath, "utf8"));
|
||||
|
||||
const { environment, input, output: expectedOutput } = fixtureData;
|
||||
|
||||
const req = {
|
||||
body: {
|
||||
job: input,
|
||||
client: dummyClient
|
||||
},
|
||||
user: {}
|
||||
};
|
||||
|
||||
const computedOutput =
|
||||
environment === "us" ? await TotalsServerSideUS(req, dummyRes) : await TotalsServerSideCA(req, dummyRes);
|
||||
|
||||
const normalizedComputed = normalizeOutput(computedOutput);
|
||||
const normalizedExpected = normalizeOutput(expectedOutput);
|
||||
|
||||
expect(normalizedComputed).toEqual(normalizedExpected);
|
||||
});
|
||||
});
|
||||
});
|
||||
58
server/job/utils/seralizeHelper.js
Normal file
58
server/job/utils/seralizeHelper.js
Normal file
@@ -0,0 +1,58 @@
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const { default: InstanceMgr } = require("../../utils/instanceMgr");
|
||||
|
||||
const fixtureDir = path.join(__dirname, "..", "test", "fixtures", "job-totals");
|
||||
|
||||
/**
|
||||
* Custom serializer for Dinero.js objects.
|
||||
* @param key
|
||||
* @param value
|
||||
* @returns {*}
|
||||
*/
|
||||
const serializeDinero = (key, value) => {
|
||||
if (value && typeof value === "object" && typeof value.toObject === "function") {
|
||||
return value.toObject();
|
||||
}
|
||||
return value;
|
||||
};
|
||||
|
||||
/**
|
||||
* Capture a fixture for job totals.
|
||||
* @param inputData
|
||||
* @param outputData
|
||||
* @param saveLocally
|
||||
*/
|
||||
const captureFixture = (inputData, outputData, saveLocally) => {
|
||||
const fileName = `${inputData.id}.json`;
|
||||
const filePath = path.join(fixtureDir, fileName);
|
||||
|
||||
const dataToSave = {
|
||||
environment: InstanceMgr({
|
||||
imex: "ca",
|
||||
rome: "us"
|
||||
}),
|
||||
meta: {
|
||||
ro_number: inputData.ro_number,
|
||||
updated_at: inputData.updated_at
|
||||
},
|
||||
input: inputData,
|
||||
output: outputData
|
||||
};
|
||||
|
||||
// Save the file using our custom serializer.
|
||||
if (saveLocally) {
|
||||
if (!fs.existsSync(fixtureDir)) {
|
||||
fs.mkdirSync(fixtureDir, { recursive: true });
|
||||
}
|
||||
|
||||
fs.writeFileSync(filePath, JSON.stringify(dataToSave, serializeDinero, 2), "utf8");
|
||||
}
|
||||
|
||||
return dataToSave;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
captureFixture,
|
||||
serializeDinero
|
||||
};
|
||||
@@ -7,6 +7,7 @@ const eventAuthorizationMiddleware = require("../middleware/eventAuthorizationMI
|
||||
const validateFirebaseIdTokenMiddleware = require("../middleware/validateFirebaseIdTokenMiddleware");
|
||||
const { totals, statustransition, totalsSsu, costing, lifecycle, costingmulti, jobUpdated } = require("../job/job");
|
||||
const withUserGraphQLClientMiddleware = require("../middleware/withUserGraphQLClientMiddleware");
|
||||
const jobTotalsRecorder = require("../job/job-totals-recorder");
|
||||
|
||||
router.post("/totals", validateFirebaseIdTokenMiddleware, withUserGraphQLClientMiddleware, totals);
|
||||
router.post("/statustransition", eventAuthorizationMiddleware, statustransition);
|
||||
@@ -17,5 +18,6 @@ router.post("/costingmulti", validateFirebaseIdTokenMiddleware, withUserGraphQLC
|
||||
router.post("/partsscan", validateFirebaseIdTokenMiddleware, withUserGraphQLClientMiddleware, partsScan);
|
||||
router.post("/ppc", validateFirebaseIdTokenMiddleware, withUserGraphQLClientMiddleware, ppc.generatePpc);
|
||||
router.post("/job-updated", eventAuthorizationMiddleware, jobUpdated);
|
||||
router.post("/totals-recorder", validateFirebaseIdTokenMiddleware, withUserGraphQLClientMiddleware, jobTotalsRecorder);
|
||||
|
||||
module.exports = router;
|
||||
|
||||
Reference in New Issue
Block a user