Merge branch 'master' of https://github.com/jgoodman/Freeside
[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-2014 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 </%ARGS>
52
53
54 <%ONCE>
55 my $COLUMN_MAP;
56
57 my $LinkCallback = sub {
58     my $method = shift;
59
60     my $mode            = $RT::Ticket::LINKTYPEMAP{$method}{Mode};
61     my $type            = $RT::Ticket::LINKTYPEMAP{$method}{Type};
62     my $other_mode      = ($mode eq "Target" ? "Base" : "Target");
63     my $mode_uri        = $mode.'URI';
64     my $local_type      = 'Local'.$mode;
65
66     return sub {
67         map {
68             \'<a href="',
69             $_->$mode_uri->Resolver->HREF,
70             \'">',
71             ( $_->$mode_uri->IsLocal && $_->$local_type ? $_->$local_type : $_->$mode_uri->Resolver->AsString ),
72             \'</a><br />',
73         } @{ $_[0]->Links($other_mode,$type)->ItemsArrayRef }
74     }
75 };
76
77 $COLUMN_MAP = {
78     Queue => {
79         attribute => 'Queue',
80         title     => 'Queue id', # loc
81         value     => sub { return $_[0]->Queue }
82     },
83     QueueName => {
84         attribute => 'Queue',
85         title     => 'Queue', # loc
86         value     => sub { return $_[0]->QueueObj->Name }
87     },
88     OwnerName => {
89         title     => 'Owner', # loc
90         attribute => 'Owner',
91         value     => sub { return $_[0]->OwnerObj->Name }
92     },
93     Status => {
94         title     => 'Status', # loc
95         attribute => 'Status',
96         value     => sub { return loc($_[0]->Status) }
97     },
98     Subject => {
99         title     => 'Subject', # loc
100         attribute => 'Subject',
101         value     => sub { return $_[0]->Subject || "(" . loc('No subject') . ")" }
102     },
103     ExtendedStatus => {
104         title     => 'Status', # loc
105         attribute => 'Status',
106         value     => sub {
107             my $Ticket = shift;
108
109             if ( my $count = $Ticket->HasUnresolvedDependencies ) {
110                 if (   $Ticket->HasUnresolvedDependencies( Type => 'approval' )
111                     or $Ticket->HasUnresolvedDependencies( Type => 'code' ) )
112                 {
113                     return \'<em>', loc('(pending approval)'), \'</em>';
114                 }
115                 else {
116                     my $Query = "DependedOnBy = " . $Ticket->id;
117                     $Query .= " AND (" . join(" OR ", map { "Status = '$_'" } RT::Queue->ActiveStatusArray) . ")";
118
119                     my $SearchURL = RT->Config->Get('WebPath') . '/Search/Results.html?' . $m->comp('/Elements/QueryString', Query => $Query);
120
121                     return \'<a href="',$SearchURL,\'">', loc('(pending [quant,_1,other ticket])',$count), \'</a>';
122                 }
123             }
124             else {
125                 return loc( $Ticket->Status );
126             }
127
128           }
129     },
130     Priority => {
131         title     => 'Priority', # loc
132         attribute => 'Priority',
133         value     => sub { return $_[0]->Priority }
134     },
135     InitialPriority => {
136         title     => 'InitialPriority', # loc
137         attribute => 'InitialPriority',
138         name      => 'Initial Priority',
139         value     => sub { return $_[0]->InitialPriority }
140     },
141     FinalPriority => {
142         title     => 'FinalPriority', # loc
143         attribute => 'FinalPriority',
144         name      => 'Final Priority',
145         value     => sub { return $_[0]->FinalPriority }
146     },
147     EffectiveId => {
148         title     => 'EffectiveId', # loc
149         attribute => 'EffectiveId',
150         value     => sub { return $_[0]->EffectiveId }
151     },
152     Type => {
153         title     => 'Type', # loc
154         attribute => 'Type',
155         value     => sub { return $_[0]->Type }
156     },
157     TimeWorked => {
158         attribute => 'TimeWorked',
159         title     => 'Time Worked', # loc
160         value     => sub { return $_[0]->TimeWorked }
161     },
162     TimeLeft => {
163         attribute => 'TimeLeft',
164         title     => 'Time Left', # loc
165         value     => sub { return $_[0]->TimeLeftAsString }
166     },
167     TimeEstimated => {
168         attribute => 'TimeEstimated',
169         title     => 'Time Estimated', # loc
170         value     => sub { return $_[0]->TimeEstimated }
171     },
172     Requestors => {
173         title     => 'Requestors', # loc
174         attribute => 'Requestor.EmailAddress',
175         value     => sub { return $_[0]->Requestors->MemberEmailAddressesAsString }
176     },
177     Cc => {
178         title     => 'Cc', # loc
179         attribute => 'Cc.EmailAddress',
180         value     => sub { return $_[0]->Cc->MemberEmailAddressesAsString }
181     },
182     AdminCc => {
183         title     => 'AdminCc', # loc
184         attribute => 'AdminCc.EmailAddress',
185         value     => sub { return $_[0]->AdminCc->MemberEmailAddressesAsString }
186     },
187     StartsRelative => {
188         title     => 'Starts', # loc
189         attribute => 'Starts',
190         value     => sub { return $_[0]->StartsObj->AgeAsString }
191     },
192     StartedRelative => {
193         title     => 'Started', # loc
194         attribute => 'Started',
195         value     => sub { return $_[0]->StartedObj->AgeAsString }
196     },
197     ToldRelative => {
198         title     => 'Told', # loc
199         attribute => 'Told',
200         value     => sub { return $_[0]->ToldObj->AgeAsString }
201     },
202     DueRelative => {
203         title     => 'Due', # loc
204         attribute => 'Due',
205         value     => sub { 
206             my $date = $_[0]->DueObj;
207             # Highlight the date if it was due in the past, and it's still active
208             if ( $date && $date->Unix > 0 && $date->Diff < 0 && $_[0]->QueueObj->IsActiveStatus($_[0]->Status)) {
209                 return (\'<span class="overdue">' , $date->AgeAsString , \'</span>');
210             } else {
211                 return $date->AgeAsString;
212             }
213         }
214     },
215     WillResolveRelative => {
216         title     => 'Will Resolve',
217         attribute => 'WillResolve',
218         value     => sub { return $_[0]->WillResolveObj->AgeAsString },
219     },
220     ResolvedRelative => {
221         title     => 'Resolved', # loc
222         attribute => 'Resolved',
223         value     => sub { return $_[0]->ResolvedObj->AgeAsString }
224     },
225     Starts => {
226         title     => 'Starts', # loc
227         attribute => 'Starts',
228         value     => sub { return $_[0]->StartsObj }
229     },
230     Started => {
231         title     => 'Started', # loc
232         attribute => 'Started',
233         value     => sub { return $_[0]->StartedObj },
234     },
235     Told => {
236         title     => 'Told', # loc
237         attribute => 'Told',
238         value     => sub { return $_[0]->ToldObj },
239     },
240     Due => {
241         title     => 'Due', # loc
242         attribute => 'Due',
243         value     => sub { return $_[0]->DueObj },
244     },
245     WillResolve => {
246         title     => 'Will Resolve',
247         attribute => 'WillResolve',
248         value     => sub { return $_[0]->WillResolveObj },
249     },
250     Resolved => {
251         title     => 'Resolved', # loc
252         attribute => 'Resolved',
253         value     => sub { return $_[0]->ResolvedObj }
254     },
255     UpdateStatus => {
256         title => 'New messages', # loc
257         value => sub {
258             my $txn = $_[0]->SeenUpTo or return $_[0]->loc('No');
259             return \('<a href="'. RT->Config->Get('WebPath') .'/Ticket/Display.html?id='
260                 . $_[0]->id .'#txn-'. $txn->id .'">'),
261                 $_[0]->loc('New'), \'</a>';
262         },
263     },
264     KeyRequestors => {
265         title     => 'Requestors', # loc
266         attribute => 'Requestor.EmailAddress',
267         value => sub {
268             my $t = shift;
269             my @requestors = $t->Requestors->MemberEmailAddresses;
270             for my $email (@requestors)
271             {
272                 my %key = RT::Crypt::GnuPG::GetKeyInfo($email);
273                 if (!defined $key{'info'}) {
274                     $email .= ' ' . loc("(no pubkey!)");
275                 }
276                 elsif ($key{'info'}{'TrustLevel'} == 0) {
277                     $email .= ' ' . loc("(untrusted!)");
278                 }
279             }
280             return join ', ', @requestors;
281         }
282     },
283     KeyOwnerName => {
284         title     => 'Owner', # loc
285         attribute => 'Owner',
286         value     => sub {
287             my $t = shift;
288             my $name = $t->OwnerObj->Name;
289             my %key = RT::Crypt::GnuPG::GetKeyInfo($t->OwnerObj->EmailAddress);
290             if (!defined $key{'info'}) {
291                 $name .= ' '. loc("(no pubkey!)");
292             }
293             elsif ($key{'info'}{'TrustLevel'} == 0) {
294                 $name .= ' '. loc("(untrusted!)");
295             }
296
297             return $name;
298         }
299     },
300
301     # Everything from LINKTYPEMAP
302     (map {
303         $_ => { value => $LinkCallback->( $_ ) }
304     } keys %RT::Ticket::LINKTYPEMAP),
305
306     '_CLASS' => {
307         value => sub { return $_[1] % 2 ? 'oddline' : 'evenline' }
308     },
309     '_CHECKBOX' => {
310         attribute => 'checkbox',
311         title => 'Update', # loc
312         align     => 'right',
313         value     => sub { return \('<input type="checkbox" class="checkbox" name="UpdateTicket'.$_[0]->id.'" value="1" checked="checked" />') }
314     },
315
316     Bookmark => {
317         title => ' ',
318         value => sub {
319             my $bookmark = $m->scomp( '/Ticket/Elements/Bookmark', id => $_[0]->id );
320             # the CollectionAsTable/Row template replaces newlines with <br>
321             $bookmark =~ s/\n//g;
322
323             return \$bookmark;
324         },
325     },
326     
327     #freeside
328     $m->comp('/Elements/CustomerFields', 'ColumnMap'),
329     $m->comp('/Elements/ServiceFields', 'ColumnMap'),
330 };
331
332 # if no GPG support, then KeyOwnerName and KeyRequestors fall back to the regular
333 # versions
334 if (RT->Config->Get('GnuPG')->{'Enable'}) {
335     require RT::Crypt::GnuPG;
336 }
337 else {
338     $COLUMN_MAP->{KeyOwnerName} = $COLUMN_MAP->{OwnerName};
339     $COLUMN_MAP->{KeyRequestors} = $COLUMN_MAP->{Requestors};
340 }
341 </%ONCE>
342 <%init>
343 $m->callback( COLUMN_MAP => $COLUMN_MAP, CallbackName => 'Once', CallbackOnce => 1 );
344 # backward compatibility
345 $m->callback( COLUMN_MAP => $COLUMN_MAP, CallbackName => 'ColumnMap' );
346 return GetColumnMapEntry( Map => $COLUMN_MAP, Name => $Name, Attribute => $Attr );
347 </%init>