[Bps-public-commit] rt-extension-assetsql branch, asset-sql-custom-roles, created. 0.04-1-g263a1a6
Craig Kaiser
craig at bestpractical.com
Tue Nov 14 08:00:31 EST 2017
The branch, asset-sql-custom-roles has been created
at 263a1a677ff199c59c1749d42616d8bd050cee06 (commit)
- Log -----------------------------------------------------------------
commit 263a1a677ff199c59c1749d42616d8bd050cee06
Author: craig <craig at bestpractical.com>
Date: Wed Nov 8 13:39:25 2017 -0500
Add support for CustomRoles in Asset Search Builder
b77e1d2db search assets based on Custom Roles.
Allows user to search CRs based on which catalog
is chosen.
If a catalog is chosen CustomRoles available for
the selected catalog can now be selected as part
of the query as well as the 'display columns' options.
diff --git a/html/Asset/Search/Build.html b/html/Asset/Search/Build.html
index 5272dc0..55748c8 100644
--- a/html/Asset/Search/Build.html
+++ b/html/Asset/Search/Build.html
@@ -147,7 +147,7 @@ my $cf_field_names =
# Try to find if we're adding a clause
foreach my $arg ( keys %ARGS ) {
- next unless $arg =~ m/^ValueOf(\w+|($cf_field_names).\{.*?\})$/
+ next unless $arg =~ m/^ValueOf(\w+|($cf_field_names).\{.*?\}|CustomRole.\{.*?\})$/
&& ( ref $ARGS{$arg} eq "ARRAY"
? grep $_ ne '', @{ $ARGS{$arg} }
: $ARGS{$arg} ne '' );
diff --git a/html/Asset/Search/Elements/BuildFormatString b/html/Asset/Search/Elements/BuildFormatString
index 4e65800..a7917a7 100644
--- a/html/Asset/Search/Elements/BuildFormatString
+++ b/html/Asset/Search/Elements/BuildFormatString
@@ -1,3 +1,50 @@
+%# 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 }}}
<%ARGS>
$Format => RT->Config->Get('AssetSearchFormat')
@@ -41,6 +88,10 @@ my @fields = qw(
); # loc_qw
my $CustomFields = RT::CustomFields->new( $session{'CurrentUser'});
+my %ranges = %{ RT->Config->Get('CustomDateRanges')->{'RT::Asset'} || {} };
+push @fields, sort keys %ranges;
+
+my $CustomRoles = RT::CustomRoles->new( $session{'CurrentUser'});
foreach my $id (keys %catalogs) {
# Gotta load up the $catalog object, since catalogs get stored by name now.
my $catalog = RT::Catalog->new($session{'CurrentUser'});
@@ -48,15 +99,16 @@ foreach my $id (keys %catalogs) {
next unless $catalog->Id;
$CustomFields->LimitToCatalog($catalog->Id);
$CustomFields->SetContextObject( $catalog ) if keys %catalogs == 1;
+ $CustomRoles->LimitToObjectId($catalog->Id);
}
$CustomFields->LimitToCatalog(0);
while ( my $CustomField = $CustomFields->Next ) {
push @fields, "CustomField.{" . $CustomField->Name . "}";
}
-
-my %ranges = %{ RT->Config->Get('CustomDateRanges')->{'RT::Asset'} || {} };
-push @fields, sort keys %ranges;
+while ( my $Role = $CustomRoles->Next ) {
+ push @fields, "CustomRole.{" . $Role->Name . "}";
+}
$m->callback( Fields => \@fields, ARGSRef => \%ARGS );
diff --git a/html/Asset/Search/Elements/ConditionRow b/html/Asset/Search/Elements/ConditionRow
new file mode 100644
index 0000000..298f951
--- /dev/null
+++ b/html/Asset/Search/Elements/ConditionRow
@@ -0,0 +1,100 @@
+%# 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 }}}
+<tr>
+<td class="label"><% $handle_block->( $Condition->{'Field'}, $Condition->{'Name'} .'Field' ) |n %></td>
+<td class="operator"><% $handle_block->( $Condition->{'Op'}, $Condition->{'Name'} .'Op') |n %></td>
+<td class="value"><% $handle_block->( $Condition->{'Value'}, 'ValueOf'. $Condition->{'Name'} ) |n %></td>
+</tr>
+<%INIT>
+return unless $Condition && $Condition->{'Name'};
+
+$m->callback( Condition => \$Condition );
+return unless $Condition;
+
+my $handle_block;
+$handle_block = sub {
+ my $box = shift;
+ return $box unless ref $box;
+
+ my $name = shift;
+ if ( UNIVERSAL::isa($box, 'ARRAY') ) {
+ my $res = '';
+ $res .= $handle_block->( $_, $name ) foreach @$box;
+ return $res;
+ }
+
+ return undef unless UNIVERSAL::isa($box, 'HASH');
+ if ( $box->{'Type'} eq 'component' ) {
+ $box->{'Arguments'} ||= {},
+ return $m->scomp( $box->{'Path'}, %{ $box->{'Arguments'} }, Name => $name );
+ }
+ if ( $box->{'Type'} eq 'text' ) {
+ $box->{id} ||= $box->{name} ||= $name;
+ $box->{value} ||= delete($box->{Default}) || '';
+ return "<input ".join(" ", map{$m->interp->apply_escapes(lc($_),'h')
+ .q{="}.$m->interp->apply_escapes($box->{$_},'h').q{"}}
+ sort keys %$box)." />";
+ }
+ if ( $box->{'Type'} eq 'select' ) {
+ my $res = '';
+ $res .= qq{<select id="$name" name="$name">};
+ my @options = @{ $box->{'Options'} };
+ while( my $k = shift @options ) {
+ my $v = shift @options;
+ $res .= qq{<option value="$k">$v</option>};
+ }
+ $res .= qq{</select>};
+ return $res;
+ }
+};
+
+</%INIT>
+<%ARGS>
+$Condition => {}
+</%ARGS>
+
diff --git a/html/Asset/Search/Elements/EditSort b/html/Asset/Search/Elements/EditSort
index ec60707..82e1ceb 100644
--- a/html/Asset/Search/Elements/EditSort
+++ b/html/Asset/Search/Elements/EditSort
@@ -69,6 +69,15 @@ $fields{'Contact'} = 'Contact';
my @cfs = grep /^CustomField/, @{$ARGS{AvailableColumns}};
$fields{$_} = $_ for @cfs;
+# Add all available CustomRoles to the list of sortable columns.
+my @roles = grep /^CustomRole/, @{$ARGS{AvailableColumns}};
+for my $role (@roles) {
+ my ($label) = $role =~ /^CustomRole.{(.*)}$/;
+ my $value = $role;
+ $fields{$label . '.EmailAddress' } = $value . '.EmailAddress';
+}
+
+
# Add PAW sort
$fields{'Custom.Ownership'} = 'Custom.Ownership';
diff --git a/html/Asset/Search/Elements/PickCriteria b/html/Asset/Search/Elements/PickCriteria
index 6a3cc34..6a4d084 100644
--- a/html/Asset/Search/Elements/PickCriteria
+++ b/html/Asset/Search/Elements/PickCriteria
@@ -5,6 +5,7 @@
% $m->callback( %ARGS, CallbackName => "BeforeBasics" );
<& PickBasics, catalogs => \%catalogs &>
+<& PickCustomRoles, catalogs => \%catalogs &>
<& PickAssetCFs, catalogs => \%catalogs &>
% $m->callback( %ARGS, CallbackName => "AfterCFs" );
diff --git a/html/Asset/Search/Elements/PickCustomRoles b/html/Asset/Search/Elements/PickCustomRoles
new file mode 100644
index 0000000..eb57465
--- /dev/null
+++ b/html/Asset/Search/Elements/PickCustomRoles
@@ -0,0 +1,90 @@
+%# BEGIN BPS TAGGED BLOCK {{{
+%#
+%# COPYRIGHT:
+%#
+%# This software is Copyright (c) 1996-2017 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>
+%catalogs => ()
+</%ARGS>
+<%INIT>
+my $CustomRoles = RT::CustomRoles->new( $session{'CurrentUser'});
+foreach my $id (keys %catalogs) {
+ my $catalog = RT::Catalog->new($session{'CurrentUser'});
+ $catalog->Load($id);
+ next unless $catalog->Id;
+ $CustomRoles->LimitToObjectId($catalog->Id);
+}
+$m->callback(
+ CallbackName => 'MassageCustomRoles',
+ CustomRoles => $CustomRoles,
+);
+
+my @lines;
+while ( my $Role = $CustomRoles->Next ) {
+ my $name = "CustomRole.{" . $Role->Name . "}";
+ my %line = (
+ Name => $name,
+ Field => {
+ Type => 'component',
+ Path => 'SelectPersonType',
+ Arguments => { Role => $Role, Default => $name },
+ },
+ Op => {
+ Type => 'component',
+ Path => '/Elements/SelectMatch',
+ },
+ Value => { Type => 'text', Size => 20 },
+ );
+
+ push @lines, \%line;
+}
+
+$m->callback( Conditions => \@lines, Catalogs => \%catalogs );
+
+</%INIT>
+% foreach( @lines ) {
+<& ConditionRow, Condition => $_ &>
+% }
+
diff --git a/html/Asset/Search/Elements/SelectPersonType b/html/Asset/Search/Elements/SelectPersonType
index 0bb34d9..f9ef677 100644
--- a/html/Asset/Search/Elements/SelectPersonType
+++ b/html/Asset/Search/Elements/SelectPersonType
@@ -3,18 +3,37 @@
<option value="">-</option>
% }
% for my $option (@types) {
+% my ($value, $label) = ($option, $option);
+% if (ref($option)) {
+% ($value, $label) = @$option;
+% }
% if ($Suffix) {
-<option value="<% $option %><% $Suffix %>"<%$option eq $Default && qq[ selected="selected"] |n %> ><% loc($option) %> <% loc('Group') %></option>
+<option value="<% $value %><% $Suffix %>"<%$value eq $Default && qq[ selected="selected"] |n %> ><% loc($label) %> <% loc('Group') %></option>
% next;
% }
% foreach my $subtype (@subtypes) {
-<option value="<%"$option.$subtype"%>"<%$option eq $Default && $subtype eq 'EmailAddress' && qq[ selected="selected"] |n %> ><% loc($option) %> <% loc($subtype) %></option>
+<option value="<%"$value.$subtype"%>"<%$value eq $Default && $subtype eq 'EmailAddress' && qq[ selected="selected"] |n %> ><% loc($label) %> <% loc($subtype) %></option>
% }
% }
</select>
<%INIT>
-my @types = qw(Owner HeldBy Contact);
+my @types;
+if ($Role) {
+ @types = (
+ [ "CustomRole.{" . $Role->Name . "}", $Role->Name ],
+ );
+}
+elsif ($Scope =~ /catalog/) {
+ @types = qw(Cc AdminCc);
+}
+elsif ($Suffix eq 'Group') {
+ @types = qw(Owner HeldBy Contact Watcher);
+}
+else {
+ @types = qw( Watcher Owner CatalogWatcher HeldBy contact );
+}
+
my @subtypes = @{ $RT::Assets::SEARCHABLE_SUBFIELDS{'User'} };
$m->callback(Types => \@types, Subtypes => \@subtypes);
@@ -25,4 +44,5 @@ $Suffix => ''
$Default =>undef
$Scope => 'asset'
$Name => 'WatcherType'
+$Role => undef
</%ARGS>
diff --git a/lib/RT/Extension/AssetSQL/Assets.pm b/lib/RT/Extension/AssetSQL/Assets.pm
index bf20558..b85ec4d 100644
--- a/lib/RT/Extension/AssetSQL/Assets.pm
+++ b/lib/RT/Extension/AssetSQL/Assets.pm
@@ -462,6 +462,8 @@ our %FIELD_METADATA = (
Contact => [ 'WATCHERFIELD' => 'Contact', ], #loc_left_pair
ContactGroup => [ 'MEMBERSHIPFIELD' => 'Contact', ], #loc_left_pair
+ CustomRole => [ 'WATCHERFIELD' ], # loc_left_pair
+
CustomFieldValue => [ 'CUSTOMFIELD' => 'Asset' ], #loc_left_pair
CustomField => [ 'CUSTOMFIELD' => 'Asset' ], #loc_left_pair
CF => [ 'CUSTOMFIELD' => 'Asset' ], #loc_left_pair
@@ -972,18 +974,24 @@ sub _WatcherLimit {
my $meta = $FIELD_METADATA{ $field };
my $type = $meta->[1] || '';
my $class = $meta->[2] || 'Asset';
+ my $column = $rest{SUBKEY};
+ if ($field eq 'CustomRole') {
+ my ($role, $col, $original_name) = $self->_CustomRoleDecipher( $column );
+ $column = $col || 'id';
+ $type = $role ? $role->GroupType : $original_name;
+ }
# Bail if the subfield is not allowed
- if ( $rest{SUBKEY}
- and not grep { $_ eq $rest{SUBKEY} } @{$SEARCHABLE_SUBFIELDS{'User'}})
+ if ( $column
+ and not grep { $_ eq $column } @{$SEARCHABLE_SUBFIELDS{'User'}})
{
- die "Invalid watcher subfield: '$rest{SUBKEY}'";
+ die "Invalid watcher subfield: '$column'";
}
$self->RoleLimit(
TYPE => $type,
CLASS => "RT::$class",
- FIELD => $rest{SUBKEY},
+ FIELD => $column,
OPERATOR => $op,
VALUE => $value,
SUBCLAUSE => "assetsql",
@@ -1107,7 +1115,6 @@ sub _CustomFieldDecipher {
$cf = $cfs->First unless $cfs->Count > 1;
}
-
}
else {
$cf = RT::CustomField->new( $self->CurrentUser );
@@ -1119,6 +1126,41 @@ sub _CustomFieldDecipher {
return ($object, $field, $cf, $column);
}
+
+=head2 _CustomRoleDecipher
+
+Try and turn a custom role descriptor (e.g. C<CustomRole.{Engineer}>) into
+(role, column, original name).
+
+=cut
+
+sub _CustomRoleDecipher {
+ my ($self, $string) = @_;
+
+ my ($field, $column) = ($string =~ /^\{(.+)\}(?:\.(\w+))?$/);
+
+ my $role;
+
+ if ( $field =~ /\D/ ) {
+ my $roles = RT::CustomRoles->new( $self->CurrentUser );
+ $roles->Limit( FIELD => 'Name', VALUE => $field, CASESENSITIVE => 0 );
+
+ # custom roles are named uniquely, but just in case there are
+ # multiple matches, bail out as we don't know which one to use
+ $role = $roles->First;
+ if ( $role ) {
+ $role = undef if $roles->Next;
+ }
+ }
+ else {
+ $role = RT::CustomRole->new( $self->CurrentUser );
+ $role->Load( $field );
+ }
+
+ return ($role, $column, $field);
+}
+
+
=head2 _CustomFieldLimit
Limit based on CustomFields
@@ -1586,4 +1628,3 @@ sub _ProcessRestrictions {
}
1;
-
-----------------------------------------------------------------------
More information about the Bps-public-commit
mailing list