Initial commit for OpenECOMP SDN-C OA&M
[sdnc/oam.git] / dgbuilder / public / red / main.js
1 /**
2  * Copyright 2013 IBM Corp.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  **/
16 var RED = (function() {
17
18     function hideDropTarget() {
19         $("#dropTarget").hide();
20         RED.keyboard.remove(/* ESCAPE */ 27);
21     }
22
23     $('#chart').on("dragenter",function(event) {
24         if ($.inArray("text/plain",event.originalEvent.dataTransfer.types) != -1) {
25             $("#dropTarget").css({display:'table'});
26             RED.keyboard.add(/* ESCAPE */ 27,hideDropTarget);
27         }
28     });
29
30     $('#dropTarget').on("dragover",function(event) {
31         if ($.inArray("text/plain",event.originalEvent.dataTransfer.types) != -1) {
32             event.preventDefault();
33         }
34     })
35     .on("dragleave",function(event) {
36         hideDropTarget();
37     })
38     .on("drop",function(event) {
39         var data = event.originalEvent.dataTransfer.getData("text/plain");
40         hideDropTarget();
41         RED.view.importNodes(data);
42         event.preventDefault();
43     });
44
45
46     function save(force) {
47         if (RED.view.dirty()) {
48             //$("#debug-tab-clear").click();  // uncomment this to auto clear debug on deploy
49
50             if (!force) {
51                 var invalid = false;
52                 var unknownNodes = [];
53                 RED.nodes.eachNode(function(node) {
54                     invalid = invalid || !node.valid;
55                     if (node.type === "unknown") {
56                         if (unknownNodes.indexOf(node.name) == -1) {
57                             unknownNodes.push(node.name);
58                         }
59                         invalid = true;
60                     }
61                 });
62                 if (invalid) {
63                     if (unknownNodes.length > 0) {
64                         $( "#node-dialog-confirm-deploy-config" ).hide();
65                         $( "#node-dialog-confirm-deploy-unknown" ).show();
66                         var list = "<li>"+unknownNodes.join("</li><li>")+"</li>";
67                         $( "#node-dialog-confirm-deploy-unknown-list" ).html(list);
68                     } else {
69                         $( "#node-dialog-confirm-deploy-config" ).show();
70                         $( "#node-dialog-confirm-deploy-unknown" ).hide();
71                     }
72                     $( "#node-dialog-confirm-deploy" ).dialog( "open" );
73                     return;
74                 }
75             }
76             var nns = RED.nodes.createCompleteNodeSet();
77             /****************************************/
78             /*added new code to save the Tabs order */
79             /****************************************/ 
80             //console.log("nns before changes.");
81             //console.dir(nns);
82             var allTabsObj={};
83             var allTabsList=[];
84             var nnsTabIdsArr = [];
85             var guiTabIdsArr = [];
86             nns.forEach(function(n) {
87                         if(n.type == 'tab'){
88                                 allTabsObj[n.id] = n;
89                                 allTabsList.push(n);
90                                 nnsTabIdsArr.push(n.id);
91                         }
92             });
93             var idx =0; 
94             $("#workspace-tabs li a").each(function(){
95                 var href = $(this).prop("href");
96                 var indexOfHash = href.indexOf("#");
97                 var idVal = href.slice(indexOfHash+1);
98                 guiTabIdsArr.push(idVal);
99                 nns.splice(idx,1,allTabsObj[idVal]);;
100                 idx++;
101             }); 
102             //console.log(nnsTabIdsArr.join(","));      
103             //console.log(guiTabIdsArr.join(","));      
104             //console.log("nns after changes.");
105             //console.dir(nns);
106             /****************************/ 
107             $("#btn-icn-deploy").removeClass('fa-download');
108             $("#btn-icn-deploy").addClass('spinner');
109             RED.view.dirty(false);
110
111             $.ajax({
112                 url:"flows",
113                 type: "POST",
114                 data: JSON.stringify(nns),
115                 contentType: "application/json; charset=utf-8"
116             }).done(function(data,textStatus,xhr) {
117                 RED.notify("Successfully saved","success");
118                 RED.nodes.eachNode(function(node) {
119                     if (node.changed) {
120                         node.dirty = true;
121                         node.changed = false;
122                     }
123                     if(node.credentials) {
124                         delete node.credentials;
125                     }
126                 });
127                 RED.nodes.eachConfig(function (confNode) {
128                     if (confNode.credentials) {
129                         delete confNode.credentials;
130                     }
131                 });
132                 // Once deployed, cannot undo back to a clean state
133                 RED.history.markAllDirty();
134                 RED.view.redraw();
135             }).fail(function(xhr,textStatus,err) {
136                 RED.view.dirty(true);
137                 if (xhr.responseText) {
138                     RED.notify("<strong>Error</strong>: "+xhr.responseText,"error");
139                 } else {
140                     RED.notify("<strong>Error</strong>: no response from server","error");
141                 }
142             }).always(function() {
143                 $("#btn-icn-deploy").removeClass('spinner');
144                 $("#btn-icn-deploy").addClass('fa-download');
145             });
146         }
147     }
148
149     $('#btn-deploy').click(function() { save(); });
150
151     $( "#node-dialog-confirm-deploy" ).dialog({
152             title: "Confirm deploy",
153             modal: true,
154             autoOpen: false,
155             width: 530,
156             height: 230,
157             buttons: [
158                 {
159                     text: "Confirm deploy",
160                     click: function() {
161                         save(true);
162                         $( this ).dialog( "close" );
163                     }
164                 },
165                 {
166                     text: "Cancel",
167                     click: function() {
168                         $( this ).dialog( "close" );
169                     }
170                 }
171             ]
172     });
173
174     function loadSettings() {
175         $.get('settings', function(data) {
176             RED.settings = data;
177             console.log("Node-RED: "+data.version);
178             loadNodeList();
179         });
180     }
181
182     function loadNodeList() {
183         $.ajax({
184             headers: {
185                 "Accept":"application/json"
186             },
187             cache: false,
188             url: 'nodes',
189             success: function(data) {
190                 RED.nodes.setNodeList(data);
191                 loadNodes();
192             }
193         });
194     }
195
196     function loadNodes() {
197         $.ajax({
198             headers: {
199                 "Accept":"text/html"
200             },
201             cache: false,
202             url: 'nodes',
203             success: function(data) {
204                 $("body").append(data);
205                 $(".palette-spinner").hide();
206                 $(".palette-scroll").show();
207                 $("#palette-search").show();
208                 loadFlows();
209             }
210         });
211     }
212
213     function loadFlows() {
214         $.ajax({
215             headers: {
216                 "Accept":"application/json"
217             },
218             cache: false,
219             url: 'flows',
220             success: function(nodes) {
221                 RED.nodes.import(nodes);
222                 RED.view.dirty(false);
223                 RED.view.redraw();
224                 RED.comms.subscribe("status/#",function(topic,msg) {
225                     var parts = topic.split("/");
226                     var node = RED.nodes.node(parts[1]);
227                     if (node) {
228                         node.status = msg;
229                         if (statusEnabled) {
230                             node.dirty = true;
231                             RED.view.redraw();
232                         }
233                     }
234                 });
235                 RED.comms.subscribe("node/#",function(topic,msg) {
236                     var i,m;
237                     var typeList;
238                     var info;
239                     
240                     if (topic == "node/added") {
241                         var addedTypes = [];
242                         for (i=0;i<msg.length;i++) {
243                             m = msg[i];
244                             var id = m.id;
245                             RED.nodes.addNodeSet(m);
246                             if (m.loaded) {
247                                 addedTypes = addedTypes.concat(m.types);
248                                 $.get('nodes/'+id, function(data) {
249                                     $("body").append(data);
250                                 });
251                             }
252                         }
253                         if (addedTypes.length) {
254                             typeList = "<ul><li>"+addedTypes.join("</li><li>")+"</li></ul>";
255                             RED.notify("Node"+(addedTypes.length!=1 ? "s":"")+" added to palette:"+typeList,"success");
256                         }
257                     } else if (topic == "node/removed") {
258                         for (i=0;i<msg.length;i++) {
259                             m = msg[i];
260                             info = RED.nodes.removeNodeSet(m.id);
261                             if (info.added) {
262                                 typeList = "<ul><li>"+m.types.join("</li><li>")+"</li></ul>";
263                                 RED.notify("Node"+(m.types.length!=1 ? "s":"")+" removed from palette:"+typeList,"success");
264                             }
265                         }
266                     } else if (topic == "node/enabled") {
267                         if (msg.types) {
268                             info = RED.nodes.getNodeSet(msg.id);
269                             if (info.added) {
270                                 RED.nodes.enableNodeSet(msg.id);
271                                 typeList = "<ul><li>"+msg.types.join("</li><li>")+"</li></ul>";
272                                 RED.notify("Node"+(msg.types.length!=1 ? "s":"")+" enabled:"+typeList,"success");
273                             } else {
274                                 $.get('nodes/'+msg.id, function(data) {
275                                     $("body").append(data);
276                                     typeList = "<ul><li>"+msg.types.join("</li><li>")+"</li></ul>";
277                                     RED.notify("Node"+(msg.types.length!=1 ? "s":"")+" added to palette:"+typeList,"success");
278                                 });
279                             } 
280                         }
281                     } else if (topic == "node/disabled") {
282                         if (msg.types) {
283                             RED.nodes.disableNodeSet(msg.id);
284                             typeList = "<ul><li>"+msg.types.join("</li><li>")+"</li></ul>";
285                             RED.notify("Node"+(msg.types.length!=1 ? "s":"")+" disabled:"+typeList,"success");
286                         }
287                     }
288                 });
289             }
290         });
291     }
292
293     var statusEnabled = false;
294     function toggleStatus(state) {
295         statusEnabled = state;
296         RED.view.status(statusEnabled);
297     }
298
299     function performLoopDetection(state) {
300         loopDetectionEnabled = state;
301         console.log("loopDetectionEnabled:" + loopDetectionEnabled);
302     }
303
304     var dgNumberEnabled = false;
305     function toggleDgNumberDisplay(state) {
306         dgNumberEnabled = state;
307         RED.view.showNumbers(dgNumberEnabled);
308     }
309
310     var nodePaletteDisplay = false;
311     function toggleNodePaletteDisplay(state) {
312         nodePaletteDisplay = state;
313         RED.view.showNodePalette(nodePaletteDisplay);
314     }
315     function displayAllDGs(state) {
316                 //defined showSLa() in dgstart.html 
317                 showSLA();
318     }
319
320
321     function showHelp() {
322
323         var dialog = $('#node-help');
324
325         //$("#node-help").draggable({
326         //        handle: ".modal-header"
327         //});
328
329         dialog.on('show',function() {
330             RED.keyboard.disable();
331         });
332         dialog.on('hidden',function() {
333             RED.keyboard.enable();
334         });
335
336         dialog.modal();
337     }
338
339
340 //Custom Functions Added here
341         function  showCodeCloudFlows(){
342                 codeCloudFlowFiles=[];
343                 var divStyle="<style>#codecloud-data-container a { color: #067ab4; font-size: 0.75em;} #codecloud-data-container a:hover { text-decoration: underline; padding: -15px -15px -15px 15px; } .header { height: 40px; border-bottom: 1px solid #EEE; background-color: #ffffff; height: 40px; -webkit-border-top-left-radius: 5px; -webkit-border-top-right-radius: 5px; -moz-border-radius-topleft: 5px; -moz-border-radius-topright: 5px; border-top-left-radius: 5px; border-top-right-radius: 5px; } .footer { height: 40px; background-color: whiteSmoke; border-top: 1px solid #DDD; -webkit-border-bottom-left-radius: 5px; -webkit-border-bottom-right-radius: 5px; -moz-border-radius-bottomleft: 5px; -moz-border-radius-bottomright: 5px; border-bottom-left-radius: 5px; border-bottom-right-radius: 5px; }</style>";
344                 $.get( "/getCodeCloudFlows")
345                                .done(function( data ) {
346                                         
347                                         var header="<div class='header'>List of DG Flows in Code Cloud</div><div><input id='flowFilterBoxId' type='text' onkeyup='filterFlows(this.value)'></div>";
348                                         var html=  divStyle + header +  "<div id='codecloud-data-container'>";
349                                         html+="<ul>";
350                                         if(data != null){
351                                                 var files=data.files;
352                                                 codeCloudFlowFiles=files;
353                                                 //console.dir(files);
354                                                 files.sort(function (a,b){
355                                                         if(a > b){
356                                                                 return 1;
357                                                         }else if(a <  b){
358                                                                 return -1;
359                                                         }else{  
360                                                                 return 0;
361                                                         }
362                                                 });
363                                                 for(var i=0;files != null && i<files.length;i++){
364                                                         html+="<li><a href=\"#\" onclick=\"getCommits('" + files[i] + "')\">" + files[i] + "</a></li>";
365                                                 }
366                                         }
367                                         html+="</ul>";
368                                         html+="</div>";
369                                         $( "#codecloud-browser-dialog" ).dialog({
370                                         title: "Code Cloud DG Flow Browser",
371                                         modal: true,
372                                         autoOpen: true,
373                                         width: 830,
374                                         height: 630,
375                                         buttons: [
376                                                 {
377                                                         text: "Close",
378                                                         click: function() {
379                                                                 $( this ).dialog( "close" );
380                                                         }
381                                                 }
382                                                 ],
383                                         close: function(ev,ui){
384                                                 $(this).dialog("destroy");
385                                         }
386                                         }).html(html);
387                                         $("#codecloud-browser-dialog").show();
388                                })
389                                 .fail(function(err) {
390                                          RED.notify("Failed to get users.");
391                                 })
392                                  .always(function() {
393                                 });
394         }
395                 
396         /*
397         function  listYangFiles(){
398                 yangFilesList=[];
399                 var divStyle="<style>#list-yang-data-container a { color: #067ab4; font-size: 0.75em;} #list-yang-data-container a:hover { text-decoration: underline; padding: -15px -15px -15px 15px; } .header { height: 40px; border-bottom: 1px solid #EEE; background-color: #ffffff; height: 40px; -webkit-border-top-left-radius: 5px; -webkit-border-top-right-radius: 5px; -moz-border-radius-topleft: 5px; -moz-border-radius-topright: 5px; border-top-left-radius: 5px; border-top-right-radius: 5px; } .footer { height: 40px; background-color: whiteSmoke; border-top: 1px solid #DDD; -webkit-border-bottom-left-radius: 5px; -webkit-border-bottom-right-radius: 5px; -moz-border-radius-bottomleft: 5px; -moz-border-radius-bottomright: 5px; border-bottom-left-radius: 5px; border-bottom-right-radius: 5px; }</style>";
400                 $.get( "/getYangFiles")
401                                .done(function( data ) {
402                                         
403                                         var header="<div class='header'>List of Yang Files </div><div><input id='flowFilterBoxId' type='text' onkeyup='filterYangFiles(this.value)'></div>";
404                                         var html=  divStyle + header +  "<div id='list-yang-data-container'>";
405                                         html+="<ul>";
406                                         if(data != null){
407                                                 var files=data.files;
408                                                 yangFilesList=files;
409                                                 //console.dir(files);
410                                                 files.sort(function (a,b){
411                                                         if(a > b){
412                                                                 return 1;
413                                                         }else if(a <  b){
414                                                                 return -1;
415                                                         }else{  
416                                                                 return 0;
417                                                         }
418                                                 });
419                                                 for(var i=0;files != null && i<files.length;i++){
420                                                         html+="<li><a href=\"#\" onclick=\"getYangFile('" + files[i] + "')\">" + files[i] + "</a></li>";
421                                                 }
422                                         }
423                                         html+="</ul>";
424                                         html+="</div>";
425                                         $( "#list-yang-browser-dialog" ).dialog({
426                                         title: "List Yang Files",
427                                         modal: true,
428                                         autoOpen: true,
429                                         width: 830,
430                                         height: 630,
431                                         buttons: [
432                                                 {
433                                                         text: "Close",
434                                                         click: function() {
435                                                                 $( this ).dialog( "close" );
436                                                         }
437                                                 }
438                                                 ],
439                                         close: function(ev,ui){
440                                                 $(this).dialog("destroy");
441                                         }
442                                         }).html(html);
443                                         $("#list-yang-browser-dialog").show();
444                                })
445                                 .fail(function(err) {
446                                          RED.notify("Failed to get yang files.");
447                                 })
448                                  .always(function() {
449                                 });
450         }
451         */
452
453         function  listYangFiles(){
454                 yangFilesList=[];
455         
456                 var divStyle="<style>#yang-files-data-container a { color: #067ab4; font-size: 0.75em;} #yang-files-data-container a:hover { text-decoration: underline; padding: -15px -15px -15px 15px; } .header { height: 40px; border-bottom: 1px solid #EEE; background-color: #ffffff; height: 40px; -webkit-border-top-left-radius: 5px; -webkit-border-top-right-radius: 5px; -moz-border-radius-topleft: 5px; -moz-border-radius-topright: 5px; border-top-left-radius: 5px; border-top-right-radius: 5px; } .footer { height: 40px; background-color: whiteSmoke; border-top: 1px solid #DDD; -webkit-border-bottom-left-radius: 5px; -webkit-border-bottom-right-radius: 5px; -moz-border-radius-bottomleft: 5px; -moz-border-radius-bottomright: 5px; border-bottom-left-radius: 5px; border-bottom-right-radius: 5px; } table#yang-file-list-table { width:100%; } table#yang-file-list-table th,table#yang-file-list-table td { border: 1px solid black; border-collapse: collapse; } table#yang-file-list-table th,table#yang-file-list-table td { padding: 5px; text-align: left; } table#yang-file-list-table tr:nth-child(even) { background-color: #eee; } table#yang-file-list-table tr:nth-child(odd) { background-color:#fff; } table#yang-file-list-table th    { background-color: #65a9d7; color: white; } table#yang-file-list-table a { color: #337ab7; } table#yang-file-list-table a:link { color: #65a9d7; } table#yang-file-list-table a:visited { color: #636; } table#yang-file-list-table a:hover { color: #3366CC; cursor: pointer } table#yang-file-list-table a:active { color: #65a9d7 }</style>";
457                 $.get( "/getYangFiles")
458                                .done(function( data ) {
459                                         
460                                         var header="<div class='header'>List of Yang Files </div><div><input id='flowFilterBoxId' type='text' onkeyup='filterYangFiles(this.value)'></div>";
461                                         var html=  divStyle + header +  "<div id='yang-files-data-container'>";
462                                         html+="<table id='yang-file-list-table'  border=1>";
463                                         html+="<tr>";
464                                         html+="<th>File</th>";
465                                         html+="<th>Delete</th>";
466                                         html+="</tr>";
467                                         if(data != null){
468                                                 var files=data.files;
469                                                 yangFilesList=files;
470                                                 //console.dir(files);
471                                                 files.sort(function (a,b){
472                                                         if(a > b){
473                                                                 return 1;
474                                                         }else if(a <  b){
475                                                                 return -1;
476                                                         }else{  
477                                                                 return 0;
478                                                         }
479                                                 });
480                                                 for(var i=0;files != null && i<files.length;i++){
481                                                         html+="<tr><td><a href=\"#\" onclick=\"getYangFile('" + files[i] + "')\">" + files[i] + "</a></td><td>" + "<input type='button'  onclick='deleteYangFile(\"" + files[i]  + "\")' value='Delete'></td></td></td></tr>";
482                                                 }
483                                         }
484                                         html+="</table>";
485                                         html+="</div>";
486                                         $( "#list-yang-browser-dialog" ).dialog({
487                                         title: "List Yang Files",
488                                         modal: true,
489                                         autoOpen: true,
490                                         width: 830,
491                                         height: 630,
492                                         buttons: [
493                                                 {
494                                                         text: "Close",
495                                                         click: function() {
496                                                                 $( this ).dialog( "close" );
497                                                         }
498                                                 }
499                                                 ],
500                                         close: function(ev,ui){
501                                                 $(this).dialog("destroy");
502                                         }
503                                         }).html(html);
504                                         $("#list-yang-browser-dialog").show();
505                                })
506                                 .fail(function(err) {
507                                          RED.notify("Failed to get yang files.");
508                                 })
509                                  .always(function() {
510                                 });
511         }
512                 
513
514         function showGitPullDialog(){
515                 $.get( "/getCurrentGitBranch")
516                                .done(function( data ) {
517                                         if(data != null){ 
518                                                 if(data.output == "GIT_LOCAL_REPOSITORY_NOT_SET" ){
519                                                         RED.notify("Git Local Repository path is not set. Please set it by choosing Configuration from the menu.");
520                                                         return;
521                                                 }       
522
523                                                 var html= "<div id='gitcheckout-container'>";
524                                                 html+="<table>";
525                                                 html+="<tr>";
526                                                 html+="<td>Branch</td>";
527                                                 html+="<td>" +  data.output + "</td>";
528                                                 html+="</tr>";
529                                                 html+="<tr>";
530                                                 html+="<td><input id='gitPullBtnId' type='button' value='Pull' onclick='performGitPull()'></td>";
531                                                 html+="<td>&nbsp;&nbsp;</td>"
532                                                 html+="</tr>";
533                                                 html+="<tr>";
534                                                 //html+="<td colspan=3><textarea readonly='1' rows='5' cols='200'  id='responseId'></textarea></td>";
535                                                 html+="</tr>";
536                                                 html+="</table>";
537                                                 html+="<br><div id='responseId'></div>";
538                                                 html+="</div>";
539                                                 $( "#gitcommands-dialog" ).dialog({
540                                                         title: "Git Pull",
541                                                         modal: true,
542                                                         autoOpen: true,
543                                                         width: 630,
544                                                         height: 500,
545                                                         buttons: [
546                                                         {
547                                                                 text: "Close",
548                                                                 click: function() {
549                                                                         $( this ).dialog( "close" );
550                                                                 }
551                                                         }
552                                                         ],
553                                                         close: function(ev,ui){
554                                                                 $(this).dialog("destroy");
555                                                         }
556                                                 }).html(html);
557                                           $("#responseId").css({width:'550',height:'275px', border: '2px solid lightgrey',overflow:'scroll', padding: '20px' });
558                                           $("#responseId").hide();
559                                         $("#gitcommands-dialog").show();
560                                 }
561                                })
562                                 .fail(function(err) {
563                                          RED.notify("Failed to get gitBranch.");
564                                 })
565                                  .always(function() {
566                                 });
567         }
568
569         function showGitStatusDialog(){
570                 $.get( "/getCurrentGitBranch")
571                                .done(function( data ) {
572                                         if(data != null){ 
573                                                 if(data.output == "GIT_LOCAL_REPOSITORY_NOT_SET" ){
574                                                         RED.notify("Git Local Repository path is not set. Please set it by choosing Configuration from the menu.");
575                                                         return;
576                                                 }       
577
578                                                 var html= "<div id='gitcheckout-container'>";
579                                                 html+="<table>";
580                                                 html+="<tr>";
581                                                 html+="<td>Branch</td>";
582                                                 html+="<td>" + data.output + "</td>";
583                                                 html+="</tr>";
584                                                 html+="<tr>";
585                                                 html+="<td><input id='gitStatusBtnId' type='button' value='Status' onclick='performGitStatus()'></td>";
586                                                 html+="<td>&nbsp;&nbsp;</td>"
587                                                 html+="</tr>";
588                                                 html+="<tr>";
589                                                 //html+="<td colspan=3><textarea readonly='1' rows='5' cols='200'  id='responseId'></textarea></td>";
590                                                 html+="</tr>";
591                                                 html+="</table>";
592                                                 html+="<br><div id='responseId'></div>";
593                                                 html+="</div>";
594                                                 $( "#gitcommands-dialog" ).dialog({
595                                                         title: "Git Status",
596                                                         modal: true,
597                                                         autoOpen: true,
598                                                         width: 630,
599                                                         height: 500,
600                                                         buttons: [
601                                                         {
602                                                                 text: "Close",
603                                                                 click: function() {
604                                                                         $( this ).dialog( "close" );
605                                                                 }
606                                                         }
607                                                         ],
608                                                         close: function(ev,ui){
609                                                                 $(this).dialog("destroy");
610                                                         }
611                                                 }).html(html);
612                                           //$("#responseId").css({width:'600px',height:'100px','border-radius' : '25px', border: '2px solid lightgrey', padding: '20px' });
613                                           $("#responseId").css({width:'550px',height:'100px', border: '2px solid lightgrey',overflow:'scroll', padding: '20px' });
614                                           $("#responseId").hide();
615                                         $("#gitcommands-dialog").show();
616                                 }
617                                })
618                                 .fail(function(err) {
619                                          RED.notify("Failed to get gitBranch.");
620                                 })
621                                  .always(function() {
622                                 });
623         }
624
625         function showGitCheckoutDialog(){
626                 $.get( "/getCurrentGitBranch")
627                                .done(function( data ) {
628                                         if(data != null){ 
629                                                 if(data.output == "GIT_LOCAL_REPOSITORY_NOT_SET" ){
630                                                         RED.notify("Git Local Repository path is not set. Please set it by choosing Configuration from the menu.");
631                                                         return;
632                                                 }       
633
634                                                 var html= "<div id='gitcheckout-container'>";
635                                                 html+="<table>";
636                                                 html+="<tr>";
637                                                 html+="<td>Branch</td>";
638                                                 html+="<td><input id='branchId' type='text' value='" + data.output + "'></td>";
639                                                 html+="</tr>";
640                                                 html+="<tr>";
641                                                 html+="<td><input id='checkoutBtnId' type='button' value='Checkout' onclick='performGitCheckout()'></td>";
642                                                 html+="<td>&nbsp;&nbsp;</td>"
643                                                 html+="</tr>";
644                                                 html+="<tr>";
645                                                 //html+="<td colspan=3><textarea readonly='1' rows='5' cols='200'  id='responseId'></textarea></td>";
646                                                 html+="</tr>";
647                                                 html+="</table>";
648                                                 html+="<br><div id='responseId'></div>";
649                                                 html+="</div>";
650                                                 $( "#gitcommands-dialog" ).dialog({
651                                                         title: "Git Checkout",
652                                                         modal: true,
653                                                         autoOpen: true,
654                                                         width: 430,
655                                                         height: 350,
656                                                         buttons: [
657                                                         {
658                                                                 text: "Close",
659                                                                 click: function() {
660                                                                         $( this ).dialog( "close" );
661                                                                 }
662                                                         }
663                                                         ],
664                                                         close: function(ev,ui){
665                                                                 $(this).dialog("destroy");
666                                                         }
667                                                 }).html(html);
668                                           $("#responseId").css({width:'300',height:'100px', border: '2px solid lightgrey',overflow:'scroll', padding: '20px' });
669                                           $("#responseId").hide();
670                                         $("#gitcommands-dialog").show();
671                                 }
672                                })
673                                 .fail(function(err) {
674                                          RED.notify("Failed to get gitBranch.");
675                                 })
676                                  .always(function() {
677                                 });
678         }
679
680         function  showGitLocalFlows(){
681                 giLocalFlowFiles=[];
682                 var divStyle="<style>#gitlocal-data-container a { color: #067ab4; font-size: 0.75em;} #gitlocal-data-container a:hover { text-decoration: underline; padding: -15px -15px -15px 15px; } .header { height: 40px; border-bottom: 1px solid #EEE; background-color: #ffffff; height: 40px; -webkit-border-top-left-radius: 5px; -webkit-border-top-right-radius: 5px; -moz-border-radius-topleft: 5px; -moz-border-radius-topright: 5px; border-top-left-radius: 5px; border-top-right-radius: 5px; } .footer { height: 40px; background-color: whiteSmoke; border-top: 1px solid #DDD; -webkit-border-bottom-left-radius: 5px; -webkit-border-bottom-right-radius: 5px; -moz-border-radius-bottomleft: 5px; -moz-border-radius-bottomright: 5px; border-bottom-left-radius: 5px; border-bottom-right-radius: 5px; }</style>";
683                 $.get( "/getGitLocalFlows")
684                                .done(function( data ) {
685                                         if(data != null && data.files != null && data.files.length == 1){
686                                                 if(data.files[0] == "GIT_LOCAL_REPOSITORY_NOT_SET" ){
687                                                         RED.notify("Git Local Repository path is not set. Please set it by choosing Configuration from the menu.");
688                                                         return;
689                                                 }       
690                                         }
691                                         //console.log("got response from server.");
692                                         
693                                         var header="<div class='header'>List of DG Flows  from  Git Local Repository </div><div><input id='flowFilterBoxId' type='text' onkeyup='filterGitLocalFlows(this.value)'></div>";
694                                         var html=  divStyle + header +  "<div id='gitlocal-data-container'>";
695                                         html+="<ul>";
696                                         if(data != null){
697                                                 var files=data.files;
698                                                 gitLocalFlowFiles=files;
699                                                 //console.dir(files);
700                                                 files.sort(function (a,b){
701                                                         if(a > b){
702                                                                 return 1;
703                                                         }else if(a <  b){
704                                                                 return -1;
705                                                         }else{  
706                                                                 return 0;
707                                                         }
708                                                 });
709                                                 for(var i=0;files != null && i<files.length;i++){
710                                                         html+="<li><a href=\"#\" onclick=\"importGitLocalFlow('" + files[i] + "')\">" + files[i] + "</a></li>";
711                                                 }
712                                         }
713                                         html+="</ul>";
714                                         html+="</div>";
715                                         $( "#gitlocal-browser-dialog" ).dialog({
716                                         title: "Git Local Repository DG Flow Browser",
717                                         modal: true,
718                                         autoOpen: true,
719                                         width: 830,
720                                         height: 630,
721                                         buttons: [
722                                                 {
723                                                         text: "Close",
724                                                         click: function() {
725                                                                 $(this).dialog("close");
726                                                         }
727                                                 }
728                                                 ]
729                                         }).html(html);
730                                         $("#gitlocal-browser-dialog").show();
731                                         /*
732                                         if ($("#gitlocal-browser-dialog").dialog( "isOpen" )===true) {
733                                                 console.log("gitlocal dialog box is open");     
734                                                 //true
735                                         } else {
736                                                 console.log("gitlocal dialog box is not open"); 
737                                         //      $( "#gitlocal-browser-dialog" ).dialog("destroy").remove();
738                                                 console.log($("#gitlocal-browser-dialog").dialog( "widget" ));
739                                                 $("#gitlocal-browser-dialog").dialog( "open" );
740                                                 if ($("#gitlocal-browser-dialog").dialog( "isOpen" )===true) {
741                                                         console.log("gitlocal dialog box is now open"); 
742                                                 }
743                                                 $("#gitlocal-browser-dialog").show();
744                                                 //false
745                                         }
746                                         */
747                                })
748                                 .fail(function(err) {
749                                          RED.notify("Failed to get flows.");
750                                 })
751                                  .always(function() {
752                                         console.log("Done displaying");
753                                 });
754         }
755
756         function  showFlowShareUsers(){
757                 var divStyle="<style>#data-container a { color: #067ab4; font-size: 0.75em;} #data-container a:hover { text-decoration: underline; padding: -15px -15px -15px 15px; } .header { height: 40px; border-bottom: 1px solid #EEE; background-color: #ffffff; height: 40px; -webkit-border-top-left-radius: 5px; -webkit-border-top-right-radius: 5px; -moz-border-radius-topleft: 5px; -moz-border-radius-topright: 5px; border-top-left-radius: 5px; border-top-right-radius: 5px; } .footer { height: 40px; background-color: whiteSmoke; border-top: 1px solid #DDD; -webkit-border-bottom-left-radius: 5px; -webkit-border-bottom-right-radius: 5px; -moz-border-radius-bottomleft: 5px; -moz-border-radius-bottomright: 5px; border-bottom-left-radius: 5px; border-bottom-right-radius: 5px; }</style>";
758                 $.get("/flowShareUsers")
759                         .done(function (data){
760                                         
761                                         var header="<div class='header'>List of Downloaded DG Flows</div>";
762                                         var html=  divStyle + header +  "<div id='data-container'>";
763                                         html+="<ul>";
764                                         if(data != null){
765                                                 var users=data.flowShareUsers;
766                                                 users.sort(function (a,b){
767                                                         if(a.name > b.name){
768                                                                 return 1;
769                                                         }else if(a.name <  b.name){
770                                                                 return -1;
771                                                         }else{  
772                                                                 return 0;
773                                                         }
774                                                 });
775                                                 for(var i=0;users != null && i<users.length;i++){
776                                                         html+="<li><a href=\"#\" onclick=\"showFlowFiles('" + users[i].rootDir + "')\">" + users[i].name + "</a></li>";
777                                                 }
778                                         }
779                                         html+="</ul>";
780                                         html+="</div>";
781                                         $( "#dgflow-browser-dialog" ).dialog({
782                                         title: "Downloaded DG Flows Browser",
783                                         modal: true,
784                                         autoOpen: true,
785                                         width: 530,
786                                         height: 530,
787                                         buttons: [
788                                                 {
789                                                         text: "Close",
790                                                         click: function() {
791                                                                 $( this ).dialog( "close" );
792                                                                 //$(this).dialog('destroy').remove();
793                                                         }
794                                                 }
795                                                 ]
796                                         }).html(html);
797                                         $("#dgflow-browser-dialog").show();
798                                         /*
799                                         if ($("#dgflow-browser-dialog").dialog( "isOpen" )===true) {
800                                                 console.log("dgflow dialog box is open");       
801                                                 //true
802                                         } else {
803                                                 console.log("dgflow dialog box is not open");   
804                                                 $("#dgflow-browser-dialog").dialog( "open" );
805                                                 $("#dgflow-browser-dialog").show();
806                                                 //false
807                                         }
808                                         */
809                                })
810                                 .fail(function(err) {
811                                          RED.notify("Failed to get users.");
812                                 })
813                                  .always(function() {
814                                 });
815         }
816
817 /*      function  showFlowShareUsers(){
818                 var divStyle="<style>#data-container a { color: #067ab4; font-size: 0.75em;} #data-container a:hover { text-decoration: underline; padding: -15px -15px -15px 15px; } .header { height: 40px; border-bottom: 1px solid #EEE; background-color: #ffffff; height: 40px; -webkit-border-top-left-radius: 5px; -webkit-border-top-right-radius: 5px; -moz-border-radius-topleft: 5px; -moz-border-radius-topright: 5px; border-top-left-radius: 5px; border-top-right-radius: 5px; } .footer { height: 40px; background-color: whiteSmoke; border-top: 1px solid #DDD; -webkit-border-bottom-left-radius: 5px; -webkit-border-bottom-right-radius: 5px; -moz-border-radius-bottomleft: 5px; -moz-border-radius-bottomright: 5px; border-bottom-left-radius: 5px; border-bottom-right-radius: 5px; }</style>";
819                 $.get( "/flowShareUsers")
820                                .done(function( data ) {
821                                         
822                                         var header="<div class='header'>List of Downloaded DG Flows</div>";
823                                         var html=  divStyle + header +  "<div id='data-container'>";
824                                         html+="<ul>";
825                                         if(data != null){
826                                                 var users=data.flowShareUsers;
827                                                 users.sort(function (a,b){
828                                                         if(a.name > b.name){
829                                                                 return 1;
830                                                         }else if(a.name <  b.name){
831                                                                 return -1;
832                                                         }else{  
833                                                                 return 0;
834                                                         }
835                                                 });
836                                                 for(var i=0;users != null && i<users.length;i++){
837                                                         html+="<li><a href=\"#\" onclick=\"showFlowFiles('" + users[i].rootDir + "')\">" + users[i].name + "</a></li>";
838                                                 }
839                                         }
840                                         html+="</ul>";
841                                         html+="</div>";
842                                         $( "#dgflow-browser-dialog" ).dialog({
843                                         title: "Downloaded DG Flows Browser",
844                                         modal: true,
845                                         autoOpen: true,
846                                         width: 530,
847                                         height: 530,
848                                         buttons: [
849                                                 {
850                                                         text: "Close",
851                                                         click: function() {
852                                                                 //$( this ).dialog( "close" );
853                                                                 $(this).dialog('destroy').remove();
854                                                         }
855                                                 }
856                                                 ]
857                                         }).html(html);
858                                         //$("#dgflow-browser-dialog").show();
859                                         $( "#dgflow-browser-dialog" ).dialog( "open" );
860                                })
861                                 .fail(function(err) {
862                                          RED.notify("Failed to get users.");
863                                 })
864                                  .always(function() {
865                                 });
866         }
867         */
868
869
870 function detectLoopInFlow(){
871                 var errList = [];
872                 var activeWorkspace=RED.view.getWorkspace();
873                 var nSet=[];
874                 
875                 RED.nodes.eachNode(function(n) {
876                         if (n.z == activeWorkspace) {
877                                 nSet.push({n:n});
878                         }
879                 });
880
881                 var nodeSet = RED.nodes.createExportableNodeSet(nSet);
882
883                 var isLoopDetected = false;     
884                 var dgStartNode = getDgStartNode(nodeSet);
885                 if(dgStartNode == null || dgStartNode == undefined) {
886                         console.log("dgstart node not linked.");
887                         return null;
888                 }
889
890                 var wires = dgStartNode.wires;
891                 var nodesInPath = {};
892                 var dgStartNodeId = dgStartNode.id;
893                 if(wires != null && wires != undefined && wires[0] != undefined){
894                         for(var k=0;k<wires[0].length;k++){
895                                 var val = wires[0][k];
896                                 nodesInPath[dgStartNodeId + "->" + val] = "";
897                         }
898                 }else{
899                                 nodesInPath[dgStartNodeId + "->" + ""] = "";
900                 }
901                         
902                 var loopDetectedObj = {};
903                 /* the nodes will not be in order so will need to loop thru again */
904         for(var m=0;nodeSet != null && m<nodeSet.length;m++){
905                 for(var i=0;nodeSet != null && i<nodeSet.length;i++){
906                         var link=nodeSet[i].id;
907                         //console.log("NAME:" + nodeSet[i].name + ":" + link);
908                         if(link == dgStartNodeId) continue;
909                         var wires = nodeSet[i].wires;
910                         //console.log("link:" + link);
911                         var delKeys = [];
912                         if(wires != null && wires != undefined && wires[0] != undefined){
913                                 for(var k=0;k<wires[0].length;k++){
914                                         var val = (wires[0])[k];
915                                         var keys = Object.keys(nodesInPath);
916                                         //console.log("keys:" + keys);
917                                         for (var j=0;j<keys.length;j++){
918                                                 //console.log("key:" + keys[j]);
919                                                 //console.log("val:" + val);
920                                                 var index = keys[j].indexOf("->" + link);
921                                                 var lastIndex = keys[j].lastIndexOf("->");
922                                                 if(index != -1 && index == lastIndex){
923                                                         //delete nodesInPath[key];
924                                                         var previousNodeId = keys[j].substr(lastIndex +2);
925                                                         var indexOfArrow = -1;
926                                                         if(previousNodeId != ""){
927                                                                 indexOfArrow = previousNodeId.indexOf("->");
928                                                         }
929                                                         if(previousNodeId != null && indexOfArrow != -1){
930                                                                 previousNodeId = previousNodeId.substr(0,indexOfArrow);
931                                                         }       
932                                                         nodesInPath[keys[j] + "->" + val] = "";
933                                                         //console.log("keys[j]:" + keys[j]);
934                                                         delKeys.push(keys[j]);
935                                                         var prevNodeIdIndex = keys[j].indexOf("->" + previousNodeId);
936                                                         var priorOccurence = keys[j].indexOf(val + "->");
937                                                         if(priorOccurence != -1 && priorOccurence<prevNodeIdIndex){
938                                                                 //console.log("previousNodeId:" + previousNodeId);
939                                                                 //console.log("val:" + val);
940                                                                 var n1 = getNode(nodeSet,previousNodeId);
941                                                                 var n2 = getNode(nodeSet,val);
942                                                                 //console.log("loop detected for node " + n1.name + " and " + n2.name); 
943                                                                 loopDetectedObj[n1.name + "->" + n2.name] ="looped";
944                                                                 console.dir(loopDetectedObj);
945                                                                 errList.push("Loop detected between " + n1.name + " and " + n2.name);
946                                                                 isLoopDetected = true;
947                                                         }               
948                                                 } 
949                                         }
950                                 }
951                         }
952                         for(var l=0;delKeys != null && l<delKeys.length;l++){
953                                 delete nodesInPath[delKeys[l]];
954                         }
955                 }
956
957
958         }       
959         /*
960         if(loopDetectedObj != null ){ 
961                 var msg = "";
962                 for(var key in loopDetectedObj){
963                         if(loopDetectedObj.hasOwnProperty(key)) {
964                                 console.log("Loop detected  " + key);
965                                 msg += "<strong>Loop detected for:" + key + "</strong><br>";
966                         }
967                 }
968                 if(msg != ""){
969                         isLoopDetected = true;
970                         //RED.notify(msg);
971                 }
972         }       
973         */
974         //images/page-loading.gif
975                 return errList;
976 }
977
978 function showLoopDetectionBox(){
979         $(function() {
980         var htmlStr="<div id='loop-box-div' style='width:375;height:225'><p>Loop detection in Progress ...</p><img src='images/page-loading.gif'></div>"
981         $("#loop-detection-dialog").dialog({
982                 modal:true,     
983                 autoOpen :true,
984                 title: "DG Flow Loop Detection",
985                 width: 400,
986                 height: 250,
987                 minWidth : 400, 
988                 minHeight :200, 
989                 }).html(htmlStr);
990                 if($("#loop-detection-dialog").dialog("isOpen") == true){
991                         var errList = detectLoopInFlow();
992                         var errList=[];
993                         if(errList == null){
994                                 $("#loop-detection-dialog").dialog("close");
995                         }
996                         var msgHtml = "";
997                         for(var i=0;errList != null && i<errList.length;i++){
998                                 msgHtml += "<p>" + errList[i] + "</p>";
999                         }
1000                         if(msgHtml == ""){
1001                                 $("loop-box-div").html("<p>SUCCESS. No Loop detected.</p>");
1002                         }else{
1003                                 $("loop-box-div").html(msgHtml);
1004                         }
1005                 }
1006         });
1007         
1008 }
1009
1010 function showSelectedTabs(){
1011         var tabSheets = [];
1012         var beforeTabsOrder=[];
1013         $(".red-ui-tabs li a").each(function(i){
1014                 var id=$(this).attr("href").replace('#','');
1015                 var title=$(this).attr("title");
1016                 var isVisible = $(this).parent().is(":visible"); 
1017                 if(title != 'info'){
1018                         tabSheets.push({"id" : id ,"title":title,"module":"NOT_SET","version" : "NOT_SET","rpc":"NOT_SET","isVisible":isVisible});
1019                         beforeTabsOrder.push(id);
1020                 }
1021         });
1022
1023         RED.nodes.eachNode(function(n) {
1024                 if(n.type == 'service-logic'){
1025                         var id = n.z;
1026                         var module = n.module;
1027                         tabSheets.forEach(function(tab){
1028                                 if(tab.id == id){
1029                                         tab.module=module;
1030                                         tab.version=n.version;
1031                                 }       
1032                         });
1033                 }else if(n.type == 'method'){
1034                         var id = n.z;
1035                         tabSheets.forEach(function(tab){
1036                                 if(tab.id == id){
1037                                         var rpc=getAttributeValue(n.xml,"rpc");
1038                                         tab.rpc=rpc;
1039                                 }       
1040                         });
1041                 }
1042         });
1043         //console.dir(tabSheets);
1044         var htmlStr = getHtmlStr(tabSheets);
1045         $("#filter-tabs-dialog").dialog({
1046                 modal:true,     
1047                 title: "DG Builder Tabs",
1048                 width: 1200,
1049                 height: 750,
1050                 minWidth : 600, 
1051                 minHeight :450, 
1052                 }).html(htmlStr);
1053 /* This code allows for the drag-drop of the rows in the table */
1054         var fixHelperModified = function(e, tr) {
1055                 var $originals = tr.children();
1056                 var $helper = tr.clone();
1057                 $helper.children().each(function(index) {
1058                 $(this).width($originals.eq(index).width())
1059         });
1060         return $helper;
1061         },
1062         updateIndex = function(e, ui) {
1063                 var afterTabsOrder=[];
1064                 $('td.index', ui.item.parent()).each(function (i) {
1065                         $(this).html(i + 1);
1066                 });
1067                 //RE-ARRANGE the tabs
1068                 var ul = $("#workspace-tabs");
1069                 $("#ftab02 tr td:nth-child(1)").each(function(i){
1070                         var idStr = $(this).prop("id").replace("tab-td_","");
1071                         afterTabsOrder.push(idStr);
1072                         link = ul.find("a[href='#"+ idStr+"']");
1073                         li = link.parent();
1074                         //li.remove();
1075                         firstTab = $("#workspace-tabs li:first-child");
1076                         lastTab = $("#workspace-tabs li:last-child");
1077                         li.insertAfter(lastTab);
1078                         //console.log( idStr);
1079                 });
1080                 var beforeTabsStr = beforeTabsOrder.join(",");
1081                 var afterTabsStr = afterTabsOrder.join(",");
1082                 //console.log("beforeTabsStr:" +beforeTabsStr);
1083                 //console.log("afterTabsStr:" +afterTabsStr);
1084                 if(beforeTabsStr !== afterTabsStr){
1085                         //activate only when order has changed
1086                         //activate the deploy button
1087                         RED.view.dirty(true);
1088                         $("#btn-deploy").removeClass("disabled");
1089                 }
1090         };
1091
1092         $("#ftab02 tbody").sortable({
1093         helper: fixHelperModified,
1094         stop: updateIndex
1095         }).disableSelection();
1096
1097 }
1098
1099 function getHtmlStr(rows){
1100         var styleStr = "<style> " + 
1101                         "table#ftab02 { width:100%; } \n" +
1102                                 "table#ftab02 th,table#ftab02 td { border: 1px solid black; border-collapse: collapse; } \n" +
1103                                 /*"table, th, td { border: 1px solid #65a9d7; border-collapse: collapse; } \n" +*/
1104                                 "table#ftab02 th,table#ftab02 td { padding: 5px; text-align: left; } \n" +
1105                                 "table#ftab02 tr:nth-child(even) { background-color: #eee; }\n" +
1106                                 "table#ftab02 tr:nth-child(odd) { background-color:#fff; }\n" +
1107                                 "table#ftab02 th        { background-color: #65a9d7; color: white; }\n" +
1108                                 "table#ftab02 a { color: #337ab7; }\n" +
1109                                 "table#ftab02 a:link { color: #65a9d7; }\n" +
1110                                 "table#ftab02 a:visited { color: #636; }\n" + 
1111                                 "table#ftab02 a:hover { color: #3366CC; cursor: pointer }\n" + 
1112                                 "table#ftab02 a:active { color: #65a9d7 }\n" +
1113                                 "</style>";
1114                         if(rows != null && rows != undefined){
1115                                 //var alertDialog = '<div id="confdialog"></div>';
1116                                 //htmlStr= alertDialog +  "<div style='width:1050;height:650'>" + styleStr;
1117                                 var alertDialog = '<div id="tabAlertDialog"></div>';
1118                                 htmlStr= alertDialog +  "<div id='tabs-div' style='width:1050;height:650'>" + styleStr;
1119                                 htmlStr += "<table id='ftab02' >";
1120                                 htmlStr += "<tr>";
1121                                 htmlStr += "<th class='index'>No.</th>" ;
1122                                 htmlStr += "<th>Tab Title</th>" ;
1123                                 htmlStr += "<th>Module</th>" ;
1124                                 htmlStr += "<th>RPC</th>" ;
1125                                 htmlStr += "<th>Version</th>" ;
1126                                 htmlStr += "<th>Rename</th>" ;
1127                                 htmlStr += "<th>Delete</th>" ;
1128                                 htmlStr += "</tr>";
1129                                 htmlStr += "<tbody>";
1130                                 if(rows != null && rows.length == 0){
1131                                         htmlStr += "<tr>";
1132                                         htmlStr += "<td><b>No rows found</b></td>";
1133                                         htmlStr += "</tr></table></div>";
1134                                         return htmlStr;
1135                                 }
1136                                 for(var i=0;i<rows.length;i++){
1137                                         var row = rows[i];
1138                                         var title = row.title;
1139                                         var _module = row.module;
1140                                         var version = row.version;
1141                                         var rpc = row.rpc;
1142                                         var idVal = row.id;
1143                                         var isVisible = row.isVisible;
1144                                         htmlStr += "<tr id='tab-tr_" + idVal + "'>";
1145                                         //htmlStr += "<td id=" + "'tab-td_" + idVal  + "' ><a href='javascript:activateClickedTab(\"" + idVal + "\")'>" + (i+1) + "</a></td>";
1146                                         htmlStr += "<td class='index' id=" + "'tab-td_" + idVal  + "' >" + (i+1) + "</td>";
1147                                         htmlStr += "<td><a href='javascript:activateClickedTab(\"" + idVal + "\")'>" + title + "</a></td>";
1148                                         htmlStr += "<td>" + _module + "</td>";
1149                                         htmlStr += "<td>" + rpc + "</td>";
1150                                         htmlStr += "<td>" + version + "</td>";
1151                                         //htmlStr += "<td><a href='javascript:deleteOrRenameTab(\"" + idVal + "\")'>Delete/Rename</a></td>";
1152                                         htmlStr += "<td><input type='button' onclick='renameSelectedTab(\"" + idVal + "\",\"" + title + "\",\"" +  _module + "\",\"" + rpc + "\",\"" + version + "\")' value='Rename'></td>";
1153                                         if(rows.length == 1){
1154                                                 htmlStr += "<td><input type='button' disabled='1' onclick='deleteSelectedTab(\"" + idVal + "\",\"" + title + "\",\"" +  _module + "\",\"" + rpc + "\",\"" + version + "\")' value='Delete'></td>";
1155                                         }else{
1156                                                 htmlStr += "<td><input type='button'  onclick='deleteSelectedTab(\"" + idVal + "\",\"" + title + "\",\"" +  _module + "\",\"" + rpc + "\",\"" + version + "\")' value='Delete'></td>";
1157                                         }
1158                                         /*
1159                                         if(isVisible){
1160                                                 htmlStr += "<td><input type='checkbox' onclick=\"showOrHideTab(this,'" + idVal + "')\" checked='true'></td>";
1161                                         }else{
1162                                                 htmlStr += "<td><input type='checkbox' onclick=\"showOrHideTab(this,'" + idVal + "')\"></td>";
1163                                         }
1164                                         */
1165                                         htmlStr += "</tr>";
1166                                 }
1167                                 htmlStr += "</tbody>";
1168                                 htmlStr += "</table>";
1169                                 htmlStr += "</div>";
1170                         }
1171         return htmlStr;
1172 }
1173 /*
1174 Added this logic because , when the configuration item is choosen in the menu the other dialog boxes were not poping up
1175 */
1176 (function(){
1177         //var msecs1= Date.now();
1178                 $( "#gitlocal-browser-dialog" ).dialog();
1179                 $( "#gitlocal-browser-dialog" ).dialog("close");
1180                 $( "#dgflow-browser-dialog" ).dialog();
1181                 $( "#dgflow-browser-dialog" ).dialog("close");
1182                 $( "#update-password-dialog" ).dialog();
1183                 $( "#update-password-dialog" ).dialog("close");
1184                 $( "#codecloud-browser-dialog" ).dialog();
1185                 $( "#codecloud-browser-dialog" ).dialog("close");
1186                 $( "#update-configuration-dialog" ).dialog();
1187                 $( "#update-configuration-dialog" ).dialog("close");
1188                 $( "#gitcommands-dialog" ).dialog();
1189                 $( "#gitcommands-dialog" ).dialog("close");
1190                 $("#filter-tabs-dialog").dialog();
1191                 $("#filter-tabs-dialog").dialog("close");
1192                 $("#loop-detection-dialog").dialog();
1193                 $("#loop-detection-dialog").dialog("close");
1194                 $("#dgstart-generate-xml-dialog").dialog();
1195                 $("#dgstart-generate-xml-dialog").dialog("close");
1196                 $("#xmldialog").dialog();
1197                 $("#xmldialog").dialog("close");
1198                 $("#upload-xml-status-dialog").dialog();
1199                 $("#upload-xml-status-dialog").dialog("close");
1200                 $("#flow-design-err-dialog").dialog();
1201                 $("#flow-design-err-dialog").dialog("close");
1202                 $("#sli-values-dialog").dialog();
1203                 $("#sli-values-dialog").dialog("close");
1204                 $("#comments-dialog").dialog();
1205                 $("#comments-dialog").dialog("close");
1206                 $("#show-errors-dialog").dialog();
1207                 $("#show-errors-dialog").dialog("close");
1208                 $("#dgnumber-find-dialog").dialog();
1209                 $("#dgnumber-find-dialog").dialog("close");
1210                 $("#search-text-dialog").dialog();
1211                 $("#search-text-dialog").dialog("close");
1212                 $("#yang-upload-dialog").dialog();
1213                 $("#yang-upload-dialog").dialog("close");
1214                 $("#yang-modules-browser-dialog").dialog();
1215                 $("#yang-modules-browser-dialog").dialog("close");
1216                 $("#list-yang-browser-dialog").dialog();
1217                 $("#list-yang-browser-dialog").dialog("close");
1218                 $("#request-input-dialog").dialog();
1219                 $("#request-input-dialog").dialog("close");
1220                 //var msecs2= Date.now();
1221                 //console.log("Time taken for dialog boxes:" + (msecs2 - msecs1));
1222 })();
1223
1224         function updateConfiguration(){
1225                 //console.log("in updateConfiguration");
1226                 $.get("/getCurrentSettings",function (data){
1227                 var dbHost = data.dbHost;
1228                 var dbPort = data.dbPort;
1229                 var dbName = data.dbName;
1230                 var dbUser = data.dbUser;
1231                 var dbPassword = data.dbPassword;
1232                 var gitLocalRepository = data.gitLocalRepository;
1233                 var performGitPull = data.performGitPull;
1234
1235                 if(dbHost == undefined) dbHost="";
1236                 if(dbPort == undefined) dbPort="";
1237                 if(dbName == undefined) dbName="";
1238                 if(dbUser == undefined) dbUser="";
1239                 if(dbPassword == undefined) dbPassword="";
1240                 if(gitLocalRepository == undefined) gitLocalRepository="";
1241                 if(performGitPull  == undefined || performGitPull == null) performGitPull="N";
1242
1243                 var divStyle="border: 1px solid #a1a1a1; padding: 10px 40px; background: #dddddd; width: 500px; border-radius: 25px;";
1244                 //var divStyle="border: 2px solid #a1a1a1; padding: 10px 40px; background: #99CCFF; width: 400px; border-radius: 25px;";
1245         
1246
1247                    var  html = "<div>";
1248                         html += "<script>function changeType(obj,targetId){if( obj.checked== true){$('#' + targetId).prop('type','password');}else{$('#'+ targetId).prop('type','text');}} function changeTitle(){ document.getElementById(\"gitLocalRepository\").title=document.getElementById(\"gitLocalRepository\").value;}</script>";
1249                         html += "<div style='" + divStyle + "' >";
1250                         html += "<table border='0' cellpadding='5' >";
1251                         html += "<tr>";
1252                         html += "<td style='font-size:12px;align:center'><b>DB Host IP</b></td>";
1253                         html += "<td><input  style='align:center;font-size:11px;font-weight:bold' id='dbhost' name='dbhost' type='text' value='" + dbHost + "'></td>";
1254                         html += "</tr>";
1255                         html += "<tr>";
1256                         html += "<td style='font-size:12px;align:center'><b>DB Port</b></td>";
1257                         html += "<td><input style='align:center;font-size:11px;font-weight:bold' id='dbport' name='dbport' type='text' value='" + dbPort + "'></td>";
1258                         html += "</tr>";
1259                         html += "<tr>";
1260                         html += "<td style='font-size:12px;align:center'><b>DB Name</b></td>";
1261                         html += "<td><input style='align:center;font-size:11px;font-weight:bold' id='dbname' name='dbname' type='text' value='" + dbName + "'></td>";
1262                         html += "</tr>";
1263                         html += "<tr>";
1264                         html += "<td style='font-size:12px;align:center'><b>DB UserName</b></td>";
1265                         html += "<td><input style='align:center;font-size:11px;font-weight:bold' id='dbuser' name='dbuser' type='password' value='" + dbUser + "'></td>";
1266                         html += "<td><input style='background:background:white;width:20px;height:20px' type='checkbox' checked value='1' onclick=\"changeType(this,'dbuser')\">Hide</td>";
1267                         html += "</tr>";
1268                         html += "<tr>";
1269                         html += "<td style='font-size:12px;align:center'><b>DB Password</b></td>";
1270                         html += "<td><input style='align:center;font-size:11px;font-weight:bold' id='dbpassword' name='dbpassword' type='password' value='" + dbPassword + "'></td>";
1271                         html += "<td><input style='background:background:white;width:20px;height:20px' type='checkbox' checked value='1' onclick=\"changeType(this,'dbpassword')\">Hide</td>";
1272                         html += "</tr>";
1273                         html += "</table>";
1274                         html += "</div>";
1275                         html += "<div style='fill:both;clear:both'></div><br>";
1276         
1277                         html += "<div style='" + divStyle + "' >";
1278                         html += "<table border='0' cellpadding='5' >";
1279                         html += "<tr>";
1280                         html += "<td style='font-size:12px;align:center'><b>Git Local Repository Path</b></td>";
1281                         html += "<td><textarea style='align:center;font-size:14px;' cols='50' rows='4' id='gitLocalRepository' name='gitLocalRepository' onkeyup='changeTitle()' title='" + gitLocalRepository + "'>" + gitLocalRepository + "</textarea></td>";
1282                         html += "</tr>";
1283                         html += "</table>";
1284                         html += "<table border='0' cellpadding='5' >";
1285                         html += "<tr>";
1286                         if(performGitPull == "N"){
1287                                 html += "<td style='align:center;'><input style='color:blue;width:20px;height:20px;' id='performGitPull' type='checkbox' value='Y'>Perform Git Pull in Local Git Repository prior to import</td>";
1288                         }else{
1289                                 html += "<td style='align:center;'><input style='color:blue;width:20px;height:20px;' id='performGitPull' type='checkbox' value='Y' checked>Perform Git Pull in Local Git Repository prior to import</td>";
1290                         }
1291                         html += "</tr>";
1292                         html += "</table>";
1293                         html += "</div>";
1294                         html += "</div>";
1295                         //console.log("html:" + html);
1296                 $( "#update-configuration-dialog" ).dialog({
1297                         title: "Configuration",
1298                         modal: true,
1299                         autoOpen: true,
1300                         width: 630,
1301                         height: 630,
1302                         buttons: [
1303                                 {
1304                                 text: "Save",
1305                                 click: function() {
1306                                         var newDBHost = $("#dbhost").val().trim();
1307                                         var newDBPort = $("#dbport").val().trim();
1308                                         var newDBName = $("#dbname").val().trim();
1309                                         var newDBUser = $("#dbuser").val().trim();
1310                                         var newDBPassword = $("#dbpassword").val().trim();
1311                                         var newGitLocalRepository = $("#gitLocalRepository").val().trim();
1312                                         var isPerformGitPullChecked = $('#performGitPull').is(':checked');
1313                                         var newPerformGitPull = "N";
1314                                         if(isPerformGitPullChecked){
1315                                                 newPerformGitPull = "Y";
1316                                         }
1317                                         if(newDBHost == ""){
1318                                                 RED.notify("Error: DB Host is required.");              
1319                                                 $("#dbhost").focus();
1320                                                 return;
1321                                         }else if(newDBPort == ""){
1322                                                 RED.notify("Error: DB Port is required.");              
1323                                                 $("#dbport").focus();
1324                                                 return;
1325                                         }else if(newDBName == ""){
1326                                                 RED.notify("Error: DB Name is required.");              
1327                                                 $("#dbname").focus();
1328                                                 return;
1329                                         }else if(newDBUser == ""){
1330                                                 RED.notify("Error: DB User is required.");              
1331                                                 $("#dbuser").focus();
1332                                                 return;
1333                                         }else if(newDBPassword == ""){
1334                                                 RED.notify("Error: DB Password is required.");          
1335                                                 $("#dbpassword").focus();
1336                                                 return;
1337                                         }else{ 
1338                                                 console.log("newGitLocalRepository:" + newGitLocalRepository);
1339                                                 var reqData= {"dbHost":newDBHost,
1340                                                                 "dbPort" : newDBPort,
1341                                                                 "dbName" : newDBName,
1342                                                                 "dbUser" : newDBUser,
1343                                                                 "dbPassword" : newDBPassword,
1344                                                                 "gitLocalRepository" : newGitLocalRepository, 
1345                                                                 "performGitPull" : newPerformGitPull 
1346                                                              };
1347                                                  $.post( "/updateConfiguration",reqData )
1348                                                 .done(function( data ) {
1349                                                         RED.notify("Configuration updated successfully"); 
1350                                                         //loadSettings();
1351                                                         //RED.comms.connect();
1352                                                         //$( "#update-configuration-dialog" ).dialog('close');
1353                                                         $("#update-configuration-dialog").dialog("close");
1354                                                         //location.reload();
1355                                                                 
1356                                                 })
1357                                                 .fail(function(err) {
1358                                                         console.log( "error" + err );
1359                                                         RED.notify("Failed to update the Configuration.");
1360                                                 })
1361                                                 .always(function() {
1362                                                 });
1363                                         }
1364                                    }
1365                                 },
1366                                 {
1367                                         text: "Cancel",
1368                                         click: function() {
1369                                                 $( this ).dialog( "close" );
1370                                         }
1371                                 }
1372                         ]
1373                 }).html(html);
1374                 //$("#update-configuration-dialog").show();
1375                 $("#gitLocalRepository").css({"width" : 300});
1376
1377                 });
1378         }
1379
1380         function updatePassword(){
1381                 var html="<div>";
1382                         html += "<div><span><b>New Password</b></span><br>";
1383                         html += "<input id='passwd1' name='passwd1' type='password' value=''>";
1384                         html += "</div>";
1385                         html += "<div><span><b>Confirm Password</b></span><br>";
1386                         html += "<input id='passwd2' name='passwd2' type='password' value=''>";
1387                         html += "</div>";
1388                 $( "#update-password-dialog" ).dialog({
1389                         title: "Update Password",
1390                         modal: true,
1391                         autoOpen: true,
1392                         width: 530,
1393                         height: 230,
1394                         buttons: [
1395                                 {
1396                                 text: "Update Password",
1397                                 click: function() {
1398                                         var passwd1 = $("#passwd1").val().trim();
1399                                         var passwd2 = $("#passwd2").val().trim();
1400                                         if((passwd1 != passwd2) || (passwd1 == "" || passwd2 == "")){
1401                                                 RED.notify("Error:Passwords entered must be same and must be populated.");              
1402                                                 return;
1403                                         }else{ 
1404                                                 var reqData= {"password":passwd1};
1405                                                  $.post( "/updatePassword",reqData )
1406                                                 .done(function( data ) {
1407                                                         RED.notify("Password updated successfully"); 
1408                                                         //loadSettings();
1409                                                         $( "#update-password-dialog" ).dialog('close');
1410                                                 })
1411                                                 .fail(function(err) {
1412                                                         console.log( "error" + err );
1413                                                         RED.notify("Failed to update the password.");
1414                                                 })
1415                                                 .always(function() {
1416                                                 });
1417                                         }
1418                                    }
1419                                 },
1420                                 {
1421                                         text: "Cancel",
1422                                         click: function() {
1423                                                 $( this ).dialog( "close" );
1424                                         }
1425                                 }
1426                         ]
1427                 }).html(html);
1428                 $("#update-password-dialog").show();
1429
1430         }
1431
1432         function  showAvailableYangModules(){
1433                 availableYangModules=[];
1434                 var divStyle="<style>#yang-modules-data-container a { color: #067ab4; font-size: 0.75em;} #yang-modules-data-container a:hover { text-decoration: underline; padding: -15px -15px -15px 15px; } .header { height: 40px; border-bottom: 1px solid #EEE; background-color: #ffffff; height: 40px; -webkit-border-top-left-radius: 5px; -webkit-border-top-right-radius: 5px; -moz-border-radius-topleft: 5px; -moz-border-radius-topright: 5px; border-top-left-radius: 5px; border-top-right-radius: 5px; } .footer { height: 40px; background-color: whiteSmoke; border-top: 1px solid #DDD; -webkit-border-bottom-left-radius: 5px; -webkit-border-bottom-right-radius: 5px; -moz-border-radius-bottomleft: 5px; -moz-border-radius-bottomright: 5px; border-bottom-left-radius: 5px; border-bottom-right-radius: 5px; } table#yang-list-table { width:100%; } table#yang-list-table th,table#yang-list-table td { border: 1px solid black; border-collapse: collapse; } table#yang-list-table th,table#yang-list-table td { padding: 5px; text-align: left; } table#yang-list-table tr:nth-child(even) { background-color: #eee; } table#yang-list-table tr:nth-child(odd) { background-color:#fff; } table#yang-list-table th        { background-color: #65a9d7; color: white; } table#yang-list-table a { color: #337ab7; } table#yang-list-table a:link { color: #65a9d7; } table#yang-list-table a:visited { color: #636; } table#yang-list-table a:hover { color: #3366CC; cursor: pointer } table#yang-list-table a:active { color: #65a9d7 }</style>";
1435                 $.get( "/listAvailableModules")
1436                                .done(function( data ) {
1437                                         var header="<div class='header'>List of Available Yang Modules</div>";
1438                                         header += "<div><p><i>Check the modules that you want to load and click on the Load button.</i></p></div>";     
1439                                         //header += "<div><input id='yangModuleFilterBoxId' type='text' onkeyup='filterYangModules(this.value)'></div>";
1440                                         var html=  divStyle + header +  "<div id='yang-modules-data-container'>";
1441                                         html+="<table id='yang-list-table'  border=1>";
1442                                         html+="<tr>";
1443                                         html+="<th>#</th>";
1444                                         html+="<th>Load</th>";
1445                                         html+="<th>Module</th>";
1446                                         html+="</tr>";
1447                                         if(data != null){
1448                                                 var files=data.files;
1449                                                 availableYangModules=files;
1450                                                 //console.dir(files);
1451                                                 files.sort(function (a,b){
1452                                                         if(a > b){
1453                                                                 return 1;
1454                                                         }else if(a <  b){
1455                                                                 return -1;
1456                                                         }else{  
1457                                                                 return 0;
1458                                                         }
1459                                                 });
1460                                                 var count=1;
1461                                                 for(var i=0;files != null && i<files.length;i++){
1462                                                         var val = files[i].replace(/:.*/,"");
1463                                                         if(files[i].indexOf(":checked") != -1){
1464                                                                 html+="<tr><td>" + count + "</td><td><input type='checkbox' checked value='" + val + "'></td><td>" + val + "</td></tr>";
1465                                                         }else{
1466                                                                 html+="<tr><td>" + count + "</td><td><input type='checkbox' value='" + val + "'></td><td>" + val + "</td></tr>";
1467                                                         }
1468                                                         count++;
1469                                                 }
1470                                         }
1471                                         html+="</table>";
1472                                         html+="</div>";
1473                                         $( "#yang-modules-browser-dialog" ).dialog({
1474                                         title: "Available Yang Modules",
1475                                         modal: true,
1476                                         autoOpen: true,
1477                                         width: 830,
1478                                         height: 630,
1479                                         buttons: [
1480                                                 {
1481                                                         text: "Load",
1482                                                         click: function() {
1483                                                                 var allVals = [];
1484                                                                 function getValuesForSelected() {         
1485                                                                         $('#yang-modules-data-container :checked').each(function() {
1486                                                                                 allVals.push($(this).val());
1487                                                                         });
1488                                                                         return allVals;
1489                                                                 }
1490                                                                 var selectedModules = getValuesForSelected().toString();
1491                                                                 console.log(selectedModules);
1492                                                                 $.ajax({
1493                                                                         type: 'GET',
1494                                                                         /*contentType: "application/x-www-form-urlencoded",*/
1495                                                                         url: '/loadSelectedModules?selectedModules=' + selectedModules,
1496                                                                         success: function(data) {
1497                                                                                 RED.notify("Modules Loaded successfully"); 
1498                                                                                 //emptying existing g;obal variables
1499                                                                                 sliValuesObj = {};
1500                                                                                 rpcValues = {};
1501                                                                                 reqInputValues = {};
1502
1503                                                                                 if(data != undefined && data != null){
1504                                                                                         for(var i=0;i<data.sliValuesObj.length;i++){
1505                                                                                                 var moduleName = data.sliValuesObj[i].moduleName;
1506                                                                                                 sliValuesObj[moduleName] = data.sliValuesObj[i][moduleName + '_PROPS'];
1507                                                                                                 rpcValues[moduleName] = data.sliValuesObj[i][ moduleName +'_RPCS'];
1508                                                                                                 for(var k=0;rpcValues[moduleName] != undefined && k<rpcValues[moduleName].length;k++){
1509                                                                                                         var rpcName = rpcValues[moduleName][k];
1510                                                                                                         reqInputValues[moduleName + "_" + rpcName] = data.sliValuesObj[i][rpcName +"-input"];
1511                                                                                                         //console.dir(reqInputValues);
1512                                                                                                 }
1513                                                                                         }
1514                                                                                 }
1515                                                                                 $( "#yang-modules-browser-dialog" ).dialog('close');
1516                                                                                 console.log('success');
1517                                                                                 //console.log(JSON.stringify(data));                               
1518                                                                         },
1519                                                                         error: function(error) {
1520                                                                                 RED.notify("Failed to load modules.");
1521                                                                                 console.log("some error in fetching the notifications");
1522                                                                         }
1523                                                                 });     
1524                                                         }
1525                                                 },
1526                                                 {
1527                                                         text: "Close",
1528                                                         click: function() {
1529                                                                 $(this).dialog("close");
1530                                                         }
1531                                                 }
1532                                                 ]
1533                                         }).html(html);
1534                                         $("#yang-modules-browser-dialog").show();
1535                                })
1536                                 .fail(function(err) {
1537                                          RED.notify("Failed to get yang modules.");
1538                                 })
1539                                  .always(function() {
1540                                         console.log("Done displaying");
1541                                 });
1542         }
1543
1544
1545     $(function() {
1546         RED.menu.init({id:"btn-sidemenu",
1547             options: [
1548                 {id:"btn-sidebar",icon:"fa fa-columns",label:"Sidebar   (Ctrl+Space)",toggle:true,onselect:RED.sidebar.toggleSidebar},
1549                 null,
1550                 {id:"btn-configure-upload",icon:"fa fa-book",label:"Configuration",toggle:false,onselect:updateConfiguration},
1551                 null,
1552                 {id:"btn-manage-tabs",icon:"fa fa-info",label:"Manage Tabs",toggle:false,onselect:showSelectedTabs},
1553                 null,
1554                 {id:"btn-find-dgnumber",icon:"fa fa-info",label:"Search Text (Ctrl+[)",toggle:false,onselect:RED.view.showSearchTextDialog},
1555                 null,
1556                 {id:"btn-find-dgnumber",icon:"fa fa-info",label:"Find Node (Ctrl+B)",toggle:false,onselect:RED.view.showDgNumberDialog},
1557                 null,
1558                 /*{id:"btn-loop-detection",icon:"fa fa-info",label:"Loop Detection",toggle:true,onselect:performLoopDetection},
1559                null ,*/
1560                 {id:"btn-node-status",icon:"fa fa-info",label:"Node Status",toggle:true,onselect:toggleStatus},
1561                 null,
1562                 {id:"btn-node-dgnumber",icon:"fa fa-info",label:"Show Node Numbers",toggle:true,onselect:toggleDgNumberDisplay},
1563                 null,
1564                 {id:"btn-node-panel",icon:"fa fa-columns",label:"Node Palette (Ctrl+M)",toggle:true,onselect:toggleNodePaletteDisplay},
1565                 null,
1566                 {id:"btn-node-viewdgs",icon:"fa fa-info",label:"View All DG List",toggle:false,onselect:displayAllDGs},
1567                 null,
1568                 /*
1569                 {id:"btn-node-gitmenu",icon:"fa fa-info",label:"Git Commands",options: [
1570                     {id:"btn-node-gitcheckout",icon:"fa fa-info",label:"Git Checkout",onselect:showGitCheckoutDialog},
1571                     {id:"btn-node-gitpull",icon:"fa fa-info",label:"Git Pull",onselect:showGitPullDialog},
1572                     {id:"btn-node-gitstatus",icon:"fa fa-info",label:"Git Status",onselect:showGitStatusDialog}
1573                 ]},
1574                 null,
1575                 */
1576                 {id:"btn-import-menu",icon:"fa fa-sign-in",label:"Import...",options:[
1577                     /*{id:"btn-import-codecloud",icon:"fa fa-clipboard",label:"Code Cloud",onselect:showCodeCloudFlows},
1578                         */
1579                     {id:"btn-import-codecloud",icon:"fa fa-clipboard",label:"Git Local Repository",onselect:showGitLocalFlows},
1580                     {id:"btn-import-userflows",icon:"fa fa-clipboard",label:"Downloaded DG Flows...",onselect:showFlowShareUsers},
1581                     {id:"btn-import-clipboard",icon:"fa fa-clipboard",label:"Clipboard...",onselect:RED.view.showImportNodesDialog},
1582                     {id:"btn-import-library",icon:"fa fa-book",label:"Library",options:[]}
1583                 ]},
1584                 {id:"btn-export-menu",icon:"fa fa-sign-out",label:"Export...",disabled:true,options:[
1585                     {id:"btn-export-clipboard",icon:"fa fa-clipboard",label:"Clipboard...",disabled:true,onselect:RED.view.showExportNodesDialog},
1586                     {id:"btn-export-library",icon:"fa fa-book",label:"Library...",disabled:true,onselect:RED.view.showExportNodesLibraryDialog}
1587                 ]},
1588                 null,
1589                 {id:"btn-change-password",icon:"fa fa-columns",label:"Change Password",toggle:false,onselect:updatePassword},
1590                 null,
1591                 /*{id:"btn-config-nodes",icon:"fa fa-th-list",label:"Configuration nodes...",onselect:RED.sidebar.config.show},
1592                 null,*/
1593                 {id:"btn-workspace-menu",icon:"fa fa-th-large",label:"Workspaces",options:[
1594                     {id:"btn-workspace-add",icon:"fa fa-plus",label:"Add"},
1595                     {id:"btn-workspace-edit",icon:"fa fa-pencil",label:"Rename"},
1596                     {id:"btn-workspace-delete",icon:"fa fa-minus",label:"Delete"},
1597                     null
1598                 ]},
1599                 null,
1600                 {id:"btn-keyboard-shortcuts",icon:"fa fa-keyboard-o",label:"Keyboard Shortcuts",onselect:showHelp}
1601                 /*{id:"btn-help",icon:"fa fa-question",label:"Help...", href:"http://nodered.org/docs"}*/
1602             ]
1603         });
1604
1605         //Making default loop detection on and display check mark in the menu
1606         //$("#btn-loop-detection").addClass("active");
1607
1608         RED.keyboard.add(/* ? */ 191,{shift:true},function(){showHelp();d3.event.preventDefault();});
1609         loadSettings();
1610         RED.comms.connect();
1611     });
1612
1613     return {
1614     };
1615 })();