Mailing List Archive

rt branch 5.0/search-chart-sorting created. rt-5.0.5-185-g479f9f1dc3
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "rt".

The branch, 5.0/search-chart-sorting has been created
at 479f9f1dc387d32b3915d9403fe7a5a2260e8431 (commit)

- Log -----------------------------------------------------------------
commit 479f9f1dc387d32b3915d9403fe7a5a2260e8431
Author: sunnavy <sunnavy@bestpractical.com>
Date: Thu Mar 28 11:41:17 2024 -0400

Test sorting/limit feature of search charts

diff --git a/t/charts/basics.t b/t/charts/basics.t
index 0f93e5a243..1527a5e1dd 100644
--- a/t/charts/basics.t
+++ b/t/charts/basics.t
@@ -12,7 +12,7 @@ my @tickets = add_tix_from_data(
{ Subject => 'n', Status => 'new' },
{ Subject => 'o', Status => 'open' },
{ Subject => 'o', Status => 'open' },
- { Subject => 'r', Status => 'resolved' },
+ { Subject => 'o', Status => 'open' },
{ Subject => 'r', Status => 'resolved' },
{ Subject => 'r', Status => 'resolved' },
);
@@ -28,6 +28,19 @@ use_ok 'RT::Report::Tickets';
);
$report->SortEntries;

+ my $new_cell = [.
+ { 'value' => 'new', 'type' => 'label' },
+ { 'query' => '(Status = \'new\')', 'value' => '1', 'type' => 'value' },
+ ];
+ my $open_cell = [.
+ { 'value' => 'open', 'type' => 'label' },
+ { 'query' => '(Status = \'open\')', 'value' => '3', 'type' => 'value' }
+ ];
+ my $resolved_cell = [.
+ { 'value' => 'resolved', 'type' => 'label' },
+ { 'query' => '(Status = \'resolved\')', 'value' => '2', 'type' => 'value' }
+ ];
+
my @colors = RT->Config->Get("ChartColors");
my $expected = {
'thead' => [ {
@@ -45,24 +58,15 @@ use_ok 'RT::Report::Tickets';
} ],
'tbody' => [.
{
- 'cells' => [.
- { 'value' => 'new', 'type' => 'label' },
- { 'query' => '(Status = \'new\')', 'value' => '1', 'type' => 'value' },
- ],
+ 'cells' => $new_cell,
'even' => 1
},
{
- 'cells' => [.
- { 'value' => 'open', 'type' => 'label' },
- { 'query' => '(Status = \'open\')', 'value' => '2', 'type' => 'value' }
- ],
+ 'cells' => $open_cell,
'even' => 0
},
{
- 'cells' => [.
- { 'value' => 'resolved', 'type' => 'label' },
- { 'query' => '(Status = \'resolved\')', 'value' => '3', 'type' => 'value' }
- ],
+ 'cells' => $resolved_cell,
'even' => 1
},
]
@@ -70,6 +74,38 @@ use_ok 'RT::Report::Tickets';

my %table = $report->FormatTable( %columns );
is_deeply( \%table, $expected, "basic table" );
+
+ $report->SortEntries( ChartOrderBy => 'label', ChartOrder => 'ASC' );
+ %table = $report->FormatTable( %columns );
+ is_deeply( \%table, $expected, "basic table sorted by label ASC" );
+
+ $report->SortEntries( ChartOrderBy => 'label', ChartOrder => 'DESC' );
+ %table = $report->FormatTable( %columns );
+ @{$expected->{'tbody'}} = reverse @{$expected->{'tbody'}};
+ is_deeply( \%table, $expected, "basic table sorted by label DESC" );
+
+ $report->SortEntries( ChartOrderBy => 'value', ChartOrder => 'ASC' );
+ %table = $report->FormatTable( %columns );
+ $expected->{'tbody'} = [.
+ {
+ 'cells' => $new_cell,
+ 'even' => 1
+ },
+ {
+ 'cells' => $resolved_cell,
+ 'even' => 0,
+ },
+ {
+ 'cells' => $open_cell,
+ 'even' => 1
+ },
+ ];
+ is_deeply( \%table, $expected, "basic table sorted by value ASC" );
+
+ $report->SortEntries( ChartOrderBy => 'value', ChartOrder => 'DESC' );
+ %table = $report->FormatTable( %columns );
+ @{$expected->{'tbody'}} = reverse @{$expected->{'tbody'}};
+ is_deeply( \%table, $expected, "basic table sorted by value DESC" );
}

done_testing;

