]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/xul/staff_client/server/admin/closed_dates.js
LP#1705524: Honor timezone of the acting library where appropriate
[Evergreen.git] / Open-ILS / xul / staff_client / server / admin / closed_dates.js
1 dojo.require('fieldmapper.AutoIDL');
2 dojo.require('fieldmapper.Fieldmapper');
3 dojo.require('fieldmapper.OrgUtils');
4 dojo.require('openils.Event');
5
6 var myPackageDir = 'open_ils_staff_client'; var IAMXUL = true; var g = {};
7 var FETCH_CLOSED_DATES    = 'open-ils.actor:open-ils.actor.org_unit.closed.retrieve.all';
8 var FETCH_CLOSED_DATE    = 'open-ils.actor:open-ils.actor.org_unit.closed.retrieve';
9 var CREATE_CLOSED_DATE    = 'open-ils.actor:open-ils.actor.org_unit.closed.create';
10 var DELETE_CLOSED_DATE    = 'open-ils.actor:open-ils.actor.org_unit.closed.delete';
11
12 var cdRowTemplate;
13 var cdAllDayTemplate;
14 var cdAllMultiDayTemplate;
15
16 var cdTbody;
17 var cdDateCache = {};
18 var orgTZ = {};
19
20 var selectedStart;
21 var selectedEnd;
22
23 var cdBaseOrg;
24
25
26 var myPerms = [ 
27     'actor.org_unit.closed_date.delete',
28     'actor.org_unit.closed_date.create',
29     ];
30
31 function cdEditorInit() {
32
33     /* set the various template rows */
34     cdTbody = $('cd_tbody');
35     cdRowTemplate                    = cdTbody.removeChild($('cd_row'));
36     cdAllDayTemplate                = cdTbody.removeChild($('cd_allday_row'));
37     cdAllMultiDayTemplate        = cdTbody.removeChild($('cd_allmultiday_row'));
38
39     cdInitCals();
40
41     fetchUser();
42     $('cd_user').appendChild(text(USER.usrname()));
43
44     setTimeout( 
45         function() { 
46             fetchHighestPermOrgs( SESSION, USER.id(), myPerms );
47             cdBuildOrgs();
48             cdDrawRange();
49         }, 
50         20 
51     );
52 }
53
54 function cdCurrentOrg() {
55     var selector = $('cd_orgs');
56     return getSelectorVal(selector);
57 }
58
59 function cdBuildOrgs() {
60     var org = findOrgUnit(PERMS['actor.org_unit.closed_date.create']);
61     if( !org || org == -1 ) org = findOrgUnit(USER.ws_ou());
62     var type = findOrgType(org.ou_type()) ;
63
64     var selector = $('cd_orgs');
65     buildOrgSel(selector, org, type.depth());
66     if(!type.can_have_users()) selector.options[0].disabled = true;
67
68
69     selector.onchange = function() { cdDrawRange(); };
70
71     cdBaseOrg = org;
72
73     if( cdBaseOrg.children() && cdBaseOrg.children().length > 0 )
74         unHideMe($('cd_apply_all_div'));
75
76     var gotoOrg = USER.ws_ou();
77     if( ! setSelector( selector, gotoOrg ) ) {
78         gotoOrg = USER.home_ou();
79         setSelector( selector, gotoOrg );
80     }
81
82     var neworg = findOrgUnit(PERMS['actor.org_unit.closed_date.create']);
83     if(!neworg || neworg == -1 || !orgIsMine(neworg, findOrgUnit(cdCurrentOrg()))) {
84         $('cd_new_allday').disabled = true;
85         $('cd_new_multiday').disabled = true;
86         $('cd_new').disabled = true;
87     }
88
89     return gotoOrg;
90 }
91
92 function cdInitCals() {
93
94     Calendar.setup({
95         inputField  : "cd_edit_allday_start_date",
96         ifFormat    : "%Y-%m-%d",
97         button      : "cd_edit_allday_start_date_img",
98         align       : "Tl",
99         singleClick : true
100     });
101
102     Calendar.setup({
103         inputField  : "cd_edit_allmultiday_start_date",
104         ifFormat    : "%Y-%m-%d",
105         button      : "cd_edit_allmultiday_start_date_img",
106         align       : "Tl",
107         singleClick : true
108     });
109
110     Calendar.setup({
111         inputField  : "cd_edit_allmultiday_end_date",
112         ifFormat    : "%Y-%m-%d",
113         button      : "cd_edit_allmultiday_end_date_img",
114         align       : "Tl",
115         singleClick : true
116     });
117
118     Calendar.setup({
119         inputField  : "cd_edit_end_date",
120         ifFormat    : "%Y-%m-%d",
121         button      : "cd_edit_end_date_img",
122         align       : "Tl",
123         singleClick : true
124     });
125
126     Calendar.setup({
127         inputField  : "cd_edit_start_date",
128         ifFormat    : "%Y-%m-%d",
129         button      : "cd_edit_start_date_img",
130         align       : "Tl",
131         singleClick : true
132     });
133
134
135 }
136
137 function cdDrawRange( start, end, alertSuccess ) {
138     start = (start) ? start : new Date().getYear() + 1899 + '-01-01'; /* include last year's closed info for comparison */
139     end = (end) ? end : '3001-01-01';
140
141     if(alertSuccess) alertId('cd_update_success');
142
143     selectedStart = start;
144     selectedEnd = end;
145
146     var req = new Request(
147         FETCH_CLOSED_DATES, SESSION, 
148         {
149             orgid            : cdCurrentOrg(),
150             start_date    : start,
151             end_date        : end,
152             idlist        : 0
153         }
154     );
155
156     req.callback( cdBuild );
157     req.send();  
158 }
159
160 /* adds one row in the display table per date */
161 function cdBuild(r) {
162     var dates = r.getResultObject();
163     removeChildren(cdTbody);
164     for( var d = 0; d < dates.length; d++ ) {
165         var date = dates[d];
166         // super-closure!
167         (function (date) {
168             cdGetTZ(date.org_unit(), function () {
169                 var row = cdBuildRow( date );
170                 cdTbody.appendChild(row);
171             })
172         })(date);
173     }
174 }
175
176 function cdDateToHours(date, org) {
177     var date_obj = moment(date).tz(orgTZ[org]);
178     var hrs = date_obj.hours();
179     var mins = date_obj.minutes();
180     // wee, strftime
181     if (hrs < 10) hrs = '0' + hrs;
182     if (mins < 10) mins = '0' + mins;
183     return hrs + ':' + mins;
184 }
185
186 function cdDateToDate(date, org) {
187     var date_obj = moment(date).tz(orgTZ[org]);
188     return date_obj.format('YYYY-MM-DD');
189 }
190
191 function cdGetTZ(org, callback) {
192     if (orgTZ[org]) {
193         if (callback) callback();
194         return;
195     }
196
197     fieldmapper.standardRequest(
198         [   'open-ils.actor',
199             'open-ils.actor.ou_setting.ancestor_default.batch'],
200         {   async: true,
201             params: [org, ['lib.timezone'], SESSION],
202             oncomplete: function(r) {
203                 var data = r.recv().content();
204                 if(e = openils.Event.parse(data))
205                     return alert(e);
206                 orgTZ[org] = data['lib.timezone'].value || OpenSRF.tz;
207                 if (callback) callback();
208             }
209         }
210     );
211 }
212
213
214 /* fleshes a single date */
215 function cdBuildRow( date ) {
216
217     cdDateCache[date.id()] = date;
218
219     var sh = cdDateToHours(date.close_start(), date.org_unit());
220     var sd = cdDateToDate(date.close_start(), date.org_unit());
221     var eh = cdDateToHours(date.close_end(), date.org_unit());
222     var ed = cdDateToDate(date.close_end(), date.org_unit());
223
224     var row;
225     var flesh = false;
226
227     if( isTrue(date.full_day()) ) {
228
229         if( !isTrue(date.multi_day()) ) {
230             row = cdAllDayTemplate.cloneNode(true);
231             $n(row, 'start_date').appendChild(text(sd));
232
233         } else {
234             row = cdAllMultiDayTemplate.cloneNode(true);
235             $n(row, 'start_date').appendChild(text(sd));
236             $n(row, 'end_date').appendChild(text(ed));
237         }
238
239     } else {
240
241         row = cdRowTemplate.cloneNode(true);    
242         cdEditFleshRow(row, date);
243     }
244
245     $n(row,'delete').onclick = function() { cdDelete(row, date); };
246     $n(row, 'note').appendChild(text(date.reason()));
247
248     /* if we don't have delete perms for this location, disable the button */
249     var delorg = findOrgUnit(PERMS['actor.org_unit.closed_date.delete']);
250     if(!orgIsMine(delorg, findOrgUnit(cdCurrentOrg()))) $n(row,'delete').disabled = true;
251
252     return row;
253 }
254
255 function cdEditFleshRow(row, date) {
256     $n(row, 'start_time').appendChild(text(cdDateToHours(date.close_start(), date.org_unit())));
257     $n(row, 'start_date').appendChild(text(cdDateToDate(date.close_start(), date.org_unit())));
258     $n(row, 'end_time').appendChild(text(cdDateToHours(date.close_end(), date.org_unit())));
259     $n(row, 'end_date').appendChild(text(cdDateToDate(date.close_end(), date.org_unit())));
260 }
261
262
263 function cdShowEditRow(id) {
264     cdCancelEdit();
265     unHideMe($(id));
266     unHideMe($('cd_edit_submit'));
267     unHideMe($('cd_edit_note_row'));
268 }
269
270 function cdCancelEdit() {
271     hideMe($('cd_edit_row'));
272     hideMe($('cd_edit_allday_row'));
273     hideMe($('cd_edit_allmultiday_row'));
274     hideMe($('cd_edit_submit'));
275     hideMe($('cd_edit_note_row'));
276 }
277
278
279
280
281 function cdDelete(row, date) {
282     if(!confirmId('cd_confirm_delete')) return;
283     var req = new Request(DELETE_CLOSED_DATE, SESSION, date.id() );
284     req.callback(
285         function(r) {
286             var res = r.getResultObject();
287             if( checkILSEvent(res) ) alertILSEvent(res);
288             cdDrawRange(selectedStart, selectedEnd, true);
289         }
290     )
291     req.send();
292 }
293
294
295 function cdVerifyDate(d) {
296     return d && d.match(/\d{4}-\d{2}-\d{2}/);
297 }
298
299 function cdVerifyTime(t) {
300     return t && t.match(/\d{2}:\d{2}:\d{2}/);
301 }
302
303 function cdDateStrToDate( str, org, callback ) {
304     if (!org) org = cdCurrentOrg();
305
306     if (callback) { // async mode
307         if (!orgTZ[org]) { // fetch then call again
308             return cdGetTZ(org, function () {
309                 cdDateStrToDate( str, org, callback );
310             });
311         } else {
312             var d = cdDateStrToDate( str, org );
313             return callback(d);
314         }
315     }
316
317     var date;
318     if (orgTZ[org]) {
319         date = moment(new Date()).tz(orgTZ[org]);
320     } else {
321          date = moment(new Date());
322     }
323
324     var data = str.replace(/\s+/, 'T').split(/T/);
325
326     var year = data[0];
327     var time = data[1];
328
329     if(!cdVerifyDate(year)) return alertId('cd_invalid_date');
330     if(!cdVerifyTime(time)) return alertId('cd_invalid_time');
331
332     var yeardata = year.split(/-/);
333     var timedata = time.split(/:/);
334     
335     /*  seed the date with day = 1, which is a valid day for any month.  
336         this prevents automatic date correction by the date code for days that 
337         fall outside of the current or target month */
338     date.date(1);
339
340     date.year(new Number(yeardata[0]));
341     date.month(new Number(yeardata[1]) - 1);
342     date.date(new Number(yeardata[2]));
343
344     date.hour(new Number(timedata[0]));
345     date.minute(new Number(timedata[1]));
346     date.second(new Number(timedata[2]));
347
348     return date;
349 }
350
351 function cdNew() {
352
353     var start;
354     var end;
355     var full_day = 0;
356     var multi_day = 0;
357
358     if( ! $('cd_edit_allday_row').className.match(/hide_me/) ) {
359
360         var date = $('cd_edit_allday_start_date').value;
361
362         start = cdDateStrToDate(date + 'T00:00:00');
363         end = cdDateStrToDate(date + 'T23:59:59');
364         full_day = 1;
365
366     } else if( ! $('cd_edit_allmultiday_row').className.match(/hide_me/) ) {
367
368         var sdate = $('cd_edit_allmultiday_start_date').value;
369         var edate = $('cd_edit_allmultiday_end_date').value;
370         start = cdDateStrToDate(sdate + 'T00:00:00');
371         end = cdDateStrToDate(edate + 'T23:59:59');
372         full_day = 1;
373         multi_day = 1;
374
375     } else {
376
377         var sdate = $('cd_edit_start_date').value;
378         var edate = $('cd_edit_end_date').value;
379         var stime;
380         var etime;
381
382         if($('cd_edit_start_time_allday').checked) {
383             stime = '00:00';
384         } else {
385             stime = $('cd_edit_start_time').value;
386         }
387
388         stime += ':00';
389
390         if($('cd_edit_end_time_allday').checked) {
391             etime = '23:59:59';
392         } else {
393             etime = $('cd_edit_end_time').value;
394             etime += ':00';
395         }
396
397         start = cdDateStrToDate(sdate + 'T' + stime);
398         end = cdDateStrToDate(edate + 'T' + etime);
399     }
400
401     if (end.unix() < start.unix()) {
402         alertId('cd_invalid_date_span');
403         return;
404     }
405
406     cdCreate(start, end, $('cd_edit_note').value, full_day, multi_day);
407 }
408
409 function cdCreate(start, end, note, full_day, multi_day) {
410
411     if( $('cd_apply_all').checked ) {
412         var list = cdGetOrgList();
413         for( var o = 0; o < list.length; o++ ) {
414             var id = list[o].id();
415             cdCreateOne( id, start, end, note, full_day, multi_day, (id == cdCurrentOrg()) );
416         }
417
418     } else {
419
420         cdCreateOne( cdCurrentOrg(), start, end, note, full_day, multi_day, true );
421     }
422 }
423
424 function cdGetOrgList(org) {
425     if(!org) org = cdBaseOrg;
426
427     var list = [];
428     var type = findOrgType(org.ou_type()) ;
429     if( type.can_have_users() ) list.push(org);
430
431     if( org.children() ) {
432         for( var i = 0; i < org.children().length; i++ ) {
433             var child = org.children()[i];
434             if( child ) {
435                 var l = cdGetOrgList(child);
436                 for( var j = 0; j < l.length; j++ )
437                     list.push(l[j]);
438             }
439         }
440     }
441
442     return list;
443 }
444
445 function cdCreateOne( org, start, end, note, full_day, multi_day, refresh ) {
446     var date = new aoucd();
447
448     // force TZ normalization
449     cdDateStrToDate(start.format('YYYY-MM-DD HH:mm:ss'), org, function (s) {
450         start = s;
451         cdDateStrToDate(end.format('YYYY-MM-DD HH:mm:ss'), org, function (e) {
452             end = e;
453
454             date.close_start(start.toISOString());
455             date.close_end(end.toISOString());
456             date.org_unit(org);
457             date.reason(note);
458             date.full_day(full_day);
459             date.multi_day(multi_day);
460         
461             var req = new Request(CREATE_CLOSED_DATE, SESSION, date);
462             req.callback(
463                 function(r) {
464                     var res = r.getResultObject();
465                     if( checkILSEvent(res) ) alertILSEvent(res);
466                     if(refresh) cdDrawRange(selectedStart, selectedEnd, true);
467                 }
468             );
469             req.send();
470         });
471     });
472
473 }
474