1
0
mirror of https://github.com/mattermost/focalboard.git synced 2024-11-24 08:22:29 +02:00

Undo grouping

This commit is contained in:
Chen-I Lim 2020-10-28 13:57:53 -07:00
parent 25a1ebeda4
commit b7ea5e677b
4 changed files with 54 additions and 10 deletions

View File

@ -545,6 +545,7 @@ class BoardComponent extends React.Component<Props, State> {
Utils.assertValue(boardTree)
if (draggedCards.length > 0) {
mutator.beginUndoGroup()
for (const draggedCard of draggedCards) {
Utils.log(`ondrop. Card: ${draggedCard.title}, column: ${optionId}`)
const oldValue = draggedCard.properties[boardTree.groupByProperty.id]
@ -552,6 +553,7 @@ class BoardComponent extends React.Component<Props, State> {
await mutator.changePropertyValue(draggedCard, boardTree.groupByProperty.id, optionId, 'drag card')
}
}
mutator.endUndoGroup()
} else if (draggedHeaderOption) {
Utils.log(`ondrop. Header option: ${draggedHeaderOption.value}, column: ${option?.value}`)
Utils.assertValue(boardTree.groupByProperty)
@ -573,13 +575,15 @@ class BoardComponent extends React.Component<Props, State> {
Utils.log(`onDropToCard: ${card.title}`)
const {boardTree} = this.props
const {activeView} = boardTree
const {draggedCards, draggedHeaderOption} = this
const {draggedCards} = this
const optionId = card.properties[activeView.groupById]
if (draggedCards.length < 1) {
return
}
mutator.beginUndoGroup()
const cardOrder = boardTree.orderedCards().map((o) => o.id)
for (const draggedCard of draggedCards) {
if (draggedCard.id === card.id) {
@ -604,6 +608,7 @@ class BoardComponent extends React.Component<Props, State> {
}
await mutator.changeViewCardOrder(activeView, cardOrder)
mutator.endUndoGroup()
}
}

View File

@ -87,28 +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()
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
card.title = `Test Card ${startCount + i + 1}`
card.icon = BlockIcons.shared.randomIcon()
}
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()
}
render(): JSX.Element {

View File

@ -17,6 +17,16 @@ import {Utils} from './utils'
// It also ensures that the Undo-manager is called for each action
//
class Mutator {
private undoGroupId?: string
beginUndoGroup() {
this.undoGroupId = Utils.createGuid()
}
endUndoGroup() {
this.undoGroupId = undefined
}
async updateBlock(newBlock: IBlock, oldBlock: IBlock, description: string): Promise<void> {
await undoManager.perform(
async () => {
@ -26,6 +36,7 @@ class Mutator {
await octoClient.updateBlock(oldBlock)
},
description,
this.undoGroupId
)
}
@ -38,6 +49,7 @@ class Mutator {
await octoClient.updateBlocks(oldBlocks)
},
description,
this.undoGroupId
)
}
@ -52,6 +64,7 @@ class Mutator {
await octoClient.deleteBlock(block.id)
},
description,
this.undoGroupId
)
}
@ -68,6 +81,7 @@ class Mutator {
}
},
description,
this.undoGroupId
)
}
@ -86,6 +100,7 @@ class Mutator {
await afterUndo?.()
},
description,
this.undoGroupId
)
}
@ -457,6 +472,7 @@ class Mutator {
await octoClient.deleteBlock(block.id)
},
'add image',
this.undoGroupId
)
return block

View File

@ -5,6 +5,7 @@ interface UndoCommand {
undo: () => Promise<void>
redo: () => Promise<void>
description?: string
groupId?: string
}
//
@ -59,10 +60,11 @@ class UndoManager {
redo: () => Promise<void>,
undo: () => Promise<void>,
description?: string,
groupId?: string,
isDiscardable = false,
): Promise<UndoManager> {
await redo()
return this.registerUndo({undo, redo}, description, isDiscardable)
return this.registerUndo({undo, redo}, description, groupId, isDiscardable)
}
registerUndo(
@ -71,6 +73,7 @@ class UndoManager {
redo: () => Promise<void>
},
description?: string,
groupId?: string,
isDiscardable = false,
): UndoManager {
if (this.isExecuting) {
@ -93,6 +96,7 @@ class UndoManager {
undo: command.undo,
redo: command.redo,
description,
groupId,
}
this.commands.push(internalCommand)
@ -115,13 +119,20 @@ class UndoManager {
}
async undo() {
const command = this.commands[this.index]
if (this.isExecuting) {
return this
}
let command = this.commands[this.index]
if (!command) {
return this
}
await this.execute(command, 'undo')
this.index -= 1
const currentGroupId = command.groupId
do {
await this.execute(command, 'undo')
this.index -= 1
command = this.commands[this.index]
} while (this.index >= 0 && currentGroupId && currentGroupId === command.groupId)
if (this.onStateDidChange) {
this.onStateDidChange()
@ -131,13 +142,20 @@ class UndoManager {
}
async redo() {
const command = this.commands[this.index + 1]
if (this.isExecuting) {
return this
}
let command = this.commands[this.index + 1]
if (!command) {
return this
}
await this.execute(command, 'redo')
this.index += 1
const currentGroupId = command.groupId
do {
await this.execute(command, 'redo')
this.index += 1
command = this.commands[this.index + 1]
} while (this.index < this.commands.length && currentGroupId && currentGroupId === command.groupId)
if (this.onStateDidChange) {
this.onStateDidChange()