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:
Hyia丶 2021-10-04 15:58:59 +08:00 committed by GitHub
parent 1a59052f0c
commit ae8bf57160
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 120 additions and 10 deletions

View file

@ -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 || '',
},
}
}

View 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

View file

@ -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

View file

@ -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>

View file

@ -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 () => {

View file

@ -79,6 +79,10 @@
margin-right: 0;
}
}
> .menu-option.bold-menu-text {
font-weight: bold;
}
}
.menu-spacer {