installers (calendaring), RT#16584
[freeside.git] / rt / share / html / Search / Calendar.html
1 <%ARGS>
2 $Month       => (localtime)[4]
3 $Year        => (localtime)[5] + 1900
4 $Query       => undef
5 $Format      => undef
6 $Order       => undef
7 $OrderBy     => undef
8 $RowsPerPage => undef
9 $NewQuery    => 0
10 $WeekDay     => undef
11 $WeekMonth   => undef
12 $WeekYear    => undef
13 $OrigMonth   => undef
14 $OrigYear    => undef
15 $Embed       => undef
16 $Display     => undef
17 @DisplayArgs => ()
18 $slots       => $default_slots
19 </%ARGS>
20
21 % my $title;
22 % if ( $WeekMonth ) {
23 %   if ( $start->month == $end->month ) {
24 %     $title = $rtdate->GetMonth( $start->month -1 ). ' '.
25 %              $start->day. '-'. $end->day. ', '. $start->year;
26 %   } elsif ( $start->year == $end->year ) {
27 %     $title =
28 %       $rtdate->GetMonth( $start->month -1 ). ' '. $start->day. ' - '.
29 %       $rtdate->GetMonth( $end->month  -1 ). ' '. $end->day.  ', '. $end->year;
30 %   } else {
31 %     $title =
32 %       $rtdate->GetMonth( $start->month -1 ).' '.$start->day.', '.$start->year.
33 %       ' - '.
34 %       $rtdate->GetMonth( $end->month  -1 ). ' '.$end->day.  ', '. $end->year;
35 %   }
36 % } else {
37 %   $title = $rtdate->GetMonth($Month) . " $Year" 
38 % }
39
40 % unless ( $Embed ) {
41
42 <& /Elements/Header, Title => $title &>
43 <& /Elements/Tabs &>
44
45 % }
46
47 <&| /Widgets/TitleBox,
48      title => loc('Calendar for '). $title,
49      title_class=> 'inverse',
50      color => "#993333" &>
51
52 % my($PMonth, $PYear, $NMonth, $NYear);
53 % unless ( $WeekDay ) {
54
55     <table width="100%">
56       <tr>
57         <td align="left">
58 % ($PMonth, $PYear) = ($Month - 1, $Year);
59 % if ($PMonth < 0) {
60 %    $PYear--;
61 %    $PMonth = 11;
62 % }
63           <a href="<%$RT::WebPath%>/Search/<%$Embed||'Calendar.html'%>?Month=<%$PMonth%>&Year=<%$PYear%>&<%$QueryString%>">«<%$rtdate->GetMonth($PMonth)%></a>
64         </td>
65         <th align="center">
66           <font size="+1"><% $rtdate->GetMonth($Month). " $Year" %></font>
67         </th>
68         <td align="right">
69 % ($NMonth, $NYear) = ($Month + 1, $Year);
70 % if ($NMonth > 11) {
71 %    $NYear++;
72 %    $NMonth = 0;
73 % }
74           <a href="<%$RT::WebPath%>/Search/<%$Embed||'Calendar.html'%>?Month=<%$NMonth%>&Year=<%$NYear%>&<%$QueryString%>"><%$rtdate->GetMonth($NMonth)%>»</a>
75         </td>
76       </tr>
77     </table>
78 % }
79
80 <table class="rtxcalendar">
81
82 <thead>
83 <tr>
84 <td class="labels" colspan=<% $WeekDay ? 2 : 1 %>></td>
85 % for ( @{$week{$weekstart}} ) {
86 <th colspan=<% $WeekDay ? $slots : 1 %>><%$rtdate->GetWeekday($_)%></th>
87 % }
88 </tr>
89 </thead>
90
91 <tbody>
92 <tr>
93
94 % if ( $WeekDay ) {
95   <td class="controls" rowspan=<% $rowspan+2 %> valign="middle">
96     <& week_collapse, date=>$start, Month=>$OrigMonth, Year=>$OrigYear, QueryString=>$QueryString, Embed=>$Embed, &>
97   </td>
98   </td>
99 % } else {
100   <& td_week_expand, date=>$start, Month=>$Month, Year=>$Year, QueryString=>$QueryString, Embed=>$Embed, &>
101 % }
102
103 % if ( $WeekDay ) {
104
105     <td class="labels"></td>
106
107 %   my $date = $start;
108 %   while ($date <= $end) {
109 %
110 %     my $is_today     = (DateTime->compare($today,     $date) == 0);
111 %     my $is_yesterday = (DateTime->compare($yesterday, $date) == 0);
112 %     my $is_aweekago  = (DateTime->compare($aweekago,  $date) == 0);
113
114       <td colspan=<%$slots%>
115           class="weekly
116                  <%   $is_today     ? 'today'
117                     : $is_yesterday ? 'yesterday'
118                     : $is_aweekago  ? 'aweekago'
119                     : ''
120                  %>"
121       >
122         <div class="<%   $is_today ? 'todays'
123                        : ''
124                     %>calendardate"
125         ><% $rtdate->GetMonth($date->month-1). ' '. $date->day %></div>
126
127       </td>
128
129 %     $date = $set->next($date);
130 %     if ( $date->day_of_week == $startday_of_week ) {
131         </tr>
132 %       if ( $date <= $end ) { #a second week? not going to work for week view yet
133           <tr>
134               <td class="controls" rowspan=<% $rowspan + 2 %> valign="middle">
135                 <& week_collapse, date=>$date, Month=>$OrigMonth, Year=>$OrigYear, QueryString=>$QueryString, Embed=>$Embed, &>
136               </td>
137 %       }
138 %     }
139
140 %   } #while ($date <= $end)
141
142     </tr>
143
144     <tr>
145 %     #slot header callback
146 %     if ( defined($Display) && $Display =~ /^(\w+)$/ ) {
147 %
148 %       my $el = "/Elements/CalendarSlotHeader$1";
149         <td class="labels"></td>
150 %       for (0..6) {
151           <& $el, Date      => $date,
152                   DateTypes => \%DateTypes,
153                   slots     => $slots,
154                   @DisplayArgs,
155           &>
156 %       }
157 %     }
158     </tr>
159
160 %   foreach my $row ( @week_rows ) {
161
162       <tr>
163       <& td_time, $row &>
164
165 %     $date = $start;
166 %     my $sday = 0;
167 %     while ($date <= $end) {
168 %
169 %       my $is_today     = (DateTime->compare($today,     $date) == 0);
170 %       my $is_yesterday = (DateTime->compare($yesterday, $date) == 0);
171 %       my $is_aweekago  = (DateTime->compare($aweekago,  $date) == 0);
172
173 %     #slot callback
174 %     if ( defined($Display) && $Display =~ /^(\w+)$/ ) {
175 %       my $el = "/Elements/CalendarSlot$1";
176         <& $el, Date      => $date,
177                 DateTypes => \%DateTypes,
178                 Tickets   => $Tickets{$date->strftime("%F")} || [],
179                 slots     => $slots,
180                 sday      => $sday,
181                 tod_row   => $row,
182                 timestep  => $timestep,
183                 @DisplayArgs,
184         &>
185 %     } else {
186
187 %       #just display the normal events for this day?
188         <td class="weekly" colspan="<%$slots%>">
189 %         for my $Ticket ( @{ $Tickets{$date->strftime("%F")} } ) {
190 %           my %dt =
191 %             map { $_=>1 }
192 %             grep {
193 %               my $meth = $_.'Obj';
194 %
195 %               #XXX off by 1h on daylight savings boundaries.. 2 sundays a year
196 %               my $tod = (   $Ticket->$meth->Unix
197 %                           - $Ticket->$meth->SetToMidnight(Timezone=>'user')
198 %                         ) / 60;
199 %
200 %               RTx::Calendar::LocalDate($Ticket->$meth->Unix) eq $date->strftime('%F') #today
201 %                 && $tod >= $row && $tod < ($row+$timestep); #and in timeslot
202 %             } keys %DateTypes;
203 %           next unless keys %dt;
204             <& /Elements/CalendarEvent,
205                  Object    => $Ticket,
206                  Date      => $date,
207                  DateTypes => \%dt
208             &>
209 %           unless ( $Ticket eq ${ $Tickets{$date->strftime("%F")} }[-1] ) { #hmm, no.. not with "next unless $dt" :/
210               <BR>
211 %           }
212 %         }
213         </td>
214
215 %     }
216
217 %       $date = $set->next($date);
218 %       if ( $date->day_of_week == $startday_of_week ) {
219           </tr>
220 %         if ( $date <= $end ) { #a second week? not going to work for week view yet
221             <tr>
222               <td class="controls" rowspan=<% $rowspan + 2 %> valign="middle">
223                   <& week_collapse, date=>$date, Month=>$OrigMonth, Year=>$OrigYear, QueryString=>$QueryString, Embed=>$Embed, &>
224                 </td>
225 %         }
226 %       }
227 %
228 %       $sday++;
229 %     } #while ($date <= $end)
230       </tr>
231 %   } #foreach my $row ( @week_rows )
232 %
233 % } else {
234 %
235 %   my $date = $start;
236 %   while ($date <= $end) {
237 %
238 %     my $offmonth = !$WeekDay && $date->month != ($Month + 1);
239 %     my $is_today     = (DateTime->compare($today,     $date) == 0);
240 %     my $is_yesterday = (DateTime->compare($yesterday, $date) == 0);
241 %     my $is_aweekago  = (DateTime->compare($aweekago,  $date) == 0);
242
243       <td
244           class="<%   $offmonth     ? 'offmonth'
245                     : $is_today     ? 'today'
246                     : $is_yesterday ? 'yesterday'
247                     : $is_aweekago  ? 'aweekago'
248                     : ''
249                  %>"
250       >
251         <div class="<%   $is_today ? 'todays'
252                        : $offmonth ? 'offmonth'
253                        : ''
254                     %>calendardate"
255         ><% $date->day %></div>
256
257 %       if ( defined($Display) && $Display =~ /^(\w+)$/ ) {
258 %
259 %         my $el = "/Elements/CalendarDay$1";
260           <& $el, Tickets   => $Tickets{$date->strftime("%F")},
261                   Date      => $date,
262                   DateTypes => \%DateTypes,
263                   @DisplayArgs,
264           &>
265 %
266 %       } else {
267 %
268 %         my $sp = 3;
269 %         for my $t ( @{ $Tickets{$date->strftime("%F")} } ) {
270 %           $sp--;
271             <& /Elements/CalendarEvent, Object => $t, Date => $date, DateTypes => \%DateTypes &>
272 %         }
273           <% ($sp>0) ? '<BR>'x$sp : '' |n %>
274 %
275 %       }
276
277       </td>
278
279 %     $date = $set->next($date);
280 %     if ( $date->day_of_week == $startday_of_week ) {
281         </tr>
282 %       if ( $date <= $end ) {
283           <tr>
284             <& td_week_expand, date=>$date, Month=>$Month, Year=>$Year, QueryString=>$QueryString, Embed=>$Embed, &>
285 %       }
286 %     }
287
288 %   } #while ($date <= $end)
289
290 % }
291 </tbody>
292 </table>
293
294 % unless ( $WeekDay ) {
295
296     <table width="100%">
297       <tr>
298         <td align="left">
299           <a href="<%$RT::WebPath%>/Search/<%$Embed||'Calendar.html'%>?Month=<%$PMonth%>&Year=<%$PYear%>&<%$QueryString%>">«<%$rtdate->GetMonth($PMonth)%></a>
300         </td>
301
302         <td valign="top" align="center">
303           <form action="<%$RT::WebPath%>/Search/<%$Embed||'Calendar.html'%>?<%$QueryString%>" method="post">
304
305             <select name="Month">
306 %             for (0..11) {
307                 <option value="<%$_%>" <% $_ == $Month ? 'selected' : ''%> ><%$rtdate->GetMonth($_)%></option>
308 %             }
309             </select>
310
311 %           my $year = (localtime)[5] + 1900;
312             <select name="Year">
313 %             for ( ($year-5) .. ($year+5)) {
314                 <option value="<%$_%>" <% $_ == $Year ? 'selected' : ''%>><%$_%></option>
315 %             }
316             </select>
317
318 %# <& /Elements/Submit&>
319             <input type="submit" value="<% loc('Submit') %>" class="button" />
320
321           </form>
322         </td>
323
324         <td align="right">
325           <a href="<%$RT::WebPath%>/Search/<%$Embed||'Calendar.html'%>?Month=<%$NMonth%>&Year=<%$NYear%>&<%$QueryString%>"><%$rtdate->GetMonth($NMonth)%>»</a>
326         </td>
327       </tr>
328   </table>
329
330 % }
331
332 % unless ( $Embed ) {
333
334 <table width="100%">
335 <tr>
336
337 <td valign="top" rowspan=9>
338   <BR>
339   <a href="<%$RT::WebPath%>/Prefs/Calendar.html">Calendar Preferences and Help</a>
340 </td>
341
342 % foreach my $legend (keys %legend) {
343     <tr>
344       <td align="right">
345         <img src="<%$RT::WebImagesURL%>/<%$legend%>.png" />
346       </td>
347       <td align="left">
348 %       my $more = 0;
349 %       foreach ( @{$legend{$legend}} ) {
350           <% $more++ ? ', ' : '' %>
351           <&|/l&><% $_ %></&>
352 %       }
353       </td>
354     </tr>
355 % }
356
357 </table>
358
359 % }
360
361 </&>
362
363 <%ONCE>
364
365 my %legend = (
366   'created'     => ['Created'],
367   'due'         => ['Due'],
368   'resolved'    => ['Resolved'],
369   'updated'     => ['Last Updated'],
370   'created_due' => ['Created','Due'],
371   'reminder'    => ['Reminders'],
372   'started'     => ['Started'],
373   'starts_due'  => ['Starts','Due'],
374 );
375
376 my $stime    = RT->Config->Get('CalendarWeeklyStartMin');
377 $stime = 480 unless $stime =~ /^\d+$/; #8am
378 my $etime    = RT->Config->Get('CalendarWeeklyEndMin');
379 $etime = 1080 unless $etime =~ /^\d+$/; #6pm
380
381 my $timestep =  RT->Config->Get('CalendarWeeklySizeMin') || 30; #1/2h
382 my $rowspan = ($etime-$stime) / $timestep;
383
384 my $default_slots = RT->Config->Get('CalendarWeeklySlots') || 5;
385
386 my $wt = $stime;
387 my @week_rows = ();
388 while ( $wt < $etime ) { push @week_rows, $wt; $wt+=$timestep }
389
390 </%ONCE>
391 <%INIT>
392 use RTx::Calendar qw(FirstDay LastDay LastDayOfWeek);
393
394 $Embed =~ /^[\w\.]*$/ or die 'xss';
395
396 my $title = loc("Calendar");
397
398 my @DateTypes = qw/Created Starts Started Due LastUpdated Resolved/;
399
400 my $rtdate = RT::Date->new($session{'CurrentUser'});
401
402 my $time_zone = $session{'CurrentUser'}->UserObj->Timezone
403                   || RT->Config->Get('Timezone');
404
405 my $weekstart = 'Sunday'; #RT::SiteConfig?  user pref?
406 my %week = (
407   'Saturday' => [6,0..5],
408   'Sunday'   => [0..6],
409   'Monday'   => [1..6,0],
410 );
411 my $startday_of_week = ${$week{$weekstart}}[0]  || 7;
412 my $endday_of_week   = ${$week{$weekstart}}[-1] || 7;
413
414 my $today = DateTime->today( time_zone=>$time_zone );
415 my $yesterday = $today->clone->subtract( days=>1 );
416 my $aweekago  = $today->clone->subtract( days=>7 );
417
418 my( $start, $end );
419 if ( $WeekDay ) {
420   $start = DateTime->new( year      => $WeekYear,
421                           month     => $WeekMonth+1,
422                           day       => $WeekDay,
423                           time_zone => $time_zone,
424                         );
425   $end  = LastDayOfWeek( $WeekYear, $WeekMonth+1, $WeekDay, $endday_of_week );
426 } else {
427   $start = FirstDay($Year, $Month + 1, $startday_of_week );
428   $end   = LastDay ($Year, $Month + 1, $endday_of_week );
429 }
430
431 # use this to loop over days until $end
432 my $set = DateTime::Set->from_recurrence(
433     next => sub { $_[0]->truncate( to => 'day' )->add( days => 1 ) }
434 );
435
436 my $QueryString;
437 if ($Query) {
438   $QueryString =
439       $m->comp(
440         '/Elements/QueryString',
441         Query   => $Query,
442         Format  => $Format,
443         Order   => $Order,
444         OrderBy => $OrderBy,
445         Rows    => $RowsPerPage,
446         @DisplayArgs,
447       );
448 } else {
449   $QueryString =
450       $m->comp(
451         '/Elements/QueryString',
452         NewQuery => 1,
453         @DisplayArgs,
454       );
455 }
456
457 # Default Query and Format
458 my $TempFormat = "__Starts__ __Due__";
459 my $TempQuery = "( Status = 'new' OR Status = 'open' OR Status = 'stalled')
460  AND ( Owner = '" . $session{CurrentUser}->Id ."' OR Owner = 'Nobody'  )
461  AND ( Type = 'reminder' OR 'Type' = 'ticket' )";
462
463 if ( my $Search = RTx::Calendar::SearchDefaultCalendar($session{CurrentUser}) ) {
464   $TempFormat = $Search->SubValue('Format');
465   $TempQuery = $Search->SubValue('Query');
466 }
467
468 # we overide them if needed
469 $TempQuery  = $Query  if $Query;
470 $TempFormat = $Format if $Format;
471
472 # we search all date types in Format string
473 my @Dates = grep { $TempFormat =~ m/__${_}(Relative)?__/ } @DateTypes;
474
475 # used to display or not a date in Element/CalendarEvent
476 my %DateTypes = map { $_ => 1 } @Dates;
477
478 $TempQuery .= RTx::Calendar::DatesClauses(\@Dates, $start->strftime("%F"), $end->strftime("%F"));
479
480 # print STDERR ("-" x 30), "\n", $TempQuery, "\n";
481
482 my %Tickets = RTx::Calendar::FindTickets($session{'CurrentUser'}, $TempQuery, \@Dates, $start->strftime("%F"), $end->strftime("%F"));
483
484 </%INIT>
485 <%def td_week_expand>
486 <%args>
487   $date  => undef
488   $Month => undef
489   $Year  => undef
490   $QueryString => undef
491   $Embed => undef
492 </%args>
493   <td class="controls">
494     <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>
495   </td>
496 </%def>
497
498 <%def week_collapse>
499 <%args>
500   $date  => undef
501   $Month => undef
502   $Year  => undef
503   $QueryString => undef
504   $Embed => undef
505 </%args>
506     <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>
507 </%def>
508
509 <%def td_time>
510 % my( $min ) = shift;
511     <td class="labels"><% pretty_time($min) |n %></td>
512 <%init>
513 sub pretty_time {
514   my $t = shift;
515
516   return 'Midnight' if $t == 0 || $t == 1440;
517   return 'Noon'     if $t == 720;
518
519   my $h = int( $t / 60 );
520   my $m = $t % 60;
521
522   my $ap = 'AM';
523   if    ( $h == 0 || $h == 24 ) { $h = 12; }
524   elsif ( $h == 12 )           { $ap = 'PM'; }
525   elsif ( $h > 12 )            { $ap = 'PM'; $h -= 12; }
526
527   sprintf('%02d:%02d&nbsp;'.$ap, $h, $m);
528
529 }
530 </%init>
531 </%def>