Merged in feature/IO-1828-Front-End-Package-Updates (pull request #1155)

Feature/IO-1828 Front End Package Updates
This commit is contained in:
Dave Richer
2024-01-13 00:33:16 +00:00
85 changed files with 1134 additions and 995 deletions

View File

@@ -8872,13 +8872,13 @@
│ ├─ email: luis@luisrudge.net
│ ├─ path: /Users/pfic/Documents/Development/bodyshop/client/node_modules/postcss-flexbugs-fixes
│ └─ licenseFile: /Users/pfic/Documents/Development/bodyshop/client/node_modules/postcss-flexbugs-fixes/LICENSE
├─ postcss-focus-visible@4.0.0
├─ postcss-focus-open@4.0.0
│ ├─ licenses: CC0-1.0
│ ├─ repository: https://github.com/jonathantneal/postcss-focus-visible
│ ├─ repository: https://github.com/jonathantneal/postcss-focus-open
│ ├─ publisher: Jonathan Neal
│ ├─ email: jonathantneal@hotmail.com
│ ├─ path: /Users/pfic/Documents/Development/bodyshop/client/node_modules/postcss-focus-visible
│ └─ licenseFile: /Users/pfic/Documents/Development/bodyshop/client/node_modules/postcss-focus-visible/LICENSE.md
│ ├─ path: /Users/pfic/Documents/Development/bodyshop/client/node_modules/postcss-focus-open
│ └─ licenseFile: /Users/pfic/Documents/Development/bodyshop/client/node_modules/postcss-focus-open/LICENSE.md
├─ postcss-focus-within@3.0.0
│ ├─ licenses: CC0-1.0
│ ├─ repository: https://github.com/jonathantneal/postcss-focus-within

277
client/package-lock.json generated
View File

@@ -16,8 +16,8 @@
"@fingerprintjs/fingerprintjs": "^4.2.1",
"@jsreport/browser-client": "^3.1.0",
"@reduxjs/toolkit": "^2.0.1",
"@sentry/react": "^7.92.0",
"@sentry/tracing": "^7.92.0",
"@sentry/react": "^7.93.0",
"@sentry/tracing": "^7.93.0",
"@splitsoftware/splitio-react": "^1.10.2",
"@tanem/react-nprogress": "^5.0.51",
"antd": "^5.12.8",
@@ -56,13 +56,13 @@
"react-grid-gallery": "^1.0.0",
"react-grid-layout": "^1.3.4",
"react-i18next": "^14.0.0",
"react-icons": "^4.7.1",
"react-icons": "^5.0.1",
"react-image-lightbox": "^5.1.4",
"react-intersection-observer": "^9.5.3",
"react-number-format": "^5.1.4",
"react-redux": "^9.0.4",
"react-redux": "^9.1.0",
"react-resizable": "^3.0.5",
"react-router-dom": "^6.21.1",
"react-router-dom": "^6.21.2",
"react-scripts": "^5.0.1",
"react-sticky": "^6.0.3",
"react-sublime-video": "^0.2.5",
@@ -74,7 +74,7 @@
"redux-state-sync": "^3.1.4",
"reselect": "^5.1.0",
"sass": "^1.69.7",
"socket.io-client": "^4.7.3",
"socket.io-client": "^4.7.4",
"styled-components": "^6.1.8",
"subscriptions-transport-ws": "^0.11.0",
"terser-webpack-plugin": "^5.3.10",
@@ -4402,9 +4402,9 @@
}
},
"node_modules/@remix-run/router": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.14.1.tgz",
"integrity": "sha512-Qg4DMQsfPNAs88rb2xkdk03N3bjK4jgX5fR24eHCTR9q6PrhZQZ4UJBPzCHJkIpTRN1UKxx2DzjZmnC+7Lj0Ow==",
"version": "1.14.2",
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.14.2.tgz",
"integrity": "sha512-ACXpdMM9hmKZww21yEqWwiLws/UPLhNKvimN8RrYSqPSvB3ov7sLvAcfvaxePeLvccTQKGdkDIhLYApZVDFuKg==",
"engines": {
"node": ">=14.0.0"
}
@@ -4508,44 +4508,44 @@
"integrity": "sha512-2/U3GXA6YiPYQDLGwtGlnNgKYBSwCFIHf8Y9LUY5VATHdtbLlU0Y1R3QoBnT0aB4qv/BEiVVsj7LJXoQCgJ2vA=="
},
"node_modules/@sentry-internal/feedback": {
"version": "7.92.0",
"resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-7.92.0.tgz",
"integrity": "sha512-/jEALRtVqboxB9kcK2tag8QCO6XANTlGBb9RV3oeGXJe0DDNJXRq6wVZbfgztXJRrfgx4XVDcNt1pRVoGGG++g==",
"version": "7.93.0",
"resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-7.93.0.tgz",
"integrity": "sha512-4G7rMeQbYGfCHxEoFroABX+UREYc2BSbFqjLmLbIcWowSpgzcwweLLphWHKOciqK6f7DnNDK0jZzx3u7NrkWHw==",
"dependencies": {
"@sentry/core": "7.92.0",
"@sentry/types": "7.92.0",
"@sentry/utils": "7.92.0"
"@sentry/core": "7.93.0",
"@sentry/types": "7.93.0",
"@sentry/utils": "7.93.0"
},
"engines": {
"node": ">=12"
}
},
"node_modules/@sentry-internal/feedback/node_modules/@sentry/core": {
"version": "7.92.0",
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.92.0.tgz",
"integrity": "sha512-1Tly7YB2I1byI5xb0Cwrxs56Rhww+6mQ7m9P7rTmdC3/ijOzbEoohtYIUPwcooCEarpbEJe/tAayRx6BrH2UbQ==",
"version": "7.93.0",
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.93.0.tgz",
"integrity": "sha512-vZQSUiDn73n+yu2fEcH+Wpm4GbRmtxmnXnYCPgM6IjnXqkVm3awWAkzrheADblx3kmxrRiOlTXYHw9NTWs56fg==",
"dependencies": {
"@sentry/types": "7.92.0",
"@sentry/utils": "7.92.0"
"@sentry/types": "7.93.0",
"@sentry/utils": "7.93.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/@sentry-internal/feedback/node_modules/@sentry/types": {
"version": "7.92.0",
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.92.0.tgz",
"integrity": "sha512-APmSOuZuoRGpbPpPeYIbMSplPjiWNLZRQa73QiXuTflW4Tu/ItDlU8hOa2+A6JKVkJCuD2EN6yUrxDGSMyNXeg==",
"version": "7.93.0",
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.93.0.tgz",
"integrity": "sha512-UnzUccNakhFRA/esWBWP+0v7cjNg+RilFBQC03Mv9OEMaZaS29zSbcOGtRzuFOXXLBdbr44BWADqpz3VW0XaNw==",
"engines": {
"node": ">=8"
}
},
"node_modules/@sentry-internal/feedback/node_modules/@sentry/utils": {
"version": "7.92.0",
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.92.0.tgz",
"integrity": "sha512-3nEfrQ1z28b/2zgFGANPh5yMVtgwXmrasZxTvKbrAj+KWJpjrJHrIR84r9W277J44NMeZ5RhRW2uoDmuBslPnA==",
"version": "7.93.0",
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.93.0.tgz",
"integrity": "sha512-Iovj7tUnbgSkh/WrAaMrd5UuYjW7AzyzZlFDIUrwidsyIdUficjCG2OIxYzh76H6nYIx9SxewW0R54Q6XoB4uA==",
"dependencies": {
"@sentry/types": "7.92.0"
"@sentry/types": "7.93.0"
},
"engines": {
"node": ">=8"
@@ -4566,60 +4566,60 @@
}
},
"node_modules/@sentry/browser": {
"version": "7.92.0",
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-7.92.0.tgz",
"integrity": "sha512-loMr02/zQ38u8aQhYLtIBg0i5n3ps2e3GUXrt3CdsJQdkRYfa62gcrE7SzvoEpMVHTk7VOI4fWGht8cWw/1k3A==",
"version": "7.93.0",
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-7.93.0.tgz",
"integrity": "sha512-MtLTcQ7y3rfk+aIvnnwCfSJvYhTJnIJi+Mf6y/ap6SKObdlsKMbQoJLlRViglGLq+nKxHLAvU0fONiCEmKfV6A==",
"dependencies": {
"@sentry-internal/feedback": "7.92.0",
"@sentry-internal/tracing": "7.92.0",
"@sentry/core": "7.92.0",
"@sentry/replay": "7.92.0",
"@sentry/types": "7.92.0",
"@sentry/utils": "7.92.0"
"@sentry-internal/feedback": "7.93.0",
"@sentry-internal/tracing": "7.93.0",
"@sentry/core": "7.93.0",
"@sentry/replay": "7.93.0",
"@sentry/types": "7.93.0",
"@sentry/utils": "7.93.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/@sentry/browser/node_modules/@sentry-internal/tracing": {
"version": "7.92.0",
"resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.92.0.tgz",
"integrity": "sha512-ur55vPcUUUWFUX4eVLNP71ohswK7ZZpleNZw9Y1GfLqyI+0ILQUwjtzqItJrdClvVsdRZJMRmDV40Hp9Lbb9mA==",
"version": "7.93.0",
"resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.93.0.tgz",
"integrity": "sha512-DjuhmQNywPp+8fxC9dvhGrqgsUb6wI/HQp25lS2Re7VxL1swCasvpkg8EOYP4iBniVQ86QK0uITkOIRc5tdY1w==",
"dependencies": {
"@sentry/core": "7.92.0",
"@sentry/types": "7.92.0",
"@sentry/utils": "7.92.0"
"@sentry/core": "7.93.0",
"@sentry/types": "7.93.0",
"@sentry/utils": "7.93.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/@sentry/browser/node_modules/@sentry/core": {
"version": "7.92.0",
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.92.0.tgz",
"integrity": "sha512-1Tly7YB2I1byI5xb0Cwrxs56Rhww+6mQ7m9P7rTmdC3/ijOzbEoohtYIUPwcooCEarpbEJe/tAayRx6BrH2UbQ==",
"version": "7.93.0",
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.93.0.tgz",
"integrity": "sha512-vZQSUiDn73n+yu2fEcH+Wpm4GbRmtxmnXnYCPgM6IjnXqkVm3awWAkzrheADblx3kmxrRiOlTXYHw9NTWs56fg==",
"dependencies": {
"@sentry/types": "7.92.0",
"@sentry/utils": "7.92.0"
"@sentry/types": "7.93.0",
"@sentry/utils": "7.93.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/@sentry/browser/node_modules/@sentry/types": {
"version": "7.92.0",
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.92.0.tgz",
"integrity": "sha512-APmSOuZuoRGpbPpPeYIbMSplPjiWNLZRQa73QiXuTflW4Tu/ItDlU8hOa2+A6JKVkJCuD2EN6yUrxDGSMyNXeg==",
"version": "7.93.0",
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.93.0.tgz",
"integrity": "sha512-UnzUccNakhFRA/esWBWP+0v7cjNg+RilFBQC03Mv9OEMaZaS29zSbcOGtRzuFOXXLBdbr44BWADqpz3VW0XaNw==",
"engines": {
"node": ">=8"
}
},
"node_modules/@sentry/browser/node_modules/@sentry/utils": {
"version": "7.92.0",
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.92.0.tgz",
"integrity": "sha512-3nEfrQ1z28b/2zgFGANPh5yMVtgwXmrasZxTvKbrAj+KWJpjrJHrIR84r9W277J44NMeZ5RhRW2uoDmuBslPnA==",
"version": "7.93.0",
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.93.0.tgz",
"integrity": "sha512-Iovj7tUnbgSkh/WrAaMrd5UuYjW7AzyzZlFDIUrwidsyIdUficjCG2OIxYzh76H6nYIx9SxewW0R54Q6XoB4uA==",
"dependencies": {
"@sentry/types": "7.92.0"
"@sentry/types": "7.93.0"
},
"engines": {
"node": ">=8"
@@ -4817,13 +4817,14 @@
}
},
"node_modules/@sentry/react": {
"version": "7.92.0",
"resolved": "https://registry.npmjs.org/@sentry/react/-/react-7.92.0.tgz",
"integrity": "sha512-lTvrLuvxtGEZbkW6NHru03K6eyixKyBliwiLwO+k37FK7Ha8Bwat2m77weyizWCdQ6DKlVazJNppkNeAlACIvQ==",
"version": "7.93.0",
"resolved": "https://registry.npmjs.org/@sentry/react/-/react-7.93.0.tgz",
"integrity": "sha512-B0bzziV1lEyN7xd0orUPyJdpoK6CtcyodmQkfY0WsHLm/1d9xi95M05lObHnsMWO1js6c9B9d9kO8RlKFz947A==",
"dependencies": {
"@sentry/browser": "7.92.0",
"@sentry/types": "7.92.0",
"@sentry/utils": "7.92.0",
"@sentry/browser": "7.93.0",
"@sentry/core": "7.93.0",
"@sentry/types": "7.93.0",
"@sentry/utils": "7.93.0",
"hoist-non-react-statics": "^3.3.2"
},
"engines": {
@@ -4833,133 +4834,145 @@
"react": "15.x || 16.x || 17.x || 18.x"
}
},
"node_modules/@sentry/react/node_modules/@sentry/core": {
"version": "7.93.0",
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.93.0.tgz",
"integrity": "sha512-vZQSUiDn73n+yu2fEcH+Wpm4GbRmtxmnXnYCPgM6IjnXqkVm3awWAkzrheADblx3kmxrRiOlTXYHw9NTWs56fg==",
"dependencies": {
"@sentry/types": "7.93.0",
"@sentry/utils": "7.93.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/@sentry/react/node_modules/@sentry/types": {
"version": "7.92.0",
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.92.0.tgz",
"integrity": "sha512-APmSOuZuoRGpbPpPeYIbMSplPjiWNLZRQa73QiXuTflW4Tu/ItDlU8hOa2+A6JKVkJCuD2EN6yUrxDGSMyNXeg==",
"version": "7.93.0",
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.93.0.tgz",
"integrity": "sha512-UnzUccNakhFRA/esWBWP+0v7cjNg+RilFBQC03Mv9OEMaZaS29zSbcOGtRzuFOXXLBdbr44BWADqpz3VW0XaNw==",
"engines": {
"node": ">=8"
}
},
"node_modules/@sentry/react/node_modules/@sentry/utils": {
"version": "7.92.0",
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.92.0.tgz",
"integrity": "sha512-3nEfrQ1z28b/2zgFGANPh5yMVtgwXmrasZxTvKbrAj+KWJpjrJHrIR84r9W277J44NMeZ5RhRW2uoDmuBslPnA==",
"version": "7.93.0",
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.93.0.tgz",
"integrity": "sha512-Iovj7tUnbgSkh/WrAaMrd5UuYjW7AzyzZlFDIUrwidsyIdUficjCG2OIxYzh76H6nYIx9SxewW0R54Q6XoB4uA==",
"dependencies": {
"@sentry/types": "7.92.0"
"@sentry/types": "7.93.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/@sentry/replay": {
"version": "7.92.0",
"resolved": "https://registry.npmjs.org/@sentry/replay/-/replay-7.92.0.tgz",
"integrity": "sha512-G1t9Uvc9cR8VpNkElwvHIMGzykjIKikb10n0tfVd3e+rBPMCCjCPWOduwG6jZYxcvCjTpqmJh6NSLXxL/Mt4JA==",
"version": "7.93.0",
"resolved": "https://registry.npmjs.org/@sentry/replay/-/replay-7.93.0.tgz",
"integrity": "sha512-dMlLU8v+OkUeGCrPvTu5NriH7BGj3el4rGHWWAYicfJ2QXqTTq50vfasQBP1JeVNcFqnf1y653TdEIvo4RH4tw==",
"dependencies": {
"@sentry-internal/tracing": "7.92.0",
"@sentry/core": "7.92.0",
"@sentry/types": "7.92.0",
"@sentry/utils": "7.92.0"
"@sentry-internal/tracing": "7.93.0",
"@sentry/core": "7.93.0",
"@sentry/types": "7.93.0",
"@sentry/utils": "7.93.0"
},
"engines": {
"node": ">=12"
}
},
"node_modules/@sentry/replay/node_modules/@sentry-internal/tracing": {
"version": "7.92.0",
"resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.92.0.tgz",
"integrity": "sha512-ur55vPcUUUWFUX4eVLNP71ohswK7ZZpleNZw9Y1GfLqyI+0ILQUwjtzqItJrdClvVsdRZJMRmDV40Hp9Lbb9mA==",
"version": "7.93.0",
"resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.93.0.tgz",
"integrity": "sha512-DjuhmQNywPp+8fxC9dvhGrqgsUb6wI/HQp25lS2Re7VxL1swCasvpkg8EOYP4iBniVQ86QK0uITkOIRc5tdY1w==",
"dependencies": {
"@sentry/core": "7.92.0",
"@sentry/types": "7.92.0",
"@sentry/utils": "7.92.0"
"@sentry/core": "7.93.0",
"@sentry/types": "7.93.0",
"@sentry/utils": "7.93.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/@sentry/replay/node_modules/@sentry/core": {
"version": "7.92.0",
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.92.0.tgz",
"integrity": "sha512-1Tly7YB2I1byI5xb0Cwrxs56Rhww+6mQ7m9P7rTmdC3/ijOzbEoohtYIUPwcooCEarpbEJe/tAayRx6BrH2UbQ==",
"version": "7.93.0",
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.93.0.tgz",
"integrity": "sha512-vZQSUiDn73n+yu2fEcH+Wpm4GbRmtxmnXnYCPgM6IjnXqkVm3awWAkzrheADblx3kmxrRiOlTXYHw9NTWs56fg==",
"dependencies": {
"@sentry/types": "7.92.0",
"@sentry/utils": "7.92.0"
"@sentry/types": "7.93.0",
"@sentry/utils": "7.93.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/@sentry/replay/node_modules/@sentry/types": {
"version": "7.92.0",
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.92.0.tgz",
"integrity": "sha512-APmSOuZuoRGpbPpPeYIbMSplPjiWNLZRQa73QiXuTflW4Tu/ItDlU8hOa2+A6JKVkJCuD2EN6yUrxDGSMyNXeg==",
"version": "7.93.0",
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.93.0.tgz",
"integrity": "sha512-UnzUccNakhFRA/esWBWP+0v7cjNg+RilFBQC03Mv9OEMaZaS29zSbcOGtRzuFOXXLBdbr44BWADqpz3VW0XaNw==",
"engines": {
"node": ">=8"
}
},
"node_modules/@sentry/replay/node_modules/@sentry/utils": {
"version": "7.92.0",
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.92.0.tgz",
"integrity": "sha512-3nEfrQ1z28b/2zgFGANPh5yMVtgwXmrasZxTvKbrAj+KWJpjrJHrIR84r9W277J44NMeZ5RhRW2uoDmuBslPnA==",
"version": "7.93.0",
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.93.0.tgz",
"integrity": "sha512-Iovj7tUnbgSkh/WrAaMrd5UuYjW7AzyzZlFDIUrwidsyIdUficjCG2OIxYzh76H6nYIx9SxewW0R54Q6XoB4uA==",
"dependencies": {
"@sentry/types": "7.92.0"
"@sentry/types": "7.93.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/@sentry/tracing": {
"version": "7.92.0",
"resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-7.92.0.tgz",
"integrity": "sha512-1+TFFPVEdax4dNi68gin6MENiyGe9mOuNXfjulrP5eCzUEByus5HAxeDI/LLQ1hArfn048AzwSwKUsS2fO5sbg==",
"version": "7.93.0",
"resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-7.93.0.tgz",
"integrity": "sha512-n4XbAQ7e098Jzv4ZvpXAsFgM+XFfjhKci18r7s3UfDMnrB4FTCwhHZoeiygO8PZhB944mEFbNXNFhHkb8nTDbA==",
"dependencies": {
"@sentry-internal/tracing": "7.92.0"
"@sentry-internal/tracing": "7.93.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/@sentry/tracing/node_modules/@sentry-internal/tracing": {
"version": "7.92.0",
"resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.92.0.tgz",
"integrity": "sha512-ur55vPcUUUWFUX4eVLNP71ohswK7ZZpleNZw9Y1GfLqyI+0ILQUwjtzqItJrdClvVsdRZJMRmDV40Hp9Lbb9mA==",
"version": "7.93.0",
"resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.93.0.tgz",
"integrity": "sha512-DjuhmQNywPp+8fxC9dvhGrqgsUb6wI/HQp25lS2Re7VxL1swCasvpkg8EOYP4iBniVQ86QK0uITkOIRc5tdY1w==",
"dependencies": {
"@sentry/core": "7.92.0",
"@sentry/types": "7.92.0",
"@sentry/utils": "7.92.0"
"@sentry/core": "7.93.0",
"@sentry/types": "7.93.0",
"@sentry/utils": "7.93.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/@sentry/tracing/node_modules/@sentry/core": {
"version": "7.92.0",
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.92.0.tgz",
"integrity": "sha512-1Tly7YB2I1byI5xb0Cwrxs56Rhww+6mQ7m9P7rTmdC3/ijOzbEoohtYIUPwcooCEarpbEJe/tAayRx6BrH2UbQ==",
"version": "7.93.0",
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.93.0.tgz",
"integrity": "sha512-vZQSUiDn73n+yu2fEcH+Wpm4GbRmtxmnXnYCPgM6IjnXqkVm3awWAkzrheADblx3kmxrRiOlTXYHw9NTWs56fg==",
"dependencies": {
"@sentry/types": "7.92.0",
"@sentry/utils": "7.92.0"
"@sentry/types": "7.93.0",
"@sentry/utils": "7.93.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/@sentry/tracing/node_modules/@sentry/types": {
"version": "7.92.0",
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.92.0.tgz",
"integrity": "sha512-APmSOuZuoRGpbPpPeYIbMSplPjiWNLZRQa73QiXuTflW4Tu/ItDlU8hOa2+A6JKVkJCuD2EN6yUrxDGSMyNXeg==",
"version": "7.93.0",
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.93.0.tgz",
"integrity": "sha512-UnzUccNakhFRA/esWBWP+0v7cjNg+RilFBQC03Mv9OEMaZaS29zSbcOGtRzuFOXXLBdbr44BWADqpz3VW0XaNw==",
"engines": {
"node": ">=8"
}
},
"node_modules/@sentry/tracing/node_modules/@sentry/utils": {
"version": "7.92.0",
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.92.0.tgz",
"integrity": "sha512-3nEfrQ1z28b/2zgFGANPh5yMVtgwXmrasZxTvKbrAj+KWJpjrJHrIR84r9W277J44NMeZ5RhRW2uoDmuBslPnA==",
"version": "7.93.0",
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.93.0.tgz",
"integrity": "sha512-Iovj7tUnbgSkh/WrAaMrd5UuYjW7AzyzZlFDIUrwidsyIdUficjCG2OIxYzh76H6nYIx9SxewW0R54Q6XoB4uA==",
"dependencies": {
"@sentry/types": "7.92.0"
"@sentry/types": "7.93.0"
},
"engines": {
"node": ">=8"
@@ -18327,9 +18340,9 @@
}
},
"node_modules/react-icons": {
"version": "4.12.0",
"resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.12.0.tgz",
"integrity": "sha512-IBaDuHiShdZqmfc/TwHu6+d6k2ltNCf3AszxNmjJc1KUfXdEeRJOKyNvLmAHaarhzGmTSVygNdyu8/opXv2gaw==",
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.0.1.tgz",
"integrity": "sha512-WqLZJ4bLzlhmsvme6iFdgO8gfZP17rfjYEJ2m9RsZjZ+cc4k1hTzknEz63YS1MeT50kVzoa1Nz36f4BEx+Wigw==",
"peerDependencies": {
"react": "*"
}
@@ -18416,9 +18429,9 @@
}
},
"node_modules/react-redux": {
"version": "9.0.4",
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.0.4.tgz",
"integrity": "sha512-9J1xh8sWO0vYq2sCxK2My/QO7MzUMRi3rpiILP/+tDr8krBHixC6JMM17fMK88+Oh3e4Ae6/sHIhNBgkUivwFA==",
"version": "9.1.0",
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.1.0.tgz",
"integrity": "sha512-6qoDzIO+gbrza8h3hjMA9aq4nwVFCKFtY2iLxCtVT38Swyy2C/dJCGBXHeHLtx6qlg/8qzc2MrhOeduf5K32wQ==",
"dependencies": {
"@types/use-sync-external-store": "^0.0.3",
"use-sync-external-store": "^1.0.0"
@@ -18462,11 +18475,11 @@
}
},
"node_modules/react-router": {
"version": "6.21.1",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.21.1.tgz",
"integrity": "sha512-W0l13YlMTm1YrpVIOpjCADJqEUpz1vm+CMo47RuFX4Ftegwm6KOYsL5G3eiE52jnJpKvzm6uB/vTKTPKM8dmkA==",
"version": "6.21.2",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.21.2.tgz",
"integrity": "sha512-jJcgiwDsnaHIeC+IN7atO0XiSRCrOsQAHHbChtJxmgqG2IaYQXSnhqGb5vk2CU/wBQA12Zt+TkbuJjIn65gzbA==",
"dependencies": {
"@remix-run/router": "1.14.1"
"@remix-run/router": "1.14.2"
},
"engines": {
"node": ">=14.0.0"
@@ -18476,12 +18489,12 @@
}
},
"node_modules/react-router-dom": {
"version": "6.21.1",
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.21.1.tgz",
"integrity": "sha512-QCNrtjtDPwHDO+AO21MJd7yIcr41UetYt5jzaB9Y1UYaPTCnVuJq6S748g1dE11OQlCFIQg+RtAA1SEZIyiBeA==",
"version": "6.21.2",
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.21.2.tgz",
"integrity": "sha512-tE13UukgUOh2/sqYr6jPzZTzmzc70aGRP4pAjG2if0IP3aUT+sBtAKUJh0qMh0zylJHGLmzS+XWVaON4UklHeg==",
"dependencies": {
"@remix-run/router": "1.14.1",
"react-router": "6.21.1"
"@remix-run/router": "1.14.2",
"react-router": "6.21.2"
},
"engines": {
"node": ">=14.0.0"
@@ -19793,9 +19806,9 @@
}
},
"node_modules/socket.io-client": {
"version": "4.7.3",
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.7.3.tgz",
"integrity": "sha512-nU+ywttCyBitXIl9Xe0RSEfek4LneYkJxCeNnKCuhwoH4jGXO1ipIUw/VA/+Vvv2G1MTym11fzFC0SxkrcfXDw==",
"version": "4.7.4",
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.7.4.tgz",
"integrity": "sha512-wh+OkeF0rAVCrABWQBaEjLfb7DVPotMbu0cgWgyR0v6eA4EoVnAwcIeIbcdTE3GT/H3kbdLl7OoH2+asoDRIIg==",
"dependencies": {
"@socket.io/component-emitter": "~3.1.0",
"debug": "~4.3.2",

View File

@@ -12,8 +12,8 @@
"@fingerprintjs/fingerprintjs": "^4.2.1",
"@jsreport/browser-client": "^3.1.0",
"@reduxjs/toolkit": "^2.0.1",
"@sentry/react": "^7.92.0",
"@sentry/tracing": "^7.92.0",
"@sentry/react": "^7.93.0",
"@sentry/tracing": "^7.93.0",
"@splitsoftware/splitio-react": "^1.10.2",
"@tanem/react-nprogress": "^5.0.51",
"antd": "^5.12.8",
@@ -52,13 +52,13 @@
"react-grid-gallery": "^1.0.0",
"react-grid-layout": "^1.3.4",
"react-i18next": "^14.0.0",
"react-icons": "^4.7.1",
"react-icons": "^5.0.1",
"react-image-lightbox": "^5.1.4",
"react-intersection-observer": "^9.5.3",
"react-number-format": "^5.1.4",
"react-redux": "^9.0.4",
"react-redux": "^9.1.0",
"react-resizable": "^3.0.5",
"react-router-dom": "^6.21.1",
"react-router-dom": "^6.21.2",
"react-scripts": "^5.0.1",
"react-sticky": "^6.0.3",
"react-sublime-video": "^0.2.5",
@@ -70,7 +70,7 @@
"redux-state-sync": "^3.1.4",
"reselect": "^5.1.0",
"sass": "^1.69.7",
"socket.io-client": "^4.7.3",
"socket.io-client": "^4.7.4",
"styled-components": "^6.1.8",
"subscriptions-transport-ws": "^0.11.0",
"terser-webpack-plugin": "^5.3.10",

View File

@@ -190,7 +190,7 @@ This package contains the following license and notice below:
# @firebase/logger
This package serves as the base of all logging in the JS SDK. Any logging that
is intended to be visible to Firebase end developers should go through this
is intended to be open to Firebase end developers should go through this
module.
## Basic Usage
@@ -9375,7 +9375,7 @@ parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
to the extent that it includes a convenient and prominently open
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the

View File

@@ -1029,7 +1029,7 @@ The following NPM packages may be included in this product:
- postcss-dir-pseudo-class@5.0.0
- postcss-double-position-gradients@1.0.0
- postcss-env-function@2.0.2
- postcss-focus-visible@4.0.0
- postcss-focus-open@4.0.0
- postcss-focus-within@3.0.0
- postcss-gap-properties@2.0.0
- postcss-image-set-function@3.0.1
@@ -1699,7 +1699,7 @@ This package contains the following license and notice below:
# @firebase/logger
This package serves as the base of all logging in the JS SDK. Any logging that
is intended to be visible to Firebase end developers should go through this
is intended to be open to Firebase end developers should go through this
module.
## Basic Usage
@@ -24029,7 +24029,7 @@ parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
to the extent that it includes a convenient and prominently open
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the

View File

@@ -1,7 +1,7 @@
import {useSplitClient} from "@splitsoftware/splitio-react";
import {Button, Result} from "antd";
import LogRocket from "logrocket";
import React, {lazy, Suspense, useEffect} from "react";
import React, {lazy, Suspense, useEffect, useState} from "react";
import {useTranslation} from "react-i18next";
import {connect} from "react-redux";
import {Route, Routes} from "react-router-dom";
@@ -19,6 +19,7 @@ import {checkUserSession} from "../redux/user/user.actions";
import {selectBodyshop, selectCurrentUser,} from "../redux/user/user.selectors";
import PrivateRoute from "../components/PrivateRoute";
import "./App.styles.scss";
import handleBeta from "../utils/betaHandler";
const ResetPassword = lazy(() =>
import("../pages/reset-password/reset-password.component")
@@ -40,14 +41,16 @@ const mapDispatchToProps = (dispatch) => ({
setOnline: (isOnline) => dispatch(setOnline(isOnline)),
});
export function App({
bodyshop,
checkUserSession,
currentUser,
online,
setOnline,
}) {
export function App({bodyshop, checkUserSession, currentUser, online, setOnline}) {
const client = useSplitClient().client;
const [listenersAdded, setListenersAdded] = useState(false)
const {t} = useTranslation();
// Handle The Beta Switch.
useEffect(() => {
handleBeta();
}, [])
useEffect(() => {
if (!navigator.onLine) {
@@ -60,21 +63,37 @@ export function App({
//const b = Grid.useBreakpoint();
// console.log("Breakpoints:", b);
const {t} = useTranslation();
// Associate event listeners, memoize to prevent multiple listeners being added
useEffect(() => {
const offlineListener = (e) => {
setOnline(false);
}
window.addEventListener("offline", function (e) {
setOnline(false);
});
const onlineListener = (e) => {
setOnline(true);
}
window.addEventListener("online", function (e) {
setOnline(true);
});
if (!listenersAdded) {
console.log('Added events for offline and online');
window.addEventListener("offline", offlineListener);
window.addEventListener("online", onlineListener);
setListenersAdded(true);
}
return () => {
window.removeEventListener("offline", offlineListener);
window.removeEventListener("online", onlineListener);
}
}, [setOnline, listenersAdded]);
useEffect(() => {
if (currentUser.authorized && bodyshop) {
client.setAttribute("imexshopid", bodyshop.imexshopid);
if (client.getTreatment("LogRocket_Tracking") === "on") {
if (
client.getTreatment("LogRocket_Tracking") === "on" ||
window.location.hostname === 'beta.imex.online'
) {
console.log("LR Start");
LogRocket.init("gvfvfw/bodyshopapp");
}

View File

@@ -1,5 +1,8 @@
//Global Styles.
@import "react-big-calendar/lib/sass/styles";
.ant-menu-item-divider {
border-bottom: 1px solid #74695c !important;
}
.imex-table-header {
display: flex;

View File

@@ -48,7 +48,7 @@ export function BillDetailEditcontainer({setPartsOrderContext, insertAuditTrail,
const {t} = useTranslation();
const [form] = Form.useForm();
const [visible, setVisible] = useState(false);
const [open, setOpen] = useState(false);
const [updateLoading, setUpdateLoading] = useState(false);
const [update_bill] = useMutation(UPDATE_BILL);
const [insertBillLine] = useMutation(INSERT_NEW_BILL_LINES);
@@ -71,7 +71,7 @@ export function BillDetailEditcontainer({setPartsOrderContext, insertAuditTrail,
form.getFieldValue("billlines").filter((b) => b.deductedfromlbr).length >
0
)
setVisible(true);
setOpen(true);
else {
form.submit();
}
@@ -154,7 +154,7 @@ export function BillDetailEditcontainer({setPartsOrderContext, insertAuditTrail,
await refetch();
form.setFieldsValue(transformData(data));
form.resetFields();
setVisible(false);
setOpen(false);
setUpdateLoading(false);
};
@@ -178,9 +178,9 @@ export function BillDetailEditcontainer({setPartsOrderContext, insertAuditTrail,
<BillDetailEditReturn data={data} />
<BillPrintButton billid={search.billid} />
<Popconfirm
visible={visible}
open={open}
onConfirm={() => form.submit()}
onCancel={() => setVisible(false)}
onCancel={() => setOpen(false)}
okButtonProps={{ loading: updateLoading }}
title={t("bills.labels.editadjwarning")}
>

View File

@@ -36,7 +36,7 @@ export function BillDetailEditReturn({
const history = useNavigate();
const { t } = useTranslation();
const [form] = Form.useForm();
const [visible, setVisible] = useState(false);
const [open, setOpen] = useState(false);
const handleFinish = ({ billlines }) => {
const selectedLines = billlines.filter((l) => l.selected).map((l) => l.id);
@@ -68,17 +68,17 @@ export function BillDetailEditReturn({
delete search.billid;
history({ search: queryString.stringify(search) });
setVisible(false);
setOpen(false);
};
useEffect(() => {
if (visible === false) form.resetFields();
}, [visible, form]);
if (open === false) form.resetFields();
}, [open, form]);
return (
<>
<Modal
open={visible}
onCancel={() => setVisible(false)}
open={open}
onCancel={() => setOpen(false)}
destroyOnClose
title={t("bills.actions.return")}
onOk={() => form.submit()}
@@ -175,7 +175,7 @@ export function BillDetailEditReturn({
<Button
disabled={data.bills_by_pk.is_credit_memo || disabled}
onClick={() => {
setVisible(true);
setOpen(true);
}}
>
{t("bills.actions.return")}

View File

@@ -346,18 +346,18 @@ function BillEnterModalContainer({
}, [enterAgain, form]);
useEffect(() => {
if (billEnterModal.visible) {
if (billEnterModal.open) {
form.setFieldsValue(formValues);
} else {
form.resetFields();
}
}, [billEnterModal.visible, form, formValues]);
}, [billEnterModal.open, form, formValues]);
return (
<Modal
title={t("bills.labels.new")}
width={"98%"}
open={billEnterModal.visible}
open={billEnterModal.open}
okText={t("general.actions.save")}
keyboard="false"
onOk={() => form.submit()}

View File

@@ -25,7 +25,7 @@ export function ContractsFindModalContainer({
}) {
const { t } = useTranslation();
const { visible } = caBcEtfTableModal;
const { open } = caBcEtfTableModal;
const [loading, setLoading] = useState(false);
const [form] = Form.useForm();
const EtfTemplate = TemplateList("special").ca_bc_etf_table;
@@ -63,14 +63,14 @@ export function ContractsFindModalContainer({
};
useEffect(() => {
if (visible) {
if (open) {
form.resetFields();
}
}, [visible, form]);
}, [open, form]);
return (
<Modal
open={visible}
open={open}
width="70%"
title={t("payments.labels.findermodal")}
onCancel={() => toggleModalVisible()}

View File

@@ -22,7 +22,7 @@ function CardPaymentModalContainer({
toggleModalVisible,
bodyshop,
}) {
const { visible } = cardPaymentModal;
const { open } = cardPaymentModal;
const { t } = useTranslation();
const handleCancel = () => {
@@ -35,7 +35,7 @@ function CardPaymentModalContainer({
return (
<Modal
open={visible}
open={open}
onOk={handleOK}
onCancel={handleCancel}
footer={[

View File

@@ -4,20 +4,11 @@ import { Button, notification, Space } from "antd";
import axios from "axios";
import React, { useEffect } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { messaging, requestForToken } from "../../firebase/firebase.utils";
import { selectChatVisible } from "../../redux/messaging/messaging.selectors";
import { selectBodyshop } from "../../redux/user/user.selectors";
import FcmHandler from "../../utils/fcm-handler";
import ChatPopupComponent from "../chat-popup/chat-popup.component";
import "./chat-affix.styles.scss";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
chatVisible: selectChatVisible,
});
export function ChatAffixContainer({ bodyshop, chatVisible }) {
const { t } = useTranslation();
const client = useApolloClient();
@@ -36,35 +27,34 @@ export function ChatAffixContainer({ bodyshop, chatVisible }) {
console.log("FCM Topic Subscription", r.data);
} catch (error) {
console.log(
"Error attempting to subscribe to messaging topic: ",
error
"Error attempting to subscribe to messaging topic: ",
error
);
notification.open({
type: "warning",
message: t("general.errors.fcm"),
btn: (
<Space>
<Button
onClick={async () => {
await requestForToken();
SubscribeToTopic();
}}
>
{t("general.actions.tryagain")}
</Button>
<Button
onClick={() => {
const win = window.open(
"https://help.imex.online/en/article/enabling-notifications-o978xi/",
"_blank"
);
win.focus();
}}
>
{t("general.labels.help")}
</Button>
</Space>
<Space>
<Button
onClick={async () => {
await requestForToken();
SubscribeToTopic();
}}
>
{t("general.actions.tryagain")}
</Button>
<Button
onClick={() => {
const win = window.open(
"https://help.imex.online/en/article/enabling-notifications-o978xi/",
"_blank"
);
win.focus();
}}
>
{t("general.labels.help")}
</Button>
</Space>
),
});
}
@@ -81,16 +71,16 @@ export function ChatAffixContainer({ bodyshop, chatVisible }) {
payload: (payload && payload.data && payload.data.data) || payload.data,
});
}
let stopMessageListenr, channel;
let stopMessageListener, channel;
try {
stopMessageListenr = onMessage(messaging, handleMessage);
stopMessageListener = onMessage(messaging, handleMessage);
channel = new BroadcastChannel("imex-sw-messages");
channel.addEventListener("message", handleMessage);
} catch (error) {
console.log("Unable to set event listeners.");
}
return () => {
stopMessageListenr && stopMessageListenr();
stopMessageListener && stopMessageListener();
channel && channel.removeEventListener("message", handleMessage);
};
}, [client]);
@@ -98,9 +88,10 @@ export function ChatAffixContainer({ bodyshop, chatVisible }) {
if (!bodyshop || !bodyshop.messagingservicesid) return <></>;
return (
<div className={`chat-affix ${chatVisible ? "chat-affix-open" : ""}`}>
{bodyshop && bodyshop.messagingservicesid ? <ChatPopupComponent /> : null}
</div>
<div className={`chat-affix ${chatVisible ? "chat-affix-open" : ""}`}>
{bodyshop && bodyshop.messagingservicesid ? <ChatPopupComponent /> : null}
</div>
);
}
export default connect(mapStateToProps, null)(ChatAffixContainer);
export default ChatAffixContainer;

View File

@@ -27,7 +27,7 @@ export function ChatMediaSelector({
conversation,
}) {
const { t } = useTranslation();
const [visible, setVisible] = useState(false);
const [open, setOpen] = useState(false);
const { loading, error, data } = useQuery(GET_DOCUMENTS_BY_JOB, {
fetchPolicy: "network-only",
@@ -39,13 +39,13 @@ export function ChatMediaSelector({
},
skip:
!visible ||
!open ||
!conversation.job_conversations ||
conversation.job_conversations.length === 0,
});
const handleVisibleChange = (visible) => {
setVisible(visible);
const handleVisibleChange = (change) => {
setOpen(change);
};
useEffect(() => {
@@ -65,7 +65,7 @@ export function ChatMediaSelector({
externalMediaState={[selectedMedia, setSelectedMedia]}
/>
)}
{bodyshop.uselocalmediaserver && visible && (
{bodyshop.uselocalmediaserver && open && (
<JobDocumentsLocalGalleryExternal
externalMediaState={[selectedMedia, setSelectedMedia]}
jobId={
@@ -88,7 +88,7 @@ export function ChatMediaSelector({
}
title={t("messaging.labels.selectmedia")}
trigger="click"
open={visible}
open={open}
onOpenChange={handleVisibleChange}
>
<Badge count={selectedMedia.filter((s) => s.isSelected).length}>

View File

@@ -9,12 +9,12 @@ export default function ChatTagRoComponent({
loading,
handleSearch,
handleInsertTag,
setVisible,
setOpen,
}) {
const { t } = useTranslation();
return (
<Space flex>
<Space>
<div style={{ width: "15rem" }}>
<Select
showSearch
@@ -38,7 +38,7 @@ export default function ChatTagRoComponent({
{loading ? (
<LoadingOutlined />
) : (
<CloseCircleOutlined onClick={() => setVisible(false)} />
<CloseCircleOutlined onClick={() => setOpen(false)} />
)}
</Space>
);

View File

@@ -11,7 +11,7 @@ import ChatTagRo from "./chat-tag-ro.component";
export default function ChatTagRoContainer({ conversation }) {
const { t } = useTranslation();
const [visible, setVisible] = useState(false);
const [open, setOpen] = useState(false);
const [loadRo, { loading, data }] = useLazyQuery(SEARCH_FOR_JOBS);
@@ -33,7 +33,7 @@ export default function ChatTagRoContainer({ conversation }) {
const handleInsertTag = (value, option) => {
logImEXEvent("messaging_add_job_tag");
insertTag({ variables: { jobId: option.key } });
setVisible(false);
setOpen(false);
};
const existingJobTags =
@@ -47,16 +47,16 @@ export default function ChatTagRoContainer({ conversation }) {
return (
<div>
{visible ? (
{open ? (
<ChatTagRo
loading={loading}
roOptions={roOptions}
handleSearch={handleSearch}
handleInsertTag={handleInsertTag}
setVisible={setVisible}
setOpen={setOpen}
/>
) : (
<Tag onClick={() => setVisible(true)}>
<Tag onClick={() => setOpen(true)}>
<PlusOutlined />
{t("messaging.actions.link")}
</Tag>

View File

@@ -38,7 +38,7 @@ export function ContractConvertToRo({
disabled,
}) {
const { t } = useTranslation();
const [visible, setVisible] = useState(false);
const [open, setOpen] = useState(false);
const [loading, setLoading] = useState(false);
const [insertJob] = useMutation(INSERT_NEW_JOB);
const history = useNavigate();
@@ -306,7 +306,7 @@ export function ContractConvertToRo({
});
}
setVisible(false);
setOpen(false);
setLoading(false);
};
@@ -380,7 +380,7 @@ export function ContractConvertToRo({
<Button type="primary" htmlType="submit" loading={loading}>
{t("contracts.actions.convertoro")}
</Button>
<Button onClick={() => setVisible(false)}>
<Button onClick={() => setOpen(false)}>
{t("general.actions.close")}
</Button>
</Space>
@@ -390,9 +390,9 @@ export function ContractConvertToRo({
return (
<div>
<Popover content={popContent} open={visible}>
<Popover content={popContent} open={open}>
<Button
onClick={() => setVisible(true)}
onClick={() => setOpen(true)}
loading={loading}
disabled={!contract.dailyrate || !contract.actualreturn || disabled}
>

View File

@@ -31,7 +31,7 @@ export function ContractsFindModalContainer({
}) {
const { t } = useTranslation();
const { visible } = contractFinderModal;
const { open } = contractFinderModal;
const [form] = Form.useForm();
@@ -52,14 +52,14 @@ export function ContractsFindModalContainer({
};
useEffect(() => {
if (visible) {
if (open) {
form.resetFields();
}
}, [visible, form]);
}, [open, form]);
return (
<Modal
open={visible}
open={open}
width="70%"
title={t("contracts.labels.findermodal")}
onCancel={() => toggleModalVisible()}

View File

@@ -26,7 +26,7 @@ export function CCReturnModalContainer({
bodyshop,
}) {
const [loading, setLoading] = useState(false);
const { visible, context, actions } = courtesyCarReturnModal;
const { open, context, actions } = courtesyCarReturnModal;
const { t } = useTranslation();
const [form] = Form.useForm();
const [updateContract] = useMutation(RETURN_CONTRACT);
@@ -64,7 +64,7 @@ export function CCReturnModalContainer({
return (
<Modal
title={t("courtesycars.labels.return")}
open={visible}
open={open}
onCancel={() => toggleModalVisible()}
width={"90%"}
okText={t("general.actions.save")}

View File

@@ -6,13 +6,13 @@ export default function DataLabel({
hideIfNull,
children,
vertical,
visible = true,
open = true,
valueStyle = {},
valueClassName,
onValueClick,
...props
}) {
if (!visible || (hideIfNull && !!!children)) return null;
if (!open || (hideIfNull && !!!children)) return null;
return (
<div {...props} style={{ display: "flex" }}>

View File

@@ -18,7 +18,7 @@ const mapDispatchToProps = (dispatch) => ({
export default connect(mapStateToProps, mapDispatchToProps)(DmsCdkVehicles);
export function DmsCdkVehicles({ bodyshop, form, socket, job }) {
const [visible, setVisible] = useState(false);
const [open, setOpen] = useState(false);
const [selectedModel, setSelectedModel] = useState(null);
const { t } = useTranslation();
@@ -51,14 +51,14 @@ export function DmsCdkVehicles({ bodyshop, form, socket, job }) {
<>
<Modal
width={"90%"}
open={visible}
onCancel={() => setVisible(false)}
open={open}
onCancel={() => setOpen(false)}
onOk={() => {
form.setFieldsValue({
dms_make: selectedModel.makecode,
dms_model: selectedModel.modelcode,
});
setVisible(false);
setOpen(false);
}}
>
{error && <AlertComponent error={error.message} />}
@@ -90,7 +90,7 @@ export function DmsCdkVehicles({ bodyshop, form, socket, job }) {
</Modal>
<Button
onClick={() => {
setVisible(true);
setOpen(true);
callSearch({
variables: {
search: job && job.v_model_desc && job.v_model_desc.substr(0, 3),

View File

@@ -21,29 +21,29 @@ export default connect(
export function DmsCustomerSelector({ bodyshop }) {
const { t } = useTranslation();
const [customerList, setcustomerList] = useState([]);
const [visible, setVisible] = useState(false);
const [open, setOpen] = useState(false);
const [selectedCustomer, setSelectedCustomer] = useState(null);
const [dmsType, setDmsType] = useState("cdk");
socket.on("cdk-select-customer", (customerList, callback) => {
setVisible(true);
setOpen(true);
setDmsType("cdk");
setcustomerList(customerList);
});
socket.on("pbs-select-customer", (customerList, callback) => {
setVisible(true);
setOpen(true);
setDmsType("pbs");
setcustomerList(customerList);
});
const onUseSelected = () => {
setVisible(false);
setOpen(false);
socket.emit(`${dmsType}-selected-customer`, selectedCustomer);
setSelectedCustomer(null);
};
const onUseGeneric = () => {
setVisible(false);
setOpen(false);
socket.emit(
`${dmsType}-selected-customer`,
bodyshop.cdk_configuration.generic_customer_number
@@ -52,7 +52,7 @@ export function DmsCustomerSelector({ bodyshop }) {
};
const onCreateNew = () => {
setVisible(false);
setOpen(false);
socket.emit(`${dmsType}-selected-customer`, null);
setSelectedCustomer(null);
};
@@ -114,7 +114,7 @@ export function DmsCustomerSelector({ bodyshop }) {
},
];
if (!visible) return null;
if (!open) return null;
return (
<Col span={24}>
<Table

View File

@@ -186,7 +186,6 @@ export function EmailOverlayContainer({
okText={t("general.actions.send")}
okButtonProps={{
loading: sending,
disabled:
selectedMedia &&
(selectedMedia

View File

@@ -16,15 +16,7 @@ export default connect(mapStateToProps, mapDispatchToProps)(FormDatePicker);
const dateFormat = "MM/DD/YYYY";
export function FormDatePicker({
bodyshop,
value,
onChange,
onBlur,
onlyFuture,
isDateOnly = true,
...restProps
}) {
export function FormDatePicker({bodyshop, value, onChange, onBlur, onlyFuture, isDateOnly = true, ...restProps }) {
const ref = useRef();
const handleChange = (newDate) => {

View File

@@ -13,6 +13,7 @@ import Icon, {
FileFilled,
HomeFilled,
ImportOutlined,
InfoCircleOutlined,
LineChartOutlined,
PaperClipOutlined,
PhoneOutlined,
@@ -25,8 +26,8 @@ import Icon, {
UserOutlined,
} from "@ant-design/icons";
import {useSplitTreatments} from "@splitsoftware/splitio-react";
import {Layout, Menu} from "antd";
import React from "react";
import {Layout, Menu, Switch, Tooltip} from "antd";
import React, {useEffect, useState} from "react";
import {useTranslation} from "react-i18next";
import {BsKanban} from "react-icons/bs";
import {FaCalendarAlt, FaCarCrash, FaCreditCard, FaFileInvoiceDollar,} from "react-icons/fa";
@@ -41,6 +42,7 @@ import {setModalContext} from "../../redux/modals/modals.actions";
import {signOutStart} from "../../redux/user/user.actions";
import {selectBodyshop, selectCurrentUser,} from "../../redux/user/user.selectors";
import {FiLogOut} from "react-icons/fi";
import handleBeta, {checkBeta, setBeta} from "../../utils/betaHandler";
const mapStateToProps = createStructuredSelector({
currentUser: selectCurrentUser,
@@ -63,16 +65,40 @@ const mapDispatchToProps = (dispatch) => ({
dispatch(setModalContext({context: context, modal: "cardPayment"})),
});
function Header({handleMenuClick, currentUser, bodyshop, selectedHeader, signOutStart, setBillEnterContext, setTimeTicketContext, setPaymentContext, setReportCenterContext, recentItems, setCardPaymentContext}) {
function Header({
handleMenuClick,
currentUser,
bodyshop,
selectedHeader,
signOutStart,
setBillEnterContext,
setTimeTicketContext,
setPaymentContext,
setReportCenterContext,
recentItems,
setCardPaymentContext
}) {
const {treatments: {ImEXPay, DmsAp, Simple_Inventory}} = useSplitTreatments({
attributes: {},
names: ["ImEXPay", "DmsAp", "Simple_Inventory"],
splitKey: bodyshop && bodyshop.imexshopid,
});
const [betaSwitch, setBetaSwitch] = useState(false);
const {t} = useTranslation();
useEffect(() => {
const isBeta = checkBeta();
setBetaSwitch(isBeta);
}, []);
const betaSwitchChange = (checked) => {
setBeta(checked);
setBetaSwitch(checked);
handleBeta();
}
const accountingChildren = [
{
key: 'bills',
@@ -173,7 +199,7 @@ function Header({handleMenuClick, currentUser, bodyshop, selectedHeader, signOut
{
key: 'receivables',
label: (<Link to="/manage/accounting/receivables">{t("menus.header.accounting-receivables")}</Link>)
}
},
]
if (!((bodyshop && bodyshop.cdk_dealerid) || (bodyshop && bodyshop.pbs_serialnumber)) || DmsAp.treatment === "on") {
@@ -193,17 +219,20 @@ function Header({handleMenuClick, currentUser, bodyshop, selectedHeader, signOut
});
}
accountingExportChildren.push(
{
key: 'exportlogs',
label: (<Link to="/manage/accounting/exportlogs">{t("menus.header.export-logs")}</Link>)
},
accountingExportChildren.push({
type: 'divider',
}, {
key: 'exportlogs',
label: (<Link to="/manage/accounting/exportlogs">{t("menus.header.export-logs")}</Link>)
});
accountingChildren.push(
{
key: 'accountingexport',
icon: <ExportOutlined/>,
label: t("menus.header.export"),
children: accountingExportChildren
}
},
);
const menuItems = [
@@ -255,6 +284,9 @@ function Header({handleMenuClick, currentUser, bodyshop, selectedHeader, signOut
icon: <UnorderedListOutlined/>,
label: (<Link to="/manage/jobs/all">{t("menus.header.alljobs")}</Link>)
},
{
type: 'divider',
},
{
key: 'productionlist',
icon: <ScheduleOutlined/>,
@@ -448,13 +480,28 @@ function Header({handleMenuClick, currentUser, bodyshop, selectedHeader, signOut
})),
}
]
];
menuItems.push({
key: 'beta-switch',
style: {marginLeft: 'auto'},
label: (
<Tooltip title="A faster more modern ImEX Online is ready for you to try! You can switch back at any time.">
<InfoCircleOutlined/>
<span style={{marginRight: 8}}>Try the new ImEX Online</span>
<Switch
checked={betaSwitch}
onChange={betaSwitchChange}
/>
</Tooltip>
)
});
return (
<Layout.Header>
<Menu
mode="horizontal"
//theme="light"
theme={"dark"}
selectedKeys={[selectedHeader]}
onClick={handleMenuClick}

View File

@@ -36,7 +36,7 @@ export function InventoryUpsertModalContainer({
const [insertInventory] = useMutation(INSERT_INVENTORY_LINE);
const [updateInventoryLine] = useMutation(UPDATE_INVENTORY_LINE);
const { visible, context, actions } = inventoryUpsertModal;
const { open, context, actions } = inventoryUpsertModal;
const { existingInventory } = context;
const { refetch } = actions;
@@ -44,12 +44,12 @@ export function InventoryUpsertModalContainer({
useEffect(() => {
//Required to prevent infinite looping.
if (existingInventory && visible) {
if (existingInventory && open) {
form.setFieldsValue(existingInventory);
} else if (!existingInventory && visible) {
} else if (!existingInventory && open) {
form.resetFields();
}
}, [existingInventory, form, visible]);
}, [existingInventory, form, open]);
const handleFinish = async (formValues) => {
const values = formValues;
@@ -103,7 +103,7 @@ export function InventoryUpsertModalContainer({
? t("inventory.actions.edit")
: t("inventory.actions.new")
}
open={visible}
open={open}
okText={t("general.actions.save")}
onOk={() => {
form.submit();

View File

@@ -57,7 +57,7 @@ export function ScheduleEventComponent({
setScheduleContext,
}) {
const { t } = useTranslation();
const [visible, setVisible] = useState(false);
const [open, setOpen] = useState(false);
const history = useNavigate();
const searchParams = queryString.parse(useLocation().search);
const [updateAppointment] = useMutation(UPDATE_APPOINTMENT);
@@ -223,7 +223,7 @@ export function ScheduleEventComponent({
time: dayjs(event.start).format("HH:mm a"),
})
);
setVisible(false);
setOpen(false);
} else {
notification["error"]({
message: t("messaging.error.invalidphone"),
@@ -290,7 +290,7 @@ export function ScheduleEventComponent({
<Button
disabled={event.arrived}
onClick={() => {
setVisible(false);
setOpen(false);
setScheduleContext({
actions: { refetch: refetch },
context: {
@@ -366,8 +366,8 @@ export function ScheduleEventComponent({
return (
<Popover
open={visible}
onOpenChange={(vis) => !event.vacation && setVisible(vis)}
open={open}
onOpenChange={(vis) => !event.vacation && setOpen(vis)}
trigger="click"
content={event.block ? blockContent : popoverContent}
style={{

View File

@@ -53,7 +53,7 @@ export function ScheduleEventNote({ event }) {
return (
<DataLabel label={t("appointments.fields.note")}>
<Space flex>
<Space>
{!editing ? (
event.note || ""
) : (

View File

@@ -23,23 +23,23 @@ export function JobCostingModalContainer({
}) {
const { t } = useTranslation();
const [costingData, setCostingData] = useState(null);
const { visible, context } = jobCostingModal;
const { open, context } = jobCostingModal;
const { jobId } = context;
useEffect(() => {
async function getData() {
if (jobId && visible) {
if (jobId && open) {
const { data } = await axios.post("/job/costing", { jobid: jobId });
setCostingData(data);
}
}
getData();
}, [jobId, visible]);
}, [jobId, open]);
return (
<Modal
open={visible}
open={open}
title={t("jobs.labels.jobcosting")}
onOk={() => {
toggleModalVisible();

View File

@@ -17,7 +17,7 @@ export default function JobDetailCardsInsuranceComponent({ loading, data }) {
</DataLabel>
<DataLabel
label={t("jobs.labels.cards.filehandler")}
visible={data.ins_ct_fn && data.ins_ct_ln}>
open={data.ins_ct_fn && data.ins_ct_ln}>
{data.ins_ea ? (
<a href={`mailto:${data.ins_ea}`}>
<div>{`${data.ins_ct_fn || ""} ${data.ins_ct_ln || ""}`}</div>
@@ -28,7 +28,7 @@ export default function JobDetailCardsInsuranceComponent({ loading, data }) {
</DataLabel>
<DataLabel
label={t("jobs.labels.cards.estimator")}
visible={data.est_ct_fn && data.est_ct_ln}>
open={data.est_ct_fn && data.est_ct_ln}>
{data.ins_ea ? (
<a href={`mailto:${data.est_ea}`}>
<div>{`${data.est_ct_fn || ""} ${data.est_ct_ln || ""}`}</div>

View File

@@ -22,7 +22,7 @@ export default connect(
export function JobLinesUpsertModalComponent({
bodyshop,
visible,
open,
jobLine,
handleCancel,
handleFinish,
@@ -33,7 +33,7 @@ export function JobLinesUpsertModalComponent({
useEffect(() => {
form.resetFields();
}, [visible, form]);
}, [open, form]);
const { treatments: {Allow_Negative_Jobline_Price, Autohouse_Detail_line} } = useSplitTreatments({
@@ -50,7 +50,7 @@ export function JobLinesUpsertModalComponent({
: t("joblines.labels.new")
}
forceRender
open={visible}
open={open}
width="60%"
okText={t("general.actions.save")}
onOk={() => form.submit()}

View File

@@ -133,7 +133,7 @@ function JobLinesUpsertModalContainer({
return (
<JobLinesUpdsertModal
visible={jobLineEditModal.visible}
open={jobLineEditModal.open}
jobLine={jobLineEditModal.context}
handleFinish={handleFinish}
handleCancel={handleCancel}

View File

@@ -24,12 +24,12 @@ function JobReconciliationModalContainer({
toggleModalVisible,
}) {
const { t } = useTranslation();
const { context, visible } = reconciliationModal;
const { context, open } = reconciliationModal;
const { job } = context;
const { loading, error, data } = useQuery(GET_JOB_RECONCILIATION_BY_PK, {
variables: { id: job && job.id },
skip: !(job && job.id) || !visible,
skip: !(job && job.id) || !open,
fetchPolicy: "network-only",
nextFetchPolicy: "network-only",
});
@@ -42,7 +42,7 @@ function JobReconciliationModalContainer({
<Modal
title={t("jobs.labels.reconciliationheader")}
width={"95%"}
open={visible}
open={open}
okText={t("general.actions.close")}
onOk={handleCancel}
onCancel={handleCancel}

View File

@@ -69,8 +69,9 @@ export function JobsAdminDatesChange({ insertAuditTrail, job }) {
}),
});
}
form.resetFields();
form.resetFields();
setLoading(false);
//Get the owner details, populate it all back into the job.
};

View File

@@ -379,7 +379,7 @@ export function JobsAvailableContainer({bodyshop, currentUser, insertAuditTrail,
setPartsQueueToggle={setPartsQueueToggle}
selectedOwner={selectedOwner}
setSelectedOwner={setSelectedOwner}
visible={ownerModalVisible}
open={ownerModalVisible}
onOk={onOwnerFindModalOk}
onCancel={onOwnerModalCancel}
@@ -390,7 +390,7 @@ export function JobsAvailableContainer({bodyshop, currentUser, insertAuditTrail,
selectedJob={selectedJob}
setSelectedJob={setSelectedJob}
importOptionsState={importOptionsState}
visible={jobModalVisible}
open={jobModalVisible}
onOk={onJobFindModalOk}
onCancel={onJobModalCancel}
modalSearchState={modalSearchState}

View File

@@ -62,13 +62,15 @@ export function JobsCloseAutoAllocate({ bodyshop, joblines, form, disabled }) {
);
};
const menu = {
const menu =bodyshop.cdk_dealerid || bodyshop.pbs_serialnumber ? {
items: bodyshop.md_responsibility_centers.dms_defaults.map((mapping) => ({
key: mapping.name,
label: mapping.name,
disabled: disabled,
})),
onClick: handleMenuClick,
} : {
items: []
}
return bodyshop.cdk_dealerid || bodyshop.pbs_serialnumber ? (

View File

@@ -37,7 +37,7 @@ export function JobsConvertButton({
insertAuditTrail,
parentFormIsFieldsTouched,
}) {
const [visible, setVisible] = useState(false);
const [open, setOpen] = useState(false);
const [loading, setLoading] = useState(false);
const [mutationConvertJob] = useMutation(CONVERT_JOB_TO_RO);
const { t } = useTranslation();
@@ -80,7 +80,7 @@ export function JobsConvertButton({
),
});
setVisible(false);
setOpen(false);
}
setLoading(false);
};
@@ -243,10 +243,10 @@ export function JobsConvertButton({
<Switch />
</Form.Item>
<Space wrap>
<Button type="danger" onClick={() => form.submit()} loading={loading}>
<Button type="primary" danger onClick={() => form.submit()} loading={loading}>
{t("jobs.actions.convert")}
</Button>
<Button onClick={() => setVisible(false)}>
<Button onClick={() => setOpen(false)}>
{t("general.actions.close")}
</Button>
</Space>
@@ -257,15 +257,16 @@ export function JobsConvertButton({
if (job.converted) return <></>;
return (
<Popover open={visible} content={popMenu}>
<Popover open={open} content={popMenu}>
<Button
key="convert"
type="danger"
type="primary"
danger
// style={{ display: job.converted ? "none" : "" }}
disabled={job.converted || jobRO}
loading={loading}
onClick={() => {
setVisible(true);
setOpen(true);
form.setFieldsValue({
driveable: true,
towin: false,

View File

@@ -1,6 +1,6 @@
import {DownCircleFilled} from "@ant-design/icons";
import {useApolloClient, useMutation} from "@apollo/client";
import {Button, Card, Dropdown, Form, Input, notification, Popconfirm, Popover, Select, Space,} from "antd";
import {Button, Card, Dropdown, Form, Input, Modal, notification, Popconfirm, Popover, Select, Space,} from "antd";
import React, {useMemo, useState} from "react";
import {useTranslation} from "react-i18next";
import {connect} from "react-redux";
@@ -77,6 +77,7 @@ export function JobsDetailHeaderActions({
const history = useNavigate();
const [form] = Form.useForm();
const [loading, setLoading] = useState(false);
const [isCancelScheduleModalVisible, setIsCancelScheduleModalVisible] = useState(false);
const [insertAppointment] = useMutation(INSERT_MANUAL_APPT);
const [deleteJob] = useMutation(DELETE_JOB);
const [insertCsi] = useMutation(INSERT_CSI);
@@ -106,6 +107,17 @@ export function JobsDetailHeaderActions({
);
}, [job.status, bodyshop.md_ro_statuses.post_production_statuses]);
// Function to show modal
const showCancelScheduleModal = () => {
setIsCancelScheduleModalVisible(true);
};
// Function to handle Cancel
const handleCancelScheduleModalCancel = () => {
setIsCancelScheduleModalVisible(false);
};
const handleDuplicate = () =>
DuplicateJob(
client,
@@ -149,7 +161,6 @@ export function JobsDetailHeaderActions({
message: t("appointments.successes.created"),
});
} catch (error) {
console.log(error);
} finally {
setLoading(false);
setVisibility(false);
@@ -459,6 +470,13 @@ export function JobsDetailHeaderActions({
});
};
// Function to handle OK
const handleCancelScheduleOK = async () => {
await form.submit(); // Assuming 'form' is the Form instance from useForm()
setIsCancelScheduleModalVisible(false);
};
const handleLostSaleFinish = async ({lost_sale_reason}) => {
const jobUpdate = await cancelAllAppointments({
variables: {
@@ -588,6 +606,7 @@ export function JobsDetailHeaderActions({
const menuItems = [
{
key: 'schedule',
disabled: !jobInPreProduction || !job.converted || jobRO,
label: t("jobs.actions.schedule"),
onClick: () => {
@@ -603,51 +622,18 @@ export function JobsDetailHeaderActions({
},
},
{
key: 'cancelallappointments',
onClick: () => {
if ( job.status !== bodyshop.md_ro_statuses.default_scheduled) {
return;
}
showCancelScheduleModal()
},
disabled: job.status !== bodyshop.md_ro_statuses.default_scheduled,
label: job.status !== bodyshop.md_ro_statuses.default_scheduled ? (
t("menus.jobsactions.cancelallappointments")
) : (
<Popover
trigger="click"
disabled={job.status !== bodyshop.md_ro_statuses.default_scheduled}
content={
<Form
layout="vertical"
onFinish={handleLostSaleFinish}
>
<Form.Item
name="lost_sale_reason"
label={t("jobs.fields.lost_sale_reason")}
rules={[
{
required: true,
//message: t("general.validation.required"),
},
]}
>
<Select
options={bodyshop.md_lost_sale_reasons.map((lsr) => ({
label: lsr,
value: lsr,
}))}
/>
</Form.Item>
<Button
htmlType="submit"
disabled={
job.status !== bodyshop.md_ro_statuses.default_scheduled
}
>
{t("appointments.actions.cancel")}
</Button>
</Form>
}
>
{t("menus.jobsactions.cancelallappointments")}
</Popover>
)
label: t("menus.jobsactions.cancelallappointments")
},
{
key: 'intake',
disabled: !!job.intakechecklist || !jobInPreProduction || !job.converted || jobRO,
label: !!job.intakechecklist || !jobInPreProduction || !job.converted || jobRO ? (
t("jobs.actions.intake")
@@ -658,6 +644,7 @@ export function JobsDetailHeaderActions({
)
},
{
key: 'deliver',
disabled: !jobInProduction || jobRO,
label: !jobInProduction ? (
t("jobs.actions.deliver")
@@ -668,6 +655,7 @@ export function JobsDetailHeaderActions({
)
},
{
key: 'checklist',
disabled: !job.converted,
label: <Link to={`/manage/jobs/${job.id}/checklist`}>
{t("jobs.actions.viewchecklist")}
@@ -771,6 +759,7 @@ export function JobsDetailHeaderActions({
label: t("menus.jobsactions.duplicate"),
children: [
{
key: 'duplicate',
label: <Popconfirm
title={t("jobs.labels.duplicateconfirm")}
okText="Yes"
@@ -783,6 +772,7 @@ export function JobsDetailHeaderActions({
</Popconfirm>
},
{
key: 'duplicatenolines',
label: <Popconfirm
title={t("jobs.labels.duplicateconfirm")}
okText="Yes"
@@ -949,13 +939,13 @@ export function JobsDetailHeaderActions({
if (job && !job.converted) {
menuItems.push(
{
key: 'deletejob',
label: <Popconfirm
title={t("jobs.labels.deleteconfirm")}
okText={t("general.labels.yes")}
cancelText={t("general.labels.no")}
onClick={(e) => e.stopPropagation()}
onConfirm={handleDeleteJob}
getPopupContainer={(trigger) => trigger.parentNode}
>
{t("menus.jobsactions.deletejob")}
</Popconfirm>
@@ -965,6 +955,7 @@ export function JobsDetailHeaderActions({
menuItems.push(
{
key: 'manualevent',
onClick: (e) => {
setVisibility(true);
},
@@ -974,6 +965,7 @@ export function JobsDetailHeaderActions({
if (!jobRO && job.converted) {
menuItems.push({
key: 'voidjob',
label: <RbacWrapper action="jobs:void" noauth>
<Popconfirm
title={t("jobs.labels.voidjob")}
@@ -981,7 +973,6 @@ export function JobsDetailHeaderActions({
cancelText="No"
onClick={(e) => e.stopPropagation()}
onConfirm={handleVoidJob}
getPopupContainer={(trigger) => trigger.parentNode}
>
{t("menus.jobsactions.void")}
</Popconfirm>
@@ -996,6 +987,47 @@ export function JobsDetailHeaderActions({
return (
<>
<Modal
title={t("menus.jobsactions.cancelallappointments")}
open={isCancelScheduleModalVisible}
onOk={handleCancelScheduleOK}
onCancel={handleCancelScheduleModalCancel}
footer={[
<Button form="cancelScheduleForm" key="back" onClick={handleCancelScheduleModalCancel}>
{t("general.actions.cancel")}
</Button>,
<Button form="cancelScheduleForm" htmlType="submit" key="submit" type="primary" loading={loading} onClick={handleCancelScheduleOK}>
{t("appointments.actions.cancel")}
</Button>,
]}
>
<Form
layout="vertical"
id="cancelScheduleForm"
onFinish={s =>{
console.log(s);
handleLostSaleFinish(s);
}}
>
<Form.Item
name="lost_sale_reason"
label={t("jobs.fields.lost_sale_reason")}
rules={[
{
required: true,
//message: t("general.validation.required"),
},
]}
>
<Select
options={bodyshop.md_lost_sale_reasons.map((lsr) => ({
label: lsr,
value: lsr,
}))}
/>
</Form.Item>
</Form>
</Modal>
<Dropdown menu={menu} trigger={["click"]} key="changestatus">
<Button>
<span>{t("general.labels.actions")}</span>

View File

@@ -35,7 +35,7 @@ export function JobsDocumentsGalleryReassign({
];
}, [galleryImages]);
const client = useApolloClient();
const [visible, setVisible] = useState(false);
const [open, setOpen] = useState(false);
const [loading, setLoading] = useState(false);
// const updateImage = async (i, jobid) => {
@@ -126,7 +126,7 @@ export function JobsDocumentsGalleryReassign({
message: t("documents.successes.updated"),
});
}
setVisible(false);
setOpen(false);
setLoading(false);
};
@@ -151,7 +151,7 @@ export function JobsDocumentsGalleryReassign({
<Button type="primary" onClick={() => form.submit()}>
{t("general.actions.submit")}
</Button>
<Button onClick={() => setVisible(false)}>
<Button onClick={() => setOpen(false)}>
{t("general.actions.cancel")}
</Button>
</Space>
@@ -159,10 +159,10 @@ export function JobsDocumentsGalleryReassign({
);
return (
<Popover content={popContent} open={visible}>
<Popover content={popContent} open={open}>
<Button
disabled={selectedImages.length < 1}
onClick={() => setVisible(true)}
onClick={() => setOpen(true)}
loading={loading}
>
{t("documents.actions.reassign")}

View File

@@ -32,7 +32,7 @@ export function JobsDocumentsLocalGalleryReassign({
const { t } = useTranslation();
const [form] = Form.useForm();
const [visible, setVisible] = useState(false);
const [open, setOpen] = useState(false);
const [loading, setLoading] = useState(false);
const handleFinish = async ({ jobid: newJobid }) => {
@@ -50,7 +50,7 @@ export function JobsDocumentsLocalGalleryReassign({
);
getJobMedia(jobid);
setVisible(false);
setOpen(false);
setLoading(false);
};
@@ -75,7 +75,7 @@ export function JobsDocumentsLocalGalleryReassign({
<Button type="primary" onClick={() => form.submit()}>
{t("general.actions.submit")}
</Button>
<Button onClick={() => setVisible(false)}>
<Button onClick={() => setOpen(false)}>
{t("general.actions.cancel")}
</Button>
</Space>
@@ -83,10 +83,10 @@ export function JobsDocumentsLocalGalleryReassign({
);
return (
<Popover content={popContent} open={visible}>
<Popover content={popContent} open={open}>
<Button
//disabled={selectedImages.length < 1}
onClick={() => setVisible(true)}
onClick={() => setOpen(true)}
loading={loading}
>
{t("documents.actions.reassign")}

View File

@@ -1,102 +1,90 @@
import { useQuery } from "@apollo/client";
import { Modal } from "antd";
import {useQuery} from "@apollo/client";
import {Modal} from "antd";
import React from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { QUERY_ALL_ACTIVE_JOBS } from "../../graphql/jobs.queries";
import { selectBodyshop } from "../../redux/user/user.selectors";
import {useTranslation} from "react-i18next";
import {connect} from "react-redux";
import {createStructuredSelector} from "reselect";
import {QUERY_ALL_ACTIVE_JOBS} from "../../graphql/jobs.queries";
import {selectBodyshop} from "../../redux/user/user.selectors";
import AlertComponent from "../alert/alert.component";
import LoadingSpinner from "../loading-spinner/loading-spinner.component";
import JobsFindModalComponent from "./jobs-find-modal.component";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
bodyshop: selectBodyshop,
});
export default connect(
mapStateToProps,
null
)(function JobsFindModalContainer({
bodyshop,
loading,
error,
selectedJob,
setSelectedJob,
importOptionsState,
modalSearchState,
partsQueueToggle,
setPartsQueueToggle,
...modalProps
}) {
const { t } = useTranslation();
mapStateToProps,
null
)(function JobsFindModalContainer({bodyshop, loading, error, selectedJob, setSelectedJob, importOptionsState, modalSearchState, partsQueueToggle, setPartsQueueToggle, ...modalProps }) {
const {t} = useTranslation();
const jobsList = useQuery(QUERY_ALL_ACTIVE_JOBS, {
variables: {
statuses: bodyshop.md_ro_statuses.active_statuses || ["Open"],
},
skip: !modalProps.visible,
fetchPolicy: "network-only",
nextFetchPolicy: "network-only",
});
const jobsList = useQuery(QUERY_ALL_ACTIVE_JOBS, {
variables: {
statuses: bodyshop.md_ro_statuses.active_statuses || ["Open"],
},
skip: !modalProps.open,
fetchPolicy: "network-only",
nextFetchPolicy: "network-only",
});
const modalSearch = modalSearchState[0];
const modalSearch = modalSearchState[0];
const jobsData =
jobsList.data && jobsList.data.jobs
? modalSearch
? jobsList.data.jobs.filter(
(j) =>
(j.ro_number || "")
.toLowerCase()
.includes(modalSearch.toLowerCase()) ||
(j.ownr_fn || "")
.toLowerCase()
.includes(modalSearch.toLowerCase()) ||
(j.ownr_ln || "")
.toLowerCase()
.includes(modalSearch.toLowerCase()) ||
(j.status || "")
.toLowerCase()
.includes(modalSearch.toLowerCase()) ||
(j.v_make_desc || "")
.toLowerCase()
.includes(modalSearch.toLowerCase()) ||
(j.v_model_desc || "")
.toLowerCase()
.includes(modalSearch.toLowerCase()) ||
(j.clm_no || "")
.toLowerCase()
.includes(modalSearch.toLowerCase()) ||
(j.plate_no || "")
.toLowerCase()
.includes(modalSearch.toLowerCase())
)
: jobsList.data.jobs
: null;
const jobsData =
jobsList.data && jobsList.data.jobs
? modalSearch
? jobsList.data.jobs.filter(
(j) =>
(j.ro_number || "")
.toLowerCase()
.includes(modalSearch.toLowerCase()) ||
(j.ownr_fn || "")
.toLowerCase()
.includes(modalSearch.toLowerCase()) ||
(j.ownr_ln || "")
.toLowerCase()
.includes(modalSearch.toLowerCase()) ||
(j.status || "")
.toLowerCase()
.includes(modalSearch.toLowerCase()) ||
(j.v_make_desc || "")
.toLowerCase()
.includes(modalSearch.toLowerCase()) ||
(j.v_model_desc || "")
.toLowerCase()
.includes(modalSearch.toLowerCase()) ||
(j.clm_no || "")
.toLowerCase()
.includes(modalSearch.toLowerCase()) ||
(j.plate_no || "")
.toLowerCase()
.includes(modalSearch.toLowerCase())
)
: jobsList.data.jobs
: null;
return (
<Modal
title={t("jobs.labels.existing_jobs")}
width={"80%"}
destroyOnClose
okButtonProps={{ disabled: selectedJob ? false : true }}
{...modalProps}
>
{loading ? <LoadingSpinner /> : null}
{error ? <AlertComponent message={error.message} type="error" /> : null}
{true ? (
<JobsFindModalComponent
selectedJob={selectedJob}
setSelectedJob={setSelectedJob}
importOptionsState={importOptionsState}
jobsListLoading={jobsList.loading}
jobsListRefetch={jobsList.refetch}
jobsList={jobsData}
modalSearchState={modalSearchState}
partsQueueToggle={partsQueueToggle}
setPartsQueueToggle={setPartsQueueToggle}
/>
) : null}
</Modal>
);
return (
<Modal
title={t("jobs.labels.existing_jobs")}
width={"80%"}
destroyOnClose
okButtonProps={{disabled: selectedJob ? false : true}}
{...modalProps}
>
{loading ? <LoadingSpinner/> : null}
{error ? <AlertComponent message={error.message} type="error"/> : null}
<JobsFindModalComponent
selectedJob={selectedJob}
setSelectedJob={setSelectedJob}
importOptionsState={importOptionsState}
jobsListLoading={jobsList.loading}
jobsListRefetch={jobsList.refetch}
jobsList={jobsData}
modalSearchState={modalSearchState}
partsQueueToggle={partsQueueToggle}
setPartsQueueToggle={setPartsQueueToggle}
/>
</Modal>
);
});

View File

@@ -37,7 +37,7 @@ export function LaborAllocationsAdjustmentEdit({
refetchQueryNames,
}) {
const [loading, setLoading] = useState(false);
const [visible, setVisible] = useState(false);
const [open, setOpen] = useState(false);
const [updateAdjustments] = useMutation(UPDATE_JOB);
const [form] = Form.useForm();
@@ -79,7 +79,7 @@ export function LaborAllocationsAdjustmentEdit({
});
}
setLoading(false);
setVisible(false);
setOpen(false);
};
const overlay = (
@@ -171,8 +171,8 @@ export function LaborAllocationsAdjustmentEdit({
return (
<Popover
open={visible}
onOpenChange={(vis) => setVisible(vis)}
open={open}
onOpenChange={(vis) => setOpen(vis)}
content={overlay}
trigger="click"
>

View File

@@ -33,7 +33,7 @@ export function NoteUpsertModalContainer({
const [insertNote] = useMutation(INSERT_NEW_NOTE);
const [updateNote] = useMutation(UPDATE_NOTE);
const { visible, context, actions } = noteUpsertModal;
const { open, context, actions } = noteUpsertModal;
const { jobId, existingNote, text } = context;
const { refetch } = actions;
@@ -41,16 +41,16 @@ export function NoteUpsertModalContainer({
useEffect(() => {
//Required to prevent infinite looping.
if (existingNote && visible) {
if (existingNote && open) {
form.setFieldsValue(existingNote);
} else if (!existingNote && visible) {
} else if (!existingNote && open) {
form.resetFields();
if (text) {
form.setFieldValue("text", text);
}
}
}, [existingNote, form, visible, text]);
}, [existingNote, form, open, text]);
const handleFinish = async (formValues) => {
const { relatedros, ...values } = formValues;
@@ -122,7 +122,7 @@ export function NoteUpsertModalContainer({
return (
<Modal
title={existingNote ? t("notes.actions.edit") : t("notes.actions.new")}
open={visible}
open={open}
okText={t("general.actions.save")}
onOk={() => {
form.submit();

View File

@@ -76,7 +76,8 @@ function OwnerDetailFormContainer({ owner, refetch }) {
title={t("owners.labels.deleteconfirm")}
>
<Button
type="danger"
type="primary"
danger
loading={loading}
disabled={owner.jobs.length !== 0}
>

View File

@@ -32,13 +32,13 @@ export default function OwnerFindModalContainer({
);
useEffect(() => {
if (modalProps.visible && owner) {
if (modalProps.open && owner) {
const s = OwnerNameDisplayFunction(owner, true);
setSearchText(s.trim());
callSearchowners({ variables: { search: s.trim() } });
}
}, [callSearchowners, modalProps.visible, owner]);
}, [callSearchowners, modalProps.open, owner]);
return (
<Modal

View File

@@ -50,7 +50,7 @@ export function PartsOrderModalContainer({partsOrderModal,toggleModalVisible,cur
splitKey: bodyshop.imexshopid,
});
const {visible, context, actions} = partsOrderModal;
const {open, context, actions} = partsOrderModal;
const {
jobId,
linesToOrder,
@@ -68,7 +68,7 @@ export function PartsOrderModalContainer({partsOrderModal,toggleModalVisible,cur
const sendType = sendTypeState[0];
const {loading, error, data} = useQuery(QUERY_ALL_VENDORS_FOR_ORDER, {
skip: !visible,
skip: !open,
variables: {jobId: jobId},
fetchPolicy: "network-only",
nextFetchPolicy: "network-only",
@@ -328,14 +328,14 @@ export function PartsOrderModalContainer({partsOrderModal,toggleModalVisible,cur
};
useEffect(() => {
if (visible && !!linesToOrder) {
if (open && !!linesToOrder) {
form.resetFields();
}
}, [visible, linesToOrder, form]);
}, [open, linesToOrder, form]);
return (
<Modal
open={visible}
open={open}
title={
isReturn
? `${t("parts_orders.labels.returnpartsorder")} ${invoiceNumber}`

View File

@@ -32,7 +32,7 @@ export function PartsReceiveModalContainer({
}) {
const { t } = useTranslation();
const [loading, setLoading] = useState(false);
const { visible, context, actions } = partsReceiveModal;
const { open, context, actions } = partsReceiveModal;
const { partsorderlines } = context;
const { refetch } = actions;
@@ -85,14 +85,14 @@ export function PartsReceiveModalContainer({
};
useEffect(() => {
if (visible && !!partsorderlines) {
if (open && !!partsorderlines) {
form.resetFields();
}
}, [visible, partsorderlines, form]);
}, [open, partsorderlines, form]);
return (
<Modal
open={visible}
open={open}
title={t("parts_orders.labels.receive")}
onCancel={() => toggleModalVisible()}
onOk={() => form.submit()}

View File

@@ -34,7 +34,7 @@ export function BillMarkSelectedExported({
}) {
const { t } = useTranslation();
const [loading, setLoading] = useState(false);
const [visible, setVisible] = useState(false);
const [open, setOpen] = useState(false);
const [insertExportLog] = useMutation(INSERT_EXPORT_LOG);
const [updateBill] = useMutation(gql`
mutation UPDATE_BILL($billIds: [uuid!]!) {
@@ -85,21 +85,21 @@ export function BillMarkSelectedExported({
completedCallback && completedCallback([]);
setLoading(false);
refetch && refetch();
setVisible(false);
setOpen(false);
};
return (
<Popconfirm
open={visible}
open={open}
title={t("general.labels.areyousure")}
onCancel={() => setVisible(false)}
onCancel={() => setOpen(false)}
onConfirm={handleUpdate}
disabled={disabled}
>
<Button
loading={loading}
disabled={disabled}
onClick={() => setVisible(true)}
onClick={() => setOpen(true)}
>
{t("bills.labels.markexported")}
</Button>

View File

@@ -34,7 +34,7 @@ export function PaymentMarkSelectedExported({
}) {
const { t } = useTranslation();
const [loading, setLoading] = useState(false);
const [visible, setVisible] = useState(false);
const [open, setOpen] = useState(false);
const [insertExportLog] = useMutation(INSERT_EXPORT_LOG);
const [updatePayments] = useMutation(gql`
@@ -88,21 +88,21 @@ export function PaymentMarkSelectedExported({
completedCallback && completedCallback([]);
setLoading(false);
refetch && refetch();
setVisible(false);
setOpen(false);
};
return (
<Popconfirm
open={visible}
open={open}
title={t("general.labels.areyousure")}
onCancel={() => setVisible(false)}
onCancel={() => setOpen(false)}
onConfirm={handleUpdate}
disabled={disabled}
>
<Button
loading={loading}
disabled={disabled}
onClick={() => setVisible(true)}
onClick={() => setOpen(true)}
>
{t("bills.labels.markexported")}
</Button>

View File

@@ -46,7 +46,7 @@ function PaymentModalContainer({
const [updatePayment] = useMutation(UPDATE_PAYMENT);
const { t } = useTranslation();
const { context, actions, visible } = paymentModal;
const { context, actions, open } = paymentModal;
const [loading, setLoading] = useState(false);
@@ -130,12 +130,12 @@ function PaymentModalContainer({
};
useEffect(() => {
if (visible) {
if (open) {
form.resetFields();
form.resetFields();
form.setFieldsValue(context);
}
}, [visible, form, context]);
}, [open, form, context]);
useEffect(() => {
if (enterAgain) form.submit();
@@ -148,7 +148,7 @@ function PaymentModalContainer({
? t("payments.labels.new")
: t("payments.labels.edit")
}
open={visible}
open={open}
destroyOnClose
okText={t("general.actions.save")}
onOk={() => form.submit()}

View File

@@ -36,7 +36,7 @@ export function PaymentsGenerateLink({
const { t } = useTranslation();
const [form] = Form.useForm();
const [visible, setVisible] = useState(false);
const [open, setOpen] = useState(false);
const [loading, setLoading] = useState(false);
const [paymentLink, setPaymentLink] = useState(null);
@@ -69,7 +69,7 @@ export function PaymentsGenerateLink({
//Add in confirmation & errors.
if (callback) callback();
// setVisible(false);
// setOpen(false);
setLoading(false);
};
@@ -137,7 +137,7 @@ export function PaymentsGenerateLink({
onClick={() => {
form.resetFields();
setPaymentLink(null);
setVisible(false);
setOpen(false);
}}
>
{t("general.actions.cancel")}
@@ -147,8 +147,8 @@ export function PaymentsGenerateLink({
);
return (
<Popover content={popContent} open={visible}>
<Button onClick={() => setVisible(true)} loading={loading}>
<Popover content={popContent} open={open}>
<Button onClick={() => setOpen(true)} loading={loading}>
{t("payments.actions.generatepaymentlink")}
</Button>
</Popover>

View File

@@ -65,7 +65,8 @@ export function PhonebookFormComponent({
{t("general.actions.save")}
</Button>
<Button
type="danger"
type="primary"
danger
disabled={hasNoAccess}
onClick={handleDelete}
loading={formLoading}

View File

@@ -22,13 +22,13 @@ export function PrintCenterModalContainer({
}) {
const { t } = useTranslation();
const { visible, context } = printCenterModal;
const { open, context } = printCenterModal;
//const { type } = context;
// const { refetch } = actions;
return (
<Modal
open={visible}
open={open}
onOk={() => toggleModalVisible()}
onCancel={() => toggleModalVisible()}
cancelButtonProps={{ style: { display: "none" } }}

View File

@@ -17,7 +17,7 @@ export default function ProductionBoardKanbanCardSettings({
associationSettings,
}) {
const [form] = Form.useForm();
const [visible, setVisible] = useState(false);
const [open, setOpen] = useState(false);
const [loading, setLoading] = useState(false);
const [updateKbSettings] = useMutation(UPDATE_KANBAN_SETTINGS);
@@ -25,7 +25,7 @@ export default function ProductionBoardKanbanCardSettings({
form.setFieldsValue(
associationSettings && associationSettings.kanban_settings
);
}, [form, associationSettings, visible]);
}, [form, associationSettings, open]);
const { t } = useTranslation();
@@ -45,7 +45,7 @@ export default function ProductionBoardKanbanCardSettings({
}),
});
}
setVisible(false);
setOpen(false);
setLoading(false);
};
@@ -173,8 +173,8 @@ export default function ProductionBoardKanbanCardSettings({
</div>
);
return (
<Popover content={overlay} open={visible} placement="topRight">
<Button loading={loading} onClick={() => setVisible(true)}>
<Popover content={overlay} open={open} placement="topRight">
<Button loading={loading} onClick={() => setOpen(true)}>
{t("production.labels.cardsettings")}
</Button>
</Popover>

View File

@@ -10,13 +10,13 @@ export default function ProductionListColumnComment({ record }) {
const [note, setNote] = useState(record.comment || "");
const [visible, setVisible] = useState(false);
const [open, setOpen] = useState(false);
const [updateAlert] = useMutation(UPDATE_JOB);
const handleSaveNote = (e) => {
e.stopPropagation();
setVisible(false);
setOpen(false);
updateAlert({
variables: {
jobId: record.id,
@@ -34,15 +34,15 @@ export default function ProductionListColumnComment({ record }) {
setNote(e.target.value);
};
const handleVisibleChange = (flag) => {
setVisible(flag);
const handleOpenChange = (flag) => {
setOpen(flag);
if (flag) setNote(record.comment || "");
};
return (
<Popover
onOpenChange={handleVisibleChange}
open={visible}
onOpenChange={handleOpenChange}
open={open}
content={
<div style={{ width: "30em" }}>
<Input.TextArea

View File

@@ -1,102 +1,111 @@
import { useMutation } from "@apollo/client";
import { Button, Card, Dropdown, TimePicker } from "antd";
import {useMutation} from "@apollo/client";
import {Button, Card, Dropdown, TimePicker} from "antd";
import dayjs from "../../utils/day";
import React, { useState } from "react";
import { useTranslation } from "react-i18next";
import { logImEXEvent } from "../../firebase/firebase.utils";
import { UPDATE_JOB } from "../../graphql/jobs.queries";
import { DateFormatter } from "../../utils/DateFormatter";
import React, {useState} from "react";
import {useTranslation} from "react-i18next";
import {logImEXEvent} from "../../firebase/firebase.utils";
import {UPDATE_JOB} from "../../graphql/jobs.queries";
import {DateFormatter} from "../../utils/DateFormatter";
import FormDatePicker from "../form-date-picker/form-date-picker.component";
export default function ProductionListDate({
record,
field,
time,
pastIndicator,
}) {
const [updateAlert] = useMutation(UPDATE_JOB);
const [visible, setVisible] = useState(false);
const { t } = useTranslation();
record,
field,
time,
pastIndicator,
}) {
const [updateAlert] = useMutation(UPDATE_JOB);
const [open, setOpen] = useState(false);
const {t} = useTranslation();
const handleChange = (date) => {
logImEXEvent("product_toggle_date", { field });
// if (date.isSame(record[field] && dayjs(record[field]))) {
// return;
// }
const handleChange = (date) => {
logImEXEvent("product_toggle_date", {field});
// if (date.isSame(record[field] && dayjs(record[field]))) {
// return;
// }
//e.stopPropagation();
//e.stopPropagation();
updateAlert({
variables: {
jobId: record.id,
job: {
[field]: date,
},
},
optimisticResponse: {
update_jobs: {
[field]: date,
},
},
}).then(() => {
if (record.refetch) record.refetch();
if (!time) {
setVisible(false);
}
});
};
updateAlert({
variables: {
jobId: record.id,
job: {
[field]: date,
},
},
optimisticResponse: {
update_jobs: {
[field]: date,
},
},
}).then(() => {
if (record.refetch) record.refetch();
if (!time) {
setOpen(false);
}
});
};
let className = "";
if (pastIndicator) {
className =
!!record[field] &&
((dayjs().isSameOrAfter(dayjs(record[field]), "day") &&
"production-completion-past") ||
(dayjs().add(1, "day").isSame(dayjs(record[field]), "day") &&
"production-completion-soon"));
}
// TODO - Client Update = Why is the overlay a card?
return (
<Dropdown
trigger={["click"]}
onOpenChange={(v) => setVisible(v)}
open={visible}
style={{
height: "19px",
}}
overlay={
<Card style={{ padding: "1rem" }} onClick={(e) => e.stopPropagation()}>
<FormDatePicker
onClick={(e) => e.stopPropagation()}
value={(record[field] && dayjs(record[field])) || null}
onChange={handleChange}
format="MM/DD/YYYY"
isDateOnly={!time}
/>
{time && (
<TimePicker
onClick={(e) => e.stopPropagation()}
value={(record[field] && dayjs(record[field])) || null}
onChange={handleChange}
minuteStep={15}
format="hh:mm a"
/>
)}
<Button onClick={() => setVisible(false)}>
{t("general.actions.close")}
</Button>
</Card>
}
>
<div
onClick={() => setVisible(true)}
style={{
height: "19px",
}}
className={className}
>
<DateFormatter bordered={false}>{record[field]}</DateFormatter>
</div>
</Dropdown>
);
let className = "";
if (pastIndicator) {
className =
!!record[field] &&
((dayjs().isSameOrAfter(dayjs(record[field]), "day") &&
"production-completion-past") ||
(dayjs().add(1, "day").isSame(dayjs(record[field]), "day") &&
"production-completion-soon"));
}
// TODO - Client Update = Why is the overlay a card?
const overlayMenu = {
items: [
{
key: 'overlayItem1',
label:
<Card style={{padding: "1rem"}} onClick={(e) => e.stopPropagation()}>
<FormDatePicker
onClick={(e) => e.stopPropagation()}
value={(record[field] && dayjs(record[field])) || null}
onChange={handleChange}
format="MM/DD/YYYY"
isDateOnly={!time}
/>
{time && (
<TimePicker
onClick={(e) => e.stopPropagation()}
value={(record[field] && dayjs(record[field])) || null}
onChange={handleChange}
minuteStep={15}
format="hh:mm a"
/>
)}
<Button onClick={() => setOpen(false)}>
{t("general.actions.close")}
</Button>
</Card>
}
]
}
return (
<Dropdown
trigger={["click"]}
onOpenChange={(v) => setOpen(v)}
open={open}
style={{
height: "19px",
}}
menu={overlayMenu}
>
<div
onClick={() => setOpen(true)}
style={{
height: "19px",
}}
className={className}
>
<DateFormatter bordered={false}>{record[field]}</DateFormatter>
</div>
</Dropdown>
);
}

View File

@@ -26,7 +26,7 @@ export default connect(
export function ProductionLastContacted({ currentUser, record }) {
const [updateAlert] = useMutation(UPDATE_JOB);
const [insertNote] = useMutation(INSERT_NEW_NOTE);
const [visible, setVisible] = useState(false);
const [open, setOpen] = useState(false);
const { t } = useTranslation();
const [form] = Form.useForm();
const handleFinish = async ({
@@ -76,63 +76,70 @@ export function ProductionLastContacted({ currentUser, record }) {
}
if (record.refetch) record.refetch();
setVisible(false);
setOpen(false);
};
useEffect(() => {
if (visible) {
if (open) {
form.setFieldsValue({
note: null,
date_last_contacted:
record.date_last_contacted && dayjs(record.date_last_contacted),
});
}
}, [visible, form, record.date_last_contacted]);
}, [open, form, record.date_last_contacted]);
const overlayMenu = {
items: [
{
key: 'overlay-item-1',
label:
<Card
style={{ padding: "1rem" }}
onClick={(e) => e.stopPropagation()}
>
<Form form={form} onFinish={handleFinish} layout="vertical">
<Form.Item
name="date_last_contacted"
label={t("jobs.fields.date_last_contacted")}
>
<FormDateTimePickerComponent />
</Form.Item>
<Form.Item
name="date_next_contact"
label={t("jobs.fields.date_next_contact")}
>
<FormDateTimePickerComponent />
</Form.Item>
<Form.Item label={t("notes.labels.notetoadd")} name="note">
<Input.TextArea rows={4} />
</Form.Item>
<Space>
<Button type="primary" htmlType="submit">
{t("general.actions.save")}
</Button>
<Button onClick={() => setOpen(false)}>
{t("general.actions.close")}
</Button>
</Space>
</Form>
</Card>
}
]
}
// TODO - Client Update - Why is this a card?
return (
<div>
<Dropdown
//trigger={["click"]}
open={visible}
open={open}
style={{
height: "19px",
}}
overlay={
<Card
style={{ padding: "1rem" }}
onClick={(e) => e.stopPropagation()}
>
<Form form={form} onFinish={handleFinish} layout="vertical">
<Form.Item
name="date_last_contacted"
label={t("jobs.fields.date_last_contacted")}
>
<FormDateTimePickerComponent />
</Form.Item>
<Form.Item
name="date_next_contact"
label={t("jobs.fields.date_next_contact")}
>
<FormDateTimePickerComponent />
</Form.Item>
<Form.Item label={t("notes.labels.notetoadd")} name="note">
<Input.TextArea rows={4} />
</Form.Item>
<Space>
<Button type="primary" htmlType="submit">
{t("general.actions.save")}
</Button>
<Button onClick={() => setVisible(false)}>
{t("general.actions.close")}
</Button>
</Space>
</Form>
</Card>
}
menu={overlayMenu}
>
<div
onClick={() => setVisible(true)}
onClick={() => setOpen(true)}
style={{
height: "19px",
}}

View File

@@ -24,14 +24,14 @@ function ProductionListColumnProductionNote({ record, setNoteUpsertContext }) {
(record.production_vars && record.production_vars.note) || ""
);
const [visible, setVisible] = useState(false);
const [open, setOpen] = useState(false);
const [updateAlert] = useMutation(UPDATE_JOB);
const handleSaveNote = (e) => {
logImEXEvent("production_add_note");
e.stopPropagation();
setVisible(false);
setOpen(false);
updateAlert({
variables: {
jobId: record.id,
@@ -52,16 +52,16 @@ function ProductionListColumnProductionNote({ record, setNoteUpsertContext }) {
setNote(e.target.value);
};
const handleVisibleChange = (flag) => {
setVisible(flag);
const handleOpenChange = (flag) => {
setOpen(flag);
if (flag)
setNote((record.production_vars && record.production_vars.note) || "");
};
return (
<Popover
onOpenChange={handleVisibleChange}
open={visible}
onOpenChange={handleOpenChange}
open={open}
content={
<div style={{ width: "30em" }}>
<Input.TextArea
@@ -79,7 +79,7 @@ function ProductionListColumnProductionNote({ record, setNoteUpsertContext }) {
</Button>
<Button
onClick={() => {
setVisible(false);
setOpen(false);
setNoteUpsertContext({
context: {
jobId: record.id,

View File

@@ -23,7 +23,7 @@ export function ProductionListSaveConfigButton({
}) {
const [updateShop] = useMutation(UPDATE_SHOP);
const [loading, setLoading] = useState(false);
const [visible, setVisible] = useState(false);
const [open, setOpen] = useState(false);
const [form] = Form.useForm();
const { t } = useTranslation();
@@ -61,7 +61,7 @@ export function ProductionListSaveConfigButton({
});
}
form.resetFields();
setVisible(false);
setOpen(false);
setLoading(false);
};
const popMenu = (
@@ -76,10 +76,10 @@ export function ProductionListSaveConfigButton({
</Form.Item>
<Space wrap>
<Button type="danger" onClick={() => form.submit()} loading={loading}>
<Button type="primary" danger onClick={() => form.submit()} loading={loading}>
{t("general.actions.save")}
</Button>
<Button onClick={() => setVisible(false)}>
<Button onClick={() => setOpen(false)}>
{t("general.actions.close")}
</Button>
</Space>
@@ -88,8 +88,8 @@ export function ProductionListSaveConfigButton({
);
return (
<Popover open={visible} content={popMenu}>
<Button loading={loading} onClick={() => setVisible(true)}>
<Popover open={open} content={popMenu}>
<Button loading={loading} onClick={() => setOpen(true)}>
{t("production.actions.saveconfig")}
</Button>
</Popover>

View File

@@ -46,12 +46,12 @@ export function ReportCenterModalComponent({ reportCenterModal }) {
const ReportsList = Object.keys(Templates).map((key) => {
return Templates[key];
});
const { visible } = reportCenterModal;
const { open } = reportCenterModal;
const [callVendorQuery, { data: vendorData, called: vendorCalled }] =
useLazyQuery(QUERY_ALL_VENDORS, {
skip: !(
visible &&
open &&
Templates[form.getFieldValue("key")] &&
Templates[form.getFieldValue("key")].idtype
),
@@ -60,7 +60,7 @@ export function ReportCenterModalComponent({ reportCenterModal }) {
const [callEmployeeQuery, { data: employeeData, called: employeeCalled }] =
useLazyQuery(QUERY_ACTIVE_EMPLOYEES, {
skip: !(
visible &&
open &&
Templates[form.getFieldValue("key")] &&
Templates[form.getFieldValue("key")].idtype
),

View File

@@ -22,11 +22,11 @@ export function ReportCenterModalContainer({
}) {
const { t } = useTranslation();
const { visible } = reportCenterModal;
const { open } = reportCenterModal;
return (
<Modal
open={visible}
open={open}
title={t("printcenter.labels.reportcentermodal")}
onOk={() => toggleModalVisible()}
onCancel={() => toggleModalVisible()}

View File

@@ -37,6 +37,7 @@ export function ScheduleCalendarHeaderComponent({
events,
...otherProps
}) {
console.log(`ScheduleCalendarHeaderComponent: ${label} Calculating: ${calculating}`)
const ATSToday = useMemo(() => {
if (!events) return [];
return _.groupBy(

View File

@@ -45,7 +45,7 @@ export function ScheduleJobModalContainer({
currentUser,
insertAuditTrail,
}) {
const { visible, context, actions } = scheduleModal;
const { open, context, actions } = scheduleModal;
const { jobId, job, previousEvent } = context;
const { refetch } = actions;
@@ -73,7 +73,7 @@ export function ScheduleJobModalContainer({
variables: { jobid: jobId },
fetchPolicy: "network-only",
nextFetchPolicy: "network-only",
skip: !visible || !!!jobId,
skip: !open || !!!jobId,
});
useEffect(() => {
@@ -129,7 +129,7 @@ export function ScheduleJobModalContainer({
jobid: jobId,
bodyshopid: bodyshop.id,
start: dayjs(values.start),
end: dayjs(values.start).add(bodyshop.appt_length || 60, "minutes"),
end: dayjs(values.start).add(bodyshop.appt_length || 60, "minute"),
color: values.color,
note: values.note,
created_by: currentUser.email,
@@ -206,7 +206,7 @@ export function ScheduleJobModalContainer({
return (
<Modal
open={visible}
open={open}
onCancel={() => toggleModalVisible()}
onOk={() => form.submit()}
width={"90%"}

View File

@@ -6,7 +6,7 @@ import { UPDATE_SCOREBOARD_ENTRY } from "../../graphql/scoreboard.queries";
import FormDatePicker from "../form-date-picker/form-date-picker.component";
export default function ScoreboardEntryEdit({ entry }) {
const [visible, setVisible] = useState(false);
const [open, setOpen] = useState(false);
const [loading, setLoading] = useState(false);
const { t } = useTranslation();
const [updateScoreboardentry] = useMutation(UPDATE_SCOREBOARD_ENTRY);
@@ -28,7 +28,7 @@ export default function ScoreboardEntryEdit({ entry }) {
notification["success"]({
message: t("scoreboard.successes.updated"),
});
setVisible(false);
setOpen(false);
}
setLoading(false);
};
@@ -81,7 +81,7 @@ export default function ScoreboardEntryEdit({ entry }) {
<Button type="primary" loading={loading} htmlType="submit">
{t("general.actions.save")}
</Button>
<Button onClick={() => setVisible(false)}>
<Button onClick={() => setOpen(false)}>
{t("general.actions.cancel")}
</Button>
</Form>
@@ -92,11 +92,11 @@ export default function ScoreboardEntryEdit({ entry }) {
return (
<div>
<Dropdown open={visible} overlay={popContent}>
<Dropdown open={open} overlay={popContent}>
<Button
onClick={(e) => {
e.stopPropagation();
setVisible(true);
setOpen(true);
}}
>
{t("scoreboard.actions.edit")}

View File

@@ -14,7 +14,7 @@ import {pageLimit} from "../../utils/config";
export default function ScoreboardJobsList({ scoreBoardlist }) {
const { t } = useTranslation();
const [state, setState] = useState({
visible: false,
open: false,
search: "",
current: 1,
pageSize: pageLimit,
@@ -25,7 +25,7 @@ export default function ScoreboardJobsList({ scoreBoardlist }) {
{
fetchPolicy: "network-only",
nextFetchPolicy: "network-only",
skip: !state.visible,
skip: !state.open,
variables: {
search: state.search !== "" ? `%${state.search}%` : null,
offset: state.current ? (state.current - 1) * state.pageSize : 0,
@@ -101,14 +101,14 @@ export default function ScoreboardJobsList({ scoreBoardlist }) {
return (
<>
<Modal
open={state.visible}
open={state.open}
destroyOnClose
width="80%"
cancelButtonProps={{ style: { display: "none" } }}
onCancel={() =>
setState((state) => ({
...state,
visible: false,
open: false,
current: 1,
search: "",
}))
@@ -157,7 +157,7 @@ export default function ScoreboardJobsList({ scoreBoardlist }) {
</Card>
</Modal>
<Button
onClick={() => setState((state) => ({ ...state, visible: true }))}
onClick={() => setState((state) => ({ ...state, open: true }))}
>
{t("scoreboard.labels.entries")}
</Button>

View File

@@ -20,7 +20,7 @@ export function ScoreboardLastDays({ bodyshop, sbEntriesByDate }) {
const ArrayOfDate = [];
for (var i = lastNumberWorkingDays - 1; i >= 0; i--) {
ArrayOfDate.push(dayjs().businessDaysSubtract(i, "day").format("yyyy-MM-DD"));
ArrayOfDate.push(dayjs().businessDaysSubtract(i, "day").format("YYYY-MM-DD"));
}
return (

View File

@@ -11,8 +11,8 @@ import { TemplateList } from "../../utils/TemplateConstants";
import ShopTemplateAdd from "../shop-template-add/shop-template-add.component";
import ShopTemplateDeleteComponent from "../shop-template-delete/shop-template-delete.component";
export default function ShopTemplatesListContainer({ visibleState }) {
const [visible, setVisible] = visibleState;
export default function ShopTemplatesListContainer({ openState }) {
const [open, setOpen] = openState;
const { loading, error, data, refetch } = useQuery(QUERY_CUSTOM_TEMPLATES, {
fetchPolicy: "network-only",
nextFetchPolicy: "network-only",
@@ -38,8 +38,8 @@ export default function ShopTemplatesListContainer({ visibleState }) {
(<Drawer
placement="left"
width="25%"
open={visible}
onClose={() => setVisible(false)}
open={open}
onClose={() => setOpen(false)}
>
<div>
<div>{t("bodyshop.labels.customtemplates")}</div>

View File

@@ -7,11 +7,11 @@ import { UPDATE_ASSOCIATION } from "../../graphql/user.queries";
export default function ShopUsersAuthEdit({ association }) {
const { t } = useTranslation();
const [updateAssociation] = useMutation(UPDATE_ASSOCIATION);
const [visible, setVisible] = useState(false);
const [open, setOpen] = useState(false);
const [value, setValue] = useState(association.authlevel);
const handleSave = async () => {
setVisible(false);
setOpen(false);
const result = await updateAssociation({
variables: {
assocId: association.id,
@@ -30,7 +30,7 @@ export default function ShopUsersAuthEdit({ association }) {
return (
<div>
{visible && (
{open && (
<div>
<InputNumber
min={0}
@@ -41,10 +41,8 @@ export default function ShopUsersAuthEdit({ association }) {
/>
</div>
)}
{!visible && (
<div
style={{ cursor: "pointer" }} //onClick={() => setVisible(true)}
>
{!open && (
<div style={{ cursor: "pointer" }}>
{association.authlevel || t("general.labels.na")}
</div>
)}

View File

@@ -37,7 +37,7 @@ export function TimeTicketModalContainer({
const [updateTicket] = useMutation(UPDATE_TIME_TICKET);
const { data: EmployeeAutoCompleteData } = useQuery(QUERY_ACTIVE_EMPLOYEES, {
skip: !timeTicketModal.visible,
skip: !timeTicketModal.open,
fetchPolicy: "network-only",
nextFetchPolicy: "network-only",
});
@@ -127,8 +127,8 @@ export function TimeTicketModalContainer({
}, [enterAgain, form]);
useEffect(() => {
if (timeTicketModal.visible) form.resetFields();
}, [timeTicketModal.visible, form]);
if (timeTicketModal.open) form.resetFields();
}, [timeTicketModal.open, form]);
const handleFieldsChange = (changedFields, allFields) => {
if (!!changedFields.employeeid && !!EmployeeAutoCompleteData) {
@@ -169,7 +169,7 @@ export function TimeTicketModalContainer({
: t("timetickets.labels.new")
}
width={"90%"}
open={timeTicketModal.visible}
open={timeTicketModal.open}
forceRender
onCancel={handleCancel}
afterClose={() => form.resetFields()}

View File

@@ -68,13 +68,15 @@ function VehicleDetailFormContainer({ vehicle, refetch }) {
title={t("menus.header.vehicles")}
extra={[
<Popconfirm
key="delete"
trigger="click"
onConfirm={handleDelete}
disabled={vehicle.jobs.length !== 0}
title={t("vehicles.labels.deleteconfirm")}
>
<Button
type="danger"
type="primary"
danger
loading={loading}
disabled={vehicle.jobs.length !== 0}
>
@@ -82,6 +84,7 @@ function VehicleDetailFormContainer({ vehicle, refetch }) {
</Button>
</Popconfirm>,
<Button
key="save"
type="primary"
loading={loading}
onClick={() => form.submit()}

View File

@@ -64,7 +64,8 @@ export function VendorsFormComponent({bodyshop, form, formLoading, handleDelete,
{t("general.actions.save")}
</Button>
<Button
type="danger"
type="primary"
danger
disabled={selectedvendor === "new"}
onClick={handleDelete}
loading={formLoading}

View File

@@ -178,7 +178,7 @@ export function JobsCloseComponent({ job, bodyshop, jobRO, insertAuditTrail, })
cancelText={t("general.labels.no")}
title={t("jobs.labels.closeconfirm")}
>
<Button loading={loading} type="danger" disabled={jobRO}>
<Button loading={loading} type="primary" danger disabled={jobRO}>
{t("general.actions.close")}
</Button>
</Popconfirm>

View File

@@ -1,6 +1,6 @@
import {FloatButton, Layout} from "antd";
import preval from "preval.macro";
import React, {lazy, Suspense, useEffect} from "react";
import React, {lazy, Suspense, useEffect, useState} from "react";
import {useTranslation} from "react-i18next";
import {connect} from "react-redux";
import {Link, Route, Routes} from "react-router-dom";
@@ -177,6 +177,8 @@ const mapStateToProps = createStructuredSelector({
export function Manage({conflict, bodyshop}) {
const {t} = useTranslation();
const [chatVisible] = useState(false);
useEffect(() => {
const widgetId = "IABVNO4scRKY11XBQkNr";
@@ -360,7 +362,7 @@ export function Manage({conflict, bodyshop}) {
return (
<>
<ChatAffixContainer/>
<ChatAffixContainer bodyshop={bodyshop} chatVisible={chatVisible} />
<Layout className="layout-container">
<UpdateAlert/>
<HeaderContainer/>

View File

@@ -42,7 +42,7 @@
// return (
// <RbacWrapper action="shop:templates">
// <div>
// <ShopTemplatesListContainer visibleState={drawerVisibility} />
// <ShopTemplatesListContainer openState={drawerVisibility} />
// <Button onClick={() => drawerVisibility[1](true)}>Show List</Button>
// <ShopTemplateEditor />
// </div>

View File

@@ -121,7 +121,7 @@ export function* calculateScheduleLoad({ payload: end }) {
}
const itemDate = dayjs(item.actual_in || item.scheduled_in).format(
"yyyy-MM-DD"
"YYYY-MM-DD"
);
const AddJobForSchedulingCalc = !item.inproduction;
@@ -171,7 +171,7 @@ export function* calculateScheduleLoad({ payload: end }) {
const itemDate = dayjs(
item.actual_completion || item.scheduled_completion
).format("yyyy-MM-DD");
).format("YYYY-MM-DD");
//Skip it, it's already completed.
if (!!load[itemDate]) {
@@ -209,10 +209,10 @@ export function* calculateScheduleLoad({ payload: end }) {
const range = Math.round(dayjs.duration(end.diff(today)).asDays()) + 1;
for (var day = 0; day < range; day++) {
const current = dayjs(today).add(day, "day").format("yyyy-MM-DD");
const current = dayjs(today).add(day, "day").format("YYYY-MM-DD");
const prev = dayjs(today)
.add(day - 1, "day")
.format("yyyy-MM-DD");
.format("YYYY-MM-DD");
if (!!!load[current]) {
load[current] = {};
}

View File

@@ -10,7 +10,7 @@ const INITIAL_STATE = {
template: { name: null, variables: {} },
},
visible: false,
open: false,
error: null,
};
@@ -19,13 +19,13 @@ const emailReducer = (state = INITIAL_STATE, action) => {
case EmailActionTypes.TOGGLE_EMAIL_OVERLAY_VISIBLE:
return {
...state,
visible: !state.visible,
open: !state.open,
};
case EmailActionTypes.SET_EMAIL_OPTIONS:
return {
...state,
emailConfig: { ...action.payload },
visible: true,
open: true,
};
default:
return state;

View File

@@ -4,7 +4,7 @@ const selectEmail = (state) => state.email;
export const selectEmailVisible = createSelector(
[selectEmail],
(email) => email.visible
(email) => email.open
);
export const selectEmailConfig = createSelector(

View File

@@ -1,7 +1,7 @@
import MessagingActionTypes from "./messaging.types";
const INITIAL_STATE = {
visible: false,
open: false,
selectedConversationId: null,
isSending: false,
error: null,
@@ -16,7 +16,7 @@ const messagingReducer = (state = INITIAL_STATE, action) => {
case MessagingActionTypes.TOGGLE_CHAT_VISIBLE:
return {
...state,
visible: !state.visible,
open: !state.open,
};
case MessagingActionTypes.OPEN_CHAT_BY_PHONE:
return {
@@ -26,7 +26,7 @@ const messagingReducer = (state = INITIAL_STATE, action) => {
case MessagingActionTypes.SET_SELECTED_CONVERSATION:
return {
...state,
visible: true,
open: true,
searchingForConversation: false,
selectedConversationId: action.payload,
};

View File

@@ -4,7 +4,7 @@ const selectMessaging = (state) => state.messaging;
export const selectChatVisible = createSelector(
[selectMessaging],
(messaging) => messaging.visible
(messaging) => messaging.open
);
export const selectIsSending = createSelector(

View File

@@ -1,7 +1,7 @@
import ModalsActionTypes from "./modals.types";
const baseModal = {
visible: false,
open: false,
context: {},
actions: {
refetch: null,
@@ -35,7 +35,7 @@ const modalsReducer = (state = INITIAL_STATE, action) => {
...state,
[action.payload]: {
...state[action.payload],
visible: !state[action.payload].visible,
open: !state[action.payload].open,
},
};
case ModalsActionTypes.SET_MODAL_CONTEXT:
@@ -44,7 +44,7 @@ const modalsReducer = (state = INITIAL_STATE, action) => {
[action.payload.modal]: {
...state[action.payload.modal],
...action.payload.context,
visible: true,
open: true,
},
};
default:

View File

@@ -1,12 +1,6 @@
import { configureStore } from '@reduxjs/toolkit';
import {
persistStore,
FLUSH,
REHYDRATE,
PAUSE,
PERSIST,
PURGE,
REGISTER
} from "redux-persist";
import { createLogger } from "redux-logger";
import createSagaMiddleware from "redux-saga";
@@ -42,9 +36,7 @@ if (process.env.NODE_ENV === "development") {
export const store = configureStore({
reducer: rootReducer,
middleware: (getDefaultMiddleware) => getDefaultMiddleware({
serializableCheck: {
ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER],
},
serializableCheck: false,
}).concat(middlewares),
// middleware: middlewares,
devTools: process.env.NODE_ENV !== 'production',

View File

@@ -0,0 +1,35 @@
export const BETA_KEY = 'betaSwitchImex';
export const checkBeta = () => {
const cookie = document.cookie.split('; ').find(row => row.startsWith(BETA_KEY));
return cookie ? cookie.split('=')[1] === 'true' : false;
}
export const setBeta = (value) => {
const domain = window.location.hostname.split('.').slice(-2).join('.');
document.cookie = `${BETA_KEY}=${value}; path=/; domain=.${domain}`;
}
export const handleBeta = () => {
// If the current host name does not start with beta or test, then we don't need to do anything.
if (window.location.hostname.startsWith('localhost')) {
console.log('Not on beta or test, so no need to handle beta.');
return;
}
const isBeta = checkBeta();
const currentHostName = window.location.hostname;
// Beta is enabled, but the current host name does start with beta.
if (isBeta && !currentHostName.startsWith('beta')) {
window.location.href = `${window.location.protocol}//beta.${currentHostName}${window.location.pathname}${window.location.search}${window.location.hash}`;
}
// Beta is not enabled, but the current host name does start with beta.
else if (!isBeta && currentHostName.startsWith('beta')) {
window.location.href = `${window.location.protocol}//${currentHostName.replace('beta.', '')}${window.location.pathname}${window.location.search}${window.location.hash}`;
}
}
export default handleBeta;

View File

@@ -1,129 +1,128 @@
import { useEffect, useCallback, useReducer } from "react";
import {useCallback, useEffect, useReducer, useState} from "react";
//Based on https://www.fullstacklabs.co/blog/keyboard-shortcuts-with-react-hooks
const blacklistedTargets = []; // ["INPUT", "TEXTAREA"];
export const useKeyboardSaveShortcut = (callback) =>
useKeyboardShortcut(["Control", "S"], callback, { overrideSystem: true });
useKeyboardShortcut(["Control", "S"], callback, {overrideSystem: true});
const keysReducer = (state, action) => {
switch (action.type) {
case "set-key-down":
const keydownState = { ...state, [action.key]: true };
return keydownState;
case "set-key-up":
const keyUpState = { ...state, [action.key]: false };
return keyUpState;
case "reset-keys":
const resetState = { ...action.data };
return resetState;
default:
return state;
}
switch (action.type) {
case "set-key-down":
const keydownState = {...state, [action.key]: true};
return keydownState;
case "set-key-up":
const keyUpState = {...state, [action.key]: false};
return keyUpState;
case "reset-keys":
const resetState = {...action.data};
return resetState;
default:
return state;
}
};
const useKeyboardShortcut = (shortcutKeys, callback, options) => {
if (!Array.isArray(shortcutKeys))
throw new Error(
"The first parameter to `useKeyboardShortcut` must be an ordered array of `KeyboardEvent.key` strings."
if (!Array.isArray(shortcutKeys))
throw new Error(
"The first parameter to `useKeyboardShortcut` must be an ordered array of `KeyboardEvent.key` strings."
);
if (!shortcutKeys.length)
throw new Error(
"The first parameter to `useKeyboardShortcut` must contain atleast one `KeyboardEvent.key` string."
);
if (!callback || typeof callback !== "function")
throw new Error(
"The second parameter to `useKeyboardShortcut` must be a function that will be envoked when the keys are pressed."
);
const {overrideSystem} = options || {};
const initalKeyMapping = shortcutKeys.reduce((currentKeys, key) => {
currentKeys[key.toLowerCase()] = false;
return currentKeys;
}, {});
const [keys, setKeys] = useReducer(keysReducer, initalKeyMapping);
const [listenersAdded, setListenersAdded] = useState(false);
const keydownListener = useCallback(
(assignedKey) => (keydownEvent) => {
const loweredKey = assignedKey.toLowerCase();
if (keydownEvent.repeat) return;
if (blacklistedTargets.includes(keydownEvent.target.tagName)) return;
if (loweredKey !== keydownEvent.key.toLowerCase()) return;
if (keys[loweredKey] === undefined) return;
if (overrideSystem) {
keydownEvent.preventDefault();
disabledEventPropagation(keydownEvent);
}
setKeys({type: "set-key-down", key: loweredKey});
return false;
},
[keys, overrideSystem]
);
if (!shortcutKeys.length)
throw new Error(
"The first parameter to `useKeyboardShortcut` must contain atleast one `KeyboardEvent.key` string."
const keyupListener = useCallback(
(assignedKey) => (keyupEvent) => {
const raisedKey = assignedKey.toLowerCase();
if (blacklistedTargets.includes(keyupEvent.target.tagName)) return;
if (keyupEvent.key.toLowerCase() !== raisedKey) return;
if (keys[raisedKey] === undefined) return;
if (overrideSystem) {
keyupEvent.preventDefault();
disabledEventPropagation(keyupEvent);
}
setKeys({type: "set-key-up", key: raisedKey});
return false;
},
[keys, overrideSystem]
);
if (!callback || typeof callback !== "function")
throw new Error(
"The second parameter to `useKeyboardShortcut` must be a function that will be envoked when the keys are pressed."
);
useEffect(() => {
if (!Object.values(keys).filter((value) => !value).length) {
callback(keys);
setKeys({type: "reset-keys", data: initalKeyMapping});
} else {
setKeys({type: null});
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [callback, keys]);
const { overrideSystem } = options || {};
const initalKeyMapping = shortcutKeys.reduce((currentKeys, key) => {
currentKeys[key.toLowerCase()] = false;
return currentKeys;
}, {});
useEffect(() => {
if (!listenersAdded) {
console.log('Added events for keyup and keydown');
shortcutKeys.forEach((k) => {
window.addEventListener("keydown", keydownListener(k));
window.addEventListener("keyup", keyupListener(k))
});
}
const [keys, setKeys] = useReducer(keysReducer, initalKeyMapping);
setListenersAdded(true);
const keydownListener = useCallback(
(assignedKey) => (keydownEvent) => {
const loweredKey = assignedKey.toLowerCase();
return () => {
shortcutKeys.forEach((k) => {
window.removeEventListener("keydown", keydownListener(k));
window.removeEventListener("keyup", keyupListener(k));
});
}
}, [listenersAdded]);
if (keydownEvent.repeat) return;
if (blacklistedTargets.includes(keydownEvent.target.tagName)) return;
if (loweredKey !== keydownEvent.key.toLowerCase()) return;
if (keys[loweredKey] === undefined) return;
if (overrideSystem) {
keydownEvent.preventDefault();
disabledEventPropagation(keydownEvent);
}
setKeys({ type: "set-key-down", key: loweredKey });
return false;
},
[keys, overrideSystem]
);
const keyupListener = useCallback(
(assignedKey) => (keyupEvent) => {
const raisedKey = assignedKey.toLowerCase();
if (blacklistedTargets.includes(keyupEvent.target.tagName)) return;
if (keyupEvent.key.toLowerCase() !== raisedKey) return;
if (keys[raisedKey] === undefined) return;
if (overrideSystem) {
keyupEvent.preventDefault();
disabledEventPropagation(keyupEvent);
}
setKeys({ type: "set-key-up", key: raisedKey });
return false;
},
[keys, overrideSystem]
);
useEffect(() => {
if (!Object.values(keys).filter((value) => !value).length) {
callback(keys);
setKeys({ type: "reset-keys", data: initalKeyMapping });
} else {
setKeys({ type: null });
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [callback, keys]);
useEffect(() => {
shortcutKeys.forEach((k) =>
window.addEventListener("keydown", keydownListener(k))
);
return () =>
shortcutKeys.forEach((k) =>
window.removeEventListener("keydown", keydownListener(k))
);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
useEffect(() => {
shortcutKeys.forEach((k) =>
window.addEventListener("keyup", keyupListener(k))
);
return () =>
shortcutKeys.forEach((k) =>
window.removeEventListener("keyup", keyupListener(k))
);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
};
export default useKeyboardShortcut;
function disabledEventPropagation(e) {
if (e) {
if (e.stopPropagation) {
e.stopPropagation();
} else if (window.event) {
window.event.cancelBubble = true;
if (e) {
if (e.stopPropagation) {
e.stopPropagation();
} else if (window.event) {
window.event.cancelBubble = true;
}
}
}
}

312
package-lock.json generated
View File

@@ -9,9 +9,9 @@
"version": "0.0.1",
"license": "UNLICENSED",
"dependencies": {
"@aws-sdk/client-secrets-manager": "^3.485.0",
"@aws-sdk/client-ses": "^3.485.0",
"@aws-sdk/credential-provider-node": "^3.485.0",
"@aws-sdk/client-secrets-manager": "^3.490.0",
"@aws-sdk/client-ses": "^3.490.0",
"@aws-sdk/credential-provider-node": "^3.490.0",
"@opensearch-project/opensearch": "^2.5.0",
"aws4": "^1.12.0",
"axios": "^1.6.5",
@@ -42,7 +42,7 @@
"nodemailer": "^6.9.8",
"phone": "^3.1.42",
"soap": "^1.0.0",
"socket.io": "^4.7.3",
"socket.io": "^4.7.4",
"ssh2-sftp-client": "^9.1.0",
"stripe": "^14.11.0",
"twilio": "^4.20.0",
@@ -151,25 +151,25 @@
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
},
"node_modules/@aws-sdk/client-secrets-manager": {
"version": "3.485.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/client-secrets-manager/-/client-secrets-manager-3.485.0.tgz",
"integrity": "sha512-TruRGEdTy1y/5ln1NcU5LvIZyK38O89zU9vCfNQIKwTSrpS0sDJQukjg8VfMC8gbqUUvXdiPcS61Fxr1WfWn7g==",
"version": "3.490.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/client-secrets-manager/-/client-secrets-manager-3.490.0.tgz",
"integrity": "sha512-wd+PBIMOfSY9CpHfAAE9ztwwde7wom3/VdSqLbBUAUAvAlArANmBS610iCZSFP3ds38v8rnliAV9fjzf7IVnxQ==",
"dependencies": {
"@aws-crypto/sha256-browser": "3.0.0",
"@aws-crypto/sha256-js": "3.0.0",
"@aws-sdk/client-sts": "3.485.0",
"@aws-sdk/core": "3.485.0",
"@aws-sdk/credential-provider-node": "3.485.0",
"@aws-sdk/middleware-host-header": "3.485.0",
"@aws-sdk/middleware-logger": "3.485.0",
"@aws-sdk/middleware-recursion-detection": "3.485.0",
"@aws-sdk/middleware-signing": "3.485.0",
"@aws-sdk/middleware-user-agent": "3.485.0",
"@aws-sdk/region-config-resolver": "3.485.0",
"@aws-sdk/types": "3.485.0",
"@aws-sdk/util-endpoints": "3.485.0",
"@aws-sdk/util-user-agent-browser": "3.485.0",
"@aws-sdk/util-user-agent-node": "3.485.0",
"@aws-sdk/client-sts": "3.490.0",
"@aws-sdk/core": "3.490.0",
"@aws-sdk/credential-provider-node": "3.490.0",
"@aws-sdk/middleware-host-header": "3.489.0",
"@aws-sdk/middleware-logger": "3.489.0",
"@aws-sdk/middleware-recursion-detection": "3.489.0",
"@aws-sdk/middleware-signing": "3.489.0",
"@aws-sdk/middleware-user-agent": "3.489.0",
"@aws-sdk/region-config-resolver": "3.489.0",
"@aws-sdk/types": "3.489.0",
"@aws-sdk/util-endpoints": "3.489.0",
"@aws-sdk/util-user-agent-browser": "3.489.0",
"@aws-sdk/util-user-agent-node": "3.489.0",
"@smithy/config-resolver": "^2.0.23",
"@smithy/core": "^1.2.2",
"@smithy/fetch-http-handler": "^2.3.2",
@@ -210,25 +210,25 @@
}
},
"node_modules/@aws-sdk/client-ses": {
"version": "3.485.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/client-ses/-/client-ses-3.485.0.tgz",
"integrity": "sha512-XXilZfQTBsp5RWl2SRNaJ7pW7Kk7x4N1N++GZPYxHoUsmfB6jdE2ilEeSdfFtKhd9QxEDinQM7yYSGouiwofvA==",
"version": "3.490.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/client-ses/-/client-ses-3.490.0.tgz",
"integrity": "sha512-vcU4+1DfdZ+7AcrpaSxG+xohPkA9rMA0l6Jt3zJPkLqUBhrBQfkWISaQ6CNpS6QlAfxzrSudI4t4J5T9J0xs/g==",
"dependencies": {
"@aws-crypto/sha256-browser": "3.0.0",
"@aws-crypto/sha256-js": "3.0.0",
"@aws-sdk/client-sts": "3.485.0",
"@aws-sdk/core": "3.485.0",
"@aws-sdk/credential-provider-node": "3.485.0",
"@aws-sdk/middleware-host-header": "3.485.0",
"@aws-sdk/middleware-logger": "3.485.0",
"@aws-sdk/middleware-recursion-detection": "3.485.0",
"@aws-sdk/middleware-signing": "3.485.0",
"@aws-sdk/middleware-user-agent": "3.485.0",
"@aws-sdk/region-config-resolver": "3.485.0",
"@aws-sdk/types": "3.485.0",
"@aws-sdk/util-endpoints": "3.485.0",
"@aws-sdk/util-user-agent-browser": "3.485.0",
"@aws-sdk/util-user-agent-node": "3.485.0",
"@aws-sdk/client-sts": "3.490.0",
"@aws-sdk/core": "3.490.0",
"@aws-sdk/credential-provider-node": "3.490.0",
"@aws-sdk/middleware-host-header": "3.489.0",
"@aws-sdk/middleware-logger": "3.489.0",
"@aws-sdk/middleware-recursion-detection": "3.489.0",
"@aws-sdk/middleware-signing": "3.489.0",
"@aws-sdk/middleware-user-agent": "3.489.0",
"@aws-sdk/region-config-resolver": "3.489.0",
"@aws-sdk/types": "3.489.0",
"@aws-sdk/util-endpoints": "3.489.0",
"@aws-sdk/util-user-agent-browser": "3.489.0",
"@aws-sdk/util-user-agent-node": "3.489.0",
"@smithy/config-resolver": "^2.0.23",
"@smithy/core": "^1.2.2",
"@smithy/fetch-http-handler": "^2.3.2",
@@ -262,22 +262,22 @@
}
},
"node_modules/@aws-sdk/client-sso": {
"version": "3.485.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.485.0.tgz",
"integrity": "sha512-apN2bEn0PZs0jD4jAfvwO3dlWqw9YIQJ6TAudM1bd3S5vzWqlBBcLfQpK6taHoQaI+WqgUWXLuOf7gRFbGXKPg==",
"version": "3.490.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.490.0.tgz",
"integrity": "sha512-yfxoHmCL1w/IKmFRfzCxdVCQrGlSQf4eei9iVEm5oi3iE8REFyPj3o/BmKQEHG3h2ITK5UbdYDb5TY4xoYHsyA==",
"dependencies": {
"@aws-crypto/sha256-browser": "3.0.0",
"@aws-crypto/sha256-js": "3.0.0",
"@aws-sdk/core": "3.485.0",
"@aws-sdk/middleware-host-header": "3.485.0",
"@aws-sdk/middleware-logger": "3.485.0",
"@aws-sdk/middleware-recursion-detection": "3.485.0",
"@aws-sdk/middleware-user-agent": "3.485.0",
"@aws-sdk/region-config-resolver": "3.485.0",
"@aws-sdk/types": "3.485.0",
"@aws-sdk/util-endpoints": "3.485.0",
"@aws-sdk/util-user-agent-browser": "3.485.0",
"@aws-sdk/util-user-agent-node": "3.485.0",
"@aws-sdk/core": "3.490.0",
"@aws-sdk/middleware-host-header": "3.489.0",
"@aws-sdk/middleware-logger": "3.489.0",
"@aws-sdk/middleware-recursion-detection": "3.489.0",
"@aws-sdk/middleware-user-agent": "3.489.0",
"@aws-sdk/region-config-resolver": "3.489.0",
"@aws-sdk/types": "3.489.0",
"@aws-sdk/util-endpoints": "3.489.0",
"@aws-sdk/util-user-agent-browser": "3.489.0",
"@aws-sdk/util-user-agent-node": "3.489.0",
"@smithy/config-resolver": "^2.0.23",
"@smithy/core": "^1.2.2",
"@smithy/fetch-http-handler": "^2.3.2",
@@ -309,23 +309,23 @@
}
},
"node_modules/@aws-sdk/client-sts": {
"version": "3.485.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.485.0.tgz",
"integrity": "sha512-PI4q36kVF0fpIPZyeQhrwwJZ6SRkOGvU3rX5Qn4b5UY5X+Ct1aLhqSX8/OB372UZIcnh6eSvERu8POHleDO7Jw==",
"version": "3.490.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.490.0.tgz",
"integrity": "sha512-n2vQ5Qu2qi2I0XMI+IH99ElpIRHOJTa1+sqNC4juMYxKQBMvw+EnsqUtaL3QvTHoyxNB/R7mpkeBB6SzPQ1TtA==",
"dependencies": {
"@aws-crypto/sha256-browser": "3.0.0",
"@aws-crypto/sha256-js": "3.0.0",
"@aws-sdk/core": "3.485.0",
"@aws-sdk/credential-provider-node": "3.485.0",
"@aws-sdk/middleware-host-header": "3.485.0",
"@aws-sdk/middleware-logger": "3.485.0",
"@aws-sdk/middleware-recursion-detection": "3.485.0",
"@aws-sdk/middleware-user-agent": "3.485.0",
"@aws-sdk/region-config-resolver": "3.485.0",
"@aws-sdk/types": "3.485.0",
"@aws-sdk/util-endpoints": "3.485.0",
"@aws-sdk/util-user-agent-browser": "3.485.0",
"@aws-sdk/util-user-agent-node": "3.485.0",
"@aws-sdk/core": "3.490.0",
"@aws-sdk/credential-provider-node": "3.490.0",
"@aws-sdk/middleware-host-header": "3.489.0",
"@aws-sdk/middleware-logger": "3.489.0",
"@aws-sdk/middleware-recursion-detection": "3.489.0",
"@aws-sdk/middleware-user-agent": "3.489.0",
"@aws-sdk/region-config-resolver": "3.489.0",
"@aws-sdk/types": "3.489.0",
"@aws-sdk/util-endpoints": "3.489.0",
"@aws-sdk/util-user-agent-browser": "3.489.0",
"@aws-sdk/util-user-agent-node": "3.489.0",
"@smithy/config-resolver": "^2.0.23",
"@smithy/core": "^1.2.2",
"@smithy/fetch-http-handler": "^2.3.2",
@@ -359,9 +359,9 @@
}
},
"node_modules/@aws-sdk/core": {
"version": "3.485.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.485.0.tgz",
"integrity": "sha512-Yvi80DQcbjkYCft471ClE3HuetuNVqntCs6eFOomDcrJaqdOFrXv2kJAxky84MRA/xb7bGlDGAPbTuj1ICputg==",
"version": "3.490.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.490.0.tgz",
"integrity": "sha512-TSBWkXtxMU7q1Zo6w3v5wIOr/sj7P5Jw3OyO7lJrFGsPsDC2xwpxkVqTesDxkzgMRypO52xjYEmveagn1xxBHg==",
"dependencies": {
"@smithy/core": "^1.2.2",
"@smithy/protocol-http": "^3.0.12",
@@ -375,11 +375,11 @@
}
},
"node_modules/@aws-sdk/credential-provider-env": {
"version": "3.485.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.485.0.tgz",
"integrity": "sha512-3XkFgwVU1XOB33dV7t9BKJ/ptdl2iS+0dxE7ecq8aqT2/gsfKmLCae1G17P8WmdD3z0kMDTvnqM2aWgUnSOkmg==",
"version": "3.489.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.489.0.tgz",
"integrity": "sha512-5PqYsx9G5SB2tqPT9/z/u0EkF6D4wP6HTMWQs+DfMdmwXihrqQAgeYaTtV3KbXqb88p6sfacwxhUvE6+Rm494w==",
"dependencies": {
"@aws-sdk/types": "3.485.0",
"@aws-sdk/types": "3.489.0",
"@smithy/property-provider": "^2.0.0",
"@smithy/types": "^2.8.0",
"tslib": "^2.5.0"
@@ -389,15 +389,15 @@
}
},
"node_modules/@aws-sdk/credential-provider-ini": {
"version": "3.485.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.485.0.tgz",
"integrity": "sha512-cFYF/Bdw7EnT4viSxYpNIv3IBkri/Yb+JpQXl8uDq7bfVJfAN5qZmK07vRkg08xL6TC4F41wshhMSAucGdTwIw==",
"version": "3.490.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.490.0.tgz",
"integrity": "sha512-7m63zyCpVqj9FsoDxWMWWRvL6c7zZzOcXYkHZmHujVVlmAXH0RT/vkXFkYgt+Ku+ov+v5NQrzwO5TmVoRt6O8g==",
"dependencies": {
"@aws-sdk/credential-provider-env": "3.485.0",
"@aws-sdk/credential-provider-process": "3.485.0",
"@aws-sdk/credential-provider-sso": "3.485.0",
"@aws-sdk/credential-provider-web-identity": "3.485.0",
"@aws-sdk/types": "3.485.0",
"@aws-sdk/credential-provider-env": "3.489.0",
"@aws-sdk/credential-provider-process": "3.489.0",
"@aws-sdk/credential-provider-sso": "3.490.0",
"@aws-sdk/credential-provider-web-identity": "3.489.0",
"@aws-sdk/types": "3.489.0",
"@smithy/credential-provider-imds": "^2.0.0",
"@smithy/property-provider": "^2.0.0",
"@smithy/shared-ini-file-loader": "^2.0.6",
@@ -409,16 +409,16 @@
}
},
"node_modules/@aws-sdk/credential-provider-node": {
"version": "3.485.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.485.0.tgz",
"integrity": "sha512-2DwzO2azkSzngifKDT61W/DL0tSzewuaFHiLJWdfc8Et3mdAQJ9x3KAj8u7XFpjIcGNqk7FiKjN+zeGUuNiEhA==",
"version": "3.490.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.490.0.tgz",
"integrity": "sha512-Gh33u2O5Xbout8G3z/Z5H/CZzdG1ophxf/XS3iMFxA1cazQ7swY1UMmGvB7Lm7upvax5anXouItD1Ph3gzKc4w==",
"dependencies": {
"@aws-sdk/credential-provider-env": "3.485.0",
"@aws-sdk/credential-provider-ini": "3.485.0",
"@aws-sdk/credential-provider-process": "3.485.0",
"@aws-sdk/credential-provider-sso": "3.485.0",
"@aws-sdk/credential-provider-web-identity": "3.485.0",
"@aws-sdk/types": "3.485.0",
"@aws-sdk/credential-provider-env": "3.489.0",
"@aws-sdk/credential-provider-ini": "3.490.0",
"@aws-sdk/credential-provider-process": "3.489.0",
"@aws-sdk/credential-provider-sso": "3.490.0",
"@aws-sdk/credential-provider-web-identity": "3.489.0",
"@aws-sdk/types": "3.489.0",
"@smithy/credential-provider-imds": "^2.0.0",
"@smithy/property-provider": "^2.0.0",
"@smithy/shared-ini-file-loader": "^2.0.6",
@@ -430,11 +430,11 @@
}
},
"node_modules/@aws-sdk/credential-provider-process": {
"version": "3.485.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.485.0.tgz",
"integrity": "sha512-X9qS6ZO/rDKYDgWqD1YmSX7sAUUHax9HbXlgGiTTdtfhZvQh1ZmnH6wiPu5WNliafHZFtZT2W07kgrDLPld/Ug==",
"version": "3.489.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.489.0.tgz",
"integrity": "sha512-3vKQYJZ5cZYjy0870CPmbmKRBgATw2xCygxhn4m4UDCjOXVXcGUtYD51DMWsvBo3S0W8kH+FIJV4yuEDMFqLFQ==",
"dependencies": {
"@aws-sdk/types": "3.485.0",
"@aws-sdk/types": "3.489.0",
"@smithy/property-provider": "^2.0.0",
"@smithy/shared-ini-file-loader": "^2.0.6",
"@smithy/types": "^2.8.0",
@@ -445,13 +445,13 @@
}
},
"node_modules/@aws-sdk/credential-provider-sso": {
"version": "3.485.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.485.0.tgz",
"integrity": "sha512-l0oC8GTrWh+LFQQfSmG1Jai1PX7Mhj9arb/CaS1/tmeZE0hgIXW++tvljYs/Dds4LGXUlaWG+P7BrObf6OyIXA==",
"version": "3.490.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.490.0.tgz",
"integrity": "sha512-3UUBUoPbFvT58IhS4Vb23omYj/QPNkjgxu9p9ruQ3KSjLkanI4w8t/l/jljA65q83P7CoLnM5UKG9L7RA8/V1Q==",
"dependencies": {
"@aws-sdk/client-sso": "3.485.0",
"@aws-sdk/token-providers": "3.485.0",
"@aws-sdk/types": "3.485.0",
"@aws-sdk/client-sso": "3.490.0",
"@aws-sdk/token-providers": "3.489.0",
"@aws-sdk/types": "3.489.0",
"@smithy/property-provider": "^2.0.0",
"@smithy/shared-ini-file-loader": "^2.0.6",
"@smithy/types": "^2.8.0",
@@ -462,11 +462,11 @@
}
},
"node_modules/@aws-sdk/credential-provider-web-identity": {
"version": "3.485.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.485.0.tgz",
"integrity": "sha512-WpBFZFE0iXtnibH5POMEKITj/hR0YV5l2n9p8BEvKjdJ63s3Xke1RN20ZdIyKDaRDwj8adnKDgNPEnAKdS4kLw==",
"version": "3.489.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.489.0.tgz",
"integrity": "sha512-mjIuE2Wg1H/ds0nXQ/7vfusEDudmdd8YzKZI1y5O4n60iZZtyB2RNIECtvLMx1EQAKclidY7/06qQkArrGau5Q==",
"dependencies": {
"@aws-sdk/types": "3.485.0",
"@aws-sdk/types": "3.489.0",
"@smithy/property-provider": "^2.0.0",
"@smithy/types": "^2.8.0",
"tslib": "^2.5.0"
@@ -476,11 +476,11 @@
}
},
"node_modules/@aws-sdk/middleware-host-header": {
"version": "3.485.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.485.0.tgz",
"integrity": "sha512-1mAUX9dQNGo2RIKseVj7SI/D5abQJQ/Os8hQ0NyVAyyVYF+Yjx5PphKgfhM5yoBwuwZUl6q71XPYEGNx7be6SA==",
"version": "3.489.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.489.0.tgz",
"integrity": "sha512-Cl7HJ1jhOfllwf0CRx1eB4ypRGMqdGKWpc0eSTXty7wWSvCdMZUhwfjQqu2bIOIlgYxg/gFu6TVmVZ6g4O8PlA==",
"dependencies": {
"@aws-sdk/types": "3.485.0",
"@aws-sdk/types": "3.489.0",
"@smithy/protocol-http": "^3.0.12",
"@smithy/types": "^2.8.0",
"tslib": "^2.5.0"
@@ -490,11 +490,11 @@
}
},
"node_modules/@aws-sdk/middleware-logger": {
"version": "3.485.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.485.0.tgz",
"integrity": "sha512-O8IgJ0LHi5wTs5GlpI7nqmmSSagkVdd1shpGgQWY2h0kMSCII8CJZHBG97dlFFpGTvx5EDlhPNek7rl/6F4dRw==",
"version": "3.489.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.489.0.tgz",
"integrity": "sha512-+EVDnWese61MdImcBNAgz/AhTcIZJaska/xsU3GWU9CP905x4a4qZdB7fExFMDu1Jlz5pJqNteFYYHCFMJhHfg==",
"dependencies": {
"@aws-sdk/types": "3.485.0",
"@aws-sdk/types": "3.489.0",
"@smithy/types": "^2.8.0",
"tslib": "^2.5.0"
},
@@ -503,11 +503,11 @@
}
},
"node_modules/@aws-sdk/middleware-recursion-detection": {
"version": "3.485.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.485.0.tgz",
"integrity": "sha512-ZeVNATGNFcqkWDut3luVszROTUzkU5u+rJpB/xmeMoenlDAjPRiHt/ca3WkI5wAnIJ1VSNGpD2sOFLMCH+EWag==",
"version": "3.489.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.489.0.tgz",
"integrity": "sha512-m4rU+fTzziQcu9DKjRNZ4nQlXENEd2ZnJblJV4ONdWqqEjbmOgOj3P6aCCQlJdIbzuNvX1FBOZ5tY59ZpERo7Q==",
"dependencies": {
"@aws-sdk/types": "3.485.0",
"@aws-sdk/types": "3.489.0",
"@smithy/protocol-http": "^3.0.12",
"@smithy/types": "^2.8.0",
"tslib": "^2.5.0"
@@ -517,11 +517,11 @@
}
},
"node_modules/@aws-sdk/middleware-signing": {
"version": "3.485.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.485.0.tgz",
"integrity": "sha512-41xzT2p1sOibhsLkdE5rwPJkNbBtKD8Gp36/ySfu0KE415wfXKacElSVxAaBw39/j7iSWDYqqybeEYbAzk+3GQ==",
"version": "3.489.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.489.0.tgz",
"integrity": "sha512-rlHcWYZn6Ym3v/u0DvKNDiD7ogIzEsHlerm0lowTiQbszkFobOiUClRTALwvsUZdAAztl706qO1OKbnGnD6Ubw==",
"dependencies": {
"@aws-sdk/types": "3.485.0",
"@aws-sdk/types": "3.489.0",
"@smithy/property-provider": "^2.0.0",
"@smithy/protocol-http": "^3.0.12",
"@smithy/signature-v4": "^2.0.0",
@@ -534,12 +534,12 @@
}
},
"node_modules/@aws-sdk/middleware-user-agent": {
"version": "3.485.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.485.0.tgz",
"integrity": "sha512-CddCVOn+OPQ0CcchketIg+WF6v+MDLAf3GOYTR2htUxxIm7HABuRd6R3kvQ5Jny9CV8gMt22G1UZITsFexSJlQ==",
"version": "3.489.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.489.0.tgz",
"integrity": "sha512-M54Cv2fAN3GGgdfUjLtZ4wFUIrfM/ivbXv4DgpcNsacEQ2g4H+weQgKp41X7XZW8MWAzl+k1zJaryK69RYNQkQ==",
"dependencies": {
"@aws-sdk/types": "3.485.0",
"@aws-sdk/util-endpoints": "3.485.0",
"@aws-sdk/types": "3.489.0",
"@aws-sdk/util-endpoints": "3.489.0",
"@smithy/protocol-http": "^3.0.12",
"@smithy/types": "^2.8.0",
"tslib": "^2.5.0"
@@ -549,10 +549,11 @@
}
},
"node_modules/@aws-sdk/region-config-resolver": {
"version": "3.485.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.485.0.tgz",
"integrity": "sha512-2FB2EQ0sIE+YgFqGtkE1lDIMIL6nYe6MkOHBwBM7bommadKIrbbr2L22bPZGs3ReTsxiJabjzxbuCAVhrpHmhg==",
"version": "3.489.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.489.0.tgz",
"integrity": "sha512-UvrnB78XTz9ddby7mr0vuUHn2MO3VTjzaIu+GQhyedMGQU0QlIQrYOlzbbu4LC5rL1O8FxFLUxRe/AAjgwyuGw==",
"dependencies": {
"@aws-sdk/types": "3.489.0",
"@smithy/node-config-provider": "^2.1.9",
"@smithy/types": "^2.8.0",
"@smithy/util-config-provider": "^2.1.0",
@@ -564,21 +565,21 @@
}
},
"node_modules/@aws-sdk/token-providers": {
"version": "3.485.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.485.0.tgz",
"integrity": "sha512-kOXA1WKIVIFNRqHL8ynVZ3hCKLsgnEmGr2iDR6agDNw5fYIlCO/6N2xR6QdGcLTvUUbwOlz4OvKLUQnWMKAnnA==",
"version": "3.489.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.489.0.tgz",
"integrity": "sha512-hSgjB8CMQoA8EIQ0ripDjDtbBcWDSa+7vSBYPIzksyknaGERR/GUfGXLV2dpm5t17FgFG6irT5f3ZlBzarL8Dw==",
"dependencies": {
"@aws-crypto/sha256-browser": "3.0.0",
"@aws-crypto/sha256-js": "3.0.0",
"@aws-sdk/middleware-host-header": "3.485.0",
"@aws-sdk/middleware-logger": "3.485.0",
"@aws-sdk/middleware-recursion-detection": "3.485.0",
"@aws-sdk/middleware-user-agent": "3.485.0",
"@aws-sdk/region-config-resolver": "3.485.0",
"@aws-sdk/types": "3.485.0",
"@aws-sdk/util-endpoints": "3.485.0",
"@aws-sdk/util-user-agent-browser": "3.485.0",
"@aws-sdk/util-user-agent-node": "3.485.0",
"@aws-sdk/middleware-host-header": "3.489.0",
"@aws-sdk/middleware-logger": "3.489.0",
"@aws-sdk/middleware-recursion-detection": "3.489.0",
"@aws-sdk/middleware-user-agent": "3.489.0",
"@aws-sdk/region-config-resolver": "3.489.0",
"@aws-sdk/types": "3.489.0",
"@aws-sdk/util-endpoints": "3.489.0",
"@aws-sdk/util-user-agent-browser": "3.489.0",
"@aws-sdk/util-user-agent-node": "3.489.0",
"@smithy/config-resolver": "^2.0.23",
"@smithy/fetch-http-handler": "^2.3.2",
"@smithy/hash-node": "^2.0.18",
@@ -611,9 +612,9 @@
}
},
"node_modules/@aws-sdk/types": {
"version": "3.485.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.485.0.tgz",
"integrity": "sha512-+QW32YQdvZRDOwrAQPo/qCyXoSjgXB6RwJwCwkd8ebJXRXw6tmGKIHaZqYHt/LtBymvnaBgBBADNa4+qFvlOFw==",
"version": "3.489.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.489.0.tgz",
"integrity": "sha512-kcDtLfKog/p0tC4gAeqJqWxAiEzfe2LRPnKamvSG2Mjbthx4R/alE2dxyIq/wW+nvRv0fqR3OD5kD1+eVfdr/w==",
"dependencies": {
"@smithy/types": "^2.8.0",
"tslib": "^2.5.0"
@@ -623,11 +624,12 @@
}
},
"node_modules/@aws-sdk/util-endpoints": {
"version": "3.485.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.485.0.tgz",
"integrity": "sha512-dTd642F7nJisApF8YjniqQ6U59CP/DCtar11fXf1nG9YNBCBsNNVw5ZfZb5nSNzaIdy27mQioWTCV18JEj1mxg==",
"version": "3.489.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.489.0.tgz",
"integrity": "sha512-uGyG1u84ATX03mf7bT4xD9XD/vlYJGD5+RxMN/UpzeTfzXfh+jvCQWbOQ44z8ttFJWYQQqrLxkfpF/JgvALzLA==",
"dependencies": {
"@aws-sdk/types": "3.485.0",
"@aws-sdk/types": "3.489.0",
"@smithy/types": "^2.8.0",
"@smithy/util-endpoints": "^1.0.8",
"tslib": "^2.5.0"
},
@@ -647,22 +649,22 @@
}
},
"node_modules/@aws-sdk/util-user-agent-browser": {
"version": "3.485.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.485.0.tgz",
"integrity": "sha512-QliWbjg0uOhGTcWgWTKPMY0SBi07g253DjwrCINT1auqDrdQPxa10xozpZExBYjAK2KuhYDNUzni127ae6MHOw==",
"version": "3.489.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.489.0.tgz",
"integrity": "sha512-85B9KMsuMpAZauzWQ16r52ZBAHYnznW6BVitnBglsibN7oJKn10Hggt4QGuRhvQFCxQ8YhvBl7r+vQGFO4hxIw==",
"dependencies": {
"@aws-sdk/types": "3.485.0",
"@aws-sdk/types": "3.489.0",
"@smithy/types": "^2.8.0",
"bowser": "^2.11.0",
"tslib": "^2.5.0"
}
},
"node_modules/@aws-sdk/util-user-agent-node": {
"version": "3.485.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.485.0.tgz",
"integrity": "sha512-QF+aQ9jnDlPUlFBxBRqOylPf86xQuD3aEPpOErR+50qJawVvKa94uiAFdvtI9jv6hnRZmuFsTj2rsyytnbAYBA==",
"version": "3.489.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.489.0.tgz",
"integrity": "sha512-CYdkBHig8sFNc0dv11Ni9WXvZQHeI5+z77OrDHKkbidFx/V4BDTuwZw4K1vWg62pzFOEfzunJFiULRcDZWJR3w==",
"dependencies": {
"@aws-sdk/types": "3.485.0",
"@aws-sdk/types": "3.489.0",
"@smithy/node-config-provider": "^2.1.9",
"@smithy/types": "^2.8.0",
"tslib": "^2.5.0"
@@ -5657,9 +5659,9 @@
}
},
"node_modules/socket.io": {
"version": "4.7.3",
"resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.3.tgz",
"integrity": "sha512-SE+UIQXBQE+GPG2oszWMlsEmWtHVqw/h1VrYJGK5/MC7CH5p58N448HwIrtREcvR4jfdOJAY4ieQfxMr55qbbw==",
"version": "4.7.4",
"resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.4.tgz",
"integrity": "sha512-DcotgfP1Zg9iP/dH9zvAQcWrE0TtbMVwXmlV4T4mqsvY+gw+LqUGPfx2AoVyRk0FLME+GQhufDMyacFmw7ksqw==",
"dependencies": {
"accepts": "~1.3.4",
"base64id": "~2.0.0",

View File

@@ -17,9 +17,9 @@
"start": "node server.js"
},
"dependencies": {
"@aws-sdk/client-secrets-manager": "^3.485.0",
"@aws-sdk/client-ses": "^3.485.0",
"@aws-sdk/credential-provider-node": "^3.485.0",
"@aws-sdk/client-secrets-manager": "^3.490.0",
"@aws-sdk/client-ses": "^3.490.0",
"@aws-sdk/credential-provider-node": "^3.490.0",
"@opensearch-project/opensearch": "^2.5.0",
"aws4": "^1.12.0",
"axios": "^1.6.5",
@@ -50,7 +50,7 @@
"nodemailer": "^6.9.8",
"phone": "^3.1.42",
"soap": "^1.0.0",
"socket.io": "^4.7.3",
"socket.io": "^4.7.4",
"ssh2-sftp-client": "^9.1.0",
"stripe": "^14.11.0",
"twilio": "^4.20.0",