MT#6967 Alias range handling and first sub cleanup

ipeshinskaya/InvoiceTemplate5
Andreas Granig 12 years ago
parent 61eb05dd13
commit b95daedc79

@ -2,6 +2,7 @@ package NGCP::Panel::Controller::Customer;
use Sipwise::Base;
use namespace::sweep;
BEGIN { extends 'Catalyst::Controller'; }
use JSON qw(decode_json encode_json);
use NGCP::Panel::Utils::Contract;
use NGCP::Panel::Form::CustomerMonthlyFraud;
use NGCP::Panel::Form::CustomerDailyFraud;
@ -558,6 +559,9 @@ sub subscriber_create :Chained('base') :PathPart('subscriber/create') :Args(0) {
});
$c->stash->{admin_subscriber} = $admin_subscribers->first;
my $params = {};
if($c->config->{features}->{cloudpbx} && $pbx) {
$c->stash(customer_id => $c->stash->{contract}->id);
# we need to create an admin subscriber first
@ -570,12 +574,17 @@ sub subscriber_create :Chained('base') :PathPart('subscriber/create') :Args(0) {
} else {
$form = NGCP::Panel::Form::Customer::PbxExtensionSubscriber->new(ctx => $c);
}
NGCP::Panel::Utils::Subscriber::prepare_alias_select(
c => $c,
subscriber => $c->stash->{admin_subscriber},
params => $params,
unselect => 1, # no numbers assigned yet, keep selection list empty
);
}
} else {
$form = NGCP::Panel::Form::Customer::Subscriber->new(ctx => $c);
}
my $params = {};
$params = $params->merge($c->session->{created_objects});
$form->process(
posted => $posted,
@ -671,6 +680,17 @@ sub subscriber_create :Chained('base') :PathPart('subscriber/create') :Args(0) {
username => $form->params->{username},
domain => $billing_subscriber->domain->domain,
) if($pbx && !$pbxadmin && $form->params->{pbx_group_id});
if($pbx && !$pbxadmin) {
NGCP::Panel::Utils::Subscriber::update_subadmin_sub_aliases(
schema => $schema,
subscriber_id => $billing_subscriber->id,
contract_id => $billing_subscriber->contract_id,
alias_selected => decode_json($form->value->{alias_select}),
sadmin_id => $c->stash->{admin_subscriber}->id,
);
}
});
delete $c->session->{created_objects}->{domain};

