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')