fix jitter and spacing errors in new customer menu under IE8, cleaner CSS
[freeside.git] / httemplate / view / cust_main / menu.html
1 <style type="text/css">
2
3 #customer_menu {
4   font-size: smaller;
5   border: none;
6   margin-top: .6em;
7   margin-bottom: 16px;
8 }
9
10 #customer_menu li {
11   float: left;
12   padding: .25em;
13 }
14
15 /* #customer_menu .ui-menu-item  */
16 #customer_menu > li {
17   background-color: #f8f8f8;
18   padding-left: 0px;
19 }
20
21 /* #customer_menu .ui-menu-item  */
22 #customer_menu > li.ui-state-focus {
23   background-color: #f8f8f8;
24   border: 1px solid transparent;
25 }
26
27 #customer_menu > li.ui-state-active {
28   background-color: #f8f8f8;
29   border: 1px solid transparent;
30 }
31
32 #customer_menu > li > a {
33   border-top: 1px solid transparent;
34   border-left: 1px solid transparent;
35   border-right: 1px solid transparent;
36   border-bottom: none;
37   padding: .5em .75em;
38 }
39
40 #customer_menu > li.ui-state-active > a {
41
42 /* if i could find something light enough that didn't look pink?
43      or is this too visually distracting and not the useful hint i think it is?
44   background: #ED55E7;
45 */
46 }
47
48 #customer_menu a.current_show {
49   font-weight: bold;
50   background: #FFFFFF;
51   border-top: 1px solid #7e0079;
52   border-left: 1px solid #7e0079;
53   border-right: 1px solid #7e0079;
54   border-bottom: 2px solid #ffffff;
55   margin-bottom: -2px;
56   border-bottom-left-radius: 2px;
57   border-bottom-right-radius: 2px;
58 }
59
60 #customer_menu a {
61   margin-left: 0;
62   margin-right: 1em;
63   margin-top: 0;
64   border-top-left-radius: .5em;
65   border-top-right-radius: .5em;
66
67   font-weight: normal;
68   background: #e0e0e0;
69   color: #525151;
70   white-space: nowrap;
71   text-decoration: none;
72 }
73
74 #customer_menu ul {
75   background: #ffffff;
76   border: 1px solid #7e0079;
77   border-radius: 2px;
78   box-shadow: #333333 1px 1px 2px;
79 }
80
81 #customer_menu ul li {
82   float: none;
83   margin-right: 2px;
84   margin-left: 2px;
85 }
86
87 #customer_menu ul a {
88   color: #333333;
89   background: transparent;
90 }
91
92 #customer_menu li.ui-menu-divider {
93   border-color: #7e0079;
94 /*  margin-right: 2px;
95   margin-left: 2px; */
96 }
97
98 #customer_menu a:hover {
99   text-decoration: underline;
100   color: #7e0079;
101 }
102
103 #customer_menu ul li.ui-state-focus {
104   background: transparent;
105   border: 1px solid transparent;
106   margin-right: 1px;
107   margin-left: 1px;
108 }
109
110 #customer_menu ul li.ui-state-active {
111   background: #f8f0fc;
112   border: 1px solid #7e0079;
113   border-radius: 2px;
114   margin-right: 1px;
115   margin-left: 1px;
116 }
117
118 #customer_menu a .arrow {
119   float: right;
120   background-image: url("<% $p %>images/arrow.right.black.png");
121   width: 3px;
122   height: 6px;
123   margin-top:4px;
124 }
125
126 @-moz-document url-prefix() {
127   #customer_menu a .arrow {
128     margin-top:-.8em;
129   }
130 }
131
132 </style>
133
134 <& /elements/one_time_charge_link.html, form_only=>1 &>
135
136 <ul id="customer_menu">
137 % foreach my $submenu (@processed_menu) {
138   <li>
139     <% shift @$submenu %>
140 %   if ( @$submenu ) {
141       <ul class="customer_submenu">
142 %     foreach my $link ( @$submenu ) {
143         <li><% $link %></li>
144 %     }
145       </ul>
146 %   }
147   </li>
148 % }
149 </ul>
150
151 <script type="text/javascript">
152
153   $("#customer_menu").menu({
154     position: { my: "left top", at: "left+1 bottom+3" },
155     blur: function() {
156       $(this).menu("option", "position", { my:"left top", at:"left+1 bottom+3" } );
157     },
158     focus: function(e,ui) {
159       if ($("#customer_menu").get(0) !== $(ui).get(0).item.parent().get(0)) {
160         $(this).menu("option", "position", { my:"left top", at:"right+2 top"} );
161       }
162     },
163   });
164
165 </script>
166
167
168 <%init>
169 my %opt = @_;
170 my $cust_main = $opt{'cust_main'};
171 my $custnum = $cust_main->custnum;
172 my $curuser = $FS::CurrentUser::CurrentUser;
173 my $conf = FS::Conf->new;
174
175 my %payby = map { $_ => 1 } $conf->config('payby');
176
177 # cached for conditions, to avoid looking it up twice
178 my $invoicing_list_emailonly = $cust_main->invoicing_list_emailonly;
179
180 # nice declarative menu; should be a parameter to some kind of menu generator
181 my @menu = ( 
182   [
183     { show        => 'basics',
184       label       => 'Basics',
185     },
186     {
187       label       => 'Edit customer',
188       url         => "edit/cust_main.cgi?$custnum",
189       acl         => 'Edit customer'
190     },
191     {
192       label       => 'Edit contacts',
193       url         => "edit/cust_main-contacts.html?$custnum",
194     },
195
196     { label   => '-',
197       content => '-',
198     },
199
200     {
201       label       => 'Bill now',
202       acl         => 'Bill customer now',
203       content     => sub { include( '/elements/bill.html',
204                               label   => emt('Bill now'),
205                               url     => $cgi->self_url,
206                               custnum => shift->custnum,
207                            ),
208                      },
209     },
210     {
211       label       => 'Suspend',
212       popup       => "misc/suspend_cust.html?custnum=$custnum",
213       acl         => 'Suspend customer',
214       condition   => sub { shift->unsuspended_pkgs > 0 },
215       actionlabel => 'Confirm Suspension',
216       color       => '#ff9900',
217     },
218     {
219       label       => 'Unsuspend',
220       popup       => "misc/unsuspend_cust.html?custnum=$custnum",
221       acl         => 'Unsuspend customer',
222       condition   => sub { shift->suspended_pkgs > 0 },
223       actionlabel => 'Confirm Unsuspension',
224     },
225     {
226       label       => 'Cancel',
227       popup       => "misc/suspend_cust.html?custnum=$custnum",
228       acl         => 'Cancel customer',
229       condition   => sub { shift->ncancelled_pkgs > 0 },
230       actionlabel => 'Confirm Cancellation',
231       color       => '#ff0000',
232     },
233     {
234       label       => 'Merge',
235       popup       => "misc/merge_cust.html?custnum=$custnum",
236       acl         => 'Merge customer',
237       actionlabel => 'Merge customer',
238       width       => 569,
239       height      => 210,
240     },
241     {
242       label       => 'Refer a new customer',
243       url         => "edit/cust_main.cgi?referral_custnum=$custnum",
244       confexists  => '!disable_customer_referrals',
245     },
246
247     { label   => '-',
248       content => '-',
249     },
250
251     {
252       label       => 'View this customer\'s referrals',
253       url         => "search/cust_main.cgi?referral_custnum=$custnum",
254       confexists  => '!disable_customer_referrals',
255       condition   => sub {
256         FS::cust_main->count('referral_custnum = ?', shift->custnum) > 0
257       },
258     },
259     {
260       label       => 'View billing events',
261       url         => "search/cust_event.html?custnum=$custnum",
262       acl         => [ 'Billing event reports',
263                        'View customer billing events' ],
264     },
265     {
266       label       => 'Email a notice to this customer',
267       url         => sub {
268                       my $cust_main = shift;
269                       my $agentnum = $cust_main->agentnum;
270                       'misc/email-customers.html?table=cust_main;'.
271                       'agent_virt_agentnum='.$agentnum.";custnum=$custnum;url=".
272                       uri_escape($cgi->self_url);
273                      },
274       condition   => sub { $invoicing_list_emailonly },
275       acl         => 'Bulk send customer notices',
276     },
277   ],
278   [
279     {
280       label => 'Notes',
281       show  => 'notes',
282     },
283     {
284       label       => 'Add note',
285       popup       => "edit/cust_main_note.cgi?custnum=$custnum",
286       actionlabel => 'Add note',
287       confexists  => '!cust_main-disable_notes',
288       acl         => 'Add customer note',
289       width       => 875,
290       height      => 538,
291     },
292     {
293       label       => 'Attach file',
294       popup       => "edit/cust_main_attach.cgi?custnum=$custnum",
295       actionlabel => 'Upload file',
296       confexists  => '!disable_cust_attachment',
297       acl         => 'Add attachment',
298       width       => 480,
299       height      => 296,
300     },
301   ],
302   [
303     {
304       label => 'Tickets',
305       show  => 'tickets',
306       confexists => 'ticket_system'
307     },
308   ],
309   [
310     {
311       label => 'Appointments',
312       show  => 'appointments',
313       confexists => 'ticket_system',
314       acl   => 'View appointments',
315     },
316     {
317       label       => 'Schedule new appointment',
318       confexists  => 'ticket_system',
319       acl        => 'Make appointment',
320       popup       => "elements/make_appointment.html?custnum=$custnum",
321       actionlabel => 'Schedule appointment',
322     },
323   ],
324   [
325     {
326       label => 'Quotations',
327       show  => 'quotations',
328     },
329     {
330       label => 'Create new quotation',
331       url   => "edit/quotation.html?custnum=$custnum",
332       acl   => 'Generate quotation',
333     },
334   ],
335   [
336     {
337       label => 'Packages',
338       show  => 'packages',
339     },
340     {
341       label       => 'New qualification',
342       popup       => "misc/qual.html?custnum=$custnum",
343       actionlabel => 'New qualification',
344       color       => '#333399',
345       width       => 763,
346       height      => 436,
347       acl         => 'Qualify service',
348     },
349     {
350       label       => 'Order new package',
351       popup       => "misc/order_pkg.html?custnum=$custnum",
352       actionlabel => 'Order new package',
353       color       => '#333399',
354       width       => 960,
355       height      => 740,
356       acl         => 'Order customer package',
357     },
358     {
359       # it's just a popup, but there's some freaky CCH tax stuff in it
360       label       => 'One-time charge',
361       content     => sub {
362                       include( '/elements/one_time_charge_link.html',
363                         custnum => shift->custnum,
364                         no_form => 1,
365                       );
366                      },
367       acl         => 'One-time charge',
368     },
369     {
370       label       => 'Move services between packages',
371       popup       => "edit/bulk-cust_svc-pkgnum.html?custnum=$custnum",
372       actionlabel => 'Move services',
373       width       => 968,
374       height      => 575,
375       acl         => 'Bulk move customer services',
376     },
377     {
378       label       => 'Bulk order and cancel packages',
379       url         => "edit/cust_pkg.cgi?$custnum",
380       acl         => 'Bulk change customer packages',
381     },
382
383     { label   => '-',
384       content => '-',
385     },
386
387     {
388       label => 'Package reports',
389       url   => "search/report_cust_pkg?custnum=$custnum",
390     },
391     {
392       label => 'View qualifications',
393       url   => "search/qual.cgi?custnum=$custnum",
394       acl   => 'Qualify service',
395     },
396     {
397       label => 'View accounts',
398       url   => "search/report_svc_acct.html?custnum=$custnum",
399     },
400     {
401       label => 'View CDRs',
402       url   => "search/report_cdr.html?custnum=$custnum",
403     },
404   ],
405   [
406     {
407       label => 'Payment History',
408       show  => 'payment_history',
409     },
410
411     # manual payment entry via edit/cust_pay
412     { label   => 'Enter payment',
413       submenu => [
414         {
415           label       => 'Enter check payment',
416           popup       => "edit/cust_pay.cgi?popup=1;payby=BILL;custnum=$custnum",
417           actionlabel => 'Enter check payment',
418           width       => 763,
419           height      => 392,
420           acl         => [ 'Post payment', 'Post check payment' ],
421           condition   => sub { $payby{BILL} },
422         },
423         {
424           label       => 'Enter cash payment',
425           popup       => "edit/cust_pay.cgi?popup=1;payby=CASH;custnum=$custnum",
426           actionlabel => 'Enter cash payment',
427           width       => 763,
428           height      => 392,
429           acl         => [ 'Post payment', 'Post cash payment' ],
430           condition   => sub { $payby{CASH} },
431         },
432         {
433           label       => 'Enter Western Union payment',
434           popup       => "edit/cust_pay.cgi?popup=1;payby=WEST;custnum=$custnum",
435           actionlabel => 'Enter Western Union payment',
436           width       => 763,
437           height      => 392,
438           acl         => [ 'Post payment', ],
439           condition   => sub { $payby{WEST} },
440         },
441         {
442           label       => 'Record manual (offline/POS) credit card payment',
443           popup       => "edit/cust_pay.cgi?popup=1;payby=MCRD;custnum=$custnum",
444           actionlabel => 'Enter credit card payment',
445           width       => 763,
446           height      => 392,
447           acl         => [ 'Post payment', ],
448           condition   => sub { $payby{MCRD} },
449         },
450         {
451           label       => 'Record manual (offline/POS) electronic check',
452           popup       => "edit/cust_pay.cgi?popup=1;payby=MCHK;custnum=$custnum",
453           actionlabel => 'Enter credit card payment',
454           width       => 763,
455           height      => 392,
456           acl         => [ 'Post payment', ],
457           condition   => sub { $payby{MCHK} },
458         },
459       ],
460     },
461
462     # realtime payments via payment.cgi
463     { label   => 'Process payment',
464       submenu => [
465         {
466           label       => 'Process credit card payment',
467           url         => "misc/payment.cgi?payby=CARD;custnum=$custnum",
468           acl         => [ 'Process payment', 'Process credit card payment', ],
469           condition   => sub { $payby{CARD} or $payby{DCRD} },
470         },
471         {
472           label       => 'Process electronic check payment',
473           url         => "misc/payment.cgi?payby=CHEK;custnum=$custnum",
474           acl         => [ 'Process payment', 'Process Echeck payment', ],
475           condition   => sub { $payby{CHEK} or $payby{DCHK} },
476         },
477       ],
478     },
479
480     { label   => '-',
481       content => '-',
482     },
483
484     {
485       label       => 'Enter credit',
486       popup       => "edit/cust_credit.cgi?custnum=$custnum",
487       actionlabel => 'Enter credit',
488       width       => 763,
489       acl         => 'Post credit',
490     },
491     {
492       label       => 'Credit line items',
493       popup       => "edit/credit-cust_bill_pkg.html?custnum=$custnum",
494       actionlabel => 'Credit line items',
495       width       => 968,
496       height      => 575,
497       acl         => 'Credit line items',
498       condition   => sub {
499         FS::cust_bill->count('custnum = ?', shift->custnum) > 0
500       },
501     },
502
503     { label   => '-',
504       content => '-',
505     },
506
507     { label   => 'Enter refund',
508       submenu => [
509
510         {
511           label       => 'Enter check refund',
512           popup       => "edit/cust_refund.cgi?popup=1;payby=BILL;custnum=$custnum",
513           actionlabel => 'Enter check refund',
514           width       => 440,
515           acl         => ['Post refund', 'Post check refund'],
516           condition   => sub { $payby{BILL} },
517         },
518         {
519           label       => 'Enter cash refund',
520           popup       => "edit/cust_refund.cgi?popup=1;payby=CASH;custnum=$custnum",
521           actionlabel => 'Enter cash refund',
522           width       => 392,
523           acl         => ['Post refund', 'Post cash refund'],
524           condition   => sub { $payby{CASH} },
525         },
526         {
527           label       => 'Record manual (offline/POS) credit card refund',
528           popup       => "edit/cust_refund.cgi?popup=1;payby=MCRD;custnum=$custnum",
529           actionlabel => 'Enter credit card refund',
530           width       => 440,
531           acl         => ['Post refund' ],
532           condition   => sub { $payby{MCRD} },
533         },
534         {
535           label       => 'Record manual (offline/POS) electronic check refund',
536           popup       => "edit/cust_refund.cgi?popup=1;payby=MCHK;custnum=$custnum",
537           actionlabel => 'Enter electronic check refund',
538           width       => 440,
539           acl         => ['Post refund' ],
540           condition   => sub { $payby{MCHK} },
541         },
542
543       ],
544
545     },
546
547     { label   => '-',
548       content => '-',
549     },
550
551     {
552       label       => 'Add tax adjustment',
553       popup       => "edit/cust_tax_adjustment.html?custnum=$custnum",
554       actionlabel => 'Add tax adjustment',
555       height      => 200,
556       confexists  => 'enable_tax_adjustments',
557       acl         => 'Add customer tax adjustment',
558     },
559
560     { label       => '-',
561       content     => '-',
562       confexists  => 'enable_tax_adjustments',
563       acl         => 'Add customer tax adjustment',
564     },
565
566     {
567       label       => 'Email statement to this customer',
568       url         => sub {
569                       my $cust_main = shift;
570                       my $agentnum = $cust_main->agentnum;
571                       'misc/email-customer-statement.html?table=cust_main;'.
572                       'agent_virt_agentnum='.$agentnum.";custnum=$custnum;url=".
573                       uri_escape($cgi->self_url);
574                      },
575       condition   => sub { $invoicing_list_emailonly },
576       acl         => 'Resend invoices',
577     },
578     {
579       label       => 'Download PDF statement',
580       url         => "view/cust_main_statement-pdf.cgi?$custnum",
581       acl         => 'View legacy typeset statements',
582       condition   => sub {
583         FS::cust_bill->count('custnum = ?', shift->custnum) > 0
584       },
585     },
586     {
587       label       => 'Search invoices',
588       url         => "search/report_cust_bill.html?custnum=$custnum",
589       acl         => 'List invoices',
590     },
591     {
592       label       => 'View tax exemptions',
593       url         => "search/cust_tax_exempt_pkg.cgi?custnum=$custnum",
594       acl         => 'View customer tax exemptions',
595     },
596     {
597       label       => 'View tax adjustments',
598       url         => "search/cust_tax_adjustment.html?custnum=$custnum",
599       confexists  => 'enable_tax_adjustments',
600       acl         => 'Add customer tax adjustment',
601     },
602     {
603       label       => 'View pending payments',
604       url         => "search/cust_pay_pending.html?magic=_date;statusNOT=done;custnum=$custnum",
605       acl         => 'View pending payments',
606       condition   => sub { 
607         FS::cust_pay_pending->count('custnum = ?', shift->custnum) > 0
608       },
609     },
610
611   ],
612   [
613     {
614       label => 'Change History',
615       show  => 'change_history',
616       acl   => 'View customer history',
617     },
618   ],
619 );
620
621
622 my @processed_menu;
623 foreach my $submenu (@menu) {
624
625   my @links;
626   my $first = 1;
627   foreach my $entry ( @$submenu ) {
628     # if the menu head was skipped, skip the whole menu
629     last if (!$first and !@links);
630     $first = 0;
631
632     my $a = entry2link($entry, $cust_main, $opt{show});
633     push @links, $a if length($a);
634
635   } # foreach $entry
636
637   if (@links) {
638     push @processed_menu, \@links;
639   }
640
641 }
642
643 sub entry2link {
644     my( $entry, $cust_main, $show ) = @_;
645
646     # check conditions
647     if ( $entry->{acl} ) {
648       return ''
649         unless $FS::CurrentUser::CurrentUser->access_right( $entry->{acl} );
650     }
651     if ( $entry->{confexists} ) {
652       if ( $entry->{confexists} =~ /^!(.*)/ ) {
653         # confexists => !foo, a negative condition
654         return '' if FS::Conf->new->exists( $1 );
655       } else {
656         return '' unless FS::Conf->new->exists( $entry->{confexists} );
657       }
658     }
659     if ( $entry->{condition} ) {
660       return '' unless &{ $entry->{condition} }($cust_main);
661     }
662
663     my $label = emt($entry->{label});
664
665     if ( $entry->{submenu} ) {
666
667       my $a = '<a href="javascript:void(0);">'. $label.
668               '<span class="arrow"></span>'.
669               '</a><ul class="customer_subsubmenu">';
670       foreach my $submenu (@{ $entry->{submenu} }) {
671         $a .= '<li>'. entry2link($submenu, $cust_main, $show), '</li>';
672       }
673
674       return $a. '</ul>';
675
676     }
677
678     my $target = $entry->{content}
679               || $entry->{popup}
680               || $entry->{url};
681
682     if ( ref($target) eq 'CODE' ) {
683       $target = &$target($cust_main);
684     }
685
686     return $target if $entry->{content}; #the coderef specified the whole thing
687
688     if ( $entry->{show} ) {
689
690       # the menu head: always a link back to this page
691       $cgi->param('show', $entry->{show});
692       $target = $cgi->self_url;
693       $cgi->param('show', $show);
694
695       my $a = qq[ <A HREF="$target"];
696       $a .= ' class="current_show"' if $show eq $entry->{show};
697       return $a. qq[>$label</A> ];
698
699     } elsif ( $entry->{popup} ) {
700
701       $target =~ s/\$custnum/$custnum/g;
702       $target = $p.$target;
703
704       return include('/elements/popup_link.html',
705         action  => $target,
706         width   => 616,
707         height  => 410,
708         %$entry,
709         label   => $label,
710       );
711
712     } elsif ( $entry->{url} ) {
713
714       $target =~ s/\$custnum/$custnum/g;
715       $target = $p.$target;
716
717       return qq[ <A HREF="$target">$label</A> ];
718
719     } else {
720       die "bad entry ". join(',',%$entry). " in menu: no url, popup or content";
721     }
722
723 }
724
725 </%init>