| /* |
| * 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 nf, Slick */ |
| |
| nf.Settings = (function () { |
| |
| var config = { |
| node: 'node', |
| ncm: 'ncm', |
| filterText: 'Filter', |
| styles: { |
| filterList: 'filter-list' |
| }, |
| urls: { |
| controllerConfig: '../nifi-api/controller/config', |
| controllerArchive: '../nifi-api/controller/archive', |
| controllerServiceTypes: '../nifi-api/controller/controller-service-types', |
| controllerServices: '../nifi-api/controller/controller-services', |
| reportingTaskTypes: '../nifi-api/controller/reporting-task-types', |
| reportingTasks: '../nifi-api/controller/reporting-tasks' |
| } |
| }; |
| |
| var gridOptions = { |
| forceFitColumns: true, |
| enableTextSelectionOnCells: true, |
| enableCellNavigation: true, |
| enableColumnReorder: false, |
| autoEdit: false, |
| multiSelect: false |
| }; |
| |
| /** |
| * Initializes the general tab. |
| */ |
| var initGeneral = function () { |
| // update the visibility of the controls |
| if (nf.Common.isDFM()) { |
| $('#general-settings div.editable').show(); |
| $('#general-settings div.read-only').hide(); |
| |
| // register the click listener for the archive link |
| $('#archive-flow-link').click(function () { |
| var revision = nf.Client.getRevision(); |
| |
| $.ajax({ |
| type: 'POST', |
| url: config.urls.controllerArchive, |
| data: { |
| version: revision.version, |
| clientId: revision.clientId |
| }, |
| dataType: 'json' |
| }).done(function (response) { |
| // update the revision |
| nf.Client.setRevision(response.revision); |
| |
| // show the result dialog |
| nf.Dialog.showOkDialog({ |
| dialogContent: 'A new flow archive was successfully created.', |
| overlayBackground: false |
| }); |
| }).fail(nf.Common.handleAjaxError); |
| }); |
| |
| // register the click listener for the save button |
| $('#settings-save').click(function () { |
| var revision = nf.Client.getRevision(); |
| |
| // marshal the configuration details |
| var configuration = marshalConfiguration(); |
| configuration['version'] = revision.version; |
| configuration['clientId'] = revision.clientId; |
| |
| // save the new configuration details |
| $.ajax({ |
| type: 'PUT', |
| url: config.urls.controllerConfig, |
| data: configuration, |
| dataType: 'json' |
| }).done(function (response) { |
| // update the revision |
| nf.Client.setRevision(response.revision); |
| |
| // update the displayed name |
| document.title = response.config.name; |
| |
| // set the data flow title and close the shell |
| $('#data-flow-title-container').children('span.link:first-child').text(response.config.name); |
| |
| // close the settings dialog |
| nf.Dialog.showOkDialog({ |
| dialogContent: 'Settings successfully applied.', |
| overlayBackground: false |
| }); |
| }).fail(nf.Common.handleAjaxError); |
| }); |
| } else { |
| $('#general-settings div.editable').hide(); |
| $('#general-settings div.read-only').show(); |
| } |
| }; |
| |
| /** |
| * Marshals the details to include in the configuration request. |
| */ |
| var marshalConfiguration = function () { |
| // create the configuration |
| var configuration = {}; |
| configuration['name'] = $('#data-flow-title-field').val(); |
| configuration['comments'] = $('#data-flow-comments-field').val(); |
| configuration['maxTimerDrivenThreadCount'] = $('#maximum-timer-driven-thread-count-field').val(); |
| configuration['maxEventDrivenThreadCount'] = $('#maximum-event-driven-thread-count-field').val(); |
| return configuration; |
| }; |
| |
| /** |
| * 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 getControllerServiceTypeFilterText = function () { |
| var filterText = ''; |
| var filterField = $('#controller-service-type-filter'); |
| if (!filterField.hasClass(config.styles.filterList)) { |
| filterText = filterField.val(); |
| } |
| return filterText; |
| }; |
| |
| /** |
| * Filters the processor type table. |
| */ |
| var applyControllerServiceTypeFilter = function () { |
| // get the dataview |
| var controllerServiceTypesGrid = $('#controller-service-types-table').data('gridInstance'); |
| |
| // ensure the grid has been initialized |
| if (nf.Common.isDefinedAndNotNull(controllerServiceTypesGrid)) { |
| var controllerServiceTypesData = controllerServiceTypesGrid.getData(); |
| |
| // update the search criteria |
| controllerServiceTypesData.setFilterArgs({ |
| searchString: getControllerServiceTypeFilterText(), |
| property: $('#controller-service-type-filter-options').combo('getSelectedOption').value |
| }); |
| |
| // need to invalidate the entire table since parent elements may need to be |
| // rerendered due to changes in their children |
| controllerServiceTypesData.refresh(); |
| controllerServiceTypesGrid.invalidate(); |
| } |
| }; |
| |
| /** |
| * Determines if all of the ancestors of the specified item are expanded. |
| * |
| * @param {type} item |
| * @returns {Boolean} |
| */ |
| var areAncestorsExpanded = function (item) { |
| var documentedType = item; |
| while (documentedType.parent !== null) { |
| if (documentedType.parent.collapsed === true) { |
| return false; |
| } |
| documentedType = documentedType.parent; |
| } |
| |
| return true; |
| }; |
| |
| /** |
| * Determines if the specified item is an ancestor. |
| * |
| * @param {type} item |
| * @returns {Boolean} |
| */ |
| var isAncestor = function (item) { |
| return item.children.length > 0; |
| }; |
| |
| /** |
| * Hides the selected controller service. |
| */ |
| var clearSelectedControllerService = function () { |
| $('#controller-service-type-description').text(''); |
| $('#controller-service-type-name').text(''); |
| $('#controller-service-availability-combo').combo('setSelectedOption', { |
| value: config.node |
| }); |
| $('#selected-controller-service-name').text(''); |
| $('#selected-controller-service-type').text(''); |
| $('#controller-service-description-container').hide(); |
| }; |
| |
| /** |
| * Clears the selected controller service type. |
| */ |
| var clearControllerServiceSelection = function () { |
| // clear the selected row |
| clearSelectedControllerService(); |
| |
| // clear the active cell the it can be reselected when its included |
| var controllerServiceTypesGrid = $('#controller-service-types-table').data('gridInstance'); |
| controllerServiceTypesGrid.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 filterControllerServiceTypes = function (item, args) { |
| if (!areAncestorsExpanded(item)) { |
| // if this item is currently selected and its parent is not collapsed |
| if ($('#selected-controller-service-type').text() === item['type']) { |
| clearControllerServiceSelection(); |
| } |
| |
| // update visibility flag |
| item.visible = false; |
| |
| return false; |
| } |
| |
| // don't allow ancestors to be filtered out (unless any of their ancestors |
| // are collapsed) |
| if (isAncestor(item)) { |
| // update visibility flag |
| item.visible = false; |
| |
| return true; |
| } |
| |
| // 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 = $('#controller-service-tag-cloud').tagcloud('getSelectedTags'); |
| var hasSelectedTags = tagFilters.length > 0; |
| if (hasSelectedTags) { |
| matchesTags = matchesSelectedTags(tagFilters, item['tags']); |
| } |
| } |
| |
| // determine if this row should be visible |
| var matches = matchesFilter && matchesTags; |
| |
| // if this row is currently selected and its being filtered |
| if (matches === false && $('#selected-controller-service-type').text() === item['type']) { |
| clearControllerServiceSelection(); |
| } |
| |
| // update visibility flag |
| item.visible = matches; |
| |
| return matches; |
| }; |
| |
| /** |
| * Determines if the item matches the filter. |
| * |
| * @param {object} item The item to filter |
| * @param {object} args The filter criteria |
| * @returns {boolean} Whether the item matches the filter |
| */ |
| var matchesRegex = function (item, args) { |
| if (args.searchString === '') { |
| return true; |
| } |
| |
| try { |
| // perform the row filtering |
| var filterExp = new RegExp(args.searchString, 'i'); |
| } catch (e) { |
| // invalid regex |
| return false; |
| } |
| |
| // determine if the item matches the filter |
| return item[args.property].search(filterExp) >= 0; |
| }; |
| |
| /** |
| * Determines if the specified tags match all the tags selected by the user. |
| * |
| * @argument {string[]} tagFilters The tag filters |
| * @argument {string} tags The tags to test |
| */ |
| var matchesSelectedTags = function (tagFilters, tags) { |
| var selectedTags = []; |
| $.each(tagFilters, function (_, filter) { |
| selectedTags.push(filter); |
| }); |
| |
| // normalize the tags |
| var normalizedTags = tags.toLowerCase(); |
| |
| var matches = true; |
| $.each(selectedTags, function (i, selectedTag) { |
| if (normalizedTags.indexOf(selectedTag) === -1) { |
| matches = false; |
| return false; |
| } |
| }); |
| |
| return matches; |
| }; |
| |
| /** |
| * Formats the type by introducing expand/collapse where appropriate. |
| * |
| * @param {type} row |
| * @param {type} cell |
| * @param {type} value |
| * @param {type} columnDef |
| * @param {type} dataContext |
| */ |
| var expandableTypeFormatter = function (row, cell, value, columnDef, dataContext) { |
| var markup = ''; |
| |
| var indent = 0; |
| var documentedType = dataContext; |
| while (documentedType.parent !== null) { |
| indent += 10; |
| documentedType = documentedType.parent; |
| } |
| |
| var padding = 3; |
| |
| // create the markup for the row |
| if (dataContext.children.length > 0) { |
| // determine how to render the expansion button |
| var expansionStyle = 'expanded'; |
| if (dataContext.collapsed === true) { |
| expansionStyle = 'collapsed'; |
| } |
| |
| // to calculate the number of visible children |
| var visibleChildren = 0; |
| $.each(dataContext.children, function (_, child) { |
| if (child.visible) { |
| visibleChildren++; |
| } |
| }); |
| |
| markup += ('<span style="margin-top: 5px; margin-left: ' + indent + 'px;" class="expansion-button ' + expansionStyle + '"></span><span class="ancestor-type" style="margin-left: ' + padding + 'px;">' + value + '</span><span class="ancestor-type-rollup">(' + visibleChildren + ' of ' + dataContext.children.length + ')</span>'); |
| } else { |
| if (dataContext.parent === null) { |
| padding = 0; |
| } |
| |
| markup += ('<span style="margin-left: ' + (indent + padding) + 'px;">' + value + '</span>'); |
| } |
| |
| return markup; |
| }; |
| |
| /** |
| * Adds a new controller service of the specified type. |
| * |
| * @param {string} controllerServiceType |
| */ |
| var addControllerService = function (controllerServiceType) { |
| var revision = nf.Client.getRevision(); |
| |
| // get the desired availability |
| var availability; |
| if (nf.Canvas.isClustered()) { |
| availability = $('#controller-service-availability-combo').combo('getSelectedOption').value; |
| } else { |
| availability = config.node; |
| } |
| |
| // add the new controller service |
| var addService = $.ajax({ |
| type: 'POST', |
| url: config.urls.controllerServices + '/' + encodeURIComponent(availability), |
| data: { |
| version: revision.version, |
| clientId: revision.clientId, |
| type: controllerServiceType |
| }, |
| dataType: 'json' |
| }).done(function (response) { |
| // update the revision |
| nf.Client.setRevision(response.revision); |
| |
| // add the item |
| var controllerService = response.controllerService; |
| var controllerServicesGrid = $('#controller-services-table').data('gridInstance'); |
| var controllerServicesData = controllerServicesGrid.getData(); |
| controllerServicesData.addItem(controllerService); |
| |
| // resort |
| controllerServicesData.reSort(); |
| controllerServicesGrid.invalidate(); |
| |
| // select the new controller service |
| var row = controllerServicesData.getRowById(controllerService.id); |
| controllerServicesGrid.setSelectedRows([row]); |
| }).fail(nf.Common.handleAjaxError); |
| |
| // hide the dialog |
| $('#new-controller-service-dialog').modal('hide'); |
| |
| return addService; |
| }; |
| |
| /** |
| * Initializes the new controller service dialog. |
| */ |
| var initNewControllerServiceDialog = function () { |
| // specify the combo options |
| $('#controller-service-type-filter-options').combo({ |
| options: [{ |
| text: 'by type', |
| value: 'label' |
| }, { |
| text: 'by tag', |
| value: 'tags' |
| }], |
| select: function (option) { |
| applyControllerServiceTypeFilter(); |
| } |
| }); |
| |
| // specify the controller service availability |
| if (nf.Canvas.isClustered()) { |
| $('#controller-service-availability-combo').combo({ |
| options: [{ |
| text: 'Node', |
| value: config.node, |
| description: 'This controller service will be available on the nodes only.' |
| }, { |
| text: 'Cluster Manager', |
| value: config.ncm, |
| description: 'This controller service will be available on the cluster manager only.' |
| }] |
| }); |
| $('#controller-service-availability-container').show(); |
| } |
| |
| // define the function for filtering the list |
| $('#controller-service-type-filter').keyup(function () { |
| applyControllerServiceTypeFilter(); |
| }).focus(function () { |
| if ($(this).hasClass(config.styles.filterList)) { |
| $(this).removeClass(config.styles.filterList).val(''); |
| } |
| }).blur(function () { |
| if ($(this).val() === '') { |
| $(this).addClass(config.styles.filterList).val(config.filterText); |
| } |
| }).addClass(config.styles.filterList).val(config.filterText); |
| |
| // initialize the processor type table |
| var controllerServiceTypesColumns = [ |
| {id: 'type', name: 'Type', field: 'label', formatter: expandableTypeFormatter, sortable: false, resizable: true}, |
| {id: 'tags', name: 'Tags', field: 'tags', sortable: false, resizable: true} |
| ]; |
| |
| // initialize the dataview |
| var controllerServiceTypesData = new Slick.Data.DataView({ |
| inlineFilters: false |
| }); |
| controllerServiceTypesData.setItems([]); |
| controllerServiceTypesData.setFilterArgs({ |
| searchString: getControllerServiceTypeFilterText(), |
| property: $('#controller-service-type-filter-options').combo('getSelectedOption').value |
| }); |
| controllerServiceTypesData.setFilter(filterControllerServiceTypes); |
| controllerServiceTypesData.getItemMetadata = function (index) { |
| var item = controllerServiceTypesData.getItem(index); |
| if (item && item.children.length > 0) { |
| return { |
| selectable: false, |
| columns: { |
| 0: { |
| colspan: '*' |
| } |
| } |
| }; |
| } else { |
| return {}; |
| } |
| }; |
| |
| var getVisibleControllerServiceCount = function () { |
| var count = 0; |
| for (var i = 0; i < controllerServiceTypesData.getLength(); i++) { |
| var item = controllerServiceTypesData.getItem(i); |
| if (item.children.length === 0) { |
| count++; |
| } |
| } |
| return count; |
| }; |
| |
| // initialize the grid |
| var controllerServiceTypesGrid = new Slick.Grid('#controller-service-types-table', controllerServiceTypesData, controllerServiceTypesColumns, gridOptions); |
| controllerServiceTypesGrid.setSelectionModel(new Slick.RowSelectionModel()); |
| controllerServiceTypesGrid.registerPlugin(new Slick.AutoTooltips()); |
| controllerServiceTypesGrid.setSortColumn('type', true); |
| controllerServiceTypesGrid.onSelectedRowsChanged.subscribe(function (e, args) { |
| if ($.isArray(args.rows) && args.rows.length === 1) { |
| var controllerServiceTypeIndex = args.rows[0]; |
| var controllerServiceType = controllerServiceTypesGrid.getDataItem(controllerServiceTypeIndex); |
| |
| // only allow selection of service implementations |
| if (controllerServiceType.children.length === 0) { |
| // set the controller service type description |
| if (nf.Common.isBlank(controllerServiceType.description)) { |
| $('#controller-service-type-description').attr('title', '').html('<span class="unset">No description specified</span>'); |
| } else { |
| $('#controller-service-type-description').text(controllerServiceType.description).ellipsis(); |
| } |
| |
| // populate the dom |
| $('#controller-service-type-name').text(controllerServiceType.label).ellipsis(); |
| $('#selected-controller-service-name').text(controllerServiceType.label); |
| $('#selected-controller-service-type').text(controllerServiceType.type); |
| |
| // show the selected controller service |
| $('#controller-service-description-container').show(); |
| } |
| } |
| }); |
| controllerServiceTypesGrid.onClick.subscribe(function (e, args) { |
| var item = controllerServiceTypesData.getItem(args.row); |
| if (item && item.children.length > 0) { |
| // update the grid |
| item.collapsed = !item.collapsed; |
| controllerServiceTypesData.updateItem(item.id, item); |
| |
| // prevent selection within slickgrid |
| e.stopImmediatePropagation(); |
| } |
| }); |
| controllerServiceTypesGrid.onDblClick.subscribe(function (e, args) { |
| var controllerServiceType = controllerServiceTypesGrid.getDataItem(args.row); |
| addControllerService(controllerServiceType.type); |
| }); |
| |
| // wire up the dataview to the grid |
| controllerServiceTypesData.onRowCountChanged.subscribe(function (e, args) { |
| controllerServiceTypesGrid.updateRowCount(); |
| controllerServiceTypesGrid.render(); |
| |
| // update the total number of displayed processors |
| $('#displayed-controller-service-types').text(getVisibleControllerServiceCount()); |
| }); |
| controllerServiceTypesData.onRowsChanged.subscribe(function (e, args) { |
| controllerServiceTypesGrid.invalidateRows(args.rows); |
| controllerServiceTypesGrid.render(); |
| }); |
| controllerServiceTypesData.syncGridSelection(controllerServiceTypesGrid, true); |
| |
| // hold onto an instance of the grid |
| $('#controller-service-types-table').data('gridInstance', controllerServiceTypesGrid); |
| |
| // load the available controller services |
| $.ajax({ |
| type: 'GET', |
| url: config.urls.controllerServiceTypes, |
| dataType: 'json' |
| }).done(function (response) { |
| var id = 0; |
| var tags = []; |
| |
| // begin the update |
| controllerServiceTypesData.beginUpdate(); |
| |
| var addType = function (parentItem, documentedType) { |
| var item = { |
| id: id++, |
| label: nf.Common.substringAfterLast(documentedType.type, '.'), |
| type: documentedType.type, |
| description: nf.Common.escapeHtml(documentedType.description), |
| tags: documentedType.tags.join(', '), |
| parent: parentItem, |
| children: [], |
| collapsed: false, |
| visible: true |
| }; |
| |
| // add the documented type |
| controllerServiceTypesData.addItem(item); |
| |
| // count the frequency of each tag for this type |
| $.each(documentedType.tags, function (i, tag) { |
| tags.push(tag.toLowerCase()); |
| }); |
| |
| // add each of its children |
| $.each(documentedType.childTypes, function (_, documentedChildType) { |
| var childItem = addType(item, documentedChildType); |
| item.children.push(childItem); |
| }); |
| |
| return item; |
| }; |
| |
| // go through each controller service type |
| $.each(response.controllerServiceTypes, function (i, documentedType) { |
| addType(null, documentedType); |
| }); |
| |
| // end the udpate |
| controllerServiceTypesData.endUpdate(); |
| |
| // set the total number of processors |
| $('#total-controller-service-types, #displayed-controller-service-types').text(getVisibleControllerServiceCount()); |
| |
| // create the tag cloud |
| $('#controller-service-tag-cloud').tagcloud({ |
| tags: tags, |
| select: applyControllerServiceTypeFilter, |
| remove: applyControllerServiceTypeFilter |
| }); |
| }).fail(nf.Common.handleAjaxError); |
| |
| // initialize the controller service dialog |
| $('#new-controller-service-dialog').modal({ |
| headerText: 'Add Controller Service', |
| overlayBackground: false, |
| buttons: [{ |
| buttonText: 'Add', |
| handler: { |
| click: function () { |
| var selectedServiceType = $('#selected-controller-service-type').text(); |
| addControllerService(selectedServiceType); |
| } |
| } |
| }, { |
| buttonText: 'Cancel', |
| handler: { |
| click: function () { |
| $(this).modal('hide'); |
| } |
| } |
| }], |
| close: function () { |
| // clear the selected row |
| clearSelectedControllerService(); |
| |
| // unselect any current selection |
| var processTypesGrid = $('#controller-service-types-table').data('gridInstance'); |
| processTypesGrid.setSelectedRows([]); |
| processTypesGrid.resetActiveCell(); |
| |
| // clear any filter strings |
| $('#controller-service-type-filter').addClass(config.styles.filterList).val(config.filterText); |
| |
| // clear the tagcloud |
| $('#controller-service-tag-cloud').tagcloud('clearSelectedTags'); |
| } |
| }).draggable({ |
| containment: 'parent', |
| handle: '.dialog-header' |
| }); |
| }; |
| |
| /** |
| * Formatter for the type column. |
| * |
| * @param {type} row |
| * @param {type} cell |
| * @param {type} value |
| * @param {type} columnDef |
| * @param {type} dataContext |
| * @returns {String} |
| */ |
| var typeFormatter = function (row, cell, value, columnDef, dataContext) { |
| return nf.Common.substringAfterLast(value, '.'); |
| }; |
| |
| /** |
| * Formatter for the availability column. |
| * |
| * @param {type} row |
| * @param {type} cell |
| * @param {type} value |
| * @param {type} columnDef |
| * @param {type} dataContext |
| * @returns {String} |
| */ |
| var availabilityFormatter = function (row, cell, value, columnDef, dataContext) { |
| if (value === config.node) { |
| return 'Node'; |
| } else { |
| return 'Cluster Manager'; |
| } |
| }; |
| |
| /** |
| * Sorts the specified data using the specified sort details. |
| * |
| * @param {object} sortDetails |
| * @param {object} data |
| */ |
| var sort = function (sortDetails, data) { |
| // defines a function for sorting |
| var comparer = function (a, b) { |
| var aString = nf.Common.isDefinedAndNotNull(a[sortDetails.columnId]) ? a[sortDetails.columnId] : ''; |
| var bString = nf.Common.isDefinedAndNotNull(b[sortDetails.columnId]) ? b[sortDetails.columnId] : ''; |
| return aString === bString ? 0 : aString > bString ? 1 : -1; |
| }; |
| |
| // perform the sort |
| data.sort(comparer, sortDetails.sortAsc); |
| }; |
| |
| /** |
| * Initializes the controller services tab. |
| */ |
| var initControllerServices = function () { |
| // initialize the new controller service dialog |
| initNewControllerServiceDialog(); |
| |
| // more details formatter |
| var moreControllerServiceDetails = function (row, cell, value, columnDef, dataContext) { |
| var markup = '<img src="images/iconDetails.png" title="View Details" class="pointer view-controller-service" style="margin-top: 5px; float: left;" /> '; |
| if (!nf.Common.isEmpty(dataContext.validationErrors)) { |
| markup += '<img src="images/iconAlert.png" class="has-errors" style="margin-top: 4px; float: left;" /><span class="hidden row-id">' + nf.Common.escapeHtml(dataContext.id) + '</span>'; |
| } |
| return markup; |
| }; |
| |
| var controllerServiceActionFormatter = function (row, cell, value, columnDef, dataContext) { |
| var markup = ''; |
| |
| // only DFMs can edit a controller service |
| if (nf.Common.isDFM()) { |
| if (dataContext.state === 'ENABLED' || dataContext.state === 'ENABLING') { |
| markup += '<img src="images/iconDisable.png" title="Disable" class="pointer disable-controller-service" style="margin-top: 2px;" /> '; |
| } else if (dataContext.state === 'DISABLED') { |
| markup += '<img src="images/iconEdit.png" title="Edit" class="pointer edit-controller-service" style="margin-top: 2px;" /> '; |
| markup += '<img src="images/iconEnable.png" title="Enable" class="pointer enable-controller-service" style="margin-top: 2px;"/> '; |
| markup += '<img src="images/iconDelete.png" title="Remove" class="pointer delete-controller-service" style="margin-top: 2px;" /> '; |
| } |
| } |
| |
| // always include a button to view the usage |
| markup += '<img src="images/iconUsage.png" title="Usage" class="pointer controller-service-usage" style="margin-top: 2px;"/> '; |
| |
| return markup; |
| }; |
| |
| // define the column model for the controller services table |
| var controllerServicesColumns = [ |
| {id: 'moreDetails', name: ' ', resizable: false, formatter: moreControllerServiceDetails, sortable: false, width: 50, maxWidth: 50}, |
| {id: 'name', field: 'name', name: 'Name', sortable: true, resizable: true}, |
| {id: 'type', field: 'type', name: 'Type', formatter: typeFormatter, sortable: true, resizable: true}, |
| {id: 'state', field: 'state', name: 'State', sortable: true, resizeable: true}, |
| {id: 'actions', name: ' ', resizable: false, formatter: controllerServiceActionFormatter, sortable: false, width: 90, maxWidth: 90} |
| ]; |
| |
| // only show availability when clustered |
| if (nf.Canvas.isClustered()) { |
| controllerServicesColumns.push({id: 'availability', field: 'availability', name: 'Availability', formatter: availabilityFormatter, sortable: true, resizeable: true}); |
| } |
| |
| // initialize the dataview |
| var controllerServicesData = new Slick.Data.DataView({ |
| inlineFilters: false |
| }); |
| controllerServicesData.setItems([]); |
| |
| // initialize the sort |
| sort({ |
| columnId: 'name', |
| sortAsc: true |
| }, controllerServicesData); |
| |
| // initialize the grid |
| var controllerServicesGrid = new Slick.Grid('#controller-services-table', controllerServicesData, controllerServicesColumns, gridOptions); |
| controllerServicesGrid.setSelectionModel(new Slick.RowSelectionModel()); |
| controllerServicesGrid.registerPlugin(new Slick.AutoTooltips()); |
| controllerServicesGrid.setSortColumn('name', true); |
| controllerServicesGrid.onSort.subscribe(function (e, args) { |
| sort({ |
| columnId: args.sortCol.field, |
| sortAsc: args.sortAsc |
| }, controllerServicesData); |
| }); |
| |
| // configure a click listener |
| controllerServicesGrid.onClick.subscribe(function (e, args) { |
| var target = $(e.target); |
| |
| // get the service at this row |
| var controllerService = controllerServicesData.getItem(args.row); |
| |
| // determine the desired action |
| if (controllerServicesGrid.getColumns()[args.cell].id === 'actions') { |
| if (target.hasClass('edit-controller-service')) { |
| nf.ControllerService.showConfiguration(controllerService); |
| } else if (target.hasClass('enable-controller-service')) { |
| nf.ControllerService.enable(controllerService); |
| } else if (target.hasClass('disable-controller-service')) { |
| nf.ControllerService.disable(controllerService); |
| } else if (target.hasClass('delete-controller-service')) { |
| nf.ControllerService.remove(controllerService); |
| } else if (target.hasClass('controller-service-usage')) { |
| // close the settings dialog |
| $('#shell-close-button').click(); |
| |
| // open the documentation for this reporting task |
| nf.Shell.showPage('../nifi-docs/documentation?' + $.param({ |
| select: nf.Common.substringAfterLast(controllerService.type, '.') |
| })); |
| } |
| } else if (controllerServicesGrid.getColumns()[args.cell].id === 'moreDetails') { |
| if (target.hasClass('view-controller-service')) { |
| |
| } |
| } |
| }); |
| |
| // wire up the dataview to the grid |
| controllerServicesData.onRowCountChanged.subscribe(function (e, args) { |
| controllerServicesGrid.updateRowCount(); |
| controllerServicesGrid.render(); |
| }); |
| controllerServicesData.onRowsChanged.subscribe(function (e, args) { |
| controllerServicesGrid.invalidateRows(args.rows); |
| controllerServicesGrid.render(); |
| }); |
| controllerServicesData.syncGridSelection(controllerServicesGrid, true); |
| |
| // hold onto an instance of the grid |
| $('#controller-services-table').data('gridInstance', controllerServicesGrid).on('mouseenter', 'div.slick-cell', function (e) { |
| var errorIcon = $(this).find('img.has-errors'); |
| if (errorIcon.length && !errorIcon.data('qtip')) { |
| var serviceId = $(this).find('span.row-id').text(); |
| |
| // get the service item |
| var item = controllerServicesData.getItemById(serviceId); |
| |
| // format the errors |
| var tooltip = nf.Common.formatUnorderedList(item.validationErrors); |
| |
| // show the tooltip |
| if (nf.Common.isDefinedAndNotNull(tooltip)) { |
| errorIcon.qtip($.extend({ |
| content: tooltip, |
| position: { |
| target: 'mouse', |
| viewport: $(window), |
| adjust: { |
| x: 8, |
| y: 8, |
| method: 'flipinvert flipinvert' |
| } |
| } |
| }, nf.Common.config.tooltipConfig)); |
| } |
| } |
| }); |
| }; |
| |
| /** |
| * Loads the controller services. |
| */ |
| var loadControllerServices = function () { |
| var services = []; |
| |
| // get the controller services that are running on the nodes |
| var nodeControllerServices = $.ajax({ |
| type: 'GET', |
| url: config.urls.controllerServices + '/' + encodeURIComponent(config.node), |
| dataType: 'json' |
| }).done(function (response) { |
| var nodeServices = response.controllerServices; |
| if (nf.Common.isDefinedAndNotNull(nodeServices)) { |
| $.each(nodeServices, function (_, nodeService) { |
| services.push(nodeService); |
| }); |
| } |
| }); |
| |
| // get the controller services that are running on the ncm |
| var ncmControllerServices = $.Deferred(function (deferred) { |
| if (nf.Canvas.isClustered()) { |
| $.ajax({ |
| type: 'GET', |
| url: config.urls.controllerServices + '/' + encodeURIComponent(config.ncm), |
| dataType: 'json' |
| }).done(function (response) { |
| var ncmServices = response.controllerServices; |
| if (nf.Common.isDefinedAndNotNull(ncmServices)) { |
| $.each(ncmServices, function (_, ncmService) { |
| services.push(ncmService); |
| }); |
| } |
| deferred.resolve(); |
| }).fail(function () { |
| deferred.reject(); |
| }); |
| } else { |
| deferred.resolve(); |
| } |
| }).promise(); |
| |
| // add all controller services |
| return $.when(nodeControllerServices, ncmControllerServices).done(function () { |
| var controllerServicesElement = $('#controller-services-table'); |
| nf.Common.cleanUpTooltips(controllerServicesElement, 'img.has-errors'); |
| |
| var controllerServicesGrid = controllerServicesElement.data('gridInstance'); |
| var controllerServicesData = controllerServicesGrid.getData(); |
| |
| // update the controller services |
| controllerServicesData.setItems(services); |
| controllerServicesData.reSort(); |
| controllerServicesGrid.invalidate(); |
| }); |
| }; |
| |
| /** |
| * 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 getReportingTaskTypeFilterText = function () { |
| var filterText = ''; |
| var filterField = $('#reporting-task-type-filter'); |
| if (!filterField.hasClass(config.styles.filterList)) { |
| filterText = filterField.val(); |
| } |
| return filterText; |
| }; |
| |
| /** |
| * Filters the reporting task type table. |
| */ |
| var applyReportingTaskTypeFilter = function () { |
| // get the dataview |
| var reportingTaskTypesGrid = $('#reporting-task-types-table').data('gridInstance'); |
| |
| // ensure the grid has been initialized |
| if (nf.Common.isDefinedAndNotNull(reportingTaskTypesGrid)) { |
| var reportingTaskTypesData = reportingTaskTypesGrid.getData(); |
| |
| // update the search criteria |
| reportingTaskTypesData.setFilterArgs({ |
| searchString: getReportingTaskTypeFilterText(), |
| property: $('#reporting-task-type-filter-options').combo('getSelectedOption').value |
| }); |
| |
| // need to invalidate the entire table since parent elements may need to be |
| // rerendered due to changes in their children |
| reportingTaskTypesData.refresh(); |
| reportingTaskTypesGrid.invalidate(); |
| } |
| }; |
| |
| /** |
| * Hides the selected reporting task. |
| */ |
| var clearSelectedReportingTask = function () { |
| $('#reporting-task-type-description').text(''); |
| $('#reporting-task-type-name').text(''); |
| $('#reporting-task-availability-combo').combo('setSelectedOption', { |
| value: config.node |
| }); |
| $('#selected-reporting-task-name').text(''); |
| $('#selected-reporting-task-type').text(''); |
| $('#reporting-task-description-container').hide(); |
| }; |
| |
| /** |
| * Clears the selected reporting task type. |
| */ |
| var clearReportingTaskSelection = function () { |
| // clear the selected row |
| clearSelectedReportingTask(); |
| |
| // clear the active cell the it can be reselected when its included |
| var reportingTaskTypesGrid = $('#reporting-task-types-table').data('gridInstance'); |
| reportingTaskTypesGrid.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 filterReportingTaskTypes = 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 = $('#reporting-task-tag-cloud').tagcloud('getSelectedTags'); |
| var hasSelectedTags = tagFilters.length > 0; |
| if (hasSelectedTags) { |
| matchesTags = matchesSelectedTags(tagFilters, item['tags']); |
| } |
| } |
| |
| // determine if this row should be visible |
| var matches = matchesFilter && matchesTags; |
| |
| // if this row is currently selected and its being filtered |
| if (matches === false && $('#selected-reporting-task-type').text() === item['type']) { |
| clearReportingTaskSelection(); |
| } |
| |
| // update visibility flag |
| item.visible = matches; |
| |
| return matches; |
| }; |
| |
| /** |
| * Adds a new reporting task of the specified type. |
| * |
| * @param {string} reportingTaskType |
| */ |
| var addReportingTask = function (reportingTaskType) { |
| var revision = nf.Client.getRevision(); |
| |
| // get the desired availability |
| var availability; |
| if (nf.Canvas.isClustered()) { |
| availability = $('#reporting-task-availability-combo').combo('getSelectedOption').value; |
| } else { |
| availability = config.node; |
| } |
| |
| // add the new reporting task |
| var addTask = $.ajax({ |
| type: 'POST', |
| url: config.urls.reportingTasks + '/' + encodeURIComponent(availability), |
| data: { |
| version: revision.version, |
| clientId: revision.clientId, |
| type: reportingTaskType |
| }, |
| dataType: 'json' |
| }).done(function (response) { |
| // update the revision |
| nf.Client.setRevision(response.revision); |
| |
| // add the item |
| var reportingTask = response.reportingTask; |
| var reportingTaskGrid = $('#reporting-tasks-table').data('gridInstance'); |
| var reportingTaskData = reportingTaskGrid.getData(); |
| reportingTaskData.addItem(reportingTask); |
| |
| // resort |
| reportingTaskData.reSort(); |
| reportingTaskGrid.invalidate(); |
| |
| // select the new reporting task |
| var row = reportingTaskData.getRowById(reportingTask.id); |
| reportingTaskGrid.setSelectedRows([row]); |
| }).fail(nf.Common.handleAjaxError); |
| |
| // hide the dialog |
| $('#new-reporting-task-dialog').modal('hide'); |
| |
| return addTask; |
| }; |
| |
| /** |
| * Initializes the new reporting task dialog. |
| */ |
| var initNewReportingTaskDialog = function () { |
| // specify the combo options |
| $('#reporting-task-type-filter-options').combo({ |
| options: [{ |
| text: 'by type', |
| value: 'label' |
| }, { |
| text: 'by tag', |
| value: 'tags' |
| }], |
| select: function (option) { |
| applyReportingTaskTypeFilter(); |
| } |
| }); |
| |
| // specify the reporting task availability |
| if (nf.Canvas.isClustered()) { |
| $('#reporting-task-availability-combo').combo({ |
| options: [{ |
| text: 'Node', |
| value: config.node, |
| description: 'This reporting task will be available on the nodes only.' |
| }, { |
| text: 'Cluster Manager', |
| value: config.ncm, |
| description: 'This reporting task will be available on the cluster manager only.' |
| }] |
| }); |
| $('#reporting-task-availability-container').show(); |
| } |
| |
| // define the function for filtering the list |
| $('#reporting-task-type-filter').keyup(function () { |
| applyReportingTaskTypeFilter(); |
| }).focus(function () { |
| if ($(this).hasClass(config.styles.filterList)) { |
| $(this).removeClass(config.styles.filterList).val(''); |
| } |
| }).blur(function () { |
| if ($(this).val() === '') { |
| $(this).addClass(config.styles.filterList).val(config.filterText); |
| } |
| }).addClass(config.styles.filterList).val(config.filterText); |
| |
| // initialize the processor type table |
| var reportingTaskTypesColumns = [ |
| {id: 'type', name: 'Type', field: 'label', sortable: false, resizable: true}, |
| {id: 'tags', name: 'Tags', field: 'tags', sortable: false, resizable: true} |
| ]; |
| |
| // initialize the dataview |
| var reportingTaskTypesData = new Slick.Data.DataView({ |
| inlineFilters: false |
| }); |
| reportingTaskTypesData.setItems([]); |
| reportingTaskTypesData.setFilterArgs({ |
| searchString: getReportingTaskTypeFilterText(), |
| property: $('#reporting-task-type-filter-options').combo('getSelectedOption').value |
| }); |
| reportingTaskTypesData.setFilter(filterReportingTaskTypes); |
| |
| // initialize the grid |
| var reportingTaskTypesGrid = new Slick.Grid('#reporting-task-types-table', reportingTaskTypesData, reportingTaskTypesColumns, gridOptions); |
| reportingTaskTypesGrid.setSelectionModel(new Slick.RowSelectionModel()); |
| reportingTaskTypesGrid.registerPlugin(new Slick.AutoTooltips()); |
| reportingTaskTypesGrid.setSortColumn('type', true); |
| reportingTaskTypesGrid.onSelectedRowsChanged.subscribe(function (e, args) { |
| var reportingTaskTypeIndex = args.rows[0]; |
| var reportingTaskType = reportingTaskTypesGrid.getDataItem(reportingTaskTypeIndex); |
| |
| // set the reporting task type description |
| if (nf.Common.isBlank(reportingTaskType.description)) { |
| $('#reporting-task-type-description').attr('title', '').html('<span class="unset">No description specified</span>'); |
| } else { |
| $('#reporting-task-type-description').text(reportingTaskType.description).ellipsis(); |
| } |
| |
| // populate the dom |
| $('#reporting-task-type-name').text(reportingTaskType.label).ellipsis(); |
| $('#selected-reporting-task-name').text(reportingTaskType.label); |
| $('#selected-reporting-task-type').text(reportingTaskType.type); |
| |
| // show the selected reporting task |
| $('#reporting-task-description-container').show(); |
| }); |
| reportingTaskTypesGrid.onDblClick.subscribe(function (e, args) { |
| var reportingTaskType = reportingTaskTypesGrid.getDataItem(args.row); |
| addReportingTask(reportingTaskType.type); |
| }); |
| |
| // wire up the dataview to the grid |
| reportingTaskTypesData.onRowCountChanged.subscribe(function (e, args) { |
| reportingTaskTypesGrid.updateRowCount(); |
| reportingTaskTypesGrid.render(); |
| |
| // update the total number of displayed processors |
| $('#displayed-reporting-task-types').text(args.current); |
| }); |
| reportingTaskTypesData.onRowsChanged.subscribe(function (e, args) { |
| reportingTaskTypesGrid.invalidateRows(args.rows); |
| reportingTaskTypesGrid.render(); |
| }); |
| reportingTaskTypesData.syncGridSelection(reportingTaskTypesGrid, true); |
| |
| // hold onto an instance of the grid |
| $('#reporting-task-types-table').data('gridInstance', reportingTaskTypesGrid); |
| |
| // load the available reporting tasks |
| $.ajax({ |
| type: 'GET', |
| url: config.urls.reportingTaskTypes, |
| dataType: 'json' |
| }).done(function (response) { |
| var id = 0; |
| var tags = []; |
| |
| // begin the update |
| reportingTaskTypesData.beginUpdate(); |
| |
| // go through each reporting task type |
| $.each(response.reportingTaskTypes, function (i, documentedType) { |
| // add the documented type |
| reportingTaskTypesData.addItem({ |
| id: id++, |
| label: nf.Common.substringAfterLast(documentedType.type, '.'), |
| type: documentedType.type, |
| description: nf.Common.escapeHtml(documentedType.description), |
| tags: documentedType.tags.join(', '), |
| children: [], |
| collapsed: false, |
| visible: true |
| }); |
| |
| // count the frequency of each tag for this type |
| $.each(documentedType.tags, function (i, tag) { |
| tags.push(tag.toLowerCase()); |
| }); |
| }); |
| |
| // end the udpate |
| reportingTaskTypesData.endUpdate(); |
| |
| // set the total number of processors |
| $('#total-reporting-task-types, #displayed-reporting-task-types').text(response.reportingTaskTypes.length); |
| |
| // create the tag cloud |
| $('#reporting-task-tag-cloud').tagcloud({ |
| tags: tags, |
| select: applyReportingTaskTypeFilter, |
| remove: applyReportingTaskTypeFilter |
| }); |
| }).fail(nf.Common.handleAjaxError); |
| |
| // initialize the reporting task dialog |
| $('#new-reporting-task-dialog').modal({ |
| headerText: 'Add Reporting Task', |
| overlayBackground: false, |
| buttons: [{ |
| buttonText: 'Add', |
| handler: { |
| click: function () { |
| var selectedTaskType = $('#selected-reporting-task-type').text(); |
| addReportingTask(selectedTaskType); |
| } |
| } |
| }, { |
| buttonText: 'Cancel', |
| handler: { |
| click: function () { |
| $(this).modal('hide'); |
| } |
| } |
| }], |
| close: function () { |
| // clear the selected row |
| clearSelectedReportingTask(); |
| |
| // unselect any current selection |
| var reportingTaskTypesGrid = $('#reporting-task-types-table').data('gridInstance'); |
| reportingTaskTypesGrid.setSelectedRows([]); |
| reportingTaskTypesGrid.resetActiveCell(); |
| |
| // clear any filter strings |
| $('#reporting-task-type-filter').addClass(config.styles.filterList).val(config.filterText); |
| |
| // clear the tagcloud |
| $('#reporting-task-tag-cloud').tagcloud('clearSelectedTags'); |
| } |
| }).draggable({ |
| containment: 'parent', |
| handle: '.dialog-header' |
| }); |
| }; |
| |
| /** |
| * Initializes the reporting tasks tab. |
| */ |
| var initReportingTasks = function () { |
| // initialize the new reporting task dialog |
| initNewReportingTaskDialog(); |
| |
| var moreReportingTaskDetails = function (row, cell, value, columnDef, dataContext) { |
| var markup = '<img src="images/iconDetails.png" title="View Details" class="pointer view-reporting-task" style="margin-top: 5px; float: left;" /> '; |
| if (!nf.Common.isEmpty(dataContext.validationErrors)) { |
| markup += '<img src="images/iconAlert.png" class="has-errors" style="margin-top: 4px; float: left;" /><span class="hidden row-id">' + nf.Common.escapeHtml(dataContext.id) + '</span>'; |
| } |
| return markup; |
| }; |
| |
| var reportingTaskRunStatusFormatter = function (row, cell, value, columnDef, dataContext) { |
| // determine the appropriate label |
| var label; |
| if (!nf.Common.isEmpty(dataContext.validationErrors)) { |
| label = 'Invalid'; |
| } else { |
| if (value === 'STOPPED') { |
| label = 'Stopped'; |
| } else if (value === 'RUNNING') { |
| label = 'Running'; |
| } else { |
| label = 'Disabled'; |
| } |
| } |
| |
| // include the active thread count if appropriate |
| var activeThreadCount = ''; |
| if (nf.Common.isDefinedAndNotNull(dataContext.activeThreadCount) && dataContext.activeThreadCount > 0) { |
| activeThreadCount = '(' + dataContext.activeThreadCount + ')'; |
| } |
| |
| // format the markup |
| var formattedValue = '<div class="' + nf.Common.escapeHtml(label.toLowerCase()) + '" style="margin-top: 3px;"></div>'; |
| return formattedValue + '<div class="status-text" style="margin-top: 2px; margin-left: 4px; float: left;">' + nf.Common.escapeHtml(label) + '</div><div style="float: left; margin-left: 4px;">' + nf.Common.escapeHtml(activeThreadCount) + '</div>'; |
| }; |
| |
| var reportingTaskActionFormatter = function (row, cell, value, columnDef, dataContext) { |
| var markup = ''; |
| |
| // only DFMs can edit reporting tasks |
| if (nf.Common.isDFM()) { |
| if (dataContext.state === 'RUNNING') { |
| markup += '<img src="images/iconStop.png" title="Stop" class="pointer stop-reporting-task" style="margin-top: 2px;" /> '; |
| } else if (dataContext.state === 'STOPPED' || dataContext.state === 'DISABLED') { |
| markup += '<img src="images/iconEdit.png" title="Edit" class="pointer edit-reporting-task" style="margin-top: 2px;" /> '; |
| markup += '<img src="images/iconRun.png" title="Start" class="pointer start-reporting-task" style="margin-top: 2px;"/> '; |
| markup += '<img src="images/iconDelete.png" title="Remove" class="pointer delete-reporting-task" style="margin-top: 2px;" /> '; |
| } |
| } |
| |
| // always include a button to view the usage |
| markup += '<img src="images/iconUsage.png" title="Usage" class="pointer reporting-task-usage" style="margin-top: 2px;"/> '; |
| |
| return markup; |
| }; |
| |
| // define the column model for the reporting tasks table |
| var reportingTasksColumnModel = [ |
| {id: 'moreDetails', field: 'moreDetails', name: ' ', resizable: false, formatter: moreReportingTaskDetails, sortable: true, width: 50, maxWidth: 50}, |
| {id: 'name', field: 'name', name: 'Name', sortable: true, resizable: true}, |
| {id: 'type', field: 'type', name: 'Type', sortable: true, resizable: true, formatter: typeFormatter}, |
| {id: 'state', field: 'state', name: 'State', sortable: true, resizeable: true, formatter: reportingTaskRunStatusFormatter}, |
| {id: 'actions', name: ' ', resizable: false, formatter: reportingTaskActionFormatter, sortable: false, width: 90, maxWidth: 90} |
| ]; |
| |
| // only show availability when clustered |
| if (nf.Canvas.isClustered()) { |
| reportingTasksColumnModel.push({id: 'availability', field: 'availability', name: 'Availability', formatter: availabilityFormatter, sortable: true, resizeable: true}); |
| } |
| |
| // initialize the dataview |
| var reportingTasksData = new Slick.Data.DataView({ |
| inlineFilters: false |
| }); |
| reportingTasksData.setItems([]); |
| |
| // initialize the sort |
| sort({ |
| columnId: 'name', |
| sortAsc: true |
| }, reportingTasksData); |
| |
| // initialize the grid |
| var reportingTasksGrid = new Slick.Grid('#reporting-tasks-table', reportingTasksData, reportingTasksColumnModel, gridOptions); |
| reportingTasksGrid.setSelectionModel(new Slick.RowSelectionModel()); |
| reportingTasksGrid.registerPlugin(new Slick.AutoTooltips()); |
| reportingTasksGrid.setSortColumn('name', true); |
| reportingTasksGrid.onSort.subscribe(function (e, args) { |
| sort({ |
| columnId: args.sortCol.field, |
| sortAsc: args.sortAsc |
| }, reportingTasksData); |
| }); |
| |
| // configure a click listener |
| reportingTasksGrid.onClick.subscribe(function (e, args) { |
| var target = $(e.target); |
| |
| // get the service at this row |
| var reportingTask = reportingTasksData.getItem(args.row); |
| |
| // determine the desired action |
| if (reportingTasksGrid.getColumns()[args.cell].id === 'actions') { |
| if (target.hasClass('edit-reporting-task')) { |
| nf.ReportingTask.showConfiguration(reportingTask); |
| } else if (target.hasClass('start-reporting-task')) { |
| nf.ReportingTask.start(reportingTask); |
| } else if (target.hasClass('stop-reporting-task')) { |
| nf.ReportingTask.stop(reportingTask); |
| } else if (target.hasClass('delete-reporting-task')) { |
| nf.ReportingTask.remove(reportingTask); |
| } else if (target.hasClass('reporting-task-usage')) { |
| // close the settings dialog |
| $('#shell-close-button').click(); |
| |
| // open the documentation for this reporting task |
| nf.Shell.showPage('../nifi-docs/documentation?' + $.param({ |
| select: nf.Common.substringAfterLast(reportingTask.type, '.') |
| })); |
| } |
| } else if (reportingTasksGrid.getColumns()[args.cell].id === 'moreDetails') { |
| if (target.hasClass('view-reporting-task')) { |
| |
| } |
| } |
| }); |
| |
| // wire up the dataview to the grid |
| reportingTasksData.onRowCountChanged.subscribe(function (e, args) { |
| reportingTasksGrid.updateRowCount(); |
| reportingTasksGrid.render(); |
| }); |
| reportingTasksData.onRowsChanged.subscribe(function (e, args) { |
| reportingTasksGrid.invalidateRows(args.rows); |
| reportingTasksGrid.render(); |
| }); |
| reportingTasksData.syncGridSelection(reportingTasksGrid, true); |
| |
| // hold onto an instance of the grid |
| $('#reporting-tasks-table').data('gridInstance', reportingTasksGrid).on('mouseenter', 'div.slick-cell', function (e) { |
| var errorIcon = $(this).find('img.has-errors'); |
| if (errorIcon.length && !errorIcon.data('qtip')) { |
| var taskId = $(this).find('span.row-id').text(); |
| |
| // get the service item |
| var item = reportingTasksData.getItemById(taskId); |
| |
| // format the errors |
| var tooltip = nf.Common.formatUnorderedList(item.validationErrors); |
| |
| // show the tooltip |
| if (nf.Common.isDefinedAndNotNull(tooltip)) { |
| errorIcon.qtip($.extend({ |
| content: tooltip, |
| position: { |
| target: 'mouse', |
| viewport: $(window), |
| adjust: { |
| x: 8, |
| y: 8, |
| method: 'flipinvert flipinvert' |
| } |
| } |
| }, nf.Common.config.tooltipConfig)); |
| } |
| } |
| }); |
| }; |
| |
| /** |
| * Loads the reporting tasks. |
| */ |
| var loadReportingTasks = function () { |
| var tasks = []; |
| |
| // get the reporting tasks that are running on the nodes |
| var nodeReportingTasks = $.ajax({ |
| type: 'GET', |
| url: config.urls.reportingTasks + '/' + encodeURIComponent(config.node), |
| dataType: 'json' |
| }).done(function (response) { |
| var nodeTasks = response.reportingTasks; |
| if (nf.Common.isDefinedAndNotNull(nodeTasks)) { |
| $.each(nodeTasks, function (_, nodeTask) { |
| tasks.push(nodeTask); |
| }); |
| } |
| }); |
| |
| // get the reporting tasks that are running on the ncm |
| var ncmReportingTasks = $.Deferred(function (deferred) { |
| if (nf.Canvas.isClustered()) { |
| $.ajax({ |
| type: 'GET', |
| url: config.urls.reportingTasks + '/' + encodeURIComponent(config.ncm), |
| dataType: 'json' |
| }).done(function (response) { |
| var ncmTasks = response.reportingTasks; |
| if (nf.Common.isDefinedAndNotNull(ncmTasks)) { |
| $.each(ncmTasks, function (_, ncmTask) { |
| tasks.push(ncmTask); |
| }); |
| } |
| deferred.resolve(); |
| }).fail(function () { |
| deferred.reject(); |
| }); |
| } else { |
| deferred.resolve(); |
| } |
| }).promise(); |
| |
| // add all reporting tasks |
| return $.when(nodeReportingTasks, ncmReportingTasks).done(function () { |
| var reportingTasksElement = $('#reporting-tasks-table'); |
| nf.Common.cleanUpTooltips(reportingTasksElement, 'img.has-errors'); |
| |
| var reportingTasksGrid = reportingTasksElement.data('gridInstance'); |
| var reportingTasksData = reportingTasksGrid.getData(); |
| |
| // update the reporting tasks |
| reportingTasksData.setItems(tasks); |
| reportingTasksData.reSort(); |
| reportingTasksGrid.invalidate(); |
| }); |
| }; |
| |
| return { |
| /** |
| * Initializes the status page. |
| */ |
| init: function () { |
| // initialize the settings tabs |
| $('#settings-tabs').tabbs({ |
| tabStyle: 'settings-tab', |
| selectedTabStyle: 'settings-selected-tab', |
| tabs: [{ |
| name: 'General', |
| tabContentId: 'general-settings-tab-content' |
| }, { |
| name: 'Controller Services', |
| tabContentId: 'controller-services-tab-content' |
| }, { |
| name: 'Reporting Tasks', |
| tabContentId: 'reporting-tasks-tab-content' |
| }], |
| select: function () { |
| var tab = $(this).text(); |
| if (tab === 'General') { |
| $('#new-service-or-task').hide(); |
| } else { |
| $('#new-service-or-task').show(); |
| |
| // update the tooltip on the button |
| $('#new-service-or-task').attr('title', function () { |
| if (tab === 'Controller Services') { |
| return 'Create a new controller service'; |
| } else if (tab === 'Reporting Tasks') { |
| return 'Create a new reporting task'; |
| } |
| }); |
| |
| // resize the table |
| nf.Settings.resetTableSize(); |
| } |
| } |
| }); |
| |
| // setup the tooltip for the refresh icon |
| $('#settings-refresh-required-icon').qtip($.extend({ |
| content: 'This flow has been modified by another user. Please refresh.' |
| }, nf.CanvasUtils.config.systemTooltipConfig)); |
| |
| // refresh the system diagnostics when clicked |
| nf.Common.addHoverEffect('#settings-refresh-button', 'button-refresh', 'button-refresh-hover').click(function () { |
| if ($('#settings-refresh-required-icon').is(':visible')) { |
| nf.CanvasHeader.reloadAndClearWarnings(); |
| } else { |
| nf.Settings.loadSettings(); |
| } |
| }); |
| |
| // create a new controller service or reporting task |
| $('#new-service-or-task').on('click', function () { |
| var selectedTab = $('li.settings-selected-tab').text(); |
| if (selectedTab === 'Controller Services') { |
| $('#new-controller-service-dialog').modal('show'); |
| |
| // reset the canvas size after the dialog is shown |
| var controllerServiceTypesGrid = $('#controller-service-types-table').data('gridInstance'); |
| if (nf.Common.isDefinedAndNotNull(controllerServiceTypesGrid)) { |
| controllerServiceTypesGrid.resizeCanvas(); |
| } |
| } else if (selectedTab === 'Reporting Tasks') { |
| $('#new-reporting-task-dialog').modal('show'); |
| |
| // reset the canvas size after the dialog is shown |
| var reportingTaskTypesGrid = $('#reporting-task-types-table').data('gridInstance'); |
| if (nf.Common.isDefinedAndNotNull(reportingTaskTypesGrid)) { |
| reportingTaskTypesGrid.resizeCanvas(); |
| } |
| } |
| }); |
| |
| // initialize each tab |
| initGeneral(); |
| initControllerServices(); |
| initReportingTasks(); |
| }, |
| /** |
| * Update the size of the grid based on its container's current size. |
| */ |
| resetTableSize: function () { |
| var controllerServicesGrid = $('#controller-services-table').data('gridInstance'); |
| if (nf.Common.isDefinedAndNotNull(controllerServicesGrid)) { |
| controllerServicesGrid.resizeCanvas(); |
| } |
| |
| var reportingTasksGrid = $('#reporting-tasks-table').data('gridInstance'); |
| if (nf.Common.isDefinedAndNotNull(reportingTasksGrid)) { |
| reportingTasksGrid.resizeCanvas(); |
| } |
| }, |
| /** |
| * Shows the settings dialog. |
| */ |
| showSettings: function () { |
| return nf.Settings.loadSettings().done(function () { |
| // show the settings dialog |
| nf.Shell.showContent('#settings').done(function () { |
| // reset button state |
| $('#settings-save').mouseout(); |
| }); |
| }); |
| }, |
| /** |
| * Loads the settings. |
| */ |
| loadSettings: function () { |
| var settings = $.ajax({ |
| type: 'GET', |
| url: config.urls.controllerConfig, |
| dataType: 'json' |
| }).done(function (response) { |
| // ensure the config is present |
| if (nf.Common.isDefinedAndNotNull(response.config)) { |
| // set the header |
| $('#settings-header-text').text(response.config.name + ' Settings'); |
| $('#settings-last-refreshed').text(response.config.currentTime); |
| |
| // populate the controller settings |
| if (nf.Common.isDFM()) { |
| $('#data-flow-title-field').val(response.config.name); |
| $('#data-flow-comments-field').val(response.config.comments); |
| $('#maximum-timer-driven-thread-count-field').val(response.config.maxTimerDrivenThreadCount); |
| $('#maximum-event-driven-thread-count-field').val(response.config.maxEventDrivenThreadCount); |
| } else { |
| $('#read-only-data-flow-title-field').html(nf.Common.formatValue(response.config.name)); |
| $('#read-only-data-flow-comments-field').html(nf.Common.formatValue(response.config.comments)); |
| $('#read-only-maximum-timer-driven-thread-count-field').text(response.config.maxTimerDrivenThreadCount); |
| $('#read-only-maximum-event-driven-thread-count-field').text(response.config.maxEventDrivenThreadCount); |
| } |
| } |
| }); |
| |
| // load the controller services |
| var controllerServices = loadControllerServices(); |
| |
| // load the reporting tasks |
| var reportingTasks = loadReportingTasks(); |
| |
| // return a deferred for all parts of the settings |
| return $.when(settings, controllerServices, reportingTasks).fail(nf.Common.handleAjaxError); |
| } |
| }; |
| }()); |