rt 4.2.16
[freeside.git] / rt / share / html / Ticket / Display.html
1 %# BEGIN BPS TAGGED BLOCK {{{
2 %#
3 %# COPYRIGHT:
4 %#
5 %# This software is Copyright (c) 1996-2019 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 => $title,
50     LinkRel => \%link_rel &>
51 <& /Elements/Tabs &>
52
53 % $m->callback(CallbackName => 'BeforeActionList', %ARGS, Actions => \@Actions, ARGSRef => \%ARGS, Ticket => $TicketObj);
54
55 <& /Elements/ListActions, actions => \@Actions &>
56 <& Elements/ShowUpdateStatus, Ticket => $TicketObj &>
57 <& Elements/ShowDependencyStatus, Ticket => $TicketObj &>
58
59 % $m->callback( %ARGS, Ticket => $TicketObj, Transactions => $transactions, Attachments => $attachments, CallbackName => 'BeforeShowSummary' );
60 <div class="summary">
61 <&| /Widgets/TitleBox, title => loc('Ticket metadata') &>
62 <& /Ticket/Elements/ShowSummary,  Ticket => $TicketObj, Attachments => $attachments &>
63 </&>
64 </div>
65 <br />
66
67 % $m->callback( Ticket => $TicketObj, %ARGS, Transactions => $transactions, Attachments => $attachments, CallbackName => 'BeforeShowHistory' );
68
69 % my $ShowHistory = RT->Config->Get("ShowHistory", $session{'CurrentUser'});
70 % if ($ShowHistory eq "delay") {
71     <& /Ticket/Elements/DelayShowHistory,
72         Ticket => $TicketObj,
73         ShowHeaders => $ARGS{'ShowHeaders'},
74     &>
75 % } elsif (not $ForceShowHistory and $ShowHistory eq "click") {
76     <& /Ticket/Elements/ClickToShowHistory,
77         Ticket => $TicketObj,
78         ShowHeaders => $ARGS{'ShowHeaders'},
79     &>
80 % } else {
81     <& /Elements/ShowHistory ,
82           Object => $TicketObj,
83           Transactions => $transactions,
84           ShowHeaders => $ARGS{'ShowHeaders'},
85           Attachments => $attachments,
86           AttachmentContent => $attachment_content
87     &>
88 % }
89
90 % $m->callback( %ARGS,
91 %     Ticket       => $TicketObj,
92 %     Transactions => $transactions,
93 %     Attachments  => $attachments,
94 %     CallbackName => 'AfterShowHistory',
95 % );
96
97 <%ARGS>
98 $TicketObj => undef
99 $ShowHeaders => 0
100 $ForceShowHistory => 0
101 $RedirectToBasics => 0
102 </%ARGS>
103
104 <%INIT>
105
106 $m->callback( TicketObj => $TicketObj, ARGSRef => \%ARGS, CallbackName => 'Initial' );
107
108 if ( ! $ARGS{'NoRedirect'} && RT::Interface::Web->MobileClient()) {
109     $ARGS{'id'} ||= $TicketObj->id if $TicketObj;
110     RT::Interface::Web::Redirect(RT->Config->Get('WebURL').'m/ticket/show?id='.$ARGS{'id'});
111     $m->abort;
112 }
113
114
115 my (@Actions, $title);
116
117
118 unless ($ARGS{'id'} || $TicketObj) {
119     Abort('No ticket specified');
120 }
121
122 if ($ARGS{'id'} eq 'new') {
123     # Create a new ticket
124
125     # Massage customer IDs into member links.
126     my @cust_uris = map { 
127       /^(\d+)$/ && "freeside://freeside/cust_main/$1"
128     } split(' ', $ARGS{'new-Customer'});
129     
130     $ARGS{'new-MemberOf'} = 
131       join(' ', $ARGS{'new-MemberOf'}, @cust_uris);
132
133     my $Queue = RT::Queue->new( $session{'CurrentUser'} );
134     $Queue->Load($ARGS{'Queue'});
135     unless ( $Queue->id ) {
136         Abort('Queue not found');
137     }
138
139     unless ( $Queue->CurrentUserHasRight('CreateTicket') ) {
140         Abort('You have no permission to create tickets in that queue.');
141     }
142
143     ($TicketObj, @Actions) = CreateTicket( %ARGS );
144     unless ( $TicketObj->CurrentUserHasRight('ShowTicket') ) {
145         Abort("No permission to view newly created ticket #".$TicketObj->id.".");
146     }
147 } else { 
148     $TicketObj ||= LoadTicket($ARGS{'id'});
149
150     $TicketObj->CurrentUser->PrincipalObj->HasRights( Object => $TicketObj );
151
152     my $SkipProcessing;
153
154     $m->callback( CallbackName => 'BeforeProcessArguments',
155         TicketObj => $TicketObj,
156         ActionsRef => \@Actions, ARGSRef => \%ARGS,
157         SkipProcessing => \$SkipProcessing );
158
159     if ( !$SkipProcessing ) {
160         if ( defined $ARGS{'Action'} ) {
161             if ($ARGS{'Action'} =~ /^(Steal|Delete|Take|SetTold)$/) {
162                 my $action = $1;
163                 my ($res, $msg) = $TicketObj->$action();
164                 push(@Actions, $msg);
165             }
166         }
167
168         $m->callback(CallbackName => 'ProcessArguments', 
169                 Ticket => $TicketObj, 
170                 ARGSRef => \%ARGS, 
171                 Actions => \@Actions);
172         
173         push @Actions, ProcessUpdateMessage(
174             ARGSRef   => \%ARGS,
175             Actions   => \@Actions,
176             TicketObj => $TicketObj,
177         );
178
179         #Process status updates
180         push @Actions, ProcessTicketWatchers(ARGSRef => \%ARGS, TicketObj => $TicketObj );
181         push @Actions, ProcessTicketBasics(  ARGSRef => \%ARGS, TicketObj => $TicketObj );
182         push @Actions, ProcessTicketLinks(   ARGSRef => \%ARGS, TicketObj => $TicketObj );
183         push @Actions, ProcessTicketDates(   ARGSRef => \%ARGS, TicketObj => $TicketObj );
184         push @Actions, ProcessObjectCustomFieldUpdates(ARGSRef => \%ARGS, TicketObj => $TicketObj );
185         # If this fails due to required fields being empty, it will set
186         # notes('RedirectToBasics').
187         push @Actions, ProcessTicketStatus(  ARGSRef => \%ARGS, TicketObj => $TicketObj );
188
189         push @Actions, ProcessTicketReminders( ARGSRef => \%ARGS, TicketObj => $TicketObj );
190
191         unless ($TicketObj->CurrentUserHasRight('ShowTicket')) {
192             if (@Actions) {
193                 Abort("A change was applied successfully, but you no longer have permissions to view the ticket", Actions => \@Actions);
194             } else {
195                 Abort("No permission to view ticket");
196             }
197         }
198         if ( $ARGS{'MarkAsSeen'} ) {
199             $TicketObj->SetAttribute(
200                 Name => 'User-'. $TicketObj->CurrentUser->id .'-SeenUpTo',
201                 Content => $TicketObj->LastUpdated,
202             );
203             push @Actions, loc('Marked all messages as seen');
204         }
205     }
206 }
207
208
209 $title = loc("Ticket #[_1]: [_2]", $TicketObj->Id, $TicketObj->Subject || '');
210
211 $m->callback(
212     CallbackName => 'BeforeDisplay',
213     TicketObj => \$TicketObj,
214     Actions => \@Actions,
215     title => \$title,
216     ARGSRef => \%ARGS,
217 );
218
219 # This code does automatic redirection if any updates happen. 
220 $m->notes('RedirectToBasics' => 1) if $RedirectToBasics;
221 my $path = '/Ticket/'. ( $m->notes('RedirectToBasics') ? 'Modify.html'
222                                                        : 'Display.html' );
223 MaybeRedirectForResults(
224     Actions   => \@Actions,
225     $TicketObj->Type eq 'approval' && RT->Config->Get('ForceApprovalsView')
226         ? (Path      => "/Approvals/Display.html", Force => 1)
227         : (Path      => $path)
228     ,
229     Anchor    => $ARGS{'Anchor'},
230     Arguments => { id => $TicketObj->id },
231 );
232
233 my $transactions = $TicketObj->SortedTransactions;
234 my $attachments = $TicketObj->Attachments;
235 my $attachment_content = $TicketObj->TextAttachments;
236
237 my %link_rel;
238 if (defined $session{'tickets'} and ($ARGS{'Query'} or $session{'CurrentSearchHash'}->{'Query'})) {
239     my $item_map = $session{'tickets'}->ItemMap;
240     $link_rel{first} = "Ticket/Display.html?id=" . $item_map->{first}                if $item_map->{$TicketObj->Id}{prev};
241     $link_rel{prev}  = "Ticket/Display.html?id=" . $item_map->{$TicketObj->Id}{prev} if $item_map->{$TicketObj->Id}{prev};
242     $link_rel{next}  = "Ticket/Display.html?id=" . $item_map->{$TicketObj->Id}{next} if $item_map->{$TicketObj->Id}{next};
243     $link_rel{last}  = "Ticket/Display.html?id=" . $item_map->{last}                 if $item_map->{$TicketObj->Id}{next} && $item_map->{last};
244 }
245 </%INIT>