Compare commits

...

18 Commits

Author SHA1 Message Date
Patrick Fic
2be0f3de09 IO-2329 Remove testing statement. 2023-06-07 12:05:55 -07:00
Patrick Fic
b791f9846f IO-2329 Change update alert to be permanent. 2023-06-07 12:03:17 -07:00
Patrick Fic
0669282432 Merged in release/2023-06-02 (pull request #840)
Release/2023 06 02
2023-06-02 20:08:34 +00:00
John Allen Delos Reyes
bf4dc7e158 Merged in feature/IO-2314-problem-job-hyperlink (pull request #835)
IO-2314 Added hyperlink to ro number

Approved-by: Patrick Fic
2023-06-02 15:55:13 +00:00
Allan Carr
5de2036fdb Merged in feature/IO-2316-Predefined-Email-Address-for-CC (pull request #833)
IO-2316 Predefined Email address for CC field

Approved-by: Patrick Fic
2023-06-02 14:37:28 +00:00
Allan Carr
1629663e15 Merged in feature/IO-2315-DMS-Posting-Sheet-Restriction (pull request #832)
IO-2315 DMS Posting Sheet

Approved-by: Patrick Fic
2023-06-02 14:36:32 +00:00
swtmply
e25f2db2b1 IO-2314 Added hyperlink to ro number 2023-06-02 22:27:53 +08:00
Allan Carr
cbf5d268ea IO-2315 DMS Posting Sheet
Restrict to DMS setups only
2023-06-01 20:32:30 -07:00
Patrick Fic
a92a95a9fa Merge branch 'release/2023-06-02' of bitbucket.org:snaptsoft/bodyshop into release/2023-06-02 2023-06-01 18:31:12 -07:00
Patrick Fic
0be7bf2c8e Merge branch 'feature/IO-2310-active-jobs-ro-sort' into release/2023-06-02 2023-06-01 18:29:53 -07:00
Patrick Fic
56b810dd40 IO-2310 Change RO sort. 2023-06-01 18:29:41 -07:00
John Allen Delos Reyes
000ded6649 Merged in feature/IO-2281-table-colors (pull request #829)
IO-2281 Added striped table colors

Approved-by: Patrick Fic
2023-06-01 22:28:30 +00:00
Patrick Fic
72181e1ff7 Add in missing filter for job search select on job clock on. 2023-05-31 14:33:59 -07:00
swtmply
d73b1d2220 IO-2281 Added striped table colors 2023-06-01 02:34:18 +08:00
Allan Carr
8645b434c8 Merged in feature/IO-2299-RBAC-for-Voiding-File (pull request #827)
IO-2299 RBAC for Voiding File

Approved-by: Patrick Fic
2023-05-31 15:30:15 +00:00
Allan Carr
38a13bd082 IO-2299 RBAC for Voiding File 2023-05-30 20:14:33 -07:00
Allan Carr
3bc5f5d626 Merged in feature/IO-2233-CDK-VEHICLE-LICENSE-PLATE (pull request #826)
IO-2233 Check for null and if stripped string is size 0 send null instead

Approved-by: Patrick Fic
2023-05-31 00:33:20 +00:00
Allan Carr
86a2351316 IO-2233 Check for null and if stripped string is size 0 send null instead 2023-05-30 17:23:22 -07:00
24 changed files with 264 additions and 82 deletions

View File

@@ -156,3 +156,11 @@
td.ant-table-column-sort { td.ant-table-column-sort {
background-color: transparent; background-color: transparent;
} }
.ant-table-tbody > tr.ant-table-row:nth-child(2n) > td {
background-color: #f4f4f4;
}
.rowWithColor > td {
background-color: var(--bgColor) !important;
}

View File

@@ -29,6 +29,7 @@ import AddToProduction from "./jobs-detail-header-actions.addtoproduction.util";
import JobsDetaiLheaderCsi from "./jobs-detail-header-actions.csi.component"; import JobsDetaiLheaderCsi from "./jobs-detail-header-actions.csi.component";
import DuplicateJob from "./jobs-detail-header-actions.duplicate.util"; import DuplicateJob from "./jobs-detail-header-actions.duplicate.util";
import JobsDetailHeaderActionsExportcustdataComponent from "./jobs-detail-header-actions.exportcustdata.component"; import JobsDetailHeaderActionsExportcustdataComponent from "./jobs-detail-header-actions.exportcustdata.component";
import RbacWrapper from "../rbac-wrapper/rbac-wrapper.component";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop, bodyshop: selectBodyshop,
@@ -461,54 +462,56 @@ export function JobsDetailHeaderActions({
)} )}
<JobsDetailHeaderActionsAddevent jobid={job.id} /> <JobsDetailHeaderActionsAddevent jobid={job.id} />
{!jobRO && job.converted && ( {!jobRO && job.converted && (
<Menu.Item> <RbacWrapper action="jobs:void" noauth>
<Popconfirm <Menu.Item>
title={t("jobs.labels.voidjob")} <Popconfirm
okText="Yes" title={t("jobs.labels.voidjob")}
cancelText="No" okText="Yes"
onClick={(e) => e.stopPropagation()} cancelText="No"
onConfirm={async () => { onClick={(e) => e.stopPropagation()}
//delete the job. onConfirm={async () => {
const result = await voidJob({ //delete the job.
variables: { const result = await voidJob({
jobId: job.id, variables: {
job: { jobId: job.id,
status: bodyshop.md_ro_statuses.default_void, job: {
voided: true, status: bodyshop.md_ro_statuses.default_void,
scheduled_in: null, voided: true,
scheduled_completion: null, scheduled_in: null,
inproduction: false, scheduled_completion: null,
}, inproduction: false,
note: [
{
jobid: job.id,
created_by: currentUser.email,
audit: true,
text: t("jobs.labels.voidnote"),
}, },
], note: [
}, {
}); jobid: job.id,
created_by: currentUser.email,
audit: true,
text: t("jobs.labels.voidnote"),
},
],
},
});
if (!!!result.errors) { if (!!!result.errors) {
notification["success"]({ notification["success"]({
message: t("jobs.successes.voided"), message: t("jobs.successes.voided"),
}); });
//go back to jobs list. //go back to jobs list.
history.push(`/manage/`); history.push(`/manage/`);
} else { } else {
notification["error"]({ notification["error"]({
message: t("jobs.errors.voiding", { message: t("jobs.errors.voiding", {
error: JSON.stringify(result.errors), error: JSON.stringify(result.errors),
}), }),
}); });
} }
}} }}
getPopupContainer={(trigger) => trigger.parentNode} getPopupContainer={(trigger) => trigger.parentNode}
> >
{t("menus.jobsactions.void")} {t("menus.jobsactions.void")}
</Popconfirm> </Popconfirm>
</Menu.Item> </Menu.Item>
</RbacWrapper>
)} )}
</Menu> </Menu>
); );

View File

@@ -112,7 +112,9 @@ export function JobsList({ bodyshop }) {
title: t("jobs.fields.ro_number"), title: t("jobs.fields.ro_number"),
dataIndex: "ro_number", dataIndex: "ro_number",
key: "ro_number", key: "ro_number",
sorter: (a, b) => alphaSort(a.ro_number, b.ro_number), sorter: (a, b) =>
parseInt((a.ro_number || "0").replace(/\D/g, "")) -
parseInt((b.ro_number || "0").replace(/\D/g, "")),
sortOrder: sortOrder:
state.sortedInfo.columnKey === "ro_number" && state.sortedInfo.order, state.sortedInfo.columnKey === "ro_number" && state.sortedInfo.order,

View File

@@ -23,17 +23,34 @@ export function PrintCenterJobsComponent({ printCenterModal, bodyshop }) {
const { id: jobId, job } = printCenterModal.context; const { id: jobId, job } = printCenterModal.context;
const tempList = TemplateList("job", {}); const tempList = TemplateList("job", {});
const { t } = useTranslation(); const { t } = useTranslation();
const JobsReportsList = Object.keys(tempList)
.map((key) => { const JobsReportsList =
return tempList[key]; bodyshop.cdk_dealerid === null && bodyshop.pbs_serialnumber === null
}) ? Object.keys(tempList)
.filter( .map((key) => {
(temp) => return tempList[key];
!temp.regions || })
(temp.regions && temp.regions[bodyshop.region_config]) || .filter(
(temp.regions && (temp) =>
bodyshop.region_config.includes(Object.keys(temp.regions)) === true) (!temp.regions ||
); (temp.regions && temp.regions[bodyshop.region_config]) ||
(temp.regions &&
bodyshop.region_config.includes(Object.keys(temp.regions)) ===
true)) &&
(!temp.dms || temp.dms === false)
)
: Object.keys(tempList)
.map((key) => {
return tempList[key];
})
.filter(
(temp) =>
!temp.regions ||
(temp.regions && temp.regions[bodyshop.region_config]) ||
(temp.regions &&
bodyshop.region_config.includes(Object.keys(temp.regions)) ===
true)
);
const filteredJobsReportsList = const filteredJobsReportsList =
search !== "" search !== ""

View File

@@ -246,11 +246,21 @@ export function ProductionListTable({
(x) => x.status === record.status (x) => x.status === record.status
); );
if (!color) return null; if (!color) {
if (index % 2 === 0)
return {
style: {
backgroundColor: `rgb(236, 236, 236)`,
},
};
return null;
}
return { return {
className: "rowWithColor",
style: { style: {
backgroundColor: `rgb(${color.color.r},${color.color.g},${color.color.b},${color.color.a})`, "--bgColor": `rgb(${color.color.r},${color.color.g},${color.color.b},${color.color.a})`,
}, },
}; };
}, },

View File

@@ -26,6 +26,8 @@ const ret = {
"jobs:partsqueue": 4, "jobs:partsqueue": 4,
"jobs:checklist-view": 2, "jobs:checklist-view": 2,
"jobs:list-ready": 1, "jobs:list-ready": 1,
"jobs:void": 5,
"bills:enter": 2, "bills:enter": 2,
"bills:view": 2, "bills:view": 2,
"bills:list": 2, "bills:list": 2,

View File

@@ -12,7 +12,8 @@ import "./schedule-calendar.styles.scss";
import JobDetailCards from "../job-detail-cards/job-detail-cards.component"; import JobDetailCards from "../job-detail-cards/job-detail-cards.component";
import { selectProblemJobs } from "../../redux/application/application.selectors"; import { selectProblemJobs } from "../../redux/application/application.selectors";
import { Alert, Collapse } from "antd"; import { Alert, Collapse } from "antd";
import { useTranslation } from "react-i18next"; import { useTranslation, Trans } from "react-i18next";
import { Link } from "react-router-dom";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop, bodyshop: selectBodyshop,
@@ -66,10 +67,21 @@ export function ScheduleCalendarWrapperComponent({
<Alert <Alert
key={problem.id} key={problem.id}
type="error" type="error"
message={t("appointments.labels.dataconsistency", { message={
ro_number: problem.ro_number, <Trans
code: problem.code, i18nKey="appointments.labels.dataconsistency"
})} components={[
<Link
to={`/manage/jobs/${problem.id}`}
target="_blank"
/>,
]}
values={{
ro_number: problem.ro_number,
code: problem.code,
}}
/>
}
/> />
))} ))}
</Collapse.Panel> </Collapse.Panel>
@@ -79,10 +91,18 @@ export function ScheduleCalendarWrapperComponent({
<Alert <Alert
key={problem.id} key={problem.id}
type="error" type="error"
message={t("appointments.labels.dataconsistency", { message={
ro_number: problem.ro_number, <Trans
code: problem.code, i18nKey="appointments.labels.dataconsistency"
})} components={[
<Link to={`/manage/jobs/${problem.id}`} target="_blank" />,
]}
values={{
ro_number: problem.ro_number,
code: problem.code,
}}
/>
}
/> />
)) ))
)} )}

