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

Ruslan Zakirov ruz at bestpractical.com
Tue Jun 14 15:57:40 EDT 2011


The branch, 4.2/date-time-improvements-in-charts has been updated
       via  fc88cc548e6828f7171dd6331e54d60e5e565891 (commit)
       via  7d66cd6817b93c567b7a41ba1ad242fad5df366e (commit)
       via  a94143c0cd5f7844cd027cb48540ea15f15f0f56 (commit)
       via  e06d188fc7b5fcaaa418d9b67f1554933eb9725a (commit)
       via  0d56119faa7378448eb3abe37d0ac5cd80d20587 (commit)
       via  b7772929a7424c630ec0b8b75be5e2ed1e0a0ca0 (commit)
       via  abed6c40ab4b2f994811bae612c1a67acb779dac (commit)
       via  23381d6c13e1f5cf23208136fd06b5a3da9469b8 (commit)
       via  c37204fd9a4d3afe41c63413078f4e67b3582670 (commit)
       via  b42cf7e54fd484cf09423618ac2e882367a9e800 (commit)
       via  4d389d8f4ff07692ae306f7fcb61c7128cddffe8 (commit)
      from  f1c6bf744003ef6031481fd5b971b60a436b1679 (commit)

Summary of changes:
 TODO.charts                      |    6 +-
 lib/RT/Report/Tickets.pm         |  188 +++++++++++++++++++++++++++++---------
 lib/RT/Report/Tickets/Entry.pm   |   65 ++++++++++----
 lib/RT/SearchBuilder.pm          |    2 +-
 share/html/Search/Chart          |    4 +-
 share/html/Search/Elements/Chart |   78 ++++++----------
 6 files changed, 226 insertions(+), 117 deletions(-)

- Log -----------------------------------------------------------------
commit 4d389d8f4ff07692ae306f7fcb61c7128cddffe8
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Fri Jun 10 23:54:27 2011 +0400

    make NotSet date to NULL conversion more accurate

diff --git a/lib/RT/SearchBuilder.pm b/lib/RT/SearchBuilder.pm
index 99c886b..c716098 100755
--- a/lib/RT/SearchBuilder.pm
+++ b/lib/RT/SearchBuilder.pm
@@ -390,7 +390,7 @@ sub NotSetDateToNullFunction {
     my $self = shift;
     my %args = ( FIELD => undef, @_ );
 
-    my $res = "CASE WHEN ? < '1970-01-02 00:00:00' THEN NULL ELSE ? END";
+    my $res = "CASE WHEN ? BETWEEN '1969-12-31 11:59:59' AND '1970-01-01 12:00:01' THEN NULL ELSE ? END";
     if ( $args{FIELD} ) {
         $res = $self->CombineFunctionWithField( %args, FUNCTION => $res );
     }

commit b42cf7e54fd484cf09423618ac2e882367a9e800
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Sat Jun 11 00:44:38 2011 +0400

    rename ColumnType -> ColumnInfo

diff --git a/lib/RT/Report/Tickets.pm b/lib/RT/Report/Tickets.pm
index f4f173c..2576dcd 100644
--- a/lib/RT/Report/Tickets.pm
+++ b/lib/RT/Report/Tickets.pm
@@ -346,27 +346,31 @@ sub SetupGroupings {
     foreach my $e ( @group_by ) {
         my ($key, $subkey) = split /\./, $e, 2;
         $e = { $self->_FieldToFunction( KEY => $key, SUBKEY => $subkey ) };
-        $e->{'TYPE'} = $GROUPINGS{ $key };
-        $e->{'META'} = $GROUPINGS_META{ $e->{'TYPE'} };
+        $e->{'TYPE'} = 'grouping';
+        $e->{'INFO'} = $GROUPINGS{ $key };
+        $e->{'META'} = $GROUPINGS_META{ $e->{'INFO'} };
     }
     $self->GroupBy( @group_by );
 
-    my (@res, %column_type);
+    my (@res, %column_info);
 
     my @function = 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] };
         push @res, $self->Column( %args );
-        $column_type{ $res[-1] } = \%args;
+        $column_info{ $res[-1] } = \%args;
     }
 
     foreach my $group_by ( @group_by ) {
         my $alias = $self->Column( %$group_by );
-        $column_type{ $alias } = $group_by;
+        $column_info{ $alias } = $group_by;
         push @res, $alias;
     }
 
