rt 4.2.15
[freeside.git] / rt / share / html / Elements / RT__Ticket / ColumnMap
1 %# BEGIN BPS TAGGED BLOCK {{{
2 %#
3 %# COPYRIGHT:
4 %#
5 %# This software is Copyright (c) 1996-2018 Best Practical Solutions, LLC
6 %#                                          <sales@bestpractical.com>
7 %#
8 %# (Except where explicitly superseded by other copyright notices)
9 %#
10 %#
11 %# LICENSE:
12 %#
13 %# This work is made available to you under the terms of Version 2 of
14 %# the GNU General Public License. A copy of that license should have
15 %# been provided with this software, but in any event can be snarfed
16 %# from www.gnu.org.
17 %#
18 %# This work is distributed in the hope that it will be useful, but
19 %# WITHOUT ANY WARRANTY; without even the implied warranty of
20 %# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21 %# General Public License for more details.
22 %#
23 %# You should have received a copy of the GNU General Public License
24 %# along with this program; if not, write to the Free Software
25 %# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26 %# 02110-1301 or visit their web page on the internet at
27 %# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html.
28 %#
29 %#
30 %# CONTRIBUTION SUBMISSION POLICY:
31 %#
32 %# (The following paragraph is not intended to limit the rights granted
33 %# to you to modify and distribute this software under the terms of
34 %# the GNU General Public License and is only of importance to you if
35 %# you choose to contribute your changes and enhancements to the
36 %# community by submitting them to Best Practical Solutions, LLC.)
37 %#
38 %# By intentionally submitting any modifications, corrections or
39 %# derivatives to this work, or any other work intended for use with
40 %# Request Tracker, to Best Practical Solutions, LLC, you confirm that
41 %# you are the copyright holder for those contributions and you grant
42 %# Best Practical Solutions,  LLC a nonexclusive, worldwide, irrevocable,
43 %# royalty-free, perpetual, license to use, copy, create derivative
44 %# works based on those contributions, and sublicense and distribute
45 %# those contributions and any derivatives thereof.
46 %#
47 %# END BPS TAGGED BLOCK }}}
48 <%ARGS>
49 $Name => undef
50 $Attr => undef
51 $GenericMap => {}
52 </%ARGS>
53
54
55 <%ONCE>
56 my $COLUMN_MAP;
57
58 my $LinkCallback = sub {
59     my $method = shift;
60
61     my $mode            = $RT::Link::TYPEMAP{$method}{Mode};
62     my $type            = $RT::Link::TYPEMAP{$method}{Type};
63     my $other_mode      = ($mode eq "Target" ? "Base" : "Target");
64     my $mode_uri        = $mode.'URI';
65
66     return sub {
67         my $ObjectType = $_[2]||'';
68         map {
69             \'<a href="',
70             $_->$mode_uri->AsHREF,
71             \'">',
72             ( $_->$mode_uri->AsString ),
73             \'</a><br />',
74         } # if someone says __RefersTo.{Ticket}__ filter for only local links that are tickets
75           grep { $ObjectType
76                     ? ( $_->$mode_uri->IsLocal
77                         && ( $_->$mode_uri->Object->RecordType eq $ObjectType ))
78                     : 1
79                }
80           @{ $_[0]->Links($other_mode,$type)->ItemsArrayRef }
81     }
82 };
83
84 my $trustSub = sub {
85     my $user = shift;
86     my %key = RT::Crypt->GetKeyInfo( Key => $user->EmailAddress );
87     if (!defined $key{'info'}) {
88         return $m->interp->apply_escapes(' ' . loc("(no pubkey!)"), "h");
89     } elsif ($key{'info'}{'TrustLevel'} == 0) {
90         return $m->interp->apply_escapes(' ' . loc("(untrusted!)"), "h");
91     }
92 };
93
94 $COLUMN_MAP = {
95     Queue => {
96         attribute => 'Queue',
97         title     => 'Queue id', # loc
98         value     => sub { return $_[0]->Queue }
99     },
100     QueueName => {
101         attribute => 'Queue',
102         title     => 'Queue', # loc
103         value     => sub { return $_[0]->QueueObj->Name }
104     },
105     OwnerName => {
106         title     => 'Owner', # loc
107         attribute => 'Owner',
108         value     => sub { return $_[0]->OwnerObj->Name }
109     },
110     Status => {
111         title     => 'Status', # loc
112         attribute => 'Status',
113         value     => sub { return loc($_[0]->Status) }
114     },
115     Subject => {
116         title     => 'Subject', # loc
117         attribute => 'Subject',
118         value     => sub { return $_[0]->Subject || "(" . loc('No subject') . ")" }
119     },
120     ExtendedStatus => {
121         title     => 'Status', # loc
122         attribute => 'Status',
123         value     => sub {
124             my $Ticket = shift;
125
126             if ( my $count = $Ticket->HasUnresolvedDependencies ) {
127                 if (   $Ticket->HasUnresolvedDependencies( Type => 'approval' )
128                     or $Ticket->HasUnresolvedDependencies( Type => 'code' ) )
129                 {
130                     return \'<em>', loc('(pending approval)'), \'</em>';
131                 }
132                 else {
133                     my $Query = "DependedOnBy = " . $Ticket->id;
134                     $Query .= " AND (" . join(" OR ", map { "Status = '$_'" } RT::Queue->ActiveStatusArray) . ")";
135
136                     my $SearchURL = RT->Config->Get('WebPath') . '/Search/Results.html?' . $m->comp('/Elements/QueryString', Query => $Query);
137
138                     return \'<a href="',$SearchURL,\'">', loc('(pending [quant,_1,other ticket,other tickets])',$count), \'</a>';
139                 }
140             }
141             else {
142                 return loc( $Ticket->Status );
143             }
144
145           }
146     },
147     Priority => {
148         title     => 'Priority', # loc
149         attribute => 'Priority',
150         value     => sub { return $_[0]->Priority }
151     },
152     InitialPriority => {
153         title     => 'InitialPriority', # loc
154         attribute => 'InitialPriority',
155         name      => 'Initial Priority',
156         value     => sub { return $_[0]->InitialPriority }
157     },
158     FinalPriority => {
159         title     => 'FinalPriority', # loc
160         attribute => 'FinalPriority',
161         name      => 'Final Priority',
162         value     => sub { return $_[0]->FinalPriority }
163     },
164     EffectiveId => {
165         title     => 'EffectiveId', # loc
166         attribute => 'EffectiveId',
167         value     => sub { return $_[0]->EffectiveId }
168     },
169     Type => {
170         title     => 'Type', # loc
171         attribute => 'Type',
172         value     => sub { return $_[0]->Type }
173     },
174     TimeWorked => {
175         attribute => 'TimeWorked',
176         title     => 'Time Worked', # loc
177         value     => sub { return $_[0]->TimeWorked }
178     },
179     TimeLeft => {
180         attribute => 'TimeLeft',
181         title     => 'Time Left', # loc
182         value     => sub { return $_[0]->TimeLeftAsString }
183     },
184     TimeEstimated => {
185         attribute => 'TimeEstimated',
186         title     => 'Time Estimated', # loc
187         value     => sub { return $_[0]->TimeEstimated }
188     },
189     StartsRelative => {
190         title     => 'Starts', # loc
191         attribute => 'Starts',
192         value     => sub { return $_[0]->StartsObj->AgeAsString }
193     },
194     StartedRelative => {
195         title     => 'Started', # loc
196         attribute => 'Started',
197         value     => sub { return $_[0]->StartedObj->AgeAsString }
198     },
199     ToldRelative => {
200         title     => 'Told', # loc
201         attribute => 'Told',
202         value     => sub { return $_[0]->ToldObj->AgeAsString }
203     },
204     DueRelative => {
205         title     => 'Due', # loc
206         attribute => 'Due',
207         value     => sub { 
208             my $date = $_[0]->DueObj;
209             # Highlight the date if it was due in the past, and it's still active
210             if ( $date && $date->IsSet && $date->Diff < 0 && $_[0]->QueueObj->IsActiveStatus($_[0]->Status)) {
211                 return (\'<span class="overdue">' , $date->AgeAsString , \'</span>');
212             } else {
213                 return $date->AgeAsString;
214             }
215         }
216     },
217     WillResolveRelative => {
218         title     => 'Will Resolve',
219         attribute => 'WillResolve',
220         value     => sub { return $_[0]->WillResolveObj->AgeAsString },
221     },
222     ResolvedRelative => {
223         title     => 'Resolved', # loc
224         attribute => 'Resolved',
225         value     => sub { return $_[0]->ResolvedObj->AgeAsString }
226     },
227     Starts => {
228         title     => 'Starts', # loc
229         attribute => 'Starts',
230         value     => sub { return $_[0]->StartsObj }
231     },
232     Started => {
233         title     => 'Started', # loc
234         attribute => 'Started',
235         value     => sub { return $_[0]->StartedObj },
236     },
237     Told => {
238         title     => 'Told', # loc
239         attribute => 'Told',
240         value     => sub { return $_[0]->ToldObj },
241     },
242     Due => {
243         title     => 'Due', # loc
244         attribute => 'Due',
245         value     => sub { return $_[0]->DueObj },
246     },
247     WillResolve => {
248         title     => 'Will Resolve',
249         attribute => 'WillResolve',
250         value     => sub { return $_[0]->WillResolveObj },
251     },
252     Resolved => {
253         title     => 'Resolved', # loc
254         attribute => 'Resolved',
255         value     => sub { return $_[0]->ResolvedObj }
256     },
257     UpdateStatus => {
258         title => 'New messages', # loc
259         value => sub {
260             my $txn = $_[0]->SeenUpTo or return $_[0]->loc('No');
261             return \('<a href="'. RT->Config->Get('WebPath') .'/Ticket/Display.html?id='
262                 . $_[0]->id .'#txn-'. $txn->id .'">'),
263                 $_[0]->loc('New'), \'</a>';
264         },
265     },
266     KeyRequestors => {
267         title     => 'Requestors', # loc
268         attribute => 'Requestor.EmailAddress',
269         value     => sub { return \($m->scomp("/Elements/ShowPrincipal", Object => $_[0]->Requestor, PostUser => $trustSub ) ) }
270     },
271     KeyOwnerName => {
272         title     => 'Owner', # loc
273         attribute => 'Owner',
274         value     => sub {
275             my $t = shift;
276             my $name = $t->OwnerObj->Name;
277             my %key = RT::Crypt->GetKeyInfo( Key => $t->OwnerObj->EmailAddress );
278             if (!defined $key{'info'}) {
279                 $name .= ' '. loc("(no pubkey!)");
280             }
281             elsif ($key{'info'}{'TrustLevel'} == 0) {
282                 $name .= ' '. loc("(untrusted!)");
283             }
284
285             return $name;
286         }
287     },
288     KeyOwner => {
289         title     => 'Owner', # loc
290         attribute => 'Owner',
291         value     => sub { return \($m->scomp("/Elements/ShowPrincipal", Object => $_[0]->OwnerObj, PostUser => $trustSub ) ) }
292     },
293
294     # Everything from LINKTYPEMAP
295     (map {
296         $_ => { value => $LinkCallback->( $_ ) }
297     } keys %RT::Link::TYPEMAP),
298
299     '_CLASS' => {
300         value => sub { return $_[1] % 2 ? 'oddline' : 'evenline' }
301     },
302     '_CHECKBOX' => {
303         attribute => 'checkbox',
304         title => 'Update', # loc
305         align     => 'right',
306         value     => sub { return \('<input type="checkbox" class="checkbox" name="UpdateTicket'.$_[0]->id.'" value="1" checked="checked" />') }
307     },
308
309     Bookmark => {
310         title => ' ',
311         value => sub {
312             my $bookmark = $m->scomp( '/Ticket/Elements/Bookmark', id => $_[0]->id );
313             # the CollectionAsTable/Row template replaces newlines with <br>
314             $bookmark =~ s/\n//g;
315
316             return \$bookmark;
317         },
318     },
319     
320     #freeside
321     $m->comp('/Elements/CustomerFields', 'ColumnMap'),
322     $m->comp('/Elements/ServiceFields', 'ColumnMap'),
323 };
324 </%ONCE>
325 <%init>
326 # if no encryption support, then KeyOwnerName and KeyRequestors fall back to the regular
327 # versions
328 unless (RT->Config->Get('Crypt')->{'Enable'}) {
329     $COLUMN_MAP->{KeyOwnerName}  = $COLUMN_MAP->{OwnerName};
330     $COLUMN_MAP->{KeyRequestors} = $GenericMap->{Requestors};
331 }
332
333 $m->callback( GenericMap => $GenericMap, COLUMN_MAP => $COLUMN_MAP, CallbackName => 'Once', CallbackOnce => 1 );
334 return GetColumnMapEntry( Map => $COLUMN_MAP, Name => $Name, Attribute => $Attr );
335 </%init>