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