Add test script for API
Fix DateTime create/update issue in TimeSets API (get2put case)
(add and edit functionlity used raw/inflated data respecively)
Add datetimepicker field
Change-Id: If724b7350658c306dbbecbc04309d1d1c0b4a3e2
changes/41/23941/8
parent
b65374e8ac
commit
e462e95957
@ -0,0 +1,217 @@
|
||||
package NGCP::Panel::Controller::TimeSet;
|
||||
use NGCP::Panel::Utils::Generic qw(:all);
|
||||
use Sipwise::Base;
|
||||
|
||||
use parent 'Catalyst::Controller';
|
||||
|
||||
use NGCP::Panel::Form;
|
||||
use NGCP::Panel::Utils::Message;
|
||||
use NGCP::Panel::Utils::Navigation;
|
||||
use NGCP::Panel::Utils::TimeSet;
|
||||
|
||||
sub auto :Does(ACL) :ACLDetachTo('/denied_page') :AllowedRole(admin) :AllowedRole(reseller) {
|
||||
my ($self, $c) = @_;
|
||||
$c->log->debug(__PACKAGE__ . '::auto');
|
||||
NGCP::Panel::Utils::Navigation::check_redirect_chain(c => $c);
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub list :Chained('/') :PathPart('timeset') :CaptureArgs(0) {
|
||||
my ( $self, $c ) = @_;
|
||||
|
||||
$c->stash->{timesets_rs} = $c->model('DB')->resultset('voip_time_sets');
|
||||
unless($c->user->roles eq "admin") {
|
||||
$c->stash->{timesets_rs} = $c->stash->{timesets_rs}->search({
|
||||
reseller_id => $c->user->reseller_id
|
||||
});
|
||||
}
|
||||
$c->stash->{timeset_dt_columns} = NGCP::Panel::Utils::Datatables::set_columns($c, [
|
||||
{ name => 'id', search => 1, title => $c->loc('#') },
|
||||
$c->user->roles eq "admin"
|
||||
? { name => 'reseller.name', search => 1, title => $c->loc('Reseller') }
|
||||
: (),
|
||||
{ name => 'name', search => 1, title => $c->loc('Name') },
|
||||
]);
|
||||
|
||||
$c->stash(template => 'timeset/list.tt');
|
||||
}
|
||||
|
||||
sub root :Chained('list') :PathPart('') :Args(0) {
|
||||
my ($self, $c) = @_;
|
||||
}
|
||||
|
||||
sub ajax :Chained('list') :PathPart('ajax') :Args(0) {
|
||||
my ($self, $c) = @_;
|
||||
my $rs = $c->stash->{timesets_rs};
|
||||
NGCP::Panel::Utils::Datatables::process($c, $rs, $c->stash->{timeset_dt_columns});
|
||||
$c->detach( $c->view("JSON") );
|
||||
}
|
||||
|
||||
sub base :Chained('list') :PathPart('') :CaptureArgs(1) {
|
||||
my ($self, $c, $timeset_id) = @_;
|
||||
|
||||
unless($timeset_id && is_int($timeset_id)) {
|
||||
NGCP::Panel::Utils::Message::error(
|
||||
c => $c,
|
||||
log => 'Invalid timeset enry id detected',
|
||||
desc => $c->loc('Invalid timeset entry id detected'),
|
||||
);
|
||||
NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for('/timeset'));
|
||||
}
|
||||
|
||||
my $rs = $c->stash->{timesets_rs}->find($timeset_id);
|
||||
unless(defined($rs)) {
|
||||
NGCP::Panel::Utils::Message::error(
|
||||
c => $c,
|
||||
log => 'Timeset entry does not exist',
|
||||
desc => $c->loc('Timeset entry does not exist'),
|
||||
);
|
||||
NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for('/timeset'));
|
||||
}
|
||||
$c->stash(
|
||||
timeset => {$rs->get_inflated_columns},
|
||||
timeset_rs => $rs
|
||||
);
|
||||
}
|
||||
|
||||
sub create :Chained('list') :PathPart('create') :Args(0) {
|
||||
my ($self, $c) = @_;
|
||||
|
||||
my $posted = ($c->request->method eq 'POST');
|
||||
my $params = {};
|
||||
$params = merge($params, $c->session->{created_objects});
|
||||
my $form;
|
||||
if($c->user->roles eq "admin") {
|
||||
$form = NGCP::Panel::Form::get("NGCP::Panel::Form::TimeSet::Admin", $c);
|
||||
} else {
|
||||
$form = NGCP::Panel::Form::get("NGCP::Panel::Form::TimeSet::Reseller", $c);
|
||||
}
|
||||
$form->process(
|
||||
posted => $posted,
|
||||
params => $c->request->params,
|
||||
item => $params,
|
||||
);
|
||||
NGCP::Panel::Utils::Navigation::check_form_buttons(
|
||||
c => $c,
|
||||
form => $form,
|
||||
fields => {
|
||||
'reseller.create' => $c->uri_for('/reseller/create'),
|
||||
},
|
||||
back_uri => $c->req->uri,
|
||||
);
|
||||
if($posted && $form->validated) {
|
||||
try {
|
||||
my $resource = $form->values;
|
||||
if($c->user->roles eq "admin") {
|
||||
$resource->{reseller_id} = $form->values->{reseller}{id};
|
||||
delete $resource->{reseller};
|
||||
} else {
|
||||
$resource->{reseller_id} = $c->user->reseller_id;
|
||||
}
|
||||
$c->model('DB')->schema->txn_do( sub {
|
||||
NGCP::Panel::Utils::TimeSet::create_timesets(
|
||||
c => $c,
|
||||
resource => $form->values,
|
||||
);
|
||||
});
|
||||
delete $c->session->{created_objects}->{reseller};
|
||||
NGCP::Panel::Utils::Message::info(
|
||||
c => $c,
|
||||
desc => $c->loc('Timeset entry successfully created'),
|
||||
);
|
||||
} catch($e) {
|
||||
NGCP::Panel::Utils::Message::error(
|
||||
c => $c,
|
||||
error => $e,
|
||||
desc => $c->loc('Failed to create timeset entry'),
|
||||
);
|
||||
}
|
||||
NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for('/timeset'));
|
||||
}
|
||||
|
||||
$c->stash(form => $form);
|
||||
$c->stash(create_flag => 1);
|
||||
}
|
||||
|
||||
sub edit :Chained('base') :PathPart('edit') {
|
||||
my ($self, $c) = @_;
|
||||
|
||||
my $posted = ($c->request->method eq 'POST');
|
||||
my $params = NGCP::Panel::Utils::TimeSet::get_timeset(c => $c, timeset => $c->stash->{timeset_rs});
|
||||
$params->{reseller}{id} = delete $params->{reseller_id};
|
||||
$params = merge($params, $c->session->{created_objects});
|
||||
my $form;
|
||||
if($c->user->roles eq "admin") {
|
||||
$form = NGCP::Panel::Form::get("NGCP::Panel::Form::TimeSet::Admin", $c);
|
||||
} else {
|
||||
$form = NGCP::Panel::Form::get("NGCP::Panel::Form::Timeset::Reseller", $c);
|
||||
}
|
||||
$form->process(
|
||||
posted => $posted,
|
||||
params => $c->request->params,
|
||||
item => $params,
|
||||
);
|
||||
NGCP::Panel::Utils::Navigation::check_form_buttons(
|
||||
c => $c,
|
||||
form => $form,
|
||||
fields => {
|
||||
'reseller.create' => $c->uri_for('/reseller/create'),
|
||||
},
|
||||
back_uri => $c->req->uri,
|
||||
);
|
||||
if($posted && $form->validated) {
|
||||
try {
|
||||
$c->model('DB')->schema->txn_do( sub {
|
||||
my $resource = $form->values;
|
||||
if($c->user->roles eq "admin") {
|
||||
$resource->{reseller_id} = $form->values->{reseller}{id};
|
||||
delete $resource->{reseller};
|
||||
} else {
|
||||
$resource->{reseller_id} = $c->user->reseller_id;
|
||||
}
|
||||
NGCP::Panel::Utils::TimeSet::update_timesets(
|
||||
c => $c,
|
||||
timeset => $c->stash->{timeset_rs},
|
||||
resource => $resource,
|
||||
);
|
||||
});
|
||||
delete $c->session->{created_objects}->{reseller};
|
||||
NGCP::Panel::Utils::Message::info(
|
||||
c => $c,
|
||||
desc => $c->loc('Timeset entry successfully updated'),
|
||||
);
|
||||
} catch($e) {
|
||||
NGCP::Panel::Utils::Message::error(
|
||||
c => $c,
|
||||
error => $e,
|
||||
desc => $c->loc('Failed to update timeset entry'),
|
||||
);
|
||||
}
|
||||
NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for('/timeset'));
|
||||
}
|
||||
|
||||
$c->stash(form => $form);
|
||||
$c->stash(edit_flag => 1);
|
||||
}
|
||||
|
||||
sub delete_timeset :Chained('base') :PathPart('delete') {
|
||||
my ($self, $c) = @_;
|
||||
|
||||
try {
|
||||
$c->stash->{timeset_rs}->delete;
|
||||
NGCP::Panel::Utils::Message::info(
|
||||
c => $c,
|
||||
data => $c->stash->{timeset},
|
||||
desc => $c->loc('Timeset entry successfully deleted'),
|
||||
);
|
||||
} catch($e) {
|
||||
NGCP::Panel::Utils::Message::error(
|
||||
c => $c,
|
||||
error => $e,
|
||||
desc => $c->loc('Failed to delete timeset entry'),
|
||||
);
|
||||
}
|
||||
NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for('/timeset'));
|
||||
}
|
||||
|
||||
1;
|
||||
@ -0,0 +1,64 @@
|
||||
package NGCP::Panel::Field::DateTimePicker;
|
||||
use HTML::FormHandler::Moose;
|
||||
use Template;
|
||||
extends 'HTML::FormHandler::Field';
|
||||
|
||||
has '+widget' => (default => ''); # leave this empty, as there is no widget ...
|
||||
has 'template' => ( isa => 'Str',
|
||||
is => 'rw',
|
||||
default => 'helpers/datetimepicker.tt' );
|
||||
has 'language_file' => (isa => 'Str', is => 'rw', default => 'dataTables.default.js' );
|
||||
has 'date_format_js' => (isa => 'Str', is => 'rw', default => 'yy-mm-dd' );
|
||||
has 'time_format_js' => (isa => 'Str', is => 'rw', default => 'HH:mm:ss' );
|
||||
|
||||
sub render_element {
|
||||
my ($self) = @_;
|
||||
my $output = '';
|
||||
|
||||
(my $fieldname = $self->html_name) =~ s!\.!!g;
|
||||
|
||||
my $vars = {
|
||||
label => $self->label,
|
||||
field_name => $self->html_name,
|
||||
field_id => $fieldname . "_datetimepicker",
|
||||
value => $self->value,
|
||||
date_format_js => $self->date_format_js,
|
||||
time_format_js => $self->time_format_js,
|
||||
errors => $self->errors,
|
||||
language_file => $self->language_file,
|
||||
};
|
||||
my $t = new Template({
|
||||
ABSOLUTE => 1,
|
||||
INCLUDE_PATH => [
|
||||
'/usr/share/ngcp-panel/templates',
|
||||
'share/templates',
|
||||
],
|
||||
});
|
||||
|
||||
$t->process($self->template, $vars, \$output) or
|
||||
die "Failed to process DateTimePicker field template: ".$t->error();
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
sub render {
|
||||
my ( $self, $result ) = @_;
|
||||
$result ||= $self->result;
|
||||
die "No result for form field '" . $self->full_name . "'. Field may be inactive." unless $result;
|
||||
return $self->render_element( $result );
|
||||
}
|
||||
|
||||
sub validate {
|
||||
my ( $self ) = @_;
|
||||
|
||||
if($self->required &&
|
||||
( !defined $self->value || !length($self->value) || $self->value !~ /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/ ) ) {
|
||||
return $self->add_error("Invalid datetime, must be in format YYYY-mm-DD HH:MM:SS");
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
no Moose;
|
||||
1;
|
||||
|
||||
# vim: set tabstop=4 expandtab:
|
||||
@ -0,0 +1,23 @@
|
||||
package NGCP::Panel::Form::TimeSet::Admin;
|
||||
|
||||
use HTML::FormHandler::Moose;
|
||||
extends 'NGCP::Panel::Form::TimeSet::Reseller';
|
||||
|
||||
has_field 'reseller' => (
|
||||
type => '+NGCP::Panel::Field::Reseller',
|
||||
validate_when_empty => 1,
|
||||
element_attr => {
|
||||
rel => ['tooltip'],
|
||||
title => ['The reseller id to assign this timeset entry to.']
|
||||
},
|
||||
);
|
||||
|
||||
has_block 'fields' => (
|
||||
tag => 'div',
|
||||
class => [qw/modal-body/],
|
||||
render_list => [qw/id reseller name times times_add/],
|
||||
);
|
||||
|
||||
1;
|
||||
|
||||
# vim: set tabstop=4 expandtab:
|
||||
@ -0,0 +1,259 @@
|
||||
package NGCP::Panel::Form::TimeSet::Reseller;
|
||||
|
||||
use HTML::FormHandler::Moose;
|
||||
extends 'HTML::FormHandler';
|
||||
|
||||
use HTML::FormHandler::Widget::Block::Bootstrap;
|
||||
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 'id' => (
|
||||
type => 'Hidden',
|
||||
);
|
||||
|
||||
has_field 'name' => (
|
||||
type => 'Text',
|
||||
label => 'Name',
|
||||
required => 1,
|
||||
);
|
||||
|
||||
has_field 'times' => (
|
||||
type => 'Repeatable',
|
||||
setup_for_js => 1,
|
||||
do_wrapper => 1,
|
||||
do_label => 1,
|
||||
wrapper_class => [qw/hfh-rep-block/],
|
||||
element_attr => {
|
||||
rel => ['tooltip'],
|
||||
title => ['An array of time definitions with a number of optional and mandatory keys.']
|
||||
},
|
||||
);
|
||||
|
||||
has_field 'times.id' => (
|
||||
type => 'Hidden',
|
||||
);
|
||||
|
||||
has_field 'times.start' => (
|
||||
type => '+NGCP::Panel::Field::DateTimePicker',
|
||||
label => 'Start',
|
||||
required => 1,
|
||||
);
|
||||
|
||||
has_field 'times.end' => (
|
||||
type => '+NGCP::Panel::Field::DateTimePicker',
|
||||
label => 'End',
|
||||
);
|
||||
|
||||
has_field 'times.freq' => (
|
||||
type => 'Select',
|
||||
label => 'Frequency',
|
||||
options => [
|
||||
map { +{value => $_, label => $_}; } (qw/secondly minutely hourly daily weekly monthly yearly/)
|
||||
],
|
||||
);
|
||||
|
||||
has_field 'times.until' => (
|
||||
label => 'Until',
|
||||
type => '+NGCP::Panel::Field::DateTimePicker',
|
||||
element_attr => {
|
||||
rel => ['tooltip'],
|
||||
title => ['Can\'t be defined together with "Count".']
|
||||
},
|
||||
);
|
||||
|
||||
has_field 'times.count' => (
|
||||
type => 'PosInteger',
|
||||
label => 'Count',
|
||||
element_attr => {
|
||||
rel => ['tooltip'],
|
||||
title => ['Valid value is a positive integer. Can\'t be defined together with "Until".']
|
||||
},
|
||||
);
|
||||
|
||||
has_field 'times.interval' => (
|
||||
type => 'PosInteger',
|
||||
label => 'Interval',
|
||||
element_attr => {
|
||||
rel => ['tooltip'],
|
||||
title => ['Valid value is a positive integer.']
|
||||
},
|
||||
);
|
||||
|
||||
has_field 'times.bysecond' => (
|
||||
type => '+NGCP::Panel::Field::IntegerList',
|
||||
label => 'By second',
|
||||
min_value => 0,
|
||||
max_value => 59,
|
||||
element_attr => {
|
||||
rel => ['tooltip'],
|
||||
title => ['Value is set of numbers from 0 to 59, i.e. 1,3,59.']
|
||||
},
|
||||
);
|
||||
|
||||
has_field 'times.byminute' => (
|
||||
type => '+NGCP::Panel::Field::IntegerList',
|
||||
label => 'By minute',
|
||||
min_value => 0,
|
||||
max_value => 59,
|
||||
element_attr => {
|
||||
rel => ['tooltip'],
|
||||
title => ['Value is set of numbers from 0 to 59, i.e. 1,3,59.']
|
||||
},
|
||||
);
|
||||
|
||||
has_field 'times.byhour' => (
|
||||
type => '+NGCP::Panel::Field::IntegerList',
|
||||
label => 'By hour',
|
||||
min_value => 0,
|
||||
max_value => 23,
|
||||
element_attr => {
|
||||
rel => ['tooltip'],
|
||||
title => ['Value is set of numbers from 0 to 23, i.e. 1,3,23.']
|
||||
},
|
||||
);
|
||||
|
||||
has_field 'times.byday' => (
|
||||
type => 'Text', # (\+|-)?\d*(MO|DI|MI|DO|FR|SA|SU)
|
||||
label => 'By day',
|
||||
element_attr => {
|
||||
rel => ['tooltip'],
|
||||
title => ['Value format is ~[+|-~]~[NUMBER~](MO|DI|MI|DO|FR|SA|SU). Example: 5FR (means fifth friday).']
|
||||
},
|
||||
# example: 5FR (means fifth friday)
|
||||
);
|
||||
|
||||
has_field 'times.bymonthday' => (
|
||||
type => '+NGCP::Panel::Field::IntegerList',
|
||||
label => 'By month day',
|
||||
min_value => 1,
|
||||
max_value => 31,
|
||||
plusminus => 1,
|
||||
element_attr => {
|
||||
rel => ['tooltip'],
|
||||
title => ['Value is set of numbers from 1 to 31, i.e. 1,3,31.']
|
||||
},
|
||||
);
|
||||
|
||||
has_field 'times.byyearday' => (
|
||||
type => '+NGCP::Panel::Field::IntegerList',
|
||||
label => 'By year day',
|
||||
min_value => 1,
|
||||
max_value => 366,
|
||||
plusminus => 1,
|
||||
element_attr => {
|
||||
rel => ['tooltip'],
|
||||
title => ['Value is set of numbers from 1 to 366, i.e. 1,3,366.']
|
||||
},
|
||||
);
|
||||
|
||||
has_field 'times.byweekno' => (
|
||||
type => '+NGCP::Panel::Field::IntegerList',
|
||||
label => 'By week number',
|
||||
min_value => 1,
|
||||
max_value => 53,
|
||||
element_attr => {
|
||||
rel => ['tooltip'],
|
||||
title => ['Value is set of numbers from 1 to 53, i.e. 1,3,53.']
|
||||
},
|
||||
);
|
||||
|
||||
has_field 'times.bymonth' => (
|
||||
type => '+NGCP::Panel::Field::IntegerList',
|
||||
label => 'By month',
|
||||
min_value => 1,
|
||||
max_value => 12,
|
||||
element_attr => {
|
||||
rel => ['tooltip'],
|
||||
title => ['Value is set of numbers from 1 to 12, i.e. 1,3,12.']
|
||||
},
|
||||
);
|
||||
|
||||
has_field 'times.bysetpos' => (
|
||||
type => '+NGCP::Panel::Field::IntegerList',
|
||||
label => 'By set position',
|
||||
min_value => 1,
|
||||
max_value => 366,
|
||||
plusminus => 1,
|
||||
element_attr => {
|
||||
rel => ['tooltip'],
|
||||
title => ['Value is set of numbers from 1 to 366, i.e. 1,3,366.']
|
||||
},
|
||||
);
|
||||
|
||||
has_field 'times.comment' => (
|
||||
type => 'Text',
|
||||
label => 'Comment',
|
||||
);
|
||||
|
||||
has_field 'times.rm' => (
|
||||
type => 'RmElement',
|
||||
value => 'Remove Set',
|
||||
order => 100,
|
||||
element_class => [qw/btn btn-primary pull-right/],
|
||||
);
|
||||
|
||||
has_field 'times_add' => (
|
||||
type => 'AddElement',
|
||||
repeatable => 'times',
|
||||
value => 'Add another Set',
|
||||
element_class => [qw/btn btn-primary pull-right/],
|
||||
);
|
||||
|
||||
|
||||
has_field 'save' => (
|
||||
type => 'Submit',
|
||||
value => 'Save',
|
||||
element_class => [qw/btn btn-primary/],
|
||||
label => '',
|
||||
);
|
||||
|
||||
has_block 'fields' => (
|
||||
tag => 'div',
|
||||
class => [qw/modal-body/],
|
||||
render_list => [qw/id name times times_add/],
|
||||
);
|
||||
|
||||
has_block 'actions' => (
|
||||
tag => 'div',
|
||||
class => [qw/modal-footer/],
|
||||
render_list => [qw/save/],
|
||||
);
|
||||
|
||||
sub validate {
|
||||
my ($self, $field) = @_;
|
||||
my $c = $self->ctx;
|
||||
return unless $c;
|
||||
my $schema = $c->model('DB');
|
||||
|
||||
my $name = $self->field('name')->value;
|
||||
my $reseller_id;
|
||||
#Todo: to some utils?
|
||||
if ($c->user->roles eq 'admin') {
|
||||
if ($self->field('reseller')) {
|
||||
$reseller_id = $self->field('reseller')->value;
|
||||
} elsif($c->stash->{reseller}) { #strange, reseller interface keeps rs as reseller, not reseller_rs
|
||||
$reseller_id = $c->stash->{reseller}->first->id;
|
||||
}
|
||||
} else {
|
||||
$reseller_id = $c->user->reseller_id
|
||||
}
|
||||
unless ($reseller_id) {
|
||||
#we shouldn't get here
|
||||
$self->field('name')->add_error($c->loc('Unknow reseller'));
|
||||
}
|
||||
#/todo
|
||||
my $existing_item = $schema->resultset('voip_time_sets')->find({
|
||||
name => $name,
|
||||
});
|
||||
my $current_item = $c->stash->{timeset_rs};
|
||||
if ($existing_item && (!$current_item || $existing_item->id != $current_item->id)) {
|
||||
$self->field('name')->add_error($c->loc('This name already exists'));
|
||||
}
|
||||
}
|
||||
1;
|
||||
|
||||
# vim: set tabstop=4 expandtab:
|
||||
@ -0,0 +1,109 @@
|
||||
package NGCP::Panel::Utils::TimeSet;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Sipwise::Base;
|
||||
use NGCP::Panel::Utils::DateTime;
|
||||
|
||||
sub delete_timesets {
|
||||
my %params = @_;
|
||||
my($c, $timeset) = @params{qw/c timeset/};
|
||||
|
||||
$timeset->delete();
|
||||
}
|
||||
|
||||
sub update_timesets {
|
||||
my %params = @_;
|
||||
my($c, $timeset, $resource) = @params{qw/c timeset resource/};
|
||||
|
||||
$timeset->update({
|
||||
name => $resource->{name},
|
||||
reseller_id => $resource->{reseller_id},
|
||||
})->discard_changes;
|
||||
$timeset->time_periods->delete;
|
||||
for my $t ( @{$resource->{times} } ) {
|
||||
$timeset->create_related("time_periods", {
|
||||
%{ $t },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
sub create_timesets {
|
||||
my %params = @_;
|
||||
my($c, $resource) = @params{qw/c resource/};
|
||||
|
||||
my $schema = $c->model('DB');
|
||||
|
||||
my $timeset = $schema->resultset('voip_time_sets')->create({
|
||||
name => $resource->{name},
|
||||
reseller_id => $resource->{reseller_id},
|
||||
});
|
||||
for my $t ( @{$resource->{times}} ) {
|
||||
$timeset->create_related("time_periods", {
|
||||
%{ $t },
|
||||
});
|
||||
}
|
||||
return $timeset;
|
||||
}
|
||||
|
||||
sub get_timeset {
|
||||
my %params = @_;
|
||||
my($c, $timeset, $date_mysql_format) = @params{qw/c timeset date_mysql_format/};
|
||||
|
||||
my $resource = { $timeset->get_inflated_columns };
|
||||
|
||||
my @periods;
|
||||
for my $period ($timeset->time_periods->all) {
|
||||
my $period_infl = { $period->get_inflated_columns, };
|
||||
delete @{ $period_infl }{'time_set_id', 'id'};
|
||||
if (!$date_mysql_format) {
|
||||
foreach my $date_key (qw/start end until/) {
|
||||
if (defined $period_infl->{$date_key}) {
|
||||
$period_infl->{$date_key} = NGCP::Panel::Utils::DateTime::from_mysql_to_js($period_infl->{$date_key});
|
||||
}
|
||||
}
|
||||
}
|
||||
for my $k (keys %{ $period_infl }) {
|
||||
delete $period_infl->{$k} unless defined $period_infl->{$k};
|
||||
}
|
||||
push @periods, $period_infl;
|
||||
}
|
||||
$resource->{times} = \@periods;
|
||||
return $resource;
|
||||
}
|
||||
1;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
NGCP::Panel::Utils::TimeSet
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
A temporary helper to manipulate resellers data
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=head2 update_timesets
|
||||
|
||||
Update timesets database data
|
||||
|
||||
=head2 create_timesets
|
||||
|
||||
Create timesets database data
|
||||
|
||||
=head2 get_timesets
|
||||
|
||||
Get timesets data from database to show to the user
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Irina Peshinskaya
|
||||
|
||||
=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:
|
||||
@ -0,0 +1,21 @@
|
||||
<div class="control-group [% IF errors.size %]error[% END %]">
|
||||
<script src="/js/libs/jquery-ui-timepicker-addon.js"></script>
|
||||
[% date_format_js = date_format_js || 'yy-mm-dd' %]
|
||||
[% time_format_js = time_format_js || 'HH:mm:ss' %]
|
||||
<label class="control-label" for="[% field_id %]">[% label %]</label>
|
||||
<div class="controls">
|
||||
<input type="text" name="[% field_name %]" id="[% field_id %]" value="[%value%]" class="ngcp-datepicker" rel="tooltip" data-original-title="[% date_format_js %] [% time_format_js %]" onclick="
|
||||
$(this).datetimepicker({
|
||||
'dateFormat': '[% date_format_js %]',
|
||||
'showSecond': true,
|
||||
'timeFormat': '[% time_format_js %]',
|
||||
});
|
||||
$(this).datetimepicker('show');"/>
|
||||
[% IF errors.size -%]
|
||||
<span class="help-inline">
|
||||
[% errors.join('<br/>') %]
|
||||
</span>
|
||||
[% END -%]
|
||||
</div>
|
||||
</div>
|
||||
[% # vim: set tabstop=4 syntax=html expandtab: -%]
|
||||
@ -0,0 +1,27 @@
|
||||
[% site_config.title = c.loc('Time Set') -%]
|
||||
[%
|
||||
helper.name = c.loc('Time Set');
|
||||
helper.identifier = 'timeset';
|
||||
helper.messages = messages;
|
||||
helper.dt_columns = timeset_dt_columns;
|
||||
helper.length_change = 1;
|
||||
|
||||
helper.close_target = close_target;
|
||||
helper.create_flag = create_flag;
|
||||
helper.edit_flag = edit_flag;
|
||||
helper.form_object = form;
|
||||
helper.ajax_uri = c.uri_for_action( "/timeset/ajax" );
|
||||
|
||||
UNLESS c.user.read_only;
|
||||
helper.dt_buttons = [
|
||||
{ name = c.loc('Edit'), uri = "/timeset/'+full.id+'/edit", class = 'btn-small btn-primary', icon = 'icon-edit' },
|
||||
{ name = c.loc('Delete'), uri = "/timeset/'+full.id+'/delete", class = 'btn-small btn-secondary', icon = 'icon-trash' },
|
||||
];
|
||||
helper.top_buttons = [
|
||||
{ name = c.loc('Create Time Set Entry'), uri = c.uri_for('/timeset/create'), icon = 'icon-star' },
|
||||
];
|
||||
END;
|
||||
|
||||
PROCESS 'helpers/datatables.tt';
|
||||
-%]
|
||||
[% # vim: set tabstop=4 syntax=html expandtab: -%]
|
||||
@ -0,0 +1,47 @@
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Test::Collection;
|
||||
use Test::FakeData;
|
||||
use Test::More;
|
||||
use Data::Dumper;
|
||||
|
||||
#init test_machine
|
||||
my $test_machine = Test::Collection->new(
|
||||
name => 'timesets',
|
||||
);
|
||||
$test_machine->methods->{collection}->{allowed} = {map {$_ => 1} qw(GET HEAD OPTIONS POST)};
|
||||
$test_machine->methods->{item}->{allowed} = {map {$_ => 1} qw(GET HEAD OPTIONS PUT PATCH DELETE)};
|
||||
|
||||
my $fake_data = Test::FakeData->new;
|
||||
$fake_data->set_data_from_script({
|
||||
timesets => {
|
||||
data => {
|
||||
reseller_id => sub { return shift->get_id('resellers',@_); },
|
||||
name => 'api_test_timeset_name',
|
||||
times => [{
|
||||
start => '1971-01-01 00:00:01',
|
||||
end => '2020-12-31 23:59:59',
|
||||
until => '1997-01-01 23:59:59',
|
||||
}],
|
||||
},
|
||||
'query' => ['name'],
|
||||
'data_callbacks' => {
|
||||
'uniquizer_cb' => sub { Test::FakeData::string_uniquizer(\$_[0]->{name}); },
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
#for item creation test purposes /post request data/
|
||||
$test_machine->DATA_ITEM_STORE($fake_data->process('timesets'));
|
||||
|
||||
$test_machine->form_data_item( );
|
||||
# create 3 new sound sets from DATA_ITEM
|
||||
$test_machine->check_create_correct( 3, sub{ $_[0]->{name} .= $_[1]->{i}; } );
|
||||
$test_machine->check_get2put();
|
||||
$test_machine->check_bundle();
|
||||
$test_machine->clear_test_data_all();
|
||||
|
||||
done_testing;
|
||||
|
||||
# vim: set tabstop=4 expandtab:
|
||||
Loading…
Reference in new issue