Add isTest to settings and ability to redirect to test env. Add rome/imex specific builds.
This commit is contained in:
4
.env.imex
Normal file
4
.env.imex
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
VITE_FIREBASE_CONFIG={"apiKey":"AIzaSyDSezy-jGJreo7ulgpLdlpOwAOrgcaEkhU","authDomain":"imex-prod.firebaseapp.com","databaseURL":"https://imex-prod.firebaseio.com","projectId":"imex-prod","storageBucket":"imex-prod.appspot.com","messagingSenderId":"253497221485","appId":"1:253497221485:web:3c81c483b94db84b227a64","measurementId":"G-NTWBKG2L0M"}
|
||||||
|
VITE_GRAPHQL_ENDPOINT=https://db.imex.online/v1/graphql
|
||||||
|
VITE_FIREBASE_CONFIG_TEST={ "apiKey":"AIzaSyBw7_GTy7GtQyfkIRPVrWHEGKfcqeyXw0c", "authDomain":"imex-test.firebaseapp.com", "projectId":"imex-test", "storageBucket":"imex-test.appspot.com", "messagingSenderId":"991923618608", "appId":"1:991923618608:web:633437569cdad78299bef5", "measurementId":"G-TW0XLZEH18"}
|
||||||
|
VITE_GRAPHQL_ENDPOINT_TEST=https://db.test.bodyshop.app/v1/graphql
|
||||||
@@ -1,2 +1,4 @@
|
|||||||
VITE_FIREBASE_CONFIG={"apiKey":"AIzaSyDPLT8GiDHDR1R4nI66Qi0BY1aYviDPioc","authDomain":"imex-dev.firebaseapp.com","databaseURL":"https://imex-dev.firebaseio.com","projectId":"imex-dev","storageBucket":"imex-dev.appspot.com","messagingSenderId":"759548147434","appId":"1:759548147434:web:e8239868a48ceb36700993","measurementId":"G-K5XRBVVB4S"}
|
VITE_FIREBASE_CONFIG={"apiKey":"AIzaSyDPLT8GiDHDR1R4nI66Qi0BY1aYviDPioc","authDomain":"imex-dev.firebaseapp.com","databaseURL":"https://imex-dev.firebaseio.com","projectId":"imex-dev","storageBucket":"imex-dev.appspot.com","messagingSenderId":"759548147434","appId":"1:759548147434:web:e8239868a48ceb36700993","measurementId":"G-K5XRBVVB4S"}
|
||||||
VITE_GRAPHQL_ENDPOINT=https://db.dev.imex.online/v1/graphql
|
VITE_GRAPHQL_ENDPOINT=https://db.dev.imex.online/v1/graphql
|
||||||
|
VITE_FIREBASE_CONFIG_TEST={ "apiKey":"AIzaSyBw7_GTy7GtQyfkIRPVrWHEGKfcqeyXw0c", "authDomain":"imex-test.firebaseapp.com", "projectId":"imex-test", "storageBucket":"imex-test.appspot.com", "messagingSenderId":"991923618608", "appId":"1:991923618608:web:633437569cdad78299bef5", "measurementId":"G-TW0XLZEH18"}
|
||||||
|
VITE_GRAPHQL_ENDPOINT_TEST=https://db.test.bodyshop.app/v1/graphql
|
||||||
4
.env.rome
Normal file
4
.env.rome
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
VITE_FIREBASE_CONFIG={ "apiKey": "AIzaSyAuLQR9SV5LsVxjU8wh9hvFLdhcAHU6cxE", "authDomain": "rome-prod-1.firebaseapp.com", "projectId": "rome-prod-1", "storageBucket": "rome-prod-1.appspot.com", "messagingSenderId": "147786367145", "appId": "1:147786367145:web:9d4cba68071c3f29a8a9b8", "measurementId": "G-G8Z9DRHTZS"}
|
||||||
|
VITE_GRAPHQL_ENDPOINT=https://db.romeonline.io/v1/graphql
|
||||||
|
VITE_FIREBASE_CONFIG_TEST={ "apiKey": "AIzaSyAuLQR9SV5LsVxjU8wh9hvFLdhcAHU6cxE", "authDomain": "rome-prod-1.firebaseapp.com", "projectId": "rome-prod-1", "storageBucket": "rome-prod-1.appspot.com", "messagingSenderId": "147786367145", "appId": "1:147786367145:web:9d4cba68071c3f29a8a9b8", "measurementId": "G-G8Z9DRHTZS"}
|
||||||
|
VITE_GRAPHQL_ENDPOINT_TEST=https://db.test.romeonline.io/v1/graphql
|
||||||
44
README.md
44
README.md
@@ -1,34 +1,18 @@
|
|||||||
# bodyshop-desktop
|
# Shop Partner
|
||||||
|
An electron app that is replacing the existing Bodyshop Partner that was a C#/WPF Application.
|
||||||
|
|
||||||
An Electron application with React and TypeScript
|
The purpose of this application is to:
|
||||||
|
* Parse EMS files, and upload them to the IO back end.
|
||||||
|
* Receive requests for EMS file parsing
|
||||||
|
|
||||||
|
The following functionality will be coming:
|
||||||
|
* Interact with QuickBooks desktop (Windows Only)
|
||||||
|
* Paint scale integrations
|
||||||
|
* Parts Price Changes for CCC
|
||||||
|
|
||||||
## Recommended IDE Setup
|
Toggling between the Production and Test servers can be done by pressing `CTRL/CMD + SHIFT + T`, and then going to the application menu, and enabling test. The application will restart automatically.
|
||||||
|
|
||||||
- [VSCode](https://code.visualstudio.com/) + [ESLint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) + [Prettier](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode)
|
## Dev and Build Notes
|
||||||
|
Unlike the main app, the dev mode will only connect to ImEX Online test data.
|
||||||
|
|
||||||
## Project Setup
|
Building the app will require specifying the company to build for. Those details are captured in their respective ENV and YAML files.
|
||||||
|
|
||||||
### Install
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ npm install
|
|
||||||
```
|
|
||||||
|
|
||||||
### Development
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ npm run dev
|
|
||||||
```
|
|
||||||
|
|
||||||
### Build
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# For windows
|
|
||||||
$ npm run build:win
|
|
||||||
|
|
||||||
# For macOS
|
|
||||||
$ npm run build:mac
|
|
||||||
|
|
||||||
# For Linux
|
|
||||||
$ npm run build:linux
|
|
||||||
```
|
|
||||||
|
|||||||
62
electron-builder.rome.yml
Normal file
62
electron-builder.rome.yml
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
appId: com.convenientbrands.bodyshop-desktop
|
||||||
|
copyright: Convenient Brands, LLC.
|
||||||
|
productName: Rome Shop Partner
|
||||||
|
generateUpdatesFilesForAllChannels: true
|
||||||
|
|
||||||
|
directories:
|
||||||
|
buildResources: build
|
||||||
|
files:
|
||||||
|
- "!**/.vscode/*"
|
||||||
|
- "!src/*"
|
||||||
|
- "!electron.vite.config.{js,ts,mjs,cjs}"
|
||||||
|
- "!{.eslintignore,.eslintrc.cjs,.prettierignore,.prettierrc.yaml,dev-app-update.yml,CHANGELOG.md,README.md}"
|
||||||
|
- "!{.env,.env.*,.npmrc,pnpm-lock.yaml}"
|
||||||
|
- "!{tsconfig.json,tsconfig.node.json,tsconfig.web.json}"
|
||||||
|
asarUnpack:
|
||||||
|
- resources/**
|
||||||
|
win:
|
||||||
|
executableName: ShopPartner
|
||||||
|
icon: resources/diamond.png
|
||||||
|
azureSignOptions:
|
||||||
|
endpoint: https://eus.codesigning.azure.net
|
||||||
|
certificateProfileName: ImEXRPS
|
||||||
|
codeSigningAccountName: ImEX
|
||||||
|
|
||||||
|
nsis:
|
||||||
|
artifactName: ${name}-${version}-setup.${ext}
|
||||||
|
shortcutName: ${productName}
|
||||||
|
uninstallDisplayName: ${productName}
|
||||||
|
createDesktopShortcut: always
|
||||||
|
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.
|
||||||
|
- NSDocumentsFolderUsageDescription: Application requests access to the user's Documents folder.
|
||||||
|
- NSDownloadsFolderUsageDescription: Application requests access to the user's Downloads folder.
|
||||||
|
target:
|
||||||
|
- target: default
|
||||||
|
arch:
|
||||||
|
- arm64
|
||||||
|
- target: default
|
||||||
|
arch:
|
||||||
|
- x64
|
||||||
|
dmg:
|
||||||
|
artifactName: ${name}-${version}-${arch}.${ext}
|
||||||
|
linux:
|
||||||
|
target:
|
||||||
|
- AppImage
|
||||||
|
- snap
|
||||||
|
- deb
|
||||||
|
maintainer: electronjs.org
|
||||||
|
category: Utility
|
||||||
|
appImage:
|
||||||
|
artifactName: ${name}-${version}.${ext}
|
||||||
|
npmRebuild: false
|
||||||
|
publish:
|
||||||
|
provider: s3
|
||||||
|
bucket: imex-partner
|
||||||
|
region: ca-central-1
|
||||||
|
electronDownload:
|
||||||
|
mirror: https://npmmirror.com/mirrors/electron/
|
||||||
@@ -13,12 +13,13 @@
|
|||||||
"typecheck": "npm run typecheck:node && npm run typecheck:web",
|
"typecheck": "npm run typecheck:node && npm run typecheck:web",
|
||||||
"start": "electron-vite preview",
|
"start": "electron-vite preview",
|
||||||
"dev": "electron-vite dev",
|
"dev": "electron-vite dev",
|
||||||
"build": "electron-vite build",
|
"build:mac:imex": "electron-vite build --mode imex && electron-builder --config electron-builder.imex.yml",
|
||||||
|
"build:mac:rome": "electron-vite build --mode rome && electron-builder --config electron-builder.rome.yml",
|
||||||
"postinstall": "electron-builder install-app-deps",
|
"postinstall": "electron-builder install-app-deps",
|
||||||
"build:unpack": "npm run build && electron-builder --dir",
|
"build:unpack": "npm run build && electron-builder --dir",
|
||||||
"build:win": "npm run build && electron-builder --win",
|
"build:win": "npm run build && electron-builder --win",
|
||||||
"build:mac": "electron-vite build && electron-builder --mac",
|
"build:mac": "npm run build && electron-builder --mac",
|
||||||
"build:linux": "electron-vite build && electron-builder --linux"
|
"build:linux": "npm run build && electron-builder --linux"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@apollo/client": "^3.13.5",
|
"@apollo/client": "^3.13.5",
|
||||||
|
|||||||
2
src/env.d.ts
vendored
2
src/env.d.ts
vendored
@@ -3,6 +3,8 @@
|
|||||||
export interface ImportMetaEnv {
|
export interface ImportMetaEnv {
|
||||||
readonly VITE_FIREBASE_CONFIG: string;
|
readonly VITE_FIREBASE_CONFIG: string;
|
||||||
readonly VITE_GRAPHQL_ENDPOINT: string;
|
readonly VITE_GRAPHQL_ENDPOINT: string;
|
||||||
|
readonly VITE_FIREBASE_CONFIG_TEST: string;
|
||||||
|
readonly VITE_GRAPHQL_ENDPOINT_TEST: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ImportMeta {
|
export interface ImportMeta {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import log from "electron-log/main";
|
|||||||
import { GraphQLClient, RequestMiddleware } from "graphql-request";
|
import { GraphQLClient, RequestMiddleware } from "graphql-request";
|
||||||
import errorTypeCheck from "../../util/errorTypeCheck.js";
|
import errorTypeCheck from "../../util/errorTypeCheck.js";
|
||||||
import ipcTypes from "../../util/ipcTypes.json";
|
import ipcTypes from "../../util/ipcTypes.json";
|
||||||
|
import store from "../store/store.js";
|
||||||
|
|
||||||
const requestMiddleware: RequestMiddleware = async (request) => {
|
const requestMiddleware: RequestMiddleware = async (request) => {
|
||||||
const token = await getTokenFromRenderer();
|
const token = await getTokenFromRenderer();
|
||||||
@@ -20,7 +21,9 @@ const requestMiddleware: RequestMiddleware = async (request) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const client: GraphQLClient = new GraphQLClient(
|
const client: GraphQLClient = new GraphQLClient(
|
||||||
import.meta.env.VITE_GRAPHQL_ENDPOINT,
|
store.get("app.isTest") || false
|
||||||
|
? import.meta.env.VITE_GRAPHQL_ENDPOINT_TEST
|
||||||
|
: import.meta.env.VITE_GRAPHQL_ENDPOINT,
|
||||||
{
|
{
|
||||||
requestMiddleware,
|
requestMiddleware,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,6 +1,14 @@
|
|||||||
import { electronApp, is, optimizer } from "@electron-toolkit/utils";
|
import { electronApp, is, optimizer } from "@electron-toolkit/utils";
|
||||||
import Sentry from "@sentry/electron/main";
|
import Sentry from "@sentry/electron/main";
|
||||||
import { app, BrowserWindow, Menu, nativeImage, shell, Tray } from "electron";
|
import {
|
||||||
|
app,
|
||||||
|
BrowserWindow,
|
||||||
|
globalShortcut,
|
||||||
|
Menu,
|
||||||
|
nativeImage,
|
||||||
|
shell,
|
||||||
|
Tray,
|
||||||
|
} 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 path, { join } from "path";
|
import path, { join } from "path";
|
||||||
@@ -138,6 +146,20 @@ function createWindow(): void {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: "Connect to Test",
|
||||||
|
checked: store.get("app.isTest") as boolean,
|
||||||
|
visible: false,
|
||||||
|
type: "checkbox",
|
||||||
|
id: "toggleTest",
|
||||||
|
click: (): void => {
|
||||||
|
const currentSetting = store.get("app.isTest") as boolean;
|
||||||
|
store.set("app.isTest", !currentSetting);
|
||||||
|
log.info("Setting isTest to: ", !currentSetting);
|
||||||
|
app.relaunch(); // Relaunch the app
|
||||||
|
app.exit(0); // Exit the current instance
|
||||||
|
},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
// { role: 'windowMenu' }
|
// { role: 'windowMenu' }
|
||||||
@@ -219,6 +241,23 @@ function createWindow(): void {
|
|||||||
const menu: Electron.Menu = Menu.buildFromTemplate(template);
|
const menu: Electron.Menu = Menu.buildFromTemplate(template);
|
||||||
Menu.setApplicationMenu(menu);
|
Menu.setApplicationMenu(menu);
|
||||||
|
|
||||||
|
// Register a global shortcut to show the hidden item
|
||||||
|
globalShortcut.register("CommandOrControl+Shift+T", () => {
|
||||||
|
console.log("Shortcut pressed! Revealing hidden item.");
|
||||||
|
|
||||||
|
// Update the menu to make the hidden item visible
|
||||||
|
// Find the menu item dynamically by its id
|
||||||
|
const fileMenu = template.find((item) => item.label === "Application");
|
||||||
|
const hiddenItem = fileMenu?.submenu?.find(
|
||||||
|
(item) => item.id === "toggleTest",
|
||||||
|
);
|
||||||
|
if (hiddenItem) {
|
||||||
|
hiddenItem.visible = true; // Update the visibility dynamically
|
||||||
|
const menu: Electron.Menu = Menu.buildFromTemplate(template);
|
||||||
|
Menu.setApplicationMenu(menu);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Store window properties for later
|
// Store window properties for later
|
||||||
const storeWindowState = (): void => {
|
const storeWindowState = (): void => {
|
||||||
const [width, height] = mainWindow.getSize();
|
const [width, height] = mainWindow.getSize();
|
||||||
@@ -388,7 +427,7 @@ app.on("before-quit", () => {
|
|||||||
openAtLogin: !currentSetting,
|
openAtLogin: !currentSetting,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
globalShortcut.unregisterAll();
|
||||||
isAppQuitting = true;
|
isAppQuitting = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ const store = new Store({
|
|||||||
y: undefined,
|
y: undefined,
|
||||||
},
|
},
|
||||||
user: null,
|
user: null,
|
||||||
|
isTest: false,
|
||||||
bodyshop: {},
|
bodyshop: {},
|
||||||
masterdata: {
|
masterdata: {
|
||||||
opcodes: null,
|
opcodes: null,
|
||||||
|
|||||||
@@ -1,9 +1,16 @@
|
|||||||
import { contextBridge } from "electron";
|
import { contextBridge } from "electron";
|
||||||
import { electronAPI } from "@electron-toolkit/preload";
|
import { electronAPI } from "@electron-toolkit/preload";
|
||||||
import "electron-log/preload";
|
import "electron-log/preload";
|
||||||
|
import store from "../main/store/store";
|
||||||
|
|
||||||
// Custom APIs for renderer
|
// Custom APIs for renderer
|
||||||
const api = {};
|
interface Api {
|
||||||
|
isTest: () => boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const api: Api = {
|
||||||
|
isTest: (): boolean => store.get("app.isTest") || false,
|
||||||
|
};
|
||||||
|
|
||||||
// Use `contextBridge` APIs to expose Electron APIs to
|
// Use `contextBridge` APIs to expose Electron APIs to
|
||||||
// renderer only if context isolation is enabled, otherwise
|
// renderer only if context isolation is enabled, otherwise
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
|
import { is } from "@electron-toolkit/utils";
|
||||||
import { auth } from "@renderer/util/firebase";
|
import { auth } from "@renderer/util/firebase";
|
||||||
import { Layout, Menu } from "antd";
|
import { Badge, Layout, Menu } from "antd";
|
||||||
import { MenuItemType } from "antd/es/menu/interface";
|
import { MenuItemType } from "antd/es/menu/interface";
|
||||||
import { signOut } from "firebase/auth";
|
import { signOut } from "firebase/auth";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
@@ -18,25 +19,22 @@ const NavigationHeader: React.FC = () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
const isTest = window.api.isTest();
|
||||||
return (
|
return (
|
||||||
// <Badge.Ribbon
|
<Badge.Ribbon
|
||||||
// text={
|
text={isTest && "Connected to Test Environment"}
|
||||||
// isWatcherStarted
|
color={isTest && "red"}
|
||||||
// ? t("settings.labels.started")
|
>
|
||||||
// : t("settings.labels.stopped")
|
<Layout.Header style={{ display: "flex", alignItems: "center" }}>
|
||||||
// }
|
<Menu
|
||||||
// color={isWatcherStarted ? "green" : "red"}
|
theme="dark"
|
||||||
// >
|
mode="horizontal"
|
||||||
<Layout.Header style={{ display: "flex", alignItems: "center" }}>
|
defaultSelectedKeys={["2"]}
|
||||||
<Menu
|
items={menuItems}
|
||||||
theme="dark"
|
style={{ flex: 1, minWidth: 0 }}
|
||||||
mode="horizontal"
|
/>
|
||||||
defaultSelectedKeys={["2"]}
|
</Layout.Header>
|
||||||
items={menuItems}
|
</Badge.Ribbon>
|
||||||
style={{ flex: 1, minWidth: 0 }}
|
|
||||||
/>
|
|
||||||
</Layout.Header>
|
|
||||||
// </Badge.Ribbon>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import SettingsWatcher from "./Settings.Watcher";
|
|||||||
import Welcome from "../Welcome/Welcome";
|
import Welcome from "../Welcome/Welcome";
|
||||||
|
|
||||||
const Settings: React.FC = () => {
|
const Settings: React.FC = () => {
|
||||||
|
console.log("is test?", window.api.isTest());
|
||||||
return (
|
return (
|
||||||
<Row gutter={[16, 16]}>
|
<Row gutter={[16, 16]}>
|
||||||
<Col span={24}>
|
<Col span={24}>
|
||||||
|
|||||||
@@ -2,7 +2,11 @@ import { initializeApp } from "firebase/app";
|
|||||||
import { getAuth } from "firebase/auth";
|
import { getAuth } from "firebase/auth";
|
||||||
|
|
||||||
// TODO: Replace the following with your app's Firebase project configuration
|
// TODO: Replace the following with your app's Firebase project configuration
|
||||||
const firebaseConfig = JSON.parse(import.meta.env.VITE_FIREBASE_CONFIG);
|
const firebaseConfig = JSON.parse(
|
||||||
|
window.api.isTest()
|
||||||
|
? import.meta.env.VITE_FIREBASE_CONFIG_TEST
|
||||||
|
: import.meta.env.VITE_FIREBASE_CONFIG,
|
||||||
|
);
|
||||||
|
|
||||||
const app = initializeApp(firebaseConfig);
|
const app = initializeApp(firebaseConfig);
|
||||||
export const auth = getAuth();
|
export const auth = getAuth();
|
||||||
|
|||||||
Reference in New Issue
Block a user