]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Open-ILS/web/reports/oils_rpt_report_editor.js
5db7a33fb5b600cacfa2ae97cbf981c99104e28d
[working/Evergreen.git] / Open-ILS / web / reports / oils_rpt_report_editor.js
1 dojo.requireLocalization("openils.reports", "reports");
2
3 var rpt_strings = dojo.i18n.getLocalization("openils.reports", "reports");
4
5 oilsRptSetSubClass('oilsRptReportEditor', 'oilsRptObject');
6 var oilsRptReportEditorFolderTree;
7
8 function oilsRptReportEditor(rptObject, folderWindow, readonly) {
9         var tmpl = rptObject.templateObject;
10         var rpt = rptObject.reportObject;
11         this.folderWindow = folderWindow;
12     this.readonly = readonly;
13
14         this.template = tmpl;
15         this.report = rpt;
16
17     if (rpt && rpt.runs() && rpt.runs().length)
18         this.last_run = rpt.runs()[rpt.runs().length - 1];
19
20         appendClear(DOM.oils_rpt_report_editor_template_name, tmpl.name());
21         appendClear(DOM.oils_rpt_report_editor_template_creator, tmpl.owner().usrname());
22         appendClear(DOM.oils_rpt_report_editor_template_description, tmpl.description());
23
24     hideMe(DOM.oils_rpt_report_editor_template_doc_url_row);
25     if (rptObject.def.version >= 4) {
26         if (URL = rptObject.def.doc_url) {
27             var link = DOM.oils_rpt_report_editor_template_doc_url;
28             link.innerHTML = URL;
29             if (typeof xulG == 'undefined') {
30                 link.setAttribute('href', URL);
31                 link.setAttribute('target', '_blank');
32             } else {
33                 link.onclick = function() {xulG.new_tab(URL); return false}
34             }
35             unHideMe(DOM.oils_rpt_report_editor_template_doc_url_row);
36         }
37     }
38     
39     appendClear(DOM.oils_rpt_report_editor_cols,'');
40         iterate(rptObject.def.select, 
41                 function(i) {
42                         if(i)
43                                 DOM.oils_rpt_report_editor_cols.appendChild(text(i.alias));
44                 if (i.field_doc) {
45                                     DOM.oils_rpt_report_editor_cols.appendChild(
46                         elem('span', {'class':'oils_rpt_field_hint'}, i.field_doc));
47                 }
48                                 DOM.oils_rpt_report_editor_cols.appendChild(document.createElement('br'));
49                 }
50         );
51
52 /*
53 oils_rpt_editor_pivot_label
54 oils_rpt_editor_pivot_data
55 */
56
57     var hasAgg = false;
58     iterate(rptObject.def.select, 
59         function(i) {
60             if(OILS_RPT_TRANSFORMS[i.column.transform].aggregate) 
61                 hasAgg = true; 
62         }
63     );
64
65     while(DOM.oils_rpt_editor_pivot_label.getElementsByTagName('option').length > 1)
66         DOM.oils_rpt_editor_pivot_label.removeChild(DOM.oils_rpt_editor_pivot_label.lastChild);
67
68     while(DOM.oils_rpt_editor_pivot_data.lastChild)
69         DOM.oils_rpt_editor_pivot_data.removeChild(DOM.oils_rpt_editor_pivot_data.lastChild);
70
71     if(hasAgg) {
72         unHideMe(DOM.oils_rpt_editor_pivot_label_row);
73         unHideMe(DOM.oils_rpt_editor_pivot_data_row);
74
75         for(var i in rptObject.def.select) {
76             var col = rptObject.def.select[i];
77             if(OILS_RPT_TRANSFORMS[col.column.transform].aggregate) 
78                insertSelectorVal(DOM.oils_rpt_editor_pivot_data, -1, col.alias, parseInt(i)+1);
79             else
80                insertSelectorVal(DOM.oils_rpt_editor_pivot_label, -1, col.alias, parseInt(i)+1);
81         }
82
83     } else {
84         hideMe(DOM.oils_rpt_editor_pivot_label_row);
85         hideMe(DOM.oils_rpt_editor_pivot_data_row);
86     }
87  
88
89         if( rpt ) {
90         // populate the report edit form w/ report data
91
92         this.orig_rpt_name = rpt.name();
93
94                 DOM.oils_rpt_report_editor_name.value = rpt.name();
95                 DOM.oils_rpt_report_editor_name.onchange(); // validation
96                 DOM.oils_rpt_report_editor_desc.value = rpt.description();
97
98         if (rpt.recur() == 't') {
99             DOM.oils_rpt_recur.checked = true;
100             DOM.oils_rpt_recur.onclick(); // enable recurrance selector
101         }
102
103         if (rpt.recurrence()) {
104             var parts = rpt.recurrence().split(/ /);
105             setSelector(DOM.oils_rpt_recur_count, parts[0]);
106             setSelector(DOM.oils_rpt_recur_interval_type, parts[1]);
107         }
108
109         if (rpt.data()) { 
110             var rpt_data = JSON2js(rpt.data());
111             if (rpt_data.__pivot_label)
112                 setSelector(DOM.oils_rpt_editor_pivot_label, rpt_data.__pivot_label);
113             if (rpt_data.__pivot_data)
114                 setSelector(DOM.oils_rpt_editor_pivot_data, rpt_data.__pivot_data);
115         }
116
117         if (run = this.last_run) {
118                     DOM.oils_rpt_report_editor_name.disabled = true;
119                     DOM.oils_rpt_report_editor_desc.disabled = true;
120             DOM.oils_rpt_format_csv.checked = run.csv_format() == 't';
121             DOM.oils_rpt_format_excel.checked = run.excel_format() == 't';
122             DOM.oils_rpt_format_html.checked = run.html_format() == 't';
123             DOM.oils_rpt_format_chart_bar.checked = run.chart_bar() == 't';
124             DOM.oils_rpt_format_chart_line.checked = run.chart_line() == 't';
125             DOM.oils_rpt_param_editor_sched_email.value = run.email();
126
127             if (run.run_time()) {
128                 DOM.oils_rpt_report_editor_run_now.checked = false;
129                 DOM.oils_rpt_report_editor_schedule.checked = true;
130                 DOM.oils_rpt_param_editor_sched_start_date.disabled = false;
131                 DOM.oils_rpt_param_editor_sched_start_hour.disabled = false;
132
133                 if (new Date(Date.parse(run.run_time())) < new Date()) {
134                     // editing a report with a past-tense run time
135                     // clear the value so the user will have to edit
136                     DOM.oils_rpt_param_editor_sched_start_date.value = mkYearMonDay();
137                 } else {
138                     DOM.oils_rpt_param_editor_sched_start_date.value = 
139                         run.run_time().match(/(\d\d\d\d-\d\d-\d\d)/)[1]
140                     setSelector(
141                         DOM.oils_rpt_param_editor_sched_start_hour,
142                         run.run_time().match(/T(\d\d:\d\d)/)[1]
143                     );
144                 }
145             } else {
146                 DOM.oils_rpt_param_editor_sched_start_date.value = mkYearMonDay();
147             }
148         }
149         }
150
151     if (this.readonly) {
152         DOM.oils_rpt_report_editor_name.disabled = true;
153         DOM.oils_rpt_report_editor_desc.disabled = true;
154         DOM.oils_rpt_recur.disabled = true;
155         DOM.oils_rpt_recur_count.disabled = true;
156         DOM.oils_rpt_recur_interval_type.disabled = true;
157         DOM.oils_rpt_report_editor_run_now.disabled = true;
158         DOM.oils_rpt_format_csv.disabled = true;
159         DOM.oils_rpt_format_excel.disabled = true;
160         DOM.oils_rpt_format_html.disabled = true;
161         DOM.oils_rpt_format_chart_bar.disabled = true;
162         DOM.oils_rpt_format_chart_line.disabled = true;
163         DOM.oils_rpt_param_editor_sched_email.disabled = true;
164
165         hideMe(DOM.oils_rpt_report_editor_save);
166         hideMe(DOM.oils_rpt_report_editor_save_new);
167         hideMe(DOM.oils_rpt_report_editor_cancel);
168         unHideMe(DOM.oils_rpt_report_editor_exit);
169
170     } else {
171         // these DOM elements are shared across instances
172         // of the UI.  Re-enable everything.
173         DOM.oils_rpt_report_editor_name.disabled = false;
174         DOM.oils_rpt_report_editor_desc.disabled = false;
175         DOM.oils_rpt_recur.disabled = false;
176         DOM.oils_rpt_recur_count.disabled = false;
177         DOM.oils_rpt_recur_interval_type.disabled = false;
178         DOM.oils_rpt_report_editor_run_now.disabled = false;
179         DOM.oils_rpt_format_csv.disabled = false;
180         DOM.oils_rpt_format_excel.disabled = false;
181         DOM.oils_rpt_format_html.disabled = false;
182         DOM.oils_rpt_format_chart_bar.disabled = false;
183         DOM.oils_rpt_format_chart_line.disabled = false;
184         DOM.oils_rpt_param_editor_sched_email.disabled = false;
185         DOM.oils_rpt_report_editor_save.disabled = false;
186
187         unHideMe(DOM.oils_rpt_report_editor_save);
188         unHideMe(DOM.oils_rpt_report_editor_cancel);
189         hideMe(DOM.oils_rpt_report_editor_exit);
190
191     }
192
193     // avoid showing save-as-new for new reports, since the
194     // regular save button acts as save-as-new
195     if (rpt && !this.readonly) {
196         unHideMe(DOM.oils_rpt_report_editor_save_new);
197     } else {
198         hideMe(DOM.oils_rpt_report_editor_save_new);
199     }
200
201         this.paramEditor = new oilsRptParamEditor(
202                 rptObject, DOM.oils_rpt_param_editor_tbody, this.readonly);
203         this.paramEditor.draw();
204
205         removeChildren(DOM.oils_rpt_report_editor_selected_folder);
206         removeChildren(DOM.oils_rpt_output_selected_folder);
207
208         var obj = this;
209         oilsRptBuildFolder(
210                 'report',
211                 DOM.oils_rpt_report_editor_dest_folder,
212                 'oilsRptReportEditorFolderTree',
213                 rpt_strings.REPORT_EDITOR_REPORT_FOLDERS,
214                 function(node) { 
215                         appendClear(DOM.oils_rpt_report_editor_selected_folder, node.folder.name());
216                         obj.selectedFolder = node; 
217         },
218         null,
219         function(node) {
220             // apply the previously selected report folder
221             if (rpt && rpt.folder() == node.folder.id()) {
222                             appendClear(DOM.oils_rpt_report_editor_selected_folder, node.folder.name());
223                             obj.selectedFolder = node; 
224             }
225         }
226     );
227
228         oilsRptBuildFolder(
229                 'output',
230                 DOM.oils_rpt_output_dest_folder,
231                 'oilsRptReportEditorOutputTree',
232                 rpt_strings.REPORT_EDITOR_OUTPUT_FOLDERS,
233                 function(node) { 
234                         appendClear(DOM.oils_rpt_output_selected_folder, node.folder.name());
235                         obj.selectedOutputFolder = node; 
236         },
237         null,
238         function(node) {
239             // apply the previously selected output folder
240             if (obj.last_run && obj.last_run.folder() == node.folder.id()) {
241                             appendClear(DOM.oils_rpt_output_selected_folder, node.folder.name());
242                             obj.selectedOutputFolder = node; 
243             }
244         }
245     );
246
247
248         var obj = this;
249         DOM.oils_rpt_report_editor_save.onclick = function(){obj.save();}
250         DOM.oils_rpt_report_editor_save_new.onclick = function(){obj.save({save_new : true});}
251         DOM.oils_rpt_report_editor_exit.onclick = function(){obj.exit();}
252         DOM.oils_rpt_report_editor_cancel.onclick = function(){obj.exit();}
253
254         DOM.oils_rpt_param_editor_sched_email.value = 
255         this.last_run ? this.last_run.email() : USER.email();
256
257         _debug("fleshing template:\n" + tmpl.name() + '\n' + formatJSON(tmpl.data()));
258 }
259
260
261 // options.save_new : save as a new report, even if we
262 // were editing an exitingn report.
263 //
264 // options.modify_schedule : update the pending schedule
265 // object instead of creating a new one.
266 oilsRptReportEditor.prototype.save = function(options) {
267     if (!options) options = {};
268
269         if(!this.selectedFolder) 
270                 return alert(rpt_strings.REPORT_EDITOR_PROVIDE_FOLDER_ALERT);
271
272         if(!DOM.oils_rpt_report_editor_name.value)
273                 return alert(rpt_strings.REPORT_EDITOR_ENTER_NAME_ALERT);
274
275         if(!this.selectedOutputFolder) 
276                 return alert(rpt_strings.REPORT_EDITOR_PROVIDE_OUTPUT_ALERT);
277
278         var report = this.report;
279
280     if (report && options.save_new) {
281         // user is saving an existing report as a new report.
282         // The new report must have a different name.
283         if (DOM.oils_rpt_report_editor_name.value == this.orig_rpt_name) 
284             return alert(rpt_strings.REPORT_EDITOR_ENTER_NEW_NAME_ALERT);
285
286         report = null;
287     }
288
289     if (!report) {
290         report = new rr();
291         report.isnew(true);
292             report.owner( USER.id() );
293             report.template( this.template.id() );
294     }
295
296         report.folder( this.selectedFolder.folder.id() );
297         report.name( DOM.oils_rpt_report_editor_name.value );
298         report.description( DOM.oils_rpt_report_editor_desc.value );
299         report.recur(this.paramEditor.recur());
300         report.recurrence(this.paramEditor.recurInterval());
301
302         /* collect the param data */
303         var data = {};
304         for( var p in this.paramEditor.params ) {
305                 var par = this.paramEditor.params[p];
306                 _debug("adding report param "+par.key+" to report data");
307                 var val = par.widget.getValue();
308
309                 if(!val || val.length == 0 )
310                         return alertId('oils_rpt_empty_param');
311
312                 if( typeof val == 'object') {
313                         for( var i = i; i < val.length; i++ ) {
314                                 _debug("looking at widget value" + val[i]);
315                                 if( val[i] == '' || val[i] == null ) 
316                                         return alertId('oils_rpt_empty_param');
317                         }
318                 }
319
320                 data[par.key] = val;
321         }
322
323     if(getSelectorVal(DOM.oils_rpt_editor_pivot_data)) {
324         data.__pivot_label = getSelectorVal(DOM.oils_rpt_editor_pivot_label);
325         data.__pivot_data = getSelectorVal(DOM.oils_rpt_editor_pivot_data);
326     }
327
328
329         data = js2JSON(data);
330         _debug("complete report data = "+data);
331         report.data(data);
332
333         _debug("Built report:\n"+js2JSON(report));
334
335
336         var time;
337         if( DOM.oils_rpt_report_editor_run_now.checked ) {
338                 DOM.oils_rpt_report_editor_run_now.checked = false;
339                 time = 'now';
340
341         } else {
342
343                 var dt = DOM.oils_rpt_param_editor_sched_start_date.value;
344                 if(!dt || !dt.match(/^\d{4}-\d{2}-\d{2}$/) ) {
345                         /* for now.. make this better in the future */
346                         alert(rpt_strings.REPORT_EDITOR_INVALID_DATE_ALERT);
347                         return;
348                 }
349                 var hour = getSelectorVal(DOM.oils_rpt_param_editor_sched_start_hour);
350                 time = dt +'T'+hour+':00';
351                 _debug("built run_time "+time);
352         }
353
354     // if the last run has yet to actually start, then we update it
355     // instead of creating a new one.
356     var schedule = options.save_new ? null : this.last_run;
357
358     if (schedule && !schedule.start_time()) {
359         if (!options.modify_schedule) {
360             // warn the user that this action will modify an existing
361             // schedule object if they continue
362             return this.showPendingScheduleDialog();
363         }
364     } else {
365         // no schedules exist or the most recent one has already
366         // started.  Create a new one.
367             schedule = new rs();
368         schedule.isnew(true);
369     }
370
371         schedule.folder(this.selectedOutputFolder.folder.id());
372         schedule.email(DOM.oils_rpt_param_editor_sched_email.value);
373         schedule.run_time(time);
374         schedule.runner(USER.id());
375
376         schedule.excel_format((DOM.oils_rpt_format_excel.checked) ? 't' : 'f');
377         schedule.html_format((DOM.oils_rpt_format_html.checked) ? 't' : 'f');
378         schedule.csv_format((DOM.oils_rpt_format_csv.checked) ? 't' : 'f');
379         //schedule.chart_pie((DOM.oils_rpt_format_chart_pie.checked) ? 't' : 'f');
380         schedule.chart_bar((DOM.oils_rpt_format_chart_bar.checked) ? 't' : 'f');
381         schedule.chart_line((DOM.oils_rpt_format_chart_line.checked) ? 't' : 'f');
382
383         debugFMObject(report);
384         debugFMObject(schedule);
385
386     if (report.isnew()) {
387         this.createReport(report, schedule);
388     } else {
389         this.updateReport(report, schedule);
390     }
391 }
392
393 // Modify an existing report.
394 // Modify or create the schedule depending on isnew()
395 oilsRptReportEditor.prototype.updateReport = function(report, schedule) {
396
397     var this_ = this;
398     function success() {
399         oilsRptAlertSuccess();
400         this_.exit();
401     }
402
403     oilsRptUpdateReport(report, function(ok) {
404         if (!ok) return oilsRptAlertFailure();
405
406         if (schedule.isnew()) {
407
408             var req = new Request(OILS_RPT_CREATE_SCHEDULE, SESSION, schedule);
409             req.callback(function(res) {
410                 if(checkILSEvent(res)) 
411                     return alertILSEvent(res);
412                 success();
413             });
414             req.send()
415
416         } else {
417
418             oilsRptUpdateSchedule(schedule, function(ok2) {
419                 if (ok2) return success();
420                 _debug("schedule update failed " + js2JSON(schedule));
421                 oilsRptAlertFailure();
422             });
423         }
424     });
425 }
426
427 oilsRptReportEditor.prototype.createReport = function(report, schedule) {
428         var obj = this;
429     var folderReq = new Request(OILS_RPT_REPORT_EXISTS, SESSION, report);
430     folderReq.callback(
431         function(r1) {
432             if(r1.getResultObject() == 1) {
433                 alertId('oils_rpt_report_exists');
434                 return;
435             } else {
436                 var req = new Request(OILS_RPT_CREATE_REPORT, SESSION, report, schedule );
437                 req.callback(
438                     function(r) {
439                         var res = r.getResultObject();
440                         if(checkILSEvent(res)) {
441                             alertILSEvent(res);
442                         } else {
443                             if( res && res != '0' ) {
444                                 oilsRptAlertSuccess();
445                                 obj.exit();
446                             }
447                         }
448                     }
449                 );
450                 req.send();
451             }
452         }
453     );
454     folderReq.send();
455 }
456
457 oilsRptReportEditor.prototype.showPendingScheduleDialog = function() {
458     hideMe(DOM.oils_rpt_editor_table);
459     unHideMe(DOM.oils_rpt_editor_sched_confirm);
460
461     function close() {
462         unHideMe(DOM.oils_rpt_editor_table);
463         hideMe(DOM.oils_rpt_editor_sched_confirm);
464     }
465
466     var this_ = this;
467     DOM.oils_rpt_report_editor_sched_apply.onclick = function() {
468         close();
469         this_.save({modify_schedule : true});
470     }
471
472     DOM.oils_rpt_report_editor_sched_asnew.onclick = function() {
473
474         if (DOM.oils_rpt_report_editor_name.value == this_.orig_rpt_name) {
475             // user is saving as new but has not yet modified the name
476             // Prompt for a new name, then udpate the name entry so save() 
477             // will see it.  Don't let them escape until they comply.
478             var new_name;
479             while (true) { 
480
481                 new_name = prompt(
482                     rpt_strings.REPORT_EDITOR_ENTER_NEW_NAME_ALERT, 
483                     this_.orig_rpt_name
484                 );
485                 
486                 if (new_name && new_name != this_.orig_rpt_name)
487                     break;
488             }
489
490             DOM.oils_rpt_report_editor_name.value = new_name;
491         } 
492
493         close();
494         this_.save({save_new : true})
495     }
496     DOM.oils_rpt_report_editor_sched_cancel.onclick = close;
497 }
498
499
500 oilsRptReportEditor.prototype.exit = function() {
501     unHideMe(DOM.oils_rpt_folder_window_contents_table);                   
502     unHideMe(DOM.oils_rpt_folder_table_right_td);
503     hideMe(DOM.oils_rpt_folder_table_alt_td);
504     hideMe(DOM.oils_rpt_editor_div);
505 }