[Rt-commit] rt branch, 4.4/show-assets-action-menu, created. rt-4.4.1rc1-18-g5cce23e

Dustin Graves dustin at bestpractical.com
Fri Jun 24 14:40:17 EDT 2016


The branch, 4.4/show-assets-action-menu has been created
        at  5cce23edbfef62c2f26e9ef0f94b2d1933b37e59 (commit)

- Log -----------------------------------------------------------------
commit 755042f6a9941734e21a987a638ff03b36b4dc18
Author: Dustin Graves <dustin at bestpractical.com>
Date:   Tue May 31 21:55:26 2016 +0000

    refactor RT menu building logic into own library module

diff --git a/share/html/Elements/Tabs b/lib/RT/Interface/Web/MenuBuilder.pm
similarity index 66%
copy from share/html/Elements/Tabs
copy to lib/RT/Interface/Web/MenuBuilder.pm
index 866e8f2..66a2a03 100644
--- a/share/html/Elements/Tabs
+++ b/lib/RT/Interface/Web/MenuBuilder.pm
@@ -1,1115 +1,1131 @@
-%# BEGIN BPS TAGGED BLOCK {{{
-%#
-%# COPYRIGHT:
-%#
-%# This software is Copyright (c) 1996-2016 Best Practical Solutions, LLC
-%#                                          <sales at bestpractical.com>
-%#
-%# (Except where explicitly superseded by other copyright notices)
-%#
-%#
-%# LICENSE:
-%#
-%# This work is made available to you under the terms of Version 2 of
-%# the GNU General Public License. A copy of that license should have
-%# been provided with this software, but in any event can be snarfed
-%# from www.gnu.org.
-%#
-%# This work is distributed in the hope that it will be useful, but
-%# WITHOUT ANY WARRANTY; without even the implied warranty of
-%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-%# General Public License for more details.
-%#
-%# You should have received a copy of the GNU General Public License
-%# along with this program; if not, write to the Free Software
-%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-%# 02110-1301 or visit their web page on the internet at
-%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html.
-%#
-%#
-%# CONTRIBUTION SUBMISSION POLICY:
-%#
-%# (The following paragraph is not intended to limit the rights granted
-%# to you to modify and distribute this software under the terms of
-%# the GNU General Public License and is only of importance to you if
-%# you choose to contribute your changes and enhancements to the
-%# community by submitting them to Best Practical Solutions, LLC.)
-%#
-%# By intentionally submitting any modifications, corrections or
-%# derivatives to this work, or any other work intended for use with
-%# Request Tracker, to Best Practical Solutions, LLC, you confirm that
-%# you are the copyright holder for those contributions and you grant
-%# Best Practical Solutions,  LLC a nonexclusive, worldwide, irrevocable,
-%# royalty-free, perpetual, license to use, copy, create derivative
-%# works based on those contributions, and sublicense and distribute
-%# those contributions and any derivatives thereof.
-%#
-%# END BPS TAGGED BLOCK }}}
-<& /Elements/PageLayout, show_menu => $show_menu &>
-<a name="skipnav" id="skipnav" accesskey="8"></a>
-<%INIT>
-
-my $request_path = $HTML::Mason::Commands::r->path_info;
-$request_path =~ s!/{2,}!/!g;
-
-my $query_string = sub {
+# BEGIN BPS TAGGED BLOCK {{{
+#
+# COPYRIGHT:
+#
+# This software is Copyright (c) 1996-2016 Best Practical Solutions, LLC
+#                                          <sales at bestpractical.com>
+#
+# (Except where explicitly superseded by other copyright notices)
+#
+#
+# LICENSE:
+#
+# This work is made available to you under the terms of Version 2 of
+# the GNU General Public License. A copy of that license should have
+# been provided with this software, but in any event can be snarfed
+# from www.gnu.org.
+#
+# This work is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301 or visit their web page on the internet at
+# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html.
+#
+#
+# CONTRIBUTION SUBMISSION POLICY:
+#
+# (The following paragraph is not intended to limit the rights granted
+# to you to modify and distribute this software under the terms of
+# the GNU General Public License and is only of importance to you if
+# you choose to contribute your changes and enhancements to the
+# community by submitting them to Best Practical Solutions, LLC.)
+#
+# By intentionally submitting any modifications, corrections or
+# derivatives to this work, or any other work intended for use with
+# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+# you are the copyright holder for those contributions and you grant
+# Best Practical Solutions,  LLC a nonexclusive, worldwide, irrevocable,
+# royalty-free, perpetual, license to use, copy, create derivative
+# works based on those contributions, and sublicense and distribute
+# those contributions and any derivatives thereof.
+#
+# END BPS TAGGED BLOCK }}}
+
+=head1 NAME
+
+RT::Interface::Web::MenuBuilder
+
+=cut
+
+use strict;
+use warnings;
+
+package RT::Interface::Web::MenuBuilder;
+
+sub loc { HTML::Mason::Commands::loc( @_ ); }
+
+sub QueryString {
     my %args = @_;
     my $u    = URI->new();
     $u->query_form(map { $_ => $args{$_} } sort keys %args);
     return $u->query;
-};
+}
 
