diff options
author | ivan <ivan> | 2010-05-19 02:32:01 +0000 |
---|---|---|
committer | ivan <ivan> | 2010-05-19 02:32:01 +0000 |
commit | ab9be1d2bfedf205eab7a9d399ef22ee14117f53 (patch) | |
tree | a486b28b107b35859ec0f3f7e371d1616b68b335 /rt/share/html | |
parent | 363f89201b3ad61da89f2141373864e7e28943eb (diff) |
add RTx::Calendar 0.07
Diffstat (limited to 'rt/share/html')
19 files changed, 812 insertions, 0 deletions
diff --git a/rt/share/html/Callbacks/RTx-Calendar/Elements/Header/Head b/rt/share/html/Callbacks/RTx-Calendar/Elements/Header/Head new file mode 100644 index 000000000..c1f24c2b4 --- /dev/null +++ b/rt/share/html/Callbacks/RTx-Calendar/Elements/Header/Head @@ -0,0 +1,2 @@ +<link rel="stylesheet" href="<%$RT::WebPath%>/NoAuth/css/calendar.css" type="text/css" media="all" /> + diff --git a/rt/share/html/Callbacks/RTx-Calendar/Ticket/Elements/Tabs/Default b/rt/share/html/Callbacks/RTx-Calendar/Ticket/Elements/Tabs/Default new file mode 100644 index 000000000..cb46fdaf6 --- /dev/null +++ b/rt/share/html/Callbacks/RTx-Calendar/Ticket/Elements/Tabs/Default @@ -0,0 +1,19 @@ +<%init> +my $args; +$args= "?" . $m->comp( + '/Elements/QueryString', + Query => $ARGS{'Query'} || $session{'CurrentSearchHash'}->{'Query'}, + Format => $ARGS{'Format'} || $session{'CurrentSearchHash'}->{'Format'}, + OrderBy => $ARGS{'OrderBy'} || $session{'CurrentSearchHash'}->{'OrderBy'}, + Order => $ARGS{'Order'} || $session{'CurrentSearchHash'}->{'Order'}, + Page => $ARGS{'Page'} || $session{'CurrentSearchHash'}->{'Page'}, + Rows => $ARGS{'Rows'}, + ) if ($ARGS{'Query'} or $session{'CurrentSearchHash'}->{'Query'}); +$args ||= ''; + +$tabs->{'zz'} = { title =>loc("Calendar"), + path => "Search/Calendar.html$args" }; +</%init> +<%args> +$tabs +</%args> diff --git a/rt/share/html/Callbacks/RTx-Calendar/User/Elements/Tabs/Default b/rt/share/html/Callbacks/RTx-Calendar/User/Elements/Tabs/Default new file mode 100644 index 000000000..06413e278 --- /dev/null +++ b/rt/share/html/Callbacks/RTx-Calendar/User/Elements/Tabs/Default @@ -0,0 +1,9 @@ +<%init> + $tabs->{'z'} = { title =>loc("Calendar"), + path => "Prefs/Calendar.html" }; +</%init> +<%args> +$tabs +$current_subtab => undef +$Searches => undef +</%args> diff --git a/rt/share/html/Elements/CalendarEvent b/rt/share/html/Elements/CalendarEvent new file mode 100644 index 000000000..3a6b00bb8 --- /dev/null +++ b/rt/share/html/Elements/CalendarEvent @@ -0,0 +1,129 @@ +<%args> +$Date => undef +$Object => undef +$DateTypes => undef +</%args> +<div class="tooltip"> +<small> + +% if ($IsReminder and RTx::Calendar::LocalDate($Object->DueObj->Unix) eq $today) { + <img src="<%$RT::WebImagesURL%>/reminder.png" /> + +% } elsif ($DateTypes->{Resolved} +% and RTx::Calendar::LocalDate($Object->ResolvedObj->Unix) eq $today) { + <img src="<%$RT::WebImagesURL%>/resolved.png" /> + +% } elsif ($DateTypes->{Starts} and $DateTypes->{Due} +% and RTx::Calendar::LocalDate($Object->StartsObj->Unix) eq $today and RTx::Calendar::LocalDate($Object->DueObj->Unix) eq $today ) { + <img src="<%$RT::WebImagesURL%>/starts_due.png" /> + +% } elsif ($DateTypes->{Due} and $DateTypes->{Created} +% and RTx::Calendar::LocalDate($Object->DueObj->Unix) eq $today and RTx::Calendar::LocalDate($Object->CreatedObj->Unix) eq $today ) { + <img src="<%$RT::WebImagesURL%>/created_due.png" /> + +% } elsif ($DateTypes->{Starts} +% and RTx::Calendar::LocalDate($Object->StartsObj->Unix) eq $today) { + <img src="<%$RT::WebImagesURL%>/starts.png" /> + +% } elsif ($DateTypes->{Due} +% and RTx::Calendar::LocalDate($Object->DueObj->Unix) eq $today) { + <img src="<%$RT::WebImagesURL%>/due.png" /> + +% } elsif ($DateTypes->{Created} +% and RTx::Calendar::LocalDate($Object->CreatedObj->Unix) eq $today) { + <img src="<%$RT::WebImagesURL%>/created.png" /> + +% } elsif ($DateTypes->{Started} +% and RTx::Calendar::LocalDate($Object->StartedObj->Unix) eq $today) { + <img src="<%$RT::WebImagesURL%>/started.png" /> + +% } elsif ($DateTypes->{LastUpdated} +% and RTx::Calendar::LocalDate($Object->LastUpdatedObj->Unix) eq $today) { + <img src="<%$RT::WebImagesURL%>/updated.png" /> + +% } + + <a href="<%$RT::WebPath%>/Ticket/Display.html?id=<%$TicketId%>"> + <% $Object->QueueObj->Name %> #<% $TicketId %> + <% $display_owner ? 'by ' . $Object->OwnerObj->Name : '' %> + <% length($Object->Subject) > 80 ? substr($Object->Subject, 0, 77) . "..." : $Object->Subject %></a></small><br /> + <span class="tip"> + <a href="<%$RT::WebPath%>/Ticket/Display.html?id=<%$TicketId%>"> + <% $Object->QueueObj->Name %> #<% $TicketId %> + </a> + :</strong> <% $subject%><br /> + <br /> + +%# logic taken from Ticket/Search/Results.tsv +% foreach my $attr (@display_fields) { +% my $value; +% +% if ($attr =~ /(.*)->ISO$/ and $Object->$1->Unix <= 0) { +% $value = '-'; +% } else { +% my $method = '$Object->'.$attr.'()'; +% $method =~ s/->ISO\(\)$/->ISO( Timezone => 'user' )/; +% $value = eval $method; +% if ($@) {die "<b>Check your CalendarPopupFields config in etc/RT_SiteConfig.pm</b>.<br /><br />Failed to find \"$attr\" - ". $@}; +% } + <strong><&|/l&><% $label_of{$attr} %></&>:</strong> <% $value %><br /> +% } + +<br /> + </span> +</div> + +<%init> +use RTx::Calendar; + +my $today = $Date->strftime("%F"); + +my $TicketId; + +my $ticket; +my $subject; +my $IsReminder; + +if ($Object->Type eq 'reminder') { + $IsReminder = 1; + if ($Object->RefersTo->First) { + $ticket = $Object->RefersTo->First->TargetObj; + $TicketId = $ticket->Id; + $subject = $Object->Subject . " (" . $ticket->Subject . ")"; + } +} else { + $TicketId = $Object->Id; + $subject = $Object->Subject; +} + +my $display_owner = $RT::CalendarDisplayOwner; +$display_owner ||= RT->Config->Get('CalendarDisplayOwner') + if RT->can('Config'); + + +# 3.6 config +my @display_fields = @RT::CalendarPopupFields; + +# 3.8 config +# the if condition is weird but it doesn't work with 3.8.0 without the last part +@display_fields = RT->Config->Get('CalendarPopupFields') + if 0 == @display_fields and RT->can('Config') and RT->Config->Get('CalendarPopupFields'); + +# default +if (0 == @display_fields) { + @display_fields = qw(OwnerObj->Name CreatedObj->ISO StartsObj->ISO + StartedObj->ISO LastUpdatedObj->ISO DueObj->ISO + ResolvedObj->ISO Status Priority + Requestors->MemberEmailAddressesAsString); +} + + +my %label_of; +for my $field (@display_fields) { + my $label = $field; + $label =~ s'Obj-.(?:AsString|Name|ISO)''g; + $label =~ s'-\>MemberEmailAddressesAsString''g; + $label_of{$field} = $label; +} + +</%init> diff --git a/rt/share/html/Elements/MyCalendar b/rt/share/html/Elements/MyCalendar new file mode 100644 index 000000000..a54ab39d6 --- /dev/null +++ b/rt/share/html/Elements/MyCalendar @@ -0,0 +1,78 @@ +<&|/Widgets/TitleBox, + title => loc("Calendar"), + title_href => "Search/Calendar.html" &> + +<table class="rtxcalendar"> +<thead> +<tr> +% my $date = $begin->clone; +% while ( $date <= $end ) { +<th width="14%"><%$rtdate->GetWeekday($date->day_of_week % 7)%></th> +% $date = $set->next($date); +% } +</tr> +</thead> +<tbody> +<tr> +% $date = $begin->clone; +% while ($date <= $end) { +<td> +<p class="date"><%$date->day%></p> +% for my $t (@{ $Tickets{$date->strftime("%F")} }) { +<& /Elements/CalendarEvent, Object => $t, Date => $date, DateTypes => \%DateTypes &> +% } +</td> +% $date = $set->next($date); +% } +</tr> +</tbody> +</table> + + </&> + +<%INIT> + +use RTx::Calendar; + +my $title = loc("Calendar"); + +my $rtdate = RT::Date->new($session{'CurrentUser'}); + +my @DateTypes = qw/Created Starts Started Due LastUpdated Resolved/; + +my $today = DateTime->today; + +# this line is used to debug MyCalendar +# $today = DateTime->new(year => 2007, month => 4, day => 11); + +my $begin = $today->clone->subtract( days => 3); +my $end = $today->clone->add( days => 3); + +# use this to loop over days until $end +my $set = DateTime::Set->from_recurrence( + next => sub { $_[0]->truncate( to => 'day' )->add( days => 1 ) } +); + +my $Query = "( Status = 'new' OR Status = 'open' OR Status = 'stalled') + AND ( Owner = '" . $session{CurrentUser}->Id ."' OR Owner = 'Nobody' ) + AND ( Type = 'reminder' OR 'Type' = 'ticket' )"; +my $Format = "__Starts__ __Due__"; + +if ( my $Search = RTx::Calendar::SearchDefaultCalendar($session{CurrentUser}) ) { + $Format = $Search->SubValue('Format'); + $Query = $Search->SubValue('Query'); +} + +# we search all date types in Format string +my @Dates = grep { $Format =~ m/__${_}(Relative)?__/ } @DateTypes; + +# used to display or not a date in Element/CalendarEvent +my %DateTypes = map { $_ => 1 } @Dates; + +$Query .= RTx::Calendar::DatesClauses(\@Dates, $begin->strftime("%F"), $end->strftime("%F")); + +# print STDERR $Query, "\n"; + +my %Tickets = RTx::Calendar::FindTickets($session{'CurrentUser'}, $Query, \@Dates); + +</%INIT> diff --git a/rt/share/html/NoAuth/Calendar/dhandler b/rt/share/html/NoAuth/Calendar/dhandler new file mode 100644 index 000000000..4b4aa631e --- /dev/null +++ b/rt/share/html/NoAuth/Calendar/dhandler @@ -0,0 +1,159 @@ +<%init> + +use Data::ICal; +use Data::ICal::Entry::Todo; +use Data::ICal::Entry::Event; +use Date::ICal; + +$RT::ICalTicketType ||= "Data::ICal::Entry::Todo"; +$RT::ICalReminderType ||= "Data::ICal::Entry::Event"; + +my ($UserId, $SearchId, $MagicNumber); +my $arg = $m->dhandler_arg; + +if ($arg =~ m{^(\d+)@(\d+)/(.*)$}) { + $UserId = $1; + $SearchId = $2; + $MagicNumber = $3; +} elsif ($arg =~ m{^(\d+)/(.*)}) { + $UserId = $1; + $MagicNumber = $2; +} else { + Abort("Corrupted URL."); +} + +my $CurrentUser = new RT::CurrentUser(); +$CurrentUser->LoadById($UserId); +my $user = $CurrentUser->Name; + +# if no user, abort +unless ($CurrentUser->Id) { + $RT::Logger->error("No such user id $UserId from $ENV{'REMOTE_ADDR'}"); + $m->out("RT/".$RT::VERSION ." ".404 ."\n\nno such file\n"); + $m->abort; +} + +# verify user has LoadSavedSearch right +if ($SearchId and not $CurrentUser->HasRight( Right => 'LoadSavedSearch', + Object=> $RT::System )) { + $RT::Logger->error("not enough rights for user $user from $ENV{'REMOTE_ADDR'}"); + $m->out("RT/".$RT::VERSION ." ".404 ."\n\nno such file\n"); + $m->abort; +} + + +# if MagicNumber doesn't match the one stored in database, abort +my $Search; +my $ICalAttribute; +if ($SearchId) { + $Search = $CurrentUser->Attributes->WithId($SearchId); + $ICalAttribute = $Search->FirstAttribute('ICalURL'); +} else { + $ICalAttribute = $CurrentUser->UserObj->FirstAttribute('ICalURL'); +} + +unless ($ICalAttribute) { + $RT::Logger->error("No such ICal feed for $user from $ENV{'REMOTE_ADDR'}"); + $m->out("RT/".$RT::VERSION ." ".404 ."\n\nno such file\n"); + $m->abort; +} + + +if ($MagicNumber ne $ICalAttribute->Content) { + $RT::Logger->error("FAILED LOGIN for $user from $ENV{'REMOTE_ADDR'}"); + $m->out("RT/".$RT::VERSION ." ".404 ."\n\nno such file\n"); + $m->abort; +} + +my $Tickets = RT::Tickets->new($CurrentUser); + +my $Query = "( Status = 'new' OR Status = 'open' OR Status = 'stalled') + AND ( Owner = '" . $CurrentUser->Id ."' OR Owner = 'Nobody' ) + AND ( Type = 'reminder' OR 'Type' = 'ticket' )"; + +$Query = $Search->SubValue('Query') + if $Search; + +$Query .= " AND ( Due > '1970-01-01' OR Starts > '1970-01-01' )"; + +$Tickets->FromSQL($Query); + +$Tickets->OrderBy(FIELD => 'Due', ORDER => 'ASC'); + +my $calendar = Data::ICal->new(); + +my ($uid) = $RT::WebURL =~ m{https?://([^:]+)}; + +while (my $Ticket = $Tickets->Next ) { + + my $event; + if ($Ticket->Type eq 'ticket') { + $event = add_todo($Ticket, $uid); + } else { + $event = add_event($Ticket, $uid); + } + next unless $event; + $calendar->add_entry($event); +} + +my $cal = $calendar->as_string; + +$r->content_type('text/calendar;charset=utf-8'); +$m->clear_buffer(); +$m->out($cal); +$m->abort; + +sub add_event { + my ($Reminder, $uid) = @_; + + return unless defined $Reminder->RefersTo->First; + my $Ticket = $Reminder->RefersTo->First->TargetObj; + + my %event = ( + summary => $Reminder->Subject ? $Reminder->Subject : '', + url => "${RT::WebURL}/Ticket/Display.html?id=" . $Ticket->id, + uid => Date::ICal->new( epoch => time() )->ical() . "-" . $Reminder->Id . "@" . $uid, + categories => $Ticket->QueueObj->Name, + dtstart => Date::ICal->new( epoch => $Reminder->DueObj->Unix )->ical, + ); + + my $event = $RT::ICalReminderType->new(); + $event->add_properties(%event); + + return $event; +} + +sub add_todo { + my ($Ticket, $uid) = @_; + + my %vtodo = ( + summary => $Ticket->Subject ? $Ticket->Subject : '', + dtstart => Date::ICal->new( epoch => $Ticket->CreatedObj->Unix )->ical, + url => "${RT::WebURL}/Ticket/Display.html?id=" . $Ticket->id, + uid => Date::ICal->new( epoch => time() )->ical() . "-" . $Ticket->Id . "@" . $uid, + categories => $Ticket->QueueObj->Name, + ); + + $vtodo{due} = Date::ICal->new( epoch => $Ticket->DueObj->Unix )->ical, + if $Ticket->DueObj; + + if ($Ticket->OwnerObj->Id != $RT::Nobody->Id and $Ticket->OwnerObj->EmailAddress) { + $vtodo{organizer} = "MAILTO:" . $Ticket->OwnerObj->EmailAddress; + $vtodo{attendee} = "MAILTO:" . $Ticket->OwnerObj->EmailAddress; + } elsif ($Ticket->QueueObj->CommentAddress) { + $vtodo{organizer} = "MAILTO:" . $Ticket->QueueObj->CommentAddress; + $vtodo{attendee} = "MAILTO:" . $Ticket->QueueObj->CommentAddress; + } + + $vtodo{priority} = $Ticket->Priority + if $Ticket->Priority; + + my $vtodo = $RT::ICalTicketType->new(); + $vtodo->add_properties(%vtodo); + + return $vtodo; +} + + + +</%init> diff --git a/rt/share/html/NoAuth/css/calendar.css b/rt/share/html/NoAuth/css/calendar.css new file mode 100644 index 000000000..e313dff99 --- /dev/null +++ b/rt/share/html/NoAuth/css/calendar.css @@ -0,0 +1,40 @@ +.tooltip{position:relative;z-index:1;} +.tooltip:hover{z-index:5;color:#000;} +.tooltip span.tip{display: none; text-align:left;} + +div.tooltip:hover span.tip{ +display:block; +position:absolute; +top:12px; left:24px; width:350px; +border:1px solid #555; +background-color:#fff; +padding: 4px; +font-size: 0.8em; +color:#505050; +} + +.date { +text-align: right; +} + +table.rtxcalendar { + width:100%; + border-collapse: collapse; + border: 1px dotted #d0d0d0; + margin-bottom: 6px; +} + +table.rtxcalendar td { + border: 1px solid #d7d7d7; + vertical-align: top; +} + +table.rtxcalendar th { + border: 1px solid #d7d7d7; + background: #eee; +} +table.rtxcalendar tbody th { + border: 1px solid #d7d7d7; + background: #eee; + font-weight: normal; +} diff --git a/rt/share/html/NoAuth/images/created.png b/rt/share/html/NoAuth/images/created.png Binary files differnew file mode 100644 index 000000000..4d5eeb9ea --- /dev/null +++ b/rt/share/html/NoAuth/images/created.png diff --git a/rt/share/html/NoAuth/images/created_due.png b/rt/share/html/NoAuth/images/created_due.png Binary files differnew file mode 100644 index 000000000..52dfc96f0 --- /dev/null +++ b/rt/share/html/NoAuth/images/created_due.png diff --git a/rt/share/html/NoAuth/images/due.png b/rt/share/html/NoAuth/images/due.png Binary files differnew file mode 100644 index 000000000..30a3aff8a --- /dev/null +++ b/rt/share/html/NoAuth/images/due.png diff --git a/rt/share/html/NoAuth/images/reminder.png b/rt/share/html/NoAuth/images/reminder.png Binary files differnew file mode 100644 index 000000000..4370b6902 --- /dev/null +++ b/rt/share/html/NoAuth/images/reminder.png diff --git a/rt/share/html/NoAuth/images/resolved.png b/rt/share/html/NoAuth/images/resolved.png Binary files differnew file mode 100644 index 000000000..09db36d5a --- /dev/null +++ b/rt/share/html/NoAuth/images/resolved.png diff --git a/rt/share/html/NoAuth/images/started.png b/rt/share/html/NoAuth/images/started.png Binary files differnew file mode 100644 index 000000000..e177addea --- /dev/null +++ b/rt/share/html/NoAuth/images/started.png diff --git a/rt/share/html/NoAuth/images/starts.png b/rt/share/html/NoAuth/images/starts.png Binary files differnew file mode 100644 index 000000000..88064ba50 --- /dev/null +++ b/rt/share/html/NoAuth/images/starts.png diff --git a/rt/share/html/NoAuth/images/starts_due.png b/rt/share/html/NoAuth/images/starts_due.png Binary files differnew file mode 100644 index 000000000..16a4de46f --- /dev/null +++ b/rt/share/html/NoAuth/images/starts_due.png diff --git a/rt/share/html/NoAuth/images/updated.png b/rt/share/html/NoAuth/images/updated.png Binary files differnew file mode 100644 index 000000000..680e79a54 --- /dev/null +++ b/rt/share/html/NoAuth/images/updated.png diff --git a/rt/share/html/Prefs/Calendar.html b/rt/share/html/Prefs/Calendar.html new file mode 100644 index 000000000..5fbdd2717 --- /dev/null +++ b/rt/share/html/Prefs/Calendar.html @@ -0,0 +1,123 @@ +<%args> +$ChangeURL => undef +$ResetURL => undef +$SearchType => 'Ticket' +$HiddenField => undef +</%args> + +<& /Elements/Header, Title => $title &> +<& /User/Elements/Tabs, + current_tab => 'Prefs/Calendar.html', + Title => $title +&> + +<&| /Widgets/TitleBox, title => loc('ICal Feeds (ics)') &> + +<&| /Widgets/TitleBox, title => 'Help' &> + +<h3>displaying reminders :</h3> +<p>If you want to have reminders in a search you need to go in the <a +href="<%$RT::WebPath%>/Search/Edit.html"><%loc("Edit Query")%></a> tab +of the <%loc("query builder")%> and add something like that : + + <pre> + AND ( Type = 'ticket' OR Type = 'reminder' ) +</pre> +</p> + +<h3>displaying other kind of dates :</h3> +<p>By default RTx::Calendar display Due and Starts dates. You can +select other kind of events you want with the <%loc("Display +Columns")%> section in the <a +href="<%$RT::WebPath%>/Search/Build.html"><%loc("Query +Builder")%></a>. The following one will display the two latter and +LastUpdated dates : + +<pre> + '<small>__Due__</small>', + '<small>__Starts__</small>', + '<small>__LastUpdated__</small>' +</pre> +</p> + +<h3>changing the default query :</h3> +<p>You can change the default Query of Calendar.html and MyCalendar +portlet by saving a query with the name <code>calendar</code> in the +<a href="<%$RT::WebPath%>/Search/Build.html"><%loc("Query +Builder")%></a>.</p> + +</&> + +<& /Prefs/Elements/CalendarFeed &> + +% # only allow this part if +% if ($AllowSearch) { + +% my $search_count; + +% # I'm quite sure the loop isn't usefull but... +% my @Objects = $session{CurrentUser}->UserObj; +% for my $object (@Objects) { +% next unless ref($object) eq 'RT::User' && $object->id == $session{'CurrentUser'}->Id; +% my @searches = $object->Attributes->Named('SavedSearch'); +% for my $search (@searches) { +% next if ($search->SubValue('SearchType') +% && $search->SubValue('SearchType') ne $SearchType); +% $search_count++; +<& /Prefs/Elements/CalendarFeed, Object => $object, Search => $search &> + +% } +% } +% unless ($search_count) { + +<&| /Widgets/TitleBox, title => loc('Private Search ICal feeds') + , title_class=> 'inverse' + , color => "#993333" &> + +You can add private ICal feeds by saving new queries in <a +href="<%$RT::WebPath . '/Search/Build.html'%>">the Query Builder</a> + +</&> + +% } +% } else { +%#<&| /Widgets/TitleBox, title => loc('Private Search ICal feeds') +%# , title_class=> 'inverse' +%# , color => "#993333" &> +%# +%#<%loc('Private search ICal feeds disabled. To enable them, ask your admin for "[_1]" and "[_2]" rights', +%# loc('CreateSavedSearch'), +%# loc('LoadSavedSearch') )%> +%# +%#</&> +% } + +</&> + +<%INIT> +use Digest::SHA1; +use RT::SavedSearches; + +my $title = loc("Calendar Prefs"); +my $AllowSearch; + +$AllowSearch = 1 + if $session{'CurrentUser'}->HasRight( Right => 'LoadSavedSearch', + Object=> $RT::System ); + +my $object; + +if ($HiddenField eq 'Private') { + $object = $session{CurrentUser}->UserObj; +} elsif ($AllowSearch and my ($SearchId) = $HiddenField =~ m/SavedSearch\-(\d+)/) { + $object = $session{CurrentUser}->Attributes->WithId($SearchId); +} + +if (defined $ChangeURL) { + my @args = $object->SetAttribute(Name => 'ICalURL', Content => Digest::SHA1::sha1_base64(time)); +} elsif (defined $ResetURL) { + my @args = $object->DeleteAttribute('ICalURL'); +} + + +</%INIT> diff --git a/rt/share/html/Prefs/Elements/CalendarFeed b/rt/share/html/Prefs/Elements/CalendarFeed new file mode 100644 index 000000000..46893435e --- /dev/null +++ b/rt/share/html/Prefs/Elements/CalendarFeed @@ -0,0 +1,68 @@ +<%args> +$Search => undef +$Object => undef +$HiddenField => undef +</%args> + +<&| /Widgets/TitleBox, title => $title &> + +% if ($FeedText) { +<p><%$FeedText%></p> +% } else { +This feed will show tickets with due date find with query:<br /> +"<%$Search->SubValue('Query')%>". +% } + +% if ($ICalURL) { +<p>Your can paste this url in your calendar : <b><a href="<%$link%>"><%$link%></a></b><p> +<table> +<tr> +<td> +<form action="<%$RT::WebPath%>/Prefs/Calendar.html" method="post"> +<input type="hidden" name="HiddenField" value="<%$HiddenField%>" /> +<input type="submit" class="button" name="ResetURL" value="<%loc('Disable Feed')%>" /> +</form> +</td> +<td> +<form action="<%$RT::WebPath%>/Prefs/Calendar.html" method="post"> +<input type="hidden" name="HiddenField" value="<%$HiddenField%>" /> +<input type="submit" class="button" name="ChangeURL" value="<%loc('Change Feed URL')%>" /> +</form> +</td> +</tr> +</table> +% } else { + +<form action="<%$RT::WebPath%>/Prefs/Calendar.html" method="post"> +<input type="hidden" name="HiddenField" value="<%$HiddenField%>" /> +<input type="submit" class="button" name="ChangeURL" value="<%loc('Enable Feed')%>" /> +</form> +% } + +</&> + +<%init> +my $title; +my $ICalURL; +my $Id; +my $FeedText; +my $link; + +if ($Object) { + $title = loc('Feed for "') . ($Search->Description || loc('Unnamed search')) . '" search'; + $HiddenField = "SavedSearch-" . $Search->Id; + $ICalURL = $Search->FirstAttribute('ICalURL'); + $Id = $session{CurrentUser}->Id . "@" . $Search->Id; + $title .= " (disabled)" unless $ICalURL; +} else { + $title = loc('Feed for default calendar'); + $HiddenField = "Private"; + $ICalURL = $session{CurrentUser}->UserObj->FirstAttribute('ICalURL'); + $Id = $session{CurrentUser}->Id; + $FeedText = "This feed will show yours and Nobody's tasks with due date."; +} + +$link = $RT::WebURL . "NoAuth/Calendar/" . $Id . "/" . $ICalURL->Content + if $ICalURL; + +</%init>
\ No newline at end of file diff --git a/rt/share/html/Search/Calendar.html b/rt/share/html/Search/Calendar.html new file mode 100644 index 000000000..e711b861c --- /dev/null +++ b/rt/share/html/Search/Calendar.html @@ -0,0 +1,185 @@ +<%args> +$Month => (localtime)[4] +$Year => (localtime)[5] + 1900 +$Query => undef +$Format => undef +$Order => undef +$OrderBy => undef +$RowsPerPage => undef +$NewQuery => 0 +</%args> + +<& /Elements/Header, Title => $title &> +<& /Ticket/Elements/Tabs, + current_tab => "Search/Calendar.html?$QueryString", + Title => $title &> +<&| /Widgets/TitleBox, + title => loc('Calendar for ') . $rtdate->GetMonth($Month) . " $Year" , + title_class=> 'inverse', + color => "#993333" &> + +<table width="100%"> +<tr> +<td align="left"> +% my ($PMonth, $PYear) = ($Month - 1, $Year); +% if ($PMonth < 0) { +% $PYear--; +% $PMonth = 11; +% } +<a href="<%$RT::WebPath%>/Search/Calendar.html?Month=<%$PMonth%>&Year=<%$PYear%>&<%$QueryString%>">«<%$rtdate->GetMonth($PMonth)%></a> +</td> +<td align="center"> +<a href="<%$RT::WebPath%>/Prefs/Calendar.html">Calendar Preferences and Help</a> +</td> +<td align="right"> +% my ($NMonth, $NYear) = ($Month + 1, $Year); +% if ($NMonth > 11) { +% $NYear++; +% $NMonth = 0; +% } +<a href="<%$RT::WebPath%>/Search/Calendar.html?Month=<%$NMonth%>&Year=<%$NYear%>&<%$QueryString%>"><%$rtdate->GetMonth($NMonth)%>»</a> +</td> +</tr> +</table> + +<table class="rtxcalendar"> +<thead> +<tr> +<th></th> +% for (1 .. 6, 0) { +<th width="14%"><%$rtdate->GetWeekday($_)%></th> +% } +</tr> +</thead> +<tbody> +<tr> +% while ($date <= $end) { +% if ( $date->day_of_week == 1) { +<th><% $date->week_number %></th> +% } +<td class="<% $date->month != ($Month + 1) ? 'oddline' : '' %>" + style="width:14%;<% DateTime->compare($today, $date) == 0 ? 'background:#f6f7f8;' : '' %>" +> +<p class="date"><%$date->day%></p> +% for my $t ( @{ $Tickets{$date->strftime("%F")} } ) { +<& /Elements/CalendarEvent, Object => $t, Date => $date, DateTypes => \%DateTypes &> +% } +</td> +% $date = $set->next($date); +% if ( $date->day_of_week == 1) { +</tr><tr> +% } +% } +</tr> +</tbody> +</table> + +<table width="100%"> +<tr> +<td align="left"> +<a href="<%$RT::WebPath%>/Search/Calendar.html?Month=<%$PMonth%>&Year=<%$PYear%>&<%$QueryString%>">«<%$rtdate->GetMonth($PMonth)%></a> +</td> +<td align="right"> +<a href="<%$RT::WebPath%>/Search/Calendar.html?Month=<%$NMonth%>&Year=<%$NYear%>&<%$QueryString%>"><%$rtdate->GetMonth($NMonth)%>»</a> +</td> +</tr> +</table> + + +<table width="100%"> +<tr> +<td valign="top" align="center" width="80%"> +<form action="<%$RT::WebPath%>/Search/Calendar.html?<%$QueryString%>" method="post"> + +<select name="Month"> +% for (0..11) { +<option value="<%$_%>" <% $_ == $Month ? 'selected' : ''%> ><%$rtdate->GetMonth($_)%></option> +% } +</select> +% my $year = (localtime)[5] + 1900; +<select name="Year"> +% for ( ($year-5) .. ($year+5)) { +<option value="<%$_%>" <% $_ == $Year ? 'selected' : ''%>><%$_%></option> +% } +</select> + +<& /Elements/Submit&> +</form> +</td> +<td valign="top" width="50%" align="right"> +<img src="<%$RT::WebImagesURL%>/created.png" /> : <&|/l&>Created</&><br /> +<img src="<%$RT::WebImagesURL%>/due.png" /> : <&|/l&>Due</&><br /> +<img src="<%$RT::WebImagesURL%>/resolved.png" /> : <&|/l&>Resolved</&><br /> +<img src="<%$RT::WebImagesURL%>/updated.png" /> : <&|/l&>Last Updated</&><br /> +<img src="<%$RT::WebImagesURL%>/created_due.png" /> : <&|/l&>Created</&>, <&|/l&>Due</&><br /> +<img src="<%$RT::WebImagesURL%>/reminder.png" /> : <&|/l&>Reminders</&><br /> +<img src="<%$RT::WebImagesURL%>/starts.png" /> : <&|/l&>Starts</&><br /> +<img src="<%$RT::WebImagesURL%>/started.png" /> : <&|/l&>Started</&><br /> +<img src="<%$RT::WebImagesURL%>/starts_due.png" /> : <&|/l&>Starts</&>, <&|/l&>Due</&><br /> + + +</td> +</table> + +</&> + +</html> +<%INIT> +use RTx::Calendar; + +my $title = loc("Calendar"); + +my @DateTypes = qw/Created Starts Started Due LastUpdated Resolved/; + +my $rtdate = RT::Date->new($session{'CurrentUser'}); + +my $today = DateTime->today; +my $date = RTx::Calendar::FirstMonday($Year, $Month + 1); +my $end = RTx::Calendar::LastSunday($Year, $Month + 1); + +# use this to loop over days until $end +my $set = DateTime::Set->from_recurrence( + next => sub { $_[0]->truncate( to => 'day' )->add( days => 1 ) } +); + +my $QueryString = + $m->comp( + '/Elements/QueryString', + Query => $Query, + Format => $Format, + Order => $Order, + OrderBy => $OrderBy, + Rows => $RowsPerPage + ) + if ($Query); + +$QueryString ||= 'NewQuery=1'; + +# Default Query and Format +my $TempFormat = "__Starts__ __Due__"; +my $TempQuery = "( Status = 'new' OR Status = 'open' OR Status = 'stalled') + AND ( Owner = '" . $session{CurrentUser}->Id ."' OR Owner = 'Nobody' ) + AND ( Type = 'reminder' OR 'Type' = 'ticket' )"; + +if ( my $Search = RTx::Calendar::SearchDefaultCalendar($session{CurrentUser}) ) { + $TempFormat = $Search->SubValue('Format'); + $TempQuery = $Search->SubValue('Query'); +} + +# we overide them if needed +$TempQuery = $Query if $Query; +$TempFormat = $Format if $Format; + +# we search all date types in Format string +my @Dates = grep { $TempFormat =~ m/__${_}(Relative)?__/ } @DateTypes; + +# used to display or not a date in Element/CalendarEvent +my %DateTypes = map { $_ => 1 } @Dates; + +$TempQuery .= RTx::Calendar::DatesClauses(\@Dates, $date->strftime("%F"), $end->strftime("%F")); + +# print STDERR ("-" x 30), "\n", $TempQuery, "\n"; + +my %Tickets = RTx::Calendar::FindTickets($session{'CurrentUser'}, $TempQuery, \@Dates, $date->strftime("%F"), $end->strftime("%F")); + +</%INIT> |