[Rt-commit] rt branch 5.0/add-link-asset-autocomplete created. rt-5.0.5-47-g4ef82fdb7c

BPS Git Server git at git.bestpractical.com
Mon Nov 13 04:08:57 UTC 2023


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "rt".

The branch, 5.0/add-link-asset-autocomplete has been created
        at  4ef82fdb7c7407e13c48cf80fa6e79d3b31727f7 (commit)

- Log -----------------------------------------------------------------
commit 4ef82fdb7c7407e13c48cf80fa6e79d3b31727f7
Author: Brad Embree <brad at bestpractical.com>
Date:   Sun Nov 12 20:04:32 2023 -0800

    Use TicketsAssets autocomplete excluding existing links

diff --git a/share/html/Elements/AddLinks b/share/html/Elements/AddLinks
index 4fd5279168..e4de960c01 100644
--- a/share/html/Elements/AddLinks
+++ b/share/html/Elements/AddLinks
@@ -55,8 +55,32 @@ my $id = ($Object and $Object->id)
     ? $Object->id
     : "new";
 
-my $exclude = qq| data-autocomplete="Tickets" data-autocomplete-multiple="1"|;
-$exclude .= qq| data-autocomplete-exclude="$id"| if $Object->id;
+my $exclude = qq| data-autocomplete="TicketsAssets" data-autocomplete-multiple="1"|;
+my @excludes;
+push @excludes, ( $Object->isa('RT::Asset') ? 'asset:' : '' ) . $id
+    if $id ne 'new';
+
+my %exclude_links = (
+    DependsOn    => '',
+    DependedOnBy => '',
+    MemberOf     => '',
+    Members      => '',
+    RefersTo     => '',
+    ReferredToBy => '',
+);
+foreach my $link_type ( keys %exclude_links ) {
+    my @ids;
+    if ( $id ne 'new' ) {
+        my $links = $Object->$link_type;
+        while ( my $link = $links->Next ) {
+            if ( my $TargetObj = $link->TargetObj ) {
+                push @ids, ( $TargetObj->isa('RT::Asset') ? 'asset:' : '' ) . $TargetObj->id;
+            }
+        }
+    }
+    $exclude_links{$link_type} = $exclude . ' data-autocomplete-exclude="' . join( ' ', @excludes, @ids ) . '"'
+        if @excludes || @ids;
+}
 </%init>
 % if (ref($Object) eq 'RT::Ticket') {
 <i><&|/l&>Enter tickets or URIs to link tickets to. Separate multiple entries with spaces.</&>
@@ -76,24 +100,24 @@ $exclude .= qq| data-autocomplete-exclude="$id"| if $Object->id;
 
 
 <&| /Elements/LabeledValue, RawLabel => $m->scomp('ShowRelationLabel', Object => $Object, Label => loc('Depends on'), Relation => 'DependsOn') &>
-  <input type="text" class="form-control" name="<%$id%>-DependsOn" value="<% $ARGSRef->{"$id-DependsOn"} || '' %>" <% $exclude |n%>/>
+  <input type="text" class="form-control" name="<%$id%>-DependsOn" value="<% $ARGSRef->{"$id-DependsOn"} || '' %>" <% $exclude_links{DependsOn} |n%>/>
 </&>
 <&| /Elements/LabeledValue, RawLabel => $m->scomp('ShowRelationLabel', Object => $Object, Label => loc('Depended on by'), Relation => 'DependedOnBy') &>
-  <input type="text" class="form-control" name="DependsOn-<%$id%>" value="<% $ARGSRef->{"DependsOn-$id"} || '' %>" <% $exclude |n%>/>
+  <input type="text" class="form-control" name="DependsOn-<%$id%>" value="<% $ARGSRef->{"DependsOn-$id"} || '' %>" <% $exclude_links{DependedOnBy} |n%>/>
 </&>
 
 <&| /Elements/LabeledValue, RawLabel => $m->scomp('ShowRelationLabel', Object => $Object, Label => loc('Parents'), Relation => 'Parents') &>
-  <input type="text" class="form-control" name="<%$id%>-MemberOf" value="<% $ARGSRef->{"$id-MemberOf"} || '' %>" <% $exclude |n%>/>
+  <input type="text" class="form-control" name="<%$id%>-MemberOf" value="<% $ARGSRef->{"$id-MemberOf"} || '' %>" <% $exclude_links{MemberOf} |n%>/>
 </&>
 <&| /Elements/LabeledValue, RawLabel => $m->scomp('ShowRelationLabel', Object => $Object, Label => loc('Children'), Relation => 'Children') &>
-  <input type="text" class="form-control" name="MemberOf-<%$id%>" value="<% $ARGSRef->{"MemberOf-$id"} || '' %>" <% $exclude |n%>/>
+  <input type="text" class="form-control" name="MemberOf-<%$id%>" value="<% $ARGSRef->{"MemberOf-$id"} || '' %>" <% $exclude_links{Members} |n%>/>
 </&>
 
 <&| /Elements/LabeledValue, RawLabel => $m->scomp('ShowRelationLabel', Object => $Object, Label => loc('Refers to'), Relation => 'RefersTo') &>
-  <input type="text" class="form-control" name="<%$id%>-RefersTo" value="<% $ARGSRef->{"$id-RefersTo"} || '' %>" <% $exclude |n%>/>
+  <input type="text" class="form-control" name="<%$id%>-RefersTo" value="<% $ARGSRef->{"$id-RefersTo"} || '' %>" <% $exclude_links{RefersTo} |n%>/>
 </&>
 <&| /Elements/LabeledValue, RawLabel => $m->scomp('ShowRelationLabel', Object => $Object, Label => loc('Referred to by'), Relation => 'ReferredToBy') &>
-  <input type="text" class="form-control" name="RefersTo-<%$id%>" value="<% $ARGSRef->{"RefersTo-$id"} || '' %>" <% $exclude |n%>/>
+  <input type="text" class="form-control" name="RefersTo-<%$id%>" value="<% $ARGSRef->{"RefersTo-$id"} || '' %>" <% $exclude_links{ReferredToBy} |n%>/>
 </&>
 
   <& /Elements/EditCustomFields,

commit bc63b8d74d8110f5eb940fa4e406a9ed94a96b96
Author: Brad Embree <brad at bestpractical.com>
Date:   Sun Nov 12 20:02:04 2023 -0800

    Exclude assets that are already linked

diff --git a/share/html/Ticket/Elements/ShowAssets b/share/html/Ticket/Elements/ShowAssets
index e6c60bb728..51bfbd152e 100644
--- a/share/html/Ticket/Elements/ShowAssets
+++ b/share/html/Ticket/Elements/ShowAssets
@@ -214,7 +214,7 @@ if ($ShowRelatedTickets) {
     <label><&|/l&>Add an asset to this ticket:</&></label>
     <div class="form-row">
       <div class="form-group mx-sm-3 mb-2">
-        <input data-autocomplete="Assets" class="form-control mb-2" size="10" name="<% $Ticket->id %>-RefersTo" placeholder="<&|/l&>Asset #</&>" type="text">
+        <input data-autocomplete="Assets" class="form-control mb-2" size="10" name="<% $Ticket->id %>-RefersTo" placeholder="<&|/l&>Asset #</&>" data-autocomplete-exclude="<% join(',', @linked_assets) |n %>" type="text">
       </div>
       <button type="submit" name="AddAsset" value="Add" class="button btn btn-primary form-control mb-2">Add</button>
     </div>

commit ad29a602fdc9b9768829bc71639b6ae0ab438a58
Author: Brad Embree <brad at bestpractical.com>
Date:   Sun Nov 12 20:00:54 2023 -0800

    Add support for TicketsAssets autocomplete

diff --git a/share/static/js/autocomplete.js b/share/static/js/autocomplete.js
index c967050ddf..7289eb5c62 100644
--- a/share/static/js/autocomplete.js
+++ b/share/static/js/autocomplete.js
@@ -9,7 +9,8 @@ window.RT.Autocomplete.Classes = {
     Queues: 'queues',
     Articles: 'articles',
     Assets: 'assets',
-    Principals: 'principals'
+    Principals: 'principals',
+    TicketsAssets: 'tickets-assets'
 };
 
 Selectize.define('rt_drag_drop', function(options) {
@@ -150,7 +151,7 @@ window.RT.Autocomplete.bind = function(from) {
         }
 
         if (input.is('[data-autocomplete-multiple]')) {
-            if ( what != 'Tickets' ) {
+            if ( what != 'Tickets' && what != 'TicketsAssets' ) {
                 queryargs.push("delim=,");
             }
 
@@ -160,13 +161,13 @@ window.RT.Autocomplete.bind = function(from) {
             }
 
             options.select = function(event, ui) {
-                var terms = this.value.split(what == 'Tickets' ? /\s+/ : /,\s*/);
+                var terms = this.value.split((what == 'Tickets' || what == 'TicketsAssets') ? /\s+/ : /,\s*/);
                 terms.pop();                    // remove current input
-                if ( what == 'Tickets' ) {
+                if ( what == 'Tickets' || what == 'TicketsAssets' ) {
                     // remove non-integers in case subject search with spaces in (like "foo bar")
                     var new_terms = [];
                     for ( var i = 0; i < terms.length; i++ ) {
-                        if ( terms[i].match(/\D/) ) {
+                        if ( terms[i].match(/^(?:asset:)?\D/) ) {
                             break; // Items after the first non-integers are all parts of search string
                         }
                         new_terms.push(terms[i]);
@@ -175,7 +176,7 @@ window.RT.Autocomplete.bind = function(from) {
                 }
                 terms.push( ui.item.value );    // add selected item
                 terms.push(''); // add trailing delimeter so user can input another value directly
-                this.value = terms.join(what == 'Tickets' ? ' ' : ", ");
+                this.value = terms.join((what == 'Tickets' || what == 'TicketsAssets') ? ' ' : ", ");
                 jQuery(this).change();
 
                 return false;

commit 49fe308742d41bc5915fd5d1481fb12f4074eb05
Author: Brad Embree <brad at bestpractical.com>
Date:   Sun Nov 12 19:59:30 2023 -0800

    Add TicketsAssets Autocomplete
    
    Add an autocomplete that supports both tickets and assets to allow
    autocomplete of both in the same input.

diff --git a/share/html/Helpers/Autocomplete/TicketsAssets b/share/html/Helpers/Autocomplete/TicketsAssets
new file mode 100644
index 0000000000..96a0f1cc45
--- /dev/null
+++ b/share/html/Helpers/Autocomplete/TicketsAssets
@@ -0,0 +1,76 @@
+%# BEGIN BPS TAGGED BLOCK {{{
+%#
+%# COPYRIGHT:
+%#
+%# This software is Copyright (c) 1996-2023 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 }}}
+% $r->content_type('application/json; charset=utf-8');
+<% JSON( \@suggestions ) |n %>
+% $m->abort;
+<%args>
+$return => ''
+$term => undef
+$max => undef
+$exclude => ''
+</%args>
+<%init>
+$m->abort unless defined $term
+             and length $term;
+
+my @suggestions;
+my @excludes;
+
+( my $prev, my $type, $term ) = $term =~ /^((?:(asset:)?\d+\s+)*)(.*)/;
+ at excludes = split ' ', $prev if $prev;
+push @excludes, split ' ', $exclude if $exclude;
+
+if ( $term =~ /^asset:./ ) {
+    my $exclude_assets = join( ',', map( /(\d+)/, grep( /^asset:\d+$/, @excludes ) ) );
+    @suggestions = $m->comp( 'Assets', term => substr($term, 6), max => $max, exclude => $exclude_assets, return_suggestions => 1 );
+    @suggestions = map { { id => $_->{id}, label => $_->{label}, value => 'asset:' . $_->{value} } } @suggestions;
+} else {
+    my $exclude_tickets = join( ' ', grep( /^\d+$/, @excludes ) );
+    @suggestions = $m->comp( 'Tickets', return => $return, term => $term, max => $max, exclude => $exclude_tickets, return_suggestions => 1 );
+}
+</%init>

commit 91ff6dab60fe7358874ee5002549bb2249c1f13e
Author: Brad Embree <brad at bestpractical.com>
Date:   Sun Nov 12 19:58:56 2023 -0800

    Format asset suggestions as id: Name

diff --git a/share/html/Helpers/Autocomplete/Assets b/share/html/Helpers/Autocomplete/Assets
index a35d61e946..433ebd0842 100644
--- a/share/html/Helpers/Autocomplete/Assets
+++ b/share/html/Helpers/Autocomplete/Assets
@@ -98,7 +98,8 @@ my @suggestions;
 while (my $a = $assets->Next) {
     next if $right and not $a->CurrentUserHasRight($right);
     my $value = $a->$return;
-    push @suggestions, { label => $a->Name, value => $value };
+    my $formatted = loc( "#[_1]: [_2]", $a->id, $a->Name );
+    push @suggestions, { label => $formatted, value => $value };
 }
 return @suggestions if $return_suggestions;
 </%INIT>

commit fb849b1b0ed72042e09bf426a2a023b389d895f3
Author: Brad Embree <brad at bestpractical.com>
Date:   Sun Nov 12 19:58:01 2023 -0800

    Add exclude arg to assets autocomplete

diff --git a/share/html/Helpers/Autocomplete/Assets b/share/html/Helpers/Autocomplete/Assets
index b426580245..a35d61e946 100644
--- a/share/html/Helpers/Autocomplete/Assets
+++ b/share/html/Helpers/Autocomplete/Assets
@@ -56,6 +56,7 @@ $op                 => 'STARTSWITH'
 $right              => undef
 $return             => 'id'
 $queue              => undef
+$exclude            => ''
 $return_suggestions => 0
 </%ARGS>
 
@@ -82,6 +83,17 @@ $assets->Limit(
     CASESENSITIVE   => 0,
 );
 
+# Exclude assets we don't want
+foreach ( split /\s*,\s*/, $exclude ) {
+    $assets->Limit(
+        FIELD           => 'id',
+        VALUE           => $_,
+        OPERATOR        => '!=',
+        ENTRYAGGREGATOR => 'AND',
+        SUBCLAUSE       => 'excludeautocomplete'
+    );
+}
+
 my @suggestions;
 while (my $a = $assets->Next) {
     next if $right and not $a->CurrentUserHasRight($right);

commit 2cc71e8388ff793fc40e908918e3ee52ff77f0a4
Author: Brad Embree <brad at bestpractical.com>
Date:   Sun Nov 12 19:54:57 2023 -0800

    Add arg to return suggestions
    
    Add a return_suggestions arg to allow other mason components to call
    assets and tickets autocomplete components.

diff --git a/share/html/Helpers/Autocomplete/Assets b/share/html/Helpers/Autocomplete/Assets
index ef93af5acc..b426580245 100644
--- a/share/html/Helpers/Autocomplete/Assets
+++ b/share/html/Helpers/Autocomplete/Assets
@@ -50,12 +50,13 @@
 % $m->abort;
 
 <%ARGS>
-$term       => undef
-$max        => 10
-$op         => 'STARTSWITH'
-$right      => undef
-$return     => 'id'
-$queue      => undef
+$term               => undef
+$max                => 10
+$op                 => 'STARTSWITH'
+$right              => undef
+$return             => 'id'
+$queue              => undef
+$return_suggestions => 0
 </%ARGS>
 
 <%INIT>
@@ -87,4 +88,5 @@ while (my $a = $assets->Next) {
     my $value = $a->$return;
     push @suggestions, { label => $a->Name, value => $value };
 }
+return @suggestions if $return_suggestions;
 </%INIT>
diff --git a/share/html/Helpers/Autocomplete/Tickets b/share/html/Helpers/Autocomplete/Tickets
index 8e9462ce6a..92b3e7c194 100644
--- a/share/html/Helpers/Autocomplete/Tickets
+++ b/share/html/Helpers/Autocomplete/Tickets
@@ -54,6 +54,7 @@ $term => undef
 $max => undef
 $exclude => ''
 $limit => undef
+$return_suggestions => 0
 </%ARGS>
 <%INIT>
 # Only allow certain return fields
@@ -110,5 +111,6 @@ while ( my $ticket = $tickets->Next ) {
     my $formatted = loc("#[_1]: [_2]", $ticket->Id, $ticket->Subject);
     push @suggestions, { label => $formatted, value => $ticket->$return };
 }
+return @suggestions if $return_suggestions;
 
 </%INIT>

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


hooks/post-receive
-- 
rt


More information about the rt-commit mailing list