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