From ae8bf57160a9b7b720f09f4290b1491dd30766c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hyia=E4=B8=B6?= Date: Mon, 4 Oct 2021 15:58:59 +0800 Subject: [PATCH] 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 --- webapp/src/blocks/boardView.ts | 2 + .../components/viewHeader/emptyCardButton.tsx | 57 +++++++++++++++++++ .../components/viewHeader/newCardButton.tsx | 19 ++++--- .../viewHeader/newCardButtonTemplateItem.tsx | 22 ++++++- webapp/src/mutator.ts | 26 +++++++++ webapp/src/widgets/menu/menu.scss | 4 ++ 6 files changed, 120 insertions(+), 10 deletions(-) create mode 100644 webapp/src/components/viewHeader/emptyCardButton.tsx diff --git a/webapp/src/blocks/boardView.ts b/webapp/src/blocks/boardView.ts index 4db0a5440..3cf76b46d 100644 --- a/webapp/src/blocks/boardView.ts +++ b/webapp/src/blocks/boardView.ts @@ -21,6 +21,7 @@ type BoardViewFields = { cardOrder: string[] columnWidths: Record columnCalculations: Record + 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 || '', }, } } diff --git a/webapp/src/components/viewHeader/emptyCardButton.tsx b/webapp/src/components/viewHeader/emptyCardButton.tsx new file mode 100644 index 000000000..b58221881 --- /dev/null +++ b/webapp/src/components/viewHeader/emptyCardButton.tsx @@ -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 ( + } + id='empty-template' + name={intl.formatMessage({id: 'ViewHeader.empty-card', defaultMessage: 'Empty card'})} + className={currentView.fields.defaultTemplateId ? '' : 'bold-menu-text'} + onClick={() => { + props.addCard() + }} + rightIcon={ + + }/> + + } + id='default' + name={intl.formatMessage({ + id: 'ViewHeader.set-default-template', + defaultMessage: 'Set as default', + })} + onClick={async () => { + await mutator.clearDefaultTemplate(currentView.id, currentView.fields.defaultTemplateId) + }} + /> + + + } + />) +}) + +export default EmptyCardButton diff --git a/webapp/src/components/viewHeader/newCardButton.tsx b/webapp/src/components/viewHeader/newCardButton.tsx index 2365c4bf5..8f4ddf802 100644 --- a/webapp/src/components/viewHeader/newCardButton.tsx +++ b/webapp/src/components/viewHeader/newCardButton.tsx @@ -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 ( { - props.addCard() + if (currentView.fields.defaultTemplateId) { + props.addCardFromTemplate(currentView.fields.defaultTemplateId) + } else { + props.addCard() + } }} text={( { /> ))} - } - id='empty-template' - name={intl.formatMessage({id: 'ViewHeader.empty-card', defaultMessage: 'Empty card'})} - onClick={() => { - props.addCard() - }} + { + 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 ( {cardTemplate.fields.icon}} + className={isDefaultTemplate ? 'bold-menu-text' : ''} onClick={() => { props.addCardFromTemplate(cardTemplate.id) }} @@ -36,6 +43,14 @@ const NewCardButtonTemplateItem = React.memo((props: Props) => { }/> + } + 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) + }} + /> } 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') + }) }} /> diff --git a/webapp/src/mutator.ts b/webapp/src/mutator.ts index 67be4add4..8aa5b70d8 100644 --- a/webapp/src/mutator.ts +++ b/webapp/src/mutator.ts @@ -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 () => { diff --git a/webapp/src/widgets/menu/menu.scss b/webapp/src/widgets/menu/menu.scss index 0ecab4470..8498efcd0 100644 --- a/webapp/src/widgets/menu/menu.scss +++ b/webapp/src/widgets/menu/menu.scss @@ -79,6 +79,10 @@ margin-right: 0; } } + + > .menu-option.bold-menu-text { + font-weight: bold; + } } .menu-spacer {