list => {
ViewPort => {
excluded_fields => [qw/id/],
+ action_order => [qw/delete_all create/],
+ Member => {
+ action_order => [qw/view update delete/],
+ },
},
},
view => {
);
}
+sub _build_action_viewport_args {
+ my $self = shift;
+ my $args = $self->next::method(@_);
+ $args->{list}{action_prototypes}{delete_all}{label} = 'Delete All Records';
+ return $args;
+}
+
1;
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?
1;
-
__END__;
=head1 NAME
use aliased 'Reaction::UI::ViewPort::ListView';
sub _build_action_viewport_map {
- my $map = shift->next::method(@_);
- $map->{list} = ListView;
- $map->{$_} = Action for qw/create update delete delete_all/;
+ my $self = shift;
+ my $map = $self->next::method(@_);
+ $map->{list} = ListView if exists $map->{list};
+
+ my %allowed = map { $_ => undef }
+ ( @{$self->default_member_actions}, @{$self->default_collection_actions} );
+
+ my @local_actions = qw/create update delete delete_all/;
+ $map->{$_} = Action for grep { exists $allowed{$_} } @local_actions;
+
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 ] } },
- ],
- Member =>
- { 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 _build_default_member_actions {
+ [ @{shift->next::method(@_)}, qw/update delete/ ];
+}
+
+sub _build_default_collection_actions {
+ [ @{shift->next::method(@_)}, qw/create delete_all/ ];
}
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);
+ return $target->action_for($name, ctx => $c);
}
sub create :Chained('base') :PathPart('create') :Args(0) {
sub delete_all :Chained('base') :PathPart('delete_all') :Args(0) {
my ($self, $c) = @_;
- $self->basic_model_action( $c, {
+ $self->basic_model_action( $c, {
on_close_callback => sub { $self->on_delete_all_close_callback($c => @_) }
});
}
my $self = shift;
for (@{ $self->members }) {
my $protos = $_->action_prototypes;
- return scalar(@$protos);
- #return scalar(keys(%$protos));
+ return scalar(keys(%$protos));
}
return 1;
},
my $orig = shift;
my $self = shift;
$self->member_args->{computed_field_order} ||= $self->computed_field_order;
-# $self->member_args->{computed_action_order} ||= [];
+ $self->member_args->{computed_action_order} ||= [];
my $members = $self->$orig(@_);
# cache everything yo
-# for my $member (@$members){
-# $member->clear_computed_action_order;
-# my $order = $member->computed_action_order;
-# @{ $self->member_args->{computed_action_order} } = @$order;
-# last;
-# }
+ for my $member (@$members){
+ $member->clear_computed_action_order;
+ my $order = $member->computed_action_order;
+ @{ $self->member_args->{computed_action_order} } = @$order;
+ last;
+ }
return $members;
};
package Reaction::UI::ViewPort::Role::Actions;
use Reaction::Role;
-use Reaction::UI::ViewPort::Action::Link;
+use Reaction::UI::ViewPort::URI;
use namespace::clean -except => [ qw(meta) ];
+has actions => (
+ is => 'ro',
+ isa => 'ArrayRef',
+ lazy_build => 1
+);
+
+has action_order => (
+ is => 'ro',
+ isa => 'ArrayRef'
+);
+
+has action_prototypes => (
+ is => 'ro',
+ isa => 'HashRef',
+ required => 1,
+ default => sub{ {} }
+);
+
+has computed_action_order => (
+ is => 'ro',
+ isa => 'ArrayRef',
+ lazy_build => 1
+);
+
+sub _build_computed_action_order {
+ my $self = shift;
+ my $ordered = $self->sort_by_spec(
+ ($self->has_action_order ? $self->action_order : []),
+ [ keys %{ $self->action_prototypes } ]
+ );
+ return $ordered ;
+}
-has actions => (is => 'ro', isa => 'ArrayRef', lazy_build => 1);
-has action_prototypes => (is => 'ro', isa => 'ArrayRef', lazy_build => 1);
-sub _build_action_prototypes { [] };
sub _build_actions {
my ($self) = @_;
my (@act, $i);
my $ctx = $self->ctx;
my $loc = $self->location;
- foreach my $proto (@{ $self->action_prototypes }) {
- my $action = Reaction::UI::ViewPort::Action::Link->new
- (
- ctx => $ctx,
- target => $self->model,
- location => join ('-', $loc, 'action', $i++),
- %$proto,
- );
+ my $target = $self->model;
+
+ foreach my $proto_name ( @{ $self->computed_action_order } ) {
+ my $proto = $self->action_prototypes->{$proto_name};
+ my $uri = $proto->{uri} or confess('uri is required in prototype action');
+ my $label = exists $proto->{label} ? $proto->{label} : $proto_name;
+
+ my $action = Reaction::UI::ViewPort::URI->new(
+ location => join ('-', $loc, 'action', $i++),
+ uri => ( ref($uri) eq 'CODE' ? $uri->($target, $ctx) : $uri ),
+ display => ( ref($label) eq 'CODE' ? $label->($target, $ctx) : $label ),
+ );
push(@act, $action);
}
return \@act;
-};
-
-
+}
1;