diff --git a/client/src/components/accounting-payables-table/accounting-payables-table.component.jsx b/client/src/components/accounting-payables-table/accounting-payables-table.component.jsx index fcdcca0b6..260589c2f 100644 --- a/client/src/components/accounting-payables-table/accounting-payables-table.component.jsx +++ b/client/src/components/accounting-payables-table/accounting-payables-table.component.jsx @@ -15,6 +15,7 @@ import { createStructuredSelector } from "reselect"; import { selectBodyshop } from "../../redux/user/user.selectors"; import ExportLogsCountDisplay from "../export-logs-count-display/export-logs-count-display.component"; import BillMarkSelectedExported from "../payable-mark-selected-exported/payable-mark-selected-exported.component"; +import {pageLimit} from "../../utils/config"; const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop, @@ -210,7 +211,7 @@ export function AccountingPayablesTableComponent({ toggleChatVisible()} style={{ cursor: "pointer" }} > - + {t("messaging.labels.messaging")} )} diff --git a/client/src/components/chat-popup/chat-popup.styles.scss b/client/src/components/chat-popup/chat-popup.styles.scss index 398762700..be9a5c0a7 100644 --- a/client/src/components/chat-popup/chat-popup.styles.scss +++ b/client/src/components/chat-popup/chat-popup.styles.scss @@ -13,6 +13,9 @@ height: 100%; } } +.chat-popup-info-icon { + margin-right: 5px; +} @media only screen and (min-width: 992px) { .chat-popup { diff --git a/client/src/components/contract-jobs/contract-jobs.component.jsx b/client/src/components/contract-jobs/contract-jobs.component.jsx index 10abd5b22..d84dd8e2a 100644 --- a/client/src/components/contract-jobs/contract-jobs.component.jsx +++ b/client/src/components/contract-jobs/contract-jobs.component.jsx @@ -4,6 +4,7 @@ import { useTranslation } from "react-i18next"; import { alphaSort } from "../../utils/sorters"; import LoadingSkeleton from "../loading-skeleton/loading-skeleton.component"; import OwnerNameDisplay from "../owner-name-display/owner-name-display.component"; +import {pageLimit} from "../../utils/config"; export default function ContractsJobsComponent({ loading, @@ -175,7 +176,7 @@ export default function ContractsJobsComponent({ loading={loading} pagination={{ position: "top", - defaultPageSize: 10, + defaultPageSize: pageLimit, defaultCurrent: defaultCurrent, }} columns={columns} diff --git a/client/src/components/contracts-list/contracts-list.component.jsx b/client/src/components/contracts-list/contracts-list.component.jsx index fa9439c65..cd25e1e9a 100644 --- a/client/src/components/contracts-list/contracts-list.component.jsx +++ b/client/src/components/contracts-list/contracts-list.component.jsx @@ -13,6 +13,7 @@ import moment from "moment"; import { connect } from "react-redux"; import { createStructuredSelector } from "reselect"; import { selectBodyshop } from "../../redux/user/user.selectors"; +import {pageLimit} from "../../utils/config"; const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop, @@ -209,7 +210,7 @@ export function ContractsList({ }} pagination={{ position: "top", - pageSize: 25, + pageSize: pageLimit, current: parseInt(page || 1), total: total, }} diff --git a/client/src/components/courtesy-car-contract-list/courtesy-car-contract-list.component.jsx b/client/src/components/courtesy-car-contract-list/courtesy-car-contract-list.component.jsx index 705337f21..125033101 100644 --- a/client/src/components/courtesy-car-contract-list/courtesy-car-contract-list.component.jsx +++ b/client/src/components/courtesy-car-contract-list/courtesy-car-contract-list.component.jsx @@ -5,6 +5,7 @@ import { useTranslation } from "react-i18next"; import { Link, useHistory, useLocation } from "react-router-dom"; import { DateFormatter } from "../../utils/DateFormatter"; import { alphaSort } from "../../utils/sorters"; +import {pageLimit} from "../../utils/config"; export default function CourtesyCarContractListComponent({ contracts, @@ -89,7 +90,7 @@ export default function CourtesyCarContractListComponent({ scroll={{ x: true }} pagination={{ position: "top", - pageSize: 25, + pageSize: pageLimit, current: parseInt(page || 1), total: totalContracts, }} diff --git a/client/src/components/courtesy-car-form/courtesy-car-form.component.jsx b/client/src/components/courtesy-car-form/courtesy-car-form.component.jsx index 29edf5243..d5315ed3a 100644 --- a/client/src/components/courtesy-car-form/courtesy-car-form.component.jsx +++ b/client/src/components/courtesy-car-form/courtesy-car-form.component.jsx @@ -34,7 +34,7 @@ export default function CourtesyCarCreateFormComponent({ form, saveLoading }) { {/* */} - - + - - - +
+ + + + + p.mileage !== c.mileage || p.nextservicekm !== c.nextservicekm + } + > + {() => { + const nextservicekm = form.getFieldValue("nextservicekm"); + const mileageOver = + nextservicekm && nextservicekm <= form.getFieldValue("mileage"); + if (mileageOver) + return ( + + + + {t("contracts.labels.cardueforservice")} + + {`${nextservicekm} km`} + + ); + + return <>; + }} + +
- p.mileage !== c.mileage || - p.nextservicedate !== c.nextservicedate || - p.nextservicekm !== c.nextservicekm - } + shouldUpdate={(p, c) => p.nextservicedate !== c.nextservicedate} > {() => { const nextservicedate = form.getFieldValue("nextservicedate"); - const nextservicekm = form.getFieldValue("nextservicekm"); - - const mileageOver = - nextservicekm <= form.getFieldValue("mileage"); - const dueForService = - nextservicedate && moment(nextservicedate).isBefore(moment()); + nextservicedate && + moment(nextservicedate).endOf("day").isSameOrBefore(moment()); - if (mileageOver || dueForService) + if (dueForService) return ( {t("contracts.labels.cardueforservice")} - {`${nextservicekm} km`} {nextservicedate} @@ -282,7 +298,8 @@ export default function CourtesyCarCreateFormComponent({ form, saveLoading }) { {() => { const expires = form.getFieldValue("registrationexpires"); - const dateover = expires && moment(expires).isBefore(moment()); + const dateover = + expires && moment(expires).endOf("day").isBefore(moment()); if (dateover) return ( @@ -317,7 +334,8 @@ export default function CourtesyCarCreateFormComponent({ form, saveLoading }) { {() => { const expires = form.getFieldValue("insuranceexpires"); - const dateover = expires && moment(expires).isBefore(moment()); + const dateover = + expires && moment(expires).endOf("day").isBefore(moment()); if (dateover) return ( diff --git a/client/src/components/csi-response-list-paginated/csi-response-list-paginated.component.jsx b/client/src/components/csi-response-list-paginated/csi-response-list-paginated.component.jsx index e512cca20..f73e35512 100644 --- a/client/src/components/csi-response-list-paginated/csi-response-list-paginated.component.jsx +++ b/client/src/components/csi-response-list-paginated/csi-response-list-paginated.component.jsx @@ -7,6 +7,7 @@ import { Link, useHistory, useLocation } from "react-router-dom"; import { DateFormatter } from "../../utils/DateFormatter"; import { alphaSort } from "../../utils/sorters"; import OwnerNameDisplay from "../owner-name-display/owner-name-display.component"; +import {pageLimit} from "../../utils/config"; export default function CsiResponseListPaginated({ refetch, @@ -106,7 +107,7 @@ export default function CsiResponseListPaginated({ loading={loading} pagination={{ position: "top", - pageSize: 25, + pageSize: pageLimit, current: parseInt(page || 1), total: total, }} diff --git a/client/src/components/dashboard-components/monthly-job-costing/monthly-job-costing.component.jsx b/client/src/components/dashboard-components/monthly-job-costing/monthly-job-costing.component.jsx index dff539d19..c3a69a708 100644 --- a/client/src/components/dashboard-components/monthly-job-costing/monthly-job-costing.component.jsx +++ b/client/src/components/dashboard-components/monthly-job-costing/monthly-job-costing.component.jsx @@ -6,6 +6,7 @@ import { alphaSort } from "../../../utils/sorters"; import LoadingSkeleton from "../../loading-skeleton/loading-skeleton.component"; import Dinero from "dinero.js"; import DashboardRefreshRequired from "../refresh-required.component"; +import {pageLimit} from "../../../utils/config"; export default function DashboardMonthlyJobCosting({ data, ...cardProps }) { const { t } = useTranslation(); @@ -118,7 +119,7 @@ export default function DashboardMonthlyJobCosting({ data, ...cardProps }) {
`${record.InvoiceNumber}${record.Account}`} dataSource={allocationsSummary} diff --git a/client/src/components/dms-allocations-summary/dms-allocations-summary.component.jsx b/client/src/components/dms-allocations-summary/dms-allocations-summary.component.jsx index d244a341c..7c9944149 100644 --- a/client/src/components/dms-allocations-summary/dms-allocations-summary.component.jsx +++ b/client/src/components/dms-allocations-summary/dms-allocations-summary.component.jsx @@ -6,6 +6,7 @@ import { createStructuredSelector } from "reselect"; import { selectBodyshop } from "../../redux/user/user.selectors"; import Dinero from "dinero.js"; import { SyncOutlined } from "@ant-design/icons"; +import {pageLimit} from "../../utils/config"; const mapStateToProps = createStructuredSelector({ //currentUser: selectCurrentUser @@ -94,7 +95,7 @@ export function DmsAllocationsSummary({ socket, bodyshop, jobId, title }) { )}
moment().isAfter(d), - })} - onChange={onChange} - showSecond={false} - minuteStep={15} - onBlur={onBlur} - format="hh:mm a" - {...restProps} + value={value ? moment(value) : null} + {...(onlyFuture && { + disabledDate: (d) => moment().isAfter(d), + })} + onChange={onChange} + showSecond={false} + minuteStep={15} + onBlur={onBlur} + format="hh:mm a" + {...restProps} /> ); diff --git a/client/src/components/inventory-list/inventory-list.component.jsx b/client/src/components/inventory-list/inventory-list.component.jsx index 9baa66de0..1e3bce8d7 100644 --- a/client/src/components/inventory-list/inventory-list.component.jsx +++ b/client/src/components/inventory-list/inventory-list.component.jsx @@ -11,6 +11,7 @@ import { selectBodyshop } from "../../redux/user/user.selectors"; import CurrencyFormatter from "../../utils/CurrencyFormatter"; import InventoryBillRo from "../inventory-bill-ro/inventory-bill-ro.component"; import InventoryLineDelete from "../inventory-line-delete/inventory-line-delete.component"; +import {pageLimit} from "../../utils/config"; const mapStateToProps = createStructuredSelector({ //currentUser: selectCurrentUser bodyshop: selectBodyshop, @@ -213,7 +214,7 @@ export function JobsList({ loading={loading} pagination={{ position: "top", - pageSize: 25, + pageSize: pageLimit, current: parseInt(page || 1), total: total, }} diff --git a/client/src/components/inventory-list/inventory-list.container.jsx b/client/src/components/inventory-list/inventory-list.container.jsx index bb265060f..e98266464 100644 --- a/client/src/components/inventory-list/inventory-list.container.jsx +++ b/client/src/components/inventory-list/inventory-list.container.jsx @@ -11,6 +11,7 @@ import { } from "../../redux/application/application.actions"; import AlertComponent from "../alert/alert.component"; import InventoryListPaginated from "./inventory-list.component"; +import {pageLimit} from "../../utils/config"; const mapStateToProps = createStructuredSelector({ //bodyshop: selectBodyshop, @@ -32,8 +33,8 @@ export function InventoryList({ setBreadcrumbs, setSelectedHeader }) { nextFetchPolicy: "network-only", variables: { search: search || "", - offset: page ? (page - 1) * 25 : 0, - limit: 25, + offset: page ? (page - 1) * pageLimit : 0, + limit: pageLimit, consumedIsNull: showall === "true" ? null : true, order: [ { diff --git a/client/src/components/job-at-change/schedule-event.container.jsx b/client/src/components/job-at-change/schedule-event.container.jsx index 89065f0f7..60abf9c61 100644 --- a/client/src/components/job-at-change/schedule-event.container.jsx +++ b/client/src/components/job-at-change/schedule-event.container.jsx @@ -2,12 +2,16 @@ import { useMutation } from "@apollo/client"; import { notification } from "antd"; import React from "react"; import { useTranslation } from "react-i18next"; +import { useDispatch } from "react-redux"; import { logImEXEvent } from "../../firebase/firebase.utils"; import { CANCEL_APPOINTMENT_BY_ID } from "../../graphql/appointments.queries"; import { UPDATE_JOB } from "../../graphql/jobs.queries"; +import { insertAuditTrail } from "../../redux/application/application.actions"; +import AuditTrailMapping from "../../utils/AuditTrailMappings"; import ScheduleEventComponent from "./schedule-event.component"; export default function ScheduleEventContainer({ bodyshop, event, refetch }) { + const dispatch = useDispatch(); const { t } = useTranslation(); const [cancelAppointment] = useMutation(CANCEL_APPOINTMENT_BY_ID); const [updateJob] = useMutation(UPDATE_JOB); @@ -34,16 +38,24 @@ export default function ScheduleEventContainer({ bodyshop, event, refetch }) { const jobUpdate = await updateJob({ variables: { jobId: event.job.id, - job: { date_scheduled: null, scheduled_in: null, scheduled_completion: null, lost_sale_reason, + date_lost_sale: new Date(), status: bodyshop.md_ro_statuses.default_imported, }, }, }); + if (!jobUpdate.errors) { + dispatch( + insertAuditTrail({ + jobid: event.job.id, + operation: AuditTrailMapping.appointmentcancel(lost_sale_reason), + }) + ); + } if (!!jobUpdate.errors) { notification["error"]({ message: t("jobs.errors.updating", { diff --git a/client/src/components/job-costing-parts-table/job-costing-parts-table.component.jsx b/client/src/components/job-costing-parts-table/job-costing-parts-table.component.jsx index 405fb9bb8..d62f08650 100644 --- a/client/src/components/job-costing-parts-table/job-costing-parts-table.component.jsx +++ b/client/src/components/job-costing-parts-table/job-costing-parts-table.component.jsx @@ -3,6 +3,7 @@ import React, { useState } from "react"; import { useTranslation } from "react-i18next"; import { alphaSort } from "../../utils/sorters"; import Dinero from "dinero.js"; +import {pageLimit} from "../../utils/config"; export default function JobCostingPartsTable({ data, summaryData }) { const [searchText, setSearchText] = useState(""); const [state, setState] = useState({ @@ -98,7 +99,7 @@ export default function JobCostingPartsTable({ data, summaryData }) { x: "50%", //y: "40rem" }} onChange={handleTableChange} - pagination={{ position: "top", defaultPageSize: 50 }} + pagination={{ position: "top", defaultPageSize: pageLimit }} columns={columns} rowKey="id" dataSource={filteredData} 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 bfddbfefc..5ac31da74 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 @@ -13,6 +13,7 @@ import LayoutFormRow from "../layout-form-row/layout-form-row.component"; import { connect } from "react-redux"; import { createStructuredSelector } from "reselect"; import { insertAuditTrail } from "../../redux/application/application.actions"; +import { DateTimeFormat } from "./../../utils/DateFormatter"; const mapStateToProps = createStructuredSelector({ //currentUser: selectCurrentUser @@ -53,7 +54,7 @@ export function JobsAdminDatesChange({ insertAuditTrail, job }) { operation: AuditTrailMapping.admin_jobfieldchange( key, changedAuditFields[key] instanceof moment - ? moment(changedAuditFields[key]).format("MM/DD/YYYY hh:mm a") + ? DateTimeFormat(changedAuditFields[key]) : changedAuditFields[key] ), }); @@ -179,6 +180,12 @@ export function JobsAdminDatesChange({ insertAuditTrail, job }) { + + + diff --git a/client/src/components/jobs-available-table/jobs-available-supplement.estlines.util.js b/client/src/components/jobs-available-table/jobs-available-supplement.estlines.util.js index bcde2eec4..6849609be 100644 --- a/client/src/components/jobs-available-table/jobs-available-supplement.estlines.util.js +++ b/client/src/components/jobs-available-table/jobs-available-supplement.estlines.util.js @@ -1,6 +1,6 @@ -import { GET_ALL_JOBLINES_BY_PK } from "../../graphql/jobs-lines.queries"; import { gql } from "@apollo/client"; import _ from "lodash"; +import { GET_ALL_JOBLINES_BY_PK } from "../../graphql/jobs-lines.queries"; export const GetSupplementDelta = async (client, jobId, newLines) => { const { @@ -50,6 +50,7 @@ export const GetSupplementDelta = async (client, jobId, newLines) => { .reduce((acc, value, idx) => { return acc + generateRemoveQuery(value, idx); }, ""); + //console.log(insertQueries, updateQueries, removeQueries); if ((insertQueries + updateQueries + removeQueries).trim() === "") { return new Promise((resolve, reject) => { diff --git a/client/src/components/jobs-available-table/jobs-available-supplement.headerfields.js b/client/src/components/jobs-available-table/jobs-available-supplement.headerfields.js index 3085f16c4..07e91f8ea 100644 --- a/client/src/components/jobs-available-table/jobs-available-supplement.headerfields.js +++ b/client/src/components/jobs-available-table/jobs-available-supplement.headerfields.js @@ -114,7 +114,7 @@ const headerFields = [ "ins_ct_ph", "ins_ct_phx", "loss_cat", - //ad2 + //AD2 "clmt_ln", "clmt_fn", "clmt_title", @@ -219,7 +219,16 @@ const headerFields = [ "loc_title", "loc_ph", "loc_phx", - "loc_ea" + "loc_ea", + //VEH + "plate_no", + "plate_st", + "v_vin", + "v_model_yr", + "v_make_desc", + "v_model_desc", + "v_options", + "v_color", ]; export default headerFields; diff --git a/client/src/components/jobs-available-table/jobs-available-table.container.jsx b/client/src/components/jobs-available-table/jobs-available-table.container.jsx index 4de0b4ab1..5f6443775 100644 --- a/client/src/components/jobs-available-table/jobs-available-table.container.jsx +++ b/client/src/components/jobs-available-table/jobs-available-table.container.jsx @@ -72,6 +72,8 @@ export function JobsAvailableContainer({ const [selectedJob, setSelectedJob] = useState(null); const [selectedOwner, setSelectedOwner] = useState(null); + const [partsQueueToggle, setPartsQueueToggle] = useState(bodyshop.md_functionality_toggles.parts_queue_toggle); + const [insertLoading, setInsertLoading] = useState(false); const [insertNote] = useMutation(INSERT_NEW_NOTE); @@ -93,6 +95,7 @@ export function JobsAvailableContainer({ logImEXEvent("job_import_new"); setOwnerModalVisible(false); + setInsertLoading(true); const estData = replaceEmpty( lazyData?.available_jobs_by_pk || estDataRaw.data.available_jobs_by_pk @@ -124,7 +127,7 @@ export function JobsAvailableContainer({ let existingVehicles; if (estData.est_data.v_vin) { - //There's vehicle data, need to double check the VIN. + //There's vehicle data, need to double-check the VIN. existingVehicles = await client.query({ query: SEARCH_VEHICLE_BY_VIN, variables: { @@ -147,7 +150,7 @@ export function JobsAvailableContainer({ text: t("jobs.labels.importnote"), }, }, - queued_for_parts: true, + queued_for_parts: partsQueueToggle, ...(existingVehicles && existingVehicles.data.vehicles.length > 0 ? { vehicleid: existingVehicles.data.vehicles[0].id, vehicle: null } : {}), @@ -197,6 +200,8 @@ export function JobsAvailableContainer({ refetch(); setInsertLoading(false); }); + + setPartsQueueToggle(bodyshop.md_functionality_toggles.parts_queue_toggle); } catch (r) { //error while inserting notification["error"]({ @@ -204,10 +209,12 @@ export function JobsAvailableContainer({ }); refetch(); setInsertLoading(false); + setPartsQueueToggle(bodyshop.md_functionality_toggles.parts_queue_toggle); + } }; - //Suplement scenario + //Supplement scenario const onJobFindModalOk = async () => { logImEXEvent("job_import_supplement"); @@ -260,11 +267,14 @@ export function JobsAvailableContainer({ // "0.00" // ), // job_totals: newTotals, - // queued_for_parts: true, + queued_for_parts: partsQueueToggle, }, }, }); - if (CriticalPartsScanning.treatment === "on") { + + setPartsQueueToggle(bodyshop.md_functionality_toggles.parts_queue_toggle); + + if (CriticalPartsScanning.treatment === "on") { CriticalPartsScan(updateResult.data.update_jobs.returning[0].id); } if (updateResult.errors) { @@ -339,12 +349,14 @@ export function JobsAvailableContainer({ const onOwnerModalCancel = () => { setOwnerModalVisible(false); setSelectedOwner(null); + setPartsQueueToggle(bodyshop.md_functionality_toggles.parts_queue_toggle); }; const onJobModalCancel = () => { setJobModalVisible(false); modalSearchState[1](""); setSelectedJob(null); + setPartsQueueToggle(bodyshop.md_functionality_toggles.parts_queue_toggle); }; const addJobAsNew = (record) => { @@ -365,6 +377,8 @@ export function JobsAvailableContainer({ }, [addJobAsSupp, availableJobId, clm_no]); if (error) return ; + + return ( {currentUser.email.includes("@rome.") || currentUser.email.includes("@imex.") ? ( 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 05cd1b289..dcd6fd941 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 @@ -145,6 +145,13 @@ export function JobsDetailDatesComponent({ jobRO, job, bodyshop }) { + + + + ); 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 683574ce8..f69ab433e 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 @@ -18,12 +18,14 @@ import { createStructuredSelector } from "reselect"; import { logImEXEvent } from "../../firebase/firebase.utils"; import { CANCEL_APPOINTMENTS_BY_JOB_ID } from "../../graphql/appointments.queries"; import { DELETE_JOB, UPDATE_JOB, VOID_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"; import { selectBodyshop, selectCurrentUser, } from "../../redux/user/user.selectors"; +import AuditTrailMapping from "../../utils/AuditTrailMappings"; import RbacWrapper from "../rbac-wrapper/rbac-wrapper.component"; import JobsDetailHeaderActionsAddevent from "./jobs-detail-header-actions.addevent"; import AddToProduction from "./jobs-detail-header-actions.addtoproduction.util"; @@ -52,6 +54,8 @@ const mapDispatchToProps = (dispatch) => ({ dispatch(setModalContext({ context: context, modal: "timeTicketTask" })), setCardPaymentContext: (context) => dispatch(setModalContext({ context: context, modal: "cardPayment" })), + insertAuditTrail: ({ jobid, operation }) => + dispatch(insertAuditTrail({ jobid, operation })), }); export function JobsDetailHeaderActions({ @@ -67,6 +71,7 @@ export function JobsDetailHeaderActions({ setTimeTicketContext, setTimeTicketTaskContext, setCardPaymentContext, + insertAuditTrail, }) { const { t } = useTranslation(); const client = useApolloClient(); @@ -161,6 +166,7 @@ export function JobsDetailHeaderActions({ scheduled_in: null, scheduled_completion: null, lost_sale_reason, + date_lost_sale: new Date(), status: bodyshop.md_ro_statuses.default_imported, }, }, @@ -169,6 +175,11 @@ export function JobsDetailHeaderActions({ notification["success"]({ message: t("appointments.successes.canceled"), }); + insertAuditTrail({ + jobid: job.id, + operation: + AuditTrailMapping.appointmentcancel(lost_sale_reason), + }); return; } }} diff --git a/client/src/components/jobs-find-modal/jobs-find-modal.component.jsx b/client/src/components/jobs-find-modal/jobs-find-modal.component.jsx index 330c0e5db..37a88e1ef 100644 --- a/client/src/components/jobs-find-modal/jobs-find-modal.component.jsx +++ b/client/src/components/jobs-find-modal/jobs-find-modal.component.jsx @@ -14,6 +14,8 @@ export default function JobsFindModalComponent({ importOptionsState, modalSearchState, jobsListRefetch, + partsQueueToggle, + setPartsQueueToggle, }) { const { t } = useTranslation(); const [modalSearch, setModalSearch] = modalSearchState; @@ -199,6 +201,12 @@ export default function JobsFindModalComponent({ > {t("jobs.labels.override_header")} + setPartsQueueToggle(e.target.checked)} + > + {t("bodyshop.fields.md_functionality_toggles.parts_queue_toggle")} + ); } diff --git a/client/src/components/jobs-find-modal/jobs-find-modal.container.jsx b/client/src/components/jobs-find-modal/jobs-find-modal.container.jsx index 7bb3591cb..64dc8be9a 100644 --- a/client/src/components/jobs-find-modal/jobs-find-modal.container.jsx +++ b/client/src/components/jobs-find-modal/jobs-find-modal.container.jsx @@ -24,6 +24,8 @@ export default connect( setSelectedJob, importOptionsState, modalSearchState, + partsQueueToggle, + setPartsQueueToggle, ...modalProps }) { const { t } = useTranslation(); @@ -91,6 +93,8 @@ export default connect( jobsListRefetch={jobsList.refetch} jobsList={jobsData} modalSearchState={modalSearchState} + partsQueueToggle={partsQueueToggle} + setPartsQueueToggle={setPartsQueueToggle} /> ) : null} diff --git a/client/src/components/jobs-list-paginated/jobs-list-paginated.component.jsx b/client/src/components/jobs-list-paginated/jobs-list-paginated.component.jsx index 7d332d61f..b5048d0ef 100644 --- a/client/src/components/jobs-list-paginated/jobs-list-paginated.component.jsx +++ b/client/src/components/jobs-list-paginated/jobs-list-paginated.component.jsx @@ -12,6 +12,7 @@ import { selectBodyshop } from "../../redux/user/user.selectors"; import CurrencyFormatter from "../../utils/CurrencyFormatter"; import StartChatButton from "../chat-open-button/chat-open-button.component"; import OwnerNameDisplay from "../owner-name-display/owner-name-display.component"; +import {pageLimit} from "../../utils/config"; const mapStateToProps = createStructuredSelector({ //currentUser: selectCurrentUser bodyshop: selectBodyshop, @@ -33,17 +34,14 @@ export function JobsList({ bodyshop, refetch, loading, jobs, total }) { title: t("jobs.fields.ro_number"), dataIndex: "ro_number", key: "ro_number", - sorter: true, //(a, b) => alphaSort(a.ro_number, b.ro_number), sortOrder: sortcolumn === "ro_number" && sortorder, - render: (text, record) => ( {record.ro_number || t("general.labels.na")} ), }, - { title: t("jobs.fields.owner"), dataIndex: "ownr_ln", @@ -125,7 +123,6 @@ export function JobsList({ bodyshop, refetch, loading, jobs, total }) { title: t("vehicles.fields.plate_no"), dataIndex: "plate_no", key: "plate_no", - ellipsis: true, sorter: true, //(a, b) => alphaSort(a.plate_no, b.plate_no), sortOrder: sortcolumn === "plate_no" && sortorder, @@ -137,7 +134,6 @@ export function JobsList({ bodyshop, refetch, loading, jobs, total }) { title: t("jobs.fields.clm_no"), dataIndex: "clm_no", key: "clm_no", - ellipsis: true, sorter: true, //(a, b) => alphaSort(a.clm_no, b.clm_no), sortOrder: sortcolumn === "clm_no" && sortorder, @@ -259,11 +255,11 @@ export function JobsList({ bodyshop, refetch, loading, jobs, total }) { pagination={ search?.search ? { - pageSize: 25, + pageSize: pageLimit, showSizeChanger: false, } : { - pageSize: 25, + pageSize: pageLimit, current: parseInt(page || 1), total: total, showSizeChanger: false, diff --git a/client/src/components/jobs-list/jobs-list.component.jsx b/client/src/components/jobs-list/jobs-list.component.jsx index e28e21901..fb2e1daa6 100644 --- a/client/src/components/jobs-list/jobs-list.component.jsx +++ b/client/src/components/jobs-list/jobs-list.component.jsx @@ -1,8 +1,8 @@ import { - SyncOutlined, - ExclamationCircleFilled, - PauseCircleOutlined, - BranchesOutlined, + SyncOutlined, + ExclamationCircleFilled, + PauseCircleOutlined, + BranchesOutlined, } from "@ant-design/icons"; import { useQuery } from "@apollo/client"; import { Button, Card, Grid, Input, Space, Table, Tooltip } from "antd"; @@ -22,374 +22,374 @@ import ChatOpenButton from "../chat-open-button/chat-open-button.component"; import OwnerNameDisplay from "../owner-name-display/owner-name-display.component"; const mapStateToProps = createStructuredSelector({ - bodyshop: selectBodyshop, + bodyshop: selectBodyshop, }); export function JobsList({ bodyshop }) { - const searchParams = queryString.parse(useLocation().search); - const { selected } = searchParams; - const selectedBreakpoint = Object.entries(Grid.useBreakpoint()) - .filter((screen) => !!screen[1]) - .slice(-1)[0]; - const { loading, error, data, refetch } = useQuery(QUERY_ALL_ACTIVE_JOBS, { - variables: { - statuses: bodyshop.md_ro_statuses.active_statuses || ["Open", "Open*"], - }, - fetchPolicy: "network-only", - nextFetchPolicy: "network-only", - }); + const searchParams = queryString.parse(useLocation().search); + const { selected } = searchParams; + const selectedBreakpoint = Object.entries(Grid.useBreakpoint()) + .filter((screen) => !!screen[1]) + .slice(-1)[0]; + const { loading, error, data, refetch } = useQuery(QUERY_ALL_ACTIVE_JOBS, { + variables: { + statuses: bodyshop.md_ro_statuses.active_statuses || ["Open", "Open*"], + }, + fetchPolicy: "network-only", + nextFetchPolicy: "network-only", + }); - const [state, setState] = useState({ - sortedInfo: {}, - filteredInfo: { text: "" }, - }); + const [state, setState] = useState({ + sortedInfo: {}, + filteredInfo: { text: "" }, + }); - const { t } = useTranslation(); - const history = useHistory(); - const [searchText, setSearchText] = useState(""); + const { t } = useTranslation(); + const history = useHistory(); + const [searchText, setSearchText] = useState(""); - if (error) return ; + if (error) return ; - const jobs = data - ? searchText === "" - ? data.jobs - : data.jobs.filter( - (j) => - (j.ro_number || "") - .toString() - .toLowerCase() - .includes(searchText.toLowerCase()) || - (j.ownr_co_nm || "") - .toLowerCase() - .includes(searchText.toLowerCase()) || - (j.comments || "") - .toLowerCase() - .includes(searchText.toLowerCase()) || - (j.ownr_fn || "") - .toLowerCase() - .includes(searchText.toLowerCase()) || - (j.ownr_ln || "") - .toLowerCase() - .includes(searchText.toLowerCase()) || - (j.clm_no || "").toLowerCase().includes(searchText.toLowerCase()) || - (j.plate_no || "") - .toLowerCase() - .includes(searchText.toLowerCase()) || - (j.v_model_desc || "") - .toLowerCase() - .includes(searchText.toLowerCase()) || - (j.est_ct_fn || "") - .toLowerCase() - .includes(searchText.toLowerCase()) || - (j.est_ct_ln || "") - .toLowerCase() - .includes(searchText.toLowerCase()) || - (j.v_make_desc || "") - .toLowerCase() - .includes(searchText.toLowerCase()) - ) - : []; + const jobs = data + ? searchText === "" + ? data.jobs + : data.jobs.filter( + (j) => + (j.ro_number || "") + .toString() + .toLowerCase() + .includes(searchText.toLowerCase()) || + (j.ownr_co_nm || "") + .toLowerCase() + .includes(searchText.toLowerCase()) || + (j.comments || "") + .toLowerCase() + .includes(searchText.toLowerCase()) || + (j.ownr_fn || "") + .toLowerCase() + .includes(searchText.toLowerCase()) || + (j.ownr_ln || "") + .toLowerCase() + .includes(searchText.toLowerCase()) || + (j.clm_no || "").toLowerCase().includes(searchText.toLowerCase()) || + (j.plate_no || "") + .toLowerCase() + .includes(searchText.toLowerCase()) || + (j.v_model_desc || "") + .toLowerCase() + .includes(searchText.toLowerCase()) || + (j.est_ct_fn || "") + .toLowerCase() + .includes(searchText.toLowerCase()) || + (j.est_ct_ln || "") + .toLowerCase() + .includes(searchText.toLowerCase()) || + (j.v_make_desc || "") + .toLowerCase() + .includes(searchText.toLowerCase()) + ) + : []; - const handleTableChange = (pagination, filters, sorter) => { - setState({ ...state, filteredInfo: filters, sortedInfo: sorter }); - }; + const handleTableChange = (pagination, filters, sorter) => { + setState({ ...state, filteredInfo: filters, sortedInfo: sorter }); + }; - const handleOnRowClick = (record) => { - if (record) { - if (record.id) { - history.push({ - search: queryString.stringify({ - ...searchParams, - selected: record.id, - }), - }); - } - } - }; + const handleOnRowClick = (record) => { + if (record) { + if (record.id) { + history.push({ + search: queryString.stringify({ + ...searchParams, + selected: record.id, + }), + }); + } + } + }; - const columns = [ - { - title: t("jobs.fields.ro_number"), - dataIndex: "ro_number", - key: "ro_number", - sorter: (a, b) => - parseInt((a.ro_number || "0").replace(/\D/g, "")) - - parseInt((b.ro_number || "0").replace(/\D/g, "")), - sortOrder: - state.sortedInfo.columnKey === "ro_number" && state.sortedInfo.order, + const columns = [ + { + title: t("jobs.fields.ro_number"), + dataIndex: "ro_number", + key: "ro_number", + sorter: (a, b) => + parseInt((a.ro_number || "0").replace(/\D/g, "")) - + parseInt((b.ro_number || "0").replace(/\D/g, "")), + sortOrder: + state.sortedInfo.columnKey === "ro_number" && state.sortedInfo.order, - render: (text, record) => ( - e.stopPropagation()} - > - - {record.ro_number || t("general.labels.na")} - {record.production_vars && record.production_vars.alert ? ( - - ) : null} - {record.suspended && ( - - )} - {record.iouparent && ( - - - - )} - - - ), - }, - { - title: t("jobs.fields.owner"), - dataIndex: "owner", - key: "owner", - ellipsis: true, + render: (text, record) => ( + e.stopPropagation()} + > + + {record.ro_number || t("general.labels.na")} + {record.production_vars && record.production_vars.alert ? ( + + ) : null} + {record.suspended && ( + + )} + {record.iouparent && ( + + + + )} + + + ), + }, + { + title: t("jobs.fields.owner"), + dataIndex: "owner", + key: "owner", + ellipsis: true, - responsive: ["md"], - sorter: (a, b) => alphaSort(a.ownr_ln, b.ownr_ln), - sortOrder: - state.sortedInfo.columnKey === "owner" && state.sortedInfo.order, - render: (text, record) => { - return record.ownerid ? ( - e.stopPropagation()} - > - - - ) : ( - + responsive: ["md"], + sorter: (a, b) => alphaSort(a.ownr_ln, b.ownr_ln), + sortOrder: + state.sortedInfo.columnKey === "owner" && state.sortedInfo.order, + render: (text, record) => { + return record.ownerid ? ( + e.stopPropagation()} + > + + + ) : ( + - ); - }, - }, - { - title: t("jobs.fields.ownr_ph1"), - dataIndex: "ownr_ph1", - key: "ownr_ph1", - ellipsis: true, - responsive: ["md"], - render: (text, record) => ( - - ), - }, - { - title: t("jobs.fields.ownr_ph2"), - dataIndex: "ownr_ph2", - key: "ownr_ph2", - ellipsis: true, - responsive: ["md"], - render: (text, record) => ( - - ), - }, - - { - title: t("jobs.fields.status"), - dataIndex: "status", - key: "status", - ellipsis: true, - - sorter: (a, b) => alphaSort(a.status, b.status), - sortOrder: - state.sortedInfo.columnKey === "status" && state.sortedInfo.order, - filters: - (jobs && - jobs - .map((j) => j.status) - .filter(onlyUnique) - .map((s) => { - return { - text: s || "No Status*", - value: [s], - }; - })) || - [], - onFilter: (value, record) => value.includes(record.status), - }, - - { - title: t("jobs.fields.vehicle"), - dataIndex: "vehicle", - key: "vehicle", - ellipsis: true, - render: (text, record) => { - return record.vehicleid ? ( - e.stopPropagation()} - > - {`${record.v_model_yr || ""} ${record.v_make_desc || ""} ${ - record.v_model_desc || "" - }`} - - ) : ( - {`${record.v_model_yr || ""} ${record.v_make_desc || ""} ${ - record.v_model_desc || "" - }`} - ); - }, - }, - { - title: t("vehicles.fields.plate_no"), - dataIndex: "plate_no", - key: "plate_no", - ellipsis: true, - - responsive: ["md"], - sorter: (a, b) => alphaSort(a.plate_no, b.plate_no), - sortOrder: - state.sortedInfo.columnKey === "plate_no" && state.sortedInfo.order, - }, - { - title: t("jobs.fields.clm_no"), - dataIndex: "clm_no", - key: "clm_no", - ellipsis: true, - responsive: ["md"], - sorter: (a, b) => alphaSort(a.clm_no, b.clm_no), - sortOrder: - state.sortedInfo.columnKey === "clm_no" && state.sortedInfo.order, - render: (text, record) => - `${record.clm_no || ""}${ - record.po_number ? ` (PO: ${record.po_number})` : "" - }`, - }, - { - title: t("jobs.fields.ins_co_nm"), - dataIndex: "ins_co_nm", - key: "ins_co_nm", - ellipsis: true, - filters: - (jobs && - jobs - .map((j) => j.ins_co_nm) - .filter(onlyUnique) - .map((s) => { - return { - text: s, - value: [s], - }; - })) || - [], - onFilter: (value, record) => value.includes(record.ins_co_nm), - responsive: ["md"], - }, - { - title: t("jobs.fields.clm_total"), - dataIndex: "clm_total", - key: "clm_total", - responsive: ["md"], - ellipsis: true, - - sorter: (a, b) => a.clm_total - b.clm_total, - sortOrder: - state.sortedInfo.columnKey === "clm_total" && state.sortedInfo.order, - render: (text, record) => ( - {record.clm_total} - ), - }, - { - title: t("jobs.labels.estimator"), - dataIndex: "jobs.labels.estimator", - key: "jobs.labels.estimator", - ellipsis: true, - responsive: ["xl"], - filterSearch: true, - filters: - (jobs && - jobs - .map((j) => `${j.est_ct_fn || ""} ${j.est_ct_ln || ""}`.trim()) - .filter(onlyUnique) - .map((s) => { - return { - text: s || "N/A", - value: [s], - }; - })) || - [], - onFilter: (value, record) => - value.includes( - `${record.est_ct_fn || ""} ${record.est_ct_ln || ""}`.trim() - ), - render: (text, record) => - `${record.est_ct_fn || ""} ${record.est_ct_ln || ""}`.trim(), - }, - { - title: t("jobs.fields.comment"), - dataIndex: "comment", - key: "comment", - ellipsis: true, - responsive: ["md"], - }, - // { - // title: t("jobs.fields.owner_owing"), - // dataIndex: "owner_owing", - // key: "owner_owing", - // responsive: ["md"], - // render: (text, record) => ( - // {record.owner_owing} - // ), - // }, - ]; - - const scrollMapper = { - xs: true, - sm: true, - md: true, - lg: "100%", - xl: "100%", - xxl: "100%", - }; - - return ( - - - { - setSearchText(e.target.value); - }} - value={searchText} - enterButton - /> - - } - > -
{ - handleOnRowClick(record); - }, - selectedRowKeys: [selected], - type: "radio", - }} - onChange={handleTableChange} - onRow={(record, rowIndex) => { - return { - onClick: (event) => { - handleOnRowClick(record); + ); }, - }; - }} - /> - - ); + }, + { + title: t("jobs.fields.ownr_ph1"), + dataIndex: "ownr_ph1", + key: "ownr_ph1", + ellipsis: true, + responsive: ["md"], + render: (text, record) => ( + + ), + }, + { + title: t("jobs.fields.ownr_ph2"), + dataIndex: "ownr_ph2", + key: "ownr_ph2", + ellipsis: true, + responsive: ["md"], + render: (text, record) => ( + + ), + }, + + { + title: t("jobs.fields.status"), + dataIndex: "status", + key: "status", + ellipsis: true, + + sorter: (a, b) => alphaSort(a.status, b.status), + sortOrder: + state.sortedInfo.columnKey === "status" && state.sortedInfo.order, + filters: + (jobs && + jobs + .map((j) => j.status) + .filter(onlyUnique) + .map((s) => { + return { + text: s || "No Status*", + value: [s], + }; + })) || + [], + onFilter: (value, record) => value.includes(record.status), + }, + + { + title: t("jobs.fields.vehicle"), + dataIndex: "vehicle", + key: "vehicle", + ellipsis: true, + render: (text, record) => { + return record.vehicleid ? ( + e.stopPropagation()} + > + {`${record.v_model_yr || ""} ${record.v_make_desc || ""} ${ + record.v_model_desc || "" + }`} + + ) : ( + {`${record.v_model_yr || ""} ${record.v_make_desc || ""} ${ + record.v_model_desc || "" + }`} + ); + }, + }, + { + title: t("vehicles.fields.plate_no"), + dataIndex: "plate_no", + key: "plate_no", + ellipsis: true, + + responsive: ["md"], + sorter: (a, b) => alphaSort(a.plate_no, b.plate_no), + sortOrder: + state.sortedInfo.columnKey === "plate_no" && state.sortedInfo.order, + }, + { + title: t("jobs.fields.clm_no"), + dataIndex: "clm_no", + key: "clm_no", + ellipsis: true, + responsive: ["md"], + sorter: (a, b) => alphaSort(a.clm_no, b.clm_no), + sortOrder: + state.sortedInfo.columnKey === "clm_no" && state.sortedInfo.order, + render: (text, record) => + `${record.clm_no || ""}${ + record.po_number ? ` (PO: ${record.po_number})` : "" + }`, + }, + { + title: t("jobs.fields.ins_co_nm"), + dataIndex: "ins_co_nm", + key: "ins_co_nm", + ellipsis: true, + filters: + (jobs && + jobs + .map((j) => j.ins_co_nm) + .filter(onlyUnique) + .map((s) => { + return { + text: s, + value: [s], + }; + })) || + [], + onFilter: (value, record) => value.includes(record.ins_co_nm), + responsive: ["md"], + }, + { + title: t("jobs.fields.clm_total"), + dataIndex: "clm_total", + key: "clm_total", + responsive: ["md"], + ellipsis: true, + + sorter: (a, b) => a.clm_total - b.clm_total, + sortOrder: + state.sortedInfo.columnKey === "clm_total" && state.sortedInfo.order, + render: (text, record) => ( + {record.clm_total} + ), + }, + { + title: t("jobs.labels.estimator"), + dataIndex: "jobs.labels.estimator", + key: "jobs.labels.estimator", + ellipsis: true, + responsive: ["xl"], + filterSearch: true, + filters: + (jobs && + jobs + .map((j) => `${j.est_ct_fn || ""} ${j.est_ct_ln || ""}`.trim()) + .filter(onlyUnique) + .map((s) => { + return { + text: s || "N/A", + value: [s], + }; + })) || + [], + onFilter: (value, record) => + value.includes( + `${record.est_ct_fn || ""} ${record.est_ct_ln || ""}`.trim() + ), + render: (text, record) => + `${record.est_ct_fn || ""} ${record.est_ct_ln || ""}`.trim(), + }, + { + title: t("jobs.fields.comment"), + dataIndex: "comment", + key: "comment", + ellipsis: true, + responsive: ["md"], + }, + // { + // title: t("jobs.fields.owner_owing"), + // dataIndex: "owner_owing", + // key: "owner_owing", + // responsive: ["md"], + // render: (text, record) => ( + // {record.owner_owing} + // ), + // }, + ]; + + const scrollMapper = { + xs: true, + sm: true, + md: true, + lg: "100%", + xl: "100%", + xxl: "100%", + }; + + return ( + + + { + setSearchText(e.target.value); + }} + value={searchText} + enterButton + /> + + } + > +
{ + handleOnRowClick(record); + }, + selectedRowKeys: [selected], + type: "radio", + }} + onChange={handleTableChange} + onRow={(record, rowIndex) => { + return { + onClick: (event) => { + handleOnRowClick(record); + }, + }; + }} + /> + + ); } export default connect(mapStateToProps, null)(JobsList); diff --git a/client/src/components/jobs-ready-list/jobs-ready-list.component.jsx b/client/src/components/jobs-ready-list/jobs-ready-list.component.jsx index 678c5e228..fee461df2 100644 --- a/client/src/components/jobs-ready-list/jobs-ready-list.component.jsx +++ b/client/src/components/jobs-ready-list/jobs-ready-list.component.jsx @@ -20,6 +20,7 @@ import { alphaSort } from "../../utils/sorters"; import AlertComponent from "../alert/alert.component"; import ChatOpenButton from "../chat-open-button/chat-open-button.component"; import OwnerNameDisplay from "../owner-name-display/owner-name-display.component"; +import {pageLimit} from "../../utils/config"; const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop, @@ -377,7 +378,7 @@ export function JobsReadyList({ bodyshop }) { >
{t("owners.labels.create_new")} + setPartsQueueToggle(e.target.checked)} + > + {t("bodyshop.fields.md_functionality_toggles.parts_queue_toggle")} + ); } diff --git a/client/src/components/owner-find-modal/owner-find-modal.container.jsx b/client/src/components/owner-find-modal/owner-find-modal.container.jsx index 9f1397ba1..f6c9453d7 100644 --- a/client/src/components/owner-find-modal/owner-find-modal.container.jsx +++ b/client/src/components/owner-find-modal/owner-find-modal.container.jsx @@ -14,6 +14,8 @@ export default function OwnerFindModalContainer({ owner, selectedOwner, setSelectedOwner, + partsQueueToggle, + setPartsQueueToggle, ...modalProps }) { //use owner object to run query and find what possible owners there are. @@ -59,6 +61,8 @@ export default function OwnerFindModalContainer({ selectedOwner={selectedOwner} setSelectedOwner={setSelectedOwner} ownersListLoading={ownersList.loading} + partsQueueToggle={partsQueueToggle} + setPartsQueueToggle={setPartsQueueToggle} ownersList={ ownersList.data && ownersList.data.search_owners ? ownersList.data.search_owners diff --git a/client/src/components/owners-list/owners-list.component.jsx b/client/src/components/owners-list/owners-list.component.jsx index d4c5f7e5c..f0ed2f4c2 100644 --- a/client/src/components/owners-list/owners-list.component.jsx +++ b/client/src/components/owners-list/owners-list.component.jsx @@ -6,6 +6,7 @@ import { useTranslation } from "react-i18next"; import { Link, useHistory, useLocation } from "react-router-dom"; import PhoneFormatter from "../../utils/PhoneFormatter"; import OwnerNameDisplay from "../owner-name-display/owner-name-display.component"; +import {pageLimit} from "../../utils/config"; export default function OwnersListComponent({ loading, @@ -122,7 +123,7 @@ export default function OwnersListComponent({ loading={loading} pagination={{ position: "top", - pageSize: 25, + pageSize: pageLimit, current: parseInt(page || 1), total: total, }} diff --git a/client/src/components/owners-list/owners-list.container.jsx b/client/src/components/owners-list/owners-list.container.jsx index 78db6bf2b..7303c4222 100644 --- a/client/src/components/owners-list/owners-list.container.jsx +++ b/client/src/components/owners-list/owners-list.container.jsx @@ -5,6 +5,7 @@ import AlertComponent from "../alert/alert.component"; import OwnersListComponent from "./owners-list.component"; import queryString from "query-string"; import { useLocation } from "react-router-dom"; +import {pageLimit} from "../../utils/config"; export default function OwnersListContainer() { const searchParams = queryString.parse(useLocation().search); @@ -16,8 +17,8 @@ export default function OwnersListContainer() { nextFetchPolicy: "network-only", variables: { search: search || "", - offset: page ? (page - 1) * 25 : 0, - limit: 25, + offset: page ? (page - 1) * pageLimit : 0, + limit: pageLimit, order: [ { [sortcolumn || "created_at"]: sortorder diff --git a/client/src/components/payments-list-paginated/payment-list-paginated.component.jsx b/client/src/components/payments-list-paginated/payment-list-paginated.component.jsx index 8337c89f8..86ad50cb8 100644 --- a/client/src/components/payments-list-paginated/payment-list-paginated.component.jsx +++ b/client/src/components/payments-list-paginated/payment-list-paginated.component.jsx @@ -18,6 +18,7 @@ import { alphaSort } from "../../utils/sorters"; import CaBcEtfTableModalContainer from "../ca-bc-etf-table-modal/ca-bc-etf-table-modal.container"; import OwnerNameDisplay from "../owner-name-display/owner-name-display.component"; import PrintWrapperComponent from "../print-wrapper/print-wrapper.component"; +import {pageLimit} from "../../utils/config"; const mapStateToProps = createStructuredSelector({ //currentUser: selectCurrentUser @@ -282,11 +283,11 @@ export function PaymentsListPaginated({ pagination={ search?.search ? { - pageSize: 25, + pageSize: pageLimit, showSizeChanger: false, } : { - pageSize: 25, + pageSize: pageLimit, current: parseInt(page || 1), total: total, showSizeChanger: false, diff --git a/client/src/components/production-board-kanban/production-board-kanban.component.jsx b/client/src/components/production-board-kanban/production-board-kanban.component.jsx index 6d9750396..b1061f973 100644 --- a/client/src/components/production-board-kanban/production-board-kanban.component.jsx +++ b/client/src/components/production-board-kanban/production-board-kanban.component.jsx @@ -20,9 +20,9 @@ import ProductionBoardCard from "../production-board-kanban-card/production-boar import ProductionListDetailComponent from "../production-list-detail/production-list-detail.component"; import ProductionBoardKanbanCardSettings from "./production-board-kanban.card-settings.component"; //import "@asseinfo/react-kanban/dist/styles.css"; +import CardColorLegend from "../production-board-kanban-card/production-board-kanban-card-color-legend.component"; import "./production-board-kanban.styles.scss"; import { createBoardData } from "./production-board-kanban.utils.js"; -import CardColorLegend from "../production-board-kanban-card/production-board-kanban-card-color-legend.component"; const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop, technician: selectTechnician, @@ -153,6 +153,18 @@ export function ProductionBoardKanbanComponent({ 0 ) .toFixed(1); + const totalLAB = data + .reduce( + (acc, val) => acc + (val.labhrs?.aggregate?.sum?.mod_lb_hrs || 0), + 0 + ) + .toFixed(1); + const totalLAR = data + .reduce( + (acc, val) => acc + (val.larhrs?.aggregate?.sum?.mod_lb_hrs || 0), + 0 + ) + .toFixed(1); const selectedBreakpoint = Object.entries(Grid.useBreakpoint()) .filter((screen) => !!screen[1]) .slice(-1)[0]; @@ -236,6 +248,14 @@ export function ProductionBoardKanbanComponent({ title={t("dashboard.titles.productionhours")} value={totalHrs} /> + + acc + (val.labhrs?.aggregate?.sum?.mod_lb_hrs || 0), + 0 + ) + .toFixed(1); + const totalLAR = data + .reduce( + (acc, val) => acc + (val.larhrs?.aggregate?.sum?.mod_lb_hrs || 0), + 0 + ) + .toFixed(1); return (
+ + ({ toggleModalVisible: () => dispatch(toggleModalVisible("schedule")), setEmailOptions: (e) => dispatch(setEmailOptions(e)), + insertAuditTrail: ({ jobid, operation }) => + dispatch(insertAuditTrail({ jobid, operation })), }); export function ScheduleJobModalContainer({ @@ -39,6 +44,7 @@ export function ScheduleJobModalContainer({ toggleModalVisible, setEmailOptions, currentUser, + insertAuditTrail, }) { const { visible, context, actions } = scheduleModal; const { jobId, job, previousEvent } = context; @@ -134,6 +140,15 @@ export function ScheduleJobModalContainer({ }, }); + if (!appt.errors) { + insertAuditTrail({ + jobid: job.id, + operation: AuditTrailMapping.appointmentinsert( + DateTimeFormat(values.start) + ), + }); + } + if (!!appt.errors) { notification["error"]({ message: t("appointments.errors.saving", { @@ -155,6 +170,7 @@ export function ScheduleJobModalContainer({ scheduled_in: values.start, scheduled_completion: values.scheduled_completion, lost_sale_reason: null, + date_lost_sale: null, }, }, }); diff --git a/client/src/components/scoreboard-jobs-list/scoreboard-jobs-list.component.jsx b/client/src/components/scoreboard-jobs-list/scoreboard-jobs-list.component.jsx index 593f11ce7..6b1c13ca3 100644 --- a/client/src/components/scoreboard-jobs-list/scoreboard-jobs-list.component.jsx +++ b/client/src/components/scoreboard-jobs-list/scoreboard-jobs-list.component.jsx @@ -10,13 +10,14 @@ import OwnerNameDisplay from "../owner-name-display/owner-name-display.component import ScoreboardEntryEdit from "../scoreboard-entry-edit/scoreboard-entry-edit.component"; import ScoreboardRemoveButton from "../scoreboard-remove-button/scorebard-remove-button.component"; import { SyncOutlined } from "@ant-design/icons"; +import {pageLimit} from "../../utils/config"; export default function ScoreboardJobsList({ scoreBoardlist }) { const { t } = useTranslation(); const [state, setState] = useState({ visible: false, search: "", current: 1, - pageSize: 10, + pageSize: pageLimit, }); const { loading, error, data, refetch } = useQuery( @@ -148,7 +149,7 @@ export default function ScoreboardJobsList({ scoreBoardlist }) { } pagination={{ position: "top", - pageSize: state.pageSize || 10, + pageSize: state.pageSize || pageLimit, current: state.current || 1, total: data ? data.scoreboard_aggregate.aggregate.count : 0, }} diff --git a/client/src/components/scoreboard-timetickets-stats/scoreboard-timetickets.component.jsx b/client/src/components/scoreboard-timetickets-stats/scoreboard-timetickets.component.jsx index d2ced5334..0117279d5 100644 --- a/client/src/components/scoreboard-timetickets-stats/scoreboard-timetickets.component.jsx +++ b/client/src/components/scoreboard-timetickets-stats/scoreboard-timetickets.component.jsx @@ -2,11 +2,9 @@ import { useQuery } from "@apollo/client"; import { Col, Row } from "antd"; import _ from "lodash"; import moment from "moment"; -import queryString from "query-string"; import React, { useMemo } from "react"; import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; -import { useLocation } from "react-router-dom"; import { createStructuredSelector } from "reselect"; import { QUERY_TIME_TICKETS_IN_RANGE_SB } from "../../graphql/timetickets.queries"; import { selectBodyshop } from "../../redux/user/user.selectors"; @@ -31,12 +29,8 @@ export default connect( export function ScoreboardTimeTicketsStats({ bodyshop }) { const { t } = useTranslation(); - const searchParams = queryString.parse(useLocation().search); - const { start, end } = searchParams; - const startDate = start - ? moment(start) - : moment().startOf("week").subtract(7, "days"); - const endDate = end ? moment(end) : moment().endOf("week"); + const startDate = moment().startOf("month") + const endDate = moment().endOf("month"); const fixedPeriods = useMemo(() => { const endOfThisMonth = moment().endOf("month"); diff --git a/client/src/components/shop-info/shop-info.general.component.jsx b/client/src/components/shop-info/shop-info.general.component.jsx index 712c47b05..28bad48e8 100644 --- a/client/src/components/shop-info/shop-info.general.component.jsx +++ b/client/src/components/shop-info/shop-info.general.component.jsx @@ -42,6 +42,7 @@ export function ShopInfoGeneral({ form, bodyshop }) { bodyshop && bodyshop.imexshopid ); + return (