cleanup of hard to read layout_args code
[catagits/Reaction.git] / lib / Reaction / UI / ViewPort / Action.pm
1 package Reaction::UI::ViewPort::Action;
2
3 use Reaction::Class;
4
5 use MooseX::Types::URI qw/Uri/;
6 use MooseX::Types::Moose qw/Int Str/;
7 use MooseX::Types::Common::String qw/NonEmptySimpleStr/;
8
9 use namespace::clean -except => [ qw(meta) ];
10
11 extends 'Reaction::UI::ViewPort::Object::Mutable';
12 with 'Reaction::UI::ViewPort::Action::Role::OK';
13
14 has message => (is => 'rw', isa => Str);
15 has '+model' => (handles => [qw/error_message has_error_message/]);
16
17 #this has to fucking go. it BLOWS.
18 has method => (
19   is => 'rw',
20   isa => NonEmptySimpleStr,
21   default => sub { 'post' }
22 );
23
24 has action => ( is => 'rw', isa => Uri );
25
26 has changed => (
27   is => 'rw',
28   isa => Int,
29   reader => 'is_changed',
30   default => sub{0}
31 );
32
33 sub can_apply {
34   my ($self) = @_;
35   foreach my $field ( @{ $self->fields } ) {
36     return 0 if $field->needs_sync;
37     # if e.g. a datetime field has an invalid value that can't be re-assembled
38     # into a datetime object, the action may be in a consistent state but
39     # not synchronized from the fields; in this case, we must not apply
40   }
41   return $self->model->can_apply;
42 }
43
44 sub do_apply {
45   shift->model->do_apply;
46 }
47
48 after apply_child_events => sub {
49   # interrupt here because fields will have been updated
50   my ($self) = @_;
51   $self->sync_action_from_fields;
52 };
53
54 sub sync_action_from_fields {
55   my ($self) = @_;
56   foreach my $field (@{$self->fields}) {
57     $field->sync_to_action; # get the field to populate the $action if possible
58   }
59   $self->model->sync_all;
60   foreach my $field (@{$self->fields}) {
61     $field->sync_from_action; # get errors from $action if applicable
62   }
63 }
64
65 __PACKAGE__->meta->make_immutable;
66
67 1;
68
69 __END__;
70
71 =head1 NAME
72
73 Reaction::UI::ViewPort::Action - Provide user with a form with OK, Apply and Close.
74
75 =head1 SYNOPSIS
76
77   $controller->push_viewport('Reaction::UI::ViewPort::Action',
78     model           => $interface_model_action,
79     field_order     => [qw( firstname lastname )],
80     excluded_fields => [qw( password )],
81   );
82
83 =head1 DESCRIPTION
84
85 This subclass of L<Reaction::UI::ViewPort::Object::Mutable> is used for 
86 rendering a complete form supporting Apply, Close and OK.
87
88 =head1 ATTRIBUTES
89
90 =head2 message
91
92 =head2 model
93
94 Inherited from L<Reaction::UI::ViewPort::Object::Mutable>. Must be a
95 L<Reaction::InterfaceModel::Action>.
96
97 Also handles C<error_message> and C<has_error_message> methods.
98
99 =head2 method
100
101 post / get
102
103 =head2 changed
104
105 Returns true if a field has been edited.
106
107 =head1 METHODS
108
109 =head2 can_apply
110
111 Returns true if no field C<needs_sync> and the L</model> C<can_apply>.
112
113 =head2 do_apply
114
115 Delegates to C<do_apply> on the L</model>, which is a 
116 L<Reaction::InterfaceModel::Action>.
117
118 =head2 sync_action_from_fields
119
120 Firstly calls C<sync_to_action> on every L<Reaction::UI::ViewPort::Field::Mutable>
121 in L<fields|Reaction::UI::ViewPort::Object/fields>. Then it calls C<sync_all> on
122 the L<Reaction::InterfaceModel::Action> in L</model>. Next it will call
123 C<sync_from_action> on every field to repopulate them from the L</model>.
124
125 =head1 SUBCLASSING
126
127   package MyApp::UI::ViewPort::Action;
128   use Reaction::Class;
129   use MooseX::Types::Moose qw( Int );
130
131   use namespace::clean -except => 'meta';
132
133   extends 'Reaction::UI::ViewPort::Action';
134
135   has render_timestamp => (
136     is       => 'ro',
137     isa      => Int,
138     default  => sub { time },
139     required => 1,
140   );
141
142   has '+field_order' => (default => sub {[qw( firstname lastname )]});
143
144   1;
145
146 =head1 SEE ALSO
147
148 L<Reaction::UI::ViewPort>
149
150 L<Reaction::UI::ViewPort::Object>
151
152 L<Reaction::UI::ViewPort::Object::Mutable>
153
154 L<Reaction::InterfaceModel::Action::Role::Apply>
155
156 L<Reaction::InterfaceModel::Action::Role::Close>
157
158 L<Reaction::InterfaceModel::Action::Role::OK>
159
160 =head1 AUTHORS
161
162 See L<Reaction::Class> for authors.
163
164 =head1 LICENSE
165
166 See L<Reaction::Class> for the license.
167
168 =cut
169