cloned tickets inherit customer links, #11169
[freeside.git] / rt / share / html / Ticket / Display.html
1 %# BEGIN BPS TAGGED BLOCK {{{
2 %#
3 %# COPYRIGHT:
4 %#
5 %# This software is Copyright (c) 1996-2011 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 <& /Elements/Header, 
49     Title => loc("Ticket #[_1]: [_2]", $TicketObj->Id, $TicketObj->Subject),
50     LinkRel => \%link_rel &>
51 <& /Ticket/Elements/Tabs, 
52     Ticket => $TicketObj, 
53     current_tab => 'Ticket/Display.html?id='.$TicketObj->id,
54     Title => loc("Ticket #[_1]: [_2]", $TicketObj->Id, $TicketObj->Subject) &>
55
56 % $m->callback(CallbackName => 'BeforeActionList', %ARGS, Actions => \@Actions, ARGSRef => \%ARGS, Ticket => $TicketObj);
57
58 <& /Elements/ListActions, actions => \@Actions &>
59 <& Elements/ShowUpdateStatus, Ticket => $TicketObj &>
60
61 % $m->callback( %ARGS, Ticket => $TicketObj, CallbackName => 'BeforeShowSummary' );
62 <div class="summary">
63 <&| /Widgets/TitleBox, title => loc('Ticket metadata') &>
64 <& /Ticket/Elements/ShowSummary,  Ticket => $TicketObj, Attachments => $attachments &>
65 </&>
66 </div>
67 <br />
68
69 % $m->callback( Ticket => $TicketObj, %ARGS, CallbackName => 'BeforeShowHistory' );
70
71 <& /Ticket/Elements/ShowHistory , 
72       Ticket => $TicketObj, 
73       Tickets => $Tickets, 
74       Collapsed => $ARGS{'Collapsed'}, 
75       ShowHeaders => $ARGS{'ShowHeaders'},
76       Attachments => $attachments,
77       AttachmentContent => $attachment_content
78 &> 
79
80 % $m->callback( %ARGS,
81 %     Ticket       => $TicketObj,
82 %     current_tab  => 'Ticket/Display.html?id=' . $TicketObj->id,
83 %     CallbackName => 'AfterShowHistory',
84 % );
85
86 <%ARGS>
87 $id => undef
88 $TicketObj => undef
89 $ShowHeaders => 0
90 $Collapsed => undef
91 </%ARGS>
92
93 <%INIT>
94
95 $m->callback( TicketObj => $TicketObj, ARGSRef => \%ARGS, CallbackName => 'Initial' );
96
97 my (@Actions, $Tickets);  
98
99
100 unless ($id || $TicketObj) {
101     Abort('No ticket specified');
102 }
103
104 if ($ARGS{'id'} eq 'new') {
105     # {{{ Create a new ticket
106
107     # Massage customer IDs into member links.
108     my @cust_uris = map { 
109       /^(\d+)$/ && "freeside://freeside/cust_main/$1"
110     } split(' ', $ARGS{'new-Customer'});
111     
112     $ARGS{'new-MemberOf'} = 
113       join(' ', $ARGS{'new-MemberOf'}, @cust_uris);
114
115     my $Queue = new RT::Queue( $session{'CurrentUser'} );
116     $Queue->Load($ARGS{'Queue'});
117     unless ( $Queue->id ) {
118         Abort('Queue not found');
119     }
120
121     unless ( $Queue->CurrentUserHasRight('CreateTicket') ) {
122         Abort('You have no permission to create tickets in that queue.');
123     }
124
125     ($TicketObj, @Actions) = CreateTicket(
126         Attachments => delete $session{'Attachments'},
127         %ARGS,
128     );
129     unless ( $TicketObj->CurrentUserHasRight('ShowTicket') ) {
130         Abort("No permission to view newly created ticket #".$TicketObj->id.".");
131     }
132     # }}}
133 } else { 
134     $TicketObj ||= LoadTicket($ARGS{'id'});
135
136     $m->callback( CallbackName => 'BeforeProcessArguments',
137         TicketObj => $TicketObj, Tickets => $Tickets,
138         ActionsRef => \@Actions, ARGSRef => \%ARGS );
139     if ( defined $ARGS{'Action'} ) {
140         if ($ARGS{'Action'} =~ /^(Steal|Kill|Take|SetTold)$/) {
141             my $action = $1;
142             my ($res, $msg) = $TicketObj->$action();
143             push(@Actions, $msg);
144         }
145     }
146
147     $m->callback(CallbackName => 'ProcessArguments', 
148             Ticket => $TicketObj, 
149             ARGSRef => \%ARGS, 
150             Actions => \@Actions);
151     
152     $ARGS{UpdateAttachments} = $session{'Attachments'};
153     push @Actions,
154         ProcessUpdateMessage(
155         ARGSRef   => \%ARGS,
156         Actions   => \@Actions,
157         TicketObj => $TicketObj,
158         );
159     delete $session{'Attachments'};
160
161     #Process status updates
162     push @Actions, ProcessTicketWatchers(ARGSRef => \%ARGS, TicketObj => $TicketObj );
163     push @Actions, ProcessTicketBasics(  ARGSRef => \%ARGS, TicketObj => $TicketObj );
164     push @Actions, ProcessTicketLinks(   ARGSRef => \%ARGS, TicketObj => $TicketObj );
165     push @Actions, ProcessTicketDates(   ARGSRef => \%ARGS, TicketObj => $TicketObj );
166     push @Actions, ProcessTicketCustomFieldUpdates(ARGSRef => \%ARGS, TicketObj => $TicketObj );
167
168     # XXX: we shouldn't block actions here if user has no right to see the ticket,
169     # but we should allow him to see actions he has done
170     unless ($TicketObj->CurrentUserHasRight('ShowTicket')) {
171         Abort("No permission to view ticket");
172     }
173     if ( $ARGS{'MarkAsSeen'} ) {
174         $TicketObj->SetAttribute(
175             Name => 'User-'. $TicketObj->CurrentUser->id .'-SeenUpTo',
176             Content => $TicketObj->LastUpdated,
177         );
178         push @Actions, loc('Marked all messages as seen');
179     }
180 }
181
182 $m->callback(
183     CallbackName => 'BeforeDisplay',
184     TicketObj => \$TicketObj,
185     Tickets => \$Tickets,
186     Actions => \@Actions,
187     ARGSRef => \%ARGS,
188 );
189
190 # This code does automatic redirection if any updates happen. 
191
192 if (@Actions) {
193
194     # We've done something, so we need to clear the decks to avoid
195     # resubmission on refresh.
196     # But we need to store Actions somewhere too, so we don't lose them.
197     my $key = Digest::MD5::md5_hex( rand(1024) );
198     push @{ $session{"Actions"}->{$key} ||= [] }, @Actions;
199     $session{'i'}++;
200     my $url = RT->Config->Get('WebURL') . "Ticket/Display.html?id=" . $TicketObj->id . "&results=" . $key;
201     $url .= '#' . $ARGS{Anchor} if $ARGS{Anchor};
202     RT::Interface::Web::Redirect($url);
203 }
204
205 my $attachments = $m->comp('Elements/FindAttachments', Ticket => $TicketObj, Tickets => $Tickets);
206 my $attachment_content = $m->comp('Elements/LoadTextAttachments', Ticket => $TicketObj);
207
208 my %link_rel;
209 if (defined $session{'tickets'} and ($ARGS{'Query'} or $session{'CurrentSearchHash'}->{'Query'})) {
210     my $item_map = $session{'tickets'}->ItemMap;
211     $link_rel{first} = "Ticket/Display.html?id=" . $item_map->{first}                if $item_map->{$TicketObj->Id}{prev};
212     $link_rel{prev}  = "Ticket/Display.html?id=" . $item_map->{$TicketObj->Id}{prev} if $item_map->{$TicketObj->Id}{prev};
213     $link_rel{next}  = "Ticket/Display.html?id=" . $item_map->{$TicketObj->Id}{next} if $item_map->{$TicketObj->Id}{next};
214     $link_rel{last}  = "Ticket/Display.html?id=" . $item_map->{last}                 if $item_map->{$TicketObj->Id}{next};
215 }
216 </%INIT>