mcgilman commented on code in PR #7191:
URL: https://github.com/apache/nifi/pull/7191#discussion_r1224497430


##########
nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-settings.js:
##########
@@ -1925,6 +1931,885 @@
         });
     };
 
+    /**
+     * 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 getFlowAnalysisRuleTypeFilterText = function () {
+        return $('#flow-analysis-rule-type-filter').val();
+    };
+
+    /**
+     * Filters the flow analysis rule type table.
+     */
+    var applyFlowAnalysisRuleTypeFilter = function () {
+        // get the dataview
+        var flowAnalysisRuleTypesGrid = 
$('#flow-analysis-rule-types-table').data('gridInstance');
+
+        // ensure the grid has been initialized
+        if (nfCommon.isDefinedAndNotNull(flowAnalysisRuleTypesGrid)) {
+            var flowAnalysisRuleTypesData = 
flowAnalysisRuleTypesGrid.getData();
+
+            // update the search criteria
+            flowAnalysisRuleTypesData.setFilterArgs({
+                searchString: getFlowAnalysisRuleTypeFilterText()
+            });
+            flowAnalysisRuleTypesData.refresh();
+
+            // update the buttons to possibly trigger the disabled state
+            $('#new-flow-analysis-rule-dialog').modal('refreshButtons');
+
+            // update the selection if possible
+            if (flowAnalysisRuleTypesData.getLength() > 0) {
+                
nfFilteredDialogCommon.choseFirstRow(flowAnalysisRuleTypesGrid);
+            }
+        }
+    };
+
+    /**
+     * Hides the selected flow analysis rule.
+     */
+    var clearSelectedFlowAnalysisRule = function () {
+        $('#flow-analysis-rule-type-description').attr('title', '').text('');
+        $('#flow-analysis-rule-type-name').attr('title', '').text('');
+        $('#flow-analysis-rule-type-bundle').attr('title', '').text('');
+        $('#selected-flow-analysis-rule-name').text('');
+        $('#selected-flow-analysis-rule-type').text('').removeData('bundle');
+        $('#flow-analysis-rule-description-container').hide();
+    };
+
+    /**
+     * Clears the selected flow analysis rule type.
+     */
+    var clearFlowAnalysisRuleSelection = function () {
+        // clear the selected row
+        clearSelectedFlowAnalysisRule();
+
+        // clear the active cell the it can be reselected when its included
+        var flowAnalysisRuleTypesGrid = 
$('#flow-analysis-rule-types-table').data('gridInstance');
+        flowAnalysisRuleTypesGrid.resetActiveCell();
+    };
+
+    /**
+     * 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 filterFlowAnalysisRuleTypes = 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 = 
$('#flow-analysis-rule-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 = 
$('#flow-analysis-rule-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-flow-analysis-rule-type').text() 
=== item['type']) {
+            clearFlowAnalysisRuleSelection();
+        }
+
+        return matches;
+    };
+
+    /**
+     * Adds the currently selected flow analysis rule.
+     */
+    var addSelectedFlowAnalysisRule = function () {
+        var selectedTaskType = $('#selected-flow-analysis-rule-type').text();
+        var selectedTaskBundle = 
$('#selected-flow-analysis-rule-type').data('bundle');
+
+        // ensure something was selected
+        if (selectedTaskType === '') {
+            nfDialog.showOkDialog({
+                headerText: 'Settings',
+                dialogContent: 'The type of flow analysis rule to create must 
be selected.'
+            });
+        } else {
+            addFlowAnalysisRule(selectedTaskType, selectedTaskBundle);
+        }
+    };
+
+    /**
+     * Adds a new flow analysis rule of the specified type.
+     *
+     * @param {string} flowAnalysisRuleType
+     * @param {object} flowAnalysisRuleBundle
+     */
+    var addFlowAnalysisRule = function (flowAnalysisRuleType, 
flowAnalysisRuleBundle) {
+        // build the flow analysis rule entity
+        var flowAnalysisRuleEntity = {
+            'revision': nfClient.getRevision({
+                'revision': {
+                    'version': 0
+                }
+            }),
+            'disconnectedNodeAcknowledged': 
nfStorage.isDisconnectionAcknowledged(),
+            'component': {
+                'type': flowAnalysisRuleType,
+                'bundle': flowAnalysisRuleBundle
+            }
+        };
+
+        // add the new flow analysis rule
+        var addRule = $.ajax({
+            type: 'POST',
+            url: config.urls.createFlowAnalysisRule,
+            data: JSON.stringify(flowAnalysisRuleEntity),
+            dataType: 'json',
+            contentType: 'application/json'
+        }).done(function (flowAnalysisRuleEntity) {
+            // add the item
+            var flowAnalysisRuleGrid = 
$('#flow-analysis-rules-table').data('gridInstance');
+            var flowAnalysisRuleData = flowAnalysisRuleGrid.getData();
+            flowAnalysisRuleData.addItem($.extend({
+                type: 'FlowAnalysisRule',
+                bulletins: []
+            }, flowAnalysisRuleEntity));
+
+            // resort
+            flowAnalysisRuleData.reSort();
+            flowAnalysisRuleGrid.invalidate();
+
+            // select the new flow analysis rule
+            var row = 
flowAnalysisRuleData.getRowById(flowAnalysisRuleEntity.id);
+            nfFilteredDialogCommon.choseRow(flowAnalysisRuleGrid, row);
+            flowAnalysisRuleGrid.scrollRowIntoView(row);
+        }).fail(nfErrorHandler.handleAjaxError);
+
+        // hide the dialog
+        $('#new-flow-analysis-rule-dialog').modal('hide');
+
+        return addRule;
+    };
+
+    /**
+     * Initializes the new flow analysis rule dialog.
+     */
+    var initNewFlowAnalysisRuleDialog = function () {
+        // initialize the flow analysis rule type table
+        var flowAnalysisRuleTypesColumns = [
+            {
+                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 flowAnalysisRuleTypesData = new Slick.Data.DataView({
+            inlineFilters: false
+        });
+        flowAnalysisRuleTypesData.setItems([]);
+        flowAnalysisRuleTypesData.setFilterArgs({
+            searchString: getFlowAnalysisRuleTypeFilterText()
+        });
+        flowAnalysisRuleTypesData.setFilter(filterFlowAnalysisRuleTypes);
+
+        // initialize the sort
+        nfCommon.sortType({
+            columnId: 'type',
+            sortAsc: true
+        }, flowAnalysisRuleTypesData);
+
+        // initialize the grid
+        var flowAnalysisRuleTypesGrid = new 
Slick.Grid('#flow-analysis-rule-types-table', flowAnalysisRuleTypesData, 
flowAnalysisRuleTypesColumns, gridOptions);
+        flowAnalysisRuleTypesGrid.setSelectionModel(new 
Slick.RowSelectionModel());
+        flowAnalysisRuleTypesGrid.registerPlugin(new Slick.AutoTooltips());
+        flowAnalysisRuleTypesGrid.setSortColumn('type', true);
+        flowAnalysisRuleTypesGrid.onSort.subscribe(function (e, args) {
+            nfCommon.sortType({
+                columnId: args.sortCol.field,
+                sortAsc: args.sortAsc
+            }, flowAnalysisRuleTypesData);
+        });
+        flowAnalysisRuleTypesGrid.onSelectedRowsChanged.subscribe(function (e, 
args) {
+            if ($.isArray(args.rows) && args.rows.length === 1) {
+                var flowAnalysisRuleTypeIndex = args.rows[0];
+                var flowAnalysisRuleType = 
flowAnalysisRuleTypesGrid.getDataItem(flowAnalysisRuleTypeIndex);
+
+                // set the flow analysis rule type description
+                if (nfCommon.isDefinedAndNotNull(flowAnalysisRuleType)) {
+                    // show the selected flow analysis rule
+                    $('#flow-analysis-rule-description-container').show();
+
+                    if (nfCommon.isBlank(flowAnalysisRuleType.description)) {
+                        $('#flow-analysis-rule-type-description')
+                            .attr('title', '')
+                            .html('<span class="unset">No description 
specified</span>');
+                    } else {
+                        $('#flow-analysis-rule-type-description')
+                            
.width($('#flow-analysis-rule-description-container').innerWidth() - 1)
+                            .html(flowAnalysisRuleType.description)
+                            .ellipsis();
+                    }
+
+                    var bundle = 
nfCommon.formatBundle(flowAnalysisRuleType.bundle);
+                    var type = nfCommon.formatType(flowAnalysisRuleType);
+
+                    // populate the dom
+                    
$('#flow-analysis-rule-type-name').text(type).attr('title', type);
+                    
$('#flow-analysis-rule-type-bundle').text(bundle).attr('title', bundle);
+                    
$('#selected-flow-analysis-rule-name').text(flowAnalysisRuleType.label);
+                    
$('#selected-flow-analysis-rule-type').text(flowAnalysisRuleType.type).data('bundle',
 flowAnalysisRuleType.bundle);
+
+                    // refresh the buttons based on the current selection
+                    
$('#new-flow-analysis-rule-dialog').modal('refreshButtons');
+                }
+            }
+        });
+        flowAnalysisRuleTypesGrid.onDblClick.subscribe(function (e, args) {
+            var flowAnalysisRuleType = 
flowAnalysisRuleTypesGrid.getDataItem(args.row);
+
+            if (isSelectable(flowAnalysisRuleType)) {
+                addFlowAnalysisRule(flowAnalysisRuleType.type, 
flowAnalysisRuleType.bundle);
+            }
+        });
+        flowAnalysisRuleTypesGrid.onViewportChanged.subscribe(function (e, 
args) {
+            nfCommon.cleanUpTooltips($('#flow-analysis-rule-types-table'), 
'div.view-usage-restriction');
+        });
+
+        // wire up the dataview to the grid
+        flowAnalysisRuleTypesData.onRowCountChanged.subscribe(function (e, 
args) {
+            flowAnalysisRuleTypesGrid.updateRowCount();
+            flowAnalysisRuleTypesGrid.render();
+
+            // update the total number of displayed processors
+            $('#displayed-flow-analysis-rule-types').text(args.current);
+        });
+        flowAnalysisRuleTypesData.onRowsChanged.subscribe(function (e, args) {
+            flowAnalysisRuleTypesGrid.invalidateRows(args.rows);
+            flowAnalysisRuleTypesGrid.render();
+        });
+        flowAnalysisRuleTypesData.syncGridSelection(flowAnalysisRuleTypesGrid, 
true);
+
+        // hold onto an instance of the grid
+        $('#flow-analysis-rule-types-table').data('gridInstance', 
flowAnalysisRuleTypesGrid).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 = flowAnalysisRuleTypesData.getItemById(rowId);
+
+                // show the tooltip
+                if (item.restricted === true) {
+                    var restrictionTip = $('<div></div>');
+
+                    if (nfCommon.isBlank(item.usageRestriction)) {
+                        restrictionTip.append($('<p style="margin-bottom: 
3px;"></p>').text('Requires the following permissions:'));
+                    } else {
+                        restrictionTip.append($('<p style="margin-bottom: 
3px;"></p>').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 flow analysis rules
+        $.ajax({
+            type: 'GET',
+            url: config.urls.flowAnalysisRuleTypes,
+            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
+            flowAnalysisRuleTypesData.beginUpdate();
+
+            // go through each flow analysis rule type
+            $.each(response.flowAnalysisRuleTypes, 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
+                flowAnalysisRuleTypesData.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
+            flowAnalysisRuleTypesData.endUpdate();
+
+            // resort
+            flowAnalysisRuleTypesData.reSort();
+            flowAnalysisRuleTypesGrid.invalidate();
+
+            // set the component restrictions and the corresponding required 
permissions
+            nfCanvasUtils.addComponentRestrictions(restrictedUsage, 
requiredPermissions);
+
+            // set the total number of processors
+            $('#total-flow-analysis-rule-types, 
#displayed-flow-analysis-rule-types').text(response.flowAnalysisRuleTypes.length);
+
+            // create the tag cloud
+            $('#flow-analysis-rule-tag-cloud').tagcloud({
+                tags: tags,
+                select: applyFlowAnalysisRuleTypeFilter,
+                remove: applyFlowAnalysisRuleTypeFilter
+            });
+
+            // 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
+            $('#flow-analysis-rule-bundle-group-combo').combo({
+                options: options,
+                select: applyFlowAnalysisRuleTypeFilter
+            });
+        }).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
+        $('#flow-analysis-rule-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 = flowAnalysisRuleTypesGrid.getSelectedRows();
+
+                if (selected.length > 0) {
+                    // grid configured with multi-select = false
+                    var item = 
flowAnalysisRuleTypesGrid.getDataItem(selected[0]);
+                    if (isSelectable(item)) {
+                        addSelectedFlowAnalysisRule();
+                    }
+                }
+            } else {
+                applyFlowAnalysisRuleTypeFilter();
+            }
+        });
+
+        // setup row navigation
+        
nfFilteredDialogCommon.addKeydownListener('#flow-analysis-rule-type-filter', 
flowAnalysisRuleTypesGrid, flowAnalysisRuleTypesGrid.getData());
+
+        // initialize the flow analysis rule dialog
+        $('#new-flow-analysis-rule-dialog').modal({
+            scrollableContentStyle: 'scrollable',
+            headerText: 'Add Flow Analysis Rule',
+            buttons: [{
+                buttonText: 'Add',
+                color: {
+                    base: '#728E9B',
+                    hover: '#004849',
+                    text: '#ffffff'
+                },
+                disabled: function () {
+                    var selected = flowAnalysisRuleTypesGrid.getSelectedRows();
+
+                    if (selected.length > 0) {
+                        // grid configured with multi-select = false
+                        var item = 
flowAnalysisRuleTypesGrid.getDataItem(selected[0]);
+                        return isSelectable(item) === false;
+                    } else {
+                        return flowAnalysisRuleTypesGrid.getData().getLength() 
=== 0;
+                    }
+                },
+                handler: {
+                    click: function () {
+                        addSelectedFlowAnalysisRule();
+                    }
+                }
+            },
+                {
+                    buttonText: 'Cancel',
+                    color: {
+                        base: '#E3E8EB',
+                        hover: '#C7D2D7',
+                        text: '#004849'
+                    },
+                    handler: {
+                        click: function () {
+                            $(this).modal('hide');
+                        }
+                    }
+                }],
+            handler: {
+                close: function () {
+                    // clear the selected row
+                    clearSelectedFlowAnalysisRule();
+
+                    // clear any filter strings
+                    $('#flow-analysis-rule-type-filter').val('');
+
+                    // clear the tagcloud
+                    
$('#flow-analysis-rule-tag-cloud').tagcloud('clearSelectedTags');
+
+                    // reset the group combo
+                    
$('#flow-analysis-rule-bundle-group-combo').combo('setSelectedOption', {
+                        value: ''
+                    });
+
+                    // reset the filter
+                    applyFlowAnalysisRuleTypeFilter();
+
+                    // unselect any current selection
+                    var flowAnalysisRuleTypesGrid = 
$('#flow-analysis-rule-types-table').data('gridInstance');
+                    flowAnalysisRuleTypesGrid.setSelectedRows([]);
+                    flowAnalysisRuleTypesGrid.resetActiveCell();
+                },
+                resize: function () {
+                    $('#flow-analysis-rule-type-description')
+                        
.width($('#flow-analysis-rule-description-container').innerWidth() - 1)
+                        
.text($('#flow-analysis-rule-type-description').attr('title'))
+                        .ellipsis();
+                }
+            }
+        });
+
+        // initialize the registry configuration dialog
+        $('#registry-configuration-dialog').modal({
+            scrollableContentStyle: 'scrollable',
+            handler: {
+                close: function () {
+                    $('#registry-id').text('');
+                    $('#registry-name').val('');
+                    $('#registry-location').val('');
+                    $('#registry-description').val('');
+                }
+            }
+        });
+    };
+
+    /**
+     * Initializes the flow analysis rules tab.
+     */
+    var initFlowAnalysisRules = function () {
+        // initialize the new flow analysis rule dialog
+        initNewFlowAnalysisRuleDialog();
+
+        var moreFlowAnalysisRuleDetails = function (row, cell, value, 
columnDef, dataContext) {
+            if (!dataContext.permissions.canRead) {
+                return '';
+            }
+
+            var markup = '<div title="View Details" class="pointer 
view-flow-analysis-rule fa fa-info-circle"></div>';
+
+            // always include a button to view the usage
+            markup += '<div title="Usage" class="pointer 
flow-analysis-rule-usage fa fa-book"></div>';

Review Comment:
   The `View Usage` action opens the generated documentation for each extension 
type. If we are going to generate documentation for them, then we should keep 
this action. If we aren't, or we're not as part of this commit, we should 
remove this action.



-- 
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]

Reply via email to