@@ -62,7 +62,17 @@
|
||||
t = d.getElementsByTagName("script")[0];
|
||||
t.parentNode.insertBefore(s, t);
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
window.$crisp = [];
|
||||
window.CRISP_WEBSITE_ID = "36724f62-2eb0-4b29-9cdd-9905fb99913e";
|
||||
(function () {
|
||||
d = document;
|
||||
s = d.createElement("script");
|
||||
s.src = "https://client.crisp.chat/l.js";
|
||||
s.async = 1;
|
||||
d.getElementsByTagName("head")[0].appendChild(s);
|
||||
})();
|
||||
</script>
|
||||
<% } %>
|
||||
<script>
|
||||
!(function () {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import * as Sentry from "@sentry/react";
|
||||
import { Button, Col, Collapse, Result, Row, Space } from "antd";
|
||||
import React from "react";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import { logImEXEvent } from "../../firebase/firebase.utils";
|
||||
import * as Sentry from "@sentry/react";
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { logImEXEvent } from "../../firebase/firebase.utils";
|
||||
import { selectBodyshop, selectCurrentUser } from "../../redux/user/user.selectors";
|
||||
import InstanceRenderManager from "../../utils/instanceRenderMgr";
|
||||
|
||||
@@ -38,28 +38,23 @@ class ErrorBoundary extends React.Component {
|
||||
}
|
||||
|
||||
handleErrorSubmit = () => {
|
||||
InstanceRenderManager({
|
||||
executeFunction: true,
|
||||
args: [],
|
||||
imex: () => {
|
||||
window.$crisp.push([
|
||||
"do",
|
||||
"message:send",
|
||||
[
|
||||
"text",
|
||||
`I hit the following error: \n\n
|
||||
window.$crisp.push([
|
||||
"do",
|
||||
"message:send",
|
||||
[
|
||||
"text",
|
||||
`I hit the following error: \n\n
|
||||
${this.state.error.message}\n\n
|
||||
${this.state.error.stack}\n\n
|
||||
URL:${window.location} as ${this.props.currentUser.email} for ${
|
||||
this.props.bodyshop && this.props.bodyshop.name
|
||||
}
|
||||
`
|
||||
]
|
||||
]);
|
||||
]
|
||||
]);
|
||||
|
||||
window.$crisp.push(["do", "chat:open"]);
|
||||
|
||||
window.$crisp.push(["do", "chat:open"]);
|
||||
}
|
||||
});
|
||||
// const errorDescription = `**Please add relevant details about what you were doing before you encountered this issue**
|
||||
|
||||
// ----
|
||||
|
||||
@@ -656,14 +656,7 @@ function Header({
|
||||
icon: <Icon component={QuestionCircleFilled} />,
|
||||
label: t("menus.header.help"),
|
||||
onClick: () => {
|
||||
window.open(
|
||||
InstanceRenderManager({
|
||||
imex: "https://help.imex.online/",
|
||||
rome: "https://rometech.com//"
|
||||
}),
|
||||
|
||||
"_blank"
|
||||
);
|
||||
window.open("https://help.imex.online/", "_blank");
|
||||
}
|
||||
},
|
||||
...(InstanceRenderManager({
|
||||
|
||||
@@ -4,11 +4,12 @@ import { useSplitTreatments } from "@splitsoftware/splitio-react";
|
||||
import { Button, Card, Dropdown, Form, Input, Modal, Popconfirm, Popover, Select, Space } from "antd";
|
||||
import axios from "axios";
|
||||
import parsePhoneNumber from "libphonenumber-js";
|
||||
import React, { useContext, useMemo, useState } from "react";
|
||||
import { useContext, useMemo, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
import { Link, useNavigate } from "react-router-dom";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import SocketContext from "../../contexts/SocketIO/socketContext.jsx";
|
||||
import { auth, logImEXEvent } from "../../firebase/firebase.utils";
|
||||
import { CANCEL_APPOINTMENTS_BY_JOB_ID, INSERT_MANUAL_APPT } from "../../graphql/appointments.queries";
|
||||
import { GET_CURRENT_QUESTIONSET_ID, INSERT_CSI } from "../../graphql/csi.queries";
|
||||
@@ -30,7 +31,6 @@ import RbacWrapper from "../rbac-wrapper/rbac-wrapper.component";
|
||||
import AddToProduction from "./jobs-detail-header-actions.addtoproduction.util";
|
||||
import DuplicateJob from "./jobs-detail-header-actions.duplicate.util";
|
||||
import JobsDetailHeaderActionsToggleProduction from "./jobs-detail-header-actions.toggle-production";
|
||||
import SocketContext from "../../contexts/SocketIO/socketContext.jsx";
|
||||
import { useNotification } from "../../contexts/Notifications/notificationContext.jsx";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
@@ -121,6 +121,7 @@ export function JobsDetailHeaderActions({
|
||||
const history = useNavigate();
|
||||
const [form] = Form.useForm();
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [dropdownOpen, setDropdownOpen] = useState(false);
|
||||
const [isCancelScheduleModalVisible, setIsCancelScheduleModalVisible] = useState(false);
|
||||
const [insertAppointment] = useMutation(INSERT_MANUAL_APPT);
|
||||
const [deleteJob] = useMutation(DELETE_JOB);
|
||||
@@ -718,7 +719,13 @@ export function JobsDetailHeaderActions({
|
||||
key: "toggleproduction",
|
||||
id: "job-actions-toggleproduction",
|
||||
disabled: !job.converted || jobRO,
|
||||
label: <JobsDetailHeaderActionsToggleProduction job={job} refetch={refetch} />
|
||||
label: (
|
||||
<JobsDetailHeaderActionsToggleProduction
|
||||
job={job}
|
||||
refetch={refetch}
|
||||
closeParentMenu={() => setDropdownOpen(false)}
|
||||
/>
|
||||
)
|
||||
},
|
||||
|
||||
{
|
||||
@@ -1148,7 +1155,7 @@ export function JobsDetailHeaderActions({
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Modal>
|
||||
<Dropdown menu={menu} trigger={["click"]} key="changestatus">
|
||||
<Dropdown menu={menu} trigger={["click"]} key="changestatus" open={dropdownOpen} onOpenChange={setDropdownOpen}>
|
||||
<Button>
|
||||
<span>{t("general.labels.actions")}</span>
|
||||
<DownCircleFilled />
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { useMutation } from "@apollo/client";
|
||||
import { useLazyQuery, useMutation } from "@apollo/client";
|
||||
import { Button, Form, Popover, Space } from "antd";
|
||||
import dayjs from "dayjs";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { JOB_PRODUCTION_TOGGLE } from "../../graphql/jobs.queries";
|
||||
import { GET_JOB_BY_PK_QUICK_INTAKE, JOB_PRODUCTION_TOGGLE } from "../../graphql/jobs.queries";
|
||||
import { insertAuditTrail } from "../../redux/application/application.actions";
|
||||
import { selectJobReadOnly } from "../../redux/application/application.selectors";
|
||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||
@@ -23,16 +23,40 @@ const mapDispatchToProps = (dispatch) => ({
|
||||
insertAuditTrail: ({ jobid, operation }) => dispatch(insertAuditTrail({ jobid, operation }))
|
||||
});
|
||||
|
||||
export function JobsDetailHeaderActionsToggleProduction({ bodyshop, job, jobRO, insertAuditTrail }) {
|
||||
export function JobsDetailHeaderActionsToggleProduction({
|
||||
bodyshop,
|
||||
job,
|
||||
jobRO,
|
||||
refetch,
|
||||
closeParentMenu,
|
||||
insertAuditTrail
|
||||
}) {
|
||||
const [scenario, setScenario] = useState(false);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [popOverVisible, setPopOverVisible] = useState(false);
|
||||
const [mutationUpdateJob] = useMutation(JOB_PRODUCTION_TOGGLE);
|
||||
const { t } = useTranslation();
|
||||
const [form] = Form.useForm();
|
||||
const notification = useNotification();
|
||||
|
||||
const [getJobDetails] = useLazyQuery(GET_JOB_BY_PK_QUICK_INTAKE, {
|
||||
variables: { id: job.id },
|
||||
onCompleted: (data) => {
|
||||
if (data?.jobs_by_pk) {
|
||||
form.setFieldsValue({
|
||||
actual_in: data.jobs_by_pk.actual_in ? data.jobs_by_pk.actual_in : dayjs(),
|
||||
scheduled_completion: data.jobs_by_pk.scheduled_completion,
|
||||
actual_completion: data.jobs_by_pk.actual_completion,
|
||||
scheduled_delivery: data.jobs_by_pk.scheduled_delivery,
|
||||
actual_delivery: data.jobs_by_pk.actual_delivery
|
||||
});
|
||||
}
|
||||
},
|
||||
fetchPolicy: "network-only"
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
//Figure out what scenario were in, populate accodingly
|
||||
//Figure out what scenario were in, populate accordingly
|
||||
if (job && bodyshop) {
|
||||
if (bodyshop.md_ro_statuses.pre_production_statuses.includes(job.status)) {
|
||||
setScenario("pre");
|
||||
@@ -76,24 +100,16 @@ export function JobsDetailHeaderActionsToggleProduction({ bodyshop, job, jobRO,
|
||||
DateTimeFormatterFunction(values.actual_completion)
|
||||
)
|
||||
});
|
||||
setPopOverVisible(false);
|
||||
closeParentMenu();
|
||||
refetch();
|
||||
}
|
||||
setLoading(false);
|
||||
};
|
||||
|
||||
const popMenu = (
|
||||
<div onClick={(e) => e.stopPropagation()}>
|
||||
<Form
|
||||
layout="vertical"
|
||||
form={form}
|
||||
onFinish={handleConvert}
|
||||
initialValues={{
|
||||
actual_in: dayjs(),
|
||||
scheduled_completion: job.scheduled_completion,
|
||||
actual_completion: job.actual_completion,
|
||||
scheduled_deliver: job.scheduled_deliver,
|
||||
actual_delivery: job.actual_delivery
|
||||
}}
|
||||
>
|
||||
<Form layout="vertical" form={form} onFinish={handleConvert}>
|
||||
{scenario === "pre" && (
|
||||
<>
|
||||
<Form.Item
|
||||
@@ -158,7 +174,12 @@ export function JobsDetailHeaderActionsToggleProduction({ bodyshop, job, jobRO,
|
||||
return (
|
||||
<Popover //open={open}
|
||||
content={popMenu}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
open={popOverVisible}
|
||||
onOpenChange={setPopOverVisible}
|
||||
onClick={(e) => {
|
||||
getJobDetails();
|
||||
e.stopPropagation();
|
||||
}}
|
||||
getPopupContainer={(trigger) => trigger.parentNode}
|
||||
trigger="click"
|
||||
>
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { useApolloClient } from "@apollo/client";
|
||||
import { Button, Form, Popover, Space } from "antd";
|
||||
import axios from "axios";
|
||||
import React, { useMemo, useState } from "react";
|
||||
import { useMemo, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { useNotification } from "../../contexts/Notifications/notificationContext.jsx";
|
||||
import { GET_DOC_SIZE_BY_JOB } from "../../graphql/documents.queries";
|
||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||
import JobSearchSelect from "../job-search-select/job-search-select.component";
|
||||
import { useNotification } from "../../contexts/Notifications/notificationContext.jsx";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
bodyshop: selectBodyshop
|
||||
@@ -134,7 +134,7 @@ export function JobsDocumentsGalleryReassign({ bodyshop, galleryImages, callback
|
||||
]}
|
||||
name={"jobid"}
|
||||
>
|
||||
<JobSearchSelect />
|
||||
<JobSearchSelect notExported={false} notInvoiced={false} />
|
||||
</Form.Item>
|
||||
</Form>
|
||||
<Space>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Button, Form, Popover, Space } from "antd";
|
||||
import React, { useState } from "react";
|
||||
import { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
@@ -60,7 +60,7 @@ export function JobsDocumentsLocalGalleryReassign({ bodyshop, jobid, allMedia, g
|
||||
]}
|
||||
name={"jobid"}
|
||||
>
|
||||
<JobSearchSelect />
|
||||
<JobSearchSelect notExported={false} notInvoiced={false}/>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
<Space>
|
||||
|
||||
@@ -2553,3 +2553,16 @@ export const QUERY_JOBS_IN_PRODUCTION = gql`
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export const GET_JOB_BY_PK_QUICK_INTAKE = gql`
|
||||
query GET_JOB_BY_PK_QUICK_INTAKE($id: uuid!) {
|
||||
jobs_by_pk(id: $id) {
|
||||
id
|
||||
actual_in
|
||||
scheduled_completion
|
||||
actual_completion
|
||||
scheduled_delivery
|
||||
actual_delivery
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { DeleteFilled } from "@ant-design/icons";
|
||||
import { DeleteFilled, PrinterFilled } from "@ant-design/icons";
|
||||
import { PageHeader } from "@ant-design/pro-layout";
|
||||
import { useApolloClient, useMutation } from "@apollo/client";
|
||||
import {
|
||||
Alert,
|
||||
@@ -16,32 +17,31 @@ import {
|
||||
Switch,
|
||||
Typography
|
||||
} from "antd";
|
||||
import { PageHeader } from "@ant-design/pro-layout";
|
||||
|
||||
import React, { useState } from "react";
|
||||
import { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
// import { useNavigate } from 'react-router-dom';
|
||||
import { useSplitTreatments } from "@splitsoftware/splitio-react";
|
||||
import Dinero from "dinero.js";
|
||||
import dayjs from "../../utils/day";
|
||||
import { Link } from "react-router-dom";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import DateTimePicker from "../../components/form-date-time-picker/form-date-time-picker.component";
|
||||
import FormsFieldChanged from "../../components/form-fields-changed-alert/form-fields-changed-alert.component";
|
||||
import CurrencyInput from "../../components/form-items-formatted/currency-form-item.component";
|
||||
import JobCloseRoGuardContainer from "../../components/job-close-ro-guard/job-close-ro-guard.container";
|
||||
import JobsScoreboardAdd from "../../components/job-scoreboard-add-button/job-scoreboard-add-button.component";
|
||||
import JobsCloseAutoAllocate from "../../components/jobs-close-auto-allocate/jobs-close-auto-allocate.component";
|
||||
import JobsCloseLines from "../../components/jobs-close-lines/jobs-close-lines.component";
|
||||
import LayoutFormRow from "../../components/layout-form-row/layout-form-row.component";
|
||||
import { useNotification } from "../../contexts/Notifications/notificationContext.jsx";
|
||||
import { generateJobLinesUpdatesForInvoicing } from "../../graphql/jobs-lines.queries";
|
||||
import { UPDATE_JOB } from "../../graphql/jobs.queries";
|
||||
import { insertAuditTrail } from "../../redux/application/application.actions";
|
||||
import { selectJobReadOnly } from "../../redux/application/application.selectors";
|
||||
import { setModalContext } from "../../redux/modals/modals.actions.js";
|
||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||
import AuditTrailMapping from "../../utils/AuditTrailMappings";
|
||||
import JobCloseRoGuardContainer from "../../components/job-close-ro-guard/job-close-ro-guard.container";
|
||||
import { useNotification } from "../../contexts/Notifications/notificationContext.jsx";
|
||||
import dayjs from "../../utils/day";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
bodyshop: selectBodyshop,
|
||||
@@ -49,10 +49,17 @@ const mapStateToProps = createStructuredSelector({
|
||||
});
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
insertAuditTrail: ({ jobid, operation, type }) => dispatch(insertAuditTrail({ jobid, operation, type }))
|
||||
insertAuditTrail: ({ jobid, operation, type }) => dispatch(insertAuditTrail({ jobid, operation, type })),
|
||||
setPrintCenterContext: (context) =>
|
||||
dispatch(
|
||||
setModalContext({
|
||||
context: context,
|
||||
modal: "printCenter"
|
||||
})
|
||||
)
|
||||
});
|
||||
|
||||
export function JobsCloseComponent({ job, bodyshop, jobRO, insertAuditTrail }) {
|
||||
export function JobsCloseComponent({ job, bodyshop, jobRO, insertAuditTrail, setPrintCenterContext }) {
|
||||
const { t } = useTranslation();
|
||||
const [form] = Form.useForm();
|
||||
const client = useApolloClient();
|
||||
@@ -171,7 +178,6 @@ export function JobsCloseComponent({ job, bodyshop, jobRO, insertAuditTrail }) {
|
||||
extra={
|
||||
<Space>
|
||||
<JobsCloseAutoAllocate joblines={job.joblines} form={form} disabled={!!job.date_exported || jobRO} />
|
||||
|
||||
<Popconfirm
|
||||
onConfirm={() => form.submit()}
|
||||
disabled={jobRO}
|
||||
@@ -188,6 +194,21 @@ export function JobsCloseComponent({ job, bodyshop, jobRO, insertAuditTrail }) {
|
||||
<Button disabled={job.date_exported || !jobRO}>{t("jobs.actions.sendtodms")}</Button>
|
||||
</Link>
|
||||
)}
|
||||
<Button
|
||||
onClick={() => {
|
||||
setPrintCenterContext({
|
||||
context: {
|
||||
id: job.id,
|
||||
job: job,
|
||||
type: "job"
|
||||
}
|
||||
});
|
||||
}}
|
||||
key="printing"
|
||||
icon={<PrinterFilled />}
|
||||
>
|
||||
{t("jobs.actions.printCenter")}
|
||||
</Button>
|
||||
<JobsScoreboardAdd job={job} disabled={false} />
|
||||
</Space>
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import {
|
||||
updateCurrentUser
|
||||
} from "../../firebase/firebase.utils";
|
||||
import { QUERY_EULA } from "../../graphql/bodyshop.queries";
|
||||
import cleanAxios from "../../utils/CleanAxios";
|
||||
import client from "../../utils/GraphQLClient";
|
||||
import dayjs from "../../utils/day";
|
||||
import InstanceRenderManager from "../../utils/instanceRenderMgr";
|
||||
@@ -47,7 +48,6 @@ import {
|
||||
validatePasswordResetSuccess
|
||||
} from "./user.actions";
|
||||
import UserActionTypes from "./user.types";
|
||||
import cleanAxios from "../../utils/CleanAxios";
|
||||
|
||||
const fpPromise = FingerprintJS.load();
|
||||
|
||||
@@ -234,16 +234,18 @@ export function* signInSuccessSaga({ payload }) {
|
||||
LogRocket.identify(payload.email);
|
||||
|
||||
try {
|
||||
window.$crisp.push(["set", "user:nickname", [payload.displayName || payload.email]]);
|
||||
window.$crisp.push(["set", "session:segments", [["user"]]]);
|
||||
InstanceRenderManager({
|
||||
executeFunction: true,
|
||||
args: [],
|
||||
imex: () => {
|
||||
window.$crisp.push(["set", "user:nickname", [payload.displayName || payload.email]]);
|
||||
window.$crisp.push(["set", "session:segments", [["user"]]]);
|
||||
window.$crisp.push(["set", "session:segments", [["imex"]]]);
|
||||
},
|
||||
rome: () => {
|
||||
window.$zoho.salesiq.visitor.name(payload.displayName || payload.email);
|
||||
window.$zoho.salesiq.visitor.email(payload.email);
|
||||
window.$crisp.push(["set", "session:segments", [["rome"]]]);
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
|
||||
Reference in New Issue
Block a user