View File

@@ -1,12 +1,12 @@
import { useTreatments } from "@splitsoftware/splitio-react";
import { Form, InputNumber } from "antd"; import { Form, InputNumber } from "antd";
import React from "react"; import React from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
import RbacWrapper from "../rbac-wrapper/rbac-wrapper.component";
import { useTreatments } from "@splitsoftware/splitio-react";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { createStructuredSelector } from "reselect"; import { createStructuredSelector } from "reselect";
import { selectBodyshop } from "../../redux/user/user.selectors"; import { selectBodyshop } from "../../redux/user/user.selectors";
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
import RbacWrapper from "../rbac-wrapper/rbac-wrapper.component";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop, bodyshop: selectBodyshop,
}); });
@@ -316,6 +316,18 @@ export function ShopInfoRbacComponent({ form, bodyshop }) {
> >
<InputNumber /> <InputNumber />
</Form.Item> </Form.Item>
<Form.Item
label={t("bodyshop.fields.rbac.jobs.void")}
rules={[
{
required: true,
//message: t("general.validation.required"),
},
]}
name={["md_rbac", "jobs:void"]}
>
<InputNumber />
</Form.Item>
<Form.Item <Form.Item
label={t("bodyshop.fields.rbac.bills.enter")} label={t("bodyshop.fields.rbac.bills.enter")}
rules={[ rules={[

View File

@@ -33,6 +33,7 @@ export function TechClockInComponent({ form, bodyshop, technician }) {
<JobSearchSelect <JobSearchSelect
convertedOnly={!bodyshop.tt_allow_post_to_invoiced} convertedOnly={!bodyshop.tt_allow_post_to_invoiced}
notExported={!bodyshop.tt_allow_post_to_invoiced} notExported={!bodyshop.tt_allow_post_to_invoiced}
notInvoiced={!bodyshop.tt_allow_post_to_invoiced}
/> />
</Form.Item> </Form.Item>

View File

@@ -0,0 +1,72 @@
import { Alert, Button, Space } from "antd";
import i18n from "i18next";
import React from "react";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { selectUpdateAvailable } from "../../redux/application/application.selectors";
import { AlertOutlined } from "@ant-design/icons";
import { useTranslation } from "react-i18next";
import { setUpdateAvailable } from "../../redux/application/application.actions";
import { store } from "../../redux/store";
import * as serviceWorkerRegistration from "../../serviceWorkerRegistration";
let globalRegistration;
const mapStateToProps = createStructuredSelector({
updateAvailable: selectUpdateAvailable,
});
const mapDispatchToProps = (dispatch) => ({
//setUserLanguage: language => dispatch(setUserLanguage(language))
});
export default connect(mapStateToProps, mapDispatchToProps)(UpdateAlert);
export function UpdateAlert({ updateAvailable }) {
const { t } = useTranslation();
if (!updateAvailable) return null;
return (
<Alert
message={t("general.messages.newversiontitle")}
showIcon
icon={<AlertOutlined />}
description={t("general.messages.newversionmessage")}
closable={false}
type="warning"
action={
<Space flex>
<Button
onClick={async () => {
window.open("https://imex-online.noticeable.news/", "_blank");
}}
>
{i18n.t("general.actions.viewreleasenotes")}
</Button>
<Button
type="primary"
onClick={async () => {
if (globalRegistration && globalRegistration.waiting) {
await globalRegistration.unregister();
// Makes Workbox call skipWaiting()
globalRegistration.waiting.postMessage({
type: "SKIP_WAITING",
});
// Once the service worker is unregistered, we can reload the page to let
// the browser download a fresh copy of our app (invalidating the cache)
window.location.reload();
}
}}
>
{i18n.t("general.actions.refresh")}
</Button>
</Space>
}
/>
);
}
const onServiceWorkerUpdate = (registration) => {
console.log("onServiceWorkerUpdate", registration);
globalRegistration = registration;
store.dispatch(setUpdateAvailable(true));
};
serviceWorkerRegistration.register({ onUpdate: onServiceWorkerUpdate });

View File

@@ -25,6 +25,7 @@ import {
import * as Sentry from "@sentry/react"; import * as Sentry from "@sentry/react";
import "./manage.page.styles.scss"; import "./manage.page.styles.scss";
import UpdateAlert from "../../components/update-alert/update-alert.component";
const ManageRootPage = lazy(() => const ManageRootPage = lazy(() =>
import("../manage-root/manage-root.page.container") import("../manage-root/manage-root.page.container")
@@ -394,6 +395,7 @@ export function Manage({ match, conflict, bodyshop }) {
<> <>
<ChatAffixContainer /> <ChatAffixContainer />
<Layout className="layout-container"> <Layout className="layout-container">
<UpdateAlert />
<HeaderContainer /> <HeaderContainer />
<Content className="content-container"> <Content className="content-container">

View File

@@ -6,7 +6,7 @@ import AlertComponent from "../../components/alert/alert.component";
import LoadingSpinner from "../../components/loading-spinner/loading-spinner.component"; import LoadingSpinner from "../../components/loading-spinner/loading-spinner.component";
import { QUERY_BODYSHOP } from "../../graphql/bodyshop.queries"; import { QUERY_BODYSHOP } from "../../graphql/bodyshop.queries";
import { setBodyshop } from "../../redux/user/user.actions"; import { setBodyshop } from "../../redux/user/user.actions";
import "../../utils/RegisterSw"; //import "../../utils/RegisterSw";
import ManagePage from "./manage.page.component"; import ManagePage from "./manage.page.component";
const mapDispatchToProps = (dispatch) => ({ const mapDispatchToProps = (dispatch) => ({

View File

@@ -12,6 +12,7 @@ import TechSider from "../../components/tech-sider/tech-sider.component";
import { selectTechnician } from "../../redux/tech/tech.selectors"; import { selectTechnician } from "../../redux/tech/tech.selectors";
import FeatureWrapper from "../../components/feature-wrapper/feature-wrapper.component"; import FeatureWrapper from "../../components/feature-wrapper/feature-wrapper.component";
import "./tech.page.styles.scss"; import "./tech.page.styles.scss";
import UpdateAlert from "../../components/update-alert/update-alert.component";
const TimeTicketModalContainer = lazy(() => const TimeTicketModalContainer = lazy(() =>
import("../../components/time-ticket-modal/time-ticket-modal.container") import("../../components/time-ticket-modal/time-ticket-modal.container")
); );
@@ -56,7 +57,9 @@ export function TechPage({ technician, match }) {
<TechSider /> <TechSider />
<Layout> <Layout>
{technician ? null : <Redirect to={`${match.path}/login`} />} {technician ? null : <Redirect to={`${match.path}/login`} />}
<UpdateAlert />
<TechHeader /> <TechHeader />
<Content className="tech-content-container"> <Content className="tech-content-container">
<ErrorBoundary> <ErrorBoundary>
<Suspense <Suspense

View File

@@ -9,7 +9,7 @@ import LoadingSpinner from "../../components/loading-spinner/loading-spinner.com
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { selectBodyshop } from "../../redux/user/user.selectors"; import { selectBodyshop } from "../../redux/user/user.selectors";
import { createStructuredSelector } from "reselect"; import { createStructuredSelector } from "reselect";
import "../../utils/RegisterSw"; //import "../../utils/RegisterSw";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop, bodyshop: selectBodyshop,

View File

@@ -62,3 +62,8 @@ export const setProblemJobs = (problemJobs) => ({
type: ApplicationActionTypes.SET_PROBLEM_JOBS, type: ApplicationActionTypes.SET_PROBLEM_JOBS,
payload: problemJobs, payload: problemJobs,
}); });
export const setUpdateAvailable = (isUpdateAvailable) => ({
type: ApplicationActionTypes.SET_UPDATE_AVAILABLE,
payload: isUpdateAvailable,
});

View File

@@ -3,6 +3,7 @@ import ApplicationActionTypes from "./application.types";
const INITIAL_STATE = { const INITIAL_STATE = {
loading: false, loading: false,
online: true, online: true,
updateAvailable: false,
breadcrumbs: [], breadcrumbs: [],
recentItems: [], recentItems: [],
selectedHeader: "home", selectedHeader: "home",
@@ -18,6 +19,11 @@ const INITIAL_STATE = {
const applicationReducer = (state = INITIAL_STATE, action) => { const applicationReducer = (state = INITIAL_STATE, action) => {
switch (action.type) { switch (action.type) {
case ApplicationActionTypes.SET_UPDATE_AVAILABLE:
return {
...state,
updateAvailable: action.payload,
};
case ApplicationActionTypes.SET_SELECTED_HEADER: case ApplicationActionTypes.SET_SELECTED_HEADER:
return { return {
...state, ...state,

View File

@@ -48,3 +48,7 @@ export const selectProblemJobs = createSelector(
[selectApplication], [selectApplication],
(application) => application.problemJobs (application) => application.problemJobs
); );
export const selectUpdateAvailable = createSelector(
[selectApplication],
(application) => application.updateAvailable
);

View File

@@ -12,5 +12,6 @@ const ApplicationActionTypes = {
SET_ONLINE_STATUS: "SET_ONLINE_STATUS", SET_ONLINE_STATUS: "SET_ONLINE_STATUS",
INSERT_AUDIT_TRAIL: "INSERT_AUDIT_TRAIL", INSERT_AUDIT_TRAIL: "INSERT_AUDIT_TRAIL",
SET_PROBLEM_JOBS: "SET_PROBLEM_JOBS", SET_PROBLEM_JOBS: "SET_PROBLEM_JOBS",
SET_UPDATE_AVAILABLE: "SET_UPDATE_AVAILABLE"
}; };
export default ApplicationActionTypes; export default ApplicationActionTypes;

View File

@@ -49,7 +49,7 @@
"blocked": "Blocked", "blocked": "Blocked",
"cancelledappointment": "Canceled appointment for: ", "cancelledappointment": "Canceled appointment for: ",
"completingjobs": "Completing Jobs", "completingjobs": "Completing Jobs",
"dataconsistency": "{{ro_number}} has a data consistency issue. It may have been excluded for scheduling purposes. CODE: {{code}}.", "dataconsistency": "<0>{{ro_number}}</0> has a data consistency issue. It may have been excluded for scheduling purposes. CODE: {{code}}.",
"expectedjobs": "Expected Jobs in Production: ", "expectedjobs": "Expected Jobs in Production: ",
"expectedprodhrs": "Expected Production Hours:", "expectedprodhrs": "Expected Production Hours:",
"history": "History", "history": "History",
@@ -405,7 +405,8 @@
"list-active": "Jobs -> List Active", "list-active": "Jobs -> List Active",
"list-all": "Jobs -> List All", "list-all": "Jobs -> List All",
"list-ready": "Jobs -> List Ready", "list-ready": "Jobs -> List Ready",
"partsqueue": "Jobs -> Parts Queue" "partsqueue": "Jobs -> Parts Queue",
"void": "Jobs -> Void"
}, },
"owners": { "owners": {
"detail": "Owners -> Detail", "detail": "Owners -> Detail",
@@ -1117,7 +1118,7 @@
}, },
"messages": { "messages": {
"exception": "$t(titles.app) has encountered an error. Please try again. If the problem persists, please submit a support ticket or contact us.", "exception": "$t(titles.app) has encountered an error. Please try again. If the problem persists, please submit a support ticket or contact us.",
"newversionmessage": "Click refresh below to update to the latest available version of ImEX Online. Please make sure all other tabs and windows are closed.", "newversionmessage": "Click refresh to update to the latest available version of ImEX Online. Please make sure all other tabs and windows are closed.",
"newversiontitle": "New version of ImEX Online Available", "newversiontitle": "New version of ImEX Online Available",
"noacctfilepath": "There is no accounting file path set. You will not be able to export any items.", "noacctfilepath": "There is no accounting file path set. You will not be able to export any items.",
"nofeatureaccess": "You do not have access to this feature of ImEX Online. Please contact support to request a license for this feature.", "nofeatureaccess": "You do not have access to this feature of ImEX Online. Please contact support to request a license for this feature.",

View File

@@ -405,7 +405,8 @@
"list-active": "", "list-active": "",
"list-all": "", "list-all": "",
"list-ready": "", "list-ready": "",
"partsqueue": "" "partsqueue": "",
"void": ""
}, },
"owners": { "owners": {
"detail": "", "detail": "",

View File

@@ -405,7 +405,8 @@
"list-active": "", "list-active": "",
"list-all": "", "list-all": "",
"list-ready": "", "list-ready": "",
"partsqueue": "" "partsqueue": "",
"void": ""
}, },
"owners": { "owners": {
"detail": "", "detail": "",

View File

@@ -3,6 +3,7 @@ import { Button, notification, Space } from "antd";
import i18n from "i18next"; import i18n from "i18next";
import React from "react"; import React from "react";
import * as serviceWorkerRegistration from "../serviceWorkerRegistration"; import * as serviceWorkerRegistration from "../serviceWorkerRegistration";
import { store } from "../redux/store";
const onServiceWorkerUpdate = (registration) => { const onServiceWorkerUpdate = (registration) => {
console.log("onServiceWorkerUpdate", registration); console.log("onServiceWorkerUpdate", registration);
@@ -33,6 +34,9 @@ const onServiceWorkerUpdate = (registration) => {
</Button> </Button>
</Space> </Space>
); );
store.dispatch()
notification.open({ notification.open({
icon: <AlertOutlined />, icon: <AlertOutlined />,
message: i18n.t("general.messages.newversiontitle"), message: i18n.t("general.messages.newversiontitle"),

View File

@@ -512,6 +512,7 @@ export const TemplateList = (type, context) => {
key: "dms_posting_sheet", key: "dms_posting_sheet",
disabled: false, disabled: false,
group: "financial", group: "financial",
dms: true,
}, },
} }
: {}), : {}),

View File

@@ -729,9 +729,15 @@ async function InsertDmsVehicle(socket) {
deliveryDate: moment() deliveryDate: moment()
// .tz(socket.JobData.bodyshop.timezone) // .tz(socket.JobData.bodyshop.timezone)
.format("YYYYMMDD"), .format("YYYYMMDD"),
licensePlateNo: String(socket.JobData.plate_no) licensePlateNo:
.replace(/([^\w]|_)/g, "") socket.JobData.plate_no === null
.toUpperCase(), ? null
: String(socket.JobData.plate_no).replace(/([^\w]|_)/g, "")
.length === 0
? null
: String(socket.JobData.plate_no)
.replace(/([^\w]|_)/g, "")
.toUpperCase(),
make: socket.txEnvelope.dms_make, make: socket.txEnvelope.dms_make,
modelAbrev: socket.txEnvelope.dms_model, modelAbrev: socket.txEnvelope.dms_model,
modelYear: socket.JobData.v_model_yr, modelYear: socket.JobData.v_model_yr,