[Rt-commit] rt branch, 4.2/date-time-improvements-in-charts, updated. rt-3.8.10-109-g1aa4ec7

Ruslan Zakirov ruz at bestpractical.com
Tue Jun 28 10:31:31 EDT 2011


The branch, 4.2/date-time-improvements-in-charts has been updated
       via  1aa4ec78bf058ed0ab582c388972f9f66ef2dc8b (commit)
       via  d6b98c5d2eb4d8ba9d163eb601d3847c6a5ed281 (commit)
       via  c832006c5e3f05cd5ac9d75aaaef03628430fadd (commit)
       via  2df4270a095b359126ff0ffbd67fe0ea7a6cb010 (commit)
       via  326b6d8d411617278035900b21d0f8589ca97cf5 (commit)
       via  5fd922a83a2571eb9324345b1d4c0339870b2e5a (commit)
       via  6150f290f914a3f771d2acfcd92951dbc7f7e044 (commit)
       via  abcc51892cf3b42085b608bc475e7e103b634b03 (commit)
       via  1e108803937608ef19dd59c8e07d90e5f2d5bd9c (commit)
       via  ba9e640fa07501d2f60a39d01c4602616b4d59a6 (commit)
       via  530ec6fdda7569efda3b1e9092cac89d3ed2ace8 (commit)
       via  3dd2af1bcb81b37cbeca0738fdbc9263834e0dd6 (commit)
       via  f15e267474c9d76338cede18698fca3a11c65cb2 (commit)
       via  101d4d1e4f3fe1e2eadc77587af2ae1716f8ea04 (commit)
       via  a7acf67b375bea0712d004da016470a3f339529d (commit)
       via  eeeb2866bfcfea0b256f9150be4aa1daab19dc55 (commit)
      from  f2cc00c572b7a3fffaeef61dba92954615cb3789 (commit)

Summary of changes:
 lib/RT/Report/Tickets.pm              |  251 +++++++++++++++++++++++++--------
 lib/RT/Report/Tickets/Entry.pm        |   20 ++-
 share/html/Search/Elements/Chart      |   56 +-------
 share/html/Search/Elements/ChartTable |   67 +++++++++
 4 files changed, 277 insertions(+), 117 deletions(-)
 create mode 100644 share/html/Search/Elements/ChartTable

- Log -----------------------------------------------------------------
commit eeeb2866bfcfea0b256f9150be4aa1daab19dc55
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Mon Jun 27 15:15:05 2011 +0400

    time worked is in minutes

