]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Open-ILS/web/js/ui/default/staff/services/org.js
LP2045292 Color contrast for AngularJS patron bills
[working/Evergreen.git] / Open-ILS / web / js / ui / default / staff / services / org.js
1 /**
2  * Core Service - egOrg
3  *
4  * This provides access to the organizational unit tree and
5  * caches it in browser session storage.
6  *
7  * Methods include:
8  *   get()  - retrieve OU based on ID or aou object
9  *   list() - retrieve flattened list of OUs
10  *   tree() - retrieve OU as tree
11  *   root() - get aou object representing root of the OU tree
12  *   ancestors() - get ancestors of supplied OU
13  *   descendants() - get descendants of supplied OU
14  * 
15  * TODO more to document
16  * 
17  */
18 angular.module('egCoreMod')
19
20 .factory('egOrg', 
21        ['$q','egEnv','egAuth','egNet','$injector',
22 function($q,  egEnv,  egAuth,  egNet , $injector) { 
23
24     var service = {};
25
26     // org unit settings cache.
27     // This allows the caller to avoid local caches
28     service.cachedSettings = {};
29
30     service.get = function(node_or_id) {
31         if (typeof node_or_id == 'object')
32             return node_or_id;
33         return egEnv.aou.map[node_or_id];
34     };
35
36     service.list = function() {
37         return egEnv.aou.list;
38     };
39
40     service.tree = function() {
41         return egEnv.aou.tree;
42     }
43
44     // get the root OU
45     service.root = function() {
46         return egEnv.aou.list[0];
47     }
48
49     // list of org_unit objects or IDs for ancestors + me
50     service.ancestors = function(node_or_id, as_id) {
51         var node = service.get(node_or_id);
52         if (!node) return [];
53         var nodes = [node];
54         while( (node = service.get(node.parent_ou())))
55             nodes.push(node);
56         if (as_id) 
57             return nodes.map(function(n){return Number(n.id())});
58         return nodes;
59     };
60
61     // tests that a node can have users
62     service.CanHaveUsers = function(node_or_id) {
63         return service
64             .get(node_or_id)
65             .ou_type()
66             .can_have_users() == 't';
67     }
68
69     // tests that a node can have volumes
70     service.CanHaveVolumes = function(node_or_id) {
71         return service
72             .get(node_or_id)
73             .ou_type()
74             .can_have_vols() == 't';
75     }
76
77     // list of org_unit objects  or IDs for me + descendants
78     service.descendants = function(node_or_id, as_id) {
79         var node = service.get(node_or_id);
80         if (!node) return [];
81         var nodes = [];
82         function descend(n) {
83             nodes.push(n);
84             angular.forEach(n.children(), descend);
85         }
86         descend(node);
87         if (as_id) 
88             return nodes.map(function(n){return Number(n.id())});
89         return nodes;
90     }
91
92     // list of org_unit objects or IDs for ancestors + me + descendants
93     service.fullPath = function(node_or_id, as_id) {
94         var list = service.ancestors(node_or_id).concat(
95           service.descendants(node_or_id).slice(1));
96         if (as_id) 
97             return list.map(function(n){return Number(n.id())});
98         return list;
99     }
100
101     var egLovefield = null;
102     // returns a promise, resolved with a hash of setting name =>
103     // setting value for the selected org unit.  Org unit defaults to 
104     // auth workstation org unit.
105     service.settings = function(names, ou_id) {
106         if (!egLovefield) {
107             egLovefield = $injector.get('egLovefield');
108         }
109
110         // allow non-array
111         if (!angular.isArray(names)) names = [names];
112
113         if (lf.isOffline) {
114             // for offline, just use whatever we have managed to cache,
115             // even if the value is expired (since we can't refresh it
116             // from the server)
117             return egLovefield.getSettingsCache(names).then(
118                 function(settings) {
119                     var hash = {};
120                     angular.forEach(settings, function (s) {
121                         hash[s.name] = s.value;
122                     });
123                     return $q.when(hash);
124                 },
125                 function() {return $q.when({})} // Not Supported
126             );
127         }
128
129
130         if (!egAuth.user()) return $q.when();
131
132         ou_id = ou_id || egAuth.user().ws_ou();
133         if (ou_id != egAuth.user().ws_ou()) {
134             // we only cache settings for the current working location;
135             // if we have requested settings for some other org unit,
136             // skip the cache and pull settings directly from the server
137             return service.settingsFromServer(names, ou_id);
138         }
139
140         var deferred = $q.defer();
141         
142         var newNames = [];
143         angular.forEach(names, function(name) {
144             if (!angular.isDefined(service.cachedSettings[name]))
145                 // we don't have a value for this setting yet 
146                 newNames.push(name)
147         });
148
149         // only retrieve uncached values
150         names = newNames;
151         if (names.length == 0)
152             return $q.when(service.cachedSettings);
153
154         // get settings from offline cache where possible;
155         // otherwise, get settings from server
156         egLovefield.getSettingsCache(names)
157         .then(function(settings) {
158
159             // populate values from offline cache
160             angular.forEach(settings, function (s) {
161                 service.cachedSettings[s.name] = s.value;
162             });
163
164             // check if any requested settings were not in offline cache
165             var uncached = [];
166             angular.forEach(names, function(name) {
167                 if (!angular.isDefined(service.cachedSettings[name]))
168                     uncached.push(name);
169             });
170
171             if (uncached.length == 0) {
172                 // all requested settings were in the offline cache already
173                 deferred.resolve(service.cachedSettings);
174             } else {
175                 // cache was missing some settings; grab those from the server
176                 service.settingsFromServer(uncached, ou_id)
177                 .then(function() {
178                     deferred.resolve(service.cachedSettings);
179                 });
180             }
181         });
182         return deferred.promise;
183     }
184
185     service.settingsFromServer = function(names, ou_id) {
186         if (!egLovefield) {
187             egLovefield = $injector.get('egLovefield');
188         }
189
190         // allow non-array
191         if (!angular.isArray(names)) names = [names];
192
193         var deferred = $q.defer();
194         ou_id = ou_id || egAuth.user().ws_ou();
195         var here = (ou_id == egAuth.user().ws_ou());
196
197         egNet.request(
198             'open-ils.actor',
199             'open-ils.actor.ou_setting.ancestor_default.batch',
200             ou_id, names, egAuth.token()
201         ).then(function(blob) {
202             var settings = {};
203             angular.forEach(blob, function(val, key) {
204                 // val is either null or a structure containing the value
205                 settings[key] = val ? val.value : null;
206                 if (here) service.cachedSettings[key] = settings[key];
207             });
208
209             return egLovefield.setSettingsCache(settings).then(
210                 function() {
211                     // resolve with cached settings if 'here', since 'settings'
212                     // will only contain settings we had to retrieve
213                     deferred.resolve(here ? service.cachedSettings : settings);
214                 },
215                 function() {
216                     deferred.resolve(here ? service.cachedSettings : settings);
217                 }
218             );
219         });
220         return deferred.promise;
221     }
222
223     return service;
224 }]);
225