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