2 $Month => (localtime)[4]
3 $Year => (localtime)[5] + 1900
22 % if ( $start->month == $end->month ) {
23 % $title = $rtdate->GetMonth( $start->month -1 ). ' '.
24 % $start->day. '-'. $end->day. ', '. $start->year;
25 % } elsif ( $start->year == $end->year ) {
27 % $rtdate->GetMonth( $start->month -1 ). ' '. $start->day. ' - '.
28 % $rtdate->GetMonth( $end->month -1 ). ' '. $end->day. ', '. $end->year;
31 % $rtdate->GetMonth( $start->month -1 ).' '.$start->day.', '.$start->year.
33 % $rtdate->GetMonth( $end->month -1 ). ' '.$end->day. ', '. $end->year;
36 % $title = $rtdate->GetMonth($Month) . " $Year"
41 <& /Elements/Header, Title => $title &>
46 <&| /Widgets/TitleBox,
47 title => loc('Calendar for '). $title,
48 title_class=> 'inverse',
51 % my($PMonth, $PYear, $NMonth, $NYear);
52 % unless ( $WeekDay ) {
57 % ($PMonth, $PYear) = ($Month - 1, $Year);
62 <a href="<%$RT::WebPath%>/Search/<%$Embed||'Calendar.html'%>?Month=<%$PMonth%>&Year=<%$PYear%>&<%$QueryString%>">«<%$rtdate->GetMonth($PMonth)%></a>
65 <font size="+1"><% $rtdate->GetMonth($Month). " $Year" %></font>
68 % ($NMonth, $NYear) = ($Month + 1, $Year);
73 <a href="<%$RT::WebPath%>/Search/<%$Embed||'Calendar.html'%>?Month=<%$NMonth%>&Year=<%$NYear%>&<%$QueryString%>"><%$rtdate->GetMonth($NMonth)%>»</a>
79 <table class="rtxcalendar">
83 <td class="labels" colspan=<% $WeekDay ? 2 : 1 %>></td>
84 % for ( @{$week{$weekstart}} ) {
85 <th colspan=<% $WeekDay ? $slots : 1 %>><%$rtdate->GetWeekday($_)%></th>
94 <td class="controls" rowspan=<% $rowspan+1 %> valign="middle">
95 <& week_collapse, date=>$start, Month=>$OrigMonth, Year=>$OrigYear, QueryString=>$QueryString, Embed=>$Embed, &>
99 <& td_week_expand, date=>$start, Month=>$Month, Year=>$Year, QueryString=>$QueryString, Embed=>$Embed, &>
104 <td class="labels"></td>
107 % while ($date <= $end) {
109 % my $is_today = (DateTime->compare($today, $date) == 0);
110 % my $is_yesterday = (DateTime->compare($yesterday, $date) == 0);
111 % my $is_aweekago = (DateTime->compare($aweekago, $date) == 0);
113 <td colspan=<%$slots%>
115 <% $is_today ? 'today'
116 : $is_yesterday ? 'yesterday'
117 : $is_aweekago ? 'aweekago'
121 <div class="<% $is_today ? 'todays'
124 ><% $rtdate->GetMonth($date->month-1). ' '. $date->day %></div>
128 % $date = $set->next($date);
129 % if ( $date->day_of_week == $startday_of_week ) {
131 % if ( $date <= $end ) { #a second week? not going to work for week view yet
133 <td class="controls" rowspan=<% $rowspan + 1 %> valign="middle">
134 <& week_collapse, date=>$date, Month=>$OrigMonth, Year=>$OrigYear, QueryString=>$QueryString, Embed=>$Embed, &>
139 % } #while ($date <= $end)
142 % my @slots = ( [], [], [], [], [], [], [] );
143 % foreach my $row ( @week_rows ) {
150 % while ($date <= $end) {
152 % my $is_today = (DateTime->compare($today, $date) == 0);
153 % my $is_yesterday = (DateTime->compare($yesterday, $date) == 0);
154 % my $is_aweekago = (DateTime->compare($aweekago, $date) == 0);
156 %# <td colspan=<%$slots%>
157 %# class="<% $is_today ? 'today'
158 %# : $is_yesterday ? 'yesterday'
159 %# : $is_aweekago ? 'aweekago'
164 % #XXX display these in a time aware fashion
166 %#% for my $t ( @{ $Tickets{$date->strftime("%F")} } ) {
168 %# <& /Elements/CalendarEvent, Object => $t, Date => $date, DateTypes => \%DateTypes &>
170 %# <% ($sp>0) ? '<BR>'x$sp : '' |n %>
172 % for my $t ( @{ $Tickets{$date->strftime("%F")} } ) {
174 % #XXX off by 1h on daylight savings boundaries... two sundays a year
175 % my $starts = ($t->StartsObj->Unix - $t->StartsObj->SetToMidnight(Timezone=>'user'))/60;
177 % if ( $starts >= $row && $starts < ($row + $timestep) ) {
178 % #then we're a new entry, find a slot for us
180 % while ( ref($slots[$sday]->[$s]) ) { $s++ }
181 % $slots[$sday]->[$s] = [ $t->Id, $t ];
184 % #XXX also off by 1h on daylight savings boundaries
185 % my $due = $t->DueObj->Unix - $t->DueObj->SetToMidnight;
187 % if ( $due <= $row && $due > ($row + $timestep ) ) {
188 % #then find our slot and remove us
189 % @{ $slots[$sday] } =
190 % map { (!ref($_) || $_->[0] != $t->Id) ? $_ : '' }
191 % @{ $slots[$sday] };
196 % pop @{ $slots[$sday] } while @{ $slots[$sday] } && !ref($slots[$sday]->[-1]);
200 % if ( scalar(@{$slots[$sday]}) > $slots ) {
201 % #overflow situation, eek... could be handled better, how?
203 <td colspan=<%$slots%>
205 <% $is_today ? 'today'
206 : $is_yesterday ? 'yesterday'
207 : $is_aweekago ? 'aweekago'
215 % foreach my $slot ( @{ $slots[$sday] } ) {
216 % my( $id, $ticket ) = @$slot;
219 <% $is_today ? 'today'
220 : $is_yesterday ? 'yesterday'
221 : $is_aweekago ? 'aweekago'
229 % if ( scalar(@{$slots[$sday]}) < $slots ) {
231 <td colspan=<% $slots - scalar(@{$slots[$sday]}) %>
233 <% $is_today ? 'today'
234 : $is_yesterday ? 'yesterday'
235 : $is_aweekago ? 'aweekago'
244 % $date = $set->next($date);
245 % if ( $date->day_of_week == $startday_of_week ) {
247 % if ( $date <= $end ) { #a second week? not going to work for week view yet
249 <td class="controls" rowspan=<% $rowspan + 1 %> valign="middle">
250 <& week_collapse, date=>$date, Month=>$OrigMonth, Year=>$OrigYear, QueryString=>$QueryString, Embed=>$Embed, &>
256 % } #while ($date <= $end)
257 % } #foreach my $row ( @week_rows )
262 % while ($date <= $end) {
264 % my $offmonth = !$WeekDay && $date->month != ($Month + 1);
265 % my $is_today = (DateTime->compare($today, $date) == 0);
266 % my $is_yesterday = (DateTime->compare($yesterday, $date) == 0);
267 % my $is_aweekago = (DateTime->compare($aweekago, $date) == 0);
270 class="<% $offmonth ? 'offmonth'
271 : $is_today ? 'today'
272 : $is_yesterday ? 'yesterday'
273 : $is_aweekago ? 'aweekago'
277 <div class="<% $is_today ? 'todays'
278 : $offmonth ? 'offmonth'
281 ><% $date->day %></div>
283 % if ( defined($DayDisplay) && $DayDisplay =~ /^(\w+)$/ ) {
285 % my $el = "/Elements/CalendarDay$1";
286 <& $el, Tickets => $Tickets{$date->strftime("%F")},
288 DateTypes => \%DateTypes,
295 % for my $t ( @{ $Tickets{$date->strftime("%F")} } ) {
297 <& /Elements/CalendarEvent, Object => $t, Date => $date, DateTypes => \%DateTypes &>
299 <% ($sp>0) ? '<BR>'x$sp : '' |n %>
305 % $date = $set->next($date);
306 % if ( $date->day_of_week == $startday_of_week ) {
308 % if ( $date <= $end ) {
310 <& td_week_expand, date=>$date, Month=>$Month, Year=>$Year, QueryString=>$QueryString, Embed=>$Embed, &>
314 % } #while ($date <= $end)
320 % unless ( $WeekDay ) {
325 <a href="<%$RT::WebPath%>/Search/<%$Embed||'Calendar.html'%>?Month=<%$PMonth%>&Year=<%$PYear%>&<%$QueryString%>">«<%$rtdate->GetMonth($PMonth)%></a>
328 <td valign="top" align="center">
329 <form action="<%$RT::WebPath%>/Search/<%$Embed||'Calendar.html'%>?<%$QueryString%>" method="post">
331 <select name="Month">
333 <option value="<%$_%>" <% $_ == $Month ? 'selected' : ''%> ><%$rtdate->GetMonth($_)%></option>
337 % my $year = (localtime)[5] + 1900;
339 % for ( ($year-5) .. ($year+5)) {
340 <option value="<%$_%>" <% $_ == $Year ? 'selected' : ''%>><%$_%></option>
344 %# <& /Elements/Submit&>
345 <input type="submit" value="<% loc('Submit') %>" class="button" />
351 <a href="<%$RT::WebPath%>/Search/<%$Embed||'Calendar.html'%>?Month=<%$NMonth%>&Year=<%$NYear%>&<%$QueryString%>"><%$rtdate->GetMonth($NMonth)%>»</a>
358 % unless ( $Embed ) {
363 <td valign="top" rowspan=9>
365 <a href="<%$RT::WebPath%>/Prefs/Calendar.html">Calendar Preferences and Help</a>
368 % foreach my $legend (keys %legend) {
371 <img src="<%$RT::WebImagesURL%>/<%$legend%>.png" />
375 % foreach ( @{$legend{$legend}} ) {
376 <% $more++ ? ', ' : '' %>
392 'created' => ['Created'],
394 'resolved' => ['Resolved'],
395 'updated' => ['Last Updated'],
396 'created_due' => ['Created','Due'],
397 'reminder' => ['Reminders'],
398 'started' => ['Started'],
399 'starts_due' => ['Starts','Due'],
402 my $stime = RT->Config->Get('CalendarWeeklyStartMin');
403 $stime = 480 unless $stime =~ /^\d+$/; #8am
404 my $etime = RT->Config->Get('CalendarWeeklyEndMin');
405 $etime = 1080 unless $etime =~ /^\d+$/; #6pm
407 my $timestep = RT->Config->Get('CalendarWeeklySizeMin') || 30; #1/2h
408 my $rowspan = ($etime-$stime) / $timestep;
410 my $slots = RT->Config->Get('CalendarWeeklySlots') || 5;
414 while ( $wt < $etime ) { push @week_rows, $wt; $wt+=$timestep }
418 use RTx::Calendar qw(FirstDay LastDay LastDayOfWeek);
420 $Embed =~ /^[\w\.]+$/ or die 'xss';
422 my $title = loc("Calendar");
424 my @DateTypes = qw/Created Starts Started Due LastUpdated Resolved/;
426 my $rtdate = RT::Date->new($session{'CurrentUser'});
428 my $time_zone = $session{'CurrentUser'}->UserObj->Timezone
429 || RT->Config->Get('Timezone');
431 my $weekstart = 'Sunday'; #RT::SiteConfig? user pref?
433 'Saturday' => [6,0..5],
435 'Monday' => [1..6,0],
437 my $startday_of_week = ${$week{$weekstart}}[0] || 7;
438 my $endday_of_week = ${$week{$weekstart}}[-1] || 7;
440 my $today = DateTime->today( time_zone=>$time_zone );
441 my $yesterday = $today->clone->subtract( days=>1 );
442 my $aweekago = $today->clone->subtract( days=>7 );
446 $start = DateTime->new( year => $WeekYear,
447 month => $WeekMonth+1,
449 time_zone => $time_zone,
451 $end = LastDayOfWeek( $WeekYear, $WeekMonth+1, $WeekDay, $endday_of_week );
453 $start = FirstDay($Year, $Month + 1, $startday_of_week );
454 $end = LastDay ($Year, $Month + 1, $endday_of_week );
457 # use this to loop over days until $end
458 my $set = DateTime::Set->from_recurrence(
459 next => sub { $_[0]->truncate( to => 'day' )->add( days => 1 ) }
466 '/Elements/QueryString',
471 Rows => $RowsPerPage,
477 '/Elements/QueryString',
483 # Default Query and Format
484 my $TempFormat = "__Starts__ __Due__";
485 my $TempQuery = "( Status = 'new' OR Status = 'open' OR Status = 'stalled')
486 AND ( Owner = '" . $session{CurrentUser}->Id ."' OR Owner = 'Nobody' )
487 AND ( Type = 'reminder' OR 'Type' = 'ticket' )";
489 if ( my $Search = RTx::Calendar::SearchDefaultCalendar($session{CurrentUser}) ) {
490 $TempFormat = $Search->SubValue('Format');
491 $TempQuery = $Search->SubValue('Query');
494 # we overide them if needed
495 $TempQuery = $Query if $Query;
496 $TempFormat = $Format if $Format;
498 # we search all date types in Format string
499 my @Dates = grep { $TempFormat =~ m/__${_}(Relative)?__/ } @DateTypes;
501 # used to display or not a date in Element/CalendarEvent
502 my %DateTypes = map { $_ => 1 } @Dates;
504 $TempQuery .= RTx::Calendar::DatesClauses(\@Dates, $start->strftime("%F"), $end->strftime("%F"));
506 # print STDERR ("-" x 30), "\n", $TempQuery, "\n";
508 my %Tickets = RTx::Calendar::FindTickets($session{'CurrentUser'}, $TempQuery, \@Dates, $start->strftime("%F"), $end->strftime("%F"));
511 <%def td_week_expand>
516 $QueryString => undef
519 <td class="controls">
520 <a href="<%$RT::WebPath%>/Search/<%$Embed||'Calendar.html'%>?WeekDay=<% $date->day %>&WeekMonth=<% $date->month -1 %>&WeekYear=<% $date->year %>&OrigMonth=<% $Month %>&OrigYear=<% $Year %>&<%$QueryString%>"><img src="<%$RT::WebPath%>/NoAuth/images/week-expand.gif"></a>
529 $QueryString => undef
532 <a href="<%$RT::WebPath%>/Search/<%$Embed||'Calendar.html'%>?Month=<% $Month %>&Year=<% $Year %>&<%$QueryString%>"><img src="<%$RT::WebPath%>/NoAuth/images/week-collapse.gif" STYLE="height:384px;width:11px"></a>
536 % my( $min ) = shift;
537 <td class="labels"><% pretty_time($min) |n %></td>
542 return 'Midnight' if $t == 0 || $t == 1440;
543 return 'Noon' if $t == 720;
545 my $h = int( $t / 60 );
549 if ( $h == 0 || $h == 24 ) { $h = 12; }
550 elsif ( $h == 12 ) { $ap = 'PM'; }
551 elsif ( $h > 12 ) { $ap = 'PM'; $h -= 12; }
553 sprintf('%02d:%02d '.$ap, $h, $m);