diff --git a/nifi-assembly/LICENSE b/nifi-assembly/LICENSE
index 0edf519b535a..69a03dc5d575 100644
--- a/nifi-assembly/LICENSE
+++ b/nifi-assembly/LICENSE
@@ -232,6 +232,37 @@ The source is available under an MIT LICENSE.
THE SOFTWARE.
This product bundles 'Javascript D3 Library' which is available under a
+"3-clause BSD" license.
+
+ Copyright 2010-2017 Mike Bostock
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ * Neither the name of the author nor the names of contributors may be used to
+ endorse or promote products derived from this software without specific prior
+ written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+This product bundles 'Javascript D3 Selection Multi Library' which is available under a
"3-clause BSD" license.
Copyright (c) 2010-2016, Michael Bostock
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework-nar/src/main/resources/META-INF/LICENSE b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework-nar/src/main/resources/META-INF/LICENSE
index 78eb4c174add..e72b32455456 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework-nar/src/main/resources/META-INF/LICENSE
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework-nar/src/main/resources/META-INF/LICENSE
@@ -261,6 +261,37 @@ licenses.
THE SOFTWARE.
This product bundles 'Javascript D3 Library' which is available under a
+"3-clause BSD" license.
+
+ Copyright 2010-2017 Mike Bostock
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ * Neither the name of the author nor the names of contributors may be used to
+ endorse or promote products derived from this software without specific prior
+ written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+This product bundles 'Javascript D3 Selection Multi Library' which is available under a
"3-clause BSD" license.
Copyright (c) 2010-2016, Michael Bostock
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/pom.xml b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/pom.xml
index c88a85130b6c..699e55d37351 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/pom.xml
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/pom.xml
@@ -151,8 +151,11 @@
false
- d3/d3.min.js*
+ d3/build/d3.min.js*
d3/LICENSE
+
+ d3-selection-multi/build/d3-selection-multi.min.js*
+ d3-selection-multi/LICENSE
angular/angular.min.js*
angular/LICENSE.md
@@ -895,7 +898,6 @@
nbactions.xml
src/main/frontend/package.json
src/main/webapp/js/jquery/jquery.base64.js
- src/main/webapp/js/d3/d3.min.js
src/main/webapp/js/codemirror/
src/main/webapp/fonts/**/*
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/frontend/package.json b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/frontend/package.json
index 4e56011f726b..967020972eb5 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/frontend/package.json
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/frontend/package.json
@@ -14,7 +14,8 @@
"jsonlint": "1.6.2",
"JSON2": "0.1.0",
"reset.css": "2.0.2",
- "d3": "3.5.17",
+ "d3": "4.13.0",
+ "d3-selection-multi": "1.0.1",
"url-search-params": "0.6.1"
},
"description": "Apache NiFi 3rd party client side resources.",
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/resources/META-INF/LICENSE b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/resources/META-INF/LICENSE
index 6d29fb05a50d..2aced50c4c43 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/resources/META-INF/LICENSE
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/resources/META-INF/LICENSE
@@ -209,6 +209,37 @@ subcomponents is subject to the terms and conditions of the following
licenses.
This product bundles 'Javascript D3 Library' which is available under a
+"3-clause BSD" license.
+
+ Copyright 2010-2017 Mike Bostock
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ * Neither the name of the author nor the names of contributors may be used to
+ endorse or promote products derived from this software without specific prior
+ written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+This product bundles 'Javascript D3 Selection Multi Library' which is available under a
"3-clause BSD" license.
Copyright (c) 2010-2016, Michael Bostock
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/pages/canvas.jsp b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/pages/canvas.jsp
index 52fc43cea373..0d14cd2bf1ee 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/pages/canvas.jsp
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/pages/canvas.jsp
@@ -46,7 +46,8 @@
-
+
+
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/pages/provenance.jsp b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/pages/provenance.jsp
index b4eb6a035b97..d4bcccc936e6 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/pages/provenance.jsp
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/pages/provenance.jsp
@@ -33,7 +33,8 @@
-
+
+
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/pages/summary.jsp b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/pages/summary.jsp
index 1746e6bcab7d..cc5ae4324635 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/pages/summary.jsp
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/pages/summary.jsp
@@ -39,7 +39,6 @@
-
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/pages/users.jsp b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/pages/users.jsp
index 42d07914cb2d..2444baa11f59 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/pages/users.jsp
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/pages/users.jsp
@@ -32,7 +32,6 @@
-
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/graph.css b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/graph.css
index 4c77066e36da..95fbbbd9496a 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/graph.css
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/graph.css
@@ -150,7 +150,7 @@ g.component.connectable-destination rect.border {
stroke-width: 3;
}
-rect.selection, rect.drag-selection, rect.label-drag {
+rect.component-selection, rect.drag-selection, rect.label-drag {
stroke: #444444;
stroke-opacity: 0.5;
fill: transparent;
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/navigation.css b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/navigation.css
index 17200d713993..0c23683d9644 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/navigation.css
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/navigation.css
@@ -225,7 +225,7 @@ div.button-spacer-large {
border: 1px solid #e5ebed;
}
-.brush .extent {
+.brush .selection {
stroke: #666;
fill-opacity: .125;
shape-rendering: crispEdges;
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/status-history.css b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/status-history.css
index e421f6158183..57a5baa98252 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/status-history.css
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/status-history.css
@@ -167,7 +167,7 @@ div.legend-label {
stroke-width: 2.5px;
}
-.brush .extent {
+.brush .selection {
stroke: #666;
fill-opacity: .125;
shape-rendering: crispEdges;
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/controllers/nf-ng-canvas-navigate-controller.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/controllers/nf-ng-canvas-navigate-controller.js
index 46dc70fafb18..6f1430f3b9d2 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/controllers/nf-ng-canvas-navigate-controller.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/controllers/nf-ng-canvas-navigate-controller.js
@@ -35,7 +35,7 @@
}(this, function (nfCanvasUtils, nfContextMenu) {
'use strict';
- return function () {
+ return function ($timeout) {
'use strict';
function NavigateCtrl() {
@@ -44,66 +44,42 @@
* Zoom in on the canvas.
*/
this.zoomIn = function () {
- nfCanvasUtils.zoomCanvasViewIn();
-
- // hide the context menu
- nfContextMenu.hide();
-
- // refresh the canvas
- nfCanvasUtils.refreshCanvasView({
- transition: true
- });
+ $timeout(function () {
+ nfCanvasUtils.zoomInCanvas();
+ }, 0);
};
/**
* Zoom out on the canvas.
*/
this.zoomOut = function () {
- nfCanvasUtils.zoomCanvasViewOut();
-
- // hide the context menu
- nfContextMenu.hide();
-
- // refresh the canvas
- nfCanvasUtils.refreshCanvasView({
- transition: true
- });
+ $timeout(function () {
+ nfCanvasUtils.zoomOutCanvas();
+ }, 0);
};
/**
* Zoom fit on the canvas.
*/
this.zoomFit = function () {
- nfCanvasUtils.fitCanvasView();
-
- // hide the context menu
- nfContextMenu.hide();
-
- // refresh the canvas
- nfCanvasUtils.refreshCanvasView({
- transition: true
- });
+ $timeout(function () {
+ nfCanvasUtils.fitCanvas();
+ }, 0);
};
/**
* Zoom actual size on the canvas.
*/
this.zoomActualSize = function () {
- nfCanvasUtils.actualSizeCanvasView();
-
- // hide the context menu
- nfContextMenu.hide();
-
- // refresh the canvas
- nfCanvasUtils.refreshCanvasView({
- transition: true
- });
+ $timeout(function () {
+ nfCanvasUtils.actualSizeCanvas();
+ }, 0);
};
}
NavigateCtrl.prototype = {
constructor: NavigateCtrl
- }
+ };
var navigateCtrl = new NavigateCtrl();
return navigateCtrl;
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/controllers/nf-ng-canvas-toolbox-controller.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/controllers/nf-ng-canvas-toolbox-controller.js
index f6b45f9a36e5..911063f2be7d 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/controllers/nf-ng-canvas-toolbox-controller.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/controllers/nf-ng-canvas-toolbox-controller.js
@@ -130,8 +130,8 @@
nfContextMenu.hide();
},
stop: function (e, ui) {
- var translate = nfCanvasUtils.translateCanvasView();
- var scale = nfCanvasUtils.scaleCanvasView();
+ var translate = nfCanvasUtils.getCanvasTranslate();
+ var scale = nfCanvasUtils.getCanvasScale();
var mouseX = e.originalEvent.pageX;
var mouseY = e.originalEvent.pageY - nfCanvasUtils.getCanvasOffset();
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/header/components/nf-ng-processor-component.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/header/components/nf-ng-processor-component.js
index 3af00da597da..55adc4d7e2ba 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/header/components/nf-ng-processor-component.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/header/components/nf-ng-processor-component.js
@@ -512,7 +512,7 @@
text: 'all groups',
value: ''
}];
- groups.forEach(function (group) {
+ groups.each(function (group) {
options.push({
text: group,
value: group
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-actions.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-actions.js
index 64b0eaba26af..2b09d144c3d0 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-actions.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-actions.js
@@ -493,11 +493,6 @@
// center on the component
nfCanvasUtils.centerBoundingBox(box);
-
- // refresh the canvas
- nfCanvasUtils.refreshCanvasView({
- transition: true
- });
}
},
@@ -996,7 +991,7 @@
});
// remove all the non connections in the snippet first
- components.forEach(function (type, ids) {
+ components.each(function (ids, type) {
if (type !== 'Connection') {
nfCanvasUtils.getComponentByType(type).remove(ids);
}
@@ -1709,8 +1704,8 @@
paste: function (selection, evt) {
if (nfCommon.isDefinedAndNotNull(evt)) {
// get the current scale and translation
- var scale = nfCanvasUtils.scaleCanvasView();
- var translate = nfCanvasUtils.translateCanvasView();
+ var scale = nfCanvasUtils.getCanvasScale();
+ var translate = nfCanvasUtils.getCanvasTranslate();
var mouseX = evt.pageX;
var mouseY = evt.pageY - nfCanvasUtils.getCanvasOffset();
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-birdseye.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-birdseye.js
index 4355e05a7b72..6cacb7f64b96 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-birdseye.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-birdseye.js
@@ -53,8 +53,8 @@
// refreshes the birdseye
var refresh = function (components) {
- var translate = nfCanvasUtils.translateCanvasView();
- var scale = nfCanvasUtils.scaleCanvasView();
+ var translate = nfCanvasUtils.getCanvasTranslate();
+ var scale = nfCanvasUtils.getCanvasScale();
// scale the translation
translate = [translate[0] / scale, translate[1] / scale];
@@ -148,7 +148,7 @@
// update the brush
d3.select('rect.birdseye-brush')
- .attr({
+ .attrs({
'width': screenWidth,
'height': screenHeight,
'stroke-width': (2 / birdseyeScale),
@@ -272,17 +272,14 @@
.attr('pointer-events', 'none');
// define the brush drag behavior
- var brush = d3.behavior.drag()
- .origin(function (d) {
+ var brush = d3.drag()
+ .subject(function (d) {
return {
x: d.x,
- y: d.y
+ y: d.y,
+ source: 'birdseye'
};
})
- .on('dragstart', function () {
- // hide the context menu
- nfContextMenu.hide();
- })
.on('drag', function (d) {
d.x += d3.event.dx;
d.y += d3.event.dy;
@@ -291,25 +288,11 @@
d3.select(this).attr('transform', function () {
return 'translate(' + d.x + ', ' + d.y + ')';
});
- // get the current transformation
- var scale = nfCanvasUtils.scaleCanvasView();
- var translate = nfCanvasUtils.translateCanvasView();
-
- // update the translation according to the delta
- translate = [(-d3.event.dx * scale) + translate[0], (-d3.event.dy * scale) + translate[1]];
-
- // record the current transforms
- nfCanvasUtils.translateCanvasView(translate);
-
- // refresh the canvas
- nfCanvasUtils.refreshCanvasView({
- persist: false,
- transition: false,
- refreshComponents: false,
- refreshBirdseye: false
- });
+
+ // transform the canvas
+ nfCanvasUtils.translateCanvas([-d3.event.dx, -d3.event.dy]);
})
- .on('dragend', function () {
+ .on('end', function () {
// update component visibility
nfGraph.updateVisibility();
@@ -322,7 +305,7 @@
// context area
birdseyeGroup.append('g')
- .attr({
+ .attrs({
'pointer-events': 'all',
'class': 'birdseye-brush-container'
})
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-bootstrap.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-bootstrap.js
index 536f87b6eb2d..4396766953dc 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-bootstrap.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-bootstrap.js
@@ -259,7 +259,7 @@
templateComponent.$inject = ['serviceProvider'];
labelComponent.$inject = ['serviceProvider'];
graphControlsCtrl.$inject = ['serviceProvider', 'navigateCtrl', 'operateCtrl'];
- navigateCtrl.$inject = [];
+ navigateCtrl.$inject = ['$timeout'];
operateCtrl.$inject = [];
breadcrumbsDirective.$inject = ['breadcrumbsCtrl'];
draggableDirective.$inject = [];
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-utils.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-utils.js
index 162da3694529..3dce37e5a24e 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-utils.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-utils.js
@@ -115,7 +115,7 @@
});
// refresh all component types as necessary (handle components that have been removed)
- componentMap.forEach(function (type, ids) {
+ componentMap.each(function (ids, type) {
nfCanvasUtils.getComponentByType(type).remove(ids);
});
@@ -576,7 +576,10 @@
* @param {type} boundingBox
*/
centerBoundingBox: function (boundingBox) {
- var scale = nfCanvas.View.scale();
+ var scale = nfCanvas.View.getScale();
+ if (nfCommon.isDefinedAndNotNull(boundingBox.scale)) {
+ scale = boundingBox.scale;
+ }
// get the canvas normalized width and height
var canvasContainer = $('#canvas-container');
@@ -587,7 +590,7 @@
var center = [(screenWidth / 2) - (boundingBox.width / 2), (screenHeight / 2) - (boundingBox.height / 2)];
// calculate the difference between the center point and the position of this component and convert to screen space
- nfCanvas.View.translate([(center[0] - boundingBox.x) * scale, (center[1] - boundingBox.y) * scale]);
+ nfCanvas.View.transform([(center[0] - boundingBox.x) * scale, (center[1] - boundingBox.y) * scale], scale);
},
/**
@@ -701,7 +704,7 @@
var line = [];
var tspan = selection.append('tspan')
- .attr({
+ .attrs({
'x': x,
'y': y,
'width': width
@@ -726,7 +729,7 @@
// create the tspan for the next line
tspan = selection.append('tspan')
- .attr({
+ .attrs({
'x': x,
'dy': '1.2em',
'width': width
@@ -1560,9 +1563,9 @@
var name = config.storage.namePrefix + nfCanvas.getGroupId();
// create the item to store
- var translate = nfCanvas.View.translate();
+ var translate = nfCanvas.View.getTranslate();
var item = {
- scale: nfCanvas.View.scale(),
+ scale: nfCanvas.View.getScale(),
translateX: translate[0],
translateY: translate[1]
};
@@ -1652,13 +1655,7 @@
if (nfCommon.isDefinedAndNotNull(item)) {
if (isFinite(item.scale) && isFinite(item.translateX) && isFinite(item.translateY)) {
// restore previous view
- nfCanvas.View.translate([item.translateX, item.translateY]);
- nfCanvas.View.scale(item.scale);
-
- // refresh the canvas
- nfCanvas.View.refresh({
- transition: true
- });
+ nfCanvas.View.transform([item.translateX, item.translateY], item.scale);
// mark the view was restore
viewRestored = true;
@@ -1902,57 +1899,53 @@
},
/**
- * Refreshes the view based on the configured translation and scale.
- *
- * @param {object} options Options for the refresh operation
+ * Gets the current scale.
*/
- refreshCanvasView: function (options) {
- return nfCanvas.View.refresh(options);
+ getCanvasScale: function () {
+ return nfCanvas.View.getScale();
},
/**
- * Sets/gets the current scale.
- *
- * @param {number} scale The new scale
+ * Gets the current translation.
*/
- scaleCanvasView: function (scale) {
- return nfCanvas.View.scale(scale);
+ getCanvasTranslate: function () {
+ return nfCanvas.View.getTranslate();
},
/**
- * Sets/gets the current translation.
+ * Translate the canvas by the specified [x, y]
*
- * @param {array} translate [x, y]
+ * @param {array} translate [x, y] to translate by
*/
- translateCanvasView: function (translate) {
- return nfCanvas.View.translate(translate);
+ translateCanvas: function (translate) {
+ nfCanvas.View.translate(translate);
},
/**
* Zooms to fit the entire graph on the canvas.
*/
- fitCanvasView: function () {
+ fitCanvas: function () {
return nfCanvas.View.fit();
},
/**
* Zooms in a single zoom increment.
*/
- zoomCanvasViewIn: function () {
+ zoomInCanvas: function () {
return nfCanvas.View.zoomIn();
},
/**
* Zooms out a single zoom increment.
*/
- zoomCanvasViewOut: function () {
+ zoomOutCanvas: function () {
return nfCanvas.View.zoomOut();
},
/**
* Zooms to the actual size (1 to 1).
*/
- actualSizeCanvasView: function () {
+ actualSizeCanvas: function () {
return nfCanvas.View.actualSize();
},
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas.js
index 00dd4a8601c7..4ef2f2c6c268 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas.js
@@ -91,7 +91,6 @@
var canvas = null;
var canvasClicked = false;
- var panning = false;
var config = {
urls: {
@@ -305,7 +304,7 @@
defs.selectAll('marker')
.data(['normal', 'ghost', 'unauthorized', 'full'])
.enter().append('marker')
- .attr({
+ .attrs({
'id': function (d) {
return d;
},
@@ -332,7 +331,7 @@
// filter for drop shadow
var componentDropShadowFilter = defs.append('filter')
- .attr({
+ .attrs({
'id': 'component-drop-shadow',
'height': '140%',
'y': '-20%'
@@ -340,7 +339,7 @@
// blur
componentDropShadowFilter.append('feGaussianBlur')
- .attr({
+ .attrs({
'in': 'SourceAlpha',
'stdDeviation': 3,
'result': 'blur'
@@ -348,7 +347,7 @@
// offset
componentDropShadowFilter.append('feOffset')
- .attr({
+ .attrs({
'in': 'blur',
'dx': 0,
'dy': 1,
@@ -357,7 +356,7 @@
// color/opacity
componentDropShadowFilter.append('feFlood')
- .attr({
+ .attrs({
'flood-color': '#000000',
'flood-opacity': 0.4,
'result': 'offsetColor'
@@ -365,7 +364,7 @@
// combine
componentDropShadowFilter.append('feComposite')
- .attr({
+ .attrs({
'in': 'offsetColor',
'in2': 'offsetBlur',
'operator': 'in',
@@ -381,7 +380,7 @@
// filter for drop shadow
var connectionFullDropShadowFilter = defs.append('filter')
- .attr({
+ .attrs({
'id': 'connection-full-drop-shadow',
'height': '140%',
'y': '-20%'
@@ -389,7 +388,7 @@
// blur
connectionFullDropShadowFilter.append('feGaussianBlur')
- .attr({
+ .attrs({
'in': 'SourceAlpha',
'stdDeviation': 3,
'result': 'blur'
@@ -397,7 +396,7 @@
// offset
connectionFullDropShadowFilter.append('feOffset')
- .attr({
+ .attrs({
'in': 'blur',
'dx': 0,
'dy': 1,
@@ -406,7 +405,7 @@
// color/opacity
connectionFullDropShadowFilter.append('feFlood')
- .attr({
+ .attrs({
'flood-color': '#ba554a',
'flood-opacity': 1,
'result': 'offsetColor'
@@ -414,7 +413,7 @@
// combine
connectionFullDropShadowFilter.append('feComposite')
- .attr({
+ .attrs({
'in': 'offsetColor',
'in2': 'offsetBlur',
'operator': 'in',
@@ -430,7 +429,7 @@
// create the canvas element
canvas = svg.append('g')
- .attr({
+ .attrs({
'transform': 'translate(' + TRANSLATE + ') scale(' + SCALE + ')',
'pointer-events': 'all',
'id': 'canvas'
@@ -455,14 +454,14 @@
.attr('ry', 6)
.attr('x', position[0])
.attr('y', position[1])
- .attr('class', 'selection')
+ .attr('class', 'component-selection')
.attr('width', 0)
.attr('height', 0)
.attr('stroke-width', function () {
- return 1 / nfCanvas.View.scale();
+ return 1 / nfCanvas.View.getScale();
})
.attr('stroke-dasharray', function () {
- return 4 / nfCanvas.View.scale();
+ return 4 / nfCanvas.View.getScale();
})
.datum(position);
@@ -474,106 +473,100 @@
d3.event.preventDefault();
}
})
- .on('mousemove.selection', function () {
- // update selection box if shift is held down
- if (d3.event.shiftKey) {
- // get the selection box
- var selectionBox = d3.select('rect.selection');
- if (!selectionBox.empty()) {
- // get the original position
- var originalPosition = selectionBox.datum();
- var position = d3.mouse(canvas.node());
-
- var d = {};
- if (originalPosition[0] < position[0]) {
- d.x = originalPosition[0];
- d.width = position[0] - originalPosition[0];
- } else {
- d.x = position[0];
- d.width = originalPosition[0] - position[0];
- }
+ .on('mousemove.selection', function () {
+ // update selection box if shift is held down
+ if (d3.event.shiftKey) {
+ // get the selection box
+ var selectionBox = d3.select('rect.component-selection');
+ if (!selectionBox.empty()) {
+ // get the original position
+ var originalPosition = selectionBox.datum();
+ var position = d3.mouse(canvas.node());
+
+ var d = {};
+ if (originalPosition[0] < position[0]) {
+ d.x = originalPosition[0];
+ d.width = position[0] - originalPosition[0];
+ } else {
+ d.x = position[0];
+ d.width = originalPosition[0] - position[0];
+ }
- if (originalPosition[1] < position[1]) {
- d.y = originalPosition[1];
- d.height = position[1] - originalPosition[1];
- } else {
- d.y = position[1];
- d.height = originalPosition[1] - position[1];
- }
+ if (originalPosition[1] < position[1]) {
+ d.y = originalPosition[1];
+ d.height = position[1] - originalPosition[1];
+ } else {
+ d.y = position[1];
+ d.height = originalPosition[1] - position[1];
+ }
- // update the selection box
- selectionBox.attr(d);
+ // update the selection box
+ selectionBox.attrs(d);
- // prevent further propagation (to parents)
- d3.event.stopPropagation();
- }
- }
- })
- .on('mouseup.selection', function () {
- // ensure this originated from clicking the canvas, not a component.
- // when clicking on a component, the event propagation is stopped so
- // it never reaches the canvas. we cannot do this however on up events
- // since the drag events break down
- if (canvasClicked === false) {
- return;
+ // prevent further propagation (to parents)
+ d3.event.stopPropagation();
}
+ }
+ })
+ .on('mouseup.selection', function () {
+ // ensure this originated from clicking the canvas, not a component.
+ // when clicking on a component, the event propagation is stopped so
+ // it never reaches the canvas. we cannot do this however on up events
+ // since the drag events break down
+ if (canvasClicked === false) {
+ return;
+ }
- // reset the canvas click flag
- canvasClicked = false;
+ // reset the canvas click flag
+ canvasClicked = false;
+
+ // get the selection box
+ var selectionBox = d3.select('rect.component-selection');
+ if (!selectionBox.empty()) {
+ var selectionBoundingBox = {
+ x: parseInt(selectionBox.attr('x'), 10),
+ y: parseInt(selectionBox.attr('y'), 10),
+ width: parseInt(selectionBox.attr('width'), 10),
+ height: parseInt(selectionBox.attr('height'), 10)
+ };
+
+ // see if a component should be selected or not
+ d3.selectAll('g.component').classed('selected', function (d) {
+ // consider it selected if its already selected or enclosed in the bounding box
+ return d3.select(this).classed('selected') ||
+ d.position.x >= selectionBoundingBox.x && (d.position.x + d.dimensions.width) <= (selectionBoundingBox.x + selectionBoundingBox.width) &&
+ d.position.y >= selectionBoundingBox.y && (d.position.y + d.dimensions.height) <= (selectionBoundingBox.y + selectionBoundingBox.height);
+ });
- // get the selection box
- var selectionBox = d3.select('rect.selection');
- if (!selectionBox.empty()) {
- var selectionBoundingBox = {
- x: parseInt(selectionBox.attr('x'), 10),
- y: parseInt(selectionBox.attr('y'), 10),
- width: parseInt(selectionBox.attr('width'), 10),
- height: parseInt(selectionBox.attr('height'), 10)
- };
+ // see if a connection should be selected or not
+ d3.selectAll('g.connection').classed('selected', function (d) {
+ // consider all points
+ var points = [d.start].concat(d.bends, [d.end]);
- // see if a component should be selected or not
- d3.selectAll('g.component').classed('selected', function (d) {
- // consider it selected if its already selected or enclosed in the bounding box
- return d3.select(this).classed('selected') ||
- d.position.x >= selectionBoundingBox.x && (d.position.x + d.dimensions.width) <= (selectionBoundingBox.x + selectionBoundingBox.width) &&
- d.position.y >= selectionBoundingBox.y && (d.position.y + d.dimensions.height) <= (selectionBoundingBox.y + selectionBoundingBox.height);
+ // determine the bounding box
+ var x = d3.extent(points, function (pt) {
+ return pt.x;
});
-
- // see if a connection should be selected or not
- d3.selectAll('g.connection').classed('selected', function (d) {
- // consider all points
- var points = [d.start].concat(d.bends, [d.end]);
-
- // determine the bounding box
- var x = d3.extent(points, function (pt) {
- return pt.x;
- });
- var y = d3.extent(points, function (pt) {
- return pt.y;
- });
-
- // consider it selected if its already selected or enclosed in the bounding box
- return d3.select(this).classed('selected') ||
- x[0] >= selectionBoundingBox.x && x[1] <= (selectionBoundingBox.x + selectionBoundingBox.width) &&
- y[0] >= selectionBoundingBox.y && y[1] <= (selectionBoundingBox.y + selectionBoundingBox.height);
+ var y = d3.extent(points, function (pt) {
+ return pt.y;
});
- // remove the selection box
- selectionBox.remove();
+ // consider it selected if its already selected or enclosed in the bounding box
+ return d3.select(this).classed('selected') ||
+ x[0] >= selectionBoundingBox.x && x[1] <= (selectionBoundingBox.x + selectionBoundingBox.width) &&
+ y[0] >= selectionBoundingBox.y && y[1] <= (selectionBoundingBox.y + selectionBoundingBox.height);
+ });
- // update URL deep linking params
- nfCanvasUtils.setURLParameters();
- } else if (panning === false) {
- // deselect as necessary if we are not panning
- nfCanvasUtils.getSelection().classed('selected', false);
+ // remove the selection box
+ selectionBox.remove();
- // update URL deep linking params
- nfCanvasUtils.setURLParameters();
- }
+ // update URL deep linking params
+ nfCanvasUtils.setURLParameters();
+ }
- // inform Angular app values have changed
- nfNgBridge.digest();
- });
+ // inform Angular app values have changed
+ nfNgBridge.digest();
+ });
// define a function for update the graph dimensions
var updateGraphSize = function () {
@@ -594,7 +587,7 @@
'height': canvasHeight + 'px',
'bottom': bottom + 'px'
});
- svg.attr({
+ svg.attrs({
'height': canvasContainer.height(),
'width': $(window).width()
});
@@ -972,22 +965,63 @@
// initialize the zoom behavior
var behavior;
+ var x = 0, y = 0, k = SCALE;
return {
+
init: function () {
var refreshed;
+
var zoomed = false;
+ var panning = false;
+
+ // filters zoom events as programmatically modifying the translate or scale now triggers the handlers
+ var isBirdseyeEvent = function(sourceEvent) {
+ if (nfCommon.isDefinedAndNotNull(sourceEvent)) {
+ if (nfCommon.isDefinedAndNotNull(sourceEvent.subject)) {
+ return sourceEvent.subject.source === 'birdseye';
+ } else {
+ return false;
+ }
+ } else {
+ return false;
+ }
+ };
+
+ // see if the scale has changed during this zoom event,
+ // we want to only transition when zooming in/out as running
+ // the transitions during pan events is undesirable
+ var shouldTransition = function(sourceEvent) {
+ if (nfCommon.isDefinedAndNotNull(sourceEvent)) {
+ if (isBirdseyeEvent(sourceEvent)) {
+ return false;
+ }
+
+ return sourceEvent.type === 'wheel' || sourceEvent.type === 'mousewheel';
+ } else {
+ return true;
+ }
+ };
// define the behavior
- behavior = d3.behavior.zoom()
+ behavior = d3.zoom()
.scaleExtent([MIN_SCALE, MAX_SCALE])
- .translate(TRANSLATE)
- .scale(SCALE)
- .on('zoomstart', function () {
+ .on('start', function () {
// hide the context menu
nfContextMenu.hide();
})
.on('zoom', function () {
+ // update the current translation and scale
+ if (!isNaN(d3.event.transform.x)) {
+ x = d3.event.transform.x;
+ }
+ if (!isNaN(d3.event.transform.y)) {
+ y = d3.event.transform.y;
+ }
+ if (!isNaN(d3.event.transform.k)) {
+ k = d3.event.transform.k;
+ }
+
// if we have zoomed, indicate that we are panning
// to prevent deselection elsewhere
if (zoomed) {
@@ -996,34 +1030,42 @@
zoomed = true;
}
- // see if the scale has changed during this zoom event,
- // we want to only transition when zooming in/out as running
- // the transitions during pan events is
- var transition = d3.event.sourceEvent.type === 'wheel' || d3.event.sourceEvent.type === 'mousewheel';
-
// refresh the canvas
refreshed = nfCanvas.View.refresh({
persist: false,
- transition: transition,
+ transition: shouldTransition(d3.event.sourceEvent),
refreshComponents: false,
refreshBirdseye: false
});
})
- .on('zoomend', function () {
- // ensure the canvas was actually refreshed
- if (nfCommon.isDefinedAndNotNull(refreshed)) {
- nfGraph.updateVisibility();
-
- // refresh the birdseye
- refreshed.done(function () {
- nfBirdseye.refresh();
- });
+ .on('end', function () {
+ if (!isBirdseyeEvent(d3.event.sourceEvent)) {
+ // ensure the canvas was actually refreshed
+ if (nfCommon.isDefinedAndNotNull(refreshed)) {
+ nfGraph.updateVisibility();
+
+ // refresh the birdseye
+ refreshed.done(function () {
+ nfBirdseye.refresh();
+ });
- // persist the users view
- nfCanvasUtils.persistUserView();
+ // persist the users view
+ nfCanvasUtils.persistUserView();
- // reset the refreshed deferred
- refreshed = null;
+ // reset the refreshed deferred
+ refreshed = null;
+ }
+
+ if (panning === false) {
+ // deselect as necessary if we are not panning
+ nfCanvasUtils.getSelection().classed('selected', false);
+
+ // update URL deep linking params
+ nfCanvasUtils.setURLParameters();
+
+ // inform Angular app values have changed
+ nfNgBridge.digest();
+ }
}
panning = false;
@@ -1040,91 +1082,71 @@
* @returns {Boolean}
*/
shouldRenderPerScale: function () {
- return nfCanvas.View.scale() >= MIN_SCALE_TO_RENDER;
+ return nfCanvas.View.getScale() >= MIN_SCALE_TO_RENDER;
},
/**
- * Sets/gets the current translation.
+ * Translates by the specified [x, y].
*
- * @param {array} translate [x, y]
+ * @param {array} translate [x, y] to translate by
*/
translate: function (translate) {
- if (nfCommon.isUndefined(translate)) {
- return behavior.translate();
- } else {
- behavior.translate(translate);
- }
+ behavior.translateBy(svg, translate[0], translate[1]);
},
/**
- * Sets/gets the current scale.
+ * Scales by the specified scale.
*
- * @param {number} scale The new scale
+ * @param {number} scale The factor to scale by
*/
scale: function (scale) {
- if (nfCommon.isUndefined(scale)) {
- return behavior.scale();
- } else {
- behavior.scale(scale);
- }
+ behavior.scaleBy(svg, scale);
},
/**
- * Zooms in a single zoom increment.
+ * Sets the current transform.
+ *
+ * @param translate
+ * @param scale
*/
- zoomIn: function () {
- var translate = nfCanvas.View.translate();
- var scale = nfCanvas.View.scale();
- var newScale = Math.min(scale * INCREMENT, MAX_SCALE);
+ transform: function (translate, scale) {
+ behavior.transform(svg, d3.zoomIdentity.translate(translate[0], translate[1]).scale(scale));
+ },
- // get the canvas normalized width and height
- var canvasContainer = $('#canvas-container');
- var screenWidth = canvasContainer.width() / scale;
- var screenHeight = canvasContainer.height() / scale;
+ /**
+ * Gets the current translate.
+ */
+ getTranslate: function () {
+ return [x, y];
+ },
- // adjust the scale
- nfCanvas.View.scale(newScale);
+ /**
+ * Gets the current scale.
+ */
+ getScale: function () {
+ return k;
+ },
- // center around the center of the screen accounting for the translation accordingly
- nfCanvasUtils.centerBoundingBox({
- x: (screenWidth / 2) - (translate[0] / scale),
- y: (screenHeight / 2) - (translate[1] / scale),
- width: 1,
- height: 1
- });
+ /**
+ * Zooms in a single zoom increment.
+ */
+ zoomIn: function () {
+ nfCanvas.View.scale(INCREMENT);
},
/**
* Zooms out a single zoom increment.
*/
zoomOut: function () {
- var translate = nfCanvas.View.translate();
- var scale = nfCanvas.View.scale();
- var newScale = Math.max(scale / INCREMENT, MIN_SCALE);
-
- // get the canvas normalized width and height
- var canvasContainer = $('#canvas-container');
- var screenWidth = canvasContainer.width() / scale;
- var screenHeight = canvasContainer.height() / scale;
-
- // adjust the scale
- nfCanvas.View.scale(newScale);
-
- // center around the center of the screen accounting for the translation accordingly
- nfCanvasUtils.centerBoundingBox({
- x: (screenWidth / 2) - (translate[0] / scale),
- y: (screenHeight / 2) - (translate[1] / scale),
- width: 1,
- height: 1
- });
+ nfCanvas.View.scale(1 / INCREMENT);
},
/**
* Zooms to fit the entire graph on the canvas.
*/
fit: function () {
- var translate = nfCanvas.View.translate();
- var scale = nfCanvas.View.scale();
+ var translate = nfCanvas.View.getTranslate();
+ var scale = nfCanvas.View.getScale();
var newScale;
// get the canvas normalized width and height
@@ -1139,7 +1161,6 @@
var graphLeft = graphBox.left / scale;
var graphTop = (graphBox.top - nfCanvas.CANVAS_OFFSET) / scale;
-
// adjust the scale to ensure the entire graph is visible
if (graphWidth > canvasWidth || graphHeight > canvasHeight) {
newScale = Math.min(canvasWidth / graphWidth, canvasHeight / graphHeight);
@@ -1154,15 +1175,13 @@
graphTop -= 50;
}
- // set the new scale
- nfCanvas.View.scale(newScale);
-
// center as appropriate
nfCanvasUtils.centerBoundingBox({
x: graphLeft - (translate[0] / scale),
y: graphTop - (translate[1] / scale),
width: canvasWidth / newScale,
- height: canvasHeight / newScale
+ height: canvasHeight / newScale,
+ scale: newScale
});
},
@@ -1170,15 +1189,12 @@
* Zooms to the actual size (1 to 1).
*/
actualSize: function () {
- var translate = nfCanvas.View.translate();
- var scale = nfCanvas.View.scale();
+ var translate = nfCanvas.View.getTranslate();
+ var scale = nfCanvas.View.getScale();
// get the first selected component
var selection = nfCanvasUtils.getSelection();
- // set the updated scale
- nfCanvas.View.scale(1);
-
// box to zoom towards
var box;
@@ -1192,7 +1208,8 @@
x: (selectionBox.left / scale) - (translate[0] / scale),
y: ((selectionBox.top - nfCanvas.CANVAS_OFFSET) / scale) - (translate[1] / scale),
width: selectionBox.width / scale,
- height: selectionBox.height / scale
+ height: selectionBox.height / scale,
+ scale: 1
};
} else {
// get the offset
@@ -1207,7 +1224,8 @@
x: (screenWidth / 2) - (translate[0] / scale),
y: (screenHeight / 2) - (translate[1] / scale),
width: 1,
- height: 1
+ height: 1,
+ scale: 1
};
}
@@ -1246,14 +1264,17 @@
nfCanvasUtils.persistUserView();
}
+ var t = nfCanvas.View.getTranslate();
+ var s = nfCanvas.View.getScale();
+
// update the canvas
if (transition === true) {
canvas.transition()
.duration(500)
.attr('transform', function () {
- return 'translate(' + behavior.translate() + ') scale(' + behavior.scale() + ')';
+ return 'translate(' + t + ') scale(' + s + ')';
})
- .each('end', function () {
+ .on('end', function () {
// refresh birdseye if appropriate
if (refreshBirdseye === true) {
nfBirdseye.refresh();
@@ -1263,7 +1284,7 @@
});
} else {
canvas.attr('transform', function () {
- return 'translate(' + behavior.translate() + ') scale(' + behavior.scale() + ')';
+ return 'translate(' + t + ') scale(' + s + ')';
});
// refresh birdseye if appropriate
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-connectable.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-connectable.js
index 91d29f612cdc..0418bef2a50c 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-connectable.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-connectable.js
@@ -57,7 +57,7 @@
* @returns {boolean}
*/
var allowConnection = function () {
- return !d3.event.shiftKey && d3.select('rect.drag-selection').empty() && d3.select('rect.selection').empty();
+ return !d3.event.shiftKey && d3.select('rect.drag-selection').empty() && d3.select('rect.component-selection').empty();
};
return {
@@ -65,15 +65,15 @@
canvas = d3.select('#canvas');
// dragging behavior for the connector
- connect = d3.behavior.drag()
- .origin(function (d) {
+ connect = d3.drag()
+ .subject(function (d) {
origin = d3.mouse(canvas.node());
return {
x: origin[0],
y: origin[1]
};
})
- .on('dragstart', function (d) {
+ .on('start', function (d) {
// stop further propagation
d3.event.sourceEvent.stopPropagation();
@@ -98,7 +98,7 @@
'x': position[0],
'y': position[1]
})
- .attr({
+ .attrs({
'class': 'connector',
'd': function (pathDatum) {
return 'M' + pathDatum.x + ' ' + pathDatum.y + 'L' + pathDatum.x + ' ' + pathDatum.y;
@@ -168,7 +168,7 @@
}
});
})
- .on('dragend', function (d) {
+ .on('end', function (d) {
// stop further propagation
d3.event.sourceEvent.stopPropagation();
@@ -243,7 +243,7 @@
origY: y
})
.call(connect)
- .attr({
+ .attrs({
'class': 'add-connect',
'transform': 'translate(' + x + ', ' + y + ')'
})
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-connection.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-connection.js
index 9e974a2eefff..611e143dee4e 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-connection.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-connection.js
@@ -274,13 +274,20 @@
});
};
+ /**
+ * Renders the connections in the specified selection.
+ *
+ * @param {selection} entered The selection of connections to be rendered
+ * @param {boolean} selected Whether the element should be selected
+ * @return the entered selection
+ */
var renderConnections = function (entered, selected) {
if (entered.empty()) {
- return;
+ return entered;
}
var connection = entered.append('g')
- .attr({
+ .attrs({
'id': function (d) {
return 'id-' + d.id;
},
@@ -290,21 +297,21 @@
// create a connection between the two components
connection.append('path')
- .attr({
+ .attrs({
'class': 'connection-path',
'pointer-events': 'none'
});
// path to show when selection
connection.append('path')
- .attr({
+ .attrs({
'class': 'connection-selection-path',
'pointer-events': 'none'
});
// path to make selection easier
connection.append('path')
- .attr({
+ .attrs({
'class': 'connection-path-selectable',
'pointer-events': 'stroke'
})
@@ -316,6 +323,8 @@
nfCanvasUtils.setURLParameters();
})
.call(nfContextMenu.activate);
+
+ return connection;
};
// determines whether the specified connection contains an unsupported relationship
@@ -584,21 +593,21 @@
// update the connection paths
nfCanvasUtils.transition(connection.select('path.connection-path'), transition)
- .attr({
+ .attrs({
'd': function () {
var datum = [d.start].concat(d.bends, [d.end]);
return lineGenerator(datum);
}
});
nfCanvasUtils.transition(connection.select('path.connection-selection-path'), transition)
- .attr({
+ .attrs({
'd': function () {
var datum = [d.start].concat(d.bends, [d.end]);
return lineGenerator(datum);
}
});
nfCanvasUtils.transition(connection.select('path.connection-path-selectable'), transition)
- .attr({
+ .attrs({
'd': function () {
var datum = [d.start].concat(d.bends, [d.end]);
return lineGenerator(datum);
@@ -624,8 +633,8 @@
startpoints = startpoints.data([d.start]);
// create a point for the start
- startpoints.enter().append('rect')
- .attr({
+ var startpointsEntered = startpoints.enter().append('rect')
+ .attrs({
'class': 'startpoint linepoint',
'pointer-events': 'all',
'width': 8,
@@ -641,7 +650,7 @@
.call(nfContextMenu.activate);
// update the start point
- nfCanvasUtils.transition(startpoints, transition)
+ nfCanvasUtils.transition(startpoints.merge(startpointsEntered), transition)
.attr('transform', function (p) {
return 'translate(' + (p.x - 4) + ', ' + (p.y - 4) + ')';
});
@@ -656,9 +665,9 @@
var endpoints = endpoints.data([d.end]);
// create a point for the end
- endpoints.enter().append('rect')
+ var endpointsEntered = endpoints.enter().append('rect')
.call(endpointDrag)
- .attr({
+ .attrs({
'class': 'endpoint linepoint',
'pointer-events': 'all',
'width': 8,
@@ -674,7 +683,7 @@
.call(nfContextMenu.activate);
// update the end point
- nfCanvasUtils.transition(endpoints, transition)
+ nfCanvasUtils.transition(endpoints.merge(endpointsEntered), transition)
.attr('transform', function (p) {
return 'translate(' + (p.x - 4) + ', ' + (p.y - 4) + ')';
});
@@ -689,8 +698,8 @@
var midpoints = midpoints.data(d.bends);
// create a point for the end
- midpoints.enter().append('rect')
- .attr({
+ var midpointsEntered = midpoints.enter().append('rect')
+ .attrs({
'class': 'midpoint linepoint',
'pointer-events': 'all',
'width': 8,
@@ -757,7 +766,7 @@
.call(nfContextMenu.activate);
// update the midpoints
- nfCanvasUtils.transition(midpoints, transition)
+ nfCanvasUtils.transition(midpoints.merge(midpointsEntered), transition)
.attr('transform', function (p) {
return 'translate(' + (p.x - 4) + ', ' + (p.y - 4) + ')';
});
@@ -783,7 +792,7 @@
if (connectionLabelContainer.empty()) {
// connection label container
connectionLabelContainer = connection.insert('g', 'rect.startpoint')
- .attr({
+ .attrs({
'class': 'connection-label-container',
'pointer-events': 'all'
})
@@ -798,7 +807,7 @@
// connection label
connectionLabelContainer.append('rect')
- .attr({
+ .attrs({
'class': 'body',
'width': dimensions.width,
'x': 0,
@@ -807,7 +816,7 @@
// processor border
connectionLabelContainer.append('rect')
- .attr({
+ .attrs({
'class': 'border',
'width': dimensions.width,
'fill': 'transparent',
@@ -835,13 +844,13 @@
// see if the connection from label is already rendered
if (connectionFrom.empty()) {
connectionFrom = connectionLabelContainer.append('g')
- .attr({
+ .attrs({
'class': 'connection-from-container'
});
// background
backgrounds.push(connectionFrom.append('rect')
- .attr({
+ .attrs({
'class': 'connection-label-background',
'width': dimensions.width,
'height': rowHeight
@@ -849,14 +858,14 @@
// border
borders.push(connectionFrom.append('rect')
- .attr({
+ .attrs({
'class': 'connection-label-border',
'width': dimensions.width,
'height': 1
}));
connectionFrom.append('text')
- .attr({
+ .attrs({
'class': 'stats-label',
'x': 5,
'y': 14
@@ -864,7 +873,7 @@
.text('From');
connectionFrom.append('text')
- .attr({
+ .attrs({
'class': 'stats-value connection-from',
'x': 43,
'y': 14,
@@ -872,7 +881,7 @@
});
connectionFrom.append('text')
- .attr({
+ .attrs({
'class': 'connection-from-run-status',
'x': 185,
'y': 14
@@ -944,13 +953,13 @@
// see if the connection to label is already rendered
if (connectionTo.empty()) {
connectionTo = connectionLabelContainer.append('g')
- .attr({
+ .attrs({
'class': 'connection-to-container'
});
// background
backgrounds.push(connectionTo.append('rect')
- .attr({
+ .attrs({
'class': 'connection-label-background',
'width': dimensions.width,
'height': rowHeight
@@ -958,14 +967,14 @@
// border
borders.push(connectionTo.append('rect')
- .attr({
+ .attrs({
'class': 'connection-label-border',
'width': dimensions.width,
'height': 1
}));
connectionTo.append('text')
- .attr({
+ .attrs({
'class': 'stats-label',
'x': 5,
'y': 14
@@ -973,7 +982,7 @@
.text('To');
connectionTo.append('text')
- .attr({
+ .attrs({
'class': 'stats-value connection-to',
'x': 25,
'y': 14,
@@ -981,7 +990,7 @@
});
connectionTo.append('text')
- .attr({
+ .attrs({
'class': 'connection-to-run-status',
'x': 185,
'y': 14
@@ -1056,13 +1065,13 @@
// see if the connection name label is already rendered
if (connectionName.empty()) {
connectionName = connectionLabelContainer.append('g')
- .attr({
+ .attrs({
'class': 'connection-name-container'
});
// background
backgrounds.push(connectionName.append('rect')
- .attr({
+ .attrs({
'class': 'connection-label-background',
'width': dimensions.width,
'height': rowHeight
@@ -1070,14 +1079,14 @@
// border
borders.push(connectionName.append('rect')
- .attr({
+ .attrs({
'class': 'connection-label-border',
'width': dimensions.width,
'height': 1
}));
connectionName.append('text')
- .attr({
+ .attrs({
'class': 'stats-label',
'x': 5,
'y': 14
@@ -1085,7 +1094,7 @@
.text('Name');
connectionName.append('text')
- .attr({
+ .attrs({
'class': 'stats-value connection-name',
'x': 45,
'y': 14,
@@ -1136,13 +1145,13 @@
var queued = connectionLabelContainer.select('g.queued-container');
if (queued.empty()) {
queued = connectionLabelContainer.append('g')
- .attr({
+ .attrs({
'class': 'queued-container'
});
// background
backgrounds.push(queued.append('rect')
- .attr({
+ .attrs({
'class': 'connection-label-background',
'width': dimensions.width,
'height': rowHeight + HEIGHT_FOR_BACKPRESSURE
@@ -1150,14 +1159,14 @@
// border
borders.push(queued.append('rect')
- .attr({
+ .attrs({
'class': 'connection-label-border',
'width': dimensions.width,
'height': 1
}));
queued.append('text')
- .attr({
+ .attrs({
'class': 'stats-label',
'x': 5,
'y': 14
@@ -1165,7 +1174,7 @@
.text('Queued');
var queuedText = queued.append('text')
- .attr({
+ .attrs({
'class': 'stats-value queued',
'x': 55,
'y': 14
@@ -1173,19 +1182,19 @@
// queued count
queuedText.append('tspan')
- .attr({
+ .attrs({
'class': 'count'
});
// queued size
queuedText.append('tspan')
- .attr({
+ .attrs({
'class': 'size'
});
// expiration icon
queued.append('text')
- .attr({
+ .attrs({
'class': 'expiration-icon',
'x': 185,
'y': 14
@@ -1201,7 +1210,7 @@
// start
queued.append('rect')
- .attr({
+ .attrs({
'class': 'backpressure-tick object',
'width': 1,
'height': 3,
@@ -1212,7 +1221,7 @@
// bar
var backpressureCountOffset = 6;
queued.append('rect')
- .attr({
+ .attrs({
'class': 'backpressure-object',
'width': backpressureBarWidth,
'height': 3,
@@ -1223,7 +1232,7 @@
// end
queued.append('rect')
- .attr({
+ .attrs({
'class': 'backpressure-tick object',
'width': 1,
'height': 3,
@@ -1233,7 +1242,7 @@
// percent full
queued.append('rect')
- .attr({
+ .attrs({
'class': 'backpressure-percent object',
'width': 0,
'height': 3,
@@ -1245,7 +1254,7 @@
// start
queued.append('rect')
- .attr({
+ .attrs({
'class': 'backpressure-tick data-size',
'width': 1,
'height': 3,
@@ -1256,7 +1265,7 @@
// bar
var backpressureDataSizeOffset = (dimensions.width / 2) + 10 + 1;
queued.append('rect')
- .attr({
+ .attrs({
'class': 'backpressure-data-size',
'width': backpressureBarWidth,
'height': 3,
@@ -1267,7 +1276,7 @@
// end
queued.append('rect')
- .attr({
+ .attrs({
'class': 'backpressure-tick data-size',
'width': 1,
'height': 3,
@@ -1277,7 +1286,7 @@
// percent full
queued.append('rect')
- .attr({
+ .attrs({
'class': 'backpressure-percent data-size',
'width': 0,
'height': 3,
@@ -1411,7 +1420,7 @@
var backpressurePercentDataSize = updated.select('rect.backpressure-percent.data-size');
backpressurePercentDataSize.transition()
.duration(400)
- .attr({
+ .attrs({
'width': function (d) {
if (nfCommon.isDefinedAndNotNull(d.status.aggregateSnapshot.percentUseBytes)) {
return (backpressureBarWidth * d.status.aggregateSnapshot.percentUseBytes) / 100;
@@ -1419,7 +1428,7 @@
return 0;
}
}
- }).each('end', function () {
+ }).on('end', function () {
backpressurePercentDataSize
.classed('warning', function (d) {
return isWarningBytes(d);
@@ -1451,7 +1460,7 @@
var backpressurePercentObject = updated.select('rect.backpressure-percent.object');
backpressurePercentObject.transition()
.duration(400)
- .attr({
+ .attrs({
'width': function (d) {
if (nfCommon.isDefinedAndNotNull(d.status.aggregateSnapshot.percentUseCount)) {
return (backpressureBarWidth * d.status.aggregateSnapshot.percentUseCount) / 100;
@@ -1459,7 +1468,7 @@
return 0;
}
}
- }).each('end', function () {
+ }).on('end', function () {
backpressurePercentObject
.classed('warning', function (d) {
return isWarningCount(d);
@@ -1487,7 +1496,7 @@
.classed('full', function (d) {
return isFullCount(d) || isFullBytes(d);
})
- .attr({
+ .attrs({
'marker-end': getEndMarker
});
@@ -1499,7 +1508,7 @@
// drop shadow
updated.select('rect.body')
- .attr({
+ .attrs({
'filter': getDropShadow
});
});
@@ -1575,24 +1584,24 @@
// create the connection container
connectionContainer = d3.select('#canvas').append('g')
- .attr({
+ .attrs({
'pointer-events': 'stroke',
'class': 'connections'
});
// define the line generator
- lineGenerator = d3.svg.line()
+ lineGenerator = d3.line()
.x(function (d) {
return d.x;
})
.y(function (d) {
return d.y;
})
- .interpolate('linear');
+ .curve(d3.curveLinear);
// handle bend point drag events
- bendPointDrag = d3.behavior.drag()
- .on('dragstart', function () {
+ bendPointDrag = d3.drag()
+ .on('start', function () {
// stop further propagation
d3.event.sourceEvent.stopPropagation();
})
@@ -1606,7 +1615,7 @@
'updateLabel': false
});
})
- .on('dragend', function () {
+ .on('end', function () {
var connection = d3.select(this.parentNode);
var connectionData = connection.datum();
var bends = connection.selectAll('rect.midpoint').data();
@@ -1649,8 +1658,8 @@
});
// handle endpoint drag events
- endpointDrag = d3.behavior.drag()
- .on('dragstart', function (d) {
+ endpointDrag = d3.drag()
+ .on('start', function (d) {
// indicate that dragging has begun
d.dragging = true;
@@ -1672,7 +1681,7 @@
'updateLabel': false
});
})
- .on('dragend', function (d) {
+ .on('end', function (d) {
// indicate that dragging as stopped
d.dragging = false;
@@ -1780,8 +1789,8 @@
});
// label drag behavior
- labelDrag = d3.behavior.drag()
- .on('dragstart', function (d) {
+ labelDrag = d3.drag()
+ .on('start', function (d) {
// stop further propagation
d3.event.sourceEvent.stopPropagation();
})
@@ -1806,10 +1815,10 @@
.attr('width', width)
.attr('height', height)
.attr('stroke-width', function () {
- return 1 / nfCanvasUtils.scaleCanvasView();
+ return 1 / nfCanvasUtils.getCanvasScale();
})
.attr('stroke-dasharray', function () {
- return 4 / nfCanvasUtils.scaleCanvasView();
+ return 4 / nfCanvasUtils.getCanvasScale();
})
.datum({
x: position.x,
@@ -1864,7 +1873,7 @@
});
}
})
- .on('dragend', function (d) {
+ .on('end', function (d) {
if (d.bends.length > 1) {
// get the drag selection
var drag = d3.select('rect.label-drag');
@@ -1935,10 +1944,15 @@
add(connectionEntities);
}
- // apply the selection and handle new connections
+ // select
var selection = select();
- selection.enter().call(renderConnections, selectAll);
- selection.call(updateConnections, {
+
+ // enter
+ var entered = renderConnections(selection.enter(), selectAll);
+
+ // update
+ var updated = selection.merge(entered);
+ updated.call(updateConnections, {
'updatePath': true,
'updateLabel': false
}).call(sort);
@@ -1955,6 +1969,7 @@
if (selection.empty()) {
return false;
}
+
var connections = d3.map();
var components = d3.map();
var isDisconnected = true;
@@ -1980,12 +1995,11 @@
}
});
});
- if (isDisconnected) {
+ if (isDisconnected) {
// go through each connection to ensure its source and destination are included
- connections.forEach(function (id, connection) {
+ connections.each(function (connection, id) {
if (isDisconnected) {
-
// determine whether this connection and its components are included within the selection
isDisconnected = components.has(nfCanvasUtils.getConnectionSourceComponentId(connection)) && components.has(nfCanvasUtils.getConnectionDestinationComponentId(connection));
}
@@ -2041,14 +2055,21 @@
set(connectionEntities);
}
- // apply the selection and handle all new connection
+ // select
var selection = select();
- selection.enter().call(renderConnections, selectAll);
- selection.call(updateConnections, {
+
+ // enter
+ var entered = renderConnections(selection.enter(), selectAll);
+
+ // update
+ var updated = selection.merge(entered);
+ updated.call(updateConnections, {
'updatePath': true,
'updateLabel': true,
'transition': transition
}).call(sort);
+
+ // exit
selection.exit().call(removeConnections);
},
@@ -2159,7 +2180,7 @@
*/
getComponentConnections: function (id) {
var connections = [];
- connectionMap.forEach(function (_, entry) {
+ connectionMap.each(function (entry, _) {
// see if this component is the source or destination of this connection
if (nfCanvasUtils.getConnectionSourceComponentId(entry) === id || nfCanvasUtils.getConnectionDestinationComponentId(entry) === id) {
connections.push(entry);
@@ -2189,7 +2210,7 @@
*/
expireCaches: function (timestamp) {
var expire = function (cache) {
- cache.forEach(function (id, entryTimestamp) {
+ cache.each(function (entryTimestamp, id) {
if (timestamp > entryTimestamp) {
cache.remove(id);
}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-controller-service.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-controller-service.js
index c97c861d18b6..d576006331ff 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-controller-service.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-controller-service.js
@@ -415,7 +415,7 @@
})
.map(bulletins, d3.map);
- bulletinsBySource.forEach(function (sourceId, sourceBulletins) {
+ bulletinsBySource.each(function (sourceBulletins, sourceId) {
$('div.' + sourceId + '-bulletins').each(function () {
updateBulletins(sourceBulletins, $(this));
});
@@ -789,7 +789,7 @@
// start polling for each controller service
var polling = [];
- services.forEach(function (controllerServiceId) {
+ services.each(function (controllerServiceId) {
getControllerService(controllerServiceId, controllerServiceData).done(function(controllerServiceEntity) {
polling.push(stopReferencingSchedulableComponents(controllerServiceEntity, pollCondition));
});
@@ -1080,7 +1080,7 @@
// start polling for each controller service
var polling = [];
- services.forEach(function (controllerServiceId) {
+ services.each(function (controllerServiceId) {
getControllerService(controllerServiceId, controllerServiceData).done(function(controllerServiceEntity) {
if (enabled) {
polling.push(enableReferencingServices(controllerServiceEntity, pollCondition));
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-controller-services.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-controller-services.js
index 30f653049e0b..0a604a9b0d2e 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-controller-services.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-controller-services.js
@@ -566,7 +566,7 @@
text: 'all groups',
value: ''
}];
- groups.forEach(function (group) {
+ groups.each(function (group) {
options.push({
text: group,
value: group
@@ -1339,7 +1339,7 @@
.key(function(d) { return d.sourceId; })
.map(controllerServiceBulletins, d3.map);
- controllerServiceBulletinsBySource.forEach(function(sourceId, sourceBulletins) {
+ controllerServiceBulletinsBySource.each(function(sourceBulletins, sourceId) {
var controllerService = controllerServicesData.getItemById(sourceId);
if (nfCommon.isDefinedAndNotNull(controllerService)) {
controllerServicesData.updateItem(sourceId, $.extend(controllerService, {
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-draggable.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-draggable.js
index 56ff8f596b51..5b8307b715ff 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-draggable.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-draggable.js
@@ -152,8 +152,8 @@
nfCanvas = canvas;
// handle component drag events
- drag = d3.behavior.drag()
- .on('dragstart', function () {
+ drag = d3.drag()
+ .on('start', function () {
// stop further propagation
d3.event.sourceEvent.stopPropagation();
})
@@ -195,10 +195,10 @@
.attr('width', maxX - minX)
.attr('height', maxY - minY)
.attr('stroke-width', function () {
- return 1 / nfCanvasUtils.scaleCanvasView();
+ return 1 / nfCanvasUtils.getCanvasScale();
})
.attr('stroke-dasharray', function () {
- return 4 / nfCanvasUtils.scaleCanvasView();
+ return 4 / nfCanvasUtils.getCanvasScale();
})
.datum({
original: {
@@ -220,7 +220,7 @@
});
}
})
- .on('dragend', function () {
+ .on('end', function () {
// stop further propagation
d3.event.sourceEvent.stopPropagation();
@@ -390,7 +390,7 @@
});
// refresh the connections
- connections.forEach(function (connectionId) {
+ connections.each(function (connectionId) {
nfConnection.refresh(connectionId);
});
}).always(function () {
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-funnel.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-funnel.js
index ed5051fe65b6..a18640798c57 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-funnel.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-funnel.js
@@ -91,6 +91,7 @@
*
* @param {selection} entered The selection of funnels to be rendered
* @param {boolean} selected Whether the element should be selected
+ * @return the entered selection
*/
var renderFunnels = function (entered, selected) {
if (entered.empty()) {
@@ -98,7 +99,7 @@
}
var funnel = entered.append('g')
- .attr({
+ .attrs({
'id': function (d) {
return 'id-' + d.id;
},
@@ -109,7 +110,7 @@
// funnel border
funnel.append('rect')
- .attr({
+ .attrs({
'rx': 2,
'ry': 2,
'class': 'border',
@@ -125,7 +126,7 @@
// funnel body
funnel.append('rect')
- .attr({
+ .attrs({
'rx': 2,
'ry': 2,
'class': 'body',
@@ -141,7 +142,7 @@
// funnel icon
funnel.append('text')
- .attr({
+ .attrs({
'class': 'funnel-icon',
'x': 9,
'y': 34
@@ -150,6 +151,8 @@
// always support selection
funnel.call(nfSelectable.activate).call(nfContextMenu.activate);
+
+ return funnel;
};
/**
@@ -212,7 +215,7 @@
// create the funnel container
funnelContainer = d3.select('#canvas').append('g')
- .attr({
+ .attrs({
'pointer-events': 'all',
'class': 'funnels'
});
@@ -252,10 +255,14 @@
add(funnelEntities);
}
- // apply the selection and handle new funnels
+ // select
var selection = select();
- selection.enter().call(renderFunnels, selectAll);
- selection.call(updateFunnels);
+
+ // enter
+ var entered = renderFunnels(selection.enter(), selectAll);
+
+ // update
+ updateFunnels(selection.merge(entered));
},
/**
@@ -305,10 +312,17 @@
set(funnelEntities);
}
- // apply the selection and handle all new processors
+ // select
var selection = select();
- selection.enter().call(renderFunnels, selectAll);
- selection.call(updateFunnels).call(nfCanvasUtils.position, transition);
+
+ // enter
+ var entered = renderFunnels(selection.enter(), selectAll);
+
+ // update
+ var updated = selection.merge(entered);
+ updated.call(updateFunnels).call(nfCanvasUtils.position, transition);
+
+ // exit
selection.exit().call(removeFunnels);
},
@@ -404,7 +418,7 @@
*/
expireCaches: function (timestamp) {
var expire = function (cache) {
- cache.forEach(function (id, entryTimestamp) {
+ cache.each(function (entryTimestamp, id) {
if (timestamp > entryTimestamp) {
cache.remove(id);
}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-graph.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-graph.js
index e7a62bd55ce0..16b32a226126 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-graph.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-graph.js
@@ -112,8 +112,8 @@
*/
var updateComponentVisibility = function () {
var canvasContainer = $('#canvas-container');
- var translate = nfCanvasUtils.translateCanvasView();
- var scale = nfCanvasUtils.scaleCanvasView();
+ var translate = nfCanvasUtils.getCanvasTranslate();
+ var scale = nfCanvasUtils.getCanvasScale();
// scale the translation
translate = [translate[0] / scale, translate[1] / scale];
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-label.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-label.js
index b4c65373286b..c6f97646842c 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-label.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-label.js
@@ -101,14 +101,15 @@
*
* @param {selection} entered The selection of labels to be rendered
* @param {boolean} selected Whether the label should be selected
+ * @return the entered selection
*/
var renderLabels = function (entered, selected) {
if (entered.empty()) {
- return;
+ return entered;
}
var label = entered.append('g')
- .attr({
+ .attrs({
'id': function (d) {
return 'id-' + d.id;
},
@@ -119,7 +120,7 @@
// label border
label.append('rect')
- .attr({
+ .attrs({
'class': 'border',
'fill': 'transparent',
'stroke': 'transparent'
@@ -127,7 +128,7 @@
// label
label.append('rect')
- .attr({
+ .attrs({
'class': 'body',
'filter': 'url(#component-drop-shadow)',
'stroke-width': 0
@@ -135,7 +136,7 @@
// label value
label.append('text')
- .attr({
+ .attrs({
'xml:space': 'preserve',
'font-weight': 'bold',
'fill': 'black',
@@ -144,6 +145,8 @@
// always support selecting
label.call(nfSelectable.activate).call(nfContextMenu.activate).call(nfQuickSelect.activate);
+
+ return label;
};
/**
@@ -158,7 +161,7 @@
// update the border using the configured color
updated.select('rect.border')
- .attr({
+ .attrs({
'width': function (d) {
return d.dimensions.width;
},
@@ -172,7 +175,7 @@
// update the body fill using the configured color
updated.select('rect.body')
- .attr({
+ .attrs({
'width': function (d) {
return d.dimensions.width;
},
@@ -266,8 +269,8 @@
var points = labelPoint.data(pointData);
// create a point for the end
- points.enter().append('rect')
- .attr({
+ var pointsEntered = points.enter().append('rect')
+ .attrs({
'class': 'labelpoint',
'width': 10,
'height': 10
@@ -275,7 +278,7 @@
.call(labelPointDrag);
// update the midpoints
- points.attr('transform', function (p) {
+ points.merge(pointsEntered).attr('transform', function (p) {
return 'translate(' + (p.x - 10) + ', ' + (p.y - 10) + ')';
});
@@ -329,14 +332,14 @@
// create the label container
labelContainer = d3.select('#canvas').append('g')
- .attr({
+ .attrs({
'pointer-events': 'all',
'class': 'labels'
});
// handle bend point drag events
- labelPointDrag = d3.behavior.drag()
- .on('dragstart', function () {
+ labelPointDrag = d3.drag()
+ .on('start', function () {
// stop further propagation
d3.event.sourceEvent.stopPropagation();
})
@@ -351,7 +354,7 @@
// redraw this connection
updateLabels(label);
})
- .on('dragend', function () {
+ .on('end', function () {
var label = d3.select(this.parentNode);
var labelData = label.datum();
@@ -448,10 +451,14 @@
add(labelEntities);
}
- // apply the selection and handle new labels
+ // select
var selection = select();
- selection.enter().call(renderLabels, selectAll);
- selection.call(updateLabels);
+
+ // enter
+ var entered = renderLabels(selection.enter(), selectAll);
+
+ // update
+ updateLabels(selection.merge(entered));
},
/**
@@ -500,10 +507,17 @@
set(labelEntities);
}
- // apply the selection and handle all new labels
+ // select
var selection = select();
- selection.enter().call(renderLabels, selectAll);
- selection.call(updateLabels).call(nfCanvasUtils.position, transition);
+
+ // enter
+ var entered = renderLabels(selection.enter(), selectAll);
+
+ // update
+ var updated = selection.merge(entered);
+ updated.call(updateLabels).call(nfCanvasUtils.position, transition);
+
+ // exit
selection.exit().call(removeLabels);
},
@@ -599,7 +613,7 @@
*/
expireCaches: function (timestamp) {
var expire = function (cache) {
- cache.forEach(function (id, entryTimestamp) {
+ cache.each(function (entryTimestamp, id) {
if (timestamp > entryTimestamp) {
cache.remove(id);
}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-port.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-port.js
index 1799a86bef56..c43cbf7e617d 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-port.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-port.js
@@ -99,14 +99,15 @@
*
* @param {selection} entered The selection of ports to be rendered
* @param {boolean} selected Whether the port should be selected
+ * @return the entered selection
*/
var renderPorts = function (entered, selected) {
if (entered.empty()) {
- return;
+ return entered;
}
var port = entered.append('g')
- .attr({
+ .attrs({
'id': function (d) {
return 'id-' + d.id;
},
@@ -123,7 +124,7 @@
// port border
port.append('rect')
- .attr({
+ .attrs({
'class': 'border',
'width': function (d) {
return d.dimensions.width;
@@ -137,7 +138,7 @@
// port body
port.append('rect')
- .attr({
+ .attrs({
'class': 'body',
'width': function (d) {
return d.dimensions.width;
@@ -157,7 +158,7 @@
// port remote banner
port.append('rect')
- .attr({
+ .attrs({
'class': 'remote-banner',
'width': function (d) {
return d.dimensions.width;
@@ -169,7 +170,7 @@
// port icon
port.append('text')
- .attr({
+ .attrs({
'class': 'port-icon',
'x': 10,
'y': 38 + offset
@@ -184,7 +185,7 @@
// port name
port.append('text')
- .attr({
+ .attrs({
'x': 70,
'y': 25 + offset,
'width': 95,
@@ -199,6 +200,8 @@
port.filter(function (d) {
return d.permissions.canWrite && d.permissions.canRead;
}).call(nfDraggable.activate).call(nfConnectable.activate);
+
+ return port;
};
/**
@@ -241,7 +244,7 @@
// port transmitting icon
details.append('text')
- .attr({
+ .attrs({
'class': 'port-transmission-icon',
'x': 10,
'y': 18
@@ -249,7 +252,7 @@
// bulletin background
details.append('rect')
- .attr({
+ .attrs({
'class': 'bulletin-background',
'x': function (d) {
return portData.dimensions.width - offset;
@@ -260,7 +263,7 @@
// bulletin icon
details.append('text')
- .attr({
+ .attrs({
'class': 'bulletin-icon',
'x': function (d) {
return portData.dimensions.width - 18;
@@ -272,7 +275,7 @@
// run status icon
details.append('text')
- .attr({
+ .attrs({
'class': 'run-status-icon',
'x': 50,
'y': function () {
@@ -285,7 +288,7 @@
// --------
details.append('path')
- .attr({
+ .attrs({
'class': 'component-comments',
'transform': 'translate(' + (portData.dimensions.width - 2) + ', ' + (portData.dimensions.height - 10) + ')',
'd': 'm0,0 l0,8 l-8,0 z'
@@ -297,7 +300,7 @@
// active thread count
details.append('text')
- .attr({
+ .attrs({
'class': 'active-thread-count-icon',
'y': 43 + offset
})
@@ -305,7 +308,7 @@
// active thread icon
details.append('text')
- .attr({
+ .attrs({
'class': 'active-thread-count',
'y': 43 + offset
});
@@ -416,7 +419,7 @@
// update the run status
updated.select('text.run-status-icon')
- .attr({
+ .attrs({
'fill': function (d) {
var fill = '#728e9b';
@@ -487,7 +490,7 @@
});
updated.select('text.port-transmission-icon')
- .attr({
+ .attrs({
'font-family': function (d) {
if (d.status.transmitting === true) {
return 'FontAwesome';
@@ -594,7 +597,7 @@
// create the port container
portContainer = d3.select('#canvas').append('g')
- .attr({
+ .attrs({
'pointer-events': 'all',
'class': 'ports'
});
@@ -643,10 +646,14 @@
add(portEntities);
}
- // apply the selection and handle new ports
+ // select
var selection = select();
- selection.enter().call(renderPorts, selectAll);
- selection.call(updatePorts);
+
+ // enter
+ var entered = renderPorts(selection.enter(), selectAll);
+
+ // update
+ updatePorts(selection.merge(entered));
},
/**
@@ -707,10 +714,17 @@
set(portEntities);
}
- // apply the selection and handle all new ports
+ // select
var selection = select();
- selection.enter().call(renderPorts, selectAll);
- selection.call(updatePorts).call(nfCanvasUtils.position, transition);
+
+ // enter
+ var entered = renderPorts(selection.enter(), selectAll);
+
+ // update
+ var updated = selection.merge(entered);
+ updated.call(updatePorts).call(nfCanvasUtils.position, transition);
+
+ // exit
selection.exit().call(removePorts);
},
@@ -813,7 +827,7 @@
*/
expireCaches: function (timestamp) {
var expire = function (cache) {
- cache.forEach(function (id, entryTimestamp) {
+ cache.each(function (entryTimestamp, id) {
if (timestamp > entryTimestamp) {
cache.remove(id);
}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-process-group.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-process-group.js
index dc7034ae9f9a..dd147c4d0dd8 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-process-group.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-process-group.js
@@ -108,14 +108,15 @@
*
* @param {selection} entered The selection of process groups to be rendered
* @param {boolean} selected Whether the process group should be selected
+ * @return the entered selection
*/
var renderProcessGroups = function (entered, selected) {
if (entered.empty()) {
- return;
+ return entered;
}
var processGroup = entered.append('g')
- .attr({
+ .attrs({
'id': function (d) {
return 'id-' + d.id;
},
@@ -130,7 +131,7 @@
// process group border
processGroup.append('rect')
- .attr({
+ .attrs({
'class': 'border',
'width': function (d) {
return d.dimensions.width;
@@ -144,7 +145,7 @@
// process group body
processGroup.append('rect')
- .attr({
+ .attrs({
'class': 'body',
'width': function (d) {
return d.dimensions.width;
@@ -158,7 +159,7 @@
// process group name background
processGroup.append('rect')
- .attr({
+ .attrs({
'width': function (d) {
return d.dimensions.width;
},
@@ -168,7 +169,7 @@
// process group name
processGroup.append('text')
- .attr({
+ .attrs({
'x': 10,
'y': 20,
'width': 316,
@@ -178,7 +179,7 @@
// process group name
processGroup.append('text')
- .attr({
+ .attrs({
'x': 10,
'y': 21,
'class': 'version-control'
@@ -228,6 +229,8 @@
})
.call(nfDraggable.activate)
.call(nfConnectable.activate);
+
+ return processGroup;
};
// attempt of space between component count and icon for process group contents
@@ -273,7 +276,7 @@
// -------------------
details.append('rect')
- .attr({
+ .attrs({
'x': 0,
'y': 32,
'width': function () {
@@ -284,7 +287,7 @@
});
details.append('rect')
- .attr({
+ .attrs({
'x': 0,
'y': function () {
return processGroupData.dimensions.height - 24;
@@ -302,7 +305,7 @@
// transmitting icon
details.append('text')
- .attr({
+ .attrs({
'x': 10,
'y': 49,
'class': 'process-group-transmitting process-group-contents-icon',
@@ -315,14 +318,14 @@
// transmitting count
details.append('text')
- .attr({
+ .attrs({
'y': 49,
'class': 'process-group-transmitting-count process-group-contents-count'
});
// not transmitting icon
details.append('text')
- .attr({
+ .attrs({
'y': 49,
'class': 'process-group-not-transmitting process-group-contents-icon',
'font-family': 'flowfont'
@@ -333,14 +336,14 @@
// not transmitting count
details.append('text')
- .attr({
+ .attrs({
'y': 49,
'class': 'process-group-not-transmitting-count process-group-contents-count'
});
// running icon
details.append('text')
- .attr({
+ .attrs({
'y': 49,
'class': 'process-group-running process-group-contents-icon',
'font-family': 'FontAwesome'
@@ -351,14 +354,14 @@
// running count
details.append('text')
- .attr({
+ .attrs({
'y': 49,
'class': 'process-group-running-count process-group-contents-count'
});
// stopped icon
details.append('text')
- .attr({
+ .attrs({
'y': 49,
'class': 'process-group-stopped process-group-contents-icon',
'font-family': 'FontAwesome'
@@ -369,14 +372,14 @@
// stopped count
details.append('text')
- .attr({
+ .attrs({
'y': 49,
'class': 'process-group-stopped-count process-group-contents-count'
});
// invalid icon
details.append('text')
- .attr({
+ .attrs({
'y': 49,
'class': 'process-group-invalid process-group-contents-icon',
'font-family': 'FontAwesome'
@@ -387,14 +390,14 @@
// invalid count
details.append('text')
- .attr({
+ .attrs({
'y': 49,
'class': 'process-group-invalid-count process-group-contents-count'
});
// disabled icon
details.append('text')
- .attr({
+ .attrs({
'y': 49,
'class': 'process-group-disabled process-group-contents-icon',
'font-family': 'flowfont'
@@ -405,14 +408,14 @@
// disabled count
details.append('text')
- .attr({
+ .attrs({
'y': 49,
'class': 'process-group-disabled-count process-group-contents-count'
});
// up to date icon
details.append('text')
- .attr({
+ .attrs({
'x': 10,
'y': function () {
return processGroupData.dimensions.height - 7;
@@ -426,7 +429,7 @@
// up to date count
details.append('text')
- .attr({
+ .attrs({
'y': function () {
return processGroupData.dimensions.height - 7;
},
@@ -435,7 +438,7 @@
// locally modified icon
details.append('text')
- .attr({
+ .attrs({
'y': function () {
return processGroupData.dimensions.height - 7;
},
@@ -448,7 +451,7 @@
// locally modified count
details.append('text')
- .attr({
+ .attrs({
'y': function () {
return processGroupData.dimensions.height - 7;
},
@@ -457,7 +460,7 @@
// stale icon
details.append('text')
- .attr({
+ .attrs({
'y': function () {
return processGroupData.dimensions.height - 7;
},
@@ -470,7 +473,7 @@
// stale count
details.append('text')
- .attr({
+ .attrs({
'y': function () {
return processGroupData.dimensions.height - 7;
},
@@ -479,7 +482,7 @@
// locally modified and stale icon
details.append('text')
- .attr({
+ .attrs({
'y': function () {
return processGroupData.dimensions.height - 7;
},
@@ -492,7 +495,7 @@
// locally modified and stale count
details.append('text')
- .attr({
+ .attrs({
'y': function () {
return processGroupData.dimensions.height - 7;
},
@@ -501,7 +504,7 @@
// sync failure icon
details.append('text')
- .attr({
+ .attrs({
'y': function () {
return processGroupData.dimensions.height - 7;
},
@@ -514,7 +517,7 @@
// sync failure count
details.append('text')
- .attr({
+ .attrs({
'y': function () {
return processGroupData.dimensions.height - 7;
},
@@ -527,7 +530,7 @@
// queued
details.append('rect')
- .attr({
+ .attrs({
'width': function () {
return processGroupData.dimensions.width;
},
@@ -539,7 +542,7 @@
// border
details.append('rect')
- .attr({
+ .attrs({
'width': function () {
return processGroupData.dimensions.width;
},
@@ -551,7 +554,7 @@
// in
details.append('rect')
- .attr({
+ .attrs({
'width': function () {
return processGroupData.dimensions.width;
},
@@ -563,7 +566,7 @@
// border
details.append('rect')
- .attr({
+ .attrs({
'width': function () {
return processGroupData.dimensions.width;
},
@@ -575,7 +578,7 @@
// read/write
details.append('rect')
- .attr({
+ .attrs({
'width': function () {
return processGroupData.dimensions.width;
},
@@ -587,7 +590,7 @@
// border
details.append('rect')
- .attr({
+ .attrs({
'width': function () {
return processGroupData.dimensions.width;
},
@@ -599,7 +602,7 @@
// out
details.append('rect')
- .attr({
+ .attrs({
'width': function () {
return processGroupData.dimensions.width;
},
@@ -615,13 +618,13 @@
// stats label container
var processGroupStatsLabel = details.append('g')
- .attr({
+ .attrs({
'transform': 'translate(6, 75)'
});
// queued label
processGroupStatsLabel.append('text')
- .attr({
+ .attrs({
'width': 73,
'height': 10,
'x': 4,
@@ -632,7 +635,7 @@
// in label
processGroupStatsLabel.append('text')
- .attr({
+ .attrs({
'width': 73,
'height': 10,
'x': 4,
@@ -643,7 +646,7 @@
// read/write label
processGroupStatsLabel.append('text')
- .attr({
+ .attrs({
'width': 73,
'height': 10,
'x': 4,
@@ -654,7 +657,7 @@
// out label
processGroupStatsLabel.append('text')
- .attr({
+ .attrs({
'width': 73,
'height': 10,
'x': 4,
@@ -665,13 +668,13 @@
// stats value container
var processGroupStatsValue = details.append('g')
- .attr({
+ .attrs({
'transform': 'translate(95, 75)'
});
// queued value
var queuedText = processGroupStatsValue.append('text')
- .attr({
+ .attrs({
'width': 180,
'height': 10,
'x': 4,
@@ -681,19 +684,19 @@
// queued count
queuedText.append('tspan')
- .attr({
+ .attrs({
'class': 'count'
});
// queued size
queuedText.append('tspan')
- .attr({
+ .attrs({
'class': 'size'
});
// in value
var inText = processGroupStatsValue.append('text')
- .attr({
+ .attrs({
'width': 180,
'height': 10,
'x': 4,
@@ -703,25 +706,25 @@
// in count
inText.append('tspan')
- .attr({
+ .attrs({
'class': 'count'
});
// in size
inText.append('tspan')
- .attr({
+ .attrs({
'class': 'size'
});
// in
inText.append('tspan')
- .attr({
+ .attrs({
'class': 'ports'
});
// read/write value
processGroupStatsValue.append('text')
- .attr({
+ .attrs({
'width': 180,
'height': 10,
'x': 4,
@@ -731,7 +734,7 @@
// out value
var outText = processGroupStatsValue.append('text')
- .attr({
+ .attrs({
'width': 180,
'height': 10,
'x': 4,
@@ -741,31 +744,31 @@
// out ports
outText.append('tspan')
- .attr({
+ .attrs({
'class': 'ports'
});
// out count
outText.append('tspan')
- .attr({
+ .attrs({
'class': 'count'
});
// out size
outText.append('tspan')
- .attr({
+ .attrs({
'class': 'size'
});
// stats value container
var processGroupStatsInfo = details.append('g')
- .attr({
+ .attrs({
'transform': 'translate(335, 75)'
});
// in info
processGroupStatsInfo.append('text')
- .attr({
+ .attrs({
'width': 25,
'height': 10,
'x': 4,
@@ -776,7 +779,7 @@
// read/write info
processGroupStatsInfo.append('text')
- .attr({
+ .attrs({
'width': 25,
'height': 10,
'x': 4,
@@ -787,7 +790,7 @@
// out info
processGroupStatsInfo.append('text')
- .attr({
+ .attrs({
'width': 25,
'height': 10,
'x': 4,
@@ -801,7 +804,7 @@
// --------
details.append('path')
- .attr({
+ .attrs({
'class': 'component-comments',
'transform': 'translate(' + (processGroupData.dimensions.width - 2) + ', ' + (processGroupData.dimensions.height - 10) + ')',
'd': 'm0,0 l0,8 l-8,0 z'
@@ -813,7 +816,7 @@
// active thread count
details.append('text')
- .attr({
+ .attrs({
'class': 'active-thread-count-icon',
'y': 20
})
@@ -821,7 +824,7 @@
// active thread icon
details.append('text')
- .attr({
+ .attrs({
'class': 'active-thread-count',
'y': 20
});
@@ -832,7 +835,7 @@
// bulletin background
details.append('rect')
- .attr({
+ .attrs({
'class': 'bulletin-background',
'x': function () {
return processGroupData.dimensions.width - 24;
@@ -844,7 +847,7 @@
// bulletin icon
details.append('text')
- .attr({
+ .attrs({
'class': 'bulletin-icon',
'x': function () {
return processGroupData.dimensions.width - 17;
@@ -1090,7 +1093,7 @@
// update version control information
var versionControl = processGroup.select('text.version-control')
- .style({
+ .styles({
'visibility': isUnderVersionControl(processGroupData) ? 'visible' : 'hidden',
'fill': function () {
if (isUnderVersionControl(processGroupData)) {
@@ -1198,7 +1201,7 @@
// update the process group name
processGroup.select('text.process-group-name')
- .attr({
+ .attrs({
'x': function () {
if (isUnderVersionControl(processGroupData)) {
var versionControlX = parseInt(versionControl.attr('x'), 10);
@@ -1236,7 +1239,7 @@
// clear the process group name
processGroup.select('text.process-group-name')
- .attr({
+ .attrs({
'x': 10,
'width': 316
})
@@ -1414,7 +1417,7 @@
// create the process group container
processGroupContainer = d3.select('#canvas').append('g')
- .attr({
+ .attrs({
'pointer-events': 'all',
'class': 'process-groups'
});
@@ -1454,10 +1457,14 @@
add(processGroupEntities);
}
- // apply the selection and handle new process groups
+ // select
var selection = select();
- selection.enter().call(renderProcessGroups, selectAll);
- selection.call(updateProcessGroups);
+
+ // enter
+ var entered = renderProcessGroups(selection.enter(), selectAll);
+
+ // update
+ updateProcessGroups(selection.merge(entered));
},
/**
@@ -1508,10 +1515,17 @@
set(processGroupEntities);
}
- // apply the selection and handle all new process group
+ // select
var selection = select();
- selection.enter().call(renderProcessGroups, selectAll);
- selection.call(updateProcessGroups).call(nfCanvasUtils.position, transition);
+
+ // enter
+ var entered = renderProcessGroups(selection.enter(), selectAll);
+
+ // update
+ var updated = selection.merge(entered);
+ updated.call(updateProcessGroups).call(nfCanvasUtils.position, transition);
+
+ // exit
selection.exit().call(removeProcessGroups);
},
@@ -1614,7 +1628,7 @@
*/
expireCaches: function (timestamp) {
var expire = function (cache) {
- cache.forEach(function (id, entryTimestamp) {
+ cache.each(function (entryTimestamp, id) {
if (timestamp > entryTimestamp) {
cache.remove(id);
}
@@ -1646,12 +1660,7 @@
// if the view was not restore attempt to fit
if (viewRestored === false) {
- nfCanvasUtils.fitCanvasView();
-
- // refresh the canvas
- nfCanvasUtils.refreshCanvasView({
- transition: true
- });
+ nfCanvasUtils.fitCanvas();
}
// update URL deep linking params
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-processor.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-processor.js
index 8b991a3d6473..b30c9813e801 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-processor.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-processor.js
@@ -93,14 +93,20 @@
});
};
- // renders the processors
+ /**
+ * Renders the processors in the specified selection.
+ *
+ * @param {selection} entered The selection of processors to be rendered
+ * @param {boolean} selected Whether the element should be selected
+ * @return the entered selection
+ */
var renderProcessors = function (entered, selected) {
if (entered.empty()) {
- return;
+ return entered;
}
var processor = entered.append('g')
- .attr({
+ .attrs({
'id': function (d) {
return 'id-' + d.id;
},
@@ -111,7 +117,7 @@
// processor border
processor.append('rect')
- .attr({
+ .attrs({
'class': 'border',
'width': function (d) {
return d.dimensions.width;
@@ -125,7 +131,7 @@
// processor body
processor.append('rect')
- .attr({
+ .attrs({
'class': 'body',
'width': function (d) {
return d.dimensions.width;
@@ -139,7 +145,7 @@
// processor name
processor.append('text')
- .attr({
+ .attrs({
'x': 75,
'y': 18,
'width': 210,
@@ -149,7 +155,7 @@
// processor icon container
processor.append('rect')
- .attr({
+ .attrs({
'x': 0,
'y': 0,
'width': 50,
@@ -159,7 +165,7 @@
// processor icon
processor.append('text')
- .attr({
+ .attrs({
'x': 9,
'y': 35,
'class': 'processor-icon'
@@ -168,7 +174,7 @@
// restricted icon background
processor.append('circle')
- .attr({
+ .attrs({
'r': 9,
'cx': 12,
'cy': 12,
@@ -177,7 +183,7 @@
// restricted icon
processor.append('text')
- .attr({
+ .attrs({
'x': 7.75,
'y': 17,
'class': 'restricted'
@@ -186,7 +192,7 @@
// is primary icon background
processor.append('circle')
- .attr({
+ .attrs({
'r': 9,
'cx': 38,
'cy': 36,
@@ -195,7 +201,7 @@
// is primary icon
processor.append('text')
- .attr({
+ .attrs({
'x': 34.75,
'y': 40,
'class': 'is-primary'
@@ -207,6 +213,8 @@
// make processors selectable
processor.call(nfSelectable.activate).call(nfContextMenu.activate).call(nfQuickSelect.activate);
+
+ return processor;
};
/**
@@ -248,7 +256,7 @@
// run status icon
details.append('text')
- .attr({
+ .attrs({
'class': 'run-status-icon',
'x': 55,
'y': 23
@@ -256,7 +264,7 @@
// processor type
details.append('text')
- .attr({
+ .attrs({
'class': 'processor-type',
'x': 75,
'y': 32,
@@ -266,7 +274,7 @@
// processor type
details.append('text')
- .attr({
+ .attrs({
'class': 'processor-bundle',
'x': 75,
'y': 45,
@@ -282,7 +290,7 @@
// in
details.append('rect')
- .attr({
+ .attrs({
'width': function () {
return processorData.dimensions.width;
},
@@ -294,7 +302,7 @@
// border
details.append('rect')
- .attr({
+ .attrs({
'width': function () {
return processorData.dimensions.width;
},
@@ -306,7 +314,7 @@
// read/write
details.append('rect')
- .attr({
+ .attrs({
'width': function () {
return processorData.dimensions.width;
},
@@ -318,7 +326,7 @@
// border
details.append('rect')
- .attr({
+ .attrs({
'width': function () {
return processorData.dimensions.width;
},
@@ -330,7 +338,7 @@
// out
details.append('rect')
- .attr({
+ .attrs({
'width': function () {
return processorData.dimensions.width;
},
@@ -342,7 +350,7 @@
// border
details.append('rect')
- .attr({
+ .attrs({
'width': function () {
return processorData.dimensions.width;
},
@@ -354,7 +362,7 @@
// tasks/time
details.append('rect')
- .attr({
+ .attrs({
'width': function () {
return processorData.dimensions.width;
},
@@ -366,13 +374,13 @@
// stats label container
var processorStatsLabel = details.append('g')
- .attr({
+ .attrs({
'transform': 'translate(10, 55)'
});
// in label
processorStatsLabel.append('text')
- .attr({
+ .attrs({
'width': 73,
'height': 10,
'y': 9,
@@ -382,7 +390,7 @@
// read/write label
processorStatsLabel.append('text')
- .attr({
+ .attrs({
'width': 73,
'height': 10,
'y': 27,
@@ -392,7 +400,7 @@
// out label
processorStatsLabel.append('text')
- .attr({
+ .attrs({
'width': 73,
'height': 10,
'y': 46,
@@ -402,7 +410,7 @@
// tasks/time label
processorStatsLabel.append('text')
- .attr({
+ .attrs({
'width': 73,
'height': 10,
'y': 65,
@@ -412,13 +420,13 @@
// stats value container
var processorStatsValue = details.append('g')
- .attr({
+ .attrs({
'transform': 'translate(85, 55)'
});
// in value
var inText = processorStatsValue.append('text')
- .attr({
+ .attrs({
'width': 180,
'height': 9,
'y': 9,
@@ -427,19 +435,19 @@
// in count
inText.append('tspan')
- .attr({
+ .attrs({
'class': 'count'
});
// in size
inText.append('tspan')
- .attr({
+ .attrs({
'class': 'size'
});
// read/write value
processorStatsValue.append('text')
- .attr({
+ .attrs({
'width': 180,
'height': 10,
'y': 27,
@@ -448,7 +456,7 @@
// out value
var outText = processorStatsValue.append('text')
- .attr({
+ .attrs({
'width': 180,
'height': 10,
'y': 46,
@@ -457,19 +465,19 @@
// out count
outText.append('tspan')
- .attr({
+ .attrs({
'class': 'count'
});
// out size
outText.append('tspan')
- .attr({
+ .attrs({
'class': 'size'
});
// tasks/time value
processorStatsValue.append('text')
- .attr({
+ .attrs({
'width': 180,
'height': 10,
'y': 65,
@@ -482,7 +490,7 @@
// in info
processorStatsInfo.append('text')
- .attr({
+ .attrs({
'width': 25,
'height': 10,
'y': 9,
@@ -492,7 +500,7 @@
// read/write info
processorStatsInfo.append('text')
- .attr({
+ .attrs({
'width': 25,
'height': 10,
'y': 27,
@@ -502,7 +510,7 @@
// out info
processorStatsInfo.append('text')
- .attr({
+ .attrs({
'width': 25,
'height': 10,
'y': 46,
@@ -512,7 +520,7 @@
// tasks/time info
processorStatsInfo.append('text')
- .attr({
+ .attrs({
'width': 25,
'height': 10,
'y': 65,
@@ -525,7 +533,7 @@
// --------
details.append('path')
- .attr({
+ .attrs({
'class': 'component-comments',
'transform': 'translate(' + (processorData.dimensions.width - 2) + ', ' + (processorData.dimensions.height - 10) + ')',
'd': 'm0,0 l0,8 l-8,0 z'
@@ -537,7 +545,7 @@
// active thread count
details.append('text')
- .attr({
+ .attrs({
'class': 'active-thread-count-icon',
'y': 45
})
@@ -545,7 +553,7 @@
// active thread background
details.append('text')
- .attr({
+ .attrs({
'class': 'active-thread-count',
'y': 45
});
@@ -556,7 +564,7 @@
// bulletin background
details.append('rect')
- .attr({
+ .attrs({
'class': 'bulletin-background',
'x': function (d) {
return processorData.dimensions.width - 24;
@@ -567,7 +575,7 @@
// bulletin icon
details.append('text')
- .attr({
+ .attrs({
'class': 'bulletin-icon',
'x': function (d) {
return processorData.dimensions.width - 17;
@@ -799,7 +807,7 @@
// update the run status
updated.select('text.run-status-icon')
- .attr({
+ .attrs({
'fill': function (d) {
var fill = '#728e9b';
@@ -978,7 +986,7 @@
// create the processor container
processorContainer = d3.select('#canvas').append('g')
- .attr({
+ .attrs({
'pointer-events': 'all',
'class': 'processors'
});
@@ -1018,10 +1026,14 @@
add(processorEntities);
}
- // apply the selection and handle new processor
+ // select
var selection = select();
- selection.enter().call(renderProcessors, selectAll);
- selection.call(updateProcessors);
+
+ // enter
+ var entered = renderProcessors(selection.enter(), selectAll);
+
+ // update
+ updateProcessors(selection.merge(entered));
},
/**
@@ -1072,10 +1084,18 @@
set(processorEntities);
}
- // apply the selection and handle all new processors
+ // select
var selection = select();
- selection.enter().call(renderProcessors, selectAll);
- selection.call(updateProcessors).call(nfCanvasUtils.position, transition);
+
+ // enter
+ var entered = renderProcessors(selection.enter(), selectAll);
+
+ // update
+ var updated = selection.merge(entered);
+ updated.call(updateProcessors);
+ updated.call(nfCanvasUtils.position, transition);
+
+ // exit
selection.exit().call(removeProcessors);
},
@@ -1178,7 +1198,7 @@
*/
expireCaches: function (timestamp) {
var expire = function (cache) {
- cache.forEach(function (id, entryTimestamp) {
+ cache.each(function (entryTimestamp, id) {
if (timestamp > entryTimestamp) {
cache.remove(id);
}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-remote-process-group.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-remote-process-group.js
index a58d8db89f03..ce3755cc5330 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-remote-process-group.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-remote-process-group.js
@@ -97,14 +97,15 @@
*
* @param {selection} entered The selection of remote process groups to be rendered
* @param {boolean} selected Whether the remote process group is selected
+ * @return the entered selection
*/
var renderRemoteProcessGroups = function (entered, selected) {
if (entered.empty()) {
- return;
+ return entered;
}
var remoteProcessGroup = entered.append('g')
- .attr({
+ .attrs({
'id': function (d) {
return 'id-' + d.id;
},
@@ -119,7 +120,7 @@
// remote process group border
remoteProcessGroup.append('rect')
- .attr({
+ .attrs({
'class': 'border',
'width': function (d) {
return d.dimensions.width;
@@ -133,7 +134,7 @@
// remote process group body
remoteProcessGroup.append('rect')
- .attr({
+ .attrs({
'class': 'body',
'width': function (d) {
return d.dimensions.width;
@@ -147,7 +148,7 @@
// remote process group name background
remoteProcessGroup.append('rect')
- .attr({
+ .attrs({
'width': function (d) {
return d.dimensions.width;
},
@@ -157,7 +158,7 @@
// remote process group name
remoteProcessGroup.append('text')
- .attr({
+ .attrs({
'x': 30,
'y': 20,
'width': 305,
@@ -167,6 +168,8 @@
// always support selection
remoteProcessGroup.call(nfSelectable.activate).call(nfContextMenu.activate).call(nfQuickSelect.activate);
+
+ return remoteProcessGroup;
};
/**
@@ -205,7 +208,7 @@
// remote process group transmission status
details.append('text')
- .attr({
+ .attrs({
'class': 'remote-process-group-transmission-status',
'x': 10,
'y': 20
@@ -216,7 +219,7 @@
// ------------------
details.append('rect')
- .attr({
+ .attrs({
'x': 0,
'y': 32,
'width': function () {
@@ -232,7 +235,7 @@
// remote process group secure transfer
details.append('text')
- .attr({
+ .attrs({
'class': 'remote-process-group-transmission-secure',
'x': 10,
'y': 48
@@ -240,7 +243,7 @@
// remote process group uri
details.append('text')
- .attr({
+ .attrs({
'x': 30,
'y': 48,
'width': 305,
@@ -254,7 +257,7 @@
// sent
details.append('rect')
- .attr({
+ .attrs({
'width': function () {
return remoteProcessGroupData.dimensions.width;
},
@@ -266,7 +269,7 @@
// border
details.append('rect')
- .attr({
+ .attrs({
'width': function () {
return remoteProcessGroupData.dimensions.width;
},
@@ -278,7 +281,7 @@
// received
details.append('rect')
- .attr({
+ .attrs({
'width': function () {
return remoteProcessGroupData.dimensions.width;
},
@@ -294,13 +297,13 @@
// stats label container
var remoteProcessGroupStatsLabel = details.append('g')
- .attr({
+ .attrs({
'transform': 'translate(6, 75)'
});
// sent label
remoteProcessGroupStatsLabel.append('text')
- .attr({
+ .attrs({
'width': 73,
'height': 10,
'x': 4,
@@ -311,7 +314,7 @@
// received label
remoteProcessGroupStatsLabel.append('text')
- .attr({
+ .attrs({
'width': 73,
'height': 10,
'x': 4,
@@ -322,13 +325,13 @@
// stats value container
var remoteProcessGroupStatsValue = details.append('g')
- .attr({
+ .attrs({
'transform': 'translate(95, 75)'
});
// sent value
var sentText = remoteProcessGroupStatsValue.append('text')
- .attr({
+ .attrs({
'width': 180,
'height': 10,
'x': 4,
@@ -338,25 +341,25 @@
// sent count
sentText.append('tspan')
- .attr({
+ .attrs({
'class': 'count'
});
// sent size
sentText.append('tspan')
- .attr({
+ .attrs({
'class': 'size'
});
// sent ports
sentText.append('tspan')
- .attr({
+ .attrs({
'class': 'ports'
});
// received value
var receivedText = remoteProcessGroupStatsValue.append('text')
- .attr({
+ .attrs({
'width': 180,
'height': 10,
'x': 4,
@@ -366,31 +369,31 @@
// received ports
receivedText.append('tspan')
- .attr({
+ .attrs({
'class': 'ports'
});
// received count
receivedText.append('tspan')
- .attr({
+ .attrs({
'class': 'count'
});
// received size
receivedText.append('tspan')
- .attr({
+ .attrs({
'class': 'size'
});
// stats value container
var processGroupStatsInfo = details.append('g')
- .attr({
+ .attrs({
'transform': 'translate(335, 75)'
});
// sent info
processGroupStatsInfo.append('text')
- .attr({
+ .attrs({
'width': 25,
'height': 10,
'x': 4,
@@ -401,7 +404,7 @@
// received info
processGroupStatsInfo.append('text')
- .attr({
+ .attrs({
'width': 25,
'height': 10,
'x': 4,
@@ -415,7 +418,7 @@
// -------------------
details.append('rect')
- .attr({
+ .attrs({
'x': 0,
'y': function () {
return remoteProcessGroupData.dimensions.height - 24;
@@ -428,7 +431,7 @@
});
details.append('text')
- .attr({
+ .attrs({
'x': 10,
'y': 150,
'class': 'remote-process-group-last-refresh'
@@ -439,7 +442,7 @@
// --------
details.append('path')
- .attr({
+ .attrs({
'class': 'component-comments',
'transform': 'translate(' + (remoteProcessGroupData.dimensions.width - 2) + ', ' + (remoteProcessGroupData.dimensions.height - 10) + ')',
'd': 'm0,0 l0,8 l-8,0 z'
@@ -451,7 +454,7 @@
// active thread count
details.append('text')
- .attr({
+ .attrs({
'class': 'active-thread-count-icon',
'y': 20
})
@@ -459,7 +462,7 @@
// active thread icon
details.append('text')
- .attr({
+ .attrs({
'class': 'active-thread-count',
'y': 20
});
@@ -470,7 +473,7 @@
// bulletin background
details.append('rect')
- .attr({
+ .attrs({
'class': 'bulletin-background',
'x': function () {
return remoteProcessGroupData.dimensions.width - 24;
@@ -482,7 +485,7 @@
// bulletin icon
details.append('text')
- .attr({
+ .attrs({
'class': 'bulletin-icon',
'x': function () {
return remoteProcessGroupData.dimensions.width - 17;
@@ -867,7 +870,7 @@
// create the process group container
remoteProcessGroupContainer = d3.select('#canvas').append('g')
- .attr({
+ .attrs({
'pointer-events': 'all',
'class': 'remote-process-groups'
});
@@ -907,10 +910,14 @@
add(remoteProcessGroupEntities);
}
- // apply the selection and handle new remote process groups
+ // select
var selection = select();
- selection.enter().call(renderRemoteProcessGroups, selectAll);
- selection.call(updateRemoteProcessGroups);
+
+ // enter
+ var entered = renderRemoteProcessGroups(selection.enter(), selectAll);
+
+ // update
+ updateRemoteProcessGroups(selection.merge(entered));
},
/**
@@ -961,10 +968,17 @@
set(remoteProcessGroupEntities);
}
- // apply the selection and handle all new remote process groups
+ // select
var selection = select();
- selection.enter().call(renderRemoteProcessGroups, selectAll);
- selection.call(updateRemoteProcessGroups).call(nfCanvasUtils.position, transition);
+
+ // enter
+ var entered = renderRemoteProcessGroups(selection.enter(), selectAll);
+
+ // update
+ var updated = selection.merge(entered);
+ updated.call(updateRemoteProcessGroups).call(nfCanvasUtils.position, transition);
+
+ // exit
selection.exit().call(removeRemoteProcessGroups);
},
@@ -1075,7 +1089,7 @@
*/
expireCaches: function (timestamp) {
var expire = function (cache) {
- cache.forEach(function (id, entryTimestamp) {
+ cache.each(function (entryTimestamp, id) {
if (timestamp > entryTimestamp) {
cache.remove(id);
}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-settings.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-settings.js
index d3289c764651..824312adb558 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-settings.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-settings.js
@@ -756,7 +756,7 @@
text: 'all groups',
value: ''
}];
- groups.forEach(function (group) {
+ groups.each(function (group) {
options.push({
text: group,
value: group
@@ -1799,7 +1799,7 @@
})
.map(reportingTaskBulletins, d3.map);
- reportingTaskBulletinsBySource.forEach(function (sourceId, sourceBulletins) {
+ reportingTaskBulletinsBySource.each(function (sourceBulletins, sourceId) {
var reportingTask = reportingTasksData.getItemById(sourceId);
if (nfCommon.isDefinedAndNotNull(reportingTask)) {
reportingTasksData.updateItem(sourceId, $.extend(reportingTask, {
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-variable-registry.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-variable-registry.js
index 24c00ab0a109..7265b7074678 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-variable-registry.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-variable-registry.js
@@ -920,7 +920,7 @@
})
.map(bulletins, d3.map);
- bulletinsBySource.forEach(function (sourceId, sourceBulletins) {
+ bulletinsBySource.each(function (sourceBulletins, sourceId) {
$('div.' + sourceId + '-affected-bulletins').each(function () {
var bulletinIcon = $(this);
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-status-history.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-status-history.js
index 190160025dfb..83cf5f8d6d07 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-status-history.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-status-history.js
@@ -87,9 +87,9 @@
var serverTimeOffset = null;
/**
- * The current extent of the brush.
+ * The current selection of the brush.
*/
- var brushExtent = null;
+ var brushSelection = null;
/**
* The currently selected descriptor.
@@ -192,7 +192,7 @@
// get the current user time to properly convert the server time
var now = new Date();
- // conver the user offset to millis
+ // convert the user offset to millis
var userTimeOffset = now.getTimezoneOffset() * 60 * 1000;
// create the proper date by adjusting by the offsets
@@ -240,7 +240,7 @@
if (selectedDescriptor !== null) {
// clear the current extent if this is a newly selected descriptor
if (descriptor === null || descriptor.field !== selectedDescriptor.field) {
- brushExtent = null;
+ brushSelection = null;
}
// record the currently selected descriptor
@@ -296,7 +296,7 @@
// add status history details
var detailsContainer = buildDetailsContainer('Status History');
- d3.map(statusHistory.details).forEach(function (label, value) {
+ d3.map(statusHistory.details).each(function (value, label) {
addDetailItem(detailsContainer, label, value);
});
@@ -312,7 +312,7 @@
// -------------
// available colors
- var color = d3.scale.category10();
+ var color = d3.scaleOrdinal(d3.schemeCategory10);
// determine the available instances
var instanceLabels = [];
@@ -351,32 +351,23 @@
// custom time axis formatter
// --------------------------
- var customTimeFormat = d3.time.format.multi([
- [':%S.%L', function (d) {
- return d.getMilliseconds();
- }],
- [':%S', function (d) {
- return d.getSeconds();
- }],
- ['%H:%M', function (d) {
- return d.getMinutes();
- }],
- ['%H:%M', function (d) {
- return d.getHours();
- }],
- ['%a %d', function (d) {
- return d.getDay() && d.getDate() !== 1;
- }],
- ['%b %d', function (d) {
- return d.getDate() !== 1;
- }],
- ['%B', function (d) {
- return d.getMonth();
- }],
- ['%Y', function () {
- return true;
- }]
- ]);
+ var customTimeFormat = function (d) {
+ if (d.getMilliseconds()) {
+ return d3.timeFormat(':%S.%L')(d);
+ } else if (d.getSeconds()) {
+ return d3.timeFormat(':%S')(d);
+ } else if (d.getMinutes() || d.getHours()) {
+ return d3.timeFormat('%H:%M')(d);
+ } else if (d.getDay() && d.getDate() !== 1) {
+ return d3.timeFormat('%a %d')(d);
+ } else if (d.getDate() !== 1) {
+ return d3.timeFormat('%b %d')(d);
+ } else if (d.getMonth()) {
+ return d3.timeFormat('%B')(d);
+ } else {
+ return d3.timeFormat('%Y')(d);
+ }
+ };
// ----------
// main chart
@@ -407,28 +398,23 @@
}
// define the x axis for the main chart
- var x = d3.time.scale()
+ var x = d3.scaleTime()
.range([0, width]);
- var xAxis = d3.svg.axis()
- .scale(x)
+ var xAxis = d3.axisBottom(x)
.ticks(5)
- .tickFormat(customTimeFormat)
- .orient('bottom');
+ .tickFormat(customTimeFormat);
// define the y axis
- var y = d3.scale.linear()
+ var y = d3.scaleLinear()
.range([height, 0]);
- var yAxis = d3.svg.axis()
- .scale(y)
- .tickFormat(formatters[selectedDescriptor.formatter])
- .orient('left');
-
+ var yAxis = d3.axisLeft(y)
+ .tickFormat(formatters[selectedDescriptor.formatter]);
// status line
- var line = d3.svg.line()
- .interpolate('monotone')
+ var line = d3.line()
+ .curve(d3.curveMonotoneX)
.x(function (d) {
return x(d.timestamp);
})
@@ -441,6 +427,7 @@
.attr('style', 'pointer-events: none;')
.attr('width', chartContainer.parent().width())
.attr('height', chartContainer.innerHeight());
+
// define a clip the path
var clipPath = chartSvg.append('defs').append('clipPath')
.attr('id', 'clip')
@@ -569,27 +556,23 @@
var chartControlContainer = $('#status-history-chart-control-container').empty();
var controlHeight = chartControlContainer.innerHeight() - margin.top - margin.bottom;
- var xControl = d3.time.scale()
+ var xControl = d3.scaleTime()
.range([0, width]);
- var xControlAxis = d3.svg.axis()
- .scale(xControl)
+ var xControlAxis = d3.axisBottom(xControl)
.ticks(5)
- .tickFormat(customTimeFormat)
- .orient('bottom');
+ .tickFormat(customTimeFormat);
- var yControl = d3.scale.linear()
+ var yControl = d3.scaleLinear()
.range([controlHeight, 0]);
- var yControlAxis = d3.svg.axis()
- .scale(yControl)
+ var yControlAxis = d3.axisLeft(yControl)
.tickValues(y.domain())
- .tickFormat(formatters[selectedDescriptor.formatter])
- .orient('left');
+ .tickFormat(formatters[selectedDescriptor.formatter]);
// status line
- var controlLine = d3.svg.line()
- .interpolate('monotone')
+ var controlLine = d3.line()
+ .curve(d3.curveMonotoneX)
.x(function (d) {
return xControl(d.timestamp);
})
@@ -606,13 +589,9 @@
var control = controlChartSvg.append('g')
.attr('transform', 'translate(' + margin.left + ', ' + margin.top + ')');
- // increase the y domain slightly
- var yControlDomain = y.domain();
- yControlDomain[1] *= 1.04;
-
// define the domain for the control chart
xControl.domain(x.domain());
- yControl.domain(yControlDomain);
+ yControl.domain(y.domain());
// build the control x axis
control.append('g')
@@ -651,6 +630,53 @@
return d.label;
});
+ // --------------------
+ // aggregate statistics
+ // --------------------
+
+ var updateAggregateStatistics = function () {
+ // locate the instances that have data points within the current brush
+ var withinBrush = $.map(statusData, function (d) {
+ var xDomain = x.domain();
+ var yDomain = y.domain();
+
+ // copy to avoid modifying the original
+ var copy = $.extend({}, d);
+
+ // update the copy to only include values within the brush
+ return $.extend(copy, {
+ values: $.grep(d.values, function (s) {
+ return s.timestamp.getTime() >= xDomain[0].getTime() && s.timestamp.getTime() <= xDomain[1].getTime() && s.value >= yDomain[0] && s.value <= yDomain[1];
+ })
+ });
+ });
+
+ // consider visible nodes with data in the brush
+ var nodes = $.grep(withinBrush, function (d) {
+ return d.id !== config.nifiInstanceId && d.visible && d.values.length > 0;
+ });
+
+ var nodeMinValue = nodes.length === 0 ? 'NA' : formatters[selectedDescriptor.formatter](getMinValue(nodes));
+ var nodeMeanValue = nodes.length === 0 ? 'NA' : formatters[selectedDescriptor.formatter](getMeanValue(nodes));
+ var nodeMaxValue = nodes.length === 0 ? 'NA' : formatters[selectedDescriptor.formatter](getMaxValue(nodes));
+
+ // update the currently displayed min/max/mean
+ $('#node-aggregate-statistics').text(nodeMinValue + ' / ' + nodeMaxValue + ' / ' + nodeMeanValue);
+
+ // only consider the cluster with data in the brush
+ var cluster = $.grep(withinBrush, function (d) {
+ return d.id === config.nifiInstanceId && d.visible && d.values.length > 0;
+ });
+
+ // determine the cluster values
+ var clusterMinValue = cluster.length === 0 ? 'NA' : formatters[selectedDescriptor.formatter](getMinValue(cluster));
+ var clusterMeanValue = cluster.length === 0 ? 'NA' : formatters[selectedDescriptor.formatter](getMeanValue(cluster));
+ var clusterMaxValue = cluster.length === 0 ? 'NA' : formatters[selectedDescriptor.formatter](getMaxValue(cluster));
+
+ // update the cluster min/max/mean
+ $('#cluster-aggregate-statistics').text(clusterMinValue + ' / ' + clusterMaxValue + ' / ' + clusterMeanValue);
+ };
+
// -------------------
// configure the brush
// -------------------
@@ -679,7 +705,7 @@
return y(v.value);
})
.attr('r', function () {
- return brush.empty() ? 1.5 : 4;
+ return d3.brushSelection(brushNode.node()) === null ? 1.5 : 4;
});
// update the x axis
@@ -692,9 +718,11 @@
* or the control domain if there is no context window.
*/
var brushed = function () {
+ brushSelection = d3.brushSelection(brushNode.node());
+
// determine the new x and y domains
var xContextDomain, yContextDomain;
- if (brush.empty()) {
+ if (brushSelection === null) {
// get the all visible instances
var visibleInstances = $.grep(statusData, function (d) {
return d.visible;
@@ -718,16 +746,9 @@
];
}
xContextDomain = xControl.domain();
-
- // clear the current extent
- brushExtent = null;
} else {
- var extent = brush.extent();
- xContextDomain = [extent[0][0], extent[1][0]];
- yContextDomain = [extent[0][1], extent[1][1]];
-
- // hold onto the current brush
- brushExtent = extent;
+ xContextDomain = [brushSelection[0][0], brushSelection[1][0]].map(xControl.invert, xControl);
+ yContextDomain = [brushSelection[1][1], brushSelection[0][1]].map(yControl.invert, yControl);
}
// update the axes accordingly
@@ -738,90 +759,34 @@
};
// build the brush
- var brush = d3.svg.brush()
- .x(xControl)
- .y(yControl)
+ var brush = d3.brush()
+ .extent([[xControl.range()[0], yControl.range()[1]], [xControl.range()[1], yControl.range()[0]]])
.on('brush', brushed);
- // conditionally set the brush extent
- if (nfCommon.isDefinedAndNotNull(brushExtent)) {
- brush = brush.extent(brushExtent);
- }
-
// context area
- control.append('g')
+ var brushNode = control.append('g')
.attr('class', 'brush')
+ .on('click', brushed)
.call(brush);
+ // conditionally set the brush extent
+ if (nfCommon.isDefinedAndNotNull(brushSelection)) {
+ brush = brush.move(brushNode, brushSelection);
+ }
+
// add expansion to the extent
- control.select('rect.extent')
+ control.select('rect.selection')
.attr('style', 'pointer-events: all;')
.on('dblclick', function () {
- if (!brush.empty()) {
- // get the current extent to get the x range
- var extent = brush.extent();
-
+ if (brushSelection !== null) {
// get the y range (this value does not change from the original y domain)
- var yRange = yControl.domain();
+ var yRange = yControl.range();
// expand the extent vertically
- brush.extent([[extent[0][0], yRange[0]], [extent[1][0], yRange[1]]]);
-
- // update the brush control
- control.select('.brush').call(brush);
-
- // run the brush to update the axes of the main chart
- brushed();
+ brush.move(brushNode, [[brushSelection[0][0], yRange[1]], [brushSelection[1][0], yRange[0]]]);
}
});
- // --------------------
- // aggregate statistics
- // --------------------
-
- var updateAggregateStatistics = function () {
- // locate the instances that have data points within the current brush
- var withinBrush = $.map(statusData, function (d) {
- var xDomain = x.domain();
- var yDomain = y.domain();
-
- // copy to avoid modifying the original
- var copy = $.extend({}, d);
-
- // update the copy to only include values within the brush
- return $.extend(copy, {
- values: $.grep(d.values, function (s) {
- return s.timestamp.getTime() >= xDomain[0].getTime() && s.timestamp.getTime() <= xDomain[1].getTime() && s.value >= yDomain[0] && s.value <= yDomain[1];
- })
- });
- });
-
- // consider visible nodes with data in the brush
- var nodes = $.grep(withinBrush, function (d) {
- return d.id !== config.nifiInstanceId && d.visible && d.values.length > 0;
- });
-
- var nodeMinValue = nodes.length === 0 ? 'NA' : formatters[selectedDescriptor.formatter](getMinValue(nodes));
- var nodeMeanValue = nodes.length === 0 ? 'NA' : formatters[selectedDescriptor.formatter](getMeanValue(nodes));
- var nodeMaxValue = nodes.length === 0 ? 'NA' : formatters[selectedDescriptor.formatter](getMaxValue(nodes));
-
- // update the currently displayed min/max/mean
- $('#node-aggregate-statistics').text(nodeMinValue + ' / ' + nodeMaxValue + ' / ' + nodeMeanValue);
-
- // only consider the cluster with data in the brush
- var cluster = $.grep(withinBrush, function (d) {
- return d.id === config.nifiInstanceId && d.visible && d.values.length > 0;
- });
-
- // determine the cluster values
- var clusterMinValue = cluster.length === 0 ? 'NA' : formatters[selectedDescriptor.formatter](getMinValue(cluster));
- var clusterMeanValue = cluster.length === 0 ? 'NA' : formatters[selectedDescriptor.formatter](getMeanValue(cluster));
- var clusterMaxValue = cluster.length === 0 ? 'NA' : formatters[selectedDescriptor.formatter](getMaxValue(cluster));
-
- // update the cluster min/max/mean
- $('#cluster-aggregate-statistics').text(clusterMinValue + ' / ' + clusterMaxValue + ' / ' + clusterMeanValue);
- };
-
// ----------------
// build the legend
// ----------------
@@ -906,19 +871,13 @@
// handle resizing
// ---------------
- var maxWidth, maxHeight, minHeight, resizeExtent, dialog;
+ var maxWidth, maxHeight, minHeight, dialog;
chartContainer.append('').resizable({
minWidth: 425,
minHeight: 150,
handles: {
'se': '.ui-resizable-se'
},
- start: function (e, ui) {
- // record the current extent so it can be reset on stop
- if (!brush.empty()) {
- resizeExtent = brush.extent();
- }
- },
resize: function (e, ui) {
// -----------
// containment
@@ -1099,7 +1058,7 @@
$('#status-history-details').empty();
// clear the extent and selected descriptor
- brushExtent = null;
+ brushSelection = null;
descriptor = null;
instances = null;
},
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/provenance/nf-provenance-lineage.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/provenance/nf-provenance-lineage.js
index 6295c0b595f9..b67e474f470e 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/provenance/nf-provenance-lineage.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/provenance/nf-provenance-lineage.js
@@ -238,7 +238,7 @@
// push off processing a node until its deepest point
// by removing any descendants from the immediate nodes.
// in this case, a link is panning multiple levels
- descendantSet.forEach(function (d) {
+ descendantSet.each(function (d) {
immediateSet.remove(d);
});
@@ -478,7 +478,7 @@
var startNodes = d3.set(nodeLookup.keys());
// go through the nodes to reset their outgoing links
- nodeLookup.forEach(function (id, node) {
+ nodeLookup.each(function (node, id) {
node.outgoing = [];
node.incoming = [];
@@ -493,7 +493,7 @@
});
// go through the links in order to compute the new layout
- linkLookup.forEach(function (id, link) {
+ linkLookup.each(function (link, id) {
// updating the nodes connections
link.source.outgoing.push(link);
link.target.incoming.push(link);
@@ -535,11 +535,11 @@
});
// handle zoom behavior
- var lineageZoom = d3.behavior.zoom()
+ var lineageZoom = d3.zoom()
.scaleExtent([0.2, 8])
.on('zoom', function () {
d3.select('g.lineage').attr('transform', function () {
- return 'translate(' + d3.event.translate + ') scale(' + d3.event.scale + ')';
+ return 'translate(' + d3.event.transform.x + ', ' + d3.event.transform.y + ') scale(' + d3.event.transform.k + ')';
});
});
@@ -576,7 +576,7 @@
});
svg.append('rect')
- .attr({
+ .attrs({
'width': '100%',
'height': '100%',
'fill': '#f9fafb'
@@ -585,7 +585,7 @@
svg.append('defs').selectAll('marker')
.data(['FLOWFILE', 'FLOWFILE-SELECTED', 'EVENT', 'EVENT-SELECTED'])
.enter().append('marker')
- .attr({
+ .attrs({
'id': function (d) {
return d;
},
@@ -614,7 +614,7 @@
// group everything together
var lineageContainer = svg.append('g')
- .attr({
+ .attrs({
'transform': 'translate(0, 0) scale(1)',
'pointer-events': 'all',
'class': 'lineage'
@@ -638,8 +638,8 @@
});
// hide applicable nodes and lines
- linksToHide.transition().duration(400).style('opacity', 0);
nodesToHide.transition().delay(200).duration(400).style('opacity', 0);
+ linksToHide.transition().duration(400).style('opacity', 0);
} else {
// the slider is ascending
@@ -652,8 +652,8 @@
});
// show applicable nodes and lines
- nodesToShow.transition().duration(400).style('opacity', 1);
linksToShow.transition().delay(200).duration(400).style('opacity', 1);
+ nodesToShow.transition().duration(400).style('opacity', 1);
}
// update the event time
@@ -679,7 +679,7 @@
// node
flowfiles.append('circle')
- .attr({
+ .attrs({
'r': 16,
'fill': '#fff',
'stroke': '#000',
@@ -704,13 +704,13 @@
});
var icon = flowfiles.append('g')
- .attr({
+ .attrs({
'class': 'flowfile-icon',
'transform': function (d) {
return 'translate(-9,-9)';
}
}).append('text')
- .attr({
+ .attrs({
'font-family': 'flowfont',
'font-size': '18px',
'fill': '#ad9897',
@@ -1021,7 +1021,7 @@
.classed('event', true)
// join node to its label
.append('rect')
- .attr({
+ .attrs({
'x': 0,
'y': -8,
'height': 16,
@@ -1037,7 +1037,7 @@
.classed('selected', function (d) {
return d.id === eventId;
})
- .attr({
+ .attrs({
'r': 8,
'fill': '#aabbc3',
'stroke': '#000',
@@ -1049,7 +1049,7 @@
events
.append('text')
- .attr({
+ .attrs({
'id': function (d) {
return 'event-text-' + d.id;
},
@@ -1083,7 +1083,7 @@
});
label.attr('transform', 'translate(10,-14)');
} else {
- label.text(d.eventType).attr({
+ label.text(d.eventType).attrs({
'x': 10,
'y': 4
});
@@ -1098,7 +1098,22 @@
return d.id;
});
- // add new nodes
+ // exit
+ nodes.exit()
+ .transition()
+ .delay(200)
+ .duration(400)
+ .attr('transform', function (d) {
+ if (d.incoming.length === 0) {
+ return 'translate(' + (width / 2) + ',50)';
+ } else {
+ return 'translate(' + d.incoming[0].source.x + ',' + d.incoming[0].source.y + ')';
+ }
+ })
+ .style('opacity', 0)
+ .remove();
+
+ // enter
var nodesEntered = nodes.enter()
.append('g')
.attr('id', function (d) {
@@ -1122,39 +1137,37 @@
return d.type === 'EVENT';
}).call(renderEvent, provenanceTableCtrl);
+ // merge
+ nodes = nodes.merge(nodesEntered);
+
// update the nodes
- nodes
- .transition()
+ nodes.transition()
.duration(400)
.attr('transform', function (d) {
return 'translate(' + d.x + ', ' + d.y + ')';
})
.style('opacity', 1);
- // remove old nodes
- nodes.exit()
+ // update the link data
+ links = links.data(linkLookup.values(), function (d) {
+ return d.id;
+ });
+
+ // exit
+ links.exit()
+ .attr('marker-end', '')
.transition()
- .delay(200)
.duration(400)
- .attr('transform', function (d) {
- if (d.incoming.length === 0) {
- return 'translate(' + (width / 2) + ',50)';
- } else {
- return 'translate(' + d.incoming[0].source.x + ',' + d.incoming[0].source.y + ')';
- }
+ .attr('d', function (d) {
+ return 'M' + d.source.x + ',' + d.source.y + 'L' + d.source.x + ',' + d.source.y;
})
.style('opacity', 0)
.remove();
- // update the link data
- links = links.data(linkLookup.values(), function (d) {
- return d.id;
- });
-
// add new links
- links.enter()
+ var linksEntered = links.enter()
.insert('path', '.node')
- .attr({
+ .attrs({
'class': 'link',
'stroke-width': 1.5,
'stroke': '#000',
@@ -1165,13 +1178,15 @@
})
.style('opacity', 0);
+ // merge
+ links = links.merge(linksEntered)
+ .attr('marker-end', '');
+
// update the links
- links
- .attr('marker-end', '')
- .transition()
+ links.transition()
.delay(200)
.duration(400)
- .attr({
+ .attrs({
'marker-end': function (d) {
return 'url(#' + d.target.type + ')';
},
@@ -1180,17 +1195,6 @@
}
})
.style('opacity', 1);
-
- // remove old links
- links.exit()
- .attr('marker-end', '')
- .transition()
- .duration(400)
- .attr('d', function (d) {
- return 'M' + d.source.x + ',' + d.source.y + 'L' + d.source.x + ',' + d.source.y;
- })
- .style('opacity', 0)
- .remove();
};
// show the lineage pane and hide the event search results
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/provenance/nf-provenance-table.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/provenance/nf-provenance-table.js
index 5a426e5a55f2..9094795f91ce 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/provenance/nf-provenance-table.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/provenance/nf-provenance-table.js
@@ -69,7 +69,7 @@
provenance: '../nifi-api/provenance',
provenanceEvents: '../nifi-api/provenance-events/',
clusterSearch: '../nifi-api/flow/cluster/search-results',
- d3Script: 'js/d3/d3.min.js',
+ d3Script: 'js/d3/build/d3.min.js',
lineageScript: 'js/nf/provenance/nf-provenance-lineage.js',
uiExtensionToken: '../nifi-api/access/ui-extension-token',
downloadToken: '../nifi-api/access/download-token'