]> git.ipfire.org Git - thirdparty/bugzilla.git/commitdiff
Bug 281876: New Admin Interface to manage old Enum fields (Field Values)
authormkanat%kerio.com <>
Fri, 25 Feb 2005 06:48:05 +0000 (06:48 +0000)
committermkanat%kerio.com <>
Fri, 25 Feb 2005 06:48:05 +0000 (06:48 +0000)
Patch By Max Kanat-Alexander <mkanat@kerio.com> r=joel, a=justdave

13 files changed:
editvalues.cgi [new file with mode: 0755]
template/en/default/admin/fieldvalues/confirm-delete.html.tmpl [new file with mode: 0644]
template/en/default/admin/fieldvalues/create.html.tmpl [new file with mode: 0644]
template/en/default/admin/fieldvalues/created.html.tmpl [new file with mode: 0644]
template/en/default/admin/fieldvalues/deleted.html.tmpl [new file with mode: 0644]
template/en/default/admin/fieldvalues/edit.html.tmpl [new file with mode: 0644]
template/en/default/admin/fieldvalues/footer.html.tmpl [new file with mode: 0644]
template/en/default/admin/fieldvalues/list.html.tmpl [new file with mode: 0644]
template/en/default/admin/fieldvalues/select-field.html.tmpl [new file with mode: 0644]
template/en/default/admin/fieldvalues/updated.html.tmpl [new file with mode: 0644]
template/en/default/admin/table.html.tmpl
template/en/default/global/useful-links.html.tmpl
template/en/default/global/user-error.html.tmpl

