fix(editor): Disable context menu actions in read-only mode (#7789)
Github issue / Community forum post (link here to close automatically):
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||
|
||||
exports[`useContextMenu > should return the correct actions opening the menu from the button 1`] = `
|
||||
exports[`useContextMenu > Read-only mode > should return the correct actions when right clicking a Node 1`] = `
|
||||
[
|
||||
{
|
||||
"id": "open",
|
||||
@@ -12,6 +12,7 @@ exports[`useContextMenu > should return the correct actions opening the menu fro
|
||||
},
|
||||
},
|
||||
{
|
||||
"disabled": true,
|
||||
"id": "execute",
|
||||
"label": "Execute node",
|
||||
},
|
||||
@@ -97,106 +98,10 @@ exports[`useContextMenu > should return the correct actions opening the menu fro
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`useContextMenu > should return the correct actions when right clicking a Node 1`] = `
|
||||
exports[`useContextMenu > Read-only mode > should return the correct actions when right clicking a sticky 1`] = `
|
||||
[
|
||||
{
|
||||
"id": "open",
|
||||
"label": "Open node...",
|
||||
"shortcut": {
|
||||
"keys": [
|
||||
"↵",
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"id": "execute",
|
||||
"label": "Execute node",
|
||||
},
|
||||
{
|
||||
"disabled": true,
|
||||
"id": "rename",
|
||||
"label": "Rename node",
|
||||
"shortcut": {
|
||||
"keys": [
|
||||
"F2",
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"disabled": true,
|
||||
"id": "toggle_activation",
|
||||
"label": "Deactivate node",
|
||||
"shortcut": {
|
||||
"keys": [
|
||||
"D",
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"disabled": true,
|
||||
"id": "toggle_pin",
|
||||
"label": "Pin node",
|
||||
"shortcut": {
|
||||
"keys": [
|
||||
"p",
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"id": "copy",
|
||||
"label": "Copy node",
|
||||
"shortcut": {
|
||||
"keys": [
|
||||
"C",
|
||||
],
|
||||
"metaKey": true,
|
||||
},
|
||||
},
|
||||
{
|
||||
"disabled": true,
|
||||
"id": "duplicate",
|
||||
"label": "Duplicate node",
|
||||
"shortcut": {
|
||||
"keys": [
|
||||
"D",
|
||||
],
|
||||
"metaKey": true,
|
||||
},
|
||||
},
|
||||
{
|
||||
"disabled": false,
|
||||
"divided": true,
|
||||
"id": "select_all",
|
||||
"label": "Select all",
|
||||
"shortcut": {
|
||||
"keys": [
|
||||
"A",
|
||||
],
|
||||
"metaKey": true,
|
||||
},
|
||||
},
|
||||
{
|
||||
"disabled": false,
|
||||
"id": "deselect_all",
|
||||
"label": "Clear selection",
|
||||
},
|
||||
{
|
||||
"disabled": true,
|
||||
"divided": true,
|
||||
"id": "delete",
|
||||
"label": "Delete node",
|
||||
"shortcut": {
|
||||
"keys": [
|
||||
"Del",
|
||||
],
|
||||
},
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`useContextMenu > should return the correct actions when right clicking a sticky 1`] = `
|
||||
[
|
||||
{
|
||||
"id": "open",
|
||||
"label": "Edit sticky note",
|
||||
"shortcut": {
|
||||
@@ -205,6 +110,11 @@ exports[`useContextMenu > should return the correct actions when right clicking
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"disabled": true,
|
||||
"id": "change_color",
|
||||
"label": "Change color",
|
||||
},
|
||||
{
|
||||
"id": "copy",
|
||||
"label": "Copy sticky note",
|
||||
@@ -257,10 +167,275 @@ exports[`useContextMenu > should return the correct actions when right clicking
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`useContextMenu > should return the correct actions opening the menu from the button 1`] = `
|
||||
[
|
||||
{
|
||||
"id": "open",
|
||||
"label": "Open node...",
|
||||
"shortcut": {
|
||||
"keys": [
|
||||
"↵",
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"disabled": false,
|
||||
"id": "execute",
|
||||
"label": "Execute node",
|
||||
},
|
||||
{
|
||||
"disabled": false,
|
||||
"id": "rename",
|
||||
"label": "Rename node",
|
||||
"shortcut": {
|
||||
"keys": [
|
||||
"F2",
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"disabled": false,
|
||||
"id": "toggle_activation",
|
||||
"label": "Deactivate node",
|
||||
"shortcut": {
|
||||
"keys": [
|
||||
"D",
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"disabled": true,
|
||||
"id": "toggle_pin",
|
||||
"label": "Pin node",
|
||||
"shortcut": {
|
||||
"keys": [
|
||||
"p",
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"id": "copy",
|
||||
"label": "Copy node",
|
||||
"shortcut": {
|
||||
"keys": [
|
||||
"C",
|
||||
],
|
||||
"metaKey": true,
|
||||
},
|
||||
},
|
||||
{
|
||||
"disabled": true,
|
||||
"id": "duplicate",
|
||||
"label": "Duplicate node",
|
||||
"shortcut": {
|
||||
"keys": [
|
||||
"D",
|
||||
],
|
||||
"metaKey": true,
|
||||
},
|
||||
},
|
||||
{
|
||||
"disabled": false,
|
||||
"divided": true,
|
||||
"id": "select_all",
|
||||
"label": "Select all",
|
||||
"shortcut": {
|
||||
"keys": [
|
||||
"A",
|
||||
],
|
||||
"metaKey": true,
|
||||
},
|
||||
},
|
||||
{
|
||||
"disabled": false,
|
||||
"id": "deselect_all",
|
||||
"label": "Clear selection",
|
||||
},
|
||||
{
|
||||
"disabled": false,
|
||||
"divided": true,
|
||||
"id": "delete",
|
||||
"label": "Delete node",
|
||||
"shortcut": {
|
||||
"keys": [
|
||||
"Del",
|
||||
],
|
||||
},
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`useContextMenu > should return the correct actions when right clicking a Node 1`] = `
|
||||
[
|
||||
{
|
||||
"id": "open",
|
||||
"label": "Open node...",
|
||||
"shortcut": {
|
||||
"keys": [
|
||||
"↵",
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"disabled": false,
|
||||
"id": "execute",
|
||||
"label": "Execute node",
|
||||
},
|
||||
{
|
||||
"disabled": false,
|
||||
"id": "rename",
|
||||
"label": "Rename node",
|
||||
"shortcut": {
|
||||
"keys": [
|
||||
"F2",
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"disabled": false,
|
||||
"id": "toggle_activation",
|
||||
"label": "Deactivate node",
|
||||
"shortcut": {
|
||||
"keys": [
|
||||
"D",
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"disabled": true,
|
||||
"id": "toggle_pin",
|
||||
"label": "Pin node",
|
||||
"shortcut": {
|
||||
"keys": [
|
||||
"p",
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"id": "copy",
|
||||
"label": "Copy node",
|
||||
"shortcut": {
|
||||
"keys": [
|
||||
"C",
|
||||
],
|
||||
"metaKey": true,
|
||||
},
|
||||
},
|
||||
{
|
||||
"disabled": true,
|
||||
"id": "duplicate",
|
||||
"label": "Duplicate node",
|
||||
"shortcut": {
|
||||
"keys": [
|
||||
"D",
|
||||
],
|
||||
"metaKey": true,
|
||||
},
|
||||
},
|
||||
{
|
||||
"disabled": false,
|
||||
"divided": true,
|
||||
"id": "select_all",
|
||||
"label": "Select all",
|
||||
"shortcut": {
|
||||
"keys": [
|
||||
"A",
|
||||
],
|
||||
"metaKey": true,
|
||||
},
|
||||
},
|
||||
{
|
||||
"disabled": false,
|
||||
"id": "deselect_all",
|
||||
"label": "Clear selection",
|
||||
},
|
||||
{
|
||||
"disabled": false,
|
||||
"divided": true,
|
||||
"id": "delete",
|
||||
"label": "Delete node",
|
||||
"shortcut": {
|
||||
"keys": [
|
||||
"Del",
|
||||
],
|
||||
},
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`useContextMenu > should return the correct actions when right clicking a sticky 1`] = `
|
||||
[
|
||||
{
|
||||
"disabled": false,
|
||||
"id": "open",
|
||||
"label": "Edit sticky note",
|
||||
"shortcut": {
|
||||
"keys": [
|
||||
"↵",
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"disabled": false,
|
||||
"id": "change_color",
|
||||
"label": "Change color",
|
||||
},
|
||||
{
|
||||
"id": "copy",
|
||||
"label": "Copy sticky note",
|
||||
"shortcut": {
|
||||
"keys": [
|
||||
"C",
|
||||
],
|
||||
"metaKey": true,
|
||||
},
|
||||
},
|
||||
{
|
||||
"disabled": true,
|
||||
"id": "duplicate",
|
||||
"label": "Duplicate sticky note",
|
||||
"shortcut": {
|
||||
"keys": [
|
||||
"D",
|
||||
],
|
||||
"metaKey": true,
|
||||
},
|
||||
},
|
||||
{
|
||||
"disabled": false,
|
||||
"divided": true,
|
||||
"id": "select_all",
|
||||
"label": "Select all",
|
||||
"shortcut": {
|
||||
"keys": [
|
||||
"A",
|
||||
],
|
||||
"metaKey": true,
|
||||
},
|
||||
},
|
||||
{
|
||||
"disabled": false,
|
||||
"id": "deselect_all",
|
||||
"label": "Clear selection",
|
||||
},
|
||||
{
|
||||
"disabled": false,
|
||||
"divided": true,
|
||||
"id": "delete",
|
||||
"label": "Delete sticky note",
|
||||
"shortcut": {
|
||||
"keys": [
|
||||
"Del",
|
||||
],
|
||||
},
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`useContextMenu > should support opening and closing (default = right click on canvas) 1`] = `
|
||||
[
|
||||
{
|
||||
"disabled": true,
|
||||
"disabled": false,
|
||||
"id": "toggle_activation",
|
||||
"label": "Deactivate 2 nodes",
|
||||
"shortcut": {
|
||||
@@ -318,7 +493,7 @@ exports[`useContextMenu > should support opening and closing (default = right cl
|
||||
"label": "Clear selection",
|
||||
},
|
||||
{
|
||||
"disabled": true,
|
||||
"disabled": false,
|
||||
"divided": true,
|
||||
"id": "delete",
|
||||
"label": "Delete 2 nodes",
|
||||
|
||||
@@ -4,6 +4,7 @@ import { NO_OP_NODE_TYPE, STICKY_NODE_TYPE, STORES } from '@/constants';
|
||||
import { faker } from '@faker-js/faker';
|
||||
import { createTestingPinia } from '@pinia/testing';
|
||||
import { setActivePinia } from 'pinia';
|
||||
import { useSourceControlStore, useUIStore } from '@/stores';
|
||||
|
||||
const nodeFactory = (data: Partial<INodeUi> = {}): INodeUi => ({
|
||||
id: faker.string.uuid(),
|
||||
@@ -16,6 +17,8 @@ const nodeFactory = (data: Partial<INodeUi> = {}): INodeUi => ({
|
||||
});
|
||||
|
||||
describe('useContextMenu', () => {
|
||||
let sourceControlStore: ReturnType<typeof useSourceControlStore>;
|
||||
let uiStore: ReturnType<typeof useUIStore>;
|
||||
const nodes = [nodeFactory(), nodeFactory(), nodeFactory()];
|
||||
const selectedNodes = nodes.slice(0, 2);
|
||||
|
||||
@@ -28,6 +31,12 @@ describe('useContextMenu', () => {
|
||||
},
|
||||
}),
|
||||
);
|
||||
sourceControlStore = useSourceControlStore();
|
||||
uiStore = useUIStore();
|
||||
vi.spyOn(uiStore, 'isReadOnlyView', 'get').mockReturnValue(false);
|
||||
vi.spyOn(sourceControlStore, 'preferences', 'get').mockReturnValue({
|
||||
branchReadOnly: false,
|
||||
} as never);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@@ -89,4 +98,28 @@ describe('useContextMenu', () => {
|
||||
expect(actions.value).toMatchSnapshot();
|
||||
expect(targetNodes.value).toEqual([node]);
|
||||
});
|
||||
|
||||
describe('Read-only mode', () => {
|
||||
it('should return the correct actions when right clicking a sticky', () => {
|
||||
vi.spyOn(uiStore, 'isReadOnlyView', 'get').mockReturnValue(true);
|
||||
const { open, isOpen, actions, targetNodes } = useContextMenu();
|
||||
const sticky = nodeFactory({ type: STICKY_NODE_TYPE });
|
||||
open(mockEvent, { source: 'node-right-click', node: sticky });
|
||||
|
||||
expect(isOpen.value).toBe(true);
|
||||
expect(actions.value).toMatchSnapshot();
|
||||
expect(targetNodes.value).toEqual([sticky]);
|
||||
});
|
||||
|
||||
it('should return the correct actions when right clicking a Node', () => {
|
||||
vi.spyOn(uiStore, 'isReadOnlyView', 'get').mockReturnValue(true);
|
||||
const { open, isOpen, actions, targetNodes } = useContextMenu();
|
||||
const node = nodeFactory();
|
||||
open(mockEvent, { source: 'node-right-click', node });
|
||||
|
||||
expect(isOpen.value).toBe(true);
|
||||
expect(actions.value).toMatchSnapshot();
|
||||
expect(targetNodes.value).toEqual([node]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -16,6 +16,7 @@ export type ContextMenuTarget =
|
||||
| { source: 'canvas' }
|
||||
| { source: 'node-right-click'; node: INode }
|
||||
| { source: 'node-button'; node: INode };
|
||||
export type ContextMenuActionCallback = (action: ContextMenuAction, targets: INode[]) => void;
|
||||
export type ContextMenuAction =
|
||||
| 'open'
|
||||
| 'copy'
|
||||
@@ -28,14 +29,16 @@ export type ContextMenuAction =
|
||||
| 'select_all'
|
||||
| 'deselect_all'
|
||||
| 'add_node'
|
||||
| 'add_sticky';
|
||||
| 'add_sticky'
|
||||
| 'change_color';
|
||||
|
||||
const position = ref<XYPosition>([0, 0]);
|
||||
const isOpen = ref(false);
|
||||
const target = ref<ContextMenuTarget>({ source: 'canvas' });
|
||||
const actions = ref<IActionDropdownItem[]>([]);
|
||||
const actionCallback = ref<ContextMenuActionCallback>(() => {});
|
||||
|
||||
export const useContextMenu = () => {
|
||||
export const useContextMenu = (onAction: ContextMenuActionCallback = () => {}) => {
|
||||
const uiStore = useUIStore();
|
||||
const nodeTypesStore = useNodeTypesStore();
|
||||
const workflowsStore = useWorkflowsStore();
|
||||
@@ -104,6 +107,7 @@ export const useContextMenu = () => {
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
actionCallback.value = onAction;
|
||||
target.value = menuTarget;
|
||||
position.value = getMousePosition(event);
|
||||
isOpen.value = true;
|
||||
@@ -196,6 +200,12 @@ export const useContextMenu = () => {
|
||||
id: 'open',
|
||||
label: i18n.baseText('contextMenu.editSticky'),
|
||||
shortcut: { keys: ['↵'] },
|
||||
disabled: isReadOnly.value,
|
||||
},
|
||||
{
|
||||
id: 'change_color',
|
||||
label: i18n.baseText('contextMenu.changeColor'),
|
||||
disabled: isReadOnly.value,
|
||||
},
|
||||
]
|
||||
: [
|
||||
@@ -207,6 +217,7 @@ export const useContextMenu = () => {
|
||||
{
|
||||
id: 'execute',
|
||||
label: i18n.baseText('contextMenu.execute'),
|
||||
disabled: isReadOnly.value,
|
||||
},
|
||||
{
|
||||
id: 'rename',
|
||||
@@ -223,6 +234,10 @@ export const useContextMenu = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const _dispatchAction = (action: ContextMenuAction) => {
|
||||
actionCallback.value(action, targetNodes.value);
|
||||
};
|
||||
|
||||
watch(
|
||||
() => uiStore.nodeViewOffsetPosition,
|
||||
() => {
|
||||
@@ -238,5 +253,6 @@ export const useContextMenu = () => {
|
||||
targetNodes,
|
||||
open,
|
||||
close,
|
||||
_dispatchAction,
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user