mirror of https://github.com/node-red/node-red.git
Merge branch 'master' into master
commit
b419e2e303
|
@ -334,6 +334,30 @@ RED.clipboard = (function() {
|
|||
},100);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates if the provided string looks like valid flow json
|
||||
* @param {string} flowString the string to validate
|
||||
* @returns If valid, returns the node array
|
||||
*/
|
||||
function validateFlowString(flowString) {
|
||||
const res = JSON.parse(flowString)
|
||||
if (!Array.isArray(res)) {
|
||||
throw new Error(RED._("clipboard.import.errors.notArray"));
|
||||
}
|
||||
for (let i = 0; i < res.length; i++) {
|
||||
if (typeof res[i] !== "object") {
|
||||
throw new Error(RED._("clipboard.import.errors.itemNotObject",{index:i}));
|
||||
}
|
||||
if (!Object.hasOwn(res[i], 'id')) {
|
||||
throw new Error(RED._("clipboard.import.errors.missingId",{index:i}));
|
||||
}
|
||||
if (!Object.hasOwn(res[i], 'type')) {
|
||||
throw new Error(RED._("clipboard.import.errors.missingType",{index:i}));
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
var validateImportTimeout;
|
||||
function validateImport() {
|
||||
if (activeTab === "red-ui-clipboard-dialog-import-tab-clipboard") {
|
||||
|
@ -351,21 +375,7 @@ RED.clipboard = (function() {
|
|||
return;
|
||||
}
|
||||
try {
|
||||
if (!/^\[[\s\S]*\]$/m.test(v)) {
|
||||
throw new Error(RED._("clipboard.import.errors.notArray"));
|
||||
}
|
||||
var res = JSON.parse(v);
|
||||
for (var i=0;i<res.length;i++) {
|
||||
if (typeof res[i] !== "object") {
|
||||
throw new Error(RED._("clipboard.import.errors.itemNotObject",{index:i}));
|
||||
}
|
||||
if (!res[i].hasOwnProperty('id')) {
|
||||
throw new Error(RED._("clipboard.import.errors.missingId",{index:i}));
|
||||
}
|
||||
if (!res[i].hasOwnProperty('type')) {
|
||||
throw new Error(RED._("clipboard.import.errors.missingType",{index:i}));
|
||||
}
|
||||
}
|
||||
validateFlowString(v)
|
||||
currentPopoverError = null;
|
||||
popover.close(true);
|
||||
importInput.removeClass("input-error");
|
||||
|
@ -998,16 +1008,16 @@ RED.clipboard = (function() {
|
|||
}
|
||||
|
||||
function importNodes(nodesStr,addFlow) {
|
||||
var newNodes = nodesStr;
|
||||
let newNodes = nodesStr;
|
||||
if (typeof nodesStr === 'string') {
|
||||
try {
|
||||
nodesStr = nodesStr.trim();
|
||||
if (nodesStr.length === 0) {
|
||||
return;
|
||||
}
|
||||
newNodes = JSON.parse(nodesStr);
|
||||
newNodes = validateFlowString(nodesStr)
|
||||
} catch(err) {
|
||||
var e = new Error(RED._("clipboard.invalidFlow",{message:err.message}));
|
||||
const e = new Error(RED._("clipboard.invalidFlow",{message:err.message}));
|
||||
e.code = "NODE_RED";
|
||||
throw e;
|
||||
}
|
||||
|
@ -1342,6 +1352,7 @@ RED.clipboard = (function() {
|
|||
}
|
||||
}
|
||||
} catch(err) {
|
||||
console.warn('Import failed: ', err)
|
||||
// Ensure any errors throw above doesn't stop the drop target from
|
||||
// being hidden.
|
||||
}
|
||||
|
|
|
@ -54,15 +54,15 @@ RED.contextMenu = (function () {
|
|||
}
|
||||
}
|
||||
|
||||
const scale = RED.view.scale()
|
||||
const offset = $("#red-ui-workspace-chart").offset()
|
||||
|
||||
let addX = options.x - offset.left + $("#red-ui-workspace-chart").scrollLeft()
|
||||
let addY = options.y - offset.top + $("#red-ui-workspace-chart").scrollTop()
|
||||
let addX = (options.x - offset.left + $("#red-ui-workspace-chart").scrollLeft()) / scale
|
||||
let addY = (options.y - offset.top + $("#red-ui-workspace-chart").scrollTop()) / scale
|
||||
|
||||
if (RED.view.snapGrid) {
|
||||
const gridSize = RED.view.gridSize()
|
||||
addX = gridSize * Math.floor(addX / gridSize)
|
||||
addY = gridSize * Math.floor(addY / gridSize)
|
||||
addX = gridSize * Math.round(addX / gridSize)
|
||||
addY = gridSize * Math.round(addY / gridSize)
|
||||
}
|
||||
|
||||
if (RED.settings.theme("menu.menu-item-action-list", true)) {
|
||||
|
@ -87,7 +87,9 @@ RED.contextMenu = (function () {
|
|||
},
|
||||
(hasLinks) ? { // has least 1 wire selected
|
||||
label: RED._("contextMenu.junction"),
|
||||
onselect: 'core:split-wires-with-junctions',
|
||||
onselect: function () {
|
||||
RED.actions.invoke('core:split-wires-with-junctions', { x: addX, y: addY })
|
||||
},
|
||||
disabled: !canEdit || !hasLinks
|
||||
} : {
|
||||
label: RED._("contextMenu.junction"),
|
||||
|
|
|
@ -11,7 +11,7 @@ RED.view.annotations = (function() {
|
|||
}
|
||||
let badgeRDX = 0;
|
||||
let badgeLDX = 0;
|
||||
|
||||
const scale = RED.view.scale()
|
||||
for (let i=0,l=evt.el.__annotations__.length;i<l;i++) {
|
||||
const annotation = evt.el.__annotations__[i];
|
||||
if (annotations.hasOwnProperty(annotation.id)) {
|
||||
|
@ -42,15 +42,17 @@ RED.view.annotations = (function() {
|
|||
}
|
||||
if (isBadge) {
|
||||
if (showAnnotation) {
|
||||
const rect = annotation.element.getBoundingClientRect();
|
||||
// getBoundingClientRect is in real-world scale so needs to be adjusted according to
|
||||
// the current scale factor
|
||||
const rectWidth = annotation.element.getBoundingClientRect().width / scale;
|
||||
let annotationX
|
||||
if (!opts.align || opts.align === 'right') {
|
||||
annotationX = evt.node.w - 3 - badgeRDX - rect.width
|
||||
badgeRDX += rect.width + 4;
|
||||
annotationX = evt.node.w - 3 - badgeRDX - rectWidth
|
||||
badgeRDX += rectWidth + 4;
|
||||
|
||||
} else if (opts.align === 'left') {
|
||||
annotationX = 3 + badgeLDX
|
||||
badgeLDX += rect.width + 4;
|
||||
badgeLDX += rectWidth + 4;
|
||||
}
|
||||
annotation.element.setAttribute("transform", "translate("+annotationX+", -8)");
|
||||
}
|
||||
|
|
|
@ -1154,11 +1154,11 @@ RED.view.tools = (function() {
|
|||
}
|
||||
}
|
||||
|
||||
function addJunctionsToWires(wires) {
|
||||
function addJunctionsToWires(options = {}) {
|
||||
if (RED.workspaces.isLocked()) {
|
||||
return
|
||||
}
|
||||
let wiresToSplit = wires || (RED.view.selection().links && RED.view.selection().links.filter(e => !e.link));
|
||||
let wiresToSplit = options.wires || (RED.view.selection().links && RED.view.selection().links.filter(e => !e.link));
|
||||
if (!wiresToSplit) {
|
||||
return
|
||||
}
|
||||
|
@ -1206,21 +1206,26 @@ RED.view.tools = (function() {
|
|||
if (links.length === 0) {
|
||||
return
|
||||
}
|
||||
let pointCount = 0
|
||||
links.forEach(function(l) {
|
||||
if (l._sliceLocation) {
|
||||
junction.x += l._sliceLocation.x
|
||||
junction.y += l._sliceLocation.y
|
||||
delete l._sliceLocation
|
||||
pointCount++
|
||||
} else {
|
||||
junction.x += l.source.x + l.source.w/2 + l.target.x - l.target.w/2
|
||||
junction.y += l.source.y + l.target.y
|
||||
pointCount += 2
|
||||
}
|
||||
})
|
||||
junction.x = Math.round(junction.x/pointCount)
|
||||
junction.y = Math.round(junction.y/pointCount)
|
||||
if (addedJunctions.length === 0 && Object.hasOwn(options, 'x') && Object.hasOwn(options, 'y')) {
|
||||
junction.x = options.x
|
||||
junction.y = options.y
|
||||
} else {
|
||||
let pointCount = 0
|
||||
links.forEach(function(l) {
|
||||
if (l._sliceLocation) {
|
||||
junction.x += l._sliceLocation.x
|
||||
junction.y += l._sliceLocation.y
|
||||
delete l._sliceLocation
|
||||
pointCount++
|
||||
} else {
|
||||
junction.x += l.source.x + l.source.w/2 + l.target.x - l.target.w/2
|
||||
junction.y += l.source.y + l.target.y
|
||||
pointCount += 2
|
||||
}
|
||||
})
|
||||
junction.x = Math.round(junction.x/pointCount)
|
||||
junction.y = Math.round(junction.y/pointCount)
|
||||
}
|
||||
if (RED.view.snapGrid) {
|
||||
let gridSize = RED.view.gridSize()
|
||||
junction.x = (gridSize*Math.round(junction.x/gridSize));
|
||||
|
@ -1410,7 +1415,7 @@ RED.view.tools = (function() {
|
|||
RED.actions.add("core:wire-multiple-to-node", function() { wireMultipleToNode() })
|
||||
|
||||
RED.actions.add("core:split-wire-with-link-nodes", function () { splitWiresWithLinkNodes() });
|
||||
RED.actions.add("core:split-wires-with-junctions", function () { addJunctionsToWires() });
|
||||
RED.actions.add("core:split-wires-with-junctions", function (options) { addJunctionsToWires(options) });
|
||||
|
||||
RED.actions.add("core:generate-node-names", generateNodeNames )
|
||||
|
||||
|
|
|
@ -321,8 +321,8 @@ RED.view = (function() {
|
|||
evt.stopPropagation()
|
||||
RED.contextMenu.show({
|
||||
type: 'workspace',
|
||||
x:evt.clientX-5,
|
||||
y:evt.clientY-5
|
||||
x: evt.clientX,
|
||||
y: evt.clientY
|
||||
})
|
||||
return false
|
||||
})
|
||||
|
@ -5174,8 +5174,8 @@ RED.view = (function() {
|
|||
var delta = Infinity;
|
||||
for (var i = 0; i < lineLength; i++) {
|
||||
var linePos = pathLine.getPointAtLength(i);
|
||||
var posDeltaX = Math.abs(linePos.x-d3.event.offsetX)
|
||||
var posDeltaY = Math.abs(linePos.y-d3.event.offsetY)
|
||||
var posDeltaX = Math.abs(linePos.x-(d3.event.offsetX / scaleFactor))
|
||||
var posDeltaY = Math.abs(linePos.y-(d3.event.offsetY / scaleFactor))
|
||||
var posDelta = posDeltaX*posDeltaX + posDeltaY*posDeltaY
|
||||
if (posDelta < delta) {
|
||||
pos = linePos
|
||||
|
|
|
@ -339,7 +339,7 @@ module.exports = function(RED) {
|
|||
}
|
||||
else {
|
||||
msg.filename = filename;
|
||||
var lines = Buffer.from([]);
|
||||
const bufferArray = [];
|
||||
var spare = "";
|
||||
var count = 0;
|
||||
var type = "buffer";
|
||||
|
@ -397,7 +397,7 @@ module.exports = function(RED) {
|
|||
}
|
||||
}
|
||||
else {
|
||||
lines = Buffer.concat([lines,chunk]);
|
||||
bufferArray.push(chunk);
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -413,10 +413,11 @@ module.exports = function(RED) {
|
|||
})
|
||||
.on('end', function() {
|
||||
if (node.chunk === false) {
|
||||
const buffer = Buffer.concat(bufferArray);
|
||||
if (node.format === "utf8") {
|
||||
msg.payload = decode(lines, node.encoding);
|
||||
msg.payload = decode(buffer, node.encoding);
|
||||
}
|
||||
else { msg.payload = lines; }
|
||||
else { msg.payload = buffer; }
|
||||
nodeSend(msg);
|
||||
}
|
||||
else if (node.format === "lines") {
|
||||
|
|
Loading…
Reference in New Issue