diff options
author | matthewt <matthewt@03d0b0b2-0e1a-0410-a411-fdb2f4bd65d7> | 2007-11-29 19:05:13 +0000 |
---|---|---|
committer | matthewt <matthewt@03d0b0b2-0e1a-0410-a411-fdb2f4bd65d7> | 2007-11-29 19:05:13 +0000 |
commit | aa8c0c904641fa20c5f50882d09c1502aae19b3a (patch) | |
tree | 3f8db7deb47c9a7918c122347b42471781b1371d | |
parent | d7b00a506917b0fc21c7781985ea65293870fbbc (diff) | |
download | reaction-aa8c0c904641fa20c5f50882d09c1502aae19b3a.tar.gz reaction-aa8c0c904641fa20c5f50882d09c1502aae19b3a.zip |
listview ported bar pager
-rw-r--r-- | Makefile.PL | 2 | ||||
-rw-r--r-- | lib/Reaction/UI/LayoutSet.pm | 58 | ||||
-rw-r--r-- | lib/Reaction/UI/ViewPort/GridView/Role/Order.pm | 11 | ||||
-rw-r--r-- | lib/Reaction/UI/Widget.pm | 2 | ||||
-rw-r--r-- | lib/Reaction/UI/Widget/GridView.pm | 24 | ||||
-rw-r--r-- | lib/Reaction/UI/Widget/GridView/Action.pm | 8 | ||||
-rw-r--r-- | lib/Reaction/UI/Widget/GridView/Entity.pm | 15 | ||||
-rw-r--r-- | lib/Reaction/UI/Widget/GridView/Entity/WithActions.pm | 18 | ||||
-rw-r--r-- | lib/Reaction/UI/Widget/ListView.pm | 76 | ||||
-rw-r--r-- | lib/Reaction/UI/Widget/Value.pm | 11 | ||||
-rw-r--r-- | lib/Reaction/UI/Widget/Value/Collection.pm | 16 | ||||
-rw-r--r-- | share/skin/default/layout/grid_view.tt | 20 | ||||
-rw-r--r-- | share/skin/default/layout/grid_view/action.tt | 2 | ||||
-rw-r--r-- | share/skin/default/layout/grid_view/entity.tt | 10 | ||||
-rw-r--r-- | share/skin/default/layout/grid_view/entity/with_actions.tt | 21 | ||||
-rw-r--r-- | share/skin/default/layout/list_view.tt | 91 |
16 files changed, 166 insertions, 219 deletions
diff --git a/Makefile.PL b/Makefile.PL index ee71807..335d847 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -28,7 +28,7 @@ requires 'Email::Send'; requires 'Email::MIME'; requires 'Email::MIME::Creator'; requires 'Text::CSV_XS'; -requires 'Devel::Declare' => '0.001004'; +requires 'Devel::Declare' => '0.001006'; catalyst; diff --git a/lib/Reaction/UI/LayoutSet.pm b/lib/Reaction/UI/LayoutSet.pm index 68d23d1..4a9c533 100644 --- a/lib/Reaction/UI/LayoutSet.pm +++ b/lib/Reaction/UI/LayoutSet.pm @@ -12,7 +12,11 @@ class LayoutSet which { has 'source_file' => (is => 'rw', lazy_fail => 1); has 'file_extension'=> (isa => 'Str', is => 'rw', lazy_build => 1); - has 'widget_class' => (is => 'rw', lazy_fail => 1); + has 'widget_class' => ( + is => 'rw', lazy_fail => 1, predicate => 'has_widget_class' + ); + + has 'super' => (is => 'rw', predicate => 'has_super'); implements _build_file_extension => as { 'html' }; @@ -20,46 +24,72 @@ class LayoutSet which { my ($self, $args) = @_; my @path = @{$args->{search_path}||[]}; confess "No search_path provided" unless @path; + confess "No view object provided" unless $args->{view}; my $found; my $ext = $self->file_extension; SEARCH: foreach my $path (@path) { my $cand = $path->file($self->name . ".${ext}"); #print STDERR $cand,"\n"; if ($cand->stat) { - $self->_load_file($cand); + $self->_load_file($cand, $args); $found = 1; last SEARCH; } } confess "Unable to load file for LayoutSet ".$self->name unless $found; - confess "No view object provided" unless $args->{view}; - $self->widget_class($args->{view}->widget_class_for($self)); + unless ($self->has_widget_class) { + $self->widget_class($args->{view}->widget_class_for($self)); + } }; implements 'widget_order_for' => as { my ($self, $name) = @_; - if ($self->has_layout($name)) { - return ([ $self->widget_class, $self ]); - } else { - return (); - } + return ( + ($self->has_layout($name) + ? ([ $self->widget_class, $self ]) #; + : ()), + ($self->has_super + ? ($self->super->widget_order_for($name)) + : ()), + ); }; - implements 'layout_names' => as { [ keys %{shift->layouts} ] }; + implements 'layout_names' => as { + my ($self) = @_; + my %seen; + return [ + grep { !$seen{$_}++ } + keys %{shift->layouts}, + ($self->has_super + ? (@{$self->super->layout_names}) + : ()) + ]; + }; implements 'has_layout' => as { exists $_[0]->layouts->{$_[1]} }; implements '_load_file' => as { - my ($self, $file) = @_; + my ($self, $file, $build_args) = @_; my $data = $file->slurp; my $layouts = $self->layouts; # cheesy match for "=for layout name ... =something" # final split group also handles last in file, (?==) is lookahead # assertion for '=' so "=for layout name1 ... =for layout name2" # doesn't have the match pos go past the latter = and lose name2 - while ($data =~ m/=for layout (.*?)\n(.+?)(?:\n(?==)|$)/sg) { - my ($fname, $text) = ($1, $2); - $layouts->{$fname} = $text; + while ($data =~ m/=(.*?)\n(.*?)(?:\n(?==)|$)/sg) { + my ($data, $text) = ($1, $2); + + if ($data =~ /^for layout (\S+)/) { + my $fname = $1; + $layouts->{$fname} = $text; + } elsif ($data =~ /^extends (\S+)/) { + my $super_name = $1; + $self->super($build_args->{view}->create_layout_set($super_name)) + } elsif ($data =~ /^cut/) { + # no-op + } else { + confess "Unparseable directive ${data}"; + } } $self->source_file($file); }; diff --git a/lib/Reaction/UI/ViewPort/GridView/Role/Order.pm b/lib/Reaction/UI/ViewPort/GridView/Role/Order.pm index 86b505e..2c5768d 100644 --- a/lib/Reaction/UI/ViewPort/GridView/Role/Order.pm +++ b/lib/Reaction/UI/ViewPort/GridView/Role/Order.pm @@ -7,6 +7,17 @@ role Order, which { has order_by => (isa => 'Str', is => 'rw', trigger_adopt('order_by')); has order_by_desc => (isa => 'Int', is => 'rw', trigger_adopt('order_by'), lazy_build => 1); + before order_by => sub { + if (@_ > 1) { + my ($self, $val) = @_; + confess "invalid column name for order_by" + unless grep { $val eq $_ } $self->collection + ->_source_resultset + ->result_source + ->columns; + } + }; + implements _build_order_by_desc => as { 0 }; implements adopt_order_by => as { diff --git a/lib/Reaction/UI/Widget.pm b/lib/Reaction/UI/Widget.pm index a5171d1..9d1e08e 100644 --- a/lib/Reaction/UI/Widget.pm +++ b/lib/Reaction/UI/Widget.pm @@ -93,6 +93,7 @@ class Widget which { my ($self, $do_render, $args, $new_args) = @_; my $vp = $args->{'_'}; my ($widget, $merge_args) = $self->view->render_viewport_args($vp); + delete @{$new_args}{keys %$new_args}; # fresh start @{$new_args}{keys %$merge_args} = values %$merge_args; $do_render->(Widget, $widget, 'widget'); }; @@ -100,6 +101,7 @@ class Widget which { implements '_fragment_widget' => as { my ($self, $do_render, $args, $new_args) = @_; my $merge = $self->basic_layout_args; +#warn "Merge: ".join(', ', keys %$merge)." into: ".join(', ', keys %$new_args); delete @{$merge}{keys %$new_args}; # nuke 'self' and 'viewport' @{$new_args}{keys %$merge} = values %$merge; }; diff --git a/lib/Reaction/UI/Widget/GridView.pm b/lib/Reaction/UI/Widget/GridView.pm index 1f73adb..c7c2530 100644 --- a/lib/Reaction/UI/Widget/GridView.pm +++ b/lib/Reaction/UI/Widget/GridView.pm @@ -3,19 +3,23 @@ package Reaction::UI::Widget::GridView; use Reaction::UI::WidgetClass; class GridView, which { - fragment widget [ qw/header body footer/ ]; - fragment header [ 'header_row' ]; - fragment header_row [ header_cell => over func('viewport', 'field_order'), - { labels => func(viewport => 'field_labels') } ]; - fragment header_cell [ string { $_{labels}->{$_} } ], { field_name => $_ }; + implements fragment header_cells { + arg 'labels' => $_{viewport}->field_labels; + render header_cell => over $_{viewport}->field_order; + }; - fragment footer [ 'footer_row' ]; - fragment footer_row [ footer_cell => over func('viewport', 'field_order'), - { labels => func(viewport => 'field_labels') } ]; - fragment footer_cell [ string { $_{labels}->{$_} } ], { field_name => $_ }; + implements fragment body_rows { + render body_row => over $_{viewport}->entities; + }; - fragment body [ viewport => over func('viewport','entities')]; + implements fragment body_row { + render 'viewport'; + }; + + implements fragment header_cell { + arg label => $_{labels}->{$_}; + }; }; diff --git a/lib/Reaction/UI/Widget/GridView/Action.pm b/lib/Reaction/UI/Widget/GridView/Action.pm index a1988e5..d5336f3 100644 --- a/lib/Reaction/UI/Widget/GridView/Action.pm +++ b/lib/Reaction/UI/Widget/GridView/Action.pm @@ -3,8 +3,12 @@ package Reaction::UI::Widget::GridView::Action; use Reaction::UI::WidgetClass; class Action, which { - fragment widget [ string{ "DUMMY" } ], - { uri => func(viewport => 'uri'), label => func(viewport => 'label') }; + + before fragment widget { + arg uri => $_{viewport}->uri; + arg label => $_{viewport}->label; + }; + }; 1; diff --git a/lib/Reaction/UI/Widget/GridView/Entity.pm b/lib/Reaction/UI/Widget/GridView/Entity.pm index 1530bf5..3efc1a4 100644 --- a/lib/Reaction/UI/Widget/GridView/Entity.pm +++ b/lib/Reaction/UI/Widget/GridView/Entity.pm @@ -3,12 +3,15 @@ package Reaction::UI::Widget::GridView::Entity; use Reaction::UI::WidgetClass; class Entity, which { - #this could be flattened if i could do: - # fragment widget [field => over sub{ $_{self}->viewport->fields } ]; - #to be honest, I think that the key viewport should be available by default in %_ - fragment widget [ 'field_list' ]; - fragment field_list [ field => over func('viewport', 'fields') ]; - fragment field [ 'viewport' ]; + + implements fragment field_list { + render 'field' => over $_{viewport}->fields; + }; + + implements fragment field { + render 'viewport'; + }; + }; 1; diff --git a/lib/Reaction/UI/Widget/GridView/Entity/WithActions.pm b/lib/Reaction/UI/Widget/GridView/Entity/WithActions.pm index 66db4b9..1684356 100644 --- a/lib/Reaction/UI/Widget/GridView/Entity/WithActions.pm +++ b/lib/Reaction/UI/Widget/GridView/Entity/WithActions.pm @@ -2,14 +2,16 @@ package Reaction::UI::Widget::GridView::Entity::WithActions; use Reaction::UI::WidgetClass; -#should I use inheritance here?? -class WithActions, which { - fragment widget [ qw(field_list actions) ]; - fragment field_list [ field => over func('viewport', 'fields') ]; - fragment field [ 'viewport' ]; - - fragment actions [ action => over func(viewport => 'actions')]; - fragment action [ 'viewport' ]; +class WithActions, is 'Reaction::UI::Widget::GridView::Entity', which { + + implements fragment actions { + render action => over $_{viewport}->actions; + }; + + implements fragment action { + render 'viewport'; + }; + }; 1; diff --git a/lib/Reaction/UI/Widget/ListView.pm b/lib/Reaction/UI/Widget/ListView.pm index 81b652e..9562900 100644 --- a/lib/Reaction/UI/Widget/ListView.pm +++ b/lib/Reaction/UI/Widget/ListView.pm @@ -3,68 +3,32 @@ package Reaction::UI::Widget::ListView; use Reaction::UI::WidgetClass; class ListView is 'Reaction::UI::Widget::GridView', which { - fragment widget [ qw/pager header body footer actions/, - { - pager => sub{ $_{viewport}->pager }, - object_action_count => sub{ $_{viewport}->object_action_count }, - #^^ it's ugly, i know, but i gotsto - } - ]; - fragment pager - [ qw/first_page previous_page current_page next_page last_page page_list/, - { - first_page => sub{ $_{pager}->first_page }, - previous_page => sub{ $_{pager}->previous_page || $_{pager}->last_page }, - current_page => sub{ $_{pager}->current_page }, - next_page => sub{ $_{pager}->next_page || $_{pager}->first_page }, - last_page => sub{ $_{pager}->last_page }, - page_list => sub{ [$_{pager}->first_page .. $_{pager}->last_page] }, - } - ]; - - fragment first_page [ string{ "First" } ], - { uri => sub{ $_{self}->connect_uri( {page => $_{first_page} }, $_{viewport} ) } }; - - fragment previous_page [ string{ "Previous" } ], - { uri => sub{ $_{self}->connect_uri( {page => $_{previous_page} }, $_{viewport} ) } }; - - fragment current_page [ string{ "Current" } ], - { uri => sub{ $_{self}->connect_uri( {page => $_{current_page} }, $_{viewport} ) } }; - - fragment next_page [ string{ "Next" } ], - { uri => sub{ $_{self}->connect_uri( {page => $_{next_page} }, $_{viewport} ) } }; - - fragment last_page [ string{ "Last" } ], - { uri => sub{ $_{self}->connect_uri( {page => $_{last_page} }, $_{viewport} ) } }; - - fragment page_list [ page => over $_{page_list} ]; - fragment page [ string{ $_ } ], - { uri => sub{ $_{self}->connect_uri( {page => $_ }, $_{viewport} ) } }; + implements fragment actions { + render action => over $_{viewport}->actions; + }; - fragment actions [ action => over func(viewport => 'actions') ]; - fragment action [ 'viewport' ]; + implements fragment action { + render 'viewport'; + }; - fragment header_cell [ string { $_{labels}->{$_} } ], - { uri => sub{ - my $ev = {order_by => $_, order_by_desc => $_{viewport}->order_by_desc ? 0 : 1 }; - return $_{self}->connect_uri($ev, $_{viewport}); - } + around fragment header_cell { + arg order_uri => event_uri { + order_by => $_, + order_by_desc => ((($_{viewport}->order_by||'') ne $_ + || $_{viewport}->order_by_desc) ? 0 : 1) }; + call_next; + }; - fragment footer_cell [ string { $_{labels}->{$_} } ], - { uri => sub{ - my $ev = {order_by => $_, order_by_desc => $_{viewport}->order_by_desc ? 0 : 1 }; - return $_{self}->connect_uri($ev, $_{viewport}); - } - }; + after fragment header_cells { + if ($_{viewport}->object_action_count) { + render 'header_action_cell'; + } + }; - #this needs to be cleaned up and moved out - implements connect_uri => as{ - my ($self, $events, $vp) = @_; - my $ctx = $vp->ctx; - my %args = map{ $vp->event_id_for($_) => $events->{$_} } keys %$events; - return $ctx->req->uri_with(\%args); + implements fragment header_action_cell { + arg 'col_count' => $_{viewport}->object_action_count; }; }; diff --git a/lib/Reaction/UI/Widget/Value.pm b/lib/Reaction/UI/Widget/Value.pm index 88d7eb6..48d362d 100644 --- a/lib/Reaction/UI/Widget/Value.pm +++ b/lib/Reaction/UI/Widget/Value.pm @@ -3,12 +3,11 @@ package Reaction::UI::Widget::Value; use Reaction::UI::WidgetClass; class Value, which { - fragment widget [ string {""} ], - { value => sub{ - my $vp = $_{viewport}; - $vp->can('value_string') ? $vp->value_string : $vp->value; - } - }; + + before fragment widget { + arg value => $_{viewport}->value_string; + }; + }; 1; diff --git a/lib/Reaction/UI/Widget/Value/Collection.pm b/lib/Reaction/UI/Widget/Value/Collection.pm index e87d881..d081216 100644 --- a/lib/Reaction/UI/Widget/Value/Collection.pm +++ b/lib/Reaction/UI/Widget/Value/Collection.pm @@ -3,9 +3,19 @@ package Reaction::UI::Widget::Value::Collection; use Reaction::UI::WidgetClass; class Collection, which { - fragment widget [ qw/list/ ]; - fragment list [ item => over func('viewport', 'value_names') ]; - fragment item [ string {""} ], { value => $_ }; + + before fragment widget { + arg 'label' => $_{viewport}->label; + }; + + implements fragment list { + render 'item' => over $_{viewport}->value_names; + }; + + implements fragment item { + arg 'name' => $_; + }; + }; 1; diff --git a/share/skin/default/layout/grid_view.tt b/share/skin/default/layout/grid_view.tt index 0015713..310fe66 100644 --- a/share/skin/default/layout/grid_view.tt +++ b/share/skin/default/layout/grid_view.tt @@ -9,37 +9,37 @@ =for layout header <thead> - [% content %] + [% header_row %] </thead> =for layout header_row <tr> - [% content %] + [% header_cells %] </tr> =for layout header_cell -<th> [% content %] </th> +<th> [% header_cell_contents %] </th> + +=for layout header_cell_contents + +[% label %] =for layout footer <tfoot> - [% content %] + [% footer_row %] </tfoot> =for layout footer_row -<tr> [% content %] </tr> - -=for layout footer_cell - -<td> [% content %] </td> +[% header_row %] =for layout body <tbody> - [% content %] + [% body_rows %] </tbody> =cut diff --git a/share/skin/default/layout/grid_view/action.tt b/share/skin/default/layout/grid_view/action.tt index 4de7797..7c07d31 100644 --- a/share/skin/default/layout/grid_view/action.tt +++ b/share/skin/default/layout/grid_view/action.tt @@ -1,3 +1,3 @@ =for layout widget - <a href="[% uri %]">[% label | html %]</a> + <a href="[% uri %]">[% label %]</a> =cut diff --git a/share/skin/default/layout/grid_view/entity.tt b/share/skin/default/layout/grid_view/entity.tt index c66af93..9cf24e2 100644 --- a/share/skin/default/layout/grid_view/entity.tt +++ b/share/skin/default/layout/grid_view/entity.tt @@ -1,15 +1,11 @@ =for layout widget <tr> - [% content %] -<tr> - -=for layout field_list - -[% content %] + [% field_list %] +</tr> =for layout field -<td>[% content %]</td> +<td>[% call_next %]</td> =cut diff --git a/share/skin/default/layout/grid_view/entity/with_actions.tt b/share/skin/default/layout/grid_view/entity/with_actions.tt index 438a168..7f84147 100644 --- a/share/skin/default/layout/grid_view/entity/with_actions.tt +++ b/share/skin/default/layout/grid_view/entity/with_actions.tt @@ -1,25 +1,12 @@ -=for layout widget - -<tr> - [% field_list %] - [% actions %] -<tr> +=extends grid_view/entity =for layout field_list -[% content %] - -=for layout field - -<td>[% content %]</td> - -=for layout actions - -[% content %] +[% call_next %] +[% actions %] =for layout action -<td>[% content %]</td> - +<td>[% call_next %]</td> =cut diff --git a/share/skin/default/layout/list_view.tt b/share/skin/default/layout/list_view.tt index 7cd3cc4..d74e2b4 100644 --- a/share/skin/default/layout/list_view.tt +++ b/share/skin/default/layout/list_view.tt @@ -1,100 +1,35 @@ +=extends grid_view + =for layout widget [% pager %] -<table> - [% header %] - [% body %] - [% footer %] -</table> +[% call_next %] [% pager %] [% actions %] -=for layout header - -<thead> - [% content %] -</thead> - -=for layout header_row - -<tr> - [% content %] - [% IF object_action_count %] - <th colspan="[% object_action_count %]"> Actions </th> - [% END %] -</tr> - -=for layout header_cell - -<th> <a href="[% uri %]"> [% content | html %] </a> </th> - -=for layout footer +=for layout header_action_cell -<tfoot> - [% content %] -</tfoot> +<th colspan="[% col_count %]"> Actions </th> -=for layout footer_row +=for layout header_cell_contents -<tr> - [% content %] - [% IF object_action_count %] - <th colspan="[% object_action_count %]"> Actions </th> - [% END %] -</tr> - -=for layout footer_cell - -<th> <a href="[% uri %]"> [% content | html %] </a> </th> - -=for layout body - -<tbody> - [% content %] -</tbody> - -=for layout pager - -<ul class="pager"> - <li>[% first_page %]</li> - <li>[% previous_page %]</li> - <li>[% page_list %]</li> - <li>[% next_page %]</li> - <li>[% last_page %]</li> -</ul> - -=for layout page_list -[% content %] - -=for layout page -<li> <a href="[% uri | html %]">[% content | html %]</a> </li> - -=for layout first_page -<a href="[% uri | html %]">[% content | html %]</a> - -=for layout previous_page -<a href="[% uri | html %]">[% content | html %]</a> - -=for layout current_page -<a href="[% uri | html %]">[% content | html %]</a> - -=for layout next_page -<a href="[% uri | html %]">[% content | html %]</a> - -=for layout last_page -<a href="[% uri | html %]">[% content | html %]</a> +<a href="[% order_uri %]">[% call_next %]</a> =for layout actions <div class="collection_actions"> <ul> - [% content %] + [% call_next %] </ul> </div> =for layout action -<li>[% content %]</li> +<li>[% call_next %]</li> + +=for layout pager + +<p>Pager would be here. But it isn't.</p> =cut |