Update default template (#516)
* Update default template * Update default template display * Add default template clear behavior * Fix merged code * remove important from css * Update mutator Co-authored-by: qingyang.zhong <qizhong@coupang.com>
This commit is contained in:
parent
1a59052f0c
commit
ae8bf57160
6 changed files with 120 additions and 10 deletions
|
@ -21,6 +21,7 @@ type BoardViewFields = {
|
|||
cardOrder: string[]
|
||||
columnWidths: Record<string, number>
|
||||
columnCalculations: Record<string, string>
|
||||
defaultTemplateId: string
|
||||
}
|
||||
|
||||
type BoardView = Block & {
|
||||
|
@ -44,6 +45,7 @@ function createBoardView(block?: Block): BoardView {
|
|||
cardOrder: block?.fields.cardOrder?.slice() || [],
|
||||
columnWidths: {...(block?.fields.columnWidths || {})},
|
||||
columnCalculations: {...(block?.fields.columnCalculations) || {}},
|
||||
defaultTemplateId: block?.fields.defaultTemplateId || '',
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
57
webapp/src/components/viewHeader/emptyCardButton.tsx
Normal file
57
webapp/src/components/viewHeader/emptyCardButton.tsx
Normal file
|
@ -0,0 +1,57 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import React from 'react'
|
||||
|
||||
import {useIntl} from 'react-intl'
|
||||
|
||||
import CardIcon from '../../widgets/icons/card'
|
||||
import Menu from '../../widgets/menu'
|
||||
|
||||
import MenuWrapper from '../../widgets/menuWrapper'
|
||||
import OptionsIcon from '../../widgets/icons/options'
|
||||
import IconButton from '../../widgets/buttons/iconButton'
|
||||
import CheckIcon from '../../widgets/icons/check'
|
||||
import mutator from '../../mutator'
|
||||
import {useAppSelector} from '../../store/hooks'
|
||||
import {getCurrentView} from '../../store/views'
|
||||
|
||||
type Props = {
|
||||
addCard: () => void
|
||||
}
|
||||
|
||||
const EmptyCardButton = React.memo((props: Props) => {
|
||||
const currentView = useAppSelector(getCurrentView)
|
||||
const intl = useIntl()
|
||||
|
||||
return (
|
||||
<Menu.Text
|
||||
icon={<CardIcon/>}
|
||||
id='empty-template'
|
||||
name={intl.formatMessage({id: 'ViewHeader.empty-card', defaultMessage: 'Empty card'})}
|
||||
className={currentView.fields.defaultTemplateId ? '' : 'bold-menu-text'}
|
||||
onClick={() => {
|
||||
props.addCard()
|
||||
}}
|
||||
rightIcon={
|
||||
<MenuWrapper stopPropagationOnToggle={true}>
|
||||
<IconButton icon={<OptionsIcon/>}/>
|
||||
<Menu position='left'>
|
||||
<Menu.Text
|
||||
icon={<CheckIcon/>}
|
||||
id='default'
|
||||
name={intl.formatMessage({
|
||||
id: 'ViewHeader.set-default-template',
|
||||
defaultMessage: 'Set as default',
|
||||
})}
|
||||
onClick={async () => {
|
||||
await mutator.clearDefaultTemplate(currentView.id, currentView.fields.defaultTemplateId)
|
||||
}}
|
||||
/>
|
||||
</Menu>
|
||||
</MenuWrapper>
|
||||
}
|
||||
/>)
|
||||
})
|
||||
|
||||
export default EmptyCardButton
|
|
@ -6,13 +6,14 @@ import {FormattedMessage, useIntl} from 'react-intl'
|
|||
|
||||
import {Card} from '../../blocks/card'
|
||||
import ButtonWithMenu from '../../widgets/buttons/buttonWithMenu'
|
||||
import CardIcon from '../../widgets/icons/card'
|
||||
import AddIcon from '../../widgets/icons/add'
|
||||
import Menu from '../../widgets/menu'
|
||||
import {useAppSelector} from '../../store/hooks'
|
||||
import {getCurrentBoardTemplates} from '../../store/cards'
|
||||
import {getCurrentView} from '../../store/views'
|
||||
|
||||
import NewCardButtonTemplateItem from './newCardButtonTemplateItem'
|
||||
import EmptyCardButton from './emptyCardButton'
|
||||
|
||||
type Props = {
|
||||
addCard: () => void
|
||||
|
@ -23,12 +24,17 @@ type Props = {
|
|||
|
||||
const NewCardButton = React.memo((props: Props): JSX.Element => {
|
||||
const cardTemplates: Card[] = useAppSelector(getCurrentBoardTemplates)
|
||||
const currentView = useAppSelector(getCurrentView)
|
||||
const intl = useIntl()
|
||||
|
||||
return (
|
||||
<ButtonWithMenu
|
||||
onClick={() => {
|
||||
props.addCard()
|
||||
if (currentView.fields.defaultTemplateId) {
|
||||
props.addCardFromTemplate(currentView.fields.defaultTemplateId)
|
||||
} else {
|
||||
props.addCard()
|
||||
}
|
||||
}}
|
||||
text={(
|
||||
<FormattedMessage
|
||||
|
@ -60,13 +66,8 @@ const NewCardButton = React.memo((props: Props): JSX.Element => {
|
|||
/>
|
||||
))}
|
||||
|
||||
<Menu.Text
|
||||
icon={<CardIcon/>}
|
||||
id='empty-template'
|
||||
name={intl.formatMessage({id: 'ViewHeader.empty-card', defaultMessage: 'Empty card'})}
|
||||
onClick={() => {
|
||||
props.addCard()
|
||||
}}
|
||||
<EmptyCardButton
|
||||
addCard={props.addCard}
|
||||
/>
|
||||
|
||||
<Menu.Text
|
||||
|
|
|
@ -12,6 +12,9 @@ import EditIcon from '../../widgets/icons/edit'
|
|||
import OptionsIcon from '../../widgets/icons/options'
|
||||
import Menu from '../../widgets/menu'
|
||||
import MenuWrapper from '../../widgets/menuWrapper'
|
||||
import CheckIcon from '../../widgets/icons/check'
|
||||
import {useAppSelector} from '../../store/hooks'
|
||||
import {getCurrentView} from '../../store/views'
|
||||
|
||||
type Props = {
|
||||
cardTemplate: Card
|
||||
|
@ -20,15 +23,19 @@ type Props = {
|
|||
}
|
||||
|
||||
const NewCardButtonTemplateItem = React.memo((props: Props) => {
|
||||
const currentView = useAppSelector(getCurrentView)
|
||||
const {cardTemplate} = props
|
||||
const intl = useIntl()
|
||||
const displayName = cardTemplate.title || intl.formatMessage({id: 'ViewHeader.untitled', defaultMessage: 'Untitled'})
|
||||
const isDefaultTemplate = currentView.fields.defaultTemplateId === cardTemplate.id
|
||||
|
||||
return (
|
||||
<Menu.Text
|
||||
key={cardTemplate.id}
|
||||
id={cardTemplate.id}
|
||||
name={displayName}
|
||||
icon={<div className='Icon'>{cardTemplate.fields.icon}</div>}
|
||||
className={isDefaultTemplate ? 'bold-menu-text' : ''}
|
||||
onClick={() => {
|
||||
props.addCardFromTemplate(cardTemplate.id)
|
||||
}}
|
||||
|
@ -36,6 +43,14 @@ const NewCardButtonTemplateItem = React.memo((props: Props) => {
|
|||
<MenuWrapper stopPropagationOnToggle={true}>
|
||||
<IconButton icon={<OptionsIcon/>}/>
|
||||
<Menu position='left'>
|
||||
<Menu.Text
|
||||
icon={<CheckIcon/>}
|
||||
id='default'
|
||||
name={intl.formatMessage({id: 'ViewHeader.set-default-template', defaultMessage: 'Set as default'})}
|
||||
onClick={async () => {
|
||||
await mutator.setDefaultTemplate(currentView.id, currentView.fields.defaultTemplateId, cardTemplate.id)
|
||||
}}
|
||||
/>
|
||||
<Menu.Text
|
||||
icon={<EditIcon/>}
|
||||
id='edit'
|
||||
|
@ -49,7 +64,12 @@ const NewCardButtonTemplateItem = React.memo((props: Props) => {
|
|||
id='delete'
|
||||
name={intl.formatMessage({id: 'ViewHeader.delete-template', defaultMessage: 'Delete'})}
|
||||
onClick={async () => {
|
||||
await mutator.deleteBlock(cardTemplate, 'delete card template')
|
||||
await mutator.performAsUndoGroup(async () => {
|
||||
if (currentView.fields.defaultTemplateId === cardTemplate.id) {
|
||||
await mutator.clearDefaultTemplate(currentView.id, currentView.fields.defaultTemplateId)
|
||||
}
|
||||
await mutator.deleteBlock(cardTemplate, 'delete card template')
|
||||
})
|
||||
}}
|
||||
/>
|
||||
</Menu>
|
||||
|
|
|
@ -139,6 +139,32 @@ class Mutator {
|
|||
)
|
||||
}
|
||||
|
||||
async setDefaultTemplate(blockId: string, oldTemplateId: string, templateId: string, description = 'set default template') {
|
||||
await undoManager.perform(
|
||||
async () => {
|
||||
await octoClient.patchBlock(blockId, {updatedFields: {defaultTemplateId: templateId}})
|
||||
},
|
||||
async () => {
|
||||
await octoClient.patchBlock(blockId, {updatedFields: {defaultTemplateId: oldTemplateId}})
|
||||
},
|
||||
description,
|
||||
this.undoGroupId,
|
||||
)
|
||||
}
|
||||
|
||||
async clearDefaultTemplate(blockId: string, oldTemplateId: string, description = 'set default template') {
|
||||
await undoManager.perform(
|
||||
async () => {
|
||||
await octoClient.patchBlock(blockId, {updatedFields: {defaultTemplateId: ''}})
|
||||
},
|
||||
async () => {
|
||||
await octoClient.patchBlock(blockId, {updatedFields: {defaultTemplateId: oldTemplateId}})
|
||||
},
|
||||
description,
|
||||
this.undoGroupId,
|
||||
)
|
||||
}
|
||||
|
||||
async changeIcon(blockId: string, oldIcon: string|undefined, icon: string, description = 'change icon') {
|
||||
await undoManager.perform(
|
||||
async () => {
|
||||
|
|
|
@ -79,6 +79,10 @@
|
|||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
> .menu-option.bold-menu-text {
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
.menu-spacer {
|
||||
|
|
Loading…
Reference in a new issue