tweaks for SearchableListViewContainer
[catagits/Reaction.git] / lib / Reaction / UI / ViewPort / SearchableListViewContainer.pm
1 package Reaction::UI::ViewPort::SearchableListViewContainer;
2 use Reaction::Class;
3
4 #use aliased 'Reaction::InterfaceModel::Search::Spec', 'SearchSpec';
5 use aliased 'Reaction::InterfaceModel::Action::Search::UpdateSpec', 'UpdateSearchSpec';
6 use aliased 'Reaction::UI::ViewPort::ListViewWithSearch';
7 use aliased 'Reaction::UI::ViewPort::Action' => 'ActionVP';
8 use aliased 'Reaction::UI::ViewPort';
9 use aliased 'Reaction::UI::ViewPort::Collection::Role::Pager', 'PagerRole';
10
11 use Method::Signatures::Simple;
12
13 use namespace::clean -except => 'meta';
14
15 extends 'Reaction::UI::ViewPort';
16
17 has 'listview' => (
18     isa => ViewPort,
19     is => 'ro', 
20     required => 1, 
21 );
22
23 has 'search_form' => (isa => ViewPort, is => 'ro', required => 1);
24
25 override BUILDARGS => sub {
26   my $args = super;
27   my $spec_event_id = $args->{location}.':search-spec';
28   my $spec_class = $args->{spec_class}
29     or confess "Argument spec_class is required";
30   my $listview_class = $args->{'listview_class'} || ListViewWithSearch;
31   my $search_form_class = $args->{'search_form_class'} || ActionVP; 
32   my $action_class = $args->{action_class}
33     or confess "Argument action_class is required";
34 #  TODO: how do we autodiscover spec classes?
35 #  $spec_class =~ s/^::/${\SearchSpec}::/;
36   Class::MOP::load_class($spec_class);
37   my $spec = do {
38     if (my $string = $args->{ctx}->req->query_params->{$spec_event_id}) {
39       $spec_class->from_string($string, $args->{spec}||{});
40     } else {
41       $spec_class->new($args->{spec}||{});
42     }
43   };
44   my $listview_location = $args->{location}.'-listview';
45   my $listview = $args->{listview} = $listview_class->new(
46     %$args,
47     layout => $args->{'listview_layout'} || 'list_view',
48     search_spec => $spec,
49     location => $listview_location,
50   );
51   $args->{search_form} = $search_form_class->new(
52     model => $action_class->new(target_model => $spec),
53     location => $args->{location}.'-search_form',
54     apply_label => 'search',
55     ctx => $args->{ctx},
56     on_apply_callback => sub {
57       my ($vp, $spec) = @_;
58       my $req = $vp->ctx->req;
59       my $new_uri = $req->uri->clone;
60       my %query = %{$req->query_parameters};
61       delete @query{grep /^\Q${listview_location}\E/, keys %query};
62       $query{$spec_event_id} = $spec->to_string;
63       $new_uri->query_form(\%query);
64       $req->uri($new_uri);
65       $listview->clear_page;
66       $listview->clear_order_by;
67     },
68     %{$args->{search}||{}}
69   );
70   $args;
71 };
72
73 override child_event_sinks => method () {
74   ((map $self->$_, 'listview', 'search_form'), super);
75 };
76
77 1;
78