Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/server web about page #3409

Merged
merged 8 commits into from
Dec 11, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ export class DesktopServerWebEnvironmentContent implements IContentGenerator {
GAUZY_API_SERVER_URL: '${variable.GAUZY_API_SERVER_URL}',
NEXT_PUBLIC_GAUZY_API_SERVER_URL: '${variable.NEXT_PUBLIC_GAUZY_API_SERVER_URL}',
DESKTOP_WEB_SERVER_HOSTNAME: '${variable.DESKTOP_WEB_SERVER_HOSTNAME}',
TERM_OF_SERVICE: '${variable.TERM_OF_SERVICE}',
PRIVACY_POLICY: '${variable.PRIVACY_POLICY}'
syns2191 marked this conversation as resolved.
Show resolved Hide resolved
`;
}
}
10 changes: 9 additions & 1 deletion .scripts/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ export type Env = Readonly<{
GAUZY_API_SERVER_URL: string;
NEXT_PUBLIC_GAUZY_API_SERVER_URL: string;
DESKTOP_WEB_SERVER_HOSTNAME: string;
TERM_OF_SERVICE: string;
PRIVACY_POLICY: string;
}>

export const env = cleanEnv(process.env, {
Expand All @@ -31,7 +33,7 @@ export const env = cleanEnv(process.env, {
default: 'https://github.com/ever-co/ever-teams'
}),
PLATFORM_LOGO: str({
default: 'src/resources/icons/platform-logo.png'
default: 'https://app.ever.team/assets/ever-teams.png'
}),
DESKTOP_WEB_SERVER_APP_NAME: str({
default: 'ever-teams-server-web'
Expand Down Expand Up @@ -69,5 +71,11 @@ export const env = cleanEnv(process.env, {
DESKTOP_WEB_SERVER_HOSTNAME: str({
default: '0.0.0.0', // let's use the same one for now for all envs
desc: 'WARNING: Using 0.0.0.0 binds to all network interfaces. Use with caution in production.'
}),
TERM_OF_SERVICE: str({
default: 'https://ever.team/tos'
}),
PRIVACY_POLICY: str({
default: 'https://ever.team/privacy'
})
});
47 changes: 45 additions & 2 deletions apps/server-web/src/main/helpers/constant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export const EventLists = {
webServerStop: 'WEB_SERVER_STOP',
gotoSetting: 'GO_TO_SETTING',
gotoAbout: 'GO_TO_ABOUT',
OPEN_WINDOW: 'OPEN_WINDOW',
UPDATE_AVAILABLE: 'UPDATE_AVAILABLE',
UPDATE_ERROR: 'UPDATE_ERROR',
UPDATE_NOT_AVAILABLE: 'UPDATE_NOT_AVAILABLE',
Expand All @@ -19,7 +20,8 @@ export const EventLists = {
CHANGE_THEME: 'CHANGE_THEME',
SETUP_WINDOW: 'SETUP_WINDOW',
SETTING_WINDOW_DEV: 'SETTING_WINDOW_DEV',
SERVER_WINDOW_DEV: 'SERVER_WINDOW_DEV'
SERVER_WINDOW_DEV: 'SERVER_WINDOW_DEV',
WINDOW_EVENT: 'WINDOW_EVENT'
}

export const SettingPageTypeMessage = {
Expand All @@ -40,7 +42,13 @@ export const SettingPageTypeMessage = {
updateSettingResponse: 'update-setting-response',
updateCancel: 'update-cancel',
restartServer: 'restart-server',
themeChange: 'theme-change'
themeChange: 'theme-change',
linkAction: 'link-action'
}

export const APP_LINK = {
TERM_OF_SERVICE: 'TERM_OF_SERVICE',
PRIVACY_POLICY: 'PRIVACY_POLICY'
}

export const ServerPageTypeMessage = {
Expand All @@ -63,3 +71,38 @@ export const IPC_TYPES: {
UPDATER_PAGE: 'updater-page',
SERVER_PAGE: 'server-page'
}

export const WindowOptions = {
SETTING_WINDOW: {
width: 1024,
height: 728,
hashPath: 'setting'
},
LOG_WINDOW: {
width: 1024,
height: 728,
hashPath: 'history-console'
},
SETUP_WINDOW: {
width: 1024,
height: 728,
hashPath: 'setup'
},
ABOUT_WINDOW: {
width: 300,
height: 250,
hashPath: 'about'
}
syns2191 marked this conversation as resolved.
Show resolved Hide resolved
}

export const WindowTypes: {
SETTING_WINDOW: 'SETTING_WINDOW',
LOG_WINDOW: 'LOG_WINDOW',
SETUP_WINDOW: 'SETUP_WINDOW',
ABOUT_WINDOW: 'ABOUT_WINDOW'
} = {
SETTING_WINDOW: 'SETTING_WINDOW',
LOG_WINDOW: 'LOG_WINDOW',
SETUP_WINDOW: 'SETUP_WINDOW',
ABOUT_WINDOW: 'ABOUT_WINDOW'
}
5 changes: 5 additions & 0 deletions apps/server-web/src/main/helpers/interfaces/i-events.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { IWindowTypes } from "./i-window";

export interface IOpenWindow {
windowType: IWindowTypes
}
8 changes: 8 additions & 0 deletions apps/server-web/src/main/helpers/interfaces/i-window.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { Menu } from "electron";

export type IWindowTypes = 'SETTING_WINDOW' | 'LOG_WINDOW' | 'SETUP_WINDOW' | 'ABOUT_WINDOW'

export interface IAppWindow {
windowType: IWindowTypes,
menu: Menu
}
2 changes: 2 additions & 0 deletions apps/server-web/src/main/helpers/interfaces/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@ export * from './i-server';
export * from './i-desktop-dialog';
export * from './i-constant';
export * from './i-menu';
export * from './i-window';
export * from './i-events';
160 changes: 86 additions & 74 deletions apps/server-web/src/main/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,16 @@ import { DesktopServer } from './helpers/desktop-server';
import { LocalStore } from './helpers/services/libs/desktop-store';
import { EventEmitter } from 'events';
import { defaultTrayMenuItem, _initTray, updateTrayMenu } from './tray';
import { EventLists, SettingPageTypeMessage, ServerPageTypeMessage, LOG_TYPES, IPC_TYPES } from './helpers/constant';
import { resolveHtmlPath } from './util';
import { EventLists, SettingPageTypeMessage, ServerPageTypeMessage, LOG_TYPES, IPC_TYPES, WindowTypes, APP_LINK } from './helpers/constant';
import Updater from './updater';
import { mainBindings } from 'i18next-electron-fs-backend';
import i18nextMainBackend from '../configs/i18n.mainconfig';
import fs from 'fs';
import { WebServer, AppMenu, ServerConfig } from './helpers/interfaces';
import { WebServer, AppMenu, ServerConfig, IWindowTypes, IOpenWindow } from './helpers/interfaces';
import { clearDesktopConfig } from './helpers';
import Log from 'electron-log';
import MenuBuilder from './menu';
import { config } from '../configs/config';
import { debounce } from 'lodash';
import WindowFactory from './windows/window-factory';


console.log = Log.log;
Expand All @@ -40,7 +38,37 @@ let tray: Tray;
let settingWindow: BrowserWindow | null = null;
let logWindow: BrowserWindow | null = null;
let setupWindow: BrowserWindow | any = null;
const appMenu = new MenuBuilder(eventEmitter)
let aboutWindow: BrowserWindow | null = null;
const appMenu = new MenuBuilder(eventEmitter);

const handleCloseWindow = (windowTypes: IWindowTypes) => {
switch (windowTypes) {
case WindowTypes.SETTING_WINDOW:
settingWindow = null;
break;
case WindowTypes.SETUP_WINDOW:
setupWindow = null;
break;
case WindowTypes.LOG_WINDOW:
logWindow = null;
break;
default:
break;
}
}
syns2191 marked this conversation as resolved.
Show resolved Hide resolved

const handleLinkAction = (linkType: string) => {
switch (linkType) {
case APP_LINK.TERM_OF_SERVICE:
shell.openExternal(config.TERM_OF_SERVICE);
break;
case APP_LINK.PRIVACY_POLICY:
shell.openExternal(config.PRIVACY_POLICY);
break;
default:
break;
}
}
Comment on lines +63 to +74
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add error handling for external links

The link handling logic should include error handling for failed external link operations.

Add error handling:

 const handleLinkAction = (linkType: string) => {
   switch (linkType) {
     case APP_LINK.TERM_OF_SERVICE:
-      shell.openExternal(config.TERM_OF_SERVICE);
+      shell.openExternal(config.TERM_OF_SERVICE)
+        .catch(error => {
+          console.error('Failed to open Terms of Service:', error);
+          dialog.showErrorBox('Error', 'Failed to open Terms of Service');
+        });
       break;
     case APP_LINK.PRIVACY_POLICY:
-      shell.openExternal(config.PRIVACY_POLICY);
+      shell.openExternal(config.PRIVACY_POLICY)
+        .catch(error => {
+          console.error('Failed to open Privacy Policy:', error);
+          dialog.showErrorBox('Error', 'Failed to open Privacy Policy');
+        });
       break;
     default:
       break;
   }
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const handleLinkAction = (linkType: string) => {
switch (linkType) {
case APP_LINK.TERM_OF_SERVICE:
shell.openExternal(config.TERM_OF_SERVICE);
break;
case APP_LINK.PRIVACY_POLICY:
shell.openExternal(config.PRIVACY_POLICY);
break;
default:
break;
}
}
const handleLinkAction = (linkType: string) => {
switch (linkType) {
case APP_LINK.TERM_OF_SERVICE:
shell.openExternal(config.TERM_OF_SERVICE)
.catch(error => {
console.error('Failed to open Terms of Service:', error);
dialog.showErrorBox('Error', 'Failed to open Terms of Service');
});
break;
case APP_LINK.PRIVACY_POLICY:
shell.openExternal(config.PRIVACY_POLICY)
.catch(error => {
console.error('Failed to open Privacy Policy:', error);
dialog.showErrorBox('Error', 'Failed to open Privacy Policy');
});
break;
default:
break;
}
}


Log.hooks.push((message: any, transport) => {
if (transport !== Log.transports.file) {
Expand Down Expand Up @@ -111,6 +139,10 @@ const getAssetPath = (...paths: string[]): string => {
return path.join(RESOURCES_PATH, ...paths);
};

const preloadPath: string = app.isPackaged
? path.join(__dirname, 'preload.js')
: path.join(__dirname, '../../.erb/dll/preload.js');

console.log(__dirname);

if (isProd) {
Expand Down Expand Up @@ -145,6 +177,12 @@ if (isDebug) {
require('electron-debug')();
}

const windowFactory = new WindowFactory(
preloadPath,
'icons/icon.png',
eventEmitter
)

const installExtensions = async () => {
const installer = require('electron-devtools-installer');
const forceDownload = !!process.env.UPGRADE_EXTENSIONS;
Expand All @@ -159,63 +197,36 @@ const installExtensions = async () => {
};


const createWindow = async (type: 'SETTING_WINDOW' | 'LOG_WINDOW' | 'SETUP_WINDOW') => {
const createWindow = async (windowType: IWindowTypes): Promise<BrowserWindow> => {
if (isDebug) {
await installExtensions();
}
return windowFactory.buildWindow({windowType, menu: appMenu.buildTemplateMenu(windowType, i18nextMainBackend)});
};

const defaultOptionWindow = {
title: app.name,
frame: true,
show: false,
width: 1024,
height: 728,
icon: getAssetPath('icons/icon.png'),
maximizable: false,
resizable: false,
webPreferences: {
preload: app.isPackaged
? path.join(__dirname, 'preload.js')
: path.join(__dirname, '../../.erb/dll/preload.js'),
},
}
let url = '';
switch (type) {
case 'SETTING_WINDOW':
settingWindow = new BrowserWindow(defaultOptionWindow);
url = resolveHtmlPath('index.html', 'setting');
settingWindow.loadURL(url);

mainBindings(ipcMain, settingWindow, fs);
settingWindow.on('closed', () => {
settingWindow = null;
});
Menu.setApplicationMenu(appMenu.buildDefaultTemplate(appMenuItems, i18nextMainBackend))
break;
case 'LOG_WINDOW':
logWindow = new BrowserWindow(defaultOptionWindow);
url = resolveHtmlPath('index.html', 'history-console')
logWindow.loadURL(url);
mainBindings(ipcMain, logWindow, fs);
logWindow.on('closed', () => {
logWindow = null;
})
Menu.setApplicationMenu(appMenu.buildDefaultTemplate(appMenuItems, i18nextMainBackend))
break;
case 'SETUP_WINDOW':
setupWindow = new BrowserWindow(defaultOptionWindow);
url = resolveHtmlPath('index.html', 'setup');
setupWindow?.loadURL(url);
mainBindings(ipcMain, setupWindow, fs);
Menu.setApplicationMenu(appMenu.buildDefaultTemplate(appMenu.initialMenu(), i18nextMainBackend));
setupWindow.on('closed', () => {
setupWindow = null;
})
const handleOpenWindow = async (data: IOpenWindow) => {
let browserWindow: BrowserWindow | null = null;
const serverSetting = LocalStore.getStore('config');
switch (data.windowType) {
case WindowTypes.ABOUT_WINDOW:
browserWindow = aboutWindow ? aboutWindow : await createWindow(data.windowType);
break;
default:
break;
}
};
if (browserWindow) {
browserWindow?.show();
browserWindow?.webContents.once('did-finish-load', () => {
setTimeout(() => {
browserWindow?.webContents.send('languageSignal', serverSetting.general?.lang);
browserWindow?.webContents.send(IPC_TYPES.SETTING_PAGE, {
data: {...serverSetting, appName: app.name, version: app.getVersion()},
type: SettingPageTypeMessage.loadSetting,
});
}, 50)
})
}
}
syns2191 marked this conversation as resolved.
Show resolved Hide resolved
syns2191 marked this conversation as resolved.
Show resolved Hide resolved

const runServer = async () => {
console.log('Run the Server...');
Expand Down Expand Up @@ -275,9 +286,9 @@ const onInitApplication = () => {
if (i18nextMainBackend.isInitialized && storeConfig.general?.setup) {
trayMenuItems = trayMenuItems.length ? trayMenuItems : defaultTrayMenuItem(eventEmitter);
updateTrayMenu('none', {}, eventEmitter, tray, trayMenuItems, i18nextMainBackend);
Menu.setApplicationMenu(appMenu.buildDefaultTemplate(appMenuItems, i18nextMainBackend))
Menu.setApplicationMenu(appMenu.buildTemplateMenu(WindowTypes.LOG_WINDOW, i18nextMainBackend))
} else {
Menu.setApplicationMenu(appMenu.buildDefaultTemplate(appMenu.initialMenu(), i18nextMainBackend))
Menu.setApplicationMenu(appMenu.buildTemplateMenu(WindowTypes.SETUP_WINDOW, i18nextMainBackend))
}
}, 250));

Expand Down Expand Up @@ -326,7 +337,7 @@ const onInitApplication = () => {

eventEmitter.on(EventLists.gotoSetting, async () => {
if (!settingWindow) {
await createWindow('SETTING_WINDOW');
settingWindow = await createWindow(WindowTypes.SETTING_WINDOW);
}
const serverSetting: WebServer = LocalStore.getStore('config');
console.log('setting data', serverSetting);
Expand Down Expand Up @@ -389,25 +400,12 @@ const onInitApplication = () => {
setupWindow?.webContents.send('themeSignal', { type: SettingPageTypeMessage.themeChange, data });
})

eventEmitter.on(EventLists.gotoAbout, async () => {
if (!settingWindow) {
await createWindow('SETTING_WINDOW');
}
const serverSetting = LocalStore.getStore('config');
settingWindow?.show();
settingWindow?.webContents.once('did-finish-load', () => {
setTimeout(() => {
SendMessageToSettingWindow(SettingPageTypeMessage.loadSetting, serverSetting);
settingWindow?.webContents.send('languageSignal', serverSetting.general?.lang);
SendMessageToSettingWindow(SettingPageTypeMessage.selectMenu, { key: 'about' });
}, 100)
})
})
eventEmitter.on(EventLists.OPEN_WINDOW, handleOpenWindow)

eventEmitter.on(EventLists.SERVER_WINDOW, async () => {
if (!logWindow) {
initTrayMenu()
await createWindow('LOG_WINDOW');
logWindow = await createWindow(WindowTypes.LOG_WINDOW);
}
const serverSetting = LocalStore.getStore('config');
logWindow?.show();
Expand Down Expand Up @@ -438,6 +436,16 @@ const onInitApplication = () => {
eventEmitter.on(EventLists.SERVER_WINDOW_DEV, () => {
logWindow?.webContents.toggleDevTools();
})

eventEmitter.on(EventLists.WINDOW_EVENT, (data) => {
switch (data.eventType) {
case 'close':
handleCloseWindow(data.windowType)
break;
default:
break;
}
})
}

const initTrayMenu = () => {
Expand Down Expand Up @@ -480,7 +488,7 @@ const initTrayMenu = () => {
eventEmitter.emit(EventLists.SERVER_WINDOW);
} else {
if (!setupWindow) {
await createWindow('SETUP_WINDOW');
setupWindow = await createWindow(WindowTypes.SETUP_WINDOW);
}
if (setupWindow) {
setupWindow?.show();
Expand Down Expand Up @@ -569,6 +577,10 @@ ipcMain.on(IPC_TYPES.SETTING_PAGE, async (event, arg) => {
createIntervalAutoUpdate()
event.sender.send(IPC_TYPES.UPDATER_PAGE, { type: SettingPageTypeMessage.updateSettingResponse, data: true })
break;
case SettingPageTypeMessage.linkAction:
console.log(arg)
handleLinkAction(arg.data.linkType)
break;
default:
break;
}
Expand Down
Loading
Loading