Refactor field create/edit templates, allow to edit nullable property

master
Vitaliy Filippov 2014-03-26 18:50:03 +04:00
parent ed744fab39
commit 0af790c826
5 changed files with 198 additions and 310 deletions

View File

@ -304,26 +304,30 @@ sub _check_type {
return $type;
}
sub _check_value_field_id {
sub _check_value_field_id
{
my ($invocant, $field_id, $is_select) = @_;
$is_select = $invocant->is_select if !defined $is_select;
if ($field_id && !$is_select) {
if ($field_id && !$is_select)
{
ThrowUserError('field_value_control_select_only');
}
return $invocant->_check_visibility_field_id($field_id);
}
sub _check_visibility_field_id {
sub _check_visibility_field_id
{
my ($invocant, $field_id) = @_;
$field_id = trim($field_id);
return undef if !$field_id;
my $field = Bugzilla->get_field($field_id);
if (blessed($invocant) && $field->id == $invocant->id) {
if (blessed($invocant) && $field->id == $invocant->id)
{
ThrowUserError('field_cant_control_self', { field => $field });
}
if (!$field->is_select) {
ThrowUserError('field_control_must_be_select',
{ field => $field });
if (!$field->is_select)
{
ThrowUserError('field_control_must_be_select', { field => $field });
}
return $field->id;
}

View File

@ -51,7 +51,7 @@ if (!$action)
elsif ($action eq 'add')
{
$vars->{token} = issue_session_token('add_field');
$template->process('admin/custom_fields/create.html.tmpl', $vars)
$template->process('admin/custom_fields/edit.html.tmpl', $vars)
|| ThrowTemplateError($template->error());
}
elsif ($action eq 'new')
@ -68,6 +68,7 @@ elsif ($action eq 'new')
enter_bug => scalar $cgi->param('enter_bug'),
clone_bug => scalar $cgi->param('clone_bug'),
obsolete => scalar $cgi->param('obsolete'),
nullable => scalar $cgi->param('nullable'),
custom => 1,
buglist => 1, # FIXME remove non-editable 'buglist' field spec
visibility_field_id => scalar $cgi->param('visibility_field_id'),
@ -109,6 +110,7 @@ elsif ($action eq 'update')
$field->set_sortkey($cgi->param('sortkey'));
$field->set_in_new_bugmail($cgi->param('new_bugmail'));
$field->set_obsolete($cgi->param('obsolete'));
$field->set_nullable($cgi->param('nullable'));
$field->set_url($cgi->param('url'));
if ($field->custom)
{
@ -116,10 +118,18 @@ elsif ($action eq 'update')
# At the moment, though, it has no effect for non-custom fields.
$field->set_enter_bug($cgi->param('enter_bug'));
$field->set_clone_bug($cgi->param('clone_bug'));
$field->set_visibility_field($cgi->param('visibility_field_id'));
$field->set_visibility_values([ $cgi->param('visibility_value_id') ]);
$field->set_value_field($cgi->param('value_field_id'));
$field->set_add_to_deps($cgi->param('add_to_deps'));
my $vf = $cgi->param('visibility_field_id');
if ($field->visibility_field_id != $vf)
{
$field->set_visibility_field($vf);
$field->set_visibility_values([]);
}
else
{
$field->set_visibility_values([ $cgi->param('visibility_value_id') ]);
}
}
$field->update();

View File

@ -1,27 +1,8 @@
[%# 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 NASA.
# Portions created by NASA are Copyright (C) 2008
# San Jose State University Foundation. All Rights Reserved.
#
# Contributor(s): Max Kanat-Alexander <mkanat@bugzilla.org>
[%# License: Dual-license MPL 1.1+ or GPL 3.0+
# Author: Vitaliy Filippov <vitalif@mail.ru>
#%]
// Disable a checkbox based on the state of another one.
function toggleCheckbox(this_checkbox, other_checkbox_id) {
var other_checkbox = document.getElementById(other_checkbox_id);
other_checkbox.disabled = !this_checkbox.checked;
}
[%# FIXME: Move this out from templates into scripts %]
var select_values = new Array();
[% USE Bugzilla %]
@ -33,19 +14,26 @@ select_values[[% sel_field.id FILTER js %]] = [
];
[% END %]
function onChangeType(type_field) {
function onChangeType()
{
var type_field = document.getElementById('type');
var value_field = document.getElementById('value_field_id');
if (type_field.value == [% constants.FIELD_TYPE_SINGLE_SELECT %]
|| type_field.value == [% constants.FIELD_TYPE_MULTI_SELECT %])
value_field.disabled = false;
else
value_field.disabled = true;
var u = type_field.value == [% constants.FIELD_TYPE_EXTURL %];
var u = document.getElementById('nullable');
u.disabled = type_field.value != [% constants.FIELD_TYPE_SINGLE_SELECT %];
if (u.disabled)
u.checked = false;
u = type_field.value == [% constants.FIELD_TYPE_EXTURL %];
document.getElementById('url_title').style.display = u ? '' : 'none';
document.getElementById('url_field').style.display = u ? '' : 'none';
}
function onChangeVisibilityField() {
function onChangeVisibilityField()
{
var vis_field = document.getElementById('visibility_field_id');
var vis_value = document.getElementById('visibility_value_id');
var vis_label = document.getElementById('visibility_value_id_label');
@ -57,5 +45,15 @@ function onChangeVisibilityField() {
bz_populateSelectFromArray(vis_value, values);
}
else
{
bz_clearOptions(vis_value);
}
}
function onChangeEnterBug()
{
var c = document.getElementById('new_bugmail');
c.disabled = !document.getElementById('enter_bug').checked;
if (c.disabled)
c.checked = false;
}

View File

@ -1,164 +0,0 @@
[%# 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 <LpSolit@gmail.com>
#%]
[%# INTERFACE:
# none
#%]
[% javascript = BLOCK %]
[% INCLUDE "admin/custom_fields/cf-js.js.tmpl" %]
[% END %]
[% PROCESS global/header.html.tmpl
title = "Add a new Custom Field"
onload = "document.getElementById('new_bugmail').disabled = true;"
doc_section = "custom-fields.html#add-custom-fields"
%]
<p>
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.
</p>
<ul>
<li>Custom field names must begin with "cf_" to distinguish them from
standard fields. If you omit "cf_" from the beginning of the name, it
will be added for you.</li>
<li>Descriptions are a very short string describing the field and will be
used as the label for this field in the user interface.</li>
</ul>
<form id="add_field" action="editfields.cgi" method="GET">
<table border="0" cellspacing="0" cellpadding="5">
<tr>
<th align="right"><label for="name">Name:</label></th>
<td>
<input type="text" id="name" name="name" value="cf_" size="40" maxlength="64">
</td>
<th align="right">
<label for="enter_bug">Can be set on [% terms.bug %] creation:</label>
</th>
<td>
<input type="checkbox" id="enter_bug" name="enter_bug" value="1"
onchange="toggleCheckbox(this, 'new_bugmail');">
</td>
</tr>
<tr>
<td colspan="2"></td>
<th align="right">
<label for="clone_bug">Is copied into the cloned [% terms.bug %]:</label>
</th>
<td><input type="checkbox" id="clone_bug" name="clone_bug" value="1" checked="checked" /></td>
</tr>
<tr>
<th align="right"><label for="desc">Description:</label></th>
<td><input type="text" id="desc" name="desc" value="" size="40"></td>
<th align="right">
<label for="new_bugmail">Displayed in [% terms.bug %]mail for new [% terms.bugs %]:</label>
</th>
<td><input type="checkbox" id="new_bugmail" name="new_bugmail" value="1"></td>
</tr>
<tr>
<th align="right"><label for="type">Type:</label></th>
<td>
<select id="type" name="type" onchange="onChangeType(this)">
[% FOREACH type = field_types.keys %]
[% NEXT IF type == constants.FIELD_TYPE_UNKNOWN %]
<option value="[% type FILTER html %]">[% field_types.$type FILTER html %]</option>
[% END %]
</select>
</td>
<th align="right"><label for="obsolete">Is obsolete:</label></th>
<td><input type="checkbox" id="obsolete" name="obsolete" value="1"></td>
</tr>
<tr>
<th align="right"><label for="sortkey">Sortkey:</label></th>
<td>
<input type="text" id="sortkey" name="sortkey" size="6" maxlength="6">
</td>
<th align="right">
<label for="visibility_field_id">Field only appears when:</label>
</th>
<td>
<select name="visibility_field_id" id="visibility_field_id"
onchange="onChangeVisibilityField()">
<option></option>
[% FOREACH sel_field = Bugzilla.get_fields({ is_select => 1, obsolete => 0 }) %]
<option value="[% sel_field.id FILTER html %]">
[% sel_field.description FILTER html %]
([% sel_field.name FILTER html %])
</option>
[% END %]
</select>
<label style="display:none" for="visibility_value_id" id="visibility_value_id_label"><strong>&nbsp;is set to one of:</strong></label>
</td>
<td rowspan="2">
<select style="display:none; min-width: 100px" id="visibility_value_id"
name="visibility_value_id" size="7" multiple="multiple">
</select>
</td>
</tr>
<tr>
<th>
<label for="url" id="url_title" style="display: none">
URL template:<br />($1 = target ID)
</label>
</th>
<td>
<input id="url_field" name="url" type="text" size="40" value="" style="display: none" />
</td>
<th>
<label for="value_field_id">
Field that controls the values<br>
that appear in this field:
</label>
</th>
<td>
<select disabled="disabled" name="value_field_id" id="value_field_id">
<option></option>
[% FOREACH sel_field = Bugzilla.get_fields({ is_select => 1, obsolete => 0 }) %]
<option value="[% sel_field.id FILTER html %]">
[% sel_field.description FILTER html %]
([% sel_field.name FILTER html %])
</option>
[% END %]
</select>
</td>
</tr>
</table>
<p>
<input type="hidden" name="action" value="new">
<input type="hidden" name="token" value="[% token FILTER html %]">
<input type="submit" id="create" value="Create">
</p>
</form>
<p>
<a href="editfields.cgi">Back to the list of existing custom fields</a>
</p>
[% PROCESS global/footer.html.tmpl %]

View File

@ -1,4 +1,4 @@
[%# 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/
@ -18,141 +18,177 @@
#%]
[% title = BLOCK %]
Edit the [% "Custom" IF field.custom %] field '[% field.name FILTER html %]' ([% field.description FILTER html %])
[% IF field.id %]
Edit the [% "Custom" IF field.custom %] field '[% field.name | html %]' ([% field.description | html %])
[% ELSE %]
Add a new Custom Field
[% END %]
[% END %]
[% javascript = BLOCK %]
[% INCLUDE "admin/custom_fields/cf-js.js.tmpl" %]
[% END %]
[% PROCESS global/header.html.tmpl
title = title
onload = field.custom ? "toggleCheckbox(document.getElementById('enter_bug'), 'new_bugmail');" : ""
doc_section = "custom-fields.html#edit-custom-fields"
[% PROCESS
global/header.html.tmpl
title = title
doc_section = "custom-fields.html#" _ (field.id ? "edit" : "add") _ "-custom-fields"
%]
<p>
Descriptions are a very short string describing the field and will be used as
the label for this field in the user interface.
[% IF !field.id %]
<p style="font-size: 120%">
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.
</p>
<ul style="font-size: 120%">
<li>Custom field names must begin with "cf_" to distinguish them from
standard fields. If you omit "cf_" from the beginning of the name, it
will be added for you.</li>
<li>Descriptions are a very short string describing the field and will be
used as the label for this field in the user interface.</li>
</ul>
[% END %]
<form id="edit_field" action="editfields.cgi" method="GET">
<table border="0" cellspacing="0" cellpadding="5">
<tr>
<th align="right">Name:</th>
<td>[% field.name FILTER html %]</td>
[% IF field.custom %]
<th align="right">
<label for="enter_bug">Can be set on [% terms.bug %] creation:</label>
</th>
<td><input type="checkbox" id="enter_bug" name="enter_bug" value="1"
[%- " checked" IF field.enter_bug %]
onchange="toggleCheckbox(this, 'new_bugmail');" /></td>
[% END %]
</tr>
[% IF field.custom %]
<tr>
<td colspan="2"></td>
<th align="right">
<label for="clone_bug">Is copied into the cloned [% terms.bug %]:</label>
</th>
<td><input type="checkbox" id="clone_bug" name="clone_bug" value="1"
[%- " checked" IF field.clone_bug %] /></td>
</tr>
[% END %]
<tr>
<th align="right"><label for="desc">Description:</label></th>
<td><input type="text" id="desc" name="desc" size="40"
value="[% field.description FILTER html %]"></td>
<th align="right">
<label for="new_bugmail">Displayed in [% terms.bug %]mail for new [% terms.bugs %]:</label>
</th>
<td><input type="checkbox" id="new_bugmail" name="new_bugmail" value="1"
[%- " checked" IF field.mailhead %]></td>
</tr>
<tr>
<th align="right">Type:</th>
<td>[% field_types.${field.type} FILTER html %]</td>
<th align="right"><label for="obsolete">Is obsolete:</label></th>
<td><input type="checkbox" id="obsolete" name="obsolete" value="1"
[%- " checked" IF field.obsolete %]></td>
</tr>
<tr valign="top">
<th align="right"><label for="sortkey">Sortkey:</label></th>
<th align="left">Name:</th>
<td>
<input type="text" id="sortkey" name="sortkey" size="6" maxlength="6"
value="[% field.sortkey FILTER html %]">
[% IF field.id %]
[% field.name | html %]
[% ELSE %]
<input type="text" id="name" name="name" value="cf_" size="40" maxlength="64" />
[% END %]
</td>
[% IF field.custom %]
<th align="right">
<label for="visibility_field_id">Field only appears when:</label>
[% IF field.custom || !field.id %]
<th align="left">
<label for="enter_bug">Can be set on [% terms.bug %] creation:</label>
</th>
<td valign="top">
<select name="visibility_field_id" id="visibility_field_id"
onchange="onChangeVisibilityField()">
<option></option>
<td>
<input type="checkbox" id="enter_bug" name="enter_bug" value="1"
[%- " checked" IF field.enter_bug %]
onchange="onChangeEnterBug()" />
</td>
[% END %]
</tr>
<tr>
<th align="left"><label for="desc">Title:</label></th>
<td><input type="text" id="desc" name="desc" style="width: 400px" value="[% field.description | html %]" /></td>
<th align="left"><label for="clone_bug">Is copied into the cloned [% terms.bug %]:</label></th>
<td><input type="checkbox" id="clone_bug" name="clone_bug" value="1" [%- " checked" IF field.clone_bug %] /></td>
</tr>
<tr>
<th align="left"><label for="sortkey">Sortkey:</label></th>
<td>
<input type="text" id="sortkey" name="sortkey" size="6"
maxlength="6" value="[% field.sortkey | html %]" />
</td>
<th align="left">
<label for="new_bugmail">Displayed in [% terms.bug %]mail for new [% terms.bugs %]:</label>
</th>
<td><input type="checkbox" id="new_bugmail" name="new_bugmail" value="1" [%- " checked" IF field.mailhead %] /></td>
</tr>
<tr>
<th align="left">Type:</th>
<td>
[% IF field.id %]
[% field_types.${field.type} | html %]
[% ELSE %]
<select id="type" name="type" onchange="onChangeType()">
[% FOREACH type = field_types.keys %]
[% NEXT IF type == constants.FIELD_TYPE_UNKNOWN %]
<option value="[% type | html %]">[% field_types.$type | html %]</option>
[% END %]
</select>
[% END %]
</td>
<th align="left"><label for="obsolete">Is obsolete:</label></th>
<td>
<input type="checkbox" id="obsolete" name="obsolete" value="1"
[%- " checked" IF field.obsolete %] />
</td>
</tr>
[% IF field.is_select AND field.name != 'product' || !field.id %]
<tr valign="top">
<td></td>
<td>
[% IF field.id %]
<a href="editvalues.cgi?field=[% field.name | url_quote %]">Edit legal values for this field</a>
[% END %]
</td>
[% IF !field.id || field.type == constants.FIELD_TYPE_SINGLE_SELECT %]
<th align="left"><label for="nullable">Allow empty value:</label></th>
<td>
<input type="checkbox" id="nullable" name="nullable"
value="1" [%- " checked" IF field.nullable %] />
</td>
[% END %]
</tr>
[% END %]
[% IF field.custom || !field.id %]
<tr valign="top">
<th align="left" colspan="2"><label for="visibility_field_id">
Show/hide the field depending on the value of:
</label></th>
<td colspan="2">
<select style="width: 400px" name="visibility_field_id" id="visibility_field_id" onchange="onChangeVisibilityField()">
<option value="">---</option>
[% FOREACH sel_field = Bugzilla.get_fields({ is_select => 1 }) %]
[%# FIXME now, fields with non-unique value name is not allowed %]
[% NEXT IF sel_field.id == field.id || sel_field.name == "component" ||
sel_field.name == "version" || sel_field.name == "target_milestone" %]
<option value="[% sel_field.id FILTER html %]"
[% ' selected="selected"'
IF sel_field.id == field.visibility_field.id %]>
[% sel_field.description FILTER html %]
([% sel_field.name FILTER html %])
</option>
[% END %]
</select>
<label for="visibility_value_id"><strong>&nbsp;is set to one of:</strong></label>
</td>
<td rowspan="2">
<select style="min-width: 100px" id="visibility_value_id"
name="visibility_value_id" size="7" multiple="multiple">
[% FOREACH value = field.visibility_field.legal_values %]
<option value="[% value.id FILTER html %]"[% ' selected="selected"' IF field.has_visibility_value(value.id) %]>
[% value.name FILTER html %]
<option value="[% sel_field.id | html %]"
[% ' selected="selected"' IF sel_field.id == field.visibility_field.id %]>
[% sel_field.description | html %]
([% sel_field.name | html %])
</option>
[% END %]
</select>
</td>
[% END %]
</tr>
[% IF field.is_select AND field.name != 'product' %]
<tr>
<th>&nbsp;</th>
<td>
<a href="editvalues.cgi?field=[% field.name FILTER url_quote %]">Edit
legal values for this field</a>.
</td>
[% IF field.custom %]
<th>
<label for="value_field_id">
Field that controls the values<br>
that appear in this field:
</label>
</th>
<td>
<select name="value_field_id" id="value_field_id">
<option></option>
<tr valign="top">
<th colspan="2" align="left"><label for="value_field_id">
Field that controls the values that appear in this field:
</label></th>
<td colspan="2">
<select style="width: 400px" name="value_field_id" id="value_field_id">
<option value="">---</option>
[% FOREACH sel_field = Bugzilla.get_fields({ is_select => 1 }) %]
[% NEXT IF sel_field.id == field.id %]
<option value="[% sel_field.id FILTER html %]"
[% ' selected="selected"'
IF sel_field.id == field.value_field.id %]>
[% sel_field.description FILTER html %]
([% sel_field.name FILTER html %])
<option value="[% sel_field.id | html %]"
[% ' selected="selected"' IF sel_field.id == field.value_field.id %]>
[% sel_field.description | html %]
([% sel_field.name | html %])
</option>
[% END %]
</select>
</td>
[% END %]
</tr>
[% IF field.visibility_field %]
<tr valign="top">
<th colspan="2" align="left"><label for="visibility_value_id">
Show the field only if [% field.visibility_field.description | html %] is set to:
</label></th>
<td colspan="2">
[% SET all = field.has_all_visibility_values %]
<select style="width: 400px" id="visibility_value_id"
name="visibility_value_id" size="7" multiple="multiple">
[% FOREACH value = field.visibility_field.legal_values %]
<option value="[% value.id | html %]"[% ' selected="selected"' IF !all && field.has_visibility_value(value.id) %]>
[% value.name | html %]
</option>
[% END %]
</select>
</td>
</tr>
[% END %]
[% END %]
[% IF field.type == constants.FIELD_TYPE_BUG_ID %]
@ -181,18 +217,16 @@
</tr>
[% END %]
</table>
<input type="hidden" name="action" value="update">
<input type="hidden" name="name" value="[% field.name FILTER html %]">
<input type="hidden" name="token" value="[% token FILTER html %]">
<input type="submit" id="edit" value="Submit">
<input type="hidden" name="action" value="[% field.id ? "update" : "new" %]" />
<input type="hidden" name="name" value="[% field.name | html %]" />
<input type="hidden" name="token" value="[% token | html %]" />
<input type="submit" id="edit" value="[% IF field.id %]Save[% ELSE %]Create[% END %]" />
</form>
[% IF field.obsolete AND field.custom %]
<p>
<a href="editfields.cgi?action=del&amp;name=[% field.name FILTER html %]">Remove
this custom field from the database.</a><br>
This action will only be successful if the custom field has never been used
in [% terms.abug %].<br>
<a href="editfields.cgi?action=del&amp;name=[% field.name | html %]">Remove this custom field from the database.</a><br />
This action will only be successful if the custom field has never been used in [% terms.abug %].
</p>
[% END %]
@ -200,4 +234,10 @@
<a href="editfields.cgi">Back to the list of existing fields</a>
</p>
<script>
onChangeEnterBug();
onChangeType();
onChangeVisibilityField();
</script>
[% PROCESS global/footer.html.tmpl %]