Commit 2bd57ce8 authored by lpsolit%gmail.com's avatar lpsolit%gmail.com

Bug 344965: Fix process_bug.cgi and bug/* templates to work with custom bug…

Bug 344965: Fix process_bug.cgi and bug/* templates to work with custom bug status workflow - Patch by Fré©ric Buclin <LpSolit@gmail.com> r=mkanat a=LpSolit
parent 9e81bb03
...@@ -120,8 +120,6 @@ use File::Basename; ...@@ -120,8 +120,6 @@ use File::Basename;
FIELD_TYPE_FREETEXT FIELD_TYPE_FREETEXT
FIELD_TYPE_SINGLE_SELECT FIELD_TYPE_SINGLE_SELECT
BUG_STATE_OPEN
USAGE_MODE_BROWSER USAGE_MODE_BROWSER
USAGE_MODE_CMDLINE USAGE_MODE_CMDLINE
USAGE_MODE_WEBSERVICE USAGE_MODE_WEBSERVICE
...@@ -351,10 +349,6 @@ use constant SAFE_PROTOCOLS => ('afs', 'cid', 'ftp', 'gopher', 'http', 'https', ...@@ -351,10 +349,6 @@ use constant SAFE_PROTOCOLS => ('afs', 'cid', 'ftp', 'gopher', 'http', 'https',
'irc', 'mid', 'news', 'nntp', 'prospero', 'telnet', 'irc', 'mid', 'news', 'nntp', 'prospero', 'telnet',
'view-source', 'wais'); 'view-source', 'wais');
# States that are considered to be "open" for bugs.
use constant BUG_STATE_OPEN => ('NEW', 'REOPENED', 'ASSIGNED',
'UNCONFIRMED');
# Usage modes. Default USAGE_MODE_BROWSER. Use with Bugzilla->usage_mode. # Usage modes. Default USAGE_MODE_BROWSER. Use with Bugzilla->usage_mode.
use constant USAGE_MODE_BROWSER => 0; use constant USAGE_MODE_BROWSER => 0;
use constant USAGE_MODE_CMDLINE => 1; use constant USAGE_MODE_CMDLINE => 1;
......
...@@ -22,7 +22,7 @@ package Bugzilla::Install::DB; ...@@ -22,7 +22,7 @@ package Bugzilla::Install::DB;
use strict; use strict;
use Bugzilla::Bug qw(is_open_state); use Bugzilla::Bug qw(BUG_STATE_OPEN is_open_state);
use Bugzilla::Constants; use Bugzilla::Constants;
use Bugzilla::Hook; use Bugzilla::Hook;
use Bugzilla::Install::Util qw(indicate_progress); use Bugzilla::Install::Util qw(indicate_progress);
......
# -*- Mode: perl; indent-tabs-mode: nil -*-
#
# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is the Bugzilla Bug Tracking System.
#
# The Initial Developer of the Original Code is Frédéric Buclin.
# Portions created by Frédéric Buclin are Copyright (C) 2007
# Frédéric Buclin. All Rights Reserved.
#
# Contributor(s): Frédéric Buclin <LpSolit@gmail.com>
use strict;
package Bugzilla::Status;
use base qw(Bugzilla::Object);
################################
##### Initialization #####
################################
use constant DB_TABLE => 'bug_status';
use constant DB_COLUMNS => qw(
id
value
sortkey
isactive
is_open
);
use constant NAME_FIELD => 'value';
use constant LIST_ORDER => 'sortkey, value';
###############################
##### Accessors ####
###############################
sub name { return $_[0]->{'value'}; }
sub sortkey { return $_[0]->{'sortkey'}; }
sub is_active { return $_[0]->{'isactive'}; }
sub is_open { return $_[0]->{'is_open'}; }
###############################
##### Methods ####
###############################
sub can_change_to {
my $self = shift;
my $dbh = Bugzilla->dbh;
if (!defined $self->{'can_change_to'}) {
my $new_status_ids = $dbh->selectcol_arrayref('SELECT new_status
FROM status_workflow
INNER JOIN bug_status
ON id = new_status
WHERE isactive = 1
AND old_status = ?',
undef, $self->id);
$self->{'can_change_to'} = Bugzilla::Status->new_from_list($new_status_ids);
}
return $self->{'can_change_to'};
}
1;
__END__
=head1 NAME
Bugzilla::Status - Bug status class.
=head1 SYNOPSIS
use Bugzilla::Status;
my $bug_status = new Bugzilla::Status({name => 'ASSIGNED'});
my $bug_status = new Bugzilla::Status(4);
=head1 DESCRIPTION
Status.pm represents a bug status object. It is an implementation
of L<Bugzilla::Object>, and thus provides all methods that
L<Bugzilla::Object> provides.
The methods that are specific to C<Bugzilla::Status> are listed
below.
=head1 METHODS
=over
=item C<can_change_to>
Description: Returns the list of active statuses a bug can be changed to
given the current bug status.
Params: none.
Returns: A list of Bugzilla::Status objects.
=back
=cut
...@@ -1139,8 +1139,26 @@ if ($dotweak) { ...@@ -1139,8 +1139,26 @@ if ($dotweak) {
$vars->{'unconfirmedstate'} = 'UNCONFIRMED'; $vars->{'unconfirmedstate'} = 'UNCONFIRMED';
$vars->{'bugstatuses'} = [ keys %$bugstatuses ]; # Convert bug statuses to their ID.
my @bug_statuses = map {$dbh->quote($_)} keys %$bugstatuses;
my $bug_status_ids =
$dbh->selectcol_arrayref('SELECT id FROM bug_status
WHERE value IN (' . join(', ', @bug_statuses) .')');
# This query collects new statuses which are common to all current bug statuses.
# It also accepts transitions where the bug status doesn't change.
$bug_status_ids =
$dbh->selectcol_arrayref('SELECT DISTINCT new_status
FROM status_workflow sw1
WHERE NOT EXISTS (SELECT * FROM status_workflow sw2
WHERE sw2.old_status != sw1.new_status
AND sw2.old_status IN (' . join(', ', @$bug_status_ids) . ')
AND NOT EXISTS (SELECT * FROM status_workflow sw3
WHERE sw3.new_status = sw1.new_status
AND sw3.old_status = sw2.old_status))');
$vars->{'current_bug_statuses'} = [keys %$bugstatuses];
$vars->{'new_bug_statuses'} = Bugzilla::Status->new_from_list($bug_status_ids);
# The groups to which the user belongs. # The groups to which the user belongs.
$vars->{'groups'} = GetGroups(); $vars->{'groups'} = GetGroups();
......
...@@ -27,6 +27,7 @@ use Bugzilla; ...@@ -27,6 +27,7 @@ use Bugzilla;
use Bugzilla::Constants; use Bugzilla::Constants;
use Bugzilla::Error; use Bugzilla::Error;
use Bugzilla::Token; use Bugzilla::Token;
use Bugzilla::Status;
my $cgi = Bugzilla->cgi; my $cgi = Bugzilla->cgi;
my $dbh = Bugzilla->dbh; my $dbh = Bugzilla->dbh;
...@@ -42,12 +43,6 @@ $user->in_group('admin') ...@@ -42,12 +43,6 @@ $user->in_group('admin')
my $action = $cgi->param('action') || 'edit'; my $action = $cgi->param('action') || 'edit';
my $token = $cgi->param('token'); my $token = $cgi->param('token');
sub get_statuses {
my $statuses = $dbh->selectall_arrayref('SELECT id, value, is_open FROM bug_status
ORDER BY sortkey, value', { Slice => {} });
return $statuses;
}
sub get_workflow { sub get_workflow {
my $workflow = $dbh->selectall_arrayref('SELECT old_status, new_status, require_comment my $workflow = $dbh->selectall_arrayref('SELECT old_status, new_status, require_comment
FROM status_workflow'); FROM status_workflow');
...@@ -64,7 +59,7 @@ sub load_template { ...@@ -64,7 +59,7 @@ sub load_template {
my $template = Bugzilla->template; my $template = Bugzilla->template;
my $vars = {}; my $vars = {};
$vars->{'statuses'} = get_statuses(); $vars->{'statuses'} = [Bugzilla::Status->get_all];
$vars->{'workflow'} = get_workflow(); $vars->{'workflow'} = get_workflow();
$vars->{'token'} = issue_session_token("workflow_$filename"); $vars->{'token'} = issue_session_token("workflow_$filename");
$vars->{'message'} = $message; $vars->{'message'} = $message;
...@@ -79,9 +74,8 @@ if ($action eq 'edit') { ...@@ -79,9 +74,8 @@ if ($action eq 'edit') {
} }
elsif ($action eq 'update') { elsif ($action eq 'update') {
check_token_data($token, 'workflow_edit'); check_token_data($token, 'workflow_edit');
my $statuses = get_statuses; my $statuses = [Bugzilla::Status->get_all];
my $workflow = get_workflow(); my $workflow = get_workflow();
my $initial_state = {id => 0};
my $sth_insert = $dbh->prepare('INSERT INTO status_workflow (old_status, new_status) my $sth_insert = $dbh->prepare('INSERT INTO status_workflow (old_status, new_status)
VALUES (?, ?)'); VALUES (?, ?)');
...@@ -90,22 +84,28 @@ elsif ($action eq 'update') { ...@@ -90,22 +84,28 @@ elsif ($action eq 'update') {
my $sth_delnul = $dbh->prepare('DELETE FROM status_workflow my $sth_delnul = $dbh->prepare('DELETE FROM status_workflow
WHERE old_status IS NULL AND new_status = ?'); WHERE old_status IS NULL AND new_status = ?');
foreach my $old ($initial_state, @$statuses) { # Part 1: Initial bug statuses.
# Hashes cannot have undef as a key, so we use 0. But the DB foreach my $new (@$statuses) {
# must store undef, for referential integrity. if ($cgi->param('w_0_' . $new->id)) {
my $old_id_for_db = $old->{'id'} || undef; $sth_insert->execute(undef, $new->id)
unless defined $workflow->{0}->{$new->id};
}
else {
$sth_delnul->execute($new->id);
}
}
# Part 2: Bug status changes.
foreach my $old (@$statuses) {
foreach my $new (@$statuses) { foreach my $new (@$statuses) {
next if $old->{'id'} == $new->{'id'}; next if $old->id == $new->id;
if ($cgi->param('w_' . $old->{'id'} . '_' . $new->{'id'})) { if ($cgi->param('w_' . $old->id . '_' . $new->id)) {
$sth_insert->execute($old_id_for_db, $new->{'id'}) $sth_insert->execute($old->id, $new->id)
unless defined $workflow->{$old->{'id'}}->{$new->{'id'}}; unless defined $workflow->{$old->id}->{$new->id};
}
elsif ($old_id_for_db) {
$sth_delete->execute($old_id_for_db, $new->{'id'});
} }
else { else {
$sth_delnul->execute($new->{'id'}); $sth_delete->execute($old->id, $new->id);
} }
} }
} }
......
...@@ -43,6 +43,7 @@ use Bugzilla; ...@@ -43,6 +43,7 @@ use Bugzilla;
use Bugzilla::Constants; use Bugzilla::Constants;
use Bugzilla::Util; use Bugzilla::Util;
use Bugzilla::Error; use Bugzilla::Error;
use Bugzilla::Bug;
eval "use GD"; eval "use GD";
$@ && ThrowCodeError("gd_not_installed"); $@ && ThrowCodeError("gd_not_installed");
......
...@@ -32,6 +32,7 @@ use Bugzilla; ...@@ -32,6 +32,7 @@ use Bugzilla;
use Bugzilla::Constants; use Bugzilla::Constants;
use Bugzilla::Util; use Bugzilla::Util;
use Bugzilla::Error; use Bugzilla::Error;
use Bugzilla::Bug;
########################################################################### ###########################################################################
# General subs # General subs
......
...@@ -50,24 +50,24 @@ ...@@ -50,24 +50,24 @@
<th>&nbsp;</th> <th>&nbsp;</th>
[% FOREACH status = statuses %] [% FOREACH status = statuses %]
<th class="col-header[% status.is_open ? " open-status" : " closed-status" %]"> <th class="col-header[% status.is_open ? " open-status" : " closed-status" %]">
[% status.value FILTER html %] [% status.name FILTER html %]
</th> </th>
[% END %] [% END %]
</tr> </tr>
[%# This defines the entry point in the workflow %] [%# This defines the entry point in the workflow %]
[% p = [{id => 0, value => "{Start}", is_open => 1}] %] [% p = [{id => 0, name => "{Start}", is_open => 1}] %]
[% FOREACH status = p.merge(statuses) %] [% FOREACH status = p.merge(statuses) %]
<tr class="highlight"> <tr class="highlight">
<th align="right" class="[% status.is_open ? "open-status" : "closed-status" %]"> <th align="right" class="[% status.is_open ? "open-status" : "closed-status" %]">
[% status.value FILTER html %] [% status.name FILTER html %]
</th> </th>
[% FOREACH new_status = statuses %] [% FOREACH new_status = statuses %]
[% IF workflow.${status.id}.${new_status.id}.defined %] [% IF workflow.${status.id}.${new_status.id}.defined %]
<td align="center" class="checkbox-cell <td align="center" class="checkbox-cell
[% " checked" IF workflow.${status.id}.${new_status.id} %]" [% " checked" IF workflow.${status.id}.${new_status.id} %]"
title="From [% status.value FILTER html %] to [% new_status.value FILTER html %]"> title="From [% status.name FILTER html %] to [% new_status.name FILTER html %]">
<input type="checkbox" name="c_[% status.id %]_[% new_status.id %]" <input type="checkbox" name="c_[% status.id %]_[% new_status.id %]"
id="c_[% status.id %]_[% new_status.id %]" onclick="toggle_cell(this)" id="c_[% status.id %]_[% new_status.id %]" onclick="toggle_cell(this)"
[% " checked='checked'" IF workflow.${status.id}.${new_status.id} %]> [% " checked='checked'" IF workflow.${status.id}.${new_status.id} %]>
......
...@@ -34,8 +34,12 @@ ...@@ -34,8 +34,12 @@
</script> </script>
<p> <p>
This page allows you to define which status transitions are valid This page allows you to define which status transitions are valid in your workflow.
in your workflow. For compatibility with older versions of [% terms.Bugzilla %], reopening [% terms.abug %]
will only display either UNCONFIRMED or REOPENED (if allowed by your workflow) but not
both. The decision depends on whether the [% terms.bug %] has ever been confirmed or not.
So it is a good idea to allow both transitions and let [% terms.Bugzilla %] select the
correct one.
</p> </p>
<form id="workflow_form" method="POST" action="editworkflow.cgi"> <form id="workflow_form" method="POST" action="editworkflow.cgi">
...@@ -50,24 +54,24 @@ ...@@ -50,24 +54,24 @@
<th>&nbsp;</th> <th>&nbsp;</th>
[% FOREACH status = statuses %] [% FOREACH status = statuses %]
<th class="col-header[% status.is_open ? " open-status" : " closed-status" %]"> <th class="col-header[% status.is_open ? " open-status" : " closed-status" %]">
[% status.value FILTER html %] [% status.name FILTER html %]
</th> </th>
[% END %] [% END %]
</tr> </tr>
[%# This defines the entry point in the workflow %] [%# This defines the entry point in the workflow %]
[% p = [{id => 0, value => "{Start}", is_open => 1}] %] [% p = [{id => 0, name => "{Start}", is_open => 1}] %]
[% FOREACH status = p.merge(statuses) %] [% FOREACH status = p.merge(statuses) %]
<tr class="highlight"> <tr class="highlight">
<th align="right" class="[% status.is_open ? "open-status" : "closed-status" %]"> <th align="right" class="[% status.is_open ? "open-status" : "closed-status" %]">
[% status.value FILTER html %] [% status.name FILTER html %]
</th> </th>
[% FOREACH new_status = statuses %] [% FOREACH new_status = statuses %]
[% IF status.id != new_status.id %] [% IF status.id != new_status.id %]
<td align="center" class="checkbox-cell <td align="center" class="checkbox-cell
[% " checked" IF workflow.${status.id}.${new_status.id}.defined %]" [% " checked" IF workflow.${status.id}.${new_status.id}.defined %]"
title="From [% status.value FILTER html %] to [% new_status.value FILTER html %]"> title="From [% status.name FILTER html %] to [% new_status.name FILTER html %]">
<input type="checkbox" name="w_[% status.id %]_[% new_status.id %]" <input type="checkbox" name="w_[% status.id %]_[% new_status.id %]"
id="w_[% status.id %]_[% new_status.id %]" onclick="toggle_cell(this)" id="w_[% status.id %]_[% new_status.id %]" onclick="toggle_cell(this)"
[% " checked='checked'" IF workflow.${status.id}.${new_status.id}.defined %]> [% " checked='checked'" IF workflow.${status.id}.${new_status.id}.defined %]>
......
...@@ -595,7 +595,7 @@ ...@@ -595,7 +595,7 @@
<td align="right"> <td align="right">
<b><a href="page.cgi?id=fields.html#status">Status</a></b>: <b><a href="page.cgi?id=fields.html#status">Status</a></b>:
</td> </td>
<td>[% status_descs.${bug.bug_status} FILTER html %]</td> <td>[% get_status(bug.bug_status) FILTER html %]</td>
</tr> </tr>
<tr> <tr>
......
...@@ -18,42 +18,39 @@ ...@@ -18,42 +18,39 @@
# #
# Contributor(s): Gervase Markham <gerv@gerv.net> # Contributor(s): Gervase Markham <gerv@gerv.net>
# Vaskin Kissoyan <vkissoyan@yahoo.com> # Vaskin Kissoyan <vkissoyan@yahoo.com>
# Frédéric Buclin <LpSolit@gmail.com>
#%] #%]
[% PROCESS global/variables.none.tmpl %] [% PROCESS global/variables.none.tmpl %]
[%# *** Knob *** %]
<br> <br>
<div id="knob"> <div id="knob">
<div id="knob-options"> <div id="knob-options">
[% knum = 1 %]
[% initial_action_shown = 0 %] [% initial_action_shown = 0 %]
[% IF bug.isunconfirmed && bug.user.canconfirm %] [%# These actions are based on the current custom workflow. %]
[% PROCESS initial_action %] [% FOREACH bug_status = bug.status.can_change_to %]
<input type="radio" id="knob-confirm" name="knob" value="confirm"> [% NEXT IF bug.isunconfirmed && bug_status.is_open && !bug.user.canconfirm %]
<label for="knob-confirm"> [% NEXT IF bug.isopened && !bug.isunconfirmed && bug_status.is_open && !bug.user.canedit %]
Confirm [% terms.bug %] (change status to <b>[% get_status("NEW") FILTER html %]</b>) [% NEXT IF !bug_status.is_open && !bug.user.canedit && !bug.user.isreporter %]
</label> [% NEXT IF !bug_status.is_open && bug_status.is_open && !bug.user.canedit && !bug.user.isreporter %]
<br> [%# Special hack to only display UNCO or REOP when reopening, but not both;
[% knum = knum + 1 %] # for compatibility with older versions. %]
[% END %] [% NEXT IF !bug.isopened && (bug.everconfirmed && bug_status.name == "UNCONFIRMED"
|| !bug.everconfirmed && bug_status.name == "REOPENED") %]
[% IF bug.isopened && bug.bug_status != "ASSIGNED" && bug.user.canedit
&& (!bug.isunconfirmed || bug.user.canconfirm) %]
[% PROCESS initial_action %] [% PROCESS initial_action %]
<input type="radio" id="knob-accept" name="knob" value="accept"> <input type="radio" id="knob_[% bug_status.id FILTER html %]" name="knob"
<label for="knob-accept"> value="[% bug_status.name FILTER html %]">
Accept [% terms.bug %] ( <label for="knob_[% bug_status.id FILTER html %]">
[% IF bug.isunconfirmed %]confirm [% terms.bug %], and [% END %]change Change status to <b>[% get_status(bug_status.name) FILTER html %]</b>
status to <b>[% get_status("ASSIGNED") FILTER html %]</b>)
</label> </label>
[% IF bug.isopened && !bug_status.is_open %]
and set the resolution to [% PROCESS select_resolution field = "knob_${bug_status.id}" %]
[% END %]
<br> <br>
[% knum = knum + 1 %]
[% END %] [% END %]
[%# These actions are special and are independent of the workflow. %]
[% IF bug.user.canedit || bug.user.isreporter %] [% IF bug.user.canedit || bug.user.isreporter %]
[% IF bug.isopened %] [% IF bug.isopened %]
[% IF bug.resolution %] [% IF bug.resolution %]
...@@ -64,65 +61,27 @@ ...@@ -64,65 +61,27 @@
<b>[% get_resolution(bug.resolution) FILTER html %]</b>) <b>[% get_resolution(bug.resolution) FILTER html %]</b>)
</label> </label>
<br> <br>
[% knum = knum + 1 %]
[% END %] [% END %]
[% PROCESS initial_action %]
<input type="radio" id="knob-resolve" name="knob" value="resolve">
<label for="knob-resolve">
Resolve [% terms.bug %], changing
<a href="page.cgi?id=fields.html#resolution">resolution</a> to
</label>
[% PROCESS select_resolution %]
[% PROCESS duplicate %]
[% ELSE %] [% ELSE %]
[% IF bug.resolution != "MOVED" || [% IF bug.resolution != "MOVED" || bug.user.canmove %]
(bug.resolution == "MOVED" && bug.user.canmove) %]
[% PROCESS initial_action %] [% PROCESS initial_action %]
<input type="radio" id="knob-change-resolution" name="knob" value="change_resolution"> <input type="radio" id="knob_change_resolution" name="knob" value="change_resolution">
<label for="knob-change-resolution"> <label for="knob_change_resolution">
Change <a href="page.cgi?id=fields.html#resolution">resolution</a> to Change <a href="page.cgi?id=fields.html#resolution">resolution</a> to
</label> </label>
[% PROCESS select_resolution %] [% PROCESS select_resolution field = "knob_change_resolution" %]
[% PROCESS duplicate %]
<input type="radio" id="knob-reopen" name="knob" value="reopen">
<label for="knob-reopen">
Reopen [% terms.bug %]
</label>
<br>
[% knum = knum + 1 %]
[% END %]
[% IF bug.bug_status == "RESOLVED" %]
[% PROCESS initial_action %]
<input type="radio" id="knob-verify" name="knob" value="verify">
<label for="knob-verify">
Mark [% terms.bug %] as <b>[% get_status("VERIFIED") FILTER html %]</b>
</label>
<br> <br>
[% knum = knum + 1 %]
[% END %]
[% IF bug.bug_status != "CLOSED" %]
[% PROCESS initial_action %]
<input type="radio" id="knob-close" name="knob" value="close">
<label for="knob-close">
Mark [% terms.bug %] as <b>[% get_status("CLOSED") FILTER html %]</b>
</label>
<br>
[% knum = knum + 1 %]
[% END %] [% END %]
[% END %] [% END %]
[% PROCESS duplicate %]
[% END %] [% END %]
</div> </div>
<div id="knob-buttons"> <div id="knob-buttons">
<input type="submit" value="Commit" id="commit"> <input type="submit" value="Commit" id="commit">
[% IF bug.user.canmove %] [% IF bug.user.canmove %]
&nbsp; <font size="+1"><b> | </b></font> &nbsp; <input type="submit" name="action" id="action" value="[% Param("move-button-text") %]">
<input type="submit" name="action" id="action"
value="[% Param("move-button-text") %]">
[% END %] [% END %]
</div> </div>
</div> </div>
...@@ -143,23 +102,20 @@ ...@@ -143,23 +102,20 @@
[% END %] [% END %]
[% BLOCK select_resolution %] [% BLOCK select_resolution %]
<select name="resolution" <select name="resolution_[% field FILTER html %]"
onchange="document.changeform.knob[[% knum %]].checked=true"> onchange="document.forms['changeform'].[% field FILTER html %].checked=true">
[% FOREACH r = bug.choices.resolution %] [% FOREACH r = bug.choices.resolution %]
<option value="[% r FILTER html %]">[% get_resolution(r) FILTER html %]</option> <option value="[% r FILTER html %]">[% get_resolution(r) FILTER html %]</option>
[% END %] [% END %]
</select> </select>
<br>
[% knum = knum + 1 %]
[% END %] [% END %]
[% BLOCK duplicate %] [% BLOCK duplicate %]
<input type="radio" id="knob-duplicate" name="knob" value="duplicate"> <input type="radio" id="knob_duplicate" name="knob" value="duplicate">
<label for="knob-duplicate"> <label for="knob_duplicate">
Mark the [% terms.bug %] as duplicate of [% terms.bug %] # Mark the [% terms.bug %] as duplicate of [% terms.bug %] #
</label> </label>
<input name="dup_id" size="6" <input name="dup_id" size="6"
onchange="if (this.value != '') {document.changeform.knob[[% knum %]].checked=true}"> onchange="if (this.value != '') {document.forms['changeform'].knob_duplicate.checked=true}">
<br> <br>
[% knum = knum + 1 %]
[% END %] [% END %]
...@@ -191,8 +191,7 @@ ...@@ -191,8 +191,7 @@
'list/edit-multiple.html.tmpl' => [ 'list/edit-multiple.html.tmpl' => [
'group.id', 'group.id',
'knum', 'menuname',
'menuname',
], ],
'list/list.rdf.tmpl' => [ 'list/list.rdf.tmpl' => [
...@@ -319,10 +318,6 @@ ...@@ -319,10 +318,6 @@
'flag.status', 'flag.status',
], ],
'bug/knob.html.tmpl' => [
'knum',
],
'bug/navigate.html.tmpl' => [ 'bug/navigate.html.tmpl' => [
'bug_list.first', 'bug_list.first',
'bug_list.last', 'bug_list.last',
......
...@@ -243,7 +243,13 @@ ...@@ -243,7 +243,13 @@
[% ELSIF error == "comment_required" %] [% ELSIF error == "comment_required" %]
[% title = "Comment Required" %] [% title = "Comment Required" %]
You have to specify a <b>comment</b> on this change. You have to specify a <b>comment</b>
[% IF old.size && new %]
to change the [% terms.bug %] status from [% old.join(", ") FILTER html %]
to [% new FILTER html %].
[% ELSE %]
on this change.
[% END %]
Please explain your change. Please explain your change.
[% ELSIF error == "comment_too_long" %] [% ELSIF error == "comment_too_long" %]
...@@ -633,7 +639,12 @@ ...@@ -633,7 +639,12 @@
[% title = "Your Search Makes No Sense" %] [% title = "Your Search Makes No Sense" %]
The only legal values for the <em>Attachment is patch</em> field are The only legal values for the <em>Attachment is patch</em> field are
0 and 1. 0 and 1.
[% ELSIF error == "illegal_bug_status_transition" %]
[% title = "Illegal $terms.Bug Status Change" %]
You are not allowed to change the [% terms.bug %] status from
[%+ old.join(", ") FILTER html %] to [%+ new FILTER html %].
[% ELSIF error == "illegal_change" %] [% ELSIF error == "illegal_change" %]
[% title = "Not allowed" %] [% title = "Not allowed" %]
You tried to change the You tried to change the
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
# #
# Contributor(s): Myk Melez <myk@mozilla.org> # Contributor(s): Myk Melez <myk@mozilla.org>
# Max Kanat-Alexander <mkanat@bugzilla.org> # Max Kanat-Alexander <mkanat@bugzilla.org>
# Frédéric Buclin <LpSolit@gmail.com>
#%] #%]
[% PROCESS global/variables.none.tmpl %] [% PROCESS global/variables.none.tmpl %]
...@@ -301,66 +302,25 @@ ...@@ -301,66 +302,25 @@
[% knum = 0 %]
<input id="knob-none" type="radio" name="knob" value="none" checked="checked"> <input id="knob-none" type="radio" name="knob" value="none" checked="checked">
<label for="knob-none">Do nothing else</label><br> <label for="knob-none">Do nothing else</label><br>
[% IF bugstatuses.size == 1 && bugstatuses.0 == unconfirmedstate %] [% FOREACH bug_status = new_bug_statuses %]
[% knum = knum + 1 %] <input type="radio" id="knob_[% bug_status.id FILTER html %]" name="knob"
<input id="knob-confirm" type="radio" name="knob" value="confirm"> value="[% bug_status.name FILTER html %]">
<label for="knob-confirm"> <label for="knob_[% bug_status.id FILTER html %]">
Confirm [% terms.bugs %] (change status to <b>[% get_status("NEW") FILTER html %]</b>) Change status to <b>[% get_status(bug_status.name) FILTER html %]</b>
</label><br> </label>
[% IF !bug_status.is_open %]
and set the resolution to [% PROCESS select_resolution field = "knob_${bug_status.id}" %]
[% END %]
<br>
[% END %] [% END %]
[%# If all the bugs being changed are open, allow the user to accept them, [%# If all the bugs being changed are open, allow the user to clear their resolution. %]
clear their resolution or resolve them. %] [% IF !current_bug_statuses.containsany(closedstates) %]
[% IF !bugstatuses.containsany(closedstates) %]
[% knum = knum + 1 %]
<input id="knob-accept" type="radio" name="knob" value="accept">
<label for="knob-accept">
Accept [% terms.bugs %] (change status to <b>[% get_status("ASSIGNED") FILTER html %]</b>)
</label><br>
[% knum = knum + 1 %]
<input id="knob-clearresolution" type="radio" name="knob" value="clearresolution"> <input id="knob-clearresolution" type="radio" name="knob" value="clearresolution">
<label for="knob-clearresolution">Clear the resolution</label><br> <label for="knob-clearresolution">Clear the resolution</label><br>
[% knum = knum + 1 %]
<input id="knob-resolve" type="radio" name="knob" value="resolve">
<label for="knob-resolve">
Resolve [% terms.bugs %], changing <a href="page.cgi?id=fields.html#resolution">resolution</a> to
</label>
<select name="resolution" onchange="document.forms.changeform.knob[[% knum %]].checked=true">
[% FOREACH resolution = resolutions %]
[% NEXT IF !resolution %]
<option value="[% resolution FILTER html %]">
[% get_resolution(resolution) FILTER html %]
</option>
[% END %]
</select><br>
[% END %]
[%# If all the bugs are closed, allow the user to reopen them. %]
[% IF !bugstatuses.containsany(openstates) %]
[% knum = knum + 1 %]
<input id="knob-reopen" type="radio" name="knob" value="reopen">
<label for="knob-reopen">Reopen [% terms.bugs %]</label><br>
[% END %]
[% IF bugstatuses.size == 1 %]
[% IF bugstatuses.contains('RESOLVED') %]
[% knum = knum + 1 %]
<input id="knob-verify" type="radio" name="knob" value="verify">
<label for="knob-verify">Mark [% terms.bugs %] as <b>[% get_status("VERIFIED") FILTER html %]</b></label><br>
[% END %]
[% END %]
[% IF !bugstatuses.containsany(openstates) AND !bugstatuses.contains('CLOSED') %]
[% knum = knum + 1 %]
<input id="knob-close" type="radio" name="knob" value="close">
<label for="knob-close">Mark [% terms.bugs %] as <b>[% get_status("CLOSED") FILTER html %]</b></label><br>
[% END %] [% END %]
<input type="submit" id="commit" value="Commit"> <input type="submit" id="commit" value="Commit">
...@@ -384,3 +344,13 @@ ...@@ -384,3 +344,13 @@
[% END %] [% END %]
</select> </select>
[% END %] [% END %]
[% BLOCK select_resolution %]
<select name="resolution"
onchange="document.forms['changeform'].[% field FILTER html %].checked=true">
[% FOREACH r = resolutions %]
[% NEXT IF !r %]
<option value="[% r FILTER html %]">[% get_resolution(r) FILTER html %]</option>
[% END %]
</select>
[% END %]
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