mirror of
https://github.com/simstudioai/sim.git
synced 2026-01-07 22:24:06 -05:00
feat(copy-paste): allow cross workflow selection, paste, move for blocks (#2649)
* feat(copy-paste): allow cross workflow selection, paste, move for blocks * fix drag options * add keyboard and mouse controls into docs * refactor sockets and undo/redo for batch additions and removals * fix tests * cleanup more code * fix perms issue * fix subflow copy/paste * remove log file * fit paste in viewport bounds * fix deselection
This commit is contained in:
committed by
GitHub
parent
fb148c6203
commit
bf5d0a5573
@@ -120,22 +120,20 @@ export {
|
||||
} from './serialized-block.factory'
|
||||
// Undo/redo operation factories
|
||||
export {
|
||||
type AddBlockOperation,
|
||||
type AddEdgeOperation,
|
||||
type BaseOperation,
|
||||
type BatchAddBlocksOperation,
|
||||
type BatchRemoveBlocksOperation,
|
||||
createAddBlockEntry,
|
||||
createAddEdgeEntry,
|
||||
createDuplicateBlockEntry,
|
||||
createMoveBlockEntry,
|
||||
createRemoveBlockEntry,
|
||||
createRemoveEdgeEntry,
|
||||
createUpdateParentEntry,
|
||||
type DuplicateBlockOperation,
|
||||
type MoveBlockOperation,
|
||||
type Operation,
|
||||
type OperationEntry,
|
||||
type OperationType,
|
||||
type RemoveBlockOperation,
|
||||
type RemoveEdgeOperation,
|
||||
type UpdateParentOperation,
|
||||
} from './undo-redo.factory'
|
||||
|
||||
@@ -257,6 +257,8 @@ export function createWorkflowAccessContext(options: {
|
||||
export const SOCKET_OPERATIONS = [
|
||||
'add',
|
||||
'remove',
|
||||
'batch-add-blocks',
|
||||
'batch-remove-blocks',
|
||||
'update',
|
||||
'update-position',
|
||||
'update-name',
|
||||
@@ -266,7 +268,7 @@ export const SOCKET_OPERATIONS = [
|
||||
'update-advanced-mode',
|
||||
'update-trigger-mode',
|
||||
'toggle-handles',
|
||||
'duplicate',
|
||||
'batch-update-positions',
|
||||
'replace-state',
|
||||
] as const
|
||||
|
||||
@@ -278,7 +280,7 @@ export type SocketOperation = (typeof SOCKET_OPERATIONS)[number]
|
||||
export const ROLE_ALLOWED_OPERATIONS: Record<PermissionType, SocketOperation[]> = {
|
||||
admin: [...SOCKET_OPERATIONS],
|
||||
write: [...SOCKET_OPERATIONS],
|
||||
read: ['update-position'],
|
||||
read: ['update-position', 'batch-update-positions'],
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -6,12 +6,11 @@ import { nanoid } from 'nanoid'
|
||||
* Operation types supported by the undo/redo store.
|
||||
*/
|
||||
export type OperationType =
|
||||
| 'add-block'
|
||||
| 'remove-block'
|
||||
| 'batch-add-blocks'
|
||||
| 'batch-remove-blocks'
|
||||
| 'add-edge'
|
||||
| 'remove-edge'
|
||||
| 'move-block'
|
||||
| 'duplicate-block'
|
||||
| 'update-parent'
|
||||
|
||||
/**
|
||||
@@ -38,22 +37,26 @@ export interface MoveBlockOperation extends BaseOperation {
|
||||
}
|
||||
|
||||
/**
|
||||
* Add block operation data.
|
||||
* Batch add blocks operation data.
|
||||
*/
|
||||
export interface AddBlockOperation extends BaseOperation {
|
||||
type: 'add-block'
|
||||
data: { blockId: string }
|
||||
export interface BatchAddBlocksOperation extends BaseOperation {
|
||||
type: 'batch-add-blocks'
|
||||
data: {
|
||||
blockSnapshots: any[]
|
||||
edgeSnapshots: any[]
|
||||
subBlockValues: Record<string, Record<string, any>>
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove block operation data.
|
||||
* Batch remove blocks operation data.
|
||||
*/
|
||||
export interface RemoveBlockOperation extends BaseOperation {
|
||||
type: 'remove-block'
|
||||
export interface BatchRemoveBlocksOperation extends BaseOperation {
|
||||
type: 'batch-remove-blocks'
|
||||
data: {
|
||||
blockId: string
|
||||
blockSnapshot: any
|
||||
edgeSnapshots?: any[]
|
||||
blockSnapshots: any[]
|
||||
edgeSnapshots: any[]
|
||||
subBlockValues: Record<string, Record<string, any>>
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,18 +76,6 @@ export interface RemoveEdgeOperation extends BaseOperation {
|
||||
data: { edgeId: string; edgeSnapshot: any }
|
||||
}
|
||||
|
||||
/**
|
||||
* Duplicate block operation data.
|
||||
*/
|
||||
export interface DuplicateBlockOperation extends BaseOperation {
|
||||
type: 'duplicate-block'
|
||||
data: {
|
||||
sourceBlockId: string
|
||||
duplicatedBlockId: string
|
||||
duplicatedBlockSnapshot: any
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update parent operation data.
|
||||
*/
|
||||
@@ -100,12 +91,11 @@ export interface UpdateParentOperation extends BaseOperation {
|
||||
}
|
||||
|
||||
export type Operation =
|
||||
| AddBlockOperation
|
||||
| RemoveBlockOperation
|
||||
| BatchAddBlocksOperation
|
||||
| BatchRemoveBlocksOperation
|
||||
| AddEdgeOperation
|
||||
| RemoveEdgeOperation
|
||||
| MoveBlockOperation
|
||||
| DuplicateBlockOperation
|
||||
| UpdateParentOperation
|
||||
|
||||
/**
|
||||
@@ -126,36 +116,51 @@ interface OperationEntryOptions {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a mock add-block operation entry.
|
||||
* Creates a mock batch-add-blocks operation entry.
|
||||
*/
|
||||
export function createAddBlockEntry(blockId: string, options: OperationEntryOptions = {}): any {
|
||||
const { id = nanoid(8), workflowId = 'wf-1', userId = 'user-1', createdAt = Date.now() } = options
|
||||
const timestamp = Date.now()
|
||||
|
||||
const mockBlockSnapshot = {
|
||||
id: blockId,
|
||||
type: 'action',
|
||||
name: `Block ${blockId}`,
|
||||
position: { x: 0, y: 0 },
|
||||
}
|
||||
|
||||
return {
|
||||
id,
|
||||
createdAt,
|
||||
operation: {
|
||||
id: nanoid(8),
|
||||
type: 'add-block',
|
||||
type: 'batch-add-blocks',
|
||||
timestamp,
|
||||
workflowId,
|
||||
userId,
|
||||
data: { blockId },
|
||||
data: {
|
||||
blockSnapshots: [mockBlockSnapshot],
|
||||
edgeSnapshots: [],
|
||||
subBlockValues: {},
|
||||
},
|
||||
},
|
||||
inverse: {
|
||||
id: nanoid(8),
|
||||
type: 'remove-block',
|
||||
type: 'batch-remove-blocks',
|
||||
timestamp,
|
||||
workflowId,
|
||||
userId,
|
||||
data: { blockId, blockSnapshot: null },
|
||||
data: {
|
||||
blockSnapshots: [mockBlockSnapshot],
|
||||
edgeSnapshots: [],
|
||||
subBlockValues: {},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a mock remove-block operation entry.
|
||||
* Creates a mock batch-remove-blocks operation entry.
|
||||
*/
|
||||
export function createRemoveBlockEntry(
|
||||
blockId: string,
|
||||
@@ -165,24 +170,39 @@ export function createRemoveBlockEntry(
|
||||
const { id = nanoid(8), workflowId = 'wf-1', userId = 'user-1', createdAt = Date.now() } = options
|
||||
const timestamp = Date.now()
|
||||
|
||||
const snapshotToUse = blockSnapshot || {
|
||||
id: blockId,
|
||||
type: 'action',
|
||||
name: `Block ${blockId}`,
|
||||
position: { x: 0, y: 0 },
|
||||
}
|
||||
|
||||
return {
|
||||
id,
|
||||
createdAt,
|
||||
operation: {
|
||||
id: nanoid(8),
|
||||
type: 'remove-block',
|
||||
type: 'batch-remove-blocks',
|
||||
timestamp,
|
||||
workflowId,
|
||||
userId,
|
||||
data: { blockId, blockSnapshot },
|
||||
data: {
|
||||
blockSnapshots: [snapshotToUse],
|
||||
edgeSnapshots: [],
|
||||
subBlockValues: {},
|
||||
},
|
||||
},
|
||||
inverse: {
|
||||
id: nanoid(8),
|
||||
type: 'add-block',
|
||||
type: 'batch-add-blocks',
|
||||
timestamp,
|
||||
workflowId,
|
||||
userId,
|
||||
data: { blockId },
|
||||
data: {
|
||||
blockSnapshots: [snapshotToUse],
|
||||
edgeSnapshots: [],
|
||||
subBlockValues: {},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -290,40 +310,6 @@ export function createMoveBlockEntry(blockId: string, options: MoveBlockOptions
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a mock duplicate-block operation entry.
|
||||
*/
|
||||
export function createDuplicateBlockEntry(
|
||||
sourceBlockId: string,
|
||||
duplicatedBlockId: string,
|
||||
duplicatedBlockSnapshot: any,
|
||||
options: OperationEntryOptions = {}
|
||||
): any {
|
||||
const { id = nanoid(8), workflowId = 'wf-1', userId = 'user-1', createdAt = Date.now() } = options
|
||||
const timestamp = Date.now()
|
||||
|
||||
return {
|
||||
id,
|
||||
createdAt,
|
||||
operation: {
|
||||
id: nanoid(8),
|
||||
type: 'duplicate-block',
|
||||
timestamp,
|
||||
workflowId,
|
||||
userId,
|
||||
data: { sourceBlockId, duplicatedBlockId, duplicatedBlockSnapshot },
|
||||
},
|
||||
inverse: {
|
||||
id: nanoid(8),
|
||||
type: 'remove-block',
|
||||
timestamp,
|
||||
workflowId,
|
||||
userId,
|
||||
data: { blockId: duplicatedBlockId, blockSnapshot: duplicatedBlockSnapshot },
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a mock update-parent operation entry.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user