Compare commits

..

1 Commits

Author SHA1 Message Date
Allan Carr
4efa01edd3 IO-3514 Print Center Restrict Financial Group on Tech Station and Fix Drawer Close on Tech Console
Signed-off-by: Allan Carr <allan@imexsystems.ca>
2026-01-23 22:26:22 -08:00
30 changed files with 109 additions and 142 deletions

View File

@@ -169,13 +169,7 @@ export function AccountingPayablesTableComponent({ bodyshop, loading, bills, ref
refetch={refetch}
/>
{bodyshop.accountingconfig && bodyshop.accountingconfig.qbo && <QboAuthorizeComponent />}
<Input
value={state.search}
onChange={handleSearch}
placeholder={t("general.labels.search")}
allowClear
enterButton
/>
<Input value={state.search} onChange={handleSearch} placeholder={t("general.labels.search")} allowClear />
</Space>
}
>

View File

@@ -182,13 +182,7 @@ export function AccountingPayablesTableComponent({ bodyshop, loading, payments,
refetch={refetch}
/>
{bodyshop.accountingconfig && bodyshop.accountingconfig.qbo && <QboAuthorizeComponent />}
<Input
value={state.search}
onChange={handleSearch}
placeholder={t("general.labels.search")}
allowClear
enterButton
/>
<Input value={state.search} onChange={handleSearch} placeholder={t("general.labels.search")} allowClear />
</Space>
}
>

View File

@@ -204,7 +204,6 @@ export function AccountingReceivablesTableComponent({ bodyshop, loading, jobs, r
onChange={handleSearch}
placeholder={t("general.labels.search")}
allowClear
enterButton
/>
</Space>
}

View File

@@ -232,7 +232,6 @@ export function BillsListTableComponent({
e.preventDefault();
setSearchText(e.target.value);
}}
enterButton
/>
</Space>
}

View File

@@ -99,7 +99,6 @@ export default function ContractsCarsComponent({ loading, data, selectedCarId, h
placeholder={t("general.labels.search")}
value={state.search}
onChange={(e) => setState({ ...state, search: e.target.value })}
enterButton
/>
}
>

View File

@@ -123,7 +123,6 @@ export default function ContractsJobsComponent({ loading, data, selectedJob, han
placeholder={t("general.labels.search")}
value={state.search}
onChange={(e) => setState({ ...state, search: e.target.value })}
enterButton
/>
}
>

View File

@@ -164,7 +164,6 @@ export function ContractsList({ bodyshop, loading, contracts, refetch, total, se
const updatedSearch = { ...search, search: value };
history({ search: queryString.stringify(updatedSearch) });
}}
enterButton
/>
</Space>
}

View File

@@ -96,7 +96,6 @@ export default function DashboardMonthlyJobCosting({ data, ...cardProps }) {
e.preventDefault();
setSearchText(e.target.value);
}}
enterButton
/>
</Space>
}

View File

@@ -62,7 +62,6 @@ export function DmsCdkVehicles({ form, job }) {
<Input.Search
onSearch={(val) => callSearch({ variables: { search: val } })}
placeholder={t("general.labels.search")}
enterButton
/>
)}
columns={columns}

View File

@@ -76,7 +76,6 @@ export default function JobCostingPartsTable({ data, summaryData }) {
e.preventDefault();
setSearchText(e.target.value);
}}
enterButton
/>
</Space>
);

View File

@@ -682,7 +682,6 @@ export function JobLinesComponent({
e.preventDefault();
setSearchText(e.target.value);
}}
enterButton
/>
</Space>
}

View File

@@ -136,7 +136,6 @@ export function JobsAvailableScan({ partnerVersion, refetch }) {
onChange={(e) => {
setSearchText(e.currentTarget.value);
}}
enterButton
/>
</Space>
}

View File

