Package upgrades and cleanup.
This commit is contained in:
@@ -44,7 +44,7 @@ export default defineConfig({
|
||||
filesToDeleteAfterUpload: ["**.js.map"],
|
||||
},
|
||||
release: {
|
||||
name: `bodyshop-desktop@${process.env.npm_package_version}`,
|
||||
name: `esdp@${process.env.npm_package_version}`,
|
||||
},
|
||||
}),
|
||||
],
|
||||
|
||||
4478
package-lock.json
generated
4478
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
63
package.json
63
package.json
@@ -22,66 +22,65 @@
|
||||
"build:mac": "node deploy/set-artifact-name.js electron-vite build --mode imex && node deploy/set-artifact-name.js electron-builder --mac"
|
||||
},
|
||||
"dependencies": {
|
||||
"@apollo/client": "^4.0.9",
|
||||
"@apollo/client": "^4.1.6",
|
||||
"@electron-toolkit/preload": "^3.0.2",
|
||||
"@electron-toolkit/utils": "^4.0.0",
|
||||
"@sentry/electron": "^7.4.0",
|
||||
"@sentry/vite-plugin": "^4.6.1",
|
||||
"axios": "^1.13.2",
|
||||
"@sentry/electron": "^7.8.0",
|
||||
"@sentry/vite-plugin": "^5.1.0",
|
||||
"axios": "^1.13.5",
|
||||
"dayjs": "^1.11.19",
|
||||
"electron-log": "^5.4.3",
|
||||
"electron-updater": "^6.6.2",
|
||||
"source-map-support": "^0.5.21",
|
||||
"winax": "^3.6.2"
|
||||
"electron-updater": "^6.8.3",
|
||||
"source-map-support": "^0.5.21"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@electron-toolkit/eslint-config-prettier": "^3.0.0",
|
||||
"@electron-toolkit/eslint-config-ts": "^3.1.0",
|
||||
"@electron-toolkit/tsconfig": "^2.0.0",
|
||||
"@playwright/test": "^1.57.0",
|
||||
"@reduxjs/toolkit": "^2.11.1",
|
||||
"@playwright/test": "^1.58.2",
|
||||
"@reduxjs/toolkit": "^2.11.2",
|
||||
"@types/cors": "^2.8.19",
|
||||
"@types/express": "^5.0.6",
|
||||
"@types/lodash": "^4.17.21",
|
||||
"@types/node": "^24.10.1",
|
||||
"@types/lodash": "^4.17.24",
|
||||
"@types/node": "^25.3.0",
|
||||
"@types/node-cron": "^3.0.11",
|
||||
"@types/react": "^19.2.7",
|
||||
"@types/react": "^19.2.14",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"@types/source-map-support": "^0.5.10",
|
||||
"@types/xml2js": "^0.4.14",
|
||||
"@vitejs/plugin-react": "^5.1.2",
|
||||
"antd": "^6.1.0",
|
||||
"@vitejs/plugin-react": "^5.1.4",
|
||||
"antd": "^6.3.1",
|
||||
"archiver": "^7.0.1",
|
||||
"chokidar": "^5.0.0",
|
||||
"cors": "^2.8.5",
|
||||
"cors": "^2.8.6",
|
||||
"cross-env": "^10.1.0",
|
||||
"dbffile": "^1.12.0",
|
||||
"electron": "^39.2.6",
|
||||
"electron-builder": "^26.0.12",
|
||||
"electron": "^40.6.0",
|
||||
"electron-builder": "^26.8.1",
|
||||
"electron-store": "^11.0.2",
|
||||
"electron-vite": "^5.0.0",
|
||||
"eslint": "^9.39.1",
|
||||
"eslint": "^10.0.2",
|
||||
"eslint-plugin-react": "^7.37.5",
|
||||
"eslint-plugin-react-hooks": "^7.0.1",
|
||||
"eslint-plugin-react-refresh": "^0.4.24",
|
||||
"eslint-plugin-react-refresh": "^0.5.2",
|
||||
"express": "^5.2.1",
|
||||
"firebase": "^12.6.0",
|
||||
"graphql": "^16.12.0",
|
||||
"graphql-request": "^7.3.5",
|
||||
"i18next": "^25.7.2",
|
||||
"lodash": "^4.17.21",
|
||||
"firebase": "^12.9.0",
|
||||
"graphql": "^16.13.0",
|
||||
"graphql-request": "^7.4.0",
|
||||
"i18next": "^25.8.13",
|
||||
"lodash": "^4.17.23",
|
||||
"node-cron": "^4.2.1",
|
||||
"playwright": "^1.57.0",
|
||||
"prettier": "^3.7.4",
|
||||
"react": "^19.2.1",
|
||||
"react-dom": "^19.2.1",
|
||||
"react-error-boundary": "^6.0.0",
|
||||
"react-i18next": "^16.4.0",
|
||||
"playwright": "^1.58.2",
|
||||
"prettier": "^3.8.1",
|
||||
"react": "^19.2.4",
|
||||
"react-dom": "^19.2.4",
|
||||
"react-error-boundary": "^6.1.1",
|
||||
"react-i18next": "^16.5.4",
|
||||
"react-redux": "^9.2.0",
|
||||
"react-router": "^7.10.1",
|
||||
"react-router": "^7.13.1",
|
||||
"redux-logger": "^3.0.6",
|
||||
"typescript": "^5.9.3",
|
||||
"vite": "7.2.7",
|
||||
"vite": "7.3.1",
|
||||
"xml2js": "^0.6.2",
|
||||
"xmlbuilder2": "^4.0.3"
|
||||
}
|
||||
|
||||
@@ -1,144 +0,0 @@
|
||||
import { APIGatewayProxyEvent, APIGatewayProxyResult } from 'aws-lambda';
|
||||
import axios, { AxiosError } from 'axios';
|
||||
import FormData from 'form-data';
|
||||
import { GraphQLClient, gql } from 'graphql-request';
|
||||
import { ESJobObject, RawJobDataObject } from '../../../shared/types';
|
||||
import { transformJobForEstimateScrubber } from '../lib/transformEstimate';
|
||||
import { getVehicleType } from '../lib/vehicleTypes/vehicleType';
|
||||
import { UUID } from 'node:crypto';
|
||||
|
||||
const ES_USER = process.env.ES_USER || '';
|
||||
const ES_PASSWORD = process.env.ES_PASSWORD || '';
|
||||
const ES_ENDPOINT = process.env.ES_ENDPOINT || '';
|
||||
const HASURA_URL = process.env.HASURA_URL || '';
|
||||
|
||||
interface ScrubRequest {
|
||||
esApiKey: string;
|
||||
rawJob: RawJobDataObject;
|
||||
}
|
||||
|
||||
interface ScrubResponse {
|
||||
report_link?: string;
|
||||
identified_item?: unknown;
|
||||
}
|
||||
|
||||
export const handler = async (event: APIGatewayProxyEvent): Promise<APIGatewayProxyResult> => {
|
||||
try {
|
||||
const { esApiKey, rawJob } = JSON.parse(event.body || '{}') as ScrubRequest;
|
||||
|
||||
await uploadJobToHasura(rawJob, esApiKey);
|
||||
// Transform the raw job object to ES format
|
||||
const estimate: ESJobObject = await transformJobForEstimateScrubber(rawJob);
|
||||
|
||||
// Set vehicle type and sending entity ID
|
||||
estimate.v_type = getVehicleType(estimate.v_model || '').type;
|
||||
estimate.sending_entity_id = '87330f61-412b-4251-baaa-d026565b23c5';
|
||||
|
||||
const fileName = `${esApiKey}-${rawJob.clm_no}-${Date.now()}`;
|
||||
const formData = new FormData();
|
||||
const jsonString = JSON.stringify(estimate);
|
||||
|
||||
formData.append('file', Buffer.from(jsonString), {
|
||||
filename: `${fileName}.json`,
|
||||
contentType: 'application/json',
|
||||
});
|
||||
|
||||
return {
|
||||
statusCode: 200,
|
||||
body: JSON.stringify({
|
||||
message: 'Debug - skipping ES scrub call',
|
||||
// Uncomment below to enable actual ES scrub call
|
||||
// ...await callEstimateScrubber(esApiKey, formData, fileName),
|
||||
}),
|
||||
};
|
||||
|
||||
const result = await axios.post<ScrubResponse>(`${ES_ENDPOINT}/api/sendems`, formData, {
|
||||
auth: {
|
||||
username: ES_USER,
|
||||
password: ES_PASSWORD,
|
||||
},
|
||||
headers: {
|
||||
APIkey: esApiKey,
|
||||
},
|
||||
});
|
||||
|
||||
const resultPDFUrl = result?.data?.report_link;
|
||||
const reportIssueUrl = `https://insurtechtoolkit.com/pcontactUs.aspx?apiKey=${esApiKey}&file=${fileName}.json`;
|
||||
|
||||
return {
|
||||
statusCode: 200,
|
||||
body: JSON.stringify({
|
||||
resultPDFUrl,
|
||||
reportIssueUrl,
|
||||
identified_item: result.data?.identified_item,
|
||||
}),
|
||||
};
|
||||
} catch (error) {
|
||||
console.log('Error in scrub handler:', error);
|
||||
return {
|
||||
statusCode: 500,
|
||||
body: JSON.stringify({
|
||||
message: 'Internal server error.',
|
||||
error: (error as Error).message,
|
||||
stack: (error as Error).stack,
|
||||
}),
|
||||
};
|
||||
|
||||
const axiosError = error as AxiosError;
|
||||
const errorMessage = axiosError.response?.data || axiosError.message || 'Unknown error';
|
||||
|
||||
return {
|
||||
statusCode: 400,
|
||||
body: JSON.stringify({
|
||||
message: 'Error scrubbing estimate.',
|
||||
error: errorMessage,
|
||||
}),
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
const uploadJobToHasura = async (rawJob: RawJobDataObject, esApiKey: string): Promise<void> => {
|
||||
const graphQLClient = new GraphQLClient(HASURA_URL, {
|
||||
headers: {
|
||||
'x-hasura-admin-secret': 'UXWqeUlNMc2dd2SD7DTOKgjEQlVkZkaW',
|
||||
},
|
||||
});
|
||||
|
||||
//Fetch to get the latest version of this based on the es api key and clm no
|
||||
|
||||
const version = await graphQLClient.request<{
|
||||
jobs: { version: number; id: UUID; clm_no: string }[];
|
||||
}>(LATEST_VERSION_BY_CLM_NO, {
|
||||
esApiKey,
|
||||
clm_no: rawJob.clm_no || '',
|
||||
});
|
||||
|
||||
//Manipulate the raw job to insert to the database.
|
||||
rawJob.version = version.jobs.length > 0 ? version.jobs[0].version + 1 : 1;
|
||||
|
||||
await graphQLClient.request(INSERT_JOB, {
|
||||
job: rawJob,
|
||||
});
|
||||
};
|
||||
|
||||
const LATEST_VERSION_BY_CLM_NO = gql`
|
||||
query LATEST_VERSION_BY_CLM_NO($esApiKey: String!, $clm_no: String!) {
|
||||
jobs(
|
||||
where: { clm_no: { _eq: $clm_no }, shop: { es_api_key: { _eq: $esApiKey } } }
|
||||
order_by: { version: desc }
|
||||
limit: 1
|
||||
) {
|
||||
id
|
||||
clm_no
|
||||
version
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const INSERT_JOB = gql`
|
||||
mutation INSERT_JOB($job: jobs_insert_input!) {
|
||||
insert_jobs_one(object: $job) {
|
||||
id
|
||||
}
|
||||
}
|
||||
`;
|
||||
@@ -1,10 +1,124 @@
|
||||
import { APIGatewayProxyEvent, APIGatewayProxyResult } from 'aws-lambda';
|
||||
import axios, { AxiosError } from 'axios';
|
||||
import FormData from 'form-data';
|
||||
import { GraphQLClient, gql } from 'graphql-request';
|
||||
import { ESJobObject, RawJobDataObject } from '../../../shared/types';
|
||||
import { transformJobForEstimateScrubber } from '../lib/transformEstimate';
|
||||
import { getVehicleType } from '../lib/vehicleTypes/vehicleType';
|
||||
import { UUID } from 'node:crypto';
|
||||
|
||||
const ES_USER = process.env.ES_USER || '';
|
||||
const ES_PASSWORD = process.env.ES_PASSWORD || '';
|
||||
const ES_ENDPOINT = process.env.ES_ENDPOINT || '';
|
||||
const HASURA_URL = process.env.HASURA_URL || '';
|
||||
|
||||
interface ScrubRequest {
|
||||
esApiKey: string;
|
||||
rawJob: RawJobDataObject;
|
||||
}
|
||||
|
||||
interface ScrubResponse {
|
||||
report_link?: string;
|
||||
identified_item?: unknown;
|
||||
}
|
||||
|
||||
export const handler = async (event: APIGatewayProxyEvent): Promise<APIGatewayProxyResult> => {
|
||||
return {
|
||||
statusCode: 200,
|
||||
body: JSON.stringify({
|
||||
message: 'Scrub handler is under construction',
|
||||
}),
|
||||
};
|
||||
try {
|
||||
const { esApiKey, rawJob } = JSON.parse(event.body || '{}') as ScrubRequest;
|
||||
|
||||
//await uploadJobToHasura(rawJob, esApiKey);
|
||||
// Transform the raw job object to ES format
|
||||
const estimate: ESJobObject = await transformJobForEstimateScrubber(rawJob);
|
||||
|
||||
// Set vehicle type and sending entity ID
|
||||
estimate.v_type = getVehicleType(estimate.v_model || '').type;
|
||||
estimate.sending_entity_id = '87330f61-412b-4251-baaa-d026565b23c5';
|
||||
|
||||
const fileName = `${esApiKey}-${rawJob.clm_no}-${Date.now()}`;
|
||||
const formData = new FormData();
|
||||
const jsonString = JSON.stringify(estimate);
|
||||
|
||||
formData.append('file', Buffer.from(jsonString), {
|
||||
filename: `${fileName}.json`,
|
||||
contentType: 'application/json',
|
||||
});
|
||||
|
||||
const result = await axios.post<ScrubResponse>(`${ES_ENDPOINT}/api/sendems`, formData, {
|
||||
auth: {
|
||||
username: ES_USER,
|
||||
password: ES_PASSWORD,
|
||||
},
|
||||
headers: {
|
||||
APIkey: esApiKey,
|
||||
},
|
||||
});
|
||||
|
||||
const resultPDFUrl = result?.data?.report_link;
|
||||
const reportIssueUrl = `https://insurtechtoolkit.com/pcontactUs.aspx?apiKey=${esApiKey}&file=${fileName}.json`;
|
||||
|
||||
return {
|
||||
statusCode: 200,
|
||||
body: JSON.stringify({
|
||||
resultPDFUrl,
|
||||
reportIssueUrl,
|
||||
identified_item: result.data?.identified_item,
|
||||
}),
|
||||
};
|
||||
} catch (error) {
|
||||
console.log('Error in scrub handler:', error);
|
||||
return {
|
||||
statusCode: 500,
|
||||
body: JSON.stringify({
|
||||
message: 'Internal server error.',
|
||||
error: (error as Error).message,
|
||||
stack: (error as Error).stack,
|
||||
}),
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
const uploadJobToHasura = async (rawJob: RawJobDataObject, esApiKey: string): Promise<void> => {
|
||||
const graphQLClient = new GraphQLClient(HASURA_URL, {
|
||||
headers: {
|
||||
'x-hasura-admin-secret': 'UXWqeUlNMc2dd2SD7DTOKgjEQlVkZkaW',
|
||||
},
|
||||
});
|
||||
|
||||
//Fetch to get the latest version of this based on the es api key and clm no
|
||||
|
||||
const version = await graphQLClient.request<{
|
||||
jobs: { version: number; id: UUID; clm_no: string }[];
|
||||
}>(LATEST_VERSION_BY_CLM_NO, {
|
||||
esApiKey,
|
||||
clm_no: rawJob.clm_no || '',
|
||||
});
|
||||
|
||||
//Manipulate the raw job to insert to the database.
|
||||
rawJob.version = version.jobs.length > 0 ? version.jobs[0].version + 1 : 1;
|
||||
|
||||
await graphQLClient.request(INSERT_JOB, {
|
||||
job: rawJob,
|
||||
});
|
||||
};
|
||||
|
||||
const LATEST_VERSION_BY_CLM_NO = gql`
|
||||
query LATEST_VERSION_BY_CLM_NO($esApiKey: String!, $clm_no: String!) {
|
||||
jobs(
|
||||
where: { clm_no: { _eq: $clm_no }, shop: { es_api_key: { _eq: $esApiKey } } }
|
||||
order_by: { version: desc }
|
||||
limit: 1
|
||||
) {
|
||||
id
|
||||
clm_no
|
||||
version
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const INSERT_JOB = gql`
|
||||
mutation INSERT_JOB($job: jobs_insert_input!) {
|
||||
insert_jobs_one(object: $job) {
|
||||
id
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import axios from "axios";
|
||||
import axios, { AxiosError } from "axios";
|
||||
import { BrowserWindow } from "electron";
|
||||
import log from "electron-log";
|
||||
import { autoUpdater } from "electron-updater";
|
||||
@@ -6,6 +6,7 @@ import { promises as fsPromises } from "fs";
|
||||
import path from "path";
|
||||
import { RawJobDataObject } from "../decoder/decoder";
|
||||
import store from "../store/store";
|
||||
import ipcTypes from "../../util/ipcTypes.json";
|
||||
|
||||
// Function to write job object to logs subfolder
|
||||
async function writeJobToLogsFolder(job, fileName): Promise<string> {
|
||||
@@ -110,21 +111,21 @@ async function ScrubEstimate({
|
||||
pdfWindow.focus();
|
||||
return resultPDFUrl;
|
||||
} catch (error) {
|
||||
log.error("Error while scrubbing estimate:", error, error.stack);
|
||||
log.error("Error Response Data:", error.response?.data);
|
||||
const err = error as AxiosError;
|
||||
log.error("Error while scrubbing estimate:", error, err.stack);
|
||||
log.error("Error Response Data:", err.response?.data);
|
||||
const mainWindow = BrowserWindow.getAllWindows()[0];
|
||||
|
||||
if (error.status === 400) {
|
||||
mainWindow.webContents.send(ipcTypes.app.toRenderer.scrubError, {
|
||||
mainWindow.webContents.send(ipcTypes.toRenderer.scrub.scrubError, {
|
||||
message:
|
||||
error.response?.data ||
|
||||
"Error encountered sending estimate to Estimate Scrubber.",
|
||||
});
|
||||
} else if (error.status === 401) {
|
||||
mainWindow.webContents.send(ipcTypes.app.toRenderer.scrubError, {
|
||||
mainWindow.webContents.send(ipcTypes.toRenderer.scrub.scrubError, {
|
||||
message:
|
||||
"Authentication with Estimate Scrubber failed." ||
|
||||
error.response?.data,
|
||||
err.response?.data || "Authentication with Estimate Scrubber failed."ta,
|
||||
});
|
||||
}
|
||||
return "Error: Unable to scrub estimate.";
|
||||
|
||||
@@ -154,7 +154,7 @@ const Home: FC = () => {
|
||||
return (
|
||||
<div style={{ maxWidth: "1400px", margin: "0 auto" }}>
|
||||
<Space
|
||||
direction="vertical"
|
||||
orientation="vertical"
|
||||
size="large"
|
||||
style={{ width: "100%", display: "flex" }}
|
||||
>
|
||||
|
||||
@@ -60,7 +60,7 @@ const SettingsConfig: FC = () => {
|
||||
layout="vertical"
|
||||
size="large"
|
||||
>
|
||||
<Space direction="vertical" size="middle" style={{ width: "100%" }}>
|
||||
<Space orientation="vertical" size="middle" style={{ width: "100%" }}>
|
||||
{settingFields.map((field) => (
|
||||
<Form.Item
|
||||
key={field.name}
|
||||
|
||||
@@ -43,7 +43,7 @@ const UpdateAvailable: FC = () => {
|
||||
boxShadow: "0 4px 12px rgba(0, 0, 0, 0.15)",
|
||||
}}
|
||||
>
|
||||
<Space direction="vertical" style={{ width: "100%" }}>
|
||||
<Space orientation="vertical" style={{ width: "100%" }}>
|
||||
{updateProgress === 0 && (
|
||||
<Button onClick={handleDownload}>{t("updates.download")}</Button>
|
||||
)}
|
||||
|
||||
@@ -55,6 +55,9 @@
|
||||
"error": "toRenderer_watcher_error",
|
||||
"polling": "toRenderer_watcher_polling"
|
||||
},
|
||||
"scrub": {
|
||||
"scrubError": "toRenderer_scrubError"
|
||||
},
|
||||
"updates": {
|
||||
"checking": "toRenderer_updates_checking",
|
||||
"available": "toRenderer_updates_available",
|
||||
|
||||
Reference in New Issue
Block a user