diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/DropRequestDTO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/DropRequestDTO.java
index f0224693d6..93dc7dd7d4 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/DropRequestDTO.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/DropRequestDTO.java
@@ -38,11 +38,14 @@ public class DropRequestDTO {
private Boolean finished;
private Integer currentCount;
- private String currentSize;
+ private Long currentSize;
+ private String current;
private Integer originalCount;
- private String originalSize;
+ private Long originalSize;
+ private String original;
private Integer droppedCount;
- private String droppedSize;
+ private Long droppedSize;
+ private String dropped;
private String state;
@@ -151,19 +154,33 @@ public class DropRequestDTO {
}
/**
- * @return the siez of the flow files currently queued.
+ * @return the size of the flow files currently queued in bytes.
*/
@ApiModelProperty(
- value = "The size of flow files currently queued."
+ value = "The size of flow files currently queued in bytes."
)
- public String getCurrentSize() {
+ public Long getCurrentSize() {
return currentSize;
}
- public void setCurrentSize(String currentSize) {
+ public void setCurrentSize(Long currentSize) {
this.currentSize = currentSize;
}
+ /**
+ * @return the count and size of the currently queued flow files.
+ */
+ @ApiModelProperty(
+ value = "The count and size of flow files currently queued."
+ )
+ public String getCurrent() {
+ return current;
+ }
+
+ public void setCurrent(String current) {
+ this.current = current;
+ }
+
/**
* @return the number of flow files to be dropped as a result of this request.
*/
@@ -179,19 +196,33 @@ public class DropRequestDTO {
}
/**
- * @return the size of the flow files to be dropped as a result of this request.
+ * @return the size of the flow files to be dropped as a result of this request in bytes.
*/
@ApiModelProperty(
- value = "The size of flow files to be dropped as a result of this request."
+ value = "The size of flow files to be dropped as a result of this request in bytes."
)
- public String getOriginalSize() {
+ public Long getOriginalSize() {
return originalSize;
}
- public void setOriginalSize(String originalSize) {
+ public void setOriginalSize(Long originalSize) {
this.originalSize = originalSize;
}
+ /**
+ * @return the count and size of flow files to be dropped as a result of this request.
+ */
+ @ApiModelProperty(
+ value = "The count and size of flow files to be dropped as a result of this request."
+ )
+ public String getOriginal() {
+ return original;
+ }
+
+ public void setOriginal(String original) {
+ this.original = original;
+ }
+
/**
* @return the number of flow files that have been dropped thus far.
*/
@@ -207,19 +238,33 @@ public class DropRequestDTO {
}
/**
- * @return the size of the flow files that have been dropped thus far.
+ * @return the size of the flow files that have been dropped thus far in bytes.
*/
@ApiModelProperty(
- value = "The size of flow files that have been dropped thus far."
+ value = "The size of flow files that have been dropped thus far in bytes."
)
- public String getDroppedSize() {
+ public Long getDroppedSize() {
return droppedSize;
}
- public void setDroppedSize(String droppedSize) {
+ public void setDroppedSize(Long droppedSize) {
this.droppedSize = droppedSize;
}
+ /**
+ * @return the count and size of the flow files that have been dropped thus far.
+ */
+ @ApiModelProperty(
+ value = "The count and size of flow files that have been dropped thus far."
+ )
+ public String getDropped() {
+ return dropped;
+ }
+
+ public void setDropped(String dropped) {
+ this.dropped = dropped;
+ }
+
/**
* @return the current state of the drop request.
*/
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiServiceFacade.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiServiceFacade.java
index 0703a41486..2d3355ae43 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiServiceFacade.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiServiceFacade.java
@@ -552,8 +552,9 @@ public interface NiFiServiceFacade {
* @param groupId group
* @param connectionId The ID of the connection
* @param dropRequestId The flow file drop request
+ * @return The DropRequest
*/
- void deleteFlowFileDropRequest(String groupId, String connectionId, String dropRequestId);
+ DropRequestDTO deleteFlowFileDropRequest(String groupId, String connectionId, String dropRequestId);
// ----------------------------------------
// InputPort methods
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java
index b2e600003e..51f87517e7 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java
@@ -810,8 +810,8 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
}
@Override
- public void deleteFlowFileDropRequest(String groupId, String connectionId, String dropRequestId) {
- connectionDAO.deleteFlowFileDropRequest(groupId, connectionId, dropRequestId);
+ public DropRequestDTO deleteFlowFileDropRequest(String groupId, String connectionId, String dropRequestId) {
+ return dtoFactory.createDropRequestDTO(connectionDAO.deleteFlowFileDropRequest(groupId, connectionId, dropRequestId));
}
@Override
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ConnectionResource.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ConnectionResource.java
index 0d00468aff..b170d39145 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ConnectionResource.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ConnectionResource.java
@@ -1086,7 +1086,8 @@ public class ConnectionResource extends ApplicationResource {
}
// delete the drop request
- serviceFacade.deleteFlowFileDropRequest(groupId, connectionId, dropRequestId);
+ final DropRequestDTO dropRequest = serviceFacade.deleteFlowFileDropRequest(groupId, connectionId, dropRequestId);
+ dropRequest.setUri(generateResourceUri("controller", "process-groups", groupId, "connections", connectionId, "contents", "drop-requests", dropRequestId));
// create the revision
final RevisionDTO revision = new RevisionDTO();
@@ -1095,6 +1096,7 @@ public class ConnectionResource extends ApplicationResource {
// create the response entity
final DropRequestEntity entity = new DropRequestEntity();
entity.setRevision(revision);
+ entity.setDropRequest(dropRequest);
return generateOkResponse(entity).build();
}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java
index d123704126..264268bf0a 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java
@@ -312,13 +312,16 @@ public final class DtoFactory {
final QueueSize dropped = dropRequest.getDroppedSize();
dto.setDroppedCount(dropped.getObjectCount());
- dto.setDroppedSize(FormatUtils.formatDataSize(dropped.getByteCount()));
+ dto.setDroppedSize(dropped.getByteCount());
+ dto.setDropped(FormatUtils.formatCount(dropped.getObjectCount()) + " / " + FormatUtils.formatDataSize(dropped.getByteCount()));
if (dropRequest.getOriginalSize() != null) {
final QueueSize original = dropRequest.getOriginalSize();
dto.setOriginalCount(original.getObjectCount());
- dto.setOriginalSize(FormatUtils.formatDataSize(original.getByteCount()));
- dto.setPercentCompleted((dropped.getObjectCount() * 100 ) / original.getObjectCount());
+ dto.setOriginalSize(original.getByteCount());
+ dto.setOriginal(FormatUtils.formatCount(original.getObjectCount()) + " / " + FormatUtils.formatDataSize(original.getByteCount()));
+
+ dto.setPercentCompleted((dropped.getObjectCount() * 100) / original.getObjectCount());
} else {
dto.setPercentCompleted(0);
}
@@ -326,7 +329,8 @@ public final class DtoFactory {
if (dropRequest.getCurrentSize() != null) {
final QueueSize current = dropRequest.getCurrentSize();
dto.setCurrentCount(current.getObjectCount());
- dto.setCurrentSize(FormatUtils.formatDataSize(current.getByteCount()));
+ dto.setCurrentSize(current.getByteCount());
+ dto.setCurrent(FormatUtils.formatCount(current.getObjectCount()) + " / " + FormatUtils.formatDataSize(current.getByteCount()));
}
return dto;
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/ConnectionDAO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/ConnectionDAO.java
index 3665a4e728..2be4403243 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/ConnectionDAO.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/ConnectionDAO.java
@@ -134,6 +134,7 @@ public interface ConnectionDAO {
* @param groupId group id
* @param id The id of the connection
* @param dropRequestId The drop request id
+ * @return The drop request
*/
- void deleteFlowFileDropRequest(String groupId, String id, String dropRequestId);
+ DropFlowFileStatus deleteFlowFileDropRequest(String groupId, String id, String dropRequestId);
}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardConnectionDAO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardConnectionDAO.java
index 399ffa1a57..66730a385c 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardConnectionDAO.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardConnectionDAO.java
@@ -496,10 +496,10 @@ public class StandardConnectionDAO extends ComponentDAO implements ConnectionDAO
}
@Override
- public void deleteFlowFileDropRequest(String groupId, String connectionId, String dropRequestId) {
+ public DropFlowFileStatus deleteFlowFileDropRequest(String groupId, String connectionId, String dropRequestId) {
final Connection connection = locateConnection(groupId, connectionId);
final FlowFileQueue queue = connection.getFlowFileQueue();
- queue.cancelDropFlowFileRequest(dropRequestId);
+ return queue.cancelDropFlowFileRequest(dropRequestId);
}
/* setters */
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 c81bb9d769..1bf63a6e42 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
@@ -119,6 +119,7 @@
+
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/drop-request-status-dialog.jsp b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/drop-request-status-dialog.jsp
new file mode 100644
index 0000000000..b001a1ad45
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/drop-request-status-dialog.jsp
@@ -0,0 +1,29 @@
+<%--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+--%>
+<%@ page contentType="text/html" pageEncoding="UTF-8" session="false" %>
+
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/dialog.css b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/dialog.css
index 88555e76c0..6cb6dba96b 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/dialog.css
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/dialog.css
@@ -269,6 +269,31 @@ div.go-to-link {
height: 195px;
}
+#drop-request-status-dialog {
+ display: none;
+ width: 400px;
+ height: 135px;
+ z-index: 1301;
+}
+
+#drop-request-percent-complete {
+ width: 378px;
+ border-radius: 0;
+}
+
+#drop-request-percent-complete .ui-progressbar-value {
+ border-radius: 0;
+}
+
+div.progress-label {
+ color: #000000;
+ display: block;
+ font-weight: bold;
+ text-align: center;
+ width: 378px;
+ margin-top: 4px;
+}
+
#nf-ok-dialog {
z-index: 1302;
display: none;
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/iconEmptyQueue.png b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/iconEmptyQueue.png
new file mode 100644
index 0000000000..42e5a15fd0
Binary files /dev/null and b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/images/iconEmptyQueue.png differ
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 2a94ec5268..ba144ef560 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
@@ -24,6 +24,31 @@ nf.Actions = (function () {
controller: '../nifi-api/controller'
}
};
+
+ /**
+ * Initializes the drop request status dialog.
+ */
+ var initializeDropRequestStatusDialog = function () {
+ // initialize the drop requst progress bar
+ var dropRequestProgressBar = $('#drop-request-percent-complete').progressbar();
+
+ // configure the drop request status dialog
+ $('#drop-request-status-dialog').modal({
+ headerText: 'Emptying queue',
+ overlayBackground: false,
+ handler: {
+ close: function () {
+ // reset the progress bar
+ dropRequestProgressBar.find('div.progress-label').remove();
+
+ // update the progress bar
+ var label = $('').text('0%');
+ dropRequestProgressBar.progressbar('value', 0).append(label);
+ }
+ }
+ });
+ };
+
/**
* Updates the resource with the specified data.
@@ -78,6 +103,13 @@ nf.Actions = (function () {
};
return {
+ /**
+ * Initializes the actions.
+ */
+ init: function () {
+ initializeDropRequestStatusDialog();
+ },
+
/**
* Enters the specified process group.
*
@@ -855,56 +887,144 @@ nf.Actions = (function () {
return;
}
- var MAX_DELAY = 4;
+ // prompt the user before emptying the queue
+ nf.Dialog.showYesNoDialog({
+ dialogContent: 'Are you sure you want to empty the queue? All data enqueued at the time of the request will be removed from the dataflow.',
+ overlayBackground: false,
+ yesHandler: function () {
+ // get the connection data
+ var connection = selection.datum();
+
+ var MAX_DELAY = 4;
+ var cancelled = false;
+ var dropRequest = null;
+ var dropRequestTimer = null;
- // process the drop request
- var processDropRequest = function (dropRequest, nextDelay) {
- // see if the drop request has completed
- if (dropRequest.finished === true) {
- // request is finished so it can be removed
- deleteDropRequest(dropRequest);
- } else {
- // update the UI with the current status of the drop request
- schedule(dropRequest, nextDelay);
- }
- };
+ // updates the progress bar
+ var updateProgress = function (percentComplete) {
+ // remove existing labels
+ var progressBar = $('#drop-request-percent-complete');
+ progressBar.find('div.progress-label').remove();
- // schedule for the next poll iteration
- var schedule = function (dropRequest, delay) {
- setTimeout(function () {
+ // update the progress bar
+ var label = $('').text(percentComplete + '%');
+ if (percentComplete > 0) {
+ label.css('margin-top', '-19px');
+ }
+ progressBar.progressbar('value', percentComplete).append(label);
+ };
+
+ // update the button model of the drop request status dialog
+ $('#drop-request-status-dialog').modal('setButtonModel', [{
+ buttonText: 'Cancel',
+ handler: {
+ click: function () {
+ cancelled = true;
+
+ // we are waiting for the next poll attempt
+ if (dropRequestTimer !== null) {
+ // cancel it
+ clearTimeout(dropRequestTimer);
+
+ // cancel the provenance
+ completeDropRequest();
+ }
+ }
+ }
+ }]);
+
+ // completes the drop request by removing it and showing how many flowfiles were deleted
+ var completeDropRequest = function () {
+ if (nf.Common.isDefinedAndNotNull(dropRequest)) {
+ $.ajax({
+ type: 'DELETE',
+ url: dropRequest.uri,
+ dataType: 'json'
+ }).done(function(response) {
+ // report the results of this drop request
+ dropRequest = response.dropRequest;
+
+ // parse the dropped stats to render results
+ var tokens = dropRequest.dropped.split(/ \/ /);
+ var results = $('').text('Successfully removed ' + tokens[0] + ' (' + tokens[1] + ') FlowFiles');
+ nf.Dialog.showOkDialog({
+ dialogContent: results,
+ overlayBackground: false
+ });
+ }).always(function() {
+ $('#drop-request-status-dialog').modal('hide');
+ });
+ } else {
+ // nothing was removed
+ nf.Dialog.showYesNoDialog({
+ dialogContent: 'No FlowFiles were removed.',
+ overlayBackground: false
+ });
+
+ // close the dialog
+ $('#drop-request-status-dialog').modal('hide');
+ }
+ };
+
+ // process the drop request
+ var processDropRequest = function (delay) {
+ // update the percent complete
+ updateProgress(dropRequest.percentCompleted);
+
+ // update the status of the drop request
+ $('#drop-request-status-message').text(dropRequest.state);
+
+ // update the current number of enqueued flowfiles
+ if (nf.Common.isDefinedAndNotNull(dropRequest.currentCount)) {
+ connection.status.queued = dropRequest.current;
+ nf.Connection.refresh(connection.id);
+ }
+
+ // close the dialog if the
+ if (dropRequest.finished === true || cancelled === true) {
+ completeDropRequest();
+ } else {
+ // wait delay to poll again
+ dropRequestTimer = setTimeout(function () {
+ // clear the drop request timer
+ dropRequestTimer = null;
+
+ // schedule to poll the status again in nextDelay
+ pollDropRequest(Math.min(MAX_DELAY, delay * 2));
+ }, delay * 1000);
+ }
+ };
+
+ // schedule for the next poll iteration
+ var pollDropRequest = function (nextDelay) {
+ $.ajax({
+ type: 'GET',
+ url: dropRequest.uri,
+ dataType: 'json'
+ }).done(function(response) {
+ dropRequest = response.dropRequest;
+ processDropRequest(nextDelay);
+ }).fail(completeDropRequest);
+ };
+
+ // issue the request to delete the flow files
$.ajax({
- type: 'GET',
- url: dropRequest.uri,
+ type: 'DELETE',
+ url: connection.component.uri + '/contents',
dataType: 'json'
}).done(function(response) {
- var dropRequest = response.dropRequest;
- processDropRequest(dropRequest, Math.min(MAX_DELAY, delay * 2));
- }).fail(nf.Common.handleAjaxError);
- }, delay * 1000);
- };
-
- // delete the drop request
- var deleteDropRequest = function (dropRequest) {
- $.ajax({
- type: 'DELETE',
- url: dropRequest.uri,
- dataType: 'json'
- }).done(function() {
- // drop request has been deleted
- }).fail(nf.Common.handleAjaxError);
- };
-
- // get the connection data
- var connection = selection.datum();
-
- // issue the request to delete the flow files
- $.ajax({
- type: 'DELETE',
- url: connection.component.uri + '/contents',
- dataType: 'json'
- }).done(function(response) {
- processDropRequest(response.dropRequest, 1);
- }).fail(nf.Common.handleAjaxError);
+ // initialize the progress bar value
+ updateProgress(0);
+
+ // show the progress dialog
+ $('#drop-request-status-dialog').modal('show');
+
+ // process the drop request
+ dropRequest = response.dropRequest;
+ processDropRequest(1);
+ }).fail(completeDropRequest);
+ }
+ });
},
/**
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 33f116e0b6..7137fe4be9 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
@@ -188,7 +188,7 @@ nf.Canvas = (function () {
if (!refreshContainer.is(':visible')) {
$('#stats-last-refreshed').addClass('alert');
var refreshMessage = "This flow has been modified by '" + revision.lastModifier + "'. Please refresh.";
-
+
// update the tooltip
var refreshRequiredIcon = $('#refresh-required-icon');
if (refreshRequiredIcon.data('qtip')) {
@@ -198,10 +198,10 @@ nf.Canvas = (function () {
content: refreshMessage
}, nf.CanvasUtils.config.systemTooltipConfig));
}
-
+
refreshContainer.show();
}
-
+
// insert the refresh needed text in the settings - if necessary
if (!settingsRefreshIcon.is(':visible')) {
$('#settings-last-refreshed').addClass('alert');
@@ -333,7 +333,7 @@ nf.Canvas = (function () {
'offset': '100%',
'stop-color': '#ffffff'
});
-
+
// define the gradient for the expiration icon
var expirationBackground = defs.append('linearGradient')
.attr({
@@ -343,7 +343,7 @@ nf.Canvas = (function () {
'x2': '0%',
'y2': '100%'
});
-
+
expirationBackground.append('stop')
.attr({
'offset': '0%',
@@ -397,106 +397,106 @@ nf.Canvas = (function () {
// prevent further propagation (to parents and others handlers
// on the same element to prevent zoom behavior)
d3.event.stopImmediatePropagation();
-
+
// prevents the browser from changing to a text selection cursor
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.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];
+ }
+
+ // update the selection box
+ selectionBox.attr(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;
}
- 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];
+ // reset the canvas click flag
+ canvasClicked = false;
+
+ // 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 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.component.position.x >= selectionBoundingBox.x && (d.component.position.x + d.dimensions.width) <= (selectionBoundingBox.x + selectionBoundingBox.width) &&
+ d.component.position.y >= selectionBoundingBox.y && (d.component.position.y + d.dimensions.height) <= (selectionBoundingBox.y + selectionBoundingBox.height);
+ });
+
+ // 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);
+ });
+
+ // remove the selection box
+ selectionBox.remove();
+ } else if (panning === false) {
+ // deselect as necessary if we are not panning
+ nf.CanvasUtils.getSelection().classed('selected', false);
}
- // update the selection box
- selectionBox.attr(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;
- }
-
- // reset the canvas click flag
- canvasClicked = false;
-
- // 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 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.component.position.x >= selectionBoundingBox.x && (d.component.position.x + d.dimensions.width) <= (selectionBoundingBox.x + selectionBoundingBox.width) &&
- d.component.position.y >= selectionBoundingBox.y && (d.component.position.y + d.dimensions.height) <= (selectionBoundingBox.y + selectionBoundingBox.height);
+ // update the toolbar
+ nf.CanvasToolbar.refresh();
});
- // 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);
- });
-
- // remove the selection box
- selectionBox.remove();
- } else if (panning === false) {
- // deselect as necessary if we are not panning
- nf.CanvasUtils.getSelection().classed('selected', false);
- }
-
- // update the toolbar
- nf.CanvasToolbar.refresh();
- });
-
// define a function for update the graph dimensions
var updateGraphSize = function () {
// get the location of the bottom of the graph
@@ -510,7 +510,7 @@ nf.Canvas = (function () {
var top = parseInt(canvasContainer.css('top'), 10);
var windowHeight = $(window).height();
var canvasHeight = (windowHeight - (bottom + top));
-
+
// canvas/svg
canvasContainer.css({
'height': canvasHeight + 'px',
@@ -536,7 +536,7 @@ nf.Canvas = (function () {
}
}).on('keydown', function (evt) {
var isCtrl = evt.ctrlKey || evt.metaKey;
-
+
// consider escape, before checking dialogs
if (!isCtrl && evt.keyCode === 27) {
// esc
@@ -552,7 +552,7 @@ nf.Canvas = (function () {
// first consider read only property detail dialog
if ($('div.property-detail').is(':visible')) {
nf.Common.removeAllPropertyDetailDialogs();
-
+
// prevent further bubbling as we're already handled it
evt.stopPropagation();
evt.preventDefault();
@@ -570,7 +570,7 @@ nf.Canvas = (function () {
var dialogMax = null;
// identify the top most cancellable
- $.each(cancellables, function(_, cancellable) {
+ $.each(cancellables, function (_, cancellable) {
var dialog = $(cancellable);
var zIndex = dialog.css('zIndex');
@@ -615,10 +615,10 @@ nf.Canvas = (function () {
}
}
}
-
+
return;
}
-
+
// if a dialog is open, disable canvas shortcuts
if ($('.dialog').is(':visible')) {
return;
@@ -833,7 +833,7 @@ nf.Canvas = (function () {
bulletinIcon.show();
}
}
-
+
// update controller service and reporting task bulletins
nf.Settings.setBulletins(controllerStatus.controllerServiceBulletins, controllerStatus.reportingTaskBulletins);
@@ -934,21 +934,17 @@ nf.Canvas = (function () {
};
return {
-
CANVAS_OFFSET: 0,
-
/**
* Determines if the current broswer supports SVG.
*/
SUPPORTS_SVG: !!document.createElementNS && !!document.createElementNS('http://www.w3.org/2000/svg', 'svg').createSVGRect,
-
/**
* Hides the splash that is displayed while the application is loading.
*/
hideSplash: function () {
$('#splash').fadeOut();
},
-
/**
* Stop polling for revision.
*/
@@ -956,7 +952,6 @@ nf.Canvas = (function () {
// set polling flag
revisionPolling = false;
},
-
/**
* Remove the status poller.
*/
@@ -964,7 +959,6 @@ nf.Canvas = (function () {
// set polling flag
statusPolling = false;
},
-
/**
* Reloads the flow from the server based on the currently specified group id.
* To load another group, update nf.Canvas.setGroupId and call nf.Canvas.reload.
@@ -973,7 +967,7 @@ nf.Canvas = (function () {
return $.Deferred(function (deferred) {
// hide the context menu
nf.ContextMenu.hide();
-
+
// get the process group to refresh everything
var processGroupXhr = reloadProcessGroup(nf.Canvas.getGroupId());
var statusXhr = reloadFlowStatus();
@@ -1007,7 +1001,6 @@ nf.Canvas = (function () {
});
}).promise();
},
-
/**
* Reloads the status.
*/
@@ -1021,7 +1014,6 @@ nf.Canvas = (function () {
});
}).promise();
},
-
/**
* Initialize NiFi.
*/
@@ -1099,6 +1091,7 @@ nf.Canvas = (function () {
nf.GraphControl.init();
nf.Search.init();
nf.Settings.init();
+ nf.Actions.init();
// initialize the component behaviors
nf.Draggable.init();
@@ -1146,7 +1139,6 @@ nf.Canvas = (function () {
}).fail(nf.Common.handleAjaxError);
}).fail(nf.Common.handleAjaxError);
},
-
/**
* Defines the gradient colors used to render processors.
*
@@ -1155,7 +1147,6 @@ nf.Canvas = (function () {
defineProcessorColors: function (colors) {
setColors(colors, 'processor');
},
-
/**
* Defines the gradient colors used to render label.
*
@@ -1164,7 +1155,6 @@ nf.Canvas = (function () {
defineLabelColors: function (colors) {
setColors(colors, 'label');
},
-
/**
* Return whether this instance of NiFi is clustered.
*
@@ -1173,14 +1163,12 @@ nf.Canvas = (function () {
isClustered: function () {
return clustered === true;
},
-
/**
* Returns whether site to site communications is secure.
*/
isSecureSiteToSite: function () {
return secureSiteToSite;
},
-
/**
* Set the group id.
*
@@ -1189,14 +1177,12 @@ nf.Canvas = (function () {
setGroupId: function (gi) {
groupId = gi;
},
-
/**
* Get the group id.
*/
getGroupId: function () {
return groupId;
},
-
/**
* Set the group name.
*
@@ -1205,14 +1191,12 @@ nf.Canvas = (function () {
setGroupName: function (gn) {
groupName = gn;
},
-
/**
* Get the group name.
*/
getGroupName: function () {
return groupName;
},
-
/**
* Set the parent group id.
*
@@ -1221,16 +1205,14 @@ nf.Canvas = (function () {
setParentGroupId: function (pgi) {
parentGroupId = pgi;
},
-
/**
* Get the parent group id.
*/
getParentGroupId: function () {
return parentGroupId;
},
-
View: (function () {
-
+
/**
* Updates component visibility based on their proximity to the screen's viewport.
*/
@@ -1297,8 +1279,8 @@ nf.Canvas = (function () {
.classed('entering', function () {
return visible && !wasVisible;
}).classed('leaving', function () {
- return !visible && wasVisible;
- });
+ return !visible && wasVisible;
+ });
};
// get the all components
@@ -1385,7 +1367,6 @@ nf.Canvas = (function () {
// add the behavior to the canvas and disable dbl click zoom
svg.call(behavior).on('dblclick.zoom', null);
},
-
/**
* Whether or not a component should be rendered based solely on the current scale.
*
@@ -1394,7 +1375,6 @@ nf.Canvas = (function () {
shouldRenderPerScale: function () {
return nf.Canvas.View.scale() >= MIN_SCALE_TO_RENDER;
},
-
/**
* Updates component visibility based on the current translation/scale.
*/
@@ -1402,7 +1382,6 @@ nf.Canvas = (function () {
updateComponentVisibility();
nf.Graph.pan();
},
-
/**
* Sets/gets the current translation.
*
@@ -1415,7 +1394,6 @@ nf.Canvas = (function () {
behavior.translate(translate);
}
},
-
/**
* Sets/gets the current scale.
*
@@ -1428,7 +1406,6 @@ nf.Canvas = (function () {
behavior.scale(scale);
}
},
-
/**
* Zooms in a single zoom increment.
*/
@@ -1453,7 +1430,6 @@ nf.Canvas = (function () {
height: 1
});
},
-
/**
* Zooms out a single zoom increment.
*/
@@ -1478,7 +1454,6 @@ nf.Canvas = (function () {
height: 1
});
},
-
/**
* Zooms to fit the entire graph on the canvas.
*/
@@ -1525,7 +1500,6 @@ nf.Canvas = (function () {
height: canvasHeight / newScale
});
},
-
/**
* Zooms to the actual size (1 to 1).
*/
@@ -1574,7 +1548,6 @@ nf.Canvas = (function () {
// center as appropriate
nf.CanvasUtils.centerBoundingBox(box);
},
-
/**
* Refreshes the view based on the configured translation and scale.
*
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-context-menu.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-context-menu.js
index f2b358dcc4..2ce3f7d615 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-context-menu.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-context-menu.js
@@ -278,11 +278,11 @@ nf.ContextMenu = (function () {
};
/**
- * Only DFMs can delete flow files from a connection.
+ * Only DFMs can empty a queue.
*
* @param {selection} selection
*/
- var canDeleteFlowFiles = function (selection) {
+ var canEmptyQueue = function (selection) {
return nf.Common.isDFM() && isConnection(selection);
};
@@ -382,7 +382,7 @@ nf.ContextMenu = (function () {
{condition: isCopyable, menuItem: {img: 'images/iconCopy.png', text: 'Copy', action: 'copy'}},
{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: canDeleteFlowFiles, menuItem: {img: 'images/iconDelete.png', text: 'Empty queue', action: 'emptyQueue'}},
+ {condition: canEmptyQueue, menuItem: {img: 'images/iconEmptyQueue.png', text: 'Empty queue', action: 'emptyQueue'}},
{condition: isDeletable, menuItem: {img: 'images/iconDelete.png', text: 'Delete', action: 'delete'}}
];