[Rt-commit] rt branch, 4.4/core-assets, repushed
Todd Wade
todd at bestpractical.com
Sat Oct 24 02:47:18 EDT 2015
The branch 4.4/core-assets was deleted and repushed:
was dcee68733a9bc5409bff43ecb117b512c77fefad
now 1e8dc8f2b9de3fb07d92c676cd22c895798e589d
1: 791cad5 ! 1: 1e8dc8f core RT::Extension::Assets
@@ -26,11 +26,12 @@
sbin/rt-attributes-viewer
sbin/rt-preferences-viewer
-diff --git a/docs/customizing/assets_introduction.pod b/docs/customizing/assets_introduction.pod
+diff --git a/docs/assets.pod b/docs/assets.pod
new file mode 100644
--- /dev/null
-+++ b/docs/customizing/assets_introduction.pod
-@@
++++ b/docs/assets.pod
+@@
++=encoding utf-8
+
+=head1 CONFIGURATION
+
@@ -67,14 +68,14 @@
+
+=head2 Adding fields
+
-+You can see the current asset CFs by navigating to Admin >
-+Assets > Custom Fields. From there you can use the "Create" link to create a
++You can see the current asset CFs by navigating to Admin →
++Assets → Custom Fields. From there you can use the "Create" link to create a
+new asset CF. If you know you want to create a new CF right away, you can do
-+so via Admin > Assets > Custom Fields > Create.
++so via Admin → Assets → Custom Fields → Create.
+
+When creating a CF, be sure to select "Assets" in the "Applies To" dropdown.
+You'll also need to grant rights to the groups and/or roles which need to see
-+the fields, otherwise they'll be hidden. See the following section.
++the fields, otherwise they'll be hidden. See the following section, Rights.
+
+Similar to ticket CFs, asset custom fields are added globally or to specific
+catalogs. Only assets within those specific catalogs will have the CFs
@@ -90,7 +91,7 @@
+
+=head3 ShowAsset
+
-+Allows viewing an asset record and it's core fields (but not CFs). Without
++Allows viewing an asset record and its core fields (but not CFs). Without
+it, no assets can be seen. Similar to ShowTicket.
+
+=head3 CreateAsset
@@ -188,7 +189,7 @@
+lifecycle is named "assets". You're free to modify it as much as you'd like,
+or add your own lifecycles. Each catalog may have its own lifecycle.
+
-+For the default "assets" configuration, see F<etc/Assets_Config.pm>.
++For the default "assets" configuration, see F<etc/RT_Config.pm>.
+
+=head2 Field organization
+
@@ -243,17 +244,18 @@
+
+=cut
-diff --git a/docs/customizing/assets_tutorial.pod b/docs/customizing/assets_tutorial.pod
+diff --git a/docs/customizing/assets/tutorial.pod b/docs/customizing/assets/tutorial.pod
new file mode 100644
--- /dev/null
-+++ b/docs/customizing/assets_tutorial.pod
-@@
++++ b/docs/customizing/assets/tutorial.pod
+@@
++=encoding utf-8
+
+=head1 Introduction
+
-+This is a basic tutorial for setting up asset tracking in RT using Best
-+Practical's Assets extension. At the end, you'll have a basic configuration
-+that lets you add assets, search for them, link them to tickets, etc.
++This is a basic tutorial for setting up asset tracking in RT using the Assets
++functionality. At the end, you'll have a basic configuration that lets you add
++assets, search for them, link them to tickets, etc.
+
+=begin HTML
+
@@ -265,16 +267,13 @@
+You can follow along with the tutorial and try setting things up yourself to
+get a feel for all of the administrative controls. If you want to get a jump
+start, the files to set up this basic configuration are provided in the
-+L<RT::Extension::Assets> distribution in the F<etc> directory. For
-+configuration, look in F<etc/Tutorial_Configuration.txt>. You can copy all or
-+part of it and paste it into your F<RT_SiteConfig.pm>.
-+
-+To load the test catalog, custom fields, and users, follow the
-+installation instructions in L<RT::Extension::Assets/INSTALLATION>, then
-+run the following from your RT directory:
++F<docs/customizing/assets> directory.
++
++To load the test catalog, custom fields, and users, run the following from
++your RT directory:
+
+ sbin/rt-setup-database --action insert --datafile \
-+ local/plugins/RT-Extension-Assets/etc/tutorialdata
++ docs/customizing/assets/tutorialdata
+
+This will change the default catalog name, create some users, and give those
+users asset permissions. Only asset rights are granted, so you need to grant
@@ -285,32 +284,26 @@
+
+=head1 Getting Started
+
-+Install the extension following the instructions and some new tables will be
-+added to your RT database and the assets code will be installed. As with all
-+extensions, first add C<RT::Extension::Assets> to your C<@Plugins> line.
-+
+There are a few configuration options you might set before starting. Assets
+offers a C<$DefaultCatalog> feature that works similar to RT's
+L<DefaultQueue|http://bestpractical.com/docs/rt/latest/RT_Config.html#DefaultQueue>,
-+but you can probably skip it for now since you don't have any catalogs yet.
++but you can probably skip it for now since you only have the one catalog so far.
+
+More interesting are some optional portlets you can activate to add asset data
+to RT's pages. MyAssets and FindAsset portlets are available for placement on
+RT at a Glance or in dashboards and a UserAssets portlet is available for the
+user summary pages.
+
-+These portlets are fairly self-explanatory and you can add them by finding
-+C<$HomepageComponents> and C<@UserSummaryPortlets> respectively in
-+F<RT_Config.pm>, copying to F<RT_SiteConfig.pm>, and adding the portlets you
-+want. There are also examples in the tutorial sample configuration file. Note
-+that C<$HomepageComponents> makes the portlets available, but doesn't put them
-+on RT at a Glance. To add them, just click the Edit link on the upper right-hand
-+corner of the homepage. C<@UserSummaryPortlets> does automatically add the
-+"Assigned Assets" portlet to the User Summary page. It will appear based on the
-+position in the configuration, so just place it in the list where you want it
-+to appear.
-+
-+Once you have your configuration complete, restart your server and you're ready
++These portlets are fairly self-explanatory and for reference you can find them
++in C<$HomepageComponents> and C<@UserSummaryPortlets> respectively in
++F<RT_Config.pm>. Note that C<$HomepageComponents> makes the portlets available,
++but doesn't put them on RT at a Glance. To add them, just click the Edit link on
++the upper right-hand corner of the homepage. C<@UserSummaryPortlets> does
++automatically add the "Assigned Assets" portlet to the User Summary page. It
++will appear based on the position in the configuration, so to move it rearrange
++the list to where you want it to appear.
++
++If you've made any configuration changes, restart your server and you're ready
+to go.
+
+=head1 Catalogs
@@ -323,7 +316,7 @@
+to look at catalogs and some other configuration. Catalogs are to assets what
+queues are to tickets, so if you've used RT, the relationship should be fairly
+familiar. Similar to the General queue, a "General assets" catalog is provided
-+to get you started. You can see it at Admin > Assets > Catalogs.
++to get you started. You can see it at Admin → Assets → Catalogs.
+
+We're going to use the default, but change it to a name more appropriate for
+our use. Clicking on the asset name brings us to the catalog edit page and we
@@ -337,26 +330,22 @@
+
+=end HTML
+
-+You'll also notice that catalogs have a lifecycle just like queues. The assets
-+extension comes with a default assets lifecycle, but just like queues you can
-+create new ones with custom statuses and other configuration to allow RT to
++You'll also notice that catalogs have a lifecycle just like queues. Request
++tracker is installed with a default assets lifecycle, but just like queues you
++can create new ones with custom statuses and other configuration to allow RT to
+reflect the states of your assets.
+
-+You can find the asset lifecycle in the asset configuration file in your RT
-+installation at:
-+
-+ local/plugins/RT-Extension-Assets/etc/Assets_Config.pm
-+
-+The initial statuses are new, allocated, in-use, recycled, stolen, and deleted.
-+Depending on your process, you might add new ones like surplussed, donated, or
-+in-repair. To create a new asset lifecycle, just copy the default into
-+F<RT_SiteConfig.pm>, replace the top-level "assets" key with a new name, and
-+make your changes.
++You can find the asset lifecycle in the F<RT_Config.pm> file in your RT
++installation. The initial statuses are new, allocated, in-use, recycled,
++stolen, and deleted. Depending on your process, you might add new ones like
++surplussed, donated, or in-repair. To create a new asset lifecycle, just copy
++the default into F<RT_SiteConfig.pm>, replace the top-level "assets" key with
++a new name, and make your changes.
+
+=head1 Asset Custom Fields
+
+Next we need to create some custom fields to hold our asset metadata. You can
-+find asset custom fields at Admin > Assets > Custom Fields and they work just
++find asset custom fields at Admin → Assets → Custom Fields and they work just
+like custom fields for other RT objects.
+
+=begin HTML
@@ -366,8 +355,8 @@
+
+=end HTML
+
-+The extension will automatically provide some core values for your assets. Each
-+asset can have a Name and Description and, like tickets, they have statuses
++Request Tracker will automatically provide some core values for your assets.
++Each asset can have a Name and Description and, like tickets, they have statuses
+based on the lifecycle configuration. You can use Name and Description however
+you want and they are not required. However, many of the asset pages use these
+fields so it's best to provide a descriptive name to make it easy for people
@@ -426,7 +415,7 @@
+
+Any custom fields you create will be displayed on the asset display page in a
+default "Custom Fields" section. That may be sufficient, but assets also
-+supports RT's new custom field grouping feature, so we can group together some
++supports RT's custom field grouping feature, so we can group together some
+similar custom fields and give them a custom name. If we add the following to
+F<RT_SiteConfig.pm>:
+
@@ -458,8 +447,8 @@
+rights individually on each custom field if you wanted to allow users to see
+some but not others.
+
-+Similar to queues, you can set rights at the catalog level. Go to Admin >
-+Assets > Catalogs and click on the catalog you want to edit. Click Group Rights
++Similar to queues, you can set rights at the catalog level. Go to Admin →
++Assets → Catalogs and click on the catalog you want to edit. Click Group Rights
+in the submenu to assign asset rights to groups like the system Privileged
+group.
+
@@ -530,11 +519,11 @@
+
+=head2 End User Asset Tickets
+
-+If an end user contacts us with some problems with their laptop, RT makes it
++If an end user contacts us with some problem with their laptop, RT makes it
+easy to find the correct laptop record and create a ticket for them. Since our
+support staff do this frequently, they have added the Find User portlet to
+their RT at a glance page and can quickly search for the user and go to their
-+User Summary page (new in RT 4.2).
++User Summary page.
+
+We have added the Assigned Assets portlet to the User Summary page, so the
+laptop is right there on the page when we find the user. We can just click on
@@ -569,16 +558,131 @@
+
+=head1 Summary
+
-+This tutorial is only a quick overview showing how the assets extension can
++This tutorial is only a quick overview showing how the assets functionality can
+help you track assets. There are many more features you'll find as you explore
+the assets interface, like stacking multiple assets on a single ticket, bulk
+update features similar to tickets, and the search interface. Have fun!
+
+=cut
+diff --git a/docs/customizing/assets/tutorialdata b/docs/customizing/assets/tutorialdata
+new file mode 100644
+--- /dev/null
++++ b/docs/customizing/assets/tutorialdata
+@@
++ at Users = (
++ { Name => 'asset-tutorial-staff',
++ RealName => 'Asset Staff User',
++ Password => 'password',
++ EmailAddress => "asset-tutorial-staff\@localhost",
++ Comments => "Sample Staff user for Assets tutorial",
++ Privileged => '1',
++ },
++ { Name => 'asset-tutorial-user1',
++ RealName => 'Asset End User',
++ Password => 'password',
++ EmailAddress => "asset-tutorial-user1\@localhost",
++ Comments => "Sample end user for Assets tutorial",
++ },
++);
++
++ at CustomFields = (
++ { Name => 'Serial Number',
++ Type => 'FreeformSingle',
++ LookupType => 'RT::Catalog-RT::Asset',
++ ApplyTo => 'General assets',
++ },
++ { Name => 'Tracking Number',
++ Type => 'FreeformSingle',
++ LookupType => 'RT::Catalog-RT::Asset',
++ ApplyTo => 'General assets',
++ },
++ { Name => 'Manufacturer',
++ Type => 'SelectSingle',
++ LookupType => 'RT::Catalog-RT::Asset',
++ ApplyTo => 'General assets',
++ MaxValues => 1,
++ RenderType => 'Dropdown',
++ Values => [
++ { Name => 'Apple', SortOrder => 1 },
++ { Name => 'Dell', SortOrder => 2 }, ],
++ },
++ { Name => 'Type',
++ Type => 'SelectSingle',
++ LookupType => 'RT::Catalog-RT::Asset',
++ ApplyTo => 'General assets',
++ MaxValues => 1,
++ RenderType => 'Dropdown',
++ Values => [
++ { Name => 'Desktop Computer', SortOrder => 1 },
++ { Name => 'Laptop Computer', SortOrder => 2 },
++ { Name => 'Server', SortOrder => 3 },
++ { Name => 'Mobile Phone', SortOrder => 4 },
++ { Name => 'Software', SortOrder => 5 },
++ { Name => 'Other', SortOrder => 6 }, ],
++ },
++ { Name => 'Issue Date',
++ Type => 'Date',
++ LookupType => 'RT::Catalog-RT::Asset',
++ ApplyTo => 'General assets',
++ },
++ { Name => 'Support Expiration',
++ Type => 'Date',
++ LookupType => 'RT::Catalog-RT::Asset',
++ ApplyTo => 'General assets',
++ },
++);
++
++push @ACL, map {
++ {
++ Right => $_,
++ GroupDomain => 'SystemInternal',
++ GroupType => 'Privileged',
++ ObjectType => 'RT::Catalog',
++ ObjectId => 'General assets',
++ }
++ } qw(ShowAsset ShowCatalog SeeCustomField CreateAsset
++ ModifyAsset ModifyCustomField);
++
++push @ACL, map {
++ {
++ Right => $_,
++ GroupDomain => 'RT::System-Role',
++ GroupType => 'HeldBy',
++ }
++ } qw(ShowAsset ShowCatalog);
++
++push @Final, sub {
++ # Update default catalog name
++ my $catalog = RT::Catalog->new(RT->SystemUser);
++ my ($ret, $msg) = $catalog->Load('General assets');
++ RT::Logger->error("Unable to load General assets catalog: $msg")
++ unless $ret;
++ $catalog->SetName('IT Department Assets');
++ return;
++};
+
diff --git a/etc/RT_Config.pm.in b/etc/RT_Config.pm.in
--- a/etc/RT_Config.pm.in
+++ b/etc/RT_Config.pm.in
+@@
+
+ =cut
+
+-Set(@UserSummaryPortlets, (qw/ExtraInfo CreateTicket ActiveTickets InactiveTickets/));
++Set(@UserSummaryPortlets, (qw/ExtraInfo CreateTicket ActiveTickets InactiveTickets UserAssets /));
+
+ =item C<$UserSummaryExtraInfo>
+
+@@
+ Set(
+ $HomepageComponents,
+ [
+- qw(QuickCreate Quicksearch MyAdminQueues MySupportQueues MyReminders RefreshHomepage Dashboards SavedSearches FindUser) # loc_qw
++ qw(QuickCreate Quicksearch MyAdminQueues MySupportQueues MyReminders RefreshHomepage Dashboards SavedSearches FindUser MyAssets FindAsset) # loc_qw
+ ]
+ );
+
@@
=back
@@ -687,21 +791,6 @@
+ Status,
+]) unless $AssetSummaryRelatedTicketsFormat;
+
-+=item C<%AdminSearchResultFormat>
-+
-+The C<Catalogs> key of this standard RT configuration option (see
-+L<RT_Config/%AdminSearchResultFormat>) controls how catalogs are
-+displayed in their list in the admin pages.
-+
-+=cut
-+
-+Set(%AdminSearchResultFormat,
-+ Catalogs =>
-+ q{'<a href="__WebPath__/Admin/Assets/Catalogs/Modify.html?id=__id__">__id__</a>/TITLE:#'}
-+ .q{,'<a href="__WebPath__/Admin/Assets/Catalogs/Modify.html?id=__id__">__Name__</a>/TITLE:Name'}
-+ .q{,__Description__,__Lifecycle__,__Disabled__},
-+) unless $AdminSearchResultFormat{Catalogs};
-+
+=item C<$AssetBasicCustomFieldsOnCreate>
+
+Specify a list of Asset custom fields to show in "Basics" widget on create.
@@ -731,6 +820,9 @@
'deleted -> open' => { label => 'Undelete', }, # loc{label}
],
},
+-);
+-
+-
+ assets => {
+ type => "asset",
+ initial => [
@@ -745,11 +837,11 @@
+ 'stolen', # loc
+ 'deleted' # loc
+ ],
-+
+
+ defaults => {
+ on_create => 'new',
+ },
-+
+
+ transitions => {
+ '' => [qw(new allocated in-use)],
+ new => [qw(allocated in-use stolen deleted)],
@@ -777,85 +869,66 @@
+ },
+ },
+ },
++);
+
+ =head1 Administrative interface
+
+@@
+ q{ '<a href="__WebPath__/Admin/Articles/Classes/Modify.html?id=__id__">__id__</a>/TITLE:#'}
+ .q{,'<a href="__WebPath__/Admin/Articles/Classes/Modify.html?id=__id__">__Name__</a>/TITLE:Name'}
+ .q{,__Description__,__Disabled__},
++
++ Catalogs =>
++ q{'<a href="__WebPath__/Admin/Assets/Catalogs/Modify.html?id=__id__">__id__</a>/TITLE:#'}
++ .q{,'<a href="__WebPath__/Admin/Assets/Catalogs/Modify.html?id=__id__">__Name__</a>/TITLE:Name'}
++ .q{,__Description__,__Lifecycle__,__Disabled__},
);
+ =item C<%AdminSearchResultRows>
+@@
+ Scrips => 50,
+ Templates => 50,
+ Classes => 50,
++ Catalogs => 50,
++ Assets => 50,
+ );
+ =back
diff --git a/etc/acl.Pg b/etc/acl.Pg
--- a/etc/acl.Pg
+++ b/etc/acl.Pg
@@
- }
- }
- return (@acls);
-+
-+{ # START assets ACL
-+ my @tables = qw (
+ ObjectTopics
+ objectclasses_id_seq
+ ObjectClasses
++ catalogs_id_seq
++ Catalogs
+ assets_id_seq
+ Assets
-+ catalogs_id_seq
-+ Catalogs
-+ );
-+
-+ my $db_user = RT->Config->Get('DatabaseUser');
-+
-+ my $sequence_right
-+ = ( $dbh->{pg_server_version} >= 80200 )
-+ ? "USAGE, SELECT, UPDATE"
-+ : "SELECT, UPDATE";
-+
-+ foreach my $table (@tables) {
-+ # Tables are upper-case, sequences are lowercase in @tables
-+ if ( $table =~ /^[a-z]/ ) {
-+ push @acls, "GRANT $sequence_right ON $table TO \"$db_user\";"
-+ }
-+ else {
-+ push @acls, "GRANT SELECT, INSERT, UPDATE, DELETE ON $table TO \"$db_user\";"
-+ }
-+ }
-+
-+} # END Assets ACL
-+
-+ return (@acls);
- }
+ );
- 1;
+ my $db_user = RT->Config->Get('DatabaseUser');
diff --git a/etc/initialdata b/etc/initialdata
--- a/etc/initialdata
+++ b/etc/initialdata
@@
+ Description => 'A system-internal queue for the approvals system',
+ Disabled => 2, } );
+
++ at Catalogs = ({
++ Name => "General assets", # loc
++ Description => "The default catalog", # loc
++});
++
+ @ScripActions = (
+
+ { Name => 'Autoreply To Requestors', # loc
+@@
},
},
);
-+
-+require RT::Asset;
-+# Create global role groups
-+push @Final, sub {
-+ foreach my $type (RT::Asset->Roles) {
-+ next if $type eq "Owner"; # There's a core global role group for Owner
-+
-+ my $group = RT::Group->new( RT->SystemUser );
-+ my ($ok, $msg) = $group->CreateRoleGroup(
-+ Object => RT->System,
-+ Name => $type,
-+ InsideTransaction => 0,
-+ );
-+ RT->Logger->error("Couldn't create global asset role group '$type': $msg")
-+ unless $ok;
-+ }
-+};
-+
-+# Create default catalog
-+push @Final, sub {
-+ my $catalog = RT::Catalog->new( RT->SystemUser );
-+ my ($ok, $msg) = $catalog->Create(
-+ Name => "General assets",
-+ Description => "The default catalog",
-+ );
-+ RT->Logger->error("Couldn't create default catalog 'General assets': $msg")
-+ unless $ok;
-+};
+
+1;
@@ -1019,20 +1092,76 @@
+CREATE INDEX CatalogsName ON Catalogs (Name);
+CREATE INDEX CatalogsDisabled ON Catalogs (Disabled);
+diff --git a/etc/upgrade/4.3.10/acl.Pg b/etc/upgrade/4.3.10/acl.Pg
+new file mode 100644
+--- /dev/null
++++ b/etc/upgrade/4.3.10/acl.Pg
+@@
++
++sub acl {
++ my $dbh = shift;
++
++ my @acls;
++
++ my @tables = qw (
++ catalogs_id_seq
++ Catalogs
++ assets_id_seq
++ Assets
++ );
++
++ my $db_user = RT->Config->Get('DatabaseUser');
++
++ my $sequence_right
++ = ( $dbh->{pg_server_version} >= 80200 )
++ ? "USAGE, SELECT, UPDATE"
++ : "SELECT, UPDATE";
++
++ foreach my $table (@tables) {
++ # Tables are upper-case, sequences are lowercase
++ if ( $table =~ /^[a-z]/ ) {
++ push @acls, "GRANT $sequence_right ON $table TO \"$db_user\";"
++ }
++ else {
++ push @acls, "GRANT SELECT, INSERT, UPDATE, DELETE ON $table TO \"$db_user\";"
++ }
++ }
++ return (@acls);
++}
++
++1;
+
diff --git a/etc/upgrade/4.3.10/content b/etc/upgrade/4.3.10/content
new file mode 100644
--- /dev/null
+++ b/etc/upgrade/4.3.10/content
@@
++use strict;
++use warnings;
+
+require RT::Asset;
++
++our @Catalogs;
++
++ at Catalogs = ({
++ Name => "General assets", # loc
++ Description => "The default catalog", # loc
++});
++
++our @Final;
+
+# Create global role groups
+push @Final, sub {
+ foreach my $type (RT::Asset->Roles) {
+ next if $type eq "Owner"; # There's a core global role group for Owner
+
-+ my $group = RT::Group->new( RT->SystemUser );
++ my $group = RT->System->RoleGroup( $type );
++ if ( $group->id ) {
++ RT->Logger->debug("Assets role '$type' already exists.");
++ next;
++ }
++
++ $group = RT::Group->new( RT->SystemUser );
+ my ($ok, $msg) = $group->CreateRoleGroup(
+ Object => RT->System,
+ Name => $type,
@@ -1041,17 +1170,6 @@
+ RT->Logger->error("Couldn't create global asset role group '$type': $msg")
+ unless $ok;
+ }
-+};
-+
-+# Create default catalog
-+push @Final, sub {
-+ my $catalog = RT::Catalog->new( RT->SystemUser );
-+ my ($ok, $msg) = $catalog->Create(
-+ Name => "General assets",
-+ Description => "The default catalog",
-+ );
-+ RT->Logger->error("Couldn't create default catalog 'General assets': $msg")
-+ unless $ok;
+};
+
+1;
@@ -1280,9 +1398,9 @@
+
+my $dbh = $RT::Handle->dbh;
+
-+my $found_assets_tables;
++my $found_assets_tables = {};
+foreach my $name ( $RT::Handle->_TableNames ) {
-+ next unless $name =~ /^RTx_/i;
++ next unless grep $name eq $_, qw(RTxAssets RTxCatalogs);
+ $found_assets_tables->{lc $name}++;
+}
+
@@ -1343,7 +1461,7 @@
+#
+# COPYRIGHT:
+#
-+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
++# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
+# <sales at bestpractical.com>
+#
+# (Except where explicitly superseded by other copyright notices)
@@ -1996,7 +2114,7 @@
+#
+# COPYRIGHT:
+#
-+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
++# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
+# <sales at bestpractical.com>
+#
+# (Except where explicitly superseded by other copyright notices)
@@ -2148,17 +2266,6 @@
+ $self->SUPER::AddRecord($asset, @_);
+}
+
-+=head2 NewItem
-+
-+Returns a new empty RT::Asset item
-+
-+=cut
-+
-+sub NewItem {
-+ my $self = shift;
-+ return RT::Asset->new( $self->CurrentUser );
-+}
-+
+=head1 PRIVATE METHODS
+
+=head2 _Init
@@ -2313,7 +2420,7 @@
+#
+# COPYRIGHT:
+#
-+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
++# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
+# <sales at bestpractical.com>
+#
+# (Except where explicitly superseded by other copyright notices)
@@ -2822,7 +2929,7 @@
+#
+# COPYRIGHT:
+#
-+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
++# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
+# <sales at bestpractical.com>
+#
+# (Except where explicitly superseded by other copyright notices)
@@ -2915,17 +3022,6 @@
+ $self->SUPER::AddRecord($catalog, @_);
+}
+
-+=head2 NewItem
-+
-+Returns a new empty RT::Catalog item
-+
-+=cut
-+
-+sub NewItem {
-+ my $self = shift;
-+ return RT::Catalog->new( $self->CurrentUser );
-+}
-+
+=head1 PRIVATE METHODS
+
+=head2 _Init
@@ -3087,6 +3183,93 @@
1;
+diff --git a/lib/RT/Handle.pm b/lib/RT/Handle.pm
+--- a/lib/RT/Handle.pm
++++ b/lib/RT/Handle.pm
+@@
+ return ($val, $msg) unless $val;
+ }
+
++ # assets role groups
++ foreach my $name (RT::Asset->Roles) {
++ next if $name eq "Owner";
++
++ my $group = RT->System->RoleGroup( $name );
++ if ( $group->id ) {
++ push @warns, "Assets role '$name' already exists.";
++ next;
++ }
++
++ $group = RT::Group->new( RT->SystemUser );
++ my ($val, $msg) = $group->CreateRoleGroup(
++ Object => RT->System,
++ Name => $name,
++ InsideTransaction => 0,
++ );
++ return ($val, $msg) unless $val;
++ }
++
+ push @warns, "You appear to have a functional RT database."
+ if @warns;
+
+@@
+
+ # Slurp in stuff to insert from the datafile. Possible things to go in here:-
+ our (@Groups, @Users, @Members, @ACL, @Queues, @ScripActions, @ScripConditions,
+- @Templates, @CustomFields, @Scrips, @Attributes, @Initial, @Final);
++ @Templates, @CustomFields, @Scrips, @Attributes, @Initial, @Final,
++ @Catalogs, @Assets);
+ local (@Groups, @Users, @Members, @ACL, @Queues, @ScripActions, @ScripConditions,
+- @Templates, @CustomFields, @Scrips, @Attributes, @Initial, @Final);
+-
++ @Templates, @CustomFields, @Scrips, @Attributes, @Initial, @Final,
++ @Catalogs, @Assets);
+ local $@;
+ $RT::Logger->debug("Going to load '$datafile' data file");
+ eval { require $datafile }
+@@
+ }
+ $RT::Logger->debug("done.");
+ }
++
++ if ( @Catalogs ) {
++ $RT::Logger->debug("Creating Catalogs...");
++
++ for my $item (@Catalogs) {
++ my $new_entry = RT::Catalog->new(RT->SystemUser);
++ my ( $return, $msg ) = $new_entry->Create(%$item);
++ unless ( $return ) {
++ $RT::Logger->error( $msg );
++ }
++ else {
++ $RT::Logger->debug( $return ."." );
++ }
++ }
++
++ $RT::Logger->debug("done.");
++ }
++ if ( @Assets ) {
++ $RT::Logger->debug("Creating Assets...");
++
++ for my $item (@Catalogs) {
++ my $new_entry = RT::Asset->new(RT->SystemUser);
++ my ( $return, $msg ) = $new_entry->Create(%$item);
++ unless ( $return ) {
++ $RT::Logger->error( $msg );
++ }
++ else {
++ $RT::Logger->debug( $return ."." );
++ }
++ }
++
++ $RT::Logger->debug("done.");
++ }
++
++
+ if ( @CustomFields ) {
+ $RT::Logger->debug("Creating custom fields...");
+ for my $item ( @CustomFields ) {
+
diff --git a/lib/RT/Interface/Web.pm b/lib/RT/Interface/Web.pm
--- a/lib/RT/Interface/Web.pm
+++ b/lib/RT/Interface/Web.pm
@@ -3134,7 +3317,7 @@
+ return $asset;
+}
+
-+sub ProcessRoleMembers {
++sub ProcessAssetRoleMembers {
+ my $object = shift;
+ my %ARGS = (@_);
+ my @results;
@@ -3359,7 +3542,7 @@
+#
+# COPYRIGHT:
+#
-+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
++# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
+# <sales at bestpractical.com>
+#
+# (Except where explicitly superseded by other copyright notices)
@@ -3453,122 +3636,11 @@
--- /dev/null
+++ b/lib/RT/Test/Assets.pm
@@
-+use strict;
-+use warnings;
-+
-+package RT::Test::Assets;
-+use base 'RT::Test';
-+
-+our @EXPORT = qw(create_catalog create_asset create_assets create_cf apply_cfs);
-+
-+sub import {
-+ my $class = shift;
-+ my %args = @_;
-+
-+ $class->SUPER::import( %args );
-+ __PACKAGE__->export_to_level(1);
-+}
-+
-+sub diag {
-+ Test::More::diag(@_) if $ENV{TEST_VERBOSE};
-+}
-+
-+sub create_catalog {
-+ my %info = @_;
-+ my $catalog = RT::Catalog->new( RT->SystemUser );
-+ my ($id, $msg) = $catalog->Create( %info );
-+ if ($id) {
-+ diag("Created catalog #$id: " . $catalog->Name);
-+ return $catalog;
-+ } else {
-+ my $spec = join "/", map { "$_=$info{$_}" } keys %info;
-+ RT->Logger->error("Failed to create catalog ($spec): $msg");
-+ return;
-+ }
-+}
-+
-+sub create_asset {
-+ my %info = @_;
-+ my $asset = RT::Asset->new( RT->SystemUser );
-+ my ($id, $msg) = $asset->Create( %info );
-+ if ($id) {
-+ diag("Created asset #$id: " . $asset->Name);
-+ return $asset;
-+ } else {
-+ my $spec = join "/", map { "$_=$info{$_}" } keys %info;
-+ RT->Logger->error("Failed to create asset ($spec): $msg");
-+ return;
-+ }
-+}
-+
-+sub create_assets {
-+ my $error = 0;
-+ for my $info (@_) {
-+ create_asset(%$info)
-+ or $error++;
-+ }
-+ return not $error;
-+}
-+
-+sub create_cf {
-+ my %args = (
-+ Name => "Test Asset CF ".($$ + rand(1024)),
-+ Type => "FreeformSingle",
-+ LookupType => RT::Asset->CustomFieldLookupType,
-+ @_,
-+ );
-+ my $cf = RT::CustomField->new( RT->SystemUser );
-+ my ($ok, $msg) = $cf->Create(%args);
-+ RT->Logger->error("Can't create CF: $msg") unless $ok;
-+ return $cf;
-+}
-+
-+sub apply_cfs {
-+ my $success = 1;
-+ for my $cf (@_) {
-+ my ($ok, $msg) = $cf->AddToObject( RT::Catalog->new(RT->SystemUser) );
-+ if (not $ok) {
-+ RT->Logger->error("Couldn't apply CF: $msg");
-+ $success = 0;
-+ }
-+ }
-+ return $success;
-+}
-+
-+1;
-
-diff --git a/lib/RT/Transaction.pm b/lib/RT/Transaction.pm
---- a/lib/RT/Transaction.pm
-+++ b/lib/RT/Transaction.pm
-@@
- "#reminder-", $ticket->id, \'">', $ticket->Subject, \'</a>'
- ];
- return ("Reminder '[_1]' completed", $subject); #loc()
-- }
-+ },
-+ 'RT::Asset-Set-Catalog' => sub {
-+ my $self = shift;
-+ return ("[_1] changed from [_2] to [_3]", #loc
-+ $self->loc($self->Field), map {
-+ my $c = RT::Catalog->new($self->CurrentUser);
-+ $c->Load($_);
-+ $c->Name || $self->loc("~[a hidden catalog~]")
-+ } $self->OldValue, $self->NewValue);
-+ },
- );
-
-
-
-diff --git a/lib/RT/URI/asset.pm b/lib/RT/URI/asset.pm
-new file mode 100644
---- /dev/null
-+++ b/lib/RT/URI/asset.pm
-@@
+# BEGIN BPS TAGGED BLOCK {{{
+#
+# COPYRIGHT:
+#
-+# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
++# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
+# <sales at bestpractical.com>
+#
+# (Except where explicitly superseded by other copyright notices)
@@ -3615,6 +3687,165 @@
+use strict;
+use warnings;
+
++package RT::Test::Assets;
++use base 'RT::Test';
++
++our @EXPORT = qw(create_catalog create_asset create_assets create_cf apply_cfs);
++
++sub import {
++ my $class = shift;
++ my %args = @_;
++
++ $class->SUPER::import( %args );
++ __PACKAGE__->export_to_level(1);
++}
++
++sub diag {
++ Test::More::diag(@_) if $ENV{TEST_VERBOSE};
++}
++
++sub create_catalog {
++ my %info = @_;
++ my $catalog = RT::Catalog->new( RT->SystemUser );
++ my ($id, $msg) = $catalog->Create( %info );
++ if ($id) {
++ diag("Created catalog #$id: " . $catalog->Name);
++ return $catalog;
++ } else {
++ my $spec = join "/", map { "$_=$info{$_}" } keys %info;
++ RT->Logger->error("Failed to create catalog ($spec): $msg");
++ return;
++ }
++}
++
++sub create_asset {
++ my %info = @_;
++ my $asset = RT::Asset->new( RT->SystemUser );
++ my ($id, $msg) = $asset->Create( %info );
++ if ($id) {
++ diag("Created asset #$id: " . $asset->Name);
++ return $asset;
++ } else {
++ my $spec = join "/", map { "$_=$info{$_}" } keys %info;
++ RT->Logger->error("Failed to create asset ($spec): $msg");
++ return;
++ }
++}
++
++sub create_assets {
++ my $error = 0;
++ for my $info (@_) {
++ create_asset(%$info)
++ or $error++;
++ }
++ return not $error;
++}
++
++sub create_cf {
++ my %args = (
++ Name => "Test Asset CF ".($$ + rand(1024)),
++ Type => "FreeformSingle",
++ LookupType => RT::Asset->CustomFieldLookupType,
++ @_,
++ );
++ my $cf = RT::CustomField->new( RT->SystemUser );
++ my ($ok, $msg) = $cf->Create(%args);
++ RT->Logger->error("Can't create CF: $msg") unless $ok;
++ return $cf;
++}
++
++sub apply_cfs {
++ my $success = 1;
++ for my $cf (@_) {
++ my ($ok, $msg) = $cf->AddToObject( RT::Catalog->new(RT->SystemUser) );
++ if (not $ok) {
++ RT->Logger->error("Couldn't apply CF: $msg");
++ $success = 0;
++ }
++ }
++ return $success;
++}
++
++1;
+
+diff --git a/lib/RT/Transaction.pm b/lib/RT/Transaction.pm
+--- a/lib/RT/Transaction.pm
++++ b/lib/RT/Transaction.pm
+@@
+ "#reminder-", $ticket->id, \'">', $ticket->Subject, \'</a>'
+ ];
+ return ("Reminder '[_1]' completed", $subject); #loc()
+- }
++ },
++ 'RT::Asset-Set-Catalog' => sub {
++ my $self = shift;
++ return ("[_1] changed from [_2] to [_3]", #loc
++ $self->loc($self->Field), map {
++ my $c = RT::Catalog->new($self->CurrentUser);
++ $c->Load($_);
++ $c->Name || $self->loc("~[a hidden catalog~]")
++ } $self->OldValue, $self->NewValue);
++ },
+ );
+
+
+
+diff --git a/lib/RT/URI/asset.pm b/lib/RT/URI/asset.pm
+new file mode 100644
+--- /dev/null
++++ b/lib/RT/URI/asset.pm
+@@
++# 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 }}}
++
++use strict;
++use warnings;
++
+package RT::URI::asset;
+use base qw/RT::URI::base/;
+
@@ -3786,7 +4017,7 @@
+%#
+%# COPYRIGHT:
+%#
-+%# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
++%# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
+%# <sales at bestpractical.com>
+%#
+%# (Except where explicitly superseded by other copyright notices)
@@ -3879,7 +4110,7 @@
+%#
+%# COPYRIGHT:
+%#
-+%# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
++%# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
+%# <sales at bestpractical.com>
+%#
+%# (Except where explicitly superseded by other copyright notices)
@@ -3946,7 +4177,7 @@
+%#
+%# COPYRIGHT:
+%#
-+%# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
++%# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
+%# <sales at bestpractical.com>
+%#
+%# (Except where explicitly superseded by other copyright notices)
@@ -4034,7 +4265,7 @@
+%#
+%# COPYRIGHT:
+%#
-+%# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
++%# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
+%# <sales at bestpractical.com>
+%#
+%# (Except where explicitly superseded by other copyright notices)
@@ -4104,7 +4335,7 @@
+%#
+%# COPYRIGHT:
+%#
-+%# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
++%# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
+%# <sales at bestpractical.com>
+%#
+%# (Except where explicitly superseded by other copyright notices)
@@ -4198,7 +4429,7 @@
+%#
+%# COPYRIGHT:
+%#
-+%# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
++%# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
+%# <sales at bestpractical.com>
+%#
+%# (Except where explicitly superseded by other copyright notices)
@@ -4251,8 +4482,8 @@
+ <&| /Widgets/TitleBox, title => loc("Roles"), class => "catalog-roles" &>
+ <table width="60%" class="edit">
+ <tr>
-+ <td><& /Elements/Assets/EditPeople, %ARGS, Object => $catalog &></td>
-+ <td><& /Elements/Assets/AddPeople, Object => $catalog &></td>
++ <td><& /Asset/Elements/EditCatalogPeople, %ARGS, Object => $catalog &></td>
++ <td><& /Asset/Elements/AddCatalogPeople, Object => $catalog &></td>
+ </tr>
+ </table>
+ </&>
@@ -4268,7 +4499,7 @@
+my @results;
+
+if ($Update) {
-+ push @results, ProcessRoleMembers( $catalog => %ARGS );
++ push @results, ProcessAssetRoleMembers( $catalog => %ARGS );
+
+ MaybeRedirectForResults(
+ Actions => \@results,
@@ -4286,7 +4517,7 @@
+%#
+%# COPYRIGHT:
+%#
-+%# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
++%# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
+%# <sales at bestpractical.com>
+%#
+%# (Except where explicitly superseded by other copyright notices)
@@ -4356,7 +4587,7 @@
+%#
+%# COPYRIGHT:
+%#
-+%# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
++%# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
+%# <sales at bestpractical.com>
+%#
+%# (Except where explicitly superseded by other copyright notices)
@@ -4410,6 +4641,7 @@
+<& /Elements/CollectionList,
+ OrderBy => 'Name',
+ Order => 'ASC',
++ Rows => $Rows,
+ %ARGS,
+ Format => $Format,
+ Collection => $catalogs,
@@ -4463,6 +4695,7 @@
+}
+
+my $Format = RT->Config->Get('AdminSearchResultFormat')->{'Catalogs'};
++my $Rows = RT->Config->Get('AdminSearchResultRows')->{'Catalogs'} || 50;
+</%INIT>
+<%ARGS>
+$FindDisabled => 0
@@ -4480,7 +4713,7 @@
+%#
+%# COPYRIGHT:
+%#
-+%# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
++%# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
+%# <sales at bestpractical.com>
+%#
+%# (Except where explicitly superseded by other copyright notices)
@@ -4536,7 +4769,7 @@
+%#
+%# COPYRIGHT:
+%#
-+%# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
++%# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
+%# <sales at bestpractical.com>
+%#
+%# (Except where explicitly superseded by other copyright notices)
@@ -4596,7 +4829,7 @@
+%#
+%# COPYRIGHT:
+%#
-+%# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
++%# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
+%# <sales at bestpractical.com>
+%#
+%# (Except where explicitly superseded by other copyright notices)
@@ -4787,7 +5020,7 @@
+%#
+%# COPYRIGHT:
+%#
-+%# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
++%# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
+%# <sales at bestpractical.com>
+%#
+%# (Except where explicitly superseded by other copyright notices)
@@ -4844,7 +5077,7 @@
+%#
+%# COPYRIGHT:
+%#
-+%# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
++%# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
+%# <sales at bestpractical.com>
+%#
+%# (Except where explicitly superseded by other copyright notices)
@@ -4908,7 +5141,7 @@
+%#
+%# COPYRIGHT:
+%#
-+%# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
++%# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
+%# <sales at bestpractical.com>
+%#
+%# (Except where explicitly superseded by other copyright notices)
@@ -4980,6 +5213,79 @@
+$m->callback(CallbackName => 'BeforeDisplay', ARGSRef => \%ARGS, Asset => $asset);
+</%init>
+diff --git a/share/html/Asset/Elements/AddCatalogPeople b/share/html/Asset/Elements/AddCatalogPeople
+new file mode 100644
+--- /dev/null
++++ b/share/html/Asset/Elements/AddCatalogPeople
+@@
++%# 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
++</%args>
++<div class="add-user">
++<h3><&|/l&>Add a person</&></h3>
++<& SelectRoleType, Object => $Object, Name => "AddUserRoleMember-Role" &>
++<input type="text" name="AddUserRoleMember"
++ data-autocomplete="Users"
++ data-autocomplete-return="Name"
++ placeholder="<% loc("Find a user...") %>">
++</div>
++
++<div class="add-group">
++<h3><&|/l&>Add a group</&></h3>
++<& SelectRoleType, Object => $Object, Name => "AddGroupRoleMember-Role" &>
++<input type="text" name="AddGroupRoleMember"
++ data-autocomplete="Groups"
++ data-autocomplete-return="Name"
++ placeholder="<% loc("Find a group...") %>">
++</div>
+
diff --git a/share/html/Asset/Elements/AssetSearchBasics b/share/html/Asset/Elements/AssetSearchBasics
new file mode 100644
--- /dev/null
@@ -4989,7 +5295,7 @@
+%#
+%# COPYRIGHT:
+%#
-+%# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
++%# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
+%# <sales at bestpractical.com>
+%#
+%# (Except where explicitly superseded by other copyright notices)
@@ -5082,7 +5388,7 @@
+%#
+%# COPYRIGHT:
+%#
-+%# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
++%# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
+%# <sales at bestpractical.com>
+%#
+%# (Except where explicitly superseded by other copyright notices)
@@ -5160,7 +5466,7 @@
+%#
+%# COPYRIGHT:
+%#
-+%# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
++%# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
+%# <sales at bestpractical.com>
+%#
+%# (Except where explicitly superseded by other copyright notices)
@@ -5249,7 +5555,7 @@
+%#
+%# COPYRIGHT:
+%#
-+%# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
++%# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
+%# <sales at bestpractical.com>
+%#
+%# (Except where explicitly superseded by other copyright notices)
@@ -5308,7 +5614,7 @@
+%#
+%# COPYRIGHT:
+%#
-+%# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
++%# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
+%# <sales at bestpractical.com>
+%#
+%# (Except where explicitly superseded by other copyright notices)
@@ -5392,7 +5698,7 @@
+%#
+%# COPYRIGHT:
+%#
-+%# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
++%# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
+%# <sales at bestpractical.com>
+%#
+%# (Except where explicitly superseded by other copyright notices)
@@ -5474,6 +5780,71 @@
+ $AssetObj->WritableAttributes;
+</%init>
+diff --git a/share/html/Asset/Elements/EditCatalogPeople b/share/html/Asset/Elements/EditCatalogPeople
+new file mode 100644
+--- /dev/null
++++ b/share/html/Asset/Elements/EditCatalogPeople
+@@
++%# 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
++</%args>
++<%init>
++</%init>
++% for my $role ($Object->Roles( ACLOnly => 0 )) {
++<div class="role-<% CSSClass($role) %> role">
++ <h3><% loc($role) %></h3>
++ <& EditRoleMembers, Group => $Object->RoleGroup($role) &>
++</div>
++% }
++<em><&|/l&>(Check box to delete)</&></em>
+
diff --git a/share/html/Asset/Elements/EditDates b/share/html/Asset/Elements/EditDates
new file mode 100644
--- /dev/null
@@ -5483,7 +5854,7 @@
+%#
+%# COPYRIGHT:
+%#
-+%# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
++%# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
+%# <sales at bestpractical.com>
+%#
+%# (Except where explicitly superseded by other copyright notices)
@@ -5561,7 +5932,7 @@
+%#
+%# COPYRIGHT:
+%#
-+%# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
++%# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
+%# <sales at bestpractical.com>
+%#
+%# (Except where explicitly superseded by other copyright notices)
@@ -5622,6 +5993,150 @@
+$AssetObj
+</%args>
+diff --git a/share/html/Asset/Elements/EditRoleMembers b/share/html/Asset/Elements/EditRoleMembers
+new file mode 100644
+--- /dev/null
++++ b/share/html/Asset/Elements/EditRoleMembers
+@@
++%# 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>
++$Group => undef
++$Recursively => 0
++</%args>
++<%init>
++my $field_name = "RemoveRoleMember-" . $Group->Name;
++</%init>
++<ul class="role-members">
++% my $Users = $Group->UserMembersObj( Recursively => $Recursively );
++% if ($Group->SingleMemberRoleGroup) {
++<input type="text" value="<% $Users->First->Name %>" name="SetRoleMember-<% $Group->Name %>" id="SetRoleMember-<% $Group->Name %>" data-autocomplete="Users" data-autocomplete-return="Name" /><br />
++% } else {
++% while ( my $user = $Users->Next ) {
++<li>
++ <label>
++ <input type="checkbox" name="<% $field_name %>" value="<% $user->PrincipalId %>">
++ <& /Elements/ShowUser, User => $user &>
++ </label>
++</li>
++% }
++% my $Groups = $Group->GroupMembersObj( Recursively => $Recursively );
++% $Groups->LimitToUserDefinedGroups;
++% while (my $group = $Groups->Next) {
++<li>
++ <label>
++ <input type="checkbox" name="<% $field_name %>" value="<% $group->PrincipalId %>">
++ <&|/l&>Group</&>: <% $group->Name %>
++ </label>
++</li>
++% }
++% }
++</ul>
+
+diff --git a/share/html/Asset/Elements/Search b/share/html/Asset/Elements/Search
+new file mode 100644
+--- /dev/null
++++ b/share/html/Asset/Elements/Search
+@@
++%# 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 }}}
++<form ACTION="<% RT->Config->Get('WebPath') %>/Asset/Search/">
++ <input size="12" name="q" accesskey="0" class="field" value="<% $value %>" placeholder="<&|/l&>Search Assets</&>..." />
++</form>
++<%init>
++my $value = defined $DECODED_ARGS->{q} ? $DECODED_ARGS->{q} : '';
++</%init>
+
diff --git a/share/html/Asset/Elements/SelectCatalog b/share/html/Asset/Elements/SelectCatalog
new file mode 100644
--- /dev/null
@@ -5631,7 +6146,7 @@
+%#
+%# COPYRIGHT:
+%#
-+%# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
++%# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
+%# <sales at bestpractical.com>
+%#
+%# (Except where explicitly superseded by other copyright notices)
@@ -5697,6 +6212,72 @@
+}
+</%init>
+diff --git a/share/html/Asset/Elements/SelectRoleType b/share/html/Asset/Elements/SelectRoleType
+new file mode 100644
+--- /dev/null
++++ b/share/html/Asset/Elements/SelectRoleType
+@@
++%# 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
++$Name
++$AllowNull => 0
++</%args>
++<select name="<% $Name %>">
++% if ($AllowNull) {
++ <option value=""></option>
++% }
++% for my $role ($Object->Roles( ACLOnly => 0, Single => 0 )) {
++ <option value="<% $role %>"><% loc($role) %></option>
++% }
++</select>
+
diff --git a/share/html/Asset/Elements/SelectStatus b/share/html/Asset/Elements/SelectStatus
new file mode 100644
--- /dev/null
@@ -5706,7 +6287,7 @@
+%#
+%# COPYRIGHT:
+%#
-+%# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
++%# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
+%# <sales at bestpractical.com>
+%#
+%# (Except where explicitly superseded by other copyright notices)
@@ -5778,7 +6359,7 @@
+%#
+%# COPYRIGHT:
+%#
-+%# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
++%# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
+%# <sales at bestpractical.com>
+%#
+%# (Except where explicitly superseded by other copyright notices)
@@ -5854,7 +6435,7 @@
+%#
+%# COPYRIGHT:
+%#
-+%# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
++%# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
+%# <sales at bestpractical.com>
+%#
+%# (Except where explicitly superseded by other copyright notices)
@@ -5929,7 +6510,7 @@
+%#
+%# COPYRIGHT:
+%#
-+%# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
++%# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
+%# <sales at bestpractical.com>
+%#
+%# (Except where explicitly superseded by other copyright notices)
@@ -6007,7 +6588,7 @@
+%#
+%# COPYRIGHT:
+%#
-+%# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
++%# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
+%# <sales at bestpractical.com>
+%#
+%# (Except where explicitly superseded by other copyright notices)
@@ -6061,7 +6642,7 @@
+%#
+%# COPYRIGHT:
+%#
-+%# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
++%# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
+%# <sales at bestpractical.com>
+%#
+%# (Except where explicitly superseded by other copyright notices)
@@ -6143,7 +6724,7 @@
+%#
+%# COPYRIGHT:
+%#
-+%# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
++%# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
+%# <sales at bestpractical.com>
+%#
+%# (Except where explicitly superseded by other copyright notices)
@@ -6239,7 +6820,7 @@
+%#
+%# COPYRIGHT:
+%#
-+%# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
++%# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
+%# <sales at bestpractical.com>
+%#
+%# (Except where explicitly superseded by other copyright notices)
@@ -6328,7 +6909,7 @@
+%#
+%# COPYRIGHT:
+%#
-+%# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
++%# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
+%# <sales at bestpractical.com>
+%#
+%# (Except where explicitly superseded by other copyright notices)
@@ -6460,7 +7041,7 @@
+%#
+%# COPYRIGHT:
+%#
-+%# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
++%# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
+%# <sales at bestpractical.com>
+%#
+%# (Except where explicitly superseded by other copyright notices)
@@ -6515,7 +7096,7 @@
+%#
+%# COPYRIGHT:
+%#
-+%# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
++%# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
+%# <sales at bestpractical.com>
+%#
+%# (Except where explicitly superseded by other copyright notices)
@@ -6577,7 +7158,7 @@
+%#
+%# COPYRIGHT:
+%#
-+%# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
++%# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
+%# <sales at bestpractical.com>
+%#
+%# (Except where explicitly superseded by other copyright notices)
@@ -6647,7 +7228,7 @@
+%#
+%# COPYRIGHT:
+%#
-+%# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
++%# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
+%# <sales at bestpractical.com>
+%#
+%# (Except where explicitly superseded by other copyright notices)
@@ -6778,7 +7359,7 @@
+</%init>
diff --git a/share/html/Asset/ModifyCFs.html b/share/html/Asset/ModifyCFs.html
-new file mode 100755
+new file mode 100644
--- /dev/null
+++ b/share/html/Asset/ModifyCFs.html
@@
@@ -6786,7 +7367,7 @@
+%#
+%# COPYRIGHT:
+%#
-+%# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
++%# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
+%# <sales at bestpractical.com>
+%#
+%# (Except where explicitly superseded by other copyright notices)
@@ -6889,7 +7470,7 @@
+</%init>
diff --git a/share/html/Asset/ModifyDates.html b/share/html/Asset/ModifyDates.html
-new file mode 100755
+new file mode 100644
--- /dev/null
+++ b/share/html/Asset/ModifyDates.html
@@
@@ -6897,7 +7478,7 @@
+%#
+%# COPYRIGHT:
+%#
-+%# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
++%# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
+%# <sales at bestpractical.com>
+%#
+%# (Except where explicitly superseded by other copyright notices)
@@ -6992,7 +7573,7 @@
+</%args>
diff --git a/share/html/Asset/ModifyLinks.html b/share/html/Asset/ModifyLinks.html
-new file mode 100755
+new file mode 100644
--- /dev/null
+++ b/share/html/Asset/ModifyLinks.html
@@
@@ -7000,7 +7581,7 @@
+%#
+%# COPYRIGHT:
+%#
-+%# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
++%# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
+%# <sales at bestpractical.com>
+%#
+%# (Except where explicitly superseded by other copyright notices)
@@ -7096,7 +7677,7 @@
+</%args>
diff --git a/share/html/Asset/ModifyPeople.html b/share/html/Asset/ModifyPeople.html
-new file mode 100755
+new file mode 100644
--- /dev/null
+++ b/share/html/Asset/ModifyPeople.html
@@
@@ -7104,7 +7685,7 @@
+%#
+%# COPYRIGHT:
+%#
-+%# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
++%# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
+%# <sales at bestpractical.com>
+%#
+%# (Except where explicitly superseded by other copyright notices)
@@ -7161,8 +7742,8 @@
+ <&| /Widgets/TitleBox, title => loc("People"), class => "asset-people", title_class => "inverse" &>
+ <table width="100%" class="edit">
+ <tr>
-+ <td width="30%"><& /Elements/Assets/EditPeople, %ARGS, Object => $asset &></td>
-+ <td width="30%"><& /Elements/Assets/AddPeople, Object => $asset &></td>
++ <td width="30%"><& /Asset/Elements/EditCatalogPeople, %ARGS, Object => $asset &></td>
++ <td width="30%"><& /Asset/Elements/AddCatalogPeople, Object => $asset &></td>
+ <td>
+ <& /Elements/EditCustomFields, Object => $asset, Grouping => 'People', AsTable => 1 &>
+ </td>
@@ -7192,7 +7773,7 @@
+ );
+
+ if ($cf_ok) {
-+ push @results, ProcessRoleMembers( $asset => %ARGS );
++ push @results, ProcessAssetRoleMembers( $asset => %ARGS );
+ push @results, ProcessObjectCustomFieldUpdates( Object => $asset, ARGSRef => \%ARGS );
+
+ MaybeRedirectForResults(
@@ -7221,7 +7802,7 @@
+%#
+%# COPYRIGHT:
+%#
-+%# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
++%# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
+%# <sales at bestpractical.com>
+%#
+%# (Except where explicitly superseded by other copyright notices)
@@ -7398,7 +7979,7 @@
+ AttributesRef => \@attributes,
+ ARGSRef => \%basics,
+ );
-+ push @tmp_res, ProcessRoleMembers( $asset => %ARGS );
++ push @tmp_res, ProcessAssetRoleMembers( $asset => %ARGS );
+ push @tmp_res, ProcessObjectCustomFieldUpdates( Object => $asset, ARGSRef => \%ARGS );
+ push @tmp_res, ProcessRecordLinks( RecordObj => $asset, RecordId => 'Asset', ARGSRef => \%ARGS );
+ push @tmp_res, ProcessRecordBulkCustomFields( RecordObj => $asset, ARGSRef => \%ARGS );
@@ -7424,7 +8005,7 @@
+%#
+%# COPYRIGHT:
+%#
-+%# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
++%# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
+%# <sales at bestpractical.com>
+%#
+%# (Except where explicitly superseded by other copyright notices)
@@ -7503,7 +8084,7 @@
+%#
+%# COPYRIGHT:
+%#
-+%# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
++%# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
+%# <sales at bestpractical.com>
+%#
+%# (Except where explicitly superseded by other copyright notices)
@@ -7617,7 +8198,7 @@
+%#
+%# COPYRIGHT:
+%#
-+%# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
++%# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
+%# <sales at bestpractical.com>
+%#
+%# (Except where explicitly superseded by other copyright notices)
@@ -7692,16 +8273,16 @@
</i><br />
% } elsif (ref($Object) eq 'RT::Queue') {
-diff --git a/share/html/Elements/Assets/AddPeople b/share/html/Elements/Assets/AddPeople
+diff --git a/share/html/Elements/FindAsset b/share/html/Elements/FindAsset
new file mode 100644
--- /dev/null
-+++ b/share/html/Elements/Assets/AddPeople
++++ b/share/html/Elements/FindAsset
@@
+%# BEGIN BPS TAGGED BLOCK {{{
+%#
+%# COPYRIGHT:
+%#
-+%# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
++%# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
+%# <sales at bestpractical.com>
+%#
+%# (Except where explicitly superseded by other copyright notices)
@@ -7744,37 +8325,23 @@
+%# those contributions and any derivatives thereof.
+%#
+%# END BPS TAGGED BLOCK }}}
-+<%args>
-+$Object
-+</%args>
-+<div class="add-user">
-+<h3><&|/l&>Add a person</&></h3>
-+<& SelectRoleType, Object => $Object, Name => "AddUserRoleMember-Role" &>
-+<input type="text" name="AddUserRoleMember"
-+ data-autocomplete="Users"
-+ data-autocomplete-return="Name"
-+ placeholder="<% loc("Find a user...") %>">
-+</div>
-+
-+<div class="add-group">
-+<h3><&|/l&>Add a group</&></h3>
-+<& SelectRoleType, Object => $Object, Name => "AddGroupRoleMember-Role" &>
-+<input type="text" name="AddGroupRoleMember"
-+ data-autocomplete="Groups"
-+ data-autocomplete-return="Name"
-+ placeholder="<% loc("Find a group...") %>">
-+</div>
-
-diff --git a/share/html/Elements/Assets/EditPeople b/share/html/Elements/Assets/EditPeople
++<&|/Widgets/TitleBox, title => loc('Find an asset') &>
++<form action="<% RT->Config->Get('WebPath') %>/Asset/Search/">
++ <input type="text" name="q" />
++ <input type="submit" value="<&|/l&>Search</&>" class="button" />
++</form>
++</&>
+
+diff --git a/share/html/Elements/MyAssets b/share/html/Elements/MyAssets
new file mode 100644
--- /dev/null
-+++ b/share/html/Elements/Assets/EditPeople
++++ b/share/html/Elements/MyAssets
@@
+%# BEGIN BPS TAGGED BLOCK {{{
+%#
+%# COPYRIGHT:
+%#
-+%# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
++%# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
+%# <sales at bestpractical.com>
+%#
+%# (Except where explicitly superseded by other copyright notices)
@@ -7817,340 +8384,6 @@
+%# those contributions and any derivatives thereof.
+%#
+%# END BPS TAGGED BLOCK }}}
-+<%args>
-+$Object
-+</%args>
-+<%init>
-+</%init>
-+% for my $role ($Object->Roles( ACLOnly => 0 )) {
-+<div class="role-<% CSSClass($role) %> role">
-+ <h3><% loc($role) %></h3>
-+ <& EditRoleMembers, Group => $Object->RoleGroup($role) &>
-+</div>
-+% }
-+<em><&|/l&>(Check box to delete)</&></em>
-
-diff --git a/share/html/Elements/Assets/EditRoleMembers b/share/html/Elements/Assets/EditRoleMembers
-new file mode 100644
---- /dev/null
-+++ b/share/html/Elements/Assets/EditRoleMembers
-@@
-+%# BEGIN BPS TAGGED BLOCK {{{
-+%#
-+%# COPYRIGHT:
-+%#
-+%# This software is Copyright (c) 1996-2014 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>
-+$Group => undef
-+$Recursively => 0
-+</%args>
-+<%init>
-+my $field_name = "RemoveRoleMember-" . $Group->Name;
-+</%init>
-+<ul class="role-members">
-+% my $Users = $Group->UserMembersObj( Recursively => $Recursively );
-+% if ($Group->SingleMemberRoleGroup) {
-+<input type="text" value="<% $Users->First->Name %>" name="SetRoleMember-<% $Group->Name %>" id="SetRoleMember-<% $Group->Name %>" data-autocomplete="Users" data-autocomplete-return="Name" /><br />
-+% } else {
-+% while ( my $user = $Users->Next ) {
-+<li>
-+ <label>
-+ <input type="checkbox" name="<% $field_name %>" value="<% $user->PrincipalId %>">
-+ <& /Elements/ShowUser, User => $user &>
-+ </label>
-+</li>
-+% }
-+% my $Groups = $Group->GroupMembersObj( Recursively => $Recursively );
-+% $Groups->LimitToUserDefinedGroups;
-+% while (my $group = $Groups->Next) {
-+<li>
-+ <label>
-+ <input type="checkbox" name="<% $field_name %>" value="<% $group->PrincipalId %>">
-+ <&|/l&>Group</&>: <% $group->Name %>
-+ </label>
-+</li>
-+% }
-+% }
-+</ul>
-
-diff --git a/share/html/Elements/Assets/Search b/share/html/Elements/Assets/Search
-new file mode 100644
---- /dev/null
-+++ b/share/html/Elements/Assets/Search
-@@
-+%# BEGIN BPS TAGGED BLOCK {{{
-+%#
-+%# COPYRIGHT:
-+%#
-+%# This software is Copyright (c) 1996-2014 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 }}}
-+<form ACTION="<% RT->Config->Get('WebPath') %>/Asset/Search/">
-+ <input size="12" name="q" accesskey="0" class="field" value="<% $value %>" placeholder="<&|/l&>Search Assets</&>..." />
-+</form>
-+<%init>
-+my $value = defined $DECODED_ARGS->{q} ? $DECODED_ARGS->{q} : '';
-+</%init>
-
-diff --git a/share/html/Elements/Assets/SelectRoleType b/share/html/Elements/Assets/SelectRoleType
-new file mode 100644
---- /dev/null
-+++ b/share/html/Elements/Assets/SelectRoleType
-@@
-+%# BEGIN BPS TAGGED BLOCK {{{
-+%#
-+%# COPYRIGHT:
-+%#
-+%# This software is Copyright (c) 1996-2014 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
-+$Name
-+$AllowNull => 0
-+</%args>
-+<select name="<% $Name %>">
-+% if ($AllowNull) {
-+ <option value=""></option>
-+% }
-+% for my $role ($Object->Roles( ACLOnly => 0, Single => 0 )) {
-+ <option value="<% $role %>"><% loc($role) %></option>
-+% }
-+</select>
-
-diff --git a/share/html/Elements/FindAsset b/share/html/Elements/FindAsset
-new file mode 100644
---- /dev/null
-+++ b/share/html/Elements/FindAsset
-@@
-+%# BEGIN BPS TAGGED BLOCK {{{
-+%#
-+%# COPYRIGHT:
-+%#
-+%# This software is Copyright (c) 1996-2014 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 }}}
-+<&|/Widgets/TitleBox, title => loc('Find an asset') &>
-+<form action="<% RT->Config->Get('WebPath') %>/Asset/Search/">
-+ <input type="text" name="q" />
-+ <input type="submit" value="<&|/l&>Search</&>" class="button" />
-+</form>
-+</&>
-
-diff --git a/share/html/Elements/MyAssets b/share/html/Elements/MyAssets
-new file mode 100644
---- /dev/null
-+++ b/share/html/Elements/MyAssets
-@@
-+%# BEGIN BPS TAGGED BLOCK {{{
-+%#
-+%# COPYRIGHT:
-+%#
-+%# This software is Copyright (c) 1996-2014 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 }}}
+<& /User/Elements/AssetList, User => $session{'CurrentUser'}->UserObj, Roles => [qw(HeldBy)], Title => loc('My Assets') &>
diff --git a/share/html/Elements/RT__Asset/ColumnMap b/share/html/Elements/RT__Asset/ColumnMap
@@ -8162,7 +8395,7 @@
+%#
+%# COPYRIGHT:
+%#
-+%# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
++%# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
+%# <sales at bestpractical.com>
+%#
+%# (Except where explicitly superseded by other copyright notices)
@@ -8289,7 +8522,7 @@
+%#
+%# COPYRIGHT:
+%#
-+%# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
++%# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
+%# <sales at bestpractical.com>
+%#
+%# (Except where explicitly superseded by other copyright notices)
@@ -8369,187 +8602,212 @@
--- a/share/html/Elements/Tabs
+++ b/share/html/Elements/Tabs
@@
- PageMenu()->child( edit => title => loc('Edit'), path => '/Prefs/MyRT.html' );
+ description => loc('Select Custom Fields for Articles in all Classes'),
+ path => '/Admin/Global/CustomFields/Class-Article.html',
+ );
++ $cfadmin->child( 'assets' =>
++ title => loc('Assets'),
++ description => loc('Select Custom Fields for Assets in all Catalogs'),
++ path => '/Admin/Global/CustomFields/Catalog-Assets.html',
++ );
+
+ my $article_admin = $admin->child( articles => title => loc('Articles'), path => "/Admin/Articles/index.html" );
+ my $class_admin = $article_admin->child(classes => title => loc('Classes'), path => '/Admin/Articles/Classes/' );
+@@
+ path => '/Admin/CustomFields/Modify.html?'.$m->comp("/Elements/QueryString", Create=>1, LookupType=> "RT::Class-RT::Article" ),
+ );
+
++ my $assets_admin = $admin->child( assets => title => loc("Assets"), path => '/Admin/Assets/' );
++ my $catalog_admin = $assets_admin->child( catalogs =>
++ title => loc("Catalogs"),
++ description => loc("Modify asset catalogs"),
++ path => "/Admin/Assets/Catalogs/"
++ );
++ $catalog_admin->child( "select", title => loc("Select"), path => $catalog_admin->path );
++ $catalog_admin->child( "create", title => loc("Create"), path => "Create.html" );
++
++
++ my $assets_cfs = $assets_admin->child( "cfs",
++ title => loc("Custom Fields"),
++ description => loc("Modify asset custom fields"),
++ path => "/Admin/CustomFields/?Type=" . RT::Asset->CustomFieldLookupType
++ );
++ $assets_cfs->child( "select", title => loc("Select"), path => $assets_cfs->path );
++ $assets_cfs->child( "create", title => loc("Create"), path => "/Admin/CustomFields/Modify.html?Create=1&LookupType=" . RT::Asset->CustomFieldLookupType);
++
+ $admin_global->child( 'group-rights' =>
+ title => loc('Group Rights'),
+ description => loc('Modify global group rights'),
+@@
+
+ my $build_main_nav = sub {
+
+- PageWidgets()->child( simple_search => raw_html => $m->scomp('SimpleSearch') );
+- PageWidgets()->child( create_ticket => raw_html => $m->scomp('CreateTicket') );
++ if ($request_path =~ m{^/Asset/}) {
++ PageWidgets()->child( asset_search => raw_html => $m->scomp('/Asset/Elements/Search') );
++ } else {
++ PageWidgets()->child( simple_search => raw_html => $m->scomp('SimpleSearch') );
++ PageWidgets()->child( create_ticket => raw_html => $m->scomp('CreateTicket') );
++ }
+
+ my $home = Menu->child( home => title => loc('Homepage'), path => '/' );
+ unless ($session{'dashboards_in_menu'}) {
+@@
+
+ $search->child( users => title => loc('Users'), path => "/User/Search.html" );
+
++ $search->child( assets => title => loc("Assets"), path => "/Asset/Search/" );
++
+ if ($session{CurrentUser}->HasRight( Right => 'ShowArticlesMenu', Object => RT->System )) {
+ my $articles = Menu->child( articles => title => loc('Articles'), path => "/Articles/index.html");
+ $articles->child( articles => title => loc('Overview'), path => "/Articles/index.html" );
+@@
+ $articles->child( search => title => loc('Search'), path => "/Articles/Article/Search.html" );
}
-+ { ### START ASSETS MENU
-+ # Top level Assets menu
-+ my $assets = Menu->child("tools")->add_before(
-+ "assets", title => loc("Assets"), path => "/Asset/Search/");
-+ $assets->child("create", title => loc("Create"), path => "/Asset/CreateInCatalog.html");
-+ $assets->child("search", title => loc("Search"), path => "/Asset/Search/");
-+
-+ Menu->child("search")->child("assets", title => loc("Assets"), path => "/Asset/Search/");
-+
-+ # Add global Assets custom field admin page
-+ my $global_cfs = Menu();
-+ $global_cfs = $global_cfs->child($_) or last
-+ for "admin" => "global" => "custom-fields";
-+ $global_cfs->child("assets", title => loc("Assets"), path => "/Admin/Global/CustomFields/Catalog-Assets.html")
-+ if $global_cfs;
-+
-+ # Add a Catalog admin menu
-+ my $config = Menu()->child("admin");
-+ if ($config) {
-+ my $assets = $config->child("tools")->add_before("assets", title => loc("Assets"), path => "/Admin/Assets/");
-+ my $catalogs = $assets->child("catalogs",
-+ title => loc("Catalogs"),
-+ description => loc("Modify asset catalogs"),
-+ path => "/Admin/Assets/Catalogs/");
-+ $catalogs->child("select", title => loc("Select"), path => $catalogs->path);
-+ $catalogs->child("create", title => loc("Create"), path => "Create.html");
-+
-+ my $cfs = $assets->child("cfs",
-+ title => loc("Custom Fields"),
-+ description => loc("Modify asset custom fields"),
-+ path => "/Admin/CustomFields/?Type=" . RT::Asset->CustomFieldLookupType);
-+ $cfs->child("select", title => loc("Select"), path => $cfs->path);
-+ $cfs->child("create", title => loc("Create"), path => "/Admin/CustomFields/Modify.html?Create=1&LookupType=" . RT::Asset->CustomFieldLookupType);
-+ }
-+
-+ # Asset search
-+ if ($request_path =~ m{^/Asset/}) {
-+ PageWidgets()->child( asset_search => raw_html => $m->scomp('/Elements/Assets/Search') );
-+ PageWidgets()->delete('create_ticket');
-+ PageWidgets()->delete('simple_search');
-+ }
-+
-+ # Page menus
-+ my $page = PageMenu();
-+
-+ if ($request_path =~ m{^/Asset/} and $DECODED_ARGS->{id} and $DECODED_ARGS->{id} !~ /\D/) {
-+ my $id = $DECODED_ARGS->{id};
-+ my $asset = RT::Asset->new( $session{CurrentUser} );
-+ $asset->Load($id);
-+
-+ if ($asset->id) {
-+ $page->child("display", title => loc("Display"), path => "/Asset/Display.html?id=$id");
-+ $page->child("history", title => loc("History"), path => "/Asset/History.html?id=$id");
-+ $page->child("basics", title => loc("Basics"), path => "/Asset/Modify.html?id=$id");
-+ $page->child("links", title => loc("Links"), path => "/Asset/ModifyLinks.html?id=$id");
-+ $page->child("people", title => loc("People"), path => "/Asset/ModifyPeople.html?id=$id");
-+ $page->child("dates", title => loc("Dates"), path => "/Asset/ModifyDates.html?id=$id");
-+
-+ for my $grouping (RT::CustomField->CustomGroupings($asset)) {
-+ my $cfs = $asset->CustomFields;
-+ $cfs->LimitToGrouping( $asset => $grouping );
-+ next unless $cfs->Count;
-+ $page->child(
-+ "cf-grouping-$grouping",
-+ title => loc($grouping),
-+ path => "/Asset/ModifyCFs.html?id=$id;Grouping=" . $m->interp->apply_escapes($grouping, 'u'),
-+ );
-+ }
-+
-+ my $actions = $page->child("actions", title => loc("Actions"));
-+ $actions->child("create-linked-ticket", title => loc("Create linked ticket"), path => "/Asset/CreateLinkedTicket.html?Asset=$id");
-+
-+ my $status = $asset->Status;
-+ my $lifecycle = $asset->LifecycleObj;
-+ for my $action ( $lifecycle->Actions($status) ) {
-+ my $next = $action->{'to'};
-+ next unless $lifecycle->IsTransition( $status => $next );
-+
-+ my $check = $lifecycle->CheckRight( $status => $next );
-+ next unless $asset->CurrentUserHasRight($check);
-+
-+ my $label = $action->{'label'} || ucfirst($next);
-+ $actions->child(
-+ $label,
-+ title => loc($label),
-+ path => "/Asset/Modify.html?id=$id;Update=1;DisplayAfter=1;Status="
-+ . $m->interp->apply_escapes($next, 'u'),
-+
-+ class => "asset-lifecycle-action",
-+ attributes => {
-+ 'data-current-status' => $status,
-+ 'data-next-status' => $next,
-+ },
-+ );
-+ }
++ my $assets = Menu->child( "assets", title => loc("Assets"), path => "/Asset/Search/" );
++ $assets->child( "create", title => loc("Create"), path => "/Asset/CreateInCatalog.html" );
++ $assets->child( "search", title => loc("Search"), path => "/Asset/Search/" );
++
+ my $tools = Menu->child( tools => title => loc('Tools'), path => '/Tools/index.html' );
+
+ $tools->child( my_day =>
+@@
+
+ }
+
++ if ($request_path =~ m{^/Asset/} and $DECODED_ARGS->{id} and $DECODED_ARGS->{id} !~ /\D/) {
++ my $page = PageMenu();
++ my $id = $DECODED_ARGS->{id};
++ my $asset = RT::Asset->new( $session{CurrentUser} );
++ $asset->Load($id);
++
++ if ($asset->id) {
++ $page->child("display", title => loc("Display"), path => "/Asset/Display.html?id=$id");
++ $page->child("history", title => loc("History"), path => "/Asset/History.html?id=$id");
++ $page->child("basics", title => loc("Basics"), path => "/Asset/Modify.html?id=$id");
++ $page->child("links", title => loc("Links"), path => "/Asset/ModifyLinks.html?id=$id");
++ $page->child("people", title => loc("People"), path => "/Asset/ModifyPeople.html?id=$id");
++ $page->child("dates", title => loc("Dates"), path => "/Asset/ModifyDates.html?id=$id");
++
++ for my $grouping (RT::CustomField->CustomGroupings($asset)) {
++ my $cfs = $asset->CustomFields;
++ $cfs->LimitToGrouping( $asset => $grouping );
++ next unless $cfs->Count;
++ $page->child(
++ "cf-grouping-$grouping",
++ title => loc($grouping),
++ path => "/Asset/ModifyCFs.html?id=$id;Grouping=" . $m->interp->apply_escapes($grouping, 'u'),
++ );
++ }
++
++ my $actions = $page->child("actions", title => loc("Actions"));
++ $actions->child("create-linked-ticket", title => loc("Create linked ticket"), path => "/Asset/CreateLinkedTicket.html?Asset=$id");
++
++ my $status = $asset->Status;
++ my $lifecycle = $asset->LifecycleObj;
++ for my $action ( $lifecycle->Actions($status) ) {
++ my $next = $action->{'to'};
++ next unless $lifecycle->IsTransition( $status => $next );
++
++ my $check = $lifecycle->CheckRight( $status => $next );
++ next unless $asset->CurrentUserHasRight($check);
++
++ my $label = $action->{'label'} || ucfirst($next);
++ $actions->child(
++ $label,
++ title => loc($label),
++ path => "/Asset/Modify.html?id=$id;Update=1;DisplayAfter=1;Status="
++ . $m->interp->apply_escapes($next, 'u'),
++
++ class => "asset-lifecycle-action",
++ attributes => {
++ 'data-current-status' => $status,
++ 'data-next-status' => $next,
++ },
++ );
+ }
+ }
-+ elsif ($request_path =~ m{^/Asset/Search/}) {
-+ my %search = map @{$_},
-+ grep defined $_->[1] && length $_->[1],
-+ map {ref $DECODED_ARGS->{$_} ? [$_, $DECODED_ARGS->{$_}[0]] : [$_, $DECODED_ARGS->{$_}] }
-+ grep /^(?:q|SearchAssets|!?(Name|Description|Catalog|Status|Role\..+|CF\..+)|Order(?:By)?|Page)$/,
-+ keys %$DECODED_ARGS;
-+ if ( $request_path =~ /Bulk/) {
-+ $page->child('search',
-+ title => loc('Show Results'),
-+ path => '/Asset/Search/?'. $query_string->(%search),
-+ );
-+ } else {
-+ $page->child('bulk',
-+ title => loc('Bulk Update'),
-+ path => '/Asset/Search/Bulk.html?'. $query_string->(%search),
-+ );
-+ }
-+ $page->child('csv',
-+ title => loc('Download Spreadsheet'),
-+ path => '/Asset/Search/Results.tsv?' . $query_string->(%search),
++ } elsif ($request_path =~ m{^/Asset/Search/}) {
++ my $page = PageMenu();
++ my %search = map @{$_},
++ grep defined $_->[1] && length $_->[1],
++ map {ref $DECODED_ARGS->{$_} ? [$_, $DECODED_ARGS->{$_}[0]] : [$_, $DECODED_ARGS->{$_}] }
++ grep /^(?:q|SearchAssets|!?(Name|Description|Catalog|Status|Role\..+|CF\..+)|Order(?:By)?|Page)$/,
++ keys %$DECODED_ARGS;
++ if ( $request_path =~ /Bulk/) {
++ $page->child('search',
++ title => loc('Show Results'),
++ path => '/Asset/Search/?' . keys %search ? $query_string->(%search) : '',
++ );
++ } else {
++ $page->child('bulk',
++ title => loc('Bulk Update'),
++ path => '/Asset/Search/Bulk.html?' . keys %search ? $query_string->(%search) : '',
+ );
+ }
-+ elsif ($request_path =~ m{^/Admin/Global/CustomFields/Catalog-Assets\.html$}) {
-+ $page->child("create", title => loc("Create New"), path => "/Admin/CustomFields/Modify.html?Create=1;LookupType=" . RT::Asset->CustomFieldLookupType);
++ $page->child('csv',
++ title => loc('Download Spreadsheet'),
++ path => '/Asset/Search/Results.tsv?' . keys %search ? $query_string->(%search) : '',
++ );
++ } elsif ($request_path =~ m{^/Admin/Global/CustomFields/Catalog-Assets\.html$}) {
++ my $page = PageMenu();
++ $page->child("create", title => loc("Create New"), path => "/Admin/CustomFields/Modify.html?Create=1;LookupType=" . RT::Asset->CustomFieldLookupType);
++ } elsif ($request_path =~ m{^/Admin/CustomFields(/|/index\.html)?$}
++ and $DECODED_ARGS->{'Type'} and $DECODED_ARGS->{'Type'} eq RT::Asset->CustomFieldLookupType) {
++ my $page = PageMenu();
++ $page->child("create")->path( $page->child("create")->path . "&LookupType=" . RT::Asset->CustomFieldLookupType );
++ } elsif ($request_path =~ m{^/Admin/Assets/Catalogs/}) {
++ my $page = PageMenu();
++ my $actions = $request_path =~ m{/((index|Create)\.html)?$}
++ ? $page
++ : $page->child("catalogs", title => loc("Catalogs"), path => "/Admin/Assets/Catalogs/");
++
++ $actions->child("select", title => loc("Select"), path => "/Admin/Assets/Catalogs/");
++ $actions->child("create", title => loc("Create"), path => "/Admin/Assets/Catalogs/Create.html");
++
++ my $catalog = RT::Catalog->new( $session{CurrentUser} );
++ $catalog->Load($DECODED_ARGS->{id}) if $DECODED_ARGS->{id};
++
++ if ($catalog->id and $catalog->CurrentUserCanSee) {
++ my $query = "id=" . $catalog->id;
++ $page->child("modify", title => loc("Basics"), path => "/Admin/Assets/Catalogs/Modify.html?$query");
++ $page->child("people", title => loc("Roles"), path => "/Admin/Assets/Catalogs/Roles.html?$query");
++
++ $page->child("cfs", title => loc("Asset Custom Fields"), path => "/Admin/Assets/Catalogs/CustomFields.html?$query");
++
++ $page->child("group-rights", title => loc("Group Rights"), path => "/Admin/Assets/Catalogs/GroupRights.html?$query");
++ $page->child("user-rights", title => loc("User Rights"), path => "/Admin/Assets/Catalogs/UserRights.html?$query");
+ }
-+ elsif ($request_path =~ m{^/Admin/CustomFields(/|/index\.html)?$}
-+ and $DECODED_ARGS->{'Type'} and $DECODED_ARGS->{'Type'} eq RT::Asset->CustomFieldLookupType) {
-+ $page->child("create")->path( $page->child("create")->path . "&LookupType=" . RT::Asset->CustomFieldLookupType );
-+ }
-+ elsif ($request_path =~ m{^/Admin/Assets/Catalogs/}) {
-+ my $actions = $request_path =~ m{/((index|Create)\.html)?$}
-+ ? $page
-+ : $page->child("catalogs", title => loc("Catalogs"), path => "/Admin/Assets/Catalogs/");
-+
-+ $actions->child("select", title => loc("Select"), path => "/Admin/Assets/Catalogs/");
-+ $actions->child("create", title => loc("Create"), path => "/Admin/Assets/Catalogs/Create.html");
-+
-+ my $catalog = RT::Catalog->new( $session{CurrentUser} );
-+ $catalog->Load($DECODED_ARGS->{id}) if $DECODED_ARGS->{id};
-+
-+ if ($catalog->id and $catalog->CurrentUserCanSee) {
-+ my $query = "id=" . $catalog->id;
-+ $page->child("modify", title => loc("Basics"), path => "/Admin/Assets/Catalogs/Modify.html?$query");
-+ $page->child("people", title => loc("Roles"), path => "/Admin/Assets/Catalogs/Roles.html?$query");
-+
-+ $page->child("cfs", title => loc("Asset Custom Fields"), path => "/Admin/Assets/Catalogs/CustomFields.html?$query");
-+
-+ $page->child("group-rights", title => loc("Group Rights"), path => "/Admin/Assets/Catalogs/GroupRights.html?$query");
-+ $page->child("user-rights", title => loc("User Rights"), path => "/Admin/Assets/Catalogs/UserRights.html?$query");
-+ }
-+ }
-+ } ### END ASSETS MENU
-+
- $m->callback( CallbackName => 'Privileged', Path => $request_path );
- };
++ }
++
+ if ( $request_path =~ m{^/User/(Summary|History)\.html} ) {
+ if (PageMenu()->child('summary')) {
+ # Already set up from having AdminUser and ShowConfigTab;
+@@
+ $tickets->child( open => title => loc('Open tickets'), path => '/SelfService/' );
+ $tickets->child( closed => title => loc('Closed tickets'), path => '/SelfService/Closed.html' );
++ my $assets = Menu->child( "assets", title => loc("Assets"), path => "/SelfService/Asset/" );
+
+ my $username = '<span class="current-user">'
+ . $m->interp->apply_escapes($session{'CurrentUser'}->Name, 'h')
@@
PageWidgets->child( goto => raw_html => $m->scomp('/SelfService/Elements/GotoTicket') );
-+ { ### START ASSETS SELFSERVICE MENU
-+ Menu->child("tickets")->add_after(
-+ "assets",
-+ title => loc("Assets"),
-+ path => "/SelfService/Asset/",
-+ );
-+
-+ # Page menus
-+ my $page = PageMenu();
-+
-+ if ($request_path =~ m{^/SelfService/Asset/} and $DECODED_ARGS->{id}) {
-+ my $id = $DECODED_ARGS->{id};
-+ $page->child("display", title => loc("Display"), path => "/SelfService/Asset/Display.html?id=$id");
-+ $page->child("history", title => loc("History"), path => "/SelfService/Asset/History.html?id=$id");
-+
-+ if (Menu->child("new")) {
-+ my $actions = $page->child("actions", title => loc("Actions"));
-+ $actions->child("create-linked-ticket", title => loc("Create linked ticket"), path => "/SelfService/Asset/CreateLinkedTicket.html?Asset=$id");
-+ }
++ if ($request_path =~ m{^/SelfService/Asset/} and $DECODED_ARGS->{id}) {
++ my $page = PageMenu();
++ my $id = $DECODED_ARGS->{id};
++ $page->child("display", title => loc("Display"), path => "/SelfService/Asset/Display.html?id=$id");
++ $page->child("history", title => loc("History"), path => "/SelfService/Asset/History.html?id=$id");
++
++ if (Menu->child("new")) {
++ my $actions = $page->child("actions", title => loc("Actions"));
++ $actions->child("create-linked-ticket", title => loc("Create linked ticket"), path => "/SelfService/Asset/CreateLinkedTicket.html?Asset=$id");
+ }
-+ } ### END ASSETS SELFSERVICE MENU
++ }
+
$m->callback( CallbackName => 'SelfService', Path => $request_path );
};
@@ -8564,7 +8822,7 @@
+%#
+%# COPYRIGHT:
+%#
-+%# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
++%# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
+%# <sales at bestpractical.com>
+%#
+%# (Except where explicitly superseded by other copyright notices)
@@ -8627,7 +8885,7 @@
+%#
+%# COPYRIGHT:
+%#
-+%# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
++%# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
+%# <sales at bestpractical.com>
+%#
+%# (Except where explicitly superseded by other copyright notices)
@@ -8690,7 +8948,7 @@
+%#
+%# COPYRIGHT:
+%#
-+%# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
++%# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
+%# <sales at bestpractical.com>
+%#
+%# (Except where explicitly superseded by other copyright notices)
@@ -8751,7 +9009,7 @@
+%#
+%# COPYRIGHT:
+%#
-+%# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
++%# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
+%# <sales at bestpractical.com>
+%#
+%# (Except where explicitly superseded by other copyright notices)
@@ -8817,7 +9075,7 @@
+%#
+%# COPYRIGHT:
+%#
-+%# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
++%# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
+%# <sales at bestpractical.com>
+%#
+%# (Except where explicitly superseded by other copyright notices)
@@ -8899,7 +9157,7 @@
+%#
+%# COPYRIGHT:
+%#
-+%# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
++%# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
+%# <sales at bestpractical.com>
+%#
+%# (Except where explicitly superseded by other copyright notices)
@@ -9088,7 +9346,7 @@
+ <div class="add-asset">
+ <label>
+ <&|/l&>Add an asset to this ticket</&>
-+ <input size="5" name="<% $Ticket->id %>-RefersTo" placeholder="<&|/l&>Asset #</&>" type="text">
++ <input size="10" name="<% $Ticket->id %>-RefersTo" placeholder="<&|/l&>Asset #</&>" type="text">
+ </label>
+ <input type="submit" value="+">
+ </div>
@@ -9109,7 +9367,7 @@
+%#
+%# COPYRIGHT:
+%#
-+%# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
++%# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
+%# <sales at bestpractical.com>
+%#
+%# (Except where explicitly superseded by other copyright notices)
@@ -9248,7 +9506,7 @@
+%#
+%# COPYRIGHT:
+%#
-+%# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
++%# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
+%# <sales at bestpractical.com>
+%#
+%# (Except where explicitly superseded by other copyright notices)
@@ -9332,7 +9590,7 @@
+%#
+%# COPYRIGHT:
+%#
-+%# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
++%# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
+%# <sales at bestpractical.com>
+%#
+%# (Except where explicitly superseded by other copyright notices)
@@ -9615,6 +9873,18 @@
+ width: 10em;
+ }
+}
+
+diff --git a/share/static/css/base/main.css b/share/static/css/base/main.css
+--- a/share/static/css/base/main.css
++++ b/share/static/css/base/main.css
+@@
+ @import "record.css";
+ @import "admin.css";
+ @import "articles.css";
++ at import "assets.css";
+ @import "portlets.css";
+ @import "tools.css";
+ @import "login.css";
diff --git a/share/static/js/assets.js b/share/static/js/assets.js
new file mode 100644
@@ -9666,6 +9936,19 @@
+ });
+});
+diff --git a/t/api/template-parsing.t b/t/api/template-parsing.t
+--- a/t/api/template-parsing.t
++++ b/t/api/template-parsing.t
+@@
+
+ SimpleTemplateTest(
+ Content => "\ntest { \$TicketOwnerId }",
+- Output => "test 12",
++ Output => "test 14",
+ );
+
+ SimpleTemplateTest(
+
diff --git a/t/assets/api.t b/t/assets/api.t
new file mode 100644
--- /dev/null
@@ -10076,18 +10359,6 @@
+}
+
+done_testing;
-
-diff --git a/t/assets/pod.t b/t/assets/pod.t
-new file mode 100644
---- /dev/null
-+++ b/t/assets/pod.t
-@@
-+use strict;
-+use warnings;
-+
-+use Test::More;
-+use Test::Pod;
-+all_pod_files_ok( all_pod_files("lib","doc","etc"));
diff --git a/t/assets/rights.t b/t/assets/rights.t
new file mode 100644
@@ -10373,3 +10644,28 @@
+undef $m;
+done_testing;
+diff --git a/t/web/case-sensitivity.t b/t/web/case-sensitivity.t
+--- a/t/web/case-sensitivity.t
++++ b/t/web/case-sensitivity.t
+@@
+ require JSON;
+ is_deeply(
+ JSON::from_json( $m->content ),
+- [{id => 12, "value" => "root\@localhost","label" => "root (Enoch Root)"}]
++ [{id => 14, "value" => "root\@localhost","label" => "root (Enoch Root)"}]
+ );
+ }
+
+
+diff --git a/t/web/rest_user_cf.t b/t/web/rest_user_cf.t
+--- a/t/web/rest_user_cf.t
++++ b/t/web/rest_user_cf.t
+@@
+ is( $root->FirstCustomFieldValue('foo'), 'blabla', 'cf is set' );
+
+ ok( $m->login, 'logged in' );
+-$m->post( "$baseurl/REST/1.0/show", [ id => 'user/12', ] );
++$m->post( "$baseurl/REST/1.0/show", [ id => 'user/14', ] );
+ like( $m->content, qr/CF-foo: blabla/, 'found the cf' );
+
+ undef $m;
2: 8b54627 < --: ------- fixes for failing tests
3: 979b49a < --: ------- commit sunnavy's feedback
4: 222bbd4 < --: ------- shawn's feedback
5: 5516fdd < --: ------- lib/RT/Interface/Web.pm share/html/Admin/Assets/Catalogs/Roles.html share/html/Asset/ModifyPeople.html share/html/Asset/Search/Bulk.html - rename ProcessRoleMembers to ProcessAssetRoleMembers
6: 4f181d5 < --: ------- change the last instance of the word 'extension'
7: 192a09e < --: ------- Fix encoding for tutorial.pod
8: b1ce73f < --: ------- fix the (hopefully) last vestiges of references to the extension
9: a3264ce < --: ------- fix tests (root is now getting id 14 instead of 12 as id?)
10: dcee687 < --: ------- move contents of share/html/Elements/Assets to share/html/Asset/Elements
More information about the rt-commit
mailing list