%# BEGIN BPS TAGGED BLOCK {{{
%#
%# COPYRIGHT:
%#
%# This software is Copyright (c) 1996-2026 Best Practical Solutions, LLC
%#                                          <sales@bestpractical.com>
%#
%# (Except where explicitly superseded by other copyright notices)
%#
%#
%# LICENSE:
%#
%# This work is made available to you under the terms of Version 2 of
%# the GNU General Public License. A copy of that license should have
%# been provided with this software, but in any event can be snarfed
%# from www.gnu.org.
%#
%# This work is distributed in the hope that it will be useful, but
%# WITHOUT ANY WARRANTY; without even the implied warranty of
%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
%# General Public License for more details.
%#
%# You should have received a copy of the GNU General Public License
%# along with this program; if not, write to the Free Software
%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
%# 02110-1301 or visit their web page on the internet at
%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html.
%#
%#
%# CONTRIBUTION SUBMISSION POLICY:
%#
%# (The following paragraph is not intended to limit the rights granted
%# to you to modify and distribute this software under the terms of
%# the GNU General Public License and is only of importance to you if
%# you choose to contribute your changes and enhancements to the
%# community by submitting them to Best Practical Solutions, LLC.)
%#
%# By intentionally submitting any modifications, corrections or
%# derivatives to this work, or any other work intended for use with
%# Request Tracker, to Best Practical Solutions, LLC, you confirm that
%# you are the copyright holder for those contributions and you grant
%# Best Practical Solutions,  LLC a nonexclusive, worldwide, irrevocable,
%# royalty-free, perpetual, license to use, copy, create derivative
%# works based on those contributions, and sublicense and distribute
%# those contributions and any derivatives thereof.
%#
%# END BPS TAGGED BLOCK }}}
<div class="<% join ' ', @classes %>" data-transaction-id="<% $Transaction->id %>">
  <div class="metadata">
% if ( $toggle_contrast || @action_icons ) {
    <span class="actions">
%   if ( $toggle_contrast ) {
      <span class="rt-inline-icon border rounded"><% $toggle_contrast |n %></span>
%     if ( @action_icons ) {
      <span class="vr"></span>
%     }
%   }
%   for my $action ( @action_icons ) {
      <span class="rt-inline-icon border rounded"><% $action |n %></span>
%   }
    </span>
% }
    <span class="type">
      <a name="txn-<% $Transaction->id %>" \
% if ( defined $DisplayPath ) {
%   if ( length $DisplayPath ) {
      href="<% $DisplayPath %>?id=<% $Object->id %>#txn-<% $Transaction->id %>" \
%   } else {
      href="#txn-<% $Transaction->id %>" \
% }
% } elsif ( $HTML::Mason::Commands::r->path_info =~ m{^/SelfService/} ) {
      href="<% RT->Config->Get('WebPath') %>/SelfService/Transaction/Display.html?id=<% $Transaction->id %>" \
% } else {
      href="<% RT->Config->Get('WebPath') %>/Transaction/Display.html?id=<% $Transaction->id %>" \
% }
      ><% GetSVGImage( Name => 'link', Title => loc('Show transaction link') ) | n %></a>
    </span>
% $m->callback( %ARGS, Transaction => $Transaction, CallbackName => 'AfterAnchor' );
    <span class="date"><% $date |n %></span>
    <span class="description">
% if ( $Transaction->Type eq 'Create' || $Transaction->Type eq 'Correspond' || $Transaction->Type eq 'Comment' ) {
      <& /Elements/ShowUser, User => $CreatorObj &> - <% $desc |n %>
% } else {
      <& /Elements/ShowUser, User => $CreatorObj, ShowUserAvatar => 0 &> - <% $desc |n %>
% }
% $m->callback( %ARGS, Transaction => $Transaction, CallbackName => 'AfterDescription' );
    </span>
% if ( $Object->isa("RT::Ticket") and $Object->CurrentUserCanSeeTime ) {
    <span class="time-taken"><% $time %></span>
% }
  </div>

  <div class="content">
<%PERL>
$m->comp('/Elements/ShowCustomFields', Object => $Transaction, HideEmpty => 1, LabelCols => 2, ValueCols => 10 ) if $HasTxnCFs;
$m->comp(
    'ShowTransactionAttachments',
    %ARGS,
    Parent => 0
) if $ShowBody;
</%PERL>
  </div>
