]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/web/js/ui/default/staff/admin/workstation/app.js
310356a0bf6f9b74b4fe7cbba9311667e90eef39
[Evergreen.git] / Open-ILS / web / js / ui / default / staff / admin / workstation / app.js
1 /**
2  * App to drive the base page. 
3  * Login Form
4  * Splash Page
5  */
6
7 angular.module('egWorkstationAdmin', 
8     ['ngRoute', 'ui.bootstrap', 'egCoreMod', 'egUiMod'])
9
10 .config(['$routeProvider','$locationProvider','$compileProvider', 
11  function($routeProvider , $locationProvider , $compileProvider) {
12
13     $locationProvider.html5Mode(true);
14     $compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|blob):/); 
15     var resolver = {delay : function(egStartup) {return egStartup.go()}};
16
17     $routeProvider.when('/admin/workstation/workstations', {
18         templateUrl: './admin/workstation/t_workstations',
19         controller: 'WSRegCtrl',
20         resolve : resolver
21     });
22
23     $routeProvider.when('/admin/workstation/print/config', {
24         templateUrl: './admin/workstation/t_print_config',
25         controller: 'PrintConfigCtrl',
26         resolve : resolver
27     });
28
29     $routeProvider.when('/admin/workstation/print/templates', {
30         templateUrl: './admin/workstation/t_print_templates',
31         controller: 'PrintTemplatesCtrl',
32         resolve : resolver
33     });
34
35     $routeProvider.when('/admin/workstation/stored_prefs', {
36         templateUrl: './admin/workstation/t_stored_prefs',
37         controller: 'StoredPrefsCtrl',
38         resolve : resolver
39     });
40
41
42     // default page 
43     $routeProvider.otherwise({
44         templateUrl : './admin/workstation/t_splash',
45         controller : 'SplashCtrl',
46         resolve : resolver
47     });
48 }])
49
50 .config(['ngToastProvider', function(ngToastProvider) {
51   ngToastProvider.configure({
52     verticalPosition: 'bottom',
53     animation: 'fade'
54   });
55 }])
56
57 .factory('workstationSvc',
58        ['$q','$timeout','$location','egCore','egConfirmDialog',
59 function($q , $timeout , $location , egCore , egConfirmDialog) {
60     
61     var service = {};
62
63     service.get_all = function() {
64         return egCore.hatch.getItem('eg.workstation.all')
65         .then(function(all) { return all || [] });
66     }
67
68     service.get_default = function() {
69         return egCore.hatch.getItem('eg.workstation.default');
70     }
71
72     service.set_default = function(name) {
73         return egCore.hatch.setItem('eg.workstation.default', name);
74     }
75
76     service.register_workstation = function(base_name, name, org_id) {
77         return service.register_ws_api(base_name, name, org_id)
78         .then(function(ws_id) {
79             return service.track_new_ws(ws_id, name, org_id);
80         });
81     };
82
83     service.register_ws_api = 
84         function(base_name, name, org_id, override, deferred) {
85         if (!deferred) deferred = $q.defer();
86
87         var method = 'open-ils.actor.workstation.register';
88         if (override) method += '.override';
89
90         egCore.net.request(
91             'open-ils.actor', method, egCore.auth.token(), name, org_id)
92
93         .then(function(resp) {
94
95             if (evt = egCore.evt.parse(resp)) {
96                 console.log('register returned ' + evt.toString());
97
98                 if (evt.textcode == 'WORKSTATION_NAME_EXISTS' && !override) {
99
100                     egConfirmDialog.open(
101                         egCore.strings.WS_EXISTS, base_name, {  
102                             ok : function() {
103                                 service.register_ws_api(
104                                     base_name, name, org_id, true, deferred)
105                             },
106                             cancel : function() {deferred.reject()} 
107                         }
108                     );
109
110                 } else {
111                     alert(evt.toString());
112                     deferred.reject();
113                 }
114             } else if (resp) {
115                 console.log('Resolving register promise with: ' + resp);
116                 deferred.resolve(resp);
117             }
118         });
119
120         return deferred.promise;
121     }
122
123     service.track_new_ws = function(ws_id, ws_name, owning_lib) {
124         console.log('Tracking newly created WS with ID ' + ws_id);
125         var new_ws = {id : ws_id, name : ws_name, owning_lib : owning_lib};
126
127         return service.get_all()
128         .then(function(all) {
129             all.push(new_ws);
130             return egCore.hatch.setItem('eg.workstation.all', all)
131             .then(function() { return new_ws });
132         });
133     }
134
135     // Remove all traces of the workstation locally.
136     // This does not remove the WS from the server.
137     service.remove_workstation = function(name) {
138         console.debug('Removing workstation: ' + name);
139
140         return egCore.hatch.getItem('eg.workstation.all')
141
142         // remove from list of all workstations
143         .then(function(all) {
144             if (!all) all = [];
145             var keep = all.filter(function(ws) {return ws.name != name});
146             return egCore.hatch.setItem('eg.workstation.all', keep)
147
148         }).then(function() { 
149
150             return service.get_default()
151
152         }).then(function(def) {
153             if (def == name) {
154                 console.debug('Removing default workstation: ' + name);
155                 return egCore.hatch.removeItem('eg.workstation.default');
156             }
157         });
158     }
159
160     return service;
161 }])
162
163
164 .controller('SplashCtrl',
165        ['$scope','$window','$location','egCore','egConfirmDialog',
166 function($scope , $window , $location , egCore , egConfirmDialog) {
167
168     // ---------------------
169     // Hatch Configs
170     $scope.hatchRequired = 
171         egCore.hatch.getLocalItem('eg.hatch.required');
172
173     $scope.updateHatchRequired = function() {
174         egCore.hatch.setLocalItem(
175             'eg.hatch.required', $scope.hatchRequired);
176     }
177
178     egCore.hatch.getItem('eg.audio.disable').then(function(val) {
179         $scope.disable_sound = val;
180     });
181
182     egCore.hatch.getItem('eg.search.search_lib').then(function(val) {
183         $scope.search_lib = egCore.org.get(val);
184     });
185     $scope.handle_search_lib_changed = function(org) {
186         egCore.hatch.setItem('eg.search.search_lib', org.id());
187     };
188
189     egCore.hatch.getItem('eg.search.pref_lib').then(function(val) {
190         $scope.pref_lib = egCore.org.get(val);
191     });
192     $scope.handle_pref_lib_changed = function(org) {
193         egCore.hatch.setItem('eg.search.pref_lib', org.id());
194     };
195
196     $scope.adv_pane = 'advanced'; // default value if not explicitly set
197     egCore.hatch.getItem('eg.search.adv_pane').then(function(val) {
198         $scope.adv_pane = val;
199     });
200     $scope.$watch('adv_pane', function(newVal, oldVal) {
201         if (newVal != oldVal) {
202             egCore.hatch.setItem('eg.search.adv_pane', newVal);
203         }
204     });
205
206     $scope.apply_sound = function() {
207         if ($scope.disable_sound) {
208             egCore.hatch.setItem('eg.audio.disable', true);
209         } else {
210             egCore.hatch.removeItem('eg.audio.disable');
211         }
212     }
213
214     $scope.test_audio = function(sound) {
215         egCore.audio.play(sound);
216     }
217
218 }])
219
220 .controller('PrintConfigCtrl',
221        ['$scope','egCore',
222 function($scope , egCore) {
223
224     $scope.printConfig = {};
225     $scope.setContext = function(ctx) { 
226         $scope.context = ctx; 
227         $scope.isTestView = false;
228     }
229     $scope.setContext('default');
230
231     $scope.hatchNotConnected = function() {
232         return !egCore.hatch.hatchAvailable;
233     }
234
235     $scope.getPrinterByAttr = function(attr, value) {
236         var printer;
237         angular.forEach($scope.printers, function(p) {
238             if (p[attr] == value) printer = p;
239         });
240         return printer;
241     }
242
243     // fetch info on all remote printers
244     egCore.hatch.getPrinters()
245     .then(function(printers) { 
246         $scope.printers = printers;
247
248         var def = $scope.getPrinterByAttr('is-default', true);
249         if (!def && printers.length) def = printers[0];
250
251         if (def) {
252             $scope.defaultPrinter = def;
253             loadPrinterOptions(def.name);
254         }
255     }).then(function() {
256         angular.forEach(
257             ['default','receipt','label','mail','offline'],
258             function(ctx) {
259                 egCore.hatch.getPrintConfig(ctx).then(function(conf) {
260                     if (conf) {
261                         $scope.printConfig[ctx] = conf;
262                     } else {
263                         $scope.resetPrinterSettings(ctx);
264                     }
265                 });
266             }
267         );
268     });
269
270     $scope.resetPrinterSettings = function(context) {
271         $scope.printConfig[context] = {
272             context : context,
273             printer : $scope.defaultPrinter ? $scope.defaultPrinter.name : null,
274             autoMargins : true, 
275             allPages : true,
276             pageRanges : []
277         };
278     }
279
280     $scope.savePrinterSettings = function(context) {
281         return egCore.hatch.setPrintConfig(
282             context, $scope.printConfig[context]);
283     }
284
285     $scope.printerConfString = function() {
286         if ($scope.printConfigError) return $scope.printConfigError;
287         if (!$scope.printConfig) return;
288         if (!$scope.printConfig[$scope.context]) return;
289         return JSON.stringify(
290             $scope.printConfig[$scope.context], undefined, 2);
291     }
292
293     function loadPrinterOptions(name) {
294         egCore.hatch.getPrinterOptions(name).then(
295             function(options) {$scope.printerOptions = options});
296     }
297
298     $scope.setPrinter = function(name) {
299         $scope.printConfig[$scope.context].printer = name;
300         loadPrinterOptions(name);
301     }
302
303     // for testing
304     $scope.setContentType = function(type) { $scope.contentType = type }
305
306     $scope.testPrint = function(withDialog) {
307         if ($scope.contentType == 'text/plain') {
308             egCore.print.print({
309                 context : $scope.context, 
310                 content_type : $scope.contentType, 
311                 content : $scope.textPrintContent,
312                 show_dialog : withDialog
313             });
314         } else {
315             egCore.print.print({
316                 context : $scope.context,
317                 content_type : $scope.contentType, 
318                 content : $scope.htmlPrintContent, 
319                 scope : {
320                     value1 : 'Value One', 
321                     value2 : 'Value Two',
322                     date_value : '2015-02-04T14:04:34-0400'
323                 },
324                 show_dialog : withDialog
325             });
326         }
327     }
328
329     $scope.setContentType('text/plain');
330
331 }])
332
333 .controller('PrintTemplatesCtrl',
334        ['$scope','$q','egCore','ngToast',
335 function($scope , $q , egCore , ngToast) {
336
337     $scope.print = {
338         template_name : 'bills_current',
339         template_output : '',
340         template_context : 'default'
341     };
342
343     // print preview scope data
344     // TODO: consider moving the template-specific bits directly
345     // into the templates or storing template- specific script files
346     // alongside the templates.
347     // NOTE: A lot of this data can be shared across templates.
348     var seed_user = {
349         first_given_name : 'Slow',
350         second_given_name : 'Joe',
351         family_name : 'Jones',
352         card : {
353             barcode : '30393830393'
354         }
355     }
356     var seed_addr = {
357         street1 : '123 Apple Rd',
358         street2 : 'Suite B',
359         city : 'Anywhere',
360         state : 'XX',
361         country : 'US',
362         post_code : '12345'
363     }
364
365     var seed_record = {
366         title : 'Traveling Pants!!',
367         author : 'Jane Jones',
368         isbn : '1231312123'
369     };
370
371     var seed_copy = {
372         barcode : '33434322323',
373         call_number : {
374             label : '636.8 JON',
375             record : {
376                 simple_record : {
377                     'title' : 'Test Title'
378                 }
379             }
380         },
381         location : {
382             name : 'General Collection'
383         },
384         // flattened versions for item status template
385         // TODO - make this go away
386         'call_number.label' : '636.8 JON',
387         'call_number.record.simple_record.title' : 'Test Title',
388         'location.name' : 'General Colleciton'
389     }
390
391     var one_hold = {
392         behind_desk : 'f',
393         phone_notify : '111-222-3333',
394         sms_notify : '111-222-3333',
395         email_notify : 'user@example.org',
396         request_time : new Date().toISOString(),
397         hold_type : 'T'
398     }
399
400     var seed_transit = {
401         source : {
402             name : 'Library Y',
403             shortname : 'LY',
404             holds_address : seed_addr
405         },
406         dest : {
407             name : 'Library X',
408             shortname : 'LX',
409             holds_address : seed_addr
410         },
411         source_send_time : new Date().toISOString(),
412         target_copy : seed_copy
413     }
414
415     $scope.preview_scope = {
416         //bills
417         transactions : [
418             {
419                 id : 1,
420                 xact_start : new Date().toISOString(),
421                 summary : {
422                     xact_type : 'circulation',
423                     last_billing_type : 'Overdue materials',
424                     total_owed : 1.50,
425                     last_payment_note : 'Test Note 1',
426                     last_payment_type : 'cash_payment',
427                     total_paid : 0.50,
428                     balance_owed : 1.00
429                 }
430             }, {
431                 id : 2,
432                 xact_start : new Date().toISOString(),
433                 summary : {
434                     xact_type : 'circulation',
435                     last_billing_type : 'Overdue materials',
436                     total_owed : 2.50,
437                     last_payment_note : 'Test Note 2',
438                     last_payment_type : 'credit_payment',
439                     total_paid : 0.50,
440                     balance_owed : 2.00
441                 }
442             }
443         ],
444
445         copy : seed_copy,
446         copies : [ seed_copy ],
447
448         checkins : [
449             {
450                 due_date : new Date().toISOString(),
451                 target_copy : seed_copy,
452                 copy_barcode : seed_copy.barcode,
453                 call_number : seed_copy.call_number,
454                 title : seed_record.title
455             },
456         ],
457
458         circulations : [
459             {
460                 circ : {
461                     due_date : new Date().toISOString(),
462                 },
463                 copy : seed_copy,
464                 title : seed_record.title,
465                 author : seed_record.author
466             },
467         ],
468
469         in_house_uses : [
470             {
471                 num_uses : 3,
472                 copy : seed_copy,
473                 title : seed_record.title
474             }
475         ],
476
477         previous_balance : 8.45,
478         payment_total : 2.00,
479         payment_applied : 2.00,
480         new_balance : 6.45,
481         amount_voided : 0,
482         change_given : 0,
483         payment_type : 'cash_payment',
484         payment_note : 'Here is a payment note',
485         note : {
486             create_date : new Date().toISOString(), 
487             title : 'Test Note Title',
488             usr : seed_user,
489             value : 'This patron is super nice!'
490         },
491
492         transit : seed_transit,
493         transits : [ seed_transit ],
494         title : seed_record.title,
495         author : seed_record.author,
496         patron : seed_user,
497         address : seed_addr,
498         dest_location : egCore.idl.toHash(egCore.org.get(egCore.auth.user().ws_ou())),
499         dest_address : seed_addr,
500         hold : one_hold,
501         holds : [
502             {
503                 hold : one_hold, title : 'Some Title 1', author : 'Some Author 1',
504                 volume : { label : '646.4 SOM' }, copy : seed_copy,
505                 part : { label : 'v. 1' },
506                 patron_barcode : 'S52802662',
507                 patron_alias : 'XYZ', patron_last : 'Smith', patron_first : 'Jane'
508             },
509             {
510                 hold : one_hold, title : 'Some Title 2', author : 'Some Author 2',
511                 volume : { label : '646.4 SOM' }, copy : seed_copy,
512                 part : { label : 'v. 1' },
513                 patron_barcode : 'S52802662',
514                 patron_alias : 'XYZ', patron_last : 'Smith', patron_first : 'Jane'
515             },
516             {
517                 hold : one_hold, title : 'Some Title 3', author : 'Some Author 3',
518                 volume : { label : '646.4 SOM' }, copy : seed_copy,
519                 part : { label : 'v. 1' },
520                 patron_barcode : 'S52802662',
521                 patron_alias : 'XYZ', patron_last : 'Smith', patron_first : 'Jane'
522             }
523         ]
524     }
525
526     $scope.preview_scope.payments = [
527         {amount : 1.00, xact : $scope.preview_scope.transactions[0]}, 
528         {amount : 1.00, xact : $scope.preview_scope.transactions[1]}
529     ]
530     $scope.preview_scope.payments[0].xact.title = 'Hali Bote Azikaban de tao fan';
531     $scope.preview_scope.payments[0].xact.copy_barcode = '334343434';
532     $scope.preview_scope.payments[1].xact.title = seed_record.title;
533     $scope.preview_scope.payments[1].xact.copy_barcode = seed_copy.barcode;
534
535     // today, staff, current_location, etc.
536     egCore.print.fleshPrintScope($scope.preview_scope);
537
538     $scope.template_changed = function() {
539         $scope.print.load_failed = false;
540         egCore.print.getPrintTemplate($scope.print.template_name)
541         .then(
542             function(html) { 
543                 $scope.print.template_content = html;
544                 console.log('set template content');
545             },
546             function() {
547                 $scope.print.template_content = '';
548                 $scope.print.load_failed = true;
549             }
550         );
551         egCore.print.getPrintTemplateContext($scope.print.template_name)
552         .then(function(template_context) {
553             $scope.print.template_context = template_context;
554         });
555     }
556
557     $scope.save_locally = function() {
558         egCore.print.storePrintTemplate(
559             $scope.print.template_name,
560             $scope.print.template_content
561         );
562         egCore.print.storePrintTemplateContext(
563             $scope.print.template_name,
564             $scope.print.template_context
565         );
566     }
567
568     $scope.exportable_templates = function() {
569         var templates = {};
570         var contexts = {};
571         var deferred = $q.defer();
572         var promises = [];
573         egCore.hatch.getKeys('eg.print.template').then(function(keys) {
574             angular.forEach(keys, function(key) {
575                 if (key.match(/^eg\.print\.template\./)) {
576                     promises.push(egCore.hatch.getItem(key).then(function(value) {
577                         templates[key.replace('eg.print.template.', '')] = value;
578                     }));
579                 } else {
580                     promises.push(egCore.hatch.getItem(key).then(function(value) {
581                         contexts[key.replace('eg.print.template_context.', '')] = value;
582                     }));
583                 }
584             });
585             $q.all(promises).then(function() {
586                 if (Object.keys(templates).length) {
587                     deferred.resolve({
588                         templates: templates,
589                         contexts: contexts
590                     });
591                 } else {
592                     ngToast.warning(egCore.strings.PRINT_TEMPLATES_FAIL_EXPORT);
593                     deferred.reject();
594                 }
595             });
596         });
597         return deferred.promise;
598     }
599
600     $scope.imported_print_templates = { data : '' };
601     $scope.$watch('imported_print_templates.data', function(newVal, oldVal) {
602         if (newVal && newVal != oldVal) {
603             try {
604                 var data = JSON.parse(newVal);
605                 angular.forEach(data.templates, function(template_content, template_name) {
606                     egCore.print.storePrintTemplate(template_name, template_content);
607                 });
608                 angular.forEach(data.contexts, function(template_context, template_name) {
609                     egCore.print.storePrintTemplateContext(template_name, template_context);
610                 });
611                 $scope.template_changed(); // refresh
612                 ngToast.create(egCore.strings.PRINT_TEMPLATES_SUCCESS_IMPORT);
613             } catch (E) {
614                 ngToast.warning(egCore.strings.PRINT_TEMPLATES_FAIL_IMPORT);
615             }
616         }
617     });
618
619     $scope.template_changed(); // load the default
620 }])
621
622 // 
623 .directive('egPrintTemplateOutput', ['$compile',function($compile) {
624     return function(scope, element, attrs) {
625         scope.$watch(
626             function(scope) {
627                 return scope.$eval(attrs.content);
628             },
629             function(value) {
630                 // create an isolate scope and copy the print context
631                 // data into the new scope.
632                 // TODO: see also print security concerns in egHatch
633                 var result = element.html(value);
634                 var context = scope.$eval(attrs.context);
635                 var print_scope = scope.$new(true);
636                 angular.forEach(context, function(val, key) {
637                     print_scope[key] = val;
638                 })
639                 $compile(element.contents())(print_scope);
640             }
641         );
642     };
643 }])
644
645 .controller('StoredPrefsCtrl',
646        ['$scope','$q','egCore','egConfirmDialog',
647 function($scope , $q , egCore , egConfirmDialog) {
648     console.log('StoredPrefsCtrl');
649
650     $scope.setContext = function(ctx) {
651         $scope.context = ctx;
652     }
653     $scope.setContext('local');
654
655     // grab the edit perm
656     $scope.userHasDeletePerm = false;
657     egCore.perm.hasPermHere('ADMIN_WORKSTATION')
658     .then(function(bool) { $scope.userHasDeletePerm = bool });
659
660     // fetch the keys
661
662     function refreshKeys() {
663         $scope.keys = {local : [], remote : []};
664
665         egCore.hatch.getRemoteKeys().then(
666             function(keys) { $scope.keys.remote = keys.sort() })
667     
668         // local calls are non-async
669         $scope.keys.local = egCore.hatch.getLocalKeys();
670     }
671     refreshKeys();
672
673     $scope.selectKey = function(key) {
674         $scope.currentKey = key;
675         $scope.currentKeyContent = null;
676
677         if ($scope.context == 'local') {
678             $scope.currentKeyContent = egCore.hatch.getLocalItem(key);
679         } else {
680             egCore.hatch.getRemoteItem(key)
681             .then(function(content) {
682                 $scope.currentKeyContent = content
683             });
684         }
685     }
686
687     $scope.getCurrentKeyContent = function() {
688         return JSON.stringify($scope.currentKeyContent, null, 2);
689     }
690
691     $scope.removeKey = function(key) {
692         egConfirmDialog.open(
693             egCore.strings.PREFS_REMOVE_KEY_CONFIRM, '',
694             {   deleteKey : key,
695                 ok : function() {
696                     if ($scope.context == 'local') {
697                         egCore.hatch.removeLocalItem(key);
698                         refreshKeys();
699                     } else {
700                         egCore.hatch.removeItem(key)
701                         .then(function() { refreshKeys() });
702                     }
703                 },
704                 cancel : function() {} // user canceled, nothing to do
705             }
706         );
707     }
708 }])
709
710 .controller('WSRegCtrl',
711        ['$scope','$q','$window','$location','egCore','egAlertDialog','workstationSvc',
712 function($scope , $q , $window , $location , egCore , egAlertDialog , workstationSvc) {
713
714     var all_workstations = [];
715     var reg_perm_orgs = [];
716
717     $scope.page_loaded = false;
718     $scope.contextOrg = egCore.org.get(egCore.auth.user().ws_ou());
719     $scope.wsOrgChanged = function(org) { $scope.contextOrg = org; }
720
721     console.log('set context org to ' + $scope.contextOrg);
722
723     // fetch workstation reg perms
724     egCore.perm.hasPermAt('REGISTER_WORKSTATION', true)
725     .then(function(orgList) { 
726         reg_perm_orgs = orgList;
727
728         // hide orgs in the context org selector where this login
729         // does not have the reg_ws perm
730         $scope.wsOrgHidden = function(id) {
731             return reg_perm_orgs.indexOf(id) == -1;
732         }
733
734     // fetch the locally stored workstation data
735     }).then(function() {
736         return workstationSvc.get_all()
737         
738     }).then(function(all) {
739         all_workstations = all || [];
740         $scope.workstations = 
741             all_workstations.map(function(w) { return w.name });
742         return workstationSvc.get_default()
743
744     // fetch the default workstation
745     }).then(function(def) { 
746         $scope.defaultWS = def;
747         $scope.activeWS = $scope.selectedWS = egCore.auth.workstation() || def;
748
749     // Handle any URL commands.
750     }).then(function() {
751         var remove = $location.search().remove;
752          if (remove) {
753             console.log('Removing WS via URL request: ' + remove);
754             return $scope.remove_ws(remove).then(
755                 function() { $scope.page_loaded = true; });
756         }
757         $scope.page_loaded = true;
758     });
759
760     $scope.get_ws_label = function(ws) {
761         return ws == $scope.defaultWS ? 
762             egCore.strings.$replace(egCore.strings.DEFAULT_WS_LABEL, {ws:ws}) : ws;
763     }
764
765     $scope.set_default_ws = function(name) {
766         delete $scope.removing_ws;
767         $scope.defaultWS = name;
768         workstationSvc.set_default(name);
769     }
770
771     $scope.cant_have_users = 
772         function (id) { return !egCore.org.CanHaveUsers(id); };
773     $scope.cant_have_volumes = 
774         function (id) { return !egCore.org.CanHaveVolumes(id); };
775
776     // Log out and return to login page with selected WS 
777     $scope.use_now = function() {
778         egCore.auth.logout();
779         $window.location.href = $location
780             .path('/login')
781             .search({ws : $scope.selectedWS})
782             .absUrl();
783     }
784
785     $scope.can_delete_ws = function(name) {
786         var ws = all_workstations.filter(
787             function(ws) { return ws.name == name })[0];
788         return ws && reg_perm_orgs.indexOf(ws.owning_lib) != -1;
789     }
790
791     $scope.remove_ws = function(remove_me) {
792         $scope.removing_ws = remove_me;
793
794         // Perm is used to disable Remove button in UI, but have to check
795         // again here in case we're removing a WS based on URL params.
796         if (!$scope.can_delete_ws(remove_me)) return $q.when();
797
798         $scope.is_removing = true;
799         return workstationSvc.remove_workstation(remove_me)
800         .then(function() {
801
802             all_workstations = all_workstations.filter(
803                 function(ws) { return ws.name != remove_me });
804
805             $scope.workstations = $scope.workstations.filter(
806                 function(ws) { return ws != remove_me });
807
808             if ($scope.selectedWS == remove_me) 
809                 $scope.selectedWS = $scope.workstations[0];
810
811             if ($scope.defaultWS == remove_me) 
812                 $scope.defaultWS = '';
813
814             $scope.is_removing = false;
815         });
816     }
817
818     $scope.register_ws = function() {
819         delete $scope.removing_ws;
820
821         var full_name = 
822             $scope.contextOrg.shortname() + '-' + $scope.newWSName;
823
824         if ($scope.workstations.indexOf(full_name) > -1) {
825             // avoid duplicate local registrations
826             return egAlertDialog.open(egCore.strings.WS_USED);
827         }
828
829         $scope.is_registering = true;
830         workstationSvc.register_workstation(
831             $scope.newWSName, full_name,
832             $scope.contextOrg.id()
833
834         ).then(function(new_ws) {
835             $scope.workstations.push(new_ws.name);
836             all_workstations.push(new_ws);  
837             $scope.is_registering = false;
838
839             if (!$scope.selectedWS) {
840                 $scope.selectedWS = new_ws.name;
841             }
842             if (!$scope.defaultWS) {
843                 return $scope.set_default_ws(new_ws.name);
844             }
845             $scope.newWSName = '';
846         });
847     }
848 }])
849
850