Add parsing of AD1 files. Memorize window size and location.
This commit is contained in:
BIN
_reference/ems/MPI_1/3698420.ENV
Normal file
BIN
_reference/ems/MPI_1/3698420.ENV
Normal file
Binary file not shown.
BIN
_reference/ems/MPI_1/3698420.LIN
Normal file
BIN
_reference/ems/MPI_1/3698420.LIN
Normal file
Binary file not shown.
BIN
_reference/ems/MPI_1/3698420.PFH
Normal file
BIN
_reference/ems/MPI_1/3698420.PFH
Normal file
Binary file not shown.
BIN
_reference/ems/MPI_1/3698420.PFL
Normal file
BIN
_reference/ems/MPI_1/3698420.PFL
Normal file
Binary file not shown.
BIN
_reference/ems/MPI_1/3698420.PFM
Normal file
BIN
_reference/ems/MPI_1/3698420.PFM
Normal file
Binary file not shown.
BIN
_reference/ems/MPI_1/3698420.PFO
Normal file
BIN
_reference/ems/MPI_1/3698420.PFO
Normal file
Binary file not shown.
BIN
_reference/ems/MPI_1/3698420.PFP
Normal file
BIN
_reference/ems/MPI_1/3698420.PFP
Normal file
Binary file not shown.
BIN
_reference/ems/MPI_1/3698420.PFT
Normal file
BIN
_reference/ems/MPI_1/3698420.PFT
Normal file
Binary file not shown.
BIN
_reference/ems/MPI_1/3698420.STL
Normal file
BIN
_reference/ems/MPI_1/3698420.STL
Normal file
Binary file not shown.
BIN
_reference/ems/MPI_1/3698420.TTL
Normal file
BIN
_reference/ems/MPI_1/3698420.TTL
Normal file
Binary file not shown.
BIN
_reference/ems/MPI_1/3698420.VEN
Normal file
BIN
_reference/ems/MPI_1/3698420.VEN
Normal file
Binary file not shown.
BIN
_reference/ems/MPI_1/3698420A.AD1
Normal file
BIN
_reference/ems/MPI_1/3698420A.AD1
Normal file
Binary file not shown.
BIN
_reference/ems/MPI_1/3698420A.dbt
Normal file
BIN
_reference/ems/MPI_1/3698420A.dbt
Normal file
Binary file not shown.
BIN
_reference/ems/MPI_1/3698420B.AD2
Normal file
BIN
_reference/ems/MPI_1/3698420B.AD2
Normal file
Binary file not shown.
BIN
_reference/ems/MPI_1/3698420B.dbt
Normal file
BIN
_reference/ems/MPI_1/3698420B.dbt
Normal file
Binary file not shown.
BIN
_reference/ems/MPI_1/3698420V.VEH
Normal file
BIN
_reference/ems/MPI_1/3698420V.VEH
Normal file
Binary file not shown.
BIN
_reference/ems/MPI_1/3698420V.dbt
Normal file
BIN
_reference/ems/MPI_1/3698420V.dbt
Normal file
Binary file not shown.
@@ -18,8 +18,13 @@ nsis:
|
||||
shortcutName: ${productName}
|
||||
uninstallDisplayName: ${productName}
|
||||
createDesktopShortcut: always
|
||||
azureSignOptions:
|
||||
endpoint: https://eus.codesigning.azure.net
|
||||
certificateProfileName: ImEXRPS
|
||||
codeSigningAccountName: ImEX
|
||||
mac:
|
||||
entitlementsInherit: build/entitlements.mac.plist
|
||||
category: public.app-category.business
|
||||
extendInfo:
|
||||
- NSCameraUsageDescription: Application requests access to the device's camera.
|
||||
- NSMicrophoneUsageDescription: Application requests access to the device's microphone.
|
||||
@@ -39,7 +44,8 @@ appImage:
|
||||
artifactName: ${name}-${version}.${ext}
|
||||
npmRebuild: false
|
||||
publish:
|
||||
provider: generic
|
||||
url: https://example.com/auto-updates
|
||||
provider: s3
|
||||
bucket: bodyshop-desktop-updater
|
||||
region: ca-central-1
|
||||
electronDownload:
|
||||
mirror: https://npmmirror.com/mirrors/electron/
|
||||
|
||||
8
package-lock.json
generated
8
package-lock.json
generated
@@ -28,6 +28,7 @@
|
||||
"@electron-toolkit/eslint-config-ts": "^3.0.0",
|
||||
"@electron-toolkit/tsconfig": "^1.0.1",
|
||||
"@playwright/test": "^1.51.0",
|
||||
"@types/lodash": "^4.17.16",
|
||||
"@types/node": "^22.13.10",
|
||||
"@types/react": "^19.0.10",
|
||||
"@types/react-dom": "^19.0.4",
|
||||
@@ -3312,6 +3313,13 @@
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/lodash": {
|
||||
"version": "4.17.16",
|
||||
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.16.tgz",
|
||||
"integrity": "sha512-HX7Em5NYQAXKW+1T+FiuG27NGwzJfCX3s1GjOa7ujxZa52kjJLOr4FUxT+giF6Tgxv1e+/czV/iTtBw27WTU9g==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/ms": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz",
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
"@electron-toolkit/eslint-config-ts": "^3.0.0",
|
||||
"@electron-toolkit/tsconfig": "^1.0.1",
|
||||
"@playwright/test": "^1.51.0",
|
||||
"@types/lodash": "^4.17.16",
|
||||
"@types/node": "^22.13.10",
|
||||
"@types/react": "^19.0.10",
|
||||
"@types/react-dom": "^19.0.4",
|
||||
|
||||
147
src/main/decoder/decode-ad1.interface.ts
Normal file
147
src/main/decoder/decode-ad1.interface.ts
Normal file
@@ -0,0 +1,147 @@
|
||||
interface ParsedAD1 {
|
||||
// Insurance company information
|
||||
ins_co_id?: string;
|
||||
ins_co_nm?: string;
|
||||
ins_addr1?: string;
|
||||
ins_addr2?: string;
|
||||
ins_city?: string;
|
||||
ins_st?: string;
|
||||
ins_zip?: string;
|
||||
ins_ctry?: string;
|
||||
ins_ea?: string;
|
||||
ins_ph1?: string;
|
||||
ins_ph1x?: string;
|
||||
ins_ph2?: string;
|
||||
ins_ph2x?: string;
|
||||
ins_fax?: string;
|
||||
ins_faxx?: string;
|
||||
ins_ct_ln?: string;
|
||||
ins_ct_fn?: string;
|
||||
ins_title?: string;
|
||||
ins_ct_ph?: string;
|
||||
ins_ct_phx?: string;
|
||||
|
||||
// Policy information
|
||||
policy_no?: string;
|
||||
ded_amt?: string;
|
||||
ded_status?: string;
|
||||
asgn_no?: string;
|
||||
asgn_date?: string;
|
||||
asgn_type?: string;
|
||||
|
||||
// Claim information
|
||||
clm_no?: string;
|
||||
clm_ofc_id?: string;
|
||||
clm_ofc_nm?: string;
|
||||
clm_addr1?: string;
|
||||
clm_addr2?: string;
|
||||
clm_city?: string;
|
||||
clm_st?: string;
|
||||
clm_zip?: string;
|
||||
clm_ctry?: string;
|
||||
clm_ph1?: string;
|
||||
clm_ph1x?: string;
|
||||
clm_ph2?: string;
|
||||
clm_ph2x?: string;
|
||||
clm_fax?: string;
|
||||
clm_faxx?: string;
|
||||
clm_ct_ln?: string;
|
||||
clm_ct_fn?: string;
|
||||
clm_title?: string;
|
||||
clm_ct_ph?: string;
|
||||
clm_ct_phx?: string;
|
||||
clm_ea?: string;
|
||||
|
||||
// Payment information
|
||||
payee_nms?: string;
|
||||
pay_type?: string;
|
||||
pay_date?: string;
|
||||
pay_chknm?: string;
|
||||
pay_amt?: string;
|
||||
|
||||
// Agent information
|
||||
agt_co_id?: string;
|
||||
agt_co_nm?: string;
|
||||
agt_addr1?: string;
|
||||
agt_addr2?: string;
|
||||
agt_city?: string;
|
||||
agt_st?: string;
|
||||
agt_zip?: string;
|
||||
agt_ctry?: string;
|
||||
agt_ph1?: string;
|
||||
agt_ph1x?: string;
|
||||
agt_ph2?: string;
|
||||
agt_ph2x?: string;
|
||||
agt_fax?: string;
|
||||
agt_faxx?: string;
|
||||
agt_ct_ln?: string;
|
||||
agt_ct_fn?: string;
|
||||
agt_ct_ph?: string;
|
||||
agt_ct_phx?: string;
|
||||
agt_ea?: string;
|
||||
agt_lic_no?: string;
|
||||
|
||||
// Loss information
|
||||
loss_date?: string;
|
||||
loss_type?: string;
|
||||
loss_desc?: string;
|
||||
theft_ind?: string;
|
||||
cat_no?: string;
|
||||
tlos_ind?: string;
|
||||
cust_pr?: string;
|
||||
loss_cat?: string;
|
||||
|
||||
// Insured information
|
||||
insd_ln?: string;
|
||||
insd_fn?: string;
|
||||
insd_title?: string;
|
||||
insd_co_nm?: string;
|
||||
insd_addr1?: string;
|
||||
insd_addr2?: string;
|
||||
insd_city?: string;
|
||||
insd_st?: string;
|
||||
insd_zip?: string;
|
||||
insd_ctry?: string;
|
||||
insd_ph1?: string;
|
||||
insd_ph2?: string;
|
||||
insd_fax?: string;
|
||||
insd_faxx?: string;
|
||||
insd_ea?: string;
|
||||
|
||||
// Owner information
|
||||
ownr_ln?: string;
|
||||
ownr_fn?: string;
|
||||
ownr_title?: string;
|
||||
ownr_co_nm?: string;
|
||||
ownr_addr1?: string;
|
||||
ownr_addr2?: string;
|
||||
ownr_city?: string;
|
||||
ownr_st?: string;
|
||||
ownr_zip?: string;
|
||||
ownr_ctry?: string;
|
||||
ownr_ph1?: string;
|
||||
ownr_ph2?: string;
|
||||
ownr_ea?: string;
|
||||
|
||||
// Owner data object - referenced in the code
|
||||
owner: {
|
||||
data: OwnerRecordInterface;
|
||||
};
|
||||
}
|
||||
|
||||
interface OwnerRecordInterface {
|
||||
ownr_ln: string;
|
||||
ownr_fn: string;
|
||||
ownr_title: string;
|
||||
ownr_co_nm: string;
|
||||
ownr_addr1: string;
|
||||
ownr_addr2: string;
|
||||
ownr_city: string;
|
||||
ownr_st: string;
|
||||
ownr_zip: string;
|
||||
ownr_ctry: string;
|
||||
ownr_ph1: string;
|
||||
ownr_ph2: string;
|
||||
ownr_ea: string;
|
||||
shopid: string;
|
||||
}
|
||||
219
src/main/decoder/decode-ad1.ts
Normal file
219
src/main/decoder/decode-ad1.ts
Normal file
@@ -0,0 +1,219 @@
|
||||
import { DBFFile } from "dbffile";
|
||||
import log from "electron-log/main";
|
||||
import _ from "lodash";
|
||||
import deepLowerCaseKeys from "../../util/deepLowercaseKeys";
|
||||
|
||||
const DecodeAD1 = async (extensionlessFilePath: string): Promise<ParsedAD1> => {
|
||||
let dbf;
|
||||
try {
|
||||
dbf = await DBFFile.open(`${extensionlessFilePath}A.AD1`);
|
||||
} catch (error) {
|
||||
log.error("Error opening AD1 File.", error);
|
||||
dbf = await DBFFile.open(`${extensionlessFilePath}.AD1`);
|
||||
log.log("Found AD1 file using regular CIECA Id.");
|
||||
}
|
||||
|
||||
if (!dbf) {
|
||||
log.error(`Could not find any AD1 files at ${extensionlessFilePath}`);
|
||||
return {
|
||||
id: 0,
|
||||
};
|
||||
}
|
||||
|
||||
const rawDBFRecord = await dbf.readRecords(1);
|
||||
|
||||
//AD1 will always have only 1 row.
|
||||
//Commented lines have been cross referenced with existing partner fields.
|
||||
|
||||
const rawAd1Data = deepLowerCaseKeys(
|
||||
_.pick(rawDBFRecord[0], [
|
||||
//TODO: Add typings for EMS File Formats.
|
||||
"INS_CO_ID",
|
||||
"INS_CO_NM",
|
||||
"INS_ADDR1",
|
||||
"INS_ADDR2",
|
||||
"INS_CITY",
|
||||
"INS_ST",
|
||||
"INS_ZIP",
|
||||
"INS_CTRY",
|
||||
"INS_EA",
|
||||
"POLICY_NO",
|
||||
"DED_AMT",
|
||||
"DED_STATUS",
|
||||
"ASGN_NO",
|
||||
"ASGN_DATE",
|
||||
"ASGN_TYPE",
|
||||
"CLM_NO",
|
||||
"CLM_OFC_ID",
|
||||
"CLM_OFC_NM",
|
||||
"CLM_ADDR1",
|
||||
"CLM_ADDR2",
|
||||
"CLM_CITY",
|
||||
"CLM_ST",
|
||||
"CLM_ZIP",
|
||||
"CLM_CTRY",
|
||||
"CLM_PH1",
|
||||
"CLM_PH1X",
|
||||
"CLM_PH2",
|
||||
"CLM_PH2X",
|
||||
"CLM_FAX",
|
||||
"CLM_FAXX",
|
||||
"CLM_CT_LN",
|
||||
"CLM_CT_FN",
|
||||
"CLM_TITLE",
|
||||
"CLM_CT_PH",
|
||||
"CLM_CT_PHX",
|
||||
"CLM_EA",
|
||||
"PAYEE_NMS",
|
||||
"PAY_TYPE",
|
||||
"PAY_DATE",
|
||||
"PAY_CHKNM",
|
||||
"PAY_AMT",
|
||||
"AGT_CO_ID",
|
||||
"AGT_CO_NM",
|
||||
"AGT_ADDR1",
|
||||
"AGT_ADDR2",
|
||||
"AGT_CITY",
|
||||
"AGT_ST",
|
||||
"AGT_ZIP",
|
||||
"AGT_CTRY",
|
||||
"AGT_PH1",
|
||||
"AGT_PH1X",
|
||||
"AGT_PH2",
|
||||
"AGT_PH2X",
|
||||
"AGT_FAX",
|
||||
"AGT_FAXX",
|
||||
"AGT_CT_LN",
|
||||
"AGT_CT_FN",
|
||||
"AGT_CT_PH",
|
||||
"AGT_CT_PHX",
|
||||
"AGT_EA",
|
||||
"AGT_LIC_NO",
|
||||
"LOSS_DATE",
|
||||
"LOSS_TYPE",
|
||||
"LOSS_DESC",
|
||||
"THEFT_IND",
|
||||
"CAT_NO",
|
||||
"TLOS_IND",
|
||||
"CUST_PR",
|
||||
"INSD_LN",
|
||||
"INSD_FN",
|
||||
"INSD_TITLE",
|
||||
"INSD_CO_NM",
|
||||
"INSD_ADDR1",
|
||||
"INSD_ADDR2",
|
||||
"INSD_CITY",
|
||||
"INSD_ST",
|
||||
"INSD_ZIP",
|
||||
"INSD_CTRY",
|
||||
"INSD_PH1",
|
||||
//"INSD_PH1X",
|
||||
"INSD_PH2",
|
||||
//"INSD_PH2X",
|
||||
"INSD_FAX",
|
||||
"INSD_FAXX",
|
||||
"INSD_EA",
|
||||
"OWNR_LN",
|
||||
"OWNR_FN",
|
||||
"OWNR_TITLE",
|
||||
"OWNR_CO_NM",
|
||||
"OWNR_ADDR1",
|
||||
"OWNR_ADDR2",
|
||||
"OWNR_CITY",
|
||||
"OWNR_ST",
|
||||
"OWNR_ZIP",
|
||||
"OWNR_CTRY",
|
||||
"OWNR_PH1",
|
||||
//"OWNR_PH1X",
|
||||
"OWNR_PH2",
|
||||
//"OWNR_PH2X",
|
||||
//"OWNR_FAX",
|
||||
//"OWNR_FAXX",
|
||||
"OWNR_EA",
|
||||
"INS_PH1",
|
||||
"INS_PH1X",
|
||||
"INS_PH2",
|
||||
"INS_PH2X",
|
||||
"INS_FAX",
|
||||
"INS_FAXX",
|
||||
"INS_CT_LN",
|
||||
"INS_CT_FN",
|
||||
"INS_TITLE",
|
||||
"INS_CT_PH",
|
||||
"INS_CT_PHX",
|
||||
"LOSS_CAT",
|
||||
])
|
||||
);
|
||||
|
||||
//Copy specific logic for manipulation.
|
||||
//If ownr_ph1 is missing, use ownr_ph2
|
||||
if (!rawAd1Data.ownr_ph1) {
|
||||
rawAd1Data.ownr_ph1 = rawAd1Data.ownr_ph2;
|
||||
}
|
||||
|
||||
let ownerRecord: OwnerRecordInterface;
|
||||
//Check if the owner information is there. If not, use the insured information as a fallback.
|
||||
if (
|
||||
_.isEmpty(rawAd1Data.ownr_ln) &&
|
||||
_.isEmpty(rawAd1Data.ownr_fn) &&
|
||||
_.isEmpty(rawAd1Data.ownr_co_nm)
|
||||
) {
|
||||
//They're all empty. Using the insured information as a fallback.
|
||||
// //Build up the owner record to insert it alongside the job.
|
||||
ownerRecord = {
|
||||
ownr_ln: rawAd1Data.insd_ln,
|
||||
ownr_fn: rawAd1Data.insd_fn,
|
||||
ownr_title: rawAd1Data.insd_title,
|
||||
ownr_co_nm: rawAd1Data.insd_co_nm,
|
||||
ownr_addr1: rawAd1Data.insd_addr1,
|
||||
ownr_addr2: rawAd1Data.insd_addr2,
|
||||
ownr_city: rawAd1Data.insd_city,
|
||||
ownr_st: rawAd1Data.insd_st,
|
||||
ownr_zip: rawAd1Data.insd_zip,
|
||||
ownr_ctry: rawAd1Data.insd_ctry,
|
||||
ownr_ph1: rawAd1Data.insd_ph1,
|
||||
ownr_ph2: rawAd1Data.insd_ph2,
|
||||
ownr_ea: rawAd1Data.insd_ea,
|
||||
|
||||
shopid: "UUID", //TODO: Need to add the shop uuid to this set of functions.
|
||||
};
|
||||
} else {
|
||||
//Use the owner information.
|
||||
ownerRecord = {
|
||||
ownr_ln: rawAd1Data.ownr_ln,
|
||||
ownr_fn: rawAd1Data.ownr_fn,
|
||||
ownr_title: rawAd1Data.ownr_title,
|
||||
ownr_co_nm: rawAd1Data.ownr_co_nm,
|
||||
ownr_addr1: rawAd1Data.ownr_addr1,
|
||||
ownr_addr2: rawAd1Data.ownr_addr2,
|
||||
ownr_city: rawAd1Data.ownr_city,
|
||||
ownr_st: rawAd1Data.ownr_st,
|
||||
ownr_zip: rawAd1Data.ownr_zip,
|
||||
ownr_ctry: rawAd1Data.ownr_ctry,
|
||||
ownr_ph1: rawAd1Data.ownr_ph1,
|
||||
ownr_ph2: rawAd1Data.ownr_ph2,
|
||||
ownr_ea: rawAd1Data.ownr_ea,
|
||||
shopid: "UUID",
|
||||
};
|
||||
}
|
||||
|
||||
return { ...rawAd1Data, owner: { data: ownerRecord } };
|
||||
};
|
||||
export default DecodeAD1;
|
||||
|
||||
interface OwnerRecordInterface {
|
||||
ownr_ln: string;
|
||||
ownr_fn: string;
|
||||
ownr_title: string;
|
||||
ownr_co_nm: string;
|
||||
ownr_addr1: string;
|
||||
ownr_addr2: string;
|
||||
ownr_city: string;
|
||||
ownr_st: string;
|
||||
ownr_zip: string;
|
||||
ownr_ctry: string;
|
||||
ownr_ph1: string;
|
||||
ownr_ph2: string;
|
||||
ownr_ea: string;
|
||||
shopid: string;
|
||||
}
|
||||
19
src/main/decoder/decoder.ts
Normal file
19
src/main/decoder/decoder.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import log from "electron-log/main";
|
||||
import path from "path";
|
||||
import DecodeAD1 from "./decode-ad1";
|
||||
|
||||
async function ImportJob(filepath: string): Promise<void> {
|
||||
const parsedFilePath = path.parse(filepath);
|
||||
const extensionlessFilePath = path.join(
|
||||
parsedFilePath.dir,
|
||||
parsedFilePath.name
|
||||
);
|
||||
log.debug("Importing Job", extensionlessFilePath);
|
||||
|
||||
const decodedJob = {};
|
||||
|
||||
const ad1: ParsedAD1 = await DecodeAD1(extensionlessFilePath);
|
||||
log.debug("AD1", ad1);
|
||||
}
|
||||
|
||||
export default ImportJob;
|
||||
@@ -1,7 +1,7 @@
|
||||
import { _electron as electron } from "playwright";
|
||||
import { test, expect } from "@playwright/test";
|
||||
|
||||
test("example test", async () => {
|
||||
test("Basic Electron app compilation.", async () => {
|
||||
const electronApp = await electron.launch({ args: ["."] });
|
||||
const isPackaged = await electronApp.evaluate(async ({ app }) => {
|
||||
// This runs in Electron's main process, parameter here is always
|
||||
@@ -14,8 +14,6 @@ test("example test", async () => {
|
||||
// Wait for the first BrowserWindow to open
|
||||
// and return its Page object
|
||||
const window = await electronApp.firstWindow();
|
||||
await window.screenshot({ path: "intro.png" });
|
||||
|
||||
// close app
|
||||
await electronApp.close();
|
||||
});
|
||||
|
||||
@@ -4,13 +4,23 @@ import log from "electron-log/main";
|
||||
import { join } from "path";
|
||||
import icon from "../../resources/icon.png?asset";
|
||||
import ErrorTypeCheck from "../util/errorTypeCheck";
|
||||
import "./store/store";
|
||||
import store from "./store/store";
|
||||
|
||||
log.initialize();
|
||||
function createWindow(): void {
|
||||
// Create the browser window.
|
||||
const { width, height, x, y } = store.get("app.windowBounds") as {
|
||||
width: number;
|
||||
height: number;
|
||||
x: number | undefined;
|
||||
y: number | undefined;
|
||||
};
|
||||
|
||||
const mainWindow = new BrowserWindow({
|
||||
width: 900,
|
||||
height: 670,
|
||||
width,
|
||||
height,
|
||||
x,
|
||||
y,
|
||||
show: false,
|
||||
autoHideMenuBar: true,
|
||||
...(process.platform === "linux" ? { icon } : {}),
|
||||
@@ -21,6 +31,17 @@ function createWindow(): void {
|
||||
},
|
||||
});
|
||||
|
||||
// Store window properties for later
|
||||
const storeWindowState = (): void => {
|
||||
const [width, height] = mainWindow.getSize();
|
||||
const [x, y] = mainWindow.getPosition();
|
||||
store.set("app.windowBounds", { width, height, x, y });
|
||||
};
|
||||
mainWindow.on("resized", storeWindowState);
|
||||
mainWindow.on("maximize", storeWindowState);
|
||||
mainWindow.on("unmaximize", storeWindowState);
|
||||
mainWindow.on("moved", storeWindowState);
|
||||
|
||||
mainWindow.on("ready-to-show", () => {
|
||||
mainWindow.show();
|
||||
});
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { ipcMain } from "electron";
|
||||
import { app, ipcMain } from "electron";
|
||||
import log from "electron-log/main";
|
||||
import path from "path";
|
||||
import ipcTypes from "../../util/ipcTypes.json";
|
||||
import ImportJob from "../decoder/decoder";
|
||||
import { StartWatcher } from "../watcher/watcher";
|
||||
import {
|
||||
SettingsWatchedFilePathsAdd,
|
||||
@@ -10,7 +12,7 @@ import {
|
||||
import { ipcMainHandleAuthStateChanged } from "./ipcMainHandler.user";
|
||||
|
||||
// Log all IPC messages and their payloads
|
||||
const logIpcMessages = () => {
|
||||
const logIpcMessages = (): void => {
|
||||
// Get all message types from ipcTypes.toMain
|
||||
Object.keys(ipcTypes.toMain).forEach((key) => {
|
||||
const messageType = ipcTypes.toMain[key];
|
||||
@@ -42,6 +44,24 @@ ipcMain.on(ipcTypes.toMain.test, (payload: any) =>
|
||||
//Auth handler
|
||||
ipcMain.on(ipcTypes.toMain.authStateChanged, ipcMainHandleAuthStateChanged);
|
||||
|
||||
//Add debug handlers if in development
|
||||
if (import.meta.env.DEV) {
|
||||
log.debug("[IPC Debug Functions] Adding Debug Handlers");
|
||||
|
||||
ipcMain.on(
|
||||
ipcTypes.toMain.debug.decodeEstimate,
|
||||
async (event, payload): Promise<void> => {
|
||||
const relativeEmsFilepath = `_reference/ems/MPI_1/3698420.ENV`;
|
||||
// Get the app's root directory and create an absolute path
|
||||
const rootDir = app.getAppPath();
|
||||
const absoluteFilepath = path.join(rootDir, relativeEmsFilepath);
|
||||
|
||||
log.debug("[IPC Debug Function] Decode test Estimate", absoluteFilepath);
|
||||
await ImportJob(absoluteFilepath);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
//Settings Handlers
|
||||
ipcMain.handle(
|
||||
ipcTypes.toMain.settings.filepaths.get,
|
||||
|
||||
@@ -11,8 +11,16 @@ const store = new Store({
|
||||
pollingInterval: 30000,
|
||||
},
|
||||
},
|
||||
app: {
|
||||
windowBounds: {
|
||||
width: 800,
|
||||
height: 600,
|
||||
x: undefined,
|
||||
y: undefined,
|
||||
},
|
||||
user: null,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export default store;
|
||||
|
||||
@@ -4,8 +4,9 @@ import log from "electron-log/main";
|
||||
import path from "path";
|
||||
import errorTypeCheck from "../../util/errorTypeCheck";
|
||||
import store from "../store/store";
|
||||
import ImportJob from "../decoder/decoder";
|
||||
|
||||
var watcher: FSWatcher;
|
||||
let watcher: FSWatcher;
|
||||
|
||||
async function StartWatcher(): Promise<boolean> {
|
||||
const filePaths = store.get("settings.filepaths") || [];
|
||||
@@ -34,8 +35,7 @@ async function StartWatcher(): Promise<boolean> {
|
||||
watcher = chokidar.watch(filePaths, {
|
||||
ignored: (filepath, stats) => {
|
||||
const p = path.parse(filepath);
|
||||
|
||||
return !stats?.isFile() && p.ext !== "" && p.ext.toUpperCase() !== ".ENV";
|
||||
return !stats?.isFile() && p.ext !== "" && p.ext.toUpperCase() !== ".ENV"; //Only watch for .ENV files.
|
||||
},
|
||||
usePolling: store.get("settings.polling").enabled || false,
|
||||
interval: store.get("settings.polling").pollingInterval || 1000,
|
||||
@@ -77,7 +77,7 @@ async function StartWatcher(): Promise<boolean> {
|
||||
return true;
|
||||
}
|
||||
|
||||
function onWatcherReady() {
|
||||
function onWatcherReady(): void {
|
||||
log.info("Watcher ready!");
|
||||
// const b = BrowserWindow.getAllWindows()[0];
|
||||
// b.webContents.send(ipcTypes.default.fileWatcher.toRenderer.startSuccess);
|
||||
@@ -102,8 +102,8 @@ async function StopWatcher(): Promise<boolean> {
|
||||
return false;
|
||||
}
|
||||
|
||||
async function HandleNewFile(path) {
|
||||
//await ImportJob(path);
|
||||
async function HandleNewFile(path): Promise<void> {
|
||||
await ImportJob(path);
|
||||
log.log("Received a new file", path);
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import {} from "react-error-boundary";
|
||||
import { ErrorBoundary } from "react-error-boundary";
|
||||
import ErrorBoundaryFallback from "./components/ErrorBoundaryFallback/ErrorBoundaryFallback";
|
||||
import Settings from "./components/Settings/Settings";
|
||||
import Home from "./components/Home/Home";
|
||||
|
||||
const App: React.FC = () => {
|
||||
const [user, setUser] = useState<User | null>(null);
|
||||
@@ -36,7 +37,7 @@ const App: React.FC = () => {
|
||||
<>
|
||||
<NavigationHeader />
|
||||
<Routes>
|
||||
<Route path="/" element={<div>AuthHome</div>} />
|
||||
<Route path="/" element={<Home />} />
|
||||
<Route path="settings" element={<Settings />} />
|
||||
</Routes>
|
||||
</>
|
||||
|
||||
21
src/renderer/src/components/Home/Home.tsx
Normal file
21
src/renderer/src/components/Home/Home.tsx
Normal file
@@ -0,0 +1,21 @@
|
||||
import { Button } from "antd";
|
||||
import ipcTypes from "../../../../util/ipcTypes.json";
|
||||
|
||||
const Home: React.FC = () => {
|
||||
return (
|
||||
<div>
|
||||
<h1>Home</h1>
|
||||
<Button
|
||||
onClick={(): void => {
|
||||
window.electron.ipcRenderer.send(
|
||||
ipcTypes.toMain.debug.decodeEstimate
|
||||
);
|
||||
}}
|
||||
>
|
||||
Test Decode Estimate
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Home;
|
||||
@@ -16,7 +16,7 @@ const SettingsWatchedPaths: React.FC = () => {
|
||||
});
|
||||
}, []);
|
||||
|
||||
const handleAddPath = () => {
|
||||
const handleAddPath = (): void => {
|
||||
window.electron.ipcRenderer
|
||||
.invoke(ipcTypes.toMain.settings.filepaths.add)
|
||||
.then((paths: string[]) => {
|
||||
@@ -24,7 +24,7 @@ const SettingsWatchedPaths: React.FC = () => {
|
||||
});
|
||||
};
|
||||
|
||||
const handleRemovePath = (path: string) => {
|
||||
const handleRemovePath = (path: string): void => {
|
||||
window.electron.ipcRenderer
|
||||
.invoke(ipcTypes.toMain.settings.filepaths.remove, path)
|
||||
.then((paths: string[]) => {
|
||||
|
||||
32
src/util/deepLowercaseKeys.ts
Normal file
32
src/util/deepLowercaseKeys.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Deep renames all keys in an object to lowercase
|
||||
* @param obj - The object to transform
|
||||
* @returns A new object with all keys converted to lowercase
|
||||
*/
|
||||
function deepLowerCaseKeys<T = any>(obj: any): T {
|
||||
if (!obj || typeof obj !== "object") {
|
||||
return obj;
|
||||
}
|
||||
|
||||
// Handle arrays
|
||||
if (Array.isArray(obj)) {
|
||||
return obj.map((item) => deepLowerCaseKeys(item)) as unknown as T;
|
||||
}
|
||||
|
||||
// Handle objects
|
||||
return Object.keys(obj).reduce(
|
||||
(result, key) => {
|
||||
const value = obj[key];
|
||||
const lowercaseKey = key.toLowerCase();
|
||||
|
||||
result[lowercaseKey] =
|
||||
typeof value === "object" && value !== null
|
||||
? deepLowerCaseKeys(value)
|
||||
: value;
|
||||
|
||||
return result;
|
||||
},
|
||||
{} as Record<string, any>
|
||||
) as T;
|
||||
}
|
||||
export default deepLowerCaseKeys;
|
||||
@@ -2,6 +2,9 @@
|
||||
"toMain": {
|
||||
"test": "toMain_test",
|
||||
"authStateChanged": "toMain_authStateChanged",
|
||||
"debug": {
|
||||
"decodeEstimate": "toMain_debug_decodeEstimate"
|
||||
},
|
||||
"watcher": {
|
||||
"start": "toMain_watcher_start",
|
||||
"stop": "toMain_watcher_stop"
|
||||
|
||||
Reference in New Issue
Block a user