diff --git a/electron/changelog.json b/electron/changelog.json index ed1156f..cfb7c86 100644 --- a/electron/changelog.json +++ b/electron/changelog.json @@ -203,5 +203,10 @@ "title": "Release Notes for 1.4.2-beta.4", "date": "09/16/2025", "notes": "New Features:\r\n* Added part quantity toggle to shop setup. This will use the part quantity from the job lines when calculating RPS instead of assuming 1 per MPI guidelines.\r\n\r\nImprovements:\r\n* Updated ES integration to use newly specified API keys." + }, + "1.5.0": { + "title": "Release Notes for 1.5.0", + "date": "10/14/2025", + "notes": "New Features:\r\n* Direct integration to Estimate Scrubber is now available in Public Beta. Existing customers should automatically have access to this feature. If you encounter any issues, please reach out to support.\r\n* Added a quantity toggle to use line quantity instead of assuming 1 per MPI guidelines for RPS calculations.\r\n* Added date shortcuts to the report page for ease of use.\r\n* Added a floating shortcut to run 1 month and 3 month reports.\r\n\r\nImprovements:\r\n* Added better indicators for quantities and negative RPS values." } } diff --git a/package.json b/package.json index bdfd1e5..72685bd 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "productName": "ImEX RPS", "author": "ImEX Systems Inc. ", "description": "ImEX RPS", - "version": "1.4.2-beta.8", + "version": "1.5.0-alpha.1", "main": "electron/main.js", "homepage": "./", "dependencies": { diff --git a/src/components/molecules/estimate-scrubber-button/estimate-scrubber-button.molecule.jsx b/src/components/molecules/estimate-scrubber-button/estimate-scrubber-button.molecule.jsx index a3f76b4..73aa061 100644 --- a/src/components/molecules/estimate-scrubber-button/estimate-scrubber-button.molecule.jsx +++ b/src/components/molecules/estimate-scrubber-button/estimate-scrubber-button.molecule.jsx @@ -1,12 +1,11 @@ -import { Button, message } from "antd"; +import { useApolloClient } from "@apollo/client"; +import { Button, message, Tooltip } from "antd"; import { useState } from "react"; import { connect } from "react-redux"; import { createStructuredSelector } from "reselect"; +import { QUERY_JOB_ESTIMATE_SCRUBBER } from "../../../graphql/jobs.queries"; import ipcTypes from "../../../ipc.types"; import { selectBodyshop } from "../../../redux/user/user.selectors"; -import { useApolloClient } from "@apollo/client"; -import { QUERY_JOB_ESTIMATE_SCRUBBER } from "../../../graphql/jobs.queries"; -import _ from "lodash"; const { ipcRenderer } = window; const mapStateToProps = createStructuredSelector({ //currentUser: selectCurrentUser @@ -61,9 +60,17 @@ export function EstimateScrubberButton({ bodyshop, jobid, job }) { setLoading(false); }; - return ( + const buttonDisabled = job?.g_bett_amt == null; + + return buttonDisabled ? ( + + + + ) : ( ); } diff --git a/src/components/molecules/estimate-scruber-results/estimate-scrubber-results.molecule.jsx b/src/components/molecules/estimate-scruber-results/estimate-scrubber-results.molecule.jsx index 91760f1..68bd884 100644 --- a/src/components/molecules/estimate-scruber-results/estimate-scrubber-results.molecule.jsx +++ b/src/components/molecules/estimate-scruber-results/estimate-scrubber-results.molecule.jsx @@ -23,6 +23,7 @@ const { Title, Text, Link } = Typography; export function EstimateScrubberResults({ bodyshop, jobid, job, esResults }) { const [searchText, setSearchText] = useState(""); + const buttonDisabled = job?.g_bett_amt == null; // Filter items based on search text const filteredItems = esResults?.items @@ -91,9 +92,13 @@ export function EstimateScrubberResults({ bodyshop, jobid, job, esResults }) { if (!esResults?.items?.length || job?.id !== esResults?.jobid) { return ( } /> @@ -133,91 +138,94 @@ export function EstimateScrubberResults({ bodyshop, jobid, job, esResults }) { return (
- - - } - value={searchText} - onChange={(e) => setSearchText(e.target.value)} - allowClear - style={{ maxWidth: 400 }} - /> - {searchText && ( -
- - Showing {filteredItems.length} of {esResults.items.length} items - -
- )} + {Object.keys(groupedItems).length === 0 ? ( + + ) : ( + + + } + value={searchText} + onChange={(e) => setSearchText(e.target.value)} + allowClear + style={{ maxWidth: 400 }} + /> + {searchText && ( +
+ + Showing {filteredItems.length} of {esResults.items.length} items + +
+ )} - - + + +
+ + {Object.entries(groupedItems).map(([category, items]) => { + const config = categoryConfig[category] || { color: "default" }; + return ( + + {category}: {items.length} + + ); + })} + + + + {sortedCategories.map((category) => { + const items = groupedItems[category]; + const config = categoryConfig[category] || { color: "default", icon: "📄" }; + + return ( + + {/* {config.icon} */} + {category} + +
+ } + key={category} + > + `${category}-${index}`} + style={{ marginTop: "12px" }} + scroll={{}} + /> + + ); + })} + - - {Object.entries(groupedItems).map(([category, items]) => { - const config = categoryConfig[category] || { color: "default" }; - return ( - - {category}: {items.length} - - ); - })} - - - {/* Grouped Results */} - - {sortedCategories.map((category) => { - const items = groupedItems[category]; - const config = categoryConfig[category] || { color: "default", icon: "📄" }; - - return ( - - {/* {config.icon} */} - {category} - - - } - key={category} - > -
`${category}-${index}`} - style={{ marginTop: "12px" }} - scroll={{}} - /> - - ); - })} - - + )} ); } diff --git a/src/components/organisms/jobs-detail/jobs-detail.organism.jsx b/src/components/organisms/jobs-detail/jobs-detail.organism.jsx index 5958d89..75756df 100644 --- a/src/components/organisms/jobs-detail/jobs-detail.organism.jsx +++ b/src/components/organisms/jobs-detail/jobs-detail.organism.jsx @@ -1,20 +1,19 @@ import { useQuery } from "@apollo/client"; -import { Card, Result } from "antd"; +import { Badge, Card, Result } from "antd"; import { useEffect, useRef } from "react"; import { connect } from "react-redux"; import { createStructuredSelector } from "reselect"; import { QUERY_JOB_BY_PK } from "../../../graphql/jobs.queries"; import { setSelectedJobTargetPc } from "../../../redux/application/application.actions"; import { selectSelectedJobId } from "../../../redux/application/application.selectors"; +import { selectBodyshop } from "../../../redux/user/user.selectors"; import ErrorResultAtom from "../../atoms/error-result/error-result.atom"; import JobsPartsGraphAtom from "../../atoms/jobs-parts-graph/jobs-parts-graph.atom"; -import EstimateScrubberButton from "../../molecules/estimate-scrubber-button/estimate-scrubber-button.molecule"; import EstimateScrubberResultsMolecule from "../../molecules/estimate-scruber-results/estimate-scrubber-results.molecule"; import JobsDetailDescriptionMolecule from "../../molecules/jobs-detail-description/jobs-detail-description.molecule"; 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 @@ -87,9 +86,11 @@ export function JobsDetailOrganism({ bodyshop, selectedJobId, setSelectedJobTarg {bodyshop.es_api_key && ( - - - + + + + + )}
({ type: ApplicationActionTypes.SET_ES_RESULTS, payload: scrubResults }); + + +export const clearEsResults = () => ({ + type: ApplicationActionTypes.CLEAR_ES_RESULTS +}); \ No newline at end of file diff --git a/src/redux/application/application.reducer.js b/src/redux/application/application.reducer.js index b96092c..ad5e616 100644 --- a/src/redux/application/application.reducer.js +++ b/src/redux/application/application.reducer.js @@ -75,6 +75,8 @@ const applicationReducer = (state = INITIAL_STATE, action) => { return { ...state, releaseNotes: action.payload }; case ApplicationActionTypes.SET_ES_RESULTS: return { ...state, esResults: action.payload }; + case ApplicationActionTypes.CLEAR_ES_RESULTS: + return { ...state, esResults: { jobid: null, identified_items: [] } }; default: return state; } diff --git a/src/redux/application/application.types.js b/src/redux/application/application.types.js index 421cba0..96f1480 100644 --- a/src/redux/application/application.types.js +++ b/src/redux/application/application.types.js @@ -11,6 +11,7 @@ const ApplicationActionTypes = { SET_UPDATE_AVAILABLE: "SET_UPDATE_AVAILABLE", SET_UPDATE_PROGRESS: "SET_UPDATE_PROGRESS", SET_RELEASE_NOTES: "SET_RELEASE_NOTES", - SET_ES_RESULTS: "SET_ES_RESULTS" + SET_ES_RESULTS: "SET_ES_RESULTS", + CLEAR_ES_RESULTS: "CLEAR_ES_RESULTS" }; export default ApplicationActionTypes;