]>
Commit | Line | Data |
---|---|---|
84fb5b46 MKG |
1 | %# BEGIN BPS TAGGED BLOCK {{{ |
2 | %# | |
3 | %# COPYRIGHT: | |
4 | %# | |
403d7b0b | 5 | %# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC |
84fb5b46 MKG |
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 | $Class => 'RT__Ticket' | |
50 | $Name | |
51 | $Attr => undef | |
52 | </%ARGS> | |
53 | <%ONCE> | |
54 | ||
55 | # This is scary and should totally be refactored -- jesse | |
af59614d MKG |
56 | my $COLUMN_MAP; |
57 | $COLUMN_MAP = { | |
84fb5b46 MKG |
58 | id => { |
59 | attribute => 'id', | |
af59614d | 60 | title => '#', # loc |
84fb5b46 MKG |
61 | align => 'right', |
62 | value => sub { return $_[0]->id } | |
63 | }, | |
64 | ||
65 | Created => { | |
66 | attribute => 'Created', | |
67 | title => 'Created', # loc | |
68 | value => sub { return $_[0]->CreatedObj->AsString } | |
69 | }, | |
70 | CreatedRelative => { | |
71 | attribute => 'Created', | |
72 | title => 'Created', # loc | |
73 | value => sub { return $_[0]->CreatedObj->AgeAsString } | |
74 | }, | |
75 | CreatedBy => { | |
76 | attribute => 'Creator', | |
77 | title => 'Created By', # loc | |
78 | value => sub { return $_[0]->CreatorObj->Name } | |
79 | }, | |
80 | LastUpdated => { | |
81 | attribute => 'LastUpdated', | |
82 | title => 'Last Updated', # loc | |
83 | value => sub { return $_[0]->LastUpdatedObj->AsString } | |
84 | }, | |
85 | LastUpdatedRelative => { | |
86 | attribute => 'LastUpdated', | |
87 | title => 'Last Updated', # loc | |
88 | value => sub { return $_[0]->LastUpdatedObj->AgeAsString } | |
89 | }, | |
90 | LastUpdatedBy => { | |
91 | attribute => 'LastUpdatedBy', | |
92 | title => 'Last Updated By', # loc | |
93 | value => sub { return $_[0]->LastUpdatedByObj->Name } | |
94 | }, | |
95 | ||
96 | CustomField => { | |
97 | attribute => sub { return shift @_ }, | |
98 | title => sub { return pop @_ }, | |
99 | value => sub { | |
af59614d MKG |
100 | my $self = $COLUMN_MAP->{CustomField}; |
101 | my $cf = $self->{load}->(@_); | |
102 | return unless $cf->Id; | |
103 | return $self->{render}->( $cf, $cf->ValuesForObject($_[0])->ItemsArrayRef ); | |
104 | }, | |
105 | load => sub { | |
403d7b0b MKG |
106 | # Cache the CF object on a per-request basis, to avoid |
107 | # having to load it for every row | |
108 | my $key = join("-","CF", | |
109 | $_[0]->CustomFieldLookupType, | |
110 | $_[0]->CustomFieldLookupId, | |
111 | $_[-1]); | |
112 | ||
113 | my $cf = $m->notes($key); | |
114 | unless ($cf) { | |
115 | $cf = $_[0]->LoadCustomFieldByIdentifier($_[-1]); | |
af59614d MKG |
116 | RT->Logger->notice("Unable to load $_[-1] for ".$_[0]->CustomFieldLookupType." ".$_[0]->CustomFieldLookupId) |
117 | unless $cf->Id; | |
403d7b0b MKG |
118 | $m->notes($key, $cf); |
119 | } | |
af59614d MKG |
120 | return $cf; |
121 | }, | |
122 | render => sub { | |
123 | my ($cf, $ocfvs) = @_; | |
124 | my $comp = $m->comp_exists("/Elements/ShowCustomField".$cf->Type) | |
125 | ? "/Elements/ShowCustomField".$cf->Type | |
126 | : undef; | |
403d7b0b | 127 | |
84fb5b46 | 128 | my @values = map { |
af59614d MKG |
129 | $comp |
130 | ? \($m->scomp( $comp, Object => $_ )) | |
131 | : $_->Content | |
132 | } @$ocfvs; | |
133 | ||
134 | if (@values > 1) { | |
135 | for my $value (splice @values) { | |
136 | push @values, \"<li>", $value, \"</li> \n"; | |
137 | } | |
138 | @values = (\"<ul class='cf-values'>", @values, \"</ul>"); | |
139 | } | |
84fb5b46 MKG |
140 | return @values; |
141 | }, | |
142 | }, | |
143 | ||
144 | CheckBox => { | |
145 | title => sub { | |
146 | my $name = $_[1] || 'SelectedTickets'; | |
dab09ea8 | 147 | my $checked = $DECODED_ARGS->{ $name .'All' }? 'checked="checked"': ''; |
84fb5b46 MKG |
148 | |
149 | return \qq{<input type="checkbox" name="}, $name, \qq{All" value="1" $checked | |
af59614d | 150 | onclick="setCheckbox(this, }, |
84fb5b46 | 151 | $m->interp->apply_escapes($name,'j'), |
af59614d | 152 | \qq{)" />}; |
84fb5b46 MKG |
153 | }, |
154 | value => sub { | |
155 | my $id = $_[0]->id; | |
156 | ||
157 | my $name = $_[2] || 'SelectedTickets'; | |
158 | return \qq{<input type="checkbox" name="}, $name, \qq{" value="$id" checked="checked" />} | |
dab09ea8 | 159 | if $DECODED_ARGS->{ $name . 'All'}; |
84fb5b46 | 160 | |
dab09ea8 | 161 | my $arg = $DECODED_ARGS->{ $name }; |
84fb5b46 MKG |
162 | my $checked = ''; |
163 | if ( $arg && ref $arg ) { | |
01e3b242 | 164 | $checked = 'checked="checked"' if grep $_ == $id, grep { defined and length } @$arg; |
84fb5b46 MKG |
165 | } |
166 | elsif ( $arg ) { | |
167 | $checked = 'checked="checked"' if $arg == $id; | |
168 | } | |
169 | return \qq{<input type="checkbox" name="}, $name, \qq{" value="$id" $checked />} | |
170 | }, | |
171 | }, | |
172 | RadioButton => { | |
173 | title => \' ', | |
174 | value => sub { | |
175 | my $id = $_[0]->id; | |
176 | ||
177 | my $name = $_[2] || 'SelectedTicket'; | |
dab09ea8 | 178 | my $arg = $DECODED_ARGS->{ $name }; |
84fb5b46 MKG |
179 | my $checked = ''; |
180 | $checked = 'checked="checked"' if $arg && $arg == $id; | |
181 | return \qq{<input type="radio" name="}, $name, \qq{" value="$id" $checked />}; | |
182 | }, | |
183 | }, | |
184 | (map { | |
185 | my $value = RT->Config->Get($_); | |
186 | $_ => { value => sub { return \$value } }; | |
187 | ||
188 | } qw(WebPath WebBaseURL WebURL)), | |
189 | WebRequestPath => { value => sub { substr( $m->request_path, 1 ) } }, | |
190 | WebRequestPathDir => { value => sub { substr( $m->request_comp->dir_path, 1 ) } }, | |
af59614d MKG |
191 | WebHomePath => { |
192 | value => sub { | |
193 | my $path = RT->Config->Get("WebPath"); | |
194 | if (not $session{CurrentUser}->Privileged) { | |
195 | $path .= "/SelfService"; | |
196 | } | |
197 | return \$path; | |
198 | }, | |
199 | }, | |
200 | CurrentUser => { value => sub { $session{CurrentUser}->id } }, | |
201 | CurrentUserName => { value => sub { $session{CurrentUser}->Name } }, | |
84fb5b46 MKG |
202 | }; |
203 | ||
204 | $COLUMN_MAP->{'CF'} = $COLUMN_MAP->{'CustomField'}; | |
205 | ||
af59614d MKG |
206 | my $ROLE_MAP = {}; |
207 | ||
84fb5b46 MKG |
208 | </%ONCE> |
209 | <%INIT> | |
210 | $m->callback( COLUMN_MAP => $COLUMN_MAP, CallbackName => 'Once', CallbackOnce => 1 ); | |
af59614d MKG |
211 | |
212 | my $generic_with_roles; | |
213 | ||
214 | # Add in roles | |
215 | my $RecordClass = $Class; | |
216 | $RecordClass =~ s/_/:/g; | |
217 | if ($RecordClass->DOES("RT::Record::Role::Roles")) { | |
218 | unless ($ROLE_MAP->{$RecordClass}) { | |
219 | for my $role ($RecordClass->Roles) { | |
220 | my $attrs = $RecordClass->Role($role); | |
221 | $ROLE_MAP->{$RecordClass}{$role} = { | |
222 | title => $role, | |
223 | attribute => $attrs->{Column} || "$role.EmailAddress", | |
224 | value => sub { return \($m->scomp("/Elements/ShowPrincipal", Object => $_[0]->RoleGroup($role) ) ) }, | |
225 | }; | |
226 | $ROLE_MAP->{$RecordClass}{$role . "s"} = $ROLE_MAP->{$RecordClass}{$role} | |
227 | unless $attrs->{Single}; | |
228 | } | |
229 | } | |
230 | $generic_with_roles = { %{$COLUMN_MAP}, %{$ROLE_MAP->{$RecordClass}} }; | |
231 | } else { | |
232 | $generic_with_roles = { %{$COLUMN_MAP} }; | |
233 | } | |
234 | ||
235 | $m->callback( COLUMN_MAP => $generic_with_roles ); | |
84fb5b46 MKG |
236 | |
237 | # first deal with class specific things | |
5b0d0914 | 238 | if (RT::Interface::Web->ComponentPathIsSafe($Class) and $m->comp_exists("/Elements/$Class/ColumnMap")) { |
af59614d | 239 | my $class_map = $m->comp("/Elements/$Class/ColumnMap", Attr => $Attr, Name => $Name, GenericMap => $generic_with_roles ); |
5b0d0914 MKG |
240 | return $class_map if defined $class_map; |
241 | } | |
af59614d MKG |
242 | |
243 | return GetColumnMapEntry( Map => $generic_with_roles, Name => $Name, Attribute => $Attr ); | |
84fb5b46 MKG |
244 | |
245 | </%INIT> |