reporter cleanup -- ready for mini-release (I think)
authormiker <miker@dcc99617-32d9-48b4-a31d-7c20da2025e4>
Tue, 22 Nov 2005 18:25:17 +0000 (18:25 +0000)
committermiker <miker@dcc99617-32d9-48b4-a31d-7c20da2025e4>
Tue, 22 Nov 2005 18:25:17 +0000 (18:25 +0000)
git-svn-id: svn://svn.open-ils.org/ILS/trunk@2117 dcc99617-32d9-48b4-a31d-7c20da2025e4

Open-ILS/src/perlmods/OpenILS/WWW/Reporter/transforms.pm
Open-ILS/src/reporter/clark-kent.pl
Open-ILS/src/reporter/tables.example.xml
Open-ILS/src/reporter/templates/dashboard.ttk
Open-ILS/src/reporter/templates/select_sorter.js
Open-ILS/src/reporter/templates/stage1.ttk
Open-ILS/src/reporter/templates/stage2.ttk
Open-ILS/src/reporter/templates/stage3.ttk
Open-ILS/src/reporter/templates/widgets/lib-choose.dropdown
Open-ILS/src/reporter/templates/widgets/string-choose.dropdown

index c34795e..8123d15 100644 (file)
@@ -10,7 +10,8 @@ our $dtype_xform_map = {
         'date'  => [ 'count', 'age','dateformat'],
         'timestamp'     => [ 'count', 'age','dateformat'],
         'timestamptz'   => [ 'count', 'age','dateformat'],
-        'text'  => [ 'count','count_dist','lower','upper','substr','dewy','dewy_prefix'],
+        'text'  => [ 'count','count_dist','lower','upper','substr'],
+        'call_number'  => [ 'count','count_dist','dewy','dewy_prefix','count_dist_dewey','count_dist_dewey_prefix','lower','upper','substr'],
 };
 
 
@@ -36,6 +37,15 @@ our $dtype_xforms = {
                 'label' => 'Distinct Count per group',
                 'select'        => 'COUNT(DISTINCT ?COLNAME?)',
                 'group' => 0 }, 
