From 7d881fc9e6e235976354fa6ef8eca53d114d3007 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Wed, 23 Apr 2025 13:17:10 -0400 Subject: [PATCH 01/22] feature/IO-3205-Paint-Scale-Integrations: init --- src/main/ipc/ipcMainConfig.ts | 90 ++++++--- src/main/ipc/ipcMainHandler.settings.ts | 175 ++++++++++++++++-- .../Settings.PaintScaleInputPaths.tsx | 157 ++++++++++++++++ .../Settings.PaintScaleOutputPaths.tsx | 157 ++++++++++++++++ .../src/components/Settings/Settings.tsx | 55 +++--- src/util/ipcTypes.json | 10 +- src/util/translations/en-US/renderer.json | 9 +- 7 files changed, 580 insertions(+), 73 deletions(-) create mode 100644 src/renderer/src/components/Settings/Settings.PaintScaleInputPaths.tsx create mode 100644 src/renderer/src/components/Settings/Settings.PaintScaleOutputPaths.tsx diff --git a/src/main/ipc/ipcMainConfig.ts b/src/main/ipc/ipcMainConfig.ts index 7a6f3ad..e9273bc 100644 --- a/src/main/ipc/ipcMainConfig.ts +++ b/src/main/ipc/ipcMainConfig.ts @@ -1,3 +1,4 @@ +// main/ipcMainConfig.ts import { app, ipcMain } from "electron"; import log from "electron-log/main"; import { autoUpdater } from "electron-updater"; @@ -16,6 +17,12 @@ import { SettingsWatcherPollingSet, SettingEmsOutFilePathSet, SettingEmsOutFilePathGet, + SettingsPaintScaleInputConfigsGet, + SettingsPaintScaleInputConfigsSet, + SettingsPaintScaleInputPathSet, + SettingsPaintScaleOutputConfigsGet, + SettingsPaintScaleOutputConfigsSet, + SettingsPaintScaleOutputPathSet, } from "./ipcMainHandler.settings"; import { ipcMainHandleAuthStateChanged, @@ -24,23 +31,19 @@ import { // Log all IPC messages and their payloads const logIpcMessages = (): void => { - // Get all message types from ipcTypes.toMain Object.keys(ipcTypes.toMain).forEach((key) => { const messageType = ipcTypes.toMain[key]; - - // Wrap the original handler with our logging - const originalHandler = ipcMain.listeners(messageType)[0]; + const originalHandler = ipcMain.listeners(messageType)?.[0]; if (originalHandler) { ipcMain.removeAllListeners(messageType); } ipcMain.on(messageType, (event, payload) => { log.info( - `%c[IPC Main]%c${messageType}`, - "color: red", - "color: green", - payload, + `%c[IPC Main]%c${messageType}`, + "color: red", + "color: green", + payload, ); - // Call original handler if it existed if (originalHandler) { originalHandler(event, payload); } @@ -49,20 +52,19 @@ const logIpcMessages = (): void => { }; ipcMain.on(ipcTypes.toMain.test, () => - console.log("** Verify that ipcMain is loaded and working."), + console.log("** Verify that ipcMain is loaded and working."), ); -//Auth handler +// Auth handler ipcMain.on(ipcTypes.toMain.authStateChanged, ipcMainHandleAuthStateChanged); ipcMain.on(ipcTypes.toMain.user.resetPassword, ipMainHandleResetPassword); -//Add debug handlers if in development +// 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 (): Promise => { 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); @@ -76,44 +78,72 @@ if (import.meta.env.DEV) { }); } -//Settings Handlers +// Settings Handlers ipcMain.handle( - ipcTypes.toMain.settings.filepaths.get, - SettingsWatchedFilePathsGet, + ipcTypes.toMain.settings.filepaths.get, + SettingsWatchedFilePathsGet, ); ipcMain.handle( - ipcTypes.toMain.settings.filepaths.add, - SettingsWatchedFilePathsAdd, + ipcTypes.toMain.settings.filepaths.add, + SettingsWatchedFilePathsAdd, ); ipcMain.handle( - ipcTypes.toMain.settings.filepaths.remove, - SettingsWatchedFilePathsRemove, + ipcTypes.toMain.settings.filepaths.remove, + SettingsWatchedFilePathsRemove, ); ipcMain.handle( - ipcTypes.toMain.settings.watcher.getpolling, - SettingsWatcherPollingGet, + ipcTypes.toMain.settings.watcher.getpolling, + SettingsWatcherPollingGet, ); ipcMain.handle( - ipcTypes.toMain.settings.watcher.setpolling, - SettingsWatcherPollingSet, + ipcTypes.toMain.settings.watcher.setpolling, + SettingsWatcherPollingSet, ); ipcMain.handle(ipcTypes.toMain.settings.getPpcFilePath, SettingsPpcFilePathGet); ipcMain.handle(ipcTypes.toMain.settings.setPpcFilePath, SettingsPpcFilePathSet); ipcMain.handle( - ipcTypes.toMain.settings.getEmsOutFilePath, - SettingEmsOutFilePathGet, + ipcTypes.toMain.settings.getEmsOutFilePath, + SettingEmsOutFilePathGet, ); ipcMain.handle( - ipcTypes.toMain.settings.setEmsOutFilePath, - SettingEmsOutFilePathSet, + ipcTypes.toMain.settings.setEmsOutFilePath, + SettingEmsOutFilePathSet, +); + +// Paint Scale Input Settings Handlers +ipcMain.handle( + ipcTypes.toMain.settings.paintScale.getInputConfigs, + SettingsPaintScaleInputConfigsGet, +); +ipcMain.handle( + ipcTypes.toMain.settings.paintScale.setInputConfigs, + SettingsPaintScaleInputConfigsSet, +); +ipcMain.handle( + ipcTypes.toMain.settings.paintScale.setInputPath, + SettingsPaintScaleInputPathSet, +); + +// Paint Scale Output Settings Handlers +ipcMain.handle( + ipcTypes.toMain.settings.paintScale.getOutputConfigs, + SettingsPaintScaleOutputConfigsGet, +); +ipcMain.handle( + ipcTypes.toMain.settings.paintScale.setOutputConfigs, + SettingsPaintScaleOutputConfigsSet, +); +ipcMain.handle( + ipcTypes.toMain.settings.paintScale.setOutputPath, + SettingsPaintScaleOutputPathSet, ); ipcMain.handle(ipcTypes.toMain.user.getActiveShop, () => { return store.get("app.bodyshop.shopname"); }); -//Watcher Handlers +// Watcher Handlers ipcMain.on(ipcTypes.toMain.watcher.start, () => { StartWatcher(); }); @@ -127,4 +157,4 @@ ipcMain.on(ipcTypes.toMain.updates.download, () => { autoUpdater.downloadUpdate(); }); -logIpcMessages(); +logIpcMessages(); \ No newline at end of file diff --git a/src/main/ipc/ipcMainHandler.settings.ts b/src/main/ipc/ipcMainHandler.settings.ts index a066d79..dbb3bb8 100644 --- a/src/main/ipc/ipcMainHandler.settings.ts +++ b/src/main/ipc/ipcMainHandler.settings.ts @@ -1,9 +1,31 @@ -import {dialog, IpcMainInvokeEvent} from "electron"; +// main/ipcMainHandler.settings.ts +import { dialog, IpcMainInvokeEvent } from "electron"; import log from "electron-log/main"; import _ from "lodash"; import Store from "../store/store"; -import {getMainWindow} from "../util/toRenderer"; -import {addWatcherPath, removeWatcherPath, StartWatcher, StopWatcher,} from "../watcher/watcher"; +import { getMainWindow } from "../util/toRenderer"; +import { + addWatcherPath, + removeWatcherPath, + StartWatcher, + StopWatcher, +} from "../watcher/watcher"; + +interface PaintScaleConfig { + id: string; + path: string | null; + type: string; +} + +// Initialize paint scale input configs in store if not set +if (!Store.get("settings.paintScaleInputConfigs")) { + Store.set("settings.paintScaleInputConfigs", []); +} + +// Initialize paint scale output configs in store if not set +if (!Store.get("settings.paintScaleOutputConfigs")) { + Store.set("settings.paintScaleOutputConfigs", []); +} const SettingsWatchedFilePathsAdd = async (): Promise => { const mainWindow = getMainWindow(); @@ -17,21 +39,22 @@ const SettingsWatchedFilePathsAdd = async (): Promise => { if (!result.canceled) { Store.set( - "settings.filepaths", - _.union(result.filePaths, Store.get("settings.filepaths")), + "settings.filepaths", + _.union(result.filePaths, Store.get("settings.filepaths")), ); addWatcherPath(result.filePaths); } return Store.get("settings.filepaths"); }; + const SettingsWatchedFilePathsRemove = async ( - _event: IpcMainInvokeEvent, - path: string, + _event: IpcMainInvokeEvent, + path: string, ): Promise => { Store.set( - "settings.filepaths", - _.without(Store.get("settings.filepaths"), path), + "settings.filepaths", + _.without(Store.get("settings.filepaths"), path), ); removeWatcherPath(path); return Store.get("settings.filepaths"); @@ -46,15 +69,16 @@ const SettingsWatcherPollingGet = async (): Promise<{ interval: number; }> => { const pollingEnabled: { enabled: boolean; interval: number } = - Store.get("settings.polling"); + Store.get("settings.polling"); return { enabled: pollingEnabled.enabled, interval: pollingEnabled.interval }; }; + const SettingsWatcherPollingSet = async ( - _event: IpcMainInvokeEvent, - pollingSettings: { - enabled: boolean; - interval: number; - }, + _event: IpcMainInvokeEvent, + pollingSettings: { + enabled: boolean; + interval: number; + }, ): Promise<{ enabled: boolean; interval: number; @@ -63,15 +87,16 @@ const SettingsWatcherPollingSet = async ( const { enabled, interval } = pollingSettings; Store.set("settings.polling", { enabled, interval }); - //Restart the watcher with these new settings. await StopWatcher(); await StartWatcher(); return { enabled, interval }; }; + const SettingsPpcFilePathGet = async (): Promise => { return Store.get("settings.ppcFilePath"); }; + const SettingsPpcFilePathSet = async (): Promise => { const mainWindow = getMainWindow(); if (!mainWindow) { @@ -83,14 +108,16 @@ const SettingsPpcFilePathSet = async (): Promise => { }); if (!result.canceled) { - Store.set("settings.ppcFilePath", result.filePaths[0]); //There should only ever be on directory that was selected. + Store.set("settings.ppcFilePath", result.filePaths[0]); } return (Store.get("settings.ppcFilePath") as string) || ""; }; + const SettingEmsOutFilePathGet = async (): Promise => { return Store.get("settings.emsOutFilePath"); }; + const SettingEmsOutFilePathSet = async (): Promise => { const mainWindow = getMainWindow(); if (!mainWindow) { @@ -102,12 +129,116 @@ const SettingEmsOutFilePathSet = async (): Promise => { }); if (!result.canceled) { - Store.set("settings.emsOutFilePath", result.filePaths[0]); //There should only ever be on directory that was selected. + Store.set("settings.emsOutFilePath", result.filePaths[0]); } return (Store.get("settings.emsOutFilePath") as string) || ""; }; +const SettingsPaintScaleInputConfigsGet = async ( + _event: IpcMainInvokeEvent, +): Promise => { + try { + const configs = Store.get("settings.paintScaleInputConfigs") as PaintScaleConfig[]; + log.debug("Retrieved paint scale input configs:", configs); + return configs || []; + } catch (error) { + log.error("Error getting paint scale input configs:", error); + throw error; + } +}; + +const SettingsPaintScaleInputConfigsSet = async ( + _event: IpcMainInvokeEvent, + configs: PaintScaleConfig[], +): Promise => { + try { + Store.set("settings.paintScaleInputConfigs", configs); + log.debug("Saved paint scale input configs:", configs); + return true; + } catch (error) { + log.error("Error setting paint scale input configs:", error); + throw error; + } +}; + +const SettingsPaintScaleInputPathSet = async ( + _event: IpcMainInvokeEvent, +): Promise => { + try { + const mainWindow = getMainWindow(); + if (!mainWindow) { + log.error("No main window found when trying to open dialog"); + return null; + } + const result = await dialog.showOpenDialog(mainWindow, { + properties: ["openDirectory"], + }); + if (result.canceled) { + log.debug("Paint scale input path selection canceled"); + return null; + } + const path = result.filePaths[0]; + log.debug("Selected paint scale input path:", path); + return path; + } catch (error) { + log.error("Error setting paint scale input path:", error); + throw error; + } +}; + +const SettingsPaintScaleOutputConfigsGet = async ( + _event: IpcMainInvokeEvent, +): Promise => { + try { + const configs = Store.get("settings.paintScaleOutputConfigs") as PaintScaleConfig[]; + log.debug("Retrieved paint scale output configs:", configs); + return configs || []; + } catch (error) { + log.error("Error getting paint scale output configs:", error); + throw error; + } +}; + +const SettingsPaintScaleOutputConfigsSet = async ( + _event: IpcMainInvokeEvent, + configs: PaintScaleConfig[], +): Promise => { + try { + Store.set("settings.paintScaleOutputConfigs", configs); + log.debug("Saved paint scale output configs:", configs); + return true; + } catch (error) { + log.error("Error setting paint scale output configs:", error); + throw error; + } +}; + +const SettingsPaintScaleOutputPathSet = async ( + _event: IpcMainInvokeEvent, +): Promise => { + try { + const mainWindow = getMainWindow(); + if (!mainWindow) { + log.error("No main window found when trying to open dialog"); + return null; + } + const result = await dialog.showOpenDialog(mainWindow, { + properties: ["openDirectory"], + }); + if (result.canceled) { + log.debug("Paint scale output path selection canceled"); + return null; + } + const path = result.filePaths[0]; + log.debug("Selected paint scale output path:", path); + return path; + } catch (error) { + log.error("Error setting paint scale output path:", error); + throw error; + } +}; + export { SettingsPpcFilePathGet, SettingsPpcFilePathSet, @@ -118,4 +249,10 @@ export { SettingsWatcherPollingSet, SettingEmsOutFilePathGet, SettingEmsOutFilePathSet, -}; + SettingsPaintScaleInputConfigsGet, + SettingsPaintScaleInputConfigsSet, + SettingsPaintScaleInputPathSet, + SettingsPaintScaleOutputConfigsGet, + SettingsPaintScaleOutputConfigsSet, + SettingsPaintScaleOutputPathSet, +}; \ No newline at end of file diff --git a/src/renderer/src/components/Settings/Settings.PaintScaleInputPaths.tsx b/src/renderer/src/components/Settings/Settings.PaintScaleInputPaths.tsx new file mode 100644 index 0000000..03bac0d --- /dev/null +++ b/src/renderer/src/components/Settings/Settings.PaintScaleInputPaths.tsx @@ -0,0 +1,157 @@ +// renderer/Settings.PaintScaleInputPaths.tsx +import { FolderOpenFilled } from "@ant-design/icons"; +import { Button, Card, Input, Select, Space, Table } from "antd"; +import { FC, useEffect, useState } from "react"; +import { useTranslation } from "react-i18next"; +import ipcTypes from "../../../../util/ipcTypes.json"; + +interface PaintScaleConfig { + id: string; + path: string | null; + type: PaintScaleType; +} + +enum PaintScaleType { + PPG = "PPG", + SHERWIN = "SHERWIN", + AKZO = "AKZO", +} + +const paintScaleTypeOptions = Object.values(PaintScaleType).map((type) => ({ + value: type, + label: type, +})); + +const SettingsPaintScaleInputPaths: FC = () => { + const { t } = useTranslation(); + const [paintScaleConfigs, setPaintScaleConfigs] = useState([]); + + // Load paint scale input configs from store on mount + useEffect(() => { + window.electron.ipcRenderer + .invoke(ipcTypes.toMain.settings.paintScale.getInputConfigs) + .then((configs: PaintScaleConfig[]) => { + setPaintScaleConfigs(configs || []); + }) + .catch((error) => { + console.error("Failed to load paint scale input configs:", error); + }); + }, []); + + // Handle adding a new paint scale config + const handleAddConfig = () => { + const newConfig: PaintScaleConfig = { + id: Date.now().toString(), + path: null, + type: PaintScaleType.PPG, + }; + const updatedConfigs = [...paintScaleConfigs, newConfig]; + setPaintScaleConfigs(updatedConfigs); + saveConfigs(updatedConfigs); + }; + + // Handle removing a config + const handleRemoveConfig = (id: string) => { + const updatedConfigs = paintScaleConfigs.filter((config) => config.id !== id); + setPaintScaleConfigs(updatedConfigs); + saveConfigs(updatedConfigs); + }; + + // Handle path selection + const handlePathChange = (id: string) => { + window.electron.ipcRenderer + .invoke(ipcTypes.toMain.settings.paintScale.setInputPath, id) + .then((path: string | null) => { + if (path) { + const updatedConfigs = paintScaleConfigs.map((config) => + config.id === id ? { ...config, path } : config, + ); + setPaintScaleConfigs(updatedConfigs); + saveConfigs(updatedConfigs); + } + }) + .catch((error) => { + console.error("Failed to set paint scale input path:", error); + }); + }; + + // Handle type change + const handleTypeChange = (id: string, type: PaintScaleType) => { + const updatedConfigs = paintScaleConfigs.map((config) => + config.id === id ? { ...config, type } : config, + ); + setPaintScaleConfigs(updatedConfigs); + saveConfigs(updatedConfigs); + }; + + // Save configs to store + const saveConfigs = (configs: PaintScaleConfig[]) => { + window.electron.ipcRenderer + .invoke(ipcTypes.toMain.settings.paintScale.setInputConfigs, configs) + .catch((error) => { + console.error("Failed to save paint scale input configs:", error); + }); + }; + + // Table columns for paint scale configs + const columns = [ + { + title: t("settings.labels.paintScalePath"), + dataIndex: "path", + key: "path", + render: (path: string | null, record: PaintScaleConfig) => ( + + + - - + } onClick={handleAddConfig}> + {t("settings.actions.addpath")} + + } + > +
); }; diff --git a/src/renderer/src/components/Settings/Settings.PaintScaleOutputPaths.tsx b/src/renderer/src/components/Settings/Settings.PaintScaleOutputPaths.tsx index dbb6edb..5dca32b 100644 --- a/src/renderer/src/components/Settings/Settings.PaintScaleOutputPaths.tsx +++ b/src/renderer/src/components/Settings/Settings.PaintScaleOutputPaths.tsx @@ -1,118 +1,27 @@ -// renderer/Settings.PaintScaleOutputPaths.tsx -import { FolderOpenFilled } from "@ant-design/icons"; +import { FileAddFilled, FolderOpenFilled, CheckCircleFilled, WarningFilled } from "@ant-design/icons"; import { Button, Card, Input, Select, Space, Table } from "antd"; -import { FC, useEffect, useState } from "react"; +import { FC } from "react"; import { useTranslation } from "react-i18next"; -import ipcTypes from "../../../../util/ipcTypes.json"; - -interface PaintScaleConfig { - id: string; - path: string | null; - type: PaintScaleType; -} - -enum PaintScaleType { - PPG = "PPG", - SHERWIN = "SHERWIN", - AKZO = "AKZO", -} - -const paintScaleTypeOptions = Object.values(PaintScaleType).map((type) => ({ - value: type, - label: type, -})); +import { + PaintScaleConfig, + PaintScaleType, + paintScaleTypeOptions, +} from "./PaintScale/types"; +import { usePaintScaleConfig } from "./PaintScale/usePaintScaleConfig"; const SettingsPaintScaleOutputPaths: FC = () => { const { t } = useTranslation(); - const [paintScaleConfigs, setPaintScaleConfigs] = useState([]); - - // Load paint scale output configs from store on mount - useEffect(() => { - window.electron.ipcRenderer - .invoke(ipcTypes.toMain.settings.paintScale.getOutputConfigs) - .then((configs: PaintScaleConfig[]) => { - setPaintScaleConfigs(configs || []); - }) - .catch((error) => { - console.error("Failed to load paint scale output configs:", error); - }); - }, []); - - // Handle adding a new paint scale config - const handleAddConfig = () => { - const newConfig: PaintScaleConfig = { - id: Date.now().toString(), - path: null, - type: PaintScaleType.PPG, - }; - const updatedConfigs = [...paintScaleConfigs, newConfig]; - setPaintScaleConfigs(updatedConfigs); - saveConfigs(updatedConfigs); - }; - - // Handle removing a config - const handleRemoveConfig = (id: string) => { - const updatedConfigs = paintScaleConfigs.filter((config) => config.id !== id); - setPaintScaleConfigs(updatedConfigs); - saveConfigs(updatedConfigs); - }; - - // Handle path selection - const handlePathChange = (id: string) => { - window.electron.ipcRenderer - .invoke(ipcTypes.toMain.settings.paintScale.setOutputPath, id) - .then((path: string | null) => { - if (path) { - const updatedConfigs = paintScaleConfigs.map((config) => - config.id === id ? { ...config, path } : config, - ); - setPaintScaleConfigs(updatedConfigs); - saveConfigs(updatedConfigs); - } - }) - .catch((error) => { - console.error("Failed to set paint scale output path:", error); - }); - }; - - // Handle type change - const handleTypeChange = (id: string, type: PaintScaleType) => { - const updatedConfigs = paintScaleConfigs.map((config) => - config.id === id ? { ...config, type } : config, - ); - setPaintScaleConfigs(updatedConfigs); - saveConfigs(updatedConfigs); - }; - - // Save configs to store - const saveConfigs = (configs: PaintScaleConfig[]) => { - window.electron.ipcRenderer - .invoke(ipcTypes.toMain.settings.paintScale.setOutputConfigs, configs) - .catch((error) => { - console.error("Failed to save paint scale output configs:", error); - }); - }; + const { + paintScaleConfigs, + handleAddConfig, + handleRemoveConfig, + handlePathChange, + handleTypeChange, + handlePollingIntervalChange, + } = usePaintScaleConfig("output"); // Table columns for paint scale configs const columns = [ - { - title: t("settings.labels.paintScalePath"), - dataIndex: "path", - key: "path", - render: (path: string | null, record: PaintScaleConfig) => ( - - - -
- + }> + {t("settings.actions.addpath")} + + } + > +
); }; diff --git a/src/renderer/src/util/graphql.client.ts b/src/renderer/src/util/graphql.client.ts index 5ddac51..939baa0 100644 --- a/src/renderer/src/util/graphql.client.ts +++ b/src/renderer/src/util/graphql.client.ts @@ -1,13 +1,13 @@ import { ApolloClient, ApolloLink, - HttpLink, + // HttpLink, InMemoryCache, } from "@apollo/client"; -const httpLink: HttpLink = new HttpLink({ - uri: import.meta.env.VITE_GRAPHQL_URL, -}); +// const httpLink: HttpLink = new HttpLink({ +// uri: import.meta.env.VITE_GRAPHQL_URL, +// }); const middlewares = []; diff --git a/src/util/translations/en-US/renderer.json b/src/util/translations/en-US/renderer.json index 4e1efaf..7d4eed5 100644 --- a/src/util/translations/en-US/renderer.json +++ b/src/util/translations/en-US/renderer.json @@ -35,13 +35,16 @@ "watchermodepolling": "Polling", "watchermoderealtime": "Real Time", "watcherstatus": "Watcher Status", - "paintScaleSettingsInput": "Paint Scale Settings Input", - "paintScaleSettingsOutput": "Paint Scale Settings Output", + "paintScaleSettingsInput": "Paint Scale Input Paths", + "paintScaleSettingsOutput": "Paint Scale Output Paths", "paintScalePath": "Paint Scale Path", "paintScaleType": "Paint Scale Type", "addPaintScalePath": "Add Paint Scale Path", "remove": "Remove", - "actions": "Actions" + "actions": "Actions", + "pollingInterval": "Polling Interval (s)", + "validPath": "Valid path", + "invalidPath": "Path not set or invalid" } }, "title": { From c73db112c70ac15133dd7e262ea3beccb4187873 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Mon, 28 Apr 2025 09:26:15 -0400 Subject: [PATCH 03/22] feature/IO-3205-Paint-Scale-Integrations: Checkpoint --- .idea/material_theme_project_new.xml | 4 +- .../PaintScale/usePaintScaleConfig.ts | 100 +++++----- .../Settings.PaintScaleInputPaths.tsx | 179 ++++++++++++------ .../Settings.PaintScaleOutputPaths.tsx | 161 ++++++++++------ src/util/translations/en-US/renderer.json | 5 +- 5 files changed, 276 insertions(+), 173 deletions(-) diff --git a/.idea/material_theme_project_new.xml b/.idea/material_theme_project_new.xml index 0cb5647..4647599 100644 --- a/.idea/material_theme_project_new.xml +++ b/.idea/material_theme_project_new.xml @@ -3,7 +3,9 @@ diff --git a/src/renderer/src/components/Settings/PaintScale/usePaintScaleConfig.ts b/src/renderer/src/components/Settings/PaintScale/usePaintScaleConfig.ts index b6fb7da..e2859bb 100644 --- a/src/renderer/src/components/Settings/PaintScale/usePaintScaleConfig.ts +++ b/src/renderer/src/components/Settings/PaintScale/usePaintScaleConfig.ts @@ -8,51 +8,52 @@ export const usePaintScaleConfig = (configType: ConfigType) => { const [paintScaleConfigs, setPaintScaleConfigs] = useState([]); // Get the appropriate IPC methods based on config type - const getConfigsMethod = configType === 'input' - ? ipcTypes.toMain.settings.paintScale.getInputConfigs - : ipcTypes.toMain.settings.paintScale.getOutputConfigs; - + const getConfigsMethod = configType === 'input' + ? ipcTypes.toMain.settings.paintScale.getInputConfigs + : ipcTypes.toMain.settings.paintScale.getOutputConfigs; + const setConfigsMethod = configType === 'input' - ? ipcTypes.toMain.settings.paintScale.setInputConfigs - : ipcTypes.toMain.settings.paintScale.setOutputConfigs; - + ? ipcTypes.toMain.settings.paintScale.setInputConfigs + : ipcTypes.toMain.settings.paintScale.setOutputConfigs; + const setPathMethod = configType === 'input' - ? ipcTypes.toMain.settings.paintScale.setInputPath - : ipcTypes.toMain.settings.paintScale.setOutputPath; + ? ipcTypes.toMain.settings.paintScale.setInputPath + : ipcTypes.toMain.settings.paintScale.setOutputPath; // Load paint scale configs on mount useEffect(() => { window.electron.ipcRenderer - .invoke(getConfigsMethod) - .then((configs: PaintScaleConfig[]) => { - // Ensure all configs have a pollingInterval (for backward compatibility) - const updatedConfigs = configs.map(config => ({ - ...config, - pollingInterval: config.pollingInterval || 60 // Default to 60 seconds if not set - })); - setPaintScaleConfigs(updatedConfigs || []); - }) - .catch((error) => { - console.error(`Failed to load paint scale ${configType} configs:`, error); - }); + .invoke(getConfigsMethod) + .then((configs: PaintScaleConfig[]) => { + // Ensure all configs have a pollingInterval and type (for backward compatibility) + const updatedConfigs = configs.map(config => ({ + ...config, + pollingInterval: config.pollingInterval || 1440, // Default to 1440 seconds if not set + type: config.type || PaintScaleType.PPG, // Default type if missing + })); + setPaintScaleConfigs(updatedConfigs || []); + }) + .catch((error) => { + console.error(`Failed to load paint scale ${configType} configs:`, error); + }); }, [getConfigsMethod]); // Save configs to store const saveConfigs = (configs: PaintScaleConfig[]) => { window.electron.ipcRenderer - .invoke(setConfigsMethod, configs) - .catch((error) => { - console.error(`Failed to save paint scale ${configType} configs:`, error); - }); + .invoke(setConfigsMethod, configs) + .catch((error) => { + console.error(`Failed to save paint scale ${configType} configs:`, error); + }); }; // Handle adding a new paint scale config - const handleAddConfig = () => { + const handleAddConfig = (type: PaintScaleType) => { const newConfig: PaintScaleConfig = { id: Date.now().toString(), path: null, - type: PaintScaleType.PPG, - pollingInterval: 60, // Default to 60 seconds + type, + pollingInterval: 1440, // Default to 1440 seconds }; const updatedConfigs = [...paintScaleConfigs, newConfig]; setPaintScaleConfigs(updatedConfigs); @@ -69,34 +70,25 @@ export const usePaintScaleConfig = (configType: ConfigType) => { // Handle path selection const handlePathChange = (id: string) => { window.electron.ipcRenderer - .invoke(setPathMethod, id) - .then((path: string | null) => { - if (path) { - const updatedConfigs = paintScaleConfigs.map((config) => - config.id === id ? { ...config, path } : config, - ); - setPaintScaleConfigs(updatedConfigs); - saveConfigs(updatedConfigs); - } - }) - .catch((error) => { - console.error(`Failed to set paint scale ${configType} path:`, error); - }); - }; - - // Handle type change - const handleTypeChange = (id: string, type: PaintScaleType) => { - const updatedConfigs = paintScaleConfigs.map((config) => - config.id === id ? { ...config, type } : config, - ); - setPaintScaleConfigs(updatedConfigs); - saveConfigs(updatedConfigs); + .invoke(setPathMethod, id) + .then((path: string | null) => { + if (path) { + const updatedConfigs = paintScaleConfigs.map((config) => + config.id === id ? { ...config, path } : config, + ); + setPaintScaleConfigs(updatedConfigs); + saveConfigs(updatedConfigs); + } + }) + .catch((error) => { + console.error(`Failed to set paint scale ${configType} path:`, error); + }); }; // Handle polling interval change const handlePollingIntervalChange = (id: string, pollingInterval: number) => { const updatedConfigs = paintScaleConfigs.map((config) => - config.id === id ? { ...config, pollingInterval } : config, + config.id === id ? { ...config, pollingInterval } : config, ); setPaintScaleConfigs(updatedConfigs); saveConfigs(updatedConfigs); @@ -107,8 +99,6 @@ export const usePaintScaleConfig = (configType: ConfigType) => { handleAddConfig, handleRemoveConfig, handlePathChange, - handleTypeChange, - handlePollingIntervalChange + handlePollingIntervalChange, }; -}; - +}; \ No newline at end of file diff --git a/src/renderer/src/components/Settings/Settings.PaintScaleInputPaths.tsx b/src/renderer/src/components/Settings/Settings.PaintScaleInputPaths.tsx index 126009e..187ff77 100644 --- a/src/renderer/src/components/Settings/Settings.PaintScaleInputPaths.tsx +++ b/src/renderer/src/components/Settings/Settings.PaintScaleInputPaths.tsx @@ -1,6 +1,21 @@ -import { FileAddFilled, FolderOpenFilled, CheckCircleFilled, WarningFilled } from "@ant-design/icons"; -import { Button, Card, Input, Select, Space, Table, Tooltip } from "antd"; -import { FC } from "react"; +import { + CheckCircleFilled, + FileAddFilled, + FolderOpenFilled, + WarningFilled, +} from "@ant-design/icons"; +import { + Button, + Card, + Input, + Modal, + Select, + Space, + Table, + Tag, + Tooltip, +} from "antd"; +import { FC, useState } from "react"; import { useTranslation } from "react-i18next"; import { PaintScaleConfig, @@ -16,55 +31,85 @@ const SettingsPaintScaleInputPaths: FC = () => { handleAddConfig, handleRemoveConfig, handlePathChange, - handleTypeChange, handlePollingIntervalChange, } = usePaintScaleConfig("input"); + const [isModalVisible, setIsModalVisible] = useState(false); + const [selectedType, setSelectedType] = useState(null); + + // Show modal when adding a new path + const showAddPathModal = () => { + setSelectedType(null); + setIsModalVisible(true); + }; + + // Handle modal confirmation + const handleModalOk = () => { + if (selectedType) { + handleAddConfig(selectedType); + setIsModalVisible(false); + } + }; + + // Handle modal cancellation + const handleModalCancel = () => { + setIsModalVisible(false); + }; + // Table columns for paint scale configs const columns = [ { title: t("settings.labels.paintScaleType"), dataIndex: "type", key: "type", - render: (type: PaintScaleType, record: PaintScaleConfig) => ( - - {isValid ? ( - - ) : ( - - )} - + + - + ), }, ]; return ( + <> } onClick={handleAddConfig}> - {t("settings.actions.addpath")} - - } + title={t("settings.labels.paintScaleSettingsInput")} + extra={ + + } >
+ + + handleTypeChange(record.id, value)} - style={{ width: 120 }} - /> - ), + render: (type: PaintScaleType) => { + const typeOption = paintScaleTypeOptions.find( + (option) => option.value === type, + ); + const label = typeOption ? typeOption.label : type; + const colorMap: Partial> = { + [PaintScaleType.PPG]: "blue", + // Add other types and colors as needed + }; + return {label}; + }, }, { title: t("settings.labels.paintScalePath"), dataIndex: "path", key: "path", render: (path: string | null, record: PaintScaleConfig) => { - const isValid = path && path.trim() !== ""; // Simple validity check + const isValid = path && path.trim() !== ""; return ( - - - ) : ( - - ) - } - /> - + ), }, ]; return ( + <> }> - {t("settings.actions.addpath")} - - } + title={t("settings.labels.paintScaleSettingsOutput")} + extra={ + + } >
+ + +