Revision 22ab10f7
Von Bernd Bleßmann vor mehr als 1 Jahr hinzugefügt
SL/Controller/CustomDataExport.pm | ||
---|---|---|
63 | 63 |
title => $self->query->name, |
64 | 64 |
allow_pdf_export => 1, |
65 | 65 |
allow_csv_export => 1, |
66 |
allow_chart_export => 1, |
|
66 | 67 |
attachment_basename => $report_name, |
67 | 68 |
); |
68 | 69 |
|
SL/Controller/Helper/ReportGenerator.pm | ||
---|---|---|
12 | 12 |
|
13 | 13 |
use Exporter 'import'; |
14 | 14 |
our @EXPORT = qw( |
15 |
action_report_generator_export_as_pdf action_report_generator_export_as_csv |
|
15 |
action_report_generator_export_as_pdf |
|
16 |
action_report_generator_export_as_csv |
|
17 |
action_report_generator_export_as_chart |
|
16 | 18 |
action_report_generator_back report_generator_do |
17 | 19 |
report_generator_list_objects |
18 | 20 |
); |
... | ... | |
26 | 28 |
for my $bar ($::request->layout->get('actionbar')) { |
27 | 29 |
$bar->add( |
28 | 30 |
action => [ |
29 |
$type eq 'pdf' ? $::locale->text('PDF export') : $::locale->text('CSV export'),
|
|
31 |
$type eq 'pdf' ? $::locale->text('PDF export') : $type eq 'csv' ? $::locale->text('CSV export') : $::locale->text('Chart export'),
|
|
30 | 32 |
submit => [ '#report_generator_form', { $key => "${value}report_generator_export_as_${type}" } ], |
31 | 33 |
], |
32 | 34 |
action => [ |
... | ... | |
92 | 94 |
print $::form->parse_html_template('report_generator/csv_export_options', { 'HIDDEN' => \@form_values }); |
93 | 95 |
} |
94 | 96 |
|
97 |
sub action_report_generator_export_as_chart { |
|
98 |
my ($self) = @_; |
|
99 |
|
|
100 |
delete $::form->{action_report_generator_export_as_chart}; |
|
101 |
|
|
102 |
if ($::form->{report_generator_chart_options_set}) { |
|
103 |
$self->report_generator_do('Chart'); |
|
104 |
return; |
|
105 |
} |
|
106 |
|
|
107 |
my $fields = delete $::form->{report_generator_chart_fields}; |
|
108 |
my @form_values = $::form->flatten_variables(grep { ($_ ne 'login') && ($_ ne 'password') } keys %{ $::form }); |
|
109 |
|
|
110 |
$::form->{title} = $::locale->text('Chart export -- options'); |
|
111 |
|
|
112 |
_setup_action_bar($self, 'chart'); # Sub not exported, therefore don't call via object. |
|
113 |
|
|
114 |
$::form->header; |
|
115 |
print $::form->parse_html_template('report_generator/chart_export_options', { 'HIDDEN' => \@form_values, fields => $fields }); |
|
116 |
} |
|
117 |
|
|
95 | 118 |
sub action_report_generator_back { |
96 | 119 |
$_[0]->report_generator_do('HTML'); |
97 | 120 |
} |
SL/ReportGenerator.pm | ||
---|---|---|
10 | 10 |
use strict; |
11 | 11 |
use SL::Helper::GlAttachments qw(append_gl_pdf_attachments); |
12 | 12 |
use SL::Helper::CreatePDF qw(merge_pdfs); |
13 |
use SL::JSON qw(to_json); |
|
13 | 14 |
|
14 | 15 |
# Cause locales.pl to parse these files: |
15 | 16 |
# parse_html_template('report_generator/html_report') |
... | ... | |
29 | 30 |
'controller_class ' => '', |
30 | 31 |
'allow_pdf_export' => 1, |
31 | 32 |
'allow_csv_export' => 1, |
33 |
'allow_chart_export' => 1, |
|
32 | 34 |
'html_template' => 'report_generator/html_report', |
33 | 35 |
'pdf_export' => { |
34 | 36 |
'paper_size' => 'a4', |
... | ... | |
52 | 54 |
'headers' => 1, |
53 | 55 |
'encoding' => 'UTF-8', |
54 | 56 |
}, |
57 |
'chart_export' => { |
|
58 |
'assignment_x' => 'x', |
|
59 |
'assignment_y' => 'y1', |
|
60 |
}, |
|
55 | 61 |
}; |
56 | 62 |
$self->{export} = { |
57 | 63 |
'nextsub' => '', |
... | ... | |
168 | 174 |
$self->{options}->{pdf_export}->{$_} = $value->{$_} for keys %{ $value }; |
169 | 175 |
} elsif ($key eq 'csv_export') { |
170 | 176 |
$self->{options}->{csv_export}->{$_} = $value->{$_} for keys %{ $value }; |
177 |
} elsif ($key eq 'chart_export') { |
|
178 |
$self->{options}->{chart_export}->{$_} = $value->{$_} for keys %{ $value }; |
|
171 | 179 |
} else { |
172 | 180 |
$self->{options}->{$key} = $value; |
173 | 181 |
} |
... | ... | |
185 | 193 |
$self->{options}->{$key} = $form->{$full_key} if (defined $form->{$full_key}); |
186 | 194 |
} |
187 | 195 |
|
188 |
foreach my $format (qw(pdf csv)) { |
|
196 |
foreach my $format (qw(pdf csv chart)) {
|
|
189 | 197 |
my $opts = $self->{options}->{"${format}_export"}; |
190 | 198 |
foreach my $key (keys %{ $opts }) { |
191 | 199 |
my $full_key = "report_generator_${format}_options_${key}"; |
... | ... | |
255 | 263 |
} elsif ($format eq 'pdf') { |
256 | 264 |
$self->generate_pdf_content(); |
257 | 265 |
|
266 |
} elsif ($format eq 'chart') { |
|
267 |
$self->generate_chart_content(); |
|
268 |
|
|
258 | 269 |
} else { |
259 |
$form->error('Incorrect usage -- unknown format (supported are HTML, CSV, PDF)'); |
|
270 |
$form->error('Incorrect usage -- unknown format (supported are HTML, CSV, PDF, Chart)');
|
|
260 | 271 |
} |
261 | 272 |
} |
262 | 273 |
|
... | ... | |
401 | 412 |
'RAW_BOTTOM_INFO_TEXT' => $opts->{raw_bottom_info_text}, |
402 | 413 |
'ALLOW_PDF_EXPORT' => $allow_pdf_export, |
403 | 414 |
'ALLOW_CSV_EXPORT' => $opts->{allow_csv_export}, |
404 |
'SHOW_EXPORT_BUTTONS' => ($allow_pdf_export || $opts->{allow_csv_export}) && $self->{data_present}, |
|
415 |
'ALLOW_CHART_EXPORT' => $opts->{allow_chart_export}, |
|
416 |
'SHOW_EXPORT_BUTTONS' => ($allow_pdf_export || $opts->{allow_csv_export} || $opts->{allow_chart_export}) && $self->{data_present}, |
|
405 | 417 |
'HEADER_ROWS' => $header_rows, |
406 | 418 |
'NUM_COLUMNS' => scalar @column_headers, |
407 | 419 |
'ROWS' => \@rows, |
... | ... | |
421 | 433 |
my ($self, $variables, %params) = @_; |
422 | 434 |
|
423 | 435 |
my @actions; |
424 |
foreach my $type (qw(pdf csv)) { |
|
436 |
foreach my $type (qw(pdf csv chart)) {
|
|
425 | 437 |
next unless $variables->{"ALLOW_" . uc($type) . "_EXPORT"}; |
426 | 438 |
|
427 | 439 |
my $key = $variables->{CONTROLLER_DISPATCH} ? 'action' : 'report_generator_dispatch_to'; |
... | ... | |
429 | 441 |
$value = $variables->{CONTROLLER_DISPATCH} . "/${value}" if $variables->{CONTROLLER_DISPATCH}; |
430 | 442 |
|
431 | 443 |
push @actions, action => [ |
432 |
$type eq 'pdf' ? $::locale->text('PDF export') : $::locale->text('CSV export'),
|
|
444 |
$type eq 'pdf' ? $::locale->text('PDF export') : $type eq 'csv' ? $::locale->text('CSV export') : $::locale->text('Chart export'),
|
|
433 | 445 |
submit => [ '#report_generator_form', {( |
434 | 446 |
$key => $value, |
435 | 447 |
defined $params{action_bar_additional_submit_values} |
... | ... | |
471 | 483 |
$params{action_bar} //= 1; |
472 | 484 |
|
473 | 485 |
my $variables = $self->prepare_html_content(%params); |
474 |
|
|
475 | 486 |
$self->setup_action_bar($variables, %params) if $params{action_bar}; |
476 | 487 |
|
477 | 488 |
my $stuff = $self->{form}->parse_html_template($self->{options}->{html_template}, $variables); |
... | ... | |
858 | 869 |
} |
859 | 870 |
} |
860 | 871 |
|
872 |
sub generate_chart_content { |
|
873 |
my ($self, %params) = @_; |
|
874 |
|
|
875 |
$params{action_bar} //= 1; |
|
876 |
|
|
877 |
my $opts = $self->{options}; |
|
878 |
|
|
879 |
my $assignment_x = $opts->{chart_export}->{assignment_x}; |
|
880 |
my $assignment_y = $opts->{chart_export}->{assignment_y}; |
|
881 |
|
|
882 |
my @data_x; |
|
883 |
my @data_y; |
|
884 |
foreach my $row_set (@{ $self->{data} }) { |
|
885 |
next if ('ARRAY' ne ref $row_set); |
|
886 |
foreach my $row (@{ $row_set }) { |
|
887 |
my $x = $row->{$assignment_x}->{data}->[0]; |
|
888 |
my $y = $row->{$assignment_y}->{data}->[0]; |
|
889 |
if ($x) { |
|
890 |
push @data_x, $x; |
|
891 |
push @data_y, $y//0; |
|
892 |
} |
|
893 |
} |
|
894 |
} |
|
895 |
|
|
896 |
my $variables = { |
|
897 |
'TITLE' => $opts->{title}, |
|
898 |
'TOP_INFO_TEXT' => $self->html_format($opts->{top_info_text}), |
|
899 |
'RAW_TOP_INFO_TEXT' => $opts->{raw_top_info_text}, |
|
900 |
'BOTTOM_INFO_TEXT' => $self->html_format($opts->{bottom_info_text}), |
|
901 |
'RAW_BOTTOM_INFO_TEXT' => $opts->{raw_bottom_info_text}, |
|
902 |
'EXPORT_VARIABLE_LIST' => join(' ', @{ $self->{export}->{variable_list} }), |
|
903 |
'EXPORT_NEXTSUB' => $self->{export}->{nextsub}, |
|
904 |
'DATA_PRESENT' => $self->{data_present}, |
|
905 |
'CONTROLLER_DISPATCH' => $opts->{controller_class}, |
|
906 |
'TABLE_CLASS' => $opts->{table_class}, |
|
907 |
'SKIP_BUTTONS' => !!$params{action_bar}, |
|
908 |
}; |
|
909 |
|
|
910 |
$::request->layout->add_javascripts('chart.js', 'kivi.ChartReport.js'); |
|
911 |
|
|
912 |
$::form->header; |
|
913 |
print $::form->parse_html_template('report_generator/chart_report', |
|
914 |
{ |
|
915 |
data_x => to_json(\@data_x), |
|
916 |
data_y => to_json(\@data_y), |
|
917 |
label_x => $assignment_x, |
|
918 |
label_y => $assignment_y, |
|
919 |
%$variables, |
|
920 |
} |
|
921 |
); |
|
922 |
} |
|
923 |
|
|
861 | 924 |
sub check_for_pdf_api { |
862 | 925 |
return eval { require PDF::API2; 1; } ? 1 : 0; |
863 | 926 |
} |
bin/mozilla/reportgenerator.pl | ||
---|---|---|
41 | 41 |
$bar->add( |
42 | 42 |
combobox => [ |
43 | 43 |
action => [ |
44 |
$type eq 'pdf' ? $::locale->text('PDF export') : $::locale->text('CSV export'),
|
|
44 |
$type eq 'pdf' ? $::locale->text('PDF export') : $type eq 'csv' ? $::locale->text('CSV export') : $::locale->text('Chart export'),
|
|
45 | 45 |
submit => [ '#report_generator_form', { 'report_generator_dispatch_to' => "report_generator_export_as_${type}" } ], |
46 | 46 |
], |
47 | 47 |
action => [ |
... | ... | |
126 | 126 |
$main::lxdebug->leave_sub(); |
127 | 127 |
} |
128 | 128 |
|
129 |
sub report_generator_export_as_chart { |
|
130 |
$main::lxdebug->enter_sub(); |
|
131 |
|
|
132 |
my $form = $main::form; |
|
133 |
my $locale = $main::locale; |
|
134 |
|
|
135 |
if ($form->{report_generator_chart_options_set}) { |
|
136 |
report_generator_do('Chart'); |
|
137 |
$main::lxdebug->leave_sub(); |
|
138 |
return; |
|
139 |
} |
|
140 |
|
|
141 |
my $fields = delete $form->{report_generator_chart_fields}; |
|
142 |
my @form_values = $form->flatten_variables(grep { ($_ ne 'login') && ($_ ne 'password') } keys %{ $form }); |
|
143 |
|
|
144 |
$form->{title} = $locale->text('Chart export -- options'); |
|
145 |
|
|
146 |
report_generator_setup_action_bar('chart'); |
|
147 |
|
|
148 |
$form->header(); |
|
149 |
print $form->parse_html_template('report_generator/chart_export_options', { 'HIDDEN' => \@form_values, fields => $fields }); |
|
150 |
|
|
151 |
$main::lxdebug->leave_sub(); |
|
152 |
} |
|
153 |
|
|
129 | 154 |
sub report_generator_back { |
130 | 155 |
$main::lxdebug->enter_sub(); |
131 | 156 |
|
js/kivi.ChartReport.js | ||
---|---|---|
1 |
namespace('kivi.ChartReport', function(ns) { |
|
2 |
"use strict"; |
|
3 |
|
|
4 |
ns.data = undefined; |
|
5 |
|
|
6 |
ns.chart = function() { |
|
7 |
$(ns.data.data_y).each(function(idx) {ns.data.data_y[idx] = kivi.parse_amount('' + ns.data.data_y[idx]);}); |
|
8 |
console.log("bb: data_y (parsed): "); console.log(ns.data.data_y); |
|
9 |
|
|
10 |
const ctx = 'chart'; |
|
11 |
const chart = new Chart(ctx, { |
|
12 |
type: 'bar', |
|
13 |
data: { |
|
14 |
labels: ns.data.data_x, |
|
15 |
datasets: [{ |
|
16 |
label: ns.data.label_y, |
|
17 |
data: ns.data.data_y, |
|
18 |
backgroundColor: [ |
|
19 |
'rgba(255, 99, 132, 0.2)', |
|
20 |
'rgba(54, 162, 235, 0.2)', |
|
21 |
'rgba(255, 206, 86, 0.2)', |
|
22 |
'rgba(75, 192, 192, 0.2)', |
|
23 |
'rgba(153, 102, 255, 0.2)', |
|
24 |
'rgba(255, 159, 64, 0.2)' |
|
25 |
], |
|
26 |
borderColor: [ |
|
27 |
'rgba(255, 99, 132, 1)', |
|
28 |
'rgba(54, 162, 235, 1)', |
|
29 |
'rgba(255, 206, 86, 1)', |
|
30 |
'rgba(75, 192, 192, 1)', |
|
31 |
'rgba(153, 102, 255, 1)', |
|
32 |
'rgba(255, 159, 64, 1)' |
|
33 |
], |
|
34 |
borderWidth: 1 |
|
35 |
}] |
|
36 |
}, |
|
37 |
options: { |
|
38 |
scales: { |
|
39 |
y: { |
|
40 |
beginAtZero: true |
|
41 |
} |
|
42 |
} |
|
43 |
} |
|
44 |
}); |
|
45 |
}; |
|
46 |
|
|
47 |
ns.debug = function() { |
|
48 |
console.log("bb: data_x: "); console.log(ns.data.data_x); |
|
49 |
console.log("bb: data_y: "); console.log(ns.data.data_y); |
|
50 |
console.log("bb: label_x: "); console.log(ns.data.label_x); |
|
51 |
console.log("bb: label_y: "); console.log(ns.data.label_y); |
|
52 |
}; |
|
53 |
|
|
54 |
$(function() { |
|
55 |
kivi.ChartReport.debug(); |
|
56 |
kivi.ChartReport.chart(); |
|
57 |
}); |
|
58 |
}); |
templates/webpages/report_generator/chart_export_options.html | ||
---|---|---|
1 |
[%- USE T8 %] |
|
2 |
[%- USE HTML %] |
|
3 |
[%- USE L %] |
|
4 |
|
|
5 |
<h1>[% HTML.escape(title) %]</h1> |
|
6 |
|
|
7 |
<form action="[% HTML.escape(script) %]" method="post" name="report_generator_form" id="report_generator_form"> |
|
8 |
|
|
9 |
[%- FOREACH var = HIDDEN %] |
|
10 |
<input type="hidden" name="[% HTML.escape(var.key) %]" value="[% HTML.escape(var.value) %]"> |
|
11 |
[%- END %] |
|
12 |
|
|
13 |
<input type="hidden" name="report_generator_chart_options_set" value="1"> |
|
14 |
<input type="hidden" name="report_generator_dispatch_to" value=""> |
|
15 |
|
|
16 |
<table> |
|
17 |
<tr> |
|
18 |
<th valign="top" align="right">[% 'Chart assignments' | $T8 %]: [% 'X axis' | $T8 %]</th> |
|
19 |
<td> |
|
20 |
[% L.select_tag('report_generator_chart_options_assignment_x', |
|
21 |
fields, |
|
22 |
default = SELF.report_generator_chart_options_assignment_x |
|
23 |
value_key = 'name', |
|
24 |
title_key = 'text') %] |
|
25 |
</td> |
|
26 |
</tr> |
|
27 |
<tr> |
|
28 |
<th valign="top" align="right">[% 'Chart assignments' | $T8 %]: [% 'Y axis' | $T8 %]</th> |
|
29 |
<td> |
|
30 |
[% L.select_tag('report_generator_chart_options_assignment_y', |
|
31 |
fields, |
|
32 |
default = SELF.report_generator_chart_options_assignment_y |
|
33 |
value_key = 'name', |
|
34 |
title_key = 'text') %] |
|
35 |
</td> |
|
36 |
</tr> |
|
37 |
</table> |
|
38 |
|
|
39 |
[%- IF CONTROLLER_DISPATCH %] |
|
40 |
<input type="hidden" name="CONTROLLER_DISPATCH" value="[% CONTROLLER_DISPATCH | html %]"> |
|
41 |
[%- ELSE %] |
|
42 |
<input type="hidden" name="action" value="report_generator_dispatcher"> |
|
43 |
[%- END %] |
|
44 |
|
|
45 |
|
|
46 |
</form> |
templates/webpages/report_generator/chart_report.html | ||
---|---|---|
1 |
[% USE P -%] |
|
2 |
|
|
3 |
<h1>[% TITLE %]</h1> |
|
4 |
|
|
5 |
[%- INCLUDE 'common/flash.html' %] |
|
6 |
|
|
7 |
[% IF TOP_INFO_TEXT %] |
|
8 |
<p>[% TOP_INFO_TEXT %]</p> |
|
9 |
[% END %] |
|
10 |
|
|
11 |
[% RAW_TOP_INFO_TEXT %] |
|
12 |
|
|
13 |
<div class="chart-container" style="position: relative;"> |
|
14 |
<canvas id="chart" height="70vH"></canvas> |
|
15 |
</div> |
|
16 |
|
|
17 |
[% RAW_BOTTOM_INFO_TEXT %] |
|
18 |
|
|
19 |
[% IF BOTTOM_INFO_TEXT %] |
|
20 |
<p>[% BOTTOM_INFO_TEXT %]</p> |
|
21 |
[% END %] |
|
22 |
|
|
23 |
|
|
24 |
<script> |
|
25 |
kivi.ChartReport.data = { data_x: [% data_x %], |
|
26 |
data_y: [% data_y %], |
|
27 |
label_y: "[% label_y %]", |
|
28 |
label_x: "[% label_x %]" |
|
29 |
}; |
|
30 |
</script> |
templates/webpages/report_generator/html_report.html | ||
---|---|---|
102 | 102 |
[% FOREACH var = EXPORT_VARIABLES %]<input type="hidden" name="report_generator_hidden_[% var.key %]" value="[% HTML.escape(var.value) %]"> |
103 | 103 |
[% END %] |
104 | 104 |
|
105 |
[% IF ALLOW_CHART_EXPORT %] |
|
106 |
[% FOREACH row = HEADER_ROWS %] |
|
107 |
[% FOREACH col = row %] |
|
108 |
[% IF col.name && col.text %] |
|
109 |
<input type="hidden" name="report_generator_chart_fields[+].name" value="[% HTML.escape(col.name) %]"> |
|
110 |
<input type="hidden" name="report_generator_chart_fields[].text" value="[% HTML.escape(col.text) %]"> |
|
111 |
[% END %] |
|
112 |
[% END %] |
|
113 |
[% END %] |
|
114 |
[% END %] |
|
115 |
|
|
105 | 116 |
[%- IF CONTROLLER_DISPATCH %] |
106 | 117 |
[% IF !SKIP_BUTTONS %] |
107 | 118 |
<input type="hidden" name="action" value="[% CONTROLLER_DISPATCH %]/dispatch"> |
Auch abrufbar als: Unified diff
Reports als Chart exportieren können