Initial commit 4.0.5-3
[usit-rt.git] / share / html / Elements / Tabs
CommitLineData
84fb5b46
MKG
1%# BEGIN BPS TAGGED BLOCK {{{
2%#
3%# COPYRIGHT:
4%#
5%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC
6%# <sales@bestpractical.com>
7%#
8%# (Except where explicitly superseded by other copyright notices)
9%#
10%#
11%# LICENSE:
12%#
13%# This work is made available to you under the terms of Version 2 of
14%# the GNU General Public License. A copy of that license should have
15%# been provided with this software, but in any event can be snarfed
16%# from www.gnu.org.
17%#
18%# This work is distributed in the hope that it will be useful, but
19%# WITHOUT ANY WARRANTY; without even the implied warranty of
20%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21%# General Public License for more details.
22%#
23%# You should have received a copy of the GNU General Public License
24%# along with this program; if not, write to the Free Software
25%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26%# 02110-1301 or visit their web page on the internet at
27%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html.
28%#
29%#
30%# CONTRIBUTION SUBMISSION POLICY:
31%#
32%# (The following paragraph is not intended to limit the rights granted
33%# to you to modify and distribute this software under the terms of
34%# the GNU General Public License and is only of importance to you if
35%# you choose to contribute your changes and enhancements to the
36%# community by submitting them to Best Practical Solutions, LLC.)
37%#
38%# By intentionally submitting any modifications, corrections or
39%# derivatives to this work, or any other work intended for use with
40%# Request Tracker, to Best Practical Solutions, LLC, you confirm that
41%# you are the copyright holder for those contributions and you grant
42%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
43%# royalty-free, perpetual, license to use, copy, create derivative
44%# works based on those contributions, and sublicense and distribute
45%# those contributions and any derivatives thereof.
46%#
47%# END BPS TAGGED BLOCK }}}
48<& /Elements/PageLayout, show_menu => $show_menu &>
49<a name="skipnav" id="skipnav" accesskey="8"></a>
50<%INIT>
51
52my $request_path = $HTML::Mason::Commands::r->path_info;
53
54my $query_string = sub {
55 my %args = @_;
56 my $u = URI->new();
57 $u->query_form(%args);
58 return $u->query;
59};
60
61my $build_admin_menu = sub {
62 my $top = shift;
63 my $admin = $top->child( config => title => loc('Configuration'), path => '/Admin/', sort_order => 99 );
64 if ( $session{'CurrentUser'}->HasRight( Object => RT->System, Right => 'AdminUsers' ) ) {
65 my $users = $admin->child( users =>
66 title => loc('Users'),
67 description => loc('Manage users and passwords'),
68 path => '/Admin/Users/',
69 );
70 $users->child( select => title => loc('Select'), path => "/Admin/Users/" );
71 $users->child( create => title => loc('Create'), path => "/Admin/Users/Modify.html?Create=1" );
72 }
73 my $groups = $admin->child( groups =>
74 title => loc('Groups'),
75 description => loc('Manage groups and group membership'),
76 path => '/Admin/Groups/',
77 );
78 $groups->child( select => title => loc('Select'), path => "/Admin/Groups/" );
79 $groups->child( create => title => loc('Create'), path => "/Admin/Groups/Modify.html?Create=1" );
80
81 my $queues = $admin->child( queues =>
82 title => loc('Queues'),
83 description => loc('Manage queues and queue-specific properties'),
84 path => '/Admin/Queues/',
85 );
86 $queues->child( select => title => loc('Select'), path => "/Admin/Queues/" );
87 $queues->child( create => title => loc('Create'), path => "/Admin/Queues/Modify.html?Create=1" );
88
89 if ( $session{'CurrentUser'}->HasRight( Object => RT->System, Right => 'AdminCustomField' ) ) {
90 my $cfs = $admin->child( 'custom-fields' =>
91 title => loc('Custom Fields'),
92 description => loc('Manage custom fields and custom field values'),
93 path => '/Admin/CustomFields/',
94 );
95 $cfs->child( select => title => loc('Select'), path => "/Admin/CustomFields/" );
96 $cfs->child( create => title => loc('Create'), path => "/Admin/CustomFields/Modify.html?Create=1" );
97 }
98
99 my $admin_global = $admin->child( global =>
100 title => loc('Global'),
101 description => loc('Manage properties and configuration which apply to all queues'),
102 path => '/Admin/Global/',
103 );
104
105 my $scrips = $admin_global->child( scrips =>
106 title => loc('Scrips'),
107 description => loc('Modify scrips which apply to all queues'),
108 path => '/Admin/Global/Scrips.html',
109 );
110 $scrips->child( select => title => loc('Select'), path => "/Admin/Global/Scrips.html" );
111 $scrips->child( create => title => loc('Create'), path => "/Admin/Global/Scrip.html?Create=1" );
112
113 my $templates = $admin_global->child( templates =>
114 title => loc('Templates'),
115 description => loc('Edit system templates'),
116 path => '/Admin/Global/Templates.html',
117 );
118 $templates->child( select => title => loc('Select'), path => "/Admin/Global/Templates.html" );
119 $templates->child( create => title => loc('Create'), path => "/Admin/Global/Template.html?Create=1" );
120
121 my $cfadmin = $admin_global->child( 'custom-fields' =>
122 title => loc('Custom Fields'),
123 description => loc('Modify global custom fields'),
124 path => '/Admin/Global/CustomFields/index.html',
125 );
126 $cfadmin->child( users =>
127 title => loc('Users'),
128 description => loc('Select custom fields for all users'),
129 path => '/Admin/Global/CustomFields/Users.html',
130 );
131 $cfadmin->child( groups =>
132 title => loc('Groups'),
133 description => loc('Select custom fields for all user groups'),
134 path => '/Admin/Global/CustomFields/Groups.html',
135 );
136 $cfadmin->child( queues =>
137 title => loc('Queues'),
138 description => loc('Select custom fields for all queues'),
139 path => '/Admin/Global/CustomFields/Queues.html',
140 );
141 $cfadmin->child( tickets =>
142 title => loc('Tickets'),
143 description => loc('Select custom fields for tickets in all queues'),
144 path => '/Admin/Global/CustomFields/Queue-Tickets.html',
145 );
146 $cfadmin->child( transactions =>
147 title => loc('Ticket Transactions'),
148 description => loc('Select custom fields for transactions on tickets in all queues'),
149 path => '/Admin/Global/CustomFields/Queue-Transactions.html',
150 );
151 $cfadmin->child( 'custom-fields' =>
152 title => loc('Articles'),
153 description => loc('Select Custom Fields for Articles in all Classes'),
154 path => '/Admin/Global/CustomFields/Class-Article.html',
155 );
156
157 my $article_admin = $admin->child( articles => title => loc('Articles'), path => "/Admin/Articles/index.html" );
158 my $class_admin = $article_admin->child(classes => title => loc('Classes'), path => '/Admin/Articles/Classes/' );
159 $class_admin->child( select =>
160 title => loc('Select'),
161 description => loc('Modify and Create Classes'),
162 path => '/Admin/Articles/Classes/',
163 );
164 $class_admin->child( create =>
165 title => loc('Create'),
166 description => loc('Modify and Create Custom Fields for Articles'),
167 path => '/Admin/Articles/Classes/Modify.html?Create=1',
168 );
169
170
171 my $cfs = $article_admin->child( 'custom-fields' =>
172 title => loc('Custom Fields'),
173 path => '/Admin/CustomFields/index.html?'.$m->comp('/Elements/QueryString', type => 'RT::Class-RT::Article'),
174 );
175 $cfs->child( select =>
176 title => loc('Select'),
177 path => '/Admin/CustomFields/index.html?'.$m->comp('/Elements/QueryString', type => 'RT::Class-RT::Article'),
178 );
179 $cfs->child( create =>
180 title => loc('Create'),
181 path => '/Admin/CustomFields/Modify.html?'.$m->comp("/Elements/QueryString", Create=>1, LookupType=> "RT::Class-RT::Article" ),
182 );
183
184 $admin_global->child( 'group-rights' =>
185 title => loc('Group Rights'),
186 description => loc('Modify global group rights'),
187 path => '/Admin/Global/GroupRights.html',
188 );
189 $admin_global->child( 'user-rights' =>
190 title => loc('User Rights'),
191 description => loc('Modify global user rights'),
192 path => '/Admin/Global/UserRights.html',
193 );
194 $admin_global->child( 'my-rt' =>
195 title => loc('RT at a glance'),
196 description => loc('Modify the default "RT at a glance" view'),
197 path => '/Admin/Global/MyRT.html',
198 );
199 $admin_global->child( 'topics' =>
200 title => loc('Topics'),
201 description => loc('Modify global article topics'),
202 path => '/Admin/Global/Topics.html',
203 );
204
205 my $admin_tools = $admin->child( tools =>
206 title => loc('Tools'),
207 description => loc('Use other RT administrative tools'),
208 path => '/Admin/Tools/',
209 );
210 $admin_tools->child( configuration =>
211 title => loc('System Configuration'),
212 description => loc('Detailed information about your RT setup'),
213 path => '/Admin/Tools/Configuration.html',
214 );
215 $admin_tools->child( theme =>
216 title => loc('Theme'),
217 description => loc('Customize the look of your RT'),
218 path => '/Admin/Tools/Theme.html',
219 );
220 if (RT->Config->Get('StatementLog')
221 && $session{'CurrentUser'}->HasRight( Right => 'SuperUser', Object => RT->System )) {
222 $admin_tools->child( 'sql-queries' =>
223 title => loc('SQL Queries'),
224 description => loc('Browse the SQL queries made in this process'),
225 path => '/Admin/Tools/Queries.html',
226 );
227 }
228 $admin_tools->child( shredder =>
229 title => loc('Shredder'),
230 description => loc('Permanently wipeout data from RT'),
231 path => '/Admin/Tools/Shredder',
232 );
233
234 if ( $request_path =~ m{^/Admin/(Queues|Users|Groups|CustomFields)} ) {
235 my $type = $1;
236 my $tabs = PageMenu();
237
238 my %labels = (
239 Queues => loc("Queues"),
240 Users => loc("Users"),
241 Groups => loc("Groups"),
242 CustomFields => loc("Custom Fields"),
243 );
244
245 my $section;
246 if ( $request_path =~ m|^/Admin/$type/?(?:index.html)?$|
247 || ( $request_path =~ m|^/Admin/$type/(?:Modify.html)$|
248 && $m->request_args->{'Create'} )
249 )
250 {
251 $section = $tabs;
252
253 } else {
254 $section = $tabs->child( select => title => $labels{$type},
255 path => "/Admin/$type/" );
256 }
257
258 $section->child( select => title => loc('Select'), path => "/Admin/$type/" );
259 $section->child( create => title => loc('Create'), path => "/Admin/$type/Modify.html?Create=1" );
260 }
261
262 if ( $request_path =~ m{^/Admin/Queues} ) {
263 if ( $m->request_args->{'id'} && $m->request_args->{'id'} =~ /^\d+$/
264 ||
265 $m->request_args->{'Queue'} && $m->request_args->{'Queue'} =~ /^\d+$/
266 ) {
267 my $id = $m->request_args->{'Queue'} || $m->request_args->{'id'};
268 my $queue_obj = RT::Queue->new( $session{'CurrentUser'} );
269 $queue_obj->Load($id);
270
271 my $queue = PageMenu();
272 $queue->child( basics => title => loc('Basics'), path => "/Admin/Queues/Modify.html?id=" . $id );
273 $queue->child( people => title => loc('Watchers'), path => "/Admin/Queues/People.html?id=" . $id );
274
275 my $templates = $queue->child(templates => title => loc('Templates'), path => "/Admin/Queues/Templates.html?id=" . $id);
276 $templates->child( select => title => loc('Select'), path => "/Admin/Queues/Templates.html?id=".$id);
277 $templates->child( create => title => loc('Create'), path => "/Admin/Queues/Template.html?Create=1;Queue=".$id);
278
279 my $scrips = $queue->child( scrips => title => loc('Scrips'), path => "/Admin/Queues/Scrips.html?id=" . $id);
280 $scrips->child( select => title => loc('Select'), path => "/Admin/Queues/Scrips.html?id=" . $id );
281 $scrips->child( create => title => loc('Create'), path => "/Admin/Queues/Scrip.html?Create=1;Queue=" . $id);
282
283 my $ticket_cfs = $queue->child( 'ticket-custom-fields' => title => loc('Ticket Custom Fields'),
284 path => '/Admin/Queues/CustomFields.html?SubType=RT::Ticket&id=' . $id );
285
286 my $txn_cfs = $queue->child( 'transaction-custom-fields' => title => loc('Transaction Custom Fields'),
287 path => '/Admin/Queues/CustomFields.html?SubType=RT::Ticket-RT::Transaction&id='.$id );
288
289 $queue->child( 'group-rights' => title => loc('Group Rights'), path => "/Admin/Queues/GroupRights.html?id=".$id );
290 $queue->child( 'user-rights' => title => loc('User Rights'), path => "/Admin/Queues/UserRights.html?id=" . $id );
291
292
293 $m->callback( CallbackName => 'PrivilegedQueue', queue_id => $id, page_menu => $queue);
294 }
295 }
296 if ( $request_path =~ m{^/Admin/Users} ) {
297 if ( $m->request_args->{'id'} && $m->request_args->{'id'} =~ /^\d+$/ ) {
298 my $id = $m->request_args->{'id'};
299 my $obj = RT::User->new( $session{'CurrentUser'} );
300 $obj->Load($id);
301
302 my $tabs = PageMenu();
303 $tabs->child( basics => title => loc('Basics'), path => "/Admin/Users/Modify.html?id=" . $id );
304 $tabs->child( memberships => title => loc('Memberships'), path => "/Admin/Users/Memberships.html?id=" . $id );
305 $tabs->child( history => title => loc('History'), path => "/Admin/Users/History.html?id=" . $id );
306 $tabs->child( 'my-rt' => title => loc('RT at a glance'), path => "/Admin/Users/MyRT.html?id=" . $id );
307 if ( RT->Config->Get('GnuPG')->{'Enable'} ) {
308 $tabs->child( pgp => title => loc('GnuPG'), path => "/Admin/Users/GnuPG.html?id=" . $id );
309 }
310 }
311
312 }
313
314 if ( $request_path =~ m{^/Admin/Groups} ) {
315 if ( $m->request_args->{'id'} && $m->request_args->{'id'} =~ /^\d+$/ ) {
316 my $id = $m->request_args->{'id'};
317 my $obj = RT::Group->new( $session{'CurrentUser'} );
318 $obj->Load($id);
319
320 my $tabs = PageMenu();
321 $tabs->child( basics => title => loc('Basics'), path => "/Admin/Groups/Modify.html?id=" . $obj->id );
322 $tabs->child( members => title => loc('Members'), path => "/Admin/Groups/Members.html?id=" . $obj->id );
323 $tabs->child( 'group-rights' => title => loc('Group Rights'), path => "/Admin/Groups/GroupRights.html?id=" . $obj->id );
324 $tabs->child( 'user-rights' => title => loc('User Rights'), path => "/Admin/Groups/UserRights.html?id=" . $obj->id );
325 $tabs->child( history => title => loc('History'), path => "/Admin/Groups/History.html?id=" . $obj->id );
326 }
327 }
328
329 if ( $request_path =~ m{^/Admin/CustomFields/} ) {
330 if ( $m->request_args->{'id'} && $m->request_args->{'id'} =~ /^\d+$/ ) {
331 my $id = $m->request_args->{'id'};
332 my $obj = RT::CustomField->new( $session{'CurrentUser'} );
333 $obj->Load($id);
334
335 my $tabs = PageMenu();
336 $tabs->child( basics => title => loc('Basics'), path => "/Admin/CustomFields/Modify.html?id=".$id );
337 $tabs->child( 'group-rights' => title => loc('Group Rights'), path => "/Admin/CustomFields/GroupRights.html?id=" . $id );
338 $tabs->child( 'user-rights' => title => loc('User Rights'), path => "/Admin/CustomFields/UserRights.html?id=" . $id );
339 $tabs->child( 'applies-to' => title => loc('Applies to'), path => "/Admin/CustomFields/Objects.html?id=" . $id );
340 }
341 }
342
343 if ( $request_path =~ m{^/Admin/Global/(Scrip|Template)s?\.html} ) {
344 my $type = $1;
345 my $tabs = PageMenu();
346
347 # With only two elements, swapping between dropdown and menu is kinda dumb
348 # In the glorious future this should be cleaner.
349
350 $tabs->child( select => title => loc('Select'), path => "/Admin/Global/${type}s.html" );
351 $tabs->child( create => title => loc('Create'), path => "/Admin/Global/${type}.html?Create=1" );
352 }
353
354 if ( $request_path =~ m{^/Admin/Articles/Classes/} ) {
355 my $tabs = PageMenu();
356 if ( my $id = $m->request_args->{'id'} ) {
357 my $obj = RT::CustomField->new( $session{'CurrentUser'} );
358 $obj->Load($id);
359
360 my $section = $tabs->child( select => title => loc("Classes"), path => "/Admin/Articles/Classes/" );
361 $section->child( select => title => loc('Select'), path => "/Admin/Articles/Classes/" );
362 $section->child( create => title => loc('Create'), path => "/Admin/Articles/Classes/Modify.html?Create=1" );
363
364 $tabs->child( basics => title => loc('Basics'), path => "/Admin/Articles/Classes/Modify.html?id=".$id );
365 $tabs->child( topics => title => loc('Topics'), path => "/Admin/Articles/Classes/Topics.html?id=".$id );
366 $tabs->child( 'custom-fields' => title => loc('Custom Fields'), path => "/Admin/Articles/Classes/CustomFields.html?id=".$id );
367 $tabs->child( 'group-rights' => title => loc('Group Rights'), path => "/Admin/Articles/Classes/GroupRights.html?id=".$id );
368 $tabs->child( 'user-rights' => title => loc('User Rights'), path => "/Admin/Articles/Classes/UserRights.html?id=".$id );
369 $tabs->child( 'applies-to' => title => loc('Applies to'), path => "/Admin/Articles/Classes/Objects.html?id=$id" );
370 } else {
371 $tabs->child( select => title => loc('Select'), path => "/Admin/Articles/Classes/" );
372 $tabs->child( create => title => loc('Create'), path => "/Admin/Articles/Classes/Modify.html?Create=1" );
373 }
374 }
375};
376
377
378my $build_main_nav = sub {
379
380 my $home = Menu->child( home => title => loc('Homepage'), path => '/' );
381 # We explicitly exclude superusers; otherwise the dashboards for
382 # groups you're not in (but can see the dashboards of by dint of
383 # being a superuser) would push the useful ones from the groups
384 # you're actually in off of the stack.
385 my @dashboards = $m->comp("/Dashboards/Elements/ListOfDashboards", IncludeSuperuserGroups => 0);
386 my $limit = 7;
387
388 my $more = 0;
389 if ( @dashboards > $limit ) {
390 $more = 1;
391 splice @dashboards, $limit;
392 }
393
394 my $dashes = Menu()->child('home');
395 if (@dashboards) {
396 for my $dash (@dashboards) {
397 $home->child( 'dashboard-' . $dash->id,
398 title => $dash->Name,
399 path => '/Dashboards/' . $dash->id . '/' . $dash->Name
400 );
401 }
402
403 $dashes->child( more => title => loc('All Dashboards'), path => 'Dashboards/index.html' );
404 }
405 my $dashboard = RT::Dashboard->new( $session{CurrentUser} );
406 if ( $dashboard->CurrentUserCanCreateAny ) {
407 $dashes->child('dashboard_create' => title => loc('New Dashboard'), path => "/Dashboards/Modify.html?Create=1" );
408 }
409
410 my $tickets = Menu->child( search => title => loc('Tickets'), path => '/Search/Build.html' );
411 $tickets->child( simple => title => loc('Simple Search'), path => "/Search/Simple.html" );
412 $tickets->child( new => title => loc('New Search'), path => "/Search/Build.html?NewQuery=1" );
413
414
415 my $tools = Menu->child( tools => title => loc('Tools'), path => '/Tools/index.html' );
416 my $articles = $tools->child( articles => title => loc('Articles'), path => "/Articles/index.html");
417 $articles->child( articles => title => loc('Overview'), path => "/Articles/index.html" );
418 $articles->child( search => title => loc('Search'), path => "/Articles/Article/Search.html" );
419 $articles->child( topics => title => loc('Topics'), path => "/Articles/Topics.html" );
420
421 $tools->child( my_day =>
422 title => loc('My Day'),
423 description => loc('Easy updating of your open tickets'),
424 path => '/Tools/MyDay.html',
425 );
426
427 if ( RT->Config->Get('EnableReminders') ) {
428 $tools->child( my_reminders =>
429 title => loc('My Reminders'),
430 description => loc('Easy viewing of your reminders'),
431 path => '/Tools/MyReminders.html',
432 );
433 }
434
435 $tools->child( offline =>
436 title => loc('Offline'),
437 description => loc('Create tickets offline'),
438 path => '/Tools/Offline.html',
439 );
440
441 if ( $session{'CurrentUser'}->HasRight( Right => 'ShowApprovalsTab', Object => RT->System ) ) {
442 $tools->child( approval =>
443 title => loc('Approval'),
444 description => loc('My Approvals'),
445 path => '/Approvals/',
446 );
447 }
448
449 if ( $session{'CurrentUser'}->HasRight( Right => 'ShowConfigTab', Object => RT->System ) )
450 {
451 $build_admin_menu->($tools);
452 }
453
454 my $username = '<span class="current-user">'
455 . $m->interp->apply_escapes($session{'CurrentUser'}->Name, 'h')
456 . '</span>';
457 my $about_me = Menu->child( 'preferences' =>
458 title => loc('Logged in as [_1]', $username),
459 escape_title => 0,
460 sort_order => 99,
461 );
462
463
464 if ( $session{'CurrentUser'}->UserObj
465 && $session{'CurrentUser'}->HasRight( Right => 'ModifySelf', Object => RT->System )) {
466 my $settings = $about_me->child( settings => title => loc('Settings'), path => '/Prefs/Other.html' );
467 $settings->child( options => title => loc('Options'), path => '/Prefs/Other.html' );
468 $settings->child( about_me => title => loc('About me'), path => '/User/Prefs.html' );
469 $settings->child( search_options => title => loc('Search options'), path => '/Prefs/SearchOptions.html' );
470 $settings->child( myrt => title => loc('RT at a glance'), path => '/Prefs/MyRT.html' );
471 $settings->child( quicksearch => title => loc('Quick search'), path => '/Prefs/Quicksearch.html' );
472
473 my $search_menu = $settings->child( 'saved-searches' => title => loc('Saved Searches') );
474 my $searches = [ $m->comp( "/Search/Elements/SearchesForObject",
475 Object => RT::System->new( $session{'CurrentUser'} )) ];
476 my $i = 0;
477
478 for my $search (@$searches) {
479 $search_menu->child( "search-" . $i++ =>
480 title => $search->[0],
481 path => "/Prefs/Search.html?"
482 . $query_string->( name => ref( $search->[1] ) . '-' . $search->[1]->Id ),
483 );
484
485 }
486 }
487 if ( $session{'CurrentUser'}->Name
488 && ( !RT->Config->Get('WebExternalAuth')
489 || RT->Config->Get('WebFallbackToInternalAuth') )) {
490 $about_me->child( logout => title => loc('Logout'), path => '/NoAuth/Logout.html' );
491 }
492 if ( $request_path =~ m{^/Dashboards/(\d+)?}) {
493 if ( my $id = ( $1 || $m->request_args->{'id'} ) ) {
494 my $obj = RT::Dashboard->new( $session{'CurrentUser'} );
495 $obj->LoadById($id);
496 if ( $obj and $obj->id ) {
497 my $tabs = PageMenu;
498 $tabs->child( basics => title => loc('Basics'), path => "/Dashboards/Modify.html?id=" . $obj->id);
499 $tabs->child( content => title => loc('Content'), path => "/Dashboards/Queries.html?id=" . $obj->id);
500 $tabs->child( subscription => title => loc('Subscription'), path => "/Dashboards/Subscription.html?id=" . $obj->id)
501 if $obj->CurrentUserCanSubscribe;
502 $tabs->child( show => title => loc('Show'), path => "/Dashboards/" . $obj->id . "/" . $obj->Name)
503 }
504 }
505 }
506
507
508 if ( $request_path =~ m{^/Ticket/} ) {
509 if ( ( $m->request_args->{'id'} || '' ) =~ /^(\d+)$/ ) {
510 my $id = $1;
511 my $obj = RT::Ticket->new( $session{'CurrentUser'} );
512 $obj->Load($id);
513
514 my $actions = PageMenu()->child( actions => title => loc('Actions'), sort_order => 95 );
515 my $tabs = PageMenu();
516 $tabs->child( bookmark => raw_html => $m->scomp( '/Ticket/Elements/Bookmark', id => $id ), sort_order => 99 );
517 $tabs->child( display => title => loc('Display'), path => "/Ticket/Display.html?id=" . $id );
518 $tabs->child( history => title => loc('History'), path => "/Ticket/History.html?id=" . $id );
519
520 my %can = %{ $obj->CurrentUser->PrincipalObj->HasRights( Object => $obj ) };
521 $can{'_ModifyOwner'} = $can{'OwnTicket'} || $can{'TakeTicket'} || $can{'StealTicket'};
522 my $can = sub {
523 unless ($_[0] eq 'ExecuteCode') {
524 return $can{$_[0]} || $can{'SuperUser'};
525 } else {
526 return !RT->Config->Get('DisallowExecuteCode')
527 && ( $can{'ExecuteCode'} || $can{'SuperUser'} );
528 }
529 };
530
531 # comment out until we can do it for an individual custom field
532 #if ( $can->('ModifyTicket') || $can->('ModifyCustomField') ) {
533 $tabs->child( basics => title => loc('Basics'), path => "/Ticket/Modify.html?id=" . $id );
534
535 #}
536
537 if ( $can->('ModifyTicket') || $can->('_ModifyOwner') || $can->('Watch') || $can->('WatchAsAdminCc') ) {
538 $tabs->child( people => title => loc('People'), path => "/Ticket/ModifyPeople.html?id=" . $id );
539 }
540
541 if ( $can->('ModifyTicket') ) {
542 $tabs->child( dates => title => loc('Dates'), path => "/Ticket/ModifyDates.html?id=" . $id );
543 $tabs->child( links => title => loc('Links'), path => "/Ticket/ModifyLinks.html?id=" . $id );
544 }
545
546 #if ( $can->('ModifyTicket') || $can->('ModifyCustomField') || $can->('_ModifyOwner') ) {
547 $tabs->child( jumbo => title => loc('Jumbo'), path => "/Ticket/ModifyAll.html?id=" . $id );
548 #}
549
550 if ( RT->Config->Get('EnableReminders') ) {
551 $tabs->child( reminders => title => loc('Reminders'), path => "/Ticket/Reminders.html?id=" . $id );
552 }
553
554 if ( $can->('ModifyTicket') or $can->('ReplyToTicket') ) {
555 $actions->child( reply => title => loc('Reply'), path => "/Ticket/Update.html?Action=Respond;id=" . $id );
556 }
557
558 if ( $can->('ModifyTicket') or $can->('CommentOnTicket') ) {
559 $actions->child( comment => title => loc('Comment'), path => "/Ticket/Update.html?Action=Comment;id=" . $id );
560 }
561
562 if ( $can->('ForwardMessage') ) {
563 $actions->child( forward => title => loc('Forward'), path => "/Ticket/Forward.html?id=" . $id );
564 }
565
566 my $hide_resolve_with_deps = RT->Config->Get('HideResolveActionsWithDependencies')
567 && $obj->HasUnresolvedDependencies;
568
569 my $current = $obj->Status;
570 my $lifecycle = $obj->QueueObj->Lifecycle;
571 my $i = 1;
572 foreach my $info ( $lifecycle->Actions($current) ) {
573 my $next = $info->{'to'};
574 next unless $lifecycle->IsTransition( $current => $next );
575
576 my $check = $lifecycle->CheckRight( $current => $next );
577 next unless $can->($check);
578
579 next if $hide_resolve_with_deps
580 && $lifecycle->IsInactive($next)
581 && !$lifecycle->IsInactive($current);
582
583 my $action = $info->{'update'} || '';
584 my $url = '/Ticket/';
585 if ($action) {
586 $url .= "Update.html?"
587 . $query_string->(
588 Action => $action,
589 DefaultStatus => $next,
590 id => $id,
591 );
592 } else {
593 $url .= "Display.html?"
594 . $query_string->(
595 Status => $next,
596 id => $id,
597 );
598 }
599 my $key = $info->{'label'} || ucfirst($next);
600 $actions->child( $key => title => loc( $key ), path => $url);
601 }
602
603 if ( $can->('OwnTicket') ) {
604 if ( $obj->OwnerObj->Id == RT->Nobody->id
605 && ( $can->('ModifyTicket') or $can->('TakeTicket') ) ) {
606 $actions->child( take => title => loc('Take'), path => "/Ticket/Display.html?Action=Take;id=" . $id );
607 }
608
609 elsif ( $obj->OwnerObj->id != RT->Nobody->id
610 && $obj->OwnerObj->id != $session{CurrentUser}->id
611 && ( $can->('ModifyTicket') or $can->('StealTicket') ) ) {
612 $actions->child( steal => title => loc('Steal'), path => "/Ticket/Display.html?Action=Steal;id=" . $id );
613 }
614 }
615
616 # TODO needs a "Can extract article into a class applied to this queue" check
617 $actions->child( 'extract-article' =>
618 title => loc('Extract Article'),
619 path => "/Articles/Article/ExtractIntoClass.html?Ticket=".$obj->id,
620 );
621
622 if ( defined $session{"tickets"} ) {
623 # we have to update session data if we get new ItemMap
624 my $updatesession = 1 unless ( $session{"tickets"}->{'item_map'} );
625
626 my $item_map = $session{"tickets"}->ItemMap;
627
628 if ($updatesession) {
629 $session{"tickets"}->PrepForSerialization();
630 }
631
632 my $search = Menu()->child('search');
633 # Don't display prev links if we're on the first ticket
634 if ( $item_map->{$id}->{prev} ) {
635 $search->child( first =>
636 title => '<< ' . loc('First'), class => "nav", path => "/Ticket/Display.html?id=" . $item_map->{first});
637 $search->child( prev =>
638 title => '< ' . loc('Prev'), class => "nav", path => "/Ticket/Display.html?id=" . $item_map->{$id}->{prev});
639 }
640 # Don't display next links if we're on the last ticket
641 if ( $item_map->{$id}->{next} ) {
642 $search->child( next =>
643 title => loc('Next') . ' >', class => "nav", path => "/Ticket/Display.html?id=" . $item_map->{$id}->{next});
644 $search->child( last =>
645 title => loc('Last') . ' >>', class => "nav", path => "/Ticket/Display.html?id=" . $item_map->{last});
646 }
647 }
648 }
649 }
650
651 if (
652 (
653 $request_path =~ m{^/(?:Ticket|Search)/}
654 && $request_path !~ m{^/Search/Simple\.html}
655 )
656 || ( $request_path =~ m{^/Search/Simple\.html}
657 && $m->request_args->{'q'} )
658 )
659 {
660 my $search = Menu()->child('search');
661 my $args = '';
662 my $has_query = '';
663 my $current_search = $session{"CurrentSearchHash"} || {};
664 my $search_id = $m->request_args->{'SavedSearchLoad'} || $m->request_args->{'SavedSearchId'} || $current_search->{'SearchId'} || '';
665 my $chart_id = $m->request_args->{'SavedChartSearchId'} || $current_search->{SavedChartSearchId};
666
667 $has_query = 1 if ( $m->request_args->{'Query'} or $current_search->{'Query'} );
668
669 my %query_args;
670 my %fallback_query_args = (
671 SavedSearchId => ( $search_id eq 'new' ) ? undef : $search_id,
672 SavedChartSearchId => $chart_id,
673 (
674 map {
675 my $p = $_;
676 $p => $m->request_args->{$p} || $current_search->{$p}
677 } qw(Query Format OrderBy Order Page)
678 ),
679 RowsPerPage => (
680 defined $m->request_args->{'RowsPerPage'}
681 ? $m->request_args->{'RowsPerPage'}
682 : $current_search->{'RowsPerPage'}
683 ),
684 );
685
686 if ($QueryString) {
687 $args = '?' . $QueryString;
688 }
689 else {
690 my %final_query_args = ();
691 # key => callback to avoid unnecessary work
692
693 for my $param (keys %fallback_query_args) {
694 $final_query_args{$param} = defined($QueryArgs->{$param})
695 ? $QueryArgs->{$param}
696 : $fallback_query_args{$param};
697 }
698
699 for my $field (qw(Order OrderBy)) {
700 if ( ref( $final_query_args{$field} ) eq 'ARRAY' ) {
701 $final_query_args{$field} = join( "|", @{ $final_query_args{$field} } );
702 } elsif (not defined $final_query_args{$field}) {
703 delete $final_query_args{$field};
704 }
705 else {
706 $final_query_args{$field} ||= '';
707 }
708 }
709
710 $args = '?' . $query_string->(%final_query_args);
711 }
712
713 my $current_search_menu;
714 if ( $request_path =~ m{^/Ticket} ) {
715 $current_search_menu = $search->child( current_search => title => loc('Current Search') );
716 $current_search_menu->path("/Search/Results.html$args") if $has_query;
717 } else {
718 $current_search_menu = PageMenu();
719 }
720
721 $current_search_menu->child( edit_search =>
722 title => loc('Edit Search'), path => "/Search/Build.html" . ( ($has_query) ? $args : '' ) );
723 $current_search_menu->child( advanced =>
724 title => loc('Advanced'), path => "/Search/Edit.html$args" );
725 if ($has_query) {
726 $current_search_menu->child( results => title => loc('Show Results'), path => "/Search/Results.html$args" );
727 }
728
729 if ( $has_query ) {
730 $current_search_menu->child( bulk => title => loc('Bulk Update'), path => "/Search/Bulk.html$args" );
731 $current_search_menu->child( chart => title => loc('Chart'), path => "/Search/Chart.html$args" );
732
733 my $more = $current_search_menu->child( more => title => loc('Feeds') );
734
735 $more->child( spreadsheet => title => loc('Spreadsheet'), path => "/Search/Results.tsv$args" );
736
737 my %rss_data = map {
738 $_ => $QueryArgs->{$_} || $fallback_query_args{$_} || '' }
739 qw(Query Order OrderBy);
740 my $RSSQueryString = "?"
741 . $query_string->( Query => $rss_data{Query},
742 Order => $rss_data{Order},
743 OrderBy => $rss_data{OrderBy}
744 );
745 my $RSSPath = join '/', map $m->interp->apply_escapes( $_, 'u' ),
746 $session{'CurrentUser'}->UserObj->Name,
747 $session{'CurrentUser'}
748 ->UserObj->GenerateAuthString( $rss_data{Query}
749 . $rss_data{Order}
750 . $rss_data{OrderBy} );
751
752 $more->child( rss => title => loc('RSS'), path => "/NoAuth/rss/$RSSPath/$RSSQueryString");
753 my $ical_path = join '/', map $m->interp->apply_escapes($_, 'u'),
754 $session{'CurrentUser'}->UserObj->Name,
755 $session{'CurrentUser'}->UserObj->GenerateAuthString( $rss_data{Query} ),
756 $rss_data{Query};
757 $more->child( ical => title => loc('iCal'), path => '/NoAuth/iCal/'.$ical_path);
758
759 if ($request_path =~ m{^/Search/Results.html}
760 && #XXX TODO better abstraction
761 $session{'CurrentUser'}->HasRight( Right => 'SuperUser', Object => RT->System )) {
762 my $shred_args = $query_string->(
763 search => 1,
764 plugin => 'Tickets',
765 'Tickets:query' => $rss_data{'Query'},
766 'Tickets:limit' => $QueryArgs->{'Rows'},
767 );
768
769 $more->child( shredder => title => loc('Shredder'), path => '/Admin/Tools/Shredder/?' . $shred_args);
770 }
771
772 }
773 }
774
775 if ( $request_path =~ m{^/Article/} ) {
776 if ( $m->request_args->{'id'} && $m->request_args->{'id'} =~ /^\d+$/ ) {
777 my $id = $m->request_args->{'id'};
778 my $tabs = PageMenu();
779
780 $tabs->child( display => title => loc('Display'), path => "/Articles/Article/Display.html?id=".$id );
781 $tabs->child( history => title => loc('History'), path => "/Articles/Article/History.html?id=".$id );
782 $tabs->child( modify => title => loc('Modify'), path => "/Articles/Article/Edit.html?id=".$id );
783 $tabs->child( delete => title => loc('Delete'), path => "/Articles/Article/Delete.html?id=".$id );
784 }
785 }
786
787 if ( $request_path =~ m{^/Articles/} ) {
788 my $tabs = PageMenu();
789 $tabs->child( search => title => loc("Search"), path => "/Articles/Article/Search.html" );
790 $tabs->child( create => title => loc("New Article" ), path => "/Articles/Article/PreCreate.html" );
791 if ( $request_path =~ m{^/Articles/Article/} and ( $m->request_args->{'id'} || '' ) =~ /^(\d+)$/ ) {
792 my $id = $1;
793 my $obj = RT::Article->new( $session{'CurrentUser'} );
794 $obj->Load($id);
795
796 $tabs->child( display => title => loc("Display"), path => "/Articles/Article/Display.html?id=" . $id );
797 $tabs->child( history => title => loc('History'), path => '/Articles/Article/History.html?id=' . $id );
798
799 if ( $obj->CurrentUserHasRight('ModifyArticle') ) {
800 $tabs->child(modify => title => loc('Modify'), path => '/Articles/Article/Edit.html?id=' . $id );
801 }
802 if ( $obj->CurrentUserHasRight('DeleteArticle') ) {
803 $tabs->child(delete => title => loc('Delete'), path => '/Articles/Article/Delete.html?id=' . $id );
804 }
805 }
806
807 }
808
809 if ( $request_path =~ /^\/(?:index.html|$)/ ) {
810 PageMenu()->child( edit => title => loc('Edit'), path => '/Prefs/MyRT.html' );
811 }
812
813 PageWidgets()->child( simple_search => raw_html => $m->scomp('SimpleSearch') );
814 PageWidgets()->child( create_ticket => raw_html => $m->scomp('CreateTicket') );
815
816 $m->callback( CallbackName => 'Privileged' );
817};
818
819my $build_selfservice_nav = sub {
820 my $queues = RT::Queues->new( $session{'CurrentUser'} );
821 $queues->UnLimit;
822
823 my $queue_count = 0;
824 my $queue_id = 1;
825
826 while ( my $queue = $queues->Next ) {
827 next unless $queue->CurrentUserHasRight('CreateTicket');
828 $queue_id = $queue->id;
829 $queue_count++;
830 last if ( $queue_count > 1 );
831 }
832
833
834 my $tickets = Menu->child( tickets => title => loc('Tickets'));
835 $tickets->child( open => title => loc('Open tickets'), path => '/SelfService/' );
836 $tickets->child( closed => title => loc('Closed tickets'), path => '/SelfService/Closed.html' );
837 if ( $queue_count > 1 ) {
838 $tickets->child( new => title => loc('New ticket'), path => '/SelfService/CreateTicketInQueue.html' );
839 } else {
840 $tickets->child( new => title => loc('New ticket'), path => '/SelfService/Create.html?Queue=' . $queue_id );
841 }
842
843
844 my $username = '<span class="current-user">'
845 . $m->interp->apply_escapes($session{'CurrentUser'}->Name, 'h')
846 . '</span>';
847 my $about_me = Menu->child( preferences =>
848 title => loc('Logged in as [_1]', $username),
849 escape_title => 0,
850 sort_order => 99,
851 );
852
853 if ( $session{'CurrentUser'}->HasRight( Right => 'ModifySelf', Object => RT->System ) ) {
854 $about_me->child( prefs => title => loc('Preferences'), path => '/SelfService/Prefs.html' );
855 }
856
857 if ( $session{'CurrentUser'}->Name
858 && ( !RT->Config->Get('WebExternalAuth')
859 || RT->Config->Get('WebFallbackToInternalAuth') )) {
860 $about_me->child( logout => title => loc('Logout'), path => '/NoAuth/Logout.html' );
861 }
862
863 if ($session{'CurrentUser'}->HasRight( Right => 'ShowArticle', Object => RT->System )) {
864 PageWidgets->child( 'goto-article' => raw_html => $m->scomp('/SelfService/Elements/SearchArticle') );
865 }
866
867 PageWidgets->child( goto => raw_html => $m->scomp('/SelfService/Elements/GotoTicket') );
868
869 $m->callback( CallbackName => 'SelfService' );
870};
871
872
873
874if ( $request_path !~ m{^/SelfService/} ) {
875 $build_main_nav->();
876} else {
877 $build_selfservice_nav->();
878}
879
880
881
882
883</%INIT>
884<%ARGS>
885$show_menu => 1
886$QueryString => ''
887$QueryArgs => {}
888</%ARGS>