]> git.ipfire.org Git - thirdparty/bugzilla.git/commitdiff
Bug 1252298 - Feature Request: Issue Templates for Components
authorKohei Yoshino <kohei.yoshino@gmail.com>
Thu, 18 Jul 2019 18:27:28 +0000 (14:27 -0400)
committerdklawren <dklawren@users.noreply.github.com>
Thu, 18 Jul 2019 18:27:28 +0000 (14:27 -0400)
Bugzilla/Component.pm
editcomponents.cgi
template/en/default/admin/components/edit-common.html.tmpl
template/en/default/bug/create/create.html.tmpl

index 73a258d31b4d2a2ccb0ff806d87cecbbfb188a56..b8e7f61531c7ad82132b4a0135fd002e13821662 100644 (file)
@@ -52,6 +52,7 @@ use constant UPDATE_COLUMNS => qw(
   description
   isactive
   triage_owner_id
+  bug_description_template
 );
 
 use constant REQUIRED_FIELD_MAP => {product_id => 'product',};
@@ -324,6 +325,7 @@ sub set_name             { $_[0]->set('name',             $_[1]); }
 sub set_description      { $_[0]->set('description',      $_[1]); }
 sub set_is_active        { $_[0]->set('isactive',         $_[1]); }
 sub set_default_bug_type { $_[0]->set('default_bug_type', $_[1]); }
