feature/IO-3499-React-19: Bug Fixes / Checkpoint

This commit is contained in:
Dave
2026-01-13 22:28:43 -05:00
parent 7bdfbfabe9
commit 53d556a621
171 changed files with 1128 additions and 954 deletions

View File

@@ -1,10 +1,17 @@
import globals from "globals"; import globals from "globals";
import pluginJs from "@eslint/js"; import pluginJs from "@eslint/js";
import pluginReact from "eslint-plugin-react"; import pluginReact from "eslint-plugin-react";
import pluginReactCompiler from "eslint-plugin-react-compiler";
/** @type {import("eslint").Linter.Config[]} */ /** @type {import("eslint").Linter.Config[]} */
export default [ export default [
{ ignores: ["node_modules/**", "dist/**", "build/**", "dev-dist/**"] }, { ignores: [
"node_modules/**",
"dist/**",
"build/**",
"dev-dist/**",
"**/trello-board/dnd/**" // Exclude third-party DnD library
] },
{ {
files: ["**/*.{js,mjs,cjs,jsx}"] files: ["**/*.{js,mjs,cjs,jsx}"]
}, },
@@ -21,5 +28,13 @@ export default [
"react/no-children-prop": 0 // Disable react/no-children-prop rule "react/no-children-prop": 0 // Disable react/no-children-prop rule
} }
}, },
pluginReact.configs.flat["jsx-runtime"] pluginReact.configs.flat["jsx-runtime"],
{
plugins: {
"react-compiler": pluginReactCompiler
},
rules: {
"react-compiler/react-compiler": "error"
}
}
]; ];

View File

