Commit 2904ac32 authored by lpsolit%gmail.com's avatar lpsolit%gmail.com

Bug 174039: Set flags on bug entry - Patch by Frédéric Buclin…

Bug 174039: Set flags on bug entry - Patch by Frédéric Buclin <LpSolit@gmail.com> r=wurblzap r=myk a=myk
parent bea873a6
...@@ -51,7 +51,8 @@ use Bugzilla::Constants; ...@@ -51,7 +51,8 @@ use Bugzilla::Constants;
use Bugzilla::Error; use Bugzilla::Error;
use Bugzilla::Flag; use Bugzilla::Flag;
use Bugzilla::User; use Bugzilla::User;
use Bugzilla::Util qw(trick_taint); use Bugzilla::Util;
use Bugzilla::Field;
sub get { sub get {
my $invocant = shift; my $invocant = shift;
...@@ -594,12 +595,89 @@ sub validate_content_type { ...@@ -594,12 +595,89 @@ sub validate_content_type {
=pod =pod
=item C<insert_attachment_for_bug($throw_error, $bug_id, $user, $timestamp, $hr_vars)> =item C<validate_can_edit()>
Description: validates if the user is allowed to edit the attachment.
Only the submitter or someone with editbugs privs can edit it.
Returns: 1 on success. Else an error is thrown.
=cut
sub validate_can_edit {
my ($class, $attach_id) = @_;
my $dbh = Bugzilla->dbh;
my $user = Bugzilla->user;
# People in editbugs can edit all attachments
return if $user->in_group('editbugs');
# Bug 97729 - the submitter can edit their attachments
my ($ref) = $dbh->selectrow_array('SELECT attach_id FROM attachments
WHERE attach_id = ? AND submitter_id = ?',
undef, ($attach_id, $user->id));
$ref || ThrowUserError('illegal_attachment_edit', { attach_id => $attach_id });
}
=item C<validate_obsolete($bug_id)>
Description: validates if attachments the user wants to mark as obsolete
really belong to the given bug and are not already obsolete.
Params: $bug_id - The bug ID obsolete attachments should belong to.
Returns: 1 on success. Else an error is thrown.
=cut
sub validate_obsolete {
my ($class, $bug_id) = @_;
my $cgi = Bugzilla->cgi;
# Make sure the attachment id is valid and the user has permissions to view
# the bug to which it is attached.
my @obsolete_attachments;
foreach my $attachid ($cgi->param('obsolete')) {
my $vars = {};
$vars->{'attach_id'} = $attachid;
detaint_natural($attachid)
|| ThrowCodeError('invalid_attach_id_to_obsolete', $vars);
my $attachment = Bugzilla::Attachment->get($attachid);
# Make sure the attachment exists in the database.
ThrowUserError('invalid_attach_id', $vars) unless $attachment;
$vars->{'description'} = $attachment->description;
if ($attachment->bug_id != $bug_id) {
$vars->{'my_bug_id'} = $bug_id;
$vars->{'attach_bug_id'} = $attachment->bug_id;
ThrowCodeError('mismatched_bug_ids_on_obsolete', $vars);
}
if ($attachment->isobsolete) {
ThrowCodeError('attachment_already_obsolete', $vars);
}
# Check that the user can modify this attachment.
$class->validate_can_edit($attachid);
push(@obsolete_attachments, $attachment);
}
return @obsolete_attachments;
}
=pod
=item C<insert_attachment_for_bug($throw_error, $bug, $user, $timestamp, $hr_vars)>
Description: inserts an attachment from CGI input for the given bug. Description: inserts an attachment from CGI input for the given bug.
Params: C<$bug_id> - integer - the ID of the bug for which Params: C<$bug> - Bugzilla::Bug object - the bug for which to insert
to insert the attachment. the attachment.
C<$user> - Bugzilla::User object - the user we're inserting an C<$user> - Bugzilla::User object - the user we're inserting an
attachment for. attachment for.
C<$timestamp> - scalar - timestamp of the insert as returned C<$timestamp> - scalar - timestamp of the insert as returned
...@@ -614,7 +692,7 @@ Returns: the ID of the new attachment. ...@@ -614,7 +692,7 @@ Returns: the ID of the new attachment.
=cut =cut
sub insert_attachment_for_bug { sub insert_attachment_for_bug {
my ($class, $throw_error, $bug_id, $user, $timestamp, $hr_vars) = @_; my ($class, $throw_error, $bug, $user, $timestamp, $hr_vars) = @_;
my $cgi = Bugzilla->cgi; my $cgi = Bugzilla->cgi;
my $dbh = Bugzilla->dbh; my $dbh = Bugzilla->dbh;
...@@ -671,8 +749,8 @@ sub insert_attachment_for_bug { ...@@ -671,8 +749,8 @@ sub insert_attachment_for_bug {
# Setting the third param to -1 will force this function to check this # Setting the third param to -1 will force this function to check this
# point. # point.
# XXX needs $throw_error treatment # XXX needs $throw_error treatment
Bugzilla::Flag::validate($cgi, $bug_id, -1); Bugzilla::Flag::validate($cgi, $bug->bug_id, -1);
Bugzilla::FlagType::validate($cgi, $bug_id, -1); Bugzilla::FlagType::validate($cgi, $bug->bug_id, -1);
# Escape characters in strings that will be used in SQL statements. # Escape characters in strings that will be used in SQL statements.
my $description = $cgi->param('description'); my $description = $cgi->param('description');
...@@ -684,7 +762,7 @@ sub insert_attachment_for_bug { ...@@ -684,7 +762,7 @@ sub insert_attachment_for_bug {
"INSERT INTO attachments "INSERT INTO attachments
(bug_id, creation_ts, filename, description, (bug_id, creation_ts, filename, description,
mimetype, ispatch, isurl, isprivate, submitter_id) mimetype, ispatch, isurl, isprivate, submitter_id)
VALUES (?,?,?,?,?,?,?,?,?)", undef, ($bug_id, $timestamp, $filename, VALUES (?,?,?,?,?,?,?,?,?)", undef, ($bug->bug_id, $timestamp, $filename,
$description, $contenttype, $cgi->param('ispatch'), $description, $contenttype, $cgi->param('ispatch'),
$isurl, $isprivate, $user->id)); $isurl, $isprivate, $user->id));
# Retrieve the ID of the newly created attachment record. # Retrieve the ID of the newly created attachment record.
...@@ -724,6 +802,36 @@ sub insert_attachment_for_bug { ...@@ -724,6 +802,36 @@ sub insert_attachment_for_bug {
close AH; close AH;
close $fh; close $fh;
} }
# Now handle flags.
my @obsolete_attachments;
if ($cgi->param('obsolete')) {
@obsolete_attachments = $class->validate_obsolete($bug->bug_id);
}
# Make existing attachments obsolete.
my $fieldid = get_field_id('attachments.isobsolete');
foreach my $obsolete_attachment (@obsolete_attachments) {
# If the obsolete attachment has request flags, cancel them.
# This call must be done before updating the 'attachments' table.
Bugzilla::Flag::CancelRequests($bug, $obsolete_attachment, $timestamp);
$dbh->do('UPDATE attachments SET isobsolete = 1 WHERE attach_id = ?',
undef, $obsolete_attachment->id);
$dbh->do('INSERT INTO bugs_activity (bug_id, attach_id, who, bug_when,
fieldid, removed, added)
VALUES (?,?,?,?,?,?,?)',
undef, ($bug->bug_id, $obsolete_attachment->id, $user->id,
$timestamp, $fieldid, 0, 1));
}
# Create flags.
my $attachment = Bugzilla::Attachment->get($attachid);
Bugzilla::Flag::process($bug, $attachment, $timestamp, $cgi);
# Return the ID of the new attachment.
return $attachid; return $attachid;
} }
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
# The Original Code is the Bugzilla Bug Tracking System. # The Original Code is the Bugzilla Bug Tracking System.
# #
# Contributor(s): Tiago R. Mello <timello@async.com.br> # Contributor(s): Tiago R. Mello <timello@async.com.br>
# # Frédéric Buclin <LpSolit@gmail.com>
use strict; use strict;
...@@ -22,6 +22,7 @@ package Bugzilla::Component; ...@@ -22,6 +22,7 @@ package Bugzilla::Component;
use Bugzilla::Util; use Bugzilla::Util;
use Bugzilla::Error; use Bugzilla::Error;
use Bugzilla::User; use Bugzilla::User;
use Bugzilla::FlagType;
############################### ###############################
#### Initialization #### #### Initialization ####
...@@ -135,6 +136,24 @@ sub default_qa_contact { ...@@ -135,6 +136,24 @@ sub default_qa_contact {
return $self->{'default_qa_contact'}; return $self->{'default_qa_contact'};
} }
sub flag_types {
my $self = shift;
if (!defined $self->{'flag_types'}) {
$self->{'flag_types'} = {};
$self->{'flag_types'}->{'bug'} =
Bugzilla::FlagType::match({ 'target_type' => 'bug',
'product_id' => $self->product_id,
'component_id' => $self->id });
$self->{'flag_types'}->{'attachment'} =
Bugzilla::FlagType::match({ 'target_type' => 'attachment',
'product_id' => $self->product_id,
'component_id' => $self->id });
}
return $self->{'flag_types'};
}
############################### ###############################
#### Accessors #### #### Accessors ####
############################### ###############################
...@@ -193,6 +212,8 @@ Bugzilla::Component - Bugzilla product component class. ...@@ -193,6 +212,8 @@ Bugzilla::Component - Bugzilla product component class.
my $product_id = $component->product_id; my $product_id = $component->product_id;
my $default_assignee = $component->default_assignee; my $default_assignee = $component->default_assignee;
my $default_qa_contact = $component->default_qa_contact; my $default_qa_contact = $component->default_qa_contact;
my $bug_flag_types = $component->flag_types->{'bug'};
my $attach_flag_types = $component->flag_types->{'attachment'};
my $component = Bugzilla::Component::check_component($product, 'AcmeComp'); my $component = Bugzilla::Component::check_component($product, 'AcmeComp');
...@@ -252,6 +273,15 @@ Component.pm represents a Product Component object. ...@@ -252,6 +273,15 @@ Component.pm represents a Product Component object.
Returns: A Bugzilla::User object. Returns: A Bugzilla::User object.
=item C<flag_types()>
Description: Returns all bug and attachment flagtypes available for
the component.
Params: none.
Returns: Two references to an array of flagtype objects.
=back =back
=head1 SUBROUTINES =head1 SUBROUTINES
......
...@@ -78,7 +78,7 @@ sub _throw_error { ...@@ -78,7 +78,7 @@ sub _throw_error {
my $message; my $message;
$template->process($name, $vars, \$message) $template->process($name, $vars, \$message)
|| ThrowTemplateError($template->error()); || ThrowTemplateError($template->error());
die("$message"); die("$message\n");
} else { } else {
print Bugzilla->cgi->header(); print Bugzilla->cgi->header();
$template->process($name, $vars) $template->process($name, $vars)
......
...@@ -177,6 +177,24 @@ sub user_has_access { ...@@ -177,6 +177,24 @@ sub user_has_access {
undef, $self->id); undef, $self->id);
} }
sub flag_types {
my $self = shift;
if (!defined $self->{'flag_types'}) {
$self->{'flag_types'} = {};
foreach my $type ('bug', 'attachment') {
my %flagtypes;
foreach my $component (@{$self->components}) {
foreach my $flagtype (@{$component->flag_types->{$type}}) {
$flagtypes{$flagtype->{'id'}} ||= $flagtype;
}
}
$self->{'flag_types'}->{$type} = [sort { $a->{'sortkey'} <=> $b->{'sortkey'}
|| $a->{'name'} cmp $b->{'name'} } values %flagtypes];
}
}
return $self->{'flag_types'};
}
############################### ###############################
#### Accessors ###### #### Accessors ######
...@@ -231,6 +249,7 @@ Bugzilla::Product - Bugzilla product class. ...@@ -231,6 +249,7 @@ Bugzilla::Product - Bugzilla product class.
my $bugcount = $product->bug_count(); my $bugcount = $product->bug_count();
my $bug_ids = $product->bug_ids(); my $bug_ids = $product->bug_ids();
my $has_access = $product->user_has_access($user); my $has_access = $product->user_has_access($user);
my $flag_types = $product->flag_types();
my $id = $product->id; my $id = $product->id;
my $name = $product->name; my $name = $product->name;
...@@ -320,6 +339,15 @@ below. ...@@ -320,6 +339,15 @@ below.
Returns C<1> If this user's groups allow him C<entry> access to Returns C<1> If this user's groups allow him C<entry> access to
this Product, C<0> otherwise. this Product, C<0> otherwise.
=item C<flag_types()>
Description: Returns flag types available for at least one of
its components.
Params: none.
Returns: Two references to an array of flagtype objects.
=back =back
=head1 SUBROUTINES =head1 SUBROUTINES
......
...@@ -206,24 +206,6 @@ sub validateContext ...@@ -206,24 +206,6 @@ sub validateContext
return $context; return $context;
} }
sub validateCanEdit
{
my ($attach_id) = (@_);
my $dbh = Bugzilla->dbh;
# People in editbugs can edit all attachments
return if UserInGroup("editbugs");
# Bug 97729 - the submitter can edit their attachments
my ($ref) = $dbh->selectrow_array("SELECT attach_id FROM attachments
WHERE attach_id = ?
AND submitter_id = ?",
undef, ($attach_id, Bugzilla->user->id));
$ref || ThrowUserError("illegal_attachment_edit",{ attach_id => $attach_id });
}
sub validateCanChangeAttachment sub validateCanChangeAttachment
{ {
my ($attachid) = @_; my ($attachid) = @_;
...@@ -270,41 +252,6 @@ sub validatePrivate ...@@ -270,41 +252,6 @@ sub validatePrivate
$cgi->param('isprivate', $cgi->param('isprivate') ? 1 : 0); $cgi->param('isprivate', $cgi->param('isprivate') ? 1 : 0);
} }
sub validateObsolete {
# Make sure the attachment id is valid and the user has permissions to view
# the bug to which it is attached.
my @obsolete_attachments;
foreach my $attachid ($cgi->param('obsolete')) {
my $vars = {};
$vars->{'attach_id'} = $attachid;
detaint_natural($attachid)
|| ThrowCodeError("invalid_attach_id_to_obsolete", $vars);
my $attachment = Bugzilla::Attachment->get($attachid);
# Make sure the attachment exists in the database.
ThrowUserError("invalid_attach_id", $vars) unless $attachment;
$vars->{'description'} = $attachment->description;
if ($attachment->bug_id != $cgi->param('bugid')) {
$vars->{'my_bug_id'} = $cgi->param('bugid');
$vars->{'attach_bug_id'} = $attachment->bug_id;
ThrowCodeError("mismatched_bug_ids_on_obsolete", $vars);
}
if ($attachment->isobsolete) {
ThrowCodeError("attachment_already_obsolete", $vars);
}
# Check that the user can modify this attachment
validateCanEdit($attachid);
push(@obsolete_attachments, $attachment);
}
return @obsolete_attachments;
}
# Returns 1 if the parameter is a content-type viewable in this browser # Returns 1 if the parameter is a content-type viewable in this browser
# Note that we don't use $cgi->Accept()'s ability to check if a content-type # Note that we don't use $cgi->Accept()'s ability to check if a content-type
# matches, because this will return a value even if it's matched by the generic # matches, because this will return a value even if it's matched by the generic
...@@ -789,38 +736,19 @@ sub insert ...@@ -789,38 +736,19 @@ sub insert
ValidateComment(scalar $cgi->param('comment')); ValidateComment(scalar $cgi->param('comment'));
my ($timestamp) = Bugzilla->dbh->selectrow_array("SELECT NOW()"); my ($timestamp) = Bugzilla->dbh->selectrow_array("SELECT NOW()");
my $bug = new Bugzilla::Bug($bugid, $user->id);
my $attachid = my $attachid =
Bugzilla::Attachment->insert_attachment_for_bug(THROW_ERROR, Bugzilla::Attachment->insert_attachment_for_bug(THROW_ERROR, $bug, $user,
$bugid, $user,
$timestamp, \$vars); $timestamp, \$vars);
my $isprivate = $cgi->param('isprivate') ? 1 : 0;
my @obsolete_attachments;
@obsolete_attachments = validateObsolete() if $cgi->param('obsolete');
# Insert a comment about the new attachment into the database. # Insert a comment about the new attachment into the database.
my $comment = "Created an attachment (id=$attachid)\n" . my $comment = "Created an attachment (id=$attachid)\n" .
$cgi->param('description') . "\n"; $cgi->param('description') . "\n";
$comment .= ("\n" . $cgi->param('comment')) if defined $cgi->param('comment'); $comment .= ("\n" . $cgi->param('comment')) if defined $cgi->param('comment');
my $isprivate = $cgi->param('isprivate') ? 1 : 0;
AppendComment($bugid, $user->id, $comment, $isprivate, $timestamp); AppendComment($bugid, $user->id, $comment, $isprivate, $timestamp);
# Make existing attachments obsolete.
my $fieldid = get_field_id('attachments.isobsolete');
my $bug = new Bugzilla::Bug($bugid, $user->id);
foreach my $obsolete_attachment (@obsolete_attachments) {
# If the obsolete attachment has request flags, cancel them.
# This call must be done before updating the 'attachments' table.
Bugzilla::Flag::CancelRequests($bug, $obsolete_attachment, $timestamp);
$dbh->do("UPDATE attachments SET isobsolete = 1 " .
"WHERE attach_id = ?", undef, $obsolete_attachment->id);
$dbh->do("INSERT INTO bugs_activity (bug_id, attach_id, who, bug_when,
fieldid, removed, added)
VALUES (?,?,?,?,?,?,?)", undef,
$bugid, $obsolete_attachment->id, $user->id, $timestamp, $fieldid, 0, 1);
}
# Assign the bug to the user, if they are allowed to take it # Assign the bug to the user, if they are allowed to take it
my $owner = ""; my $owner = "";
...@@ -862,13 +790,7 @@ sub insert ...@@ -862,13 +790,7 @@ sub insert
} }
} }
} }
# Create flags.
# Update the bug object with updated data.
$bug = new Bugzilla::Bug($bugid, $user->id);
my $attachment = Bugzilla::Attachment->get($attachid);
Bugzilla::Flag::process($bug, $attachment, $timestamp, $cgi);
# Define the variables and functions that will be passed to the UI template. # Define the variables and functions that will be passed to the UI template.
$vars->{'mailrecipients'} = { 'changer' => $user->login, $vars->{'mailrecipients'} = { 'changer' => $user->login,
'owner' => $owner }; 'owner' => $owner };
...@@ -947,7 +869,7 @@ sub update ...@@ -947,7 +869,7 @@ sub update
# Retrieve and validate parameters # Retrieve and validate parameters
ValidateComment(scalar $cgi->param('comment')); ValidateComment(scalar $cgi->param('comment'));
my ($attach_id, $bugid) = validateID(); my ($attach_id, $bugid) = validateID();
validateCanEdit($attach_id); Bugzilla::Attachment->validate_can_edit($attach_id);
validateCanChangeAttachment($attach_id); validateCanChangeAttachment($attach_id);
Bugzilla::Attachment->validate_description(THROW_ERROR); Bugzilla::Attachment->validate_description(THROW_ERROR);
Bugzilla::Attachment->validate_is_patch(THROW_ERROR); Bugzilla::Attachment->validate_is_patch(THROW_ERROR);
...@@ -1113,7 +1035,7 @@ sub delete_attachment { ...@@ -1113,7 +1035,7 @@ sub delete_attachment {
# Make sure the administrator is allowed to edit this attachment. # Make sure the administrator is allowed to edit this attachment.
my ($attach_id, $bug_id) = validateID(); my ($attach_id, $bug_id) = validateID();
validateCanEdit($attach_id); Bugzilla::Attachment->validate_can_edit($attach_id);
validateCanChangeAttachment($attach_id); validateCanChangeAttachment($attach_id);
my $attachment = Bugzilla::Attachment->get($attach_id); my $attachment = Bugzilla::Attachment->get($attach_id);
......
...@@ -536,11 +536,13 @@ $dbh->do("UPDATE bugs SET creation_ts = ? WHERE bug_id = ?", ...@@ -536,11 +536,13 @@ $dbh->do("UPDATE bugs SET creation_ts = ? WHERE bug_id = ?",
$dbh->bz_unlock_tables(); $dbh->bz_unlock_tables();
my $bug = new Bugzilla::Bug($id, $user->id);
# Add an attachment if requested. # Add an attachment if requested.
if (defined($cgi->upload('data')) || $cgi->param('attachurl')) { if (defined($cgi->upload('data')) || $cgi->param('attachurl')) {
$cgi->param('isprivate', $cgi->param('commentprivacy')); $cgi->param('isprivate', $cgi->param('commentprivacy'));
Bugzilla::Attachment->insert_attachment_for_bug(!THROW_ERROR, Bugzilla::Attachment->insert_attachment_for_bug(!THROW_ERROR,
$id, $user, $timestamp, $bug, $user, $timestamp,
\$vars) \$vars)
|| ($vars->{'message'} = 'attachment_creation_failed'); || ($vars->{'message'} = 'attachment_creation_failed');
...@@ -551,11 +553,30 @@ if (defined($cgi->upload('data')) || $cgi->param('attachurl')) { ...@@ -551,11 +553,30 @@ if (defined($cgi->upload('data')) || $cgi->param('attachurl')) {
}; };
} }
# Add flags, if any. To avoid dying if something goes wrong
# while processing flags, we will eval() flag validation.
# This requires to be in batch mode.
# XXX: this can go away as soon as flag validation is able to
# fail without dying.
Bugzilla->batch(1);
eval {
# Make sure no flags have already been set for this bug.
# Impossible? - Well, depends if you hack the URL or not.
# Passing a bug ID of 0 will make it complain if it finds one.
Bugzilla::Flag::validate($cgi, 0);
Bugzilla::FlagType::validate($cgi, $id);
Bugzilla::Flag::process($bug, undef, $timestamp, $cgi);
};
Bugzilla->batch(0);
if ($@) {
$vars->{'message'} = 'flag_creation_failed';
$vars->{'flag_creation_error'} = $@;
}
# Email everyone the details of the new bug # Email everyone the details of the new bug
$vars->{'mailrecipients'} = {'changer' => $user->login}; $vars->{'mailrecipients'} = {'changer' => $user->login};
$vars->{'id'} = $id; $vars->{'id'} = $id;
my $bug = new Bugzilla::Bug($id, $user->id);
$vars->{'bug'} = $bug; $vars->{'bug'} = $bug;
ThrowCodeError("bug_error", { bug => $bug }) if $bug->error; ThrowCodeError("bug_error", { bug => $bug }) if $bug->error;
......
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
var initialowners = new Array([% product.components.size %]); var initialowners = new Array([% product.components.size %]);
var last_initialowner; var last_initialowner;
var components = new Array([% product.components.size %]); var components = new Array([% product.components.size %]);
var flags = new Array([% product.components.size %]);
[% IF Param("useqacontact") %] [% IF Param("useqacontact") %]
var initialqacontacts = new Array([% product.components.size %]); var initialqacontacts = new Array([% product.components.size %]);
var last_initialqacontact; var last_initialqacontact;
...@@ -45,6 +46,17 @@ var components = new Array([% product.components.size %]); ...@@ -45,6 +46,17 @@ var components = new Array([% product.components.size %]);
[%- FOREACH c = product.components %] [%- FOREACH c = product.components %]
components[[% count %]] = "[% c.name FILTER js %]"; components[[% count %]] = "[% c.name FILTER js %]";
initialowners[[% count %]] = "[% c.default_assignee.login FILTER js %]"; initialowners[[% count %]] = "[% c.default_assignee.login FILTER js %]";
var flag_list = new Array([% c.flag_types.bug.size + c.flag_types.attachment.size %]);
[% flag_count = 0 %]
[% FOREACH f = c.flag_types.bug %]
flag_list[[% flag_count %]] = "[% f.id %]";
[% flag_count = flag_count + 1 %]
[% END %]
[% FOREACH f = c.flag_types.attachment %]
flag_list[[% flag_count %]] = "[% f.id %]";
[% flag_count = flag_count + 1 %]
[% END %]
flags[[% count %]] = flag_list;
[% IF Param("useqacontact") %] [% IF Param("useqacontact") %]
initialqacontacts[[% count %]] = "[% c.default_qa_contact.login FILTER js %]"; initialqacontacts[[% count %]] = "[% c.default_qa_contact.login FILTER js %]";
[% END %] [% END %]
...@@ -53,8 +65,8 @@ var components = new Array([% product.components.size %]); ...@@ -53,8 +65,8 @@ var components = new Array([% product.components.size %]);
function set_assign_to() { function set_assign_to() {
// Based on the selected component, fill the "Assign To:" field // Based on the selected component, fill the "Assign To:" field
// with the default component owner, and the the "QA Contact:" field // with the default component owner, and the "QA Contact:" field
// with the default QA Contact. // with the default QA Contact. It also selectively enables flags.
var form = document.Create; var form = document.Create;
var assigned_to = form.assigned_to.value; var assigned_to = form.assigned_to.value;
...@@ -87,6 +99,31 @@ function set_assign_to() { ...@@ -87,6 +99,31 @@ function set_assign_to() {
last_initialqacontact = contact; last_initialqacontact = contact;
} }
[% END %] [% END %]
// First, we disable all flags. Then we re-enable those
// which are available for the selected component.
var inputElements = document.getElementsByTagName("select");
var inputElement, flagField;
for ( var i=0 ; i<inputElements.length ; i++ ) {
inputElement = inputElements.item(i);
if (inputElement.name.search(/^flag_type-(\d+)$/) != -1) {
var id = inputElement.name.replace(/^flag_type-(\d+)$/, "$1");
inputElement.disabled = true;
// Also disable the requestee field, if it exists.
inputElement = document.getElementById("requestee_type-" + id);
if (inputElement) inputElement.disabled = true;
}
}
// Now enable flags available for the selected component.
for (var i = 0; i < flags[index].length; i++) {
flagField = document.getElementById("flag_type-" + flags[index][i]);
if (flagField) {
flagField.disabled = false;
// Re-enabling the requestee field depends on the status
// of the flag.
toggleRequesteeField(flagField, 1);
}
}
} }
} }
...@@ -113,11 +150,7 @@ function handleWantsAttachment(wants_attachment) { ...@@ -113,11 +150,7 @@ function handleWantsAttachment(wants_attachment) {
<table cellspacing="2" cellpadding="0" border="0"> <table cellspacing="2" cellpadding="0" border="0">
<tr> <tr>
<td><br></td> <td>&nbsp;</td>
</tr>
<tr>
<td></td>
<td colspan="3"> <td colspan="3">
[%# Migration note: The following file corresponds to the old Param [%# Migration note: The following file corresponds to the old Param
# 'entryheaderhtml' # 'entryheaderhtml'
...@@ -127,7 +160,8 @@ function handleWantsAttachment(wants_attachment) { ...@@ -127,7 +160,8 @@ function handleWantsAttachment(wants_attachment) {
</tr> </tr>
<tr> <tr>
<td><br></td> <td>&nbsp;</td>
<td colspan="3">&nbsp;</td>
</tr> </tr>
<tr> <tr>
...@@ -173,7 +207,7 @@ function handleWantsAttachment(wants_attachment) { ...@@ -173,7 +207,7 @@ function handleWantsAttachment(wants_attachment) {
<tr> <tr>
<td>&nbsp;</td> <td>&nbsp;</td>
<td colspan="3"></td> <td colspan="3">&nbsp;</td>
</tr> </tr>
<tr> <tr>
...@@ -185,29 +219,30 @@ function handleWantsAttachment(wants_attachment) { ...@@ -185,29 +219,30 @@ function handleWantsAttachment(wants_attachment) {
</tr> </tr>
<tr> <tr>
[% IF Param('letsubmitterchoosepriority') %] [% IF Param('letsubmitterchoosepriority') %]
[% sel = { description => 'Priority', name => 'priority' } %] [% sel = { description => 'Priority', name => 'priority' } %]
[% INCLUDE select %] [% INCLUDE select %]
[% ELSE %] [% ELSE %]
<input type="hidden" name="priority" <td colspan="2">
value="[% default.priority FILTER html %]"> <input type="hidden" name="priority" value="[% default.priority FILTER html %]">
[% END %] </td>
[% END %]
[% sel = { description => 'Severity', name => 'bug_severity' } %] [% sel = { description => 'Severity', name => 'bug_severity' } %]
[% INCLUDE select %] [% INCLUDE select %]
</tr> </tr>
[% IF Param('usetargetmilestone') && Param('letsubmitterchoosemilestone') %] [% IF Param('usetargetmilestone') && Param('letsubmitterchoosemilestone') %]
<tr> <tr>
[% sel = { description => 'Target Milestone', name => 'target_milestone' } %] [% sel = { description => 'Target Milestone', name => 'target_milestone' } %]
[% INCLUDE select %] [% INCLUDE select %]
<td colspan="2"></td> <td colspan="2">&nbsp;</td>
</tr> </tr>
[% END %] [% END %]
<tr> <tr>
<td>&nbsp;</td> <td>&nbsp;</td>
<td colspan="3"></td> <td colspan="3">&nbsp;</td>
</tr> </tr>
<tr> <tr>
...@@ -220,7 +255,19 @@ function handleWantsAttachment(wants_attachment) { ...@@ -220,7 +255,19 @@ function handleWantsAttachment(wants_attachment) {
[% sel = { description => 'Initial State', name => 'bug_status' } %] [% sel = { description => 'Initial State', name => 'bug_status' } %]
[% INCLUDE select %] [% INCLUDE select %]
[% END %] [% END %]
<td colspan="2"></td> <td>&nbsp;</td>
[%# Calculate the number of rows we can use for flags %]
[% num_rows = 6 + (Param("useqacontact") ? 1 : 0) +
(UserInGroup(Param('timetrackinggroup')) ? 3 : 0) +
(Param("usebugaliases") ? 1 : 0)
%]
<td rowspan="[% num_rows FILTER html %]" valign="top">
[% IF product.flag_types.bug.size > 0 %]
[% PROCESS "flag/list.html.tmpl" flag_types = product.flag_types.bug
any_flags_requesteeble = 1
%]
[% END %]
</td>
</tr> </tr>
<tr> <tr>
...@@ -229,7 +276,7 @@ function handleWantsAttachment(wants_attachment) { ...@@ -229,7 +276,7 @@ function handleWantsAttachment(wants_attachment) {
<a href="page.cgi?id=fields.html#assigned_to">Assign To</a>: <a href="page.cgi?id=fields.html#assigned_to">Assign To</a>:
</strong> </strong>
</td> </td>
<td colspan="3"> <td colspan="2">
[% INCLUDE global/userselect.html.tmpl [% INCLUDE global/userselect.html.tmpl
name => "assigned_to" name => "assigned_to"
value => assigned_to value => assigned_to
...@@ -244,7 +291,7 @@ function handleWantsAttachment(wants_attachment) { ...@@ -244,7 +291,7 @@ function handleWantsAttachment(wants_attachment) {
[% IF Param("useqacontact") %] [% IF Param("useqacontact") %]
<tr> <tr>
<td align="right"><strong>QA Contact:</strong></td> <td align="right"><strong>QA Contact:</strong></td>
<td colspan="3"> <td colspan="2">
[% INCLUDE global/userselect.html.tmpl [% INCLUDE global/userselect.html.tmpl
name => "qa_contact" name => "qa_contact"
value => qa_contact value => qa_contact
...@@ -259,7 +306,7 @@ function handleWantsAttachment(wants_attachment) { ...@@ -259,7 +306,7 @@ function handleWantsAttachment(wants_attachment) {
<tr> <tr>
<td align="right"><strong>Cc:</strong></td> <td align="right"><strong>Cc:</strong></td>
<td colspan="3"> <td colspan="2">
[% INCLUDE global/userselect.html.tmpl [% INCLUDE global/userselect.html.tmpl
name => "cc" name => "cc"
value => cc value => cc
...@@ -272,19 +319,19 @@ function handleWantsAttachment(wants_attachment) { ...@@ -272,19 +319,19 @@ function handleWantsAttachment(wants_attachment) {
<tr> <tr>
<td>&nbsp;</td> <td>&nbsp;</td>
<td colspan="3"></td> <td colspan="2"></td>
</tr> </tr>
[% IF UserInGroup(Param('timetrackinggroup')) %] [% IF UserInGroup(Param('timetrackinggroup')) %]
<tr> <tr>
<td align="right"><strong>Estimated Hours:</strong></td> <td align="right"><strong>Estimated Hours:</strong></td>
<td colspan="3"> <td colspan="2">
<input name="estimated_time" size="6" maxlength="6" value="0.0"> <input name="estimated_time" size="6" maxlength="6" value="0.0">
</td> </td>
</tr> </tr>
<tr> <tr>
<td align="right"><strong>Deadline:</strong></td> <td align="right"><strong>Deadline:</strong></td>
<td colspan="3"> <td colspan="2">
<input name="deadline" size="10" maxlength="10" value="[% deadline FILTER html %]"> <input name="deadline" size="10" maxlength="10" value="[% deadline FILTER html %]">
<small>(YYYY-MM-DD)</small> <small>(YYYY-MM-DD)</small>
</td> </td>
...@@ -292,14 +339,14 @@ function handleWantsAttachment(wants_attachment) { ...@@ -292,14 +339,14 @@ function handleWantsAttachment(wants_attachment) {
<tr> <tr>
<td>&nbsp;</td> <td>&nbsp;</td>
<td colspan="3"></td> <td colspan="2"></td>
</tr> </tr>
[% END %] [% END %]
[% IF Param("usebugaliases") %] [% IF Param("usebugaliases") %]
<tr> <tr>
<td align="right"><strong>Alias:</strong></td> <td align="right"><strong>Alias:</strong></td>
<td colspan="3"> <td colspan="2">
<input name="alias" size="20"> <input name="alias" size="20">
</td> </td>
</tr> </tr>
...@@ -307,7 +354,7 @@ function handleWantsAttachment(wants_attachment) { ...@@ -307,7 +354,7 @@ function handleWantsAttachment(wants_attachment) {
<tr> <tr>
<td align="right"><strong>URL:</strong></td> <td align="right"><strong>URL:</strong></td>
<td colspan="3"> <td colspan="2">
<input name="bug_file_loc" size="60" <input name="bug_file_loc" size="60"
value="[% bug_file_loc FILTER html %]"> value="[% bug_file_loc FILTER html %]">
</td> </td>
...@@ -324,7 +371,7 @@ function handleWantsAttachment(wants_attachment) { ...@@ -324,7 +371,7 @@ function handleWantsAttachment(wants_attachment) {
<tr> <tr>
<td align="right"><strong>Summary:</strong></td> <td align="right"><strong>Summary:</strong></td>
<td colspan="3"> <td colspan="2">
<input name="short_desc" size="60" value="[% short_desc FILTER html %]" <input name="short_desc" size="60" value="[% short_desc FILTER html %]"
maxlength="255"> maxlength="255">
</td> </td>
...@@ -389,7 +436,8 @@ function handleWantsAttachment(wants_attachment) { ...@@ -389,7 +436,8 @@ function handleWantsAttachment(wants_attachment) {
<fieldset> <fieldset>
<legend>Add an attachment</legend> <legend>Add an attachment</legend>
<table class="attachment_entry"> <table class="attachment_entry">
[% PROCESS attachment/createformcontents.html.tmpl %] [% PROCESS attachment/createformcontents.html.tmpl
flag_types = product.flag_types.attachment %]
</table> </table>
</fieldset> </fieldset>
<script type="text/javascript"> <script type="text/javascript">
......
...@@ -407,7 +407,9 @@ ...@@ -407,7 +407,9 @@
'g.description', 'g.description',
'sel.name', 'sel.name',
'sel.description', 'sel.description',
'cloned_bug_id' 'cloned_bug_id',
'flag_count',
'f.id',
], ],
'bug/create/create-guided.html.tmpl' => [ 'bug/create/create-guided.html.tmpl' => [
......
...@@ -21,10 +21,9 @@ ...@@ -21,10 +21,9 @@
<script type="text/javascript"> <script type="text/javascript">
<!-- <!--
var stored_onload = window.onload;
// Enables or disables a requestee field depending on whether or not // Enables or disables a requestee field depending on whether or not
// the user is requesting the corresponding flag. // the user is requesting the corresponding flag.
function toggleRequesteeField(flagField) function toggleRequesteeField(flagField, no_focus)
{ {
// Convert the ID of the flag field into the ID of its corresponding // Convert the ID of the flag field into the ID of its corresponding
// requestee field and then use the ID to get the field. // requestee field and then use the ID to get the field.
...@@ -36,7 +35,7 @@ ...@@ -36,7 +35,7 @@
// of the flag field. // of the flag field.
if (flagField.value == "?") { if (flagField.value == "?") {
requesteeField.disabled = false; requesteeField.disabled = false;
requesteeField.focus(); if (!no_focus) requesteeField.focus();
} else } else
requesteeField.disabled = true; requesteeField.disabled = true;
} }
...@@ -60,9 +59,6 @@ ...@@ -60,9 +59,6 @@
inputElement.disabled = true; inputElement.disabled = true;
} }
} }
if (stored_onload) {
stored_onload();
}
} }
window.onload = disableRequesteeFields; window.onload = disableRequesteeFields;
// --> // -->
......
...@@ -386,6 +386,13 @@ ...@@ -386,6 +386,13 @@
[% END %] [% END %]
[% END %] [% END %]
[%# If we are in batch mode, we want the error message to be plain text, not HTML %]
[% USE Bugzilla %]
[% IF Bugzilla.batch %]
[% error_message FILTER none %]
[% RETURN %]
[% END %]
[% UNLESS header_done %] [% UNLESS header_done %]
[% PROCESS global/header.html.tmpl %] [% PROCESS global/header.html.tmpl %]
[% END %] [% END %]
......
...@@ -163,6 +163,11 @@ ...@@ -163,6 +163,11 @@
[%+ new_email FILTER html %] has been cancelled. [%+ new_email FILTER html %] has been cancelled.
Your old account settings have been reinstated. Your old account settings have been reinstated.
[% ELSIF message_tag == "flag_creation_failed" %]
[% title = "Flag Creation Failure" %]
An error occured while validating flags:
[%+ flag_creation_error FILTER none %]
[% ELSIF message_tag == "logged_out" %] [% ELSIF message_tag == "logged_out" %]
[% title = "Logged Out" %] [% title = "Logged Out" %]
[% url = "index.cgi?GoAheadAndLogIn=1" %] [% url = "index.cgi?GoAheadAndLogIn=1" %]
......
...@@ -1412,6 +1412,13 @@ ...@@ -1412,6 +1412,13 @@
[% END %] [% END %]
[% END %] [% END %]
[%# If we are in batch mode, we want the error message to be plain text, not HTML %]
[% USE Bugzilla %]
[% IF Bugzilla.batch %]
[% error_message FILTER none %]
[% RETURN %]
[% END %]
[% UNLESS header_done %] [% UNLESS header_done %]
[% PROCESS global/header.html.tmpl %] [% PROCESS global/header.html.tmpl %]
[% END %] [% END %]
...@@ -1438,8 +1445,7 @@ ...@@ -1438,8 +1445,7 @@
[%# If a saved search fails, people want the ability to edit or delete it. [%# If a saved search fails, people want the ability to edit or delete it.
# This is the best way of getting information about that possible saved # This is the best way of getting information about that possible saved
# search from any error call location. %] # search from any error call location. %]
[% USE Bugzilla %]
[% namedcmd = Bugzilla.cgi.param("namedcmd") %] [% namedcmd = Bugzilla.cgi.param("namedcmd") %]
[% IF namedcmd AND error != "missing_query" [% IF namedcmd AND error != "missing_query"
AND error != "saved_search_used_by_whines" %] AND error != "saved_search_used_by_whines" %]
......
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