simple mutable fields now use value_string (ChooseMany unconverted)
[catagits/Reaction.git] / lib / Reaction / UI / ViewPort / Field / TimeRange.pm
CommitLineData
7adfd53f 1package Reaction::UI::ViewPort::Field::TimeRange;
2
3use Reaction::Class;
4use Reaction::Types::DateTime;
5use DateTime;
6use DateTime::SpanSet;
7use Time::ParseDate ();
8
9class TimeRange is 'Reaction::UI::ViewPort::Field', which {
10
e739c9a2 11 has '+value' => (isa => 'SpanSet');
6ab43711 12
13 #has '+layout' => (default => 'timerange');
14
15 has value_string =>
7adfd53f 16 (isa => 'Str', is => 'rw', lazy_fail => 1, trigger_adopt('value_string'));
6ab43711 17
7adfd53f 18 has delete_label => (
19 isa => 'Str', is => 'rw', required => 1, default => sub { 'Delete' },
20 );
6ab43711 21
7adfd53f 22 has parent => (
23 isa => 'Reaction::UI::ViewPort::TimeRangeCollection',
24 is => 'ro',
25 required => 1,
26 is_weak_ref => 1
27 );
6ab43711 28
89939ff9 29 implements _build_value_string => as {
7adfd53f 30 my $self = shift;
31 #return '' unless $self->has_value;
32 #return $self->value_string;
33 };
6ab43711 34
7adfd53f 35 implements value_array => as {
36 my $self = shift;
37 return split(',', $self->value_string);
38 };
6ab43711 39
7adfd53f 40 implements adopt_value_string => as {
41 my ($self) = @_;
42 my @values = $self->value_array;
43 for my $idx (0 .. 3) { # last value is repeat
44 if (length $values[$idx]) {
45 my ($epoch) = Time::ParseDate::parsedate($values[$idx], UK => 1);
46 $values[$idx] = DateTime->from_epoch( epoch => $epoch );
6ab43711 47 }
7adfd53f 48 }
49 $self->value($self->range_to_spanset(@values));
50 };
6ab43711 51
7adfd53f 52 implements range_to_spanset => as {
53 my ($self, $time_from, $time_to, $repeat_from, $repeat_to, $pattern) = @_;
54 my $spanset = DateTime::SpanSet->empty_set;
55 if (!$pattern || $pattern eq 'none') {
56 my $span = DateTime::Span->from_datetimes(
57 start => $time_from, end => $time_to
58 );
59 $spanset = $spanset->union( $span );
60 } else {
61 my $duration = $time_to - $time_from;
62 my %args = ( days => $time_from->day + 2,
63 hours => $time_from->hour,
64 minutes => $time_from->minute,
65 seconds => $time_from->second );
6ab43711 66
7adfd53f 67 delete $args{'days'} if ($pattern eq 'daily');
68 delete @args{qw/hours days/} if ($pattern eq 'hourly');
69 $args{'days'} = $time_from->day if ($pattern eq 'monthly');
70 my $start_set = DateTime::Event::Recurrence->$pattern( %args );
71 my $iter = $start_set->iterator( start => $repeat_from, end => $repeat_to );
72 while ( my $dt = $iter->next ) {
73 my $endtime = $dt + $duration;
74 my $new_span = DateTime::Span->from_datetimes(
75 start => $dt,
76 end => $endtime
77 );
78 $spanset = $spanset->union( $new_span );
79 }
80 }
81 return $spanset;
82 };
6ab43711 83
7adfd53f 84 implements delete => as {
85 my ($self) = @_;
86 $self->parent->remove_range_vp($self);
87 };
6ab43711 88
7adfd53f 89 override accept_events => sub { ('value_string', 'delete', super()) };
90
91};
92
6ab43711 931;
7adfd53f 94
95=head1 NAME
96
97Reaction::UI::ViewPort::Field::TimeRange
98
99=head1 SYNOPSIS
100
101=head1 DESCRIPTION
102
103=head1 METHODS
104
105=head2 value
106
107 Accessor for a L<DateTime::SpanSet> object.
108
109=head2 value_string
110
111 Returns: Encoded range string representing the value.
112
113=head2 value_array
114
115 Returns: Arrayref of the elements of C<value_string>.
116
117=head2 parent
118
119 L<Reaction::UI::ViewPort::TimeRangeCollection> object.
120
121=head2 range_to_spanset
122
123 Arguments: $self, $time_from, $time_to, $repeat_from, $repeat_to, $pattern
124 where $time_from, $time_to, $repeat_from, $repeat_to are L<DateTime>
125 objects, and $pattern is a L<DateTime::Event::Recurrence> method name
126
127 Returns: $spanset
128
129=head2 delete
130
131 Removes TimeRange from C<parent> collection.
132
133=head2 delete_label
134
135 Label for the delete option. Default: 'Delete'.
136
137=head1 SEE ALSO
138
139=head2 L<Reaction::UI::ViewPort::Field>
140
141=head2 L<Reaction::UI::ViewPort::TimeRangeCollection>
142
143=head1 AUTHORS
144
145See L<Reaction::Class> for authors.
146
147=head1 LICENSE
148
149See L<Reaction::Class> for the license.
150
151=cut