]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Open-ILS/web/js/ui/default/staff/reporter/template/app.js
LP2061136 - Stamping 1405 DB upgrade script
[working/Evergreen.git] / Open-ILS / web / js / ui / default / staff / reporter / template / app.js
1 /*
2  * Report template builder
3  */
4
5 angular.module('egReporter',
6     ['ngRoute', 'ui.bootstrap', 'egCoreMod', 'egUiMod', 'egGridMod', 'egReportMod', 'treeControl', 'ngToast'])
7
8 .config(['ngToastProvider', function(ngToastProvider) {
9   ngToastProvider.configure({
10     verticalPosition: 'bottom',
11     animation: 'fade'
12   });
13 }])
14
15 .config(function($routeProvider, $locationProvider, $compileProvider) {
16     $locationProvider.html5Mode(true);
17     $compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|mailto|blob):/); // grid export
18         
19     var resolver = {delay : function(egStartup) {return egStartup.go()}};
20
21     $routeProvider.when('/reporter/template/clone/:folder/:id', {
22         templateUrl: './reporter/t_edit_template',
23         controller: 'ReporterTemplateEdit',
24         resolve : resolver
25     });
26
27     $routeProvider.when('/reporter/legacy/template/clone/:folder/:id', {
28         templateUrl: './reporter/t_legacy',
29         controller: 'ReporterTemplateLegacy',
30         resolve : resolver
31     });
32
33     $routeProvider.when('/reporter/template/new/:folder', {
34         templateUrl: './reporter/t_edit_template',
35         controller: 'ReporterTemplateEdit',
36         resolve : resolver
37     });
38
39     $routeProvider.when('/reporter/legacy/main', {
40         templateUrl: './reporter/t_legacy',
41         controller: 'ReporterTemplateLegacy',
42         resolve : resolver
43     });
44
45     // default page
46     $routeProvider.otherwise({redirectTo : '/reporter/legacy/main'});
47 })
48
49 /**
50  * controller for legacy template stuff
51  */
52 .controller('ReporterTemplateLegacy',
53        ['$scope','$routeParams','$location','egCore',
54 function($scope , $routeParams , $location , egCore) {
55
56     var template_id = $routeParams.id;
57     var folder_id = $routeParams.folder;
58
59     $scope.rurl = '/reports/oils_rpt.xhtml?ses=' + egCore.auth.token();
60
61     if (folder_id) {
62         $scope.rurl = '/reports/oils_rpt_builder.xhtml?ses=' +
63                         egCore.auth.token() + '&folder=' + folder_id;
64
65         if (template_id) $scope.rurl += '&ct=' + template_id;
66     }
67
68 }])
69
70 /**
71  * Uber-controller for template editing
72  */
73 .controller('ReporterTemplateEdit',
74        ['$scope','$q','$routeParams','$location','$timeout','$window','egCore','$uibModal','egPromptDialog',
75         'egGridDataProvider','egReportTemplateSvc','$uibModal','egConfirmDialog','egSelectDialog','ngToast',
76 function($scope , $q , $routeParams , $location , $timeout , $window,  egCore , $uibModal , egPromptDialog ,
77          egGridDataProvider , egReportTemplateSvc , $uibModal , egConfirmDialog , egSelectDialog , ngToast) {
78
79     function values(o) { return Object.keys(o).map(function(k){return o[k]}) };
80
81     var template_id = $routeParams.id;
82     var folder_id = $routeParams.folder;
83
84     $scope.grid_display_fields_provider = egGridDataProvider.instance({
85         get : function (offset, count) {
86             return this.arrayNotifier(egReportTemplateSvc.display_fields, offset, count);
87         }
88     });
89     $scope.grid_filter_fields_provider = egGridDataProvider.instance({
90         get : function (offset, count) {
91             return this.arrayNotifier(egReportTemplateSvc.filter_fields, offset, count);
92         }
93     });
94
95     var dgrid = $scope.display_grid_controls = {};
96     var fgrid = $scope.filter_grid_controls = {};
97
98     var default_filter_obj = {
99         op : '=',
100         label     : egReportTemplateSvc.Filters['='].label
101     };
102
103     var default_transform_obj = {
104         transform : 'Bare',
105         label     : egReportTemplateSvc.Transforms.Bare.label,
106         aggregate : false
107     };
108
109     function mergePaths (items) {
110         var tree = {};
111
112         items.forEach(function (item) {
113             var t = tree;
114             var join_path = '';
115
116             var last_jtype = '';
117             item.path.forEach(function (p, i, a) {
118                 var alias; // unpredictable hashes are fine for intermediate tables
119
120                 if (i) { // not at the top of the tree
121                     if (i == 1) join_path = join_path.split('-')[0];
122
123                     // SQLBuilder relies on the first dash-separated component
124                     // of the join key to specify the column of left-hand relation
125                     // to join on; for has_many and might_have link types, we have to grab the
126                     // primary key of the left-hand table; otherwise, we can
127                     // just use the field/column name found in p.uplink.name.
128                     var uplink = (p.uplink.reltype == 'has_many' || p.uplink.reltype == 'might_have') ?
129                         egCore.idl.classes[p.from.split('.').slice(-1)[0]].pkey + '-' + p.uplink.name :
130                         p.uplink.name;
131                     join_path += '-' + uplink;
132                     alias = hex_md5(join_path);
133
134                     var uplink_alias = uplink + '-' + alias;
135
136                     if (!t.join) t.join = {};
137                     if (!t.join[uplink_alias]) t.join[uplink_alias] = {};
138
139                     t = t.join[uplink_alias];
140
141                     var djtype = 'inner';
142                     // we use LEFT JOINs for might_have and has_many, AND
143                     // also if our previous JOIN was a LEFT JOIN
144                     //
145                     // The last piece prevents later joins from limiting those
146                     // closer to the core table
147                     if (p.uplink.reltype != 'has_a' || last_jtype == 'left') djtype = 'left';
148
149                     t.type = p.jtype || djtype;
150                     last_jtype = t.type;
151                     t.key = p.uplink.key;
152                 } else {
153                     join_path = p.classname + '-' + p.classname;
154                     alias = hex_md5(join_path);
155                 }
156
157                 if (!t.alias) t.alias = alias;
158                 t.path = join_path;
159
160                 t.table = p.struct.source ? p.struct.source : p.table;
161                 t.idlclass = p.classname;
162
163                 if (a.length == i + 1) { // end of the path array, need a predictable hash
164                     t.label = item.path_label;
165                     t.alias = hex_md5(item.path_label);
166                 }
167
168             });
169         });
170
171         return tree;
172     };
173     // expose for testing
174     $scope._mergePaths = mergePaths;
175
176     $scope.constructTemplate = function () {
177         var param_counter = 0;
178         return {
179             version     : 5,
180             doc_url     : $scope.templateDocURL,
181             core_class  : egCore.idl.classTree.top.classname,
182             select      : dgrid.allItems().map(function (i) {
183                             return {
184                                 alias     : i.label,
185                                 path      : i.path[i.path.length - 1].classname + '-' + i.name,
186                                 field_doc : i.doc_text,
187                                 relation  : hex_md5(i.path_label),
188                                 column    : {
189                                     colname         : i.name,
190                                     transform       : i.transform ? i.transform.transform : '',
191                                     transform_label : i.transform ? i.transform.label : '',
192                                     aggregate       : !!i.transform.aggregate
193                                 }
194                             }
195                           }),
196             from        : mergePaths( dgrid.allItems().concat(fgrid.allItems()) ),
197             where       : fgrid.allItems().filter(function(i) {
198                             return !i.transform.aggregate;
199                           }).map(function (i) {
200                             var cond = {};
201                             if (
202                                 i.operator.op == 'is' ||
203                                 i.operator.op == 'is not' ||
204                                 i.operator.op == 'is blank' ||
205                                 i.operator.op == 'is not blank'
206                             ) {
207                                 cond[i.operator.op] = null;
208                             } else {
209                                 if (i.value === undefined) {
210                                     cond[i.operator.op] = '::P' + param_counter++;
211                                 }else {
212                                     cond[i.operator.op] = i.value;
213                                 }
214                             }
215                             return {
216                                 alias     : i.label,
217                                 path      : i.path[i.path.length - 1].classname + '-' + i.name,
218                                 field_doc : i.doc_text,
219                                 relation  : hex_md5(i.path_label),
220                                 column    : {
221                                     colname         : i.name,
222                                     transform       : i.transform.transform,
223                                     transform_label : i.transform.label,
224                                     aggregate       : 0
225                                 },
226                                 condition : cond // constructed above
227                             }
228                           }),
229             having      : fgrid.allItems().filter(function(i) {
230                             return !!i.transform.aggregate;
231                           }).map(function (i) {
232                             var cond = {};
233                             if (i.value === undefined) {
234                                 cond[i.operator.op] = '::P' + param_counter++;
235                             }else {
236                                 cond[i.operator.op] = i.value;
237                             }
238                             return {
239                                 alias     : i.label,
240                                 path      : i.path[i.path.length - 1].classname + '-' + i.name,
241                                 field_doc : i.doc_text,
242                                 relation  : hex_md5(i.path_label),
243                                 column    : {
244                                     colname         : i.name,
245                                     transform       : i.transform.transform,
246                                     transform_label : i.transform.label,
247                                     aggregate       : 1
248                                 },
249                                 condition : cond // constructed above
250                             }
251                           }),
252             display_cols: angular.copy( dgrid.allItems() ).map(strip_item),
253             filter_cols : angular.copy( fgrid.allItems() ).map(strip_item)
254         };
255
256         function strip_item (i) {
257             delete i.children;
258             i.path.forEach(function(p){
259                 delete p.children;
260                 delete p.fields;
261                 delete p.links;
262                 delete p.struct.permacrud;
263                 delete p.struct.field_map;
264                 delete p.struct.fields;
265             });
266             return i;
267         }
268
269     }
270
271     $scope.upgradeTemplate = function(template) {
272         template.name(template.name() + ' (converted from XUL)');
273         template.data.version = 5;
274
275         var order_by;
276         var rels = [];
277         for (var key in template.data.rel_cache) {
278             if (key == 'order_by') {
279                 order_by = template.data.rel_cache[key];
280             } else {
281                 rels.push(template.data.rel_cache[key]);
282             }
283         }
284
285         // preserve the old select order for the display cols
286         var sel_order = {};
287         template.data.select.map(function(val, idx) {
288             // set key to unique value easily derived from relcache
289             sel_order[val.relation + val.column.colname] = idx;
290         });
291
292         template.data['display_cols'] = [];
293         template.data['filter_cols'] = [];
294
295         function _convertPath(orig, rel) {
296             var newPath = [];
297
298             var table_path = rel.path.split(/\./);
299             if (table_path.length > 1 || rel.path.indexOf('-') > -1) table_path.push( rel.idlclass );
300
301             var prev_type = '';
302             var prev_link = '';
303             table_path.forEach(function(link) {
304                 var cls = link.split(/-/)[0];
305                 var fld = link.split(/-/)[1];
306                 var args = {
307                     label : egCore.idl.classes[cls].label
308                 }
309                 if (prev_link != '') {
310                     var link_parts = prev_link.split(/-/);
311                     args['from'] = link_parts[0];
312                     var join_parts = link_parts[1].split(/>/);
313                     var prev_col = join_parts[0];
314                     egCore.idl.classes[prev_link.split(/-/)[0]].fields.forEach(function(f) {
315                         if (prev_col == f.name) {
316                             args['link'] = f;
317                         }
318                     });
319                     args['jtype'] = join_parts[1]; // frequently undefined
320                 }
321                 newPath.push(egCore.idl.classTree.buildNode(cls, args));
322                 prev_link = link;
323             });
324             return newPath;
325
326         }
327
328         function _buildCols(rel, tab_type, col_idx) {
329             if (tab_type == 'dis_tab') {
330                 col_type = 'display_cols';
331             } else {
332                 col_type = 'filter_cols';
333             }
334
335             for (var col in rel.fields[tab_type]) {
336                 var orig = rel.fields[tab_type][col];
337                 var col = {
338                     name        : orig.colname,
339                     path        : _convertPath(orig, rel),
340                     label       : orig.alias,
341                     datatype    : orig.datatype,
342                     doc_text    : orig.field_doc,
343                     transform   : {
344                                     label     : orig.transform_label,
345                                     transform : orig.transform,
346                                     aggregate : (orig.aggregate == "undefined") ? undefined : orig.aggregate  // old structure sometimes has undefined as a quoted string
347                                   },
348                     path_label  : rel.label.replace('::', '->')
349                 };
350                 if (col_type == 'filter_cols') {
351                     col['operator'] = {
352                         op        : orig.op,
353                         label     : orig.op_label
354                     };
355                     col['index'] = col_idx++;
356                     if ('value' in orig.op_value) {
357                         col['value'] = orig.op_value.value;
358                     }
359                 } else { // display
360                     col['index'] = sel_order[rel.alias + orig.colname];
361                 }
362
363                 template.data[col_type].push(col);
364             }
365         }
366
367         rels.map(function(rel) {
368             _buildCols(rel, 'dis_tab');
369             _buildCols(rel, 'filter_tab', template.data.filter_cols.length);
370             _buildCols(rel, 'aggfilter_tab', template.data.filter_cols.length);
371         });
372
373         template.data['display_cols'].sort(function(a, b){return a.index - b.index});
374     }
375
376     function loadTemplate () {
377         if (!template_id) return;
378         egCore.pcrud.retrieve( 'rt', template_id)
379         .then( function(template) {
380             template.data = angular.fromJson(template.data());
381             if (template.data.version < 5) {
382                 $scope.upgradeTemplate(template);
383             }
384
385             $scope.templateName = template.name() + ' (clone)';
386             $scope.templateDescription = template.description();
387             $scope.templateDocURL = template.data.doc_url;
388
389             $scope.changeCoreSource( template.data.core_class );
390
391             egReportTemplateSvc.display_fields = template.data.display_cols;
392             egReportTemplateSvc.filter_fields = template.data.filter_cols;
393
394             $timeout(function(){
395                 dgrid.refresh();
396                 fgrid.refresh();
397             });
398         });
399
400     }
401
402     $scope.saveTemplate = function () {
403         var tmpl = new egCore.idl.rt();
404         tmpl.name( $scope.templateName );
405         tmpl.description( $scope.templateDescription );
406         tmpl.owner(egCore.auth.user().id());
407         tmpl.folder(folder_id);
408         tmpl.data(angular.toJson($scope.constructTemplate()));
409
410         egConfirmDialog.open(tmpl.name(), egCore.strings.TEMPLATE_CONF_CONFIRM_SAVE,
411             {ok : function() {
412                 return egCore.pcrud.create( tmpl )
413                 .then(
414                     function() {
415                         ngToast.create(egCore.strings.TEMPLATE_CONF_SUCCESS_SAVE);
416                         return $timeout(
417                             function(){
418                                 $window.location.href = egCore.env.basePath + 'reporter/legacy/main';
419                             },
420                             1000
421                         );
422                     },
423                     function() {
424                         ngToast.warning(egCore.strings.TEMPLATE_CONF_FAIL_SAVE);
425                     }
426                 );
427             }}
428         );
429     }
430
431     $scope.addDisplayFields = function () {
432         var t = $scope.selected_transform;
433         if (!t) t = default_transform_obj;
434
435         egReportTemplateSvc.addFields(
436             'display_fields',
437             $scope.selected_source_field_list, 
438             t,
439             $scope.currentPathLabel,
440             $scope.currentPath
441         );
442         $scope.selected_transform = null;
443         dgrid.refresh();
444     }
445
446     $scope.addFilterFields = function () {
447         var t = $scope.selected_transform;
448         if (!t) t = default_transform_obj;
449         f = default_filter_obj;
450
451         egReportTemplateSvc.addFields(
452             'filter_fields',
453             $scope.selected_source_field_list, 
454             t,
455             $scope.currentPathLabel,
456             $scope.currentPath,
457             f
458         );
459         $scope.selected_transform = null;
460         fgrid.refresh();
461     }
462
463     $scope.moveDisplayFieldUp = function (items) {
464         items.reverse().forEach(function(item) {
465             egReportTemplateSvc.moveFieldUp('display_fields', item);
466         });
467         dgrid.refresh();
468     }
469
470     $scope.moveDisplayFieldDown = function (items) {
471         items.forEach(function(item) {
472             egReportTemplateSvc.moveFieldDown('display_fields', item);
473         });
474         dgrid.refresh();
475     }
476
477     $scope.removeDisplayField = function (items) {
478         items.forEach(function(item) {egReportTemplateSvc.removeField('display_fields', item)});
479         dgrid.refresh();
480     }
481
482     $scope.changeDisplayLabel = function (items) {
483         items.forEach(function(item) {
484             egPromptDialog.open(egCore.strings.TEMPLATE_CONF_PROMPT_CHANGE, item.label || '',
485                 {ok : function(value) {
486                     if (value) egReportTemplateSvc.display_fields[item.index].label = value;
487                 }}
488             );
489         });
490         dgrid.refresh();
491     }
492
493     $scope.changeDisplayFieldDoc = function (items) {
494         items.forEach(function(item) {
495             egPromptDialog.open(egCore.strings.TEMPLATE_FIELD_DOC_PROMPT_CHANGE, item.doc_text || '',
496                 {ok : function(value) {
497                     if (value) egReportTemplateSvc.display_fields[item.index].doc_text = value;
498                 }}
499             );
500         });
501         dgrid.refresh();
502     }
503
504     $scope.changeFilterFieldDoc = function (items) {
505         items.forEach(function(item) {
506             egPromptDialog.open(egCore.strings.TEMPLATE_FIELD_DOC_PROMPT_CHANGE, item.doc_text || '',
507                 {ok : function(value) {
508                     if (value) egReportTemplateSvc.filter_fields[item.index].doc_text = value;
509                 }}
510             );
511         });
512         fgrid.refresh();
513     }
514
515     $scope.changeFilterValue = function (items) {
516         items.forEach(function(item) {
517             var l = null;
518             if (item.datatype == "bool") {
519                 var displayVal = typeof item.value === "undefined" ? egCore.strings.TEMPLATE_CONF_UNSET :
520                                  item.value === 't'                ? egCore.strings.TEMPLATE_CONF_TRUE :
521                                  item.value === 'f'                ? egCore.strings.TEMPLATE_CONF_FALSE :
522                                  item.value.toString();
523                 egConfirmDialog.open(egCore.strings.TEMPLATE_CONF_DEFAULT, displayVal,
524                     {ok : function() {
525                         egReportTemplateSvc.filter_fields[item.index].value = 't';
526                     },
527                     cancel : function() {
528                         egReportTemplateSvc.filter_fields[item.index].value = 'f';
529                     }}, egCore.strings.TEMPLATE_CONF_TRUE, egCore.strings.TEMPLATE_CONF_FALSE
530                 );
531             } else {
532                 egPromptDialog.open(egCore.strings.TEMPLATE_CONF_DEFAULT, item.value || '',
533                     {ok : function(value) {
534                         if (value) egReportTemplateSvc.updateFilterValue(item, value);
535                     }}
536                 );
537             }
538         });
539         fgrid.refresh();
540     }
541
542     $scope.changeTransform = function (items) {
543
544         var f = items[0];
545
546         var tlist = [];
547         angular.forEach(egReportTemplateSvc.Transforms, function (o,n) {
548             if ( o.datatype.indexOf(f.datatype) > -1) {
549                 if (tlist.indexOf(o.label) == -1) tlist.push( o.label );
550             }
551         });
552         
553         items.forEach(function(item) {
554             egSelectDialog.open(
555                 egCore.strings.SELECT_TFORM, tlist, item.transform.label,
556                 {ok : function(value) {
557                     if (value) {
558                         var t = egReportTemplateSvc.getTransformByLabel(value);
559                         item.transform = {
560                             label     : value,
561                             transform : t,
562                             aggregate : egReportTemplateSvc.Transforms[t].aggregate ? true : false
563                         };
564                     }
565                 }}
566             );
567         });
568
569         fgrid.refresh();
570     }
571
572     $scope.changeOperator = function (items) {
573
574         var flist = [];
575         Object.keys(egReportTemplateSvc.Filters).forEach(function(k){
576             var v = egReportTemplateSvc.Filters[k];
577             if (flist.indexOf(v.label) == -1) flist.push(v.label);
578             if (v.labels && v.labels.length > 0) {
579                 v.labels.forEach(function(l) {
580                     if (flist.indexOf(l) == -1) flist.push(l);
581                 })
582             }
583         });
584
585         items.forEach(function(item) {
586             var l = item.operator ? item.operator.label : '';
587             egSelectDialog.open(
588                 egCore.strings.SELECT_OP, flist, l,
589                 {ok : function(value) {
590                     if (value) {
591                         var t = egReportTemplateSvc.getFilterByLabel(value);
592                         item.operator = { label: value, op : t };
593
594                         //Update the filter value based on the new operator, because
595                         //  different operators treat the value differently
596                         egReportTemplateSvc.updateFilterValue(item, egReportTemplateSvc.filter_fields[item.index].value);
597                     }
598                 }}
599             );
600         });
601
602         fgrid.refresh();
603     }
604
605     $scope.removeFilterValue = function (items) {
606         items.forEach(function(item) {delete egReportTemplateSvc.filter_fields[item.index].value});
607         fgrid.refresh();
608     }
609
610     $scope.removeFilterField = function (items) {
611         items.forEach(function(item) {egReportTemplateSvc.removeField('filter_fields', item)});
612         fgrid.refresh();
613     }
614
615     $scope.allSources = values(egCore.idl.classes).sort( function(a,b) {
616         if (a.core && !b.core) return -1;
617         if (b.core && !a.core) return 1;
618         aname = a.label ? a.label : a.name;
619         bname = b.label ? b.label : b.name;
620         if (aname > bname) return 1;
621         return -1;
622     });
623
624     $scope.class_tree = [];
625     $scope.selected_source = null;
626     $scope.selected_source_fields = [];
627     $scope.selected_source_field_list = [];
628     $scope.available_field_transforms = [];
629     $scope.coreSource = null;
630     $scope.coreSourceChosen = false;
631     $scope.currentPathLabel = '';
632
633     $scope.treeExpand = function (node, expanding) {
634         if (expanding) node.children.map(egCore.idl.classTree.fleshNode);
635     }
636
637     $scope.filterFields = function (n) {
638         return n.virtual ? false : true;
639         // should we hide links?
640         return n.datatype && n.datatype != 'link'
641     }
642
643     $scope.field_tree_opts = {
644         multiSelection: true,
645         equality      : function(node1, node2) {
646             return node1.name == node2.name;
647         }
648     }
649
650     $scope.field_transforms_tree_opts = {
651         equality : function(node1, node2) {
652             if (!node2) return false;
653             return node1.transform == node2.transform;
654         }
655     }
656
657     $scope.selectFields = function () {
658         while ($scope.available_field_transforms.length) {
659             $scope.available_field_transforms.pop();
660         }
661
662         angular.forEach( $scope.selected_source_field_list, function (f) {
663             angular.forEach(egReportTemplateSvc.Transforms, function (o,n) {
664                 if ( o.datatype.indexOf(f.datatype) > -1) {
665                     var include = true;
666
667                     angular.forEach($scope.available_field_transforms, function (t) {
668                         if (t.transform == n) include = false;
669                     });
670
671                     if (include) $scope.available_field_transforms.push({
672                         transform : n,
673                         label     : o.label,
674                         aggregate : o.aggregate ? true : false
675                     });
676                 }
677             });
678         });
679
680     }
681
682     $scope.selectSource = function (node, selected, $path) {
683
684         while ($scope.selected_source_field_list.length) {
685             $scope.selected_source_field_list.pop();
686         }
687         while ($scope.selected_source_fields.length) {
688             $scope.selected_source_fields.pop();
689         }
690
691         if (selected) {
692             $scope.currentPath = angular.copy( $path().reverse() );
693             $scope.selected_source = node;
694             $scope.currentPathLabel = $scope.currentPath.map(function(n,i){
695                 var l = n.label
696                 if (i && n.jtype) l += ' (' + n.jtype + ')';
697                 return l;
698             }).join( ' -> ' );
699             angular.forEach( node.fields, function (f) {
700                 $scope.selected_source_fields.push( f );
701             });
702         } else {
703             $scope.currentPathLabel = '';
704         }
705
706         // console.log($scope.selected_source);
707     }
708
709     $scope.changeCoreSource = function (new_core) {
710         console.log('changeCoreSource: '+new_core);
711         function change_core () {
712             if (new_core) $scope.coreSource = new_core;
713             $scope.coreSourceChosen = true;
714
715             $scope.class_tree.pop();
716             $scope.class_tree.push(
717                 egCore.idl.classTree.setTop($scope.coreSource)
718             );
719
720             while ($scope.selected_source_fields.length) {
721                 $scope.selected_source_fields.pop();
722             }
723
724             while ($scope.available_field_transforms.length) {
725                 $scope.available_field_transforms.pop();
726             }
727
728             $scope.currentPathLabel = '';
729         }
730
731         if ($scope.coreSourceChosen) {
732             egConfirmDialog.open(
733                 egCore.strings.FOLDERS_TEMPLATE,
734                 egCore.strings.SOURCE_SETUP_CONFIRM_EXIT,
735                 {ok : change_core}
736             );
737         } else {
738             change_core();
739         }
740     }
741
742     loadTemplate();
743 }])
744
745 ;