diff options
-rw-r--r-- | FS/FS/TicketSystem/RT_Internal.pm | 4 | ||||
-rw-r--r-- | httemplate/elements/freeside-menu.css | 10 | ||||
-rw-r--r-- | httemplate/elements/freeside.css | 2 | ||||
-rw-r--r-- | httemplate/elements/notify-tickets.html | 9 | ||||
-rw-r--r-- | httemplate/elements/table-tickets.html | 11 | ||||
-rw-r--r-- | rt/lib/RT/Search/UnrepliedTickets.pm | 21 | ||||
-rw-r--r-- | rt/lib/RT/Ticket_Vendor.pm | 23 | ||||
-rw-r--r-- | rt/share/html/Elements/CollectionAsTable/Row | 5 | ||||
-rw-r--r-- | rt/share/html/Elements/QueueSummaryByLifecycle | 24 | ||||
-rw-r--r-- | rt/share/static/css/freeside3/ticket-lists.css | 14 | ||||
-rw-r--r-- | rt/share/static/css/freeside4/ticket-lists.css | 13 |
11 files changed, 117 insertions, 19 deletions
diff --git a/FS/FS/TicketSystem/RT_Internal.pm b/FS/FS/TicketSystem/RT_Internal.pm index 1c4513e6d..ffee484e9 100644 --- a/FS/FS/TicketSystem/RT_Internal.pm +++ b/FS/FS/TicketSystem/RT_Internal.pm @@ -240,7 +240,8 @@ sub service_tickets { sub _ticket_info { # Takes an RT::Ticket; returns a hashref of the ticket's fields, including # custom fields. Also returns custom and selfservice priority values as - # _custom_priority and _selfservice_priority. + # _custom_priority and _selfservice_priority, and the IsUnreplied property + # as is_unreplied. my $t = shift; my $custom_priority = @@ -265,6 +266,7 @@ sub _ticket_info { if ( $ss_priority ) { $ticket_info{'_selfservice_priority'} = $ticket_info{"CF.{$ss_priority}"}; } + $ticket_info{'is_unreplied'} = $t->IsUnreplied; my $svcnums = [ map { $_->Target =~ /cust_svc\/(\d+)/; $1 } @{ $t->Services->ItemsArrayRef } diff --git a/httemplate/elements/freeside-menu.css b/httemplate/elements/freeside-menu.css index a66ebc0db..365b9d443 100644 --- a/httemplate/elements/freeside-menu.css +++ b/httemplate/elements/freeside-menu.css @@ -142,3 +142,13 @@ a:visited:hover.fsdarkbutton { overflow:visible; } + +/* elements/notify-tickets.html is in the menu area */ +.dot { + border-radius: 50%; + border: 1px solid black; + width: 1ex; + height: 1ex; + display: inline-block; + margin-top: 0.3ex; +} diff --git a/httemplate/elements/freeside.css b/httemplate/elements/freeside.css index 7bf374c84..fb5e7d961 100644 --- a/httemplate/elements/freeside.css +++ b/httemplate/elements/freeside.css @@ -341,3 +341,5 @@ div.package-marker-change_from { border-left: solid #bbffbb 30px; display: inline-block; } + + diff --git a/httemplate/elements/notify-tickets.html b/httemplate/elements/notify-tickets.html index faf998e2b..e661737bc 100644 --- a/httemplate/elements/notify-tickets.html +++ b/httemplate/elements/notify-tickets.html @@ -1,13 +1,4 @@ % if ($enabled) { -<style> -.dot { - border-radius: 50%; - border: 1px solid black; - width: 1ex; - height: 1ex; - display: inline-block; -} -</style> <div style="font-weight: bold; vertical-align: bottom; text-align: left"> % if ( $UnrepliedTickets->Count > 0 ) { <a href="<% $fsurl %>rt/Search/UnrepliedTickets.html"> diff --git a/httemplate/elements/table-tickets.html b/httemplate/elements/table-tickets.html index d722c9d2b..b322a5f7c 100644 --- a/httemplate/elements/table-tickets.html +++ b/httemplate/elements/table-tickets.html @@ -14,6 +14,7 @@ View <THEAD> <TR> + <TH CLASS="grid" BGCOLOR="#cccccc"></TH> <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('#') |h %></TH> <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Subject') |h %></TH> <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Status') |h %></TH> @@ -42,6 +43,16 @@ View <TR> <TD CLASS="grid" BGCOLOR="<% $bgcolor %>"> +% if ( $ticket->{is_unreplied} ) { + <A CLASS="dot" STYLE="background-color: green" HREF=<%$href%>> +% } else { +% # placeholder + <A CLASS="dot" STYLE="visibility: hidden" HREF=<%$href%>> +% } + </A> + </TD> + + <TD CLASS="grid" BGCOLOR="<% $bgcolor %>"> <A HREF=<%$href%>><% $ticket->{id} %></A> </TD> diff --git a/rt/lib/RT/Search/UnrepliedTickets.pm b/rt/lib/RT/Search/UnrepliedTickets.pm index a99690156..12d847a0a 100644 --- a/rt/lib/RT/Search/UnrepliedTickets.pm +++ b/rt/lib/RT/Search/UnrepliedTickets.pm @@ -6,9 +6,9 @@ =head1 DESCRIPTION -Find all unresolved tickets owned by the current user where the last correspondence -from a requestor (or ticket creation) is more recent than the last -correspondence from a non-requestor (if there is any). +Find all unresolved tickets owned by the current user where the last +correspondence from a requestor (or ticket creation) is more recent than the +last correspondence from a non-requestor (if there is any). =head1 METHODS @@ -30,14 +30,23 @@ sub Prepare { my $self = shift; my $TicketsObj = $self->TicketsObj; + # if SystemUser does this search (as in QueueSummaryByLifecycle), they + # should get all tickets regardless of ownership + if ($TicketsObj->CurrentUser->id != RT->SystemUser->id) { + $TicketsObj->Limit( + FIELD => 'Owner', + VALUE => $TicketsObj->CurrentUser->id + ); + } $TicketsObj->Limit( - FIELD => 'Owner', - VALUE => $TicketsObj->CurrentUser->id + FIELD => 'Status', + OPERATOR => '!=', + VALUE => 'resolved' ); $TicketsObj->Limit( FIELD => 'Status', OPERATOR => '!=', - VALUE => 'resolved' + VALUE => 'rejected', ); my $txn_alias = $TicketsObj->JoinTransactions; $TicketsObj->Limit( diff --git a/rt/lib/RT/Ticket_Vendor.pm b/rt/lib/RT/Ticket_Vendor.pm index a55bb7b0d..4a7883888 100644 --- a/rt/lib/RT/Ticket_Vendor.pm +++ b/rt/lib/RT/Ticket_Vendor.pm @@ -92,5 +92,28 @@ sub WillResolveAsString { return $self->WillResolveObj->AsString(); } +=head2 IsUnreplied + +Returns true if there's a Correspond or Create transaction more recent than +the Told date of this ticket (or the ticket has no Told date) and the ticket +is not rejected or resolved. + +=cut + +sub IsUnreplied { + my $self = shift; + return 0 if $self->Status eq 'resolved' + or $self->Status eq 'rejected'; + + my $Told = $self->Told || '1970-01-01'; + my $Txns = $self->Transactions; + $Txns->Limit(FIELD => 'Type', + OPERATOR => 'IN', + VALUE => [ 'Correspond', 'Create' ]); + $Txns->Limit(FIELD => 'Created', + OPERATOR => '>', + VALUE => $Told); + $Txns->Count ? 1 : 0; +} 1; diff --git a/rt/share/html/Elements/CollectionAsTable/Row b/rt/share/html/Elements/CollectionAsTable/Row index deaa312ba..4b2cfae43 100644 --- a/rt/share/html/Elements/CollectionAsTable/Row +++ b/rt/share/html/Elements/CollectionAsTable/Row @@ -57,6 +57,11 @@ $Class => 'RT__Ticket' $Classes => '' </%ARGS> <%init> +# it's a hack, but it has to be applied in every ticket search regardless +# of format, so... +if ( $record and $record->isa('RT::Ticket') and $record->IsUnreplied ) { + $Classes .= ' unreplied-ticket'; +} $m->out( '<tr class="' . $Classes . ' ' . ( $Warning ? 'warnline' : $i % 2 ? 'oddline' : 'evenline' ) . '" >' . "\n" ); diff --git a/rt/share/html/Elements/QueueSummaryByLifecycle b/rt/share/html/Elements/QueueSummaryByLifecycle index f21cb20c3..d6ed1e678 100644 --- a/rt/share/html/Elements/QueueSummaryByLifecycle +++ b/rt/share/html/Elements/QueueSummaryByLifecycle @@ -66,9 +66,13 @@ for my $queue (@queues) { next if lc($queue->{Lifecycle} || '') ne lc $lifecycle->Name; $i++; + + my $classes = $i%2 ? 'oddline' : 'evenline'; + $classes .= ' unreplied-ticket' if $queue->{Unreplied} > 0; </%PERL> -<tr class="<% $i%2 ? 'oddline' : 'evenline'%>" > +<tr class="<% $classes %>"> +<td></td> <td> <a href="<% $link_all->($queue, \@cur_statuses) %>" title="<% $queue->{Description} %>"><% $queue->{Name} %></a> </td> @@ -134,6 +138,24 @@ for my $queue (@queues) { $lifecycle{ lc $cycle->Name } = $cycle; } +use RT::Search::UnrepliedTickets; +my $Tickets = RT::Tickets->new( RT->SystemUser ); +my $Search = RT::Search::UnrepliedTickets->new( TicketsObj => $Tickets ); +$Search->Prepare; + +for my $queue (@queues) { + my $cycle = RT::Lifecycle->Load( Name => $queue->{'Lifecycle'} ); + $lifecycle{ lc $cycle->Name } = $cycle; + + # show whether there are unreplied tickets + # somewhat inefficient but we only use the count query + my $tix = $Tickets->Clone; + $tix->Limit(FIELD => 'Queue', + OPERATOR => '=', + VALUE => $queue->{id}); + $queue->{Unreplied} = $tix->Count; +} + unless (@statuses) { my %seen; foreach my $set ( 'initial', 'active' ) { diff --git a/rt/share/static/css/freeside3/ticket-lists.css b/rt/share/static/css/freeside3/ticket-lists.css index 84c9a92de..257cf3b07 100644 --- a/rt/share/static/css/freeside3/ticket-lists.css +++ b/rt/share/static/css/freeside3/ticket-lists.css @@ -99,8 +99,18 @@ tr.collection-as-table+tr.collection-as-table th { } - - +tr.unreplied-ticket > :first-child::before { + /* green dot */ + border: 1px solid black; + border-radius: 50%; + display: inline-block; + height: 1ex; + width: 1ex; + float: left; + content: ''; + margin-top: 1ex; + background-color: green; +} table.queue-summary td { background: #efefef; diff --git a/rt/share/static/css/freeside4/ticket-lists.css b/rt/share/static/css/freeside4/ticket-lists.css index cdf10193a..3d4706fd2 100644 --- a/rt/share/static/css/freeside4/ticket-lists.css +++ b/rt/share/static/css/freeside4/ticket-lists.css @@ -81,6 +81,19 @@ table.collection-as-table.chart th { border-bottom: 2px solid #ccc } +tr.unreplied-ticket > :first-child::before { + /* green dot */ + border: 1px solid black; + border-radius: 50%; + display: inline-block; + height: 1ex; + width: 1ex; + float: left; + content: ''; + margin-right: 1ex; + background-color: green; +} + table.queue-summary td { background: #efefef; border-bottom: 1px solid #ccc; |