commit 1d1afc5156d99b187ca2bad6f033a12259550751
Author: sunnavy <sunnavy@bestpractical.com>
Date: Wed Mar 27 20:16:23 2024 -0400

Support to sort/limit items in search charts

Previously charts were always sorted by labels in ascending order, this
commit enhances it to support descending order too, as well as sorting by
values(i.e. asset/ticket/transaction count).

Limiting the number of results is also implemented in this commit, with
which users can easily get a more friendly chart that contains significant
data only.

diff --git a/lib/RT/Interface/Web.pm b/lib/RT/Interface/Web.pm
index 6fe866f97f..dc90a31294 100644
--- a/lib/RT/Interface/Web.pm
+++ b/lib/RT/Interface/Web.pm
@@ -84,7 +84,7 @@ use RT::Interface::Web::ReportsRegistry;

our @SHORTENER_SEARCH_FIELDS
= qw/Class ObjectType BaseQuery Query Format RowsPerPage Order OrderBy ExtraQueryParams ResultPage/;
-our @SHORTENER_CHART_FIELDS = qw/Width Height ChartStyle GroupBy ChartFunction StackedGroupBy/;
+our @SHORTENER_CHART_FIELDS = qw/Width Height ChartStyle GroupBy ChartFunction StackedGroupBy ChartOrderBy ChartOrder ChartLimit/;

=head2 SquishedCSS $style