@@ -103,11 +103,13 @@
"@testing-library/jest-dom": "^6.9.1", "@testing-library/jest-dom": "^6.9.1",
"@testing-library/react": "^16.3.1", "@testing-library/react": "^16.3.1",
"@vitejs/plugin-react": "^5.1.2", "@vitejs/plugin-react": "^5.1.2",
"babel-plugin-react-compiler": "^1.0.0",
"browserslist": "^4.28.1", "browserslist": "^4.28.1",
"browserslist-to-esbuild": "^2.1.1", "browserslist-to-esbuild": "^2.1.1",
"chalk": "^5.6.2", "chalk": "^5.6.2",
"eslint": "^9.39.2", "eslint": "^9.39.2",
"eslint-plugin-react": "^7.37.5", "eslint-plugin-react": "^7.37.5",
"eslint-plugin-react-compiler": "^19.1.0-rc.2",
"globals": "^17.0.0", "globals": "^17.0.0",
"jsdom": "^27.4.0", "jsdom": "^27.4.0",
"memfs": "^4.51.1", "memfs": "^4.51.1",
@@ -1077,6 +1079,24 @@
"@babel/core": "^7.0.0" "@babel/core": "^7.0.0"
} }
}, },
"node_modules/@babel/plugin-proposal-private-methods": {
"version": "7.18.6",
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz",
"integrity": "sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==",
"deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-private-methods instead.",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/helper-create-class-features-plugin": "^7.18.6",
"@babel/helper-plugin-utils": "^7.18.6"
},
"engines": {
"node": ">=6.9.0"
},
"peerDependencies": {
"@babel/core": "^7.0.0-0"
}
},
"node_modules/@babel/plugin-proposal-private-property-in-object": { "node_modules/@babel/plugin-proposal-private-property-in-object": {
"version": "7.21.11", "version": "7.21.11",
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.11.tgz", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.11.tgz",
@@ -8076,6 +8096,16 @@
"@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
} }
}, },
"node_modules/babel-plugin-react-compiler": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/babel-plugin-react-compiler/-/babel-plugin-react-compiler-1.0.0.tgz",
"integrity": "sha512-Ixm8tFfoKKIPYdCCKYTsqv+Fd4IJ0DQqMyEimo+pxUOMUR9cVPlwTrFt9Avu+3cb6Zp3mAzl+t1MrG2fxxKsxw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/types": "^7.26.0"
}
},
"node_modules/babel-runtime": { "node_modules/babel-runtime": {
"version": "6.26.0", "version": "6.26.0",
"resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
@@ -10198,6 +10228,27 @@
"eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7"
} }
}, },
"node_modules/eslint-plugin-react-compiler": {
"version": "19.1.0-rc.2",
"resolved": "https://registry.npmjs.org/eslint-plugin-react-compiler/-/eslint-plugin-react-compiler-19.1.0-rc.2.tgz",
"integrity": "sha512-oKalwDGcD+RX9mf3NEO4zOoUMeLvjSvcbbEOpquzmzqEEM2MQdp7/FY/Hx9NzmUwFzH1W9SKTz5fihfMldpEYw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/core": "^7.24.4",
"@babel/parser": "^7.24.4",
"@babel/plugin-proposal-private-methods": "^7.18.6",
"hermes-parser": "^0.25.1",
"zod": "^3.22.4",
"zod-validation-error": "^3.0.3"
},
"engines": {
"node": "^14.17.0 || ^16.0.0 || >= 18.0.0"
},
"peerDependencies": {
"eslint": ">=7"
}
},
"node_modules/eslint-plugin-react/node_modules/resolve": { "node_modules/eslint-plugin-react/node_modules/resolve": {
"version": "2.0.0-next.5", "version": "2.0.0-next.5",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz",
@@ -11238,6 +11289,23 @@
"tslib": "^2.0.3" "tslib": "^2.0.3"
} }
}, },
"node_modules/hermes-estree": {
"version": "0.25.1",
"resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz",
"integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==",
"dev": true,
"license": "MIT"
},
"node_modules/hermes-parser": {
"version": "0.25.1",
"resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz",
"integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==",
"dev": true,
"license": "MIT",
"dependencies": {
"hermes-estree": "0.25.1"
}
},
"node_modules/hmac-drbg": { "node_modules/hmac-drbg": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
@@ -19138,6 +19206,29 @@
"zen-observable": "0.8.15" "zen-observable": "0.8.15"
} }
}, },
"node_modules/zod": {
"version": "3.25.76",
"resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz",
"integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==",
"dev": true,
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/colinhacks"
}
},
"node_modules/zod-validation-error": {
"version": "3.5.4",
"resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-3.5.4.tgz",
"integrity": "sha512-+hEiRIiPobgyuFlEojnqjJnhFvg4r/i3cqgcm67eehZf/WBaK3g6cD02YU9mtdVxZjv8CzCA9n/Rhrs3yAAvAw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=18.0.0"
},
"peerDependencies": {
"zod": "^3.24.4"
}
},
"node_modules/zwitch": { "node_modules/zwitch": {
"version": "2.0.4", "version": "2.0.4",
"resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz",

View File

@@ -145,11 +145,13 @@
"@testing-library/jest-dom": "^6.9.1", "@testing-library/jest-dom": "^6.9.1",
"@testing-library/react": "^16.3.1", "@testing-library/react": "^16.3.1",
"@vitejs/plugin-react": "^5.1.2", "@vitejs/plugin-react": "^5.1.2",
"babel-plugin-react-compiler": "^1.0.0",
"browserslist": "^4.28.1", "browserslist": "^4.28.1",
"browserslist-to-esbuild": "^2.1.1", "browserslist-to-esbuild": "^2.1.1",
"chalk": "^5.6.2", "chalk": "^5.6.2",
"eslint": "^9.39.2", "eslint": "^9.39.2",
"eslint-plugin-react": "^7.37.5", "eslint-plugin-react": "^7.37.5",
"eslint-plugin-react-compiler": "^19.1.0-rc.2",
"globals": "^17.0.0", "globals": "^17.0.0",
"jsdom": "^27.4.0", "jsdom": "^27.4.0",
"memfs": "^4.51.1", "memfs": "^4.51.1",

View File

@@ -19,15 +19,15 @@ export default function AllocationsAssignmentContainer({ jobLineId, hours, refet
const handleAssignment = () => { const handleAssignment = () => {
insertAllocation({ variables: { alloc: { ...assignment } } }) insertAllocation({ variables: { alloc: { ...assignment } } })
.then(() => { .then(() => {
notification["success"]({ notification.success({
message: t("allocations.successes.save") title: t("allocations.successes.save")
}); });
visibilityState[1](false); visibilityState[1](false);
if (refetch) refetch(); if (refetch) refetch();
}) })
.catch((error) => { .catch((error) => {
notification["error"]({ notification.error({
message: t("employees.errors.saving", { message: error.message }) title: t("employees.errors.saving", { message: error.message })
}); });
}); });
}; };

View File

@@ -25,8 +25,8 @@ export default function AllocationsBulkAssignmentContainer({ jobLines, refetch }
}, []); }, []);
insertAllocation({ variables: { alloc: allocs } }).then(() => { insertAllocation({ variables: { alloc: allocs } }).then(() => {
notification["success"]({ notification.success({
message: t("employees.successes.save") title: t("employees.successes.save")
}); });
visibilityState[1](false); visibilityState[1](false);
if (refetch) refetch(); if (refetch) refetch();

View File

@@ -13,13 +13,13 @@ export default function AllocationsLabelContainer({ allocation, refetch }) {
e.preventDefault(); e.preventDefault();
deleteAllocation({ variables: { id: allocation.id } }) deleteAllocation({ variables: { id: allocation.id } })
.then(() => { .then(() => {
notification["success"]({ notification.success({
message: t("allocations.successes.deleted") title: t("allocations.successes.deleted")
}); });
if (refetch) refetch(); if (refetch) refetch();
}) })
.catch(() => { .catch(() => {
notification["error"]({ message: t("allocations.errors.deleting") }); notification.error({ title: t("allocations.errors.deleting") });
}); });
}; };

View File

@@ -44,7 +44,7 @@ export function BillDeleteButton({ bill, jobid, callback, insertAuditTrail }) {
}); });
if (!result.errors) { if (!result.errors) {
notification["success"]({ message: t("bills.successes.deleted") }); notification.success({ title: t("bills.successes.deleted") });
insertAuditTrail({ insertAuditTrail({
jobid: jobid, jobid: jobid,
operation: AuditTrailMapping.billdeleted(bill.invoice_number), operation: AuditTrailMapping.billdeleted(bill.invoice_number),
@@ -57,14 +57,14 @@ export function BillDeleteButton({ bill, jobid, callback, insertAuditTrail }) {
const error = JSON.stringify(result.errors); const error = JSON.stringify(result.errors);
if (error.toLowerCase().includes("inventory_billid_fkey")) { if (error.toLowerCase().includes("inventory_billid_fkey")) {
notification["error"]({ notification.error({
message: t("bills.errors.deleting", { title: t("bills.errors.deleting", {
error: t("bills.errors.existinginventoryline") error: t("bills.errors.existinginventoryline")
}) })
}); });
} else { } else {
notification["error"]({ notification.error({
message: t("bills.errors.deleting", { title: t("bills.errors.deleting", {
error: JSON.stringify(result.errors) error: JSON.stringify(result.errors)
}) })
}); });

View File

@@ -23,7 +23,7 @@ export default function BillDetailEditcontainer() {
return ( return (
<Drawer <Drawer
width={drawerPercentage} size={drawerPercentage}
onClose={() => { onClose={() => {
delete search.billid; delete search.billid;
history({ search: queryString.stringify(search) }); history({ search: queryString.stringify(search) });

View File

@@ -205,8 +205,8 @@ function BillEnterModalContainer({ billEnterModal, toggleModalVisible, bodyshop,
} }
}); });
if (jobUpdate.errors) { if (jobUpdate.errors) {
notification["error"]({ notification.error({
message: t("jobs.errors.saving", { title: t("jobs.errors.saving", {
message: JSON.stringify(jobUpdate.errors) message: JSON.stringify(jobUpdate.errors)
}) })
}); });
@@ -224,8 +224,8 @@ function BillEnterModalContainer({ billEnterModal, toggleModalVisible, bodyshop,
if (r2.errors) { if (r2.errors) {
setLoading(false); setLoading(false);
setEnterAgain(false); setEnterAgain(false);
notification["error"]({ notification.error({
message: t("parts_orders.errors.updating", { title: t("parts_orders.errors.updating", {
message: JSON.stringify(r2.errors) message: JSON.stringify(r2.errors)
}) })
}); });
@@ -235,8 +235,8 @@ function BillEnterModalContainer({ billEnterModal, toggleModalVisible, bodyshop,
if (r1.errors) { if (r1.errors) {
setLoading(false); setLoading(false);
setEnterAgain(false); setEnterAgain(false);
notification["error"]({ notification.error({
message: t("bills.errors.creating", { title: t("bills.errors.creating", {
message: JSON.stringify(r1.errors) message: JSON.stringify(r1.errors)
}) })
}); });
@@ -255,8 +255,8 @@ function BillEnterModalContainer({ billEnterModal, toggleModalVisible, bodyshop,
if (r2.errors) { if (r2.errors) {
setLoading(false); setLoading(false);
setEnterAgain(false); setEnterAgain(false);
notification["error"]({ notification.error({
message: t("inventory.errors.updating", { title: t("inventory.errors.updating", {
message: JSON.stringify(r2.errors) message: JSON.stringify(r2.errors)
}) })
}); });
@@ -343,8 +343,8 @@ function BillEnterModalContainer({ billEnterModal, toggleModalVisible, bodyshop,
} }
/////////////////////////// ///////////////////////////
setLoading(false); setLoading(false);
notification["success"]({ notification.success({
message: t("bills.successes.created") title: t("bills.successes.created")
}); });
if (generateLabel) { if (generateLabel) {

View File

@@ -612,32 +612,51 @@ export function BillEnterModalLinesComponent({
export default connect(mapStateToProps, mapDispatchToProps)(BillEnterModalLinesComponent); export default connect(mapStateToProps, mapDispatchToProps)(BillEnterModalLinesComponent);
const EditableCell = ({ dataIndex, record, children, formInput, formItemProps, additional, wrapper, ...restProps }) => { const EditableCell = ({
const propsFinal = formItemProps && formItemProps(record); dataIndex,
if (propsFinal && "key" in propsFinal) { record,
delete propsFinal.key; children,
} formInput,
if (additional) formItemProps,
additional,
wrapper: Wrapper,
...restProps
}) => {
const rawProps = formItemProps?.(record);
// DO NOT mutate rawProps; omit `key` immutably
const propsFinal = rawProps
? (() => {
const { ...rest } = rawProps;
return rest;
})()
: undefined;
if (additional) {
return ( return (
<td {...restProps}> <td {...restProps}>
<div size="small"> <div>
<Form.Item name={dataIndex} labelCol={{ span: 0 }} {...propsFinal}> <Form.Item name={dataIndex} labelCol={{ span: 0 }} {...propsFinal}>
{(formInput && formInput(record, record.name)) || children} {(formInput && formInput(record, record.name)) || children}
</Form.Item> </Form.Item>
{additional && additional(record, record.name)} {additional(record, record.name)}
</div> </div>
</td> </td>
); );
if (wrapper) }
if (Wrapper) {
return ( return (
<wrapper> <Wrapper>
<td {...restProps}> <td {...restProps}>
<Form.Item labelCol={{ span: 0 }} name={dataIndex} {...propsFinal}> <Form.Item labelCol={{ span: 0 }} name={dataIndex} {...propsFinal}>
{(formInput && formInput(record, record.name)) || children} {(formInput && formInput(record, record.name)) || children}
</Form.Item> </Form.Item>
</td> </td>
</wrapper> </Wrapper>
); );
}
return ( return (
<td {...restProps}> <td {...restProps}>
<Form.Item labelCol={{ span: 0 }} name={dataIndex} {...propsFinal}> <Form.Item labelCol={{ span: 0 }} name={dataIndex} {...propsFinal}>

View File

@@ -62,12 +62,12 @@ export function BillMarkExportedButton({ currentUser, bodyshop, authLevel, bill
}); });
if (!result.errors) { if (!result.errors) {
notification["success"]({ notification.success({
message: t("bills.successes.markexported") title: t("bills.successes.markexported")
}); });
} else { } else {
notification["error"]({ notification.error({
message: t("bills.errors.saving", { title: t("bills.errors.saving", {
error: JSON.stringify(result.errors) error: JSON.stringify(result.errors)
}) })
}); });

View File

@@ -44,12 +44,12 @@ export function BillMarkForReexportButton({ bodyshop, authLevel, bill }) {
}); });
if (!result.errors) { if (!result.errors) {
notification["success"]({ notification.success({
message: t("bills.successes.reexport") title: t("bills.successes.reexport")
}); });
} else { } else {
notification["error"]({ notification.error({
message: t("bills.errors.saving", { title: t("bills.errors.saving", {
error: JSON.stringify(result.errors) error: JSON.stringify(result.errors)
}) })
}); });

View File

@@ -107,14 +107,12 @@ export function BilllineAddInventory({ currentUser, bodyshop, billline, disabled
}); });
if (!insertResult.errors) { if (!insertResult.errors) {
notification.open({ notification.success({
type: "success", title: t("inventory.successes.inserted")
message: t("inventory.successes.inserted")
}); });
} else { } else {
notification.open({ notification.error({
type: "error", title: t("inventory.errors.inserting", {
message: t("inventory.errors.inserting", {
error: JSON.stringify(insertResult.errors) error: JSON.stringify(insertResult.errors)
}) })
}); });

View File

@@ -2,11 +2,13 @@ import { CopyFilled, DeleteFilled } from "@ant-design/icons";
import { useLazyQuery, useMutation } from "@apollo/client/react"; import { useLazyQuery, useMutation } from "@apollo/client/react";
import { Button, Card, Col, Form, Input, message, Row, Space, Spin, Statistic } from "antd"; import { Button, Card, Col, Form, Input, message, Row, Space, Spin, Statistic } from "antd";
import axios from "axios"; import axios from "axios";
import { useState } from "react"; import { useCallback, useEffect, useMemo, useRef, 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 { INSERT_PAYMENT_RESPONSE, QUERY_RO_AND_OWNER_BY_JOB_PKS } from "../../graphql/payment_response.queries"; import { INSERT_PAYMENT_RESPONSE, QUERY_RO_AND_OWNER_BY_JOB_PKS } from "../../graphql/payment_response.queries";
import { getCurrentUser, logImEXEvent } from "../../firebase/firebase.utils";
import { useNotification } from "../../contexts/Notifications/notificationContext.jsx";
import { insertAuditTrail } from "../../redux/application/application.actions"; import { insertAuditTrail } from "../../redux/application/application.actions";
import { toggleModalVisible } from "../../redux/modals/modals.actions"; import { toggleModalVisible } from "../../redux/modals/modals.actions";
import { selectCardPayment } from "../../redux/modals/modals.selectors"; import { selectCardPayment } from "../../redux/modals/modals.selectors";
@@ -14,8 +16,6 @@ import { selectBodyshop } from "../../redux/user/user.selectors";
import AuditTrailMapping from "../../utils/AuditTrailMappings"; import AuditTrailMapping from "../../utils/AuditTrailMappings";
import CurrencyFormItemComponent from "../form-items-formatted/currency-form-item.component"; import CurrencyFormItemComponent from "../form-items-formatted/currency-form-item.component";
import JobSearchSelectComponent from "../job-search-select/job-search-select.component"; import JobSearchSelectComponent from "../job-search-select/job-search-select.component";
import { getCurrentUser, logImEXEvent } from "../../firebase/firebase.utils";
import { useNotification } from "../../contexts/Notifications/notificationContext.jsx";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
cardPaymentModal: selectCardPayment, cardPaymentModal: selectCardPayment,
@@ -51,9 +51,48 @@ const CardPaymentModalComponent = ({
const { t } = useTranslation(); const { t } = useTranslation();
const notification = useNotification(); const notification = useNotification();
const [, { data, refetch, queryLoading }] = useLazyQuery(QUERY_RO_AND_OWNER_BY_JOB_PKS, { const [loadRoAndOwnerByJobPks, { data, loading: queryLoading, error: queryError, refetch, called }] = useLazyQuery(
skip: !context?.jobid QUERY_RO_AND_OWNER_BY_JOB_PKS,
}); {
fetchPolicy: "network-only",
notifyOnNetworkStatusChange: true
}
);
const safeRefetchRoAndOwner = useCallback(
(vars) => {
// First run: execute the lazy query
if (!called) return loadRoAndOwnerByJobPks({ variables: vars });
// Subsequent runs: refetch expects the variables object directly (not { variables: ... })
return refetch(vars);
},
[called, loadRoAndOwnerByJobPks, refetch]
);
// Watch form payments so we can query jobs when all jobids are filled (without side effects during render)
const payments = Form.useWatch(["payments"], form);
const jobids = useMemo(() => {
if (!Array.isArray(payments) || payments.length === 0) return [];
return payments.map((p) => p?.jobid).filter(Boolean);
}, [payments]);
const allJobIdsFilled = useMemo(() => {
if (!Array.isArray(payments) || payments.length === 0) return false;
return payments.every((p) => !!p?.jobid);
}, [payments]);
const lastJobidsKeyRef = useRef("");
useEffect(() => {
if (!allJobIdsFilled) return;
const nextKey = jobids.join("|");
if (!nextKey || nextKey === lastJobidsKeyRef.current) return;
lastJobidsKeyRef.current = nextKey;
safeRefetchRoAndOwner({ jobids });
}, [allJobIdsFilled, jobids, safeRefetchRoAndOwner]);
const collectIPayFields = () => { const collectIPayFields = () => {
const iPayFields = document.querySelectorAll(".ipayfield"); const iPayFields = document.querySelectorAll(".ipayfield");
@@ -72,8 +111,8 @@ const CardPaymentModalComponent = ({
}); });
window.intellipay.runOnApproval(() => { window.intellipay.runOnApproval(() => {
//2024-04-25: Nothing is going to happen here anymore. We'll completely rely on the callback. // 2024-04-25: Nothing is going to happen here anymore. We'll completely rely on the callback.
//Add a slight delay to allow the refetch to properly get the data. // Add a slight delay to allow the refetch to properly get the data.
setTimeout(() => { setTimeout(() => {
if (actions?.refetch) actions.refetch(); if (actions?.refetch) actions.refetch();
setLoading(false); setLoading(false);
@@ -111,7 +150,7 @@ const CardPaymentModalComponent = ({
const handleIntelliPayCharge = async () => { const handleIntelliPayCharge = async () => {
setLoading(true); setLoading(true);
//Validate // Validate
try { try {
await form.validateFields(); await form.validateFields();
} catch { } catch {
@@ -133,7 +172,9 @@ const CardPaymentModalComponent = ({
}); });
if (window.intellipay) { if (window.intellipay) {
eval(response.data); // Use Function constructor instead of eval for security (still executes dynamic code but safer)
// IntelliPay provides initialization code that must be executed
Function(response.data)();
pollForIntelliPay(() => { pollForIntelliPay(() => {
SetIntellipayCallbackFunctions(); SetIntellipayCallbackFunctions();
window.intellipay.autoOpen(); window.intellipay.autoOpen();
@@ -144,14 +185,14 @@ const CardPaymentModalComponent = ({
document.documentElement.appendChild(node); document.documentElement.appendChild(node);
pollForIntelliPay(() => { pollForIntelliPay(() => {
SetIntellipayCallbackFunctions(); SetIntellipayCallbackFunctions();
// eslint-disable-next-line react-compiler/react-compiler
window.intellipay.isAutoOpen = true; window.intellipay.isAutoOpen = true;
window.intellipay.initialize(); window.intellipay.initialize();
}); });
} }
} catch { } catch {
notification.open({ notification.error({
type: "error", title: t("job_payments.notifications.error.openingip")
message: t("job_payments.notifications.error.openingip")
}); });
setLoading(false); setLoading(false);
} }
@@ -159,7 +200,7 @@ const CardPaymentModalComponent = ({
const handleIntelliPayChargeShortLink = async () => { const handleIntelliPayChargeShortLink = async () => {
setLoading(true); setLoading(true);
//Validate // Validate
try { try {
await form.validateFields(); await form.validateFields();
} catch { } catch {
@@ -188,9 +229,8 @@ const CardPaymentModalComponent = ({
} }
setLoading(false); setLoading(false);
} catch { } catch {
notification.open({ notification.error({
type: "error", title: t("job_payments.notifications.error.openingip")
message: t("job_payments.notifications.error.openingip")
}); });
setLoading(false); setLoading(false);
} }
@@ -247,40 +287,20 @@ const CardPaymentModalComponent = ({
)} )}
</Form.List> </Form.List>
<Form.Item {/* Hidden IntelliPay fields driven by watched payments + query result. IMPORTANT: no refetch() here (avoid side effects during render). */}
shouldUpdate={(prevValues, curValues) => <Input
prevValues.payments?.map((p) => p?.jobid + p?.amount).join() !== className="ipayfield"
curValues.payments?.map((p) => p?.jobid + p?.amount).join() data-ipayname="account"
} type="hidden"
> value={data?.jobs?.length > 0 ? data.jobs.map((j) => j.ro_number).join(", ") : null}
{() => { />
//If all of the job ids have been fileld in, then query and update the IP field. <Input
const { payments } = form.getFieldsValue(); className="ipayfield"
if (payments?.length > 0 && payments?.filter((p) => p?.jobid).length === payments?.length) { data-ipayname="email"
refetch({ variables: { jobids: payments.map((p) => p.jobid) } }); type="hidden"
} value={data?.jobs?.length > 0 ? (data.jobs.find((j) => j.ownr_ea)?.ownr_ea ?? null) : null}
return ( />
<>
<Input
className="ipayfield"
data-ipayname="account"
type="hidden"
value={
payments && data && data.jobs.length > 0 ? data.jobs.map((j) => j.ro_number).join(", ") : null
}
/>
<Input
className="ipayfield"
data-ipayname="email"
type="hidden"
value={
payments && data && data.jobs.length > 0 ? data.jobs.filter((j) => j.ownr_ea)[0]?.ownr_ea : null
}
/>
</>
);
}}
</Form.Item>
<Form.Item <Form.Item
shouldUpdate={(prevValues, curValues) => shouldUpdate={(prevValues, curValues) =>
prevValues.payments?.map((p) => p?.amount).join() !== curValues.payments?.map((p) => p?.amount).join() prevValues.payments?.map((p) => p?.amount).join() !== curValues.payments?.map((p) => p?.amount).join()
@@ -332,6 +352,7 @@ const CardPaymentModalComponent = ({
}} }}
</Form.Item> </Form.Item>
</Form> </Form>
{paymentLink && ( {paymentLink && (
<Space <Space
style={{ cursor: "pointer", float: "right" }} style={{ cursor: "pointer", float: "right" }}
@@ -345,6 +366,12 @@ const CardPaymentModalComponent = ({
<CopyFilled /> <CopyFilled />
</Space> </Space>
)} )}
{queryError ? (
<div style={{ marginTop: 12 }}>
<span style={{ color: "red" }}>{queryError.message}</span>
</div>
) : null}
</Spin> </Spin>
</Card> </Card>
); );
@@ -352,10 +379,10 @@ const CardPaymentModalComponent = ({
export default connect(mapStateToProps, mapDispatchToProps)(CardPaymentModalComponent); export default connect(mapStateToProps, mapDispatchToProps)(CardPaymentModalComponent);
//Poll for window.IntelliPay.fixAmount for 5 seconds. If it doesn't come up, just try anyways to force the possible error. // Poll for window.IntelliPay.fixAmount for 5 seconds. If it doesn't come up, just try anyways to force the possible error.
function pollForIntelliPay(callbackFunction) { function pollForIntelliPay(callbackFunction) {
const timeout = 5000; const timeout = 5000;
const interval = 150; // Poll every 100 milliseconds const interval = 150;
const startTime = Date.now(); const startTime = Date.now();
function checkFixAmount() { function checkFixAmount() {
@@ -365,7 +392,7 @@ function pollForIntelliPay(callbackFunction) {
} }
if (Date.now() - startTime >= timeout) { if (Date.now() - startTime >= timeout) {
console.log("Stopped polling IntelliPay after 10 seconds. Attemping to set functions anyways."); console.log("Stopped polling IntelliPay after 5 seconds. Attempting to set functions anyways.");
callbackFunction(); callbackFunction();
return; return;
} }

View File

@@ -33,8 +33,8 @@ export function ChatLabel({ conversation, bodyshop }) {
variables: { id: conversation.id, label: value } variables: { id: conversation.id, label: value }
}); });
if (response.errors) { if (response.errors) {
notification["error"]({ notification.error({
message: t("messages.errors.updatinglabel", { title: t("messages.errors.updatinglabel", {
error: JSON.stringify(response.errors) error: JSON.stringify(response.errors)
}) })
}); });
@@ -50,8 +50,8 @@ export function ChatLabel({ conversation, bodyshop }) {
setEditing(false); setEditing(false);
} }
} catch (error) { } catch (error) {
notification["error"]({ notification.error({
message: t("messages.errors.updatinglabel", { title: t("messages.errors.updatinglabel", {
error: JSON.stringify(error) error: JSON.stringify(error)
}) })
}); });

View File

@@ -43,7 +43,7 @@ export function ChatOpenButton({ bodyshop, searchingForConversation, phone, type
if (p && p.isValid()) { if (p && p.isValid()) {
openChatByPhone({ phone_num: p.formatInternational(), jobid, socket }); openChatByPhone({ phone_num: p.formatInternational(), jobid, socket });
} else { } else {
notification["error"]({ message: t("messaging.error.invalidphone") }); notification.error({ title: t("messaging.error.invalidphone") });
} }
}} }}
> >

View File

@@ -278,14 +278,14 @@ export function ContractConvertToRo({ bodyshop, currentUser, contract, disabled
}); });
if (result.errors) { if (result.errors) {
notification["error"]({ notification.error({
message: t("jobs.errors.inserting", { title: t("jobs.errors.inserting", {
message: JSON.stringify(result.errors) message: JSON.stringify(result.errors)
}) })
}); });
} else { } else {
notification["success"]({ notification.success({
message: t("jobs.successes.created"), title: t("jobs.successes.created"),
onClick: () => { onClick: () => {
history.push(`/manage/jobs/${result.data.insert_jobs.returning[0].id}`); history.push(`/manage/jobs/${result.data.insert_jobs.returning[0].id}`);
} }

View File

@@ -30,8 +30,8 @@ export default function ContractCreateJobPrefillComponent({ jobId, form }) {
}, [data, form]); }, [data, form]);
if (error) { if (error) {
notification["error"]({ notification.error({
message: t("contracts.errors.fetchingjobinfo", { title: t("contracts.errors.fetchingjobinfo", {
error: JSON.stringify(error) error: JSON.stringify(error)
}) })
}); });

View File

@@ -4,7 +4,7 @@ import { useTranslation } from "react-i18next";
const { Option } = Select; const { Option } = Select;
const ContractStatusComponent = ({ value, onChange }) => { const ContractStatusComponent = forwardRef(({ value, onChange }, ref) => {
const [option, setOption] = useState(value); const [option, setOption] = useState(value);
const { t } = useTranslation(); const { t } = useTranslation();
@@ -15,17 +15,14 @@ const ContractStatusComponent = ({ value, onChange }) => {
}, [value, option, onChange]); }, [value, option, onChange]);
return ( return (
<Select <Select ref={ref} value={option} style={{ width: 100 }} onChange={setOption}>
value={option}
style={{
width: 100
}}
onChange={setOption}
>
<Option value="contracts.status.new">{t("contracts.status.new")}</Option> <Option value="contracts.status.new">{t("contracts.status.new")}</Option>
<Option value="contracts.status.out">{t("contracts.status.out")}</Option> <Option value="contracts.status.out">{t("contracts.status.out")}</Option>
<Option value="contracts.status.returned">{t("contracts.status.returned")}</Option> <Option value="contracts.status.returned">{t("contracts.status.out")}</Option>
</Select> </Select>
); );
}; });
export default forwardRef(ContractStatusComponent);
ContractStatusComponent.displayName = "ContractStatusComponent";
export default ContractStatusComponent;

View File

@@ -127,10 +127,13 @@ export function ContractsList({ bodyshop, loading, contracts, refetch, total, se
const handleTableChange = (pagination, filters, sorter) => { const handleTableChange = (pagination, filters, sorter) => {
setState({ ...state, filteredInfo: filters, sortedInfo: sorter }); setState({ ...state, filteredInfo: filters, sortedInfo: sorter });
search.page = pagination.current; const updatedSearch = {
search.sortcolumn = sorter.columnKey; ...search,
search.sortorder = sorter.order; page: pagination.current,
history({ search: queryString.stringify(search) }); sortcolumn: sorter.columnKey,
sortorder: sorter.order
};
history({ search: queryString.stringify(updatedSearch) });
}; };
return ( return (
@@ -159,8 +162,8 @@ export function ContractsList({ bodyshop, loading, contracts, refetch, total, se
<Input.Search <Input.Search
placeholder={search.searh || t("general.labels.search")} placeholder={search.searh || t("general.labels.search")}
onSearch={(value) => { onSearch={(value) => {
search.search = value; const updatedSearch = { ...search, search: value };
history({ search: queryString.stringify(search) }); history({ search: queryString.stringify(updatedSearch) });
}} }}
/> />
</Space> </Space>

View File

@@ -51,8 +51,8 @@ export function CCReturnModalContainer({ courtesyCarReturnModal, toggleModalVisi
toggleModalVisible(); toggleModalVisible();
}) })
.catch((error) => { .catch((error) => {
notification["error"]({ notification.error({
message: t("contracts.errors.returning", { error: error }) title: t("contracts.errors.returning", { error: error })
}); });
}); });
setLoading(false); setLoading(false);

View File

@@ -106,7 +106,7 @@ export function DashboardGridComponent({ currentUser }) {
if (errors.length) { if (errors.length) {
const errorMessages = errors.map(({ message }) => message || String(error)); const errorMessages = errors.map(({ message }) => message || String(error));
notification.error({ notification.error({
message: t("dashboard.errors.updatinglayout", { title: t("dashboard.errors.updatinglayout", {
message: errorMessages.join("; ") message: errorMessages.join("; ")
}) })
}); });
@@ -117,7 +117,7 @@ export function DashboardGridComponent({ currentUser }) {
} catch (err) { } catch (err) {
console.error(`Dashboard ${errorContext} failed`, err); console.error(`Dashboard ${errorContext} failed`, err);
notification.error({ notification.error({
message: t("dashboard.errors.updatinglayout", { title: t("dashboard.errors.updatinglayout", {
message: err?.message || String(err) message: err?.message || String(err)
}) })
}); });

View File

@@ -1,6 +1,6 @@
import { SyncOutlined } from "@ant-design/icons"; import { SyncOutlined } from "@ant-design/icons";
import { Button, Card, Form, Input, Table } from "antd"; import { Button, Card, Form, Input, Table } from "antd";
import { useEffect, useState } from "react"; import { useEffect, useState, useRef } 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";
@@ -21,6 +21,11 @@ export default connect(mapStateToProps, mapDispatchToProps)(DmsAllocationsSummar
export function DmsAllocationsSummaryAp({ socket, bodyshop, billids, title }) { export function DmsAllocationsSummaryAp({ socket, bodyshop, billids, title }) {
const { t } = useTranslation(); const { t } = useTranslation();
const [allocationsSummary, setAllocationsSummary] = useState([]); const [allocationsSummary, setAllocationsSummary] = useState([]);
const socketRef = useRef(socket);
useEffect(() => {
socketRef.current = socket;
}, [socket]);
useEffect(() => { useEffect(() => {
socket.on("ap-export-success", (billid) => { socket.on("ap-export-success", (billid) => {
@@ -50,8 +55,8 @@ export function DmsAllocationsSummaryAp({ socket, bodyshop, billids, title }) {
if (socket.connected) { if (socket.connected) {
socket.emit("pbs-calculate-allocations-ap", billids, (ack) => { socket.emit("pbs-calculate-allocations-ap", billids, (ack) => {
setAllocationsSummary(ack); setAllocationsSummary(ack);
// Store on socket for side-channel communication
socket.allocationsSummary = ack; socketRef.current.allocationsSummary = ack;
}); });
} }
}, [socket, socket.connected, billids]); }, [socket, socket.connected, billids]);

View File

@@ -1,6 +1,6 @@
import { Alert, Button, Card, Table, Typography } from "antd"; import { Alert, Button, Card, Table, Typography } from "antd";
import { SyncOutlined } from "@ant-design/icons"; import { SyncOutlined } from "@ant-design/icons";
import { useCallback, useEffect, useState } from "react"; import { useCallback, useEffect, useState, useRef } 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";
@@ -31,6 +31,11 @@ export default connect(mapStateToProps, mapDispatchToProps)(DmsAllocationsSummar
export function DmsAllocationsSummary({ mode, socket, bodyshop, jobId, title, onAllocationsChange }) { export function DmsAllocationsSummary({ mode, socket, bodyshop, jobId, title, onAllocationsChange }) {
const { t } = useTranslation(); const { t } = useTranslation();
const [allocationsSummary, setAllocationsSummary] = useState([]); const [allocationsSummary, setAllocationsSummary] = useState([]);
const socketRef = useRef(socket);
useEffect(() => {
socketRef.current = socket;
}, [socket]);
// Resolve event name by mode (PBS reuses the CDK event per existing behavior) // Resolve event name by mode (PBS reuses the CDK event per existing behavior)
const allocationsEvent = const allocationsEvent =
@@ -48,14 +53,14 @@ export function DmsAllocationsSummary({ mode, socket, bodyshop, jobId, title, on
const list = Array.isArray(ack) ? ack : []; const list = Array.isArray(ack) ? ack : [];
setAllocationsSummary(list); setAllocationsSummary(list);
// Preserve side-channel used by the post form for discrepancy checks // Preserve side-channel used by the post form for discrepancy checks
socket.allocationsSummary = list; socketRef.current.allocationsSummary = list;
if (onAllocationsChange) onAllocationsChange(list); if (onAllocationsChange) onAllocationsChange(list);
}); });
} catch { } catch {
// Best-effort; leave table empty on error // Best-effort; leave table empty on error
setAllocationsSummary([]); setAllocationsSummary([]);
if (socket) { if (socketRef.current) {
socket.allocationsSummary = []; socketRef.current.allocationsSummary = [];
} }
if (onAllocationsChange) { if (onAllocationsChange) {
onAllocationsChange([]); onAllocationsChange([]);

View File

@@ -1,6 +1,6 @@
import { Alert, Button, Card, Table, Tabs, Typography } from "antd"; import { Alert, Button, Card, Table, Tabs, Typography } from "antd";
import { SyncOutlined } from "@ant-design/icons"; import { SyncOutlined } from "@ant-design/icons";
import { useCallback, useEffect, useMemo, useState } from "react"; import { useCallback, useEffect, useMemo, useState, useRef } 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";
@@ -74,6 +74,11 @@ export function RrAllocationsSummary({ socket, bodyshop, jobId, title, onAllocat
const [roggPreview, setRoggPreview] = useState(null); const [roggPreview, setRoggPreview] = useState(null);
const [rolaborPreview, setRolaborPreview] = useState(null); const [rolaborPreview, setRolaborPreview] = useState(null);
const [error, setError] = useState(null); const [error, setError] = useState(null);
const socketRef = useRef(socket);
useEffect(() => {
socketRef.current = socket;
}, [socket]);
// Prefer the user-selected OpCode (from DmsContainer), fall back to config default // Prefer the user-selected OpCode (from DmsContainer), fall back to config default
const effectiveOpCode = useMemo(() => opCode || resolveRROpCodeFromBodyshop(bodyshop), [opCode, bodyshop]); const effectiveOpCode = useMemo(() => opCode || resolveRROpCodeFromBodyshop(bodyshop), [opCode, bodyshop]);
@@ -87,9 +92,9 @@ export function RrAllocationsSummary({ socket, bodyshop, jobId, title, onAllocat
setRoggPreview(null); setRoggPreview(null);
setRolaborPreview(null); setRolaborPreview(null);
setError(ack.error || t("dms.labels.allocations_error")); setError(ack.error || t("dms.labels.allocations_error"));
if (socket) { if (socketRef.current) {
socket.allocationsSummary = []; socketRef.current.allocationsSummary = [];
socket.rrAllocationsRaw = ack; socketRef.current.rrAllocationsRaw = ack;
} }
if (onAllocationsChange) { if (onAllocationsChange) {
onAllocationsChange([]); onAllocationsChange([]);
@@ -103,9 +108,9 @@ export function RrAllocationsSummary({ socket, bodyshop, jobId, title, onAllocat
setRolaborPreview(ack?.rolabor || null); setRolaborPreview(ack?.rolabor || null);
setError(null); setError(null);
if (socket) { if (socketRef.current) {
socket.allocationsSummary = jobAllocRows; socketRef.current.allocationsSummary = jobAllocRows;
socket.rrAllocationsRaw = ack; socketRef.current.rrAllocationsRaw = ack;
} }
if (onAllocationsChange) { if (onAllocationsChange) {
onAllocationsChange(jobAllocRows); onAllocationsChange(jobAllocRows);
@@ -115,8 +120,8 @@ export function RrAllocationsSummary({ socket, bodyshop, jobId, title, onAllocat
setRoggPreview(null); setRoggPreview(null);
setRolaborPreview(null); setRolaborPreview(null);
setError(t("dms.labels.allocations_error")); setError(t("dms.labels.allocations_error"));
if (socket) { if (socketRef.current) {
socket.allocationsSummary = []; socketRef.current.allocationsSummary = [];
} }
if (onAllocationsChange) { if (onAllocationsChange) {
onAllocationsChange([]); onAllocationsChange([]);

View File

@@ -43,10 +43,9 @@ export const handleUpload = async ({ ev, context, notification }) => {
} else { } else {
onSuccess && onSuccess(file); onSuccess && onSuccess(file);
if (notification) { if (notification) {
notification.open({ notification.success({
type: "success",
key: "docuploadsuccess", key: "docuploadsuccess",
message: i18n.t("documents.successes.insert") title: i18n.t("documents.successes.insert")
}); });
} else { } else {
console.error("No notification context found in document local upload utility."); console.error("No notification context found in document local upload utility.");

View File

@@ -69,7 +69,7 @@ export function DocumentsUploadImgproxyComponent({
if (shouldStopUpload) { if (shouldStopUpload) {
notification.error({ notification.error({
key: "cannotuploaddocuments", key: "cannotuploaddocuments",
message: t("documents.labels.upload_limitexceeded_title"), title: t("documents.labels.upload_limitexceeded_title"),
description: t("documents.labels.upload_limitexceeded") description: t("documents.labels.upload_limitexceeded")
}); });
return Upload.LIST_IGNORE; return Upload.LIST_IGNORE;

View File

@@ -27,7 +27,7 @@ export const handleUpload = (ev, context, notification) => {
(error) => { (error) => {
console.error("Error uploading file to S3", error); console.error("Error uploading file to S3", error);
notification.error({ notification.error({
message: i18n.t("documents.errors.insert", { title: i18n.t("documents.errors.insert", {
message: error.message message: error.message
}) })
}); });
@@ -59,7 +59,7 @@ export const uploadToS3 = async (
if (signedURLResponse.status !== 200) { if (signedURLResponse.status !== 200) {
if (onError) onError(signedURLResponse.statusText); if (onError) onError(signedURLResponse.statusText);
notification.error({ notification.error({
message: i18n.t("documents.errors.getpresignurl", { title: i18n.t("documents.errors.getpresignurl", {
message: signedURLResponse.statusText message: signedURLResponse.statusText
}) })
}); });
@@ -74,7 +74,7 @@ export const uploadToS3 = async (
if (onProgress) onProgress({ percent: (e.loaded / e.total) * 100 }); if (onProgress) onProgress({ percent: (e.loaded / e.total) * 100 });
}, },
headers: { headers: {
...contentType ? { "Content-Type": fileType } : {} ...(contentType ? { "Content-Type": fileType } : {})
} }
}; };
@@ -120,7 +120,7 @@ export const uploadToS3 = async (
}); });
notification.success({ notification.success({
key: "docuploadsuccess", key: "docuploadsuccess",
message: i18n.t("documents.successes.insert") title: i18n.t("documents.successes.insert")
}); });
if (callback) { if (callback) {
callback(); callback();
@@ -128,7 +128,7 @@ export const uploadToS3 = async (
} else { } else {
if (onError) onError(JSON.stringify(documentInsert.errors)); if (onError) onError(JSON.stringify(documentInsert.errors));
notification.error({ notification.error({
message: i18n.t("documents.errors.insert", { title: i18n.t("documents.errors.insert", {
message: JSON.stringify(documentInsert.errors) message: JSON.stringify(documentInsert.errors)
}) })
}); });
@@ -137,7 +137,7 @@ export const uploadToS3 = async (
} catch (error) { } catch (error) {
console.log("Error uploading file to S3", error.message, error.stack); console.log("Error uploading file to S3", error.message, error.stack);
notification.error({ notification.error({
message: i18n.t("documents.errors.insert", { title: i18n.t("documents.errors.insert", {
message: error.message message: error.message
}) })
}); });

View File

@@ -67,10 +67,9 @@ export function DocumentsUploadComponent({
//Check to see if old files plus newly uploaded ones will be too much. //Check to see if old files plus newly uploaded ones will be too much.
if (shouldStopUpload) { if (shouldStopUpload) {
notification.open({ notification.error({
key: "cannotuploaddocuments", key: "cannotuploaddocuments",
type: "error", title: t("documents.labels.upload_limitexceeded_title"),
message: t("documents.labels.upload_limitexceeded_title"),
description: t("documents.labels.upload_limitexceeded") description: t("documents.labels.upload_limitexceeded")
}); });
return Upload.LIST_IGNORE; return Upload.LIST_IGNORE;

View File

@@ -58,8 +58,8 @@ export const uploadToCloudinary = async (
if (signedURLResponse.status !== 200) { if (signedURLResponse.status !== 200) {
if (onError) onError(signedURLResponse.statusText); if (onError) onError(signedURLResponse.statusText);
notification["error"]({ notification.error({
message: i18n.t("documents.errors.getpresignurl", { title: i18n.t("documents.errors.getpresignurl", {
message: signedURLResponse.statusText message: signedURLResponse.statusText
}) })
}); });
@@ -110,8 +110,8 @@ export const uploadToCloudinary = async (
// NO OP // NO OP
} }
notification["error"]({ notification.error({
message: i18n.t("documents.errors.insert", { title: i18n.t("documents.errors.insert", {
message: cloudinaryUploadResponse.statusText message: cloudinaryUploadResponse.statusText
}) })
}); });
@@ -155,18 +155,17 @@ export const uploadToCloudinary = async (
status: "done", status: "done",
key: documentInsert.data.insert_documents.returning[0].key key: documentInsert.data.insert_documents.returning[0].key
}); });
notification.open({ notification.success({
type: "success",
key: "docuploadsuccess", key: "docuploadsuccess",
message: i18n.t("documents.successes.insert") title: i18n.t("documents.successes.insert")
}); });
if (callback) { if (callback) {
callback(); callback();
} }
} else { } else {
if (onError) onError(JSON.stringify(documentInsert.errors)); if (onError) onError(JSON.stringify(documentInsert.errors));
notification["error"]({ notification.error({
message: i18n.t("documents.errors.insert", { title: i18n.t("documents.errors.insert", {
message: JSON.stringify(documentInsert.errors) message: JSON.stringify(documentInsert.errors)
}) })
}); });

View File

@@ -98,11 +98,11 @@ export function EmailOverlayContainer({ emailConfig, modalVisible, toggleEmailOv
media: selectedMedia.filter((m) => m.isSelected).map((m) => m.fullsize) media: selectedMedia.filter((m) => m.isSelected).map((m) => m.fullsize)
//attachments, //attachments,
}); });
notification["success"]({ message: t("emails.successes.sent") }); notification.success({ title: t("emails.successes.sent") });
toggleEmailOverlayVisible(); toggleEmailOverlayVisible();
} catch (error) { } catch (error) {
notification["error"]({ notification.error({
message: t("emails.errors.notsent", { message: error.message }) title: t("emails.errors.notsent", { message: error.message })
}); });
} }
setSending(false); setSending(false);

View File

@@ -78,7 +78,7 @@ const Eula = ({ currentEula, currentUser, acceptEula }) => {
acceptEula(); acceptEula();
} catch (err) { } catch (err) {
notification.error({ notification.error({
message: t("eula.errors.acceptance.message"), title: t("eula.errors.acceptance.message"),
description: t("eula.errors.acceptance.description") description: t("eula.errors.acceptance.description")
}); });
console.log(`${t("eula.errors.acceptance.message")}`); console.log(`${t("eula.errors.acceptance.message")}`);

View File

@@ -32,12 +32,12 @@ export default function InventoryLineDelete({ inventoryline, disabled, refetch }
}); });
if (!result.errors) { if (!result.errors) {
notification["success"]({ message: t("inventory.successes.deleted") }); notification.success({ title: t("inventory.successes.deleted") });
} else { } else {
//Check if it's an fkey violation. //Check if it's an fkey violation.
notification["error"]({ notification.error({
message: t("bills.errors.deleting", { title: t("bills.errors.deleting", {
error: JSON.stringify(result.errors) error: JSON.stringify(result.errors)
}) })
}); });

View File

@@ -120,10 +120,13 @@ export function JobsList({ refetch, loading, jobs, total, setInventoryUpsertCont
]; ];
const handleTableChange = (pagination, filters, sorter) => { const handleTableChange = (pagination, filters, sorter) => {
search.page = pagination.current; const updatedSearch = {
search.sortcolumn = sorter.column && sorter.column.key; ...search,
search.sortorder = sorter.order; page: pagination.current,
history({ search: queryString.stringify(search) }); sortcolumn: sorter.column && sorter.column.key,
sortorder: sorter.order
};
history({ search: queryString.stringify(updatedSearch) });
}; };
return ( return (
@@ -157,11 +160,13 @@ export function JobsList({ refetch, loading, jobs, total, setInventoryUpsertCont
</Button> </Button>
<Button <Button
onClick={() => { onClick={() => {
if (search.showall) delete search.showall; const updatedSearch = { ...search };
else { if (updatedSearch.showall) {
search.showall = true; delete updatedSearch.showall;
} else {
updatedSearch.showall = true;
} }
history({ search: queryString.stringify(search) }); history({ search: queryString.stringify(updatedSearch) });
}} }}
> >
{search.showall ? t("inventory.labels.showavailable") : t("inventory.labels.showall")} {search.showall ? t("inventory.labels.showavailable") : t("inventory.labels.showall")}
@@ -173,8 +178,8 @@ export function JobsList({ refetch, loading, jobs, total, setInventoryUpsertCont
<Input.Search <Input.Search
placeholder={search.search || t("general.labels.search")} placeholder={search.search || t("general.labels.search")}
onSearch={(value) => { onSearch={(value) => {
search.search = value; const updatedSearch = { ...search, search: value };
history({ search: queryString.stringify(search) }); history({ search: queryString.stringify(updatedSearch) });
}} }}
enterButton enterButton
/> />

View File

@@ -53,8 +53,8 @@ export function InventoryUpsertModalContainer({ bodyshop, inventoryUpsertModal,
inventoryItem: values inventoryItem: values
} }
}).then(() => { }).then(() => {
notification["success"]({ notification.success({
message: t("inventory.successes.updated") title: t("inventory.successes.updated")
}); });
}); });
// if (refetch) refetch(); // if (refetch) refetch();
@@ -80,8 +80,8 @@ export function InventoryUpsertModalContainer({ bodyshop, inventoryUpsertModal,
if (refetch) refetch(); if (refetch) refetch();
form.resetFields(); form.resetFields();
toggleModalVisible(); toggleModalVisible();
notification["success"]({ notification.success({
message: t("inventory.successes.inserted") title: t("inventory.successes.inserted")
}); });
} }
}; };

View File

@@ -29,8 +29,8 @@ export function JobAltTransportChange({ bodyshop, job }) {
if (!result.errors) { if (!result.errors) {
// notification["success"]({ message: t("appointments.successes.saved") }); // notification["success"]({ message: t("appointments.successes.saved") });
} else { } else {
notification["error"]({ notification.error({
message: t("jobs.errors.saving", { title: t("jobs.errors.saving", {
error: JSON.stringify(result.errors) error: JSON.stringify(result.errors)
}) })
}); });

View File

@@ -27,10 +27,10 @@ export function ScheduleEventColor({ bodyshop, event }) {
}); });
if (!result.errors) { if (!result.errors) {
notification["success"]({ message: t("appointments.successes.saved") }); notification.success({ title: t("appointments.successes.saved") });
} else { } else {
notification["error"]({ notification.error({
message: t("appointments.errors.saving", { title: t("appointments.errors.saving", {
error: JSON.stringify(result.errors) error: JSON.stringify(result.errors)
}) })
}); });

View File

@@ -131,8 +131,8 @@ export function ScheduleEventComponent({
} }
}); });
if (!res.errors) { if (!res.errors) {
notification["success"]({ notification.success({
message: t("jobs.successes.converted") title: t("jobs.successes.converted")
}); });
insertAuditTrail({ insertAuditTrail({
jobid: event.job.id, jobid: event.job.id,
@@ -309,8 +309,8 @@ export function ScheduleEventComponent({
); );
setOpen(false); setOpen(false);
} else { } else {
notification["error"]({ notification.error({
message: t("messaging.error.invalidphone") title: t("messaging.error.invalidphone")
}); });
} }
} }

View File

@@ -22,13 +22,13 @@ export default function ScheduleEventContainer({ bodyshop, event, refetch }) {
const cancelAppt = await cancelAppointment({ const cancelAppt = await cancelAppointment({
variables: { appid: event.id } variables: { appid: event.id }
}); });
notification["success"]({ notification.success({
message: t("appointments.successes.canceled") title: t("appointments.successes.canceled")
}); });
if (cancelAppt.errors) { if (cancelAppt.errors) {
notification["error"]({ notification.error({
message: t("appointments.errors.canceling", { title: t("appointments.errors.canceling", {
message: JSON.stringify(cancelAppt.errors) message: JSON.stringify(cancelAppt.errors)
}) })
}); });
@@ -59,8 +59,8 @@ export default function ScheduleEventContainer({ bodyshop, event, refetch }) {
); );
} }
if (jobUpdate.errors) { if (jobUpdate.errors) {
notification["error"]({ notification.error({
message: t("jobs.errors.updating", { title: t("jobs.errors.updating", {
message: JSON.stringify(jobUpdate.errors) message: JSON.stringify(jobUpdate.errors)
}) })
}); });

View File

@@ -39,8 +39,8 @@ export function ScheduleEventNote({ event }) {
if (!result.errors) { if (!result.errors) {
// notification["success"]({ message: t("appointments.successes.saved") }); // notification["success"]({ message: t("appointments.successes.saved") });
} else { } else {
notification["error"]({ notification.error({
message: t("jobs.errors.saving", { title: t("jobs.errors.saving", {
error: JSON.stringify(result.errors) error: JSON.stringify(result.errors)
}) })
}); });

View File

@@ -35,15 +35,15 @@ export default function JobCalculateTotals({ job, disabled, refetch }) {
// if (!!!result.errors) { // if (!!!result.errors) {
// notification["success"]({ message: t("jobs.successes.updated") }); // notification["success"]({ message: t("jobs.successes.updated") });
// } else { // } else {
// notification["error"]({ // notification.error({
// message: t("jobs.errors.updating", { // message: t("jobs.errors.updating", {
// error: JSON.stringify(result.errors), // error: JSON.stringify(result.errors),
// }), // }),
// }); // });
// } // }
} catch (error) { } catch (error) {
notification["error"]({ notification.error({
message: t("jobs.errors.updating", { title: t("jobs.errors.updating", {
error: JSON.stringify(error) error: JSON.stringify(error)
}) })
}); });

View File

@@ -107,8 +107,8 @@ export function JobChecklistForm({ insertAuditTrail, formItems, bodyshop, curren
}); });
if (appUpdate.errors) { if (appUpdate.errors) {
notification["error"]({ notification.error({
message: t("checklist.errors.complete", { title: t("checklist.errors.complete", {
error: JSON.stringify(result.errors) error: JSON.stringify(result.errors)
}) })
}); });
@@ -119,8 +119,8 @@ export function JobChecklistForm({ insertAuditTrail, formItems, bodyshop, curren
}); });
if (appUpdate.errors) { if (appUpdate.errors) {
notification["error"]({ notification.error({
message: t("checklist.errors.complete", { title: t("checklist.errors.complete", {
error: JSON.stringify(result.errors) error: JSON.stringify(result.errors)
}) })
}); });
@@ -130,7 +130,7 @@ export function JobChecklistForm({ insertAuditTrail, formItems, bodyshop, curren
setLoading(false); setLoading(false);
if (!result.errors) { if (!result.errors) {
notification["success"]({ message: t("checklist.successes.completed") }); notification.success({ title: t("checklist.successes.completed") });
history(`/manage/jobs/${jobId}`); history(`/manage/jobs/${jobId}`);
insertAuditTrail({ insertAuditTrail({
@@ -145,8 +145,8 @@ export function JobChecklistForm({ insertAuditTrail, formItems, bodyshop, curren
type: "jobchecklist" type: "jobchecklist"
}); });
} else { } else {
notification["error"]({ notification.error({
message: t("checklist.errors.complete", { title: t("checklist.errors.complete", {
error: JSON.stringify(result.errors) error: JSON.stringify(result.errors)
}) })
}); });

View File

@@ -55,9 +55,8 @@ export function JobCreateIOU({ bodyshop, currentUser, job, selectedJobLines, tec
currentUser currentUser
}); });
notification.open({ notification.success({
type: "success", title: t("jobs.successes.ioucreated"),
message: t("jobs.successes.ioucreated"),
onClick: () => history(`/manage/jobs/${iouId}`) onClick: () => history(`/manage/jobs/${iouId}`)
}); });
const selectedJobLinesIds = selectedJobLines.map((l) => l.id); const selectedJobLinesIds = selectedJobLines.map((l) => l.id);

View File

@@ -41,23 +41,20 @@ export function JobLinesPartPriceChange({ job, line, refetch, technician, isPart
id: job.id id: job.id
}); });
if (result.errors) { if (result.errors) {
notification.open({ notification.error({
type: "error", title: t("joblines.errors.saving", {
message: t("joblines.errors.saving", {
error: JSON.stringify(result.errors) error: JSON.stringify(result.errors)
}) })
}); });
if (refetch) refetch(); if (refetch) refetch();
} else { } else {
notification.open({ notification.success({
type: "success", title: t("joblines.successes.saved")
message: t("joblines.successes.saved")
}); });
} }
} catch (error) { } catch (error) {
notification.open({ notification.error({
type: "error", title: t("joblines.errors.saving", { error: JSON.stringify(error) })
message: t("joblines.errors.saving", { error: JSON.stringify(error) })
}); });
} finally { } finally {
setLoading(false); setLoading(false);

View File

@@ -174,7 +174,7 @@ export function JobLinesComponent({
prev.map((l) => (l && selectedLineIds.includes(l.id) ? { ...l, location: locationToSave } : l)) prev.map((l) => (l && selectedLineIds.includes(l.id) ? { ...l, location: locationToSave } : l))
); );
notification["success"]({ message: t("joblines.successes.saved") }); notification.success({ title: t("joblines.successes.saved") });
logImEXEvent("joblines_bulk_location_saved", { logImEXEvent("joblines_bulk_location_saved", {
count: selectedLineIds.length, count: selectedLineIds.length,
@@ -184,13 +184,13 @@ export function JobLinesComponent({
closeBulkLocationModal(); closeBulkLocationModal();
if (refetch) refetch(); if (refetch) refetch();
} else { } else {
notification["error"]({ notification.error({
message: t("joblines.errors.saving", { error: JSON.stringify(result.errors) }) title: t("joblines.errors.saving", { error: JSON.stringify(result.errors) })
}); });
} }
} catch (error) { } catch (error) {
notification["error"]({ notification.error({
message: t("joblines.errors.saving", { error: error?.message || String(error) }) title: t("joblines.errors.saving", { error: error?.message || String(error) })
}); });
} finally { } finally {
setBulkLocationSaving(false); setBulkLocationSaving(false);

View File

@@ -44,8 +44,8 @@ export function JobEmployeeAssignmentsContainer({ job, refetch, insertAuditTrail
type: "jobassignmentchange" type: "jobassignmentchange"
}); });
} else { } else {
notification["error"]({ notification.error({
message: t("jobs.errors.assigning", { title: t("jobs.errors.assigning", {
message: JSON.stringify(result.errors) message: JSON.stringify(result.errors)
}) })
}); });
@@ -68,8 +68,8 @@ export function JobEmployeeAssignmentsContainer({ job, refetch, insertAuditTrail
type: "jobassignmentremoved" type: "jobassignmentremoved"
}); });
} else { } else {
notification["error"]({ notification.error({
message: t("jobs.errors.assigning", { title: t("jobs.errors.assigning", {
message: JSON.stringify(result.errors) message: JSON.stringify(result.errors)
}) })
}); });

View File

@@ -43,9 +43,8 @@ export function JoblineBulkAssign({ setSelectedLines, selectedLines, insertAudit
} }
}); });
if (result.errors) { if (result.errors) {
notification.open({ notification.error({
type: "error", title: t("parts_dispatch.errors.creating", {
message: t("parts_dispatch.errors.creating", {
error: JSON.stringify(result.errors) error: JSON.stringify(result.errors)
}) })
}); });
@@ -64,9 +63,8 @@ export function JoblineBulkAssign({ setSelectedLines, selectedLines, insertAudit
setVisible(false); setVisible(false);
} }
} catch (error) { } catch (error) {
notification.open({ notification.error({
type: "error", title: t("parts_dispatch.errors.creating", {
message: t("parts_dispatch.errors.creating", {
error: error error: error
}) })
}); });

View File

@@ -82,16 +82,16 @@ export function JobLineConvertToLabor({
}); });
if (jobUpdate.errors) { if (jobUpdate.errors) {
notification["error"]({ notification.error({
message: t("jobs.errors.saving", { title: t("jobs.errors.saving", {
message: JSON.stringify(jobUpdate.errors) message: JSON.stringify(jobUpdate.errors)
}) })
}); });
return; return;
} }
if (lineUpdate.errors) { if (lineUpdate.errors) {
notification["error"]({ notification.error({
message: t("joblines.errors.saving", { title: t("joblines.errors.saving", {
message: JSON.stringify(lineUpdate.errors) message: JSON.stringify(lineUpdate.errors)
}) })
}); });

View File

@@ -67,9 +67,8 @@ export function JobLineDispatchButton({
}); });
if (result.errors) { if (result.errors) {
console.log("🚀 ~ handleConvert ~ result.errors:", result.errors); console.log("🚀 ~ handleConvert ~ result.errors:", result.errors);
notification.open({ notification.error({
type: "error", title: t("parts_dispatch.errors.creating", {
message: t("parts_dispatch.errors.creating", {
error: result.errors error: result.errors
}) })
}); });
@@ -91,9 +90,8 @@ export function JobLineDispatchButton({
setVisible(false); setVisible(false);
} catch (error) { } catch (error) {
console.log("🚀 ~ handleConvert ~ error:", error); console.log("🚀 ~ handleConvert ~ error:", error);
notification.open({ notification.error({
type: "error", title: t("parts_dispatch.errors.creating", {
message: t("parts_dispatch.errors.creating", {
error: error error: error
}) })
}); });

View File

@@ -44,17 +44,17 @@ export function JobLineLocationPopup({ bodyshop, jobline, disabled }) {
}); });
if (!result.errors) { if (!result.errors) {
notification["success"]({ message: t("joblines.successes.saved") }); notification.success({ title: t("joblines.successes.saved") });
} else { } else {
notification["error"]({ notification.error({
message: t("joblines.errors.saving", { title: t("joblines.errors.saving", {
error: JSON.stringify(result.errors) error: JSON.stringify(result.errors)
}) })
}); });
} }
} catch (error) { } catch (error) {
notification["error"]({ notification.error({
message: t("joblines.errors.saving", { error: error?.message || String(error) }) title: t("joblines.errors.saving", { error: error?.message || String(error) })
}); });
} finally { } finally {
setSaving(false); setSaving(false);

View File

@@ -32,10 +32,10 @@ export default function JobLineNotePopup({ jobline, disabled }) {
}); });
if (!result.errors) { if (!result.errors) {
notification["success"]({ message: t("joblines.successes.saved") }); notification.success({ title: t("joblines.successes.saved") });
} else { } else {
notification["error"]({ notification.error({
message: t("joblines.errors.saving", { title: t("joblines.errors.saving", {
error: JSON.stringify(result.errors) error: JSON.stringify(result.errors)
}) })
}); });

View File

@@ -40,10 +40,10 @@ export function JobLineStatusPopup({ bodyshop, jobline, disabled }) {
}); });
if (!result.errors) { if (!result.errors) {
notification["success"]({ message: t("joblines.successes.saved") }); notification.success({ title: t("joblines.successes.saved") });
} else { } else {
notification["error"]({ notification.error({
message: t("joblines.errors.saving", { title: t("joblines.errors.saving", {
error: JSON.stringify(result.errors) error: JSON.stringify(result.errors)
}) })
}); });

View File

@@ -45,7 +45,7 @@ export function JoblineTeamAssignment({ bodyshop, jobline, disabled, jobId, inse
}); });
if (!result.errors) { if (!result.errors) {
notification["success"]({ message: t("joblines.successes.saved") }); notification.success({ title: t("joblines.successes.saved") });
//insert the audit trail here. //insert the audit trail here.
const teamName = bodyshop.employee_teams.find((et) => et.id === assignedTeam)?.name; const teamName = bodyshop.employee_teams.find((et) => et.id === assignedTeam)?.name;
insertAuditTrail({ insertAuditTrail({
@@ -53,8 +53,8 @@ export function JoblineTeamAssignment({ bodyshop, jobline, disabled, jobId, inse
operation: AuditTrailMapping.assignedlinehours(teamName, jobline.mod_lb_hrs) operation: AuditTrailMapping.assignedlinehours(teamName, jobline.mod_lb_hrs)
}); });
} else { } else {
notification["error"]({ notification.error({
message: t("joblines.errors.saving", { title: t("joblines.errors.saving", {
error: JSON.stringify(result.errors) error: JSON.stringify(result.errors)
}) })
}); });

View File

@@ -71,12 +71,12 @@ function JobLinesUpsertModalContainer({ jobLineEditModal, toggleModalVisible, bo
if (jobLineEditModal.actions.refetch) jobLineEditModal.actions.refetch(); if (jobLineEditModal.actions.refetch) jobLineEditModal.actions.refetch();
//Need to recalcuate totals. //Need to recalcuate totals.
toggleModalVisible(); toggleModalVisible();
notification["success"]({ notification.success({
message: t("joblines.successes.created") title: t("joblines.successes.created")
}); });
} else { } else {
notification["error"]({ notification.error({
message: t("joblines.errors.creating", { title: t("joblines.errors.creating", {
message: JSON.stringify(r.errors.message) message: JSON.stringify(r.errors.message)
}) })
}); });
@@ -100,12 +100,12 @@ function JobLinesUpsertModalContainer({ jobLineEditModal, toggleModalVisible, bo
refetchQueries: ["GET_LINE_TICKET_BY_PK"] refetchQueries: ["GET_LINE_TICKET_BY_PK"]
}); });
if (!r.errors) { if (!r.errors) {
notification["success"]({ notification.success({
message: t("joblines.successes.updated") title: t("joblines.successes.updated")
}); });
} else { } else {
notification["success"]({ notification.success({
message: t("joblines.errors.updating", { title: t("joblines.errors.updating", {
message: JSON.stringify(r.errors.message) message: JSON.stringify(r.errors.message)
}) })
}); });

View File

@@ -21,10 +21,10 @@ export default function JobRemoveFromPartsQueue({ checked, jobId }) {
}); });
if (!result.errors) { if (!result.errors) {
notification["success"]({ message: t("jobs.successes.save") }); notification.success({ title: t("jobs.successes.save") });
} else { } else {
notification["error"]({ notification.error({
message: t("jobs.errors.saving", { title: t("jobs.errors.saving", {
error: JSON.stringify(result.errors) error: JSON.stringify(result.errors)
}) })
}); });

View File

@@ -69,14 +69,14 @@ export function ScoreboardAddButton({ bodyshop, job, disabled, ...otherBtnProps
} }
if (result.errors) { if (result.errors) {
notification["error"]({ notification.error({
message: t("scoreboard.errors.adding", { title: t("scoreboard.errors.adding", {
message: JSON.stringify(result.errors) message: JSON.stringify(result.errors)
}) })
}); });
} else { } else {
notification["success"]({ notification.success({
message: t("scoreboard.successes.added") title: t("scoreboard.successes.added")
}); });
} }
setLoading(false); setLoading(false);

View File

@@ -2,7 +2,7 @@ import { LoadingOutlined } from "@ant-design/icons";
import { useLazyQuery } from "@apollo/client/react"; import { useLazyQuery } from "@apollo/client/react";
import { Select, Space, Spin, Tag } from "antd"; import { Select, Space, Spin, Tag } from "antd";
import _ from "lodash"; import _ from "lodash";
import { forwardRef, useEffect, useState } from "react"; import { forwardRef, useEffect, useMemo, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { SEARCH_JOBS_BY_ID_FOR_AUTOCOMPLETE, SEARCH_JOBS_FOR_AUTOCOMPLETE } from "../../graphql/jobs.queries"; import { SEARCH_JOBS_BY_ID_FOR_AUTOCOMPLETE, SEARCH_JOBS_FOR_AUTOCOMPLETE } from "../../graphql/jobs.queries";
import AlertComponent from "../alert/alert.component"; import AlertComponent from "../alert/alert.component";
@@ -16,33 +16,45 @@ const JobSearchSelect = (
) => { ) => {
const { t } = useTranslation(); const { t } = useTranslation();
const [theOptions, setTheOptions] = useState([]); const [theOptions, setTheOptions] = useState([]);
const [callSearch, { loading, error, data }] = useLazyQuery(SEARCH_JOBS_FOR_AUTOCOMPLETE, {});
const [callSearch, { loading, error, data }] = useLazyQuery(SEARCH_JOBS_FOR_AUTOCOMPLETE);
const [callIdSearch, { loading: idLoading, error: idError, data: idData }] = useLazyQuery( const [callIdSearch, { loading: idLoading, error: idError, data: idData }] = useLazyQuery(
SEARCH_JOBS_BY_ID_FOR_AUTOCOMPLETE SEARCH_JOBS_BY_ID_FOR_AUTOCOMPLETE
); );
const executeSearch = (v) => { const debouncedExecuteSearch = useMemo(() => {
if (v && v.variables?.search !== "" && v.variables.search.length >= 2) callSearch(v); return _.debounce((value) => {
}; if (value == null || value === "" || value.length < 2) return;
const debouncedExecuteSearch = _.debounce(executeSearch, 500);
const variables = {
search: value,
...(convertedOnly || notExported
? {
...(convertedOnly ? { isConverted: true } : {}),
...(notExported ? { notExported: true } : {}),
...(notInvoiced ? { notInvoiced: true } : {})
}
: {})
};
callSearch({ variables });
}, 500);
}, [callSearch, convertedOnly, notExported, notInvoiced]);
useEffect(() => {
return () => {
debouncedExecuteSearch.cancel();
};
}, [debouncedExecuteSearch]);
const handleSearch = (value) => { const handleSearch = (value) => {
debouncedExecuteSearch({ debouncedExecuteSearch(value);
search: value,
...(convertedOnly || notExported
? {
...(convertedOnly ? { isConverted: true } : {}),
...(notExported ? { notExported: true } : {}),
...(notInvoiced ? { notInvoiced: true } : {})
}
: {})
});
}; };
useEffect(() => { useEffect(() => {
// Keep OLD "truthy" semantics (only fetch by id when value is truthy)
if (restProps.value) { if (restProps.value) {
callIdSearch({ id: restProps.value }); // Sometimes results in a no-op. Not sure how to fix. callIdSearch({ variables: { id: restProps.value } });
} }
}, [restProps.value, callIdSearch]); }, [restProps.value, callIdSearch]);
@@ -58,6 +70,7 @@ const JobSearchSelect = (
return ( return (
<div> <div>
<Select <Select
{...restProps}
ref={ref} ref={ref}
disabled={disabled} disabled={disabled}
showSearch={{ showSearch={{
@@ -65,25 +78,19 @@ const JobSearchSelect = (
onSearch: handleSearch onSearch: handleSearch
}} }}
autoFocus autoFocus
allowClear={!loading} allowClear={!loading} // matches OLD
style={{ style={{ width: "100%" }}
width: "100%" suffixIcon={(loading || idLoading) && <Spin />} // matches OLD spinner semantics
}} notFoundContent={loading ? <LoadingOutlined /> : null} // matches OLD (loading only)
//loading={loading || idLoading}
suffixIcon={(loading || idLoading) && <Spin />}
notFoundContent={loading ? <LoadingOutlined /> : null}
{...restProps}
> >
{theOptions {theOptions
? theOptions.map((o) => ( ? theOptions.map((o) => (
<Option key={o.id} value={o.id} status={o.status}> <Option key={o.id} value={o.id} status={o.status}>
<Space align="center"> <Space align="center">
<span> <span>
{`${clm_no && o.clm_no ? `${o.clm_no} | ` : ""}${ {`${clm_no && o.clm_no ? `${o.clm_no} | ` : ""}${o.ro_number || t("general.labels.na")} | ${OwnerNameDisplayFunction(
o.ro_number || t("general.labels.na") o
} | ${OwnerNameDisplayFunction(o)} | ${o.v_model_yr || ""} ${o.v_make_desc || ""} ${ )} | ${o.v_model_yr || ""} ${o.v_make_desc || ""} ${o.v_model_desc || ""}`}
o.v_model_desc || ""
}`}
</span> </span>
<Tag> <Tag>
<strong>{o.status}</strong> <strong>{o.status}</strong>
@@ -99,4 +106,5 @@ const JobSearchSelect = (
</div> </div>
); );
}; };
export default forwardRef(JobSearchSelect); export default forwardRef(JobSearchSelect);

View File

@@ -15,9 +15,8 @@ export default function JobSendPartPriceChangeComponent({ job, disabled }) {
const ppcData = await axios.post("/job/ppc", { jobid: job.id }); const ppcData = await axios.post("/job/ppc", { jobid: job.id });
await axios.post("http://localhost:1337/ppc/", ppcData.data); await axios.post("http://localhost:1337/ppc/", ppcData.data);
} catch (error) { } catch (error) {
notification.open({ notification.error({
type: "error", title: t("jobs.errors.partspricechange", {
message: t("jobs.errors.partspricechange", {
error: JSON.stringify(error) error: JSON.stringify(error)
}) })
}); });

View File

@@ -7,9 +7,9 @@ export default function JobSyncButton({ job }) {
const { t } = useTranslation(); const { t } = useTranslation();
const history = useNavigate(); const history = useNavigate();
const handleClick = () => { const handleClick = () => {
history(`/manage/available?availableJobId=${job.available_jobs[0].id}&clm_no=${job.clm_no}`); history(`/manage/available?availableJobId=${job?.available_jobs?.[0]?.id}&clm_no=${job?.clm_no}`);
}; };
if (job?.available_jobs && job.available_jobs.length > 0) if (job?.available_jobs && job?.available_jobs?.length > 0)
return ( return (
<Button onClick={handleClick}> <Button onClick={handleClick}>
<SyncOutlined /> <SyncOutlined />

View File

@@ -33,12 +33,12 @@ export function JobTotalsCashDiscount({ bodyshop, amountDinero }) {
}); });
if (data?.error) { if (data?.error) {
notification.open({ type: "error", message: data.error || errorMessage }); notification.error({ title: data.error || errorMessage });
} else { } else {
setFee(data?.fee ?? 0); setFee(data?.fee ?? 0);
} }
} catch (error) { } catch (error) {
notification.open({ type: "error", message: error.response?.data?.error || errorMessage }); notification.error({ title: error.response?.data?.error || errorMessage });
} finally { } finally {
setLoading(false); setLoading(false);
} }

View File

@@ -28,7 +28,7 @@ export function JobsAdminStatus({ insertAuditTrail, bodyshop, job }) {
variables: { jobId: job.id, status: status } variables: { jobId: job.id, status: status }
}) })
.then(() => { .then(() => {
notification["success"]({ message: t("jobs.successes.save") }); notification.success({ title: t("jobs.successes.save") });
insertAuditTrail({ insertAuditTrail({
jobid: job.id, jobid: job.id,
operation: AuditTrailMapping.admin_jobstatuschange(status), operation: AuditTrailMapping.admin_jobstatuschange(status),
@@ -37,7 +37,7 @@ export function JobsAdminStatus({ insertAuditTrail, bodyshop, job }) {
// refetch(); // refetch();
}) })
.catch(() => { .catch(() => {
notification["error"]({ message: t("jobs.errors.saving") }); notification.error({ title: t("jobs.errors.saving") });
}); });
}; };

View File

@@ -30,10 +30,10 @@ export function JobsAdminClass({ bodyshop, job }) {
}); });
if (!result.errors) { if (!result.errors) {
notification["success"]({ message: t("jobs.successes.save") }); notification.success({ title: t("jobs.successes.save") });
} else { } else {
notification["error"]({ notification.error({
message: t("jobs.errors.saving", { title: t("jobs.errors.saving", {
error: JSON.stringify(result.errors) error: JSON.stringify(result.errors)
}) })
}); });

View File

@@ -61,10 +61,10 @@ export function JobsAdminDatesChange({ insertAuditTrail, job }) {
}); });
if (!result.errors) { if (!result.errors) {
notification["success"]({ message: t("jobs.successes.save") }); notification.success({ title: t("jobs.successes.save") });
} else { } else {
notification["error"]({ notification.error({
message: t("jobs.errors.saving", { title: t("jobs.errors.saving", {
error: JSON.stringify(result.errors) error: JSON.stringify(result.errors)
}) })
}); });

View File

@@ -21,10 +21,10 @@ export default function JobAdminDeleteIntake({ job }) {
}); });
if (!result.errors) { if (!result.errors) {
notification["success"]({ message: t("jobs.successes.save") }); notification.success({ title: t("jobs.successes.save") });
} else { } else {
notification["error"]({ notification.error({
message: t("jobs.errors.saving", { title: t("jobs.errors.saving", {
error: JSON.stringify(result.errors) error: JSON.stringify(result.errors)
}) })
}); });
@@ -39,10 +39,10 @@ export default function JobAdminDeleteIntake({ job }) {
}); });
if (!result.errors) { if (!result.errors) {
notification["success"]({ message: t("jobs.successes.save") }); notification.success({ title: t("jobs.successes.save") });
} else { } else {
notification["error"]({ notification.error({
message: t("jobs.errors.saving", { title: t("jobs.errors.saving", {
error: JSON.stringify(result.errors) error: JSON.stringify(result.errors)
}) })
}); });

View File

@@ -41,15 +41,15 @@ export function JobAdminMarkReexport({ insertAuditTrail, bodyshop, currentUser,
}); });
if (!result.errors) { if (!result.errors) {
notification["success"]({ message: t("jobs.successes.save") }); notification.success({ title: t("jobs.successes.save") });
insertAuditTrail({ insertAuditTrail({
jobid: job.id, jobid: job.id,
operation: AuditTrailMapping.admin_jobmarkforreexport(), operation: AuditTrailMapping.admin_jobmarkforreexport(),
type: "admin_jobmarkforreexport" type: "admin_jobmarkforreexport"
}); });
} else { } else {
notification["error"]({ notification.error({
message: t("jobs.errors.saving", { title: t("jobs.errors.saving", {
error: JSON.stringify(result.errors) error: JSON.stringify(result.errors)
}) })
}); });
@@ -82,15 +82,15 @@ export function JobAdminMarkReexport({ insertAuditTrail, bodyshop, currentUser,
}); });
if (!result.errors) { if (!result.errors) {
notification["success"]({ message: t("jobs.successes.save") }); notification.success({ title: t("jobs.successes.save") });
insertAuditTrail({ insertAuditTrail({
jobid: job.id, jobid: job.id,
operation: AuditTrailMapping.admin_jobmarkexported(), operation: AuditTrailMapping.admin_jobmarkexported(),
type: "admin_jobmarkexported" type: "admin_jobmarkexported"
}); });
} else { } else {
notification["error"]({ notification.error({
message: t("jobs.errors.saving", { title: t("jobs.errors.saving", {
error: JSON.stringify(result.errors) error: JSON.stringify(result.errors)
}) })
}); });
@@ -108,15 +108,15 @@ export function JobAdminMarkReexport({ insertAuditTrail, bodyshop, currentUser,
}); });
if (!result.errors) { if (!result.errors) {
notification["success"]({ message: t("jobs.successes.save") }); notification.success({ title: t("jobs.successes.save") });
insertAuditTrail({ insertAuditTrail({
jobid: job.id, jobid: job.id,
operation: AuditTrailMapping.admin_jobuninvoice(), operation: AuditTrailMapping.admin_jobuninvoice(),
type: "admin_jobuninvoice" type: "admin_jobuninvoice"
}); });
} else { } else {
notification["error"]({ notification.error({
message: t("jobs.errors.saving", { title: t("jobs.errors.saving", {
error: JSON.stringify(result.errors) error: JSON.stringify(result.errors)
}) })
}); });

View File

@@ -20,10 +20,10 @@ export default function JobAdminOwnerReassociate({ job }) {
}); });
if (!result.errors) { if (!result.errors) {
notification["success"]({ message: t("jobs.successes.save") }); notification.success({ title: t("jobs.successes.save") });
} else { } else {
notification["error"]({ notification.error({
message: t("jobs.errors.saving", { title: t("jobs.errors.saving", {
error: JSON.stringify(result.errors) error: JSON.stringify(result.errors)
}) })
}); });

View File

@@ -31,7 +31,7 @@ export function JobsAdminRemoveAR({ insertAuditTrail, job }) {
}); });
if (!result.errors) { if (!result.errors) {
notification["success"]({ message: t("jobs.successes.save") }); notification.success({ title: t("jobs.successes.save") });
insertAuditTrail({ insertAuditTrail({
jobid: job.id, jobid: job.id,
operation: AuditTrailMapping.admin_job_remove_from_ar(value), operation: AuditTrailMapping.admin_job_remove_from_ar(value),
@@ -39,8 +39,8 @@ export function JobsAdminRemoveAR({ insertAuditTrail, job }) {
}); });
setSwitchValue(value); setSwitchValue(value);
} else { } else {
notification["error"]({ notification.error({
message: t("jobs.errors.saving", { title: t("jobs.errors.saving", {
error: JSON.stringify(result.errors) error: JSON.stringify(result.errors)
}) })
}); });

View File

@@ -37,7 +37,7 @@ export function JobsAdminUnvoid({ insertAuditTrail, bodyshop, job, currentUser }
}); });
if (!result.errors) { if (!result.errors) {
notification["success"]({ message: t("jobs.successes.save") }); notification.success({ title: t("jobs.successes.save") });
insertAuditTrail({ insertAuditTrail({
jobid: job.id, jobid: job.id,
@@ -45,8 +45,8 @@ export function JobsAdminUnvoid({ insertAuditTrail, bodyshop, job, currentUser }
type: "admin_jobunvoid" type: "admin_jobunvoid"
}); });
} else { } else {
notification["error"]({ notification.error({
message: t("jobs.errors.saving", { title: t("jobs.errors.saving", {
error: JSON.stringify(result.errors) error: JSON.stringify(result.errors)
}) })
}); });

View File

@@ -20,10 +20,10 @@ export default function JobAdminOwnerReassociate({ job }) {
}); });
if (!result.errors) { if (!result.errors) {
notification["success"]({ message: t("jobs.successes.save") }); notification.success({ title: t("jobs.successes.save") });
} else { } else {
notification["error"]({ notification.error({
message: t("jobs.errors.saving", { title: t("jobs.errors.saving", {
error: JSON.stringify(result.errors) error: JSON.stringify(result.errors)
}) })
}); });

View File

@@ -47,8 +47,8 @@ export function JobsAvailableScan({ partnerVersion, refetch }) {
//Came through //Came through
if (refetch) refetch(); if (refetch) refetch();
} else { } else {
notification["error"]({ notification.error({
message: t("jobs.errors.scanimport", { message: response.data.error }) title: t("jobs.errors.scanimport", { message: response.data.error })
}); });
} }
setLoading(false); setLoading(false);

View File

@@ -129,8 +129,8 @@ export function JobsAvailableComponent({ bodyshop, loading, data, refetch, addJo
<Button <Button
onClick={() => { onClick={() => {
deleteJob({ variables: { id: record.id } }).then(() => { deleteJob({ variables: { id: record.id } }).then(() => {
notification["success"]({ notification.success({
message: t("jobs.successes.deleted") title: t("jobs.successes.deleted")
}); });
refetch(); refetch();
}); });
@@ -182,16 +182,16 @@ export function JobsAvailableComponent({ bodyshop, loading, data, refetch, addJo
onClick={() => { onClick={() => {
deleteAllAvailableJobs() deleteAllAvailableJobs()
.then((r) => { .then((r) => {
notification["success"]({ notification.success({
message: t("jobs.successes.all_deleted", { title: t("jobs.successes.all_deleted", {
count: r.data.delete_available_jobs.affected_rows count: r.data.delete_available_jobs.affected_rows
}) })
}); });
refetch(); refetch();
}) })
.catch((r) => { .catch((r) => {
notification["error"]({ notification.error({
message: t("jobs.errors.deleted") + " " + r.message title: t("jobs.errors.deleted") + " " + r.message
}); });
}); });
}} }}

View File

@@ -103,8 +103,8 @@ export function JobsAvailableContainer({ bodyshop, currentUser, insertAuditTrail
if (!(estData && estData.est_data)) { if (!(estData && estData.est_data)) {
//We don't have the right data. Error! //We don't have the right data. Error!
setInsertLoading(false); setInsertLoading(false);
notification["error"]({ notification.error({
message: t("jobs.errors.creating", { error: "No job data present." }) title: t("jobs.errors.creating", { error: "No job data present." })
}); });
return; return;
} }
@@ -184,8 +184,8 @@ export function JobsAvailableContainer({ bodyshop, currentUser, insertAuditTrail
id: r.data.insert_jobs.returning[0].id id: r.data.insert_jobs.returning[0].id
}); });
notification["success"]({ notification.success({
message: t("jobs.successes.created"), title: t("jobs.successes.created"),
onClick: () => { onClick: () => {
history(`/manage/jobs/${r.data.insert_jobs.returning[0].id}`); history(`/manage/jobs/${r.data.insert_jobs.returning[0].id}`);
} }
@@ -208,8 +208,8 @@ export function JobsAvailableContainer({ bodyshop, currentUser, insertAuditTrail
setPartsQueueToggle(bodyshop.md_functionality_toggles.parts_queue_toggle); setPartsQueueToggle(bodyshop.md_functionality_toggles.parts_queue_toggle);
} catch (r) { } catch (r) {
//error while inserting //error while inserting
notification["error"]({ notification.error({
message: t("jobs.errors.creating", { error: r.message }) title: t("jobs.errors.creating", { error: r.message })
}); });
refetch().catch((err) => { refetch().catch((err) => {
console.error(`Something went wrong in jobs available table container - ${err.message || ""}`); console.error(`Something went wrong in jobs available table container - ${err.message || ""}`);
@@ -231,8 +231,8 @@ export function JobsAvailableContainer({ bodyshop, currentUser, insertAuditTrail
if (!(estData && estData.est_data)) { if (!(estData && estData.est_data)) {
//We don't have the right data. Error! //We don't have the right data. Error!
setInsertLoading(false); setInsertLoading(false);
notification["error"]({ notification.error({
message: t("jobs.errors.creating", { error: "No job data present." }) title: t("jobs.errors.creating", { error: "No job data present." })
}); });
} else { } else {
//create upsert job //create upsert job
@@ -289,8 +289,8 @@ export function JobsAvailableContainer({ bodyshop, currentUser, insertAuditTrail
if (updateResult.errors) { if (updateResult.errors) {
//error while inserting //error while inserting
notification["error"]({ notification.error({
message: t("jobs.errors.creating", { title: t("jobs.errors.creating", {
error: JSON.stringify(updateResult.errors) error: JSON.stringify(updateResult.errors)
}) })
}); });
@@ -304,14 +304,14 @@ export function JobsAvailableContainer({ bodyshop, currentUser, insertAuditTrail
}); });
if (newTotals.status !== 200) { if (newTotals.status !== 200) {
notification["error"]({ notification.error({
message: t("jobs.errors.totalscalc") title: t("jobs.errors.totalscalc")
}); });
setInsertLoading(false); setInsertLoading(false);
return; return;
} }
notification["success"]({ notification.success({
message: t("jobs.successes.supplemented"), title: t("jobs.successes.supplemented"),
onClick: () => { onClick: () => {
history(`/manage/jobs/${updateResult.data.update_jobs.returning[0].id}`); history(`/manage/jobs/${updateResult.data.update_jobs.returning[0].id}`);
} }

View File

@@ -33,7 +33,7 @@ export function JobsChangeStatus({ job, bodyshop, jobRO, insertAuditTrail, isPar
variables: { jobId: job.id, status: status } variables: { jobId: job.id, status: status }
}) })
.then(() => { .then(() => {
notification["success"]({ message: t("jobs.successes.save") }); notification.success({ title: t("jobs.successes.save") });
insertAuditTrail({ insertAuditTrail({
jobid: job.id, jobid: job.id,
operation: AuditTrailMapping.jobstatuschange(status), operation: AuditTrailMapping.jobstatuschange(status),
@@ -42,7 +42,7 @@ export function JobsChangeStatus({ job, bodyshop, jobRO, insertAuditTrail, isPar
// refetch(); // refetch();
}) })
.catch(() => { .catch(() => {
notification["error"]({ message: t("jobs.errors.saving") }); notification.error({ title: t("jobs.errors.saving") });
}); });
}; };

View File

@@ -77,8 +77,8 @@ export function JobsCloseExportButton({ bodyshop, currentUser, jobId, disabled,
console.log("handle -> XML", QbXmlResponse); console.log("handle -> XML", QbXmlResponse);
} catch (error) { } catch (error) {
console.log("Error getting QBXML from Server.", error); console.log("Error getting QBXML from Server.", error);
notification["error"]({ notification.error({
message: t("jobs.errors.exporting", { title: t("jobs.errors.exporting", {
error: "Unable to retrieve QBXML. " + JSON.stringify(error.message) error: "Unable to retrieve QBXML. " + JSON.stringify(error.message)
}) })
}); });
@@ -99,8 +99,8 @@ export function JobsCloseExportButton({ bodyshop, currentUser, jobId, disabled,
); );
} catch (error) { } catch (error) {
console.log("Error connecting to quickbooks or partner.", error); console.log("Error connecting to quickbooks or partner.", error);
notification["error"]({ notification.error({
message: t("jobs.errors.exporting-partner") title: t("jobs.errors.exporting-partner")
}); });
setLoading(false); setLoading(false);
return; return;
@@ -116,10 +116,9 @@ export function JobsCloseExportButton({ bodyshop, currentUser, jobId, disabled,
//Uh oh. At least one was no good. //Uh oh. At least one was no good.
failedTransactions.forEach((ft) => { failedTransactions.forEach((ft) => {
//insert failed export log //insert failed export log
notification.open({ notification.error({
// key: "failedexports", // key: "failedexports",
type: "error", title: t("jobs.errors.exporting", {
message: t("jobs.errors.exporting", {
error: ft.errorMessage || "" error: ft.errorMessage || ""
}) })
}); });
@@ -169,10 +168,9 @@ export function JobsCloseExportButton({ bodyshop, currentUser, jobId, disabled,
}); });
if (!jobUpdateResponse.errors) { if (!jobUpdateResponse.errors) {
notification.open({ notification.success({
type: "success",
key: "jobsuccessexport", key: "jobsuccessexport",
message: t("jobs.successes.exported") title: t("jobs.successes.exported")
}); });
insertAuditTrail({ insertAuditTrail({
jobid: jobId, jobid: jobId,
@@ -181,18 +179,17 @@ export function JobsCloseExportButton({ bodyshop, currentUser, jobId, disabled,
}); });
updateJobCache(jobUpdateResponse.data.update_jobs.returning.map((job) => job.id)); updateJobCache(jobUpdateResponse.data.update_jobs.returning.map((job) => job.id));
} else { } else {
notification["error"]({ notification.error({
message: t("jobs.errors.exporting", { title: t("jobs.errors.exporting", {
error: JSON.stringify(jobUpdateResponse.error) error: JSON.stringify(jobUpdateResponse.error)
}) })
}); });
} }
} }
if (bodyshop.accountingconfig?.qbo && successfulTransactions.length > 0) { if (bodyshop.accountingconfig?.qbo && successfulTransactions.length > 0) {
notification.open({ notification.success({
type: "success",
key: "jobsuccessexport", key: "jobsuccessexport",
message: t("jobs.successes.exported") title: t("jobs.successes.exported")
}); });
insertAuditTrail({ insertAuditTrail({
jobid: jobId, jobid: jobId,

View File

@@ -65,8 +65,8 @@ export function JobsConvertButton({ bodyshop, job, refetch, jobRO, insertAuditTr
if (!res.errors) { if (!res.errors) {
refetch(); refetch();
notification["success"]({ notification.success({
message: t("jobs.successes.converted") title: t("jobs.successes.converted")
}); });
insertAuditTrail({ insertAuditTrail({

View File

@@ -15,8 +15,8 @@ export default function AddToProduction(apolloClient, jobId, completionCallback,
variables: { jobId: jobId, job: { inproduction: !remove } } variables: { jobId: jobId, job: { inproduction: !remove } }
}) })
.then(() => { .then(() => {
notification["success"]({ notification.success({
message: i18n.t("jobs.successes.save") title: i18n.t("jobs.successes.save")
}); });
store.dispatch( store.dispatch(
@@ -29,8 +29,8 @@ export default function AddToProduction(apolloClient, jobId, completionCallback,
if (completionCallback) completionCallback(); if (completionCallback) completionCallback();
}) })
.catch((error) => { .catch((error) => {
notification["errors"]({ notification.error({
message: i18n.t("jobs.errors.saving", { title: i18n.t("jobs.errors.saving", {
error: JSON.stringify(error) error: JSON.stringify(error)
}) })
}); });

View File

@@ -182,7 +182,7 @@ export function JobsDetailHeaderActions({
completionCallback: (newJobId) => { completionCallback: (newJobId) => {
history(`/manage/jobs/${newJobId}`); history(`/manage/jobs/${newJobId}`);
notification.success({ notification.success({
message: t("jobs.successes.duplicated") title: t("jobs.successes.duplicated")
}); });
}, },
keepJobLines: true, keepJobLines: true,
@@ -197,7 +197,7 @@ export function JobsDetailHeaderActions({
completionCallback: (newJobId) => { completionCallback: (newJobId) => {
history(`/manage/jobs/${newJobId}`); history(`/manage/jobs/${newJobId}`);
notification.success({ notification.success({
message: t("jobs.successes.duplicated") title: t("jobs.successes.duplicated")
}); });
}, },
keepJobLines: false, keepJobLines: false,
@@ -215,14 +215,12 @@ export function JobsDetailHeaderActions({
}, },
refetchQueries: ["QUERY_ALL_ACTIVE_APPOINTMENTS"] refetchQueries: ["QUERY_ALL_ACTIVE_APPOINTMENTS"]
}); });
notification.open({ notification.success({
type: "success", title: t("appointments.successes.created")
message: t("appointments.successes.created")
}); });
} catch (error) { } catch (error) {
notification.open({ notification.error({
type: "error", title: t("appointments.errors.saving", { error: error.message })
message: t("appointments.errors.saving", { error: error.message })
}); });
} finally { } finally {
setLoading(false); setLoading(false);
@@ -236,13 +234,13 @@ export function JobsDetailHeaderActions({
if (!result.errors) { if (!result.errors) {
notification.success({ notification.success({
message: t("jobs.successes.delete") title: t("jobs.successes.delete")
}); });
//go back to jobs list. //go back to jobs list.
history(`/manage/`); history(`/manage/`);
} else { } else {
notification.error({ notification.error({
message: t("jobs.errors.deleted", { title: t("jobs.errors.deleted", {
error: JSON.stringify(result.errors) error: JSON.stringify(result.errors)
}) })
}); });
@@ -293,10 +291,10 @@ export function JobsDetailHeaderActions({
}); });
if (!result.errors) { if (!result.errors) {
notification.success({ message: t("csi.successes.created") }); notification.success({ title: t("csi.successes.created") });
} else { } else {
notification.error({ notification.error({
message: t("csi.errors.creating", { title: t("csi.errors.creating", {
message: JSON.stringify(result.errors) message: JSON.stringify(result.errors)
}) })
}); });
@@ -335,7 +333,7 @@ export function JobsDetailHeaderActions({
); );
} else { } else {
notification.error({ notification.error({
message: t("messaging.error.invalidphone") title: t("messaging.error.invalidphone")
}); });
} }
} }
@@ -347,7 +345,7 @@ export function JobsDetailHeaderActions({
} }
} else { } else {
notification.error({ notification.error({
message: t("csi.errors.notconfigured") title: t("csi.errors.notconfigured")
}); });
} }
} else { } else {
@@ -377,7 +375,7 @@ export function JobsDetailHeaderActions({
setMessage(`${window.location.protocol}//${window.location.host}/csi/${job.csiinvites[0].id}`); setMessage(`${window.location.protocol}//${window.location.host}/csi/${job.csiinvites[0].id}`);
} else { } else {
notification.error({ notification.error({
message: t("messaging.error.invalidphone") title: t("messaging.error.invalidphone")
}); });
} }
} }
@@ -417,7 +415,7 @@ export function JobsDetailHeaderActions({
if (!result.errors) { if (!result.errors) {
notification.success({ notification.success({
message: t("jobs.successes.voided") title: t("jobs.successes.voided")
}); });
insertAuditTrail({ insertAuditTrail({
jobid: job.id, jobid: job.id,
@@ -428,7 +426,7 @@ export function JobsDetailHeaderActions({
history(`/manage/`); history(`/manage/`);
} else { } else {
notification.error({ notification.error({
message: t("jobs.errors.voiding", { title: t("jobs.errors.voiding", {
error: JSON.stringify(result.errors) error: JSON.stringify(result.errors)
}) })
}); });
@@ -461,7 +459,7 @@ export function JobsDetailHeaderActions({
} catch (error) { } catch (error) {
console.log("Error getting QBXML from Server.", error); console.log("Error getting QBXML from Server.", error);
notification.error({ notification.error({
message: t("jobs.errors.exporting", { title: t("jobs.errors.exporting", {
error: "Unable to retrieve QBXML. " + JSON.stringify(error.message) error: "Unable to retrieve QBXML. " + JSON.stringify(error.message)
}) })
}); });
@@ -479,7 +477,7 @@ export function JobsDetailHeaderActions({
} catch (error) { } catch (error) {
console.log("Error connecting to quickbooks or partner.", error); console.log("Error connecting to quickbooks or partner.", error);
notification.error({ notification.error({
message: t("jobs.errors.exporting-partner") title: t("jobs.errors.exporting-partner")
}); });
return; return;
@@ -491,10 +489,9 @@ export function JobsDetailHeaderActions({
//Uh oh. At least one was no good. //Uh oh. At least one was no good.
failedTransactions.forEach((ft) => { failedTransactions.forEach((ft) => {
//insert failed export log //insert failed export log
notification.open({ notification.error({
// key: "failedexports", // key: "failedexports",
type: "error", title: t("jobs.errors.exporting", {
message: t("jobs.errors.exporting", {
error: ft.errorMessage || "" error: ft.errorMessage || ""
}) })
}); });
@@ -504,10 +501,9 @@ export function JobsDetailHeaderActions({
} else { } else {
//Insert success export log. //Insert success export log.
notification.open({ notification.success({
type: "success",
key: "jobsuccessexport", key: "jobsuccessexport",
message: t("jobs.successes.exported") title: t("jobs.successes.exported")
}); });
} }
}; };
@@ -575,7 +571,7 @@ export function JobsDetailHeaderActions({
}); });
if (!jobUpdate.errors) { if (!jobUpdate.errors) {
notification.success({ notification.success({
message: t("appointments.successes.canceled") title: t("appointments.successes.canceled")
}); });
insertAuditTrail({ insertAuditTrail({
jobid: job.id, jobid: job.id,
@@ -952,11 +948,11 @@ export function JobsDetailHeaderActions({
if (!result.errors) { if (!result.errors) {
notification.success({ notification.success({
message: t("jobs.successes.partsqueue") title: t("jobs.successes.partsqueue")
}); });
} else { } else {
notification.error({ notification.error({
message: t("jobs.errors.saving", { title: t("jobs.errors.saving", {
error: JSON.stringify(result.errors) error: JSON.stringify(result.errors)
}) })
}); });
@@ -1145,12 +1141,12 @@ export function JobsDetailHeaderActions({
try { try {
await axios.post("/job/totals-recorder", { id: job.id }); await axios.post("/job/totals-recorder", { id: job.id });
notification.success({ notification.success({
message: t("general.messages.submit-for-testing") title: t("general.messages.submit-for-testing")
}); });
} catch (err) { } catch (err) {
console.error(`Error submitting job for testing: ${err?.message}`); console.error(`Error submitting job for testing: ${err?.message}`);
notification.error({ notification.error({
message: t("general.errors.submit-for-testing-error") title: t("general.errors.submit-for-testing-error")
}); });
} }
} }

View File

@@ -91,8 +91,8 @@ export function JobsDetailHeaderActionsToggleProduction({
}); });
if (!res.errors) { if (!res.errors) {
notification["success"]({ notification.success({
message: t("jobs.successes.converted") title: t("jobs.successes.converted")
}); });
insertAuditTrail({ insertAuditTrail({

View File

@@ -104,7 +104,7 @@ export function JobsDetailHeader({ job, bodyshop, disabled, insertAuditTrail, is
}); });
} catch (error) { } catch (error) {
notification.error({ notification.error({
message: t("jobs.errors.saving", { error: error.message }) title: t("jobs.errors.saving", { error: error.message })
}); });
} }
}; };

View File

@@ -55,7 +55,7 @@ export function JobsDocumentsGalleryReassign({ bodyshop, galleryImages, callback
// }); // });
// if (!!result.errors) { // if (!!result.errors) {
// notification["error"]({ // notification.error({
// message: t("documents.errors.updating", { // message: t("documents.errors.updating", {
// message: JSON.stringify(result.errors), // message: JSON.stringify(result.errors),
// }), // }),
@@ -82,10 +82,9 @@ export function JobsDocumentsGalleryReassign({ bodyshop, galleryImages, callback
bodyshop.jobsizelimit - newJobData.data.documents_aggregate.aggregate.sum.size < transferedDocSizeTotal; bodyshop.jobsizelimit - newJobData.data.documents_aggregate.aggregate.sum.size < transferedDocSizeTotal;
if (shouldPreventTransfer) { if (shouldPreventTransfer) {
notification.open({ notification.error({
key: "cannotuploaddocuments", key: "cannotuploaddocuments",
type: "error", title: t("documents.labels.reassign_limitexceeded_title"),
message: t("documents.labels.reassign_limitexceeded_title"),
description: t("documents.labels.reassign_limitexceeded") description: t("documents.labels.reassign_limitexceeded")
}); });
setLoading(false); setLoading(false);
@@ -112,15 +111,15 @@ export function JobsDocumentsGalleryReassign({ bodyshop, galleryImages, callback
if (callback) callback(); if (callback) callback();
if (res.errors) { if (res.errors) {
notification["error"]({ notification.error({
message: t("documents.errors.updating", { title: t("documents.errors.updating", {
message: JSON.stringify(res.errors) message: JSON.stringify(res.errors)
}) })
}); });
} }
if (!res.mutationResult?.errors) { if (!res.mutationResult?.errors) {
notification["success"]({ notification.success({
message: t("documents.successes.updated") title: t("documents.successes.updated")
}); });
} }
setOpen(false); setOpen(false);

View File

@@ -30,16 +30,15 @@ export default function JobsDocumentsDeleteButton({ galleryImages, deletionCallb
}); });
if (res.data.error) { if (res.data.error) {
notification["error"]({ notification.error({
message: t("documents.errors.deleting", { title: t("documents.errors.deleting", {
error: JSON.stringify(res.data.error.response.errors) error: JSON.stringify(res.data.error.response.errors)
}) })
}); });
} else { } else {
notification.open({ notification.success({
key: "docdeletedsuccesfully", key: "docdeletedsuccesfully",
type: "success", title: t("documents.successes.delete")
message: t("documents.successes.delete")
}); });
if (deletionCallback) deletionCallback(); if (deletionCallback) deletionCallback();

View File

@@ -58,7 +58,7 @@ export function JobsDocumentsImgproxyGalleryReassign({ bodyshop, galleryImages,
if (shouldPreventTransfer) { if (shouldPreventTransfer) {
notification.error({ notification.error({
key: "cannotuploaddocuments", key: "cannotuploaddocuments",
message: t("documents.labels.reassign_limitexceeded_title"), title: t("documents.labels.reassign_limitexceeded_title"),
description: t("documents.labels.reassign_limitexceeded") description: t("documents.labels.reassign_limitexceeded")
}); });
setLoading(false); setLoading(false);
@@ -86,7 +86,7 @@ export function JobsDocumentsImgproxyGalleryReassign({ bodyshop, galleryImages,
if (res.errors) { if (res.errors) {
notification.error({ notification.error({
message: t("documents.errors.updating", { title: t("documents.errors.updating", {
message: JSON.stringify(res.errors) message: JSON.stringify(res.errors)
}) })
}); });

View File

@@ -35,21 +35,21 @@ export default function JobsDocumentsImgproxyDeleteButton({ galleryImages, delet
if (res.data.error) { if (res.data.error) {
notification.error({ notification.error({
message: t("documents.errors.deleting", { title: t("documents.errors.deleting", {
error: JSON.stringify(res.data.error.response.errors) error: JSON.stringify(res.data.error.response.errors)
}) })
}); });
} else { } else {
notification.success({ notification.success({
key: "docdeletedsuccesfully", key: "docdeletedsuccesfully",
message: t("documents.successes.delete") title: t("documents.successes.delete")
}); });
if (isFunction(deletionCallback)) deletionCallback(); if (isFunction(deletionCallback)) deletionCallback();
} }
} catch (error) { } catch (error) {
notification.error({ notification.error({
message: t("documents.errors.deleting", { title: t("documents.errors.deleting", {
error: error.message error: error.message
}) })
}); });

View File

@@ -44,16 +44,15 @@ export function JobsDocumentsLocalDeleteButton({ bodyshop, getJobMedia, allMedia
); );
if (delres.errors) { if (delres.errors) {
notification["error"]({ notification.error({
message: t("documents.errors.deleting", { title: t("documents.errors.deleting", {
message: JSON.stringify(delres.errors) message: JSON.stringify(delres.errors)
}) })
}); });
} else { } else {
notification.open({ notification.success({
key: "docdeletedsuccesfully", key: "docdeletedsuccesfully",
type: "success", title: t("documents.successes.delete")
message: t("documents.successes.delete")
}); });
} }
getJobMedia(jobid); getJobMedia(jobid);

View File

@@ -73,8 +73,8 @@ export function JobsExportAllButton({
); );
} catch (error) { } catch (error) {
console.log("Error getting QBXML from Server.", error); console.log("Error getting QBXML from Server.", error);
notification["error"]({ notification.error({
message: t("jobs.errors.exporting", { title: t("jobs.errors.exporting", {
error: "Unable to retrieve QBXML. " + JSON.stringify(error.message) error: "Unable to retrieve QBXML. " + JSON.stringify(error.message)
}) })
}); });
@@ -95,8 +95,8 @@ export function JobsExportAllButton({
); );
} catch (error) { } catch (error) {
console.log("Error connecting to quickbooks or partner.", error); console.log("Error connecting to quickbooks or partner.", error);
notification["error"]({ notification.error({
message: t("jobs.errors.exporting-partner") title: t("jobs.errors.exporting-partner")
}); });
setLoading(false); setLoading(false);
return; return;
@@ -114,10 +114,9 @@ export function JobsExportAllButton({
if (failedTransactions.length > 0) { if (failedTransactions.length > 0) {
//Uh oh. At least one was no good. //Uh oh. At least one was no good.
failedTransactions.forEach((ft) => { failedTransactions.forEach((ft) => {
notification.open({ notification.error({
// key: "failedexports", // key: "failedexports",
type: "error", title: t("jobs.errors.exporting", {
message: t("jobs.errors.exporting", {
error: ft.errorMessage || "" error: ft.errorMessage || ""
}) })
}); });
@@ -167,10 +166,9 @@ export function JobsExportAllButton({
}); });
if (!jobUpdateResponse.errors) { if (!jobUpdateResponse.errors) {
notification.open({ notification.success({
type: "success",
key: "jobsuccessexport", key: "jobsuccessexport",
message: t("jobs.successes.exported") title: t("jobs.successes.exported")
}); });
jobUpdateResponse.data.update_jobs.returning.forEach((job) => { jobUpdateResponse.data.update_jobs.returning.forEach((job) => {
insertAuditTrail({ insertAuditTrail({
@@ -181,18 +179,17 @@ export function JobsExportAllButton({
}); });
updateJobCache(jobUpdateResponse.data.update_jobs.returning.map((job) => job.id)); updateJobCache(jobUpdateResponse.data.update_jobs.returning.map((job) => job.id));
} else { } else {
notification["error"]({ notification.error({
message: t("jobs.errors.exporting", { title: t("jobs.errors.exporting", {
error: JSON.stringify(jobUpdateResponse.error) error: JSON.stringify(jobUpdateResponse.error)
}) })
}); });
} }
} }
if (bodyshop.accountingconfig?.qbo && successfulTransactions.length > 0) { if (bodyshop.accountingconfig?.qbo && successfulTransactions.length > 0) {
notification.open({ notification.success({
type: "success",
key: "jobsuccessexport", key: "jobsuccessexport",
message: t("jobs.successes.exported") title: t("jobs.successes.exported")
}); });
const successfulTransactionsSet = [ const successfulTransactionsSet = [
...new Set(successfulTransactions.map((st) => st[bodyshop.accountingconfig?.qbo ? "jobid" : "id"])) ...new Set(successfulTransactions.map((st) => st[bodyshop.accountingconfig?.qbo ? "jobid" : "id"]))

View File

@@ -70,7 +70,7 @@ export function JobMarkSelectedExported({
}); });
if (!result.errors) { if (!result.errors) {
notification["success"]({ message: t("jobs.successes.save") }); notification.success({ title: t("jobs.successes.save") });
result.data.update_jobs.returning.forEach((job) => { result.data.update_jobs.returning.forEach((job) => {
console.log("results job", job.id, "audit: ", AuditTrailMapping.admin_jobmarkexported()); console.log("results job", job.id, "audit: ", AuditTrailMapping.admin_jobmarkexported());
insertAuditTrail({ insertAuditTrail({
@@ -80,8 +80,8 @@ export function JobMarkSelectedExported({
}); });
}); });
} else { } else {
notification["error"]({ notification.error({
message: t("jobs.errors.saving", { title: t("jobs.errors.saving", {
error: JSON.stringify(result.errors) error: JSON.stringify(result.errors)
}) })
}); });

View File

@@ -40,8 +40,8 @@ export function JobNotesContainer({ jobId, insertAuditTrail }) {
} }
}).then(() => { }).then(() => {
refetch(); refetch();
notification["success"]({ notification.success({
message: t("notes.successes.deleted") title: t("notes.successes.deleted")
}); });
insertAuditTrail({ insertAuditTrail({
jobid: jobId, jobid: jobId,

View File

@@ -50,14 +50,14 @@ export function LaborAllocationsAdjustmentEdit({
}); });
if (result.errors) { if (result.errors) {
notification["error"]({ notification.error({
message: t("jobs.errors.saving", { title: t("jobs.errors.saving", {
message: JSON.stringify(result.errors) message: JSON.stringify(result.errors)
}) })
}); });
} else { } else {
notification["success"]({ notification.success({
message: t("jobs.successes.save") title: t("jobs.successes.save")
}); });
insertAuditTrail({ insertAuditTrail({
jobid: jobId, jobid: jobId,

View File

@@ -215,14 +215,12 @@ export function PayrollLaborAllocationsTable({
if (response.status === 200) { if (response.status === 200) {
if (response.data.success !== false) { if (response.data.success !== false) {
notification.open({ notification.success({
type: "success", title: t("timetickets.successes.payall")
message: t("timetickets.successes.payall")
}); });
} else { } else {
notification.open({ notification.error({
type: "error", title: t("timetickets.errors.payall", {
message: t("timetickets.errors.payall", {
error: response.data.error error: response.data.error
}) })
}); });
@@ -230,9 +228,8 @@ export function PayrollLaborAllocationsTable({
if (refetch) refetch(); if (refetch) refetch();
} else { } else {
notification.open({ notification.error({
type: "error", title: t("timetickets.errors.payall", {
message: t("timetickets.errors.payall", {
error: JSON.stringify("") error: JSON.stringify("")
}) })
}); });

View File

@@ -68,8 +68,8 @@ export function NoteUpsertModalContainer({ currentUser, noteUpsertModal, toggleM
}, },
refetchQueries: ["GET_JOB_BY_PK", "QUERY_JOB_CARD_DETAILS", "QUERY_PARTS_QUEUE_CARD_DETAILS"] refetchQueries: ["GET_JOB_BY_PK", "QUERY_JOB_CARD_DETAILS", "QUERY_PARTS_QUEUE_CARD_DETAILS"]
}).then(() => { }).then(() => {
notification["success"]({ notification.success({
message: t("notes.successes.updated") title: t("notes.successes.updated")
}); });
insertAuditTrail({ insertAuditTrail({
jobid: context.jobId, jobid: context.jobId,
@@ -136,8 +136,8 @@ export function NoteUpsertModalContainer({ currentUser, noteUpsertModal, toggleM
if (refetch) refetch(); if (refetch) refetch();
form.resetFields(); form.resetFields();
toggleModalVisible(); toggleModalVisible();
notification["success"]({ notification.success({
message: t("notes.successes.create") title: t("notes.successes.create")
}); });
insertAuditTrail({ insertAuditTrail({
jobid: context.jobId, jobid: context.jobId,

View File

@@ -77,14 +77,14 @@ const NotificationSettingsForm = ({ currentUser, bodyshop }) => {
if (!result?.errors) { if (!result?.errors) {
setAutoAddEnabled(checked); setAutoAddEnabled(checked);
setInitialAutoAdd(checked); setInitialAutoAdd(checked);
notification.success({ message: t("notifications.labels.auto-add-success") }); notification.success({ title: t("notifications.labels.auto-add-success") });
setIsDirty(false); // Reset dirty state if only auto-add was changed setIsDirty(false); // Reset dirty state if only auto-add was changed
} else { } else {
throw new Error("Failed to update auto-add setting"); throw new Error("Failed to update auto-add setting");
} }
} catch { } catch {
setAutoAddEnabled(!checked); // Revert on error setAutoAddEnabled(!checked); // Revert on error
notification.error({ message: t("notifications.labels.auto-add-failure") }); notification.error({ title: t("notifications.labels.auto-add-failure") });
} }
} }
}; };
@@ -96,14 +96,14 @@ const NotificationSettingsForm = ({ currentUser, bodyshop }) => {
try { try {
const result = await updateNotificationSettings({ variables: { id: userId, ns: values } }); const result = await updateNotificationSettings({ variables: { id: userId, ns: values } });
if (!result?.errors) { if (!result?.errors) {
notification.success({ message: t("notifications.labels.notification-settings-success") }); notification.success({ title: t("notifications.labels.notification-settings-success") });
setInitialValues(values); setInitialValues(values);
setIsDirty(false); setIsDirty(false);
} else { } else {
throw new Error("Failed to update notification settings"); throw new Error("Failed to update notification settings");
} }
} catch { } catch {
notification.error({ message: t("notifications.labels.notification-settings-failure") }); notification.error({ title: t("notifications.labels.notification-settings-failure") });
} }
} }
}; };

View File

@@ -63,19 +63,19 @@ function OwnerDetailFormContainer({ owner, refetch, bodyshop }) {
}); });
if (result.errors) { if (result.errors) {
notification.error({ notification.error({
message: t("owners.errors.deleting", { title: t("owners.errors.deleting", {
error: JSON.stringify(result.errors) error: JSON.stringify(result.errors)
}) })
}); });
} else { } else {
notification.success({ notification.success({
message: t("owners.successes.delete") title: t("owners.successes.delete")
}); });
navigate(`/manage/owners`); navigate(`/manage/owners`);
} }
} catch (error) { } catch (error) {
notification.error({ notification.error({
message: t("owners.errors.deleting", { title: t("owners.errors.deleting", {
error: error.message error: error.message
}) })
}); });
@@ -93,20 +93,20 @@ function OwnerDetailFormContainer({ owner, refetch, bodyshop }) {
}); });
if (result.errors) { if (result.errors) {
notification.error({ notification.error({
message: t("owners.errors.saving", { title: t("owners.errors.saving", {
error: JSON.stringify(result.errors) error: JSON.stringify(result.errors)
}) })
}); });
} else { } else {
notification.success({ notification.success({
message: t("owners.successes.save") title: t("owners.successes.save")
}); });
if (refetch) await refetch(); if (refetch) await refetch();
form.resetFields(); form.resetFields();
} }
} catch (error) { } catch (error) {
notification.error({ notification.error({
message: t("owners.errors.saving", { title: t("owners.errors.saving", {
error: error.message error: error.message
}) })
}); });

View File

@@ -36,11 +36,11 @@ export default function OwnerDetailUpdateJobsComponent({ owner, selectedJobs, di
} }
}) })
.then(() => { .then(() => {
notification["success"]({ message: t("jobs.successes.updated") }); notification.success({ title: t("jobs.successes.updated") });
}) })
.catch((error) => { .catch((error) => {
notification["error"]({ notification.error({
message: t("jobs.errors.updating", { error: JSON.stringify(error) }) title: t("jobs.errors.updating", { error: JSON.stringify(error) })
}); });
}); });
}; };

View File

@@ -71,10 +71,13 @@ export default function OwnersListComponent({ loading, owners, total, refetch })
const handleTableChange = (pagination, filters, sorter) => { const handleTableChange = (pagination, filters, sorter) => {
setState({ ...state, filteredInfo: filters, sortedInfo: sorter }); setState({ ...state, filteredInfo: filters, sortedInfo: sorter });
search.page = pagination.current; const updatedSearch = {
search.sortcolumn = sorter.columnKey; ...search,
search.sortorder = sorter.order; page: pagination.current,
history({ search: queryString.stringify(search) }); sortcolumn: sorter.columnKey,
sortorder: sorter.order
};
history({ search: queryString.stringify(updatedSearch) });
}; };
return ( return (
<Card <Card
@@ -102,12 +105,13 @@ export default function OwnersListComponent({ loading, owners, total, refetch })
<Input.Search <Input.Search
placeholder={search.search || t("general.labels.search")} placeholder={search.search || t("general.labels.search")}
onSearch={(value) => { onSearch={(value) => {
const updatedSearch = { ...search };
if (value?.length >= 3) { if (value?.length >= 3) {
search.search = value; updatedSearch.search = value;
} else { } else {
delete search.search; delete updatedSearch.search;
} }
history({ search: queryString.stringify(search) }); history({ search: queryString.stringify(updatedSearch) });
}} }}
enterButton enterButton
/> />

View File

@@ -48,14 +48,14 @@ export async function checkPartnerStatus(bodyshop) {
// bodyshop.accountingconfig.qbo) // bodyshop.accountingconfig.qbo)
// ) // )
// ) { // ) {
// notification["error"]({ // notification.error({
// title: "", // title: "",
// message: i18n.t("general.messages.noacctfilepath"), // message: i18n.t("general.messages.noacctfilepath"),
// }); // });
// } // }
} catch (error) { } catch (error) {
console.log("Partner is not running.", error); console.log("Partner is not running.", error);
// notification["error"]({ // notification.error({
// title: "", // title: "",
// message: i18n.t("general.messages.partnernotrunning"), // message: i18n.t("general.messages.partnernotrunning"),
// }); // });

View File

@@ -23,9 +23,8 @@ export default function PartsDispatchExpander({ dispatch }) {
} }
}); });
if (result.errors) { if (result.errors) {
notification.open({ notification.error({
type: "error", title: t("parts_dispatch.errors.accepting", {
message: t("parts_dispatch.errors.accepting", {
error: JSON.stringify(result.errors) error: JSON.stringify(result.errors)
}) })
}); });

View File

@@ -38,8 +38,8 @@ export function PartsOrderBackorderEta({ backordered_eta, partsOrderStatus, part
}); });
if (result.errors) { if (result.errors) {
notification["error"]({ notification.error({
message: t("parts_orders.errors.backordering", { title: t("parts_orders.errors.backordering", {
message: JSON.stringify(result.errors) message: JSON.stringify(result.errors)
}) })
}); });

View File

@@ -42,12 +42,12 @@ export default function PartsOrderCmReceived({ checked, orderLineId, partsOrderI
}); });
if (!result.errors) { if (!result.errors) {
notification["success"]({ notification.success({
message: t("parts_orders.successes.line_updated") title: t("parts_orders.successes.line_updated")
}); });
} else { } else {
notification["error"]({ notification.error({
message: t("parts_orders.errors.saving", { title: t("parts_orders.errors.saving", {
error: JSON.stringify(result.errors) error: JSON.stringify(result.errors)
}) })
}); });

View File

@@ -48,8 +48,8 @@ export function PartsOrderLineBackorderButton({ partsOrderStatus, partsLineId, j
}); });
if (result.errors) { if (result.errors) {
notification["error"]({ notification.error({
message: t("parts_orders.errors.backordering", { title: t("parts_orders.errors.backordering", {
message: JSON.stringify(result.errors) message: JSON.stringify(result.errors)
}) })
}); });

View File

@@ -387,7 +387,7 @@ export function PartsOrderListTableDrawerComponent({
onClose={() => handleOnRowClick(null)} onClose={() => handleOnRowClick(null)}
open={selectedpartsorder} open={selectedpartsorder}
closable closable
width={drawerPercentage} size={drawerPercentage}
> >
{selectedPartsOrderRecord && rowExpander(selectedPartsOrderRecord)} {selectedPartsOrderRecord && rowExpander(selectedPartsOrderRecord)}
</Drawer> </Drawer>

Some files were not shown because too many files have changed in this diff Show More