1
0
mirror of https://github.com/mattermost/focalboard.git synced 2024-12-24 13:43:12 +02:00

Undomanager groups: error checks for nested calls

This commit is contained in:
Chen-I Lim 2020-10-29 09:22:35 -07:00
parent a427190926
commit 48a067ab15
3 changed files with 66 additions and 49 deletions

View File

@ -552,16 +552,16 @@ class BoardComponent extends React.Component<Props, State> {
Utils.assertValue(boardTree)
if (draggedCards.length > 0) {
mutator.beginUndoGroup()
const description = draggedCards.length > 1 ? `drag ${draggedCards.length} cards` : 'drag card'
for (const draggedCard of draggedCards) {
Utils.log(`ondrop. Card: ${draggedCard.title}, column: ${optionId}`)
const oldValue = draggedCard.properties[boardTree.groupByProperty.id]
if (optionId !== oldValue) {
await mutator.changePropertyValue(draggedCard, boardTree.groupByProperty.id, optionId, description)
await mutator.performAsUndoGroup(async () => {
const description = draggedCards.length > 1 ? `drag ${draggedCards.length} cards` : 'drag card'
for (const draggedCard of draggedCards) {
Utils.log(`ondrop. Card: ${draggedCard.title}, column: ${optionId}`)
const oldValue = draggedCard.properties[boardTree.groupByProperty.id]
if (optionId !== oldValue) {
await mutator.changePropertyValue(draggedCard, boardTree.groupByProperty.id, optionId, description)
}
}
}
mutator.endUndoGroup()
})
} else if (draggedHeaderOption) {
Utils.log(`ondrop. Header option: ${draggedHeaderOption.value}, column: ${option?.value}`)
Utils.assertValue(boardTree.groupByProperty)
@ -605,20 +605,18 @@ class BoardComponent extends React.Component<Props, State> {
}
cardOrder.splice(destIndex, 0, ...draggedCardIds)
mutator.beginUndoGroup()
// Update properties of dragged cards
for (const draggedCard of draggedCards) {
Utils.log(`draggedCard: ${draggedCard.title}, column: ${optionId}`)
const oldOptionId = draggedCard.properties[boardTree.groupByProperty.id]
if (optionId !== oldOptionId) {
await mutator.changePropertyValue(draggedCard, boardTree.groupByProperty.id, optionId, description)
await mutator.performAsUndoGroup(async () => {
// Update properties of dragged cards
for (const draggedCard of draggedCards) {
Utils.log(`draggedCard: ${draggedCard.title}, column: ${optionId}`)
const oldOptionId = draggedCard.properties[boardTree.groupByProperty.id]
if (optionId !== oldOptionId) {
await mutator.changePropertyValue(draggedCard, boardTree.groupByProperty.id, optionId, description)
}
}
}
await mutator.changeViewCardOrder(activeView, cardOrder, description)
mutator.endUndoGroup()
await mutator.changeViewCardOrder(activeView, cardOrder, description)
})
}
private async deleteSelectedCards() {
@ -627,12 +625,12 @@ class BoardComponent extends React.Component<Props, State> {
return
}
mutator.beginUndoGroup()
for (const cardId of selectedCardIds) {
const card = this.props.boardTree.allCards.find((o) => o.id === cardId)
mutator.deleteBlock(card, selectedCardIds.length > 1 ? `delete ${selectedCardIds.length} cards` : 'delete card')
}
mutator.endUndoGroup()
mutator.performAsUndoGroup(async () => {
for (const cardId of selectedCardIds) {
const card = this.props.boardTree.allCards.find((o) => o.id === cardId)
mutator.deleteBlock(card, selectedCardIds.length > 1 ? `delete ${selectedCardIds.length} cards` : 'delete card')
}
})
this.setState({selectedCardIds: []})
}

View File

@ -87,33 +87,33 @@ class ViewHeader extends React.Component<Props, State> {
const startCount = boardTree?.cards?.length
let optionIndex = 0
mutator.beginUndoGroup()
for (let i = 0; i < count; i++) {
const card = new MutableCard()
card.parentId = boardTree.board.id
card.properties = CardFilter.propertiesThatMeetFilterGroup(activeView.filter, board.cardProperties)
card.title = `Test Card ${startCount + i + 1}`
card.icon = BlockIcons.shared.randomIcon()
await mutator.performAsUndoGroup(async () => {
for (let i = 0; i < count; i++) {
const card = new MutableCard()
card.parentId = boardTree.board.id
card.properties = CardFilter.propertiesThatMeetFilterGroup(activeView.filter, board.cardProperties)
card.title = `Test Card ${startCount + i + 1}`
card.icon = BlockIcons.shared.randomIcon()
if (boardTree.groupByProperty && boardTree.groupByProperty.options.length > 0) {
// Cycle through options
const option = boardTree.groupByProperty.options[optionIndex]
optionIndex = (optionIndex + 1) % boardTree.groupByProperty.options.length
card.properties[boardTree.groupByProperty.id] = option.id
if (boardTree.groupByProperty && boardTree.groupByProperty.options.length > 0) {
// Cycle through options
const option = boardTree.groupByProperty.options[optionIndex]
optionIndex = (optionIndex + 1) % boardTree.groupByProperty.options.length
card.properties[boardTree.groupByProperty.id] = option.id
}
await mutator.insertBlock(card, 'test add card')
}
await mutator.insertBlock(card, 'test add card')
}
mutator.endUndoGroup()
})
}
private async testRandomizeIcons() {
const {boardTree} = this.props
mutator.beginUndoGroup()
for (const card of boardTree.cards) {
mutator.changeIcon(card, BlockIcons.shared.randomIcon(), 'randomize icon')
}
mutator.endUndoGroup()
await mutator.performAsUndoGroup(async () => {
for (const card of boardTree.cards) {
await mutator.changeIcon(card, BlockIcons.shared.randomIcon(), 'randomize icon')
}
})
}
render(): JSX.Element {

View File

@ -19,14 +19,33 @@ import {Utils} from './utils'
class Mutator {
private undoGroupId?: string
beginUndoGroup() {
private beginUndoGroup(): string {
if (this.undoGroupId) {
Utils.assertFailure('UndoManager does not support nested groups')
return
}
this.undoGroupId = Utils.createGuid()
return this.undoGroupId
}
endUndoGroup() {
private endUndoGroup(groupId: string) {
if (this.undoGroupId !== groupId) {
Utils.assertFailure('Mismatched groupId. UndoManager does not support nested groups')
return
}
this.undoGroupId = undefined
}
async performAsUndoGroup(actions: () => Promise<void>): Promise<void> {
const groupId = this.beginUndoGroup()
try {
await actions()
} catch(err) {
Utils.assertFailure(`ERROR: ${err?.toString?.()}`)
}
this.endUndoGroup(groupId)
}
async updateBlock(newBlock: IBlock, oldBlock: IBlock, description: string): Promise<void> {
await undoManager.perform(
async () => {