Commit 12b3b674 authored by lpsolit%gmail.com's avatar lpsolit%gmail.com

Bug 94534: Customised resolutions - Patch by Frédéric Buclin <LpSolit@gmail.com> r=mkanat a=myk

parent 8eadcd8a
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
# Gervase Markham <gerv@gerv.net> # Gervase Markham <gerv@gerv.net>
# Richard Walters <rwalters@qualcomm.com> # Richard Walters <rwalters@qualcomm.com>
# Jean-Sebastien Guay <jean_seb@hybride.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. # Run me out of cron at midnight to collect Bugzilla statistics.
# #
...@@ -41,6 +42,7 @@ use Bugzilla::Util; ...@@ -41,6 +42,7 @@ use Bugzilla::Util;
use Bugzilla::Search; use Bugzilla::Search;
use Bugzilla::User; use Bugzilla::User;
use Bugzilla::Product; use Bugzilla::Product;
use Bugzilla::Field;
# Turn off output buffering (probably needed when displaying output feedback # Turn off output buffering (probably needed when displaying output feedback
# in the regenerate mode.) # in the regenerate mode.)
...@@ -55,7 +57,7 @@ if (chdir("graphs")) { ...@@ -55,7 +57,7 @@ if (chdir("graphs")) {
# Let Throw*Error() work correctly outside a web browser. # Let Throw*Error() work correctly outside a web browser.
Bugzilla->batch(1); Bugzilla->batch(1);
Bugzilla->switch_to_shadow_db(); my $dbh = Bugzilla->switch_to_shadow_db();
# To recreate the daily statistics, run "collectstats.pl --regenerate" . # To recreate the daily statistics, run "collectstats.pl --regenerate" .
my $regenerate = 0; my $regenerate = 0;
...@@ -69,6 +71,39 @@ my $datadir = bz_locations()->{'datadir'}; ...@@ -69,6 +71,39 @@ my $datadir = bz_locations()->{'datadir'};
my @myproducts = map {$_->name} Bugzilla::Product::get_all_products(); my @myproducts = map {$_->name} Bugzilla::Product::get_all_products();
unshift(@myproducts, "-All-"); 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; my $tstart = time;
foreach (@myproducts) { foreach (@myproducts) {
my $dir = "$datadir/mining"; my $dir = "$datadir/mining";
...@@ -143,15 +178,24 @@ sub collect_stats { ...@@ -143,15 +178,24 @@ sub collect_stats {
my $file = join '/', $dir, $file_product; my $file = join '/', $dir, $file_product;
my $exists = -f $file; my $exists = -f $file;
if (open DATA, ">>$file") { # if the file exists, get the old status and resolution list for that product.
push (my @row, &today); my @data;
my $status_sql = q{SELECT COUNT(*) @data = get_old_data($file) if $exists;
FROM bugs
WHERE bug_status = ?};
my $reso_sql = q{SELECT COUNT(*) # If @data is not empty, then we have to recreate the data file.
FROM bugs if (scalar(@data)) {
WHERE resolution = ?}; 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-') { if ($product ne '-All-') {
$status_sql .= q{ AND product_id = ?}; $status_sql .= q{ AND product_id = ?};
...@@ -162,37 +206,80 @@ sub collect_stats { ...@@ -162,37 +206,80 @@ sub collect_stats {
my $sth_reso = $dbh->prepare($reso_sql); my $sth_reso = $dbh->prepare($reso_sql);
my @values ; my @values ;
foreach my $status ('NEW', 'ASSIGNED', 'REOPENED', 'UNCONFIRMED', 'RESOLVED', 'VERIFIED', 'CLOSED') { foreach my $status (@statuses) {
@values = ($status); @values = ($status);
push (@values, $product_id) if ($product ne '-All-'); push (@values, $product_id) if ($product ne '-All-');
my $count = $dbh->selectrow_array($sth_status, undef, @values); my $count = $dbh->selectrow_array($sth_status, undef, @values);
push(@row, $count); push(@row, $count);
} }
foreach my $resolution ('FIXED', 'INVALID', 'WONTFIX', 'LATER', 'REMIND', 'DUPLICATE', 'WORKSFORME', 'MOVED') { foreach my $resolution (@resolutions) {
@values = ($resolution); @values = ($resolution);
push (@values, $product_id) if ($product ne '-All-'); push (@values, $product_id) if ($product ne '-All-');
my $count = $dbh->selectrow_array($sth_reso, undef, @values); my $count = $dbh->selectrow_array($sth_reso, undef, @values);
push(@row, $count); push(@row, $count);
} }
if (! $exists) { if (!$exists || scalar(@data)) {
my $fields = join('|', ('DATE', @statuses, @resolutions));
print DATA <<FIN; print DATA <<FIN;
# Bugzilla Daily Bug Stats # Bugzilla Daily Bug Stats
# #
# Do not edit me! This file is generated. # 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 # Product: $product
# Created: $when # Created: $when
FIN FIN
} }
# 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"; print DATA (join '|', @row) . "\n";
close DATA; close DATA;
chmod 0644, $file; chmod 0644, $file;
} else { }
print "$0: $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 { sub calculate_dupes {
...@@ -317,12 +404,13 @@ sub regenerate_stats { ...@@ -317,12 +404,13 @@ sub regenerate_stats {
if (open DATA, ">$file") { if (open DATA, ">$file") {
DATA->autoflush(1); DATA->autoflush(1);
my $fields = join('|', ('DATE', @statuses, @resolutions));
print DATA <<FIN; print DATA <<FIN;
# Bugzilla Daily Bug Stats # Bugzilla Daily Bug Stats
# #
# Do not edit me! This file is generated. # 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 # Product: $product
# Created: $when # Created: $when
FIN FIN
...@@ -355,17 +443,8 @@ FIN ...@@ -355,17 +443,8 @@ FIN
# the bugs_activity table for that bug made on or after that # the bugs_activity table for that bug made on or after that
# day. # day.
my %bugcount; my %bugcount;
my @logstates = qw(NEW ASSIGNED REOPENED UNCONFIRMED RESOLVED foreach (@statuses) { $bugcount{$_} = 0; }
VERIFIED CLOSED); foreach (@resolutions) { $bugcount{$_} = 0; }
my @logresolutions = qw(FIXED INVALID WONTFIX LATER REMIND
DUPLICATE WORKSFORME MOVED);
foreach (@logstates) {
$bugcount{$_} = 0;
}
foreach (@logresolutions) {
$bugcount{$_} = 0;
}
# Get information on bug states and resolutions. # Get information on bug states and resolutions.
$query = qq{SELECT bugs_activity.removed $query = qq{SELECT bugs_activity.removed
FROM bugs_activity FROM bugs_activity
...@@ -412,14 +491,8 @@ FIN ...@@ -412,14 +491,8 @@ FIN
# of bugs in each state. # of bugs in each state.
my $date = sqlday($day, $base); my $date = sqlday($day, $base);
print DATA "$date"; print DATA "$date";
foreach (@logstates) { foreach (@statuses) { print DATA "|$bugcount{$_}"; }
print DATA "|$bugcount{$_}"; foreach (@resolutions) { print DATA "|$bugcount{$_}"; }
}
foreach (@logresolutions) {
print DATA "|$bugcount{$_}";
}
print DATA "\n"; print DATA "\n";
} }
......
...@@ -31,9 +31,9 @@ use Bugzilla::Config qw(:admin); ...@@ -31,9 +31,9 @@ use Bugzilla::Config qw(:admin);
# (the old "enums.") Keep them in alphabetical order by their # (the old "enums.") Keep them in alphabetical order by their
# English name from field-descs.html.tmpl. # English name from field-descs.html.tmpl.
# Format: Array of valid field names. # Format: Array of valid field names.
# Admins may add resolution and bug_status to this list, but they # Admins may add bug_status to this list, but they do so at their own risk.
# do so at their own risk. our @valid_fields = ('op_sys', 'rep_platform', 'priority', 'bug_severity',
our @valid_fields = ('op_sys', 'rep_platform', 'priority', 'bug_severity',); 'resolution');
###################################################################### ######################################################################
# Subroutines # Subroutines
...@@ -124,6 +124,11 @@ $defaults{'rep_platform'} = 'defaultplatform'; ...@@ -124,6 +124,11 @@ $defaults{'rep_platform'} = 'defaultplatform';
$defaults{'priority'} = 'defaultpriority'; $defaults{'priority'} = 'defaultpriority';
$defaults{'bug_severity'} = 'defaultseverity'; $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 # field = '' -> Show nice list of fields
# #
...@@ -156,9 +161,9 @@ unless ($action) { ...@@ -156,9 +161,9 @@ unless ($action) {
{Slice =>{}}); {Slice =>{}});
$vars->{'field'} = $field; $vars->{'field'} = $field;
$vars->{'values'} = $fieldvalues; $vars->{'values'} = $fieldvalues;
$vars->{'default'} = Bugzilla->params->{$defaults{$field}}; $vars->{'default'} = Bugzilla->params->{$defaults{$field}} if defined $defaults{$field};
$template->process("admin/fieldvalues/list.html.tmpl", $vars->{'static'} = $static{$field} if exists $static{$field};
$vars) $template->process("admin/fieldvalues/list.html.tmpl", $vars)
|| ThrowTemplateError($template->error()); || ThrowTemplateError($template->error());
exit; exit;
...@@ -245,6 +250,12 @@ if ($action eq 'del') { ...@@ -245,6 +250,12 @@ if ($action eq 'del') {
$vars->{'value'} = $value; $vars->{'value'} = $value;
$vars->{'field'} = $field; $vars->{'field'} = $field;
$vars->{'param_name'} = $defaults{$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", $template->process("admin/fieldvalues/confirm-delete.html.tmpl",
$vars) $vars)
|| ThrowTemplateError($template->error()); || ThrowTemplateError($template->error());
...@@ -258,11 +269,21 @@ if ($action eq 'del') { ...@@ -258,11 +269,21 @@ if ($action eq 'del') {
# #
if ($action eq 'delete') { if ($action eq 'delete') {
ValueMustExist($field, $value); ValueMustExist($field, $value);
if ($value eq Bugzilla->params->{$defaults{$field}}) {
ThrowUserError('fieldvalue_is_default', {field => $field, $vars->{'value'} = $value;
value => $value, $vars->{'field'} = $field;
param_name => $defaults{$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($field);
trick_taint($value); trick_taint($value);
...@@ -284,8 +305,6 @@ if ($action eq 'delete') { ...@@ -284,8 +305,6 @@ if ($action eq 'delete') {
$dbh->bz_unlock_tables(); $dbh->bz_unlock_tables();
$vars->{'value'} = $value;
$vars->{'field'} = $field;
$template->process("admin/fieldvalues/deleted.html.tmpl", $template->process("admin/fieldvalues/deleted.html.tmpl",
$vars) $vars)
|| ThrowTemplateError($template->error()); || ThrowTemplateError($template->error());
...@@ -307,9 +326,9 @@ if ($action eq 'edit') { ...@@ -307,9 +326,9 @@ if ($action eq 'edit') {
$vars->{'value'} = $value; $vars->{'value'} = $value;
$vars->{'field'} = $field; $vars->{'field'} = $field;
$vars->{'is_static'} = (lsearch($static{$field}, $value) >= 0) ? 1 : 0;
$template->process("admin/fieldvalues/edit.html.tmpl", $template->process("admin/fieldvalues/edit.html.tmpl", $vars)
$vars)
|| ThrowTemplateError($template->error()); || ThrowTemplateError($template->error());
exit; exit;
...@@ -327,9 +346,17 @@ if ($action eq 'update') { ...@@ -327,9 +346,17 @@ if ($action eq 'update') {
trick_taint($field); trick_taint($field);
trick_taint($valueold); 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) { if (length($value) > 60) {
ThrowUserError('fieldvalue_name_too_long', ThrowUserError('fieldvalue_name_too_long', $vars);
{'value' => $value});
} }
$dbh->bz_lock_tables('bugs WRITE', "$field WRITE"); $dbh->bz_lock_tables('bugs WRITE', "$field WRITE");
...@@ -359,9 +386,7 @@ if ($action eq 'update') { ...@@ -359,9 +386,7 @@ if ($action eq 'update') {
ThrowUserError('fieldvalue_undefined'); ThrowUserError('fieldvalue_undefined');
} }
if (ValueExists($field, $value)) { if (ValueExists($field, $value)) {
ThrowUserError('fieldvalue_already_exists', ThrowUserError('fieldvalue_already_exists', $vars);
{'value' => $value,
'field' => $field});
} }
trick_taint($value); trick_taint($value);
...@@ -380,7 +405,8 @@ if ($action eq 'update') { ...@@ -380,7 +405,8 @@ if ($action eq 'update') {
# update data/params accordingly. # update data/params accordingly.
# This update is done while tables are unlocked due to the # This update is done while tables are unlocked due to the
# annoying calls in Bugzilla/Config/Common.pm. # annoying calls in Bugzilla/Config/Common.pm.
if ($value ne $valueold if (defined $defaults{$field}
&& $value ne $valueold
&& $valueold eq Bugzilla->params->{$defaults{$field}}) && $valueold eq Bugzilla->params->{$defaults{$field}})
{ {
SetParam($defaults{$field}, $value); SetParam($defaults{$field}, $value);
...@@ -388,8 +414,6 @@ if ($action eq 'update') { ...@@ -388,8 +414,6 @@ if ($action eq 'update') {
$vars->{'default_value_updated'} = 1; $vars->{'default_value_updated'} = 1;
} }
$vars->{'value'} = $value;
$vars->{'field'} = $field;
$template->process("admin/fieldvalues/updated.html.tmpl", $template->process("admin/fieldvalues/updated.html.tmpl",
$vars) $vars)
|| ThrowTemplateError($template->error()); || ThrowTemplateError($template->error());
......
...@@ -228,10 +228,10 @@ sub chart_image_name { ...@@ -228,10 +228,10 @@ sub chart_image_name {
# is that we have to check the safety of doing this. We can't just require # 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 # that the fields exist, because what stats were collected could change
# over time (eg by changing the resolutions available) # over time (eg by changing the resolutions available)
# Instead, just require that each field name consists only of letters # Instead, just require that each field name consists only of letters,
# and number # numbers, underscores and hyphens.
if ($datasets !~ m/^[A-Za-z0-9:]+$/) { if ($datasets !~ m/^[A-Za-z0-9:_-]+$/) {
$vars->{'datasets'} = $datasets; $vars->{'datasets'} = $datasets;
ThrowUserError('invalid_datasets', $vars); ThrowUserError('invalid_datasets', $vars);
} }
......
...@@ -176,7 +176,7 @@ sub directive_ok { ...@@ -176,7 +176,7 @@ sub directive_ok {
return 1 if $directive =~ /^(IF|END|UNLESS|FOREACH|PROCESS|INCLUDE| return 1 if $directive =~ /^(IF|END|UNLESS|FOREACH|PROCESS|INCLUDE|
BLOCK|USE|ELSE|NEXT|LAST|DEFAULT|FLUSH| BLOCK|USE|ELSE|NEXT|LAST|DEFAULT|FLUSH|
ELSIF|SET|SWITCH|CASE|WHILE|RETURN|STOP| ELSIF|SET|SWITCH|CASE|WHILE|RETURN|STOP|
TRY|CATCH|FINAL|THROW|CLEAR)/x; TRY|CATCH|FINAL|THROW|CLEAR|MACRO)/x;
# ? : # ? :
if ($directive =~ /.+\?(.+):(.+)/) { if ($directive =~ /.+\?(.+):(.+)/) {
......
...@@ -61,13 +61,13 @@ ...@@ -61,13 +61,13 @@
<h2>Confirmation</h2> <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 <p>Sorry, but the '[% value FILTER html %]' value cannot be deleted
from the '[% field FILTER html %]' field for the following reason(s):</p> from the '[% field FILTER html %]' field for the following reason(s):</p>
<ul class="warningmessages"> <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 <li>'[% value FILTER html %]' is the default value for
the '[% field FILTER html %]' field. the '[% field FILTER html %]' field.
[% IF user.groups.tweakparams %] [% IF user.groups.tweakparams %]
......
...@@ -33,8 +33,15 @@ ...@@ -33,8 +33,15 @@
<tr> <tr>
<th valign="top"><label for="value">Field Value:</label></th> <th valign="top"><label for="value">Field Value:</label></th>
<td><input id="value" size="20" maxlength="60" name="value" value=" <td>
[%- value FILTER html %]"></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>
<tr> <tr>
<th align="right"><label for="sortkey">Sortkey:</label></th> <th align="right"><label for="sortkey">Sortkey:</label></th>
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
# displayed to the user in a list. # displayed to the user in a list.
# #
# field: string; the name of the field we are editing values for. # 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 %] [% USE Bugzilla %]
...@@ -58,7 +59,8 @@ ...@@ -58,7 +59,8 @@
} ] } ]
%] %]
[% overrides.action = [ { [% IF default.defined %]
[% overrides.action = [ {
match_value => "$default" match_value => "$default"
match_field => 'name' match_field => 'name'
override_content => 1 override_content => 1
...@@ -66,7 +68,26 @@ ...@@ -66,7 +68,26 @@
override_contentlink => 1 override_contentlink => 1
contentlink => undef 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 [% PROCESS admin/table.html.tmpl
columns = columns columns = columns
......
...@@ -85,7 +85,7 @@ ...@@ -85,7 +85,7 @@
[% ELSIF change.fieldname == 'bug_status' %] [% ELSIF change.fieldname == 'bug_status' %]
[% status_descs.${change.removed} FILTER html %] [% status_descs.${change.removed} FILTER html %]
[% ELSIF change.fieldname == 'resolution' %] [% ELSIF change.fieldname == 'resolution' %]
[% resolution_descs.${change.removed} FILTER html %] [% get_resolution(change.removed) FILTER html %]
[% ELSIF change.fieldname == 'blocked' || [% ELSIF change.fieldname == 'blocked' ||
change.fieldname == 'dependson' %] change.fieldname == 'dependson' %]
[% change.removed FILTER bug_list_link FILTER none %] [% change.removed FILTER bug_list_link FILTER none %]
...@@ -105,7 +105,7 @@ ...@@ -105,7 +105,7 @@
[% ELSIF change.fieldname == 'bug_status' %] [% ELSIF change.fieldname == 'bug_status' %]
[% status_descs.${change.added} FILTER html %] [% status_descs.${change.added} FILTER html %]
[% ELSIF change.fieldname == 'resolution' %] [% ELSIF change.fieldname == 'resolution' %]
[% resolution_descs.${change.added} FILTER html %] [% get_resolution(change.added) FILTER html %]
[% ELSIF change.fieldname == 'blocked' || [% ELSIF change.fieldname == 'blocked' ||
change.fieldname == 'dependson' %] change.fieldname == 'dependson' %]
[% change.added FILTER bug_list_link FILTER none %] [% change.added FILTER bug_list_link FILTER none %]
......
...@@ -198,7 +198,7 @@ ...@@ -198,7 +198,7 @@
</b> </b>
</td> </td>
<td> <td>
[% resolution_descs.${bug.resolution} FILTER html %] [% get_resolution(bug.resolution) FILTER html %]
[% IF bug.resolution == "DUPLICATE" %] [% IF bug.resolution == "DUPLICATE" %]
of [% terms.bug %] [%+ "${bug.dup_id}" FILTER bug_link(bug.dup_id) %] of [% terms.bug %] [%+ "${bug.dup_id}" FILTER bug_link(bug.dup_id) %]
[% END %] [% END %]
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
<input type="radio" id="knob-leave" name="knob" value="none" checked="checked"> <input type="radio" id="knob-leave" name="knob" value="none" checked="checked">
<label for="knob-leave"> <label for="knob-leave">
Leave as <b>[% status_descs.${bug.bug_status} FILTER html %]&nbsp; Leave as <b>[% status_descs.${bug.bug_status} FILTER html %]&nbsp;
[% resolution_descs.${bug.resolution} FILTER html %]</b> [% get_resolution(bug.resolution) FILTER html %]</b>
</label> </label>
<br> <br>
...@@ -185,7 +185,7 @@ ...@@ -185,7 +185,7 @@
<select name="resolution" <select name="resolution"
onchange="document.changeform.knob[[% knum %]].checked=true"> onchange="document.changeform.knob[[% knum %]].checked=true">
[% FOREACH r = bug.choices.resolution %] [% 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 %] [% END %]
</select> </select>
<br> <br>
......
...@@ -117,7 +117,7 @@ ...@@ -117,7 +117,7 @@
<th>[% field_descs.bug_status FILTER html %]:</th> <th>[% field_descs.bug_status FILTER html %]:</th>
<td> <td>
[% status_descs.${bug.bug_status} FILTER html %] [% status_descs.${bug.bug_status} FILTER html %]
[%+ resolution_descs.${bug.resolution} FILTER html %] [%+ get_resolution(bug.resolution) FILTER html %]
</td> </td>
[% PROCESS rightcell %] [% PROCESS rightcell %]
......
...@@ -37,7 +37,7 @@ You need to take a look at them, and decide on an initial action. ...@@ -37,7 +37,7 @@ You need to take a look at them, and decide on an initial action.
Generally, this means one of three things: 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. and so you get rid of it immediately.
(2) You decide the [% terms.bug %] doesn't belong to you, and you reassign it to (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 someone else. (Hint: if you don't know who to reassign it to, make
......
...@@ -88,4 +88,6 @@ ...@@ -88,4 +88,6 @@
"---" => "---", "---" => "---",
" " => " " } %] " " => " " } %]
[% MACRO get_resolution(res) GET resolution_descs.$res || res %]
[% Hook.process("end") %] [% Hook.process("end") %]
...@@ -396,6 +396,16 @@ ...@@ -396,6 +396,16 @@
The value of a field is limited to 60 characters. The value of a field is limited to 60 characters.
'[% value FILTER html %]' is too long ([% value.length %] 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" %] [% ELSIF error == "fieldvalue_not_specified" %]
[% title = "Field Value Not Specified" %] [% title = "Field Value Not Specified" %]
No field value specified when trying to edit a field value. No field value specified when trying to edit a field value.
......
...@@ -300,8 +300,8 @@ ...@@ -300,8 +300,8 @@
<select name="resolution" onchange="document.forms.changeform.knob[[% knum %]].checked=true"> <select name="resolution" onchange="document.forms.changeform.knob[[% knum %]].checked=true">
[% FOREACH resolution = resolutions %] [% FOREACH resolution = resolutions %]
[% NEXT IF !resolution %] [% NEXT IF !resolution %]
<option value="[% resolution FILTER html %]" [% 'selected="selected"' IF resolution == "FIXED" %]> <option value="[% resolution FILTER html %]">
[% resolution_descs.$resolution FILTER html %] [% get_resolution(resolution) FILTER html %]
</option> </option>
[% END %] [% END %]
</select><br> </select><br>
......
...@@ -193,7 +193,7 @@ ...@@ -193,7 +193,7 @@
[% ELSIF column == 'bug_status' %] [% ELSIF column == 'bug_status' %]
[%- status_descs.${bug.$column}.truncate(abbrev.$column.maxlength, abbrev.$column.ellipsis) FILTER html %] [%- status_descs.${bug.$column}.truncate(abbrev.$column.maxlength, abbrev.$column.ellipsis) FILTER html %]
[% ELSIF column == 'resolution' %] [% 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 %] [% ELSE %]
[%- bug.$column.truncate(abbrev.$column.maxlength, abbrev.$column.ellipsis) FILTER html -%] [%- bug.$column.truncate(abbrev.$column.maxlength, abbrev.$column.ellipsis) FILTER html -%]
[% END %] [% END %]
......
...@@ -148,7 +148,7 @@ cycle of [% terms.abug %]. ...@@ -148,7 +148,7 @@ cycle of [% terms.abug %].
<td> <td>
<dl> <dl>
<dt> <dt>
<b>[% resolution_descs.FIXED FILTER html %]</b> <b>[% get_resolution("FIXED") FILTER html %]</b>
</dt> </dt>
<dd> <dd>
A fix for this [% terms.bug %] is checked into the tree and A fix for this [% terms.bug %] is checked into the tree and
...@@ -156,14 +156,14 @@ cycle of [% terms.abug %]. ...@@ -156,14 +156,14 @@ cycle of [% terms.abug %].
</dd> </dd>
<dt> <dt>
<b>[% resolution_descs.INVALID FILTER html %]</b> <b>[% get_resolution("INVALID") FILTER html %]</b>
</dt> </dt>
<dd> <dd>
The problem described is not [% terms.abug %]. The problem described is not [% terms.abug %].
</dd> </dd>
<dt> <dt>
<b>[% resolution_descs.WONTFIX FILTER html %]</b> <b>[% get_resolution("WONTFIX") FILTER html %]</b>
</dt> </dt>
<dd> <dd>
The problem described is [% terms.abug %] which will never be The problem described is [% terms.abug %] which will never be
...@@ -171,7 +171,7 @@ cycle of [% terms.abug %]. ...@@ -171,7 +171,7 @@ cycle of [% terms.abug %].
</dd> </dd>
<dt> <dt>
<b>[% resolution_descs.DUPLICATE FILTER html %]</b> <b>[% get_resolution("DUPLICATE") FILTER html %]</b>
</dt> </dt>
<dd> <dd>
The problem is a duplicate of an existing [% terms.bug %]. The problem is a duplicate of an existing [% terms.bug %].
...@@ -181,7 +181,7 @@ cycle of [% terms.abug %]. ...@@ -181,7 +181,7 @@ cycle of [% terms.abug %].
</dd> </dd>
<dt> <dt>
<b>[% resolution_descs.WORKSFORME FILTER html %]</b> <b>[% get_resolution("WORKSFORME") FILTER html %]</b>
</dt> </dt>
<dd> <dd>
All attempts at reproducing this [% terms.bug %] were futile, All attempts at reproducing this [% terms.bug %] were futile,
...@@ -191,7 +191,7 @@ cycle of [% terms.abug %]. ...@@ -191,7 +191,7 @@ cycle of [% terms.abug %].
</dd> </dd>
<dt> <dt>
<b>[% resolution_descs.MOVED FILTER html %]</b> <b>[% get_resolution("MOVED") FILTER html %]</b>
</dt> </dt>
<dd> <dd>
The problem was specific to a related product The problem was specific to a related product
......
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
[% IF col_field == 'resolution' %] [% IF col_field == 'resolution' %]
[% FOR i IN [ 0 .. data.0.0.max ] %] [% 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 %]
[% END %] [% END %]
...@@ -47,7 +47,7 @@ ...@@ -47,7 +47,7 @@
[% IF row_field == 'resolution' %] [% IF row_field == 'resolution' %]
[% FOR i IN [ 0 .. row_names.max ] %] [% 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 %]
[% END %] [% END %]
......
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
[% IF col_field == 'resolution' %] [% IF col_field == 'resolution' %]
[% FOR i IN [ 0 .. data.0.0.max ] %] [% 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 %]
[% END %] [% END %]
...@@ -47,7 +47,7 @@ ...@@ -47,7 +47,7 @@
[% IF row_field == 'resolution' %] [% IF row_field == 'resolution' %]
[% FOR i IN [ 0 .. row_names.max ] %] [% 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 %]
[% END %] [% END %]
......
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
[% IF col_field == 'resolution' %] [% IF col_field == 'resolution' %]
[% FOR i IN [ 0 .. data.0.0.max ] %] [% 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 %]
[% END %] [% END %]
......
...@@ -44,7 +44,7 @@ ...@@ -44,7 +44,7 @@
[% IF col_field == 'bug_status' %] [% IF col_field == 'bug_status' %]
[% status_descs.$col FILTER csv -%] [% status_descs.$col FILTER csv -%]
[% ELSIF col_field == 'resolution' %] [% ELSIF col_field == 'resolution' %]
[% resolution_descs.$col FILTER csv -%] [% get_resolution(col) FILTER csv -%]
[% ELSE %] [% ELSE %]
[% col FILTER csv -%] [% col FILTER csv -%]
[% END %] [% END %]
...@@ -57,7 +57,7 @@ ...@@ -57,7 +57,7 @@
[% IF row_field == 'bug_status' %] [% IF row_field == 'bug_status' %]
[% status_descs.$row FILTER csv -%] [% status_descs.$row FILTER csv -%]
[% ELSIF row_field == 'resolution' %] [% ELSIF row_field == 'resolution' %]
[% resolution_descs.$row FILTER csv -%] [% get_resolution(row) FILTER csv -%]
[% ELSE %] [% ELSE %]
[% row FILTER csv -%] [% row FILTER csv -%]
[% END %] [% END %]
......
...@@ -88,7 +88,7 @@ ...@@ -88,7 +88,7 @@
[% IF col_field == 'bug_status' %] [% IF col_field == 'bug_status' %]
[% status_descs.$col FILTER html FILTER replace('^ $','&nbsp;') %] [% status_descs.$col FILTER html FILTER replace('^ $','&nbsp;') %]
[% ELSIF col_field == 'resolution' %] [% ELSIF col_field == 'resolution' %]
[% resolution_descs.$col FILTER html FILTER replace('^ $','&nbsp;') %] [% get_resolution(col) FILTER html FILTER replace('^ $','&nbsp;') %]
[% ELSE %] [% ELSE %]
[% col FILTER html FILTER replace('^ $','&nbsp;') %] [% col FILTER html FILTER replace('^ $','&nbsp;') %]
[% END %] [% END %]
...@@ -109,7 +109,7 @@ ...@@ -109,7 +109,7 @@
[% IF row_field == 'bug_status' %] [% IF row_field == 'bug_status' %]
[% status_descs.$row FILTER html FILTER replace('^ $','&nbsp;') %] [% status_descs.$row FILTER html FILTER replace('^ $','&nbsp;') %]
[% ELSIF row_field == 'resolution' %] [% ELSIF row_field == 'resolution' %]
[% resolution_descs.$row FILTER html FILTER replace('^ $','&nbsp;') %] [% get_resolution(row) FILTER html FILTER replace('^ $','&nbsp;') %]
[% ELSE %] [% ELSE %]
[% row FILTER html FILTER replace('^ $','&nbsp;') %] [% row FILTER html FILTER replace('^ $','&nbsp;') %]
[% END %] [% END %]
......
...@@ -628,12 +628,13 @@ function doOnSelectProduct(selectmode) { ...@@ -628,12 +628,13 @@ function doOnSelectProduct(selectmode) {
<option value="[% name FILTER html %]" <option value="[% name FILTER html %]"
[% " selected" IF lsearch(default.${sel.name}, name) != -1 %]> [% " selected" IF lsearch(default.${sel.name}, name) != -1 %]>
[% IF sel.name == "bug_status" %] [% IF sel.name == "bug_status" %]
[% status_descs.${name} FILTER html %]</option> [% status_descs.${name} FILTER html %]
[% ELSIF sel.name == "resolution" %] [% ELSIF sel.name == "resolution" %]
[% resolution_descs.${name} FILTER html %]</option> [% get_resolution(name) FILTER html %]
[% ELSE %] [% ELSE %]
[% name FILTER html %]</option> [% name FILTER html %]
[% END %] [% END %]
</option>
[% END %] [% END %]
</select> </select>
</td> </td>
......
...@@ -84,7 +84,7 @@ ...@@ -84,7 +84,7 @@
<td align="left">[% bug.rep_platform FILTER html %]</td> <td align="left">[% bug.rep_platform FILTER html %]</td>
<td align="left">[% bug.$assignee_login_string 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">[% 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> <td align="left">[% bug.short_desc FILTER html %]</td>
</tr> </tr>
[% END %] [% END %]
......
...@@ -59,7 +59,7 @@ ...@@ -59,7 +59,7 @@
Platform: [%+ bug.rep_platform %] Platform: [%+ bug.rep_platform %]
Assignee: [%+ bug.$assignee_login_string %] Assignee: [%+ bug.$assignee_login_string %]
Status: [%+ status_descs.${bug.bug_status} %] Status: [%+ status_descs.${bug.bug_status} %]
[%- IF bug.resolution -%] Resolution: [% resolution_descs.${bug.resolution} -%] [%- IF bug.resolution -%] Resolution: [% get_resolution(bug.resolution) -%]
[%- END %] [%- END %]
Summary: [% bug.short_desc %] Summary: [% bug.short_desc %]
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment