From 86b99a8982a34845dcb1e9e4a76880da48254c72 Mon Sep 17 00:00:00 2001 From: miker Date: Fri, 18 Nov 2005 09:29:07 +0000 Subject: [PATCH] yay! the reporter spits out csv and excel now ... html tomorrow (with any luck) git-svn-id: svn://svn.open-ils.org/ILS/trunk@2066 dcc99617-32d9-48b4-a31d-7c20da2025e4 --- Open-ILS/src/perlmods/OpenILS/WWW/Reporter.pm | 11 +- Open-ILS/src/reporter/clark-kent.pl | 266 ++++++++++++++---- Open-ILS/src/reporter/config.sql | 20 +- Open-ILS/src/reporter/templates/dashboard.ttk | 3 +- Open-ILS/src/reporter/templates/header.ttk | 2 + Open-ILS/src/reporter/templates/html/cell | 1 + Open-ILS/src/reporter/templates/html/center | 1 + Open-ILS/src/reporter/templates/html/table | 1 + Open-ILS/src/reporter/templates/inputs | 10 +- .../src/reporter/templates/select_sorter.js | 147 ++++++++++ Open-ILS/src/reporter/templates/stage1.ttk | 56 +--- Open-ILS/src/reporter/templates/stage2.ttk | 154 +++++++--- Open-ILS/src/reporter/templates/stage3.ttk | 96 ++++++- 13 files changed, 614 insertions(+), 154 deletions(-) create mode 100644 Open-ILS/src/reporter/templates/html/center create mode 100644 Open-ILS/src/reporter/templates/select_sorter.js diff --git a/Open-ILS/src/perlmods/OpenILS/WWW/Reporter.pm b/Open-ILS/src/perlmods/OpenILS/WWW/Reporter.pm index ecbb273914..d9d4ecccc7 100644 --- a/Open-ILS/src/perlmods/OpenILS/WWW/Reporter.pm +++ b/Open-ILS/src/perlmods/OpenILS/WWW/Reporter.pm @@ -55,12 +55,18 @@ sub child_init { sub handler { my $apache = shift; + return Apache2::Const::DECLINED if (-e $apache->filename); + my $cgi = CGI->new; my $path = $apache->path_info; (my $ttk = $path) =~ s{^/?([a-zA-Z0-9_]+).*?$}{$1}o; - $ttk = "s1" unless $ttk; + $ttk = $apache->filename unless $ttk; + $ttk = "dashboard" unless $ttk; + + $ttk = (split '/', $ttk)[-1]; + my $user; # if the user is not logged in via cookie, route them to the login page @@ -68,6 +74,7 @@ sub handler { $ttk = "login"; } + print "Content-type: text/html; charset=utf-8\n\n"; _process_template( @@ -91,7 +98,7 @@ sub _process_template { my $apache = $params{apache} || undef; my $param_hash = $params{params} || {}; $$param_hash{dtype_xform_map} = $OpenILS::WWW::Reporter::dtype_xform_map; - $$param_hash{dtype_xform} = $OpenILS::WWW::Reporter::dtype_xform; + $$param_hash{dtype_xforms} = $OpenILS::WWW::Reporter::dtype_xforms; my $template; diff --git a/Open-ILS/src/reporter/clark-kent.pl b/Open-ILS/src/reporter/clark-kent.pl index 438efb6cca..9a5a50b21d 100755 --- a/Open-ILS/src/reporter/clark-kent.pl +++ b/Open-ILS/src/reporter/clark-kent.pl @@ -2,6 +2,7 @@ use strict; use DBI; +use FileHandle; use XML::LibXML; use Getopt::Long; use DateTime; @@ -9,13 +10,19 @@ use DateTime::Format::ISO8601; use JSON; use Data::Dumper; use OpenILS::WWW::Reporter::transforms; +use Text::CSV_XS; +use Spreadsheet::WriteExcel; +use OpenSRF::EX qw/:try/; +use OpenSRF::Utils qw/:daemon/; +use OpenSRF::Utils::Logger qw/:level/; my $current_time = DateTime->from_epoch( epoch => time() )->strftime('%FT%T%z'); -my ($base_xml, $count) = ('/openils/conf/reporter.xml', 1); +my ($base_xml, $count, $daemon) = ('/openils/conf/reporter.xml', 1); GetOptions( "file=s" => \$base_xml, + "daemon" => \$daemon, "concurrency=i" => \$count, ); @@ -24,8 +31,6 @@ $parser->expand_xinclude(1); my $doc = $parser->parse_file($base_xml); -warn $doc->toString; - my $db_driver = $doc->findvalue('/reporter/setup/database/driver'); my $db_host = $doc->findvalue('/reporter/setup/database/host'); my $db_name = $doc->findvalue('/reporter/setup/database/name'); @@ -34,12 +39,36 @@ my $db_pw = $doc->findvalue('/reporter/setup/database/password'); my $dsn = "dbi:" . $db_driver . ":dbname=" . $db_name .';host=' . $db_host; -my $dbh = DBI->connect($dsn,$db_user,$db_pw); +my $dbh; + +daemonize("Clark Kent, waiting for trouble") if ($daemon); + +DAEMON: + +$dbh = DBI->connect($dsn,$db_user,$db_pw); + +# Move new reports into the run queue +$dbh->do(<<'SQL', {}, $current_time); +INSERT INTO reporter.output ( stage3, state ) + SELECT id, 'wait' + FROM reporter.stage3 + WHERE runtime <= $1 + AND ( ( recurrence = '0 seconds'::INTERVAL + AND id NOT IN ( SELECT stage3 FROM reporter.output ) ) + OR ( recurrence > '0 seconds'::INTERVAL + AND id NOT IN ( + SELECT stage3 + FROM reporter.output + WHERE state <> 'complete') + ) + ) + ORDER BY runtime; +SQL # make sure we're not already running $count reports my ($running) = $dbh->selectrow_array(<prepare(<execute($current_time); +$sth->execute; my @reports; while (my $r = $sth->fetchrow_hashref) { - $r->{sql} = generate_query( $r ); + my $s3 = $dbh->selectrow_hashref(<<" SQL", {}, $r->{stage3}); + SELECT * FROM reporter.stage3 WHERE id = ?; + SQL + + my $s2 = $dbh->selectrow_hashref(<<" SQL", {}, $s3->{stage2}); + SELECT * FROM reporter.stage2 WHERE id = ?; + SQL + + $s3->{stage2} = $s2; + $r->{stage3} = $s3; + + generate_query( $r ); push @reports, $r; } + $sth->finish; +$dbh->disconnect; + +# Now we spaun the report runners + for my $r ( @reports ) { - my $sql = shift @{ $r->{sql} }; + next if (safe_fork()); - $sth = $dbh->prepare($sql); + # This is the child (runner) process; + my $p = JSON->JSON2perl( $r->{stage3}->{params} ); + daemonize("Clark Kent reporting: $p->{reportname}"); - $sth->execute(@{ $r->{sql} }); - while (my $row = $sth->fetchrow_hashref) { - print join(', ', map {"$_\t=> $$row{$_}"} keys %$row)."\n"; - } + $dbh = DBI->connect($dsn,$db_user,$db_pw); + + try { + + $dbh->do(<<' SQL',{}, $r->{sql}->{'select'}, $$, $r->{id}); + UPDATE reporter.output + SET state = 'running', + run_time = 'now', + query = ?, + run_pid = ? + WHERE id = ?; + SQL + + $sth = $dbh->prepare($r->{sql}->{'select'}); + + $sth->execute(@{ $r->{sql}->{'bind'} }); + $r->{data} = $sth->fetchall_arrayref; + + my $base = $doc->findvalue('/reporter/setup/files/output_base'); + my $s1 = $r->{stage3}->{stage2}->{stage1}; + my $s2 = $r->{stage3}->{stage2}->{id}; + my $s3 = $r->{stage3}->{id}; + my $output = $r->{id}; + + mkdir($base); + mkdir("$base/$s1"); + mkdir("$base/$s1/$s2"); + mkdir("$base/$s1/$s2/$s3"); + mkdir("$base/$s1/$s2/$s3/$output"); + + my @formats; + if (ref $p->{output_format}) { + @formats = @{ $p->{output_format} }; + } else { + @formats = ( $p->{output_format} ); + } + + if ( grep { $_ eq 'csv' } @formats ) { + build_csv("$base/$s1/$s2/$s3/$output/report-data.csv", $r); + } + + if ( grep { $_ eq 'excel' } @formats ) { + build_excel("$base/$s1/$s2/$s3/$output/report-data.xls", $r); + } + + if ( grep { $_ eq 'html' } @formats ) { + mkdir("$base/$s1/$s2/$s3/$output/html"); + build_html("$base/$s1/$s2/$s3/$output/report-data.html", $r); + } + + + $dbh->begin_work; + $dbh->do(<<' SQL',{}, $r->{stage3}->{id}); + UPDATE reporter.stage3 + SET runtime = runtime + recurrence + WHERE id = ? AND recurrence > '0 seconds'::INTERVAL; + SQL + $dbh->do(<<' SQL',{}, $r->{id}); + UPDATE reporter.output + SET state = 'complete', + complete_time = 'now' + WHERE id = ?; + SQL + $dbh->commit; + + + } otherwise { + my $e = shift; + $dbh->rollback; + $dbh->do(<<' SQL',{}, $e, $r->{id}); + UPDATE reporter.output + SET state = 'error', + error_time = 'now', + error = ?, + run_pid = NULL + WHERE id = ?; + SQL + }; + + $dbh->disconnect; + + exit; # leave the child } +if ($daemon) { + sleep 60; + goto DAEMON; +} #------------------------------------------------------------------- +sub build_csv { + my $file = shift; + my $r = shift; + + my $csv = Text::CSV_XS->new({ always_quote => 1, eol => "\015\012" }); + my $f = new FileHandle (">$file"); + + $csv->print($f, $r->{sql}->{columns}); + $csv->print($f, $_) for (@{$r->{data}}); + + $f->close; +} +sub build_excel { + my $file = shift; + my $r = shift; + my $p = JSON->JSON2perl( $r->{stage3}->{params} ); + + my $xls = Spreadsheet::WriteExcel->new($file); + my $sheet = $xls->add_worksheet($p->{reportname}); + + $sheet->write_row('A1', $r->{sql}->{columns}); + + $sheet->write_col('A2', $r->{data}); + + $xls->close; +} + +sub build_html {} + sub table_by_id { my $id = shift; my ($node) = $doc->findnodes("//*[\@id='$id']"); @@ -91,36 +250,26 @@ sub table_by_id { } sub generate_query { - my $s3 = shift; - warn Dumper($s3); - - my $r = JSON->JSON2perl( $s3->{params} ); - warn Dumper($r); + my $r = shift; - my $s2 = $dbh->selectrow_hashref(<<" SQL", {}, $s3->{stage2}); - SELECT * - FROM reporter.stage2 - WHERE id = ? - SQL - warn Dumper($s2); + my $p = JSON->JSON2perl( $r->{stage3}->{params} ); my @group_by; my @aggs; - my $core = $s2->{stage1}; + my $core = $r->{stage3}->{stage2}->{stage1}; my @dims; - for my $t (keys %{$$r{filter}}) { + for my $t (keys %{$$p{filter}}) { if ($t ne $core) { push @dims, $t; } } - for my $t (keys %{$$r{output}}) { + for my $t (keys %{$$p{output}}) { if ($t ne $core && !grep { $t } @dims ) { push @dims, $t; } } - warn Dumper(\@dims); my @dim_select; my @dim_from; @@ -132,12 +281,12 @@ sub generate_query { my $k = $doc->findvalue("//*[\@id='$d']/\@key"); push @dim_select, "\"$d\".\"$k\" AS \"${d}_${k}\""; - for my $c ( keys %{$$r{output}{$d}} ) { + for my $c ( keys %{$$p{output}{$d}} ) { push @dim_select, "\"$d\".\"$c\" AS \"${d}_${c}\""; } - for my $c ( keys %{$$r{filter}{$d}} ) { - next if (exists $$r{output}{$d}{$c}); + for my $c ( keys %{$$p{filter}{$d}} ) { + next if (exists $$p{output}{$d}{$c}); push @dim_select, "\"$d\".\"$c\" AS \"${d}_${c}\""; } } @@ -146,19 +295,23 @@ sub generate_query { '(SELECT ' . join(',', @dim_select) . ' FROM ' . join(',', @dim_from) . ') AS dims'; - warn "*** [$d_select]\n"; - + my @output_order = map { { (split ':')[1] => (split ':')[2] } } @{ $$p{output_order} }; + my $col = 1; my @groupby; my @output; + my @columns; my @join; - for my $t ( keys %{$$r{output}} ) { - my $t_name = $t; + my @join_base; + for my $pair (@output_order) { + my ($t_name) = keys %$pair; + my $t = $t_name; + $t_name = "dims" if ($t ne $core); my $t_node = table_by_id($t); - for my $c ( keys %{$$r{output}{$t}} ) { + for my $c ( values %$pair ) { my $label = $t_node->findvalue("fields/field[\@name='$c']/label"); my $full_col = $c; @@ -166,7 +319,7 @@ sub generate_query { $full_col = "\"$t_name\".\"$full_col\""; - if (my $xform_type = $$r{xform}{type}{$t}{$c}) { + if (my $xform_type = $$p{xform}{type}{$t}{$c}) { my $xform = $$OpenILS::WWW::Reporter::dtype_xforms{$xform_type}; if ($xform->{group}) { push @groupby, $col; @@ -175,32 +328,34 @@ sub generate_query { my $tmp = $xform->{'select'}; $tmp =~ s/\?COLNAME\?/$full_col/gs; - $tmp =~ s/\?PARAM\?/$$r{xform}{param}{$t}{$c}/gs; + $tmp =~ s/\?PARAM\?/$$p{xform}{param}{$t}{$c}/gs; $full_col = $tmp; } else { push @groupby, $col; } push @output, "$full_col AS \"$label\""; + push @columns, $label; $col++; } - if ($t ne $t_name) { + if ($t ne $t_name && (!@join_base || !grep{$t eq $_}@join_base)) { my $k = $doc->findvalue("//*[\@id='$t']/\@key"); my $f = $doc->findvalue("//*[\@id='$t']/\@field"); push @join, "dims.\"${t}_${k}\" = \"$core\".\"$f\""; + push @join_base, $t; } } my @where; my @bind; - for my $t ( keys %{$$r{filter}} ) { + for my $t ( keys %{$$p{filter}} ) { my $t_name = $t; $t_name = "dims" if ($t ne $core); my $t_node = table_by_id($t); - for my $c ( keys %{$$r{filter}{$t}} ) { + for my $c ( keys %{$$p{filter}{$t}} ) { my $label = $t_node->findvalue("fields/field[\@name='$c']/label"); my $full_col = $c; @@ -209,9 +364,9 @@ sub generate_query { # XXX make this use widget specific code - my ($fam) = keys %{ $$r{filter}{$t}{$c} }; - my ($w) = keys %{ $$r{filter}{$t}{$c}{$fam} }; - my $val = $$r{filter}{$t}{$c}{$fam}{$w}; + my ($fam) = keys %{ $$p{filter}{$t}{$c} }; + my ($w) = keys %{ $$p{filter}{$t}{$c}{$fam} }; + my $val = $$p{filter}{$t}{$c}{$fam}{$w}; if (ref $val) { push @where, "$full_col IN (".join(",",map {'?'}@$val).")"; @@ -221,6 +376,13 @@ sub generate_query { push @bind, $val; } } + + if ($t ne $t_name && (!@join_base || !grep{$t eq $_}@join_base)) { + my $k = $doc->findvalue("//*[\@id='$t']/\@key"); + my $f = $doc->findvalue("//*[\@id='$t']/\@field"); + push @join, "dims.\"${t}_${k}\" = \"$core\".\"$f\""; + push @join_base, $t; + } } my $t = table_by_id($core)->findvalue('tablename'); @@ -231,10 +393,10 @@ sub generate_query { ' WHERE '.join(' AND ', @where). ' GROUP BY '.join(',',@groupby); - warn " !!! [$select]\n"; - warn " !!! [".join(', ',@bind)."]\n"; - - return [ $select, @bind ]; + $r->{sql}->{'select'} = $select; + $r->{sql}->{'bind'} = \@bind; + $r->{sql}->{columns} = \@columns; + } diff --git a/Open-ILS/src/reporter/config.sql b/Open-ILS/src/reporter/config.sql index 9cc8bd8d7d..a8237e835d 100644 --- a/Open-ILS/src/reporter/config.sql +++ b/Open-ILS/src/reporter/config.sql @@ -46,7 +46,7 @@ CREATE TABLE reporter.stage3 ( recurrence interval ); -CREATE TABLE reporter.run_queue ( +CREATE TABLE reporter.output ( id serial primary key, stage3 int not null references reporter.stage3 (id) @@ -55,20 +55,12 @@ CREATE TABLE reporter.run_queue ( initially deferred, queue_time timestamp with time zone not null default now(), run_time timestamp with time zone, + run_pid int, + query text, + error text, + error_time timestamp with time zone, complete_time timestamp with time zone, - state text check (state in ('wait','running','complete')) -); - -CREATE TABLE reporter.output ( - id int primary key, - stage3 int not null - references reporter.stage3 (id) - on delete restrict - deferrable - initially deferred, - queue_time timestamp with time zone not null default now(), - run_time timestamp with time zone not null, - complete_time timestamp with time zone not null + state text check (state in ('wait','running','complete','error')) ); COMMIT; diff --git a/Open-ILS/src/reporter/templates/dashboard.ttk b/Open-ILS/src/reporter/templates/dashboard.ttk index e5a6f2b22a..8cbfc1db38 100644 --- a/Open-ILS/src/reporter/templates/dashboard.ttk +++ b/Open-ILS/src/reporter/templates/dashboard.ttk @@ -122,6 +122,7 @@ BLOCK show_reports; INCLUDE html/cell content='Recurrence' nowrap='nowrap' col='lightgray' style='border:solid gray 1px;'; END; FOR report = DBI.query(q); + rid = report.id; bg='lightblue'; IF loop.count % 2; bg='white'; @@ -129,7 +130,7 @@ BLOCK show_reports; WRAPPER html/row; p = utils.JSON2perl( report.params ); INCLUDE html/cell content=(report.pub ? 'Y' : 'N') col=bg style='border:solid gray 1px;' align='center'; - INCLUDE html/cell content=p.reportname col=bg style='border:solid gray 1px;'; + INCLUDE html/cell content=link(content=p.reportname,href="stage3?id=$rid") col=bg style='border:solid gray 1px;'; INCLUDE html/cell content=report.create_date.chunk(10).0 col=bg style='border:solid gray 1px;'; INCLUDE html/cell content=report.runtime.chunk(10).0 col=bg style='border:solid gray 1px;'; INCLUDE html/cell content=report.recurrence col=bg style='border:solid gray 1px;'; diff --git a/Open-ILS/src/reporter/templates/header.ttk b/Open-ILS/src/reporter/templates/header.ttk index 7cce23f024..28e7de91e0 100644 --- a/Open-ILS/src/reporter/templates/header.ttk +++ b/Open-ILS/src/reporter/templates/header.ttk @@ -13,5 +13,7 @@ + + [% content %] diff --git a/Open-ILS/src/reporter/templates/html/cell b/Open-ILS/src/reporter/templates/html/cell index 890ab80a06..8a9d680f2c 100644 --- a/Open-ILS/src/reporter/templates/html/cell +++ b/Open-ILS/src/reporter/templates/html/cell @@ -14,6 +14,7 @@ [%- IF colspan %] colspan="[% colspan %]"[% END %] [%- IF rowspan %] rowspan="[% rowspan %]"[% END %] [%- IF align %] align="[% align %]"[% END %] + [%- IF padding %] padding="[% padding %]"[% END %] [%- IF class %] class="[% class %]"[% END %] [%- IF id %] id="[% id %]"[% END %] [%- IF valign %] valign="[% valign %]"[% END %] diff --git a/Open-ILS/src/reporter/templates/html/center b/Open-ILS/src/reporter/templates/html/center new file mode 100644 index 0000000000..c72e721df3 --- /dev/null +++ b/Open-ILS/src/reporter/templates/html/center @@ -0,0 +1 @@ +
[% content %]
diff --git a/Open-ILS/src/reporter/templates/html/table b/Open-ILS/src/reporter/templates/html/table index 7b0095941a..1a2a83a46a 100644 --- a/Open-ILS/src/reporter/templates/html/table +++ b/Open-ILS/src/reporter/templates/html/table @@ -12,6 +12,7 @@ [%- IF width %] width="[% width %]"[% END %] [%- IF pad.defined %] cellpadding="[% pad %]"[% END %] [%- IF class %] class="[% class %]"[% END %] + [%- IF style %] style="[% style %]"[% END %] [%- IF id %] id="[% id %]"[% END %] [%- IF cellspace.defined %] cellspacing="[% cellspace %]"[% END %]> [%- content -%] diff --git a/Open-ILS/src/reporter/templates/inputs b/Open-ILS/src/reporter/templates/inputs index db967acc4c..5f86ad238b 100644 --- a/Open-ILS/src/reporter/templates/inputs +++ b/Open-ILS/src/reporter/templates/inputs @@ -42,7 +42,7 @@ BLOCK textarea; END; BLOCK select; - %][% content; %][% END; @@ -66,11 +66,15 @@ BLOCK radio; END; BLOCK checkbox; - %][% + %][% END; BLOCK submit; - %][% + %][% +END; + +BLOCK button; + %][% END; MACRO link INCLUDE anchor; diff --git a/Open-ILS/src/reporter/templates/select_sorter.js b/Open-ILS/src/reporter/templates/select_sorter.js new file mode 100644 index 0000000000..868408f608 --- /dev/null +++ b/Open-ILS/src/reporter/templates/select_sorter.js @@ -0,0 +1,147 @@ + diff --git a/Open-ILS/src/reporter/templates/stage1.ttk b/Open-ILS/src/reporter/templates/stage1.ttk index 8aed7c2d36..45b56700d7 100644 --- a/Open-ILS/src/reporter/templates/stage1.ttk +++ b/Open-ILS/src/reporter/templates/stage1.ttk @@ -13,11 +13,6 @@ WRAPPER html/html; "document.getElementById('templatename').focus();" _ "document.getElementById('templatename').select();}"; IF !CGI.param('id'); - IF CGI.param('detail'); - %]No Details (All)[% - ELSE; - %]Details (All)[% - END; INCLUDE all_stage1; ELSE; INCLUDE one_stage1; @@ -33,12 +28,6 @@ END; BLOCK one_stage1; - %]Show all[% - table_xpath = '/reporter/tables/table[@id="' _ CGI.param('id') _ '"]'; @@ -85,27 +74,16 @@ BLOCK stage2_new; %]
- -
- - Public template

