summaryrefslogtreecommitdiff
path: root/rt/html/Search
diff options
context:
space:
mode:
authorivan <ivan>2003-07-15 13:16:32 +0000
committerivan <ivan>2003-07-15 13:16:32 +0000
commit945721f48f74d5cfffef7c7cf3a3d6bc2521f5dd (patch)
treec874aeac27d37fce2e41d64c3347c99527f6e66d /rt/html/Search
parent160be29a0dc62e79a4fb95d2ab8c0c7e5996760e (diff)
import of rt 3.0.4
Diffstat (limited to 'rt/html/Search')
-rw-r--r--rt/html/Search/Bulk.html217
-rw-r--r--rt/html/Search/Elements/PickRestriction141
-rw-r--r--rt/html/Search/Elements/TicketHeader40
-rw-r--r--rt/html/Search/Elements/TicketHeaderCell55
-rw-r--r--rt/html/Search/Elements/TicketRow55
-rw-r--r--rt/html/Search/Listing.html112
6 files changed, 620 insertions, 0 deletions
diff --git a/rt/html/Search/Bulk.html b/rt/html/Search/Bulk.html
new file mode 100644
index 000000000..df43cfa50
--- /dev/null
+++ b/rt/html/Search/Bulk.html
@@ -0,0 +1,217 @@
+%# BEGIN LICENSE BLOCK
+%#
+%# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
+%#
+%# (Except where explictly superceded by other copyright notices)
+%#
+%# This work is made available to you under the terms of Version 2 of
+%# the GNU General Public License. A copy of that license should have
+%# been provided with this software, but in any event can be snarfed
+%# from www.gnu.org.
+%#
+%# This work is distributed in the hope that it will be useful, but
+%# WITHOUT ANY WARRANTY; without even the implied warranty of
+%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+%# General Public License for more details.
+%#
+%# Unless otherwise specified, all modifications, corrections or
+%# extensions to this work which alter its source code become the
+%# property of Best Practical Solutions, LLC when submitted for
+%# inclusion in the work.
+%#
+%#
+%# END LICENSE BLOCK
+<& /Elements/Header, Title => loc("Bulk ticket update") &>
+<& /Elements/Tabs, Title => loc("Bulk ticket update") &>
+
+<& /Elements/ListActions, actions => \@results &>
+
+<FORM METHOD=POST>
+<TABLE WIDTH=100% border=0 cellpadding=3 CELLSPACING=0>
+<TR>
+<TH><&|/l&>Update</&></TH>
+%foreach my $col (@cols) {
+% my $colalias = $col;
+% $colalias =~ s/(Obj\-\>|)(Name|AsString)//;
+
+<TH><% loc($colalias) %>&nbsp;</TH>
+%}
+</TR>
+
+<%PERL>
+
+my $i;
+
+
+
+$session{'tickets'}->RedoSearch();
+while (my $Ticket = $session{'tickets'}->Next) {
+ $i++;
+ if ($i % 2) {
+ $bgcolor = "#dddddd";
+ }
+ else {
+ $bgcolor = "#ffffff";
+ }
+ </%PERL>
+<TR bgcolor="<%$bgcolor%>">
+<TD><input type=checkbox name="UpdateTicket<%$Ticket->Id%>" CHECKED></TD>
+%# The ticket view is controlled by config.pm, WebOptions
+%foreach my $col (@cols) {
+<TD>
+% if ($col eq 'id') {
+<A HREF="<% $RT::WebPath%>/Ticket/Display.html?id=<%$Ticket->Id%>"><%$Ticket->Id()%></A>
+% }
+%else {
+<% eval "\$Ticket->$col()" %>&nbsp;
+%}
+</TD>
+%}
+</TR>
+%}
+
+
+
+</TABLE>
+
+<HR>
+
+
+<& /Elements/TitleBoxStart, title => loc('Update selected tickets') &>
+<TABLE>
+<TR>
+<TD VALIGN=TOP>
+<table>
+<tr><td class=label> <&|/l&>Make Owner</&>: </td>
+<td class=value> <& /Elements/SelectOwner, Name => "Owner" &> (<input type=checkbox name="ForceOwnerChange"> <&|/l&>Force change</&>) </td></tr>
+<tr><td class=label> <&|/l&>Add Requestor</&>: </td>
+<td class=value> <INPUT Name="AddRequestor" SIZE=20> </td></tr>
+<tr><td class=label> <&|/l&>Remove Requestor</&>: </td>
+<td class=value> <INPUT Name="DeleteRequestor" SIZE=20> </td></tr>
+<tr><td class=label> <&|/l&>Add Cc</&>: </td>
+<td class=value> <INPUT Name="AddCc" SIZE=20> </td></tr>
+<tr><td class=label> <&|/l&>Remove Cc</&>: </td>
+<td class=value> <INPUT Name="DeleteCc" SIZE=20> </td></tr>
+<tr><td class=label> <&|/l&>Add AdminCc</&>: </td>
+<td class=value> <INPUT Name="AddAdminCc" SIZE=20> </td></tr>
+<tr><td class=label> <&|/l&>Remove AdminCc</&>: </td>
+<td class=value> <INPUT Name="DeleteAdminCc" SIZE=20> </td></tr>
+</table>
+</TD>
+<TD VALIGN=TOP>
+<table>
+<tr><td class=label> <&|/l&>Make subject</&>: </td>
+<td class=value> <INPUT Name="Subject" SIZE=20> </td></tr>
+<tr><td class=label> <&|/l&>Make priority</&>: </td>
+<td class=value> <INPUT Name="Priority" SIZE=4> </td></tr>
+<tr><td class=label> <&|/l&>Make queue</&>: </td>
+<td class=value> <& /Elements/SelectQueue, Name => "Queue" &> </td></tr>
+<tr><td class=label> <&|/l&>Make Status</&>: </td>
+<td class=value> <& /Elements/SelectStatus, Name => "Status" &> </td></tr>
+<tr><td class=label> <&|/l&>Make date Starts</&>: </td>
+<td class=value> <& /Elements/SelectDate, Name => "Starts_Date", ShowTime => 0, Default => '' &> </td></tr>
+<tr><td class=label> <&|/l&>Make date Started</&>: </td>
+<td class=value> <& /Elements/SelectDate, Name => "Started_Date", ShowTime => 0, Default => '' &> </td></tr>
+<tr><td class=label> <&|/l&>Make date Told</&>: </td>
+<td class=value> <& /Elements/SelectDate, Name => "Told_Date", ShowTime => 0, Default => '' &> </td></tr>
+<tr><td class=label> <&|/l&>Make date Due</&>: </td>
+<td class=value> <& /Elements/SelectDate, Name => "Due_Date", ShowTime => 0, Default => '' &> </td></tr>
+<tr><td class=label> <&|/l&>Make date Resolved</&>: </td>
+<td class=value> <& /Elements/SelectDate, Name => "Resolved_Date", ShowTime => 0, Default => '' &> </td></tr>
+</table>
+
+</TD>
+</TR>
+</table>
+<& /Elements/TitleBoxEnd&>
+<& /Elements/TitleBoxStart, title => loc('Add comments or replies to selected tickets') &>
+<table>
+<tr><td align=right><&|/l&>Update Type</&>:</td>
+<td><select name="UpdateType">
+ <option value="private" ><&|/l&>Comments (not sent to requestors)</&></option>
+<option value="response" ><&|/l&>Response to requestors</&></option>
+</select>
+</td></tr>
+<tr><td align=right><&|/l&>Subject</&>:</td><td> <input name="UpdateSubject" size=60 value=""></td></tr>
+ <tr><td align=right><&|/l&>Attach</&>:</td><td><input name="UpdateAttachment" type="file"></td></tr>
+ <tr><td class=labeltop><&|/l&>Message</&>:</td><td>
+ <& /Elements/MessageBox, Name=>"UpdateContent"&>
+ </td></tr>
+ </table>
+<& /Elements/TitleBoxEnd &>
+
+<& /Elements/TitleBoxStart, title => loc('Edit Relationships'), color => "#336633"&>
+<i><&|/l&>Enter tickets or URIs to link tickets to. Seperate multiple entries with spaces.</&></i><br>
+<& /Ticket/Elements/BulkLinks &>
+<& /Elements/TitleBoxEnd &>
+
+<& /Elements/Submit &>
+
+
+</FORM>
+<%INIT>
+
+# Iterate through the ARGS hash and remove anything with a null value.
+map ($ARGS{$_} =~ /^$/ && (delete $ARGS{$_}), keys %ARGS);
+
+my ($bgcolor, @results);
+my @cols = qw(id Status Priority Subject QueueObj->Name OwnerObj->Name RequestorAddresses DueAsString );
+
+Abort(loc("No search to operate on.")) unless ($session{'tickets'});
+
+
+my $do_comment_reply=0;
+# Prepare for ticket updates
+$ARGS{'UpdateContent'} =~ s/\r\n/\n/g;
+chomp ($ARGS{'UpdateContent'}) ;
+
+if ($ARGS{'UpdateContent'} &&
+ $ARGS{'UpdateContent'} ne '' &&
+ $ARGS{'UpdateContent'} ne "-- \n" .
+ $session{'CurrentUser'}->UserObj->Signature) {
+ $do_comment_reply=1;
+}
+
+#Iterate through each ticket we've been handed
+my @linkresults;
+
+while (my $Ticket = $session{'tickets'}->Next) {
+ $RT::Logger->debug( "Checking Ticket ".$Ticket->Id ."\n");
+ next unless ($ARGS{"UpdateTicket".$Ticket->Id});
+ $RT::Logger->debug ("Matched\n");
+ #Update the basics.
+ my @basicresults = ProcessTicketBasics(TicketObj => $Ticket, ARGSRef => \%ARGS);
+ my @dateresults = ProcessTicketDates(TicketObj => $Ticket, ARGSRef => \%ARGS);
+ #Update the watchers
+ my @watchresults = ProcessTicketWatchers(TicketObj => $Ticket, ARGSRef => \%ARGS);
+
+ #Update the links
+ $ARGS{'id'} = $Ticket;
+ $ARGS{$Ticket->Id.'-MergeInto'} = $ARGS{'Ticket-MergeInto'};
+ $ARGS{$Ticket->Id.'-DependsOn'} = $ARGS{'Ticket-DependsOn'};
+ $ARGS{'DependsOn-'.$Ticket->Id} = $ARGS{'DependsOn-Ticket'};
+ $ARGS{$Ticket->Id.'-MemberOf'} = $ARGS{'Ticket-MemberOf'};
+ $ARGS{'MemberOf-'.$Ticket->Id} = $ARGS{'MemberOf-Ticket'};
+ $ARGS{$Ticket->Id.'-RefersTo'} = $ARGS{'Ticket-RefersTo'};
+ $ARGS{'RefersTo-'.$Ticket->Id} = $ARGS{'RefersTo-Ticket'};
+ @linkresults = ProcessTicketLinks( TicketObj => $Ticket, ARGSRef => \%ARGS);
+ delete $ARGS{'id'};
+ delete $ARGS{$Ticket->Id.'-MergeInto'};
+ delete $ARGS{$Ticket->Id.'-DependsOn'};
+ delete $ARGS{'DependsOn-'.$Ticket->Id};
+ delete $ARGS{$Ticket->Id.'-MemberOf'};
+ delete $ARGS{'MemberOf-'.$Ticket->Id};
+ delete $ARGS{$Ticket->Id.'-RefersTo'};
+ delete $ARGS{'RefersTo-'.$Ticket->Id};
+
+ my @updateresults;
+ if ($do_comment_reply) {
+ ProcessUpdateMessage(TicketObj => $Ticket, ARGSRef => \%ARGS, Actions => \@updateresults);
+ }
+ my @tempresults = (@watchresults, @basicresults, @dateresults, @updateresults, @linkresults);
+ @tempresults = map { loc("Ticket [_1]: [_2]",$Ticket->Id,$_) } @tempresults;
+
+ @results = (@results, @tempresults);
+}
+
+</%INIT>
diff --git a/rt/html/Search/Elements/PickRestriction b/rt/html/Search/Elements/PickRestriction
new file mode 100644
index 000000000..a6911df5a
--- /dev/null
+++ b/rt/html/Search/Elements/PickRestriction
@@ -0,0 +1,141 @@
+%# BEGIN LICENSE BLOCK
+%#
+%# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
+%#
+%# (Except where explictly superceded by other copyright notices)
+%#
+%# This work is made available to you under the terms of Version 2 of
+%# the GNU General Public License. A copy of that license should have
+%# been provided with this software, but in any event can be snarfed
+%# from www.gnu.org.
+%#
+%# This work is distributed in the hope that it will be useful, but
+%# WITHOUT ANY WARRANTY; without even the implied warranty of
+%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+%# General Public License for more details.
+%#
+%# Unless otherwise specified, all modifications, corrections or
+%# extensions to this work which alter its source code become the
+%# property of Best Practical Solutions, LLC when submitted for
+%# inclusion in the work.
+%#
+%#
+%# END LICENSE BLOCK
+<FORM ACTION="Listing.html" METHOD="GET">
+<INPUT TYPE=HIDDEN NAME="Bookmark" VALUE="<% $session{'tickets'}->FreezeLimits()|u %>">
+<& /Elements/TitleBoxStart, title => loc('Refine search')&>
+<INPUT TYPE=HIDDEN NAME="CompileRestriction" VALUE=1>
+
+<ul>
+<li><&|/l&>Owner is</&> <& /Elements/SelectBoolean, Name => "OwnerOp",
+ TrueVal=> '=',
+ FalseVal => '!='
+&>
+<& /Elements/SelectOwner, Name => "ValueOfOwner" &>
+
+<li>
+<&|/l&>Requestor email address</&>
+<& /Elements/SelectMatch, Name => "RequestorOp" &>
+<INPUT Name="ValueOfRequestor" SIZE=20>
+
+<li>
+<&|/l&>Subject</&> <& /Elements/SelectMatch, Name => "SubjectOp" &>
+<INPUT Name="ValueOfSubject" SIZE=20>
+
+<li><&|/l&>Queue</&> <& /Elements/SelectBoolean, Name => "QueueOp" ,
+ True => loc("is"),
+ False => loc("isn't"),
+ TrueVal=> '=',
+ FalseVal => '!=' &>
+<& /Elements/SelectQueue, Name => loc("ValueOfQueue") &>
+
+
+<li><&|/l&>Priority</&> <& /Elements/SelectEqualityOperator, Name => "PriorityOp" &>
+
+<INPUT Name="ValueOfPriority" SIZE=5>
+
+<li>
+<& /Elements/SelectDateType, Name => 'DateType' &>
+<& /Elements/SelectDateRelation, Name=>"DateOp" &>
+<& /Elements/SelectDate, Name => "ValueOfDate", ShowTime => 0, Default => '' &>
+
+<li><&|/l&>Ticket attachment</&>
+
+<& /Elements/SelectAttachmentField, Name => 'AttachmentField' &>
+<& /Elements/SelectBoolean, Name => "AttachmentFieldOp",
+ True => loc("matches"),
+ False => loc("does not match"),
+ TrueVal => 'LIKE',
+ FalseVal => 'NOT LIKE'
+&>
+<Input Name="ValueOfAttachmentField" Size=20>
+
+<li><&|/l&>Status</&>
+<& /Elements/SelectBoolean, Name => "StatusOp",
+ True => loc("is"),
+ False => loc("isn't"),
+ TrueVal=> '=',
+ FalseVal => '!='
+&>
+<& /Elements/SelectStatus, Name => "ValueOfStatus" &>
+
+
+% while ( my $CustomField = $CustomFields->Next ) {
+
+<li><% $CustomField->Name %>
+ <& /Elements/SelectCustomFieldOperator, Name => "CustomFieldOp". $CustomField->id,
+ True => loc("is"),
+ False => loc("isn't"),
+ TrueVal=> '=', FalseVal => '!=' &>
+
+<& /Elements/SelectCustomFieldValue, Name => "CustomField".$CustomField->id,
+ CustomField => $CustomField,
+ &>
+% }
+
+</UL>
+
+<& /Elements/TitleBoxEnd &>
+
+<& /Elements/TitleBoxStart, title => loc('Ordering and sorting')&>
+
+<UL>
+
+<li><&|/l&>Results per page</&> <& /Elements/SelectResultsPerPage, Name => "RowsPerPage",
+ Default => $session{'tickets_rows_per_page'} || '50'
+&>
+
+<li><&|/l&>Sort results by</&> <& /Elements/SelectTicketSortBy, Name => "TicketsSortBy",
+ Default => $session{'tickets_sort_by'}
+&>
+<& /Elements/SelectSortOrder, Name => 'TicketsSortOrder', Default => $session{'tickets_sort_order'} &>
+
+<li><input type="checkbox" name="HideResults" <%$ARGS{'HideResults'} && 'CHECKED'%>> <&|/l&>Don't show search results</&>
+<li><& /Elements/Refresh, Name => 'RefreshSearchInterval' , Default => $session{'tickets_refresh_interval'} &>
+
+</UL>
+
+
+</DIV>
+
+
+
+<& /Elements/TitleBoxEnd &>
+
+<& /Elements/Submit, Label => loc('Search'), Name => 'Action'&>
+
+</FORM>
+
+
+ <%INIT>
+my $CustomFields = RT::CustomFields->new( $session{'CurrentUser'});
+ foreach ( $session{'tickets'}->RestrictionValues('Queue') ) {
+ # Gotta load up the $queue object, since queues get stored by name now.
+ my $queue = RT::Queue->new($session{'CurrentUser'});
+ $queue->Load($_);
+ $CustomFields->LimitToQueue($queue->Id);
+ }
+
+ $CustomFields->LimitToGlobal();
+
+</%INIT>
diff --git a/rt/html/Search/Elements/TicketHeader b/rt/html/Search/Elements/TicketHeader
new file mode 100644
index 000000000..ed2f60e4e
--- /dev/null
+++ b/rt/html/Search/Elements/TicketHeader
@@ -0,0 +1,40 @@
+%# BEGIN LICENSE BLOCK
+%#
+%# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
+%#
+%# (Except where explictly superceded by other copyright notices)
+%#
+%# This work is made available to you under the terms of Version 2 of
+%# the GNU General Public License. A copy of that license should have
+%# been provided with this software, but in any event can be snarfed
+%# from www.gnu.org.
+%#
+%# This work is distributed in the hope that it will be useful, but
+%# WITHOUT ANY WARRANTY; without even the implied warranty of
+%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+%# General Public License for more details.
+%#
+%# Unless otherwise specified, all modifications, corrections or
+%# extensions to this work which alter its source code become the
+%# property of Best Practical Solutions, LLC when submitted for
+%# inclusion in the work.
+%#
+%#
+%# END LICENSE BLOCK
+<TR>
+<& TicketHeaderCell , Attribute => 'id', Header => '#'&>
+<& TicketHeaderCell , Attribute => 'Subject'&>
+<& TicketHeaderCell , Attribute => 'Status'&>
+<& TicketHeaderCell , Attribute => 'Queue'&>
+<& TicketHeaderCell , Attribute => 'Owner'&>
+<& TicketHeaderCell , Attribute => 'Priority'&>
+</TR>
+<TR>
+<TH class="ticketheader">&nbsp;</TH>
+<& TicketHeaderCell , Attribute => 'Requestor(s)'&>
+<& TicketHeaderCell , Attribute => 'Created'&>
+<& TicketHeaderCell , Attribute => 'Told', Header => 'Last Contact'&>
+<& TicketHeaderCell , Attribute => 'LastUpdated', Header => 'Last Updated'&>
+<& TicketHeaderCell , Attribute => 'TimeLeft', Header => 'Left'&>
+</TR>
+%# loc('Last Notified');
diff --git a/rt/html/Search/Elements/TicketHeaderCell b/rt/html/Search/Elements/TicketHeaderCell
new file mode 100644
index 000000000..5def9ea37
--- /dev/null
+++ b/rt/html/Search/Elements/TicketHeaderCell
@@ -0,0 +1,55 @@
+%# BEGIN LICENSE BLOCK
+%#
+%# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
+%#
+%# (Except where explictly superceded by other copyright notices)
+%#
+%# This work is made available to you under the terms of Version 2 of
+%# the GNU General Public License. A copy of that license should have
+%# been provided with this software, but in any event can be snarfed
+%# from www.gnu.org.
+%#
+%# This work is distributed in the hope that it will be useful, but
+%# WITHOUT ANY WARRANTY; without even the implied warranty of
+%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+%# General Public License for more details.
+%#
+%# Unless otherwise specified, all modifications, corrections or
+%# extensions to this work which alter its source code become the
+%# property of Best Practical Solutions, LLC when submitted for
+%# inclusion in the work.
+%#
+%#
+%# END LICENSE BLOCK
+<%INIT>
+my ($order,$curorder);
+ $Attribute =~ s/Obj->(Name|AsString|AgeAsString)//g;
+ if ($session{'tickets_sort_order'} =~ /^asc$/i) {
+ $order = 'DESC';
+ $curorder = 'ASC';
+ } else {
+ $order = 'ASC';
+ $curorder = 'DESC';
+ }
+$Header = $Attribute unless ($Header);
+
+</%INIT>
+<th class="ticketheader">
+% if (grep (/^$Attribute$/i, $session{'tickets'}->SortFields)) {
+<A
+% if ($Attribute eq $session{'tickets_sort_by'}) {
+class="currenttab"
+HREF="<% $RT::WebPath%>/Search/Listing.html?Bookmark=<%$session{'tickets'}->FreezeLimits()|u%>&TicketsSortBy=<%$Attribute%>&TicketsSortOrder=<%$order%>&RowsPerPage=<%$session{'tickets_rows_per_page'}%>">
+% } else {
+HREF="<% $RT::WebPath%>/Search/Listing.html?Bookmark=<%$session{'tickets'}->FreezeLimits()|u%>&TicketsSortBy=<%$Attribute%>&TicketsSortOrder=<%$curorder%>&RowsPerPage=<%$session{'tickets_rows_per_page'}%>">
+% }
+<% loc($Header) %>
+</A>
+% } else {
+<% loc($Header) %>
+% }
+</th>
+<%ARGS>
+$Header => undef
+$Attribute => undef
+</%ARGS>
diff --git a/rt/html/Search/Elements/TicketRow b/rt/html/Search/Elements/TicketRow
new file mode 100644
index 000000000..5d1ad209a
--- /dev/null
+++ b/rt/html/Search/Elements/TicketRow
@@ -0,0 +1,55 @@
+%# BEGIN LICENSE BLOCK
+%#
+%# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
+%#
+%# (Except where explictly superceded by other copyright notices)
+%#
+%# This work is made available to you under the terms of Version 2 of
+%# the GNU General Public License. A copy of that license should have
+%# been provided with this software, but in any event can be snarfed
+%# from www.gnu.org.
+%#
+%# This work is distributed in the hope that it will be useful, but
+%# WITHOUT ANY WARRANTY; without even the implied warranty of
+%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+%# General Public License for more details.
+%#
+%# Unless otherwise specified, all modifications, corrections or
+%# extensions to this work which alter its source code become the
+%# property of Best Practical Solutions, LLC when submitted for
+%# inclusion in the work.
+%#
+%#
+%# END LICENSE BLOCK
+<SPAN class="search">
+<TR
+% if ($i%2) {
+CLASS="oddline"
+% } else {
+CLASS="evenline"
+% }
+>
+<TD ROWSPAN="2"><B><A HREF="<%$RT::WebPath%>/Ticket/Display.html?id=<%$Ticket->Id%>"><%$Ticket->id%></a></B></TD>
+<TD><B><A HREF="<%$RT::WebPath%>/Ticket/Display.html?id=<%$Ticket->Id%>"><%$Ticket->Subject%></a></B></TD>
+<TD><%loc($Ticket->Status)%></TD>
+<TD><%$Ticket->QueueObj->Name%></TD>
+<TD><%$Ticket->Owner == $RT::Nobody->Id ? loc('Nobody') : $Ticket->OwnerObj->Name%></TD>
+<TD><%$Ticket->Priority%></TD>
+</TR>
+<TR
+% if ($i%2) {
+CLASS="oddline"
+% } else {
+CLASS="evenline"
+% }
+><TD><small><%$Ticket->Requestors->MemberEmailAddressesAsString%></small></TD>
+<TD><SMALL><%$Ticket->CreatedObj->AgeAsString || '-'%></SMALL></TD>
+<TD><SMALL><%$Ticket->ToldObj->AgeAsString || '-'%></SMALL></TD>
+<TD><SMALL><%$Ticket->LastUpdatedObj->AgeAsString || '-'%></SMALL></TD>
+<TD><SMALL><%$Ticket->TimeLeft%></SMALL></TD>
+</TR>
+</SPAN>
+<%ARGS>
+$Ticket => undef
+$i => undef
+</%ARGS>
diff --git a/rt/html/Search/Listing.html b/rt/html/Search/Listing.html
new file mode 100644
index 000000000..508534549
--- /dev/null
+++ b/rt/html/Search/Listing.html
@@ -0,0 +1,112 @@
+%# BEGIN LICENSE BLOCK
+%#
+%# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
+%#
+%# (Except where explictly superceded by other copyright notices)
+%#
+%# This work is made available to you under the terms of Version 2 of
+%# the GNU General Public License. A copy of that license should have
+%# been provided with this software, but in any event can be snarfed
+%# from www.gnu.org.
+%#
+%# This work is distributed in the hope that it will be useful, but
+%# WITHOUT ANY WARRANTY; without even the implied warranty of
+%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+%# General Public License for more details.
+%#
+%# Unless otherwise specified, all modifications, corrections or
+%# extensions to this work which alter its source code become the
+%# property of Best Practical Solutions, LLC when submitted for
+%# inclusion in the work.
+%#
+%#
+%# END LICENSE BLOCK
+<& /Elements/Header, Title => $title, Refresh => $session{'tickets_refresh_interval'} &>
+<& /Ticket/Elements/Tabs,
+ current_tab => 'Search/Listing.html',
+ Title => $title &>
+
+%if ($ticketcount && ! $ARGS{'HideResults'}) {
+<TABLE WIDTH=100% border=0 cellpadding=2 CELLSPACING=0>
+<& Elements/TicketHeader, %ARGS &>
+% my $i;
+%while (my $Ticket = $session{'tickets'}->Next) {
+% $i++;
+<& Elements/TicketRow, Ticket => $Ticket, i=> $i, %ARGS &>
+%}
+</TABLE>
+<div align=center>
+<font size=2>
+<a href="Listing.html?GotoPage=1"><&|/l&>First page</&></a>
+&nbsp;&nbsp;
+% if ( $session{'tickets'}->FirstRow >= $session{'tickets_rows_per_page'}-1 ) {
+<a href="Listing.html?GotoPage=Prev">&lt;<&|/l&>Previous page</&></a>
+&nbsp;&nbsp;
+% }
+% if ( $session{'tickets'}->FirstRow + $session{'tickets_rows_per_page'} < $ticketcount ) {
+<a href="Listing.html?GotoPage=Next"><&|/l&>Next page</&>&gt;</a>
+% }
+%#&nbsp;&nbsp;<form method=get action="Listing.html"><&|/l&>Goto page</&> <input name=GotoPage size=2></form>
+</font>
+</div>
+<!--<div align=right>-->
+<table width="100%" border=0 cellpadding=3 CELLSPACING=1>
+<tr>
+<td align=left>
+(<&|/l, ($session{'tickets'}->FirstRow+1), ($session{'tickets'}->FirstRow() + $session{'tickets'}->RowsPerPage() ) &>[_1] - [_2] shown</&>)
+</td>
+<td align=right>
+
+<a href="Bulk.html"><&|/l&>Update all these tickets at once</&></a>
+<!--</div>-->
+</td>
+</tr>
+</table>
+
+% }
+<TABLE WIDTH="100%">
+<TR>
+<TD VALIGN="TOP">
+<& /Elements/TitleBoxStart, title => loc('Current search criteria')&>
+
+%my %restrictions=$session{'tickets'}->DescribeRestrictions();
+%foreach my $row (keys %restrictions){
+<%$restrictions{"$row"}%> <A HREF="<% $RT::WebPath %>/Search/Listing.html?DeleteRestriction=<%$row%>">[<&|/l&>delete</&>]</a><br>
+%}
+<BR>
+<BR>
+<A HREF="<% $RT::WebPath%>/Search/Listing.html?Bookmark=<%$session{'tickets'}->FreezeLimits()|u%>&TicketsSortBy=<%$session{'tickets_sort_by'}%>&TicketsSortOrder=<%$session{'tickets_sort_order'}%>&RowsPerPage=<%$session{'tickets_rows_per_page'}%>"><&|/l&>Bookmarkable URL for this search</&></a>
+<& /Elements/TitleBoxEnd&>
+</TD>
+<TD>
+
+<& Elements/PickRestriction, %ARGS &>
+
+</TD>
+</TR>
+</TABLE>
+
+<%INIT>
+
+my ($title, $ticketcount);
+$session{'i'}++;
+if ($session{'tickets'}) {
+ if ($ARGS{'DeleteRestriction'}) {
+ $session{'tickets'}->DeleteRestriction($ARGS{'DeleteRestriction'});
+ }
+ if ( ($ARGS{'ClearRestrictions'}) || ($ARGS{'NewSearch'}) ) {
+ $session{'tickets'}->ClearRestrictions;
+ }
+}
+ ProcessSearchQuery(ARGS=>\%ARGS);
+ $session{'tickets'}->RedoSearch();
+ if ( $session{'tickets'}->DescribeRestrictions()) {
+ $ticketcount = $session{tickets}->CountAll();
+ $title = loc('Found [quant,_1,ticket]', $ticketcount);
+ } else {
+ $title = loc("Find tickets");
+ }
+</%INIT>
+<%CLEANUP>
+$session{'tickets'}->PrepForSerialization();
+</%CLEANUP>