[Rt-commit] rt branch, menuing, created. rt-3.9.4-186-gde13bc8

Jesse Vincent jesse at bestpractical.com
Wed Oct 20 05:01:49 EDT 2010


The branch, menuing has been created
        at  de13bc8ca841b0d1d6a4769d34bc411ccc0f17fa (commit)

- Log -----------------------------------------------------------------
commit 18ddeac23266256b5eb7f040692a6eb779abb78b
Author: Jesse Vincent <jesse at bestpractical.com>
Date:   Wed Oct 20 01:01:33 2010 +0900

    make autoconf's relativization support our vessel layout

diff --git a/configure.ac b/configure.ac
index dcc023d..be38f53 100755
--- a/configure.ac
+++ b/configure.ac
@@ -342,7 +342,7 @@ AC_SUBST([LOCAL_LIB_PATH],		${exp_customlibdir})
 AC_SUBST([LOCAL_PLUGIN_PATH],		${exp_customplugindir})
 AC_SUBST([RT_LOG_PATH],			${exp_logfiledir})
 
-if test ${exp_sysconfdir} = "etc"; then
+if test ${exp_sysconfdir} = "etc" -o ${exp_sysconfdir} = "etc/rt"; then
 AC_SUBST([RT_PATH_R],			${exp_prefix})
 AC_SUBST([RT_DOC_PATH_R],			${exp_prefix}/${exp_manualdir})
 AC_SUBST([RT_LOCAL_PATH_R],		${exp_prefix}/${exp_customdir})

commit 6c87deed637eacd3969c56bf9a2794e855edea8e
Author: Jesse Vincent <jesse at bestpractical.com>
Date:   Wed Oct 20 09:09:42 2010 +0900

    another try at a vessel layout

diff --git a/config.layout b/config.layout
index d951f1f..3da8e07 100755
--- a/config.layout
+++ b/config.layout
@@ -207,8 +207,8 @@
   sbindir:		sbin
   sysconfdir:	etc/rt/
   mandir:		man
-  libdir:		rt/lib/
-  datadir:		rt/share/
+  libdir:		lib/rt
+  datadir:		share/rt
   plugindir:	${datadir}/plugins
   htmldir:		${datadir}/html
   fontdir:		${datadir}/fonts
@@ -218,7 +218,7 @@
   logfiledir:		${localstatedir}/log
   masonstatedir:	${localstatedir}/mason_data
   sessionstatedir:	${localstatedir}/session_data
-  customdir:		rt/local
+  customdir:		local/rt/
   custometcdir:		${customdir}/etc
   customhtmldir:	${customdir}/html
   customlexdir:		${customdir}/po

commit 0f703337651ebb3c32f7a1062b98dc177248bf6e
Author: Jesse Vincent <jesse at bestpractical.com>
Date:   Sat Sep 25 09:20:01 2010 -0400

    replace RT's menuing library (unusued) with one from jifty

diff --git a/lib/RT/Interface/Web/Menu.pm b/lib/RT/Interface/Web/Menu.pm
index 899f209..1665d7b 100644
--- a/lib/RT/Interface/Web/Menu.pm
+++ b/lib/RT/Interface/Web/Menu.pm
@@ -47,24 +47,269 @@
 # END BPS TAGGED BLOCK }}}
 
 package RT::Interface::Web::Menu;
-use warnings;
+
 use strict;
+use warnings;
+
+
+use base qw/Class::Accessor::Fast/;
+use URI;
+use Scalar::Util qw(weaken);
+
+__PACKAGE__->mk_accessors(qw(
+    label sort_order link target escape_label class render_children_inline
+    raw_html
+));
+
+=head1 NAME
+
+RT::Interface::Web::Menu - Handle the API for menu navigation
+
+=head1 METHODS
+
+=head2 new PARAMHASH
+
+Creates a new L<RT::Interface::Web::Menu> object.  Possible keys in the
+I<PARAMHASH> are L</label>, L</parent>, L</sort_order>, L</url>, and
+L</active>.  See the subroutines with the respective name below for
+each option's use.
+
+=cut
 
 sub new {
-    my $class = shift;
-    my $self = bless {}, $class;
-    $self->{'root_node'} = RT::Interface::Web::Menu::Item->new();
+    my $package = shift;
+    my $args = ref($_[0]) eq 'HASH' ? shift @_ : {@_};
+
+    my $parent = delete $args->{'parent'};
+    $args->{sort_order} ||= 0;
+
+    # Class::Accessor only wants a hashref;
+    my $self = $package->SUPER::new( $args );
+
+    # make sure our reference is weak
+    $self->parent($parent) if defined $parent;
+
     return $self;
 }
 
 