diff --git a/lib/RT/Report/Tickets.pm b/lib/RT/Report/Tickets.pm
index ca7380a..7ecd4bb 100644
--- a/lib/RT/Report/Tickets.pm
+++ b/lib/RT/Report/Tickets.pm
@@ -266,7 +266,7 @@ our %STATISTICS_META = (
             my %args = @_;
             my $v = $args{'VALUE'};
             return $self->loc("(no value)") unless defined $v && length $v;
-            return RT::Date->new( $self->CurrentUser )->DurationAsString( $v );
+            return RT::Date->new( $self->CurrentUser )->DurationAsString( $v*60 );
         },
     },
     DateTimeInterval => {

commit a7acf67b375bea0712d004da016470a3f339529d
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Mon Jun 27 15:16:17 2011 +0400

    don't print zero totals

diff --git a/share/html/Search/Elements/Chart b/share/html/Search/Elements/Chart
index e68d0b6..37ea084 100644
--- a/share/html/Search/Elements/Chart
+++ b/share/html/Search/Elements/Chart
@@ -130,7 +130,9 @@ my $query_string = $m->comp('/Elements/QueryString', %ARGS, GroupBy => \@GroupBy
 <tr class="<% $i%2 ? 'evenline' : 'oddline' %>">
 <td class="label collection-as-table" colspan="<% scalar @{ $columns{'Groups'} } %>"><% loc('Total') %></td>
 % foreach my $column ( @{ $columns{'Functions'} } ) {
-% if ( my $code = $report->LabelValueCode( $column ) ) {
+% if ( !$total{ $column } ) {
+<td class="value collection-as-table">&nbsp;</td>
+% } elsif ( my $code = $report->LabelValueCode( $column ) ) {
 % my $info = $report->ColumnInfo( $column );
 <td class="value collection-as-table"><% $code->( $report, %$info, VALUE => $total{ $column } ) %></td>
 % } else {

commit 101d4d1e4f3fe1e2eadc77587af2ae1716f8ea04
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Mon Jun 27 15:17:19 2011 +0400

    get rid _StatsToFunction so we can implement post calc functions

diff --git a/lib/RT/Report/Tickets.pm b/lib/RT/Report/Tickets.pm
index 7ecd4bb..9f393e7 100644
--- a/lib/RT/Report/Tickets.pm
+++ b/lib/RT/Report/Tickets.pm
@@ -381,6 +381,7 @@ sub ColumnInfo {
 
     return $self->{'column_info'}{$column};
 }
+
 sub ColumnsList {
     my $self = shift;
     return keys %{ $self->{'column_info'} || {} };
@@ -423,20 +424,42 @@ sub SetupGroupings {
         push @{ $res{'Groups'} }, $group_by->{'NAME'};
     }
 
+    %STATISTICS = @STATISTICS unless keys %STATISTICS;
+
     my @function = grep defined && length,
         ref( $args{'Function'} )? @{ $args{'Function'} } : ($args{'Function'});
     foreach my $e ( @function ) {
-        my %args = $self->_StatsToFunction( $e );
-        $args{'TYPE'} = 'statistic';
-        $args{'INFO'} = $STATISTICS{ $e };
-        $args{'META'} = $STATISTICS_META{ $args{'INFO'}[1] };
-        $args{'NAME'} = $self->Column(
-            ALIAS    => $args{'ALIAS'},
-            FIELD    => $args{'FIELD'},
-            FUNCTION => $args{'FUNCTION'},
-        );
-        push @{ $res{'Functions'} }, $args{'NAME'};
-        $column_info{ $args{'NAME'} } = \%args;
+        $e = {
+            TYPE => 'statistic',
+            KEY  => $e,
+            INFO => $STATISTICS{ $e },
+            META => $STATISTICS_META{ $STATISTICS{ $e }[1] },
+
+        };
+        unless ( $e->{'INFO'} && $e->{'META'} ) {
+            $RT::Logger->error("'". $e->{'KEY'} ."' is not valid statistic for report");
+            $e->{'FUNCTION'} = 'NULL';
+            $e->{'NAME'} = $self->Column( FUNCTION => 'NULL' );
+        }
+        elsif ( $e->{'META'}{'Function'} ) {
+            my $code = $self->FindImplementationCode( $e->{'META'}{'Function'} );
+            unless ( $code ) {
+                $e->{'FUNCTION'} = 'NULL';
+                $e->{'NAME'} = $self->Column( FUNCTION => 'NULL' );
+            }
+            else {
+                my %tmp = $code->( $self, @{ $e->{INFO} }[2 .. scalar @{ $e->{INFO} } -1 ] );
+                $e->{'NAME'} = $self->Column( %tmp );
+                @{ $e }{'FUNCTION', 'ALIAS', 'FIELD'} = @tmp{'FUNCTION', 'ALIAS', 'FIELD'};
+            }
+        }
+        elsif ( $e->{'META'}{'Calculate'} ) {
+            # ....
+        }
+        else {
+        }
+        push @{ $res{'Functions'} }, $e->{'NAME'};
+        $column_info{ $e->{'NAME'} } = $e;
     }
 
     $self->{'column_info'} = \%column_info;
@@ -488,25 +511,6 @@ sub _FieldToFunction {
     return $code->( $self, %args );
 }
 
-sub _StatsToFunction {
-    my $self = shift;
-    my ($stat) = (@_);
-
-    %STATISTICS = @STATISTICS unless keys %STATISTICS;
-
-    my ($display, $type, @args) = @{ $STATISTICS{ $stat } || [] };
-    unless ( $type ) {
-        $RT::Logger->error("'$stat' is not valid statistics for report");
-        return ('FUNCTION' => 'NULL');
-    }
-
-    my $meta = $STATISTICS_META{ $type };
-    return ('FUNCTION' => 'NULL') unless $meta;
-    return ('FUNCTION' => 'NULL') unless $meta->{'Function'};
-    return $meta->{'Function'}->( $self, @args );
-}
-
-
 # Override the AddRecord from DBI::SearchBuilder::Unique. id isn't id here
 # wedon't want to disambiguate all the items with a count of 1.
 sub AddRecord {

commit f15e267474c9d76338cede18698fca3a11c65cb2
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Mon Jun 27 15:22:00 2011 +0400

    drop AddEmptyRow as it doesn't work

diff --git a/lib/RT/Report/Tickets.pm b/lib/RT/Report/Tickets.pm
index 9f393e7..96580fa 100644
--- a/lib/RT/Report/Tickets.pm
+++ b/lib/RT/Report/Tickets.pm
@@ -483,7 +483,6 @@ sub _DoSearch {
         );
     }
     else {
-        $self->AddEmptyRows;
     }
 }
 
@@ -539,31 +538,6 @@ sub NewItem {
     return $res;
 }
 
-
-=head2 AddEmptyRows
-
-If we're grouping on a criterion we know how to add zero-value rows
-for, do that.
-
-=cut
-
-sub AddEmptyRows {
-    my $self = shift;
-    if ( @{ $self->{'_group_by_field'} || [] } == 1 && $self->{'_group_by_field'}[0] eq 'Status' ) {
-        my %has = map { $_->__Value('Status') => 1 } @{ $self->ItemsArrayRef || [] };
-
-        foreach my $status ( grep !$has{$_}, RT::Queue->new($self->CurrentUser)->StatusArray ) {
-
-            my $record = $self->NewItem;
-            $record->LoadFromHash( {
-                id     => 0,
-                status => $status
-            } );
-            $self->AddRecord($record);
-        }
-    }
-}
-
 { our @SORT_OPS;
 sub __sort_function_we_need_named($$) {
     for my $f ( @SORT_OPS ) {

commit 3dd2af1bcb81b37cbeca0738fdbc9263834e0dd6
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Mon Jun 27 22:33:34 2011 +0400

    move chart's table formatting into libs

diff --git a/lib/RT/Report/Tickets.pm b/lib/RT/Report/Tickets.pm
index 96580fa..b97b1e1 100644
--- a/lib/RT/Report/Tickets.pm
+++ b/lib/RT/Report/Tickets.pm
@@ -741,6 +741,72 @@ sub Deserialize {
     }
 }
 
+
+sub FormatTable {
+    my $self = shift;
+    my %columns = @_;
+
+    my @head = ({ cells => []});
+    foreach my $column ( @{ $columns{'Groups'} }, @{ $columns{'Functions'} } ) {
+        push @{ $head[0]{'cells'} }, { type => 'head', value => $self->Label($column) };
+    }
+
+    my %total;
+
+    my @body;
+    my $i = 0;
+    my @groups_stack = ();
+    while ( my $entry = $self->Next ) {
+        my %row = (
+            even => ++$i%2,
+            cells => [],
+        );
+        foreach my $column ( @{ $columns{'Groups'} } ) {
+            push @{ $row{'cells'} }, { type => 'label', value => $entry->LabelValue( $column ) };
+        }
+
+        my $entry_query = $entry->Query;
+        
+        foreach my $column ( @{ $columns{'Functions'} } ) {
+            my $raw = $entry->RawValue( $column );
+            $total{ $column } += $raw if defined $raw && length $raw;
+
+            my $value = $entry->LabelValue( $column );
+            push @{ $row{'cells'} }, { type => 'value', value => $value, query => $entry_query };
+        }
+        push @body, \%row;
+    }
+
+    my @footer;
+    {
+        my %row = (
+            even => ++$i%2,
+            cells => [],
+        );
+        push @{ $row{'cells'} }, {
+            type => 'label',
+            value => $self->loc('Total'),
+            colspan => scalar @{ $columns{'Groups'} }
+        };
+        foreach my $column ( @{ $columns{'Functions'} } ) {
+            my %cell = ( type => 'value' );
+            if ( !$total{ $column } ) {
+                $cell{'value'} = undef;
+            }
+            elsif ( my $code = $self->LabelValueCode( $column ) ) {
+                my $info = $self->ColumnInfo( $column );
+                $cell{'value'} = $code->( $self, %$info, VALUE => $total{ $column } );
+            } else {
+                $cell{'value'} = $total{ $column };
+            }
+            push @{ $row{'cells'} }, \%cell;
+        }
+        push @footer, \%row;
+    }
+
+    return thead => \@head, tbody => \@body, tfoot => \@footer;
+}
+
 RT::Base->_ImportOverlays();
 
 1;
diff --git a/share/html/Search/Elements/Chart b/share/html/Search/Elements/Chart
index 37ea084..6c9b141 100644
--- a/share/html/Search/Elements/Chart
+++ b/share/html/Search/Elements/Chart
@@ -85,14 +85,6 @@ my $query_string = $m->comp('/Elements/QueryString', %ARGS, GroupBy => \@GroupBy
 <img src="<% RT->Config->Get('WebPath') %>/Search/Chart?Cache=<% $key |un %>&<% $query_string |n %>" /><br />
 % }
 
-<table class="collection-as-table">
-
-<tr>
-% foreach my $column ( @{ $columns{'Groups'} }, @{ $columns{'Functions'} } ) {
-<th class="collection-as-table"><% $report->Label( $column ) %></th>
-% }
-</tr>
-
 % my $base_query = $m->comp('/Elements/QueryString',
 %     Format  => $ARGS{Format},
 %     Rows    => $ARGS{Rows},
@@ -100,45 +92,41 @@ my $query_string = $m->comp('/Elements/QueryString', %ARGS, GroupBy => \@GroupBy
 %     Order   => $ARGS{Order},
 % );
 
-% my $i = 0;
-% my %total = map { $_ => 0 } @{ $columns{Functions} };
-% while ( my $entry = $report->Next ) {
-<tr class="<% ++$i%2 ? 'evenline' : 'oddline' %>">
-
-% foreach my $column ( @{ $columns{'Groups'} } ) {
-<td class="label collection-as-table"><% $entry->LabelValue( $column ) %></td>
-% }
-
-% my $entry_query = $entry->Query;
-
-% foreach my $column ( @{ $columns{'Functions'} } ) {
-<td class="value collection-as-table">
-% $total{ $column } += $entry->RawValue( $column );
-% my $value = $entry->LabelValue( $column );
-% if ( $entry_query ) {
-<a href="<% RT->Config->Get('WebPath') %>/Search/Results.html?Query=<% "$Query AND $entry_query" |un %>&<% $base_query %>"><% $value %></a>
-% } else {
-<% $value %>
+% my %table = $report->FormatTable( %columns );
+<table class="collection-as-table">
+% foreach my $section (qw(thead tbody tfoot)) {
+% next unless $table{ $section } && @{ $table{ $section } };
+<<% $section %>>
+% foreach my $row ( @{ $table{ $section } } ) {
+
+<tr \
+  class="<% defined $row->{'even'}?  $row->{'even'}? 'evenline' : 'oddline' : '' %>" \
+>
+% foreach my $cell ( @{ $row->{'cells'} } ) {
+% my @class = ('collection-as-table');
+% push @class, ($cell->{'type'}) unless $cell->{'type'} eq 'head';
+% my $tag = $cell->{'type'} eq 'value'? 'td' : 'th';
+<<% $tag %> class="<% join ' ', @class %>" \
+% if ( $cell->{'colspan'} ) {
+colspan="<% int $cell->{'colspan'} %>" \
 % }
-</td>
+% if ( $cell->{'rowspan'} ) {
+rowspan="<% int $cell->{'rowspan'} %>" \
 % }
-
-</tr>
+>\
+% if ( defined $cell->{'value'} ) {
+% if ( my $q = $cell->{'query'} ) {
+<a href="<% RT->Config->Get('WebPath') %>/Search/Results.html?Query=<% "$Query AND $q" |un %>&<% $base_query %>"><% $cell->{'value'} %></a>\
+% } else {
+<% $cell->{'value'} %>\
 % }
-
-% $i++;
-<tr class="<% $i%2 ? 'evenline' : 'oddline' %>">
-<td class="label collection-as-table" colspan="<% scalar @{ $columns{'Groups'} } %>"><% loc('Total') %></td>
-% foreach my $column ( @{ $columns{'Functions'} } ) {
-% if ( !$total{ $column } ) {
-<td class="value collection-as-table">&nbsp;</td>
-% } elsif ( my $code = $report->LabelValueCode( $column ) ) {
-% my $info = $report->ColumnInfo( $column );
-<td class="value collection-as-table"><% $code->( $report, %$info, VALUE => $total{ $column } ) %></td>
 % } else {
-<td class="value collection-as-table"><% $total{ $column } %></td>
+&nbsp;\
 % }
+</<% $tag %>>
 % }
 </tr>
-
+% }
+</<% $section %>>
+% }
 </table>

commit 530ec6fdda7569efda3b1e9092cac89d3ed2ace8
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Mon Jun 27 22:59:19 2011 +0400

    move table rendering into it's own component

diff --git a/share/html/Search/Elements/Chart b/share/html/Search/Elements/Chart
index 6c9b141..a861ab9 100644
--- a/share/html/Search/Elements/Chart
+++ b/share/html/Search/Elements/Chart
@@ -85,48 +85,4 @@ my $query_string = $m->comp('/Elements/QueryString', %ARGS, GroupBy => \@GroupBy
 <img src="<% RT->Config->Get('WebPath') %>/Search/Chart?Cache=<% $key |un %>&<% $query_string |n %>" /><br />
 % }
 
-% my $base_query = $m->comp('/Elements/QueryString',
-%     Format  => $ARGS{Format},
-%     Rows    => $ARGS{Rows},
-%     OrderBy => $ARGS{OrderBy},
-%     Order   => $ARGS{Order},
-% );
-
-% my %table = $report->FormatTable( %columns );
-<table class="collection-as-table">
-% foreach my $section (qw(thead tbody tfoot)) {
-% next unless $table{ $section } && @{ $table{ $section } };
-<<% $section %>>
-% foreach my $row ( @{ $table{ $section } } ) {
-
-<tr \
-  class="<% defined $row->{'even'}?  $row->{'even'}? 'evenline' : 'oddline' : '' %>" \
->
-% foreach my $cell ( @{ $row->{'cells'} } ) {
-% my @class = ('collection-as-table');
-% push @class, ($cell->{'type'}) unless $cell->{'type'} eq 'head';
-% my $tag = $cell->{'type'} eq 'value'? 'td' : 'th';
-<<% $tag %> class="<% join ' ', @class %>" \
-% if ( $cell->{'colspan'} ) {
-colspan="<% int $cell->{'colspan'} %>" \
-% }
-% if ( $cell->{'rowspan'} ) {
-rowspan="<% int $cell->{'rowspan'} %>" \
-% }
->\
-% if ( defined $cell->{'value'} ) {
-% if ( my $q = $cell->{'query'} ) {
-<a href="<% RT->Config->Get('WebPath') %>/Search/Results.html?Query=<% "$Query AND $q" |un %>&<% $base_query %>"><% $cell->{'value'} %></a>\
-% } else {
-<% $cell->{'value'} %>\
-% }
-% } else {
-&nbsp;\
-% }
-</<% $tag %>>
-% }
-</tr>
-% }
-</<% $section %>>
-% }
-</table>
+<& ChartTable, %ARGS, Table => { $report->FormatTable( %columns ) } &>
diff --git a/share/html/Search/Elements/ChartTable b/share/html/Search/Elements/ChartTable
new file mode 100644
index 0000000..62e96ac
--- /dev/null
+++ b/share/html/Search/Elements/ChartTable
@@ -0,0 +1,67 @@
+<%ARGS>
+%Table => ()
+$Query => undef
+</%ARGS>
+<%INIT>
+
+my $base_query = $m->comp('/Elements/QueryString',
+    Format  => $ARGS{Format},
+    Rows    => $ARGS{Rows},
+    OrderBy => $ARGS{OrderBy},
+    Order   => $ARGS{Order},
+);
+
+my $interp = $m->interp;
+my $eh  = sub { $interp->apply_escapes( @_, 'h' ) };
+my $eu  = sub { $interp->apply_escapes( @_, 'u' ) };
+
+$m->out('<table class="collection-as-table">'. "\n");
+foreach my $section (qw(thead tbody tfoot)) {
+    next unless $Table{ $section } && @{ $Table{ $section } };
+
+    $m->out("<$section>\n");
+    foreach my $row ( @{ $Table{ $section } } ) {
+        $m->out('  <tr');
+        $m->out(' class="'. ($row->{'even'}? 'evenline' : 'oddline') .'"')
+            if defined $row->{'even'};
+        $m->out(">");
+
+        foreach my $cell ( @{ $row->{'cells'} } ) {
+            my $tag = $cell->{'type'} eq 'value'? 'td' : 'th';
+            $m->out("<$tag");
+
+            my @class = ('collection-as-table');
+            push @class, ($cell->{'type'}) unless $cell->{'type'} eq 'head';
+            $m->out(' class="'. $eh->( join ' ', @class ) .'"');
+
+            foreach my $dir ( grep $cell->{$_}, qw(rawspan colspan) ) {
+                my $value = int $cell->{ $dir };
+                $m->out(qq{ $dir="$value"});
+            }
+            $m->out('>');
+            if ( defined $cell->{'value'} ) {
+                if ( my $q = $cell->{'query'} ) {
+                    $m->out(
+                        '<a href="'. RT->Config->Get('WebPath') .'/Search/Results.html'
+                        .'?Query='. $eu->("$Query AND $q")
+                        .'&'. $base_query
+                        . '">'
+                    );
+                    $m->out( $eh->( $cell->{'value'} ) );
+                    $m->out('</a>');
+                }
+                else {
+                    $m->out( $eh->( $cell->{'value'} ) );
+                }
+            }
+            else {
+                $m->out('&nbsp;');
+            }
+            $m->out("</$tag>");
+        }
+        $m->out("</tr>\n");
+    }
+    $m->out("</$section>\n\n");
+}
+$m->out("</table>");
+</%INIT>

commit ba9e640fa07501d2f60a39d01c4602616b4d59a6
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Mon Jun 27 23:19:41 2011 +0400

    first pass at caculating stats after querying DB

diff --git a/lib/RT/Report/Tickets.pm b/lib/RT/Report/Tickets.pm
index b97b1e1..f147ea1 100644
--- a/lib/RT/Report/Tickets.pm
+++ b/lib/RT/Report/Tickets.pm
@@ -454,9 +454,7 @@ sub SetupGroupings {
             }
         }
         elsif ( $e->{'META'}{'Calculate'} ) {
-            # ....
-        }
-        else {
+            $e->{'NAME'} = 'postfunction'. $self->{'postfunctions'}++;
         }
         push @{ $res{'Functions'} }, $e->{'NAME'};
         $column_info{ $e->{'NAME'} } = $e;
@@ -483,6 +481,7 @@ sub _DoSearch {
         );
     }
     else {
+        $self->CalculatePostFunctions;
     }
 }
 
@@ -593,6 +592,40 @@ sub SortEntries {
     ];
 } }
 
+sub CalculatePostFunctions {
+    my $self = shift;
+
+    my $info = $self->{'column_info'};
+    foreach my $column ( values %$info ) {
+        next unless $column->{'TYPE'} eq 'statistic';
+        next unless $column->{'META'}{'Calculate'};
+
+        $self->CalculatePostFunction( $column );
+    }
+}
+
+sub CalculatePostFunction {
+    my $self = shift;
+    my $info = shift;
+
+    my $code = $self->FindImplementationCode( $info->{'META'}{'Calculate'} );
+    unless ( $code ) {
+        # TODO: fill in undefs
+        return;
+    }
+
+    my $column = $info->{'NAME'};
+
+    my $base_query = $self->{'_sql_query'};
+    foreach my $item ( @{ $self->{'items'} } ) {
+        $item->{'values'}{$column} = $code->(
+            $self,
+            Query => join( ' AND ', grep defined && length, $base_query, $item->Query ),
+        );
+        $item->{'fetched'}{$column} = 1;
+    }
+}
+
 sub GenerateDateFunction {
     my $self = shift;
     my %args = @_;
diff --git a/lib/RT/Report/Tickets/Entry.pm b/lib/RT/Report/Tickets/Entry.pm
index e0cc854..f58ff4a 100644
--- a/lib/RT/Report/Tickets/Entry.pm
+++ b/lib/RT/Report/Tickets/Entry.pm
@@ -123,6 +123,7 @@ sub Query {
             push @parts, "$field $op $value";
         }
     }
+    return () unless @parts;
     return join ' AND ', grep defined && length, @parts;
 }
 

commit 1e108803937608ef19dd59c8e07d90e5f2d5bd9c
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Mon Jun 27 23:57:03 2011 +0400

    reverse how we process table, make it column first

diff --git a/lib/RT/Report/Tickets.pm b/lib/RT/Report/Tickets.pm
index f147ea1..28c9cd9 100644
--- a/lib/RT/Report/Tickets.pm
+++ b/lib/RT/Report/Tickets.pm
@@ -787,27 +787,36 @@ sub FormatTable {
     my %total;
 
     my @body;
+
     my $i = 0;
-    my @groups_stack = ();
     while ( my $entry = $self->Next ) {
-        my %row = (
-            even => ++$i%2,
-            cells => [],
-        );
-        foreach my $column ( @{ $columns{'Groups'} } ) {
-            push @{ $row{'cells'} }, { type => 'label', value => $entry->LabelValue( $column ) };
+        $body[ $i ] = { even => ($i+1)%2, cells => [] };
+        $i++;
+    }
+
+    foreach my $column ( @{ $columns{'Groups'} } ) {
+        $i = 0;
+        while ( my $entry = $self->Next ) {
+            push @{ $body[ $i++ ]{'cells'} }, {
+                type => 'label',
+                value => $entry->LabelValue( $column )
+            };
         }
+    }
 
-        my $entry_query = $entry->Query;
-        
-        foreach my $column ( @{ $columns{'Functions'} } ) {
+    foreach my $column ( @{ $columns{'Functions'} } ) {
+        $i = 0;
+        while ( my $entry = $self->Next ) {
             my $raw = $entry->RawValue( $column );
             $total{ $column } += $raw if defined $raw && length $raw;
 
             my $value = $entry->LabelValue( $column );
-            push @{ $row{'cells'} }, { type => 'value', value => $value, query => $entry_query };
+            push @{ $body[ $i++ ]{'cells'} }, {
+                type => 'value',
+                value => $value,
+                query => $entry->Query,
+            };
         }
-        push @body, \%row;
     }
 
     my @footer;

commit abcc51892cf3b42085b608bc475e7e103b634b03
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Tue Jun 28 00:08:27 2011 +0400

    simplify how we calculate totals for chart's table

diff --git a/lib/RT/Report/Tickets.pm b/lib/RT/Report/Tickets.pm
index 28c9cd9..dd31cd5 100644
--- a/lib/RT/Report/Tickets.pm
+++ b/lib/RT/Report/Tickets.pm
@@ -779,20 +779,19 @@ sub FormatTable {
     my $self = shift;
     my %columns = @_;
 
-    my @head = ({ cells => []});
+    my (@head, @body, @footer);
+
+    @head = ({ cells => []});
     foreach my $column ( @{ $columns{'Groups'} }, @{ $columns{'Functions'} } ) {
         push @{ $head[0]{'cells'} }, { type => 'head', value => $self->Label($column) };
     }
 
-    my %total;
-
-    my @body;
-
     my $i = 0;
     while ( my $entry = $self->Next ) {
         $body[ $i ] = { even => ($i+1)%2, cells => [] };
         $i++;
     }
+    @footer = ({ even => ++$i%2, cells => []});
 
     foreach my $column ( @{ $columns{'Groups'} } ) {
         $i = 0;
@@ -803,12 +802,18 @@ sub FormatTable {
             };
         }
     }
+    push @{ $footer[0]{'cells'} }, {
+        type => 'label',
+        value => $self->loc('Total'),
+        colspan => scalar @{ $columns{'Groups'} },
+    };
 
     foreach my $column ( @{ $columns{'Functions'} } ) {
         $i = 0;
+        my $total;
         while ( my $entry = $self->Next ) {
             my $raw = $entry->RawValue( $column );
-            $total{ $column } += $raw if defined $raw && length $raw;
+            $total += $raw if defined $raw && length $raw;
 
             my $value = $entry->LabelValue( $column );
             push @{ $body[ $i++ ]{'cells'} }, {
@@ -817,33 +822,11 @@ sub FormatTable {
                 query => $entry->Query,
             };
         }
-    }
-
-    my @footer;
-    {
-        my %row = (
-            even => ++$i%2,
-            cells => [],
-        );
-        push @{ $row{'cells'} }, {
-            type => 'label',
-            value => $self->loc('Total'),
-            colspan => scalar @{ $columns{'Groups'} }
-        };
-        foreach my $column ( @{ $columns{'Functions'} } ) {
-            my %cell = ( type => 'value' );
-            if ( !$total{ $column } ) {
-                $cell{'value'} = undef;
-            }
-            elsif ( my $code = $self->LabelValueCode( $column ) ) {
-                my $info = $self->ColumnInfo( $column );
-                $cell{'value'} = $code->( $self, %$info, VALUE => $total{ $column } );
-            } else {
-                $cell{'value'} = $total{ $column };
-            }
-            push @{ $row{'cells'} }, \%cell;
+        if ( $total and my $code = $self->LabelValueCode( $column ) ) {
+            my $info = $self->ColumnInfo( $column );
+            $total = $code->( $self, %$info, VALUE => $total );
         }
-        push @footer, \%row;
+        push @{ $footer[0]{'cells'} }, { type => 'value', value => $total };
     }
 
     return thead => \@head, tbody => \@body, tfoot => \@footer;

commit 6150f290f914a3f771d2acfcd92951dbc7f7e044
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Tue Jun 28 04:50:27 2011 +0400

    it's rOwspan, not rAwspan

diff --git a/share/html/Search/Elements/ChartTable b/share/html/Search/Elements/ChartTable
index 62e96ac..2f5a3ff 100644
--- a/share/html/Search/Elements/ChartTable
+++ b/share/html/Search/Elements/ChartTable
@@ -34,7 +34,7 @@ foreach my $section (qw(thead tbody tfoot)) {
             push @class, ($cell->{'type'}) unless $cell->{'type'} eq 'head';
             $m->out(' class="'. $eh->( join ' ', @class ) .'"');
 
-            foreach my $dir ( grep $cell->{$_}, qw(rawspan colspan) ) {
+            foreach my $dir ( grep $cell->{$_}, qw(rowspan colspan) ) {
                 my $value = int $cell->{ $dir };
                 $m->out(qq{ $dir="$value"});
             }

commit 5fd922a83a2571eb9324345b1d4c0339870b2e5a
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Tue Jun 28 04:51:03 2011 +0400

    get rid of undef warning

diff --git a/share/html/Search/Elements/ChartTable b/share/html/Search/Elements/ChartTable
index 2f5a3ff..ade045e 100644
--- a/share/html/Search/Elements/ChartTable
+++ b/share/html/Search/Elements/ChartTable
@@ -43,7 +43,7 @@ foreach my $section (qw(thead tbody tfoot)) {
                 if ( my $q = $cell->{'query'} ) {
                     $m->out(
                         '<a href="'. RT->Config->Get('WebPath') .'/Search/Results.html'
-                        .'?Query='. $eu->("$Query AND $q")
+                        .'?Query='. $eu->(join ' AND ', grep defined && length, $Query, $q)
                         .'&'. $base_query
                         . '">'
                     );

commit 326b6d8d411617278035900b21d0f8589ca97cf5
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Tue Jun 28 04:51:55 2011 +0400

    we should use SB's method as local breaks references

diff --git a/lib/RT/Report/Tickets/Entry.pm b/lib/RT/Report/Tickets/Entry.pm
index f58ff4a..ad55d06 100644
--- a/lib/RT/Report/Tickets/Entry.pm
+++ b/lib/RT/Report/Tickets/Entry.pm
@@ -92,7 +92,7 @@ sub LabelValue {
 }
 
 sub RawValue {
-    return (shift)->__Value( @_ );
+    return (shift)->DBIx::SearchBuilder::Record::__Value( @_ );
 }
 
 sub Query {

commit 2df4270a095b359126ff0ffbd67fe0ea7a6cb010
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Tue Jun 28 07:20:59 2011 +0400

    position columns, so sorting entries works

diff --git a/lib/RT/Report/Tickets.pm b/lib/RT/Report/Tickets.pm
index dd31cd5..4b50c24 100644
--- a/lib/RT/Report/Tickets.pm
+++ b/lib/RT/Report/Tickets.pm
@@ -384,7 +384,8 @@ sub ColumnInfo {
 
 sub ColumnsList {
     my $self = shift;
-    return keys %{ $self->{'column_info'} || {} };
+    return sort { $self->{'column_info'}{$a}{'POSITION'} <=> $self->{'column_info'}{$b}{'POSITION'} }
+        keys %{ $self->{'column_info'} || {} };
 }
 
 sub SetupGroupings {
@@ -400,6 +401,8 @@ sub SetupGroupings {
 
     %GROUPINGS = @GROUPINGS unless keys %GROUPINGS;
 
+    my $i = 0;
+
     my @group_by = grep defined && length,
         ref( $args{'GroupBy'} )? @{ $args{'GroupBy'} } : ($args{'GroupBy'});
     foreach my $e ( @group_by ) {
@@ -408,6 +411,7 @@ sub SetupGroupings {
         $e->{'TYPE'} = 'grouping';
         $e->{'INFO'} = $GROUPINGS{ $key };
         $e->{'META'} = $GROUPINGS_META{ $e->{'INFO'} };
+        $e->{'POSITION'} = $i++;
     }
     $self->GroupBy( map { {
         ALIAS    => $_->{'ALIAS'},
@@ -434,7 +438,7 @@ sub SetupGroupings {
             KEY  => $e,
             INFO => $STATISTICS{ $e },
             META => $STATISTICS_META{ $STATISTICS{ $e }[1] },
-
+            POSITION => $i++,
         };
         unless ( $e->{'INFO'} && $e->{'META'} ) {
             $RT::Logger->error("'". $e->{'KEY'} ."' is not valid statistic for report");

commit c832006c5e3f05cd5ac9d75aaaef03628430fadd
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Tue Jun 28 07:22:12 2011 +0400

    support compex functions in Entry->LabelValue

diff --git a/lib/RT/Report/Tickets/Entry.pm b/lib/RT/Report/Tickets/Entry.pm
index ad55d06..7d140e2 100644
--- a/lib/RT/Report/Tickets/Entry.pm
+++ b/lib/RT/Report/Tickets/Entry.pm
@@ -86,9 +86,20 @@ sub LabelValue {
         return $code->( $self, %{ $self->ColumnInfo( $name ) }, VALUE => $raw );
     }
 
-    return $self->loc('(no value)') unless defined $raw && length $raw;
-    return $self->loc($raw) if $self->ColumnInfo( $name )->{'META'}{'Localize'};
-    return $raw;
+    unless ( ref $raw ) {
+        return $self->loc('(no value)') unless defined $raw && length $raw;
+        return $self->loc($raw) if $self->ColumnInfo( $name )->{'META'}{'Localize'};
+        return $raw;
+    } else {
+        my $loc = $self->ColumnInfo( $name )->{'META'}{'Localize'};
+        my %res = %$raw;
+        if ( $loc ) {
+            $res{ $self->loc($_) } = delete $res{ $_ } foreach keys %res;
+            $_ = $self->loc($_) foreach values %res;
+        }
+        $_ = $self->loc('(no value)') foreach grep !defined || !length, values %res;
+        return \%res;
+    }
 }
 
 sub RawValue {

commit d6b98c5d2eb4d8ba9d163eb601d3847c6a5ed281
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Tue Jun 28 07:24:35 2011 +0400

    table rendering of complex functions with SubValues

diff --git a/lib/RT/Report/Tickets.pm b/lib/RT/Report/Tickets.pm
index 4b50c24..3bb1abc 100644
--- a/lib/RT/Report/Tickets.pm
+++ b/lib/RT/Report/Tickets.pm
@@ -786,8 +786,8 @@ sub FormatTable {
     my (@head, @body, @footer);
 
     @head = ({ cells => []});
-    foreach my $column ( @{ $columns{'Groups'} }, @{ $columns{'Functions'} } ) {
-        push @{ $head[0]{'cells'} }, { type => 'head', value => $self->Label($column) };
+    foreach my $column ( @{ $columns{'Groups'} } ) {
+        push @{ $head[0]{'cells'} }, { type => 'head', value => $self->Label( $column ) };
     }
 
     my $i = 0;
@@ -814,23 +814,80 @@ sub FormatTable {
 
     foreach my $column ( @{ $columns{'Functions'} } ) {
         $i = 0;
-        my $total;
+
+        my $info = $self->ColumnInfo( $column );
+
+        my @subs = ('');
+        if ( $info->{'META'}{'SubValues'} ) {
+            @subs = $self->FindImplementationCode( $info->{'META'}{'SubValues'} )->(
+                $self
+            );
+        }
+
+        my %total;
         while ( my $entry = $self->Next ) {
-            my $raw = $entry->RawValue( $column );
-            $total += $raw if defined $raw && length $raw;
+            my $raw = $entry->RawValue( $column ) || {};
+            $raw = { '' => $raw } unless ref $raw;
+            $total{ $_ } += $raw->{ $_ } foreach grep $raw->{$_}, @subs;
+        }
+        @subs = grep $total{$_}, @subs;
 
-            my $value = $entry->LabelValue( $column );
-            push @{ $body[ $i++ ]{'cells'} }, {
-                type => 'value',
-                value => $value,
-                query => $entry->Query,
+        my $label = $self->Label( $column );
+
+        unless (@subs) {
+            while ( my $entry = $self->Next ) {
+                push @{ $body[ $i++ ]{'cells'} }, {
+                    type => 'value',
+                    value => undef,
+                    query => $entry->Query,
+                };
+            }
+            push @{ $head[0]{'cells'} }, {
+                type => 'head',
+                value => $label,
+                rowspan => scalar @head,
+            };
+            push @{ $footer[0]{'cells'} }, { type => 'value', value => undef };
+            next;
+        }
+
+        if ( @subs > 1 && @head == 1 ) {
+            $_->{rowspan} = 2 foreach @{ $head[0]{'cells'} };
+        }
+
+        if ( @subs == 1 ) {
+            push @{ $head[0]{'cells'} }, {
+                type => 'head',
+                value => $label,
+                rowspan => scalar @head,
             };
+        } else {
+            push @{ $head[0]{'cells'} }, { type => 'head', value => $label, colspan => scalar @subs };
+            push @{ $head[1]{'cells'} }, { type => 'head', value => $_ }
+                foreach @subs;
         }
-        if ( $total and my $code = $self->LabelValueCode( $column ) ) {
-            my $info = $self->ColumnInfo( $column );
-            $total = $code->( $self, %$info, VALUE => $total );
+
+        while ( my $entry = $self->Next ) {
+            my $query = $entry->Query;
+            my $value = $entry->LabelValue( $column ) || {};
+            $value = { '' => $value } unless ref $value;
+            foreach my $e ( @subs ) {
+                push @{ $body[ $i ]{'cells'} }, {
+                    type => 'value',
+                    value => $value->{ $e },
+                    query => $query,
+                };
+            }
+            $i++;
+        }
+
+        my $total_code = $self->LabelValueCode( $column );
+        foreach my $e ( @subs ) {
+            my $total = $total{ $e };
+            $total = $total_code->( $self, %$info, VALUE => $total )
+                if $total_code;
+            push @{ $footer[0]{'cells'} }, { type => 'value', value => $total };
         }
-        push @{ $footer[0]{'cells'} }, { type => 'value', value => $total };
     }
 
     return thead => \@head, tbody => \@body, tfoot => \@footer;

commit 1aa4ec78bf058ed0ab582c388972f9f66ef2dc8b
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Tue Jun 28 07:44:57 2011 +0400

    rowspan equal grouping values

diff --git a/lib/RT/Report/Tickets.pm b/lib/RT/Report/Tickets.pm
index 3bb1abc..1099191 100644
--- a/lib/RT/Report/Tickets.pm
+++ b/lib/RT/Report/Tickets.pm
@@ -799,11 +799,16 @@ sub FormatTable {
 
     foreach my $column ( @{ $columns{'Groups'} } ) {
         $i = 0;
+        my $last;
         while ( my $entry = $self->Next ) {
-            push @{ $body[ $i++ ]{'cells'} }, {
-                type => 'label',
-                value => $entry->LabelValue( $column )
-            };
+            my $value = $entry->LabelValue( $column );
+            if ( !$last || $last->{'value'} ne $value ) {
+                push @{ $body[ $i++ ]{'cells'} }, $last = { type => 'label', value => $value, };
+            }
+            else {
+                $i++;
+                $last->{rowspan} = ($last->{rowspan}||1) + 1;
+            }
         }
     }
     push @{ $footer[0]{'cells'} }, {

-----------------------------------------------------------------------


More information about the Rt-commit mailing list