import rt 3.8.11
[freeside.git] / rt / html / Admin / Elements / EditCustomFields
1 %# BEGIN BPS TAGGED BLOCK {{{
2 %# 
3 %# COPYRIGHT:
4 %#  
5 %# This software is Copyright (c) 1996-2009 Best Practical Solutions, LLC 
6 %#                                          <jesse@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 <& /Elements/ListActions, actions => \@results &>
49
50 <form action="<%$RT::WebPath%><% $m->request_comp->path |n %>" method="post" name="EditCustomFields">
51 <input type="hidden" class="hidden" name="id" value="<% $Object->Id %>" />
52 <input type="hidden" class="hidden" name="ObjectType" value="<% $ObjectType %>" />
53 <input type="hidden" class="hidden" name="SubType" value="<% $SubType %>" />
54 <input type="hidden" class="hidden" name="UpdateCFs" value="1" />
55
56 % if ($Object->Id) {
57 <h2><&|/l&>Global Custom Fields</&></h2>
58 <& PickCustomFields, CustomFields => \@GlobalCFs, ReadOnly => 1, id => $id, SubType => $SubType &>
59 % }
60 <h2><&|/l&>Selected Custom Fields</&></h2>
61 <& PickCustomFields, CustomFields => [$ObjectCFs->CustomFields], id => $id, Checked => 1, SubType => $SubType &>
62 <h2><&|/l&>Unselected Custom Fields</&></h2>
63 <& PickCustomFields, CustomFields => \@UnassignedCFs, id => $id, SubType => $SubType &>
64
65 <& /Elements/Submit, CheckAll => 1, ClearAll => 1 &>
66 </form>
67
68
69 <%INIT>
70 my $CustomFields = RT::CustomFields->new($session{'CurrentUser'});
71 my @results;
72 my (@GlobalCFs, @UnassignedCFs);
73
74 my $id = $Object->Id;
75 if ($id and !$Object->CurrentUserHasRight('AssignCustomFields')) {
76     $m->out('<p><i>', loc('(No custom fields)'), '</i></p>');
77     return;
78 }
79
80 my $lookup = $ObjectType;
81 $lookup .= "-$SubType" if $SubType;
82
83 $CustomFields->LimitToLookupType($lookup);
84 $CustomFields->OrderBy( FIELD => 'Name' );
85
86
87 my ($GlobalCFs, $ObjectCFs);
88 $ObjectCFs = RT::ObjectCustomFields->new($session{'CurrentUser'});
89 $ObjectCFs->UnLimit;
90 $ObjectCFs->LimitToObjectId($id);
91 $ObjectCFs->LimitToLookupType($lookup);
92
93 # Check sanity of SortOrders
94 my %SortOrders;
95 $SortOrders{$_->SortOrder}++
96   while ($_ = $ObjectCFs->Next);
97
98 # If there are duplicates, run though and squash them
99 if (grep {$_ > 1} values %SortOrders) {
100     my $i = 1;
101     while (my $ObjectCF = $ObjectCFs->Next) {
102         $ObjectCF->SetSortOrder($i++);
103     }
104     $ObjectCFs->GotoFirstItem;
105 }
106
107 # {{{ deal with moving sortorder of custom fields
108 if ($CustomField and $Move) {
109     my $SourceObj = RT::ObjectCustomField->new($session{'CurrentUser'});
110     $SourceObj->LoadByCols( ObjectId => $id, CustomField => $CustomField );
111
112     my $TargetObj;
113     my $target_order = $SourceObj->SortOrder + $Move;
114     while (my $ObjectCF = $ObjectCFs->Next) { 
115         my $this_order = $ObjectCF->SortOrder;
116
117         # if we have an exact match, finish the loop now
118         ($TargetObj = $ObjectCF, last) if $this_order == $target_order;
119
120         # otherwise, we need to apropos toward the general direction
121         # ... first, check the sign is correct
122         next unless ($this_order - $SourceObj->SortOrder) * $Move > 0;
123
124         # ... next, see if we already have a candidate
125         if ($TargetObj) {
126             # ... if yes, compare the delta and choose the smaller one
127             my $orig_delta = abs($TargetObj->SortOrder - $target_order);
128             my $this_delta = abs($this_order - $target_order);
129             next if $orig_delta < $this_delta;
130         }
131
132         $TargetObj = $ObjectCF;
133     }
134
135     if ($TargetObj) {
136         # swap their sort order
137         my ($s, $t) = ($SourceObj->SortOrder, $TargetObj->SortOrder);
138         $TargetObj->SetSortOrder($s);
139         $SourceObj->SetSortOrder($t);
140         # because order changed, we must redo search for subsequent uses
141     }
142
143     $ObjectCFs->GotoFirstItem;
144 }
145 # }}}
146
147 if ($id) {
148     $GlobalCFs = RT::ObjectCustomFields->new($session{'CurrentUser'});
149     $GlobalCFs->LimitToObjectId(0);
150     $GlobalCFs->LimitToLookupType($lookup);
151 }
152
153 while (my $cf = $CustomFields->Next) { 
154     my $cf_id = $cf->Id;
155
156     if ($GlobalCFs and $GlobalCFs->HasEntryForCustomField($cf_id)) {
157         push @GlobalCFs, $cf;
158         next;
159     }
160
161     if ($UpdateCFs) {
162         # Go through and delete all the custom field relationships that this object
163         # no longer has
164         my $key = "Object-$id-CF-$cf_id";
165         if ($ARGS{$key}) {
166             if (!$ObjectCFs->HasEntryForCustomField($cf_id)) {
167                 my ($val, $msg) = $cf->AddToObject($Object);
168                 push (@results, $msg);
169                 push @UnassignedCFs, $cf if !$val;
170             }
171         }
172         else {
173             push @UnassignedCFs, $cf;
174             if ($ObjectCFs->HasEntryForCustomField($cf_id)) {
175                 my ($val, $msg) = $cf->RemoveFromObject($Object);
176                 push (@results, $msg);
177                 pop @UnassignedCFs if !$val;
178             }
179         }
180     }
181     elsif (!$ObjectCFs->HasEntryForCustomField($cf_id)) {
182         push @UnassignedCFs, $cf;
183     }
184         else {
185         }
186 }
187
188 # redo search...
189 $ObjectCFs = RT::ObjectCustomFields->new($session{'CurrentUser'});
190 $ObjectCFs->UnLimit;
191 $ObjectCFs->LimitToObjectId($id);
192 $ObjectCFs->LimitToLookupType($lookup);
193
194 </%INIT>
195 <%ARGS>
196 $title => undef
197 $Move => undef
198 $Source => undef
199 $CustomField => undef
200 $FindDisabledCustomFields => undef
201 $UpdateCFs => 0
202 $Object
203 $ObjectType
204 $SubType => ''
205 </%ARGS>