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