-
Notifications
You must be signed in to change notification settings - Fork 9.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(editor): Add undo/redo support for canvas actions #4787
Merged
Merged
Changes from all commits
Commits
Show all changes
75 commits
Select commit
Hold shift + click to select a range
027e143
✨ Added history store and mixin
MiloradFilipovic 3a1aa22
Merge branch 'master' into feature/undo-redo
MiloradFilipovic fe7d27d
✨ Implemented node position change undo/redo
MiloradFilipovic ff352cd
✨ Implemented move nodes bulk command
MiloradFilipovic 6e9fbfb
⚡ Not clearing the redo stack after pushing the bulk command
MiloradFilipovic d17845b
Merge branch 'master' into feature/undo-redo
MiloradFilipovic ad1cfea
🔨 Implemented commands using classes
MiloradFilipovic 6b6ce4e
🔥 Removed unnecessary interfaces and actions
MiloradFilipovic 45bae25
🔥 Removing unused constants
MiloradFilipovic ddded3b
🔨 Refactoring classes file
MiloradFilipovic b0b35fa
⚡ Adding eventBus to command obects
MiloradFilipovic fda6e8f
Merge branch 'master' into feature/undo-redo
MiloradFilipovic 8ff1b63
✨ Added undo/redo support for adding and removing nodes
MiloradFilipovic 2f724da
Merge branch 'master' into feature/undo-redo
MiloradFilipovic 568be3f
✨ Implemented initial add/remove connections undo support
MiloradFilipovic b20f72e
⚡ Covering some corner cases with reconnecting nodes
MiloradFilipovic a73b875
⚡ Adding undo support for reconnecting nodes
MiloradFilipovic 35f732c
⚡ Fixing going back and forward between undo and redo
MiloradFilipovic 7c22278
Merge branch 'master' into feature/undo-redo
MiloradFilipovic 601a0d3
✨ Implemented async command revert
MiloradFilipovic cb003e2
⚡ Preventing push to undo if bulk redo/undo is in progress
MiloradFilipovic 316fb77
⚡ Handling re-connecting nodes and stopped pushing empty bulk actions…
MiloradFilipovic 22f71e2
✨ Handling adding a node between two connected nodes
MiloradFilipovic bb008f7
⚡ Handling the case of removing multiple connections on the same inde…
MiloradFilipovic 25827eb
⚡ Removing unnecessary timeouts, adding missing awaits, refactoring
MiloradFilipovic dc167da
Merge branch 'master' into feature/undo-redo
MiloradFilipovic 8abd54c
⚡ Resetting history when opening new workflow, fixing incorrect bulk …
MiloradFilipovic cc6444d
Merge branch 'master' into feature/undo-redo
MiloradFilipovic 87ff5f0
✔️ Fixing lint error
MiloradFilipovic 2137c21
⚡ Minor refactoring + some temporary debugging logs
MiloradFilipovic 5f211aa
Merge branch 'master' into feature/undo-redo
MiloradFilipovic f0dc35b
⚡ Preserving node properties when undoing it's removal, removing some…
MiloradFilipovic 3e6477a
Merge branch 'master' into feature/undo-redo
MiloradFilipovic 504107b
✨ Added undo/redo support for import workflow and node enable/disable
MiloradFilipovic 4ef36bd
🔥 Removing some unused constant
MiloradFilipovic fe17735
Merge branch 'master' into feature/undo-redo
MiloradFilipovic e28da7e
✨ Added undo/redo support for renaming nodes
MiloradFilipovic 253bb3b
⚡ Fixing rename history recording
MiloradFilipovic cb7bda2
Merge branch 'master' into feature/undo-redo
MiloradFilipovic 9e88a72
✨ Added undo/redo support for duplicating nodes
MiloradFilipovic 4a00b1c
Merge branch 'master' into feature/undo-redo
MiloradFilipovic 52970b3
📈 Implemented telemetry events
MiloradFilipovic e215654
🔨 A bit of refactoring
MiloradFilipovic f1907f2
⚡ Fixing edgecases in removing connection and moving nodes
MiloradFilipovic cd5edea
⚡ Handling case of adding duplicate nodes when going back and forward…
MiloradFilipovic 69313f1
Merge branch 'master' into feature/undo-redo
MiloradFilipovic d7720e1
⚡ Recording connections added directly to store
MiloradFilipovic c040209
⚡ Moving main history reset after wf is opened
MiloradFilipovic 20eb771
🔨 Simplifying rename recording
MiloradFilipovic 7030c21
Merge branch 'master' into feature/undo-redo
MiloradFilipovic 6c6054c
📈 Adding NDV telemetry event, updating existing event name case
MiloradFilipovic c44951a
📈 Updating telemetry events
MiloradFilipovic 791af5e
Merge branch 'master' into feature/undo-redo
MiloradFilipovic 47e013a
⚡ Fixing duplicate connections on undo/redo
MiloradFilipovic 1229ec7
⚡ Stopping undo events from firing constantly on keydown
MiloradFilipovic 7efe3e2
Merge branch 'master' into feature/undo-redo
MiloradFilipovic 48174f2
Merge branch 'master' into feature/undo-redo
MiloradFilipovic cd075f8
📈 Updated telemetry event for hitting undo in NDV
MiloradFilipovic 0e3760a
⚡ Adding undo support for disabling nodes using keyboard shortcuts
MiloradFilipovic 8f8bc57
⚡ Preventing adding duplicate connection commands to history
MiloradFilipovic 0f5a2d5
⚡ Clearing redo stack when new change is added
MiloradFilipovic f590c5c
⚡ Preventing adding connection actions to undo stack while redoing them
MiloradFilipovic 35d8ac3
👌 Addressing PR comments part 1
MiloradFilipovic a099612
👌 Moving undo logic for disabling nodes to `NodeView`
MiloradFilipovic b5a8468
👌 Implemented command comparing logic
MiloradFilipovic db98b94
⚡ Fix for not clearing redo stack on every user action
MiloradFilipovic f56d1bb
⚡ Fixing recording when moving nodes
MiloradFilipovic 34d25f2
⚡ Fixing undo for moving connections
MiloradFilipovic 68ac78c
Merge branch 'master' into feature/undo-redo
MiloradFilipovic 6ae8f07
⚡ Fixing tracking new nodes after latest merge
MiloradFilipovic a159929
⚡ Fixing broken bulk delete
MiloradFilipovic 7f3980f
Merge branch 'master' into feature/undo-redo
MiloradFilipovic 386c6f6
⚡ Preventing undo/redo when not on main node view tab
MiloradFilipovic e244fce
👌 Addressing PR comments
MiloradFilipovic 5e329e3
👌 Addressing PR comment
MiloradFilipovic File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
import { MAIN_HEADER_TABS } from './../constants'; | ||
import { useNDVStore } from '@/stores/ndv'; | ||
import { BulkCommand, Undoable } from '@/models/history'; | ||
import { useHistoryStore } from '@/stores/history'; | ||
import { useUIStore } from '@/stores/ui'; | ||
import { useWorkflowsStore } from '@/stores/workflows'; | ||
import { mapStores } from 'pinia'; | ||
import mixins from 'vue-typed-mixins'; | ||
import { Command } from '@/models/history'; | ||
import { debounceHelper } from '@/mixins/debounce'; | ||
import { deviceSupportHelpers } from '@/mixins/deviceSupportHelpers'; | ||
import Vue from 'vue'; | ||
import { getNodeViewTab } from '@/utils'; | ||
|
||
const UNDO_REDO_DEBOUNCE_INTERVAL = 100; | ||
|
||
export const historyHelper = mixins(debounceHelper, deviceSupportHelpers).extend({ | ||
computed: { | ||
...mapStores( | ||
useNDVStore, | ||
useHistoryStore, | ||
useUIStore, | ||
useWorkflowsStore, | ||
), | ||
isNDVOpen(): boolean { | ||
return this.ndvStore.activeNodeName !== null; | ||
}, | ||
}, | ||
mounted() { | ||
document.addEventListener('keydown', this.handleKeyDown); | ||
}, | ||
destroyed() { | ||
document.removeEventListener('keydown', this.handleKeyDown); | ||
}, | ||
methods: { | ||
handleKeyDown(event: KeyboardEvent) { | ||
const currentNodeViewTab = getNodeViewTab(this.$route); | ||
|
||
if (event.repeat || currentNodeViewTab !== MAIN_HEADER_TABS.WORKFLOW) return; | ||
if (this.isCtrlKeyPressed(event) && event.key === 'z') { | ||
event.preventDefault(); | ||
if (!this.isNDVOpen) { | ||
if (event.shiftKey) { | ||
this.callDebounced('redo', { debounceTime: UNDO_REDO_DEBOUNCE_INTERVAL, trailing: true }); | ||
} else { | ||
this.callDebounced('undo', { debounceTime: UNDO_REDO_DEBOUNCE_INTERVAL, trailing: true }); | ||
} | ||
} else if (!event.shiftKey) { | ||
this.trackUndoAttempt(event); | ||
} | ||
} | ||
}, | ||
async undo() { | ||
const command = this.historyStore.popUndoableToUndo(); | ||
if (!command) { | ||
return; | ||
} | ||
if (command instanceof BulkCommand) { | ||
this.historyStore.bulkInProgress = true; | ||
const commands = command.commands; | ||
const reverseCommands: Command[] = []; | ||
for (let i = commands.length - 1; i >= 0; i--) { | ||
await commands[i].revert(); | ||
reverseCommands.push(commands[i].getReverseCommand()); | ||
} | ||
this.historyStore.pushUndoableToRedo(new BulkCommand(reverseCommands)); | ||
await Vue.nextTick(); | ||
this.historyStore.bulkInProgress = false; | ||
} | ||
if (command instanceof Command) { | ||
await command.revert(); | ||
this.historyStore.pushUndoableToRedo(command.getReverseCommand()); | ||
this.uiStore.stateIsDirty = true; | ||
} | ||
this.trackCommand(command, 'undo'); | ||
}, | ||
async redo() { | ||
const command = this.historyStore.popUndoableToRedo(); | ||
if (!command) { | ||
return; | ||
} | ||
if (command instanceof BulkCommand) { | ||
this.historyStore.bulkInProgress = true; | ||
const commands = command.commands; | ||
const reverseCommands = []; | ||
for (let i = commands.length - 1; i >= 0; i--) { | ||
await commands[i].revert(); | ||
reverseCommands.push(commands[i].getReverseCommand()); | ||
} | ||
this.historyStore.pushBulkCommandToUndo(new BulkCommand(reverseCommands), false); | ||
await Vue.nextTick(); | ||
this.historyStore.bulkInProgress = false; | ||
} | ||
if (command instanceof Command) { | ||
await command.revert(); | ||
this.historyStore.pushCommandToUndo(command.getReverseCommand(), false); | ||
this.uiStore.stateIsDirty = true; | ||
} | ||
this.trackCommand(command, 'redo'); | ||
}, | ||
trackCommand(command: Undoable, type: 'undo'|'redo'): void { | ||
if (command instanceof Command) { | ||
this.$telemetry.track(`User hit ${type}`, { commands_length: 1, commands: [ command.name ] }); | ||
} else if (command instanceof BulkCommand) { | ||
this.$telemetry.track(`User hit ${type}`, { commands_length: command.commands.length, commands: command.commands.map(c => c.name) }); | ||
} | ||
}, | ||
trackUndoAttempt(event: KeyboardEvent) { | ||
if (this.isNDVOpen && !event.shiftKey) { | ||
const activeNode = this.ndvStore.activeNode; | ||
if (activeNode) { | ||
this.$telemetry.track(`User hit undo in NDV`, { node_type: activeNode.type }); | ||
} | ||
} | ||
}, | ||
}, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
weird we are not tracking the event itself
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Talked with Nik about it, looks like we are only interested in the fact that users attempted undo here.