diff --git a/client/src/App/App.styles.scss b/client/src/App/App.styles.scss
index 2ed11cbc6..b57e94677 100644
--- a/client/src/App/App.styles.scss
+++ b/client/src/App/App.styles.scss
@@ -156,3 +156,11 @@
td.ant-table-column-sort {
background-color: transparent;
}
+
+.ant-table-tbody > tr.ant-table-row:nth-child(2n) > td {
+ background-color: #f4f4f4;
+}
+
+.rowWithColor > td {
+ background-color: var(--bgColor) !important;
+}
diff --git a/client/src/components/email-overlay/email-overlay.component.jsx b/client/src/components/email-overlay/email-overlay.component.jsx
index 7db03471d..362d973b4 100644
--- a/client/src/components/email-overlay/email-overlay.component.jsx
+++ b/client/src/components/email-overlay/email-overlay.component.jsx
@@ -1,28 +1,28 @@
import { UploadOutlined, UserAddOutlined } from "@ant-design/icons";
import {
+ Button,
Divider,
+ Dropdown,
Form,
Input,
+ Menu,
Select,
+ Space,
Tabs,
Upload,
- Space,
- Menu,
- Dropdown,
- Button,
} from "antd";
+import _ from "lodash";
import React from "react";
import { useTranslation } from "react-i18next";
-import EmailDocumentsComponent from "../email-documents/email-documents.component";
-import _ from "lodash";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
+import { selectEmailConfig } from "../../redux/email/email.selectors";
import {
selectBodyshop,
selectCurrentUser,
} from "../../redux/user/user.selectors";
import { CreateExplorerLinkForJob } from "../../utils/localmedia";
-import { selectEmailConfig } from "../../redux/email/email.selectors";
+import EmailDocumentsComponent from "../email-documents/email-documents.component";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
@@ -54,6 +54,15 @@ export function EmailOverlayComponent({
]),
});
};
+ const handle_CC_Click = ({ item, key, keyPath }) => {
+ const email = item.props.value;
+ form.setFieldsValue({
+ cc: _.uniq([
+ ...(form.getFieldValue("cc") || ""),
+ ...(typeof email === "string" ? [email] : email),
+ ]),
+ });
+ };
const menu = (
@@ -74,6 +83,25 @@ export function EmailOverlayComponent({
);
+ const menuCC = (
+
+
+
+ );
+
return (
-
+
+ {t("emails.fields.cc")}
+
+ e.preventDefault()}
+ >
+
+
+
+
+ }
+ name="cc"
+ >
{
+const EmployeeSearchSelect = ({ options, ...props }) => {
const { t } = useTranslation();
return (
@@ -39,4 +39,4 @@ const EmployeeSearchSelect = ({ options, ...props }, ref) => {
);
};
-export default forwardRef(EmployeeSearchSelect);
+export default EmployeeSearchSelect;
diff --git a/client/src/components/header/header.component.jsx b/client/src/components/header/header.component.jsx
index ee70e08cd..ecb12a1a4 100644
--- a/client/src/components/header/header.component.jsx
+++ b/client/src/components/header/header.component.jsx
@@ -262,11 +262,13 @@ function Header({
{t("menus.header.timetickets")}
- }>
-
- {t("menus.header.ttapprovals")}
-
-
+ {bodyshop?.md_tasks_presets?.use_approvals && (
+ }>
+
+ {t("menus.header.ttapprovals")}
+
+
+ )}
}
diff --git a/client/src/components/jobs-detail-header-actions/jobs-detail-header-actions.component.jsx b/client/src/components/jobs-detail-header-actions/jobs-detail-header-actions.component.jsx
index fb5c352bc..edb3f7dde 100644
--- a/client/src/components/jobs-detail-header-actions/jobs-detail-header-actions.component.jsx
+++ b/client/src/components/jobs-detail-header-actions/jobs-detail-header-actions.component.jsx
@@ -29,6 +29,7 @@ import AddToProduction from "./jobs-detail-header-actions.addtoproduction.util";
import JobsDetaiLheaderCsi from "./jobs-detail-header-actions.csi.component";
import DuplicateJob from "./jobs-detail-header-actions.duplicate.util";
import JobsDetailHeaderActionsExportcustdataComponent from "./jobs-detail-header-actions.exportcustdata.component";
+import RbacWrapper from "../rbac-wrapper/rbac-wrapper.component";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
@@ -250,21 +251,24 @@ export function JobsDetailHeaderActions({
>
{t("timetickets.actions.enter")}
- {
- setTimeTicketTaskContext({
- actions: {},
- context: { jobid: job.id },
- });
- }}
- >
- {t("timetickets.actions.claimtasks")}
-
+ {bodyshop.md_tasks_presets.enable_tasks && (
+ {
+ setTimeTicketTaskContext({
+ actions: {},
+ context: { jobid: job.id },
+ });
+ }}
+ >
+ {t("timetickets.actions.claimtasks")}
+
+ )}
+
{!jobRO && job.converted && (
-
- e.stopPropagation()}
- onConfirm={async () => {
- //delete the job.
- const result = await voidJob({
- variables: {
- jobId: job.id,
- job: {
- status: bodyshop.md_ro_statuses.default_void,
- voided: true,
- scheduled_in: null,
- scheduled_completion: null,
- inproduction: false,
- },
- note: [
- {
- jobid: job.id,
- created_by: currentUser.email,
- audit: true,
- text: t("jobs.labels.voidnote"),
+
+
+ e.stopPropagation()}
+ onConfirm={async () => {
+ //delete the job.
+ const result = await voidJob({
+ variables: {
+ jobId: job.id,
+ job: {
+ status: bodyshop.md_ro_statuses.default_void,
+ voided: true,
+ scheduled_in: null,
+ scheduled_completion: null,
+ inproduction: false,
},
- ],
- },
- });
+ note: [
+ {
+ jobid: job.id,
+ created_by: currentUser.email,
+ audit: true,
+ text: t("jobs.labels.voidnote"),
+ },
+ ],
+ },
+ });
- if (!!!result.errors) {
- notification["success"]({
- message: t("jobs.successes.voided"),
- });
- //go back to jobs list.
- history.push(`/manage/`);
- } else {
- notification["error"]({
- message: t("jobs.errors.voiding", {
- error: JSON.stringify(result.errors),
- }),
- });
- }
- }}
- getPopupContainer={(trigger) => trigger.parentNode}
- >
- {t("menus.jobsactions.void")}
-
-
+ if (!!!result.errors) {
+ notification["success"]({
+ message: t("jobs.successes.voided"),
+ });
+ //go back to jobs list.
+ history.push(`/manage/`);
+ } else {
+ notification["error"]({
+ message: t("jobs.errors.voiding", {
+ error: JSON.stringify(result.errors),
+ }),
+ });
+ }
+ }}
+ getPopupContainer={(trigger) => trigger.parentNode}
+ >
+ {t("menus.jobsactions.void")}
+
+
+
)}
);
diff --git a/client/src/components/print-center-jobs/print-center-jobs.component.jsx b/client/src/components/print-center-jobs/print-center-jobs.component.jsx
index c96e3d3a5..ddb9a247d 100644
--- a/client/src/components/print-center-jobs/print-center-jobs.component.jsx
+++ b/client/src/components/print-center-jobs/print-center-jobs.component.jsx
@@ -23,17 +23,34 @@ export function PrintCenterJobsComponent({ printCenterModal, bodyshop }) {
const { id: jobId, job } = printCenterModal.context;
const tempList = TemplateList("job", {});
const { t } = useTranslation();
- const JobsReportsList = 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 JobsReportsList =
+ bodyshop.cdk_dealerid === null && bodyshop.pbs_serialnumber === null
+ ? 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)) &&
+ (!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 =
search !== ""
diff --git a/client/src/components/production-list-table/production-list-table.component.jsx b/client/src/components/production-list-table/production-list-table.component.jsx
index 746d956ab..1585c6480 100644
--- a/client/src/components/production-list-table/production-list-table.component.jsx
+++ b/client/src/components/production-list-table/production-list-table.component.jsx
@@ -246,11 +246,21 @@ export function ProductionListTable({
(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 {
+ className: "rowWithColor",
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})`,
},
};
},
diff --git a/client/src/components/rbac-wrapper/rbac-defaults.js b/client/src/components/rbac-wrapper/rbac-defaults.js
index 1c2a779c4..24a564872 100644
--- a/client/src/components/rbac-wrapper/rbac-defaults.js
+++ b/client/src/components/rbac-wrapper/rbac-defaults.js
@@ -26,6 +26,8 @@ const ret = {
"jobs:partsqueue": 4,
"jobs:checklist-view": 2,
"jobs:list-ready": 1,
+ "jobs:void": 5,
+
"bills:enter": 2,
"bills:view": 2,
"bills:list": 2,
diff --git a/client/src/components/schedule-calendar-wrapper/scheduler-calendar-wrapper.component.jsx b/client/src/components/schedule-calendar-wrapper/scheduler-calendar-wrapper.component.jsx
index 837f5cbbe..7cd90bd14 100644
--- a/client/src/components/schedule-calendar-wrapper/scheduler-calendar-wrapper.component.jsx
+++ b/client/src/components/schedule-calendar-wrapper/scheduler-calendar-wrapper.component.jsx
@@ -12,7 +12,8 @@ import "./schedule-calendar.styles.scss";
import JobDetailCards from "../job-detail-cards/job-detail-cards.component";
import { selectProblemJobs } from "../../redux/application/application.selectors";
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({
bodyshop: selectBodyshop,
@@ -66,10 +67,21 @@ export function ScheduleCalendarWrapperComponent({
,
+ ]}
+ values={{
+ ro_number: problem.ro_number,
+ code: problem.code,
+ }}
+ />
+ }
/>
))}
@@ -79,10 +91,18 @@ export function ScheduleCalendarWrapperComponent({
,
+ ]}
+ values={{
+ ro_number: problem.ro_number,
+ code: problem.code,
+ }}
+ />
+ }
/>
))
)}
diff --git a/client/src/components/shop-info/shop-info.rbac.component.jsx b/client/src/components/shop-info/shop-info.rbac.component.jsx
index 315d1f5dd..50301561a 100644
--- a/client/src/components/shop-info/shop-info.rbac.component.jsx
+++ b/client/src/components/shop-info/shop-info.rbac.component.jsx
@@ -1,12 +1,12 @@
+import { useTreatments } from "@splitsoftware/splitio-react";
import { Form, InputNumber } from "antd";
import React from "react";
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 { createStructuredSelector } from "reselect";
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({
bodyshop: selectBodyshop,
});
@@ -316,6 +316,18 @@ export function ShopInfoRbacComponent({ form, bodyshop }) {
>
+
+
+
-
- {(fields, { add, remove, move }) => {
- return (
-
+ );
+ }}
+
+
+ >
);
}
diff --git a/client/src/components/tech-job-clock-in-form/tech-job-clock-in-form.component.jsx b/client/src/components/tech-job-clock-in-form/tech-job-clock-in-form.component.jsx
index 6c9f357e8..77bc795a8 100644
--- a/client/src/components/tech-job-clock-in-form/tech-job-clock-in-form.component.jsx
+++ b/client/src/components/tech-job-clock-in-form/tech-job-clock-in-form.component.jsx
@@ -33,6 +33,7 @@ export function TechClockInComponent({ form, bodyshop, technician }) {
diff --git a/client/src/components/time-ticket-list/time-ticket-list.component.jsx b/client/src/components/time-ticket-list/time-ticket-list.component.jsx
index 6cc2e3e3d..8f5cbba90 100644
--- a/client/src/components/time-ticket-list/time-ticket-list.component.jsx
+++ b/client/src/components/time-ticket-list/time-ticket-list.component.jsx
@@ -205,16 +205,15 @@ export function TimeTicketList({
}
},
},
- {
- title: "Pay",
- dataIndex: "pay",
- key: "pay",
- render: (text, record) =>
- Dinero({ amount: Math.round(record.rate * 100) })
- .multiply(record.flat_rate ? record.productivehrs : record.actualhrs)
- .toFormat("$0.00"),
- },
-
+ // {
+ // title: "Pay",
+ // dataIndex: "pay",
+ // key: "pay",
+ // render: (text, record) =>
+ // Dinero({ amount: Math.round(record.rate * 100) })
+ // .multiply(record.flat_rate ? record.productivehrs : record.actualhrs)
+ // .toFormat("$0.00"),
+ // },
{
title: t("general.labels.actions"),
dataIndex: "actions",
@@ -282,16 +281,18 @@ export function TimeTicketList({
// context={{ jobId: jobId }}
// />
}
-
+ {bodyshop.md_tasks_presets.enable_tasks && (
+
+ )}
{jobId &&
(techConsole ? null : (
{emps &&
emps.rates.map((item) => (
@@ -73,7 +74,7 @@ export function TimeTicketModalComponent({
);
};
@@ -127,7 +128,7 @@ export function TimeTicketModalComponent({
]}
>
{
const emps =
@@ -279,6 +280,7 @@ export function TimeTicketModalComponent({
-