From 0e70cd46fe9377b9a267a8e1efbc6f8e7064e95e Mon Sep 17 00:00:00 2001 From: "lpsolit%gmail.com" <> Date: Sun, 20 Aug 2006 06:02:55 +0000 Subject: Bug 344875: Implement a UI to manage custom fields and remove customfield.pl - Patch by Frédéric Buclin r=mkanat a=myk MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Bugzilla/Field.pm | 48 +++++++-- customfield.pl | 89 --------------- editfields.cgi | 120 +++++++++++++++++++++ .../default/admin/custom_fields/create.html.tmpl | 111 +++++++++++++++++++ .../en/default/admin/custom_fields/edit.html.tmpl | 99 +++++++++++++++++ .../en/default/admin/custom_fields/list.html.tmpl | 63 +++++++++++ template/en/default/global/user-error.html.tmpl | 30 +++++- 7 files changed, 462 insertions(+), 98 deletions(-) delete mode 100755 customfield.pl create mode 100644 editfields.cgi create mode 100644 template/en/default/admin/custom_fields/create.html.tmpl create mode 100644 template/en/default/admin/custom_fields/edit.html.tmpl create mode 100644 template/en/default/admin/custom_fields/list.html.tmpl diff --git a/Bugzilla/Field.pm b/Bugzilla/Field.pm index c6c889957..cd510471d 100644 --- a/Bugzilla/Field.pm +++ b/Bugzilla/Field.pm @@ -93,6 +93,8 @@ use constant DB_COLUMNS => ( 'description', 'type', 'custom', + 'mailhead', + 'sortkey', 'obsolete', 'enter_bug', ); @@ -216,6 +218,31 @@ sub custom { return $_[0]->{custom} } =over +=item C + +a boolean specifying whether or not the field is displayed in bugmail +for newly-created bugs; + +=back + +=cut + +sub in_new_bugmail { return $_[0]->{mailhead} } + +=over + +=item C + +an integer specifying the sortkey of the field. + +=back + +=cut + +sub sortkey { return $_[0]->{sortkey} } + +=over + =item C a boolean specifying whether or not the field is obsolete; @@ -256,8 +283,14 @@ Params: This function takes named parameters in a hashref: C - string - The field label to display in the UI. C - boolean - Whether this field appears at the top of the bugmail for a newly-filed bug. + + The following parameters are only available on field creation: C - boolean - True if this is a Custom Field. The field will be added to the C table if it does not exist. + C - integer - The sortkey of the field. + C - boolean - Whether this field is + editable on the bug creation form. + C - boolean - Whether this field is obsolete. Returns: a C object. @@ -267,12 +300,16 @@ Returns: a C object. sub create_or_update { my ($params) = @_; - + my $custom = $params->{custom} ? 1 : 0; my $name = $params->{name}; my $in_new_bugmail = $params->{in_new_bugmail} ? 1 : 0; + my $sortkey = $params->{sortkey} || 0; + my $enter_bug = $params->{editable_on_enter_bug} ? 1 : 0; + my $is_obsolete = $params->{is_obsolete} ? 1 : 0; # Some day we'll allow invocants to specify the field type. + # We don't care about $params->{type} yet. my $type = $custom ? FIELD_TYPE_FREETEXT : FIELD_TYPE_UNKNOWN; my $field = new Bugzilla::Field({name => $name}); @@ -285,16 +322,15 @@ sub create_or_update { undef, $params->{desc}, $in_new_bugmail, $field->id); } else { - # Some day we'll allow invocants to specify the sort key. - my ($sortkey) = $dbh->selectrow_array( + $sortkey ||= $dbh->selectrow_array( "SELECT MAX(sortkey) + 100 FROM fielddefs") || 100; # Add the field to the list of fields at this Bugzilla installation. $dbh->do("INSERT INTO fielddefs (name, description, sortkey, type, - custom, mailhead) - VALUES (?, ?, ?, ?, ?, ?)", undef, + custom, mailhead, obsolete, enter_bug) + VALUES (?, ?, ?, ?, ?, ?, ?, ?)", undef, $name, $params->{desc}, $sortkey, $type, $custom, - $in_new_bugmail); + $in_new_bugmail, $is_obsolete, $enter_bug); } if (!$dbh->bz_column_info('bugs', $name) && $custom) { diff --git a/customfield.pl b/customfield.pl deleted file mode 100755 index b5b9fd07b..000000000 --- a/customfield.pl +++ /dev/null @@ -1,89 +0,0 @@ -#!/usr/bin/perl -wT -# -*- Mode: perl; indent-tabs-mode: nil -*- -# -# 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 - -################################################################################ -# Script Initialization -################################################################################ - -use strict; - -use lib "."; - -use Bugzilla; -use Bugzilla::Field; -use Getopt::Long; - -my ($name, $desc); -my $result = GetOptions("name=s" => \$name, - "description|desc=s" => \$desc); - -if (!$name or !$desc) { - my $command = - $^O =~ /MSWin32/i ? "perl -T customfield.pl" : "./customfield.pl"; - print < --desc="" - - is the name of the custom field in the database. - The string "cf_" will be prepended to this name to distinguish - the field from standard fields. This name must conform to the - naming rules for the database server you use. - - is a short string describing the field. It will - be displayed to Bugzilla users in several parts of Bugzilla's UI, - for example as the label for the field on the "show bug" page. - -Warning: - - Custom fields can make Bugzilla less usable. See this URL - for alternatives to custom fields: - - http://www.gerv.net/hacking/custom-fields.html - - You should try to implement applicable alternatives before using - this script to add a custom field. -END - - exit; -} - -# Prepend cf_ to the custom field name to distinguish it from standard fields. -$name =~ /^cf_/ - or $name = "cf_" . $name; - -# Exit gracefully if there is already a field with the given name. -if ( new Bugzilla::Field({name => $name}) ) { - print "There is already a field named $name. Please choose " . - "a different name.\n"; - exit; -} - - -# Create the field. -print "Creating custom field $name ...\n"; -Bugzilla::Field::create_or_update( - {name => $name, desc => $desc, custom => 1}); -print "Custom field $name created.\n"; diff --git a/editfields.cgi b/editfields.cgi new file mode 100644 index 000000000..17db14092 --- /dev/null +++ b/editfields.cgi @@ -0,0 +1,120 @@ +#!/usr/bin/perl -wT +# -*- Mode: perl; indent-tabs-mode: nil -*- +# +# 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): Frédéric Buclin + +use strict; +use lib "."; + +use Bugzilla; +use Bugzilla::Constants; +use Bugzilla::Error; +use Bugzilla::Util; +use Bugzilla::Field; + +my $cgi = Bugzilla->cgi; +my $template = Bugzilla->template; +my $vars = {}; + +# Make sure the user is logged in and is an administrator. +my $user = Bugzilla->login(LOGIN_REQUIRED); +$user->in_group('admin') + || ThrowUserError('auth_failure', {group => 'admin', + action => 'edit', + object => 'custom_fields'}); + +my $action = trim($cgi->param('action') || ''); + +print $cgi->header(); + +# List all existing custom fields if no action is given. +if (!$action) { + $vars->{'custom_fields'} = [Bugzilla->get_fields({'custom' => 1})]; + + $template->process('admin/custom_fields/list.html.tmpl', $vars) + || ThrowTemplateError($template->error()); +} +# Interface to add a new custom field. +elsif ($action eq 'add') { + $template->process('admin/custom_fields/create.html.tmpl') + || ThrowTemplateError($template->error()); +} +elsif ($action eq 'new') { + my $name = clean_text($cgi->param('name') || ''); + my $desc = clean_text($cgi->param('desc') || ''); + # For now, there is only one type available for custom fields. + # In the future, we will have to look at $cgi->param('type'). + my $type = FIELD_TYPE_FREETEXT; + my $sortkey = $cgi->param('sortkey') || 0; + + # Validate these fields. + $name || ThrowUserError('customfield_missing_name'); + # Prepend cf_ to the custom field name to distinguish it from standard fields. + if ($name !~ /^cf_/) { + $name = 'cf_' . $name; + } + my $field = new Bugzilla::Field({'name' => $name}); + ThrowUserError('customfield_already_exists', {'field' => $field }) if $field; + + $desc || ThrowUserError('customfield_missing_description', {'name' => $name}); + + my $skey = $sortkey; + detaint_natural($sortkey) + || ThrowUserError('customfield_invalid_sortkey', {'name' => $name, + 'sortkey' => $skey}); + + # All fields have been validated. We can create this new custom field. + trick_taint($name); + trick_taint($desc); + + $vars->{'name'} = $name; + $vars->{'desc'} = $desc; + $vars->{'sortkey'} = $sortkey; + $vars->{'type'} = $type; + $vars->{'custom'} = 1; + $vars->{'in_new_bugmail'} = $cgi->param('new_bugmail') ? 1 : 0; + $vars->{'editable_on_enter_bug'} = $cgi->param('enter_bug') ? 1 : 0; + $vars->{'is_obsolete'} = $cgi->param('obsolete') ? 1 : 0; + + Bugzilla::Field::create_or_update($vars); + + $vars->{'custom_fields'} = [Bugzilla->get_fields({'custom' => 1})]; + + $template->process('admin/custom_fields/list.html.tmpl', $vars) + || ThrowTemplateError($template->error()); +} +elsif ($action eq 'edit') { + my $name = $cgi->param('name') || ThrowUserError('customfield_missing_name'); + trick_taint($name); + my @field = Bugzilla->get_fields({'name' => $name, 'custom' => 1}); + scalar(@field) || ThrowUserError('customfield_nonexistent', {'name' => $name}); + + $vars->{'field'} = $field[0]; + + $template->process('admin/custom_fields/edit.html.tmpl', $vars) + || ThrowTemplateError($template->error()); +} +elsif ($action eq 'update') { + die "not yet implemented...\n"; +} +elsif ($action eq 'del') { + die "not yet implemented...\n"; +} +elsif ($action eq 'delete') { + die "not yet implemented...\n"; +} +else { + ThrowUserError('no_valid_action', {'field' => 'custom_field'}); +} diff --git a/template/en/default/admin/custom_fields/create.html.tmpl b/template/en/default/admin/custom_fields/create.html.tmpl new file mode 100644 index 000000000..b366371bd --- /dev/null +++ b/template/en/default/admin/custom_fields/create.html.tmpl @@ -0,0 +1,111 @@ +[%# 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): Frédéric Buclin + #%] + +[%# INTERFACE: + # none + #%] + +[% PROCESS "global/field-descs.none.tmpl" %] + +[% PROCESS global/header.html.tmpl + title = "Add a new Custom Field" + onload = "document.getElementById('new_bugmail').disabled = true;" %] + + + +

+ Adding custom fields can make the interface of [% terms.Bugzilla %] very + complicated. Many admins who are new to [% terms.Bugzilla %] start off + adding many custom fields, and then their users complain that the interface + is "too complex". Please think carefully before adding any custom fields. + It may be the case that [% terms.Bugzilla %] already does what you need, + and you just haven't enabled the correct feature yet. + +

    +
  • Custom field names must begin with "cf_" to distinguish them from standard + fields. If you omit "cf_" from the name, it will automatically be appended.
  • +
  • Descriptions are a very short string describing the field and will be used + as the label for this field in the user interface.
  • +
+
+

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ +
+ [%# Only one field type is valid right now. But let's prepare the UI + # for future new types. %] + +
+ +   
+
+ + +
+ +

+ Back to the list of existing custom fields +

+ +[% PROCESS global/footer.html.tmpl %] diff --git a/template/en/default/admin/custom_fields/edit.html.tmpl b/template/en/default/admin/custom_fields/edit.html.tmpl new file mode 100644 index 000000000..cb7b56a0a --- /dev/null +++ b/template/en/default/admin/custom_fields/edit.html.tmpl @@ -0,0 +1,99 @@ +[%# 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): Frédéric Buclin + #%] + +[%# INTERFACE: + # none + #%] + +[% PROCESS "global/field-descs.none.tmpl" %] + +[% title = BLOCK %] + Edit the Custom Field '[% field.name FILTER html %]' ([% field.description FILTER html %]) +[% END %] + +[% PROCESS global/header.html.tmpl + title = title + onload = "toggleCheckbox(document.getElementById('enter_bug'), 'new_bugmail');" %] + + + +

+ Descriptions are a very short string describing the field and will be used as + the label for this field in the user interface. +

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name:[% field.name FILTER html %] + +
+ +
Type:Free Text
+ +   
+
+ + + +
+ +

+ Back to the list of existing custom fields +

+ +[% PROCESS global/footer.html.tmpl %] diff --git a/template/en/default/admin/custom_fields/list.html.tmpl b/template/en/default/admin/custom_fields/list.html.tmpl new file mode 100644 index 000000000..e02609dd3 --- /dev/null +++ b/template/en/default/admin/custom_fields/list.html.tmpl @@ -0,0 +1,63 @@ +[%# 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): Frédéric Buclin + #%] + +[%# INTERFACE: + # custom_fields: a list of Bugzilla::Field objects, representing custom fields. + #%] + +[% PROCESS "global/field-descs.none.tmpl" %] + +[% PROCESS global/header.html.tmpl title = "Custom Fields" %] + +[% columns = [ + { + name => "name" + heading => "Edit custom field..." + contentlink => "editfields.cgi?action=edit&name=%%name%%" + }, + { + name => "description" + heading => "Description" + }, + { + name => "sortkey" + heading => "Sortkey" + }, + { + name => "enter_bug" + heading => "Editable on Bug Creation" + }, + { + name => "mailhead" + heading => "In Bugmail on Bug Creation" + }, + { + name => "obsolete" + heading => "Is Obsolete" + } + ] +%] + +[% PROCESS admin/table.html.tmpl + columns = columns + data = custom_fields +%] + +

+ Add a new custom field +

+ +[% PROCESS global/footer.html.tmpl %] diff --git a/template/en/default/global/user-error.html.tmpl b/template/en/default/global/user-error.html.tmpl index e67c1a81c..e07be8846 100644 --- a/template/en/default/global/user-error.html.tmpl +++ b/template/en/default/global/user-error.html.tmpl @@ -158,6 +158,8 @@ classifications [% ELSIF object == "components" %] components + [% ELSIF object == "custom_fields" %] + custom fields [% ELSIF object == "flagtypes" %] flag types [% ELSIF object == "group_access" %] @@ -307,9 +309,27 @@ Product [% product FILTER html %] does not have a component named [% name FILTER html %]. - [% ELSIF error == "product_doesnt_exist" %] - [% title = "Specified Product Does Not Exist" %] - The product '[% product FILTER html %]' does not exist. + [% ELSIF error == "customfield_already_exists" %] + [% title = "Field Already Exists" %] + The field '[% field.name FILTER html %]' ([% field.description FILTER html %]) + already exists. Please choose another name. + + [% ELSIF error == "customfield_nonexistent" %] + [% title = "Unknown Custom Field" %] + There is no custom field with the name '[% name FILTER html %]'. + + [% ELSIF error == "customfield_invalid_sortkey" %] + [% title = "Invalid Sortkey for Field" %] + The sortkey [% sortkey FILTER html %] that you have provided for + the '[% name FILTER html %]' field is not a valid positive integer. + + [% ELSIF error == "customfield_missing_description" %] + [% title = "Missing Description for Field" %] + You must enter a description for the '[% name FILTER html %]' field. + + [% ELSIF error == "customfield_missing_name" %] + [% title = "Missing Name for Field" %] + You must enter a name for this field. [% ELSIF error == "dependency_loop_multi" %] [% title = "Dependency Loop Detected" %] @@ -1086,6 +1106,10 @@ Patches cannot be more than [% Param('maxpatchsize') %] KB in size. Try breaking your patch into several pieces. + [% ELSIF error == "product_doesnt_exist" %] + [% title = "Specified Product Does Not Exist" %] + The product '[% product FILTER html %]' does not exist. + [% ELSIF error == "product_votes_per_bug_must_be_nonnegative" %] [% title = "Maximum Votes Must Be Non-negative" %] [% admindocslinks = {'voting.html' => 'Setting up the voting feature'} %] -- cgit v1.2.3-24-g4f1b