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