+sub set_bug_description_template { $_[0]->set('bug_description_template', $_[1]); }
 
 sub set_default_assignee {
   my ($self, $owner) = @_;
@@ -374,6 +376,22 @@ sub bug_count {
   return $self->{'bug_count'};
 }
 
+# Lazy-load the bug_description_template column. If the component-specific
+# template is not found, look for the product's template instead. Can be empty.
+sub bug_description_template {
+  my $self = shift;
+
+  if (!exists $self->{'bug_description_template'}) {
+    my ($comp_template, $prod_template) = Bugzilla->dbh->selectrow_array('
+      SELECT c.bug_description_template, p.bug_description_template
+      FROM components AS c INNER JOIN products AS p ON c.product_id = p.id
+      WHERE c.id = ?', undef, $self->id);
+    $self->{'bug_description_template'} = $comp_template || $prod_template;
+  }
+
+  return $self->{'bug_description_template'};
+}
+
 sub bug_ids {
   my $self = shift;
   my $dbh  = Bugzilla->dbh;
@@ -535,6 +553,7 @@ Bugzilla::Component - Bugzilla product component class.
     my $product            = $component->product;
     my $bug_flag_types     = $component->flag_types->{'bug'};
     my $attach_flag_types  = $component->flag_types->{'attachment'};
+    my $bug_desc_template  = $component->bug_description_template;
 
     my $component = Bugzilla::Component->check({ product => $product, name => $name });
 
@@ -554,6 +573,7 @@ Bugzilla::Component - Bugzilla product component class.
     $component->set_default_qa_contact($new_login_name);
     $component->set_cc_list(\@new_login_names);
     $component->set_triage_owner($new_triage_owner);
+    $component->set_bug_description_template($new_template);
     $component->update();
 
     $component->remove_from_db;
@@ -589,6 +609,16 @@ Component.pm represents a Product Component object.
 
  Returns:     Integer with the number of bugs.
 
+=item C<bug_description_template()>
+
+ Description: Returns the default description text for new bugs filed under this
+              component. If missing, the product's template, if any, will be
+              returned.
+
+ Params:      none.
+
+ Returns:     A string.
+
 =item C<bugs_ids()>
 
  Description: Returns all bug IDs that belong to the component.
@@ -680,6 +710,15 @@ Component.pm represents a Product Component object.
 
  Returns:     a new Bugzilla::FlagType object or undef
 
+=item C<set_bug_description_template($new_template)>
+
+ Description: Changes the default description text for new bugs filed under this
+              component.
+
+ Params:      $new_template - new description template of the component (string).
+
+ Returns:     Nothing.
+
 =item C<set_description($new_desc)>
 
  Description: Changes the description of the component.
index 23922e53373277b8c6efdd22abf97b62fdb91609..29d4f68523541eee1681cfb5eff9e9a16214355d 100755 (executable)
@@ -120,6 +120,7 @@ if ($action eq 'new') {
   my @initial_cc         = $cgi->param('initialcc');
   my $isactive           = $cgi->param('isactive');
   my $default_bug_type   = $cgi->param('default_bug_type');
+  my $bug_desc_template  = $cgi->param('bug_description_template');
 
   my $component = Bugzilla::Component->create({
     name             => $comp_name,
@@ -130,6 +131,7 @@ if ($action eq 'new') {
     initial_cc       => \@initial_cc,
     triage_owner_id  => $triage_owner,
     default_bug_type => $default_bug_type,
+    bug_description_template => $bug_desc_template,
 
     # XXX We should not be creating series for products that we
     # didn't create series for.
@@ -230,6 +232,7 @@ if ($action eq 'update') {
   my $triage_owner       = trim($cgi->param('triage_owner')     || '');
   my @initial_cc         = $cgi->param('initialcc');
   my $isactive           = $cgi->param('isactive');
+  my $bug_desc_template  = $cgi->param('bug_description_template'),
 
   my $component
     = Bugzilla::Component->check({product => $product, name => $comp_old_name});
@@ -242,6 +245,7 @@ if ($action eq 'update') {
   $component->set_triage_owner($triage_owner);
   $component->set_cc_list(\@initial_cc);
   $component->set_is_active($isactive);
+  $component->set_bug_description_template($bug_desc_template);
   my $changes = $component->update();
 
   $vars->{'message'} = 'component_updated';
index cbeda3a7b2d4bb66b6f2a6f81eaf1cafda59f4a5..094357fca57dbb39b8282dfaf3d5c9af1ca88674 100644 (file)
     %]
   </td>
 </tr>
+<tr>
+  <th class="field_label"><label for="bug_description_template">New [% terms.bug %] comment template:</label></th>
+  <td><textarea rows="8" cols="64" wrap="virtual" name="bug_description_template"
+                placeholder="[% product.bug_description_template FILTER html %]">
+        [% comp.bug_description_template FILTER html %]</textarea>
+  </td>
+</tr>
 <tr>
   <th class="field_label"><label for="default_bug_type">Default [% terms.Bug %] Type:</label></th>
   <td>
index a01725c91c17bdc2bdeea8cd9a46702f9949e82a..ef4a700887a38d1413988c258eefd5834fc5cf6b 100644 (file)
@@ -55,6 +55,10 @@ function init() {
   document.querySelector('#bug_type').addEventListener('change', () => {
     bug_type_specified = true;
   }, { once: true });
+
+  document.querySelector('#comment').addEventListener('input', () => {
+    desc_edited = true;
+  }, { once: true });
 }
 
 function initCrashSignatureField() {
@@ -70,10 +74,12 @@ function initCrashSignatureField() {
 
 const params = new URLSearchParams(location.search);
 let bug_type_specified = params.has('bug_type') || params.has('cloned_bug_id') || params.has('regressed_by');
+let desc_edited = false;
 
 var initialowners = new Array([% product.components.size %]);
 var last_initialowner;
 var default_bug_types = new Array([% product.components.size %]);
+var desc_templates = new Array([% product.components.size %]);
 var initialccs = new Array([% product.components.size %]);
 var components = new Array([% product.components.size %]);
 var comp_desc = new Array([% product.components.size %]);
@@ -89,6 +95,7 @@ var flags = new Array([% product.components.size %]);
     comp_desc[[% count %]] = "[% comp.description FILTER html_light FILTER js %]";
     initialowners[[% count %]] = "[% comp.default_assignee.login FILTER js %]";
     default_bug_types[[% count %]] = "[% comp.default_bug_type FILTER js %]";
+    desc_templates[[% count %]] = "[% comp.bug_description_template.replace('\\r', '') FILTER js %]";
     [% flag_list = [] %]
     [% FOREACH f = comp.flag_types.bug %]
       [% flag_list.push(f.id) %]
@@ -142,6 +149,13 @@ function set_assign_to() {
           form.bug_type.value = default_bug_types[index];
         }
 
+        // Fill the Description field with the product- or component-specific
+        // template if defined. Skip if the Description is edited by the user.
+        const desc_template = desc_templates[index];
+        if ((!desc_edited && form.comment.value !== desc_template) || !form.comment.value) {
+          form.comment.value = desc_template;
+        }
+
         document.getElementById('initial_cc').innerHTML = initialccs[index];
         document.getElementById('comp_desc').innerHTML = comp_desc[index];