diff --git a/bodyshop_translations.babel b/bodyshop_translations.babel index e455e0d2b..513fa13f6 100644 --- a/bodyshop_translations.babel +++ b/bodyshop_translations.babel @@ -19569,6 +19569,27 @@ + + date_last_contacted + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + date_open false @@ -22324,6 +22345,27 @@ + + referral_source_other + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + referralsource false diff --git a/client/package.json b/client/package.json index ba56f9bf0..8f86c402f 100644 --- a/client/package.json +++ b/client/package.json @@ -4,35 +4,35 @@ "private": true, "proxy": "http://localhost:5000", "dependencies": { - "@apollo/client": "^3.4.15", + "@apollo/client": "^3.4.16", "@craco/craco": "^6.3.0", "@fingerprintjs/fingerprintjs": "^3.3.0", "@lourenci/react-kanban": "^2.1.0", - "@openreplay/tracker": "^3.4.1", - "@openreplay/tracker-assist": "^3.4.0", + "@openreplay/tracker": "^3.4.4", + "@openreplay/tracker-assist": "^3.4.3", "@openreplay/tracker-graphql": "^3.0.0", "@openreplay/tracker-redux": "^3.0.0", "@sentry/react": "^6.13.2", "@sentry/tracing": "^6.13.2", "@stripe/react-stripe-js": "^1.5.0", - "@stripe/stripe-js": "^1.18.0", + "@stripe/stripe-js": "^1.19.1", "@tanem/react-nprogress": "^3.0.79", "antd": "^4.16.13", "apollo-link-logger": "^2.0.0", - "axios": "^0.21.4", + "axios": "^0.22.0", "craco-less": "^1.20.0", "dinero.js": "^1.9.0", "dotenv": "^10.0.0", "enquire-js": "^0.2.1", "env-cmd": "^10.1.0", "exifr": "^7.1.3", - "firebase": "^9.1.0", + "firebase": "^9.1.1", "graphql": "^15.6.0", - "i18next": "^21.2.0", + "i18next": "^21.2.4", "i18next-browser-languagedetector": "^6.1.2", "jsoneditor": "^9.5.6", "jsreport-browser-client-dist": "^1.3.0", - "libphonenumber-js": "^1.9.34", + "libphonenumber-js": "^1.9.36", "logrocket": "^2.0.0", "markerjs2": "^2.13.0", "moment-business-days": "^1.2.0", @@ -43,7 +43,7 @@ "rc-queue-anim": "^2.0.0", "rc-scroll-anim": "^2.7.6", "react": "^17.0.1", - "react-big-calendar": "^0.36.0", + "react-big-calendar": "^0.36.1", "react-color": "^2.19.3", "react-cookie": "^4.1.1", "react-dom": "^17.0.1", @@ -51,7 +51,7 @@ "react-grid-gallery": "^0.5.5", "react-grid-layout": "^1.3.0", "react-i18next": "^11.12.0", - "react-icons": "^4.2.0", + "react-icons": "^4.3.1", "react-number-format": "^4.7.3", "react-redux": "^7.2.5", "react-resizable": "^3.0.4", @@ -114,7 +114,7 @@ ] }, "devDependencies": { - "@sentry/webpack-plugin": "^1.17.1", + "@sentry/webpack-plugin": "^1.17.2", "patch-package": "^6.4.7", "redux-logger": "^3.0.6", "source-map-explorer": "^2.5.2" diff --git a/client/src/components/bill-line-search-select/bill-line-search-select.component.jsx b/client/src/components/bill-line-search-select/bill-line-search-select.component.jsx index 66a67c7d5..dd5558f85 100644 --- a/client/src/components/bill-line-search-select/bill-line-search-select.component.jsx +++ b/client/src/components/bill-line-search-select/bill-line-search-select.component.jsx @@ -12,7 +12,18 @@ const BillLineSearchSelect = ({ options, disabled, ...restProps }, ref) => { disabled={disabled} ref={ref} showSearch - optionFilterProp="line_desc" + // optionFilterProp="line_desc" + filterOption={(inputValue, option) => { + console.log(inputValue); + return ( + (option.line_desc && + option.line_desc + .toLowerCase() + .includes(inputValue.toLowerCase())) || + (option.oem_partno && + option.oem_partno.toLowerCase().includes(inputValue.toLowerCase())) + ); + }} notFoundContent={"Removed."} {...restProps} > @@ -29,6 +40,7 @@ const BillLineSearchSelect = ({ options, disabled, ...restProps }, ref) => { part_type={item.part_type} line_desc={item.line_desc} part_qty={item.part_qty} + oem_partno={item.oem_partno} style={{ ...(item.removed ? { textDecoration: "line-through" } : {}), }} diff --git a/client/src/components/job-checklist/components/job-checklist-form/job-checklist-form.component.jsx b/client/src/components/job-checklist/components/job-checklist-form/job-checklist-form.component.jsx index 6d76cdd8b..cdffbec23 100644 --- a/client/src/components/job-checklist/components/job-checklist-form/job-checklist-form.component.jsx +++ b/client/src/components/job-checklist/components/job-checklist-form/job-checklist-form.component.jsx @@ -167,7 +167,11 @@ export function JobChecklistForm({ title={t("checklist.labels.checklist")} extra={ !readOnly && ( - ) diff --git a/client/src/components/job-detail-cards/job-detail-cards.component.jsx b/client/src/components/job-detail-cards/job-detail-cards.component.jsx index ca456e584..8987d2d9c 100644 --- a/client/src/components/job-detail-cards/job-detail-cards.component.jsx +++ b/client/src/components/job-detail-cards/job-detail-cards.component.jsx @@ -112,60 +112,46 @@ export function JobDetailCards({ setPrintCenterContext }) { - - - + - - - + - - - + - - - + - - - + - - - + - - - + diff --git a/client/src/components/job-detail-cards/job-detail-cards.dates.component.jsx b/client/src/components/job-detail-cards/job-detail-cards.dates.component.jsx index e5fbe7f67..e1e165408 100644 --- a/client/src/components/job-detail-cards/job-detail-cards.dates.component.jsx +++ b/client/src/components/job-detail-cards/job-detail-cards.dates.component.jsx @@ -1,7 +1,7 @@ import { Timeline } from "antd"; import React from "react"; import { useTranslation } from "react-i18next"; -import { DateFormatter } from "../../utils/DateFormatter"; +import { DateTimeFormatter } from "../../utils/DateFormatter"; import CardTemplate from "./job-detail-cards.template.component"; export default function JobDetailCardsDatesComponent({ loading, data }) { @@ -26,80 +26,86 @@ export default function JobDetailCardsDatesComponent({ loading, data }) { ) ? (
{t("jobs.errors.nodates")}
) : null} + {data.date_last_contacted ? ( + + + {data.date_last_contacted} + + ) : null} {data.date_open ? ( - {data.date_open} + {data.date_open} ) : null} {data.date_estimated ? ( - {data.date_estimated} + {data.date_estimated} ) : null} {data.date_scheduled ? ( - {data.date_scheduled} + {data.date_scheduled} ) : null} {data.scheduled_in ? ( - {data.scheduled_in} + {data.scheduled_in} ) : null} {data.actual_in ? ( - {data.actual_in} + {data.actual_in} ) : null} {data.scheduled_completion ? ( - {data.scheduled_completion} + {data.scheduled_completion} ) : null} {data.actual_completion ? ( - {data.actual_completion} + {data.actual_completion} ) : null} {data.scheduled_delivery ? ( - {data.scheduled_delivery} + {data.scheduled_delivery} ) : null} {data.actual_delivery ? ( - {data.actual_delivery} + {data.actual_delivery} ) : null} {data.date_invoiced ? ( - {data.date_invoiced} + {data.date_invoiced} ) : null} {data.date_exported ? ( - {data.date_exported} + {data.date_exported} ) : null} diff --git a/client/src/components/job-detail-cards/job-detail-cards.documents.component.jsx b/client/src/components/job-detail-cards/job-detail-cards.documents.component.jsx index bb431f023..c4031b8b4 100644 --- a/client/src/components/job-detail-cards/job-detail-cards.documents.component.jsx +++ b/client/src/components/job-detail-cards/job-detail-cards.documents.component.jsx @@ -1,8 +1,8 @@ import { Carousel } from "antd"; import React from "react"; import { useTranslation } from "react-i18next"; +import { GenerateThumbUrl } from "../jobs-documents-gallery/job-documents.utility"; import CardTemplate from "./job-detail-cards.template.component"; -import { DetermineFileType } from "../documents-upload/documents-upload.utility"; export default function JobDetailCardsDocumentsComponent({ loading, data }) { const { t } = useTranslation(); @@ -22,15 +22,7 @@ export default function JobDetailCardsDocumentsComponent({ loading, data }) { {data.documents.length > 0 ? ( {data.documents.map((item) => ( - {item.name} + {item.name} ))} ) : ( diff --git a/client/src/components/job-detail-cards/job-detail-cards.template.component.jsx b/client/src/components/job-detail-cards/job-detail-cards.template.component.jsx index a2e9e78aa..4aa6e0d6e 100644 --- a/client/src/components/job-detail-cards/job-detail-cards.template.component.jsx +++ b/client/src/components/job-detail-cards/job-detail-cards.template.component.jsx @@ -12,11 +12,13 @@ export default function JobDetailCardTemplate({ if (extraLink) extra = { extra: More }; return ( + style={{ height: "100%" }} + {...extra} + > {otherProps.children} ); diff --git a/client/src/components/job-detail-lines/job-lines.component.jsx b/client/src/components/job-detail-lines/job-lines.component.jsx index b02b26663..9d799b991 100644 --- a/client/src/components/job-detail-lines/job-lines.component.jsx +++ b/client/src/components/job-detail-lines/job-lines.component.jsx @@ -36,6 +36,7 @@ import JobLinesBillRefernece from "../job-lines-bill-reference/job-lines-bill-re // import AllocationsBulkAssignmentContainer from "../allocations-bulk-assignment/allocations-bulk-assignment.container"; // import AllocationsEmployeeLabelContainer from "../allocations-employee-label/allocations-employee-label.container"; import PartsOrderModalContainer from "../parts-order-modal/parts-order-modal.container"; +import _ from "lodash"; const mapStateToProps = createStructuredSelector({ //currentUser: selectCurrentUser @@ -334,10 +335,12 @@ export function JobLinesComponent({ const markedTypes = [e.key]; if (e.key === "PAN") markedTypes.push("PAP"); if (e.key === "PAS") markedTypes.push("PASL"); - setSelectedLines([ - ...selectedLines, - ...jobLines.filter((item) => markedTypes.includes(item.part_type)), - ]); + setSelectedLines( + _.uniq([ + ...selectedLines, + ...jobLines.filter((item) => markedTypes.includes(item.part_type)), + ]) + ); } }; diff --git a/client/src/components/jobs-admin-dates/jobs-admin-dates.component.jsx b/client/src/components/jobs-admin-dates/jobs-admin-dates.component.jsx index 9a4c4a398..a72d28473 100644 --- a/client/src/components/jobs-admin-dates/jobs-admin-dates.component.jsx +++ b/client/src/components/jobs-admin-dates/jobs-admin-dates.component.jsx @@ -74,7 +74,12 @@ export default function JobsAdminDatesChange({ job }) { - + + + { - if ( - (jl.part_type === "PASL" || jl.part_type === "PAS") && - jl.lbr_op !== "OP11" - ) { - estData.joblines.data[index].tax_part = jl.lbr_tax; - console.log(estData.joblines.data[index], jl); - } - }); - } + //if (bodyshop.region_config === "CA_SK") { + estData.joblines.data.forEach((jl, index) => { + if ( + (jl.part_type === "PASL" || jl.part_type === "PAS") && + jl.lbr_op !== "OP11" + ) { + estData.joblines.data[index].tax_part = jl.lbr_tax; + } + }); + //} } diff --git a/client/src/components/jobs-detail-dates/jobs-detail-dates.component.jsx b/client/src/components/jobs-detail-dates/jobs-detail-dates.component.jsx index 038dc168b..cf1366612 100644 --- a/client/src/components/jobs-detail-dates/jobs-detail-dates.component.jsx +++ b/client/src/components/jobs-detail-dates/jobs-detail-dates.component.jsx @@ -69,6 +69,12 @@ export function JobsDetailDatesComponent({ jobRO, job, bodyshop }) { + + + - { - // console.log("Added event listening for reteching."); - // window.addEventListener("storage", (ev) => { - // if (ev.key === "refetch" && ev.newValue === true) { - // refetch && refetch(); - // localStorage.setItem("refetch", false); - // } - // }); - - // return () => { - // window.removeEventListener("storage"); - // }; - // }, [refetch]); - useEffect(() => { let documents = data.reduce( (acc, value) => { diff --git a/client/src/components/parts-order-modal/parts-order-modal.component.jsx b/client/src/components/parts-order-modal/parts-order-modal.component.jsx index 4da7ade50..08973075d 100644 --- a/client/src/components/parts-order-modal/parts-order-modal.component.jsx +++ b/client/src/components/parts-order-modal/parts-order-modal.component.jsx @@ -73,7 +73,7 @@ export default function PartsOrderModalComponent({ )} -
- { - remove(field.name); - }} - /> + +
+ { + remove(field.name); + }} + /> +
-
+
))} diff --git a/client/src/components/parts-order-modal/parts-order-modal.container.jsx b/client/src/components/parts-order-modal/parts-order-modal.container.jsx index 02d2d7614..ad9efeb72 100644 --- a/client/src/components/parts-order-modal/parts-order-modal.container.jsx +++ b/client/src/components/parts-order-modal/parts-order-modal.container.jsx @@ -260,7 +260,7 @@ export function PartsOrderModalContainer({ onCancel={() => toggleModalVisible()} onOk={() => form.submit()} destroyOnClose - width="50%" + width="75%" forceRender > {error ? : null} diff --git a/client/src/components/production-list-columns/production-list-columns.data.js b/client/src/components/production-list-columns/production-list-columns.data.js index a4dcf7c8e..59ea04c3e 100644 --- a/client/src/components/production-list-columns/production-list-columns.data.js +++ b/client/src/components/production-list-columns/production-list-columns.data.js @@ -97,6 +97,19 @@ const r = ({ technician, state }) => { ), }, + { + title: i18n.t("jobs.fields.date_last_contacted"), + dataIndex: "date_last_contacted", + key: "date_last_contacted", + ellipsis: true, + sorter: (a, b) => dateSort(a.date_last_contacted, b.date_last_contacted), + sortOrder: + state.sortedInfo.columnKey === "date_last_contacted" && + state.sortedInfo.order, + render: (text, record) => ( + + ), + }, { title: i18n.t("jobs.fields.scheduled_delivery"), dataIndex: "scheduled_delivery", diff --git a/client/src/components/production-list-columns/production-list-columns.date.component.jsx b/client/src/components/production-list-columns/production-list-columns.date.component.jsx index 46046aba6..51999c288 100644 --- a/client/src/components/production-list-columns/production-list-columns.date.component.jsx +++ b/client/src/components/production-list-columns/production-list-columns.date.component.jsx @@ -1,17 +1,20 @@ import { useMutation } from "@apollo/client"; -import { DatePicker, Dropdown } from "antd"; +import { DatePicker, Dropdown, TimePicker, Button, Card } from "antd"; import moment from "moment"; -import React from "react"; +import React, { useState } from "react"; import { logImEXEvent } from "../../firebase/firebase.utils"; import { UPDATE_JOB } from "../../graphql/jobs.queries"; import { DateFormatter } from "../../utils/DateFormatter"; +import { useTranslation } from "react-i18next"; + const OneCalendarDay = 60 * 60 * 24 * 1000; const Now = new Date(); -export default function ProductionListDate({ record, field }) { +export default function ProductionListDate({ record, field, time }) { const [updateAlert] = useMutation(UPDATE_JOB); - + const [visible, setVisible] = useState(false); + const { t } = useTranslation(); const handleChange = (date) => { logImEXEvent("product_toggle_date", { field }); @@ -25,27 +28,47 @@ export default function ProductionListDate({ record, field }) { }, }).then(() => { if (record.refetch) record.refetch(); + if (!time) { + setVisible(false); + } }); }; return (
e.stopPropagation()}> + e.stopPropagation()} + > e.stopPropagation()} value={(record[field] && moment(record[field])) || null} onChange={handleChange} + format="MM/DD/YYYY" /> -
+ {time && ( + e.stopPropagation()} + value={(record[field] && moment(record[field])) || null} + onChange={handleChange} + format="hh:mm a" + /> + )} + + } >
setVisible(true)} style={{ height: "19px", }} diff --git a/client/src/components/production-list-save-config-button/production-list-save-config-button.component.jsx b/client/src/components/production-list-save-config-button/production-list-save-config-button.component.jsx index 0f7381c84..246177367 100644 --- a/client/src/components/production-list-save-config-button/production-list-save-config-button.component.jsx +++ b/client/src/components/production-list-save-config-button/production-list-save-config-button.component.jsx @@ -66,12 +66,7 @@ export function ProductionListSaveConfigButton({ }; const popMenu = (
-
+ { + if (a.useremail !== currentUser.email) return a; + return { ...a, default_prod_list_view: value }; + }); + }, + }, + }); + }, }); } }; @@ -85,13 +98,18 @@ export function ProductionListTable({ setState(bodyshop.production_config[0].columns.tableState); }; + const assoc = bodyshop.associations.find( + (a) => a.useremail === currentUser.email + ); + const defaultView = assoc && assoc.default_prod_list_view; return (