diff --git a/nifi-assembly/LICENSE b/nifi-assembly/LICENSE
index a6f1a03409..edfd806a5d 100644
--- a/nifi-assembly/LICENSE
+++ b/nifi-assembly/LICENSE
@@ -445,6 +445,29 @@ For details see http://qtip2.com
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
+This product bundles 'url-search-params' which is available under an MIT style license.
+For details see https://github.com/WebReflection/url-search-params
+
+ Copyright (C) 2015 by WebReflection
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+
This product bundles 'jQuery MiniColors' which is available under the MIT License.
For details see http://www.abeautifulsite.net/
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 f4b4b09972..175ec8f0dc 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
@@ -474,6 +474,29 @@ For details see http://qtip2.com
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
+This product bundles 'url-search-params' which is available under an MIT style license.
+For details see https://github.com/WebReflection/url-search-params
+
+ Copyright (C) 2015 by WebReflection
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+
This product bundles 'jQuery MiniColors' which is available under the MIT License.
For details see http://www.abeautifulsite.net/
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 9108fe7577..08c0d46bd5 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
@@ -226,6 +226,10 @@
Unable to select component(s).
')); + + nfDialog.showOkDialog({ + headerText: 'Error', + dialogContent: dialogContent + }); + } + + nfActions.show(components); + }); + + return refreshGraph; + } + }, + + MAX_URL_LENGTH: 2000, // the maximum (suggested) safe string length of a URL supported by all browsers and application servers + + /** + * Set the parameters of the URL. + * + * @param groupId The process group id. + * @param selections The component ids. + */ + setURLParameters: function (groupId, selections) { + // Feature detection and browser support for URLSearchParams + if ('URLSearchParams' in window) { + if (!nfCommon.isDefinedAndNotNull(groupId)) { + groupId = nfCanvasUtils.getGroupId(); + } + + if (!nfCommon.isDefinedAndNotNull(selections)) { + selections = nfCanvasUtils.getSelection(); + } + + var selectedComponentIds = []; + selections.each(function (selection) { + selectedComponentIds.push(selection.id); + }); + + // get all URL parameters + var params = new URL(window.location).searchParams; + params.set('processGroupId', groupId); + params.set('componentIds', selectedComponentIds.sort()); + + // create object whose keys are the parameter name and the values are the parameter values + var paramsObject = {}; + params.forEach(function (v, k) { + paramsObject[k] = v; + }); + + var url = new URL(window.location); + var newUrl = url.origin + url.pathname; + + if (nfCommon.isDefinedAndNotNull(nfCanvasUtils.getParentGroupId()) || selectedComponentIds.length > 0) { + if (!nfCommon.isDefinedAndNotNull(nfCanvasUtils.getParentGroupId())) { + // we are in the root group so set processGroupId param value to 'root' alias + paramsObject['processGroupId'] = 'root'; + } + + if ((url.origin + url.pathname + '?' + $.param(paramsObject)).length <= nfCanvasUtils.MAX_URL_LENGTH) { + newUrl = url.origin + url.pathname + '?' + $.param(paramsObject); + } else if (nfCommon.isDefinedAndNotNull(nfCanvasUtils.getParentGroupId())) { + // silently remove all component ids + paramsObject['componentIds'] = ''; + newUrl = url.origin + url.pathname + '?' + $.param(paramsObject); + } + } + + window.history.replaceState({'previous_url': url.href}, window.document.title, newUrl); + } + }, + /** * Gets the currently selected components and connections. * 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 74b43d8607..051f397fcb 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 @@ -284,6 +284,9 @@ // since the context menu event propagated back to the canvas, clear the selection nfCanvasUtils.getSelection().classed('selected', false); + // update URL deep linking params + nfCanvasUtils.setURLParameters(); + // show the context menu on the canvas nfContextMenu.show(); @@ -553,9 +556,15 @@ // remove the selection box selectionBox.remove(); + + // update URL deep linking params + nfCanvasUtils.setURLParameters(); } else 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 @@ -697,6 +706,10 @@ } else if (evt.keyCode === 65) { // ctrl-a nfActions.selectAll(); + + // update URL deep linking params + nfCanvasUtils.setURLParameters(); + nfNgBridge.digest(); // only want to prevent default if the action was performed, otherwise default select all would be overridden 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 14f6880780..6b0e5a9541 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 @@ -310,6 +310,9 @@ .on('mousedown.selection', function () { // select the connection when clicking the selectable path nfSelectable.select(d3.select(this.parentNode)); + + // update URL deep linking params + nfCanvasUtils.setURLParameters(); }) .call(nfContextMenu.activate); }; @@ -630,6 +633,9 @@ .on('mousedown.selection', function () { // select the connection when clicking the label nfSelectable.select(d3.select(this.parentNode)); + + // update URL deep linking params + nfCanvasUtils.setURLParameters(); }) .call(nfContextMenu.activate); @@ -660,6 +666,9 @@ .on('mousedown.selection', function () { // select the connection when clicking the label nfSelectable.select(d3.select(this.parentNode)); + + // update URL deep linking params + nfCanvasUtils.setURLParameters(); }) .call(nfContextMenu.activate); @@ -740,6 +749,9 @@ .on('mousedown.selection', function () { // select the connection when clicking the label nfSelectable.select(d3.select(this.parentNode)); + + // update URL deep linking params + nfCanvasUtils.setURLParameters(); }) .call(nfContextMenu.activate); @@ -777,6 +789,9 @@ .on('mousedown.selection', function () { // select the connection when clicking the label nfSelectable.select(d3.select(this.parentNode)); + + // update URL deep linking params + nfCanvasUtils.setURLParameters(); }) .call(nfContextMenu.activate); 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 394bf42a2c..9cc4345b40 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 @@ -206,8 +206,8 @@ nfProcessor.init(nfConnectable, nfDraggable, nfSelectable, nfContextMenu); nfConnection.init(nfSelectable, nfContextMenu, nfConnectionConfiguration); - // load the graph - return nfProcessGroup.enterGroup(nfCanvasUtils.getGroupId()); + // display the deep link + return nfCanvasUtils.showDeepLink(true); }, /** @@ -389,6 +389,9 @@ updateVisibility: function () { updateComponentVisibility(); nfGraph.pan(); + + // update URL deep linking params + nfCanvasUtils.setURLParameters(); }, /** 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 bec3d6c360..c142b75c34 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 @@ -1279,6 +1279,10 @@ transition: true }); } + + // update URL deep linking params + nfCanvasUtils.setURLParameters(groupId, d3.select()); + }).fail(function () { nfDialog.showOkDialog({ headerText: 'Process Group', diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-selectable.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-selectable.js index c8b51792b3..c24457d110 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-selectable.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-selectable.js @@ -21,21 +21,24 @@ if (typeof define === 'function' && define.amd) { define(['d3', 'nf.ng.Bridge', - 'nf.ContextMenu'], - function (d3, nfNgBridge, nfContextMenu) { - return (nf.Selectable = factory(d3, nfNgBridge, nfContextMenu)); + 'nf.ContextMenu', + 'nf.CanvasUtils'], + function (d3, nfNgBridge, nfContextMenu, nfCanvasUtils) { + return (nf.Selectable = factory(d3, nfNgBridge, nfContextMenu, nfCanvasUtils)); }); } else if (typeof exports === 'object' && typeof module === 'object') { module.exports = (nf.Selectable = factory(require('d3'), require('nf.ng.Bridge'), - require('nf.ContextMenu'))); + require('nf.ContextMenu'), + require('nf.CanvasUtils'))); } else { nf.Selectable = factory(root.d3, root.nf.ng.Bridge, - root.nf.ContextMenu); + root.nf.ContextMenu, + root.nf.CanvasUtils); } -}(this, function (d3, nfNgBridge, nfContextMenu) { +}(this, function (d3, nfNgBridge, nfContextMenu, nfCanvasUtils) { 'use strict'; var nfSelectable = { @@ -77,6 +80,9 @@ components.on('mousedown.selection', function () { // get the clicked component to update selection nfSelectable.select(d3.select(this)); + + // update URL deep linking params + nfCanvasUtils.setURLParameters(); }); } }; diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-dialog.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-dialog.js index fff81b4c77..01a5411845 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-dialog.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-dialog.js @@ -70,7 +70,7 @@ // regardless of whether the dialog is already visible, the new content will be appended var content = $('').append(options.dialogContent); - $('#nf-ok-dialog-content').append(content); + $('#nf-ok-dialog-content').append(content).append(''); // update the button model $('#nf-ok-dialog').modal('setButtonModel', [{