Create template from card
This commit is contained in:
parent
ca1c46dbab
commit
57d7eb35bd
9 changed files with 174 additions and 133 deletions
|
@ -9,7 +9,7 @@ interface Card extends IBlock {
|
|||
readonly icon: string
|
||||
readonly isTemplate: boolean
|
||||
readonly properties: Readonly<Record<string, string>>
|
||||
newCardFromTemplate(): MutableCard
|
||||
duplicate(): MutableCard
|
||||
}
|
||||
|
||||
class MutableCard extends MutableBlock {
|
||||
|
@ -41,11 +41,9 @@ class MutableCard extends MutableBlock {
|
|||
this.properties = {...(block.fields?.properties || {})}
|
||||
}
|
||||
|
||||
newCardFromTemplate(): MutableCard {
|
||||
duplicate(): MutableCard {
|
||||
const card = new MutableCard(this)
|
||||
card.id = Utils.createGuid()
|
||||
card.isTemplate = false
|
||||
card.title = ''
|
||||
return card
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ type Props = {
|
|||
|
||||
type State = {
|
||||
isSearching: boolean
|
||||
shownCard?: Card
|
||||
shownCardId?: string
|
||||
viewMenu: boolean
|
||||
selectedCardIds: string[]
|
||||
showFilter: boolean
|
||||
|
@ -131,12 +131,14 @@ class BoardComponent extends React.Component<Props, State> {
|
|||
this.backgroundClicked(e)
|
||||
}}
|
||||
>
|
||||
{this.state.shownCard &&
|
||||
{this.state.shownCardId &&
|
||||
<RootPortal>
|
||||
<CardDialog
|
||||
key={this.state.shownCardId}
|
||||
boardTree={boardTree}
|
||||
card={this.state.shownCard}
|
||||
onClose={() => this.setState({shownCard: undefined})}
|
||||
cardId={this.state.shownCardId}
|
||||
onClose={() => this.setState({shownCardId: undefined})}
|
||||
showCard={(cardId) => this.setState({shownCardId: cardId})}
|
||||
/>
|
||||
</RootPortal>}
|
||||
|
||||
|
@ -155,7 +157,6 @@ class BoardComponent extends React.Component<Props, State> {
|
|||
addCardFromTemplate={this.addCardFromTemplate}
|
||||
addCardTemplate={() => this.addCardTemplate()}
|
||||
editCardTemplate={this.editCardTemplate}
|
||||
deleteCardTemplate={this.deleteCardTemplate}
|
||||
withGroupBy={true}
|
||||
/>
|
||||
<div
|
||||
|
@ -479,21 +480,23 @@ class BoardComponent extends React.Component<Props, State> {
|
|||
}
|
||||
}
|
||||
|
||||
private addCardFromTemplate = async (cardTemplate?: Card) => {
|
||||
this.addCard(undefined, cardTemplate)
|
||||
private addCardFromTemplate = async (cardTemplateId?: string) => {
|
||||
this.addCard(undefined, cardTemplateId)
|
||||
}
|
||||
|
||||
private async addCard(groupByOptionId?: string, cardTemplate?: Card): Promise<void> {
|
||||
private async addCard(groupByOptionId?: string, cardTemplateId?: string): Promise<void> {
|
||||
const {boardTree} = this.props
|
||||
const {activeView, board} = boardTree
|
||||
|
||||
let card: MutableCard
|
||||
let blocksToInsert: IBlock[]
|
||||
if (cardTemplate) {
|
||||
const templateCardTree = new MutableCardTree(cardTemplate.id)
|
||||
if (cardTemplateId) {
|
||||
const templateCardTree = new MutableCardTree(cardTemplateId)
|
||||
await templateCardTree.sync()
|
||||
const newCardTree = templateCardTree.duplicateFromTemplate()
|
||||
const newCardTree = templateCardTree.templateCopy()
|
||||
card = newCardTree.card
|
||||
card.isTemplate = false
|
||||
card.title = ''
|
||||
blocksToInsert = [newCardTree.card, ...newCardTree.contents]
|
||||
} else {
|
||||
card = new MutableCard()
|
||||
|
@ -515,10 +518,10 @@ class BoardComponent extends React.Component<Props, State> {
|
|||
blocksToInsert,
|
||||
'add card',
|
||||
async () => {
|
||||
this.setState({shownCard: card})
|
||||
this.setState({shownCardId: card.id})
|
||||
},
|
||||
async () => {
|
||||
this.setState({shownCard: undefined})
|
||||
this.setState({shownCardId: undefined})
|
||||
},
|
||||
)
|
||||
}
|
||||
|
@ -539,18 +542,14 @@ class BoardComponent extends React.Component<Props, State> {
|
|||
}
|
||||
}
|
||||
await mutator.insertBlock(cardTemplate, 'add card template', async () => {
|
||||
this.setState({shownCard: cardTemplate})
|
||||
this.setState({shownCardId: cardTemplate.id})
|
||||
}, async () => {
|
||||
this.setState({shownCard: undefined})
|
||||
this.setState({shownCardId: undefined})
|
||||
})
|
||||
}
|
||||
|
||||
private editCardTemplate = (cardTemplate: Card) => {
|
||||
this.setState({shownCard: cardTemplate})
|
||||
}
|
||||
|
||||
private deleteCardTemplate = (cardTemplate: Card) => {
|
||||
mutator.deleteBlock(cardTemplate, 'delete card template')
|
||||
private editCardTemplate = (cardTemplateId: string) => {
|
||||
this.setState({shownCardId: cardTemplateId})
|
||||
}
|
||||
|
||||
private async propertyNameChanged(option: IPropertyOption, text: string): Promise<void> {
|
||||
|
@ -586,7 +585,7 @@ class BoardComponent extends React.Component<Props, State> {
|
|||
this.setState({selectedCardIds})
|
||||
}
|
||||
} else {
|
||||
this.setState({selectedCardIds: [], shownCard: card})
|
||||
this.setState({selectedCardIds: [], shownCardId: card.id})
|
||||
}
|
||||
|
||||
e.stopPropagation()
|
||||
|
|
|
@ -7,9 +7,8 @@ import {BlockIcons} from '../blockIcons'
|
|||
import {MutableTextBlock} from '../blocks/textBlock'
|
||||
import {BoardTree} from '../viewModel/boardTree'
|
||||
import {PropertyType} from '../blocks/board'
|
||||
import {CardTree, MutableCardTree} from '../viewModel/cardTree'
|
||||
import {CardTree} from '../viewModel/cardTree'
|
||||
import mutator from '../mutator'
|
||||
import {OctoListener} from '../octoListener'
|
||||
import {Utils} from '../utils'
|
||||
|
||||
import MenuWrapper from '../widgets/menuWrapper'
|
||||
|
@ -29,18 +28,16 @@ import './cardDetail.scss'
|
|||
|
||||
type Props = {
|
||||
boardTree: BoardTree
|
||||
cardId: string
|
||||
cardTree: CardTree
|
||||
intl: IntlShape
|
||||
}
|
||||
|
||||
type State = {
|
||||
cardTree?: CardTree
|
||||
title: string
|
||||
}
|
||||
|
||||
class CardDetail extends React.Component<Props, State> {
|
||||
private titleRef = React.createRef<Editable>()
|
||||
private cardListener?: OctoListener
|
||||
|
||||
shouldComponentUpdate() {
|
||||
return true
|
||||
|
@ -49,54 +46,12 @@ class CardDetail extends React.Component<Props, State> {
|
|||
constructor(props: Props) {
|
||||
super(props)
|
||||
this.state = {
|
||||
title: '',
|
||||
title: props.cardTree.card.title,
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.createCardTreeAndSync()
|
||||
}
|
||||
|
||||
private async createCardTreeAndSync() {
|
||||
const cardTree = new MutableCardTree(this.props.cardId)
|
||||
await cardTree.sync()
|
||||
this.createListener()
|
||||
this.setState({cardTree, title: cardTree.card.title})
|
||||
setTimeout(() => {
|
||||
if (this.titleRef.current) {
|
||||
this.titleRef.current.focus()
|
||||
}
|
||||
}, 0)
|
||||
}
|
||||
|
||||
private createListener() {
|
||||
this.cardListener = new OctoListener()
|
||||
this.cardListener.open(
|
||||
[this.props.cardId],
|
||||
async (blocks) => {
|
||||
Utils.log(`cardListener.onChanged: ${blocks.length}`)
|
||||
const newCardTree = this.state.cardTree.mutableCopy()
|
||||
if (newCardTree.incrementalUpdate(blocks)) {
|
||||
this.setState({cardTree: newCardTree, title: newCardTree.card.title})
|
||||
}
|
||||
},
|
||||
async () => {
|
||||
Utils.log('cardListener.onReconnect')
|
||||
const newCardTree = this.state.cardTree.mutableCopy()
|
||||
await newCardTree.sync()
|
||||
this.setState({cardTree: newCardTree, title: newCardTree.card.title})
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.cardListener?.close()
|
||||
this.cardListener = undefined
|
||||
}
|
||||
|
||||
render() {
|
||||
const {boardTree, intl} = this.props
|
||||
const {cardTree} = this.state
|
||||
const {boardTree, cardTree, intl} = this.props
|
||||
const {board} = boardTree
|
||||
if (!cardTree) {
|
||||
return null
|
||||
|
@ -128,7 +83,7 @@ class CardDetail extends React.Component<Props, State> {
|
|||
const block = new MutableTextBlock()
|
||||
block.parentId = card.id
|
||||
block.title = text
|
||||
block.order = (this.state.cardTree.contents.length + 1) * 1000
|
||||
block.order = (this.props.cardTree.contents.length + 1) * 1000
|
||||
mutator.insertBlock(block, 'add card text')
|
||||
}
|
||||
}}
|
||||
|
@ -170,11 +125,11 @@ class CardDetail extends React.Component<Props, State> {
|
|||
onChange={(title: string) => this.setState({title})}
|
||||
saveOnEsc={true}
|
||||
onSave={() => {
|
||||
if (this.state.title !== this.state.cardTree.card.title) {
|
||||
if (this.state.title !== this.props.cardTree.card.title) {
|
||||
mutator.changeTitle(card, this.state.title)
|
||||
}
|
||||
}}
|
||||
onCancel={() => this.setState({title: this.state.cardTree.card.title})}
|
||||
onCancel={() => this.setState({title: this.props.cardTree.card.title})}
|
||||
/>
|
||||
|
||||
{/* Property list */}
|
||||
|
@ -254,7 +209,7 @@ class CardDetail extends React.Component<Props, State> {
|
|||
onClick={() => {
|
||||
const block = new MutableTextBlock()
|
||||
block.parentId = card.id
|
||||
block.order = (this.state.cardTree.contents.length + 1) * 1000
|
||||
block.order = (this.props.cardTree.contents.length + 1) * 1000
|
||||
mutator.insertBlock(block, 'add text')
|
||||
}}
|
||||
/>
|
||||
|
@ -262,7 +217,7 @@ class CardDetail extends React.Component<Props, State> {
|
|||
id='image'
|
||||
name={intl.formatMessage({id: 'CardDetail.image', defaultMessage: 'Image'})}
|
||||
onClick={() => Utils.selectLocalFile(
|
||||
(file) => mutator.createImageBlock(card.id, file, (this.state.cardTree.contents.length + 1) * 1000),
|
||||
(file) => mutator.createImageBlock(card.id, file, (this.props.cardTree.contents.length + 1) * 1000),
|
||||
'.jpg,.jpeg,.png',
|
||||
)}
|
||||
/>
|
||||
|
|
|
@ -4,23 +4,79 @@ import React from 'react'
|
|||
|
||||
import {FormattedMessage} from 'react-intl'
|
||||
|
||||
import {Card} from '../blocks/card'
|
||||
import {BoardTree} from '../viewModel/boardTree'
|
||||
import mutator from '../mutator'
|
||||
import Menu from '../widgets/menu'
|
||||
import DeleteIcon from '../widgets/icons/delete'
|
||||
|
||||
import CardDetail from './cardDetail'
|
||||
import {MutableCardTree} from '../viewModel/cardTree'
|
||||
import {CardTree} from '../viewModel/cardTree'
|
||||
import {OctoListener} from '../octoListener'
|
||||
import {Utils} from '../utils'
|
||||
|
||||
import Dialog from './dialog'
|
||||
import CardDetail from './cardDetail'
|
||||
|
||||
type Props = {
|
||||
boardTree: BoardTree
|
||||
card: Card
|
||||
cardId: string
|
||||
onClose: () => void
|
||||
showCard: (cardId?: string) => void
|
||||
}
|
||||
|
||||
class CardDialog extends React.Component<Props> {
|
||||
type State = {
|
||||
cardTree?: CardTree
|
||||
}
|
||||
|
||||
class CardDialog extends React.Component<Props, State> {
|
||||
state: State = {}
|
||||
|
||||
private cardListener?: OctoListener
|
||||
|
||||
shouldComponentUpdate() {
|
||||
return true
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.createCardTreeAndSync()
|
||||
}
|
||||
|
||||
private async createCardTreeAndSync() {
|
||||
const cardTree = new MutableCardTree(this.props.cardId)
|
||||
await cardTree.sync()
|
||||
this.createListener()
|
||||
this.setState({cardTree})
|
||||
Utils.log(`cardDialog.createCardTreeAndSync: ${cardTree.card.id}`)
|
||||
}
|
||||
|
||||
private createListener() {
|
||||
this.cardListener = new OctoListener()
|
||||
this.cardListener.open(
|
||||
[this.props.cardId],
|
||||
async (blocks) => {
|
||||
Utils.log(`cardListener.onChanged: ${blocks.length}`)
|
||||
const newCardTree = this.state.cardTree.mutableCopy()
|
||||
if (newCardTree.incrementalUpdate(blocks)) {
|
||||
this.setState({cardTree: newCardTree})
|
||||
}
|
||||
},
|
||||
async () => {
|
||||
Utils.log('cardListener.onReconnect')
|
||||
const newCardTree = this.state.cardTree.mutableCopy()
|
||||
await newCardTree.sync()
|
||||
this.setState({cardTree: newCardTree})
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.cardListener?.close()
|
||||
this.cardListener = undefined
|
||||
}
|
||||
|
||||
render() {
|
||||
const {cardTree} = this.state
|
||||
|
||||
const menu = (
|
||||
<Menu position='left'>
|
||||
<Menu.Text
|
||||
|
@ -28,10 +84,22 @@ class CardDialog extends React.Component<Props> {
|
|||
icon={<DeleteIcon/>}
|
||||
name='Delete'
|
||||
onClick={async () => {
|
||||
await mutator.deleteBlock(this.props.card, 'delete card')
|
||||
const card = this.state.cardTree?.card
|
||||
if (!card) {
|
||||
Utils.assertFailure()
|
||||
return
|
||||
}
|
||||
await mutator.deleteBlock(card, 'delete card')
|
||||
this.props.onClose()
|
||||
}}
|
||||
/>
|
||||
{(cardTree && !cardTree.card.isTemplate) &&
|
||||
<Menu.Text
|
||||
id='makeTemplate'
|
||||
name='New template from card'
|
||||
onClick={this.makeTemplate}
|
||||
/>
|
||||
}
|
||||
</Menu>
|
||||
)
|
||||
return (
|
||||
|
@ -39,7 +107,7 @@ class CardDialog extends React.Component<Props> {
|
|||
onClose={this.props.onClose}
|
||||
toolsMenu={menu}
|
||||
>
|
||||
{(this.props.card.isTemplate) &&
|
||||
{(cardTree?.card.isTemplate) &&
|
||||
<div className='banner'>
|
||||
<FormattedMessage
|
||||
id='CardDialog.editing-template'
|
||||
|
@ -47,13 +115,41 @@ class CardDialog extends React.Component<Props> {
|
|||
/>
|
||||
</div>
|
||||
}
|
||||
<CardDetail
|
||||
boardTree={this.props.boardTree}
|
||||
cardId={this.props.card.id}
|
||||
/>
|
||||
{this.state.cardTree &&
|
||||
<CardDetail
|
||||
boardTree={this.props.boardTree}
|
||||
cardTree={this.state.cardTree}
|
||||
/>
|
||||
}
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
|
||||
private makeTemplate = async () => {
|
||||
const {cardTree} = this.state
|
||||
if (!cardTree) {
|
||||
Utils.assertFailure('this.state.cardTree')
|
||||
return
|
||||
}
|
||||
|
||||
const newCardTree = cardTree.templateCopy()
|
||||
newCardTree.card.isTemplate = true
|
||||
newCardTree.card.title = 'New Template'
|
||||
|
||||
Utils.log(`Created new template: ${newCardTree.card.id}`)
|
||||
|
||||
const blocksToInsert = [newCardTree.card, ...newCardTree.contents]
|
||||
await mutator.insertBlocks(
|
||||
blocksToInsert,
|
||||
'create template from card',
|
||||
async () => {
|
||||
this.props.showCard(newCardTree.card.id)
|
||||
},
|
||||
async () => {
|
||||
this.props.showCard(undefined)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export {CardDialog}
|
||||
|
|
|
@ -6,7 +6,7 @@ import {FormattedMessage} from 'react-intl'
|
|||
import {Constants} from '../constants'
|
||||
import {BlockIcons} from '../blockIcons'
|
||||
import {IPropertyTemplate} from '../blocks/board'
|
||||
import {Card, MutableCard} from '../blocks/card'
|
||||
import {MutableCard} from '../blocks/card'
|
||||
import {BoardTree} from '../viewModel/boardTree'
|
||||
import mutator from '../mutator'
|
||||
import {Utils} from '../utils'
|
||||
|
@ -36,7 +36,7 @@ type Props = {
|
|||
}
|
||||
|
||||
type State = {
|
||||
shownCard?: Card
|
||||
shownCardId?: string
|
||||
}
|
||||
|
||||
class TableComponent extends React.Component<Props, State> {
|
||||
|
@ -76,12 +76,14 @@ class TableComponent extends React.Component<Props, State> {
|
|||
|
||||
return (
|
||||
<div className='TableComponent octo-app'>
|
||||
{this.state.shownCard &&
|
||||
{this.state.shownCardId &&
|
||||
<RootPortal>
|
||||
<CardDialog
|
||||
key={this.state.shownCardId}
|
||||
boardTree={boardTree}
|
||||
card={this.state.shownCard}
|
||||
onClose={() => this.setState({shownCard: undefined})}
|
||||
cardId={this.state.shownCardId}
|
||||
onClose={() => this.setState({shownCardId: undefined})}
|
||||
showCard={(cardId) => this.setState({shownCardId: cardId})}
|
||||
/>
|
||||
</RootPortal>}
|
||||
<div className='octo-frame'>
|
||||
|
@ -99,7 +101,6 @@ class TableComponent extends React.Component<Props, State> {
|
|||
addCardFromTemplate={this.addCardFromTemplate}
|
||||
addCardTemplate={this.addCardTemplate}
|
||||
editCardTemplate={this.editCardTemplate}
|
||||
deleteCardTemplate={this.deleteCardTemplate}
|
||||
/>
|
||||
|
||||
{/* Main content */}
|
||||
|
@ -266,6 +267,9 @@ class TableComponent extends React.Component<Props, State> {
|
|||
}
|
||||
console.log('STILL WORKING')
|
||||
}}
|
||||
showCard={(cardId) => {
|
||||
this.setState({shownCardId: cardId})
|
||||
}}
|
||||
/>)
|
||||
|
||||
this.cardIdToRowMap.set(card.id, tableRowRef)
|
||||
|
@ -303,20 +307,22 @@ class TableComponent extends React.Component<Props, State> {
|
|||
this.addCard(true)
|
||||
}
|
||||
|
||||
private addCardFromTemplate = async (cardTemplate?: Card) => {
|
||||
this.addCard(true, cardTemplate)
|
||||
private addCardFromTemplate = async (cardTemplateId?: string) => {
|
||||
this.addCard(true, cardTemplateId)
|
||||
}
|
||||
|
||||
private addCard = async (show = false, cardTemplate?: Card) => {
|
||||
private addCard = async (show = false, cardTemplateId?: string) => {
|
||||
const {boardTree} = this.props
|
||||
|
||||
let card: MutableCard
|
||||
let blocksToInsert: IBlock[]
|
||||
if (cardTemplate) {
|
||||
const templateCardTree = new MutableCardTree(cardTemplate.id)
|
||||
if (cardTemplateId) {
|
||||
const templateCardTree = new MutableCardTree(cardTemplateId)
|
||||
await templateCardTree.sync()
|
||||
const newCardTree = templateCardTree.duplicateFromTemplate()
|
||||
const newCardTree = templateCardTree.templateCopy()
|
||||
card = newCardTree.card
|
||||
card.isTemplate = false
|
||||
card.title = ''
|
||||
blocksToInsert = [newCardTree.card, ...newCardTree.contents]
|
||||
} else {
|
||||
card = new MutableCard()
|
||||
|
@ -330,7 +336,7 @@ class TableComponent extends React.Component<Props, State> {
|
|||
'add card',
|
||||
async () => {
|
||||
if (show) {
|
||||
this.setState({shownCard: card})
|
||||
this.setState({shownCardId: card.id})
|
||||
} else {
|
||||
// Focus on this card's title inline on next render
|
||||
this.cardIdToFocusOnRender = card.id
|
||||
|
@ -350,17 +356,13 @@ class TableComponent extends React.Component<Props, State> {
|
|||
cardTemplate,
|
||||
'add card',
|
||||
async () => {
|
||||
this.setState({shownCard: cardTemplate})
|
||||
this.setState({shownCardId: cardTemplate.id})
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
private editCardTemplate = (cardTemplate: Card) => {
|
||||
this.setState({shownCard: cardTemplate})
|
||||
}
|
||||
|
||||
private deleteCardTemplate = (cardTemplate: Card) => {
|
||||
mutator.deleteBlock(cardTemplate, 'delete card template')
|
||||
private editCardTemplate = (cardTemplateId: string) => {
|
||||
this.setState({shownCardId: cardTemplateId})
|
||||
}
|
||||
|
||||
private async onDropToColumn(template: IPropertyTemplate) {
|
||||
|
|
|
@ -12,8 +12,6 @@ import Editable from '../widgets/editable'
|
|||
import Button from '../widgets/buttons/button'
|
||||
|
||||
import PropertyValueElement from './propertyValueElement'
|
||||
import {CardDialog} from './cardDialog'
|
||||
import RootPortal from './rootPortal'
|
||||
|
||||
import './tableRow.scss'
|
||||
|
||||
|
@ -22,10 +20,10 @@ type Props = {
|
|||
card: Card
|
||||
focusOnMount: boolean
|
||||
onSaveWithEnter: () => void
|
||||
showCard: (cardId: string) => void
|
||||
}
|
||||
|
||||
type State = {
|
||||
showCard: boolean
|
||||
title: string
|
||||
}
|
||||
|
||||
|
@ -34,7 +32,6 @@ class TableRow extends React.Component<Props, State> {
|
|||
constructor(props: Props) {
|
||||
super(props)
|
||||
this.state = {
|
||||
showCard: false,
|
||||
title: props.card.title,
|
||||
}
|
||||
}
|
||||
|
@ -84,21 +81,13 @@ class TableRow extends React.Component<Props, State> {
|
|||
</div>
|
||||
|
||||
<div className='open-button'>
|
||||
<Button onClick={() => this.setState({showCard: true})}>
|
||||
<Button onClick={() => this.props.showCard(this.props.card.id)}>
|
||||
<FormattedMessage
|
||||
id='TableRow.open'
|
||||
defaultMessage='Open'
|
||||
/>
|
||||
</Button>
|
||||
</div>
|
||||
{this.state.showCard &&
|
||||
<RootPortal>
|
||||
<CardDialog
|
||||
boardTree={boardTree}
|
||||
card={card}
|
||||
onClose={() => this.setState({showCard: false})}
|
||||
/>
|
||||
</RootPortal>}
|
||||
</div>
|
||||
|
||||
{/* Columns, one per property */}
|
||||
|
|
|
@ -6,7 +6,7 @@ import {injectIntl, IntlShape, FormattedMessage} from 'react-intl'
|
|||
import {Archiver} from '../archiver'
|
||||
import {ISortOption, MutableBoardView} from '../blocks/boardView'
|
||||
import {BlockIcons} from '../blockIcons'
|
||||
import {Card, MutableCard} from '../blocks/card'
|
||||
import {MutableCard} from '../blocks/card'
|
||||
import {IPropertyTemplate} from '../blocks/board'
|
||||
import {BoardTree} from '../viewModel/boardTree'
|
||||
import ViewMenu from '../components/viewMenu'
|
||||
|
@ -38,10 +38,9 @@ type Props = {
|
|||
showView: (id: string) => void
|
||||
setSearchText: (text: string) => void
|
||||
addCard: () => void
|
||||
addCardFromTemplate: (cardTemplate?: Card) => void
|
||||
addCardFromTemplate: (cardTemplateId?: string) => void
|
||||
addCardTemplate: () => void
|
||||
editCardTemplate: (cardTemplate: Card) => void
|
||||
deleteCardTemplate: (cardTemplate: Card) => void
|
||||
editCardTemplate: (cardTemplateId: string) => void
|
||||
withGroupBy?: boolean
|
||||
intl: IntlShape
|
||||
}
|
||||
|
@ -406,7 +405,7 @@ class ViewHeader extends React.Component<Props, State> {
|
|||
id={cardTemplate.id}
|
||||
name={cardTemplate.title || intl.formatMessage({id: 'ViewHeader.untitled', defaultMessage: 'Untitled'})}
|
||||
onClick={() => {
|
||||
this.props.addCardFromTemplate(cardTemplate)
|
||||
this.props.addCardFromTemplate(cardTemplate.id)
|
||||
}}
|
||||
rightIcon={
|
||||
<MenuWrapper stopPropagationOnToggle={true}>
|
||||
|
@ -416,15 +415,15 @@ class ViewHeader extends React.Component<Props, State> {
|
|||
id='edit'
|
||||
name={intl.formatMessage({id: 'ViewHeader.edit-template', defaultMessage: 'Edit'})}
|
||||
onClick={() => {
|
||||
this.props.editCardTemplate(cardTemplate)
|
||||
this.props.editCardTemplate(cardTemplate.id)
|
||||
}}
|
||||
/>
|
||||
<Menu.Text
|
||||
icon={<DeleteIcon/>}
|
||||
id='delete'
|
||||
name={intl.formatMessage({id: 'ViewHeader.delete-template', defaultMessage: 'Delete'})}
|
||||
onClick={() => {
|
||||
this.props.deleteCardTemplate(cardTemplate)
|
||||
onClick={async () => {
|
||||
await mutator.deleteBlock(cardTemplate, 'delete card template')
|
||||
}}
|
||||
/>
|
||||
</Menu>
|
||||
|
|
|
@ -13,6 +13,7 @@ interface CardTree {
|
|||
readonly contents: readonly IOrderedBlock[]
|
||||
|
||||
mutableCopy(): MutableCardTree
|
||||
templateCopy(): MutableCardTree
|
||||
}
|
||||
|
||||
class MutableCardTree implements CardTree {
|
||||
|
@ -57,8 +58,9 @@ class MutableCardTree implements CardTree {
|
|||
return cardTree
|
||||
}
|
||||
|
||||
duplicateFromTemplate(): MutableCardTree {
|
||||
const card = this.card.newCardFromTemplate()
|
||||
templateCopy(): MutableCardTree {
|
||||
const card = this.card.duplicate()
|
||||
|
||||
const contents: IOrderedBlock[] = this.contents.map((content) => {
|
||||
const copy = MutableBlock.duplicate(content)
|
||||
copy.parentId = card.id
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
flex-direction: row;
|
||||
align-items: center;
|
||||
|
||||
white-space: nowrap;
|
||||
font-weight: 400;
|
||||
padding: 2px 10px;
|
||||
cursor: pointer;
|
||||
|
|
Loading…
Reference in a new issue