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

Ruslan Zakirov ruz at bestpractical.com
Tue Jun 21 21:33:50 EDT 2011


The branch, 4.2/date-time-improvements-in-charts has been updated
       via  5966a7f04caa3da9c0a790656347ce7a6fb6e0d8 (commit)
       via  ee8bd21664ebc92521469eb772c9a53856fd53ea (commit)
       via  ca9d525077633d33cc0fb352035305c16f615aac (commit)
       via  09b29c1bb46a9e382fb8d83674808dcaaffa185a (commit)
       via  0cf0ac109543e775e8ee609a03893566f2125843 (commit)
       via  5483f575ce035209b457a29416b4c9fb4d2c2a6b (commit)
       via  6310eb1f7460c149777547fc0c6109a9c0004021 (commit)
       via  a9a1e2d8752cad9bd05eb6697978d032f21974b6 (commit)
      from  1e3b8a597813d122f680531efdf36d45f3c4bb1f (commit)

Summary of changes:
 lib/RT/Report/Tickets.pm         |  132 ++++++++++++++++++++++++++------------
 share/html/Search/Chart          |   71 +++++++++++++-------
 share/html/Search/Elements/Chart |   19 +++--
 3 files changed, 148 insertions(+), 74 deletions(-)

- Log -----------------------------------------------------------------
commit a9a1e2d8752cad9bd05eb6697978d032f21974b6
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Tue Jun 21 16:55:57 2011 +0400

    s/tix/report/. it's a report, isn't it?

diff --git a/share/html/Search/Chart b/share/html/Search/Chart
index c3f8c0e..b4532cd 100644
--- a/share/html/Search/Chart
+++ b/share/html/Search/Chart
@@ -65,27 +65,27 @@ if ($ChartStyle eq 'pie') {
 }
 
 use RT::Report::Tickets;
-my $tix = RT::Report::Tickets->new( $session{'CurrentUser'} );
+my $report = RT::Report::Tickets->new( $session{'CurrentUser'} );
 
 foreach my $e ( splice @GroupBy ) {
     next unless defined $e && length $e;
-    next unless $tix->IsValidGrouping( Query => $Query, GroupBy => $e );
+    next unless $report->IsValidGrouping( Query => $Query, GroupBy => $e );
     push @GroupBy, $e;
 }
 
