Compare commits

..

1 Commits

Author SHA1 Message Date
Dave Conway-Jones
fc657ecc71 let delay node handle both flush then reset
and add tests
2022-09-22 10:51:48 +01:00
11 changed files with 455 additions and 419 deletions

View File

@@ -152,7 +152,6 @@ module.exports = function(grunt) {
"packages/node_modules/@node-red/editor-client/src/js/history.js",
"packages/node_modules/@node-red/editor-client/src/js/validators.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/utils.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/utils-domselection.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/common/editableList.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/common/treeList.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/common/checkboxSet.js",

View File

@@ -267,7 +267,7 @@ RED.keyboard = (function() {
return resolveKeyEvent(evt);
}
if (Object.keys(handler).length > 0) {
// check if there's a potential combined handler initiated by this keyCode
// check if there's a potential combined handler initiated by this keyCode
for (let h in handler) {
if (matchHandlerToEvent(evt,handler[h]) > -1) {
partialState = handler;
@@ -298,21 +298,21 @@ RED.keyboard = (function() {
return resolveKeyEvent(evt);
}
}
document.addEventListener("keydown", function(event) {
d3.select(window).on("keydown",function() {
if (!handlersActive) {
return;
}
if (metaKeyCodes[event.keyCode]) {
if (metaKeyCodes[d3.event.keyCode]) {
return;
}
var handler = resolveKeyEvent(event);
var handler = resolveKeyEvent(d3.event);
if (handler && handler.ondown) {
if (typeof handler.ondown === "string") {
RED.actions.invoke(handler.ondown);
} else {
handler.ondown();
}
event.preventDefault();
d3.event.preventDefault();
}
});

View File

@@ -299,7 +299,7 @@ RED.palette = (function() {
RED.view.focus();
},
stop: function() {
document.querySelectorAll(".red-ui-flow-link-splice").forEach(n => { n.classList.remove("red-ui-flow-link-splice") })
d3.select('.red-ui-flow-link-splice').classed('red-ui-flow-link-splice',false);
if (hoverGroup) {
document.getElementById("group_select_"+hoverGroup.id).classList.remove("red-ui-flow-group-hovered");
}
@@ -358,26 +358,26 @@ RED.palette = (function() {
var mx = mouseX / RED.view.scale();
var my = mouseY / RED.view.scale();
for (var i=0;i<nodes.length;i++) {
var node = nodes[i];
if (node.classList.contains('red-ui-flow-link-background') && !node.classList.contains('red-ui-flow-link-link')) {
var length = node.getTotalLength();
var node = d3.select(nodes[i]);
if (node.classed('red-ui-flow-link-background') && !node.classed('red-ui-flow-link-link')) {
var length = nodes[i].getTotalLength();
for (var j=0;j<length;j+=10) {
var p = node.getPointAtLength(j);
var p = nodes[i].getPointAtLength(j);
var d2 = ((p.x-mx)*(p.x-mx))+((p.y-my)*(p.y-my));
if (d2 < 200 && d2 < bestDistance) {
bestDistance = d2;
bestLink = node;
bestLink = nodes[i];
}
}
}
}
if (activeSpliceLink && activeSpliceLink !== bestLink) {
activeSpliceLink.parentNode.classList.remove('red-ui-flow-link-splice');
d3.select(activeSpliceLink.parentNode).classed('red-ui-flow-link-splice',false);
}
if (bestLink) {
bestLink.parentNode.classList.add('red-ui-flow-link-splice');
d3.select(bestLink.parentNode).classed('red-ui-flow-link-splice',true)
} else {
document.querySelectorAll(".red-ui-flow-link-splice").forEach(n => { n.classList.remove("red-ui-flow-link-splice") })
d3.select('.red-ui-flow-link-splice').classed('red-ui-flow-link-splice',false);
}
if (activeSpliceLink !== bestLink) {
if (bestLink) {

View File

@@ -27,24 +27,26 @@ RED.touch.radialMenu = (function() {
function createRadial(obj,pos,options) {
isActive = true;
try {
touchMenu = $('<div>', {class: 'red-ui-editor-radial-menu'}).appendTo('body')
.on('touchstart',function(evt) {
touchMenu = d3.select("body").append("div").classed("red-ui-editor-radial-menu",true)
.on('touchstart',function() {
hide();
evt.preventDefault();
d3.event.preventDefault();
});
var menu = $('<div>').appendTo(touchMenu).css({
var menu = touchMenu.append("div")
.style({
top: (pos[1]-80)+"px",
left:(pos[0]-80)+"px",
});
var menuOpts = [];
var createMenuOpt = function(x,y,opt) {
opt.el = $('<div>', {class: 'red-ui-editor-radial-menu-opt'}).appendTo(menu)
.css({
opt.el = menu.append("div").classed("red-ui-editor-radial-menu-opt",true)
.style({
top: (y+80-25)+"px",
left:(x+80-25)+"px"
})
.toggleClass("red-ui-editor-radial-menu-opt-disabled",!!opt.disabled)
.classed("red-ui-editor-radial-menu-opt-disabled",!!opt.disabled)
opt.el.html(opt.name);
@@ -52,16 +54,16 @@ RED.touch.radialMenu = (function() {
opt.y = y;
menuOpts.push(opt);
opt.el.on('touchstart',function(evt) {
opt.el.toggleClass("red-ui-editor-radial-menu-opt-active",true)
evt.preventDefault();
evt.stopPropagation();
opt.el.on('touchstart',function() {
opt.el.classed("red-ui-editor-radial-menu-opt-active",true)
d3.event.preventDefault();
d3.event.stopPropagation();
});
opt.el.on('touchend',function(evt) {
opt.el.on('touchend',function() {
hide();
opt.onselect();
evt.preventDefault();
evt.stopPropagation();
d3.event.preventDefault();
d3.event.stopPropagation();
});
}
@@ -86,8 +88,8 @@ RED.touch.radialMenu = (function() {
}
obj.on('touchend.radial',function() {
obj.off('touchend.radial');
obj.off('touchmenu.radial');
obj.on('touchend.radial',null);
obj.on('touchmenu.radial',null);
if (activeOption) {
try {
@@ -101,9 +103,9 @@ RED.touch.radialMenu = (function() {
}
});
obj.on('touchmove.radial',function(evt) {
obj.on('touchmove.radial',function() {
try {
var touch0 = evt.touches.item(0);
var touch0 = d3.event.touches.item(0);
var p = [touch0.pageX - pos[0],touch0.pageY-pos[1]];
for (var i=0;i<menuOpts.length;i++) {
var opt = menuOpts[i];
@@ -117,7 +119,7 @@ RED.touch.radialMenu = (function() {
if (opt === activeOption) {
activeOption = null;
}
opt.el.toggleClass("selected",false);
opt.el.classed("selected",false);
}
}
}

View File

@@ -1,61 +0,0 @@
/**
* Modelled after `d3.selection` this provides a way to keep a mapping of
* DOM Nodes with a data collection.
*
* The goal here is not to reproduce d3 functionality as-is, but to provide an
* api that is specific to what we need to do
*
* const domSelection = RED.utils.domSelection(container, selector, createNode, eachNode)
*
* - container - a DOM Node that is the container of the DOM Nodes to track
* - selector - CSS selector to get the DOM nodes to track
* - createNode - function called when a DOM node must be created for a piece of data.
* `this` is the data item. Should return the DOM Node. It will
* get added to the container.
* - eachNode - function called for each DOM node/data item in the selection
*
* DomSelection.refresh(data) - called whenever the selection should be refreshed.
* Data is expected to be an array of objects that contain an 'id' property
*
*/
RED.utils.domSelection = (function() {
class DomSelection {
constructor(container, selector, createNode, eachNode) {
this.container = container
this.selector = selector
this.createNode = createNode
this.eachNode = eachNode
this.data = []
}
refresh(data) {
const domNodes = this.container.querySelectorAll(this.selector)
const domItems = new Map()
const dataLength = data.length
const domLength = domNodes.length
for (let i = 0; i < domLength; i++) {
const domNode = domNodes[i]
if (domNode.__data__) {
domItems.set(domNode.__data__.id, domNode)
}
}
for (let i = 0; i < dataLength; i++) {
const datum = data[i]
let domNode = domItems.get(datum.id)
if (!domNode) {
domNode = this.createNode.call(datum)
this.container.appendChild(domNode)
domNode.__data__ = datum
} else {
domItems.delete(datum.id)
}
this.eachNode.call(datum, domNode)
}
for (const remainingDomNodes of domItems) {
remainingDomNodes[1].remove()
}
}
}
return (container, selector, createNode, eachNode) => new DomSelection(container, selector, createNode, eachNode)
})()

View File

@@ -1397,17 +1397,6 @@ RED.utils = (function() {
return r;
}
function createSVGElement(tag, attrs = {}, parent) {
const element = document.createElementNS('http://www.w3.org/2000/svg', tag)
for (const k in attrs) {
element.setAttribute(k, attrs[k])
}
if (parent) {
parent.appendChild(element)
}
return element
}
return {
createObjectElement: createObjectElement,
getMessageProperty: getMessageProperty,
@@ -1431,7 +1420,6 @@ RED.utils = (function() {
getDarkerColor: getDarkerColor,
parseModuleList: parseModuleList,
checkModuleAllowed: checkModuleAllowed,
getBrowserInfo: getBrowserInfo,
createSVGElement: createSVGElement
getBrowserInfo: getBrowserInfo
}
})();

View File

@@ -91,7 +91,8 @@ RED.view.annotations = (function() {
function addAnnotation(id,evt) {
var opts = annotations[id];
evt.el.__annotations__ = evt.el.__annotations__ || [];
var annotationGroup = RED.utils.createSVGElement("g", { class: opts.class || '' })
var annotationGroup = document.createElementNS("http://www.w3.org/2000/svg","g");
annotationGroup.setAttribute("class",opts.class || "");
evt.el.__annotations__.push({
id:id,
element: annotationGroup

View File

@@ -15,128 +15,133 @@
**/
RED.view.navigator = (function() {
var nav_scale = 25;
var nav_width = 5000/nav_scale;
var nav_height = 5000/nav_scale;
RED.view.navigator = (function() {
var navContainer;
var navBox;
var navBorder;
var scrollPos;
var scaleFactor;
var chartSize;
var dimensions;
var isDragging;
var isShowing = false;
var nav_scale = 25;
var nav_width = 5000/nav_scale;
var nav_height = 5000/nav_scale;
var domSelection
var navContainer;
var navBox;
var navBorder;
var navVis;
var scrollPos;
var scaleFactor;
var chartSize;
var dimensions;
var isDragging;
var isShowing = false;
function refreshNodes() {
if (!isShowing) {
return;
}
domSelection.refresh(RED.view.getActiveNodes())
}
function refreshNodes() {
if (!isShowing) {
return;
}
var navNode = navVis.selectAll(".red-ui-navigator-node").data(RED.view.getActiveNodes(),function(d){return d.id});
navNode.exit().remove();
navNode.enter().insert("rect")
.attr('class','red-ui-navigator-node')
.attr("pointer-events", "none");
navNode.each(function(d) {
d3.select(this).attr("x",function(d) { return (d.x-d.w/2)/nav_scale })
.attr("y",function(d) { return (d.y-d.h/2)/nav_scale })
.attr("width",function(d) { return Math.max(9,d.w/nav_scale) })
.attr("height",function(d) { return Math.max(3,d.h/nav_scale) })
.attr("fill",function(d) { return RED.utils.getNodeColor(d.type,d._def);})
});
}
function onScroll() {
if (!isDragging) {
resizeNavBorder();
}
}
function resizeNavBorder() {
if (navBorder) {
scaleFactor = RED.view.scale();
chartSize = [ $("#red-ui-workspace-chart").width(), $("#red-ui-workspace-chart").height()];
scrollPos = [$("#red-ui-workspace-chart").scrollLeft(),$("#red-ui-workspace-chart").scrollTop()];
navBorder.attr('x',scrollPos[0]/nav_scale)
.attr('y',scrollPos[1]/nav_scale)
.attr('width',chartSize[0]/nav_scale/scaleFactor)
.attr('height',chartSize[1]/nav_scale/scaleFactor)
}
}
function toggle() {
if (!isShowing) {
isShowing = true;
$("#red-ui-view-navigate").addClass("selected");
resizeNavBorder();
refreshNodes();
$("#red-ui-workspace-chart").on("scroll",onScroll);
navContainer.fadeIn(200);
} else {
isShowing = false;
navContainer.fadeOut(100);
$("#red-ui-workspace-chart").off("scroll",onScroll);
$("#red-ui-view-navigate").removeClass("selected");
}
}
function onScroll() {
if (!isDragging) {
resizeNavBorder();
}
}
function resizeNavBorder() {
if (navBorder) {
scaleFactor = RED.view.scale();
chartSize = [ $("#red-ui-workspace-chart").width(), $("#red-ui-workspace-chart").height()];
scrollPos = [$("#red-ui-workspace-chart").scrollLeft(),$("#red-ui-workspace-chart").scrollTop()];
return {
init: function() {
navBorder.attr('x', scrollPos[0]/nav_scale)
navBorder.attr('y', scrollPos[1]/nav_scale)
navBorder.attr('width',chartSize[0]/nav_scale/scaleFactor)
navBorder.attr('height',chartSize[1]/nav_scale/scaleFactor)
}
}
function toggle() {
if (!isShowing) {
isShowing = true;
$("#red-ui-view-navigate").addClass("selected");
resizeNavBorder();
refreshNodes();
$("#red-ui-workspace-chart").on("scroll",onScroll);
navContainer.fadeIn(200);
} else {
isShowing = false;
navContainer.fadeOut(100);
$("#red-ui-workspace-chart").off("scroll",onScroll);
$("#red-ui-view-navigate").removeClass("selected");
}
}
$(window).on("resize", resizeNavBorder);
RED.events.on("sidebar:resize",resizeNavBorder);
RED.actions.add("core:toggle-navigator",toggle);
var hideTimeout;
return {
init: function() {
navContainer = $('<div>').css({
"position":"absolute",
"bottom":$("#red-ui-workspace-footer").height(),
"right":0,
zIndex: 1
}).appendTo("#red-ui-workspace").hide();
$(window).on("resize", resizeNavBorder);
RED.events.on("sidebar:resize",resizeNavBorder);
RED.actions.add("core:toggle-navigator",toggle);
navBox = d3.select(navContainer[0])
.append("svg:svg")
.attr("width", nav_width)
.attr("height", nav_height)
.attr("pointer-events", "all")
.attr("id","red-ui-navigator-canvas")
navContainer = $('<div>').css({
"position":"absolute",
"bottom":$("#red-ui-workspace-footer").height(),
"right":0,
zIndex: 1
}).appendTo("#red-ui-workspace").hide();
navBox.append("rect").attr("x",0).attr("y",0).attr("width",nav_width).attr("height",nav_height).style({
fill:"none",
stroke:"none",
pointerEvents:"all"
}).on("mousedown", function() {
// Update these in case they have changed
scaleFactor = RED.view.scale();
chartSize = [ $("#red-ui-workspace-chart").width(), $("#red-ui-workspace-chart").height()];
dimensions = [chartSize[0]/nav_scale/scaleFactor, chartSize[1]/nav_scale/scaleFactor];
var newX = Math.max(0,Math.min(d3.event.offsetX+dimensions[0]/2,nav_width)-dimensions[0]);
var newY = Math.max(0,Math.min(d3.event.offsetY+dimensions[1]/2,nav_height)-dimensions[1]);
navBorder.attr('x',newX).attr('y',newY);
isDragging = true;
$("#red-ui-workspace-chart").scrollLeft(newX*nav_scale*scaleFactor);
$("#red-ui-workspace-chart").scrollTop(newY*nav_scale*scaleFactor);
}).on("mousemove", function() {
if (!isDragging) { return }
if (d3.event.buttons === 0) {
isDragging = false;
return;
}
var newX = Math.max(0,Math.min(d3.event.offsetX+dimensions[0]/2,nav_width)-dimensions[0]);
var newY = Math.max(0,Math.min(d3.event.offsetY+dimensions[1]/2,nav_height)-dimensions[1]);
navBorder.attr('x',newX).attr('y',newY);
$("#red-ui-workspace-chart").scrollLeft(newX*nav_scale*scaleFactor);
$("#red-ui-workspace-chart").scrollTop(newY*nav_scale*scaleFactor);
}).on("mouseup", function() {
isDragging = false;
})
navBox = $(RED.utils.createSVGElement('svg', {id: "red-ui-navigator-canvas", width: nav_width, height: nav_height, 'pointer-events': 'all'})).appendTo(navContainer)
navBorder = navBox.append("rect").attr("class","red-ui-navigator-border")
const navBoxBody = $(RED.utils.createSVGElement("rect", { x: 0, y: 0, width: nav_width, height: nav_height, fill: 'none', stroke: 'none', 'pointer-events': 'all'}))
.css({'cursor': 'pointer'})
navBoxBody.on('mousedown',function(event) {
// Update these in case they have changed
scaleFactor = RED.view.scale();
chartSize = [ $("#red-ui-workspace-chart").width(), $("#red-ui-workspace-chart").height()];
dimensions = [chartSize[0]/nav_scale/scaleFactor, chartSize[1]/nav_scale/scaleFactor];
var newX = Math.max(0,Math.min(event.offsetX+dimensions[0]/2,nav_width)-dimensions[0]);
var newY = Math.max(0,Math.min(event.offsetY+dimensions[1]/2,nav_height)-dimensions[1]);
navBorder.attr('x',newX)
navBorder.attr('y',newY);
isDragging = true;
$("#red-ui-workspace-chart").scrollLeft(newX*nav_scale*scaleFactor);
$("#red-ui-workspace-chart").scrollTop(newY*nav_scale*scaleFactor);
}).on('mousemove', function(event) {
if (!isDragging) { return }
if (event.buttons === 0) {
isDragging = false;
return;
}
var newX = Math.max(0,Math.min(event.offsetX+dimensions[0]/2,nav_width)-dimensions[0]);
var newY = Math.max(0,Math.min(event.offsetY+dimensions[1]/2,nav_height)-dimensions[1]);
navBorder.attr('x',newX)
navBorder.attr('y',newY);
$("#red-ui-workspace-chart").scrollLeft(newX*nav_scale*scaleFactor);
$("#red-ui-workspace-chart").scrollTop(newY*nav_scale*scaleFactor);
}).on('mouseup', function() {
isDragging = false;
}).appendTo(navBox)
navVis = navBox.append("svg:g")
navBorder = $(RED.utils.createSVGElement("rect", { "class": "red-ui-navigator-border" })).appendTo(navBox)
const navVis = $(RED.utils.createSVGElement('g')).appendTo(navBox)
domSelection = RED.utils.domSelection(navVis[0], '.red-ui-navigator-node', function() {
return RED.utils.createSVGElement('rect', { class: 'red-ui-navigator-node', 'pointer-events': 'none' })
}, function(node) {
node.setAttribute('x', (this.x-this.w/2)/nav_scale)
node.setAttribute('y', (this.y-this.h/2)/nav_scale)
node.setAttribute('width', Math.max(9,this.w/nav_scale))
node.setAttribute('height', Math.max(3,this.h/nav_scale))
node.setAttribute('fill', RED.utils.getNodeColor(this.type,this._def))
})
RED.statusBar.add({
id: "view-navigator",
align: "right",
element: $('<button class="red-ui-footer-button-toggle single" id="red-ui-view-navigate"><i class="fa fa-map-o"></i></button>')
})
RED.statusBar.add({
id: "view-navigator",
align: "right",
element: $('<button class="red-ui-footer-button-toggle single" id="red-ui-view-navigate"><i class="fa fa-map-o"></i></button>')
})
$("#red-ui-view-navigate").on("click", function(evt) {
evt.preventDefault();

View File

@@ -294,13 +294,25 @@ RED.view = (function() {
]
startTouchDistance = Math.sqrt((a*a)+(b*b));
} else {
var obj = d3.select(document.body);
touch0 = d3.event.touches.item(0);
var pos = [touch0.pageX,touch0.pageY];
startTouchCenter = [touch0.pageX,touch0.pageY];
startTouchDistance = 0;
var point = d3.touches(this)[0];
touchStartTime = setTimeout(function() {
touchStartTime = null;
showTouchMenu(document.body,pos);
showTouchMenu(obj,pos);
//lasso = eventLayer.append("rect")
// .attr("ox",point[0])
// .attr("oy",point[1])
// .attr("rx",2)
// .attr("ry",2)
// .attr("x",point[0])
// .attr("y",point[1])
// .attr("width",0)
// .attr("height",0)
// .attr("class","nr-ui-view-lasso");
},touchLongPressTimeout);
}
d3.event.preventDefault();
@@ -700,11 +712,11 @@ RED.view = (function() {
type: "badge",
class: "red-ui-flow-node-changed",
element: function() {
return RED.utils.createSVGElement("circle", {
cx: 5,
cy: 5,
r: 5
})
var changeBadge = document.createElementNS("http://www.w3.org/2000/svg","circle");
changeBadge.setAttribute("cx",5);
changeBadge.setAttribute("cy",5);
changeBadge.setAttribute("r",5);
return changeBadge;
},
show: function(n) { return n.changed||n.moved }
})
@@ -713,9 +725,9 @@ RED.view = (function() {
type: "badge",
class: "red-ui-flow-node-error",
element: function(d) {
return RED.utils.createSVGElement("path", {
d: "M 0,9 l 10,0 -5,-8 z"
})
var errorBadge = document.createElementNS("http://www.w3.org/2000/svg","path");
errorBadge.setAttribute("d","M 0,9 l 10,0 -5,-8 z");
return errorBadge
},
tooltip: function(d) {
if (d.validationErrors && d.validationErrors.length > 0) {
@@ -3691,12 +3703,13 @@ RED.view = (function() {
}
function nodeTouchStart(d) {
if (RED.view.DEBUG) { console.warn("nodeTouchStart", mouse_mode,d); }
var obj = d3.select(this);
var touch0 = d3.event.touches.item(0);
var pos = [touch0.pageX,touch0.pageY];
startTouchCenter = [touch0.pageX,touch0.pageY];
startTouchDistance = 0;
touchStartTime = setTimeout(function() {
showTouchMenu(this,pos);
showTouchMenu(obj,pos);
},touchLongPressTimeout);
nodeMouseDown.call(this,d)
d3.event.preventDefault();
@@ -3855,11 +3868,12 @@ RED.view = (function() {
focusView();
d3.event.stopPropagation();
var obj = d3.select(document.body);
var touch0 = d3.event.touches.item(0);
var pos = [touch0.pageX,touch0.pageY];
touchStartTime = setTimeout(function() {
touchStartTime = null;
showTouchMenu(document.body,pos);
showTouchMenu(obj,pos);
},touchLongPressTimeout);
d3.event.preventDefault();
}
@@ -4233,14 +4247,13 @@ RED.view = (function() {
d.resize = true;
d.dirty = true;
var mainRect = RED.utils.createSVGElement("rect", {
class: "red-ui-flow-subflow-port",
rx: 8,
ry: 8,
width: 40,
height: 40,
})
var mainRect = document.createElementNS("http://www.w3.org/2000/svg","rect");
mainRect.__data__ = d;
mainRect.setAttribute("class", "red-ui-flow-subflow-port");
mainRect.setAttribute("rx", 8);
mainRect.setAttribute("ry", 8);
mainRect.setAttribute("width", 40);
mainRect.setAttribute("height", 40);
node[0][0].__mainRect__ = mainRect;
d3.select(mainRect)
.on("mouseup",nodeMouseUp)
@@ -4249,50 +4262,50 @@ RED.view = (function() {
.on("touchend",nodeTouchEnd)
nodeContents.appendChild(mainRect);
var output_groupEl = RED.utils.createSVGElement("g", { x: 0, y: 0 })
var output_groupEl = document.createElementNS("http://www.w3.org/2000/svg","g");
output_groupEl.setAttribute("x",0);
output_groupEl.setAttribute("y",0);
node[0][0].__outputLabelGroup__ = output_groupEl;
var output_output = RED.utils.createSVGElement("text", { class: "red-ui-flow-port-label" })
var output_output = document.createElementNS("http://www.w3.org/2000/svg","text");
output_output.setAttribute("class","red-ui-flow-port-label");
output_output.style["font-size"] = "10px";
output_output.textContent = "output";
output_groupEl.appendChild(output_output);
node[0][0].__outputOutput__ = output_output;
var output_number = RED.utils.createSVGElement("text", {
class: "red-ui-flow-port-label red-ui-flow-port-index",
x: 0,
y: 0
})
var output_number = document.createElementNS("http://www.w3.org/2000/svg","text");
output_number.setAttribute("class","red-ui-flow-port-label red-ui-flow-port-index");
output_number.setAttribute("x",0);
output_number.setAttribute("y",0);
output_number.textContent = d.i+1;
output_groupEl.appendChild(output_number);
node[0][0].__outputNumber__ = output_number;
var output_border = RED.utils.createSVGElement("path", {
d: "M 40 1 l 0 38",
class: "red-ui-flow-node-icon-shade-border"
})
var output_border = document.createElementNS("http://www.w3.org/2000/svg","path");
output_border.setAttribute("d","M 40 1 l 0 38")
output_border.setAttribute("class", "red-ui-flow-node-icon-shade-border")
output_groupEl.appendChild(output_border);
node[0][0].__outputBorder__ = output_border;
nodeContents.appendChild(output_groupEl);
var text = RED.utils.createSVGElement("g", {
class: "red-ui-flow-port-label",
transform: "translate(38,0)",
style: 'fill : #888' // hard coded here!
})
var text = document.createElementNS("http://www.w3.org/2000/svg","g");
text.setAttribute("class","red-ui-flow-port-label");
text.setAttribute("transform","translate(38,0)");
text.setAttribute('style', 'fill : #888'); // hard coded here!
node[0][0].__textGroup__ = text;
nodeContents.append(text);
var portEl = RED.utils.createSVGElement("g", { transform: 'translate(-5,15)'})
var portEl = document.createElementNS("http://www.w3.org/2000/svg","g");
portEl.setAttribute('transform','translate(-5,15)')
var port = RED.utils.createSVGElement("rect", {
class: "red-ui-flow-port",
rx: 3,
ry: 3,
width: 10,
height: 10
})
var port = document.createElementNS("http://www.w3.org/2000/svg","rect");
port.setAttribute("class","red-ui-flow-port");
port.setAttribute("rx",3);
port.setAttribute("ry",3);
port.setAttribute("width",10);
port.setAttribute("height",10);
portEl.appendChild(port);
port.__data__ = d;
@@ -4421,11 +4434,10 @@ RED.view = (function() {
}
for (var i=0; i<sn; i++) {
if (i===textLines.length) {
var line = RED.utils.createSVGElement("text", {
class: "red-ui-flow-node-label-text",
x: 0,
y: i*24
});
var line = document.createElementNS("http://www.w3.org/2000/svg","text");
line.setAttribute("class","red-ui-flow-node-label-text");
line.setAttribute("x",0);
line.setAttribute("y",i*24);
this.__textGroup__.appendChild(line);
}
textLines[i].textContent = sa[i];
@@ -4495,35 +4507,32 @@ RED.view = (function() {
d.resize = true;
if (d._def.button) {
var buttonGroup = RED.utils.createSVGElement("g", {
class: "red-ui-flow-node-button",
transform: "translate("+((d._def.align == "right") ? 94 : -25)+",2)"
})
var buttonGroup = document.createElementNS("http://www.w3.org/2000/svg","g");
buttonGroup.__data__ = d;
buttonGroup.setAttribute("transform", "translate("+((d._def.align == "right") ? 94 : -25)+",2)");
buttonGroup.setAttribute("class","red-ui-flow-node-button");
node[0][0].__buttonGroup__ = buttonGroup;
var bgBackground = RED.utils.createSVGElement("rect", {
class: "red-ui-flow-node-button-background",
rx: 5,
ry: 5,
width: 32,
height: node_height-4
})
var bgBackground = document.createElementNS("http://www.w3.org/2000/svg","rect");
bgBackground.__data__ = d;
bgBackground.setAttribute("class","red-ui-flow-node-button-background");
bgBackground.setAttribute("rx",5);
bgBackground.setAttribute("ry",5);
bgBackground.setAttribute("width",32);
bgBackground.setAttribute("height",node_height-4);
buttonGroup.appendChild(bgBackground);
node[0][0].__buttonGroupBackground__ = bgBackground;
var bgButton = RED.utils.createSVGElement("rect", {
class: "red-ui-flow-node-button-button",
x: d._def.align == "right"? 11:5,
y: 4,
rx: 4,
ry: 4,
width: 16,
height: node_height-12,
fill: RED.utils.getNodeColor(d.type,d._def)
})
var bgButton = document.createElementNS("http://www.w3.org/2000/svg","rect");
bgButton.__data__ = d;
bgButton.setAttribute("class","red-ui-flow-node-button-button");
bgButton.setAttribute("x", d._def.align == "right"? 11:5);
bgButton.setAttribute("y",4);
bgButton.setAttribute("rx",4);
bgButton.setAttribute("ry",4);
bgButton.setAttribute("width",16);
bgButton.setAttribute("height",node_height-12);
bgButton.setAttribute("fill", RED.utils.getNodeColor(d.type,d._def));
d3.select(bgButton)
.on("mousedown",function(d) {if (!lasso && isButtonEnabled(d)) {focusView();d3.select(this).attr("fill-opacity",0.2);d3.event.preventDefault(); d3.event.stopPropagation();}})
.on("mouseup",function(d) {if (!lasso && isButtonEnabled(d)) { d3.select(this).attr("fill-opacity",0.4);d3.event.preventDefault();d3.event.stopPropagation();}})
@@ -4544,13 +4553,12 @@ RED.view = (function() {
}
var mainRect = RED.utils.createSVGElement("rect", {
class: "red-ui-flow-node "+(d.type == "unknown"?"red-ui-flow-node-unknown":""),
rx: 5,
ry: 5,
fill: RED.utils.getNodeColor(d.type,d._def)
})
var mainRect = document.createElementNS("http://www.w3.org/2000/svg","rect");
mainRect.__data__ = d;
mainRect.setAttribute("class", "red-ui-flow-node "+(d.type == "unknown"?"red-ui-flow-node-unknown":""));
mainRect.setAttribute("rx", 5);
mainRect.setAttribute("ry", 5);
mainRect.setAttribute("fill", RED.utils.getNodeColor(d.type,d._def));
node[0][0].__mainRect__ = mainRect;
d3.select(mainRect)
.on("mouseup",nodeMouseUp)
@@ -4565,65 +4573,61 @@ RED.view = (function() {
if (d._def.icon) {
var icon_url = RED.utils.getNodeIcon(d._def,d);
var icon_groupEl = RED.utils.createSVGElement("g", {
class: "red-ui-flow-node-icon-group"+("right" == d._def.align?" red-ui-flow-node-icon-group-right":""),
x: 0,
y: 0
})
icon_groupEl.style["pointer-events"] = "none";
var icon_groupEl = document.createElementNS("http://www.w3.org/2000/svg","g");
icon_groupEl.__data__ = d;
icon_groupEl.setAttribute("class","red-ui-flow-node-icon-group"+("right" == d._def.align?" red-ui-flow-node-icon-group-right":""));
icon_groupEl.setAttribute("x",0);
icon_groupEl.setAttribute("y",0);
icon_groupEl.style["pointer-events"] = "none";
node[0][0].__iconGroup__ = icon_groupEl;
var icon_shade = RED.utils.createSVGElement("path", {
x: 0,
y: 0,
class: "red-ui-flow-node-icon-shade"
})
var icon_shade = document.createElementNS("http://www.w3.org/2000/svg","path");
icon_shade.setAttribute("x",0);
icon_shade.setAttribute("y",0);
icon_shade.setAttribute("class","red-ui-flow-node-icon-shade")
icon_groupEl.appendChild(icon_shade);
node[0][0].__iconShade__ = icon_shade;
var icon_group = d3.select(icon_groupEl)
createIconAttributes(icon_url, icon_group, d);
var icon_shade_border = RED.utils.createSVGElement("path", {
d: "right" != d._def.align ? "M 30 1 l 0 "+(d.h-2) : "M 0 1 l 0 "+(d.h-2),
class: "red-ui-flow-node-icon-shade-border"
})
var icon_shade_border = document.createElementNS("http://www.w3.org/2000/svg","path");
icon_shade_border.setAttribute("d","right" != d._def.align ? "M 30 1 l 0 "+(d.h-2) : "M 0 1 l 0 "+(d.h-2) )
icon_shade_border.setAttribute("class", "red-ui-flow-node-icon-shade-border")
icon_groupEl.appendChild(icon_shade_border);
node[0][0].__iconShadeBorder__ = icon_shade_border;
nodeContents.appendChild(icon_groupEl);
}
var text = RED.utils.createSVGElement("g", {
class: "red-ui-flow-node-label"+(hideLabel?" hide":"")+(d._def.align?" red-ui-flow-node-label-"+d._def.align:""),
transform: "translate(38,0)"
// dy: ".3px",
// "text-anchor": d._def.align !== "right" ? "start":"end"
})
var text = document.createElementNS("http://www.w3.org/2000/svg","g");
text.setAttribute("class","red-ui-flow-node-label"+(hideLabel?" hide":"")+(d._def.align?" red-ui-flow-node-label-"+d._def.align:""));
text.setAttribute("transform","translate(38,0)");
// text.setAttribute("dy", ".3px");
// text.setAttribute("text-anchor",d._def.align !== "right" ? "start":"end");
nodeContents.appendChild(text);
node[0][0].__textGroup__ = text;
var statusEl = RED.utils.createSVGElement("g", { class: "red-ui-flow-node-status-group" })
var statusEl = document.createElementNS("http://www.w3.org/2000/svg","g");
// statusEl.__data__ = d;
statusEl.setAttribute("class","red-ui-flow-node-status-group");
statusEl.style.display = "none";
node[0][0].__statusGroup__ = statusEl;
var statusRect = RED.utils.createSVGElement("rect", {
class: "red-ui-flow-node-status",
x: 6,
y: 1,
width: 9,
height: 9,
rx: 2,
ry: 2,
"stroke-width": 3
})
var statusRect = document.createElementNS("http://www.w3.org/2000/svg","rect");
statusRect.setAttribute("class","red-ui-flow-node-status");
statusRect.setAttribute("x",6);
statusRect.setAttribute("y",1);
statusRect.setAttribute("width",9);
statusRect.setAttribute("height",9);
statusRect.setAttribute("rx",2);
statusRect.setAttribute("ry",2);
statusRect.setAttribute("stroke-width","3");
statusEl.appendChild(statusRect);
node[0][0].__statusShape__ = statusRect;
var statusLabel = RED.utils.createSVGElement("text", {
class: "red-ui-flow-node-status-label",
x: 20,
y: 10
})
var statusLabel = document.createElementNS("http://www.w3.org/2000/svg","text");
statusLabel.setAttribute("class","red-ui-flow-node-status-label");
statusLabel.setAttribute("x",20);
statusLabel.setAttribute("y",10);
statusEl.appendChild(statusLabel);
node[0][0].__statusLabel__ = statusLabel;
@@ -4708,11 +4712,10 @@ RED.view = (function() {
}
for (var i=0; i<sn; i++) {
if (i===textLines.length) {
var line = RED.utils.createSVGElement("text", {
class: "red-ui-flow-node-label-text",
x: 0,
y: i*24
})
var line = document.createElementNS("http://www.w3.org/2000/svg","text");
line.setAttribute("class","red-ui-flow-node-label-text");
line.setAttribute("x",0);
line.setAttribute("y",i*24);
this.__textGroup__.appendChild(line);
}
textLines[i].textContent = sa[i];
@@ -4811,23 +4814,22 @@ RED.view = (function() {
for(var portIndex = 0; portIndex < numOutputs; portIndex++ ) {
var portGroup;
if (portIndex === this.__outputs__.length) {
portGroup = RED.utils.createSVGElement("g", { class: "red-ui-flow-port-output" })
portGroup = document.createElementNS("http://www.w3.org/2000/svg","g");
portGroup.setAttribute("class","red-ui-flow-port-output");
var portPort;
if (d.type === "link out") {
portPort = RED.utils.createSVGElement("circle", {
cx: 11,
cy: 5,
r: 5,
class: "red-ui-flow-port red-ui-flow-link-port"
})
portPort = document.createElementNS("http://www.w3.org/2000/svg","circle");
portPort.setAttribute("cx",11);
portPort.setAttribute("cy",5);
portPort.setAttribute("r",5);
portPort.setAttribute("class","red-ui-flow-port red-ui-flow-link-port");
} else {
portPort = RED.utils.createSVGElement("rect", {
rx: 3,
ry: 3,
width: 10,
height: 10,
class: "red-ui-flow-port"
})
portPort = document.createElementNS("http://www.w3.org/2000/svg","rect");
portPort.setAttribute("rx",3);
portPort.setAttribute("ry",3);
portPort.setAttribute("width",10);
portPort.setAttribute("height",10);
portPort.setAttribute("class","red-ui-flow-port");
}
portGroup.appendChild(portPort);
portGroup.__port__ = portPort;
@@ -4979,28 +4981,26 @@ RED.view = (function() {
var junction = d3.select(this);
var contents = document.createDocumentFragment();
// d.added = true;
var junctionBack = RED.utils.createSVGElement("rect", {
class: "red-ui-flow-junction-background",
x: -5,
y: -5,
width: 10,
height: 10,
rx: 3,
ry: 3
})
var junctionBack = document.createElementNS("http://www.w3.org/2000/svg","rect");
junctionBack.setAttribute("class","red-ui-flow-junction-background");
junctionBack.setAttribute("x",-5);
junctionBack.setAttribute("y",-5);
junctionBack.setAttribute("width",10);
junctionBack.setAttribute("height",10);
junctionBack.setAttribute("rx",3);
junctionBack.setAttribute("ry",3);
junctionBack.__data__ = d;
this.__junctionBack__ = junctionBack;
contents.appendChild(junctionBack);
var junctionInput = RED.utils.createSVGElement("rect", {
class: "red-ui-flow-junction-port red-ui-flow-junction-port-input",
x: -5,
y: -5,
width: 10,
height: 10,
rx: 3,
ry: 3
})
var junctionInput = document.createElementNS("http://www.w3.org/2000/svg","rect");
junctionInput.setAttribute("class","red-ui-flow-junction-port red-ui-flow-junction-port-input");
junctionInput.setAttribute("x",-5);
junctionInput.setAttribute("y",-5);
junctionInput.setAttribute("width",10);
junctionInput.setAttribute("height",10);
junctionInput.setAttribute("rx",3);
junctionInput.setAttribute("ry",3);
junctionInput.__data__ = d;
junctionInput.__portType__ = PORT_TYPE_INPUT;
junctionInput.__portIndex__ = 0;
@@ -5012,15 +5012,14 @@ RED.view = (function() {
this.__junctionInput__ = junctionInput;
contents.appendChild(junctionInput);
var junctionOutput = RED.utils.createSVGElement("rect", {
class: "red-ui-flow-junction-port red-ui-flow-junction-port-output",
x: -5,
y: -5,
width: 10,
height: 10,
rx: 3,
ry: 3,
})
var junctionOutput = document.createElementNS("http://www.w3.org/2000/svg","rect");
junctionOutput.setAttribute("class","red-ui-flow-junction-port red-ui-flow-junction-port-output");
junctionOutput.setAttribute("x",-5);
junctionOutput.setAttribute("y",-5);
junctionOutput.setAttribute("width",10);
junctionOutput.setAttribute("height",10);
junctionOutput.setAttribute("rx",3);
junctionOutput.setAttribute("ry",3);
junctionOutput.__data__ = d;
junctionOutput.__portType__ = PORT_TYPE_OUTPUT;
junctionOutput.__portIndex__ = 0;
@@ -5077,8 +5076,9 @@ RED.view = (function() {
var pathContents = document.createDocumentFragment();
d.added = true;
var pathBack = RED.utils.createSVGElement("path", { class: "red-ui-flow-link-background red-ui-flow-link-path"+(d.link?" red-ui-flow-link-link":"")})
var pathBack = document.createElementNS("http://www.w3.org/2000/svg","path");
pathBack.__data__ = d;
pathBack.setAttribute("class","red-ui-flow-link-background red-ui-flow-link-path"+(d.link?" red-ui-flow-link-link":""));
this.__pathBack__ = pathBack;
pathContents.appendChild(pathBack);
d3.select(pathBack)
@@ -5114,17 +5114,16 @@ RED.view = (function() {
}
})
var pathOutline = RED.utils.createSVGElement("path", {
class: "red-ui-flow-link-outline red-ui-flow-link-path"
})
var pathOutline = document.createElementNS("http://www.w3.org/2000/svg","path");
pathOutline.__data__ = d;
pathOutline.setAttribute("class","red-ui-flow-link-outline red-ui-flow-link-path");
this.__pathOutline__ = pathOutline;
pathContents.appendChild(pathOutline);
var pathLine = RED.utils.createSVGElement("path", {
class: "red-ui-flow-link-line red-ui-flow-link-path"+(d.link?" red-ui-flow-link-link":(activeSubflow?" red-ui-flow-subflow-link":""))
})
var pathLine = document.createElementNS("http://www.w3.org/2000/svg","path");
pathLine.__data__ = d;
pathLine.setAttribute("class","red-ui-flow-link-line red-ui-flow-link-path"+
(d.link?" red-ui-flow-link-link":(activeSubflow?" red-ui-flow-subflow-link":"")));
this.__pathLine__ = pathLine;
pathContents.appendChild(pathLine);

View File

@@ -201,6 +201,7 @@ module.exports = function(RED) {
});
node.on("close", function() { clearDelayList(); });
}
else if (node.pauseType === "random") {
node.on("input", function(msg, send, done) {
var wait = node.randomFirst + (node.diff * Math.random());
@@ -226,34 +227,19 @@ module.exports = function(RED) {
// The rate limit/queue type modes
else if (node.pauseType === "rate") {
node.on("input", function(msg, send, done) {
if (msg.hasOwnProperty("reset")) {
if (node.intervalID !== -1 ) {
clearInterval(node.intervalID);
node.intervalID = -1;
}
delete node.lastSent;
node.buffer = [];
node.rate = node.fixedrate;
node.status({fill:"blue",shape:"ring",text:0});
done();
return;
}
if (!node.drop) {
var m = RED.util.cloneMessage(msg);
delete m.flush;
delete m.lifo;
if (Object.keys(m).length > 1) {
if (node.intervalID !== -1) {
if (node.allowrate && msg.hasOwnProperty("rate") && !isNaN(parseFloat(msg.rate)) && node.rate !== msg.rate) {
node.rate = msg.rate;
if (node.allowrate && m.hasOwnProperty("rate") && !isNaN(parseFloat(m.rate)) && node.rate !== m.rate) {
node.rate = m.rate;
clearInterval(node.intervalID);
node.intervalID = setInterval(sendMsgFromBuffer, node.rate);
}
var max_msgs = maxKeptMsgsCount(node);
if ((max_msgs > 0) && (node.buffer.length >= max_msgs)) {
node.buffer = [];
node.error(RED._("delay.errors.too-many"), msg);
node.error(RED._("delay.errors.too-many"), m);
} else if (msg.toFront === true) {
node.buffer.unshift({msg: m, send: send, done: done});
node.reportDepth();
@@ -263,8 +249,8 @@ module.exports = function(RED) {
}
}
else {
if (node.allowrate && msg.hasOwnProperty("rate") && !isNaN(parseFloat(msg.rate))) {
node.rate = msg.rate;
if (node.allowrate && m.hasOwnProperty("rate") && !isNaN(parseFloat(m.rate))) {
node.rate = m.rate;
}
send(m);
node.reportDepth();
@@ -282,6 +268,8 @@ module.exports = function(RED) {
else {
while (len > 0) {
const msgInfo = node.buffer.shift();
delete msgInfo.msg.flush;
delete msgInfo.msg.reset;
if (Object.keys(msgInfo.msg).length > 1) {
node.send(msgInfo.msg);
msgInfo.done();
@@ -335,6 +323,21 @@ module.exports = function(RED) {
}
done();
}
if (msg.hasOwnProperty("reset")) {
if (msg.flush === undefined) {
if (node.intervalID !== -1 ) {
clearInterval(node.intervalID);
node.intervalID = -1;
}
delete node.lastSent;
}
node.buffer = [];
node.rate = node.fixedrate;
node.status({fill:"blue",shape:"ring",text:0});
done();
return;
}
});
node.on("close", function() {
clearInterval(node.intervalID);
@@ -387,6 +390,22 @@ module.exports = function(RED) {
node.buffer.push({msg, send, done}); // if not add to end of queue
node.reportDepth();
}
if (msg.hasOwnProperty("flush")) {
var len = node.buffer.length;
if (typeof(msg.flush) == 'number') { len = Math.min(Math.floor(msg.flush,len)); }
while (len > 0) {
const msgInfo = node.buffer.shift();
delete msgInfo.msg.flush;
delete msgInfo.msg.reset;
if (Object.keys(msgInfo.msg).length > 2) {
node.send(msgInfo.msg);
msgInfo.done();
}
len = len - 1;
}
node.status({});
done();
}
if (msg.hasOwnProperty("reset")) {
while (node.buffer.length > 0) {
const msgInfo = node.buffer.shift();
@@ -397,21 +416,6 @@ module.exports = function(RED) {
node.status({text:"reset"});
done();
}
if (msg.hasOwnProperty("flush")) {
var len = node.buffer.length;
if (typeof(msg.flush) == 'number') { len = Math.min(Math.floor(msg.flush,len)); }
while (len > 0) {
const msgInfo = node.buffer.shift();
delete msgInfo.msg.flush;
if (Object.keys(msgInfo.msg).length > 2) {
node.send(msgInfo.msg);
msgInfo.done();
}
len = len - 1;
}
node.status({});
done();
}
});
node.on("close", function() {
clearInterval(node.intervalID);

View File

@@ -817,6 +817,105 @@ describe('delay Node', function() {
});
});
it('can part flush and reset rate limit queue', function(done) {
this.timeout(2000);
var flow = [{"id":"delayNode1","type":"delay","name":"delayNode","pauseType":"rate","timeout":1,"timeoutUnits":"seconds","rate":1,"rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"wires":[["helperNode1"]]},
{id:"helperNode1", type:"helper", wires:[]}];
helper.load(delayNode, flow, function() {
var delayNode1 = helper.getNode("delayNode1");
var helperNode1 = helper.getNode("helperNode1");
var t = Date.now();
var c = 0;
helperNode1.on("input", function(msg) {
// console.log("GOT",Date.now() - t,msg)
msg.should.have.a.property('payload');
msg.should.have.a.property('topic');
try {
if (msg.topic === "foo") {
msg.payload.should.equal(1);
(Date.now() - t).should.be.approximately(0,50);
c = c + 1;
}
else if (msg.topic === "bar") {
msg.payload.should.equal(2);
(Date.now() - t).should.be.approximately(200,100);
c = c + 1;
}
else if (msg.topic === "fob") {
msg.payload.should.equal(5);
(Date.now() - t).should.be.approximately(400,100);
c = 5;
}
if (c === 5) { done(); }
} catch(e) {
done(e);
}
});
// send test messages
// delayNode1.receive({payload:1,topic:"foo"});
setImmediate( function() { delayNode1.receive({payload:1,topic:"foo"}); } );
setTimeout( function() { delayNode1.receive({payload:2,topic:"far"}); }, 10 );
setTimeout( function() { delayNode1.receive({payload:3,topic:"boo"}); }, 20 );
setTimeout( function() { delayNode1.receive({payload:4,topic:"bar"}); }, 30 );
setTimeout( function() { delayNode1.receive({flush:2,reset:true}); }, 200);
setTimeout( function() { delayNode1.receive({payload:5,topic:"fob"}); }, 300 );
setTimeout( function() { delayNode1.receive({flush:1,reset:true}); }, 400);
});
});
it('can full flush and reset rate limit queue', function(done) {
this.timeout(2000);
var flow = [{"id":"delayNode1","type":"delay","name":"delayNode","pauseType":"rate","timeout":1,"timeoutUnits":"seconds","rate":1,"rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"wires":[["helperNode1"]]},
{id:"helperNode1", type:"helper", wires:[]}];
helper.load(delayNode, flow, function() {
var delayNode1 = helper.getNode("delayNode1");
var helperNode1 = helper.getNode("helperNode1");
var t = Date.now();
var c = 0;
helperNode1.on("input", function(msg) {
// console.log("GOT",Date.now() - t,msg)
msg.should.have.a.property('payload');
msg.should.have.a.property('topic');
try {
if (msg.topic === "foo") {
msg.payload.should.equal(1);
(Date.now() - t).should.be.approximately(0,50);
c = c + 1;
}
else if (msg.topic === "bar") {
msg.payload.should.equal(4);
(Date.now() - t).should.be.approximately(200,100);
c = c + 1;
}
else if (msg.topic === "all") {
msg.payload.should.equal(5);
(Date.now() - t).should.be.approximately(200,100);
c = c + 1;
}
else if (msg.topic === "fob") {
msg.payload.should.equal(6);
(Date.now() - t).should.be.approximately(400,100);
c = 5;
}
if (c === 5) { done(); }
} catch(e) {
done(e);
}
});
// send test messages
// delayNode1.receive({payload:1,topic:"foo"});
setImmediate( function() { delayNode1.receive({payload:1,topic:"foo"}); } );
setTimeout( function() { delayNode1.receive({payload:2,topic:"far"}); }, 10 );
setTimeout( function() { delayNode1.receive({payload:3,topic:"boo"}); }, 20 );
setTimeout( function() { delayNode1.receive({payload:4,topic:"bar"}); }, 30 );
setTimeout( function() { delayNode1.receive({payload:5,topic:"last",flush:true,reset:true}); }, 200);
setTimeout( function() { delayNode1.receive({payload:6,topic:"fob"}); }, 300 );
setTimeout( function() { delayNode1.receive({flush:1,reset:true}); }, 400);
});
});
it('can part push to front of rate limit queue', function(done) {
this.timeout(2000);
var flow = [{"id":"delayNode1","type":"delay","name":"delayNode","pauseType":"rate","timeout":1,"timeoutUnits":"seconds","rate":1,"rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"wires":[["helperNode1"]]},