@@ -196,16 +196,13 @@ export function JobsAvailableComponent({ bodyshop, loading, data, refetch, addJo
>
{t("general.actions.deleteall")}
</Button>
<Input.Search
placeholder={t("general.labels.search")}
onChange={(e) => {
setSearchText(e.currentTarget.value);
}}
enterButton
/>
<Link to="/manage/jobs/new">
<Button>{t("jobs.actions.manualnew")}</Button>
</Link>
</Space>
}
>

View File

@@ -24,7 +24,7 @@ export default function JobsCreateVehicleInfoPredefined({ disabled, form }) {
<div>
<Table
size="small"
title={() => <Input.Search onSearch={(value) => setSearch(value)} enterButton/>}
title={() => <Input.Search onSearch={(value) => setSearch(value)} />}
dataSource={filteredPredefinedVehicles}
columns={[
{

View File

@@ -48,7 +48,6 @@ export default function OwnerFindModalContainer({
value={searchText}
onChange={(e) => setSearchText(e.target.value)}
onSearch={(val) => callSearchowners({ variables: { search: val.trim() } })}
enterButton
/>
<OwnerFindModalComponent
selectedOwner={selectedOwner}

View File

@@ -101,7 +101,6 @@ export function PartDispatchTableComponent({ bodyshop, job, billsQuery }) {
e.preventDefault();
setSearchText(e.target.value);
}}
enterButton
/>
</Space>
}

View File

@@ -295,7 +295,6 @@ export function PartsOrderListTableComponent({
e.preventDefault();
setSearchText(e.target.value);
}}
enterButton
/>
</Space>
}

View File

@@ -269,7 +269,6 @@ export function PartsQueueListComponent({ bodyshop }) {
return (
<Card
title={t("titles.bc.parts-queue")}
extra={
<Space wrap>
<Button onClick={() => refetch()}>

View File

@@ -129,7 +129,6 @@ function PhoneNumberConsentList({ bodyshop }) {
placeholder={t("general.labels.search")}
onSearch={(value) => setSearch(value)}
style={{ marginBottom: 16 }}
enterButton
/>
<Table

View File

@@ -9,6 +9,7 @@ import { TemplateList } from "../../utils/TemplateConstants";
import { GenerateDocument } from "../../utils/RenderTemplate";
import { useNotification } from "../../contexts/Notifications/notificationContext.jsx";
import { HistoryOutlined, MailOutlined, PrinterOutlined, UnorderedListOutlined } from "@ant-design/icons";
import { bodyshopHasDmsKey } from "../../utils/dmsUtils.js";
const mapStateToProps = createStructuredSelector({
printCenterModal: selectPrintCenter,
@@ -29,27 +30,29 @@ export function PrintCenterJobsPartsComponent({ printCenterModal, bodyshop, tech
names: ["Enhanced_Payroll"],
splitKey: bodyshop.imexshopid
});
const Templates =
bodyshop.cdk_dealerid === null && bodyshop.pbs_serialnumber === null
? Object.keys(tempList)
.map((key) => tempList[key])
.filter(
(temp) =>
(!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) => tempList[key])
.filter(
(temp) =>
!temp.regions ||
const hasDMSKey = bodyshopHasDmsKey(bodyshop);
const Templates = !hasDMSKey
? Object.keys(tempList)
.map((key) => tempList[key])
.filter(
(temp) =>
(!temp.regions ||
temp.regions?.[bodyshop.region_config] ||
(temp.regions && bodyshop.region_config.includes(Object.keys(temp.regions)) === true)
);
(temp.regions && bodyshop.region_config.includes(Object.keys(temp.regions)) === true)) &&
(!temp.dms || temp.dms === false)
)
.filter((temp) => !technician || temp.group !== "financial")
: Object.keys(tempList)
.map((key) => tempList[key])
.filter(
(temp) =>
!temp.regions ||
temp.regions?.[bodyshop.region_config] ||
(temp.regions && bodyshop.region_config.includes(Object.keys(temp.regions)) === true)
)
.filter((temp) => !technician || temp.group !== "financial");
const JobsReportsList =
Enhanced_Payroll.treatment === "on"
? Object.keys(Templates)

View File

@@ -12,15 +12,18 @@ import Jobd3RdPartyModal from "../job-3rd-party-modal/job-3rd-party-modal.compon
import PrintCenterItem from "../print-center-item/print-center-item.component";
import PrintCenterJobsLabels from "../print-center-jobs-labels/print-center-jobs-labels.component";
import PrintCenterSpeedPrint from "../print-center-speed-print/print-center-speed-print.component";
import { bodyshopHasDmsKey } from "../../utils/dmsUtils";
import { selectTechnician } from "../../redux/tech/tech.selectors";
const mapStateToProps = createStructuredSelector({
printCenterModal: selectPrintCenter,
bodyshop: selectBodyshop
bodyshop: selectBodyshop,
technician: selectTechnician
});
const mapDispatchToProps = () => ({});
export function PrintCenterJobsComponent({ printCenterModal, bodyshop }) {
export function PrintCenterJobsComponent({ printCenterModal, bodyshop, technician }) {
const [search, setSearch] = useState("");
const { id: jobId, job } = printCenterModal.context;
const tempList = TemplateList("job", {});
@@ -32,30 +35,33 @@ export function PrintCenterJobsComponent({ printCenterModal, bodyshop }) {
names: ["Enhanced_Payroll"],
splitKey: bodyshop.imexshopid
});
const hasDMSKey = bodyshopHasDmsKey(bodyshop);
const Templates =
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 ||
const Templates = !hasDMSKey
? 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.regions && bodyshop.region_config.includes(Object.keys(temp.regions)) === true)) &&
(!temp.dms || temp.dms === false)
)
.filter((temp) => !technician || temp.group !== "financial")
: 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)
)
.filter((temp) => !technician || temp.group !== "financial");
const JobsReportsList =
Enhanced_Payroll.treatment === "on"
? Object.keys(Templates)

View File

@@ -45,7 +45,6 @@ export function ProductionBoardFilters({ bodyshop, filter, setFilter, loading })
setFilter({ ...filter, search: e.target.value });
logImEXEvent("visual_board_filter_search", { search: e.target.value });
}}
enterButton
/>
<EmployeeSearchSelectComponent
style={{ minWidth: "20rem" }}

View File

@@ -44,7 +44,6 @@ export default function ProfileShopsComponent({ loading, data, updateActiveShop
onChange={(e) => setSearch(e.target.value)}
allowClear
placeholder={t("general.labels.search")}
enterButton
/>
}
>

View File

@@ -145,7 +145,7 @@ export function ReportCenterModalComponent({ reportCenterModal, bodyshop }) {
return (
<div className="report-center-modal">
<Form onFinish={handleFinish} autoComplete={"off"} layout="vertical" form={form}>
<Input.Search onChange={(e) => setSearch(e.target.value)} value={search} enterButton />
<Input.Search onChange={(e) => setSearch(e.target.value)} value={search} />
<Form.Item name="defaultSorters" hidden>
<Input type="hidden" />
</Form.Item>

View File

@@ -3,7 +3,8 @@ import { Button, Form, Input, InputNumber, Select, Space, Switch } from "antd";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import FeatureWrapper from "../feature-wrapper/feature-wrapper.component";
import { selectBodyshop } from "../../redux/user/user.selectors";
import FeatureWrapper, { HasFeatureAccess } from "../feature-wrapper/feature-wrapper.component";
import CurrencyInput from "../form-items-formatted/currency-form-item.component";
import FormItemEmail from "../form-items-formatted/email-form-item.component";
import PhoneFormItem, { PhoneItemFormatterValidation } from "../form-items-formatted/phone-form-item.component";
@@ -11,13 +12,15 @@ import FormListMoveArrows from "../form-list-move-arrows/form-list-move-arrows.c
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
const timeZonesList = Intl.supportedValuesOf("timeZone");
const mapStateToProps = createStructuredSelector({});
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop
});
const mapDispatchToProps = () => ({
//setUserLanguage: language => dispatch(setUserLanguage(language))
});
export default connect(mapStateToProps, mapDispatchToProps)(ShopInfoGeneral);
export function ShopInfoGeneral({ form }) {
export function ShopInfoGeneral({ form, bodyshop }) {
const { t } = useTranslation();
return (
@@ -375,6 +378,34 @@ export function ShopInfoGeneral({ form }) {
>
<Select mode="tags" />
</Form.Item>,
...(HasFeatureAccess({ featureName: "timetickets", bodyshop })
? [
<Form.Item
key="tt_allow_post_to_invoiced"
name={["tt_allow_post_to_invoiced"]}
label={t("bodyshop.fields.tt_allow_post_to_invoiced")}
valuePropName="checked"
>
<Switch />
</Form.Item>,
<Form.Item
key="tt_enforce_hours_for_tech_console"
name={["tt_enforce_hours_for_tech_console"]}
label={t("bodyshop.fields.tt_enforce_hours_for_tech_console")}
valuePropName="checked"
>
<Switch />
</Form.Item>,
<Form.Item
key="bill_allow_post_to_closed"
name={["bill_allow_post_to_closed"]}
label={t("bodyshop.fields.bill_allow_post_to_closed")}
valuePropName="checked"
>
<Switch />
</Form.Item>
]
: []),
<Form.Item
key="md_ded_notes"
name={["md_ded_notes"]}

View File

@@ -313,38 +313,6 @@ export function ShopInfoResponsibilityCenterComponent({ bodyshop, form }) {
>
<Select mode="tags" />
</Form.Item>,
...(HasFeatureAccess({ featureName: "timetickets", bodyshop })
? [
<Form.Item
key="tt_allow_post_to_invoiced"
name={["tt_allow_post_to_invoiced"]}
label={t("bodyshop.fields.tt_allow_post_to_invoiced")}
valuePropName="checked"
>
<Switch />
</Form.Item>,
<Form.Item
key="tt_enforce_hours_for_tech_console"
name={["tt_enforce_hours_for_tech_console"]}
label={t("bodyshop.fields.tt_enforce_hours_for_tech_console")}
valuePropName="checked"
>
<Switch />
</Form.Item>
]
: []),
...(HasFeatureAccess({ featureName: "bills", bodyshop })
? [
<Form.Item
key="bill_allow_post_to_closed"
name={["bill_allow_post_to_closed"]}
label={t("bodyshop.fields.bill_allow_post_to_closed")}
valuePropName="checked"
>
<Switch />
</Form.Item>
]
: []),
...(HasFeatureAccess({ featureName: "export", bodyshop })
? [
...(ClosingPeriod.treatment === "on"

View File

@@ -59,7 +59,8 @@ export function TechLookupJobsDrawer({ bodyshop, setPrintCenterContext }) {
const handleDrawerClose = () => {
// Immutable omit (no delete/mutation)
const { ...rest } = searchParams || {};
const { selected, ...rest } = searchParams || {};
void selected;
history({
search: queryString.stringify(rest)
});
@@ -72,7 +73,6 @@ export function TechLookupJobsDrawer({ bodyshop, setPrintCenterContext }) {
{data ? (
<PageHeader
onBack={() => window.history.back()}
title={data.jobs_by_pk.ro_number || t("general.labels.na")}
extra={
<Button

View File

@@ -181,7 +181,6 @@ export function ExportLogsPageComponent() {
searchParams.search = value;
history({ search: queryString.stringify(searchParams) });
}}
enterButton
/>
</Space>
}

View File

@@ -4,6 +4,7 @@ import { PageHeader } from "@ant-design/pro-layout";
import { useEffect } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { Link } from "react-router-dom";
import { createStructuredSelector } from "reselect";
import AlertComponent from "../../components/alert/alert.component";
import JobsAvailableTableContainer from "../../components/jobs-available-table/jobs-available-table.container";
@@ -24,26 +25,6 @@ const mapDispatchToProps = (dispatch) => ({
export function JobsAvailablePageContainer({ partnerVersion, setBreadcrumbs, setSelectedHeader }) {
const { t } = useTranslation();
const getOS = () => {
const userAgent = navigator.userAgent;
if (userAgent.indexOf("Win") !== -1) return "windows";
if (userAgent.indexOf("Mac") !== -1) return "mac";
if (userAgent.indexOf("Linux") !== -1) return "linux";
return "unknown";
};
const os = getOS();
const downloadUrl = InstanceRenderManager({
imex:
os === "windows"
? "https://imex-partner.s3.ca-central-1.amazonaws.com/imex-partner-x64.exe"
: "https://imex-partner.s3.ca-central-1.amazonaws.com/imex-partner-arm64.dmg",
rome:
os === "windows"
? "https://rome-partner.s3.us-east-2.amazonaws.com/rome-partner-x64.exe"
: "https://rome-partner.s3.us-east-2.amazonaws.com/rome-partner-arm64.dmg"
});
useEffect(() => {
document.title = t("titles.jobsavailable", {
app: InstanceRenderManager({
@@ -58,12 +39,24 @@ export function JobsAvailablePageContainer({ partnerVersion, setBreadcrumbs, set
return (
<RbacWrapper action="jobs:available-list">
<div>
<PageHeader />
<PageHeader
title={t("titles.bc.availablejobs")}
extra={
<Link to="/manage/jobs/new">
<Button>{t("jobs.actions.manualnew")}</Button>
</Link>
}
/>
{!partnerVersion && (
<AlertComponent
type="warning"
action={
<a href={downloadUrl}>
<a
href={InstanceRenderManager({
imex: "https://partner.imex.online/Setup.exe",
rome: "https://partner.romeonline.io/Setup.exe"
})}
>
<Button size="small">{t("general.actions.download")}</Button>
</a>
}

View File

@@ -167,7 +167,6 @@ export function PhonebookPageComponent({ bodyshop, authLevel }) {
searchParams.page = 1;
history({ search: queryString.stringify(searchParams) });
}}
enterButton
/>
</Space>
}