-    $self->{'column_types'} = \%column_type;
+    $self->{'column_info'} = \%column_info;
 
     return @res;
 }
@@ -471,7 +475,7 @@ sub Next {
 sub NewItem {
     my $self = shift;
     my $res = RT::Report::Tickets::Entry->new($RT::SystemUser); # $self->CurrentUser);
-    $res->{'column_types'} = $self->{'column_types'};
+    $res->{'column_info'} = $self->{'column_info'};
     return $res;
 }
 
diff --git a/lib/RT/Report/Tickets/Entry.pm b/lib/RT/Report/Tickets/Entry.pm
index d69819f..aa872e2 100644
--- a/lib/RT/Report/Tickets/Entry.pm
+++ b/lib/RT/Report/Tickets/Entry.pm
@@ -52,11 +52,11 @@ use base qw/RT::Record/;
 # XXX TODO: how the heck do we acl a report?
 sub CurrentUserHasRight {1}
 
-sub ColumnType {
+sub ColumnInfo {
     my $self = shift;
     my $column = shift;
 
-    return $self->{'column_types'}{$column};
+    return $self->{'column_info'}{$column};
 }
 
 
@@ -74,7 +74,7 @@ sub LabelValue {
 
     my $raw = $self->RawValue( $name, @_ );
 
-    my $info = $self->ColumnType( $name );
+    my $info = $self->ColumnInfo( $name );
 
     my $meta = $info->{'META'};
     return $raw unless $meta && $meta->{'Display'};

commit c37204fd9a4d3afe41c63413078f4e67b3582670
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Sat Jun 11 00:45:38 2011 +0400

    change $report->Label, we need labels for stats
    
    get column name instead of grouping. Fetch data
    from META hashes

diff --git a/lib/RT/Report/Tickets.pm b/lib/RT/Report/Tickets.pm
index 2576dcd..5cfa49e 100644
--- a/lib/RT/Report/Tickets.pm
+++ b/lib/RT/Report/Tickets.pm
@@ -172,6 +172,19 @@ our %GROUPINGS_META = (
             }
             return @res;
         },
+        Label => sub {
+            my $self = shift;
+            my %args = (@_);
+
+            my ($cf) = ( $args{'SUBKEY'} =~ /^{(.*)}$/ );
+            if ( $cf =~ /^\d+$/ ) {
+                my $obj = RT::CustomField->new( $self->CurrentUser );
+                $obj->Load( $cf );
+                $cf = $obj->Name;
+            }
+
+            return 'Custom field [_1]', $self->CurrentUser->loc( $cf );
+        },
     },
     Enum => {
     },
@@ -230,7 +243,6 @@ our %STATISTICS_META = (
 
             return (FUNCTION => $function, FIELD => 'id');
         },
-
     },
     Simple => {
         Function => sub {
@@ -252,7 +264,6 @@ our %STATISTICS_META = (
             return (FUNCTION => "$function($interval)");
         },
     },
-
 );
 
 sub Groupings {
@@ -318,15 +329,48 @@ sub Statistics {
 
 sub Label {
     my $self = shift;
-    my $field = shift;
-    if ( $field =~ /^(?:CF|CustomField)\.{(.*)}$/ ) {
-        my $cf = $1;
-        return $self->CurrentUser->loc( "Custom field '[_1]'", $cf ) if $cf =~ /\D/;
-        my $obj = RT::CustomField->new( $self->CurrentUser );
-        $obj->Load( $cf );
-        return $self->CurrentUser->loc( "Custom field '[_1]'", $obj->Name );
+    my $column = shift;
+
+    my $info = $self->ColumnInfo( $column );
+    unless ( $info ) {
+        $RT::Logger->error("Unknown column '$column'");
+        return $self->CurrentUser->loc('(Incorrect data)');
+    }
+
+    my $label = $info->{'META'}{'Label'};
+    unless ( $label ) {
+        my $res = '';
+        if ( $info->{'TYPE'} eq 'statistic' ) {
+            $res = $info->{'INFO'}[0];
+        }
+        else {
+            $res = join ' ', grep defined && length, @{ $info }{'KEY', 'SUBKEY'};
+        }
+        return $self->CurrentUser->loc( $res );
+    }
+
+    my $code;
+    unless ( ref $label ) {
+        $code = $self->can( $label );
+        unless ( $code ) {
+            $RT::Logger->error("No method ". $label );
+            return $self->CurrentUser->loc('(Incorrect data)');
+        }
+    }
+    elsif ( ref( $label ) eq 'CODE' ) {
+        $code = $label;
     }
-    return $self->CurrentUser->loc($field);
+    else {
+        return $self->CurrentUser->loc('(Incorrect data)');
+    }
+    return $self->CurrentUser->loc( $code->( $self, %$info ) );
+}
+
+sub ColumnInfo {
+    my $self = shift;
+    my $column = shift;
+
+    return $self->{'column_info'}{$column};
 }
 
 sub SetupGroupings {
diff --git a/share/html/Search/Chart b/share/html/Search/Chart
index 5776215..a8337e9 100644
--- a/share/html/Search/Chart
+++ b/share/html/Search/Chart
@@ -137,8 +137,8 @@ if ($tix->Count == 0) {
 if ($chart_class eq "GD::Graph::bars") {
     my $count = keys %data;
     $chart->set(
-        x_label => $tix->Label( $PrimaryGroupBy ),
-        y_label => loc('Tickets'),
+        x_label => $tix->Label( $value_name ),
+        y_label => $tix->Label( $count_name ),
         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 edc3a62..529db52 100644
--- a/share/html/Search/Elements/Chart
+++ b/share/html/Search/Elements/Chart
@@ -93,10 +93,8 @@ my $query_string = $m->comp('/Elements/QueryString', %ARGS);
 
 <table class="collection-as-table">
 <tr>
-<th class="collection-as-table"><% loc($tix->Label($PrimaryGroupBy)) %>
-</th>
-<th class="collection-as-table"><&|/l&>Tickets</&>
-</th>
+<th class="collection-as-table"><% $tix->Label( $value_name ) %></th>
+<th class="collection-as-table"><% $tix->Label( $count_name ) %></th>
 </tr>
 % my ($i,$total);
 % while (my $key = shift @sorted_keys) {

commit 23381d6c13e1f5cf23208136fd06b5a3da9469b8
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Sat Jun 11 00:49:08 2011 +0400

    update TODO

diff --git a/TODO.charts b/TODO.charts
index e555d32..7c7362a 100644
--- a/TODO.charts
+++ b/TODO.charts
@@ -1,12 +1,7 @@
-expand GROUPINGS to list fields and a few callbacks
-
 move abuse protection code from callers to SetupGrouping
 
 protect Function in SetupGrouping from abuse
 
-Y-axis in charts still always labeled as 'Tickets' even
-if calculate different function
-
 upgrade for saved charts to switch from space separator
 to dot
 
@@ -16,3 +11,4 @@ it'd be nice if full day and month names worked in
 we shouldn't sort "day of week" bars according to translated
 values. Now we get Mon, Fri, Wed, Sat, Thu... in russian, so
 it's very annoying to look at.
+

commit abed6c40ab4b2f994811bae612c1a67acb779dac
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Tue Jun 14 20:28:48 2011 +0400

    ColumnList - list of columns on the report entry

diff --git a/lib/RT/Report/Tickets/Entry.pm b/lib/RT/Report/Tickets/Entry.pm
index aa872e2..ceff929 100644
--- a/lib/RT/Report/Tickets/Entry.pm
+++ b/lib/RT/Report/Tickets/Entry.pm
@@ -59,6 +59,10 @@ sub ColumnInfo {
     return $self->{'column_info'}{$column};
 }
 
+sub ColumnsList {
+    return keys %{ $self->{'column_info'} || {} };
+}
+
 
 =head2 LabelValue
 

commit b7772929a7424c630ec0b8b75be5e2ed1e0a0ca0
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Tue Jun 14 20:29:24 2011 +0400

    FindImplementationCode - resolve entries to code ref

diff --git a/lib/RT/Report/Tickets/Entry.pm b/lib/RT/Report/Tickets/Entry.pm
index ceff929..f7eea72 100644
--- a/lib/RT/Report/Tickets/Entry.pm
+++ b/lib/RT/Report/Tickets/Entry.pm
@@ -105,6 +105,36 @@ sub RawValue {
     return (shift)->__Value( @_ );
 }
 
+sub FindImplementationCode {
+    my $self = shift;
+    my $value = shift;
+    my $silent = shift;
+
+    my $code;
+    unless ( $value ) {
+        $RT::Logger->error("Value is not defined. Should be method name or code reference")
+            unless $silent;
+        return undef;
+    }
+    elsif ( !ref $value ) {
+        $code = $self->can( $value );
+        unless ( $code ) {
+            $RT::Logger->error("No method $value in ". (ref $self || $self) ." class" )
+                unless $silent;
+            return undef;
+        }
+    }
+    elsif ( ref( $value ) eq 'CODE' ) {
+        $code = $value;
+    }
+    else {
+        $RT::Logger->error("$value is not method name or code reference")
+            unless $silent;
+        return undef;
+    }
+    return $code;
+}
+
 RT::Base->_ImportOverlays();
 
 1;

commit 0d56119faa7378448eb3abe37d0ac5cd80d20587
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Tue Jun 14 20:30:34 2011 +0400

    ::Query - turn entry of the report into a query

diff --git a/lib/RT/Report/Tickets/Entry.pm b/lib/RT/Report/Tickets/Entry.pm
index f7eea72..9371248 100644
--- a/lib/RT/Report/Tickets/Entry.pm
+++ b/lib/RT/Report/Tickets/Entry.pm
@@ -105,6 +105,37 @@ sub RawValue {
     return (shift)->__Value( @_ );
 }
 
+sub Query {
+    my $self = shift;
+
+    my @parts;
+    foreach my $column ( $self->ColumnsList ) {
+        my $info = $self->ColumnInfo( $column );
+        next unless $info->{'TYPE'} eq 'grouping';
+
+        my $custom = $info->{'META'}{'Query'};
+        if ( $custom and my $code = $self->FindImplementationCode( $custom ) ) {
+            push @parts, $code->( $self, COLUMN => $column, %$info );
+        }
+        else {
+            my $field = join '.', grep $_, $info->{KEY}, $info->{SUBKEY};
+            my $value = $self->RawValue( $column );
+            my $op = '=';
+            if ( defined $value ) {
+                unless ( $value =~ /^\d+$/ ) {
+                    $value =~ s/(['\\])/\\$1/g;
+                    $value = "'$value'";
+                }
+            }
+            else {
+                ($op, $value) = ('IS', 'NULL');
+            }
+            push @parts, "$field $op $value";
+        }
+    }
+    return join ' AND ', grep defined && length, @parts;
+}
+
 sub FindImplementationCode {
     my $self = shift;
     my $value = shift;

commit e06d188fc7b5fcaaa418d9b67f1554933eb9725a
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Tue Jun 14 21:01:04 2011 +0400

    spread usage of FindImplementationCode

diff --git a/lib/RT/Report/Tickets.pm b/lib/RT/Report/Tickets.pm
index 5cfa49e..db42a07 100644
--- a/lib/RT/Report/Tickets.pm
+++ b/lib/RT/Report/Tickets.pm
@@ -281,14 +281,14 @@ sub Groupings {
         elsif ( ref( $meta->{'SubFields'} ) eq 'ARRAY' ) {
             push @fields, map { ("$field $_", "$field.$_") } @{ $meta->{'SubFields'} };
         }
-        elsif ( ref( $meta->{'SubFields'} ) eq 'CODE' ) {
-            push @fields, $meta->{'SubFields'}->(
-                $self,
-                \%args,
-            );
+        elsif ( my $code = $self->FindImplementationCode( $meta->{'SubFields'} ) ) {
+            push @fields, $code->( $self, \%args );
         }
         else {
-            $RT::Logger->error("%GROUPINGS_META for $type has unsupported SubFields");
+            $RT::Logger->error(
+                "$type has unsupported SubFields."
+                ." Not an array, a method name or a code reference"
+            );
         }
     }
     return @fields;
@@ -313,11 +313,8 @@ sub IsValidGrouping {
     elsif ( ref( $meta->{'SubFields'} ) eq 'ARRAY' ) {
         return 1 if grep $_ eq $subkey, @{ $meta->{'SubFields'} };
     }
-    elsif ( ref( $meta->{'SubFields'} ) eq 'CODE' ) {
-        return 1 if grep $_ eq "$key.$subkey", $meta->{'SubFields'}->(
-            $self,
-            \%args,
-        );
+    elsif ( my $code = $self->FindImplementationCode( $meta->{'SubFields'}, 'silent' ) ) {
+        return 1 if grep $_ eq "$key.$subkey", $code->( $self, \%args );
     }
     return 0;
 }
@@ -337,33 +334,20 @@ sub Label {
         return $self->CurrentUser->loc('(Incorrect data)');
     }
 
-    my $label = $info->{'META'}{'Label'};
-    unless ( $label ) {
-        my $res = '';
-        if ( $info->{'TYPE'} eq 'statistic' ) {
-            $res = $info->{'INFO'}[0];
-        }
-        else {
-            $res = join ' ', grep defined && length, @{ $info }{'KEY', 'SUBKEY'};
-        }
-        return $self->CurrentUser->loc( $res );
+    if ( $info->{'META'}{'Label'} ) {
+        my $code = $self->FindImplementationCode( $info->{'META'}{'Label'} );
+        return $self->CurrentUser->loc( $code->( $self, %$info ) )
+            if $code;
     }
 
-    my $code;
-    unless ( ref $label ) {
-        $code = $self->can( $label );
-        unless ( $code ) {
-            $RT::Logger->error("No method ". $label );
-            return $self->CurrentUser->loc('(Incorrect data)');
-        }
-    }
-    elsif ( ref( $label ) eq 'CODE' ) {
-        $code = $label;
+    my $res = '';
+    if ( $info->{'TYPE'} eq 'statistic' ) {
+        $res = $info->{'INFO'}[0];
     }
     else {
-        return $self->CurrentUser->loc('(Incorrect data)');
+        $res = join ' ', grep defined && length, @{ $info }{'KEY', 'SUBKEY'};
     }
-    return $self->CurrentUser->loc( $code->( $self, %$info ) );
+    return $self->CurrentUser->loc( $res );
 }
 
 sub ColumnInfo {
@@ -457,21 +441,8 @@ sub _FieldToFunction {
 
     return %args unless $meta->{'Function'};
 
-    my $code;
-    unless ( ref $meta->{'Function'} ) {
-        $code = $self->can( $meta->{'Function'} );
-        unless ( $code ) {
-            $RT::Logger->error("No method ". $meta->{'Function'} );
-            return ('FUNCTION' => 'NULL');
-        }
-    }
-    elsif ( ref( $meta->{'Function'} ) eq 'CODE' ) {
-        $code = $meta->{'Function'};
-    }
-    else {
-        $RT::Logger->error("%GROUPINGS_META for $args{FIELD} has unsupported Function");
-        return ('FUNCTION' => 'NULL');
-    }
+    my $code = $self->FindImplementationCode( $meta->{'Function'} );
+    return ('FUNCTION' => 'NULL') unless $code;
 
     return $code->( $self, %args );
 }
@@ -622,6 +593,35 @@ sub GenerateWatcherFunction {
     return %args;
 }
 
+sub FindImplementationCode {
+    my $self = shift;
+    my $value = shift;
+    my $silent = shift;
+
+    my $code;
+    unless ( $value ) {
+        $RT::Logger->error("Value is not defined. Should be method name or code reference")
+            unless $silent;
+        return undef;
+    }
+    elsif ( !ref $value ) {
+        $code = $self->can( $value );
+        unless ( $code ) {
+            $RT::Logger->error("No method $value in ". (ref $self || $self) ." class" )
+                unless $silent;
+            return undef;
+        }
+    }
+    elsif ( ref( $value ) eq 'CODE' ) {
+        $code = $value;
+    }
+    else {
+        $RT::Logger->error("$value is not method name or code reference")
+            unless $silent;
+        return undef;
+    }
+    return $code;
+}
 RT::Base->_ImportOverlays();
 
 1;
diff --git a/lib/RT/Report/Tickets/Entry.pm b/lib/RT/Report/Tickets/Entry.pm
index 9371248..902eec8 100644
--- a/lib/RT/Report/Tickets/Entry.pm
+++ b/lib/RT/Report/Tickets/Entry.pm
@@ -83,20 +83,8 @@ sub LabelValue {
     my $meta = $info->{'META'};
     return $raw unless $meta && $meta->{'Display'};
 
-    my $code;
-    unless ( ref $meta->{'Display'} ) {
-        $code = $self->can( $meta->{'Display'} );
-        unless ( $code ) {
-            $RT::Logger->error("No method ". $meta->{'Display'} );
-            return $raw;
-        }
-    }
-    elsif ( ref( $meta->{'Display'} ) eq 'CODE' ) {
-        $code = $meta->{'Display'};
-    }
-    else {
-        return $raw;
-    }
+    my $code = $self->FindImplementationCode( $meta->{'Display'} );
+    return $raw unless $code;
 
     return $code->( $self, %$info, VALUE => $raw );
 }
@@ -137,33 +125,7 @@ sub Query {
 }
 
 sub FindImplementationCode {
-    my $self = shift;
-    my $value = shift;
-    my $silent = shift;
-
-    my $code;
-    unless ( $value ) {
-        $RT::Logger->error("Value is not defined. Should be method name or code reference")
-            unless $silent;
-        return undef;
-    }
-    elsif ( !ref $value ) {
-        $code = $self->can( $value );
-        unless ( $code ) {
-            $RT::Logger->error("No method $value in ". (ref $self || $self) ." class" )
-                unless $silent;
-            return undef;
-        }
-    }
-    elsif ( ref( $value ) eq 'CODE' ) {
-        $code = $value;
-    }
-    else {
-        $RT::Logger->error("$value is not method name or code reference")
-            unless $silent;
-        return undef;
-    }
-    return $code;
+    return RT::Report::Tickets->can('FindImplementationCode')->(@_);
 }
 
 RT::Base->_ImportOverlays();

commit a94143c0cd5f7844cd027cb48540ea15f15f0f56
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Tue Jun 14 23:54:18 2011 +0400

    use strict and fix missing var declaration

diff --git a/lib/RT/Report/Tickets/Entry.pm b/lib/RT/Report/Tickets/Entry.pm
index 902eec8..d322174 100644
--- a/lib/RT/Report/Tickets/Entry.pm
+++ b/lib/RT/Report/Tickets/Entry.pm
@@ -46,6 +46,9 @@
 #
 # END BPS TAGGED BLOCK }}}
 
+use strict;
+use warnings;
+
 package RT::Report::Tickets::Entry;
 use base qw/RT::Record/;
 
@@ -60,6 +63,7 @@ sub ColumnInfo {
 }
 
 sub ColumnsList {
+    my $self = shift;
     return keys %{ $self->{'column_info'} || {} };
 }
 

commit 7d66cd6817b93c567b7a41ba1ad242fad5df366e
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Tue Jun 14 23:55:01 2011 +0400

    sort reports in libs

diff --git a/lib/RT/Report/Tickets.pm b/lib/RT/Report/Tickets.pm
index db42a07..d80e87a 100644
--- a/lib/RT/Report/Tickets.pm
+++ b/lib/RT/Report/Tickets.pm
@@ -135,6 +135,7 @@ our %GROUPINGS_META = (
             }
             return $raw;
         },
+        Sort => 'raw',
     },
     CustomField => {
         SubFields => sub {
@@ -356,6 +357,10 @@ sub ColumnInfo {
 
     return $self->{'column_info'}{$column};
 }
+sub ColumnsList {
+    my $self = shift;
+    return keys %{ $self->{'column_info'} || {} };
+}
 
 sub SetupGroupings {
     my $self = shift;
@@ -389,12 +394,14 @@ sub SetupGroupings {
         $args{'INFO'} = $STATISTICS{ $e };
         $args{'META'} = $STATISTICS_META{ $args{'INFO'}[1] };
         push @res, $self->Column( %args );
-        $column_info{ $res[-1] } = \%args;
+        $args{'NAME'} = $res[-1];
+        $column_info{ $args{'NAME'} } = \%args;
     }
 
     foreach my $group_by ( @group_by ) {
         my $alias = $self->Column( %$group_by );
         $column_info{ $alias } = $group_by;
+        $group_by->{'NAME'} = $alias;
         push @res, $alias;
     }
 
@@ -519,6 +526,53 @@ sub AddEmptyRows {
     }
 }
 
+sub SortEntries {
+    my $self = shift;
+
+    # XXX: at the begining let's support only grouping by one column
+    my ($group_by) =
+        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'");
+    }
+}
+
 sub GenerateDateFunction {
     my $self = shift;
     my %args = @_;

commit fc88cc548e6828f7171dd6331e54d60e5e565891
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Tue Jun 14 23:56:47 2011 +0400

    use sorting from libs

diff --git a/share/html/Search/Elements/Chart b/share/html/Search/Elements/Chart
index 529db52..836898f 100644
--- a/share/html/Search/Elements/Chart
+++ b/share/html/Search/Elements/Chart
@@ -66,20 +66,6 @@ my ($count_name, $value_name) = $tix->SetupGroupings(
     Function => $ChartFunction,
 );
 
-my (@keys, @values);
-while ( my $entry = $tix->Next ) {
-    push @keys, $entry->LabelValue( $value_name )
-        || loc('(no value)');
-    push @values, $entry->__Value( $count_name );
-}
-
-my %data;
-my %loc_keys;
-foreach my $key (@keys) { $data{$key} = shift @values; $loc_keys{$key} = loc($key); }
-my @sorted_keys = map { $loc_keys{$_}} sort { $loc_keys{$a} cmp $loc_keys{$b} } keys %loc_keys;
-my @sorted_values = map { $data{$_}} sort { $loc_keys{$a} cmp $loc_keys{$b} } keys %loc_keys;
-
-
 my $query_string = $m->comp('/Elements/QueryString', %ARGS);
 </%init>
 
@@ -92,49 +78,45 @@ my $query_string = $m->comp('/Elements/QueryString', %ARGS);
 % }
 
 <table class="collection-as-table">
+
 <tr>
 <th class="collection-as-table"><% $tix->Label( $value_name ) %></th>
 <th class="collection-as-table"><% $tix->Label( $count_name ) %></th>
 </tr>
-% my ($i,$total);
-% while (my $key = shift @sorted_keys) {
-% $i++;
-% my $value = shift @sorted_values;
-% $total += $value;
-<tr class="<%$i%2 ? 'evenline' : 'oddline' %>">
+
+% my $base_query = $m->comp('/Elements/QueryString',
+%     Format  => $ARGS{Format},
+%     Rows    => $ARGS{Rows},
+%     OrderBy => $ARGS{OrderBy},
+%     Order   => $ARGS{Order},
+% );
+
+% $tix->SortEntries;
+
+% my ($i,$total) = (0, 0);
+% while ( my $entry = $tix->Next ) {
+<tr class="<% $i%2 ? 'evenline' : 'oddline' %>">
+
 <td class="label collection-as-table">
-%# TODO sadly we don't have "creator.city is null" or alike support yet
-%# so no link if the key is undef for now
-% if ( $PrimaryGroupBy !~ /(Hourly|Daily|Monthly|Annually)$/
-%        && $key ne loc('(no value)') ) {
-% my $group = $PrimaryGroupBy; $group =~ s! !.!;
-% my %orig_keys = reverse %loc_keys;
-% my $QueryString = $m->comp('/Elements/QueryString',
-%           Query => "$Query and $group = '$orig_keys{$key}'",
-%                           Format  => $ARGS{Format},
-%                           Rows    => $ARGS{Rows},
-%                           OrderBy => $ARGS{OrderBy},
-%                           Order   => $ARGS{Order},
-%                          );
-<a href=<% RT->Config->Get('WebURL') %>Search/Results.html?<%$QueryString%>><%$key%></a>
+% my $key = $entry->LabelValue( $value_name ) || loc('(no value)');
+% my $entry_query = $entry->Query;
+% if ( $entry_query ) {
+<a href="<% RT->Config->Get('WebPath') %>/Search/Results.html?Query=<% "$Query AND $entry_query" |u %>&<% $base_query |hn %>"><% $key %></a>
 % } else {
 <% $key %>
 % }
 </td>
-<td class="value collection-as-table">
-<%$value%>
-</td>
+
+% $total += my $value = $entry->RawValue( $count_name );
+<td class="value collection-as-table"><%$value%></td>
+
 </tr>
 % }
 
-%$i++;
-<tr class="<%$i%2 ? 'evenline' : 'oddline' %>">
-<td class="label collection-as-table">
-<%loc('Total')%>
-</td>
-<td class="value collection-as-table">
-<%$total||''%>
-</td>
+% $i++;
+<tr class="<% $i%2 ? 'evenline' : 'oddline' %>">
+<td class="label collection-as-table"><% loc('Total') %></td>
+<td class="value collection-as-table"><% $total || '' %></td>
 </tr>
 
 </table>

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


More information about the Rt-commit mailing list