aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Reaction/UI
diff options
context:
space:
mode:
authormatthewt <matthewt@03d0b0b2-0e1a-0410-a411-fdb2f4bd65d7>2007-12-17 17:15:03 +0000
committermatthewt <matthewt@03d0b0b2-0e1a-0410-a411-fdb2f4bd65d7>2007-12-17 17:15:03 +0000
commit8d80af1678b87d06a3109bfe6db3cb65b6b10dbf (patch)
tree694847a311ba087240326f4731f5116904df22fa /lib/Reaction/UI
parent5db4d87c00bf1bd7099d7609d4595634d81d9f30 (diff)
parent13c66bc28d070b919cce4af600e884ab7285b056 (diff)
downloadreaction-8d80af1678b87d06a3109bfe6db3cb65b6b10dbf.tar.gz
reaction-8d80af1678b87d06a3109bfe6db3cb65b6b10dbf.zip
r62511@cain (orig r406): groditi | 2007-11-14 20:04:23 +0000
merging in the lats of my two branches and killing them off r62639@cain (orig r411): groditi | 2007-11-16 16:31:34 +0000 changes to CRUDController to make adding new CRUDish actions easier. makes sense since the controller is so specific anyways r62640@cain (orig r412): groditi | 2007-11-16 18:09:38 +0000 oops, missing comma r62641@cain (orig r413): groditi | 2007-11-16 21:20:55 +0000 fixed Bar Controller, tons of bugs everywhere, restructured controller namespace r72711@cain (orig r418): groditi | 2007-12-16 02:02:36 +0000 empty IM example
Diffstat (limited to 'lib/Reaction/UI')
-rw-r--r--lib/Reaction/UI/CRUDController.pm169
-rw-r--r--lib/Reaction/UI/Controller/Collection.pm69
-rw-r--r--lib/Reaction/UI/Controller/Collection/CRUD.pm111
-rw-r--r--lib/Reaction/UI/Controller/Root.pm (renamed from lib/Reaction/UI/RootController.pm)6
-rw-r--r--lib/Reaction/UI/ViewPort.pm2
-rw-r--r--lib/Reaction/UI/ViewPort/GridView/Entity.pm11
-rw-r--r--lib/Reaction/UI/Widget/Field/ChooseOne.pm2
7 files changed, 196 insertions, 174 deletions
diff --git a/lib/Reaction/UI/CRUDController.pm b/lib/Reaction/UI/CRUDController.pm
deleted file mode 100644
index 554d588..0000000
--- a/lib/Reaction/UI/CRUDController.pm
+++ /dev/null
@@ -1,169 +0,0 @@
-package Reaction::UI::CRUDController;
-
-use strict;
-use warnings;
-use base 'Reaction::UI::Controller';
-use Reaction::Class;
-
-use aliased 'Reaction::UI::ViewPort::ListView';
-use aliased 'Reaction::UI::ViewPort::ActionForm';
-use aliased 'Reaction::UI::ViewPort::ObjectView';
-
-has 'model_name' => (isa => 'Str', is => 'rw', required => 1);
-has 'collection_name' => (isa => 'Str', is => 'rw', required => 1);
-
-has action_viewport_map => (isa => 'HashRef', is => 'rw', lazy_build => 1);
-has action_viewport_args => (isa => 'HashRef', is => 'rw', lazy_build => 1);
-
-sub _build_action_viewport_map {
- return {
- list => ListView,
- view => ObjectView,
- create => ActionForm,
- update => ActionForm,
- delete => ActionForm,
- delete_all => ActionForm,
- };
-}
-
-sub _build_action_viewport_args {
- my $self = shift;
- return { list =>
- { action_prototypes =>
- [ { label => 'Create', action => sub {
- [ '', 'create', $_[1]->req->captures ] } },
- { label => 'Delete all', action => sub {
- [ '', 'delete_all', $_[1]->req->captures ] } },
- ],
- Entity =>
- { action_prototypes =>
- [ { label => 'View', action => sub {
- [ '', 'view', [ @{$_[1]->req->captures}, $_[0]->__id ] ] } },
- { label => 'Edit', action => sub {
- [ '', 'update', [ @{$_[1]->req->captures}, $_[0]->__id ] ] } },
- { label => 'Delete', action => sub {
- [ '', 'delete', [ @{$_[1]->req->captures}, $_[0]->__id ] ] } },
- ],
- },
- },
- };
-}
-
-sub base :Action :CaptureArgs(0) {
- my ($self, $c) = @_;
-}
-
-#XXX candidate for futre optimization
-sub get_collection {
- my ($self, $c) = @_;
- my $model = $c->model( $self->model_name );
- my $attr = $model->meta->find_attribute_by_name( $self->collection_name );
- my $reader = $attr->get_read_method;
- return $model->$reader;
-}
-
-sub get_model_action {
- my ($self, $c, $name, $target) = @_;
-
- if ($target->can('action_for')) {
- return $target->action_for($name, ctx => $c);
- }
-
- #can we please kill this already?
- my $model_name = "Action::${name}".$self->model_name;
- my $model = $c->model($model_name);
- confess "no such Model $model_name" unless $model;
- return $model->new(target_model => $target, ctx => $c);
-}
-
-sub list :Chained('base') :PathPart('') :Args(0) {
- my ($self, $c) = @_;
-
- $self->push_viewport(
- $self->action_viewport_map->{list},
- %{ $self->action_viewport_args->{list} || {} },
- collection => $self->get_collection($c)
- );
-}
-
-sub create :Chained('base') :PathPart('create') :Args(0) {
- my ($self, $c) = @_;
- my $action = $self->get_model_action($c, 'Create', $self->get_collection($c));
- $self->push_viewport
- (
- $self->action_viewport_map->{create},
- %{ $self->action_viewport_args->{create} || {} },
- action => $action,
- next_action => 'list',
- on_apply_callback => sub { $self->after_create_callback($c => @_); },
- );
-}
-
-sub delete_all :Chained('base') :PathPart('delete_all') :Args(0) {
- my ($self, $c) = @_;
- my $action = $self->get_model_action($c, 'DeleteAll', $self->get_collection($c));
- $self->push_viewport
- (
- $self->action_viewport_map->{delete_all},
- %{ $self->action_viewport_args->{delete_all} || {} },
- action => $action,
- next_action => 'list',
- );
-}
-
-sub after_create_callback {
- my ($self, $c, $vp, $result) = @_;
- return $self->redirect_to
- ( $c, 'update', [ @{$c->req->captures}, $result->id ] );
-}
-
-sub object :Chained('base') :PathPart('id') :CaptureArgs(1) {
- my ($self, $c, $key) = @_;
- my $object :Stashed = $self->get_collection($c)->find($key);
- confess "Object? what object?" unless $object; # should be a 404.
-}
-
-sub update :Chained('object') :Args(0) {
- my ($self, $c) = @_;
- my $object :Stashed;
- my $action = $self->get_model_action($c, 'Update', $object);
- my @cap = @{$c->req->captures};
- pop(@cap); # object id
- $self->push_viewport
- (
- $self->action_viewport_map->{update},
- %{ $self->action_viewport_args->{update} || {} },
- action => $action,
- next_action => [ $self, 'redirect_to', 'list', \@cap ]
- );
-}
-
-sub delete :Chained('object') :Args(0) {
- my ($self, $c) = @_;
- my $object :Stashed;
- my $action = $self->get_model_action($c, 'Delete', $object);
- my @cap = @{$c->req->captures};
- pop(@cap); # object id
- $self->push_viewport
- (
- $self->action_viewport_map->{delete},
- %{ $self->action_viewport_args->{delete} || {} },
- action => $action,
- next_action => [ $self, 'redirect_to', 'list', \@cap ]
- );
-}
-
-sub view :Chained('object') :Args(0) {
- my ($self, $c) = @_;
- my $object :Stashed;
- my @cap = @{$c->req->captures};
- pop(@cap); # object id
- $self->push_viewport
- (
- $self->action_viewport_map->{view},
- %{ $self->action_viewport_args->{view} || {} },
- object => $object,
- );
-}
-
-1;
diff --git a/lib/Reaction/UI/Controller/Collection.pm b/lib/Reaction/UI/Controller/Collection.pm
new file mode 100644
index 0000000..d7d727b
--- /dev/null
+++ b/lib/Reaction/UI/Controller/Collection.pm
@@ -0,0 +1,69 @@
+package Reaction::UI::Controller::Collection;
+
+use strict;
+use warnings;
+use base 'Reaction::UI::Controller';
+use Reaction::Class;
+
+use aliased 'Reaction::UI::ViewPort::ListView';
+use aliased 'Reaction::UI::ViewPort::ObjectView';
+
+has 'model_name' => (isa => 'Str', is => 'rw', required => 1);
+has 'collection_name' => (isa => 'Str', is => 'rw', required => 1);
+
+has action_viewport_map => (isa => 'HashRef', is => 'rw', lazy_build => 1);
+has action_viewport_args => (isa => 'HashRef', is => 'rw', lazy_build => 1);
+
+sub _build_action_viewport_map {
+ return {
+ list => ListView,
+ view => ObjectView,
+ };
+}
+
+sub _build_action_viewport_args {
+ return { };
+}
+
+sub base :Action :CaptureArgs(0) {
+ my ($self, $c) = @_;
+}
+
+#XXX candidate for futre optimization, should cache reader?
+sub get_collection {
+ my ($self, $c) = @_;
+ my $model = $c->model( $self->model_name );
+ my $attr = $model->meta->find_attribute_by_name( $self->collection_name );
+ my $reader = $attr->get_read_method;
+ return $model->$reader;
+}
+
+sub list :Chained('base') :PathPart('') :Args(0) {
+ my ($self, $c) = @_;
+ $c->forward(basic_page => [{ collection => $self->get_collection($c) }]);
+}
+
+sub object :Chained('base') :PathPart('id') :CaptureArgs(1) {
+ my ($self, $c, $key) = @_;
+ my $object :Stashed = $self->get_collection($c)->find($key);
+ confess "Object? what object?" unless $object; # should be a 404.
+}
+
+sub view :Chained('object') :Args(0) {
+ my ($self, $c) = @_;
+ my $object :Stashed;
+ $c->forward(basic_page => [{object => $object}]);
+}
+
+sub basic_page : Private {
+ my ($self, $c, $vp_args) = @_;
+ my $action_name = $c->stack->[-2]->name;
+ return $self->push_viewport
+ (
+ $self->action_viewport_map->{$action_name},
+ %{ $vp_args || {} },
+ %{ $self->action_viewport_args->{$action_name} || {} },
+ );
+}
+
+1;
diff --git a/lib/Reaction/UI/Controller/Collection/CRUD.pm b/lib/Reaction/UI/Controller/Collection/CRUD.pm
new file mode 100644
index 0000000..8a2dcd0
--- /dev/null
+++ b/lib/Reaction/UI/Controller/Collection/CRUD.pm
@@ -0,0 +1,111 @@
+package Reaction::UI::Controller::Collection::CRUD;
+
+use strict;
+use warnings;
+use base 'Reaction::UI::Controller::Collection';
+use Reaction::Class;
+
+use aliased 'Reaction::UI::ViewPort::ActionForm';
+
+sub _build_action_viewport_map {
+ my $map = shift->next::method(@_);
+ map{ $map->{$_} = ActionForm } qw/create update delete delete_all/;
+ return $map;
+}
+
+sub _build_action_viewport_args {
+ my $args = shift->next::method(@_);
+ $args->{list} =
+ { action_prototypes =>
+ [ { label => 'Create', action => sub {
+ [ '', 'create', $_[1]->req->captures ] } },
+ { label => 'Delete all', action => sub {
+ [ '', 'delete_all', $_[1]->req->captures ] } },
+ ],
+ Entity =>
+ { action_prototypes =>
+ [ { label => 'View', action => sub {
+ [ '', 'view', [ @{$_[1]->req->captures}, $_[0]->__id ] ] } },
+ { label => 'Edit', action => sub {
+ [ '', 'update', [ @{$_[1]->req->captures}, $_[0]->__id ] ] } },
+ { label => 'Delete', action => sub {
+ [ '', 'delete', [ @{$_[1]->req->captures}, $_[0]->__id ] ] } },
+ ],
+ },
+ };
+ return $args;
+}
+
+sub get_model_action {
+ my ($self, $c, $name, $target) = @_;
+
+ if ($target->can('action_for')) {
+ return $target->action_for($name, ctx => $c);
+ }
+
+ #can we please kill this already?
+ my $model_name = "Action::${name}".$self->model_name;
+ my $model = $c->model($model_name);
+ confess "no such Model $model_name" unless $model;
+ return $model->new(target_model => $target, ctx => $c);
+}
+
+sub create :Chained('base') :PathPart('create') :Args(0) {
+ my ($self, $c) = @_;
+ my $vp_args = {
+ next_action => 'list',
+ on_apply_callback => sub { $self->after_create_callback($c => @_); },
+ };
+ $c->forward( basic_model_action => [$vp_args]);
+}
+
+sub delete_all :Chained('base') :PathPart('delete_all') :Args(0) {
+ my ($self, $c) = @_;
+ $c->forward(basic_model_action => [{ next_action => 'list'}]);
+}
+
+sub after_create_callback {
+ my ($self, $c, $vp, $result) = @_;
+ return $self->redirect_to
+ ( $c, 'update', [ @{$c->req->captures}, $result->id ] );
+}
+
+sub update :Chained('object') :Args(0) {
+ my ($self, $c) = @_;
+ #this needs a better solution. currently thinking about it
+ my @cap = @{$c->req->captures};
+ pop(@cap); # object id
+ my $vp_args = { next_action => [ $self, 'redirect_to', 'list', \@cap ]};
+ $c->forward(basic_model_action => [$vp_args]);
+}
+
+sub delete :Chained('object') :Args(0) {
+ my ($self, $c) = @_;
+ #this needs a better solution. currently thinking about it
+ my @cap = @{$c->req->captures};
+ pop(@cap); # object id
+ my $vp_args = { next_action => [ $self, 'redirect_to', 'list', \@cap ]};
+ $c->forward(basic_model_action => [$vp_args]);
+}
+
+sub basic_model_action :Private {
+ my ($self, $c, $vp_args) = @_;
+
+ my $target = exists $c->stash->{object} ?
+ $c->stash->{object} : $self->get_collection($c);
+
+ my $cat_action_name = $c->stack->[-2]->name;
+ my $im_action_name = join('', (map{ ucfirst } split('_', $cat_action_name)));
+ $c->log->debug($cat_action_name);
+ $c->log->debug($self->action_viewport_map->{$cat_action_name});
+ $c->log->debug(keys %{$self->action_viewport_map});
+ return $self->push_viewport
+ (
+ $self->action_viewport_map->{$cat_action_name},
+ action => $self->get_model_action($c, $im_action_name, $target),
+ %{ $vp_args || {} },
+ %{ $self->action_viewport_args->{$cat_action_name} || {} },
+ );
+}
+
+1;
diff --git a/lib/Reaction/UI/RootController.pm b/lib/Reaction/UI/Controller/Root.pm
index 89f1a0f..2760ec8 100644
--- a/lib/Reaction/UI/RootController.pm
+++ b/lib/Reaction/UI/Controller/Root.pm
@@ -1,4 +1,4 @@
-package Reaction::UI::RootController;
+package Reaction::UI::Controller::Root;
use base qw/Reaction::UI::Controller/;
use Reaction::Class;
@@ -33,12 +33,12 @@ sub end :Private {
=head1 NAME
-Reaction::UI::RootController - Base component for the Root Controller
+Reaction::UI::Root - Base component for the Root Controller
=head1 SYNOPSIS
package MyApp::Controller::Root;
- use base 'Reaction::UI::RootController';
+ use base 'Reaction::UI::COntroller::Root';
# Create UI elements:
$c->stash->{focus_stack}->push_viewport('Reaction::UI::ViewPort');
diff --git a/lib/Reaction/UI/ViewPort.pm b/lib/Reaction/UI/ViewPort.pm
index 98a210e..8cc6917 100644
--- a/lib/Reaction/UI/ViewPort.pm
+++ b/lib/Reaction/UI/ViewPort.pm
@@ -83,7 +83,7 @@ class ViewPort which {
my ($self, $events) = @_;
foreach my $event ($self->accept_events) {
if (exists $events->{$event}) {
- # $self->ctx->log->debug("Applying Event: $event with value: ". $events->{$event});
+ # $self->ctx->log->debug("Applying Event: $event with value: ". $events->{$event});
$self->$event($events->{$event});
}
}
diff --git a/lib/Reaction/UI/ViewPort/GridView/Entity.pm b/lib/Reaction/UI/ViewPort/GridView/Entity.pm
index 3011f7f..98a55f5 100644
--- a/lib/Reaction/UI/ViewPort/GridView/Entity.pm
+++ b/lib/Reaction/UI/ViewPort/GridView/Entity.pm
@@ -173,6 +173,17 @@ class Entity is 'Reaction::UI::ViewPort', which {
);
return $self->_build_simple_field(String, $obj, $attr, $args);
};
+
+ implements _build_fields_for_type_Reaction_InterfaceModel_Object => as {
+ my ($self, $obj, $attr, $args) = @_;
+ $args->{Field}{$attr->name}{layout} = 'value/string'
+ unless( exists $args->{Field}{$attr->name} &&
+ exists $args->{Field}{$attr->name}{layout} &&
+ defined $args->{Field}{$attr->name}{layout}
+ );
+ return $self->_build_simple_field(RelatedObject, $obj, $attr, $args);
+ };
+
};
1;
diff --git a/lib/Reaction/UI/Widget/Field/ChooseOne.pm b/lib/Reaction/UI/Widget/Field/ChooseOne.pm
index e9aa439..cd6ed5e 100644
--- a/lib/Reaction/UI/Widget/Field/ChooseOne.pm
+++ b/lib/Reaction/UI/Widget/Field/ChooseOne.pm
@@ -5,7 +5,7 @@ use Reaction::UI::WidgetClass;
class ChooseOne is 'Reaction::UI::Widget::Field', which {
implements fragment option_is_required {
- if ($_{viewport}->attribute->required) {
+ if ($_{viewport}->attribute->is_required) {
render 'options_is_required_yes';
} else {
render 'options_is_required_no';