-%# BEGIN LICENSE BLOCK;
+%# BEGIN BPS TAGGED BLOCK {{{
%#
-%# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
+%# COPYRIGHT:
+%#
+%# This software is Copyright (c) 1996-2009 Best Practical Solutions, LLC
+%# <jesse@bestpractical.com>
%#
-%# (Except where explictly superceded by other copyright notices)
+%# (Except where explicitly superseded by other copyright notices)
+%#
+%#
+%# LICENSE:
%#
%# 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
%# 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.
+%# You should have received a copy of the GNU General Public License
+%# along with this program; if not, write to the Free Software
+%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+%# 02110-1301 or visit their web page on the internet at
+%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html.
%#
%#
-%# END LICENSE BLOCK
-
+%# CONTRIBUTION SUBMISSION POLICY:
+%#
+%# (The following paragraph is not intended to limit the rights granted
+%# to you to modify and distribute this software under the terms of
+%# the GNU General Public License and is only of importance to you if
+%# you choose to contribute your changes and enhancements to the
+%# community by submitting them to Best Practical Solutions, LLC.)
+%#
+%# By intentionally submitting any modifications, corrections or
+%# derivatives to this work, or any other work intended for use with
+%# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+%# you are the copyright holder for those contributions and you grant
+%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
+%# royalty-free, perpetual, license to use, copy, create derivative
+%# works based on those contributions, and sublicense and distribute
+%# those contributions and any derivatives thereof.
+%#
+%# END BPS TAGGED BLOCK }}}
<%ARGS>
$Name => undef
$Attr => undef
</%ARGS>
-<%perl>
-return ColumnMap($Name, $Attr);
-</%perl>
-<%INIT>
-our ( $COLUMN_MAP, $CUSTOM_FIELD_MAP );
+<%ONCE>
+our ( $COLUMN_MAP );
-sub ColumnMap {
+my $ColumnMap = sub {
my $name = shift;
my $attr = shift;
# now, let's deal with harder things, like Custom Fields
- elsif ( $name =~ /^(?:CF|CustomField).(.*)$/ ) {
+ elsif ( $name =~ /^(?:CF|CustomField)\.\{(.+)\}$/ ) {
my $field = $1;
- my $cf;
- if ( $CUSTOM_FIELD_MAP->{$field} ) {
- $cf = $CUSTOM_FIELD_MAP->{$field};
- }
- else {
-
- $cf = RT::CustomField->new( $session{'CurrentUser'} );
-
- if ( $field =~ /^(.+?)\.{(.+)}$/ ) {
- $cf->LoadByNameAndQueue( Queue => $1, Name => $2 );
- }
- else {
- $field = $1 if $field =~ /^{(.+)}$/; # trim { }
- $cf->LoadByNameAndQueue( Queue => "0", Name => $field );
- }
- $CUSTOM_FIELD_MAP->{$field} = $cf if ( $cf->id );
- }
-
- unless ( $cf->id ) {
- return undef;
- }
if ( $attr eq 'attribute' ) {
- return (undef);
+ return ("CF.{$field}");
}
elsif ( $attr eq 'title' ) {
- return ( $cf->Name );
+ return ( $field );
}
elsif ( $attr eq 'value' ) {
- my $value = eval "sub {
- my \$values = \$_[0]->CustomFieldValues('" . $cf->id . "');
- return ( join( ', ', map { \$_->Content } \@{ \$values->ItemsArrayRef } ))
- }" || die $@;
- return ($value);
+ # Display custom field contents, separated by newlines.
+ # For Image custom fields we also show a thumbnail here.
+ return sub {
+ my $values = $_[0]->CustomFieldValues($field);
+ my @values = map {
+ (
+ ($_->CustomFieldObj->Type eq 'Image')
+ ? \($m->scomp( '/Elements/ShowCustomFieldImage', Object => $_ ))
+ : $_->Content
+ ),
+ \'<br />',
+ } @{ $values->ItemsArrayRef };
+ pop @values; # Remove that last <br />
+ return @values;
+ };
}
}
-}
+};
+
+my $LinkCallback = sub {
+ my $method = shift;
+
+ my $mode = $RT::Ticket::LINKTYPEMAP{$method}{Mode};
+ my $type = $RT::Ticket::LINKTYPEMAP{$method}{Type};
+ my $other_mode = ($mode eq "Target" ? "Base" : "Target");
+ my $mode_uri = $mode.'URI';
+ my $local_type = 'Local'.$mode;
+
+ return sub {
+ map {
+ \'<a href="',
+ $_->$mode_uri->Resolver->HREF,
+ \'">',
+ ( $_->$mode_uri->IsLocal ? $_->$local_type : $_->$mode ),
+ \'</a><br />',
+ } @{ $_[0]->Links($other_mode,$type)->ItemsArrayRef }
+ }
+};
$COLUMN_MAP = {
+ Queue => {
+ attribute => 'Queue',
+ title => 'Queue id',
+ value => sub { return $_[0]->Queue }
+ },
QueueName => {
attribute => 'Queue',
title => 'Queue',
},
Status => {
attribute => 'Status',
- value => sub { return $_[0]->Status }
+ value => sub { return loc($_[0]->Status) }
},
Subject => {
attribute => 'Subject',
if ( $Ticket->HasUnresolvedDependencies( Type => 'approval' )
or $Ticket->HasUnresolvedDependencies( Type => 'code' ) )
{
- return "<em>" . loc('(pending approval)') . "</em>";
+ return \'<em>', loc('(pending approval)'), \'</em>';
}
else {
- return "<em>" . loc('(pending other Collection)') . "</em>";
+ return \'<em>', loc('(pending other Collection)'), \'</em>';
}
}
else {
},
InitialPriority => {
attribute => 'InitialPriority',
+ name => 'Initial Priority',
value => sub { return $_[0]->InitialPriority }
},
FinalPriority => {
attribute => 'FinalPriority',
+ name => 'Final Priority',
value => sub { return $_[0]->FinalPriority }
},
EffectiveId => {
},
TimeWorked => {
attribute => 'TimeWorked',
+ title => 'Time Worked',
value => sub { return $_[0]->TimeWorked }
},
TimeLeft => {
attribute => 'TimeLeft',
+ title => 'Time Left',
value => sub { return $_[0]->TimeLeft }
},
TimeEstimated => {
attribute => 'TimeEstimated',
+ title => 'Time Estimated',
value => sub { return $_[0]->TimeEstimated }
},
Requestors => {
+ attribute => 'Requestor.EmailAddress',
value => sub { return $_[0]->Requestors->MemberEmailAddressesAsString }
},
Cc => {
+ attribute => 'Cc.EmailAddress',
value => sub { return $_[0]->Cc->MemberEmailAddressesAsString }
},
AdminCc => {
+ attribute => 'AdminCc.EmailAddress',
value => sub { return $_[0]->AdminCc->MemberEmailAddressesAsString }
},
StartsRelative => {
value => sub { return $_[0]->CreatedObj->AgeAsString }
},
LastUpdatedRelative => {
- title => 'LastUpdated',
+ title => 'Last Updated',
attribute => 'LastUpdated',
value => sub { return $_[0]->LastUpdatedObj->AgeAsString }
},
value => sub {
my $date = $_[0]->DueObj;
if ($date && $date->Unix > 0 && $date->Unix < time()) {
- return '<span class="overdue">' . $date->AgeAsString . '</span>';
+ return (\'<span class="overdue">' , $date->AgeAsString , \'</span>');
} else {
return $date->AgeAsString;
}
value => sub { return $_[0]->CreatedObj->AsString }
},
CreatedBy => {
- attribute => 'CreatedBy',
+ attribute => 'Creator',
+ title => 'Created By',
value => sub { return $_[0]->CreatorObj->Name }
},
LastUpdated => {
attribute => 'LastUpdated',
+ title => 'Last Updated',
value => sub { return $_[0]->LastUpdatedObj->AsString }
},
LastUpdatedBy => {
attribute => 'LastUpdatedBy',
+ title => 'Last Updated By',
value => sub { return $_[0]->LastUpdatedByObj->Name }
},
Told => {
value => sub { return $_[0]->ResolvedObj->AsString }
},
- DependedOnBy => {
- value => sub {
- my $links = $_[0]->DependedOnBy;
- return (
- join(
- "<br>",
- map {
- '<A HREF="'
- . $_->BaseURI->Resolver->HREF . '">'
- . ( $_->BaseIsLocal ? $_->LocalBase : $_->Base )
- . '</A>'
- } @{ $links->ItemsArrayRef }
- )
- );
- }
- },
- Members => {
- value => sub {
- my $links = $_[0]->Members;
- return (
- join(
- "<br>",
- map {
- '<A HREF="'
- . $_->BaseURI->Resolver->HREF . '">'
- . ( $_->BaseIsLocal ? $_->LocalBase : $_->Base )
- . '</A>'
- } @{ $links->ItemsArrayRef }
- )
- );
- }
- },
- Children => {
- value => sub {
- my $links = $_[0]->Members;
- return (
- join(
- "<br>",
- map {
- '<A HREF="'
- . $_->BaseURI->Resolver->HREF . '">'
- . ( $_->BaseIsLocal ? $_->LocalBase : $_->Base )
- . '</A>'
- } @{ $links->ItemsArrayRef }
- )
- );
- }
- },
- ReferredToBy => {
- value => sub {
- my $links = $_[0]->ReferredToBy;
- return (
- join(
- "<br>",
- map {
- '<A HREF="'
- . $_->BaseURI->Resolver->HREF . '">'
- . ( $_->BaseIsLocal ? $_->LocalBase : $_->Base )
- . '</A>'
- } @{ $links->ItemsArrayRef }
- )
- );
- }
- },
-
- DependsOn => {
- value => sub {
- my $links = $_[0]->DependsOn;
- return (
- join(
- "<br>",
- map {
- '<A HREF="'
- . $_->TargetURI->Resolver->HREF . '">'
- . ( $_->TargetIsLocal ? $_->LocalTarget : $_->Target )
- . '</A>'
- } @{ $links->ItemsArrayRef }
- )
- );
- }
- },
- MemberOf => {
- value => sub {
- my $links = $_[0]->MemberOf;
- return (
- join(
- "<br>",
- map {
- '<A HREF="'
- . $_->TargetURI->Resolver->HREF . '">'
- . ( $_->TargetIsLocal ? $_->LocalTarget : $_->Target )
- . '</A>'
- } @{ $links->ItemsArrayRef }
- )
- );
- }
- },
- Parents => {
- value => sub {
- my $links = $_[0]->MemberOf;
- return (
- join(
- "<br>",
- map {
- '<A HREF="'
- . $_->TargetURI->Resolver->HREF . '">'
- . ( $_->TargetIsLocal ? $_->LocalTarget : $_->Target )
- . '</A>'
- } @{ $links->ItemsArrayRef }
- )
- );
- }
- },
- RefersTo => {
- value => sub {
- my $links = $_[0]->RefersTo;
- return (
- join(
- "<br>",
- map {
- '<A HREF="'
- . $_->TargetURI->Resolver->HREF . '">'
- . ( $_->TargetIsLocal ? $_->LocalTarget : $_->Target )
- . '</A>'
- } @{ $links->ItemsArrayRef }
- )
- );
- }
- },
+ # Everything from LINKTYPEMAP
+ (map {
+ $_ => { value => $LinkCallback->( $_ ) }
+ } keys %RT::Ticket::LINKTYPEMAP),
'_CLASS' => {
value => sub { return $_[1] % 2 ? 'oddline' : 'evenline' }
},
+ '_CHECKBOX' => {
+ attribute => 'checkbox',
+ title => loc('Update'),
+ align => 'right',
+ value => sub { return \('<input type="checkbox" class="checkbox" name="UpdateTicket'.$_[0]->id.'" value="1" checked />') }
+ },
};
-
-
-
-# }}}
+</%ONCE>
+<%init>
$m->comp( '/Elements/Callback', COLUMN_MAP => $COLUMN_MAP, _CallbackName => 'ColumnMap');
-</%INIT>
+return $ColumnMap->( $Name, $Attr );
+</%init>