-sub as_hash_of_hashes {
+=head2 label [STRING]
+
+Sets or returns the string that the menu item will be displayed as.
+
+=cut
+
+=head2 parent [MENU]
+
+Gets or sets the parent L<RT::Interface::Web::Menu> of this item; this defaults
+to null. This ensures that the reference is weakened.
+
+=head2 raw_html [STRING]
+
+Sets the content of this menu item to a raw blob of HTML. When
+asked or output, rather than constructing a link, Jifty will return
+this raw content. No escaping is done.
 
+=cut
+
+sub parent {
+    my $self = shift;
+    if (@_) {
+        $self->{parent} = shift;
+        weaken $self->{parent};
+    }
+
+    return $self->{parent};
 }
 
-sub root {
+
+=head2 sort_order [NUMBER]
+
+Gets or sets the sort order of the item, as it will be displayed under
+the parent.  This defaults to adding onto the end.
+
+=head2 link
+
+Gets or set a L<Jifty::Web::Form::Link> object that represents this
+menu item. If you're looking to do complex ajaxy things with menus,
+this is likely the option you want.
+
+=head2 target [STRING]
+
+Get or set the frame or pseudo-target for this link. something like L<_blank>
+
+=cut
+
+=head2 class [STRING]
+
+Gets or sets the CSS class the link should have in addition to the default
+classes.  This is only used if L</link> isn't specified.
+
+=head2 render_children_inline [BOOLEAN]
+
+Gets or sets whether children are rendered inline as a menu "group" instead
+of a true submenu.  Only used when rendering with YUI for now.
+Defaults to false.
+
+Note that YUI doesn't support rendering nested menu groups, so having direct
+parent/children render_children_inline is likely not going to do what you
+want or expect.
+
+=head2 url
+
+Gets or sets the URL that the menu's link goes to.  If the link
+provided is not absolute (does not start with a "/"), then is is
+treated as relative to it's parent's url, and made absolute.
+
+=cut
+
+sub url {
+    my $self = shift;
+    if (@_) {
+        $self->{url} = shift;
+        $self->{url} = URI->new_abs($self->{url}, $self->parent->url . "/")->as_string
+            if defined $self->{url} and $self->parent and $self->parent->url;
+        $self->{url} =~ s!///!/! if $self->{url};
+    }
+    return $self->{url};
+}
+
+=head2 active [BOOLEAN]
+
+Gets or sets if the menu item is marked as active.  Setting this
+cascades to all of the parents of the menu item.
+
+=cut
+
+sub active {
+    my $self = shift;
+    if (@_) {
+        $self->{active} = shift;
+        $self->parent->active($self->{active}) if defined $self->parent;
+    }
+    return $self->{active};
+}
+
+=head2 child KEY [, PARAMHASH]
+
+If only a I<KEY> is provided, returns the child with that I<KEY>.
+
+Otherwise, creates or overwrites the child with that key, passing the
+I<PARAMHASH> to L<RT::Interface::Web::Menu/new>.  Additionally, the paramhash's
+L</label> defaults to the I<KEY>, and the L</sort_order> defaults to the
+pre-existing child's sort order (if a C<KEY> is being over-written) or
+the end of the list, if it is a new C<KEY>.
+
+If the paramhash contains a key called C<menu>, that will be used instead
+of creating a new RT::Interface::Web::Menu.
+
+
+=cut
+
+sub child {
+    my $self  = shift;
+    my $key   = shift;
+    my $proto = ref $self || $self;
+
+    if ( my %args = @_ ) {
+
+        # Clear children ordering cache
+        delete $self->{children_list};
+
+        my $child;
+        if ( $child = $args{menu} ) {
+            $child->parent($self);
+        } else {
+            $child = $proto->new(
+                {   parent     => $self,
+                    label        => $key,
+                    escape_label => 1,
+                    %args
+                }
+            );
+        }
+        $self->{children}{$key} = $child;
+
+        $child->sort_order( $args{sort_order} || (scalar values %{ $self->{children} })  )
+            unless ($child->sort_order());
+
+        # URL is relative to parents, and cached, so set it up now
+        $child->url( $child->{url} );
+
+        # Figure out the URL
+        my $url
+            = (     defined $child->link
+                and ref $child->link
+                and $child->link->can('url') )
+            ? $child->link->url
+            : $child->url;
+
+        # Activate it
+        if ( defined $url and length $url and Jifty->web->request ) {
+
+            # XXX TODO cleanup for mod_perl
+            my $base_path = Jifty->web->request->path;
+            chomp($base_path);
+
+            $base_path =~ s/index\.html$//;
+            $base_path =~ s/\/+$//;
+            $url       =~ s/\/+$//;
+
+            if ( $url eq $base_path ) {
+                $self->{children}{$key}->active(1);
+            }
+        }
+    }
+
+    return $self->{children}{$key};
+}
+
+=head2 active_child
+
+Returns the first active child node, or C<undef> is there is none.
+
+=cut
+
+sub active_child {
+    my $self = shift;
+    foreach my $kid ($self->children) {
+        return $kid if $kid->active;
+    }
+    return undef;
+}
+
+
+=head2 delete KEY
+
+Removes the child with the provided I<KEY>.
+
+=cut
+
+sub delete {
+    my $self = shift;
+    my $key = shift;
+    delete $self->{children_list};
+    delete $self->{children}{$key};
+}
+
+=head2 children
+
+Returns the children of this menu item in sorted order; as an array in
+array context, or as an array reference in scalar context.
+
+=cut
+
+sub children {
     my $self = shift;
-    return $self->{'root_node'};
+    my @kids;
+    if ($self->{children_list}) {
+        @kids = @{$self->{children_list}};
+    } else {
+        @kids = values %{$self->{children} || {}};
+        @kids = sort {$a->{sort_order} <=> $b->{sort_order}} @kids;
+        $self->{children_list} = \@kids;
+    }
+    return wantarray ? @kids : \@kids;
 }
 
 1;
diff --git a/lib/RT/Interface/Web/Menu/Item.pm b/lib/RT/Interface/Web/Menu/Item.pm
deleted file mode 100644
index e5efa29..0000000
--- a/lib/RT/Interface/Web/Menu/Item.pm
+++ /dev/null
@@ -1,87 +0,0 @@
-# BEGIN BPS TAGGED BLOCK {{{
-#
-# COPYRIGHT:
-#
-# This software is Copyright (c) 1996-2010 Best Practical Solutions, LLC
-#                                          <jesse 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 }}}
-
-package RT::Interface::Web::Menu::Item;
-
-
-sub new {
-    my $class = shift;
-    my $self = bless {},$class;
-    $self->{'_attributes'} = {};
-    return($self);
-}
-
-sub label { my $self = shift; $self->_accessor( label => @_) } ;
-sub absolute_url { my $self = shift; $self->_accessor( absolute_url => @_) } ;
-sub rt_path { my $self = shift; $self->_accessor( rt_path => @_) } ;
-sub hilight { my $self = shift; $self->_accessor( hilight => @_);
-              $self->parent->hilight(1);
-            } ;
-sub sort_order { my $self = shift; $self->_accessor( sort_order => @_) } ;
-
-sub add_child {
-}
-
-sub delete {
-}
-
-sub children {
-
-}
-
-sub _accessor {
-    my $self = shift;
-    my $key = shift;
-    if (@_){ 
-        $self->{'attributes'}->{$key} = shift;
-
-    }
-    return $self->{'_attributes'}->{$key};
-}
-
-1;

commit 04b525740a79501721bca87c9890d13e6f361b00
Author: Jesse Vincent <jesse at bestpractical.com>
Date:   Sat Sep 25 20:15:54 2010 -0400

    first pass of making the toplevel menu use a new menu object

diff --git a/lib/RT/Interface/Web.pm b/lib/RT/Interface/Web.pm
index c50c1a7..e29e46b 100755
--- a/lib/RT/Interface/Web.pm
+++ b/lib/RT/Interface/Web.pm
@@ -65,6 +65,7 @@ package RT::Interface::Web;
 
 use RT::SavedSearches;
 use URI qw();
+use RT::Interface::Web::Menu;
 use RT::Interface::Web::Session;
 use Digest::MD5 ();
 use Encode qw();
@@ -284,6 +285,12 @@ sub MaybeShowNoAuthPage {
     $m->abort;
 }
 
+sub InitializeMenu {
+    $HTML::Mason::Commands::m->notes('menu', RT::Interface::Web::Menu->new());
+
+}
+
+
 =head2 ShowRequestedPage  \%ARGS
 
 This function, called exclusively by RT's autohandler, dispatches
@@ -297,6 +304,8 @@ sub ShowRequestedPage {
 
     my $m = $HTML::Mason::Commands::m;
 
+    InitializeMenu();
+
     SendSessionCookie();
 
     # If the user isn't privileged, they can only see SelfService
@@ -810,6 +819,9 @@ package HTML::Mason::Commands;
 
 use vars qw/$r $m %session/;
 
+sub Menu {
+    return $HTML::Mason::Commands::m->notes('menu');
+}
 
 =head2 loc ARRAY
 
diff --git a/lib/RT/Interface/Web/Menu.pm b/lib/RT/Interface/Web/Menu.pm
index 1665d7b..6f831f4 100644
--- a/lib/RT/Interface/Web/Menu.pm
+++ b/lib/RT/Interface/Web/Menu.pm
@@ -57,7 +57,7 @@ use URI;
 use Scalar::Util qw(weaken);
 
 __PACKAGE__->mk_accessors(qw(
-    label sort_order link target escape_label class render_children_inline
+    title sort_order link target escape_title class render_children_inline
     raw_html
 ));
 
@@ -70,7 +70,7 @@ RT::Interface::Web::Menu - Handle the API for menu navigation
 =head2 new PARAMHASH
 
 Creates a new L<RT::Interface::Web::Menu> object.  Possible keys in the
-I<PARAMHASH> are L</label>, L</parent>, L</sort_order>, L</url>, and
+I<PARAMHASH> are L</title>, L</parent>, L</sort_order>, L</path>, and
 L</active>.  See the subroutines with the respective name below for
 each option's use.
 
@@ -93,7 +93,7 @@ sub new {
 }
 
 
-=head2 label [STRING]
+=head2 title [STRING]
 
 Sets or returns the string that the menu item will be displayed as.
 
@@ -155,23 +155,23 @@ Note that YUI doesn't support rendering nested menu groups, so having direct
 parent/children render_children_inline is likely not going to do what you
 want or expect.
 
-=head2 url
+=head2 path
 
 Gets or sets the URL that the menu's link goes to.  If the link
 provided is not absolute (does not start with a "/"), then is is
-treated as relative to it's parent's url, and made absolute.
+treated as relative to it's parent's path, and made absolute.
 
 =cut
 
-sub url {
+sub path {
     my $self = shift;
     if (@_) {
-        $self->{url} = shift;
-        $self->{url} = URI->new_abs($self->{url}, $self->parent->url . "/")->as_string
-            if defined $self->{url} and $self->parent and $self->parent->url;
-        $self->{url} =~ s!///!/! if $self->{url};
+        $self->{path} = shift;
+        $self->{path} = URI->new_abs($self->{path}, $self->parent->path . "/")->as_string
+            if defined $self->{path} and $self->parent and $self->parent->path;
+        $self->{path} =~ s!///!/! if $self->{path};
     }
-    return $self->{url};
+    return $self->{path};
 }
 
 =head2 active [BOOLEAN]
@@ -196,7 +196,7 @@ If only a I<KEY> is provided, returns the child with that I<KEY>.
 
 Otherwise, creates or overwrites the child with that key, passing the
 I<PARAMHASH> to L<RT::Interface::Web::Menu/new>.  Additionally, the paramhash's
-L</label> defaults to the I<KEY>, and the L</sort_order> defaults to the
+L</title> defaults to the I<KEY>, and the L</sort_order> defaults to the
 pre-existing child's sort order (if a C<KEY> is being over-written) or
 the end of the list, if it is a new C<KEY>.
 
@@ -222,8 +222,8 @@ sub child {
         } else {
             $child = $proto->new(
                 {   parent     => $self,
-                    label        => $key,
-                    escape_label => 1,
+                    title        => $key,
+                    escape_title => 1,
                     %args
                 }
             );
@@ -234,28 +234,28 @@ sub child {
             unless ($child->sort_order());
 
         # URL is relative to parents, and cached, so set it up now
-        $child->url( $child->{url} );
+        $child->path( $child->{path} );
 
         # Figure out the URL
-        my $url
+        my $path
             = (     defined $child->link
                 and ref $child->link
-                and $child->link->can('url') )
-            ? $child->link->url
-            : $child->url;
+                and $child->link->can('path') )
+            ? $child->link->path
+            : $child->path;
 
         # Activate it
-        if ( defined $url and length $url and Jifty->web->request ) {
+        if ( defined $path and length $path ) {
 
             # XXX TODO cleanup for mod_perl
-            my $base_path = Jifty->web->request->path;
+            my $base_path = '';#Jifty->web->request->path;
             chomp($base_path);
 
             $base_path =~ s/index\.html$//;
             $base_path =~ s/\/+$//;
-            $url       =~ s/\/+$//;
+            $path       =~ s/\/+$//;
 
-            if ( $url eq $base_path ) {
+            if ( $path eq $base_path ) {
                 $self->{children}{$key}->active(1);
             }
         }
diff --git a/share/html/Elements/Menu b/share/html/Elements/Menu
index 9c5f78d..7107599 100755
--- a/share/html/Elements/Menu
+++ b/share/html/Elements/Menu
@@ -45,6 +45,15 @@
 %# those contributions and any derivatives thereof.
 %#
 %# END BPS TAGGED BLOCK }}}
+<div id="new-menu">
+<pre>
+<ul>
+% for my $child (Menu->children) {
+<li><a href="<%RT->Config->Get('WebPath')%>/<%$child->path%>"><%$child->title%></a></li>
+% }
+</ul>
+</pre>
+</div>
 <ul<% !$level ? ' id="system-menu"' : ''|n %><% $menu_class ? qq[ class="$menu_class"] : ''|n %>>
 <div<% $menu_class ? qq[ class="$menu_class"] : ''|n %>><div class="wrapper">
 <%perl>
diff --git a/share/html/Elements/Tabs b/share/html/Elements/Tabs
index 833ab9c..19955d8 100755
--- a/share/html/Elements/Tabs
+++ b/share/html/Elements/Tabs
@@ -65,44 +65,29 @@ my $basetopactions = {
 	B => { html => $m->scomp('/Elements/SimpleSearch') 
 		}
 	};
-my $basetabs = {     A => { title => loc('Homepage'),
-                           path => 'index.html',
-                         },
-                    Ab => { title => loc('Simple Search'),
-                        path => 'Search/Simple.html'
-                         },
-                    B => { title => loc('Tickets'),
-                        path => 'Search/Build.html'
-                      },
-                    C => { title => loc('Tools'),
-                           path => 'Tools/index.html'
-                         },
-                 };
 
-if ($session{'CurrentUser'}->HasRight( Right => 'ShowConfigTab', 
-				       Object => $RT::System )) {
-    $basetabs->{E} = { title => loc('Configuration'),
-                       path => 'Admin/',
-		     };
-}
+Menu->child( A => title => loc('Homepage'), path => 'index.html' );
+Menu->child( Ab   => title => loc('Simple Search'), path => 'Search/Simple.html' );
+Menu->child( B => title => loc('Tickets'), path => 'Search/Build.html' );
+Menu->child( C => title => loc('Tools'),   path => 'Tools/index.html' );
 
-if ($session{'CurrentUser'}->HasRight( Right => 'ModifySelf', 
-				       Object => $RT::System )) {
-    $basetabs->{K} = { title => loc('Preferences'),
-                       path => 'Prefs/Other.html'
-		     };
+if ( $session{'CurrentUser'}->HasRight( Right  => 'ShowConfigTab', Object => $RT::System )) {
+    Menu->child( E => title => loc('Configuration'), path => 'Admin/' );
 }
 
-if ($session{'CurrentUser'}->HasRight( Right => 'ShowApprovalsTab',
-                        Object => $RT::System )) {
-    $basetabs->{P} = { title => loc('Approval'),
-                        path => 'Approvals/'
-            };
+if ( $session{'CurrentUser'}->HasRight( Right  => 'ModifySelf', Object => $RT::System )) {
+    Menu->child( K    => title => loc('Preferences'), path => 'Prefs/Other.html' );
 }
 
-if (!defined $toptabs) {
-   $toptabs = $basetabs;
+if (
+     $session{'CurrentUser'}->HasRight( Right  => 'ShowApprovalsTab',
+                                        Object => $RT::System )
+   )
+{
+    Menu->child( P    => title => loc('Approval'),
+                 path => 'Approvals/' );
 }
+
 if (!defined $topactions) {
    $topactions = $basetopactions;
 }

commit cf3d0bb4571f075fff15a16bffc1aaeff8f3925c
Author: Jesse Vincent <jesse at bestpractical.com>
Date:   Wed Oct 13 06:45:07 2010 -0400

    first pass at backporting the RT 3.999 stuff

diff --git a/etc/RT_Config.pm.in b/etc/RT_Config.pm.in
index bf8ca2a..6aacbe7 100755
--- a/etc/RT_Config.pm.in
+++ b/etc/RT_Config.pm.in
@@ -2174,6 +2174,8 @@ Set(@JSFilesInHead, qw/
     titlebox-state.js
     util.js
     userautocomplete.js
+    superfish.js
+    supersubs.js
 /);
 
 =item C<$JSMinPath>
diff --git a/lib/RT/Interface/Web.pm b/lib/RT/Interface/Web.pm
index e29e46b..1c8d276 100755
--- a/lib/RT/Interface/Web.pm
+++ b/lib/RT/Interface/Web.pm
@@ -287,6 +287,7 @@ sub MaybeShowNoAuthPage {
 
 sub InitializeMenu {
     $HTML::Mason::Commands::m->notes('menu', RT::Interface::Web::Menu->new());
+    $HTML::Mason::Commands::m->notes('page-menu', RT::Interface::Web::Menu->new());
 
 }
 
@@ -823,6 +824,10 @@ sub Menu {
     return $HTML::Mason::Commands::m->notes('menu');
 }
 
+sub PageMenu {
+    return $HTML::Mason::Commands::m->notes('page-menu');
+}
+
 =head2 loc ARRAY
 
 loc is a nice clean global routine which calls $session{'CurrentUser'}->loc()
diff --git a/lib/RT/Interface/Web/Menu.pm b/lib/RT/Interface/Web/Menu.pm
index 6f831f4..10907b3 100644
--- a/lib/RT/Interface/Web/Menu.pm
+++ b/lib/RT/Interface/Web/Menu.pm
@@ -292,6 +292,23 @@ sub delete {
     delete $self->{children}{$key};
 }
 
+
+=head2 has_children
+
+Returns true if there are any children on this menu
+
+=cut
+
+sub has_children {
+    my $self = shift;
+    if (@{ $self->children}) {
+        return 1
+    } else {
+        return 0;
+    }
+}
+
+
 =head2 children
 
 Returns the children of this menu item in sorted order; as an array in
diff --git a/lib/RT/SharedSetting.pm b/lib/RT/SharedSetting.pm
index 5eab2ea..32a515d 100644
--- a/lib/RT/SharedSetting.pm
+++ b/lib/RT/SharedSetting.pm
@@ -295,6 +295,9 @@ sub Id {
     return $self->{'Id'};
 }
 
+*id = \&Id;
+
+
 =head2 Privacy
 
 Returns the principal object to whom this shared setting belongs, in a string
diff --git a/share/html/Elements/Menu b/share/html/Elements/Menu
index 7107599..184b757 100755
--- a/share/html/Elements/Menu
+++ b/share/html/Elements/Menu
@@ -45,85 +45,16 @@
 %# those contributions and any derivatives thereof.
 %#
 %# END BPS TAGGED BLOCK }}}
-<div id="new-menu">
-<pre>
-<ul>
-% for my $child (Menu->children) {
-<li><a href="<%RT->Config->Get('WebPath')%>/<%$child->path%>"><%$child->title%></a></li>
+<ul <%$id ? "id=\"$id\"" : '' |n%> class="sf-menu sf-navbar">
+% for my $child ($menu->children) {
+<li><a href="<%RT->Config->Get('WebPath')%><%$child->path%>"><%$child->title%></a></li>
+% next unless ($child->has_children);
+<& Menu, menu => $child &>
 % }
 </ul>
-</pre>
-</div>
-<ul<% !$level ? ' id="system-menu"' : ''|n %><% $menu_class ? qq[ class="$menu_class"] : ''|n %>>
-<div<% $menu_class ? qq[ class="$menu_class"] : ''|n %>><div class="wrapper">
-<%perl>
- my $sep         = 0;
- my $postsep     = 0;
- my $accesskey   = 1;
- 
- $count = 0;
- $class = {};
-
-my @tabs = sort keys %$toptabs;
- foreach $tab (@tabs) {
-     $count++;
-
-     my $current = $current_toptab || '';
-     my $path    = $toptabs->{$tab}->{'path'} || "";
-     my $target  = $toptabs->{$tab}->{'target'} || "";
-     
-     $path    =~ s#/index.html$##gi;
-     $current =~ s#/index.html$##gi;
-     
-     $sep     = $toptabs->{$tab}->{'separator'} ? 1 : 0;
-
-     my @aclass;
-     push @aclass, 'selected' if $path eq $current;
-     push @aclass, 'odd' if $level % 2;
-     $class->{a} = join ' ', @aclass;
-
-     my @li;
-     push @li, 'first' if $count == 1;
-     push @li, 'pre-separator' if $sep;
-     push @li, 'post-separator' if $postsep;
-     push @li, 'last' if ( $tab eq $tabs[-1]);
-     $class->{li} = join ' ', @li;
-
-     my $url = ($toptabs->{$tab}->{'path'}||'') =~ /^(?:https?|mailto):/i
-         ? $toptabs->{$tab}->{'path'} || ''
-         : RT->Config->Get('WebPath') . "/" . $toptabs->{$tab}->{'path'};
-     
-</%perl>
-    <li<% $class->{'li'} ? qq[ class="$class->{li}"] : ''|n %>><% $count > 1 && !$postsep && qq[<span class="bullet">&#183; </span>]|n%><a href="<% $url %>" <% $class->{a} && qq[ class="$class->{a}"] |n %> <% $target && qq[ target="$target"] |n %> <% !$level && " accesskey='".$accesskey++."'" |n %>><% $toptabs->{$tab}->{'title'}%></a>
-%
-%# Second-level items
-%     if ($toptabs->{$tab}->{'subtabs'}
-%         and keys %{$toptabs->{$tab}->{'subtabs'}})
-%     {
-          <& /Elements/Menu, level => $level+1, 
-                             current_toptab => $toptabs->{$tab}->{'current_subtab'},
-                             toptabs => $toptabs->{$tab}->{'subtabs'},
-                             last_level => $toptabs->{$tab}->{last_system_menu_level} &>
-%     }
-  </li>
-%     if ($sep) {
-  <li class="separator">&#183;&#183;&#183;</li>
-%     }
-%
-%     $postsep = $sep;
-% }
-</div></div>
-</ul>
-
 <%INIT>
-my ($tab, $class, $count, @ul);
-push @ul, 'last-menu-level' if $last_level;
-push @ul, 'odd' if $level % 2;
-my $menu_class = join ' ', @ul;
 </%INIT>
 <%ARGS>
-$toptabs => {}
-$current_toptab => ''
-$level => 0
-$last_level => 0
+$menu
+$id => undef
 </%ARGS>
diff --git a/share/html/Elements/PageLayout b/share/html/Elements/PageLayout
index 0ba9529..dc7b8eb 100755
--- a/share/html/Elements/PageLayout
+++ b/share/html/Elements/PageLayout
@@ -55,69 +55,20 @@
 </div>
 
 % if ( $show_menu ) {
-<div id="nav">
-<& /Elements/Menu, toptabs => $toptabs, current_toptab => $current_toptab &>
-</div>
-% }
+<div id="nav"><& /Elements/Menu, menu => Menu(), id => 'app-nav' &></div>
 
+<div id="page-navigation"><& /Elements/Menu, menu => PageMenu(), id => 'page-menu' &></div>
+% }
+<script>
+  jQuery("nav>ul").superfish();
+</script>
 <div id="header">
 <h1><% $title %></h1>
-<div id="page-navigation">
 % my $sep       = 0;
 % my $postsep   = 0;
 % my $count     = 0;
 % my $class     = { };
 % 
-  <ul id="page-menu" <% (($actions && %$actions) || ($subactions && %$subactions)) && q[ class="actions-present"] | n %>>
-    <div><div><div>
-<%perl>
- if ($page_tabs) {
-     my @tabs = ( sort grep { $_ !~ /^(?:current_toptab|this)$/ } keys %{$page_tabs});
-     my $tab_idx = -1;
-     foreach my $tab ( @tabs ) {
-         $count++;
-         $tab_idx++;
-
-         my $current = $page_tabs->{current_toptab} || "";
-         my $path    = $page_tabs->{$tab}->{'path'} || "";
-         
-         $path    =~ s#(/index\.html)?(\?)?$##gi;
-         $current =~ s#(/index\.html)?(\?)?$##gi;
-         
-         $sep = $toptabs->{$tab}->{'separator'} ? 1 : 0;
-
-         my $next_tab = $tabs[$tab_idx+1];
-         if ($next_tab && $toptabs->{$next_tab}->{'pre_separator'}) {
-            $sep = 1;
-         }
-
-         $class->{a} = $path eq $current ? ' class="selected"' : undef;
-
-         my @li;
-         push @li, 'first' if $count == 1;
-         push @li, 'pre-separator' if $sep;
-         push @li, 'post-separator' if $postsep;
-         push @li, 'last' if $tab eq $tabs[-1];
-         $class->{li} = join ' ', @li;
-
-         my $href = $page_tabs->{$tab}->{'path'} || "";
-         $href = RT->Config->Get('WebPath') .'/'. $href
-            unless $path =~ /^\w+:/;
-         my $target = $page_tabs->{$tab}->{'target'} || '';
-         $target = $m->interp->apply_escapes( $target, 'h' );
-</%perl>
-    <li<% $class->{li} ? qq[ class="$class->{li}"] : ''|n %>><% $count > 1 && !$postsep && "&#183; "|n%><a href="<% $href %>"<%$class->{a}|n%><% $class->{a} ? ' name="focus"' : ''|n %><% $target? " target='$target'": '' |n %>><% $page_tabs->{$tab}->{'title'} %></a></li>
-%
-%         if ($sep) {
-    <li class="separator">&#183;&#183;&#183;</li>
-%         }
-%         $postsep = $sep;
-%     }
-% } else {
-&nbsp;
-% }
-    </div></div></div>
-  </ul>
 
 % if (($actions && %$actions) || ($subactions && %$subactions)) {
   <ul id="actions-menu">
@@ -170,7 +121,6 @@
   </ul>
 % }
 </div>
-</div>
 <div id="body">
 % $m->callback( %ARGS, CallbackName => 'BeforeBody' );
 % $m->flush_buffer(); # we've got the page laid out, let's flush the buffer;
diff --git a/share/html/Elements/Tabs b/share/html/Elements/Tabs
index 19955d8..1469194 100755
--- a/share/html/Elements/Tabs
+++ b/share/html/Elements/Tabs
@@ -2,10 +2,10 @@
 %#
 %# COPYRIGHT:
 %#
-%# This software is Copyright (c) 1996-2010 Best Practical Solutions, LLC
+%# This software is CopyRight (c) 1996-2010 Best Practical Solutions, LLC
 %#                                          <jesse at bestpractical.com>
 %#
-%# (Except where explicitly superseded by other copyright notices)
+%# (Except where explicitly superseded by other copyRight notices)
 %#
 %#
 %# LICENSE:
@@ -29,7 +29,7 @@
 %#
 %# CONTRIBUTION SUBMISSION POLICY:
 %#
-%# (The following paragraph is not intended to limit the rights granted
+%# (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
@@ -38,7 +38,7 @@
 %# 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
+%# 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
@@ -58,46 +58,439 @@
 &>
 <a name="skipnav" id="skipnav" accesskey="8"></a>
 <%INIT>
-my $action;
-my $basetopactions = {
-	A => { html => $m->scomp('/Elements/CreateTicket')	
-		},
-	B => { html => $m->scomp('/Elements/SimpleSearch') 
-		}
+
+my $request_path = $HTML::Mason::Commands::m->request_comp->path;
+
+my $query_string = sub { my %args = @_; my $u = URI->new(); $u->query_form(%args); return $u->query };
+
+my $PREFS_NAV = RT::Interface::Web::Menu->new( { title => loc('Preferences'), path => '/Prefs/Other.html' } );
+$PREFS_NAV->child( loc('Settings'),       path => '/Prefs/Other.html', );
+$PREFS_NAV->child( loc('About me'),       path => '/User/Prefs.html', );
+$PREFS_NAV->child( loc('Search options'), path => '/Prefs/SearchOptions.html', );
+$PREFS_NAV->child( loc('RT at a glance'), path => '/Prefs/MyRT.html', );
+
+
+if ($request_path =~ qr{.*} ) {
+    Menu->child( loc('Homepage'),      path => '/' );
+    my $tickets = Menu->child( loc('Tickets'),       path => '/Search/Build.html' );
+    $tickets->child( new => title => loc('New Search')  => path => "/Search/Build.html?NewQuery=1" );
+    my $new = $tickets->child(create => title => loc('New ticket'), path => '/Ticket/Create.html');
+
+    my $q = RT::Queues->new($session{'CurrentUser'});
+    $q->FindAllRows;
+    while (my $queue = $q->Next) {
+            next unless $queue->CurrentUserHasRight('CreateTicket');
+            $new->child( $queue->id => title => $queue->Name, path => '/Ticket/Create.html?Queue='.$queue->id);
+    }
+
+    my $tools = Menu->child( loc('Tools'), path => '/Tools/index.html' );
+    $tools->child( loc('Dashboards'), path => '/Dashboards/index.html' );
+
+    my $reports = $tools->child( loc('Reports'), path => '/Tools/Reports/index.html' );
+    $reports->child( loc('Resolved by owner'),       path => '/Tools/Reports/ResolvedByOwner.html', );
+    $reports->child( loc('Resolved in date range'),  path => '/Tools/Reports/ResolvedByDates.html', );
+    $reports->child( loc('Created in a date range'), path => '/Tools/Reports/CreatedByDates.html', );
+
+    $tools->child( loc('My Day'), path => '/Tools/MyDay.html' );
+    if ( $session{'CurrentUser'}->HasRight( Right => 'ShowApprovalsTab', Object => $RT::System ) )
+    {
+        $tools->child( loc('Approval'), path => '/Approvals/' );
+    }
+
+    if ( $session{'CurrentUser'}->HasRight( Right => 'ShowConfigTab', Object => $RT::System ) )
+    {
+        my $admin = Menu->child( Config => title => loc('Configuration'), path => '/Admin/' );
+        $admin->child( loc('Users'),         path => '/Admin/Users/', );
+        $admin->child( loc('Groups'),        path => '/Admin/Groups/', );
+        $admin->child( loc('Queues'),        path => '/Admin/Queues/', );
+        $admin->child( loc('Custom Fields'), path => '/Admin/CustomFields/', );
+        $admin->child( loc('Rules'),         path => '/admin/rules/', );
+
+        my $admin_global = $admin->child( loc('Global'), path => '/Admin/Global/', );
+
+        $admin_global->child( loc('Templates'), path => '/Admin/Global/Templates.html', );
+        my $workflows = $admin_global->child( loc('Workflows'), path => '/Admin/Global/Workflows/index.html', );
+        {
+            $workflows->child( loc('Overview')     => path => "/Admin/Global/Workflows/index.html" );
+            $workflows->child( loc('Localization') => path => "/Admin/Global/Workflows/Localization.html" );
+            $workflows->child( loc('Mappings')     => path => "/Admin/Global/Workflows/Mappings.html" );
+        }
+
+        my $cfadmin = $admin_global->child( loc('Custom Fields'), path => '/Admin/Global/CustomFields/index.html', );
+        {
+            $cfadmin->child(
+                loc('Users') => text => loc('Select custom fields for all users'),
+               path => '/Admin/Global/CustomFields/Users.html'
+            );
+
+            $cfadmin->child(
+                loc('Groups') => text => loc('Select custom fields for all user groups'),
+               path => '/Admin/Global/CustomFields/Groups.html'
+            );
+
+            $cfadmin->child(
+                loc('Queues') => text => loc('Select custom fields for all queues'),
+               path => '/Admin/Global/CustomFields/Queues.html'
+            );
+
+            $cfadmin->child(
+                loc('Tickets') => text => loc('Select custom fields for tickets in all queues'),
+                path => '/Admin/Global/CustomFields/Queue-Tickets.html'
+            );
+
+            $cfadmin->child(
+                loc('Ticket Transactions') => text => loc('Select custom fields for transactions on tickets in all queues'),
+                path => 'Admin/Global/CustomFields/Queue-Transactions.html'
+            );
+
+        }
+
+        $admin_global->child( loc('Group Rights'),   path => '/Admin/Global/GroupRights.html', );
+        $admin_global->child( loc('User Rights'),    path => '/Admin/Global/UserRights.html', );
+        $admin_global->child( loc('RT at a glance'), path => '/Admin/Global/MyRT.html', );
+        $admin_global->child( loc('System'),         path => '/Admin/Global/System.html', );
+
+        my $admin_tools = $admin->child( loc('Tools'), path => '/Admin/Tools/', );
+        $admin_tools->child( loc('System Configuration'), path => '/Admin/Tools/Configuration.html', );
+        $admin_tools->child( loc('Shredder'),             path => '/Admin/Tools/Shredder', );
+    }
+    if ($session{'CurrentUser'}->UserObj
+        && $session{'CurrentUser'}->HasRight(
+            Right  => 'ModifySelf',
+            Object => $RT::System
+        )
+        )
+    {
+
+     if ( $session{'CurrentUser'}->HasRight( Right => 'ModifySelf', Object => $RT::System ) ) {
+
+        Menu->child( 'Preferences' => menu => $PREFS_NAV, order => 99 );
+    }
+     }
+
+
+
+
 	};
 
-Menu->child( A => title => loc('Homepage'), path => 'index.html' );
-Menu->child( Ab   => title => loc('Simple Search'), path => 'Search/Simple.html' );
-Menu->child( B => title => loc('Tickets'), path => 'Search/Build.html' );
-Menu->child( C => title => loc('Tools'),   path => 'Tools/index.html' );
+if ($request_path =~ qr'Dashboards/?' ) {
+    require RT::Dashboard;    # not a record class, so not autoloaded :/
+    PageMenu->child( loc('Select'), path => "/Dashboards/index.html" );
+    my $dashboard = RT::Dashboard->new($session{CurrentUser});
+    if ( $dashboard->_PrivacyObjects( create => 1 ) ) {
+        PageMenu->child( loc('Create') => path => "/Dashboards/Modify.html?Create=1" );
+    }
+};
 
-if ( $session{'CurrentUser'}->HasRight( Right  => 'ShowConfigTab', Object => $RT::System )) {
-    Menu->child( E => title => loc('Configuration'), path => 'Admin/' );
-}
 
-if ( $session{'CurrentUser'}->HasRight( Right  => 'ModifySelf', Object => $RT::System )) {
-    Menu->child( K    => title => loc('Preferences'), path => 'Prefs/Other.html' );
-}
+if ($request_path =~ qr'Dashboards/(\d*)?' ) {
+    if ( my $id = ( $1 || $m->request_args->{'id'} ) ) {
+        my $obj = RT::Dashboard->new($session{'CurrentUser'});
+        $obj->LoadById($id);
+        if ( $obj and $obj->id ) {
+            my $tabs = PageMenu->child( "this" => title => $obj->Name, path => "/Dashboards/Modify.html?id=" . $obj->id );
+            $tabs->child( loc('Basics'),       path => "/Dashboards/Modify.html?id=" . $obj->id );
+            $tabs->child( loc('Queries'),      path => "/Dashboards/Queries.html?id=" . $obj->id );
+            $tabs->child( loc('Subscription'), path => "/Dashboards/Subscription.html?dashboard_id=" . $obj->id )
+                if $obj->CurrentUserCanSubscribe;
+            $tabs->child( loc('Show'), path => "/Dashboards/" . $obj->id . "/" . $obj->Name )
+
+        }
+    }
+};
+
+if ($request_path =~ qr'/SelfService' ) {
+
+    my $queues = RT::Queues->new($session{'CurrentUser'});
+    $queues->FindAllRows;
+
+    my $queue_count = 0;
+    my $queue_id    = 1;
+
+    while ( my $queue = $queues->Next ) {
+        next unless $queue->CurrentUserHasRight('CreateTicket');
+        $queue_id = $queue->id;
+        $queue_count++;
+        last if ( $queue_count > 1 );
+    }
+
+    my $TOP = Menu();
+
+    $TOP->child( loc('Open tickets'),   path => '/SelfService/', );
+    $TOP->child( loc('Closed tickets'), path => '/SelfService/Closed.html', );
+    if ( $queue_count > 1 ) {
+        $TOP->child( loc('New ticket'), path => '/SelfService/CreateTicketInQueue.html' );
+    } else {
+        $TOP->child( loc('New ticket'), path => '/SelfService/Create.html?queue=' . $queue_id );
+    }
+
+    if ( $session{'CurrentUser'}->HasRight( Right => 'ModifySelf', Object => $RT::System ) ) {
+        $TOP->child( loc('Preferences'), path => '/SelfService/Prefs.html' );
+    }
+
+    # XXX TODO RENDER GOTO TICKET WIDGET
+    #Menu->child( B =>  html => $m->scomp('GotoTicket'))
+};
+
+if ($request_path =~ qr'Admin/Queues' ) {
+    if ( $session{'CurrentUser'}->HasRight( Object => $RT::System, Right => 'AdminQueue' ) ) {
+        PageMenu->child( loc('Select'), path => "/Admin/Queues/" );
+        PageMenu->child( loc('Create'), path => "/Admin/Queues/Modify.html?Create=1" );
+    }
+    if ( my $id = $m->request_args->{'id'} ) {
+        my $queue_obj = RT::Queue->new($session{'CurrentUser'});
+        $queue_obj->Load($id);
+
+        my $queue = PageMenu->child( $queue_obj->Name => path => "/Admin/Queues/Modify.html?id=" . $id );
+        $queue->child( loc('Basics'),    path => "/Admin/Queues/Modify.html?id=" . $id );
+        $queue->child( loc('Watchers'),  path => "/Admin/Queues/People.html?id=" . $id );
+        $queue->child( loc('Templates'), path => "/Admin/Queues/Templates.html?id=" . $id );
+
+        $queue->child( loc('Ticket Custom Fields'),
+            path => '/Admin/Queues/CustomFields.html?sub_type=RT::Ticket&id=' . $id );
+
+        $queue->child( loc('Transaction Custom Fields'),
+            path => '/Admin/Queues/CustomFields.html?sub_type=RT::Ticket-RT::Transaction&id=' . $id );
+
+        $queue->child( loc('Group Rights'), path => "/Admin/Queues/GroupRights.html?id=" . $id );
+        $queue->child( loc('User Rights'),  path => "/Admin/Queues/UserRights.html?id=" . $id );
+    }
+};
+
+if ($request_path =~ qr'/Admin/Users' ) {
+    if ( $session{'CurrentUser'}->HasRight( Object => $RT::System, Right => 'AdminUsers' ) ) {
+        PageMenu->child( loc('Select'), path => "/Admin/Users/" );
+        PageMenu->child( loc('Create'), path => "/Admin/Users/Modify.html?Create=1", separator => 1 );
+    }
+    if ( my $id = $m->request_args->{'id'} ) {
+        my $obj = RT::User->new($session{'CurrentUser'});
+        $obj->Load($id);
+        my $tabs = PageMenu->child( 'current' => title => $obj->Name, path => "/Admin/Users/Modify.html?id=" . $id, );
+        $tabs->child( loc('Basics'),         path => "/Admin/Users/Modify.html?id=" . $id );
+        $tabs->child( loc('Memberships'),    path => "/Admin/Users/Memberships.html?id=" . $id );
+        $tabs->child( loc('History'),        path => "/Admin/Users/History.html?id=" . $id );
+        $tabs->child( loc('RT at a glance'), path => "/Admin/Users/MyRT.html?id=" . $id );
+        if ( RT->config->get('gnupg')->{'enable'} ) {
+            $tabs->child( loc('GnuPG'), path => "/Admin/Users/GnuPG.html?id=" . $id );
+        }
+    }
+
+};
+
+if ($request_path =~ qr'Admin/Groups' ) {
+
+    PageMenu->child( loc('Select') => path => "/Admin/Groups/" );
+    PageMenu->child( loc('Create') => path => "/Admin/Groups/Modify.html?Create=1", separator => 1 );
+    if ( my $id = $m->request_args->{'id'} ) {
+        my $obj = RT::User->new($session{'CurrentUser'});
+        $obj->Load($id);
+        my $tabs = PageMenu->child( $obj->Name, path => "/Admin/CustomFields/Modify.html?id=" . $id );
+        $tabs->child( loc('Basics')       => path => "/Admin/Groups/Modify.html?id=" . $obj->id );
+        $tabs->child( loc('Members')      => path => "/Admin/Groups/Members.html?id=" . $obj->id );
+        $tabs->child( loc('Group Rights') => path => "/Admin/Groups/GroupRights.html?id=" . $obj->id );
+        $tabs->child( loc('User Rights')  => path => "/Admin/Groups/UserRights.html?id=" . $obj->id );
+        $tabs->child( loc('History')      => path => "/Admin/Groups/History.html?id=" . $obj->id );
+    }
+};
+
+if ($request_path =~ qr'Admin/CustomFields/' ) {
+    if ( $session{'CurrentUser'}->HasRight( Object => $RT::System, Right => 'AdminCustomField' ) ) {
+        PageMenu->child( loc('Select'), path => "/Admin/CustomFields/" );
+        PageMenu->child( loc('Create') => path => "/Admin/CustomFields/Modify.html?Create=1", );
+
+    }
+    if ( my $id = $m->request_args->{'id'} ) {
+        my $obj = RT::CustomField->new($session{'CurrentUser'});
+        $obj->Load($id);
+        my $tabs = PageMenu->child( $obj->Name, path => "/Admin/CustomFields/Modify.html?id=" . $id );
+
+        $tabs->child( loc('Basics')       => path => "/Admin/CustomFields/Modify.html?id=" . $id );
+        $tabs->child( loc('Group Rights') => path => "/Admin/CustomFields/GroupRights.html?id=" . $id );
+        $tabs->child( loc('User Rights')  => path => "/Admin/CustomFields/UserRights.html?id=" . $id );
+
+        if ( $obj->lookup_type =~ /^RT::Queue-/io ) {
+            $tabs->child( loc('Applies to'), path => "/Admin/CustomFields/Objects.html?id=" . $id );
+        }
+
+    }
+
+};
+
+if ($request_path =~ qr'Admin/Rules' ) {
+    PageMenu->child( loc('Select'), path => "/Admin/Rules/" );
+    PageMenu->child( loc('Create'), path => "/Admin/Rules/Modify.html?Create=1" );
+};
+
+if ($request_path =~ qr'(?:Ticket|Search)/' ) {
+    if ( ( $m->request_args->{'id'} || '' ) =~ /^(\d+)$/ ) {
+        my $id  = $1;
+        my $obj = RT::Ticket->new($session{'CurrentUser'});
+        $obj->Load($id);
+
+        my $tabs = PageMenu(); #->child( "#" . $id => class => "currentnav",path => "/Ticket/Display.html?id=" . $id);
+
+        $tabs->child( loc('Display') => path => "/Ticket/Display.html?id=" . $id );
+
+        $tabs->child( loc('History') => path => "/Ticket/History.html?id=" . $id );
+        $tabs->child( loc('Basics')  => path => "/Ticket/Modify.html?id=" . $id );
+
+        $tabs->child( loc('Dates') => path => "/Ticket/ModifyDates.html?id=" . $id );
+        $tabs->child( loc('People'), path => "/Ticket/ModifyPeople.html?id=" . $id );
+        $tabs->child( loc('Links'),  path => "/Ticket/ModifyLinks.html?id=" . $id );
+        $tabs->child( loc('Jumbo'),  path => "/Ticket/ModifyAll.html?id=" . $id );
+
+        my %can = ( ModifyTicket => $obj->CurrentUserHasRight('ModifyTicket') );
+
+        if ( $can{'ModifyTicket'} or $obj->CurrentUserHasRight('ReplyToTicket') ) {
+            $tabs->child( loc('Reply'), path => "/Ticket/Update.html?action=respond&id=" . $id );
+        }
+
+        if ( $can{'ModifyTicket'} ) {
+            my $current = $obj->Status;
+            my $schema  = $obj->QueueObj->lifecycle;
+            my $i       = 1;
+            foreach my $next ( $schema->transitions($current) ) {
+                my $action = $schema->transition_action( $current => $next );
+                next if $action eq 'hide';
+
+                my $url = '/Ticket/';
+                if ($action) {
+
+                    $url .= "Update.html?" . $query_string->( Action => $action, DefaultStatus => $next, id => $id );
+                } else {
+
+                    #$url .= "Display.html?" .$query_string->(Status => $next, id => $id );
+                }
+                $tabs->child( loc( $schema->transition_label( $current => $next ) ) => path => $url );
+            }
+
+        }
+        if ( $obj->CurrentUserHasRight('OwnTicket') ) {
+            if ( $obj->OwnerObj->id == RT->Nobody->id ) {
+                $tabs->child( loc('Take') => path => "/Ticket/Display.html?action=take&id=" . $id )
+                    if ( $can{'ModifyTicket'} or $obj->CurrentUserHasRight('TakeTicket') );
+            } elsif ( $obj->OwnerObj->id != $session{'CurrentUser'}->id ) {
+                $tabs->child( loc('Steal') => path => "/Ticket/Display.html?action=steal&id=" . $id )
+                    if ( $can{'ModifyTicket'}
+                    or $obj->CurrentUserHasRight('StealTicket') );
+            }
+        }
+
+        if ( $can{'ModifyTicket'} or $obj->CurrentUserHasRight('CommentOnTicket') ) {
+            $tabs->child( loc('Comment') => path => "/Ticket/Update.html?action=comment&id=" . $id );
+        }
+
+        # $actions->{'_ZZ'} = { html => $m->scomp( '/Ticket/Elements/Bookmark', id => $obj->id ), };
+
+        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();
+            }
+
+            # Don't display prev links if we're on the first ticket
+            if ( $item_map->{$id}->{prev} ) {
+                PageMenu->child(
+                    '<< ' . loc('First') => class => "nav",
+                   path => "/Ticket/Display.html?id=" . $item_map->{first}
+                );
+                PageMenu->child(
+                    '< ' . 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} ) {
+                    PageMenu->child(
+                        loc('next') . ' >' => class => "nav",
+                       path => "/Ticket/Display.html?id=" . $item_map->{$id}->{next}
+                    );
+                    PageMenu->child(
+                        loc('Last') . ' >>' => class => "nav",
+                       path => "/Ticket/Display.html?id=" . $item_map->{last}
+                    );
+                }
+            }
+        }
+    }
+    my $args      = '';
+    my $has_query = '';
+
+    my $search = $session{"CurrentSearchHash"} || {};
+    my $search_id = $m->request_args->{'saved_search_id'} || $search->{'searchid'} || '';
+
+    $has_query = 1 if ( $m->request_args->{'query'} or $search->{'query'} );
+
+    my %query_args = (
+
+        saved_search_id => ( $search_id eq 'new' ) ? undef : $search_id,
+        query    => $m->request_args->{'query'}    || $search->{'query'},
+        format   => $m->request_args->{'format'}   || $search->{'format'},
+        order_by => $m->request_args->{'order_by'} || $search->{'order_by'},
+        order    => $m->request_args->{'order'}    || $search->{'order'},
+        page     => $m->request_args->{'page'}     || $search->{'page'},
+        rows_per_page => (
+            defined $m->request_args->{'rows_per_page'}
+            ? $m->request_args->{'rows_per_page'}
+            : $search->{'rows_per_page'}
+        )
+    );
+
+    $args = "?" . $query_string->(%query_args);
+
+    PageMenu->child( loc('Edit Search') => path => "/Search/Build.html" . ( ($has_query) ? $args : '' ) );
+    PageMenu->child( loc('Advanced')    => path => "/Search/Edit.html$args" );
+
+    if ($has_query) {
+        if ($request_path =~ qr|^Search/Results.html| &&    #XXX TODO better abstraction
+            $session{'CurrentUser'}->HasRight( Right => 'SuperUser', Object => $RT::System )
+            )
+        {
+            my $shred_args = URI->new->query_param(
+                search          => 1,
+                plugin          => 'Tickets',
+                'Tickets:query' => $query_args{'query'},
+                'Tickets:limit' => $query_args{'rows_per_page'}
+            );
+
+            PageMenu->child( 'shredder' => title => loc('Shredder'), path => 'Admin/Tools/Shredder/?' . $shred_args );
+        }
+
+        PageMenu->child( loc('Show Results') => path => "/Search/Results.html$args" );
+
+        PageMenu->child( loc('Bulk Update') => path => "/Search/Bulk.html$args" );
+
+    }
+};
+
+if ( $request_path =~ qr'User/Group' ) {
+    if ( my $id = $m->request_args->{'id'} ) {
+        my $obj = RT::User->new( $session{'CurrentUser'} );
+        $obj->Load($id);
+        my $group = PageMenu->child(
+                           path => "/User/Groups/Modify.html?id=" . $obj->id );
+        $group->child( loc('Basics'),
+                       path => "/User/Groups/Modify.html?id=" . $obj->id );
+        $group->child( loc('Members'),
+                       path => "/User/Groups/Members.html?id=" . $obj->id );
+
+    }
+    PageMenu( loc('Select') => path => "/User/Groups/index.html" );
+    PageMenu( loc('Create') => path => "/User/Groups/Modify.html?Create=1",
+              separator   => 1 );
 
-if (
-     $session{'CurrentUser'}->HasRight( Right  => 'ShowApprovalsTab',
-                                        Object => $RT::System )
-   )
-{
-    Menu->child( P    => title => loc('Approval'),
-                 path => 'Approvals/' );
 }
 
-if (!defined $topactions) {
-   $topactions = $basetopactions;
+if ($request_path =~ qr'Prefs' ) {
+
+    PageMenu->child( 'Quick search' => title => loc('Quick search'), path => '/Prefs/Quicksearch.html' );
 }
-                    
-# Now let callbacks add their extra tabs
-$m->callback(
-    topactions => $topactions, 
-    toptabs    => $toptabs,
-    %ARGS
-);
+
 
 </%INIT>
 <%ARGS>
diff --git a/share/html/NoAuth/css/base/main.css b/share/html/NoAuth/css/base/main.css
index af80183..9c63d85 100644
--- a/share/html/NoAuth/css/base/main.css
+++ b/share/html/NoAuth/css/base/main.css
@@ -54,6 +54,9 @@
 @import "theme-editor.css";
 @import "ticket.css";
 @import "tablesorter.css";
+ at import "superfish.css";
+ at import "superfish-navbar.css";
+ at import "superfish-vertical.css";
 
 % $m->callback(CallbackName => 'End');
 
diff --git a/share/html/NoAuth/css/web2/nav.css b/share/html/NoAuth/css/web2/nav.css
index eb71cdb..82d57e4 100644
--- a/share/html/NoAuth/css/web2/nav.css
+++ b/share/html/NoAuth/css/web2/nav.css
@@ -45,6 +45,8 @@
 %# those contributions and any derivatives thereof.
 %#
 %# END BPS TAGGED BLOCK }}}
+
+% return 0;
 div#nav {
  position: absolute;
  left: 0;

commit 8f50933446490ed179e3b873d7ec6c2ac7faafdc
Author: Jesse Vincent <jesse at bestpractical.com>
Date:   Mon Oct 18 12:01:34 2010 +0900

    basic superfish menuing.

diff --git a/share/html/Elements/Menu b/share/html/Elements/Menu
index 184b757..d47abdb 100755
--- a/share/html/Elements/Menu
+++ b/share/html/Elements/Menu
@@ -45,11 +45,12 @@
 %# those contributions and any derivatives thereof.
 %#
 %# END BPS TAGGED BLOCK }}}
-<ul <%$id ? "id=\"$id\"" : '' |n%> class="sf-menu sf-navbar">
+<ul <%$id ? "id=\"$id\"" : '' |n%> <% $toplevel? 'class="sf-menu sf-js-enabled sf-shadow' : '' |n %>">
 % for my $child ($menu->children) {
-<li><a href="<%RT->Config->Get('WebPath')%><%$child->path%>"><%$child->title%></a></li>
+<li><a href="<%RT->Config->Get('WebPath')%><%$child->path%>"><%$child->title%></a>
 % next unless ($child->has_children);
-<& Menu, menu => $child &>
+<& Menu, menu => $child, toplevel => 0 &>
+</li>
 % }
 </ul>
 <%INIT>
@@ -57,4 +58,5 @@
 <%ARGS>
 $menu
 $id => undef
+$toplevel => 1
 </%ARGS>
diff --git a/share/html/Elements/PageLayout b/share/html/Elements/PageLayout
index dc7b8eb..3dd8a56 100755
--- a/share/html/Elements/PageLayout
+++ b/share/html/Elements/PageLayout
@@ -59,9 +59,12 @@
 
 <div id="page-navigation"><& /Elements/Menu, menu => PageMenu(), id => 'page-menu' &></div>
 % }
-<script>
-  jQuery("nav>ul").superfish();
+<script type="text/javascript">
+jQuery(document).ready(function(){ jQuery("#app-nav").superfish(); });
+jQuery(document).ready(function(){ jQuery("#page-menu").superfish(); });
+jQuery(document).ready(function(){ jQuery("#actions-menu").superfish(); });
 </script>
+
 <div id="header">
 <h1><% $title %></h1>
 % my $sep       = 0;
@@ -70,56 +73,6 @@
 % my $class     = { };
 % 
 
-% if (($actions && %$actions) || ($subactions && %$subactions)) {
-  <ul id="actions-menu">
-    <div><div><div>
-<%perl>
- $sep       = 0;
- $postsep   = 0;
- $count     = 0;
- $class     = { };
-
- for my $type ($actions, $subactions) {
-
- if ($type && %$type) {
-     my @actions  = sort keys %{$type};
-     my $action_idx = -1;
-     foreach my $action (@actions) {
-         $count++;
-         $action_idx++;
-
-         $sep = $type->{$action}->{'separator'} ? 1 : 0;
-
-         my $next_action = $actions[$action_idx+1];
-         if ($next_action && $type->{$next_action}->{'pre_separator'}) {
-            $sep = 1;
-         }
-
-         my @li;
-         push @li, 'first' if $count == 1;
-         push @li, 'pre-separator' if $sep;
-         push @li, 'post-separator' if $postsep;
-         push @li, 'last' if $action  eq $actions[-1];
-
-         $class->{li} = join ' ', @li;
-</%perl>
-    <li<% $class->{li} ? qq[ class="$class->{li}"] : ''|n %>><% $count > 1 && !$postsep && qq[<span class="bullet">&#183; </span>]|n%>
-%         if ($type->{"$action"}->{'html'}) {
-      <% $type->{"$action"}->{'html'} | n %>
-%         } elsif ($type->{$action}->{path})  {
-      <a href="<%RT->Config->Get('WebPath')%>/<%$type->{$action}->{'path'}%>"<% $type->{$action}->{class} && ' class="'.$type->{$action}->{class}.'"' |n %><% $type->{$action}->{id} && ' id="'.$type->{$action}->{id}.'"' |n %>><%$type->{$action}->{'title'}%></a>
-%         }
-    </li>
-%         if ($sep) {
-    <li class="separator">&#183;&#183;&#183;</li>
-%         }
-%         $postsep = $sep;
-%     }
-% }
-% }
-    </div></div></div>
-  </ul>
-% }
 </div>
 <div id="body">
 % $m->callback( %ARGS, CallbackName => 'BeforeBody' );
diff --git a/share/html/Elements/PersonalQuickbar b/share/html/Elements/PersonalQuickbar
index f815366..6e4aecd 100644
--- a/share/html/Elements/PersonalQuickbar
+++ b/share/html/Elements/PersonalQuickbar
@@ -52,9 +52,6 @@ $Prefs => '/Prefs/Other.html'
     <span class="hide"><a href="#skipnav"><&|/l&>Skip Menu</&></a> | </span>
 % if ($session{'CurrentUser'}->Name) {
     <&|/l, "<span>".$session{'CurrentUser'}->Name."</span>" &>Logged in as [_1]</&>
-%     if ( $session{'CurrentUser'}->HasRight( Right => 'ModifySelf', Object => $RT::System ) ) {
-    | <a href="<%RT->Config->Get('WebPath')%><%$Prefs%>"><&|/l&>Preferences</&></a>
-%     }
 % } else {
     <&|/l&>Not logged in.</&>
 % }
diff --git a/share/html/Elements/Tabs b/share/html/Elements/Tabs
index 1469194..641c8d2 100755
--- a/share/html/Elements/Tabs
+++ b/share/html/Elements/Tabs
@@ -23,7 +23,7 @@
 %# 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
+%# 02110-1301 or visit their web Page on the internet at
 %# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html.
 %#
 %#
@@ -61,147 +61,190 @@
 
 my $request_path = $HTML::Mason::Commands::m->request_comp->path;
 
-my $query_string = sub { my %args = @_; my $u = URI->new(); $u->query_form(%args); return $u->query };
+my $query_string = sub {
+    my %args = @_;
+    my $u    = URI->new();
+    $u->query_form(%args);
+    return $u->query;
+};
 
-my $PREFS_NAV = RT::Interface::Web::Menu->new( { title => loc('Preferences'), path => '/Prefs/Other.html' } );
-$PREFS_NAV->child( loc('Settings'),       path => '/Prefs/Other.html', );
-$PREFS_NAV->child( loc('About me'),       path => '/User/Prefs.html', );
-$PREFS_NAV->child( loc('Search options'), path => '/Prefs/SearchOptions.html', );
+my $PREFS_NAV = RT::Interface::Web::Menu->new(
+               { title => loc('Preferences'), path => '/Prefs/Other.html' } );
+$PREFS_NAV->child( loc('Settings'), path => '/Prefs/Other.html', );
+$PREFS_NAV->child( loc('About me'), path => '/User/Prefs.html', );
+$PREFS_NAV->child( loc('Search options'),
+                   path => '/Prefs/SearchOptions.html', );
 $PREFS_NAV->child( loc('RT at a glance'), path => '/Prefs/MyRT.html', );
 
+if ( $request_path =~ qr{.*} ) {
+    Menu->child( home => title =>  loc('HomePage'), path => '/' );
+    my $tickets = Menu->child( search => title => loc('Tickets'),
+                               path => '/Search/Build.html' );
+    $tickets->child( new => title => loc('New Search') => path =>
+                     "/Search/Build.html?NewQuery=1" );
+    my $new = $tickets->child( create => title => loc('New ticket'),
+                               path => '/Ticket/Create.html' );
 
-if ($request_path =~ qr{.*} ) {
-    Menu->child( loc('Homepage'),      path => '/' );
-    my $tickets = Menu->child( loc('Tickets'),       path => '/Search/Build.html' );
-    $tickets->child( new => title => loc('New Search')  => path => "/Search/Build.html?NewQuery=1" );
-    my $new = $tickets->child(create => title => loc('New ticket'), path => '/Ticket/Create.html');
-
-    my $q = RT::Queues->new($session{'CurrentUser'});
+    my $q = RT::Queues->new( $session{'CurrentUser'} );
     $q->FindAllRows;
-    while (my $queue = $q->Next) {
-            next unless $queue->CurrentUserHasRight('CreateTicket');
-            $new->child( $queue->id => title => $queue->Name, path => '/Ticket/Create.html?Queue='.$queue->id);
+    while ( my $queue = $q->Next ) {
+        next unless $queue->CurrentUserHasRight('CreateTicket');
+        $new->child( $queue->id => title => $queue->Name,
+                     path => '/Ticket/Create.html?Queue=' . $queue->id );
     }
 
     my $tools = Menu->child( loc('Tools'), path => '/Tools/index.html' );
     $tools->child( loc('Dashboards'), path => '/Dashboards/index.html' );
 
-    my $reports = $tools->child( loc('Reports'), path => '/Tools/Reports/index.html' );
-    $reports->child( loc('Resolved by owner'),       path => '/Tools/Reports/ResolvedByOwner.html', );
-    $reports->child( loc('Resolved in date range'),  path => '/Tools/Reports/ResolvedByDates.html', );
-    $reports->child( loc('Created in a date range'), path => '/Tools/Reports/CreatedByDates.html', );
+    my $reports = $tools->child( loc('Reports'),
+                                 path => '/Tools/Reports/index.html' );
+    $reports->child( loc('Resolved by owner'),
+                     path => '/Tools/Reports/ResolvedByOwner.html', );
+    $reports->child( loc('Resolved in date range'),
+                     path => '/Tools/Reports/ResolvedByDates.html', );
+    $reports->child( loc('Created in a date range'),
+                     path => '/Tools/Reports/CreatedByDates.html', );
 
     $tools->child( loc('My Day'), path => '/Tools/MyDay.html' );
-    if ( $session{'CurrentUser'}->HasRight( Right => 'ShowApprovalsTab', Object => $RT::System ) )
+    if ( $session{'CurrentUser'}
+         ->HasRight( Right => 'ShowApprovalsTab', Object => $RT::System ) )
     {
         $tools->child( loc('Approval'), path => '/Approvals/' );
     }
 
-    if ( $session{'CurrentUser'}->HasRight( Right => 'ShowConfigTab', Object => $RT::System ) )
+    if ( $session{'CurrentUser'}
+         ->HasRight( Right => 'ShowConfigTab', Object => $RT::System ) )
     {
-        my $admin = Menu->child( Config => title => loc('Configuration'), path => '/Admin/' );
-        $admin->child( loc('Users'),         path => '/Admin/Users/', );
-        $admin->child( loc('Groups'),        path => '/Admin/Groups/', );
-        $admin->child( loc('Queues'),        path => '/Admin/Queues/', );
-        $admin->child( loc('Custom Fields'), path => '/Admin/CustomFields/', );
-        $admin->child( loc('Rules'),         path => '/admin/rules/', );
-
-        my $admin_global = $admin->child( loc('Global'), path => '/Admin/Global/', );
-
-        $admin_global->child( loc('Templates'), path => '/Admin/Global/Templates.html', );
-        my $workflows = $admin_global->child( loc('Workflows'), path => '/Admin/Global/Workflows/index.html', );
+        my $admin = Menu->child( Config => title => loc('Configuration'),
+                                 path   => '/Admin/' );
+        $admin->child( loc('Users'),  path => '/Admin/Users/', );
+        $admin->child( loc('Groups'), path => '/Admin/Groups/', );
+        my $queues = $admin->child( queues => title => loc('Queues'),
+                                    path => '/Admin/Queues/', );
+        $queues->child( loc('Select'), path => "/Admin/Queues/" );
+        $queues->child( loc('Create'),
+                        path => "/Admin/Queues/Modify.html?Create=1" );
+        $admin->child( loc('Custom Fields'), path => '/Admin/CustomFields/',
+        );
+        $admin->child( loc('Rules'), path => '/admin/rules/', );
+
+        my $admin_global
+            = $admin->child( loc('Global'), path => '/Admin/Global/', );
+
+        $admin_global->child( loc('Templates'),
+                              path => '/Admin/Global/Templates.html', );
+
+#        my $workflows = $admin_global->child( loc('Workflows'), path => '/Admin/Global/Workflows/index.html', );
+#        {
+#            $workflows->child( loc('Overview')     => path => "/Admin/Global/Workflows/index.html" );
+#            $workflows->child( loc('Localization') => path => "/Admin/Global/Workflows/Localization.html" );
+#            $workflows->child( loc('Mappings')     => path => "/Admin/Global/Workflows/Mappings.html" );
+#        }
+
+        my $cfadmin = $admin_global->child( loc('Custom Fields'),
+                           path => '/Admin/Global/CustomFields/index.html', );
         {
-            $workflows->child( loc('Overview')     => path => "/Admin/Global/Workflows/index.html" );
-            $workflows->child( loc('Localization') => path => "/Admin/Global/Workflows/Localization.html" );
-            $workflows->child( loc('Mappings')     => path => "/Admin/Global/Workflows/Mappings.html" );
-        }
+            $cfadmin->child( loc('Users') => text =>
+                                 loc('Select custom fields for all users'),
+                             path => '/Admin/Global/CustomFields/Users.html'
+                           );
 
-        my $cfadmin = $admin_global->child( loc('Custom Fields'), path => '/Admin/Global/CustomFields/index.html', );
-        {
             $cfadmin->child(
-                loc('Users') => text => loc('Select custom fields for all users'),
-               path => '/Admin/Global/CustomFields/Users.html'
+                          loc('Groups') => text =>
+                              loc('Select custom fields for all user groups'),
+                          path => '/Admin/Global/CustomFields/Groups.html'
             );
 
-            $cfadmin->child(
-                loc('Groups') => text => loc('Select custom fields for all user groups'),
-               path => '/Admin/Global/CustomFields/Groups.html'
-            );
-
-            $cfadmin->child(
-                loc('Queues') => text => loc('Select custom fields for all queues'),
-               path => '/Admin/Global/CustomFields/Queues.html'
-            );
+            $cfadmin->child( loc('Queues') => text =>
+                                 loc('Select custom fields for all queues'),
+                             path => '/Admin/Global/CustomFields/Queues.html'
+                           );
 
             $cfadmin->child(
-                loc('Tickets') => text => loc('Select custom fields for tickets in all queues'),
-                path => '/Admin/Global/CustomFields/Queue-Tickets.html'
+                    loc('Tickets') => text =>
+                        loc('Select custom fields for tickets in all queues'),
+                    path => '/Admin/Global/CustomFields/Queue-Tickets.html'
             );
 
             $cfadmin->child(
-                loc('Ticket Transactions') => text => loc('Select custom fields for transactions on tickets in all queues'),
+                loc('Ticket Transactions') => text =>
+                    loc(
+                    'Select custom fields for transactions on tickets in all queues'
+                    ),
                 path => 'Admin/Global/CustomFields/Queue-Transactions.html'
             );
 
         }
 
-        $admin_global->child( loc('Group Rights'),   path => '/Admin/Global/GroupRights.html', );
-        $admin_global->child( loc('User Rights'),    path => '/Admin/Global/UserRights.html', );
-        $admin_global->child( loc('RT at a glance'), path => '/Admin/Global/MyRT.html', );
-        $admin_global->child( loc('System'),         path => '/Admin/Global/System.html', );
-
-        my $admin_tools = $admin->child( loc('Tools'), path => '/Admin/Tools/', );
-        $admin_tools->child( loc('System Configuration'), path => '/Admin/Tools/Configuration.html', );
-        $admin_tools->child( loc('Shredder'),             path => '/Admin/Tools/Shredder', );
+        $admin_global->child( loc('Group Rights'),
+                              path => '/Admin/Global/GroupRights.html', );
+        $admin_global->child( loc('User Rights'),
+                              path => '/Admin/Global/UserRights.html', );
+        $admin_global->child( loc('RT at a glance'),
+                              path => '/Admin/Global/MyRT.html', );
+        $admin_global->child( loc('System'),
+                              path => '/Admin/Global/System.html', );
+
+        my $admin_tools
+            = $admin->child( loc('Tools'), path => '/Admin/Tools/', );
+        $admin_tools->child( loc('System Configuration'),
+                             path => '/Admin/Tools/Configuration.html', );
+        $admin_tools->child( loc('Shredder'),
+                             path => '/Admin/Tools/Shredder', );
     }
-    if ($session{'CurrentUser'}->UserObj
-        && $session{'CurrentUser'}->HasRight(
-            Right  => 'ModifySelf',
-            Object => $RT::System
-        )
-        )
+    if ( $session{'CurrentUser'}->UserObj
+         && $session{'CurrentUser'}->HasRight( Right  => 'ModifySelf',
+                                               Object => $RT::System )
+       )
     {
 
-     if ( $session{'CurrentUser'}->HasRight( Right => 'ModifySelf', Object => $RT::System ) ) {
+        if ( $session{'CurrentUser'}
+             ->HasRight( Right => 'ModifySelf', Object => $RT::System ) )
+        {
 
-        Menu->child( 'Preferences' => menu => $PREFS_NAV, order => 99 );
+            Menu->child( 'Preferences' => menu => $PREFS_NAV, Order => 99 );
+        }
     }
-     }
-
-
 
+}
 
-	};
-
-if ($request_path =~ qr'Dashboards/?' ) {
+if ( $request_path =~ qr'Dashboards/?' ) {
     require RT::Dashboard;    # not a record class, so not autoloaded :/
     PageMenu->child( loc('Select'), path => "/Dashboards/index.html" );
-    my $dashboard = RT::Dashboard->new($session{CurrentUser});
+    my $dashboard = RT::Dashboard->new( $session{CurrentUser} );
     if ( $dashboard->_PrivacyObjects( create => 1 ) ) {
-        PageMenu->child( loc('Create') => path => "/Dashboards/Modify.html?Create=1" );
+        PageMenu->child(
+                loc('Create') => path => "/Dashboards/Modify.html?Create=1" );
     }
-};
-
+}
 
-if ($request_path =~ qr'Dashboards/(\d*)?' ) {
+if ( $request_path =~ qr'Dashboards/(\d*)?' ) {
     if ( my $id = ( $1 || $m->request_args->{'id'} ) ) {
-        my $obj = RT::Dashboard->new($session{'CurrentUser'});
+        my $obj = RT::Dashboard->new( $session{'CurrentUser'} );
         $obj->LoadById($id);
         if ( $obj and $obj->id ) {
-            my $tabs = PageMenu->child( "this" => title => $obj->Name, path => "/Dashboards/Modify.html?id=" . $obj->id );
-            $tabs->child( loc('Basics'),       path => "/Dashboards/Modify.html?id=" . $obj->id );
-            $tabs->child( loc('Queries'),      path => "/Dashboards/Queries.html?id=" . $obj->id );
-            $tabs->child( loc('Subscription'), path => "/Dashboards/Subscription.html?dashboard_id=" . $obj->id )
+            my $tabs = PageMenu->child(
+                              "this" => title => $obj->Name,
+                              path => "/Dashboards/Modify.html?id=" . $obj->id
+            );
+            $tabs->child( loc('Basics'),
+                          path => "/Dashboards/Modify.html?id=" . $obj->id );
+            $tabs->child( loc('Queries'),
+                          path => "/Dashboards/Queries.html?id=" . $obj->id );
+            $tabs->child( loc('Subscription'),
+                         path => "/Dashboards/Subscription.html?dashboard_id="
+                             . $obj->id )
                 if $obj->CurrentUserCanSubscribe;
-            $tabs->child( loc('Show'), path => "/Dashboards/" . $obj->id . "/" . $obj->Name )
+            $tabs->child( loc('Show'),
+                        path => "/Dashboards/" . $obj->id . "/" . $obj->Name )
 
         }
     }
-};
+}
 
-if ($request_path =~ qr'/SelfService' ) {
+if ( $request_path =~ qr'/SelfService' ) {
 
-    my $queues = RT::Queues->new($session{'CurrentUser'});
+    my $queues = RT::Queues->new( $session{'CurrentUser'} );
     $queues->FindAllRows;
 
     my $queue_count = 0;
@@ -219,130 +262,193 @@ if ($request_path =~ qr'/SelfService' ) {
     $TOP->child( loc('Open tickets'),   path => '/SelfService/', );
     $TOP->child( loc('Closed tickets'), path => '/SelfService/Closed.html', );
     if ( $queue_count > 1 ) {
-        $TOP->child( loc('New ticket'), path => '/SelfService/CreateTicketInQueue.html' );
+        $TOP->child( loc('New ticket'),
+                     path => '/SelfService/CreateTicketInQueue.html' );
     } else {
-        $TOP->child( loc('New ticket'), path => '/SelfService/Create.html?queue=' . $queue_id );
+        $TOP->child( loc('New ticket'),
+                     path => '/SelfService/Create.html?queue=' . $queue_id );
     }
 
-    if ( $session{'CurrentUser'}->HasRight( Right => 'ModifySelf', Object => $RT::System ) ) {
+    if ( $session{'CurrentUser'}
+         ->HasRight( Right => 'ModifySelf', Object => $RT::System ) )
+    {
         $TOP->child( loc('Preferences'), path => '/SelfService/Prefs.html' );
     }
 
     # XXX TODO RENDER GOTO TICKET WIDGET
     #Menu->child( B =>  html => $m->scomp('GotoTicket'))
-};
+}
 
-if ($request_path =~ qr'Admin/Queues' ) {
-    if ( $session{'CurrentUser'}->HasRight( Object => $RT::System, Right => 'AdminQueue' ) ) {
-        PageMenu->child( loc('Select'), path => "/Admin/Queues/" );
-        PageMenu->child( loc('Create'), path => "/Admin/Queues/Modify.html?Create=1" );
+if ( $request_path =~ qr'Admin/Queues' ) {
+    if ( $session{'CurrentUser'}
+         ->HasRight( Object => $RT::System, Right => 'AdminQueue' ) )
+    {
     }
     if ( my $id = $m->request_args->{'id'} ) {
-        my $queue_obj = RT::Queue->new($session{'CurrentUser'});
+        my $queue_obj = RT::Queue->new( $session{'CurrentUser'} );
         $queue_obj->Load($id);
 
-        my $queue = PageMenu->child( $queue_obj->Name => path => "/Admin/Queues/Modify.html?id=" . $id );
-        $queue->child( loc('Basics'),    path => "/Admin/Queues/Modify.html?id=" . $id );
-        $queue->child( loc('Watchers'),  path => "/Admin/Queues/People.html?id=" . $id );
-        $queue->child( loc('Templates'), path => "/Admin/Queues/Templates.html?id=" . $id );
+        my $queue
+            = PageMenu->child(
+                   $queue_obj->Name => path => "/Admin/Queues/Modify.html?id="
+                       . $id );
+        $queue->child( loc('Basics'),
+                       path => "/Admin/Queues/Modify.html?id=" . $id );
+        $queue->child( loc('Watchers'),
+                       path => "/Admin/Queues/People.html?id=" . $id );
+        $queue->child( loc('Templates'),
+                       path => "/Admin/Queues/Templates.html?id=" . $id );
 
         $queue->child( loc('Ticket Custom Fields'),
-            path => '/Admin/Queues/CustomFields.html?sub_type=RT::Ticket&id=' . $id );
+             path => '/Admin/Queues/CustomFields.html?sub_type=RT::Ticket&id='
+                 . $id );
 
         $queue->child( loc('Transaction Custom Fields'),
-            path => '/Admin/Queues/CustomFields.html?sub_type=RT::Ticket-RT::Transaction&id=' . $id );
-
-        $queue->child( loc('Group Rights'), path => "/Admin/Queues/GroupRights.html?id=" . $id );
-        $queue->child( loc('User Rights'),  path => "/Admin/Queues/UserRights.html?id=" . $id );
+            path =>
+                '/Admin/Queues/CustomFields.html?sub_type=RT::Ticket-RT::Transaction&id='
+                . $id );
+
+        $queue->child( loc('Group Rights'),
+                       path => "/Admin/Queues/GroupRights.html?id=" . $id );
+        $queue->child( loc('User Rights'),
+                       path => "/Admin/Queues/UserRights.html?id=" . $id );
     }
-};
+}
 
-if ($request_path =~ qr'/Admin/Users' ) {
-    if ( $session{'CurrentUser'}->HasRight( Object => $RT::System, Right => 'AdminUsers' ) ) {
+if ( $request_path =~ qr'/Admin/Users' ) {
+    if ( $session{'CurrentUser'}
+         ->HasRight( Object => $RT::System, Right => 'AdminUsers' ) )
+    {
         PageMenu->child( loc('Select'), path => "/Admin/Users/" );
-        PageMenu->child( loc('Create'), path => "/Admin/Users/Modify.html?Create=1", separator => 1 );
+        PageMenu->child( loc('Create'),
+                         path      => "/Admin/Users/Modify.html?Create=1",
+                         separator => 1
+                       );
     }
     if ( my $id = $m->request_args->{'id'} ) {
-        my $obj = RT::User->new($session{'CurrentUser'});
+        my $obj = RT::User->new( $session{'CurrentUser'} );
         $obj->Load($id);
-        my $tabs = PageMenu->child( 'current' => title => $obj->Name, path => "/Admin/Users/Modify.html?id=" . $id, );
-        $tabs->child( loc('Basics'),         path => "/Admin/Users/Modify.html?id=" . $id );
-        $tabs->child( loc('Memberships'),    path => "/Admin/Users/Memberships.html?id=" . $id );
-        $tabs->child( loc('History'),        path => "/Admin/Users/History.html?id=" . $id );
-        $tabs->child( loc('RT at a glance'), path => "/Admin/Users/MyRT.html?id=" . $id );
-        if ( RT->config->get('gnupg')->{'enable'} ) {
-            $tabs->child( loc('GnuPG'), path => "/Admin/Users/GnuPG.html?id=" . $id );
+        my $tabs = PageMenu->child(
+                                 'current' => title => $obj->Name,
+                                 path => "/Admin/Users/Modify.html?id=" . $id,
+        );
+        $tabs->child( loc('Basics'),
+                      path => "/Admin/Users/Modify.html?id=" . $id );
+        $tabs->child( loc('Memberships'),
+                      path => "/Admin/Users/Memberships.html?id=" . $id );
+        $tabs->child( loc('History'),
+                      path => "/Admin/Users/History.html?id=" . $id );
+        $tabs->child( loc('RT at a glance'),
+                      path => "/Admin/Users/MyRT.html?id=" . $id );
+        if ( RT->Config->Get('GnuPG')->{'enable'} ) {
+            $tabs->child( loc('GnuPG'),
+                          path => "/Admin/Users/GnuPG.html?id=" . $id );
         }
     }
 
-};
+}
 
-if ($request_path =~ qr'Admin/Groups' ) {
+if ( $request_path =~ qr'Admin/Groups' ) {
 
     PageMenu->child( loc('Select') => path => "/Admin/Groups/" );
-    PageMenu->child( loc('Create') => path => "/Admin/Groups/Modify.html?Create=1", separator => 1 );
+    PageMenu->child(
+                loc('Create') => path => "/Admin/Groups/Modify.html?Create=1",
+                separator     => 1 );
     if ( my $id = $m->request_args->{'id'} ) {
-        my $obj = RT::User->new($session{'CurrentUser'});
+        my $obj = RT::User->new( $session{'CurrentUser'} );
         $obj->Load($id);
-        my $tabs = PageMenu->child( $obj->Name, path => "/Admin/CustomFields/Modify.html?id=" . $id );
-        $tabs->child( loc('Basics')       => path => "/Admin/Groups/Modify.html?id=" . $obj->id );
-        $tabs->child( loc('Members')      => path => "/Admin/Groups/Members.html?id=" . $obj->id );
-        $tabs->child( loc('Group Rights') => path => "/Admin/Groups/GroupRights.html?id=" . $obj->id );
-        $tabs->child( loc('User Rights')  => path => "/Admin/Groups/UserRights.html?id=" . $obj->id );
-        $tabs->child( loc('History')      => path => "/Admin/Groups/History.html?id=" . $obj->id );
+        my $tabs = PageMenu->child( $obj->Name,
+                        path => "/Admin/CustomFields/Modify.html?id=" . $id );
+        $tabs->child( loc('Basics') => path => "/Admin/Groups/Modify.html?id="
+                      . $obj->id );
+        $tabs->child(
+                    loc('Members') => path => "/Admin/Groups/Members.html?id="
+                        . $obj->id );
+        $tabs->child( loc('Group Rights') => path =>
+                      "/Admin/Groups/GroupRights.html?id=" . $obj->id );
+        $tabs->child(
+             loc('User Rights') => path => "/Admin/Groups/UserRights.html?id="
+                 . $obj->id );
+        $tabs->child(
+                    loc('History') => path => "/Admin/Groups/History.html?id="
+                        . $obj->id );
     }
-};
+}
 
-if ($request_path =~ qr'Admin/CustomFields/' ) {
-    if ( $session{'CurrentUser'}->HasRight( Object => $RT::System, Right => 'AdminCustomField' ) ) {
+if ( $request_path =~ qr'Admin/CustomFields/' ) {
+    if ( $session{'CurrentUser'}
+         ->HasRight( Object => $RT::System, Right => 'AdminCustomField' ) )
+    {
         PageMenu->child( loc('Select'), path => "/Admin/CustomFields/" );
-        PageMenu->child( loc('Create') => path => "/Admin/CustomFields/Modify.html?Create=1", );
+        PageMenu->child( loc('Create') => path =>
+                         "/Admin/CustomFields/Modify.html?Create=1", );
 
     }
     if ( my $id = $m->request_args->{'id'} ) {
-        my $obj = RT::CustomField->new($session{'CurrentUser'});
+        my $obj = RT::CustomField->new( $session{'CurrentUser'} );
         $obj->Load($id);
-        my $tabs = PageMenu->child( $obj->Name, path => "/Admin/CustomFields/Modify.html?id=" . $id );
+        my $tabs = PageMenu->child( $obj->Name,
+                        path => "/Admin/CustomFields/Modify.html?id=" . $id );
 
-        $tabs->child( loc('Basics')       => path => "/Admin/CustomFields/Modify.html?id=" . $id );
-        $tabs->child( loc('Group Rights') => path => "/Admin/CustomFields/GroupRights.html?id=" . $id );
-        $tabs->child( loc('User Rights')  => path => "/Admin/CustomFields/UserRights.html?id=" . $id );
+        $tabs->child(
+                loc('Basics') => path => "/Admin/CustomFields/Modify.html?id="
+                    . $id );
+        $tabs->child( loc('Group Rights') => path =>
+                      "/Admin/CustomFields/GroupRights.html?id=" . $id );
+        $tabs->child( loc('User Rights') => path =>
+                      "/Admin/CustomFields/UserRights.html?id=" . $id );
 
         if ( $obj->lookup_type =~ /^RT::Queue-/io ) {
-            $tabs->child( loc('Applies to'), path => "/Admin/CustomFields/Objects.html?id=" . $id );
+            $tabs->child( loc('Applies to'),
+                       path => "/Admin/CustomFields/Objects.html?id=" . $id );
         }
 
     }
 
-};
+}
 
-if ($request_path =~ qr'Admin/Rules' ) {
+if ( $request_path =~ qr'Admin/Rules' ) {
     PageMenu->child( loc('Select'), path => "/Admin/Rules/" );
-    PageMenu->child( loc('Create'), path => "/Admin/Rules/Modify.html?Create=1" );
-};
+    PageMenu->child( loc('Create'),
+                     path => "/Admin/Rules/Modify.html?Create=1" );
+}
 
-if ($request_path =~ qr'(?:Ticket|Search)/' ) {
+if ( $request_path =~ qr'(?:Ticket|Search)/' ) {
+    my $search = Menu()->child('search');
+    my $actions = PageMenu()->child( transitions => title => lc('Actions') );
     if ( ( $m->request_args->{'id'} || '' ) =~ /^(\d+)$/ ) {
         my $id  = $1;
-        my $obj = RT::Ticket->new($session{'CurrentUser'});
+        my $obj = RT::Ticket->new( $session{'CurrentUser'} );
         $obj->Load($id);
 
-        my $tabs = PageMenu(); #->child( "#" . $id => class => "currentnav",path => "/Ticket/Display.html?id=" . $id);
+        my $tabs = PageMenu()
+            ; #->child( "#" . $id => class => "currentnav",path => "/Ticket/Display.html?id=" . $id);
 
-        $tabs->child( loc('Display') => path => "/Ticket/Display.html?id=" . $id );
+        $tabs->child(
+                 loc('Display') => path => "/Ticket/Display.html?id=" . $id );
 
-        $tabs->child( loc('History') => path => "/Ticket/History.html?id=" . $id );
-        $tabs->child( loc('Basics')  => path => "/Ticket/Modify.html?id=" . $id );
+        $tabs->child(
+                 loc('History') => path => "/Ticket/History.html?id=" . $id );
+        $tabs->child(
+                   loc('Basics') => path => "/Ticket/Modify.html?id=" . $id );
 
-        $tabs->child( loc('Dates') => path => "/Ticket/ModifyDates.html?id=" . $id );
-        $tabs->child( loc('People'), path => "/Ticket/ModifyPeople.html?id=" . $id );
-        $tabs->child( loc('Links'),  path => "/Ticket/ModifyLinks.html?id=" . $id );
-        $tabs->child( loc('Jumbo'),  path => "/Ticket/ModifyAll.html?id=" . $id );
+        $tabs->child(
+               loc('Dates') => path => "/Ticket/ModifyDates.html?id=" . $id );
+        $tabs->child( loc('People'),
+                      path => "/Ticket/ModifyPeople.html?id=" . $id );
+        $tabs->child( loc('Links'),
+                      path => "/Ticket/ModifyLinks.html?id=" . $id );
+        $tabs->child( loc('Jumbo'),
+                      path => "/Ticket/ModifyAll.html?id=" . $id );
 
-        my %can = ( ModifyTicket => $obj->CurrentUserHasRight('ModifyTicket') );
+        my %can
+            = ( ModifyTicket => $obj->CurrentUserHasRight('ModifyTicket') );
 
-        if ( $can{'ModifyTicket'} or $obj->CurrentUserHasRight('ReplyToTicket') ) {
-            $tabs->child( loc('Reply'), path => "/Ticket/Update.html?action=respond&id=" . $id );
+        if (    $can{'ModifyTicket'}
+             or $obj->CurrentUserHasRight('ReplyToTicket') )
+        {
+            $actions->child( loc('Reply'),
+                     path => "/Ticket/Update.html?action=respond&id=" . $id );
         }
 
         if ( $can{'ModifyTicket'} ) {
@@ -356,36 +462,49 @@ if ($request_path =~ qr'(?:Ticket|Search)/' ) {
                 my $url = '/Ticket/';
                 if ($action) {
 
-                    $url .= "Update.html?" . $query_string->( Action => $action, DefaultStatus => $next, id => $id );
+                    $url .= "Update.html?"
+                        . $query_string->( Action        => $action,
+                                           DefaultStatus => $next,
+                                           id            => $id
+                                         );
                 } else {
 
-                    #$url .= "Display.html?" .$query_string->(Status => $next, id => $id );
+       #$url .= "Display.html?" .$query_string->(Status => $next, id => $id );
                 }
-                $tabs->child( loc( $schema->transition_label( $current => $next ) ) => path => $url );
+                $actions->child(
+                      loc( $schema->transition_label( $current => $next ) ) =>
+                          path => $url );
             }
 
         }
         if ( $obj->CurrentUserHasRight('OwnTicket') ) {
             if ( $obj->OwnerObj->id == RT->Nobody->id ) {
-                $tabs->child( loc('Take') => path => "/Ticket/Display.html?action=take&id=" . $id )
-                    if ( $can{'ModifyTicket'} or $obj->CurrentUserHasRight('TakeTicket') );
+                $actions->child( loc('Take') => path =>
+                                "/Ticket/Display.html?action=take&id=" . $id )
+                    if (    $can{'ModifyTicket'}
+                         or $obj->CurrentUserHasRight('TakeTicket') );
             } elsif ( $obj->OwnerObj->id != $session{'CurrentUser'}->id ) {
-                $tabs->child( loc('Steal') => path => "/Ticket/Display.html?action=steal&id=" . $id )
-                    if ( $can{'ModifyTicket'}
-                    or $obj->CurrentUserHasRight('StealTicket') );
+                $actions->child( loc('Steal') => path =>
+                               "/Ticket/Display.html?action=steal&id=" . $id )
+                    if (    $can{'ModifyTicket'}
+                         or $obj->CurrentUserHasRight('StealTicket') );
             }
         }
 
-        if ( $can{'ModifyTicket'} or $obj->CurrentUserHasRight('CommentOnTicket') ) {
-            $tabs->child( loc('Comment') => path => "/Ticket/Update.html?action=comment&id=" . $id );
+        if (    $can{'ModifyTicket'}
+             or $obj->CurrentUserHasRight('CommentOnTicket') )
+        {
+            $actions->child( loc('Comment') => path =>
+                             "/Ticket/Update.html?action=comment&id=" . $id );
         }
 
-        # $actions->{'_ZZ'} = { html => $m->scomp( '/Ticket/Elements/Bookmark', id => $obj->id ), };
+# $actions->{'_ZZ'} = { html => $m->scomp( '/Ticket/Elements/Bookmark', id => $obj->id ), };
 
         if ( defined $session{"tickets"} ) {
 
             # we have to update session data if we get new ItemMap
-            my $updatesession = 1 unless ( $session{"tickets"}->{'item_map'} );
+            my $updatesession = 1
+                unless ( $session{"tickets"}->{'item_map'} );
 
             my $item_map = $session{"tickets"}->ItemMap;
 
@@ -395,24 +514,24 @@ if ($request_path =~ qr'(?:Ticket|Search)/' ) {
 
             # Don't display prev links if we're on the first ticket
             if ( $item_map->{$id}->{prev} ) {
-                PageMenu->child(
-                    '<< ' . loc('First') => class => "nav",
-                   path => "/Ticket/Display.html?id=" . $item_map->{first}
-                );
-                PageMenu->child(
-                    '< ' . loc('Prev') => class => "nav",
-                   path => "/Ticket/Display.html?id=" . $item_map->{$id}->{prev}
+                $search->child(
+                       '<< ' . loc('First') => class => "nav",
+                       path => "/Ticket/Display.html?id=" . $item_map->{first}
                 );
+                $search->child( '< ' . 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} ) {
-                    PageMenu->child(
-                        loc('next') . ' >' => class => "nav",
-                       path => "/Ticket/Display.html?id=" . $item_map->{$id}->{next}
-                    );
-                    PageMenu->child(
+                    $search->child( loc('next') . ' >' => class => "nav",
+                                    path => "/Ticket/Display.html?id="
+                                        . $item_map->{$id}->{next}
+                                  );
+                    $search->child(
                         loc('Last') . ' >>' => class => "nav",
-                       path => "/Ticket/Display.html?id=" . $item_map->{last}
+                        path => "/Ticket/Display.html?id=" . $item_map->{last}
                     );
                 }
             }
@@ -421,59 +540,70 @@ if ($request_path =~ qr'(?:Ticket|Search)/' ) {
     my $args      = '';
     my $has_query = '';
 
-    my $search = $session{"CurrentSearchHash"} || {};
-    my $search_id = $m->request_args->{'saved_search_id'} || $search->{'searchid'} || '';
+    my $current_search = $session{"CurrentSearchHash"} || {};
+    my $search_id
+        = $m->request_args->{'SavedSearchId'}
+        || $search->{'SearchId'}
+        || '';
 
-    $has_query = 1 if ( $m->request_args->{'query'} or $search->{'query'} );
+    $has_query = 1
+        if ( $m->request_args->{'Query'} or $current_search->{'Query'} );
 
     my %query_args = (
 
-        saved_search_id => ( $search_id eq 'new' ) ? undef : $search_id,
-        query    => $m->request_args->{'query'}    || $search->{'query'},
-        format   => $m->request_args->{'format'}   || $search->{'format'},
-        order_by => $m->request_args->{'order_by'} || $search->{'order_by'},
-        order    => $m->request_args->{'order'}    || $search->{'order'},
-        page     => $m->request_args->{'page'}     || $search->{'page'},
-        rows_per_page => (
-            defined $m->request_args->{'rows_per_page'}
-            ? $m->request_args->{'rows_per_page'}
-            : $search->{'rows_per_page'}
-        )
-    );
+        SavedSearchId => ( $search_id eq 'new' ) ? undef : $search_id,
+        Query  => $m->request_args->{'Query'}  || $current_search->{'Query'},
+        Format => $m->request_args->{'Format'} || $current_search->{'Format'},
+        OrderBy => $m->request_args->{'OrderBy'}
+            || $current_search->{'OrderBy'},
+        Order => $m->request_args->{'Order'} || $current_search->{'Order'},
+        Page  => $m->request_args->{'Page'}  || $current_search->{'Page'},
+        RowsPerPage => ( defined $m->request_args->{'RowsPerPage'}
+                           ? $m->request_args->{'RowsPerPage'}
+                           : $current_search->{'RowsPerPage'}
+                         )
+                     );
 
     $args = "?" . $query_string->(%query_args);
 
-    PageMenu->child( loc('Edit Search') => path => "/Search/Build.html" . ( ($has_query) ? $args : '' ) );
-    PageMenu->child( loc('Advanced')    => path => "/Search/Edit.html$args" );
 
+        my $current_search_menu = $search->child( current_search => title => loc('Current Search'));
+        $current_search_menu->child( edit_search => title => loc('Edit Search') => path => "/Search/Build.html" . ( ($has_query) ? $args : '' ) );
+        $current_search_menu->child( loc('Advanced') => path => "/Search/Edit.html$args" );
     if ($has_query) {
-        if ($request_path =~ qr|^Search/Results.html| &&    #XXX TODO better abstraction
-            $session{'CurrentUser'}->HasRight( Right => 'SuperUser', Object => $RT::System )
-            )
+        if ($request_path =~ qr|^Search/Results.html|
+            &&                        #XXX TODO better abstraction
+            $session{'CurrentUser'}
+            ->HasRight( Right => 'SuperUser', Object => $RT::System )
+           )
         {
-            my $shred_args = URI->new->query_param(
-                search          => 1,
-                plugin          => 'Tickets',
-                'Tickets:query' => $query_args{'query'},
-                'Tickets:limit' => $query_args{'rows_per_page'}
-            );
+            my $shred_args =
+                URI->new->query_param(
+                               search          => 1,
+                               plugin          => 'Tickets',
+                               'Tickets:query' => $query_args{'Query'},
+                               'Tickets:limit' => $query_args{'RowsPerPage'}
+                );
 
-            PageMenu->child( 'shredder' => title => loc('Shredder'), path => 'Admin/Tools/Shredder/?' . $shred_args );
+            $current_search_menu->child( 'shredder' => title => loc('Shredder'),
+                            path => 'Admin/Tools/Shredder/?' . $shred_args );
         }
 
-        PageMenu->child( loc('Show Results') => path => "/Search/Results.html$args" );
+        $current_search_menu->child( results => title =>
+                 loc('Show Results') => path => "/Search/Results.html$args" );
 
-        PageMenu->child( loc('Bulk Update') => path => "/Search/Bulk.html$args" );
+        $current_search_menu->child( bulk => title =>
+                     loc('Bulk Update') => path => "/Search/Bulk.html$args" );
 
     }
-};
+}
 
 if ( $request_path =~ qr'User/Group' ) {
     if ( my $id = $m->request_args->{'id'} ) {
         my $obj = RT::User->new( $session{'CurrentUser'} );
         $obj->Load($id);
         my $group = PageMenu->child(
-                           path => "/User/Groups/Modify.html?id=" . $obj->id );
+                          path => "/User/Groups/Modify.html?id=" . $obj->id );
         $group->child( loc('Basics'),
                        path => "/User/Groups/Modify.html?id=" . $obj->id );
         $group->child( loc('Members'),
@@ -482,13 +612,14 @@ if ( $request_path =~ qr'User/Group' ) {
     }
     PageMenu( loc('Select') => path => "/User/Groups/index.html" );
     PageMenu( loc('Create') => path => "/User/Groups/Modify.html?Create=1",
-              separator   => 1 );
+              separator     => 1 );
 
 }
 
-if ($request_path =~ qr'Prefs' ) {
+if ( $request_path =~ qr'Prefs' ) {
 
-    PageMenu->child( 'Quick search' => title => loc('Quick search'), path => '/Prefs/Quicksearch.html' );
+    PageMenu->child( 'Quick search' => title => loc('Quick search'),
+                     path => '/Prefs/Quicksearch.html' );
 }
 
 
diff --git a/share/html/NoAuth/css/base/superfish-navbar.css b/share/html/NoAuth/css/base/superfish-navbar.css
new file mode 100644
index 0000000..68c7135
--- /dev/null
+++ b/share/html/NoAuth/css/base/superfish-navbar.css
@@ -0,0 +1,93 @@
+
+/*** adding the class sf-navbar in addition to sf-menu creates an all-horizontal nav-bar menu ***/
+.sf-navbar {
+	background:		#BDD2FF;
+	height:			2.5em;
+	padding-bottom:	2.5em;
+	position:		relative;
+}
+.sf-navbar li {
+	background:		#AABDE6;
+	position:		static;
+}
+.sf-navbar a {
+	border-top:		none;
+}
+.sf-navbar li ul {
+	width:			44em; /*IE6 soils itself without this*/
+}
+.sf-navbar li li {
+	background:		#BDD2FF;
+	position:		relative;
+}
+.sf-navbar li li ul {
+	width:			13em;
+}
+.sf-navbar li li li {
+	width:			100%;
+}
+.sf-navbar ul li {
+	width:			auto;
+	float:			left;
+}
+.sf-navbar a, .sf-navbar a:visited {
+	border:			none;
+}
+.sf-navbar li.current {
+	background:		#BDD2FF;
+}
+.sf-navbar li:hover,
+.sf-navbar li.sfHover,
+.sf-navbar li li.current,
+.sf-navbar a:focus, .sf-navbar a:hover, .sf-navbar a:active {
+	background:		#BDD2FF;
+}
+.sf-navbar ul li:hover,
+.sf-navbar ul li.sfHover,
+ul.sf-navbar ul li:hover li,
+ul.sf-navbar ul li.sfHover li,
+.sf-navbar ul a:focus, .sf-navbar ul a:hover, .sf-navbar ul a:active {
+	background:		#D1DFFF;
+}
+ul.sf-navbar li li li:hover,
+ul.sf-navbar li li li.sfHover,
+.sf-navbar li li.current li.current,
+.sf-navbar ul li li a:focus, .sf-navbar ul li li a:hover, .sf-navbar ul li li a:active {
+	background:		#E6EEFF;
+}
+ul.sf-navbar .current ul,
+ul.sf-navbar ul li:hover ul,
+ul.sf-navbar ul li.sfHover ul {
+	left:			0;
+	top:			2.5em; /* match top ul list item height */
+}
+ul.sf-navbar .current ul ul {
+	top: 			-999em;
+}
+
+.sf-navbar li li.current > a {
+	font-weight:	bold;
+}
+
+/*** point all arrows down ***/
+/* point right for anchors in subs */
+.sf-navbar ul .sf-sub-indicator { background-position: -10px -100px; }
+.sf-navbar ul a > .sf-sub-indicator { background-position: 0 -100px; }
+/* apply hovers to modern browsers */
+.sf-navbar ul a:focus > .sf-sub-indicator,
+.sf-navbar ul a:hover > .sf-sub-indicator,
+.sf-navbar ul a:active > .sf-sub-indicator,
+.sf-navbar ul li:hover > a > .sf-sub-indicator,
+.sf-navbar ul li.sfHover > a > .sf-sub-indicator {
+	background-position: -10px -100px; /* arrow hovers for modern browsers*/
+}
+
+/*** remove shadow on first submenu ***/
+.sf-navbar > li > ul {
+	background: transparent;
+	padding: 0;
+	-moz-border-radius-bottomleft: 0;
+	-moz-border-radius-topright: 0;
+	-webkit-border-top-right-radius: 0;
+	-webkit-border-bottom-left-radius: 0;
+}
\ No newline at end of file
diff --git a/share/html/NoAuth/css/base/superfish-vertical.css b/share/html/NoAuth/css/base/superfish-vertical.css
new file mode 100644
index 0000000..8025b78
--- /dev/null
+++ b/share/html/NoAuth/css/base/superfish-vertical.css
@@ -0,0 +1,23 @@
+/*** adding sf-vertical in addition to sf-menu creates a vertical menu ***/
+.sf-vertical, .sf-vertical li {
+	width:	10em;
+}
+/* this lacks ul at the start of the selector, so the styles from the main CSS file override it where needed */
+.sf-vertical li:hover ul,
+.sf-vertical li.sfHover ul {
+	left:	10em; /* match ul width */
+	top:	0;
+}
+
+/*** alter arrow directions ***/
+.sf-vertical .sf-sub-indicator { background-position: -10px 0; } /* IE6 gets solid image only */
+.sf-vertical a > .sf-sub-indicator { background-position: 0 0; } /* use translucent arrow for modern browsers*/
+
+/* hover arrow direction for modern browsers*/
+.sf-vertical a:focus > .sf-sub-indicator,
+.sf-vertical a:hover > .sf-sub-indicator,
+.sf-vertical a:active > .sf-sub-indicator,
+.sf-vertical li:hover > a > .sf-sub-indicator,
+.sf-vertical li.sfHover > a > .sf-sub-indicator {
+	background-position: -10px 0; /* arrow hovers for modern browsers*/
+}
\ No newline at end of file
diff --git a/share/html/NoAuth/css/base/superfish.css b/share/html/NoAuth/css/base/superfish.css
new file mode 100644
index 0000000..cc33fdb
--- /dev/null
+++ b/share/html/NoAuth/css/base/superfish.css
@@ -0,0 +1,136 @@
+
+/*** ESSENTIAL STYLES ***/
+.sf-menu, .sf-menu * {
+	margin:			0;
+	padding:		0;
+	list-style:		none;
+}
+.sf-menu {
+	line-height:	1.0;
+}
+.sf-menu ul {
+	position:		absolute;
+	top:			-999em;
+	width:			10em; /* left offset of submenus need to match (see below) */
+}
+.sf-menu ul li {
+	width:			100%;
+}
+.sf-menu li:hover {
+	visibility:		inherit; /* fixes IE7 'sticky bug' */
+}
+.sf-menu li {
+	float:			left;
+	position:		relative;
+}
+.sf-menu a {
+	display:		block;
+	position:		relative;
+}
+.sf-menu li:hover ul,
+.sf-menu li.sfHover ul {
+	left:			0;
+	top:			2.5em; /* match top ul list item height */
+	z-index:		99;
+}
+ul.sf-menu li:hover li ul,
+ul.sf-menu li.sfHover li ul {
+	top:			-999em;
+}
+ul.sf-menu li li:hover ul,
+ul.sf-menu li li.sfHover ul {
+	left:			10em; /* match ul width */
+	top:			0;
+}
+ul.sf-menu li li:hover li ul,
+ul.sf-menu li li.sfHover li ul {
+	top:			-999em;
+}
+ul.sf-menu li li li:hover ul,
+ul.sf-menu li li li.sfHover ul {
+	left:			10em; /* match ul width */
+	top:			0;
+}
+
+/*** DEMO SKIN ***/
+.sf-menu {
+	float:			left;
+	margin-bottom:	1em;
+}
+.sf-menu a {
+	border-left:	1px solid #fff;
+	border-top:		1px solid #CFDEFF;
+	padding: 		.75em 1em;
+	text-decoration:none;
+}
+.sf-menu a, .sf-menu a:visited  { /* visited pseudo selector so IE6 applies text colour*/
+	color:			#13a;
+}
+.sf-menu li {
+	background:		#BDD2FF;
+}
+.sf-menu li li {
+	background:		#AABDE6;
+}
+.sf-menu li li li {
+	background:		#9AAEDB;
+}
+.sf-menu li:hover, .sf-menu li.sfHover,
+.sf-menu a:focus, .sf-menu a:hover, .sf-menu a:active {
+	background:		#CFDEFF;
+	outline:		0;
+}
+
+/*** arrows **/
+.sf-menu a.sf-with-ul {
+	padding-right: 	2.25em;
+	min-width:		1px; /* trigger IE7 hasLayout so spans position accurately */
+}
+.sf-sub-indicator {
+	position:		absolute;
+	display:		block;
+	right:			.75em;
+	top:			1.05em; /* IE6 only */
+	width:			10px;
+	height:			10px;
+	text-indent: 	-999em;
+	overflow:		hidden;
+	background:		url('../images/arrows-ffffff.png') no-repeat -10px -100px; /* 8-bit indexed alpha png. IE6 gets solid image only */
+}
+a > .sf-sub-indicator {  /* give all except IE6 the correct values */
+	top:			.8em;
+	background-position: 0 -100px; /* use translucent arrow for modern browsers*/
+}
+/* apply hovers to modern browsers */
+a:focus > .sf-sub-indicator,
+a:hover > .sf-sub-indicator,
+a:active > .sf-sub-indicator,
+li:hover > a > .sf-sub-indicator,
+li.sfHover > a > .sf-sub-indicator {
+	background-position: -10px -100px; /* arrow hovers for modern browsers*/
+}
+
+/* point right for anchors in subs */
+.sf-menu ul .sf-sub-indicator { background-position:  -10px 0; }
+.sf-menu ul a > .sf-sub-indicator { background-position:  0 0; }
+/* apply hovers to modern browsers */
+.sf-menu ul a:focus > .sf-sub-indicator,
+.sf-menu ul a:hover > .sf-sub-indicator,
+.sf-menu ul a:active > .sf-sub-indicator,
+.sf-menu ul li:hover > a > .sf-sub-indicator,
+.sf-menu ul li.sfHover > a > .sf-sub-indicator {
+	background-position: -10px 0; /* arrow hovers for modern browsers*/
+}
+
+/*** shadows for all but IE6 ***/
+.sf-shadow ul {
+	background:	url('../images/shadow.png') no-repeat bottom right;
+	padding: 0 8px 9px 0;
+	-moz-border-radius-bottomleft: 17px;
+	-moz-border-radius-topright: 17px;
+	-webkit-border-top-right-radius: 17px;
+	-webkit-border-bottom-left-radius: 17px;
+}
+.sf-shadow ul.sf-shadow-off {
+	background: transparent;
+}
diff --git a/share/html/NoAuth/css/images/arrows-ffffff.png b/share/html/NoAuth/css/images/arrows-ffffff.png
new file mode 100644
index 0000000..995df52
Binary files /dev/null and b/share/html/NoAuth/css/images/arrows-ffffff.png differ
diff --git a/share/html/NoAuth/css/images/shadow.png b/share/html/NoAuth/css/images/shadow.png
new file mode 100644
index 0000000..c04d21b
Binary files /dev/null and b/share/html/NoAuth/css/images/shadow.png differ
diff --git a/share/html/NoAuth/css/web2/layout.css b/share/html/NoAuth/css/web2/layout.css
index c1f2eb3..75a7b32 100644
--- a/share/html/NoAuth/css/web2/layout.css
+++ b/share/html/NoAuth/css/web2/layout.css
@@ -68,7 +68,7 @@ div#body {
     -webkit-border-top-left-radius: 0.5em;
     -moz-border-radius-bottomleft: 0.5em;
     -webkit-border-bottom-left-radius: 0.5em;
-    margin-left: 10.5em;
+    margin-left: 1em;
     margin-top: 5.6em;
     margin-right: 0;
     margin-bottom: 0em;
@@ -217,8 +217,9 @@ div#quick-personal {
 
 div#header h1 {
  position: absolute;
- left: 7.25em;
+ left: 0.5em;
  right: 20em;
+ top: 3em;
  overflow: hidden;
  height: 1em;
  font-size: 1.4em;
diff --git a/share/html/NoAuth/css/web2/nav.css b/share/html/NoAuth/css/web2/nav.css
index 82d57e4..f4cc392 100644
--- a/share/html/NoAuth/css/web2/nav.css
+++ b/share/html/NoAuth/css/web2/nav.css
@@ -45,161 +45,22 @@
 %# those contributions and any derivatives thereof.
 %#
 %# END BPS TAGGED BLOCK }}}
-
-% return 0;
-div#nav {
- position: absolute;
- left: 0;
- font-size: 0.9em;
- top: 3.2em;
- width: 10.5em;
- background: #fff;
- -moz-border-radius-bottomright: 0.5em;
- -webkit-border-bottom-right-radius: 0.5em;
-  border-left: 1px solid #999;  
-border-top: 1px solid #999;
-
- -moz-border-radius-topright: 0.5em;
- -webkit-border-top-right-radius: 0.5em;
- z-index: 99;
-
-
-}
-
-#nav #system-menu {
-    overflow: hidden;
-}
-
-div#nav ul {
- padding-left: 0.75em;
- margin-left: 0;
- padding-right: 0.75em;
- list-style-type: none;
-}
-
-div#nav li:first-child {
- border-top: 1px solid #ccc;
- padding-top: 0.25em;
-
-}
-
-div#nav li {
- padding: 0.125em;
- padding-bottom: 0.25em;
- margin-bottom: 0.25em;
- border-bottom: 1px solid #ccc;
- padding-left: 0.5em;
- margin-right: 0.25em;
- margin-left: 0em;
-}
-
-div#nav li li:first-child {
-    margin-top: 0.25em;
-}
-div#nav li li {
-    margin-left: -0.5em;
-    padding-left: 0.25em;
-    margin-right: -0.5em;
-}
-
-div#nav li li:last-child {
-    margin-bottom: 0; 
-    padding-bottom: 0;
-    border: none;
-}
-
-div#nav .bullet {
- display: none;
-}
-
-div#nav .separator {
-display: none;
-}
-
-
-div#nav a, div#page-navigation a{
- text-decoration: none;
- font-weight: normal;
- color: #000;
-}
-
-div#nav a:hover, div#page-navigation a:hover {
- text-decoration: underline;
-}
-
-
-
-div#nav a.selected, div#page-navigation a.selected {
-  font-weight: bold;
-}
-
-
-div#nav a.selected:after {
-/* content: " > " */
-}
-
-div#page-navigation {
- background: white;
- position: relative;
- width:100%;
- z-index: 10;
-
-}
-
-
-div#page-navigation ul#page-menu {
- display: block;
- position: absolute;
- left: 8em;
- font-size: 0.9em;
- top: 2.3em;
- background-color: white;
- right: 0em;
- padding-top:0.3em;
- padding-bottom:0.5em;
- border-top: 1px solid #aaa;
- overflow: auto;
+#nav {
+    background: #fff;
 }
-
-/* ie hack */
-* html div#page-navigation ul#page-menu {
-    left: 6.5em;
-    top: 3.2em;
-    padding-left: 2em;
-    width: 88%;
+.sf-menu {
+    z-index: 9999;
+    width: 100%;
 }
 
-
-div#page-navigation ul#actions-menu {
- position: absolute;
- right: 0em;
- top: 5.6em;
- margin-top: 0em;
- padding: 0.25em;
- padding-left: 0.5em;
- padding-right: 0.5em;
-
- background: #dedede;
- border-left: 1px solid #aaa;
- border-bottom: 2px solid #aaa;
- -moz-border-radius-bottomleft: 0.5em;
- -webkit-border-bottom-left-radius: 0.5em;
- -moz-border-radius-topright: 0.25em;
- -webkit-border-top-right-radius: 0.25em;
-
-
-
+.sf-menu a {
+    padding-top: 0.5em;
+    padding-bottom: 0.5em;
 }
-
-
-
-div#page-navigation ul li{
- display: inline;
-
+.sf-menu li:hover {
+    background-color: #fff;
 }
 
-
-ul.page-navigation ul.page-menu {
- float: right;
+.sf-menu li, .sf-menu li li, .sf-menu li li li {
+    background-color: #ccc;
 }
-
diff --git a/share/html/NoAuth/js/superfish.js b/share/html/NoAuth/js/superfish.js
new file mode 100644
index 0000000..2d74318
--- /dev/null
+++ b/share/html/NoAuth/js/superfish.js
@@ -0,0 +1,121 @@
+
+/*
+ * Superfish v1.4.8 - jQuery menu widget
+ * Copyright (c) 2008 Joel Birch
+ *
+ * Dual licensed under the MIT and GPL licenses:
+ * 	http://www.opensource.org/licenses/mit-license.php
+ * 	http://www.gnu.org/licenses/gpl.html
+ *
+ * CHANGELOG: http://users.tpg.com.au/j_birch/plugins/superfish/changelog.txt
+ */
+
+;(function($){
+	$.fn.superfish = function(op){
+
+		var sf = $.fn.superfish,
+			c = sf.c,
+			$arrow = $(['<span class="',c.arrowClass,'"> &#187;</span>'].join('')),
+			over = function(){
+				var $$ = $(this), menu = getMenu($$);
+				clearTimeout(menu.sfTimer);
+				$$.showSuperfishUl().siblings().hideSuperfishUl();
+			},
+			out = function(){
+				var $$ = $(this), menu = getMenu($$), o = sf.op;
+				clearTimeout(menu.sfTimer);
+				menu.sfTimer=setTimeout(function(){
+					o.retainPath=($.inArray($$[0],o.$path)>-1);
+					$$.hideSuperfishUl();
+					if (o.$path.length && $$.parents(['li.',o.hoverClass].join('')).length<1){over.call(o.$path);}
+				},o.delay);
+			},
+			getMenu = function($menu){
+				var menu = $menu.parents(['ul.',c.menuClass,':first'].join(''))[0];
+				sf.op = sf.o[menu.serial];
+				return menu;
+			},
+			addArrow = function($a){ $a.addClass(c.anchorClass).append($arrow.clone()); };
+
+		return this.each(function() {
+			var s = this.serial = sf.o.length;
+			var o = $.extend({},sf.defaults,op);
+			o.$path = $('li.'+o.pathClass,this).slice(0,o.pathLevels).each(function(){
+				$(this).addClass([o.hoverClass,c.bcClass].join(' '))
+					.filter('li:has(ul)').removeClass(o.pathClass);
+			});
+			sf.o[s] = sf.op = o;
+
+			$('li:has(ul)',this)[($.fn.hoverIntent && !o.disableHI) ? 'hoverIntent' : 'hover'](over,out).each(function() {
+				if (o.autoArrows) addArrow( $('>a:first-child',this) );
+			})
+			.not('.'+c.bcClass)
+				.hideSuperfishUl();
+
+			var $a = $('a',this);
+			$a.each(function(i){
+				var $li = $a.eq(i).parents('li');
+				$a.eq(i).focus(function(){over.call($li);}).blur(function(){out.call($li);});
+			});
+			o.onInit.call(this);
+
+		}).each(function() {
+			var menuClasses = [c.menuClass];
+			if (sf.op.dropShadows  && !($.browser.msie && $.browser.version < 7)) menuClasses.push(c.shadowClass);
+			$(this).addClass(menuClasses.join(' '));
+		});
+	};
+
+	var sf = $.fn.superfish;
+	sf.o = [];
+	sf.op = {};
+	sf.IE7fix = function(){
+		var o = sf.op;
+		if ($.browser.msie && $.browser.version > 6 && o.dropShadows && o.animation.opacity!=undefined)
+			this.toggleClass(sf.c.shadowClass+'-off');
+		};
+	sf.c = {
+		bcClass     : 'sf-breadcrumb',
+		menuClass   : 'sf-js-enabled',
+		anchorClass : 'sf-with-ul',
+		arrowClass  : 'sf-sub-indicator',
+		shadowClass : 'sf-shadow'
+	};
+	sf.defaults = {
+		hoverClass	: 'sfHover',
+		pathClass	: 'overideThisToUse',
+		pathLevels	: 1,
+		delay		: 800,
+		animation	: {opacity:'show'},
+		speed		: 'normal',
+		autoArrows	: true,
+		dropShadows : true,
+		disableHI	: false,		// true disables hoverIntent detection
+		onInit		: function(){}, // callback functions
+		onBeforeShow: function(){},
+		onShow		: function(){},
+		onHide		: function(){}
+	};
+	$.fn.extend({
+		hideSuperfishUl : function(){
+			var o = sf.op,
+				not = (o.retainPath===true) ? o.$path : '';
+			o.retainPath = false;
+			var $ul = $(['li.',o.hoverClass].join(''),this).add(this).not(not).removeClass(o.hoverClass)
+					.find('>ul').hide().css('visibility','hidden');
+			o.onHide.call($ul);
+			return this;
+		},
+		showSuperfishUl : function(){
+			var o = sf.op,
+				sh = sf.c.shadowClass+'-off',
+				$ul = this.addClass(o.hoverClass)
+					.find('>ul:hidden').css('visibility','visible');
+			sf.IE7fix.call($ul);
+			o.onBeforeShow.call($ul);
+			$ul.animate(o.animation,o.speed,function(){ sf.IE7fix.call($ul); o.onShow.call($ul); });
+			return this;
+		}
+	});
+
+})(jQuery);
diff --git a/share/html/NoAuth/js/supersubs.js b/share/html/NoAuth/js/supersubs.js
new file mode 100644
index 0000000..a6fce65
--- /dev/null
+++ b/share/html/NoAuth/js/supersubs.js
@@ -0,0 +1,90 @@
+
+/*
+ * Supersubs v0.2b - jQuery plugin
+ * Copyright (c) 2008 Joel Birch
+ *
+ * Dual licensed under the MIT and GPL licenses:
+ * 	http://www.opensource.org/licenses/mit-license.php
+ * 	http://www.gnu.org/licenses/gpl.html
+ *
+ *
+ * This plugin automatically adjusts submenu widths of suckerfish-style menus to that of
+ * their longest list item children. If you use this, please expect bugs and report them
+ * to the jQuery Google Group with the word 'Superfish' in the subject line.
+ *
+ */
+
+;(function($){ // $ will refer to jQuery within this closure
+
+	$.fn.supersubs = function(options){
+		var opts = $.extend({}, $.fn.supersubs.defaults, options);
+		// return original object to support chaining
+		return this.each(function() {
+			// cache selections
+			var $$ = $(this);
+			// support metadata
+			var o = $.meta ? $.extend({}, opts, $$.data()) : opts;
+			// get the font size of menu.
+			// .css('fontSize') returns various results cross-browser, so measure an em dash instead
+			var fontsize = $('<li id="menu-fontsize">&#8212;</li>').css({
+				'padding' : 0,
+				'position' : 'absolute',
+				'top' : '-999em',
+				'width' : 'auto'
+			}).appendTo($$).width(); //clientWidth is faster, but was incorrect here
+			// remove em dash
+			$('#menu-fontsize').remove();
+			// cache all ul elements
+			$ULs = $$.find('ul');
+			// loop through each ul in menu
+			$ULs.each(function(i) {
+				// cache this ul
+				var $ul = $ULs.eq(i);
+				// get all (li) children of this ul
+				var $LIs = $ul.children();
+				// get all anchor grand-children
+				var $As = $LIs.children('a');
+				// force content to one line and save current float property
+				var liFloat = $LIs.css('white-space','nowrap').css('float');
+				// remove width restrictions and floats so elements remain vertically stacked
+				var emWidth = $ul.add($LIs).add($As).css({
+					'float' : 'none',
+					'width'	: 'auto'
+				})
+				// this ul will now be shrink-wrapped to longest li due to position:absolute
+				// so save its width as ems. Clientwidth is 2 times faster than .width() - thanks Dan Switzer
+				.end().end()[0].clientWidth / fontsize;
+				// add more width to ensure lines don't turn over at certain sizes in various browsers
+				emWidth += o.extraWidth;
+				// restrict to at least minWidth and at most maxWidth
+				if (emWidth > o.maxWidth)		{ emWidth = o.maxWidth; }
+				else if (emWidth < o.minWidth)	{ emWidth = o.minWidth; }
+				emWidth += 'em';
+				// set ul to width in ems
+				$ul.css('width',emWidth);
+				// restore li floats to avoid IE bugs
+				// set li width to full width of this ul
+				// revert white-space to normal
+				$LIs.css({
+					'float' : liFloat,
+					'width' : '100%',
+					'white-space' : 'normal'
+				})
+				// update offset position of descendant ul to reflect new width of parent
+				.each(function(){
+					var $childUl = $('>ul',this);
+					var offsetDirection = $childUl.css('left')!==undefined ? 'left' : 'right';
+					$childUl.css(offsetDirection,emWidth);
+				});
+			});
+
+		});
+	};
+	// expose defaults
+	$.fn.supersubs.defaults = {
+		minWidth		: 9,		// requires em unit.
+		maxWidth		: 25,		// requires em unit.
+		extraWidth		: 0			// extra width can ensure lines don't sometimes turn over due to slight browser differences in how they round-off values
+	};
+
+})(jQuery); // plugin code ends

commit 346f48f78058d216eb36c3b23cb35b0bd44219fc
Author: Jesse Vincent <jesse at bestpractical.com>
Date:   Mon Oct 18 12:28:22 2010 +0900

    dashboard nav cleanup

diff --git a/share/html/Dashboards/Subscription.html b/share/html/Dashboards/Subscription.html
index c4eb1d3..dc17cd7 100644
--- a/share/html/Dashboards/Subscription.html
+++ b/share/html/Dashboards/Subscription.html
@@ -47,14 +47,13 @@
 %# END BPS TAGGED BLOCK }}}
 <& /Elements/Header, Title => $title &>
 <& /Dashboards/Elements/Tabs,
-    current_subtab => $current_subtab,
     Title => $title,
     DashboardObj => $DashboardObj &>
 
 <& /Elements/ListActions, actions => \@results &>
 
 <form action="<%RT->Config->Get('WebPath')%>/Dashboards/Subscription.html" method="post" enctype="multipart/form-data" name="SubscribeDashboard">
-<input type="hidden" class="hidden" name="DashboardId" value="<% $fields{'DashboardId'} %>" />
+<input type="hidden" class="hidden" name="Id" value="<% $fields{'Id'} %>" />
 <table width="100%" border="0">
 <tr>
 
@@ -183,8 +182,6 @@
 
 <%INIT>
 
-my $current_subtab = 'Dashboards/Subscription.html?DashboardId=' . $DashboardId;
-
 my ($title, @results);
 my ($val, $msg);
 my $Loaded = 0;
@@ -197,20 +194,20 @@ my $SubscriptionObj = RT::Attribute->new($session{'CurrentUser'});
 
 # first let's see if we already have a subscription to this DashboardId
 for my $sub ($session{'CurrentUser'}->UserObj->Attributes->Named('Subscription')) {
-    next unless $sub->SubValue('DashboardId') == $DashboardId;
+    next unless $sub->SubValue('DashboardId') == $id;
     $SubscriptionObj = $sub;
     last;
 }
 
-$DashboardId = $SubscriptionObj->Id
+$id = $SubscriptionObj->Id
              ? $SubscriptionObj->SubValue('DashboardId')
-             : $ARGS{'DashboardId'};
+             : $ARGS{'id'};
 
-($val, $msg) = $DashboardObj->LoadById($DashboardId);
-$val || Abort(loc("Couldn't load dashboard [_1]: [_2].", $DashboardId, $msg));
+($val, $msg) = $DashboardObj->LoadById($id);
+$val || Abort(loc("Couldn't load dashboard [_1]: [_2].", $id, $msg));
 
 my %fields = (
-    DashboardId => $DashboardId,
+    DashboardId => $id,
     Frequency   => 'daily',
     Hour        => '06:00',
     Dow         => 'Monday',
@@ -238,9 +235,9 @@ for my $field (keys %fields) {
 if (defined $ARGS{Save}) {
     # update
     if ($SubscriptionObj->Id) {
-        $DashboardId = delete $fields{'DashboardId'}; # immutable
+        $id = delete $fields{'DashboardId'}; # immutable
         ($val, $msg) = $SubscriptionObj->SetSubValues(%fields);
-        $fields{'DashboardId'} = $DashboardId;
+        $fields{'DashboardId'} = $id;
 
         # not so good to spew base64-encoded data at the user :)
         if ($msg =~ /^Content changed from/) {
@@ -251,12 +248,12 @@ if (defined $ARGS{Save}) {
     }
     # create
     else {
-        Abort(loc("Unable to subscribe to dashboard [_1]: Permission denied", $DashboardId))
+        Abort(loc("Unable to subscribe to dashboard [_1]: Permission denied", $id))
             unless $DashboardObj->CurrentUserCanSubscribe;
 
         my ($val, $msg) = $SubscriptionObj->Create(
             Name        => 'Subscription',
-            Description => 'Subscription to dashboard ' . $DashboardId,
+            Description => 'Subscription to dashboard ' . $id,
             ContentType => 'storable',
             Object      => $session{'CurrentUser'}->UserObj,
             Content     => \%fields,
@@ -281,7 +278,7 @@ else {
 
 </%INIT>
 <%ARGS>
-$DashboardId => undef
+$id => undef
 $Frequency   => undef
 $Hour        => undef
 $Dow         => undef
diff --git a/share/html/Elements/Tabs b/share/html/Elements/Tabs
index 641c8d2..d10c1ec 100755
--- a/share/html/Elements/Tabs
+++ b/share/html/Elements/Tabs
@@ -59,7 +59,7 @@
 <a name="skipnav" id="skipnav" accesskey="8"></a>
 <%INIT>
 
-my $request_path = $HTML::Mason::Commands::m->request_comp->path;
+my $request_path = $HTML::Mason::Commands::r->uri;
 
 my $query_string = sub {
     my %args = @_;
@@ -94,8 +94,13 @@ if ( $request_path =~ qr{.*} ) {
     }
 
     my $tools = Menu->child( loc('Tools'), path => '/Tools/index.html' );
-    $tools->child( loc('Dashboards'), path => '/Dashboards/index.html' );
+    my $dashes = $tools->child( loc('Dashboards'), path => '/Dashboards/index.html' );
 
+    $dashes->child( loc('Select'), path => "/Dashboards/index.html" );
+    my $dashboard = RT::Dashboard->new( $session{CurrentUser} );
+    if ( $dashboard->_PrivacyObjects( create => 1 ) ) {
+        $dashes->child( loc('Create') => path => "/Dashboards/Modify.html?Create=1" );
+    }
     my $reports = $tools->child( loc('Reports'),
                                  path => '/Tools/Reports/index.html' );
     $reports->child( loc('Resolved by owner'),
@@ -208,32 +213,18 @@ if ( $request_path =~ qr{.*} ) {
 
 }
 
-if ( $request_path =~ qr'Dashboards/?' ) {
-    require RT::Dashboard;    # not a record class, so not autoloaded :/
-    PageMenu->child( loc('Select'), path => "/Dashboards/index.html" );
-    my $dashboard = RT::Dashboard->new( $session{CurrentUser} );
-    if ( $dashboard->_PrivacyObjects( create => 1 ) ) {
-        PageMenu->child(
-                loc('Create') => path => "/Dashboards/Modify.html?Create=1" );
-    }
-}
-
-if ( $request_path =~ qr'Dashboards/(\d*)?' ) {
+if ( $request_path =~ qr'Dashboards/(\d+)?' ) {
     if ( my $id = ( $1 || $m->request_args->{'id'} ) ) {
         my $obj = RT::Dashboard->new( $session{'CurrentUser'} );
         $obj->LoadById($id);
         if ( $obj and $obj->id ) {
-            my $tabs = PageMenu->child(
-                              "this" => title => $obj->Name,
-                              path => "/Dashboards/Modify.html?id=" . $obj->id
-            );
+            my $tabs = PageMenu;
             $tabs->child( loc('Basics'),
                           path => "/Dashboards/Modify.html?id=" . $obj->id );
-            $tabs->child( loc('Queries'),
+            $tabs->child( loc('Content'),
                           path => "/Dashboards/Queries.html?id=" . $obj->id );
             $tabs->child( loc('Subscription'),
-                         path => "/Dashboards/Subscription.html?dashboard_id="
-                             . $obj->id )
+                         path => "/Dashboards/Subscription.html?id=" . $obj->id )
                 if $obj->CurrentUserCanSubscribe;
             $tabs->child( loc('Show'),
                         path => "/Dashboards/" . $obj->id . "/" . $obj->Name )
@@ -415,7 +406,7 @@ if ( $request_path =~ qr'Admin/Rules' ) {
 
 if ( $request_path =~ qr'(?:Ticket|Search)/' ) {
     my $search = Menu()->child('search');
-    my $actions = PageMenu()->child( transitions => title => lc('Actions') );
+    my $actions = PageMenu()->child( transitions => title => loc('Actions'), sort_order => 99 );
     if ( ( $m->request_args->{'id'} || '' ) =~ /^(\d+)$/ ) {
         my $id  = $1;
         my $obj = RT::Ticket->new( $session{'CurrentUser'} );
@@ -598,23 +589,6 @@ if ( $request_path =~ qr'(?:Ticket|Search)/' ) {
     }
 }
 
-if ( $request_path =~ qr'User/Group' ) {
-    if ( my $id = $m->request_args->{'id'} ) {
-        my $obj = RT::User->new( $session{'CurrentUser'} );
-        $obj->Load($id);
-        my $group = PageMenu->child(
-                          path => "/User/Groups/Modify.html?id=" . $obj->id );
-        $group->child( loc('Basics'),
-                       path => "/User/Groups/Modify.html?id=" . $obj->id );
-        $group->child( loc('Members'),
-                       path => "/User/Groups/Members.html?id=" . $obj->id );
-
-    }
-    PageMenu( loc('Select') => path => "/User/Groups/index.html" );
-    PageMenu( loc('Create') => path => "/User/Groups/Modify.html?Create=1",
-              separator     => 1 );
-
-}
 
 if ( $request_path =~ qr'Prefs' ) {
 
diff --git a/share/html/NoAuth/css/web2/nav.css b/share/html/NoAuth/css/web2/nav.css
index f4cc392..345d96a 100644
--- a/share/html/NoAuth/css/web2/nav.css
+++ b/share/html/NoAuth/css/web2/nav.css
@@ -48,6 +48,14 @@
 #nav {
     background: #fff;
 }
+
+#page-navigation {
+    position: absolute;
+    top: 7.8em;
+    right: 0em;
+    left: auto;
+    z-index: 9999;
+}
 .sf-menu {
     z-index: 9999;
     width: 100%;

commit f6ed3212e799df5db91bfdb7489970ec6f3b2706
Author: Jesse Vincent <jesse at bestpractical.com>
Date:   Mon Oct 18 12:31:40 2010 +0900

    prefs nav rectification

diff --git a/share/html/Elements/Tabs b/share/html/Elements/Tabs
index d10c1ec..d83e2a4 100755
--- a/share/html/Elements/Tabs
+++ b/share/html/Elements/Tabs
@@ -75,6 +75,7 @@ $PREFS_NAV->child( loc('About me'), path => '/User/Prefs.html', );
 $PREFS_NAV->child( loc('Search options'),
                    path => '/Prefs/SearchOptions.html', );
 $PREFS_NAV->child( loc('RT at a glance'), path => '/Prefs/MyRT.html', );
+$PREFS_NAV->child( 'Quick search' => title => loc('Quick search'), path => '/Prefs/Quicksearch.html' );
 
 if ( $request_path =~ qr{.*} ) {
     Menu->child( home => title =>  loc('HomePage'), path => '/' );
@@ -590,11 +591,7 @@ if ( $request_path =~ qr'(?:Ticket|Search)/' ) {
 }
 
 
-if ( $request_path =~ qr'Prefs' ) {
 
-    PageMenu->child( 'Quick search' => title => loc('Quick search'),
-                     path => '/Prefs/Quicksearch.html' );
-}
 
 
 </%INIT>

commit 160e43baa8c7adb26a28a1d090d7fcc4ff6e79d1
Author: Jesse Vincent <jesse at bestpractical.com>
Date:   Mon Oct 18 14:00:39 2010 +0900

    move menu to the upper right-hand corner

diff --git a/share/html/Elements/Logout b/share/html/Elements/Logout
index 3f5bca7..e69de29 100644
--- a/share/html/Elements/Logout
+++ b/share/html/Elements/Logout
@@ -1,65 +0,0 @@
-%# BEGIN BPS TAGGED BLOCK {{{
-%#
-%# COPYRIGHT:
-%#
-%# This software is Copyright (c) 1996-2010 Best Practical Solutions, LLC
-%#                                          <jesse 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 }}}
- | <a href="<% RT->Config->Get('WebPath') %>/NoAuth/Logout.html<% $URL ? "?URL=". $URL : '' %>"><&|/l&>Logout</&></a>
-<%ARGS>
-$URL => undef
-</%ARGS>
-<%INIT>
-my $show = 0;
-if ( $session{'CurrentUser'}->Name
-    && ( !RT->Config->Get('WebExternalAuth')
-        || RT->Config->Get('WebFallbackToInternalAuth')
-    )
-) {
-    $show = 1;
-}
-
-$m->callback( %ARGS, URL => \$URL, show => \$show );
-
-return unless $show;
-</%INIT>
diff --git a/share/html/Elements/PageLayout b/share/html/Elements/PageLayout
index 3dd8a56..58f9b04 100755
--- a/share/html/Elements/PageLayout
+++ b/share/html/Elements/PageLayout
@@ -55,7 +55,7 @@
 </div>
 
 % if ( $show_menu ) {
-<div id="nav"><& /Elements/Menu, menu => Menu(), id => 'app-nav' &></div>
+<div id="main-navigation"><& /Elements/Menu, menu => Menu(), id => 'app-nav' &></div>
 
 <div id="page-navigation"><& /Elements/Menu, menu => PageMenu(), id => 'page-menu' &></div>
 % }
diff --git a/share/html/Elements/PersonalQuickbar b/share/html/Elements/PersonalQuickbar
index 6e4aecd..0c6893e 100644
--- a/share/html/Elements/PersonalQuickbar
+++ b/share/html/Elements/PersonalQuickbar
@@ -51,10 +51,8 @@ $Prefs => '/Prefs/Other.html'
 <div id="quick-personal">
     <span class="hide"><a href="#skipnav"><&|/l&>Skip Menu</&></a> | </span>
 % if ($session{'CurrentUser'}->Name) {
-    <&|/l, "<span>".$session{'CurrentUser'}->Name."</span>" &>Logged in as [_1]</&>
 % } else {
     <&|/l&>Not logged in.</&>
 % }
 % $m->callback( %ARGS );
-<& Logout, %ARGS &>
 </div>
diff --git a/share/html/Elements/Tabs b/share/html/Elements/Tabs
index d83e2a4..250a6c9 100755
--- a/share/html/Elements/Tabs
+++ b/share/html/Elements/Tabs
@@ -68,15 +68,6 @@ my $query_string = sub {
     return $u->query;
 };
 
-my $PREFS_NAV = RT::Interface::Web::Menu->new(
-               { title => loc('Preferences'), path => '/Prefs/Other.html' } );
-$PREFS_NAV->child( loc('Settings'), path => '/Prefs/Other.html', );
-$PREFS_NAV->child( loc('About me'), path => '/User/Prefs.html', );
-$PREFS_NAV->child( loc('Search options'),
-                   path => '/Prefs/SearchOptions.html', );
-$PREFS_NAV->child( loc('RT at a glance'), path => '/Prefs/MyRT.html', );
-$PREFS_NAV->child( 'Quick search' => title => loc('Quick search'), path => '/Prefs/Quicksearch.html' );
-
 if ( $request_path =~ qr{.*} ) {
     Menu->child( home => title =>  loc('HomePage'), path => '/' );
     my $tickets = Menu->child( search => title => loc('Tickets'),
@@ -198,22 +189,29 @@ if ( $request_path =~ qr{.*} ) {
         $admin_tools->child( loc('Shredder'),
                              path => '/Admin/Tools/Shredder', );
     }
+    my $about_me =  Menu->child( 'preferences' => title => loc("Logged in as [_1]", $session{'CurrentUser'}->Name), sort_rder => 99 );
     if ( $session{'CurrentUser'}->UserObj
          && $session{'CurrentUser'}->HasRight( Right  => 'ModifySelf',
                                                Object => $RT::System )
        )
     {
+$about_me->child( loc('Settings'), path => '/Prefs/Other.html', );
+$about_me->child( loc('About me'), path => '/User/Prefs.html', );
+$about_me->child( loc('Search options'),
+                   path => '/Prefs/SearchOptions.html', );
+$about_me->child( loc('RT at a glance'), path => '/Prefs/MyRT.html', );
+$about_me->child( 'Quick search' => title => loc('Quick search'), path => '/Prefs/Quicksearch.html' );
 
-        if ( $session{'CurrentUser'}
-             ->HasRight( Right => 'ModifySelf', Object => $RT::System ) )
-        {
 
-            Menu->child( 'Preferences' => menu => $PREFS_NAV, Order => 99 );
-        }
+if ( $session{'CurrentUser'}->Name
+    && ( !RT->Config->Get('WebExternalAuth')
+        || RT->Config->Get('WebFallbackToInternalAuth')
+    )
+) {
+  $about_me->child(logout => title => loc('Logout'),  path =>'NoAuth/Logout.html');
     }
-
 }
-
+}
 if ( $request_path =~ qr'Dashboards/(\d+)?' ) {
     if ( my $id = ( $1 || $m->request_args->{'id'} ) ) {
         my $obj = RT::Dashboard->new( $session{'CurrentUser'} );
diff --git a/share/html/NoAuth/css/web2/layout.css b/share/html/NoAuth/css/web2/layout.css
index 75a7b32..511418e 100644
--- a/share/html/NoAuth/css/web2/layout.css
+++ b/share/html/NoAuth/css/web2/layout.css
@@ -69,7 +69,7 @@ div#body {
     -moz-border-radius-bottomleft: 0.5em;
     -webkit-border-bottom-left-radius: 0.5em;
     margin-left: 1em;
-    margin-top: 5.6em;
+    margin-top: 3em;
     margin-right: 0;
     margin-bottom: 0em;
     min-height: 10%;
@@ -219,7 +219,7 @@ div#header h1 {
  position: absolute;
  left: 0.5em;
  right: 20em;
- top: 3em;
+ top: 1.6em;
  overflow: hidden;
  height: 1em;
  font-size: 1.4em;
diff --git a/share/html/NoAuth/css/web2/nav.css b/share/html/NoAuth/css/web2/nav.css
index 345d96a..652a38e 100644
--- a/share/html/NoAuth/css/web2/nav.css
+++ b/share/html/NoAuth/css/web2/nav.css
@@ -45,19 +45,22 @@
 %# those contributions and any derivatives thereof.
 %#
 %# END BPS TAGGED BLOCK }}}
-#nav {
-    background: #fff;
+#main-navigation {
+    position: absolute;
+    top: 0;
+    right: 0;
+    left: auto;
+    z-index: 9999;
 }
 
 #page-navigation {
     position: absolute;
-    top: 7.8em;
+    top: 5.5em;
     right: 0em;
     left: auto;
-    z-index: 9999;
+    z-index: 9995;
 }
 .sf-menu {
-    z-index: 9999;
     width: 100%;
 }
 
@@ -70,5 +73,5 @@
 }
 
 .sf-menu li, .sf-menu li li, .sf-menu li li li {
-    background-color: #ccc;
+    background-color: #eee;
 }

commit de13bc8ca841b0d1d6a4769d34bc411ccc0f17fa
Author: Jesse Vincent <jesse at bestpractical.com>
Date:   Wed Oct 20 17:57:40 2010 +0900

    Continued updates to admin ui

diff --git a/lib/RT/Interface/Web/Menu.pm b/lib/RT/Interface/Web/Menu.pm
index 10907b3..f996358 100644
--- a/lib/RT/Interface/Web/Menu.pm
+++ b/lib/RT/Interface/Web/Menu.pm
@@ -58,7 +58,7 @@ use Scalar::Util qw(weaken);
 
 __PACKAGE__->mk_accessors(qw(
     title sort_order link target escape_title class render_children_inline
-    raw_html
+    raw_html key
 ));
 
 =head1 NAME
@@ -222,6 +222,7 @@ sub child {
         } else {
             $child = $proto->new(
                 {   parent     => $self,
+                    key         => $key,
                     title        => $key,
                     escape_title => 1,
                     %args
diff --git a/share/html/Admin/Queues/CustomFields.html b/share/html/Admin/Queues/CustomFields.html
index addce57..dc4ceb8 100755
--- a/share/html/Admin/Queues/CustomFields.html
+++ b/share/html/Admin/Queues/CustomFields.html
@@ -48,8 +48,6 @@
 <& /Admin/Elements/Header, Title => $title &>
 <&    /Admin/Elements/QueueTabs,
     id => $Object->id, 
-    current_tab => "Admin/Queues/CustomFields.html?SubType=$SubType&id=$id", 
-    current_subtab => "Admin/Queues/CustomFields.html?SubType=$SubType&id=$id", 
     QueueObj => $Object,
     Title => $title
     &>
@@ -63,7 +61,7 @@ my $FriendlySubTypes =
   RT::CustomField->new( $session{'CurrentUser'} )
   ->FriendlyLookupType( $Object->CustomFieldLookupType );
 
-my $title = loc( 'Edit Custom Fields for [_1]', $Object->Name );
+my $title = loc( 'Custom Fields for queue [_1]', $Object->Name );
 
 </%INIT>
 <%ARGS>
diff --git a/share/html/Admin/Queues/Modify.html b/share/html/Admin/Queues/Modify.html
index d784adb..3916508 100755
--- a/share/html/Admin/Queues/Modify.html
+++ b/share/html/Admin/Queues/Modify.html
@@ -158,7 +158,7 @@ if ($Create) {
     else {
         $QueueObj->Load($id) || $QueueObj->Load($Name) || Abort(loc("Couldn't load queue '[_1]'", $Name));
     }
-    $title = loc('Editing Configuration for queue [_1]', $QueueObj->Name);
+    $title = loc('Configuration for queue [_1]', $QueueObj->Name);
     
     $current_tab = 'Admin/Queues/Modify.html?id='.$QueueObj->id;
 }
diff --git a/share/html/Admin/Queues/People.html b/share/html/Admin/Queues/People.html
index 4dfeb77..7091d13 100755
--- a/share/html/Admin/Queues/People.html
+++ b/share/html/Admin/Queues/People.html
@@ -45,11 +45,11 @@
 %# those contributions and any derivatives thereof.
 %#
 %# END BPS TAGGED BLOCK }}}
-<& /Elements/Header, Title => loc('Modify people related to queue [_1]', $QueueObj->Name) &>
+<& /Elements/Header, Title => $title &>
+
 <& /Admin/Elements/QueueTabs, id => $id, 
     QueueObj => $QueueObj,                                                      
-    current_tab => $current_tab, 
-    Title => loc('Modify people related to queue [_1]', $QueueObj->Name) &>
+    Title => $title &>
 
 <& /Elements/ListActions, actions => \@results &>
 
@@ -131,13 +131,6 @@
 my $current_tab;
 my ($field, @results, $User, $Users, $Groups, $watcher, $user_msg, $group_msg);
 
-# Load the queue
-#If we get handed two ids, mason will make them an array. bleck.
-# We want teh first one. Just because there's no other sensible way
-# to deal
-
-
-
 my $QueueObj = RT::Queue->new($session{'CurrentUser'});
 $QueueObj->Load($id) || Abort(loc("Couldn't load queue", $id));
 
@@ -163,7 +156,6 @@ unless ($OnlySearchForPeople or $OnlySearchForGroup) {
 
         next unless RT::Queue->IsManageableRoleGroupType($type);
 
-        $RT::Logger->debug("Adding a watcher $id to $type\n");
         my ($code, $msg) = $QueueObj->AddWatcher(
             Type => $type,
             PrincipalId => $id,
@@ -196,7 +188,7 @@ if ( $ARGS{'GroupString'} ) {
 } else {
     $group_msg = loc("No principals selected.");
 }
-$current_tab = 'Admin/Queues/People.html?id=' . $QueueObj->id;
+my $title = loc('People related to queue [_1]', $QueueObj->Name);
 </%INIT>
 
 <%ARGS>
diff --git a/share/html/Admin/Queues/Template.html b/share/html/Admin/Queues/Template.html
index c109e93..d3295b9 100755
--- a/share/html/Admin/Queues/Template.html
+++ b/share/html/Admin/Queues/Template.html
@@ -48,9 +48,6 @@
 <& /Admin/Elements/Header, Title => $title &>
 <& /Admin/Elements/QueueTabs, id => $Queue, 
     QueueObj => $QueueObj,
-     current_tab => 'Admin/Queues/Templates.html?id='.$Queue,
-     current_subtab => $current_subtab, 
-     subtabs => $subtabs, 
      Title => $title &>
 <& /Elements/ListActions, actions => \@results &>
 
@@ -75,59 +72,49 @@
 
 <%INIT>
 
-my $TemplateObj = RT::Template->new($session{'CurrentUser'});
-my  ($title, @results, $current_subtab, $SubmitLabel);
+my $TemplateObj = RT::Template->new( $session{'CurrentUser'} );
+my $QueueObj;
+my $SubmitLabel;
+my $title;
+my @results;
 
-my $subtabs = {
-		 A => { title => loc('Select template'),
-  		     	path => "Admin/Queues/Templates.html?id=$Queue"
-			   },
-		 B => { title => loc('New template'),
-  		     	path => "Admin/Queues/Template.html?Create=1&Queue=$Queue",
-			separator => 1,
-			   }
-	      };
+if ( !$Create ) {
+    if ( $Template eq 'new' ) {
+        my ( $val, $msg )
+            = $TemplateObj->Create( Queue => $Queue, Name => $Name );
+        Abort( loc( "Could not create template: [_1]", $msg ) ) unless ($val);
+        push @results, $msg;
+    } else {
+        $TemplateObj->Load($Template) || Abort( loc('No Template') );
+    }
 
-if ($Create) {
-  $title = loc("Create a template");
-  $current_subtab = "Admin/Queues/Template.html?Create=1&Queue=".$Queue;
-  $SubmitLabel = loc('Create');
 }
 
-else {
-  if ($Template eq 'new') {
-      my ($val, $msg) =  $TemplateObj->Create(Queue => $Queue, Name => $Name);
-      Abort(loc("Could not create template: [_1]", $msg)) unless ($val);
-     push @results, $msg;
-    }
-    else {
-       $TemplateObj->Load($Template) || Abort(loc('No Template'));
-    }
-     $title = loc('Modify template [_1]', loc($TemplateObj->Name())); 
-     $SubmitLabel = loc('Save Changes');
-  
-    
-}
-my $QueueObj;
-if ($TemplateObj->Id()) {
-  $Queue = $TemplateObj->Queue;
-  $QueueObj = $TemplateObj->QueueObj;
+if ( $TemplateObj->Id() ) {
+    $Queue    = $TemplateObj->Queue;
+    $QueueObj = $TemplateObj->QueueObj;
+
+    my @attribs = qw( Description Content Queue Name Type );
+    my @aresults = UpdateRecordObject( AttributesRef => \@attribs,
+                                       Object        => $TemplateObj,
+                                       ARGSRef       => \%ARGS
+                                     );
+    push @results, @aresults;
 
-  my @attribs = qw( Description Content Queue Name Type );
-  my @aresults = UpdateRecordObject( AttributesRef => \@attribs, 
-				     Object => $TemplateObj, 
-				     ARGSRef => \%ARGS);
-  $current_subtab = "Admin/Queues/Template.html?Queue=$Queue&Template=".$TemplateObj->Id();
-  $subtabs->{"C"} = { title => loc('Template #[_1]', $TemplateObj->Id()),
-  		     	path => "Admin/Queues/Template.html?Queue=$Queue&Template=".$TemplateObj->Id(),
-			};
-  push @results, @aresults;
+    my ( $ok, $msg ) = $TemplateObj->CompileCheck;
+    push @results, $msg if !$ok;
+} else {
+    $QueueObj = RT::Queue->new( $session{'CurrentUser'} );
+    $QueueObj->Load($Queue);
+}
 
-  my ($ok, $msg) = $TemplateObj->CompileCheck;
-  push @results, $msg if !$ok;
+if ($Create) {
+    $title = loc( 'Create a new template for queue [_1]', $QueueObj->Name );
+    $SubmitLabel = loc('Create');
 } else {
-  $QueueObj = RT::Queue->new($session{'CurrentUser'});
-  $QueueObj->Load($Queue);
+
+    $title = loc( 'Modify template [_1] for queue [_2]', loc( $TemplateObj->Name()), $QueueObj->Name  );
+    $SubmitLabel = loc('Save Changes');
 }
 
 </%INIT>
diff --git a/share/html/Admin/Queues/Templates.html b/share/html/Admin/Queues/Templates.html
index 86091e8..8d84c48 100755
--- a/share/html/Admin/Queues/Templates.html
+++ b/share/html/Admin/Queues/Templates.html
@@ -47,10 +47,7 @@
 %# END BPS TAGGED BLOCK }}}
 <& /Admin/Elements/Header, Title => $title &>
 <& /Admin/Elements/QueueTabs, id => $QueueObj->id, 
-    current_tab => 'Admin/Queues/Templates.html?id='.$id, 
-    current_subtab => 'Admin/Queues/Templates.html?id='.$id, 
         QueueObj => $QueueObj,
-    subtabs => $subtabs, 
     Title => $title &>
 
 <& /Admin/Elements/EditTemplates, title => $title, %ARGS &>
@@ -59,21 +56,10 @@
 my $QueueObj = RT::Queue->new($session{'CurrentUser'});
 $QueueObj->Load($id);
 
-my ($title, $current_subtab);
-
-if ($QueueObj->id) {
-    $title = loc("Edit Templates for queue [_1]", $QueueObj->Name);
-} else {
+if (!$QueueObj->id) {
     Abort(loc("Queue [_1] not found",$id));
 }
-my $subtabs = {
-	 A => { title => loc('Select'),
-	     	path => "Admin/Queues/Templates.html?id=".$id,
-		   },
-	 B => { title => loc('Create'),
-	     	path => "Admin/Queues/Template.html?Create=1&Queue=".$id,
-		   }
-	      };
+my $title = loc("Templates for queue [_1]", $QueueObj->Name);
 
 </%INIT>
 <%ARGS>
diff --git a/share/html/Elements/Menu b/share/html/Elements/Menu
index d47abdb..dcaa673 100755
--- a/share/html/Elements/Menu
+++ b/share/html/Elements/Menu
@@ -45,11 +45,14 @@
 %# those contributions and any derivatives thereof.
 %#
 %# END BPS TAGGED BLOCK }}}
-<ul <%$id ? "id=\"$id\"" : '' |n%> <% $toplevel? 'class="sf-menu sf-js-enabled sf-shadow' : '' |n %>">
+<ul <%$id ? 'id="'.$id.'"' : '' |n%><% $toplevel? 'class="sf-menu sf-js-enabled sf-shadow"' : '' |n %>>
 % for my $child ($menu->children) {
-<li><a href="<%RT->Config->Get('WebPath')%><%$child->path%>"><%$child->title%></a>
+<li>
+<a id="<%$parent_id%>-<%$child->key%>"  \
+<% $child->path ? 'href="'.RT->Config->Get('WebPath').$child->path.'"' : '' |n%> \
+><%$child->title%></a>
 % next unless ($child->has_children);
-<& Menu, menu => $child, toplevel => 0 &>
+<& Menu, menu => $child, toplevel => 0, parent_id => ($parent_id? $parent_id."-": '').$child->key &>
 </li>
 % }
 </ul>
@@ -59,4 +62,5 @@
 $menu
 $id => undef
 $toplevel => 1
+$parent_id => ''
 </%ARGS>
diff --git a/share/html/Elements/Tabs b/share/html/Elements/Tabs
index 250a6c9..3770277 100755
--- a/share/html/Elements/Tabs
+++ b/share/html/Elements/Tabs
@@ -114,22 +114,35 @@ if ( $request_path =~ qr{.*} ) {
     {
         my $admin = Menu->child( Config => title => loc('Configuration'),
                                  path   => '/Admin/' );
-        $admin->child( loc('Users'),  path => '/Admin/Users/', );
-        $admin->child( loc('Groups'), path => '/Admin/Groups/', );
-        my $queues = $admin->child( queues => title => loc('Queues'),
-                                    path => '/Admin/Queues/', );
+        my $users = $admin->child( loc('Users'),  path => '/Admin/Users/', );
+        $users->child( loc('Select'), path => "/Admin/Users/" );
+        $users->child( loc('Create'), path => "/Admin/Users/Modify.html?Create=1" );
+
+
+        my $groups = $admin->child( loc('Groups'), path => '/Admin/Groups/', );
+
+        $groups->child( loc('Select'), path => "/Admin/Groups/" );
+        $groups->child( loc('Create'), path => "/Admin/Groups/Modify.html?Create=1" );
+
+
+        my $queues = $admin->child( queues => title => loc('Queues'), path => '/Admin/Queues/', );
         $queues->child( loc('Select'), path => "/Admin/Queues/" );
-        $queues->child( loc('Create'),
-                        path => "/Admin/Queues/Modify.html?Create=1" );
-        $admin->child( loc('Custom Fields'), path => '/Admin/CustomFields/',
+        $queues->child( loc('Create'), path => "/Admin/Queues/Modify.html?Create=1" );
+        my $cfs = $admin->child( loc('Custom Fields'), path => '/Admin/CustomFields/',
         );
-        $admin->child( loc('Rules'), path => '/admin/rules/', );
+        $cfs->child( loc('Select'), path => "/Admin/CustomFields/" );
+        $cfs->child( loc('Create'), path => "/Admin/CustomFields/Modify.html?Create=1" );
 
         my $admin_global
             = $admin->child( loc('Global'), path => '/Admin/Global/', );
 
-        $admin_global->child( loc('Templates'),
+        my $scrips = $admin_global->child( loc('Scrips'), path => '/Admin/Global/Scripshtml', );
+        $scrips->child( loc('Select'), path => "/Admin/Global/Scrips.html" );
+        $scrips->child( loc('Create'), path => "/Admin/Global/Scrip.html?Create=1" );
+        my $templates = $admin_global->child( loc('Templates'),
                               path => '/Admin/Global/Templates.html', );
+        $templates->child( loc('Select'), path => "/Admin/Global/Templates.html" );
+        $templates->child( loc('Create'), path => "/Admin/Global/Template.html?Create=1" );
 
 #        my $workflows = $admin_global->child( loc('Workflows'), path => '/Admin/Global/Workflows/index.html', );
 #        {
@@ -270,25 +283,27 @@ if ( $request_path =~ qr'/SelfService' ) {
 }
 
 if ( $request_path =~ qr'Admin/Queues' ) {
-    if ( $session{'CurrentUser'}
-         ->HasRight( Object => $RT::System, Right => 'AdminQueue' ) )
+    if ( $session{'CurrentUser'}->HasRight( Object => $RT::System, Right => 'AdminQueue' ) )
     {
     }
-    if ( my $id = $m->request_args->{'id'} ) {
+    if ( my $id = $m->request_args->{'id'} ||$m->request_args->{'Queue'}) {
         my $queue_obj = RT::Queue->new( $session{'CurrentUser'} );
         $queue_obj->Load($id);
 
-        my $queue
-            = PageMenu->child(
-                   $queue_obj->Name => path => "/Admin/Queues/Modify.html?id="
-                       . $id );
-        $queue->child( loc('Basics'),
+        my $queue = PageMenu();
+        $queue->child( basics => title =>loc('Basics'),
                        path => "/Admin/Queues/Modify.html?id=" . $id );
-        $queue->child( loc('Watchers'),
+        $queue->child( people => title => loc('Watchers'),
                        path => "/Admin/Queues/People.html?id=" . $id );
-        $queue->child( loc('Templates'),
+        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 );
+
         $queue->child( loc('Ticket Custom Fields'),
              path => '/Admin/Queues/CustomFields.html?sub_type=RT::Ticket&id='
                  . $id );
@@ -309,10 +324,8 @@ if ( $request_path =~ qr'/Admin/Users' ) {
     if ( $session{'CurrentUser'}
          ->HasRight( Object => $RT::System, Right => 'AdminUsers' ) )
     {
-        PageMenu->child( loc('Select'), path => "/Admin/Users/" );
-        PageMenu->child( loc('Create'),
-                         path      => "/Admin/Users/Modify.html?Create=1",
-                         separator => 1
+        PageMenu->child(select => title => loc('Select'), path => "/Admin/Users/" );
+        PageMenu->child( create => title =>  loc('Create'), path      => "/Admin/Users/Modify.html?Create=1",
                        );
     }
     if ( my $id = $m->request_args->{'id'} ) {

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


More information about the Rt-commit mailing list