focalboard/webapp/src/components/viewMenu.tsx

188 lines
6.3 KiB
TypeScript
Raw Normal View History

2020-10-20 21:50:53 +02:00
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
2020-10-20 21:52:56 +02:00
import React from 'react'
2020-11-12 22:24:17 +01:00
import {injectIntl, IntlShape} from 'react-intl'
2020-10-20 21:52:56 +02:00
import {Board} from '../blocks/board'
2020-12-10 20:00:34 +01:00
import {IViewType, MutableBoardView} from '../blocks/boardView'
2020-11-13 03:48:59 +01:00
import {Constants} from '../constants'
2020-10-20 21:52:56 +02:00
import mutator from '../mutator'
import {Utils} from '../utils'
2020-11-13 03:48:59 +01:00
import {BoardTree} from '../viewModel/boardTree'
2020-12-11 21:01:11 +01:00
import AddIcon from '../widgets/icons/add'
2020-12-10 20:00:34 +01:00
import BoardIcon from '../widgets/icons/board'
2020-12-11 21:01:11 +01:00
import DeleteIcon from '../widgets/icons/delete'
2021-01-04 22:36:16 +01:00
import DuplicateIcon from '../widgets/icons/duplicate'
2020-12-10 20:00:34 +01:00
import TableIcon from '../widgets/icons/table'
2020-10-20 21:52:56 +02:00
import Menu from '../widgets/menu'
type Props = {
boardTree: BoardTree
2020-10-20 21:50:53 +02:00
board: Board,
showView: (id: string) => void
2020-11-12 22:24:17 +01:00
intl: IntlShape
2020-12-17 21:02:12 +01:00
readonly: boolean
}
2020-10-14 21:39:34 +02:00
2020-11-12 23:55:55 +01:00
export class ViewMenu extends React.PureComponent<Props> {
2021-01-04 22:36:16 +01:00
private handleDuplicateView = async () => {
const {boardTree, showView} = this.props
Utils.log('duplicateView')
const currentViewId = boardTree.activeView.id
const newView = boardTree.activeView.duplicate()
newView.title = `${boardTree.activeView.title} copy`
2021-01-04 22:36:16 +01:00
await mutator.insertBlock(
newView,
'duplicate view',
async () => {
// This delay is needed because OctoListener has a default 100 ms notification delay before updates
setTimeout(() => {
showView(newView.id)
}, 120)
},
async () => {
showView(currentViewId)
},
)
}
2020-11-12 23:55:55 +01:00
private handleDeleteView = async () => {
2020-10-22 01:17:31 +02:00
const {boardTree, showView} = this.props
2020-10-20 21:50:53 +02:00
Utils.log('deleteView')
const view = boardTree.activeView
const nextView = boardTree.views.find((o) => o !== view)
2020-10-20 21:50:53 +02:00
await mutator.deleteBlock(view, 'delete view')
2020-11-12 23:06:02 +01:00
if (nextView) {
showView(nextView.id)
}
2020-10-20 21:50:53 +02:00
}
2020-11-12 23:55:55 +01:00
private handleViewClick = (id: string) => {
2020-10-20 21:50:53 +02:00
const {boardTree, showView} = this.props
Utils.log('view ' + id)
const view = boardTree.views.find((o) => o.id === id)
2020-11-12 23:06:02 +01:00
Utils.assert(view, `view not found: ${id}`)
if (view) {
showView(view.id)
}
2020-10-20 21:50:53 +02:00
}
2020-11-12 23:55:55 +01:00
private handleAddViewBoard = async () => {
2020-11-12 22:24:17 +01:00
const {board, boardTree, showView, intl} = this.props
2020-10-20 21:50:53 +02:00
Utils.log('addview-board')
const view = new MutableBoardView()
2020-12-11 20:10:25 +01:00
view.title = intl.formatMessage({id: 'View.NewBoardTitle', defaultMessage: 'Board view'})
2020-10-20 21:52:56 +02:00
view.viewType = 'board'
2020-10-20 21:50:53 +02:00
view.parentId = board.id
view.rootId = board.rootId
2020-10-20 21:50:53 +02:00
const oldViewId = boardTree.activeView.id
2020-10-20 21:50:53 +02:00
await mutator.insertBlock(
view,
'add view',
async () => {
// This delay is needed because OctoListener has a default 100 ms notification delay before updates
setTimeout(() => {
showView(view.id)
}, 120)
2020-10-20 21:50:53 +02:00
},
async () => {
2020-10-20 21:50:53 +02:00
showView(oldViewId)
2020-10-20 21:52:56 +02:00
})
2020-10-20 21:50:53 +02:00
}
2020-11-12 23:55:55 +01:00
private handleAddViewTable = async () => {
2020-11-12 22:24:17 +01:00
const {board, boardTree, showView, intl} = this.props
Utils.log('addview-table')
const view = new MutableBoardView()
2020-12-11 20:10:25 +01:00
view.title = intl.formatMessage({id: 'View.NewTableTitle', defaultMessage: 'Table view'})
view.viewType = 'table'
view.parentId = board.id
view.rootId = board.rootId
2020-10-20 21:50:53 +02:00
view.visiblePropertyIds = board.cardProperties.map((o) => o.id)
2020-11-03 00:47:45 +01:00
view.columnWidths = {}
view.columnWidths[Constants.titleColumnId] = Constants.defaultTitleColumnWidth
const oldViewId = boardTree.activeView.id
2020-10-20 21:50:53 +02:00
await mutator.insertBlock(
view,
'add view',
async () => {
// This delay is needed because OctoListener has a default 100 ms notification delay before updates
setTimeout(() => {
Utils.log(`showView: ${view.id}`)
showView(view.id)
}, 120)
2020-10-20 21:50:53 +02:00
},
async () => {
showView(oldViewId)
2020-10-20 21:52:56 +02:00
})
2020-10-20 21:50:53 +02:00
}
2020-11-12 23:55:55 +01:00
render(): JSX.Element {
const {boardTree} = this.props
2020-10-20 21:50:53 +02:00
return (
<Menu>
2020-10-22 01:17:31 +02:00
{boardTree.views.map((view) => (
<Menu.Text
key={view.id}
id={view.id}
name={view.title}
2020-12-10 20:00:34 +01:00
icon={this.iconForViewType(view.viewType)}
2020-10-22 01:17:31 +02:00
onClick={this.handleViewClick}
/>))}
2020-10-20 21:50:53 +02:00
<Menu.Separator/>
2021-01-04 22:36:16 +01:00
{!this.props.readonly &&
<Menu.Text
id='__duplicateView'
name='Duplicate View'
icon={<DuplicateIcon/>}
onClick={this.handleDuplicateView}
/>
}
2020-12-17 21:02:12 +01:00
{!this.props.readonly && boardTree.views.length > 1 &&
2020-11-12 23:55:55 +01:00
<Menu.Text
id='__deleteView'
name='Delete View'
2020-12-11 21:01:11 +01:00
icon={<DeleteIcon/>}
2020-11-12 23:55:55 +01:00
onClick={this.handleDeleteView}
2020-10-20 21:50:53 +02:00
/>
2020-12-17 21:02:12 +01:00
}
{!this.props.readonly &&
<Menu.SubMenu
id='__addView'
name='Add View'
icon={<AddIcon/>}
>
<Menu.Text
id='board'
name='Board'
icon={<BoardIcon/>}
onClick={this.handleAddViewBoard}
/>
<Menu.Text
id='table'
name='Table'
icon={<TableIcon/>}
onClick={this.handleAddViewTable}
/>
</Menu.SubMenu>
}
2020-10-20 21:50:53 +02:00
</Menu>
)
}
2020-12-10 20:00:34 +01:00
private iconForViewType(viewType: IViewType) {
switch (viewType) {
case 'board': return <BoardIcon/>
case 'table': return <TableIcon/>
default: return <div/>
}
}
}
2020-11-12 22:24:17 +01:00
export default injectIntl(ViewMenu)