[% + +
+ Template name (required):


+
+ Select Filter Widgets
[% WRAPPER html/table width="100%" style='border-top: 1px solid black'; WRAPPER html/row; - WRAPPER html/cell; - WRAPPER html/table + html/row width='100%'; - INCLUDE html/cell content='Report Base'; - END; - WRAPPER html/table + html/row width='100%'; - INCLUDE html/cell content='Attribute' align='right'; - END; - END; - INCLUDE html/cell content='Widget' align='center'; - END; - WRAPPER html/row; - WRAPPER html/cell colspan=2; + WRAPPER html/cell colspan=2 align='center' style="border: solid black 1px; background: lightgray;"; # hidden input here ... table = config.findnodes("/reporter/tables/table[@id='$fact_table']"); INCLUDE hidden name="filter" value=fact_table; @@ -113,6 +91,10 @@ BLOCK stage2_new; ' Core Columns'; END; END; + #WRAPPER html/row; + # INCLUDE html/cell content='Attribute' align='right'; + # INCLUDE html/cell content='Widget' align='center'; + #END; INCLUDE widget_selector tableid=fact_table columns=config.findnodes(col_xpath) force=1; END; @@ -126,18 +108,7 @@ BLOCK stage2_new; WRAPPER html/table width="100%" style='border-top: 1px solid black'; WRAPPER html/row; - WRAPPER html/cell; - WRAPPER html/table + html/row width='100%'; - INCLUDE html/cell content='Dimension'; - END; - WRAPPER html/table + html/row width='100%'; - INCLUDE html/cell content='Attribute' align='right'; - END; - END; - INCLUDE html/cell content='Widget' align='center'; - END; - WRAPPER html/row; - WRAPPER html/cell colspan=2; + WRAPPER html/cell colspan=2 align='center' style="border: solid black 1px; background: lightgray;"; # checkbox input here ... INCLUDE checkbox name="filter" value=link_id checked=1; @@ -153,9 +124,12 @@ BLOCK stage2_new; END; END; + %] + Public template

+ [% INCLUDE submit name='button' value='Save'; - %]
[% + ''; END; diff --git a/Open-ILS/src/reporter/templates/stage2.ttk b/Open-ILS/src/reporter/templates/stage2.ttk index 0bd913e78e..cb3d107aff 100644 --- a/Open-ILS/src/reporter/templates/stage2.ttk +++ b/Open-ILS/src/reporter/templates/stage2.ttk @@ -1,24 +1,27 @@ [% -PROCESS inputs; -PROCESS class_manip; -PROCESS widget_manip; -PROCESS logic_header.ttk; -INCLUDE logout.ttk; +WRAPPER html/html; + WRAPPER header.ttk + navbar.ttk title="Report Templates"; + PROCESS inputs; + PROCESS class_manip; + PROCESS widget_manip; + PROCESS logic_header.ttk; + INCLUDE logout.ttk; + END; -templates = DBI.tie('reporter.stage2', 'id') -tmpl = {}; + WRAPPER html/body; + PROCESS select_sorter.js; -IF CGI.param('id'); - tid = CGI.param('id'); - tmpl = templates.$tid; -END; + templates = DBI.tie('reporter.stage2', 'id') + tmpl = {}; -WRAPPER html/html; - INCLUDE header.ttk + navbar.ttk title="Report Templates"; - WRAPPER html/body; + IF CGI.param('id'); + tid = CGI.param('id'); + tmpl = templates.$tid; + END; + IF CGI.param('action') == 'save'; PROCESS save_stage2; ELSIF CGI.param('action') == 'edit'; @@ -232,40 +235,90 @@ BLOCK run_stage2; logme(tmpl.params); params = utils.JSON2perl( tmpl.params ); - '
'; + %] + +
+ [% + + WRAPPER html/table width="100%"; + WRAPPER html/row; + WRAPPER html/cell align='center'; + s1_name_xpath = '/reporter/tables/table[@id="' _ params.stage1 _ '"]/label'; + INCLUDE anchor + content=config.findvalue( s1_name_xpath ) + href="stage1?id=" _ params.stage1; + ' :: ' _ params.templatename; + END; + END; + END; + + '

'; + WRAPPER form id="stage3_new" name="stage3_new" action="stage3" method="POST"; INCLUDE hidden name='stage2' value=CGI.param('id'); - '
Report Name:'; - INCLUDE text name='reportname'; + '
Report Name:'; + INCLUDE text name='reportname' size="50"; + '


'; - WRAPPER html/table border=0 width='100%'; + WRAPPER html/table width="100%"; + WRAPPER html/row style="border-top: solid black 2px;"; + INCLUDE html/cell colspan=2 content='Output and Sort Order' style="border-top: solid black 2px;"; + INCLUDE html/cell colspan=2 content='Output Formats' align="center" style="border-top: solid black 2px;"; + END; WRAPPER html/row; - WRAPPER html/cell colspan=4 align='center'; - s1_name_xpath = '/reporter/tables/table[@id="' _ params.stage1 _ '"]/label'; - INCLUDE anchor - content=config.findvalue( s1_name_xpath ) - href="stage1?id=" _ params.stage1; - ' :: ' _ params.templatename; + WRAPPER html/cell rowspan=3 width="25%"; + INCLUDE select multi=1 size=5 id='output_order' name='output_order'; + END; + WRAPPER html/cell; + INCLUDE anchor href='javascript:void(0);' content='Up' onclick="Widget.Select.moveSelectedOptionsUp('output_order')"; END; + + WRAPPER html/cell align="right"; + INCLUDE checkbox name='output_format' value='csv'; + END; + INCLUDE html/cell content="CSV" align="left"; END; + WRAPPER html/row; + WRAPPER html/cell; + INCLUDE anchor href='javascript:void(0);' content='Down' onclick="Widget.Select.moveSelectedOptionsDown('output_order')"; + END; + WRAPPER html/cell align="right"; + INCLUDE checkbox name='output_format' value='excel'; + END; + INCLUDE html/cell content="Excel" align="left"; + END; WRAPPER html/row; - INCLUDE html/cell colspan=4 content="Filterable Attributes:"; + INCLUDE html/cell; + WRAPPER html/cell align="right"; + INCLUDE checkbox name='output_format' value='html'; + END; + INCLUDE html/cell content="HTML" align="left"; + END; + END; + + '

'; + + WRAPPER html/table border=0 width='100%'; + WRAPPER html/row; + INCLUDE html/cell colspan=4 content="Filterable Attributes

" style="border-top: solid black 2px;"; END; core_table = params.stage1; tables = params.filter.keys; - tables.unshift(core_table); + tables.unshift(core_table) IF tables.grep("^$core_table$"); tables = tables.unique; FOR t = tables; + NEXT UNLESS params.filter.$t.keys; f_table = INCLUDE find_table_id id=t; - logme([f_table]); table = config.findnodes( "/reporter/tables/table[@id='$f_table']"); WRAPPER html/row; - WRAPPER html/cell colspan=3 align='left'; + WRAPPER html/cell colspan=3 align='center' style="border: solid black 1px; background: lightgray;"; IF t != f_table; link_xpath = '//*[@id="' _ t _ '"]'; dim_link = config.findnodes(link_xpath); @@ -321,7 +374,7 @@ BLOCK run_stage2; END; WRAPPER html/row; - INCLUDE html/cell colspan=4 content="Attributes Available for Output"; + INCLUDE html/cell colspan=4 content="Attributes Available for Output

" style="border-top: solid black 2px;"; END; table = config.findnodes( "/reporter/tables/table[@id='$core_table']" ); @@ -330,7 +383,7 @@ BLOCK run_stage2; tdesc = table.findvalue( "desription" ); WRAPPER html/row; - INCLUDE html/cell colspan=4 align='left' content=tname; + INCLUDE html/cell colspan=4 align='center' content=tname style="border: solid black 1px; background: lightgray;"; END; pkey_field = table.findnodes('fields/field[@primary = "true"]'); @@ -339,8 +392,14 @@ BLOCK run_stage2; WRAPPER html/row; WRAPPER html/cell align='right'; - INCLUDE checkbox checked='checked' name="output:$classname:$pid" value="include"; + INCLUDE checkbox checked='checked' name="output:$classname:$pid" value="include" onclick="field_add_remove(this)"; INCLUDE hidden name="xform:type:$classname:$pid" value="count_dist"; + %] + + [% END; INCLUDE html/cell align='right' content="Per group count of $plabel"; INCLUDE html/cell align='center'; @@ -357,13 +416,17 @@ BLOCK run_stage2; noheader = 0; noheader = 1 IF f_table == core_table; INCLUDE show_filter_atts; + WRAPPER html/row; + INCLUDE html/cell colspan=4 content="

"; + END; END; END; + INCLUDE checkbox name="publicreport" value="t"; 'Public Report
'; - INCLUDE submit name="action" value="Run Now"; - INCLUDE submit name="action" value="Schedule"; + INCLUDE submit name="action" value="Run Now" onclick="Widget.Select.selectAll('output_order');this.form.submit();"; + INCLUDE submit name="action" value="Schedule" onclick="Widget.Select.selectAll('output_order');this.form.submit();"; END; END; @@ -378,7 +441,7 @@ BLOCK show_filter_atts; IF ! noheader; WRAPPER html/row; - WRAPPER html/cell colspan=4 align='left'; + WRAPPER html/cell colspan=4 align='center' style="border: solid black 1px; background: lightgray;"; IF t != f_table; link_xpath = '//*[@id="' _ t _ '"]'; dim_link = config.findnodes(link_xpath); @@ -397,6 +460,9 @@ BLOCK show_filter_atts; fields_xpath = 'fields/field[not(@primary) or @primary != "true"]'; + + count = 1; + FOR field = table.findnodes(fields_xpath); link_test = '../../links/link[@field="' _ field.findvalue('@name') _ '"]'; logme(['link_test',link_test]); @@ -405,13 +471,24 @@ BLOCK show_filter_atts; fname = field.findvalue( "label" ); fid = field.findvalue( "@name" ); + bg_color = 'white'; + IF count % 2; + bg_color = 'lightcyan'; + END; + WRAPPER html/row; - WRAPPER html/cell align='right'; - INCLUDE checkbox name="output:$t:$fid" value="include"; + WRAPPER html/cell align='right' col=bg_color; + INCLUDE checkbox name="output:$t:$fid" value="include" onclick="field_add_remove(this)"; + %] + + [% + END; - INCLUDE html/cell align='right' content=fname; - WRAPPER html/cell align='center'; + INCLUDE html/cell align='right' content=fname col=bg_color; + WRAPPER html/cell align='right' col=bg_color; 'Output Transformation: '; dtype = field.findvalue('@datatype'); WRAPPER select name="xform:type:$t:$fid"; @@ -429,6 +506,7 @@ BLOCK show_filter_atts; INCLUDE text name="xform:param:$t:$fid"; END; END; + count = count + 1; END; END; %] diff --git a/Open-ILS/src/reporter/templates/stage3.ttk b/Open-ILS/src/reporter/templates/stage3.ttk index 06a2c8aad4..0edafb1446 100644 --- a/Open-ILS/src/reporter/templates/stage3.ttk +++ b/Open-ILS/src/reporter/templates/stage3.ttk @@ -13,10 +13,10 @@ tmpl = {}; IF CGI.param('id'); - tid = CGI.param('stage2'); - tmpl = templates.$tid; rid = CGI.param('id'); rpt = reports.$rid; + tid = rpt.stage2; + tmpl = templates.$tid; END; @@ -182,9 +182,99 @@ END; BLOCK view_stage3; logme(rpt.params); params = utils.JSON2perl( rpt.params ); + s2_params = utils.JSON2perl( tmpl.params ); + - # stuff goes here ... + WRAPPER html/center; + WRAPPER html/table style="border-collapse:collapse"; + WRAPPER html/row; + INCLUDE html/cell content="Report Name" style="border:solid gray 1px;"; + INCLUDE html/cell content=params.reportname style="border:solid gray 1px;"; + END; + WRAPPER html/row; + INCLUDE html/cell content="Based on Template" style="border:solid gray 1px;"; + INCLUDE html/cell content=s2_params.templatename style="border:solid gray 1px;"; + END; + WRAPPER html/row; + INCLUDE html/cell content="Creation Time" style="border:solid gray 1px;"; + INCLUDE html/cell content=rpt.create_date style="border:solid gray 1px;"; + END; + WRAPPER html/row; + INCLUDE html/cell content="Scheduled Run Time" style="border:solid gray 1px;"; + INCLUDE html/cell content=rpt.runtime style="border:solid gray 1px;"; + END; + WRAPPER html/row; + INCLUDE html/cell content="Recurrence Interval" style="border:solid gray 1px;"; + INCLUDE html/cell content=rpt.recurrence style="border:solid gray 1px;"; + END; + END; + END; + '

'; + + type_map = { 'csv' => 'csv', 'excel' => 'xls', 'html' => 'html' }; + + WRAPPER html/center; + 'Report Runs:'; + run_q = DBI.prepare("SELECT * FROM reporter.output WHERE stage3 = ? ORDER BY queue_time DESC"); + FOR run = run_q.execute(rpt.id); + WRAPPER html/table style="border-collapse:collapse"; + WRAPPER html/row; + INCLUDE html/cell content="Current State" style="border:solid gray 1px;" width="20%"; + WRAPPER html/cell style="border:solid gray 1px;"; + run.state; + IF run.state == 'complete'; + '
'; + FOR f = params.output_format.list; + h = tmpl.stage1 _ '/' _ tmpl.id _ + '/' _ rpt.id _ '/' _ run.id _ + '/report-data.' _ type_map.$f; + link(content=f, href=h); + IF !loop.last; + ' | '; + END; + END; + END; + END; + END; + WRAPPER html/row; + INCLUDE html/cell content="Queue Time" style="border:solid gray 1px;"; + INCLUDE html/cell content=run.queue_time style="border:solid gray 1px;"; + END; + IF run.run_time; + WRAPPER html/row; + INCLUDE html/cell content="Run Time" style="border:solid gray 1px;"; + INCLUDE html/cell content=run.run_time style="border:solid gray 1px;"; + END; + END; + IF run.complete_time; + WRAPPER html/row; + INCLUDE html/cell content="Complete Time" style="border:solid gray 1px;"; + INCLUDE html/cell content=run.complete_time style="border:solid gray 1px;"; + END; + END; + IF run.query; + WRAPPER html/row; + INCLUDE html/cell content="Query" style="border:solid gray 1px;"; + INCLUDE html/cell content=run.query style="border:solid gray 1px;"; + END; + END; + IF run.error; + WRAPPER html/row; + INCLUDE html/cell content="Error" style="border:solid gray 1px;"; + INCLUDE html/cell content=run.error style="border:solid gray 1px;"; + END; + END; + IF run.error_time; + WRAPPER html/row; + INCLUDE html/cell content="Error Time" style="border:solid gray 1px;"; + INCLUDE html/cell content=run.error_time style="border:solid gray 1px;"; + END; + END; + END; + '

'; + END; + END; END; %] -- 2.43.2