TT#37204 bnumber cf panel

Change-Id: I77e5f5d0b1eb126d1dbd57697913baac1a2a2ac1
changes/26/21826/6
Gerhard Jungwirth 8 years ago
parent 11c1e0499b
commit c55028291d

@ -643,6 +643,17 @@ sub preferences :Chained('base') :PathPart('preferences') :Args(0) {
$sset_name = $map->source_set->name;
$sset_mode = $map->source_set->mode;
}
my @bnumbers = ();
my $bset_name = undef;
my $bset_mode = undef;
if($map->bnumber_set) {
@bnumbers = map { { $_->get_columns } } $map->bnumber_set->voip_cf_bnumbers->all;
foreach my $s(@bnumbers) {
$s->{as_string} = $s->{bnumber};
}
$bset_name = $map->bnumber_set->name;
$bset_mode = $map->bnumber_set->mode;
}
push @{ $cfs->{$type} }, {
destinations => \@dset,
dset_name => $dset_name,
@ -650,7 +661,11 @@ sub preferences :Chained('base') :PathPart('preferences') :Args(0) {
tset_name => $tset_name,
sources => \@sources,
sset_name => $sset_name,
sset_mode => $sset_mode };
sset_mode => $sset_mode,
bset_name => $bset_name,
bset_mode => $bset_mode,
bnumbers => \@bnumbers,
};
}
}
$c->stash(cf_destinations => $cfs);
@ -876,10 +891,12 @@ sub preferences_callforward :Chained('base') :PathPart('preferences/callforward'
} elsif($cf_mapping->first && $cf_mapping->first->destination_set &&
$cf_mapping->first->destination_set->voip_cf_destinations->first) {
# there are more than one destinations or a time set, so
# which can only be handled in advanced mode
# there are more than one destinations or a time set or a source set or a bnumber set
# => these can only be handled in advanced mode
if($cf_mapping->first->destination_set->voip_cf_destinations->count > 1 ||
$cf_mapping->first->time_set) {
$cf_mapping->first->time_set_id ||
$cf_mapping->first->source_set_id ||
$cf_mapping->first->bnumber_set_id) {
$c->response->redirect(
$c->uri_for_action('/subscriber/preferences_callforward_advanced',
@ -1094,6 +1111,7 @@ sub preferences_callforward_advanced :Chained('base') :PathPart('preferences/cal
->search_rs(undef,{order_by => 'name'});
$c->stash->{cf_time_sets} = $prov_subscriber->voip_cf_time_sets;
$c->stash->{cf_source_sets} = $prov_subscriber->voip_cf_source_sets;
$c->stash->{cf_bnumber_sets} = $prov_subscriber->voip_cf_bnumber_sets;
my $posted = ($c->request->method eq 'POST');
@ -1110,6 +1128,7 @@ sub preferences_callforward_advanced :Chained('base') :PathPart('preferences/cal
destination_set => $map->destination_set ? $map->destination_set->id : undef,
time_set => $map->time_set ? $map->time_set->id : undef,
source_set => $map->source_set ? $map->source_set->id : undef,
bnumber_set => $map->bnumber_set ? $map->bnumber_set->id : undef,
};
}
my $params = {
@ -1143,6 +1162,10 @@ sub preferences_callforward_advanced :Chained('base') :PathPart('preferences/cal
$c->uri_for_action('/subscriber/preferences_callforward_sourceset',
[$c->req->captures->[0]], $cf_type,
),
'cf_actions.edit_bnumber_sets' =>
$c->uri_for_action('/subscriber/preferences_callforward_bnumberset',
[$c->req->captures->[0]], $cf_type,
),
},
back_uri => $c->req->uri,
);
@ -1180,6 +1203,7 @@ sub preferences_callforward_advanced :Chained('base') :PathPart('preferences/cal
destination_set_id => $map->field('destination_set')->value,
time_set_id => $map->field('time_set')->value,
source_set_id => $map->field('source_set')->value,
bnumber_set_id => $map->field('bnumber_set')->value,
});
$cf_preference->create({ value => $m->id });
$autoattendant_count -= NGCP::Panel::Utils::Subscriber::check_dset_autoattendant_status($m->destination_set);
@ -1818,6 +1842,277 @@ sub preferences_callforward_sourceset_delete :Chained('preferences_callforward_s
);
}
sub preferences_callforward_bnumberset :Chained('base') :PathPart('preferences/bnumberset') :Args(1) {
my ($self, $c, $cf_type) = @_;
$c->detach('/denied_page')
if(($c->user->roles eq "admin" || $c->user->roles eq "reseller") && $c->user->read_only);
my $prov_subscriber = $c->stash->{subscriber}->provisioning_voip_subscriber;
my @sets;
if($prov_subscriber->voip_cf_bnumber_sets) {
foreach my $set($prov_subscriber->voip_cf_bnumber_sets->all) {
if($set->voip_cf_bnumbers) {
my @bnumbers = map { { $_->get_columns } } $set->voip_cf_bnumbers->all;
foreach my $s(@bnumbers) {
$s->{as_string} = $s->{bnumber};
}
push @sets, { name => $set->name, mode => $set->mode, id => $set->id, bnumbers => \@bnumbers };
}
}
}
$self->load_preference_list($c);
$c->stash(template => 'subscriber/preferences.tt');
$c->stash(
edit_bnumberset_flag => 1,
cf_form => undef,
cf_type => $cf_type,
cf_bnumber_sets => \@sets,
);
}
sub preferences_callforward_bnumberset_create :Chained('base') :PathPart('preferences/bnumberset/create') :Args(1) {
my ($self, $c, $cf_type) = @_;
$c->detach('/denied_page')
if(($c->user->roles eq "admin" || $c->user->roles eq "reseller") && $c->user->read_only);
my $prov_subscriber = $c->stash->{subscriber}->provisioning_voip_subscriber;
my $form = NGCP::Panel::Form::get("NGCP::Panel::Form::CallforwardBnumberSet", $c);
my $posted = ($c->request->method eq 'POST');
$form->process(
posted => $posted,
params => $c->req->params,
);
NGCP::Panel::Utils::Navigation::check_form_buttons(
c => $c,
form => $form,
fields => {},
back_uri => $c->req->uri,
);
if($posted && $form->validated) {
try {
my $schema = $c->model('DB');
$schema->txn_do(sub {
my @fields = $form->field('bnumbers')->fields;
if(@fields) {
my $set = $prov_subscriber->voip_cf_bnumber_sets->create({
name => $form->field('name')->value,
mode => $form->field('mode')->value,
});
foreach my $bnum_row(@fields) {
my $s = $bnum_row->field('number')->value;
$set->voip_cf_bnumbers->create({
bnumber => $s,
});
}
}
});
NGCP::Panel::Utils::Message::info(
c => $c,
type => 'internal',
desc => $c->loc('Successfully created new source set'),
);
} catch($e) {
NGCP::Panel::Utils::Message::error(
c => $c,
error => $e,
type => 'internal',
desc => $c->loc('Failed to create new source set'),
);
}
NGCP::Panel::Utils::Navigation::back_or($c,
$c->uri_for_action('/subscriber/preferences_callforward_bnumberset',
[$c->req->captures->[0]], $cf_type)
);
}
$self->load_preference_list($c);
$c->stash(template => 'subscriber/preferences.tt');
$c->stash(
edit_cf_flag => 1,
cf_description => $c->loc('B-Number Set'),
cf_form => $form,
cf_type => $cf_type,
);
}
sub preferences_callforward_bnumberset_base :Chained('base') :PathPart('preferences/bnumberset') :CaptureArgs(1) {
my ($self, $c, $set_id) = @_;
$c->detach('/denied_page')
if(($c->user->roles eq "admin" || $c->user->roles eq "reseller") && $c->user->read_only);
$c->stash->{bnumber_set} = $c->stash->{subscriber}
->provisioning_voip_subscriber
->voip_cf_bnumber_sets
->find($set_id);
$self->load_preference_list($c);
$c->stash(template => 'subscriber/preferences.tt');
}
sub preferences_callforward_bnumberset_edit :Chained('preferences_callforward_bnumberset_base') :PathPart('edit') :Args(1) {
my ($self, $c, $cf_type) = @_;
my $fallback = $c->uri_for_action('/subscriber/preferences_callforward_bnumberset',
[$c->req->captures->[0]], $cf_type);
my $posted = ($c->request->method eq 'POST');
my $cf_preference = NGCP::Panel::Utils::Preferences::get_usr_preference_rs(
c => $c, prov_subscriber => $c->stash->{subscriber}->provisioning_voip_subscriber,
attribute => $cf_type,
);
my $ringtimeout_preference = NGCP::Panel::Utils::Preferences::get_usr_preference_rs(
c => $c, prov_subscriber => $c->stash->{subscriber}->provisioning_voip_subscriber,
attribute => 'ringtimeout',
);
my $set = $c->stash->{bnumber_set};
my $params;
unless($posted) {
$params->{name} = $set->name;
$params->{mode} = $set->mode;
my @numbers;
for my $bnum_rows($set->voip_cf_bnumbers->all) {
push @numbers, {
number => $bnum_rows->bnumber,
id => $bnum_rows->id,
};
}
$params->{bnumbers} = \@numbers;
}
my $form = NGCP::Panel::Form::get("NGCP::Panel::Form::CallforwardBnumberSet", $c);
$form->process(
posted => $posted,
params => $c->req->params,
item => $params,
);
NGCP::Panel::Utils::Navigation::check_form_buttons(
c => $c,
form => $form,
fields => {},
back_uri => $c->req->uri,
);
if($posted && $form->validated) {
try {
my $schema = $c->model('DB');
$schema->txn_do(sub {
# delete whole set and mapping if empty
my @fields = $form->field('bnumbers')->fields;
unless(@fields) {
foreach my $mapping($set->voip_cf_mappings->all) {
# delete it here (this has been a design decicion from the beginning for all parts of cfs)
my $cf = $cf_preference->find({ value => $mapping->id });
$cf->delete if $cf;
$ringtimeout_preference->first->delete
if($cf_type eq "cft" && $ringtimeout_preference->first);
$mapping->delete;
}
$set->delete;
NGCP::Panel::Utils::Navigation::back_or($c, $fallback, 1);
return;
}
if($form->field('name')->value ne $set->name) {
$set->update({name => $form->field('name')->value});
}
if($form->field('mode')->value ne $set->mode) {
$set->update({mode => $form->field('mode')->value});
}
$set->voip_cf_bnumbers->delete_all;
foreach my $src(@fields) {
my $s = $src->field('number')->value;
$set->voip_cf_bnumbers->create({
bnumber => $s,
});
}
$set->discard_changes; # reload (voip_cf_bnumbers may be cached)
});
NGCP::Panel::Utils::Message::info(
c => $c,
type => 'internal',
desc => $c->loc('Successfully updated bnumber set'),
);
} catch($e) {
NGCP::Panel::Utils::Message::error(
c => $c,
error => $e,
type => 'internal',
desc => $c->loc('Failed to update bnumber set'),
);
}
NGCP::Panel::Utils::Navigation::back_or($c, $fallback);
}
$c->stash(
edit_cf_flag => 1,
cf_description => "B-Number Set",
cf_form => $form,
);
}
sub preferences_callforward_bnumberset_delete :Chained('preferences_callforward_bnumberset_base') :PathPart('delete') :Args(1) {
my ($self, $c, $cf_type) = @_;
my $cf_preference = NGCP::Panel::Utils::Preferences::get_usr_preference_rs(
c => $c, prov_subscriber => $c->stash->{subscriber}->provisioning_voip_subscriber,
attribute => $cf_type,
);
my $ringtimeout_preference = NGCP::Panel::Utils::Preferences::get_usr_preference_rs(
c => $c, prov_subscriber => $c->stash->{subscriber}->provisioning_voip_subscriber,
attribute => 'ringtimeout',
);
my $set = $c->stash->{bnumber_set};
my $prov_subscriber = $c->stash->{subscriber}->provisioning_voip_subscriber;
try {
my $schema = $c->model('DB');
$schema->txn_do(sub {
foreach my $map($set->voip_cf_mappings->all) {
my $cf = $cf_preference->find({ value => $map->id });
$cf->delete if $cf;
$map->delete;
}
if($cf_type eq "cft" &&
$prov_subscriber->voip_cf_mappings->search_rs({ type => $cf_type})->count == 0) {
$ringtimeout_preference->first->delete;
}
$set->delete;
});
NGCP::Panel::Utils::Message::info(
c => $c,
data => { $set->get_inflated_columns },
type => 'internal',
desc => $c->loc('Successfully deleted bnumber set'),
);
} catch($e) {
NGCP::Panel::Utils::Message::error(
c => $c,
error => $e,
data => { $set->get_inflated_columns },
type => 'internal',
desc => $c->loc('Failed to delete bnumber set'),
);
}
NGCP::Panel::Utils::Navigation::back_or($c,
$c->uri_for_action('/subscriber/preferences_callforward_bnumberset',
[$c->req->captures->[0]], $cf_type)
);
}
sub preferences_callforward_timeset :Chained('base') :PathPart('preferences/timeset') :Args(1) {
my ($self, $c, $cf_type) = @_;

@ -0,0 +1,29 @@
package NGCP::Panel::Field::SubscriberBNumberSet;
use Sipwise::Base;
use HTML::FormHandler::Moose;
extends 'HTML::FormHandler::Field::Select';
sub build_options {
my ($self) = @_;
my $form = $self->form;
return [] unless $form->ctx;
my $sets = $form->ctx->stash->{cf_bnumber_sets};
my @all;
return \@all unless($sets);
push @all, { label => '<any number>', value => undef};
foreach my $set($sets->all) {
my $entry = {};
$entry->{label} = $set->name;
$entry->{value} = $set->id;
push @all, $entry;
}
return \@all;
}
no Moose;
1;
# vim: set tabstop=4 expandtab:

@ -0,0 +1,104 @@
package NGCP::Panel::Form::CallforwardBnumberSet;
use HTML::FormHandler::Moose;
use HTML::FormHandler::Widget::Block::Bootstrap;
extends 'HTML::FormHandler';
with 'NGCP::Panel::Render::RepeatableJs';
has '+widget_wrapper' => (default => 'Bootstrap');
has_field 'submitid' => ( type => 'Hidden' );
sub build_render_list {[qw/submitid fields actions/]}
sub build_form_element_class {[qw(form-horizontal)]}
has_field 'name' => (
type => 'Text',
label => 'Name',
wrapper_class => [qw/hfh-rep-field/],
required => 1,
element_attr => {
rel => ['tooltip'],
title => ['The unique name of the B-Number set. Arbitrary text'],
},
);
has_field 'mode' => (
type => 'Select',
options => [
{value => 'whitelist', label => 'whitelist'},
{value => 'blacklist', label => 'blacklist'},
],
required => 1,
element_attr => {
rel => ['tooltip'],
title => ['The source set mode']
},
);
has_field 'bnumbers' => (
type => 'Repeatable',
setup_for_js => 1,
do_wrapper => 1,
do_label => 0,
required => 1,
tags => {
controls_div => 1,
},
wrapper_class => [qw/hfh-rep/],
);
has_field 'bnumbers.id' => (
type => 'Hidden',
);
has_field 'bnumbers.number' => (
type => 'Text', # +NGCP::Panel::Field::URI
label => 'B-Number',
required => 1,
do_label => 1,
wrapper_class => [qw/hfh-rep-field/],
element_attr => {
rel => ['tooltip'],
title => ['Matches the B-Number (original number dialled by the caller) in E164 format. ' .
'Shell patterns like 431* or 49123~[1-5~]67 are possible. ' .
'Use &quot;anonymous&quot; to match suppressed numbers.'],
},
);
has_field 'bnumbers.rm' => (
type => 'RmElement',
value => 'Remove',
element_class => [qw/btn btn-primary pull-right/],
# tags => {
# "data-confirm" => "Delete",
# },
);
has_field 'bnumber_add' => (
type => 'AddElement',
repeatable => 'bnumbers',
value => 'Add another B-Number',
element_class => [qw/btn btn-primary pull-right/],
);
has_block 'fields' => (
tag => 'div',
class => [qw(modal-body)],
render_list => [qw(name mode bnumbers bnumber_add)],
);
has_field 'save' => (
type => 'Submit',
do_label => 0,
value => 'Save',
element_class => [qw(btn btn-primary)],
);
has_block 'actions' => (
tag => 'div',
class => [qw(modal-footer)],
render_list => [qw(save)],
);
1;
# vim: set tabstop=4 expandtab:

@ -21,13 +21,6 @@ has_field 'active_callforward' => (
wrapper_class => [qw/hfh-rep/],
);
has_field 'active_callforward.destination_set' => (
type => '+NGCP::Panel::Field::SubscriberDestinationSet',
label => 'Destination Set',
wrapper_class => [qw/hfh-rep-field/],
);
has_field 'active_callforward.time_set' => (
type => '+NGCP::Panel::Field::SubscriberTimeSet',
label => 'during Time Set',
@ -40,6 +33,18 @@ has_field 'active_callforward.source_set' => (
wrapper_class => [qw/hfh-rep-field/],
);
has_field 'active_callforward.bnumber_set' => (
type => '+NGCP::Panel::Field::SubscriberBNumberSet',
label => 'to B-Number Set',
wrapper_class => [qw/hfh-rep-field/],
);
has_field 'active_callforward.destination_set' => (
type => '+NGCP::Panel::Field::SubscriberDestinationSet',
label => 'Destination Set',
wrapper_class => [qw/hfh-rep-field/],
);
has_field 'active_callforward.rm' => (
type => 'RmElement',
value => 'Remove',
@ -111,6 +116,14 @@ has_field 'cf_actions.edit_source_sets' => (
wrapper_class => [qw(pull-right)],
);
has_field 'cf_actions.edit_bnumber_sets' => (
type => 'Button',
do_label => 0,
value => 'Manage B-Number Sets',
element_class => [qw(btn btn-tertiary)],
wrapper_class => [qw(pull-right)],
);
has_block 'actions' => (
tag => 'div',
class => [qw(modal-footer)],

@ -104,9 +104,11 @@ $( document ).ready(function() {
<tr>
<th>[% c.loc('Type') %]</th>
<th>[% c.loc('Answer Timeout') %]</th>
<th>[% c.loc('Destinations') %]</th>
<th>[% c.loc('Timeset') %]</th>
<th>[% c.loc('Sources') %]</th>
<th>[% c.loc('To (B-Numbers)') %]</th>
<th>[% c.loc('New Destinations') %]</th>
[% # one for actions -%]
<th class="ngcp-actions-column"></th>
</tr>
@ -121,39 +123,11 @@ $( document ).ready(function() {
[% NEXT IF special_prefs.check && !special_prefs.callforward.${cf.type} -%]
[% END -%]
<tr class="sw_action_row">
<td>[% cf.desc %]</td>
<td>
<td>[% cf.desc %]</td> <!--- Type -->
<td> <!--- Answer Timeout (only cft) -->
[% cf_ringtimeout _ 's' IF cf.type == "cft" && cf_destinations.${cf.type}.size %]
</td>
<td>
[% BLOCK print_destination;
c.loc('[_1] for [_2]s',d.as_string _' <span class="pull-right">', d.timeout) _ '</span>';
END; -%]
[% idx = 0 -%]
[% FOR maps IN cf_destinations.${cf.type} -%]
[% IF maps.dset_name.search('^quickset_') && maps.destinations.size == 1 %]
[% PROCESS print_destination d=maps.destinations.0; -%]
[% ELSE %]
[% jdx = 0 -%]
[% maps.dset_name -%]
[% dset_unique_id = cf.type _ "dset" _ idx _ jdx _ maps.id -%]
<a href="#" data-toggle="modal" data-target="#[% dset_unique_id %]" class="pull-right"><i class="icon-question-sign"></i></a>
[% modal_header_dynamic(m.header = c.loc('Destination Set "[_1]" Details', maps.dset_name), m.id=dset_unique_id) %]
<div class="modal-body">
[% FOR d IN maps.destinations -%]
[% PROCESS print_destination d=d; %]<br/>
[% jdx = jdx + 1 -%]
[% END -%]
</div>
[% modal_footer() %]
[% idx = idx + 1 -%]
[% END %]
<br/>
[% END -%]
</td>
<td>
<td> <!--- Timeset -->
[% idx = 0 -%]
[% FOR maps IN cf_destinations.${cf.type} -%]
[% jdx = 0 -%]
@ -176,7 +150,7 @@ $( document ).ready(function() {
<br/>
[% END -%]
</td>
<td>
<td> <!--- Sources -->
[% idx = 0 -%]
[% FOR maps IN cf_destinations.${cf.type} -%]
[% jdx = 0 -%]
@ -200,6 +174,60 @@ $( document ).ready(function() {
<br/>
[% END -%]
</td>
<td> <!--- B Number (To) -->
[% idx = 0 -%]
[% FOR maps IN cf_destinations.${cf.type} -%]
[% jdx = 0 -%]
[% UNLESS maps.bset_name.defined -%]
<!-- empty or no bnumber_set -->
[% c.loc('any number'); %]
[% jdx = jdx + 1 %]
[% ELSE -%]
[% maps.bset_name -%] ([% maps.bset_mode -%])
[% bset_unique_id = cf.type _ idx _ '-' _ jdx _ '-' _ maps.id _ 'b' -%]
<a href="#" data-toggle="modal" data-target="#[% bset_unique_id %]" class="pull-right"><i class="icon-question-sign"></i></a>
[% modal_header_dynamic(m.header = c.loc('B-Number Set "[_1]" Details', maps.bset_name), m.id=bset_unique_id) %]
<div class="modal-body">
[% FOR s IN maps.bnumbers -%]
[% s.as_string %]<br/>
[% END -%]
</div>
[% modal_footer() %]
[% END %]
[% idx = idx + 1 -%]
<br/>
[% END -%]
</td>
<td> <!--- New Destinations (C-Number) -->
[% BLOCK print_destination;
c.loc('[_1] for [_2]s',d.as_string _' <span class="pull-right">', d.timeout) _ '</span>';
END; -%]
[% idx = 0 -%]
[% FOR maps IN cf_destinations.${cf.type} -%]
[% IF maps.dset_name.search('^quickset_') && maps.destinations.size == 1 %]
[% PROCESS print_destination d=maps.destinations.0; -%]
[% ELSE %]
[% jdx = 0 -%]
[% maps.dset_name -%]
[% dset_unique_id = cf.type _ "dset" _ idx _ jdx _ maps.id -%]
<a href="#" data-toggle="modal" data-target="#[% dset_unique_id %]" class="pull-right"><i class="icon-question-sign"></i></a>
[% modal_header_dynamic(m.header = c.loc('Destination Set "[_1]" Details', maps.dset_name), m.id=dset_unique_id) %]
<div class="modal-body">
[% FOR d IN maps.destinations -%]
[% PROCESS print_destination d=d; %]<br/>
[% jdx = jdx + 1 -%]
[% END -%]
</div>
[% modal_footer() %]
[% idx = idx + 1 -%]
[% END %]
<br/>
[% END -%]
</td>
<td class="ngcp-actions-column">
<div class="sw_actions">
[% UNLESS (c.user.roles == "admin" || c.user.roles == "reseller") && c.user.read_only -%]
@ -1020,6 +1048,58 @@ $( document ).ready(function() {
[% END -%]
</div>
[%
modal_footer();
modal_script(m.close_target = close_target ? close_target : c.uri_for_action('/subscriber/preferences', [c.req.captures.0]));
-%]
[% ELSIF edit_bnumberset_flag -%]
[%
PROCESS "helpers/modal.tt";
modal_header(m.name = c.loc("B-Number Sets"));
-%]
<div class="modal-body">
<div class="row" style="margin-left: 10px">
<a class="btn btn-primary btn-medium" href="[% c.uri_for_action('/subscriber/preferences_callforward_bnumberset_create', [c.req.captures.0], cf_type) %]"><i class="icon-star"></i>[% c.loc('Create New') %]</a>
</div>
<div class="ngcp-separator"></div>
[% IF cf_bnumber_sets.size -%]
<table class="table table-bordered table-striped table-highlight table-hover">
<thead>
<tr>
<th>[% c.loc('Name') %]</th>
<th>[% c.loc('Mode') %]</th>
<th>[% c.loc('Values') %]</th>
<th></th>
</tr>
</thead>
<tbody>
[% FOREACH set IN cf_bnumber_sets -%]
<tr class="sw_action_row">
<td>[% set.name %]</td>
<td>[% set.mode %]</td>
<td>
[% FOREACH number IN set.bnumbers -%]
[% number.as_string %]<br/>
[% END -%]
</td>
<td class="ngcp-actions-column">
<div class="sw_actions pull-right">
<a class="btn btn-small btn-primary" href="[% c.uri_for_action('/subscriber/preferences_callforward_bnumberset_edit', [ c.req.captures.0, set.id ], cf_type) %]">
<i class="icon-edit"></i> [% c.loc('Edit') %]
</a>
<a class="btn btn-small btn-secondary" data-confirm="Delete" href="[% c.uri_for_action('/subscriber/preferences_callforward_bnumberset_delete', [ c.req.captures.0, set.id ], cf_type) %]">
<i class="icon-trash"></i> [% c.loc('Delete') %]
</a>
</div>
</td>
</tr>
[% END -%]
</tbody>
</table>
[% END -%]
</div>
[%
modal_footer();
modal_script(m.close_target = close_target ? close_target : c.uri_for_action('/subscriber/preferences', [c.req.captures.0]));

Loading…
Cancel
Save