]> git.ipfire.org Git - thirdparty/bugzilla.git/commitdiff
Bug 487508: Allow restricting the visibility of custom fields and values by component
authorMax Kanat-Alexander <mkanat@bugzilla.org>
Tue, 2 Feb 2010 01:34:26 +0000 (17:34 -0800)
committerMax Kanat-Alexander <mkanat@bugzilla.org>
Tue, 2 Feb 2010 01:34:26 +0000 (17:34 -0800)
r=dkl, a=mkanat

21 files changed:
Bugzilla/Component.pm
Bugzilla/Constants.pm
Bugzilla/Field.pm
Bugzilla/Field/Choice.pm
Bugzilla/Migrate.pm
Bugzilla/Product.pm
Bugzilla/Search.pm
Bugzilla/Status.pm
Bugzilla/WebService/Bug.pm
editvalues.cgi
report.cgi
template/en/default/admin/custom_fields/cf-js.js.tmpl
template/en/default/admin/custom_fields/edit.html.tmpl
template/en/default/admin/fieldvalues/create.html.tmpl
template/en/default/admin/fieldvalues/edit.html.tmpl
template/en/default/bug/create/create.html.tmpl
template/en/default/bug/edit.html.tmpl
template/en/default/bug/field-events.js.tmpl
template/en/default/bug/field.html.tmpl
template/en/default/global/user-error.html.tmpl
template/en/default/list/edit-multiple.html.tmpl

index 194a3957c78fdf4cbaa84777024250f592e0ce48..5fb9110318ea25e25faef21ac006bce0934b7f4f 100644 (file)
 #                 Max Kanat-Alexander <mkanat@bugzilla.org>
 #                 Akamai Technologies <bugzilla-dev@akamai.com>
 
-use strict;
-
 package Bugzilla::Component;
-
-use base qw(Bugzilla::Object);
+use strict;
+use base qw(Bugzilla::Field::ChoiceInterface Bugzilla::Object);
 
 use Bugzilla::Constants;
 use Bugzilla::Util;
@@ -35,6 +33,8 @@ use Bugzilla::Series;
 ###############################
 
 use constant DB_TABLE => 'components';