diff --git a/lib/RT/Report.pm b/lib/RT/Report.pm
index 5e76fa29ed..6cea047123 100644
--- a/lib/RT/Report.pm
+++ b/lib/RT/Report.pm
@@ -759,6 +759,12 @@ sub _FieldToFunction {

sub SortEntries {
my $self = shift;
+ my %args = (
+ ChartOrderBy => 'label',
+ ChartOrder => 'ASC',
+ ChartLimit => undef,
+ @_,
+ );

$self->_DoSearch if $self->{'must_redo_search'};
return unless $self->{'items'} && @{ $self->{'items'} };
@@ -772,16 +778,21 @@ sub SortEntries {
my @SORT_OPS;
my $by_multiple = sub ($$) {
for my $f ( @SORT_OPS ) {
- my $r = $f->($_[0], $_[1]);
+ my $r = uc $f->($args{ChartOrder} eq 'ASC' ? ( $_[0], $_[1] ) : ( $_[1], $_[0] ) );
return $r if $r;
}
};
+
my @data = map [$_], @{ $self->{'items'} };

- for ( my $i = 0; $i < @groups; $i++ ) {
- my $group_by = $groups[$i];
- my $idx = $i+1;
+ if ( $args{ChartOrderBy} eq 'value' && grep { $_ eq 'id' } $self->ColumnsList ) {
+ $_->[1] = $_->[0]->RawValue('id') for @data;
+ push @SORT_OPS, sub { $_[0][1] <=> $_[1][1] };
+ }

+ # Even if charts are sorted by value, it's still good to sort by labels next, to sort items with the same value.
+ for my $group_by ( @groups ) {
+ my $idx = @SORT_OPS + 1;
my $order = $group_by->{'META'}{Sort} || 'label';
my $method = $order =~ /label$/ ? 'LabelValue' : 'RawValue';

@@ -834,6 +845,10 @@ sub SortEntries {
map $_->[0],
sort $by_multiple @data
];
+
+ if ( $args{ChartLimit} ) {
+ $self->{'items'} = [ splice @{ $self->{'items'} }, 0, $args{ChartLimit} ];
+ }
}

sub PostProcessRecords {
diff --git a/share/html/Search/Chart b/share/html/Search/Chart
index 5b3a19afcc..516eb2b232 100644
--- a/share/html/Search/Chart
+++ b/share/html/Search/Chart
@@ -119,7 +119,7 @@ if ( $Cache and my $data = delete $session{'charts_cache'}{ $Cache } ) {
Function => \@ChartFunction,
);

- $report->SortEntries;
+ $report->SortEntries( map { $_ => $ARGS{$_} } grep { $ARGS{$_} } qw(ChartOrderBy ChartOrder ChartLimit) );
}

my @data = ([],[]);
diff --git a/share/html/Search/Chart.html b/share/html/Search/Chart.html
index 14774cdb37..667d5d1344 100644
--- a/share/html/Search/Chart.html
+++ b/share/html/Search/Chart.html
@@ -56,13 +56,16 @@ my $default_value = {
GroupBy => [ $report->DefaultGroupBy ],
ChartStyle => 'bar+table+sql',
ChartFunction => ['COUNT'],
+ ChartOrderBy => 'label',
+ ChartOrder => 'ASC',
+ ChartLimit => '',
};

$m->callback( ARGSRef => \%ARGS, CallbackName => 'Initial' );

my $title = loc( "Grouped search results");

-my @search_fields = ( qw(Query GroupBy StackedGroupBy ChartStyle ChartFunction Width Height Class ExtraQueryParams), grep $_, @ExtraQueryParams );
+my @search_fields = ( qw(Query GroupBy StackedGroupBy ChartStyle ChartFunction Width Height Class ExtraQueryParams ChartOrderBy ChartOrder ChartLimit), grep $_, @ExtraQueryParams );
my $saved_search = $m->comp( '/Widgets/SavedSearch:new',
SearchType => 'Chart',
SearchFields => [@search_fields],
@@ -273,6 +276,37 @@ $m->callback( ARGSRef => \%ARGS, QueryArgsRef => \%query );
<input type="checkbox" id="ChartStyleIncludeSQL" name="ChartStyleIncludeSQL" class="custom-control-input" <% $query{ChartStyle} =~ /\bsql\b/ ? 'checked="checked"' : '' |n %>>
<label class="custom-control-label" for="ChartStyleIncludeSQL"><&|/l&>Include TicketSQL query</&></label>
</div>
+
+ <div class="form-row sorting">
+ <div class="label col-auto">
+ <span class="far fa-question-circle icon-helper" data-toggle="tooltip" data-placement="top" data-original-title="<&|/l&>Value only works for count calculations</&>"></span>
+ <&|/l&>Order by</&>:
+ </div>
+ <div class="value col-auto">
+ <select name="ChartOrderBy" class="form-control selectpicker">
+ <option value="label" <% $query{ChartOrderBy} eq 'label' ? 'selected="selected"' : '' |n %>><&|/l&>Label</&></option>
+ <option value="value" <% $query{ChartOrderBy} eq 'value' ? 'selected="selected"' : '' |n %>><&|/l&>Value</&></option>
+ </select>
+ </div>
+ <div class="value col-auto">
+ <select name="ChartOrder" class="form-control selectpicker">
+ <option value="ASC" <% $query{ChartOrder} eq 'ASC' ? 'selected="selected"' : '' |n %>><&|/l&>ASC</&></option>
+ <option value="DESC" <% $query{ChartOrder} eq 'DESC' ? 'selected="selected"' : '' |n %>><&|/l&>DESC</&></option>
+ </select>
+ </div>
+ <div class="label col-auto"><&|/l&>Limit</&>:</div>
+ <div class="value col-auto">
+ <div class="input-group">
+ <div class="input-group-prepend">
+ <span class="input-group-text"><&|/l&>top</&></span>
+ </div>
+ <input name="ChartLimit" size="3" class="form-control" value="<% $query{ChartLimit} // '' %>" />
+ <div class="input-group-append">
+ <span class="input-group-text"><&|/l&>items</&></span>
+ </div>
+ </div>
+ </div>
+ </div>
</&>

<script type="text/javascript">
diff --git a/share/html/Search/Elements/Chart b/share/html/Search/Elements/Chart
index 7079551846..1c260788f8 100644
--- a/share/html/Search/Elements/Chart
+++ b/share/html/Search/Elements/Chart
@@ -65,7 +65,7 @@ my %columns = $report->SetupGroupings(
Function => \@ChartFunction,
);

-$report->SortEntries;
+$report->SortEntries(map { $_ => $ARGS{$_} } grep { $ARGS{$_} } qw(ChartOrderBy ChartOrder ChartLimit));

my $query_string = $m->comp('/Elements/QueryString', %ARGS, GroupBy => \@GroupBy );

diff --git a/share/html/Search/JSChart b/share/html/Search/JSChart
index dc72c4cddf..14e3024a49 100644
--- a/share/html/Search/JSChart
+++ b/share/html/Search/JSChart
@@ -208,7 +208,7 @@ if ( $Cache and my $data = delete $session{'charts_cache'}{ $Cache } ) {
Function => \@ChartFunction,
);

- $report->SortEntries;
+ $report->SortEntries( map { $_ => $ARGS{$_} } grep { $ARGS{$_} } qw(ChartOrderBy ChartOrder ChartLimit) );
}

my @data = ([],[]);

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


hooks/post-receive
--
rt
_______________________________________________
rt-commit mailing list
rt-commit@lists.bestpractical.com
https://lists.bestpractical.com/mailman/listinfo/rt-commit