diff options
author | groditi <groditi@03d0b0b2-0e1a-0410-a411-fdb2f4bd65d7> | 2008-08-21 00:38:47 +0000 |
---|---|---|
committer | groditi <groditi@03d0b0b2-0e1a-0410-a411-fdb2f4bd65d7> | 2008-08-21 00:38:47 +0000 |
commit | 599c1172394e3377d8e3e28c06557a99a1a10d1e (patch) | |
tree | 78e277ddc4cd5af9c43f9b033d82afc071e3f1e8 | |
parent | 3671c9c3a3eb9640371d09a80ff88ae774d0a0b7 (diff) | |
download | reaction-599c1172394e3377d8e3e28c06557a99a1a10d1e.tar.gz reaction-599c1172394e3377d8e3e28c06557a99a1a10d1e.zip |
container support built into fields and an example of usage in ComponentUI
-rw-r--r-- | lib/ComponentUI/Controller/TestModel/Bar.pm | 4 | ||||
-rw-r--r-- | lib/ComponentUI/Controller/TestModel/Foo.pm | 33 | ||||
-rw-r--r-- | lib/Reaction/UI/ViewPort/Action.pm | 179 | ||||
-rw-r--r-- | lib/Reaction/UI/ViewPort/Action/Role/Apply.pm | 42 | ||||
-rw-r--r-- | lib/Reaction/UI/ViewPort/Action/Role/Close.pm | 48 | ||||
-rw-r--r-- | lib/Reaction/UI/ViewPort/Action/Role/OK.pm | 34 | ||||
-rw-r--r-- | lib/Reaction/UI/ViewPort/Field.pm | 24 | ||||
-rw-r--r-- | lib/Reaction/UI/ViewPort/Object.pm | 99 | ||||
-rw-r--r-- | lib/Reaction/UI/Widget/Action.pm | 4 | ||||
-rw-r--r-- | lib/Reaction/UI/Widget/Object.pm | 21 | ||||
-rw-r--r-- | share/skin/base/layout/action.tt | 10 | ||||
-rw-r--r-- | share/skin/base/layout/object.tt | 11 | ||||
-rw-r--r-- | share/skin/default/layout/action.tt | 2 | ||||
-rw-r--r-- | share/skin/default/layout/object.tt | 2 | ||||
-rw-r--r-- | t/lib/RTest/TestDB/Bar.pm | 5 |
15 files changed, 310 insertions, 208 deletions
diff --git a/lib/ComponentUI/Controller/TestModel/Bar.pm b/lib/ComponentUI/Controller/TestModel/Bar.pm index f7859b7..0839506 100644 --- a/lib/ComponentUI/Controller/TestModel/Bar.pm +++ b/lib/ComponentUI/Controller/TestModel/Bar.pm @@ -6,7 +6,9 @@ use Reaction::Class; __PACKAGE__->config( model_name => 'TestModel', collection_name => 'Bar', - action => { base => { Chained => '/base', PathPart => 'testmodel/bar' }}, + action => { + base => { Chained => '/base', PathPart => 'testmodel/bar' }, + }, ); 1; diff --git a/lib/ComponentUI/Controller/TestModel/Foo.pm b/lib/ComponentUI/Controller/TestModel/Foo.pm index cc821c5..b5dfe5b 100644 --- a/lib/ComponentUI/Controller/TestModel/Foo.pm +++ b/lib/ComponentUI/Controller/TestModel/Foo.pm @@ -6,7 +6,38 @@ use Reaction::Class; __PACKAGE__->config( model_name => 'TestModel', collection_name => 'Foo', - action => { base => { Chained => '/base', PathPart => 'testmodel/foo' } }, + action => { + base => { Chained => '/base', PathPart => 'testmodel/foo' }, + list => { + ViewPort => { + excluded_fields => [qw/id/], + }, + }, + view => { + ViewPort => { + excluded_fields => [qw/id/], + }, + }, + }, ); +for my $action (qw/view create update/){ + __PACKAGE__->config( + action => { + $action => { + ViewPort => { + container_layouts => [ + { name => 'primary', fields => [qw/first_name last_name/]}, + { + name => 'secondary', + label => 'Optional Label', + fields => [qw/bars bazes/], + }, + ], + }, + }, + } + ); +} + 1; diff --git a/lib/Reaction/UI/ViewPort/Action.pm b/lib/Reaction/UI/ViewPort/Action.pm index 9fc808f..6a2ac58 100644 --- a/lib/Reaction/UI/ViewPort/Action.pm +++ b/lib/Reaction/UI/ViewPort/Action.pm @@ -2,47 +2,27 @@ package Reaction::UI::ViewPort::Action; use Reaction::Class; -use aliased 'Reaction::UI::ViewPort::Object'; -use aliased 'Reaction::UI::ViewPort::Field::Mutable::Text'; -use aliased 'Reaction::UI::ViewPort::Field::Mutable::Array'; -use aliased 'Reaction::UI::ViewPort::Field::Mutable::String'; -use aliased 'Reaction::UI::ViewPort::Field::Mutable::Number'; -use aliased 'Reaction::UI::ViewPort::Field::Mutable::Integer'; -use aliased 'Reaction::UI::ViewPort::Field::Mutable::Boolean'; -use aliased 'Reaction::UI::ViewPort::Field::Mutable::Password'; -use aliased 'Reaction::UI::ViewPort::Field::Mutable::DateTime'; -use aliased 'Reaction::UI::ViewPort::Field::Mutable::ChooseOne'; -use aliased 'Reaction::UI::ViewPort::Field::Mutable::ChooseMany'; - -use aliased 'Reaction::UI::ViewPort::Field::Mutable::File'; -#use aliased 'Reaction::UI::ViewPort::Field::Mutable::TimeRange'; - use MooseX::Types::Moose qw/Int/; use Reaction::Types::Core qw/NonEmptySimpleStr/; use namespace::clean -except => [ qw(meta) ]; -extends Object; + +extends 'Reaction::UI::ViewPort::Object::Mutable'; with 'Reaction::UI::ViewPort::Action::Role::OK'; -has model => ( - is => 'ro', - isa => 'Reaction::InterfaceModel::Action', - required => 1 - ); +#this has to fucking go. it BLOWS. +has method => ( + is => 'rw', + isa => NonEmptySimpleStr, + default => sub { 'post' } +); has changed => ( is => 'rw', isa => Int, reader => 'is_changed', default => sub{0} - ); - -#this has to fucking go. it BLOWS. -has method => ( - is => 'rw', - isa => NonEmptySimpleStr, - default => sub { 'post' } - ); +); sub can_apply { my ($self) = @_; @@ -76,75 +56,6 @@ sub sync_action_from_fields { } } -sub _build_fields_for_type_Num { - my ($self, $attr, $args) = @_; - $self->_build_simple_field(attribute => $attr, class => Number, %$args); -} - -sub _build_fields_for_type_Int { - my ($self, $attr, $args) = @_; - $self->_build_simple_field(attribute => $attr, class => Integer, %$args); -} - -sub _build_fields_for_type_Bool { - my ($self, $attr, $args) = @_; - $self->_build_simple_field(attribute => $attr, class => Boolean, %$args); -} - -sub _build_fields_for_type_Reaction_Types_Core_SimpleStr { - my ($self, $attr, $args) = @_; - $self->_build_simple_field(attribute => $attr, class => String, %$args); -} - -sub _build_fields_for_type_Reaction_Types_File_File { - my ($self, $attr, $args) = @_; - $self->_build_simple_field(attribute => $attr, class => File, %$args); -} - -sub _build_fields_for_type_Str { - my ($self, $attr, $args) = @_; - if ($attr->has_valid_values) { # There's probably a better way to do this - $self->_build_simple_field(attribute => $attr, class => ChooseOne, %$args); - } else { - $self->_build_simple_field(attribute => $attr, class => Text, %$args); - } -} - -sub _build_fields_for_type_Reaction_Types_Core_Password { - my ($self, $attr, $args) = @_; - $self->_build_simple_field(attribute => $attr, class => Password, %$args); -} - -sub _build_fields_for_type_Reaction_Types_DateTime_DateTime { - my ($self, $attr, $args) = @_; - $self->_build_simple_field(attribute => $attr, class => DateTime, %$args); -} - -sub _build_fields_for_type_Enum { - my ($self, $attr, $args) = @_; - $self->_build_simple_field(attribute => $attr, class => ChooseOne, %$args); -} - -#this needs to be fixed. somehow. beats the shit our of me. really. -#implements build_fields_for_type_Reaction_InterfaceModel_Object => as { -sub _build_fields_for_type_DBIx_Class_Row { - my ($self, $attr, $args) = @_; - $self->_build_simple_field(attribute => $attr, class => ChooseOne, %$args); -} - -sub _build_fields_for_type_ArrayRef { - my ($self, $attr, $args) = @_; - if ($attr->has_valid_values) { - $self->_build_simple_field(attribute => $attr, class => ChooseMany, %$args); - } else { - $self->_build_simple_field - ( - attribute => $attr, - class => Array, - layout => 'field/mutable/hidden_array', - %$args); - } -} __PACKAGE__->meta->make_immutable; @@ -154,88 +65,46 @@ __END__; =head1 NAME -Reaction::UI::ViewPort::Object::Mutable +Reaction::UI::ViewPort::Action =head1 SYNOPSIS - use aliased 'Reaction::UI::ViewPort::Object::Mutable'; - - $self->push_viewport(Mutable, - layout => 'register', - model => $action, - next_action => [ $self, 'redirect_to', 'accounts', $c->req->captures ], - ctx => $c, - field_order => [ - qw / contact_title company_name email address1 address2 address3 - city country post_code telephone mobile fax/ ], - ); - =head1 DESCRIPTION -This subclass of L<Reaction::UI::ViewPort::Object> is used for rendering a -collection of C<Reaction::UI::ViewPort::Field::Mutable::*> objects for user editing. +This subclass of L<Reaction::UI::ViewPort::Object::Mutable> is used for +rendering a complete form supporting Apply, Close and OK. =head1 ATTRIBUTES -=head2 model - -L<Reaction::InterfaceModel::Action> - -=head2 ok_label - -Default: 'ok' - -=head2 apply_label - -Default: 'apply' - -=head2 close_label_close - -Default: 'close' - -=head2 close_label_cancel +=head2 method -This label is only shown when C<changed> is true. - -Default: 'cancel' - -=head2 fields - -=head2 can_apply - -=head2 can_close +post / get =head2 changed Returns true if a field has been edited. -=head2 next_action - -=head2 on_apply_callback - -CodeRef. - =head1 METHODS -=head2 ok +=head2 can_apply -Calls C<apply>, and then C<close> if successful. +=head2 do_apply -=head2 close +=head2 sync_action_from_fields -Pop viewport and proceed to C<next_action>. +=head1 SEE ALSO -=head2 apply +L<Reaction::UI::ViewPort> -Attempt to save changes and update C<changed> attribute if required. +L<Reaction::UI::ViewPort::Object> -=head1 SEE ALSO +L<Reaction::UI::ViewPort::Object::Mutable> -L<Reaction::UI::ViewPort::Object> +L<Reaction::InterfaceModel::Action::Role::Apply> -L<Reaction::UI::ViewPort> +L<Reaction::InterfaceModel::Action::Role::Close> -L<Reaction::InterfaceModel::Action> +L<Reaction::InterfaceModel::Action::Role::OK> =head1 AUTHORS diff --git a/lib/Reaction/UI/ViewPort/Action/Role/Apply.pm b/lib/Reaction/UI/ViewPort/Action/Role/Apply.pm index 4138dde..e65b9e7 100644 --- a/lib/Reaction/UI/ViewPort/Action/Role/Apply.pm +++ b/lib/Reaction/UI/ViewPort/Action/Role/Apply.pm @@ -27,3 +27,45 @@ sub apply { around accept_events => sub { ( 'apply', shift->(@_) ) }; 1; + +__END__ + +=head1 NAME + +Reaction::UI::ViewPort::Action::Role::Apply + +=head1 ATTRIBUTES + +=head2 apply_label + +Default: 'apply' + +=head2 on_apply_callback + +CodeRef. + +=head1 METHODS + +=head2 can_apply + +=head2 apply + +Calls a user-supplied C<do_apply> and if it is successful runs the +C<on_apply_callback> passing C<$self> and the result of C<do_apply> as args. + +=head1 SEE ALSO + +L<Reaction::UI::ViewPort::Action::Role::Close> + +L<Reaction::UI::ViewPort::Action::Role::OK> + +=head1 AUTHORS + +See L<Reaction::Class> for authors. + +=head1 LICENSE + +See L<Reaction::Class> for the license. + +=cut + diff --git a/lib/Reaction/UI/ViewPort/Action/Role/Close.pm b/lib/Reaction/UI/ViewPort/Action/Role/Close.pm index ad31722..f236a9d 100644 --- a/lib/Reaction/UI/ViewPort/Action/Role/Close.pm +++ b/lib/Reaction/UI/ViewPort/Action/Role/Close.pm @@ -37,3 +37,51 @@ around accept_events => sub { }; 1; + +__END__ + +=head1 NAME + +Reaction::UI::ViewPort::Action::Role::Close + +=head1 ATTRIBUTES + +=head2 close_label + +Default: C<close_label_close> + +=head2 close_label_close + +Default: 'close' + +=head2 close_label_cancel + +This label is only shown when C<changed> is true. + +Default: 'cancel' + +=head2 on_close_callback + +CodeRef. + +=head1 METHODS + +=head2 close + +=head2 can_close + +=head1 SEE ALSO + +L<Reaction::UI::ViewPort::Action::Role::Apply> + +L<Reaction::UI::ViewPort::Action::Role::OK> + +=head1 AUTHORS + +See L<Reaction::Class> for authors. + +=head1 LICENSE + +See L<Reaction::Class> for the license. + +=cut diff --git a/lib/Reaction/UI/ViewPort/Action/Role/OK.pm b/lib/Reaction/UI/ViewPort/Action/Role/OK.pm index 59e96c7..38001f8 100644 --- a/lib/Reaction/UI/ViewPort/Action/Role/OK.pm +++ b/lib/Reaction/UI/ViewPort/Action/Role/OK.pm @@ -20,3 +20,37 @@ around accept_events => sub { }; 1; + +__END__ + +=head1 NAME + +Reaction::UI::ViewPort::Action::Role::Close + +=head1 ATTRIBUTES + +=head2 ok_label + +Default: 'ok' + +=head1 METHODS + +=head2 ok + +Calls C<apply>, and then C<close> if successful. + +=head1 SEE ALSO + +L<Reaction::UI::ViewPort::Action::Role::Apply> + +L<Reaction::UI::ViewPort::Action::Role::Close> + +=head1 AUTHORS + +See L<Reaction::Class> for authors. + +=head1 LICENSE + +See L<Reaction::Class> for the license. + +=cut diff --git a/lib/Reaction/UI/ViewPort/Field.pm b/lib/Reaction/UI/ViewPort/Field.pm index a4bb219..d3dd2e7 100644 --- a/lib/Reaction/UI/ViewPort/Field.pm +++ b/lib/Reaction/UI/ViewPort/Field.pm @@ -7,8 +7,6 @@ use aliased 'Reaction::Meta::InterfaceModel::Object::ParameterAttribute'; use namespace::clean -except => [ qw(meta) ]; extends 'Reaction::UI::ViewPort'; - - has value => (is => 'rw', lazy_build => 1); has name => (is => 'rw', isa => 'Str', lazy_build => 1); has label => (is => 'rw', isa => 'Str', lazy_build => 1); @@ -16,15 +14,19 @@ has value_string => (is => 'rw', isa => 'Str', lazy_build => 1); has model => (is => 'ro', isa => Object, required => 1); has attribute => (is => 'ro', isa => ParameterAttribute, required => 1); + sub _build_name { shift->attribute->name }; + sub _build_label { join(' ', map { ucfirst } split('_', shift->name)); -}; +} + sub _build_value { my ($self) = @_; my $reader = $self->attribute->get_read_method; return $self->model->$reader; -}; +} + sub _model_has_value { my ($self) = @_; my $predicate = $self->attribute->get_predicate_method; @@ -37,7 +39,8 @@ sub _model_has_value { return 1; } return 0; -}; +} + sub _build_value_string { my ($self) = @_; # XXX need the defined test because the IM lazy builds from @@ -47,14 +50,17 @@ sub _build_value_string { return ($self->_model_has_value && defined($self->_build_value) ? $self->_value_string_from_value : $self->_empty_string_value); -}; +} + sub _value_string_from_value { shift->value; -}; -sub _empty_string_value { '' }; +} + +sub _empty_string_value { '' } + sub value_is_required { shift->attribute->is_required; -}; +} __PACKAGE__->meta->make_immutable; diff --git a/lib/Reaction/UI/ViewPort/Object.pm b/lib/Reaction/UI/ViewPort/Object.pm index 35fa9c9..e7a2e3a 100644 --- a/lib/Reaction/UI/ViewPort/Object.pm +++ b/lib/Reaction/UI/ViewPort/Object.pm @@ -12,6 +12,7 @@ use aliased 'Reaction::UI::ViewPort::Field::RelatedObject'; use aliased 'Reaction::UI::ViewPort::Field::Array'; use aliased 'Reaction::UI::ViewPort::Field::Collection'; use aliased 'Reaction::UI::ViewPort::Field::File'; +use aliased 'Reaction::UI::ViewPort::Field::Container'; use aliased 'Reaction::InterfaceModel::Object' => 'IM_Object'; @@ -29,15 +30,62 @@ has field_order => (is => 'ro', isa => 'ArrayRef'); has builder_cache => (is => 'ro', isa => 'HashRef', lazy_build => 1); has excluded_fields => (is => 'ro', isa => 'ArrayRef', lazy_build => 1); has computed_field_order => (is => 'ro', isa => 'ArrayRef', lazy_build => 1); + +has containers => ( is => 'ro', isa => 'ArrayRef', lazy_build => 1); +has container_layouts => ( is => 'rw', isa => 'ArrayRef' ); + sub BUILD { my ($self, $args) = @_; if( my $field_args = delete $args->{Field} ){ $self->field_args( $field_args ); } -}; +} + +sub _build_builder_cache { {} } +sub _build_excluded_fields { [] } + +sub _build_containers { + my $self = shift; + + my @container_layouts; + if( $self->has_container_layouts ){ + #make sure we don't accidentally modify the original + @container_layouts = map { {%$_} }@{ $self->container_layouts }; + } #we should always have a '_' container; + unless (grep {$_->{name} eq '_'} @container_layouts ){ + unshift(@container_layouts, {name => '_'}); + } + + my %fields; + my $ordered_field_names = $self->computed_field_order; + @fields{ @$ordered_field_names } = @{ $self->fields }; + + my %containers; + my @container_order; + for my $layout ( @container_layouts ){ + my @container_fields; + my $name = $layout->{name}; + push(@container_order, $name); + if( my $field_names = delete $layout->{fields} ){ + map{ push(@container_fields, $_) } grep { defined } + map { delete $fields{$_} } @$field_names; + } + $containers{$name} = Container->new( + ctx => $self->ctx, + location => join( '-', $self->location, 'container', $name ), + fields => \@container_fields, + %$layout, + ); + } + if( keys %fields ){ + my @leftovers = grep { exists $fields{$_} } @$ordered_field_names; + push(@{ $containers{_}->fields }, @fields{@leftovers} ); + } + + #only return containers with at least one field + return [ grep { scalar(@{ $_->fields }) } @containers{@container_order} ]; +} -sub _build_excluded_fields { [] }; -sub _build_builder_cache { {} }; sub _build_fields { my ($self) = @_; my $obj = $self->model; @@ -48,10 +96,11 @@ sub _build_fields { my $attr = $param_attrs{$field_name}; my $meth = $self->builder_cache->{$field_name} ||= $self->get_builder_for($attr); my $field = $self->$meth($attr, ($args->{$field_name} || {})); - push(@fields, $field) if $field; + next unless $field; + push(@fields, $field); } return \@fields; -}; +} sub _build_computed_field_order { my ($self) = @_; @@ -60,7 +109,7 @@ sub _build_computed_field_order { my @names = grep { $_ !~ /^_/ && !exists($excluded{$_})} map { $_->name } grep { defined $_->get_read_method } $self->model->parameter_attributes; return $self->sort_by_spec($self->field_order || [], \@names); -}; +} override child_event_sinks => sub { return ( @{shift->fields}, super()); @@ -109,7 +158,8 @@ sub get_builder_for { } else { confess "Can't build field ${attr} without $builder method or type constraint"; } -}; +} + sub _build_simple_field { my ($self, %args) = @_; my $class = delete $args{class}; @@ -125,20 +175,23 @@ sub _build_simple_field { location => join('-', $self->location, 'field', $field_name), %args ); -}; +} + sub _build_fields_for_type_Num { my ($self, $attr, $args) = @_; $self->_build_simple_field(attribute => $attr, class => Number, %$args); -}; +} + sub _build_fields_for_type_Int { my ($self, $attr, $args) = @_; #XXX $self->_build_simple_field(attribute => $attr, class => Integer, %$args); -}; +} + sub _build_fields_for_type_Bool { my ($self, $attr, $args) = @_; $self->_build_simple_field(attribute => $attr, class => Boolean, %$args); -}; +} #XXX sub _build_fields_for_type_Reaction_Types_Core_Password { return }; @@ -147,41 +200,47 @@ sub _build_fields_for_type_Str { my ($self, $attr, $args) = @_; #XXX $self->_build_simple_field(attribute => $attr, class => String, %$args); -}; +} + sub _build_fields_for_type_Reaction_Types_Core_SimpleStr { my ($self, $attr, $args) = @_; $self->_build_simple_field(attribute => $attr, class => String, %$args); -}; +} + sub _build_fields_for_type_Reaction_Types_DateTime_DateTime { my ($self, $attr, $args) = @_; $self->_build_simple_field(attribute => $attr, class => DateTime, %$args); -}; +} + sub _build_fields_for_type_Enum { my ($self, $attr, $args) = @_; #XXX $self->_build_simple_field(attribute => $attr, class => String, %$args); -}; +} + sub _build_fields_for_type_ArrayRef { my ($self, $attr, $args) = @_; $self->_build_simple_field(attribute => $attr, class => Array, %$args); -}; +} + sub _build_fields_for_type_Reaction_Types_File_File { my ($self, $attr, $args) = @_; $self->_build_simple_field(attribute => $attr, class => File, %$args); -}; +} + sub _build_fields_for_type_Reaction_InterfaceModel_Object { my ($self, $attr, $args) = @_; #XXX $self->_build_simple_field(attribute => $attr, class => RelatedObject, %$args); -}; +} + sub _build_fields_for_type_Reaction_InterfaceModel_Collection { my ($self, $attr, $args) = @_; $self->_build_simple_field(attribute => $attr, class => Collection, %$args); -}; +} __PACKAGE__->meta->make_immutable; - 1; __END__; diff --git a/lib/Reaction/UI/Widget/Action.pm b/lib/Reaction/UI/Widget/Action.pm index 32ca4b7..2957317 100644 --- a/lib/Reaction/UI/Widget/Action.pm +++ b/lib/Reaction/UI/Widget/Action.pm @@ -3,9 +3,7 @@ package Reaction::UI::Widget::Action; use Reaction::UI::WidgetClass; use namespace::clean -except => [ qw(meta) ]; -extends 'Reaction::UI::Widget::Object'; - - +extends 'Reaction::UI::Widget::Object::Mutable'; after fragment widget { arg 'method' => $_{viewport}->method; diff --git a/lib/Reaction/UI/Widget/Object.pm b/lib/Reaction/UI/Widget/Object.pm index dc898cc..a44a66d 100644 --- a/lib/Reaction/UI/Widget/Object.pm +++ b/lib/Reaction/UI/Widget/Object.pm @@ -4,7 +4,15 @@ use Reaction::UI::WidgetClass; use namespace::clean -except => [ qw(meta) ]; +implements fragment container_list { + render container => over $_{viewport}->containers; +}; + +implements fragment container { + render 'viewport'; +}; +#we won't be needing these anymore implements fragment field_list { render field => over $_{viewport}->fields; }; @@ -15,7 +23,6 @@ implements fragment field { __PACKAGE__->meta->make_immutable; - 1; __END__; @@ -28,9 +35,19 @@ Reaction::UI::Widget::Object =head1 FRAGMENTS +=head2 container_list + +Sequentially renders the C<fields> of the viewport; + +=head2 container + +Renders the C<field> viewport passed by C<field_list> + +=head1 DEPRECATED FRAGMENTS + =head2 field_list -Sequentially renders the C<fields> of the viewport in the C<computed_field_order> +Sequentially renders the C<fields> of the viewport; =head2 field diff --git a/share/skin/base/layout/action.tt b/share/skin/base/layout/action.tt index 6fda5a1..5ef48cd 100644 --- a/share/skin/base/layout/action.tt +++ b/share/skin/base/layout/action.tt @@ -3,7 +3,7 @@ <div class="action_form"> <form action="" method="[% method %]" enctype="multipart/form-data"> [% header %] - [% field_list %] + [% container_list %] [% buttons %] [% footer %] </form> @@ -11,13 +11,11 @@ =for layout header -=for layout field_list +=for layout container_list -<div class="action_field_list"> - [% call_next %] -</div> +[% call_next %] -=for layout field +=for layout container [% call_next %] diff --git a/share/skin/base/layout/object.tt b/share/skin/base/layout/object.tt index 00816d3..8a5074a 100644 --- a/share/skin/base/layout/object.tt +++ b/share/skin/base/layout/object.tt @@ -1,13 +1,10 @@ =for layout widget -<div class="object_field_list"> - [% field_list %] -</div> +[% container_list %] -=for layout field +=for layout container -<span class="object_field"> - [% call_next %] -</span> +[% call_next %] =cut + diff --git a/share/skin/default/layout/action.tt b/share/skin/default/layout/action.tt index 4c32a37..a18e51d 100644 --- a/share/skin/default/layout/action.tt +++ b/share/skin/default/layout/action.tt @@ -1,6 +1,6 @@ =extends NEXT -=for layout field +=for layout container [% call_next %] <br /> diff --git a/share/skin/default/layout/object.tt b/share/skin/default/layout/object.tt index 20dee31..0f32321 100644 --- a/share/skin/default/layout/object.tt +++ b/share/skin/default/layout/object.tt @@ -1,6 +1,6 @@ =extends NEXT -=for layout field +=for layout container [% call_next %] <br> diff --git a/t/lib/RTest/TestDB/Bar.pm b/t/lib/RTest/TestDB/Bar.pm index 4359d87..36faca8 100644 --- a/t/lib/RTest/TestDB/Bar.pm +++ b/t/lib/RTest/TestDB/Bar.pm @@ -5,12 +5,13 @@ use base qw/DBIx::Class/; use metaclass 'Reaction::Meta::Class'; use Moose; +use aliased 'RTest::TestDB::Foo'; use Reaction::Types::Core qw/NonEmptySimpleStr/; use Reaction::Types::DateTime qw//; use Reaction::Types::File 'File'; has 'name' => (isa => NonEmptySimpleStr, is => 'rw', required => 1); -has 'foo' => (isa => 'RTest::TestDB::Foo', is => 'rw', required => 1); +has 'foo' => (isa => Foo, is => 'rw', required => 1); has 'published_at' => (isa => Reaction::Types::DateTime::DateTime, is => 'rw'); has 'avatar' => (isa => File, is => 'rw'); @@ -30,7 +31,7 @@ __PACKAGE__->add_columns( __PACKAGE__->set_primary_key('name'); __PACKAGE__->belongs_to( - 'foo' => 'RTest::TestDB::Foo', + 'foo' => Foo, { 'foreign.id' => 'self.foo_id' } ); |