Commit | Line | Data |
ddccc6a2 |
1 | package Reaction::UI::ViewPort::Collection::Role::Order; |
e22de101 |
2 | |
3 | use Reaction::Role; |
4 | |
81393881 |
5 | use namespace::clean -except => [ qw(meta) ]; |
e22de101 |
6 | |
c1b16a7d |
7 | has enable_order_by => (is => 'rw', isa => 'ArrayRef'); |
8 | has coerce_order_by => (isa => 'HashRef', is => 'rw'); |
9 | |
10 | has order_by => ( |
11 | isa => 'Str', |
12 | is => 'rw', |
13 | trigger_adopt('order_by'), |
14 | clearer => 'clear_order_by' |
15 | ); |
16 | |
17 | has order_by_desc => ( |
18 | isa => 'Int', |
19 | is => 'rw', |
20 | trigger_adopt('order_by'), |
21 | lazy_build => 1 |
22 | ); |
23 | |
24 | sub _build_order_by_desc { 0 } |
e22de101 |
25 | |
81393881 |
26 | sub adopt_order_by { |
27 | shift->clear_current_collection; |
c1b16a7d |
28 | } |
29 | |
30 | sub can_order_by { |
31 | my ($self,$order_by) = @_; |
32 | return 1 unless $self->has_enable_order_by; |
33 | return scalar grep { $order_by eq $_ } @{ $self->enable_order_by }; |
34 | } |
35 | |
36 | sub _order_search_attrs { |
37 | my $self = shift; |
38 | my %attrs; |
39 | if ($self->has_order_by) { |
40 | my $order_by = $self->order_by; |
41 | if( $self->has_coerce_order_by ){ |
42 | $order_by = $self->coerce_order_by->{$order_by} |
43 | if exists $self->coerce_order_by->{$order_by}; |
44 | } |
45 | my $key = $self->order_by_desc ? '-desc' : '-asc'; |
46 | $attrs{order_by} = { $key => $order_by }; |
47 | } |
48 | return \%attrs; |
49 | } |
b8faba69 |
50 | |
cf6fb234 |
51 | after clear_order_by => sub { |
52 | my ($self) = @_; |
53 | $self->order_by_desc(0); |
54 | $self->clear_current_collection; |
55 | }; |
56 | |
81393881 |
57 | around _build_current_collection => sub { |
58 | my $orig = shift; |
59 | my ($self) = @_; |
60 | my $collection = $orig->(@_); |
c1b16a7d |
61 | return $collection->where(undef, $self->_order_search_attrs); |
81393881 |
62 | }; |
e22de101 |
63 | |
81393881 |
64 | around accept_events => sub { ('order_by', 'order_by_desc', shift->(@_)); }; |
e22de101 |
65 | |
1d97ac81 |
66 | 1; |
e22de101 |
67 | |
1d97ac81 |
68 | __END__; |
e22de101 |
69 | |
1d97ac81 |
70 | =head1 NAME |
71 | |
72 | Reaction::UI::ViewPort::Collection::Role::Order - Order support for collections |
73 | |
74 | =head1 DESCRIPTION |
75 | |
76 | Role to add order support to collection viewports. |
77 | |
78 | =head1 ATTRIBUTES |
79 | |
80 | =head2 enable_order_by |
81 | |
82 | Re-writable array reference. Optionally use this to manually specify a list of |
83 | fields that support ordering, instead of the default of all fields. This is |
84 | useful to exclude computed values or non-indexed columns from being sortable. |
85 | |
86 | =head2 coerce_order_by |
87 | |
88 | Re-writeable hash reference. Optionally use this to manually specify the way in |
89 | which a field should be ordered. This is useful when the field name and the |
90 | query to sort it differ. E.g. for a belongs_to item: |
91 | |
92 | coerce_order_by => { foo => ['foo.last_name', 'foo.first_name'] }, |
93 | |
94 | =head2 order_by |
95 | |
96 | Re-writeable string. Optionally set it to dictate which field to use when |
97 | sorting. |
98 | |
99 | =head2 order_by_desc |
100 | |
101 | Re-writeable boolean. Optionally use descending order when sorting. Defaults to false. |
102 | |
103 | =head1 METHODS |
104 | |
105 | =head2 can_order_by $field_name |
106 | |
107 | Returns true if sorting by that field is supported, false otherwise. |
108 | |
109 | =head1 AUTHORS |
110 | |
111 | See L<Reaction::Class> for authors. |
112 | |
113 | =head1 LICENSE |
114 | |
115 | See L<Reaction::Class> for the license. |
116 | |
117 | =cut |