[Rt-commit] rt branch, 4.4/role-group-input, created. rt-4.4.1-126-g82dd14d

Shawn Moore shawn at bestpractical.com
Thu May 18 11:56:04 EDT 2017


The branch, 4.4/role-group-input has been created
        at  82dd14dd6c5723d14da24616507e882f2382d9c8 (commit)

- Log -----------------------------------------------------------------
commit 5df72a7f3ee11081cca992d58426086e5bf02fbe
Author: Shawn M Moore <shawn at bestpractical.com>
Date:   Wed May 17 22:47:24 2017 +0000

    Use CanonicalizePrincipal in DeleteWatcher
    
    This also fixes a bug where the internal "RT::CustomRole-#" syntax may
    show up in error messages when removing a watcher from a custom
    role fails

diff --git a/lib/RT/Record/Role/Roles.pm b/lib/RT/Record/Role/Roles.pm
index 284c6c0..71dd14a 100644
--- a/lib/RT/Record/Role/Roles.pm
+++ b/lib/RT/Record/Role/Roles.pm
@@ -541,20 +541,28 @@ sub DeleteRoleMember {
     return (0, $self->loc("That role is invalid for this object"))
         unless $args{Type} and $self->HasRole($args{Type});
 
-    if ($args{User}) {
-        my $user = RT::User->new( $self->CurrentUser );
-        $user->LoadByEmail( $args{User} );
-        $user->Load( $args{User} ) unless $user->id;
-        return (0, $self->loc("Could not load user '[_1]'", $args{User}) )
-            unless $user->id;
-        $args{PrincipalId} = $user->PrincipalId;
+    my $principal;
+    if ($args{Principal}) {
+        $principal = $args{Principal};
+        $args{PrincipalId} = $principal->Id;
     }
+    else {
+        if ($args{User}) {
+            my $user = RT::User->new( $self->CurrentUser );
+            $user->LoadByEmail( $args{User} );
+            $user->Load( $args{User} ) unless $user->id;
+            return (0, $self->loc("Could not load user '[_1]'", $args{User}) )
+                unless $user->id;
+            $args{PrincipalId} = $user->PrincipalId;
+        }
 
-    return (0, $self->loc("No valid PrincipalId"))
-        unless $args{PrincipalId};
+        return (0, $self->loc("No valid PrincipalId"))
+            unless $args{PrincipalId};
+
+        $principal = RT::Principal->new( $self->CurrentUser );
+        $principal->Load( $args{PrincipalId} );
+    }
 
-    my $principal = RT::Principal->new( $self->CurrentUser );
-    $principal->Load( $args{PrincipalId} );
 
     my $acl = delete $args{ACL};
     return (0, $self->loc("Permission denied"))
@@ -573,7 +581,7 @@ sub DeleteRoleMember {
         $RT::Logger->error("Failed to remove $args{PrincipalId} as a member of group ".$group->Id.": ".$msg);
 
         return ( 0, $self->loc('Could not remove [_1] as a [_2]',
-                    $principal->Object->Name, $self->loc($args{Type})) );
+                    $principal->Object->Name, $group->Label) );
     }
 
     return ($principal, $msg);
