mcgilman commented on code in PR #5671:
URL: https://github.com/apache/nifi/pull/5671#discussion_r956242407
##########
nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-parameter-contexts.js:
##########
@@ -132,6 +134,27 @@
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) {
+ if (dataContext.component.parameterProviderConfiguration) {
Review Comment:
This condition assumes the user `canRead`. When the user lacks permissions
to a given Parameter Context, the `component` will not be provided.
##########
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,2631 @@
+/*
+ * 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'],
+ 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')));
+ } 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);
+ }
+}(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 sensitiveParametersArray = [];
+
+ 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);
+
+ // show update steps
+ $('#fetch-parameters-update-status-container').show();
+
+ // if this request was cancelled, remove the update request
+ if (cancelled) {
+ deleteUpdateRequest(currentParameterProviderEntity.id,
requestId);
+ } else {
+ 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
+
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 = 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
+ $('<div class="parameter-contexts-to-create"><span
class="unset">None</span></div>')
+ .appendTo($('#parameter-contexts-to-create-container'));
+
+ // list parameter contexts to update
+ var parameterContextsToUpdate =
$('#parameter-contexts-to-update-container').empty();
+
+ if
(!updatedParameterProviderEntity.component.referencingParameterContexts) {
+ $('<div class="parameter-contexts-to-update"><span
class="unset">None</span></div>')
+ .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(', '));
+ }
+
+ // hide affected referencing components list
+ var affectedReferencingComponents =
$('#fetch-parameters-affected-referencing-components-container');
+ if (!affectedReferencingComponents.hasClass('hidden')) {
+ affectedReferencingComponents.addClass('hidden');
+ }
+
+ loadParameterGroups(updatedParameterProviderEntity);
+
+ // update visibility
+ $('#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 () {
+ var disabled = true;
+
+ if
(!updatedParameterProviderEntity.component.referencingParameterContexts) {
+ var groupsGrid =
$('#parameter-groups-table').data('gridInstance');
+ var groupsData = groupsGrid.getData();
+
+ $.each(groupsData.getItems(), function (_, group) {
+ if (group.createNewParameterContext) {
+ disabled = false;
+ }
+ })
+ } else {
+ disabled = false;
+ }
+
+ return disabled;
+ },
+ 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 () {
+ confirmCancelDialog('#fetch-parameters-dialog');
+ }
+ }
+ }];
+
+ // synchronize the current component canvas attributes in the
status bar
+ if (fetchParameterProviderOptions.supportsStatusBar) {
+ // initialize the canvas synchronization
+ if (updatedParameterProviderEntity.bulletins.length !== 0) {
+ $('#fetch-parameters-status-bar').statusbar(
+ 'observe',
+ { provider: updatedParameterProviderEntity.bulletins }
+ );
+ }
+ }
+
+ // show the dialog
+ $('#fetch-parameters-dialog')
+ .modal('setButtonModel', buttons)
+ .modal('show');
+
+ if ($('#fetched-parameters-listing-container').is(':visible')) {
+
updateReferencingComponentsBorder($('#fetched-parameters-listing-container'));
+ }
+ });
+ };
+
+ /**
+ * 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 isReferencingParameterContext =
parameterProviderGroupEntity.component.referencingParameterContexts
+ ?
isReferencingParamContext(parameterProviderGroupEntity.component.referencingParameterContexts,
groupConfig.parameterContextName)
+ : false;
+
+ var group = {
+ id: groupCount++,
+ hidden: false,
+ isParameterContext: isReferencingParameterContext,
+ name: groupConfig.groupName,
+ parameterContextName: groupConfig.parameterContextName,
+ parameterSensitivities: groupConfig.parameterSensitivities,
+ referencingParameterContexts:
groupConfig.referencingParameterContexts ?
groupConfig.referencingParameterContexts : null
+ };
+
+ 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 isReferencingParamContext = false;
+ $.each(referencingParameterContexts, function (_, paramContext) {
+ if (paramContext.component.name.includes(parameterContextName)) {
+ return isReferencingParamContext = true;
+ }
+ })
+
+ return isReferencingParamContext;
+ }
+
+ /**
+ * Loads the selectable parameters for a specified parameter group.
+ *
+ * @param groupId
+ * @param {object} parametersEntity
+ */
+ var loadSelectableParameters = function (groupId, parametersEntity) {
+ sensitiveParametersArray = [];
+ 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 idx = 0;
+ for (var param in parametersEntity) {
+
+ var parameter = {
+ id: idx++,
+ groupId: groupId,
+ name: param,
+ sensitivity: parametersEntity[param] ?
parametersEntity[param] : SENSITIVE
+ }
+ // if the parameter is sensitive, then show the parameter
checkbox as check-marked
+ if (parameter.sensitivity === SENSITIVE) {
+ sensitiveParametersArray.push(parameter.id);
+ }
+
+ parametersData.addItem(parameter);
+ }
+
+ // complete the update
+ parametersData.endUpdate();
+ parametersData.reSort();
+
+ // select the sensitive rows
+ if (sensitiveParametersArray.length !== 0) {
+
selectableParametersGrid.setSelectedRows(sensitiveParametersArray);
+ }
+
+ // 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
+ if
($('#fetch-parameters-affected-referencing-components-container').hasClass('hidden'))
{
+
$('#fetch-parameters-affected-referencing-components-container').removeClass('hidden');
+ }
+
+ 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
+ $('<div class="referencing-component-container"><span
class="unset">Pending
Apply</span></div>').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 = $('<ul class="referencing-component-listing
clear"></ul>');
+
+ var referencingProcessGroupsArray = [];
+ for (var key in referencingProcessGroups) {
+ if (referencingProcessGroups.hasOwnProperty(key)) {
+
referencingProcessGroupsArray.push(referencingProcessGroups[key]);
+ }
+ }
+
+ if (nfCommon.isEmpty(referencingProcessGroupsArray)) {
+ // set to none
+ $('<div class="referencing-component-container"><span
class="unset">None</span></div>').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 = $('<div
class="referencing-component-references"></div>');
+
parameterReferencingComponentsContainer.append(referencingPgReferencesContainer);
+
+ // create the collapsable listing for each PG
+ var createReferenceBlock = function
(referencingProcessGroup, list) {
+ var twist = $('<div class="expansion-button
collapsed"></div>');
+ var title = $('<span
class="referencing-component-title"></span>').text(referencingProcessGroup.name);
+ var count = $('<span
class="referencing-component-count"></span>').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 = $('<div
class="referencing-component-block pointer
unselectable"></div>').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) {
+ $('<li
class="referencing-component-container"><span
class="unset">None</span></li>').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) {
+ $('<li
class="referencing-component-container"><span
class="unset">None</span></li>').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) {
+ $('<li
class="referencing-component-container"><span
class="unset">None</span></li>').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 = $('<li
class="referencing-component-container"></li>').appendTo(unauthorizedComponentsContainer);
+ $('<span
class="fetch-parameters-referencing-component-name link ellipsis"></span>')
+ .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('<div
class="unset">No referencing components.</div>');
+ 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 = $('<ul class="referencing-component-listing
clear"></ul>');
+ var unauthorized = $('<ul class="referencing-component-listing
clear"></ul>');
+
+ $.each(parameterProviderComponent.referencingParameterContexts,
function (_, refParameterContextComponent) {
+ // check the access policy for this referencing component
+ if
(nfCommon.isDefinedAndNotNull(parameterProviderEntity.permissions) &&
parameterProviderEntity.permissions.canRead === false) {
+ var unauthorizedReferencingComponent = $('<div
class="unset"></div>').text(refParameterContextComponent.id);
+ unauthorized.append(unauthorizedReferencingComponent);
+ } else {
+ var referencingComponent =
refParameterContextComponent.component;
+
+ var parameterContextLink = $('<span
class="referencing-component-name link"></span>')
+ .text(referencingComponent.name)
+ .on('click', function () {
+ // show the component
+
nfParameterContexts.showParameterContext(referencingComponent.id, null,
referencingComponent.name);
Review Comment:
When linking to a Parameter Context, I would expect to be taken to the
listing with `this` Parameter Context selected. As-is the user is returned to
the canvas with the Parameter Context shown in a dialog.
Linking in the other direction is working as expected. When linking to a
Parameter Provider from a Parameter Context, the user is taken to the listing
of Parameter Providers with the desired Parameter Provider selected.
##########
nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-parameter-contexts.js:
##########
@@ -2493,6 +2525,10 @@
markup += '<div title="Access Policies" class="pointer
edit-access-policies fa fa-key"></div>';
}
+ if (dataContext.component.parameterProviderConfiguration &&
canRead) {
Review Comment:
`canRead` should be evaluated prior to
`dataContext.component.parameterProviderConfiguration`. If `canRead` is false,
`component` will not be available.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]