ES Cleanup
This commit is contained in:
@@ -86,7 +86,7 @@ async function ScrubEstimate({ job }) {
|
||||
});
|
||||
}
|
||||
|
||||
const fileName = `RPSTest-${job.id}-${Date.now()}`;
|
||||
const fileName = `RPS-Scrub-${job.id}-${job.clm_no}-${Date.now()}`;
|
||||
|
||||
// Write job object to logs subfolder
|
||||
try {
|
||||
@@ -110,22 +110,23 @@ async function ScrubEstimate({ job }) {
|
||||
|
||||
const resultPDFUrl = result?.data?.report_link
|
||||
|
||||
log.log("Estimate Scrubber Result:", result.data, resultPDFUrl);
|
||||
// log.log("Estimate Scrubber Result:", result.data, resultPDFUrl);
|
||||
const b = BrowserWindow.getAllWindows()[0];
|
||||
b.webContents.send(ipcTypes.app.toRenderer.scrubResults, {
|
||||
jobid: job.id,
|
||||
items: result.data?.identified_item
|
||||
items: result.data?.identified_item,
|
||||
pdfUrl: resultPDFUrl
|
||||
});
|
||||
|
||||
const pdfWindow = new BrowserWindow({
|
||||
// const pdfWindow = new BrowserWindow({
|
||||
|
||||
webPreferences: {
|
||||
plugins: true, // Enable PDF viewing
|
||||
},
|
||||
});
|
||||
// webPreferences: {
|
||||
// plugins: true, // Enable PDF viewing
|
||||
// },
|
||||
// });
|
||||
|
||||
pdfWindow.loadURL(resultPDFUrl);
|
||||
pdfWindow.focus();
|
||||
// pdfWindow.loadURL(resultPDFUrl);
|
||||
// pdfWindow.focus();
|
||||
return resultPDFUrl
|
||||
}
|
||||
exports.ScrubEstimate = ScrubEstimate
|
||||
@@ -3,7 +3,7 @@
|
||||
"productName": "ImEX RPS",
|
||||
"author": "ImEX Systems Inc. <support@thinkimex.com>",
|
||||
"description": "ImEX RPS",
|
||||
"version": "1.4.2-alpha.10",
|
||||
"version": "1.4.2-alpha.11",
|
||||
"main": "electron/main.js",
|
||||
"homepage": "./",
|
||||
"dependencies": {
|
||||
|
||||
@@ -37,6 +37,22 @@ export function EstimateScrubberButton({ bodyshop, jobid, job }) {
|
||||
const result = await ipcRenderer.invoke(ipcTypes.app.toMain.scrubEstimate, {
|
||||
job: jobData.data.jobs_by_pk
|
||||
});
|
||||
|
||||
message.success("Estimate scrubbed successfully! ");
|
||||
// Scroll to the estimate scrubber results section
|
||||
const scrollToResults = () => {
|
||||
const element = document.getElementById("es-results-card");
|
||||
if (element) {
|
||||
element.scrollIntoView({
|
||||
behavior: "smooth",
|
||||
block: "start",
|
||||
inline: "nearest"
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// Small delay to ensure DOM is updated before scrolling
|
||||
setTimeout(scrollToResults, 100);
|
||||
} catch (error) {
|
||||
message.error("Error scrubbing estimate: " + error.message);
|
||||
console.error("Error scrubbing estimate:", error);
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import { InfoCircleOutlined, LinkOutlined, SearchOutlined } from "@ant-design/icons";
|
||||
import { Badge, Collapse, Input, Space, Table, Tag, Typography } from "antd";
|
||||
import { Badge, Button, Collapse, Input, Result, Space, Table, Tag, Typography } from "antd";
|
||||
import _ from "lodash";
|
||||
import { useState } from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { selectEsResults } from "../../../redux/application/application.selectors";
|
||||
import { selectBodyshop } from "../../../redux/user/user.selectors";
|
||||
import EstimateScrubberButton from "../estimate-scrubber-button/estimate-scrubber-button.molecule";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
//currentUser: selectCurrentUser
|
||||
@@ -24,8 +25,8 @@ export function EstimateScrubberResults({ bodyshop, jobid, job, esResults }) {
|
||||
const [searchText, setSearchText] = useState("");
|
||||
|
||||
// Filter items based on search text
|
||||
const filteredItems = esResults?.items
|
||||
? esResults.items.filter(item => {
|
||||
const filteredItems = esResults?.items
|
||||
? esResults.items.filter((item) => {
|
||||
if (!searchText.trim()) return true;
|
||||
const searchLower = searchText.toLowerCase();
|
||||
return (
|
||||
@@ -86,13 +87,21 @@ export function EstimateScrubberResults({ bodyshop, jobid, job, esResults }) {
|
||||
|
||||
if (!esResults?.items?.length || job?.id !== esResults?.jobid) {
|
||||
return (
|
||||
<div style={{ padding: "24px", textAlign: "center" }}>
|
||||
<InfoCircleOutlined style={{ fontSize: "48px", color: "#d9d9d9", marginBottom: "16px" }} />
|
||||
<Title level={4} type="secondary">
|
||||
Estimate not yet scrubbed.
|
||||
</Title>
|
||||
<Text type="secondary">Run the estimate scrubber to see results here.</Text>
|
||||
</div>
|
||||
<Result
|
||||
status={"info"}
|
||||
title="Estimate not yet scrubbed."
|
||||
subTitle="Run the estimate scrubber to see results here."
|
||||
extra={<EstimateScrubberButton key="es" jobid={job ? job.id : null} job={job ? job : null} />}
|
||||
/>
|
||||
|
||||
// <div style={{ padding: "24px", textAlign: "center" }}>
|
||||
// <InfoCircleOutlined style={{ fontSize: "48px", color: "#d9d9d9", marginBottom: "16px" }} />
|
||||
// <Title level={4} type="secondary">
|
||||
// Estimate not yet scrubbed.
|
||||
// </Title>
|
||||
// <Text type="secondary">Run the estimate scrubber to see results here.</Text>
|
||||
// <EstimateScrubberButton key="es" jobid={job ? job.id : null} job={job ? job : null} />
|
||||
// </div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -101,7 +110,7 @@ export function EstimateScrubberResults({ bodyshop, jobid, job, esResults }) {
|
||||
return (
|
||||
<div style={{ padding: "16px" }}>
|
||||
<Input
|
||||
placeholder="Search items and descriptions..."
|
||||
placeholder="Search..."
|
||||
prefix={<SearchOutlined />}
|
||||
value={searchText}
|
||||
onChange={(e) => setSearchText(e.target.value)}
|
||||
@@ -124,21 +133,43 @@ export function EstimateScrubberResults({ bodyshop, jobid, job, esResults }) {
|
||||
<Space direction="vertical" size="large" style={{ width: "100%" }}>
|
||||
{/* Search Input */}
|
||||
<div>
|
||||
<Input
|
||||
placeholder="Search items and descriptions..."
|
||||
prefix={<SearchOutlined />}
|
||||
value={searchText}
|
||||
onChange={(e) => setSearchText(e.target.value)}
|
||||
allowClear
|
||||
style={{ maxWidth: 400 }}
|
||||
/>
|
||||
{searchText && (
|
||||
<div style={{ marginTop: "8px" }}>
|
||||
<Text type="secondary">
|
||||
Showing {filteredItems.length} of {esResults.items.length} items
|
||||
</Text>
|
||||
</div>
|
||||
)}
|
||||
<Space>
|
||||
<Input
|
||||
placeholder="Search"
|
||||
prefix={<SearchOutlined />}
|
||||
value={searchText}
|
||||
onChange={(e) => setSearchText(e.target.value)}
|
||||
allowClear
|
||||
style={{ maxWidth: 400 }}
|
||||
/>
|
||||
{searchText && (
|
||||
<div style={{ marginTop: "8px" }}>
|
||||
<Text type="secondary">
|
||||
Showing {filteredItems.length} of {esResults.items.length} items
|
||||
</Text>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<Space wrap size={"small"}>
|
||||
{Object.entries(groupedItems).map(([category, items]) => {
|
||||
const config = categoryConfig[category] || { color: "default" };
|
||||
return (
|
||||
<Tag key={category} color={config.color}>
|
||||
{category}: {items.length}
|
||||
</Tag>
|
||||
);
|
||||
})}
|
||||
</Space>
|
||||
</Space>
|
||||
<Button
|
||||
style={{ float: "right" }}
|
||||
type="primary"
|
||||
href={esResults?.pdfUrl}
|
||||
target="_blank"
|
||||
disabled={!esResults?.pdfUrl}
|
||||
>
|
||||
View PDF
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{/* Grouped Results */}
|
||||
@@ -179,18 +210,6 @@ export function EstimateScrubberResults({ bodyshop, jobid, job, esResults }) {
|
||||
</Collapse>
|
||||
|
||||
{/* Summary */}
|
||||
|
||||
<Title level={5}>Summary</Title>
|
||||
<Space wrap>
|
||||
{Object.entries(groupedItems).map(([category, items]) => {
|
||||
const config = categoryConfig[category] || { color: "default" };
|
||||
return (
|
||||
<Tag key={category} color={config.color}>
|
||||
{category}: {items.length}
|
||||
</Tag>
|
||||
);
|
||||
})}
|
||||
</Space>
|
||||
</Space>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -13,8 +13,17 @@ import TimeAgoFormatter from "../../atoms/time-ago-formatter/time-ago-formatter.
|
||||
import VehicleGroupAlertAtom from "../../atoms/vehicle-group-alert/vehicle-group-alert.atom";
|
||||
import CloseDateDisplayMolecule from "../close-date-display/close-date-display.molecule";
|
||||
import JobGroupMolecule from "../job-group/job-group.molecule";
|
||||
import EstimateScrubberButton from "../estimate-scrubber-button/estimate-scrubber-button.molecule.jsx";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { selectBodyshop } from "../../../redux/user/user.selectors.js";
|
||||
import { connect } from "react-redux";
|
||||
|
||||
export default function JobsDetailDescriptionMolecule({ loading, job, jobDetailRef }) {
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
bodyshop: selectBodyshop
|
||||
});
|
||||
export default connect(mapStateToProps, null)(JobsDetailDescriptionMolecule);
|
||||
|
||||
export function JobsDetailDescriptionMolecule({ bodyshop, loading, job, jobDetailRef }) {
|
||||
// Store original theme state
|
||||
const originalThemeRef = useRef(null);
|
||||
|
||||
@@ -88,6 +97,7 @@ export default function JobsDetailDescriptionMolecule({ loading, job, jobDetailR
|
||||
/>
|
||||
</Tooltip>
|
||||
),
|
||||
bodyshop.phone && <EstimateScrubberButton key="es" jobid={job ? job.id : null} job={job ? job : null} />,
|
||||
<DeleteJobAtom key="delete" jobId={job.id} />,
|
||||
<Button key="print" onClick={handlePrint}>
|
||||
<PrinterFilled />
|
||||
|
||||
@@ -14,17 +14,19 @@ import JobsDetailDescriptionMolecule from "../../molecules/jobs-detail-descripti
|
||||
import JobsLinesTableMolecule from "../../molecules/jobs-lines-table/jobs-lines-table.molecule";
|
||||
import JobsTargetsStatsMolecule from "../../molecules/jobs-targets-stats/jobs-targets-stats.molecule";
|
||||
import "./jobs-detail.organism.styles.scss";
|
||||
import { selectBodyshop } from "../../../redux/user/user.selectors";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
//currentUser: selectCurrentUser
|
||||
selectedJobId: selectSelectedJobId
|
||||
selectedJobId: selectSelectedJobId,
|
||||
bodyshop: selectBodyshop
|
||||
});
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
//setUserLanguage: language => dispatch(setUserLanguage(language))
|
||||
setSelectedJobTargetPc: (job) => dispatch(setSelectedJobTargetPc(job))
|
||||
});
|
||||
|
||||
export function JobsDetailOrganism({ selectedJobId, setSelectedJobTargetPc }) {
|
||||
export function JobsDetailOrganism({ bodyshop, selectedJobId, setSelectedJobTargetPc }) {
|
||||
const { loading, error, data } = useQuery(QUERY_JOB_BY_PK, {
|
||||
variables: { jobId: selectedJobId },
|
||||
skip: !selectedJobId
|
||||
@@ -81,30 +83,14 @@ export function JobsDetailOrganism({ selectedJobId, setSelectedJobTargetPc }) {
|
||||
//2025-05-27 Removing CC AI
|
||||
*/}
|
||||
|
||||
<Card
|
||||
title="Estimate Lines"
|
||||
extra={[
|
||||
<EstimateScrubberButton
|
||||
key="es"
|
||||
jobid={data ? data.jobs_by_pk?.id : null}
|
||||
job={data ? data.jobs_by_pk : null}
|
||||
/>
|
||||
]}
|
||||
>
|
||||
<Card title="Estimate Lines">
|
||||
<JobsLinesTableMolecule loading={loading} job={data ? data.jobs_by_pk : {}} />
|
||||
</Card>
|
||||
<Card
|
||||
title="Estimate Scrubber Results"
|
||||
extra={[
|
||||
<EstimateScrubberButton
|
||||
key="es"
|
||||
jobid={data ? data.jobs_by_pk?.id : null}
|
||||
job={data ? data.jobs_by_pk : null}
|
||||
/>
|
||||
]}
|
||||
>
|
||||
<EstimateScrubberResultsMolecule loading={loading} job={data ? data.jobs_by_pk : {}} />
|
||||
</Card>
|
||||
{bodyshop.phone && (
|
||||
<Card id="es-results-card" title="Estimate Scrubber Results" extra={[]}>
|
||||
<EstimateScrubberResultsMolecule loading={loading} job={data ? data.jobs_by_pk : {}} />
|
||||
</Card>
|
||||
)}
|
||||
<Card title="Parts Breakdown">
|
||||
<div
|
||||
style={{
|
||||
|
||||
@@ -10,6 +10,8 @@ export const QUERY_BODYSHOP = gql`
|
||||
ppd_diff_alert
|
||||
features
|
||||
channel
|
||||
zip_post
|
||||
phone
|
||||
}
|
||||
targets {
|
||||
id
|
||||
|
||||
Reference in New Issue
Block a user