]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Open-ILS/xul/staff_client/server/admin/closed_dates.js
LP#1705524 Closed dates editor handles no timezones
[working/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                 if (data['lib.timezone'] && data['lib.timezone'].value) {
207                     orgTZ[org] = data['lib.timezone'].value;
208                 } else {
209                     orgTZ[org] = OpenSRF.tz;
210                 }
211                 if (callback) callback();
212             }
213         }
214     );
215 }
216
217
218 /* fleshes a single date */
219 function cdBuildRow( date ) {
220
221     cdDateCache[date.id()] = date;
222
223     var sh = cdDateToHours(date.close_start(), date.org_unit());
224     var sd = cdDateToDate(date.close_start(), date.org_unit());
225     var eh = cdDateToHours(date.close_end(), date.org_unit());
226     var ed = cdDateToDate(date.close_end(), date.org_unit());
227
228     var row;
229     var flesh = false;
230
231     if( isTrue(date.full_day()) ) {
232
233         if( !isTrue(date.multi_day()) ) {
234             row = cdAllDayTemplate.cloneNode(true);
235             $n(row, 'start_date').appendChild(text(sd));
236
237         } else {
238             row = cdAllMultiDayTemplate.cloneNode(true);
239             $n(row, 'start_date').appendChild(text(sd));
240             $n(row, 'end_date').appendChild(text(ed));
241         }
242
243     } else {
244
245         row = cdRowTemplate.cloneNode(true);    
246         cdEditFleshRow(row, date);
247     }
248
249     $n(row,'delete').onclick = function() { cdDelete(row, date); };
250     $n(row, 'note').appendChild(text(date.reason()));
251
252     /* if we don't have delete perms for this location, disable the button */
253     var delorg = findOrgUnit(PERMS['actor.org_unit.closed_date.delete']);
254     if(!orgIsMine(delorg, findOrgUnit(cdCurrentOrg()))) $n(row,'delete').disabled = true;
255
256     return row;
257 }
258
259 function cdEditFleshRow(row, date) {
260     $n(row, 'start_time').appendChild(text(cdDateToHours(date.close_start(), date.org_unit())));
261     $n(row, 'start_date').appendChild(text(cdDateToDate(date.close_start(), date.org_unit())));
262     $n(row, 'end_time').appendChild(text(cdDateToHours(date.close_end(), date.org_unit())));
263     $n(row, 'end_date').appendChild(text(cdDateToDate(date.close_end(), date.org_unit())));
264 }
265
266
267 function cdShowEditRow(id) {
268     cdCancelEdit();
269     unHideMe($(id));
270     unHideMe($('cd_edit_submit'));
271     unHideMe($('cd_edit_note_row'));
272 }
273
274 function cdCancelEdit() {
275     hideMe($('cd_edit_row'));
276     hideMe($('cd_edit_allday_row'));
277     hideMe($('cd_edit_allmultiday_row'));
278     hideMe($('cd_edit_submit'));
279     hideMe($('cd_edit_note_row'));
280 }
281
282
283
284
285 function cdDelete(row, date) {
286     if(!confirmId('cd_confirm_delete')) return;
287     var req = new Request(DELETE_CLOSED_DATE, SESSION, date.id() );
288     req.callback(
289         function(r) {
290             var res = r.getResultObject();
291             if( checkILSEvent(res) ) alertILSEvent(res);
292             cdDrawRange(selectedStart, selectedEnd, true);
293         }
294     )
295     req.send();
296 }
297
298
299 function cdVerifyDate(d) {
300     return d && d.match(/\d{4}-\d{2}-\d{2}/);
301 }
302
303 function cdVerifyTime(t) {
304     return t && t.match(/\d{2}:\d{2}:\d{2}/);
305 }
306
307 function cdDateStrToDate( str, org, callback ) {
308     if (!org) org = cdCurrentOrg();
309
310     if (callback) { // async mode
311         if (!orgTZ[org]) { // fetch then call again
312             return cdGetTZ(org, function () {
313                 cdDateStrToDate( str, org, callback );
314             });
315         } else {
316             var d = cdDateStrToDate( str, org );
317             return callback(d);
318         }
319     }
320
321     var date;
322     if (orgTZ[org]) {
323         date = moment(new Date()).tz(orgTZ[org]);
324     } else {
325          date = moment(new Date());
326     }
327
328     var data = str.replace(/\s+/, 'T').split(/T/);
329
330     var year = data[0];
331     var time = data[1];
332
333     if(!cdVerifyDate(year)) return alertId('cd_invalid_date');
334     if(!cdVerifyTime(time)) return alertId('cd_invalid_time');
335
336     var yeardata = year.split(/-/);
337     var timedata = time.split(/:/);
338     
339     /*  seed the date with day = 1, which is a valid day for any month.  
340         this prevents automatic date correction by the date code for days that 
341         fall outside of the current or target month */
342     date.date(1);
343
344     date.year(new Number(yeardata[0]));
345     date.month(new Number(yeardata[1]) - 1);
346     date.date(new Number(yeardata[2]));
347
348     date.hour(new Number(timedata[0]));
349     date.minute(new Number(timedata[1]));
350     date.second(new Number(timedata[2]));
351
352     return date;
353 }
354
355 function cdNew() {
356
357     var start;
358     var end;
359     var full_day = 0;
360     var multi_day = 0;
361
362     if( ! $('cd_edit_allday_row').className.match(/hide_me/) ) {
363
364         var date = $('cd_edit_allday_start_date').value;
365
366         start = cdDateStrToDate(date + 'T00:00:00');
367         end = cdDateStrToDate(date + 'T23:59:59');
368         full_day = 1;
369
370     } else if( ! $('cd_edit_allmultiday_row').className.match(/hide_me/) ) {
371
372         var sdate = $('cd_edit_allmultiday_start_date').value;
373         var edate = $('cd_edit_allmultiday_end_date').value;
374         start = cdDateStrToDate(sdate + 'T00:00:00');
375         end = cdDateStrToDate(edate + 'T23:59:59');
376         full_day = 1;
377         multi_day = 1;
378
379     } else {
380
381         var sdate = $('cd_edit_start_date').value;
382         var edate = $('cd_edit_end_date').value;
383         var stime;
384         var etime;
385
386         if($('cd_edit_start_time_allday').checked) {
387             stime = '00:00';
388         } else {
389             stime = $('cd_edit_start_time').value;
390         }
391
392         stime += ':00';
393
394         if($('cd_edit_end_time_allday').checked) {
395             etime = '23:59:59';
396         } else {
397             etime = $('cd_edit_end_time').value;
398             etime += ':00';
399         }
400
401         start = cdDateStrToDate(sdate + 'T' + stime);
402         end = cdDateStrToDate(edate + 'T' + etime);
403     }
404
405     if (end.unix() < start.unix()) {
406         alertId('cd_invalid_date_span');
407         return;
408     }
409
410     cdCreate(start, end, $('cd_edit_note').value, full_day, multi_day);
411 }
412
413 function cdCreate(start, end, note, full_day, multi_day) {
414
415     if( $('cd_apply_all').checked ) {
416         var list = cdGetOrgList();
417         for( var o = 0; o < list.length; o++ ) {
418             var id = list[o].id();
419             cdCreateOne( id, start, end, note, full_day, multi_day, (id == cdCurrentOrg()) );
420         }
421
422     } else {
423
424         cdCreateOne( cdCurrentOrg(), start, end, note, full_day, multi_day, true );
425     }
426 }
427
428 function cdGetOrgList(org) {
429     if(!org) org = cdBaseOrg;
430
431     var list = [];
432     var type = findOrgType(org.ou_type()) ;
433     if( type.can_have_users() ) list.push(org);
434
435     if( org.children() ) {
436         for( var i = 0; i < org.children().length; i++ ) {
437             var child = org.children()[i];
438             if( child ) {
439                 var l = cdGetOrgList(child);
440                 for( var j = 0; j < l.length; j++ )
441                     list.push(l[j]);
442             }
443         }
444     }
445
446     return list;
447 }
448
449 function cdCreateOne( org, start, end, note, full_day, multi_day, refresh ) {
450     var date = new aoucd();
451
452     // force TZ normalization
453     cdDateStrToDate(start.format('YYYY-MM-DD HH:mm:ss'), org, function (s) {
454         start = s;
455         cdDateStrToDate(end.format('YYYY-MM-DD HH:mm:ss'), org, function (e) {
456             end = e;
457
458             date.close_start(start.toISOString());
459             date.close_end(end.toISOString());
460             date.org_unit(org);
461             date.reason(note);
462             date.full_day(full_day);
463             date.multi_day(multi_day);
464         
465             var req = new Request(CREATE_CLOSED_DATE, SESSION, date);
466             req.callback(
467                 function(r) {
468                     var res = r.getResultObject();
469                     if( checkILSEvent(res) ) alertILSEvent(res);
470                     if(refresh) cdDrawRange(selectedStart, selectedEnd, true);
471                 }
472             );
473             req.send();
474         });
475     });
476
477 }
478