-my %columns = $tix->SetupGroupings(
+my %columns = $report->SetupGroupings(
     Query => $Query,
     GroupBy => \@GroupBy,
     # TODO: We don't picture more than one function at the moment
     Function => (grep defined && length, @ChartFunction)[0],
 );
 
-$tix->SortEntries;
+$report->SortEntries;
 
 my @data = ([],[]);
 my $max_value = 0;
 my $max_key_length = 0;
-while ( my $entry = $tix->Next ) {
+while ( my $entry = $report->Next ) {
     my $key = join ' - ', map $entry->LabelValue( $_ ), @{ $columns{'Groups'} };
     my $value = $entry->RawValue( $columns{'Functions'}[0] );
     if ($chart_class eq 'GD::Graph::pie') {
@@ -107,7 +107,7 @@ my $font = $font_config{ $session{CurrentUser}->UserObj->Lang || '' }
 # that indicates an error message. Because this is used in an <img>
 # context, it can't be a simple error message. Without this check,
 # the chart will just be a non-loading image.
-unless ( $tix->Count ) {
+unless ( $report->Count ) {
     my $plot = GD::Image->new(600 => 400);
     $plot->colorAllocate(255, 255, 255); # background
     my $black = $plot->colorAllocate(0, 0, 0);
@@ -138,8 +138,8 @@ $chart->set_value_font( $font, 12 ) if $chart->can('set_value_font');
 if ($chart_class eq "GD::Graph::bars") {
     my $count = @{ $data[0] };
     $chart->set(
-        x_label => join( ' - ', map $tix->Label( $_ ), @{ $columns{'Groups'} } ),
-        y_label => $tix->Label( $columns{'Functions'}[0] ),
+        x_label => join( ' - ', map $report->Label( $_ ), @{ $columns{'Groups'} } ),
+        y_label => $report->Label( $columns{'Functions'}[0] ),
         show_values => 1,
         x_label_position => 0.6,
         y_label_position => 0.6,
diff --git a/share/html/Search/Elements/Chart b/share/html/Search/Elements/Chart
index 0009dc4..2afe506 100644
--- a/share/html/Search/Elements/Chart
+++ b/share/html/Search/Elements/Chart
@@ -54,15 +54,15 @@ $ChartStyle => 'bars'
 <%init>
 use RT::Report::Tickets;
 
-my $tix = RT::Report::Tickets->new( $session{'CurrentUser'} );
+my $report = RT::Report::Tickets->new( $session{'CurrentUser'} );
 
 foreach my $e ( splice @GroupBy ) {
     next unless defined $e && length $e;
-    next unless $tix->IsValidGrouping( Query => $Query, GroupBy => $e );
+    next unless $report->IsValidGrouping( Query => $Query, GroupBy => $e );
     push @GroupBy, $e;
 }
 
-my %columns = $tix->SetupGroupings(
+my %columns = $report->SetupGroupings(
     Query => $Query,
     GroupBy => \@GroupBy,
     Function => \@ChartFunction,
@@ -83,7 +83,7 @@ my $query_string = $m->comp('/Elements/QueryString', %ARGS, GroupBy => \@GroupBy
 
 <tr>
 % foreach my $column ( @{ $columns{'Groups'} }, @{ $columns{'Functions'} } ) {
-<th class="collection-as-table"><% $tix->Label( $column ) %></th>
+<th class="collection-as-table"><% $report->Label( $column ) %></th>
 % }
 </tr>
 
@@ -94,11 +94,11 @@ my $query_string = $m->comp('/Elements/QueryString', %ARGS, GroupBy => \@GroupBy
 %     Order   => $ARGS{Order},
 % );
 
-% $tix->SortEntries;
+% $report->SortEntries;
 
 % my $i = 0;
 % my %total = map { $_ => 0 } @{ $columns{Functions} };
-% while ( my $entry = $tix->Next ) {
+% while ( my $entry = $report->Next ) {
 <tr class="<% ++$i%2 ? 'evenline' : 'oddline' %>">
 
 % foreach my $column ( @{ $columns{'Groups'} } ) {

commit 6310eb1f7460c149777547fc0c6109a9c0004021
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Tue Jun 21 20:05:24 2011 +0400

    multiple functions in the charts, but bars only

diff --git a/share/html/Search/Chart b/share/html/Search/Chart
index b4532cd..e94ad42 100644
--- a/share/html/Search/Chart
+++ b/share/html/Search/Chart
@@ -52,10 +52,13 @@ $ChartStyle => 'bars'
 @ChartFunction => 'COUNT'
 </%args>
 <%init>
-my $chart_class;
 use GD;
 use GD::Text;
 
+ at ChartFunction = grep defined && length, @ChartFunction;
+$ChartStyle = 'bars' if @ChartFunction > 1;
+
+my $chart_class;
 if ($ChartStyle eq 'pie') {
     require GD::Graph::pie;
     $chart_class = "GD::Graph::pie";
@@ -76,8 +79,7 @@ foreach my $e ( splice @GroupBy ) {
 my %columns = $report->SetupGroupings(
     Query => $Query,
     GroupBy => \@GroupBy,
-    # TODO: We don't picture more than one function at the moment
-    Function => (grep defined && length, @ChartFunction)[0],
+    Function => \@ChartFunction,
 );
 
 $report->SortEntries;
@@ -87,15 +89,20 @@ my $max_value = 0;
 my $max_key_length = 0;
 while ( my $entry = $report->Next ) {
     my $key = join ' - ', map $entry->LabelValue( $_ ), @{ $columns{'Groups'} };
-    my $value = $entry->RawValue( $columns{'Functions'}[0] );
+
+    my @values = map $entry->RawValue($_), @{ $columns{'Functions'} };
     if ($chart_class eq 'GD::Graph::pie') {
-        $key .= ' - '. $value;
+        $key .= ' - '. $values[0];
     }
 
     push @{ $data[0] }, $key;
-    push @{ $data[1] }, $value;
 
-    $max_value = $value if $max_value < $value;
+    my $i = 0;
+    push @{ $data[++$i] }, $_ foreach @values;
+
+    foreach my $v ( @values ) {
+        $max_value = $v if $max_value < $v;
+    }
     $max_key_length = length $key if $max_key_length < length $key;
 }
 

commit 5483f575ce035209b457a29416b4c9fb4d2c2a6b
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Tue Jun 21 20:06:17 2011 +0400

    bargroup_spacing five times bigger than bar spacing

diff --git a/share/html/Search/Chart b/share/html/Search/Chart
index e94ad42..f352911 100644
--- a/share/html/Search/Chart
+++ b/share/html/Search/Chart
@@ -144,6 +144,12 @@ $chart->set_value_font( $font, 12 ) if $chart->can('set_value_font');
 
 if ($chart_class eq "GD::Graph::bars") {
     my $count = @{ $data[0] };
+    my $bar_spacing =
+        $count > 30 ? 1
+        : $count > 20 ? 2
+        : $count > 10 ? 3
+        : 5
+    ;
     $chart->set(
         x_label => join( ' - ', map $report->Label( $_ ), @{ $columns{'Groups'} } ),
         y_label => $report->Label( $columns{'Functions'}[0] ),
@@ -157,9 +163,8 @@ if ($chart_class eq "GD::Graph::bars") {
         y_max_value => 5*(int($max_value/5) + 2),
 # if there're too many bars or at least one key is too long, use vertical
         x_labels_vertical => ( $count * $max_key_length > 60 ) ? 1 : 0,
-        $count > 30 ? ( bar_spacing => 1 ) : ( $count > 20 ? ( bar_spacing => 2 ) : 
-            ( $count > 10 ? ( bar_spacing => 3 ) : ( bar_spacing => 5 ) )
-        ),
+        bar_spacing => $bar_spacing,
+        bargroup_spacing => $bar_spacing*5,
     );
 }
 

commit 0cf0ac109543e775e8ee609a03893566f2125843
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Tue Jun 21 22:27:24 2011 +0400

    sort by all groupings

diff --git a/lib/RT/Report/Tickets.pm b/lib/RT/Report/Tickets.pm
index 9562c39..b063ab8 100644
--- a/lib/RT/Report/Tickets.pm
+++ b/lib/RT/Report/Tickets.pm
@@ -530,52 +530,60 @@ sub AddEmptyRows {
     }
 }
 
+{ our @SORT_OPS;
+sub __sort_function_we_need_named($$) {
+    for my $f ( @SORT_OPS ) {
+        my $r = $f->($_[0], $_[1]);
+        return $r if $r;
+    }
+}
 sub SortEntries {
     my $self = shift;
 
-    # XXX: at the begining let's support only grouping by one column
-    my ($group_by) =
+    $self->_DoSearch if $self->{'must_redo_search'};
+    return unless $self->{'items'} && @{ $self->{'items'} };
+
+    my @groups =
         grep $_->{'TYPE'} eq 'grouping',
         map $self->ColumnInfo($_),
         $self->ColumnsList;
-    return unless $group_by;
-
-    my $order = $group_by->{'META'}{Sort} || 'label';
-    if ( $order eq 'label' ) {
-        $self->{'items'} = [
-            map $_->[0],
-            sort { $a->[1] cmp $b->[1] }
-            map [ $_, $_->LabelValue( $group_by->{'NAME'} ) ],
-            @{ $self->{'items'} || [] }
-        ];
-    }
-    elsif ( $order eq 'numeric label' ) {
-        $self->{'items'} = [
-            map $_->[0],
-            sort { $a->[1] <=> $b->[1] }
-            map [ $_, $_->LabelValue( $group_by->{'NAME'} ) ],
-            @{ $self->{'items'} || [] }
-        ];
-    }
-    elsif ( $order eq 'raw' ) {
-        $self->{'items'} = [
-            map $_->[0],
-            sort { $a->[1] cmp $b->[1] }
-            map [ $_, $_->RawValue( $group_by->{'NAME'} ) ],
-            @{ $self->{'items'} || [] }
-        ];
-    }
-    elsif ( $order eq 'numeric raw' ) {
-        $self->{'items'} = [
-            map $_->[0],
-            sort { $a->[1] <=> $b->[1] }
-            map [ $_, $_->RawValue( $group_by->{'NAME'} ) ],
-            @{ $self->{'items'} || [] }
-        ];
-    } else {
-        $RT::Logger->error("Unknown sorting function '$order'");
+    return unless @groups;
+
+    local @SORT_OPS;
+    my @data = map [$_], @{ $self->{'items'} };
+
+    for ( my $i = 0; $i < @groups; $i++ ) {
+        my $group_by = $groups[$i];
+        my $idx = $i+1;
+        my $method;
+
+        my $order = $group_by->{'META'}{Sort} || 'label';
+        if ( $order eq 'label' ) {
+            push @SORT_OPS, sub { $_[0][$idx] cmp $_[1][$idx] };
+            $method = 'LabelValue';
+        }
+        elsif ( $order eq 'numeric label' ) {
+            push @SORT_OPS, sub { $_[0][$idx] <=> $_[1][$idx] };
+            $method = 'LabelValue';
+        }
+        elsif ( $order eq 'raw' ) {
+            push @SORT_OPS, sub { $_[0][$idx] cmp $_[1][$idx] };
+            $method = 'RawValue';
+        }
+        elsif ( $order eq 'numeric raw' ) {
+            push @SORT_OPS, sub { $_[0][$idx] <=> $_[1][$idx] };
+            $method = 'RawValue';
+        } else {
+            $RT::Logger->error("Unknown sorting function '$order'");
+            next;
+        }
+        $_->[$idx] = $_->[0]->$method( $group_by->{'NAME'} ) for @data;
     }
-}
+    $self->{'items'} = [
+        map $_->[0],
+        sort __sort_function_we_need_named @data
+    ];
+} }
 
 sub GenerateDateFunction {
     my $self = shift;

commit 09b29c1bb46a9e382fb8d83674808dcaaffa185a
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Wed Jun 22 04:28:57 2011 +0400

    pass only required things into GroupBy and Column
    
    these methods may store all passed attributes internaly
    this makes sreialization harder to do

diff --git a/lib/RT/Report/Tickets.pm b/lib/RT/Report/Tickets.pm
index b063ab8..2a1d4b7 100644
--- a/lib/RT/Report/Tickets.pm
+++ b/lib/RT/Report/Tickets.pm
@@ -386,7 +386,11 @@ sub SetupGroupings {
         $e->{'INFO'} = $GROUPINGS{ $key };
         $e->{'META'} = $GROUPINGS_META{ $e->{'INFO'} };
     }
-    $self->GroupBy( @group_by );
+    $self->GroupBy( map { {
+        ALIAS    => $_->{'ALIAS'},
+        FIELD    => $_->{'FIELD'},
+        FUNCTION => $_->{'FUNCTION'},
+    } } @group_by );
 
     my %res = (Groups => [], Functions => []);
     my %column_info;
@@ -404,7 +408,11 @@ sub SetupGroupings {
         $args{'TYPE'} = 'statistic';
         $args{'INFO'} = $STATISTICS{ $e };
         $args{'META'} = $STATISTICS_META{ $args{'INFO'}[1] };
-        $args{'NAME'} = $self->Column( %args );
+        $args{'NAME'} = $self->Column(
+            ALIAS    => $args{'ALIAS'},
+            FIELD    => $args{'FIELD'},
+            FUNCTION => $args{'FUNCTION'},
+        );
         push @{ $res{'Functions'} }, $args{'NAME'};
         $column_info{ $args{'NAME'} } = \%args;
     }

commit ca9d525077633d33cc0fb352035305c16f615aac
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Wed Jun 22 04:31:28 2011 +0400

    sort report earlier, want to serialize sorted report

diff --git a/share/html/Search/Elements/Chart b/share/html/Search/Elements/Chart
index 2afe506..1606bec 100644
--- a/share/html/Search/Elements/Chart
+++ b/share/html/Search/Elements/Chart
@@ -68,6 +68,8 @@ my %columns = $report->SetupGroupings(
     Function => \@ChartFunction,
 );
 
+$report->SortEntries;
+
 my $query_string = $m->comp('/Elements/QueryString', %ARGS, GroupBy => \@GroupBy );
 </%init>
 
@@ -94,8 +96,6 @@ my $query_string = $m->comp('/Elements/QueryString', %ARGS, GroupBy => \@GroupBy
 %     Order   => $ARGS{Order},
 % );
 
-% $report->SortEntries;
-
 % my $i = 0;
 % my %total = map { $_ => 0 } @{ $columns{Functions} };
 % while ( my $entry = $report->Next ) {

commit ee8bd21664ebc92521469eb772c9a53856fd53ea
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Wed Jun 22 04:33:27 2011 +0400

    Serialize and Deserialize methods for reports

diff --git a/lib/RT/Report/Tickets.pm b/lib/RT/Report/Tickets.pm
index 2a1d4b7..62b93ca 100644
--- a/lib/RT/Report/Tickets.pm
+++ b/lib/RT/Report/Tickets.pm
@@ -696,6 +696,40 @@ sub FindImplementationCode {
     }
     return $code;
 }
+
+sub Serialize {
+    my $self = shift;
+
+    my %clone = %$self;
+# current user, handle and column_info
+    delete @clone{'user', 'DBIxHandle', 'column_info'};
+    $clone{'items'} = [ map $_->{'values'}, @{ $clone{'items'} || [] } ];
+    $clone{'column_info'} = {};
+    while ( my ($k, $v) = each %{ $self->{'column_info'} } ) {
+        $clone{'column_info'}{$k} = { %$v };
+        delete $clone{'column_info'}{$k}{'META'};
+    }
+    return \%clone;
+}
+
+sub Deserialize {
+    my $self = shift;
+    my $data = shift;
+
+    $self->CleanSlate;
+    %$self = (%$self, %$data);
+
+    $self->{'items'} = [
+        map { my $r = $self->NewItem; $r->LoadFromHash( $_ ); $r }
+        @{ $self->{'items'} }
+    ];
+    foreach my $e ( values %{ $self->{column_info} } ) {
+        $e->{'META'} = $e->{'TYPE'} eq 'grouping'
+            ? $GROUPINGS_META{ $e->{'INFO'} }
+            : $STATISTICS_META{ $e->{'INFO'}[1] }
+    }
+}
+
 RT::Base->_ImportOverlays();
 
 1;

commit 5966a7f04caa3da9c0a790656347ce7a6fb6e0d8
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Wed Jun 22 04:36:53 2011 +0400

    cache report's data for pictures to re-use

diff --git a/share/html/Search/Chart b/share/html/Search/Chart
index f352911..b315251 100644
--- a/share/html/Search/Chart
+++ b/share/html/Search/Chart
@@ -46,6 +46,7 @@
 %#
 %# END BPS TAGGED BLOCK }}}
 <%args>
+$Cache => undef
 $Query => "id > 0"
 @GroupBy => 'Queue'
 $ChartStyle => 'bars'
@@ -70,19 +71,27 @@ if ($ChartStyle eq 'pie') {
 use RT::Report::Tickets;
 my $report = RT::Report::Tickets->new( $session{'CurrentUser'} );
 
-foreach my $e ( splice @GroupBy ) {
-    next unless defined $e && length $e;
-    next unless $report->IsValidGrouping( Query => $Query, GroupBy => $e );
-    push @GroupBy, $e;
-}
+my %columns;
+
+if ( $Cache and my $data = delete $session{'charts_cache'}{ $Cache } ) {
+    %columns = %{ $data->{'columns'} };
+    $report->Deserialize( $data->{'report'} );
+    $session{'i'}++;
+} else {
+    foreach my $e ( splice @GroupBy ) {
+        next unless defined $e && length $e;
+        next unless $report->IsValidGrouping( Query => $Query, GroupBy => $e );
+        push @GroupBy, $e;
+    }
 
-my %columns = $report->SetupGroupings(
-    Query => $Query,
-    GroupBy => \@GroupBy,
-    Function => \@ChartFunction,
-);
+    %columns = $report->SetupGroupings(
+        Query => $Query,
+        GroupBy => \@GroupBy,
+        Function => \@ChartFunction,
+    );
 
-$report->SortEntries;
+    $report->SortEntries;
+}
 
 my @data = ([],[]);
 my $max_value = 0;
diff --git a/share/html/Search/Elements/Chart b/share/html/Search/Elements/Chart
index 1606bec..7e3f82c 100644
--- a/share/html/Search/Elements/Chart
+++ b/share/html/Search/Elements/Chart
@@ -78,7 +78,10 @@ my $query_string = $m->comp('/Elements/QueryString', %ARGS, GroupBy => \@GroupBy
 % if (RT->Config->Get('DisableGD')) {
 <% loc('Graphical charts are not available.') %><br />
 % } else {
-<img src="<%RT->Config->Get('WebPath')%>/Search/Chart?<%$query_string|n%>" /><br />
+% my $key = Digest::MD5::md5_hex( rand(1024) );
+% $session{'charts_cache'}{$key} = { columns => \%columns, report => $report->Serialize };
+% $session{'i'}++;
+<img src="<% RT->Config->Get('WebPath') %>/Search/Chart?Cache=<% $key |un %>&<% $query_string |n %>" /><br />
 % }
 
 <table class="collection-as-table">

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


More information about the Rt-commit mailing list