mirror of https://github.com/apache/nifi.git
NIFI-618:
- Adding a context menu item that allows users to move components out of a process group.
This commit is contained in:
parent
3295f7f193
commit
f72fdcdb15
|
@ -1685,7 +1685,11 @@ public final class StandardProcessGroup implements ProcessGroup {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isRootGroup() && (!snippet.getInputPorts().isEmpty() || !snippet.getOutputPorts().isEmpty())) {
|
if (isRootGroup() && (!snippet.getInputPorts().isEmpty() || !snippet.getOutputPorts().isEmpty())) {
|
||||||
throw new IllegalStateException("Cannot move Ports from the Root Group to a Non-Root Group");
|
throw new IllegalStateException("Cannot move Ports out of the root group");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (destination.isRootGroup() && (!snippet.getInputPorts().isEmpty() || !snippet.getOutputPorts().isEmpty())) {
|
||||||
|
throw new IllegalStateException("Cannot move Ports into the root group");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (final String id : replaceNullWithEmptySet(snippet.getInputPorts())) {
|
for (final String id : replaceNullWithEmptySet(snippet.getInputPorts())) {
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 215 B |
|
@ -914,6 +914,21 @@ nf.Actions = (function () {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Moves the currently selected component into the current parent group.
|
||||||
|
*/
|
||||||
|
moveIntoParent: function () {
|
||||||
|
var selection = nf.CanvasUtils.getSelection();
|
||||||
|
|
||||||
|
// ensure that components have been specified
|
||||||
|
if (selection.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// move the current selection into the parent group
|
||||||
|
nf.CanvasUtils.moveComponentsToParent(selection);
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new template based off the currently selected components. If no components
|
* Creates a new template based off the currently selected components. If no components
|
||||||
* are selected, a template of the entire canvas is made.
|
* are selected, a template of the entire canvas is made.
|
||||||
|
|
|
@ -51,6 +51,58 @@ nf.CanvasUtils = (function () {
|
||||||
return mid;
|
return mid;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var moveComponents = function (components, groupId) {
|
||||||
|
return $.Deferred(function (deferred) {
|
||||||
|
// ensure the current selection is eligible for move into the specified group
|
||||||
|
nf.CanvasUtils.eligibleForMove(components, groupId).done(function () {
|
||||||
|
// create a snippet for the specified components and link to the data flow
|
||||||
|
var snippetDetails = nf.Snippet.marshal(components, true);
|
||||||
|
nf.Snippet.create(snippetDetails).done(function (response) {
|
||||||
|
var snippet = response.snippet;
|
||||||
|
|
||||||
|
// move the snippet into the target
|
||||||
|
nf.Snippet.move(snippet.id, groupId).done(function () {
|
||||||
|
var componentMap = d3.map();
|
||||||
|
|
||||||
|
// add the id to the type's array
|
||||||
|
var addComponent = function (type, id) {
|
||||||
|
if (!componentMap.has(type)) {
|
||||||
|
componentMap.set(type, []);
|
||||||
|
}
|
||||||
|
componentMap.get(type).push(id);
|
||||||
|
};
|
||||||
|
|
||||||
|
// go through each component being removed
|
||||||
|
components.each(function (d) {
|
||||||
|
addComponent(d.type, d.component.id);
|
||||||
|
});
|
||||||
|
|
||||||
|
// refresh all component types as necessary (handle components that have been removed)
|
||||||
|
componentMap.forEach(function (type, ids) {
|
||||||
|
nf[type].remove(ids);
|
||||||
|
});
|
||||||
|
|
||||||
|
// refresh the birdseye
|
||||||
|
nf.Birdseye.refresh();
|
||||||
|
deferred.resolve();
|
||||||
|
}).fail(nf.Common.handleAjaxError).fail(function () {
|
||||||
|
deferred.reject();
|
||||||
|
}).always(function () {
|
||||||
|
// unable to acutally move the components so attempt to
|
||||||
|
// unlink and remove just the snippet
|
||||||
|
nf.Snippet.unlink(snippet.id).done(function () {
|
||||||
|
nf.Snippet.remove(snippet.id);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}).fail(nf.Common.handleAjaxError).fail(function () {
|
||||||
|
deferred.reject();
|
||||||
|
});
|
||||||
|
}).fail(function () {
|
||||||
|
deferred.reject();
|
||||||
|
});
|
||||||
|
}).promise();
|
||||||
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
config: {
|
config: {
|
||||||
systemTooltipConfig: {
|
systemTooltipConfig: {
|
||||||
|
@ -1025,6 +1077,22 @@ nf.CanvasUtils = (function () {
|
||||||
return origin;
|
return origin;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Moves the specified components into the current parent group.
|
||||||
|
*
|
||||||
|
* @param {selection} components
|
||||||
|
*/
|
||||||
|
moveComponentsToParent: function (components) {
|
||||||
|
var groupId = nf.Canvas.getParentGroupId();
|
||||||
|
|
||||||
|
// if the group id is null, we're already in the top most group
|
||||||
|
if (groupId === null) {
|
||||||
|
nf.Dialog.showOkDialog('Components are already in the topmost group.');
|
||||||
|
} else {
|
||||||
|
moveComponents(components, groupId);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Moves the specified components into the specified group.
|
* Moves the specified components into the specified group.
|
||||||
*
|
*
|
||||||
|
@ -1034,45 +1102,10 @@ nf.CanvasUtils = (function () {
|
||||||
moveComponents: function (components, group) {
|
moveComponents: function (components, group) {
|
||||||
var groupData = group.datum();
|
var groupData = group.datum();
|
||||||
|
|
||||||
// ensure the current selection is eligible for move into the specified group
|
// move the components into the destination and...
|
||||||
nf.CanvasUtils.eligibleForMove(components, group).done(function () {
|
moveComponents(components, groupData.component.id).done(function () {
|
||||||
// create a snippet for the specified components and link to the data flow
|
|
||||||
var snippetDetails = nf.Snippet.marshal(components, true);
|
|
||||||
nf.Snippet.create(snippetDetails).done(function (response) {
|
|
||||||
var snippet = response.snippet;
|
|
||||||
|
|
||||||
// move the snippet into the target
|
|
||||||
nf.Snippet.move(snippet.id, groupData.component.id).done(function () {
|
|
||||||
var componentMap = d3.map();
|
|
||||||
|
|
||||||
// add the id to the type's array
|
|
||||||
var addComponent = function (type, id) {
|
|
||||||
if (!componentMap.has(type)) {
|
|
||||||
componentMap.set(type, []);
|
|
||||||
}
|
|
||||||
componentMap.get(type).push(id);
|
|
||||||
};
|
|
||||||
|
|
||||||
// go through each component being removed
|
|
||||||
components.each(function (d) {
|
|
||||||
addComponent(d.type, d.component.id);
|
|
||||||
});
|
|
||||||
|
|
||||||
// refresh all component types as necessary (handle components that have been removed)
|
|
||||||
componentMap.forEach(function (type, ids) {
|
|
||||||
nf[type].remove(ids);
|
|
||||||
});
|
|
||||||
|
|
||||||
// reload the target group
|
// reload the target group
|
||||||
nf.ProcessGroup.reload(groupData.component);
|
nf.ProcessGroup.reload(groupData.component);
|
||||||
}).fail(nf.Common.handleAjaxError).always(function () {
|
|
||||||
// unable to acutally move the components so attempt to
|
|
||||||
// unlink and remove just the snippet
|
|
||||||
nf.Snippet.unlink(snippet.id).done(function () {
|
|
||||||
nf.Snippet.remove(snippet.id);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}).fail(nf.Common.handleAjaxError);
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -1161,15 +1194,15 @@ nf.CanvasUtils = (function () {
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ensures components are eligible to be moved. The new target can be optionally specified.
|
* Ensures components are eligible to be moved. The new group can be optionally specified.
|
||||||
*
|
*
|
||||||
* 1) Ensuring that the input and output ports are not connected outside of this group
|
* 1) Ensuring that the input and output ports are not connected outside of this group
|
||||||
* 2) If the target is specified; ensuring there are no port name conflicts in the target group
|
* 2) If the target is specified; ensuring there are no port name conflicts in the target group
|
||||||
*
|
*
|
||||||
* @argument {selection} selection The selection being moved
|
* @argument {selection} selection The selection being moved
|
||||||
* @argument {selection} group The selection containing the new group
|
* @argument {string} groupId The id of the new group
|
||||||
*/
|
*/
|
||||||
eligibleForMove: function (selection, group) {
|
eligibleForMove: function (selection, groupId) {
|
||||||
var inputPorts = [];
|
var inputPorts = [];
|
||||||
var outputPorts = [];
|
var outputPorts = [];
|
||||||
|
|
||||||
|
@ -1191,7 +1224,7 @@ nf.CanvasUtils = (function () {
|
||||||
// ports in the root group cannot be moved
|
// ports in the root group cannot be moved
|
||||||
if (nf.Canvas.getParentGroupId() === null) {
|
if (nf.Canvas.getParentGroupId() === null) {
|
||||||
nf.Dialog.showOkDialog({
|
nf.Dialog.showOkDialog({
|
||||||
dialogContent: 'Ports in the root group cannot be moved into another group.',
|
dialogContent: 'Cannot move Ports out of the root group',
|
||||||
overlayBackground: false
|
overlayBackground: false
|
||||||
});
|
});
|
||||||
portConnectionDeferred.reject();
|
portConnectionDeferred.reject();
|
||||||
|
@ -1245,12 +1278,11 @@ nf.CanvasUtils = (function () {
|
||||||
// create a deferred for checking port names in the target
|
// create a deferred for checking port names in the target
|
||||||
var portNameCheck = function () {
|
var portNameCheck = function () {
|
||||||
return $.Deferred(function (portNameDeferred) {
|
return $.Deferred(function (portNameDeferred) {
|
||||||
var groupData = group.datum();
|
|
||||||
|
|
||||||
// add the get request
|
// add the get request
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: 'GET',
|
type: 'GET',
|
||||||
url: config.urls.controller + '/process-groups/' + encodeURIComponent(groupData.component.id),
|
url: config.urls.controller + '/process-groups/' + encodeURIComponent(groupId),
|
||||||
data: {
|
data: {
|
||||||
verbose: true
|
verbose: true
|
||||||
},
|
},
|
||||||
|
@ -1294,7 +1326,7 @@ nf.CanvasUtils = (function () {
|
||||||
|
|
||||||
// execute the checks in order
|
// execute the checks in order
|
||||||
portConnectionCheck().done(function () {
|
portConnectionCheck().done(function () {
|
||||||
if (nf.Common.isDefinedAndNotNull(group)) {
|
if (nf.Common.isDefinedAndNotNull(groupId)) {
|
||||||
$.when(portNameCheck()).done(function () {
|
$.when(portNameCheck()).done(function () {
|
||||||
deferred.resolve();
|
deferred.resolve();
|
||||||
}).fail(function () {
|
}).fail(function () {
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* global nf */
|
/* global nf, d3 */
|
||||||
|
|
||||||
nf.ContextMenu = (function () {
|
nf.ContextMenu = (function () {
|
||||||
|
|
||||||
|
@ -277,6 +277,15 @@ nf.ContextMenu = (function () {
|
||||||
return nf.Common.isDFM() && nf.CanvasUtils.canAllStopTransmitting(selection);
|
return nf.Common.isDFM() && nf.CanvasUtils.canAllStopTransmitting(selection);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if the components in the specified selection can be moved into a parent group.
|
||||||
|
*
|
||||||
|
* @param {type} selection
|
||||||
|
*/
|
||||||
|
var canMoveToParent = function (selection) {
|
||||||
|
return !selection.empty() && nf.CanvasUtils.isDisconnected(selection) && nf.Canvas.getParentGroupId() !== null;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a menu item to the context menu.
|
* Adds a menu item to the context menu.
|
||||||
*
|
*
|
||||||
|
@ -363,6 +372,7 @@ nf.ContextMenu = (function () {
|
||||||
{condition: isNotConnection, menuItem: {img: 'images/iconCenterView.png', text: 'Center in view', action: 'center'}},
|
{condition: isNotConnection, menuItem: {img: 'images/iconCenterView.png', text: 'Center in view', action: 'center'}},
|
||||||
{condition: isCopyable, menuItem: {img: 'images/iconCopy.png', text: 'Copy', action: 'copy'}},
|
{condition: isCopyable, menuItem: {img: 'images/iconCopy.png', text: 'Copy', action: 'copy'}},
|
||||||
{condition: isPastable, menuItem: {img: 'images/iconPaste.png', text: 'Paste', action: 'paste'}},
|
{condition: isPastable, menuItem: {img: 'images/iconPaste.png', text: 'Paste', action: 'paste'}},
|
||||||
|
{condition: canMoveToParent, menuItem: {img: 'images/iconMoveToParent.png', text: 'Move to parent group', action: 'moveIntoParent'}},
|
||||||
{condition: isDeletable, menuItem: {img: 'images/iconDelete.png', text: 'Delete', action: 'delete'}}
|
{condition: isDeletable, menuItem: {img: 'images/iconDelete.png', text: 'Delete', action: 'delete'}}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue