Minor bug fixes and CI change.

This commit is contained in:
Patrick Fic
2025-04-01 10:16:24 -07:00
parent ab3de9a382
commit 88dd8adfa5
12 changed files with 150 additions and 38 deletions

View File

@@ -41,6 +41,8 @@ function createWindow(): void {
x,
y,
show: false,
minWidth: 600,
minHeight: 400,
//autoHideMenuBar: true,
...(process.platform === "linux" ? { icon } : {}),
webPreferences: {

View File

@@ -13,7 +13,10 @@ import {
SettingsWatcherPollingGet,
SettingsWatcherPollingSet,
} from "./ipcMainHandler.settings";
import { ipcMainHandleAuthStateChanged } from "./ipcMainHandler.user";
import {
ipcMainHandleAuthStateChanged,
ipMainHandleResetPassword,
} from "./ipcMainHandler.user";
// Log all IPC messages and their payloads
const logIpcMessages = (): void => {
@@ -47,6 +50,7 @@ ipcMain.on(ipcTypes.toMain.test, () =>
//Auth handler
ipcMain.on(ipcTypes.toMain.authStateChanged, ipcMainHandleAuthStateChanged);
ipcMain.on(ipcTypes.toMain.user.resetPassword, ipMainHandleResetPassword);
//Add debug handlers if in development
if (import.meta.env.DEV) {

View File

@@ -1,4 +1,4 @@
import { IpcMainEvent } from "electron";
import { IpcMainEvent, shell } from "electron";
import log from "electron-log/main";
import { autoUpdater } from "electron-updater";
import { User } from "firebase/auth";
@@ -10,13 +10,16 @@ import {
QUERY_MASTERDATA_TYPED,
} from "../graphql/queries";
import Store from "../store/store";
import errorTypeCheck from "../../util/errorTypeCheck";
import { sendIpcToRenderer } from "../util/toRenderer";
import ipcTypes from "../../util/ipcTypes.json";
const ipcMainHandleAuthStateChanged = async (
event: IpcMainEvent,
_event: IpcMainEvent,
user: User | null,
): Promise<void> => {
Store.set("user", user);
try {
//Need to query the currently active shop, and store the metadata as well.
//Also need to query the OP Codes for decoding reference.
const activeBodyshop: ActiveBodyshopQueryResult = await client.request(
@@ -31,7 +34,10 @@ const ipcMainHandleAuthStateChanged = async (
key: `${activeBodyshop.bodyshops[0].region_config}_ciecaopcodes`,
},
);
Store.set("app.masterdata.opcodes", JSON.parse(OpCodes.masterdata[0]?.value));
Store.set(
"app.masterdata.opcodes",
JSON.parse(OpCodes.masterdata[0]?.value),
);
log.debug("Received authentication state change from Renderer.", user);
log.debug("Requery shop information & master data.");
@@ -42,7 +48,21 @@ const ipcMainHandleAuthStateChanged = async (
} else if (convCo === "beta") {
autoUpdater.channel = "beta";
}
} catch (error) {
log.error(
"Error while querying active bodyshop or masterdata",
errorTypeCheck(error),
);
sendIpcToRenderer(
ipcTypes.toRenderer.general.showErrorMessage,
"Error connecting to ImEX Online servers to get shop data. Please try again.",
);
}
autoUpdater.checkForUpdatesAndNotify();
};
export { ipcMainHandleAuthStateChanged };
const ipMainHandleResetPassword = async (): Promise<void> => {
shell.openExternal("https://imex.online/resetpassword");
};
export { ipcMainHandleAuthStateChanged, ipMainHandleResetPassword };

View File

@@ -0,0 +1,21 @@
import { BrowserWindow } from "electron";
import log from "electron-log/main";
const getMainWindow = (): Electron.BrowserWindow => {
const mainWindow = BrowserWindow.getAllWindows()[0];
return mainWindow;
};
const sendIpcToRenderer = (ipcMessage: string, ...args: any[]): void => {
const window = getMainWindow();
if (window) {
window.webContents.send(ipcMessage, ...args);
} else {
log.error(
"Unable to find main window. Cannot send IPC message.",
ipcMessage,
args,
);
}
};
export { getMainWindow, sendIpcToRenderer };

View File

@@ -12,7 +12,7 @@ const ErrorBoundaryFallback: React.FC<FallbackProps> = ({
return (
<Result
status={"500"}
title={t("app.errors.errorboundary")}
title={t("errors.errorboundary")}
subTitle={error?.message}
extra={[
<Button key="try-again" onClick={resetErrorBoundary}>

View File

@@ -73,7 +73,7 @@ const SettingsWatcher: React.FC = () => {
return (
<Card title={t("settings.labels.watcherstatus")}>
<Space>
<Space wrap>
{isWatcherStarted ? (
<Button onClick={handleStop}>
{t("settings.actions.stopwatcher")}
@@ -100,7 +100,7 @@ const SettingsWatcher: React.FC = () => {
checkedChildren={t("settings.labels.watchermoderealtime")}
unCheckedChildren={t("settings.labels.watchermodepolling")}
/>
<Space size="small">
<Space size="small" wrap>
<span>{t("settings.labels.pollinginterval")}</span>
<InputNumber
title={t("settings.labels.pollinginterval")}

View File

@@ -1,11 +1,12 @@
import { auth } from "@renderer/util/firebase";
import type { FormProps } from "antd";
import { Alert, Button, Form, Input } from "antd";
import { Alert, Button, Form, Input, Space } from "antd";
import log from "electron-log/renderer";
import { signInWithEmailAndPassword } from "firebase/auth";
import { useState } from "react";
import { useTranslation } from "react-i18next";
import errorTypeCheck from "../../../../util/errorTypeCheck";
import ipcTypes from "../../../../util/ipcTypes.json";
type FieldType = {
username: string;
@@ -15,15 +16,19 @@ type FieldType = {
const SignInForm: React.FC = () => {
const [error, setError] = useState<string | null>(null);
const [loading, setLoading] = useState<boolean>(false);
const { t } = useTranslation();
const onFinish: FormProps<FieldType>["onFinish"] = async (values) => {
const { username, password } = values;
setLoading(true);
try {
const result = await signInWithEmailAndPassword(auth, username, password);
log.debug("Login result", result);
} catch (error) {
log.error("Login error", errorTypeCheck(error));
setError(t("auth.login.error"));
} finally {
setLoading(false);
}
};
@@ -59,18 +64,27 @@ const SignInForm: React.FC = () => {
<Input.Password />
</Form.Item>
<Form.Item label={null}>
<Button type="primary" htmlType="submit">
<Space>
<Button type="primary" loading={loading} htmlType="submit">
{t("auth.login.login")}
</Button>
<Button
onClick={(): void => {
window.electron.ipcRenderer.send(
ipcTypes.toMain.user.resetPassword,
);
}}
>
{t("auth.login.resetpassword")}
</Button>
</Space>
</Form.Item>
{error && (
<Form.Item label={null}>
<Alert message={error} type="error" />
</Form.Item>
)}
<Form.Item label={null}>
<Button>{t("auth.login.resetpassword")}</Button>
</Form.Item>
<Form.Item label={null}></Form.Item>
</Form>
);
};

View File

@@ -12,6 +12,8 @@ import {
import store from "@renderer/redux/redux-store";
import ipcTypes from "../../../util/ipcTypes.json";
import { auth } from "./firebase";
import { notification } from "antd";
import i18n from "./i18n";
const ipcRenderer = window.electron.ipcRenderer;
const dispatch = store.dispatch;
@@ -74,3 +76,13 @@ ipcRenderer.on(
);
},
);
ipcRenderer.on(
ipcTypes.toRenderer.general.showErrorMessage,
(_event: Electron.IpcRendererEvent, error) => {
notification.error({
message: i18n.t("errors.notificationtitle"),
description: error,
});
},
);

View File

@@ -27,7 +27,8 @@
},
"user": {
"getTokenResponse": "toMain_user_getTokenResponse",
"getActiveShop": "toMain_user_getActiveShopify"
"getActiveShop": "toMain_user_getActiveShopify",
"resetPassword": "toMain_user_resetPassword"
}
},
"toRenderer": {
@@ -48,6 +49,9 @@
},
"user": {
"getToken": "toRenderer_user_getToken"
},
"general": {
"showErrorMessage": "toRenderer_general_showErrorMessage"
}
}
}

View File

@@ -10,6 +10,10 @@
"resetpassword": "Reset Password"
}
},
"errors": {
"errorboundary": "Uh oh - we've hit an error.",
"notificationtitle": "Error Encountered"
},
"navigation": {
"home": "Home",
"settings": "Settings",

View File

@@ -112,6 +112,37 @@
</folder_node>
</children>
</folder_node>
<folder_node>
<name>errors</name>
<children>
<concept_node>
<name>errorboundary</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>notificationtitle</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
</children>
</folder_node>
<folder_node>
<name>navigation</name>
<children>