]> git.ipfire.org Git - thirdparty/bugzilla.git/commitdiff
Bug 174039: Set flags on bug entry - Patch by Frédéric Buclin <LpSolit@gmail.com...
authorlpsolit%gmail.com <>
Tue, 25 Jul 2006 06:22:53 +0000 (06:22 +0000)
committerlpsolit%gmail.com <>
Tue, 25 Jul 2006 06:22:53 +0000 (06:22 +0000)
12 files changed:
Bugzilla/Attachment.pm
Bugzilla/Component.pm
Bugzilla/Error.pm
Bugzilla/Product.pm
attachment.cgi
post_bug.cgi
template/en/default/bug/create/create.html.tmpl
template/en/default/filterexceptions.pl
template/en/default/flag/list.html.tmpl
template/en/default/global/code-error.html.tmpl
template/en/default/global/messages.html.tmpl
template/en/default/global/user-error.html.tmpl

index f012c3f2e75468ba65ae363fadfb91754d9ddfed..90ec689742024c116d4aa8e504438d77d6282fb1 100644 (file)
@@ -51,7 +51,8 @@ use Bugzilla::Constants;
 use Bugzilla::Error;
 use Bugzilla::Flag;
 use Bugzilla::User;
-use Bugzilla::Util qw(trick_taint);
+use Bugzilla::Util;
+use Bugzilla::Field;
 
 sub get {
     my $invocant = shift;
@@ -594,12 +595,89 @@ sub validate_content_type {
 
 =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.
 
-Params:     C<$bug_id> - integer - the ID of the bug for which
-            to insert the attachment.
+Params:     C<$bug> - Bugzilla::Bug object - the bug for which to insert
+            the attachment.
             C<$user> - Bugzilla::User object - the user we're inserting an
             attachment for.
             C<$timestamp> - scalar - timestamp of the insert as returned
@@ -614,7 +692,7 @@ Returns:    the ID of the new attachment.
 =cut
 
 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 $dbh = Bugzilla->dbh;
@@ -671,8 +749,8 @@ sub insert_attachment_for_bug {
     # Setting the third param to -1 will force this function to check this
     # point.
     # XXX needs $throw_error treatment
-    Bugzilla::Flag::validate($cgi, $bug_id, -1);
-    Bugzilla::FlagType::validate($cgi, $bug_id, -1);
+    Bugzilla::Flag::validate($cgi, $bug->bug_id, -1);
+    Bugzilla::FlagType::validate($cgi, $bug->bug_id, -1);
 
     # Escape characters in strings that will be used in SQL statements.
     my $description = $cgi->param('description');
@@ -684,7 +762,7 @@ sub insert_attachment_for_bug {
         "INSERT INTO attachments
             (bug_id, creation_ts, filename, description,
              mimetype, ispatch, isurl, isprivate, submitter_id)
-         VALUES (?,?,?,?,?,?,?,?,?)", undef, ($bug_id, $timestamp, $filename,
+         VALUES (?,?,?,?,?,?,?,?,?)", undef, ($bug->bug_id, $timestamp, $filename,
               $description, $contenttype, $cgi->param('ispatch'),
               $isurl, $isprivate, $user->id));
     # Retrieve the ID of the newly created attachment record.
@@ -724,6 +802,36 @@ sub insert_attachment_for_bug {
         close AH;
         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;
 }
 
index 827be789df45a3e785b1590e00772c7bc3dd8932..abd3711f5ec9765c08f98da273a464d96ee44376 100644 (file)
@@ -13,7 +13,7 @@
 # The Original Code is the Bugzilla Bug Tracking System.
 #
 # Contributor(s): Tiago R. Mello <timello@async.com.br>
-#
+#                 Frédéric Buclin <LpSolit@gmail.com>
 
 use strict;
 
@@ -22,6 +22,7 @@ package Bugzilla::Component;
 use Bugzilla::Util;
 use Bugzilla::Error;
 use Bugzilla::User;
+use Bugzilla::FlagType;
 
 ###############################
 ####    Initialization     ####
@@ -135,6 +136,24 @@ sub 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        ####
 ###############################
@@ -193,6 +212,8 @@ Bugzilla::Component - Bugzilla product component class.
     my $product_id         = $component->product_id;
     my $default_assignee   = $component->default_assignee;
     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');
 
@@ -252,6 +273,15 @@ Component.pm represents a Product Component 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
 
 =head1 SUBROUTINES
index 5498f76708c7bf43d50f81ee767b2f666f345467..b88c4eeb88af8ae0779caa6a29c87d68646b9bf0 100644 (file)
@@ -78,7 +78,7 @@ sub _throw_error {
         my $message;
         $template->process($name, $vars, \$message)
           || ThrowTemplateError($template->error());
-        die("$message");
+        die("$message\n");
     } else {
         print Bugzilla->cgi->header();
         $template->process($name, $vars)
index 99536913092e811553cfe9ce01b63338f3272ea7..b025cd7cbfd38be0da95617c51bd134b197f64b6 100644 (file)
@@ -177,6 +177,24 @@ sub user_has_access {
           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      ######
@@ -231,6 +249,7 @@ Bugzilla::Product - Bugzilla product class.
     my $bugcount        = $product->bug_count();
     my $bug_ids         = $product->bug_ids();
     my $has_access      = $product->user_has_access($user);
+    my $flag_types      = $product->flag_types();
 
     my $id               = $product->id;
     my $name             = $product->name;
@@ -320,6 +339,15 @@ below.
  Returns      C<1> If this user's groups allow him C<entry> access to
               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
 
 =head1 SUBROUTINES
index 94f4fbe5c2d8b1395236eed7bd5f5cef1cf621fd..7f66c9984f93d437909e1b3ff2421b8f525d190a 100755 (executable)
@@ -206,24 +206,6 @@ sub validateContext
   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 
 {
     my ($attachid) = @_;
@@ -270,41 +252,6 @@ sub validatePrivate
     $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
 # 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
@@ -789,38 +736,19 @@ sub insert
     ValidateComment(scalar $cgi->param('comment'));
     my ($timestamp) = Bugzilla->dbh->selectrow_array("SELECT NOW()"); 
 
+    my $bug = new Bugzilla::Bug($bugid, $user->id);
     my $attachid =
-        Bugzilla::Attachment->insert_attachment_for_bug(THROW_ERROR,
-                                                        $bugid, $user,
+        Bugzilla::Attachment->insert_attachment_for_bug(THROW_ERROR, $bug, $user,
                                                         $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.
   my $comment = "Created an attachment (id=$attachid)\n" .
                 $cgi->param('description') . "\n";
   $comment .= ("\n" . $cgi->param('comment')) if defined $cgi->param('comment');
 
+  my $isprivate = $cgi->param('isprivate') ? 1 : 0;
   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
   my $owner = "";
   
@@ -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.
   $vars->{'mailrecipients'} =  { 'changer' => $user->login,
                                  'owner'   => $owner };
@@ -947,7 +869,7 @@ sub update
     # Retrieve and validate parameters
     ValidateComment(scalar $cgi->param('comment'));
     my ($attach_id, $bugid) = validateID();
-    validateCanEdit($attach_id);
+    Bugzilla::Attachment->validate_can_edit($attach_id);
     validateCanChangeAttachment($attach_id);
     Bugzilla::Attachment->validate_description(THROW_ERROR);
     Bugzilla::Attachment->validate_is_patch(THROW_ERROR);
@@ -1113,7 +1035,7 @@ sub delete_attachment {
 
     # Make sure the administrator is allowed to edit this attachment.
     my ($attach_id, $bug_id) = validateID();
-    validateCanEdit($attach_id);
+    Bugzilla::Attachment->validate_can_edit($attach_id);
     validateCanChangeAttachment($attach_id);
 
     my $attachment = Bugzilla::Attachment->get($attach_id);
index 083f577ac3270b35eb295d249792f6e407a50ce8..6fb054c9f5f9a2747ddfe8cbfdd76df8e59baf2c 100755 (executable)
@@ -536,11 +536,13 @@ $dbh->do("UPDATE bugs SET creation_ts = ? WHERE bug_id = ?",
 
 $dbh->bz_unlock_tables();
 
+my $bug = new Bugzilla::Bug($id, $user->id);
+
 # Add an attachment if requested.
 if (defined($cgi->upload('data')) || $cgi->param('attachurl')) {
     $cgi->param('isprivate', $cgi->param('commentprivacy'));
     Bugzilla::Attachment->insert_attachment_for_bug(!THROW_ERROR,
-                                                    $id, $user, $timestamp,
+                                                    $bug, $user, $timestamp,
                                                     \$vars)
         || ($vars->{'message'} = 'attachment_creation_failed');
 
@@ -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 
 $vars->{'mailrecipients'} = {'changer' => $user->login};
 
 $vars->{'id'} = $id;
-my $bug = new Bugzilla::Bug($id, $user->id);
 $vars->{'bug'} = $bug;
 
 ThrowCodeError("bug_error", { bug => $bug }) if $bug->error;
index 8b2bcb9972205f955f32b9301f2dadf1683eb533..bb4936861fa761832e2fdee45bb6e80206fb4807 100644 (file)
@@ -37,6 +37,7 @@
 var initialowners = new Array([% product.components.size %]);
 var last_initialowner;
 var components = new Array([% product.components.size %]);
+var flags = new Array([% product.components.size %]);
 [% IF Param("useqacontact") %]
     var initialqacontacts = new Array([% product.components.size %]);
     var last_initialqacontact;
@@ -45,6 +46,17 @@ var components = new Array([% product.components.size %]);
 [%- FOREACH c = product.components %]
     components[[% count %]] = "[% c.name 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") %]
         initialqacontacts[[% count %]] = "[% c.default_qa_contact.login FILTER js %]";
     [% END %]
@@ -53,8 +65,8 @@ var components = new Array([% product.components.size %]);
 
 function set_assign_to() {
     // Based on the selected component, fill the "Assign To:" field
-    // with the default component owner, and the the "QA Contact:" field
-    // with the default QA Contact.
+    // with the default component owner, and the "QA Contact:" field
+    // with the default QA Contact. It also selectively enables flags.
     var form = document.Create;
     var assigned_to = form.assigned_to.value;
 
@@ -87,6 +99,31 @@ function set_assign_to() {
                   last_initialqacontact = contact;
             }
         [% 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) {
 <table cellspacing="2" cellpadding="0" border="0">
 
   <tr>
-    <td><br></td>
-  </tr>
-
-  <tr>
-    <td></td>
+    <td>&nbsp;</td>
     <td colspan="3">
     [%# Migration note: The following file corresponds to the old Param
       # 'entryheaderhtml'
@@ -127,7 +160,8 @@ function handleWantsAttachment(wants_attachment) {
   </tr>
 
   <tr>
-    <td><br></td>
+    <td>&nbsp;</td>
+    <td colspan="3">&nbsp;</td>
   </tr>
 
   <tr>
@@ -173,7 +207,7 @@ function handleWantsAttachment(wants_attachment) {
 
   <tr>
     <td>&nbsp;</td>
-    <td colspan="3"></td>
+    <td colspan="3">&nbsp;</td>
   </tr>
 
   <tr>
@@ -185,29 +219,30 @@ function handleWantsAttachment(wants_attachment) {
   </tr>
 
   <tr>
-  [% IF Param('letsubmitterchoosepriority') %]
-    [% sel = { description => 'Priority', name => 'priority' } %]
-    [% INCLUDE select %]
-  [% ELSE %]
-    <input type="hidden" name="priority"
-           value="[% default.priority FILTER html %]">
-  [% END %]
+    [% IF Param('letsubmitterchoosepriority') %]
+      [% sel = { description => 'Priority', name => 'priority' } %]
+      [% INCLUDE select %]
+    [% ELSE %]
+      <td colspan="2">
+        <input type="hidden" name="priority" value="[% default.priority FILTER html %]">
+      </td>
+    [% END %]
 
-  [% sel = { description => 'Severity', name => 'bug_severity' } %]
-  [% INCLUDE select %]
+    [% sel = { description => 'Severity', name => 'bug_severity' } %]
+    [% INCLUDE select %]
   </tr>
 
   [% IF Param('usetargetmilestone') && Param('letsubmitterchoosemilestone') %]
     <tr>
-    [% sel = { description => 'Target Milestone', name => 'target_milestone' } %]
-    [% INCLUDE select %]
-    <td colspan="2"></td>
+      [% sel = { description => 'Target Milestone', name => 'target_milestone' } %]
+      [% INCLUDE select %]
+      <td colspan="2">&nbsp;</td>
     </tr>
   [% END %]
 
   <tr>
     <td>&nbsp;</td>
-    <td colspan="3"></td>
+    <td colspan="3">&nbsp;</td>
   </tr>
 
   <tr>
@@ -220,7 +255,19 @@ function handleWantsAttachment(wants_attachment) {
     [% sel = { description => 'Initial State', name => 'bug_status' } %]
     [% INCLUDE select %]
 [% 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>
@@ -229,7 +276,7 @@ function handleWantsAttachment(wants_attachment) {
         <a href="page.cgi?id=fields.html#assigned_to">Assign To</a>:
       </strong>
     </td>
-    <td colspan="3">
+    <td colspan="2">
       [% INCLUDE global/userselect.html.tmpl
          name => "assigned_to"
          value => assigned_to
@@ -244,7 +291,7 @@ function handleWantsAttachment(wants_attachment) {
 [% IF Param("useqacontact") %]
     <tr>
       <td align="right"><strong>QA Contact:</strong></td>
-      <td colspan="3">
+      <td colspan="2">
       [% INCLUDE global/userselect.html.tmpl
          name => "qa_contact"
          value => qa_contact
@@ -259,7 +306,7 @@ function handleWantsAttachment(wants_attachment) {
 
   <tr>
     <td align="right"><strong>Cc:</strong></td>
-    <td colspan="3">
+    <td colspan="2">
       [% INCLUDE global/userselect.html.tmpl
          name => "cc"
          value => cc
@@ -272,19 +319,19 @@ function handleWantsAttachment(wants_attachment) {
   
   <tr>
     <td>&nbsp;</td>
-    <td colspan="3"></td>
+    <td colspan="2"></td>
   </tr>
 
 [% IF UserInGroup(Param('timetrackinggroup')) %]
   <tr>
     <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">
     </td>
   </tr>
   <tr>
     <td align="right"><strong>Deadline:</strong></td>
-    <td colspan="3">
+    <td colspan="2">
       <input name="deadline" size="10" maxlength="10" value="[% deadline FILTER html %]">
       <small>(YYYY-MM-DD)</small>
     </td>
@@ -292,14 +339,14 @@ function handleWantsAttachment(wants_attachment) {
 
   <tr>
     <td>&nbsp;</td>
-    <td colspan="3"></td>
+    <td colspan="2"></td>
   </tr>
 [% END %]
 
 [% IF Param("usebugaliases") %]
   <tr>
     <td align="right"><strong>Alias:</strong></td>
-    <td colspan="3">
+    <td colspan="2">
       <input name="alias" size="20">
     </td>
   </tr>
@@ -307,7 +354,7 @@ function handleWantsAttachment(wants_attachment) {
 
   <tr>
     <td align="right"><strong>URL:</strong></td>
-    <td colspan="3">
+    <td colspan="2">
       <input name="bug_file_loc" size="60"
              value="[% bug_file_loc FILTER html %]">
     </td>
@@ -324,7 +371,7 @@ function handleWantsAttachment(wants_attachment) {
 
   <tr>
     <td align="right"><strong>Summary:</strong></td>
-    <td colspan="3">
+    <td colspan="2">
       <input name="short_desc" size="60" value="[% short_desc FILTER html %]"
              maxlength="255">
     </td>
@@ -389,7 +436,8 @@ function handleWantsAttachment(wants_attachment) {
         <fieldset>
           <legend>Add an attachment</legend>
           <table class="attachment_entry">
-            [% PROCESS attachment/createformcontents.html.tmpl %]
+            [% PROCESS attachment/createformcontents.html.tmpl
+                       flag_types = product.flag_types.attachment %]
           </table>
         </fieldset>
       <script type="text/javascript">
index 78bbd27dc01149bd45a75e7246811e00332c5f21..bc2ee0fa8f0abc42732c517971802f6770370ad3 100644 (file)
   'g.description',
   'sel.name',
   'sel.description',
-  'cloned_bug_id'
+  'cloned_bug_id',
+  'flag_count',
+  'f.id',
 ],
 
 'bug/create/create-guided.html.tmpl' => [
index 7a92f127776ed55f4c0597982359fa128933e353..1cf71025071a09ed065e78041a34068b87a9ed60 100644 (file)
 
 <script type="text/javascript">
 <!-- 
-  var stored_onload = window.onload;
   // Enables or disables a requestee field depending on whether or not
   // 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
     // requestee field and then use the ID to get the field.
@@ -36,7 +35,7 @@
     // of the flag field.
     if (flagField.value == "?") {
         requesteeField.disabled = false;
-        requesteeField.focus();
+        if (!no_focus) requesteeField.focus();
     } else                         
         requesteeField.disabled = true;
   }
@@ -60,9 +59,6 @@
             inputElement.disabled = true;
       }
     }
-    if (stored_onload) {
-        stored_onload();
-    }
   }
   window.onload = disableRequesteeFields;
 // -->
index 18e478300acaf576e4bb64eb6bc8c4c8c570a63e..a131d25d6c82a2843b88abed5eff0cffa8e5e76b 100644 (file)
   [% 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 %]
   [% PROCESS global/header.html.tmpl %]
 [% END %]
index bb8a08fddb5a2bcfdbf1eacdc3e924841e9480f3..45b584bea49b5f604c60a4324817d5f334c89cbc 100644 (file)
     [%+ new_email FILTER html %] has been cancelled.
    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" %]
     [% title = "Logged Out" %]
     [% url = "index.cgi?GoAheadAndLogIn=1" %]
index 1827da090c20f51d81fc6d68cdbe6c412025ffa7..6b939070120b07ec6517fed25e54ac48e76323e0 100644 (file)
   [% 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 %]
   [% PROCESS global/header.html.tmpl %]
 [% END %]
 [%# 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
   # search from any error call location. %]
-  
-[% USE Bugzilla %]
+
 [% namedcmd = Bugzilla.cgi.param("namedcmd") %]
 [% IF namedcmd AND error != "missing_query" 
                AND error != "saved_search_used_by_whines" %]