Merge branch 'feature/IO-1828-Front-End-Package-Updates' into feature/IO-2477

This commit is contained in:
Dave Richer
2024-01-18 16:52:20 -05:00
16 changed files with 300 additions and 180 deletions

View File

@@ -153,7 +153,7 @@ jobs:
name: Install Dependencies
command: npm i
- run: npm run build
- run: npm run build:test
- aws-s3/sync:
from: build

View File

@@ -1,4 +1,4 @@
GENERATE_SOURCEMAP=true
GENERATE_SOURCEMAP=false
REACT_APP_GRAPHQL_ENDPOINT=https://db.imex.online/v1/graphql
REACT_APP_GRAPHQL_ENDPOINT_WS=wss://db.imex.online/v1/graphql
REACT_APP_GA_CODE=231103507

132
client/package-lock.json generated
View File

@@ -10,7 +10,7 @@
"dependencies": {
"@ant-design/compatible": "^5.1.2",
"@ant-design/pro-layout": "^7.17.16",
"@apollo/client": "^3.8.9",
"@apollo/client": "^3.8.10",
"@asseinfo/react-kanban": "^2.2.0",
"@craco/craco": "^7.1.0",
"@fingerprintjs/fingerprintjs": "^4.2.1",
@@ -18,7 +18,7 @@
"@reduxjs/toolkit": "^2.0.1",
"@sentry/react": "^7.93.0",
"@sentry/tracing": "^7.93.0",
"@splitsoftware/splitio-react": "^1.10.2",
"@splitsoftware/splitio-react": "^1.11.0",
"@tanem/react-nprogress": "^5.0.51",
"antd": "^5.12.8",
"apollo-link-logger": "^2.0.1",
@@ -31,7 +31,7 @@
"enquire-js": "^0.2.1",
"env-cmd": "^10.1.0",
"exifr": "^7.1.3",
"firebase": "^10.7.1",
"firebase": "^10.7.2",
"graphql": "^16.6.0",
"i18next": "^23.7.16",
"i18next-browser-languagedetector": "^7.0.2",
@@ -63,7 +63,7 @@
"react-number-format": "^5.1.4",
"react-redux": "^9.1.0",
"react-resizable": "^3.0.5",
"react-router-dom": "^6.21.2",
"react-router-dom": "^6.21.3",
"react-scripts": "^5.0.1",
"react-sticky": "^6.0.3",
"react-sublime-video": "^0.2.5",
@@ -74,7 +74,7 @@
"redux-saga": "^1.3.0",
"redux-state-sync": "^3.1.4",
"reselect": "^5.1.0",
"sass": "^1.69.7",
"sass": "^1.70.0",
"socket.io-client": "^4.7.4",
"styled-components": "^6.1.8",
"subscriptions-transport-ws": "^0.11.0",
@@ -92,7 +92,7 @@
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
"@sentry/webpack-plugin": "^2.10.2",
"@testing-library/cypress": "^10.0.1",
"cypress": "^13.6.2",
"cypress": "^13.6.3",
"eslint-plugin-cypress": "^2.15.1",
"react-error-overlay": "6.0.11",
"redux-logger": "^3.0.6",
@@ -305,9 +305,9 @@
}
},
"node_modules/@apollo/client": {
"version": "3.8.9",
"resolved": "https://registry.npmjs.org/@apollo/client/-/client-3.8.9.tgz",
"integrity": "sha512-IcQDFEEPc9+PEQsxhxQvsoQ04BRarOzi/Ila5PcniRSDeKJWgY22dnp6+V1i1fWXRDVd1ybdvze4sFESDVQUCQ==",
"version": "3.8.10",
"resolved": "https://registry.npmjs.org/@apollo/client/-/client-3.8.10.tgz",
"integrity": "sha512-p/22RZ8ehHyvySnC20EHPPe0gdu8Xp6ZCiXOfdEe1ZORw5cUteD/TLc66tfKv8qu8NLIfbiWoa+6s70XnKvxqg==",
"dependencies": {
"@graphql-typed-document-node/core": "^3.1.1",
"@wry/equality": "^0.5.6",
@@ -3040,9 +3040,9 @@
"integrity": "sha512-iRP+QKI2+oz3UAh4nPEq14CsEjrjD6a5+fuypjScisAh9kXKFvdJOZJDwk7kikLvWVLGEs9+kIUS4LPQV7VZVw=="
},
"node_modules/@firebase/app": {
"version": "0.9.25",
"resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.9.25.tgz",
"integrity": "sha512-fX22gL5USXhOK21Hlh3oTeOzQZ6th6S2JrjXNEpBARmwzuUkqmVGVdsOCIFYIsLpK0dQE3o8xZnLrRg5wnzZ/g==",
"version": "0.9.26",
"resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.9.26.tgz",
"integrity": "sha512-zCjo6KhNhbuFB+V+Z4H9g4+BZ78E7n3ShxaBtuIcRkpwdm7+1BsafzChOsDYuI86m97HUWsyLPurLBhqcupFFA==",
"dependencies": {
"@firebase/component": "0.6.4",
"@firebase/logger": "0.4.0",
@@ -3092,11 +3092,11 @@
"integrity": "sha512-uwSUj32Mlubybw7tedRzR24RP8M8JUVR3NPiMk3/Z4bCmgEKTlQBwMXrehDAZ2wF+TsBq0SN1c6ema71U/JPyQ=="
},
"node_modules/@firebase/app-compat": {
"version": "0.2.25",
"resolved": "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.2.25.tgz",
"integrity": "sha512-B/JtCp1FsTuzlh1tIGQpYM2AXps21/zlzpFsk5LRsROOTRhBcR2N45AyaONPFD06C0yS0Tw19foxADzHyOSC3A==",
"version": "0.2.26",
"resolved": "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.2.26.tgz",
"integrity": "sha512-tVNOYvB3lIFkN3RmcTieo5qYRIkYak9iC6E7dZMxax52uMIUJiIKKtPkarbwZh6EnUxru5hJRo8tfUZGuaQDQw==",
"dependencies": {
"@firebase/app": "0.9.25",
"@firebase/app": "0.9.26",
"@firebase/component": "0.6.4",
"@firebase/logger": "0.4.0",
"@firebase/util": "1.9.3",
@@ -3205,9 +3205,9 @@
}
},
"node_modules/@firebase/firestore": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-4.4.0.tgz",
"integrity": "sha512-VeDXD9PUjvcWY1tInBOMTIu2pijR3YYy+QAe5cxCo1Q1vW+aA/mpQHhebPM1J6b4Zd1MuUh8xpBRvH9ujKR56A==",
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-4.4.1.tgz",
"integrity": "sha512-LCWZZ+rgNET1qw3vpugmGCJZVbz7c5NkgKect5pZn36gaBzGVb8+pRQ8WSZ1veYVMOK6SKrBkS1Rw6EqcmPnyw==",
"dependencies": {
"@firebase/component": "0.6.4",
"@firebase/logger": "0.4.0",
@@ -3226,12 +3226,12 @@
}
},
"node_modules/@firebase/firestore-compat": {
"version": "0.3.23",
"resolved": "https://registry.npmjs.org/@firebase/firestore-compat/-/firestore-compat-0.3.23.tgz",
"integrity": "sha512-uUTBiP0GLVBETaOCfB11d33OWB8x1r2G1Xrl0sRK3Va0N5LJ/GRvKVSGfM7VScj+ypeHe8RpdwKoCqLpN1e+uA==",
"version": "0.3.24",
"resolved": "https://registry.npmjs.org/@firebase/firestore-compat/-/firestore-compat-0.3.24.tgz",
"integrity": "sha512-Wj5cgqmQwTnqHS4KabOpXCNIaSTtVDP1NitnhjXff04Q4QK0aeIbeO1TPlSSTmUb6S7KzoKD4XR99hfKZDYbfA==",
"dependencies": {
"@firebase/component": "0.6.4",
"@firebase/firestore": "4.4.0",
"@firebase/firestore": "4.4.1",
"@firebase/firestore-types": "3.0.0",
"@firebase/util": "1.9.3",
"tslib": "^2.1.0"
@@ -3503,9 +3503,9 @@
}
},
"node_modules/@grpc/grpc-js": {
"version": "1.9.13",
"resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.9.13.tgz",
"integrity": "sha512-OEZZu9v9AA+7/tghMDE8o5DAMD5THVnwSqDWuh7PPYO5287rTyqy0xEHT6/e4pbqSrhyLPdQFsam4TwFQVVIIw==",
"version": "1.9.14",
"resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.9.14.tgz",
"integrity": "sha512-nOpuzZ2G3IuMFN+UPPpKrC6NsLmWsTqSsm66IRfnBt1D4pwTqE27lmbpcPM+l2Ua4gE7PfjRHI6uedAy7hoXUw==",
"dependencies": {
"@grpc/proto-loader": "^0.7.8",
"@types/node": ">=12.12.47"
@@ -5043,17 +5043,17 @@
"integrity": "sha512-XExJS3cLqgrmNBIP3bBw6+1oQ1ksGjFh0+oClDKFYpCCqx/hlqwWO5KO/S63fzUo67SxI9dMrF0y5T/Ey7h8Zw=="
},
"node_modules/@splitsoftware/splitio": {
"version": "10.24.1",
"resolved": "https://registry.npmjs.org/@splitsoftware/splitio/-/splitio-10.24.1.tgz",
"integrity": "sha512-WzVZrP2IAqzNBywNXgmLxiS60qumkcnu6u1lUPlNgdVek82TzWeqyqW+htKmDMJ/ifsJPWrgT1VLMZJvOnBsVA==",
"version": "10.25.1",
"resolved": "https://registry.npmjs.org/@splitsoftware/splitio/-/splitio-10.25.1.tgz",
"integrity": "sha512-QmCOI2VNhjIMieibtMcc595oyQB5sgrYKSqw7wxKtwMX0VtuPbZ3Lw8fwd0nH2WSKq3Pcjyu3nVSYQRp1bGEvA==",
"dependencies": {
"@splitsoftware/splitio-commons": "1.12.1",
"@splitsoftware/splitio-commons": "1.13.1",
"@types/google.analytics": "0.0.40",
"@types/ioredis": "^4.28.0",
"bloom-filters": "^3.0.0",
"ioredis": "^4.28.0",
"js-yaml": "^3.13.1",
"node-fetch": "^2.6.7",
"node-fetch": "^2.7.0",
"unfetch": "^4.2.0"
},
"engines": {
@@ -5065,9 +5065,9 @@
}
},
"node_modules/@splitsoftware/splitio-commons": {
"version": "1.12.1",
"resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-1.12.1.tgz",
"integrity": "sha512-EkCcqlYvVafazs9c5i+pmhf6rIyj3A70dqQ4U3BKE646t7tf6mxGzqZz1sAl540xNyYI7CA/iIqisEWvDtJc0A==",
"version": "1.13.1",
"resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-1.13.1.tgz",
"integrity": "sha512-xGu94sLx+tJb6PeM26vH8/LEElsaVbh2BjoLvL5twR4gKsVezie5ZtHhejWT1+iCVCtJuhjZxKwOm4HGYoVIHQ==",
"dependencies": {
"tslib": "^2.3.1"
},
@@ -5081,11 +5081,11 @@
}
},
"node_modules/@splitsoftware/splitio-react": {
"version": "1.10.2",
"resolved": "https://registry.npmjs.org/@splitsoftware/splitio-react/-/splitio-react-1.10.2.tgz",
"integrity": "sha512-dFU/cHgsPPOyc0a5QxphqexcbqhyF4mG8krk3/Tid9F01I9b6h6xT8vmtwXJ9j+cQmulnpad/Pd6dSleR4Yhrw==",
"version": "1.11.0",
"resolved": "https://registry.npmjs.org/@splitsoftware/splitio-react/-/splitio-react-1.11.0.tgz",
"integrity": "sha512-z7+xh9m8M0x6vOWWNMNelG20JptGMbcY6kSh32pC2WZt2Vfr7PzJqI3g0mx+0ZCDXPaODR0O3OKdp16jp7aA4Q==",
"dependencies": {
"@splitsoftware/splitio": "10.24.1",
"@splitsoftware/splitio": "10.25.1",
"memoize-one": "^5.1.1",
"shallowequal": "^1.1.0"
},
@@ -8821,15 +8821,14 @@
"integrity": "sha512-d4ZVpCW31eWwCMe1YT3ur7mUDnTXbgwyzaL320DrcRT45rfjYxkt5QWLrmOJ+/UEAI2+fQgKe/fCjR8l4TpRgw=="
},
"node_modules/cypress": {
"version": "13.6.2",
"resolved": "https://registry.npmjs.org/cypress/-/cypress-13.6.2.tgz",
"integrity": "sha512-TW3bGdPU4BrfvMQYv1z3oMqj71YI4AlgJgnrycicmPZAXtvywVFZW9DAToshO65D97rCWfG/kqMFsYB6Kp91gQ==",
"version": "13.6.3",
"resolved": "https://registry.npmjs.org/cypress/-/cypress-13.6.3.tgz",
"integrity": "sha512-d/pZvgwjAyZsoyJ3FOsJT5lDsqnxQ/clMqnNc++rkHjbkkiF2h9s0JsZSyyH4QXhVFW3zPFg82jD25roFLOdZA==",
"dev": true,
"hasInstallScript": true,
"dependencies": {
"@cypress/request": "^3.0.0",
"@cypress/xvfb": "^1.2.4",
"@types/node": "^18.17.5",
"@types/sinonjs__fake-timers": "8.1.1",
"@types/sizzle": "^2.3.2",
"arch": "^2.2.0",
@@ -8878,15 +8877,6 @@
"node": "^16.0.0 || ^18.0.0 || >=20.0.0"
}
},
"node_modules/cypress/node_modules/@types/node": {
"version": "18.19.3",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.3.tgz",
"integrity": "sha512-k5fggr14DwAytoA/t8rPrIz++lXK7/DqckthCmoZOKNsEbJkId4Z//BqgApXBUGrGddrigYa1oqheo/7YmW4rg==",
"dev": true,
"dependencies": {
"undici-types": "~5.26.4"
}
},
"node_modules/cypress/node_modules/proxy-from-env": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz",
@@ -11147,23 +11137,23 @@
}
},
"node_modules/firebase": {
"version": "10.7.1",
"resolved": "https://registry.npmjs.org/firebase/-/firebase-10.7.1.tgz",
"integrity": "sha512-Mlt7y7zQ43FtKp4SCyYie3tnrOL3UMF2XXiV4ZXMrC0d0wtcOYmABuybhkJpJCKILpdekxr39wjnaai0DZlWFg==",
"version": "10.7.2",
"resolved": "https://registry.npmjs.org/firebase/-/firebase-10.7.2.tgz",
"integrity": "sha512-zED3kAJyf+Xx5tXpC3vjmlWTm/SIVoJJ6MOLuXYJkqKAUJLG7Q1Jxy6l1DxCzGgBqZHxc0Jh6q+qG++9kimHsw==",
"dependencies": {
"@firebase/analytics": "0.10.0",
"@firebase/analytics-compat": "0.2.6",
"@firebase/app": "0.9.25",
"@firebase/app": "0.9.26",
"@firebase/app-check": "0.8.1",
"@firebase/app-check-compat": "0.3.8",
"@firebase/app-compat": "0.2.25",
"@firebase/app-compat": "0.2.26",
"@firebase/app-types": "0.9.0",
"@firebase/auth": "1.5.1",
"@firebase/auth-compat": "0.5.1",
"@firebase/database": "1.0.2",
"@firebase/database-compat": "1.0.2",
"@firebase/firestore": "4.4.0",
"@firebase/firestore-compat": "0.3.23",
"@firebase/firestore": "4.4.1",
"@firebase/firestore-compat": "0.3.24",
"@firebase/functions": "0.11.0",
"@firebase/functions-compat": "0.3.6",
"@firebase/installations": "0.6.4",
@@ -17983,9 +17973,9 @@
}
},
"node_modules/protobufjs": {
"version": "7.2.5",
"resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.5.tgz",
"integrity": "sha512-gGXRSXvxQ7UiPgfw8gevrfRWcTlSbOFg+p/N+JVJEK5VhueL2miT6qTymqAmjr1Q5WbOCyJbyrk6JfWKwlFn6A==",
"version": "7.2.6",
"resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.6.tgz",
"integrity": "sha512-dgJaEDDL6x8ASUZ1YqWciTRrdOuYNzoOf27oHNfdyvKqHr5i0FV7FSLU+aIeFjyFgVxrpTOtQUi0BLLBymZaBw==",
"hasInstallScript": true,
"dependencies": {
"@protobufjs/aspromise": "^1.1.2",
@@ -19323,9 +19313,9 @@
}
},
"node_modules/react-router": {
"version": "6.21.2",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.21.2.tgz",
"integrity": "sha512-jJcgiwDsnaHIeC+IN7atO0XiSRCrOsQAHHbChtJxmgqG2IaYQXSnhqGb5vk2CU/wBQA12Zt+TkbuJjIn65gzbA==",
"version": "6.21.3",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.21.3.tgz",
"integrity": "sha512-a0H638ZXULv1OdkmiK6s6itNhoy33ywxmUFT/xtSoVyf9VnC7n7+VT4LjVzdIHSaF5TIh9ylUgxMXksHTgGrKg==",
"dependencies": {
"@remix-run/router": "1.14.2"
},
@@ -19337,12 +19327,12 @@
}
},
"node_modules/react-router-dom": {
"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==",
"version": "6.21.3",
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.21.3.tgz",
"integrity": "sha512-kNzubk7n4YHSrErzjLK72j0B5i969GsuCGazRl3G6j1zqZBLjuSlYBdVdkDOgzGdPIffUOc9nmgiadTEVoq91g==",
"dependencies": {
"@remix-run/router": "1.14.2",
"react-router": "6.21.2"
"react-router": "6.21.3"
},
"engines": {
"node": ">=14.0.0"
@@ -20277,9 +20267,9 @@
"integrity": "sha512-ZRwKbh/eQ6w9vmTjkuG0Ioi3HBwPFce0O+v//ve+aOq1oeCy7jMV2qzzAlpsNuqpqCBjjriM1lbtZbF/Q8jVyA=="
},
"node_modules/sass": {
"version": "1.69.7",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.69.7.tgz",
"integrity": "sha512-rzj2soDeZ8wtE2egyLXgOOHQvaC2iosZrkF6v3EUG+tBwEvhqUCzm0VP3k9gHF9LXbSrRhT5SksoI56Iw8NPnQ==",
"version": "1.70.0",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.70.0.tgz",
"integrity": "sha512-uUxNQ3zAHeAx5nRFskBnrWzDUJrrvpCPD5FNAoRvTi0WwremlheES3tg+56PaVtCs5QDRX5CBLxxKMDJMEa1WQ==",
"dependencies": {
"chokidar": ">=3.0.0 <4.0.0",
"immutable": "^4.0.0",

View File

@@ -6,7 +6,7 @@
"dependencies": {
"@ant-design/compatible": "^5.1.2",
"@ant-design/pro-layout": "^7.17.16",
"@apollo/client": "^3.8.9",
"@apollo/client": "^3.8.10",
"@asseinfo/react-kanban": "^2.2.0",
"@craco/craco": "^7.1.0",
"@fingerprintjs/fingerprintjs": "^4.2.1",
@@ -14,7 +14,7 @@
"@reduxjs/toolkit": "^2.0.1",
"@sentry/react": "^7.93.0",
"@sentry/tracing": "^7.93.0",
"@splitsoftware/splitio-react": "^1.10.2",
"@splitsoftware/splitio-react": "^1.11.0",
"@tanem/react-nprogress": "^5.0.51",
"antd": "^5.12.8",
"apollo-link-logger": "^2.0.1",
@@ -27,7 +27,7 @@
"enquire-js": "^0.2.1",
"env-cmd": "^10.1.0",
"exifr": "^7.1.3",
"firebase": "^10.7.1",
"firebase": "^10.7.2",
"graphql": "^16.6.0",
"i18next": "^23.7.16",
"i18next-browser-languagedetector": "^7.0.2",
@@ -59,7 +59,7 @@
"react-number-format": "^5.1.4",
"react-redux": "^9.1.0",
"react-resizable": "^3.0.5",
"react-router-dom": "^6.21.2",
"react-router-dom": "^6.21.3",
"react-scripts": "^5.0.1",
"react-sticky": "^6.0.3",
"react-sublime-video": "^0.2.5",
@@ -70,7 +70,7 @@
"redux-saga": "^1.3.0",
"redux-state-sync": "^3.1.4",
"reselect": "^5.1.0",
"sass": "^1.69.7",
"sass": "^1.70.0",
"socket.io-client": "^4.7.4",
"styled-components": "^6.1.8",
"subscriptions-transport-ws": "^0.11.0",
@@ -121,7 +121,7 @@
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
"@sentry/webpack-plugin": "^2.10.2",
"@testing-library/cypress": "^10.0.1",
"cypress": "^13.6.2",
"cypress": "^13.6.3",
"eslint-plugin-cypress": "^2.15.1",
"react-error-overlay": "6.0.11",
"redux-logger": "^3.0.6",

View File

@@ -48,10 +48,6 @@ export function App({bodyshop, checkUserSession, currentUser, online, setOnline}
const [listenersAdded, setListenersAdded] = useState(false)
const {t} = useTranslation();
// Handle The Beta Switch.
useEffect(() => {
handleBeta();
}, [])
useEffect(() => {
if (!navigator.onLine) {
@@ -59,7 +55,7 @@ export function App({bodyshop, checkUserSession, currentUser, online, setOnline}
}
checkUserSession();
}, [checkUserSession, setOnline]);
}, [checkUserSession, setOnline]);
//const b = Grid.useBreakpoint();
// console.log("Breakpoints:", b);
@@ -105,6 +101,8 @@ export function App({bodyshop, checkUserSession, currentUser, online, setOnline}
return <LoadingSpinner message={t("general.labels.loggingin")}/>;
}
handleBeta();
if (!online)
return (
<Result

View File

@@ -1,15 +1,37 @@
import React from "react";
import { Card } from "antd";
import React from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { Link } from "react-router-dom";
import { createStructuredSelector } from "reselect";
import { selectTechnician } from "../../redux/tech/tech.selectors";
export default function JobDetailCardTemplate({
const mapStateToProps = createStructuredSelector({
technician: selectTechnician,
});
const mapDispatchToProps = (dispatch) => ({
//setUserLanguage: language => dispatch(setUserLanguage(language))
});
export default connect(
mapStateToProps,
mapDispatchToProps
)(JobDetailCardTemplate);
export function JobDetailCardTemplate({
loading,
title,
extraLink,
technician,
...otherProps
}) {
const { t } = useTranslation();
let extra;
if (extraLink) extra = { extra: <Link to={extraLink}>More</Link> };
if (extraLink && !technician)
extra = {
extra: <Link to={extraLink}>{t("jobs.labels.cards.more")}</Link>,
};
return (
<Card
size="small"

View File

@@ -15,6 +15,7 @@ import { setModalContext } from "../../redux/modals/modals.actions";
import { selectBodyshop } from "../../redux/user/user.selectors";
import CurrencyFormatter from "../../utils/CurrencyFormatter";
import { DateTimeFormatter } from "../../utils/DateFormatter";
import PhoneNumberFormatter from "../../utils/PhoneFormatter";
import ChatOpenButton from "../chat-open-button/chat-open-button.component";
import DataLabel from "../data-label/data-label.component";
import JobAltTransportChange from "../job-at-change/job-at-change.component";
@@ -160,19 +161,35 @@ export function JobsDetailHeader({ job, bodyshop, disabled }) {
<Card
style={{ height: "100%" }}
title={
<Link to={disabled ? "#" : `/manage/owners/${job.owner.id}`}>
{ownerTitle.length > 0
? ownerTitle
: t("owner.labels.noownerinfo")}
</Link>
disabled ? (
<>
{ownerTitle.length > 0
? ownerTitle
: t("owner.labels.noownerinfo")}
</>
) : (
<Link to={`/manage/owners/${job.owner.id}`}>
{ownerTitle.length > 0
? ownerTitle
: t("owner.labels.noownerinfo")}
</Link>
)
}
>
<div>
<DataLabel key="2" label={t("jobs.fields.ownr_ph1")}>
<ChatOpenButton phone={job.ownr_ph1} jobid={job.id} />
{disabled ? (
<PhoneNumberFormatter>{job.ownr_ph1}</PhoneNumberFormatter>
) : (
<ChatOpenButton phone={job.ownr_ph1} jobid={job.id} />
)}
</DataLabel>
<DataLabel key="22" label={t("jobs.fields.ownr_ph2")}>
<ChatOpenButton phone={job.ownr_ph2} jobid={job.id} />
{disabled ? (
<PhoneNumberFormatter>{job.ownr_ph2}</PhoneNumberFormatter>
) : (
<ChatOpenButton phone={job.ownr_ph2} jobid={job.id} />
)}
</DataLabel>
<DataLabel key="3" label={t("owners.fields.address")}>
{`${job.ownr_addr1 || ""} ${job.ownr_addr2 || ""} ${
@@ -180,7 +197,11 @@ export function JobsDetailHeader({ job, bodyshop, disabled }) {
} ${job.ownr_st || ""} ${job.ownr_zip || ""}`}
</DataLabel>
<DataLabel key="4" label={t("owners.fields.ownr_ea")}>
{job.ownr_ea || ""}
{disabled ? (
<>{job.ownr_ea || ""}</>
) : job.ownr_ea ? (
<a href={`mailto:${job.ownr_ea}`}>{job.ownr_ea}</a>
) : null}
</DataLabel>
{job.owner?.tax_number && (
<DataLabel key="5" label={t("owners.fields.tax_number")}>
@@ -195,17 +216,19 @@ export function JobsDetailHeader({ job, bodyshop, disabled }) {
style={{ height: "100%" }}
title={
job.vehicle ? (
<Link
to={
disabled
? "#"
: job.vehicle && `/manage/vehicles/${job.vehicle.id}`
}
>
{vehicleTitle.length > 0
? vehicleTitle
: t("vehicles.labels.novehinfo")}
</Link>
disabled ? (
<>
{vehicleTitle.length > 0
? vehicleTitle
: t("vehicles.labels.novehinfo")}{" "}
</>
) : (
<Link to={job.vehicle && `/manage/vehicles/${job.vehicle.id}`}>
{vehicleTitle.length > 0
? vehicleTitle
: t("vehicles.labels.novehinfo")}
</Link>
)
) : (
<span></span>
)
@@ -223,7 +246,9 @@ export function JobsDetailHeader({ job, bodyshop, disabled }) {
</VehicleVinDisplay>
{bodyshop.pbs_serialnumber || bodyshop.cdk_dealerid ? (
job.v_vin?.length !== 17 ? (
<WarningFilled style={{ color: "tomato", marginLeft: ".3rem" }} />
<WarningFilled
style={{ color: "tomato", marginLeft: ".3rem" }}
/>
) : null
) : null}
</DataLabel>
@@ -231,7 +256,7 @@ export function JobsDetailHeader({ job, bodyshop, disabled }) {
{job.regie_number || t("general.labels.na")}
</DataLabel>
<DataLabel label={t("jobs.labels.relatedros")}>
<JobsRelatedRos jobid={job.id} job={job} />
<JobsRelatedRos jobid={job.id} job={job} disabled={disabled} />
</DataLabel>
{job.vehicle && job.vehicle.notes && (
<DataLabel

View File

@@ -2,7 +2,7 @@ import { Space, Tag } from "antd";
import React from "react";
import { Link } from "react-router-dom";
export default function JobsRelatedRos({ jobid, job }) {
export default function JobsRelatedRos({ jobid, job, disabled }) {
if (!(job && job.vehicle && job.vehicle.jobs)) return null;
return (
<Space wrap>
@@ -10,9 +10,15 @@ export default function JobsRelatedRos({ jobid, job }) {
.filter((j) => j.id !== job.id)
.map((j) => (
<Tag key={j.id}>
<Link to={`/manage/jobs/${j?.id}`}>{`${j.ro_number || "N/A"}${
j.clm_no ? ` | ${j.clm_no}` : ""
}${j.status ? ` | ${j.status}` : ""}`}</Link>
{disabled ? (
<>{`${j.ro_number || "N/A"}${j.clm_no ? ` | ${j.clm_no}` : ""}${
j.status ? ` | ${j.status}` : ""
}`}</>
) : (
<Link to={`/manage/jobs/${j?.id}`}>{`${j.ro_number || "N/A"}${
j.clm_no ? ` | ${j.clm_no}` : ""
}${j.status ? ` | ${j.status}` : ""}`}</Link>
)}
</Tag>
))}
</Space>

View File

@@ -76,7 +76,14 @@ const r = ({ technician, state, activeStatuses, data, bodyshop }) => {
dataIndex: "ownr",
key: "ownr",
ellipsis: true,
render: (text, record) => <OwnerNameDisplay ownerObject={record} />,
render: (text, record) =>
technician ? (
<OwnerNameDisplay ownerObject={record} />
) : (
<Link to={`/manage/owners/${record.ownerid}`}>
<OwnerNameDisplay ownerObject={record} />
</Link>
),
sorter: (a, b) => alphaSort(a.ownr_ln, b.ownr_ln),
sortOrder:
state.sortedInfo.columnKey === "ownr" && state.sortedInfo.order,
@@ -93,13 +100,18 @@ const r = ({ technician, state, activeStatuses, data, bodyshop }) => {
),
sortOrder:
state.sortedInfo.columnKey === "vehicle" && state.sortedInfo.order,
render: (text, record) => (
<Link to={`/manage/vehicles/${record.vehicleid}`}>{`${
record.v_model_yr || ""
} ${record.v_make_desc || ""} ${record.v_model_desc || ""} ${
record.v_color || ""
} ${record.plate_no || ""}`}</Link>
),
render: (text, record) =>
technician ? (
<>{`${record.v_model_yr || ""} ${record.v_make_desc || ""} ${
record.v_model_desc || ""
} ${record.v_color || ""} ${record.plate_no || ""}`}</>
) : (
<Link to={`/manage/vehicles/${record.vehicleid}`}>{`${
record.v_model_yr || ""
} ${record.v_make_desc || ""} ${record.v_model_desc || ""} ${
record.v_color || ""
} ${record.plate_no || ""}`}</Link>
),
},
{
title: i18n.t("jobs.fields.actual_in"),

View File

@@ -14,12 +14,14 @@ import { selectTechnician } from "../../redux/tech/tech.selectors";
import { selectBodyshop } from "../../redux/user/user.selectors";
import CurrencyFormatter from "../../utils/CurrencyFormatter";
import { DateFormatter } from "../../utils/DateFormatter";
import PhoneNumberFormatter from "../../utils/PhoneFormatter";
import AlertComponent from "../alert/alert.component";
import StartChatButton from "../chat-open-button/chat-open-button.component";
import JobAtChange from "../job-at-change/job-at-change.component";
import JobDetailCardsDocumentsComponent from "../job-detail-cards/job-detail-cards.documents.component";
import JobDetailCardsNotesComponent from "../job-detail-cards/job-detail-cards.notes.component";
import JobDetailCardsPartsComponent from "../job-detail-cards/job-detail-cards.parts.component";
import CardTemplate from "../job-detail-cards/job-detail-cards.template.component";
import JobEmployeeAssignments from "../job-employee-assignments/job-employee-assignments.container";
import ScoreboardAddButton from "../job-scoreboard-add-button/job-scoreboard-add-button.component";
import LoadingSkeleton from "../loading-skeleton/loading-skeleton.component";
@@ -104,65 +106,85 @@ export function ProductionListDetail({
{error && <AlertComponent error={JSON.stringify(error)} />}
{!loading && data && (
<div>
<JobEmployeeAssignments job={data.jobs_by_pk} refetch={refetch} />
<Descriptions bordered column={1}>
<Descriptions.Item label={t("jobs.fields.ro_number")}>
{theJob.ro_number || ""}
</Descriptions.Item>
<Descriptions.Item label={t("jobs.fields.alt_transport")}>
<Space>
{data.jobs_by_pk.alt_transport || ""}
<JobAtChange event={{ job: data.jobs_by_pk }} />
</Space>
</Descriptions.Item>
<Descriptions.Item label={t("jobs.fields.clm_no")}>
{theJob.clm_no || ""}
</Descriptions.Item>
<Descriptions.Item label={t("jobs.fields.ins_co_nm")}>
{theJob.ins_co_nm || ""}
</Descriptions.Item>
<Descriptions.Item label={t("jobs.fields.owner")}>
<OwnerNameDisplay ownerObject={theJob} />
<StartChatButton
phone={data.jobs_by_pk.ownr_ph1}
jobid={data.jobs_by_pk.id}
/>
<StartChatButton
phone={data.jobs_by_pk.ownr_ph2}
jobid={data.jobs_by_pk.id}
/>
</Descriptions.Item>
<Descriptions.Item label={t("jobs.fields.vehicle")}>
{`${theJob.v_model_yr || ""} ${theJob.v_color || ""} ${
theJob.v_make_desc || ""
} ${theJob.v_model_desc || ""}`}
</Descriptions.Item>
<Descriptions.Item label={t("jobs.fields.clm_total")}>
<CurrencyFormatter>{theJob.clm_total}</CurrencyFormatter>
</Descriptions.Item>
<Descriptions.Item label={t("jobs.fields.actual_in")}>
<DateFormatter>{theJob.actual_in}</DateFormatter>
</Descriptions.Item>
<Descriptions.Item label={t("jobs.fields.scheduled_completion")}>
<DateFormatter>{theJob.scheduled_completion}</DateFormatter>
</Descriptions.Item>
</Descriptions>
<JobDetailCardsPartsComponent
loading={loading}
data={data ? data.jobs_by_pk : null}
/>
<JobDetailCardsNotesComponent
loading={loading}
data={data ? data.jobs_by_pk : null}
/>
{!bodyshop.uselocalmediaserver && (
<JobDetailCardsDocumentsComponent
<Space direction="vertical">
<CardTemplate
title={t("jobs.labels.employeeassignments")}
loading={loading}
>
<JobEmployeeAssignments job={data.jobs_by_pk} refetch={refetch} />
</CardTemplate>
<Descriptions bordered column={1}>
<Descriptions.Item label={t("jobs.fields.ro_number")}>
{theJob.ro_number || ""}
</Descriptions.Item>
<Descriptions.Item label={t("jobs.fields.alt_transport")}>
<Space>
{data.jobs_by_pk.alt_transport || ""}
<JobAtChange job={data.jobs_by_pk} />
</Space>
</Descriptions.Item>
<Descriptions.Item label={t("jobs.fields.clm_no")}>
{theJob.clm_no || ""}
</Descriptions.Item>
<Descriptions.Item label={t("jobs.fields.ins_co_nm")}>
{theJob.ins_co_nm || ""}
</Descriptions.Item>
<Descriptions.Item label={t("jobs.fields.owner")}>
<Space>
<OwnerNameDisplay ownerObject={theJob} />
{!technician ? (
<>
<StartChatButton
phone={data.jobs_by_pk.ownr_ph1}
jobid={data.jobs_by_pk.id}
/>
<StartChatButton
phone={data.jobs_by_pk.ownr_ph2}
jobid={data.jobs_by_pk.id}
/>
</>
) : (
<>
<PhoneNumberFormatter>
{data.jobs_by_pk.ownr_ph1}
</PhoneNumberFormatter>
<PhoneNumberFormatter>
{data.jobs_by_pk.ownr_ph2}
</PhoneNumberFormatter>
</>
)}
</Space>
</Descriptions.Item>
<Descriptions.Item label={t("jobs.fields.vehicle")}>
{`${theJob.v_model_yr || ""} ${theJob.v_color || ""} ${
theJob.v_make_desc || ""
} ${theJob.v_model_desc || ""}`}
</Descriptions.Item>
<Descriptions.Item label={t("jobs.fields.clm_total")}>
<CurrencyFormatter>{theJob.clm_total}</CurrencyFormatter>
</Descriptions.Item>
<Descriptions.Item label={t("jobs.fields.actual_in")}>
<DateFormatter>{theJob.actual_in}</DateFormatter>
</Descriptions.Item>
<Descriptions.Item label={t("jobs.fields.scheduled_completion")}>
<DateFormatter>{theJob.scheduled_completion}</DateFormatter>
</Descriptions.Item>
</Descriptions>
<JobDetailCardsPartsComponent
loading={loading}
data={data ? data.jobs_by_pk : null}
/>
)}
<JobDetailCardsNotesComponent
loading={loading}
data={data ? data.jobs_by_pk : null}
/>
{!bodyshop.uselocalmediaserver && (
<JobDetailCardsDocumentsComponent
loading={loading}
data={data ? data.jobs_by_pk : null}
/>
)}
</Space>
</div>
)}
</Drawer>

View File

@@ -5,7 +5,7 @@ export const QUERY_ALL_ACTIVE_JOBS_PAGINATED = gql`
$offset: Int
$limit: Int
$order: [jobs_order_by!]
$statuses: [String!]!,
$statuses: [String!]!
$isConverted: Boolean
) {
jobs(
@@ -120,7 +120,9 @@ export const QUERY_PARTS_QUEUE = gql`
}
}
jobs(
where: { _and: [{ status: { _in: $statuses }, converted: { _eq: true } }] }
where: {
_and: [{ status: { _in: $statuses }, converted: { _eq: true } }]
}
offset: $offset
limit: $limit
order_by: $order
@@ -336,6 +338,7 @@ export const QUERY_JOBS_IN_PRODUCTION = gql`
category
iouparent
ro_number
ownerid
ownr_fn
ownr_ln
ownr_co_nm

View File

@@ -1704,6 +1704,7 @@
"estimator": "Estimator",
"filehandler": "File Handler",
"insurance": "Insurance Details",
"more": "More",
"notes": "Notes",
"parts": "Parts",
"totals": "Totals",

View File

@@ -1704,6 +1704,7 @@
"estimator": "Estimador",
"filehandler": "File Handler",
"insurance": "detalles del seguro",
"more": "Más",
"notes": "Notas",
"parts": "Partes",
"totals": "Totales",

View File

@@ -1704,6 +1704,7 @@
"estimator": "Estimateur",
"filehandler": "Gestionnaire de fichiers",
"insurance": "Détails de l'assurance",
"more": "Plus",
"notes": "Remarques",
"parts": "les pièces",
"totals": "Totaux",

View File

@@ -24,12 +24,14 @@ export const handleBeta = () => {
// 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}`;
const href = `${window.location.protocol}//beta.${currentHostName}${window.location.pathname}${window.location.search}${window.location.hash}`;
window.location.replace(href);
}
// Beta is not enabled, but the current host name does start with beta.
else if (!isBeta && currentHostName.startsWith('beta')) {
window.location.href = `${window.location.protocol}//${currentHostName.replace('beta.', '')}${window.location.pathname}${window.location.search}${window.location.hash}`;
const href = `${window.location.protocol}//${currentHostName.replace('beta.', '')}${window.location.pathname}${window.location.search}${window.location.hash}`;
window.location.replace(href);
}
}
export default handleBeta;

View File

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