summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Bugzilla/Search.pm10
-rwxr-xr-xreport.cgi82
-rw-r--r--skins/standard/reports.css5
-rw-r--r--template/en/default/filterexceptions.pl3
-rw-r--r--template/en/default/reports/report-table.html.tmpl23
5 files changed, 87 insertions, 36 deletions
diff --git a/Bugzilla/Search.pm b/Bugzilla/Search.pm
index 7bd4381ed..e89a9b361 100644
--- a/Bugzilla/Search.pm
+++ b/Bugzilla/Search.pm
@@ -656,12 +656,7 @@ sub REPORT_COLUMNS {
# or simply don't work with the current reporting system.
my @no_report_columns =
qw(bug_id alias short_short_desc opendate changeddate
- flagtypes.name keywords relevance);
-
- # Multi-select fields are not currently supported.
- my @multi_selects = @{Bugzilla->fields(
- { obsolete => 0, type => FIELD_TYPE_MULTI_SELECT })};
- push(@no_report_columns, map { $_->name } @multi_selects);
+ flagtypes.name relevance);
# If you're not a time-tracker, you can't use time-tracking
# columns.
@@ -2863,9 +2858,10 @@ sub _multiselect_table {
sub _multiselect_term {
my ($self, $args, $not) = @_;
my ($operator) = $args->{operator};
+ my $value = $args->{value} || '';
# 'empty' operators require special handling
return $self->_multiselect_isempty($args, $not)
- if $operator =~ /^is(not)?empty$/;
+ if ($operator =~ /^is(not)?empty$/ || $value eq '---');
my $table = $self->_multiselect_table($args);
$self->_do_operator_function($args);
my $term = $args->{term};
diff --git a/report.cgi b/report.cgi
index 3a1130f2d..cefe96d5a 100755
--- a/report.cgi
+++ b/report.cgi
@@ -185,20 +185,64 @@ my $col_isnumeric = 1;
my $row_isnumeric = 1;
my $tbl_isnumeric = 1;
+# define which fields are multiselect
+my @multi_selects = map { $_->name } @{Bugzilla->fields(
+ {
+ obsolete => 0,
+ type => [FIELD_TYPE_MULTI_SELECT, FIELD_TYPE_KEYWORDS]
+ }
+)};
+my $col_ismultiselect = scalar grep {$col_field eq $_} @multi_selects;
+my $row_ismultiselect = scalar grep {$row_field eq $_} @multi_selects;
+my $tbl_ismultiselect = scalar grep {$tbl_field eq $_} @multi_selects;
+
+
foreach my $result (@$results) {
# handle empty dimension member names
- my $row = check_value($row_field, $result);
- my $col = check_value($col_field, $result);
- my $tbl = check_value($tbl_field, $result);
-
- $data{$tbl}{$col}{$row}++;
- $names{"col"}{$col}++;
- $names{"row"}{$row}++;
- $names{"tbl"}{$tbl}++;
- $col_isnumeric &&= ($col =~ /^-?\d+(\.\d+)?$/o);
- $row_isnumeric &&= ($row =~ /^-?\d+(\.\d+)?$/o);
- $tbl_isnumeric &&= ($tbl =~ /^-?\d+(\.\d+)?$/o);
+ my @rows = check_value($row_field, $result, $row_ismultiselect);
+ my @cols = check_value($col_field, $result, $col_ismultiselect);
+ my @tbls = check_value($tbl_field, $result, $tbl_ismultiselect);
+
+ my %in_total_row;
+ my %in_total_col;
+ for my $tbl (@tbls) {
+ my %in_row_total;
+ for my $col (@cols) {
+ for my $row (@rows) {
+ $data{$tbl}{$col}{$row}++;
+ $names{"row"}{$row}++;
+ $row_isnumeric &&= ($row =~ /^-?\d+(\.\d+)?$/o);
+ if ($formatparam eq "table") {
+ if (!$in_row_total{$row}) {
+ $data{$tbl}{'-total-'}{$row}++;
+ $in_row_total{$row} = 1;
+ }
+ if (!$in_total_row{$row}) {
+ $data{'-total-'}{'-total-'}{$row}++;
+ $in_total_row{$row} = 1;
+ }
+ }
+ }
+ if ($formatparam eq "table") {
+ $data{$tbl}{$col}{'-total-'}++;
+ if (!$in_total_col{$col}) {
+ $data{'-total-'}{$col}{'-total-'}++;
+ $in_total_col{$col} = 1;
+ }
+ }
+ $names{"col"}{$col}++;
+ $col_isnumeric &&= ($col =~ /^-?\d+(\.\d+)?$/o);
+ }
+ $names{"tbl"}{$tbl}++;
+ $tbl_isnumeric &&= ($tbl =~ /^-?\d+(\.\d+)?$/o);
+ if ($formatparam eq "table") {
+ $data{$tbl}{'-total-'}{'-total-'}++;
+ }
+ }
+ if ($formatparam eq "table") {
+ $data{'-total-'}{'-total-'}{'-total-'}++;
+ }
}
my @col_names = get_names($names{"col"}, $col_isnumeric, $col_field);
@@ -242,6 +286,7 @@ $vars->{'time'} = localtime(time());
$vars->{'col_names'} = \@col_names;
$vars->{'row_names'} = \@row_names;
$vars->{'tbl_names'} = \@tbl_names;
+$vars->{'note_multi_select'} = $row_ismultiselect || $col_ismultiselect;
# Below a certain width, we don't see any bars, so there needs to be a minimum.
if ($formatparam eq "bar") {
@@ -352,7 +397,8 @@ sub get_names {
foreach my $value (@{$field->legal_values}) {
push(@sorted, $value->name) if $names->{$value->name};
}
- unshift(@sorted, '---') if $field_name eq 'resolution';
+ unshift(@sorted, '---') if ($field_name eq 'resolution'
+ || $field->type == FIELD_TYPE_MULTI_SELECT);
@sorted = uniq @sorted;
}
elsif ($isnumeric) {
@@ -369,7 +415,7 @@ sub get_names {
}
sub check_value {
- my ($field, $result) = @_;
+ my ($field, $result, $ismultiselect) = @_;
my $value;
if (!defined $field) {
@@ -381,9 +427,15 @@ sub check_value {
else {
$value = shift @$result;
$value = ' ' if (!defined $value || $value eq '');
- $value = '---' if ($field eq 'resolution' && $value eq ' ');
+ $value = '---' if (($field eq 'resolution' || $ismultiselect ) &&
+ $value eq ' ');
+ }
+ if ($ismultiselect) {
+ # Some DB servers have a space after the comma, some others don't.
+ return split(/, ?/, $value);
+ } else {
+ return ($value);
}
- return $value;
}
sub get_field_restrictions {
diff --git a/skins/standard/reports.css b/skins/standard/reports.css
index 97ef316ba..8e0ddf1b0 100644
--- a/skins/standard/reports.css
+++ b/skins/standard/reports.css
@@ -102,3 +102,8 @@
max-width: 100%;
height: auto;
}
+
+.extra_info {
+ font-size: smaller;
+ font-style: italic;
+} \ No newline at end of file
diff --git a/template/en/default/filterexceptions.pl b/template/en/default/filterexceptions.pl
index 239b6828c..2270f0919 100644
--- a/template/en/default/filterexceptions.pl
+++ b/template/en/default/filterexceptions.pl
@@ -78,9 +78,6 @@
'classes.$row_idx.$col_idx',
'urlbase',
'data.$tbl.$col.$row',
- 'row_total',
- 'col_totals.$col',
- 'grand_total',
],
'reports/report.html.tmpl' => [
diff --git a/template/en/default/reports/report-table.html.tmpl b/template/en/default/reports/report-table.html.tmpl
index 2747166be..927a38917 100644
--- a/template/en/default/reports/report-table.html.tmpl
+++ b/template/en/default/reports/report-table.html.tmpl
@@ -156,7 +156,7 @@ YAHOO.util.Event.addListener(window, "load", function() {
[% classes = [ [ "t1", "t2" ] , [ "t3", "t4" ] ] %]
[% col_idx = 0 %]
[% row_idx = 0 %]
-[% grand_total = 0 %]
+[% total_key = '-total-' %]
<div id="tabular_report_container_[% tbl FILTER html %]">
<table id="tabular_report" border="1">
[% IF col_field %]
@@ -165,7 +165,6 @@ YAHOO.util.Event.addListener(window, "load", function() {
<th class="[% classes.$row_idx.$col_idx %]">
</th>
[% FOREACH col = col_names %]
- [% col_totals.$col = 0 %]
[% NEXT IF col == "" %]
[% col_idx = 1 - col_idx %]
@@ -181,17 +180,13 @@ YAHOO.util.Event.addListener(window, "load", function() {
[% END %]
<tbody>
[% FOREACH row = row_names %]
- [% row_total = 0 %]
-
[% row_idx = 1 - row_idx %]
<tr>
<td class="[% classes.$row_idx.$col_idx %]" align="right">
[% PROCESS value_display value = row field = row_field %]
</td>
[% FOREACH col = col_names %]
- [% row_total = row_total + data.$tbl.$col.$row %]
[% NEXT IF col == "" %]
- [% col_totals.$col = (col_totals.$col || 0) + data.$tbl.$col.$row %]
[% col_idx = 1 - col_idx %]
<td class="[% classes.$row_idx.$col_idx %]" align="center">
@@ -209,8 +204,7 @@ YAHOO.util.Event.addListener(window, "load", function() {
<a href="[% urlbase %]&amp;
[% row_field FILTER uri %]=[% row FILTER uri %]
[% "&amp;$col_vals" IF col_vals %]">
- [% row_total %]</a>
- [% grand_total = grand_total + row_total %]
+ [% data.$tbl.$total_key.$row OR 0 FILTER html %]</a>
</td>
</tr>
[% END %]
@@ -221,19 +215,19 @@ YAHOO.util.Event.addListener(window, "load", function() {
</td>
[% FOREACH col = col_names %]
[% NEXT IF col == "" %]
-
+
<td class="ttotal" align="center">
<a href="[% urlbase %]&amp;
[% col_field FILTER uri %]=[% col FILTER uri %]
[% "&amp;$row_vals" IF row_vals %]">
- [% col_totals.$col %]</a>
+ [% data.$tbl.$col.$total_key OR 0 FILTER html %]</a>
</td>
[% END %]
<td class="ttotal" align="right">
<strong>
<a href="[% urlbase %]
[% "&amp;$row_vals" IF row_vals %]
- [% "&amp;$col_vals" IF col_vals %]">[% grand_total %]</a>
+ [% "&amp;$col_vals" IF col_vals %]">[% data.$tbl.$total_key.$total_key OR 0 FILTER html %]</a>
</strong>
</td>
</tr>
@@ -245,6 +239,13 @@ YAHOO.util.Event.addListener(window, "load", function() {
</tr>
</table>
+[% IF note_multi_select %]
+ <p class="extra_info">
+ NOTE: Axes contain multi-value fields, so the total numbers might not add up,
+ as a single [% terms.bug %] can match several rows or columns.
+ </p>
+[% END %]
+
[% BLOCK value_display %]
[% SET disp_value = display_value(field, value) %]
[% IF field == 'assigned_to' OR field == 'reporter'