r31695@martha (orig r1238): groditi | 2009-09-25 14:51:47 -0400
[catagits/Reaction.git] / lib / Reaction / UI / Controller / Collection.pm
1 package Reaction::UI::Controller::Collection;
2
3 use base 'Reaction::UI::Controller';
4 use Reaction::Class;
5
6 use aliased 'Reaction::UI::ViewPort::Collection::Grid';
7
8 __PACKAGE__->config(
9   action => {
10     list => { Chained => 'base', PathPart => '' },
11     object => { Chained => 'base', PathPart => 'id' },
12     view => { Chained => 'object', },
13   },
14 );
15
16 with(
17   'Reaction::UI::Controller::Role::GetCollection',
18   'Reaction::UI::Controller::Role::Action::Simple',
19   'Reaction::UI::Controller::Role::Action::Object',
20   'Reaction::UI::Controller::Role::Action::View',
21   'Reaction::UI::Controller::Role::Action::List'
22 );
23
24 has default_member_actions => (
25   isa => 'ArrayRef',
26   is => 'rw',
27   lazy_build => 1
28 );
29
30 has default_collection_actions => (
31   isa => 'ArrayRef',
32   is => 'rw',
33   lazy_build => 1
34 );
35
36 sub _build_default_member_actions { ['view'] }
37
38 sub _build_default_collection_actions { [] }
39
40 around _build_action_viewport_map => sub {
41   my $orig = shift;
42   my $map = shift->$orig( @_ );
43   $map->{list} = Grid;
44   return $map;
45 };
46
47 around _build_action_viewport_args => sub {
48   my $orig = shift;
49   my $self = shift;
50   my $args = { list => { Member => {} } };
51
52    my $m_protos = $args->{list}{Member}{action_prototypes} = {};
53    for my $action_name( @{ $self->default_member_actions }){
54      my $label = join(' ', map { ucfirst } split(/_/, $action_name));
55      my $proto = $self->_build_member_action_prototype($label, $action_name);
56      $m_protos->{$action_name} = $proto;
57    }
58
59    my $c_protos = $args->{list}{action_prototypes} = {};
60    for my $action_name( @{ $self->default_collection_actions }){
61      my $label = join(' ', map { ucfirst } split(/_/, $action_name));
62      my $proto = $self->_build_collection_action_prototype($label, $action_name);
63      $c_protos->{$action_name} = $proto;
64    }
65
66   return $args;
67 };
68
69 sub _build_member_action_prototype {
70   my ($self, $label, $action_name) = @_;
71   return {
72     label => $label,
73     uri => sub {
74       my $action = $self->action_for($action_name);
75       $_[1]->uri_for($action, [ @{$_[1]->req->captures}, $_[0]->__id ]);
76     },
77   };
78 }
79
80 sub _build_collection_action_prototype {
81   my ($self, $label, $action_name) = @_;
82   return {
83     label => $label,
84     uri => sub {
85       my $action = $self->action_for($action_name);
86       $_[1]->uri_for($action, $_[1]->req->captures);
87     },
88   };
89 }
90
91
92 sub base :CaptureArgs(0) {
93   my ($self, $c) = @_;
94 }
95
96 ##DEPRECATED ACTION
97
98 sub basic_page {
99   my( $self, $c, @args) = @_;
100   if( $c->debug ){
101     my ($package,undef,$line,$sub_name,@rest) = caller(1);
102     my $message = "The method 'basic_page', called from sub '${sub_name}' in package ${package} at line ${line} is deprecated. Please use 'setup_viewport' instead.";
103     $c->log->debug( $message );
104   }
105   $self->setup_viewport( $c, @args );
106 }
107
108 1;
109
110 __END__;
111
112 =head1 NAME
113
114 Reaction::UI::Controller
115
116 =head1 DESCRIPTION
117
118 Controller class used to make displaying collections easier.
119 Inherits from L<Reaction::UI::Controller>.
120
121 =head1 ROLES CONSUMED
122
123 This role also consumes the following roles:
124
125 =over4
126
127 =item L<Reaction::UI::Controller::Role::Action::GetCollection>
128
129 =item L<Reaction::UI::Controller::Role::Action::Simple>
130
131 =item L<Reaction::UI::Controller::Role::Action::Object>
132
133 =item L<Reaction::UI::Controller::Role::Action::List>
134
135 =item L<Reaction::UI::Controller::Role::Action::View>
136
137 =back
138
139 =head1 ATTRIBUTES
140
141 =head2 default_member_actions
142
143 Read-write lazy building arrayref. The names of the member actions (the actions
144 that apply to each member of the collection and typically have an object as a
145 target e.g. update,delete) to be enabled by default. By default, this is only
146 'view'
147
148 =over 4
149
150 =item B<_build_default_member_actions> - Provided builder method, see METHODS
151
152 =item B<has_default_member_actions> - Auto generated predicate
153
154 =item B<clear_default_member_actions>- Auto generated clearer method
155
156 =back
157
158 =head2 default_collection_actions
159
160 Read-write lazy building arrayref. The names of the collection actions (the
161 actions that apply to the entire collection and typically have a collection as
162 a target e.g. create, delete_all) to be enabled by default. By default, this
163 is only empty.
164
165 =over 4
166
167 =item B<_build_default_member_actions> - Provided builder method, see METHODS
168
169 =item B<has_default_member_actions> - Auto generated predicate
170
171 =item B<clear_default_member_actions>- Auto generated clearer method
172
173 =back
174
175 =head1 METHODS
176
177 =head2 _build_action_viewport_map
178
179 Set C<list> to L<Reaction::UI::ViewPort::Collection::Grid>
180
181 =head2 _build_action_viewport_args
182
183 By default will reurn a hashref containing action prototypes for all default
184 member and collection actions. The prototype URI generators are generated by
185 C<_build_member_action_prototype> and C<_build_collection_action_prototype>
186 respectively and labels are the result of replacing underscores in the name
187 with spaces and capitalizing the first letter. If you plan to use custom
188 actions that are not supported by this scheme or you would like to customize
189 the values it is suggested you wrap / override this method.
190
191 Default output for a controller having only 'view' enabled:
192
193     { list => {
194         action_prototypes => {},
195         Member => {
196           action_prototypes => {
197             view => {label => 'View', uri => sub{...} },
198           },
199         },
200       },
201     }
202
203 =head2 _build_member_action_prototype $label, $action_name
204
205 Creates an action prototype suitable for creating action links in
206 L<Reaction::UI::ViewPort::Role::Actions>. C<$action_name> should be the name of
207 a Catalyst action in this controller.The prototype will generate a URI
208 based on the action, current captures.
209
210 =head2 _build_collection_action_prototype $label, $action_name
211
212 =head2 basic_page $c, \%vp_args
213
214 Deprecated alias to C<setup_viewport>.
215
216 =head1 ACTIONS
217
218 =head2 base
219
220 Chain link, no-op.
221
222 =head2 list
223
224 Chained to C<base>. See L<Reaction::UI::Controller::Role::Action::List>
225
226 =head2 object
227
228 Chained to C<base>. See L<Reaction::UI::Controller::Role::Action::Object>
229
230 =head2 view
231
232 Chained to C<object>. See L<Reaction::UI::Controller::Role::Action::View>
233
234 =head1 SEE ALSO
235
236 L<Reaction::UI::Controller>
237
238 =head1 AUTHORS
239
240 See L<Reaction::Class> for authors.
241
242 =head1 LICENSE
243
244 See L<Reaction::Class> for the license.
245
246 =cut