mirror of
https://github.com/n8n-io/n8n.git
synced 2025-03-05 20:50:17 -08:00
🐛 Fix issues in read-only mode #39
This commit is contained in:
parent
2cdfb69e0c
commit
5718330e29
|
@ -65,6 +65,7 @@ export const nodeBase = mixins(nodeIndex).extend({
|
||||||
'name',
|
'name',
|
||||||
'nodeId',
|
'nodeId',
|
||||||
'instance',
|
'instance',
|
||||||
|
'isReadOnly',
|
||||||
],
|
],
|
||||||
methods: {
|
methods: {
|
||||||
__addNode (node: INodeUi) {
|
__addNode (node: INodeUi) {
|
||||||
|
@ -182,7 +183,7 @@ export const nodeBase = mixins(nodeIndex).extend({
|
||||||
endpoint: inputData.endpoint,
|
endpoint: inputData.endpoint,
|
||||||
endpointStyle: inputData.endpointStyle,
|
endpointStyle: inputData.endpointStyle,
|
||||||
isSource: false,
|
isSource: false,
|
||||||
isTarget: true,
|
isTarget: !this.isReadOnly,
|
||||||
parameters: {
|
parameters: {
|
||||||
nodeIndex: this.nodeIndex,
|
nodeIndex: this.nodeIndex,
|
||||||
type: inputName,
|
type: inputName,
|
||||||
|
@ -246,7 +247,7 @@ export const nodeBase = mixins(nodeIndex).extend({
|
||||||
maxConnections: inputData.maxConnections,
|
maxConnections: inputData.maxConnections,
|
||||||
endpoint: inputData.endpoint,
|
endpoint: inputData.endpoint,
|
||||||
endpointStyle: inputData.endpointStyle,
|
endpointStyle: inputData.endpointStyle,
|
||||||
isSource: true,
|
isSource: !this.isReadOnly,
|
||||||
isTarget: false,
|
isTarget: false,
|
||||||
parameters: {
|
parameters: {
|
||||||
nodeIndex: this.nodeIndex,
|
nodeIndex: this.nodeIndex,
|
||||||
|
@ -275,61 +276,63 @@ export const nodeBase = mixins(nodeIndex).extend({
|
||||||
this.instance.addEndpoint(this.nodeName, newEndpointData);
|
this.instance.addEndpoint(this.nodeName, newEndpointData);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Make nodes draggable
|
if (this.isReadOnly === false) {
|
||||||
this.instance.draggable(this.nodeName, {
|
// Make nodes draggable
|
||||||
grid: [10, 10],
|
this.instance.draggable(this.nodeName, {
|
||||||
start: (params: { e: MouseEvent }) => {
|
grid: [10, 10],
|
||||||
if (params.e && !this.$store.getters.isNodeSelected(this.data.name)) {
|
start: (params: { e: MouseEvent }) => {
|
||||||
// Only the node which gets dragged directly gets an event, for all others it is
|
if (params.e && !this.$store.getters.isNodeSelected(this.data.name)) {
|
||||||
// undefined. So check if the currently dragged node is selected and if not clear
|
// Only the node which gets dragged directly gets an event, for all others it is
|
||||||
// the drag-selection.
|
// undefined. So check if the currently dragged node is selected and if not clear
|
||||||
this.instance.clearDragSelection();
|
// the drag-selection.
|
||||||
this.$store.commit('resetSelectedNodes');
|
this.instance.clearDragSelection();
|
||||||
}
|
this.$store.commit('resetSelectedNodes');
|
||||||
|
|
||||||
this.$store.commit('addActiveAction', 'dragActive');
|
|
||||||
},
|
|
||||||
stop: (params: { e: MouseEvent}) => {
|
|
||||||
if (this.$store.getters.isActionActive('dragActive')) {
|
|
||||||
const moveNodes = this.$store.getters.getSelectedNodes.slice();
|
|
||||||
const selectedNodeNames = moveNodes.map((node: INodeUi) => node.name);
|
|
||||||
if (!selectedNodeNames.includes(this.data.name)) {
|
|
||||||
// If the current node is not in selected add it to the nodes which
|
|
||||||
// got moved manually
|
|
||||||
moveNodes.push(this.data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This does for some reason just get called once for the node that got clicked
|
this.$store.commit('addActiveAction', 'dragActive');
|
||||||
// even though "start" and "drag" gets called for all. So lets do for now
|
},
|
||||||
// some dirty DOM query to get the new positions till I have more time to
|
stop: (params: { e: MouseEvent }) => {
|
||||||
// create a proper solution
|
if (this.$store.getters.isActionActive('dragActive')) {
|
||||||
let newNodePositon: XYPositon;
|
const moveNodes = this.$store.getters.getSelectedNodes.slice();
|
||||||
moveNodes.forEach((node: INodeUi) => {
|
const selectedNodeNames = moveNodes.map((node: INodeUi) => node.name);
|
||||||
const nodeElement = `node-${this.getNodeIndex(node.name)}`;
|
if (!selectedNodeNames.includes(this.data.name)) {
|
||||||
const element = document.getElementById(nodeElement);
|
// If the current node is not in selected add it to the nodes which
|
||||||
if (element === null) {
|
// got moved manually
|
||||||
return;
|
moveNodes.push(this.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
newNodePositon = [
|
// This does for some reason just get called once for the node that got clicked
|
||||||
parseInt(element.style.left!.slice(0, -2), 10),
|
// even though "start" and "drag" gets called for all. So lets do for now
|
||||||
parseInt(element.style.top!.slice(0, -2), 10),
|
// some dirty DOM query to get the new positions till I have more time to
|
||||||
];
|
// create a proper solution
|
||||||
|
let newNodePositon: XYPositon;
|
||||||
|
moveNodes.forEach((node: INodeUi) => {
|
||||||
|
const nodeElement = `node-${this.getNodeIndex(node.name)}`;
|
||||||
|
const element = document.getElementById(nodeElement);
|
||||||
|
if (element === null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const updateInformation = {
|
newNodePositon = [
|
||||||
name: node.name,
|
parseInt(element.style.left!.slice(0, -2), 10),
|
||||||
properties: {
|
parseInt(element.style.top!.slice(0, -2), 10),
|
||||||
// @ts-ignore, draggable does not have definitions
|
];
|
||||||
position: newNodePositon,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
this.$store.commit('updateNodeProperties', updateInformation);
|
const updateInformation = {
|
||||||
});
|
name: node.name,
|
||||||
}
|
properties: {
|
||||||
},
|
// @ts-ignore, draggable does not have definitions
|
||||||
filter: '.node-description, .node-description .node-name, .node-description .node-subtitle',
|
position: newNodePositon,
|
||||||
});
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
this.$store.commit('updateNodeProperties', updateInformation);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
filter: '.node-description, .node-description .node-name, .node-description .node-subtitle',
|
||||||
|
});
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
isCtrlKeyPressed (e: MouseEvent | KeyboardEvent): boolean {
|
isCtrlKeyPressed (e: MouseEvent | KeyboardEvent): boolean {
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
:id="'node-' + getNodeIndex(nodeData.name)"
|
:id="'node-' + getNodeIndex(nodeData.name)"
|
||||||
:key="getNodeIndex(nodeData.name)"
|
:key="getNodeIndex(nodeData.name)"
|
||||||
:name="nodeData.name"
|
:name="nodeData.name"
|
||||||
|
:isReadOnly="isReadOnly"
|
||||||
:instance="instance"
|
:instance="instance"
|
||||||
></node>
|
></node>
|
||||||
</div>
|
</div>
|
||||||
|
@ -102,6 +103,9 @@
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
|
import {
|
||||||
|
OverlaySpec,
|
||||||
|
} from 'jsplumb';
|
||||||
import { MessageBoxInputData } from 'element-ui/types/message-box';
|
import { MessageBoxInputData } from 'element-ui/types/message-box';
|
||||||
import { jsPlumb, Endpoint, OnConnectionBindInfo } from 'jsplumb';
|
import { jsPlumb, Endpoint, OnConnectionBindInfo } from 'jsplumb';
|
||||||
import { NODE_NAME_PREFIX, PLACEHOLDER_EMPTY_WORKFLOW_ID } from '@/constants';
|
import { NODE_NAME_PREFIX, PLACEHOLDER_EMPTY_WORKFLOW_ID } from '@/constants';
|
||||||
|
@ -1013,21 +1017,9 @@ export default mixins(
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
initNodeView () {
|
initNodeView () {
|
||||||
this.instance.importDefaults({
|
const connectionOverlays: OverlaySpec[] = [];
|
||||||
// notice the 'curviness' argument to this Bezier curve.
|
if (this.isReadOnly === false) {
|
||||||
// the curves on this page are far smoother
|
connectionOverlays.push.apply(connectionOverlays, [
|
||||||
// than the curves on the first demo, which use the default curviness value.
|
|
||||||
// Connector: ["Bezier", { curviness: 80 }],
|
|
||||||
Connector: ['Bezier', { curviness: 40 }],
|
|
||||||
// @ts-ignore
|
|
||||||
Endpoint: ['Dot', { radius: 5 }],
|
|
||||||
DragOptions: { cursor: 'pointer', zIndex: 5000 },
|
|
||||||
PaintStyle: { strokeWidth: 2, stroke: '#334455' },
|
|
||||||
EndpointStyle: { radius: 9, fill: '#acd', stroke: 'red' },
|
|
||||||
// EndpointStyle: {},
|
|
||||||
HoverPaintStyle: { stroke: '#ff6d5a', lineWidth: 4 },
|
|
||||||
EndpointHoverStyle: { fill: '#ff6d5a', stroke: '#acd' },
|
|
||||||
ConnectionOverlays: [
|
|
||||||
[
|
[
|
||||||
'Arrow',
|
'Arrow',
|
||||||
{
|
{
|
||||||
|
@ -1045,7 +1037,24 @@ export default mixins(
|
||||||
location: 0.5,
|
location: 0.5,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
],
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.instance.importDefaults({
|
||||||
|
// notice the 'curviness' argument to this Bezier curve.
|
||||||
|
// the curves on this page are far smoother
|
||||||
|
// than the curves on the first demo, which use the default curviness value.
|
||||||
|
// Connector: ["Bezier", { curviness: 80 }],
|
||||||
|
Connector: ['Bezier', { curviness: 40 }],
|
||||||
|
// @ts-ignore
|
||||||
|
Endpoint: ['Dot', { radius: 5 }],
|
||||||
|
DragOptions: { cursor: 'pointer', zIndex: 5000 },
|
||||||
|
PaintStyle: { strokeWidth: 2, stroke: '#334455' },
|
||||||
|
EndpointStyle: { radius: 9, fill: '#acd', stroke: 'red' },
|
||||||
|
// EndpointStyle: {},
|
||||||
|
HoverPaintStyle: { stroke: '#ff6d5a', lineWidth: 4 },
|
||||||
|
EndpointHoverStyle: { fill: '#ff6d5a', stroke: '#acd' },
|
||||||
|
ConnectionOverlays: connectionOverlays,
|
||||||
Container: '#node-view',
|
Container: '#node-view',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1100,41 +1109,43 @@ export default mixins(
|
||||||
info.connection.setConnector(['Straight']);
|
info.connection.setConnector(['Straight']);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Display the connection-delete button only on hover
|
|
||||||
let timer: NodeJS.Timeout | undefined;
|
|
||||||
info.connection.bind('mouseover', (connection: IConnection) => {
|
|
||||||
if (timer !== undefined) {
|
|
||||||
clearTimeout(timer);
|
|
||||||
}
|
|
||||||
const overlay = info.connection.getOverlay('remove-connection');
|
|
||||||
overlay.setVisible(true);
|
|
||||||
});
|
|
||||||
info.connection.bind('mouseout', (connection: IConnection) => {
|
|
||||||
timer = setTimeout(() => {
|
|
||||||
const overlay = info.connection.getOverlay('remove-connection');
|
|
||||||
overlay.setVisible(false);
|
|
||||||
timer = undefined;
|
|
||||||
}, 500);
|
|
||||||
});
|
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
info.connection.removeOverlay('drop-add-node');
|
info.connection.removeOverlay('drop-add-node');
|
||||||
|
|
||||||
// @ts-ignore
|
if (this.isReadOnly === false) {
|
||||||
info.connection.addOverlay([
|
// Display the connection-delete button only on hover
|
||||||
'Label',
|
let timer: NodeJS.Timeout | undefined;
|
||||||
{
|
info.connection.bind('mouseover', (connection: IConnection) => {
|
||||||
id: 'remove-connection',
|
if (timer !== undefined) {
|
||||||
label: '<span class="delete-connection clickable" title="Delete Connection">x</span>',
|
clearTimeout(timer);
|
||||||
cssClass: 'remove-connection-label',
|
}
|
||||||
visible: false,
|
const overlay = info.connection.getOverlay('remove-connection');
|
||||||
events: {
|
overlay.setVisible(true);
|
||||||
mousedown: () => {
|
});
|
||||||
this.__removeConnectionByConnectionInfo(info, true);
|
info.connection.bind('mouseout', (connection: IConnection) => {
|
||||||
|
timer = setTimeout(() => {
|
||||||
|
const overlay = info.connection.getOverlay('remove-connection');
|
||||||
|
overlay.setVisible(false);
|
||||||
|
timer = undefined;
|
||||||
|
}, 500);
|
||||||
|
});
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
info.connection.addOverlay([
|
||||||
|
'Label',
|
||||||
|
{
|
||||||
|
id: 'remove-connection',
|
||||||
|
label: '<span class="delete-connection clickable" title="Delete Connection">x</span>',
|
||||||
|
cssClass: 'remove-connection-label',
|
||||||
|
visible: false,
|
||||||
|
events: {
|
||||||
|
mousedown: () => {
|
||||||
|
this.__removeConnectionByConnectionInfo(info, true);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
]);
|
||||||
]);
|
}
|
||||||
|
|
||||||
// Display input names if they exist on connection
|
// Display input names if they exist on connection
|
||||||
const targetNodeTypeData: INodeTypeDescription = this.$store.getters.nodeType(targetNode.type);
|
const targetNodeTypeData: INodeTypeDescription = this.$store.getters.nodeType(targetNode.type);
|
||||||
|
@ -1329,6 +1340,7 @@ export default mixins(
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
this.instance.connect({
|
this.instance.connect({
|
||||||
uuids: uuid,
|
uuids: uuid,
|
||||||
|
detachable: !this.isReadOnly,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// When nodes get connected it gets saved automatically to the storage
|
// When nodes get connected it gets saved automatically to the storage
|
||||||
|
|
Loading…
Reference in a new issue