mirror of https://github.com/apache/nifi.git
NIFI-3575:
- Verify that when moving a snippet, we do not attempt to move a process group into itself. - Update the UI to ensure a subsequent move event cannot be triggered while a previous move event is still in progress. This closes #1582. Signed-off-by: Andy LoPresto <alopresto@apache.org>
This commit is contained in:
parent
18f05856ff
commit
977aa6919c
|
@ -2107,6 +2107,7 @@ public final class StandardProcessGroup implements ProcessGroup {
|
|||
writeLock.lock();
|
||||
try {
|
||||
verifyContents(snippet);
|
||||
verifyDestinationNotInSnippet(snippet, destination);
|
||||
|
||||
if (!isDisconnected(snippet)) {
|
||||
throw new IllegalStateException("One or more components within the snippet is connected to a component outside of the snippet. Only a disconnected snippet may be moved.");
|
||||
|
@ -2260,6 +2261,23 @@ public final class StandardProcessGroup implements ProcessGroup {
|
|||
verifyAllKeysExist(snippet.getConnections().keySet(), connections, "Connection");
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that a move request cannot attempt to move a process group into itself.
|
||||
*
|
||||
* @param snippet the snippet
|
||||
* @param destination the destination
|
||||
* @throws IllegalStateException if the snippet contains an ID that is equal to the identifier of the destination
|
||||
*/
|
||||
private void verifyDestinationNotInSnippet(final Snippet snippet, final ProcessGroup destination) throws IllegalStateException {
|
||||
if (snippet.getProcessGroups() != null && destination != null) {
|
||||
snippet.getProcessGroups().forEach((processGroupId, revision) -> {
|
||||
if (processGroupId.equals(destination.getIdentifier())) {
|
||||
throw new IllegalStateException("Unable to move Process Group into itself.");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Verifies that all ID's specified by the given set exist as keys in the
|
||||
|
@ -2497,6 +2515,7 @@ public final class StandardProcessGroup implements ProcessGroup {
|
|||
}
|
||||
|
||||
verifyContents(snippet);
|
||||
verifyDestinationNotInSnippet(snippet, newProcessGroup);
|
||||
|
||||
if (!isDisconnected(snippet)) {
|
||||
throw new IllegalStateException("One or more components within the snippet is connected to a component outside of the snippet. Only a disconnected snippet may be moved.");
|
||||
|
|
|
@ -941,8 +941,10 @@
|
|||
nfNgBridge.digest();
|
||||
}).fail(nfErrorHandler.handleAjaxError);
|
||||
} else {
|
||||
var parentGroupId = nfCanvasUtils.getGroupId();
|
||||
|
||||
// create a snippet for the specified component and link to the data flow
|
||||
var snippet = nfSnippet.marshal(selection);
|
||||
var snippet = nfSnippet.marshal(selection, parentGroupId);
|
||||
nfSnippet.create(snippet).done(function (response) {
|
||||
// remove the snippet, effectively removing the components
|
||||
nfSnippet.remove(response.snippet.id).done(function () {
|
||||
|
@ -1502,7 +1504,8 @@
|
|||
var templateDescription = $('#new-template-description').val();
|
||||
|
||||
// create a snippet
|
||||
var snippet = nfSnippet.marshal(selection);
|
||||
var parentGroupId = nfCanvasUtils.getGroupId();
|
||||
var snippet = nfSnippet.marshal(selection, parentGroupId);
|
||||
|
||||
// create the snippet
|
||||
nfSnippet.create(snippet).done(function (response) {
|
||||
|
@ -1569,8 +1572,9 @@
|
|||
var origin = nfCanvasUtils.getOrigin(selection);
|
||||
|
||||
// copy the snippet details
|
||||
var parentGroupId = nfCanvasUtils.getGroupId();
|
||||
nfClipboard.copy({
|
||||
snippet: nfSnippet.marshal(selection),
|
||||
snippet: nfSnippet.marshal(selection, parentGroupId),
|
||||
origin: origin
|
||||
});
|
||||
},
|
||||
|
@ -1608,6 +1612,8 @@
|
|||
deferred.reject(xhr.responseText);
|
||||
};
|
||||
|
||||
var destinationProcessGroupId = nfCanvasUtils.getGroupId();
|
||||
|
||||
// create a snippet from the details
|
||||
nfSnippet.create(data['snippet']).done(function (createResponse) {
|
||||
// determine the origin of the bounding box of the copy
|
||||
|
@ -1622,7 +1628,7 @@
|
|||
}
|
||||
|
||||
// copy the snippet to the new location
|
||||
nfSnippet.copy(createResponse.snippet.id, origin).done(function (copyResponse) {
|
||||
nfSnippet.copy(createResponse.snippet.id, origin, destinationProcessGroupId).done(function (copyResponse) {
|
||||
var snippetFlow = copyResponse.flow;
|
||||
|
||||
// update the graph accordingly
|
||||
|
|
|
@ -21,17 +21,19 @@
|
|||
define(['d3',
|
||||
'jquery',
|
||||
'nf.Common',
|
||||
'nf.ErrorHandler',
|
||||
'nf.Dialog',
|
||||
'nf.Clipboard',
|
||||
'nf.Storage'],
|
||||
function (d3, $, nfCommon, nfDialog, nfClipboard, nfStorage) {
|
||||
return (nf.CanvasUtils = factory(d3, $, nfCommon, nfDialog, nfClipboard, nfStorage));
|
||||
function (d3, $, nfCommon, nfErrorHandler, nfDialog, nfClipboard, nfStorage) {
|
||||
return (nf.CanvasUtils = factory(d3, $, nfCommon, nfErrorHandler, nfDialog, nfClipboard, nfStorage));
|
||||
});
|
||||
} else if (typeof exports === 'object' && typeof module === 'object') {
|
||||
module.exports = (nf.CanvasUtils = factory(
|
||||
require('d3'),
|
||||
require('jquery'),
|
||||
require('nf.Common'),
|
||||
require('nf.ErrorHandler'),
|
||||
require('nf.Dialog'),
|
||||
require('nf.Clipboard'),
|
||||
require('nf.Storage')));
|
||||
|
@ -40,11 +42,12 @@
|
|||
root.d3,
|
||||
root.$,
|
||||
root.nf.Common,
|
||||
root.nf.ErrorHandler,
|
||||
root.nf.Dialog,
|
||||
root.nf.Clipboard,
|
||||
root.nf.Storage);
|
||||
}
|
||||
}(this, function (d3, $, nfCommon, nfDialog, nfClipboard, nfStorage) {
|
||||
}(this, function (d3, $, nfCommon, nfErrorHandler, nfDialog, nfClipboard, nfStorage) {
|
||||
'use strict';
|
||||
|
||||
var nfCanvas;
|
||||
|
@ -87,8 +90,10 @@
|
|||
|
||||
var moveComponents = function (components, groupId) {
|
||||
return $.Deferred(function (deferred) {
|
||||
var parentGroupId = nfCanvasUtils.getGroupId();
|
||||
|
||||
// create a snippet for the specified components
|
||||
var snippet = nfSnippet.marshal(components);
|
||||
var snippet = nfSnippet.marshal(components, parentGroupId);
|
||||
nfSnippet.create(snippet).done(function (response) {
|
||||
// move the snippet into the target
|
||||
nfSnippet.move(response.snippet.id, groupId).done(function () {
|
||||
|
@ -116,10 +121,10 @@
|
|||
nfBirdseye.refresh();
|
||||
|
||||
deferred.resolve();
|
||||
}).fail(nfCommon.handleAjaxError).fail(function () {
|
||||
}).fail(nfErrorHandler.handleAjaxError).fail(function () {
|
||||
deferred.reject();
|
||||
});
|
||||
}).fail(nfCommon.handleAjaxError).fail(function () {
|
||||
}).fail(nfErrorHandler.handleAjaxError).fail(function () {
|
||||
deferred.reject();
|
||||
});
|
||||
}).promise();
|
||||
|
|
|
@ -121,10 +121,12 @@
|
|||
|
||||
/**
|
||||
* Updates the parent group of all selected components.
|
||||
*
|
||||
* @param {selection} the destination group
|
||||
*/
|
||||
var updateComponentsGroup = function () {
|
||||
var selection = d3.selectAll('g.component.selected, g.connection.selected');
|
||||
var group = d3.select('g.drop');
|
||||
var updateComponentsGroup = function (group) {
|
||||
// get the selection and deselect the components being moved
|
||||
var selection = d3.selectAll('g.component.selected, g.connection.selected').classed('selected', false);
|
||||
|
||||
if (nfCanvasUtils.canModify(selection) === false) {
|
||||
nfDialog.showOkDialog({
|
||||
|
@ -230,11 +232,15 @@
|
|||
return;
|
||||
}
|
||||
|
||||
// get the destination group if applicable... remove the drop flag if necessary to prevent
|
||||
// subsequent drop events from triggering prior to this move's completion
|
||||
var group = d3.select('g.drop').classed('drop', false);
|
||||
|
||||
// either move or update the selections group as appropriate
|
||||
if (d3.select('g.drop').empty()) {
|
||||
if (group.empty()) {
|
||||
updateComponentsPosition(dragSelection);
|
||||
} else {
|
||||
updateComponentsGroup();
|
||||
updateComponentsGroup(group);
|
||||
}
|
||||
|
||||
// remove the drag selection
|
||||
|
|
|
@ -54,10 +54,11 @@
|
|||
* Marshals snippet from the specified selection.
|
||||
*
|
||||
* @argument {selection} selection The selection to marshal
|
||||
* @argument {string} parentGroupId The parent group id
|
||||
*/
|
||||
marshal: function (selection) {
|
||||
marshal: function (selection, parentGroupId) {
|
||||
var snippet = {
|
||||
parentGroupId: nfCanvasUtils.getGroupId(),
|
||||
parentGroupId: parentGroupId,
|
||||
processors: {},
|
||||
funnels: {},
|
||||
inputPorts: {},
|
||||
|
@ -118,8 +119,9 @@
|
|||
*
|
||||
* @argument {string} snippetId The snippet id
|
||||
* @argument {object} origin The origin
|
||||
* @argument {string} destinationGroupId The destination group id
|
||||
*/
|
||||
copy: function (snippetId, origin) {
|
||||
copy: function (snippetId, origin, destinationGroupId) {
|
||||
var copySnippetRequestEntity = {
|
||||
'snippetId': snippetId,
|
||||
'originX': origin.x,
|
||||
|
@ -128,7 +130,7 @@
|
|||
|
||||
return $.ajax({
|
||||
type: 'POST',
|
||||
url: config.urls.processGroups + '/' + encodeURIComponent(nfCanvasUtils.getGroupId()) + '/snippet-instance',
|
||||
url: config.urls.processGroups + '/' + encodeURIComponent(destinationGroupId) + '/snippet-instance',
|
||||
data: JSON.stringify(copySnippetRequestEntity),
|
||||
dataType: 'json',
|
||||
contentType: 'application/json'
|
||||
|
|
Loading…
Reference in New Issue