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);
144 DOM.oils_rpt_editor_do_rollup.checked = rpt_data.__do_rollup == '1';
147 if (run = this.last_run) {
148 DOM.oils_rpt_report_editor_name.disabled = true;
149 DOM.oils_rpt_report_editor_desc.disabled = true;
150 DOM.oils_rpt_format_csv.checked = run.csv_format() == 't';
151 DOM.oils_rpt_format_excel.checked = run.excel_format() == 't';
152 DOM.oils_rpt_format_html.checked = run.html_format() == 't';
153 DOM.oils_rpt_format_chart_bar.checked = run.chart_bar() == 't';
154 DOM.oils_rpt_format_chart_line.checked = run.chart_line() == 't';
155 DOM.oils_rpt_param_editor_sched_email.value = run.email();
157 if (run.run_time()) {
158 console.log('view/edit report with last run_time: ' + run.run_time());
159 if (new Date(Date.parse(run.run_time())) >= new Date() || this.readonly) {
160 // Next run of the edited report is scheduled for some time in the future.
161 // Propagate the value into the data selector and de-select run-now.
162 // Ditto read-only mode, so the user can see info on the most recent run.
164 DOM.oils_rpt_param_editor_sched_start_date.value =
165 run.run_time().match(/(\d{4}-\d{2}-\d{2})/)[1]
168 DOM.oils_rpt_param_editor_sched_start_hour,
169 run.run_time().match(/T(\d{2})/)[1] + ':00'
172 DOM.oils_rpt_report_editor_run_now.checked = false;
173 DOM.oils_rpt_report_editor_schedule.checked = true;
174 DOM.oils_rpt_param_editor_sched_start_date.disabled = false;
175 DOM.oils_rpt_param_editor_sched_start_hour.disabled = false;
182 DOM.oils_rpt_report_editor_name.disabled = true;
183 DOM.oils_rpt_report_editor_desc.disabled = true;
184 DOM.oils_rpt_recur.disabled = true;
185 DOM.oils_rpt_recur_count.disabled = true;
186 DOM.oils_rpt_recur_interval_type.disabled = true;
187 DOM.oils_rpt_report_editor_run_now.disabled = true;
188 DOM.oils_rpt_format_csv.disabled = true;
189 DOM.oils_rpt_format_excel.disabled = true;
190 DOM.oils_rpt_format_html.disabled = true;
191 DOM.oils_rpt_format_chart_bar.disabled = true;
192 DOM.oils_rpt_format_chart_line.disabled = true;
193 DOM.oils_rpt_param_editor_sched_email.disabled = true;
195 hideMe(DOM.oils_rpt_report_editor_save);
196 hideMe(DOM.oils_rpt_report_editor_save_new);
197 hideMe(DOM.oils_rpt_report_editor_cancel);
198 unHideMe(DOM.oils_rpt_report_editor_exit);
201 // these DOM elements are shared across instances
202 // of the UI. Re-enable everything.
203 DOM.oils_rpt_report_editor_name.disabled = false;
204 DOM.oils_rpt_report_editor_desc.disabled = false;
205 DOM.oils_rpt_recur.disabled = false;
206 DOM.oils_rpt_recur_count.disabled = false;
207 DOM.oils_rpt_recur_interval_type.disabled = false;
208 DOM.oils_rpt_report_editor_run_now.disabled = false;
209 DOM.oils_rpt_format_csv.disabled = false;
210 DOM.oils_rpt_format_excel.disabled = false;
211 DOM.oils_rpt_format_html.disabled = false;
212 DOM.oils_rpt_format_chart_bar.disabled = false;
213 DOM.oils_rpt_format_chart_line.disabled = false;
214 DOM.oils_rpt_param_editor_sched_email.disabled = false;
215 DOM.oils_rpt_report_editor_save.disabled = false;
217 unHideMe(DOM.oils_rpt_report_editor_save);
218 unHideMe(DOM.oils_rpt_report_editor_cancel);
219 hideMe(DOM.oils_rpt_report_editor_exit);
223 // avoid showing save-as-new for new reports, since the
224 // regular save button acts as save-as-new
225 if (rpt && !this.readonly) {
226 unHideMe(DOM.oils_rpt_report_editor_save_new);
228 hideMe(DOM.oils_rpt_report_editor_save_new);
231 this.paramEditor = new oilsRptParamEditor(
232 rptObject, DOM.oils_rpt_param_editor_tbody, this.readonly);
233 this.paramEditor.draw();
235 removeChildren(DOM.oils_rpt_report_editor_selected_folder);
236 removeChildren(DOM.oils_rpt_output_selected_folder);
241 DOM.oils_rpt_report_editor_dest_folder,
242 'oilsRptReportEditorFolderTree',
243 rpt_strings.REPORT_EDITOR_REPORT_FOLDERS,
245 appendClear(DOM.oils_rpt_report_editor_selected_folder, node.folder.name());
246 obj.selectedFolder = node;
250 // apply the previously selected report folder
251 if (rpt && rpt.folder() == node.folder.id()) {
252 appendClear(DOM.oils_rpt_report_editor_selected_folder, node.folder.name());
253 obj.selectedFolder = node;
260 DOM.oils_rpt_output_dest_folder,
261 'oilsRptReportEditorOutputTree',
262 rpt_strings.REPORT_EDITOR_OUTPUT_FOLDERS,
264 appendClear(DOM.oils_rpt_output_selected_folder, node.folder.name());
265 obj.selectedOutputFolder = node;
269 // apply the previously selected output folder
270 if (obj.last_run && obj.last_run.folder() == node.folder.id()) {
271 appendClear(DOM.oils_rpt_output_selected_folder, node.folder.name());
272 obj.selectedOutputFolder = node;
279 DOM.oils_rpt_report_editor_save.onclick = function(){obj.save();}
280 DOM.oils_rpt_report_editor_save_new.onclick = function(){obj.save({save_new : true});}
281 DOM.oils_rpt_report_editor_exit.onclick = function(){obj.exit();}
282 DOM.oils_rpt_report_editor_cancel.onclick = function(){obj.exit();}
284 DOM.oils_rpt_param_editor_sched_email.value =
285 this.last_run ? this.last_run.email() : USER.email();
287 _debug("fleshing template:\n" + tmpl.name() + '\n' + formatJSON(tmpl.data()));
291 // options.save_new : save as a new report, even if we
292 // were editing an exitingn report.
294 // options.modify_schedule : update the pending schedule
295 // object instead of creating a new one.
296 oilsRptReportEditor.prototype.save = function(options) {
297 if (!options) options = {};
299 if(!this.selectedFolder)
300 return alert(rpt_strings.REPORT_EDITOR_PROVIDE_FOLDER_ALERT);
302 if(!DOM.oils_rpt_report_editor_name.value)
303 return alert(rpt_strings.REPORT_EDITOR_ENTER_NAME_ALERT);
305 if(!this.selectedOutputFolder)
306 return alert(rpt_strings.REPORT_EDITOR_PROVIDE_OUTPUT_ALERT);
308 var report = this.report;
310 if (report && options.save_new) {
311 // user is saving an existing report as a new report.
312 // The new report must have a different name.
313 if (DOM.oils_rpt_report_editor_name.value == this.orig_rpt_name)
314 return alert(rpt_strings.REPORT_EDITOR_ENTER_NEW_NAME_ALERT);
322 report.owner( USER.id() );
323 report.template( this.template.id() );
326 report.folder( this.selectedFolder.folder.id() );
327 report.name( DOM.oils_rpt_report_editor_name.value );
328 report.description( DOM.oils_rpt_report_editor_desc.value );
329 report.recur(this.paramEditor.recur());
330 report.recurrence(this.paramEditor.recurInterval());
332 /* collect the param data */
334 for( var p in this.paramEditor.params ) {
335 var par = this.paramEditor.params[p];
336 _debug("adding report param "+par.key+" to report data");
337 var val = par.widget.getValue();
339 if(!val || val.length == 0 )
340 return alertId('oils_rpt_empty_param');
342 if( typeof val == 'object') {
343 for( var i = i; i < val.length; i++ ) {
344 _debug("looking at widget value" + val[i]);
345 if( val[i] == '' || val[i] == null )
346 return alertId('oils_rpt_empty_param');
353 if(getSelectorVal(DOM.oils_rpt_editor_pivot_data)) {
354 data.__pivot_label = getSelectorVal(DOM.oils_rpt_editor_pivot_label);
355 data.__pivot_data = getSelectorVal(DOM.oils_rpt_editor_pivot_data);
357 data.__do_rollup = DOM.oils_rpt_editor_do_rollup.checked ? '1' : '0';
359 data = js2JSON(data);
360 _debug("complete report data = "+data);
363 _debug("Built report:\n"+js2JSON(report));
367 if( DOM.oils_rpt_report_editor_run_now.checked ) {
372 var dt = DOM.oils_rpt_param_editor_sched_start_date.value;
373 if(!dt || !dt.match(/^\d{4}-\d{2}-\d{2}$/) ) {
374 /* for now.. make this better in the future */
375 alert(rpt_strings.REPORT_EDITOR_INVALID_DATE_ALERT);
378 var hour = getSelectorVal(DOM.oils_rpt_param_editor_sched_start_hour);
379 time = dt +'T'+hour+':00';
380 _debug("built run_time "+time);
383 // if the last run has yet to actually start, then we update it
384 // instead of creating a new one.
385 var schedule = options.save_new ? null : this.last_run;
387 if (schedule && !schedule.start_time()) {
388 if (!options.modify_schedule) {
389 // warn the user that this action will modify an existing
390 // schedule object if they continue
391 return this.showPendingScheduleDialog();
394 // no schedules exist or the most recent one has already
395 // started. Create a new one.
397 schedule.isnew(true);
400 schedule.folder(this.selectedOutputFolder.folder.id());
401 schedule.email(DOM.oils_rpt_param_editor_sched_email.value);
402 schedule.run_time(time);
403 schedule.runner(USER.id());
405 schedule.excel_format((DOM.oils_rpt_format_excel.checked) ? 't' : 'f');
406 schedule.html_format((DOM.oils_rpt_format_html.checked) ? 't' : 'f');
407 schedule.csv_format((DOM.oils_rpt_format_csv.checked) ? 't' : 'f');
408 //schedule.chart_pie((DOM.oils_rpt_format_chart_pie.checked) ? 't' : 'f');
409 schedule.chart_bar((DOM.oils_rpt_format_chart_bar.checked) ? 't' : 'f');
410 schedule.chart_line((DOM.oils_rpt_format_chart_line.checked) ? 't' : 'f');
412 debugFMObject(report);
413 debugFMObject(schedule);
415 if (report.isnew()) {
416 this.createReport(report, schedule);
418 this.updateReport(report, schedule);
422 // Modify an existing report.
423 // Modify or create the schedule depending on isnew()
424 oilsRptReportEditor.prototype.updateReport = function(report, schedule) {
428 oilsRptAlertSuccess();
432 oilsRptUpdateReport(report, function(ok) {
433 if (!ok) return oilsRptAlertFailure();
435 if (schedule.isnew()) {
437 var req = new Request(OILS_RPT_CREATE_SCHEDULE, SESSION, schedule);
438 req.callback(function(res) {
439 if(checkILSEvent(res))
440 return alertILSEvent(res);
447 oilsRptUpdateSchedule(schedule, function(ok2) {
448 if (ok2) return success();
449 _debug("schedule update failed " + js2JSON(schedule));
450 oilsRptAlertFailure();
456 oilsRptReportEditor.prototype.createReport = function(report, schedule) {
458 var folderReq = new Request(OILS_RPT_REPORT_EXISTS, SESSION, report);
461 if(r1.getResultObject() == 1) {
462 alertId('oils_rpt_report_exists');
465 var req = new Request(OILS_RPT_CREATE_REPORT, SESSION, report, schedule );
468 var res = r.getResultObject();
469 if(checkILSEvent(res)) {
472 if( res && res != '0' ) {
473 oilsRptAlertSuccess();
486 oilsRptReportEditor.prototype.showPendingScheduleDialog = function() {
487 hideMe(DOM.oils_rpt_editor_table);
488 unHideMe(DOM.oils_rpt_editor_sched_confirm);
491 unHideMe(DOM.oils_rpt_editor_table);
492 hideMe(DOM.oils_rpt_editor_sched_confirm);
496 DOM.oils_rpt_report_editor_sched_apply.onclick = function() {
498 this_.save({modify_schedule : true});
501 DOM.oils_rpt_report_editor_sched_asnew.onclick = function() {
503 if (DOM.oils_rpt_report_editor_name.value == this_.orig_rpt_name) {
504 // user is saving as new but has not yet modified the name
505 // Prompt for a new name, then udpate the name entry so save()
506 // will see it. Don't let them escape until they comply.
511 rpt_strings.REPORT_EDITOR_ENTER_NEW_NAME_ALERT,
515 if (new_name && new_name != this_.orig_rpt_name)
519 DOM.oils_rpt_report_editor_name.value = new_name;
523 this_.save({save_new : true})
525 DOM.oils_rpt_report_editor_sched_cancel.onclick = close;
529 oilsRptReportEditor.prototype.exit = function() {
530 unHideMe(DOM.oils_rpt_folder_window_contents_table);
531 unHideMe(DOM.oils_rpt_folder_table_right_td);
532 hideMe(DOM.oils_rpt_folder_table_alt_td);
533 hideMe(DOM.oils_rpt_editor_div);