ImEX and App Improvements.

This commit is contained in:
Patrick Fic
2024-03-15 09:29:49 -07:00
parent 7e01f667b3
commit f279fc1e81
16 changed files with 141 additions and 88 deletions

View File

@@ -1,16 +1,17 @@
import Icon, {UploadOutlined} from "@ant-design/icons";
import {useApolloClient} from "@apollo/client";
import {useSplitTreatments} from "@splitsoftware/splitio-react";
import {Alert, Divider, Form, Input, Select, Space, Statistic, Switch, Upload,} from "antd";
import Icon, { UploadOutlined } from "@ant-design/icons";
import { useApolloClient } from "@apollo/client";
import { useSplitTreatments } from "@splitsoftware/splitio-react";
import { Alert, Divider, Form, Input, Select, Space, Statistic, Switch, Upload, } from "antd";
import React, { useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import { MdOpenInNew } from "react-icons/md";
import { connect } from "react-redux";
import { Link } from "react-router-dom";
import { createStructuredSelector } from "reselect";
import { CHECK_BILL_INVOICE_NUMBER } from "../../graphql/bills.queries";
import { selectBodyshop } from "../../redux/user/user.selectors";
import dayjs from "../../utils/day";
import React, {useEffect, useState} from "react";
import {useTranslation} from "react-i18next";
import {MdOpenInNew} from "react-icons/md";
import {connect} from "react-redux";
import {Link} from "react-router-dom";
import {createStructuredSelector} from "reselect";
import {CHECK_BILL_INVOICE_NUMBER} from "../../graphql/bills.queries";
import {selectBodyshop} from "../../redux/user/user.selectors";
import InstanceRenderManager from "../../utils/instanceRenderMgr";
import AlertComponent from "../alert/alert.component";
import BillFormLinesExtended from "../bill-form-lines-extended/bill-form-lines-extended.component";
import FormDatePicker from "../form-date-picker/form-date-picker.component";
@@ -20,8 +21,7 @@ import JobSearchSelect from "../job-search-select/job-search-select.component";
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
import VendorSearchSelect from "../vendor-search-select/vendor-search-select.component";
import BillFormLines from "./bill-form.lines.component";
import {CalculateBillTotal} from "./bill-form.totals.utility";
import InstanceRenderManager from "../../utils/instanceRenderMgr";
import { CalculateBillTotal } from "./bill-form.totals.utility";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
@@ -149,9 +149,9 @@ export function BillFormComponent({
convertedOnly
notExported={false}
onBlur={() => {
if (form.getFieldValue("jobid") !== null) {
if (form.getFieldValue("jobid") !== null && form.getFieldValue("jobid") !== undefined) {
loadLines({variables: {id: form.getFieldValue("jobid")}});
if (form.getFieldValue("vendorid") !== null) {
if (form.getFieldValue("vendorid") !== null && form.getFieldValue("vendorid") !== undefined) {
loadOutstandingReturns({
variables: {
jobId: form.getFieldValue("jobid"),

View File

@@ -62,7 +62,7 @@ export function ChatAffixContainer({bodyshop, chatVisible}) {
SubscribeToTopic();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [bodyshop]);
}, []);
useEffect(() => {
function handleMessage(payload) {

View File

@@ -19,7 +19,6 @@ export default function FormsFieldChanged({form, skipPrompt}) {
style={{margin: 0, padding: 0, minHeight: "unset"}}
>
{() => {
console.log("should update",form.isFieldsTouched())
const errors = form.getFieldsError().filter((e) => e.errors.length > 0);
if (form.isFieldsTouched())
return (

View File

@@ -1,13 +1,13 @@
import {useMutation} from "@apollo/client";
import {Button, Form, notification, Popover, Tooltip} from "antd";
import {t} from "i18next";
import React, {useState} from "react";
import {UPDATE_LINE_PPC} from "../../graphql/jobs-lines.queries";
import { useMutation } from "@apollo/client";
import { Button, Form, notification, Popover, Tooltip } from "antd";
import axios from "axios";
import { t } from "i18next";
import React, { useState } from "react";
import { UPDATE_LINE_PPC } from "../../graphql/jobs-lines.queries";
import CurrencyFormatter from "../../utils/CurrencyFormatter";
import InstanceRenderManager from "../../utils/instanceRenderMgr";
import CurrencyFormItemComponent from "../form-items-formatted/currency-form-item.component";
import JobLineConvertToLabor from "../job-line-convert-to-labor/job-line-convert-to-labor.component";
import axios from "axios";
import InstanceRenderManager from "../../utils/instanceRenderMgr";
export default function JobLinesPartPriceChange({job, line, refetch}) {
const [loading, setLoading] = useState(false);
@@ -54,7 +54,9 @@ export default function JobLinesPartPriceChange({job, line, refetch}) {
}
};
const popcontent = (
const popcontent = InstanceRenderManager({
imex: null,
rome: (
<Form layout="vertical" onFinish={handleFinish} initialValues={{act_price: line.act_price}}>
<Form.Item
name="act_price"
@@ -63,15 +65,18 @@ export default function JobLinesPartPriceChange({job, line, refetch}) {
>
<CurrencyFormItemComponent/>
</Form.Item>
<Button loading={loading} htmlType="primary">
<Button disabled={InstanceRenderManager({imex:true, rome: false, promanager: true})} loading={loading} htmlType="primary">
{t("general.actions.save")}
</Button>
</Form>
);
),
promanager: null
}) ;
return (
<JobLineConvertToLabor jobline={line} job={job}>
<Popover trigger="click" disabled={line.manual_line || InstanceRenderManager({imex:false, rome:true})} content={popcontent}>
<Popover trigger="click"
disabled={true || line.manual_line} content={popcontent}>
<CurrencyFormatter>
{line.db_ref === "900510" || line.db_ref === "900511"
? line.prt_dsmk_m

View File

@@ -8,9 +8,9 @@ import {
SyncOutlined,
WarningFilled,
} from '@ant-design/icons';
import { useMutation } from '@apollo/client';
import { Button, Checkbox, Dropdown, Input, Space, Table, Tag } from 'antd';
import { PageHeader } from '@ant-design/pro-layout';
import { useMutation } from '@apollo/client';
import { Button, Dropdown, Input, Space, Table, Tag } from 'antd';
import axios from 'axios';
import React, { useState } from 'react';
import { useTranslation } from 'react-i18next';
@@ -29,19 +29,19 @@ import JobLinesBillRefernece from '../job-lines-bill-reference/job-lines-bill-re
// import AllocationsAssignmentContainer from "../allocations-assignment/allocations-assignment.container";
// import AllocationsBulkAssignmentContainer from "../allocations-bulk-assignment/allocations-bulk-assignment.container";
// import AllocationsEmployeeLabelContainer from "../allocations-employee-label/allocations-employee-label.container";
import { useSplitTreatments } from '@splitsoftware/splitio-react';
import _ from 'lodash';
import { selectBodyshop } from '../../redux/user/user.selectors';
import dayjs from '../../utils/day';
import { HasFeatureAccess } from '../feature-wrapper/feature-wrapper.component';
import JobCreateIOU from '../job-create-iou/job-create-iou.component';
import JobLineBulkAssignComponent from '../job-line-bulk-assign/job-line-bulk-assign.component';
import JobLineDispatchButton from '../job-line-dispatch-button/job-line-dispatch-button.component';
import JoblineTeamAssignment from '../job-line-team-assignment/job-line-team-assignmnent.component';
import JobSendPartPriceChangeComponent from '../job-send-parts-price-change/job-send-parts-price-change.component';
import PartsOrderModalContainer from '../parts-order-modal/parts-order-modal.container';
import JobLinesExpander from './job-lines-expander.component';
import { selectBodyshop } from '../../redux/user/user.selectors';
import dayjs from '../../utils/day';
import JobLinesPartPriceChange from './job-lines-part-price-change.component';
import JoblineTeamAssignment from '../job-line-team-assignment/job-line-team-assignmnent.component';
import JobLineDispatchButton from '../job-line-dispatch-button/job-line-dispatch-button.component';
import JobLineBulkAssignComponent from '../job-line-bulk-assign/job-line-bulk-assign.component';
import { useSplitTreatments } from '@splitsoftware/splitio-react';
import { HasFeatureAccess } from '../feature-wrapper/feature-wrapper.component';
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
@@ -219,12 +219,12 @@ export function JobLinesComponent({
key: 'part_qty',
},
{
title: t('joblines.fields.tax_part'),
dataIndex: 'tax_part',
key: 'tax_part',
render: (text, record) => <Checkbox checked={record.tax_part} />,
},
// {
// title: t('joblines.fields.tax_part'),
// dataIndex: 'tax_part',
// key: 'tax_part',
// render: (text, record) => <Checkbox checked={record.tax_part} />,
// },
// {
// title: t("joblines.fields.total"),
// dataIndex: "total",

View File

@@ -57,7 +57,7 @@ export function JobLineDispatchButton({
parts_dispatch_lines: {
data: selectedLines.map((l) => ({
joblineid: l.id,
quantity: l.part_qty,
quantity: l.part_qty,
})),
},
},
@@ -65,6 +65,7 @@ export function JobLineDispatchButton({
},
});
if (result.errors) {
console.log("🚀 ~ handleConvert ~ result.errors:", result.errors)
notification.open({
type: "error",
message: t("parts_dispatch.errors.creating", {
@@ -86,6 +87,7 @@ export function JobLineDispatchButton({
}
setVisible(false);
} catch (error) {
console.log("🚀 ~ handleConvert ~ error:", error)
notification.open({
type: "error",
message: t("parts_dispatch.errors.creating", {
@@ -136,7 +138,7 @@ export function JobLineDispatchButton({
<Space wrap>
<Button
type="danger"
danger
onClick={() => form.submit()}
loading={loading}
disabled={selectedLines.length === 0}

View File

@@ -1,11 +1,13 @@
import {useLazyQuery} from "@apollo/client";
import {Select, Space, Tag} from "antd";
import {Select, Space, Spin, Tag} from "antd";
import _ from "lodash";
import React, {forwardRef, useEffect, useState} from "react";
import {useTranslation} from "react-i18next";
import {SEARCH_JOBS_BY_ID_FOR_AUTOCOMPLETE, SEARCH_JOBS_FOR_AUTOCOMPLETE,} from "../../graphql/jobs.queries";
import AlertComponent from "../alert/alert.component";
import {OwnerNameDisplayFunction} from "../owner-name-display/owner-name-display.component";
import { SearchOutlined } from '@ant-design/icons';
import { LoadingOutlined } from '@ant-design/icons';
const {Option} = Select;
@@ -31,7 +33,6 @@ const JobSearchSelect = (
useLazyQuery(SEARCH_JOBS_BY_ID_FOR_AUTOCOMPLETE);
const executeSearch = (v) => {
console.log(v);
if (v && v.variables?.search !== "" && v.variables.search.length >= 2)
callSearch(v);
};
@@ -77,14 +78,15 @@ const JobSearchSelect = (
disabled={disabled}
showSearch
autoFocus
allowClear
allowClear={!loading}
style={{
width: "100%",
}}
filterOption={false}
onSearch={handleSearch}
loading={loading || idLoading}
//notFoundContent={loading ? <LoadingOutlined /> : <Empty />}
//loading={loading || idLoading}
suffixIcon={loading &&<Spin/>}
notFoundContent={loading ? <LoadingOutlined /> : null}
{...restProps}
>
{theOptions
@@ -106,6 +108,7 @@ const JobSearchSelect = (
))
: null}
</Select>
{error ? <AlertComponent message={error.message} type="error"/> : null}
{idError ? (
<AlertComponent message={idError.message} type="error"/>

View File

@@ -117,7 +117,6 @@ export function JobsAvailableContainer({bodyshop, currentUser, insertAuditTrail,
//IO-539 Check for Parts Rate on PAL for SGI use case.
//TODO:AIO Check that the async function is actually waiting before moving on.
await InstanceRenderManager({executeFunction: true,
debug:true,
imex: CheckTaxRates, rome: CheckTaxRatesUSA, promanager: CheckTaxRatesUSA, args: [estData.est_data, bodyshop]})
// }

View File

@@ -153,7 +153,7 @@ function PaymentModalContainer({
}}
afterClose={() => form.resetFields()}
footer={
<span>
<Space>
<Button onClick={handleCancel}>{t("general.actions.cancel")}</Button>
<Button loading={loading} onClick={() => form.submit()}>
{t("general.actions.save")}
@@ -169,7 +169,7 @@ function PaymentModalContainer({
{t("general.actions.saveandnew")}
</Button>
)}
</span>
</Space>
}
>
{!context || (context && !context.id) ? null : (

View File

@@ -1,5 +1,5 @@
import Icon from "@ant-design/icons";
import {Popover} from "antd";
import {Popover, Space} from "antd";
import _ from "lodash";
import dayjs from "../../utils/day";
@@ -135,7 +135,7 @@ export function ScheduleCalendarHeaderComponent({
const LoadComponent = loadData ? (
<div>
<div className="imex-flex-row imex-flex-row__flex-space-around">
<Space align='center'>
<Popover
placement={"bottom"}
content={jobsInPopup}
@@ -155,7 +155,7 @@ export function ScheduleCalendarHeaderComponent({
{(loadData.allHoursOut || 0) && loadData.allHoursOut.toFixed(2)}
</Popover>
<ScheduleCalendarHeaderGraph loadData={loadData}/>
</div>
</Space>
<div>
<ul style={{listStyleType: "none", columns: "2 auto", padding: 0}}>
{Object.keys(ATSToday).map((key, idx) => (

View File

@@ -1,18 +1,13 @@
import { AlertOutlined } from '@ant-design/icons';
import { Alert, Button, Col, Row, Space } from 'antd';
import i18n from 'i18next';
import React from 'react';
import { useTranslation } from 'react-i18next';
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';
import InstanceRenderManager from '../../utils/instanceRenderMgr';
import { useRegisterSW } from 'virtual:pwa-register/react';
let globalRegistration;
import InstanceRenderManager from '../../utils/instanceRenderMgr';
const mapStateToProps = createStructuredSelector({
updateAvailable: selectUpdateAvailable,
@@ -46,7 +41,9 @@ export function UpdateAlert({ updateAvailable }) {
console.log('SW registration error', error);
},
});
console.log(`SW Status => Refresh? ${needRefresh} - offlineReady? ${offlineReady}`);
if (import.meta.env.DEV)
console.log(`SW Status => Refresh? ${needRefresh} - offlineReady? ${offlineReady}`);
if (!needRefresh) return null;
return (

View File

@@ -13,6 +13,7 @@ import {GET_UNACCEPTED_PARTS_DISPATCH} from "../../graphql/parts-dispatch.querie
import {selectTechnician} from "../../redux/tech/tech.selectors";
import {selectBodyshop} from "../../redux/user/user.selectors";
import {alphaSort} from "../../utils/sorters";
import { useSplitTreatments } from "@splitsoftware/splitio-react";
const mapStateToProps = createStructuredSelector({
//currentUser: selectCurrentUser
@@ -25,6 +26,12 @@ export function TechDispatchedParts({technician, bodyshop}) {
const searchParams = queryString.parse(useLocation().search);
const {page} = searchParams;
const {treatments: {Enhanced_Payroll}} = useSplitTreatments({
attributes: {},
names: ["Enhanced_Payroll"],
splitKey: bodyshop.imexshopid,
});
const {loading, error, data, refetch} = useQuery(
GET_UNACCEPTED_PARTS_DISPATCH,
{
@@ -73,7 +80,7 @@ export function TechDispatchedParts({technician, bodyshop}) {
} ${record.job.v_model_desc || ""}`}</span>
),
},
{
...Enhanced_Payroll.treatment=== 'on' ? [ {
title: t("general.labels.actions"),
dataIndex: "actions",
key: "actions",
@@ -83,7 +90,9 @@ export function TechDispatchedParts({technician, bodyshop}) {
{t("timetickets.actions.claimtasks")}
</Button>
),
},
},] : []
];
const handleTableChange = (pagination, filters, sorter) => {
searchParams.page = pagination.current;

View File

@@ -220,24 +220,26 @@ export function* signInSuccessSaga({payload}) {
LogRocket.identify(payload.email);
try {
InstanceRenderManager({
executeFunction: true,
imex: () => {
window.$crisp.push([
"set",
"user:nickname",
[payload.displayName || payload.email],
]);
window.$crisp.push(["set", "session:segments", [["user"]]]);
} })
Sentry.setUser({
email: payload.email,
username: payload.displayName || payload.email,
});
InstanceRenderManager({
executeFunction: true,
args:[],
imex: () => {
window.$crisp.push(['set', 'user:nickname', [payload.displayName || payload.email]]);
window.$crisp.push(['set', 'session:segments', [['user']]]);
},
});
} catch (error) {
console.log("Error updating Crisp settings.", error);
console.log('Error updating Crisp settings.', error);
}
try {
Sentry.setUser({
email: payload.email,
username: payload.displayName || payload.email,
});
} catch (error) {
console.log('Error setting Sentry user.', error);
}
setUserId(analytics, payload.email);

View File

@@ -2342,7 +2342,7 @@
"associatedbills": "This parts order cannot",
"backordering": "Error backordering part {{message}}.",
"creating": "Error encountered when creating parts order. ",
"oec": "Error creating EMS files for OEC. {{error}}",
"oec": "Error creating EMS files for parts order. {{error}}",
"saving": "Error saving parts order. {{error}}.",
"updating": "Error updating parts order/parts order line. {{error}}."
},
@@ -2379,7 +2379,7 @@
"mark_as_received": "Mark as Received?",
"newpartsorder": "New Parts Order",
"notyetordered": "This part has not yet been ordered.",
"oec": "Order via OEC",
"oec": "Order via EMS",
"order_type": "Order Type",
"orderhistory": "Order History",
"parts_order": "Parts Order",

View File

@@ -20,7 +20,7 @@ i18n
//lng: "en",
detection: {},
fallbackLng: 'en-US',
debug: import.meta.env.PROD ? false : true,
debug: import.meta.env.DEV,
//keySeparator: false, // we do not use keys in form messages.welcome
interpolation: {
escapeValue: false, // react already safes from xss

View File

@@ -0,0 +1,37 @@
import { useEffect, useRef } from 'react';
const usePrevious = (value, initialValue) => {
const ref = useRef(initialValue);
useEffect(() => {
ref.current = value;
});
return ref.current;
};
const useEffectDebugger = (effectHook, dependencies, dependencyNames = []) => {
const previousDeps = usePrevious(dependencies, []);
const changedDeps = dependencies.reduce((accum, dependency, index) => {
if (dependency !== previousDeps[index]) {
const keyName = dependencyNames[index] || index;
return {
...accum,
[keyName]: {
before: previousDeps[index],
after: dependency,
},
};
}
return accum;
}, {});
if (Object.keys(changedDeps).length) {
console.log('[use-effect-debugger] ', changedDeps);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
useEffect(effectHook, dependencies);
};
export default useEffectDebugger;