diff --git a/editvalues.cgi b/editvalues.cgi
new file mode 100755 (executable)
index 0000000..8231dab
--- /dev/null
@@ -0,0 +1,386 @@
+#!/usr/bin/perl -wT
+# 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.
+#
+# Contributor(s): Max Kanat-Alexander <mkanat@kerio.com>
+
+# This is a script to edit the values of fields that have drop-down
+# or select boxes. It is largely a copy of editmilestones.cgi, but 
+# with some cleanup.
+
+use strict;
+use lib ".";
+
+use Bugzilla;
+use Bugzilla::Util;
+use Bugzilla::Error;
+use Bugzilla::Constants;
+use Bugzilla::Config qw(:DEFAULT :locations);
+
+# List of different tables that contain the changeable field values
+# (the old "enums.") Keep them in alphabetical order by their 
+# English name from field-descs.html.tmpl.
+# Format: Array of valid field names.
+# Admins may add resolution and bug_status to this list, but they
+# do so at their own risk.
+our @valid_fields = ('op_sys', 'rep_platform', 'priority', 'bug_severity',);
+
+######################################################################
+# Subroutines
+######################################################################
+
+# Returns whether or not the specified table exists in the @tables array.
+sub FieldExists ($) {
+  my ($field) = @_;
+
+  return lsearch(\@valid_fields, $field) >= 0;
+}
+
+# Same as FieldExists, but emits and error and dies if it fails.
+sub FieldMustExist ($) {
+    my ($field)= @_;
+
+    $field ||
+        ThrowUserError('fieldname_not_specified');
+
+    # Is it a valid field to be editing?
+    FieldExists($field) ||
+        ThrowUserError('fieldname_invalid', {'field' => $field});
+}
+
+# Returns if the specified value exists for the field specified.
+sub ValueExists ($$) {
+    my ($field, $value) = @_;
+    FieldMustExist($field);
+    trick_taint($field);
+    # Value is safe because it's being passed only to a SELECT
+    # statement via a placeholder.
+    trick_taint($value);
+
+    my $dbh = Bugzilla->dbh;
+    my $value_count = 
+        $dbh->selectrow_array("SELECT COUNT(*) FROM $field "
+                           .  " WHERE value = ?", undef, $value);
+
+    return $value_count;
+}
+
+# Same check as ValueExists, emits an error text and dies if it fails.
+sub ValueMustExist ($$) {
+    my ($field, $value)= @_;
+
+    # Values may not be empty (it's very difficult to deal 
+    # with empty values in the admin interface).
+    trim($value) || ThrowUserError('fieldvalue_not_specified');
+
+    # Does it exist in the DB?
+    ValueExists($field, $value) ||
+        ThrowUserError('fieldvalue_doesnt_exist', {'value' => $value,
+                                                   'field' => $field});
+}
+
+######################################################################
+# Main Body Execution
+######################################################################
+
+# require the user to have logged in
+Bugzilla->login(LOGIN_REQUIRED);
+
+my $dbh      = Bugzilla->dbh;
+my $cgi      = Bugzilla->cgi;
+my $template = Bugzilla->template;
+my $vars = {};
+
+print $cgi->header();
+
+exists Bugzilla->user->groups->{'editcomponents'} ||
+    ThrowUserError('auth_failure', {group  => "editcomponents",
+                                    action => "edit",
+                                    object => "field values"});
+
+#
+# often-used variables
+#
+my $field   = trim($cgi->param('field')   || '');
+my $value   = trim($cgi->param('value')   || '');
+my $sortkey = trim($cgi->param('sortkey') || '0');
+my $action  = trim($cgi->param('action')  || '');
+
+
+#
+# field = '' -> Show nice list of fields
+#
+unless ($field) {
+    # Convert @valid_fields into the format that select-field wants.
+    my @field_list = ();
+    foreach my $field_name (@valid_fields) {
+        push(@field_list, {name => $field_name});
+    }
+
+    $vars->{'fields'} = \@field_list;
+    $template->process("admin/fieldvalues/select-field.html.tmpl",
+                       $vars)
+      || ThrowTemplateError($template->error());
+    exit;
+}
+
+
+#
+# action='' -> Show nice list of values.
+#
+unless ($action) {
+    FieldMustExist($field);
+    # Now we know the $field is valid.
+    trick_taint($field);
+
+    my $fieldvalues = 
+        $dbh->selectall_arrayref("SELECT value AS name, sortkey"
+                               . "  FROM $field ORDER BY sortkey, value",
+                                 {Slice =>{}});
+    $vars->{'field'} = $field;
+    $vars->{'values'} = $fieldvalues;
+    $template->process("admin/fieldvalues/list.html.tmpl",
+                       $vars)
+      || ThrowTemplateError($template->error());
+
+    exit;
+}
+
+
+#
+# action='add' -> show form for adding new field value.
+# (next action will be 'new')
+#
+if ($action eq 'add') {
+    FieldMustExist($field);
+
+    $vars->{'value'} = $value;
+    $vars->{'field'} = $field;
+    $template->process("admin/fieldvalues/create.html.tmpl",
+                       $vars)
+      || ThrowTemplateError($template->error());
+
+    exit;
+}
+
+
+#
+# action='new' -> add field value entered in the 'action=add' screen
+#
+if ($action eq 'new') {
+    FieldMustExist($field);
+    trick_taint($field);
+
+    # Cleanups and validity checks
+    $value || ThrowUserError('fieldvalue_undefined');
+
+    if (length($value) > 60) {
+        ThrowUserError('fieldvalue_name_too_long',
+                       {'value' => $value});
+    }
+    # Need to store in case detaint_natural() clears the sortkey
+    my $stored_sortkey = $sortkey;
+    if (!detaint_natural($sortkey)) {
+        ThrowUserError('fieldvalue_sortkey_invalid',
+                       {'name' => $field,
+                        'sortkey' => $stored_sortkey});
+    }
+    if (ValueExists($field, $value)) {
+        ThrowUserError('fieldvalue_already_exists',
+                       {'field' => $field,
+                        'value' => $value});
+    }
+    # Value is only used in a SELECT placeholder and through the HTML filter.
+    trick_taint($value);
+
+    # Add the new field value.
+    my $sth = $dbh->prepare("INSERT INTO $field ( value, sortkey )
+                             VALUES ( ?, ? )");
+    $sth->execute($value, $sortkey);
+
+    unlink "$datadir/versioncache";
+
+    $vars->{'value'} = $value;
+    $vars->{'field'} = $field;
+    $template->process("admin/fieldvalues/created.html.tmpl",
+                       $vars)
+      || ThrowTemplateError($template->error());
+
+    exit;
+}
+
+
+#
+# action='del' -> ask if user really wants to delete
+# (next action would be 'delete')
+#
+if ($action eq 'del') {
+    ValueMustExist($field, $value);
+    trick_taint($field);
+    trick_taint($value);
+
+    # See if any bugs are still using this value.
+    $vars->{'bug_count'} = 
+        $dbh->selectrow_array("SELECT COUNT(*) FROM bugs WHERE $field = ?",
+                              undef, $value) || 0;
+    $vars->{'value_count'} = 
+        $dbh->selectrow_array("SELECT COUNT(*) FROM $field");
+
+    $vars->{'value'} = $value;
+    $vars->{'field'} = $field;
+    $template->process("admin/fieldvalues/confirm-delete.html.tmpl",
+                       $vars)
+      || ThrowTemplateError($template->error());
+
+    exit;
+}
+
+
+#
+# action='delete' -> really delete the field value
+#
+if ($action eq 'delete') {
+    ValueMustExist($field, $value);
+    trick_taint($field);
+    trick_taint($value);
+
+    # Check if there are any bugs that still have this value.
+    my $bug_ids = $dbh->selectcol_arrayref(
+        "SELECT bug_id FROM bugs WHERE $field = ?", undef, $value);
+
+    if (scalar(@$bug_ids)) {
+        # You tried to delete a field that bugs are still using.
+        # You can't just delete the bugs. That's ridiculous. 
+        $dbh->do('UNLOCK TABLES');
+        ThrowUserError("fieldvalue_still_has_bugs", 
+                       { field => $field, value => $value,
+                         count => scalar(@$bug_ids) });
+    }
+
+    $dbh->do("DELETE FROM $field WHERE value = ?", undef, $value);
+
+    unlink "$datadir/versioncache";
+
+    $vars->{'value'} = $value;
+    $vars->{'field'} = $field;
+    $template->process("admin/fieldvalues/deleted.html.tmpl",
+                       $vars)
+      || ThrowTemplateError($template->error());
+    exit;
+}
+
+
+#
+# action='edit' -> present the edit-value form
+# (next action would be 'update')
+#
+if ($action eq 'edit') {
+    ValueMustExist($field, $value);
+    trick_taint($field);
+    trick_taint($value);
+
+    $vars->{'sortkey'} = $dbh->selectrow_array(
+        "SELECT sortkey FROM $field WHERE value = ?", undef, $value) || 0;
+
+    $vars->{'value'} = $value;
+    $vars->{'field'} = $field;
+
+    $template->process("admin/fieldvalues/edit.html.tmpl",
+                       $vars)
+      || ThrowTemplateError($template->error());
+
+    exit;
+}
+
+
+#
+# action='update' -> update the field value
+#
+if ($action eq 'update') {
+    my $valueold   = trim($cgi->param('valueold')   || '');
+    my $sortkeyold = trim($cgi->param('sortkeyold') || '0');
+
+    ValueMustExist($field, $valueold);
+    trick_taint($field);
+    trick_taint($valueold);
+
+    if (length($value) > 60) {
+        ThrowUserError('fieldvalue_name_too_long',
+                       {'value' => $value});
+    }
+
+    $dbh->do("LOCK TABLES bugs WRITE, $field WRITE");
+
+    # Need to store because detaint_natural() will delete this if
+    # invalid
+    my $stored_sortkey = $sortkey;
+    if ($sortkey != $sortkeyold) {
+
+        if (!detaint_natural($sortkey)) {
+            $dbh->do('UNLOCK TABLES');
+            ThrowUserError('fieldvalue_sortkey_invalid',
+                           {'name' => $field,
+                            'sortkey' => $stored_sortkey});
+
+        }
+
+        $dbh->do("UPDATE $field SET sortkey = ? WHERE value = ?",
+                 undef, $sortkey, $valueold);
+
+        unlink "$datadir/versioncache";
+        $vars->{'updated_sortkey'} = 1;
+        $vars->{'sortkey'} = $sortkey;
+    }
+
+    if ($value ne $valueold) {
+
+        unless ($value) {
+            $dbh->do('UNLOCK TABLES'); 
+            ThrowUserError('fieldvalue_undefined');
+        }
+        if (ValueExists($field, $value)) {
+            $dbh->do('UNLOCK TABLES'); 
+            ThrowUserError('fieldvalue_already_exists',
+                           {'value' => $value,
+                            'field' => $field});
+        }
+        trick_taint($value);
+
+        $dbh->do("UPDATE bugs SET $field = ?, delta_ts = NOW()
+                   WHERE $field = ?", undef, $value, $valueold);
+
+        $dbh->do("UPDATE $field SET value = ? WHERE value = ?",
+                 undef, $value, $valueold);
+
+        unlink "$datadir/versioncache";
+
+        $vars->{'updated_value'} = 1;
+    }
+
+    $dbh->do('UNLOCK TABLES'); 
+
+    $vars->{'value'} = $value;
+    $vars->{'field'} = $field;
+    $template->process("admin/fieldvalues/updated.html.tmpl",
+                       $vars)
+      || ThrowTemplateError($template->error());
+
+    exit;
+}
+
+
+#
+# No valid action found
+#
+# We can't get here without $field being defined --
+# See the unless($field) block at the top.
+ThrowUserError('no_valid_action', { field => $field } );
diff --git a/template/en/default/admin/fieldvalues/confirm-delete.html.tmpl b/template/en/default/admin/fieldvalues/confirm-delete.html.tmpl
new file mode 100644 (file)
index 0000000..234a895
--- /dev/null
@@ -0,0 +1,108 @@
+[%# 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.
+  #
+  # Contributor(s): Max Kanat-Alexander <mkanat@kerio.com>
+  #%]
+
+[%# INTERFACE:
+  # value: string; The field value being deleted.
+  # bug_count: number; The number of bugs that have this field value.
+  # value_count: number; The number of values left for this field, including
+  #              this value.
+  # field: string; The name of the field.
+  #%]
+
+[% title = BLOCK %]Delete Value '[% value FILTER html %]' from the 
+  '[% field FILTER html %]' field[% END %]
+
+[% PROCESS global/header.html.tmpl
+  title = title
+%]
+
+<table border="1" cellpadding="4" cellspacing="0">
+<tr bgcolor="#6666FF">
+  <th valign="top" align="left">Field</th>
+  <th valign="top" align="left">Value</th>
+</tr>
+<tr>
+  <td valign="top">Field Name:</td>
+  <td valign="top">[% field FILTER html %]</td>
+</tr>
+<tr>
+  <td valign="top">Field Value:</td>
+  <td valign="top">[% value FILTER html %]</td>
+</tr>
+<tr>
+  <td valign="top">[% terms.Bugs %]:</td>
+  <td valign="top">
+[% IF bug_count %]
+  <a title="List of [% terms.bugs %] where '[% field FILTER html %]' is '
+            [% value FILTER html %]'"
+     href="buglist.cgi?[% field FILTER url_quote %]=[%- value FILTER url_quote %]">[% bug_count FILTER html %]</a>
+[% ELSE %]
+  None
+[% END %]
+  </td>
+</tr>
+</table>
+
+<h2>Confirmation</h2>
+  
+[% IF bug_count %]
+
+    Sorry, there
+
+    [% IF bug_count > 1 %] 
+      are [% bug_count FILTER html %] [%+ terms.bugs %] 
+    [% ELSE %]
+      is [% bug_count FILTER html %] [%+ terms.bug %] 
+    [% END %]
+
+    that still have this field value. You must change the field value on
+    <a title="List of [% terms.bugs %] where '[% field FILTER html %]' is '[% value FILTER html %]'"
+       href="buglist.cgi?[% field FILTER url_quote %]=[%- value FILTER url_quote %]">
+    [% IF bug_count > 1 %]
+       those [% terms.bugs %] 
+    [% ELSE %]
+       that [% terms.bug %]
+    [% END %]
+    </a>
+    to another value before you can delete this value.
+
+[% END %]
+
+[% IF value_count == 1 %]
+
+    <p>Sorry, but '[% value FILTER html %]' is the last value for
+    '[%- field FILTER html %]', and so it can not be deleted.</p>
+
+  [% ELSE %]
+
+    [% IF bug_count == 0 %]
+
+      <p>Do you really want to delete this value?<p>
+  
+      <form method="post" action="editvalues.cgi">
+        <input type="submit" value="Yes, delete">
+        <input type="hidden" name="action" value="delete">
+        <input type="hidden" name="field" value="[% field FILTER html %]">
+        <input type="hidden" name="value" value="[% value FILTER html %]">
+      </form>
+
+  [% END %]
+
+[% END %]
+
+[% PROCESS admin/fieldvalues/footer.html.tmpl %]
+
+[% PROCESS global/footer.html.tmpl %] 
diff --git a/template/en/default/admin/fieldvalues/create.html.tmpl b/template/en/default/admin/fieldvalues/create.html.tmpl
new file mode 100644 (file)
index 0000000..70dbc4e
--- /dev/null
@@ -0,0 +1,54 @@
+[%# 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.
+  #
+  # Contributor(s): Max Kanat-Alexander <mkanat@kerio.com>
+  #%]
+
+[%# INTERFACE:
+  # field: string; name of the field the value is being created for
+  #%]
+  
+[% title = BLOCK %]Add Value for the '[% field FILTER html %]' field[% END %]
+[% h2 = BLOCK %]This page allows you to add a new value for the
+                '[% field FILTER html %]' field.[% END %]
+[% PROCESS global/header.html.tmpl
+  title = title
+  h2 = h2
+%]
+
+<form method="post" action="editvalues.cgi">
+  <table border="0" cellpadding="4" cellspacing="0">
+    <tr>
+      <th align="right"><label for="value">Value:</label></th>
+      <td><input id="value" size="30" maxlength="60" name="value"
+                 value=""></td>
+    </tr>
+    <tr>
+      <th align="right"><label for="sortkey">Sortkey:</label></th>
+      <td><input id="sortkey" size="10" maxlength="20" name="sortkey"
+                 value=""></td>
+    </tr>
+  </table>
+  <input type="submit" value="Add">
+  <input type="hidden" name="action" value="new">
+  <input type="hidden" name='field' value="[% field FILTER html %]">
+
+</form>
+
+<p>
+
+[% PROCESS admin/fieldvalues/footer.html.tmpl
+    no_add_link = 1
+ %]
+
+[% PROCESS global/footer.html.tmpl %]
diff --git a/template/en/default/admin/fieldvalues/created.html.tmpl b/template/en/default/admin/fieldvalues/created.html.tmpl
new file mode 100644 (file)
index 0000000..28688d9
--- /dev/null
@@ -0,0 +1,39 @@
+[%# 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.
+  #
+  # Contributor(s): Max Kanat-Alexander <mkanat@kerio.com>
+  #%]
+
+[%# INTERFACE:
+  # value: string; the name of the newly created field value
+  # field: string; the name of the field the value belongs to
+  #%]
+  
+[% title = BLOCK %]New Value '[% product FILTER html %]' added to 
+  '[% field FILTER html %]' field[% END %]
+[% PROCESS global/header.html.tmpl
+  title = title
+%]
+
+<p>The value '<a title="Edit value '[% value FILTER html %]' of 
+   for the '[% field FILTER html %]' field"
+   href="editvalues.cgi?action=edit&amp;field=
+   [%- field FILTER url_quote %]&amp;value=[% value FILTER url_quote %]">
+   [%- value FILTER html %]</a>' has been added as a valid choice for
+   the '[% field FILTER html %]' field.</p>
+
+<p>
+
+[% PROCESS admin/fieldvalues/footer.html.tmpl %]
+
+[% PROCESS global/footer.html.tmpl %]
diff --git a/template/en/default/admin/fieldvalues/deleted.html.tmpl b/template/en/default/admin/fieldvalues/deleted.html.tmpl
new file mode 100644 (file)
index 0000000..2bb3c84
--- /dev/null
@@ -0,0 +1,38 @@
+[%# 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.
+  #
+  # Contributor(s): Max Kanat-Alexander <mkanat@kerio.com>
+  #%]
+
+[%# INTERFACE:
+  # value: string; the field value that was deleted.
+  #
+  # field: string; the field the value was deleted from.
+  #
+  #%]
+  
+[% title = BLOCK %]Deleted Value '[% value FILTER html %]' for the
+                   '[% field FILTER html %]' Field[% END %]
+[% PROCESS global/header.html.tmpl
+  title = title
+%]
+
+<p>Field Value '[% value FILTER html %]' deleted.</p>
+
+<p>
+
+[% PROCESS admin/fieldvalues/footer.html.tmpl
+  no_edit_link = 1
+ %]
+
+[% PROCESS global/footer.html.tmpl %]
diff --git a/template/en/default/admin/fieldvalues/edit.html.tmpl b/template/en/default/admin/fieldvalues/edit.html.tmpl
new file mode 100644 (file)
index 0000000..9771148
--- /dev/null
@@ -0,0 +1,60 @@
+[%# 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.
+  #
+  # Contributor(s): Max Kanat-Alexander <mkanat@kerio.com>
+  #%]
+
+[%# INTERFACE:
+  # value: string; The field value we are editing.
+  # sortkey: number; Sortkey of the field value we are editing.
+  # field: string; The field this value belongs to.
+  #%]
+
+[% PROCESS global/variables.none.tmpl %]
+
+[% title = BLOCK %]Edit Value '[% value FILTER html %]'  '
+                   [%- filter FILTER html %]'[% END %]
+[% PROCESS global/header.html.tmpl
+  title = title
+%]
+
+<form method="post" action="editvalues.cgi">
+  <table border="0" cellpadding="4" cellspacing="0">
+
+    <tr>
+      <th valign="top"><label for="value">Field Value:</label></th>
+      <td><input id="value" size="20" maxlength="60" name="value" value="
+      [%- value FILTER html %]"></td>
+    </tr>
+    <tr>
+      <th align="right"><label for="sortkey">Sortkey:</label></th>
+      <td><input id="sortkey" size="20" maxlength="20" name="sortkey" value="
+      [%- sortkey FILTER html %]"></td>
+    </tr>
+
+  </table>
+
+  <input type="hidden" name="valueold" value="[% value FILTER html %]">
+  <input type="hidden" name="sortkeyold" value="[% sortkey FILTER html %]">
+  <input type="hidden" name="action" value="update">
+  <input type="hidden" name="field" value="[% field FILTER html %]">
+  <input type="submit" value="Update">
+
+</form>
+
+<p>
+
+[% PROCESS admin/fieldvalues/footer.html.tmpl
+  no_edit_link = 1 %]
+
+[% PROCESS global/footer.html.tmpl %]
diff --git a/template/en/default/admin/fieldvalues/footer.html.tmpl b/template/en/default/admin/fieldvalues/footer.html.tmpl
new file mode 100644 (file)
index 0000000..05e8c75
--- /dev/null
@@ -0,0 +1,56 @@
+[%# 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.
+  #
+  # Contributor(s): Max Kanat-Alexander <mkanat@kerio.com>
+  #%]
+
+[%# INTERFACE:
+  # value: string; the value being inserted/edited.
+  # field: string; the name of the field which the value
+  #                  belongs/belonged to
+  #
+  # no_XXX_link: boolean; if defined, then don't show the corresponding
+  #                       link. Supported parameters are:
+  #
+  # no_edit_link
+  # no_edit_other_link
+  # no_add_link
+  #%]
+  
+<p>
+
+<hr>
+
+[% UNLESS no_add_link %]
+  <a title="Add a value for the '[% field FILTER html %]' field."
+     href="editvalues.cgi?action=add&amp;field=
+          [%- field FILTER url_quote %]">Add</a> a value.
+[% END %]
+
+[% IF value && !no_edit_milestone_link %]
+  Edit value <a 
+  title="Edit value '[% value FILTER html %]' for the '
+         [%- field FILTER html %]' field"
+  href="editvalues.cgi?action=edit&amp;field=
+        [%- field FILTER url_quote %]&amp;value=[% value FILTER url_quote %]">
+        '[% value FILTER html %]'</a>.
+[% END %]
+
+[% UNLESS no_edit_other_link %]
+  Edit other values for the <a 
+  href="editvalues.cgi?field=
+        [%- field FILTER url_quote %]">'[% field FILTER html %]'</a> field.
+   
+[% END %]
+
+</p>
diff --git a/template/en/default/admin/fieldvalues/list.html.tmpl b/template/en/default/admin/fieldvalues/list.html.tmpl
new file mode 100644 (file)
index 0000000..4f686d3
--- /dev/null
@@ -0,0 +1,73 @@
+[%# 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.
+  #
+  # Contributor(s): Max Kanat-Alexander <mkanat@kerio.com>
+  #%]
+
+[%# INTERFACE:
+  # values: array of hashes having the following properties:
+  #   - name: string; The value.
+  #   - sortkey: number; The sortkey used to order the value when 
+  #              displayed to the user in a list.
+  #
+  # field: string; the name of the field we are editing values for.
+  #%]
+
+[% USE Bugzilla %]
+[% cgi = Bugzilla.cgi %]
+
+[% PROCESS global/variables.none.tmpl %]
+
+[% title = BLOCK %]Select value for the
+                   '[% field FILTER html %]' field[% END %]
+[% PROCESS global/header.html.tmpl
+  title = title
+%]
+
+[% edit_contentlink = BLOCK %]editvalues.cgi?action=edit&amp;field=
+  [%- field FILTER url_quote %]&amp;value=%%name%%[% END %]
+[% delete_contentlink = BLOCK %]editvalues.cgi?action=del&amp;field=
+  [%- field FILTER url_quote %]&amp;value=%%name%%[% END %]
+
+
+[% columns = [
+     { 
+       name => "name"
+       heading => "Edit field value..."
+       contentlink => edit_contentlink
+     },
+     { 
+       name => "sortkey"
+       heading => "Sortkey"
+     },
+   ]
+%]
+
+[% columns.push({
+     heading => "Action"
+     content => "Delete"
+     contentlink => delete_contentlink
+   }) %]
+
+[% PROCESS admin/table.html.tmpl
+     columns = columns
+     data = values
+%]
+
+<p>
+
+[% PROCESS admin/fieldvalues/footer.html.tmpl
+  no_edit_other_link = 1
+ %]
+
+[% PROCESS global/footer.html.tmpl %]
diff --git a/template/en/default/admin/fieldvalues/select-field.html.tmpl b/template/en/default/admin/fieldvalues/select-field.html.tmpl
new file mode 100644 (file)
index 0000000..8342952
--- /dev/null
@@ -0,0 +1,50 @@
+[%# 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.
+  #
+  # Contributor(s): Max Kanat-Alexander <mkanat@kerio.com>
+  #
+  #%]
+
+[%# INTERFACE:
+  #    fields: Array of hashes. Each hash contains only one key, "name."
+  #            The names are the same as the keys from field_descs 
+  #            (see global/field-descs.html.tmpl).
+  #%]
+
+[% USE Bugzilla %]
+[% cgi = Bugzilla.cgi %]
+
+[% PROCESS global/variables.none.tmpl %]
+
+[% PROCESS global/header.html.tmpl
+  title = "Edit values for which field?"
+%]
+
+[% columns = [
+     { 
+       name => "name"
+       heading => "Edit field values for..."
+       content_use_field = 1
+       contentlink => "editvalues.cgi?field=%%name%%"
+     }
+   ]
+%]
+
+[% PROCESS admin/table.html.tmpl
+     columns = columns
+     data = fields
+%]
+
+<p>
+
+[% PROCESS global/footer.html.tmpl %]
diff --git a/template/en/default/admin/fieldvalues/updated.html.tmpl b/template/en/default/admin/fieldvalues/updated.html.tmpl
new file mode 100644 (file)
index 0000000..c19aac2
--- /dev/null
@@ -0,0 +1,51 @@
+[%# 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.
+  #
+  # Contributor(s): Max Kanat-Alexander <mkanat@kerio.com>
+  #%]
+
+[%# INTERFACE:
+  #
+  # 'updated_XXX' variables are booleans, and are defined if the
+  # 'XXX' field was updated during the edit just being handled.
+  # Variables called just 'XXX' are strings, and are the _new_ contents
+  # of the fields.
+  #
+  # value & updated_value: the name of the field value
+  # sortkey & updated_sortkey: the field value sortkey
+  # field: string; the field that the value belongs to
+  #%]
+  
+[% title = BLOCK %]Updating Value '[% value FILTER html %]' of the
+                   '[% field FILTER html %]' Field[% END %]
+[% PROCESS global/header.html.tmpl
+  title = title
+%]
+
+[% IF updated_value %]
+  <p>Updated field value to: '[% value FILTER html %]'.</p>
+[% END %]
+
+[% IF updated_sortkey %]
+  <p>Updated field value sortkey to: '[% sortkey FILTER html %]'.</p>
+[% END %]
+
+[% UNLESS (updated_sortkey || updated_value) %]
+  <p>Nothing changed for field value '[% value FILTER html %]'.
+[% END %]
+   
+<p>
+
+[% PROCESS admin/fieldvalues/footer.html.tmpl %]
+
+[% PROCESS global/footer.html.tmpl %]
index fd1382b14056f9a3db0738a8b56e0646e4ffc0a3..4254f80e19cd22c03a73941c5ebb7e6a04172f1f 100644 (file)
   #     content: If specified, the content of this variable is used
   #              instead of the data pulled from the current row. 
   #              NOTE: This value is not HTML filtered at output!
+  #     content_use_field: If defined and true, then each value in the 
+  #                        column corresponds with a key in the
+  #                        field_descs field, and that value from the 
+  #                        field_descs hash will be used instead of "content."
+  #                        See fieldvalues/select-field for an example of use.
+  #                        This content WILL be HTML-filtered in this case.
   #     align: left/center/right. Controls the horizontal alignment of the
   #            text in the column.
   #     allow_html_content: if defined, then this column allows html content
@@ -46,6 +52,8 @@
   #
   #%]
 
+[% PROCESS "global/field-descs.none.tmpl" %]
+
 [%###################  TABLE HEADER   ######################%]
 
 <table border="1" cellpadding="4" cellspacing="0">
           <a href="[% link_uri %]">
         [% END %]
         
-        [% IF c.content %] 
-          [% c.content %]
+        [% IF c.content_use_field %]
+           [% colname = row.${c.name} %]
+           [% field_descs.${colname} FILTER html %]
+        [% ELSIF c.content %]
+            [% c.content %]
         [% ELSE %]
           [% IF c.yesno_field %]
             [% IF row.${c.name} %]
index b9a69a9e9bdf2488e7fcae6fd4ae9e36ab62bd35..eb8c7e24c06898974c7ac87909edc8c8621ecd8d 100644 (file)
                                                   IF user.groups.tweakparams %]
         [% ' | <a href="editusers.cgi">Users</a>'     IF user.groups.editusers 
                                                   || user.can_bless %]
-        [% IF Param('useclassification') %]
-          [% IF user.groups.editclassifications %]
+        [% IF Param('useclassification') && user.groups.editclassifications %]
             [% ' | <a href="editclassifications.cgi">Classifications</a>' %]
-          [% END %]
-          [% IF user.groups.editcomponents %]
-            [% ' | <a href="editproducts.cgi">Products</a>' %]
-          [% END %]
-        [% ELSE %]
-          [% ' | <a href="editproducts.cgi">Products</a>' 
+        [% END %] 
+        [% ' | <a href="editproducts.cgi">Products</a>' 
                                                IF user.groups.editcomponents %]
-        [% END %]
         [% ' | <a href="editflagtypes.cgi">Flags</a>'
                                                IF user.groups.editcomponents %]
+        [% ' | <a href="editvalues.cgi">Field Values</a>'
+                                               IF user.groups.editcomponents %]
         [% ' | <a href="editgroups.cgi">Groups</a>' 
                                                  IF user.groups.creategroups %]
         [% ' | <a href="editkeywords.cgi">Keywords</a>' 
index 55c7969242ed8255aaecb6b5563ce0c1b3756b7d..47dcaca101fa80e7435096b8d12dc5de4597453f 100644 (file)
     Sorry; you do not have the permissions necessary to enter [% terms.abug %]
     against the [% product FILTER html %] product.
 
+  [% ELSIF error == "fieldname_invalid" %]
+    [% title = "Specified Field Does Not Exist" %]
+    The field '[% field FILTER html %]' does not exist or 
+    cannot be edited with this interface.
+
+  [% ELSIF error == "fieldname_not_specified" %]
+    [% title = "Field Name Not Specified" %]
+    No field name specified when trying to edit field values.
+
+  [% ELSIF error == "fieldvalue_already_exists" %]
+    [% title = "Field Value Already Exists" %]
+    The value '[% value FILTER html %]' already exists for the
+    '[%- field FILTER html %]' field.
+
+  [% ELSIF error == "fieldvalue_doesnt_exist" %]
+    [% title = "Specified Field Value Does Not Exist" %]
+    The value '[% value FILTER html %]' does not exist for
+    the '[% field FILTER html %]' field.
+
+  [% ELSIF error == "fieldvalue_name_too_long" %]
+    [% title = "Field Value Is Too Long" %]
+    The value of a field is limited to 60 characters.
+    '[% value FILTER html %]' is too long ([% value.length %] characters).
+
+  [% ELSIF error == "fieldvalue_not_specified" %]
+    [% title = "Field Value Not Specified" %]
+    No field value specified when trying to edit a field value.
+
+  [% ELSIF error == "fieldvalue_sortkey_invalid" %]
+    [% title = "Invalid Field Value Sortkey" %]
+    The sortkey '[% sortkey FILTER html %]' for the '[% name FILTER html %]'
+    field is not a valid (positive) number.
+
+  [% ELSIF error == "fieldvalue_still_has_bugs" %]
+    [% title = "You Cannot Delete This Field Value" %]
+    You cannot delete the value '[% value FILTER html %]' from the 
+    '[% field FILTER html%]' field, because there are still 
+    [% count FILTER html %] [% terms.bugs %] using it.
+
+  [% ELSIF error == "fieldvalue_undefined" %]
+    [% title = "Undefined Value Not Allowed" %]
+    You must specify a value.
+
   [% ELSIF error == "file_not_specified" %]
     [% title = "No File Specified" %]
     You did not specify a file to attach.