% if ( ( $Transaction->Type eq 'CustomField' && $Transaction->Field ) or ( $Transaction->Type eq 'SetConfig' ) or ( $Transaction->ObjectType eq 'RT::Ticket' && ( $Transaction->Field // '') eq 'Description' ) ) {
%     my ($old, $new);
%     if ($show_cf_diff) {
%         my $cf = RT::CustomField->new( $session{CurrentUser} );
%         $cf->SetContextObject( $Transaction->Object );
%         $cf->Load( $Transaction->Field );
%         my $comp = '/Elements/ShowCustomField' . $cf->Type;
%         my $old_ref = $Transaction->OldReferenceObject;
%         $old = $old_ref ? $m->scomp($comp, Object => $old_ref) : loc('(no value)');
%         my $new_ref = $Transaction->NewReferenceObject;
%         $new = $new_ref ? $m->scomp($comp, Object => $new_ref) : loc('(no value)');
%     }
%     elsif ( $show_config_diff ) {
%         # pull in new value from reference if exists
%         if ( my $newobj = $Transaction->NewReferenceObject ) {
%             $new = $newobj->Content;
%         }
%         else {
%             $new = loc('(no value)');
%         }
%         # pull in old value from reference if exists
%         if ( my $oldobj = $Transaction->OldReferenceObject ) {
%             $old = $oldobj->Content // loc('(no value)');
%         }
%         else {
%             $old = loc('(no value)');
%         }
%     }
%     elsif ( $Transaction->ObjectType eq 'RT::Ticket' && $Transaction->Field eq 'Description' ) {
%         $old = $Transaction->OldValue;
%         $old = loc('(no value)') unless defined $old && length $old;
%         $new = $Transaction->NewValue;
%         $new = loc('(no value)') unless defined $new && length $new;
%     }
%     if ( $old || $new ) {
<div class="details hidden" id="txn-<% $Transaction->Id %>-details">
% if ( $old && $old eq loc('(no value)')  ) {
  <div class="row mt-2">
    <div class="label col-2"><% loc('Added') %>:</div>
    <div class="value col-10"><% $new |n %></div>
  </div>
% }
% elsif ( $new && $new eq loc('(no value)')  ) {
  <div class="row mt-2">
    <div class="label col-2"><% loc('Deleted') %>:</div>
    <div class="value col-10"><% $old |n %></div>
  </div>
% }
% else {
  <div class="row mt-2">
    <div class="label col-2"><% loc('From') %>:</div>
    <div class="value col-10"><% $old |n %></div>
  </div>
  <div class="row mt-2">
    <div class="label col-2"><% loc('To') %>:</div>
    <div class="value col-10"><% $new |n %></div>
  </div>
  <div class="row mt-2 diff">
    <div class="label col-2"><% loc('Changes') %>:</div>
    <div class="value col-10"><% loc('Loading...') %></div>
  </div>
% }
</div>
%     }
% }
% $m->callback( %ARGS, Transaction => $Transaction, CallbackName => 'AfterContent' );
</div>

<%ARGS>
$Transaction
$Object => $Transaction->Object

$Attachments => undef
$AttachmentContent => undef
$HasTxnCFs => 1

$ShowBody => 1
$ShowActions => 1
$RowNum => 1

$DisplayPath => undef
$AttachmentPath => undef
$UpdatePath => undef
$ForwardPath => undef
$EncryptionPath => undef
$EmailRecordPath => undef
</%ARGS>

<%ONCE>

</%ONCE>
<%INIT>
my $record_type = $Object->RecordType;
my $type_class  = $Object->ClassifyTransaction( $Transaction );

$m->callback(
    CallbackName => 'MassageTypeClass',
    Transaction  => $Transaction,
    TypeClassRef => \$type_class,
    ARGSRef      => \%ARGS,
);

my @classes = (
    "transaction",
    "$record_type-transaction",
    $type_class,
    ($RowNum % 2 ? 'odd' : 'even')
);

my $desc = $Transaction->BriefDescriptionAsHTML;
if ( $Object->id && $Object->id != $Transaction->ObjectId ) {
    # merged objects
    $desc = join " - ",
        $m->interp->apply_escapes(
            loc("[_1] #[_2]:", loc($record_type), $Transaction->ObjectId), 'h'),
        $desc;
}

my $date = $Transaction->CreatedAsString;

my $time = '';
$time = loc('[quant,_1,minute,minutes]', $Transaction->TimeTaken)
    if $Transaction->TimeTaken;

if ( $ShowBody && !$Attachments ) {
    $ARGS{'Attachments'} = $Attachments = {};

    my $attachments = $Transaction->Attachments( WithHeaders => 1 );
    push @{ $Attachments->{ $_->Parent || 0 } ||= [] }, $_
        foreach @{ $attachments->ItemsArrayRef };
}

my $show_cf_diff = 0; # Show/hide colorized diff panel in transaction display
my $show_config_diff = 0;

my @actions = ();
my $txn_type = $Transaction->Type;
if ( $txn_type =~ /EmailRecord$/ ) {
    push @actions, {
        title  => GetSVGImage( Name => 'envelope', Title => loc('Show email contents') ),
        target => '_blank',
        path   => $EmailRecordPath
            .'?id='. $Object->id
            .'&Transaction='. $Transaction->id
            .'&Attachment='. ( $Attachments->{0}[0] && $Attachments->{0}[0]->id ),
    } if $EmailRecordPath;

    $ShowBody = 0;
}
elsif ($txn_type eq 'CustomField' && $Transaction->Field) {
    my $cf = RT::CustomField->new( $session{CurrentUser} );
    $cf->SetContextObject( $Transaction->Object );
    $cf->Load( $Transaction->Field );

    if ($cf->Id && $cf->Type =~ /text|html/i) {
        $show_cf_diff = 1;
    }

    $m->callback(
        CallbackName   => 'ModifyShowCFDiff',
        TransactionObj => $Transaction,
        Object         => $Object,
        CustomFieldObj => $cf,
        ShowDiffRef    => \$show_cf_diff,
        ARGSRef        => \%ARGS,
    );

    if ($show_cf_diff) {
        push @actions, { class => 'toggle-txn-details', title => loc('Show Details'), path => '#' };
    }
}
elsif ($txn_type eq 'SetConfig' && $Transaction->Field) {
    my $meta = $RT::Config::META{$Transaction->Field} || {};
    $show_config_diff = ( $meta->{Widget} // '' ) =~ m{/(?:Boolean|Integer|String|Select)$} ? 0 : 1;
    if ( $show_config_diff ) {
        push @actions, { class => 'toggle-txn-details', title => loc('Show Details'), path => '#' };
    }
}
elsif ( $Transaction->ObjectType eq 'RT::Ticket' && ( $Transaction->Field // '' ) eq 'Description' ) {
    push @actions, { class => 'toggle-txn-details', title => loc('Show Details'), path => '#' };
}

# If the transaction has anything attached to it at all
elsif ( %$Attachments && $ShowActions ) {
    my %has_right = map {
        $_ => RT::ACE->CanonicalizeRightName( $_ . $record_type )
    } qw(Modify CommentOn ReplyTo);
    $has_right{'Forward'} = RT::ACE->CanonicalizeRightName('ForwardMessage');

    my $can_modify = $has_right{'Modify'}
        && $Object->CurrentUserHasRight( $has_right{'Modify'} );

    if ( $UpdatePath && $has_right{'ReplyTo'}
        && ( $can_modify
            || $Object->CurrentUserHasRight( $has_right{'ReplyTo'} )
        )
    ) {
        push @actions, {
            class  => "reply-link",
            title  => GetSVGImage( Name => 'reply', Title => loc('Reply') ),
            path   => $UpdatePath
                .'?id='. $Object->id
                .'&QuoteTransaction='. $Transaction->id
                .'&Action=Respond'
            ,
        };
    }
    if ( $UpdatePath && $has_right{'CommentOn'}
        && ( $can_modify
            || $Object->CurrentUserHasRight( $has_right{'CommentOn'} )
        )
    ) {
        push @actions, {
            class  => "comment-link",
            title  => GetSVGImage( Name => 'comment', Title => loc('Comment') ),
            path   => $UpdatePath
                .'?id='. $Object->id
                .'&QuoteTransaction='. $Transaction->id
                .'&Action=Comment'
            ,
        };
    }
    if ( $ForwardPath && $has_right{'Forward'}
        && $Object->CurrentUserHasRight( $has_right{'Forward'} )
    ) {
        push @actions, {
            class  => "forward-link",
            title  => GetSVGImage( Name => 'forward', Title => loc('Forward') ),
            path   => $ForwardPath
                .'?id='. $Object->id
                .'&QuoteTransaction='. $Transaction->id
            ,
        };
    }
    if ( $EncryptionPath && $can_modify
        && RT->Config->Get('Crypt')->{'Enable'}
        && RT->Config->Get('Crypt')->{'AllowEncryptDataInDB'}
    ) {
        push @actions, {
            class  => "encryption-link",
            title  => GetSVGImage( Name => 'key', Title => loc('Encrypt/Decrypt') ),
            path   => $EncryptionPath
                .'?id='. $Transaction->id
                .'&QuoteTransaction='. $Transaction->id
            ,
        };
    }
}

# Toggle contrast icon for message transactions with a messagebody
my $toggle_contrast;
if ( %$Attachments && $ShowBody && $txn_type =~ /^(?:Create|Correspond|Comment)$/ ) {
    $toggle_contrast = '<a href="#" class="toggle-contrast-link">'
        . GetSVGImage( Name => 'circle-half', Title => loc('Toggle contrast') )
        . '</a>';
}

my $CreatorObj = $Transaction->CreatorObj;

$m->callback(
    %ARGS,
    Transaction => $Transaction,
    Object      => $Object,

    Classes     => \@classes,
    Actions     => \@actions,
    Created     => \$date,
    TimeTaken   => \$time,
    Description => \$desc,
    ShowBody    => \$ShowBody,
    CreatorObj  => \$CreatorObj,
    HasTxnCFs   => \$HasTxnCFs,
    ARGSRef     => \%ARGS,
);

my @action_icons;
if ( @actions ) {
    my $i = $m->interp;

    foreach my $a ( @actions ) {
        push @action_icons, '<a'
            .' href="'. $i->apply_escapes( $a->{'path'}, 'h' ) .'"'
            . ($a->{'target'}
                ? ' target="'. $i->apply_escapes( $a->{'target'}, 'h' ) .'"'
                : ''
            )
            . ($a->{'class'}
                ? ' class="'. $i->apply_escapes( $a->{'class'}, 'h' ) .'"'
                : ''
            )
            .'>'. $a->{'title'} .'</a>'
        ;
    }
}

# make date unbreakable
$date = $m->interp->apply_escapes( $date, 'h' );
$date =~ s/\s/&nbsp;/g;
</%INIT>
