Link DCAE MOD design tool to Acumos Adapter
[dcaegen2/platform.git] / mod / designtool / designtool-web / src / main / webapp / js / nf / canvas / nf-settings.js
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * Modifications to the original nifi code for the ONAP project are made
18  * available under the Apache License, Version 2.0
19  */
20
21 /* global define, module, require, exports */
22
23 (function (root, factory) {
24     if (typeof define === 'function' && define.amd) {
25         define(['jquery',
26                 'Slick',
27                 'd3',
28                 'nf.Client',
29                 'nf.Dialog',
30                 'nf.Storage',
31                 'nf.Common',
32                 'nf.CanvasUtils',
33                 'nf.ControllerServices',
34                 'nf.ErrorHandler',
35                 'nf.FilteredDialogCommon',
36                 'nf.ReportingTask',
37                 'nf.Shell',
38                 'nf.ComponentState',
39                 'nf.ComponentVersion',
40                 'nf.PolicyManagement'],
41             function ($, Slick, d3, nfClient, nfDialog, nfStorage, nfCommon, nfCanvasUtils, nfControllerServices, nfErrorHandler, nfFilteredDialogCommon, nfReportingTask, nfShell, nfComponentState, nfComponentVersion, nfPolicyManagement) {
42                 return (nf.Settings = factory($, Slick, d3, nfClient, nfDialog, nfStorage, nfCommon, nfCanvasUtils, nfControllerServices, nfErrorHandler, nfFilteredDialogCommon, nfReportingTask, nfShell, nfComponentState, nfComponentVersion, nfPolicyManagement));
43             });
44     } else if (typeof exports === 'object' && typeof module === 'object') {
45         module.exports = (nf.Settings =
46             factory(require('jquery'),
47                 require('Slick'),
48                 require('d3'),
49                 require('nf.Client'),
50                 require('nf.Dialog'),
51                 require('nf.Storage'),
52                 require('nf.Common'),
53                 require('nf.CanvasUtils'),
54                 require('nf.ControllerServices'),
55                 require('nf.ErrorHandler'),
56                 require('nf.FilteredDialogCommon'),
57                 require('nf.ReportingTask'),
58                 require('nf.Shell'),
59                 require('nf.ComponentState'),
60                 require('nf.ComponentVersion'),
61                 require('nf.PolicyManagement')));
62     } else {
63         nf.Settings = factory(root.$,
64             root.Slick,
65             root.d3,
66             root.nf.Client,
67             root.nf.Dialog,
68             root.nf.Storage,
69             root.nf.Common,
70             root.nf.CanvasUtils,
71             root.nf.ControllerServices,
72             root.nf.ErrorHandler,
73             root.nf.FilteredDialogCommon,
74             root.nf.ReportingTask,
75             root.nf.Shell,
76             root.nf.ComponentState,
77             root.nf.ComponentVersion,
78             root.nf.PolicyManagement);
79     }
80 }(this, function ($, Slick, d3, nfClient, nfDialog, nfStorage, nfCommon, nfCanvasUtils, nfControllerServices, nfErrorHandler, nfFilteredDialogCommon, nfReportingTask, nfShell, nfComponentState, nfComponentVersion, nfPolicyManagement) {
81     'use strict';
82
83
84     var config = {
85         urls: {
86             api: '../nifi-api',
87             controllerConfig: '../nifi-api/controller/config',
88             reportingTaskTypes: '../nifi-api/flow/reporting-task-types',
89             createReportingTask: '../nifi-api/controller/reporting-tasks',
90             reportingTasks: '../nifi-api/flow/reporting-tasks',
91             registries: '../nifi-api/controller/registry-clients'
92         }
93     };
94
95     var gridOptions = {
96         forceFitColumns: true,
97         enableTextSelectionOnCells: true,
98         enableCellNavigation: true,
99         enableColumnReorder: false,
100         autoEdit: false,
101         multiSelect: false,
102         rowHeight: 24
103     };
104
105
106     /**
107      * Gets the controller services table.
108      *
109      * @returns {*|jQuery|HTMLElement}
110      */
111     var getDistributionEnvironmentsTable = function () {
112         return $('#distribution-environments-table');
113     };
114
115     /**
116      * Gets the controller services table.
117      *
118      * @returns {*|jQuery|HTMLElement}
119      */
120     var getControllerServicesTable = function () {
121         return $('#controller-services-table');
122     };
123
124     /**
125      * Saves the settings for the controller.
126      *
127      * @param version
128      */
129     var saveSettings = function (version) {
130         // marshal the configuration details
131         var configuration = marshalConfiguration();
132         var entity = {
133             'revision': nfClient.getRevision({
134                 'revision': {
135                     'version': version
136                 }
137             }),
138             'disconnectedNodeAcknowledged': nfStorage.isDisconnectionAcknowledged(),
139             'component': configuration
140         };
141
142         // save the new configuration details
143         $.ajax({
144             type: 'PUT',
145             url: config.urls.controllerConfig,
146             data: JSON.stringify(entity),
147             dataType: 'json',
148             contentType: 'application/json'
149         }).done(function (response) {
150             // close the settings dialog
151             nfDialog.showOkDialog({
152                 headerText: 'Settings',
153                 dialogContent: 'Settings successfully applied.'
154             });
155
156             // register the click listener for the save button
157             $('#settings-save').off('click').on('click', function () {
158                 saveSettings(response.revision.version);
159             });
160         }).fail(nfErrorHandler.handleAjaxError);
161     }
162
163     /**
164      * Initializes the general tab.
165      */
166     var initGeneral = function () {
167     };
168
169     /**
170      * Marshals the details to include in the configuration request.
171      */
172     var marshalConfiguration = function () {
173         // create the configuration
174         var configuration = {};
175         configuration['maxTimerDrivenThreadCount'] = $('#maximum-timer-driven-thread-count-field').val();
176         configuration['maxEventDrivenThreadCount'] = $('#maximum-event-driven-thread-count-field').val();
177         return configuration;
178     };
179
180     /**
181      * Determines if the item matches the filter.
182      *
183      * @param {object} item     The item to filter
184      * @param {object} args     The filter criteria
185      * @returns {boolean}       Whether the item matches the filter
186      */
187     var matchesRegex = function (item, args) {
188         if (args.searchString === '') {
189             return true;
190         }
191
192         try {
193             // perform the row filtering
194             var filterExp = new RegExp(args.searchString, 'i');
195         } catch (e) {
196             // invalid regex
197             return false;
198         }
199
200         // determine if the item matches the filter
201         var matchesLabel = item['label'].search(filterExp) >= 0;
202         var matchesTags = item['tags'].search(filterExp) >= 0;
203         return matchesLabel || matchesTags;
204     };
205
206     /**
207      * Determines if the specified tags match all the tags selected by the user.
208      *
209      * @argument {string[]} tagFilters      The tag filters
210      * @argument {string} tags              The tags to test
211      */
212     var matchesSelectedTags = function (tagFilters, tags) {
213         var selectedTags = [];
214         $.each(tagFilters, function (_, filter) {
215             selectedTags.push(filter);
216         });
217
218         // normalize the tags
219         var normalizedTags = tags.toLowerCase();
220
221         var matches = true;
222         $.each(selectedTags, function (i, selectedTag) {
223             if (normalizedTags.indexOf(selectedTag) === -1) {
224                 matches = false;
225                 return false;
226             }
227         });
228
229         return matches;
230     };
231
232     /**
233      * Whether the specified item is selectable.
234      *
235      * @param item reporting task type
236      */
237     var isSelectable = function (item) {
238         return item.restricted === false || nfCommon.canAccessComponentRestrictions(item.explicitRestrictions);
239     };
240
241     /**
242      * Formatter for the name column.
243      *
244      * @param {type} row
245      * @param {type} cell
246      * @param {type} value
247      * @param {type} columnDef
248      * @param {type} dataContext
249      * @returns {String}
250      */
251     var nameFormatter = function (row, cell, value, columnDef, dataContext) {
252         if (!dataContext.permissions.canRead) {
253             return '<span class="blank">' + nfCommon.escapeHtml(dataContext.id) + '</span>';
254         }
255
256         return nfCommon.escapeHtml(dataContext.component.name);
257     };
258
259     /**
260      * Sorts the specified data using the specified sort details.
261      *
262      * @param {object} sortDetails
263      * @param {object} data
264      */
265     var sort = function (sortDetails, data) {
266         // defines a function for sorting
267         var comparer = function (a, b) {
268             if (a.permissions.canRead && b.permissions.canRead) {
269                 if (sortDetails.columnId === 'moreDetails') {
270                     var aBulletins = 0;
271                     if (!nfCommon.isEmpty(a.bulletins)) {
272                         aBulletins = a.bulletins.length;
273                     }
274                     var bBulletins = 0;
275                     if (!nfCommon.isEmpty(b.bulletins)) {
276                         bBulletins = b.bulletins.length;
277                     }
278                     return aBulletins - bBulletins;
279                 } else if (sortDetails.columnId === 'type') {
280                     var aType = nfCommon.isDefinedAndNotNull(a.component[sortDetails.columnId]) ? nfCommon.substringAfterLast(a.component[sortDetails.columnId], '.') : '';
281                     var bType = nfCommon.isDefinedAndNotNull(b.component[sortDetails.columnId]) ? nfCommon.substringAfterLast(b.component[sortDetails.columnId], '.') : '';
282                     return aType === bType ? 0 : aType > bType ? 1 : -1;
283                 } else if (sortDetails.columnId === 'state') {
284                     var aState;
285                     if (a.component.validationStatus === 'VALIDATING') {
286                         aState = 'Validating';
287                     } else if (a.component.validationStatus === 'INVALID') {
288                         aState = 'Invalid';
289                     } else {
290                         aState = nfCommon.isDefinedAndNotNull(a.component[sortDetails.columnId]) ? a.component[sortDetails.columnId] : '';
291                     }
292                     var bState;
293                     if (b.component.validationStatus === 'VALIDATING') {
294                         bState = 'Validating';
295                     } else if (b.component.validationStatus === 'INVALID') {
296                         bState = 'Invalid';
297                     } else {
298                         bState = nfCommon.isDefinedAndNotNull(b.component[sortDetails.columnId]) ? b.component[sortDetails.columnId] : '';
299                     }
300                     return aState === bState ? 0 : aState > bState ? 1 : -1;
301                 } else {
302                     var aString = nfCommon.isDefinedAndNotNull(a.component[sortDetails.columnId]) ? a.component[sortDetails.columnId] : '';
303                     var bString = nfCommon.isDefinedAndNotNull(b.component[sortDetails.columnId]) ? b.component[sortDetails.columnId] : '';
304                     return aString === bString ? 0 : aString > bString ? 1 : -1;
305                 }
306             } else {
307                 if (!a.permissions.canRead && !b.permissions.canRead) {
308                     return 0;
309                 }
310                 if (a.permissions.canRead) {
311                     return 1;
312                 } else {
313                     return -1;
314                 }
315             }
316         };
317
318         // perform the sort
319         data.sort(comparer, sortDetails.sortAsc);
320     };
321
322     /**
323      * Get the text out of the filter field. If the filter field doesn't
324      * have any text it will contain the text 'filter list' so this method
325      * accounts for that.
326      */
327     var getReportingTaskTypeFilterText = function () {
328         return $('#reporting-task-type-filter').val();
329     };
330
331     /**
332      * Filters the reporting task type table.
333      */
334     var applyReportingTaskTypeFilter = function () {
335         // get the dataview
336         var reportingTaskTypesGrid = $('#reporting-task-types-table').data('gridInstance');
337
338         // ensure the grid has been initialized
339         if (nfCommon.isDefinedAndNotNull(reportingTaskTypesGrid)) {
340             var reportingTaskTypesData = reportingTaskTypesGrid.getData();
341
342             // update the search criteria
343             reportingTaskTypesData.setFilterArgs({
344                 searchString: getReportingTaskTypeFilterText()
345             });
346             reportingTaskTypesData.refresh();
347
348             // update the buttons to possibly trigger the disabled state
349             $('#new-reporting-task-dialog').modal('refreshButtons');
350
351             // update the selection if possible
352             if (reportingTaskTypesData.getLength() > 0) {
353                 nfFilteredDialogCommon.choseFirstRow(reportingTaskTypesGrid);
354             }
355         }
356     };
357
358     /**
359      * Hides the selected reporting task.
360      */
361     var clearSelectedReportingTask = function () {
362         $('#reporting-task-type-description').attr('title', '').text('');
363         $('#reporting-task-type-name').attr('title', '').text('');
364         $('#reporting-task-type-bundle').attr('title', '').text('');
365         $('#selected-reporting-task-name').text('');
366         $('#selected-reporting-task-type').text('').removeData('bundle');
367         $('#reporting-task-description-container').hide();
368     };
369
370     /**
371      * Clears the selected reporting task type.
372      */
373     var clearReportingTaskSelection = function () {
374         // clear the selected row
375         clearSelectedReportingTask();
376
377         // clear the active cell the it can be reselected when its included
378         var reportingTaskTypesGrid = $('#reporting-task-types-table').data('gridInstance');
379         reportingTaskTypesGrid.resetActiveCell();
380     };
381
382     /**
383      * Performs the filtering.
384      *
385      * @param {object} item     The item subject to filtering
386      * @param {object} args     Filter arguments
387      * @returns {Boolean}       Whether or not to include the item
388      */
389     var filterReportingTaskTypes = function (item, args) {
390         // determine if the item matches the filter
391         var matchesFilter = matchesRegex(item, args);
392
393         // determine if the row matches the selected tags
394         var matchesTags = true;
395         if (matchesFilter) {
396             var tagFilters = $('#reporting-task-tag-cloud').tagcloud('getSelectedTags');
397             var hasSelectedTags = tagFilters.length > 0;
398             if (hasSelectedTags) {
399                 matchesTags = matchesSelectedTags(tagFilters, item['tags']);
400             }
401         }
402
403         // determine if the row matches the selected source group
404         var matchesGroup = true;
405         if (matchesFilter && matchesTags) {
406             var bundleGroup = $('#reporting-task-bundle-group-combo').combo('getSelectedOption');
407             if (nfCommon.isDefinedAndNotNull(bundleGroup) && bundleGroup.value !== '') {
408                 matchesGroup = (item.bundle.group === bundleGroup.value);
409             }
410         }
411
412         // determine if this row should be visible
413         var matches = matchesFilter && matchesTags && matchesGroup;
414
415         // if this row is currently selected and its being filtered
416         if (matches === false && $('#selected-reporting-task-type').text() === item['type']) {
417             clearReportingTaskSelection();
418         }
419
420         return matches;
421     };
422
423     /**
424      * Adds the currently selected reporting task.
425      */
426     var addSelectedReportingTask = function () {
427         var selectedTaskType = $('#selected-reporting-task-type').text();
428         var selectedTaskBundle = $('#selected-reporting-task-type').data('bundle');
429
430         // ensure something was selected
431         if (selectedTaskType === '') {
432             nfDialog.showOkDialog({
433                 headerText: 'Settings',
434                 dialogContent: 'The type of reporting task to create must be selected.'
435             });
436         } else {
437             addReportingTask(selectedTaskType, selectedTaskBundle);
438         }
439     };
440
441     /**
442      * Adds a new reporting task of the specified type.
443      *
444      * @param {string} reportingTaskType
445      * @param {object} reportingTaskBundle
446      */
447     var addReportingTask = function (reportingTaskType, reportingTaskBundle) {
448         // build the reporting task entity
449         var reportingTaskEntity = {
450             'revision': nfClient.getRevision({
451                 'revision': {
452                     'version': 0
453                 }
454             }),
455             'disconnectedNodeAcknowledged': nfStorage.isDisconnectionAcknowledged(),
456             'component': {
457                 'type': reportingTaskType,
458                 'bundle': reportingTaskBundle
459             }
460         };
461
462         // add the new reporting task
463         var addTask = $.ajax({
464             type: 'POST',
465             url: config.urls.createReportingTask,
466             data: JSON.stringify(reportingTaskEntity),
467             dataType: 'json',
468             contentType: 'application/json'
469         }).done(function (reportingTaskEntity) {
470             // add the item
471             var reportingTaskGrid = $('#reporting-tasks-table').data('gridInstance');
472             var reportingTaskData = reportingTaskGrid.getData();
473             reportingTaskData.addItem($.extend({
474                 type: 'ReportingTask',
475                 bulletins: []
476             }, reportingTaskEntity));
477
478             // resort
479             reportingTaskData.reSort();
480             reportingTaskGrid.invalidate();
481
482             // select the new reporting task
483             var row = reportingTaskData.getRowById(reportingTaskEntity.id);
484             nfFilteredDialogCommon.choseRow(reportingTaskGrid, row);
485             reportingTaskGrid.scrollRowIntoView(row);
486         }).fail(nfErrorHandler.handleAjaxError);
487
488         // hide the dialog
489         $('#new-reporting-task-dialog').modal('hide');
490
491         return addTask;
492     };
493
494     /**
495      * Adds the specified entity.
496      */
497     var addRegistry = function () {
498         var registryEntity = {
499             'revision': nfClient.getRevision({
500                 'revision': {
501                     'version': 0
502                 }
503             }),
504             'disconnectedNodeAcknowledged': nfStorage.isDisconnectionAcknowledged(),
505             'component': {
506                 'name': $('#registry-name').val(),
507                 'uri': $('#registry-location').val(),
508                 'description': $('#registry-description').val()
509             }
510         };
511
512         // add the new registry
513         var addRegistry = $.ajax({
514             type: 'POST',
515             url: config.urls.registries,
516             data: JSON.stringify(registryEntity),
517             dataType: 'json',
518             contentType: 'application/json'
519         }).done(function (registryEntity) {
520             // add the item
521             var registriesGrid = $('#registries-table').data('gridInstance');
522             var registriesData = registriesGrid.getData();
523             registriesData.addItem($.extend({
524                 type: 'Registry'
525             }, registryEntity));
526
527             // resort
528             registriesData.reSort();
529             registriesGrid.invalidate();
530
531             // select the new reporting task
532             var row = registriesData.getRowById(registryEntity.id);
533             nfFilteredDialogCommon.choseRow(registriesGrid, row);
534             registriesGrid.scrollRowIntoView(row);
535         }).fail(nfErrorHandler.handleAjaxError);
536
537         // hide the dialog
538         $('#registry-configuration-dialog').modal('hide');
539
540         return addRegistry;
541     };
542
543
544  /**
545      * Adds the specific environment.
546      */
547     var addDistributionEnvironment= function () {
548         var environmentEntity = {
549                 'name': $('#distribution-environment-name').val(),
550                 'runtimeApiUrl': $('#distribution-environment-location').val(),
551                 'description': $('#distribution-environment-description').val()
552 //                'nextDistributionTargetId': $('#distribution-environment-nextDistributionTargetId').val()
553       };
554
555         console.log("before POST call ");
556         console.log(environmentEntity);
557
558         // add the new distribution environment
559         var addDistributionEnvironment= $.ajax({
560             type: 'POST',
561             url: '/distributor/distribution-targets',
562             data: JSON.stringify(environmentEntity),
563             dataType: 'json',
564             contentType: 'application/json'
565         }).done(function (environmentEntity) {
566             // add the item
567             console.log("after POST call in response ");
568             console.log(environmentEntity);
569             var environmentsGrid = $('#distribution-environments-table').data('gridInstance');
570             console.log(environmentsGrid);
571             var environmentsData = environmentsGrid.getData();
572             environmentsData.addItem($.extend({
573                 type: 'Environment'
574             }, environmentEntity));
575
576
577             // resort
578             environmentsData.reSort();
579             environmentsGrid.invalidate();
580
581             // select the new distribution env.
582             var row = environmentsData.getRowById(environmentEntity.id);
583             nfFilteredDialogCommon.choseRow(environmentsGrid, row);
584             registriesGrid.scrollRowIntoView(row);
585         }).fail(nfErrorHandler.handleAjaxError);
586
587         // hide the dialog
588         $('#distribution-environment-dialog').modal('hide');
589
590         return addDistributionEnvironment;
591     };
592
593
594     /**
595      * Updates the registry with the specified id.
596      *
597      * @param registryId
598      */
599     var updateRegistry = function (registryId) {
600         var registriesGrid = $('#registries-table').data('gridInstance');
601         var registriesData = registriesGrid.getData();
602
603         var registryEntity = registriesData.getItemById(registryId);
604         var requestRegistryEntity = {
605             'revision': nfClient.getRevision(registryEntity),
606             'disconnectedNodeAcknowledged': nfStorage.isDisconnectionAcknowledged(),
607             'component': {
608                 'id': registryId,
609                 'name': $('#registry-name').val(),
610                 'uri': $('#registry-location').val(),
611                 'description': $('#registry-description').val()
612             }
613         };
614
615         // add the new reporting task
616         var updateRegistry = $.ajax({
617             type: 'PUT',
618             url: registryEntity.uri,
619             data: JSON.stringify(requestRegistryEntity),
620             dataType: 'json',
621             contentType: 'application/json'
622         }).done(function (registryEntity) {
623             // add the item
624             registriesData.updateItem(registryId, $.extend({
625                 type: 'Registry'
626             }, registryEntity));
627         }).fail(nfErrorHandler.handleAjaxError);
628
629         // hide the dialog
630         $('#registry-configuration-dialog').modal('hide');
631
632         return updateRegistry;
633     };
634
635
636     /**
637      * Updates the distribution environment with the specified id.
638      *
639      * @param environmentId
640      */
641     var updateDistributionEnvironment   = function (environmentId) {
642         var environmentsGrid = $('#distribution-environments-table').data('gridInstance');
643         var environmentsData = environmentsGrid.getData();
644
645         var environmentEntity = environmentsData.getItemById(environmentId);
646         var requestEnvironmentEntity = {
647                 'id': environmentId,
648                 'name': $('#distribution-environment-name').val(),
649                 'runtimeApiUrl': $('#distribution-environment-location').val(),
650                 'description': $('#distribution-environment-description').val(),
651 //                'nextDistributionTargetId': $('#distribution-environment-nextDistributionTargetId').val()
652         };
653
654         console.log(requestEnvironmentEntity);
655         // updating distribution environment
656         var updateDistributionEnvironment = $.ajax({
657             type: 'PUT',
658             url: '/distributor/distribution-targets/'+environmentEntity.id,
659             data: JSON.stringify(requestEnvironmentEntity),
660             dataType: 'json',
661             contentType: 'application/json'
662         }).done(function (environmentEntity) {
663             // update the item
664             console.log(environmentsGrid);
665             environmentsData.updateItem(environmentId, $.extend({
666                 type: 'Environment'
667             }, environmentEntity));
668         }).fail(nfErrorHandler.handleAjaxError);
669
670         // hide the dialog
671         $('#distribution-environment-dialog').modal('hide');
672
673         return updateDistributionEnvironment;
674     };
675
676
677
678
679
680     /**
681      * Initializes the new reporting task dialog.
682      */
683     var initNewReportingTaskDialog = function () {
684         // initialize the reporting task type table
685         var reportingTaskTypesColumns = [
686             {
687                 id: 'type',
688                 name: 'Type',
689                 field: 'label',
690                 formatter: nfCommon.typeFormatter,
691                 sortable: true,
692                 resizable: true
693             },
694             {
695                 id: 'version',
696                 name: 'Version',
697                 field: 'version',
698                 formatter: nfCommon.typeVersionFormatter,
699                 sortable: true,
700                 resizable: true
701             },
702             {
703                 id: 'tags',
704                 name: 'Tags',
705                 field: 'tags',
706                 sortable: true,
707                 resizable: true,
708                 formatter: nfCommon.genericValueFormatter
709             }
710         ];
711
712         // initialize the dataview
713         var reportingTaskTypesData = new Slick.Data.DataView({
714             inlineFilters: false
715         });
716         reportingTaskTypesData.setItems([]);
717         reportingTaskTypesData.setFilterArgs({
718             searchString: getReportingTaskTypeFilterText()
719         });
720         reportingTaskTypesData.setFilter(filterReportingTaskTypes);
721
722         // initialize the sort
723         nfCommon.sortType({
724             columnId: 'type',
725             sortAsc: true
726         }, reportingTaskTypesData);
727
728         // initialize the grid
729         var reportingTaskTypesGrid = new Slick.Grid('#reporting-task-types-table', reportingTaskTypesData, reportingTaskTypesColumns, gridOptions);
730         reportingTaskTypesGrid.setSelectionModel(new Slick.RowSelectionModel());
731         reportingTaskTypesGrid.registerPlugin(new Slick.AutoTooltips());
732         reportingTaskTypesGrid.setSortColumn('type', true);
733         reportingTaskTypesGrid.onSort.subscribe(function (e, args) {
734             nfCommon.sortType({
735                 columnId: args.sortCol.field,
736                 sortAsc: args.sortAsc
737             }, reportingTaskTypesData);
738         });
739         reportingTaskTypesGrid.onSelectedRowsChanged.subscribe(function (e, args) {
740             if ($.isArray(args.rows) && args.rows.length === 1) {
741                 var reportingTaskTypeIndex = args.rows[0];
742                 var reportingTaskType = reportingTaskTypesGrid.getDataItem(reportingTaskTypeIndex);
743
744                 // set the reporting task type description
745                 if (nfCommon.isDefinedAndNotNull(reportingTaskType)) {
746                     // show the selected reporting task
747                     $('#reporting-task-description-container').show();
748
749                     if (nfCommon.isBlank(reportingTaskType.description)) {
750                         $('#reporting-task-type-description')
751                             .attr('title', '')
752                             .html('<span class="unset">No description specified</span>');
753                     } else {
754                         $('#reporting-task-type-description')
755                             .width($('#reporting-task-description-container').innerWidth() - 1)
756                             .html(reportingTaskType.description)
757                             .ellipsis();
758                     }
759
760                     var bundle = nfCommon.formatBundle(reportingTaskType.bundle);
761                     var type = nfCommon.formatType(reportingTaskType);
762
763                     // populate the dom
764                     $('#reporting-task-type-name').text(type).attr('title', type);
765                     $('#reporting-task-type-bundle').text(bundle).attr('title', bundle);
766                     $('#selected-reporting-task-name').text(reportingTaskType.label);
767                     $('#selected-reporting-task-type').text(reportingTaskType.type).data('bundle', reportingTaskType.bundle);
768
769                     // refresh the buttons based on the current selection
770                     $('#new-reporting-task-dialog').modal('refreshButtons');
771                 }
772             }
773         });
774         reportingTaskTypesGrid.onDblClick.subscribe(function (e, args) {
775             var reportingTaskType = reportingTaskTypesGrid.getDataItem(args.row);
776
777             if (isSelectable(reportingTaskType)) {
778                 addReportingTask(reportingTaskType.type, reportingTaskType.bundle);
779             }
780         });
781         reportingTaskTypesGrid.onViewportChanged.subscribe(function (e, args) {
782             nfCommon.cleanUpTooltips($('#reporting-task-types-table'), 'div.view-usage-restriction');
783         });
784
785         // wire up the dataview to the grid
786         reportingTaskTypesData.onRowCountChanged.subscribe(function (e, args) {
787             reportingTaskTypesGrid.updateRowCount();
788             reportingTaskTypesGrid.render();
789
790             // update the total number of displayed processors
791             $('#displayed-reporting-task-types').text(args.current);
792         });
793         reportingTaskTypesData.onRowsChanged.subscribe(function (e, args) {
794             reportingTaskTypesGrid.invalidateRows(args.rows);
795             reportingTaskTypesGrid.render();
796         });
797         reportingTaskTypesData.syncGridSelection(reportingTaskTypesGrid, true);
798
799         // hold onto an instance of the grid
800         $('#reporting-task-types-table').data('gridInstance', reportingTaskTypesGrid).on('mouseenter', 'div.slick-cell', function (e) {
801             var usageRestriction = $(this).find('div.view-usage-restriction');
802             if (usageRestriction.length && !usageRestriction.data('qtip')) {
803                 var rowId = $(this).find('span.row-id').text();
804
805                 // get the status item
806                 var item = reportingTaskTypesData.getItemById(rowId);
807
808                 // show the tooltip
809                 if (item.restricted === true) {
810                     var restrictionTip = $('<div></div>');
811
812                     if (nfCommon.isBlank(item.usageRestriction)) {
813                         restrictionTip.append($('<p style="margin-bottom: 3px;"></p>').text('Requires the following permissions:'));
814                     } else {
815                         restrictionTip.append($('<p style="margin-bottom: 3px;"></p>').text(item.usageRestriction + ' Requires the following permissions:'));
816                     }
817
818                     var restrictions = [];
819                     if (nfCommon.isDefinedAndNotNull(item.explicitRestrictions)) {
820                         $.each(item.explicitRestrictions, function (_, explicitRestriction) {
821                             var requiredPermission = explicitRestriction.requiredPermission;
822                             restrictions.push("'" + requiredPermission.label + "' - " + nfCommon.escapeHtml(explicitRestriction.explanation));
823                         });
824                     } else {
825                         restrictions.push('Access to restricted components regardless of restrictions.');
826                     }
827                     restrictionTip.append(nfCommon.formatUnorderedList(restrictions));
828
829                     usageRestriction.qtip($.extend({}, nfCommon.config.tooltipConfig, {
830                         content: restrictionTip,
831                         position: {
832                             container: $('#summary'),
833                             at: 'bottom right',
834                             my: 'top left',
835                             adjust: {
836                                 x: 4,
837                                 y: 4
838                             }
839                         }
840                     }));
841                 }
842             }
843         });
844
845         var generalRestriction = nfCommon.getPolicyTypeListing('restricted-components');
846
847         // load the available reporting tasks
848         $.ajax({
849             type: 'GET',
850             url: config.urls.reportingTaskTypes,
851             dataType: 'json'
852         }).done(function (response) {
853             var id = 0;
854             var tags = [];
855             var groups = d3.set();
856             var restrictedUsage = d3.map();
857             var requiredPermissions = d3.map();
858
859             // begin the update
860             reportingTaskTypesData.beginUpdate();
861
862             // go through each reporting task type
863             $.each(response.reportingTaskTypes, function (i, documentedType) {
864                 if (documentedType.restricted === true) {
865                     if (nfCommon.isDefinedAndNotNull(documentedType.explicitRestrictions)) {
866                         $.each(documentedType.explicitRestrictions, function (_, explicitRestriction) {
867                             var requiredPermission = explicitRestriction.requiredPermission;
868
869                             // update required permissions
870                             if (!requiredPermissions.has(requiredPermission.id)) {
871                                 requiredPermissions.set(requiredPermission.id, requiredPermission.label);
872                             }
873
874                             // update component restrictions
875                             if (!restrictedUsage.has(requiredPermission.id)) {
876                                 restrictedUsage.set(requiredPermission.id, []);
877                             }
878
879                             restrictedUsage.get(requiredPermission.id).push({
880                                 type: nfCommon.formatType(documentedType),
881                                 bundle: nfCommon.formatBundle(documentedType.bundle),
882                                 explanation: nfCommon.escapeHtml(explicitRestriction.explanation)
883                             })
884                         });
885                     } else {
886                         // update required permissions
887                         if (!requiredPermissions.has(generalRestriction.value)) {
888                             requiredPermissions.set(generalRestriction.value, generalRestriction.text);
889                         }
890
891                         // update component restrictions
892                         if (!restrictedUsage.has(generalRestriction.value)) {
893                             restrictedUsage.set(generalRestriction.value, []);
894                         }
895
896                         restrictedUsage.get(generalRestriction.value).push({
897                             type: nfCommon.formatType(documentedType),
898                             bundle: nfCommon.formatBundle(documentedType.bundle),
899                             explanation: nfCommon.escapeHtml(documentedType.usageRestriction)
900                         });
901                     }
902                 }
903
904                 // record the group
905                 groups.add(documentedType.bundle.group);
906
907                 // add the documented type
908                 reportingTaskTypesData.addItem({
909                     id: id++,
910                     label: nfCommon.substringAfterLast(documentedType.type, '.'),
911                     type: documentedType.type,
912                     bundle: documentedType.bundle,
913                     description: nfCommon.escapeHtml(documentedType.description),
914                     restricted:  documentedType.restricted,
915                     usageRestriction: nfCommon.escapeHtml(documentedType.usageRestriction),
916                     explicitRestrictions: documentedType.explicitRestrictions,
917                     tags: documentedType.tags.join(', ')
918                 });
919
920                 // count the frequency of each tag for this type
921                 $.each(documentedType.tags, function (i, tag) {
922                     tags.push(tag.toLowerCase());
923                 });
924             });
925
926             // end the update
927             reportingTaskTypesData.endUpdate();
928
929             // resort
930             reportingTaskTypesData.reSort();
931             reportingTaskTypesGrid.invalidate();
932
933             // set the component restrictions and the corresponding required permissions
934             nfCanvasUtils.addComponentRestrictions(restrictedUsage, requiredPermissions);
935
936             // set the total number of processors
937             $('#total-reporting-task-types, #displayed-reporting-task-types').text(response.reportingTaskTypes.length);
938
939             // create the tag cloud
940             $('#reporting-task-tag-cloud').tagcloud({
941                 tags: tags,
942                 select: applyReportingTaskTypeFilter,
943                 remove: applyReportingTaskTypeFilter
944             });
945
946             // build the combo options
947             var options = [{
948                 text: 'all groups',
949                 value: ''
950             }];
951             groups.each(function (group) {
952                 options.push({
953                     text: group,
954                     value: group
955                 });
956             });
957
958             // initialize the bundle group combo
959             $('#reporting-task-bundle-group-combo').combo({
960                 options: options,
961                 select: applyReportingTaskTypeFilter
962             });
963         }).fail(nfErrorHandler.handleAjaxError);
964
965         var navigationKeys = [$.ui.keyCode.UP, $.ui.keyCode.PAGE_UP, $.ui.keyCode.DOWN, $.ui.keyCode.PAGE_DOWN];
966
967         // define the function for filtering the list
968         $('#reporting-task-type-filter').off('keyup').on('keyup', function (e) {
969             var code = e.keyCode ? e.keyCode : e.which;
970
971             // ignore navigation keys
972             if ($.inArray(code, navigationKeys) !== -1) {
973                 return;
974             }
975
976             if (code === $.ui.keyCode.ENTER) {
977                 var selected = reportingTaskTypesGrid.getSelectedRows();
978
979                 if (selected.length > 0) {
980                     // grid configured with multi-select = false
981                     var item = reportingTaskTypesGrid.getDataItem(selected[0]);
982                     if (isSelectable(item)) {
983                         addSelectedReportingTask();
984                     }
985                 }
986             } else {
987                 applyReportingTaskTypeFilter();
988             }
989         });
990
991         // setup row navigation
992         nfFilteredDialogCommon.addKeydownListener('#reporting-task-type-filter', reportingTaskTypesGrid, reportingTaskTypesGrid.getData());
993
994         // initialize the reporting task dialog
995         $('#new-reporting-task-dialog').modal({
996             scrollableContentStyle: 'scrollable',
997             headerText: 'Add Reporting Task',
998             buttons: [{
999                 buttonText: 'Add',
1000                 color: {
1001                     base: '#728E9B',
1002                     hover: '#004849',
1003                     text: '#ffffff'
1004                 },
1005                 disabled: function () {
1006                     var selected = reportingTaskTypesGrid.getSelectedRows();
1007
1008                     if (selected.length > 0) {
1009                         // grid configured with multi-select = false
1010                         var item = reportingTaskTypesGrid.getDataItem(selected[0]);
1011                         return isSelectable(item) === false;
1012                     } else {
1013                         return reportingTaskTypesGrid.getData().getLength() === 0;
1014                     }
1015                 },
1016                 handler: {
1017                     click: function () {
1018                         addSelectedReportingTask();
1019                     }
1020                 }
1021             },
1022                 {
1023                     buttonText: 'Cancel',
1024                     color: {
1025                         base: '#E3E8EB',
1026                         hover: '#C7D2D7',
1027                         text: '#004849'
1028                     },
1029                     handler: {
1030                         click: function () {
1031                             $(this).modal('hide');
1032                         }
1033                     }
1034                 }],
1035             handler: {
1036                 close: function () {
1037                     // clear the selected row
1038                     clearSelectedReportingTask();
1039
1040                     // clear any filter strings
1041                     $('#reporting-task-type-filter').val('');
1042
1043                     // clear the tagcloud
1044                     $('#reporting-task-tag-cloud').tagcloud('clearSelectedTags');
1045
1046                     // reset the group combo
1047                     $('#reporting-task-bundle-group-combo').combo('setSelectedOption', {
1048                         value: ''
1049                     });
1050
1051                     // reset the filter
1052                     applyReportingTaskTypeFilter();
1053
1054                     // unselect any current selection
1055                     var reportingTaskTypesGrid = $('#reporting-task-types-table').data('gridInstance');
1056                     reportingTaskTypesGrid.setSelectedRows([]);
1057                     reportingTaskTypesGrid.resetActiveCell();
1058                 },
1059                 resize: function () {
1060                     $('#reporting-task-type-description')
1061                         .width($('#reporting-task-description-container').innerWidth() - 1)
1062                         .text($('#reporting-task-type-description').attr('title'))
1063                         .ellipsis();
1064                 }
1065             }
1066         });
1067
1068         // initialize the registry configuration dialog
1069                    $('#registry-configuration-dialog').modal({
1070                        scrollableContentStyle: 'scrollable',
1071                        handler: {
1072                            close: function () {
1073                                $('#registry-id').text('');
1074                                $('#registry-name').val('');
1075                                $('#registry-location').val('');
1076                                $('#registry-description').val('');
1077                            }
1078                        }
1079                    });
1080
1081
1082               // initialize the distribution environment  dialog
1083                  $('#distribution-environment-dialog').modal({
1084                      scrollableContentStyle: 'scrollable',
1085                      handler: {
1086                          close: function () {
1087                              $('#distribution-environment-id').text('');
1088                              $('#distribution-environment-name').val('');
1089                              $('#distribution-environment-location').val('');
1090                              $('#distribution-environment-description').val('');
1091 //                             $('#distribution-environment-nextDistributionTargetId').val('');
1092                          }
1093                      }
1094                  });
1095     };
1096
1097     /**
1098      * Initializes the reporting tasks tab.
1099      */
1100     var initReportingTasks = function () {
1101         // initialize the new reporting task dialog
1102         initNewReportingTaskDialog();
1103
1104         var moreReportingTaskDetails = function (row, cell, value, columnDef, dataContext) {
1105             if (!dataContext.permissions.canRead) {
1106                 return '';
1107             }
1108
1109             var markup = '<div title="View Details" class="pointer view-reporting-task fa fa-info-circle"></div>';
1110
1111             // always include a button to view the usage
1112             markup += '<div title="Usage" class="pointer reporting-task-usage fa fa-book"></div>';
1113
1114             var hasErrors = !nfCommon.isEmpty(dataContext.component.validationErrors);
1115             var hasBulletins = !nfCommon.isEmpty(dataContext.bulletins);
1116
1117             if (hasErrors) {
1118                 markup += '<div class="pointer has-errors fa fa-warning" ></div>';
1119             }
1120
1121             if (hasBulletins) {
1122                 markup += '<div class="has-bulletins fa fa-sticky-note-o"></div>';
1123             }
1124
1125             if (hasErrors || hasBulletins) {
1126                 markup += '<span class="hidden row-id">' + nfCommon.escapeHtml(dataContext.component.id) + '</span>';
1127             }
1128
1129             return markup;
1130         };
1131
1132         var reportingTaskRunStatusFormatter = function (row, cell, value, columnDef, dataContext) {
1133             // determine the appropriate label
1134             var icon = '', label = '';
1135             if (dataContext.status.validationStatus === 'VALIDATING') {
1136                 icon = 'validating fa fa-spin fa-circle-notch';
1137                 label = 'Validating';
1138             } else if (dataContext.status.validationStatus === 'INVALID') {
1139                 icon = 'invalid fa fa-warning';
1140                 label = 'Invalid';
1141             } else {
1142                 if (dataContext.status.runStatus === 'STOPPED') {
1143                     label = 'Stopped';
1144                     icon = 'fa fa-stop stopped';
1145                 } else if (dataContext.status.runStatus === 'RUNNING') {
1146                     label = 'Running';
1147                     icon = 'fa fa-play running';
1148                 } else {
1149                     label = 'Disabled';
1150                     icon = 'icon icon-enable-false disabled';
1151                 }
1152             }
1153
1154             // include the active thread count if appropriate
1155             var activeThreadCount = '';
1156             if (nfCommon.isDefinedAndNotNull(dataContext.status.activeThreadCount) && dataContext.status.activeThreadCount > 0) {
1157                 activeThreadCount = '(' + dataContext.status.activeThreadCount + ')';
1158             }
1159
1160             // format the markup
1161             var formattedValue = '<div layout="row"><div class="' + icon + '"></div>';
1162             return formattedValue + '<div class="status-text">' + nfCommon.escapeHtml(label) + '</div><div style="float: left; margin-left: 4px;">' + nfCommon.escapeHtml(activeThreadCount) + '</div></div>';
1163         };
1164
1165         var reportingTaskActionFormatter = function (row, cell, value, columnDef, dataContext) {
1166             var markup = '';
1167
1168             var canWrite = dataContext.permissions.canWrite;
1169             var canRead = dataContext.permissions.canRead;
1170             var canOperate = dataContext.operatePermissions.canWrite || canWrite;
1171             var isStopped = dataContext.status.runStatus === 'STOPPED';
1172
1173             if (dataContext.status.runStatus === 'RUNNING') {
1174                 if (canOperate) {
1175                     markup += '<div title="Stop" class="pointer stop-reporting-task fa fa-stop"></div>';
1176                 }
1177
1178             } else if (isStopped || dataContext.status.runStatus === 'DISABLED') {
1179
1180                 if (canRead && canWrite) {
1181                     markup += '<div title="Edit" class="pointer edit-reporting-task fa fa-pencil"></div>';
1182                 }
1183
1184                 // support starting when stopped and no validation errors
1185                 if (canOperate && dataContext.status.runStatus === 'STOPPED' && dataContext.status.validationStatus === 'VALID') {
1186                     markup += '<div title="Start" class="pointer start-reporting-task fa fa-play"></div>';
1187                 }
1188
1189                 if (canRead && canWrite && dataContext.component.multipleVersionsAvailable === true) {
1190                     markup += '<div title="Change Version" class="pointer change-version-reporting-task fa fa-exchange"></div>';
1191                 }
1192
1193                 if (canRead && canWrite && nfCommon.canModifyController()) {
1194                     markup += '<div title="Remove" class="pointer delete-reporting-task fa fa-trash"></div>';
1195                 }
1196             }
1197
1198             if (canRead && canWrite && dataContext.component.persistsState === true) {
1199                 markup += '<div title="View State" class="pointer view-state-reporting-task fa fa-tasks"></div>';
1200             }
1201
1202             // allow policy configuration conditionally
1203             if (nfCanvasUtils.isManagedAuthorizer() && nfCommon.canAccessTenants()) {
1204                 markup += '<div title="Access Policies" class="pointer edit-access-policies fa fa-key"></div>';
1205             }
1206
1207             return markup;
1208         };
1209
1210         // define the column model for the reporting tasks table
1211         var reportingTasksColumnModel = [
1212             {
1213                 id: 'moreDetails',
1214                 name: '&nbsp;',
1215                 resizable: false,
1216                 formatter: moreReportingTaskDetails,
1217                 sortable: true,
1218                 width: 90,
1219                 maxWidth: 90,
1220                 toolTip: 'Sorts based on presence of bulletins'
1221             },
1222             {
1223                 id: 'name',
1224                 name: 'Name',
1225                 sortable: true,
1226                 resizable: true,
1227                 formatter: nameFormatter
1228             },
1229             {
1230                 id: 'type',
1231                 name: 'Type',
1232                 formatter: nfCommon.instanceTypeFormatter,
1233                 sortable: true,
1234                 resizable: true
1235             },
1236             {
1237                 id: 'bundle',
1238                 name: 'Bundle',
1239                 formatter: nfCommon.instanceBundleFormatter,
1240                 sortable: true,
1241                 resizable: true
1242             },
1243             {
1244                 id: 'state',
1245                 name: 'Run Status',
1246                 sortable: true,
1247                 resizeable: true,
1248                 formatter: reportingTaskRunStatusFormatter
1249             }
1250         ];
1251
1252         // action column should always be last
1253         reportingTasksColumnModel.push({
1254             id: 'actions',
1255             name: '&nbsp;',
1256             resizable: false,
1257             formatter: reportingTaskActionFormatter,
1258             sortable: false,
1259             width: 90,
1260             maxWidth: 90
1261         });
1262
1263         // initialize the dataview
1264         var reportingTasksData = new Slick.Data.DataView({
1265             inlineFilters: false
1266         });
1267         reportingTasksData.setItems([]);
1268
1269         // initialize the sort
1270         sort({
1271             columnId: 'name',
1272             sortAsc: true
1273         }, reportingTasksData);
1274
1275         // initialize the grid
1276         var reportingTasksGrid = new Slick.Grid('#reporting-tasks-table', reportingTasksData, reportingTasksColumnModel, gridOptions);
1277         reportingTasksGrid.setSelectionModel(new Slick.RowSelectionModel());
1278         reportingTasksGrid.registerPlugin(new Slick.AutoTooltips());
1279         reportingTasksGrid.setSortColumn('name', true);
1280         reportingTasksGrid.onSort.subscribe(function (e, args) {
1281             sort({
1282                 columnId: args.sortCol.id,
1283                 sortAsc: args.sortAsc
1284             }, reportingTasksData);
1285         });
1286
1287         // configure a click listener
1288         reportingTasksGrid.onClick.subscribe(function (e, args) {
1289             var target = $(e.target);
1290
1291             // get the service at this row
1292             var reportingTaskEntity = reportingTasksData.getItem(args.row);
1293
1294             // determine the desired action
1295             if (reportingTasksGrid.getColumns()[args.cell].id === 'actions') {
1296                 if (target.hasClass('edit-reporting-task')) {
1297                     nfReportingTask.showConfiguration(reportingTaskEntity);
1298                 } else if (target.hasClass('start-reporting-task')) {
1299                     nfReportingTask.start(reportingTaskEntity);
1300                 } else if (target.hasClass('stop-reporting-task')) {
1301                     nfReportingTask.stop(reportingTaskEntity);
1302                 } else if (target.hasClass('delete-reporting-task')) {
1303                     nfReportingTask.promptToDeleteReportingTask(reportingTaskEntity);
1304                 } else if (target.hasClass('view-state-reporting-task')) {
1305                     var canClear = reportingTaskEntity.status.runStatus === 'STOPPED' && reportingTaskEntity.status.activeThreadCount === 0;
1306                     nfComponentState.showState(reportingTaskEntity, canClear);
1307                 } else if (target.hasClass('change-version-reporting-task')) {
1308                     nfComponentVersion.promptForVersionChange(reportingTaskEntity);
1309                 } else if (target.hasClass('edit-access-policies')) {
1310                     // show the policies for this service
1311                     nfPolicyManagement.showReportingTaskPolicy(reportingTaskEntity);
1312
1313                     // close the settings dialog
1314                     $('#shell-close-button').click();
1315                 }
1316             } else if (reportingTasksGrid.getColumns()[args.cell].id === 'moreDetails') {
1317                 if (target.hasClass('view-reporting-task')) {
1318                     nfReportingTask.showDetails(reportingTaskEntity);
1319                 } else if (target.hasClass('reporting-task-usage')) {
1320                     // close the settings dialog
1321                     $('#shell-close-button').click();
1322
1323                     // open the documentation for this reporting task
1324                     nfShell.showPage('../nifi-docs/documentation?' + $.param({
1325                             select: reportingTaskEntity.component.type,
1326                             group: reportingTaskEntity.component.bundle.group,
1327                             artifact: reportingTaskEntity.component.bundle.artifact,
1328                             version: reportingTaskEntity.component.bundle.version
1329                         })).done(function () {
1330                         nfSettings.showSettings();
1331                     });
1332                 }
1333             }
1334         });
1335
1336         // wire up the dataview to the grid
1337         reportingTasksData.onRowCountChanged.subscribe(function (e, args) {
1338             reportingTasksGrid.updateRowCount();
1339             reportingTasksGrid.render();
1340         });
1341         reportingTasksData.onRowsChanged.subscribe(function (e, args) {
1342             reportingTasksGrid.invalidateRows(args.rows);
1343             reportingTasksGrid.render();
1344         });
1345         reportingTasksData.syncGridSelection(reportingTasksGrid, true);
1346
1347         // hold onto an instance of the grid
1348         $('#reporting-tasks-table').data('gridInstance', reportingTasksGrid).on('mouseenter', 'div.slick-cell', function (e) {
1349             var errorIcon = $(this).find('div.has-errors');
1350             if (errorIcon.length && !errorIcon.data('qtip')) {
1351                 var taskId = $(this).find('span.row-id').text();
1352
1353                 // get the task item
1354                 var reportingTaskEntity = reportingTasksData.getItemById(taskId);
1355
1356                 // format the errors
1357                 var tooltip = nfCommon.formatUnorderedList(reportingTaskEntity.component.validationErrors);
1358
1359                 // show the tooltip
1360                 if (nfCommon.isDefinedAndNotNull(tooltip)) {
1361                     errorIcon.qtip($.extend({},
1362                         nfCommon.config.tooltipConfig,
1363                         {
1364                             content: tooltip,
1365                             position: {
1366                                 target: 'mouse',
1367                                 viewport: $('#shell-container'),
1368                                 adjust: {
1369                                     x: 8,
1370                                     y: 8,
1371                                     method: 'flipinvert flipinvert'
1372                                 }
1373                             }
1374                         }));
1375                 }
1376             }
1377
1378             var bulletinIcon = $(this).find('div.has-bulletins');
1379             if (bulletinIcon.length && !bulletinIcon.data('qtip')) {
1380                 var taskId = $(this).find('span.row-id').text();
1381
1382                 // get the task item
1383                 var reportingTaskEntity = reportingTasksData.getItemById(taskId);
1384
1385                 // format the tooltip
1386                 var bulletins = nfCommon.getFormattedBulletins(reportingTaskEntity.bulletins);
1387                 var tooltip = nfCommon.formatUnorderedList(bulletins);
1388
1389                 // show the tooltip
1390                 if (nfCommon.isDefinedAndNotNull(tooltip)) {
1391                     bulletinIcon.qtip($.extend({},
1392                         nfCommon.config.tooltipConfig,
1393                         {
1394                             content: tooltip,
1395                             position: {
1396                                 target: 'mouse',
1397                                 viewport: $('#shell-container'),
1398                                 adjust: {
1399                                     x: 8,
1400                                     y: 8,
1401                                     method: 'flipinvert flipinvert'
1402                                 }
1403                             }
1404                         }));
1405                 }
1406             }
1407         });
1408     };
1409
1410
1411
1412    /**
1413     * Initializing Registry table
1414     */
1415     var initRegistriesTable = function () {
1416
1417         var locationFormatter = function (row, cell, value, columnDef, dataContext) {
1418             if (!dataContext.permissions.canRead) {
1419                 return '<span class="blank">' + nfCommon.escapeHtml(dataContext.id) + '</span>';
1420             }
1421
1422             return nfCommon.escapeHtml(dataContext.component.uri);
1423         };
1424
1425         var descriptionFormatter = function (row, cell, value, columnDef, dataContext) {
1426             if (!dataContext.permissions.canRead) {
1427                 return '<span class="blank">' + nfCommon.escapeHtml(dataContext.id) + '</span>';
1428             }
1429
1430             return nfCommon.escapeHtml(dataContext.component.description);
1431         };
1432
1433         var registriesActionFormatter = function (row, cell, value, columnDef, dataContext) {
1434             var markup = '';
1435
1436             if (nfCommon.canModifyController()) {
1437                 // edit registry
1438                 markup += '<div title="Edit" class="pointer edit-registry fa fa-pencil"></div>';
1439
1440                 // remove registry
1441                 markup += '<div title="Remove" class="pointer remove-registry fa fa-trash"></div>';
1442             }
1443
1444             return markup;
1445         };
1446
1447         // define the column model for the reporting tasks table
1448         var registriesColumnModel = [
1449             {
1450                 id: 'name',
1451                 name: 'Name',
1452                 field: 'name',
1453                 formatter: nameFormatter,
1454                 sortable: true,
1455                 resizable: true
1456             },
1457             {
1458                 id: 'uri',
1459                 name: 'Location',
1460                 field: 'uri',
1461                 formatter: locationFormatter,
1462                 sortable: true,
1463                 resizable: true
1464             },
1465             {
1466                 id: 'description',
1467                 name: 'Description',
1468                 field: 'description',
1469                 formatter: descriptionFormatter,
1470                 sortable: true,
1471                 resizable: true
1472             }
1473         ];
1474
1475         // action column should always be last
1476         registriesColumnModel.push({
1477             id: 'actions',
1478             name: '&nbsp;',
1479             resizable: false,
1480             formatter: registriesActionFormatter,
1481             sortable: false,
1482             width: 90,
1483             maxWidth: 90
1484         });
1485
1486         // initialize the dataview
1487         var registriesData = new Slick.Data.DataView({
1488             inlineFilters: false
1489         });
1490         registriesData.setItems([]);
1491
1492         // initialize the sort
1493         sort({
1494             columnId: 'name',
1495             sortAsc: true
1496         }, registriesData);
1497
1498         // initialize the grid
1499         var registriesGrid = new Slick.Grid('#registries-table', registriesData, registriesColumnModel, gridOptions);
1500         registriesGrid.setSelectionModel(new Slick.RowSelectionModel());
1501         registriesGrid.registerPlugin(new Slick.AutoTooltips());
1502         registriesGrid.setSortColumn('name', true);
1503         registriesGrid.onSort.subscribe(function (e, args) {
1504             sort({
1505                 columnId: args.sortCol.id,
1506                 sortAsc: args.sortAsc
1507             }, registriesData);
1508         });
1509
1510         // configure a click listener
1511         registriesGrid.onClick.subscribe(function (e, args) {
1512             var target = $(e.target);
1513
1514             // get the service at this row
1515             var registryEntity = registriesData.getItem(args.row);
1516
1517             // determine the desired action
1518             if (registriesGrid.getColumns()[args.cell].id === 'actions') {
1519                 if (target.hasClass('edit-registry')) {
1520                     editRegistry(registryEntity);
1521                 } else if (target.hasClass('remove-registry')) {
1522                     promptToRemoveRegistry(registryEntity);
1523                 }
1524             } else if (registriesGrid.getColumns()[args.cell].id === 'moreDetails') {
1525                 // if (target.hasClass('view-reporting-task')) {
1526                 //     nfReportingTask.showDetails(reportingTaskEntity);
1527                 // } else if (target.hasClass('reporting-task-usage')) {
1528                 //     // close the settings dialog
1529                 //     $('#shell-close-button').click();
1530                 //
1531                 //     // open the documentation for this reporting task
1532                 //     nfShell.showPage('../nifi-docs/documentation?' + $.param({
1533                 //         select: reportingTaskEntity.component.type,
1534                 //         group: reportingTaskEntity.component.bundle.group,
1535                 //         artifact: reportingTaskEntity.component.bundle.artifact,
1536                 //         version: reportingTaskEntity.component.bundle.version
1537                 //     })).done(function () {
1538                 //         nfSettings.showSettings();
1539                 //     });
1540                 // }
1541             }
1542         });
1543
1544         // wire up the dataview to the grid
1545         registriesData.onRowCountChanged.subscribe(function (e, args) {
1546             registriesGrid.updateRowCount();
1547             registriesGrid.render();
1548         });
1549         registriesData.onRowsChanged.subscribe(function (e, args) {
1550             registriesGrid.invalidateRows(args.rows);
1551             registriesGrid.render();
1552         });
1553         registriesData.syncGridSelection(registriesGrid, true);
1554
1555         // hold onto an instance of the grid
1556         $('#registries-table').data('gridInstance', registriesGrid);
1557     };
1558
1559
1560
1561
1562     /**
1563      * Initializing Distribution Environments table
1564      */
1565     var initDistributionEnvironmentsTable = function () {
1566
1567         var locationFormatter = function (row, cell, value, columnDef, dataContext) {
1568 //            if (!dataContext.permissions.canRead) {
1569                 return '<span class="blank">' + nfCommon.escapeHtml(dataContext.id) + '</span>';
1570 //            }
1571
1572             return nfCommon.escapeHtml(dataContext.component.uri);
1573         };
1574
1575         var descriptionFormatter = function (row, cell, value, columnDef, dataContext) {
1576 //            if (!dataContext.permissions.canRead) {
1577                 return '<span class="blank">' + nfCommon.escapeHtml(dataContext.id) + '</span>';
1578 //            }
1579
1580             return nfCommon.escapeHtml(dataContext.component.description);
1581         };
1582
1583         var envActionFormatter = function (row, cell, value, columnDef, dataContext) {
1584             var markup = '';
1585
1586             if (nfCommon.canModifyController()) {
1587                 // edit environment
1588                 markup += '<div title="Edit" class="pointer edit-registry fa fa-pencil"></div>';
1589
1590                 // remove environment
1591                 markup += '<div title="Remove" class="pointer remove-registry fa fa-trash"></div>';
1592             }
1593
1594             return markup;
1595         };
1596
1597           // define the column model for the Distribution environments table
1598                 var environmentsColumnModel = [
1599                     {
1600                         id: 'name',
1601                         name: 'Name',
1602                         field: 'name',
1603 //                        formatter: nameFormatter,
1604                         sortable: true,
1605                         resizable: true
1606                     },
1607                     {
1608                         id: 'runtimeApiUrl',
1609                         name: 'Location',
1610                         field: 'runtimeApiUrl',
1611 //                        formatter: locationFormatter,
1612                         sortable: true,
1613                         resizable: true
1614                     },
1615                     {
1616                         id: 'description',
1617                         name: 'Description',
1618                         field: 'description',
1619 //                        formatter: descriptionFormatter,
1620                         sortable: true,
1621                         resizable: true
1622                     }
1623 //                    ,
1624 //                    {
1625 //                        id: 'nextDistributionTargetId',
1626 //                        name: 'Next Distribution TargetId',
1627 //                        field: 'nextDistributionTargetId',
1628 //                        formatter: descriptionFormatter,
1629 //                        sortable: true,
1630 //                        resizable: true
1631 //                    }
1632                 ];
1633
1634               // action column should always be last
1635                     environmentsColumnModel.push({
1636                         id: 'actions',
1637                         name: '&nbsp;',
1638                         resizable: false,
1639                         formatter: envActionFormatter,
1640                         sortable: false,
1641                         width: 90,
1642                         maxWidth: 90
1643                     });
1644
1645                // initialize the dataview
1646                     var environmentsData = new Slick.Data.DataView({
1647                         inlineFilters: false
1648                     });
1649                     environmentsData.setItems([]);
1650
1651               // initialize the sort
1652                  sort({
1653                      columnId: 'name',
1654                      sortAsc: true
1655                  }, environmentsData);
1656
1657              // initialize the grid
1658                  var environmentsGrid = new Slick.Grid('#distribution-environments-table', environmentsData, environmentsColumnModel, gridOptions);
1659                  environmentsGrid.setSelectionModel(new Slick.RowSelectionModel());
1660                  environmentsGrid.registerPlugin(new Slick.AutoTooltips());
1661                  environmentsGrid.setSortColumn('name', true);
1662                  environmentsGrid.onSort.subscribe(function (e, args) {
1663                      sort({
1664                          columnId: args.sortCol.id,
1665                          sortAsc: args.sortAsc
1666                      }, environmentsData);
1667                  });
1668
1669              // configure a click listener
1670                 environmentsGrid.onClick.subscribe(function (e, args) {
1671                     var target = $(e.target);
1672
1673              // get the service at this row
1674                var environmentEntity = environmentsData.getItem(args.row);
1675
1676              // determine the desired action
1677               if (environmentsGrid.getColumns()[args.cell].id === 'actions') {
1678                   if (target.hasClass('edit-registry')) {                      //left it as edit-registry intentionally to inherit styles
1679                       editDistributionEnvironment(environmentEntity);
1680                   } else if (target.hasClass('remove-registry')) {             //left it as remove-registry intentionally to inherit styles
1681                       promptToRemoveDistributionEnvironment(environmentEntity);
1682                   }
1683               } else if (environmentsGrid.getColumns()[args.cell].id === 'moreDetails') { }
1684           });
1685
1686           // wire up the dataview to the grid
1687             environmentsData.onRowCountChanged.subscribe(function (e, args) {
1688                 environmentsGrid.updateRowCount();
1689                 environmentsGrid.render();
1690             });
1691             environmentsData.onRowsChanged.subscribe(function (e, args) {
1692                 environmentsGrid.invalidateRows(args.rows);
1693                 environmentsGrid.render();
1694             });
1695             environmentsData.syncGridSelection(environmentsGrid, true);
1696
1697             // hold onto an instance of the grid
1698             $('#distribution-environments-table').data('gridInstance', environmentsGrid);
1699         };
1700
1701
1702
1703     /**
1704      * Edits the specified registry entity.
1705      *
1706      * @param registryEntity
1707      */
1708     var editRegistry = function (registryEntity) {
1709         // populate the dialog
1710         $('#registry-id').text(registryEntity.id);
1711         $('#registry-name').val(registryEntity.component.name);
1712         $('#registry-location').val(registryEntity.component.uri);
1713         $('#registry-description').val(registryEntity.component.description);
1714
1715         // show the dialog
1716         $('#registry-configuration-dialog').modal('setHeaderText', 'Edit Registry Client').modal('setButtonModel', [{
1717             buttonText: 'Update',
1718             color: {
1719                 base: '#728E9B',
1720                 hover: '#004849',
1721                 text: '#ffffff'
1722             },
1723             handler: {
1724                 click: function () {
1725                     updateRegistry(registryEntity.id);
1726                 }
1727             }
1728         }, {
1729             buttonText: 'Cancel',
1730             color: {
1731                 base: '#E3E8EB',
1732                 hover: '#C7D2D7',
1733                 text: '#004849'
1734             },
1735             handler: {
1736                 click: function () {
1737                     $(this).modal('hide');
1738                 }
1739             }
1740         }]).modal('show');
1741     };
1742
1743
1744         /**
1745          * Edits the specified distribution environment entity.
1746          *@author Renu
1747          * @param distributionEnvironmentEntity
1748          */
1749         var editDistributionEnvironment = function (distributionEnvironmentEntity) {
1750             // populate the dialog
1751             $('#distribution-environment-id').text(distributionEnvironmentEntity.id);
1752             $('#distribution-environment-name').val(distributionEnvironmentEntity.name);
1753             $('#distribution-environment-location').val(distributionEnvironmentEntity.runtimeApiUrl);
1754             $('#distribution-environment-description').val(distributionEnvironmentEntity.description);
1755 //            $('#distribution-environment-nextDistributionTargetId ').val(distributionEnvironmentEntity.component.description);
1756
1757             // show the dialog
1758             $('#distribution-environment-dialog').modal('setHeaderText', 'Edit Environment').modal('setButtonModel', [{
1759                 buttonText: 'Update',
1760                 color: {
1761                     base: '#728E9B',
1762                     hover: '#004849',
1763                     text: '#ffffff'
1764                 },
1765                 handler: {
1766                     click: function () {
1767                         updateDistributionEnvironment(distributionEnvironmentEntity.id);
1768                     }
1769                 }
1770             }, {
1771                 buttonText: 'Cancel',
1772                 color: {
1773                     base: '#E3E8EB',
1774                     hover: '#C7D2D7',
1775                     text: '#004849'
1776                 },
1777                 handler: {
1778                     click: function () {
1779                         $(this).modal('hide');
1780                     }
1781                 }
1782             }]).modal('show');
1783         };
1784
1785
1786     /**
1787      * Prompts the user before attempting to delete the specified environment.
1788      *
1789      * @param {object} environmentEntity
1790      */
1791     var promptToRemoveDistributionEnvironment = function (environmentEntity) {
1792         // prompt for deletion
1793         nfDialog.showYesNoDialog({
1794             headerText: 'Delete Environment',
1795             dialogContent: 'Delete Environment \'' + nfCommon.escapeHtml(environmentEntity.name) + '\'?',
1796             yesHandler: function () {
1797                 removeDistributionEnvironment(environmentEntity);
1798             }
1799         });
1800     };
1801
1802
1803      /**
1804       * Deletes the specified environment.
1805       *
1806       * @param {object} environmentEntity
1807       */
1808      var removeDistributionEnvironment = function (environmentEntity) {
1809          console.log(environmentEntity);
1810          $.ajax({
1811              type: 'DELETE',
1812              url: '/distributor/distribution-targets/'+environmentEntity.id,
1813              dataType: 'json'
1814          }).done(function (response) {
1815           console.log(response);
1816              // remove the task
1817              var environmentsGrid = $('#distribution-environments-table').data('gridInstance');
1818              console.log(environmentsGrid);
1819              var environmentsData = environmentsGrid.getData();
1820              environmentsData.deleteItem(environmentEntity.id);
1821          }).fail(nfErrorHandler.handleAjaxError);
1822      };
1823
1824
1825     /**
1826      * Prompts the user before attempting to delete the specified registry.
1827      *
1828      * @param {object} registryEntity
1829      */
1830     var promptToRemoveRegistry = function (registryEntity) {
1831         // prompt for deletion
1832         nfDialog.showYesNoDialog({
1833             headerText: 'Delete Registry',
1834             dialogContent: 'Delete registry \'' + nfCommon.escapeHtml(registryEntity.component.name) + '\'?',
1835             yesHandler: function () {
1836                 removeRegistry(registryEntity);
1837             }
1838         });
1839     };
1840
1841     /**
1842      * Deletes the specified registry.
1843      *
1844      * @param {object} registryEntity
1845      */
1846     var removeRegistry = function (registryEntity) {
1847         var revision = nfClient.getRevision(registryEntity);
1848         $.ajax({
1849             type: 'DELETE',
1850             url: registryEntity.uri + '?' + $.param({
1851                 'version': revision.version,
1852                 'clientId': revision.clientId,
1853                 'disconnectedNodeAcknowledged': nfStorage.isDisconnectionAcknowledged()
1854             }),
1855             dataType: 'json'
1856         }).done(function (response) {
1857             // remove the task
1858             var registryGrid = $('#registries-table').data('gridInstance');
1859             var registryData = registryGrid.getData();
1860             registryData.deleteItem(registryEntity.id);
1861         }).fail(nfErrorHandler.handleAjaxError);
1862     };
1863
1864     /**
1865      * Loads the settings.
1866      */
1867     var loadSettings = function () {
1868         var setUnauthorizedText = function () {
1869             $('#read-only-maximum-timer-driven-thread-count-field').addClass('unset').text('Unauthorized');
1870             $('#read-only-maximum-event-driven-thread-count-field').addClass('unset').text('Unauthorized');
1871         };
1872
1873         var setEditable = function (editable) {
1874             if (editable) {
1875                 $('#general-settings div.editable').show();
1876                 $('#general-settings div.read-only').hide();
1877                 $('#settings-save').show();
1878             } else {
1879                 $('#general-settings div.editable').hide();
1880                 $('#general-settings div.read-only').show();
1881                 $('#settings-save').hide();
1882             }
1883         };
1884
1885         var settings = $.Deferred(function (deferred) {
1886             $.ajax({
1887                 type: 'GET',
1888                 url: config.urls.controllerConfig,
1889                 dataType: 'json'
1890             }).done(function (response) {
1891                 if (response.permissions.canWrite) {
1892                     // populate the settings
1893                     $('#maximum-timer-driven-thread-count-field').removeClass('unset').val(response.component.maxTimerDrivenThreadCount);
1894                     $('#maximum-event-driven-thread-count-field').removeClass('unset').val(response.component.maxEventDrivenThreadCount);
1895
1896                     setEditable(true);
1897
1898                     // register the click listener for the save button
1899                     $('#settings-save').off('click').on('click', function () {
1900                         saveSettings(response.revision.version);
1901                     });
1902                 } else {
1903                     if (response.permissions.canRead) {
1904                         // populate the settings
1905                         $('#read-only-maximum-timer-driven-thread-count-field').removeClass('unset').text(response.component.maxTimerDrivenThreadCount);
1906                         $('#read-only-maximum-event-driven-thread-count-field').removeClass('unset').text(response.component.maxEventDrivenThreadCount);
1907                     } else {
1908                         setUnauthorizedText();
1909                     }
1910
1911                     setEditable(false);
1912                 }
1913                 deferred.resolve();
1914             }).fail(function (xhr, status, error) {
1915                 if (xhr.status === 403) {
1916                     setUnauthorizedText();
1917                     setEditable(false);
1918                     deferred.resolve();
1919                 } else {
1920                     deferred.reject(xhr, status, error);
1921                 }
1922             });
1923         }).promise();
1924
1925         // load the controller services
1926         var controllerServicesUri = config.urls.api + '/flow/controller/controller-services';
1927         var controllerServicesXhr = nfControllerServices.loadControllerServices(controllerServicesUri, getControllerServicesTable());
1928
1929         // load the reporting tasks
1930         var reportingTasks = loadReportingTasks();
1931
1932         // load the registries
1933         var registries = loadRegistries();
1934
1935         // load the distribution environments
1936         var distributionEnvironments = loadDistributionEnvironments();
1937
1938         // return a deferred for all parts of the settings
1939         return $.when(settings, controllerServicesXhr, reportingTasks).done(function (settingsResult, controllerServicesResult) {
1940             var controllerServicesResponse = controllerServicesResult[0];
1941
1942             // update the current time
1943             $('#settings-last-refreshed').text(controllerServicesResponse.currentTime);
1944         }).fail(nfErrorHandler.handleAjaxError);
1945     };
1946
1947     /**
1948      * Loads the reporting tasks.
1949      */
1950     var loadReportingTasks = function () {
1951         return $.ajax({
1952             type: 'GET',
1953             url: config.urls.reportingTasks,
1954             dataType: 'json'
1955         }).done(function (response) {
1956             var tasks = [];
1957             $.each(response.reportingTasks, function (_, task) {
1958                 tasks.push($.extend({
1959                     type: 'ReportingTask',
1960                     bulletins: []
1961                 }, task));
1962             });
1963
1964             var reportingTasksElement = $('#reporting-tasks-table');
1965             nfCommon.cleanUpTooltips(reportingTasksElement, 'div.has-errors');
1966             nfCommon.cleanUpTooltips(reportingTasksElement, 'div.has-bulletins');
1967
1968             var reportingTasksGrid = reportingTasksElement.data('gridInstance');
1969             var reportingTasksData = reportingTasksGrid.getData();
1970
1971             // update the reporting tasks
1972             reportingTasksData.setItems(tasks);
1973             reportingTasksData.reSort();
1974             reportingTasksGrid.invalidate();
1975         });
1976     };
1977
1978     /**
1979      * Loads the registries.
1980      */
1981     var loadRegistries = function () {
1982         return $.ajax({
1983             type: 'GET',
1984             url: config.urls.registries,
1985             dataType: 'json'
1986         }).done(function (response) {
1987             var registries = [];
1988             $.each(response.registries, function (_, registryEntity) {
1989                 registries.push($.extend({
1990                     type: 'Registry'
1991                 }, registryEntity));
1992             });
1993
1994             var registriesGrid = $('#registries-table').data('gridInstance');
1995             var registriesData = registriesGrid.getData();
1996
1997             // update the registries
1998             registriesData.setItems(registries);
1999             registriesData.reSort();
2000             registriesGrid.invalidate();
2001         });
2002     };
2003
2004     /**
2005      * Loads the distribution environments.
2006      */
2007     var loadDistributionEnvironments = function(){
2008         console.log("in loadDistributionEnvironments.. ");
2009             return $.ajax({
2010                 type: 'GET',
2011                 url: '/distributor/distribution-targets',
2012                 dataType: 'json'
2013             }).done(function (response) {
2014                 console.log(response);
2015                 var environments = [];
2016                 $.each(response.distributionTargets, function (_, environmentEntity) {
2017                     console.log(environmentEntity);
2018                     environments.push($.extend({
2019                         type: 'Environment'
2020                     }, environmentEntity));
2021                 });
2022
2023                 console.log(environments);
2024                 var environmentsGrid = $('#distribution-environments-table').data('gridInstance');
2025                 console.log(environmentsGrid);
2026                 var environmentsData = environmentsGrid.getData();
2027
2028                 // update the distribution environments
2029                 environmentsData.setItems(environments);
2030                 environmentsData.reSort();
2031                 environmentsGrid.invalidate();
2032             });
2033     };
2034
2035     /**
2036      * Shows the process group configuration.
2037      */
2038     var showSettings = function () {
2039         // show the settings dialog
2040         nfShell.showContent('#settings').done(function () {
2041             reset();
2042         });
2043
2044         //reset content to account for possible policy changes
2045         $('#settings-tabs').find('.selected-tab').click();
2046
2047         // adjust the table size
2048         nfSettings.resetTableSize();
2049     };
2050
2051     /**
2052      * Reset state of this dialog.
2053      */
2054     var reset = function () {
2055         // reset button state
2056         $('#settings-save').mouseout();
2057     };
2058
2059     var nfSettings = {
2060         /**
2061          * Initializes the settings page.
2062          */
2063         init: function () {
2064             // initialize the settings tabs
2065             $('#settings-tabs').tabbs({
2066                 tabStyle: 'tab',
2067                 selectedTabStyle: 'selected-tab',
2068                 scrollableTabContentStyle: 'scrollable',
2069                 tabs: [{
2070                     name: 'General',
2071                     tabContentId: 'general-settings-tab-content'
2072                 }, {
2073                     name: 'Reporting Task Controller Services',
2074                     tabContentId: 'controller-services-tab-content'
2075                 }, {
2076                     name: 'Reporting Tasks',
2077                     tabContentId: 'reporting-tasks-tab-content'
2078                 }, {
2079                     name: 'Registry Clients',
2080                     tabContentId: 'registries-tab-content'
2081                 },{
2082                     name: 'Distribution Target Environments',
2083                     tabContentId: 'distribution-environment-content'
2084                   }
2085                 ],
2086                 select: function () {
2087                     var tab = $(this).text();
2088                     if (tab === 'General') {
2089                         $('#controller-cs-availability').hide();
2090                         $('#new-service-or-task').hide();
2091                         $('#settings-save').show();
2092                     } else {
2093                         var canModifyController = false;
2094                         if (nfCommon.isDefinedAndNotNull(nfCommon.currentUser)) {
2095                             // only consider write permissions for creating new controller services/reporting tasks
2096                             canModifyController = nfCommon.currentUser.controllerPermissions.canWrite === true;
2097                         }
2098
2099                         if (canModifyController) {
2100                             $('#new-service-or-task').show();
2101                             $('div.controller-settings-table').css('top', '32px');
2102
2103                             // update the tooltip on the button
2104                             $('#new-service-or-task').attr('title', function () {
2105                                 if (tab === 'Reporting Task Controller Services') {
2106                                     $('#settings-save').hide();
2107                                     return 'Create a new reporting task controller service';
2108                                 } else if (tab === 'Reporting Tasks') {
2109                                     $('#settings-save').hide();
2110                                     return 'Create a new reporting task';
2111                                 } else if (tab === 'Registry Clients') {
2112                                     $('#settings-save').hide();
2113                                     return 'Register a new registry client';
2114                                 }else if (tab === 'Distribution Target Environments') {
2115                                       console.log("in env tab...");
2116                                     $('#settings-save').hide();
2117                                     return 'Add a new distribution environment';
2118                                 }
2119                             });
2120                         } else {
2121                             $('#new-service-or-task').hide();
2122                             $('div.controller-settings-table').css('top', '0');
2123                         }
2124
2125                         if (tab === 'Reporting Task Controller Services') {
2126                             $('#controller-cs-availability').show();
2127                         } else if (tab === 'Reporting Tasks' || tab === 'Registry Clients'|| tab === 'Distribution Target Environments') {
2128                             $('#controller-cs-availability').hide();
2129                         }
2130
2131                         // resize the table
2132                         nfSettings.resetTableSize();
2133                     }
2134                 }
2135             });
2136
2137             // settings refresh button
2138             $('#settings-refresh-button').click(function () {
2139                 loadSettings();
2140             });
2141
2142             // create a new controller service or reporting task
2143             $('#new-service-or-task').on('click', function () {
2144             console.log("on Add Buttton clicked");
2145                 var selectedTab = $('#settings-tabs li.selected-tab').text();
2146                 if (selectedTab === 'Reporting Task Controller Services') {
2147                     var controllerServicesUri = config.urls.api + '/controller/controller-services';
2148                     nfControllerServices.promptNewControllerService(controllerServicesUri, getControllerServicesTable());
2149                 } else if (selectedTab === 'Reporting Tasks') {
2150                     $('#new-reporting-task-dialog').modal('show');
2151
2152                     var reportingTaskTypesGrid = $('#reporting-task-types-table').data('gridInstance');
2153                     if (nfCommon.isDefinedAndNotNull(reportingTaskTypesGrid)) {
2154                         var reportingTaskTypesData = reportingTaskTypesGrid.getData();
2155
2156                         // reset the canvas size after the dialog is shown
2157                         reportingTaskTypesGrid.resizeCanvas();
2158
2159                         // select the first row if possible
2160                         if (reportingTaskTypesData.getLength() > 0) {
2161                             nfFilteredDialogCommon.choseFirstRow(reportingTaskTypesGrid);
2162                         }
2163                     }
2164
2165                     // set the initial focus
2166                     $('#reporting-task-type-filter').focus();
2167                 } else if (selectedTab === 'Registry Clients') {
2168                     $('#registry-configuration-dialog').modal('setHeaderText', 'Add Registry Client').modal('setButtonModel', [{
2169                         buttonText: 'Add',
2170                         color: {
2171                             base: '#728E9B',
2172                             hover: '#004849',
2173                             text: '#ffffff'
2174                         },
2175                         handler: {
2176                             click: function () {
2177                                 addRegistry();
2178                             }
2179                         }
2180                     }, {
2181                         buttonText: 'Cancel',
2182                         color: {
2183                             base: '#E3E8EB',
2184                             hover: '#C7D2D7',
2185                             text: '#004849'
2186                         },
2187                         handler: {
2188                             click: function () {
2189                                 $(this).modal('hide');
2190                             }
2191                         }
2192                     }]).modal('show');
2193
2194                     // set the initial focus
2195                     $('#registry-name').focus();
2196                 } else if (selectedTab === 'Distribution Target Environments') {
2197                                     $('#distribution-environment-dialog').modal('setHeaderText', 'Add New Environment').modal('setButtonModel', [{
2198                                         buttonText: 'Add',
2199                                         color: {
2200                                             base: '#728E9B',
2201                                             hover: '#004849',
2202                                             text: '#ffffff'
2203                                         },
2204                                         handler: {
2205                                             click: function () {
2206                                                 addDistributionEnvironment();
2207                                             }
2208                                         }
2209                                     }, {
2210                                         buttonText: 'Cancel',
2211                                         color: {
2212                                             base: '#E3E8EB',
2213                                             hover: '#C7D2D7',
2214                                             text: '#004849'
2215                                         },
2216                                         handler: {
2217                                             click: function () {
2218                                                 $(this).modal('hide');
2219                                             }
2220                                         }
2221                                     }]).modal('show');
2222
2223                              $(window).resize(function() {
2224                                   var x=0;
2225                                   console.log(x);
2226                                   $("#distribution-environment-content").text(x= x + 1);
2227                               });
2228
2229                               $(window).resize(function() {
2230                                   var x=0;
2231                                   console.log(x);
2232                                   $("#distribution-environments-table").text(x= x + 1);
2233                                   console.log(x);
2234                                   console.log("resizing...table...");
2235                               });
2236                                     // set the initial focus
2237                                     $('#distribution-environment-name').focus();
2238                                 }
2239             });
2240
2241             // initialize each tab
2242             initGeneral();
2243             nfControllerServices.init(getControllerServicesTable(), nfSettings.showSettings);
2244             initReportingTasks();
2245             initRegistriesTable();
2246             initDistributionEnvironmentsTable();
2247         },
2248
2249         /**
2250          * Update the size of the grid based on its container's current size.
2251          */
2252         resetTableSize: function () {
2253             nfControllerServices.resetTableSize(getControllerServicesTable());
2254             nfControllerServices.resetTableSize(getDistributionEnvironmentsTable());
2255
2256             var reportingTasksGrid = $('#reporting-tasks-table').data('gridInstance');
2257             if (nfCommon.isDefinedAndNotNull(reportingTasksGrid)) {
2258                 reportingTasksGrid.resizeCanvas();
2259             }
2260         },
2261
2262         /**
2263          * Shows the settings dialog.
2264          */
2265         showSettings: function () {
2266             return loadSettings().done(showSettings);
2267         },
2268
2269         /**
2270          * Loads the settings dialogs.
2271          */
2272         loadSettings: function () {
2273             return loadSettings();
2274         },
2275
2276         /**
2277          * Selects the specified controller service.
2278          *
2279          * @param {string} controllerServiceId
2280          */
2281         selectControllerService: function (controllerServiceId) {
2282             var controllerServiceGrid = getControllerServicesTable().data('gridInstance');
2283             var controllerServiceData = controllerServiceGrid.getData();
2284
2285             // select the desired service
2286             var row = controllerServiceData.getRowById(controllerServiceId);
2287             nfFilteredDialogCommon.choseRow(controllerServiceGrid, row);
2288             controllerServiceGrid.scrollRowIntoView(row);
2289
2290             // select the controller services tab
2291             $('#settings-tabs').find('li:eq(1)').click();
2292         },
2293
2294         /**
2295          * Selects the specified reporting task.
2296          *
2297          * @param {string} reportingTaskId
2298          */
2299         selectReportingTask: function (reportingTaskId) {
2300             var reportingTaskGrid = $('#reporting-tasks-table').data('gridInstance');
2301             var reportingTaskData = reportingTaskGrid.getData();
2302
2303             // select the desired service
2304             var row = reportingTaskData.getRowById(reportingTaskId);
2305             nfFilteredDialogCommon.choseRow(reportingTaskGrid, row);
2306             reportingTaskGrid.scrollRowIntoView(row);
2307
2308             // select the controller services tab
2309             $('#settings-tabs').find('li:eq(2)').click();
2310         },
2311
2312         /**
2313          * Sets the controller service and reporting task bulletins in their respective tables.
2314          *
2315          * @param {object} controllerServiceBulletins
2316          * @param {object} reportingTaskBulletins
2317          */
2318         setBulletins: function (controllerServiceBulletins, reportingTaskBulletins) {
2319             if ($('#controller-services-table').data('gridInstance')) {
2320                 nfControllerServices.setBulletins(getControllerServicesTable(), controllerServiceBulletins);
2321             }
2322
2323             // reporting tasks
2324             var reportingTasksGrid = $('#reporting-tasks-table').data('gridInstance');
2325             var reportingTasksData = reportingTasksGrid.getData();
2326             reportingTasksData.beginUpdate();
2327
2328             // if there are some bulletins process them
2329             if (!nfCommon.isEmpty(reportingTaskBulletins)) {
2330                 var reportingTaskBulletinsBySource = d3.nest()
2331                     .key(function (d) {
2332                         return d.sourceId;
2333                     })
2334                     .map(reportingTaskBulletins, d3.map);
2335
2336                 reportingTaskBulletinsBySource.each(function (sourceBulletins, sourceId) {
2337                     var reportingTask = reportingTasksData.getItemById(sourceId);
2338                     if (nfCommon.isDefinedAndNotNull(reportingTask)) {
2339                         reportingTasksData.updateItem(sourceId, $.extend(reportingTask, {
2340                             bulletins: sourceBulletins
2341                         }));
2342                     }
2343                 });
2344             } else {
2345                 // if there are no bulletins clear all
2346                 var reportingTasks = reportingTasksData.getItems();
2347                 $.each(reportingTasks, function (_, reportingTask) {
2348                     reportingTasksData.updateItem(reportingTask.id, $.extend(reportingTask, {
2349                         bulletins: []
2350                     }));
2351                 });
2352             }
2353             reportingTasksData.endUpdate();
2354         }
2355     };
2356
2357     return nfSettings;
2358 }));