From 3ede6df028160e3aae91454c2a6c3686cc69bcc0 Mon Sep 17 00:00:00 2001 From: Miguel de la Cruz Date: Wed, 10 Nov 2021 16:33:56 +0100 Subject: [PATCH] Show a refresh banner on plugin update (#1720) * Reload plugin on plugin update * Add a banner that shows when updating the plugin and asks the user to reload * Fix linter --- mattermost-plugin/webapp/src/index.tsx | 1 + webapp/i18n/en.json | 1 + webapp/src/app.tsx | 2 + webapp/src/components/newVersionBanner.scss | 5 +++ webapp/src/components/newVersionBanner.tsx | 41 +++++++++++++++++++++ webapp/src/wsclient.ts | 18 +++++++++ 6 files changed, 68 insertions(+) create mode 100644 webapp/src/components/newVersionBanner.scss create mode 100644 webapp/src/components/newVersionBanner.tsx diff --git a/mattermost-plugin/webapp/src/index.tsx b/mattermost-plugin/webapp/src/index.tsx index 3641989ab..e0b86702f 100644 --- a/mattermost-plugin/webapp/src/index.tsx +++ b/mattermost-plugin/webapp/src/index.tsx @@ -182,6 +182,7 @@ export default class Plugin { // register websocket handlers this.registry?.registerWebSocketEventHandler(`custom_${manifest.id}_${ACTION_UPDATE_BLOCK}`, (e: any) => wsClient.updateBlockHandler(e.data)) this.registry?.registerWebSocketEventHandler(`custom_${manifest.id}_${ACTION_UPDATE_CLIENT_CONFIG}`, (e: any) => wsClient.updateClientConfigHandler(e.data)) + this.registry?.registerWebSocketEventHandler(`plugin_statuses_changed`, (e: any) => wsClient.pluginStatusesChangedHandler(e.data)) this.registry?.registerWebSocketEventHandler('preferences_changed', (e: any) => { let preferences try { diff --git a/webapp/i18n/en.json b/webapp/i18n/en.json index 12ba3d480..8411b0e69 100644 --- a/webapp/i18n/en.json +++ b/webapp/i18n/en.json @@ -8,6 +8,7 @@ "BoardComponent.no-property-title": "Items with an empty {property} property will go here. This column cannot be removed.", "BoardComponent.show": "Show", "BoardPage.syncFailed": "Board may be deleted or access revoked.", + "BoardPage.newVersion": "A new version of Boards is available, click here to reload.", "Calculations.Options.average.displayName": "Average", "Calculations.Options.average.label": "Average", "Calculations.Options.count.displayName": "Count", diff --git a/webapp/src/app.tsx b/webapp/src/app.tsx index 989bf1db3..1c653c2df 100644 --- a/webapp/src/app.tsx +++ b/webapp/src/app.tsx @@ -19,6 +19,7 @@ import TelemetryClient from './telemetry/telemetryClient' import {IAppWindow} from './types' import {getMessages} from './i18n' import {FlashMessages} from './components/flashMessages' +import NewVersionBanner from './components/newVersionBanner' import BoardPage from './pages/boardPage' import ChangePasswordPage from './pages/changePasswordPage' import DashboardPage from './pages/dashboard/dashboardPage' @@ -141,6 +142,7 @@ const App = React.memo((): JSX.Element => { >
+ {globalErrorRedirect} diff --git a/webapp/src/components/newVersionBanner.scss b/webapp/src/components/newVersionBanner.scss new file mode 100644 index 000000000..c4f79afc4 --- /dev/null +++ b/webapp/src/components/newVersionBanner.scss @@ -0,0 +1,5 @@ +.NewVersionBanner { + background-color: var(--prop-blue); + text-align: center; + padding: 10px; +} diff --git a/webapp/src/components/newVersionBanner.tsx b/webapp/src/components/newVersionBanner.tsx new file mode 100644 index 000000000..7cca56fde --- /dev/null +++ b/webapp/src/components/newVersionBanner.tsx @@ -0,0 +1,41 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. +import React, {useState, useEffect} from 'react' +import {FormattedMessage} from 'react-intl' + +import wsClient from '../wsclient' + +import './newVersionBanner.scss' + +const NewVersionBanner = () => { + const [appVersionChanged, setAppVersionChanged] = useState(false) + useEffect(() => { + wsClient.onAppVersionChangeHandler = setAppVersionChanged + }, []) + + if (!appVersionChanged) { + return null + } + + const newVersionReload = (e: any) => { + e.preventDefault() + location.reload() + } + + return ( +
+ + + +
+ ) +} + +export default NewVersionBanner diff --git a/webapp/src/wsclient.ts b/webapp/src/wsclient.ts index 979d92739..0ab189202 100644 --- a/webapp/src/wsclient.ts +++ b/webapp/src/wsclient.ts @@ -49,6 +49,8 @@ type OnConfigChangeHandler = (client: WSClient, clientConfig: ClientConfig) => v class WSClient { ws: WebSocket|null = null client: MMWebSocketClient|null = null + pluginId = '' + onAppVersionChangeHandler: ((versionHasChanged: boolean) => void) | null = null clientPrefix = '' serverUrl: string | undefined state: 'init'|'open'|'close' = 'init' @@ -88,6 +90,7 @@ class WSClient { } initPlugin(pluginId: string, client: MMWebSocketClient): void { + this.pluginId = pluginId this.clientPrefix = `custom_${pluginId}_` this.client = client Utils.log(`WSClient initialised for plugin id "${pluginId}"`) @@ -299,6 +302,21 @@ class WSClient { } } + setOnAppVersionChangeHandler(fn: (versionHasChanged: boolean) => void): void { + this.onAppVersionChangeHandler = fn + } + + pluginStatusesChangedHandler(data: any): void { + if (this.pluginId === '' || !this.onAppVersionChangeHandler) { + return + } + + if (data.plugin_statuses.some((s: any) => s.plugin_id === this.pluginId)) { + Utils.log('Boards plugin has been updated') + this.onAppVersionChangeHandler(true) + } + } + authenticate(workspaceId: string, token: string): void { if (!this.hasConn()) { Utils.assertFailure('WSClient.addBlocks: ws is not open')