- Merge master-aio, bump packages.
Signed-off-by: Dave Richer <dave@imexsystems.ca>
This commit is contained in:
@@ -31,3 +31,11 @@
|
|||||||
|
|
||||||
These allow users to turn fields on or off, turning them all off will show the card in the most minimal form
|
These allow users to turn fields on or off, turning them all off will show the card in the most minimal form
|
||||||
|
|
||||||
|
|
||||||
|
### Statistics
|
||||||
|
|
||||||
|
- The statistics section allows users to see accumulations of both jobs on the board, and jobs in production.
|
||||||
|
- you can click a statistic to turn it on and off, and drag and drop the statistics to rearrange them
|
||||||
|
|
||||||
|
### Filters
|
||||||
|
- Allows you to set, and persist filters for estimators and insurance companies
|
||||||
|
|||||||
@@ -1,174 +1,177 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8"/>
|
||||||
<% if (env.VITE_APP_INSTANCE === 'IMEX') { %>
|
<% if (env.VITE_APP_INSTANCE === 'IMEX') { %>
|
||||||
<link rel="icon" href="/favicon.png" />
|
<link rel="icon" href="/favicon.png"/>
|
||||||
<% } %> <% if (env.VITE_APP_INSTANCE === 'ROME') { %>
|
<% } %> <% if (env.VITE_APP_INSTANCE === 'ROME') { %>
|
||||||
<link rel="icon" href="/ro-favicon.png" />
|
<link rel="icon" href="/ro-favicon.png"/>
|
||||||
<% } %> <% if (env.VITE_APP_INSTANCE === 'PROMANAGER') { %>
|
<% } %> <% if (env.VITE_APP_INSTANCE === 'PROMANAGER') { %>
|
||||||
<link rel="icon" href="/pm/pm-favicon.ico" />
|
<link rel="icon" href="/pm/pm-favicon.ico"/>
|
||||||
<% } %>
|
<% } %>
|
||||||
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
||||||
<meta name="theme-color" content="#1690ff" />
|
<meta name="theme-color" content="#1690ff"/>
|
||||||
<!-- <link rel="apple-touch-icon" href="logo192.png" /> -->
|
<!-- <link rel="apple-touch-icon" href="logo192.png" /> -->
|
||||||
<!-- TODO:AIo Update the individual logos for each.-->
|
<!-- TODO:AIo Update the individual logos for each.-->
|
||||||
<link rel="apple-touch-icon" href="public/logo192.png" />
|
<link rel="apple-touch-icon" href="public/logo192.png"/>
|
||||||
<link rel="mask-icon" href="/mask-icon.svg" color="#FFFFFF">
|
<link rel="mask-icon" href="/mask-icon.svg" color="#FFFFFF">
|
||||||
<!--
|
<!--
|
||||||
manifest.json provides metadata used when your web app is installed on a
|
manifest.json provides metadata used when your web app is installed on a
|
||||||
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
|
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
|
||||||
-->
|
-->
|
||||||
<!--
|
<!--
|
||||||
Notice the use of %PUBLIC_URL% in the tags above.
|
Notice the use of %PUBLIC_URL% in the tags above.
|
||||||
It will be replaced with the URL of the `public` folder during the build.
|
It will be replaced with the URL of the `public` folder during the build.
|
||||||
Only files inside the `public` folder can be referenced from the HTML.
|
Only files inside the `public` folder can be referenced from the HTML.
|
||||||
|
|
||||||
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
|
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
|
||||||
work correctly both with client-side routing and a non-root public URL.
|
work correctly both with client-side routing and a non-root public URL.
|
||||||
Learn how to configure a non-root public URL by running `npm run build`.
|
Learn how to configure a non-root public URL by running `npm run build`.
|
||||||
-->
|
-->
|
||||||
<% if (env.VITE_APP_INSTANCE === 'IMEX') { %>
|
<% if (env.VITE_APP_INSTANCE === 'IMEX') { %>
|
||||||
<meta name="description" content="ImEX Online" />
|
<meta name="description" content="ImEX Online"/>
|
||||||
<title>ImEX Online</title>
|
<title>ImEX Online</title>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
window.$crisp = [];
|
window.$crisp = [];
|
||||||
window.CRISP_WEBSITE_ID = '36724f62-2eb0-4b29-9cdd-9905fb99913e';
|
window.CRISP_WEBSITE_ID = '36724f62-2eb0-4b29-9cdd-9905fb99913e';
|
||||||
(function () {
|
(function () {
|
||||||
d = document;
|
d = document;
|
||||||
s = d.createElement('script');
|
s = d.createElement('script');
|
||||||
s.src = 'https://client.crisp.chat/l.js';
|
s.src = 'https://client.crisp.chat/l.js';
|
||||||
s.async = 1;
|
s.async = 1;
|
||||||
d.getElementsByTagName('head')[0].appendChild(s);
|
d.getElementsByTagName('head')[0].appendChild(s);
|
||||||
})();
|
})();
|
||||||
</script>
|
</script>
|
||||||
<% } %> <% if (env.VITE_APP_INSTANCE === 'ROME') { %>
|
<% } %> <% if (env.VITE_APP_INSTANCE === 'ROME') { %>
|
||||||
<meta name="description" content="Rome Online" />
|
<meta name="description" content="Rome Online"/>
|
||||||
<title>Rome Online</title>
|
<title>Rome Online</title>
|
||||||
|
|
||||||
<!--Use the below code snippet to provide real time updates to the live chat plugin without the need of copying and paste each time to your website when changes are made via PBX-->
|
<!--Use the below code snippet to provide real time updates to the live chat plugin without the need of copying and paste each time to your website when changes are made via PBX-->
|
||||||
|
|
||||||
<call-us-selector phonesystem-url=https://rometech.east.3cx.us:5001 party="LiveChat528346"></call-us-selector>
|
<call-us-selector phonesystem-url=https://rometech.east.3cx.us:5001
|
||||||
|
party="LiveChat528346"></call-us-selector>
|
||||||
|
|
||||||
<!--Incase you don't want real time updates to the live chat plugin when options are changed, use the below code snippet. Please note that each time you change the settings you will need to copy and paste the snippet code to your website-->
|
<!--Incase you don't want real time updates to the live chat plugin when options are changed, use the below code snippet. Please note that each time you change the settings you will need to copy and paste the snippet code to your website-->
|
||||||
|
|
||||||
<!--<call-us
|
<!--<call-us
|
||||||
|
|
||||||
phonesystem-url=https://rometech.east.3cx.us:5001
|
phonesystem-url=https://rometech.east.3cx.us:5001
|
||||||
|
|
||||||
style="position:fixed;font-size:16px;line-height:17px;z-index: 99999;right: 20px; bottom: 20px;"
|
style="position:fixed;font-size:16px;line-height:17px;z-index: 99999;right: 20px; bottom: 20px;"
|
||||||
|
|
||||||
id="wp-live-chat-by-3CX"
|
id="wp-live-chat-by-3CX"
|
||||||
|
|
||||||
minimized="true"
|
minimized="true"
|
||||||
|
|
||||||
animation-style="noanimation"
|
animation-style="noanimation"
|
||||||
|
|
||||||
party="LiveChat528346"
|
party="LiveChat528346"
|
||||||
|
|
||||||
minimized-style="bubbleright"
|
minimized-style="bubbleright"
|
||||||
|
|
||||||
allow-call="true"
|
allow-call="true"
|
||||||
|
|
||||||
allow-video="false"
|
allow-video="false"
|
||||||
|
|
||||||
allow-soundnotifications="true"
|
allow-soundnotifications="true"
|
||||||
|
|
||||||
enable-mute="true"
|
enable-mute="true"
|
||||||
|
|
||||||
enable-onmobile="true"
|
enable-onmobile="true"
|
||||||
|
|
||||||
offline-enabled="true"
|
offline-enabled="true"
|
||||||
|
|
||||||
enable="true"
|
enable="true"
|
||||||
|
|
||||||
ignore-queueownership="false"
|
ignore-queueownership="false"
|
||||||
|
|
||||||
authentication="both"
|
authentication="both"
|
||||||
|
|
||||||
show-operator-actual-name="true"
|
show-operator-actual-name="true"
|
||||||
|
|
||||||
aknowledge-received="true"
|
aknowledge-received="true"
|
||||||
|
|
||||||
gdpr-enabled="false"
|
gdpr-enabled="false"
|
||||||
|
|
||||||
message-userinfo-format="name"
|
message-userinfo-format="name"
|
||||||
|
|
||||||
message-dateformat="both"
|
message-dateformat="both"
|
||||||
|
|
||||||
lang="browser"
|
lang="browser"
|
||||||
|
|
||||||
button-icon-type="default"
|
button-icon-type="default"
|
||||||
|
|
||||||
greeting-visibility="none"
|
greeting-visibility="none"
|
||||||
|
|
||||||
greeting-offline-visibility="none"
|
greeting-offline-visibility="none"
|
||||||
|
|
||||||
chat-delay="2000"
|
chat-delay="2000"
|
||||||
|
|
||||||
enable-direct-call="true"
|
enable-direct-call="true"
|
||||||
|
|
||||||
enable-ga="false"
|
enable-ga="false"
|
||||||
|
|
||||||
></call-us>-->
|
></call-us>-->
|
||||||
|
|
||||||
<script defer src=https://downloads-global.3cx.com/downloads/livechatandtalk/v1/callus.js id="tcx-callus-js" charset="utf-8"></script>
|
<script defer src=https://downloads-global.3cx.com/downloads/livechatandtalk/v1/callus.js
|
||||||
|
id="tcx-callus-js" charset="utf-8"></script>
|
||||||
|
|
||||||
|
|
||||||
|
<% } %> <% if (env.VITE_APP_INSTANCE === 'PROMANAGER') { %>
|
||||||
|
<title>ProManager</title>
|
||||||
|
<meta name="description" content="ProManager"/>
|
||||||
|
|
||||||
<% } %> <% if (env.VITE_APP_INSTANCE === 'PROMANAGER') { %>
|
<% } %>
|
||||||
<title>ProManager</title>
|
<script>
|
||||||
<meta name="description" content="ProManager" />
|
!(function () {
|
||||||
|
'use strict';
|
||||||
|
var e = [
|
||||||
|
'debug',
|
||||||
|
'destroy',
|
||||||
|
'do',
|
||||||
|
'help',
|
||||||
|
'identify',
|
||||||
|
'is',
|
||||||
|
'off',
|
||||||
|
'on',
|
||||||
|
'ready',
|
||||||
|
'render',
|
||||||
|
'reset',
|
||||||
|
'safe',
|
||||||
|
'set',
|
||||||
|
];
|
||||||
|
if (window.noticeable) console.warn('Noticeable SDK code snippet loaded more than once');
|
||||||
|
else {
|
||||||
|
var n = (window.noticeable = window.noticeable || []);
|
||||||
|
|
||||||
<% } %>
|
function t(e) {
|
||||||
<script>
|
return function () {
|
||||||
!(function () {
|
var t = Array.prototype.slice.call(arguments);
|
||||||
'use strict';
|
return t.unshift(e), n.push(t), n;
|
||||||
var e = [
|
};
|
||||||
'debug',
|
|
||||||
'destroy',
|
|
||||||
'do',
|
|
||||||
'help',
|
|
||||||
'identify',
|
|
||||||
'is',
|
|
||||||
'off',
|
|
||||||
'on',
|
|
||||||
'ready',
|
|
||||||
'render',
|
|
||||||
'reset',
|
|
||||||
'safe',
|
|
||||||
'set',
|
|
||||||
];
|
|
||||||
if (window.noticeable) console.warn('Noticeable SDK code snippet loaded more than once');
|
|
||||||
else {
|
|
||||||
var n = (window.noticeable = window.noticeable || []);
|
|
||||||
function t(e) {
|
|
||||||
return function () {
|
|
||||||
var t = Array.prototype.slice.call(arguments);
|
|
||||||
return t.unshift(e), n.push(t), n;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
!(function () {
|
|
||||||
for (var o = 0; o < e.length; o++) {
|
|
||||||
var r = e[o];
|
|
||||||
n[r] = t(r);
|
|
||||||
}
|
|
||||||
})(),
|
|
||||||
(function () {
|
|
||||||
var e = document.createElement('script');
|
|
||||||
(e.async = !0), (e.src = 'https://sdk.noticeable.io/l.js');
|
|
||||||
var n = document.head;
|
|
||||||
n.insertBefore(e, n.firstChild);
|
|
||||||
})();
|
|
||||||
}
|
}
|
||||||
})();
|
|
||||||
</script>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
|
||||||
<div id="root"></div>
|
|
||||||
|
|
||||||
<script type="module" src="src/index.jsx"></script>
|
!(function () {
|
||||||
</body>
|
for (var o = 0; o < e.length; o++) {
|
||||||
|
var r = e[o];
|
||||||
|
n[r] = t(r);
|
||||||
|
}
|
||||||
|
})(),
|
||||||
|
(function () {
|
||||||
|
var e = document.createElement('script');
|
||||||
|
(e.async = !0), (e.src = 'https://sdk.noticeable.io/l.js');
|
||||||
|
var n = document.head;
|
||||||
|
n.insertBefore(e, n.firstChild);
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||||
|
<div id="root"></div>
|
||||||
|
|
||||||
|
<script type="module" src="src/index.jsx"></script>
|
||||||
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
680
client/package-lock.json
generated
680
client/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -2,15 +2,14 @@
|
|||||||
"name": "bodyshop",
|
"name": "bodyshop",
|
||||||
"version": "0.2.1",
|
"version": "0.2.1",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=20.15.0"
|
"node": ">=18.18.2"
|
||||||
},
|
},
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"private": true,
|
"private": true,
|
||||||
"proxy": "http://localhost:4000",
|
"proxy": "http://localhost:4000",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ant-design/icons": "^5.4.0",
|
|
||||||
"@ant-design/pro-layout": "^7.19.12",
|
"@ant-design/pro-layout": "^7.19.12",
|
||||||
"@apollo/client": "^3.11.3",
|
"@apollo/client": "^3.11.4",
|
||||||
"@emotion/is-prop-valid": "^1.3.0",
|
"@emotion/is-prop-valid": "^1.3.0",
|
||||||
"@fingerprintjs/fingerprintjs": "^4.4.3",
|
"@fingerprintjs/fingerprintjs": "^4.4.3",
|
||||||
"@jsreport/browser-client": "^3.1.0",
|
"@jsreport/browser-client": "^3.1.0",
|
||||||
@@ -20,11 +19,11 @@
|
|||||||
"@splitsoftware/splitio-react": "^1.12.1",
|
"@splitsoftware/splitio-react": "^1.12.1",
|
||||||
"@tanem/react-nprogress": "^5.0.51",
|
"@tanem/react-nprogress": "^5.0.51",
|
||||||
"@vitejs/plugin-react": "^4.3.1",
|
"@vitejs/plugin-react": "^4.3.1",
|
||||||
"antd": "^5.20.0",
|
"antd": "^5.20.2",
|
||||||
"apollo-link-logger": "^2.0.1",
|
"apollo-link-logger": "^2.0.1",
|
||||||
"apollo-link-sentry": "^3.3.0",
|
"apollo-link-sentry": "^3.3.0",
|
||||||
"autosize": "^6.0.1",
|
"autosize": "^6.0.1",
|
||||||
"axios": "^1.7.3",
|
"axios": "^1.7.4",
|
||||||
"classnames": "^2.5.1",
|
"classnames": "^2.5.1",
|
||||||
"css-box-model": "^1.2.1",
|
"css-box-model": "^1.2.1",
|
||||||
"dayjs": "^1.11.12",
|
"dayjs": "^1.11.12",
|
||||||
@@ -33,12 +32,12 @@
|
|||||||
"dotenv": "^16.4.5",
|
"dotenv": "^16.4.5",
|
||||||
"env-cmd": "^10.1.0",
|
"env-cmd": "^10.1.0",
|
||||||
"exifr": "^7.1.3",
|
"exifr": "^7.1.3",
|
||||||
"firebase": "^10.12.5",
|
"firebase": "^10.13.0",
|
||||||
"graphql": "^16.9.0",
|
"graphql": "^16.9.0",
|
||||||
"i18next": "^23.12.2",
|
"i18next": "^23.14.0",
|
||||||
"i18next-browser-languagedetector": "^8.0.0",
|
"i18next-browser-languagedetector": "^8.0.0",
|
||||||
"immutability-helper": "^3.1.1",
|
"immutability-helper": "^3.1.1",
|
||||||
"libphonenumber-js": "^1.11.5",
|
"libphonenumber-js": "^1.11.7",
|
||||||
"logrocket": "^8.1.2",
|
"logrocket": "^8.1.2",
|
||||||
"markerjs2": "^2.32.1",
|
"markerjs2": "^2.32.1",
|
||||||
"memoize-one": "^6.0.0",
|
"memoize-one": "^6.0.0",
|
||||||
@@ -48,7 +47,7 @@
|
|||||||
"query-string": "^9.1.0",
|
"query-string": "^9.1.0",
|
||||||
"raf-schd": "^4.0.3",
|
"raf-schd": "^4.0.3",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-big-calendar": "^1.13.2",
|
"react-big-calendar": "^1.13.3",
|
||||||
"react-color": "^2.19.3",
|
"react-color": "^2.19.3",
|
||||||
"react-cookie": "^7.2.0",
|
"react-cookie": "^7.2.0",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^18.3.1",
|
||||||
@@ -56,19 +55,18 @@
|
|||||||
"react-grid-gallery": "^1.0.1",
|
"react-grid-gallery": "^1.0.1",
|
||||||
"react-grid-layout": "1.3.4",
|
"react-grid-layout": "1.3.4",
|
||||||
"react-i18next": "^14.1.3",
|
"react-i18next": "^14.1.3",
|
||||||
"react-icons": "^5.2.1",
|
"react-icons": "^5.3.0",
|
||||||
"react-image-lightbox": "^5.1.4",
|
"react-image-lightbox": "^5.1.4",
|
||||||
"react-joyride": "^2.8.2",
|
|
||||||
"react-markdown": "^9.0.1",
|
"react-markdown": "^9.0.1",
|
||||||
"react-number-format": "^5.4.0",
|
"react-number-format": "^5.4.0",
|
||||||
"react-popopo": "^2.1.9",
|
"react-popopo": "^2.1.9",
|
||||||
"react-product-fruits": "^2.2.6",
|
"react-product-fruits": "^2.2.61",
|
||||||
"react-redux": "^9.1.2",
|
"react-redux": "^9.1.2",
|
||||||
"react-resizable": "^3.0.5",
|
"react-resizable": "^3.0.5",
|
||||||
"react-router-dom": "^6.26.0",
|
"react-router-dom": "^6.26.1",
|
||||||
"react-sticky": "^6.0.3",
|
"react-sticky": "^6.0.3",
|
||||||
"react-virtualized": "^9.22.5",
|
"react-virtualized": "^9.22.5",
|
||||||
"react-virtuoso": "^4.9.0",
|
"react-virtuoso": "^4.10.1",
|
||||||
"recharts": "^2.12.7",
|
"recharts": "^2.12.7",
|
||||||
"redux": "^5.0.1",
|
"redux": "^5.0.1",
|
||||||
"redux-actions": "^3.0.3",
|
"redux-actions": "^3.0.3",
|
||||||
@@ -81,7 +79,7 @@
|
|||||||
"styled-components": "^6.1.12",
|
"styled-components": "^6.1.12",
|
||||||
"subscriptions-transport-ws": "^0.11.0",
|
"subscriptions-transport-ws": "^0.11.0",
|
||||||
"use-memo-one": "^1.1.3",
|
"use-memo-one": "^1.1.3",
|
||||||
"userpilot": "^1.3.2",
|
"userpilot": "^1.3.5",
|
||||||
"vite-plugin-ejs": "^1.7.0",
|
"vite-plugin-ejs": "^1.7.0",
|
||||||
"web-vitals": "^3.5.2"
|
"web-vitals": "^3.5.2"
|
||||||
},
|
},
|
||||||
@@ -132,15 +130,15 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
|
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
|
||||||
"@babel/preset-react": "^7.24.7",
|
"@babel/preset-react": "^7.24.7",
|
||||||
"@dotenvx/dotenvx": "^1.6.4",
|
"@dotenvx/dotenvx": "^1.7.0",
|
||||||
"@emotion/babel-plugin": "^11.12.0",
|
"@emotion/babel-plugin": "^11.12.0",
|
||||||
"@emotion/react": "^11.13.0",
|
"@emotion/react": "^11.13.0",
|
||||||
"@sentry/webpack-plugin": "^2.22.0",
|
"@sentry/webpack-plugin": "^2.22.2",
|
||||||
"@testing-library/cypress": "^10.0.2",
|
"@testing-library/cypress": "^10.0.2",
|
||||||
"browserslist": "^4.23.3",
|
"browserslist": "^4.23.3",
|
||||||
"browserslist-to-esbuild": "^2.1.1",
|
"browserslist-to-esbuild": "^2.1.1",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"cypress": "^13.13.2",
|
"cypress": "^13.13.3",
|
||||||
"eslint": "^8.57.0",
|
"eslint": "^8.57.0",
|
||||||
"eslint-config-react-app": "^7.0.1",
|
"eslint-config-react-app": "^7.0.1",
|
||||||
"eslint-plugin-cypress": "^2.15.1",
|
"eslint-plugin-cypress": "^2.15.1",
|
||||||
@@ -149,7 +147,7 @@
|
|||||||
"react-error-overlay": "6.0.11",
|
"react-error-overlay": "6.0.11",
|
||||||
"redux-logger": "^3.0.6",
|
"redux-logger": "^3.0.6",
|
||||||
"source-map-explorer": "^2.5.3",
|
"source-map-explorer": "^2.5.3",
|
||||||
"vite": "^5.3.5",
|
"vite": "^5.4.1",
|
||||||
"vite-plugin-babel": "^1.2.0",
|
"vite-plugin-babel": "^1.2.0",
|
||||||
"vite-plugin-eslint": "^1.8.1",
|
"vite-plugin-eslint": "^1.8.1",
|
||||||
"vite-plugin-legacy": "^2.1.0",
|
"vite-plugin-legacy": "^2.1.0",
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import { checkUserSession } from "../redux/user/user.actions";
|
|||||||
import { selectBodyshop, selectCurrentEula, selectCurrentUser } from "../redux/user/user.selectors";
|
import { selectBodyshop, selectCurrentEula, selectCurrentUser } from "../redux/user/user.selectors";
|
||||||
import PrivateRoute from "../components/PrivateRoute";
|
import PrivateRoute from "../components/PrivateRoute";
|
||||||
import "./App.styles.scss";
|
import "./App.styles.scss";
|
||||||
import handleBeta from "../utils/betaHandler";
|
import handleBeta from "../utils/handleBeta";
|
||||||
import Eula from "../components/eula/eula.component";
|
import Eula from "../components/eula/eula.component";
|
||||||
import InstanceRenderMgr from "../utils/instanceRenderMgr";
|
import InstanceRenderMgr from "../utils/instanceRenderMgr";
|
||||||
import ProductFruitsWrapper from "./ProductFruitsWrapper.jsx";
|
import ProductFruitsWrapper from "./ProductFruitsWrapper.jsx";
|
||||||
|
|||||||
@@ -161,3 +161,15 @@
|
|||||||
.rowWithColor > td {
|
.rowWithColor > td {
|
||||||
background-color: var(--bgColor) !important;
|
background-color: var(--bgColor) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.muted-button {
|
||||||
|
color: lightgray;
|
||||||
|
border: none;
|
||||||
|
background: none;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 16px; /* Adjust as needed */
|
||||||
|
}
|
||||||
|
|
||||||
|
.muted-button:hover {
|
||||||
|
color: darkgrey;
|
||||||
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import { createStructuredSelector } from "reselect";
|
|||||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||||
import { DateFormatter } from "../../utils/DateFormatter";
|
import { DateFormatter } from "../../utils/DateFormatter";
|
||||||
import ExportLogsCountDisplay from "../export-logs-count-display/export-logs-count-display.component";
|
import ExportLogsCountDisplay from "../export-logs-count-display/export-logs-count-display.component";
|
||||||
|
import JobMarkSelectedExported from "../jobs-mark-selected-exported/jobs-mark-selected-exported";
|
||||||
import OwnerNameDisplay, { OwnerNameDisplayFunction } from "../owner-name-display/owner-name-display.component";
|
import OwnerNameDisplay, { OwnerNameDisplayFunction } from "../owner-name-display/owner-name-display.component";
|
||||||
import QboAuthorizeComponent from "../qbo-authorize/qbo-authorize.component";
|
import QboAuthorizeComponent from "../qbo-authorize/qbo-authorize.component";
|
||||||
|
|
||||||
@@ -170,13 +171,22 @@ export function AccountingReceivablesTableComponent({ bodyshop, loading, jobs, r
|
|||||||
extra={
|
extra={
|
||||||
<Space wrap>
|
<Space wrap>
|
||||||
{!bodyshop.cdk_dealerid && !bodyshop.pbs_serialnumber && (
|
{!bodyshop.cdk_dealerid && !bodyshop.pbs_serialnumber && (
|
||||||
<JobsExportAllButton
|
<>
|
||||||
jobIds={selectedJobs}
|
<JobMarkSelectedExported
|
||||||
disabled={transInProgress || selectedJobs.length === 0}
|
jobIds={selectedJobs}
|
||||||
loadingCallback={setTransInProgress}
|
disabled={transInProgress || selectedJobs.length === 0}
|
||||||
completedCallback={setSelectedJobs}
|
loadingCallback={setTransInProgress}
|
||||||
refetch={refetch}
|
completedCallback={setSelectedJobs}
|
||||||
/>
|
refetch={refetch}
|
||||||
|
/>
|
||||||
|
<JobsExportAllButton
|
||||||
|
jobIds={selectedJobs}
|
||||||
|
disabled={transInProgress || selectedJobs.length === 0}
|
||||||
|
loadingCallback={setTransInProgress}
|
||||||
|
completedCallback={setSelectedJobs}
|
||||||
|
refetch={refetch}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
{bodyshop.accountingconfig && bodyshop.accountingconfig.qbo && <QboAuthorizeComponent />}
|
{bodyshop.accountingconfig && bodyshop.accountingconfig.qbo && <QboAuthorizeComponent />}
|
||||||
<Input.Search
|
<Input.Search
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
import { PageHeader } from "@ant-design/pro-layout";
|
||||||
import { useMutation, useQuery } from "@apollo/client";
|
import { useMutation, useQuery } from "@apollo/client";
|
||||||
import { Button, Divider, Form, Popconfirm, Space } from "antd";
|
import { Button, Divider, Form, Popconfirm, Space } from "antd";
|
||||||
import dayjs from "../../utils/day";
|
|
||||||
import queryString from "query-string";
|
import queryString from "query-string";
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
@@ -13,6 +13,7 @@ import { insertAuditTrail } from "../../redux/application/application.actions";
|
|||||||
import { setModalContext } from "../../redux/modals/modals.actions";
|
import { setModalContext } from "../../redux/modals/modals.actions";
|
||||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||||
import AuditTrailMapping from "../../utils/AuditTrailMappings";
|
import AuditTrailMapping from "../../utils/AuditTrailMappings";
|
||||||
|
import dayjs from "../../utils/day";
|
||||||
import AlertComponent from "../alert/alert.component";
|
import AlertComponent from "../alert/alert.component";
|
||||||
import BillFormContainer from "../bill-form/bill-form.container";
|
import BillFormContainer from "../bill-form/bill-form.container";
|
||||||
import BillMarkExportedButton from "../bill-mark-exported-button/bill-mark-exported-button.component";
|
import BillMarkExportedButton from "../bill-mark-exported-button/bill-mark-exported-button.component";
|
||||||
@@ -22,7 +23,6 @@ import JobDocumentsGallery from "../jobs-documents-gallery/jobs-documents-galler
|
|||||||
import JobsDocumentsLocalGallery from "../jobs-documents-local-gallery/jobs-documents-local-gallery.container";
|
import JobsDocumentsLocalGallery from "../jobs-documents-local-gallery/jobs-documents-local-gallery.container";
|
||||||
import LoadingSkeleton from "../loading-skeleton/loading-skeleton.component";
|
import LoadingSkeleton from "../loading-skeleton/loading-skeleton.component";
|
||||||
import BillDetailEditReturn from "./bill-detail-edit-return.component";
|
import BillDetailEditReturn from "./bill-detail-edit-return.component";
|
||||||
import { PageHeader } from "@ant-design/pro-layout";
|
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
bodyshop: selectBodyshop
|
bodyshop: selectBodyshop
|
||||||
@@ -153,6 +153,7 @@ export function BillDetailEditcontainer({ setPartsOrderContext, insertAuditTrail
|
|||||||
if (!search.billid) return <></>; //<div>{t("bills.labels.noneselected")}</div>;
|
if (!search.billid) return <></>; //<div>{t("bills.labels.noneselected")}</div>;
|
||||||
|
|
||||||
const exported = data && data.bills_by_pk && data.bills_by_pk.exported;
|
const exported = data && data.bills_by_pk && data.bills_by_pk.exported;
|
||||||
|
const isinhouse = data && data.bills_by_pk && data.bills_by_pk.isinhouse;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -188,7 +189,7 @@ export function BillDetailEditcontainer({ setPartsOrderContext, insertAuditTrail
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<Form form={form} onFinish={handleFinish} initialValues={transformData(data)} layout="vertical">
|
<Form form={form} onFinish={handleFinish} initialValues={transformData(data)} layout="vertical">
|
||||||
<BillFormContainer form={form} billEdit disabled={exported} />
|
<BillFormContainer form={form} billEdit disabled={exported} disableInHouse={isinhouse} />
|
||||||
<Divider orientation="left">{t("general.labels.media")}</Divider>
|
<Divider orientation="left">{t("general.labels.media")}</Divider>
|
||||||
{bodyshop.uselocalmediaserver ? (
|
{bodyshop.uselocalmediaserver ? (
|
||||||
<JobsDocumentsLocalGallery
|
<JobsDocumentsLocalGallery
|
||||||
|
|||||||
@@ -41,7 +41,8 @@ export function BillFormComponent({
|
|||||||
job,
|
job,
|
||||||
loadOutstandingReturns,
|
loadOutstandingReturns,
|
||||||
loadInventory,
|
loadInventory,
|
||||||
preferredMake
|
preferredMake,
|
||||||
|
disableInHouse
|
||||||
}) {
|
}) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const client = useApolloClient();
|
const client = useApolloClient();
|
||||||
@@ -177,7 +178,7 @@ export function BillFormComponent({
|
|||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<VendorSearchSelect
|
<VendorSearchSelect
|
||||||
disabled={disabled}
|
disabled={disabled || disableInHouse}
|
||||||
options={vendorAutoCompleteOptions}
|
options={vendorAutoCompleteOptions}
|
||||||
preferredMake={preferredMake}
|
preferredMake={preferredMake}
|
||||||
onSelect={handleVendorSelect}
|
onSelect={handleVendorSelect}
|
||||||
@@ -243,7 +244,7 @@ export function BillFormComponent({
|
|||||||
})
|
})
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<Input disabled={disabled || disableInvNumber} />
|
<Input disabled={disabled || disableInvNumber || disableInHouse} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("bills.fields.date")}
|
label={t("bills.fields.date")}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ const mapStateToProps = createStructuredSelector({
|
|||||||
bodyshop: selectBodyshop
|
bodyshop: selectBodyshop
|
||||||
});
|
});
|
||||||
|
|
||||||
export function BillFormContainer({ bodyshop, form, billEdit, disabled, disableInvNumber }) {
|
export function BillFormContainer({ bodyshop, form, billEdit, disabled, disableInvNumber, disableInHouse }) {
|
||||||
const {
|
const {
|
||||||
treatments: { Simple_Inventory }
|
treatments: { Simple_Inventory }
|
||||||
} = useSplitTreatments({
|
} = useSplitTreatments({
|
||||||
@@ -47,6 +47,7 @@ export function BillFormContainer({ bodyshop, form, billEdit, disabled, disableI
|
|||||||
job={lineData ? lineData.jobs_by_pk : null}
|
job={lineData ? lineData.jobs_by_pk : null}
|
||||||
responsibilityCenters={bodyshop.md_responsibility_centers || null}
|
responsibilityCenters={bodyshop.md_responsibility_centers || null}
|
||||||
disableInvNumber={disableInvNumber}
|
disableInvNumber={disableInvNumber}
|
||||||
|
disableInHouse={disableInHouse}
|
||||||
loadOutstandingReturns={loadOutstandingReturns}
|
loadOutstandingReturns={loadOutstandingReturns}
|
||||||
loadInventory={loadInventory}
|
loadInventory={loadInventory}
|
||||||
preferredMake={lineData ? lineData.jobs_by_pk.v_make_desc : null}
|
preferredMake={lineData ? lineData.jobs_by_pk.v_make_desc : null}
|
||||||
|
|||||||
@@ -36,9 +36,6 @@ export default function DashboardScheduledOutToday({ data, ...cardProps }) {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log("Scheduled Out Today");
|
|
||||||
console.dir(scheduledOutToday);
|
|
||||||
|
|
||||||
const tvFontSize = 18;
|
const tvFontSize = 18;
|
||||||
const tvFontWeight = "bold";
|
const tvFontWeight = "bold";
|
||||||
|
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ import { selectRecentItems, selectSelectedHeader } from "../../redux/application
|
|||||||
import { setModalContext } from "../../redux/modals/modals.actions";
|
import { setModalContext } from "../../redux/modals/modals.actions";
|
||||||
import { signOutStart } from "../../redux/user/user.actions";
|
import { signOutStart } from "../../redux/user/user.actions";
|
||||||
import { selectBodyshop, selectCurrentUser } from "../../redux/user/user.selectors";
|
import { selectBodyshop, selectCurrentUser } from "../../redux/user/user.selectors";
|
||||||
import { checkBeta, handleBeta, setBeta } from "../../utils/betaHandler";
|
import { checkBeta, handleBeta, setBeta } from "../../utils/handleBeta";
|
||||||
import InstanceRenderManager from "../../utils/instanceRenderMgr";
|
import InstanceRenderManager from "../../utils/instanceRenderMgr";
|
||||||
import { HasFeatureAccess } from "../feature-wrapper/feature-wrapper.component";
|
import { HasFeatureAccess } from "../feature-wrapper/feature-wrapper.component";
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import { useSplitTreatments } from "@splitsoftware/splitio-react";
|
|||||||
import { Col, Row, notification } from "antd";
|
import { Col, Row, notification } from "antd";
|
||||||
import Axios from "axios";
|
import Axios from "axios";
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
import dayjs from "../../utils/day";
|
|
||||||
import queryString from "query-string";
|
import queryString from "query-string";
|
||||||
import React, { useCallback, useEffect, useState } from "react";
|
import React, { useCallback, useEffect, useState } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
@@ -24,6 +23,8 @@ import { selectBodyshop, selectCurrentUser } from "../../redux/user/user.selecto
|
|||||||
import AuditTrailMapping from "../../utils/AuditTrailMappings";
|
import AuditTrailMapping from "../../utils/AuditTrailMappings";
|
||||||
import confirmDialog from "../../utils/asyncConfirm";
|
import confirmDialog from "../../utils/asyncConfirm";
|
||||||
import CriticalPartsScan from "../../utils/criticalPartsScan";
|
import CriticalPartsScan from "../../utils/criticalPartsScan";
|
||||||
|
import dayjs from "../../utils/day";
|
||||||
|
import InstanceRenderManager from "../../utils/instanceRenderMgr";
|
||||||
import AlertComponent from "../alert/alert.component";
|
import AlertComponent from "../alert/alert.component";
|
||||||
import JobsAvailableScan from "../jobs-available-scan/jobs-available-scan.component";
|
import JobsAvailableScan from "../jobs-available-scan/jobs-available-scan.component";
|
||||||
import JobsFindModalContainer from "../jobs-find-modal/jobs-find-modal.container";
|
import JobsFindModalContainer from "../jobs-find-modal/jobs-find-modal.container";
|
||||||
@@ -32,7 +33,6 @@ import OwnerFindModalContainer from "../owner-find-modal/owner-find-modal.contai
|
|||||||
import { GetSupplementDelta } from "./jobs-available-supplement.estlines.util";
|
import { GetSupplementDelta } from "./jobs-available-supplement.estlines.util";
|
||||||
import HeaderFields from "./jobs-available-supplement.headerfields";
|
import HeaderFields from "./jobs-available-supplement.headerfields";
|
||||||
import JobsAvailableTableComponent from "./jobs-available-table.component";
|
import JobsAvailableTableComponent from "./jobs-available-table.component";
|
||||||
import InstanceRenderManager from "../../utils/instanceRenderMgr";
|
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
bodyshop: selectBodyshop,
|
bodyshop: selectBodyshop,
|
||||||
@@ -580,12 +580,13 @@ function ResolveCCCLineIssues(estData, bodyshop) {
|
|||||||
InstanceRenderManager({
|
InstanceRenderManager({
|
||||||
executeFunction: true,
|
executeFunction: true,
|
||||||
args: [],
|
args: [],
|
||||||
promanager: () => {
|
rome: () => {
|
||||||
if (line.mod_lbr_ty === "LAET" || line.mod_lbr_ty === "LAUT") {
|
if (line.mod_lbr_ty === "LAET" || line.mod_lbr_ty === "LAUT") {
|
||||||
// line.notes += ` | ET/UT Update (prev = ${line.mod_lbr_ty})`;
|
// line.notes += ` | ET/UT Update (prev = ${line.mod_lbr_ty})`;
|
||||||
line.mod_lbr_ty = "LAR";
|
line.mod_lbr_ty = "LAR";
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
promanager: "USE_ROME"
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import { createStructuredSelector } from "reselect";
|
|||||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||||
import CurrencyFormatter from "../../utils/CurrencyFormatter";
|
import CurrencyFormatter from "../../utils/CurrencyFormatter";
|
||||||
import { pageLimit } from "../../utils/config";
|
import { pageLimit } from "../../utils/config";
|
||||||
|
import { alphaSort, statusSort } from "../../utils/sorters";
|
||||||
import useLocalStorage from "../../utils/useLocalStorage";
|
import useLocalStorage from "../../utils/useLocalStorage";
|
||||||
import StartChatButton from "../chat-open-button/chat-open-button.component";
|
import StartChatButton from "../chat-open-button/chat-open-button.component";
|
||||||
import OwnerNameDisplay from "../owner-name-display/owner-name-display.component";
|
import OwnerNameDisplay from "../owner-name-display/owner-name-display.component";
|
||||||
@@ -37,7 +38,10 @@ export function JobsList({ bodyshop, refetch, loading, jobs, total }) {
|
|||||||
title: t("jobs.fields.ro_number"),
|
title: t("jobs.fields.ro_number"),
|
||||||
dataIndex: "ro_number",
|
dataIndex: "ro_number",
|
||||||
key: "ro_number",
|
key: "ro_number",
|
||||||
sorter: true, //(a, b) => alphaSort(a.ro_number, b.ro_number),
|
sorter: search?.search
|
||||||
|
? (a, b) =>
|
||||||
|
parseInt((a.ro_number || "0").replace(/\D/g, "")) - parseInt((b.ro_number || "0").replace(/\D/g, ""))
|
||||||
|
: true,
|
||||||
sortOrder: sortcolumn === "ro_number" && sortorder,
|
sortOrder: sortcolumn === "ro_number" && sortorder,
|
||||||
render: (text, record) => (
|
render: (text, record) => (
|
||||||
<Link to={"/manage/jobs/" + record.id}>{record.ro_number || t("general.labels.na")}</Link>
|
<Link to={"/manage/jobs/" + record.id}>{record.ro_number || t("general.labels.na")}</Link>
|
||||||
@@ -49,7 +53,6 @@ export function JobsList({ bodyshop, refetch, loading, jobs, total }) {
|
|||||||
key: "ownr_ln",
|
key: "ownr_ln",
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
//sorter: true, // (a, b) => alphaSort(a.ownr_ln, b.ownr_ln),
|
//sorter: true, // (a, b) => alphaSort(a.ownr_ln, b.ownr_ln),
|
||||||
|
|
||||||
//sortOrder: sortcolumn === "ownr_ln" && sortorder,
|
//sortOrder: sortcolumn === "ownr_ln" && sortorder,
|
||||||
render: (text, record) => {
|
render: (text, record) => {
|
||||||
return record.ownerid ? (
|
return record.ownerid ? (
|
||||||
@@ -67,7 +70,6 @@ export function JobsList({ bodyshop, refetch, loading, jobs, total }) {
|
|||||||
title: t("jobs.fields.ownr_ph1"),
|
title: t("jobs.fields.ownr_ph1"),
|
||||||
dataIndex: "ownr_ph1",
|
dataIndex: "ownr_ph1",
|
||||||
key: "ownr_ph1",
|
key: "ownr_ph1",
|
||||||
|
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
render: (text, record) => <StartChatButton phone={record.ownr_ph1} jobid={record.id} />
|
render: (text, record) => <StartChatButton phone={record.ownr_ph1} jobid={record.id} />
|
||||||
},
|
},
|
||||||
@@ -75,7 +77,6 @@ export function JobsList({ bodyshop, refetch, loading, jobs, total }) {
|
|||||||
title: t("jobs.fields.ownr_ph2"),
|
title: t("jobs.fields.ownr_ph2"),
|
||||||
dataIndex: "ownr_ph2",
|
dataIndex: "ownr_ph2",
|
||||||
key: "ownr_ph2",
|
key: "ownr_ph2",
|
||||||
|
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
render: (text, record) => <StartChatButton phone={record.ownr_ph2} jobid={record.id} />
|
render: (text, record) => <StartChatButton phone={record.ownr_ph2} jobid={record.id} />
|
||||||
},
|
},
|
||||||
@@ -85,7 +86,7 @@ export function JobsList({ bodyshop, refetch, loading, jobs, total }) {
|
|||||||
key: "status",
|
key: "status",
|
||||||
|
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
sorter: true, // (a, b) => alphaSort(a.status, b.status),
|
sorter: search?.search ? (a, b) => statusSort(a.status, b.status, bodyshop.md_ro_statuses.active_statuses) : true,
|
||||||
sortOrder: sortcolumn === "status" && sortorder,
|
sortOrder: sortcolumn === "status" && sortorder,
|
||||||
render: (text, record) => {
|
render: (text, record) => {
|
||||||
return record.status || t("general.labels.na");
|
return record.status || t("general.labels.na");
|
||||||
@@ -100,7 +101,6 @@ export function JobsList({ bodyshop, refetch, loading, jobs, total }) {
|
|||||||
title: t("jobs.fields.vehicle"),
|
title: t("jobs.fields.vehicle"),
|
||||||
dataIndex: "vehicle",
|
dataIndex: "vehicle",
|
||||||
key: "vehicle",
|
key: "vehicle",
|
||||||
|
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
render: (text, record) => {
|
render: (text, record) => {
|
||||||
return record.vehicleid ? (
|
return record.vehicleid ? (
|
||||||
@@ -117,7 +117,7 @@ export function JobsList({ bodyshop, refetch, loading, jobs, total }) {
|
|||||||
dataIndex: "plate_no",
|
dataIndex: "plate_no",
|
||||||
key: "plate_no",
|
key: "plate_no",
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
sorter: true, //(a, b) => alphaSort(a.plate_no, b.plate_no),
|
sorter: search?.search ? (a, b) => alphaSort(a.plate_no, b.plate_no) : true,
|
||||||
sortOrder: sortcolumn === "plate_no" && sortorder,
|
sortOrder: sortcolumn === "plate_no" && sortorder,
|
||||||
render: (text, record) => {
|
render: (text, record) => {
|
||||||
return record.plate_no ? record.plate_no : "";
|
return record.plate_no ? record.plate_no : "";
|
||||||
@@ -128,7 +128,7 @@ export function JobsList({ bodyshop, refetch, loading, jobs, total }) {
|
|||||||
dataIndex: "clm_no",
|
dataIndex: "clm_no",
|
||||||
key: "clm_no",
|
key: "clm_no",
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
sorter: true, //(a, b) => alphaSort(a.clm_no, b.clm_no),
|
sorter: search?.search ? (a, b) => alphaSort(a.clm_no, b.clm_no) : true,
|
||||||
sortOrder: sortcolumn === "clm_no" && sortorder,
|
sortOrder: sortcolumn === "clm_no" && sortorder,
|
||||||
render: (text, record) => `${record.clm_no || ""}${record.po_number ? ` (PO: ${record.po_number})` : ""}`
|
render: (text, record) => `${record.clm_no || ""}${record.po_number ? ` (PO: ${record.po_number})` : ""}`
|
||||||
},
|
},
|
||||||
@@ -142,8 +142,7 @@ export function JobsList({ bodyshop, refetch, loading, jobs, total }) {
|
|||||||
title: t("jobs.fields.clm_total"),
|
title: t("jobs.fields.clm_total"),
|
||||||
dataIndex: "clm_total",
|
dataIndex: "clm_total",
|
||||||
key: "clm_total",
|
key: "clm_total",
|
||||||
|
sorter: search?.search ? (a, b) => a.clm_total - b.clm_total : true,
|
||||||
sorter: true, //(a, b) => a.clm_total - b.clm_total,
|
|
||||||
sortOrder: sortcolumn === "clm_total" && sortorder,
|
sortOrder: sortcolumn === "clm_total" && sortorder,
|
||||||
render: (text, record) => {
|
render: (text, record) => {
|
||||||
return record.clm_total ? (
|
return record.clm_total ? (
|
||||||
@@ -157,7 +156,6 @@ export function JobsList({ bodyshop, refetch, loading, jobs, total }) {
|
|||||||
title: t("jobs.fields.owner_owing"),
|
title: t("jobs.fields.owner_owing"),
|
||||||
dataIndex: "owner_owing",
|
dataIndex: "owner_owing",
|
||||||
key: "owner_owing",
|
key: "owner_owing",
|
||||||
|
|
||||||
render: (text, record) => <CurrencyFormatter>{record.owner_owing}</CurrencyFormatter>
|
render: (text, record) => <CurrencyFormatter>{record.owner_owing}</CurrencyFormatter>
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -16,18 +16,15 @@ import useLocalStorage from "../../utils/useLocalStorage";
|
|||||||
import AlertComponent from "../alert/alert.component";
|
import AlertComponent from "../alert/alert.component";
|
||||||
import ChatOpenButton from "../chat-open-button/chat-open-button.component";
|
import ChatOpenButton from "../chat-open-button/chat-open-button.component";
|
||||||
import OwnerNameDisplay from "../owner-name-display/owner-name-display.component";
|
import OwnerNameDisplay from "../owner-name-display/owner-name-display.component";
|
||||||
import { setJoyRideSteps } from "../../redux/application/application.actions";
|
|
||||||
import { OwnerNameDisplayFunction } from "./../owner-name-display/owner-name-display.component";
|
import { OwnerNameDisplayFunction } from "./../owner-name-display/owner-name-display.component";
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
bodyshop: selectBodyshop
|
bodyshop: selectBodyshop
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
const mapDispatchToProps = (dispatch) => ({});
|
||||||
setJoyRideSteps: (steps) => dispatch(setJoyRideSteps(steps))
|
|
||||||
});
|
|
||||||
|
|
||||||
export function JobsList({ bodyshop, setJoyRideSteps }) {
|
export function JobsList({ bodyshop }) {
|
||||||
const searchParams = queryString.parse(useLocation().search);
|
const searchParams = queryString.parse(useLocation().search);
|
||||||
const { selected } = searchParams;
|
const { selected } = searchParams;
|
||||||
const selectedBreakpoint = Object.entries(Grid.useBreakpoint())
|
const selectedBreakpoint = Object.entries(Grid.useBreakpoint())
|
||||||
|
|||||||
@@ -0,0 +1,105 @@
|
|||||||
|
import { useMutation } from "@apollo/client";
|
||||||
|
import { Button, notification, Popconfirm } from "antd";
|
||||||
|
import React, { useState } from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { connect } from "react-redux";
|
||||||
|
import { createStructuredSelector } from "reselect";
|
||||||
|
import { INSERT_EXPORT_LOG } from "../../graphql/accounting.queries";
|
||||||
|
import { UPDATE_JOBS } from "../../graphql/jobs.queries";
|
||||||
|
import { insertAuditTrail } from "../../redux/application/application.actions";
|
||||||
|
import { selectBodyshop, selectCurrentUser } from "../../redux/user/user.selectors";
|
||||||
|
import AuditTrailMapping from "../../utils/AuditTrailMappings";
|
||||||
|
|
||||||
|
const mapStateToProps = createStructuredSelector({
|
||||||
|
bodyshop: selectBodyshop,
|
||||||
|
currentUser: selectCurrentUser
|
||||||
|
});
|
||||||
|
|
||||||
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
|
insertAuditTrail: ({ jobid, operation, type }) => dispatch(insertAuditTrail({ jobid, operation, type }))
|
||||||
|
});
|
||||||
|
|
||||||
|
export default connect(mapStateToProps, mapDispatchToProps)(JobMarkSelectedExported);
|
||||||
|
|
||||||
|
export function JobMarkSelectedExported({
|
||||||
|
bodyshop,
|
||||||
|
currentUser,
|
||||||
|
jobIds,
|
||||||
|
disabled,
|
||||||
|
loadingCallback,
|
||||||
|
completedCallback,
|
||||||
|
refetch,
|
||||||
|
insertAuditTrail
|
||||||
|
}) {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
const [open, setOpen] = useState(false);
|
||||||
|
const [insertExportLog] = useMutation(INSERT_EXPORT_LOG);
|
||||||
|
|
||||||
|
const [updateJob] = useMutation(UPDATE_JOBS);
|
||||||
|
const handleUpdate = async () => {
|
||||||
|
setLoading(true);
|
||||||
|
loadingCallback(true);
|
||||||
|
const result = await updateJob({
|
||||||
|
variables: {
|
||||||
|
jobIds: jobIds,
|
||||||
|
fields: {
|
||||||
|
status: bodyshop.md_ro_statuses.default_exported || "Exported*",
|
||||||
|
date_exported: new Date()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
update(cache) {}
|
||||||
|
});
|
||||||
|
|
||||||
|
await insertExportLog({
|
||||||
|
variables: {
|
||||||
|
logs: jobIds.map((id) => {
|
||||||
|
return {
|
||||||
|
bodyshopid: bodyshop.id,
|
||||||
|
jobid: id,
|
||||||
|
successful: true,
|
||||||
|
message: JSON.stringify([t("general.labels.markedexported")]),
|
||||||
|
useremail: currentUser.email
|
||||||
|
};
|
||||||
|
})
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!result.errors) {
|
||||||
|
notification["success"]({ message: t("jobs.successes.save") });
|
||||||
|
result.data.update_jobs.returning.forEach((job) => {
|
||||||
|
console.log("results job", job.id, "audit: ", AuditTrailMapping.admin_jobmarkexported());
|
||||||
|
insertAuditTrail({
|
||||||
|
jobid: job.id,
|
||||||
|
operation: AuditTrailMapping.admin_jobmarkexported(),
|
||||||
|
type: "admin_jobmarkexported"
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
notification["error"]({
|
||||||
|
message: t("jobs.errors.saving", {
|
||||||
|
error: JSON.stringify(result.errors)
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
loadingCallback(false);
|
||||||
|
completedCallback && completedCallback([]);
|
||||||
|
setLoading(false);
|
||||||
|
refetch && refetch();
|
||||||
|
setOpen(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Popconfirm
|
||||||
|
open={open}
|
||||||
|
title={t("general.labels.areyousure")}
|
||||||
|
onCancel={() => setOpen(false)}
|
||||||
|
onConfirm={handleUpdate}
|
||||||
|
disabled={disabled}
|
||||||
|
>
|
||||||
|
<Button loading={loading} disabled={disabled} onClick={() => setOpen(true)} type="primary" danger>
|
||||||
|
{t("jobs.actions.markasexported")}
|
||||||
|
</Button>
|
||||||
|
</Popconfirm>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -90,7 +90,7 @@ export function BillMarkSelectedExported({
|
|||||||
onConfirm={handleUpdate}
|
onConfirm={handleUpdate}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
>
|
>
|
||||||
<Button loading={loading} disabled={disabled} onClick={() => setOpen(true)}>
|
<Button loading={loading} disabled={disabled} onClick={() => setOpen(true)} type="primary" danger>
|
||||||
{t("bills.labels.markexported")}
|
{t("bills.labels.markexported")}
|
||||||
</Button>
|
</Button>
|
||||||
</Popconfirm>
|
</Popconfirm>
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ export function PaymentMarkSelectedExported({
|
|||||||
onConfirm={handleUpdate}
|
onConfirm={handleUpdate}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
>
|
>
|
||||||
<Button loading={loading} disabled={disabled} onClick={() => setOpen(true)}>
|
<Button loading={loading} disabled={disabled} onClick={() => setOpen(true)} type="primary" danger>
|
||||||
{t("bills.labels.markexported")}
|
{t("bills.labels.markexported")}
|
||||||
</Button>
|
</Button>
|
||||||
</Popconfirm>
|
</Popconfirm>
|
||||||
|
|||||||
@@ -1,22 +1,32 @@
|
|||||||
import { Input, Space, Spin } from "antd";
|
import { Button, Input, Space, Spin } from "antd";
|
||||||
import React from "react";
|
import React, { useState } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import { createStructuredSelector } from "reselect";
|
import { createStructuredSelector } from "reselect";
|
||||||
|
import { ExclamationCircleFilled, ExclamationCircleOutlined } from "@ant-design/icons";
|
||||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||||
import EmployeeSearchSelectComponent from "../employee-search-select/employee-search-select.component";
|
import EmployeeSearchSelectComponent from "../employee-search-select/employee-search-select.component";
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
//currentUser: selectCurrentUser
|
|
||||||
bodyshop: selectBodyshop
|
bodyshop: selectBodyshop
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
//setUserLanguage: language => dispatch(setUserLanguage(language))
|
//setUserLanguage: language => dispatch(setUserLanguage(language))
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(ProductionBoardFilters);
|
export default connect(mapStateToProps, mapDispatchToProps)(ProductionBoardFilters);
|
||||||
|
|
||||||
export function ProductionBoardFilters({ bodyshop, filter, setFilter, loading }) {
|
export function ProductionBoardFilters({ bodyshop, filter, setFilter, loading }) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const [alertFilter, setAlertFilter] = useState(false);
|
||||||
|
|
||||||
|
const toggleAlertFilter = () => {
|
||||||
|
const newAlertFilter = !alertFilter;
|
||||||
|
setAlertFilter(newAlertFilter);
|
||||||
|
setFilter({ ...filter, alert: newAlertFilter });
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Space wrap>
|
<Space wrap>
|
||||||
{loading && <Spin />}
|
{loading && <Spin />}
|
||||||
@@ -35,6 +45,13 @@ export function ProductionBoardFilters({ bodyshop, filter, setFilter, loading })
|
|||||||
onChange={(emp) => setFilter({ ...filter, employeeId: emp })}
|
onChange={(emp) => setFilter({ ...filter, employeeId: emp })}
|
||||||
allowClear
|
allowClear
|
||||||
/>
|
/>
|
||||||
|
<Button
|
||||||
|
type={alertFilter ? "primary" : "default"}
|
||||||
|
onClick={toggleAlertFilter}
|
||||||
|
icon={alertFilter ? <ExclamationCircleFilled /> : <ExclamationCircleOutlined />}
|
||||||
|
>
|
||||||
|
{t("production.labels.alerts")}
|
||||||
|
</Button>
|
||||||
</Space>
|
</Space>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -290,6 +290,22 @@ const PartsStatusComponent = ({ metadata, cardSettings }) =>
|
|||||||
</Col>
|
</Col>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const TasksToolTip = ({ metadata, cardSettings, t }) =>
|
||||||
|
cardSettings?.tasks && (
|
||||||
|
<Col span={12}>
|
||||||
|
<EllipsesToolTip
|
||||||
|
title={`${t("production.labels.tasks")}: ${metadata.tasks_aggregate?.aggregate?.count || 0}`}
|
||||||
|
kiosk={cardSettings.kiosk}
|
||||||
|
>
|
||||||
|
{metadata.tasks_aggregate?.aggregate?.count ? (
|
||||||
|
`T: ${metadata.tasks_aggregate.aggregate.count}`
|
||||||
|
) : (
|
||||||
|
<span>T: 0</span>
|
||||||
|
)}
|
||||||
|
</EllipsesToolTip>
|
||||||
|
</Col>
|
||||||
|
);
|
||||||
|
|
||||||
export default function ProductionBoardCard({ technician, card, bodyshop, cardSettings, clone }) {
|
export default function ProductionBoardCard({ technician, card, bodyshop, cardSettings, clone }) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { metadata } = card;
|
const { metadata } = card;
|
||||||
@@ -336,21 +352,15 @@ export default function ProductionBoardCard({ technician, card, bodyshop, cardSe
|
|||||||
cardSettings?.production_note ||
|
cardSettings?.production_note ||
|
||||||
cardSettings?.partsstatus ||
|
cardSettings?.partsstatus ||
|
||||||
cardSettings?.estimator ||
|
cardSettings?.estimator ||
|
||||||
cardSettings?.subtotal
|
cardSettings?.subtotal ||
|
||||||
|
cardSettings?.tasks
|
||||||
);
|
);
|
||||||
}, [cardSettings]);
|
}, [cardSettings]);
|
||||||
|
|
||||||
const headerContent = (
|
const headerContent = (
|
||||||
<div className="header-content-container">
|
<div className="header-content-container">
|
||||||
<div className="inner-container">
|
<div className="inner-container">
|
||||||
<ProductionAlert
|
<ProductionAlert id={card.id} productionVars={metadata?.production_vars} refetch={card?.refetch} key="alert" />
|
||||||
record={{
|
|
||||||
id: card.id,
|
|
||||||
production_vars: card?.metadata.production_vars,
|
|
||||||
refetch: card?.refetch
|
|
||||||
}}
|
|
||||||
key="alert"
|
|
||||||
/>
|
|
||||||
{metadata?.suspended && <PauseCircleOutlined className="circle-outline" key="suspended" />}
|
{metadata?.suspended && <PauseCircleOutlined className="circle-outline" key="suspended" />}
|
||||||
{metadata?.iouparent && (
|
{metadata?.iouparent && (
|
||||||
<EllipsesToolTip
|
<EllipsesToolTip
|
||||||
@@ -393,6 +403,7 @@ export default function ProductionBoardCard({ technician, card, bodyshop, cardSe
|
|||||||
employee_csr={employee_csr}
|
employee_csr={employee_csr}
|
||||||
/>
|
/>
|
||||||
<EstimatorToolTip metadata={metadata} cardSettings={cardSettings} />
|
<EstimatorToolTip metadata={metadata} cardSettings={cardSettings} />
|
||||||
|
<TasksToolTip metadata={metadata} cardSettings={cardSettings} t={t} />
|
||||||
<SubtotalTooltip metadata={metadata} cardSettings={cardSettings} t={t} />
|
<SubtotalTooltip metadata={metadata} cardSettings={cardSettings} t={t} />
|
||||||
<ActualInToolTip metadata={metadata} cardSettings={cardSettings} />
|
<ActualInToolTip metadata={metadata} cardSettings={cardSettings} />
|
||||||
<ScheduledCompletionToolTip metadata={metadata} cardSettings={cardSettings} pastDueAlert={pastDueAlert} />
|
<ScheduledCompletionToolTip metadata={metadata} cardSettings={cardSettings} pastDueAlert={pastDueAlert} />
|
||||||
@@ -15,13 +15,13 @@ import AuditTrailMapping from "../../utils/AuditTrailMappings";
|
|||||||
import IndefiniteLoading from "../indefinite-loading/indefinite-loading.component";
|
import IndefiniteLoading from "../indefinite-loading/indefinite-loading.component";
|
||||||
import ProductionBoardFilters from "../production-board-filters/production-board-filters.component";
|
import ProductionBoardFilters from "../production-board-filters/production-board-filters.component";
|
||||||
import ProductionListDetailComponent from "../production-list-detail/production-list-detail.component";
|
import ProductionListDetailComponent from "../production-list-detail/production-list-detail.component";
|
||||||
import CardColorLegend from "../production-board-kanban-card/production-board-kanban-card-color-legend.component";
|
import CardColorLegend from "./production-board-kanban-card-color-legend.component.jsx";
|
||||||
import "./production-board-kanban.styles.scss";
|
import "./production-board-kanban.styles.scss";
|
||||||
import { createBoardData } from "./production-board-kanban.utils.js";
|
import { createBoardData } from "./production-board-kanban.utils.js";
|
||||||
import ProductionBoardKanbanSettings from "./settings/production-board-kanban.settings.component.jsx";
|
import ProductionBoardKanbanSettings from "./settings/production-board-kanban.settings.component.jsx";
|
||||||
import cloneDeep from "lodash/cloneDeep";
|
import cloneDeep from "lodash/cloneDeep";
|
||||||
import isEqual from "lodash/isEqual";
|
import isEqual from "lodash/isEqual";
|
||||||
import { defaultKanbanSettings } from "./settings/defaultKanbanSettings.js";
|
import { defaultFilters, mergeWithDefaults } from "./settings/defaultKanbanSettings.js";
|
||||||
import NoteUpsertModal from "../../components/note-upsert-modal/note-upsert-modal.container";
|
import NoteUpsertModal from "../../components/note-upsert-modal/note-upsert-modal.container";
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
@@ -41,7 +41,7 @@ const mapDispatchToProps = (dispatch) => ({
|
|||||||
|
|
||||||
function ProductionBoardKanbanComponent({ data, bodyshop, refetch, insertAuditTrail, associationSettings, statuses }) {
|
function ProductionBoardKanbanComponent({ data, bodyshop, refetch, insertAuditTrail, associationSettings, statuses }) {
|
||||||
const [boardLanes, setBoardLanes] = useState({ lanes: [] });
|
const [boardLanes, setBoardLanes] = useState({ lanes: [] });
|
||||||
const [filter, setFilter] = useState({ search: "", employeeId: null });
|
const [filter, setFilter] = useState(defaultFilters);
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
const [isMoving, setIsMoving] = useState(false);
|
const [isMoving, setIsMoving] = useState(false);
|
||||||
const [orientation, setOrientation] = useState("vertical");
|
const [orientation, setOrientation] = useState("vertical");
|
||||||
@@ -182,19 +182,14 @@ function ProductionBoardKanbanComponent({ data, bodyshop, refetch, insertAuditTr
|
|||||||
[boardLanes, client, getCardByID, isMoving, t, insertAuditTrail]
|
[boardLanes, client, getCardByID, isMoving, t, insertAuditTrail]
|
||||||
);
|
);
|
||||||
|
|
||||||
const cardSettings = useMemo(
|
const cardSettings = useMemo(() => {
|
||||||
() =>
|
const kanbanSettings = associationSettings?.kanban_settings;
|
||||||
associationSettings?.kanban_settings && Object.keys(associationSettings.kanban_settings).length > 0
|
return mergeWithDefaults(kanbanSettings);
|
||||||
? associationSettings.kanban_settings
|
}, [associationSettings]);
|
||||||
: defaultKanbanSettings,
|
|
||||||
[associationSettings]
|
|
||||||
);
|
|
||||||
|
|
||||||
const handleSettingsChange = useCallback((newSettings) => {
|
const handleSettingsChange = () => {
|
||||||
setLoading(true);
|
setFilter(defaultFilters);
|
||||||
setOrientation(newSettings.orientation ? "vertical" : "horizontal");
|
};
|
||||||
setLoading(false);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
if (loading) {
|
if (loading) {
|
||||||
return <Skeleton active />;
|
return <Skeleton active />;
|
||||||
|
|||||||
@@ -2,11 +2,13 @@ import React, { useMemo } from "react";
|
|||||||
import { Card, Statistic } from "antd";
|
import { Card, Statistic } from "antd";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import PropTypes from "prop-types";
|
import PropTypes from "prop-types";
|
||||||
import { statisticsItems, defaultKanbanSettings } from "./settings/defaultKanbanSettings.js";
|
import { defaultKanbanSettings, statisticsItems } from "./settings/defaultKanbanSettings.js";
|
||||||
|
|
||||||
export const StatisticType = {
|
export const StatisticType = {
|
||||||
HOURS: "hours",
|
HOURS: "hours",
|
||||||
AMOUNT: "amount",
|
AMOUNT: "amount",
|
||||||
JOBS: "jobs"
|
JOBS: "jobs",
|
||||||
|
TASKS: "tasks"
|
||||||
};
|
};
|
||||||
|
|
||||||
const mergeStatistics = (items, values) => {
|
const mergeStatistics = (items, values) => {
|
||||||
@@ -122,6 +124,20 @@ const ProductionStatistics = ({ data, cardSettings, reducerData }) => {
|
|||||||
return parseFloat(total.toFixed(2));
|
return parseFloat(total.toFixed(2));
|
||||||
}, [reducerData, cardSettings.totalAmountOnBoard]);
|
}, [reducerData, cardSettings.totalAmountOnBoard]);
|
||||||
|
|
||||||
|
const tasksInProduction = useMemo(() => {
|
||||||
|
if (!data || !cardSettings.tasksInProduction) return null;
|
||||||
|
return data.reduce((acc, item) => acc + (item.tasks_aggregate?.aggregate?.count || 0), 0);
|
||||||
|
}, [data, cardSettings.tasksInProduction]);
|
||||||
|
|
||||||
|
const tasksOnBoard = useMemo(() => {
|
||||||
|
if (!reducerData || !cardSettings.tasksOnBoard) return null;
|
||||||
|
return reducerData.lanes.reduce((acc, lane) => {
|
||||||
|
return (
|
||||||
|
acc + lane.cards.reduce((laneAcc, card) => laneAcc + (card.metadata.tasks_aggregate?.aggregate?.count || 0), 0)
|
||||||
|
);
|
||||||
|
}, 0);
|
||||||
|
}, [reducerData, cardSettings.tasksOnBoard]);
|
||||||
|
|
||||||
const statistics = useMemo(
|
const statistics = useMemo(
|
||||||
() =>
|
() =>
|
||||||
mergeStatistics(statisticsItems, [
|
mergeStatistics(statisticsItems, [
|
||||||
@@ -134,7 +150,9 @@ const ProductionStatistics = ({ data, cardSettings, reducerData }) => {
|
|||||||
{ id: 6, value: totalAmountOnBoard, type: StatisticType.AMOUNT },
|
{ id: 6, value: totalAmountOnBoard, type: StatisticType.AMOUNT },
|
||||||
{ id: 7, value: totalLABOnBoard, type: StatisticType.HOURS },
|
{ id: 7, value: totalLABOnBoard, type: StatisticType.HOURS },
|
||||||
{ id: 8, value: totalLAROnBoard, type: StatisticType.HOURS },
|
{ id: 8, value: totalLAROnBoard, type: StatisticType.HOURS },
|
||||||
{ id: 9, value: jobsOnBoard, type: StatisticType.JOBS }
|
{ id: 9, value: jobsOnBoard, type: StatisticType.JOBS },
|
||||||
|
{ id: 10, value: tasksOnBoard, type: StatisticType.TASKS },
|
||||||
|
{ id: 11, value: tasksInProduction, type: StatisticType.TASKS }
|
||||||
]),
|
]),
|
||||||
[
|
[
|
||||||
totalHrs,
|
totalHrs,
|
||||||
@@ -146,7 +164,9 @@ const ProductionStatistics = ({ data, cardSettings, reducerData }) => {
|
|||||||
totalAmountOnBoard,
|
totalAmountOnBoard,
|
||||||
totalLABOnBoard,
|
totalLABOnBoard,
|
||||||
totalLAROnBoard,
|
totalLAROnBoard,
|
||||||
jobsOnBoard
|
jobsOnBoard,
|
||||||
|
tasksOnBoard,
|
||||||
|
tasksInProduction
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -187,37 +207,9 @@ const ProductionStatistics = ({ data, cardSettings, reducerData }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
ProductionStatistics.propTypes = {
|
ProductionStatistics.propTypes = {
|
||||||
data: PropTypes.arrayOf(
|
data: PropTypes.array.isRequired,
|
||||||
PropTypes.shape({
|
cardSettings: PropTypes.object.isRequired,
|
||||||
labhrs: PropTypes.object,
|
reducerData: PropTypes.object
|
||||||
larhrs: PropTypes.object,
|
|
||||||
job_totals: PropTypes.object
|
|
||||||
})
|
|
||||||
).isRequired,
|
|
||||||
cardSettings: PropTypes.shape({
|
|
||||||
totalHrs: PropTypes.bool,
|
|
||||||
totalLAB: PropTypes.bool,
|
|
||||||
totalLAR: PropTypes.bool,
|
|
||||||
jobsInProduction: PropTypes.bool,
|
|
||||||
totalAmountInProduction: PropTypes.bool,
|
|
||||||
totalHrsOnBoard: PropTypes.bool,
|
|
||||||
totalLABOnBoard: PropTypes.bool,
|
|
||||||
totalLAROnBoard: PropTypes.bool,
|
|
||||||
jobsOnBoard: PropTypes.bool,
|
|
||||||
totalAmountOnBoard: PropTypes.bool,
|
|
||||||
statisticsOrder: PropTypes.arrayOf(PropTypes.number)
|
|
||||||
}).isRequired,
|
|
||||||
reducerData: PropTypes.shape({
|
|
||||||
lanes: PropTypes.arrayOf(
|
|
||||||
PropTypes.shape({
|
|
||||||
cards: PropTypes.arrayOf(
|
|
||||||
PropTypes.shape({
|
|
||||||
metadata: PropTypes.object
|
|
||||||
})
|
|
||||||
).isRequired
|
|
||||||
})
|
|
||||||
).isRequired
|
|
||||||
})
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ProductionStatistics;
|
export default ProductionStatistics;
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ const sortByParentId = (arr) => {
|
|||||||
|
|
||||||
// Function to create board data based on statuses and jobs, with optional filtering
|
// Function to create board data based on statuses and jobs, with optional filtering
|
||||||
export const createBoardData = ({ statuses, data, filter, cardSettings }) => {
|
export const createBoardData = ({ statuses, data, filter, cardSettings }) => {
|
||||||
const { search, employeeId } = filter;
|
const { search, employeeId, alert } = filter;
|
||||||
|
|
||||||
const lanes = statuses.map((status) => ({
|
const lanes = statuses.map((status) => ({
|
||||||
id: status,
|
id: status,
|
||||||
@@ -52,6 +52,11 @@ export const createBoardData = ({ statuses, data, filter, cardSettings }) => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Filter jobs by alert if alert filter is true
|
||||||
|
if (alert) {
|
||||||
|
filteredJobs = filteredJobs.filter((job) => job.production_vars?.alert);
|
||||||
|
}
|
||||||
|
|
||||||
const DataGroupedByStatus = groupBy(filteredJobs, "status");
|
const DataGroupedByStatus = groupBy(filteredJobs, "status");
|
||||||
|
|
||||||
Object.keys(DataGroupedByStatus).forEach((statusGroupKey) => {
|
Object.keys(DataGroupedByStatus).forEach((statusGroupKey) => {
|
||||||
|
|||||||
@@ -18,7 +18,8 @@ const InformationSettings = ({ t }) => (
|
|||||||
"sublets",
|
"sublets",
|
||||||
"partsstatus",
|
"partsstatus",
|
||||||
"estimator",
|
"estimator",
|
||||||
"subtotal"
|
"subtotal",
|
||||||
|
"tasks"
|
||||||
].map((item) => (
|
].map((item) => (
|
||||||
<Col span={4} key={item}>
|
<Col span={4} key={item}>
|
||||||
<Form.Item name={item} valuePropName="checked">
|
<Form.Item name={item} valuePropName="checked">
|
||||||
|
|||||||
@@ -8,7 +8,9 @@ const statisticsItems = [
|
|||||||
{ id: 6, name: "totalAmountOnBoard", label: "total_amount_on_board" },
|
{ id: 6, name: "totalAmountOnBoard", label: "total_amount_on_board" },
|
||||||
{ id: 7, name: "totalLABOnBoard", label: "total_lab_on_board" },
|
{ id: 7, name: "totalLABOnBoard", label: "total_lab_on_board" },
|
||||||
{ id: 8, name: "totalLAROnBoard", label: "total_lar_on_board" },
|
{ id: 8, name: "totalLAROnBoard", label: "total_lar_on_board" },
|
||||||
{ id: 9, name: "jobsOnBoard", label: "total_jobs_on_board" }
|
{ id: 9, name: "jobsOnBoard", label: "total_jobs_on_board" },
|
||||||
|
{ id: 10, name: "tasksOnBoard", label: "tasks_on_board" },
|
||||||
|
{ id: 11, name: "tasksInProduction", label: "tasks_in_production" }
|
||||||
];
|
];
|
||||||
|
|
||||||
const defaultKanbanSettings = {
|
const defaultKanbanSettings = {
|
||||||
@@ -23,6 +25,7 @@ const defaultKanbanSettings = {
|
|||||||
scheduled_completion: true,
|
scheduled_completion: true,
|
||||||
cardcolor: false,
|
cardcolor: false,
|
||||||
orientation: false,
|
orientation: false,
|
||||||
|
tasks: false,
|
||||||
cardSize: "small",
|
cardSize: "small",
|
||||||
model_info: true,
|
model_info: true,
|
||||||
kiosk: false,
|
kiosk: false,
|
||||||
@@ -35,6 +38,8 @@ const defaultKanbanSettings = {
|
|||||||
totalLABOnBoard: false,
|
totalLABOnBoard: false,
|
||||||
totalLAROnBoard: false,
|
totalLAROnBoard: false,
|
||||||
jobsOnBoard: false,
|
jobsOnBoard: false,
|
||||||
|
tasksOnBoard: false,
|
||||||
|
tasksInProduction: false,
|
||||||
totalAmountOnBoard: true,
|
totalAmountOnBoard: true,
|
||||||
estimator: false,
|
estimator: false,
|
||||||
subtotal: false,
|
subtotal: false,
|
||||||
@@ -43,4 +48,22 @@ const defaultKanbanSettings = {
|
|||||||
selectedEstimators: []
|
selectedEstimators: []
|
||||||
};
|
};
|
||||||
|
|
||||||
export { defaultKanbanSettings, statisticsItems };
|
const defaultFilters = { search: "", employeeId: null, alert: false };
|
||||||
|
|
||||||
|
const mergeWithDefaults = (settings) => {
|
||||||
|
// Create a new object that starts with the default settings
|
||||||
|
const mergedSettings = { ...defaultKanbanSettings };
|
||||||
|
|
||||||
|
// Override with the provided settings, if any
|
||||||
|
if (settings) {
|
||||||
|
for (const key in settings) {
|
||||||
|
if (settings.hasOwnProperty(key)) {
|
||||||
|
mergedSettings[key] = settings[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return mergedSettings;
|
||||||
|
};
|
||||||
|
|
||||||
|
export { defaultKanbanSettings, statisticsItems, mergeWithDefaults, defaultFilters };
|
||||||
|
|||||||
@@ -3,13 +3,15 @@ import { Button, Card, Col, Form, notification, Popover, Row, Tabs } from "antd"
|
|||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { UPDATE_KANBAN_SETTINGS } from "../../../graphql/user.queries.js";
|
import { UPDATE_KANBAN_SETTINGS } from "../../../graphql/user.queries.js";
|
||||||
import { defaultKanbanSettings } from "./defaultKanbanSettings.js";
|
import { defaultKanbanSettings, mergeWithDefaults } from "./defaultKanbanSettings.js";
|
||||||
import LayoutSettings from "./LayoutSettings.jsx";
|
import LayoutSettings from "./LayoutSettings.jsx";
|
||||||
import InformationSettings from "./InformationSettings.jsx";
|
import InformationSettings from "./InformationSettings.jsx";
|
||||||
import StatisticsSettings from "./StatisticsSettings.jsx";
|
import StatisticsSettings from "./StatisticsSettings.jsx";
|
||||||
import FilterSettings from "./FilterSettings.jsx";
|
import FilterSettings from "./FilterSettings.jsx";
|
||||||
|
import PropTypes from "prop-types";
|
||||||
|
import { isFunction } from "lodash";
|
||||||
|
|
||||||
export default function ProductionBoardKanbanSettings({ associationSettings, parentLoading, bodyshop, data }) {
|
function ProductionBoardKanbanSettings({ associationSettings, parentLoading, bodyshop, data, onSettingsChange }) {
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
@@ -23,16 +25,11 @@ export default function ProductionBoardKanbanSettings({ associationSettings, par
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (associationSettings?.kanban_settings) {
|
if (associationSettings?.kanban_settings) {
|
||||||
form.setFieldsValue(associationSettings.kanban_settings);
|
const finalSettings = mergeWithDefaults(associationSettings.kanban_settings);
|
||||||
if (associationSettings.kanban_settings.statisticsOrder) {
|
form.setFieldsValue(finalSettings);
|
||||||
setStatisticsOrder(associationSettings.kanban_settings.statisticsOrder);
|
setStatisticsOrder(finalSettings.statisticsOrder);
|
||||||
}
|
setSelectedMdInsCos(finalSettings.selectedMdInsCos);
|
||||||
if (associationSettings.kanban_settings.selectedMdInsCos) {
|
setSelectedEstimators(finalSettings.selectedEstimators);
|
||||||
setSelectedMdInsCos(associationSettings.kanban_settings.selectedMdInsCos);
|
|
||||||
}
|
|
||||||
if (associationSettings.kanban_settings.selectedEstimators) {
|
|
||||||
setSelectedEstimators(associationSettings.kanban_settings.selectedEstimators);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}, [form, associationSettings]);
|
}, [form, associationSettings]);
|
||||||
|
|
||||||
@@ -65,6 +62,11 @@ export default function ProductionBoardKanbanSettings({ associationSettings, par
|
|||||||
setOpen(false);
|
setOpen(false);
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
parentLoading(false);
|
parentLoading(false);
|
||||||
|
|
||||||
|
if (onSettingsChange && isFunction(onSettingsChange)) {
|
||||||
|
onSettingsChange(values);
|
||||||
|
}
|
||||||
|
|
||||||
setHasChanges(false);
|
setHasChanges(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -155,3 +157,13 @@ export default function ProductionBoardKanbanSettings({ associationSettings, par
|
|||||||
</Popover>
|
</Popover>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ProductionBoardKanbanSettings.propTypes = {
|
||||||
|
associationSettings: PropTypes.object,
|
||||||
|
parentLoading: PropTypes.func.isRequired,
|
||||||
|
bodyshop: PropTypes.object.isRequired,
|
||||||
|
onSettingsChange: PropTypes.func,
|
||||||
|
data: PropTypes.array
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ProductionBoardKanbanSettings;
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import { EyeInvisibleOutlined, EyeOutlined } from "@ant-design/icons";
|
|||||||
import { createStructuredSelector } from "reselect";
|
import { createStructuredSelector } from "reselect";
|
||||||
import { selectBodyshop } from "../../../../redux/user/user.selectors.js";
|
import { selectBodyshop } from "../../../../redux/user/user.selectors.js";
|
||||||
import { selectTechnician } from "../../../../redux/tech/tech.selectors.js";
|
import { selectTechnician } from "../../../../redux/tech/tech.selectors.js";
|
||||||
import ProductionBoardCard from "../../../production-board-kanban-card/production-board-kanban-card.component.jsx";
|
import ProductionBoardCard from "../../production-board-kanban-card.component.jsx";
|
||||||
import HeightMemoryWrapper from "../components/HeightMemoryWrapper.jsx";
|
import HeightMemoryWrapper from "../components/HeightMemoryWrapper.jsx";
|
||||||
import SizeMemoryWrapper from "../components/SizeMemoryWrapper.jsx";
|
import SizeMemoryWrapper from "../components/SizeMemoryWrapper.jsx";
|
||||||
import ListComponent from "../components/ListComponent.jsx";
|
import ListComponent from "../components/ListComponent.jsx";
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import React from "react";
|
|||||||
import { Button, Dropdown } from "antd";
|
import { Button, Dropdown } from "antd";
|
||||||
import dataSource from "./production-list-columns.data";
|
import dataSource from "./production-list-columns.data";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import { createStructuredSelector } from "reselect";
|
import { createStructuredSelector } from "reselect";
|
||||||
import { selectTechnician } from "../../redux/tech/tech.selectors";
|
import { selectTechnician } from "../../redux/tech/tech.selectors";
|
||||||
@@ -10,16 +9,23 @@ import { selectBodyshop } from "../../redux/user/user.selectors";
|
|||||||
import { useSplitTreatments } from "@splitsoftware/splitio-react";
|
import { useSplitTreatments } from "@splitsoftware/splitio-react";
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
//currentUser: selectCurrentUser
|
|
||||||
technician: selectTechnician,
|
technician: selectTechnician,
|
||||||
bodyshop: selectBodyshop
|
bodyshop: selectBodyshop
|
||||||
});
|
});
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
|
||||||
//setUserLanguage: language => dispatch(setUserLanguage(language))
|
|
||||||
});
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(ProductionColumnsComponent);
|
|
||||||
|
|
||||||
export function ProductionColumnsComponent({ columnState, technician, bodyshop, data, tableState, refetch }) {
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
|
// Add any necessary dispatch actions here
|
||||||
|
});
|
||||||
|
|
||||||
|
export function ProductionColumnsComponent({
|
||||||
|
columnState,
|
||||||
|
technician,
|
||||||
|
bodyshop,
|
||||||
|
data,
|
||||||
|
tableState,
|
||||||
|
refetch,
|
||||||
|
onColumnAdd
|
||||||
|
}) {
|
||||||
const [columns, setColumns] = columnState;
|
const [columns, setColumns] = columnState;
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const {
|
const {
|
||||||
@@ -29,18 +35,26 @@ export function ProductionColumnsComponent({ columnState, technician, bodyshop,
|
|||||||
names: ["Enhanced_Payroll"],
|
names: ["Enhanced_Payroll"],
|
||||||
splitKey: bodyshop.imexshopid
|
splitKey: bodyshop.imexshopid
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleAdd = (e) => {
|
const handleAdd = (e) => {
|
||||||
setColumns([
|
const newColumn = dataSource({
|
||||||
...columns,
|
bodyshop,
|
||||||
...dataSource({
|
technician,
|
||||||
bodyshop,
|
state: tableState,
|
||||||
technician,
|
data,
|
||||||
state: tableState,
|
activeStatuses: bodyshop.md_ro_statuses.active_statuses,
|
||||||
data,
|
treatments: { Enhanced_Payroll }
|
||||||
activeStatuses: bodyshop.md_ro_statuses.active_statuses,
|
}).find((i) => i.key === e.key);
|
||||||
treatments: { Enhanced_Payroll }
|
|
||||||
}).filter((i) => i.key === e.key)
|
if (newColumn) {
|
||||||
]);
|
const updatedColumns = [...columns, newColumn];
|
||||||
|
setColumns(updatedColumns);
|
||||||
|
|
||||||
|
// Call the onColumnAdd function passed as a prop
|
||||||
|
if (onColumnAdd) {
|
||||||
|
onColumnAdd(newColumn);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const columnKeys = columns.map((i) => i.key);
|
const columnKeys = columns.map((i) => i.key);
|
||||||
@@ -76,12 +90,4 @@ export function ProductionColumnsComponent({ columnState, technician, bodyshop,
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// <Transfer
|
export default connect(mapStateToProps, mapDispatchToProps)(ProductionColumnsComponent);
|
||||||
// dataSource={dataSource}
|
|
||||||
// titles={["Source", "Target"]}
|
|
||||||
// targetKeys={columns.map((c) => c.key)}
|
|
||||||
// render={(item) => item.title}
|
|
||||||
// onChange={(nextTargetKeys, direction, moveKeys) => {
|
|
||||||
// setColumns(dataSource.filter((i) => nextTargetKeys.includes(i.key)));
|
|
||||||
// }}
|
|
||||||
// />
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { ExclamationCircleFilled } from "@ant-design/icons";
|
import { ExclamationCircleFilled, PlusCircleFilled } from "@ant-design/icons";
|
||||||
import { useMutation } from "@apollo/client";
|
import { useMutation } from "@apollo/client";
|
||||||
import { Button } from "antd";
|
import { Button, Popconfirm } from "antd";
|
||||||
import React, { useCallback } from "react";
|
import React, { useCallback } from "react";
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import { createStructuredSelector } from "reselect";
|
import { createStructuredSelector } from "reselect";
|
||||||
@@ -8,6 +8,7 @@ import { logImEXEvent } from "../../firebase/firebase.utils";
|
|||||||
import { UPDATE_JOB } from "../../graphql/jobs.queries";
|
import { UPDATE_JOB } from "../../graphql/jobs.queries";
|
||||||
import { insertAuditTrail } from "../../redux/application/application.actions";
|
import { insertAuditTrail } from "../../redux/application/application.actions";
|
||||||
import AuditTrailMapping from "../../utils/AuditTrailMappings";
|
import AuditTrailMapping from "../../utils/AuditTrailMappings";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({});
|
const mapStateToProps = createStructuredSelector({});
|
||||||
|
|
||||||
@@ -22,22 +23,24 @@ const mapDispatchToProps = (dispatch) => ({
|
|||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
const ProductionListColumnAlert = ({ record, insertAuditTrail }) => {
|
const ProductionListColumnAlert = ({ id, productionVars, refetch, insertAuditTrail }) => {
|
||||||
const [updateAlert] = useMutation(UPDATE_JOB);
|
const [updateAlert] = useMutation(UPDATE_JOB);
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const handleAlertToggle = useCallback(() => {
|
const handleAlertToggle = useCallback(() => {
|
||||||
logImEXEvent("production_toggle_alert");
|
logImEXEvent("production_toggle_alert");
|
||||||
|
|
||||||
const newAlertState = !!record.production_vars?.alert ? !record.production_vars.alert : true;
|
const newAlertState = !!productionVars?.alert ? !productionVars?.alert : true;
|
||||||
|
const finalProductionVars = {
|
||||||
|
...productionVars,
|
||||||
|
alert: newAlertState
|
||||||
|
};
|
||||||
|
|
||||||
updateAlert({
|
updateAlert({
|
||||||
variables: {
|
variables: {
|
||||||
jobId: record.id,
|
jobId: id,
|
||||||
job: {
|
job: {
|
||||||
production_vars: {
|
production_vars: finalProductionVars
|
||||||
...record.production_vars,
|
|
||||||
alert: newAlertState
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
@@ -45,17 +48,26 @@ const ProductionListColumnAlert = ({ record, insertAuditTrail }) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
insertAuditTrail({
|
insertAuditTrail({
|
||||||
jobid: record.id,
|
jobid: id,
|
||||||
operation: AuditTrailMapping.alertToggle(newAlertState),
|
operation: AuditTrailMapping.alertToggle(newAlertState),
|
||||||
type: "alertToggle"
|
type: "alertToggle"
|
||||||
});
|
});
|
||||||
|
|
||||||
if (record.refetch) record.refetch();
|
if (refetch) refetch();
|
||||||
}, [updateAlert, insertAuditTrail, record]);
|
}, [updateAlert, insertAuditTrail, id, productionVars, refetch]);
|
||||||
|
|
||||||
if (!record.production_vars?.alert) return null;
|
return productionVars?.alert ? (
|
||||||
|
<Popconfirm
|
||||||
return <Button className="production-alert" icon={<ExclamationCircleFilled />} onClick={handleAlertToggle} />;
|
title={t("general.actions.remove_alert")}
|
||||||
|
onConfirm={handleAlertToggle}
|
||||||
|
okText={t("general.labels.yes")}
|
||||||
|
cancelText={t("general.labels.no")}
|
||||||
|
>
|
||||||
|
<Button className="production-alert" icon={<ExclamationCircleFilled />} />
|
||||||
|
</Popconfirm>
|
||||||
|
) : (
|
||||||
|
<Button className="muted-button" icon={<PlusCircleFilled />} onClick={handleAlertToggle} />
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(ProductionListColumnAlert);
|
export default connect(mapStateToProps, mapDispatchToProps)(ProductionListColumnAlert);
|
||||||
|
|||||||
@@ -2,10 +2,13 @@ import { BranchesOutlined, PauseCircleOutlined } from "@ant-design/icons";
|
|||||||
import { Checkbox, Space, Tooltip } from "antd";
|
import { Checkbox, Space, Tooltip } from "antd";
|
||||||
import i18n from "i18next";
|
import i18n from "i18next";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
|
import { setModalContext } from "../../redux/modals/modals.actions";
|
||||||
|
import { store } from "../../redux/store";
|
||||||
import CurrencyFormatter from "../../utils/CurrencyFormatter";
|
import CurrencyFormatter from "../../utils/CurrencyFormatter";
|
||||||
import { TimeFormatter } from "../../utils/DateFormatter";
|
import { TimeFormatter } from "../../utils/DateFormatter";
|
||||||
import PhoneFormatter from "../../utils/PhoneFormatter";
|
import PhoneFormatter from "../../utils/PhoneFormatter";
|
||||||
import { onlyUnique } from "../../utils/arrayHelper";
|
import { onlyUnique } from "../../utils/arrayHelper";
|
||||||
|
import InstanceRenderManager from "../../utils/instanceRenderMgr";
|
||||||
import { alphaSort, dateSort, statusSort } from "../../utils/sorters";
|
import { alphaSort, dateSort, statusSort } from "../../utils/sorters";
|
||||||
import JobAltTransportChange from "../job-at-change/job-at-change.component";
|
import JobAltTransportChange from "../job-at-change/job-at-change.component";
|
||||||
import JobPartsQueueCount from "../job-parts-queue-count/job-parts-queue-count.component";
|
import JobPartsQueueCount from "../job-parts-queue-count/job-parts-queue-count.component";
|
||||||
@@ -23,10 +26,7 @@ import ProductionListColumnPartsReceived from "./production-list-columns.partsre
|
|||||||
import ProductionListColumnNote from "./production-list-columns.productionnote.component";
|
import ProductionListColumnNote from "./production-list-columns.productionnote.component";
|
||||||
import ProductionListColumnCategory from "./production-list-columns.status.category";
|
import ProductionListColumnCategory from "./production-list-columns.status.category";
|
||||||
import ProductionListColumnStatus from "./production-list-columns.status.component";
|
import ProductionListColumnStatus from "./production-list-columns.status.component";
|
||||||
import ProductionlistColumnTouchTime from "./prodution-list-columns.touchtime.component";
|
import ProductionListColumnTouchTime from "./prodution-list-columns.touchtime.component";
|
||||||
import { store } from "../../redux/store";
|
|
||||||
import { setModalContext } from "../../redux/modals/modals.actions";
|
|
||||||
import InstanceRenderManager from "../../utils/instanceRenderMgr";
|
|
||||||
|
|
||||||
const r = ({ technician, state, activeStatuses, data, bodyshop, refetch, treatments }) => {
|
const r = ({ technician, state, activeStatuses, data, bodyshop, refetch, treatments }) => {
|
||||||
const { Enhanced_Payroll } = treatments;
|
const { Enhanced_Payroll } = treatments;
|
||||||
@@ -258,7 +258,7 @@ const r = ({ technician, state, activeStatuses, data, bodyshop, refetch, treatme
|
|||||||
{ text: "True", value: true },
|
{ text: "True", value: true },
|
||||||
{ text: "False", value: false }
|
{ text: "False", value: false }
|
||||||
],
|
],
|
||||||
onFilter: (value, record) => value.includes(record.special_coverage_policy),
|
onFilter: (value, record) => value === record.special_coverage_policy,
|
||||||
render: (text, record) => <Checkbox checked={record.special_coverage_policy} />
|
render: (text, record) => <Checkbox checked={record.special_coverage_policy} />
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -349,7 +349,14 @@ const r = ({ technician, state, activeStatuses, data, bodyshop, refetch, treatme
|
|||||||
key: "alert",
|
key: "alert",
|
||||||
sorter: (a, b) => Number(a.production_vars?.alert || false) - Number(b.production_vars?.alert || false),
|
sorter: (a, b) => Number(a.production_vars?.alert || false) - Number(b.production_vars?.alert || false),
|
||||||
sortOrder: state.sortedInfo.columnKey === "alert" && state.sortedInfo.order,
|
sortOrder: state.sortedInfo.columnKey === "alert" && state.sortedInfo.order,
|
||||||
render: (text, record) => <ProductionListColumnAlert record={{ record }} />
|
filters: [
|
||||||
|
{ text: "True", value: true },
|
||||||
|
{ text: "False", value: false }
|
||||||
|
],
|
||||||
|
onFilter: (value, record) => value === (record.production_vars?.alert || false),
|
||||||
|
render: (text, record) => (
|
||||||
|
<ProductionListColumnAlert id={record.id} productionVars={record?.production_vars} refetch={refetch} />
|
||||||
|
)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: i18n.t("production.labels.note"),
|
title: i18n.t("production.labels.note"),
|
||||||
@@ -370,7 +377,7 @@ const r = ({ technician, state, activeStatuses, data, bodyshop, refetch, treatme
|
|||||||
dataIndex: "tt",
|
dataIndex: "tt",
|
||||||
key: "tt",
|
key: "tt",
|
||||||
render: (text, record) => {
|
render: (text, record) => {
|
||||||
return <ProductionlistColumnTouchTime job={record} />;
|
return <ProductionListColumnTouchTime job={record} />;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -148,6 +148,7 @@ export function ProductionListEmpAssignment({ insertAuditTrail, bodyshop, record
|
|||||||
) : (
|
) : (
|
||||||
<PlusCircleFilled
|
<PlusCircleFilled
|
||||||
style={iconStyle}
|
style={iconStyle}
|
||||||
|
className="muted-button"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setAssignment({ operation: type });
|
setAssignment({ operation: type });
|
||||||
setVisibility(true);
|
setVisibility(true);
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { Button, Form, Input, notification, Popover, Space } from "antd";
|
|||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { UPDATE_SHOP } from "../../graphql/bodyshop.queries";
|
import { UPDATE_SHOP } from "../../graphql/bodyshop.queries";
|
||||||
import { logImEXEvent } from "../../firebase/firebase.utils";
|
import { logImEXEvent } from "../../firebase/firebase.utils";
|
||||||
|
import { isFunction } from "lodash";
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
//currentUser: selectCurrentUser
|
//currentUser: selectCurrentUser
|
||||||
@@ -16,7 +17,7 @@ const mapDispatchToProps = (dispatch) => ({
|
|||||||
//setUserLanguage: language => dispatch(setUserLanguage(language))
|
//setUserLanguage: language => dispatch(setUserLanguage(language))
|
||||||
});
|
});
|
||||||
|
|
||||||
export function ProductionListSaveConfigButton({ columns, bodyshop, tableState }) {
|
export function ProductionListSaveConfigButton({ columns, bodyshop, tableState, onSave }) {
|
||||||
const [updateShop] = useMutation(UPDATE_SHOP);
|
const [updateShop] = useMutation(UPDATE_SHOP);
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
@@ -49,6 +50,9 @@ export function ProductionListSaveConfigButton({ columns, bodyshop, tableState }
|
|||||||
});
|
});
|
||||||
if (!!!result.errors) {
|
if (!!!result.errors) {
|
||||||
notification["success"]({ message: t("bodyshop.successes.save") });
|
notification["success"]({ message: t("bodyshop.successes.save") });
|
||||||
|
if (onSave && isFunction(onSave)) {
|
||||||
|
onSave();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
notification["error"]({
|
notification["error"]({
|
||||||
message: t("bodyshop.errors.saving", {
|
message: t("bodyshop.errors.saving", {
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import { selectTechnician } from "../../redux/tech/tech.selectors";
|
|||||||
import { selectBodyshop, selectCurrentUser } from "../../redux/user/user.selectors";
|
import { selectBodyshop, selectCurrentUser } from "../../redux/user/user.selectors";
|
||||||
import ProductionListColumns from "../production-list-columns/production-list-columns.data";
|
import ProductionListColumns from "../production-list-columns/production-list-columns.data";
|
||||||
import { useSplitTreatments } from "@splitsoftware/splitio-react";
|
import { useSplitTreatments } from "@splitsoftware/splitio-react";
|
||||||
|
import { isFunction } from "lodash";
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
bodyshop: selectBodyshop,
|
bodyshop: selectBodyshop,
|
||||||
@@ -18,7 +19,17 @@ const mapStateToProps = createStructuredSelector({
|
|||||||
currentUser: selectCurrentUser
|
currentUser: selectCurrentUser
|
||||||
});
|
});
|
||||||
|
|
||||||
export function ProductionListTable({ refetch, bodyshop, technician, currentUser, state, data, setColumns, setState }) {
|
export function ProductionListTable({
|
||||||
|
refetch,
|
||||||
|
bodyshop,
|
||||||
|
technician,
|
||||||
|
currentUser,
|
||||||
|
state,
|
||||||
|
data,
|
||||||
|
setColumns,
|
||||||
|
setState,
|
||||||
|
onProfileChange
|
||||||
|
}) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [updateDefaultProdView] = useMutation(UPDATE_ACTIVE_PROD_LIST_VIEW);
|
const [updateDefaultProdView] = useMutation(UPDATE_ACTIVE_PROD_LIST_VIEW);
|
||||||
const [updateShop] = useMutation(UPDATE_SHOP);
|
const [updateShop] = useMutation(UPDATE_SHOP);
|
||||||
@@ -32,25 +43,25 @@ export function ProductionListTable({ refetch, bodyshop, technician, currentUser
|
|||||||
});
|
});
|
||||||
|
|
||||||
const handleSelect = async (value, option) => {
|
const handleSelect = async (value, option) => {
|
||||||
setColumns(
|
const newColumns = bodyshop.production_config
|
||||||
bodyshop.production_config
|
.filter((pc) => pc.name === value)[0]
|
||||||
.filter((pc) => pc.name === value)[0]
|
.columns.columnKeys.map((k) => {
|
||||||
.columns.columnKeys.map((k) => {
|
return {
|
||||||
return {
|
...ProductionListColumns({
|
||||||
...ProductionListColumns({
|
bodyshop,
|
||||||
bodyshop,
|
refetch,
|
||||||
refetch,
|
technician,
|
||||||
technician,
|
state,
|
||||||
state,
|
data: data,
|
||||||
data: data,
|
activeStatuses: bodyshop.md_ro_statuses.active_statuses,
|
||||||
activeStatuses: bodyshop.md_ro_statuses.active_statuses,
|
treatments: { Enhanced_Payroll }
|
||||||
treatments: { Enhanced_Payroll }
|
}).find((e) => e.key === k.key),
|
||||||
}).find((e) => e.key === k.key),
|
width: k.width
|
||||||
width: k.width
|
};
|
||||||
};
|
});
|
||||||
})
|
setColumns(newColumns);
|
||||||
);
|
const newState = bodyshop.production_config.filter((pc) => pc.name === value)[0].columns.tableState;
|
||||||
setState(bodyshop.production_config.filter((pc) => pc.name === value)[0].columns.tableState);
|
setState(newState);
|
||||||
|
|
||||||
const assoc = bodyshop.associations.find((a) => a.useremail === currentUser.email);
|
const assoc = bodyshop.associations.find((a) => a.useremail === currentUser.email);
|
||||||
|
|
||||||
@@ -72,6 +83,10 @@ export function ProductionListTable({ refetch, bodyshop, technician, currentUser
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (onProfileChange && isFunction(onProfileChange)) {
|
||||||
|
onProfileChange({ value, option, newColumns, newState, assoc });
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleTrash = async (name) => {
|
const handleTrash = async (name) => {
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
import { SyncOutlined } from "@ant-design/icons";
|
import React, { useEffect, useMemo, useRef, useState } from "react";
|
||||||
import { useSplitTreatments } from "@splitsoftware/splitio-react";
|
|
||||||
import { Button, Dropdown, Input, Space, Statistic, Table } from "antd";
|
import { Button, Dropdown, Input, Space, Statistic, Table } from "antd";
|
||||||
import { PageHeader } from "@ant-design/pro-layout";
|
import { PageHeader } from "@ant-design/pro-layout";
|
||||||
import React, { useEffect, useMemo, useState } from "react";
|
|
||||||
import ReactDragListView from "react-drag-listview";
|
import ReactDragListView from "react-drag-listview";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
@@ -16,6 +14,11 @@ import ProductionListSaveConfigButton from "../production-list-save-config-butto
|
|||||||
import ProductionListPrint from "./production-list-print.component";
|
import ProductionListPrint from "./production-list-print.component";
|
||||||
import ProductionListTableViewSelect from "./production-list-table-view-select.component";
|
import ProductionListTableViewSelect from "./production-list-table-view-select.component";
|
||||||
import ResizeableTitle from "./production-list-table.resizeable.component";
|
import ResizeableTitle from "./production-list-table.resizeable.component";
|
||||||
|
import { useSplitTreatments } from "@splitsoftware/splitio-react";
|
||||||
|
import { SyncOutlined } from "@ant-design/icons";
|
||||||
|
import Prompt from "../../utils/prompt.js";
|
||||||
|
import _ from "lodash";
|
||||||
|
import AlertComponent from "../alert/alert.component.jsx";
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
bodyshop: selectBodyshop,
|
bodyshop: selectBodyshop,
|
||||||
@@ -25,6 +28,7 @@ const mapStateToProps = createStructuredSelector({
|
|||||||
|
|
||||||
export function ProductionListTable({ loading, data, refetch, bodyshop, technician, currentUser }) {
|
export function ProductionListTable({ loading, data, refetch, bodyshop, technician, currentUser }) {
|
||||||
const [searchText, setSearchText] = useState("");
|
const [searchText, setSearchText] = useState("");
|
||||||
|
const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
treatments: { Production_List_Status_Colors, Enhanced_Payroll }
|
treatments: { Production_List_Status_Colors, Enhanced_Payroll }
|
||||||
@@ -35,10 +39,9 @@ export function ProductionListTable({ loading, data, refetch, bodyshop, technici
|
|||||||
});
|
});
|
||||||
|
|
||||||
const assoc = bodyshop.associations.find((a) => a.useremail === currentUser.email);
|
const assoc = bodyshop.associations.find((a) => a.useremail === currentUser.email);
|
||||||
|
|
||||||
const defaultView = assoc && assoc.default_prod_list_view;
|
const defaultView = assoc && assoc.default_prod_list_view;
|
||||||
|
|
||||||
const [state, setState] = useState(
|
const initialStateRef = useRef(
|
||||||
(bodyshop.production_config &&
|
(bodyshop.production_config &&
|
||||||
bodyshop.production_config.find((p) => p.name === defaultView)?.columns.tableState) ||
|
bodyshop.production_config.find((p) => p.name === defaultView)?.columns.tableState) ||
|
||||||
bodyshop.production_config[0]?.columns.tableState || {
|
bodyshop.production_config[0]?.columns.tableState || {
|
||||||
@@ -47,80 +50,102 @@ export function ProductionListTable({ loading, data, refetch, bodyshop, technici
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
const { t } = useTranslation();
|
const initialColumnsRef = useRef(
|
||||||
|
(initialStateRef.current &&
|
||||||
const matchingColumnConfig = useMemo(() => {
|
bodyshop.production_config
|
||||||
return bodyshop.production_config.find((p) => p.name === defaultView);
|
.find((p) => p.name === defaultView)
|
||||||
}, [bodyshop.production_config, defaultView]);
|
?.columns.columnKeys.map((k) => {
|
||||||
|
|
||||||
const [columns, setColumns] = useState(
|
|
||||||
(state &&
|
|
||||||
matchingColumnConfig &&
|
|
||||||
matchingColumnConfig.columns.columnKeys.map((k) => {
|
|
||||||
return {
|
|
||||||
...ProductionListColumns({
|
|
||||||
bodyshop,
|
|
||||||
refetch,
|
|
||||||
technician,
|
|
||||||
state,
|
|
||||||
data,
|
|
||||||
activeStatuses: bodyshop.md_ro_statuses.active_statuses,
|
|
||||||
treatments: { Production_List_Status_Colors, Enhanced_Payroll }
|
|
||||||
}).find((e) => e.key === k.key),
|
|
||||||
width: k.width ?? 100
|
|
||||||
};
|
|
||||||
})) ||
|
|
||||||
[]
|
|
||||||
);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const newColumns =
|
|
||||||
(state &&
|
|
||||||
matchingColumnConfig &&
|
|
||||||
matchingColumnConfig.columns.columnKeys.map((k) => {
|
|
||||||
return {
|
return {
|
||||||
...ProductionListColumns({
|
...ProductionListColumns({
|
||||||
bodyshop,
|
bodyshop,
|
||||||
technician,
|
|
||||||
refetch,
|
refetch,
|
||||||
state,
|
technician,
|
||||||
data: data,
|
state: initialStateRef.current,
|
||||||
|
data,
|
||||||
activeStatuses: bodyshop.md_ro_statuses.active_statuses,
|
activeStatuses: bodyshop.md_ro_statuses.active_statuses,
|
||||||
treatments: { Production_List_Status_Colors, Enhanced_Payroll }
|
treatments: { Production_List_Status_Colors, Enhanced_Payroll }
|
||||||
}).find((e) => e.key === k.key),
|
}).find((e) => e.key === k.key),
|
||||||
width: k.width ?? 100
|
width: k.width ?? 100
|
||||||
};
|
};
|
||||||
})) ||
|
})) ||
|
||||||
[];
|
[]
|
||||||
setColumns(newColumns);
|
);
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
|
const [state, setState] = useState(initialStateRef.current);
|
||||||
|
const [columns, setColumns] = useState(initialColumnsRef.current);
|
||||||
|
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
const matchingColumnConfig = useMemo(() => {
|
||||||
|
return bodyshop.production_config.find((p) => p.name === defaultView);
|
||||||
|
}, [bodyshop.production_config, defaultView]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const newColumns =
|
||||||
|
matchingColumnConfig?.columns.columnKeys.map((k) => {
|
||||||
|
return {
|
||||||
|
...ProductionListColumns({
|
||||||
|
bodyshop,
|
||||||
|
technician,
|
||||||
|
refetch,
|
||||||
|
state,
|
||||||
|
data: data,
|
||||||
|
activeStatuses: bodyshop.md_ro_statuses.active_statuses,
|
||||||
|
treatments: { Production_List_Status_Colors, Enhanced_Payroll }
|
||||||
|
}).find((e) => e.key === k.key),
|
||||||
|
width: k.width ?? 100
|
||||||
|
};
|
||||||
|
}) || [];
|
||||||
|
|
||||||
|
// Only update columns if they haven't been manually changed by the user
|
||||||
|
if (_.isEqual(initialColumnsRef.current, columns)) {
|
||||||
|
setColumns(newColumns);
|
||||||
|
}
|
||||||
}, [
|
}, [
|
||||||
//state,
|
|
||||||
matchingColumnConfig,
|
matchingColumnConfig,
|
||||||
bodyshop,
|
bodyshop,
|
||||||
technician,
|
technician,
|
||||||
data
|
data,
|
||||||
]); //State removed from dependency array as it causes race condition when removing columns from table view and is not needed.
|
Enhanced_Payroll,
|
||||||
|
Production_List_Status_Colors,
|
||||||
|
refetch,
|
||||||
|
state,
|
||||||
|
columns
|
||||||
|
]);
|
||||||
|
|
||||||
const handleTableChange = (pagination, filters, sorter) => {
|
const handleTableChange = (pagination, filters, sorter) => {
|
||||||
setState({
|
const newState = {
|
||||||
...state,
|
...state,
|
||||||
filteredInfo: filters,
|
filteredInfo: filters,
|
||||||
sortedInfo: { columnKey: sorter.columnKey, order: sorter.order }
|
sortedInfo: { columnKey: sorter.columnKey, order: sorter.order }
|
||||||
});
|
};
|
||||||
|
if (!_.isEqual(newState, state)) {
|
||||||
|
setState(newState);
|
||||||
|
setHasUnsavedChanges(true);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const onDragEnd = (fromIndex, toIndex) => {
|
const onDragEnd = (fromIndex, toIndex) => {
|
||||||
const columnsCopy = columns.slice();
|
if (fromIndex === toIndex) return;
|
||||||
const item = columnsCopy.splice(fromIndex, 1)[0];
|
|
||||||
columnsCopy.splice(toIndex, 0, item);
|
const columnsCopy = [...columns];
|
||||||
setColumns(columnsCopy);
|
const [movedItem] = columnsCopy.splice(fromIndex, 1);
|
||||||
|
columnsCopy.splice(toIndex, 0, movedItem);
|
||||||
|
|
||||||
|
if (!_.isEqual(columnsCopy, columns)) {
|
||||||
|
setColumns(columnsCopy);
|
||||||
|
setHasUnsavedChanges(true);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const removeColumn = (e) => {
|
const removeColumn = (e) => {
|
||||||
const { key } = e;
|
const { key } = e;
|
||||||
const newColumns = columns.filter((i) => i.key !== key);
|
const newColumns = columns.filter((i) => i.key !== key);
|
||||||
setColumns(newColumns);
|
|
||||||
|
if (!_.isEqual(newColumns, columns)) {
|
||||||
|
setColumns(newColumns);
|
||||||
|
setHasUnsavedChanges(true);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleResize =
|
const handleResize =
|
||||||
@@ -131,9 +156,21 @@ export function ProductionListTable({ loading, data, refetch, bodyshop, technici
|
|||||||
...nextColumns[index],
|
...nextColumns[index],
|
||||||
width: size.width
|
width: size.width
|
||||||
};
|
};
|
||||||
setColumns(nextColumns);
|
|
||||||
|
if (!_.isEqual(nextColumns, columns)) {
|
||||||
|
setColumns(nextColumns);
|
||||||
|
setHasUnsavedChanges(true);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const addColumn = (newColumn) => {
|
||||||
|
const updatedColumns = [...columns, newColumn];
|
||||||
|
if (!_.isEqual(updatedColumns, columns)) {
|
||||||
|
setColumns(updatedColumns);
|
||||||
|
setHasUnsavedChanges(true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const headerItem = (col) => {
|
const headerItem = (col) => {
|
||||||
const menu = {
|
const menu = {
|
||||||
onClick: removeColumn,
|
onClick: removeColumn,
|
||||||
@@ -152,29 +189,29 @@ export function ProductionListTable({ loading, data, refetch, bodyshop, technici
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const dataSource =
|
const resetChanges = () => {
|
||||||
searchText === ""
|
setState(initialStateRef.current);
|
||||||
? data
|
setColumns(initialColumnsRef.current);
|
||||||
: data.filter(
|
setHasUnsavedChanges(false);
|
||||||
(j) =>
|
};
|
||||||
(j.ro_number || "").toString().toLowerCase().includes(searchText.toLowerCase()) ||
|
|
||||||
(j.ownr_co_nm || "").toLowerCase().includes(searchText.toLowerCase()) ||
|
|
||||||
(j.ownr_fn || "").toLowerCase().includes(searchText.toLowerCase()) ||
|
|
||||||
(j.ownr_ln || "").toLowerCase().includes(searchText.toLowerCase()) ||
|
|
||||||
(j.status || "").toLowerCase().includes(searchText.toLowerCase()) ||
|
|
||||||
(j.ins_co_nm || "").toLowerCase().includes(searchText.toLowerCase()) ||
|
|
||||||
(j.clm_no || "").toLowerCase().includes(searchText.toLowerCase()) ||
|
|
||||||
(j.v_model_desc || "").toLowerCase().includes(searchText.toLowerCase()) ||
|
|
||||||
(j.v_make_desc || "").toLowerCase().includes(searchText.toLowerCase())
|
|
||||||
);
|
|
||||||
|
|
||||||
// const handleSelectRecord = (record) => {
|
const filterData = (item, searchText) => {
|
||||||
// if (selected !== record.id) {
|
const fieldsToSearch = [
|
||||||
// setSelected(record.id);
|
item.ro_number,
|
||||||
// } else {
|
item.ownr_co_nm,
|
||||||
// setSelected(null);
|
item.ownr_fn,
|
||||||
// }
|
item.ownr_ln,
|
||||||
// };
|
item.status,
|
||||||
|
item.ins_co_nm,
|
||||||
|
item.clm_no,
|
||||||
|
item.v_model_desc,
|
||||||
|
item.v_make_desc
|
||||||
|
];
|
||||||
|
|
||||||
|
return fieldsToSearch.some((field) => (field || "").toString().toLowerCase().includes(searchText.toLowerCase()));
|
||||||
|
};
|
||||||
|
|
||||||
|
const dataSource = searchText === "" ? data : data.filter((j) => filterData(j, searchText));
|
||||||
|
|
||||||
if (!!!columns) return <div>No columns found.</div>;
|
if (!!!columns) return <div>No columns found.</div>;
|
||||||
|
|
||||||
@@ -186,8 +223,29 @@ export function ProductionListTable({ loading, data, refetch, bodyshop, technici
|
|||||||
.toFixed(1);
|
.toFixed(1);
|
||||||
const totalLAB = data.reduce((acc, val) => acc + (val.labhrs?.aggregate?.sum?.mod_lb_hrs || 0), 0).toFixed(1);
|
const totalLAB = data.reduce((acc, val) => acc + (val.labhrs?.aggregate?.sum?.mod_lb_hrs || 0), 0).toFixed(1);
|
||||||
const totalLAR = data.reduce((acc, val) => acc + (val.larhrs?.aggregate?.sum?.mod_lb_hrs || 0), 0).toFixed(1);
|
const totalLAR = data.reduce((acc, val) => acc + (val.larhrs?.aggregate?.sum?.mod_lb_hrs || 0), 0).toFixed(1);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
<Prompt when={hasUnsavedChanges} beforeUnload={true} message={t("general.messages.unsavedchangespopup")} />
|
||||||
|
{hasUnsavedChanges && (
|
||||||
|
<AlertComponent
|
||||||
|
type="warning"
|
||||||
|
message={
|
||||||
|
<div>
|
||||||
|
<span>{t("general.messages.unsavedchanges")} </span>
|
||||||
|
<span
|
||||||
|
onClick={resetChanges}
|
||||||
|
style={{
|
||||||
|
cursor: "pointer",
|
||||||
|
textDecoration: "underline"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{t("general.actions.reset")}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
<PageHeader
|
<PageHeader
|
||||||
title={
|
title={
|
||||||
<Space>
|
<Space>
|
||||||
@@ -199,20 +257,37 @@ export function ProductionListTable({ loading, data, refetch, bodyshop, technici
|
|||||||
}
|
}
|
||||||
extra={
|
extra={
|
||||||
<Space wrap>
|
<Space wrap>
|
||||||
<Button onClick={() => refetch && refetch()}>
|
<Button
|
||||||
|
onClick={() => {
|
||||||
|
refetch && refetch();
|
||||||
|
}}
|
||||||
|
>
|
||||||
<SyncOutlined />
|
<SyncOutlined />
|
||||||
</Button>
|
</Button>
|
||||||
<ProductionListColumnsAdd columnState={[columns, setColumns]} tableState={state} data={data} />
|
<ProductionListColumnsAdd
|
||||||
<ProductionListSaveConfigButton columns={columns} tableState={state} />
|
columnState={[columns, setColumns]}
|
||||||
|
tableState={state}
|
||||||
|
data={data}
|
||||||
|
onColumnAdd={addColumn}
|
||||||
|
/>
|
||||||
|
<ProductionListSaveConfigButton
|
||||||
|
columns={columns}
|
||||||
|
tableState={state}
|
||||||
|
onSave={() => {
|
||||||
|
setHasUnsavedChanges(false);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
<ProductionListTableViewSelect
|
<ProductionListTableViewSelect
|
||||||
state={state}
|
state={state}
|
||||||
setState={setState}
|
setState={setState}
|
||||||
setColumns={setColumns}
|
setColumns={setColumns}
|
||||||
|
onProfileChange={() => {
|
||||||
|
initialStateRef.current = state;
|
||||||
|
setHasUnsavedChanges(false);
|
||||||
|
}}
|
||||||
refetch={refetch}
|
refetch={refetch}
|
||||||
data={data}
|
data={data}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Input
|
<Input
|
||||||
onChange={(e) => setSearchText(e.target.value)}
|
onChange={(e) => setSearchText(e.target.value)}
|
||||||
placeholder={t("general.labels.search")}
|
placeholder={t("general.labels.search")}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { AlertOutlined } from "@ant-design/icons";
|
import { AlertOutlined } from "@ant-design/icons";
|
||||||
import { Alert, Button, Col, Row, Space } from "antd";
|
import { Alert, Button, Col, Row, Space } from "antd";
|
||||||
import i18n from "i18next";
|
import i18n from "i18next";
|
||||||
import React from "react";
|
import React, { useEffect } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import { createStructuredSelector } from "reselect";
|
import { createStructuredSelector } from "reselect";
|
||||||
@@ -12,39 +12,42 @@ import InstanceRenderManager from "../../utils/instanceRenderMgr";
|
|||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
updateAvailable: selectUpdateAvailable
|
updateAvailable: selectUpdateAvailable
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
//setUserLanguage: language => dispatch(setUserLanguage(language))
|
// setUserLanguage: language => dispatch(setUserLanguage(language))
|
||||||
});
|
});
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(UpdateAlert);
|
|
||||||
const intervalMS = 10 * 60 * 1000;
|
|
||||||
export function UpdateAlert({ updateAvailable }) {
|
export function UpdateAlert({ updateAvailable }) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
offlineReady: [
|
offlineReady: [offlineReady],
|
||||||
offlineReady //setOfflineReady
|
needRefresh: [needRefresh],
|
||||||
],
|
|
||||||
needRefresh: [
|
|
||||||
needRefresh //setNeedRefresh
|
|
||||||
],
|
|
||||||
updateServiceWorker
|
updateServiceWorker
|
||||||
} = useRegisterSW({
|
} = useRegisterSW({
|
||||||
onRegistered(r) {
|
onRegistered(r) {
|
||||||
// eslint-disable-next-line prefer-template
|
console.log("SW Registered:", r);
|
||||||
console.log("SW Registered: " + r);
|
if (r) {
|
||||||
r &&
|
setInterval(
|
||||||
setInterval(() => {
|
() => {
|
||||||
r.update();
|
r.update();
|
||||||
}, intervalMS);
|
},
|
||||||
|
10 * 60 * 1000
|
||||||
|
);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
onRegisterError(error) {
|
onRegisterError(error) {
|
||||||
console.log("SW registration error", error);
|
console.error("SW registration error", error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (import.meta.env.DEV) console.log(`SW Status => Refresh? ${needRefresh} - offlineReady? ${offlineReady}`);
|
useEffect(() => {
|
||||||
|
if (import.meta.env.DEV) {
|
||||||
|
console.log(`SW Status => Refresh? ${needRefresh} - offlineReady? ${offlineReady}`);
|
||||||
|
}
|
||||||
|
}, [needRefresh, offlineReady]);
|
||||||
|
|
||||||
if (!needRefresh) return null;
|
if (!needRefresh) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Alert
|
<Alert
|
||||||
message={t("general.messages.newversiontitle", {
|
message={t("general.messages.newversiontitle", {
|
||||||
@@ -69,19 +72,10 @@ export function UpdateAlert({ updateAvailable }) {
|
|||||||
</Col>
|
</Col>
|
||||||
<Col sm={24} md={8} lg={6}>
|
<Col sm={24} md={8} lg={6}>
|
||||||
<Space wrap>
|
<Space wrap>
|
||||||
<Button
|
<Button onClick={() => window.open("https://imex-online.noticeable.news/", "_blank")}>
|
||||||
onClick={async () => {
|
|
||||||
window.open("https://imex-online.noticeable.news/", "_blank");
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{i18n.t("general.actions.viewreleasenotes")}
|
{i18n.t("general.actions.viewreleasenotes")}
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button type="primary" onClick={() => updateServiceWorker(true)}>
|
||||||
type="primary"
|
|
||||||
onClick={async () => {
|
|
||||||
updateServiceWorker(true);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{i18n.t("general.actions.refresh")}
|
{i18n.t("general.actions.refresh")}
|
||||||
</Button>
|
</Button>
|
||||||
</Space>
|
</Space>
|
||||||
@@ -93,3 +87,5 @@ export function UpdateAlert({ updateAvailable }) {
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default connect(mapStateToProps, mapDispatchToProps)(UpdateAlert);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { gql } from "@apollo/client";
|
import { gql } from "@apollo/client";
|
||||||
|
|
||||||
export const QUERY_ALL_ACTIVE_JOBS_PAGINATED = gql`
|
export const QUERY_ALL_ACTIVE_JOBS_PAGINATED = gql`
|
||||||
query QUERY_ALL_JOBS_PAGINATED_STATUS_FILTERED(
|
query QUERY_ALL_ACTIVE_JOBS_PAGINATED(
|
||||||
$offset: Int
|
$offset: Int
|
||||||
$limit: Int
|
$limit: Int
|
||||||
$order: [jobs_order_by!]
|
$order: [jobs_order_by!]
|
||||||
@@ -2465,6 +2465,11 @@ export const SUBSCRIPTION_JOBS_IN_PRODUCTION = gql`
|
|||||||
export const QUERY_JOBS_IN_PRODUCTION = gql`
|
export const QUERY_JOBS_IN_PRODUCTION = gql`
|
||||||
query QUERY_JOBS_IN_PRODUCTION {
|
query QUERY_JOBS_IN_PRODUCTION {
|
||||||
jobs(where: { inproduction: { _eq: true } }) {
|
jobs(where: { inproduction: { _eq: true } }) {
|
||||||
|
tasks_aggregate(where: { completed: { _eq: false }, deleted: { _eq: false } }) {
|
||||||
|
aggregate {
|
||||||
|
count
|
||||||
|
}
|
||||||
|
}
|
||||||
id
|
id
|
||||||
updated_at
|
updated_at
|
||||||
comment
|
comment
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ import ErrorBoundary from "../../components/error-boundary/error-boundary.compon
|
|||||||
//import FooterComponent from "../../components/footer/footer.component";
|
//import FooterComponent from "../../components/footer/footer.component";
|
||||||
//Component Imports
|
//Component Imports
|
||||||
import * as Sentry from "@sentry/react";
|
import * as Sentry from "@sentry/react";
|
||||||
import Joyride from "react-joyride";
|
|
||||||
import TestComponent from "../../components/_test/test.page";
|
import TestComponent from "../../components/_test/test.page";
|
||||||
import HeaderContainer from "../../components/header/header.container";
|
import HeaderContainer from "../../components/header/header.container";
|
||||||
import LoadingSpinner from "../../components/loading-spinner/loading-spinner.component";
|
import LoadingSpinner from "../../components/loading-spinner/loading-spinner.component";
|
||||||
@@ -23,8 +22,6 @@ import { requestForToken } from "../../firebase/firebase.utils";
|
|||||||
import { selectBodyshop, selectInstanceConflict } from "../../redux/user/user.selectors";
|
import { selectBodyshop, selectInstanceConflict } from "../../redux/user/user.selectors";
|
||||||
|
|
||||||
import UpdateAlert from "../../components/update-alert/update-alert.component";
|
import UpdateAlert from "../../components/update-alert/update-alert.component";
|
||||||
import { setJoyRideFinished } from "../../redux/application/application.actions.js";
|
|
||||||
import { selectEnableJoyRide, selectJoyRideSteps } from "../../redux/application/application.selectors.js";
|
|
||||||
import InstanceRenderManager from "../../utils/instanceRenderMgr.js";
|
import InstanceRenderManager from "../../utils/instanceRenderMgr.js";
|
||||||
import "./manage.page.styles.scss";
|
import "./manage.page.styles.scss";
|
||||||
|
|
||||||
@@ -105,16 +102,12 @@ const { Content, Footer } = Layout;
|
|||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
conflict: selectInstanceConflict,
|
conflict: selectInstanceConflict,
|
||||||
bodyshop: selectBodyshop,
|
bodyshop: selectBodyshop
|
||||||
enableJoyRide: selectEnableJoyRide,
|
|
||||||
joyRideSteps: selectJoyRideSteps
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
const mapDispatchToProps = (dispatch) => ({});
|
||||||
setJoyRideFinished: (steps) => dispatch(setJoyRideFinished(steps))
|
|
||||||
});
|
|
||||||
|
|
||||||
export function Manage({ conflict, bodyshop, enableJoyRide, joyRideSteps, setJoyRideFinished }) {
|
export function Manage({ conflict, bodyshop }) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [chatVisible] = useState(false);
|
const [chatVisible] = useState(false);
|
||||||
|
|
||||||
@@ -583,21 +576,6 @@ export function Manage({ conflict, bodyshop, enableJoyRide, joyRideSteps, setJoy
|
|||||||
<UpdateAlert />
|
<UpdateAlert />
|
||||||
<HeaderContainer />
|
<HeaderContainer />
|
||||||
<Content className="content-container">
|
<Content className="content-container">
|
||||||
<Joyride
|
|
||||||
debug
|
|
||||||
run={enableJoyRide}
|
|
||||||
steps={joyRideSteps}
|
|
||||||
continuous
|
|
||||||
hideCloseButton
|
|
||||||
scrollToFirstStep
|
|
||||||
showProgress
|
|
||||||
showSkipButton
|
|
||||||
callback={(props) => {
|
|
||||||
if (props.action === "reset") {
|
|
||||||
setJoyRideFinished();
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<PartnerPingComponent />
|
<PartnerPingComponent />
|
||||||
<Sentry.ErrorBoundary fallback={<ErrorBoundary />} showDialog>
|
<Sentry.ErrorBoundary fallback={<ErrorBoundary />} showDialog>
|
||||||
{PageContent}
|
{PageContent}
|
||||||
|
|||||||
@@ -67,11 +67,3 @@ export const setUpdateAvailable = (isUpdateAvailable) => ({
|
|||||||
type: ApplicationActionTypes.SET_UPDATE_AVAILABLE,
|
type: ApplicationActionTypes.SET_UPDATE_AVAILABLE,
|
||||||
payload: isUpdateAvailable
|
payload: isUpdateAvailable
|
||||||
});
|
});
|
||||||
export const setJoyRideSteps = (steps) => ({
|
|
||||||
type: ApplicationActionTypes.SET_JOYRIDE_STEPS,
|
|
||||||
payload: steps
|
|
||||||
});
|
|
||||||
export const setJoyRideFinished = () => ({
|
|
||||||
type: ApplicationActionTypes.SET_JOYRIDE_FINISHED
|
|
||||||
//payload: isUpdateAvailable,
|
|
||||||
});
|
|
||||||
|
|||||||
@@ -14,9 +14,7 @@ const INITIAL_STATE = {
|
|||||||
error: null
|
error: null
|
||||||
},
|
},
|
||||||
jobReadOnly: false,
|
jobReadOnly: false,
|
||||||
partnerVersion: null,
|
partnerVersion: null
|
||||||
enableJoyRide: false,
|
|
||||||
joyRideSteps: []
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const applicationReducer = (state = INITIAL_STATE, action) => {
|
const applicationReducer = (state = INITIAL_STATE, action) => {
|
||||||
@@ -89,12 +87,6 @@ const applicationReducer = (state = INITIAL_STATE, action) => {
|
|||||||
case ApplicationActionTypes.SET_PROBLEM_JOBS: {
|
case ApplicationActionTypes.SET_PROBLEM_JOBS: {
|
||||||
return { ...state, problemJobs: action.payload };
|
return { ...state, problemJobs: action.payload };
|
||||||
}
|
}
|
||||||
case ApplicationActionTypes.SET_JOYRIDE_STEPS: {
|
|
||||||
return { ...state, enableJoyRide: true, joyRideSteps: action.payload };
|
|
||||||
}
|
|
||||||
case ApplicationActionTypes.SET_JOYRIDE_FINISHED: {
|
|
||||||
return { ...state, enableJoyRide: false, joyRideSteps: [] };
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,5 +22,3 @@ export const selectJobReadOnly = createSelector([selectApplication], (applicatio
|
|||||||
export const selectOnline = createSelector([selectApplication], (application) => application.online);
|
export const selectOnline = createSelector([selectApplication], (application) => application.online);
|
||||||
export const selectProblemJobs = createSelector([selectApplication], (application) => application.problemJobs);
|
export const selectProblemJobs = createSelector([selectApplication], (application) => application.problemJobs);
|
||||||
export const selectUpdateAvailable = createSelector([selectApplication], (application) => application.updateAvailable);
|
export const selectUpdateAvailable = createSelector([selectApplication], (application) => application.updateAvailable);
|
||||||
export const selectEnableJoyRide = createSelector([selectApplication], (application) => application.enableJoyRide);
|
|
||||||
export const selectJoyRideSteps = createSelector([selectApplication], (application) => application.joyRideSteps);
|
|
||||||
|
|||||||
@@ -12,8 +12,6 @@ const ApplicationActionTypes = {
|
|||||||
SET_ONLINE_STATUS: "SET_ONLINE_STATUS",
|
SET_ONLINE_STATUS: "SET_ONLINE_STATUS",
|
||||||
INSERT_AUDIT_TRAIL: "INSERT_AUDIT_TRAIL",
|
INSERT_AUDIT_TRAIL: "INSERT_AUDIT_TRAIL",
|
||||||
SET_PROBLEM_JOBS: "SET_PROBLEM_JOBS",
|
SET_PROBLEM_JOBS: "SET_PROBLEM_JOBS",
|
||||||
SET_UPDATE_AVAILABLE: "SET_UPDATE_AVAILABLE",
|
SET_UPDATE_AVAILABLE: "SET_UPDATE_AVAILABLE"
|
||||||
SET_JOYRIDE_STEPS: "SET_JOYRIDE_STEPS",
|
|
||||||
SET_JOYRIDE_FINISHED: "SET_JOYRIDE_FINISHED"
|
|
||||||
};
|
};
|
||||||
export default ApplicationActionTypes;
|
export default ApplicationActionTypes;
|
||||||
|
|||||||
@@ -1160,7 +1160,8 @@
|
|||||||
"submit": "Submit",
|
"submit": "Submit",
|
||||||
"tryagain": "Try Again",
|
"tryagain": "Try Again",
|
||||||
"view": "View",
|
"view": "View",
|
||||||
"viewreleasenotes": "See What's Changed"
|
"viewreleasenotes": "See What's Changed",
|
||||||
|
"remove_alert": "Are you sure you want to dismiss the alert?"
|
||||||
},
|
},
|
||||||
"errors": {
|
"errors": {
|
||||||
"fcm": "You must allow notification permissions to have real time messaging. Click to try again.",
|
"fcm": "You must allow notification permissions to have real time messaging. Click to try again.",
|
||||||
@@ -2757,7 +2758,9 @@
|
|||||||
"total_lab_on_board": "Body Hours on Board",
|
"total_lab_on_board": "Body Hours on Board",
|
||||||
"total_lar_on_board": "Refinish Hours on Board",
|
"total_lar_on_board": "Refinish Hours on Board",
|
||||||
"total_amount_on_board": "Dollars on Board",
|
"total_amount_on_board": "Dollars on Board",
|
||||||
"total_jobs_on_board": "Jobs on Board"
|
"total_jobs_on_board": "Jobs on Board",
|
||||||
|
"tasks_in_production": "Tasks in Production",
|
||||||
|
"tasks_on_board": "Tasks on Board"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"actions": {
|
"actions": {
|
||||||
@@ -2792,6 +2795,7 @@
|
|||||||
"model_info": "Vehicle Info",
|
"model_info": "Vehicle Info",
|
||||||
"actual_in": "Actual In",
|
"actual_in": "Actual In",
|
||||||
"alert": "Alert",
|
"alert": "Alert",
|
||||||
|
"tasks": "Tasks",
|
||||||
"alertoff": "Remove alert from Job",
|
"alertoff": "Remove alert from Job",
|
||||||
"alerton": "Add alert to Job",
|
"alerton": "Add alert to Job",
|
||||||
"ats": "Alternative Transportation",
|
"ats": "Alternative Transportation",
|
||||||
@@ -2829,7 +2833,8 @@
|
|||||||
"sublets": "Sublets",
|
"sublets": "Sublets",
|
||||||
"totalhours": "Total Hrs ",
|
"totalhours": "Total Hrs ",
|
||||||
"touchtime": "T/T",
|
"touchtime": "T/T",
|
||||||
"viewname": "View Name"
|
"viewname": "View Name",
|
||||||
|
"alerts": "Alerts"
|
||||||
},
|
},
|
||||||
"successes": {
|
"successes": {
|
||||||
"removed": "Job removed from production."
|
"removed": "Job removed from production."
|
||||||
@@ -2845,6 +2850,9 @@
|
|||||||
"total_lar_on_board": "Refinish Hours on Board",
|
"total_lar_on_board": "Refinish Hours on Board",
|
||||||
"total_amount_on_board": "Dollars on Board",
|
"total_amount_on_board": "Dollars on Board",
|
||||||
"total_jobs_on_board": "Jobs on Board",
|
"total_jobs_on_board": "Jobs on Board",
|
||||||
|
"tasks_in_production": "Tasks in Production",
|
||||||
|
"tasks_on_board": "Tasks on Board",
|
||||||
|
"tasks": "Tasks",
|
||||||
"hours": "Hours",
|
"hours": "Hours",
|
||||||
"currency_symbol": "$",
|
"currency_symbol": "$",
|
||||||
"jobs": "Jobs"
|
"jobs": "Jobs"
|
||||||
|
|||||||
@@ -1160,7 +1160,8 @@
|
|||||||
"submit": "",
|
"submit": "",
|
||||||
"tryagain": "",
|
"tryagain": "",
|
||||||
"view": "",
|
"view": "",
|
||||||
"viewreleasenotes": ""
|
"viewreleasenotes": "",
|
||||||
|
"remove_alert": ""
|
||||||
},
|
},
|
||||||
"errors": {
|
"errors": {
|
||||||
"fcm": "",
|
"fcm": "",
|
||||||
@@ -2757,7 +2758,9 @@
|
|||||||
"total_lab_on_board": "",
|
"total_lab_on_board": "",
|
||||||
"total_lar_on_board": "",
|
"total_lar_on_board": "",
|
||||||
"total_amount_on_board": "",
|
"total_amount_on_board": "",
|
||||||
"total_jobs_on_board": ""
|
"total_jobs_on_board": "",
|
||||||
|
"tasks_in_production": "",
|
||||||
|
"tasks_on_board": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"actions": {
|
"actions": {
|
||||||
@@ -2792,6 +2795,7 @@
|
|||||||
"model_info": "",
|
"model_info": "",
|
||||||
"actual_in": "",
|
"actual_in": "",
|
||||||
"alert": "",
|
"alert": "",
|
||||||
|
"tasks": "",
|
||||||
"alertoff": "",
|
"alertoff": "",
|
||||||
"alerton": "",
|
"alerton": "",
|
||||||
"ats": "",
|
"ats": "",
|
||||||
@@ -2829,7 +2833,8 @@
|
|||||||
"sublets": "",
|
"sublets": "",
|
||||||
"totalhours": "",
|
"totalhours": "",
|
||||||
"touchtime": "",
|
"touchtime": "",
|
||||||
"viewname": ""
|
"viewname": "",
|
||||||
|
"alerts": ""
|
||||||
},
|
},
|
||||||
"successes": {
|
"successes": {
|
||||||
"removed": ""
|
"removed": ""
|
||||||
@@ -2845,6 +2850,9 @@
|
|||||||
"total_lar_on_board": "",
|
"total_lar_on_board": "",
|
||||||
"total_amount_on_board": "",
|
"total_amount_on_board": "",
|
||||||
"total_jobs_on_board": "",
|
"total_jobs_on_board": "",
|
||||||
|
"tasks_in_production": "",
|
||||||
|
"tasks_on_board": "",
|
||||||
|
"tasks": "",
|
||||||
"hours": "",
|
"hours": "",
|
||||||
"currency_symbol": "",
|
"currency_symbol": "",
|
||||||
"jobs": ""
|
"jobs": ""
|
||||||
|
|||||||
@@ -1160,7 +1160,8 @@
|
|||||||
"submit": "",
|
"submit": "",
|
||||||
"tryagain": "",
|
"tryagain": "",
|
||||||
"view": "",
|
"view": "",
|
||||||
"viewreleasenotes": ""
|
"viewreleasenotes": "",
|
||||||
|
"remove_alert": ""
|
||||||
},
|
},
|
||||||
"errors": {
|
"errors": {
|
||||||
"fcm": "",
|
"fcm": "",
|
||||||
@@ -2757,7 +2758,9 @@
|
|||||||
"total_lab_on_board": "",
|
"total_lab_on_board": "",
|
||||||
"total_lar_on_board": "",
|
"total_lar_on_board": "",
|
||||||
"total_amount_on_board": "",
|
"total_amount_on_board": "",
|
||||||
"total_jobs_on_board": ""
|
"total_jobs_on_board": "",
|
||||||
|
"tasks_in_production": "",
|
||||||
|
"tasks_on_board": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"actions": {
|
"actions": {
|
||||||
@@ -2792,6 +2795,7 @@
|
|||||||
"model_info": "",
|
"model_info": "",
|
||||||
"actual_in": "",
|
"actual_in": "",
|
||||||
"alert": "",
|
"alert": "",
|
||||||
|
"tasks": "",
|
||||||
"alertoff": "",
|
"alertoff": "",
|
||||||
"alerton": "",
|
"alerton": "",
|
||||||
"ats": "",
|
"ats": "",
|
||||||
@@ -2829,7 +2833,8 @@
|
|||||||
"sublets": "",
|
"sublets": "",
|
||||||
"totalhours": "",
|
"totalhours": "",
|
||||||
"touchtime": "",
|
"touchtime": "",
|
||||||
"viewname": ""
|
"viewname": "",
|
||||||
|
"alerts": ""
|
||||||
},
|
},
|
||||||
"successes": {
|
"successes": {
|
||||||
"removed": ""
|
"removed": ""
|
||||||
@@ -2845,6 +2850,9 @@
|
|||||||
"total_lar_on_board": "",
|
"total_lar_on_board": "",
|
||||||
"total_amount_on_board": "",
|
"total_amount_on_board": "",
|
||||||
"total_jobs_on_board": "",
|
"total_jobs_on_board": "",
|
||||||
|
"tasks_in_production": "",
|
||||||
|
"tasks_on_board": "",
|
||||||
|
"tasks": "",
|
||||||
"hours": "",
|
"hours": "",
|
||||||
"currency_symbol": "",
|
"currency_symbol": "",
|
||||||
"jobs": ""
|
"jobs": ""
|
||||||
|
|||||||
@@ -1,36 +0,0 @@
|
|||||||
export const BETA_KEY = "betaSwitchImex";
|
|
||||||
|
|
||||||
export const checkBeta = () => {
|
|
||||||
const cookie = document.cookie.split("; ").find((row) => row.startsWith(BETA_KEY));
|
|
||||||
return cookie ? cookie.split("=")[1] === "true" : false;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const setBeta = (value) => {
|
|
||||||
const domain = window.location.hostname.split(".").slice(-2).join(".");
|
|
||||||
document.cookie = `${BETA_KEY}=${value}; path=/; domain=.${domain}`;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const handleBeta = () => {
|
|
||||||
// If the current host name does not start with beta or test, then we don't need to do anything.
|
|
||||||
if (window.location.hostname.startsWith("localhost")) {
|
|
||||||
console.log("Not on beta or test, so no need to handle beta.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const isBeta = checkBeta();
|
|
||||||
|
|
||||||
const currentHostName = window.location.hostname;
|
|
||||||
|
|
||||||
// Beta is enabled, but the current host name does start with beta.
|
|
||||||
if (isBeta && !currentHostName.startsWith("beta")) {
|
|
||||||
const href = `${window.location.protocol}//beta.${currentHostName}${window.location.pathname}${window.location.search}${window.location.hash}`;
|
|
||||||
window.location.replace(href);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Beta is not enabled, but the current host name does start with beta.
|
|
||||||
else if (!isBeta && currentHostName.startsWith("beta")) {
|
|
||||||
const href = `${window.location.protocol}//${currentHostName.replace("beta.", "")}${window.location.pathname}${window.location.search}${window.location.hash}`;
|
|
||||||
window.location.replace(href);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
export default handleBeta;
|
|
||||||
@@ -11,26 +11,37 @@ export const setBeta = (value) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const handleBeta = () => {
|
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")) {
|
if (window.location.hostname.startsWith("localhost")) {
|
||||||
console.log("Not on beta or test, so no need to handle beta.");
|
console.log("Not on beta or test, so no need to handle beta.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const isBeta = checkBeta();
|
const isBeta = checkBeta();
|
||||||
|
|
||||||
const currentHostName = window.location.hostname;
|
const currentHostName = window.location.hostname;
|
||||||
|
|
||||||
// Beta is enabled, but the current host name does start with beta.
|
// Determine if the host name starts with "beta" or "www.beta"
|
||||||
if (isBeta && !currentHostName.startsWith("beta")) {
|
const isBetaHost = currentHostName.startsWith("beta.");
|
||||||
const href = `${window.location.protocol}//beta.${currentHostName}${window.location.pathname}${window.location.search}${window.location.hash}`;
|
const isBetaHostWithWWW = currentHostName.startsWith("www.beta.");
|
||||||
window.location.replace(href);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Beta is not enabled, but the current host name does start with beta.
|
if (isBeta) {
|
||||||
else if (!isBeta && currentHostName.startsWith("beta")) {
|
// If beta is on and we are not on a beta domain, redirect to the beta version
|
||||||
const href = `${window.location.protocol}//${currentHostName.replace("beta.", "")}${window.location.pathname}${window.location.search}${window.location.hash}`;
|
if (!isBetaHost && !isBetaHostWithWWW) {
|
||||||
window.location.replace(href);
|
const newHostName = currentHostName.startsWith("www.")
|
||||||
|
? `www.beta.${currentHostName.replace(/^www\./, "")}`
|
||||||
|
: `beta.${currentHostName}`;
|
||||||
|
const href = `${window.location.protocol}//${newHostName}${window.location.pathname}${window.location.search}${window.location.hash}`;
|
||||||
|
window.location.replace(href);
|
||||||
|
}
|
||||||
|
// Otherwise, if beta is on and we're already on a beta domain, stay there
|
||||||
|
} else {
|
||||||
|
// If beta is off and we are on a beta domain, redirect to the non-beta version
|
||||||
|
if (isBetaHost || isBetaHostWithWWW) {
|
||||||
|
const newHostName = currentHostName.replace(/^www\.beta\./, "www.").replace(/^beta\./, "");
|
||||||
|
const href = `${window.location.protocol}//${newHostName}${window.location.pathname}${window.location.search}${window.location.hash}`;
|
||||||
|
window.location.replace(href);
|
||||||
|
}
|
||||||
|
// Otherwise, if beta is off and we're not on a beta domain, stay there
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export default handleBeta;
|
export default handleBeta;
|
||||||
|
|||||||
@@ -6,8 +6,6 @@ import * as url from "url";
|
|||||||
import { defineConfig } from "vite";
|
import { defineConfig } from "vite";
|
||||||
import { ViteEjsPlugin } from "vite-plugin-ejs";
|
import { ViteEjsPlugin } from "vite-plugin-ejs";
|
||||||
import eslint from "vite-plugin-eslint";
|
import eslint from "vite-plugin-eslint";
|
||||||
|
|
||||||
//import CompressionPlugin from 'vite-plugin-compression';
|
|
||||||
import { VitePWA } from "vite-plugin-pwa";
|
import { VitePWA } from "vite-plugin-pwa";
|
||||||
import InstanceRenderManager from "./src/utils/instanceRenderMgr";
|
import InstanceRenderManager from "./src/utils/instanceRenderMgr";
|
||||||
|
|
||||||
@@ -16,7 +14,8 @@ process.env.VITE_APP_GIT_SHA_DATE = new Date().toLocaleString("en-US", {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const WRONG_CODE = `import { bpfrpt_proptype_WindowScroller } from "../WindowScroller.js";`;
|
const WRONG_CODE = `import { bpfrpt_proptype_WindowScroller } from "../WindowScroller.js";`;
|
||||||
function reactVirtualized() {
|
|
||||||
|
function reactVirtualizedFix() {
|
||||||
return {
|
return {
|
||||||
name: "flat:react-virtualized",
|
name: "flat:react-virtualized",
|
||||||
configResolved: async () => {
|
configResolved: async () => {
|
||||||
@@ -37,10 +36,7 @@ function reactVirtualized() {
|
|||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
base: "/",
|
base: "/",
|
||||||
plugins: [
|
plugins: [
|
||||||
ViteEjsPlugin((viteConfig) => {
|
ViteEjsPlugin((viteConfig) => ({ env: viteConfig.env })),
|
||||||
// viteConfig is the current Vite resolved config
|
|
||||||
return { env: viteConfig.env };
|
|
||||||
}),
|
|
||||||
VitePWA({
|
VitePWA({
|
||||||
injectRegister: "auto",
|
injectRegister: "auto",
|
||||||
registerType: "prompt",
|
registerType: "prompt",
|
||||||
@@ -60,7 +56,6 @@ export default defineConfig({
|
|||||||
description: "The ultimate bodyshop management system.",
|
description: "The ultimate bodyshop management system.",
|
||||||
icons: [
|
icons: [
|
||||||
{
|
{
|
||||||
//TODO:AIO Ensure that these are correct for Rome and IO.
|
|
||||||
src: InstanceRenderManager({
|
src: InstanceRenderManager({
|
||||||
instance: process.env.VITE_APP_INSTANCE,
|
instance: process.env.VITE_APP_INSTANCE,
|
||||||
imex: "favicon.png",
|
imex: "favicon.png",
|
||||||
@@ -101,7 +96,7 @@ export default defineConfig({
|
|||||||
gcm_sender_id: "103953800507"
|
gcm_sender_id: "103953800507"
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
reactVirtualized(),
|
reactVirtualizedFix(),
|
||||||
react(),
|
react(),
|
||||||
eslint()
|
eslint()
|
||||||
// CompressionPlugin(), //Cloudfront already compresses assets, so not needed.
|
// CompressionPlugin(), //Cloudfront already compresses assets, so not needed.
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
-- Could not auto-generate a down migration.
|
||||||
|
-- Please write an appropriate down migration for the SQL below:
|
||||||
|
-- UPDATE "public"."masterdata"
|
||||||
|
-- SET value = jsonb_set(
|
||||||
|
-- value::jsonb,
|
||||||
|
-- '{OP20}',
|
||||||
|
-- '{"desc": "REMOVE AND REINSTALL", "opcode": "OP20", "partcode": "PAE"}'::jsonb,
|
||||||
|
-- true
|
||||||
|
-- );
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
UPDATE "public"."masterdata"
|
||||||
|
SET value = jsonb_set(
|
||||||
|
value::jsonb,
|
||||||
|
'{OP20}',
|
||||||
|
'{"desc": "REMOVE AND REINSTALL", "opcode": "OP20", "partcode": "PAE"}'::jsonb,
|
||||||
|
true
|
||||||
|
);
|
||||||
194
package-lock.json
generated
194
package-lock.json
generated
@@ -9,12 +9,12 @@
|
|||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"license": "UNLICENSED",
|
"license": "UNLICENSED",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@aws-sdk/client-secrets-manager": "^3.624.0",
|
"@aws-sdk/client-secrets-manager": "^3.632.0",
|
||||||
"@aws-sdk/client-ses": "^3.624.0",
|
"@aws-sdk/client-ses": "^3.632.0",
|
||||||
"@aws-sdk/credential-provider-node": "^3.624.0",
|
"@aws-sdk/credential-provider-node": "^3.632.0",
|
||||||
"@opensearch-project/opensearch": "^2.11.0",
|
"@opensearch-project/opensearch": "^2.11.0",
|
||||||
"aws4": "^1.13.1",
|
"aws4": "^1.13.1",
|
||||||
"axios": "^1.7.3",
|
"axios": "^1.7.4",
|
||||||
"better-queue": "^3.8.12",
|
"better-queue": "^3.8.12",
|
||||||
"bluebird": "^3.7.2",
|
"bluebird": "^3.7.2",
|
||||||
"body-parser": "^1.20.2",
|
"body-parser": "^1.20.2",
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
"dinero.js": "^1.9.1",
|
"dinero.js": "^1.9.1",
|
||||||
"dotenv": "^16.4.5",
|
"dotenv": "^16.4.5",
|
||||||
"express": "^4.19.2",
|
"express": "^4.19.2",
|
||||||
"firebase-admin": "^12.3.0",
|
"firebase-admin": "^12.3.1",
|
||||||
"graphql": "^16.9.0",
|
"graphql": "^16.9.0",
|
||||||
"graphql-request": "^6.1.0",
|
"graphql-request": "^6.1.0",
|
||||||
"graylog2": "^0.2.1",
|
"graylog2": "^0.2.1",
|
||||||
@@ -42,12 +42,12 @@
|
|||||||
"node-mailjet": "^6.0.5",
|
"node-mailjet": "^6.0.5",
|
||||||
"node-persist": "^4.0.3",
|
"node-persist": "^4.0.3",
|
||||||
"nodemailer": "^6.9.14",
|
"nodemailer": "^6.9.14",
|
||||||
"phone": "^3.1.49",
|
"phone": "^3.1.50",
|
||||||
"recursive-diff": "^1.0.9",
|
"recursive-diff": "^1.0.9",
|
||||||
"rimraf": "^6.0.1",
|
"rimraf": "^6.0.1",
|
||||||
"soap": "^1.1.1",
|
"soap": "^1.1.1",
|
||||||
"socket.io": "^4.7.5",
|
"socket.io": "^4.7.5",
|
||||||
"ssh2-sftp-client": "^11.0.0",
|
"ssh2-sftp-client": "^10.0.3",
|
||||||
"twilio": "^4.23.0",
|
"twilio": "^4.23.0",
|
||||||
"uuid": "^10.0.0",
|
"uuid": "^10.0.0",
|
||||||
"xml2js": "^0.6.2",
|
"xml2js": "^0.6.2",
|
||||||
@@ -60,8 +60,8 @@
|
|||||||
"source-map-explorer": "^2.5.2"
|
"source-map-explorer": "^2.5.2"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=20.15.0",
|
"node": ">=18.0.0",
|
||||||
"npm": ">=10.7.0"
|
"npm": ">=8.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@aws-crypto/sha256-browser": {
|
"node_modules/@aws-crypto/sha256-browser": {
|
||||||
@@ -180,24 +180,24 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@aws-sdk/client-secrets-manager": {
|
"node_modules/@aws-sdk/client-secrets-manager": {
|
||||||
"version": "3.624.0",
|
"version": "3.632.0",
|
||||||
"resolved": "https://registry.npmjs.org/@aws-sdk/client-secrets-manager/-/client-secrets-manager-3.624.0.tgz",
|
"resolved": "https://registry.npmjs.org/@aws-sdk/client-secrets-manager/-/client-secrets-manager-3.632.0.tgz",
|
||||||
"integrity": "sha512-sW4eT+OVhfMTTB9Ke5tAz8/1gZmJ4G40z9Pvm4fJYRopIMIkHSeSQKTo5urX0APYZ3fdKs2Hxo22MKIZAO4kmw==",
|
"integrity": "sha512-WsQhPHHK1yPfALcP1B7nBSGDzky6vFTUEXnUdfzb5Xy2cT+JTBTS6ChtQGqqOuGHDP/3t/9soqZ+L6rUCYBb/Q==",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@aws-crypto/sha256-browser": "5.2.0",
|
"@aws-crypto/sha256-browser": "5.2.0",
|
||||||
"@aws-crypto/sha256-js": "5.2.0",
|
"@aws-crypto/sha256-js": "5.2.0",
|
||||||
"@aws-sdk/client-sso-oidc": "3.624.0",
|
"@aws-sdk/client-sso-oidc": "3.632.0",
|
||||||
"@aws-sdk/client-sts": "3.624.0",
|
"@aws-sdk/client-sts": "3.632.0",
|
||||||
"@aws-sdk/core": "3.624.0",
|
"@aws-sdk/core": "3.629.0",
|
||||||
"@aws-sdk/credential-provider-node": "3.624.0",
|
"@aws-sdk/credential-provider-node": "3.632.0",
|
||||||
"@aws-sdk/middleware-host-header": "3.620.0",
|
"@aws-sdk/middleware-host-header": "3.620.0",
|
||||||
"@aws-sdk/middleware-logger": "3.609.0",
|
"@aws-sdk/middleware-logger": "3.609.0",
|
||||||
"@aws-sdk/middleware-recursion-detection": "3.620.0",
|
"@aws-sdk/middleware-recursion-detection": "3.620.0",
|
||||||
"@aws-sdk/middleware-user-agent": "3.620.0",
|
"@aws-sdk/middleware-user-agent": "3.632.0",
|
||||||
"@aws-sdk/region-config-resolver": "3.614.0",
|
"@aws-sdk/region-config-resolver": "3.614.0",
|
||||||
"@aws-sdk/types": "3.609.0",
|
"@aws-sdk/types": "3.609.0",
|
||||||
"@aws-sdk/util-endpoints": "3.614.0",
|
"@aws-sdk/util-endpoints": "3.632.0",
|
||||||
"@aws-sdk/util-user-agent-browser": "3.609.0",
|
"@aws-sdk/util-user-agent-browser": "3.609.0",
|
||||||
"@aws-sdk/util-user-agent-node": "3.614.0",
|
"@aws-sdk/util-user-agent-node": "3.614.0",
|
||||||
"@smithy/config-resolver": "^3.0.5",
|
"@smithy/config-resolver": "^3.0.5",
|
||||||
@@ -245,24 +245,24 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@aws-sdk/client-ses": {
|
"node_modules/@aws-sdk/client-ses": {
|
||||||
"version": "3.624.0",
|
"version": "3.632.0",
|
||||||
"resolved": "https://registry.npmjs.org/@aws-sdk/client-ses/-/client-ses-3.624.0.tgz",
|
"resolved": "https://registry.npmjs.org/@aws-sdk/client-ses/-/client-ses-3.632.0.tgz",
|
||||||
"integrity": "sha512-CIi5tbQQ3wI4MBYUNZDti0xkj5SonZ+l/Bc4eBxqJK61tQB45T68SSigdMBr9fICTQ067WMYvvOtTvq9PqV4jA==",
|
"integrity": "sha512-hi01MPJF55LEK7NB1LZrqUV7b5GyjH08EToYuekFvQf9aNoR5mqWuMEDQ/dFAowYhUa2KqCdn67HnPn0ySQxHg==",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@aws-crypto/sha256-browser": "5.2.0",
|
"@aws-crypto/sha256-browser": "5.2.0",
|
||||||
"@aws-crypto/sha256-js": "5.2.0",
|
"@aws-crypto/sha256-js": "5.2.0",
|
||||||
"@aws-sdk/client-sso-oidc": "3.624.0",
|
"@aws-sdk/client-sso-oidc": "3.632.0",
|
||||||
"@aws-sdk/client-sts": "3.624.0",
|
"@aws-sdk/client-sts": "3.632.0",
|
||||||
"@aws-sdk/core": "3.624.0",
|
"@aws-sdk/core": "3.629.0",
|
||||||
"@aws-sdk/credential-provider-node": "3.624.0",
|
"@aws-sdk/credential-provider-node": "3.632.0",
|
||||||
"@aws-sdk/middleware-host-header": "3.620.0",
|
"@aws-sdk/middleware-host-header": "3.620.0",
|
||||||
"@aws-sdk/middleware-logger": "3.609.0",
|
"@aws-sdk/middleware-logger": "3.609.0",
|
||||||
"@aws-sdk/middleware-recursion-detection": "3.620.0",
|
"@aws-sdk/middleware-recursion-detection": "3.620.0",
|
||||||
"@aws-sdk/middleware-user-agent": "3.620.0",
|
"@aws-sdk/middleware-user-agent": "3.632.0",
|
||||||
"@aws-sdk/region-config-resolver": "3.614.0",
|
"@aws-sdk/region-config-resolver": "3.614.0",
|
||||||
"@aws-sdk/types": "3.609.0",
|
"@aws-sdk/types": "3.609.0",
|
||||||
"@aws-sdk/util-endpoints": "3.614.0",
|
"@aws-sdk/util-endpoints": "3.632.0",
|
||||||
"@aws-sdk/util-user-agent-browser": "3.609.0",
|
"@aws-sdk/util-user-agent-browser": "3.609.0",
|
||||||
"@aws-sdk/util-user-agent-node": "3.614.0",
|
"@aws-sdk/util-user-agent-node": "3.614.0",
|
||||||
"@smithy/config-resolver": "^3.0.5",
|
"@smithy/config-resolver": "^3.0.5",
|
||||||
@@ -298,21 +298,21 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@aws-sdk/client-sso": {
|
"node_modules/@aws-sdk/client-sso": {
|
||||||
"version": "3.624.0",
|
"version": "3.632.0",
|
||||||
"resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.624.0.tgz",
|
"resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.632.0.tgz",
|
||||||
"integrity": "sha512-EX6EF+rJzMPC5dcdsu40xSi2To7GSvdGQNIpe97pD9WvZwM9tRNQnNM4T6HA4gjV1L6Jwk8rBlG/CnveXtLEMw==",
|
"integrity": "sha512-iYWHiKBz44m3chCFvtvHnvCpL2rALzyr1e6tOZV3dLlOKtQtDUlPy6OtnXDu4y+wyJCniy8ivG3+LAe4klzn1Q==",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@aws-crypto/sha256-browser": "5.2.0",
|
"@aws-crypto/sha256-browser": "5.2.0",
|
||||||
"@aws-crypto/sha256-js": "5.2.0",
|
"@aws-crypto/sha256-js": "5.2.0",
|
||||||
"@aws-sdk/core": "3.624.0",
|
"@aws-sdk/core": "3.629.0",
|
||||||
"@aws-sdk/middleware-host-header": "3.620.0",
|
"@aws-sdk/middleware-host-header": "3.620.0",
|
||||||
"@aws-sdk/middleware-logger": "3.609.0",
|
"@aws-sdk/middleware-logger": "3.609.0",
|
||||||
"@aws-sdk/middleware-recursion-detection": "3.620.0",
|
"@aws-sdk/middleware-recursion-detection": "3.620.0",
|
||||||
"@aws-sdk/middleware-user-agent": "3.620.0",
|
"@aws-sdk/middleware-user-agent": "3.632.0",
|
||||||
"@aws-sdk/region-config-resolver": "3.614.0",
|
"@aws-sdk/region-config-resolver": "3.614.0",
|
||||||
"@aws-sdk/types": "3.609.0",
|
"@aws-sdk/types": "3.609.0",
|
||||||
"@aws-sdk/util-endpoints": "3.614.0",
|
"@aws-sdk/util-endpoints": "3.632.0",
|
||||||
"@aws-sdk/util-user-agent-browser": "3.609.0",
|
"@aws-sdk/util-user-agent-browser": "3.609.0",
|
||||||
"@aws-sdk/util-user-agent-node": "3.614.0",
|
"@aws-sdk/util-user-agent-node": "3.614.0",
|
||||||
"@smithy/config-resolver": "^3.0.5",
|
"@smithy/config-resolver": "^3.0.5",
|
||||||
@@ -347,22 +347,22 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@aws-sdk/client-sso-oidc": {
|
"node_modules/@aws-sdk/client-sso-oidc": {
|
||||||
"version": "3.624.0",
|
"version": "3.632.0",
|
||||||
"resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.624.0.tgz",
|
"resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.632.0.tgz",
|
||||||
"integrity": "sha512-Ki2uKYJKKtfHxxZsiMTOvJoVRP6b2pZ1u3rcUb2m/nVgBPUfLdl8ZkGpqE29I+t5/QaS/sEdbn6cgMUZwl+3Dg==",
|
"integrity": "sha512-Oh1fIWaoZluihOCb/zDEpRTi+6an82fgJz7fyRBugyLhEtDjmvpCQ3oKjzaOhoN+4EvXAm1ZS/ZgpvXBlIRTgw==",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@aws-crypto/sha256-browser": "5.2.0",
|
"@aws-crypto/sha256-browser": "5.2.0",
|
||||||
"@aws-crypto/sha256-js": "5.2.0",
|
"@aws-crypto/sha256-js": "5.2.0",
|
||||||
"@aws-sdk/core": "3.624.0",
|
"@aws-sdk/core": "3.629.0",
|
||||||
"@aws-sdk/credential-provider-node": "3.624.0",
|
"@aws-sdk/credential-provider-node": "3.632.0",
|
||||||
"@aws-sdk/middleware-host-header": "3.620.0",
|
"@aws-sdk/middleware-host-header": "3.620.0",
|
||||||
"@aws-sdk/middleware-logger": "3.609.0",
|
"@aws-sdk/middleware-logger": "3.609.0",
|
||||||
"@aws-sdk/middleware-recursion-detection": "3.620.0",
|
"@aws-sdk/middleware-recursion-detection": "3.620.0",
|
||||||
"@aws-sdk/middleware-user-agent": "3.620.0",
|
"@aws-sdk/middleware-user-agent": "3.632.0",
|
||||||
"@aws-sdk/region-config-resolver": "3.614.0",
|
"@aws-sdk/region-config-resolver": "3.614.0",
|
||||||
"@aws-sdk/types": "3.609.0",
|
"@aws-sdk/types": "3.609.0",
|
||||||
"@aws-sdk/util-endpoints": "3.614.0",
|
"@aws-sdk/util-endpoints": "3.632.0",
|
||||||
"@aws-sdk/util-user-agent-browser": "3.609.0",
|
"@aws-sdk/util-user-agent-browser": "3.609.0",
|
||||||
"@aws-sdk/util-user-agent-node": "3.614.0",
|
"@aws-sdk/util-user-agent-node": "3.614.0",
|
||||||
"@smithy/config-resolver": "^3.0.5",
|
"@smithy/config-resolver": "^3.0.5",
|
||||||
@@ -396,27 +396,27 @@
|
|||||||
"node": ">=16.0.0"
|
"node": ">=16.0.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@aws-sdk/client-sts": "^3.624.0"
|
"@aws-sdk/client-sts": "^3.632.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@aws-sdk/client-sts": {
|
"node_modules/@aws-sdk/client-sts": {
|
||||||
"version": "3.624.0",
|
"version": "3.632.0",
|
||||||
"resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.624.0.tgz",
|
"resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.632.0.tgz",
|
||||||
"integrity": "sha512-k36fLZCb2nfoV/DKK3jbRgO/Yf7/R80pgYfMiotkGjnZwDmRvNN08z4l06L9C+CieazzkgRxNUzyppsYcYsQaw==",
|
"integrity": "sha512-Ss5cBH09icpTvT+jtGGuQlRdwtO7RyE9BF4ZV/CEPATdd9whtJt4Qxdya8BUnkWR7h5HHTrQHqai3YVYjku41A==",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@aws-crypto/sha256-browser": "5.2.0",
|
"@aws-crypto/sha256-browser": "5.2.0",
|
||||||
"@aws-crypto/sha256-js": "5.2.0",
|
"@aws-crypto/sha256-js": "5.2.0",
|
||||||
"@aws-sdk/client-sso-oidc": "3.624.0",
|
"@aws-sdk/client-sso-oidc": "3.632.0",
|
||||||
"@aws-sdk/core": "3.624.0",
|
"@aws-sdk/core": "3.629.0",
|
||||||
"@aws-sdk/credential-provider-node": "3.624.0",
|
"@aws-sdk/credential-provider-node": "3.632.0",
|
||||||
"@aws-sdk/middleware-host-header": "3.620.0",
|
"@aws-sdk/middleware-host-header": "3.620.0",
|
||||||
"@aws-sdk/middleware-logger": "3.609.0",
|
"@aws-sdk/middleware-logger": "3.609.0",
|
||||||
"@aws-sdk/middleware-recursion-detection": "3.620.0",
|
"@aws-sdk/middleware-recursion-detection": "3.620.0",
|
||||||
"@aws-sdk/middleware-user-agent": "3.620.0",
|
"@aws-sdk/middleware-user-agent": "3.632.0",
|
||||||
"@aws-sdk/region-config-resolver": "3.614.0",
|
"@aws-sdk/region-config-resolver": "3.614.0",
|
||||||
"@aws-sdk/types": "3.609.0",
|
"@aws-sdk/types": "3.609.0",
|
||||||
"@aws-sdk/util-endpoints": "3.614.0",
|
"@aws-sdk/util-endpoints": "3.632.0",
|
||||||
"@aws-sdk/util-user-agent-browser": "3.609.0",
|
"@aws-sdk/util-user-agent-browser": "3.609.0",
|
||||||
"@aws-sdk/util-user-agent-node": "3.614.0",
|
"@aws-sdk/util-user-agent-node": "3.614.0",
|
||||||
"@smithy/config-resolver": "^3.0.5",
|
"@smithy/config-resolver": "^3.0.5",
|
||||||
@@ -451,13 +451,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@aws-sdk/core": {
|
"node_modules/@aws-sdk/core": {
|
||||||
"version": "3.624.0",
|
"version": "3.629.0",
|
||||||
"resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.624.0.tgz",
|
"resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.629.0.tgz",
|
||||||
"integrity": "sha512-WyFmPbhRIvtWi7hBp8uSFy+iPpj8ccNV/eX86hwF4irMjfc/FtsGVIAeBXxXM/vGCjkdfEzOnl+tJ2XACD4OXg==",
|
"integrity": "sha512-+/ShPU/tyIBM3oY1cnjgNA/tFyHtlWq+wXF9xEKRv19NOpYbWQ+xzNwVjGq8vR07cCRqy/sDQLWPhxjtuV/FiQ==",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@smithy/core": "^2.3.2",
|
"@smithy/core": "^2.3.2",
|
||||||
"@smithy/node-config-provider": "^3.1.4",
|
"@smithy/node-config-provider": "^3.1.4",
|
||||||
|
"@smithy/property-provider": "^3.1.3",
|
||||||
"@smithy/protocol-http": "^4.1.0",
|
"@smithy/protocol-http": "^4.1.0",
|
||||||
"@smithy/signature-v4": "^4.1.0",
|
"@smithy/signature-v4": "^4.1.0",
|
||||||
"@smithy/smithy-client": "^3.1.12",
|
"@smithy/smithy-client": "^3.1.12",
|
||||||
@@ -506,15 +507,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@aws-sdk/credential-provider-ini": {
|
"node_modules/@aws-sdk/credential-provider-ini": {
|
||||||
"version": "3.624.0",
|
"version": "3.632.0",
|
||||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.624.0.tgz",
|
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.632.0.tgz",
|
||||||
"integrity": "sha512-mMoNIy7MO2WTBbdqMyLpbt6SZpthE6e0GkRYpsd0yozPt0RZopcBhEh+HG1U9Y1PVODo+jcMk353vAi61CfnhQ==",
|
"integrity": "sha512-m6epoW41xa1ajU5OiHcmQHoGVtrbXBaRBOUhlCLZmcaqMLYsboM4iD/WZP8aatKEON5tTnVXh/4StV8D/+wemw==",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@aws-sdk/credential-provider-env": "3.620.1",
|
"@aws-sdk/credential-provider-env": "3.620.1",
|
||||||
"@aws-sdk/credential-provider-http": "3.622.0",
|
"@aws-sdk/credential-provider-http": "3.622.0",
|
||||||
"@aws-sdk/credential-provider-process": "3.620.1",
|
"@aws-sdk/credential-provider-process": "3.620.1",
|
||||||
"@aws-sdk/credential-provider-sso": "3.624.0",
|
"@aws-sdk/credential-provider-sso": "3.632.0",
|
||||||
"@aws-sdk/credential-provider-web-identity": "3.621.0",
|
"@aws-sdk/credential-provider-web-identity": "3.621.0",
|
||||||
"@aws-sdk/types": "3.609.0",
|
"@aws-sdk/types": "3.609.0",
|
||||||
"@smithy/credential-provider-imds": "^3.2.0",
|
"@smithy/credential-provider-imds": "^3.2.0",
|
||||||
@@ -527,20 +528,20 @@
|
|||||||
"node": ">=16.0.0"
|
"node": ">=16.0.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@aws-sdk/client-sts": "^3.624.0"
|
"@aws-sdk/client-sts": "^3.632.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@aws-sdk/credential-provider-node": {
|
"node_modules/@aws-sdk/credential-provider-node": {
|
||||||
"version": "3.624.0",
|
"version": "3.632.0",
|
||||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.624.0.tgz",
|
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.632.0.tgz",
|
||||||
"integrity": "sha512-vYyGK7oNpd81BdbH5IlmQ6zfaQqU+rPwsKTDDBeLRjshtrGXOEpfoahVpG9PX0ibu32IOWp4ZyXBNyVrnvcMOw==",
|
"integrity": "sha512-cL8fuJWm/xQBO4XJPkeuZzl3XinIn9EExWgzpG48NRMKR5us1RI/ucv7xFbBBaG+r/sDR2HpYBIA3lVIpm1H3Q==",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@aws-sdk/credential-provider-env": "3.620.1",
|
"@aws-sdk/credential-provider-env": "3.620.1",
|
||||||
"@aws-sdk/credential-provider-http": "3.622.0",
|
"@aws-sdk/credential-provider-http": "3.622.0",
|
||||||
"@aws-sdk/credential-provider-ini": "3.624.0",
|
"@aws-sdk/credential-provider-ini": "3.632.0",
|
||||||
"@aws-sdk/credential-provider-process": "3.620.1",
|
"@aws-sdk/credential-provider-process": "3.620.1",
|
||||||
"@aws-sdk/credential-provider-sso": "3.624.0",
|
"@aws-sdk/credential-provider-sso": "3.632.0",
|
||||||
"@aws-sdk/credential-provider-web-identity": "3.621.0",
|
"@aws-sdk/credential-provider-web-identity": "3.621.0",
|
||||||
"@aws-sdk/types": "3.609.0",
|
"@aws-sdk/types": "3.609.0",
|
||||||
"@smithy/credential-provider-imds": "^3.2.0",
|
"@smithy/credential-provider-imds": "^3.2.0",
|
||||||
@@ -570,12 +571,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@aws-sdk/credential-provider-sso": {
|
"node_modules/@aws-sdk/credential-provider-sso": {
|
||||||
"version": "3.624.0",
|
"version": "3.632.0",
|
||||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.624.0.tgz",
|
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.632.0.tgz",
|
||||||
"integrity": "sha512-A02bayIjU9APEPKr3HudrFHEx0WfghoSPsPopckDkW7VBqO4wizzcxr75Q9A3vNX+cwg0wCN6UitTNe6pVlRaQ==",
|
"integrity": "sha512-P/4wB6j7ym5QCPTL2xlMfvf2NcXSh+z0jmsZP4WW/tVwab4hvgabPPbLeEZDSWZ0BpgtxKGvRq0GSHuGeirQbA==",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@aws-sdk/client-sso": "3.624.0",
|
"@aws-sdk/client-sso": "3.632.0",
|
||||||
"@aws-sdk/token-providers": "3.614.0",
|
"@aws-sdk/token-providers": "3.614.0",
|
||||||
"@aws-sdk/types": "3.609.0",
|
"@aws-sdk/types": "3.609.0",
|
||||||
"@smithy/property-provider": "^3.1.3",
|
"@smithy/property-provider": "^3.1.3",
|
||||||
@@ -649,13 +650,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@aws-sdk/middleware-user-agent": {
|
"node_modules/@aws-sdk/middleware-user-agent": {
|
||||||
"version": "3.620.0",
|
"version": "3.632.0",
|
||||||
"resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.620.0.tgz",
|
"resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.632.0.tgz",
|
||||||
"integrity": "sha512-bvS6etn+KsuL32ubY5D3xNof1qkenpbJXf/ugGXbg0n98DvDFQ/F+SMLxHgbnER5dsKYchNnhmtI6/FC3HFu/A==",
|
"integrity": "sha512-yY/sFsHKwG9yzSf/DTclqWJaGPI2gPBJDCGBujSqTG1zlS7Ot4fqi91DZ6088BFWzbOorDzJFcAhAEFzc6LuQg==",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@aws-sdk/types": "3.609.0",
|
"@aws-sdk/types": "3.609.0",
|
||||||
"@aws-sdk/util-endpoints": "3.614.0",
|
"@aws-sdk/util-endpoints": "3.632.0",
|
||||||
"@smithy/protocol-http": "^4.1.0",
|
"@smithy/protocol-http": "^4.1.0",
|
||||||
"@smithy/types": "^3.3.0",
|
"@smithy/types": "^3.3.0",
|
||||||
"tslib": "^2.6.2"
|
"tslib": "^2.6.2"
|
||||||
@@ -712,9 +713,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@aws-sdk/util-endpoints": {
|
"node_modules/@aws-sdk/util-endpoints": {
|
||||||
"version": "3.614.0",
|
"version": "3.632.0",
|
||||||
"resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.614.0.tgz",
|
"resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.632.0.tgz",
|
||||||
"integrity": "sha512-wK2cdrXHH4oz4IomV/yrGkftU9A+ITB6nFL+rxxyO78is2ifHJpFdV4aqk4LSkXYPi6CXWNru/Dqc7yiKXgJPw==",
|
"integrity": "sha512-LlYMU8pAbcEQphOpE6xaNLJ8kPGhklZZTVzZVpVW477NaaGgoGTMYNXTABYHcxeF5E2lLrxql9OmVpvr8GWN8Q==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@aws-sdk/types": "3.609.0",
|
"@aws-sdk/types": "3.609.0",
|
||||||
"@smithy/types": "^3.3.0",
|
"@smithy/types": "^3.3.0",
|
||||||
@@ -2425,11 +2427,12 @@
|
|||||||
"integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w=="
|
"integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w=="
|
||||||
},
|
},
|
||||||
"node_modules/@types/node": {
|
"node_modules/@types/node": {
|
||||||
"version": "20.11.7",
|
"version": "22.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.7.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.3.0.tgz",
|
||||||
"integrity": "sha512-GPmeN1C3XAyV5uybAf4cMLWT9fDWcmQhZVtMFu7OR32WjrqGG+Wnk2V1d0bmtUyE/Zy1QJ9BxyiTih9z8Oks8A==",
|
"integrity": "sha512-nrWpWVaDZuaVc5X84xJ0vNrLvomM205oQyLsRt7OHNZbSHslcWsvgFR7O7hire2ZonjLrWBbedmotmIlJDVd6g==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"undici-types": "~5.26.4"
|
"undici-types": "~6.18.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@types/qs": {
|
"node_modules/@types/qs": {
|
||||||
@@ -2693,9 +2696,9 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/axios": {
|
"node_modules/axios": {
|
||||||
"version": "1.7.3",
|
"version": "1.7.4",
|
||||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.7.3.tgz",
|
"resolved": "https://registry.npmjs.org/axios/-/axios-1.7.4.tgz",
|
||||||
"integrity": "sha512-Ar7ND9pU99eJ9GpoGQKhKf58GpUOgnzuaB7ueNQ5BMi0p+LZ5oaEnfF999fAArcTIBwXTCHAmGcHOZJaWPq9Nw==",
|
"integrity": "sha512-DukmaFRnY6AzAALSH4J2M3k6PkaC+MfaAGdEERRWcC9q3/TWQwLpHR8ZRLKTdQ3aBDL64EdluRDjJqKw+BPZEw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"follow-redirects": "^1.15.6",
|
"follow-redirects": "^1.15.6",
|
||||||
@@ -4105,15 +4108,15 @@
|
|||||||
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
|
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
|
||||||
},
|
},
|
||||||
"node_modules/firebase-admin": {
|
"node_modules/firebase-admin": {
|
||||||
"version": "12.3.0",
|
"version": "12.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/firebase-admin/-/firebase-admin-12.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/firebase-admin/-/firebase-admin-12.3.1.tgz",
|
||||||
"integrity": "sha512-AKJcFbOZ7W8Fwcqh6Ba7FThXVoXwPdsf+E9vyjk5Z1vN1Z9mnTw88EQWfIsR91YglQ0KvWu1rvMhW65bcB4sog==",
|
"integrity": "sha512-vEr3s3esl8nPIA9r/feDT4nzIXCfov1CyyCSpMQWp6x63Q104qke0MEGZlrHUZVROtl8FLus6niP/M9I1s4VBA==",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fastify/busboy": "^3.0.0",
|
"@fastify/busboy": "^3.0.0",
|
||||||
"@firebase/database-compat": "^1.0.2",
|
"@firebase/database-compat": "^1.0.2",
|
||||||
"@firebase/database-types": "^1.0.0",
|
"@firebase/database-types": "^1.0.0",
|
||||||
"@types/node": "^20.10.3",
|
"@types/node": "^22.0.1",
|
||||||
"farmhash-modern": "^1.1.0",
|
"farmhash-modern": "^1.1.0",
|
||||||
"jsonwebtoken": "^9.0.0",
|
"jsonwebtoken": "^9.0.0",
|
||||||
"jwks-rsa": "^3.1.0",
|
"jwks-rsa": "^3.1.0",
|
||||||
@@ -5795,9 +5798,10 @@
|
|||||||
"integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ=="
|
"integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ=="
|
||||||
},
|
},
|
||||||
"node_modules/phone": {
|
"node_modules/phone": {
|
||||||
"version": "3.1.49",
|
"version": "3.1.50",
|
||||||
"resolved": "https://registry.npmjs.org/phone/-/phone-3.1.49.tgz",
|
"resolved": "https://registry.npmjs.org/phone/-/phone-3.1.50.tgz",
|
||||||
"integrity": "sha512-S+rHWXSQrllK5eQwz0sDbwfxQ2PzennWPgsP/jdpEPH3k7P5IBJZYjvYfU8e/RF5AwKCgOtzbTGTGJcBSLJVVw==",
|
"integrity": "sha512-TRmb2bX3sX+rrOrc8FRd8hmy4exoH2Lu3vjBP/dLgwwci1lv7DbjJ2iHMe7X4Hm8Pa0rJcfqTbq/O1vjU4NgxQ==",
|
||||||
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
}
|
}
|
||||||
@@ -6627,17 +6631,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/ssh2-sftp-client": {
|
"node_modules/ssh2-sftp-client": {
|
||||||
"version": "11.0.0",
|
"version": "10.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/ssh2-sftp-client/-/ssh2-sftp-client-11.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/ssh2-sftp-client/-/ssh2-sftp-client-10.0.3.tgz",
|
||||||
"integrity": "sha512-lOjgNYtioYquhtgyHwPryFNhllkuENjvCKkUXo18w/Q4UpEffCnEUBfiOTlwFdKIhG1rhrOGnA6DeKPSF2CP6w==",
|
"integrity": "sha512-Wlhasz/OCgrlqC8IlBZhF19Uw/X/dHI8ug4sFQybPE+0sDztvgvDf7Om6o7LbRLe68E7XkFZf3qMnqAvqn1vkQ==",
|
||||||
"license": "Apache-2.0",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"concat-stream": "^2.0.0",
|
"concat-stream": "^2.0.0",
|
||||||
"promise-retry": "^2.0.1",
|
"promise-retry": "^2.0.1",
|
||||||
"ssh2": "^1.15.0"
|
"ssh2": "^1.15.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.20.4"
|
"node": ">=16.20.2"
|
||||||
},
|
},
|
||||||
"funding": {
|
"funding": {
|
||||||
"type": "individual",
|
"type": "individual",
|
||||||
@@ -7160,9 +7163,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/undici-types": {
|
"node_modules/undici-types": {
|
||||||
"version": "5.26.5",
|
"version": "6.18.2",
|
||||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
|
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.18.2.tgz",
|
||||||
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="
|
"integrity": "sha512-5ruQbENj95yDYJNS3TvcaxPMshV7aizdv/hWYjGIKoANWKjhWNBsr2YEuYZKodQulB1b8l7ILOuDQep3afowQQ==",
|
||||||
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/universalify": {
|
"node_modules/universalify": {
|
||||||
"version": "0.1.2",
|
"version": "0.1.2",
|
||||||
|
|||||||
18
package.json
18
package.json
@@ -3,8 +3,8 @@
|
|||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"license": "UNLICENSED",
|
"license": "UNLICENSED",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=20.15.0",
|
"node": ">=18.0.0",
|
||||||
"npm": ">=10.7.0"
|
"npm": ">=8.0.0"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"setup": "rm -rf node_modules && npm i && cd client && rm -rf node_modules && npm i",
|
"setup": "rm -rf node_modules && npm i && cd client && rm -rf node_modules && npm i",
|
||||||
@@ -19,12 +19,12 @@
|
|||||||
"makeitpretty": "prettier --write \"**/*.{css,js,json,jsx,scss}\""
|
"makeitpretty": "prettier --write \"**/*.{css,js,json,jsx,scss}\""
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@aws-sdk/client-secrets-manager": "^3.624.0",
|
"@aws-sdk/client-secrets-manager": "^3.632.0",
|
||||||
"@aws-sdk/client-ses": "^3.624.0",
|
"@aws-sdk/client-ses": "^3.632.0",
|
||||||
"@aws-sdk/credential-provider-node": "^3.624.0",
|
"@aws-sdk/credential-provider-node": "^3.632.0",
|
||||||
"@opensearch-project/opensearch": "^2.11.0",
|
"@opensearch-project/opensearch": "^2.11.0",
|
||||||
"aws4": "^1.13.1",
|
"aws4": "^1.13.1",
|
||||||
"axios": "^1.7.3",
|
"axios": "^1.7.4",
|
||||||
"better-queue": "^3.8.12",
|
"better-queue": "^3.8.12",
|
||||||
"bluebird": "^3.7.2",
|
"bluebird": "^3.7.2",
|
||||||
"body-parser": "^1.20.2",
|
"body-parser": "^1.20.2",
|
||||||
@@ -38,7 +38,7 @@
|
|||||||
"dinero.js": "^1.9.1",
|
"dinero.js": "^1.9.1",
|
||||||
"dotenv": "^16.4.5",
|
"dotenv": "^16.4.5",
|
||||||
"express": "^4.19.2",
|
"express": "^4.19.2",
|
||||||
"firebase-admin": "^12.3.0",
|
"firebase-admin": "^12.3.1",
|
||||||
"graphql": "^16.9.0",
|
"graphql": "^16.9.0",
|
||||||
"graphql-request": "^6.1.0",
|
"graphql-request": "^6.1.0",
|
||||||
"graylog2": "^0.2.1",
|
"graylog2": "^0.2.1",
|
||||||
@@ -52,12 +52,12 @@
|
|||||||
"node-mailjet": "^6.0.5",
|
"node-mailjet": "^6.0.5",
|
||||||
"node-persist": "^4.0.3",
|
"node-persist": "^4.0.3",
|
||||||
"nodemailer": "^6.9.14",
|
"nodemailer": "^6.9.14",
|
||||||
"phone": "^3.1.49",
|
"phone": "^3.1.50",
|
||||||
"recursive-diff": "^1.0.9",
|
"recursive-diff": "^1.0.9",
|
||||||
"rimraf": "^6.0.1",
|
"rimraf": "^6.0.1",
|
||||||
"soap": "^1.1.1",
|
"soap": "^1.1.1",
|
||||||
"socket.io": "^4.7.5",
|
"socket.io": "^4.7.5",
|
||||||
"ssh2-sftp-client": "^11.0.0",
|
"ssh2-sftp-client": "^10.0.3",
|
||||||
"twilio": "^4.23.0",
|
"twilio": "^4.23.0",
|
||||||
"uuid": "^10.0.0",
|
"uuid": "^10.0.0",
|
||||||
"xml2js": "^0.6.2",
|
"xml2js": "^0.6.2",
|
||||||
|
|||||||
@@ -30,8 +30,14 @@ exports.default = function ({ bodyshop, jobs_by_pk, qbo = false, items, taxCodes
|
|||||||
if (jobline.db_ref === "936007") {
|
if (jobline.db_ref === "936007") {
|
||||||
hasMashLine = true;
|
hasMashLine = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Check if the line is a Towing Line and flag as such.
|
||||||
|
let isTowingLine = false;
|
||||||
|
if (jobline.db_ref === "936001" && jobline.line_desc.includes("Towing")) {
|
||||||
|
isTowingLine = true;
|
||||||
|
}
|
||||||
//Parts Lines Mappings.
|
//Parts Lines Mappings.
|
||||||
if (jobline.profitcenter_part) {
|
if (!isTowingLine && jobline.profitcenter_part) {
|
||||||
//TODO:AIO This appears to be a net 0 change exept for default quantity as 0 instead of 1 for imex. Need to verify.
|
//TODO:AIO This appears to be a net 0 change exept for default quantity as 0 instead of 1 for imex. Need to verify.
|
||||||
const discountAmount =
|
const discountAmount =
|
||||||
((jobline.prt_dsmk_m && jobline.prt_dsmk_m !== 0) || (jobline.prt_dsmk_p && jobline.prt_dsmk_p !== 0)) &&
|
((jobline.prt_dsmk_m && jobline.prt_dsmk_m !== 0) || (jobline.prt_dsmk_p && jobline.prt_dsmk_p !== 0)) &&
|
||||||
|
|||||||
@@ -273,7 +273,7 @@ async function InsertBill(oauthClient, qbo_realmId, req, bill, vendor, bodyshop)
|
|||||||
return result && result.json && result.json.Bill;
|
return result && result.json && result.json.Bill;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.log("qbo-payables-error", "DEBUG", req.user.email, bill.id, {
|
logger.log("qbo-payables-error", "DEBUG", req.user.email, bill.id, {
|
||||||
error: (error && error.authResponse && error.authResponse.body) || (error && error.message),
|
error: error, //(error && error.authResponse && error.authResponse.body) || (error && error.message),
|
||||||
method: "InsertBill"
|
method: "InsertBill"
|
||||||
});
|
});
|
||||||
throw error;
|
throw error;
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ const ftpSetup = {
|
|||||||
exports.default = async (req, res) => {
|
exports.default = async (req, res) => {
|
||||||
//Query for the List of Bodyshop Clients.
|
//Query for the List of Bodyshop Clients.
|
||||||
logger.log("kaizen-start", "DEBUG", "api", null, null);
|
logger.log("kaizen-start", "DEBUG", "api", null, null);
|
||||||
const kaizenShopsIDs = ["SUMMIT", "STRATHMORE", "SUNRIDGE"];
|
const kaizenShopsIDs = ["SUMMIT", "STRATHMORE", "SUNRIDGE", "SHAW"];
|
||||||
|
|
||||||
const { bodyshops } = await client.request(queries.GET_KAIZEN_SHOPS, {
|
const { bodyshops } = await client.request(queries.GET_KAIZEN_SHOPS, {
|
||||||
imexshopid: kaizenShopsIDs
|
imexshopid: kaizenShopsIDs
|
||||||
|
|||||||
Reference in New Issue
Block a user