Merge branch 'master' of git.freeside.biz:/home/git/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-2012 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 : $_->$mode ),
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     ResolvedRelative => {
216         title     => 'Resolved', # loc
217         attribute => 'Resolved',
218         value     => sub { return $_[0]->ResolvedObj->AgeAsString }
219     },
220     Starts => {
221         title     => 'Starts', # loc
222         attribute => 'Starts',
223         date      => sub { return $_[0]->StartsObj },
224         value     => sub { return $_[0]->StartsObj->AsString }
225     },
226     Started => {
227         title     => 'Started', # loc
228         attribute => 'Started',
229         date      => sub { return $_[0]->StartedObj },
230         value     => sub { return $_[0]->StartedObj->AsString }
231     },
232     Told => {
233         title     => 'Told', # loc
234         attribute => 'Told',
235         date      => sub { return $_[0]->ToldObj },
236         value     => sub { return $_[0]->ToldObj->AsString }
237     },
238     Due => {
239         title     => 'Due', # loc
240         attribute => 'Due',
241         date      => sub { return $_[0]->DueObj },
242         value     => sub { return $_[0]->DueObj->AsString }
243     },
244     Resolved => {
245         title     => 'Resolved', # loc
246         attribute => 'Resolved',
247         date      => sub { return $_[0]->ResolvedObj },
248         value     => sub { return $_[0]->ResolvedObj->AsString }
249     },
250     UpdateStatus => {
251         title => 'New messages', # loc
252         value => sub {
253             my $txn = $_[0]->SeenUpTo or return $_[0]->loc('No');
254             return \('<a href="'. RT->Config->Get('WebPath') .'/Ticket/Display.html?id='
255                 . $_[0]->id .'#txn-'. $txn->id .'">'),
256                 $_[0]->loc('New'), \'</a>';
257         },
258     },
259     KeyRequestors => {
260         title     => 'Requestors', # loc
261         attribute => 'Requestor.EmailAddress',
262         value => sub {
263             my $t = shift;
264             my @requestors = $t->Requestors->MemberEmailAddresses;
265             for my $email (@requestors)
266             {
267                 my %key = RT::Crypt::GnuPG::GetKeyInfo($email);
268                 if (!defined $key{'info'}) {
269                     $email .= ' ' . loc("(no pubkey!)");
270                 }
271                 elsif ($key{'info'}{'TrustLevel'} == 0) {
272                     $email .= ' ' . loc("(untrusted!)");
273                 }
274             }
275             return join ', ', @requestors;
276         }
277     },
278     KeyOwnerName => {
279         title     => 'Owner', # loc
280         attribute => 'Owner',
281         value     => sub {
282             my $t = shift;
283             my $name = $t->OwnerObj->Name;
284             my %key = RT::Crypt::GnuPG::GetKeyInfo($t->OwnerObj->EmailAddress);
285             if (!defined $key{'info'}) {
286                 $name .= ' '. loc("(no pubkey!)");
287             }
288             elsif ($key{'info'}{'TrustLevel'} == 0) {
289                 $name .= ' '. loc("(untrusted!)");
290             }
291
292             return $name;
293         }
294     },
295
296     # Everything from LINKTYPEMAP
297     (map {
298         $_ => { value => $LinkCallback->( $_ ) }
299     } keys %RT::Ticket::LINKTYPEMAP),
300
301     '_CLASS' => {
302         value => sub { return $_[1] % 2 ? 'oddline' : 'evenline' }
303     },
304     '_CHECKBOX' => {
305         attribute => 'checkbox',
306         title => 'Update', # loc
307         align     => 'right',
308         value     => sub { return \('<input type="checkbox" class="checkbox" name="UpdateTicket'.$_[0]->id.'" value="1" checked="checked" />') }
309     },
310
311     Bookmark => {
312         title => ' ',
313         value => sub {
314             my $bookmark = $m->scomp( '/Ticket/Elements/Bookmark', id => $_[0]->id );
315             # the CollectionAsTable/Row template replaces newlines with <br>
316             $bookmark =~ s/\n//g;
317
318             return \$bookmark;
319         },
320     },
321     
322     #freeside
323     $m->comp('/Elements/CustomerFields', 'ColumnMap'),
324     $m->comp('/Elements/ServiceFields', 'ColumnMap'),
325 };
326
327 # if no GPG support, then KeyOwnerName and KeyRequestors fall back to the regular
328 # versions
329 if (RT->Config->Get('GnuPG')->{'Enable'}) {
330     require RT::Crypt::GnuPG;
331 }
332 else {
333     $COLUMN_MAP->{KeyOwnerName} = $COLUMN_MAP->{OwnerName};
334     $COLUMN_MAP->{KeyRequestors} = $COLUMN_MAP->{Requestors};
335 }
336 </%ONCE>
337 <%init>
338 $m->callback( COLUMN_MAP => $COLUMN_MAP, CallbackName => 'Once', CallbackOnce => 1 );
339 # backward compatibility
340 $m->callback( COLUMN_MAP => $COLUMN_MAP, CallbackName => 'ColumnMap' );
341 return GetColumnMapEntry( Map => $COLUMN_MAP, Name => $Name, Attribute => $Attr );
342 </%init>