+        'count_dist_dewey'      => {
+                'label' => 'Distinct Count of Dewey numbers per group',
+                'select'        => 'COUNT(DISTINCT call_number_dewey(?COLNAME?))',
+                'group' => 1 }, 
+        'count_dist_dewey_prefix'=> {
+                'label' => 'Distinct Count of Dewey Number Prefixes per group',
+                'select'        => 'COUNT(DISTINCT call_number_dewey(?COLNAME?,?PARAM?))',
+                'param' => 1,           
+                'group' => 1 }, 
         'dewy_prefix'         => {    
                 'label' => 'Extract Dewey number prefix from call number',
                 'select'        => 'call_number_dewey(?COLNAME?,?PARAM?)',
index 25ba182..10af011 100755 (executable)
@@ -22,7 +22,6 @@ use GD::Graph::lines;
 
 use open ':utf8';
 
-my $current_time = DateTime->from_epoch( epoch => time() )->strftime('%FT%T%z');
 
 my ($base_xml, $count, $daemon) = ('/openils/conf/reporter.xml', 1);
 
@@ -45,7 +44,7 @@ my $db_pw = $doc->findvalue('/reporter/setup/database/password');
 
 my $dsn = "dbi:" . $db_driver . ":dbname=" . $db_name .';host=' . $db_host;
 
-my $dbh;
+my ($dbh,$running,$sth,@reports,$run, $current_time);
 
 daemonize("Clark Kent, waiting for trouble") if ($daemon);
 
@@ -53,6 +52,7 @@ DAEMON:
 
 $dbh = DBI->connect($dsn,$db_user,$db_pw, {pg_enable_utf8 => 1, RaiseError => 1});
 
+$current_time = DateTime->from_epoch( epoch => time() )->strftime('%FT%T%z');
 # Move new reports into the run queue
 $dbh->do(<<'SQL', {}, $current_time);
 INSERT INTO reporter.output ( stage3, state ) 
@@ -76,7 +76,7 @@ INSERT INTO reporter.output ( stage3, state )
 SQL
 
 # make sure we're not already running $count reports
-my ($running) = $dbh->selectrow_array(<<SQL);
+($running) = $dbh->selectrow_array(<<SQL);
 SELECT count(*)
   FROM reporter.output
   WHERE        state = 'running';
@@ -95,9 +95,9 @@ if ($count <= $running) {
 }
 
 # if we have some open slots then generate the sql
-my $run = $count - $running;
+$run = $count - $running;
 
-my $sth = $dbh->prepare(<<SQL);
+$sth = $dbh->prepare(<<SQL);
 SELECT *
   FROM reporter.output
   WHERE        state = 'wait'
@@ -107,7 +107,7 @@ SQL
 
 $sth->execute;
 
-my @reports;
+@reports = ();
 while (my $r = $sth->fetchrow_hashref) {
        my $s3 = $dbh->selectrow_hashref(<<"    SQL", {}, $r->{stage3});
                SELECT * FROM reporter.stage3 WHERE id = ?;
@@ -149,12 +149,15 @@ for my $r ( @reports ) {
                          WHERE id = ?;
                SQL
 
+               my ($runtime) = $dbh->selectrow_array("SELECT run_time FROM reporter.output WHERE id = ?",{},$r->{id});
+               $r->{run_time} = $runtime;
+
                $sth = $dbh->prepare($r->{sql}->{'select'});
 
                $sth->execute(@{ $r->{sql}->{'bind'} });
                $r->{data} = $sth->fetchall_arrayref;
 
-               pivot_data($r, $p);
+               pivot_data($r);
 
                my $base = $doc->findvalue('/reporter/setup/files/output_base');
                my $s1 = $r->{stage3}->{stage2}->{stage1};
@@ -190,9 +193,9 @@ for my $r ( @reports ) {
 
 
                $dbh->begin_work;
-               $dbh->do(<<'            SQL',{}, $r->{stage3}->{id});
+               $dbh->do(<<'            SQL',{}, $r->{run_time}, $r->{stage3}->{id});
                        UPDATE  reporter.stage3
-                         SET   runtime = runtime + recurrence
+                         SET   runtime = CAST(? AS TIMESTAMP WITH TIME ZONE) + recurrence
                          WHERE id = ? AND recurrence > '0 seconds'::INTERVAL;
                SQL
                $dbh->do(<<'            SQL',{}, $r->{stage3}->{id});
@@ -238,7 +241,7 @@ if ($daemon) {
 
 sub pivot_data {
        my $r = shift;
-       my $p = shift;
+       my $p = JSON->JSON2perl( $r->{stage3}->{params} );
        my $settings = $r->{sql};
        my $data = $r->{data};
 
@@ -452,8 +455,9 @@ sub draw_pie {
                my @pic_data = ([],[]);
                for my $row (@$data) {
                        next if (!defined($$row[$vcol]) || $$row[$vcol] == 0);
-                       push @{$pic_data[0]}, join(" -- ", @$row[@groups]);
-                       push @{$pic_data[1]}, $$row[$vcol];
+                       my $val = $$row[$vcol];
+                       push @{$pic_data[0]}, join(" -- ", @$row[@groups])." ($val)";
+                       push @{$pic_data[1]}, $val;
                }
 
                next unless (@{$pic_data[0]});
@@ -644,10 +648,10 @@ sub generate_query {
 
        my $p = JSON->JSON2perl( $r->{stage3}->{params} );
 
-       my @group_by;
-       my @aggs;
+       my @group_by = ();
+       my @aggs = ();
        my $core = $r->{stage3}->{stage2}->{stage1};
-       my @dims;
+       my @dims = ();
 
        for my $t (keys %{$$p{filter}}) {
                if ($t ne $core) {
@@ -661,8 +665,8 @@ sub generate_query {
                }
        }
 
-       my @dim_select;
-       my @dim_from;
+       my @dim_select = ();
+       my @dim_from = ();
        for my $d (@dims) {
                my $t = table_by_id($d);
                my $t_name = $t->findvalue('tablename');
@@ -685,7 +689,7 @@ sub generate_query {
                '(SELECT ' . join(',', @dim_select) .
                '  FROM ' . join(',', @dim_from) . ') AS dims';
        
-       my @opord;
+       my @opord = ();
        if (ref $$p{output_order}) {
                @opord = @{ $$p{output_order} };
        } else {
@@ -693,14 +697,14 @@ sub generate_query {
        }
        my @output_order = map { { (split ':')[1] => (split ':')[2] } } @opord;
        my @p_col = split(':',$p->{pivot_col}) if $p->{pivot_col};
-       my $pivot;
+       my $pivot = undef;
 
        my $col = 1;
-       my @groupby;
-       my @output;
-       my @columns;
-       my @join;
-       my @join_base;
+       my @groupby = ();
+       my @output = ();
+       my @columns = ();
+       my @join = ();
+       my @join_base = ();
        for my $pair (@output_order) {
                my ($t_name) = keys %$pair;
                my $t = $t_name;
@@ -746,8 +750,8 @@ sub generate_query {
                }
        }
 
-       my @where;
-       my @bind;
+       my @where = ();
+       my @bind = ();
        for my $t ( keys %{$$p{filter}} ) {
                my $t_name = $t;
                $t_name = "dims" if ($t ne $core);
index ad9d59d..8023af1 100644 (file)
@@ -64,6 +64,7 @@
                        </field>
                        <field
                          name="call_number_label"
+                         transform-group="call_number"
                          widget-family="string-input"
                          datatype="text">
                                <label>Call Number</label>
index 8cbfc1d..bda9ac3 100644 (file)
@@ -118,8 +118,9 @@ BLOCK show_reports;
                        INCLUDE html/cell content='Public' nowrap='nowrap' col='lightgray' style='border:solid gray 1px;';
                        INCLUDE html/cell content='Report Name' nowrap='nowrap' col='lightgray' style='border:solid gray 1px;';
                        INCLUDE html/cell content='Created at' nowrap='nowrap' col='lightgray' style='border:solid gray 1px;';
-                       INCLUDE html/cell content='Scheduled Run Date' nowrap='nowrap' col='lightgray' style='border:solid gray 1px;';
+                       INCLUDE html/cell content='Scheduled Run Time<br>Last Run Time' nowrap='nowrap' col='lightgray' style='border:solid gray 1px;';
                        INCLUDE html/cell content='Recurrence' nowrap='nowrap' col='lightgray' style='border:solid gray 1px;';
+                       INCLUDE html/cell content='Runs' nowrap='nowrap' col='lightgray' style='border:solid gray 1px;';
                END;
                FOR report = DBI.query(q);
                        rid = report.id;
@@ -127,13 +128,27 @@ BLOCK show_reports;
                        IF loop.count % 2;
                                bg='white';
                        END;
+                       run_q = 'SELECT * FROM reporter.output WHERE stage3 = ? ORDER BY queue_time LIMIT 1';
+                       run_count_q = 'SELECT count(*) as count FROM reporter.output WHERE stage3 = ?';
+
+                       s = DBI.prepare(run_count_q);
+                       run_count = s.execute(rid);
+                       
+                       s = DBI.prepare(run_q);
+                       run = s.execute(rid);
+                       
                        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=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 nowrap='nowrap' content=report.create_date.chunk(19).0 col=bg style='border:solid gray 1px;';
+                               INCLUDE html/cell
+                                       nowrap='nowrap'
+                                       content=report.runtime.chunk(19).0 _ '<br>' _ run.get.run_time.chunk(19).0
+                                       col=bg
+                                       style='border:solid gray 1px;';
                                INCLUDE html/cell content=report.recurrence col=bg style='border:solid gray 1px;';
+                               INCLUDE html/cell content=run_count.get.count col=bg style='border:solid gray 1px;';
                        END;
                END;
        END;
index ddd57a1..e195313 100644 (file)
@@ -1,5 +1,16 @@
 <script language="javascript">
 
+function show_hide_params (sel) {
+       var span = document.getElementById('hide-param:' + sel.name);
+       if (sel.options[sel.selectedIndex].textContent.match(/\(*\)/)) {
+               span.style.visibility = 'visible';
+       } else {
+               span.style.visibility = 'hidden';
+       }
+       
+       return true;
+}
+
 function field_add_remove (x) {
        var field = x.name;
        if (x.checked) {
index d6b81e1..7a62f29 100644 (file)
@@ -72,11 +72,20 @@ BLOCK stage2_new;
        col_xpath = "/reporter/tables/table[@id='" _ fact_table _ "']/fields/field[@core='true']";
        logme(col_xpath);
 
-       %]<br/><form id="stage2_new" name="stage2_new" action="stage2" method="POST">
+       %]<br/><form id="stage2_new" name="stage2_new" action="stage2" method="POST" onsubmit="return require_name(this)">
+               <script language="javascript">
+                       function require_name (f) {
+                               if (!f.elements['templatename'].value) {
+                                       alert("Template Name is required!");
+                                       return false;
+                               }
+                               return true;
+                       }
+               </script>
                <input type="hidden" name="action" value="save">
                <input type="hidden" name="stage1" value="[% CGI.param('id') %]">
                <center>
-                       <b>Template name (required):</b> <input type="text" name="templatename" id="templatename" size="40" ><br/><br><br>
+                       <b>Template name </b> <input type="text" name="templatename" id="templatename" size="40" ><br/><br><br>
                </center>
                <b>Select Filter Widgets and Output Dimensions</b><br>[%
 
index 617275b..d2e26e9 100644 (file)
@@ -251,7 +251,7 @@ BLOCK run_stage2;
                                        for (var i in bad_filters)
                                                fstring = fstring + "\n\t" + bad_filters[i];
 
-                                       alert('You must choose a filter value for these filter:\n' + fstring);
+                                       alert('You must choose a value for these filters or settings:\n' + fstring);
                                        return false;
                                }
 
@@ -282,6 +282,7 @@ BLOCK run_stage2;
                '<br/><center><b>Report Name:</b>';
                INCLUDE text name='reportname' size="50";
                '</center><br/><br/>';
+               '<script language="javascript">filters["reportname"] = "Report Name";</script>';
 
                WRAPPER html/table width="100%";
                        WRAPPER html/row  style="border-top: solid black 2px;";
@@ -324,22 +325,22 @@ BLOCK run_stage2;
                                                END;
                                                WRAPPER html/row;
                                                        WRAPPER html/cell;
-                                                               INCLUDE checkbox name='html_graph_type' value='bar';
+                                                               INCLUDE checkbox name='html_graph_type' value='bar' checked=1;
                                                        END;
                                                        INCLUDE html/cell content='Bar';
                                                END;
                                                WRAPPER html/row;
                                                        WRAPPER html/cell;
-                                                               INCLUDE checkbox name='html_graph_type' value='pie';
+                                                               INCLUDE checkbox name='html_graph_type' value='pie' checked=1;
                                                        END;
                                                        INCLUDE html/cell content='Pie';
                                                END;
-                                               WRAPPER html/row;
-                                                       WRAPPER html/cell;
-                                                               INCLUDE checkbox name='html_graph_type' value='line';
-                                                       END;
-                                                       INCLUDE html/cell content='Line';
-                                               END;
+                                               #WRAPPER html/row;
+                                               #       WRAPPER html/cell;
+                                               #               INCLUDE checkbox name='html_graph_type' value='line';
+                                               #       END;
+                                               #       INCLUDE html/cell content='Line';
+                                               #END;
                                        END;
                                END;
                        END;
@@ -398,10 +399,9 @@ BLOCK run_stage2;
                                                        widget = fam.findnodes( "widget[@name='$f_widget']" );
 
                                                        w_file = 'widgets/' _ fam.findvalue('@name') _ '.' _ widget.findvalue('@name');
-                                                       INCLUDE html/cell;
-                                                       INCLUDE html/cell align='right' content=field.findvalue( 'label' );
+                                                       INCLUDE html/cell align='left' style="padding-left: 50px;" content=field.findvalue( 'label' );
 
-                                                       WRAPPER html/cell align='right';
+                                                       WRAPPER html/cell align='left';
                                                                TRY;
                                                                                classname = table.findvalue('@id');
                                                                                fieldname = field.findvalue('@name');
@@ -443,7 +443,7 @@ BLOCK run_stage2;
                        plabel = pkey_field.findvalue('label');
                
                        WRAPPER html/row;
-                               WRAPPER html/cell align='right';
+                               WRAPPER html/cell align='left' style="padding-left: 50px;";
                                        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";
                                        %]
@@ -452,8 +452,8 @@ BLOCK run_stage2;
                                                        Widget.Select.addOption('output_order','[% "output:$classname:$pid" %]', '[% "Per group count of $plabel" %]');
                                                </script>
                                        [%
+                               "Per group count of $plabel<br/><br/>";
                                END;
-                               INCLUDE html/cell align='right' content="Per group count of $plabel";
                                INCLUDE html/cell align='center';
                        END;
 
@@ -530,7 +530,7 @@ BLOCK show_filter_atts;
 
                WRAPPER html/row;
 
-                       WRAPPER html/cell align='right' col=bg_color;
+                       WRAPPER html/cell align='left' col=bg_color style="padding-left: 50px;";
                                INCLUDE checkbox name="output:$t:$fid" value="include" onclick="field_add_remove(this)";
                                %]
                                        <script language="javascript">
@@ -538,12 +538,17 @@ BLOCK show_filter_atts;
                                        </script>
                                [%
 
+                               fname;
                        END;
-                       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";
+                       INCLUDE html/cell align='right' content='Output Transformation:' col=bg_color;
+                       WRAPPER html/cell align='left' col=bg_color style="padding-left: 50px;";
+
+                               dtype = field.findvalue('@transform-group');
+                               IF !dtype;
+                                       dtype = field.findvalue('@datatype');
+                               END;
+
+                               WRAPPER select id="xform:type:$t:$fid" name="xform:type:$t:$fid" onchange="show_hide_params(this)";
                                        INCLUDE option value='' content='None' selected=1;
                                        FOR xform = dtype_xform_map.$dtype;
                                                xform_label = dtype_xforms.$xform.label;
@@ -553,9 +558,16 @@ BLOCK show_filter_atts;
                                                INCLUDE option value=xform content=xform_label;
                                        END;
                                END;
-                               '<br/>';
-                               '<small><super>*</super>Output Tranformation Parameter: </small>';
-                               INCLUDE text name="xform:param:$t:$fid";
+
+                               %]
+
+                               <br/>
+                               <span id="hide-param:xform:type:[% t %]:[% fid %]" style="visibility: hidden;">
+                                       <small><super>*</super>Output Tranformation Parameter: </small>
+                                       [% INCLUDE text name="xform:param:$t:$fid" %]
+                               </span>
+
+                               [%
                        END;
                END;
                count = count + 1;
index 012eb21..3bf3cd7 100644 (file)
@@ -66,6 +66,8 @@ BLOCK schedule_stage3;
                'Optional Recurrence:';
                INCLUDE text name='recurrence-count' value='0';
                WRAPPER select name='recurrence-interval';
+                       INCLUDE option value='minutes' content='Minutes(s)'; # for testing
+                       INCLUDE option value='hours' content='Hours(s)'; # for testing
                        INCLUDE option value='days' content='Day(s)';
                        INCLUDE option value='weeks' content='Week(s)';
                        INCLUDE option value='months' content='Month(s)';
@@ -74,7 +76,9 @@ BLOCK schedule_stage3;
                FOR p = CGI.param();
                        NEXT IF p == 'action';
                        NEXT IF p == 'runtime';
-                       INCLUDE hidden name=p value=CGI.param(p);
+                       FOR pval = CGI.param(p);
+                               INCLUDE hidden name=p value=pval;
+                       END;
                END;
                '<br>';
                INCLUDE submit name='action' value='Save';
index 7461b50..4d27612 100644 (file)
@@ -27,14 +27,17 @@ org_unit_type = DBI.tie('actor.org_unit_type', 'id')
 
 [%
 
-WRAPPER select name=input_prefix onchange='change_hier_' _ table_alias _ '(this);';
+WRAPPER select id=input_prefix name=input_prefix onchange='change_hier_' _ table_alias _ '(this);';
        depth = 0;
+       INCLUDE option value='' content='Select One';
+       INCLUDE option value='' content='----------';
        FOR f = DBI.query(root);
                INCLUDE option value=f.$fieldname;
                INCLUDE next_level parent_ou = f.id depth;
        END;
 END;
 
+
 BLOCK next_level;
        depth = depth + 1;
        x = depth;
index 0cc12a4..8619b4b 100644 (file)
@@ -7,6 +7,8 @@ q = 'SELECT * FROM ' _ table.findvalue('tablename') _ ' ORDER BY ' _ fieldname _
 '<script language="javascript">filters["' _ input_prefix _ '"] = "' _ table_label _ ' -- ' _ field.findvalue('label') _ '";</script>';
 
 WRAPPER select name=input_prefix;
+       INCLUDE option value='' content='Select One';
+       INCLUDE option value='' content='----------';
        FOR f = DBI.query(q);
                INCLUDE option value=f.$fieldname;
        END;