You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by mc...@apache.org on 2019/04/26 16:07:57 UTC
[nifi] branch master updated: NIFI-5986 Adding "Stop & Configure"
button functionality to Processor Details modal. NIFI-5986 Refactored Stop
& Configure feature to enable bulletin/thread notifications and terminate
capability in processor dialogs. Also added feature as a menu item to the
canvas context menu. NIFI-5986 Refactored Stop & Configure feature to
enable a status bar in a dialog that conveys bulletin/thread notifications
and buttons. NIFI-5986 Refactored Stop & Configure feature to decouple
status bar from mod [...]
This is an automated email from the ASF dual-hosted git repository.
mcgilman pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nifi.git
The following commit(s) were added to refs/heads/master by this push:
new c5c9425 NIFI-5986 Adding "Stop & Configure" button functionality to Processor Details modal. NIFI-5986 Refactored Stop & Configure feature to enable bulletin/thread notifications and terminate capability in processor dialogs. Also added feature as a menu item to the canvas context menu. NIFI-5986 Refactored Stop & Configure feature to enable a status bar in a dialog that conveys bulletin/thread notifications and buttons. NIFI-5986 Refactored Stop & Configure feature to decouple [...]
c5c9425 is described below
commit c5c9425989ebd6d2b162b599da9dd12aadc72a6d
Author: Alex Aversa <al...@gmail.com>
AuthorDate: Wed Jan 30 21:09:56 2019 +0000
NIFI-5986 Adding "Stop & Configure" button functionality to Processor Details modal.
NIFI-5986 Refactored Stop & Configure feature to enable bulletin/thread notifications and terminate capability in processor dialogs. Also added feature as a menu item to the canvas context menu.
NIFI-5986 Refactored Stop & Configure feature to enable a status bar in a dialog that conveys bulletin/thread notifications and buttons.
NIFI-5986 Refactored Stop & Configure feature to decouple status bar from modal component, updated styling and revised graph synchronization process.
NIFI-5986 Refactored Stop & Configure feature to improve status bar button hide/show functionality.
NIFI-5986: Rebased and resolved conflicts.
NIFI-5986 - Refactored Stop & Configure statusbar observer, as well as processor dialogs to remove duplicative code.
This closes #3281
---
.../src/main/webapp/WEB-INF/pages/canvas.jsp | 2 +
.../partials/canvas/processor-configuration.jsp | 1 +
.../webapp/WEB-INF/partials/processor-details.jsp | 1 +
.../nifi-web-ui/src/main/webapp/css/common-ui.css | 32 +++
.../main/webapp/css/processor-configuration.css | 5 +
.../src/main/webapp/css/processor-details.css | 5 +
.../js/jquery/statusbar/jquery.statusbar.css | 141 ++++++++++
.../webapp/js/jquery/statusbar/jquery.statusbar.js | 288 +++++++++++++++++++++
.../src/main/webapp/js/nf/canvas/nf-actions.js | 44 +++-
.../webapp/js/nf/canvas/nf-canvas-bootstrap.js | 12 +-
.../main/webapp/js/nf/canvas/nf-canvas-utils.js | 10 +
.../main/webapp/js/nf/canvas/nf-context-menu.js | 18 +-
.../js/nf/canvas/nf-processor-configuration.js | 117 ++++++++-
.../nifi-web-ui/src/main/webapp/js/nf/nf-common.js | 13 +
.../src/main/webapp/js/nf/nf-processor-details.js | 89 ++++++-
.../main/webapp/js/nf/summary/nf-summary-table.js | 5 +-
16 files changed, 756 insertions(+), 27 deletions(-)
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 38e8097..cee2c5e 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
@@ -32,6 +32,7 @@
<link rel="stylesheet" href="js/jquery/propertytable/jquery.propertytable.css?${project.version}" type="text/css" />
<link rel="stylesheet" href="js/jquery/tagcloud/jquery.tagcloud.css?${project.version}" type="text/css" />
<link rel="stylesheet" href="js/jquery/modal/jquery.modal.css?${project.version}" type="text/css" />
+ <link rel="stylesheet" href="js/jquery/statusbar/jquery.statusbar.css?${project.version}" type="text/css" />
<link rel="stylesheet" href="assets/qtip2/dist/jquery.qtip.min.css?" type="text/css" />
<link rel="stylesheet" href="assets/jquery-ui-dist/jquery-ui.min.css" type="text/css" />
<link rel="stylesheet" href="assets/jquery-minicolors/jquery.minicolors.css" type="text/css" />
@@ -88,6 +89,7 @@
<script type="text/javascript" src="js/jquery/nfeditor/jquery.nfeditor.js?${project.version}"></script>
<script type="text/javascript" src="js/jquery/propertytable/jquery.propertytable.js?${project.version}"></script>
<script type="text/javascript" src="js/jquery/tagcloud/jquery.tagcloud.js?${project.version}"></script>
+ <script type="text/javascript" src="js/jquery/statusbar/jquery.statusbar.js?${project.version}"></script>
</head>
<body ng-controller="ngCanvasAppCtrl" id="canvas-body">
<div id="splash">
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/processor-configuration.jsp b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/processor-configuration.jsp
index b7917a1..9f0494d 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/processor-configuration.jsp
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/processor-configuration.jsp
@@ -16,6 +16,7 @@
--%>
<%@ page contentType="text/html" pageEncoding="UTF-8" session="false" %>
<div id="processor-configuration" layout="column" class="hidden large-dialog">
+ <div id="processor-configuration-status-bar"></div>
<div class="processor-configuration-tab-container dialog-content">
<div id="processor-configuration-tabs" class="tab-container"></div>
<div id="processor-configuration-tabs-content">
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/processor-details.jsp b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/processor-details.jsp
index dffe4cf..fcb8f60 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/processor-details.jsp
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/processor-details.jsp
@@ -16,6 +16,7 @@
--%>
<%@ page contentType="text/html" pageEncoding="UTF-8" session="false" %>
<div id="processor-details" class="hidden large-dialog">
+ <div id="processor-details-status-bar"></div>
<div class="dialog-content">
<div id="processor-details-tabs" class="tab-container"></div>
<div id="processor-details-tabs-content">
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/common-ui.css b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/common-ui.css
index 9f99c57..26bafd4 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/common-ui.css
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/common-ui.css
@@ -415,6 +415,33 @@ input.filter {
margin-bottom: 5px;
}
+/* overlay icon styles */
+
+.stop-configure-icon.fa-stop {
+ display : inline-block;
+ font-size: 15px;
+ position : relative;
+ top : -1px;
+}
+
+.stop-configure-icon::after {
+ content : "\f013";
+ font-size: 14px;
+ position : relative;
+ top : 0px;
+ left : -8px;
+ color : #ffffff;
+ -webkit-text-stroke-width : 1px;
+ -webkit-text-stroke-color : #004849;
+
+}
+
+*.stop-configure-icon + span {
+ display : inline-block;
+ padding : 0px 0px 0px 0px;
+ margin-left : -10px;
+}
+
/* buttons */
button.fa {
@@ -443,6 +470,11 @@ div.button-icon {
font-size: 18px !important;
}
+div.button.auto-width,
+div.button-icon.auto-width {
+ width : auto !important;
+}
+
div.button {
height: 32px;
width: 90px;
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/processor-configuration.css b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/processor-configuration.css
index a12edcb..6a78ef8 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/processor-configuration.css
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/processor-configuration.css
@@ -187,3 +187,8 @@ div.processor-relationship-container {
#processor-comments {
height: 100%;
}
+
+/* status bar button icon */
+#processor-configuration div.dialog-status-bar div.button-icon.fa-hourglass-end {
+ font-size : 11px !important;
+}
\ No newline at end of file
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/processor-details.css b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/processor-details.css
index 5b1f758..db11152 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/processor-details.css
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/processor-details.css
@@ -71,3 +71,8 @@ div.relationship-description {
margin-left: 16px;
margin-top: 2px;
}
+
+/* status bar button icon */
+#processor-details div.dialog-status-bar div.button-icon.fa-cog {
+ font-size : 14px !important;
+}
\ No newline at end of file
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/jquery/statusbar/jquery.statusbar.css b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/jquery/statusbar/jquery.statusbar.css
new file mode 100644
index 0000000..c13f7c0
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/jquery/statusbar/jquery.statusbar.css
@@ -0,0 +1,141 @@
+/*
+ * 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.
+ */
+/*
+ Styles for the Nifi status bar module.
+*/
+
+.dialog-status-bar {
+ padding-left : 32px;
+ background-color : #e3e8eb;
+ width : calc(100% - 32px);
+ height : 32px;
+}
+
+.dialog-status-bar[state] + .dialog-content {
+ top: 104px;
+}
+
+.dialog-status-bar:not([state]),
+.dialog-status-bar:not([state]) text.run-status-icon,
+.dialog-status-bar-bulletins-content,
+.dialog-status-bar-bulletins[count="0"],
+.dialog-status-bar-threads[count="0"] {
+ display : none;
+}
+
+.dialog-status-bar[state] text.run-status-icon {
+ position : absolute;
+ font-style : normal;
+ font-weight : normal;
+ text-decoration : inherit;
+ font-family : FontAwesome;
+ font-size : 14px;
+ margin: 8px 5px 0px -17px;
+}
+
+.dialog-status-bar-buttons,
+.dialog-status-bar[state] text.run-status-icon:before {
+ display : inline-block;
+}
+
+.dialog-status-bar-buttons {
+ float : right;
+}
+
+.dialog-status-bar[state="RUNNING"] text.run-status-icon::before {
+ content : "\f04b";
+ color : #7dc7a0;
+}
+
+.dialog-status-bar[state="STOPPED"] text.run-status-icon::before {
+ content : "\f04d";
+ color : #d18686;
+}
+
+.dialog-status-bar[state="VALIDATING"] text.run-status-icon::before {
+ content: '\f1ce';
+ color : #7728e9b;
+ -webkit-animation: fa-spin 2s linear infinite;
+ -moz-animation: fa-spin 2s linear infinite;
+ animation: fa-spin 2s linear infinite;
+ margin-left : -3px !important;
+}
+
+.dialog-status-bar[state="DISABLED"] text.run-status-icon::before {
+ content: '\e802';
+ color : #7728e9b;
+ font-family: flowfont;
+}
+
+.dialog-status-bar[state="INVALID"] text.run-status-icon::before {
+ content : "\f071";
+ color : #cf9f5d;
+ margin-left : -3px !important;
+}
+
+.dialog-status-bar-state,
+.dialog-status-bar-threads:not([count="0"]){
+ display : inline-block;
+ position : relative;
+ font-size : 12px;
+ color : #775351;
+ top : 10px;
+ left : -2px;
+ margin-right : 5px;
+ font-weight : bold;
+ cursor : default;
+}
+
+.dialog-status-bar .dialog-buttons {
+ position: static;
+ display : inline-block !important;
+ height: 32px;
+ width : auto !important;
+}
+
+.dialog-status-bar-bulletins:not([count="0"]) {
+ float : right;
+ display : inline-block;
+ padding : 10px 8px 7px 8px;
+ background-color : #ba544a;
+ color : #ffffff;
+ font-size : 15px;
+ cursor : pointer;
+}
+
+.dialog-status-bar-bulletins:not([count="0"]):hover .dialog-status-bar-bulletins-content {
+ position : fixed;
+ display : block;
+ float : right;
+ margin-left : 22px;
+ margin-top : 5px;
+ background-color : rgba(36,36,36,0.75);
+ font-family: Arial;
+ font-weight : bold;
+ font-size : 12px;
+ padding : 10px 10px 10px 20px;
+ width : auto;
+ max-width : 490px;
+}
+
+.dialog-status-bar-bulletins-content ul {
+ list-style-type : disc !important;
+}
+
+.dialog-status-bar-buttons *.disabled-button {
+ display:none;
+}
\ No newline at end of file
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/jquery/statusbar/jquery.statusbar.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/jquery/statusbar/jquery.statusbar.js
new file mode 100644
index 0000000..c16e314
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/jquery/statusbar/jquery.statusbar.js
@@ -0,0 +1,288 @@
+/*
+ * 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.
+ */
+
+/**
+ * Create a new status bar.
+ *
+ * $(selector).statusbar();
+ *
+ *
+ */
+(function ($) {
+
+ // static key path variables
+ var PROCESSOR_ID_KEY = 'component.id',
+ ACTIVE_THREAD_COUNT_KEY = 'status.aggregateSnapshot.activeThreadCount',
+ RUN_STATUS_KEY = 'status.aggregateSnapshot.runStatus',
+ BULLETINS_KEY = 'bulletins';
+
+ var isUndefined = function (obj) {
+ return typeof obj === 'undefined';
+ };
+
+ var isNull = function (obj) {
+ return obj === null;
+ };
+
+ var isDefinedAndNotNull = function (obj) {
+ return !isUndefined(obj) && !isNull(obj);
+ };
+
+ var getKeyValue = function(obj,key){
+ return key.split('.').reduce(function(o,x){
+ return(typeof o === undefined || o === null)? o : (typeof o[x] == 'function')?o[x]():o[x];
+ }, obj);
+ };
+
+ var methods = {
+
+ /**
+ * Initializes the status bar.
+ */
+ init: function () {
+ // get the combo
+ var bar = $(this).addClass('dialog-status-bar');
+
+ bar.html('<text class="run-status-icon"></text>'+
+ '<span class="dialog-status-bar-state"></span>'+
+ '<span class="dialog-status-bar-threads" count="0"></span>'+
+ '<div class="dialog-status-bar-bulletins fa fa-sticky-note-o" count="0">'+
+ '<div class="dialog-status-bar-bulletins-content"></div>'+
+ '</div>'+
+ '<div class="dialog-status-bar-buttons"></div>');
+ return bar;
+ },
+
+ /**
+ * Shows the status bar.
+ */
+ show: function () {
+ var bar = $(this);
+ if (bar.is(':visible')) {
+ bar.show();
+ }
+ return bar;
+ },
+
+ /**
+ * Hides the status bar.
+ */
+ hide: function () {
+ var bar = $(this);
+ if (bar.is(':visible')) {
+ bar.hide();
+ }
+ return bar;
+ },
+
+
+ /**
+ * Initializes the synchronization process to the canvas element
+ *
+ * @param id - id value of the processor to observe
+ * @param cb - callback to execute when a mutation is detected
+ */
+ observe: function(id,cb) {
+ var bar = $(this);
+ var g = document.querySelector('g[id="id-'+id+'"]');
+
+ //perform the initial set
+ bar.statusbar('set',id);
+
+ //create and store an observer
+ bar.data('observer',new MutationObserver(function(mutations){
+ bar.statusbar('set',id);
+ if(typeof cb == 'function'){
+ cb();
+ }
+ }));
+
+ //initialize the observer
+ bar.data('observer').observe(g,{attributes:true,childList:true,subtree:true});
+
+ return bar.data('observer');
+ },
+
+ /**
+ * Terminates the synchronization process
+ */
+ disconnect: function () {
+ var bar = $(this);
+ if(isDefinedAndNotNull(bar.data('observer'))){
+ bar.data('observer').disconnect();
+ bar.data('observer',null);
+ }
+ if(isDefinedAndNotNull(bar.data('buttonModel'))){
+ bar.data('buttonModel', []);
+ bar.statusbar('refreshButtons',[]);
+ }
+ },
+
+ /**
+ * Refreshes the buttons with the existing button model.
+ */
+ refreshButtons: function () {
+ var bar = $(this);
+ bar.statusbar('buttons',bar.data('buttonModel'));
+ return bar;
+ },
+
+ /**
+ * Hides all buttons
+ */
+ hideButtons: function () {
+ var bar = $(this);
+ bar.find('.dialog-status-bar-buttons').hide();
+ return bar;
+ },
+
+ /**
+ * Shows all buttons.
+ */
+ showButtons: function () {
+ var bar = $(this);
+ bar.find('.dialog-status-bar-buttons').show(250);
+ return bar;
+ },
+
+ /**
+ * Sets/Retrieves the buttons on the status bar
+ *
+ * @param [{object}] button objects to apply
+ */
+ buttons : function(buttons){
+ var bar = $(this),
+ buttonWrapper = bar.find('.dialog-status-bar-buttons');
+
+ if(isDefinedAndNotNull(buttons)){
+ //remove any existing buttons
+ buttonWrapper.children().remove();
+
+ //add in new buttons
+ $.each(buttons, function (i, buttonConfig) {
+ var isDisabled = function () {
+ return typeof buttonConfig.disabled === 'function' && buttonConfig.disabled.call() === true;
+ };
+
+ // create the button
+ var button = $('<div class="button"></div>');
+ if(buttonConfig.buttonText){
+ button.append($('<span></span>').text(buttonConfig.buttonText));
+ }
+ else if(buttonConfig.buttonHtml){
+ button.html(buttonConfig.buttonHtml);
+ }
+
+ // add the class if specified
+ if (isDefinedAndNotNull(buttonConfig.clazz)) {
+ button.addClass(buttonConfig.clazz);
+ }
+
+ // set the color if specified
+ if (isDefinedAndNotNull(buttonConfig.color)) {
+ button.css({
+ 'background': buttonConfig.color.base,
+ 'color': buttonConfig.color.text
+ });
+ }
+
+ // check if the button should be disabled
+ if (isDisabled()) {
+ button.addClass('disabled-button');
+ } else {
+ // enable custom hover if specified
+ if (isDefinedAndNotNull(buttonConfig.color)) {
+ button.hover(function () {
+ $(this).css("background-color", buttonConfig.color.hover);
+ }, function () {
+ $(this).css("background-color", buttonConfig.color.base);
+ });
+ }
+
+ button.click(function () {
+ var handler = $(this).data('handler');
+ if (isDefinedAndNotNull(handler) && typeof handler.click === 'function') {
+ handler.click.call(bar);
+ }
+ });
+ }
+
+ // add the button to the wrapper
+ button.data('handler', buttonConfig.handler).appendTo(buttonWrapper);
+ });
+
+ // store the button model to refresh later
+ bar.data('buttonModel', buttons);
+ }
+
+ //return the buttons as an array object
+ buttons = [];
+ $.each(buttonWrapper.find('.button'),function(i, button){
+ buttons.push($(button));
+ });
+ return buttons;
+ },
+
+ /**
+ * Set the status bar display values
+ *
+ * @param id - processor id to evaluate
+ */
+ set : function(id) {
+ var bar = $(this),
+ obj = d3.select('#id-' + id).datum(),
+ bulletinList = $("<ul></ul>"),
+ runStatus = getKeyValue(obj,RUN_STATUS_KEY),
+ activeThreadCount = getKeyValue(obj,ACTIVE_THREAD_COUNT_KEY),
+ bulletins = getKeyValue(obj,BULLETINS_KEY);
+
+ //set the values
+ if(isDefinedAndNotNull(runStatus) &&
+ isDefinedAndNotNull(activeThreadCount) &&
+ isDefinedAndNotNull(bulletins) &&
+ Array.isArray(bulletins)) {
+
+ bar.attr('state',runStatus.toUpperCase());
+ bar.find('.dialog-status-bar-state').text(runStatus);
+ bar.find('.dialog-status-bar-threads').attr('count',activeThreadCount);
+ bar.find('.dialog-status-bar-threads').attr('title',activeThreadCount+' active threads');
+ bar.find('.dialog-status-bar-threads').text('('+activeThreadCount+')');
+ $.each(bulletins, function(i,item){
+ if(item.canRead){
+ bulletinList.append($('<li>'+item.bulletin.timestamp+' '+item.bulletin.level+'<br/>'+item.bulletin.message+'<br> </li>'));
+ }
+ });
+ var bulletinCount = bulletinList.find('li').length;
+ bar.find('.dialog-status-bar-bulletins-content').html((bulletinCount > 0)?bulletinList:'');
+ bar.find('.dialog-status-bar-bulletins').attr('count',bulletinCount);
+
+ //update the button state
+ bar.statusbar('refreshButtons');
+ }
+ return bar;
+ }
+ };
+
+ $.fn.statusbar = function (method) {
+ if (methods[method]) {
+ return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
+ } else {
+ return methods.init.apply(this, arguments);
+ }
+ };
+
+})(jQuery);
\ No newline at end of file
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 238ff05..ed45d12 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
@@ -701,8 +701,9 @@
* Stops the components in the specified selection.
*
* @argument {selection} selection The selection
+ * @argument {cb} callback The function to call when request is processed
*/
- stop: function (selection) {
+ stop: function (selection,cb) {
if (selection.empty()) {
// build the entity
var entity = {
@@ -753,18 +754,41 @@
if (stopRequests.length > 0) {
$.when.apply(window, stopRequests).always(function () {
nfNgBridge.digest();
+ if(typeof cb == 'function'){
+ cb();
+ }
});
+ } else if(typeof cb == 'function'){
+ cb();
}
}
}
},
/**
+ * Stops the component and displays the processor configuration dialog
+ *
+ * @param {selection} selection The selection
+ * @param {cb} callback The function to call when complete
+ */
+ stopAndConfigure: function (selection,cb) {
+ if(selection.size() === 1 &&
+ nfCanvasUtils.isProcessor(selection) &&
+ nfCanvasUtils.canModify(selection)){
+
+ nfActions.stop(selection,function(){
+ nfProcessorConfiguration.showConfiguration(selection,cb);
+ });
+ }
+ },
+
+ /**
* Terminates active threads for the selected component.
*
- * @param {selection} selection
+ * @param {selection} selection
+ * @param {cb} callback The function to call when complete
*/
- terminate: function (selection) {
+ terminate: function (selection,cb) {
if (selection.size() === 1 && nfCanvasUtils.isProcessor(selection)) {
var selectionData = selection.datum();
@@ -774,6 +798,9 @@
dataType: 'json'
}).done(function (response) {
nfProcessor.set(response);
+ if(typeof cb == 'function'){
+ cb();
+ }
}).fail(nfErrorHandler.handleAjaxError);
}
},
@@ -831,14 +858,15 @@
* Shows the configuration dialog for the specified selection.
*
* @param {selection} selection Selection of the component to be configured
+ * @param {fn} callback Callback
*/
- showConfiguration: function (selection) {
+ showConfiguration: function (selection,cb) {
if (selection.empty()) {
nfProcessGroupConfiguration.showConfiguration(nfCanvasUtils.getGroupId());
} else if (selection.size() === 1) {
var selectionData = selection.datum();
if (nfCanvasUtils.isProcessor(selection)) {
- nfProcessorConfiguration.showConfiguration(selection);
+ nfProcessorConfiguration.showConfiguration(selection,cb);
} else if (nfCanvasUtils.isLabel(selection)) {
nfLabelConfiguration.showConfiguration(selection);
} else if (nfCanvasUtils.isProcessGroup(selection)) {
@@ -871,7 +899,11 @@
} else if (selection.size() === 1) {
var selectionData = selection.datum();
if (nfCanvasUtils.isProcessor(selection)) {
- nfProcessorDetails.showDetails(nfCanvasUtils.getGroupId(), selectionData.id);
+ if(!nfCanvasUtils.isStoppable(selection) && nfCanvasUtils.canModify(selection)){
+ nfProcessorConfiguration.showConfiguration(selection);
+ } else {
+ nfProcessorDetails.showDetails(nfCanvasUtils.getGroupId(), selectionData.id);
+ }
} else if (nfCanvasUtils.isProcessGroup(selection)) {
nfProcessGroupConfiguration.showConfiguration(selectionData.id);
} else if (nfCanvasUtils.isRemoteProcessGroup(selection)) {
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 14aaf71..ac0bb47 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
@@ -365,14 +365,22 @@
nfControllerService.init(nfControllerServices, nfReportingTask);
nfReportingTask.init(nfSettings);
nfPolicyManagement.init();
- nfProcessorConfiguration.init();
+ nfProcessorConfiguration.init({
+ supportsStatusBar : true,
+ nfActions : nfActions
+ });
// initialize the PG config and invert control of the controllerServices
nfProcessGroupConfiguration.init(nfControllerServices);
nfRemoteProcessGroupConfiguration.init();
nfRemoteProcessGroupPorts.init();
nfPortConfiguration.init();
nfLabelConfiguration.init();
- nfProcessorDetails.init(true);
+ nfProcessorDetails.init({
+ supportsGoTo : true,
+ supportsStatusBar : true,
+ nfCanvasUtils : nfCanvasUtils,
+ nfActions : nfActions
+ });
nfPortDetails.init();
nfConnectionDetails.init();
nfRemoteProcessGroupDetails.init();
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 6d908d8..b90c9b3 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
@@ -575,6 +575,16 @@
},
/**
+ * Gets the selection object of the id passed.
+ *
+ * @param {id} The uuid of the component to retrieve
+ * @returns {selection} The selection object of the component id passed
+ */
+ getSelectionById: function(id){
+ return d3.select('#id-' + id);
+ },
+
+ /**
* Gets the coordinates neccessary to center a bounding box on the screen.
*
* @param {type} boundingBox
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 77984f6..9d58c47 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
@@ -61,7 +61,15 @@
* @param {selection} selection The selection of currently selected components
*/
var isConfigurable = function (selection) {
- return nfCanvasUtils.isConfigurable(selection);
+ if(selection.size() == 1 &&
+ nfCanvasUtils.isProcessor(selection) &&
+ nfCanvasUtils.canModify(selection) &&
+ (nfCanvasUtils.isConfigurable(selection) ||
+ canTerminate(selection))){
+ return true;
+ } else {
+ return nfCanvasUtils.isConfigurable(selection);
+ }
};
/**
@@ -79,7 +87,13 @@
* @param {selection} selection The selection of currently selected components
*/
var hasDetails = function (selection) {
- return nfCanvasUtils.hasDetails(selection);
+ if(selection.size() == 1 &&
+ nfCanvasUtils.isProcessor(selection) &&
+ nfCanvasUtils.canModify(selection)){
+ return !isConfigurable(selection);
+ } else {
+ return nfCanvasUtils.hasDetails(selection);
+ }
};
/**
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-processor-configuration.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-processor-configuration.js
index 54ca51f..baad61e 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-processor-configuration.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-processor-configuration.js
@@ -68,9 +68,19 @@
}(this, function ($, nfErrorHandler, nfCommon, nfDialog, nfStorage, nfClient, nfCanvasUtils, nfNgBridge, nfProcessor, nfClusterSummary, nfCustomUi, nfUniversalCapture, nfConnection) {
'use strict';
+ /**
+ * Configuration option variable for the nfProcessorDetails dialog
+ */
+ var config;
+
// possible values for a processor's run duration (in millis)
var RUN_DURATION_VALUES = [0, 25, 50, 100, 250, 500, 1000, 2000];
+ // key paths to the status objects
+ var ACTIVE_THREAD_COUNT_KEY = 'status.aggregateSnapshot.activeThreadCount',
+ RUN_STATUS_KEY = 'status.aggregateSnapshot.runStatus',
+ BULLETINS_KEY = 'bulletins';
+
/**
* Gets the available scheduling strategies based on the specified processor.
*
@@ -492,8 +502,13 @@
return {
/**
* Initializes the processor properties tab.
+ *
+ * @param {options} The configuration options object for the dialog
*/
- init: function () {
+ init: function (options) {
+ //set the configuration options
+ config = options;
+
// initialize the properties tabs
$('#processor-configuration-tabs').tabbs({
tabStyle: 'tab',
@@ -546,6 +561,11 @@
// removed the cached processor details
$('#processor-configuration').removeData('processorDetails');
+
+ //stop any synchronization
+ if(config.supportsStatusBar){
+ $('#processor-configuration-status-bar').statusbar('disconnect');
+ }
},
open: function () {
nfCommon.toggleScrollable($('#' + this.find('.tab-container').attr('id') + '-content').get(0));
@@ -553,6 +573,11 @@
}
});
+ //if the status bar is supported, initialize it.
+ if(config.supportsStatusBar){
+ $('#processor-configuration-status-bar').statusbar();
+ }
+
// initialize the bulletin combo
$('#bulletin-level-combo').combo({
options: [{
@@ -612,8 +637,9 @@
* Shows the configuration dialog for the specified processor.
*
* @argument {selection} selection The selection
+ * @argument {cb} callback The callback function to execute after the dialog is displayed
*/
- showConfiguration: function (selection) {
+ showConfiguration: function (selection, cb) {
if (nfCanvasUtils.isProcessor(selection)) {
var selectionData = selection.datum();
@@ -773,6 +799,9 @@
hover: '#004849',
text: '#ffffff'
},
+ disabled : function() {
+ return !nfCanvasUtils.supportsModification(selection);
+ },
handler: {
click: function () {
// close all fields currently being edited
@@ -792,19 +821,19 @@
}
}
},
- {
- buttonText: 'Cancel',
- color: {
- base: '#E3E8EB',
- hover: '#C7D2D7',
- text: '#004849'
- },
- handler: {
- click: function () {
- $('#processor-configuration').modal('hide');
- }
+ {
+ buttonText: 'Cancel',
+ color: {
+ base: '#E3E8EB',
+ hover: '#C7D2D7',
+ text: '#004849'
+ },
+ handler: {
+ click: function () {
+ $('#processor-configuration').modal('hide');
}
- }];
+ }
+ }];
// determine if we should show the advanced button
if (nfCommon.isDefinedAndNotNull(processor.config.customUiUrl) && processor.config.customUiUrl !== '') {
@@ -858,6 +887,55 @@
});
}
+ //Synchronize the current component canvas attributes in the status bar
+ if(config.supportsStatusBar){
+
+ //initialize the canvas synchronization
+ $("#processor-configuration-status-bar").statusbar('observe',processor.id, function(){
+ $('#processor-configuration').modal('refreshButtons');
+ });
+
+ //if there are active threads, add the terminate button to the status bar
+ if(nfCommon.isDefinedAndNotNull(config.nfActions) &&
+ nfCommon.getKeyValue(processorResponse,ACTIVE_THREAD_COUNT_KEY) != 0){
+
+ $("#processor-configuration-status-bar").statusbar('buttons',[{
+ buttonText: 'Terminate',
+ clazz: 'fa fa-hourglass-end button-icon',
+ color: {
+ hover: '#C7D2D7',
+ base: 'transparent',
+ text: '#004849'
+ },
+ disabled : function() {
+ return nfCanvasUtils.supportsModification(selection);
+ },
+ handler: {
+ click: function() {
+ var cb = function(){
+ var p = nfProcessor.get(processor.id);
+ if(nfCommon.getKeyValue(p,ACTIVE_THREAD_COUNT_KEY) != 0){
+ nfDialog.showOkDialog({
+ dialogContent: 'Terminate threads request was processed, but active threads still persist. Please try again later.',
+ headerText: 'Unable to Terminate'
+ });
+ }
+ else {
+ //refresh the dialog
+ $('#processor-configuration-status-bar').statusbar('refreshButtons');
+ $('#processor-configuration').modal('refreshButtons');
+ }
+ $('#processor-configuration-status-bar').statusbar('showButtons');
+ };
+
+ //execute the terminate call
+ $('#processor-configuration-status-bar').statusbar('hideButtons');
+ config.nfActions.terminate(selection,cb);
+ }
+ }
+ }]);
+ }
+ }
// set the button model
$('#processor-configuration').modal('setButtonModel', buttons);
@@ -877,6 +955,17 @@
if (processorRelationships.is(':visible') && processorRelationships.get(0).scrollHeight > Math.round(processorRelationships.innerHeight())) {
processorRelationships.css('border-width', '1px');
}
+
+ // Ensure the properties table has rendered correctly if initially selected
+ if ($('#processor-configuration-tabs').find('.selected-tab').text() === 'Properties' &&
+ $('#processor-properties').find('.slick-viewport').height() == 0) {
+ $('#processor-properties').propertytable('resetTableSize');
+ }
+
+ //execute the callback if one was provided
+ if(typeof cb == 'function'){
+ cb();
+ }
}).fail(nfErrorHandler.handleAjaxError);
}
}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-common.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-common.js
index eaaa63d..7e5a1c0 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-common.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-common.js
@@ -1714,6 +1714,19 @@
*/
throttle: function (func, wait) {
return _.throttle(func, wait);
+ },
+
+ /**
+ * Find the corresponding value of the object key passed
+ *
+ * @param {object} obj The obj to search
+ * @param {string} key The key path to return
+ * @returns {object/literal} The value of the key passed or undefined/null
+ */
+ getKeyValue : function(obj,key){
+ return key.split('.').reduce(function(o,x){
+ return(typeof o === undefined || o === null)? o : (typeof o[x] == 'function')?o[x]():o[x];
+ }, obj);
}
};
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-processor-details.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-processor-details.js
index 30d388f..f38561b 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-processor-details.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-processor-details.js
@@ -51,6 +51,11 @@
'use strict';
/**
+ * Configuration option variable for the nfProcessorDetails dialog
+ */
+ var config;
+
+ /**
* Creates an option for the specified relationship name.
*
* @argument {object} relationship The relationship
@@ -76,8 +81,13 @@
return {
/**
* Initializes the processor details dialog.
+ *
+ * @param {options} The configuration options object for the dialog
*/
- init: function (supportsGoTo) {
+ init: function (options) {
+
+ //set the dialog window configuration options.
+ config = options;
// initialize the properties tabs
$('#processor-details-tabs').tabbs({
@@ -143,6 +153,11 @@
// removed the cached processor details
$('#processor-details').removeData('processorDetails');
$('#processor-details').removeData('processorHistory');
+
+ //stop any synchronization on the status bar
+ if(config.supportsStatusBar){
+ $("#processor-details-status-bar").statusbar('disconnect');
+ }
},
open: function () {
nfCommon.toggleScrollable($('#' + this.find('.tab-container').attr('id') + '-content').get(0));
@@ -150,9 +165,14 @@
}
});
+ //apply the status bar if indicated
+ if(config.supportsStatusBar){
+ $("#processor-details-status-bar").statusbar();
+ }
+
// initialize the properties
$('#read-only-processor-properties').propertytable({
- supportsGoTo: supportsGoTo,
+ supportsGoTo: config.supportsGoTo,
readOnly: true
});
},
@@ -255,6 +275,7 @@
var processor = processorResponse.component;
var historyResponse = historyResult[0];
var history = historyResponse.componentHistory;
+ var selection;
// load the properties
$('#read-only-processor-properties').propertytable('loadProperties', processor.config.properties, processor.config.descriptors, history.propertyHistory);
@@ -296,6 +317,70 @@
});
}
+ //Populate the status bar if the feature is enabled
+ if (config.supportsStatusBar && nfCommon.isDefinedAndNotNull(config.nfCanvasUtils)){
+
+ //initialize the canvas synchronization
+ $("#processor-details-status-bar").statusbar('observe',processor.id);
+
+ //Fetch the component as a selection from the canvas
+ selection = config.nfCanvasUtils.getSelectionById(processor.id);
+
+ //Add the stop & configure button if appropriate
+ if(nfCommon.isDefinedAndNotNull(config.nfActions) &&
+ config.nfCanvasUtils.isProcessor(selection) &&
+ config.nfCanvasUtils.canModify(selection)){
+
+ //Declare a callback handler to perform should ProcessorConfiguration be invoked
+ var cb = function(){
+ var selectedTab = $('#processor-details-tabs').find('.selected-tab').text();
+ $('#processor-configuration-tabs').find('.tab:contains("'+selectedTab+'")').trigger('click');
+ $('#processor-details').modal('hide');
+ $("#processor-details-status-bar").statusbar('showButtons');
+ };
+
+ $("#processor-details-status-bar").statusbar('buttons',[{
+ buttonHtml: '<i class="fa fa-stop stop-configure-icon" aria-hidden="true"></i><span>Stop & Configure</span>',
+ clazz: 'button button-icon auto-width',
+ color: {
+ hover: '#C7D2D7',
+ base: 'transparent',
+ text: '#004849'
+ },
+ disabled : function() {
+ return !config.nfCanvasUtils.isStoppable(selection);
+ },
+ handler: {
+ click: function() {
+ //execute the stop and open the configuration modal
+ $("#processor-details-status-bar").statusbar('hideButtons');
+ config.nfActions.stopAndConfigure(selection,cb);
+ }
+ }
+ },
+ {
+ buttonText: 'Configure',
+ clazz: 'fa fa-cog button-icon',
+ color: {
+ hover: '#C7D2D7',
+ base: 'transparent',
+ text: '#004849'
+ },
+ disabled : function() {
+ return config.nfCanvasUtils.isStoppable(selection);
+ },
+ handler: {
+ click: function() {
+ //execute the stop and open the configuration modal
+ $("#processor-details-status-bar").statusbar('hideButtons');
+ config.nfActions.showConfiguration(selection,cb);
+ }
+ }
+ }]);
+ }
+
+ }
+
// show the dialog
$('#processor-details').modal('setButtonModel', buttons).modal('show');
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/summary/nf-summary-table.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/summary/nf-summary-table.js
index 1838a66..3f2fd1d 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/summary/nf-summary-table.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/summary/nf-summary-table.js
@@ -3041,7 +3041,10 @@
nfStatusHistory.init(configDetails.timeOffset);
// initialize the processor/connection details dialog
- nfProcessorDetails.init(false);
+ nfProcessorDetails.init({
+ supportsGoTo : false,
+ supportsStatusBar : false
+ });
nfConnectionDetails.init();
initSummaryTable(isClustered);