feat(editor): Add undo/redo when moving nodes in new canvas (no-changelog) (#10137)

This commit is contained in:
Alex Grozav
2024-07-23 10:16:56 +03:00
committed by GitHub
parent aa15d22499
commit 278edd6010
6 changed files with 126 additions and 24 deletions

View File

@@ -190,6 +190,60 @@ describe('useCanvasOperations', () => {
});
});
describe('updateNodesPosition', () => {
it('records history for multiple node position updates when tracking is enabled', () => {
const events = [
{ id: 'node1', position: { x: 100, y: 100 } },
{ id: 'node2', position: { x: 200, y: 200 } },
];
const startRecordingUndoSpy = vi.spyOn(historyStore, 'startRecordingUndo');
const stopRecordingUndoSpy = vi.spyOn(historyStore, 'stopRecordingUndo');
canvasOperations.updateNodesPosition(events, { trackHistory: true, trackBulk: true });
expect(startRecordingUndoSpy).toHaveBeenCalled();
expect(stopRecordingUndoSpy).toHaveBeenCalled();
});
it('updates positions for multiple nodes', () => {
const events = [
{ id: 'node1', position: { x: 100, y: 100 } },
{ id: 'node2', position: { x: 200, y: 200 } },
];
const setNodePositionByIdSpy = vi.spyOn(workflowsStore, 'setNodePositionById');
vi.spyOn(workflowsStore, 'getNodeById')
.mockReturnValueOnce(
createTestNode({
id: events[0].id,
position: [events[0].position.x, events[0].position.y],
}),
)
.mockReturnValueOnce(
createTestNode({
id: events[1].id,
position: [events[1].position.x, events[1].position.y],
}),
);
canvasOperations.updateNodesPosition(events);
expect(setNodePositionByIdSpy).toHaveBeenCalledTimes(2);
expect(setNodePositionByIdSpy).toHaveBeenCalledWith('node1', [100, 100]);
expect(setNodePositionByIdSpy).toHaveBeenCalledWith('node2', [200, 200]);
});
it('does not record history when trackHistory is false', () => {
const events = [{ id: 'node1', position: { x: 100, y: 100 } }];
const startRecordingUndoSpy = vi.spyOn(historyStore, 'startRecordingUndo');
const stopRecordingUndoSpy = vi.spyOn(historyStore, 'stopRecordingUndo');
canvasOperations.updateNodesPosition(events, { trackHistory: false, trackBulk: false });
expect(startRecordingUndoSpy).not.toHaveBeenCalled();
expect(stopRecordingUndoSpy).not.toHaveBeenCalled();
});
});
describe('updateNodePosition', () => {
it('should update node position', () => {
const setNodePositionByIdSpy = vi

View File

@@ -49,7 +49,12 @@ import { useSettingsStore } from '@/stores/settings.store';
import { useTagsStore } from '@/stores/tags.store';
import { useUIStore } from '@/stores/ui.store';
import { useWorkflowsStore } from '@/stores/workflows.store';
import type { CanvasConnection, CanvasConnectionCreateData, CanvasNode } from '@/types';
import type {
CanvasConnection,
CanvasConnectionCreateData,
CanvasNode,
CanvasNodeMoveEvent,
} from '@/types';
import { CanvasConnectionMode } from '@/types';
import {
createCanvasConnectionHandleString,
@@ -138,20 +143,33 @@ export function useCanvasOperations({
* Node operations
*/
function updateNodesPosition(
events: CanvasNodeMoveEvent[],
{ trackHistory = false, trackBulk = true } = {},
) {
if (trackHistory && trackBulk) {
historyStore.startRecordingUndo();
}
events.forEach(({ id, position }) => {
updateNodePosition(id, position, { trackHistory });
});
if (trackBulk) {
historyStore.stopRecordingUndo();
}
}
function updateNodePosition(
id: string,
position: CanvasNode['position'],
{ trackHistory = false, trackBulk = true } = {},
{ trackHistory = false } = {},
) {
const node = workflowsStore.getNodeById(id);
if (!node) {
return;
}
if (trackHistory && trackBulk) {
historyStore.startRecordingUndo();
}
const oldPosition: XYPosition = [...node.position];
const newPosition: XYPosition = [position.x, position.y];
@@ -159,13 +177,18 @@ export function useCanvasOperations({
if (trackHistory) {
historyStore.pushCommandToUndo(new MoveNodeCommand(node.name, oldPosition, newPosition));
if (trackBulk) {
historyStore.stopRecordingUndo();
}
}
}
function revertUpdateNodePosition(nodeName: string, position: CanvasNode['position']) {
const node = workflowsStore.getNodeByName(nodeName);
if (!node) {
return;
}
updateNodePosition(node.id, position);
}
async function renameNode(currentName: string, newName: string, { trackHistory = false } = {}) {
if (currentName === newName) {
return;
@@ -1648,7 +1671,9 @@ export function useCanvasOperations({
addNodes,
addNode,
revertAddNode,
updateNodesPosition,
updateNodePosition,
revertUpdateNodePosition,
setNodeActive,
setNodeActiveByName,
setNodeSelected,