+# This is mostly for the editfields.cgi case where ->get_all is called.
+use constant LIST_ORDER => 'product_id, name';
 
 use constant DB_COLUMNS => qw(
     id
@@ -80,7 +80,7 @@ sub new {
     my $dbh = Bugzilla->dbh;
 
     my $product;
-    if (ref $param) {
+    if (ref $param and !defined $param->{id}) {
         $product = $param->{product};
         my $name = $param->{name};
         if (!defined $product) {
@@ -156,6 +156,8 @@ sub remove_from_db {
     my $self = shift;
     my $dbh = Bugzilla->dbh;
 
+    $self->_check_if_controller(); # From ChoiceInterface
+
     $dbh->bz_start_transaction();
 
     if ($self->bug_count) {
@@ -418,11 +420,25 @@ sub product {
 ####      Accessors        ####
 ###############################
 
-sub id          { return $_[0]->{'id'};          }
-sub name        { return $_[0]->{'name'};        }
 sub description { return $_[0]->{'description'}; }
 sub product_id  { return $_[0]->{'product_id'};  }
 
+##############################################
+# Implement Bugzilla::Field::ChoiceInterface #
+##############################################
+
+use constant FIELD_NAME => 'component';
+use constant is_default => 0;
+use constant is_active => 1;
+
+sub is_set_on_bug {
+    my ($self, $bug) = @_;
+    # We treat it like a hash always, so that we don't have to check if it's
+    # a hash or an object.
+    return 0 if !defined $bug->{component_id};
+    $bug->{component_id} == $self->id ? 1 : 0;
+}
+
 ###############################
 ####      Subroutines      ####
 ###############################
index 94d9f8bed4c2b63e30aa28c6aa7d96fd6d8309d5..948ff5337811949c4a812a550e31468c89d42ac8 100644 (file)
@@ -129,6 +129,8 @@ use File::Basename;
     FIELD_TYPE_BUG_ID
     FIELD_TYPE_BUG_URLS
 
+    ABNORMAL_SELECTS
+
     TIMETRACKING_FIELDS
 
     USAGE_MODE_BROWSER
@@ -368,6 +370,13 @@ use constant FIELD_TYPE_DATETIME  => 5;
 use constant FIELD_TYPE_BUG_ID  => 6;
 use constant FIELD_TYPE_BUG_URLS => 7;
 
+# See the POD for Bugzilla::Field/is_abnormal to see why these are listed
+# here.
+use constant ABNORMAL_SELECTS => qw(
+    product
+    component
+);
+
 # The fields from fielddefs that are blocked from non-timetracking users.
 # work_time is sometimes called actual_time.
 use constant TIMETRACKING_FIELDS =>
index 7b1569c520209552360a0e70bfd92f81295541a9..2f14037abc5f1720268875c09d0107aecaedb5c6 100644 (file)
@@ -180,7 +180,7 @@ use constant DEFAULT_FIELDS => (
     {name => 'priority',     desc => 'Priority',   in_new_bugmail => 1,
      type => FIELD_TYPE_SINGLE_SELECT, buglist => 1},
     {name => 'component',    desc => 'Component',  in_new_bugmail => 1,
-     buglist => 1},
+     type => FIELD_TYPE_SINGLE_SELECT, buglist => 1},
     {name => 'assigned_to',  desc => 'AssignedTo', in_new_bugmail => 1,
      buglist => 1},
     {name => 'reporter',     desc => 'ReportedBy', in_new_bugmail => 1,
@@ -492,6 +492,28 @@ sub is_select {
             || $_[0]->type == FIELD_TYPE_MULTI_SELECT) ? 1 : 0 
 }
 
+=over
+
+=item C<is_abnormal>
+
+Most fields that have a C<SELECT> L</type> have a certain schema for
+the table that stores their values, the table has the same name as the field,
+and the field's legal values can be edited via F<editvalues.cgi>.
+
+However, some fields do not follow that pattern. Those fields are
+considered "abnormal".
+
+This method returns C<1> if the field is "abnormal", C<0> otherwise.
+
+=back
+
+=cut
+
+sub is_abnormal {
+    my $self = shift;
+    return grep($_ eq $self->name, ABNORMAL_SELECTS) ? 1 : 0;
+}
+
 sub legal_values {
     my $self = shift;
 
index 7e07ca1e2a159df18916913d82783e73660f6f01..9c2fbdb38028b27b19e1126a55b5569953dbafa4 100644 (file)
@@ -23,7 +23,7 @@ use strict;
 
 package Bugzilla::Field::Choice;
 
-use base qw(Bugzilla::Object);
+use base qw(Bugzilla::Field::ChoiceInterface Bugzilla::Object);
 
 use Bugzilla::Config qw(SetParam write_params);
 use Bugzilla::Constants;
@@ -66,6 +66,7 @@ use constant VALIDATORS => {
 
 use constant CLASS_MAP => {
     bug_status => 'Bugzilla::Status',
+    component  => 'Bugzilla::Component',
     product    => 'Bugzilla::Product',
 };
 
@@ -194,115 +195,10 @@ sub remove_from_db {
         ThrowUserError("fieldvalue_still_has_bugs",
                        { field => $self->field, value => $self });
     }
-    $self->_check_if_controller();
+    $self->_check_if_controller(); # From ChoiceInterface.
     $self->SUPER::remove_from_db();
 }
 
-# Factored out to make life easier for subclasses.
-sub _check_if_controller {
-    my $self = shift;
-    my $vis_fields = $self->controls_visibility_of_fields;
-    my $values     = $self->controlled_values;
-    if (@$vis_fields || scalar(keys %$values)) {
-        ThrowUserError('fieldvalue_is_controller',
-            { value => $self, fields => [map($_->name, @$vis_fields)],
-              vals => $values });
-    }
-}
-
-
-#############
-# Accessors #
-#############
-
-sub is_active { return $_[0]->{'isactive'}; }
-sub sortkey   { return $_[0]->{'sortkey'};  }
-
-sub bug_count {
-    my $self = shift;
-    return $self->{bug_count} if defined $self->{bug_count};
-    my $dbh = Bugzilla->dbh;
-    my $fname = $self->field->name;
-    my $count;
-    if ($self->field->type == FIELD_TYPE_MULTI_SELECT) {
-        $count = $dbh->selectrow_array("SELECT COUNT(*) FROM bug_$fname
-                                         WHERE value = ?", undef, $self->name);
-    }
-    else {
-        $count = $dbh->selectrow_array("SELECT COUNT(*) FROM bugs 
-                                         WHERE $fname = ?",
-                                       undef, $self->name);
-    }
-    $self->{bug_count} = $count;
-    return $count;
-}
-
-sub field {
-    my $invocant = shift;
-    my $class = ref $invocant || $invocant;
-    my $cache = Bugzilla->request_cache;
-    # This is just to make life easier for subclasses. Our auto-generated
-    # subclasses from type() already have this set.
-    $cache->{"field_$class"} ||=  
-        new Bugzilla::Field({ name => $class->DB_TABLE });
-    return $cache->{"field_$class"};
-}
-
-sub is_default {
-    my $self = shift;
-    my $name = $self->DEFAULT_MAP->{$self->field->name};
-    # If it doesn't exist in DEFAULT_MAP, then there is no parameter
-    # related to this field.
-    return 0 unless $name;
-    return ($self->name eq Bugzilla->params->{$name}) ? 1 : 0;
-}
-
-sub is_static {
-    my $self = shift;
-    # If we need to special-case Resolution for *anything* else, it should
-    # get its own subclass.
-    if ($self->field->name eq 'resolution') {
-        return grep($_ eq $self->name, ('', 'FIXED', 'MOVED', 'DUPLICATE'))
-               ? 1 : 0;
-    }
-    elsif ($self->field->custom) {
-        return $self->name eq '---' ? 1 : 0;
-    }
-    return 0;
-}
-
-sub controls_visibility_of_fields {
-    my $self = shift;
-    $self->{controls_visibility_of_fields} ||= Bugzilla::Field->match(
-        { visibility_field_id => $self->field->id, 
-          visibility_value_id => $self->id });
-    return $self->{controls_visibility_of_fields};
-}
-
-sub visibility_value {
-    my $self = shift;
-    if ($self->{visibility_value_id}) {
-        $self->{visibility_value} ||=
-            Bugzilla::Field::Choice->type($self->field->value_field)->new(
-                $self->{visibility_value_id});
-    }
-    return $self->{visibility_value};
-}
-
-sub controlled_values {
-    my $self = shift;
-    return $self->{controlled_values} if defined $self->{controlled_values};
-    my $fields = $self->field->controls_values_of;
-    my %controlled_values;
-    foreach my $field (@$fields) {
-        $controlled_values{$field->name} = 
-            Bugzilla::Field::Choice->type($field)
-            ->match({ visibility_value_id => $self->id });
-    }
-    $self->{controlled_values} = \%controlled_values;
-    return $self->{controlled_values};
-}
-
 ############
 # Mutators #
 ############
@@ -402,6 +298,9 @@ each value type needs its own class.
 
 See the L</SYNOPSIS> for examples of how this works.
 
+This class implements L<Bugzilla::Field::ChoiceInterface>, and so all
+methods of that class are also available here.
+
 =head1 METHODS
 
 =head2 Class Factory
@@ -424,28 +323,7 @@ must call C<type> to get a class you can call methods on.
 
 =back
 
-=head2 Accessors
+=head2 Mutators
 
-These are in addition to the standard L<Bugzilla::Object> accessors.
-
-=over
-
-=item C<sortkey>
-
-The key that determines the sort order of this item.
-
-=item C<field>
-
-The L<Bugzilla::Field> object that this field value belongs to.
-
-=item C<controlled_values>
-
-Tells you which values in B<other> fields appear (become visible) when this
-value is set in its field.
-
-Returns a hashref of arrayrefs. The hash keys are the names of fields,
-and the values are arrays of C<Bugzilla::Field::Choice> objects,
-representing values that this value controls the visibility of, for
-that field.
-
-=back
+This class implements mutators for all of the settable accessors in
+L<Bugzilla::Field::ChoiceInterface>.
index 282279e75cc16a1224065d516ad7c14b583bde65..6c353357d98843519b3eea14e129968a2690ad0c 100644 (file)
@@ -323,7 +323,7 @@ sub reset_serial_values {
     );
     my @select_fields = grep { $_->is_select } (values %{ $self->bug_fields });
     foreach my $field (@select_fields) {
-        next if $field->name eq 'product';
+        next if $field->is_abnormal;
         $reset{$field->name} = 'id';
     }
     
@@ -709,8 +709,8 @@ sub insert_bugs {
         $self->debug($bug, 3);
 
         foreach my $field (@standard_drop_downs) {
+            next if $field->is_abnormal;
             my $field_name = $field->name;
-            next if $field_name eq 'product';
             if (!defined $bug->{$field_name}) {
                 # If there's a default value for this, then just let create()
                 # pick it.
index c993905db9508557723fb1c018f2ca67e7182e4d..6b00fcbf6a4d431803484d9166f1d603f1c30137 100644 (file)
@@ -32,9 +32,7 @@ use Bugzilla::Mailer;
 use Bugzilla::Series;
 use Bugzilla::Hook;
 
-# Currently, we only implement enough of the Bugzilla::Field::Choice
-# interface to control the visibility of other fields.
-use base qw(Bugzilla::Field::Choice);
+use base qw(Bugzilla::Field::ChoiceInterface Bugzilla::Object);
 
 use constant DEFAULT_CLASSIFICATION_ID => 1;
 
@@ -43,10 +41,6 @@ use constant DEFAULT_CLASSIFICATION_ID => 1;
 ###############################
 
 use constant DB_TABLE => 'products';
-# Reset these back to the Bugzilla::Object defaults, instead of the
-# Bugzilla::Field::Choice defaults.
-use constant NAME_FIELD => 'name';
-use constant LIST_ORDER => 'name';
 
 use constant DB_COLUMNS => qw(
    id
@@ -565,14 +559,7 @@ sub _check_votes {
 # Implement Bugzilla::Field::Choice #
 #####################################
 
-sub field {
-    my $invocant = shift;
-    my $class = ref $invocant || $invocant;
-    my $cache = Bugzilla->request_cache;
-    $cache->{"field_$class"} ||= new Bugzilla::Field({ name => 'product' });
-    return $cache->{"field_$class"};
-}
-
+use constant FIELD_NAME => 'product';
 use constant is_default => 0;
 
 ###############################
index 43b95f2936d3681bfc5ae3d13c157959ea21ef71..88e44ac1d74283aa3f9172ee0db8b9c8369e3252 100644 (file)
@@ -219,8 +219,8 @@ sub init {
         type     => [FIELD_TYPE_MULTI_SELECT, FIELD_TYPE_BUG_URLS],
         obsolete => 0 });
     foreach my $field (@select_fields) {
+        next if $field->is_abnormal;
         my $name = $field->name;
-        next if $name eq 'product'; # products don't have sortkeys.
         $special_order{$name} = [ "$name.sortkey", "$name.value" ],
         $special_order_join{$name} =
            "LEFT JOIN $name ON $name.value = bugs.$name";
index 4d1281e7e875034360a7938d7a3f6c95c77c403a..0dd17ae3936e76bd54392e54d999f81873818dec 100644 (file)
@@ -23,7 +23,10 @@ use strict;
 package Bugzilla::Status;
 
 use Bugzilla::Error;
-
+# This subclasses Bugzilla::Field::Choice instead of implementing 
+# ChoiceInterface, because a bug status literally is a special type
+# of Field::Choice, not just an object that happens to have the same
+# methods.
 use base qw(Bugzilla::Field::Choice Exporter);
 @Bugzilla::Status::EXPORT = qw(
     BUG_STATE_OPEN
index 53f3255d19b3ea02dbb39dfdaf6d70e7609b4801..16217bb638c5b56e10d6f3fd70af8525c0217f3e 100644 (file)
@@ -422,8 +422,8 @@ sub legal_values {
     my $field = Bugzilla::Bug::FIELD_MAP->{$params->{field}} 
                 || $params->{field};
 
-    my @global_selects = Bugzilla->get_fields(
-        {type => [FIELD_TYPE_SINGLE_SELECT, FIELD_TYPE_MULTI_SELECT]});
+    my @global_selects = grep { !$_->is_abnormal }
+                         Bugzilla->get_fields({ is_select => 1 });
 
     my $values;
     if (grep($_->name eq $field, @global_selects)) {
index 477bf86967a657fe3319b489518f3bdb918ff4a1..b651b23c293e65701354d915bf5d484a507bc1fb 100755 (executable)
@@ -71,16 +71,12 @@ Bugzilla->user->in_group('admin') ||
 my $action = trim($cgi->param('action')  || '');
 my $token  = $cgi->param('token');
 
-# Fields listed here must not be edited from this interface.
-my @non_editable_fields = qw(product);
-my %block_list = map { $_ => 1 } @non_editable_fields;
-
 #
 # field = '' -> Show nice list of fields
 #
 if (!$cgi->param('field')) {
-    my @field_list = grep { !$block_list{$_->name} }
-                       Bugzilla->get_fields({ is_select => 1 });
+    my @field_list = grep { !$_->is_abnormal }
+                          Bugzilla->get_fields({ is_select => 1 });
 
     $vars->{'fields'} = \@field_list;
     $template->process("admin/fieldvalues/select-field.html.tmpl", $vars)
@@ -90,7 +86,7 @@ if (!$cgi->param('field')) {
 
 # At this point, the field must be defined.
 my $field = Bugzilla::Field->check($cgi->param('field'));
-if (!$field->is_select || $block_list{$field->name}) {
+if (!$field->is_select || $field->is_abnormal) {
     ThrowUserError('fieldname_invalid', { field => $field });
 }
 $vars->{'field'} = $field;
index 9a618c0136e27bbe5ef424c60ecec0b338690f01..6612ded2a2c8b7064063360b942f51d4b2e5cafb 100755 (executable)
@@ -111,7 +111,6 @@ my @columns = qw(
     assigned_to
     reporter
     qa_contact
-    component
     classification
     version
     votes
index 331d809f6d056f1a27e206f86e5bc6bf4b8b77fd..778dd3373b951a9142ce061933938eb5441b1fe3 100644 (file)
@@ -28,7 +28,14 @@ var select_values = new Array();
 [% FOREACH sel_field = Bugzilla.get_fields({ is_select => 1 }) %]
   select_values[[% sel_field.id FILTER js %]] = [
   [% FOREACH legal_value = sel_field.legal_values %]
-    [[% legal_value.id FILTER js %], '[% legal_value.name FILTER js %]'][% ',' UNLESS loop.last %]
+    [%# Prefix components with the name of their product so that admins
+        know which component we're talking about. #%]
+    [% IF sel_field.name == 'component' %]
+      [% SET value_name = legal_value.product.name _ ': ' _ legal_value.name %]
+    [% ELSE %]
+      [% SET value_name = legal_value.name %]
+    [% END %]
+    [[% legal_value.id FILTER js %], '[% value_name FILTER js %]'][% ',' UNLESS loop.last %]
   [% END %]
   ];
 [% END %]
index b6a8ae9bd789babb5d9641854791b71be01044a5..981668260f142ce787c5ac342a34cb2127905f06 100644 (file)
             <option value="[% value.id FILTER html %]"
              [% ' selected="selected"' 
                 IF field.visibility_value.id == value.id %]>
-              [% value.name FILTER html %]
+              [% IF field.visibility_field.name == 'component' %]
+                [% value.product.name FILTER html %]:
+              [% END %]
+              [%+ value.name FILTER html %]
             </option>
           [% END %]   
         </select>
index f1eec1a5a4a7c24d307680b7618e0beb406e7608..0198314891857d4ea1ed038dcf456e3a7d1ad2f0 100644 (file)
@@ -75,6 +75,9 @@
             [% FOREACH field_value = field.value_field.legal_values %]
               [% NEXT IF field_value.name == '' %]
               <option value="[% field_value.id FILTER none %]">
+                [% IF field.value_field.name == 'component' %]
+                  [% field_value.product.name FILTER html %]:
+                [% END %]
                 [%- field_value.name FILTER html -%]
               </option>
             [% END %]
index 5650ee87b5bcf23f4f16682eb818a11ebb0ebe8f..fb58e578444aafec3ffd6dd37c2e035bdb7f7a14 100644 (file)
               <option value="[% field_value.id FILTER none %]"
                [% ' selected="selected"' 
                   IF field_value.id == value.visibility_value.id %]>
-                [%- field_value.name FILTER html -%]
+                [% IF field.value_field.name == 'component' %]
+                  [% field_value.product.name FILTER html %]:
+                [% END %]
+                [% field_value.name FILTER html -%]
               </option>
             [% END %]
           </select>
index 4b1745757a16a9f4d7006eda323058891fd9890a..1f3380a2973715e0c469672787e861aa6948adf5 100644 (file)
@@ -168,14 +168,6 @@ TUI_hide_default('expert_fields');
 -->
 </script>
 
-[% USE Bugzilla %]
-[% SET select_fields = {} %]
-[% FOREACH field = Bugzilla.get_fields(
-  { type => constants.FIELD_TYPE_SINGLE_SELECT, custom => 0 })
-%]
-  [% select_fields.${field.name} = field %]
-[% END %]
-
 <form name="Create" id="Create" method="post" action="post_bug.cgi"
       enctype="multipart/form-data">
 <input type="hidden" name="product" value="[% product.name FILTER html %]">
@@ -224,8 +216,8 @@ TUI_hide_default('expert_fields');
       Component</a>:
     </th>
     <td>
-      <select name="component" onchange="set_assign_to();" size="7"
-              aria-required="true" class="required">
+      <select name="component" id="component" onchange="set_assign_to();"
+              size="7" aria-required="true" class="required">
         [%# Build the lists of assignees and QA contacts if "usemenuforusers" is enabled. %]
         [% IF Param("usemenuforusers") %]
           [% assignees_list = user.get_userlist.clone %]
@@ -234,7 +226,13 @@ TUI_hide_default('expert_fields');
 
         [%- FOREACH c = product.components %]
           <option value="[% c.name FILTER html %]"
-            [% " selected=\"selected\"" IF c.name == default.component_ %]>
+                  id="v[% c.id FILTER html %]_component"
+            [% IF c.name == default.component_ %]
+              [%# This is for bug/field.html.tmpl, for visibility-related
+                # controls. %]
+              [% default.component_id = c.id %]
+              selected="selected"
+            [% END %]>
             [% c.name FILTER html -%]
           </option>
           [% IF Param("usemenuforusers") %]
@@ -245,6 +243,13 @@ TUI_hide_default('expert_fields');
           [% END %]
         [%- END %]
       </select>
+
+      <script type="text/javascript">
+       <!--
+         [%+ INCLUDE "bug/field-events.js.tmpl" 
+                    field = bug_fields.component %]
+       //-->
+       </script>
     </td>
 
     <td colspan="2">
@@ -276,19 +281,19 @@ TUI_hide_default('expert_fields');
     </td>
 
     [% INCLUDE bug/field.html.tmpl
-      bug = default, field = select_fields.bug_severity, editable = 1, 
+      bug = default, field = bug_fields.bug_severity, editable = 1, 
       value = default.bug_severity %]
   </tr>
 
   <tr>
     [% INCLUDE bug/field.html.tmpl
-      bug = default, field = select_fields.rep_platform, editable = 1,
+      bug = default, field = bug_fields.rep_platform, editable = 1,
       value = default.rep_platform %]
   </tr>
 
   <tr>
     [% INCLUDE bug/field.html.tmpl 
-       bug = default, field = select_fields.op_sys, editable = 1, 
+       bug = default, field = bug_fields.op_sys, editable = 1, 
        value = default.op_sys %]
   </tr>
 </tbody>
@@ -304,7 +309,7 @@ TUI_hide_default('expert_fields');
 
     [% IF Param('letsubmitterchoosepriority') %]
       [% INCLUDE bug/field.html.tmpl
-        bug = default, field = select_fields.priority, editable = 1, 
+        bug = default, field = bug_fields.priority, editable = 1, 
         value = default.priority %]
     [% ELSE %]
       <td colspan="2">&nbsp;</td>
@@ -679,7 +684,7 @@ TUI_hide_default('expert_fields');
        <script type="text/javascript">
         <!--
           [%+ INCLUDE "bug/field-events.js.tmpl" 
-                     field = select_fields.bug_status %]
+                     field = bug_fields.bug_status %]
         //-->
         </script>
     [% END %]
index 379370689202357691ad8f64f2e5f26937a443ae..63b81d733789837a24da2455edc40a317c1c06dc 100644 (file)
 
 [% PROCESS bug/time.html.tmpl %]
 
-[% USE Bugzilla %]
-[% SET select_fields = {} %]
-[% FOREACH field = Bugzilla.get_fields(
-  { type => constants.FIELD_TYPE_SINGLE_SELECT, custom => 0 })
-%]
-  [% select_fields.${field.name} = field %]
-[% END %]
-
   <script type="text/javascript">
   <!--
   
     
     <tr>
        [% INCLUDE bug/field.html.tmpl
-            bug = bug, field = select_fields.product,
+            bug = bug, field = bug_fields.product,
             override_legal_values = bug.choices.product
             desc_url = 'describecomponents.cgi', value = bug.product
             editable = bug.check_can_change_field('product', 0, 1) %]
     [%#  Component  #%]
     [%###############%]
     <tr>
-      <td class="field_label">
-        <label for="component" accesskey="m">
-          <b><a href="describecomponents.cgi?product=[% bug.product FILTER url_quote %]">
-            Co<u>m</u>ponent</a>:
-          </b>
-        </label>
-      </td>
-      [% PROCESS select selname => "component" %]
+      [% INCLUDE bug/field.html.tmpl
+          bug = bug, field = bug_fields.component, value = bug.component
+          override_legal_values = bug.choices.component
+          desc_url = "describecomponents.cgi?product=$bug.product"
+          editable = bug.check_can_change_field('component', 0, 1)
+      %]
     </tr>
     <tr>
       <td class="field_label">
       </td>
       <td class="field_value">
        [% INCLUDE bug/field.html.tmpl
-            bug = bug, field = select_fields.rep_platform,
+            bug = bug, field = bug_fields.rep_platform,
             no_tds = 1, value = bug.rep_platform
             editable = bug.check_can_change_field('rep_platform', 0, 1) %]
        [%+ INCLUDE bug/field.html.tmpl 
-            bug = bug, field = select_fields.op_sys, 
+            bug = bug, field = bug_fields.op_sys, 
             no_tds = 1, value = bug.op_sys
             editable = bug.check_can_change_field('op_sys', 0, 1) %]
        <script type="text/javascript">
       </td>
       <td>
        [% INCLUDE bug/field.html.tmpl
-            bug = bug, field = select_fields.priority,
+            bug = bug, field = bug_fields.priority,
             no_tds = 1, value = bug.priority
             editable = bug.check_can_change_field('priority', 0, 1) %]
        [%+ INCLUDE bug/field.html.tmpl
-            bug = bug, field = select_fields.bug_severity,
+            bug = bug, field = bug_fields.bug_severity,
             no_tds = 1, value = bug.bug_severity
             editable = bug.check_can_change_field('bug_severity', 0, 1) %]
         [% IF bug.use_votes %]
 
 [% BLOCK section_customfields %]
 [%# *** Custom Fields *** %]
-
+  [% USE Bugzilla %]
   [% FOREACH field = Bugzilla.active_custom_fields %]
     <tr>
       [% PROCESS bug/field.html.tmpl value=bug.${field.name}
index 06fba12450e5671407bd65e59705cabd0a794dbf..763687e06c87075fbb6a0898376c4ae6a7f93dbe 100644 (file)
@@ -32,6 +32,7 @@
     [% FOREACH val = legal_value.controlled_values.$controlled_field %]
       [% cont_ids.push(val.id) %]
     [% END %]
+    [% NEXT IF !cont_ids.size %]
     showValueWhen('[% controlled_field FILTER js %]',
                   [[% cont_ids.join(',') FILTER js %]],
                   '[% field.name FILTER js %]',
index bb678d79dfc97ee35635cf4319c19280a70cb597..ac62bf7ba4730c604d3659dcccf84ce3f47ef362 100644 (file)
   #%]
 
 [% SET hidden = 0 %]
-[% IF field.visibility_field.defined %]
-  [% IF !bug.${field.visibility_field.name}
-         .contains(field.visibility_value.name) 
-  %]
-    [% SET hidden = 1 %]
-  [% END %]
+[% IF field.visibility_field.defined AND bug
+      AND !field.visibility_value.is_set_on_bug(bug) 
+%]
+  [% SET hidden = 1 %]
 [% END %]
 
 [% IF NOT no_tds %]
             [% legal_values = field.legal_values %]
           [% END %]
           [% FOREACH legal_value = legal_values %]
-            [% SET control_value = legal_value.visibility_value %]
-            [% SET control_field = field.value_field %]
             <option value="[% legal_value.name FILTER html %]"
                     id="v[% legal_value.id FILTER html %]_
                         [%- field.name FILTER html %]"
                 # hidden %]
               [% IF value.contains(legal_value.name).size %]
                 selected="selected"
-              [% ELSIF (control_field && control_value
-                        && !bug.${control_field.name}.contains(control_value.name))
-                       || !legal_value.is_active
-              %]
+              [% ELSIF bug AND !legal_value.is_visible_on_bug(bug) %]
                 class="bz_hidden_option" disabled="disabled"
               [% END %]>
               [%- display_value(field.name, legal_value.name) FILTER html ~%]
index 79faabbfde6c930ae4025b3d77a1419061846bf2..37429a57ddfe83ab7e299d83971f718247cbd0a8 100644 (file)
       it controls the visibility of the following fields:
       [%+ fields.join(', ') FILTER html %].
     [% END %]
-    [% ' and ' IF fields.size AND vals.size %]
+    [% ' Also, ' IF fields.size AND vals.size %]
     [% IF vals.size %]
       it controls the visibility of the following field values:
       <ul>
index 75f2f833b76d54e2101b09b5bca75cd4ad6d696d..91c86cc6498aa0f57bcf9cdffb71efffb94f4166 100644 (file)
   [% END %]
 
   [% USE Bugzilla %]
+  [%# Show all legal values and all fields, ignoring visibility controls. %]
+  [% bug = 0 %]
   [% FOREACH field = Bugzilla.active_custom_fields %]
     <tr>
       [% PROCESS bug/field.html.tmpl value = dontchange