1 dojo.requireLocalization("openils.reports", "reports");
3 var rpt_strings = dojo.i18n.getLocalization("openils.reports", "reports");
5 oilsRptSetSubClass('oilsRptReportEditor', 'oilsRptObject');
6 var oilsRptReportEditorFolderTree;
8 function oilsRptReportEditor(rptObject, folderWindow, readonly) {
9 var tmpl = rptObject.templateObject;
10 var rpt = rptObject.reportObject;
11 this.folderWindow = folderWindow;
12 this.readonly = readonly;
17 if (rpt && rpt.runs() && rpt.runs().length)
18 this.last_run = rpt.runs()[rpt.runs().length - 1];
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());
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;
29 if (typeof xulG == 'undefined') {
30 link.setAttribute('href', URL);
31 link.setAttribute('target', '_blank');
33 link.onclick = function() {xulG.new_tab(URL); return false}
35 unHideMe(DOM.oils_rpt_report_editor_template_doc_url_row);
39 appendClear(DOM.oils_rpt_report_editor_cols,'');
40 iterate(rptObject.def.select,
43 DOM.oils_rpt_report_editor_cols.appendChild(text(i.alias));
45 DOM.oils_rpt_report_editor_cols.appendChild(
46 elem('span', {'class':'oils_rpt_field_hint'}, i.field_doc));
48 DOM.oils_rpt_report_editor_cols.appendChild(document.createElement('br'));
53 oils_rpt_editor_pivot_label
54 oils_rpt_editor_pivot_data
58 iterate(rptObject.def.select,
60 if(OILS_RPT_TRANSFORMS[i.column.transform].aggregate)
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);
68 while(DOM.oils_rpt_editor_pivot_data.lastChild)
69 DOM.oils_rpt_editor_pivot_data.removeChild(DOM.oils_rpt_editor_pivot_data.lastChild);
72 unHideMe(DOM.oils_rpt_editor_pivot_label_row);
73 unHideMe(DOM.oils_rpt_editor_pivot_data_row);
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);
80 insertSelectorVal(DOM.oils_rpt_editor_pivot_label, -1, col.alias, parseInt(i)+1);
84 hideMe(DOM.oils_rpt_editor_pivot_label_row);
85 hideMe(DOM.oils_rpt_editor_pivot_data_row);
90 DOM.oils_rpt_param_editor_sched_start_date.value = mkYearMonDay();
91 setSelector(DOM.oils_rpt_param_editor_sched_start_hour, '12:00');
92 DOM.oils_rpt_report_editor_run_now.checked = true;
93 DOM.oils_rpt_report_editor_schedule.checked = false;
94 DOM.oils_rpt_param_editor_sched_start_date.disabled = true;
95 DOM.oils_rpt_param_editor_sched_start_hour.disabled = true;
98 setSelector(DOM.oils_rpt_recur_interval_type, 'days');
99 setSelector(DOM.oils_rpt_recur_count, '1');
102 // populate the report edit form w/ report data
104 this.orig_rpt_name = rpt.name();
106 DOM.oils_rpt_report_editor_name.value = rpt.name();
107 DOM.oils_rpt_report_editor_name.onchange(); // validation
108 DOM.oils_rpt_report_editor_desc.value = rpt.description();
110 if (rpt.recur() == 't') {
111 DOM.oils_rpt_recur.checked = true;
112 DOM.oils_rpt_recur.onclick(); // enable recurrance selector
115 if (rpt.recurrence()) {
116 console.log('editing report with recurrence: ' + rpt.recurrence());
117 var parts = rpt.recurrence().split(/ /);
119 var count = Number(parts[0]);
121 if (type.match(/^mon/)) {
122 // PG stores 'months' as 'mon(s)'
124 } else if (type.match(/^day/)) {
125 // PG stores weeks as days. Assuming a person would typically
126 // use weeks to represent sets of 7 days, translate back to
127 // weeks when we can.
128 if (count % 7 == 0) {
134 setSelector(DOM.oils_rpt_recur_count, count);
135 setSelector(DOM.oils_rpt_recur_interval_type, type);
139 var rpt_data = JSON2js(rpt.data());
140 if (rpt_data.__pivot_label)
141 setSelector(DOM.oils_rpt_editor_pivot_label, rpt_data.__pivot_label);
142 if (rpt_data.__pivot_data)
143 setSelector(DOM.oils_rpt_editor_pivot_data, rpt_data.__pivot_data);
146 if (run = this.last_run) {
147 DOM.oils_rpt_report_editor_name.disabled = true;
148 DOM.oils_rpt_report_editor_desc.disabled = true;
149 DOM.oils_rpt_format_csv.checked = run.csv_format() == 't';
150 DOM.oils_rpt_format_excel.checked = run.excel_format() == 't';
151 DOM.oils_rpt_format_html.checked = run.html_format() == 't';
152 DOM.oils_rpt_format_chart_bar.checked = run.chart_bar() == 't';
153 DOM.oils_rpt_format_chart_line.checked = run.chart_line() == 't';
154 DOM.oils_rpt_param_editor_sched_email.value = run.email();
156 if (run.run_time()) {
157 console.log('view/edit report with last run_time: ' + run.run_time());
158 if (new Date(Date.parse(run.run_time())) >= new Date() || this.readonly) {
159 // Next run of the edited report is scheduled for some time in the future.
160 // Propagate the value into the data selector and de-select run-now.
161 // Ditto read-only mode, so the user can see info on the most recent run.
163 DOM.oils_rpt_param_editor_sched_start_date.value =
164 run.run_time().match(/(\d{4}-\d{2}-\d{2})/)[1]
167 DOM.oils_rpt_param_editor_sched_start_hour,
168 run.run_time().match(/T(\d{2})/)[1] + ':00'
171 DOM.oils_rpt_report_editor_run_now.checked = false;
172 DOM.oils_rpt_report_editor_schedule.checked = true;
173 DOM.oils_rpt_param_editor_sched_start_date.disabled = false;
174 DOM.oils_rpt_param_editor_sched_start_hour.disabled = false;
181 DOM.oils_rpt_report_editor_name.disabled = true;
182 DOM.oils_rpt_report_editor_desc.disabled = true;
183 DOM.oils_rpt_recur.disabled = true;
184 DOM.oils_rpt_recur_count.disabled = true;
185 DOM.oils_rpt_recur_interval_type.disabled = true;
186 DOM.oils_rpt_report_editor_run_now.disabled = true;
187 DOM.oils_rpt_format_csv.disabled = true;
188 DOM.oils_rpt_format_excel.disabled = true;
189 DOM.oils_rpt_format_html.disabled = true;
190 DOM.oils_rpt_format_chart_bar.disabled = true;
191 DOM.oils_rpt_format_chart_line.disabled = true;
192 DOM.oils_rpt_param_editor_sched_email.disabled = true;
194 hideMe(DOM.oils_rpt_report_editor_save);
195 hideMe(DOM.oils_rpt_report_editor_save_new);
196 hideMe(DOM.oils_rpt_report_editor_cancel);
197 unHideMe(DOM.oils_rpt_report_editor_exit);
200 // these DOM elements are shared across instances
201 // of the UI. Re-enable everything.
202 DOM.oils_rpt_report_editor_name.disabled = false;
203 DOM.oils_rpt_report_editor_desc.disabled = false;
204 DOM.oils_rpt_recur.disabled = false;
205 DOM.oils_rpt_recur_count.disabled = false;
206 DOM.oils_rpt_recur_interval_type.disabled = false;
207 DOM.oils_rpt_report_editor_run_now.disabled = false;
208 DOM.oils_rpt_format_csv.disabled = false;
209 DOM.oils_rpt_format_excel.disabled = false;
210 DOM.oils_rpt_format_html.disabled = false;
211 DOM.oils_rpt_format_chart_bar.disabled = false;
212 DOM.oils_rpt_format_chart_line.disabled = false;
213 DOM.oils_rpt_param_editor_sched_email.disabled = false;
214 DOM.oils_rpt_report_editor_save.disabled = false;
216 unHideMe(DOM.oils_rpt_report_editor_save);
217 unHideMe(DOM.oils_rpt_report_editor_cancel);
218 hideMe(DOM.oils_rpt_report_editor_exit);
222 // avoid showing save-as-new for new reports, since the
223 // regular save button acts as save-as-new
224 if (rpt && !this.readonly) {
225 unHideMe(DOM.oils_rpt_report_editor_save_new);
227 hideMe(DOM.oils_rpt_report_editor_save_new);
230 this.paramEditor = new oilsRptParamEditor(
231 rptObject, DOM.oils_rpt_param_editor_tbody, this.readonly);
232 this.paramEditor.draw();
234 removeChildren(DOM.oils_rpt_report_editor_selected_folder);
235 removeChildren(DOM.oils_rpt_output_selected_folder);
240 DOM.oils_rpt_report_editor_dest_folder,
241 'oilsRptReportEditorFolderTree',
242 rpt_strings.REPORT_EDITOR_REPORT_FOLDERS,
244 appendClear(DOM.oils_rpt_report_editor_selected_folder, node.folder.name());
245 obj.selectedFolder = node;
249 // apply the previously selected report folder
250 if (rpt && rpt.folder() == node.folder.id()) {
251 appendClear(DOM.oils_rpt_report_editor_selected_folder, node.folder.name());
252 obj.selectedFolder = node;
259 DOM.oils_rpt_output_dest_folder,
260 'oilsRptReportEditorOutputTree',
261 rpt_strings.REPORT_EDITOR_OUTPUT_FOLDERS,
263 appendClear(DOM.oils_rpt_output_selected_folder, node.folder.name());
264 obj.selectedOutputFolder = node;
268 // apply the previously selected output folder
269 if (obj.last_run && obj.last_run.folder() == node.folder.id()) {
270 appendClear(DOM.oils_rpt_output_selected_folder, node.folder.name());
271 obj.selectedOutputFolder = node;
278 DOM.oils_rpt_report_editor_save.onclick = function(){obj.save();}
279 DOM.oils_rpt_report_editor_save_new.onclick = function(){obj.save({save_new : true});}
280 DOM.oils_rpt_report_editor_exit.onclick = function(){obj.exit();}
281 DOM.oils_rpt_report_editor_cancel.onclick = function(){obj.exit();}
283 DOM.oils_rpt_param_editor_sched_email.value =
284 this.last_run ? this.last_run.email() : USER.email();
286 _debug("fleshing template:\n" + tmpl.name() + '\n' + formatJSON(tmpl.data()));
290 // options.save_new : save as a new report, even if we
291 // were editing an exitingn report.
293 // options.modify_schedule : update the pending schedule
294 // object instead of creating a new one.
295 oilsRptReportEditor.prototype.save = function(options) {
296 if (!options) options = {};
298 if(!this.selectedFolder)
299 return alert(rpt_strings.REPORT_EDITOR_PROVIDE_FOLDER_ALERT);
301 if(!DOM.oils_rpt_report_editor_name.value)
302 return alert(rpt_strings.REPORT_EDITOR_ENTER_NAME_ALERT);
304 if(!this.selectedOutputFolder)
305 return alert(rpt_strings.REPORT_EDITOR_PROVIDE_OUTPUT_ALERT);
307 var report = this.report;
309 if (report && options.save_new) {
310 // user is saving an existing report as a new report.
311 // The new report must have a different name.
312 if (DOM.oils_rpt_report_editor_name.value == this.orig_rpt_name)
313 return alert(rpt_strings.REPORT_EDITOR_ENTER_NEW_NAME_ALERT);
321 report.owner( USER.id() );
322 report.template( this.template.id() );
325 report.folder( this.selectedFolder.folder.id() );
326 report.name( DOM.oils_rpt_report_editor_name.value );
327 report.description( DOM.oils_rpt_report_editor_desc.value );
328 report.recur(this.paramEditor.recur());
329 report.recurrence(this.paramEditor.recurInterval());
331 /* collect the param data */
333 for( var p in this.paramEditor.params ) {
334 var par = this.paramEditor.params[p];
335 _debug("adding report param "+par.key+" to report data");
336 var val = par.widget.getValue();
338 if(!val || val.length == 0 )
339 return alertId('oils_rpt_empty_param');
341 if( typeof val == 'object') {
342 for( var i = i; i < val.length; i++ ) {
343 _debug("looking at widget value" + val[i]);
344 if( val[i] == '' || val[i] == null )
345 return alertId('oils_rpt_empty_param');
352 if(getSelectorVal(DOM.oils_rpt_editor_pivot_data)) {
353 data.__pivot_label = getSelectorVal(DOM.oils_rpt_editor_pivot_label);
354 data.__pivot_data = getSelectorVal(DOM.oils_rpt_editor_pivot_data);
358 data = js2JSON(data);
359 _debug("complete report data = "+data);
362 _debug("Built report:\n"+js2JSON(report));
366 if( DOM.oils_rpt_report_editor_run_now.checked ) {
371 var dt = DOM.oils_rpt_param_editor_sched_start_date.value;
372 if(!dt || !dt.match(/^\d{4}-\d{2}-\d{2}$/) ) {
373 /* for now.. make this better in the future */
374 alert(rpt_strings.REPORT_EDITOR_INVALID_DATE_ALERT);
377 var hour = getSelectorVal(DOM.oils_rpt_param_editor_sched_start_hour);
378 time = dt +'T'+hour+':00';
379 _debug("built run_time "+time);
382 // if the last run has yet to actually start, then we update it
383 // instead of creating a new one.
384 var schedule = options.save_new ? null : this.last_run;
386 if (schedule && !schedule.start_time()) {
387 if (!options.modify_schedule) {
388 // warn the user that this action will modify an existing
389 // schedule object if they continue
390 return this.showPendingScheduleDialog();
393 // no schedules exist or the most recent one has already
394 // started. Create a new one.
396 schedule.isnew(true);
399 schedule.folder(this.selectedOutputFolder.folder.id());
400 schedule.email(DOM.oils_rpt_param_editor_sched_email.value);
401 schedule.run_time(time);
402 schedule.runner(USER.id());
404 schedule.excel_format((DOM.oils_rpt_format_excel.checked) ? 't' : 'f');
405 schedule.html_format((DOM.oils_rpt_format_html.checked) ? 't' : 'f');
406 schedule.csv_format((DOM.oils_rpt_format_csv.checked) ? 't' : 'f');
407 //schedule.chart_pie((DOM.oils_rpt_format_chart_pie.checked) ? 't' : 'f');
408 schedule.chart_bar((DOM.oils_rpt_format_chart_bar.checked) ? 't' : 'f');
409 schedule.chart_line((DOM.oils_rpt_format_chart_line.checked) ? 't' : 'f');
411 debugFMObject(report);
412 debugFMObject(schedule);
414 if (report.isnew()) {
415 this.createReport(report, schedule);
417 this.updateReport(report, schedule);
421 // Modify an existing report.
422 // Modify or create the schedule depending on isnew()
423 oilsRptReportEditor.prototype.updateReport = function(report, schedule) {
427 oilsRptAlertSuccess();
431 oilsRptUpdateReport(report, function(ok) {
432 if (!ok) return oilsRptAlertFailure();
434 if (schedule.isnew()) {
436 var req = new Request(OILS_RPT_CREATE_SCHEDULE, SESSION, schedule);
437 req.callback(function(res) {
438 if(checkILSEvent(res))
439 return alertILSEvent(res);
446 oilsRptUpdateSchedule(schedule, function(ok2) {
447 if (ok2) return success();
448 _debug("schedule update failed " + js2JSON(schedule));
449 oilsRptAlertFailure();
455 oilsRptReportEditor.prototype.createReport = function(report, schedule) {
457 var folderReq = new Request(OILS_RPT_REPORT_EXISTS, SESSION, report);
460 if(r1.getResultObject() == 1) {
461 alertId('oils_rpt_report_exists');
464 var req = new Request(OILS_RPT_CREATE_REPORT, SESSION, report, schedule );
467 var res = r.getResultObject();
468 if(checkILSEvent(res)) {
471 if( res && res != '0' ) {
472 oilsRptAlertSuccess();
485 oilsRptReportEditor.prototype.showPendingScheduleDialog = function() {
486 hideMe(DOM.oils_rpt_editor_table);
487 unHideMe(DOM.oils_rpt_editor_sched_confirm);
490 unHideMe(DOM.oils_rpt_editor_table);
491 hideMe(DOM.oils_rpt_editor_sched_confirm);
495 DOM.oils_rpt_report_editor_sched_apply.onclick = function() {
497 this_.save({modify_schedule : true});
500 DOM.oils_rpt_report_editor_sched_asnew.onclick = function() {
502 if (DOM.oils_rpt_report_editor_name.value == this_.orig_rpt_name) {
503 // user is saving as new but has not yet modified the name
504 // Prompt for a new name, then udpate the name entry so save()
505 // will see it. Don't let them escape until they comply.
510 rpt_strings.REPORT_EDITOR_ENTER_NEW_NAME_ALERT,
514 if (new_name && new_name != this_.orig_rpt_name)
518 DOM.oils_rpt_report_editor_name.value = new_name;
522 this_.save({save_new : true})
524 DOM.oils_rpt_report_editor_sched_cancel.onclick = close;
528 oilsRptReportEditor.prototype.exit = function() {
529 unHideMe(DOM.oils_rpt_folder_window_contents_table);
530 unHideMe(DOM.oils_rpt_folder_table_right_td);
531 hideMe(DOM.oils_rpt_folder_table_alt_td);
532 hideMe(DOM.oils_rpt_editor_div);