[Rt-commit] rt branch, 4.4/ticket-history-infinite-scroll, repushed
Dustin Graves
dustin at bestpractical.com
Mon Oct 19 10:58:43 EDT 2015
The branch 4.4/ticket-history-infinite-scroll was deleted and repushed:
was f6596c4047af1366672b6cdc5581d1a1dc89e318
now 1456980b48e1e361cdca3cfab61dfc002994dd8a
1: f6596c4 ! 1: 1456980 add infinite scrolling option to ticket display transaction history
@@ -1,6 +1,6 @@
Author: Dustin Graves <dustin at bestpractical.com>
- add infinite scrolling and infinite scroll with gradual link to load page
+ add infinite scrolling option to ticket display transaction history
Fixes: T#154449
@@ -12,23 +12,180 @@
WidgetArguments => {
Description => 'Show history', #loc
- Values => [qw(delay click always)],
-+ Values => [qw(delay click always continuous)],
++ Values => [qw(delay click always scroll)],
ValuesLabel => {
-- delay => "after the rest of the page loads", #loc
-- click => "after clicking a link", #loc
-- always => "immediately", #loc
-+ delay => "after the rest of the page loads", #loc
-+ click => "after clicking a link", #loc
-+ always => "immediately", #loc
-+ continuous => "as you scroll", #loc
+ delay => "after the rest of the page loads", #loc
+ click => "after clicking a link", #loc
+ always => "immediately", #loc
++ scroll => "as you scroll", #loc
},
},
},
-diff --git a/share/html/Elements/ShowHistoryPage b/share/html/Elements/ShowHistoryPage
+diff --git a/share/html/Elements/ShowHistory b/share/html/Elements/ShowHistory
+--- a/share/html/Elements/ShowHistory
++++ b/share/html/Elements/ShowHistory
+@@
+ %# those contributions and any derivatives thereof.
+ %#
+ %# END BPS TAGGED BLOCK }}}
+-<div class="history <% lc $record_type %>" id="<% $histid %>">
+-<%perl>
+-if ( $ShowDisplayModes or $ShowTitle ) {
+- my $title = $ShowTitle
+- ? loc('History')
+- : ' ';
++<& /Elements/ShowHistoryHeader,
++ Object => $Object,
++ ShowHeaders => $ShowHeaders,
++ ShowTitle => $ShowTitle,
++ ShowDisplayModes => $ShowDisplayModes,
++ &>
++
++% $m->callback( %ARGS, Object => $Object, CallbackName => 'BeforeTransactions' );
++
++<& /Elements/ShowHistoryPage,
++ Object => $Object,
++ Transactions => $Object->SortedTransactions,
++ ShowHeaders => $ARGS{'ShowHeaders'},
++ Attachments => $Attachments,
++ AttachmentContent => $AttachmentContent,
++ PathPrefix => ''
++ &>
+
+- my $titleright = '';
+- if ( $ShowDisplayModes ) {
+- if ( RT->Config->Get( 'QuoteFolding', $session{CurrentUser} ) ) {
+- my $open_all = $m->interp->apply_escapes( loc("Show all quoted text"), 'j' );
+- my $open_html = $m->interp->apply_escapes( loc("Show all quoted text"), 'h' );
+- my $close_all = $m->interp->apply_escapes( loc("Hide all quoted text"), 'j' );
+- $titleright .= '<a href="#" data-direction="open" '
+- . qq{onclick="return toggle_all_folds(this, $open_all, $close_all);"}
+- . ">$open_html</a> — ";
+- }
+-
+- if ($ShowHeaders) {
+- $titleright .= qq{<a href="?ForceShowHistory=1;id=} .
+- $Object->id.qq{#$histid">} .
+- loc("Show brief headers") .
+- qq{</a>};
+- } else {
+- $titleright .= qq{<a href="?ForceShowHistory=1;ShowHeaders=1;id=} .
+- $Object->id.qq{#$histid">} .
+- loc("Show full headers") .
+- qq{</a>};
+- }
+- }
+-</%perl>
+-<& /Widgets/TitleBoxStart, title => $title, titleright_raw => $titleright &>
+-% }
+-
+-<div class="history-container">
+-<%perl>
+-$m->callback( %ARGS, Object => $Object, CallbackName => 'BeforeTransactions' );
+-my $i = 1;
+-while ( my $Transaction = $Transactions->Next ) {
+- my $skip = 0;
+-
+- # Skip display of SetWatcher transactions for ticket Owner groups. Owner
+- # was a single member role group and denormalized into a column well before
+- # the generic role group handling and transactions came about. For
+- # tickets, we rely on rendering ownership changes using the Set-Owner
+- # transaction. For all other record types, or even potential ticket single
+- # role groups which aren't Owner, we use SetWatcher to render history and
+- # skip the Set transactions. This complication is necessary to avoid
+- # creating backdated transactions on upgrade which normalize to one type or
+- # another.
+- #
+- # These conditions assumes ticket Owner is a single-member denormalized
+- # role group, which is safe since that is unlikely to ever change in the
+- # future.
+- if ($Object->isa("RT::Ticket") and ($Transaction->Field || '') eq "Owner") {
+- $skip = 1 if $Transaction->Type eq "SetWatcher";
+- } else {
+- $skip = 1 if $Transaction->Type eq "Set"
+- and $Transaction->Field
+- and $Object->DOES("RT::Record::Role::Roles")
+- and $Object->HasRole( $Transaction->Field )
+- and $Object->RoleGroup( $Transaction->Field )->SingleMemberRoleGroupColumn;
+- }
+-
+- $m->callback(
+- %ARGS,
+- Transaction => $Transaction,
+- skip => \$skip,
+- CallbackName => 'SkipTransaction',
+- );
+- next if $skip;
+-
+- # ARGS is first because we're clobbering the "Attachments" parameter
+- $m->comp( 'ShowTransaction',
+- %ARGS,
+- Object => $Object,
+- Transaction => $Transaction,
+- ShowHeaders => $ShowHeaders,
+- RowNum => $i,
+- Attachments => $trans_attachments->{$Transaction->id} || {},
+- AttachmentContent => $trans_content,
+- HasTxnCFs => $HasTxnCFs,
+- );
+-
+- # manually flush the content buffer after each txn,
+- # so the user sees some update
+- $m->flush_buffer;
+-
+- $i++;
+-}
+-
+-</%perl>
+ </div>
+ % if ($ShowDisplayModes or $ShowTitle) {
+ <& /Widgets/TitleBoxEnd &>
+ % }
+ </div>
+-<%INIT>
+-my $trans_content = {};
+-my $trans_attachments = {};
+-
+-for my $content (@{$AttachmentContent->ItemsArrayRef()}) {
+- $trans_content->{$content->TransactionId}->{$content->Id} = $content;
+-}
+-
+-for my $attachment (@{$Attachments->ItemsArrayRef()}) {
+- my $tmp = $trans_attachments->{ $attachment->TransactionId } ||= {};
+- push @{ $tmp->{ $attachment->Parent || 0 } ||= [] }, $attachment;
+-}
+-
+-{
+- my %tmp = (
+- DisplayPath => 'Display.html',
+- AttachmentPath => 'Attachment',
+- UpdatePath => 'Update.html',
+- ForwardPath => 'Forward.html',
+- EmailRecordPath => 'ShowEmailRecord.html',
+- EncryptionPath => 'Crypt.html',
+- );
+-
+- my $prefix = $ARGS{PathPrefix}||'';
+- while ( my ($arg, $path) = each %tmp ) {
+- next if defined $ARGS{ $arg };
+- $ARGS{ $arg } = $prefix.$path;
+- }
+-}
+-
+-my $record_type = $Object->RecordType;
+-my $histid = "\L$record_type\E-" . $Object->id . "-history";
+-
+-my $HasTxnCFs = ($Object->can("TransactionCustomFields") and $Object->TransactionCustomFields->Count);
+-</%INIT>
+ <%ARGS>
+ $Object
+ $Transactions => $Object->SortedTransactions
+
+diff --git a/share/html/Elements/ShowHistoryHeader b/share/html/Elements/ShowHistoryHeader
new file mode 100644
--- /dev/null
-+++ b/share/html/Elements/ShowHistoryPage
++++ b/share/html/Elements/ShowHistoryHeader
@@
+%# BEGIN BPS TAGGED BLOCK {{{
+%#
@@ -79,10 +236,110 @@
+%# END BPS TAGGED BLOCK }}}
+<%ARGS>
+$Object
++$ShowHeaders => 0
++$ShowTitle => 1
++$ShowDisplayModes => 1
++</%ARGS>
++<%INIT>
++my $record_type = $Object->RecordType;
++my $histid = "\L$record_type\E-" . $Object->id . "-history";
++</%INIT>
++<div class="history <% lc $record_type %>" id="<% $histid %>">
++<%perl>
++if ( $ShowDisplayModes or $ShowTitle ) {
++ my $title = $ShowTitle
++ ? loc('History')
++ : ' ';
++
++ my $titleright = '';
++ if ( $ShowDisplayModes ) {
++ if ( RT->Config->Get( 'QuoteFolding', $session{CurrentUser} ) ) {
++ my $open_all = $m->interp->apply_escapes( loc("Show all quoted text"), 'j' );
++ my $open_html = $m->interp->apply_escapes( loc("Show all quoted text"), 'h' );
++ my $close_all = $m->interp->apply_escapes( loc("Hide all quoted text"), 'j' );
++ $titleright .= '<a href="#" data-direction="open" '
++ . qq{onclick="return toggle_all_folds(this, $open_all, $close_all);"}
++ . ">$open_html</a> — ";
++ }
++
++ if ($ShowHeaders) {
++ $titleright .= qq{<a href="?ForceShowHistory=1;id=} .
++ $Object->id.qq{#$histid">} .
++ loc("Show brief headers") .
++ qq{</a>};
++ } else {
++ $titleright .= qq{<a href="?ForceShowHistory=1;ShowHeaders=1;id=} .
++ $Object->id.qq{#$histid">} .
++ loc("Show full headers") .
++ qq{</a>};
++ }
++ }
++</%perl>
++<& /Widgets/TitleBoxStart, title => $title, titleright_raw => $titleright &>
++% }
++
++<div class="history-container">
+
+diff --git a/share/html/Elements/ShowHistoryPage b/share/html/Elements/ShowHistoryPage
+new file mode 100644
+--- /dev/null
++++ b/share/html/Elements/ShowHistoryPage
+@@
++%# BEGIN BPS TAGGED BLOCK {{{
++%#
++%# COPYRIGHT:
++%#
++%# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
++%# <sales at 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 }}}
++<%ARGS>
++$Object
+$Transactions => $Object->SortedTransactions
+$Attachments => $Object->Attachments( WithHeaders => 1 )
+$AttachmentContent => $Object->TextAttachments
++
+$ShowHeaders => 0
++
+$PathPrefix => ''
+</%ARGS>
+<%INIT>
@@ -115,20 +372,11 @@
+ }
+}
+
-+my $record_type = $Object->RecordType;
-+my $histid = "\L$record_type\E-" . $Object->id . "-history";
-+
+my $HasTxnCFs = ($Object->can("TransactionCustomFields") and $Object->TransactionCustomFields->Count);
+</%INIT>
+<%perl>
-+$m->callback( %ARGS, Object => $Object, CallbackName => 'BeforeTransactions' );
-+
-+# Properly set starting index
-+my $i = 0;
-+
-+my $Transaction;
-+
-+while ( $Transaction = $Transactions->Next ) {
++my $i = 1;
++while ( my $Transaction = $Transactions->Next ) {
+ my $skip = 0;
+
+ # Skip display of SetWatcher transactions for ticket Owner groups. Owner
@@ -140,7 +388,7 @@
+ # skip the Set transactions. This complication is necessary to avoid
+ # creating backdated transactions on upgrade which normalize to one type or
+ # another.
-+ #
++ #
+ # These conditions assumes ticket Owner is a single-member denormalized
+ # role group, which is safe since that is unlikely to ever change in the
+ # future.
@@ -180,11 +428,8 @@
+
+ $i++;
+}
-+
-+# abort if we have no transactions, so the client knows we had no results
-+$m->abort() unless ($Transaction);
+</%perl>
-+<script type="text/javascript">ReplaceUserReferences()</script>
++
diff --git a/share/html/Elements/ShowTransaction b/share/html/Elements/ShowTransaction
--- a/share/html/Elements/ShowTransaction
@@ -255,14 +500,12 @@
+$id
+$oldestTransactionsFirst
+$lastTransactionId => undef
-+$transactionId => undef
++$focusTransactionId => undef
+</%ARGS>
+<%INIT>
+my $TicketObj = RT::Ticket->new($session{'CurrentUser'});
+$TicketObj->Load($id);
+
-+my $attachments = $TicketObj->Attachments;
-+my $attachment_content = $TicketObj->TextAttachments;
+my %extra_args;
+$m->callback( CallbackName => 'ExtraShowHistoryArguments', Ticket => $TicketObj, ExtraArgs => \%extra_args );
+
@@ -279,13 +522,13 @@
+ { FIELD => 'Created', ORDER => $order },
+ { FIELD => 'id', ORDER => $order },
+);
-+if ($transactionId) {
++if ($focusTransactionId) { # make sure we load enough if we need to focus a transaction
+ $transactions->Limit(
+ FIELD => 'id',
+ OPERATOR => $oldestTransactionsFirst ? '<=' : '>=',
-+ VALUE => $transactionId
++ VALUE => $focusTransactionId
+ );
-+} else {
++} else { # otherwise, just load the standard page of 10 transactions
+ $transactions->RowsPerPage(10);
+ $transactions->FirstPage();
+}
@@ -293,8 +536,6 @@
+<& /Elements/ShowHistoryPage,
+ Object => $TicketObj,
+ ShowHeaders => $ARGS{'ShowHeaders'},
-+ Attachments => $attachments,
-+ AttachmentContent => $attachment_content,
+ Transactions => $transactions,
+ %extra_args,
+ &>
@@ -308,8 +549,8 @@
% my $ShowHistory = RT->Config->Get("ShowHistory", $session{'CurrentUser'});
-% if ($ShowHistory eq "delay") {
-+% if ($ShowHistory eq "continuous") {
-+ <& /Ticket/Elements/ContinuousShowHistory,
++% if ($ShowHistory eq "scroll") {
++ <& /Ticket/Elements/ScrollShowHistory,
+ Ticket => $TicketObj
+ &>
+% } elsif ($ShowHistory eq "delay") {
@@ -317,10 +558,10 @@
Ticket => $TicketObj,
ShowHeaders => $ARGS{'ShowHeaders'},
-diff --git a/share/html/Ticket/Elements/ContinuousShowHistory b/share/html/Ticket/Elements/ContinuousShowHistory
+diff --git a/share/html/Ticket/Elements/ScrollShowHistory b/share/html/Ticket/Elements/ScrollShowHistory
new file mode 100644
--- /dev/null
-+++ b/share/html/Ticket/Elements/ContinuousShowHistory
++++ b/share/html/Ticket/Elements/ScrollShowHistory
@@
+%# BEGIN BPS TAGGED BLOCK {{{
+%#
@@ -372,6 +613,7 @@
+<%ARGS>
+$Ticket
+</%ARGS>
++
+<%INIT>
+my %params = %ARGS;
+delete $params{Ticket};
@@ -386,61 +628,27 @@
+my $ShowTitle = 1 || $extra_args{'ShowTitle'};
+my $ShowHeaders = 0 || $extra_args{'ShowHeaders'};
+
-+my $record_type = $Ticket->RecordType;
-+my $histid = "\L$record_type\E-" . $Ticket->id . "-history";
-+
+my $oldestTransactionsFirst = RT->Config->Get("OldestTransactionsFirst", $session{CurrentUser});
+</%INIT>
-+<div id="delayed_ticket_history">
-+<div class="history <% lc $record_type %>" id="<% $histid %>">
-+<%perl>
-+if ( $ShowDisplayModes or $ShowTitle ) {
-+ my $title = $ShowTitle
-+ ? loc('History')
-+ : ' ';
-+
-+ my $titleright = '';
-+ if ( $ShowDisplayModes ) {
-+ if ( RT->Config->Get( 'QuoteFolding', $session{CurrentUser} ) ) {
-+ my $open_all = $m->interp->apply_escapes( loc("Show all quoted text"), 'j' );
-+ my $open_html = $m->interp->apply_escapes( loc("Show all quoted text"), 'h' );
-+ my $close_all = $m->interp->apply_escapes( loc("Hide all quoted text"), 'j' );
-+ $titleright .= '<a href="#" data-direction="open" '
-+ . qq{onclick="return toggle_all_folds(this, $open_all, $close_all);"}
-+ . ">$open_html</a> — ";
-+ }
-+
-+ if ($ShowHeaders) {
-+ $titleright .= qq{<a href="?ForceShowHistory=1;id=} .
-+ $Ticket->id.qq{#$histid">} .
-+ loc("Show brief headers") .
-+ qq{</a>};
-+ } else {
-+ $titleright .= qq{<a href="?ForceShowHistory=1;ShowHeaders=1;id=} .
-+ $Ticket->id.qq{#$histid">} .
-+ loc("Show full headers") .
-+ qq{</a>};
-+ }
-+ }
-+</%perl>
-+<& /Widgets/TitleBoxStart, title => $title, titleright_raw => $titleright &>
-+% }
-+
-+<div class="history-container">
-+
++
++<& /Elements/ShowHistoryHeader,
++ Object => $Ticket,
++ ShowHeaders => $ShowHeaders,
++ ShowTitle => $ShowTitle,
++ ShowDisplayModes => $ShowDisplayModes,
++ &>
++
++</div>
+% if ($ShowDisplayModes or $ShowTitle) {
+ <& /Widgets/TitleBoxEnd &>
+% }
-+
-+</div>
-+</div>
+</div>
+
+<script type="text/javascript">
+jQuery(function(){
+ var isLoading = false, // prevent multiple simultaneous load events
+ disableLoading = false, // prevent repeated fruitless attempts
-+ loadDistanceFromBottom = 600, // to load before bottom of page is reached
++ loadDistanceFromBottom = 750, // to load before bottom of page is reached
+ lastTransactionId = null,
+ hash = window.location.hash,
+ hashTransactionId = null;
@@ -448,13 +656,11 @@
+ var oldestTransactionsFirst = <% $oldestTransactionsFirst || 0 %>;
+
+ var removeLoadingMessage = function() {
-+ var loadingMessages = jQuery('.loading-message');
-+ if (loadingMessages.length) loadingMessages.remove();
++ jQuery('.loading-message').remove();
+ };
+
+ var removeLoadLink = function() {
-+ var loadLink = jQuery('.error-load-history');
-+ if (loadLink.length) loadLink.remove();
++ jQuery('.error-load-history').remove();
+ };
+
+ var showLoadingMessage = function() {
@@ -467,7 +673,7 @@
+ removeLoadingMessage();
+ disableLoading = true;
+ removeLoadLink();
-+ var loadLink = jQuery('<div class="error-load-history"><&|/l&>Could not load ticket history. Reason: </&>' + reason + '.<br/><a href="#"><&|/l&>Try again</&></a></div>');
++ var loadLink = jQuery('<div class="error-load-history"><&|/l&>Could not load ticket history. Reason: </&>' + reason + '<br/><a href="#"><&|/l&>Try again</&></a></div>');
+ jQuery(".history-container").append(loadLink);
+ };
+
@@ -480,20 +686,21 @@
+ var queryString = '&oldestTransactionsFirst=' + oldestTransactionsFirst;
+ if (lastTransactionId) queryString += '&lastTransactionId=' + lastTransactionId;
+
-+ // check for link to specific transaction and make sure we load enough to view it
++ // check for link to specific transaction and make sure we load enough to focus it
+ if (hash && !lastTransactionId) {
+ var matches = hash.match(/^#txn-(\d+)$/);
+ if (matches) {
+ hashTransactionId = matches[1];
-+ queryString += '&transactionId=' + hashTransactionId;
++ queryString += '&focusTransactionId=' + hashTransactionId;
+ }
+ }
+
+ jQuery.ajax({
+ url: "<% $url %>" + queryString,
+ success: function(html) {
-+ if(html) {
-+ lastTransactionId = jQuery(html).filter('div.transaction').last().data('transactionId');
++ var transactions = jQuery(html).filter('div.transaction');
++ if(html && transactions.length) {
++ lastTransactionId = transactions.last().data('transactionId');
+ jQuery(".history-container").append(html);
+
+ if (hashTransactionId) { // focus transaction if we are following a link to it
More information about the rt-commit
mailing list