# Gervase Markham <gerv@gerv.net>
# Richard Walters <rwalters@qualcomm.com>
# Jean-Sebastien Guay <jean_seb@hybride.com>
+# Frédéric Buclin <LpSolit@gmail.com>
# Run me out of cron at midnight to collect Bugzilla statistics.
#
use Bugzilla::Search;
use Bugzilla::User;
use Bugzilla::Product;
+use Bugzilla::Field;
# Turn off output buffering (probably needed when displaying output feedback
# in the regenerate mode.)
# Let Throw*Error() work correctly outside a web browser.
Bugzilla->batch(1);
-Bugzilla->switch_to_shadow_db();
+my $dbh = Bugzilla->switch_to_shadow_db();
# To recreate the daily statistics, run "collectstats.pl --regenerate" .
my $regenerate = 0;
my @myproducts = map {$_->name} Bugzilla::Product::get_all_products();
unshift(@myproducts, "-All-");
+# As we can now customize the list of resolutions, looking at the actual list
+# of available resolutions only is not enough as some now removed resolutions
+# may have existed in the past, or have been renamed. We want them all.
+my @resolutions = @{get_legal_field_values('resolution')};
+my $old_resolutions =
+ $dbh->selectcol_arrayref('SELECT bugs_activity.added
+ FROM bugs_activity
+ INNER JOIN fielddefs
+ ON fielddefs.fieldid = bugs_activity.fieldid
+ LEFT JOIN resolution
+ ON resolution.value = bugs_activity.added
+ WHERE fielddefs.name = ?
+ AND resolution.id IS NULL
+
+ UNION
+
+ SELECT bugs_activity.removed
+ FROM bugs_activity
+ INNER JOIN fielddefs
+ ON fielddefs.fieldid = bugs_activity.fieldid
+ LEFT JOIN resolution
+ ON resolution.value = bugs_activity.removed
+ WHERE fielddefs.name = ?
+ AND resolution.id IS NULL',
+ undef, ('resolution', 'resolution'));
+
+push(@resolutions, @$old_resolutions);
+# Exclude "" from the resolution list.
+@resolutions = grep {$_} @resolutions;
+
+# Actually, the list of statuses is predefined. This will change in the near future.
+my @statuses = qw(NEW ASSIGNED REOPENED UNCONFIRMED RESOLVED VERIFIED CLOSED);
+
my $tstart = time;
foreach (@myproducts) {
my $dir = "$datadir/mining";
my $file = join '/', $dir, $file_product;
my $exists = -f $file;
- if (open DATA, ">>$file") {
- push (my @row, &today);
- my $status_sql = q{SELECT COUNT(*)
- FROM bugs
- WHERE bug_status = ?};
-
- my $reso_sql = q{SELECT COUNT(*)
- FROM bugs
- WHERE resolution = ?};
-
- if ($product ne '-All-') {
- $status_sql .= q{ AND product_id = ?};
- $reso_sql .= q{ AND product_id = ?};
- }
-
- my $sth_status = $dbh->prepare($status_sql);
- my $sth_reso = $dbh->prepare($reso_sql);
-
- my @values ;
- foreach my $status ('NEW', 'ASSIGNED', 'REOPENED', 'UNCONFIRMED', 'RESOLVED', 'VERIFIED', 'CLOSED') {
- @values = ($status);
- push (@values, $product_id) if ($product ne '-All-');
- my $count = $dbh->selectrow_array($sth_status, undef, @values);
- push(@row, $count);
- }
- foreach my $resolution ('FIXED', 'INVALID', 'WONTFIX', 'LATER', 'REMIND', 'DUPLICATE', 'WORKSFORME', 'MOVED') {
- @values = ($resolution);
- push (@values, $product_id) if ($product ne '-All-');
- my $count = $dbh->selectrow_array($sth_reso, undef, @values);
- push(@row, $count);
- }
+ # if the file exists, get the old status and resolution list for that product.
+ my @data;
+ @data = get_old_data($file) if $exists;
+
+ # If @data is not empty, then we have to recreate the data file.
+ if (scalar(@data)) {
+ open(DATA, '>', $file)
+ || ThrowCodeError('chart_file_open_fail', {'filename' => $file});
+ }
+ else {
+ open(DATA, '>>', $file)
+ || ThrowCodeError('chart_file_open_fail', {'filename' => $file});
+ }
+
+ # Now collect current data.
+ my @row = (today());
+ my $status_sql = q{SELECT COUNT(*) FROM bugs WHERE bug_status = ?};
+ my $reso_sql = q{SELECT COUNT(*) FROM bugs WHERE resolution = ?};
+
+ if ($product ne '-All-') {
+ $status_sql .= q{ AND product_id = ?};
+ $reso_sql .= q{ AND product_id = ?};
+ }
+
+ my $sth_status = $dbh->prepare($status_sql);
+ my $sth_reso = $dbh->prepare($reso_sql);
+
+ my @values ;
+ foreach my $status (@statuses) {
+ @values = ($status);
+ push (@values, $product_id) if ($product ne '-All-');
+ my $count = $dbh->selectrow_array($sth_status, undef, @values);
+ push(@row, $count);
+ }
+ foreach my $resolution (@resolutions) {
+ @values = ($resolution);
+ push (@values, $product_id) if ($product ne '-All-');
+ my $count = $dbh->selectrow_array($sth_reso, undef, @values);
+ push(@row, $count);
+ }
- if (! $exists) {
- print DATA <<FIN;
+ if (!$exists || scalar(@data)) {
+ my $fields = join('|', ('DATE', @statuses, @resolutions));
+ print DATA <<FIN;
# Bugzilla Daily Bug Stats
#
# Do not edit me! This file is generated.
#
-# fields: DATE|NEW|ASSIGNED|REOPENED|UNCONFIRMED|RESOLVED|VERIFIED|CLOSED|FIXED|INVALID|WONTFIX|LATER|REMIND|DUPLICATE|WORKSFORME|MOVED
+# fields: $fields
# Product: $product
# Created: $when
FIN
- }
+ }
- print DATA (join '|', @row) . "\n";
- close DATA;
- chmod 0644, $file;
- } else {
- print "$0: $file, $!";
+ # Add existing data, if needed. Note that no count is not treated
+ # the same way as a count with 0 bug.
+ foreach my $data (@data) {
+ print DATA join('|', map {defined $data->{$_} ? $data->{$_} : ''}
+ ('DATE', @statuses, @resolutions)) . "\n";
+ }
+ print DATA (join '|', @row) . "\n";
+ close DATA;
+ chmod 0644, $file;
+}
+
+sub get_old_data {
+ my $file = shift;
+
+ open(DATA, '<', $file)
+ || ThrowCodeError('chart_file_open_fail', {'filename' => $file});
+
+ my @data;
+ my @columns;
+ my $recreate = 0;
+ while (<DATA>) {
+ chomp;
+ next unless $_;
+ if (/^# fields?:\s*(.+)\s*$/) {
+ @columns = split(/\|/, $1);
+ # Compare this list with @statuses and @resolutions.
+ # If they are identical, then we can safely append new data
+ # to the end of the file; else we have to recreate it.
+ $recreate = 1;
+ my @new_cols = ($columns[0], @statuses, @resolutions);
+ if (scalar(@columns) == scalar(@new_cols)) {
+ my ($removed, $added) = diff_arrays(\@columns, \@new_cols);
+ last if (!scalar(@$removed) && !scalar(@$added));
+ }
+ }
+ next unless $recreate;
+ next if (/^#/); # Ignore comments.
+ # If we have to recreate the file, we have to load all existing
+ # data first.
+ my @line = split /\|/;
+ my %data;
+ foreach my $column (@columns) {
+ $data{$column} = shift @line;
+ }
+ push(@data, \%data);
}
+ close(DATA);
+ return @data;
}
sub calculate_dupes {
if (open DATA, ">$file") {
DATA->autoflush(1);
+ my $fields = join('|', ('DATE', @statuses, @resolutions));
print DATA <<FIN;
# Bugzilla Daily Bug Stats
#
# Do not edit me! This file is generated.
#
-# fields: DATE|NEW|ASSIGNED|REOPENED|UNCONFIRMED|RESOLVED|VERIFIED|CLOSED|FIXED|INVALID|WONTFIX|LATER|REMIND|DUPLICATE|WORKSFORME|MOVED
+# fields: $fields
# Product: $product
# Created: $when
FIN
# the bugs_activity table for that bug made on or after that
# day.
my %bugcount;
- my @logstates = qw(NEW ASSIGNED REOPENED UNCONFIRMED RESOLVED
- VERIFIED CLOSED);
- my @logresolutions = qw(FIXED INVALID WONTFIX LATER REMIND
- DUPLICATE WORKSFORME MOVED);
- foreach (@logstates) {
- $bugcount{$_} = 0;
- }
-
- foreach (@logresolutions) {
- $bugcount{$_} = 0;
- }
+ foreach (@statuses) { $bugcount{$_} = 0; }
+ foreach (@resolutions) { $bugcount{$_} = 0; }
# Get information on bug states and resolutions.
$query = qq{SELECT bugs_activity.removed
FROM bugs_activity
# of bugs in each state.
my $date = sqlday($day, $base);
print DATA "$date";
- foreach (@logstates) {
- print DATA "|$bugcount{$_}";
- }
-
- foreach (@logresolutions) {
- print DATA "|$bugcount{$_}";
- }
-
+ foreach (@statuses) { print DATA "|$bugcount{$_}"; }
+ foreach (@resolutions) { print DATA "|$bugcount{$_}"; }
print DATA "\n";
}
# (the old "enums.") Keep them in alphabetical order by their
# English name from field-descs.html.tmpl.
# Format: Array of valid field names.
-# Admins may add resolution and bug_status to this list, but they
-# do so at their own risk.
-our @valid_fields = ('op_sys', 'rep_platform', 'priority', 'bug_severity',);
+# Admins may add bug_status to this list, but they do so at their own risk.
+our @valid_fields = ('op_sys', 'rep_platform', 'priority', 'bug_severity',
+ 'resolution');
######################################################################
# Subroutines
$defaults{'priority'} = 'defaultpriority';
$defaults{'bug_severity'} = 'defaultseverity';
+# Alternatively, a list of non-editable values can be specified.
+# In this case, only the sortkey can be altered.
+my %static;
+$static{'resolution'} = ['', 'FIXED', 'MOVED', 'DUPLICATE'];
+
#
# field = '' -> Show nice list of fields
#
{Slice =>{}});
$vars->{'field'} = $field;
$vars->{'values'} = $fieldvalues;
- $vars->{'default'} = Bugzilla->params->{$defaults{$field}};
- $template->process("admin/fieldvalues/list.html.tmpl",
- $vars)
+ $vars->{'default'} = Bugzilla->params->{$defaults{$field}} if defined $defaults{$field};
+ $vars->{'static'} = $static{$field} if exists $static{$field};
+ $template->process("admin/fieldvalues/list.html.tmpl", $vars)
|| ThrowTemplateError($template->error());
exit;
$vars->{'value'} = $value;
$vars->{'field'} = $field;
$vars->{'param_name'} = $defaults{$field};
+
+ # If the value cannot be deleted, throw an error.
+ if (lsearch($static{$field}, $value) >= 0) {
+ ThrowUserError('fieldvalue_not_deletable', $vars);
+ }
+
$template->process("admin/fieldvalues/confirm-delete.html.tmpl",
$vars)
|| ThrowTemplateError($template->error());
#
if ($action eq 'delete') {
ValueMustExist($field, $value);
- if ($value eq Bugzilla->params->{$defaults{$field}}) {
- ThrowUserError('fieldvalue_is_default', {field => $field,
- value => $value,
- param_name => $defaults{$field}})
+
+ $vars->{'value'} = $value;
+ $vars->{'field'} = $field;
+ $vars->{'param_name'} = $defaults{$field};
+
+ if (defined $defaults{$field}
+ && ($value eq Bugzilla->params->{$defaults{$field}}))
+ {
+ ThrowUserError('fieldvalue_is_default', $vars);
+ }
+ # If the value cannot be deleted, throw an error.
+ if (lsearch($static{$field}, $value) >= 0) {
+ ThrowUserError('fieldvalue_not_deletable', $vars);
}
+
trick_taint($field);
trick_taint($value);
$dbh->bz_unlock_tables();
- $vars->{'value'} = $value;
- $vars->{'field'} = $field;
$template->process("admin/fieldvalues/deleted.html.tmpl",
$vars)
|| ThrowTemplateError($template->error());
$vars->{'value'} = $value;
$vars->{'field'} = $field;
+ $vars->{'is_static'} = (lsearch($static{$field}, $value) >= 0) ? 1 : 0;
- $template->process("admin/fieldvalues/edit.html.tmpl",
- $vars)
+ $template->process("admin/fieldvalues/edit.html.tmpl", $vars)
|| ThrowTemplateError($template->error());
exit;
trick_taint($field);
trick_taint($valueold);
+ $vars->{'value'} = $value;
+ $vars->{'field'} = $field;
+
+ # If the value cannot be renamed, throw an error.
+ if (lsearch($static{$field}, $valueold) >= 0 && $value ne $valueold) {
+ $vars->{'old_value'} = $valueold;
+ ThrowUserError('fieldvalue_not_editable', $vars);
+ }
+
if (length($value) > 60) {
- ThrowUserError('fieldvalue_name_too_long',
- {'value' => $value});
+ ThrowUserError('fieldvalue_name_too_long', $vars);
}
$dbh->bz_lock_tables('bugs WRITE', "$field WRITE");
ThrowUserError('fieldvalue_undefined');
}
if (ValueExists($field, $value)) {
- ThrowUserError('fieldvalue_already_exists',
- {'value' => $value,
- 'field' => $field});
+ ThrowUserError('fieldvalue_already_exists', $vars);
}
trick_taint($value);
# update data/params accordingly.
# This update is done while tables are unlocked due to the
# annoying calls in Bugzilla/Config/Common.pm.
- if ($value ne $valueold
+ if (defined $defaults{$field}
+ && $value ne $valueold
&& $valueold eq Bugzilla->params->{$defaults{$field}})
{
SetParam($defaults{$field}, $value);
$vars->{'default_value_updated'} = 1;
}
- $vars->{'value'} = $value;
- $vars->{'field'} = $field;
$template->process("admin/fieldvalues/updated.html.tmpl",
$vars)
|| ThrowTemplateError($template->error());
# is that we have to check the safety of doing this. We can't just require
# that the fields exist, because what stats were collected could change
# over time (eg by changing the resolutions available)
- # Instead, just require that each field name consists only of letters
- # and number
+ # Instead, just require that each field name consists only of letters,
+ # numbers, underscores and hyphens.
- if ($datasets !~ m/^[A-Za-z0-9:]+$/) {
+ if ($datasets !~ m/^[A-Za-z0-9:_-]+$/) {
$vars->{'datasets'} = $datasets;
ThrowUserError('invalid_datasets', $vars);
}
return 1 if $directive =~ /^(IF|END|UNLESS|FOREACH|PROCESS|INCLUDE|
BLOCK|USE|ELSE|NEXT|LAST|DEFAULT|FLUSH|
ELSIF|SET|SWITCH|CASE|WHILE|RETURN|STOP|
- TRY|CATCH|FINAL|THROW|CLEAR)/x;
+ TRY|CATCH|FINAL|THROW|CLEAR|MACRO)/x;
# ? :
if ($directive =~ /.+\?(.+):(.+)/) {
<h2>Confirmation</h2>
-[% IF (Param(param_name) == value) || bug_count || (value_count == 1) %]
+[% IF (param_name.defined && Param(param_name) == value) || bug_count || (value_count == 1) %]
<p>Sorry, but the '[% value FILTER html %]' value cannot be deleted
from the '[% field FILTER html %]' field for the following reason(s):</p>
<ul class="warningmessages">
- [% IF Param(param_name) == value %]
+ [% IF param_name.defined && Param(param_name) == value %]
<li>'[% value FILTER html %]' is the default value for
the '[% field FILTER html %]' field.
[% IF user.groups.tweakparams %]
<tr>
<th valign="top"><label for="value">Field Value:</label></th>
- <td><input id="value" size="20" maxlength="60" name="value" value="
- [%- value FILTER html %]"></td>
+ <td>
+ [% IF is_static %]
+ <input type="hidden" name="value" value="[% value FILTER html %]">
+ [% value FILTER html %]
+ [% ELSE %]
+ <input id="value" size="20" maxlength="60" name="value" value="
+ [%- value FILTER html %]">
+ [% END %]
+ </td>
</tr>
<tr>
<th align="right"><label for="sortkey">Sortkey:</label></th>
# displayed to the user in a list.
#
# field: string; the name of the field we are editing values for.
+ # static: array; list of values which cannot be renamed nor deleted.
#%]
[% USE Bugzilla %]
} ]
%]
-[% overrides.action = [ {
- match_value => "$default"
- match_field => 'name'
- override_content => 1
- content => "(Default value)"
- override_contentlink => 1
- contentlink => undef
- } ]
-%]
+[% IF default.defined %]
+ [% overrides.action = [ {
+ match_value => "$default"
+ match_field => 'name'
+ override_content => 1
+ content => "(Default value)"
+ override_contentlink => 1
+ contentlink => undef
+ } ]
+ %]
+[% END %]
+
+[% IF static.size %]
+ [% UNLESS overrides.action.size %]
+ [% overrides.action = [] %]
+ [% END %]
+
+ [% FOREACH static_value = static %]
+ [% overrides.action.push({
+ match_value => "$static_value"
+ match_field => 'name'
+ override_content => 1
+ content => "(Non deletable value)"
+ override_contentlink => 1
+ contentlink => undef
+ })
+ %]
+ [% END %]
+[% END %]
[% PROCESS admin/table.html.tmpl
columns = columns
[% ELSIF change.fieldname == 'bug_status' %]
[% status_descs.${change.removed} FILTER html %]
[% ELSIF change.fieldname == 'resolution' %]
- [% resolution_descs.${change.removed} FILTER html %]
+ [% get_resolution(change.removed) FILTER html %]
[% ELSIF change.fieldname == 'blocked' ||
change.fieldname == 'dependson' %]
[% change.removed FILTER bug_list_link FILTER none %]
[% ELSIF change.fieldname == 'bug_status' %]
[% status_descs.${change.added} FILTER html %]
[% ELSIF change.fieldname == 'resolution' %]
- [% resolution_descs.${change.added} FILTER html %]
+ [% get_resolution(change.added) FILTER html %]
[% ELSIF change.fieldname == 'blocked' ||
change.fieldname == 'dependson' %]
[% change.added FILTER bug_list_link FILTER none %]
</b>
</td>
<td>
- [% resolution_descs.${bug.resolution} FILTER html %]
+ [% get_resolution(bug.resolution) FILTER html %]
[% IF bug.resolution == "DUPLICATE" %]
of [% terms.bug %] [%+ "${bug.dup_id}" FILTER bug_link(bug.dup_id) %]
[% END %]
<input type="radio" id="knob-leave" name="knob" value="none" checked="checked">
<label for="knob-leave">
Leave as <b>[% status_descs.${bug.bug_status} FILTER html %]
- [% resolution_descs.${bug.resolution} FILTER html %]</b>
+ [% get_resolution(bug.resolution) FILTER html %]</b>
</label>
<br>
<select name="resolution"
onchange="document.changeform.knob[[% knum %]].checked=true">
[% FOREACH r = bug.choices.resolution %]
- <option value="[% r FILTER html %]">[% resolution_descs.${r} FILTER html %]</option>
+ <option value="[% r FILTER html %]">[% get_resolution(r) FILTER html %]</option>
[% END %]
</select>
<br>
<th>[% field_descs.bug_status FILTER html %]:</th>
<td>
[% status_descs.${bug.bug_status} FILTER html %]
- [%+ resolution_descs.${bug.resolution} FILTER html %]
+ [%+ get_resolution(bug.resolution) FILTER html %]
</td>
[% PROCESS rightcell %]
Generally, this means one of three things:
-(1) You decide this [% terms.bug %] is really quick to deal with (like, it's [% resolution_descs.INVALID %]),
+(1) You decide this [% terms.bug %] is really quick to deal with (like, it's [% get_resolution("INVALID") %]),
and so you get rid of it immediately.
(2) You decide the [% terms.bug %] doesn't belong to you, and you reassign it to
someone else. (Hint: if you don't know who to reassign it to, make
"---" => "---",
" " => " " } %]
+[% MACRO get_resolution(res) GET resolution_descs.$res || res %]
+
[% Hook.process("end") %]
The value of a field is limited to 60 characters.
'[% value FILTER html %]' is too long ([% value.length %] characters).
+ [% ELSIF error == "fieldvalue_not_editable" %]
+ [% title = "Field Value Not Editable" %]
+ The value '[% old_value FILTER html %]' cannot be renamed because
+ it plays some special role for the '[% field FILTER html %]' field.
+
+ [% ELSIF error == "fieldvalue_not_deletable" %]
+ [% title = "Field Value Not Deletable" %]
+ The value '[% value FILTER html %]' cannot be removed because
+ it plays some special role for the '[% field FILTER html %]' field.
+
[% ELSIF error == "fieldvalue_not_specified" %]
[% title = "Field Value Not Specified" %]
No field value specified when trying to edit a field value.
<select name="resolution" onchange="document.forms.changeform.knob[[% knum %]].checked=true">
[% FOREACH resolution = resolutions %]
[% NEXT IF !resolution %]
- <option value="[% resolution FILTER html %]" [% 'selected="selected"' IF resolution == "FIXED" %]>
- [% resolution_descs.$resolution FILTER html %]
+ <option value="[% resolution FILTER html %]">
+ [% get_resolution(resolution) FILTER html %]
</option>
[% END %]
</select><br>
[% ELSIF column == 'bug_status' %]
[%- status_descs.${bug.$column}.truncate(abbrev.$column.maxlength, abbrev.$column.ellipsis) FILTER html %]
[% ELSIF column == 'resolution' %]
- [%- resolution_descs.${bug.$column}.truncate(abbrev.$column.maxlength, abbrev.$column.ellipsis) FILTER html %]
+ [%- get_resolution(bug.$column).truncate(abbrev.$column.maxlength, abbrev.$column.ellipsis) FILTER html %]
[% ELSE %]
[%- bug.$column.truncate(abbrev.$column.maxlength, abbrev.$column.ellipsis) FILTER html -%]
[% END %]
<td>
<dl>
<dt>
- <b>[% resolution_descs.FIXED FILTER html %]</b>
+ <b>[% get_resolution("FIXED") FILTER html %]</b>
</dt>
<dd>
A fix for this [% terms.bug %] is checked into the tree and
</dd>
<dt>
- <b>[% resolution_descs.INVALID FILTER html %]</b>
+ <b>[% get_resolution("INVALID") FILTER html %]</b>
</dt>
<dd>
The problem described is not [% terms.abug %].
</dd>
<dt>
- <b>[% resolution_descs.WONTFIX FILTER html %]</b>
+ <b>[% get_resolution("WONTFIX") FILTER html %]</b>
</dt>
<dd>
The problem described is [% terms.abug %] which will never be
</dd>
<dt>
- <b>[% resolution_descs.DUPLICATE FILTER html %]</b>
+ <b>[% get_resolution("DUPLICATE") FILTER html %]</b>
</dt>
<dd>
The problem is a duplicate of an existing [% terms.bug %].
</dd>
<dt>
- <b>[% resolution_descs.WORKSFORME FILTER html %]</b>
+ <b>[% get_resolution("WORKSFORME") FILTER html %]</b>
</dt>
<dd>
All attempts at reproducing this [% terms.bug %] were futile,
</dd>
<dt>
- <b>[% resolution_descs.MOVED FILTER html %]</b>
+ <b>[% get_resolution("MOVED") FILTER html %]</b>
</dt>
<dd>
The problem was specific to a related product
[% IF col_field == 'resolution' %]
[% FOR i IN [ 0 .. data.0.0.max ] %]
- [% data.0.0.$i = resolution_descs.${data.0.0.$i} %]
+ [% data.0.0.$i = get_resolution(data.0.0.$i) %]
[% END %]
[% END %]
[% IF row_field == 'resolution' %]
[% FOR i IN [ 0 .. row_names.max ] %]
- [% row_names.$i = resolution_descs.${row_names.$i} %]
+ [% row_names.$i = get_resolution(row_names.$i) %]
[% END %]
[% END %]
[% IF col_field == 'resolution' %]
[% FOR i IN [ 0 .. data.0.0.max ] %]
- [% data.0.0.$i = resolution_descs.${data.0.0.$i} %]
+ [% data.0.0.$i = get_resolution(data.0.0.$i) %]
[% END %]
[% END %]
[% IF row_field == 'resolution' %]
[% FOR i IN [ 0 .. row_names.max ] %]
- [% row_names.$i = resolution_descs.${row_names.$i} %]
+ [% row_names.$i = get_resolution(row_names.$i) %]
[% END %]
[% END %]
[% IF col_field == 'resolution' %]
[% FOR i IN [ 0 .. data.0.0.max ] %]
- [% data.0.0.$i = resolution_descs.${data.0.0.$i} %]
+ [% data.0.0.$i = get_resolution(data.0.0.$i) %]
[% END %]
[% END %]
[% IF col_field == 'bug_status' %]
[% status_descs.$col FILTER csv -%]
[% ELSIF col_field == 'resolution' %]
- [% resolution_descs.$col FILTER csv -%]
+ [% get_resolution(col) FILTER csv -%]
[% ELSE %]
[% col FILTER csv -%]
[% END %]
[% IF row_field == 'bug_status' %]
[% status_descs.$row FILTER csv -%]
[% ELSIF row_field == 'resolution' %]
- [% resolution_descs.$row FILTER csv -%]
+ [% get_resolution(row) FILTER csv -%]
[% ELSE %]
[% row FILTER csv -%]
[% END %]
[% IF col_field == 'bug_status' %]
[% status_descs.$col FILTER html FILTER replace('^ $',' ') %]
[% ELSIF col_field == 'resolution' %]
- [% resolution_descs.$col FILTER html FILTER replace('^ $',' ') %]
+ [% get_resolution(col) FILTER html FILTER replace('^ $',' ') %]
[% ELSE %]
[% col FILTER html FILTER replace('^ $',' ') %]
[% END %]
[% IF row_field == 'bug_status' %]
[% status_descs.$row FILTER html FILTER replace('^ $',' ') %]
[% ELSIF row_field == 'resolution' %]
- [% resolution_descs.$row FILTER html FILTER replace('^ $',' ') %]
+ [% get_resolution(row) FILTER html FILTER replace('^ $',' ') %]
[% ELSE %]
[% row FILTER html FILTER replace('^ $',' ') %]
[% END %]
<option value="[% name FILTER html %]"
[% " selected" IF lsearch(default.${sel.name}, name) != -1 %]>
[% IF sel.name == "bug_status" %]
- [% status_descs.${name} FILTER html %]</option>
+ [% status_descs.${name} FILTER html %]
[% ELSIF sel.name == "resolution" %]
- [% resolution_descs.${name} FILTER html %]</option>
+ [% get_resolution(name) FILTER html %]
[% ELSE %]
- [% name FILTER html %]</option>
+ [% name FILTER html %]
[% END %]
+ </option>
[% END %]
</select>
</td>
<td align="left">[% bug.rep_platform FILTER html %]</td>
<td align="left">[% bug.$assignee_login_string FILTER html %]</td>
<td align="left">[% status_descs.${bug.bug_status} FILTER html %]</td>
- <td align="left">[% resolution_descs.${bug.resolution} FILTER html %]</td>
+ <td align="left">[% get_resolution(bug.resolution) FILTER html %]</td>
<td align="left">[% bug.short_desc FILTER html %]</td>
</tr>
[% END %]
Platform: [%+ bug.rep_platform %]
Assignee: [%+ bug.$assignee_login_string %]
Status: [%+ status_descs.${bug.bug_status} %]
- [%- IF bug.resolution -%] Resolution: [% resolution_descs.${bug.resolution} -%]
+ [%- IF bug.resolution -%] Resolution: [% get_resolution(bug.resolution) -%]
[%- END %]
Summary: [% bug.short_desc %]