@ -18,8 +18,6 @@ use NGCP::Panel::Utils::Hylafax;
use NGCP::Panel::Form::Subscriber;
use NGCP::Panel::Form::SubscriberEdit;
use NGCP::Panel::Form::Customer::PbxSubscriberEdit;
use NGCP::Panel::Form::Customer::PbxExtensionSubscriberEdit;
use NGCP::Panel::Form::Customer::PbxExtensionSubscriberEditAdmin;
use NGCP::Panel::Form::Customer::PbxExtensionSubscriberEditSubadmin;
use NGCP::Panel::Form::Customer::PbxExtensionSubscriberEditSubadminNoGroup;
use NGCP::Panel::Form::SubscriberCFSimple;
@ -1918,6 +1916,7 @@ sub edit_master :Chained('master') :PathPart('edit') :Args(0) :Does(ACL) :ACLDet
my $prov_subscriber = $subscriber->provisioning_voip_subscriber;
my $form; my $pbx_ext; my $is_admin; my $subadmin_pbx;
my $base_number;
if ($c->config->{features}->{cloudpbx}) {
$c->stash(customer_id => $subscriber->contract->id);
@ -1930,15 +1929,22 @@ sub edit_master :Chained('master') :PathPart('edit') :Args(0) :Does(ACL) :ACLDet
$form = NGCP::Panel::Form::Customer::PbxSubscriberEdit->new(ctx => $c);
}
} else {
my $admin_subscribers = $c->stash->{subscribers}->search({
'provisioning_voip_subscriber.admin' => 1,
});
$c->stash->{admin_subscriber} = $admin_subscribers->first;
$base_number = $c->stash->{admin_subscriber}->primary_number;
if($c->user->roles eq 'subscriberadmin') {
$subadmin_pbx = 1;
$form = NGCP::Panel::Form::Customer::PbxExtensionSubscriberEditSubadmin->new(ctx => $c);
} else {
$is_admin = 1;
$form = NGCP::Panel::Form::Customer::PbxExtensionSubscriberEditAdmin->new(ctx => $c);
$form = NGCP::Panel::Form::Customer::PbxExtensionSubscriber->new(ctx => $c);
}
$pbx_ext = 1;
}
} else {
if($c->user->roles eq 'subscriberadmin') {
$subadmin_pbx = 1;
@ -1954,15 +1960,6 @@ sub edit_master :Chained('master') :PathPart('edit') :Args(0) :Does(ACL) :ACLDet
my $params = {};
my $lock = $c->stash->{prov_lock};
my $base_number;
if($pbx_ext) {
my $admin_subscribers = $c->stash->{subscribers}->search({
'provisioning_voip_subscriber.admin' => 1,
});
$c->stash->{admin_subscriber} = $admin_subscribers->first;
$base_number = $c->stash->{admin_subscriber}->primary_number;
}
# we don't change this on edit
$c->request->params->{username} = $prov_subscriber->username;
if ($subadmin_pbx) {
@ -2002,21 +1999,11 @@ sub edit_master :Chained('master') :PathPart('edit') :Args(0) :Does(ACL) :ACLDet
}
=cut
my @alias_options = ();
my @alias_nums = ();
my $num_rs = $c->model('DB')->resultset('voip_numbers')->search_rs({
'subscriber.contract_id' => $subscriber->contract_id,
},{
prefetch => 'subscriber',
});
for my $num($num_rs->all) {
next if ($num->voip_subscribers->first); # is a primary number
next unless ($num->subscriber_id == $subscriber->id);
push @alias_nums, { e164 => { cc => $num->cc, ac => $num->ac, sn => $num->sn } };
push @alias_options, $num->id;
}
$params->{alias_number} = \@alias_nums;
$params->{alias_select} = encode_json(\@alias_options);
NGCP::Panel::Utils::Subscriber::prepare_alias_select(
c => $c,
subscriber => $subscriber,
params => $params,
);
$params->{status} = $subscriber->status;
$params->{external_id} = $subscriber->external_id;
@ -2322,7 +2309,7 @@ sub edit_master :Chained('master') :PathPart('edit') :Args(0) :Does(ACL) :ACLDet
}
sub aliases_ajax :Chained('master') :PathPart('aliases/ajax') :Args(0) :Does(ACL) :ACLDetachTo('/denied_page') :AllowedRole(subscriberadmin) {
sub aliases_ajax :Chained('master') :PathPart('aliases/ajax') :Args(0) :Does(ACL) :ACLDetachTo('/denied_page') :AllowedRole(admin) :AllowedRole(reseller) :AllowedRole(subscriberadmin) {
my ($self, $c) = @_;
my $subscriber = $c->stash->{subscriber};

@ -0,0 +1,88 @@
package NGCP::Panel::Field::E164Range;
use HTML::FormHandler::Moose;
extends 'HTML::FormHandler::Field::Compound';
#has 'label' => ( default => 'E164 Number');
has_field 'cc' => (
type => '+NGCP::Panel::Field::PosInteger',
element_attr => {
class => ['ngcp_e164_cc'],
rel => ['tooltip'],
title => ['Country Code, e.g. 1 for US or 43 for Austria']
},
do_label => 0,
do_wrapper => 0,
);
has_field 'ac' => (
type => '+NGCP::Panel::Field::PosInteger',
element_attr => {
class => ['ngcp_e164_ac'],
rel => ['tooltip'],
title => ['Area Code, e.g. 212 for NYC or 1 for Vienna']
},
do_label => 0,
do_wrapper => 0,
);
has_field 'snbase' => (
type => '+NGCP::Panel::Field::PosInteger',
element_attr => {
class => ['ngcp_e164_snbase'],
rel => ['tooltip'],
title => ['Subscriber Base, e.g. 12345']
},
do_label => 0,
do_wrapper => 0,
);
has_field 'snlength' => (
type => '+NGCP::Panel::Field::PosInteger',
element_attr => {
class => ['ngcp_e164_snlength'],
rel => ['tooltip'],
title => ['Subscriber Number Range Length (e.g. 2 for 1-212-12345xx']
},
do_label => 0,
do_wrapper => 0,
);
sub validate {
my $self = shift;
my $cc = $self->field('cc')->value;
my $sn = $self->field('snbase')->value;
my $snlen = $self->field('snlength')->value;
my %sub_errors = map {$_, 1} (
@{ $self->field('cc')->errors },
@{ $self->field('ac')->errors },
@{ $self->field('snbase')->errors },
@{ $self->field('snlength')->errors } );
for my $sub_error( keys %sub_errors ) {
$self->add_error($sub_error);
}
$self->field('cc')->clear_errors if $self->field('cc');
$self->field('ac')->clear_errors if $self->field('ac');
$self->field('snbase')->clear_errors if $self->field('snbase');
$self->field('snlength')->clear_errors if $self->field('snlength');
if ($self->has_errors) {
#dont add more errors
} elsif (defined $cc && $cc ne '' && (!defined $sn || $sn eq '')) {
my $err_msg = 'Subscriber Number required if Country Code is set';
$self->add_error($err_msg);
} elsif(defined $sn && $sn ne '' && (!defined $cc || $cc eq '')) {
my $err_msg = 'Country Code required if Subscriber Number is set';
$self->add_error($err_msg);
}
if(defined $sn && $sn ne '' && (!defined $snlen || $snlen eq '')) {
my $err_msg = 'Subscriber Number Range Length required if Subscriber Base is set';
$self->add_error($err_msg);
}
}
1;
# vim: set tabstop=4 expandtab:

@ -0,0 +1,29 @@
package NGCP::Panel::Field::E164RangeRepeat;
use HTML::FormHandler::Moose;
extends 'HTML::FormHandler::Field::Repeatable';
has_field 'id' => (
type => 'Hidden',
);
has_field 'e164range' => (
type => '+NGCP::Panel::Field::E164Range',
order => 99,
required => 0,
label => 'Number Range',
do_label => 1,
do_wrapper => 1,
wrapper_class => [qw/hfh-rep-field/],
);
has_field 'rm' => (
type => 'RmElement',
value => 'Remove',
order => 100,
element_class => [qw/btn btn-primary pull-right/],
);
1;
# vim: set tabstop=4 expandtab:

@ -13,6 +13,24 @@ has_field 'e164' => (
do_wrapper => 1,
);
has_field 'e164range' => (
type => '+NGCP::Panel::Field::E164RangeRepeat',
setup_for_js => 1,
do_wrapper => 1,
do_label => 0,
tags => {
controls_div => 1,
},
wrapper_class => [qw/hfh-rep/],
);
has_field 'e164range_add' => (
type => 'AddElement',
repeatable => 'e164range',
value => 'Add another range',
element_class => [qw/btn btn-primary pull-right/],
);
has_field 'domain' => (
type => '+NGCP::Panel::Field::Domain',
label => 'SIP Domain',
@ -22,7 +40,7 @@ has_field 'domain' => (
has_block 'fields' => (
tag => 'div',
class => [qw/modal-body/],
render_list => [qw/domain e164 display_name email webusername webpassword username password status external_id profile_set/ ],
render_list => [qw/domain e164 e164range e164range_add display_name email webusername webpassword username password status external_id profile_set/ ],
);
1;

@ -20,10 +20,23 @@ has_field 'pbx_extension' => (
label => 'Extension',
);
has_field 'alias_select' => (
type => '+NGCP::Panel::Field::DataTable',
label => 'Numbers',
do_label => 0,
do_wrapper => 0,
required => 0,
template => 'helpers/datatables_multifield.tt',
ajax_src => '/invalid',
table_titles => ['#', 'Number', 'Subscriber'],
table_fields => ['id', 'number', 'subscriber_username'],
);
has_block 'fields' => (
tag => 'div',
class => [qw/modal-body/],
render_list => [qw/group pbx_extension display_name email webusername webpassword username password status external_id profile/ ],
render_list => [qw/group alias_select pbx_extension display_name email webusername webpassword username password status external_id profile_set profile/ ],
);
sub field_list {
@ -31,25 +44,62 @@ sub field_list {
my $c = $self->ctx;
return unless $c;
print ">>>>>>>>>>>>>> PbxExtensionSubscriber::field_list\n";
if($self->field('alias_select') && $c->stash->{admin_subscriber}) {
print ">>>>>>>>>>>>>>>> setting alias_select, url=" . $c->uri_for_action("/subscriber/aliases_ajax", [$c->stash->{admin_subscriber}->id]) . "\n";
$self->field('alias_select')->ajax_src(
$c->uri_for_action("/subscriber/aliases_ajax", [$c->stash->{admin_subscriber}->id])->as_string
);
}
my $group = $self->field('group');
$group->field('id')->ajax_src(
$c->uri_for_action('/customer/pbx_group_ajax', [$c->stash->{customer_id}])->as_string
);
if($c->stash->{admin_subscriber}) {
if($c->stash->{subscriber}) {
my $profile_set_field = $self->field('profile_set');
if($profile_set_field) {
$profile_set_field->field('id')->ajax_src(
$c->uri_for_action('/subscriberprofile/set_ajax_reseller', [$c->stash->{subscriber}->contract->contact->reseller_id])->as_string
);
}
my $set_id = $c->stash->{subscriber}->provisioning_voip_subscriber->profile_set_id;
if($set_id) {
# don't show the profile set selection if we already have a profile set
$profile_set_field->inactive(1) if($profile_set_field);
my $profile = $self->field('profile');
if($profile) {
$profile->field('id')->ajax_src(
$c->uri_for_action('/subscriberprofile/profile_ajax', [$set_id])->as_string
);
}
}
} elsif($c->stash->{admin_subscriber}) {
my $profile_set = $c->stash->{admin_subscriber}->provisioning_voip_subscriber->voip_subscriber_profile_set;
if($profile_set && $self->field('profile')) {
print ">>>>>>>>>>>>>> setting profile, url=" . $c->uri_for_action('/subscriberprofile/profile_ajax', [$profile_set->id]) . "\n";
$self->field('profile')->field('id')->ajax_src(
$c->uri_for_action('/subscriberprofile/profile_ajax', [$profile_set->id])->as_string
);
}
}
if($c->config->{security}->{password_sip_autogenerate}) {
# todo: only set to inactive for certain roles, and only if specified in config
$self->field('password')->inactive(1);
$self->field('password')->required(0);
}
if($c->config->{security}->{password_web_autogenerate}) {
# todo: only set to inactive for certain roles, and only if specified in config
$self->field('webpassword')->inactive(1);
$self->field('webpassword')->required(0);
}

@ -1,73 +0,0 @@
package NGCP::Panel::Form::Customer::PbxExtensionSubscriberEdit;
use HTML::FormHandler::Moose;
use NGCP::Panel::Field::PosInteger;
extends 'NGCP::Panel::Form::Customer::PbxSubscriber';
has_field 'group' => (
type => '+NGCP::Panel::Field::PbxGroup',
label => 'Group',
validate_when_empty => 1,
);
has_field 'pbx_extension' => (
type => '+NGCP::Panel::Field::PosInteger',
element_attr => {
rel => ['tooltip'],
title => ['Extension Number, e.g. 101']
},
required => 1,
label => 'Extension',
);
has_block 'fields' => (
tag => 'div',
class => [qw/modal-body/],
render_list => [qw/group pbx_extension email webusername webpassword password status external_id profile/ ],
);
sub update_fields {
my $self = shift;
my $c = $self->ctx;
my $pkg = __PACKAGE__;
$c->log->debug("my form: $pkg");
my $group = $self->field('group');
$group->field('id')->ajax_src(
$c->uri_for_action('/customer/pbx_group_ajax', [$c->stash->{customer_id}])->as_string
);
my $profile_set = $c->stash->{subscriber}->provisioning_voip_subscriber->voip_subscriber_profile_set;
if($profile_set && $self->field('profile')) {
$self->field('profile')->field('id')->ajax_src(
$c->uri_for_action('/subscriberprofile/profile_ajax', [$profile_set->id])->as_string
);
}
$self->field('password')->required(0); # optional on edit
}
1;
=head1 NAME
NGCP::Panel::Form::Subscriber
=head1 DESCRIPTION
Form to modify a subscriber.
=head1 METHODS
=head1 AUTHOR
Gerhard Jungwirth
=head1 LICENSE
This library is free software. You can redistribute it and/or modify
it under the same terms as Perl itself.
=cut
# vim: set tabstop=4 expandtab:

@ -1,82 +0,0 @@
package NGCP::Panel::Form::Customer::PbxExtensionSubscriberEditAdmin;
use HTML::FormHandler::Moose;
use NGCP::Panel::Field::PosInteger;
extends 'NGCP::Panel::Form::Customer::PbxExtensionSubscriberEdit';
with 'NGCP::Panel::Render::RepeatableJs';
has_field 'alias_number' => (
type => '+NGCP::Panel::Field::AliasNumber',
setup_for_js => 1,
do_wrapper => 1,
do_label => 0,
tags => {
controls_div => 1,
},
wrapper_class => [qw/hfh-rep/],
);
has_field 'alias_number_add' => (
type => 'AddElement',
repeatable => 'alias_number',
value => 'Add another number',
element_class => [qw/btn btn-primary pull-right/],
);
has_block 'fields' => (
tag => 'div',
class => [qw/modal-body/],
render_list => [qw/group pbx_extension alias_number alias_number_add email webusername webpassword password status external_id profile_set profile/ ],
);
sub field_list {
my ($self) = @_;
my $c = $self->ctx;
return unless($c);
print "+++++++++++++++++++++++++++++ PbxExtensionSubscriberEditAdmin field_list\n";
my $profile_set = $self->field('profile_set');
if($profile_set) {
$profile_set->field('id')->ajax_src(
$c->uri_for_action('/subscriberprofile/set_ajax_reseller', [$c->stash->{subscriber}->contract->contact->reseller_id])->as_string
);
}
my $set_id = $c->stash->{subscriber}->provisioning_voip_subscriber->profile_set_id;
if($set_id) {
my $profile = $self->field('profile');
if($profile) {
$profile->field('id')->ajax_src(
$c->uri_for_action('/subscriberprofile/profile_ajax', [$set_id])->as_string
);
}
}
}
1;
=head1 NAME
NGCP::Panel::Form::Subscriber
=head1 DESCRIPTION
Form to modify a subscriber.
=head1 METHODS
=head1 AUTHOR
Gerhard Jungwirth
=head1 LICENSE
This library is free software. You can redistribute it and/or modify
it under the same terms as Perl itself.
=cut
# vim: set tabstop=4 expandtab:

@ -2,19 +2,7 @@ package NGCP::Panel::Form::Customer::PbxExtensionSubscriberEditSubadmin;
use HTML::FormHandler::Moose;
use NGCP::Panel::Field::PosInteger;
extends 'NGCP::Panel::Form::Customer::PbxExtensionSubscriberEdit';
has_field 'alias_select' => (
type => '+NGCP::Panel::Field::DataTable',
label => 'Numbers',
do_label => 0,
do_wrapper => 0,
required => 0,
template => 'helpers/datatables_multifield.tt',
ajax_src => '/invalid',
table_titles => ['#', 'Number', 'Subscriber'],
table_fields => ['id', 'number', 'subscriber_username'],
);
extends 'NGCP::Panel::Form::Customer::PbxExtensionSubscriber';
has_block 'fields' => (
tag => 'div',
@ -22,27 +10,11 @@ has_block 'fields' => (
render_list => [qw/group pbx_extension email webusername webpassword password alias_select profile/ ],
);
sub update_fields {
override 'update_fields' => sub {
my $self = shift;
my $c = $self->ctx;
my $pkg = __PACKAGE__;
$c->log->debug("my form: $pkg");
$self->field('alias_select')->ajax_src(
"".$c->uri_for_action("/subscriber/aliases_ajax", $c->req->captures)
);
my $group = $self->field('group');
$group->field('id')->ajax_src(
$c->uri_for_action('/customer/pbx_group_ajax', [$c->stash->{customer_id}])->as_string
);
my $profile_set = $c->stash->{subscriber}->provisioning_voip_subscriber->voip_subscriber_profile_set;
if($profile_set && $self->field('profile')) {
$self->field('profile')->field('id')->ajax_src(
$c->uri_for_action('/subscriberprofile/profile_ajax', [$profile_set->id])->as_string
);
}
super();
if($c->user->roles eq "subscriberadmin") {
if(!$c->config->{security}->{password_sip_expose_subadmin}) {
@ -52,9 +24,7 @@ sub update_fields {
$self->field('webpassword')->inactive(1);
}
}
$self->field('password')->required(0); # optional on edit
}
};
1;

@ -4,33 +4,16 @@ use HTML::FormHandler::Moose;
use NGCP::Panel::Field::PosInteger;
extends 'NGCP::Panel::Form::Customer::PbxSubscriber';
has_field 'alias_select' => (
type => '+NGCP::Panel::Field::DataTable',
label => 'Numbers',
do_label => 0,
do_wrapper => 0,
required => 0,
template => 'helpers/datatables_multifield.tt',
ajax_src => '/invalid',
table_titles => ['#', 'Number', 'Subscriber'],
table_fields => ['id', 'number', 'subscriber_username'],
);
has_block 'fields' => (
tag => 'div',
class => [qw/modal-body/],
render_list => [qw/email webusername webpassword password alias_select profile/ ],
render_list => [qw/alias_select email webusername webpassword password profile/ ],
);
sub update_fields {
my $self = shift;
my $c = $self->ctx;
my $pkg = __PACKAGE__;
$c->log->debug("my form: $pkg");
$self->field('alias_select')->ajax_src(
"".$c->uri_for_action("/subscriber/aliases_ajax", $c->req->captures)
);
return unless $c;
my $profile_set = $c->stash->{subscriber}->provisioning_voip_subscriber->voip_subscriber_profile_set;
if($profile_set) {

@ -9,6 +9,7 @@ use NGCP::Panel::Utils::DateTime;
use NGCP::Panel::Utils::Preferences;
use NGCP::Panel::Utils::Email;
use UUID qw/generate unparse/;
use JSON qw/decode_json encode_json/;
my %LOCK = (
0, 'none',
@ -215,7 +216,6 @@ sub create_subscriber {
primary_number => $params->{e164},
);
}
unless(exists $params->{password}) {
my ($pass_bin, $pass_str);
UUID::generate($pass_bin);
@ -281,6 +281,32 @@ sub create_subscriber {
NGCP::Panel::Utils::Email::new_subscriber($c, $billing_subscriber, $url);
}
if(defined $params->{e164range} && ref $params->{e164range} eq "ARRAY") {
my @alias_numbers = ();
foreach my $range(@{ $params->{e164range} }) {
if(defined $range->{e164range}{cc} && $range->{e164range}{cc} ne '') {
my $len = $range->{e164range}{snlength};
foreach my $ext(0 .. int("9" x $len)) {
$range->{e164range}{sn} = sprintf("%s%0".$len."d", $range->{e164range}{snbase}, $ext);
push @alias_numbers, { e164 => {
cc => $range->{e164range}{cc},
ac => $range->{e164range}{ac},
sn => $range->{e164range}{sn},
}};
}
}
}
if(@alias_numbers) {
update_subscriber_numbers(
schema => $schema,
subscriber_id => $billing_subscriber->id,
reseller_id => $reseller->id,
alias_numbers => \@alias_numbers,
);
}
}
return $billing_subscriber;
});
}
@ -732,6 +758,32 @@ sub callforward_create_or_update_quickset_destinations {
return;
}
sub prepare_alias_select {
my (%p) = @_;
my $c = $p{c};
my $subscriber = $p{subscriber};
my $params = $p{params};
my $unselect = $p{unselect} // 0;
my @alias_options = ();
my @alias_nums = ();
my $num_rs = $c->model('DB')->resultset('voip_numbers')->search_rs({
'subscriber.contract_id' => $subscriber->contract_id,
},{
prefetch => 'subscriber',
});
for my $num($num_rs->all) {
next if ($num->voip_subscribers->first); # is a primary number
next unless ($num->subscriber_id == $subscriber->id);
push @alias_nums, { e164 => { cc => $num->cc, ac => $num->ac, sn => $num->sn } };
unless($unselect) {
push @alias_options, $num->id;
}
}
$params->{alias_number} = \@alias_nums;
$params->{alias_select} = encode_json(\@alias_options);
}
1;
=head1 NAME

@ -427,8 +427,13 @@ div.ngcp-modal .control-group.error .dataTables_wrapper input[type="text"] {
width: 15%;
}
.modal-body .control-group .controls input.ngcp_e164_sn {
width: 67%;
float: right;
width: 67.9%;
}
.modal-body .control-group .controls input.ngcp_e164_snbase {
width: 60%;
}
.modal-body .control-group .controls input.ngcp_e164_snlength {
width: 7.1%;
}
.modal-body div.ngcp_field_inline {
display: inline-block;

Loading…
Cancel
Save