POD FTW
[catagits/Reaction.git] / lib / Reaction / UI / Controller / Collection.pm
index 265ff79..e28fbdf 100644 (file)
@@ -8,21 +8,77 @@ use Reaction::Class;
 use aliased 'Reaction::UI::ViewPort::Collection::Grid';
 use aliased 'Reaction::UI::ViewPort::Object';
 
-has 'model_name'      => (isa => 'Str', is => 'rw', required => 1);
-has 'collection_name' => (isa => 'Str', is => 'rw', required => 1);
+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_map => (isa => 'HashRef', is => 'rw', lazy_build => 1);
 has action_viewport_args => (isa => 'HashRef', is => 'rw', lazy_build => 1);
 
+has default_member_actions => (
+  isa => 'ArrayRef',
+  is => 'rw',
+  lazy_build => 1
+);
+
+has default_collection_actions => (
+  isa => 'ArrayRef',
+  is => 'rw',
+  lazy_build => 1
+);
+
+sub _build_default_member_actions { ['view'] }
+
+sub _build_default_collection_actions { [] }
+
 sub _build_action_viewport_map {
-  return {
-          list => Grid,
-          view => Object,
-         };
+  my $self = shift;
+  my %map;
+  $map{list} = Grid;
+  $map{view} = Object; #if grep {$_ eq 'view'} @{$self->default_member_actions};
+  return \%map;
 }
 
 sub _build_action_viewport_args {
-  return { };
+  my $self = shift;
+  my $args = { list => { Member => {} } };
+
+  my $m_protos = $args->{list}{Member}{action_prototypes} = {};
+  for my $action_name( @{ $self->default_member_actions }){
+    my $label = ucfirst(join(' ', split(/_/, $action_name)));
+    my $proto = $self->_build_member_action_prototype($label, $action_name);
+    $m_protos->{$action_name} = $proto;
+  }
+
+  my $c_protos = $args->{list}{action_prototypes} = {};
+  for my $action_name( @{ $self->default_collection_actions }){
+    my $label = ucfirst(join(' ', split(/_/, $action_name)));
+    my $proto = $self->_build_collection_action_prototype($label, $action_name);
+    $c_protos->{$action_name} = $proto;
+  }
+
+  return $args;
+}
+
+sub _build_member_action_prototype {
+  my ($self, $label, $action_name) = @_;
+  return {
+    label => $label,
+    uri => sub {
+      my $action = $self->action_for($action_name);
+      $_[1]->uri_for($action, [ @{$_[1]->req->captures}, $_[0]->__id ]);
+    },
+  };
+}
+
+sub _build_collection_action_prototype {
+  my ($self, $label, $action_name) = @_;
+  return {
+    label => $label,
+    uri => sub {
+      my $action = $self->action_for($action_name);
+      $_[1]->uri_for($action, $_[1]->req->captures);
+    },
+  };
 }
 
 #XXX candidate for futre optimization, should cache reader?
@@ -63,17 +119,17 @@ sub view :Chained('object') :Args(0) {
 sub basic_page {
   my ($self, $c, $vp_args) = @_;
   my $action_name = $c->stack->[-1]->name;
-  return $self->push_viewport
+  my $vp = $self->action_viewport_map->{$action_name},
+  my $args = $self->merge_config_hashes
     (
-     $self->action_viewport_map->{$action_name},
-     %{ $vp_args || {} },
-     %{ $self->action_viewport_args->{$action_name} || {} },
+     $vp_args || {},
+     $self->action_viewport_args->{$action_name} || {} ,
     );
+  return $self->push_viewport($vp, %$args);
 }
 
 1;
 
-
 __END__;
 
 =head1 NAME
@@ -113,7 +169,7 @@ Read-write lazy building hashref. The keys should match action names in the
 Controller and the value should be the ViewPort class that this action should
 use. See method C<basic_page> for more info.
 
-=head action_viewport_args
+=head2 action_viewport_args
 
 Read-write lazy building hashref. Additional ViewPort arguments for the action
 named as the key in the controller.  See method C<basic_page> for more info.
@@ -128,6 +184,40 @@ named as the key in the controller.  See method C<basic_page> for more info.
 
 =back
 
+=head2 default_member_actions
+
+Read-write lazy building arrayref. The names of the member actions (the actions
+that apply to each member of the collection and typically have an object as a
+target e.g. update,delete) to be enabled by default. By default, this is only
+'view'
+
+=over 4
+
+=item B<_build_defualt_member_actions - Provided builder method, see METHODS
+
+=item B<has_default_member_actions> - Auto generated predicate
+
+=item B<clear_default_member_actions>- Auto generated clearer method
+
+=back
+
+=head2 default_collection_actions
+
+Read-write lazy building arrayref. The names of the collection actions (the
+actions that apply to the entire collection and typically have a collection as
+a target e.g. create, delete_all) to be enabled by default. By default, this
+is only empty.
+
+=over 4
+
+=item B<_build_defualt_member_actions - Provided builder method, see METHODS
+
+=item B<has_default_member_actions> - Auto generated predicate
+
+=item B<clear_default_member_actions>- Auto generated clearer method
+
+=back
+
 =head1 METHODS
 
 =head2 get_collection $c
@@ -136,14 +226,41 @@ Returns an instance of the collection this controller uses.
 
 =head2 _build_action_viewport_map
 
-Provided builder for C<action_viewport_map>. Returns a hash with two items:
+Provided builder for C<action_viewport_map>. Returns a hash containing:
 
-    list => 'Reaction::UI::ViewPort::ListView',
+    list => 'Reaction::UI::ViewPort::Collection::Grid',
     view => 'Reaction::UI::ViewPort::Object',
 
 =head2 _build_action_viewport_args
 
-Returns an empty hashref.
+By default will reurn a hashref containing action prototypes for all default
+member and collection actions. The prototype URI generators are generated by
+C<_build_member_action_prototype> and C<_build_collection_action_prototype>
+respectively and labels are the result of replacing underscores in the name
+with spaces and capitalizing the first letter. If you plan to use custom
+actions that are not supported by this scheme or you would like to customize
+the values it is suggested you wrap / override this method.
+
+Default output for a controller having only 'view' enabled:
+
+    { list => {
+        action_prototypes => {},
+        Member => {
+          action_prototypes => {
+            view => {label => 'View', uri => sub{...} },
+          },
+        },
+      },
+    }
+
+=head2 _build_member_action_prototype $label, $action_name
+
+Creates an action prototype suitable for creating action links in
+L<Reaction::UI::ViewPort::Role::Actions>. C<$action_name> should be the name of
+a Catalyst action in this controller.The prototype will generate a URI
+based on the action, current captures.
+
+=head2 _build_collection_action_prototype $label, $action_name
 
 =head2 basic_page $c, \%vp_args
 
@@ -183,7 +300,7 @@ action link.
 The default ViewPort for this action is C<Reaction::UI::ViewPort::Object> and
 can be changed by altering the C<action_viewport_map> attribute hash.
 
-=SEE ALSO
+=head1 SEE ALSO
 
 L<Reaction::UI::Controller>