From 513a7e0a86a6857d9bf327f62565891ef1da9351 Mon Sep 17 00:00:00 2001 From: Devin Binnie <52460000+devinbinnie@users.noreply.github.com> Date: Fri, 22 Nov 2024 10:18:38 -0500 Subject: [PATCH] [MM-56795] Improve help options in the Help menu (#3216) * [MM-56795] Improve help options in the Help menu * Fix i18n * Remove extra separator --- i18n/en.json | 4 ++- src/common/config/buildConfig.ts | 5 +++- src/common/config/index.ts | 3 ++ src/common/constants.ts | 10 ++++--- src/main/downloadsManager.ts | 7 +---- src/main/menus/app.test.js | 2 ++ src/main/menus/app.ts | 47 ++++++++++++++++++++++++++++---- src/main/server/serverInfo.ts | 11 ++++++++ src/types/config.ts | 1 + src/types/downloads.ts | 5 +++- src/types/server.ts | 6 ++++ 11 files changed, 83 insertions(+), 18 deletions(-) diff --git a/i18n/en.json b/i18n/en.json index f5e04084602..d5bae7405f9 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -67,13 +67,15 @@ "main.menus.app.file.signInToAnotherServer": "Sign in to Another Server", "main.menus.app.file.unhide": "Show All", "main.menus.app.help": "Hel&p", + "main.menus.app.help.academy": "Mattermost Academy", "main.menus.app.help.checkForUpdates": "Check for Updates", "main.menus.app.help.commitString": " commit: {hashVersion}", "main.menus.app.help.downloadUpdate": "Download Update", - "main.menus.app.help.learnMore": "Learn More...", + "main.menus.app.help.reportProblem": "Report a problem", "main.menus.app.help.restartAndUpdate": "Restart and Update", "main.menus.app.help.RunDiagnostics": "Run diagnostics", "main.menus.app.help.ShowLogs": "Show logs", + "main.menus.app.help.userGuide": "User guide", "main.menus.app.help.versionString": "Version {version}{commit}", "main.menus.app.history": "&History", "main.menus.app.history.back": "Back", diff --git a/src/common/config/buildConfig.ts b/src/common/config/buildConfig.ts index feb72de680d..2272c4f215f 100644 --- a/src/common/config/buildConfig.ts +++ b/src/common/config/buildConfig.ts @@ -4,6 +4,8 @@ import type {BuildConfig} from 'types/config'; +import {DEFAULT_ACADEMY_LINK, DEFAULT_HELP_LINK} from '../../common/constants'; + // For detailed guides, please refer to https://docs.mattermost.com/deployment/desktop-app-deployment.html /** @@ -27,7 +29,8 @@ const buildConfig: BuildConfig = { url: 'https://example.com' } */], - helpLink: 'https://docs.mattermost.com/messaging/managing-desktop-app-servers.html', + helpLink: DEFAULT_HELP_LINK, + academyLink: DEFAULT_ACADEMY_LINK, enableServerManagement: true, enableAutoUpdater: true, managedResources: ['trusted'], diff --git a/src/common/config/index.ts b/src/common/config/index.ts index 4f999b27478..746703a7e5c 100644 --- a/src/common/config/index.ts +++ b/src/common/config/index.ts @@ -216,6 +216,9 @@ export class Config extends EventEmitter { get helpLink() { return this.combinedData?.helpLink; } + get academyLink() { + return this.combinedData?.academyLink; + } get minimizeToTray() { return this.combinedData?.minimizeToTray; } diff --git a/src/common/constants.ts b/src/common/constants.ts index d2a56d13236..0f0739ac60b 100644 --- a/src/common/constants.ts +++ b/src/common/constants.ts @@ -1,16 +1,13 @@ // Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import type {DownloadItemTypeEnum} from 'main/downloadsManager'; - -import type {DownloadedItem} from 'types/downloads'; +import type {DownloadedItem, DownloadItemTypeEnum} from 'types/downloads'; /** * This string includes special characters so that it's not confused with * a file that may have the same filename (eg APP_UPDATE) */ export const APP_UPDATE_KEY = '#:(APP_UPDATE):#'; - export const UPDATE_DOWNLOAD_ITEM: Omit = { type: 'update' as DownloadItemTypeEnum, progress: 0, @@ -46,3 +43,8 @@ export const IS_ONLINE_ENDPOINT = 'https://community.mattermost.com/api/v4/syste export const COOKIE_NAME_USER_ID = 'MMUSERID'; export const COOKIE_NAME_CSRF = 'MMCSRF'; export const COOKIE_NAME_AUTH_TOKEN = 'MMAUTHTOKEN'; + +export const DEFAULT_HELP_LINK = 'https://docs.mattermost.com/guides/collaborate.html'; +export const DEFAULT_ACADEMY_LINK = 'https://academy.mattermost.com/'; +export const DEFAULT_TE_REPORT_PROBLEM_LINK = 'https://mattermost.com/pl/report-a-bug'; +export const DEFAULT_EE_REPORT_PROBLEM_LINK = 'https://support.mattermost.com/hc/en-us/requests/new'; diff --git a/src/main/downloadsManager.ts b/src/main/downloadsManager.ts index 49cd5bbe0b4..eb81ca9b93d 100644 --- a/src/main/downloadsManager.ts +++ b/src/main/downloadsManager.ts @@ -36,18 +36,13 @@ import {doubleSecToMs, getPercentage, isStringWithLength, readFilenameFromConten import ViewManager from 'main/views/viewManager'; import MainWindow from 'main/windows/mainWindow'; -import type {DownloadedItem, DownloadItemDoneEventState, DownloadedItems, DownloadItemState, DownloadItemUpdatedEventState} from 'types/downloads'; +import {type DownloadedItem, type DownloadItemDoneEventState, type DownloadedItems, type DownloadItemState, type DownloadItemUpdatedEventState, DownloadItemTypeEnum} from 'types/downloads'; import appVersionManager from './AppVersionManager'; import {downloadsJson} from './constants'; const log = new Logger('DownloadsManager'); -export enum DownloadItemTypeEnum { - FILE = 'file', - UPDATE = 'update', -} - export class DownloadsManager extends JsonFileManager { autoCloseTimeout: NodeJS.Timeout | null; open: boolean; diff --git a/src/main/menus/app.test.js b/src/main/menus/app.test.js index 9e9348806cc..e1977fa4636 100644 --- a/src/main/menus/app.test.js +++ b/src/main/menus/app.test.js @@ -68,6 +68,7 @@ jest.mock('common/servers/serverManager', () => ({ hasServers: jest.fn(), getOrderedServers: jest.fn(), getOrderedTabsForServer: jest.fn(), + getRemoteInfo: jest.fn(), })); jest.mock('app/serverViewState', () => ({ switchServer: jest.fn(), @@ -302,6 +303,7 @@ describe('main/menus/app', () => { } return id; }); + ServerManager.hasServers.mockReturnValue(true); ServerViewState.getCurrentServer.mockImplementation(() => ({id: servers[0].id})); const modifiedViews = [...Array(15).keys()].map((key) => ({ diff --git a/src/main/menus/app.ts b/src/main/menus/app.ts index 816d0b86e26..ea8174fe1a6 100644 --- a/src/main/menus/app.ts +++ b/src/main/menus/app.ts @@ -10,6 +10,7 @@ import log from 'electron-log'; import ServerViewState from 'app/serverViewState'; import {OPEN_SERVERS_DROPDOWN, SHOW_NEW_SERVER_MODAL} from 'common/communication'; import type {Config} from 'common/config'; +import {DEFAULT_EE_REPORT_PROBLEM_LINK, DEFAULT_TE_REPORT_PROBLEM_LINK} from 'common/constants'; import ServerManager from 'common/servers/serverManager'; import {t} from 'common/utils/util'; import {getViewDisplayName} from 'common/views/View'; @@ -312,6 +313,7 @@ export function createTemplate(config: Config, updateManager: UpdateManager) { }); const servers = ServerManager.getOrderedServers(); + const currentServer = ServerManager.hasServers() ? ServerViewState.getCurrentServer() : undefined; const windowMenu = { id: 'window', label: localizeMessage('main.menus.app.window', '&Window'), @@ -347,7 +349,7 @@ export function createTemplate(config: Config, updateManager: UpdateManager) { ServerViewState.switchServer(server.id); }, }); - if (ServerViewState.getCurrentServer().id === server.id) { + if (currentServer?.id === server.id) { ServerManager.getOrderedTabsForServer(server.id).slice(0, 9).forEach((view, i) => { items.push({ label: ` ${localizeMessage(`common.views.${view.type}`, getViewDisplayName(view.type as ViewType))}`, @@ -380,6 +382,8 @@ export function createTemplate(config: Config, updateManager: UpdateManager) { ], }; template.push(windowMenu); + + const currentRemoteInfo = currentServer ? ServerManager.getRemoteInfo(currentServer.id) : undefined; const submenu = []; if (updateManager && config.canUpgrade) { if (updateManager.versionDownloaded) { @@ -404,16 +408,28 @@ export function createTemplate(config: Config, updateManager: UpdateManager) { }, }); } + submenu.push(separatorItem); } - if (config.helpLink) { + + const helpLink = currentRemoteInfo?.helpLink ?? config.helpLink; + if (helpLink) { submenu.push({ - label: localizeMessage('main.menus.app.help.learnMore', 'Learn More...'), + label: localizeMessage('main.menus.app.help.userGuide', 'User guide'), click() { - shell.openExternal(config.helpLink!); + shell.openExternal(helpLink); + }, + }); + } + const academyLink = config.academyLink; + if (academyLink) { + submenu.push({ + label: localizeMessage('main.menus.app.help.academy', 'Mattermost Academy'), + click() { + shell.openExternal(academyLink); }, }); - submenu.push(separatorItem); } + submenu.push(separatorItem); submenu.push({ id: 'Show logs', @@ -430,6 +446,27 @@ export function createTemplate(config: Config, updateManager: UpdateManager) { Diagnostics.run(); }, }); + + let reportProblemLink = currentRemoteInfo?.reportProblemLink; + if (!reportProblemLink) { + switch (currentRemoteInfo?.licenseSku) { + case 'enterprise': + case 'professional': + reportProblemLink = DEFAULT_EE_REPORT_PROBLEM_LINK; + break; + default: + reportProblemLink = DEFAULT_TE_REPORT_PROBLEM_LINK; + break; + } + } + if (reportProblemLink) { + submenu.push({ + label: localizeMessage('main.menus.app.help.reportProblem', 'Report a problem'), + click() { + shell.openExternal(reportProblemLink!); + }, + }); + } submenu.push(separatorItem); const version = localizeMessage('main.menus.app.help.versionString', 'Version {version}{commit}', { diff --git a/src/main/server/serverInfo.ts b/src/main/server/serverInfo.ts index 191209fd938..9dabc3aac50 100644 --- a/src/main/server/serverInfo.ts +++ b/src/main/server/serverInfo.ts @@ -32,6 +32,10 @@ export class ServerInfo { this.onGetPlugins, parseURL(`${this.server.url}/api/v4/plugins/webapp`), ); + await this.getRemoteInfo<{SkuShortName: string}>( + this.onGetLicense, + parseURL(`${this.server.url}/api/v4/license/client?format=old`), + ); return this.remoteInfo; }; @@ -66,10 +70,17 @@ export class ServerInfo { this.remoteInfo.siteURL = data.SiteURL; this.remoteInfo.siteName = data.SiteName; this.remoteInfo.hasFocalboard = this.remoteInfo.hasFocalboard || data.BuildBoards === 'true'; + this.remoteInfo.helpLink = data.HelpLink; + this.remoteInfo.reportProblemLink = data.ReportAProblemLink; + }; + + private onGetLicense = (data: {SkuShortName: string}) => { + this.remoteInfo.licenseSku = data.SkuShortName; }; private onGetPlugins = (data: Array<{id: string; version: string}>) => { this.remoteInfo.hasFocalboard = this.remoteInfo.hasFocalboard || data.some((plugin) => plugin.id === 'focalboard'); this.remoteInfo.hasPlaybooks = data.some((plugin) => plugin.id === 'playbooks'); + this.remoteInfo.hasUserSurvey = data.some((plugin) => plugin.id === 'com.mattermost.nps'); }; } diff --git a/src/types/config.ts b/src/types/config.ts index 670012f9571..75997fbe4f8 100644 --- a/src/types/config.ts +++ b/src/types/config.ts @@ -106,6 +106,7 @@ export type AnyConfig = ConfigV3 | ConfigV2 | ConfigV1 | ConfigV0; export type BuildConfig = { defaultServers?: Server[]; helpLink: string; + academyLink: string; enableServerManagement: boolean; enableAutoUpdater: boolean; managedResources: string[]; diff --git a/src/types/downloads.ts b/src/types/downloads.ts index b5b9b608f82..162613b70d5 100644 --- a/src/types/downloads.ts +++ b/src/types/downloads.ts @@ -1,7 +1,10 @@ // Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import type {DownloadItemTypeEnum} from 'main/downloadsManager'; +export enum DownloadItemTypeEnum { + FILE = 'file', + UPDATE = 'update', +} export type DownloadItemUpdatedEventState = 'interrupted' | 'progressing'; export type DownloadItemDoneEventState = 'completed' | 'cancelled' | 'interrupted'; diff --git a/src/types/server.ts b/src/types/server.ts index 742b44f7a70..c0b732b0a55 100644 --- a/src/types/server.ts +++ b/src/types/server.ts @@ -5,8 +5,12 @@ export type RemoteInfo = { serverVersion?: string; siteName?: string; siteURL?: string; + licenseSku?: string; + helpLink?: string; + reportProblemLink?: string; hasFocalboard?: boolean; hasPlaybooks?: boolean; + hasUserSurvey?: boolean; }; export type ClientConfig = { @@ -14,6 +18,8 @@ export type ClientConfig = { SiteURL: string; SiteName: string; BuildBoards: string; + HelpLink: string; + ReportAProblemLink: string; } export type URLValidationResult = {