]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Open-ILS/web/reports/oils_rpt_report_editor.js
5bc5e89ef93007f9d4a2dd31e8100612814965f4
[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_schedule.checked = true;
129                 if (new Date(Date.parse(run.run_time())) < new Date()) {
130                     // editing a report with a past-tense run time
131                     // clear the value so the user will have to edit
132                     DOM.oils_rpt_param_editor_sched_start_date.value = '';
133                 } else {
134                     DOM.oils_rpt_param_editor_sched_start_date.value = 
135                         run.run_time().match(/(\d\d\d\d-\d\d-\d\d)/)[1]
136                     setSelector(
137                         DOM.oils_rpt_param_editor_sched_start_hour,
138                         run.run_time().match(/T(\d\d:\d\d)/)[1]
139                     );
140                 }
141             } else {
142                 DOM.oils_rpt_param_editor_sched_start_date.value = mkYearMonDay();
143             }
144         }
145         }
146
147     if (this.readonly) {
148         DOM.oils_rpt_report_editor_name.disabled = true;
149         DOM.oils_rpt_report_editor_desc.disabled = true;
150         DOM.oils_rpt_recur.disabled = true;
151         DOM.oils_rpt_recur_count.disabled = true;
152         DOM.oils_rpt_recur_interval_type.disabled = true;
153         DOM.oils_rpt_report_editor_run_now.disabled = true;
154         DOM.oils_rpt_format_csv.disabled = true;
155         DOM.oils_rpt_format_excel.disabled = true;
156         DOM.oils_rpt_format_html.disabled = true;
157         DOM.oils_rpt_format_chart_bar.disabled = true;
158         DOM.oils_rpt_format_chart_line.disabled = true;
159         DOM.oils_rpt_param_editor_sched_email.disabled = true;
160
161         hideMe(DOM.oils_rpt_report_editor_save);
162         hideMe(DOM.oils_rpt_report_editor_save_new);
163         hideMe(DOM.oils_rpt_report_editor_cancel);
164         unHideMe(DOM.oils_rpt_report_editor_exit);
165
166     } else {
167         // these DOM elements are shared across instances
168         // of the UI.  Re-enable everything.
169         DOM.oils_rpt_report_editor_name.disabled = false;
170         DOM.oils_rpt_report_editor_desc.disabled = false;
171         DOM.oils_rpt_recur.disabled = false;
172         DOM.oils_rpt_recur_count.disabled = false;
173         DOM.oils_rpt_recur_interval_type.disabled = false;
174         DOM.oils_rpt_report_editor_run_now.disabled = false;
175         DOM.oils_rpt_format_csv.disabled = false;
176         DOM.oils_rpt_format_excel.disabled = false;
177         DOM.oils_rpt_format_html.disabled = false;
178         DOM.oils_rpt_format_chart_bar.disabled = false;
179         DOM.oils_rpt_format_chart_line.disabled = false;
180         DOM.oils_rpt_param_editor_sched_email.disabled = false;
181         DOM.oils_rpt_report_editor_save.disabled = false;
182
183         unHideMe(DOM.oils_rpt_report_editor_save);
184         unHideMe(DOM.oils_rpt_report_editor_cancel);
185         hideMe(DOM.oils_rpt_report_editor_exit);
186
187     }
188
189     // avoid showing save-as-new for new reports, since the
190     // regular save button acts as save-as-new
191     if (rpt && !this.readonly) {
192         unHideMe(DOM.oils_rpt_report_editor_save_new);
193     } else {
194         hideMe(DOM.oils_rpt_report_editor_save_new);
195     }
196
197         this.paramEditor = new oilsRptParamEditor(
198                 rptObject, DOM.oils_rpt_param_editor_tbody, this.readonly);
199         this.paramEditor.draw();
200
201         removeChildren(DOM.oils_rpt_report_editor_selected_folder);
202         removeChildren(DOM.oils_rpt_output_selected_folder);
203
204         var obj = this;
205         oilsRptBuildFolder(
206                 'report',
207                 DOM.oils_rpt_report_editor_dest_folder,
208                 'oilsRptReportEditorFolderTree',
209                 rpt_strings.REPORT_EDITOR_REPORT_FOLDERS,
210                 function(node) { 
211                         appendClear(DOM.oils_rpt_report_editor_selected_folder, node.folder.name());
212                         obj.selectedFolder = node; 
213         },
214         null,
215         function(node) {
216             // apply the previously selected report folder
217             if (rpt && rpt.folder() == node.folder.id()) {
218                             appendClear(DOM.oils_rpt_report_editor_selected_folder, node.folder.name());
219                             obj.selectedFolder = node; 
220             }
221         }
222     );
223
224         oilsRptBuildFolder(
225                 'output',
226                 DOM.oils_rpt_output_dest_folder,
227                 'oilsRptReportEditorOutputTree',
228                 rpt_strings.REPORT_EDITOR_OUTPUT_FOLDERS,
229                 function(node) { 
230                         appendClear(DOM.oils_rpt_output_selected_folder, node.folder.name());
231                         obj.selectedOutputFolder = node; 
232         },
233         null,
234         function(node) {
235             // apply the previously selected output folder
236             if (obj.last_run && obj.last_run.folder() == node.folder.id()) {
237                             appendClear(DOM.oils_rpt_output_selected_folder, node.folder.name());
238                             obj.selectedOutputFolder = node; 
239             }
240         }
241     );
242
243
244         var obj = this;
245         DOM.oils_rpt_report_editor_save.onclick = function(){obj.save();}
246         DOM.oils_rpt_report_editor_save_new.onclick = function(){obj.save({save_new : true});}
247         DOM.oils_rpt_report_editor_exit.onclick = function(){obj.exit();}
248         DOM.oils_rpt_report_editor_cancel.onclick = function(){obj.exit();}
249
250         DOM.oils_rpt_param_editor_sched_email.value = 
251         this.last_run ? this.last_run.email() : USER.email();
252
253         _debug("fleshing template:\n" + tmpl.name() + '\n' + formatJSON(tmpl.data()));
254 }
255
256
257 // options.save_new : save as a new report, even if we
258 // were editing an exitingn report.
259 //
260 // options.modify_schedule : update the pending schedule
261 // object instead of creating a new one.
262 oilsRptReportEditor.prototype.save = function(options) {
263     if (!options) options = {};
264
265         if(!this.selectedFolder) 
266                 return alert(rpt_strings.REPORT_EDITOR_PROVIDE_FOLDER_ALERT);
267
268         if(!DOM.oils_rpt_report_editor_name.value)
269                 return alert(rpt_strings.REPORT_EDITOR_ENTER_NAME_ALERT);
270
271         if(!this.selectedOutputFolder) 
272                 return alert(rpt_strings.REPORT_EDITOR_PROVIDE_OUTPUT_ALERT);
273
274         var report = this.report;
275
276     if (report && options.save_new) {
277         // user is saving an existing report as a new report.
278         // The new report must have a different name.
279         if (DOM.oils_rpt_report_editor_name.value == this.orig_rpt_name) 
280             return alert(rpt_strings.REPORT_EDITOR_ENTER_NEW_NAME_ALERT);
281
282         report = null;
283     }
284
285     if (!report) {
286         report = new rr();
287         report.isnew(true);
288             report.owner( USER.id() );
289             report.template( this.template.id() );
290     }
291
292         report.folder( this.selectedFolder.folder.id() );
293         report.name( DOM.oils_rpt_report_editor_name.value );
294         report.description( DOM.oils_rpt_report_editor_desc.value );
295         report.recur(this.paramEditor.recur());
296         report.recurrence(this.paramEditor.recurInterval());
297
298         /* collect the param data */
299         var data = {};
300         for( var p in this.paramEditor.params ) {
301                 var par = this.paramEditor.params[p];
302                 _debug("adding report param "+par.key+" to report data");
303                 var val = par.widget.getValue();
304
305                 if(!val || val.length == 0 )
306                         return alertId('oils_rpt_empty_param');
307
308                 if( typeof val == 'object') {
309                         for( var i = i; i < val.length; i++ ) {
310                                 _debug("looking at widget value" + val[i]);
311                                 if( val[i] == '' || val[i] == null ) 
312                                         return alertId('oils_rpt_empty_param');
313                         }
314                 }
315
316                 data[par.key] = val;
317         }
318
319     if(getSelectorVal(DOM.oils_rpt_editor_pivot_data)) {
320         data.__pivot_label = getSelectorVal(DOM.oils_rpt_editor_pivot_label);
321         data.__pivot_data = getSelectorVal(DOM.oils_rpt_editor_pivot_data);
322     }
323
324
325         data = js2JSON(data);
326         _debug("complete report data = "+data);
327         report.data(data);
328
329         _debug("Built report:\n"+js2JSON(report));
330
331
332         var time;
333         if( DOM.oils_rpt_report_editor_run_now.checked ) {
334                 DOM.oils_rpt_report_editor_run_now.checked = false;
335                 time = 'now';
336
337         } else {
338
339                 var dt = DOM.oils_rpt_param_editor_sched_start_date.value;
340                 if(!dt || !dt.match(/^\d{4}-\d{2}-\d{2}$/) ) {
341                         /* for now.. make this better in the future */
342                         alert(rpt_strings.REPORT_EDITOR_INVALID_DATE_ALERT);
343                         return;
344                 }
345                 var hour = getSelectorVal(DOM.oils_rpt_param_editor_sched_start_hour);
346                 time = dt +'T'+hour+':00';
347                 _debug("built run_time "+time);
348         }
349
350     // if the last run has yet to actually start, then we update it
351     // instead of creating a new one.
352     var schedule = options.save_new ? null : this.last_run;
353
354     if (schedule && !schedule.start_time()) {
355         if (!options.modify_schedule) {
356             // warn the user that this action will modify an existing
357             // schedule object if they continue
358             return this.showPendingScheduleDialog();
359         }
360     } else {
361         // no schedules exist or the most recent one has already
362         // started.  Create a new one.
363             schedule = new rs();
364         schedule.isnew(true);
365     }
366
367         schedule.folder(this.selectedOutputFolder.folder.id());
368         schedule.email(DOM.oils_rpt_param_editor_sched_email.value);
369         schedule.run_time(time);
370         schedule.runner(USER.id());
371
372         schedule.excel_format((DOM.oils_rpt_format_excel.checked) ? 't' : 'f');
373         schedule.html_format((DOM.oils_rpt_format_html.checked) ? 't' : 'f');
374         schedule.csv_format((DOM.oils_rpt_format_csv.checked) ? 't' : 'f');
375         //schedule.chart_pie((DOM.oils_rpt_format_chart_pie.checked) ? 't' : 'f');
376         schedule.chart_bar((DOM.oils_rpt_format_chart_bar.checked) ? 't' : 'f');
377         schedule.chart_line((DOM.oils_rpt_format_chart_line.checked) ? 't' : 'f');
378
379         debugFMObject(report);
380         debugFMObject(schedule);
381
382     if (report.isnew()) {
383         this.createReport(report, schedule);
384     } else {
385         this.updateReport(report, schedule);
386     }
387 }
388
389 // Modify an existing report.
390 // Modify or create the schedule depending on isnew()
391 oilsRptReportEditor.prototype.updateReport = function(report, schedule) {
392
393     var this_ = this;
394     function success() {
395         oilsRptAlertSuccess();
396         this_.exit();
397     }
398
399     oilsRptUpdateReport(report, function(ok) {
400         if (!ok) return oilsRptAlertFailure();
401
402         if (schedule.isnew()) {
403
404             var req = new Request(OILS_RPT_CREATE_SCHEDULE, SESSION, schedule);
405             req.callback(function(res) {
406                 if(checkILSEvent(res)) 
407                     return alertILSEvent(res);
408                 success();
409             });
410             req.send()
411
412         } else {
413
414             oilsRptUpdateSchedule(schedule, function(ok2) {
415                 if (ok2) return success();
416                 _debug("schedule update failed " + js2JSON(schedule));
417                 oilsRptAlertFailure();
418             });
419         }
420     });
421 }
422
423 oilsRptReportEditor.prototype.createReport = function(report, schedule) {
424         var obj = this;
425     var folderReq = new Request(OILS_RPT_REPORT_EXISTS, SESSION, report);
426     folderReq.callback(
427         function(r1) {
428             if(r1.getResultObject() == 1) {
429                 alertId('oils_rpt_report_exists');
430                 return;
431             } else {
432                 var req = new Request(OILS_RPT_CREATE_REPORT, SESSION, report, schedule );
433                 req.callback(
434                     function(r) {
435                         var res = r.getResultObject();
436                         if(checkILSEvent(res)) {
437                             alertILSEvent(res);
438                         } else {
439                             if( res && res != '0' ) {
440                                 oilsRptAlertSuccess();
441                                 obj.exit();
442                             }
443                         }
444                     }
445                 );
446                 req.send();
447             }
448         }
449     );
450     folderReq.send();
451 }
452
453 oilsRptReportEditor.prototype.showPendingScheduleDialog = function() {
454     hideMe(DOM.oils_rpt_editor_table);
455     unHideMe(DOM.oils_rpt_editor_sched_confirm);
456
457     function close() {
458         unHideMe(DOM.oils_rpt_editor_table);
459         hideMe(DOM.oils_rpt_editor_sched_confirm);
460     }
461
462     var this_ = this;
463     DOM.oils_rpt_report_editor_sched_apply.onclick = function() {
464         close();
465         this_.save({modify_schedule : true});
466     }
467
468     DOM.oils_rpt_report_editor_sched_asnew.onclick = function() {
469
470         if (DOM.oils_rpt_report_editor_name.value == this_.orig_rpt_name) {
471             // user is saving as new but has not yet modified the name
472             // Prompt for a new name, then udpate the name entry so save() 
473             // will see it.  Don't let them escape until they comply.
474             var new_name;
475             while (true) { 
476
477                 new_name = prompt(
478                     rpt_strings.REPORT_EDITOR_ENTER_NEW_NAME_ALERT, 
479                     this_.orig_rpt_name
480                 );
481                 
482                 if (new_name && new_name != this_.orig_rpt_name)
483                     break;
484             }
485
486             DOM.oils_rpt_report_editor_name.value = new_name;
487         } 
488
489         close();
490         this_.save({save_new : true})
491     }
492     DOM.oils_rpt_report_editor_sched_cancel.onclick = close;
493 }
494
495
496 oilsRptReportEditor.prototype.exit = function() {
497     unHideMe(DOM.oils_rpt_folder_window_contents_table);                   
498     unHideMe(DOM.oils_rpt_folder_table_right_td);
499     hideMe(DOM.oils_rpt_folder_table_alt_td);
500     hideMe(DOM.oils_rpt_editor_div);
501 }