diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/canvas.css b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/canvas.css
index 8159795426..a9de76f303 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/canvas.css
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/canvas.css
@@ -23,6 +23,7 @@
@import url(controller-service.css);
@import url(component-state.css);
@import url(reporting-task.css);
+@import url(parameter-provider.css);
@import url(port-configuration.css);
@import url(port-details.css);
@import url(label-configuration.css);
@@ -34,6 +35,7 @@
@import url(new-port-dialog.css);
@import url(new-controller-service-dialog.css);
@import url(new-reporting-task-dialog.css);
+@import url(new-parameter-provider-dialog.css);
@import url(new-parameter-context-dialog.css);
@import url(graph.css);
@import url(header.css);
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 e28d68088e..2baa79bf27 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
@@ -478,7 +478,9 @@ div.variable-step {
margin-bottom: 2px;
}
-div.parameter-context-step, div.referencing-components-loading {
+div.parameter-context-step,
+div.referencing-components-loading,
+div.fetch-parameters-step {
min-width: 16px;
width: 16px;
height: 16px;
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/new-parameter-provider-dialog.css b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/new-parameter-provider-dialog.css
new file mode 100644
index 0000000000..6dbf19c0bc
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/new-parameter-provider-dialog.css
@@ -0,0 +1,105 @@
+/*
+ * 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.
+ */
+
+/*
+ New parameter provider dialog.
+*/
+
+#new-parameter-provider-dialog {
+ min-height:620px;
+ height: 620px;
+ width: 800px;
+ min-width: 760px;
+}
+
+#parameter-provider-types-container {
+ padding: 0px;
+}
+
+#parameter-provider-bundle-group-combo {
+ margin-right: 2px;
+}
+
+#parameter-provider-description-container {
+ padding: 0px;
+}
+
+#parameter-provider-type-container {
+ padding: 20px 0 5px 0;
+ display: flex;
+}
+
+#parameter-provider-type-name {
+ color: #775351;
+ font-size: 16px;
+ font-weight: 500;
+ overflow: hidden;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+}
+
+#parameter-provider-type-bundle {
+ margin-left: 15px;
+ overflow: hidden;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ font-size: 13px;
+ line-height: 16px;
+ color: #666;
+ letter-spacing: 0.25px;
+ min-width: 0;
+}
+
+#parameter-provider-type-description {
+ height: 80px;
+ font-size: 13px;
+ line-height: 17px;
+ padding-top: 10px;
+}
+
+#parameter-provider-types-table {
+ min-height: 150px;
+ overflow: hidden;
+ height: 70%;
+ width: 100%;
+}
+
+#parameter-provider-types-table-container th {
+ vertical-align: middle;
+}
+
+#parameter-provider-types-table div.slick-viewport {
+ overflow-x: hidden !important;
+}
+
+/*
+ Processor type table filter
+*/
+
+#parameter-provider-type-filter-controls {
+ min-height: 32px;
+ padding: 0px;
+ margin: 0px;
+}
+
+#parameter-provider-type-filter {
+ width: 200px;
+}
+
+#parameter-provider-tag-cloud {
+ margin-top: -2px;
+}
\ 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/parameter-provider.css b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/parameter-provider.css
new file mode 100644
index 0000000000..368ddb433b
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/parameter-provider.css
@@ -0,0 +1,496 @@
+/*
+ * 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.
+ */
+
+/*
+ Parameter provider configuration styles.
+*/
+
+#parameter-provider-configuration {
+ position: absolute;
+ overflow: hidden;
+ width: 800px;
+ height: 450px;
+ font-size: 10px;
+ z-index: 1301;
+ display: none;
+}
+
+#parameter-provider-configuration-advanced {
+ display: none;
+}
+
+#parameter-provider-configuration div.configuration-tab {
+ display: none;
+}
+
+.parameter-provider-editable.setting-field {
+ height: 32px;
+}
+
+#parameter-provider-referencing-components {
+ padding: 2px;
+}
+
+/* parameter-provider settings */
+
+#parameter-provider-name {
+ width: 250px;
+ float: left;
+}
+
+#parameter-provider-bundle {
+ overflow: hidden;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+}
+
+/*
+ Comments
+*/
+
+#parameter-provider-comments {
+ height: 100%;
+}
+
+#read-only-parameter-provider-comments {
+ height: 100%;
+ white-space: pre-wrap;
+}
+
+/*
+ Fetch parameters dialog
+*/
+
+#fetch-parameters-dialog {
+ position: absolute;
+ overflow: hidden;
+ min-width: 1048px;
+ height: 62%;
+ font-size: 10px;
+ z-index: 1301;
+ display: none;
+}
+
+#fetch-parameters-dialog .dialog-content {
+ bottom: 48px;
+}
+
+#fetch-parameters-dialog div.create-parameter-context-label {
+ display: inline-block;
+ line-height: normal;
+}
+
+#fetch-parameters-dialog .dialog-content div.settings-left {
+ float: left;
+ width: 33%;
+}
+
+#fetch-parameters-dialog .dialog-content div.settings-center {
+ float: left;
+ width: 33%;
+}
+
+#fetch-parameters-dialog .dialog-content div.settings-right {
+ float: left;
+ width: 30%;
+ height: 100%;
+ position: absolute;
+ left: calc(72% - 20px);
+}
+
+#parameter-groups-table {
+ position: relative;
+ height: 300px;
+}
+
+#fetch-parameters-referencing-components {
+ border: 0 solid #CCCCCC;
+ overflow: auto;
+ padding: 2px;
+}
+
+#fetch-parameters-update-steps li {
+ width: 300px;
+ margin-bottom: 2px;
+}
+
+#fetched-parameters-listing-container {
+ position: relative;
+ overflow-x: auto;
+ border: 0 solid #CCCCCC;
+ padding: 2px;
+ min-height: 100px;
+ max-height: 343px;
+ min-width: 150px;
+ max-width: 326px;
+}
+
+#fetched-parameters-listing li,
+#fetched-parameters-listing span {
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ overflow: hidden;
+}
+
+ol#fetched-parameters-listing ul {
+ padding-bottom: 4px;
+}
+
+ul.fetched-parameters {
+ padding: 0 0 2px 0;
+ list-style-type: disc;
+}
+
+div.referencing-component-block {
+ margin-bottom: 6px;
+}
+
+span.referencing-component-title {
+ margin-left: 5px;
+ font-weight: bold
+}
+
+span.referencing-component-count {
+ margin-left: 5px;
+ color: #aaa;
+}
+
+ul.referencing-component-listing {
+ margin-left: 20px;
+ margin-bottom: 6px;
+}
+
+ul.referencing-component-listing li {
+ margin-bottom: 6px;
+ white-space: nowrap;
+}
+
+div.referencing-component-state {
+ width: 13px;
+}
+
+div.referencing-component-state.disabled:before {
+ content: '\e802';
+ font-family: flowfont;
+}
+
+div.referencing-component-state.enabled:before {
+ content: '\f0e7';
+ font-family: FontAwesome;
+}
+
+div.referencing-component-bulletins {
+ float: left;
+ margin-left: 5px;
+ width: 12px;
+ height: 12px;
+ background-color: transparent;
+ display: none;
+}
+
+div.referencing-component-bulletins:before {
+ font-family: FontAwesome;
+ content: "\f24a";
+ font-size: 16px;
+ color: #004849;
+}
+
+div.service.expansion-button {
+ float: left;
+ margin-right: 4px;
+ width: 10px;
+ height: 10px;
+}
+
+span.referencing-component-active-thread-count {
+ margin-left: 5px;
+ float: left;
+}
+
+span.referencing-component-name {
+ margin-left: 5px;
+ margin-right: 5px;
+}
+
+span.referencing-component-type {
+ color: #aaa;
+ font-style: italic;
+}
+
+div.referencing-component-references {
+ margin-left: 2px;
+ margin-top: 0;
+ clear: left;
+}
+
+.fetch-parameters-referencing-components-template {
+ padding-left: 14px;
+}
+
+div.fetch-parameters-canceling {
+ position: absolute;
+ bottom: 10px;
+ right: 8px;
+}
+
+#fetch-parameters-name {
+ float: left;
+ max-width: 280px;
+ text-overflow: ellipsis;
+}
+
+#fetch-parameters-bulletins {
+ float: left;
+ margin-left: 5px;
+ width: 12px;
+ height: 12px;
+ background-color: transparent;
+ display: none;
+}
+
+#fetch-parameters-referencing-components {
+ border: 0 solid #CCCCCC;
+ padding: 2px;
+ overflow: auto;
+ white-space: nowrap;
+}
+
+div.fetch-parameters-referencing-components {
+ width: 16px;
+ height: 16px;
+ background-color: transparent;
+ float: right;
+}
+
+#fetch-parameters-progress {
+ margin-top: 2px;
+}
+
+#fetch-parameters-progress li {
+ line-height: 16px;
+}
+
+#affected-referencing-components-container,
+#fetch-parameter-referencing-components-container {
+ position: absolute;
+ bottom: 10px;
+ top: 108px;
+ width: calc(100% - 6px);
+ overflow: auto;
+ border: 0 solid #CCCCCC;
+ padding: 2px;
+}
+
+#affected-referencing-components-container div.referencing-component-references {
+ margin: 0;
+}
+
+.affected-referencing-components-template {
+ position: relative;
+ left: 15px;
+ width: calc(100% - 15px);
+}
+
+span.parameter-provider-referencing-component-name {
+ margin-left: 5px;
+ max-width: calc(100% - 30px);
+}
+
+#checkbox-container {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+}
+
+/*
+ Slickgrid selectable parameters table
+*/
+#selectable-parameters-table {
+ position: absolute;
+ height: 267px;
+ width: 332px;
+}
+
+#selectable-parameters-table .slick-cell-checkboxsel {
+ padding: 1px 2px 5px 4px;
+}
+
+#selectable-parameters-table .slick-cell-checkboxsel.selected {
+ padding: 0px 2px 6px 4px;
+}
+
+#selectable-parameters-table .slick-column-name input {
+ margin: 5px 3px 3px 4px;
+}
+
+#selectable-parameters-table .slick-pane-left .slick-viewport {
+ overflow-x: hidden;
+}
+
+#selectable-parameters-table input[type="checkbox"] {
+ margin-top: 2px;
+ width: 0;
+}
+
+#selectable-parameters-table input[type="checkbox"]:focus {
+ box-shadow: none;
+ border: none;
+}
+
+#selectable-parameters-table .slick-column-name input[type="checkbox"] {
+ margin-top: 5px;
+}
+
+#selectable-parameters-table .slick-column-name input[checked="checked"]:before {
+ margin-top: 2px;
+}
+
+#selectable-parameters-table input[type="checkbox"]:before {
+ content: url(../images/inputCheckbox.png);
+ cursor: pointer;
+ clip-path: polygon(0% -16%, 50% -16%, 50% 104%, 0% 104%);
+ position: absolute;
+ margin-left: 1px;
+ margin-top: 3px;
+}
+
+#selectable-parameters-table input[checked="checked"]:before {
+ content: url(../images/inputCheckbox.png);
+ cursor: pointer;
+ clip-path: polygon(50% -16%, 100% -16%, 100% 116%, 50% 116%);
+ margin-left: -11px;
+ margin-top: 3px;
+}
+
+#selectable-parameters-table input[type="checkbox"].disabled:before {
+ content: url(../images/inputCheckbox.png);
+ opacity: .5;
+ cursor: not-allowed;
+ clip-path: polygon(0% -16%, 50% -16%, 50% 104%, 0% 104%);
+ position: absolute;
+ margin-left: 1px;
+ margin-top: 3px;
+}
+
+#selectable-parameters-table input[checked="checked"].disabled:before {
+ content: url(../images/inputCheckbox.png);
+ opacity: .5;
+ cursor: not-allowed;
+ clip-path: polygon(50% -16%, 100% -16%, 100% 116%, 50% 116%);
+ margin-left: -11px;
+ margin-top: 3px;
+}
+
+#parameter-groups-table .slick-pane-top .slick-viewport-top .grid-canvas-top,
+#selectable-parameters-table .slick-pane-top .slick-viewport .grid-canvas-top {
+ width: 100% !important;
+}
+
+#selectable-parameters-table .slick-pane-top .slick-viewport-top .grid-canvas-top .slick-cell.l1 {
+ padding-top: 1px;
+}
+
+#selectable-parameters-table .slick-pane-top .slick-viewport-top .slick-cell.l1:not(.selected) .table-cell {
+ margin-top: 5px;
+}
+
+#fetched-parameters-listing .slick-cell-checkboxsel {
+ background: #f0f0f0;
+ border-right-color: silver;
+ border-right-style: solid;
+}
+
+.slick-columnpicker {
+ border: 1px solid #718BB7;
+ background: #f0f0f0;
+ padding: 6px;
+ -moz-box-shadow: 2px 2px 2px silver;
+ -webkit-box-shadow: 2px 2px 2px silver;
+ box-shadow: 2px 2px 2px silver;
+ min-width: 100px;
+ cursor: default;
+}
+
+.slick-columnpicker li {
+ list-style: none;
+ margin: 0;
+ padding: 0;
+ background: none;
+}
+
+.slick-columnpicker input {
+ margin: 4px;
+}
+
+.slick-columnpicker li a {
+ display: block;
+ padding: 4px;
+ font-weight: bold;
+}
+
+.slick-columnpicker li a:hover {
+ background: white;
+}
+
+#selectable-parameters-buttons {
+ position: relative;
+ padding-bottom: 4px;
+}
+
+.selectable-parameters-buttons {
+ line-height: 30px;
+ border: 1px solid #CCDADB;
+ background-color: rgba(249,250,251,1);
+ color: #004849;
+ padding: 0 7px;
+ float: left;
+ width: inherit;
+ margin-right: 8px;
+ display: flex;
+ align-items: center;
+ flex-direction: row;
+}
+
+.selectable-parameters-buttons span {
+ font-size: 12px;
+ text-transform: uppercase;
+}
+
+.selectable-parameters-buttons .fa {
+ font-size: 14px;
+ margin-left: -2px;
+ margin-right: 4px;
+}
+
+button.selectable-parameters-buttons:hover {
+ border: 1px solid #004849;
+}
+
+#create-parameter-context-container {
+ line-height: 12px;
+}
+
+.fetch-parameters-dialog-message {
+ position: absolute;
+ top: 537px;
+ left: 20px;
+ font-size: 13px;
+ line-height: normal;
+ color: #775351;
+ max-width: calc(100% - 230px);
+ z-index: 999;
+}
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
index c13f7c025d..ddff90653f 100644
--- 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
@@ -25,11 +25,12 @@
height : 32px;
}
-.dialog-status-bar[state] + .dialog-content {
+.dialog-status-bar[state] + .dialog-content,
+.dialog-status-bar[alerts] + .dialog-content {
top: 104px;
}
-.dialog-status-bar:not([state]),
+.dialog-status-bar:not([state]):not([alerts]),
.dialog-status-bar:not([state]) text.run-status-icon,
.dialog-status-bar-bulletins-content,
.dialog-status-bar-bulletins[count="0"],
@@ -123,11 +124,12 @@
float : right;
margin-left : 22px;
margin-top : 5px;
- background-color : rgba(36,36,36,0.75);
- font-family: Arial;
+ background-color: rgba(0, 0, 0, 0.80) !important;
+ box-shadow: 0 2px 5px rgba(0, 0, 0, 0.25);
+ font-family: Roboto;
font-weight : bold;
- font-size : 12px;
- padding : 10px 10px 10px 20px;
+ font-size : 13px;
+ padding : 10px;
width : auto;
max-width : 490px;
}
@@ -138,4 +140,4 @@
.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
index c16e314271..c7c9afa745 100644
--- 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
@@ -27,8 +27,7 @@
// 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';
+ RUN_STATUS_KEY = 'status.aggregateSnapshot.runStatus'
var isUndefined = function (obj) {
return typeof obj === 'undefined';
@@ -52,18 +51,28 @@
/**
* Initializes the status bar.
+ *
+ * @param type - the type of component or service for the status bus
*/
- init: function () {
+ init: function (type) {
+
// get the combo
var bar = $(this).addClass('dialog-status-bar');
- bar.html('
'+
- '
'+
- '
'+
- '
'+
- '
');
+ if (type === 'processor') {
+ bar.html('
'+
+ '
'+
+ '
'+
+ '
'+
+ '
');
+ } else { // parameter provider
+ bar.html('
');
+ }
+
return bar;
},
@@ -93,28 +102,36 @@
/**
* Initializes the synchronization process to the canvas element
*
- * @param id - id value of the processor to observe
+ * @param data - object of type or service to observe
* @param cb - callback to execute when a mutation is detected
*/
- observe: function(id,cb) {
+ observe: function(data,cb) {
var bar = $(this);
- var g = document.querySelector('g[id="id-'+id+'"]');
- //perform the initial set
- bar.statusbar('set',id);
+ if (data.processor) {
+ // id value of the processor to observe
+ var id = data.processor;
+ var g = document.querySelector('g[id="id-'+id+'"]');
- //create and store an observer
- bar.data('observer',new MutationObserver(function(mutations){
- bar.statusbar('set',id);
- if(typeof cb == 'function'){
- cb();
- }
- }));
+ //perform the initial set
+ bar.statusbar('set', data);
- //initialize the observer
- bar.data('observer').observe(g,{attributes:true,childList:true,subtree:true});
+ //create and store an observer
+ bar.data('observer',new MutationObserver(function(mutations){
+ bar.statusbar('set',data);
+ if(typeof cb == 'function'){
+ cb();
+ }
+ }));
- return bar.data('observer');
+ //initialize the observer
+ bar.data('observer').observe(g,{attributes:true,childList:true,subtree:true});
+
+ return bar.data('observer');
+ } else { // parameter provider bulletins
+ //perform the initial set
+ return bar.statusbar('set', data);
+ }
},
/**
@@ -240,38 +257,48 @@
/**
* Set the status bar display values
*
- * @param id - processor id to evaluate
+ * @param data - object of type or service to set
*/
- set : function(id) {
+ set : function(data) {
var bar = $(this),
- obj = d3.select('#id-' + id).datum(),
- bulletinList = $("
"),
- runStatus = getKeyValue(obj,RUN_STATUS_KEY),
- activeThreadCount = getKeyValue(obj,ACTIVE_THREAD_COUNT_KEY),
- bulletins = getKeyValue(obj,BULLETINS_KEY);
+ processorId,
+ obj,
+ runStatus,
+ activeThreadCount,
+ bulletins;
- //set the values
- if(isDefinedAndNotNull(runStatus) &&
- isDefinedAndNotNull(activeThreadCount) &&
- isDefinedAndNotNull(bulletins) &&
- Array.isArray(bulletins)) {
+ if (data.processor) {
+ processorId = data.processor;
+ obj = d3.select('#id-' + processorId).datum();
+ runStatus = getKeyValue(obj,RUN_STATUS_KEY);
+ activeThreadCount = getKeyValue(obj,ACTIVE_THREAD_COUNT_KEY);
+ bulletins = data.bulletins;
+ } else if (data.provider) {
+ bulletins = data.provider;
+ }
+ // set the values
+ if (isDefinedAndNotNull(runStatus) && isDefinedAndNotNull(activeThreadCount)) {
bar.attr('state',runStatus.toUpperCase());
+ bar.attr('alerts', 'true');
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($('
'+item.bulletin.timestamp+' '+item.bulletin.level+' '+item.bulletin.message+' '));
- }
- });
- var bulletinCount = bulletinList.find('li').length;
- bar.find('.dialog-status-bar-bulletins-content').html((bulletinCount > 0)?bulletinList:'');
+ }
+
+ // set the bulletins
+ if (isDefinedAndNotNull(bulletins)) {
+ var bulletinCount = bulletins.find('li').length;
+ bar.find('.dialog-status-bar-bulletins-content').html((bulletinCount > 0)?bulletins:'');
bar.find('.dialog-status-bar-bulletins').attr('count',bulletinCount);
- //update the button state
- bar.statusbar('refreshButtons');
+ if (data.processor) {
+ // update the button state
+ bar.statusbar('refreshButtons');
+ } else {
+ bar.attr('alerts', 'true');
+ }
}
return bar;
}
@@ -285,4 +312,4 @@
}
};
-})(jQuery);
\ No newline at end of file
+})(jQuery);
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 e51f3634a7..530893367d 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
@@ -49,6 +49,7 @@
'nf.ConnectionConfiguration',
'nf.ControllerService',
'nf.ReportingTask',
+ 'nf.ParameterProvider',
'nf.PolicyManagement',
'nf.ProcessorConfiguration',
'nf.ProcessGroupConfiguration',
@@ -84,8 +85,8 @@
'nf.ng.Canvas.OperateCtrl',
'nf.ng.BreadcrumbsDirective',
'nf.ng.DraggableDirective'],
- function ($, angular, nfCommon, nfCanvasUtils, nfErrorHandler, nfClient, nfDialog, nfStorage, nfCanvas, nfGraph, nfContextMenu, nfQuickSelect, nfShell, nfParameterContexts, nfSettings, nfActions, nfSnippet, nfQueueListing, nfVerify, nfVariableRegistry, nfComponentState, nfFlowVersion, nfComponentVersion, nfDraggable, nfConnectable, nfStatusHistory, nfBirdseye, nfConnectionConfiguration, nfControllerService, nfReportingTask, nfPolicyManagement, nfProcessorConfiguration, nfProcessGroupConfiguration, nfControllerServices, nfRemoteProcessGroupConfiguration, nfRemoteProcessGroupPorts, nfPortConfiguration, nfLabelConfiguration, nfProcessorDetails, nfPortDetails, nfConnectionDetails, nfRemoteProcessGroupDetails, nfGoto, nfNgBridge, appCtrl, appConfig, serviceProvider, breadcrumbsCtrl, headerCtrl, flowStatusCtrl, globalMenuCtrl, toolboxCtrl, processorComponent, inputPortComponent, outputPortComponent, processGroupComponent, remoteProcessGroupComponent, funnelComponent, templateComponent, labelComponent, graphControlsCtrl, navigateCtrl, operateCtrl, breadcrumbsDirective, draggableDirective) {
- return factory($, angular, nfCommon, nfCanvasUtils, nfErrorHandler, nfClient, nfDialog, nfStorage, nfCanvas, nfGraph, nfContextMenu, nfQuickSelect, nfShell, nfParameterContexts, nfSettings, nfActions, nfSnippet, nfQueueListing, nfVerify, nfVariableRegistry, nfComponentState, nfFlowVersion, nfComponentVersion, nfDraggable, nfConnectable, nfStatusHistory, nfBirdseye, nfConnectionConfiguration, nfControllerService, nfReportingTask, nfPolicyManagement, nfProcessorConfiguration, nfProcessGroupConfiguration, nfControllerServices, nfRemoteProcessGroupConfiguration, nfRemoteProcessGroupPorts, nfPortConfiguration, nfLabelConfiguration, nfProcessorDetails, nfPortDetails, nfConnectionDetails, nfRemoteProcessGroupDetails, nfGoto, nfNgBridge, appCtrl, appConfig, serviceProvider, breadcrumbsCtrl, headerCtrl, flowStatusCtrl, globalMenuCtrl, toolboxCtrl, processorComponent, inputPortComponent, outputPortComponent, processGroupComponent, remoteProcessGroupComponent, funnelComponent, templateComponent, labelComponent, graphControlsCtrl, navigateCtrl, operateCtrl, breadcrumbsDirective, draggableDirective);
+ function ($, angular, nfCommon, nfCanvasUtils, nfErrorHandler, nfClient, nfDialog, nfStorage, nfCanvas, nfGraph, nfContextMenu, nfQuickSelect, nfShell, nfParameterContexts, nfSettings, nfActions, nfSnippet, nfQueueListing, nfVerify, nfVariableRegistry, nfComponentState, nfFlowVersion, nfComponentVersion, nfDraggable, nfConnectable, nfStatusHistory, nfBirdseye, nfConnectionConfiguration, nfControllerService, nfReportingTask, nfParameterProvider, nfPolicyManagement, nfProcessorConfiguration, nfProcessGroupConfiguration, nfControllerServices, nfRemoteProcessGroupConfiguration, nfRemoteProcessGroupPorts, nfPortConfiguration, nfLabelConfiguration, nfProcessorDetails, nfPortDetails, nfConnectionDetails, nfRemoteProcessGroupDetails, nfGoto, nfNgBridge, appCtrl, appConfig, serviceProvider, breadcrumbsCtrl, headerCtrl, flowStatusCtrl, globalMenuCtrl, toolboxCtrl, processorComponent, inputPortComponent, outputPortComponent, processGroupComponent, remoteProcessGroupComponent, funnelComponent, templateComponent, labelComponent, graphControlsCtrl, navigateCtrl, operateCtrl, breadcrumbsDirective, draggableDirective) {
+ return factory($, angular, nfCommon, nfCanvasUtils, nfErrorHandler, nfClient, nfDialog, nfStorage, nfCanvas, nfGraph, nfContextMenu, nfQuickSelect, nfShell, nfParameterContexts, nfSettings, nfActions, nfSnippet, nfQueueListing, nfVerify, nfVariableRegistry, nfComponentState, nfFlowVersion, nfComponentVersion, nfDraggable, nfConnectable, nfStatusHistory, nfBirdseye, nfConnectionConfiguration, nfControllerService, nfReportingTask, nfParameterProvider, nfPolicyManagement, nfProcessorConfiguration, nfProcessGroupConfiguration, nfControllerServices, nfRemoteProcessGroupConfiguration, nfRemoteProcessGroupPorts, nfPortConfiguration, nfLabelConfiguration, nfProcessorDetails, nfPortDetails, nfConnectionDetails, nfRemoteProcessGroupDetails, nfGoto, nfNgBridge, appCtrl, appConfig, serviceProvider, breadcrumbsCtrl, headerCtrl, flowStatusCtrl, globalMenuCtrl, toolboxCtrl, processorComponent, inputPortComponent, outputPortComponent, processGroupComponent, remoteProcessGroupComponent, funnelComponent, templateComponent, labelComponent, graphControlsCtrl, navigateCtrl, operateCtrl, breadcrumbsDirective, draggableDirective);
});
} else if (typeof exports === 'object' && typeof module === 'object') {
module.exports = factory(require('jquery'),
@@ -118,6 +119,7 @@
require('nf.ConnectionConfiguration'),
require('nf.ControllerService'),
require('nf.ReportingTask'),
+ require('nf.ParameterProvider'),
require('nf.PolicyManagement'),
require('nf.ProcessorConfiguration'),
require('nf.ProcessGroupConfiguration'),
@@ -184,6 +186,7 @@
root.nf.ConnectionConfiguration,
root.nf.ControllerService,
root.nf.ReportingTask,
+ root.nf.ParameterProvider,
root.nf.PolicyManagement,
root.nf.ProcessorConfiguration,
root.nf.ProcessGroupConfiguration,
@@ -220,7 +223,7 @@
root.nf.ng.BreadcrumbsDirective,
root.nf.ng.DraggableDirective);
}
-}(this, function ($, angular, nfCommon, nfCanvasUtils, nfErrorHandler, nfClient, nfDialog, nfStorage, nfCanvas, nfGraph, nfContextMenu, nfQuickSelect, nfShell, nfParameterContexts, nfSettings, nfActions, nfSnippet, nfQueueListing, nfVerify, nfVariableRegistry, nfComponentState, nfFlowVersion, nfComponentVersion, nfDraggable, nfConnectable, nfStatusHistory, nfBirdseye, nfConnectionConfiguration, nfControllerService, nfReportingTask, nfPolicyManagement, nfProcessorConfiguration, nfProcessGroupConfiguration, nfControllerServices, nfRemoteProcessGroupConfiguration, nfRemoteProcessGroupPorts, nfPortConfiguration, nfLabelConfiguration, nfProcessorDetails, nfPortDetails, nfConnectionDetails, nfRemoteProcessGroupDetails, nfGoto, nfNgBridge, appCtrl, appConfig, serviceProvider, breadcrumbsCtrl, headerCtrl, flowStatusCtrl, globalMenuCtrl, toolboxCtrl, processorComponent, inputPortComponent, outputPortComponent, processGroupComponent, remoteProcessGroupComponent, funnelComponent, templateComponent, labelComponent, graphControlsCtrl, navigateCtrl, operateCtrl, breadcrumbsDirective, draggableDirective) {
+}(this, function ($, angular, nfCommon, nfCanvasUtils, nfErrorHandler, nfClient, nfDialog, nfStorage, nfCanvas, nfGraph, nfContextMenu, nfQuickSelect, nfShell, nfParameterContexts, nfSettings, nfActions, nfSnippet, nfQueueListing, nfVerify, nfVariableRegistry, nfComponentState, nfFlowVersion, nfComponentVersion, nfDraggable, nfConnectable, nfStatusHistory, nfBirdseye, nfConnectionConfiguration, nfControllerService, nfReportingTask, nfParameterProvider, nfPolicyManagement, nfProcessorConfiguration, nfProcessGroupConfiguration, nfControllerServices, nfRemoteProcessGroupConfiguration, nfRemoteProcessGroupPorts, nfPortConfiguration, nfLabelConfiguration, nfProcessorDetails, nfPortDetails, nfConnectionDetails, nfRemoteProcessGroupDetails, nfGoto, nfNgBridge, appCtrl, appConfig, serviceProvider, breadcrumbsCtrl, headerCtrl, flowStatusCtrl, globalMenuCtrl, toolboxCtrl, processorComponent, inputPortComponent, outputPortComponent, processGroupComponent, remoteProcessGroupComponent, funnelComponent, templateComponent, labelComponent, graphControlsCtrl, navigateCtrl, operateCtrl, breadcrumbsDirective, draggableDirective) {
var config = {
urls: {
@@ -349,7 +352,7 @@
nfShell.init(nfContextMenu);
nfNgBridge.injector.get('headerCtrl').init();
nfSettings.init();
- nfParameterContexts.init();
+ nfParameterContexts.init(nfParameterProvider);
nfActions.init();
nfQueueListing.init();
nfVerify.init();
@@ -370,8 +373,14 @@
// initialize the connection config and invert control of the birdseye and graph
nfConnectionConfiguration.init(nfBirdseye, nfGraph, configDetails.defaultBackPressureObjectThreshold, configDetails.defaultBackPressureDataSizeThreshold);
- nfControllerService.init(nfControllerServices, nfReportingTask);
+ nfControllerService.init(nfControllerServices, nfReportingTask, nfParameterProvider);
nfReportingTask.init(nfSettings);
+ nfParameterProvider.init({
+ nfSettings: nfSettings,
+ statusBarOptions: {
+ supportsStatusBar : true
+ }
+ });
nfPolicyManagement.init();
nfProcessorConfiguration.init({
supportsStatusBar : true,
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-controller-service.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-controller-service.js
index 086f31f7ff..72d37daa22 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-controller-service.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-controller-service.js
@@ -68,7 +68,9 @@
}(this, function ($, d3, nfErrorHandler, nfCommon, nfDialog, nfStorage, nfClient, nfSettings, nfUniversalCapture, nfCustomUi, nfVerify, nfCanvasUtils, nfProcessor) {
'use strict';
- var nfControllerServices, nfReportingTask;
+ var nfControllerServices,
+ nfReportingTask,
+ nfParameterProvider;
var config = {
edit: 'edit',
@@ -251,6 +253,15 @@
if (referencingComponentState.length) {
updateReferencingSchedulableComponentState(referencingComponentState, reference);
}
+ } else if (reference.referenceType === 'ParameterProvider') {
+ // reload
+ nfParameterProvider.reload(reference.id);
+
+ // update the validation errors of this parameter provider
+ var referencingComponentState = $('div.' + reference.id + '-state');
+ if (referencingComponentState.length) {
+ updateValidationErrors(referencingComponentState, reference);
+ }
} else {
// reload the referencing services
reloadControllerService(serviceTable, reference.id);
@@ -391,6 +402,42 @@
});
};
+ /**
+ * Updates validation errors. This is used for parameter providers and registry clients.
+ *
+ * @param validationErrorIcon
+ * @param referencingComponent
+ */
+ var updateValidationErrors = function (validationErrorIcon, referencingComponent) {
+ var currentValidationErrors = validationErrorIcon.data('validation-errors');
+
+ // update the validation errors if necessary
+ if (!_.isEqual(currentValidationErrors, referencingComponent.validationErrors)) {
+ validationErrorIcon.data('validation-errors', referencingComponent.validationErrors);
+
+ // if there are validation errors update them
+ if (!nfCommon.isEmpty(referencingComponent.validationErrors)) {
+ var list = nfCommon.formatUnorderedList(referencingComponent.validationErrors);
+
+ // update existing tooltip or initialize a new one if appropriate
+ if (validationErrorIcon.data('qtip')) {
+ validationErrorIcon.qtip('option', 'content.text', list);
+ } else {
+ validationErrorIcon.show().qtip($.extend({},
+ nfCanvasUtils.config.systemTooltipConfig,
+ {
+ content: list
+ }));
+ }
+ } else {
+ if (validationErrorIcon.data('qtip')) {
+ validationErrorIcon.removeData('validation-errors').qtip('api').destroy(true);
+ }
+ validationErrorIcon.hide();
+ }
+ }
+ };
+
/**
* Updates the bulletins for all referencing components.
*
@@ -444,6 +491,7 @@
var processors = $('
');
var services = $('
');
var tasks = $('
');
+ var providers = $('
');
var unauthorized = $('
');
$.each(referencingComponents, function (_, referencingComponentEntity) {
// check the access policy for this referencing component
@@ -582,6 +630,46 @@
// reporting task
var reportingTaskItem = $('
').append(reportingTaskState).append(reportingTaskBulletins).append(reportingTaskLink).append(reportingTaskType).append(reportingTaskActiveThreadCount);
tasks.append(reportingTaskItem);
+ } else if (referencingComponent.referenceType === 'ParameterProvider') {
+ var parameterProviderLink = $('
').text(referencingComponent.name).on('click', function () {
+ var parameterProvidersGrid = $('#parameter-providers-table').data('gridInstance');
+ var parameterProvidersData = parameterProvidersGrid.getData();
+
+ // select the selected row
+ var row = parameterProvidersData.getRowById(referencingComponent.id);
+ parameterProvidersGrid.setSelectedRows([row]);
+ parameterProvidersGrid.scrollRowIntoView(row);
+
+ // close the dialog and shell
+ referenceContainer.closest('.dialog').modal('hide');
+
+ $('#settings-tabs').find('li:eq(4)').click();
+
+ // adjust the table size
+ parameterProvidersGrid.resizeCanvas();
+ });
+
+ // provider state - used to show the validation errors
+ var providerState = $('
').addClass(referencingComponent.id + '-state');
+ if (nfCommon.isEmpty(referencingComponent.validationErrors)) {
+ providerState.hide();
+ } else {
+ updateValidationErrors(providerState, referencingComponent);
+ }
+
+ // bulletin
+ var providerBulletins = $('
').addClass(referencingComponent.id + '-bulletins');
+ if (!nfCommon.isEmpty(referencingComponentEntity.bulletins)) {
+ updateBulletins(referencingComponentEntity.bulletins, providerBulletins);
+ }
+
+ // type
+ var providerType = $('
').text(referencingComponent.type);
+
+ // parameter provider
+ var providerItem = $('
').append(providerState).append(providerBulletins).append(parameterProviderLink).append(providerType);
+
+ providers.append(providerItem);
}
}
});
@@ -614,6 +702,7 @@
createReferenceBlock('Processors', processors);
createReferenceBlock('Reporting Tasks', tasks);
createReferenceBlock('Controller Services', services);
+ createReferenceBlock('Parameter Providers', providers);
createReferenceBlock('Unauthorized', unauthorized);
// now that the dom elements are in place, we can show the bulletin icons.
@@ -734,7 +823,7 @@
referencingComponentRevisions[referencingComponentEntity.id] = nfClient.getRevision(referencingComponentEntity);
}
} else {
- if (referencingComponent.referenceType !== 'ControllerService') {
+ if (referencingComponent.referenceType === 'Processor' || referencingComponent.referenceType === 'ReportingTask') {
referencingComponentRevisions[referencingComponentEntity.id] = nfClient.getRevision(referencingComponentEntity);
}
}
@@ -948,7 +1037,7 @@
var referencingComponents = service.referencingComponents;
$.each(referencingComponents, function (_, referencingComponentEntity) {
var referencingComponent = referencingComponentEntity.component;
- if (referencingComponent.referenceType === 'Processor' || referencingComponent.referenceType === 'ReportingTask') {
+ if (referencingComponent.referenceType === 'Processor' || referencingComponent.referenceType === 'ReportingTask' || referencingComponent.referenceType === 'ParameterProvider') {
referencingSchedulableComponents.push(referencingComponent.id);
}
});
@@ -1753,9 +1842,10 @@
/**
* Initializes the controller service configuration dialog.
*/
- init: function (nfControllerServicesRef, nfReportingTaskRef) {
+ init: function (nfControllerServicesRef, nfReportingTaskRef, nfParameterProviderRef) {
nfControllerServices = nfControllerServicesRef;
nfReportingTask = nfReportingTaskRef;
+ nfParameterProvider = nfParameterProviderRef;
// initialize the configuration dialog tabs
$('#controller-service-configuration-tabs').tabbs({
@@ -1862,7 +1952,7 @@
}
}
});
-
+
// initialize the bulletin combo
$('#controller-service-bulletin-level-combo').combo({
options: [{
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-parameter-contexts.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-parameter-contexts.js
index 62b972196b..6b4bfc30c6 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-parameter-contexts.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-parameter-contexts.js
@@ -86,6 +86,8 @@
}(this, function ($, Slick, d3, nfClient, nfDialog, nfStorage, nfCommon, nfCanvasUtils, nfNgBridge, nfErrorHandler, nfFilteredDialogCommon, nfShell, nfComponentState, nfComponentVersion, nfPolicyManagement, nfProcessor, nfProcessGroup, nfProcessGroupConfiguration, _) {
'use strict';
+ var nfParameterProvider;
+
var config = {
urls: {
parameterContexts: '../nifi-api/parameter-contexts'
@@ -132,6 +134,29 @@
return nfCommon.escapeHtml(dataContext.component.name);
};
+ /**
+ * Formatter for the provider column.
+ *
+ * @param {type} row
+ * @param {type} cell
+ * @param {type} value
+ * @param {type} columnDef
+ * @param {type} dataContext
+ * @returns {String}
+ */
+ var providerFormatter = function (row, cell, value, columnDef, dataContext) {
+ var component = dataContext.component ? dataContext.component : null;
+
+ if (component && component.parameterProviderConfiguration) {
+ if (!dataContext.permissions.canRead) {
+ return '
' + nfCommon.escapeHtml(component.parameterProviderConfiguration.id) + ' ';
+ }
+
+ return nfCommon.escapeHtml(component.parameterProviderConfiguration.component.parameterGroupName +
+ ' from ' + component.parameterProviderConfiguration.component.parameterProviderName);
+ }
+ };
+
/**
* Sorts the specified data using the specified sort details.
*
@@ -216,6 +241,8 @@
$('#parameter-process-group-id').text('').removeData('revision');
$('#parameter-referencing-components-context').removeClass('unset').attr('title', '').text('');
+ $('#parameter-context-provider-setting').hide();
+
var parameterGrid = $('#parameter-table').data('gridInstance');
var parameterData = parameterGrid.getData();
parameterGrid.setSelectedRows([]);
@@ -1053,7 +1080,7 @@
referencingComponents: originalParameter.referencingComponents,
previousValue: originalParameter.value,
previousDescription: originalParameter.description,
- isEditable: originalParameter.isEditable,
+ isEditable: originalParameter.isEditable || originalParameter.provided !== true,
isEmptyStringSet: serializedParam.isEmptyStringSet,
isNew: originalParameter.isNew,
hasValueChanged: serializedParam.hasValueChanged,
@@ -1086,12 +1113,11 @@
$('#parameter-context-dialog').modal('refreshButtons');
};
-
var hasParameterContextChanged = function (parameterContextEntity) {
- var parameters = marshalParameters();
var proposedParamContextName = $('#parameter-context-name').val();
var proposedParamContextDesc = $('#parameter-context-description-field').val();
var inheritedParameterContexts = marshalInheritedParameterContexts();
+ var componentDescription = _.get(parameterContextEntity, 'component.description', '');
var inheritedParameterContextEquals = isInheritedParameterContextEquals(parameterContextEntity, inheritedParameterContexts);
if (inheritedParameterContextEquals) {
@@ -1100,15 +1126,23 @@
$('#inherited-parameter-contexts-message').removeClass('hidden');
}
- if (_.isEmpty(parameters) &&
- proposedParamContextName === _.get(parameterContextEntity, 'component.name') &&
- proposedParamContextDesc === _.get(parameterContextEntity, 'component.description') &&
- inheritedParameterContextEquals) {
-
- return false;
+ if (parameterContextEntity.component.parameterProviderConfiguration) {
+ if (proposedParamContextName === _.get(parameterContextEntity, 'component.name') &&
+ proposedParamContextDesc === componentDescription &&
+ inheritedParameterContextEquals) {
+ return false;
+ }
} else {
- return true;
+ var parameters = marshalParameters();
+ if (_.isEmpty(parameters) &&
+ proposedParamContextName === _.get(parameterContextEntity, 'component.name') &&
+ proposedParamContextDesc === _.get(parameterContextEntity, 'component.description') &&
+ inheritedParameterContextEquals) {
+ return false;
+ }
}
+
+ return true;
};
/**
@@ -1560,7 +1594,7 @@
description: parameterEntity.parameter.description,
previousValue: parameterEntity.parameter.value,
previousDescription: parameterEntity.parameter.description,
- isEditable: _.defaultTo(readOnly, false) ? false : parameterEntity.canWrite,
+ isEditable: _.defaultTo(readOnly, false) || parameterEntity.parameter.provided ? false : parameterEntity.canWrite,
referencingComponents: parameterEntity.parameter.referencingComponents,
parameterContext: containingParameterContext,
isInherited: (containingParameterContext.id !== parameterContext.component.id),
@@ -2496,6 +2530,10 @@
markup += '
';
}
+ if (canRead && dataContext.component.parameterProviderConfiguration) {
+ markup += '
';
+ }
+
return markup;
};
@@ -2537,6 +2575,13 @@
resizable: true,
formatter: nameFormatter
},
+ {
+ id: 'parameterProviderConfiguration',
+ name: 'Provider',
+ sortable: true,
+ resizable: true,
+ formatter: providerFormatter
+ },
{
id: 'description',
name: 'Description',
@@ -2600,6 +2645,13 @@
// close the settings dialog
$('#shell-close-button').click();
+ } else if (target.hasClass('go-to-provider')) {
+ if (parameterContextEntity.component.parameterProviderConfiguration) {
+ nfParameterProvider.showParameterProvider(parameterContextEntity.component.parameterProviderConfiguration.id);
+
+ // close the settings dialog
+ $('#shell-close-button').click();
+ }
}
} else if (parameterContextsGrid.getColumns()[args.cell].id === 'info') {
if (target.hasClass('view-parameter-context')) {
@@ -2657,8 +2709,12 @@
var nfParameterContexts = {
/**
* Initializes the parameter contexts page.
+ *
+ * @param nfParameterProviderRef The nfParameterProvider module.
*/
- init: function () {
+ init: function (nfParameterProviderRef) {
+ nfParameterProvider = nfParameterProviderRef;
+
// parameter context refresh button
$('#parameter-contexts-refresh-button').on('click', function () {
loadParameterContexts();
@@ -2926,6 +2982,36 @@
.prop('title', parameterContextEntity.id)
.text(parameterContextEntity.id);
+ // if provided, show the provider setting
+ if (parameterContextEntity.component.parameterProviderConfiguration) {
+ $('#parameter-context-provider-setting').show();
+
+ var parameterContextProviderSetting = $('#parameter-context-provider-setting').empty();
+ var providerContent = nfCommon.escapeHtml(parameterContextEntity.component.parameterProviderConfiguration.component.parameterGroupName +
+ ' from ' + parameterContextEntity.component.parameterProviderConfiguration.component.parameterProviderName);
+
+ $('
Provider
').appendTo(parameterContextProviderSetting);
+ var settingEl = $('
');
+
+ // provider name
+ var providerLinkEl = $('
')
+ .prop('title', providerContent)
+ .text(providerContent)
+ .on('click', function () {
+ // check if there are outstanding changes
+ handleOutstandingChanges().done(function () {
+ // close the shell
+ $('#shell-dialog').modal('hide');
+
+ // show the provider in question
+ nfParameterProvider.showParameterProvider(parameterContextEntity.component.parameterProviderConfiguration.id)
+ });
+ });
+
+ providerLinkEl.appendTo(settingEl);
+ settingEl.appendTo(parameterContextProviderSetting);
+ }
+
// get the reference container
var referencingComponentsContainer = $('#parameter-context-referencing-components');
@@ -2996,6 +3082,22 @@
// select the parameters tab
$('#parameter-context-tabs').find('li:eq(1)').click();
+ // if parameters are provided
+ if (parameterContextEntity.component.parameterProviderConfiguration) {
+ // hide the add parameter button
+ $('#add-parameter').hide();
+ } else {
+ // hide the provider details
+ if (!$('#parameter-context-provider-setting').hasClass('hidden')) {
+ $('#parameter-context-provider-setting')
+ .empty()
+ .addClass('hidden');
+ }
+
+ // show the add parameter button
+ $('#add-parameter').show();
+ }
+
// check if border is necessary
updateReferencingComponentsBorder($('#parameter-referencing-components-container'));
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-parameter-provider.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-parameter-provider.js
new file mode 100644
index 0000000000..6e4ff661e2
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-parameter-provider.js
@@ -0,0 +1,3317 @@
+/*
+ * 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.
+ */
+
+/* global define, module, require, exports */
+
+(function (root, factory) {
+ if (typeof define === 'function' && define.amd) {
+ define(['jquery',
+ 'Slick',
+ 'nf.ErrorHandler',
+ 'nf.Common',
+ 'nf.CanvasUtils',
+ 'nf.Dialog',
+ 'nf.Storage',
+ 'nf.Client',
+ 'nf.ControllerService',
+ 'nf.ControllerServices',
+ 'nf.UniversalCapture',
+ 'nf.CustomUi',
+ 'nf.Verify',
+ 'nf.Processor',
+ 'nf.ProcessGroup',
+ 'nf.ParameterContexts',
+ 'nf.ProcessGroupConfiguration',
+ 'lodash'],
+ function ($, Slick, nfErrorHandler, nfCommon, nfCanvasUtils, nfDialog, nfStorage, nfClient, nfControllerService, nfControllerServices, nfUniversalCapture, nfCustomUi, nfVerify, nfProcessor, nfProcessGroup, nfParameterContexts, nfProcessGroupConfiguration, _) {
+ return (nf.ParameterProvider = factory($, Slick, nfErrorHandler, nfCommon, nfCanvasUtils, nfDialog, nfStorage, nfClient, nfControllerService, nfControllerServices, nfUniversalCapture, nfCustomUi, nfVerify, nfProcessor, nfProcessGroup, nfParameterContexts, nfProcessGroupConfiguration, _));
+ });
+ } else if (typeof exports === 'object' && typeof module === 'object') {
+ module.exports = (nf.ParameterProvider =
+ factory(require('jquery'),
+ require('Slick'),
+ require('nf.ErrorHandler'),
+ require('nf.Common'),
+ require('nf.CanvasUtils'),
+ require('nf.Dialog'),
+ require('nf.Storage'),
+ require('nf.Client'),
+ require('nf.ControllerService'),
+ require('nf.ControllerServices'),
+ require('nf.UniversalCapture'),
+ require('nf.CustomUi'),
+ require('nf.Verify'),
+ require('nf.Processor'),
+ require('nf.ProcessGroup'),
+ require('nf.ParameterContexts'),
+ require('nf.ProcessGroupConfiguration'),
+ require('lodash')));
+ } else {
+ nf.ParameterProvider = factory(root.$,
+ root.Slick,
+ root.nf.ErrorHandler,
+ root.nf.Common,
+ root.nf.CanvasUtils,
+ root.nf.Dialog,
+ root.nf.Storage,
+ root.nf.Client,
+ root.nf.ControllerService,
+ root.nf.ControllerServices,
+ root.nf.UniversalCapture,
+ root.nf.CustomUi,
+ root.nf.Verify,
+ root.nf.Processor,
+ root.nf.ProcessGroup,
+ root.nf.ParameterContexts,
+ root.nf.ProcessGroupConfiguration,
+ root._);
+ }
+}(this, function ($, Slick, nfErrorHandler, nfCommon, nfCanvasUtils, nfDialog, nfStorage, nfClient, nfControllerService, nfControllerServices, nfUniversalCapture, nfCustomUi, nfVerify, nfProcessor, nfProcessGroup, nfParameterContexts, nfProcessGroupConfiguration, _) {
+ 'use strict';
+
+ var nfSettings;
+ var fetchParameterProviderOptions;
+
+ var config = {
+ edit: 'edit',
+ readOnly: 'read-only',
+ urls: {
+ parameterProviders: '../nifi-api/parameter-providers',
+ api: '../nifi-api'
+ }
+ };
+
+ // load the controller services
+ var controllerServicesUri = config.urls.api + '/flow/controller/controller-services';
+
+ var groupCount = 0;
+ var parameterCount = 0;
+
+ var SENSITIVE = 'SENSITIVE';
+ var NON_SENSITIVE = 'NON_SENSITIVE';
+
+ var parameterGroupsGridOptions = {
+ autosizeColsMode: Slick.GridAutosizeColsMode.LegacyForceFit,
+ enableTextSelectionOnCells: true,
+ enableCellNavigation: true,
+ enableColumnReorder: false,
+ editable: false,
+ enableAddRow: false,
+ autoEdit: false,
+ multiSelect: false,
+ rowHeight: 24
+ };
+
+ var selectableParametersGridOptions = {
+ autosizeColsMode: Slick.GridAutosizeColsMode.LegacyForceFit,
+ enableTextSelectionOnCells: true,
+ enableCellNavigation: true,
+ enableColumnReorder: false,
+ editable: false,
+ enableAddRow: false,
+ autoEdit: false,
+ multiSelect: false,
+ rowHeight: 24,
+ asyncEditorLoading: false
+ };
+
+ // the last submitted referenced attributes
+ var referencedAttributes = null;
+
+ /**
+ * Gets the controller services table.
+ *
+ * @returns {*|jQuery|HTMLElement}
+ */
+ var getControllerServicesTable = function () {
+ return $('#controller-services-table');
+ };
+
+ /**
+ * Determines whether the user has made any changes to the parameter provider configuration
+ * that needs to be saved.
+ */
+ var isSaveRequired = function () {
+ var entity = $('#parameter-provider-configuration').data('parameterProviderDetails');
+
+ // determine if any parameter provider settings have changed
+ if ($('#parameter-provider-name').val() !== entity.component['name']) {
+ return true;
+ }
+ if ($('#parameter-provider-comments').val() !== entity.component['comments']) {
+ return true;
+ }
+
+ // defer to the properties
+ return $('#parameter-provider-properties').propertytable('isSaveRequired');
+ };
+
+
+ /**
+ * Marshals the data that will be used to update the parameter provider's configuration.
+ */
+ var marshalDetails = function () {
+ // properties
+ var properties = $('#parameter-provider-properties').propertytable('marshalProperties');
+
+ // create the parameter provider dto
+ var parameterProviderDto = {};
+ parameterProviderDto['id'] = $('#parameter-provider-id').text();
+ parameterProviderDto['name'] = $('#parameter-provider-name').val();
+ parameterProviderDto['comments'] = $('#parameter-provider-comments').val();
+
+ // set the properties
+ if ($.isEmptyObject(properties) === false) {
+ parameterProviderDto['properties'] = properties;
+ }
+
+ // create the parameter provider entity
+ var parameterProviderEntity = {};
+ parameterProviderEntity['component'] = parameterProviderDto;
+
+ // return the marshaled details
+ return parameterProviderEntity;
+ };
+
+ /**
+ * Marshals the parameter groups in the table.
+ */
+ var marshalParameterGroups = function () {
+ var groups = [];
+ var table = $('#parameter-groups-table');
+ var groupsGrid = table.data('gridInstance');
+ var groupsData = groupsGrid.getData();
+ $.each(groupsData.getItems(), function (_, g) {
+ if (g.isParameterContext || g.createNewParameterContext) {
+ var group = {
+ 'groupName': g.name,
+ 'parameterContextName': g.parameterContextName,
+ 'synchronized': true,
+ 'parameterSensitivities': g.parameterSensitivities
+ }
+
+ groups.push(group);
+ }
+ })
+
+ return groups;
+ };
+
+ /**
+ * Validates the specified details.
+ *
+ * @param providerDetails the parameter provider details to validate
+ * @param originalProviderDetails the original parameter provider details to compare changes
+ * @param existingParametersProviders existing parameter providers to verify there are no duplicates
+ * @return {boolean}
+ */
+ var validateDetails = function (providerDetails, existingParametersProviders, originalProviderDetails) {
+ var parameterProvider = providerDetails['component'];
+
+ if (parameterProvider.name === '') {
+ nfDialog.showOkDialog({
+ headerText: 'Configuration Error',
+ dialogContent: 'The name of the Parameter Provider must be specified.'
+ });
+ return false;
+ }
+
+ // make sure the parameter provider name does not use any unsupported characters
+ var parameterProviderNameRegex = /^[a-zA-Z0-9-_. ]+$/;
+ if (!parameterProviderNameRegex.test(parameterProvider.name)) {
+ nfDialog.showOkDialog({
+ headerText: 'Configuration Error',
+ dialogContent: 'The name of the Parameter Provider appears to have an invalid character or characters. Only alpha-numeric characters (a-z, A-Z, 0-9), hyphens (-), underscores (_), periods (.), and spaces ( ) are accepted.'
+ });
+ return false;
+ }
+
+ // validate the parameter provider is not a duplicate
+ var matchingParameterProvider;
+ var match;
+
+ if (nfCommon.isUndefinedOrNull(matchingParameterProvider) && originalProviderDetails.component.name !== providerDetails.component.name){
+ $.each(existingParametersProviders, function (i, provider) {
+ if (nfCommon.isUndefinedOrNull(match)) {
+ match = _.find(provider, {name: parameterProvider.name});
+ if (match) {
+ matchingParameterProvider = match;
+ }
+ }
+
+ });
+ }
+
+ if (_.isNil(matchingParameterProvider)) {
+ return true;
+ } else {
+ nfDialog.showOkDialog({
+ headerText: 'Parameter Provider Exists',
+ dialogContent: 'A Parameter Provider with this name already exists.'
+ });
+ }
+ return false;
+ };
+
+ /**
+ * Renders the specified parameter provider.
+ *
+ * @param {object} parameterProviderEntity parameter provider entity
+ */
+ var renderParameterProvider = function (parameterProviderEntity) {
+ // get the table and update the row accordingly
+ var parameterProviderGrid = $('#parameter-providers-table').data('gridInstance');
+ var parameterProviderData = parameterProviderGrid.getData();
+ var currentParameterProvider = parameterProviderData.getItemById(parameterProviderEntity.id);
+ parameterProviderData.updateItem(parameterProviderEntity.id, $.extend({
+ type: 'ParameterProvider',
+ bulletins: currentParameterProvider.bulletins
+ }, parameterProviderEntity));
+ };
+
+ /**
+ * Goes to a service configuration from the property table.
+ */
+ var goToServiceFromProperty = function () {
+ return $.Deferred(function (deferred) {
+ // close all fields currently being edited
+ $('#parameter-provider-properties').propertytable('saveRow');
+
+ // determine if changes have been made
+ if (isSaveRequired()) {
+ // see if those changes should be saved
+ nfDialog.showYesNoDialog({
+ headerText: 'Save',
+ dialogContent: 'Save changes before going to this Controller Service?',
+ noHandler: function () {
+ deferred.resolve();
+ },
+ yesHandler: function () {
+ var parameterProvider = $('#parameter-provider-configuration').data('parameterProviderDetails');
+ saveParameterProvider(parameterProvider).done(function () {
+ deferred.resolve();
+ }).fail(function () {
+ deferred.reject();
+ });
+ }
+ });
+ } else {
+ deferred.resolve();
+ }
+ }).promise();
+ };
+
+ /**
+ * Saves the specified parameter provider.
+ *
+ * @param {type} parameterProviderEntity parameter provider entity
+ */
+ var saveParameterProvider = function (parameterProviderEntity) {
+ // save the original provider to detect a name change
+ var originalParameterProvider = parameterProviderEntity;
+
+ // marshal the settings and properties and update the parameter provider
+ var updatedParameterProvider = marshalDetails();
+
+ // ensure details are valid as far as we can tell
+ var parameterProvidersGrid = $('#parameter-providers-table').data('gridInstance');
+ var parameterProvidersData = parameterProvidersGrid.getData();
+
+ if (validateDetails(updatedParameterProvider, parameterProvidersData.getItems(), originalParameterProvider)) {
+ updatedParameterProvider['revision'] = nfClient.getRevision(parameterProviderEntity);
+ updatedParameterProvider['disconnectedNodeAcknowledged'] = nfStorage.isDisconnectionAcknowledged();
+
+ // update the selected component
+ return $.ajax({
+ type: 'PUT',
+ data: JSON.stringify(updatedParameterProvider),
+ url: parameterProviderEntity.uri,
+ dataType: 'json',
+ contentType: 'application/json'
+ }).done(function (response) {
+ // update the parameter provider
+ renderParameterProvider(response);
+ }).fail(nfErrorHandler.handleConfigurationUpdateAjaxError);
+ } else {
+ return $.Deferred(function (deferred) {
+ deferred.reject();
+ }).promise();
+ }
+ };
+
+ /**
+ * Gets a property descriptor for the parameter provider currently being configured.
+ *
+ * @param {type} propertyName property descriptor name
+ * @param {type} sensitive requested sensitive status
+ */
+ var getParameterProviderPropertyDescriptor = function (propertyName, sensitive) {
+ var details = $('#parameter-provider-configuration').data('parameterProviderDetails');
+ return $.ajax({
+ type: 'GET',
+ url: details.uri + '/descriptors',
+ data: {
+ propertyName: propertyName,
+ sensitive: sensitive
+ },
+ dataType: 'json'
+ }).fail(nfErrorHandler.handleAjaxError);
+ };
+
+ /**
+ * Handles verification results.
+ */
+ var handleVerificationResults = function (verificationResults, referencedAttributeMap) {
+ // record the most recently submitted referenced attributes
+ referencedAttributes = referencedAttributeMap;
+
+ var verificationResultsContainer = $('#parameter-provider-properties-verification-results');
+
+ // expand the dialog to make room for the verification result
+ if (verificationResultsContainer.is(':visible') === false) {
+ // show the verification results
+ $('#parameter-provider-properties').css('bottom', '40%').propertytable('resetTableSize')
+ verificationResultsContainer.show();
+ }
+
+ // show borders if appropriate
+ var verificationResultsListing = $('#parameter-provider-properties-verification-results-listing');
+ if (verificationResultsListing.get(0).scrollHeight > Math.round(verificationResultsListing.innerHeight())) {
+ verificationResultsListing.css('border-width', '1px');
+ }
+ };
+
+ /**
+ * Applies the fetched parameters of a specified Parameter Provider.
+ *
+ * @param parameterProviderEntity
+ * @returns {*}
+ */
+ var applyParametersHandler = function (parameterProviderEntity) {
+ var currentParameterProviderEntity = parameterProviderEntity;
+ var fetchParametersDialog = $('#fetch-parameters-dialog');
+
+ // clean up any tooltips that may have been generated
+ nfCommon.cleanUpTooltips($('#parameter-table'), 'div.fa-question-circle, div.fa-info');
+
+ var groups = marshalParameterGroups();
+ currentParameterProviderEntity.component.parameterGroupConfigurations = groups;
+
+ return $.Deferred(function (deferred) {
+ // updates the button model to show the close button
+ var updateToCloseButtonModel = function () {
+ fetchParametersDialog.modal('setButtonModel', [{
+ buttonText: 'Close',
+ color: {
+ base: '#728E9B',
+ hover: '#004849',
+ text: '#ffffff'
+ },
+ handler: {
+ click: function () {
+ deferred.resolve();
+ closeModal('#fetch-parameters-dialog');
+ }
+ }
+ }]);
+ };
+
+ var updateToApplyOrCancelButtonModel = function () {
+ fetchParametersDialog.modal('setButtonModel', [{
+ buttonText: 'Apply',
+ color: {
+ base: '#728E9B',
+ hover: '#004849',
+ text: '#ffffff'
+ },
+ handler: {
+ click: function () {
+ applyParametersHandler(currentParameterProviderEntity).done(function () {
+ // reload the parameter provider
+ nfParameterProvider.reload(parameterProviderEntity.id);
+ });
+ }
+ }
+ }, {
+ buttonText: 'Cancel',
+ color: {
+ base: '#E3E8EB',
+ hover: '#C7D2D7',
+ text: '#004849'
+ },
+ handler: {
+ click: function () {
+ deferred.resolve();
+ confirmCancelDialog('#fetch-parameters-dialog');
+ }
+ }
+ }]);
+ };
+
+ var cancelled = false;
+
+ // update the button model to show the cancel button
+ fetchParametersDialog.modal('setButtonModel', [{
+ buttonText: 'Cancel',
+ color: {
+ base: '#E3E8EB',
+ hover: '#C7D2D7',
+ text: '#004849'
+ },
+ handler: {
+ click: function () {
+ cancelled = true;
+ updateToCloseButtonModel();
+ }
+ }
+ }]);
+
+ var requestId;
+ var handleAjaxFailure = function (xhr, status, error) {
+ // delete the request if possible
+ if (nfCommon.isDefinedAndNotNull(requestId)) {
+ deleteUpdateRequest(currentParameterProviderEntity.id, requestId);
+ }
+
+ // update the step status
+ $('#fetch-parameters-update-steps')
+ .find('div.fetch-parameters-step.ajax-loading')
+ .removeClass('ajax-loading')
+ .addClass('ajax-error');
+
+ if ($('#affected-referencing-components-container').is(':visible')) {
+ updateReferencingComponentsBorder($('#affected-referencing-components-container'));
+ }
+
+ // update the button model
+ updateToApplyOrCancelButtonModel();
+ };
+
+ submitUpdateRequest(currentParameterProviderEntity).done(function (response) {
+ var pollUpdateRequest = function (updateRequestEntity) {
+ var updateRequest = updateRequestEntity.request;
+ var errored = nfCommon.isDefinedAndNotNull(updateRequest.failureReason);
+
+ // get the request id
+ requestId = updateRequest.requestId;
+
+ // update the affected referencing components
+ populateAffectedReferencingComponents(updateRequest.referencingComponents);
+
+ // update the progress/steps
+ populateFetchParametersUpdateStep(updateRequest.updateSteps, cancelled, errored);
+
+ // if this request was cancelled, remove the update request
+ if (cancelled) {
+ deleteUpdateRequest(currentParameterProviderEntity.id, requestId);
+ } else {
+ // show update steps
+ $('#fetch-parameters-update-status-container').show();
+
+ if (updateRequest.complete === true) {
+ if (errored) {
+ nfDialog.showOkDialog({
+ headerText: 'Apply Parameter Provider Error',
+ dialogContent: 'Unable to complete parameter provider update request: ' + nfCommon.escapeHtml(updateRequest.failureReason)
+ });
+ }
+
+ // reload referencing processors
+ $.each(updateRequest.referencingComponents, function (_, referencingComponentEntity) {
+ if (referencingComponentEntity.permissions.canRead === true) {
+ var referencingComponent = referencingComponentEntity.component;
+
+ // reload the processor if it's in the current group
+ if (referencingComponent.referenceType === 'PROCESSOR' && nfCanvasUtils.getGroupId() === referencingComponent.processGroupId) {
+ nfProcessor.reload(referencingComponent.id);
+ }
+ }
+ });
+
+ // update the fetch parameter table if displayed
+ if ($('#fetch-parameters-table').is(':visible')) {
+ var parameterProviderGrid = $('#fetch-parameters-table').data('gridInstance');
+ var parameterProviderData = parameterProviderGrid.getData();
+
+ $.extend(currentParameterProviderEntity, {
+ revision: updateRequestEntity.parameterContextRevision,
+ component: updateRequestEntity.request.parameterProvider
+ });
+
+ var item = parameterProviderData.getItemById(currentParameterProviderEntity.id);
+ if (nfCommon.isDefinedAndNotNull(item)) {
+ parameterProviderData.updateItem(currentParameterProviderEntity.id, currentParameterProviderEntity);
+ }
+ }
+
+ // delete the update request
+ deleteUpdateRequest(currentParameterProviderEntity.id, requestId);
+
+ // update the button model
+ updateToCloseButtonModel();
+
+ // check if border is necessary
+ if ($('#affected-referencing-components-container').is(':visible')) {
+ updateReferencingComponentsBorder($('#affected-referencing-components-container'));
+ }
+ } else {
+ // wait to get an updated status
+ setTimeout(function () {
+ getUpdateRequest(currentParameterProviderEntity.id, requestId).done(function (getResponse) {
+ pollUpdateRequest(getResponse);
+ }).fail(handleAjaxFailure);
+ }, 2000);
+ }
+ }
+ };
+
+ // get the parameter provider groups names
+ var parameterProviderGroupNames = [];
+ $.each(response.request.parameterProvider.parameterGroupConfigurations, function (_, parameterProviderGroup) {
+ parameterProviderGroupNames.push(parameterProviderGroup.groupName);
+ });
+ $('#apply-groups-list')
+ .removeClass('unset')
+ .attr('title', parameterProviderGroupNames.join(', '))
+ .text(parameterProviderGroupNames.join(', '));
+
+ // update the visibility
+ // left column
+ $('#fetch-parameters-usage-container').hide();
+ $('#apply-groups-container').show();
+
+ // middle column
+ $('#parameters-container').hide();
+ $('#fetch-parameters-update-status').show();
+
+ pollUpdateRequest(response);
+ }).fail(handleAjaxFailure);
+ }).promise();
+ };
+
+ /**
+ * Confirms a cancel dialog.
+ */
+ var confirmCancelDialog = function (dialog) {
+ nfDialog.showYesNoDialog({
+ headerText: 'Fetch Parameters',
+ dialogContent: 'Are you sure you want to cancel?',
+ noText: 'Cancel',
+ yesText: 'Yes',
+ yesHandler: function () {
+ closeModal(dialog);
+ }
+ });
+ };
+
+ /**
+ * Shows the dialog to fetch parameters.
+ *
+ * @param {object} parameterProviderEntity parameterProviderEntity
+ * @param {object} fetchParameterProviderOptions fetchParameterProviderOptions
+ */
+ var showFetchParametersDialog = function (parameterProviderEntity, fetchParameterProviderOptions) {
+ updateFetchParametersRequest(parameterProviderEntity).done(function (response) {
+ var updatedParameterProviderEntity = _.cloneDeep(response);
+ currentParameterProviderEntity = response;
+
+ groupCount = 0;
+ parameterCount = 0;
+
+ // populate the fetch parameters dialog
+ $('#fetch-parameters-id').text(updatedParameterProviderEntity.id);
+ $('#fetch-parameters-name').text(nfCommon.getComponentName(updatedParameterProviderEntity));
+
+ // set parameters contexts to be updated to none
+ $('
None
')
+ .appendTo($('#parameter-contexts-to-create-container'));
+
+ // list parameter contexts to update
+ var parameterContextsToUpdate = $('#parameter-contexts-to-update-container').empty();
+
+ if (!updatedParameterProviderEntity.component.referencingParameterContexts) {
+ $('
None
')
+ .appendTo(parameterContextsToUpdate);
+ } else {
+ // populate contexts to be updated
+ var parameterContextNames = [];
+ $.each(updatedParameterProviderEntity.component.referencingParameterContexts, function (_, paramContext) {
+ parameterContextNames.push(paramContext.component.name);
+ });
+ parameterContextNames.sort();
+ parameterContextsToUpdate
+ .removeClass('unset')
+ .attr('title', parameterContextNames.join(', '))
+ .text(parameterContextNames.join(', '));
+ }
+
+ loadParameterGroups(updatedParameterProviderEntity);
+
+ // keep original group data
+ var initialFetchedGroups = getFetchedParameterGroups(response);
+
+ // update visibility
+ $('#fetch-parameters-permissions-parameter-contexts-message').addClass('hidden');
+ $('#fetch-parameters-permissions-affected-components-message').addClass('hidden');
+ $('#fetch-parameters-missing-context-name-message').addClass('hidden');
+
+ $('#fetch-parameters-usage-container').show();
+ $('#parameters-container').show();
+
+ // build the button model
+ var buttons = [{
+ buttonText: 'Apply',
+ color: {
+ base: '#728E9B',
+ hover: '#004849',
+ text: '#ffffff'
+ },
+ disabled: function () {
+ return disableApplyButton(updatedParameterProviderEntity, initialFetchedGroups);
+ },
+ handler: {
+ click: function () {
+ applyParametersHandler(updatedParameterProviderEntity).done(function () {
+ // reload the parameter provider
+ nfParameterProvider.reload(parameterProviderEntity.id);
+ });
+ }
+ }
+ }, {
+ buttonText: 'Cancel',
+ color: {
+ base: '#E3E8EB',
+ hover: '#C7D2D7',
+ text: '#004849'
+ },
+ handler: {
+ click: function () {
+ if (!disableApplyButton(updatedParameterProviderEntity, initialFetchedGroups)) {
+ return confirmCancelDialog('#fetch-parameters-dialog');
+ }
+ closeModal('#fetch-parameters-dialog');
+ }
+ }
+ }];
+
+ // synchronize the current component canvas attributes in the status bar
+ if (fetchParameterProviderOptions.supportsStatusBar) {
+ var formattedBulletins = nfCommon.getFormattedBulletins(updatedParameterProviderEntity.bulletins);
+ var unorderedBulletins = nfCommon.formatUnorderedList(formattedBulletins);
+
+ // initialize the canvas synchronization
+ if (updatedParameterProviderEntity.bulletins.length !== 0) {
+ $('#fetch-parameters-status-bar').statusbar(
+ 'observe',
+ { provider: unorderedBulletins }
+ );
+ }
+ }
+
+ $('#fetch-parameters-affected-referencing-components-container').hide();
+ $('#fetch-parameters-referencing-components-container').show();
+
+ // show the dialog
+ $('#fetch-parameters-dialog')
+ .modal('setButtonModel', buttons)
+ .modal('show');
+
+ if ($('#fetched-parameters-listing-container').is(':visible')) {
+ updateReferencingComponentsBorder($('#fetched-parameters-listing-container'));
+ }
+ });
+ };
+
+ /**
+ * Determines if the fetch parameters dialog has changes and whether the user has permissions to apply the changes.
+ *
+ * @param {object} updatedParameterProviderEntity updatedParameterProviderEntity
+ * @param {object} initialFetchedGroups initialFetchedGroups
+ */
+ var disableApplyButton = function (updatedParameterProviderEntity, initialFetchedGroups) {
+ var canReadWrite = function (component) {
+ return component.permissions.canRead && component.permissions.canWrite;
+ }
+
+ // referencing parameter contexts
+ if (updatedParameterProviderEntity.component.referencingParameterContexts) {
+ var hasReadWriteParameterContextsPermissions = updatedParameterProviderEntity.component.referencingParameterContexts.every(canReadWrite);
+
+ if (hasReadWriteParameterContextsPermissions) {
+ // user has read and write permissions on a referencing parameter context
+ $('#fetch-parameters-permissions-parameter-contexts-message').addClass('hidden');
+ } else {
+ // user does not have read and write permissions on a referencing parameter context
+ // no need to continue checking
+ $('#fetch-parameters-permissions-parameter-contexts-message').removeClass('hidden');
+ return true;
+ }
+ }
+
+ // affected referencing components
+ if (updatedParameterProviderEntity.component.affectedComponents) {
+ var hasReadWriteAffectedComponentsPermissions = updatedParameterProviderEntity.component.affectedComponents.every(canReadWrite);
+
+ if (hasReadWriteAffectedComponentsPermissions) {
+ // user has read and write permissions on an affected component
+ $('#fetch-parameters-permissions-affected-components-message').addClass('hidden');
+
+ // user has permissions to all affected component... enable Apply button
+ } else {
+ // user does not have read and write permissions on an affected component
+ // no need to continue checking
+ $('#fetch-parameters-permissions-affected-components-message').removeClass('hidden');
+ return true;
+ }
+ }
+
+ var groupsData = $('#parameter-groups-table').data('gridInstance').getData();
+ var groups = groupsData.getItems();
+
+ // new parameter contexts
+ var parameterContextNames = [];
+ $.each(groups, function (i, g) {
+ if (g.createNewParameterContext) {
+ parameterContextNames.push(g.parameterContextName);
+ }
+ })
+
+ // if any createNewParameterContext, then the name input cannot be empty
+ var isNameBlank = function (name) {
+ return nfCommon.isBlank(name);
+ }
+
+ if (!_.isEmpty(parameterContextNames)) {
+ var isAnyParameterContextNameBlank = parameterContextNames.some(isNameBlank);
+
+ if (isAnyParameterContextNameBlank) {
+ // missing a parameter context name
+ // no need to continue checking
+ $('#fetch-parameters-missing-context-name-message').removeClass('hidden');
+ return true;
+ } else {
+ $('#fetch-parameters-missing-context-name-message').addClass('hidden');
+ }
+ } else {
+ // hide the message if previously shown
+ $('#fetch-parameters-missing-context-name-message').addClass('hidden');
+ }
+
+ // parameter sensitivities
+ for (var k = 0; k < initialFetchedGroups.length; k++) {
+ var groupFromDataGrid = groups[k];
+
+ if (nfCommon.isDefinedAndNotNull(groupFromDataGrid)) {
+ if (groupFromDataGrid.isParameterContext && nfCommon.isUndefinedOrNull(groupFromDataGrid.createNewParameterContext)) {
+ // form the initially fetched group sensitivities
+ var groupInitiallyFetched = initialFetchedGroups[k];
+ var initialGroupParamSensitivity = {};
+
+ for (var param in groupInitiallyFetched.parameterSensitivities) {
+ initialGroupParamSensitivity[param] = groupInitiallyFetched.parameterSensitivities[param] ? groupInitiallyFetched.parameterSensitivities[param] : SENSITIVE;
+ }
+
+ // compare
+ if (!_.isEqual(initialGroupParamSensitivity, groupFromDataGrid.parameterSensitivities)) {
+ // parameter sensitive has changed... do not disable the Apply button
+ return false;
+ }
+ }
+ }
+ }
+
+ // check for changed parameter values
+ if (updatedParameterProviderEntity.component.parameterStatus) {
+ var isChanged = function (parameterStatus) {
+ return parameterStatus.status === 'CHANGED';
+ }
+
+ var isAnyParameterValueChanged = updatedParameterProviderEntity.component.parameterStatus.some(isChanged);
+
+ if (isAnyParameterValueChanged) {
+ // a fetched parameter value has changed... do not disable the Apply button
+ return false;
+ }
+ }
+
+ return _.isEmpty(parameterContextNames);
+ };
+
+ /**
+ * Loads the specified fetched groups.
+ *
+ * @param {object} parameterProviderGroupEntity
+ * @param {boolean} if the parameters should be displayed in a read-only state regardless of permissions
+ */
+ var loadParameterGroups = function (parameterProviderGroupEntity) {
+ // providedGroups will be an array of groups
+ if (nfCommon.isDefinedAndNotNull(parameterProviderGroupEntity)) {
+ var groupsGrid = $('#parameter-groups-table').data('gridInstance');
+ var groupsData = groupsGrid.getData();
+
+ // begin the update
+ groupsData.beginUpdate();
+
+ var parameterGroups = [];
+ $.each(parameterProviderGroupEntity.component.parameterGroupConfigurations, function (i, groupConfig) {
+ var referencingParameterContext = parameterProviderGroupEntity.component.referencingParameterContexts
+ ? isReferencingParamContext(parameterProviderGroupEntity.component.referencingParameterContexts, groupConfig.parameterContextName)
+ : false;
+
+ var canWriteParameterContexts;
+ if (referencingParameterContext) {
+ canWriteParameterContexts = referencingParameterContext.permissions.canWrite;
+ } else {
+ canWriteParameterContexts = true;
+ }
+
+ var canWriteAffectedComponents;
+ if (parameterProviderGroupEntity.component.affectedComponents) {
+ canWriteAffectedComponents = (parameterProviderGroupEntity.component.affectedComponents).every(function (c) {
+ return c.permissions.canRead && c.permissions.canWrite;
+ });
+ } else {
+ canWriteAffectedComponents = true;
+ }
+
+ var group = {
+ id: groupCount++,
+ hidden: false,
+ isParameterContext: referencingParameterContext ? true : false,
+ name: groupConfig.groupName,
+ parameterContextName: groupConfig.parameterContextName,
+ parameterSensitivities: groupConfig.parameterSensitivities,
+ referencingParameterContexts: groupConfig.referencingParameterContexts ? groupConfig.referencingParameterContexts : null,
+ enableParametersCheckboxes: canWriteParameterContexts && canWriteAffectedComponents,
+ parameterStatus: parameterProviderGroupEntity.component.parameterStatus
+ };
+
+ parameterGroups.push({
+ group: group
+ });
+
+ groupsData.addItem(group);
+ });
+
+ // complete the update
+ groupsData.endUpdate();
+ groupsData.reSort();
+
+ // select the first row
+ groupsGrid.setSelectedRows([0]);
+ }
+ };
+
+ /**
+ * Determines if the provided group is synced to a parameter context.
+ *
+ * @param {object} referencingParameterContexts
+ * @param {string} parameterContextName
+ * @returns {boolean}
+ */
+ var isReferencingParamContext = function (referencingParameterContexts, parameterContextName) {
+ var referencingParamContext = null;
+ $.each(referencingParameterContexts, function (i, paramContext) {
+ if (paramContext.component.name.includes(parameterContextName)) {
+ referencingParamContext = paramContext;
+ }
+ })
+
+ return referencingParamContext;
+ }
+
+ /**
+ * Loads the selectable parameters for a specified parameter group.
+ *
+ * @param groupId
+ * @param {object} parametersEntity
+ * @param {object} updatedGroup
+ */
+ var loadSelectableParameters = function (groupId, parametersEntity, updatedGroup) {
+ if (nfCommon.isDefinedAndNotNull(parametersEntity)) {
+ var selectableParametersGrid = $('#selectable-parameters-table').data('gridInstance');
+ var parametersData = selectableParametersGrid.getData();
+
+ // clear the rows
+ selectableParametersGrid.setSelectedRows([]);
+ parametersData.setItems([]);
+
+ // begin the update
+ parametersData.beginUpdate();
+
+ var isAffectedParameter = function (providerEntity, param) {
+ var isAffectedParameter = false;
+ // check for affected components
+ $.each(providerEntity.component.parameterStatus, function (i, status) {
+ if (status.parameter.parameter.name === param) {
+ if (status.status === 'CHANGED') {
+ isAffectedParameter = true;
+ }
+ }
+ });
+ return isAffectedParameter;
+ }
+
+ var getParameterStatus = function (parameterStatus, param) {
+ return nfCommon.isDefinedAndNotNull(parameterStatus.find(function (status) { return status.parameter.parameter.name === param }))
+ ? parameterStatus.find(function (status) { return status.parameter.parameter.name === param })
+ : [];
+ }
+
+ var isReferencedParameter = function (paramStatus, param) {
+ var status = getParameterStatus(paramStatus, param);
+ return !_.isEmpty(status) && !_.isEmpty(status.parameter.parameter.referencingComponents);
+ }
+
+ var idx = 0;
+ var referencingParameters = 0;
+ var parameterCount = 0;
+ for (var param in parametersEntity) {
+
+ var parameter = {
+ id: idx++,
+ groupId: groupId,
+ name: param,
+ sensitivity: parametersEntity[param] ? parametersEntity[param] : SENSITIVE,
+ isAffectedParameter: currentParameterProviderEntity.component.affectedComponents ? isAffectedParameter(currentParameterProviderEntity, param) : false,
+ isReferencingParameter: !_.isEmpty(updatedGroup.parameterStatus) ? isReferencedParameter(updatedGroup.parameterStatus, param) : false,
+ parameterStatus: !_.isEmpty(updatedGroup.parameterStatus) ? getParameterStatus(updatedGroup.parameterStatus, param) : []
+ }
+
+ parametersData.addItem(parameter);
+
+ parameterCount++;
+ if (parameter.isReferencingParameter === true) {
+ referencingParameters++;
+ }
+ }
+
+ // complete the update
+ parametersData.endUpdate();
+ parametersData.reSort();
+
+ // select the the first row
+ selectableParametersGrid.setSelectedRows([0]);
+
+ // list the parameters to be created
+ loadParameterContextsToCreate();
+ }
+ };
+
+ /**
+ * Populates the affected referencing components for the specified parameter provider.
+ *
+ * @param {object} referencingComponents
+ */
+ var populateAffectedReferencingComponents = function (referencingComponents) {
+ // toggles the visibility of a container
+ var toggle = function (twist, container) {
+ if (twist.hasClass('expanded')) {
+ twist.removeClass('expanded').addClass('collapsed');
+ container.hide();
+ } else {
+ twist.removeClass('collapsed').addClass('expanded');
+ container.show();
+ }
+ };
+
+ // update visibility
+ $('#fetch-parameters-referencing-components-container').hide();
+ $('#affected-referencing-components-container').show();
+ updateReferencingComponentsBorder($('#affected-referencing-components-container'));
+
+ $('#fetch-parameters-affected-referencing-components-container').show();
+
+ var referencingProcessors = [];
+ var referencingControllerServices = [];
+ var unauthorizedReferencingComponents = [];
+
+ var spinner = $('#fetch-parameters-affected-referencing-components-container .referencing-components-loading');
+
+ var loadingDeferred = $.Deferred(function (deferred) {
+ spinner.addClass('ajax-loading');
+ deferred.resolve();
+ });
+ loadingDeferred.then(function () {
+ resetUsage();
+ }).then(function() {
+ var parameterReferencingComponentsContainer = $('#affected-referencing-components-container').empty();
+
+ // referencing component will be undefined when a new parameter is added
+ if (nfCommon.isUndefined(referencingComponents)) {
+ // set to pending
+ $('
Pending Apply
').appendTo(parameterReferencingComponentsContainer);
+ } else {
+ // bin the referencing components according to their type
+ $.each(referencingComponents, function (_, referencingComponentEntity) {
+ if (referencingComponentEntity.permissions.canRead === true && referencingComponentEntity.permissions.canWrite === true) {
+ if (referencingComponentEntity.component.referenceType === 'PROCESSOR') {
+ referencingProcessors.push(referencingComponentEntity);
+ } else {
+ referencingControllerServices.push(referencingComponentEntity);
+ }
+ } else {
+ unauthorizedReferencingComponents.push(referencingComponentEntity);
+ }
+ });
+
+ var referencingProcessGroups = {};
+
+ // bin the referencing processors according to their PG
+ $.each(referencingProcessors, function (_, referencingProcessorEntity) {
+ if (referencingProcessGroups[referencingProcessorEntity.processGroup.id]) {
+ referencingProcessGroups[referencingProcessorEntity.processGroup.id].referencingProcessors.push(referencingProcessorEntity);
+ referencingProcessGroups[referencingProcessorEntity.processGroup.id].id = referencingProcessorEntity.processGroup.id;
+ referencingProcessGroups[referencingProcessorEntity.processGroup.id].name = referencingProcessorEntity.processGroup.name;
+ } else {
+ referencingProcessGroups[referencingProcessorEntity.processGroup.id] = {
+ referencingProcessors: [],
+ referencingControllerServices: [],
+ unauthorizedReferencingComponents: [],
+ name: referencingProcessorEntity.processGroup.name,
+ id: referencingProcessorEntity.processGroup.id
+ };
+
+ referencingProcessGroups[referencingProcessorEntity.processGroup.id].referencingProcessors.push(referencingProcessorEntity);
+ }
+ });
+
+ // bin the referencing CS according to their PG
+ $.each(referencingControllerServices, function (_, referencingControllerServiceEntity) {
+ if (referencingProcessGroups[referencingControllerServiceEntity.processGroup.id]) {
+ referencingProcessGroups[referencingControllerServiceEntity.processGroup.id].referencingControllerServices.push(referencingControllerServiceEntity);
+ referencingProcessGroups[referencingControllerServiceEntity.processGroup.id].id = referencingControllerServiceEntity.processGroup.id;
+ referencingProcessGroups[referencingControllerServiceEntity.processGroup.id].name = referencingControllerServiceEntity.processGroup.name;
+ } else {
+ referencingProcessGroups[referencingControllerServiceEntity.processGroup.id] = {
+ referencingProcessors: [],
+ referencingControllerServices: [],
+ unauthorizedReferencingComponents: [],
+ name: referencingControllerServiceEntity.processGroup.name,
+ id: referencingControllerServiceEntity.processGroup.id
+ };
+
+ referencingProcessGroups[referencingControllerServiceEntity.processGroup.id].referencingControllerServices.push(referencingControllerServiceEntity);
+ }
+ });
+
+ // bin the referencing unauthorized components according to their PG
+ $.each(unauthorizedReferencingComponents, function (_, unauthorizedReferencingComponentEntity) {
+ if (referencingProcessGroups[unauthorizedReferencingComponentEntity.processGroup.id]) {
+ referencingProcessGroups[unauthorizedReferencingComponentEntity.processGroup.id].unauthorizedReferencingComponents.push(unauthorizedReferencingComponentEntity);
+ referencingProcessGroups[unauthorizedReferencingComponentEntity.processGroup.id].id = unauthorizedReferencingComponentEntity.processGroup.id;
+ referencingProcessGroups[unauthorizedReferencingComponentEntity.processGroup.id].name = unauthorizedReferencingComponentEntity.processGroup.name;
+ } else {
+ referencingProcessGroups[unauthorizedReferencingComponentEntity.processGroup.id] = {
+ referencingProcessors: [],
+ referencingControllerServices: [],
+ unauthorizedReferencingComponents: [],
+ name: unauthorizedReferencingComponentEntity.processGroup.name,
+ id: unauthorizedReferencingComponentEntity.processGroup.id
+ };
+
+ referencingProcessGroups[unauthorizedReferencingComponentEntity.processGroup.id].unauthorizedReferencingComponents.push(unauthorizedReferencingComponentEntity);
+ }
+ });
+
+ var parameterReferencingComponentsContainer = $('#affected-referencing-components-container');
+ var groups = $('
');
+
+ var referencingProcessGroupsArray = [];
+ for (var key in referencingProcessGroups) {
+ if (referencingProcessGroups.hasOwnProperty(key)) {
+ referencingProcessGroupsArray.push(referencingProcessGroups[key]);
+ }
+ }
+
+ if (nfCommon.isEmpty(referencingProcessGroupsArray)) {
+ // set to none
+ $('
None
').appendTo(parameterReferencingComponentsContainer);
+ } else {
+ //sort alphabetically
+ var sortedReferencingProcessGroups = referencingProcessGroupsArray.sort(function (a, b) {
+ if (a.name < b.name) {
+ return -1;
+ }
+ if (a.name > b.name) {
+ return 1;
+ }
+ return 0;
+ });
+
+ sortedReferencingProcessGroups.forEach(function (referencingProcessGroup) {
+ // container for this pg's references
+ var referencingPgReferencesContainer = $('
');
+ parameterReferencingComponentsContainer.append(referencingPgReferencesContainer);
+
+ // create the collapsable listing for each PG
+ var createReferenceBlock = function (referencingProcessGroup, list) {
+ var twist = $('
');
+ var title = $('
').text(referencingProcessGroup.name);
+ var count = $('
').text('(' + (referencingProcessGroup.referencingProcessors.length + referencingProcessGroup.referencingControllerServices.length + referencingProcessGroup.unauthorizedReferencingComponents.length) + ')');
+ var referencingComponents = $('#affected-referencing-components-template').clone();
+ referencingComponents.removeAttr('id');
+ referencingComponents.removeClass('hidden');
+
+ // create the reference block
+ var groupTwist = $('
').data('processGroupId', referencingProcessGroup.id).on('click', function () {
+ if (twist.hasClass('collapsed')) {
+ groupTwist.append(referencingComponents);
+
+ var processorContainer = groupTwist.find('.fetch-parameters-referencing-processors');
+ nfCommon.cleanUpTooltips(processorContainer, 'div.referencing-component-state');
+ nfCommon.cleanUpTooltips(processorContainer, 'div.referencing-component-bulletins');
+ processorContainer.empty();
+
+ var controllerServiceContainer = groupTwist.find('.fetch-parameters-referencing-controller-services');
+ nfCommon.cleanUpTooltips(controllerServiceContainer, 'div.referencing-component-state');
+ nfCommon.cleanUpTooltips(controllerServiceContainer, 'div.referencing-component-bulletins');
+ controllerServiceContainer.empty();
+
+ var unauthorizedComponentsContainer = groupTwist.find('.fetch-parameters-referencing-unauthorized-components').empty();
+
+ if (referencingProcessGroups[$(this).data('processGroupId')].referencingProcessors.length === 0) {
+ $('
None ').appendTo(processorContainer);
+ } else {
+ // sort the referencing processors
+ referencingProcessGroups[$(this).data('processGroupId')].referencingProcessors.sort(nameComparator);
+
+ // render each and register a click handler
+ $.each(referencingProcessGroups[$(this).data('processGroupId')].referencingProcessors, function (_, referencingProcessorEntity) {
+ renderReferencingProcessor(referencingProcessorEntity, processorContainer);
+ });
+ }
+
+ if (referencingProcessGroups[$(this).data('processGroupId')].referencingControllerServices.length === 0) {
+ $('
None ').appendTo(controllerServiceContainer);
+ } else {
+ // sort the referencing controller services
+ referencingProcessGroups[$(this).data('processGroupId')].referencingControllerServices.sort(nameComparator);
+
+ // render each and register a click handler
+ $.each(referencingProcessGroups[$(this).data('processGroupId')].referencingControllerServices, function (_, referencingControllerServiceEntity) {
+ renderReferencingControllerService(referencingControllerServiceEntity, controllerServiceContainer);
+ });
+ }
+
+ if (referencingProcessGroups[$(this).data('processGroupId')].unauthorizedReferencingComponents.length === 0) {
+ $('
None ').appendTo(unauthorizedComponentsContainer);
+ } else {
+ // sort the unauthorized referencing components
+ referencingProcessGroups[$(this).data('processGroupId')].unauthorizedReferencingComponents.sort(function (a, b) {
+ if (a.permissions.canRead === true && b.permissions.canRead === true) {
+ // processors before controller services
+ var sortVal = a.component.referenceType === b.component.referenceType ? 0 : a.component.referenceType > b.component.referenceType ? -1 : 1;
+
+ // if a and b are the same type, then sort by name
+ if (sortVal === 0) {
+ sortVal = a.component.name === b.component.name ? 0 : a.component.name > b.component.name ? 1 : -1;
+ }
+
+ return sortVal;
+ } else {
+
+ // if lacking read and write perms on both, sort by id
+ if (a.permissions.canRead === false && b.permissions.canRead === false) {
+ return a.id > b.id ? 1 : -1;
+ } else {
+ // if only one has read perms, then let it come first
+ if (a.permissions.canRead === true) {
+ return -1;
+ } else {
+ return 1;
+ }
+ }
+ }
+ });
+
+ $.each(referencingProcessGroups[$(this).data('processGroupId')].unauthorizedReferencingComponents, function (_, unauthorizedReferencingComponentEntity) {
+ if (unauthorizedReferencingComponentEntity.permissions.canRead === true) {
+ if (unauthorizedReferencingComponentEntity.component.referenceType === 'PROCESSOR') {
+ renderReferencingProcessor(unauthorizedReferencingComponentEntity, unauthorizedComponentsContainer);
+ } else {
+ renderReferencingControllerService(unauthorizedReferencingComponentEntity, unauthorizedComponentsContainer);
+ }
+ } else {
+ var referencingUnauthorizedComponentContainer = $('
').appendTo(unauthorizedComponentsContainer);
+ $('
')
+ .prop('title', unauthorizedReferencingComponentEntity.id)
+ .text(unauthorizedReferencingComponentEntity.id)
+ .on('click', function () {
+ // close the shell
+ $('#shell-dialog').modal('hide');
+
+ // show the component in question
+ if (unauthorizedReferencingComponentEntity.referenceType === 'PROCESSOR') {
+ nfCanvasUtils.showComponent(unauthorizedReferencingComponentEntity.processGroup.id, unauthorizedReferencingComponentEntity.id);
+ } else if (unauthorizedReferencingComponentEntity.referenceType === 'CONTROLLER_SERVICE') {
+ nfProcessGroupConfiguration.showConfiguration(unauthorizedReferencingComponentEntity.processGroup.id).done(function () {
+ nfProcessGroup.enterGroup(unauthorizedReferencingComponentEntity.processGroup.id);
+ nfProcessGroupConfiguration.selectControllerService(unauthorizedReferencingComponentEntity.id);
+ });
+ }
+ })
+ .appendTo(referencingUnauthorizedComponentContainer);
+ }
+ });
+ }
+ } else {
+ groupTwist.find('.affected-referencing-components-template').remove();
+ }
+
+ // toggle this block
+ toggle(twist, list);
+
+ // update the border if necessary
+ updateReferencingComponentsBorder($('#affected-referencing-components-container'));
+ }).append(twist).append(title).append(count).appendTo(referencingPgReferencesContainer);
+
+ // add the listing
+ list.appendTo(referencingPgReferencesContainer);
+
+ // expand the group twist
+ groupTwist.click();
+ };
+
+ // create block for this process group
+ createReferenceBlock(referencingProcessGroup, groups);
+ });
+ }
+ }
+ })
+ .always(function () {
+ spinner.removeClass('ajax-loading');
+ });
+ return loadingDeferred.promise();
+ };
+
+ /**
+ * Loads the referencing components for this parameter provider.
+ *
+ * @param {jQuery} parameterProviderReferencingComponentsContainer
+ * @param {object} parameterProviderEntity
+ */
+ var loadParameterProviderReferencingComponents = function (parameterProviderReferencingComponentsContainer, parameterProviderEntity) {
+ parameterProviderReferencingComponentsContainer.empty();
+ var parameterProviderComponent = parameterProviderEntity;
+
+ if (nfCommon.isEmpty(parameterProviderComponent.referencingParameterContexts)) {
+ parameterProviderReferencingComponentsContainer.append('
No referencing components.
');
+ return;
+ }
+
+ // toggles the visibility of a container
+ var toggle = function (twist, container) {
+ if (twist.hasClass('expanded')) {
+ twist.removeClass('expanded').addClass('collapsed');
+ container.hide();
+ } else {
+ twist.removeClass('collapsed').addClass('expanded');
+ container.show();
+ }
+ };
+
+ var parameterContexts = $('
');
+ var unauthorized = $('
');
+
+ $.each(parameterProviderComponent.referencingParameterContexts, function (_, refParameterContextComponent) {
+ // check the access policy for this referencing component
+ if (refParameterContextComponent.permissions.canRead === false) {
+ var unauthorizedReferencingComponent = $('
').text(refParameterContextComponent.id);
+ unauthorized.append(unauthorizedReferencingComponent);
+ } else {
+ var referencingComponent = refParameterContextComponent.component;
+
+ var parameterContextLink = $('
')
+ .text(referencingComponent.name)
+ .on('click', function () {
+ // show the component
+ nfParameterContexts.showParameterContexts(referencingComponent.id);
+
+ // close the dialog and shell
+ parameterProviderReferencingComponentsContainer.closest('.dialog').modal('hide');
+ $('#shell-close-button').click();
+ });
+ var parameterContextItem = $('
').append(parameterContextLink);
+ parameterContexts.append(parameterContextItem);
+ }
+ });
+
+ // create the collapsable listing for each type
+ var createReferenceBlock = function (titleText, list) {
+ if (list.is(':empty')) {
+ list.remove();
+ return;
+ }
+
+ var twist = $('
');
+ var title = $('
').text(titleText);
+ var count = $('
').text('(' + list.children().length + ')');
+
+ // create the reference block
+ $('
')
+ .on('click', function () {
+ // toggle this block
+ toggle(twist, list);
+
+ // update the border if necessary
+ updateReferencingComponentsBorder(parameterProviderReferencingComponentsContainer);
+ })
+ .append(twist)
+ .append(title)
+ .append(count)
+ .appendTo(parameterProviderReferencingComponentsContainer);
+
+ // add the listing
+ list.appendTo(parameterProviderReferencingComponentsContainer);
+ };
+
+ // create blocks for each type of component
+ createReferenceBlock('Parameter Contexts', parameterContexts);
+ createReferenceBlock('Unauthorized', unauthorized);
+ };
+
+ /**
+ * Loads the groups that will be created as a parameter context.
+ *
+ */
+ var loadParameterContextsToCreate = function () {
+ var parameterContextsToCreate = $('#parameter-contexts-to-create-container').empty();
+ var parameterContextNames = [];
+
+ var groupsGrid = $('#parameter-groups-table').data('gridInstance');
+ var groupsData = groupsGrid.getData();
+
+ $.each(groupsData.getItems(), function (_, group) {
+ if (group.createNewParameterContext) {
+ parameterContextNames.push(group.parameterContextName);
+ }
+ });
+
+ if (parameterContextNames.length === 0) {
+ $('
None
')
+ .appendTo(parameterContextsToCreate);
+ } else {
+ parameterContextNames.sort();
+ parameterContextsToCreate
+ .removeClass('unset')
+ .attr('title', parameterContextNames.join(', '))
+ .text(parameterContextNames.join(', '));
+ }
+ }
+
+ var getFetchedParameterGroups = function (groupEntity) {
+ var parameterGroups = [];
+ $.each(groupEntity.component.parameterGroupConfigurations, function (i, groupConfig) {
+ var referencingParameterContext = groupEntity.component.referencingParameterContexts
+ ? isReferencingParamContext(groupEntity.component.referencingParameterContexts, groupConfig.parameterContextName)
+ : false;
+
+ var canWriteParameterContexts;
+ if (referencingParameterContext) {
+ canWriteParameterContexts = referencingParameterContext.permissions.canWrite;
+ } else {
+ canWriteParameterContexts = true;
+ }
+
+ var canWriteAffectedComponents;
+ if (groupEntity.component.affectedComponents) {
+ canWriteAffectedComponents = (groupEntity.component.affectedComponents).every(function (c) {
+ return c.permissions.canRead && c.permissions.canWrite;
+ });
+ } else {
+ canWriteAffectedComponents = true;
+ }
+
+ var index = 0;
+ var group = {
+ id: index++,
+ hidden: false,
+ isParameterContext: referencingParameterContext ? true : false,
+ name: groupConfig.groupName,
+ parameterContextName: groupConfig.parameterContextName,
+ parameterSensitivities: groupConfig.parameterSensitivities,
+ referencingParameterContexts: groupConfig.referencingParameterContexts ? groupConfig.referencingParameterContexts : null,
+ enableParametersCheckboxes: canWriteParameterContexts && canWriteAffectedComponents,
+ parameterStatus: groupEntity.component.parameterStatus
+ };
+
+ parameterGroups.push(group);
+ });
+ return parameterGroups;
+ }
+
+ /**
+ * Handles outstanding changes.
+ *
+ * @returns {deferred}
+ */
+ var handleOutstandingChanges = function () {
+ return $.Deferred(function (deferred) {
+ if ($('#fetch-parameters-update-status').is(':visible')) {
+ close();
+ deferred.resolve();
+ } else {
+ var parameterGroups = marshalParameterGroups();
+
+ // if there are no parameters there is nothing to save
+ if ($.isEmptyObject(parameterGroups)) {
+ close();
+ deferred.resolve();
+ } else {
+ // see if those changes should be saved
+ nfDialog.showYesNoDialog({
+ headerText: 'Fetch Parameters',
+ dialogContent: 'Save changes before leaving parameters configuration?',
+ noHandler: function () {
+ close();
+ deferred.resolve();
+ },
+ yesHandler: function () {
+ applyParametersHandler(currentParameterProviderEntity).done(function () {
+ deferred.resolve();
+ }).fail(function () {
+ deferred.reject();
+ });
+ }
+ });
+ }
+ }
+
+ }).promise();
+ };
+
+ /**
+ * Adds a border to the fetch parameters referencing components if necessary.
+ *
+ * @argument {jQuery} referenceContainer
+ */
+ var updateReferencingComponentsBorder = function (referenceContainer) {
+ // determine if it is too big
+ var tooBig = referenceContainer.get(0).scrollHeight > Math.round(referenceContainer.innerHeight()) ||
+ referenceContainer.get(0).scrollWidth > Math.round(referenceContainer.innerWidth());
+
+ // draw the border if necessary
+ if (referenceContainer.is(':visible') && tooBig) {
+ referenceContainer.css('border-width', '1px');
+ } else {
+ referenceContainer.css('border-width', '0px');
+ }
+ };
+
+ /**
+ * Determines if any of the specified referencing components are not authorized to apply parameters.
+ *
+ * @param {object} parameterProviderEntity having referencingComponents referencing components
+ * @returns {boolean}
+ */
+ var hasUnauthorizedReferencingComponent = function (parameterProviderEntity) {
+
+ if (parameterProviderEntity.permissions.canRead === false
+ || (parameterProviderEntity.permissions.canWrite === false && parameterProviderEntity.operatePermissions.canWrite === false)) {
+ return true;
+ }
+
+ var hasUnauthorized = false;
+ var referencingComponents = parameterProviderEntity.component.referencingComponents;
+ $.each(referencingComponents, function (_, referencingComponentEntity) {
+ if (hasUnauthorizedReferencingComponent(referencingComponentEntity)) {
+ hasUnauthorized = true;
+ return false;
+ }
+ });
+
+ return hasUnauthorized;
+ };
+
+ /**
+ * Used to handle closing a modal dialog
+ *
+ * * @param {string} dialog the dialog to close
+ */
+ var closeModal = function (dialog) {
+ $(dialog).modal('hide');
+ };
+
+ /**
+ * Obtains the current state of the updateRequest using the specified update request id.
+ *
+ * @param {string} parameterProviderId parameter provider id
+ * @param {string} updateRequestId update request id
+ * @returns {deferred} update request xhr
+ */
+ var getUpdateRequest = function (parameterProviderId, updateRequestId) {
+ return $.ajax({
+ type: 'GET',
+ url: config.urls.parameterProviders + '/' + encodeURIComponent(parameterProviderId) + '/apply-parameters-requests/' + encodeURIComponent(updateRequestId),
+ dataType: 'json'
+ }).fail(nfErrorHandler.handleAjaxError);
+ };
+
+ /**
+ * Deletes an updateRequest using the specified update request id.
+ *
+ * @param {string} parameterProviderId parameter provider id
+ * @param {string} updateRequestId update request id
+ * @returns {deferred} update request xhr
+ */
+ var deleteUpdateRequest = function (parameterProviderId, updateRequestId) {
+ return $.ajax({
+ type: 'DELETE',
+ url: config.urls.parameterProviders + '/' + encodeURIComponent(parameterProviderId) + '/apply-parameters-requests/' + encodeURIComponent(updateRequestId) + '?' + $.param({
+ 'disconnectedNodeAcknowledged': nfStorage.isDisconnectionAcknowledged()
+ }),
+ dataType: 'json'
+ }).fail(nfErrorHandler.handleAjaxError);
+ };
+
+ /**
+ * Submits a parameter provider update request.
+ *
+ * @param {object} parameterProviderEntity parameter provider id
+ * @returns {deferred} update request xhr
+ */
+ var submitUpdateRequest = function (parameterProviderEntity) {
+ var requestEntity = {
+ 'id': parameterProviderEntity.id,
+ 'revision': nfClient.getRevision(parameterProviderEntity),
+ 'disconnectedNodeAcknowledged': nfStorage.isDisconnectionAcknowledged(),
+ 'parameterGroupConfigurations': parameterProviderEntity.component.parameterGroupConfigurations
+ }
+
+ return $.ajax({
+ type: 'POST',
+ data: JSON.stringify(requestEntity),
+ url: config.urls.parameterProviders + '/' + encodeURIComponent(requestEntity.id) + '/apply-parameters-requests',
+ dataType: 'json',
+ contentType: 'application/json'
+ }).fail(nfErrorHandler.handleAjaxError);
+ };
+
+ /**
+ * Submits a parameter provider update request.
+ *
+ * @param {object} parameterProviderEntity parameter provider id
+ * @returns {deferred} update request xhr
+ */
+ var updateFetchParametersRequest = function (parameterProviderEntity) {
+ return $.ajax({
+ type: 'POST',
+ data: JSON.stringify(parameterProviderEntity),
+ url: config.urls.parameterProviders + '/' + encodeURIComponent(parameterProviderEntity.id) + '/parameters/fetch-requests'+ '?' + $.param({
+ 'disconnectedNodeAcknowledged': nfStorage.isDisconnectionAcknowledged()
+ }),
+ dataType: 'json',
+ contentType: 'application/json'
+ }).fail(nfErrorHandler.handleAjaxError);
+ };
+
+ /**
+ * Populates the fetch parameters update steps.
+ *
+ * @param {array} updateSteps steps to update
+ * @param {boolean} cancelled whether this request has been cancelled
+ * @param {boolean} errored whether this request has errored
+ */
+ var populateFetchParametersUpdateStep = function (updateSteps, cancelled, errored) {
+ var updateStatusContainer = $('#fetch-parameters-update-steps').empty();
+
+ // go through each step
+ $.each(updateSteps, function (_, updateStep) {
+ var stepItem = $('
').text(updateStep.description).appendTo(updateStatusContainer);
+
+ $('
').addClass(function () {
+ if (nfCommon.isDefinedAndNotNull(updateStep.failureReason)) {
+ return 'ajax-error';
+ } else {
+ if (updateStep.complete === true) {
+ return 'ajax-complete';
+ } else {
+ return cancelled === true || errored === true ? 'ajax-error' : 'ajax-loading';
+ }
+ }
+ }).appendTo(stepItem);
+
+ $('
').appendTo(stepItem);
+ });
+ };
+
+ /**
+ * Loads the fetched parameters for the specified parameter group.
+ *
+ * @param {object} fetchedGroup the parameter group
+ */
+ var loadFetchedParameters = function (fetchedGroup) {
+ var updatedGroup = fetchedGroup;
+ var isParameterContext = updatedGroup.isParameterContext;
+ var isCreateNewParameterContext = updatedGroup.createNewParameterContext;
+
+ $('#fetched-parameters-listing').empty();
+
+ // get an instance of the grid
+ var groupsGrid = $('#parameter-groups-table').data('gridInstance');
+ var groupsData = groupsGrid.getData();
+
+ // show the appropriate parameters table when dialog first opens
+ if (isParameterContext) {
+ // get the active group's parameters to populate the selectable parameters container
+ loadSelectableParameters(updatedGroup.id, updatedGroup.parameterSensitivities, updatedGroup);
+
+ $('#parameters-container').show();
+ $('#selectable-parameters-container').show();
+ $('#fetched-parameters-container').hide();
+ } else {
+ $('#selectable-parameters-container').hide();
+ $('#fetched-parameters-container').show();
+ }
+
+ if (Object.keys(updatedGroup.parameterSensitivities).length !== 0) {
+ $('#create-parameter-context-checkbox-container').show();
+
+ /* Form the create parameter context checkbox */
+ var parametersCheckboxContainer = $('#create-parameter-context-checkbox-container').empty();
+ var createParamContextContainer;
+
+ /* Form the parameter context name input */
+ if (isParameterContext) {
+ // only show the name
+ createParamContextContainer = $('
');
+
+ $('
' +
+ '
Parameter Context Name
' +
+ '
' +
+ '
' + nfCommon.escapeHtml(fetchedGroup.parameterContextName) + '
' +
+ '
').appendTo(createParamContextContainer);
+ } else {
+
+ var checkboxMarkup = $('
');
+
+ if (isCreateNewParameterContext) {
+ // select checkbox
+ $('
').appendTo(checkboxMarkup);
+
+ loadSelectableParameters(updatedGroup.id, updatedGroup.parameterSensitivities, updatedGroup);
+
+ $('#parameters-container').show();
+ $('#selectable-parameters-container').show();
+ $('#fetched-parameters-container').hide();
+ } else {
+ // deselect checkbox
+ $('
').appendTo(checkboxMarkup);
+
+ $('#selectable-parameters-container').hide();
+ $('#fetched-parameters-container').show();
+ }
+
+ $('
' +
+ 'Create Parameter Context' +
+ '
').appendTo(checkboxMarkup);
+
+ var settingMarkup = $('
');
+ $(checkboxMarkup).appendTo(settingMarkup);
+ $(settingMarkup).appendTo(parametersCheckboxContainer);
+
+ // create the input container and set visibility
+ if (isCreateNewParameterContext) {
+ createParamContextContainer = $('
');
+ } else {
+ createParamContextContainer = $('
');
+ }
+
+ // create the input
+ $('
' +
+ '
Parameter Context Name
' +
+ '
' +
+ '
' +
+ '
').appendTo(createParamContextContainer);
+ }
+
+ createParamContextContainer.appendTo(parametersCheckboxContainer);
+
+ // populate the name input
+ var contextName = updatedGroup.parameterContextName;
+ $('#create-parameter-context-input').val(contextName);
+ } else {
+ $('#create-parameter-context-checkbox-container').hide();
+ }
+
+ /* Form the parameters listing */
+ var fetchedParametersContainer = $('#fetched-parameters-listing').empty();
+ var fetchedParameters = updatedGroup.parameterSensitivities;
+
+ // get parameter names only
+ var parametersArray = Object.keys(fetchedParameters);
+
+ // create parameter names listing
+ if (parametersArray.length > 0) {
+ $.each(parametersArray, function (i, parameter) {
+ var li = $('
').text(parameter);
+ $('
').appendTo(li);
+ li.appendTo(fetchedParametersContainer);
+ })
+ } else {
+ // set to none
+ $('
None
').appendTo(fetchedParametersContainer);
+ }
+
+ // update the border if necessary
+ updateReferencingComponentsBorder($('#fetched-parameters-listing-container'));
+
+ /* Temporarily save any changes */
+ // begin updating the group table
+ groupsData.beginUpdate();
+
+ // save parameter context name change
+ $('#create-parameter-context-input').on('blur', function () {
+ // get the input value
+ updatedGroup.parameterContextName = $('#create-parameter-context-input').val();
+
+ // update the group item
+ groupsData.updateItem(updatedGroup.id, updatedGroup);
+
+ // update the list of parameters to be created
+ loadParameterContextsToCreate();
+
+ $('#fetch-parameters-dialog').modal('refreshButtons');
+ })
+
+ // create parameter checkbox behaviors
+ $('#create-parameter-context-field').off().on('change', function (event, args) {
+ // if checked then show the name input, hide parameters listing, show selectable parameters table
+ if (args.isChecked) {
+ updatedGroup.createNewParameterContext = true;
+
+ loadSelectableParameters(updatedGroup.id, updatedGroup.parameterSensitivities, updatedGroup);
+
+ $('#fetched-parameters-container').hide();
+ $('#create-parameter-context-container').show();
+ $('#selectable-parameters-container').show();
+ $('#fetch-parameters-dialog').modal('refreshButtons');
+ } else {
+ // if unchecked, then hide the input and only show the parameters listing
+ updatedGroup.createNewParameterContext = false;
+
+ loadSelectableParameters(updatedGroup.id, updatedGroup.parameterSensitivities, updatedGroup);
+
+ $('#create-parameter-context-container').hide();
+ $('#selectable-parameters-container').hide();
+ $('#fetched-parameters-container').show();
+ $('#fetch-parameters-dialog').modal('refreshButtons');
+ }
+
+ // update the group item
+ groupsData.updateItem(updatedGroup.id, updatedGroup);
+ });
+
+ // finish updating the group table
+ groupsData.endUpdate();
+ groupsData.reSort();
+ };
+
+ /**
+ * Reset the dialog.
+ */
+ var resetFetchParametersDialog = function () {
+ $('#fetch-parameters-affected-referencing-components-container').hide();
+ $('#fetch-parameters-referencing-components-container').show();
+ $('#fetch-parameters-permissions-parameter-contexts-message').addClass('hidden');
+ $('#fetch-parameters-permissions-affected-components-message').addClass('hidden');
+ $('#create-parameter-context-input').val('');
+
+ var headerCheckbox = $('#selectable-parameters-table .slick-column-name input');
+ headerCheckbox.removeAttr('checked');
+
+ // clear the groups table
+ var groupsGrid = $('#parameter-groups-table').data('gridInstance');
+ var groupsData = groupsGrid.getData();
+ groupsGrid.setSelectedRows([]);
+ groupsData.setItems([]);
+
+ // clear the selectable parameters table
+ var selectableParametersGrid = $('#selectable-parameters-table').data('gridInstance');
+ var selectableParametersData = selectableParametersGrid.getData();
+ selectableParametersGrid.setSelectedRows([]);
+ selectableParametersData.setItems([]);
+
+ resetUsage();
+
+ // reset the last selected
+ lastSelectedGroupId = null;
+ lastSelectedParameterId = null;
+ };
+
+ var lastSelectedGroupId = null;
+ var lastSelectedParameterId = null;
+
+ /**
+ * Sorts the specified data using the specified sort details.
+ *
+ * @param {object} sortDetails
+ * @param {object} data
+ */
+ var sortParameters = function (sortDetails, data) {
+ // defines a function for sorting
+ var comparer = function (a, b) {
+ // direct parameters always come above inherited ones
+ if (a.isInherited === false && b.isInherited === true) {
+ return -1;
+ }
+ if (a.isInherited === true && b.isInherited === false) {
+ return 1;
+ }
+ if (sortDetails.columnId === 'name') {
+ var aString = _.get(a, '[' + sortDetails.columnId + ']', '');
+ var bString = _.get(b, '[' + sortDetails.columnId + ']', '');
+ return aString === bString ? 0 : aString > bString ? 1 : -1;
+ }
+ };
+
+ // perform the sort
+ data.sort(comparer, sortDetails.sortAsc);
+ };
+
+ /**
+ * Sorts the specified entities based on the name.
+ *
+ * @param {object} a
+ * @param {object} b
+ * @returns {number}
+ */
+ var nameComparator = function (a, b) {
+ return a.component.name.localeCompare(b.component.name);
+ };
+
+ /**
+ * Performs the filtering.
+ *
+ * @param {object} item The item subject to filtering
+ * @param {object} args Filter arguments
+ * @returns {Boolean} Whether or not to include the item
+ */
+ var filter = function (item, args) {
+ return item.hidden === false;
+ };
+
+ /**
+ * Renders the bulletins as a tooltip of the bulletinIconElement, shows the icon
+ *
+ * @param bulletins bulletins to be rendered
+ * @param bulletinIconElement jQuery element to display as the bulletin icon and source for the tooltip
+ */
+ var renderBulletins = function (bulletins, bulletinIconElement) {
+ // format the new bulletins
+ var formattedBulletins = nfCommon.getFormattedBulletins(bulletins);
+
+ var list = nfCommon.formatUnorderedList(formattedBulletins);
+
+ // update existing tooltip or initialize a new one if appropriate
+ bulletinIconElement.addClass('has-bulletins').show().qtip($.extend({},
+ nfCanvasUtils.config.systemTooltipConfig,
+ {
+ content: list
+ }));
+ }
+
+ /**
+ * Populates the referencing components for the specified parameter context.
+ *
+ * @param {object} referencingComponents
+ */
+ var populateReferencingComponents = function (referencingComponents) {
+ // toggles the visibility of a container
+ var toggle = function (twist, container) {
+ if (twist.hasClass('expanded')) {
+ twist.removeClass('expanded').addClass('collapsed');
+ container.hide();
+ } else {
+ twist.removeClass('collapsed').addClass('expanded');
+ container.show();
+ }
+ };
+
+ var referencingProcessors = [];
+ var referencingControllerServices = [];
+ var unauthorizedReferencingComponents = [];
+
+ var spinner = $('#fetch-parameters-referencing-components-container .referencing-components-loading');
+
+ var loadingDeferred = $.Deferred(function (deferred) {
+ spinner.addClass('ajax-loading');
+ deferred.resolve();
+ });
+ loadingDeferred.then(function () {
+ resetUsage();
+ }).then(function() {
+ var fetchParameterReferencingComponentsContainer = $('#fetch-parameter-referencing-components-container').empty();
+
+ // referencing component will be undefined when a new parameter is added
+ if (_.isEmpty(referencingComponents)) {
+ // set to pending
+ $('
None
').appendTo(fetchParameterReferencingComponentsContainer);
+ } else {
+ // bin the referencing components according to their type
+ $.each(referencingComponents.parameter.parameter.referencingComponents, function (_, referencingComponentEntity) {
+ if (referencingComponentEntity.permissions.canRead === true && referencingComponentEntity.permissions.canWrite === true) {
+ if (referencingComponentEntity.component.referenceType === 'PROCESSOR') {
+ referencingProcessors.push(referencingComponentEntity);
+ } else {
+ referencingControllerServices.push(referencingComponentEntity);
+ }
+ } else {
+ unauthorizedReferencingComponents.push(referencingComponentEntity);
+ }
+ });
+
+ var referencingProcessGroups = {};
+
+ // bin the referencing processors according to their PG
+ $.each(referencingProcessors, function (_, referencingProcessorEntity) {
+ if (referencingProcessGroups[referencingProcessorEntity.processGroup.id]) {
+ referencingProcessGroups[referencingProcessorEntity.processGroup.id].referencingProcessors.push(referencingProcessorEntity);
+ referencingProcessGroups[referencingProcessorEntity.processGroup.id].id = referencingProcessorEntity.processGroup.id;
+ referencingProcessGroups[referencingProcessorEntity.processGroup.id].name = referencingProcessorEntity.processGroup.name;
+ } else {
+ referencingProcessGroups[referencingProcessorEntity.processGroup.id] = {
+ referencingProcessors: [],
+ referencingControllerServices: [],
+ unauthorizedReferencingComponents: [],
+ name: referencingProcessorEntity.processGroup.name,
+ id: referencingProcessorEntity.processGroup.id
+ };
+
+ referencingProcessGroups[referencingProcessorEntity.processGroup.id].referencingProcessors.push(referencingProcessorEntity);
+ }
+ });
+
+ // bin the referencing CS according to their PG
+ $.each(referencingControllerServices, function (_, referencingControllerServiceEntity) {
+ if (referencingProcessGroups[referencingControllerServiceEntity.processGroup.id]) {
+ referencingProcessGroups[referencingControllerServiceEntity.processGroup.id].referencingControllerServices.push(referencingControllerServiceEntity);
+ referencingProcessGroups[referencingControllerServiceEntity.processGroup.id].id = referencingControllerServiceEntity.processGroup.id;
+ referencingProcessGroups[referencingControllerServiceEntity.processGroup.id].name = referencingControllerServiceEntity.processGroup.name;
+ } else {
+ referencingProcessGroups[referencingControllerServiceEntity.processGroup.id] = {
+ referencingProcessors: [],
+ referencingControllerServices: [],
+ unauthorizedReferencingComponents: [],
+ name: referencingControllerServiceEntity.processGroup.name,
+ id: referencingControllerServiceEntity.processGroup.id
+ };
+
+ referencingProcessGroups[referencingControllerServiceEntity.processGroup.id].referencingControllerServices.push(referencingControllerServiceEntity);
+ }
+ });
+
+ // bin the referencing unauthorized components according to their PG
+ $.each(unauthorizedReferencingComponents, function (_, unauthorizedReferencingComponentEntity) {
+ if (referencingProcessGroups[unauthorizedReferencingComponentEntity.processGroup.id]) {
+ referencingProcessGroups[unauthorizedReferencingComponentEntity.processGroup.id].unauthorizedReferencingComponents.push(unauthorizedReferencingComponentEntity);
+ referencingProcessGroups[unauthorizedReferencingComponentEntity.processGroup.id].id = unauthorizedReferencingComponentEntity.processGroup.id;
+ referencingProcessGroups[unauthorizedReferencingComponentEntity.processGroup.id].name = unauthorizedReferencingComponentEntity.processGroup.name;
+ } else {
+ referencingProcessGroups[unauthorizedReferencingComponentEntity.processGroup.id] = {
+ referencingProcessors: [],
+ referencingControllerServices: [],
+ unauthorizedReferencingComponents: [],
+ name: unauthorizedReferencingComponentEntity.processGroup.name,
+ id: unauthorizedReferencingComponentEntity.processGroup.id
+ };
+
+ referencingProcessGroups[unauthorizedReferencingComponentEntity.processGroup.id].unauthorizedReferencingComponents.push(unauthorizedReferencingComponentEntity);
+ }
+ });
+
+ var fetchParameterReferencingComponentsContainer = $('#fetch-parameter-referencing-components-container');
+ var groups = $('
');
+
+ var referencingProcessGroupsArray = [];
+ for (var key in referencingProcessGroups) {
+ if (referencingProcessGroups.hasOwnProperty(key)) {
+ referencingProcessGroupsArray.push(referencingProcessGroups[key]);
+ }
+ }
+
+ if (nfCommon.isEmpty(referencingProcessGroupsArray)) {
+ // set to none
+ $('
None
').appendTo(fetchParameterReferencingComponentsContainer);
+ } else {
+ //sort alphabetically
+ var sortedReferencingProcessGroups = referencingProcessGroupsArray.sort(function (a, b) {
+ if (a.name < b.name) {
+ return -1;
+ }
+ if (a.name > b.name) {
+ return 1;
+ }
+ return 0;
+ });
+
+ sortedReferencingProcessGroups.forEach(function (referencingProcessGroup) {
+ // container for this pg's references
+ var referencingPgReferencesContainer = $('
');
+ fetchParameterReferencingComponentsContainer.append(referencingPgReferencesContainer);
+
+ // create the collapsable listing for each PG
+ var createReferenceBlock = function (referencingProcessGroup, list) {
+ var twist = $('
');
+ var title = $('
').text(referencingProcessGroup.name);
+ var count = $('
').text('(' + (referencingProcessGroup.referencingProcessors.length + referencingProcessGroup.referencingControllerServices.length + referencingProcessGroup.unauthorizedReferencingComponents.length) + ')');
+ var referencingComponents = $('#fetch-parameters-referencing-components-template').clone();
+ referencingComponents.removeAttr('id');
+ referencingComponents.removeClass('hidden');
+
+ // create the reference block
+ var groupTwist = $('
').data('processGroupId', referencingProcessGroup.id).on('click', function () {
+ if (twist.hasClass('collapsed')) {
+ groupTwist.append(referencingComponents);
+
+ var processorContainer = groupTwist.find('.fetch-parameters-referencing-processors');
+ nfCommon.cleanUpTooltips(processorContainer, 'div.referencing-component-state');
+ nfCommon.cleanUpTooltips(processorContainer, 'div.referencing-component-bulletins');
+ processorContainer.empty();
+
+ var controllerServiceContainer = groupTwist.find('.fetch-parameters-referencing-controller-services');
+ nfCommon.cleanUpTooltips(controllerServiceContainer, 'div.referencing-component-state');
+ nfCommon.cleanUpTooltips(controllerServiceContainer, 'div.referencing-component-bulletins');
+ controllerServiceContainer.empty();
+
+ var unauthorizedComponentsContainer = groupTwist.find('.fetch-parameters-referencing-unauthorized-components').empty();
+
+ if (referencingProcessGroups[$(this).data('processGroupId')].referencingProcessors.length === 0) {
+ $('
None ').appendTo(processorContainer);
+ } else {
+ // sort the referencing processors
+ referencingProcessGroups[$(this).data('processGroupId')].referencingProcessors.sort(nameComparator);
+
+ // render each and register a click handler
+ $.each(referencingProcessGroups[$(this).data('processGroupId')].referencingProcessors, function (_, referencingProcessorEntity) {
+ renderReferencingProcessor(referencingProcessorEntity, processorContainer);
+ });
+ }
+
+ if (referencingProcessGroups[$(this).data('processGroupId')].referencingControllerServices.length === 0) {
+ $('
None ').appendTo(controllerServiceContainer);
+ } else {
+ // sort the referencing controller services
+ referencingProcessGroups[$(this).data('processGroupId')].referencingControllerServices.sort(nameComparator);
+
+ // render each and register a click handler
+ $.each(referencingProcessGroups[$(this).data('processGroupId')].referencingControllerServices, function (_, referencingControllerServiceEntity) {
+ renderReferencingControllerService(referencingControllerServiceEntity, controllerServiceContainer);
+ });
+ }
+
+ if (referencingProcessGroups[$(this).data('processGroupId')].unauthorizedReferencingComponents.length === 0) {
+ $('
None ').appendTo(unauthorizedComponentsContainer);
+ } else {
+ // sort the unauthorized referencing components
+ referencingProcessGroups[$(this).data('processGroupId')].unauthorizedReferencingComponents.sort(function (a, b) {
+ if (a.permissions.canRead === true && b.permissions.canRead === true) {
+ // processors before controller services
+ var sortVal = a.component.referenceType === b.component.referenceType ? 0 : a.component.referenceType > b.component.referenceType ? -1 : 1;
+
+ // if a and b are the same type, then sort by name
+ if (sortVal === 0) {
+ sortVal = a.component.name === b.component.name ? 0 : a.component.name > b.component.name ? 1 : -1;
+ }
+
+ return sortVal;
+ } else {
+
+ // if lacking read and write perms on both, sort by id
+ if (a.permissions.canRead === false && b.permissions.canRead === false) {
+ return a.id > b.id ? 1 : -1;
+ } else {
+ // if only one has read perms, then let it come first
+ if (a.permissions.canRead === true) {
+ return -1;
+ } else {
+ return 1;
+ }
+ }
+ }
+ });
+
+ $.each(referencingProcessGroups[$(this).data('processGroupId')].unauthorizedReferencingComponents, function (_, unauthorizedReferencingComponentEntity) {
+ if (unauthorizedReferencingComponentEntity.permissions.canRead === true) {
+ if (unauthorizedReferencingComponentEntity.component.referenceType === 'PROCESSOR') {
+ renderReferencingProcessor(unauthorizedReferencingComponentEntity, unauthorizedComponentsContainer);
+ } else {
+ renderReferencingControllerService(unauthorizedReferencingComponentEntity, unauthorizedComponentsContainer);
+ }
+ } else {
+ var referencingUnauthorizedComponentContainer = $('
').appendTo(unauthorizedComponentsContainer);
+ $('
')
+ .prop('title', unauthorizedReferencingComponentEntity.id)
+ .text(unauthorizedReferencingComponentEntity.id)
+ .on('click', function () {
+ // check if there are outstanding changes
+ handleOutstandingChanges().done(function () {
+ // close the shell
+ $('#shell-dialog').modal('hide');
+
+ // show the component in question
+ if (unauthorizedReferencingComponentEntity.referenceType === 'PROCESSOR') {
+ nfCanvasUtils.showComponent(unauthorizedReferencingComponentEntity.processGroup.id, unauthorizedReferencingComponentEntity.id);
+ } else if (unauthorizedReferencingComponentEntity.referenceType === 'CONTROLLER_SERVICE') {
+ nfProcessGroupConfiguration.showConfiguration(unauthorizedReferencingComponentEntity.processGroup.id).done(function () {
+ nfProcessGroup.enterGroup(unauthorizedReferencingComponentEntity.processGroup.id);
+ nfProcessGroupConfiguration.selectControllerService(unauthorizedReferencingComponentEntity.id);
+ });
+ }
+ });
+ })
+ .appendTo(referencingUnauthorizedComponentContainer);
+ }
+ });
+ }
+ } else {
+ groupTwist.find('.fetch-parameters-referencing-components-template').remove();
+ }
+
+ // toggle this block
+ toggle(twist, list);
+
+ // update the border if necessary
+ updateReferencingComponentsBorder($('#fetch-parameter-referencing-components-container'));
+ }).append(twist).append(title).append(count).appendTo(referencingPgReferencesContainer);
+
+ // add the listing
+ list.appendTo(referencingPgReferencesContainer);
+
+ // expand the group twist
+ groupTwist.click();
+ };
+
+ // create block for this process group
+ createReferenceBlock(referencingProcessGroup, groups);
+ });
+ }
+ }
+ })
+ .always(function () {
+ spinner.removeClass('ajax-loading');
+ });
+ return loadingDeferred.promise();
+ };
+
+ /**
+ * Renders the specified referencing component.
+ *
+ * @param {object} referencingProcessorEntity
+ * @param {jQuery} container
+ */
+ var renderReferencingProcessor = function (referencingProcessorEntity, container) {
+ var referencingProcessorContainer = $('
').appendTo(container);
+ var referencingProcessor = referencingProcessorEntity.component;
+
+ // processor state
+ $('
').addClass(function () {
+ if (nfCommon.isDefinedAndNotNull(referencingProcessor.state)) {
+ var icon = $(this);
+
+ var state = referencingProcessor.state.toLowerCase();
+ if (state === 'stopped' && !nfCommon.isEmpty(referencingProcessor.validationErrors)) {
+ state = 'invalid';
+
+ // build the validation error listing
+ var list = nfCommon.formatUnorderedList(referencingProcessor.validationErrors);
+
+ // add tooltip for the warnings
+ icon.qtip($.extend({},
+ nfCanvasUtils.config.systemTooltipConfig,
+ {
+ content: list
+ }));
+ }
+
+ return state;
+ } else {
+ return '';
+ }
+ }).appendTo(referencingProcessorContainer);
+
+
+ // processor name
+ $('
')
+ .prop('title', referencingProcessor.name)
+ .text(referencingProcessor.name)
+ .on('click', function () {
+ // close the shell
+ $('#shell-dialog').modal('hide');
+
+ // show the component in question
+ nfCanvasUtils.showComponent(referencingProcessorEntity.processGroup.id, referencingProcessor.id);
+ $('#fetch-parameters-dialog').modal('hide');
+ }).appendTo(referencingProcessorContainer);
+
+ // bulletin
+ var bulletinIcon = $('
').addClass(referencingProcessor.id + '-referencing-bulletins');
+ bulletinIcon.appendTo(referencingProcessorContainer);
+ if (!nfCommon.isEmpty(referencingProcessorEntity.bulletins)) {
+ renderBulletins(referencingProcessorEntity.bulletins, bulletinIcon);
+ }
+
+ // processor active threads
+ $('
').text(function () {
+ if (nfCommon.isDefinedAndNotNull(referencingProcessor.activeThreadCount) && referencingProcessor.activeThreadCount > 0) {
+ return '(' + referencingProcessor.activeThreadCount + ')';
+ } else {
+ return '';
+ }
+ }).appendTo(referencingProcessorContainer);
+ };
+
+ /**
+ * Renders the specified affect controller service.
+ *
+ * @param {object} referencingControllerServiceEntity
+ * @param {jQuery} container
+ */
+ var renderReferencingControllerService = function (referencingControllerServiceEntity, container) {
+ var referencingControllerServiceContainer = $('
').appendTo(container);
+ var referencingControllerService = referencingControllerServiceEntity.component;
+
+ // controller service state
+ $('
').addClass(function () {
+ if (nfCommon.isDefinedAndNotNull(referencingControllerService.state)) {
+ var icon = $(this);
+
+ var state = referencingControllerService.state === 'ENABLED' ? 'enabled' : 'disabled';
+ if (state === 'disabled' && !nfCommon.isEmpty(referencingControllerService.validationErrors)) {
+ state = 'invalid';
+
+ // build the error listing
+ var list = nfCommon.formatUnorderedList(referencingControllerService.validationErrors);
+
+ // add tooltip for the warnings
+ icon.qtip($.extend({},
+ nfCanvasUtils.config.systemTooltipConfig,
+ {
+ content: list
+ }));
+ }
+ return state;
+ } else {
+ return '';
+ }
+ }).appendTo(referencingControllerServiceContainer);
+
+ // bulletin
+ var bulletinIcon = $('
')
+ .addClass(referencingControllerService.id + '-referencing-bulletins')
+ .appendTo(referencingControllerServiceContainer);
+ if (!nfCommon.isEmpty(referencingControllerServiceEntity.bulletins)) {
+ renderBulletins(referencingControllerServiceEntity.bulletins, bulletinIcon);
+ }
+
+ // controller service name
+ $('
')
+ .prop('title', referencingControllerService.name)
+ .text(referencingControllerService.name)
+ .on('click', function () {
+ // close the shell
+ $('#shell-dialog').modal('hide');
+
+ nfProcessGroup.enterGroup(referencingControllerService.processGroupId);
+
+ // show the component in question
+ nfProcessGroupConfiguration.showConfiguration(referencingControllerService.processGroupId)
+ .done(function () {
+ nfProcessGroupConfiguration.selectControllerService(referencingControllerService.id);
+ $('#fetch-parameters-dialog').modal('hide');
+ });
+ }).appendTo(referencingControllerServiceContainer);
+ };
+
+ /**
+ * Initializes the selectable parameters table
+ */
+ var initSelectableParametersTable = function () {
+ var selectableParametersTable = $('#selectable-parameters-table');
+
+ var nameFormatter = function (row, cell, value, columnDef, dataContext) {
+ var valueWidthOffset = 10;
+ var cellContent = $('
');
+
+ // format the contents
+ var formattedValue = $('
').addClass('table-cell').text(value).appendTo(cellContent);
+ if (dataContext.type === 'required') {
+ formattedValue.addClass('required');
+ }
+
+ if (dataContext.isAffectedParameter || dataContext.parameterStatus.status === 'CHANGED') {
+ valueWidthOffset += 30;
+ $('
').appendTo(cellContent);
+ }
+
+ if (dataContext.isReferencingParameter) {
+ valueWidthOffset += 30;
+ $('
').appendTo(cellContent);
+ }
+
+ // adjust the width accordingly
+ formattedValue.width(columnDef.width - valueWidthOffset).ellipsis();
+
+ // return the cell content
+ return cellContent.html();
+ };
+
+ var checkboxSelectionFormatter = function (row, cell, value, columnDef, dataContext) {
+ if (dataContext) {
+ if (_.isEmpty(dataContext.parameterStatus) || _.isEmpty(dataContext.parameterStatus.parameter.parameter.referencingComponents)) {
+ if (dataContext.sensitivity === SENSITIVE) {
+ return "
";
+ } else {
+ return "
";
+ }
+ }
+
+ if (!_.isEmpty(dataContext.parameterStatus.parameter.parameter.referencingComponents)) {
+ // disable checkboxes
+ if (dataContext.sensitivity === SENSITIVE) {
+ return "
";
+ } else {
+ return "
";
+ }
+ }
+
+ $('#fetch-parameters-dialog').modal('refreshButtons');
+ }
+ return null;
+ };
+
+ var parametersColumn = [];
+
+ // define the column models for the table
+ var nameColumnDefinition = {
+ id: 'name',
+ name: 'Parameter Name',
+ field: 'name',
+ formatter: nameFormatter,
+ sortable: true,
+ resizable: false,
+ rerenderOnResize: true,
+ width: 280,
+ minWidth: 280,
+ editor: Slick.Editors.Text
+ };
+
+ var checkboxColumnDefinition = {
+ id: 'selector',
+ field: 'sel',
+ width: 30,
+ resizable: false,
+ sortable: false,
+ cssClass: 'slick-cell-checkboxsel',
+ hideSelectAllCheckbox: false,
+ formatter: checkboxSelectionFormatter
+ }
+
+ parametersColumn.push(checkboxColumnDefinition);
+ parametersColumn.push(nameColumnDefinition);
+
+ // initialize the dataview
+ var selectableParametersData = new Slick.Data.DataView({
+ inlineFilters: false
+ });
+
+ // initialize the sort
+ sortParameters({
+ columnId: 'name',
+ sortAsc: true
+ }, selectableParametersData);
+
+
+ // initialize the grid
+ var selectableParametersGrid = new Slick.Grid(selectableParametersTable, selectableParametersData, parametersColumn, selectableParametersGridOptions);
+ selectableParametersGrid.setSelectionModel(new Slick.RowSelectionModel());
+ selectableParametersGrid.registerPlugin(new Slick.AutoTooltips());
+
+ selectableParametersGrid.setSortColumn('name', true);
+ selectableParametersGrid.onSort.subscribe(function (e, args) {
+ sortParameters({
+ columnId: args.sortCol.id,
+ sortAsc: args.sortAsc
+ }, selectableParametersData);
+ });
+
+ selectableParametersGrid.onClick.subscribe(function (e, args) {
+ var target = $(e.target);
+ // get the node at this row
+ var item = selectableParametersData.getItem(args.row);
+ var saveToGroup = false;
+
+ if (selectableParametersGrid.getColumns()[args.cell].id === 'selector') {
+ if (target.hasClass('unchecked-input-enabled')) {
+ saveToGroup = true;
+ // check the box
+ item.sensitivity = SENSITIVE;
+ selectableParametersData.updateItem(item.id, item)
+ } else if (target.hasClass('checked-input-enabled')) {
+ saveToGroup = true;
+ // uncheck the box
+ item.sensitivity = NON_SENSITIVE;
+ selectableParametersData.updateItem(item.id, item)
+ }
+
+ // save to its group
+ if (saveToGroup) {
+ var groupsGrid = $('#parameter-groups-table').data('gridInstance');
+ var groupsData = groupsGrid.getData();
+ var currentGroup = groupsData.getItem([item.groupId]);
+
+ currentGroup.parameterSensitivities[item.name] = item.sensitivity;
+ groupsData.updateItem(item.groupId, currentGroup);
+
+ $('#fetch-parameters-dialog').modal('refreshButtons');
+ }
+ }
+ })
+
+ selectableParametersGrid.onSelectedRowsChanged.subscribe(function (e, args) {
+ if ($.isArray(args.rows) && args.rows.length === 1) {
+ // show the referencing components for the selected parameter
+ if (selectableParametersGrid.getDataLength() > 0) {
+ var parameterIndex = args.rows[0];
+ var parameter = selectableParametersGrid.getDataItem(parameterIndex);
+
+ // only populate referencing components if this parameter is different than the last selected
+ if (lastSelectedParameterId === null || lastSelectedParameterId !== parameter.id) {
+
+ populateReferencingComponents(parameter.parameterStatus)
+ .then(function () {
+ updateReferencingComponentsBorder($('#fetch-parameter-referencing-components-container'));
+
+ // update the last selected id
+ lastSelectedParameterId = parameter.id;
+ });
+ }
+ }
+ }
+
+ $('#fetch-parameters-dialog').modal('refreshButtons');
+ })
+
+ // wire up the dataview to the grid
+ selectableParametersData.onRowCountChanged.subscribe(function (e, args) {
+ var selectableParameters = args.dataView.getItems();
+
+ if (!_.isEmpty(selectableParameters)) {
+ var groupsGrid = $('#parameter-groups-table').data('gridInstance');
+ var groupsData = groupsGrid.getData();
+ var currentGroupId = selectableParameters[0].groupId;
+ var currentGroup = groupsData.getItem([currentGroupId]);
+
+ if (!currentGroup.isParameterContext) {
+ // update parameter sensitivities
+ var paramSensitivities = {};
+ $.each(selectableParameters, function (i, param) {
+ paramSensitivities[param.name] = param.sensitivity;
+ })
+
+ // save to its group
+ currentGroup.parameterSensitivities = paramSensitivities;
+ groupsData.updateItems(currentGroupId, currentGroup);
+ }
+ }
+
+ selectableParametersGrid.updateRowCount();
+ selectableParametersGrid.render();
+ });
+ selectableParametersData.onRowsChanged.subscribe(function (e, args) {
+ selectableParametersGrid.invalidateRows(args.rows);
+ selectableParametersGrid.render();
+ });
+ selectableParametersData.syncGridSelection(selectableParametersGrid, true);
+
+ // hold onto an instance of the grid and create an affected component tooltip
+ selectableParametersTable.data('gridInstance', selectableParametersGrid).on('mouseenter', 'div.slick-cell', function (e) {
+ var asteriskIconElement = $(this).find('div.fa-asterisk');
+ var asteriskTooltipContent = nfCommon.escapeHtml('Value has changed.');
+
+ // initialize tooltip
+ asteriskIconElement.qtip($.extend({},
+ nfCommon.config.tooltipConfig,
+ {
+ content: asteriskTooltipContent
+ }));
+
+ var hashtagIconElement = $(this).find('div.fa-hashtag');
+ var hashtagTooltipContent = nfCommon.escapeHtml('This parameter is currently referenced by a property. The sensitivity cannot be changed.');
+
+ // initialize tooltip
+ hashtagIconElement.qtip($.extend({},
+ nfCommon.config.tooltipConfig,
+ {
+ content: hashtagTooltipContent
+ }));
+ });
+
+ /**
+ * Select or deselect parameters that are not disabled.
+ *
+ * @param selectionType The type of selection.
+ */
+ var selectOrDeselectAll = function (selectionType) {
+ var sensitivity = selectionType === 'select' ? SENSITIVE : NON_SENSITIVE;
+
+ // get all selectable parameters
+ var selectableParams = [];
+ $.each(selectableParametersData.getItems(), function (i, param) {
+ if (!param.isReferencingParameter) {
+ selectableParams.push(param);
+ }
+ });
+
+ if (!_.isEmpty(selectableParams)) {
+ var groupsGrid = $('#parameter-groups-table').data('gridInstance');
+ var groupsData = groupsGrid.getData();
+ var currentGroupId = groupsGrid.getSelectedRows();
+ var currentGroup = groupsData.getItem(currentGroupId);
+
+ // begin updating
+ groupsData.beginUpdate();
+
+ // set sensitivities
+ $.each(selectableParams, function (i, param) {
+ var updateParamItem = $.extend(param, { sensitivity: sensitivity });
+ selectableParametersData.updateItem(param.id, updateParamItem);
+
+ // save to its group
+ currentGroup.parameterSensitivities[param.name] = sensitivity;
+ })
+
+ // complete the update
+ groupsData.endUpdate();
+
+ $('#fetch-parameters-dialog').modal('refreshButtons');
+ }
+ }
+
+ $('#select-all-fetched-parameters').on('click', function() {
+ selectOrDeselectAll('select');
+ });
+
+ $('#deselect-all-fetched-parameters').on('click', function() {
+ selectOrDeselectAll('deselect');
+ });
+
+ // end
+ }
+
+ /**
+ * Initializes the parameter groups table
+ */
+ var initParameterGroupsTable = function () {
+ var parameterGroupsTable = $('#parameter-groups-table');
+
+ var nameFormatter = function (row, cell, value, columnDef, dataContext) {
+ var nameWidthOffset = 30;
+ var cellContent = $('
');
+
+ // format the contents
+ var formattedValue = $('
').addClass('table-cell').text(value).appendTo(cellContent);
+ if (dataContext.type === 'required') {
+ formattedValue.addClass('required');
+ }
+
+ // add icon if group is or will be created as a parameter context
+ if (dataContext.isParameterContext || dataContext.createNewParameterContext) {
+ $('
').appendTo(cellContent);
+ }
+
+ // adjust the width accordingly
+ formattedValue.width(columnDef.width - nameWidthOffset).ellipsis();
+
+ // return the cell content
+ return cellContent.html();
+ };
+
+ // define the column model for the table
+ var groupsColumn = [
+ {
+ id: 'name',
+ name: 'Parameter Group Name',
+ field: 'name',
+ formatter: nameFormatter,
+ sortable: true,
+ resizable: true,
+ rerenderOnResize: true,
+ width: 327,
+ minWidth: 327,
+ maxWidth: 327
+ }
+ ];
+
+ // initialize the dataview
+ var groupsData = new Slick.Data.DataView({
+ inlineFilters: false
+ });
+ groupsData.setFilterArgs({
+ searchString: '',
+ property: 'hidden'
+ });
+ groupsData.setFilter(filter);
+
+ // initialize the sort
+ sortParameters({
+ columnId: 'name',
+ sortAsc: true
+ }, groupsData);
+
+ // initialize the grid
+ var groupsGrid = new Slick.Grid(parameterGroupsTable, groupsData, groupsColumn, parameterGroupsGridOptions);
+ groupsGrid.setSelectionModel(new Slick.RowSelectionModel());
+ groupsGrid.registerPlugin(new Slick.AutoTooltips());
+ groupsGrid.setSortColumn('name', true);
+ groupsGrid.onSort.subscribe(function (e, args) {
+ sortParameters({
+ columnId: args.sortCol.id,
+ sortAsc: args.sortAsc
+ }, groupsData);
+ });
+ groupsGrid.onSelectedRowsChanged.subscribe(function (e, args) {
+ // clean up tooltips
+ nfCommon.cleanUpTooltips($('#selectable-parameters-table'), 'div.fa-asterisk');
+ nfCommon.cleanUpTooltips($('#selectable-parameters-table'), 'div.fa-hashtag');
+
+ if ($.isArray(args.rows) && args.rows.length === 1) {
+ if (groupsGrid.getDataLength() > 0) {
+ var groupIndex = args.rows[0];
+ var group = groupsGrid.getDataItem(groupIndex);
+
+ // only populate fetch parameters column if this group is different than the last selected
+ if (lastSelectedGroupId === null || lastSelectedGroupId !== group.id) {
+ loadFetchedParameters(group);
+
+ // update the last selected id
+ lastSelectedGroupId = group.id;
+
+ // populate parameter referencing components
+ var selectableParametersGrid = $('#selectable-parameters-table').data('gridInstance');
+ var selectedRow = selectableParametersGrid.getSelectedRows()[0];
+ var parameter = selectableParametersGrid.getData().getItem(selectedRow);
+
+ if (parameter && group.isParameterContext) {
+ populateReferencingComponents(parameter.parameterStatus).then(function () {
+ updateReferencingComponentsBorder($('#fetch-parameter-referencing-components-container'));
+ });
+ } else {
+ // show 'None' for referencing components
+ populateReferencingComponents({}).then(function () {
+ updateReferencingComponentsBorder($('#fetch-parameter-referencing-components-container'));
+ });
+ }
+ }
+ }
+ }
+ });
+ groupsGrid.onBeforeCellEditorDestroy.subscribe(function (e, args) {
+ setTimeout(function () {
+ groupsGrid.resizeCanvas();
+ }, 50);
+ });
+
+ // wire up the dataview to the grid
+ groupsData.onRowCountChanged.subscribe(function (e, args) {
+ groupsGrid.updateRowCount();
+ groupsGrid.render();
+ });
+ groupsData.onRowsChanged.subscribe(function (e, args) {
+ groupsGrid.invalidateRows(args.rows);
+ groupsGrid.render();
+ });
+ groupsData.syncGridSelection(groupsGrid, true);
+
+ // hold onto an instance of the grid and create parameter context tooltip
+ parameterGroupsTable.data('gridInstance', groupsGrid).on('mouseenter', 'div.slick-cell', function (e) {
+ var starIconElement = $(this).find('div.fa-star');
+ var tooltipContent = nfCommon.escapeHtml('Synced to a parameter context.');
+
+ // initialize tooltip
+ starIconElement.qtip($.extend({},
+ nfCommon.config.tooltipConfig,
+ {
+ content: tooltipContent
+ }));
+ });
+ };
+ // end initParameterGroupTable
+
+ var resetUsage = function () {
+ // empty the containers
+ var fetchParameterRefComponents = $('#fetch-parameter-referencing-components-container .referencing-component-references');
+ fetchParameterRefComponents.empty();
+ var fetchParameterRefComponentsContainer = $('#fetch-parameter-referencing-components-container');
+
+ var processorContainer = $('.fetch-parameters-referencing-processors');
+ nfCommon.cleanUpTooltips(processorContainer, 'div.referencing-component-state');
+ nfCommon.cleanUpTooltips(processorContainer, 'div.referencing-component-bulletins');
+ processorContainer.empty();
+
+ var controllerServiceContainer = $('.fetch-parameters-referencing-controller-services');
+ nfCommon.cleanUpTooltips(controllerServiceContainer, 'div.referencing-component-state');
+ nfCommon.cleanUpTooltips(controllerServiceContainer, 'div.referencing-component-bulletins');
+ controllerServiceContainer.empty();
+
+ var unauthorizedComponentsContainer = $('.fetch-parameters-referencing-unauthorized-components').empty();
+
+ $('#affected-referencing-components-container').empty();
+
+ // reset the last selected
+ lastSelectedGroupId = null;
+ lastSelectedParameterId = null;
+
+ // indicate no referencing components
+ $('
None
').appendTo(fetchParameterRefComponentsContainer);
+ $('
None ').appendTo(processorContainer);
+ $('
None ').appendTo(controllerServiceContainer);
+ $('
None ').appendTo(unauthorizedComponentsContainer);
+ };
+
+ var currentParameterProviderEntity = null;
+
+ var nfParameterProvider = {
+ /**
+ * Initializes the parameter provider configuration dialog.
+ *
+ * @param options Option settings for the parameter provider.
+ */
+ init: function (options) {
+ nfSettings = options.nfSettings;
+ fetchParameterProviderOptions = options.statusBarOptions;
+
+
+ // initialize the configuration dialog tabs
+ $('#parameter-provider-configuration-tabs').tabbs({
+ tabStyle: 'tab',
+ selectedTabStyle: 'selected-tab',
+ scrollableTabContentStyle: 'scrollable',
+ tabs: [{
+ name: 'Settings',
+ tabContentId: 'parameter-provider-standard-settings-tab-content'
+ }, {
+ name: 'Properties',
+ tabContentId: 'parameter-provider-properties-tab-content'
+ }, {
+ name: 'Comments',
+ tabContentId: 'parameter-provider-comments-tab-content'
+ }],
+ select: function () {
+ // remove all property detail dialogs
+ nfUniversalCapture.removeAllPropertyDetailDialogs();
+
+ // update the property table size in case this is the first time its rendered
+ if ($(this).text() === 'Properties') {
+ $('#parameter-provider-properties').propertytable('resetTableSize');
+ }
+
+ // close all fields currently being edited
+ $('#parameter-provider-properties').propertytable('saveRow');
+ }
+ });
+
+ // initialize the parameter provider configuration dialog
+ $('#parameter-provider-configuration').data('mode', config.edit).modal({
+ scrollableContentStyle: 'scrollable',
+ headerText: 'Configure Parameter Provider',
+ handler: {
+ close: function () {
+ // cancel any active edits
+ $('#parameter-provider-properties').propertytable('cancelEdit');
+
+ // clear the tables
+ $('#parameter-provider-properties').propertytable('clear');
+
+ // clear the comments
+ nfCommon.clearField('read-only-parameter-provider-comments');
+
+ // removed the cached parameter provider details
+ $('#parameter-provider-configuration').removeData('parameterProviderDetails');
+
+ // clean up an shown verification errors
+ $('#parameter-provider-properties-verification-results').hide();
+ $('#parameter-provider-properties-verification-results-listing').css('border-width', '0').empty();
+ $('#parameter-provider-properties').css('bottom', '0');
+
+ // clean up an shown verification errors
+ $('#parameter-provider-properties-verification-results').hide();
+ $('#parameter-provider-properties-verification-results-listing').css('border-width', '0').empty();
+ $('#parameter-provider-properties').css('bottom', '0');
+
+ // clear most recently submitted referenced attributes
+ referencedAttributes = null;
+ },
+ open: function () {
+ nfCommon.toggleScrollable($('#' + this.find('.tab-container').attr('id') + '-content').get(0));
+ }
+ }
+ });
+
+ // if the status bar is supported, initialize it.
+ if (fetchParameterProviderOptions) {
+ $('#fetch-parameters-status-bar').statusbar('provider');
+ }
+
+ // initialize the property table
+ $('#parameter-provider-properties').propertytable({
+ readOnly: false,
+ supportsGoTo: true,
+ dialogContainer: '#new-parameter-provider-property-container',
+ descriptorDeferred: getParameterProviderPropertyDescriptor,
+ controllerServiceCreatedDeferred: function (response) {
+ return nfControllerServices.loadControllerServices(controllerServicesUri, $('#controller-services-table'));
+ },
+ goToServiceDeferred: goToServiceFromProperty
+ });
+
+ // initialize the fetch parameters dialog
+ $('#fetch-parameters-dialog').modal({
+ headerText: 'Fetch Parameters',
+ scrollableContentStyle: 'scrollable',
+ handler: {
+ close: function () {
+ // reset visibility
+ $('#fetch-parameters-update-status-container').hide();
+ $('#apply-groups-container').hide();
+
+ // clear the dialog
+ $('#fetch-parameters-id').text('');
+ $('#fetch-parameters-name').text('');
+ $('#fetched-parameters-listing').empty();
+ $('#fetch-parameters-update-steps').empty();
+ $('#parameter-contexts-to-create-container').empty();
+
+ // clean up tooltips
+ nfCommon.cleanUpTooltips($('#parameter-groups-table'), 'div.fa-star');
+
+ // reset progress
+ $('div.parameter-contexts-to-update').removeClass('ajax-loading ajax-complete ajax-error');
+
+ //stop any synchronization
+ if (fetchParameterProviderOptions) {
+ $('#fetch-parameters-status-bar').statusbar('disconnect');
+ }
+
+ // reset dialog
+ resetFetchParametersDialog();
+ }
+ }
+ });
+
+ initParameterGroupsTable();
+ initSelectableParametersTable();
+
+ $(window).on('resize', function (e) {
+ if ($('#affected-referencing-components-container').is(':visible')) {
+ updateReferencingComponentsBorder($('#affected-referencing-components-container'));
+ }
+
+ if ($('#fetch-parameter-referencing-components-container').is(':visible')) {
+ updateReferencingComponentsBorder($('#fetch-parameter-referencing-components-container'));
+ }
+ });
+ },
+
+ /**
+ * Shows the configuration dialog for the specified parameter provider.
+ *
+ * @argument {parameterProvider} parameterProviderEntity the parameter provider
+ */
+ showConfiguration: function (parameterProviderEntity) {
+ var parameterProviderDialog = $('#parameter-provider-configuration');
+
+ parameterProviderDialog.find('.dialog-header .dialog-header-text').text('Configure Parameter Provider');
+ if (parameterProviderDialog.data('mode') === config.readOnly) {
+ // update the visibility
+ $('#parameter-provider-configuration .parameter-provider-read-only').hide();
+ $('#parameter-provider-configuration .parameter-provider-editable').show();
+
+ // initialize the property table
+ $('#parameter-provider-properties').propertytable('destroy').propertytable({
+ readOnly: false,
+ supportsGoTo: true,
+ dialogContainer: '#new-parameter-provider-property-container',
+ descriptorDeferred: getParameterProviderPropertyDescriptor,
+ controllerServiceCreatedDeferred: function (response) {
+ return nfControllerServices.loadControllerServices(controllerServicesUri, $('#controller-services-table'));
+ },
+ goToServiceDeferred: goToServiceFromProperty
+ });
+
+ // update the mode
+ parameterProviderDialog.data('mode', config.edit);
+ }
+
+ // reload the provider in case the property descriptors have changed
+ var reloadProvider = $.ajax({
+ type: 'GET',
+ url: parameterProviderEntity.uri,
+ dataType: 'json'
+ });
+
+ // get the parameter provider history
+ var loadHistory = $.ajax({
+ type: 'GET',
+ url: '../nifi-api/flow/history/components/' + encodeURIComponent(parameterProviderEntity.id),
+ dataType: 'json'
+ });
+
+ // once everything is loaded, show the dialog
+ $.when(reloadProvider, loadHistory).done(function (providerResponse, historyResponse) {
+ // get the updated parameter provider
+ parameterProviderEntity = providerResponse[0];
+ currentParameterProviderEntity = parameterProviderEntity;
+ var parameterProvider = parameterProviderEntity.component;
+
+ // get the parameter provider history
+ var parameterProviderHistory = historyResponse[0].componentHistory;
+
+ // record the parameter provider details
+ $('#parameter-provider-configuration').data('parameterProviderDetails', parameterProviderEntity);
+
+ // populate the parameter provider settings
+ nfCommon.populateField('parameter-provider-id', parameterProvider['id']);
+
+ nfCommon.populateField('parameter-provider-type', nfCommon.formatType(parameterProvider));
+ $('#parameter-provider-configuration').modal('setSubtitle', nfCommon.formatType(parameterProvider));
+
+ nfCommon.populateField('parameter-provider-bundle', nfCommon.formatBundle(parameterProvider['bundle']));
+ $('#parameter-provider-name').val(parameterProvider['name']);
+ $('#parameter-provider-comments').val(parameterProvider['comments']);
+
+ // load referencing components for the parameter provider
+ loadParameterProviderReferencingComponents($('#parameter-provider-referencing-components'), parameterProvider);
+
+ var buttons = [{
+ buttonText: 'Apply',
+ color: {
+ base: '#728E9B',
+ hover: '#004849',
+ text: '#ffffff'
+ },
+ handler: {
+ click: function () {
+ // close all fields currently being edited
+ $('#parameter-provider-properties').propertytable('saveRow');
+
+ // save the parameter provider
+ saveParameterProvider(parameterProviderEntity).done(function (response) {
+ // reload the parameter provider
+ nfControllerService.reloadReferencedServices(getControllerServicesTable(), response.component);
+
+ // close the details panel
+ closeModal('#parameter-provider-configuration');
+ });
+ }
+ }
+ },
+ {
+ buttonText: 'Cancel',
+ color: {
+ base: '#E3E8EB',
+ hover: '#C7D2D7',
+ text: '#004849'
+ },
+ handler: {
+ click: function () {
+ closeModal('#parameter-provider-configuration');
+ }
+ }
+ }];
+
+ // determine if we should show the advanced button
+ if (nfCommon.isDefinedAndNotNull(parameterProvider.customUiUrl) && parameterProvider.customUiUrl !== '') {
+ buttons.push({
+ buttonText: 'Advanced',
+ clazz: 'fa fa-cog button-icon',
+ color: {
+ base: '#E3E8EB',
+ hover: '#C7D2D7',
+ text: '#004849'
+ },
+ handler: {
+ click: function () {
+ var openCustomUi = function () {
+ // reset state and close the dialog manually to avoid hiding the faded background
+ closeModal('#parameter-provider-configuration');
+
+ // close the settings dialog since the custom ui is also opened in the shell
+ $('#shell-close-button').click();
+
+ // show the custom ui
+ nfCustomUi.showCustomUi(parameterProviderEntity, parameterProvider.customUiUrl, true).done(function () {
+ // once the custom ui is closed, reload the parameter provider
+ nfParameterProvider.reload(parameterProviderEntity.id).done(function (response) {
+ nfControllerService.reloadReferencedServices(getControllerServicesTable(), response.parameterProvider);
+ });
+
+ // show the settings
+ nfSettings.showSettings();
+ });
+ };
+
+ // close all fields currently being edited
+ $('#parameter-provider-properties').propertytable('saveRow');
+
+ // determine if changes have been made
+ if (isSaveRequired()) {
+ // see if those changes should be saved
+ nfDialog.showYesNoDialog({
+ headerText: 'Save',
+ dialogContent: 'Save changes before opening the advanced configuration?',
+ noHandler: openCustomUi,
+ yesHandler: function () {
+ saveParameterProvider(parameterProviderEntity).done(function () {
+ // open the custom ui
+ openCustomUi();
+ });
+ }
+ });
+ } else {
+ // if there were no changes, simply open the custom ui
+ openCustomUi();
+ }
+ }
+ }
+ });
+ }
+
+ // set the button model
+ $('#parameter-provider-configuration').modal('setButtonModel', buttons);
+
+ // load the property table
+ $('#parameter-provider-properties')
+ .propertytable('setGroupId', null)
+ .propertytable('loadProperties', parameterProvider.properties, parameterProvider.descriptors, parameterProviderHistory.propertyHistory)
+ .propertytable('setPropertyVerificationCallback', function (proposedProperties) {
+ nfVerify.verify(parameterProvider['id'], parameterProviderEntity['uri'], proposedProperties, referencedAttributes, handleVerificationResults, $('#parameter-provider-properties-verification-results-listing'));
+ });
+
+ // show the details
+ $('#parameter-provider-configuration').modal('show');
+
+ $('#parameter-provider-properties').propertytable('resetTableSize');
+ }).fail(nfErrorHandler.handleAjaxError);
+ },
+
+ /**
+ * Shows the parameter provider details in a read only dialog.
+ *
+ * @param {object} parameterProviderEntity parameter provider id
+ */
+ showDetails: function (parameterProviderEntity) {
+ var parameterProviderDialog = $('#parameter-provider-configuration');
+
+ parameterProviderDialog.find('.dialog-header .dialog-header-text').text('Parameter Provider Details');
+ if (parameterProviderDialog.data('mode') === config.edit) {
+ // update the visibility
+ $('#parameter-provider-configuration .parameter-provider-read-only').show();
+ $('#parameter-provider-configuration .parameter-provider-editable').hide();
+
+ // initialize the property table
+ $('#parameter-provider-properties').propertytable('destroy').propertytable({
+ supportsGoTo: true,
+ readOnly: true
+ });
+
+ // update the mode
+ parameterProviderDialog.data('mode', config.readOnly);
+ }
+
+ // reload the provider in case the property descriptors have changed
+ var reloadProvider = $.ajax({
+ type: 'GET',
+ url: parameterProviderEntity.uri,
+ dataType: 'json'
+ });
+
+ // get the parameter provider history
+ var loadHistory = $.ajax({
+ type: 'GET',
+ url: '../nifi-api/flow/history/components/' + encodeURIComponent(parameterProviderEntity.id),
+ dataType: 'json'
+ });
+
+ // once everything is loaded, show the dialog
+ $.when(reloadProvider, loadHistory).done(function (providerResponse, historyResponse) {
+ // get the updated parameter provider
+ parameterProviderEntity = providerResponse[0];
+ var parameterProvider = parameterProviderEntity.component;
+
+ // get the parameter provider history
+ var parameterProviderHistory = historyResponse[0].componentHistory;
+
+ // populate the parameter provider settings
+ nfCommon.populateField('parameter-provider-id', parameterProvider['id']);
+ nfCommon.populateField('parameter-provider-type', nfCommon.substringAfterLast(parameterProvider['type'], '.'));
+ nfCommon.populateField('parameter-provider-bundle', nfCommon.formatBundle(parameterProvider['bundle']));
+ nfCommon.populateField('read-only-parameter-provider-name', parameterProvider['name']);
+ nfCommon.populateField('read-only-parameter-provider-comments', parameterProvider['comments']);
+
+ // load referencing components for the parameter provider
+ loadParameterProviderReferencingComponents($('#parameter-provider-referencing-components'), parameterProvider);
+
+ var buttons = [{
+ buttonText: 'Ok',
+ color: {
+ base: '#728E9B',
+ hover: '#004849',
+ text: '#ffffff'
+ },
+ handler: {
+ click: function () {
+ // hide the dialog
+ closeModal('#parameter-provider-configuration');
+ }
+ }
+ }];
+
+ // determine if we should show the advanced button
+ if (nfCommon.isDefinedAndNotNull(nfCustomUi) && nfCommon.isDefinedAndNotNull(parameterProvider.customUiUrl) && parameterProvider.customUiUrl !== '') {
+ buttons.push({
+ buttonText: 'Advanced',
+ clazz: 'fa fa-cog button-icon',
+ color: {
+ base: '#E3E8EB',
+ hover: '#C7D2D7',
+ text: '#004849'
+ },
+ handler: {
+ click: function () {
+ // reset state and close the dialog manually to avoid hiding the faded background
+ closeModal('#parameter-provider-configuration');
+
+ // close the settings dialog since the custom ui is also opened in the shell
+ $('#shell-close-button').click();
+
+ // show the custom ui
+ nfCustomUi.showCustomUi(parameterProviderEntity, parameterProvider.customUiUrl, false).done(function () {
+ nfSettings.showSettings();
+ });
+ }
+ }
+ });
+ }
+
+ // show the dialog
+ parameterProviderDialog.modal('setButtonModel', buttons).modal('show');
+
+ // load the property table
+ $('#parameter-provider-properties')
+ .propertytable('setGroupId', null)
+ .propertytable('loadProperties', parameterProvider.properties, parameterProvider.descriptors, parameterProviderHistory.propertyHistory);
+
+ // show the details
+ parameterProviderDialog.modal('show');
+
+ $('#parameter-provider-properties').propertytable('resetTableSize');
+ });
+ },
+
+ /**
+ * Show the fetch parameters dialog.
+ *
+ * @param {object} parameterProviderEntity parameter provider id
+ */
+ showFetchDialog: function (parameterProviderEntity) {
+ showFetchParametersDialog(parameterProviderEntity, fetchParameterProviderOptions);
+ },
+
+ /**
+ * Reloads the specified parameter provider.
+ *
+ * @param {string} id
+ */
+ reload: function (id) {
+ var parameterProviderGrid = $('#parameter-providers-table').data('gridInstance');
+ var parameterProviderData = parameterProviderGrid.getData();
+ var parameterProviderEntity = parameterProviderData.getItemById(id);
+
+ return $.ajax({
+ type: 'GET',
+ url: parameterProviderEntity.uri,
+ dataType: 'json'
+ }).done(function (response) {
+ renderParameterProvider(response);
+ }).fail(nfErrorHandler.handleAjaxError);
+ },
+
+ /**
+ * Prompts the user before attempting to delete the specified parameter provider.
+ *
+ * @param {object} parameterProviderEntity parameter provider id
+ */
+ promptToDeleteParameterProvider: function (parameterProviderEntity) {
+ // prompt for deletion
+ nfDialog.showYesNoDialog({
+ headerText: 'Delete Parameter Provider',
+ dialogContent: 'Delete parameter provider \'' + nfCommon.escapeHtml(parameterProviderEntity.component.name) + '\'?',
+ yesHandler: function () {
+ nfParameterProvider.remove(parameterProviderEntity);
+ }
+ });
+ },
+
+ /**
+ * Deletes the specified parameter provider.
+ *
+ * @param {object} parameterProviderEntity parameter provider id
+ */
+ remove: function (parameterProviderEntity) {
+ var revision = nfClient.getRevision(parameterProviderEntity);
+ $.ajax({
+ type: 'DELETE',
+ url: parameterProviderEntity.uri + '?' + $.param({
+ 'version': revision.version,
+ 'clientId': revision.clientId,
+ 'disconnectedNodeAcknowledged': nfStorage.isDisconnectionAcknowledged()
+ }),
+ dataType: 'json'
+ }).done(function (response) {
+ // remove the provider
+ var parameterProviderGrid = $('#parameter-providers-table').data('gridInstance');
+ var parameterProviderData = parameterProviderGrid.getData();
+ parameterProviderData.deleteItem(parameterProviderEntity.id);
+ }).fail(nfErrorHandler.handleAjaxError);
+ },
+
+ /**
+ * Shows the specified parameter provider.
+ */
+ showParameterProvider: function (parameterProviderId) {
+ // show the settings dialog
+ nfSettings.showSettings().done(function () {
+ var parameterProviderGrid = $('#parameter-providers-table').data('gridInstance');
+ var parameterProviderData = parameterProviderGrid.getData();
+
+ // select the desired provider
+ var row = parameterProviderData.getRowById(parameterProviderId);
+ parameterProviderGrid.setSelectedRows([row]);
+ parameterProviderGrid.scrollRowIntoView(row);
+
+ $('#settings-tabs').find('li:eq(4)').click();
+
+ // adjust the table size
+ nfSettings.resetTableSize();
+ });
+ }
+ };
+
+ return nfParameterProvider;
+}));
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-policy-management.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-policy-management.js
index a5874d2c07..01e699c311 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-policy-management.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-policy-management.js
@@ -1556,6 +1556,60 @@
return loadPolicy().always(showPolicy);
},
+ /**
+ * Shows the paramter provider policy.
+ *
+ * @param d
+ */
+ showParameterProviderPolicy: function (d) {
+ initializingComponentPolicy = true;
+
+ // reset the policy message
+ resetPolicyMessage();
+
+ // update the policy controls visibility
+ $('#component-policy-controls').show();
+ $('#global-policy-controls').hide();
+
+ // update the visibility
+ if (d.permissions.canRead === true) {
+ $('#policy-selected-parameter-provider-container div.policy-selected-component-name').text(d.component.name);
+ } else {
+ $('#policy-selected-parameter-provider-container div.policy-selected-component-name').text(d.id);
+ }
+ $('#policy-selected-parameter-provider-container').show();
+
+ // populate the initial resource
+ $('#selected-policy-component-id').text(d.id);
+ $('#selected-policy-component-type').text('parameter-providers');
+ $('#component-policy-target')
+ .combo('setOptionEnabled', {
+ value: 'operate-component'
+ }, false)
+ .combo('setOptionEnabled', {
+ value: 'write-receive-data'
+ }, false)
+ .combo('setOptionEnabled', {
+ value: 'write-send-data'
+ }, false)
+ .combo('setOptionEnabled', {
+ value: 'read-data'
+ }, false)
+ .combo('setOptionEnabled', {
+ value: 'read-provenance'
+ }, false)
+ .combo('setOptionEnabled', {
+ value: 'write-data'
+ }, false)
+ .combo('setSelectedOption', {
+ value: 'read-component'
+ });
+
+ initializingComponentPolicy = false;
+
+ return loadPolicy().always(showPolicy);
+ },
+
/**
* Shows the template policy.
*
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 b802c3b4b0..027f4ff27d 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
@@ -659,7 +659,7 @@
//if the status bar is supported, initialize it.
if(config.supportsStatusBar){
- $('#processor-configuration-status-bar').statusbar();
+ $('#processor-configuration-status-bar').statusbar('processor');
}
// initialize the bulletin combo
@@ -784,6 +784,7 @@
$.when.apply(window, requests).done(function (processorResult, historyResult) {
// get the updated processor'
var processorResponse = processorResult[0];
+ var bulletins = processorResponse.bulletins;
processor = processorResponse.component;
// get the processor history
@@ -1047,10 +1048,20 @@
//Synchronize the current component canvas attributes in the status bar
if(config.supportsStatusBar){
+ var formattedBulletins = nfCommon.getFormattedBulletins(bulletins);
+ var unorderedBulletins = nfCommon.formatUnorderedList(formattedBulletins);
+
//initialize the canvas synchronization
- $("#processor-configuration-status-bar").statusbar('observe',processor.id, function(){
- $('#processor-configuration').modal('refreshButtons');
- });
+ $("#processor-configuration-status-bar").statusbar(
+ 'observe',
+ {
+ processor: processor.id,
+ bulletins: unorderedBulletins
+ },
+ function () {
+ $('#processor-configuration').modal('refreshButtons');
+ }
+ );
//if there are active threads, add the terminate button to the status bar
if(nfCommon.isDefinedAndNotNull(config.nfActions) &&
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-settings.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-settings.js
index a602335a57..0c5ef6acbc 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-settings.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-settings.js
@@ -34,9 +34,10 @@
'nf.Shell',
'nf.ComponentState',
'nf.ComponentVersion',
- 'nf.PolicyManagement'],
- function ($, Slick, d3, nfClient, nfDialog, nfStorage, nfCommon, nfCanvasUtils, nfControllerServices, nfErrorHandler, nfFilteredDialogCommon, nfReportingTask, nfShell, nfComponentState, nfComponentVersion, nfPolicyManagement) {
- return (nf.Settings = factory($, Slick, d3, nfClient, nfDialog, nfStorage, nfCommon, nfCanvasUtils, nfControllerServices, nfErrorHandler, nfFilteredDialogCommon, nfReportingTask, nfShell, nfComponentState, nfComponentVersion, nfPolicyManagement));
+ 'nf.PolicyManagement',
+ 'nf.ParameterProvider'],
+ function ($, Slick, d3, nfClient, nfDialog, nfStorage, nfCommon, nfCanvasUtils, nfControllerServices, nfErrorHandler, nfFilteredDialogCommon, nfReportingTask, nfShell, nfComponentState, nfComponentVersion, nfPolicyManagement, nfParameterProvider) {
+ return (nf.Settings = factory($, Slick, d3, nfClient, nfDialog, nfStorage, nfCommon, nfCanvasUtils, nfControllerServices, nfErrorHandler, nfFilteredDialogCommon, nfReportingTask, nfShell, nfComponentState, nfComponentVersion, nfPolicyManagement, nfParameterProvider));
});
} else if (typeof exports === 'object' && typeof module === 'object') {
module.exports = (nf.Settings =
@@ -55,7 +56,8 @@
require('nf.Shell'),
require('nf.ComponentState'),
require('nf.ComponentVersion'),
- require('nf.PolicyManagement')));
+ require('nf.PolicyManagement'),
+ require('nf.ParameterProvider')));
} else {
nf.Settings = factory(root.$,
root.Slick,
@@ -72,9 +74,10 @@
root.nf.Shell,
root.nf.ComponentState,
root.nf.ComponentVersion,
- root.nf.PolicyManagement);
+ root.nf.PolicyManagement,
+ root.nf.ParameterProvider);
}
-}(this, function ($, Slick, d3, nfClient, nfDialog, nfStorage, nfCommon, nfCanvasUtils, nfControllerServices, nfErrorHandler, nfFilteredDialogCommon, nfReportingTask, nfShell, nfComponentState, nfComponentVersion, nfPolicyManagement) {
+}(this, function ($, Slick, d3, nfClient, nfDialog, nfStorage, nfCommon, nfCanvasUtils, nfControllerServices, nfErrorHandler, nfFilteredDialogCommon, nfReportingTask, nfShell, nfComponentState, nfComponentVersion, nfPolicyManagement, nfParameterProvider) {
'use strict';
@@ -85,7 +88,10 @@
reportingTaskTypes: '../nifi-api/flow/reporting-task-types',
createReportingTask: '../nifi-api/controller/reporting-tasks',
reportingTasks: '../nifi-api/flow/reporting-tasks',
- registries: '../nifi-api/controller/registry-clients'
+ registries: '../nifi-api/controller/registry-clients',
+ createParameterProvider: '../nifi-api/controller/parameter-providers',
+ parameterProviderTypes: '../nifi-api/flow/parameter-provider-types',
+ parameterProviders: '../nifi-api/flow/parameter-providers'
}
};
@@ -345,6 +351,15 @@
return $('#reporting-task-type-filter').val();
};
+ /**
+ * Get the text out of the filter field. If the filter field doesn't
+ * have any text it will contain the text 'filter list' so this method
+ * accounts for that.
+ */
+ var getParameterProviderTypeFilterText = function () {
+ return $('#parameter-provider-type-filter').val();
+ };
+
/**
* Filters the reporting task type table.
*/
@@ -372,6 +387,33 @@
}
};
+ /**
+ * Filters the parameter provider type table.
+ */
+ var applyParameterProviderTypeFilter = function () {
+ // get the dataview
+ var parameterProviderTypesGrid = $('#parameter-provider-types-table').data('gridInstance');
+
+ // ensure the grid has been initialized
+ if (nfCommon.isDefinedAndNotNull(parameterProviderTypesGrid)) {
+ var parameterProviderTypesData = parameterProviderTypesGrid.getData();
+
+ // update the search criteria
+ parameterProviderTypesData.setFilterArgs({
+ searchString: getParameterProviderTypeFilterText()
+ });
+ parameterProviderTypesData.refresh();
+
+ // update the buttons to possibly trigger the disabled state
+ $('#new-parameter-provider-dialog').modal('refreshButtons');
+
+ // update the selection if possible
+ if (parameterProviderTypesData.getLength() > 0) {
+ nfFilteredDialogCommon.choseFirstRow(parameterProviderTypesGrid);
+ }
+ }
+ };
+
/**
* Hides the selected reporting task.
*/
@@ -384,6 +426,18 @@
$('#reporting-task-description-container').hide();
};
+ /**
+ * Hides the selected parameter provider.
+ */
+ var clearSelectedParameterProvider = function () {
+ $('#parameter-provider-type-description').attr('title', '').text('');
+ $('#parameter-provider-type-name').attr('title', '').text('');
+ $('#parameter-provider-type-bundle').attr('title', '').text('');
+ $('#selected-parameter-provider-name').text('');
+ $('#selected-parameter-provider-type').text('').removeData('bundle');
+ $('#parameter-provider-description-container').hide();
+ };
+
/**
* Clears the selected reporting task type.
*/
@@ -396,6 +450,18 @@
reportingTaskTypesGrid.resetActiveCell();
};
+ /**
+ * Clears the selected parameter provider type.
+ */
+ var clearParameterProviderSelection = function () {
+ // clear the selected row
+ clearSelectedParameterProvider();
+
+ // clear the active cell then it can be reselected when its included
+ var parameterProviderTypesGrid = $('#parameter-provider-types-table').data('gridInstance');
+ parameterProviderTypesGrid.resetActiveCell();
+ };
+
/**
* Performs the filtering.
*
@@ -437,6 +503,47 @@
return matches;
};
+ /**
+ * Performs the filtering.
+ *
+ * @param {object} item The item subject to filtering
+ * @param {object} args Filter arguments
+ * @returns {Boolean} Whether or not to include the item
+ */
+ var filterParameterProviderTypes = function (item, args) {
+ // determine if the item matches the filter
+ var matchesFilter = matchesRegex(item, args);
+
+ // determine if the row matches the selected tags
+ var matchesTags = true;
+ if (matchesFilter) {
+ var tagFilters = $('#parameter-provider-tag-cloud').tagcloud('getSelectedTags');
+ var hasSelectedTags = tagFilters.length > 0;
+ if (hasSelectedTags) {
+ matchesTags = matchesSelectedTags(tagFilters, item['tags']);
+ }
+ }
+
+ // determine if the row matches the selected source group
+ var matchesGroup = true;
+ if (matchesFilter && matchesTags) {
+ var bundleGroup = $('#parameter-provider-bundle-group-combo').combo('getSelectedOption');
+ if (nfCommon.isDefinedAndNotNull(bundleGroup) && bundleGroup.value !== '') {
+ matchesGroup = (item.bundle.group === bundleGroup.value);
+ }
+ }
+
+ // determine if this row should be visible
+ var matches = matchesFilter && matchesTags && matchesGroup;
+
+ // if this row is currently selected and its being filtered
+ if (matches === false && $('#selected-parameter-provider-type').text() === item['type']) {
+ clearParameterProviderSelection();
+ }
+
+ return matches;
+ };
+
/**
* Adds the currently selected reporting task.
*/
@@ -455,6 +562,24 @@
}
};
+ /**
+ * Adds the currently selected parameter provider.
+ */
+ var addSelectedParameterProvider = function () {
+ var selectedParameterProviderType = $('#selected-parameter-provider-type').text();
+ var selectedParameterProviderBundle = $('#selected-selected-parameter-type').data('bundle');
+
+ // ensure something was selected
+ if (selectedParameterProviderType === '') {
+ nfDialog.showOkDialog({
+ headerText: 'Settings',
+ dialogContent: 'The type of parameter provider to create must be selected.'
+ });
+ } else {
+ addParameterProvider(selectedParameterProviderType, selectedParameterProviderBundle);
+ }
+ };
+
/**
* Adds a new reporting task of the specified type.
*
@@ -558,6 +683,59 @@
return addRegistry;
};
+ /**
+ * Adds a new parameter provider of the specified type.
+ *
+ * @param {string} parameterProviderType
+ * @param {object} parameterProviderBundle
+ */
+ var addParameterProvider = function (parameterProviderType, parameterProviderBundle) {
+ // build the parameter provider entity
+ var parameterProviderEntity = {
+ 'revision': nfClient.getRevision({
+ 'revision': {
+ 'version': 0
+ }
+ }),
+ 'disconnectedNodeAcknowledged': nfStorage.isDisconnectionAcknowledged(),
+ 'component': {
+ 'type': parameterProviderType,
+ 'bundle': parameterProviderBundle
+ }
+ };
+
+ // add the new parameter provider
+ var addProvider = $.ajax({
+ type: 'POST',
+ url: config.urls.createParameterProvider,
+ data: JSON.stringify(parameterProviderEntity),
+ dataType: 'json',
+ contentType: 'application/json'
+ }).done(function (parameterProviderEntity) {
+ // add the item
+ var parameterProviderGrid = $('#parameter-providers-table').data('gridInstance');
+ var parameterProviderData = parameterProviderGrid.getData();
+ parameterProviderData.addItem($.extend({
+ type: 'ParameterProvider',
+ bulletins: []
+ }, parameterProviderEntity));
+
+ // resort
+ parameterProviderData.reSort();
+ parameterProviderGrid.invalidate();
+
+ // select the new parameter provider
+ var row = parameterProviderData.getRowById(parameterProviderEntity.id);
+ nfFilteredDialogCommon.choseRow(parameterProviderGrid, row);
+ parameterProviderGrid.scrollRowIntoView(row);
+ }).fail(nfErrorHandler.handleAjaxError);
+
+ // hide the dialog
+ $('#new-parameter-provider-dialog').modal('hide');
+
+ return addProvider;
+ };
+
/**
* Updates the registry with the specified id.
*
@@ -1001,6 +1179,395 @@
});
};
+ /**
+ * Initializes the new parameter provider dialog.
+ */
+ var initNewParameterProviderDialog = function () {
+ // initialize the parameter provider type table
+ var parameterProviderColumns = [
+ {
+ id: 'type',
+ name: 'Type',
+ field: 'label',
+ formatter: nfCommon.typeFormatter,
+ sortable: true,
+ resizable: true
+ },
+ {
+ id: 'version',
+ name: 'Version',
+ field: 'version',
+ formatter: nfCommon.typeVersionFormatter,
+ sortable: true,
+ resizable: true
+ },
+ {
+ id: 'tags',
+ name: 'Tags',
+ field: 'tags',
+ sortable: true,
+ resizable: true,
+ formatter: nfCommon.genericValueFormatter
+ }
+ ];
+
+ // initialize the dataview
+ var parameterProviderTypesData = new Slick.Data.DataView({
+ inlineFilters: false
+ });
+ parameterProviderTypesData.setItems([]);
+ parameterProviderTypesData.setFilterArgs({
+ searchString: getParameterProviderTypeFilterText()
+ });
+ parameterProviderTypesData.setFilter(filterParameterProviderTypes);
+
+ // initialize the sort
+ nfCommon.sortType({
+ columnId: 'type',
+ sortAsc: true
+ }, parameterProviderTypesData);
+
+ // initialize the grid
+ var parameterProviderTypesGrid = new Slick.Grid('#parameter-provider-types-table', parameterProviderTypesData, parameterProviderColumns, gridOptions);
+ parameterProviderTypesGrid.setSelectionModel(new Slick.RowSelectionModel());
+ parameterProviderTypesGrid.registerPlugin(new Slick.AutoTooltips());
+ parameterProviderTypesGrid.setSortColumn('type', true);
+ parameterProviderTypesGrid.onSort.subscribe(function (e, args) {
+ nfCommon.sortType({
+ columnId: args.sortCol.field,
+ sortAsc: args.sortAsc
+ }, parameterProviderTypesData);
+ });
+ parameterProviderTypesGrid.onSelectedRowsChanged.subscribe(function (e, args) {
+ if ($.isArray(args.rows) && args.rows.length === 1) {
+ var parameterProviderTypeIndex = args.rows[0];
+ var parameterProviderType = parameterProviderTypesGrid.getDataItem(parameterProviderTypeIndex);
+
+ // set the parameter provider type description
+ if (nfCommon.isDefinedAndNotNull(parameterProviderType)) {
+ // show the selected parameter provider
+ $('#parameter-provider-description-container').show();
+
+ if (nfCommon.isBlank(parameterProviderType.description)) {
+ $('#parameter-provider-type-description')
+ .attr('title', '')
+ .html('
No description specified ');
+ } else {
+ $('#parameter-provider-type-description')
+ .width($('#parameter-provider-description-container').innerWidth() - 1)
+ .html(parameterProviderType.description)
+ .ellipsis();
+ }
+
+ var bundle = nfCommon.formatBundle(parameterProviderType.bundle);
+ var type = nfCommon.formatType(parameterProviderType);
+
+ // populate the dom
+ $('#parameter-provider-type-name').text(type).attr('title', type);
+ $('#parameter-provider-type-bundle').text(bundle).attr('title', bundle);
+ $('#selected-parameter-provider-name').text(parameterProviderType.label);
+ $('#selected-parameter-provider-type').text(parameterProviderType.type).data('bundle', parameterProviderType.bundle);
+
+ // refresh the buttons based on the current selection
+ $('#new-parameter-provider-dialog').modal('refreshButtons');
+ }
+ }
+ });
+ parameterProviderTypesGrid.onDblClick.subscribe(function (e, args) {
+ var parameterProviderType = parameterProviderTypesGrid.getDataItem(args.row);
+
+ if (isSelectable(parameterProviderType)) {
+ addParameterProvider(parameterProviderType.type, parameterProviderType.bundle);
+ }
+ });
+ parameterProviderTypesGrid.onViewportChanged.subscribe(function (e, args) {
+ nfCommon.cleanUpTooltips($('#parameter-provider-types-table'), 'div.view-usage-restriction');
+ });
+
+ // wire up the dataview to the grid
+ parameterProviderTypesData.onRowCountChanged.subscribe(function (e, args) {
+ parameterProviderTypesGrid.updateRowCount();
+ parameterProviderTypesGrid.render();
+
+ // update the total number of displayed processors
+ $('#displayed-parameter-provider-types').text(args.current);
+ });
+ parameterProviderTypesData.onRowsChanged.subscribe(function (e, args) {
+ parameterProviderTypesGrid.invalidateRows(args.rows);
+ parameterProviderTypesGrid.render();
+ });
+ parameterProviderTypesData.syncGridSelection(parameterProviderTypesGrid, true);
+
+ // hold onto an instance of the grid
+ $('#parameter-provider-types-table').data('gridInstance', parameterProviderTypesGrid).on('mouseenter', 'div.slick-cell', function (e) {
+ var usageRestriction = $(this).find('div.view-usage-restriction');
+ if (usageRestriction.length && !usageRestriction.data('qtip')) {
+ var rowId = $(this).find('span.row-id').text();
+
+ // get the status item
+ var item = parameterProviderTypesData.getItemById(rowId);
+
+ // show the tooltip
+ if (item.restricted === true) {
+ var restrictionTip = $('
');
+
+ if (nfCommon.isBlank(item.usageRestriction)) {
+ restrictionTip.append($('
').text('Requires the following permissions:'));
+ } else {
+ restrictionTip.append($('
').text(item.usageRestriction + ' Requires the following permissions:'));
+ }
+
+ var restrictions = [];
+ if (nfCommon.isDefinedAndNotNull(item.explicitRestrictions)) {
+ $.each(item.explicitRestrictions, function (_, explicitRestriction) {
+ var requiredPermission = explicitRestriction.requiredPermission;
+ restrictions.push("'" + requiredPermission.label + "' - " + nfCommon.escapeHtml(explicitRestriction.explanation));
+ });
+ } else {
+ restrictions.push('Access to restricted components regardless of restrictions.');
+ }
+ restrictionTip.append(nfCommon.formatUnorderedList(restrictions));
+
+ usageRestriction.qtip($.extend({}, nfCommon.config.tooltipConfig, {
+ content: restrictionTip,
+ position: {
+ container: $('#summary'),
+ at: 'bottom right',
+ my: 'top left',
+ adjust: {
+ x: 4,
+ y: 4
+ }
+ }
+ }));
+ }
+ }
+ });
+
+ var generalRestriction = nfCommon.getPolicyTypeListing('restricted-components');
+
+ // load the available parameter providers
+ $.ajax({
+ type: 'GET',
+ url: config.urls.parameterProviderTypes,
+ dataType: 'json'
+ }).done(function (response) {
+ var id = 0;
+ var tags = [];
+ var groups = d3.set();
+ var restrictedUsage = d3.map();
+ var requiredPermissions = d3.map();
+
+ // begin the update
+ parameterProviderTypesData.beginUpdate();
+
+ // go through each parameter provider type
+ $.each(response.parameterProviderTypes, function (i, documentedType) {
+ if (documentedType.restricted === true) {
+ if (nfCommon.isDefinedAndNotNull(documentedType.explicitRestrictions)) {
+ $.each(documentedType.explicitRestrictions, function (_, explicitRestriction) {
+ var requiredPermission = explicitRestriction.requiredPermission;
+
+ // update required permissions
+ if (!requiredPermissions.has(requiredPermission.id)) {
+ requiredPermissions.set(requiredPermission.id, requiredPermission.label);
+ }
+
+ // update component restrictions
+ if (!restrictedUsage.has(requiredPermission.id)) {
+ restrictedUsage.set(requiredPermission.id, []);
+ }
+
+ restrictedUsage.get(requiredPermission.id).push({
+ type: nfCommon.formatType(documentedType),
+ bundle: nfCommon.formatBundle(documentedType.bundle),
+ explanation: nfCommon.escapeHtml(explicitRestriction.explanation)
+ })
+ });
+ } else {
+ // update required permissions
+ if (!requiredPermissions.has(generalRestriction.value)) {
+ requiredPermissions.set(generalRestriction.value, generalRestriction.text);
+ }
+
+ // update component restrictions
+ if (!restrictedUsage.has(generalRestriction.value)) {
+ restrictedUsage.set(generalRestriction.value, []);
+ }
+
+ restrictedUsage.get(generalRestriction.value).push({
+ type: nfCommon.formatType(documentedType),
+ bundle: nfCommon.formatBundle(documentedType.bundle),
+ explanation: nfCommon.escapeHtml(documentedType.usageRestriction)
+ });
+ }
+ }
+
+ // record the group
+ groups.add(documentedType.bundle.group);
+
+ // add the documented type
+ parameterProviderTypesData.addItem({
+ id: id++ + '',
+ label: nfCommon.substringAfterLast(documentedType.type, '.'),
+ type: documentedType.type,
+ bundle: documentedType.bundle,
+ description: nfCommon.escapeHtml(documentedType.description),
+ restricted: documentedType.restricted,
+ usageRestriction: nfCommon.escapeHtml(documentedType.usageRestriction),
+ explicitRestrictions: documentedType.explicitRestrictions,
+ tags: documentedType.tags.join(', ')
+ });
+
+ // count the frequency of each tag for this type
+ $.each(documentedType.tags, function (i, tag) {
+ tags.push(tag.toLowerCase());
+ });
+ });
+
+ // end the update
+ parameterProviderTypesData.endUpdate();
+
+ // resort
+ parameterProviderTypesData.reSort();
+ parameterProviderTypesGrid.invalidate();
+
+ // set the component restrictions and the corresponding required permissions
+ nfCanvasUtils.addComponentRestrictions(restrictedUsage, requiredPermissions);
+
+ // set the total number of processors
+ $('#total-parameter-provider-types, #displayed-parameter-provider-types').text(response.parameterProviderTypes.length);
+
+ // create the tag cloud
+ $('#parameter-provider-tag-cloud').tagcloud({
+ tags: tags,
+ select: applyParameterProviderTypeFilter,
+ remove: applyParameterProviderTypeFilter
+ });
+
+ // build the combo options
+ var options = [{
+ text: 'all groups',
+ value: ''
+ }];
+ groups.each(function (group) {
+ options.push({
+ text: group,
+ value: group
+ });
+ });
+
+ // initialize the bundle group combo
+ $('#parameter-provider-bundle-group-combo').combo({
+ options: options,
+ select: applyParameterProviderTypeFilter
+ });
+ }).fail(nfErrorHandler.handleAjaxError);
+
+ var navigationKeys = [$.ui.keyCode.UP, $.ui.keyCode.PAGE_UP, $.ui.keyCode.DOWN, $.ui.keyCode.PAGE_DOWN];
+
+ // define the function for filtering the list
+ $('#parameter-provider-type-filter').off('keyup').on('keyup', function (e) {
+ var code = e.keyCode ? e.keyCode : e.which;
+
+ // ignore navigation keys
+ if ($.inArray(code, navigationKeys) !== -1) {
+ return;
+ }
+
+ if (code === $.ui.keyCode.ENTER) {
+ var selected = parameterProviderTypesGrid.getSelectedRows();
+
+ if (selected.length > 0) {
+ // grid configured with multi-select = false
+ var item = parameterProviderTypesGrid.getDataItem(selected[0]);
+ if (isSelectable(item)) {
+ addSelectedParameterProvider();
+ }
+ }
+ } else {
+ applyParameterProviderTypeFilter();
+ }
+ });
+
+ // setup row navigation
+ nfFilteredDialogCommon.addKeydownListener('#parameter-provider-type-filter', parameterProviderTypesGrid, parameterProviderTypesGrid.getData());
+
+ // initialize the parameter provider dialog
+ $('#new-parameter-provider-dialog').modal({
+ scrollableContentStyle: 'scrollable',
+ headerText: 'Add Parameter Provider',
+ buttons: [{
+ buttonText: 'Add',
+ color: {
+ base: '#728E9B',
+ hover: '#004849',
+ text: '#ffffff'
+ },
+ disabled: function () {
+ var selected = parameterProviderTypesGrid.getSelectedRows();
+
+ if (selected.length > 0) {
+ // grid configured with multi-select = false
+ var item = parameterProviderTypesGrid.getDataItem(selected[0]);
+ return isSelectable(item) === false;
+ } else {
+ return parameterProviderTypesGrid.getData().getLength() === 0;
+ }
+ },
+ handler: {
+ click: function () {
+ addSelectedParameterProvider();
+ }
+ }
+ },
+ {
+ buttonText: 'Cancel',
+ color: {
+ base: '#E3E8EB',
+ hover: '#C7D2D7',
+ text: '#004849'
+ },
+ handler: {
+ click: function () {
+ $(this).modal('hide');
+ }
+ }
+ }],
+ handler: {
+ close: function () {
+ // clear the selected row
+ clearSelectedParameterProvider();
+
+ // clear any filter strings
+ $('#parameter-provider-type-filter').val('');
+
+ // clear the tagcloud
+ $('#parameter-provider-tag-cloud').tagcloud('clearSelectedTags');
+
+ // reset the group combo
+ $('#parameter-provider-bundle-group-combo').combo('setSelectedOption', {
+ value: ''
+ });
+
+ // reset the filter
+ applyParameterProviderTypeFilter();
+
+ // unselect any current selection
+ var parameterProviderTypesGrid = $('#parameter-provider-types-table').data('gridInstance');
+ parameterProviderTypesGrid.setSelectedRows([]);
+ parameterProviderTypesGrid.resetActiveCell();
+ },
+ resize: function () {
+ $('#parameter-provider-type-description')
+ .width($('#parameter-provider-description-container').innerWidth() - 1)
+ .text($('#parameter-provider-type-description').attr('title'))
+ .ellipsis();
+ }
+ }
+ });
+ };
+
/**
* Initializes the reporting tasks tab.
*/
@@ -1458,6 +2025,263 @@
$('#registries-table').data('gridInstance', registriesGrid);
};
+ /**
+ * Initializes the parameter providers tab.
+ */
+ var initParameterProvidersTable = function () {
+ // initialize the new parameter provider dialog
+ initNewParameterProviderDialog();
+
+ var moreParameterProvidersDetails = function (row, cell, value, columnDef, dataContext) {
+ if (!dataContext.permissions.canRead) {
+ return '';
+ }
+
+ var markup = '
';
+
+ // always include a button to view the usage
+ markup += '
';
+
+ var hasErrors = !nfCommon.isEmpty(dataContext.component.validationErrors);
+ var hasBulletins = !nfCommon.isEmpty(dataContext.bulletins);
+
+ if (hasErrors) {
+ markup += '
';
+ }
+
+ if (hasBulletins) {
+ markup += '
';
+ }
+
+ if (hasErrors || hasBulletins) {
+ markup += '
' + nfCommon.escapeHtml(dataContext.component.id) + ' ';
+ }
+
+ return markup;
+ };
+
+ var parameterProvidersActionFormatter = function (row, cell, value, columnDef, dataContext) {
+ var markup = '';
+
+ var canWrite = dataContext.permissions.canWrite;
+ var canRead = dataContext.permissions.canRead;
+
+ var hasErrors = canRead ? !nfCommon.isEmpty(dataContext.component.validationErrors) : null;
+
+ var hasReadParameterContextsPermissions = true;
+
+ if (canRead && dataContext.component.referencingParameterContexts) {
+ (dataContext.component.referencingParameterContexts).every(function (refParamContext) {
+ return hasReadParameterContextsPermissions = refParamContext.permissions.canRead;
+ });
+ }
+
+ if (canRead && canWrite) {
+ markup += '
';
+
+ if (hasReadParameterContextsPermissions && !hasErrors) {
+ markup += '
';
+ }
+ }
+
+ if (canRead && canWrite && nfCommon.canModifyController()) {
+ markup += '
';
+ }
+
+ // allow policy configuration conditionally
+ if (nfCanvasUtils.isManagedAuthorizer() && nfCommon.canAccessTenants()) {
+ markup += '
';
+ }
+
+ return markup;
+ };
+
+ // define the column model for the parameter providers table
+ var parameterProvidersColumnModel = [
+ {
+ id: 'moreDetails',
+ name: ' ',
+ resizable: false,
+ formatter: moreParameterProvidersDetails,
+ sortable: true,
+ width: 90,
+ maxWidth: 90,
+ toolTip: 'Sorts based on presence of bulletins'
+ },
+ {
+ id: 'name',
+ name: 'Name',
+ sortable: true,
+ resizable: true,
+ formatter: nameFormatter
+ },
+ {
+ id: 'type',
+ name: 'Type',
+ formatter: nfCommon.instanceTypeFormatter,
+ sortable: true,
+ resizable: true
+ },
+ {
+ id: 'bundle',
+ name: 'Bundle',
+ formatter: nfCommon.instanceBundleFormatter,
+ sortable: true,
+ resizable: true
+ }
+ ];
+
+ // action column should always be last
+ parameterProvidersColumnModel.push({
+ id: 'actions',
+ name: ' ',
+ resizable: false,
+ formatter: parameterProvidersActionFormatter,
+ sortable: false,
+ width: 115,
+ maxWidth: 115
+ });
+
+ // initialize the dataview
+ var parameterProvidersData = new Slick.Data.DataView({
+ inlineFilters: false
+ });
+ parameterProvidersData.setItems([]);
+
+ // initialize the sort
+ sort({
+ columnId: 'name',
+ sortAsc: true
+ }, parameterProvidersData);
+
+ // initialize the grid
+ var parameterProvidersGrid = new Slick.Grid('#parameter-providers-table', parameterProvidersData, parameterProvidersColumnModel, gridOptions);
+ parameterProvidersGrid.setSelectionModel(new Slick.RowSelectionModel());
+ parameterProvidersGrid.registerPlugin(new Slick.AutoTooltips());
+ parameterProvidersGrid.setSortColumn('name', true);
+ parameterProvidersGrid.onSort.subscribe(function (e, args) {
+ sort({
+ columnId: args.sortCol.id,
+ sortAsc: args.sortAsc
+ }, parameterProvidersData);
+ });
+
+ // configure a click listener
+ parameterProvidersGrid.onClick.subscribe(function (e, args) {
+ var target = $(e.target);
+
+ // get the service at this row
+ var parameterProviderEntity = parameterProvidersData.getItem(args.row);
+
+ // determine the desired action
+ if (parameterProvidersGrid.getColumns()[args.cell].id === 'actions') {
+ if (target.hasClass('edit-parameter-provider')) {
+ nfParameterProvider.showConfiguration(parameterProviderEntity);
+ } else if (target.hasClass('fetch-parameter-provider')) {
+ nfParameterProvider.showFetchDialog(parameterProviderEntity);
+ } else if (target.hasClass('delete-parameter-provider')) {
+ nfParameterProvider.promptToDeleteParameterProvider(parameterProviderEntity);
+ } else if (target.hasClass('edit-access-policies')) {
+ // show the policies for this service
+ nfPolicyManagement.showParameterProviderPolicy(parameterProviderEntity);
+
+ // close the settings dialog
+ $('#shell-close-button').click();
+ }
+ } else if (parameterProvidersGrid.getColumns()[args.cell].id === 'moreDetails') {
+ if (target.hasClass('view-parameter-provider')) {
+ nfParameterProvider.showDetails(parameterProviderEntity);
+ } else if (target.hasClass('parameter-provider-usage')) {
+ // close the settings dialog
+ $('#shell-close-button').click();
+
+ // open the documentation for this parameter provider
+ nfShell.showPage('../nifi-docs/documentation?' + $.param({
+ select: parameterProviderEntity.component.type,
+ group: parameterProviderEntity.component.bundle.group,
+ artifact: parameterProviderEntity.component.bundle.artifact,
+ version: parameterProviderEntity.component.bundle.version
+ })).done(function () {
+ nfSettings.showSettings();
+ });
+ }
+ }
+ });
+
+ // wire up the dataview to the grid
+ parameterProvidersData.onRowCountChanged.subscribe(function (e, args) {
+ parameterProvidersGrid.updateRowCount();
+ parameterProvidersGrid.render();
+ });
+ parameterProvidersData.onRowsChanged.subscribe(function (e, args) {
+ parameterProvidersGrid.invalidateRows(args.rows);
+ parameterProvidersGrid.render();
+ });
+ parameterProvidersData.syncGridSelection(parameterProvidersGrid, true);
+
+ // hold onto an instance of the grid
+ $('#parameter-providers-table').data('gridInstance', parameterProvidersGrid).on('mouseenter', 'div.slick-cell', function (e) {
+ var errorIcon = $(this).find('div.has-errors');
+ if (errorIcon.length && !errorIcon.data('qtip')) {
+ var providerId = $(this).find('span.row-id').text();
+
+ // get the provider item
+ var providerEntity = parameterProvidersData.getItemById(providerId);
+
+ // format the errors
+ var tooltip = nfCommon.formatUnorderedList(providerEntity.component.validationErrors);
+
+ // show the tooltip
+ if (nfCommon.isDefinedAndNotNull(tooltip)) {
+ errorIcon.qtip($.extend({},
+ nfCommon.config.tooltipConfig,
+ {
+ content: tooltip,
+ position: {
+ target: 'mouse',
+ viewport: $('#shell-container'),
+ adjust: {
+ x: 8,
+ y: 8,
+ method: 'flipinvert flipinvert'
+ }
+ }
+ }));
+ }
+ }
+
+ var bulletinIcon = $(this).find('div.has-bulletins');
+ if (bulletinIcon.length && !bulletinIcon.data('qtip')) {
+ var providerId = $(this).find('span.row-id').text();
+
+ // get the provider item
+ var parameterProviderEntity = parameterProvidersData.getItemById(providerId);
+
+ // format the tooltip
+ var bulletins = nfCommon.getFormattedBulletins(parameterProviderEntity.bulletins);
+ var tooltip = nfCommon.formatUnorderedList(bulletins);
+
+ // show the tooltip
+ if (nfCommon.isDefinedAndNotNull(tooltip)) {
+ bulletinIcon.qtip($.extend({},
+ nfCommon.config.tooltipConfig,
+ {
+ content: tooltip,
+ position: {
+ target: 'mouse',
+ viewport: $('#shell-container'),
+ adjust: {
+ x: 8,
+ y: 8,
+ method: 'flipinvert flipinvert'
+ }
+ }
+ }));
+ }
+ }
+ });
+ };
+
/**
* Edits the specified registry entity.
*
@@ -1608,8 +2432,11 @@
// load the registries
var registries = loadRegistries();
+ // load the parameter providers
+ var parameterProviders = loadParameterProviders();
+
// return a deferred for all parts of the settings
- return $.when(settings, controllerServicesXhr, reportingTasks).done(function (settingsResult, controllerServicesResult) {
+ return $.when(settings, controllerServicesXhr, reportingTasks, parameterProviders).done(function (settingsResult, controllerServicesResult) {
var controllerServicesResponse = controllerServicesResult[0];
// update the current time
@@ -1674,6 +2501,37 @@
});
};
+ /**
+ * Loads the parameter providers.
+ */
+ var loadParameterProviders = function () {
+ return $.ajax({
+ type: 'GET',
+ url: config.urls.parameterProviders,
+ dataType: 'json'
+ }).done(function (response) {
+ var providers = [];
+ $.each(response.parameterProviders, function (_, provider) {
+ providers.push($.extend({
+ type: 'ParameterProvider',
+ bulletins: []
+ }, provider));
+ });
+
+ var parameterProvidersElement = $('#parameter-providers-table');
+ nfCommon.cleanUpTooltips(parameterProvidersElement, 'div.has-errors');
+ nfCommon.cleanUpTooltips(parameterProvidersElement, 'div.has-bulletins');
+
+ var parameterProvidersGrid = parameterProvidersElement.data('gridInstance');
+ var parameterProvidersData = parameterProvidersGrid.getData();
+
+ // update the parameter providers
+ parameterProvidersData.setItems(providers);
+ parameterProvidersData.reSort();
+ parameterProvidersGrid.invalidate();
+ });
+ };
+
/**
* Shows the process group configuration.
*/
@@ -1712,7 +2570,7 @@
name: 'General',
tabContentId: 'general-settings-tab-content'
}, {
- name: 'Reporting Task Controller Services',
+ name: 'Management Controller Services',
tabContentId: 'controller-services-tab-content'
}, {
name: 'Reporting Tasks',
@@ -1720,6 +2578,9 @@
}, {
name: 'Registry Clients',
tabContentId: 'registries-tab-content'
+ }, {
+ name: 'Parameter Providers',
+ tabContentId: 'parameter-providers-tab-content'
}],
select: function () {
var tab = $(this).text();
@@ -1740,15 +2601,18 @@
// update the tooltip on the button
$('#new-service-or-task').attr('title', function () {
- if (tab === 'Reporting Task Controller Services') {
+ if (tab === 'Management Controller Services') {
$('#settings-save').hide();
- return 'Create a new reporting task controller service';
+ return 'Create a new controller level controller service';
} else if (tab === 'Reporting Tasks') {
$('#settings-save').hide();
return 'Create a new reporting task';
} else if (tab === 'Registry Clients') {
$('#settings-save').hide();
return 'Register a new registry client';
+ } else if (tab === 'Parameter Providers') {
+ $('#settings-save').hide();
+ return 'Add a new parameter provider';
}
});
} else {
@@ -1756,9 +2620,9 @@
$('div.controller-settings-table').css('top', '0');
}
- if (tab === 'Reporting Task Controller Services') {
+ if (tab === 'Management Controller Services') {
$('#controller-cs-availability').show();
- } else if (tab === 'Reporting Tasks' || tab === 'Registry Clients') {
+ } else if (tab === 'Reporting Tasks' || tab === 'Registry Clients' || tab === 'Parameter Providers') {
$('#controller-cs-availability').hide();
}
@@ -1776,7 +2640,7 @@
// create a new controller service or reporting task
$('#new-service-or-task').on('click', function () {
var selectedTab = $('#settings-tabs li.selected-tab').text();
- if (selectedTab === 'Reporting Task Controller Services') {
+ if (selectedTab === 'Management Controller Services') {
var controllerServicesUri = config.urls.api + '/controller/controller-services';
nfControllerServices.promptNewControllerService(controllerServicesUri, getControllerServicesTable());
} else if (selectedTab === 'Reporting Tasks') {
@@ -1826,6 +2690,24 @@
// set the initial focus
$('#registry-name').focus();
+ } else if (selectedTab === 'Parameter Providers') {
+ $('#new-parameter-provider-dialog').modal('show');
+
+ var parameterProviderTypesGrid = $('#parameter-provider-types-table').data('gridInstance');
+ if (nfCommon.isDefinedAndNotNull(parameterProviderTypesGrid)) {
+ var parameterProviderTypesData = parameterProviderTypesGrid.getData();
+
+ // reset the canvas size after the dialog is shown
+ parameterProviderTypesGrid.resizeCanvas();
+
+ // select the first row if possible
+ if (parameterProviderTypesData.getLength() > 0) {
+ nfFilteredDialogCommon.choseFirstRow(parameterProviderTypesGrid);
+ }
+ }
+
+ // set the initial focus
+ $('#parameter-provider-type-filter').focus();
}
});
@@ -1834,6 +2716,7 @@
nfControllerServices.init(getControllerServicesTable(), nfSettings.showSettings);
initReportingTasks();
initRegistriesTable();
+ initParameterProvidersTable();
},
/**
@@ -1846,6 +2729,10 @@
if (nfCommon.isDefinedAndNotNull(reportingTasksGrid)) {
reportingTasksGrid.resizeCanvas();
}
+ var parameterProvidersGrid = $('#parameter-providers-table').data('gridInstance');
+ if (nfCommon.isDefinedAndNotNull(parameterProvidersGrid)) {
+ parameterProvidersGrid.resizeCanvas();
+ }
},
/**
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 fc2bcaaab5..49a3b1a7bb 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
@@ -183,7 +183,7 @@
//apply the status bar if indicated
if(config.supportsStatusBar){
- $("#processor-details-status-bar").statusbar();
+ $("#processor-details-status-bar").statusbar('processor');
}
// initialize the properties
@@ -372,9 +372,17 @@
//Populate the status bar if the feature is enabled
if (config.supportsStatusBar && nfCommon.isDefinedAndNotNull(config.nfCanvasUtils)){
+ var formattedBulletins = nfCommon.getFormattedBulletins(processorResponse.bulletins);
+ var unorderedBulletins = nfCommon.formatUnorderedList(formattedBulletins);
//initialize the canvas synchronization
- $("#processor-details-status-bar").statusbar('observe',processor.id);
+ $("#processor-details-status-bar").statusbar(
+ 'observe',
+ {
+ processor: processor.id,
+ bulletins: unorderedBulletins
+ }
+ );
//Fetch the component as a selection from the canvas
selection = config.nfCanvasUtils.getSelectionById(processor.id);