add a link to create new dashboards, #30905
[freeside.git] / rt / share / html / Elements / Tabs
index ef17f6f..f769a80 100755 (executable)
@@ -2,7 +2,7 @@
 %#
 %# COPYRIGHT:
 %#
-%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC
+%# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
 %#                                          <sales@bestpractical.com>
 %#
 %# (Except where explicitly superseded by other copyright notices)
 
 #my $request_path = $HTML::Mason::Commands::r->path_info;
 my $request_path = $m->request_comp->path;
+$request_path =~ s!/{2,}!/!g;
 
 my $query_string = sub {
     my %args = @_;
     my $u    = URI->new();
-    $u->query_form(%args);
+    $u->query_form(map { $_ => $args{$_} } sort keys %args);
     return $u->query;
 };
 
@@ -246,7 +247,7 @@ my $build_admin_menu = sub {
         my $section;
         if ( $request_path =~ m|^/Admin/$type/?(?:index.html)?$|
              || (    $request_path =~ m|^/Admin/$type/(?:Modify.html)$|
-                  && $m->request_args->{'Create'} )
+                  && $DECODED_ARGS->{'Create'} )
            )
         {
             $section = $tabs;
@@ -261,83 +262,91 @@ my $build_admin_menu = sub {
     }
 
     if ( $request_path =~ m{^/Admin/Queues} ) {
-        if ( $m->request_args->{'id'} && $m->request_args->{'id'} =~ /^\d+$/
+        if ( $DECODED_ARGS->{'id'} && $DECODED_ARGS->{'id'} =~ /^\d+$/
                 ||
-              $m->request_args->{'Queue'} && $m->request_args->{'Queue'} =~ /^\d+$/
+              $DECODED_ARGS->{'Queue'} && $DECODED_ARGS->{'Queue'} =~ /^\d+$/
                 ) {
-            my $id = $m->request_args->{'Queue'} || $m->request_args->{'id'};
+            my $id = $DECODED_ARGS->{'Queue'} || $DECODED_ARGS->{'id'};
             my $queue_obj = RT::Queue->new( $session{'CurrentUser'} );
             $queue_obj->Load($id);
 
-            my $queue = PageMenu();
-            $queue->child( basics => title => loc('Basics'),   path => "/Admin/Queues/Modify.html?id=" . $id );
-            $queue->child( people => title => loc('Watchers'), path => "/Admin/Queues/People.html?id=" . $id );
+            if ( $queue_obj and $queue_obj->id ) {
+                my $queue = PageMenu();
+                $queue->child( basics => title => loc('Basics'),   path => "/Admin/Queues/Modify.html?id=" . $id );
+                $queue->child( people => title => loc('Watchers'), path => "/Admin/Queues/People.html?id=" . $id );
 
-            my $templates = $queue->child(templates => title => loc('Templates'), path => "/Admin/Queues/Templates.html?id=" . $id);
-            $templates->child( select => title => loc('Select'), path => "/Admin/Queues/Templates.html?id=".$id);
-            $templates->child( create => title => loc('Create'), path => "/Admin/Queues/Template.html?Create=1;Queue=".$id);
+                my $templates = $queue->child(templates => title => loc('Templates'), path => "/Admin/Queues/Templates.html?id=" . $id);
+                $templates->child( select => title => loc('Select'), path => "/Admin/Queues/Templates.html?id=".$id);
+                $templates->child( create => title => loc('Create'), path => "/Admin/Queues/Template.html?Create=1;Queue=".$id);
 
-            my $scrips = $queue->child( scrips => title => loc('Scrips'), path => "/Admin/Queues/Scrips.html?id=" . $id);
-            $scrips->child( select => title => loc('Select'), path => "/Admin/Queues/Scrips.html?id=" . $id );
-            $scrips->child( create => title => loc('Create'), path => "/Admin/Queues/Scrip.html?Create=1;Queue=" . $id);
+                my $scrips = $queue->child( scrips => title => loc('Scrips'), path => "/Admin/Queues/Scrips.html?id=" . $id);
+                $scrips->child( select => title => loc('Select'), path => "/Admin/Queues/Scrips.html?id=" . $id );
+                $scrips->child( create => title => loc('Create'), path => "/Admin/Queues/Scrip.html?Create=1;Queue=" . $id);
 
-            my $ticket_cfs = $queue->child( 'ticket-custom-fields' => title => loc('Ticket Custom Fields'),
-                path => '/Admin/Queues/CustomFields.html?SubType=RT::Ticket&id=' . $id );
+                my $ticket_cfs = $queue->child( 'ticket-custom-fields' => title => loc('Ticket Custom Fields'),
+                    path => '/Admin/Queues/CustomFields.html?SubType=RT::Ticket&id=' . $id );
 
-            my $txn_cfs = $queue->child( 'transaction-custom-fields' => title => loc('Transaction Custom Fields'),
-                path => '/Admin/Queues/CustomFields.html?SubType=RT::Ticket-RT::Transaction&id='.$id );
+                my $txn_cfs = $queue->child( 'transaction-custom-fields' => title => loc('Transaction Custom Fields'),
+                    path => '/Admin/Queues/CustomFields.html?SubType=RT::Ticket-RT::Transaction&id='.$id );
 
-            $queue->child( 'group-rights' => title => loc('Group Rights'), path => "/Admin/Queues/GroupRights.html?id=".$id );
-            $queue->child( 'user-rights' => title => loc('User Rights'), path => "/Admin/Queues/UserRights.html?id=" . $id );
+                $queue->child( 'group-rights' => title => loc('Group Rights'), path => "/Admin/Queues/GroupRights.html?id=".$id );
+                $queue->child( 'user-rights' => title => loc('User Rights'), path => "/Admin/Queues/UserRights.html?id=" . $id );
+                $queue->child( 'history' => title => loc('History'), path => "/Admin/Queues/History.html?id=" . $id );
 
-
-            $m->callback( CallbackName => 'PrivilegedQueue', queue_id => $id, page_menu => $queue);
+                $m->callback( CallbackName => 'PrivilegedQueue', queue_id => $id, page_menu => $queue);
+            }
         }
     }
     if ( $request_path =~ m{^/Admin/Users} ) {
-        if ( $m->request_args->{'id'} && $m->request_args->{'id'} =~ /^\d+$/ ) {
-            my $id = $m->request_args->{'id'};
+        if ( $DECODED_ARGS->{'id'} && $DECODED_ARGS->{'id'} =~ /^\d+$/ ) {
+            my $id = $DECODED_ARGS->{'id'};
             my $obj = RT::User->new( $session{'CurrentUser'} );
             $obj->Load($id);
 
-            my $tabs = PageMenu();
-            $tabs->child( basics      => title => loc('Basics'),         path => "/Admin/Users/Modify.html?id=" . $id );
-            $tabs->child( memberships => title => loc('Memberships'),    path => "/Admin/Users/Memberships.html?id=" . $id );
-            $tabs->child( history     => title => loc('History'),        path => "/Admin/Users/History.html?id=" . $id );
-            $tabs->child( 'my-rt'     => title => loc('RT at a glance'), path => "/Admin/Users/MyRT.html?id=" . $id );
-            if ( RT->Config->Get('GnuPG')->{'Enable'} ) {
-                $tabs->child( pgp     => title => loc('GnuPG'),          path => "/Admin/Users/GnuPG.html?id=" . $id );
+            if ( $obj and $obj->id ) {
+                my $tabs = PageMenu();
+                $tabs->child( basics      => title => loc('Basics'),         path => "/Admin/Users/Modify.html?id=" . $id );
+                $tabs->child( memberships => title => loc('Memberships'),    path => "/Admin/Users/Memberships.html?id=" . $id );
+                $tabs->child( history     => title => loc('History'),        path => "/Admin/Users/History.html?id=" . $id );
+                $tabs->child( 'my-rt'     => title => loc('RT at a glance'), path => "/Admin/Users/MyRT.html?id=" . $id );
+                if ( RT->Config->Get('GnuPG')->{'Enable'} ) {
+                    $tabs->child( pgp     => title => loc('GnuPG'),          path => "/Admin/Users/GnuPG.html?id=" . $id );
+                }
             }
         }
 
     }
 
     if ( $request_path =~ m{^/Admin/Groups} ) {
-        if ( $m->request_args->{'id'} && $m->request_args->{'id'} =~ /^\d+$/ ) {
-            my $id = $m->request_args->{'id'};
+        if ( $DECODED_ARGS->{'id'} && $DECODED_ARGS->{'id'} =~ /^\d+$/ ) {
+            my $id = $DECODED_ARGS->{'id'};
             my $obj = RT::Group->new( $session{'CurrentUser'} );
             $obj->Load($id);
 
-            my $tabs = PageMenu();
-            $tabs->child( basics         => title => loc('Basics'),       path => "/Admin/Groups/Modify.html?id=" . $obj->id );
-            $tabs->child( members        => title => loc('Members'),      path => "/Admin/Groups/Members.html?id=" . $obj->id );
-            $tabs->child( 'group-rights' => title => loc('Group Rights'), path => "/Admin/Groups/GroupRights.html?id=" . $obj->id );
-            $tabs->child( 'user-rights'  => title => loc('User Rights'),  path => "/Admin/Groups/UserRights.html?id=" . $obj->id );
-            $tabs->child( history        => title => loc('History'),      path => "/Admin/Groups/History.html?id=" . $obj->id );
+            if ( $obj and $obj->id ) {            
+                my $tabs = PageMenu();
+                $tabs->child( basics         => title => loc('Basics'),       path => "/Admin/Groups/Modify.html?id=" . $obj->id );
+                $tabs->child( members        => title => loc('Members'),      path => "/Admin/Groups/Members.html?id=" . $obj->id );
+                $tabs->child( 'group-rights' => title => loc('Group Rights'), path => "/Admin/Groups/GroupRights.html?id=" . $obj->id );
+                $tabs->child( 'user-rights'  => title => loc('User Rights'),  path => "/Admin/Groups/UserRights.html?id=" . $obj->id );
+                $tabs->child( history        => title => loc('History'),      path => "/Admin/Groups/History.html?id=" . $obj->id );
+            }
         }
     }
 
     if ( $request_path =~ m{^/Admin/CustomFields/} ) {
-        if ( $m->request_args->{'id'} && $m->request_args->{'id'} =~ /^\d+$/ ) {
-            my $id = $m->request_args->{'id'};
+        if ( $DECODED_ARGS->{'id'} && $DECODED_ARGS->{'id'} =~ /^\d+$/ ) {
+            my $id = $DECODED_ARGS->{'id'};
             my $obj = RT::CustomField->new( $session{'CurrentUser'} );
             $obj->Load($id);
 
-            my $tabs = PageMenu();
-            $tabs->child( basics         => title => loc('Basics'),       path => "/Admin/CustomFields/Modify.html?id=".$id );
-            $tabs->child( 'group-rights' => title => loc('Group Rights'), path => "/Admin/CustomFields/GroupRights.html?id=" . $id );
-            $tabs->child( 'user-rights'  => title => loc('User Rights'),  path => "/Admin/CustomFields/UserRights.html?id=" . $id );
-            $tabs->child( 'applies-to'   => title => loc('Applies to'),   path => "/Admin/CustomFields/Objects.html?id=" . $id );
+            if ( $obj and $obj->id ) {
+                my $tabs = PageMenu();
+                $tabs->child( basics         => title => loc('Basics'),       path => "/Admin/CustomFields/Modify.html?id=".$id );
+                $tabs->child( 'group-rights' => title => loc('Group Rights'), path => "/Admin/CustomFields/GroupRights.html?id=" . $id );
+                $tabs->child( 'user-rights'  => title => loc('User Rights'),  path => "/Admin/CustomFields/UserRights.html?id=" . $id );
+                $tabs->child( 'applies-to'   => title => loc('Applies to'),   path => "/Admin/CustomFields/Objects.html?id=" . $id );
+            }
         }
     }
 
@@ -354,20 +363,22 @@ my $build_admin_menu = sub {
 
     if ( $request_path =~ m{^/Admin/Articles/Classes/} ) {
         my $tabs = PageMenu();
-        if ( my $id = $m->request_args->{'id'} ) {
-            my $obj = RT::CustomField->new( $session{'CurrentUser'} );
+        if ( my $id = $DECODED_ARGS->{'id'} ) {
+            my $obj = RT::Class->new( $session{'CurrentUser'} );
             $obj->Load($id);
 
-            my $section = $tabs->child( select => title => loc("Classes"), path => "/Admin/Articles/Classes/" );
-            $section->child( select => title => loc('Select'), path => "/Admin/Articles/Classes/" );
-            $section->child( create => title => loc('Create'), path => "/Admin/Articles/Classes/Modify.html?Create=1" );
-
-            $tabs->child( basics          => title => loc('Basics'),        path => "/Admin/Articles/Classes/Modify.html?id=".$id );
-            $tabs->child( topics          => title => loc('Topics'),        path => "/Admin/Articles/Classes/Topics.html?id=".$id );
-            $tabs->child( 'custom-fields' => title => loc('Custom Fields'), path => "/Admin/Articles/Classes/CustomFields.html?id=".$id );
-            $tabs->child( 'group-rights'  => title => loc('Group Rights'),  path => "/Admin/Articles/Classes/GroupRights.html?id=".$id );
-            $tabs->child( 'user-rights'   => title => loc('User Rights'),   path => "/Admin/Articles/Classes/UserRights.html?id=".$id );
-            $tabs->child( 'applies-to'    => title => loc('Applies to'),    path => "/Admin/Articles/Classes/Objects.html?id=$id" );
+            if ( $obj and $obj->id ) {
+                my $section = $tabs->child( select => title => loc("Classes"), path => "/Admin/Articles/Classes/" );
+                $section->child( select => title => loc('Select'), path => "/Admin/Articles/Classes/" );
+                $section->child( create => title => loc('Create'), path => "/Admin/Articles/Classes/Modify.html?Create=1" );
+
+                $tabs->child( basics          => title => loc('Basics'),        path => "/Admin/Articles/Classes/Modify.html?id=".$id );
+                $tabs->child( topics          => title => loc('Topics'),        path => "/Admin/Articles/Classes/Topics.html?id=".$id );
+                $tabs->child( 'custom-fields' => title => loc('Custom Fields'), path => "/Admin/Articles/Classes/CustomFields.html?id=".$id );
+                $tabs->child( 'group-rights'  => title => loc('Group Rights'),  path => "/Admin/Articles/Classes/GroupRights.html?id=".$id );
+                $tabs->child( 'user-rights'   => title => loc('User Rights'),   path => "/Admin/Articles/Classes/UserRights.html?id=".$id );
+                $tabs->child( 'applies-to'    => title => loc('Applies to'),    path => "/Admin/Articles/Classes/Objects.html?id=$id" );
+            }
         } else {
             $tabs->child( select => title => loc('Select'), path => "/Admin/Articles/Classes/" );
             $tabs->child( create => title => loc('Create'), path => "/Admin/Articles/Classes/Modify.html?Create=1" );
@@ -378,6 +389,9 @@ my $build_admin_menu = sub {
 
 my $build_main_nav = sub {
 
+    PageWidgets()->child( simple_search => raw_html => $m->scomp('SimpleSearch') );
+    PageWidgets()->child( create_ticket => raw_html => $m->scomp('CreateTicket') );
+
     my $home = Menu->child( home => title => loc('Homepage'), path => '/' );
     # We explicitly exclude superusers; otherwise the dashboards for
     # groups you're not in (but can see the dashboards of by dint of
@@ -478,9 +492,9 @@ my $build_main_nav = sub {
 
         for my $search (@$searches) {
             $search_menu->child( "search-" . $i++ =>
-                title => $search->[0],
+                title => $search->[1],
                 path  => "/Prefs/Search.html?"
-                       . $query_string->( name => ref( $search->[1] ) . '-' . $search->[1]->Id ),
+                       . $query_string->( name => ref( $search->[2] ) . '-' . $search->[2]->Id ),
             );
 
         }
@@ -491,7 +505,7 @@ my $build_main_nav = sub {
         $about_me->child( logout => title => loc('Logout'), path => '/NoAuth/Logout.html' );
     }
     if ( $request_path =~ m{^/Dashboards/(\d+)?}) {
-        if ( my $id = ( $1 || $m->request_args->{'id'} ) ) {
+        if ( my $id = ( $1 || $DECODED_ARGS->{'id'} ) ) {
             my $obj = RT::Dashboard->new( $session{'CurrentUser'} );
             $obj->LoadById($id);
             if ( $obj and $obj->id ) {
@@ -502,151 +516,160 @@ my $build_main_nav = sub {
                     if $obj->CurrentUserCanSubscribe;
                 $tabs->child( show         => title => loc('Show'),         path => "/Dashboards/" . $obj->id . "/" . $obj->Name)
             }
+        } else {
+            my $tabs = PageMenu();
+            if ( $dashboard->CurrentUserCanCreateAny ) {
+                # FREESIDE: provide a way to create dashboards
+                $tabs->child('dashboard_create' => title => loc('New Dashboard'), path => "/Dashboards/Modify.html?Create=1");
+            }
         }
     }
 
-
     if ( $request_path =~ m{^/Ticket/} ) {
-        if ( ( $m->request_args->{'id'} || '' ) =~ /^(\d+)$/ ) {
+        if ( ( $DECODED_ARGS->{'id'} || '' ) =~ /^(\d+)$/ ) {
             my $id  = $1;
             my $obj = RT::Ticket->new( $session{'CurrentUser'} );
             $obj->Load($id);
 
-            my $actions = PageMenu()->child( actions => title => loc('Actions'), sort_order  => 95 );
-            my $tabs = PageMenu();
-            $tabs->child( bookmark => raw_html => $m->scomp( '/Ticket/Elements/Bookmark', id => $id ), sort_order => 99 );
-            $tabs->child( display => title => loc('Display'), path => "/Ticket/Display.html?id=" . $id );
-            $tabs->child( history => title => loc('History'), path => "/Ticket/History.html?id=" . $id );
-
-            my %can = %{ $obj->CurrentUser->PrincipalObj->HasRights( Object => $obj ) };
-            $can{'_ModifyOwner'} = $can{'OwnTicket'} || $can{'TakeTicket'} || $can{'StealTicket'};
-            my $can = sub {
-                unless ($_[0] eq 'ExecuteCode') {
-                    return $can{$_[0]} || $can{'SuperUser'};
-                } else {
-                    return !RT->Config->Get('DisallowExecuteCode')
-                        && ( $can{'ExecuteCode'} || $can{'SuperUser'} );
+            if ( $obj and $obj->id ) {
+                my $actions = PageMenu()->child( actions => title => loc('Actions'), sort_order  => 95 );
+                my $tabs = PageMenu();
+                $tabs->child( bookmark => raw_html => $m->scomp( '/Ticket/Elements/Bookmark', id => $id ), sort_order => 99 );
+                $tabs->child( display => title => loc('Display'), path => "/Ticket/Display.html?id=" . $id );
+                $tabs->child( history => title => loc('History'), path => "/Ticket/History.html?id=" . $id );
+
+                my %can = %{ $obj->CurrentUser->PrincipalObj->HasRights( Object => $obj ) };
+                $can{'_ModifyOwner'} = $can{'OwnTicket'} || $can{'TakeTicket'} || $can{'StealTicket'};
+                my $can = sub {
+                    unless ($_[0] eq 'ExecuteCode') {
+                        return $can{$_[0]} || $can{'SuperUser'};
+                    } else {
+                        return !RT->Config->Get('DisallowExecuteCode')
+                            && ( $can{'ExecuteCode'} || $can{'SuperUser'} );
+                    }
+                };
+
+                # comment out until we can do it for an individual custom field
+                #if ( $can->('ModifyTicket') || $can->('ModifyCustomField') ) {
+                $tabs->child( basics => title => loc('Basics'), path => "/Ticket/Modify.html?id=" . $id );
+
+                #}
+
+                #ACL?
+                $tabs->child( customers => title => loc('Customers'), path => "/Ticket/ModifyCustomers.html?id=" . $id );
+
+                if ( $can->('ModifyTicket') || $can->('_ModifyOwner') || $can->('Watch') || $can->('WatchAsAdminCc') ) {
+                    $tabs->child( people => title => loc('People'), path => "/Ticket/ModifyPeople.html?id=" . $id );
                 }
-            };
-
-            # comment out until we can do it for an individual custom field
-            #if ( $can->('ModifyTicket') || $can->('ModifyCustomField') ) {
-            $tabs->child( basics => title => loc('Basics'), path => "/Ticket/Modify.html?id=" . $id );
-
-            #}
-
-            #ACL?
-            $tabs->child( customers => title => loc('Customers'), path => "/Ticket/ModifyCustomers.html?id=" . $id );
-
-            if ( $can->('ModifyTicket') || $can->('_ModifyOwner') || $can->('Watch') || $can->('WatchAsAdminCc') ) {
-                $tabs->child( people => title => loc('People'), path => "/Ticket/ModifyPeople.html?id=" . $id );
-            }
-
-            if ( $can->('ModifyTicket') ) {
-                $tabs->child( dates => title => loc('Dates'), path => "/Ticket/ModifyDates.html?id=" . $id );
-                $tabs->child( links => title => loc('Links'), path => "/Ticket/ModifyLinks.html?id=" . $id );
-            }
 
-            #if ( $can->('ModifyTicket') || $can->('ModifyCustomField') || $can->('_ModifyOwner') ) {
-            $tabs->child( jumbo => title => loc('Jumbo'), path => "/Ticket/ModifyAll.html?id=" . $id );
-            #}
-
-            if ( RT->Config->Get('EnableReminders') ) {
-                $tabs->child( reminders => title => loc('Reminders'), path => "/Ticket/Reminders.html?id=" . $id );
-            }
-
-            if ( $can->('ModifyTicket') or $can->('ReplyToTicket') ) {
-                $actions->child( reply => title => loc('Reply'), path => "/Ticket/Update.html?Action=Respond;id=" . $id );
-            }
-
-            if ( $can->('ModifyTicket') or $can->('CommentOnTicket') ) {
-                $actions->child( comment => title => loc('Comment'), path => "/Ticket/Update.html?Action=Comment;id=" . $id );
-            }
+                if ( $can->('ModifyTicket') ) {
+                    $tabs->child( dates => title => loc('Dates'), path => "/Ticket/ModifyDates.html?id=" . $id );
+                    $tabs->child( links => title => loc('Links'), path => "/Ticket/ModifyLinks.html?id=" . $id );
+                }
 
-            if ( $can->('ForwardMessage') ) {
-                $actions->child( forward => title => loc('Forward'), path => "/Ticket/Forward.html?id=" . $id );
-            }
+                #if ( $can->('ModifyTicket') || $can->('ModifyCustomField') || $can->('_ModifyOwner') ) {
+                $tabs->child( jumbo => title => loc('Jumbo'), path => "/Ticket/ModifyAll.html?id=" . $id );
+                #}
 
-            my $hide_resolve_with_deps = RT->Config->Get('HideResolveActionsWithDependencies')
-                && $obj->HasUnresolvedDependencies;
-
-            my $current   = $obj->Status;
-            my $lifecycle = $obj->QueueObj->Lifecycle;
-            my $i         = 1;
-            foreach my $info ( $lifecycle->Actions($current) ) {
-                my $next = $info->{'to'};
-                next unless $lifecycle->IsTransition( $current => $next );
-
-                my $check = $lifecycle->CheckRight( $current => $next );
-                next unless $can->($check);
-
-                next if $hide_resolve_with_deps
-                    && $lifecycle->IsInactive($next)
-                    && !$lifecycle->IsInactive($current);
-
-                my $action = $info->{'update'} || '';
-                my $url = '/Ticket/';
-                if ($action) {
-                    $url .= "Update.html?"
-                        . $query_string->(
-                            Action        => $action,
-                            DefaultStatus => $next,
-                            id            => $id,
-                        );
-                } else {
-                    $url .= "Display.html?"
-                        . $query_string->(
-                            Status => $next,
-                            id     => $id,
-                        );
+                if ( RT->Config->Get('EnableReminders') ) {
+                    $tabs->child( reminders => title => loc('Reminders'), path => "/Ticket/Reminders.html?id=" . $id );
                 }
-                my $key = $info->{'label'} || ucfirst($next);
-                $actions->child( $key => title => loc( $key ), path => $url);
-            }
 
-            if ( $can->('OwnTicket') ) {
-                if ( $obj->OwnerObj->Id == RT->Nobody->id
-                     && ( $can->('ModifyTicket') or $can->('TakeTicket') ) ) {
-                    $actions->child( take => title => loc('Take'), path => "/Ticket/Display.html?Action=Take;id=" . $id );
+                if ( $can->('ModifyTicket') or $can->('ReplyToTicket') ) {
+                    $actions->child( reply => title => loc('Reply'), path => "/Ticket/Update.html?Action=Respond;id=" . $id );
                 }
 
-                elsif (    $obj->OwnerObj->id != RT->Nobody->id
-                        && $obj->OwnerObj->id != $session{CurrentUser}->id
-                        && ( $can->('ModifyTicket') or $can->('StealTicket') ) ) {
-                    $actions->child( steal => title => loc('Steal'), path => "/Ticket/Display.html?Action=Steal;id=" . $id );
+                if ( $can->('ModifyTicket') or $can->('CommentOnTicket') ) {
+                    $actions->child( comment => title => loc('Comment'), path => "/Ticket/Update.html?Action=Comment;id=" . $id );
                 }
-            }
-
-            # TODO needs a "Can extract article into a class applied to this queue" check
-            $actions->child( 'extract-article' =>
-                title => loc('Extract Article'),
-                path  => "/Articles/Article/ExtractIntoClass.html?Ticket=".$obj->id,
-            );
 
-            if ( 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 ( $can->('ForwardMessage') ) {
+                    $actions->child( forward => title => loc('Forward'), path => "/Ticket/Forward.html?id=" . $id );
+                }
 
-                if ($updatesession) {
-                    $session{"tickets"}->PrepForSerialization();
+                my $hide_resolve_with_deps = RT->Config->Get('HideResolveActionsWithDependencies')
+                    && $obj->HasUnresolvedDependencies;
+
+                my $current   = $obj->Status;
+                my $lifecycle = $obj->QueueObj->Lifecycle;
+                my $i         = 1;
+                foreach my $info ( $lifecycle->Actions($current) ) {
+                    my $next = $info->{'to'};
+                    next unless $lifecycle->IsTransition( $current => $next );
+
+                    my $check = $lifecycle->CheckRight( $current => $next );
+                    next unless $can->($check);
+
+                    next if $hide_resolve_with_deps
+                        && $lifecycle->IsInactive($next)
+                        && !$lifecycle->IsInactive($current);
+
+                    my $action = $info->{'update'} || '';
+                    my $url = '/Ticket/';
+                    if ($action) {
+                        $url .= "Update.html?"
+                            . $query_string->(
+                                Action        => $action,
+                                DefaultStatus => $next,
+                                id            => $id,
+                            );
+                    } else {
+                        $url .= "Display.html?"
+                            . $query_string->(
+                                Status => $next,
+                                id     => $id,
+                            );
+                    }
+                    my $key = $info->{'label'} || ucfirst($next);
+                    $actions->child( $key => title => loc( $key ), path => $url);
                 }
 
-                my $search = Menu()->child('search');
-                # Don't display prev links if we're on the first ticket
-                if ( $item_map->{$id}->{prev} ) {
-                    $search->child( first =>
-                        title => '<< ' . loc('First'), class => "nav", path => "/Ticket/Display.html?id=" . $item_map->{first});
-                    $search->child( prev =>
-                        title => '< ' . loc('Prev'),   class => "nav", path => "/Ticket/Display.html?id=" . $item_map->{$id}->{prev});
+                if ( $can->('OwnTicket') ) {
+                    if ( $obj->OwnerObj->Id == RT->Nobody->id
+                         && ( $can->('ModifyTicket') or $can->('TakeTicket') ) ) {
+                        $actions->child( take => title => loc('Take'), path => "/Ticket/Display.html?Action=Take;id=" . $id );
+                    }
+
+                    elsif (    $obj->OwnerObj->id != RT->Nobody->id
+                            && $obj->OwnerObj->id != $session{CurrentUser}->id
+                            && ( $can->('ModifyTicket') or $can->('StealTicket') ) ) {
+                        $actions->child( steal => title => loc('Steal'), path => "/Ticket/Display.html?Action=Steal;id=" . $id );
+                    }
                 }
-                # Don't display next links if we're on the last ticket
-                if ( $item_map->{$id}->{next} ) {
-                    $search->child( next =>
-                        title => loc('Next') . ' >',  class => "nav", path => "/Ticket/Display.html?id=" . $item_map->{$id}->{next});
-                    $search->child( last =>
-                        title => loc('Last') . ' >>', class => "nav", path => "/Ticket/Display.html?id=" . $item_map->{last});
+
+                # TODO needs a "Can extract article into a class applied to this queue" check
+                $actions->child( 'extract-article' =>
+                    title => loc('Extract Article'),
+                    path  => "/Articles/Article/ExtractIntoClass.html?Ticket=".$obj->id,
+                );
+
+                if ( defined $session{"tickets"} ) {
+                    # we have to update session data if we get new ItemMap
+                    my $updatesession = 1 unless ( $session{"tickets"}->{'item_map'} );
+
+                    my $item_map = $session{"tickets"}->ItemMap;
+
+                    if ($updatesession) {
+                        $session{"tickets"}->PrepForSerialization();
+                    }
+
+                    my $search = Menu()->child('search');
+                    # Don't display prev links if we're on the first ticket
+                    if ( $item_map->{$id}->{prev} ) {
+                        $search->child( first =>
+                            title => '<< ' . loc('First'), class => "nav", path => "/Ticket/Display.html?id=" . $item_map->{first});
+                        $search->child( prev =>
+                            title => '< ' . loc('Prev'),   class => "nav", path => "/Ticket/Display.html?id=" . $item_map->{$id}->{prev});
+                    }
+                    # Don't display next links if we're on the last ticket
+                    if ( $item_map->{$id}->{next} ) {
+                        $search->child( next =>
+                            title => loc('Next') . ' >',  class => "nav", path => "/Ticket/Display.html?id=" . $item_map->{$id}->{next});
+                        if ( $item_map->{last} ) {
+                            $search->child( last =>
+                                title => loc('Last') . ' >>', class => "nav", path => "/Ticket/Display.html?id=" . $item_map->{last});
+                        }
+                    }
                 }
             }
         }
@@ -658,17 +681,17 @@ my $build_main_nav = sub {
             && $request_path !~ m{^/Search/Simple\.html}
         )
         || (   $request_path =~ m{^/Search/Simple\.html}
-            && $m->request_args->{'q'} )
+            && $DECODED_ARGS->{'q'} )
       )
     {
         my $search = Menu()->child('search');
         my $args      = '';
         my $has_query = '';
         my $current_search = $session{"CurrentSearchHash"} || {};
-        my $search_id = $m->request_args->{'SavedSearchLoad'} || $m->request_args->{'SavedSearchId'} || $current_search->{'SearchId'} || '';
-        my $chart_id = $m->request_args->{'SavedChartSearchId'} || $current_search->{SavedChartSearchId};
+        my $search_id = $DECODED_ARGS->{'SavedSearchLoad'} || $DECODED_ARGS->{'SavedSearchId'} || $current_search->{'SearchId'} || '';
+        my $chart_id = $DECODED_ARGS->{'SavedChartSearchId'} || $current_search->{SavedChartSearchId};
 
-        $has_query = 1 if ( $m->request_args->{'Query'} or $current_search->{'Query'} );
+        $has_query = 1 if ( $DECODED_ARGS->{'Query'} or $current_search->{'Query'} );
 
         my %query_args;
         my %fallback_query_args = (
@@ -677,12 +700,12 @@ my $build_main_nav = sub {
             (
                 map {
                     my $p = $_;
-                    $p => $m->request_args->{$p} || $current_search->{$p}
+                    $p => $DECODED_ARGS->{$p} || $current_search->{$p}
                 } qw(Query Format OrderBy Order Page)
             ),
             RowsPerPage => (
-                defined $m->request_args->{'RowsPerPage'}
-                ? $m->request_args->{'RowsPerPage'}
+                defined $DECODED_ARGS->{'RowsPerPage'}
+                ? $DECODED_ARGS->{'RowsPerPage'}
                 : $current_search->{'RowsPerPage'}
             ),
         );
@@ -734,9 +757,14 @@ my $build_main_nav = sub {
             $current_search_menu->child( bulk  => title => loc('Bulk Update'), path => "/Search/Bulk.html$args" );
             $current_search_menu->child( chart => title => loc('Chart'),       path => "/Search/Chart.html$args" );
 
+            #formerly Callbacks/RTx-Calendar/Ticket/Element/Tabs/Default
+            $current_search_menu->child( calendar => title => loc('Calendar'), path => "/Search/Calendar.html$args" );
+
             my $more = $current_search_menu->child( more => title => loc('Feeds') );
 
-            $more->child( spreadsheet => title => loc('Spreadsheet'), path => "/Search/Results.tsv$args" );
+            $more->child( tsv => title => loc('TSV'), path => "/Search/Results.tsv$args" );
+            $more->child( csv => title => loc('CSV'), path => "/Search/Results.csv$args" );
+            $more->child( spreadsheet => title => loc('Spreadsheet'), path => "/Search/Results.xls$args" );
 
             my %rss_data = map {
                 $_ => $QueryArgs->{$_} || $fallback_query_args{$_} || '' }
@@ -764,8 +792,8 @@ my $build_main_nav = sub {
                 &&                        #XXX TODO better abstraction
                 $session{'CurrentUser'}->HasRight( Right => 'SuperUser', Object => RT->System )) {
                 my $shred_args = $query_string->(
-                    search          => 1,
-                    plugin          => 'Tickets',
+                    Search          => 1,
+                    Plugin          => 'Tickets',
                     'Tickets:query' => $rss_data{'Query'},
                     'Tickets:limit' => $QueryArgs->{'Rows'},
                 );
@@ -777,8 +805,8 @@ my $build_main_nav = sub {
     }
 
     if ( $request_path =~ m{^/Article/} ) {
-        if ( $m->request_args->{'id'} && $m->request_args->{'id'} =~ /^\d+$/ ) {
-            my $id = $m->request_args->{'id'};
+        if ( $DECODED_ARGS->{'id'} && $DECODED_ARGS->{'id'} =~ /^\d+$/ ) {
+            my $id = $DECODED_ARGS->{'id'};
             my $tabs = PageMenu();
 
             $tabs->child( display => title => loc('Display'), path => "/Articles/Article/Display.html?id=".$id );
@@ -789,22 +817,28 @@ my $build_main_nav = sub {
     }
 
     if ( $request_path =~ m{^/Articles/} ) {
+        PageWidgets()->child( article_search => raw_html => $m->scomp('/Articles/Elements/GotoArticle') );
+        PageWidgets()->delete('create_ticket');
+        PageWidgets()->delete('simple_search');
+
         my $tabs = PageMenu();
         $tabs->child( search => title => loc("Search"),       path => "/Articles/Article/Search.html" );
         $tabs->child( create => title => loc("New Article" ), path => "/Articles/Article/PreCreate.html" );
-        if ( ( $m->request_args->{'id'} || '' ) =~ /^(\d+)$/ ) {
+        if ( $request_path =~ m{^/Articles/Article/} and ( $DECODED_ARGS->{'id'} || '' ) =~ /^(\d+)$/ ) {
             my $id  = $1;
             my $obj = RT::Article->new( $session{'CurrentUser'} );
             $obj->Load($id);
 
-            $tabs->child( display => title => loc("Display"), path => "/Articles/Article/Display.html?id=" . $id );
-            $tabs->child( history => title => loc('History'), path => '/Articles/Article/History.html?id=' . $id );
+            if ( $obj and $obj->id ) {
+                $tabs->child( display => title => loc("Display"), path => "/Articles/Article/Display.html?id=" . $id );
+                $tabs->child( history => title => loc('History'), path => '/Articles/Article/History.html?id=' . $id );
 
-            if ( $obj->CurrentUserHasRight('ModifyArticle') ) {
-                $tabs->child(modify => title => loc('Modify'), path => '/Articles/Article/Edit.html?id=' . $id );
-            }
-            if ( $obj->CurrentUserHasRight('DeleteArticle') ) {
-                $tabs->child(delete => title => loc('Delete'), path => '/Articles/Article/Delete.html?id=' . $id );
+                if ( $obj->CurrentUserHasRight('ModifyArticle') ) {
+                    $tabs->child(modify => title => loc('Modify'), path => '/Articles/Article/Edit.html?id=' . $id );
+                }
+                if ( $obj->CurrentUserHasRight('DeleteArticle') ) {
+                    $tabs->child(delete => title => loc('Delete'), path => '/Articles/Article/Delete.html?id=' . $id );
+                }
             }
         }
 
@@ -814,9 +848,6 @@ my $build_main_nav = sub {
         PageMenu()->child( edit => title => loc('Edit'), path => '/Prefs/MyRT.html' );
     }
 
-    PageWidgets()->child( simple_search => raw_html => $m->scomp('SimpleSearch') );
-    PageWidgets()->child( create_ticket => raw_html => $m->scomp('CreateTicket') );
-
     $m->callback( CallbackName => 'Privileged' );
 };
 
@@ -825,7 +856,7 @@ my $build_selfservice_nav = sub {
     $queues->UnLimit;
 
     my $queue_count = 0;
-    my $queue_id    = 1;
+    my $queue_id;
 
     while ( my $queue = $queues->Next ) {
         next unless $queue->CurrentUserHasRight('CreateTicket');
@@ -835,14 +866,14 @@ my $build_selfservice_nav = sub {
     }
 
 
-    my $tickets = Menu->child( tickets => title => loc('Tickets'));
-    $tickets->child( open   => title => loc('Open tickets'),   path => '/SelfService/' );
-    $tickets->child( closed => title => loc('Closed tickets'), path => '/SelfService/Closed.html' );
     if ( $queue_count > 1 ) {
-        $tickets->child( new => title => loc('New ticket'),    path => '/SelfService/CreateTicketInQueue.html' );
-    } else {
-        $tickets->child( new => title => loc('New ticket'),    path => '/SelfService/Create.html?Queue=' . $queue_id );
+        Menu->child( new => title => loc('New ticket'), path => '/SelfService/CreateTicketInQueue.html' );
+    } elsif ( $queue_id ) {
+        Menu->child( new => title => loc('New ticket'), path => '/SelfService/Create.html?Queue=' . $queue_id );
     }
+    my $tickets = Menu->child( tickets => title => loc('Tickets'), path => '/SelfService/' );
+    $tickets->child( open   => title => loc('Open tickets'),   path => '/SelfService/' );
+    $tickets->child( closed => title => loc('Closed tickets'), path => '/SelfService/Closed.html' );
 
 
     my $username = '<span class="current-user">'