oopsie typo
[catagits/Reaction.git] / lib / Reaction / UI / CRUDController.pm
CommitLineData
7adfd53f 1package Reaction::UI::CRUDController;
2
3use strict;
4use warnings;
5use base 'Reaction::UI::Controller';
6use Reaction::Class;
7
8use aliased 'Reaction::UI::ViewPort::ListView';
9use aliased 'Reaction::UI::ViewPort::ActionForm';
10use aliased 'Reaction::UI::ViewPort::ObjectView';
11
12has 'model_base' => (isa => 'Str', is => 'rw', required => 1);
13has 'model_name' => (isa => 'Str', is => 'rw', required => 1);
14
b8faba69 15has action_viewport_map => (isa => 'HashRef', is => 'rw', lazy_build => 1);
16has action_viewport_args => (isa => 'HashRef', is => 'rw', lazy_build => 1);
17
18sub build_action_viewport_map {
19 return {
20 list => ListView,
21 view => ObjectView,
22 create => ActionForm,
23 update => ActionForm,
24 delete => ActionForm,
25 delete_all => ActionForm,
26 };
27}
28
29sub build_action_viewport_args {
30 my $self = shift;
31 return { list =>
32 { action_prototypes =>
33 [ { label => 'Create', action => sub {
34 [ '', 'create', $_[1]->req->captures ] } },
35 { label => 'Delete all', action => sub {
36 [ '', 'delete_all', $_[1]->req->captures ] } },
37 ],
38 Entity =>
39 { action_prototypes =>
40 [ { label => 'View', action => sub {
41 [ '', 'view', [ @{$_[1]->req->captures}, $_[0]->__id ] ] } },
42 { label => 'Edit', action => sub {
43 [ '', 'update', [ @{$_[1]->req->captures}, $_[0]->__id ] ] } },
44 { label => 'Delete', action => sub {
45 [ '', 'delete', [ @{$_[1]->req->captures}, $_[0]->__id ] ] } },
46 ],
47 },
48 },
49 };
50}
7adfd53f 51
52sub base :Action :CaptureArgs(0) {
53 my ($self, $c) = @_;
54}
55
56sub get_collection {
57 my ($self, $c) = @_;
f670cfd0 58 #this sucks and should be fixed
7adfd53f 59 return $c->model(join('::', $self->model_base, $self->model_name));
60}
61
62sub get_model_action {
63 my ($self, $c, $name, $target) = @_;
64
65 if ($target->can('action_for')) {
66 return $target->action_for($name, ctx => $c);
67 }
68
f670cfd0 69 #can we please kill this already?
7adfd53f 70 my $model_name = "Action::${name}".$self->model_name;
71 my $model = $c->model($model_name);
72 confess "no such Model $model_name" unless $model;
73 return $model->new(target_model => $target, ctx => $c);
74}
75
76sub list :Chained('base') :PathPart('') :Args(0) {
77 my ($self, $c) = @_;
78
79 $self->push_viewport(
b8faba69 80 $self->action_viewport_map->{list},
81 %{ $self->action_viewport_args->{list} || {} },
82 collection => $self->get_collection($c)
83 );
7adfd53f 84}
85
86sub create :Chained('base') :PathPart('create') :Args(0) {
87 my ($self, $c) = @_;
88 my $action = $self->get_model_action($c, 'Create', $self->get_collection($c));
b8faba69 89 $self->push_viewport
90 (
91 $self->action_viewport_map->{create},
92 %{ $self->action_viewport_args->{create} || {} },
93 action => $action,
94 next_action => 'list',
95 on_apply_callback => sub { $self->after_create_callback($c => @_); },
96 );
97}
98
99sub delete_all :Chained('base') :PathPart('delete_all') :Args(0) {
100 my ($self, $c) = @_;
101 my $action = $self->get_model_action($c, 'DeleteAll', $self->get_collection($c));
102 $self->push_viewport
103 (
104 $self->action_viewport_map->{delete_all},
105 %{ $self->action_viewport_args->{delete_all} || {} },
106 action => $action,
107 next_action => 'list',
108 );
7adfd53f 109}
110
111sub after_create_callback {
112 my ($self, $c, $vp, $result) = @_;
b8faba69 113 return $self->redirect_to
114 ( $c, 'update', [ @{$c->req->captures}, $result->id ] );
7adfd53f 115}
116
117sub object :Chained('base') :PathPart('id') :CaptureArgs(1) {
118 my ($self, $c, $key) = @_;
f670cfd0 119 my $object :Stashed = $self->get_collection($c)->find($key);
7adfd53f 120 confess "Object? what object?" unless $object; # should be a 404.
121}
122
123sub update :Chained('object') :Args(0) {
124 my ($self, $c) = @_;
125 my $object :Stashed;
126 my $action = $self->get_model_action($c, 'Update', $object);
127 my @cap = @{$c->req->captures};
128 pop(@cap); # object id
b8faba69 129 $self->push_viewport
130 (
131 $self->action_viewport_map->{update},
132 %{ $self->action_viewport_args->{update} || {} },
133 action => $action,
134 next_action => [ $self, 'redirect_to', 'list', \@cap ]
7adfd53f 135 );
136}
137
138sub delete :Chained('object') :Args(0) {
139 my ($self, $c) = @_;
140 my $object :Stashed;
141 my $action = $self->get_model_action($c, 'Delete', $object);
142 my @cap = @{$c->req->captures};
143 pop(@cap); # object id
b8faba69 144 $self->push_viewport
145 (
146 $self->action_viewport_map->{delete},
147 %{ $self->action_viewport_args->{delete} || {} },
148 action => $action,
149 next_action => [ $self, 'redirect_to', 'list', \@cap ]
7adfd53f 150 );
151}
152
153sub view :Chained('object') :Args(0) {
154 my ($self, $c) = @_;
155 my $object :Stashed;
156 my @cap = @{$c->req->captures};
157 pop(@cap); # object id
b8faba69 158 $self->push_viewport
159 (
160 $self->action_viewport_map->{view},
161 %{ $self->action_viewport_args->{view} || {} },
162 object => $object,
163 );
7adfd53f 164}
165
1661;