[Rt-commit] rt branch, 4.4/emailinput-autocomplete-exclude, created. rt-4.4.4-85-g90d615c9d6

Craig Kaiser craig at bestpractical.com
Wed Jan 8 10:18:07 EST 2020


The branch, 4.4/emailinput-autocomplete-exclude has been created
        at  90d615c9d6587ec0dc09487a4b4338e58913279e (commit)

- Log -----------------------------------------------------------------
commit 812dedd63c8549b09dc6b9240cbcb3168faa1c31
Author: Craig Kaiser <craig at bestpractical.com>
Date:   Thu May 23 10:17:29 2019 -0400

    Jump to unread message, if transaction is not loaded yet load it
    
    If the load history as scroll feature is enabled and a user wants to
    jump to an unread message the history leading to the unread transaction
    may need to be loaded.

diff --git a/share/html/Ticket/Elements/ScrollShowHistory b/share/html/Ticket/Elements/ScrollShowHistory
index d2aca08a85..e30f1a57f3 100644
--- a/share/html/Ticket/Elements/ScrollShowHistory
+++ b/share/html/Ticket/Elements/ScrollShowHistory
@@ -77,103 +77,111 @@ my $oldestTransactionsFirst = RT->Config->Get("OldestTransactionsFirst", $sessio
 </div>
 
 <script type="text/javascript">
-jQuery(function(){
-    var isLoading = false, // prevent multiple simultaneous load events
-        disableLoading = false, // prevent repeated fruitless attempts
-        loadDistanceFromBottom = 1500, // to load before bottom of page is reached
-        lastTransactionId = null,
-        hash = window.location.hash,
-        hashTransactionId = null,
-        loadAll = false;
-
-    var oldestTransactionsFirst = <% $oldestTransactionsFirst || 0 %>;
-
-    var removeLoadingMessage = function() {
-        jQuery('.loading-message').remove();
-    };
-
-    var removeLoadLink = function() {
-        jQuery('.error-load-history').remove();
-    };
-
-    var showLoadingMessage = function() {
-        removeLoadingMessage();
-        var loadingMessage = jQuery('<span class="loading-message">' +
-            loc_key('loading') + '</span>');
-        jQuery(".history-container").append(loadingMessage);
-    };
-
-    var loadingError = function(reason) {
-        removeLoadingMessage();
-        disableLoading = true;
-        removeLoadLink();
-        var loadLink = jQuery('<div class="error-load-history">' +
-            loc_key('history_scroll_error') + ' ' + reason +
-            '<br/><a href="#">' + loc_key('try_again') + '</a></div>');
-        jQuery(".history-container").append(loadLink);
-    };
-
-    var loadHistoryPage = function() {
-        if (isLoading || disableLoading) return;
-
-        isLoading = true;
-        showLoadingMessage();
-
-        var queryString = '&oldestTransactionsFirst=' + oldestTransactionsFirst;
-        if (lastTransactionId) queryString += '&lastTransactionId=' + lastTransactionId;
-        if (loadAll) queryString += '&loadAll=1';
+var isLoading = false, // prevent multiple simultaneous load events
+    disableLoading = false, // prevent repeated fruitless attempts
+    loadDistanceFromBottom = 1500, // to load before bottom of page is reached
+    lastTransactionId = null,
+    hash = window.location.hash,
+    hashTransactionId = null,
+    loadAll = false;
+
+var oldestTransactionsFirst = <% $oldestTransactionsFirst || 0 %>;
+
+var removeLoadingMessage = function() {
+    jQuery('.loading-message').remove();
+};
+
+var removeLoadLink = function() {
+    jQuery('.error-load-history').remove();
+};
+
+var showLoadingMessage = function() {
+    removeLoadingMessage();
+    var loadingMessage = jQuery('<span class="loading-message">' +
+        loc_key('loading') + '</span>');
+    jQuery(".history-container").append(loadingMessage);
+};
+
+var loadingError = function(reason) {
+    removeLoadingMessage();
+    disableLoading = true;
+    removeLoadLink();
+    var loadLink = jQuery('<div class="error-load-history">' +
+        loc_key('history_scroll_error') + ' ' + reason +
+        '<br/><a href="#">' + loc_key('try_again') + '</a></div>');
+    jQuery(".history-container").append(loadLink);
+};
+
+function loadHistoryPage (path) {
+    if (isLoading || disableLoading) return;
+
+    if ( path ) {
+        hash = path;
+    }
+
+    isLoading = true;
+    showLoadingMessage();
+
+    var queryString = '&oldestTransactionsFirst=' + oldestTransactionsFirst;
+    if (lastTransactionId) queryString += '&lastTransactionId=' + lastTransactionId;
+    if (loadAll) queryString += '&loadAll=1';
+
+    // don't load all over and over again
+    loadAll = false;
+
+    // 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 += '&focusTransactionId=' + hashTransactionId;
+        }
+    }
+
+    jQuery.ajax({
+        url: "<% $url |n %>" + queryString,
+        success: function(html) {
+            var transactions = jQuery(html).filter('div.transaction');
+            if(html && transactions.length) {
+                lastTransactionId = transactions.last().data('transactionId');
+                jQuery(".history-container").append(html);
+                if ( transactions.filter(':not(.hidden.end-of-history-list)').length == 0 ) {
+                    // if none is visible, automatically load more
+                    isLoading = false;
+                    loadHistoryPage();
+                    return;
+                }
 
-        // don't load all over and over again
-        loadAll = false;
+                if (hashTransactionId) { // focus transaction if we are following a link to it
+                    hashTransactionId = null;
+                    location.href = hash;
+                }
+            } else {
+                disableLoading = true;
 
-        // 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 += '&focusTransactionId=' + hashTransactionId;
+                // hide 'Load All' link container if we're done loading
+                var loadAllHistoryContainer = jQuery('#LoadAllHistoryContainer');
+                loadAllHistoryContainer.hide();
             }
-        }
 
-        jQuery.ajax({
-            url: "<% $url |n %>" + queryString,
-            success: function(html) {
-                var transactions = jQuery(html).filter('div.transaction');
-                if(html && transactions.length) {
-                    lastTransactionId = transactions.last().data('transactionId');
-                    jQuery(".history-container").append(html);
-                    if ( transactions.filter(':not(.hidden.end-of-history-list)').length == 0 ) {
-                        // if none is visible, automatically load more
-                        isLoading = false;
-                        loadHistoryPage();
-                        return;
-                    }
-
-                    if (hashTransactionId) { // focus transaction if we are following a link to it
-                        hashTransactionId = null;
-                        location.href = hash;
-                    }
-                } else {
-                    disableLoading = true;
-
-                    // hide 'Load All' link container if we're done loading
-                    var loadAllHistoryContainer = jQuery('#LoadAllHistoryContainer');
-                    loadAllHistoryContainer.hide();
-                }
+            isLoading = false;
+            removeLoadingMessage();
 
-                isLoading = false;
-                removeLoadingMessage();
+            // make sure we load all if we clicked the "Load All" button while we were already loading
+            if (loadAll) loadHistoryPage();
 
-                // make sure we load all if we clicked the "Load All" button while we were already loading
-                if (loadAll) loadHistoryPage();
-            },
-            error: function(xhr, reason) {
-                isLoading = false;
-                loadingError(reason);
+            if ( path ) {
+                window.location.href = path;
             }
-        });
-    };
+        },
+        error: function(xhr, reason) {
+            isLoading = false;
+            loadingError(reason);
+        }
+    });
+};
 
+jQuery(function(){
     var loadAllHistory = function() {
         // hide link container
         var loadAllHistoryContainer = jQuery('#LoadAllHistoryContainer');
diff --git a/share/html/Ticket/Elements/ShowUpdateStatus b/share/html/Ticket/Elements/ShowUpdateStatus
index 9c3bc43f90..a26b3d3980 100644
--- a/share/html/Ticket/Elements/ShowUpdateStatus
+++ b/share/html/Ticket/Elements/ShowUpdateStatus
@@ -52,7 +52,7 @@
 <&|/l&>There are unread messages on this ticket.</&>
 </span>
 <span class="new-messages-buttons">
-<a class="button small-button" href="<% RT->Config->Get('WebPath') ."/$DisplayPath/Display.html?id=". $Ticket->id ."#txn-" . $txn->id |n %>"><&|/l&>Jump to Unread</&></a>
+<a class="button small-button" href="<% RT->Config->Get('WebPath') ."/$DisplayPath/Display.html?id=". $Ticket->id ."#txn-" . $txn->id |n %>" onclick="loadHistoryPage('<%"#txn-" . $txn->id%>')"><&|/l&>Jump to Unread</&></a>
 <a class="button small-button" href="<% RT->Config->Get('WebPath') ."/$DisplayPath/Display.html?id=". $Ticket->id. "&MarkAsSeen=1" |n %>"><&|/l&>Mark as Seen</&></a>
 <a class="button small-button" href="<% RT->Config->Get('WebPath') ."/$DisplayPath/Display.html?id=". $Ticket->id ."&MarkAsSeen=1&Anchor=txn-" . $txn->id |n %>"><&|/l&>Jump & Mark as Seen</&></a>
 </span>

commit 4d1a4149ca9b6b44a3443796b0248c20308ca18b
Author: Craig Kaiser <craig at bestpractical.com>
Date:   Fri May 24 15:45:38 2019 -0400

    Allow saved searches to be sorted
    
    Saved searches are saved in the database as attributes meaning that the
    order by cols method usually available is not.

diff --git a/lib/RT/SavedSearches.pm b/lib/RT/SavedSearches.pm
index 224b20a242..d44b8594bb 100644
--- a/lib/RT/SavedSearches.pm
+++ b/lib/RT/SavedSearches.pm
@@ -109,6 +109,23 @@ sub LimitToPrivacy {
     }
 }
 
+
+=head2 SortSavedSearches
+
+Sort the list of saved searches. The default is to sort alphabetically.
+
+=cut
+
+sub SortSavedSearches {
+    my $self = shift;
+
+    # Work directly with the internal data structure since saved searches
+    # aren't fully backed by a DB table and can't support typical OrderBy, etc.
+    my @sorted = sort { lcfirst($a->Name) cmp lcfirst($b->Name) } @{$self->{'objects'}};
+    @{$self->{'objects'}} = @sorted;
+    return;
+}
+
 RT::Base->_ImportOverlays();
 
 1;
diff --git a/share/html/Elements/SavedSearches b/share/html/Elements/SavedSearches
index 1ef131c10b..9a519873e3 100644
--- a/share/html/Elements/SavedSearches
+++ b/share/html/Elements/SavedSearches
@@ -49,6 +49,7 @@
 % foreach my $Object (@Objects) {
 %   my $SavedSearches = RT::SavedSearches->new($session{CurrentUser});
 %   $SavedSearches->LimitToPrivacy(join('-',ref($Object),$Object->Id),'Ticket');
+%   $SavedSearches->SortSavedSearches();
 %   my $title;
 %   if (ref $Object eq 'RT::User' && $Object->Id == $session{CurrentUser}->Id) {
 %       $title = loc("My saved searches");

commit e83bbb5d6d1c201a0a41ed2f0ffe9f1a287a639c
Author: Craig Kaiser <craig at bestpractical.com>
Date:   Sun Jul 14 12:41:23 2019 -0400

    Initial demo of favorited transactions portlet

diff --git a/share/html/Elements/ShowTransaction b/share/html/Elements/ShowTransaction
index 790d026b18..129cf2e6c3 100644
--- a/share/html/Elements/ShowTransaction
+++ b/share/html/Elements/ShowTransaction
@@ -45,6 +45,13 @@
 %# those contributions and any derivatives thereof.
 %#
 %# END BPS TAGGED BLOCK }}}
+<span class="type">
+%   if ( $Transaction->FirstAttribute('Favorited') && $Transaction->FirstAttribute('Favorited')->Content->{$session{'CurrentUser'}->Id } ) {
+  <a href="<% $DisplayPath %>?id=<% $Object->id %>&txt-favorite-remove=1&txn-id=<% $Transaction->id %>">Un-Favorite</a>
+%   } else {
+  <a href="<% $DisplayPath %>?id=<% $Object->id %>&txt-favorite=1&txn-id=<% $Transaction->id %>">Favorite</a>
+%   }
+</span>
 <div class="<% join ' ', @classes %>" data-transaction-id="<% $Transaction->id %>">
   <div class="metadata">
     <span class="type">
diff --git a/share/html/Ticket/Display.html b/share/html/Ticket/Display.html
index 2681a38313..93acaa6ce6 100644
--- a/share/html/Ticket/Display.html
+++ b/share/html/Ticket/Display.html
@@ -160,6 +160,21 @@ if ($ARGS{'id'} eq 'new') {
 
     my $SkipProcessing;
 
+    if ( $ARGS{'txt-favorite'} or $ARGS{'txt-favorite-remove'} && $ARGS{'txn-id'} ) {
+        my $txn = RT::Transaction->new($session{'CurrentUser'});
+        $txn->Load($ARGS{'txn-id'});
+
+        my $current_value = $txn->FirstAttribute('Favorited') ? $txn->FirstAttribute('Favorited')->Content : ();
+        if ( $ARGS{'txt-favorite'} ) {
+            $current_value->{$session{'CurrentUser'}->Id} = 1;
+            $txn->SetAttribute(Name => 'Favorited', Content => $current_value);
+        }
+        if ( $ARGS{'txt-favorite-remove'} ) {
+            $current_value->{$session{'CurrentUser'}->Id} = 0;
+            $txn->SetAttribute(Name => 'Favorited', Content => $current_value);
+        }
+    }
+
     $TicketObj->Atomic(sub{
         $m->callback( CallbackName => 'BeforeProcessArguments',
             TicketObj => $TicketObj,
diff --git a/share/html/Ticket/Elements/Favorited b/share/html/Ticket/Elements/Favorited
new file mode 100644
index 0000000000..19856b21c2
--- /dev/null
+++ b/share/html/Ticket/Elements/Favorited
@@ -0,0 +1,33 @@
+<&| /Widgets/TitleBox, title => loc("Favorites"), class => 'ticket-info-reminders', &>
+<div>
+<%perl>
+my $txns = RT::Transactions->new($session{'CurrentUser'});
+$txns->LimitToTicket($Ticket->Id);
+
+while (my $tx = $txns->Next) {
+    my $attr = $tx->FirstAttribute('Favorited');
+    next unless $attr;
+
+    if ( $attr->Content->{$session{'CurrentUser'}->Id} ) {
+</%perl>
+        <div>
+          <a href="<% RT->Config->Get('WebPath') ."/Ticket/Display.html?id=".$Ticket->id."#txn-".$tx->id%>">
+            <%  $m->comp( '/Elements/ShowTransaction',
+                %ARGS,
+                Object            => $Ticket,
+                Transaction       => $tx,
+                ShowHeaders       => 0,
+                DisplayPath       => $HTML::Mason::Commands::r->path_info
+            ) %>
+          </a>
+        </div>
+%   }
+% }
+</div>
+</&>
+<%init>
+return unless $Ticket;
+</%init>
+<%args>
+$Ticket => undef
+</%args>
diff --git a/share/html/Ticket/Elements/ShowSummary b/share/html/Ticket/Elements/ShowSummary
index 5aaacb1f87..10566aa71e 100644
--- a/share/html/Ticket/Elements/ShowSummary
+++ b/share/html/Ticket/Elements/ShowSummary
@@ -64,6 +64,8 @@
         class => 'ticket-info-people',
     &><& /Ticket/Elements/ShowPeople, Ticket => $Ticket &></&>
 % $m->callback( %ARGS, CallbackName => 'AfterPeople' );
+    <& Favorited, Ticket => $Ticket &>
+% $m->callback( %ARGS, CallbackName => 'AfterFavorites' );
     <& /Ticket/Elements/ShowAttachments, Ticket => $Ticket, Attachments => $Attachments, Count => RT->Config->Get('AttachmentListCount') &>
 % $m->callback( %ARGS, CallbackName => 'AfterAttachments' );
     <& /Ticket/Elements/ShowRequestor, Ticket => $Ticket &>

commit 90d615c9d6587ec0dc09487a4b4338e58913279e
Author: Craig Kaiser <craig at bestpractical.com>
Date:   Wed Jan 8 10:17:27 2020 -0500

    Allow for string of user IDs to be passed for exclusion from autocomplete results

diff --git a/share/html/Elements/EmailInput b/share/html/Elements/EmailInput
index 078a2870c4..b38fe48e74 100644
--- a/share/html/Elements/EmailInput
+++ b/share/html/Elements/EmailInput
@@ -79,6 +79,10 @@
     data-autocomplete-include-system
 % }
 
+if ($Exclude) {
+    data-autocomplete-exclude="<% $Exclude %>"
+}
+
 />
 % if ($EntryHint) {
 <br>
@@ -97,4 +101,5 @@ $AutocompleteNobody => 0
 $AutocompleteSystem => 0
 $EntryHint => ''
 $Placeholder => ''
+$Exclude     => undef
 </%ARGS>

-----------------------------------------------------------------------


More information about the rt-commit mailing list