Minor bug fixes and CI change.
This commit is contained in:
@@ -15,7 +15,7 @@ files:
|
|||||||
asarUnpack:
|
asarUnpack:
|
||||||
- resources/**
|
- resources/**
|
||||||
win:
|
win:
|
||||||
executableName: Shop Partner
|
executableName: ShopPartner
|
||||||
icon: resources/diamond.png
|
icon: resources/diamond.png
|
||||||
azureSignOptions:
|
azureSignOptions:
|
||||||
endpoint: https://eus.codesigning.azure.net
|
endpoint: https://eus.codesigning.azure.net
|
||||||
|
|||||||
@@ -41,6 +41,8 @@ function createWindow(): void {
|
|||||||
x,
|
x,
|
||||||
y,
|
y,
|
||||||
show: false,
|
show: false,
|
||||||
|
minWidth: 600,
|
||||||
|
minHeight: 400,
|
||||||
//autoHideMenuBar: true,
|
//autoHideMenuBar: true,
|
||||||
...(process.platform === "linux" ? { icon } : {}),
|
...(process.platform === "linux" ? { icon } : {}),
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
|
|||||||
@@ -13,7 +13,10 @@ import {
|
|||||||
SettingsWatcherPollingGet,
|
SettingsWatcherPollingGet,
|
||||||
SettingsWatcherPollingSet,
|
SettingsWatcherPollingSet,
|
||||||
} from "./ipcMainHandler.settings";
|
} from "./ipcMainHandler.settings";
|
||||||
import { ipcMainHandleAuthStateChanged } from "./ipcMainHandler.user";
|
import {
|
||||||
|
ipcMainHandleAuthStateChanged,
|
||||||
|
ipMainHandleResetPassword,
|
||||||
|
} from "./ipcMainHandler.user";
|
||||||
|
|
||||||
// Log all IPC messages and their payloads
|
// Log all IPC messages and their payloads
|
||||||
const logIpcMessages = (): void => {
|
const logIpcMessages = (): void => {
|
||||||
@@ -47,6 +50,7 @@ ipcMain.on(ipcTypes.toMain.test, () =>
|
|||||||
|
|
||||||
//Auth handler
|
//Auth handler
|
||||||
ipcMain.on(ipcTypes.toMain.authStateChanged, ipcMainHandleAuthStateChanged);
|
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) {
|
if (import.meta.env.DEV) {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { IpcMainEvent } from "electron";
|
import { IpcMainEvent, shell } from "electron";
|
||||||
import log from "electron-log/main";
|
import log from "electron-log/main";
|
||||||
import { autoUpdater } from "electron-updater";
|
import { autoUpdater } from "electron-updater";
|
||||||
import { User } from "firebase/auth";
|
import { User } from "firebase/auth";
|
||||||
@@ -10,39 +10,59 @@ import {
|
|||||||
QUERY_MASTERDATA_TYPED,
|
QUERY_MASTERDATA_TYPED,
|
||||||
} from "../graphql/queries";
|
} from "../graphql/queries";
|
||||||
import Store from "../store/store";
|
import Store from "../store/store";
|
||||||
|
import errorTypeCheck from "../../util/errorTypeCheck";
|
||||||
|
import { sendIpcToRenderer } from "../util/toRenderer";
|
||||||
|
import ipcTypes from "../../util/ipcTypes.json";
|
||||||
|
|
||||||
const ipcMainHandleAuthStateChanged = async (
|
const ipcMainHandleAuthStateChanged = async (
|
||||||
event: IpcMainEvent,
|
_event: IpcMainEvent,
|
||||||
user: User | null,
|
user: User | null,
|
||||||
): Promise<void> => {
|
): Promise<void> => {
|
||||||
Store.set("user", user);
|
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(
|
||||||
|
QUERY_ACTIVE_BODYSHOP_TYPED,
|
||||||
|
);
|
||||||
|
|
||||||
//Need to query the currently active shop, and store the metadata as well.
|
Store.set("app.bodyshop", activeBodyshop.bodyshops[0]);
|
||||||
//Also need to query the OP Codes for decoding reference.
|
|
||||||
const activeBodyshop: ActiveBodyshopQueryResult = await client.request(
|
|
||||||
QUERY_ACTIVE_BODYSHOP_TYPED,
|
|
||||||
);
|
|
||||||
|
|
||||||
Store.set("app.bodyshop", activeBodyshop.bodyshops[0]);
|
const OpCodes: MasterdataQueryResult = await client.request(
|
||||||
|
QUERY_MASTERDATA_TYPED,
|
||||||
|
{
|
||||||
|
key: `${activeBodyshop.bodyshops[0].region_config}_ciecaopcodes`,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
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.");
|
||||||
|
|
||||||
const OpCodes: MasterdataQueryResult = await client.request(
|
//Check for updates
|
||||||
QUERY_MASTERDATA_TYPED,
|
const convCo = activeBodyshop.bodyshops[0].convenient_company;
|
||||||
{
|
if (convCo === "alpha") {
|
||||||
key: `${activeBodyshop.bodyshops[0].region_config}_ciecaopcodes`,
|
autoUpdater.channel = "alpha";
|
||||||
},
|
} else if (convCo === "beta") {
|
||||||
);
|
autoUpdater.channel = "beta";
|
||||||
Store.set("app.masterdata.opcodes", JSON.parse(OpCodes.masterdata[0]?.value));
|
}
|
||||||
log.debug("Received authentication state change from Renderer.", user);
|
} catch (error) {
|
||||||
log.debug("Requery shop information & master data.");
|
log.error(
|
||||||
|
"Error while querying active bodyshop or masterdata",
|
||||||
//Check for updates
|
errorTypeCheck(error),
|
||||||
const convCo = activeBodyshop.bodyshops[0].convenient_company;
|
);
|
||||||
if (convCo === "alpha") {
|
sendIpcToRenderer(
|
||||||
autoUpdater.channel = "alpha";
|
ipcTypes.toRenderer.general.showErrorMessage,
|
||||||
} else if (convCo === "beta") {
|
"Error connecting to ImEX Online servers to get shop data. Please try again.",
|
||||||
autoUpdater.channel = "beta";
|
);
|
||||||
}
|
}
|
||||||
autoUpdater.checkForUpdatesAndNotify();
|
autoUpdater.checkForUpdatesAndNotify();
|
||||||
};
|
};
|
||||||
|
|
||||||
export { ipcMainHandleAuthStateChanged };
|
const ipMainHandleResetPassword = async (): Promise<void> => {
|
||||||
|
shell.openExternal("https://imex.online/resetpassword");
|
||||||
|
};
|
||||||
|
|
||||||
|
export { ipcMainHandleAuthStateChanged, ipMainHandleResetPassword };
|
||||||
|
|||||||
21
src/main/util/toRenderer.ts
Normal file
21
src/main/util/toRenderer.ts
Normal 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 };
|
||||||
@@ -12,7 +12,7 @@ const ErrorBoundaryFallback: React.FC<FallbackProps> = ({
|
|||||||
return (
|
return (
|
||||||
<Result
|
<Result
|
||||||
status={"500"}
|
status={"500"}
|
||||||
title={t("app.errors.errorboundary")}
|
title={t("errors.errorboundary")}
|
||||||
subTitle={error?.message}
|
subTitle={error?.message}
|
||||||
extra={[
|
extra={[
|
||||||
<Button key="try-again" onClick={resetErrorBoundary}>
|
<Button key="try-again" onClick={resetErrorBoundary}>
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ const SettingsWatcher: React.FC = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Card title={t("settings.labels.watcherstatus")}>
|
<Card title={t("settings.labels.watcherstatus")}>
|
||||||
<Space>
|
<Space wrap>
|
||||||
{isWatcherStarted ? (
|
{isWatcherStarted ? (
|
||||||
<Button onClick={handleStop}>
|
<Button onClick={handleStop}>
|
||||||
{t("settings.actions.stopwatcher")}
|
{t("settings.actions.stopwatcher")}
|
||||||
@@ -100,7 +100,7 @@ const SettingsWatcher: React.FC = () => {
|
|||||||
checkedChildren={t("settings.labels.watchermoderealtime")}
|
checkedChildren={t("settings.labels.watchermoderealtime")}
|
||||||
unCheckedChildren={t("settings.labels.watchermodepolling")}
|
unCheckedChildren={t("settings.labels.watchermodepolling")}
|
||||||
/>
|
/>
|
||||||
<Space size="small">
|
<Space size="small" wrap>
|
||||||
<span>{t("settings.labels.pollinginterval")}</span>
|
<span>{t("settings.labels.pollinginterval")}</span>
|
||||||
<InputNumber
|
<InputNumber
|
||||||
title={t("settings.labels.pollinginterval")}
|
title={t("settings.labels.pollinginterval")}
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
import { auth } from "@renderer/util/firebase";
|
import { auth } from "@renderer/util/firebase";
|
||||||
import type { FormProps } from "antd";
|
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 log from "electron-log/renderer";
|
||||||
import { signInWithEmailAndPassword } from "firebase/auth";
|
import { signInWithEmailAndPassword } from "firebase/auth";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import errorTypeCheck from "../../../../util/errorTypeCheck";
|
import errorTypeCheck from "../../../../util/errorTypeCheck";
|
||||||
|
import ipcTypes from "../../../../util/ipcTypes.json";
|
||||||
|
|
||||||
type FieldType = {
|
type FieldType = {
|
||||||
username: string;
|
username: string;
|
||||||
@@ -15,15 +16,19 @@ type FieldType = {
|
|||||||
|
|
||||||
const SignInForm: React.FC = () => {
|
const SignInForm: React.FC = () => {
|
||||||
const [error, setError] = useState<string | null>(null);
|
const [error, setError] = useState<string | null>(null);
|
||||||
|
const [loading, setLoading] = useState<boolean>(false);
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const onFinish: FormProps<FieldType>["onFinish"] = async (values) => {
|
const onFinish: FormProps<FieldType>["onFinish"] = async (values) => {
|
||||||
const { username, password } = values;
|
const { username, password } = values;
|
||||||
|
setLoading(true);
|
||||||
try {
|
try {
|
||||||
const result = await signInWithEmailAndPassword(auth, username, password);
|
const result = await signInWithEmailAndPassword(auth, username, password);
|
||||||
log.debug("Login result", result);
|
log.debug("Login result", result);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
log.error("Login error", errorTypeCheck(error));
|
log.error("Login error", errorTypeCheck(error));
|
||||||
setError(t("auth.login.error"));
|
setError(t("auth.login.error"));
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -59,18 +64,27 @@ const SignInForm: React.FC = () => {
|
|||||||
<Input.Password />
|
<Input.Password />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item label={null}>
|
<Form.Item label={null}>
|
||||||
<Button type="primary" htmlType="submit">
|
<Space>
|
||||||
{t("auth.login.login")}
|
<Button type="primary" loading={loading} htmlType="submit">
|
||||||
</Button>
|
{t("auth.login.login")}
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
onClick={(): void => {
|
||||||
|
window.electron.ipcRenderer.send(
|
||||||
|
ipcTypes.toMain.user.resetPassword,
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{t("auth.login.resetpassword")}
|
||||||
|
</Button>
|
||||||
|
</Space>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
{error && (
|
{error && (
|
||||||
<Form.Item label={null}>
|
<Form.Item label={null}>
|
||||||
<Alert message={error} type="error" />
|
<Alert message={error} type="error" />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
)}
|
)}
|
||||||
<Form.Item label={null}>
|
<Form.Item label={null}></Form.Item>
|
||||||
<Button>{t("auth.login.resetpassword")}</Button>
|
|
||||||
</Form.Item>
|
|
||||||
</Form>
|
</Form>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ import {
|
|||||||
import store from "@renderer/redux/redux-store";
|
import store from "@renderer/redux/redux-store";
|
||||||
import ipcTypes from "../../../util/ipcTypes.json";
|
import ipcTypes from "../../../util/ipcTypes.json";
|
||||||
import { auth } from "./firebase";
|
import { auth } from "./firebase";
|
||||||
|
import { notification } from "antd";
|
||||||
|
import i18n from "./i18n";
|
||||||
|
|
||||||
const ipcRenderer = window.electron.ipcRenderer;
|
const ipcRenderer = window.electron.ipcRenderer;
|
||||||
const dispatch = store.dispatch;
|
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,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|||||||
@@ -27,7 +27,8 @@
|
|||||||
},
|
},
|
||||||
"user": {
|
"user": {
|
||||||
"getTokenResponse": "toMain_user_getTokenResponse",
|
"getTokenResponse": "toMain_user_getTokenResponse",
|
||||||
"getActiveShop": "toMain_user_getActiveShopify"
|
"getActiveShop": "toMain_user_getActiveShopify",
|
||||||
|
"resetPassword": "toMain_user_resetPassword"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"toRenderer": {
|
"toRenderer": {
|
||||||
@@ -48,6 +49,9 @@
|
|||||||
},
|
},
|
||||||
"user": {
|
"user": {
|
||||||
"getToken": "toRenderer_user_getToken"
|
"getToken": "toRenderer_user_getToken"
|
||||||
|
},
|
||||||
|
"general": {
|
||||||
|
"showErrorMessage": "toRenderer_general_showErrorMessage"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,10 @@
|
|||||||
"resetpassword": "Reset Password"
|
"resetpassword": "Reset Password"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"errors": {
|
||||||
|
"errorboundary": "Uh oh - we've hit an error.",
|
||||||
|
"notificationtitle": "Error Encountered"
|
||||||
|
},
|
||||||
"navigation": {
|
"navigation": {
|
||||||
"home": "Home",
|
"home": "Home",
|
||||||
"settings": "Settings",
|
"settings": "Settings",
|
||||||
|
|||||||
@@ -112,6 +112,37 @@
|
|||||||
</folder_node>
|
</folder_node>
|
||||||
</children>
|
</children>
|
||||||
</folder_node>
|
</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>
|
<folder_node>
|
||||||
<name>navigation</name>
|
<name>navigation</name>
|
||||||
<children>
|
<children>
|
||||||
|
|||||||
Reference in New Issue
Block a user