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