diff --git a/mattermost-plugin/server/manifest.go b/mattermost-plugin/server/manifest.go
index d0c95fbee..516e7fd6f 100644
--- a/mattermost-plugin/server/manifest.go
+++ b/mattermost-plugin/server/manifest.go
@@ -20,7 +20,7 @@ const manifestStr = `
"release_notes_url": "https://github.com/mattermost/focalboard/releases",
"icon_path": "assets/starter-template-icon.svg",
"version": "0.8.0",
- "min_server_version": "5.36.0",
+ "min_server_version": "5.37.0",
"server": {
"executables": {
"linux-amd64": "server/dist/plugin-linux-amd64",
diff --git a/webapp/src/components/sidebar/boardTemplateMenuItem.tsx b/webapp/src/components/sidebar/boardTemplateMenuItem.tsx
index e1b65b632..1ce7ee6b7 100644
--- a/webapp/src/components/sidebar/boardTemplateMenuItem.tsx
+++ b/webapp/src/components/sidebar/boardTemplateMenuItem.tsx
@@ -50,7 +50,7 @@ const BoardTemplateMenuItem = React.memo((props: Props) => {
key={boardTemplate.id}
id={boardTemplate.id}
name={displayName}
- icon={
{boardTemplate.icon}
}
+ icon={{boardTemplate.fields.icon}
}
onClick={() => {
addBoardFromTemplate(intl, props.showBoard, boardTemplate.id, activeBoardId, isGlobal)
}}
diff --git a/webapp/src/components/sidebar/sidebarAddBoardMenu.tsx b/webapp/src/components/sidebar/sidebarAddBoardMenu.tsx
index 9813c494f..1e653a073 100644
--- a/webapp/src/components/sidebar/sidebarAddBoardMenu.tsx
+++ b/webapp/src/components/sidebar/sidebarAddBoardMenu.tsx
@@ -1,6 +1,6 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
-import React, {useState, useEffect, useCallback} from 'react'
+import React, {useEffect, useCallback} from 'react'
import {FormattedMessage, useIntl, IntlShape} from 'react-intl'
import {generatePath, useHistory, useRouteMatch} from 'react-router-dom'
@@ -8,12 +8,13 @@ import {MutableBoard} from '../../blocks/board'
import {MutableBoardView} from '../../blocks/boardView'
import mutator from '../../mutator'
import octoClient from '../../octoClient'
-import {GlobalTemplateTree, MutableGlobalTemplateTree} from '../../viewModel/globalTemplateTree'
import {WorkspaceTree} from '../../viewModel/workspaceTree'
import AddIcon from '../../widgets/icons/add'
import BoardIcon from '../../widgets/icons/board'
import Menu from '../../widgets/menu'
import MenuWrapper from '../../widgets/menuWrapper'
+import {useAppDispatch, useAppSelector} from '../../store/hooks'
+import {getGlobalTemplates, fetchGlobalTemplates} from '../../store/globalTemplates'
import BoardTemplateMenuItem from './boardTemplateMenuItem'
@@ -68,7 +69,8 @@ const addBoardTemplateClicked = async (showBoard: (id: string) => void, activeBo
}
const SidebarAddBoardMenu = (props: Props): JSX.Element => {
- const [globalTemplateTree, setGlobalTemplateTree] = useState(null)
+ const globalTemplates = useAppSelector(getGlobalTemplates)
+ const dispatch = useAppDispatch()
const history = useHistory()
const match = useRouteMatch()
@@ -78,13 +80,10 @@ const SidebarAddBoardMenu = (props: Props): JSX.Element => {
}, [match, history])
useEffect(() => {
- if (octoClient.workspaceId !== '0' && !globalTemplateTree) {
- const syncFunc = async () => {
- setGlobalTemplateTree(await MutableGlobalTemplateTree.sync())
- }
- syncFunc()
+ if (octoClient.workspaceId !== '0' && globalTemplates.length === 0) {
+ dispatch(fetchGlobalTemplates())
}
- }, [])
+ }, [octoClient.workspaceId])
const {workspaceTree} = props
const intl = useIntl()
@@ -126,7 +125,7 @@ const SidebarAddBoardMenu = (props: Props): JSX.Element => {
/>
))}
- {globalTemplateTree && globalTemplateTree.boardTemplates.map((boardTemplate) => (
+ {globalTemplates.map((boardTemplate: MutableBoard) => (
{
+ const rootClient = new OctoClient(client.serverUrl, '0')
+ const rawBlocks = await rootClient.getBlocksWithType('board')
+ const allBoards = rawBlocks as MutableBoard[]
+ return allBoards.filter((block) => block.fields.isTemplate).sort((a, b) => a.title.localeCompare(b.title)) as MutableBoard[]
+ },
+)
+
+const globalTemplatesSlice = createSlice({
+ name: 'globalTemplates',
+ initialState: {value: []} as {value: MutableBoard[]},
+ reducers: {},
+ extraReducers: (builder) => {
+ builder.addCase(fetchGlobalTemplates.fulfilled, (state, action) => {
+ state.value = action.payload || []
+ })
+ },
+})
+
+export const {reducer} = globalTemplatesSlice
+
+export function getGlobalTemplates(state: RootState): MutableBoard[] {
+ return state.globalTemplates.value
+}
diff --git a/webapp/src/store/index.ts b/webapp/src/store/index.ts
index aecf4bd6b..159e192f9 100644
--- a/webapp/src/store/index.ts
+++ b/webapp/src/store/index.ts
@@ -7,6 +7,7 @@ import {reducer as currentUserReducer} from './currentUser'
import {reducer as currentWorkspaceReducer} from './currentWorkspace'
import {reducer as currentWorkspaceUsersReducer} from './currentWorkspaceUsers'
import {reducer as languageReducer} from './language'
+import {reducer as globalTemplatesReducer} from './globalTemplates'
const store = configureStore({
reducer: {
@@ -14,6 +15,7 @@ const store = configureStore({
currentWorkspace: currentWorkspaceReducer,
currentWorkspaceUsers: currentWorkspaceUsersReducer,
language: languageReducer,
+ globalTemplates: globalTemplatesReducer,
},
})
diff --git a/webapp/src/viewModel/globalTemplateTree.ts b/webapp/src/viewModel/globalTemplateTree.ts
deleted file mode 100644
index f42323bce..000000000
--- a/webapp/src/viewModel/globalTemplateTree.ts
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
-// See LICENSE.txt for license information.
-import {IBlock} from '../blocks/block'
-import {Board} from '../blocks/board'
-import octoClient, {OctoClient} from '../octoClient'
-import {OctoUtils} from '../octoUtils'
-
-interface GlobalTemplateTree {
- readonly boardTemplates: readonly Board[]
- readonly allBlocks: readonly IBlock[]
-}
-
-class MutableGlobalTemplateTree implements GlobalTemplateTree {
- boardTemplates: Board[] = []
- get allBlocks(): IBlock[] {
- return [...this.boardTemplates]
- }
-
- // Factory methods
-
- static async sync(): Promise {
- const rootClient = new OctoClient(octoClient.serverUrl, '0')
- const rawBlocks = await rootClient.getBlocksWithType('board')
-
- return this.buildTree(rawBlocks)
- }
-
- static incrementalUpdate(originalTree: GlobalTemplateTree, updatedBlocks: IBlock[]): GlobalTemplateTree {
- const relevantBlocks = updatedBlocks.filter((block) => block.deleteAt !== 0 || block.type === 'board' || block.type === 'view')
- if (relevantBlocks.length < 1) {
- // No change
- return originalTree
- }
- const rawBlocks = OctoUtils.mergeBlocks(originalTree.allBlocks, relevantBlocks)
- return this.buildTree(rawBlocks)
- }
-
- private static buildTree(sourceBlocks: readonly IBlock[]): MutableGlobalTemplateTree {
- const blocks = OctoUtils.hydrateBlocks(sourceBlocks)
-
- const workspaceTree = new MutableGlobalTemplateTree()
- const allBoards = blocks.filter((block) => block.type === 'board') as Board[]
- workspaceTree.boardTemplates = allBoards.filter((block) => block.isTemplate).
- sort((a, b) => a.title.localeCompare(b.title)) as Board[]
-
- return workspaceTree
- }
-
- // private mutableCopy(): MutableWorkspaceTree {
- // return MutableWorkspaceTree.buildTree(this.allBlocks)!
- // }
-}
-
-export {MutableGlobalTemplateTree, GlobalTemplateTree}