diff --git a/lib/NGCP/Panel/Controller/SubscriberProfile.pm b/lib/NGCP/Panel/Controller/SubscriberProfile.pm index 299c659601..2de410895c 100644 --- a/lib/NGCP/Panel/Controller/SubscriberProfile.pm +++ b/lib/NGCP/Panel/Controller/SubscriberProfile.pm @@ -3,9 +3,11 @@ use Sipwise::Base; BEGIN { extends 'Catalyst::Controller'; } -use NGCP::Panel::Form::SubscriberProfile::Admin; -use NGCP::Panel::Form::SubscriberProfile::Reseller; -use NGCP::Panel::Form::SubscriberProfile::Clone; +use NGCP::Panel::Form::SubscriberProfile::CatalogAdmin; +use NGCP::Panel::Form::SubscriberProfile::CatalogReseller; +use NGCP::Panel::Form::SubscriberProfile::Profile; +use NGCP::Panel::Form::SubscriberProfile::CatalogClone; +use NGCP::Panel::Form::SubscriberProfile::ProfileClone; use NGCP::Panel::Utils::Message; use NGCP::Panel::Utils::Navigation; @@ -16,67 +18,67 @@ sub auto { return 1; } -sub profile_list :Chained('/') :PathPart('subscriberprofile') :CaptureArgs(0) { +sub catalog_list :Chained('/') :PathPart('subscriberprofile') :CaptureArgs(0) :Does(ACL) :ACLDetachTo('/denied_page') :AllowedRole(admin) :AllowedRole(reseller) { my ( $self, $c ) = @_; - $c->stash->{profiles_rs} = $c->model('DB')->resultset('voip_subscriber_profiles'); + $c->stash->{cat_rs} = $c->model('DB')->resultset('voip_subscriber_profile_catalogs'); if($c->user->roles eq "admin") { } elsif($c->user->roles eq "reseller") { - $c->stash->{profiles_rs} = $c->stash->{profiles_rs}->search({ + $c->stash->{cat_rs} = $c->stash->{cat_rs}->search({ reseller_id => $c->user->reseller_id }); } else { - $c->stash->{profiles_rs} = $c->stash->{profiles_rs}->search({ + $c->stash->{cat_rs} = $c->stash->{cat_rs}->search({ reseller_id => $c->user->voip_subscriber->contract->contact->reseller_id, }); } - $c->stash->{profile_dt_columns} = NGCP::Panel::Utils::Datatables::set_columns($c, [ + $c->stash->{cat_dt_columns} = NGCP::Panel::Utils::Datatables::set_columns($c, [ { name => 'id', search => 1, title => $c->loc('#') }, { name => 'reseller.name', search => 1, title => $c->loc('Reseller') }, { name => 'name', search => 1, title => $c->loc('Name') }, { name => 'description', search => 1, title => $c->loc('Description') }, ]); - $c->stash(template => 'subprofile/list.tt'); + $c->stash(template => 'subprofile/cat_list.tt'); } -sub root :Chained('profile_list') :PathPart('') :Args(0) :Does(ACL) :ACLDetachTo('/denied_page') :AllowedRole(admin) :AllowedRole(reseller) { +sub catalog_root :Chained('catalog_list') :PathPart('') :Args(0) { my ($self, $c) = @_; } -sub ajax :Chained('profile_list') :PathPart('ajax') :Args(0) { +sub catalog_ajax :Chained('catalog_list') :PathPart('ajax') :Args(0) { my ($self, $c) = @_; - my $rs = $c->stash->{profiles_rs}; - NGCP::Panel::Utils::Datatables::process($c, $rs, $c->stash->{profile_dt_columns}); + my $rs = $c->stash->{cat_rs}; + NGCP::Panel::Utils::Datatables::process($c, $rs, $c->stash->{cat_dt_columns}); $c->detach( $c->view("JSON") ); } -sub base :Chained('profile_list') :PathPart('') :CaptureArgs(1) :Does(ACL) :ACLDetachTo('/denied_page') :AllowedRole(admin) :AllowedRole(reseller) { - my ($self, $c, $profile_id) = @_; +sub catalog_base :Chained('catalog_list') :PathPart('') :CaptureArgs(1) { + my ($self, $c, $cat_id) = @_; - unless($profile_id && $profile_id->is_integer) { + unless($cat_id && $cat_id->is_integer) { NGCP::Panel::Utils::Message->error( c => $c, - log => 'Invalid subscriber profile id detected', - desc => $c->loc('Invalid subscriber profile id detected'), + log => 'Invalid subscriber profile catalog id detected', + desc => $c->loc('Invalid subscriber profile catalog id detected'), ); - NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for('/rewrite')); + NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for('/subscriberprofile')); } - my $res = $c->stash->{profiles_rs}->find($profile_id); + my $res = $c->stash->{cat_rs}->find($cat_id); unless(defined($res)) { NGCP::Panel::Utils::Message->error( c => $c, - log => 'Subscriber profile does not exist', - desc => $c->loc('Subscriber profile does not exist'), + log => 'Subscriber profile catalog does not exist', + desc => $c->loc('Subscriber profile catalog does not exist'), ); NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for('/subscriberprofile')); } - $c->stash(profile_result => $res); + $c->stash(cat => $res); } -sub create :Chained('profile_list') :PathPart('create') :Args(0) :Does(ACL) :ACLDetachTo('/denied_page') :AllowedRole(admin) :AllowedRole(reseller) { +sub catalog_create :Chained('catalog_list') :PathPart('create') :Args(0) { my ($self, $c) = @_; my $posted = ($c->request->method eq 'POST'); @@ -84,11 +86,66 @@ sub create :Chained('profile_list') :PathPart('create') :Args(0) :Does(ACL) :ACL $params = $params->merge($c->session->{created_objects}); my $form; if($c->user->roles eq "admin") { - $form = NGCP::Panel::Form::SubscriberProfile::Admin->new(ctx => $c); - $form->create_structure($form->field_names); + $form = NGCP::Panel::Form::SubscriberProfile::CatalogAdmin->new; + } else { + $form = NGCP::Panel::Form::SubscriberProfile::CatalogReseller->new; + } + $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 $schema = $c->model('DB'); + $schema->txn_do(sub { + my $reseller_id; + if($c->user->roles eq "admin") { + $form->values->{reseller_id} = $form->values->{reseller}{id}; + } else { + $form->values->{reseller_id} = $c->user->reseller_id; + } + delete $form->values->{reseller}; + $c->stash->{cat_rs}->create($form->values); + + delete $c->session->{created_objects}->{reseller}; + }); + $c->flash(messages => [{type => 'success', text => $c->loc('Subscriber profile catalog successfully created')}]); + } catch($e) { + NGCP::Panel::Utils::Message->error( + c => $c, + error => $e, + desc => $c->loc('Failed to create subscriber profile catalog.'), + ); + } + NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for('/subscriberprofile')); + } + + $c->stash(form => $form); + $c->stash(create_flag => 1); +} + +sub catalog_edit :Chained('catalog_base') :PathPart('edit') { + my ($self, $c) = @_; + + my $cat = $c->stash->{cat}; + my $posted = ($c->request->method eq 'POST'); + my $params = { $cat->get_inflated_columns }; + $params->{reseller}{id} = delete $params->{reseller_id}; + $params = $params->merge($c->session->{created_objects}); + my $form; + if($c->user->roles eq "admin") { + $form = NGCP::Panel::Form::SubscriberProfile::CatalogAdmin->new; } else { - $form = NGCP::Panel::Form::SubscriberProfile::Reseller->new(ctx => $c); - $form->create_structure($form->field_names); + $form = NGCP::Panel::Form::SubscriberProfile::CatalogReseller->new; } $form->process( posted => $posted, @@ -109,15 +166,190 @@ sub create :Chained('profile_list') :PathPart('create') :Args(0) :Does(ACL) :ACL $schema->txn_do(sub { my $reseller_id; if($c->user->roles eq "admin") { - $reseller_id = $form->values->{reseller}{id}; + $form->values->{reseller_id} = $form->values->{reseller}{id}; } else { - $reseller_id = $c->user->reseller_id; + $form->values->{reseller_id} = $c->user->reseller_id; } delete $form->values->{reseller}; + $cat->update($form->values); + + delete $c->session->{created_objects}->{reseller}; + }); + $c->flash(messages => [{type => 'success', text => $c->loc('Subscriber profile catalog successfully updated')}]); + } catch($e) { + NGCP::Panel::Utils::Message->error( + c => $c, + error => $e, + desc => $c->loc('Failed to update subscriber profile catalog.'), + ); + } + NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for('/subscriberprofile')); + } + + $c->stash(form => $form); + $c->stash(edit_flag => 1); +} + +sub catalog_delete :Chained('catalog_base') :PathPart('delete') { + my ($self, $c) = @_; + + try { + my $schema = $c->model('DB'); + $schema->txn_do(sub{ + $schema->resultset('provisioning_voip_subscribers')->search({ + profile_catalog_id => $c->stash->{cat}->id + })->update({ + profile_catalog_id => undef, + profile_id => undef, + }); + $c->stash->{cat}->voip_subscriber_profiles->delete; + $c->stash->{cat}->delete; + }); + $c->flash(messages => [{type => 'success', text => $c->loc('Subscriber profile catalog successfully deleted')}]); + } catch($e) { + NGCP::Panel::Utils::Message->error( + c => $c, + error => $e, + desc => $c->loc('Failed to delete subscriber profile catalog.'), + ); + } + NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for('/subscriberprofile')); +} + +sub catalog_clone :Chained('catalog_base') :PathPart('clone') :Does(ACL) :ACLDetachTo('/denied_page') :AllowedRole(admin) :AllowedRole(reseller) { + my ($self, $c) = @_; + + my $posted = ($c->request->method eq 'POST'); + my $params = { $c->stash->{cat}->get_inflated_columns }; + $params = $params->merge($c->session->{created_objects}); + my $form = NGCP::Panel::Form::SubscriberProfile::CatalogClone->new; + $form->process( + posted => $posted, + params => $c->request->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 { + my $new_cat = $schema->resultset('voip_subscriber_profile_catalogs')->create({ + %{ $form->values }, + reseller_id => $c->stash->{cat}->reseller_id, + }); + foreach my $prof($c->stash->{cat}->voip_subscriber_profiles->all) { + my $old = { $prof->get_inflated_columns }; + foreach(qw/id catalog_id/) { + delete $old->{$_}; + } + my $new_prof = $new_cat->voip_subscriber_profiles->create($old); + my @old_attributes = $prof->profile_attributes->all; + foreach my $attr (@old_attributes) { + $new_prof->profile_attributes->create({ + attribute_id => $attr->attribute_id, + }); + } + } + }); + + $c->flash(messages => [{type => 'success', text => $c->loc('Subscriber profile successfully cloned')}]); + } catch($e) { + NGCP::Panel::Utils::Message->error( + c => $c, + error => $e, + desc => $c->loc('Failed to clone subscriber profile.'), + ); + } + NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for('/subscriberprofile')); + } + + $c->stash(form => $form); + $c->stash(create_flag => 1); + $c->stash(clone_flag => 1); +} + + +sub profile_list :Chained('catalog_base') :PathPart('profile') :CaptureArgs(0) { + my ( $self, $c ) = @_; + + $c->stash->{profile_dt_columns} = NGCP::Panel::Utils::Datatables::set_columns($c, [ + { name => 'id', search => 1, title => $c->loc('#') }, + { name => 'name', search => 1, title => $c->loc('Name') }, + { name => 'description', search => 1, title => $c->loc('Description') }, + ]); + + $c->stash(template => 'subprofile/profile_list.tt'); +} + +sub profile_root :Chained('profile_list') :PathPart('') :Args(0) :Does(ACL) :ACLDetachTo('/denied_page') :AllowedRole(admin) :AllowedRole(reseller) { + my ($self, $c) = @_; +} + +sub profile_ajax :Chained('profile_list') :PathPart('ajax') :Args(0) { + my ($self, $c) = @_; + my $rs = $c->stash->{cat}->voip_subscriber_profiles; + NGCP::Panel::Utils::Datatables::process($c, $rs, $c->stash->{profile_dt_columns}); + $c->detach( $c->view("JSON") ); +} + +sub profile_base :Chained('profile_list') :PathPart('') :CaptureArgs(1) :Does(ACL) :ACLDetachTo('/denied_page') :AllowedRole(admin) :AllowedRole(reseller) { + my ($self, $c, $profile_id) = @_; + + unless($profile_id && $profile_id->is_integer) { + NGCP::Panel::Utils::Message->error( + c => $c, + log => 'Invalid subscriber profile id detected', + desc => $c->loc('Invalid subscriber profile id detected'), + ); + NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for('/rewrite')); + } + + my $res = $c->stash->{cat}->voip_subscriber_profiles->find($profile_id); + unless(defined($res)) { + NGCP::Panel::Utils::Message->error( + c => $c, + log => 'Subscriber profile does not exist', + desc => $c->loc('Subscriber profile does not exist'), + ); + NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for_action('/subscriberprofile/profile_root', [$c->stash->{cat}->id])); + } + $c->stash( + profile => $res, + close_target => $c->uri_for_action('/subscriberprofile/profile_root', [$c->stash->{cat}->id]), + ); +} + +sub profile_create :Chained('profile_list') :PathPart('create') :Args(0) :Does(ACL) :ACLDetachTo('/denied_page') :AllowedRole(admin) :AllowedRole(reseller) { + my ($self, $c) = @_; + + my $posted = ($c->request->method eq 'POST'); + my $params = {}; + $params = $params->merge($c->session->{created_objects}); + my $form = NGCP::Panel::Form::SubscriberProfile::Profile->new(ctx => $c); + $form->create_structure($form->field_names); + $form->process( + posted => $posted, + params => $c->request->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 { my $name = delete $form->values->{name}; my $desc = delete $form->values->{description}; - my $profile = $c->stash->{profiles_rs}->create({ - reseller_id => $reseller_id, + my $profile = $c->stash->{cat}->voip_subscriber_profiles->create({ name => $name, description => $desc, }); @@ -130,8 +362,6 @@ sub create :Chained('profile_list') :PathPart('create') :Args(0) :Does(ACL) :ACL attribute_id => $form->values->{$attr}, }); } - - delete $c->session->{created_objects}->{reseller}; }); $c->flash(messages => [{type => 'success', text => $c->loc('Subscriber profile successfully created')}]); } catch($e) { @@ -141,32 +371,24 @@ sub create :Chained('profile_list') :PathPart('create') :Args(0) :Does(ACL) :ACL desc => $c->loc('Failed to create subscriber profile.'), ); } - NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for('/subscriberprofile')); + NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for_action('/subscriberprofile/profile_root', [$c->stash->{cat}->id])); } $c->stash(form => $form); $c->stash(create_flag => 1); } -sub edit :Chained('base') :PathPart('edit') :Does(ACL) :ACLDetachTo('/denied_page') :AllowedRole(admin) :AllowedRole(reseller) { +sub profile_edit :Chained('profile_base') :PathPart('edit') :Does(ACL) :ACLDetachTo('/denied_page') :AllowedRole(admin) :AllowedRole(reseller) { my ($self, $c) = @_; - my $profile = $c->stash->{profile_result}; + my $profile = $c->stash->{profile}; my $posted = ($c->request->method eq 'POST'); my $params = { $profile->get_inflated_columns }; - $params->{reseller}{id} = delete $params->{reseller_id}; - $params = $params->merge($c->session->{created_objects}); foreach my $old_attr($profile->profile_attributes->all) { $params->{$old_attr->attribute->attribute} = $old_attr->attribute->id; } - my $form; - if($c->user->roles eq "admin") { - $form = NGCP::Panel::Form::SubscriberProfile::Admin->new(ctx => $c); - $form->create_structure($form->field_names); - } else { - $form = NGCP::Panel::Form::SubscriberProfile::Reseller->new(ctx => $c); - $form->create_structure($form->field_names); - } + my $form = NGCP::Panel::Form::SubscriberProfile::Profile->new(ctx => $c); + $form->create_structure($form->field_names); $form->process( posted => $posted, params => $c->request->params, @@ -175,22 +397,13 @@ sub edit :Chained('base') :PathPart('edit') :Does(ACL) :ACLDetachTo('/denied_pag NGCP::Panel::Utils::Navigation::check_form_buttons( c => $c, form => $form, - fields => { - 'reseller.create' => $c->uri_for('/reseller/create'), - }, + fields => {}, back_uri => $c->req->uri, ); if($posted && $form->validated) { try { my $schema = $c->model('DB'); $schema->txn_do(sub { - my $reseller_id; - if($c->user->roles eq "admin") { - $reseller_id = $form->values->{reseller}{id}; - } else { - $reseller_id = $c->user->reseller_id; - } - delete $form->values->{reseller}; my $name = delete $form->values->{name}; my $desc = delete $form->values->{description}; unless($name eq $profile->name && $desc eq $profile->description) { @@ -201,7 +414,7 @@ sub edit :Chained('base') :PathPart('edit') :Does(ACL) :ACLDetachTo('/denied_pag } # TODO: reuse attributes for efficiency reasons? - $profile->profile_attributes->delete_all; + $profile->profile_attributes->delete; # TODO: should we rather take the name and load the id from db, # instead of trusting the id coming from user input? @@ -212,7 +425,6 @@ sub edit :Chained('base') :PathPart('edit') :Does(ACL) :ACLDetachTo('/denied_pag }); } - delete $c->session->{created_objects}->{reseller}; }); $c->flash(messages => [{type => 'success', text => $c->loc('Subscriber profile successfully updated')}]); } catch($e) { @@ -222,18 +434,27 @@ sub edit :Chained('base') :PathPart('edit') :Does(ACL) :ACLDetachTo('/denied_pag desc => $c->loc('Failed to update subscriber profile.'), ); } - NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for('/subscriberprofile')); + NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for_action('/subscriberprofile/profile_root', [$c->stash->{cat}->id])); } $c->stash(form => $form); $c->stash(edit_flag => 1); } -sub delete :Chained('base') :PathPart('delete') :Does(ACL) :ACLDetachTo('/denied_page') :AllowedRole(admin) :AllowedRole(reseller) { +sub profile_delete :Chained('profile_base') :PathPart('delete') :Does(ACL) :ACLDetachTo('/denied_page') :AllowedRole(admin) :AllowedRole(reseller) { my ($self, $c) = @_; try { - $c->stash->{profile_result}->delete; + my $schema = $c->model('DB'); + $schema->txn_do(sub{ + $schema->resultset('provisioning_voip_subscribers')->search({ + profile_id => $c->stash->{profile}->id, + })->update({ + # TODO: set this to another profile, or reject deletion if profile is in use + profile_id => undef, + }); + $c->stash->{profile}->delete; + }); $c->flash(messages => [{type => 'success', text => $c->loc('Subscriber profile successfully deleted')}]); } catch($e) { NGCP::Panel::Utils::Message->error( @@ -242,16 +463,16 @@ sub delete :Chained('base') :PathPart('delete') :Does(ACL) :ACLDetachTo('/denied desc => $c->loc('Failed to delete subscriber profile.'), ); } - NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for('/subscriberprofile')); + NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for_action('/subscriberprofile/profile_root', [$c->stash->{cat}->id])); } -sub clone :Chained('base') :PathPart('clone') :Does(ACL) :ACLDetachTo('/denied_page') :AllowedRole(admin) :AllowedRole(reseller) { +sub profile_clone :Chained('profile_base') :PathPart('clone') :Does(ACL) :ACLDetachTo('/denied_page') :AllowedRole(admin) :AllowedRole(reseller) { my ($self, $c) = @_; my $posted = ($c->request->method eq 'POST'); - my $params = { $c->stash->{profile_result}->get_inflated_columns }; + my $params = { $c->stash->{profile}->get_inflated_columns }; $params = $params->merge($c->session->{created_objects}); - my $form = NGCP::Panel::Form::SubscriberProfile::Clone->new; + my $form = NGCP::Panel::Form::SubscriberProfile::ProfileClone->new; $form->process( posted => $posted, params => $c->request->params, @@ -267,13 +488,13 @@ sub clone :Chained('base') :PathPart('clone') :Does(ACL) :ACLDetachTo('/denied_p try { my $schema = $c->model('DB'); $schema->txn_do(sub { - my $new_profile = $c->stash->{profiles_rs}->create({ + my $new_profile = $c->stash->{cat}->voip_subscriber_profiles->create({ %{ $form->values }, - reseller_id => $c->stash->{profile_result}->reseller_id, + catalog_id => $c->stash->{cat}->id, }); - my @old_attributes = $c->stash->{profile_result}->profile_attributes->all; - for my $attr (@old_attributes) { + my @old_attributes = $c->stash->{profile}->profile_attributes->all; + foreach my $attr (@old_attributes) { $new_profile->profile_attributes->create({ attribute_id => $attr->attribute_id, }); @@ -288,7 +509,7 @@ sub clone :Chained('base') :PathPart('clone') :Does(ACL) :ACLDetachTo('/denied_p desc => $c->loc('Failed to clone subscriber profile.'), ); } - NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for('/subscriberprofile')); + NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for_action('/subscriberprofile/profile_root', [$c->stash->{cat}->id])); } $c->stash(form => $form); diff --git a/lib/NGCP/Panel/Field/SubscriberProfileCatalog.pm b/lib/NGCP/Panel/Field/SubscriberProfileCatalog.pm new file mode 100644 index 0000000000..62e89ed336 --- /dev/null +++ b/lib/NGCP/Panel/Field/SubscriberProfileCatalog.pm @@ -0,0 +1,24 @@ +package NGCP::Panel::Field::SubscriberProfileCatalog; +use HTML::FormHandler::Moose; +extends 'HTML::FormHandler::Field::Compound'; + +has_field 'id' => ( + type => '+NGCP::Panel::Field::DataTable', + label => 'Subscriber Profile Catalog', + do_label => 0, + do_wrapper => 0, + required => 1, + template => 'helpers/datatables_field.tt', + ajax_src => '/subscriberprofile/ajax', + table_titles => ['#', 'Reseller', 'Name', 'Description'], + table_fields => ['id', 'reseller_name', 'name', 'description'], +); + +has_field 'create' => ( + type => 'Button', + do_label => 0, + value => 'Create Profile Catalog', + element_class => [qw/btn btn-tertiary pull-right/], +); + +1; diff --git a/lib/NGCP/Panel/Form/SubscriberProfile/ApiProfile.pm b/lib/NGCP/Panel/Form/SubscriberProfile/ApiProfile.pm new file mode 100644 index 0000000000..e8af4b2cfb --- /dev/null +++ b/lib/NGCP/Panel/Form/SubscriberProfile/ApiProfile.pm @@ -0,0 +1,24 @@ +package NGCP::Panel::Form::SubscriberProfile::ApiProfile; + +use HTML::FormHandler::Moose; +extends 'NGCP::Panel::Form::SubscriberProfile::ProfileReseller'; +use Moose::Util::TypeConstraints; + +has_field 'catalog' => ( + type => '+NGCP::Panel::Field::SubscriberProfileCatalog', + validate_when_empty => 1, + element_attr => { + rel => ['tooltip'], + title => ['The subscriber profile catalog this profile belongs to.'], + }, +); + +has_block 'fields' => ( + tag => 'div', + class => [qw/modal-body/], + render_list => [qw/catalog name description/], +); + +1; + +# vim: set tabstop=4 expandtab: diff --git a/lib/NGCP/Panel/Form/SubscriberProfile/Admin.pm b/lib/NGCP/Panel/Form/SubscriberProfile/CatalogAdmin.pm similarity index 65% rename from lib/NGCP/Panel/Form/SubscriberProfile/Admin.pm rename to lib/NGCP/Panel/Form/SubscriberProfile/CatalogAdmin.pm index 52a08d4f5f..d25e9fdb13 100644 --- a/lib/NGCP/Panel/Form/SubscriberProfile/Admin.pm +++ b/lib/NGCP/Panel/Form/SubscriberProfile/CatalogAdmin.pm @@ -1,7 +1,7 @@ -package NGCP::Panel::Form::SubscriberProfile::Admin; +package NGCP::Panel::Form::SubscriberProfile::CatalogAdmin; use HTML::FormHandler::Moose; -extends 'NGCP::Panel::Form::SubscriberProfile::Reseller'; +extends 'NGCP::Panel::Form::SubscriberProfile::CatalogReseller'; use Moose::Util::TypeConstraints; has_field 'reseller' => ( @@ -9,7 +9,7 @@ has_field 'reseller' => ( validate_when_empty => 1, element_attr => { rel => ['tooltip'], - title => ['The reseller this Subscriber Profile belongs to.'], + title => ['The reseller this Subscriber Profile Catalog belongs to.'], }, ); diff --git a/lib/NGCP/Panel/Form/SubscriberProfile/Clone.pm b/lib/NGCP/Panel/Form/SubscriberProfile/CatalogClone.pm similarity index 94% rename from lib/NGCP/Panel/Form/SubscriberProfile/Clone.pm rename to lib/NGCP/Panel/Form/SubscriberProfile/CatalogClone.pm index 34c794e1df..d8069f3967 100644 --- a/lib/NGCP/Panel/Form/SubscriberProfile/Clone.pm +++ b/lib/NGCP/Panel/Form/SubscriberProfile/CatalogClone.pm @@ -1,4 +1,4 @@ -package NGCP::Panel::Form::SubscriberProfile::Clone; +package NGCP::Panel::Form::SubscriberProfile::CatalogClone; use HTML::FormHandler::Moose; extends 'HTML::FormHandler'; diff --git a/lib/NGCP/Panel/Form/SubscriberProfile/CatalogReseller.pm b/lib/NGCP/Panel/Form/SubscriberProfile/CatalogReseller.pm new file mode 100644 index 0000000000..676914b45a --- /dev/null +++ b/lib/NGCP/Panel/Form/SubscriberProfile/CatalogReseller.pm @@ -0,0 +1,53 @@ +package NGCP::Panel::Form::SubscriberProfile::CatalogReseller; + +use HTML::FormHandler::Moose; +extends 'HTML::FormHandler'; +use Moose::Util::TypeConstraints; + +use HTML::FormHandler::Widget::Block::Bootstrap; + +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', + required => 1, + element_attr => { + rel => ['tooltip'], + title => ['The name of the Subscriber Profile Catalog.'], + }, +); + +has_field 'description' => ( + type => 'Text', + required => 0, + element_attr => { + rel => ['tooltip'], + title => ['Arbitrary text.'], + }, +); + +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/reseller name description/], +); + +has_block 'actions' => ( + tag => 'div', + class => [qw/modal-footer/], + render_list => [qw/save/], +); + +1; + +# vim: set tabstop=4 expandtab: diff --git a/lib/NGCP/Panel/Form/SubscriberProfile/Reseller.pm b/lib/NGCP/Panel/Form/SubscriberProfile/Profile.pm similarity index 95% rename from lib/NGCP/Panel/Form/SubscriberProfile/Reseller.pm rename to lib/NGCP/Panel/Form/SubscriberProfile/Profile.pm index 3767aa3892..21ff35181c 100644 --- a/lib/NGCP/Panel/Form/SubscriberProfile/Reseller.pm +++ b/lib/NGCP/Panel/Form/SubscriberProfile/Profile.pm @@ -1,4 +1,4 @@ -package NGCP::Panel::Form::SubscriberProfile::Reseller; +package NGCP::Panel::Form::SubscriberProfile::Profile; use HTML::FormHandler::Moose; extends 'HTML::FormHandler'; @@ -39,7 +39,7 @@ has_field 'save' => ( has_block 'fields' => ( tag => 'div', class => [qw/modal-body/], - render_list => [qw/reseller name description/], + render_list => [qw/name description/], ); has_block 'actions' => ( diff --git a/lib/NGCP/Panel/Form/SubscriberProfile/ProfileAdmin.pm b/lib/NGCP/Panel/Form/SubscriberProfile/ProfileAdmin.pm new file mode 100644 index 0000000000..20128d17cd --- /dev/null +++ b/lib/NGCP/Panel/Form/SubscriberProfile/ProfileAdmin.pm @@ -0,0 +1,24 @@ +package NGCP::Panel::Form::SubscriberProfile::ProfileAdmin; + +use HTML::FormHandler::Moose; +extends 'NGCP::Panel::Form::SubscriberProfile::ProfileReseller'; +use Moose::Util::TypeConstraints; + +has_field 'catalog' => ( + type => '+NGCP::Panel::Field::SubscriberProfileCatalog', + validate_when_empty => 1, + element_attr => { + rel => ['tooltip'], + title => ['The subscriber profile catalog this profile belongs to.'], + }, +); + +has_block 'fields' => ( + tag => 'div', + class => [qw/modal-body/], + render_list => [qw/catalog name description/], +); + +1; + +# vim: set tabstop=4 expandtab: diff --git a/lib/NGCP/Panel/Form/SubscriberProfile/ProfileClone.pm b/lib/NGCP/Panel/Form/SubscriberProfile/ProfileClone.pm new file mode 100644 index 0000000000..381f6ab4bb --- /dev/null +++ b/lib/NGCP/Panel/Form/SubscriberProfile/ProfileClone.pm @@ -0,0 +1,47 @@ +package NGCP::Panel::Form::SubscriberProfile::ProfileClone; + +use HTML::FormHandler::Moose; +extends 'HTML::FormHandler'; +use Moose::Util::TypeConstraints; + +use HTML::FormHandler::Widget::Block::Bootstrap; + +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', + required => 1, + label => 'New Name', +); + +has_field 'description' => ( + type => 'Text', + required => 0, + label => 'New Description', +); + +has_field 'clone' => ( + type => 'Submit', + value => 'Clone', + element_class => [qw/btn btn-primary/], + label => '', +); + +has_block 'fields' => ( + tag => 'div', + class => [qw/modal-body/], + render_list => [qw/name description/], +); + +has_block 'actions' => ( + tag => 'div', + class => [qw/modal-footer/], + render_list => [qw/clone/], +); + +1; + +# vim: set tabstop=4 expandtab: diff --git a/share/templates/subprofile/list.tt b/share/templates/subprofile/cat_list.tt similarity index 57% rename from share/templates/subprofile/list.tt rename to share/templates/subprofile/cat_list.tt index 1ad359d76c..1710123b80 100644 --- a/share/templates/subprofile/list.tt +++ b/share/templates/subprofile/cat_list.tt @@ -1,19 +1,19 @@ -[% site_config.title = c.loc('Subscriber Profiles') -%] +[% site_config.title = c.loc('Subscriber Profile Catalogs') -%] [% - helper.name = c.loc('Subscriber Profile'); - helper.identifier = 'subscriber_profile'; + helper.name = c.loc('Subscriber Profile Catalogs'); + helper.identifier = 'subscriber_profile_catalogs'; helper.messages = messages; - helper.dt_columns = profile_dt_columns; + helper.dt_columns = cat_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( "/subscriberprofile/ajax" ); + helper.ajax_uri = c.uri_for_action( "/subscriberprofile/catalog_ajax" ); IF clone_flag; - helper.name = c.loc('cloned Subscriber Profile'); + helper.name = c.loc('cloned Subscriber Profile Catalog'); END; UNLESS c.user.read_only; @@ -21,9 +21,10 @@ { name = c.loc('Edit'), uri = "/subscriberprofile/'+full.id+'/edit", class = 'btn-small btn-primary', icon = 'icon-edit' }, { name = c.loc('Delete'), uri = "/subscriberprofile/'+full.id+'/delete", class = 'btn-small btn-secondary', icon = 'icon-trash' }, { name = c.loc('Clone'), uri = "/subscriberprofile/'+full.id+'/clone", class = 'btn-small btn-tertiary', icon = 'icon-retweet' }, + { name = c.loc('Profiles'), uri = "/subscriberprofile/'+full.id+'/profile", class = 'btn-small btn-primary', icon = 'icon-list' }, ]; helper.top_buttons = [ - { name = c.loc('Create Subscriber Profile'), uri = c.uri_for('/subscriberprofile/create'), icon = 'icon-star' }, + { name = c.loc('Create Subscriber Profile Catalog'), uri = c.uri_for_action('/subscriberprofile/catalog_create'), icon = 'icon-star' }, ]; END; diff --git a/share/templates/subprofile/profile_list.tt b/share/templates/subprofile/profile_list.tt new file mode 100644 index 0000000000..82f090a93d --- /dev/null +++ b/share/templates/subprofile/profile_list.tt @@ -0,0 +1,37 @@ +[% site_config.title = c.loc('Subscriber Profiles for catalog [_1]', cat.name) -%] +[% + helper.name = c.loc('Subscriber Profile'); + helper.identifier = 'subscriber_profile'; + helper.messages = messages; + helper.dt_columns = profile_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( "/subscriberprofile/profile_ajax", [c.req.captures.0] ); + + IF clone_flag; + helper.name = c.loc('cloned Subscriber Profile'); + END; + + UNLESS c.user.read_only; + helper.dt_buttons = [ + { name = c.loc('Edit'), uri = "/subscriberprofile/" _ cat.id _ "/profile/'+full.id+'/edit", class = 'btn-small btn-primary', icon = 'icon-edit' }, + { name = c.loc('Delete'), uri = "/subscriberprofile/" _ cat.id _ "/profile/'+full.id+'/delete", class = 'btn-small btn-secondary', icon = 'icon-trash' }, + { name = c.loc('Clone'), uri = "/subscriberprofile/" _ cat.id _ "/profile/'+full.id+'/clone", class = 'btn-small btn-tertiary', icon = 'icon-retweet' }, + ]; + helper.top_buttons = [ + { name = c.loc('Profile Catalogs'), uri = c.uri_for('/subscriberprofile'), icon = 'icon-list' }, + { name = c.loc('Create Subscriber Profile'), uri = c.uri_for_action('/subscriberprofile/profile_create', c.req.captures), icon = 'icon-star' }, + ]; + ELSE; + helper.top_buttons = [ + { name = c.loc('Profile Catalogs'), uri = c.uri_for('/subscriberprofile'), icon = 'icon-list' }, + ]; + END; + + PROCESS 'helpers/datatables.tt'; +-%] +[% # vim: set tabstop=4 syntax=html expandtab: -%]