]> git.ipfire.org Git - thirdparty/bugzilla.git/commitdiff
Bug 319067: editflagtypes.cgi should allow to filter flag types based on their produc...
authorlpsolit%gmail.com <>
Thu, 15 Jun 2006 04:20:52 +0000 (04:20 +0000)
committerlpsolit%gmail.com <>
Thu, 15 Jun 2006 04:20:52 +0000 (04:20 +0000)
editflagtypes.cgi
template/en/default/admin/flag-type/edit.html.tmpl
template/en/default/admin/flag-type/list.html.tmpl
template/en/default/global/code-error.html.tmpl
template/en/default/global/js-products.html.tmpl [new file with mode: 0644]
template/en/default/global/user-error.html.tmpl
template/en/default/request/queue.html.tmpl

index 8f6bf601f658de67697f67a82bd331723eeea3d3..822f00744ca5400815fa6c700c208b877a047705 100755 (executable)
@@ -42,6 +42,8 @@ use Bugzilla::Util;
 use Bugzilla::Product;
 use Bugzilla::Component;
 
+use List::Util qw(reduce);
+
 my $template = Bugzilla->template;
 my $vars = {};
 
@@ -92,13 +94,54 @@ exit;
 ################################################################################
 
 sub list {
+    # Restrict the list to the given product and component, if given.
+    $vars = get_products_and_components($vars);
+
+    my $product = validateProduct(scalar $cgi->param('product'));
+    my $component = validateComponent($product, scalar $cgi->param('component'));
+    my $product_id = $product ? $product->id : 0;
+    my $component_id = $component ? $component->id : 0;
+
     # Define the variables and functions that will be passed to the UI template.
-    $vars->{'bug_types'} = 
-      Bugzilla::FlagType::match({ 'target_type' => 'bug', 
-                                  'group' => scalar $cgi->param('group') }, 1);
-    $vars->{'attachment_types'} = 
-      Bugzilla::FlagType::match({ 'target_type' => 'attachment', 
-                                  'group' => scalar $cgi->param('group') }, 1);
+    $vars->{'selected_product'} = $cgi->param('product');
+    $vars->{'selected_component'} = $cgi->param('component');
+
+    # If only a product was specified but no component, then we restrict
+    # the list to flag types available in ALL components of that product.
+    my @comp_ids = ($component_id);
+    if ($product_id && !$component_id) {
+        @comp_ids = map {$_->id} @{$product->components};
+    }
+
+    my @bug_flagtypes;
+    my @attach_flagtypes;
+
+    foreach my $comp_id (@comp_ids) {
+        my $bug_types =
+          Bugzilla::FlagType::match({ 'target_type' => 'bug',
+                                      'group' => scalar $cgi->param('group'),
+                                      'product_id' => $product_id,
+                                      'component_id' => $comp_id }, 1);
+        push(@bug_flagtypes, $bug_types);
+
+        my $attach_types =
+          Bugzilla::FlagType::match({ 'target_type' => 'attachment',
+                                      'group' => scalar $cgi->param('group'),
+                                      'product_id' => $product_id,
+                                      'component_id' => $comp_id }, 1);
+        push(@attach_flagtypes, $attach_types);
+    }
+
+    sub intersection {
+        my ($aa, $bb) = @_;
+        my %union;
+        my %isect;
+        foreach my $e (@$aa, @$bb) { $union{$e->{'id'}}++ && ($isect{$e->{'id'}} ||= $e) };
+        return [sort { $a->{'sortkey'} <=> $b->{'sortkey'}
+                       || $a->{'name'} cmp $b->{'name'} } values %isect];
+    }
+    $vars->{'bug_types'} = reduce { intersection($a, $b) } @bug_flagtypes;
+    $vars->{'attachment_types'} = reduce { intersection($a, $b) } @attach_flagtypes;
 
     # Users want to see group names, not IDs
     # So get the group names
@@ -127,16 +170,8 @@ sub edit {
     $action eq 'enter' ? validateTargetType() : (my $id = validateID());
     my $dbh = Bugzilla->dbh;
 
-    my @products = Bugzilla::Product::get_all_products();
-    # We require all unique component names.
-    my %components;
-    foreach my $product (@products) {
-        foreach my $component (@{$product->components}) {
-            $components{$component->name} = 1;
-        }
-    }
-    $vars->{'products'} = \@products;
-    $vars->{'components'} = [sort(keys %components)];
+    # Fill $vars with products and components data.
+    $vars = get_products_and_components($vars);
 
     $vars->{'last_action'} = $cgi->param('action');
     if ($cgi->param('action') eq 'enter' || $cgi->param('action') eq 'copy') {
@@ -217,16 +252,8 @@ sub processCategoryChange {
     my %inclusions = clusion_array_to_hash(\@inclusions);
     my %exclusions = clusion_array_to_hash(\@exclusions);
 
-    my @products = Bugzilla::Product::get_all_products();
-    # We require all unique component names.
-    my %components;
-    foreach my $product (@products) {
-        foreach my $component (@{$product->components}) {
-            $components{$component->name} = 1;
-        }
-    }
-    $vars->{'products'} = \@products;
-    $vars->{'components'} = [sort(keys %components)];
+    # Fill $vars with products and components data.
+    $vars = get_products_and_components($vars);
 
     my @groups = Bugzilla::Group::get_all_groups();
     $vars->{'groups'} = \@groups;
@@ -475,6 +502,21 @@ sub deactivate {
       || ThrowTemplateError($template->error());
 }
 
+sub get_products_and_components {
+    my $vars = shift;
+
+    my @products = Bugzilla::Product::get_all_products();
+    # We require all unique component names.
+    my %components;
+    foreach my $product (@products) {
+        foreach my $component (@{$product->components}) {
+            $components{$component->name} = 1;
+        }
+    }
+    $vars->{'products'} = \@products;
+    $vars->{'components'} = [sort(keys %components)];
+    return $vars;
+}
 
 ################################################################################
 # Data Validation / Security Authorization
@@ -550,7 +592,7 @@ sub validateComponent {
     return unless $component_name;
 
     ($product && $product->id)
-      || ThrowCodeError("flag_type_component_without_product");
+      || ThrowUserError("flag_type_component_without_product");
 
     my $component = Bugzilla::Component::check_component($product, $component_name);
     return $component;
index cb3ce9e172042991b0dfa6035206d674dbf9182f..483a5d2de7745458b6df5cf0451b95fe5d7d6975 100644 (file)
 
 [% PROCESS global/variables.none.tmpl %]
 
-[%# The javascript block gets used in header.html.tmpl. %]
-[% javascript = BLOCK %]
-  var usetms = 0; // do we have target milestone?
-  var first_load = 1; // is this the first time we load the page?
-  var last_sel = []; // caches last selection
-  var cpts = new Array();
-  [% FOREACH prod = products %]
-    cpts['[% prod.name FILTER js %]'] = [
-      [%- FOREACH comp = prod.components %]'[% comp.name FILTER js %]'[% ", " UNLESS loop.last %] [%- END -%] ];
-  [% END %]
-[% END %]
+[% PROCESS "global/js-products.html.tmpl" %]
 
 [% IF type.target_type == "bug" %]
   [% title = BLOCK %]Create Flag Type for [% terms.Bugs %][% END %]
index a9dc40519f34594261cb2cc684333b354bd1061b..7ca897ecd66f91e2a5a5591d1e2be5f01b9dfe4d 100644 (file)
@@ -21,6 +21,8 @@
 
 [% PROCESS global/variables.none.tmpl %]
 
+[% PROCESS "global/js-products.html.tmpl" %]
+
 [% PROCESS global/header.html.tmpl
   title = 'Administer Flag Types'
   style = "
@@ -28,6 +30,8 @@
     .inactive { color: #787878; }
     .multiplicable { display: block; }
   "
+  onload="selectProduct(document.forms[0], 'product', 'component', '__All__');"
+  javascript_urls=["productmenu.js"]
 %]
 
 <p>
   depending on whether the patch passed or failed review.
 </p>
 
+<p>
+  You can restrict the list of flag types to those available for a given product
+  and component. If a product is selected with no component, only flag types
+  which are available to ALL components of the product are shown.
+</p>
+
+<form action="editflagtypes.cgi" method="get">
+  <table>
+    <tr>
+      <th><label for="product">Product:</label></th>
+      <td>
+        <select name="product" onchange="selectProduct(this.form, 'product', 'component', '__All__');">
+          <option value="">__All__</option>
+          [% FOREACH prod = products %]
+            <option value="[% prod.name FILTER html %]"
+                    [% " selected" IF selected_product == prod.name %]>
+                    [% prod.name FILTER html %]</option>
+          [% END %]
+        </select>
+      </td>
+      <th><label for="component">Component:</label></th>
+      <td>
+        <select name="component">
+          <option value="">__All__</option>
+          [% FOREACH comp = components %]
+            <option value="[% comp FILTER html %]"
+                    [% " selected" IF selected_component == comp %]>
+                    [% comp FILTER html %]</option>
+          [% END %]
+        </select>
+      </td>
+      <td><input type="submit" id="submit" value="Filter"></td>
+    </tr>
+  </table>
+</form>
+
 <h3>Flag Types for [% terms.Bugs %]</h3>
 
 [% PROCESS display_flag_types types=bug_types %]
index 5081589edd65054dfa8bd6e9e2388d3e2b009da2..e1dfe57d92e9bc777646643109900b44767b917f 100644 (file)
     [% END %]
     is invalid.
 
-  [% ELSIF error == "flag_type_component_without_product" %]
-    A component was selected without a product being selected.
-  
   [% ELSIF error == "flag_type_id_invalid" %]
     The flag type ID <em>[% id FILTER html %]</em> is not
     a positive integer.
diff --git a/template/en/default/global/js-products.html.tmpl b/template/en/default/global/js-products.html.tmpl
new file mode 100644 (file)
index 0000000..57126f0
--- /dev/null
@@ -0,0 +1,33 @@
+[%# 1.0@bugzilla.org %]
+[%# 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 Netscape Communications
+  # Corporation. Portions created by Netscape are
+  # Copyright (C) 1998 Netscape Communications Corporation. All
+  # Rights Reserved.
+  #
+  # Contributor(s): Myk Melez <myk@mozilla.org>
+  #                 Frédéric Buclin <LpSolit@gmail.com>
+  #%]
+
+[%# The javascript block gets used in header.html.tmpl. %]
+[% javascript = BLOCK %]
+  var usetms = 0; // do we have target milestone?
+  var first_load = 1; // is this the first time we load the page?
+  var last_sel = []; // caches last selection
+  var cpts = new Array();
+  [% FOREACH prod = products %]
+    cpts['[% prod.name FILTER js %]'] = [
+      [%- FOREACH comp = prod.components %]'[% comp.name FILTER js %]'[% ", " UNLESS loop.last %] [%- END -%] ];
+  [% END %]
+[% END %]
index 49375de0e349a3f511411455819453b2ec6aceb8..dd2e529c2029d97f88f9645948394e8851e2ed03 100644 (file)
     [% admindocslinks = {'flags-overview.html#flags-admin'  => 'Administering Flags'} %]
     The CC list [% cc_list FILTER html %] must be less than 200 characters long.
 
+  [% ELSIF error == "flag_type_component_without_product" %]
+    [% title = "Product Missing" %]
+    A component was selected without a product being selected.
+
   [% ELSIF error == "flag_type_description_invalid" %]
     [% title = "Flag Type Description Invalid" %]
     [% admindocslinks = {'flags-overview.html#flags-admin'  => 'Administering Flags'} %]
index 73bbd8195fb45d36b5d4063465c82e8e976b7329..573e95bfa628ea195c5ad5a089dca0616f2a8cb2 100644 (file)
 [% USE Bugzilla %]
 [% cgi = Bugzilla.cgi %]
 
-[%# The javascript block gets used in header.html.tmpl. %]
-[% javascript = BLOCK %]
-  var usetms = 0; // do we have target milestone?
-  var first_load = 1; // is this the first time we load the page?
-  var last_sel = []; // caches last selection
-  var cpts = new Array();
-  [% FOREACH prod = products %]
-    cpts['[% prod.name FILTER js %]'] = [
-      [%- FOREACH comp = prod.components %]'[% comp.name FILTER js %]'[% ", " UNLESS loop.last %] [%- END -%] ];
-  [% END %]
-[% END %]
+[% PROCESS "global/js-products.html.tmpl" %]
 
 [% PROCESS global/header.html.tmpl
   title="Request Queue"