mirror of
https://github.com/mattermost/focalboard.git
synced 2024-12-24 13:43:12 +02:00
move template id handling to plugin
This commit is contained in:
parent
66c255e2cd
commit
3b88cefcff
3
mattermost-plugin/server/manifest.go
generated
3
mattermost-plugin/server/manifest.go
generated
@ -45,7 +45,8 @@ const manifestStr = `
|
||||
"type": "bool",
|
||||
"help_text": "This allows board editors to share boards that can be accessed by anyone with the link.",
|
||||
"placeholder": "",
|
||||
"default": false
|
||||
"default": false,
|
||||
"hosting": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -23,16 +23,16 @@ describe('components/createBoardFromTemplate', () => {
|
||||
it('renders the Create Boards from template component and match snapshot', async () => {
|
||||
const store = mockStateStore([], state)
|
||||
let container: Element | DocumentFragment | null = null
|
||||
const setSelectedTemplate = jest.fn
|
||||
const toggleAddBoardCheckbox = jest.fn
|
||||
const setCanCreate = jest.fn
|
||||
const setAction = jest.fn
|
||||
const newBoardInfoIcon = (<i className="icon-information-outline" />)
|
||||
|
||||
await act(async () => {
|
||||
const result = render(wrapIntl(
|
||||
<ReduxProvider store={store}>
|
||||
<CreateBoardFromTemplate
|
||||
setSelectedTemplate={setSelectedTemplate}
|
||||
toggleAddBoardCheck={toggleAddBoardCheckbox}
|
||||
setAction={setAction}
|
||||
setCanCreate={setCanCreate}
|
||||
newBoardInfoIcon={newBoardInfoIcon}
|
||||
/>
|
||||
</ReduxProvider>
|
||||
@ -45,16 +45,16 @@ describe('components/createBoardFromTemplate', () => {
|
||||
|
||||
it('clicking checkbox toggles the templates selector', async () => {
|
||||
const store = mockStateStore([], state)
|
||||
const setSelectedTemplate = jest.fn
|
||||
const toggleAddBoardCheckbox = jest.fn
|
||||
const setCanCreate = jest.fn
|
||||
const setAction = jest.fn
|
||||
const newBoardInfoIcon = (<i className="icon-information-outline" />)
|
||||
|
||||
await act(async () => {
|
||||
render(wrapIntl(
|
||||
<ReduxProvider store={store}>
|
||||
<CreateBoardFromTemplate
|
||||
setSelectedTemplate={setSelectedTemplate}
|
||||
toggleAddBoardCheck={toggleAddBoardCheckbox}
|
||||
setAction={setAction}
|
||||
setCanCreate={setCanCreate}
|
||||
newBoardInfoIcon={newBoardInfoIcon}
|
||||
/>
|
||||
</ReduxProvider>
|
||||
@ -74,7 +74,7 @@ describe('components/createBoardFromTemplate', () => {
|
||||
await act(async () => {
|
||||
await userEvent.click(checkbox)
|
||||
const templatesSelector = screen.queryByText('Select a template')
|
||||
expect(templatesSelector).not.toBeInTheDocument()
|
||||
expect(templatesSelector).toBeNull()
|
||||
})
|
||||
|
||||
})
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
import React, {useState} from 'react'
|
||||
import React, {useCallback, useEffect, useRef, useState} from 'react'
|
||||
|
||||
import {createIntl, createIntlCache, IntlProvider} from 'react-intl'
|
||||
|
||||
@ -18,10 +18,11 @@ import {mutator} from '../../../../webapp/src/mutator'
|
||||
import {useGetAllTemplates} from '../../../../webapp/src/hooks/useGetAllTemplates'
|
||||
|
||||
import './createBoardFromTemplate.scss'
|
||||
import {Board} from '../../../../webapp/src/blocks/board'
|
||||
|
||||
type Props = {
|
||||
setSelectedTemplate: (templateId: string) => void;
|
||||
toggleAddBoardCheck: (addBoard: boolean) => void;
|
||||
setCanCreate: (canCreate: boolean) => void;
|
||||
setAction: (fn: () => (channelId: string, teamId: string) => Promise<Board | undefined>) => void;
|
||||
newBoardInfoIcon: React.ReactNode;
|
||||
}
|
||||
|
||||
@ -41,23 +42,6 @@ const intl = createIntl({
|
||||
messages: getMessages(getCurrentLanguage())
|
||||
}, cache)
|
||||
|
||||
export const createBoardFromTemplateAction = async (templateId: string, teamId: string, channelId: string) => {
|
||||
const ACTION_DESCRIPTION = 'board created from channel'
|
||||
const asTemplate = false
|
||||
|
||||
let boardsAndBlocks = undefined
|
||||
|
||||
if (templateId === EMPTY_BOARD) {
|
||||
boardsAndBlocks = await mutator.addEmptyBoard(teamId, intl)
|
||||
} else {
|
||||
boardsAndBlocks = await mutator.duplicateBoard(templateId, ACTION_DESCRIPTION, asTemplate, undefined, undefined, teamId)
|
||||
}
|
||||
|
||||
const board = boardsAndBlocks.boards[0]
|
||||
await mutator.updateBoard({...board, channelId: channelId}, board, 'linked channel')
|
||||
return board
|
||||
}
|
||||
|
||||
const {ValueContainer, Placeholder} = components
|
||||
|
||||
const CreateBoardFromTemplate = (props: Props) => {
|
||||
@ -65,14 +49,49 @@ const CreateBoardFromTemplate = (props: Props) => {
|
||||
|
||||
const [addBoard, setAddBoard] = useState(false)
|
||||
const allTemplates = useGetAllTemplates()
|
||||
const [selectedBoardTemplateId, setSelectedBoardTemplateId] = useState<string>('')
|
||||
|
||||
const addBoardRef = useRef(false)
|
||||
addBoardRef.current = addBoard
|
||||
const templateIdRef = useRef('')
|
||||
templateIdRef.current = selectedBoardTemplateId
|
||||
|
||||
|
||||
const showNewBoardTemplateSelector = async () => {
|
||||
setAddBoard((prev: boolean) => {
|
||||
props.toggleAddBoardCheck(!prev)
|
||||
return !prev
|
||||
})
|
||||
setAddBoard((prev: boolean) => !prev)
|
||||
}
|
||||
|
||||
// CreateBoardFromTemplate
|
||||
const addBoardToChannel = async (channelId: string, teamId: string) => {
|
||||
if (!addBoardRef.current || !templateIdRef.current) {
|
||||
return
|
||||
}
|
||||
|
||||
const ACTION_DESCRIPTION = 'board created from channel'
|
||||
const LINKED_CHANNEL = 'linked channel'
|
||||
const asTemplate = false
|
||||
|
||||
let boardsAndBlocks = undefined
|
||||
|
||||
if (selectedBoardTemplateId === EMPTY_BOARD) {
|
||||
boardsAndBlocks = await mutator.addEmptyBoard(teamId, intl)
|
||||
} else {
|
||||
boardsAndBlocks = await mutator.duplicateBoard(templateIdRef.current as string, ACTION_DESCRIPTION, asTemplate, undefined, undefined, teamId)
|
||||
}
|
||||
|
||||
const board = boardsAndBlocks.boards[0]
|
||||
await mutator.updateBoard({...board, channelId: channelId}, board, LINKED_CHANNEL)
|
||||
return board
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
props.setAction(() => addBoardToChannel)
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
props.setCanCreate(!addBoard || (addBoard && selectedBoardTemplateId !== ''))
|
||||
}, [addBoard, selectedBoardTemplateId])
|
||||
|
||||
const getSubstringWithCompleteWords = (str: string, len: number) => {
|
||||
if (str?.length <= len) {
|
||||
return str
|
||||
@ -128,7 +147,7 @@ const CreateBoardFromTemplate = (props: Props) => {
|
||||
)
|
||||
}
|
||||
|
||||
const loadOptions = async (value = '') => {
|
||||
const loadOptions = useCallback(async (value = '') => {
|
||||
let templates = allTemplates.map((template) => {
|
||||
return {
|
||||
id: template.id,
|
||||
@ -151,7 +170,13 @@ const CreateBoardFromTemplate = (props: Props) => {
|
||||
templates = templates.filter(template => template.title.toLowerCase().includes(value.toLowerCase()))
|
||||
}
|
||||
return templates
|
||||
}
|
||||
}, [allTemplates])
|
||||
|
||||
const onChange = useCallback((item: SingleValue<ReactSelectItem>) => {
|
||||
if (item) {
|
||||
setSelectedBoardTemplateId(item.id)
|
||||
}
|
||||
}, [setSelectedBoardTemplateId])
|
||||
|
||||
const selectorStyles = {
|
||||
menu: (baseStyles: CSSObject): CSSObject => ({
|
||||
@ -205,11 +230,7 @@ const CreateBoardFromTemplate = (props: Props) => {
|
||||
<Select
|
||||
classNamePrefix={'CreateBoardFromTemplate--templates-selector'}
|
||||
placeholder={formatMessage({id: 'new_channel_modal.create_board.select_template_placeholder', defaultMessage: 'Select a template'})}
|
||||
onChange={(item: SingleValue<ReactSelectItem>) => {
|
||||
if (item) {
|
||||
props.setSelectedTemplate(item.id)
|
||||
}
|
||||
}}
|
||||
onChange={onChange}
|
||||
components={{IndicatorSeparator: () => null, ValueContainer: CustomValueContainer}}
|
||||
loadOptions={loadOptions}
|
||||
getOptionValue={(v) => v.id}
|
||||
|
@ -139,7 +139,7 @@ const RHSChannelBoards = () => {
|
||||
<div className='rhs-boards-header'>
|
||||
<span className='linked-boards'>
|
||||
<FormattedMessage
|
||||
id='rhs-boards.linked-boards'
|
||||
id='rhs-boards.linked-boards2'
|
||||
defaultMessage='Linked boards'
|
||||
/>
|
||||
</span>
|
||||
|
@ -39,6 +39,7 @@ import '../../../webapp/src/styles/main.scss'
|
||||
import '../../../webapp/src/styles/labels.scss'
|
||||
import octoClient from '../../../webapp/src/octoClient'
|
||||
import {Constants} from '../../../webapp/src/constants'
|
||||
import {Board} from '../../../webapp/src/blocks/board'
|
||||
|
||||
import appBarIcon from '../../../webapp/static/app-bar-icon.png'
|
||||
|
||||
@ -66,7 +67,7 @@ import {PluginRegistry} from './types/mattermost-webapp'
|
||||
|
||||
import './plugin.scss'
|
||||
import CloudUpgradeNudge from "./components/cloudUpgradeNudge/cloudUpgradeNudge"
|
||||
import CreateBoardFromTemplate, {createBoardFromTemplateAction} from './components/createBoardFromTemplate'
|
||||
import CreateBoardFromTemplate from './components/createBoardFromTemplate'
|
||||
|
||||
function getSubpath(siteURL: string): string {
|
||||
const url = new URL(siteURL)
|
||||
@ -339,18 +340,18 @@ export default class Plugin {
|
||||
|
||||
if (this.registry.registerActionAfterChannelCreation) {
|
||||
this.registry.registerActionAfterChannelCreation((props: {
|
||||
setSelectedTemplate: (templateId: string) => void,
|
||||
toggleAddBoardCheck: (addBoard: boolean) => void,
|
||||
setCanCreate: (canCreate: boolean) => void,
|
||||
setAction: (fn: () => (channelId: string, teamId: string) => Promise<Board | undefined>) => void,
|
||||
newBoardInfoIcon: React.ReactNode,
|
||||
}) => (
|
||||
<ReduxProvider store={store}>
|
||||
<CreateBoardFromTemplate
|
||||
setSelectedTemplate={props.setSelectedTemplate}
|
||||
toggleAddBoardCheck={props.toggleAddBoardCheck}
|
||||
setCanCreate={props.setCanCreate}
|
||||
setAction={props.setAction}
|
||||
newBoardInfoIcon={props.newBoardInfoIcon}
|
||||
/>
|
||||
</ReduxProvider>
|
||||
), createBoardFromTemplateAction)
|
||||
))
|
||||
}
|
||||
|
||||
this.registry.registerPostWillRenderEmbedComponent(
|
||||
|
@ -20,7 +20,7 @@ export interface PluginRegistry {
|
||||
registerInsightsHandler(handler: (timeRange: string, page: number, perPage: number, teamId: string, insightType: string) => void)
|
||||
registerSiteStatisticsHandler(handler: () => void)
|
||||
|
||||
registerActionAfterChannelCreation(component: React.Element, action: any)
|
||||
registerActionAfterChannelCreation(component: React.Element)
|
||||
|
||||
// Add more if needed from https://developers.mattermost.com/extend/plugins/webapp/reference
|
||||
}
|
||||
|
@ -25,7 +25,6 @@ export const useGetAllTemplates = () => {
|
||||
|
||||
const unsortedTemplates = useAppSelector(getTemplates)
|
||||
const templates = useMemo(() => Object.values(unsortedTemplates).sort((a: Board, b: Board) => a.createAt - b.createAt), [unsortedTemplates])
|
||||
const allTemplates = globalTemplates.concat(templates)
|
||||
|
||||
return allTemplates
|
||||
return useMemo(() => globalTemplates.concat(templates), [globalTemplates])
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user