diff --git a/lib/RT/Ticket.pm b/lib/RT/Ticket.pm
index ff9b8d2..0530d7c 100644
--- a/lib/RT/Ticket.pm
+++ b/lib/RT/Ticket.pm
@@ -710,8 +710,17 @@ sub DeleteWatcher {
 
     $args{ACL} = sub { $self->_HasModifyWatcherRight( @_ ) };
     $args{User} ||= delete $args{Email};
-    my ($principal, $msg) = $self->DeleteRoleMember( %args );
-    return ( 0, $msg ) unless $principal;
+
+    my ($principal, $msg) = $self->CanonicalizePrincipal(%args);
+    if (!$principal) {
+        return (0, $msg);
+    }
+
+    ((my $ok), $msg) = $self->DeleteRoleMember(
+        Principal => $principal,
+        %args,
+    );
+    return ( 0, $msg ) unless $ok;
 
     my $group = $self->RoleGroup( $args{Type} );
     return ( 1,

commit cd177418bf26dd9cafdae6308eb66cbe56c39495
Author: Shawn M Moore <shawn at bestpractical.com>
Date:   Wed May 17 22:47:44 2017 +0000

    Handle Group:Name and Group:ID in role input fields

diff --git a/lib/RT/Record/Role/Roles.pm b/lib/RT/Record/Role/Roles.pm
index 71dd14a..d7381df 100644
--- a/lib/RT/Record/Role/Roles.pm
+++ b/lib/RT/Record/Role/Roles.pm
@@ -389,8 +389,14 @@ sub CanonicalizePrincipal {
                 if RT::EmailParser->IsRTAddress( $email );
         }
     } else {
-        if ($args{User}) {
+        if ($args{User} =~ /^\s*Group\s*:\s*(.+?)\s*$/) {
+            $args{Group} = $1;
+            delete $args{User};
+        }
+        elsif ($args{User}) {
             my $name = delete $args{User};
+            delete $args{Group};
+
             # Sanity check the address
             return (0, $self->loc("[_1] is an address RT receives mail at. Adding it as a '[_2]' would create a mail loop",
                                   $name, $self->loc($args{Type}) ))
@@ -411,7 +417,8 @@ sub CanonicalizePrincipal {
             }
             $args{PrincipalId} = $user->PrincipalId;
         }
-        elsif ($args{Group}) {
+
+        if ($args{Group}) {
             my $name = delete $args{Group};
             my $group = RT::Group->new( $self->CurrentUser );
             $group->LoadUserDefinedGroup($name);
@@ -617,7 +624,18 @@ sub _ResolveRoles {
         } else {
             $roles->{$role} = [];
             my @values = ref $args{ $role } ? @{ $args{$role} } : ($args{$role});
-            for my $value (grep {defined} @values) {
+
+            while (my $value = shift @values) {
+                # extract "Group:xyz" early because Email::Address::List
+                # chokes on trying to parse that as an email address.
+                # (but not if "Group:xyz" is the very first entry, otherwise
+                # you'll get stuck in an infinite loop)
+                while ($value =~ s/,\s*(Group\s*:\s*[^,]+)($|,)/$2/) {
+                    push @values, $1;
+                }
+
+                next unless ($value||'') =~ /\S/;
+
                 if ( $value =~ /^\d+$/ ) {
                     # This implicitly allows groups, if passed by id.
                     my $principal = RT::Principal->new( $self->CurrentUser );
@@ -628,6 +646,18 @@ sub _ResolveRoles {
                         push @errors,
                             $self->loc("Couldn't load principal: [_1]", $msg);
                     }
+                } elsif ($value =~ /^\s*Group\s*:\s*([^,]+),?(.*)/) {
+                    my ($name, $rest) = ($1, $2);
+                    push @values, $rest;
+
+                    my $group = RT::Group->new( $self->CurrentUser );
+                    my ($ok, $msg) = $group->LoadUserDefinedGroup( $name );
+                    if ($ok) {
+                        push @{ $roles->{$role} }, $group->PrincipalObj;
+                    } else {
+                        push @errors,
+                            $self->loc("Couldn't load group [_1]: [_1]", $name, $msg);
+                    }
                 } else {
                     my @addresses = RT::EmailParser->ParseEmailAddress( $value );
                     for my $address ( @addresses ) {
diff --git a/share/html/Ticket/Create.html b/share/html/Ticket/Create.html
index e396857..f8546da 100644
--- a/share/html/Ticket/Create.html
+++ b/share/html/Ticket/Create.html
@@ -463,17 +463,18 @@ if ( !exists $ARGS{'AddMoreAttach'} && ($ARGS{'id'}||'') eq 'new' ) {
 
 # check email addresses for RT's
 {
+    my $roles = {};
+    $QueueObj->_ResolveRoles( $roles, %ARGS );
+
     foreach my $field ( qw(Requestors Cc AdminCc) ) {
-        my $value = $ARGS{ $field };
-        next unless defined $value && length $value;
+        for my $principal (@{ $roles->{ $field } }) {
+            next unless $principal->IsUser;
+            my $email = $principal->Object->EmailAddress;
+            next unless RT::EmailParser->IsRTAddress($email);
 
-        my @emails = Email::Address->parse( $value );
-        foreach my $email ( grep RT::EmailParser->IsRTAddress($_->address), @emails ) {
-            push @results, loc("[_1] is an address RT receives mail at. Adding it as a '[_2]' would create a mail loop", $email->format, loc($field =~ /^(.*?)s?$/) );
+            push @results, loc("[_1] is an address RT receives mail at. Adding it as a '[_2]' would create a mail loop", $email, loc($field =~ /^(.*?)s?$/) );
             $checks_failure = 1;
-            $email = undef;
         }
-        $ARGS{ $field } = join ', ', map $_->format, grep defined, @emails;
     }
 }
 

commit d45dc7c7008427888fc8d1e3cd90afca13518243
Author: Shawn M Moore <shawn at bestpractical.com>
Date:   Wed May 17 21:31:27 2017 +0000

    Add principals (user and group) autocompleter

diff --git a/share/html/Elements/EmailInput b/share/html/Elements/EmailInput
index 9e078d7..f327018 100644
--- a/share/html/Elements/EmailInput
+++ b/share/html/Elements/EmailInput
@@ -60,7 +60,7 @@
 % }
 
 % if ($Autocomplete) {
-    data-autocomplete="Users"
+    data-autocomplete="<% $AutocompleteType %>"
 % }
 
 % if ($AutocompleteMultiple) {
@@ -91,6 +91,7 @@ $Name
 $Size    => 40
 $Default => ''
 $Autocomplete => 1
+$AutocompleteType => 'Users'
 $AutocompleteMultiple => 0
 $AutocompleteReturn => ''
 $AutocompleteNobody => 0
diff --git a/share/html/Helpers/Autocomplete/Principals b/share/html/Helpers/Autocomplete/Principals
new file mode 100644
index 0000000..77191e1
--- /dev/null
+++ b/share/html/Helpers/Autocomplete/Principals
@@ -0,0 +1,142 @@
+%# BEGIN BPS TAGGED BLOCK {{{
+%#
+%# COPYRIGHT:
+%#
+%# This software is Copyright (c) 1996-2016 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>
+$term => undef
+$delim => undef
+$max => undef
+$privileged => undef
+$exclude => ''
+$include_nobody => 0
+$include_system => 0
+</%ARGS>
+<%INIT>
+my $return = 'EmailAddress';
+my $op = 'STARTSWITH';
+
+$m->abort unless defined $return
+             and defined $term
+             and length $term;
+
+# Use our delimeter if we have one
+if ( defined $delim and length $delim ) {
+    if ( $delim eq ',' ) {
+        $delim = qr/,\s*/;
+    } else {
+        $delim = qr/\Q$delim\E/;
+    }
+
+    # If the field handles multiple values, pop the last one off
+    $term = (split $delim, $term)[-1] if $term =~ $delim;
+}
+
+my $CurrentUser = $session{'CurrentUser'};
+
+# Require privileged users or overriding config
+$m->abort unless $CurrentUser->Privileged
+              or RT->Config->Get('AllowUserAutocompleteForUnprivileged');
+
+# the API wants a list of ids
+my @exclude = split /\s*,\s*/, $exclude;
+push @exclude, RT->SystemUser->id unless $include_system;
+push @exclude, RT->Nobody->id unless $include_nobody;
+
+$m->callback( CallbackName => 'ModifyMaxResults', max => \$max );
+$max //= 10;
+
+my $users = RT::Users->new($CurrentUser);
+$users->SimpleSearch( Privileged => $privileged,
+                      Return     => $return,
+                      Term       => $term,
+                      Max        => $max,
+                      Exclude    => \@exclude,
+                      # If an operator is provided, check against only
+                      # the returned field using that operator
+                      $op ? ( Fields => { $return => $op } ) : (),
+                    );
+
+(my $group_term = $term) =~ s/^\s*Group\s*:\s*//;
+my $groups = RT::Groups->new( $CurrentUser );
+$groups->RowsPerPage( $max );
+$groups->LimitToUserDefinedGroups();
+$groups->Limit(
+    FIELD           => 'Name',
+    OPERATOR        => $op,
+    VALUE           => $group_term,
+    CASESENSITIVE   => 0,
+);
+
+# Exclude groups we don't want
+foreach (@exclude) {
+    $groups->Limit(FIELD => 'id', VALUE => $_, OPERATOR => '!=', ENTRYAGGREGATOR => 'AND');
+}
+
+my @suggestions;
+
+while ( my $user = $users->Next ) {
+    my $suggestion = { id => $user->id, label => $user->Format, value => $user->$return, type => loc('User') };
+    $m->callback( CallbackName => "ModifySuggestion", suggestion => $suggestion, user => $user );
+    push @suggestions, $suggestion;
+}
+
+while ( my $group = $groups->Next ) {
+    my $value = 'Group:' . $group->Name;
+
+    # if group name contains, say, a comma, then use its id instead to avoid
+    # parsing problems
+    $value = 'Group:' . $group->id if $delim && $value =~ $delim;
+
+    my $suggestion = { id => $group->Id, label => $group->Label, value => $value, type => loc('Group') };
+    $m->callback( CallbackName => "ModifySuggestion", suggestion => $suggestion, group => $group );
+    push @suggestions, $suggestion;
+
+    last if @suggestions >= $max;
+}
+</%INIT>
diff --git a/share/static/css/base/forms.css b/share/static/css/base/forms.css
index 2584ee0..d31927e 100644
--- a/share/static/css/base/forms.css
+++ b/share/static/css/base/forms.css
@@ -268,6 +268,13 @@ ul.selectable a {
     font-size: .8em;
 }
 
+.ui-autocomplete .recordtype {
+    display: block;
+    font-size: .8em;
+    font-style: italic;
+    color: #999;
+}
+
 /* query builder */
 
 #formatbuttons {
diff --git a/share/static/js/autocomplete.js b/share/static/js/autocomplete.js
index cd8ab2b..a995078 100644
--- a/share/static/js/autocomplete.js
+++ b/share/static/js/autocomplete.js
@@ -5,7 +5,8 @@ window.RT.Autocomplete.Classes = {
     Users: 'user',
     Groups: 'group',
     Tickets: 'tickets',
-    Queues: 'queues'
+    Queues: 'queues',
+    Principals: 'principals'
 };
 
 window.RT.Autocomplete.bind = function(from) {
@@ -106,6 +107,12 @@ window.RT.Autocomplete.bind = function(from) {
                 else
                     rendered.html( item.html );
 
+                if (item.type) {
+                    var type = jQuery('<span class="recordtype">');
+                    type.text(item.type);
+                    rendered.append(type);
+                }
+
                 return jQuery("<li/>")
                     .data( "item.autocomplete", item )
                     .append( rendered )

commit 82dd14dd6c5723d14da24616507e882f2382d9c8
Author: Shawn M Moore <shawn at bestpractical.com>
Date:   Wed May 17 21:38:42 2017 +0000

    Use principals autocompleter for role input fields

diff --git a/share/html/Asset/Elements/EditPeople b/share/html/Asset/Elements/EditPeople
index 658b436..41bf625 100644
--- a/share/html/Asset/Elements/EditPeople
+++ b/share/html/Asset/Elements/EditPeople
@@ -52,7 +52,7 @@
 <% loc($role) %>:
 </td>
 <td class="value" colspan="5">
-<& /Elements/EmailInput, Name => $role, Size => undef, Default => $ARGS{$role}, Autocomplete => 1 &>
+<& /Elements/EmailInput, Name => $role, Size => undef, Default => $ARGS{$role}, Autocomplete => 1, ($AssetObj->Role($role)->{Single} ? () : (AutocompleteType => 'Principals', AutocompleteMultiple => 1)) &>
 </td>
 </tr>
 % }
diff --git a/share/html/Asset/Elements/EditPeople b/share/html/Elements/MultiUserRoleInput
similarity index 84%
copy from share/html/Asset/Elements/EditPeople
copy to share/html/Elements/MultiUserRoleInput
index 658b436..7814d35 100644
--- a/share/html/Asset/Elements/EditPeople
+++ b/share/html/Elements/MultiUserRoleInput
@@ -45,20 +45,16 @@
 %# those contributions and any derivatives thereof.
 %#
 %# END BPS TAGGED BLOCK }}}
-<table border="0" cellpadding="0" cellspacing="0">
-% for my $role ( $AssetObj->Roles ) {
-<tr class="asset-people-<% CSSClass($role) %>">
-<td class="label">
-<% loc($role) %>:
-</td>
-<td class="value" colspan="5">
-<& /Elements/EmailInput, Name => $role, Size => undef, Default => $ARGS{$role}, Autocomplete => 1 &>
-</td>
-</tr>
-% }
-
-</table>
-
-<%args>
-$AssetObj
-</%args>
+<& /Elements/EmailInput,
+    Name => $role->GroupType,
+    ($ShowEntryHint ? (EntryHint => $role->EntryHint) : ()),
+    Autocomplete => 1,
+    AutocompleteType => 'Principals',
+    AutocompleteMultiple => 1,
+    %ARGS,
+&>
+<%ARGS>
+$role
+$Ticket => undef
+$ShowEntryHint => 1
+</%ARGS>
diff --git a/share/html/Elements/QuickCreate b/share/html/Elements/QuickCreate
index 466565d..ab7648f 100644
--- a/share/html/Elements/QuickCreate
+++ b/share/html/Elements/QuickCreate
@@ -69,7 +69,7 @@
 </tr>
 <tr class="input-row">
     <td class="label"><&|/l&>Requestors</&>:</td>
-    <td colspan="3" class="value"><& /Elements/EmailInput, Name => 'Requestors', Size => '40', Default => $args->{Requestors} || $session{CurrentUser}->EmailAddress, AutocompleteMultiple => 1 &></td>
+    <td colspan="3" class="value"><& /Elements/EmailInput, Name => 'Requestors', AutocompleteType => 'Principals', Size => '40', Default => $args->{Requestors} || $session{CurrentUser}->EmailAddress, AutocompleteMultiple => 1 &></td>
 </tr>
 <tr class="input-row">
 <td class="labeltop"><&|/l&>Content</&>:</td>
diff --git a/share/html/Search/Bulk.html b/share/html/Search/Bulk.html
index 326e830..2281203 100644
--- a/share/html/Search/Bulk.html
+++ b/share/html/Search/Bulk.html
@@ -83,17 +83,17 @@
 <label>(<input type="checkbox" class="checkbox" name="ForceOwnerChange"
 <% $ARGS{ForceOwnerChange} ? 'checked="checked"' : '' %> /> <&|/l&>Force change</&>)</label></td></tr>
 <tr><td class="label"> <&|/l&>Add Requestor</&>: </td>
-<td class="value"> <& /Elements/EmailInput, Name => "AddRequestor", Size=> 20, Default => $ARGS{AddRequestor} &> </td></tr>
+<td class="value"> <& /Elements/EmailInput, Name => "AddRequestor", Size=> 20, Default => $ARGS{AddRequestor}, AutocompleteType => 'Principals' &> </td></tr>
 <tr><td class="label"> <&|/l&>Remove Requestor</&>: </td>
-<td class="value"> <& /Elements/EmailInput, Name => "DeleteRequestor", Size=> 20, Default => $ARGS{DeleteRequestor} &> </td></tr>
+<td class="value"> <& /Elements/EmailInput, Name => "DeleteRequestor", Size=> 20, Default => $ARGS{DeleteRequestor}, AutocompleteType => 'Principals' &> </td></tr>
 <tr><td class="label"> <&|/l&>Add Cc</&>: </td>
-<td class="value"> <& /Elements/EmailInput, Name => "AddCc", Size=> 20, Default => $ARGS{AddCc} &> </td></tr>
+<td class="value"> <& /Elements/EmailInput, Name => "AddCc", Size=> 20, Default => $ARGS{AddCc}, AutocompleteType => 'Principals' &> </td></tr>
 <tr><td class="label"> <&|/l&>Remove Cc</&>: </td>
-<td class="value"> <& /Elements/EmailInput, Name => "DeleteCc", Size=> 20, Default => $ARGS{DeleteCc} &> </td></tr>
+<td class="value"> <& /Elements/EmailInput, Name => "DeleteCc", Size=> 20, Default => $ARGS{DeleteCc}, AutocompleteType => 'Principals' &> </td></tr>
 <tr><td class="label"> <&|/l&>Add AdminCc</&>: </td>
-<td class="value"> <& /Elements/EmailInput, Name => "AddAdminCc", Size=> 20, Default => $ARGS{AddAdminCc} &> </td></tr>
+<td class="value"> <& /Elements/EmailInput, Name => "AddAdminCc", Size=> 20, Default => $ARGS{AddAdminCc}, AutocompleteType => 'Principals' &> </td></tr>
 <tr><td class="label"> <&|/l&>Remove AdminCc</&>: </td>
-<td class="value"> <& /Elements/EmailInput, Name => "DeleteAdminCc", Size=> 20, Default => $ARGS{DeleteAdminCc} &> </td></tr>
+<td class="value"> <& /Elements/EmailInput, Name => "DeleteAdminCc", Size=> 20, Default => $ARGS{DeleteAdminCc}, AutocompleteType => 'Principals' &> </td></tr>
 
 % my $single_roles = RT::CustomRoles->new($session{CurrentUser});
 % $single_roles->LimitToSingleValue;
@@ -111,11 +111,11 @@
 % while (my $role = $multi_roles->Next) {
 <tr>
 <td class="label"> <&|/l, $role->Name &>Add [_1]</&>: </td>
-<td class="value"> <& /Elements/EmailInput, Name => "AddRT::CustomRole-" . $role->Id, Size=> 20, Default => $ARGS{"AddRT::CustomRole-" . $role->Id} &> </td>
+<td class="value"> <& /Elements/MultiUserRoleInput, role => $role, Name => "AddRT::CustomRole-" . $role->Id, Size => 20, Default => $ARGS{"AddRT::CustomRole-" . $role->Id}, AutocompleteMultiple => 0 &> </td>
 </tr>
 <tr>
 <td class="label"> <&|/l, $role->Name &>Remove [_1]</&>: </td>
-<td class="value"> <& /Elements/EmailInput, Name => "DeleteRT::CustomRole-" . $role->Id, Size=> 20, Default => $ARGS{"DeleteRT::CustomRole-" . $role->Id} &> </td>
+<td class="value"> <& /Elements/MultiUserRoleInput, role => $role, Name => "DeleteRT::CustomRole-" . $role->Id, Size => 20, Default => $ARGS{"DeleteRT::CustomRole-" . $role->Id}, AutocompleteMultiple => 0 &> </td>
 </tr>
 % }
 
diff --git a/share/html/SelfService/Create.html b/share/html/SelfService/Create.html
index 33faa5b..c8d0749 100644
--- a/share/html/SelfService/Create.html
+++ b/share/html/SelfService/Create.html
@@ -71,7 +71,7 @@
 <&|/l&>Requestors</&>:
 </td>
 <td class="value">
-<& /Elements/EmailInput, Name => 'Requestors', Size => '20', Default => $ARGS{Requestors} || $session{CurrentUser}->EmailAddress, AutocompleteMultiple => 1 &>
+<& /Elements/EmailInput, Name => 'Requestors', Size => '20', Default => $ARGS{Requestors} || $session{CurrentUser}->EmailAddress, AutocompleteMultiple => 1, AutocompleteType => 'Principals' &>
 </td>
 </tr>
 <tr>
@@ -79,7 +79,7 @@
 <&|/l&>Cc</&>:
 </td>
 <td class="value">
-<& /Elements/EmailInput, Name => 'Cc', Size => '20', Default => $ARGS{Cc} || '', AutocompleteMultiple => 1 &>
+<& /Elements/EmailInput, Name => 'Cc', Size => '20', Default => $ARGS{Cc} || '', AutocompleteMultiple => 1, AutocompleteType => 'Principals' &>
 </td>
 </tr>
 <tr>
diff --git a/share/html/Ticket/Create.html b/share/html/Ticket/Create.html
index f8546da..037cbe1 100644
--- a/share/html/Ticket/Create.html
+++ b/share/html/Ticket/Create.html
@@ -148,7 +148,7 @@
 <&|/l&>Requestors</&>:
 </td>
 <td class="value" colspan="5">
-<& /Elements/EmailInput, Name => 'Requestors', Size => undef, Default => $ARGS{Requestors} // $session{CurrentUser}->EmailAddress, AutocompleteMultiple => 1 &>
+<& /Elements/EmailInput, Name => 'Requestors', Size => undef, Default => $ARGS{Requestors} // $session{CurrentUser}->EmailAddress, AutocompleteMultiple => 1, AutocompleteType => 'Principals' &>
 % $m->callback( CallbackName => 'AfterRequestors', QueueObj => $QueueObj, ARGSRef => \%ARGS );
 </td>
 </tr>
@@ -156,7 +156,7 @@
 <td class="label">
 <&|/l&>Cc</&>:
 </td>
-<td class="value" colspan="5"><& /Elements/EmailInput, Name => 'Cc', Size => undef, Default => $ARGS{Cc}, AutocompleteMultiple => 1 &></td>
+<td class="value" colspan="5"><& /Elements/EmailInput, Name => 'Cc', Size => undef, Default => $ARGS{Cc}, AutocompleteMultiple => 1, AutocompleteType => 'Principals' &></td>
 </tr>
 
 <tr>
@@ -172,7 +172,7 @@
 <td class="label">
 <&|/l&>Admin Cc</&>:
 </td>
-<td class="value" colspan="5"><& /Elements/EmailInput, Name => 'AdminCc', Size => undef, Default => $ARGS{AdminCc}, AutocompleteMultiple => 1 &></td>
+<td class="value" colspan="5"><& /Elements/EmailInput, Name => 'AdminCc', Size => undef, Default => $ARGS{AdminCc}, AutocompleteMultiple => 1, AutocompleteType => 'Principals' &></td>
 </tr>
 
 <tr>
@@ -191,7 +191,7 @@
 <td class="label">
 <% $role->Name %>:
 </td>
-<td class="value" colspan="5"><& /Elements/EmailInput, Name => $role->GroupType, Size => undef, Default => $ARGS{$role->GroupType}, AutocompleteMultiple => 1 &></td>
+<td class="value" colspan="5"><& /Elements/MultiUserRoleInput, role => $role, Default => $ARGS{$role->GroupType} &></td>
 </tr>
 
 % if ($role->EntryHint) {
diff --git a/share/html/Ticket/Elements/AddWatchers b/share/html/Ticket/Elements/AddWatchers
index 1cbb6fc..6bbf0a8 100644
--- a/share/html/Ticket/Elements/AddWatchers
+++ b/share/html/Ticket/Elements/AddWatchers
@@ -104,7 +104,7 @@
 <tr><td>
 <&/Elements/SelectWatcherType, Name => "WatcherTypeEmail" . $i, Queue => $Ticket->QueueObj &>
 </td><td>
-<& /Elements/EmailInput, Name => 'WatcherAddressEmail' . $i, Size => '20' &>
+<& /Elements/EmailInput, Name => 'WatcherAddressEmail' . $i, Size => '20', AutocompleteType => 'Principals' &>
 </td></tr>
 % }
 </table>

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


More information about the rt-commit mailing list