1 %# BEGIN BPS TAGGED BLOCK {{{
5 %# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
6 %# <sales@bestpractical.com>
8 %# (Except where explicitly superseded by other copyright notices)
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
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.
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.
30 %# CONTRIBUTION SUBMISSION POLICY:
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.)
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.
47 %# END BPS TAGGED BLOCK }}}
48 <div class="history <% lc $record_type %>" id="<% $histid %>">
50 if ( $ShowDisplayModes or $ShowTitle ) {
51 my $title = $ShowTitle
56 if ( $ShowDisplayModes ) {
57 if ( RT->Config->Get( 'QuoteFolding', $session{CurrentUser} ) ) {
58 my $open_all = $m->interp->apply_escapes( loc("Show all quoted text"), 'j' );
59 my $open_html = $m->interp->apply_escapes( loc("Show all quoted text"), 'h' );
60 my $close_all = $m->interp->apply_escapes( loc("Hide all quoted text"), 'j' );
61 $titleright .= '<a href="#" data-direction="open" '
62 . qq{onclick="return toggle_all_folds(this, $open_all, $close_all);"}
63 . ">$open_html</a> — ";
67 $titleright .= qq{<a href="?ForceShowHistory=1;id=} .
68 $Object->id.qq{#$histid">} .
69 loc("Show brief headers") .
72 $titleright .= qq{<a href="?ForceShowHistory=1;ShowHeaders=1;id=} .
73 $Object->id.qq{#$histid">} .
74 loc("Show full headers") .
79 <& /Widgets/TitleBoxStart, title => $title, titleright_raw => $titleright &>
82 <div class="history-container">
84 $m->callback( %ARGS, Object => $Object, CallbackName => 'BeforeTransactions' );
86 while ( my $Transaction = $Transactions->Next ) {
89 # Skip display of SetWatcher transactions for ticket Owner groups. Owner
90 # was a single member role group and denormalized into a column well before
91 # the generic role group handling and transactions came about. For
92 # tickets, we rely on rendering ownership changes using the Set-Owner
93 # transaction. For all other record types, or even potential ticket single
94 # role groups which aren't Owner, we use SetWatcher to render history and
95 # skip the Set transactions. This complication is necessary to avoid
96 # creating backdated transactions on upgrade which normalize to one type or
99 # These conditions assumes ticket Owner is a single-member denormalized
100 # role group, which is safe since that is unlikely to ever change in the
102 if ($Object->isa("RT::Ticket") and ($Transaction->Field || '') eq "Owner") {
103 $skip = 1 if $Transaction->Type eq "SetWatcher";
105 $skip = 1 if $Transaction->Type eq "Set"
106 and $Transaction->Field
107 and $Object->DOES("RT::Record::Role::Roles")
108 and $Object->HasRole( $Transaction->Field )
109 and $Object->RoleGroup( $Transaction->Field )->SingleMemberRoleGroupColumn;
114 Transaction => $Transaction,
116 CallbackName => 'SkipTransaction',
120 # ARGS is first because we're clobbering the "Attachments" parameter
121 $m->comp( 'ShowTransaction',
124 Transaction => $Transaction,
125 ShowHeaders => $ShowHeaders,
127 Attachments => $trans_attachments->{$Transaction->id} || {},
128 AttachmentContent => $trans_content,
129 HasTxnCFs => $HasTxnCFs,
132 # manually flush the content buffer after each txn,
133 # so the user sees some update
141 % if ($ShowDisplayModes or $ShowTitle) {
142 <& /Widgets/TitleBoxEnd &>
146 my $trans_content = {};
147 my $trans_attachments = {};
149 for my $content (@{$AttachmentContent->ItemsArrayRef()}) {
150 $trans_content->{$content->TransactionId}->{$content->Id} = $content;
153 for my $attachment (@{$Attachments->ItemsArrayRef()}) {
154 my $tmp = $trans_attachments->{ $attachment->TransactionId } ||= {};
155 push @{ $tmp->{ $attachment->Parent || 0 } ||= [] }, $attachment;
160 DisplayPath => 'Display.html',
161 AttachmentPath => 'Attachment',
162 UpdatePath => 'Update.html',
163 ForwardPath => 'Forward.html',
164 EmailRecordPath => 'ShowEmailRecord.html',
165 EncryptionPath => 'Crypt.html',
168 my $prefix = $ARGS{PathPrefix}||'';
169 while ( my ($arg, $path) = each %tmp ) {
170 next if defined $ARGS{ $arg };
171 $ARGS{ $arg } = $prefix.$path;
175 my $record_type = $Object->RecordType;
176 my $histid = "\L$record_type\E-" . $Object->id . "-history";
178 my $HasTxnCFs = ($Object->can("TransactionCustomFields") and $Object->TransactionCustomFields->Count);
182 $Transactions => $Object->SortedTransactions
183 $Attachments => $Object->Attachments( WithHeaders => 1 )
184 $AttachmentContent => $Object->TextAttachments
188 $ShowDisplayModes => 1