diff options
author | lpsolit%gmail.com <> | 2006-06-15 06:20:52 +0200 |
---|---|---|
committer | lpsolit%gmail.com <> | 2006-06-15 06:20:52 +0200 |
commit | 48b0cf3844779964de405a3139f8c0b3f0d7dc56 (patch) | |
tree | 7cb6dafbf489f37f14de53a194eb7dcfeb03254b | |
parent | a59456eb3675e8d716f9516a4f9f0c140da29c9f (diff) | |
download | bugzilla-48b0cf3844779964de405a3139f8c0b3f0d7dc56.tar.gz bugzilla-48b0cf3844779964de405a3139f8c0b3f0d7dc56.tar.xz |
Bug 319067: editflagtypes.cgi should allow to filter flag types based on their product/component - Patch by Frédéric Buclin <LpSolit@gmail.com> r=wicked a=myk
-rwxr-xr-x | editflagtypes.cgi | 96 | ||||
-rw-r--r-- | template/en/default/admin/flag-type/edit.html.tmpl | 12 | ||||
-rw-r--r-- | template/en/default/admin/flag-type/list.html.tmpl | 40 | ||||
-rw-r--r-- | template/en/default/global/code-error.html.tmpl | 3 | ||||
-rw-r--r-- | template/en/default/global/js-products.html.tmpl | 33 | ||||
-rw-r--r-- | template/en/default/global/user-error.html.tmpl | 4 | ||||
-rw-r--r-- | template/en/default/request/queue.html.tmpl | 12 |
7 files changed, 148 insertions, 52 deletions
diff --git a/editflagtypes.cgi b/editflagtypes.cgi index 8f6bf601f..822f00744 100755 --- a/editflagtypes.cgi +++ b/editflagtypes.cgi @@ -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; diff --git a/template/en/default/admin/flag-type/edit.html.tmpl b/template/en/default/admin/flag-type/edit.html.tmpl index cb3ce9e17..483a5d2de 100644 --- a/template/en/default/admin/flag-type/edit.html.tmpl +++ b/template/en/default/admin/flag-type/edit.html.tmpl @@ -22,17 +22,7 @@ [% 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 %] diff --git a/template/en/default/admin/flag-type/list.html.tmpl b/template/en/default/admin/flag-type/list.html.tmpl index a9dc40519..7ca897ecd 100644 --- a/template/en/default/admin/flag-type/list.html.tmpl +++ b/template/en/default/admin/flag-type/list.html.tmpl @@ -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> @@ -44,6 +48,42 @@ 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 %] diff --git a/template/en/default/global/code-error.html.tmpl b/template/en/default/global/code-error.html.tmpl index 5081589ed..e1dfe57d9 100644 --- a/template/en/default/global/code-error.html.tmpl +++ b/template/en/default/global/code-error.html.tmpl @@ -227,9 +227,6 @@ [% 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 index 000000000..57126f004 --- /dev/null +++ b/template/en/default/global/js-products.html.tmpl @@ -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 %] diff --git a/template/en/default/global/user-error.html.tmpl b/template/en/default/global/user-error.html.tmpl index 49375de0e..dd2e529c2 100644 --- a/template/en/default/global/user-error.html.tmpl +++ b/template/en/default/global/user-error.html.tmpl @@ -473,6 +473,10 @@ [% 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'} %] diff --git a/template/en/default/request/queue.html.tmpl b/template/en/default/request/queue.html.tmpl index 73bbd8195..573e95bfa 100644 --- a/template/en/default/request/queue.html.tmpl +++ b/template/en/default/request/queue.html.tmpl @@ -24,17 +24,7 @@ [% 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" |