-my $build_admin_menu = sub {
-    my $top = shift;
-    my $admin = $top->child( admin => title => loc('Admin'), path => '/Admin/' );
-    if ( $session{'CurrentUser'}->HasRight( Object => RT->System, Right => 'AdminUsers' ) ) {
-        my $users = $admin->child( users =>
-            title       => loc('Users'),
-            description => loc('Manage users and passwords'),
-            path        => '/Admin/Users/',
+sub BuildMainNav {
+    my $request_path = shift;
+    my $query_string = shift;
+    my $query_args = shift;
+
+    if ($request_path =~ m{^/Asset/}) {
+        HTML::Mason::Commands::PageWidgets()->child( asset_search => raw_html => $HTML::Mason::Commands::m->scomp('/Asset/Elements/Search') );
+    } else {
+        HTML::Mason::Commands::PageWidgets()->child( simple_search => raw_html => $HTML::Mason::Commands::m->scomp('SimpleSearch') );
+        HTML::Mason::Commands::PageWidgets()->child( create_ticket => raw_html => $HTML::Mason::Commands::m->scomp('CreateTicket') );
+    }
+
+    my $home = HTML::Mason::Commands::Menu()->child( home => title => loc('Homepage'), path => '/' );
+    unless ($HTML::Mason::Commands::session{'dashboards_in_menu'}) {
+        my $dashboards_in_menu = $HTML::Mason::Commands::session{CurrentUser}->UserObj->Preferences(
+            'DashboardsInMenu',
+            {},
         );
-        $users->child( select => title => loc('Select'), path => "/Admin/Users/" );
-        $users->child( create => title => loc('Create'), path => "/Admin/Users/Modify.html?Create=1" );
+
+        unless ($dashboards_in_menu->{dashboards}) {
+            my ($default_dashboards) =
+                RT::System->new( $HTML::Mason::Commands::session{'CurrentUser'} )
+                    ->Attributes
+                    ->Named('DashboardsInMenu');
+            if ($default_dashboards) {
+                $dashboards_in_menu = $default_dashboards->Content;
+            }
+        }
+
+        $HTML::Mason::Commands::session{'dashboards_in_menu'} = $dashboards_in_menu->{dashboards} || [];
     }
-    my $groups = $admin->child( groups =>
-        title       => loc('Groups'),
-        description => loc('Manage groups and group membership'),
-        path        => '/Admin/Groups/',
-    );
-    $groups->child( select => title => loc('Select'), path => "/Admin/Groups/" );
-    $groups->child( create => title => loc('Create'), path => "/Admin/Groups/Modify.html?Create=1" );
 
-    my $queues = $admin->child( queues =>
-        title       => loc('Queues'),
-        description => loc('Manage queues and queue-specific properties'),
-        path        => '/Admin/Queues/',
-    );
-    $queues->child( select => title => loc('Select'), path => "/Admin/Queues/" );
-    $queues->child( create => title => loc('Create'), path => "/Admin/Queues/Modify.html?Create=1" );
+    my @dashboards;
+    for my $id ( @{$HTML::Mason::Commands::session{'dashboards_in_menu'}} ) {
+        my $dash = RT::Dashboard->new( $HTML::Mason::Commands::session{CurrentUser} );
+        my ( $status, $msg ) = $dash->LoadById($id);
+        if ( $status ) {
+            push @dashboards, $dash;
+        } else {
+            $RT::Logger->warning( "Failed to load dashboard $id: $msg" );
+        }
+    }
 
-    if ( $session{'CurrentUser'}->HasRight( Object => RT->System, Right => 'AdminCustomField' ) ) {
-        my $cfs = $admin->child( 'custom-fields' =>
-            title       => loc('Custom Fields'),
-            description => loc('Manage custom fields and custom field values'),
-            path        => '/Admin/CustomFields/',
-        );
-        $cfs->child( select => title => loc('Select'), path => "/Admin/CustomFields/" );
-        $cfs->child( create => title => loc('Create'), path => "/Admin/CustomFields/Modify.html?Create=1" );
+    my $dashes = HTML::Mason::Commands::Menu()->child('home');
+    if (@dashboards) {
+        for my $dash (@dashboards) {
+            $home->child( 'dashboard-' . $dash->id,
+                title => $dash->Name,
+                path  => '/Dashboards/' . $dash->id . '/' . $dash->Name
+            );
+        }
+    }
+    $dashes->child( edit => title => loc('Update This Menu'), path => 'Prefs/DashboardsInMenu.html' );
+    $dashes->child( more => title => loc('All Dashboards'),   path => 'Dashboards/index.html' );
+    my $dashboard = RT::Dashboard->new( $HTML::Mason::Commands::session{CurrentUser} );
+    if ( $dashboard->CurrentUserCanCreateAny ) {
+        $dashes->child('dashboard_create' => title => loc('New Dashboard'), path => "/Dashboards/Modify.html?Create=1" );
     }
 
-    if ( $session{'CurrentUser'}->HasRight( Object => RT->System, Right => 'AdminCustomRoles' ) ) {
-        my $roles = $admin->child( 'custom-roles' =>
-            title       => loc('Custom Roles'),
-            description => loc('Manage custom roles'),
-            path        => '/Admin/CustomRoles/',
+    my $search = HTML::Mason::Commands::Menu()->child( search => title => loc('Search'), path => '/Search/Simple.html' );
+
+    my $tickets = $search->child( tickets => title => loc('Tickets'), path => '/Search/Build.html' );
+    $tickets->child( simple => title => loc('Simple Search'), path => "/Search/Simple.html" );
+    $tickets->child( new    => title => loc('New Search'),    path => "/Search/Build.html?NewQuery=1" );
+
+    $search->child( articles => title => loc('Articles'),   path => "/Articles/Article/Search.html" )
+        if $HTML::Mason::Commands::session{CurrentUser}->HasRight( Right => 'ShowArticlesMenu', Object => RT->System );
+
+    $search->child( users => title => loc('Users'),   path => "/User/Search.html" );
+
+    $search->child( assets => title => loc("Assets"), path => "/Asset/Search/" )
+        if $HTML::Mason::Commands::session{CurrentUser}->HasRight( Right => 'ShowAssetsMenu', Object => RT->System );
+
+    if ($HTML::Mason::Commands::session{CurrentUser}->HasRight( Right => 'ShowArticlesMenu', Object => RT->System )) {
+        my $articles = HTML::Mason::Commands::Menu()->child( articles => title => loc('Articles'), path => "/Articles/index.html");
+        $articles->child( articles => title => loc('Overview'), path => "/Articles/index.html" );
+        $articles->child( topics   => title => loc('Topics'),   path => "/Articles/Topics.html" );
+        $articles->child( create   => title => loc('Create'),   path => "/Articles/Article/PreCreate.html" );
+        $articles->child( search   => title => loc('Search'),   path => "/Articles/Article/Search.html" );
+    }
+
+    if ($HTML::Mason::Commands::session{CurrentUser}->HasRight( Right => 'ShowAssetsMenu', Object => RT->System )) {
+        my $assets = HTML::Mason::Commands::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 = HTML::Mason::Commands::Menu()->child( tools => title => loc('Tools'), path => '/Tools/index.html' );
+
+    $tools->child( my_day =>
+        title       => loc('My Day'),
+        description => loc('Easy updating of your open tickets'),
+        path        => '/Tools/MyDay.html',
+    );
+
+    if ( RT->Config->Get('EnableReminders') ) {
+        $tools->child( my_reminders =>
+            title       => loc('My Reminders'),
+            description => loc('Easy viewing of your reminders'),
+            path        => '/Tools/MyReminders.html',
         );
-        $roles->child( select => title => loc('Select'), path => "/Admin/CustomRoles/" );
-        $roles->child( create => title => loc('Create'), path => "/Admin/CustomRoles/Modify.html?Create=1" );
     }
 
-    if ( $session{'CurrentUser'}->HasRight( Object => RT->System, Right => 'ModifyScrips' ) ) {
-        my $scrips = $admin->child( 'scrips' =>
-            title       => loc('Scrips'),
-            description => loc('Manage scrips'),
-            path        => '/Admin/Scrips/',
+    if ( $HTML::Mason::Commands::session{'CurrentUser'}->HasRight( Right => 'ShowApprovalsTab', Object => RT->System ) ) {
+        $tools->child( approval =>
+            title       => loc('Approval'),
+            description => loc('My Approvals'),
+            path        => '/Approvals/',
         );
-        $scrips->child( select => title => loc('Select'), path => "/Admin/Scrips/" );
-        $scrips->child( create => title => loc('Create'), path => "/Admin/Scrips/Create.html" );
     }
 
-    my $admin_global = $admin->child( global =>
-        title       => loc('Global'),
-        description => loc('Manage properties and configuration which apply to all queues'),
-        path        => '/Admin/Global/',
-    );
+    if ( $HTML::Mason::Commands::session{'CurrentUser'}->HasRight( Right => 'ShowConfigTab', Object => RT->System ) )
+    {
+        _BuildAdminMenu($request_path, HTML::Mason::Commands::Menu());
+    }
 
-    my $scrips = $admin_global->child( scrips =>
-        title       => loc('Scrips'),
-        description => loc('Modify scrips which apply to all queues'),
-        path        => '/Admin/Global/Scrips.html',
+    my $username = '<span class="current-user">'
+                 . $HTML::Mason::Commands::m->interp->apply_escapes($HTML::Mason::Commands::session{'CurrentUser'}->Name, 'h')
+                 . '</span>';
+    my $about_me = HTML::Mason::Commands::Menu()->child( 'preferences' =>
+        title        => loc('Logged in as [_1]', $username),
+        escape_title => 0,
+        path         => '/User/Summary.html?id=' . $HTML::Mason::Commands::session{CurrentUser}->id,
+        sort_order   => 99,
     );
-    $scrips->child( select => title => loc('Select'), path => "/Admin/Global/Scrips.html" );
-    $scrips->child( create => title => loc('Create'), path => "/Admin/Scrips/Create.html?Global=1" );
 
-    my $templates = $admin_global->child( templates =>
-        title       => loc('Templates'),
-        description => loc('Edit system templates'),
-        path        => '/Admin/Global/Templates.html',
-    );
-    $templates->child( select => title => loc('Select'), path => "/Admin/Global/Templates.html" );
-    $templates->child( create => title => loc('Create'), path => "/Admin/Global/Template.html?Create=1" );
 
-    my $cfadmin = $admin_global->child( 'custom-fields' =>
-        title       => loc('Custom Fields'),
-        description => loc('Modify global custom fields'),
-        path        => '/Admin/Global/CustomFields/index.html',
-    );
-    $cfadmin->child( users =>
-        title       => loc('Users'),
-        description => loc('Select custom fields for all users'),
-        path        => '/Admin/Global/CustomFields/Users.html',
-    );
-    $cfadmin->child( groups =>
-        title       => loc('Groups'),
-        description => loc('Select custom fields for all user groups'),
-        path        => '/Admin/Global/CustomFields/Groups.html',
-    );
-    $cfadmin->child( queues =>
-        title       => loc('Queues'),
-        description => loc('Select custom fields for all queues'),
-        path        => '/Admin/Global/CustomFields/Queues.html',
-    );
-    $cfadmin->child( tickets =>
-        title       => loc('Tickets'),
-        description => loc('Select custom fields for tickets in all queues'),
-        path        => '/Admin/Global/CustomFields/Queue-Tickets.html',
-    );
-    $cfadmin->child( transactions =>
-        title       => loc('Ticket Transactions'),
-        description => loc('Select custom fields for transactions on tickets in all queues'),
-        path        => '/Admin/Global/CustomFields/Queue-Transactions.html',
-    );
-    $cfadmin->child( 'custom-fields' =>
-        title       => loc('Articles'),
-        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',
-    );
+    if ( $HTML::Mason::Commands::session{'CurrentUser'}->UserObj
+         && $HTML::Mason::Commands::session{'CurrentUser'}->HasRight( Right => 'ModifySelf', Object => RT->System )) {
+        my $settings = $about_me->child( settings => title => loc('Settings'), path => '/Prefs/Other.html' );
+        $settings->child( options        => title => loc('Preferences'),        path => '/Prefs/Other.html' );
+        $settings->child( about_me       => title => loc('About me'),       path => '/Prefs/AboutMe.html' );
+        $settings->child( search_options => title => loc('Search options'), path => '/Prefs/SearchOptions.html' );
+        $settings->child( myrt           => title => loc('RT at a glance'), path => '/Prefs/MyRT.html' );
+        $settings->child( dashboards_in_menu =>
+            title => loc('Dashboards in menu'),
+            path  => '/Prefs/DashboardsInMenu.html',
+        );
+        $settings->child( queue_list    => title => loc('Queue list'),   path => '/Prefs/QueueList.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/' );
-    $class_admin->child( select =>
-        title       => loc('Select'),
-        description => loc('Modify and Create Classes'),
-        path        => '/Admin/Articles/Classes/',
-    );
-    $class_admin->child( create =>
-        title       => loc('Create'),
-        description => loc('Modify and Create Custom Fields for Articles'),
-        path        => '/Admin/Articles/Classes/Modify.html?Create=1',
-    );
+        my $search_menu = $settings->child( 'saved-searches' => title => loc('Saved Searches') );
+        my $searches = [ $HTML::Mason::Commands::m->comp( "/Search/Elements/SearchesForObject",
+                          Object => RT::System->new( $HTML::Mason::Commands::session{'CurrentUser'} )) ];
+        my $i = 0;
 
+        for my $search (@$searches) {
+            $search_menu->child( "search-" . $i++ =>
+                title => $search->[1],
+                path  => "/Prefs/Search.html?"
+                       . QueryString( name => ref( $search->[2] ) . '-' . $search->[2]->Id ),
+            );
 
-    my $cfs = $article_admin->child( 'custom-fields' =>
-        title => loc('Custom Fields'),
-        path  => '/Admin/CustomFields/index.html?'.$m->comp('/Elements/QueryString', Type => 'RT::Class-RT::Article'),
-    );
-    $cfs->child( select =>
-        title => loc('Select'),
-        path => '/Admin/CustomFields/index.html?'.$m->comp('/Elements/QueryString', Type => 'RT::Class-RT::Article'),
-    );
-    $cfs->child( create =>
-        title => loc('Create'),
-        path => '/Admin/CustomFields/Modify.html?'.$m->comp("/Elements/QueryString", Create=>1, LookupType=> "RT::Class-RT::Article" ),
-    );
+        }
+    }
+    if ( $HTML::Mason::Commands::session{'CurrentUser'}->Name
+         && (   !RT->Config->Get('WebRemoteUserAuth')
+              || RT->Config->Get('WebFallbackToRTLogin') )) {
+        $about_me->child( logout => title => loc('Logout'), path => '/NoAuth/Logout.html' );
+    }
+    if ( $request_path =~ m{^/Dashboards/(\d+)?}) {
+        if ( my $id = ( $1 || $HTML::Mason::Commands::DECODED_ARGS->{'id'} ) ) {
+            my $obj = RT::Dashboard->new( $HTML::Mason::Commands::session{'CurrentUser'} );
+            $obj->LoadById($id);
+            if ( $obj and $obj->id ) {
+                my $tabs = HTML::Mason::Commands::PageMenu();
+                $tabs->child( basics       => title => loc('Basics'),       path => "/Dashboards/Modify.html?id=" . $obj->id);
+                $tabs->child( content      => title => loc('Content'),      path => "/Dashboards/Queries.html?id=" . $obj->id);
+                $tabs->child( subscription => title => loc('Subscription'), path => "/Dashboards/Subscription.html?id=" . $obj->id)
+                    if $obj->CurrentUserCanSubscribe;
+                $tabs->child( show         => title => loc('Show'),         path => "/Dashboards/" . $obj->id . "/" . $obj->Name)
+            }
+        }
+    }
 
-    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" );
 
+    if ( $request_path =~ m{^/Ticket/} ) {
+        if ( ( $HTML::Mason::Commands::DECODED_ARGS->{'id'} || '' ) =~ /^(\d+)$/ ) {
+            my $id  = $1;
+            my $obj = RT::Ticket->new( $HTML::Mason::Commands::session{'CurrentUser'} );
+            $obj->Load($id);
 
-    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);
+            if ( $obj and $obj->id ) {
+                my $actions = HTML::Mason::Commands::PageMenu()->child( actions => title => loc('Actions'), sort_order  => 95 );
 
-    $admin_global->child( 'group-rights' =>
-        title       => loc('Group Rights'),
-        description => loc('Modify global group rights'),
-        path        => '/Admin/Global/GroupRights.html',
-    );
-    $admin_global->child( 'user-rights' =>
-        title       => loc('User Rights'),
-        description => loc('Modify global user rights'),
-        path        => '/Admin/Global/UserRights.html',
-    );
-    $admin_global->child( 'my-rt' =>
-        title       => loc('RT at a glance'),
-        description => loc('Modify the default "RT at a glance" view'),
-        path        => '/Admin/Global/MyRT.html',
-    );
-    $admin_global->child( 'dashboards-in-menu' =>
-        title       => loc('Dashboards in menu'),
-        description => loc('Customize dashboards in menu'),
-        path        => '/Admin/Global/DashboardsInMenu.html',
-    );
-    $admin_global->child( 'topics' =>
-        title       => loc('Topics'),
-        description => loc('Modify global article topics'),
-        path        => '/Admin/Global/Topics.html',
-    );
+                my %can = %{ $obj->CurrentUser->PrincipalObj->HasRights( Object => $obj ) };
+                $can{'_ModifyOwner'} = $obj->CurrentUserCanSetOwner();
+                my $can = sub {
+                    unless ($_[0] eq 'ExecuteCode') {
+                        return $can{$_[0]} || $can{'SuperUser'};
+                    } else {
+                        return !RT->Config->Get('DisallowExecuteCode')
+                            && ( $can{'ExecuteCode'} || $can{'SuperUser'} );
+                    }
+                };
 
-    my $admin_tools = $admin->child( tools =>
-        title       => loc('Tools'),
-        description => loc('Use other RT administrative tools'),
-        path        => '/Admin/Tools/',
-    );
-    $admin_tools->child( configuration =>
-        title       => loc('System Configuration'),
-        description => loc('Detailed information about your RT setup'),
-        path        => '/Admin/Tools/Configuration.html',
-    );
-    $admin_tools->child( theme =>
-        title       => loc('Theme'),
-        description => loc('Customize the look of your RT'),
-        path        => '/Admin/Tools/Theme.html',
-    );
-    if (RT->Config->Get('StatementLog')
-        && $session{'CurrentUser'}->HasRight( Right => 'SuperUser', Object => RT->System )) {
-       $admin_tools->child( 'sql-queries' =>
-           title       => loc('SQL Queries'),
-           description => loc('Browse the SQL queries made in this process'),
-           path        => '/Admin/Tools/Queries.html',
-       );
-    }
-    $admin_tools->child( shredder =>
-        title       => loc('Shredder'),
-        description => loc('Permanently wipeout data from RT'),
-        path        => '/Admin/Tools/Shredder',
-    );
+                my $tabs = HTML::Mason::Commands::PageMenu();
+                $tabs->child( bookmark => raw_html => $HTML::Mason::Commands::m->scomp( '/Ticket/Elements/Bookmark', id => $id ), sort_order => 98 );
 
-    if ( $request_path =~ m{^/Admin/(Queues|Users|Groups|CustomFields|CustomRoles)} ) {
-        my $type = $1;
-        my $tabs = PageMenu();
+                if ($can->('ModifyTicket')) {
+                    $tabs->child( timer => raw_html => $HTML::Mason::Commands::m->scomp( '/Ticket/Elements/PopupTimerLink', id => $id ), sort_order => 99 );
+                }
 
-        my %labels = (
-            Queues       => loc("Queues"),
-            Users        => loc("Users"),
-            Groups       => loc("Groups"),
-            CustomFields => loc("Custom Fields"),
-            CustomRoles  => loc("Custom Roles"),
-        );
+                $tabs->child( display => title => loc('Display'), path => "/Ticket/Display.html?id=" . $id );
+                $tabs->child( history => title => loc('History'), path => "/Ticket/History.html?id=" . $id );
 
-        my $section;
-        if ( $request_path =~ m|^/Admin/$type/?(?:index.html)?$|
-             || (    $request_path =~ m|^/Admin/$type/(?:Modify.html)$|
-                  && $DECODED_ARGS->{'Create'} )
-           )
-        {
-            $section = $tabs;
+                # comment out until we can do it for an individual custom field
+                #if ( $can->('ModifyTicket') || $can->('ModifyCustomField') ) {
+                $tabs->child( basics => title => loc('Basics'), path => "/Ticket/Modify.html?id=" . $id );
 
-        } else {
-            $section = $tabs->child( select => title => $labels{$type},
-                                     path => "/Admin/$type/" );
-        }
+                #}
 
-        $section->child( select => title => loc('Select'), path => "/Admin/$type/" );
-        $section->child( create => title => loc('Create'), path => "/Admin/$type/Modify.html?Create=1" );
-    }
+                if ( $can->('ModifyTicket') || $can->('_ModifyOwner') || $can->('Watch') || $can->('WatchAsAdminCc') ) {
+                    $tabs->child( people => title => loc('People'), path => "/Ticket/ModifyPeople.html?id=" . $id );
+                }
 
-    if ( $request_path =~ m{^/Admin/Queues} ) {
-        if ( $DECODED_ARGS->{'id'} && $DECODED_ARGS->{'id'} =~ /^\d+$/
-                ||
-              $DECODED_ARGS->{'Queue'} && $DECODED_ARGS->{'Queue'} =~ /^\d+$/
-                ) {
-            my $id = $DECODED_ARGS->{'Queue'} || $DECODED_ARGS->{'id'};
-            my $queue_obj = RT::Queue->new( $session{'CurrentUser'} );
-            $queue_obj->Load($id);
+                if ( $can->('ModifyTicket') ) {
+                    $tabs->child( dates => title => loc('Dates'), path => "/Ticket/ModifyDates.html?id=" . $id );
+                    $tabs->child( links => title => loc('Links'), path => "/Ticket/ModifyLinks.html?id=" . $id );
+                }
 
-            if ( $queue_obj and $queue_obj->id ) {
-                my $queue = PageMenu();
-                $queue->child( basics => title => loc('Basics'),   path => "/Admin/Queues/Modify.html?id=" . $id );
-                $queue->child( people => title => loc('Watchers'), path => "/Admin/Queues/People.html?id=" . $id );
+                #if ( $can->('ModifyTicket') || $can->('ModifyCustomField') || $can->('_ModifyOwner') ) {
+                $tabs->child( jumbo => title => loc('Jumbo'), path => "/Ticket/ModifyAll.html?id=" . $id );
+                #}
 
-                my $templates = $queue->child(templates => title => loc('Templates'), path => "/Admin/Queues/Templates.html?id=" . $id);
-                $templates->child( select => title => loc('Select'), path => "/Admin/Queues/Templates.html?id=".$id);
-                $templates->child( create => title => loc('Create'), path => "/Admin/Queues/Template.html?Create=1;Queue=".$id);
+                if ( RT->Config->Get('EnableReminders') ) {
+                    $tabs->child( reminders => title => loc('Reminders'), path => "/Ticket/Reminders.html?id=" . $id );
+                }
 
-                my $scrips = $queue->child( scrips => title => loc('Scrips'), path => "/Admin/Queues/Scrips.html?id=" . $id);
-                $scrips->child( select => title => loc('Select'), path => "/Admin/Queues/Scrips.html?id=" . $id );
-                $scrips->child( create => title => loc('Create'), path => "/Admin/Scrips/Create.html?Queue=" . $id);
+                if ( $can->('ModifyTicket') or $can->('ReplyToTicket') ) {
+                    $actions->child( reply => title => loc('Reply'), path => "/Ticket/Update.html?Action=Respond;id=" . $id );
+                }
 
-                my $cfs = $queue->child( 'custom-fields' => title => loc('Custom Fields') );
-                my $ticket_cfs = $cfs->child( 'tickets' => title => loc('Tickets'),
-                    path => '/Admin/Queues/CustomFields.html?SubType=RT::Ticket&id=' . $id );
+                if ( $can->('ModifyTicket') or $can->('CommentOnTicket') ) {
+                    $actions->child( comment => title => loc('Comment'), path => "/Ticket/Update.html?Action=Comment;id=" . $id );
+                }
 
-                my $txn_cfs = $cfs->child( 'transactions' => title => loc('Transactions'),
-                    path => '/Admin/Queues/CustomFields.html?SubType=RT::Ticket-RT::Transaction&id='.$id );
+                if ( $can->('ForwardMessage') ) {
+                    $actions->child( forward => title => loc('Forward'), path => "/Ticket/Forward.html?id=" . $id );
+                }
 
-                $queue->child( 'group-rights' => title => loc('Group Rights'), path => "/Admin/Queues/GroupRights.html?id=".$id );
-                $queue->child( 'user-rights' => title => loc('User Rights'), path => "/Admin/Queues/UserRights.html?id=" . $id );
-                $queue->child( 'history' => title => loc('History'), path => "/Admin/Queues/History.html?id=" . $id );
-                $queue->child( 'default-values' => title => loc('Default Values'), path => "/Admin/Queues/DefaultValues.html?id=" . $id );
+                my $hide_resolve_with_deps = RT->Config->Get('HideResolveActionsWithDependencies')
+                    && $obj->HasUnresolvedDependencies;
 
-                $m->callback( CallbackName => 'PrivilegedQueue', queue_id => $id, page_menu => $queue);
-            }
-        }
-    }
-    if ( $request_path =~ m{^(/Admin/Users|/User/(Summary|History)\.html)} and $admin->child("users") ) {
-        if ( $DECODED_ARGS->{'id'} && $DECODED_ARGS->{'id'} =~ /^\d+$/ ) {
-            my $id = $DECODED_ARGS->{'id'};
-            my $obj = RT::User->new( $session{'CurrentUser'} );
-            $obj->Load($id);
+                my $current   = $obj->Status;
+                my $lifecycle = $obj->LifecycleObj;
+                my $i         = 1;
+                foreach my $info ( $lifecycle->Actions($current) ) {
+                    my $next = $info->{'to'};
+                    next unless $lifecycle->IsTransition( $current => $next );
 
-            if ( $obj and $obj->id ) {
-                my $tabs = PageMenu();
-                $tabs->child( basics      => title => loc('Basics'),         path => "/Admin/Users/Modify.html?id=" . $id );
-                $tabs->child( memberships => title => loc('Memberships'),    path => "/Admin/Users/Memberships.html?id=" . $id );
-                $tabs->child( history     => title => loc('History'),        path => "/Admin/Users/History.html?id=" . $id );
-                $tabs->child( 'my-rt'     => title => loc('RT at a glance'), path => "/Admin/Users/MyRT.html?id=" . $id );
-                $tabs->child( 'dashboards-in-menu' =>
-                    title => loc('Dashboards in menu'),
-                    path  => '/Admin/Users/DashboardsInMenu.html?id=' . $id,
-                );
-                if ( RT->Config->Get('Crypt')->{'Enable'} ) {
-                    $tabs->child( keys    => title => loc('Private keys'),   path => "/Admin/Users/Keys.html?id=" . $id );
-                }
-                $tabs->child( 'summary'   => title => loc('User Summary'),   path => "/User/Summary.html?id=" . $id );
-            }
-        }
+                    my $check = $lifecycle->CheckRight( $current => $next );
+                    next unless $can->($check);
 
-    }
+                    next if $hide_resolve_with_deps
+                        && $lifecycle->IsInactive($next)
+                        && !$lifecycle->IsInactive($current);
 
-    if ( $request_path =~ m{^/Admin/Groups} ) {
-        if ( $DECODED_ARGS->{'id'} && $DECODED_ARGS->{'id'} =~ /^\d+$/ ) {
-            my $id = $DECODED_ARGS->{'id'};
-            my $obj = RT::Group->new( $session{'CurrentUser'} );
-            $obj->Load($id);
+                    my $action = $info->{'update'} || '';
+                    my $url = '/Ticket/';
+                    $url .= "Update.html?". QueryString(
+                        $action
+                            ? (Action        => $action)
+                            : (SubmitTicket  => 1, Status => $next),
+                        DefaultStatus => $next,
+                        id            => $id,
+                    );
+                    my $key = $info->{'label'} || ucfirst($next);
+                    $actions->child( $key => title => loc( $key ), path => $url);
+                }
 
-            if ( $obj and $obj->id ) {
-                my $tabs = PageMenu();
-                $tabs->child( basics         => title => loc('Basics'),       path => "/Admin/Groups/Modify.html?id=" . $obj->id );
-                $tabs->child( members        => title => loc('Members'),      path => "/Admin/Groups/Members.html?id=" . $obj->id );
-                $tabs->child( memberships    => title => loc('Memberships'),  path => "/Admin/Groups/Memberships.html?id=" . $obj->id );
-                $tabs->child( 'group-rights' => title => loc('Group Rights'), path => "/Admin/Groups/GroupRights.html?id=" . $obj->id );
-                $tabs->child( 'user-rights'  => title => loc('User Rights'),  path => "/Admin/Groups/UserRights.html?id=" . $obj->id );
-                $tabs->child( history        => title => loc('History'),      path => "/Admin/Groups/History.html?id=" . $obj->id );
-            }
-        }
-    }
+                my ($can_take, $tmsg) = $obj->CurrentUserCanSetOwner( Type => 'Take' );
+                my ($can_steal, $smsg) = $obj->CurrentUserCanSetOwner( Type => 'Steal' );
+                if ( $can_take ){
+                    $actions->child( take => title => loc('Take'), path => "/Ticket/Display.html?Action=Take;id=" . $id );
+                }
+                elsif ( $can_steal ){
+                    $actions->child( steal => title => loc('Steal'), path => "/Ticket/Display.html?Action=Steal;id=" . $id );
+                }
 
-    if ( $request_path =~ m{^/Admin/CustomFields/} ) {
-        if ( $DECODED_ARGS->{'id'} && $DECODED_ARGS->{'id'} =~ /^\d+$/ ) {
-            my $id = $DECODED_ARGS->{'id'};
-            my $obj = RT::CustomField->new( $session{'CurrentUser'} );
-            $obj->Load($id);
+                # TODO needs a "Can extract article into a class applied to this queue" check
+                $actions->child( 'extract-article' =>
+                    title => loc('Extract Article'),
+                    path  => "/Articles/Article/ExtractIntoClass.html?Ticket=".$obj->id,
+                ) if $HTML::Mason::Commands::session{CurrentUser}->HasRight( Right => 'ShowArticlesMenu', Object => RT->System );
 
-            if ( $obj and $obj->id ) {
-                my $tabs = PageMenu();
-                $tabs->child( basics           => title => loc('Basics'),       path => "/Admin/CustomFields/Modify.html?id=".$id );
-                $tabs->child( 'group-rights'   => title => loc('Group Rights'), path => "/Admin/CustomFields/GroupRights.html?id=" . $id );
-                $tabs->child( 'user-rights'    => title => loc('User Rights'),  path => "/Admin/CustomFields/UserRights.html?id=" . $id );
-                unless ( $obj->IsOnlyGlobal ) {
-                    $tabs->child( 'applies-to' => title => loc('Applies to'),   path => "/Admin/CustomFields/Objects.html?id=" . $id );
-                }
-            }
-        }
-    }
+                if ( defined $HTML::Mason::Commands::session{"tickets"} ) {
+                    # we have to update session data if we get new ItemMap
+                    my $updatesession = 1 unless ( $HTML::Mason::Commands::session{"tickets"}->{'item_map'} );
 
-    if ( $request_path =~ m{^/Admin/CustomRoles} ) {
-        if ( $DECODED_ARGS->{'id'} && $DECODED_ARGS->{'id'} =~ /^\d+$/ ) {
-            my $id = $DECODED_ARGS->{'id'};
-            my $obj = RT::CustomRole->new( $session{'CurrentUser'} );
-            $obj->Load($id);
+                    my $item_map = $HTML::Mason::Commands::session{"tickets"}->ItemMap;
 
-            if ( $obj and $obj->id ) {
-                my $tabs = PageMenu();
-                $tabs->child( basics       => title => loc('Basics'),       path => "/Admin/CustomRoles/Modify.html?id=".$id );
-                $tabs->child( 'applies-to' => title => loc('Applies to'),   path => "/Admin/CustomRoles/Objects.html?id=" . $id );
+                    if ($updatesession) {
+                        $HTML::Mason::Commands::session{"tickets"}->PrepForSerialization();
+                    }
+
+                    my $search = HTML::Mason::Commands::Menu()->child('search')->child('tickets');
+                    # Don't display prev links if we're on the first ticket
+                    if ( $item_map->{$id}->{prev} ) {
+                        $search->child( first =>
+                            title => '<< ' . loc('First'), class => "nav", path => "/Ticket/Display.html?id=" . $item_map->{first});
+                        $search->child( prev =>
+                            title => '< ' . loc('Prev'),   class => "nav", path => "/Ticket/Display.html?id=" . $item_map->{$id}->{prev});
+                    }
+                    # Don't display next links if we're on the last ticket
+                    if ( $item_map->{$id}->{next} ) {
+                        $search->child( next =>
+                            title => loc('Next') . ' >',  class => "nav", path => "/Ticket/Display.html?id=" . $item_map->{$id}->{next});
+                        if ( $item_map->{last} ) {
+                            $search->child( last =>
+                                title => loc('Last') . ' >>', class => "nav", path => "/Ticket/Display.html?id=" . $item_map->{last});
+                        }
+                    }
+                }
             }
         }
     }
 
-    if ( $request_path =~ m{^/Admin/Scrips/} ) {
-        if ( $m->request_args->{'id'} && $m->request_args->{'id'} =~ /^\d+$/ ) {
-            my $id = $m->request_args->{'id'};
-            my $obj = RT::Scrip->new( $session{'CurrentUser'} );
-            $obj->Load($id);
+    if (
+        (
+               $request_path =~ m{^/(?:Ticket|Search)/}
+            && $request_path !~ m{^/Search/Simple\.html}
+        )
+        || (   $request_path =~ m{^/Search/Simple\.html}
+            && $HTML::Mason::Commands::DECODED_ARGS->{'q'} )
+      )
+    {
+        my $search = HTML::Mason::Commands::Menu()->child('search')->child('tickets');
+        my $args      = '';
+        my $has_query = '';
+        my $current_search = $HTML::Mason::Commands::session{"CurrentSearchHash"} || {};
+        my $search_id = $HTML::Mason::Commands::DECODED_ARGS->{'SavedSearchLoad'} || $HTML::Mason::Commands::DECODED_ARGS->{'SavedSearchId'} || $current_search->{'SearchId'} || '';
+        my $chart_id = $HTML::Mason::Commands::DECODED_ARGS->{'SavedChartSearchId'} || $current_search->{SavedChartSearchId};
 
-            my $tabs = PageMenu();
+        $has_query = 1 if ( $HTML::Mason::Commands::DECODED_ARGS->{'Query'} or $current_search->{'Query'} );
 
-            my ( $admin_cat, $create_path_arg, $from_query_param );
-            my $from_arg = $DECODED_ARGS->{'From'} || q{};
-            my ($from_queue) = $from_arg =~ /^(\d+)$/;
-            if ( $from_queue ) {
-                $admin_cat = "Queues/Scrips.html?id=$from_queue";
-                $create_path_arg = "?Queue=$from_queue";
-                $from_query_param = "&From=$from_queue";
-            }
-            elsif ( $from_arg eq 'Global' ) {
-                $admin_cat = 'Global/Scrips.html';
-                $create_path_arg = '?Global=1';
-                $from_query_param = '&From=Global';
+        my %query_args;
+        my %fallback_query_args = (
+            SavedSearchId => ( $search_id eq 'new' ) ? undef : $search_id,
+            SavedChartSearchId => $chart_id,
+            (
+                map {
+                    my $p = $_;
+                    $p => $HTML::Mason::Commands::DECODED_ARGS->{$p} || $current_search->{$p}
+                } qw(Query Format OrderBy Order Page)
+            ),
+            RowsPerPage => (
+                defined $HTML::Mason::Commands::DECODED_ARGS->{'RowsPerPage'}
+                ? $HTML::Mason::Commands::DECODED_ARGS->{'RowsPerPage'}
+                : $current_search->{'RowsPerPage'}
+            ),
+        );
+
+        if ($query_string) {
+            $args = '?' . $query_string;
+        }
+        else {
+            my %final_query_args = ();
+            # key => callback to avoid unnecessary work
+
+            for my $param (keys %fallback_query_args) {
+                $final_query_args{$param} = defined($query_args->{$param})
+                                          ? $query_args->{$param}
+                                          : $fallback_query_args{$param};
             }
-            else {
-                $admin_cat = 'Scrips';
-                $from_query_param = $create_path_arg = q{};
+
+            for my $field (qw(Order OrderBy)) {
+                if ( ref( $final_query_args{$field} ) eq 'ARRAY' ) {
+                    $final_query_args{$field} = join( "|", @{ $final_query_args{$field} } );
+                } elsif (not defined $final_query_args{$field}) {
+                    delete $final_query_args{$field};
+                }
+                else {
+                    $final_query_args{$field} ||= '';
+                }
             }
-            my $scrips = $tabs->child( scrips => title => loc('Scrips'), path => "/Admin/${admin_cat}" );
-            $scrips->child( select => title => loc('Select'), path => "/Admin/${admin_cat}" );
-            $scrips->child( create => title => loc('Create'), path => "/Admin/Scrips/Create.html${create_path_arg}" );
 
-            $tabs->child( basics => title => loc('Basics') => path => "/Admin/Scrips/Modify.html?id=" . $id . $from_query_param );
-            $tabs->child( 'applies-to' => title => loc('Applies to'), path => "/Admin/Scrips/Objects.html?id=" . $id . $from_query_param );
+            $args = '?' . QueryString(%final_query_args);
         }
-        elsif ( $request_path =~ m{^/Admin/Scrips/(index\.html)?$} ) {
-            PageMenu->child( select => title => loc('Select') => path => "/Admin/Scrips/" );
-            PageMenu->child( create => title => loc('Create') => path => "/Admin/Scrips/Create.html" );
+
+        my $current_search_menu;
+        if ( $request_path =~ m{^/Ticket} ) {
+            $current_search_menu = $search->child( current_search => title => loc('Current Search') );
+            $current_search_menu->path("/Search/Results.html$args") if $has_query;
+        } else {
+            $current_search_menu = HTML::Mason::Commands::PageMenu();
         }
-        elsif ( $request_path =~ m{^/Admin/Scrips/Create\.html$} ) {
-            my ($queue) = $DECODED_ARGS->{'Queue'} && $DECODED_ARGS->{'Queue'} =~ /^(\d+)$/;
-            my $global_arg = $DECODED_ARGS->{'Global'};
-            if ($queue) {
-                PageMenu->child( select => title => loc('Select') => path => "/Admin/Queues/Scrips.html?id=$queue" );
-                PageMenu->child( create => title => loc('Create') => path => "/Admin/Scrips/Create.html?Queue=$queue" );
-            } elsif ($global_arg) {
-                PageMenu->child( select => title => loc('Select') => path => "/Admin/Global/Scrips.html" );
-                PageMenu->child( create => title => loc('Create') => path => "/Admin/Scrips/Create.html?Global=1" );
-            } else {
-                PageMenu->child( select => title => loc('Select') => path => "/Admin/Scrips" );
-                PageMenu->child( create => title => loc('Create') => path => "/Admin/Scrips/Create.html" );
+
+        $current_search_menu->child( edit_search =>
+            title => loc('Edit Search'), path => "/Search/Build.html" . ( ($has_query) ? $args : '' ) );
+        $current_search_menu->child( advanced =>
+            title => loc('Advanced'),    path => "/Search/Edit.html$args" );
+        if ($has_query) {
+            $current_search_menu->child( results => title => loc('Show Results'), path => "/Search/Results.html$args" );
+        }
+
+        if ( $has_query ) {
+            $current_search_menu->child( bulk  => title => loc('Bulk Update'), path => "/Search/Bulk.html$args" );
+            $current_search_menu->child( chart => title => loc('Chart'),       path => "/Search/Chart.html$args" );
+
+            my $more = $current_search_menu->child( more => title => loc('Feeds') );
+
+            $more->child( spreadsheet => title => loc('Spreadsheet'), path => "/Search/Results.tsv$args" );
+
+            my %rss_data = map {
+                $_ => $query_args->{$_} || $fallback_query_args{$_} || '' }
+                    qw(Query Order OrderBy);
+            my $RSSQueryString = "?"
+                . QueryString( Query   => $rss_data{Query},
+                                   Order   => $rss_data{Order},
+                                   OrderBy => $rss_data{OrderBy}
+                                 );
+            my $RSSPath = join '/', map $HTML::Mason::Commands::m->interp->apply_escapes( $_, 'u' ),
+                $HTML::Mason::Commands::session{'CurrentUser'}->UserObj->Name,
+                $HTML::Mason::Commands::session{'CurrentUser'}
+                ->UserObj->GenerateAuthString(   $rss_data{Query}
+                                               . $rss_data{Order}
+                                               . $rss_data{OrderBy} );
+
+            $more->child( rss => title => loc('RSS'), path => "/NoAuth/rss/$RSSPath/$RSSQueryString");
+            my $ical_path = join '/', map $HTML::Mason::Commands::m->interp->apply_escapes($_, 'u'),
+                $HTML::Mason::Commands::session{'CurrentUser'}->UserObj->Name,
+                $HTML::Mason::Commands::session{'CurrentUser'}->UserObj->GenerateAuthString( $rss_data{Query} ),
+                $rss_data{Query};
+            $more->child( ical => title => loc('iCal'), path => '/NoAuth/iCal/'.$ical_path);
+
+            if ($request_path =~ m{^/Search/Results.html}
+                &&                        #XXX TODO better abstraction
+                $HTML::Mason::Commands::session{'CurrentUser'}->HasRight( Right => 'SuperUser', Object => RT->System )) {
+                my $shred_args = QueryString(
+                    Search          => 1,
+                    Plugin          => 'Tickets',
+                    'Tickets:query' => $rss_data{'Query'},
+                    'Tickets:limit' => $query_args->{'Rows'},
+                );
+
+                $more->child( shredder => title => loc('Shredder'), path => '/Admin/Tools/Shredder/?' . $shred_args);
             }
+
         }
     }
 
-    if ( $request_path =~ m{^/Admin/Global/Scrips\.html} ) {
-        my $tabs = PageMenu();
-        $tabs->child( select => title => loc('Select'), path => "/Admin/Global/Scrips.html" );
-        $tabs->child( create => title => loc('Create'), path => "/Admin/Scrips/Create.html?Global=1" );
-    }
+    if ( $request_path =~ m{^/Article/} ) {
+        if ( $HTML::Mason::Commands::DECODED_ARGS->{'id'} && $HTML::Mason::Commands::DECODED_ARGS->{'id'} =~ /^\d+$/ ) {
+            my $id = $HTML::Mason::Commands::DECODED_ARGS->{'id'};
+            my $tabs = HTML::Mason::Commands::PageMenu();
 
-    if ( $request_path =~ m{^/Admin/Global/Templates?\.html} ) {
-        my $tabs = PageMenu();
-        $tabs->child( select => title => loc('Select'), path => "/Admin/Global/Templates.html" );
-        $tabs->child( create => title => loc('Create'), path => "/Admin/Global/Template.html?Create=1" );
+            $tabs->child( display => title => loc('Display'), path => "/Articles/Article/Display.html?id=".$id );
+            $tabs->child( history => title => loc('History'), path => "/Articles/Article/History.html?id=".$id );
+            $tabs->child( modify  => title => loc('Modify'),  path => "/Articles/Article/Edit.html?id=".$id );
+        }
     }
 
-    if ( $request_path =~ m{^/Admin/Articles/Classes/} ) {
-        my $tabs = PageMenu();
-        if ( my $id = $DECODED_ARGS->{'id'} ) {
-            my $obj = RT::Class->new( $session{'CurrentUser'} );
+    if ( $request_path =~ m{^/Articles/} ) {
+        HTML::Mason::Commands::PageWidgets()->child( article_search => raw_html => $HTML::Mason::Commands::m->scomp('/Articles/Elements/GotoArticle') );
+        HTML::Mason::Commands::PageWidgets()->delete('create_ticket');
+        HTML::Mason::Commands::PageWidgets()->delete('simple_search');
+
+        my $tabs = HTML::Mason::Commands::PageMenu();
+        $tabs->child( search => title => loc("Search"),       path => "/Articles/Article/Search.html" );
+        $tabs->child( create => title => loc("New Article" ), path => "/Articles/Article/PreCreate.html" );
+        if ( $request_path =~ m{^/Articles/Article/} and ( $HTML::Mason::Commands::DECODED_ARGS->{'id'} || '' ) =~ /^(\d+)$/ ) {
+            my $id  = $1;
+            my $obj = RT::Article->new( $HTML::Mason::Commands::session{'CurrentUser'} );
             $obj->Load($id);
 
             if ( $obj and $obj->id ) {
-                my $section = $tabs->child( select => title => loc("Classes"), path => "/Admin/Articles/Classes/" );
-                $section->child( select => title => loc('Select'), path => "/Admin/Articles/Classes/" );
-                $section->child( create => title => loc('Create'), path => "/Admin/Articles/Classes/Modify.html?Create=1" );
+                $tabs->child( display => title => loc("Display"), path => "/Articles/Article/Display.html?id=" . $id );
+                $tabs->child( history => title => loc('History'), path => '/Articles/Article/History.html?id=' . $id );
 
-                $tabs->child( basics          => title => loc('Basics'),        path => "/Admin/Articles/Classes/Modify.html?id=".$id );
-                $tabs->child( topics          => title => loc('Topics'),        path => "/Admin/Articles/Classes/Topics.html?id=".$id );
-                $tabs->child( 'custom-fields' => title => loc('Custom Fields'), path => "/Admin/Articles/Classes/CustomFields.html?id=".$id );
-                $tabs->child( 'group-rights'  => title => loc('Group Rights'),  path => "/Admin/Articles/Classes/GroupRights.html?id=".$id );
-                $tabs->child( 'user-rights'   => title => loc('User Rights'),   path => "/Admin/Articles/Classes/UserRights.html?id=".$id );
-                $tabs->child( 'applies-to'    => title => loc('Applies to'),    path => "/Admin/Articles/Classes/Objects.html?id=$id" );
+                if ( $obj->CurrentUserHasRight('ModifyArticle') ) {
+                    $tabs->child(modify => title => loc('Modify'), path => '/Articles/Article/Edit.html?id=' . $id );
+                }
             }
-        } else {
-            $tabs->child( select => title => loc('Select'), path => "/Admin/Articles/Classes/" );
-            $tabs->child( create => title => loc('Create'), path => "/Admin/Articles/Classes/Modify.html?Create=1" );
         }
-    }
-};
-
-my $build_main_nav = sub {
 
-    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'}) {
-        my $dashboards_in_menu = $session{CurrentUser}->UserObj->Preferences(
-            'DashboardsInMenu',
-            {},
-        );
+    if ($request_path =~ m{^/Asset/} and $HTML::Mason::Commands::DECODED_ARGS->{id} and $HTML::Mason::Commands::DECODED_ARGS->{id} !~ /\D/) {
+        my $page  = HTML::Mason::Commands::PageMenu();
+        my $id    = $HTML::Mason::Commands::DECODED_ARGS->{id};
+        my $asset = RT::Asset->new( $HTML::Mason::Commands::session{CurrentUser} );
+        $asset->Load($id);
 
-        unless ($dashboards_in_menu->{dashboards}) {
-            my ($default_dashboards) =
-                RT::System->new( $session{'CurrentUser'} )
-                    ->Attributes
-                    ->Named('DashboardsInMenu');
-            if ($default_dashboards) {
-                $dashboards_in_menu = $default_dashboards->Content;
+        if ($asset->id) {
+            $page->child("display",     title => HTML::Mason::Commands::loc("Display"),        path => "/Asset/Display.html?id=$id");
+            $page->child("history",     title => HTML::Mason::Commands::loc("History"),        path => "/Asset/History.html?id=$id");
+            $page->child("basics",      title => HTML::Mason::Commands::loc("Basics"),         path => "/Asset/Modify.html?id=$id");
+            $page->child("links",       title => HTML::Mason::Commands::loc("Links"),          path => "/Asset/ModifyLinks.html?id=$id");
+            $page->child("people",      title => HTML::Mason::Commands::loc("People"),         path => "/Asset/ModifyPeople.html?id=$id");
+            $page->child("dates",       title => HTML::Mason::Commands::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   => HTML::Mason::Commands::loc($grouping),
+                    path    => "/Asset/ModifyCFs.html?id=$id;Grouping=" . $HTML::Mason::Commands::m->interp->apply_escapes($grouping, 'u'),
+                );
             }
-        }
 
-        $session{'dashboards_in_menu'} = $dashboards_in_menu->{dashboards} || [];
-    }
+            my $actions = $page->child("actions", title => HTML::Mason::Commands::loc("Actions"));
+            $actions->child("create-linked-ticket", title => HTML::Mason::Commands::loc("Create linked ticket"), path => "/Asset/CreateLinkedTicket.html?Asset=$id");
 
-    my @dashboards;
-    for my $id ( @{$session{'dashboards_in_menu'}} ) {
-        my $dash = RT::Dashboard->new( $session{CurrentUser} );
-        my ( $status, $msg ) = $dash->LoadById($id);
-        if ( $status ) {
-            push @dashboards, $dash;
-        } else {
-            $RT::Logger->warning( "Failed to load dashboard $id: $msg" );
-        }
-    }
+            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 $dashes = Menu()->child('home');
-    if (@dashboards) {
-        for my $dash (@dashboards) {
-            $home->child( 'dashboard-' . $dash->id,
-                title => $dash->Name,
-                path  => '/Dashboards/' . $dash->id . '/' . $dash->Name
+                my $check = $lifecycle->CheckRight( $status => $next );
+                next unless $asset->CurrentUserHasRight($check);
+
+                my $label = $action->{'label'} || ucfirst($next);
+                $actions->child(
+                    $label,
+                    title   => HTML::Mason::Commands::loc($label),
+                    path    => "/Asset/Modify.html?id=$id;Update=1;DisplayAfter=1;Status="
+                                . $HTML::Mason::Commands::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 $page  = HTML::Mason::Commands::PageMenu();
+        my %search = map @{$_},
+            grep defined $_->[1] && length $_->[1],
+            map {ref $HTML::Mason::Commands::DECODED_ARGS->{$_} ? [$_, $HTML::Mason::Commands::DECODED_ARGS->{$_}[0]] : [$_, $HTML::Mason::Commands::DECODED_ARGS->{$_}] }
+            grep /^(?:q|SearchAssets|!?(Name|Description|Catalog|Status|Role\..+|CF\..+)|Order(?:By)?|Page)$/,
+            keys %$HTML::Mason::Commands::DECODED_ARGS;
+        if ( $request_path =~ /Bulk/) {
+            $page->child('search',
+                title => loc('Show Results'),
+                path => '/Asset/Search/?' . (keys %search ? QueryString(%search) : ''),
+            );
+        } else {
+            $page->child('bulk',
+                title => loc('Bulk Update'),
+                path => '/Asset/Search/Bulk.html?' . (keys %search ? QueryString(%search) : ''),
             );
         }
-    }
-    $dashes->child( edit => title => loc('Update This Menu'), path => 'Prefs/DashboardsInMenu.html' );
-    $dashes->child( more => title => loc('All Dashboards'),   path => 'Dashboards/index.html' );
-    my $dashboard = RT::Dashboard->new( $session{CurrentUser} );
-    if ( $dashboard->CurrentUserCanCreateAny ) {
-        $dashes->child('dashboard_create' => title => loc('New Dashboard'), path => "/Dashboards/Modify.html?Create=1" );
-    }
+        $page->child('csv',
+            title => loc('Download Spreadsheet'),
+            path  => '/Asset/Search/Results.tsv?' . (keys %search ? QueryString(%search) : ''),
+        );
+    } elsif ($request_path =~ m{^/Admin/Global/CustomFields/Catalog-Assets\.html$}) {
+        my $page  = HTML::Mason::Commands::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 $HTML::Mason::Commands::DECODED_ARGS->{'Type'} and $HTML::Mason::Commands::DECODED_ARGS->{'Type'} eq RT::Asset->CustomFieldLookupType) {
+        my $page  = HTML::Mason::Commands::PageMenu();
+        $page->child("create")->path( $page->child("create")->path . "&LookupType=" . RT::Asset->CustomFieldLookupType );
+    } elsif ($request_path =~ m{^/Admin/Assets/Catalogs/}) {
+        my $page  = HTML::Mason::Commands::PageMenu();
+        my $actions = $request_path =~ m{/((index|Create)\.html)?$}
+            ? $page
+            : $page->child("catalogs", title => loc("Catalogs"), path => "/Admin/Assets/Catalogs/");
 
-    my $search = Menu->child( search => title => loc('Search'), path => '/Search/Simple.html' );
+        $actions->child("select", title => loc("Select"), path => "/Admin/Assets/Catalogs/");
+        $actions->child("create", title => loc("Create"), path => "/Admin/Assets/Catalogs/Create.html");
 
-    my $tickets = $search->child( tickets => title => loc('Tickets'), path => '/Search/Build.html' );
-    $tickets->child( simple => title => loc('Simple Search'), path => "/Search/Simple.html" );
-    $tickets->child( new    => title => loc('New Search'),    path => "/Search/Build.html?NewQuery=1" );
+        my $catalog = RT::Catalog->new( $HTML::Mason::Commands::session{CurrentUser} );
+        $catalog->Load($HTML::Mason::Commands::DECODED_ARGS->{id}) if $HTML::Mason::Commands::DECODED_ARGS->{id};
 
-    $search->child( articles => title => loc('Articles'),   path => "/Articles/Article/Search.html" )
-        if $session{CurrentUser}->HasRight( Right => 'ShowArticlesMenu', Object => RT->System );
+        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");
 
-    $search->child( users => title => loc('Users'),   path => "/User/Search.html" );
+            $page->child("cfs", title => loc("Asset Custom Fields"), path => "/Admin/Assets/Catalogs/CustomFields.html?$query");
 
-    $search->child( assets => title => loc("Assets"), path => "/Asset/Search/" )
-        if $session{CurrentUser}->HasRight( Right => 'ShowAssetsMenu', Object => RT->System );
+            $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");
+        }
+    }
 
-    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( topics   => title => loc('Topics'),   path => "/Articles/Topics.html" );
-        $articles->child( create   => title => loc('Create'),   path => "/Articles/Article/PreCreate.html" );
-        $articles->child( search   => title => loc('Search'),   path => "/Articles/Article/Search.html" );
+    if ( $request_path =~ m{^/User/(Summary|History)\.html} ) {
+        if (HTML::Mason::Commands::PageMenu()->child('summary')) {
+            # Already set up from having AdminUser and ShowConfigTab;
+            # but rename "Basics" to "Edit" in this context
+            HTML::Mason::Commands::PageMenu()->child( 'basics' )->title( loc('Edit') );
+        } elsif ( $HTML::Mason::Commands::session{'CurrentUser'}->HasRight( Object => $RT::System, Right => 'ShowUserHistory' ) ) {
+            HTML::Mason::Commands::PageMenu()->child( display => title => loc('Summary'), path => '/User/Summary.html?id=' . $HTML::Mason::Commands::DECODED_ARGS->{'id'} );
+            HTML::Mason::Commands::PageMenu()->child( history => title => loc('History'), path => '/User/History.html?id=' . $HTML::Mason::Commands::DECODED_ARGS->{'id'} );
+        }
     }
 
-    if ($session{CurrentUser}->HasRight( Right => 'ShowAssetsMenu', Object => RT->System )) {
-        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/" );
+    if ( $request_path =~ /^\/(?:index.html|$)/ ) {
+        HTML::Mason::Commands::PageMenu()->child( edit => title => loc('Edit'), path => '/Prefs/MyRT.html' );
     }
 
-    my $tools = Menu->child( tools => title => loc('Tools'), path => '/Tools/index.html' );
+    # due to historical reasons of always having been in /Elements/Tabs
+    $HTML::Mason::Commands::m->callback( CallbackName => 'Privileged', Path => $request_path, CallbackPage => '/Elements/Tabs' );
+}
 
-    $tools->child( my_day =>
-        title       => loc('My Day'),
-        description => loc('Easy updating of your open tickets'),
-        path        => '/Tools/MyDay.html',
-    );
+sub _BuildAdminMenu {
+    my $request_path = shift;
+    my $top = shift;
 
-    if ( RT->Config->Get('EnableReminders') ) {
-        $tools->child( my_reminders =>
-            title       => loc('My Reminders'),
-            description => loc('Easy viewing of your reminders'),
-            path        => '/Tools/MyReminders.html',
+    my $admin = $top->child( admin => title => loc('Admin'), path => '/Admin/' );
+    if ( $HTML::Mason::Commands::session{'CurrentUser'}->HasRight( Object => RT->System, Right => 'AdminUsers' ) ) {
+        my $users = $admin->child( users =>
+            title       => loc('Users'),
+            description => loc('Manage users and passwords'),
+            path        => '/Admin/Users/',
         );
+        $users->child( select => title => loc('Select'), path => "/Admin/Users/" );
+        $users->child( create => title => loc('Create'), path => "/Admin/Users/Modify.html?Create=1" );
     }
+    my $groups = $admin->child( groups =>
+        title       => loc('Groups'),
+        description => loc('Manage groups and group membership'),
+        path        => '/Admin/Groups/',
+    );
+    $groups->child( select => title => loc('Select'), path => "/Admin/Groups/" );
+    $groups->child( create => title => loc('Create'), path => "/Admin/Groups/Modify.html?Create=1" );
 
-    if ( $session{'CurrentUser'}->HasRight( Right => 'ShowApprovalsTab', Object => RT->System ) ) {
-        $tools->child( approval =>
-            title       => loc('Approval'),
-            description => loc('My Approvals'),
-            path        => '/Approvals/',
+    my $queues = $admin->child( queues =>
+        title       => loc('Queues'),
+        description => loc('Manage queues and queue-specific properties'),
+        path        => '/Admin/Queues/',
+    );
+    $queues->child( select => title => loc('Select'), path => "/Admin/Queues/" );
+    $queues->child( create => title => loc('Create'), path => "/Admin/Queues/Modify.html?Create=1" );
+
+    if ( $HTML::Mason::Commands::session{'CurrentUser'}->HasRight( Object => RT->System, Right => 'AdminCustomField' ) ) {
+        my $cfs = $admin->child( 'custom-fields' =>
+            title       => loc('Custom Fields'),
+            description => loc('Manage custom fields and custom field values'),
+            path        => '/Admin/CustomFields/',
         );
+        $cfs->child( select => title => loc('Select'), path => "/Admin/CustomFields/" );
+        $cfs->child( create => title => loc('Create'), path => "/Admin/CustomFields/Modify.html?Create=1" );
     }
 
-    if ( $session{'CurrentUser'}->HasRight( Right => 'ShowConfigTab', Object => RT->System ) )
-    {
-        $build_admin_menu->(Menu());
+    if ( $HTML::Mason::Commands::session{'CurrentUser'}->HasRight( Object => RT->System, Right => 'AdminCustomRoles' ) ) {
+        my $roles = $admin->child( 'custom-roles' =>
+            title       => loc('Custom Roles'),
+            description => loc('Manage custom roles'),
+            path        => '/Admin/CustomRoles/',
+        );
+        $roles->child( select => title => loc('Select'), path => "/Admin/CustomRoles/" );
+        $roles->child( create => title => loc('Create'), path => "/Admin/CustomRoles/Modify.html?Create=1" );
     }
 
-    my $username = '<span class="current-user">'
-                 . $m->interp->apply_escapes($session{'CurrentUser'}->Name, 'h')
-                 . '</span>';
-    my $about_me = Menu->child( 'preferences' =>
-        title        => loc('Logged in as [_1]', $username),
-        escape_title => 0,
-        path         => '/User/Summary.html?id=' . $session{CurrentUser}->id,
-        sort_order   => 99,
-    );
-
-
-    if ( $session{'CurrentUser'}->UserObj
-         && $session{'CurrentUser'}->HasRight( Right => 'ModifySelf', Object => RT->System )) {
-        my $settings = $about_me->child( settings => title => loc('Settings'), path => '/Prefs/Other.html' );
-        $settings->child( options        => title => loc('Preferences'),        path => '/Prefs/Other.html' );
-        $settings->child( about_me       => title => loc('About me'),       path => '/Prefs/AboutMe.html' );
-        $settings->child( search_options => title => loc('Search options'), path => '/Prefs/SearchOptions.html' );
-        $settings->child( myrt           => title => loc('RT at a glance'), path => '/Prefs/MyRT.html' );
-        $settings->child( dashboards_in_menu =>
-            title => loc('Dashboards in menu'),
-            path  => '/Prefs/DashboardsInMenu.html',
+    if ( $HTML::Mason::Commands::session{'CurrentUser'}->HasRight( Object => RT->System, Right => 'ModifyScrips' ) ) {
+        my $scrips = $admin->child( 'scrips' =>
+            title       => loc('Scrips'),
+            description => loc('Manage scrips'),
+            path        => '/Admin/Scrips/',
         );
-        $settings->child( queue_list    => title => loc('Queue list'),   path => '/Prefs/QueueList.html' );
-
-        my $search_menu = $settings->child( 'saved-searches' => title => loc('Saved Searches') );
-        my $searches = [ $m->comp( "/Search/Elements/SearchesForObject",
-                          Object => RT::System->new( $session{'CurrentUser'} )) ];
-        my $i = 0;
-
-        for my $search (@$searches) {
-            $search_menu->child( "search-" . $i++ =>
-                title => $search->[1],
-                path  => "/Prefs/Search.html?"
-                       . $query_string->( name => ref( $search->[2] ) . '-' . $search->[2]->Id ),
-            );
-
-        }
-    }
-    if ( $session{'CurrentUser'}->Name
-         && (   !RT->Config->Get('WebRemoteUserAuth')
-              || RT->Config->Get('WebFallbackToRTLogin') )) {
-        $about_me->child( logout => title => loc('Logout'), path => '/NoAuth/Logout.html' );
-    }
-    if ( $request_path =~ m{^/Dashboards/(\d+)?}) {
-        if ( my $id = ( $1 || $DECODED_ARGS->{'id'} ) ) {
-            my $obj = RT::Dashboard->new( $session{'CurrentUser'} );
-            $obj->LoadById($id);
-            if ( $obj and $obj->id ) {
-                my $tabs = PageMenu;
-                $tabs->child( basics       => title => loc('Basics'),       path => "/Dashboards/Modify.html?id=" . $obj->id);
-                $tabs->child( content      => title => loc('Content'),      path => "/Dashboards/Queries.html?id=" . $obj->id);
-                $tabs->child( subscription => title => loc('Subscription'), path => "/Dashboards/Subscription.html?id=" . $obj->id)
-                    if $obj->CurrentUserCanSubscribe;
-                $tabs->child( show         => title => loc('Show'),         path => "/Dashboards/" . $obj->id . "/" . $obj->Name)
-            }
-        }
+        $scrips->child( select => title => loc('Select'), path => "/Admin/Scrips/" );
+        $scrips->child( create => title => loc('Create'), path => "/Admin/Scrips/Create.html" );
     }
 
+    my $admin_global = $admin->child( global =>
+        title       => loc('Global'),
+        description => loc('Manage properties and configuration which apply to all queues'),
+        path        => '/Admin/Global/',
+    );
 
-    if ( $request_path =~ m{^/Ticket/} ) {
-        if ( ( $DECODED_ARGS->{'id'} || '' ) =~ /^(\d+)$/ ) {
-            my $id  = $1;
-            my $obj = RT::Ticket->new( $session{'CurrentUser'} );
-            $obj->Load($id);
-
-            if ( $obj and $obj->id ) {
-                my $actions = PageMenu()->child( actions => title => loc('Actions'), sort_order  => 95 );
-
-                my %can = %{ $obj->CurrentUser->PrincipalObj->HasRights( Object => $obj ) };
-                $can{'_ModifyOwner'} = $obj->CurrentUserCanSetOwner();
-                my $can = sub {
-                    unless ($_[0] eq 'ExecuteCode') {
-                        return $can{$_[0]} || $can{'SuperUser'};
-                    } else {
-                        return !RT->Config->Get('DisallowExecuteCode')
-                            && ( $can{'ExecuteCode'} || $can{'SuperUser'} );
-                    }
-                };
-
-                my $tabs = PageMenu();
-                $tabs->child( bookmark => raw_html => $m->scomp( '/Ticket/Elements/Bookmark', id => $id ), sort_order => 98 );
-
-                if ($can->('ModifyTicket')) {
-                    $tabs->child( timer => raw_html => $m->scomp( '/Ticket/Elements/PopupTimerLink', id => $id ), sort_order => 99 );
-                }
-
-                $tabs->child( display => title => loc('Display'), path => "/Ticket/Display.html?id=" . $id );
-                $tabs->child( history => title => loc('History'), path => "/Ticket/History.html?id=" . $id );
-
-                # comment out until we can do it for an individual custom field
-                #if ( $can->('ModifyTicket') || $can->('ModifyCustomField') ) {
-                $tabs->child( basics => title => loc('Basics'), path => "/Ticket/Modify.html?id=" . $id );
-
-                #}
-
-                if ( $can->('ModifyTicket') || $can->('_ModifyOwner') || $can->('Watch') || $can->('WatchAsAdminCc') ) {
-                    $tabs->child( people => title => loc('People'), path => "/Ticket/ModifyPeople.html?id=" . $id );
-                }
-
-                if ( $can->('ModifyTicket') ) {
-                    $tabs->child( dates => title => loc('Dates'), path => "/Ticket/ModifyDates.html?id=" . $id );
-                    $tabs->child( links => title => loc('Links'), path => "/Ticket/ModifyLinks.html?id=" . $id );
-                }
-
-                #if ( $can->('ModifyTicket') || $can->('ModifyCustomField') || $can->('_ModifyOwner') ) {
-                $tabs->child( jumbo => title => loc('Jumbo'), path => "/Ticket/ModifyAll.html?id=" . $id );
-                #}
-
-                if ( RT->Config->Get('EnableReminders') ) {
-                    $tabs->child( reminders => title => loc('Reminders'), path => "/Ticket/Reminders.html?id=" . $id );
-                }
-
-                if ( $can->('ModifyTicket') or $can->('ReplyToTicket') ) {
-                    $actions->child( reply => title => loc('Reply'), path => "/Ticket/Update.html?Action=Respond;id=" . $id );
-                }
-
-                if ( $can->('ModifyTicket') or $can->('CommentOnTicket') ) {
-                    $actions->child( comment => title => loc('Comment'), path => "/Ticket/Update.html?Action=Comment;id=" . $id );
-                }
-
-                if ( $can->('ForwardMessage') ) {
-                    $actions->child( forward => title => loc('Forward'), path => "/Ticket/Forward.html?id=" . $id );
-                }
-
-                my $hide_resolve_with_deps = RT->Config->Get('HideResolveActionsWithDependencies')
-                    && $obj->HasUnresolvedDependencies;
+    my $scrips = $admin_global->child( scrips =>
+        title       => loc('Scrips'),
+        description => loc('Modify scrips which apply to all queues'),
+        path        => '/Admin/Global/Scrips.html',
+    );
+    $scrips->child( select => title => loc('Select'), path => "/Admin/Global/Scrips.html" );
+    $scrips->child( create => title => loc('Create'), path => "/Admin/Scrips/Create.html?Global=1" );
 
-                my $current   = $obj->Status;
-                my $lifecycle = $obj->LifecycleObj;
-                my $i         = 1;
-                foreach my $info ( $lifecycle->Actions($current) ) {
-                    my $next = $info->{'to'};
-                    next unless $lifecycle->IsTransition( $current => $next );
+    my $templates = $admin_global->child( templates =>
+        title       => loc('Templates'),
+        description => loc('Edit system templates'),
+        path        => '/Admin/Global/Templates.html',
+    );
+    $templates->child( select => title => loc('Select'), path => "/Admin/Global/Templates.html" );
+    $templates->child( create => title => loc('Create'), path => "/Admin/Global/Template.html?Create=1" );
 
-                    my $check = $lifecycle->CheckRight( $current => $next );
-                    next unless $can->($check);
+    my $cfadmin = $admin_global->child( 'custom-fields' =>
+        title       => loc('Custom Fields'),
+        description => loc('Modify global custom fields'),
+        path        => '/Admin/Global/CustomFields/index.html',
+    );
+    $cfadmin->child( users =>
+        title       => loc('Users'),
+        description => loc('Select custom fields for all users'),
+        path        => '/Admin/Global/CustomFields/Users.html',
+    );
+    $cfadmin->child( groups =>
+        title       => loc('Groups'),
+        description => loc('Select custom fields for all user groups'),
+        path        => '/Admin/Global/CustomFields/Groups.html',
+    );
+    $cfadmin->child( queues =>
+        title       => loc('Queues'),
+        description => loc('Select custom fields for all queues'),
+        path        => '/Admin/Global/CustomFields/Queues.html',
+    );
+    $cfadmin->child( tickets =>
+        title       => loc('Tickets'),
+        description => loc('Select custom fields for tickets in all queues'),
+        path        => '/Admin/Global/CustomFields/Queue-Tickets.html',
+    );
+    $cfadmin->child( transactions =>
+        title       => loc('Ticket Transactions'),
+        description => loc('Select custom fields for transactions on tickets in all queues'),
+        path        => '/Admin/Global/CustomFields/Queue-Transactions.html',
+    );
+    $cfadmin->child( 'custom-fields' =>
+        title       => loc('Articles'),
+        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',
+    );
 
-                    next if $hide_resolve_with_deps
-                        && $lifecycle->IsInactive($next)
-                        && !$lifecycle->IsInactive($current);
+    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/' );
+    $class_admin->child( select =>
+        title       => loc('Select'),
+        description => loc('Modify and Create Classes'),
+        path        => '/Admin/Articles/Classes/',
+    );
+    $class_admin->child( create =>
+        title       => loc('Create'),
+        description => loc('Modify and Create Custom Fields for Articles'),
+        path        => '/Admin/Articles/Classes/Modify.html?Create=1',
+    );
 
-                    my $action = $info->{'update'} || '';
-                    my $url = '/Ticket/';
-                    $url .= "Update.html?". $query_string->(
-                        $action
-                            ? (Action        => $action)
-                            : (SubmitTicket  => 1, Status => $next),
-                        DefaultStatus => $next,
-                        id            => $id,
-                    );
-                    my $key = $info->{'label'} || ucfirst($next);
-                    $actions->child( $key => title => loc( $key ), path => $url);
-                }
 
-                my ($can_take, $tmsg) = $obj->CurrentUserCanSetOwner( Type => 'Take' );
-                my ($can_steal, $smsg) = $obj->CurrentUserCanSetOwner( Type => 'Steal' );
-                if ( $can_take ){
-                    $actions->child( take => title => loc('Take'), path => "/Ticket/Display.html?Action=Take;id=" . $id );
-                }
-                elsif ( $can_steal ){
-                    $actions->child( steal => title => loc('Steal'), path => "/Ticket/Display.html?Action=Steal;id=" . $id );
-                }
+    my $cfs = $article_admin->child( 'custom-fields' =>
+        title => loc('Custom Fields'),
+        path  => '/Admin/CustomFields/index.html?'.$HTML::Mason::Commands::m->comp('/Elements/QueryString', Type => 'RT::Class-RT::Article'),
+    );
+    $cfs->child( select =>
+        title => loc('Select'),
+        path => '/Admin/CustomFields/index.html?'.$HTML::Mason::Commands::m->comp('/Elements/QueryString', Type => 'RT::Class-RT::Article'),
+    );
+    $cfs->child( create =>
+        title => loc('Create'),
+        path => '/Admin/CustomFields/Modify.html?'.$HTML::Mason::Commands::m->comp("/Elements/QueryString", Create=>1, LookupType=> "RT::Class-RT::Article" ),
+    );
 
-                # TODO needs a "Can extract article into a class applied to this queue" check
-                $actions->child( 'extract-article' =>
-                    title => loc('Extract Article'),
-                    path  => "/Articles/Article/ExtractIntoClass.html?Ticket=".$obj->id,
-                ) if $session{CurrentUser}->HasRight( Right => 'ShowArticlesMenu', Object => RT->System );
+    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" );
 
-                if ( defined $session{"tickets"} ) {
-                    # we have to update session data if we get new ItemMap
-                    my $updatesession = 1 unless ( $session{"tickets"}->{'item_map'} );
 
-                    my $item_map = $session{"tickets"}->ItemMap;
+    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);
 
-                    if ($updatesession) {
-                        $session{"tickets"}->PrepForSerialization();
-                    }
+    $admin_global->child( 'group-rights' =>
+        title       => loc('Group Rights'),
+        description => loc('Modify global group rights'),
+        path        => '/Admin/Global/GroupRights.html',
+    );
+    $admin_global->child( 'user-rights' =>
+        title       => loc('User Rights'),
+        description => loc('Modify global user rights'),
+        path        => '/Admin/Global/UserRights.html',
+    );
+    $admin_global->child( 'my-rt' =>
+        title       => loc('RT at a glance'),
+        description => loc('Modify the default "RT at a glance" view'),
+        path        => '/Admin/Global/MyRT.html',
+    );
+    $admin_global->child( 'dashboards-in-menu' =>
+        title       => loc('Dashboards in menu'),
+        description => loc('Customize dashboards in menu'),
+        path        => '/Admin/Global/DashboardsInMenu.html',
+    );
+    $admin_global->child( 'topics' =>
+        title       => loc('Topics'),
+        description => loc('Modify global article topics'),
+        path        => '/Admin/Global/Topics.html',
+    );
 
-                    my $search = Menu()->child('search')->child('tickets');
-                    # Don't display prev links if we're on the first ticket
-                    if ( $item_map->{$id}->{prev} ) {
-                        $search->child( first =>
-                            title => '<< ' . loc('First'), class => "nav", path => "/Ticket/Display.html?id=" . $item_map->{first});
-                        $search->child( prev =>
-                            title => '< ' . loc('Prev'),   class => "nav", path => "/Ticket/Display.html?id=" . $item_map->{$id}->{prev});
-                    }
-                    # Don't display next links if we're on the last ticket
-                    if ( $item_map->{$id}->{next} ) {
-                        $search->child( next =>
-                            title => loc('Next') . ' >',  class => "nav", path => "/Ticket/Display.html?id=" . $item_map->{$id}->{next});
-                        if ( $item_map->{last} ) {
-                            $search->child( last =>
-                                title => loc('Last') . ' >>', class => "nav", path => "/Ticket/Display.html?id=" . $item_map->{last});
-                        }
-                    }
-                }
-            }
-        }
+    my $admin_tools = $admin->child( tools =>
+        title       => loc('Tools'),
+        description => loc('Use other RT administrative tools'),
+        path        => '/Admin/Tools/',
+    );
+    $admin_tools->child( configuration =>
+        title       => loc('System Configuration'),
+        description => loc('Detailed information about your RT setup'),
+        path        => '/Admin/Tools/Configuration.html',
+    );
+    $admin_tools->child( theme =>
+        title       => loc('Theme'),
+        description => loc('Customize the look of your RT'),
+        path        => '/Admin/Tools/Theme.html',
+    );
+    if (RT->Config->Get('StatementLog')
+        && $HTML::Mason::Commands::session{'CurrentUser'}->HasRight( Right => 'SuperUser', Object => RT->System )) {
+       $admin_tools->child( 'sql-queries' =>
+           title       => loc('SQL Queries'),
+           description => loc('Browse the SQL queries made in this process'),
+           path        => '/Admin/Tools/Queries.html',
+       );
     }
+    $admin_tools->child( shredder =>
+        title       => loc('Shredder'),
+        description => loc('Permanently wipeout data from RT'),
+        path        => '/Admin/Tools/Shredder',
+    );
 
-    if (
-        (
-               $request_path =~ m{^/(?:Ticket|Search)/}
-            && $request_path !~ m{^/Search/Simple\.html}
-        )
-        || (   $request_path =~ m{^/Search/Simple\.html}
-            && $DECODED_ARGS->{'q'} )
-      )
-    {
-        my $search = Menu()->child('search')->child('tickets');
-        my $args      = '';
-        my $has_query = '';
-        my $current_search = $session{"CurrentSearchHash"} || {};
-        my $search_id = $DECODED_ARGS->{'SavedSearchLoad'} || $DECODED_ARGS->{'SavedSearchId'} || $current_search->{'SearchId'} || '';
-        my $chart_id = $DECODED_ARGS->{'SavedChartSearchId'} || $current_search->{SavedChartSearchId};
-
-        $has_query = 1 if ( $DECODED_ARGS->{'Query'} or $current_search->{'Query'} );
+    if ( $request_path =~ m{^/Admin/(Queues|Users|Groups|CustomFields|CustomRoles)} ) {
+        my $type = $1;
+        my $tabs = HTML::Mason::Commands::PageMenu();
 
-        my %query_args;
-        my %fallback_query_args = (
-            SavedSearchId => ( $search_id eq 'new' ) ? undef : $search_id,
-            SavedChartSearchId => $chart_id,
-            (
-                map {
-                    my $p = $_;
-                    $p => $DECODED_ARGS->{$p} || $current_search->{$p}
-                } qw(Query Format OrderBy Order Page)
-            ),
-            RowsPerPage => (
-                defined $DECODED_ARGS->{'RowsPerPage'}
-                ? $DECODED_ARGS->{'RowsPerPage'}
-                : $current_search->{'RowsPerPage'}
-            ),
+        my %labels = (
+            Queues       => loc("Queues"),
+            Users        => loc("Users"),
+            Groups       => loc("Groups"),
+            CustomFields => loc("Custom Fields"),
+            CustomRoles  => loc("Custom Roles"),
         );
 
-        if ($QueryString) {
-            $args = '?' . $QueryString;
-        }
-        else {
-            my %final_query_args = ();
-            # key => callback to avoid unnecessary work
-
-            for my $param (keys %fallback_query_args) {
-                $final_query_args{$param} = defined($QueryArgs->{$param})
-                                          ? $QueryArgs->{$param}
-                                          : $fallback_query_args{$param};
-            }
-
-            for my $field (qw(Order OrderBy)) {
-                if ( ref( $final_query_args{$field} ) eq 'ARRAY' ) {
-                    $final_query_args{$field} = join( "|", @{ $final_query_args{$field} } );
-                } elsif (not defined $final_query_args{$field}) {
-                    delete $final_query_args{$field};
-                }
-                else {
-                    $final_query_args{$field} ||= '';
-                }
-            }
-
-            $args = '?' . $query_string->(%final_query_args);
-        }
+        my $section;
+        if ( $request_path =~ m|^/Admin/$type/?(?:index.html)?$|
+             || (    $request_path =~ m|^/Admin/$type/(?:Modify.html)$|
+                  && $HTML::Mason::Commands::DECODED_ARGS->{'Create'} )
+           )
+        {
+            $section = $tabs;
 
-        my $current_search_menu;
-        if ( $request_path =~ m{^/Ticket} ) {
-            $current_search_menu = $search->child( current_search => title => loc('Current Search') );
-            $current_search_menu->path("/Search/Results.html$args") if $has_query;
         } else {
-            $current_search_menu = PageMenu();
+            $section = $tabs->child( select => title => $labels{$type},
+                                     path => "/Admin/$type/" );
         }
 
-        $current_search_menu->child( edit_search =>
-            title => loc('Edit Search'), path => "/Search/Build.html" . ( ($has_query) ? $args : '' ) );
-        $current_search_menu->child( advanced =>
-            title => loc('Advanced'),    path => "/Search/Edit.html$args" );
-        if ($has_query) {
-            $current_search_menu->child( results => title => loc('Show Results'), path => "/Search/Results.html$args" );
-        }
+        $section->child( select => title => loc('Select'), path => "/Admin/$type/" );
+        $section->child( create => title => loc('Create'), path => "/Admin/$type/Modify.html?Create=1" );
+    }
 
-        if ( $has_query ) {
-            $current_search_menu->child( bulk  => title => loc('Bulk Update'), path => "/Search/Bulk.html$args" );
-            $current_search_menu->child( chart => title => loc('Chart'),       path => "/Search/Chart.html$args" );
+    if ( $request_path =~ m{^/Admin/Queues} ) {
+        if ( $HTML::Mason::Commands::DECODED_ARGS->{'id'} && $HTML::Mason::Commands::DECODED_ARGS->{'id'} =~ /^\d+$/
+                ||
+              $HTML::Mason::Commands::DECODED_ARGS->{'Queue'} && $HTML::Mason::Commands::DECODED_ARGS->{'Queue'} =~ /^\d+$/
+                ) {
+            my $id = $HTML::Mason::Commands::DECODED_ARGS->{'Queue'} || $HTML::Mason::Commands::DECODED_ARGS->{'id'};
+            my $queue_obj = RT::Queue->new( $HTML::Mason::Commands::session{'CurrentUser'} );
+            $queue_obj->Load($id);
 
-            my $more = $current_search_menu->child( more => title => loc('Feeds') );
+            if ( $queue_obj and $queue_obj->id ) {
+                my $queue = HTML::Mason::Commands::PageMenu();
+                $queue->child( basics => title => loc('Basics'),   path => "/Admin/Queues/Modify.html?id=" . $id );
+                $queue->child( people => title => loc('Watchers'), path => "/Admin/Queues/People.html?id=" . $id );
 
-            $more->child( spreadsheet => title => loc('Spreadsheet'), path => "/Search/Results.tsv$args" );
+                my $templates = $queue->child(templates => title => loc('Templates'), path => "/Admin/Queues/Templates.html?id=" . $id);
+                $templates->child( select => title => loc('Select'), path => "/Admin/Queues/Templates.html?id=".$id);
+                $templates->child( create => title => loc('Create'), path => "/Admin/Queues/Template.html?Create=1;Queue=".$id);
 
-            my %rss_data = map {
-                $_ => $QueryArgs->{$_} || $fallback_query_args{$_} || '' }
-                    qw(Query Order OrderBy);
-            my $RSSQueryString = "?"
-                . $query_string->( Query   => $rss_data{Query},
-                                   Order   => $rss_data{Order},
-                                   OrderBy => $rss_data{OrderBy}
-                                 );
-            my $RSSPath = join '/', map $m->interp->apply_escapes( $_, 'u' ),
-                $session{'CurrentUser'}->UserObj->Name,
-                $session{'CurrentUser'}
-                ->UserObj->GenerateAuthString(   $rss_data{Query}
-                                               . $rss_data{Order}
-                                               . $rss_data{OrderBy} );
+                my $scrips = $queue->child( scrips => title => loc('Scrips'), path => "/Admin/Queues/Scrips.html?id=" . $id);
+                $scrips->child( select => title => loc('Select'), path => "/Admin/Queues/Scrips.html?id=" . $id );
+                $scrips->child( create => title => loc('Create'), path => "/Admin/Scrips/Create.html?Queue=" . $id);
 
-            $more->child( rss => title => loc('RSS'), path => "/NoAuth/rss/$RSSPath/$RSSQueryString");
-            my $ical_path = join '/', map $m->interp->apply_escapes($_, 'u'),
-                $session{'CurrentUser'}->UserObj->Name,
-                $session{'CurrentUser'}->UserObj->GenerateAuthString( $rss_data{Query} ),
-                $rss_data{Query};
-            $more->child( ical => title => loc('iCal'), path => '/NoAuth/iCal/'.$ical_path);
+                my $cfs = $queue->child( 'custom-fields' => title => loc('Custom Fields') );
+                my $ticket_cfs = $cfs->child( 'tickets' => title => loc('Tickets'),
+                    path => '/Admin/Queues/CustomFields.html?SubType=RT::Ticket&id=' . $id );
 
-            if ($request_path =~ m{^/Search/Results.html}
-                &&                        #XXX TODO better abstraction
-                $session{'CurrentUser'}->HasRight( Right => 'SuperUser', Object => RT->System )) {
-                my $shred_args = $query_string->(
-                    Search          => 1,
-                    Plugin          => 'Tickets',
-                    'Tickets:query' => $rss_data{'Query'},
-                    'Tickets:limit' => $QueryArgs->{'Rows'},
-                );
+                my $txn_cfs = $cfs->child( 'transactions' => title => loc('Transactions'),
+                    path => '/Admin/Queues/CustomFields.html?SubType=RT::Ticket-RT::Transaction&id='.$id );
 
-                $more->child( shredder => title => loc('Shredder'), path => '/Admin/Tools/Shredder/?' . $shred_args);
+                $queue->child( 'group-rights' => title => loc('Group Rights'), path => "/Admin/Queues/GroupRights.html?id=".$id );
+                $queue->child( 'user-rights' => title => loc('User Rights'), path => "/Admin/Queues/UserRights.html?id=" . $id );
+                $queue->child( 'history' => title => loc('History'), path => "/Admin/Queues/History.html?id=" . $id );
+                $queue->child( 'default-values' => title => loc('Default Values'), path => "/Admin/Queues/DefaultValues.html?id=" . $id );
+
+                # due to historical reasons of always having been in /Elements/Tabs
+                $HTML::Mason::Commands::m->callback( CallbackName => 'PrivilegedQueue', queue_id => $id, page_menu => $queue, CallbackPage => '/Elements/Tabs' );
             }
+        }
+    }
+    if ( $request_path =~ m{^(/Admin/Users|/User/(Summary|History)\.html)} and $admin->child("users") ) {
+        if ( $HTML::Mason::Commands::DECODED_ARGS->{'id'} && $HTML::Mason::Commands::DECODED_ARGS->{'id'} =~ /^\d+$/ ) {
+            my $id = $HTML::Mason::Commands::DECODED_ARGS->{'id'};
+            my $obj = RT::User->new( $HTML::Mason::Commands::session{'CurrentUser'} );
+            $obj->Load($id);
 
+            if ( $obj and $obj->id ) {
+                my $tabs = HTML::Mason::Commands::PageMenu();
+                $tabs->child( basics      => title => loc('Basics'),         path => "/Admin/Users/Modify.html?id=" . $id );
+                $tabs->child( memberships => title => loc('Memberships'),    path => "/Admin/Users/Memberships.html?id=" . $id );
+                $tabs->child( history     => title => loc('History'),        path => "/Admin/Users/History.html?id=" . $id );
+                $tabs->child( 'my-rt'     => title => loc('RT at a glance'), path => "/Admin/Users/MyRT.html?id=" . $id );
+                $tabs->child( 'dashboards-in-menu' =>
+                    title => loc('Dashboards in menu'),
+                    path  => '/Admin/Users/DashboardsInMenu.html?id=' . $id,
+                );
+                if ( RT->Config->Get('Crypt')->{'Enable'} ) {
+                    $tabs->child( keys    => title => loc('Private keys'),   path => "/Admin/Users/Keys.html?id=" . $id );
+                }
+                $tabs->child( 'summary'   => title => loc('User Summary'),   path => "/User/Summary.html?id=" . $id );
+            }
         }
+
     }
 
-    if ( $request_path =~ m{^/Article/} ) {
-        if ( $DECODED_ARGS->{'id'} && $DECODED_ARGS->{'id'} =~ /^\d+$/ ) {
-            my $id = $DECODED_ARGS->{'id'};
-            my $tabs = PageMenu();
+    if ( $request_path =~ m{^/Admin/Groups} ) {
+        if ( $HTML::Mason::Commands::DECODED_ARGS->{'id'} && $HTML::Mason::Commands::DECODED_ARGS->{'id'} =~ /^\d+$/ ) {
+            my $id = $HTML::Mason::Commands::DECODED_ARGS->{'id'};
+            my $obj = RT::Group->new( $HTML::Mason::Commands::session{'CurrentUser'} );
+            $obj->Load($id);
 
-            $tabs->child( display => title => loc('Display'), path => "/Articles/Article/Display.html?id=".$id );
-            $tabs->child( history => title => loc('History'), path => "/Articles/Article/History.html?id=".$id );
-            $tabs->child( modify  => title => loc('Modify'),  path => "/Articles/Article/Edit.html?id=".$id );
+            if ( $obj and $obj->id ) {
+                my $tabs = HTML::Mason::Commands::PageMenu();
+                $tabs->child( basics         => title => loc('Basics'),       path => "/Admin/Groups/Modify.html?id=" . $obj->id );
+                $tabs->child( members        => title => loc('Members'),      path => "/Admin/Groups/Members.html?id=" . $obj->id );
+                $tabs->child( memberships    => title => loc('Memberships'),  path => "/Admin/Groups/Memberships.html?id=" . $obj->id );
+                $tabs->child( 'group-rights' => title => loc('Group Rights'), path => "/Admin/Groups/GroupRights.html?id=" . $obj->id );
+                $tabs->child( 'user-rights'  => title => loc('User Rights'),  path => "/Admin/Groups/UserRights.html?id=" . $obj->id );
+                $tabs->child( history        => title => loc('History'),      path => "/Admin/Groups/History.html?id=" . $obj->id );
+            }
         }
     }
 
-    if ( $request_path =~ m{^/Articles/} ) {
-        PageWidgets()->child( article_search => raw_html => $m->scomp('/Articles/Elements/GotoArticle') );
-        PageWidgets()->delete('create_ticket');
-        PageWidgets()->delete('simple_search');
-
-        my $tabs = PageMenu();
-        $tabs->child( search => title => loc("Search"),       path => "/Articles/Article/Search.html" );
-        $tabs->child( create => title => loc("New Article" ), path => "/Articles/Article/PreCreate.html" );
-        if ( $request_path =~ m{^/Articles/Article/} and ( $DECODED_ARGS->{'id'} || '' ) =~ /^(\d+)$/ ) {
-            my $id  = $1;
-            my $obj = RT::Article->new( $session{'CurrentUser'} );
+    if ( $request_path =~ m{^/Admin/CustomFields/} ) {
+        if ( $HTML::Mason::Commands::DECODED_ARGS->{'id'} && $HTML::Mason::Commands::DECODED_ARGS->{'id'} =~ /^\d+$/ ) {
+            my $id = $HTML::Mason::Commands::DECODED_ARGS->{'id'};
+            my $obj = RT::CustomField->new( $HTML::Mason::Commands::session{'CurrentUser'} );
             $obj->Load($id);
 
             if ( $obj and $obj->id ) {
-                $tabs->child( display => title => loc("Display"), path => "/Articles/Article/Display.html?id=" . $id );
-                $tabs->child( history => title => loc('History'), path => '/Articles/Article/History.html?id=' . $id );
-
-                if ( $obj->CurrentUserHasRight('ModifyArticle') ) {
-                    $tabs->child(modify => title => loc('Modify'), path => '/Articles/Article/Edit.html?id=' . $id );
+                my $tabs = HTML::Mason::Commands::PageMenu();
+                $tabs->child( basics           => title => loc('Basics'),       path => "/Admin/CustomFields/Modify.html?id=".$id );
+                $tabs->child( 'group-rights'   => title => loc('Group Rights'), path => "/Admin/CustomFields/GroupRights.html?id=" . $id );
+                $tabs->child( 'user-rights'    => title => loc('User Rights'),  path => "/Admin/CustomFields/UserRights.html?id=" . $id );
+                unless ( $obj->IsOnlyGlobal ) {
+                    $tabs->child( 'applies-to' => title => loc('Applies to'),   path => "/Admin/CustomFields/Objects.html?id=" . $id );
                 }
             }
         }
-
     }
 
-    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");
+    if ( $request_path =~ m{^/Admin/CustomRoles} ) {
+        if ( $HTML::Mason::Commands::DECODED_ARGS->{'id'} && $HTML::Mason::Commands::DECODED_ARGS->{'id'} =~ /^\d+$/ ) {
+            my $id = $HTML::Mason::Commands::DECODED_ARGS->{'id'};
+            my $obj = RT::CustomRole->new( $HTML::Mason::Commands::session{'CurrentUser'} );
+            $obj->Load($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'),
-                );
+            if ( $obj and $obj->id ) {
+                my $tabs = HTML::Mason::Commands::PageMenu();
+                $tabs->child( basics       => title => loc('Basics'),       path => "/Admin/CustomRoles/Modify.html?id=".$id );
+                $tabs->child( 'applies-to' => title => loc('Applies to'),   path => "/Admin/CustomRoles/Objects.html?id=" . $id );
             }
+        }
+    }
 
-            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);
+    if ( $request_path =~ m{^/Admin/Scrips/} ) {
+        if ( $HTML::Mason::Commands::m->request_args->{'id'} && $HTML::Mason::Commands::m->request_args->{'id'} =~ /^\d+$/ ) {
+            my $id = $HTML::Mason::Commands::m->request_args->{'id'};
+            my $obj = RT::Scrip->new( $HTML::Mason::Commands::session{'CurrentUser'} );
+            $obj->Load($id);
 
-                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'),
+            my $tabs = HTML::Mason::Commands::PageMenu();
 
-                    class       => "asset-lifecycle-action",
-                    attributes  => {
-                        'data-current-status'   => $status,
-                        'data-next-status'      => $next,
-                    },
-                );
+            my ( $admin_cat, $create_path_arg, $from_query_param );
+            my $from_arg = $HTML::Mason::Commands::DECODED_ARGS->{'From'} || q{};
+            my ($from_queue) = $from_arg =~ /^(\d+)$/;
+            if ( $from_queue ) {
+                $admin_cat = "Queues/Scrips.html?id=$from_queue";
+                $create_path_arg = "?Queue=$from_queue";
+                $from_query_param = "&From=$from_queue";
+            }
+            elsif ( $from_arg eq 'Global' ) {
+                $admin_cat = 'Global/Scrips.html';
+                $create_path_arg = '?Global=1';
+                $from_query_param = '&From=Global';
+            }
+            else {
+                $admin_cat = 'Scrips';
+                $from_query_param = $create_path_arg = q{};
             }
+            my $scrips = $tabs->child( scrips => title => loc('Scrips'), path => "/Admin/${admin_cat}" );
+            $scrips->child( select => title => loc('Select'), path => "/Admin/${admin_cat}" );
+            $scrips->child( create => title => loc('Create'), path => "/Admin/Scrips/Create.html${create_path_arg}" );
+
+            $tabs->child( basics => title => loc('Basics') => path => "/Admin/Scrips/Modify.html?id=" . $id . $from_query_param );
+            $tabs->child( 'applies-to' => title => loc('Applies to'), path => "/Admin/Scrips/Objects.html?id=" . $id . $from_query_param );
         }
-    } 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/Scrips/(index\.html)?$} ) {
+            HTML::Mason::Commands::PageMenu->child( select => title => loc('Select') => path => "/Admin/Scrips/" );
+            HTML::Mason::Commands::PageMenu->child( create => title => loc('Create') => path => "/Admin/Scrips/Create.html" );
         }
-        $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");
+        elsif ( $request_path =~ m{^/Admin/Scrips/Create\.html$} ) {
+            my ($queue) = $HTML::Mason::Commands::DECODED_ARGS->{'Queue'} && $HTML::Mason::Commands::DECODED_ARGS->{'Queue'} =~ /^(\d+)$/;
+            my $global_arg = $HTML::Mason::Commands::DECODED_ARGS->{'Global'};
+            if ($queue) {
+                HTML::Mason::Commands::PageMenu->child( select => title => loc('Select') => path => "/Admin/Queues/Scrips.html?id=$queue" );
+                HTML::Mason::Commands::PageMenu->child( create => title => loc('Create') => path => "/Admin/Scrips/Create.html?Queue=$queue" );
+            } elsif ($global_arg) {
+                HTML::Mason::Commands::PageMenu->child( select => title => loc('Select') => path => "/Admin/Global/Scrips.html" );
+                HTML::Mason::Commands::PageMenu->child( create => title => loc('Create') => path => "/Admin/Scrips/Create.html?Global=1" );
+            } else {
+                HTML::Mason::Commands::PageMenu->child( select => title => loc('Select') => path => "/Admin/Scrips" );
+                HTML::Mason::Commands::PageMenu->child( create => title => loc('Create') => path => "/Admin/Scrips/Create.html" );
+            }
+        }
+    }
 
-        my $catalog = RT::Catalog->new( $session{CurrentUser} );
-        $catalog->Load($DECODED_ARGS->{id}) if $DECODED_ARGS->{id};
+    if ( $request_path =~ m{^/Admin/Global/Scrips\.html} ) {
+        my $tabs = HTML::Mason::Commands::PageMenu();
+        $tabs->child( select => title => loc('Select'), path => "/Admin/Global/Scrips.html" );
+        $tabs->child( create => title => loc('Create'), path => "/Admin/Scrips/Create.html?Global=1" );
+    }
 
-        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");
+    if ( $request_path =~ m{^/Admin/Global/Templates?\.html} ) {
+        my $tabs = HTML::Mason::Commands::PageMenu();
+        $tabs->child( select => title => loc('Select'), path => "/Admin/Global/Templates.html" );
+        $tabs->child( create => title => loc('Create'), path => "/Admin/Global/Template.html?Create=1" );
+    }
 
-            $page->child("cfs", title => loc("Asset Custom Fields"), path => "/Admin/Assets/Catalogs/CustomFields.html?$query");
+    if ( $request_path =~ m{^/Admin/Articles/Classes/} ) {
+        my $tabs = HTML::Mason::Commands::PageMenu();
+        if ( my $id = $HTML::Mason::Commands::DECODED_ARGS->{'id'} ) {
+            my $obj = RT::Class->new( $HTML::Mason::Commands::session{'CurrentUser'} );
+            $obj->Load($id);
 
-            $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");
-        }
-    }
+            if ( $obj and $obj->id ) {
+                my $section = $tabs->child( select => title => loc("Classes"), path => "/Admin/Articles/Classes/" );
+                $section->child( select => title => loc('Select'), path => "/Admin/Articles/Classes/" );
+                $section->child( create => title => loc('Create'), path => "/Admin/Articles/Classes/Modify.html?Create=1" );
 
-    if ( $request_path =~ m{^/User/(Summary|History)\.html} ) {
-        if (PageMenu()->child('summary')) {
-            # Already set up from having AdminUser and ShowConfigTab;
-            # but rename "Basics" to "Edit" in this context
-            PageMenu()->child( 'basics' )->title( loc('Edit') );
-        } elsif ( $session{'CurrentUser'}->HasRight( Object => $RT::System, Right => 'ShowUserHistory' ) ) {
-            PageMenu()->child( display => title => loc('Summary'), path => '/User/Summary.html?id=' . $DECODED_ARGS->{'id'} );
-            PageMenu()->child( history => title => loc('History'), path => '/User/History.html?id=' . $DECODED_ARGS->{'id'} );
+                $tabs->child( basics          => title => loc('Basics'),        path => "/Admin/Articles/Classes/Modify.html?id=".$id );
+                $tabs->child( topics          => title => loc('Topics'),        path => "/Admin/Articles/Classes/Topics.html?id=".$id );
+                $tabs->child( 'custom-fields' => title => loc('Custom Fields'), path => "/Admin/Articles/Classes/CustomFields.html?id=".$id );
+                $tabs->child( 'group-rights'  => title => loc('Group Rights'),  path => "/Admin/Articles/Classes/GroupRights.html?id=".$id );
+                $tabs->child( 'user-rights'   => title => loc('User Rights'),   path => "/Admin/Articles/Classes/UserRights.html?id=".$id );
+                $tabs->child( 'applies-to'    => title => loc('Applies to'),    path => "/Admin/Articles/Classes/Objects.html?id=$id" );
+            }
+        } else {
+            $tabs->child( select => title => loc('Select'), path => "/Admin/Articles/Classes/" );
+            $tabs->child( create => title => loc('Create'), path => "/Admin/Articles/Classes/Modify.html?Create=1" );
         }
     }
+}
 
-    if ( $request_path =~ /^\/(?:index.html|$)/ ) {
-        PageMenu()->child( edit => title => loc('Edit'), path => '/Prefs/MyRT.html' );
-    }
-
-    $m->callback( CallbackName => 'Privileged', Path => $request_path );
-};
+sub BuildSelfServiceNav {
+    my $request_path = shift;
 
-my $build_selfservice_nav = sub {
-    my $queues = RT::Queues->new( $session{'CurrentUser'} );
+    my $queues = RT::Queues->new( $HTML::Mason::Commands::session{'CurrentUser'} );
     $queues->UnLimit;
 
     my $queue_count = 0;
@@ -1124,45 +1140,45 @@ my $build_selfservice_nav = sub {
 
 
     if ( $queue_count > 1 ) {
-        Menu->child( new => title => loc('New ticket'), path => '/SelfService/CreateTicketInQueue.html' );
+        HTML::Mason::Commands::Menu()->child( new => title => loc('New ticket'), path => '/SelfService/CreateTicketInQueue.html' );
     } elsif ( $queue_id ) {
-        Menu->child( new => title => loc('New ticket'), path => '/SelfService/Create.html?Queue=' . $queue_id );
+        HTML::Mason::Commands::Menu()->child( new => title => loc('New ticket'), path => '/SelfService/Create.html?Queue=' . $queue_id );
     }
-    my $tickets = Menu->child( tickets => title => loc('Tickets'), path => '/SelfService/' );
+    my $tickets = HTML::Mason::Commands::Menu()->child( tickets => title => loc('Tickets'), path => '/SelfService/' );
     $tickets->child( open   => title => loc('Open tickets'),   path => '/SelfService/' );
     $tickets->child( closed => title => loc('Closed tickets'), path => '/SelfService/Closed.html' );
 
-    Menu->child( "assets", title => loc("Assets"), path => "/SelfService/Asset/" )
-        if $session{CurrentUser}->HasRight( Right => 'ShowAssetsMenu', Object => RT->System );
+    HTML::Mason::Commands::Menu()->child( "assets", title => loc("Assets"), path => "/SelfService/Asset/" )
+        if $HTML::Mason::Commands::session{CurrentUser}->HasRight( Right => 'ShowAssetsMenu', Object => RT->System );
 
     my $username = '<span class="current-user">'
-                 . $m->interp->apply_escapes($session{'CurrentUser'}->Name, 'h')
+                 . $HTML::Mason::Commands::m->interp->apply_escapes($HTML::Mason::Commands::session{'CurrentUser'}->Name, 'h')
                  . '</span>';
-    my $about_me = Menu->child( preferences =>
+    my $about_me = HTML::Mason::Commands::Menu()->child( preferences =>
         title        => loc('Logged in as [_1]', $username),
         escape_title => 0,
         sort_order   => 99,
     );
 
-    if ( $session{'CurrentUser'}->HasRight( Right => 'ModifySelf', Object => RT->System ) ) {
+    if ( $HTML::Mason::Commands::session{'CurrentUser'}->HasRight( Right => 'ModifySelf', Object => RT->System ) ) {
         $about_me->child( prefs => title => loc('Preferences'), path => '/SelfService/Prefs.html' );
     }
 
-    if ( $session{'CurrentUser'}->Name
+    if ( $HTML::Mason::Commands::session{'CurrentUser'}->Name
          && (   !RT->Config->Get('WebRemoteUserAuth')
               || RT->Config->Get('WebFallbackToRTLogin') )) {
         $about_me->child( logout => title => loc('Logout'), path => '/NoAuth/Logout.html' );
     }
 
-    if ($session{'CurrentUser'}->HasRight( Right => 'ShowArticle', Object => RT->System )) {
-        PageWidgets->child( 'goto-article' => raw_html => $m->scomp('/SelfService/Elements/SearchArticle') );
+    if ($HTML::Mason::Commands::session{'CurrentUser'}->HasRight( Right => 'ShowArticle', Object => RT->System )) {
+        HTML::Mason::Commands::PageWidgets()->child( 'goto-article' => raw_html => $HTML::Mason::Commands::m->scomp('/SelfService/Elements/SearchArticle') );
     }
 
-    PageWidgets->child( goto => raw_html => $m->scomp('/SelfService/Elements/GotoTicket') );
+    HTML::Mason::Commands::PageWidgets()->child( goto => raw_html => $HTML::Mason::Commands::m->scomp('/SelfService/Elements/GotoTicket') );
 
-    if ($request_path =~ m{^/SelfService/Asset/} and $DECODED_ARGS->{id}) {
-        my $page = PageMenu();
-        my $id   = $DECODED_ARGS->{id};
+    if ($request_path =~ m{^/SelfService/Asset/} and $HTML::Mason::Commands::DECODED_ARGS->{id}) {
+        my $page = HTML::Mason::Commands::PageMenu();
+        my $id   = $HTML::Mason::Commands::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");
 
@@ -1172,23 +1188,8 @@ my $build_selfservice_nav = sub {
         }
     }
 
-    $m->callback( CallbackName => 'SelfService', Path => $request_path );
-};
-
-
-
-if ( $request_path !~ m{^/SelfService/} ) {
-    $build_main_nav->();
-} else {
-    $build_selfservice_nav->();
+    # due to historical reasons of always having been in /Elements/Tabs
+    $HTML::Mason::Commands::m->callback( CallbackName => 'SelfService', Path => $request_path, CallbackPage => '/Elements/Tabs' );
 }
 
-
-
-
-</%INIT>
-<%ARGS>
-$show_menu => 1
-$QueryString => ''
-$QueryArgs => {}
-</%ARGS>
+1;
diff --git a/share/html/Elements/Tabs b/share/html/Elements/Tabs
index 866e8f2..875960c 100644
--- a/share/html/Elements/Tabs
+++ b/share/html/Elements/Tabs
@@ -52,1140 +52,12 @@
 my $request_path = $HTML::Mason::Commands::r->path_info;
 $request_path =~ s!/{2,}!/!g;
 
-my $query_string = sub {
-    my %args = @_;
-    my $u    = URI->new();
-    $u->query_form(map { $_ => $args{$_} } sort keys %args);
-    return $u->query;
-};
-
-my $build_admin_menu = sub {
-    my $top = shift;
-    my $admin = $top->child( admin => title => loc('Admin'), path => '/Admin/' );
-    if ( $session{'CurrentUser'}->HasRight( Object => RT->System, Right => 'AdminUsers' ) ) {
-        my $users = $admin->child( users =>
-            title       => loc('Users'),
-            description => loc('Manage users and passwords'),
-            path        => '/Admin/Users/',
-        );
-        $users->child( select => title => loc('Select'), path => "/Admin/Users/" );
-        $users->child( create => title => loc('Create'), path => "/Admin/Users/Modify.html?Create=1" );
-    }
-    my $groups = $admin->child( groups =>
-        title       => loc('Groups'),
-        description => loc('Manage groups and group membership'),
-        path        => '/Admin/Groups/',
-    );
-    $groups->child( select => title => loc('Select'), path => "/Admin/Groups/" );
-    $groups->child( create => title => loc('Create'), path => "/Admin/Groups/Modify.html?Create=1" );
-
-    my $queues = $admin->child( queues =>
-        title       => loc('Queues'),
-        description => loc('Manage queues and queue-specific properties'),
-        path        => '/Admin/Queues/',
-    );
-    $queues->child( select => title => loc('Select'), path => "/Admin/Queues/" );
-    $queues->child( create => title => loc('Create'), path => "/Admin/Queues/Modify.html?Create=1" );
-
-    if ( $session{'CurrentUser'}->HasRight( Object => RT->System, Right => 'AdminCustomField' ) ) {
-        my $cfs = $admin->child( 'custom-fields' =>
-            title       => loc('Custom Fields'),
-            description => loc('Manage custom fields and custom field values'),
-            path        => '/Admin/CustomFields/',
-        );
-        $cfs->child( select => title => loc('Select'), path => "/Admin/CustomFields/" );
-        $cfs->child( create => title => loc('Create'), path => "/Admin/CustomFields/Modify.html?Create=1" );
-    }
-
-    if ( $session{'CurrentUser'}->HasRight( Object => RT->System, Right => 'AdminCustomRoles' ) ) {
-        my $roles = $admin->child( 'custom-roles' =>
-            title       => loc('Custom Roles'),
-            description => loc('Manage custom roles'),
-            path        => '/Admin/CustomRoles/',
-        );
-        $roles->child( select => title => loc('Select'), path => "/Admin/CustomRoles/" );
-        $roles->child( create => title => loc('Create'), path => "/Admin/CustomRoles/Modify.html?Create=1" );
-    }
-
-    if ( $session{'CurrentUser'}->HasRight( Object => RT->System, Right => 'ModifyScrips' ) ) {
-        my $scrips = $admin->child( 'scrips' =>
-            title       => loc('Scrips'),
-            description => loc('Manage scrips'),
-            path        => '/Admin/Scrips/',
-        );
-        $scrips->child( select => title => loc('Select'), path => "/Admin/Scrips/" );
-        $scrips->child( create => title => loc('Create'), path => "/Admin/Scrips/Create.html" );
-    }
-
-    my $admin_global = $admin->child( global =>
-        title       => loc('Global'),
-        description => loc('Manage properties and configuration which apply to all queues'),
-        path        => '/Admin/Global/',
-    );
-
-    my $scrips = $admin_global->child( scrips =>
-        title       => loc('Scrips'),
-        description => loc('Modify scrips which apply to all queues'),
-        path        => '/Admin/Global/Scrips.html',
-    );
-    $scrips->child( select => title => loc('Select'), path => "/Admin/Global/Scrips.html" );
-    $scrips->child( create => title => loc('Create'), path => "/Admin/Scrips/Create.html?Global=1" );
-
-    my $templates = $admin_global->child( templates =>
-        title       => loc('Templates'),
-        description => loc('Edit system templates'),
-        path        => '/Admin/Global/Templates.html',
-    );
-    $templates->child( select => title => loc('Select'), path => "/Admin/Global/Templates.html" );
-    $templates->child( create => title => loc('Create'), path => "/Admin/Global/Template.html?Create=1" );
-
-    my $cfadmin = $admin_global->child( 'custom-fields' =>
-        title       => loc('Custom Fields'),
-        description => loc('Modify global custom fields'),
-        path        => '/Admin/Global/CustomFields/index.html',
-    );
-    $cfadmin->child( users =>
-        title       => loc('Users'),
-        description => loc('Select custom fields for all users'),
-        path        => '/Admin/Global/CustomFields/Users.html',
-    );
-    $cfadmin->child( groups =>
-        title       => loc('Groups'),
-        description => loc('Select custom fields for all user groups'),
-        path        => '/Admin/Global/CustomFields/Groups.html',
-    );
-    $cfadmin->child( queues =>
-        title       => loc('Queues'),
-        description => loc('Select custom fields for all queues'),
-        path        => '/Admin/Global/CustomFields/Queues.html',
-    );
-    $cfadmin->child( tickets =>
-        title       => loc('Tickets'),
-        description => loc('Select custom fields for tickets in all queues'),
-        path        => '/Admin/Global/CustomFields/Queue-Tickets.html',
-    );
-    $cfadmin->child( transactions =>
-        title       => loc('Ticket Transactions'),
-        description => loc('Select custom fields for transactions on tickets in all queues'),
-        path        => '/Admin/Global/CustomFields/Queue-Transactions.html',
-    );
-    $cfadmin->child( 'custom-fields' =>
-        title       => loc('Articles'),
-        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/' );
-    $class_admin->child( select =>
-        title       => loc('Select'),
-        description => loc('Modify and Create Classes'),
-        path        => '/Admin/Articles/Classes/',
-    );
-    $class_admin->child( create =>
-        title       => loc('Create'),
-        description => loc('Modify and Create Custom Fields for Articles'),
-        path        => '/Admin/Articles/Classes/Modify.html?Create=1',
-    );
-
-
-    my $cfs = $article_admin->child( 'custom-fields' =>
-        title => loc('Custom Fields'),
-        path  => '/Admin/CustomFields/index.html?'.$m->comp('/Elements/QueryString', Type => 'RT::Class-RT::Article'),
-    );
-    $cfs->child( select =>
-        title => loc('Select'),
-        path => '/Admin/CustomFields/index.html?'.$m->comp('/Elements/QueryString', Type => 'RT::Class-RT::Article'),
-    );
-    $cfs->child( create =>
-        title => loc('Create'),
-        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'),
-        path        => '/Admin/Global/GroupRights.html',
-    );
-    $admin_global->child( 'user-rights' =>
-        title       => loc('User Rights'),
-        description => loc('Modify global user rights'),
-        path        => '/Admin/Global/UserRights.html',
-    );
-    $admin_global->child( 'my-rt' =>
-        title       => loc('RT at a glance'),
-        description => loc('Modify the default "RT at a glance" view'),
-        path        => '/Admin/Global/MyRT.html',
-    );
-    $admin_global->child( 'dashboards-in-menu' =>
-        title       => loc('Dashboards in menu'),
-        description => loc('Customize dashboards in menu'),
-        path        => '/Admin/Global/DashboardsInMenu.html',
-    );
-    $admin_global->child( 'topics' =>
-        title       => loc('Topics'),
-        description => loc('Modify global article topics'),
-        path        => '/Admin/Global/Topics.html',
-    );
-
-    my $admin_tools = $admin->child( tools =>
-        title       => loc('Tools'),
-        description => loc('Use other RT administrative tools'),
-        path        => '/Admin/Tools/',
-    );
-    $admin_tools->child( configuration =>
-        title       => loc('System Configuration'),
-        description => loc('Detailed information about your RT setup'),
-        path        => '/Admin/Tools/Configuration.html',
-    );
-    $admin_tools->child( theme =>
-        title       => loc('Theme'),
-        description => loc('Customize the look of your RT'),
-        path        => '/Admin/Tools/Theme.html',
-    );
-    if (RT->Config->Get('StatementLog')
-        && $session{'CurrentUser'}->HasRight( Right => 'SuperUser', Object => RT->System )) {
-       $admin_tools->child( 'sql-queries' =>
-           title       => loc('SQL Queries'),
-           description => loc('Browse the SQL queries made in this process'),
-           path        => '/Admin/Tools/Queries.html',
-       );
-    }
-    $admin_tools->child( shredder =>
-        title       => loc('Shredder'),
-        description => loc('Permanently wipeout data from RT'),
-        path        => '/Admin/Tools/Shredder',
-    );
-
-    if ( $request_path =~ m{^/Admin/(Queues|Users|Groups|CustomFields|CustomRoles)} ) {
-        my $type = $1;
-        my $tabs = PageMenu();
-
-        my %labels = (
-            Queues       => loc("Queues"),
-            Users        => loc("Users"),
-            Groups       => loc("Groups"),
-            CustomFields => loc("Custom Fields"),
-            CustomRoles  => loc("Custom Roles"),
-        );
-
-        my $section;
-        if ( $request_path =~ m|^/Admin/$type/?(?:index.html)?$|
-             || (    $request_path =~ m|^/Admin/$type/(?:Modify.html)$|
-                  && $DECODED_ARGS->{'Create'} )
-           )
-        {
-            $section = $tabs;
-
-        } else {
-            $section = $tabs->child( select => title => $labels{$type},
-                                     path => "/Admin/$type/" );
-        }
-
-        $section->child( select => title => loc('Select'), path => "/Admin/$type/" );
-        $section->child( create => title => loc('Create'), path => "/Admin/$type/Modify.html?Create=1" );
-    }
-
-    if ( $request_path =~ m{^/Admin/Queues} ) {
-        if ( $DECODED_ARGS->{'id'} && $DECODED_ARGS->{'id'} =~ /^\d+$/
-                ||
-              $DECODED_ARGS->{'Queue'} && $DECODED_ARGS->{'Queue'} =~ /^\d+$/
-                ) {
-            my $id = $DECODED_ARGS->{'Queue'} || $DECODED_ARGS->{'id'};
-            my $queue_obj = RT::Queue->new( $session{'CurrentUser'} );
-            $queue_obj->Load($id);
-
-            if ( $queue_obj and $queue_obj->id ) {
-                my $queue = PageMenu();
-                $queue->child( basics => title => loc('Basics'),   path => "/Admin/Queues/Modify.html?id=" . $id );
-                $queue->child( people => title => loc('Watchers'), path => "/Admin/Queues/People.html?id=" . $id );
-
-                my $templates = $queue->child(templates => title => loc('Templates'), path => "/Admin/Queues/Templates.html?id=" . $id);
-                $templates->child( select => title => loc('Select'), path => "/Admin/Queues/Templates.html?id=".$id);
-                $templates->child( create => title => loc('Create'), path => "/Admin/Queues/Template.html?Create=1;Queue=".$id);
-
-                my $scrips = $queue->child( scrips => title => loc('Scrips'), path => "/Admin/Queues/Scrips.html?id=" . $id);
-                $scrips->child( select => title => loc('Select'), path => "/Admin/Queues/Scrips.html?id=" . $id );
-                $scrips->child( create => title => loc('Create'), path => "/Admin/Scrips/Create.html?Queue=" . $id);
-
-                my $cfs = $queue->child( 'custom-fields' => title => loc('Custom Fields') );
-                my $ticket_cfs = $cfs->child( 'tickets' => title => loc('Tickets'),
-                    path => '/Admin/Queues/CustomFields.html?SubType=RT::Ticket&id=' . $id );
-
-                my $txn_cfs = $cfs->child( 'transactions' => title => loc('Transactions'),
-                    path => '/Admin/Queues/CustomFields.html?SubType=RT::Ticket-RT::Transaction&id='.$id );
-
-                $queue->child( 'group-rights' => title => loc('Group Rights'), path => "/Admin/Queues/GroupRights.html?id=".$id );
-                $queue->child( 'user-rights' => title => loc('User Rights'), path => "/Admin/Queues/UserRights.html?id=" . $id );
-                $queue->child( 'history' => title => loc('History'), path => "/Admin/Queues/History.html?id=" . $id );
-                $queue->child( 'default-values' => title => loc('Default Values'), path => "/Admin/Queues/DefaultValues.html?id=" . $id );
-
-                $m->callback( CallbackName => 'PrivilegedQueue', queue_id => $id, page_menu => $queue);
-            }
-        }
-    }
-    if ( $request_path =~ m{^(/Admin/Users|/User/(Summary|History)\.html)} and $admin->child("users") ) {
-        if ( $DECODED_ARGS->{'id'} && $DECODED_ARGS->{'id'} =~ /^\d+$/ ) {
-            my $id = $DECODED_ARGS->{'id'};
-            my $obj = RT::User->new( $session{'CurrentUser'} );
-            $obj->Load($id);
-
-            if ( $obj and $obj->id ) {
-                my $tabs = PageMenu();
-                $tabs->child( basics      => title => loc('Basics'),         path => "/Admin/Users/Modify.html?id=" . $id );
-                $tabs->child( memberships => title => loc('Memberships'),    path => "/Admin/Users/Memberships.html?id=" . $id );
-                $tabs->child( history     => title => loc('History'),        path => "/Admin/Users/History.html?id=" . $id );
-                $tabs->child( 'my-rt'     => title => loc('RT at a glance'), path => "/Admin/Users/MyRT.html?id=" . $id );
-                $tabs->child( 'dashboards-in-menu' =>
-                    title => loc('Dashboards in menu'),
-                    path  => '/Admin/Users/DashboardsInMenu.html?id=' . $id,
-                );
-                if ( RT->Config->Get('Crypt')->{'Enable'} ) {
-                    $tabs->child( keys    => title => loc('Private keys'),   path => "/Admin/Users/Keys.html?id=" . $id );
-                }
-                $tabs->child( 'summary'   => title => loc('User Summary'),   path => "/User/Summary.html?id=" . $id );
-            }
-        }
-
-    }
-
-    if ( $request_path =~ m{^/Admin/Groups} ) {
-        if ( $DECODED_ARGS->{'id'} && $DECODED_ARGS->{'id'} =~ /^\d+$/ ) {
-            my $id = $DECODED_ARGS->{'id'};
-            my $obj = RT::Group->new( $session{'CurrentUser'} );
-            $obj->Load($id);
-
-            if ( $obj and $obj->id ) {
-                my $tabs = PageMenu();
-                $tabs->child( basics         => title => loc('Basics'),       path => "/Admin/Groups/Modify.html?id=" . $obj->id );
-                $tabs->child( members        => title => loc('Members'),      path => "/Admin/Groups/Members.html?id=" . $obj->id );
-                $tabs->child( memberships    => title => loc('Memberships'),  path => "/Admin/Groups/Memberships.html?id=" . $obj->id );
-                $tabs->child( 'group-rights' => title => loc('Group Rights'), path => "/Admin/Groups/GroupRights.html?id=" . $obj->id );
-                $tabs->child( 'user-rights'  => title => loc('User Rights'),  path => "/Admin/Groups/UserRights.html?id=" . $obj->id );
-                $tabs->child( history        => title => loc('History'),      path => "/Admin/Groups/History.html?id=" . $obj->id );
-            }
-        }
-    }
-
-    if ( $request_path =~ m{^/Admin/CustomFields/} ) {
-        if ( $DECODED_ARGS->{'id'} && $DECODED_ARGS->{'id'} =~ /^\d+$/ ) {
-            my $id = $DECODED_ARGS->{'id'};
-            my $obj = RT::CustomField->new( $session{'CurrentUser'} );
-            $obj->Load($id);
-
-            if ( $obj and $obj->id ) {
-                my $tabs = PageMenu();
-                $tabs->child( basics           => title => loc('Basics'),       path => "/Admin/CustomFields/Modify.html?id=".$id );
-                $tabs->child( 'group-rights'   => title => loc('Group Rights'), path => "/Admin/CustomFields/GroupRights.html?id=" . $id );
-                $tabs->child( 'user-rights'    => title => loc('User Rights'),  path => "/Admin/CustomFields/UserRights.html?id=" . $id );
-                unless ( $obj->IsOnlyGlobal ) {
-                    $tabs->child( 'applies-to' => title => loc('Applies to'),   path => "/Admin/CustomFields/Objects.html?id=" . $id );
-                }
-            }
-        }
-    }
-
-    if ( $request_path =~ m{^/Admin/CustomRoles} ) {
-        if ( $DECODED_ARGS->{'id'} && $DECODED_ARGS->{'id'} =~ /^\d+$/ ) {
-            my $id = $DECODED_ARGS->{'id'};
-            my $obj = RT::CustomRole->new( $session{'CurrentUser'} );
-            $obj->Load($id);
-
-            if ( $obj and $obj->id ) {
-                my $tabs = PageMenu();
-                $tabs->child( basics       => title => loc('Basics'),       path => "/Admin/CustomRoles/Modify.html?id=".$id );
-                $tabs->child( 'applies-to' => title => loc('Applies to'),   path => "/Admin/CustomRoles/Objects.html?id=" . $id );
-            }
-        }
-    }
-
-    if ( $request_path =~ m{^/Admin/Scrips/} ) {
-        if ( $m->request_args->{'id'} && $m->request_args->{'id'} =~ /^\d+$/ ) {
-            my $id = $m->request_args->{'id'};
-            my $obj = RT::Scrip->new( $session{'CurrentUser'} );
-            $obj->Load($id);
-
-            my $tabs = PageMenu();
-
-            my ( $admin_cat, $create_path_arg, $from_query_param );
-            my $from_arg = $DECODED_ARGS->{'From'} || q{};
-            my ($from_queue) = $from_arg =~ /^(\d+)$/;
-            if ( $from_queue ) {
-                $admin_cat = "Queues/Scrips.html?id=$from_queue";
-                $create_path_arg = "?Queue=$from_queue";
-                $from_query_param = "&From=$from_queue";
-            }
-            elsif ( $from_arg eq 'Global' ) {
-                $admin_cat = 'Global/Scrips.html';
-                $create_path_arg = '?Global=1';
-                $from_query_param = '&From=Global';
-            }
-            else {
-                $admin_cat = 'Scrips';
-                $from_query_param = $create_path_arg = q{};
-            }
-            my $scrips = $tabs->child( scrips => title => loc('Scrips'), path => "/Admin/${admin_cat}" );
-            $scrips->child( select => title => loc('Select'), path => "/Admin/${admin_cat}" );
-            $scrips->child( create => title => loc('Create'), path => "/Admin/Scrips/Create.html${create_path_arg}" );
-
-            $tabs->child( basics => title => loc('Basics') => path => "/Admin/Scrips/Modify.html?id=" . $id . $from_query_param );
-            $tabs->child( 'applies-to' => title => loc('Applies to'), path => "/Admin/Scrips/Objects.html?id=" . $id . $from_query_param );
-        }
-        elsif ( $request_path =~ m{^/Admin/Scrips/(index\.html)?$} ) {
-            PageMenu->child( select => title => loc('Select') => path => "/Admin/Scrips/" );
-            PageMenu->child( create => title => loc('Create') => path => "/Admin/Scrips/Create.html" );
-        }
-        elsif ( $request_path =~ m{^/Admin/Scrips/Create\.html$} ) {
-            my ($queue) = $DECODED_ARGS->{'Queue'} && $DECODED_ARGS->{'Queue'} =~ /^(\d+)$/;
-            my $global_arg = $DECODED_ARGS->{'Global'};
-            if ($queue) {
-                PageMenu->child( select => title => loc('Select') => path => "/Admin/Queues/Scrips.html?id=$queue" );
-                PageMenu->child( create => title => loc('Create') => path => "/Admin/Scrips/Create.html?Queue=$queue" );
-            } elsif ($global_arg) {
-                PageMenu->child( select => title => loc('Select') => path => "/Admin/Global/Scrips.html" );
-                PageMenu->child( create => title => loc('Create') => path => "/Admin/Scrips/Create.html?Global=1" );
-            } else {
-                PageMenu->child( select => title => loc('Select') => path => "/Admin/Scrips" );
-                PageMenu->child( create => title => loc('Create') => path => "/Admin/Scrips/Create.html" );
-            }
-        }
-    }
-
-    if ( $request_path =~ m{^/Admin/Global/Scrips\.html} ) {
-        my $tabs = PageMenu();
-        $tabs->child( select => title => loc('Select'), path => "/Admin/Global/Scrips.html" );
-        $tabs->child( create => title => loc('Create'), path => "/Admin/Scrips/Create.html?Global=1" );
-    }
-
-    if ( $request_path =~ m{^/Admin/Global/Templates?\.html} ) {
-        my $tabs = PageMenu();
-        $tabs->child( select => title => loc('Select'), path => "/Admin/Global/Templates.html" );
-        $tabs->child( create => title => loc('Create'), path => "/Admin/Global/Template.html?Create=1" );
-    }
-
-    if ( $request_path =~ m{^/Admin/Articles/Classes/} ) {
-        my $tabs = PageMenu();
-        if ( my $id = $DECODED_ARGS->{'id'} ) {
-            my $obj = RT::Class->new( $session{'CurrentUser'} );
-            $obj->Load($id);
-
-            if ( $obj and $obj->id ) {
-                my $section = $tabs->child( select => title => loc("Classes"), path => "/Admin/Articles/Classes/" );
-                $section->child( select => title => loc('Select'), path => "/Admin/Articles/Classes/" );
-                $section->child( create => title => loc('Create'), path => "/Admin/Articles/Classes/Modify.html?Create=1" );
-
-                $tabs->child( basics          => title => loc('Basics'),        path => "/Admin/Articles/Classes/Modify.html?id=".$id );
-                $tabs->child( topics          => title => loc('Topics'),        path => "/Admin/Articles/Classes/Topics.html?id=".$id );
-                $tabs->child( 'custom-fields' => title => loc('Custom Fields'), path => "/Admin/Articles/Classes/CustomFields.html?id=".$id );
-                $tabs->child( 'group-rights'  => title => loc('Group Rights'),  path => "/Admin/Articles/Classes/GroupRights.html?id=".$id );
-                $tabs->child( 'user-rights'   => title => loc('User Rights'),   path => "/Admin/Articles/Classes/UserRights.html?id=".$id );
-                $tabs->child( 'applies-to'    => title => loc('Applies to'),    path => "/Admin/Articles/Classes/Objects.html?id=$id" );
-            }
-        } else {
-            $tabs->child( select => title => loc('Select'), path => "/Admin/Articles/Classes/" );
-            $tabs->child( create => title => loc('Create'), path => "/Admin/Articles/Classes/Modify.html?Create=1" );
-        }
-    }
-};
-
-my $build_main_nav = sub {
-
-    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'}) {
-        my $dashboards_in_menu = $session{CurrentUser}->UserObj->Preferences(
-            'DashboardsInMenu',
-            {},
-        );
-
-        unless ($dashboards_in_menu->{dashboards}) {
-            my ($default_dashboards) =
-                RT::System->new( $session{'CurrentUser'} )
-                    ->Attributes
-                    ->Named('DashboardsInMenu');
-            if ($default_dashboards) {
-                $dashboards_in_menu = $default_dashboards->Content;
-            }
-        }
-
-        $session{'dashboards_in_menu'} = $dashboards_in_menu->{dashboards} || [];
-    }
-
-    my @dashboards;
-    for my $id ( @{$session{'dashboards_in_menu'}} ) {
-        my $dash = RT::Dashboard->new( $session{CurrentUser} );
-        my ( $status, $msg ) = $dash->LoadById($id);
-        if ( $status ) {
-            push @dashboards, $dash;
-        } else {
-            $RT::Logger->warning( "Failed to load dashboard $id: $msg" );
-        }
-    }
-
-    my $dashes = Menu()->child('home');
-    if (@dashboards) {
-        for my $dash (@dashboards) {
-            $home->child( 'dashboard-' . $dash->id,
-                title => $dash->Name,
-                path  => '/Dashboards/' . $dash->id . '/' . $dash->Name
-            );
-        }
-    }
-    $dashes->child( edit => title => loc('Update This Menu'), path => 'Prefs/DashboardsInMenu.html' );
-    $dashes->child( more => title => loc('All Dashboards'),   path => 'Dashboards/index.html' );
-    my $dashboard = RT::Dashboard->new( $session{CurrentUser} );
-    if ( $dashboard->CurrentUserCanCreateAny ) {
-        $dashes->child('dashboard_create' => title => loc('New Dashboard'), path => "/Dashboards/Modify.html?Create=1" );
-    }
-
-    my $search = Menu->child( search => title => loc('Search'), path => '/Search/Simple.html' );
-
-    my $tickets = $search->child( tickets => title => loc('Tickets'), path => '/Search/Build.html' );
-    $tickets->child( simple => title => loc('Simple Search'), path => "/Search/Simple.html" );
-    $tickets->child( new    => title => loc('New Search'),    path => "/Search/Build.html?NewQuery=1" );
-
-    $search->child( articles => title => loc('Articles'),   path => "/Articles/Article/Search.html" )
-        if $session{CurrentUser}->HasRight( Right => 'ShowArticlesMenu', Object => RT->System );
-
-    $search->child( users => title => loc('Users'),   path => "/User/Search.html" );
-
-    $search->child( assets => title => loc("Assets"), path => "/Asset/Search/" )
-        if $session{CurrentUser}->HasRight( Right => 'ShowAssetsMenu', Object => RT->System );
-
-    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( topics   => title => loc('Topics'),   path => "/Articles/Topics.html" );
-        $articles->child( create   => title => loc('Create'),   path => "/Articles/Article/PreCreate.html" );
-        $articles->child( search   => title => loc('Search'),   path => "/Articles/Article/Search.html" );
-    }
-
-    if ($session{CurrentUser}->HasRight( Right => 'ShowAssetsMenu', Object => RT->System )) {
-        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 =>
-        title       => loc('My Day'),
-        description => loc('Easy updating of your open tickets'),
-        path        => '/Tools/MyDay.html',
-    );
-
-    if ( RT->Config->Get('EnableReminders') ) {
-        $tools->child( my_reminders =>
-            title       => loc('My Reminders'),
-            description => loc('Easy viewing of your reminders'),
-            path        => '/Tools/MyReminders.html',
-        );
-    }
-
-    if ( $session{'CurrentUser'}->HasRight( Right => 'ShowApprovalsTab', Object => RT->System ) ) {
-        $tools->child( approval =>
-            title       => loc('Approval'),
-            description => loc('My Approvals'),
-            path        => '/Approvals/',
-        );
-    }
-
-    if ( $session{'CurrentUser'}->HasRight( Right => 'ShowConfigTab', Object => RT->System ) )
-    {
-        $build_admin_menu->(Menu());
-    }
-
-    my $username = '<span class="current-user">'
-                 . $m->interp->apply_escapes($session{'CurrentUser'}->Name, 'h')
-                 . '</span>';
-    my $about_me = Menu->child( 'preferences' =>
-        title        => loc('Logged in as [_1]', $username),
-        escape_title => 0,
-        path         => '/User/Summary.html?id=' . $session{CurrentUser}->id,
-        sort_order   => 99,
-    );
-
-
-    if ( $session{'CurrentUser'}->UserObj
-         && $session{'CurrentUser'}->HasRight( Right => 'ModifySelf', Object => RT->System )) {
-        my $settings = $about_me->child( settings => title => loc('Settings'), path => '/Prefs/Other.html' );
-        $settings->child( options        => title => loc('Preferences'),        path => '/Prefs/Other.html' );
-        $settings->child( about_me       => title => loc('About me'),       path => '/Prefs/AboutMe.html' );
-        $settings->child( search_options => title => loc('Search options'), path => '/Prefs/SearchOptions.html' );
-        $settings->child( myrt           => title => loc('RT at a glance'), path => '/Prefs/MyRT.html' );
-        $settings->child( dashboards_in_menu =>
-            title => loc('Dashboards in menu'),
-            path  => '/Prefs/DashboardsInMenu.html',
-        );
-        $settings->child( queue_list    => title => loc('Queue list'),   path => '/Prefs/QueueList.html' );
-
-        my $search_menu = $settings->child( 'saved-searches' => title => loc('Saved Searches') );
-        my $searches = [ $m->comp( "/Search/Elements/SearchesForObject",
-                          Object => RT::System->new( $session{'CurrentUser'} )) ];
-        my $i = 0;
-
-        for my $search (@$searches) {
-            $search_menu->child( "search-" . $i++ =>
-                title => $search->[1],
-                path  => "/Prefs/Search.html?"
-                       . $query_string->( name => ref( $search->[2] ) . '-' . $search->[2]->Id ),
-            );
-
-        }
-    }
-    if ( $session{'CurrentUser'}->Name
-         && (   !RT->Config->Get('WebRemoteUserAuth')
-              || RT->Config->Get('WebFallbackToRTLogin') )) {
-        $about_me->child( logout => title => loc('Logout'), path => '/NoAuth/Logout.html' );
-    }
-    if ( $request_path =~ m{^/Dashboards/(\d+)?}) {
-        if ( my $id = ( $1 || $DECODED_ARGS->{'id'} ) ) {
-            my $obj = RT::Dashboard->new( $session{'CurrentUser'} );
-            $obj->LoadById($id);
-            if ( $obj and $obj->id ) {
-                my $tabs = PageMenu;
-                $tabs->child( basics       => title => loc('Basics'),       path => "/Dashboards/Modify.html?id=" . $obj->id);
-                $tabs->child( content      => title => loc('Content'),      path => "/Dashboards/Queries.html?id=" . $obj->id);
-                $tabs->child( subscription => title => loc('Subscription'), path => "/Dashboards/Subscription.html?id=" . $obj->id)
-                    if $obj->CurrentUserCanSubscribe;
-                $tabs->child( show         => title => loc('Show'),         path => "/Dashboards/" . $obj->id . "/" . $obj->Name)
-            }
-        }
-    }
-
-
-    if ( $request_path =~ m{^/Ticket/} ) {
-        if ( ( $DECODED_ARGS->{'id'} || '' ) =~ /^(\d+)$/ ) {
-            my $id  = $1;
-            my $obj = RT::Ticket->new( $session{'CurrentUser'} );
-            $obj->Load($id);
-
-            if ( $obj and $obj->id ) {
-                my $actions = PageMenu()->child( actions => title => loc('Actions'), sort_order  => 95 );
-
-                my %can = %{ $obj->CurrentUser->PrincipalObj->HasRights( Object => $obj ) };
-                $can{'_ModifyOwner'} = $obj->CurrentUserCanSetOwner();
-                my $can = sub {
-                    unless ($_[0] eq 'ExecuteCode') {
-                        return $can{$_[0]} || $can{'SuperUser'};
-                    } else {
-                        return !RT->Config->Get('DisallowExecuteCode')
-                            && ( $can{'ExecuteCode'} || $can{'SuperUser'} );
-                    }
-                };
-
-                my $tabs = PageMenu();
-                $tabs->child( bookmark => raw_html => $m->scomp( '/Ticket/Elements/Bookmark', id => $id ), sort_order => 98 );
-
-                if ($can->('ModifyTicket')) {
-                    $tabs->child( timer => raw_html => $m->scomp( '/Ticket/Elements/PopupTimerLink', id => $id ), sort_order => 99 );
-                }
-
-                $tabs->child( display => title => loc('Display'), path => "/Ticket/Display.html?id=" . $id );
-                $tabs->child( history => title => loc('History'), path => "/Ticket/History.html?id=" . $id );
-
-                # comment out until we can do it for an individual custom field
-                #if ( $can->('ModifyTicket') || $can->('ModifyCustomField') ) {
-                $tabs->child( basics => title => loc('Basics'), path => "/Ticket/Modify.html?id=" . $id );
-
-                #}
-
-                if ( $can->('ModifyTicket') || $can->('_ModifyOwner') || $can->('Watch') || $can->('WatchAsAdminCc') ) {
-                    $tabs->child( people => title => loc('People'), path => "/Ticket/ModifyPeople.html?id=" . $id );
-                }
-
-                if ( $can->('ModifyTicket') ) {
-                    $tabs->child( dates => title => loc('Dates'), path => "/Ticket/ModifyDates.html?id=" . $id );
-                    $tabs->child( links => title => loc('Links'), path => "/Ticket/ModifyLinks.html?id=" . $id );
-                }
-
-                #if ( $can->('ModifyTicket') || $can->('ModifyCustomField') || $can->('_ModifyOwner') ) {
-                $tabs->child( jumbo => title => loc('Jumbo'), path => "/Ticket/ModifyAll.html?id=" . $id );
-                #}
-
-                if ( RT->Config->Get('EnableReminders') ) {
-                    $tabs->child( reminders => title => loc('Reminders'), path => "/Ticket/Reminders.html?id=" . $id );
-                }
-
-                if ( $can->('ModifyTicket') or $can->('ReplyToTicket') ) {
-                    $actions->child( reply => title => loc('Reply'), path => "/Ticket/Update.html?Action=Respond;id=" . $id );
-                }
-
-                if ( $can->('ModifyTicket') or $can->('CommentOnTicket') ) {
-                    $actions->child( comment => title => loc('Comment'), path => "/Ticket/Update.html?Action=Comment;id=" . $id );
-                }
-
-                if ( $can->('ForwardMessage') ) {
-                    $actions->child( forward => title => loc('Forward'), path => "/Ticket/Forward.html?id=" . $id );
-                }
-
-                my $hide_resolve_with_deps = RT->Config->Get('HideResolveActionsWithDependencies')
-                    && $obj->HasUnresolvedDependencies;
-
-                my $current   = $obj->Status;
-                my $lifecycle = $obj->LifecycleObj;
-                my $i         = 1;
-                foreach my $info ( $lifecycle->Actions($current) ) {
-                    my $next = $info->{'to'};
-                    next unless $lifecycle->IsTransition( $current => $next );
-
-                    my $check = $lifecycle->CheckRight( $current => $next );
-                    next unless $can->($check);
-
-                    next if $hide_resolve_with_deps
-                        && $lifecycle->IsInactive($next)
-                        && !$lifecycle->IsInactive($current);
-
-                    my $action = $info->{'update'} || '';
-                    my $url = '/Ticket/';
-                    $url .= "Update.html?". $query_string->(
-                        $action
-                            ? (Action        => $action)
-                            : (SubmitTicket  => 1, Status => $next),
-                        DefaultStatus => $next,
-                        id            => $id,
-                    );
-                    my $key = $info->{'label'} || ucfirst($next);
-                    $actions->child( $key => title => loc( $key ), path => $url);
-                }
-
-                my ($can_take, $tmsg) = $obj->CurrentUserCanSetOwner( Type => 'Take' );
-                my ($can_steal, $smsg) = $obj->CurrentUserCanSetOwner( Type => 'Steal' );
-                if ( $can_take ){
-                    $actions->child( take => title => loc('Take'), path => "/Ticket/Display.html?Action=Take;id=" . $id );
-                }
-                elsif ( $can_steal ){
-                    $actions->child( steal => title => loc('Steal'), path => "/Ticket/Display.html?Action=Steal;id=" . $id );
-                }
-
-                # TODO needs a "Can extract article into a class applied to this queue" check
-                $actions->child( 'extract-article' =>
-                    title => loc('Extract Article'),
-                    path  => "/Articles/Article/ExtractIntoClass.html?Ticket=".$obj->id,
-                ) if $session{CurrentUser}->HasRight( Right => 'ShowArticlesMenu', Object => RT->System );
-
-                if ( defined $session{"tickets"} ) {
-                    # we have to update session data if we get new ItemMap
-                    my $updatesession = 1 unless ( $session{"tickets"}->{'item_map'} );
-
-                    my $item_map = $session{"tickets"}->ItemMap;
-
-                    if ($updatesession) {
-                        $session{"tickets"}->PrepForSerialization();
-                    }
-
-                    my $search = Menu()->child('search')->child('tickets');
-                    # Don't display prev links if we're on the first ticket
-                    if ( $item_map->{$id}->{prev} ) {
-                        $search->child( first =>
-                            title => '<< ' . loc('First'), class => "nav", path => "/Ticket/Display.html?id=" . $item_map->{first});
-                        $search->child( prev =>
-                            title => '< ' . loc('Prev'),   class => "nav", path => "/Ticket/Display.html?id=" . $item_map->{$id}->{prev});
-                    }
-                    # Don't display next links if we're on the last ticket
-                    if ( $item_map->{$id}->{next} ) {
-                        $search->child( next =>
-                            title => loc('Next') . ' >',  class => "nav", path => "/Ticket/Display.html?id=" . $item_map->{$id}->{next});
-                        if ( $item_map->{last} ) {
-                            $search->child( last =>
-                                title => loc('Last') . ' >>', class => "nav", path => "/Ticket/Display.html?id=" . $item_map->{last});
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    if (
-        (
-               $request_path =~ m{^/(?:Ticket|Search)/}
-            && $request_path !~ m{^/Search/Simple\.html}
-        )
-        || (   $request_path =~ m{^/Search/Simple\.html}
-            && $DECODED_ARGS->{'q'} )
-      )
-    {
-        my $search = Menu()->child('search')->child('tickets');
-        my $args      = '';
-        my $has_query = '';
-        my $current_search = $session{"CurrentSearchHash"} || {};
-        my $search_id = $DECODED_ARGS->{'SavedSearchLoad'} || $DECODED_ARGS->{'SavedSearchId'} || $current_search->{'SearchId'} || '';
-        my $chart_id = $DECODED_ARGS->{'SavedChartSearchId'} || $current_search->{SavedChartSearchId};
-
-        $has_query = 1 if ( $DECODED_ARGS->{'Query'} or $current_search->{'Query'} );
-
-        my %query_args;
-        my %fallback_query_args = (
-            SavedSearchId => ( $search_id eq 'new' ) ? undef : $search_id,
-            SavedChartSearchId => $chart_id,
-            (
-                map {
-                    my $p = $_;
-                    $p => $DECODED_ARGS->{$p} || $current_search->{$p}
-                } qw(Query Format OrderBy Order Page)
-            ),
-            RowsPerPage => (
-                defined $DECODED_ARGS->{'RowsPerPage'}
-                ? $DECODED_ARGS->{'RowsPerPage'}
-                : $current_search->{'RowsPerPage'}
-            ),
-        );
-
-        if ($QueryString) {
-            $args = '?' . $QueryString;
-        }
-        else {
-            my %final_query_args = ();
-            # key => callback to avoid unnecessary work
-
-            for my $param (keys %fallback_query_args) {
-                $final_query_args{$param} = defined($QueryArgs->{$param})
-                                          ? $QueryArgs->{$param}
-                                          : $fallback_query_args{$param};
-            }
-
-            for my $field (qw(Order OrderBy)) {
-                if ( ref( $final_query_args{$field} ) eq 'ARRAY' ) {
-                    $final_query_args{$field} = join( "|", @{ $final_query_args{$field} } );
-                } elsif (not defined $final_query_args{$field}) {
-                    delete $final_query_args{$field};
-                }
-                else {
-                    $final_query_args{$field} ||= '';
-                }
-            }
-
-            $args = '?' . $query_string->(%final_query_args);
-        }
-
-        my $current_search_menu;
-        if ( $request_path =~ m{^/Ticket} ) {
-            $current_search_menu = $search->child( current_search => title => loc('Current Search') );
-            $current_search_menu->path("/Search/Results.html$args") if $has_query;
-        } else {
-            $current_search_menu = PageMenu();
-        }
-
-        $current_search_menu->child( edit_search =>
-            title => loc('Edit Search'), path => "/Search/Build.html" . ( ($has_query) ? $args : '' ) );
-        $current_search_menu->child( advanced =>
-            title => loc('Advanced'),    path => "/Search/Edit.html$args" );
-        if ($has_query) {
-            $current_search_menu->child( results => title => loc('Show Results'), path => "/Search/Results.html$args" );
-        }
-
-        if ( $has_query ) {
-            $current_search_menu->child( bulk  => title => loc('Bulk Update'), path => "/Search/Bulk.html$args" );
-            $current_search_menu->child( chart => title => loc('Chart'),       path => "/Search/Chart.html$args" );
-
-            my $more = $current_search_menu->child( more => title => loc('Feeds') );
-
-            $more->child( spreadsheet => title => loc('Spreadsheet'), path => "/Search/Results.tsv$args" );
-
-            my %rss_data = map {
-                $_ => $QueryArgs->{$_} || $fallback_query_args{$_} || '' }
-                    qw(Query Order OrderBy);
-            my $RSSQueryString = "?"
-                . $query_string->( Query   => $rss_data{Query},
-                                   Order   => $rss_data{Order},
-                                   OrderBy => $rss_data{OrderBy}
-                                 );
-            my $RSSPath = join '/', map $m->interp->apply_escapes( $_, 'u' ),
-                $session{'CurrentUser'}->UserObj->Name,
-                $session{'CurrentUser'}
-                ->UserObj->GenerateAuthString(   $rss_data{Query}
-                                               . $rss_data{Order}
-                                               . $rss_data{OrderBy} );
-
-            $more->child( rss => title => loc('RSS'), path => "/NoAuth/rss/$RSSPath/$RSSQueryString");
-            my $ical_path = join '/', map $m->interp->apply_escapes($_, 'u'),
-                $session{'CurrentUser'}->UserObj->Name,
-                $session{'CurrentUser'}->UserObj->GenerateAuthString( $rss_data{Query} ),
-                $rss_data{Query};
-            $more->child( ical => title => loc('iCal'), path => '/NoAuth/iCal/'.$ical_path);
-
-            if ($request_path =~ m{^/Search/Results.html}
-                &&                        #XXX TODO better abstraction
-                $session{'CurrentUser'}->HasRight( Right => 'SuperUser', Object => RT->System )) {
-                my $shred_args = $query_string->(
-                    Search          => 1,
-                    Plugin          => 'Tickets',
-                    'Tickets:query' => $rss_data{'Query'},
-                    'Tickets:limit' => $QueryArgs->{'Rows'},
-                );
-
-                $more->child( shredder => title => loc('Shredder'), path => '/Admin/Tools/Shredder/?' . $shred_args);
-            }
-
-        }
-    }
-
-    if ( $request_path =~ m{^/Article/} ) {
-        if ( $DECODED_ARGS->{'id'} && $DECODED_ARGS->{'id'} =~ /^\d+$/ ) {
-            my $id = $DECODED_ARGS->{'id'};
-            my $tabs = PageMenu();
-
-            $tabs->child( display => title => loc('Display'), path => "/Articles/Article/Display.html?id=".$id );
-            $tabs->child( history => title => loc('History'), path => "/Articles/Article/History.html?id=".$id );
-            $tabs->child( modify  => title => loc('Modify'),  path => "/Articles/Article/Edit.html?id=".$id );
-        }
-    }
-
-    if ( $request_path =~ m{^/Articles/} ) {
-        PageWidgets()->child( article_search => raw_html => $m->scomp('/Articles/Elements/GotoArticle') );
-        PageWidgets()->delete('create_ticket');
-        PageWidgets()->delete('simple_search');
-
-        my $tabs = PageMenu();
-        $tabs->child( search => title => loc("Search"),       path => "/Articles/Article/Search.html" );
-        $tabs->child( create => title => loc("New Article" ), path => "/Articles/Article/PreCreate.html" );
-        if ( $request_path =~ m{^/Articles/Article/} and ( $DECODED_ARGS->{'id'} || '' ) =~ /^(\d+)$/ ) {
-            my $id  = $1;
-            my $obj = RT::Article->new( $session{'CurrentUser'} );
-            $obj->Load($id);
-
-            if ( $obj and $obj->id ) {
-                $tabs->child( display => title => loc("Display"), path => "/Articles/Article/Display.html?id=" . $id );
-                $tabs->child( history => title => loc('History'), path => '/Articles/Article/History.html?id=' . $id );
-
-                if ( $obj->CurrentUserHasRight('ModifyArticle') ) {
-                    $tabs->child(modify => title => loc('Modify'), path => '/Articles/Article/Edit.html?id=' . $id );
-                }
-            }
-        }
-
-    }
-
-    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 $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) : ''),
-            );
-        }
-        $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");
-        }
-    }
-
-    if ( $request_path =~ m{^/User/(Summary|History)\.html} ) {
-        if (PageMenu()->child('summary')) {
-            # Already set up from having AdminUser and ShowConfigTab;
-            # but rename "Basics" to "Edit" in this context
-            PageMenu()->child( 'basics' )->title( loc('Edit') );
-        } elsif ( $session{'CurrentUser'}->HasRight( Object => $RT::System, Right => 'ShowUserHistory' ) ) {
-            PageMenu()->child( display => title => loc('Summary'), path => '/User/Summary.html?id=' . $DECODED_ARGS->{'id'} );
-            PageMenu()->child( history => title => loc('History'), path => '/User/History.html?id=' . $DECODED_ARGS->{'id'} );
-        }
-    }
-
-    if ( $request_path =~ /^\/(?:index.html|$)/ ) {
-        PageMenu()->child( edit => title => loc('Edit'), path => '/Prefs/MyRT.html' );
-    }
-
-    $m->callback( CallbackName => 'Privileged', Path => $request_path );
-};
-
-my $build_selfservice_nav = sub {
-    my $queues = RT::Queues->new( $session{'CurrentUser'} );
-    $queues->UnLimit;
-
-    my $queue_count = 0;
-    my $queue_id;
-
-    while ( my $queue = $queues->Next ) {
-        next unless $queue->CurrentUserHasRight('CreateTicket');
-        $queue_id = $queue->id;
-        $queue_count++;
-        last if ( $queue_count > 1 );
-    }
-
-
-    if ( $queue_count > 1 ) {
-        Menu->child( new => title => loc('New ticket'), path => '/SelfService/CreateTicketInQueue.html' );
-    } elsif ( $queue_id ) {
-        Menu->child( new => title => loc('New ticket'), path => '/SelfService/Create.html?Queue=' . $queue_id );
-    }
-    my $tickets = Menu->child( tickets => title => loc('Tickets'), path => '/SelfService/' );
-    $tickets->child( open   => title => loc('Open tickets'),   path => '/SelfService/' );
-    $tickets->child( closed => title => loc('Closed tickets'), path => '/SelfService/Closed.html' );
-
-    Menu->child( "assets", title => loc("Assets"), path => "/SelfService/Asset/" )
-        if $session{CurrentUser}->HasRight( Right => 'ShowAssetsMenu', Object => RT->System );
-
-    my $username = '<span class="current-user">'
-                 . $m->interp->apply_escapes($session{'CurrentUser'}->Name, 'h')
-                 . '</span>';
-    my $about_me = Menu->child( preferences =>
-        title        => loc('Logged in as [_1]', $username),
-        escape_title => 0,
-        sort_order   => 99,
-    );
-
-    if ( $session{'CurrentUser'}->HasRight( Right => 'ModifySelf', Object => RT->System ) ) {
-        $about_me->child( prefs => title => loc('Preferences'), path => '/SelfService/Prefs.html' );
-    }
-
-    if ( $session{'CurrentUser'}->Name
-         && (   !RT->Config->Get('WebRemoteUserAuth')
-              || RT->Config->Get('WebFallbackToRTLogin') )) {
-        $about_me->child( logout => title => loc('Logout'), path => '/NoAuth/Logout.html' );
-    }
-
-    if ($session{'CurrentUser'}->HasRight( Right => 'ShowArticle', Object => RT->System )) {
-        PageWidgets->child( 'goto-article' => raw_html => $m->scomp('/SelfService/Elements/SearchArticle') );
-    }
-
-    PageWidgets->child( goto => raw_html => $m->scomp('/SelfService/Elements/GotoTicket') );
-
-    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");
-        }
-    }
-
-    $m->callback( CallbackName => 'SelfService', Path => $request_path );
-};
-
-
-
+use RT::Interface::Web::MenuBuilder;
 if ( $request_path !~ m{^/SelfService/} ) {
-    $build_main_nav->();
+    RT::Interface::Web::MenuBuilder::BuildMainNav( $request_path, $QueryString, $QueryArgs );
 } else {
-    $build_selfservice_nav->();
+    RT::Interface::Web::MenuBuilder::BuildSelfServiceNav( $request_path );
 }
-
-
-
-
 </%INIT>
 <%ARGS>
 $show_menu => 1

commit 16bdea4d95726999249d6b5043863c140e986ca7
Author: Dustin Graves <dustin at bestpractical.com>
Date:   Tue May 31 22:04:57 2016 +0000

    refactor asset menu logic into separate functions

diff --git a/lib/RT/Interface/Web/MenuBuilder.pm b/lib/RT/Interface/Web/MenuBuilder.pm
index 66a2a03..9946a6a 100644
--- a/lib/RT/Interface/Web/MenuBuilder.pm
+++ b/lib/RT/Interface/Web/MenuBuilder.pm
@@ -544,57 +544,7 @@ sub BuildMainNav {
     }
 
     if ($request_path =~ m{^/Asset/} and $HTML::Mason::Commands::DECODED_ARGS->{id} and $HTML::Mason::Commands::DECODED_ARGS->{id} !~ /\D/) {
-        my $page  = HTML::Mason::Commands::PageMenu();
-        my $id    = $HTML::Mason::Commands::DECODED_ARGS->{id};
-        my $asset = RT::Asset->new( $HTML::Mason::Commands::session{CurrentUser} );
-        $asset->Load($id);
-
-        if ($asset->id) {
-            $page->child("display",     title => HTML::Mason::Commands::loc("Display"),        path => "/Asset/Display.html?id=$id");
-            $page->child("history",     title => HTML::Mason::Commands::loc("History"),        path => "/Asset/History.html?id=$id");
-            $page->child("basics",      title => HTML::Mason::Commands::loc("Basics"),         path => "/Asset/Modify.html?id=$id");
-            $page->child("links",       title => HTML::Mason::Commands::loc("Links"),          path => "/Asset/ModifyLinks.html?id=$id");
-            $page->child("people",      title => HTML::Mason::Commands::loc("People"),         path => "/Asset/ModifyPeople.html?id=$id");
-            $page->child("dates",       title => HTML::Mason::Commands::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   => HTML::Mason::Commands::loc($grouping),
-                    path    => "/Asset/ModifyCFs.html?id=$id;Grouping=" . $HTML::Mason::Commands::m->interp->apply_escapes($grouping, 'u'),
-                );
-            }
-
-            my $actions = $page->child("actions", title => HTML::Mason::Commands::loc("Actions"));
-            $actions->child("create-linked-ticket", title => HTML::Mason::Commands::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   => HTML::Mason::Commands::loc($label),
-                    path    => "/Asset/Modify.html?id=$id;Update=1;DisplayAfter=1;Status="
-                                . $HTML::Mason::Commands::m->interp->apply_escapes($next, 'u'),
-
-                    class       => "asset-lifecycle-action",
-                    attributes  => {
-                        'data-current-status'   => $status,
-                        'data-next-status'      => $next,
-                    },
-                );
-            }
-        }
+        _BuildAssetMenu();
     } elsif ($request_path =~ m{^/Asset/Search/}) {
         my $page  = HTML::Mason::Commands::PageMenu();
         my %search = map @{$_},
@@ -667,6 +617,71 @@ sub BuildMainNav {
     $HTML::Mason::Commands::m->callback( CallbackName => 'Privileged', Path => $request_path, CallbackPage => '/Elements/Tabs' );
 }
 
+sub _BuildAssetMenu {
+    my $page  = HTML::Mason::Commands::PageMenu();
+    my $current_user = $HTML::Mason::Commands::session{CurrentUser};
+
+    my $id    = $HTML::Mason::Commands::DECODED_ARGS->{id};
+    my $asset = RT::Asset->new( $current_user );
+    $asset->Load($id);
+
+    if ($asset->id) {
+        $page->child("display",     title => HTML::Mason::Commands::loc("Display"),        path => "/Asset/Display.html?id=$id");
+        $page->child("history",     title => HTML::Mason::Commands::loc("History"),        path => "/Asset/History.html?id=$id");
+        $page->child("basics",      title => HTML::Mason::Commands::loc("Basics"),         path => "/Asset/Modify.html?id=$id");
+        $page->child("links",       title => HTML::Mason::Commands::loc("Links"),          path => "/Asset/ModifyLinks.html?id=$id");
+        $page->child("people",      title => HTML::Mason::Commands::loc("People"),         path => "/Asset/ModifyPeople.html?id=$id");
+        $page->child("dates",       title => HTML::Mason::Commands::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   => HTML::Mason::Commands::loc($grouping),
+                path    => "/Asset/ModifyCFs.html?id=$id;Grouping=" . $HTML::Mason::Commands::m->interp->apply_escapes($grouping, 'u'),
+            );
+        }
+
+        _BuildAssetMenuActionSubmenu($asset);
+    }
+}
+
+sub _BuildAssetMenuActionSubmenu {
+    my $asset = shift;
+
+    my $page  = HTML::Mason::Commands::PageMenu();
+    my $id    = $asset->id;
+
+    my $actions = $page->child("actions", title => HTML::Mason::Commands::loc("Actions"));
+    $actions->child("create-linked-ticket", title => HTML::Mason::Commands::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   => HTML::Mason::Commands::loc($label),
+            path    => "/Asset/Modify.html?id=$id;Update=1;DisplayAfter=1;Status="
+                        . $HTML::Mason::Commands::m->interp->apply_escapes($next, 'u'),
+
+            class       => "asset-lifecycle-action",
+            attributes  => {
+                'data-current-status'   => $status,
+                'data-next-status'      => $next,
+            },
+        );
+    }
+}
+
 sub _BuildAdminMenu {
     my $request_path = shift;
     my $top = shift;

commit ad11c4dc43b513dd467a0d4a3fda1a4270c22a8e
Author: Dustin Graves <dustin at bestpractical.com>
Date:   Wed Jun 22 20:42:31 2016 +0000

    clean up repeated calls to HTML::Mason::Commands with variables
    
    this replaces repeated calls to
        HTML::Mason::Commands::Menu() with $top variable
        HTML::Mason::Commands::PageWidgets() with $widgets variable
        HTML::Mason::Commands::PageMenu() with $page variable
        $HTML::Mason::Commands::session{CurrentUser} with $current_user variable

diff --git a/lib/RT/Interface/Web/MenuBuilder.pm b/lib/RT/Interface/Web/MenuBuilder.pm
index 9946a6a..efd0ef7 100644
--- a/lib/RT/Interface/Web/MenuBuilder.pm
+++ b/lib/RT/Interface/Web/MenuBuilder.pm
@@ -71,23 +71,29 @@ sub BuildMainNav {
     my $query_string = shift;
     my $query_args = shift;
 
+    my $top     = HTML::Mason::Commands::Menu();
+    my $widgets = HTML::Mason::Commands::PageWidgets();
+    my $page    = HTML::Mason::Commands::PageMenu();
+
+    my $current_user = $HTML::Mason::Commands::session{CurrentUser};
+
     if ($request_path =~ m{^/Asset/}) {
-        HTML::Mason::Commands::PageWidgets()->child( asset_search => raw_html => $HTML::Mason::Commands::m->scomp('/Asset/Elements/Search') );
+        $widgets->child( asset_search => raw_html => $HTML::Mason::Commands::m->scomp('/Asset/Elements/Search') );
     } else {
-        HTML::Mason::Commands::PageWidgets()->child( simple_search => raw_html => $HTML::Mason::Commands::m->scomp('SimpleSearch') );
-        HTML::Mason::Commands::PageWidgets()->child( create_ticket => raw_html => $HTML::Mason::Commands::m->scomp('CreateTicket') );
+        $widgets->child( simple_search => raw_html => $HTML::Mason::Commands::m->scomp('SimpleSearch') );
+        $widgets->child( create_ticket => raw_html => $HTML::Mason::Commands::m->scomp('CreateTicket') );
     }
 
-    my $home = HTML::Mason::Commands::Menu()->child( home => title => loc('Homepage'), path => '/' );
+    my $home = $top->child( home => title => loc('Homepage'), path => '/' );
     unless ($HTML::Mason::Commands::session{'dashboards_in_menu'}) {
-        my $dashboards_in_menu = $HTML::Mason::Commands::session{CurrentUser}->UserObj->Preferences(
+        my $dashboards_in_menu = $current_user->UserObj->Preferences(
             'DashboardsInMenu',
             {},
         );
 
         unless ($dashboards_in_menu->{dashboards}) {
             my ($default_dashboards) =
-                RT::System->new( $HTML::Mason::Commands::session{'CurrentUser'} )
+                RT::System->new( $current_user )
                     ->Attributes
                     ->Named('DashboardsInMenu');
             if ($default_dashboards) {
@@ -100,7 +106,7 @@ sub BuildMainNav {
 
     my @dashboards;
     for my $id ( @{$HTML::Mason::Commands::session{'dashboards_in_menu'}} ) {
-        my $dash = RT::Dashboard->new( $HTML::Mason::Commands::session{CurrentUser} );
+        my $dash = RT::Dashboard->new( $current_user );
         my ( $status, $msg ) = $dash->LoadById($id);
         if ( $status ) {
             push @dashboards, $dash;
@@ -109,7 +115,7 @@ sub BuildMainNav {
         }
     }
 
-    my $dashes = HTML::Mason::Commands::Menu()->child('home');
+    my $dashes = $top->child('home');
     if (@dashboards) {
         for my $dash (@dashboards) {
             $home->child( 'dashboard-' . $dash->id,
@@ -120,40 +126,40 @@ sub BuildMainNav {
     }
     $dashes->child( edit => title => loc('Update This Menu'), path => 'Prefs/DashboardsInMenu.html' );
     $dashes->child( more => title => loc('All Dashboards'),   path => 'Dashboards/index.html' );
-    my $dashboard = RT::Dashboard->new( $HTML::Mason::Commands::session{CurrentUser} );
+    my $dashboard = RT::Dashboard->new( $current_user );
     if ( $dashboard->CurrentUserCanCreateAny ) {
         $dashes->child('dashboard_create' => title => loc('New Dashboard'), path => "/Dashboards/Modify.html?Create=1" );
     }
 
-    my $search = HTML::Mason::Commands::Menu()->child( search => title => loc('Search'), path => '/Search/Simple.html' );
+    my $search = $top->child( search => title => loc('Search'), path => '/Search/Simple.html' );
 
     my $tickets = $search->child( tickets => title => loc('Tickets'), path => '/Search/Build.html' );
     $tickets->child( simple => title => loc('Simple Search'), path => "/Search/Simple.html" );
     $tickets->child( new    => title => loc('New Search'),    path => "/Search/Build.html?NewQuery=1" );
 
     $search->child( articles => title => loc('Articles'),   path => "/Articles/Article/Search.html" )
-        if $HTML::Mason::Commands::session{CurrentUser}->HasRight( Right => 'ShowArticlesMenu', Object => RT->System );
+        if $current_user->HasRight( Right => 'ShowArticlesMenu', Object => RT->System );
 
     $search->child( users => title => loc('Users'),   path => "/User/Search.html" );
 
     $search->child( assets => title => loc("Assets"), path => "/Asset/Search/" )
-        if $HTML::Mason::Commands::session{CurrentUser}->HasRight( Right => 'ShowAssetsMenu', Object => RT->System );
+        if $current_user->HasRight( Right => 'ShowAssetsMenu', Object => RT->System );
 
-    if ($HTML::Mason::Commands::session{CurrentUser}->HasRight( Right => 'ShowArticlesMenu', Object => RT->System )) {
-        my $articles = HTML::Mason::Commands::Menu()->child( articles => title => loc('Articles'), path => "/Articles/index.html");
+    if ($current_user->HasRight( Right => 'ShowArticlesMenu', Object => RT->System )) {
+        my $articles = $top->child( articles => title => loc('Articles'), path => "/Articles/index.html");
         $articles->child( articles => title => loc('Overview'), path => "/Articles/index.html" );
         $articles->child( topics   => title => loc('Topics'),   path => "/Articles/Topics.html" );
         $articles->child( create   => title => loc('Create'),   path => "/Articles/Article/PreCreate.html" );
         $articles->child( search   => title => loc('Search'),   path => "/Articles/Article/Search.html" );
     }
 
-    if ($HTML::Mason::Commands::session{CurrentUser}->HasRight( Right => 'ShowAssetsMenu', Object => RT->System )) {
-        my $assets = HTML::Mason::Commands::Menu()->child( "assets", title => loc("Assets"), path => "/Asset/Search/" );
+    if ($current_user->HasRight( Right => 'ShowAssetsMenu', Object => RT->System )) {
+        my $assets = $top->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 = HTML::Mason::Commands::Menu()->child( tools => title => loc('Tools'), path => '/Tools/index.html' );
+    my $tools = $top->child( tools => title => loc('Tools'), path => '/Tools/index.html' );
 
     $tools->child( my_day =>
         title       => loc('My Day'),
@@ -169,7 +175,7 @@ sub BuildMainNav {
         );
     }
 
-    if ( $HTML::Mason::Commands::session{'CurrentUser'}->HasRight( Right => 'ShowApprovalsTab', Object => RT->System ) ) {
+    if ( $current_user->HasRight( Right => 'ShowApprovalsTab', Object => RT->System ) ) {
         $tools->child( approval =>
             title       => loc('Approval'),
             description => loc('My Approvals'),
@@ -177,24 +183,24 @@ sub BuildMainNav {
         );
     }
 
-    if ( $HTML::Mason::Commands::session{'CurrentUser'}->HasRight( Right => 'ShowConfigTab', Object => RT->System ) )
+    if ( $current_user->HasRight( Right => 'ShowConfigTab', Object => RT->System ) )
     {
-        _BuildAdminMenu($request_path, HTML::Mason::Commands::Menu());
+        _BuildAdminMenu($request_path, $top);
     }
 
     my $username = '<span class="current-user">'
-                 . $HTML::Mason::Commands::m->interp->apply_escapes($HTML::Mason::Commands::session{'CurrentUser'}->Name, 'h')
+                 . $HTML::Mason::Commands::m->interp->apply_escapes($current_user->Name, 'h')
                  . '</span>';
-    my $about_me = HTML::Mason::Commands::Menu()->child( 'preferences' =>
+    my $about_me = $top->child( 'preferences' =>
         title        => loc('Logged in as [_1]', $username),
         escape_title => 0,
-        path         => '/User/Summary.html?id=' . $HTML::Mason::Commands::session{CurrentUser}->id,
+        path         => '/User/Summary.html?id=' . $current_user->id,
         sort_order   => 99,
     );
 
 
-    if ( $HTML::Mason::Commands::session{'CurrentUser'}->UserObj
-         && $HTML::Mason::Commands::session{'CurrentUser'}->HasRight( Right => 'ModifySelf', Object => RT->System )) {
+    if ( $current_user->UserObj
+         && $current_user->HasRight( Right => 'ModifySelf', Object => RT->System )) {
         my $settings = $about_me->child( settings => title => loc('Settings'), path => '/Prefs/Other.html' );
         $settings->child( options        => title => loc('Preferences'),        path => '/Prefs/Other.html' );
         $settings->child( about_me       => title => loc('About me'),       path => '/Prefs/AboutMe.html' );
@@ -208,7 +214,7 @@ sub BuildMainNav {
 
         my $search_menu = $settings->child( 'saved-searches' => title => loc('Saved Searches') );
         my $searches = [ $HTML::Mason::Commands::m->comp( "/Search/Elements/SearchesForObject",
-                          Object => RT::System->new( $HTML::Mason::Commands::session{'CurrentUser'} )) ];
+                          Object => RT::System->new( $current_user )) ];
         my $i = 0;
 
         for my $search (@$searches) {
@@ -220,22 +226,21 @@ sub BuildMainNav {
 
         }
     }
-    if ( $HTML::Mason::Commands::session{'CurrentUser'}->Name
+    if ( $current_user->Name
          && (   !RT->Config->Get('WebRemoteUserAuth')
               || RT->Config->Get('WebFallbackToRTLogin') )) {
         $about_me->child( logout => title => loc('Logout'), path => '/NoAuth/Logout.html' );
     }
     if ( $request_path =~ m{^/Dashboards/(\d+)?}) {
         if ( my $id = ( $1 || $HTML::Mason::Commands::DECODED_ARGS->{'id'} ) ) {
-            my $obj = RT::Dashboard->new( $HTML::Mason::Commands::session{'CurrentUser'} );
+            my $obj = RT::Dashboard->new( $current_user );
             $obj->LoadById($id);
             if ( $obj and $obj->id ) {
-                my $tabs = HTML::Mason::Commands::PageMenu();
-                $tabs->child( basics       => title => loc('Basics'),       path => "/Dashboards/Modify.html?id=" . $obj->id);
-                $tabs->child( content      => title => loc('Content'),      path => "/Dashboards/Queries.html?id=" . $obj->id);
-                $tabs->child( subscription => title => loc('Subscription'), path => "/Dashboards/Subscription.html?id=" . $obj->id)
+                $page->child( basics       => title => loc('Basics'),       path => "/Dashboards/Modify.html?id=" . $obj->id);
+                $page->child( content      => title => loc('Content'),      path => "/Dashboards/Queries.html?id=" . $obj->id);
+                $page->child( subscription => title => loc('Subscription'), path => "/Dashboards/Subscription.html?id=" . $obj->id)
                     if $obj->CurrentUserCanSubscribe;
-                $tabs->child( show         => title => loc('Show'),         path => "/Dashboards/" . $obj->id . "/" . $obj->Name)
+                $page->child( show         => title => loc('Show'),         path => "/Dashboards/" . $obj->id . "/" . $obj->Name)
             }
         }
     }
@@ -244,11 +249,11 @@ sub BuildMainNav {
     if ( $request_path =~ m{^/Ticket/} ) {
         if ( ( $HTML::Mason::Commands::DECODED_ARGS->{'id'} || '' ) =~ /^(\d+)$/ ) {
             my $id  = $1;
-            my $obj = RT::Ticket->new( $HTML::Mason::Commands::session{'CurrentUser'} );
+            my $obj = RT::Ticket->new( $current_user );
             $obj->Load($id);
 
             if ( $obj and $obj->id ) {
-                my $actions = HTML::Mason::Commands::PageMenu()->child( actions => title => loc('Actions'), sort_order  => 95 );
+                my $actions = $page->child( actions => title => loc('Actions'), sort_order  => 95 );
 
                 my %can = %{ $obj->CurrentUser->PrincipalObj->HasRights( Object => $obj ) };
                 $can{'_ModifyOwner'} = $obj->CurrentUserCanSetOwner();
@@ -261,37 +266,36 @@ sub BuildMainNav {
                     }
                 };
 
-                my $tabs = HTML::Mason::Commands::PageMenu();
-                $tabs->child( bookmark => raw_html => $HTML::Mason::Commands::m->scomp( '/Ticket/Elements/Bookmark', id => $id ), sort_order => 98 );
+                $page->child( bookmark => raw_html => $HTML::Mason::Commands::m->scomp( '/Ticket/Elements/Bookmark', id => $id ), sort_order => 98 );
 
                 if ($can->('ModifyTicket')) {
-                    $tabs->child( timer => raw_html => $HTML::Mason::Commands::m->scomp( '/Ticket/Elements/PopupTimerLink', id => $id ), sort_order => 99 );
+                    $page->child( timer => raw_html => $HTML::Mason::Commands::m->scomp( '/Ticket/Elements/PopupTimerLink', id => $id ), sort_order => 99 );
                 }
 
-                $tabs->child( display => title => loc('Display'), path => "/Ticket/Display.html?id=" . $id );
-                $tabs->child( history => title => loc('History'), path => "/Ticket/History.html?id=" . $id );
+                $page->child( display => title => loc('Display'), path => "/Ticket/Display.html?id=" . $id );
+                $page->child( history => title => loc('History'), path => "/Ticket/History.html?id=" . $id );
 
                 # comment out until we can do it for an individual custom field
                 #if ( $can->('ModifyTicket') || $can->('ModifyCustomField') ) {
-                $tabs->child( basics => title => loc('Basics'), path => "/Ticket/Modify.html?id=" . $id );
+                $page->child( basics => title => loc('Basics'), path => "/Ticket/Modify.html?id=" . $id );
 
                 #}
 
                 if ( $can->('ModifyTicket') || $can->('_ModifyOwner') || $can->('Watch') || $can->('WatchAsAdminCc') ) {
-                    $tabs->child( people => title => loc('People'), path => "/Ticket/ModifyPeople.html?id=" . $id );
+                    $page->child( people => title => loc('People'), path => "/Ticket/ModifyPeople.html?id=" . $id );
                 }
 
                 if ( $can->('ModifyTicket') ) {
-                    $tabs->child( dates => title => loc('Dates'), path => "/Ticket/ModifyDates.html?id=" . $id );
-                    $tabs->child( links => title => loc('Links'), path => "/Ticket/ModifyLinks.html?id=" . $id );
+                    $page->child( dates => title => loc('Dates'), path => "/Ticket/ModifyDates.html?id=" . $id );
+                    $page->child( links => title => loc('Links'), path => "/Ticket/ModifyLinks.html?id=" . $id );
                 }
 
                 #if ( $can->('ModifyTicket') || $can->('ModifyCustomField') || $can->('_ModifyOwner') ) {
-                $tabs->child( jumbo => title => loc('Jumbo'), path => "/Ticket/ModifyAll.html?id=" . $id );
+                $page->child( jumbo => title => loc('Jumbo'), path => "/Ticket/ModifyAll.html?id=" . $id );
                 #}
 
                 if ( RT->Config->Get('EnableReminders') ) {
-                    $tabs->child( reminders => title => loc('Reminders'), path => "/Ticket/Reminders.html?id=" . $id );
+                    $page->child( reminders => title => loc('Reminders'), path => "/Ticket/Reminders.html?id=" . $id );
                 }
 
                 if ( $can->('ModifyTicket') or $can->('ReplyToTicket') ) {
@@ -349,7 +353,7 @@ sub BuildMainNav {
                 $actions->child( 'extract-article' =>
                     title => loc('Extract Article'),
                     path  => "/Articles/Article/ExtractIntoClass.html?Ticket=".$obj->id,
-                ) if $HTML::Mason::Commands::session{CurrentUser}->HasRight( Right => 'ShowArticlesMenu', Object => RT->System );
+                ) if $current_user->HasRight( Right => 'ShowArticlesMenu', Object => RT->System );
 
                 if ( defined $HTML::Mason::Commands::session{"tickets"} ) {
                     # we have to update session data if we get new ItemMap
@@ -361,7 +365,7 @@ sub BuildMainNav {
                         $HTML::Mason::Commands::session{"tickets"}->PrepForSerialization();
                     }
 
-                    my $search = HTML::Mason::Commands::Menu()->child('search')->child('tickets');
+                    my $search = $top->child('search')->child('tickets');
                     # Don't display prev links if we're on the first ticket
                     if ( $item_map->{$id}->{prev} ) {
                         $search->child( first =>
@@ -392,7 +396,7 @@ sub BuildMainNav {
             && $HTML::Mason::Commands::DECODED_ARGS->{'q'} )
       )
     {
-        my $search = HTML::Mason::Commands::Menu()->child('search')->child('tickets');
+        my $search = $top->child('search')->child('tickets');
         my $args      = '';
         my $has_query = '';
         my $current_search = $HTML::Mason::Commands::session{"CurrentSearchHash"} || {};
@@ -450,7 +454,7 @@ sub BuildMainNav {
             $current_search_menu = $search->child( current_search => title => loc('Current Search') );
             $current_search_menu->path("/Search/Results.html$args") if $has_query;
         } else {
-            $current_search_menu = HTML::Mason::Commands::PageMenu();
+            $current_search_menu = $page;
         }
 
         $current_search_menu->child( edit_search =>
@@ -478,22 +482,22 @@ sub BuildMainNav {
                                    OrderBy => $rss_data{OrderBy}
                                  );
             my $RSSPath = join '/', map $HTML::Mason::Commands::m->interp->apply_escapes( $_, 'u' ),
-                $HTML::Mason::Commands::session{'CurrentUser'}->UserObj->Name,
-                $HTML::Mason::Commands::session{'CurrentUser'}
+                $current_user->UserObj->Name,
+                $current_user
                 ->UserObj->GenerateAuthString(   $rss_data{Query}
                                                . $rss_data{Order}
                                                . $rss_data{OrderBy} );
 
             $more->child( rss => title => loc('RSS'), path => "/NoAuth/rss/$RSSPath/$RSSQueryString");
             my $ical_path = join '/', map $HTML::Mason::Commands::m->interp->apply_escapes($_, 'u'),
-                $HTML::Mason::Commands::session{'CurrentUser'}->UserObj->Name,
-                $HTML::Mason::Commands::session{'CurrentUser'}->UserObj->GenerateAuthString( $rss_data{Query} ),
+                $current_user->UserObj->Name,
+                $current_user->UserObj->GenerateAuthString( $rss_data{Query} ),
                 $rss_data{Query};
             $more->child( ical => title => loc('iCal'), path => '/NoAuth/iCal/'.$ical_path);
 
             if ($request_path =~ m{^/Search/Results.html}
                 &&                        #XXX TODO better abstraction
-                $HTML::Mason::Commands::session{'CurrentUser'}->HasRight( Right => 'SuperUser', Object => RT->System )) {
+                $current_user->HasRight( Right => 'SuperUser', Object => RT->System )) {
                 my $shred_args = QueryString(
                     Search          => 1,
                     Plugin          => 'Tickets',
@@ -510,33 +514,30 @@ sub BuildMainNav {
     if ( $request_path =~ m{^/Article/} ) {
         if ( $HTML::Mason::Commands::DECODED_ARGS->{'id'} && $HTML::Mason::Commands::DECODED_ARGS->{'id'} =~ /^\d+$/ ) {
             my $id = $HTML::Mason::Commands::DECODED_ARGS->{'id'};
-            my $tabs = HTML::Mason::Commands::PageMenu();
-
-            $tabs->child( display => title => loc('Display'), path => "/Articles/Article/Display.html?id=".$id );
-            $tabs->child( history => title => loc('History'), path => "/Articles/Article/History.html?id=".$id );
-            $tabs->child( modify  => title => loc('Modify'),  path => "/Articles/Article/Edit.html?id=".$id );
+            $page->child( display => title => loc('Display'), path => "/Articles/Article/Display.html?id=".$id );
+            $page->child( history => title => loc('History'), path => "/Articles/Article/History.html?id=".$id );
+            $page->child( modify  => title => loc('Modify'),  path => "/Articles/Article/Edit.html?id=".$id );
         }
     }
 
     if ( $request_path =~ m{^/Articles/} ) {
-        HTML::Mason::Commands::PageWidgets()->child( article_search => raw_html => $HTML::Mason::Commands::m->scomp('/Articles/Elements/GotoArticle') );
-        HTML::Mason::Commands::PageWidgets()->delete('create_ticket');
-        HTML::Mason::Commands::PageWidgets()->delete('simple_search');
+        $widgets->child( article_search => raw_html => $HTML::Mason::Commands::m->scomp('/Articles/Elements/GotoArticle') );
+        $widgets->delete('create_ticket');
+        $widgets->delete('simple_search');
 
-        my $tabs = HTML::Mason::Commands::PageMenu();
-        $tabs->child( search => title => loc("Search"),       path => "/Articles/Article/Search.html" );
-        $tabs->child( create => title => loc("New Article" ), path => "/Articles/Article/PreCreate.html" );
+        $page->child( search => title => loc("Search"),       path => "/Articles/Article/Search.html" );
+        $page->child( create => title => loc("New Article" ), path => "/Articles/Article/PreCreate.html" );
         if ( $request_path =~ m{^/Articles/Article/} and ( $HTML::Mason::Commands::DECODED_ARGS->{'id'} || '' ) =~ /^(\d+)$/ ) {
             my $id  = $1;
-            my $obj = RT::Article->new( $HTML::Mason::Commands::session{'CurrentUser'} );
+            my $obj = RT::Article->new( $current_user );
             $obj->Load($id);
 
             if ( $obj and $obj->id ) {
-                $tabs->child( display => title => loc("Display"), path => "/Articles/Article/Display.html?id=" . $id );
-                $tabs->child( history => title => loc('History'), path => '/Articles/Article/History.html?id=' . $id );
+                $page->child( display => title => loc("Display"), path => "/Articles/Article/Display.html?id=" . $id );
+                $page->child( history => title => loc('History'), path => '/Articles/Article/History.html?id=' . $id );
 
                 if ( $obj->CurrentUserHasRight('ModifyArticle') ) {
-                    $tabs->child(modify => title => loc('Modify'), path => '/Articles/Article/Edit.html?id=' . $id );
+                    $page->child(modify => title => loc('Modify'), path => '/Articles/Article/Edit.html?id=' . $id );
                 }
             }
         }
@@ -546,7 +547,6 @@ sub BuildMainNav {
     if ($request_path =~ m{^/Asset/} and $HTML::Mason::Commands::DECODED_ARGS->{id} and $HTML::Mason::Commands::DECODED_ARGS->{id} !~ /\D/) {
         _BuildAssetMenu();
     } elsif ($request_path =~ m{^/Asset/Search/}) {
-        my $page  = HTML::Mason::Commands::PageMenu();
         my %search = map @{$_},
             grep defined $_->[1] && length $_->[1],
             map {ref $HTML::Mason::Commands::DECODED_ARGS->{$_} ? [$_, $HTML::Mason::Commands::DECODED_ARGS->{$_}[0]] : [$_, $HTML::Mason::Commands::DECODED_ARGS->{$_}] }
@@ -568,14 +568,11 @@ sub BuildMainNav {
             path  => '/Asset/Search/Results.tsv?' . (keys %search ? QueryString(%search) : ''),
         );
     } elsif ($request_path =~ m{^/Admin/Global/CustomFields/Catalog-Assets\.html$}) {
-        my $page  = HTML::Mason::Commands::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 $HTML::Mason::Commands::DECODED_ARGS->{'Type'} and $HTML::Mason::Commands::DECODED_ARGS->{'Type'} eq RT::Asset->CustomFieldLookupType) {
-        my $page  = HTML::Mason::Commands::PageMenu();
         $page->child("create")->path( $page->child("create")->path . "&LookupType=" . RT::Asset->CustomFieldLookupType );
     } elsif ($request_path =~ m{^/Admin/Assets/Catalogs/}) {
-        my $page  = HTML::Mason::Commands::PageMenu();
         my $actions = $request_path =~ m{/((index|Create)\.html)?$}
             ? $page
             : $page->child("catalogs", title => loc("Catalogs"), path => "/Admin/Assets/Catalogs/");
@@ -583,7 +580,7 @@ sub BuildMainNav {
         $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( $HTML::Mason::Commands::session{CurrentUser} );
+        my $catalog = RT::Catalog->new( $current_user );
         $catalog->Load($HTML::Mason::Commands::DECODED_ARGS->{id}) if $HTML::Mason::Commands::DECODED_ARGS->{id};
 
         if ($catalog->id and $catalog->CurrentUserCanSee) {
@@ -599,18 +596,18 @@ sub BuildMainNav {
     }
 
     if ( $request_path =~ m{^/User/(Summary|History)\.html} ) {
-        if (HTML::Mason::Commands::PageMenu()->child('summary')) {
+        if ($page->child('summary')) {
             # Already set up from having AdminUser and ShowConfigTab;
             # but rename "Basics" to "Edit" in this context
-            HTML::Mason::Commands::PageMenu()->child( 'basics' )->title( loc('Edit') );
-        } elsif ( $HTML::Mason::Commands::session{'CurrentUser'}->HasRight( Object => $RT::System, Right => 'ShowUserHistory' ) ) {
-            HTML::Mason::Commands::PageMenu()->child( display => title => loc('Summary'), path => '/User/Summary.html?id=' . $HTML::Mason::Commands::DECODED_ARGS->{'id'} );
-            HTML::Mason::Commands::PageMenu()->child( history => title => loc('History'), path => '/User/History.html?id=' . $HTML::Mason::Commands::DECODED_ARGS->{'id'} );
+            $page->child( 'basics' )->title( loc('Edit') );
+        } elsif ( $current_user->HasRight( Object => $RT::System, Right => 'ShowUserHistory' ) ) {
+            $page->child( display => title => loc('Summary'), path => '/User/Summary.html?id=' . $HTML::Mason::Commands::DECODED_ARGS->{'id'} );
+            $page->child( history => title => loc('History'), path => '/User/History.html?id=' . $HTML::Mason::Commands::DECODED_ARGS->{'id'} );
         }
     }
 
     if ( $request_path =~ /^\/(?:index.html|$)/ ) {
-        HTML::Mason::Commands::PageMenu()->child( edit => title => loc('Edit'), path => '/Prefs/MyRT.html' );
+        $page->child( edit => title => loc('Edit'), path => '/Prefs/MyRT.html' );
     }
 
     # due to historical reasons of always having been in /Elements/Tabs
@@ -686,8 +683,11 @@ sub _BuildAdminMenu {
     my $request_path = shift;
     my $top = shift;
 
+    my $page = HTML::Mason::Commands::PageMenu();
+    my $current_user = $HTML::Mason::Commands::session{CurrentUser};
+
     my $admin = $top->child( admin => title => loc('Admin'), path => '/Admin/' );
-    if ( $HTML::Mason::Commands::session{'CurrentUser'}->HasRight( Object => RT->System, Right => 'AdminUsers' ) ) {
+    if ( $current_user->HasRight( Object => RT->System, Right => 'AdminUsers' ) ) {
         my $users = $admin->child( users =>
             title       => loc('Users'),
             description => loc('Manage users and passwords'),
@@ -712,7 +712,7 @@ sub _BuildAdminMenu {
     $queues->child( select => title => loc('Select'), path => "/Admin/Queues/" );
     $queues->child( create => title => loc('Create'), path => "/Admin/Queues/Modify.html?Create=1" );
 
-    if ( $HTML::Mason::Commands::session{'CurrentUser'}->HasRight( Object => RT->System, Right => 'AdminCustomField' ) ) {
+    if ( $current_user->HasRight( Object => RT->System, Right => 'AdminCustomField' ) ) {
         my $cfs = $admin->child( 'custom-fields' =>
             title       => loc('Custom Fields'),
             description => loc('Manage custom fields and custom field values'),
@@ -722,7 +722,7 @@ sub _BuildAdminMenu {
         $cfs->child( create => title => loc('Create'), path => "/Admin/CustomFields/Modify.html?Create=1" );
     }
 
-    if ( $HTML::Mason::Commands::session{'CurrentUser'}->HasRight( Object => RT->System, Right => 'AdminCustomRoles' ) ) {
+    if ( $current_user->HasRight( Object => RT->System, Right => 'AdminCustomRoles' ) ) {
         my $roles = $admin->child( 'custom-roles' =>
             title       => loc('Custom Roles'),
             description => loc('Manage custom roles'),
@@ -732,7 +732,7 @@ sub _BuildAdminMenu {
         $roles->child( create => title => loc('Create'), path => "/Admin/CustomRoles/Modify.html?Create=1" );
     }
 
-    if ( $HTML::Mason::Commands::session{'CurrentUser'}->HasRight( Object => RT->System, Right => 'ModifyScrips' ) ) {
+    if ( $current_user->HasRight( Object => RT->System, Right => 'ModifyScrips' ) ) {
         my $scrips = $admin->child( 'scrips' =>
             title       => loc('Scrips'),
             description => loc('Manage scrips'),
@@ -892,7 +892,7 @@ sub _BuildAdminMenu {
         path        => '/Admin/Tools/Theme.html',
     );
     if (RT->Config->Get('StatementLog')
-        && $HTML::Mason::Commands::session{'CurrentUser'}->HasRight( Right => 'SuperUser', Object => RT->System )) {
+        && $current_user->HasRight( Right => 'SuperUser', Object => RT->System )) {
        $admin_tools->child( 'sql-queries' =>
            title       => loc('SQL Queries'),
            description => loc('Browse the SQL queries made in this process'),
@@ -907,7 +907,6 @@ sub _BuildAdminMenu {
 
     if ( $request_path =~ m{^/Admin/(Queues|Users|Groups|CustomFields|CustomRoles)} ) {
         my $type = $1;
-        my $tabs = HTML::Mason::Commands::PageMenu();
 
         my %labels = (
             Queues       => loc("Queues"),
@@ -923,10 +922,10 @@ sub _BuildAdminMenu {
                   && $HTML::Mason::Commands::DECODED_ARGS->{'Create'} )
            )
         {
-            $section = $tabs;
+            $section = $page;
 
         } else {
-            $section = $tabs->child( select => title => $labels{$type},
+            $section = $page->child( select => title => $labels{$type},
                                      path => "/Admin/$type/" );
         }
 
@@ -940,11 +939,11 @@ sub _BuildAdminMenu {
               $HTML::Mason::Commands::DECODED_ARGS->{'Queue'} && $HTML::Mason::Commands::DECODED_ARGS->{'Queue'} =~ /^\d+$/
                 ) {
             my $id = $HTML::Mason::Commands::DECODED_ARGS->{'Queue'} || $HTML::Mason::Commands::DECODED_ARGS->{'id'};
-            my $queue_obj = RT::Queue->new( $HTML::Mason::Commands::session{'CurrentUser'} );
+            my $queue_obj = RT::Queue->new( $current_user );
             $queue_obj->Load($id);
 
             if ( $queue_obj and $queue_obj->id ) {
-                my $queue = HTML::Mason::Commands::PageMenu();
+                my $queue = $page;
                 $queue->child( basics => title => loc('Basics'),   path => "/Admin/Queues/Modify.html?id=" . $id );
                 $queue->child( people => title => loc('Watchers'), path => "/Admin/Queues/People.html?id=" . $id );
 
@@ -976,23 +975,22 @@ sub _BuildAdminMenu {
     if ( $request_path =~ m{^(/Admin/Users|/User/(Summary|History)\.html)} and $admin->child("users") ) {
         if ( $HTML::Mason::Commands::DECODED_ARGS->{'id'} && $HTML::Mason::Commands::DECODED_ARGS->{'id'} =~ /^\d+$/ ) {
             my $id = $HTML::Mason::Commands::DECODED_ARGS->{'id'};
-            my $obj = RT::User->new( $HTML::Mason::Commands::session{'CurrentUser'} );
+            my $obj = RT::User->new( $current_user );
             $obj->Load($id);
 
             if ( $obj and $obj->id ) {
-                my $tabs = HTML::Mason::Commands::PageMenu();
-                $tabs->child( basics      => title => loc('Basics'),         path => "/Admin/Users/Modify.html?id=" . $id );
-                $tabs->child( memberships => title => loc('Memberships'),    path => "/Admin/Users/Memberships.html?id=" . $id );
-                $tabs->child( history     => title => loc('History'),        path => "/Admin/Users/History.html?id=" . $id );
-                $tabs->child( 'my-rt'     => title => loc('RT at a glance'), path => "/Admin/Users/MyRT.html?id=" . $id );
-                $tabs->child( 'dashboards-in-menu' =>
+                $page->child( basics      => title => loc('Basics'),         path => "/Admin/Users/Modify.html?id=" . $id );
+                $page->child( memberships => title => loc('Memberships'),    path => "/Admin/Users/Memberships.html?id=" . $id );
+                $page->child( history     => title => loc('History'),        path => "/Admin/Users/History.html?id=" . $id );
+                $page->child( 'my-rt'     => title => loc('RT at a glance'), path => "/Admin/Users/MyRT.html?id=" . $id );
+                $page->child( 'dashboards-in-menu' =>
                     title => loc('Dashboards in menu'),
                     path  => '/Admin/Users/DashboardsInMenu.html?id=' . $id,
                 );
                 if ( RT->Config->Get('Crypt')->{'Enable'} ) {
-                    $tabs->child( keys    => title => loc('Private keys'),   path => "/Admin/Users/Keys.html?id=" . $id );
+                    $page->child( keys    => title => loc('Private keys'),   path => "/Admin/Users/Keys.html?id=" . $id );
                 }
-                $tabs->child( 'summary'   => title => loc('User Summary'),   path => "/User/Summary.html?id=" . $id );
+                $page->child( 'summary'   => title => loc('User Summary'),   path => "/User/Summary.html?id=" . $id );
             }
         }
 
@@ -1001,17 +999,16 @@ sub _BuildAdminMenu {
     if ( $request_path =~ m{^/Admin/Groups} ) {
         if ( $HTML::Mason::Commands::DECODED_ARGS->{'id'} && $HTML::Mason::Commands::DECODED_ARGS->{'id'} =~ /^\d+$/ ) {
             my $id = $HTML::Mason::Commands::DECODED_ARGS->{'id'};
-            my $obj = RT::Group->new( $HTML::Mason::Commands::session{'CurrentUser'} );
+            my $obj = RT::Group->new( $current_user );
             $obj->Load($id);
 
             if ( $obj and $obj->id ) {
-                my $tabs = HTML::Mason::Commands::PageMenu();
-                $tabs->child( basics         => title => loc('Basics'),       path => "/Admin/Groups/Modify.html?id=" . $obj->id );
-                $tabs->child( members        => title => loc('Members'),      path => "/Admin/Groups/Members.html?id=" . $obj->id );
-                $tabs->child( memberships    => title => loc('Memberships'),  path => "/Admin/Groups/Memberships.html?id=" . $obj->id );
-                $tabs->child( 'group-rights' => title => loc('Group Rights'), path => "/Admin/Groups/GroupRights.html?id=" . $obj->id );
-                $tabs->child( 'user-rights'  => title => loc('User Rights'),  path => "/Admin/Groups/UserRights.html?id=" . $obj->id );
-                $tabs->child( history        => title => loc('History'),      path => "/Admin/Groups/History.html?id=" . $obj->id );
+                $page->child( basics         => title => loc('Basics'),       path => "/Admin/Groups/Modify.html?id=" . $obj->id );
+                $page->child( members        => title => loc('Members'),      path => "/Admin/Groups/Members.html?id=" . $obj->id );
+                $page->child( memberships    => title => loc('Memberships'),  path => "/Admin/Groups/Memberships.html?id=" . $obj->id );
+                $page->child( 'group-rights' => title => loc('Group Rights'), path => "/Admin/Groups/GroupRights.html?id=" . $obj->id );
+                $page->child( 'user-rights'  => title => loc('User Rights'),  path => "/Admin/Groups/UserRights.html?id=" . $obj->id );
+                $page->child( history        => title => loc('History'),      path => "/Admin/Groups/History.html?id=" . $obj->id );
             }
         }
     }
@@ -1019,16 +1016,15 @@ sub _BuildAdminMenu {
     if ( $request_path =~ m{^/Admin/CustomFields/} ) {
         if ( $HTML::Mason::Commands::DECODED_ARGS->{'id'} && $HTML::Mason::Commands::DECODED_ARGS->{'id'} =~ /^\d+$/ ) {
             my $id = $HTML::Mason::Commands::DECODED_ARGS->{'id'};
-            my $obj = RT::CustomField->new( $HTML::Mason::Commands::session{'CurrentUser'} );
+            my $obj = RT::CustomField->new( $current_user );
             $obj->Load($id);
 
             if ( $obj and $obj->id ) {
-                my $tabs = HTML::Mason::Commands::PageMenu();
-                $tabs->child( basics           => title => loc('Basics'),       path => "/Admin/CustomFields/Modify.html?id=".$id );
-                $tabs->child( 'group-rights'   => title => loc('Group Rights'), path => "/Admin/CustomFields/GroupRights.html?id=" . $id );
-                $tabs->child( 'user-rights'    => title => loc('User Rights'),  path => "/Admin/CustomFields/UserRights.html?id=" . $id );
+                $page->child( basics           => title => loc('Basics'),       path => "/Admin/CustomFields/Modify.html?id=".$id );
+                $page->child( 'group-rights'   => title => loc('Group Rights'), path => "/Admin/CustomFields/GroupRights.html?id=" . $id );
+                $page->child( 'user-rights'    => title => loc('User Rights'),  path => "/Admin/CustomFields/UserRights.html?id=" . $id );
                 unless ( $obj->IsOnlyGlobal ) {
-                    $tabs->child( 'applies-to' => title => loc('Applies to'),   path => "/Admin/CustomFields/Objects.html?id=" . $id );
+                    $page->child( 'applies-to' => title => loc('Applies to'),   path => "/Admin/CustomFields/Objects.html?id=" . $id );
                 }
             }
         }
@@ -1037,13 +1033,12 @@ sub _BuildAdminMenu {
     if ( $request_path =~ m{^/Admin/CustomRoles} ) {
         if ( $HTML::Mason::Commands::DECODED_ARGS->{'id'} && $HTML::Mason::Commands::DECODED_ARGS->{'id'} =~ /^\d+$/ ) {
             my $id = $HTML::Mason::Commands::DECODED_ARGS->{'id'};
-            my $obj = RT::CustomRole->new( $HTML::Mason::Commands::session{'CurrentUser'} );
+            my $obj = RT::CustomRole->new( $current_user );
             $obj->Load($id);
 
             if ( $obj and $obj->id ) {
-                my $tabs = HTML::Mason::Commands::PageMenu();
-                $tabs->child( basics       => title => loc('Basics'),       path => "/Admin/CustomRoles/Modify.html?id=".$id );
-                $tabs->child( 'applies-to' => title => loc('Applies to'),   path => "/Admin/CustomRoles/Objects.html?id=" . $id );
+                $page->child( basics       => title => loc('Basics'),       path => "/Admin/CustomRoles/Modify.html?id=".$id );
+                $page->child( 'applies-to' => title => loc('Applies to'),   path => "/Admin/CustomRoles/Objects.html?id=" . $id );
             }
         }
     }
@@ -1051,11 +1046,9 @@ sub _BuildAdminMenu {
     if ( $request_path =~ m{^/Admin/Scrips/} ) {
         if ( $HTML::Mason::Commands::m->request_args->{'id'} && $HTML::Mason::Commands::m->request_args->{'id'} =~ /^\d+$/ ) {
             my $id = $HTML::Mason::Commands::m->request_args->{'id'};
-            my $obj = RT::Scrip->new( $HTML::Mason::Commands::session{'CurrentUser'} );
+            my $obj = RT::Scrip->new( $current_user );
             $obj->Load($id);
 
-            my $tabs = HTML::Mason::Commands::PageMenu();
-
             my ( $admin_cat, $create_path_arg, $from_query_param );
             my $from_arg = $HTML::Mason::Commands::DECODED_ARGS->{'From'} || q{};
             my ($from_queue) = $from_arg =~ /^(\d+)$/;
@@ -1073,12 +1066,12 @@ sub _BuildAdminMenu {
                 $admin_cat = 'Scrips';
                 $from_query_param = $create_path_arg = q{};
             }
-            my $scrips = $tabs->child( scrips => title => loc('Scrips'), path => "/Admin/${admin_cat}" );
+            my $scrips = $page->child( scrips => title => loc('Scrips'), path => "/Admin/${admin_cat}" );
             $scrips->child( select => title => loc('Select'), path => "/Admin/${admin_cat}" );
             $scrips->child( create => title => loc('Create'), path => "/Admin/Scrips/Create.html${create_path_arg}" );
 
-            $tabs->child( basics => title => loc('Basics') => path => "/Admin/Scrips/Modify.html?id=" . $id . $from_query_param );
-            $tabs->child( 'applies-to' => title => loc('Applies to'), path => "/Admin/Scrips/Objects.html?id=" . $id . $from_query_param );
+            $page->child( basics => title => loc('Basics') => path => "/Admin/Scrips/Modify.html?id=" . $id . $from_query_param );
+            $page->child( 'applies-to' => title => loc('Applies to'), path => "/Admin/Scrips/Objects.html?id=" . $id . $from_query_param );
         }
         elsif ( $request_path =~ m{^/Admin/Scrips/(index\.html)?$} ) {
             HTML::Mason::Commands::PageMenu->child( select => title => loc('Select') => path => "/Admin/Scrips/" );
@@ -1101,38 +1094,35 @@ sub _BuildAdminMenu {
     }
 
     if ( $request_path =~ m{^/Admin/Global/Scrips\.html} ) {
-        my $tabs = HTML::Mason::Commands::PageMenu();
-        $tabs->child( select => title => loc('Select'), path => "/Admin/Global/Scrips.html" );
-        $tabs->child( create => title => loc('Create'), path => "/Admin/Scrips/Create.html?Global=1" );
+        $page->child( select => title => loc('Select'), path => "/Admin/Global/Scrips.html" );
+        $page->child( create => title => loc('Create'), path => "/Admin/Scrips/Create.html?Global=1" );
     }
 
     if ( $request_path =~ m{^/Admin/Global/Templates?\.html} ) {
-        my $tabs = HTML::Mason::Commands::PageMenu();
-        $tabs->child( select => title => loc('Select'), path => "/Admin/Global/Templates.html" );
-        $tabs->child( create => title => loc('Create'), path => "/Admin/Global/Template.html?Create=1" );
+        $page->child( select => title => loc('Select'), path => "/Admin/Global/Templates.html" );
+        $page->child( create => title => loc('Create'), path => "/Admin/Global/Template.html?Create=1" );
     }
 
     if ( $request_path =~ m{^/Admin/Articles/Classes/} ) {
-        my $tabs = HTML::Mason::Commands::PageMenu();
         if ( my $id = $HTML::Mason::Commands::DECODED_ARGS->{'id'} ) {
-            my $obj = RT::Class->new( $HTML::Mason::Commands::session{'CurrentUser'} );
+            my $obj = RT::Class->new( $current_user );
             $obj->Load($id);
 
             if ( $obj and $obj->id ) {
-                my $section = $tabs->child( select => title => loc("Classes"), path => "/Admin/Articles/Classes/" );
+                my $section = $page->child( select => title => loc("Classes"), path => "/Admin/Articles/Classes/" );
                 $section->child( select => title => loc('Select'), path => "/Admin/Articles/Classes/" );
                 $section->child( create => title => loc('Create'), path => "/Admin/Articles/Classes/Modify.html?Create=1" );
 
-                $tabs->child( basics          => title => loc('Basics'),        path => "/Admin/Articles/Classes/Modify.html?id=".$id );
-                $tabs->child( topics          => title => loc('Topics'),        path => "/Admin/Articles/Classes/Topics.html?id=".$id );
-                $tabs->child( 'custom-fields' => title => loc('Custom Fields'), path => "/Admin/Articles/Classes/CustomFields.html?id=".$id );
-                $tabs->child( 'group-rights'  => title => loc('Group Rights'),  path => "/Admin/Articles/Classes/GroupRights.html?id=".$id );
-                $tabs->child( 'user-rights'   => title => loc('User Rights'),   path => "/Admin/Articles/Classes/UserRights.html?id=".$id );
-                $tabs->child( 'applies-to'    => title => loc('Applies to'),    path => "/Admin/Articles/Classes/Objects.html?id=$id" );
+                $page->child( basics          => title => loc('Basics'),        path => "/Admin/Articles/Classes/Modify.html?id=".$id );
+                $page->child( topics          => title => loc('Topics'),        path => "/Admin/Articles/Classes/Topics.html?id=".$id );
+                $page->child( 'custom-fields' => title => loc('Custom Fields'), path => "/Admin/Articles/Classes/CustomFields.html?id=".$id );
+                $page->child( 'group-rights'  => title => loc('Group Rights'),  path => "/Admin/Articles/Classes/GroupRights.html?id=".$id );
+                $page->child( 'user-rights'   => title => loc('User Rights'),   path => "/Admin/Articles/Classes/UserRights.html?id=".$id );
+                $page->child( 'applies-to'    => title => loc('Applies to'),    path => "/Admin/Articles/Classes/Objects.html?id=$id" );
             }
         } else {
-            $tabs->child( select => title => loc('Select'), path => "/Admin/Articles/Classes/" );
-            $tabs->child( create => title => loc('Create'), path => "/Admin/Articles/Classes/Modify.html?Create=1" );
+            $page->child( select => title => loc('Select'), path => "/Admin/Articles/Classes/" );
+            $page->child( create => title => loc('Create'), path => "/Admin/Articles/Classes/Modify.html?Create=1" );
         }
     }
 }
@@ -1140,7 +1130,13 @@ sub _BuildAdminMenu {
 sub BuildSelfServiceNav {
     my $request_path = shift;
 
-    my $queues = RT::Queues->new( $HTML::Mason::Commands::session{'CurrentUser'} );
+    my $top     = HTML::Mason::Commands::Menu();
+    my $widgets = HTML::Mason::Commands::PageWidgets();
+    my $page    = HTML::Mason::Commands::PageMenu();
+
+    my $current_user = $HTML::Mason::Commands::session{CurrentUser};
+
+    my $queues = RT::Queues->new( $current_user );
     $queues->UnLimit;
 
     my $queue_count = 0;
@@ -1155,44 +1151,43 @@ sub BuildSelfServiceNav {
 
 
     if ( $queue_count > 1 ) {
-        HTML::Mason::Commands::Menu()->child( new => title => loc('New ticket'), path => '/SelfService/CreateTicketInQueue.html' );
+        $top->child( new => title => loc('New ticket'), path => '/SelfService/CreateTicketInQueue.html' );
     } elsif ( $queue_id ) {
-        HTML::Mason::Commands::Menu()->child( new => title => loc('New ticket'), path => '/SelfService/Create.html?Queue=' . $queue_id );
+        $top->child( new => title => loc('New ticket'), path => '/SelfService/Create.html?Queue=' . $queue_id );
     }
-    my $tickets = HTML::Mason::Commands::Menu()->child( tickets => title => loc('Tickets'), path => '/SelfService/' );
+    my $tickets = $top->child( tickets => title => loc('Tickets'), path => '/SelfService/' );
     $tickets->child( open   => title => loc('Open tickets'),   path => '/SelfService/' );
     $tickets->child( closed => title => loc('Closed tickets'), path => '/SelfService/Closed.html' );
 
-    HTML::Mason::Commands::Menu()->child( "assets", title => loc("Assets"), path => "/SelfService/Asset/" )
-        if $HTML::Mason::Commands::session{CurrentUser}->HasRight( Right => 'ShowAssetsMenu', Object => RT->System );
+    $top->child( "assets", title => loc("Assets"), path => "/SelfService/Asset/" )
+        if $current_user->HasRight( Right => 'ShowAssetsMenu', Object => RT->System );
 
     my $username = '<span class="current-user">'
-                 . $HTML::Mason::Commands::m->interp->apply_escapes($HTML::Mason::Commands::session{'CurrentUser'}->Name, 'h')
+                 . $HTML::Mason::Commands::m->interp->apply_escapes($current_user->Name, 'h')
                  . '</span>';
-    my $about_me = HTML::Mason::Commands::Menu()->child( preferences =>
+    my $about_me = $top->child( preferences =>
         title        => loc('Logged in as [_1]', $username),
         escape_title => 0,
         sort_order   => 99,
     );
 
-    if ( $HTML::Mason::Commands::session{'CurrentUser'}->HasRight( Right => 'ModifySelf', Object => RT->System ) ) {
+    if ( $current_user->HasRight( Right => 'ModifySelf', Object => RT->System ) ) {
         $about_me->child( prefs => title => loc('Preferences'), path => '/SelfService/Prefs.html' );
     }
 
-    if ( $HTML::Mason::Commands::session{'CurrentUser'}->Name
+    if ( $current_user->Name
          && (   !RT->Config->Get('WebRemoteUserAuth')
               || RT->Config->Get('WebFallbackToRTLogin') )) {
         $about_me->child( logout => title => loc('Logout'), path => '/NoAuth/Logout.html' );
     }
 
-    if ($HTML::Mason::Commands::session{'CurrentUser'}->HasRight( Right => 'ShowArticle', Object => RT->System )) {
-        HTML::Mason::Commands::PageWidgets()->child( 'goto-article' => raw_html => $HTML::Mason::Commands::m->scomp('/SelfService/Elements/SearchArticle') );
+    if ($current_user->HasRight( Right => 'ShowArticle', Object => RT->System )) {
+        $widgets->child( 'goto-article' => raw_html => $HTML::Mason::Commands::m->scomp('/SelfService/Elements/SearchArticle') );
     }
 
-    HTML::Mason::Commands::PageWidgets()->child( goto => raw_html => $HTML::Mason::Commands::m->scomp('/SelfService/Elements/GotoTicket') );
+    $widgets->child( goto => raw_html => $HTML::Mason::Commands::m->scomp('/SelfService/Elements/GotoTicket') );
 
     if ($request_path =~ m{^/SelfService/Asset/} and $HTML::Mason::Commands::DECODED_ARGS->{id}) {
-        my $page = HTML::Mason::Commands::PageMenu();
         my $id   = $HTML::Mason::Commands::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");

commit c50da430656093028dc14e2a2665d7d31107e641
Author: Dustin Graves <dustin at bestpractical.com>
Date:   Wed Jun 22 21:51:41 2016 +0000

    define a new calling convention for menu building functions
    
    passing request path, top menu, widgets, page menu, and %ARGS to each
    
    this allows for more submenu functions like _BuildAssetMenu and
    _BuildAssetMenuActionSubmenu as well as being able to call
    _BuildAssetMenuActionSubmenu on an empty menu

diff --git a/lib/RT/Interface/Web/MenuBuilder.pm b/lib/RT/Interface/Web/MenuBuilder.pm
index efd0ef7..d286824 100644
--- a/lib/RT/Interface/Web/MenuBuilder.pm
+++ b/lib/RT/Interface/Web/MenuBuilder.pm
@@ -68,12 +68,14 @@ sub QueryString {
 
 sub BuildMainNav {
     my $request_path = shift;
-    my $query_string = shift;
-    my $query_args = shift;
+    my $top          = shift;
+    my $widgets      = shift;
+    my $page         = shift;
 
-    my $top     = HTML::Mason::Commands::Menu();
-    my $widgets = HTML::Mason::Commands::PageWidgets();
-    my $page    = HTML::Mason::Commands::PageMenu();
+    my %args = ( @_ );
+
+    my $query_string = $args{QueryString};
+    my $query_args = $args{QueryArgs};
 
     my $current_user = $HTML::Mason::Commands::session{CurrentUser};
 
@@ -185,7 +187,7 @@ sub BuildMainNav {
 
     if ( $current_user->HasRight( Right => 'ShowConfigTab', Object => RT->System ) )
     {
-        _BuildAdminMenu($request_path, $top);
+        _BuildAdminMenu( $request_path, $top, $widgets, $page, %args );
     }
 
     my $username = '<span class="current-user">'
@@ -545,7 +547,7 @@ sub BuildMainNav {
     }
 
     if ($request_path =~ m{^/Asset/} and $HTML::Mason::Commands::DECODED_ARGS->{id} and $HTML::Mason::Commands::DECODED_ARGS->{id} !~ /\D/) {
-        _BuildAssetMenu();
+        _BuildAssetMenu( $request_path, $top, $widgets, $page, %args );
     } elsif ($request_path =~ m{^/Asset/Search/}) {
         my %search = map @{$_},
             grep defined $_->[1] && length $_->[1],
@@ -615,7 +617,13 @@ sub BuildMainNav {
 }
 
 sub _BuildAssetMenu {
-    my $page  = HTML::Mason::Commands::PageMenu();
+    my $request_path = shift;
+    my $top          = shift;
+    my $widgets      = shift;
+    my $page         = shift;
+
+    my %args = ( @_ );
+
     my $current_user = $HTML::Mason::Commands::session{CurrentUser};
 
     my $id    = $HTML::Mason::Commands::DECODED_ARGS->{id};
@@ -641,14 +649,22 @@ sub _BuildAssetMenu {
             );
         }
 
-        _BuildAssetMenuActionSubmenu($asset);
+        _BuildAssetMenuActionSubmenu( $request_path, $top, $widgets, $page, %args, Asset => $asset );
     }
 }
 
 sub _BuildAssetMenuActionSubmenu {
-    my $asset = shift;
+    my $request_path = shift;
+    my $top          = shift;
+    my $widgets      = shift;
+    my $page         = shift;
+
+    my %args = (
+        Asset => undef,
+        @_
+    );
 
-    my $page  = HTML::Mason::Commands::PageMenu();
+    my $asset = $args{Asset};
     my $id    = $asset->id;
 
     my $actions = $page->child("actions", title => HTML::Mason::Commands::loc("Actions"));
@@ -681,9 +697,12 @@ sub _BuildAssetMenuActionSubmenu {
 
 sub _BuildAdminMenu {
     my $request_path = shift;
-    my $top = shift;
+    my $top          = shift;
+    my $widgets      = shift;
+    my $page         = shift;
+
+    my %args = ( @_ );
 
-    my $page = HTML::Mason::Commands::PageMenu();
     my $current_user = $HTML::Mason::Commands::session{CurrentUser};
 
     my $admin = $top->child( admin => title => loc('Admin'), path => '/Admin/' );
@@ -1129,10 +1148,11 @@ sub _BuildAdminMenu {
 
 sub BuildSelfServiceNav {
     my $request_path = shift;
+    my $top          = shift;
+    my $widgets      = shift;
+    my $page         = shift;
 
-    my $top     = HTML::Mason::Commands::Menu();
-    my $widgets = HTML::Mason::Commands::PageWidgets();
-    my $page    = HTML::Mason::Commands::PageMenu();
+    my %args = ( @_ );
 
     my $current_user = $HTML::Mason::Commands::session{CurrentUser};
 
diff --git a/share/html/Elements/Tabs b/share/html/Elements/Tabs
index 875960c..fe0809d 100644
--- a/share/html/Elements/Tabs
+++ b/share/html/Elements/Tabs
@@ -52,11 +52,15 @@
 my $request_path = $HTML::Mason::Commands::r->path_info;
 $request_path =~ s!/{2,}!/!g;
 
+my $top     = Menu();
+my $widgets = PageWidgets();
+my $page    = PageMenu();
+
 use RT::Interface::Web::MenuBuilder;
 if ( $request_path !~ m{^/SelfService/} ) {
-    RT::Interface::Web::MenuBuilder::BuildMainNav( $request_path, $QueryString, $QueryArgs );
+    RT::Interface::Web::MenuBuilder::BuildMainNav( $request_path, $top, $widgets, $page, %ARGS );
 } else {
-    RT::Interface::Web::MenuBuilder::BuildSelfServiceNav( $request_path );
+    RT::Interface::Web::MenuBuilder::BuildSelfServiceNav( $request_path, $top, $widgets, $page, %ARGS );
 }
 </%INIT>
 <%ARGS>

commit 5cce23edbfef62c2f26e9ef0f94b2d1933b37e59
Author: Dustin Graves <dustin at bestpractical.com>
Date:   Tue May 31 22:09:18 2016 +0000

    add asset display menu actions to ShowAssets template

diff --git a/share/html/Ticket/Elements/ShowAssets b/share/html/Ticket/Elements/ShowAssets
index de3aebb..113b6cc 100644
--- a/share/html/Ticket/Elements/ShowAssets
+++ b/share/html/Ticket/Elements/ShowAssets
@@ -144,6 +144,21 @@ if ($Ticket->CurrentUserHasRight("ModifyTicket")) {
 </%perl>
 <a href="<% $delete_url %>" class="unlink-asset ui-icon ui-icon-circle-close" title="Unlink asset">X</a>
 % }
+
+%# show asset actions menu
+% my $request_path = $HTML::Mason::Commands::r->path_info;
+% $request_path =~ s!/{2,}!/!g;
+% my $page = RT::Interface::Web::Menu->new();
+% RT::Interface::Web::MenuBuilder::_BuildAssetMenuActionSubmenu( $request_path, Menu(), PageWidgets(), $page, Asset => $asset );
+<& /Elements/Menu, menu => $page, id => 'asset-'.$asset->id.'-actions-menu', parent_id => 'asset-'.$asset->id &>
+<script>
+jQuery("#assets-accordion ul.toplevel").addClass('sf-menu sf-js-enabled sf-shadow').supersubs().superfish({ dropShadows: false, speed: 'fast', delay: 0 }).supposition()
+    .find('a').click(function(ev){
+        ev.stopPropagation();
+        return true;
+    });
+</script>
+
   </h3>
   <div class="details">
     <& /Elements/ShowRecord,
diff --git a/share/static/css/base/assets.css b/share/static/css/base/assets.css
index c09a8a7..f951889 100644
--- a/share/static/css/base/assets.css
+++ b/share/static/css/base/assets.css
@@ -227,3 +227,32 @@ body#comp-Asset-Search .collection-as-table td {
         width: 10em;
     }
 }
+
+#assets-accordion ul.toplevel {
+    position: absolute;
+    top: 0;
+    right: 20px;
+    width: auto;
+    font-size: .9em;
+}
+
+#assets-accordion li.has-children {
+    background: transparent;
+}
+
+#assets-accordion li.has-children ul {
+    min-width: 12em;
+}
+
+#assets-accordion a {
+    border: none;
+    color: #000;
+}
+
+#assets-accordion a.sf-with-ul {
+    padding-top: .3em;
+}
+
+#assets-accordion .sf-sub-indicator {
+    top: .2em;
+}

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


More information about the rt-commit mailing list