From 320a25024b7c9913b6b3f148f38cfd80afd81a15 Mon Sep 17 00:00:00 2001 From: Andreas Granig Date: Thu, 7 Mar 2013 13:32:47 +0100 Subject: [PATCH] Add Contact form and extract redir chain handling. --- lib/NGCP/Panel/Controller/Contact.pm | 136 +++++++++++++++++++++++++ lib/NGCP/Panel/Controller/Contract.pm | 18 ++-- lib/NGCP/Panel/Controller/Dashboard.pm | 1 + lib/NGCP/Panel/Controller/Reseller.pm | 40 +++----- lib/NGCP/Panel/Form/Contact.pm | 51 ++++++++++ lib/NGCP/Panel/Form/Contract.pm | 6 +- lib/NGCP/Panel/Form/Reseller.pm | 8 +- lib/NGCP/Panel/Utils.pm | 54 ++++++++++ share/templates/contact/list.tt | 16 +++ 9 files changed, 289 insertions(+), 41 deletions(-) create mode 100644 lib/NGCP/Panel/Controller/Contact.pm create mode 100644 lib/NGCP/Panel/Form/Contact.pm create mode 100644 lib/NGCP/Panel/Utils.pm create mode 100644 share/templates/contact/list.tt diff --git a/lib/NGCP/Panel/Controller/Contact.pm b/lib/NGCP/Panel/Controller/Contact.pm new file mode 100644 index 0000000000..6b9ff53139 --- /dev/null +++ b/lib/NGCP/Panel/Controller/Contact.pm @@ -0,0 +1,136 @@ +package NGCP::Panel::Controller::Contact; +use Moose; +use namespace::autoclean; +use Data::Dumper; + +BEGIN { extends 'Catalyst::Controller'; } + +use NGCP::Panel::Form::Contact; + +=head1 NAME + +NGCP::Panel::Controller::Contact - Catalyst Controller + +=head1 DESCRIPTION + +Catalyst Controller. + +=head1 METHODS + +=cut + +sub list :Chained('/') :PathPart('contact') :CaptureArgs(0) { + my ($self, $c) = @_; + + my $contacts = [ + {id => 1, firstname => 'Foo1', lastname => '1Bar', email => 'foo1@example.org' }, + {id => 1, firstname => 'Foo2', lastname => '2Bar', email => 'foo2@example.org' }, + {id => 1, firstname => 'Foo3', lastname => '3Bar', email => 'foo3@example.org' }, + {id => 1, firstname => 'Foo4', lastname => '4Bar', email => 'foo4@example.org' }, + ]; + $c->stash(contacts => $contacts); + $c->stash(template => 'contact/list.tt'); + + if($c->session->{redirect_targets} && @{ $c->session->{redirect_targets} }) { + my $target = ${ $c->session->{redirect_targets} }[0]; + if('/'.$c->request->path eq $target->path) { + shift @{$c->session->{redirect_targets}}; + } else { + $c->stash(close_target => $target); + } + } +} + +sub root :Chained('list') :PathPart('') :Args(0) { + my ($self, $c) = @_; +} + +sub create :Chained('list') :PathPart('create') :Args(0) { + my ($self, $c) = @_; + + my $form = NGCP::Panel::Form::Contact->new; + $form->process( + posted => ($c->request->method eq 'POST'), + params => $c->request->params, + action => $c->uri_for('create'), + ); + if($form->validated) { + if($c->stash->{close_target}) { + # TODO: set created contact in flash to be selected at target + $c->response->redirect($c->stash->{close_target}); + return; + } + $c->flash(messages => [{type => 'success', text => 'Contact successfully created!'}]); + $c->response->redirect($c->stash->{close_target}); + return; + } + + $c->stash(create_flag => 1); + $c->stash(form => $form); +} + +sub search :Chained('list') :PathPart('search') Args(0) { + my ($self, $c) = @_; + + $c->flash(messages => [{type => 'info', text => 'Contact search not implemented!'}]); + $c->response->redirect($c->uri_for()); +} + +sub base :Chained('/contact/list') :PathPart('') :CaptureArgs(1) { + my ($self, $c, $contact_id) = @_; + + unless($contact_id && $contact_id =~ /^\d+$/) { + $c->flash(messages => [{type => 'error', text => 'Invalid contact id detected!'}]); + $c->response->redirect($c->uri_for()); + return; + } + + # TODO: fetch details of contact from model + my @rfilter = grep { $_->{id} == $contact_id } @{ $c->stash->{contacts} }; + $c->stash(contact => shift @rfilter); +} + +sub edit :Chained('base') :PathPart('edit') :Args(0) { + my ($self, $c) = @_; + + my $posted = ($c->request->method eq 'POST'); + my $form = NGCP::Panel::Form::Contact->new; + $form->process( + posted => 1, + params => $posted ? $c->request->params : $c->stash->{contact}, + action => $c->uri_for($c->stash->{contact}->{id}, 'edit'), + ); + if($posted && $form->validated) { + $c->flash(messages => [{type => 'success', text => 'Contact successfully changed!'}]); + $c->response->redirect($c->uri_for()); + return; + } + + $c->stash(form => $form); +} + +sub delete :Chained('base') :PathPart('delete') :Args(0) { + my ($self, $c) = @_; + + # $c->model('Provisioning')->contact($c->stash->{contact}->{id})->delete; + $c->flash(messages => [{type => 'info', text => 'Contact delete not implemented!'}]); + $c->response->redirect($c->uri_for()); +} + + +=head1 AUTHOR + +Andreas Granig,,, + +=head1 LICENSE + +This library is free software. You can redistribute it and/or modify +it under the same terms as Perl itself. + +=cut + +__PACKAGE__->meta->make_immutable; + +1; + +# vim: set tabstop=4 expandtab: diff --git a/lib/NGCP/Panel/Controller/Contract.pm b/lib/NGCP/Panel/Controller/Contract.pm index 7c9ae9c71f..ed5355c2cb 100644 --- a/lib/NGCP/Panel/Controller/Contract.pm +++ b/lib/NGCP/Panel/Controller/Contract.pm @@ -6,6 +6,7 @@ use Data::Dumper; BEGIN { extends 'Catalyst::Controller'; } use NGCP::Panel::Form::Contract; +use NGCP::Panel::Utils; =head1 NAME @@ -33,14 +34,7 @@ sub list :Chained('/') :PathPart('contract') :CaptureArgs(0) { $c->stash(contracts => $contracts); $c->stash(template => 'contract/list.tt'); - if($c->session->{redirect_targets} && @{ $c->session->{redirect_targets} }) { - my $target = ${ $c->session->{redirect_targets} }[0]; - if('/'.$c->request->path eq $target->path) { - shift @{$c->session->{redirect_targets}}; - } else { - $c->stash(close_target => $target); - } - } + NGCP::Panel::Utils::check_redirect_chain(c => $c); } sub root :Chained('list') :PathPart('') :Args(0) { @@ -56,6 +50,10 @@ sub create :Chained('list') :PathPart('create') :Args(0) { params => $c->request->params, action => $c->uri_for('create'), ); + return if NGCP::Panel::Utils::check_form_buttons( + c => $c, form => $form, fields => [qw/contact.create/], + back_uri => $c->uri_for('create') + ); if($form->validated) { if($c->stash->{close_target}) { # TODO: set created contract in flash to be selected at target @@ -102,6 +100,10 @@ sub edit :Chained('base') :PathPart('edit') :Args(0) { params => $posted ? $c->request->params : $c->stash->{contract}, action => $c->uri_for($c->stash->{contract}->{id}, 'edit'), ); + return if NGCP::Panel::Utils::check_form_buttons( + c => $c, form => $form, fields => [qw/contact.create/], + back_uri => $c->uri_for($c->stash->{contract}->{id}, 'edit') + ); if($posted && $form->validated) { $c->flash(messages => [{type => 'success', text => 'Contract successfully changed!'}]); $c->response->redirect($c->uri_for()); diff --git a/lib/NGCP/Panel/Controller/Dashboard.pm b/lib/NGCP/Panel/Controller/Dashboard.pm index 01b060740d..06f43f89c7 100644 --- a/lib/NGCP/Panel/Controller/Dashboard.pm +++ b/lib/NGCP/Panel/Controller/Dashboard.pm @@ -37,6 +37,7 @@ sub index :Path :Args(0) { $c->stash(widgets => $widget_templates); $c->stash(template => 'dashboard.tt'); + delete $c->session->{redirect_targets}; } =head1 AUTHOR diff --git a/lib/NGCP/Panel/Controller/Reseller.pm b/lib/NGCP/Panel/Controller/Reseller.pm index 150b47afce..a6211876bf 100644 --- a/lib/NGCP/Panel/Controller/Reseller.pm +++ b/lib/NGCP/Panel/Controller/Reseller.pm @@ -6,6 +6,7 @@ use Data::Dumper; BEGIN { extends 'Catalyst::Controller'; } use NGCP::Panel::Form::Reseller; +use NGCP::Panel::Utils; =head1 NAME @@ -33,9 +34,7 @@ sub list :Chained('/') :PathPart('reseller') :CaptureArgs(0) { $c->stash(resellers => $resellers); $c->stash(template => 'reseller/list.tt'); - # this is the root of a target chain for creating resellers->contracts->contacts, - # so clear chain here. - delete $c->session->{redirect_targets}; + NGCP::Panel::Utils::check_redirect_chain(c => $c); } sub root :Chained('list') :PathPart('') :Args(0) { @@ -55,19 +54,13 @@ sub create :Chained('list') :PathPart('create') :Args(0) { params => $c->request->params, action => $c->uri_for('create'), ); - if($posted && $form->field('submitid') && - $form->field('submitid')->value eq 'contract.create') { - if($c->session->{redirect_targets}) { - push @{ $c->session->{redirect_targets} }, $c->uri_for('create'); - } else { - $c->session->{redirect_targets} = [ $c->uri_for('create') ]; - } - # TODO: preserve the current "reseller" object for continuing editing - # when coming back from /contract/create - $c->response->redirect($c->uri_for('/contract/create')); - return; - } - + return if NGCP::Panel::Utils::check_form_buttons( + c => $c, form => $form, fields => [qw/contract.create/], + back_uri => $c->uri_for('create') + ); + # TODO: preserve the current "reseller" object for continuing editing + # when coming back from /contract/create + if($form->validated) { $c->flash(messages => [{type => 'success', text => 'Reseller successfully created!'}]); $c->response->redirect($c->uri_for()); @@ -112,16 +105,11 @@ sub edit :Chained('base') :PathPart('edit') :Args(0) { params => $posted ? $c->request->params : $c->stash->{reseller}, action => $c->uri_for($c->stash->{reseller}->{id}, 'edit'), ); - if($posted && $form->field('submitid') && - $form->field('submitid')->value eq 'contract.create') { - if($c->session->{redirect_targets}) { - push @{ $c->session->{redirect_targets} }, $c->uri_for($c->stash->{reseller}->{id}, 'edit'); - } else { - $c->session->{redirect_targets} = [ $c->uri_for($c->stash->{reseller}->{id}, 'edit') ]; - } - $c->response->redirect($c->uri_for('/contract/create')); - return; - } + return if NGCP::Panel::Utils::check_form_buttons( + c => $c, form => $form, fields => [qw/contract.create/], + back_uri => $c->uri_for($c->stash->{reseller}->{id}, 'edit') + ); + if($posted && $form->validated) { $c->flash(messages => [{type => 'success', text => 'Reseller successfully changed!'}]); $c->response->redirect($c->uri_for()); diff --git a/lib/NGCP/Panel/Form/Contact.pm b/lib/NGCP/Panel/Form/Contact.pm new file mode 100644 index 0000000000..0bf2182c83 --- /dev/null +++ b/lib/NGCP/Panel/Form/Contact.pm @@ -0,0 +1,51 @@ +package NGCP::Panel::Form::Contact; + +use HTML::FormHandler::Moose; +extends 'HTML::FormHandler'; +use Moose::Util::TypeConstraints; + +use HTML::FormHandler::Widget::Block::Bootstrap; + +has '+widget_wrapper' => ( default => 'Bootstrap' ); +sub build_render_list {[qw/fields actions/]} +sub build_form_element_class { [qw/form-horizontal/] } + +has_field 'firstname' => ( + type => 'Text', + label => 'First Name', + required => 1, +); + +has_field 'lastname' => ( + type => 'Text', + label => 'Last Name', + required => 1, +); + + +has_field 'email' => ( + type => 'Email', + required => 1, +); + +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/firstname lastname email/], +); + +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/Contract.pm b/lib/NGCP/Panel/Form/Contract.pm index b8332ed15b..eeadbf74c6 100644 --- a/lib/NGCP/Panel/Form/Contract.pm +++ b/lib/NGCP/Panel/Form/Contract.pm @@ -7,9 +7,13 @@ use Moose::Util::TypeConstraints; use HTML::FormHandler::Widget::Block::Bootstrap; has '+widget_wrapper' => ( default => 'Bootstrap' ); -sub build_render_list {[qw/fields actions/]} +sub build_render_list {[qw/submitid fields actions/]} sub build_form_element_class { [qw/form-horizontal/] } +has_field 'submitid' => ( + type => 'Hidden' +); + has_field 'contact' => ( type => '+NGCP::Panel::Field::Contact', label => 'Contact', diff --git a/lib/NGCP/Panel/Form/Reseller.pm b/lib/NGCP/Panel/Form/Reseller.pm index fed01e521b..840075c708 100644 --- a/lib/NGCP/Panel/Form/Reseller.pm +++ b/lib/NGCP/Panel/Form/Reseller.pm @@ -7,13 +7,9 @@ use Moose::Util::TypeConstraints; use HTML::FormHandler::Widget::Block::Bootstrap; has '+widget_wrapper' => ( default => 'Bootstrap' ); -sub build_render_list {[qw/fields actions/]} +sub build_render_list {[qw/submitid fields actions/]} sub build_form_element_class { [qw/form-horizontal/] } -has_field 'id' => ( - type => 'Hidden' -); - has_field 'submitid' => ( type => 'Hidden' ); @@ -45,7 +41,7 @@ has_field 'save' => ( has_block 'fields' => ( tag => 'div', class => [qw/modal-body/], - render_list => [qw/submitid contract name status/], + render_list => [qw/contract name status/], ); has_block 'actions' => ( diff --git a/lib/NGCP/Panel/Utils.pm b/lib/NGCP/Panel/Utils.pm new file mode 100644 index 0000000000..46c9b51ab8 --- /dev/null +++ b/lib/NGCP/Panel/Utils.pm @@ -0,0 +1,54 @@ +package NGCP::Panel::Utils; +use strict; +use warnings; + +use Data::Dumper; + +sub check_redirect_chain { + my %params = @_; + + # TODO: check for missing fields + my $c = $params{c}; + + if($c->session->{redirect_targets} && @{ $c->session->{redirect_targets} }) { + my $target = ${ $c->session->{redirect_targets} }[0]; + if('/'.$c->request->path eq $target->path) { + shift @{$c->session->{redirect_targets}}; + $c->stash(close_target => ${ $c->session->{redirect_targets} }[0]); + } else { + $c->stash(close_target => $target); + } + } +} + +sub check_form_buttons { + my %params = @_; + + # TODO: check for missing fields + my $c = $params{c}; + my $fields = $params{fields}; + my $form = $params{form}; + my $back_uri = $params{back_uri}; + + my $posted = ($c->request->method eq 'POST'); + + if($posted && $form->field('submitid')) { + my $val = $form->field('submitid')->value; + + if(grep {/^$val$/} @{ $fields }) { + my $target = '/'.$val; + $target =~ s/\./\//g; + if($c->session->{redirect_targets}) { + unshift @{ $c->session->{redirect_targets} }, $back_uri; + } else { + $c->session->{redirect_targets} = [ $back_uri ]; + } + $c->response->redirect($c->uri_for($target)); + return 1; + } + } + return; +} + +1; +# vim: set tabstop=4 expandtab: diff --git a/share/templates/contact/list.tt b/share/templates/contact/list.tt new file mode 100644 index 0000000000..4e261aa819 --- /dev/null +++ b/share/templates/contact/list.tt @@ -0,0 +1,16 @@ +[% META title = 'Contacts' -%] +[% + helper.name = 'Contact'; + helper.data = contacts; + helper.messages = messages; + helper.column_titles = [ '#', 'First Name', 'Last Name', 'Email' ]; + helper.column_fields = [ 'id', 'firstname', 'lastname', 'email' ]; + + helper.close_target = close_target; + helper.create_flag = create_flag; + helper.edit_object = contact; + helper.form_object = form; + + PROCESS 'helpers/table_form.tt'; +-%] +[% # vim: set tabstop=4 syntax=html expandtab: -%]