Add nullable property for fields
parent
b2d8118048
commit
1cd3cae485
|
@ -102,9 +102,10 @@ sub get_param_list
|
|||
my $legal = {};
|
||||
for (qw(priority bug_severity platform op_sys))
|
||||
{
|
||||
$legal->{$_} = [ Bugzilla->get_field($_)->legal_value_names ];
|
||||
# Ignore evaluation errors - this piece of code may be called in checksetup.pl,
|
||||
# fielddefs table may not be created at that time...
|
||||
$legal->{$_} = eval { Bugzilla->get_field($_)->legal_value_names } || [];
|
||||
}
|
||||
|
||||
my @param_list = (
|
||||
{
|
||||
name => 'useclassification',
|
||||
|
|
|
@ -541,6 +541,7 @@ use constant ABSTRACT_SCHEMA => {
|
|||
mailhead => {TYPE => 'BOOLEAN', NOTNULL => 1, DEFAULT => 'FALSE'},
|
||||
sortkey => {TYPE => 'INT2', NOTNULL => 1},
|
||||
obsolete => {TYPE => 'BOOLEAN', NOTNULL => 1, DEFAULT => 'FALSE'},
|
||||
nullable => {TYPE => 'BOOLEAN', NOTNULL => 1, DEFAULT => 'FALSE'},
|
||||
enter_bug => {TYPE => 'BOOLEAN', NOTNULL => 1, DEFAULT => 'FALSE'},
|
||||
buglist => {TYPE => 'BOOLEAN', NOTNULL => 1, DEFAULT => 'FALSE'},
|
||||
visibility_field_id => {TYPE => 'INT4', REFERENCES => {TABLE => 'fielddefs', COLUMN => 'id'}},
|
||||
|
|
|
@ -102,6 +102,7 @@ use constant DB_COLUMNS => qw(
|
|||
mailhead
|
||||
sortkey
|
||||
obsolete
|
||||
nullable
|
||||
enter_bug
|
||||
clone_bug
|
||||
buglist
|
||||
|
@ -123,6 +124,7 @@ use constant VALIDATORS => {
|
|||
buglist => \&Bugzilla::Object::check_boolean,
|
||||
mailhead => \&Bugzilla::Object::check_boolean,
|
||||
obsolete => \&Bugzilla::Object::check_boolean,
|
||||
nullable => \&Bugzilla::Object::check_boolean,
|
||||
sortkey => \&_check_sortkey,
|
||||
type => \&_check_type,
|
||||
visibility_field_id => \&_check_visibility_field_id,
|
||||
|
@ -138,6 +140,7 @@ use constant UPDATE_COLUMNS => qw(
|
|||
mailhead
|
||||
sortkey
|
||||
obsolete
|
||||
nullable
|
||||
enter_bug
|
||||
clone_bug
|
||||
buglist
|
||||
|
@ -168,7 +171,7 @@ use constant SQL_DEFINITIONS => {
|
|||
# These are used by populate_field_definitions to populate
|
||||
# the fielddefs table.
|
||||
use constant DEFAULT_FIELDS => (
|
||||
{name => 'bug_id', desc => 'Bug ID', buglist => 1, in_new_bugmail => 1},
|
||||
{name => 'bug_id', desc => 'Bug ID', buglist => 1, in_new_bugmail => 1},
|
||||
{name => 'short_desc', desc => 'Summary', buglist => 1, in_new_bugmail => 1},
|
||||
{name => 'classification', desc => 'Classification', buglist => 1, in_new_bugmail => 1},
|
||||
{name => 'product', desc => 'Product', buglist => 1, in_new_bugmail => 1, type => FIELD_TYPE_SINGLE_SELECT},
|
||||
|
@ -426,10 +429,21 @@ sub obsolete { return $_[0]->{obsolete} }
|
|||
|
||||
=over
|
||||
|
||||
=item C<nullable>
|
||||
|
||||
a boolean specifying whether NULL value is allowed for this field
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
||||
|
||||
sub nullable { return $_[0]->{nullable} }
|
||||
|
||||
=over
|
||||
|
||||
=item C<enter_bug>
|
||||
|
||||
A boolean specifying whether or not this field should appear on
|
||||
enter_bug.cgi
|
||||
A boolean specifying whether this field should appear on enter_bug.cgi
|
||||
|
||||
=back
|
||||
|
||||
|
@ -736,6 +750,8 @@ They will throw an error if you try to set the values to something invalid.
|
|||
|
||||
=item C<set_obsolete>
|
||||
|
||||
=item C<set_nullable>
|
||||
|
||||
=item C<set_sortkey>
|
||||
|
||||
=item C<set_in_new_bugmail>
|
||||
|
@ -754,6 +770,7 @@ sub set_description { $_[0]->set('description', $_[1]); }
|
|||
sub set_enter_bug { $_[0]->set('enter_bug', $_[1]); }
|
||||
sub set_clone_bug { $_[0]->set('clone_bug', $_[1]); }
|
||||
sub set_obsolete { $_[0]->set('obsolete', $_[1]); }
|
||||
sub set_nullable { $_[0]->set('nullable', $_[1]); }
|
||||
sub set_sortkey { $_[0]->set('sortkey', $_[1]); }
|
||||
sub set_in_new_bugmail { $_[0]->set('mailhead', $_[1]); }
|
||||
sub set_buglist { $_[0]->set('buglist', $_[1]); }
|
||||
|
|
|
@ -1,31 +1,10 @@
|
|||
# -*- 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 Initial Developer of the Original Code is NASA.
|
||||
# Portions created by NASA are Copyright (C) 2006 San Jose State
|
||||
# University Foundation. All Rights Reserved.
|
||||
#
|
||||
# The Original Code is the Bugzilla Bug Tracking System.
|
||||
#
|
||||
# Contributor(s): Max Kanat-Alexander <mkanat@bugzilla.org>
|
||||
# Greg Hendricks <ghendricks@novell.com>
|
||||
# Vitaliy Filippov <vitalif@mail.ru>
|
||||
# Class representing single value of a field
|
||||
# Nearly 100% refactored
|
||||
# Author(s): Vitaliy Filippov <vitalif@mail.ru>, Max Kanat-Alexander <mkanat@bugzilla.org>, Greg Hendricks <ghendricks@novell.com>
|
||||
# License: Dual-license GPL 3.0+ or MPL 1.1+
|
||||
|
||||
use strict;
|
||||
|
||||
##############################################
|
||||
# Class representing single value of a field #
|
||||
##############################################
|
||||
|
||||
package Bugzilla::Field::Choice;
|
||||
|
||||
use base qw(Bugzilla::Object);
|
||||
|
@ -139,9 +118,11 @@ EOC
|
|||
# We just make new() enforce this, which should give developers
|
||||
# the understanding that you can't use Bugzilla::Field::Choice
|
||||
# without calling type().
|
||||
sub new {
|
||||
sub new
|
||||
{
|
||||
my $class = shift;
|
||||
if ($class eq 'Bugzilla::Field::Choice') {
|
||||
if ($class eq 'Bugzilla::Field::Choice')
|
||||
{
|
||||
ThrowCodeError('field_choice_must_use_type');
|
||||
}
|
||||
$class->SUPER::new(@_);
|
||||
|
@ -164,7 +145,8 @@ sub create
|
|||
return $self;
|
||||
}
|
||||
|
||||
sub update {
|
||||
sub update
|
||||
{
|
||||
my $self = shift;
|
||||
my $dbh = Bugzilla->dbh;
|
||||
my $fname = $self->field->name;
|
||||
|
@ -172,7 +154,8 @@ sub update {
|
|||
$dbh->bz_start_transaction();
|
||||
|
||||
my ($changes, $old_self) = $self->SUPER::update(@_);
|
||||
if (exists $changes->{$self->NAME_FIELD}) {
|
||||
if (exists $changes->{$self->NAME_FIELD})
|
||||
{
|
||||
my ($old, $new) = @{ $changes->{$self->NAME_FIELD} };
|
||||
if ($self->field->type != FIELD_TYPE_MULTI_SELECT)
|
||||
{
|
||||
|
@ -185,8 +168,8 @@ sub update {
|
|||
$dbh->do("UPDATE bugs SET $fname = ?, lastdiffed = NOW() WHERE $fname = ?",
|
||||
undef, $new, $old);
|
||||
}
|
||||
|
||||
if ($old_self->is_default) {
|
||||
if ($old_self->is_default)
|
||||
{
|
||||
my $param = $self->DEFAULT_MAP->{$self->field->name};
|
||||
SetParam($param, $self->name);
|
||||
write_params();
|
||||
|
@ -198,21 +181,30 @@ sub update {
|
|||
return wantarray ? ($changes, $old_self) : $changes;
|
||||
}
|
||||
|
||||
sub remove_from_db {
|
||||
sub remove_from_db
|
||||
{
|
||||
my $self = shift;
|
||||
if ($self->is_default) {
|
||||
ThrowUserError('fieldvalue_is_default',
|
||||
{ field => $self->field, value => $self,
|
||||
param_name => $self->DEFAULT_MAP->{$self->field->name},
|
||||
});
|
||||
if ($self->is_default)
|
||||
{
|
||||
ThrowUserError('fieldvalue_is_default', {
|
||||
field => $self->field,
|
||||
value => $self,
|
||||
param_name => $self->DEFAULT_MAP->{$self->field->name},
|
||||
});
|
||||
}
|
||||
if ($self->is_static) {
|
||||
ThrowUserError('fieldvalue_not_deletable',
|
||||
{ field => $self->field, value => $self });
|
||||
if ($self->is_static)
|
||||
{
|
||||
ThrowUserError('fieldvalue_not_deletable', {
|
||||
field => $self->field,
|
||||
value => $self,
|
||||
});
|
||||
}
|
||||
if ($self->bug_count) {
|
||||
ThrowUserError('fieldvalue_still_has_bugs',
|
||||
{ field => $self->field, value => $self });
|
||||
if ($self->bug_count)
|
||||
{
|
||||
ThrowUserError('fieldvalue_still_has_bugs', {
|
||||
field => $self->field,
|
||||
value => $self,
|
||||
});
|
||||
}
|
||||
$self->_check_if_controller();
|
||||
$self->set_visibility_values(undef);
|
||||
|
@ -353,20 +345,20 @@ sub _check_if_controller
|
|||
sub is_active { return $_[0]->{'isactive'}; }
|
||||
sub sortkey { return $_[0]->{'sortkey'}; }
|
||||
|
||||
sub bug_count {
|
||||
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_id = ?", undef, $self->id);
|
||||
if ($self->field->type == FIELD_TYPE_MULTI_SELECT)
|
||||
{
|
||||
$count = $dbh->selectrow_array("SELECT COUNT(*) FROM bug_$fname WHERE value_id = ?", undef, $self->id);
|
||||
}
|
||||
else {
|
||||
$count = $dbh->selectrow_array("SELECT COUNT(*) FROM bugs
|
||||
WHERE $fname = ?",
|
||||
undef, $self->name);
|
||||
else
|
||||
{
|
||||
$count = $dbh->selectrow_array("SELECT COUNT(*) FROM bugs WHERE $fname = ?", undef, $self->id);
|
||||
}
|
||||
$self->{bug_count} = $count;
|
||||
return $count;
|
||||
|
@ -378,7 +370,8 @@ sub field
|
|||
return Bugzilla->get_field($invocant->FIELD_NAME);
|
||||
}
|
||||
|
||||
sub is_default {
|
||||
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
|
||||
|
@ -389,14 +382,6 @@ sub is_default {
|
|||
|
||||
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;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -529,14 +514,15 @@ sub set_visibility_values
|
|||
my ($value_ids) = @_;
|
||||
update_visibility_values($self->field, $self->id, $value_ids);
|
||||
delete $self->{visibility_values};
|
||||
return 1;
|
||||
return $value_ids;
|
||||
}
|
||||
|
||||
##############
|
||||
# Validators #
|
||||
##############
|
||||
|
||||
sub _check_value {
|
||||
sub _check_value
|
||||
{
|
||||
my ($invocant, $value) = @_;
|
||||
|
||||
my $field = $invocant->field;
|
||||
|
@ -544,11 +530,9 @@ sub _check_value {
|
|||
$value = trim($value);
|
||||
|
||||
# Make sure people don't rename static values
|
||||
if (blessed($invocant) && $value ne $invocant->name
|
||||
&& $invocant->is_static)
|
||||
if (blessed($invocant) && $value ne $invocant->name && $invocant->is_static)
|
||||
{
|
||||
ThrowUserError('fieldvalue_not_editable',
|
||||
{ field => $field, old_value => $invocant });
|
||||
ThrowUserError('fieldvalue_not_editable', { field => $field, old_value => $invocant });
|
||||
}
|
||||
|
||||
ThrowUserError('fieldvalue_undefined') if !defined $value || $value eq "";
|
||||
|
@ -556,24 +540,25 @@ sub _check_value {
|
|||
if length($value) > MAX_FIELD_VALUE_SIZE;
|
||||
|
||||
my $exists = $invocant->type($field)->new({ name => $value });
|
||||
if ($exists && (!blessed($invocant) || $invocant->id != $exists->id)) {
|
||||
ThrowUserError('fieldvalue_already_exists',
|
||||
{ field => $field, value => $exists });
|
||||
if ($exists && (!blessed($invocant) || $invocant->id != $exists->id))
|
||||
{
|
||||
ThrowUserError('fieldvalue_already_exists', { field => $field, value => $exists });
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
sub _check_sortkey {
|
||||
sub _check_sortkey
|
||||
{
|
||||
my ($invocant, $value) = @_;
|
||||
$value = trim($value);
|
||||
return 0 if !$value;
|
||||
# Store for the error message in case detaint_natural clears it.
|
||||
my $orig_value = $value;
|
||||
detaint_natural($value)
|
||||
|| ThrowUserError('fieldvalue_sortkey_invalid',
|
||||
{ sortkey => $orig_value,
|
||||
field => $invocant->field });
|
||||
detaint_natural($value) || ThrowUserError('fieldvalue_sortkey_invalid', {
|
||||
sortkey => $orig_value,
|
||||
field => $invocant->field,
|
||||
});
|
||||
return $value;
|
||||
}
|
||||
|
||||
|
|
|
@ -215,24 +215,27 @@ if ($action eq 'edit') {
|
|||
#
|
||||
# action='update' -> update the field value
|
||||
#
|
||||
if ($action eq 'update') {
|
||||
if ($action eq 'update')
|
||||
{
|
||||
check_token_data($token, 'edit_field_value');
|
||||
$vars->{'value_old'} = $value->name;
|
||||
my $visibility_values;
|
||||
if (!($value->is_static || $value->is_default)) {
|
||||
$value->set_is_active($cgi->param('is_active'));
|
||||
$value->set_name($cgi->param('value_new'));
|
||||
$visibility_values = [ $cgi->param('visibility_value_id') ];
|
||||
}
|
||||
if ($value->can('set_timetracking')) {
|
||||
$vars->{value_old} = $value->name;
|
||||
if ($value->can('set_timetracking'))
|
||||
{
|
||||
$value->set_timetracking($cgi->param('timetracking') ? 1 : 0);
|
||||
}
|
||||
$value->set_sortkey($cgi->param('sortkey'));
|
||||
$vars->{'changes'} = $value->update();
|
||||
my $ch = $value->set_visibility_values($visibility_values);
|
||||
$vars->{'changes'}->{'visibility_values'} = $ch if $visibility_values && $ch;
|
||||
if (!($value->is_static || $value->is_default))
|
||||
{
|
||||
$value->set_is_active($cgi->param('is_active'));
|
||||
$value->set_name($cgi->param('value_new'));
|
||||
if ($value->field->value_field)
|
||||
{
|
||||
$vars->{changes}->{visibility_values} = $value->set_visibility_values([ $cgi->param('visibility_value_id') ]);
|
||||
}
|
||||
}
|
||||
delete_token($token);
|
||||
$vars->{'message'} = 'field_value_updated';
|
||||
$vars->{changes} = $value->update;
|
||||
$vars->{message} = 'field_value_updated';
|
||||
display_field_values($vars);
|
||||
}
|
||||
|
||||
|
|
|
@ -401,11 +401,6 @@ $vars->{'product'} = $product;
|
|||
$vars->{product_flag_types} = $types;
|
||||
}
|
||||
|
||||
$vars->{'priority'} = Bugzilla->get_field('priority')->legal_value_names;
|
||||
$vars->{'bug_severity'} = Bugzilla->get_field('bug_severity')->legal_value_names;
|
||||
$vars->{'rep_platform'} = Bugzilla->get_field('rep_platform')->legal_value_names if Bugzilla->params->{useplatform};
|
||||
$vars->{'op_sys'} = Bugzilla->get_field('op_sys')->legal_value_names if Bugzilla->params->{useopsys};
|
||||
|
||||
$vars->{'assigned_to'} = formvalue('assigned_to');
|
||||
$vars->{'assigned_to_disabled'} = !$has_editbugs;
|
||||
$vars->{'cc_disabled'} = 0;
|
||||
|
@ -615,7 +610,6 @@ unless ($has_editbugs || $has_canconfirm) {
|
|||
}
|
||||
|
||||
$vars->{bug_status} = \@status;
|
||||
$vars->{resolution} = [ grep ($_, @{Bugzilla->get_field('resolution')->legal_value_names}) ];
|
||||
|
||||
# Get the default from a template value if it is legitimate.
|
||||
# Otherwise, and only if the user has privs, set the default
|
||||
|
|
|
@ -424,6 +424,9 @@ sub install_update_fielddefs
|
|||
# Bug 90854 - Тип поля "ссылка во внешнюю систему по ID"
|
||||
$dbh->bz_add_column('fielddefs', url => {TYPE => 'VARCHAR(255)'});
|
||||
|
||||
# Nullable field property
|
||||
$dbh->bz_add_column('fielddefs', nullable => {TYPE => 'BOOLEAN', NOTNULL => 1, DEFAULT => 'FALSE'});
|
||||
|
||||
# Bug 70605 - Кэширование зависимостей полей для поиска и формы бага на клиентской стороне
|
||||
if (!$dbh->bz_column_info('fielddefs', 'delta_ts'))
|
||||
{
|
||||
|
|
|
@ -397,8 +397,8 @@ function checkWorktime(inp)
|
|||
[% IF Param('useopsys') %]
|
||||
<tr>
|
||||
[% INCLUDE bug/field.html.tmpl
|
||||
bug = default, field = select_fields.op_sys, editable = 1,
|
||||
value = default.op_sys %]
|
||||
bug = default, field = select_fields.op_sys, editable = 1,
|
||||
value = default.op_sys %]
|
||||
</tr>
|
||||
[% END %]
|
||||
</tbody>
|
||||
|
@ -406,8 +406,9 @@ function checkWorktime(inp)
|
|||
<tbody class="expert_fields">
|
||||
<tr>
|
||||
[% IF Param('usetargetmilestone') && Param('letsubmitterchoosemilestone') %]
|
||||
[% sel = { description => 'Target Milestone', name => 'target_milestone' } %]
|
||||
[% INCLUDE select %]
|
||||
[% INCLUDE bug/field.html.tmpl
|
||||
bug = default, field = select_fields.target_milestone, editable = 1,
|
||||
value = default.target_milestone %]
|
||||
[% ELSE %]
|
||||
<td colspan="2"> </td>
|
||||
[% END %]
|
||||
|
@ -445,8 +446,7 @@ function checkWorktime(inp)
|
|||
|
||||
<tr>
|
||||
[% IF bug_status.size <= 1 %]
|
||||
<input type="hidden" name="bug_status"
|
||||
value="[% default.bug_status FILTER html %]">
|
||||
<input type="hidden" name="bug_status" value="[% default.bug_status FILTER html %]" />
|
||||
<th>Initial State:</th>
|
||||
<td>[% default.bug_status FILTER html %]</td>
|
||||
[% ELSE %]
|
||||
|
@ -461,15 +461,8 @@ function checkWorktime(inp)
|
|||
</tr>
|
||||
|
||||
<tr id="resolution_container" style="display:none">
|
||||
<th><a href="page.cgi?id=fields.html#resolution">Resolution</a>:</th>
|
||||
<td>
|
||||
<select name="resolution" id="resolution">
|
||||
[%- FOREACH x = resolution %]
|
||||
[% NEXT IF x == "MOVED" %]
|
||||
<option value="[% x FILTER html %]">[% x FILTER html %]</option>
|
||||
[% END %]
|
||||
</select>
|
||||
</td>
|
||||
[% INCLUDE bug/field.html.tmpl
|
||||
bug = default, field = select_fields.resolution, editable = 1 %]
|
||||
</tr>
|
||||
|
||||
<tr><td colspan="4"><hr /></td></tr>
|
||||
|
|
|
@ -57,14 +57,10 @@
|
|||
[%- '</a>' IF (!field.custom || desc_url) %]
|
||||
[% '</label>' IF editable %]
|
||||
</th>
|
||||
[% END %]
|
||||
|
||||
[% IF NOT no_tds %]
|
||||
<td class="field_value [% ' bz_hidden_field' IF hidden %]"
|
||||
<td class="field_value [% ' bz_hidden_field' IF hidden %]"
|
||||
id="field_container_[% field.name FILTER html %]"
|
||||
[% " colspan=\"$value_span\"" FILTER none IF value_span %]>
|
||||
[% END %]
|
||||
[% Hook.process('start_field_column') %]
|
||||
[% IF editable %]
|
||||
[% SWITCH field.type %]
|
||||
[% CASE constants.FIELD_TYPE_FREETEXT %]
|
||||
|
@ -239,11 +235,10 @@
|
|||
[% ELSIF field.type == constants.FIELD_TYPE_TEXTAREA %]
|
||||
<div class="uneditable_textarea">[% value FILTER html FILTER wrap_comment %]</div>
|
||||
[% ELSIF field.type == constants.FIELD_TYPE_BUG_ID %]
|
||||
[% IF bug.${field.name} %]
|
||||
[% bug.${field.name} FILTER bug_link(bug.${field.name}) FILTER none %]
|
||||
[% END %]
|
||||
[% IF bug.${field.name} %]
|
||||
[% bug.${field.name} FILTER bug_link(bug.${field.name}) FILTER none %]
|
||||
[% END %]
|
||||
[% ELSE %]
|
||||
[% value.join(', ') FILTER html %]
|
||||
[% END %]
|
||||
[% Hook.process('end_field_column') %]
|
||||
[% '</td>' IF NOT no_tds %]
|
||||
|
|
|
@ -350,8 +350,10 @@
|
|||
</li>
|
||||
[% END %]
|
||||
[% IF changes.sortkey %]
|
||||
<li>Sortkey updated to
|
||||
<em>[% changes.sortkey.1 | html %]</em>.</li>
|
||||
<li>Sortkey updated to <em>[% changes.sortkey.1 | html %]</em>.</li>
|
||||
[% END %]
|
||||
[% IF changes.isactive %]
|
||||
<li>It is now [% IF changes.isactive.1 %]enabled[% ELSE %]disabled[% END %] for selection.</li>
|
||||
[% END %]
|
||||
[% IF changes.visibility_values.defined %]
|
||||
[% IF value.visibility_values.size > 0 %]
|
||||
|
|
Loading…
Reference in New Issue