diff options
| author | Ivan Kohler <ivan@freeside.biz> | 2012-07-08 22:45:58 -0700 |
|---|---|---|
| committer | Ivan Kohler <ivan@freeside.biz> | 2012-07-08 22:45:58 -0700 |
| commit | a6fe07e49e3fc12169e801b1ed6874c3a5bd8500 (patch) | |
| tree | b87a7e6f37da5c8e13eb4d4653cfc8ce9239d8f0 /httemplate/elements | |
| parent | e27244386c346f459d1569db26344407a0372a05 (diff) | |
| parent | 005424d0c899aa899f43f583a6c74deb13ea4be1 (diff) | |
Merge branch 'master' of git.freeside.biz:/home/git/freeside
Conflicts:
httemplate/misc/process/cancel_pkg.html
Diffstat (limited to 'httemplate/elements')
34 files changed, 913 insertions, 368 deletions
diff --git a/httemplate/elements/city.html b/httemplate/elements/city.html index f6d2b4bad..6a2142f29 100644 --- a/httemplate/elements/city.html +++ b/httemplate/elements/city.html @@ -107,7 +107,11 @@ function <% $pre %>county_changed(what, callback) {} <% $text_style %> > -% if ( !$disable_select ) { +% if ( $disable_select ) { +%# avoid JS errors +<INPUT TYPE="hidden" ID="city_select"> +% } +% else { <SELECT NAME = "<%$pre%>city_select" ID = "<%$pre%>city_select" diff --git a/httemplate/elements/coord-links.html b/httemplate/elements/coord-links.html index 3fd3ff696..02a224a00 100644 --- a/httemplate/elements/coord-links.html +++ b/httemplate/elements/coord-links.html @@ -3,7 +3,7 @@ <& /elements/popup_link.html, 'action' => $p. 'view/map.html?'. $query, 'label' => mt('map'), - 'actionlabel' => $name, + 'actionlabel' => $js_name, 'width' => 763, 'height' => 575, #'color' @@ -12,8 +12,8 @@ % if ( $origin ) { <& /elements/popup_link.html, 'action' => $p. "view/directions.html?origin=$origin;". $query, - 'label' => mt('dir'), - 'actionlabel' => $name, + 'label' => mt('directions'), + 'actionlabel' => $js_name, 'width' => 763, 'height' => 575, &> @@ -29,6 +29,12 @@ my $query = 'name='. uri_escape_utf8($name). ';lat='. $latitude. ';lon='. $longitude; +my $js_name = $name; +$js_name =~ s/[<>"]/ /g; +$m->interp->apply_escapes($js_name, 'js_string'); +$js_name =~ s/^'//; +$js_name =~ s/'$//; + my $origin; #for directions link if ( $agentnum =~ /^\d+$/ ) { diff --git a/httemplate/elements/customer-table.html b/httemplate/elements/customer-table.html index aa085c41a..79443dc8b 100644 --- a/httemplate/elements/customer-table.html +++ b/httemplate/elements/customer-table.html @@ -41,6 +41,8 @@ Example: <SCRIPT TYPE="text/javascript"> + var num_open_invoices = new Array; + function clearhint_invnum() { if ( this.value == 'Not found' || this.value == 'Multiple' ) { @@ -67,7 +69,46 @@ Example: this.value = ''; } - + + function update_customer(searchrow, customerArray) { + + var custnum_obj = document.getElementById('custnum'+searchrow); + var customer = document.getElementById('customer'+searchrow); + var customer_select = document.getElementById('cust_select'+searchrow); + + custnum_obj.disabled = false; + custnum_obj.style.backgroundColor = '#ffffff'; + customer.disabled = false; + customer.style.backgroundColor = '#ffffff'; + + if ( customerArray.length == 0 ) { + + custnum_obj.value = 'Not found'; + customer.value = 'Not found'; + custnum_obj.style.color = '#ff0000'; + customer.style.color = '#ff0000'; + + customer.style.display = ''; + customer_select.style.display = 'none'; + return false; + + } else if ( customerArray.length == 6 ) { + + custnum_obj.value = customerArray[0]; + custnum_obj.style.color = '#000000'; + customer.value = customerArray[1]; + + update_balance_text(searchrow, customerArray[2]); + update_status_text( searchrow, customerArray[3]); + update_status_color(searchrow, '#'+customerArray[4]); + update_num_open(searchrow, customerArray[5]); + + customer.style.display = ''; + customer_select.style.display = 'none'; + return true; + } + } + function <% $opt{prefix} %>search_invnum() { this.style.color = '#000000' @@ -99,55 +140,26 @@ Example: customer_select.style.display = 'none'; var custnum_obj = document.getElementById('custnum'+searchrow); - var balance = document.getElementById('balance'+searchrow); - var status = document.getElementById('status'+searchrow); - balance.innerHTML = ''; - status.innerHTML = ''; + update_balance_text(searchrow, ''); + update_status_text(searchrow, ''); + update_status_color(searchrow, '#000000'); + update_num_open(searchrow, 0); function search_invnum_update(customers) { var customerArray = eval('(' + customers + ')'); - - custnum_obj.disabled = false; - custnum_obj.style.backgroundColor = '#ffffff'; - customer.disabled = false; - customer.style.backgroundColor = '#ffffff'; - - if ( customerArray.length == 0 ) { - - custnum_obj.value = 'Not found'; - customer.value = 'Not found'; - custnum_obj.style.color = '#ff0000'; - customer.style.color = '#ff0000'; - - customer.style.display = ''; - customer_select.style.display = 'none'; - - } else if ( customerArray.length == 5 ) { - - custnum_obj.value = customerArray[0]; - custnum_obj.style.color = '#000000'; - customer.value = customerArray[1]; - balance.innerHTML = '<% $money_char %>' + customerArray[2] + ' '; - status.innerHTML = customerArray[3]; - status.style.color = '#'+customerArray[4]; - - customer.style.display = ''; - customer_select.style.display = 'none'; + update_customer(searchrow, customerArray); % if ( $opt{invnum_update_callback} ) { <% $opt{invnum_update_callback} %>(searchrow, '<% $opt{prefix} %>') % } - } - } invnum_search( invnum, search_invnum_update ); } - function <% $opt{prefix} %>search_custnum() { this.style.color = '#000000' @@ -167,55 +179,62 @@ Example: if ( ( <% $opt{prefix} %>rownum - searchrow ) == 1 ) { <% $opt{prefix} %>addRow(); } - var customer = document.getElementById('customer'+searchrow); - customer.value = 'searching...'; - customer.disabled = true; - customer.style.color = '#000000'; - customer.style.backgroundColor = '#dddddd'; + + var customer_obj = document.getElementById('customer'+searchrow); + customer_obj.value = 'searching...'; + customer_obj.disabled = true; + customer_obj.style.color = '#000000'; + customer_obj.style.backgroundColor = '#dddddd'; var customer_select = document.getElementById('cust_select'+searchrow); - customer.style.display = ''; + customer_obj.style.display = ''; customer_select.style.display = 'none'; var invnum = document.getElementById('invnum'+searchrow); invnum.value = ''; - - var balance = document.getElementById('balance'+searchrow); - balance.innerHTML = ''; - - var status = document.getElementById('status'+searchrow); - status.innerHTML = ''; + + update_balance_text(searchrow, ''); + update_status_text( searchrow, ''); + update_status_color(searchrow, '#000000'); + update_num_open(searchrow, 0); function search_custnum_update(customers) { - var customerArray = eval('(' + customers + ')'); + var customerArrayArray = eval('(' + customers + ')') || []; - customer.disabled = false; - customer.style.backgroundColor = '#ffffff'; - - if ( customerArray.length == 0 ) { + if ( customerArrayArray.length == 1 ) { - customer.value = 'Not found'; - customer.style.color = '#ff0000'; + update_customer(searchrow, customerArrayArray[0]); +% if ( $opt{custnum_update_callback} ) { + <% $opt{custnum_update_callback} %>(searchrow, '<% $opt{prefix} %>') +% } + + } else { + + custnum_obj.value = 'Multiple'; // or something custnum_obj.style.color = '#ff0000'; - } else if ( customerArray.length == 5 ) { + //blank the current list + customer_select.options.length = 0; + + opt(customer_select, '', 'Multiple customers match "' + custnum + '" - select one', '#ff0000'); + //add the multiple customers + for ( var s = 0; s < customerArrayArray.length; s++ ) { + opt(customer_select, + JSON.stringify(customerArrayArray[s]), + customerArrayArray[s][1], + '#000000'); + } - custnum_obj.value = customerArray[0]; - custnum_obj.style.color = '#000000'; - customer.value = customerArray[1]; - balance.innerHTML = '<% $money_char %>' + customerArray[2] + ' '; - status.innerHTML = customerArray[3]; - status.style.color = '#'+customerArray[4]; + opt(customer_select, 'cancel', '(Edit search string)', '#000000'); - customer.style.display = ''; - customer_select.style.display = 'none'; + customer_obj.style.display = 'none'; + + customer_select.style.display = ''; -% if ( $opt{custnum_update_callback} ) { - <% $opt{custnum_update_callback} %>(searchrow, '<% $opt{prefix} %>') -% } } + } custnum_search(custnum, search_custnum_update ); @@ -251,39 +270,16 @@ Example: var customer_select = document.getElementById('cust_select'+searchrow); - var balance = document.getElementById('balance'+searchrow); - balance.innerHTML = ''; - - var status = document.getElementById('status'+searchrow); - status.innerHTML = ''; - function search_customer_update(customers) { - var customerArray = eval('(' + customers + ')'); + var customerArrayArray = eval('(' + customers + ')') || [ [] ]; custnum_obj.disabled = false; custnum_obj.style.backgroundColor = '#ffffff'; - if ( customerArray.length == 0 ) { - - custnum_obj.value = 'Not found'; - custnum_obj.style.color = '#ff0000'; - customer_obj.style.color = '#ff0000'; - - customer_obj.style.display = ''; - customer_select.style.display = 'none'; - - } else if ( customerArray.length == 1 ) { - - custnum_obj.value = customerArray[0][0]; - customer_obj.value = customerArray[0][1]; - balance.innerHTML = '<% $money_char %>' + customerArray[0][2] + ' '; - status.innerHTML = customerArray[0][3]; - status.style.color = '#'+customerArray[0][4]; - - customer_obj.style.display = ''; - customer_select.style.display = 'none'; + if ( customerArrayArray.length == 1 ) { + update_customer(searchrow, customerArrayArray[0]); % if ( $opt{custnum_update_callback} ) { <% $opt{custnum_update_callback} %>(searchrow, '<% $opt{prefix} %>') % } @@ -294,14 +290,16 @@ Example: custnum_obj.style.color = '#ff0000'; //blank the current list - for ( var i = customer_select.length; i >= 0; i-- ) - customer_select.options[i] = null; + customer_select.options.length = 0; opt(customer_select, '', 'Multiple customers match "' + customer + '" - select one', '#ff0000'); - //add the multiple customers - for ( var s = 0; s < customerArray.length; s++ ) - opt(customer_select, customerArray[s][0] + '_' + customerArray[s][2] + '_' + customerArray[s][3] + '_' + customerArray[s][4], customerArray[s][1], '#000000'); + for ( var s = 0; s < customerArrayArray.length; s++ ) { + opt(customer_select, + JSON.stringify(customerArrayArray[s]), + customerArrayArray[s][1], + '#000000'); + } opt(customer_select, 'cancel', '(Edit search string)', '#000000'); @@ -341,27 +339,7 @@ Example: } else { - var pos_underscore1 = custnum_balance_status.indexOf('_'); - var pos_underscore2 = custnum_balance_status.indexOf('_',pos_underscore1+1); - var pos_underscore3 = custnum_balance_status.indexOf('_',pos_underscore2+1); - var custnum = custnum_balance_status.substring(0,pos_underscore1); - var balance = custnum_balance_status.substring(pos_underscore1+1,pos_underscore2) + ' '; - var status = custnum_balance_status.substring(pos_underscore2+1,pos_underscore3); - var color = custnum_balance_status.substring(pos_underscore3+1); - - custnum_obj.value = custnum; - custnum_obj.style.color = '#000000'; - - customer_obj.value = customer; - customer_obj.style.color = '#000000'; - - balance_obj.innerHTML = '<% $money_char %>' + balance; - - status_obj.innerHTML = status; - status_obj.style.color = '#'+color; - - this.style.display = 'none'; - customer_obj.style.display = ''; + update_customer(searchrow, JSON.parse(custnum_balance_status)); % if ( $opt{custnum_update_callback} ) { <% $opt{custnum_update_callback} %>(searchrow, '<% $opt{prefix} %>') @@ -378,6 +356,26 @@ Example: what.options[length] = optionName; } + function update_status_text(rownum, newval) { + document.getElementById('status'+rownum).value = newval; + document.getElementById('status'+rownum+'_text').innerHTML = newval; + } + + function update_status_color(rownum, newval) { + document.getElementById('statuscolor'+rownum).value = newval; + document.getElementById('status'+rownum+'_text').style.color = newval; + } + + function update_balance_text(rownum, newval) { + document.getElementById('balance'+rownum).value = newval; + document.getElementById('balance'+rownum+'_text').innerHTML = newval; + } + + function update_num_open(rownum, newval) { + num_open_invoices[rownum] = newval; + } + + </SCRIPT> <TABLE ID="<% $opt{prefix} %>OneTrueTable" BGCOLOR="#cccccc" BORDER=0 CELLSPACING=0> @@ -395,7 +393,7 @@ Example: % my $row = 0; % for ( $row = 0; exists($param->{"custnum$row"}); $row++ ) { - <TR> + <TR id="row<%$row%>" rownum="<%$row%>"> <TD> <INPUT TYPE = "text" NAME = "invnum<% $row %>" @@ -430,14 +428,26 @@ Example: </SCRIPT> </TD> - <TD> - <SPAN + <TD STYLE="text-align: center"> + <SPAN + ID = "status<% $row %>_text" + rownum = "<% $row %>" + STYLE = "font-weight: bold; + color: <%$param->{"statuscolor$row"} || '#000000'%>" + + ><% $param->{"status$row"} %></SPAN> + <INPUT TYPE = "hidden" NAME = "status<% $row %>" ID = "status<% $row %>" + VALUE = "<% $param->{"status$row"} %>" + rownum = "<% $row %>" + > + <INPUT TYPE = "hidden" + NAME = "statuscolor<% $row %>" + ID = "statuscolor<% $row %>" + VALUE = "<% $param->{"statuscolor$row"} %>" rownum = "<% $row %>" - STYLE = "text-align:center; font-weight: bold" > - </SPAN> </TD> <TD> @@ -456,6 +466,21 @@ Example: </SCRIPT> </TD> + <TD STYLE="text-align:right"> + <% $money_char %> + <SPAN + ID = "balance<% $row %>_text" + rownum = "<% $row %>" + ><% $param->{"balance$row"} %></SPAN> + + <INPUT TYPE = "hidden" + NAME = "balance<% $row %>" + ID = "balance<% $row %>" + VALUE = "<% $param->{"balance$row"} %>" + rownum = "<% $row %>" + > + </TD> + % my $col = 0; % foreach my $field ( @{$opt{fields}} ) { % my $value; @@ -470,19 +495,24 @@ Example: % my $color = $opt{color}->[$col]; % my $font = $color ? qq(<FONT COLOR="$color">) : ''; % my $onchange = ''; -% if ( $opt{footer}->[$col] eq '_TOTAL' ) { +% if ( $opt{onchange}->[$col] ) { +% $onchange = 'onchange="'.$opt{onchange}->[$col].'"'; +% } +% elsif ( $opt{footer}->[$col] eq '_TOTAL' ) { % $total[$col] += $value; % $onchange = $opt{prefix}. "calc_total$col();"; % $onchange = qq(onchange="$onchange" onkeyup="$onchange"); % } <TD ALIGN="<% $align %>"> -% if (! $types->[$col] || $types->[$col] eq 'text') { - <INPUT TYPE = "text" +% my $type = $types->[$col] || 'text'; +% if ($type eq 'text' or $type eq 'checkbox') { + <INPUT TYPE = "<% $type %>" NAME = "<% $name %>" ID = "<% $name %>" SIZE = "<% $size %>" STYLE = "text-align: <% $align %>;" VALUE = "<% $value %>" + rownum = "<% $row %>" <% $onchange %> > % } elsif ($types->[$col] eq 'immutable') { @@ -494,19 +524,10 @@ Example: </TD> % $col++; % } - <TD STYLE="text-align:right;"> - <SPAN - NAME = "balance<% $row %>" - ID = "balance<% $row %>" - rownum = "<% $row %>" - > - </SPAN> - - </TD> </TR> % } -<TR> +<TR id="row_total"> <TH COLSPAN=5 ID="<% $opt{'prefix'} %>_TOTAL_TOTAL"> Total <% $row ? $row-1 : 0 %> <% PL($opt{name_singular} || 'customer', ( $row ? $row-1 : 0 ) ) %> @@ -580,7 +601,8 @@ Example: var table = document.getElementById('<% $opt{prefix} %>OneTrueTable'); var tablebody = table.getElementsByTagName('tbody').item(0); - var row = table.insertRow(rownum+1); + var row = table.insertRow(table.rows.length - 1); + row.setAttribute('id', 'row'+rownum); var invnum_cell = document.createElement('TD'); @@ -613,15 +635,28 @@ Example: row.appendChild(custnum_cell); var status_cell = document.createElement('TD'); + status_cell.style.textAlign = 'center'; - var status_span = document.createElement('SPAN'); - status_span.setAttribute('name', 'status'+<% $opt{prefix} %>rownum); - status_span.setAttribute('id', 'status'+<% $opt{prefix} %>rownum); - status_span.style.textAlign = 'center'; - status_span.style.fontWeight = 'bold'; - status_span.setAttribute('rownum', <% $opt{prefix} %>rownum); - status_cell.appendChild(status_span); + var status_span = document.createElement('SPAN'); + status_span.setAttribute('id', 'status'+<% $opt{prefix} %>rownum+'_text'); + status_span.style.fontWeight = 'bold'; + status_span.setAttribute('rownum', <% $opt{prefix} %>rownum); + status_cell.appendChild(status_span); + var status_input = document.createElement('INPUT'); + status_input.setAttribute('type', 'hidden'); + status_input.setAttribute('name', 'status'+<% $opt{prefix} %>rownum); + status_input.setAttribute('id', 'status'+<% $opt{prefix} %>rownum); + status_input.setAttribute('rownum', <% $opt{prefix} %>rownum); + status_cell.appendChild(status_input); + + var statuscolor_input = document.createElement('INPUT'); + statuscolor_input.setAttribute('type', 'hidden'); + statuscolor_input.setAttribute('name', 'statuscolor'+<% $opt{prefix} %>rownum); + statuscolor_input.setAttribute('id', 'statuscolor'+<% $opt{prefix} %>rownum); + statuscolor_input.setAttribute('rownum', <% $opt{prefix} %>rownum); + status_cell.appendChild(statuscolor_input); + row.appendChild(status_cell); var customer_cell = document.createElement('TD'); @@ -649,13 +684,25 @@ Example: row.appendChild(customer_cell); var balance_cell = document.createElement('TD'); - balance_cell.style.textAlign = 'right'; - - var balance_span = document.createElement('SPAN'); - balance_span.setAttribute('name', 'balance'+<% $opt{prefix} %>rownum); - balance_span.setAttribute('id', 'balance'+<% $opt{prefix} %>rownum); - balance_span.setAttribute('rownum', <% $opt{prefix} %>rownum); - balance_cell.appendChild(balance_span); + + balance_cell.style.textAlign = 'right'; + balance_cell.appendChild(document.createTextNode('<%$money_char%>')); + + var balance_span = document.createElement('SPAN'); + balance_span.setAttribute('id', 'balance'+<% $opt{prefix} %>rownum+'_text'); + balance_span.setAttribute('rownum', <% $opt{prefix} %>rownum); + balance_cell.appendChild(balance_span); + + balance_cell.appendChild( + document.createTextNode(String.fromCharCode(160)) // + ); + + var balance_input = document.createElement('INPUT'); + balance_input.setAttribute('type', 'hidden'); + balance_input.setAttribute('name', 'balance'+<% $opt{prefix} %>rownum); + balance_input.setAttribute('id', 'balance'+<% $opt{prefix} %>rownum); + balance_input.setAttribute('rownum', <% $opt{prefix} %>rownum); + balance_cell.appendChild(balance_input); row.appendChild(balance_cell); @@ -672,19 +719,27 @@ Example: % } else { % $value = $param->{"$field$row"}; % } - var my_text = document.createTextNode('<% $value %>'); + var my_text = document.createTextNode(<% $value |js_string %>); my_cell.appendChild(my_text); % } +% my $name = (ref($field) eq 'CODE') ? "column${col}_" : $field; var my_input = document.createElement('INPUT'); - my_input.setAttribute('name', '<% $field %>'+<% $opt{prefix} %>rownum); - my_input.setAttribute('id', '<% $field %>'+<% $opt{prefix} %>rownum); + my_input.setAttribute('name', '<% $name %>'+<% $opt{prefix} %>rownum); + my_input.setAttribute('id', '<% $name %>'+<% $opt{prefix} %>rownum); my_input.style.textAlign = '<% $align{ $opt{align}->[$col] || 'l' } %>'; my_input.setAttribute('size', <% $sizes->[$col] || 10 %>); -% if ($types->[$col] eq 'immutable') { + my_input.setAttribute('rownum', <% $opt{prefix} %>rownum); +% if ( $types->[$col] eq 'immutable' ) { my_input.setAttribute('type', 'hidden'); % } -% if ( $opt{footer}->[$col] eq '_TOTAL' ) { +% elsif ( $types->[$col] eq 'checkbox' ) { + my_input.setAttribute('type', 'checkbox'); +% } +% if ( $opt{onchange}->[$col] ) { + my_input.onchange = <% $opt{onchange}->[$col] %>; +% } +% elsif ( $opt{footer}->[$col] eq '_TOTAL' ) { my_input.onchange = <% $opt{prefix} %>calc_total<%$col%>; my_input.onkeyup = <% $opt{prefix} %>calc_total<%$col%>; % } @@ -708,6 +763,11 @@ Example: + ' <% PL($opt{name_singular} || 'customer') %>'; } +% if ( $opt{add_row_callback} ) { + <% $opt{add_row_callback} %>(<% $opt{prefix} %>rownum, + '<% $opt{prefix} %>'); +% } + <% $opt{prefix} %>rownum++; } @@ -725,7 +785,7 @@ my $conf = new FS::Conf; $opt{prefix} = '' unless defined $opt{prefix}; $opt{prefix} .= '_' if $opt{prefix}; -my $types = $opt{'types'} ? [ @{$opt{'types'}} ] : []; +my $types = $opt{'type'} ? [ @{$opt{'type'}} ] : []; my $sizes = $opt{'size'} ? [ @{$opt{'size'}} ] : []; my $param = $opt{param}; @@ -742,5 +802,4 @@ my %align = ( ); my $money_char = $conf->config('money_char') || '$'; - </%init> diff --git a/httemplate/elements/form-create_ticket.html b/httemplate/elements/form-create_ticket.html new file mode 100644 index 000000000..362e82397 --- /dev/null +++ b/httemplate/elements/form-create_ticket.html @@ -0,0 +1,38 @@ +<FORM METHOD="GET" NAME="CreateTicketForm" STYLE="display:inline"> +<SCRIPT TYPE="text/javascript"> +function updateTicketLink() { + var link = document.getElementById('CreateTicketLink'); + var selector = document.getElementById('Queue') + link.href = "<% $new_base.'?'. + join(';', map( + { ($_ eq 'Queue') ? () : "$_=$new_param{$_}"} + keys %new_param),'Queue=') %>" + selector.options[selector.selectedIndex].value; +} +</SCRIPT> +<A NAME="tickets"><FONT CLASS="fsinnerbox-title">Tickets</FONT></A> +<A id="CreateTicketLink" HREF="<% $new_link %>"><% mt('Create new ticket') |h %></A> + <% mt('in queue') |h %> +%# fetch list of queues in which the user can create tickets +% my %queues = FS::TicketSystem->queues('', 'CreateTicket'); +% if( $conf->exists('ticket_system-force_default_queueid') ) { +<B><% $queues{$new_param{'Queue'}} %></B> +<INPUT TYPE="hidden" NAME="Queue" VALUE="<% $new_param{'Queue'} %>"> +% } +% else { +<SELECT NAME="Queue" id="Queue" onchange="updateTicketLink()"> +% foreach my $queueid ( sort { $queues{$a} cmp $queues{$b} } keys %queues ) { + <OPTION VALUE="<% $queueid %>" + <% $queueid == $new_param{'Queue'} ? 'SELECTED' : '' %> + ><% $queues{$queueid} |h %> +% } +</SELECT> +<SCRIPT DEFER TYPE="text/javascript">updateTicketLink();</SCRIPT> +% } +</FORM> +<%init> +my %opt = @_; +my $conf = new FS::Conf; +my $object = $opt{'object'}; # must be a cust_main, cust_svc, or svc_... +my ($new_base, %new_param) = FS::TicketSystem->href_params_new_ticket($object); +my $new_link = FS::TicketSystem->href_new_ticket($object); +</%init> diff --git a/httemplate/elements/freeside.css b/httemplate/elements/freeside.css index 44a4a3ca2..82eb9b562 100644 --- a/httemplate/elements/freeside.css +++ b/httemplate/elements/freeside.css @@ -108,8 +108,8 @@ a.fstab { -moz-border-radius-topright:8px; -webkit-border-radius-topleft:8px; -webkit-border-radius-topright:8px; - border-radius-topleft:8px; - border-radius-topright:8px; + border-top-left-radius:8px; + border-top-right-radius:8px; /*font-weight:bold;*/ /*padding-left:12px; padding-right:12px;*/ @@ -141,8 +141,8 @@ a.fstabselected { -moz-border-radius-topright:8px; -webkit-border-radius-topleft:8px; -webkit-border-radius-topright:8px; - border-radius-topleft:8px; - border-radius-topright:8px; + border-top-left-radius:8px; + border-top-right-radius:8px; /*font-weight:bold;*/ /*padding-left:12px; padding-right:12px;*/ @@ -175,8 +175,8 @@ div.fstabcontainer { -moz-border-radius-bottomright:8px; -webkit-border-radius-bottomleft:8px; -webkit-border-radius-bottomright:8px; - border-radius-bottomleft:8px; - border-radius-bottomright:8px; + border-bottom-left-radius:8px; + border-bottom-right-radius:8px; -moz-box-shadow: #666666 1px 1px 2px; -webkit-box-shadow: #666666 1px 1px 2px; box-shadow: #666666 1px 1px 2px; @@ -206,8 +206,8 @@ div.fstabcontainer { -moz-border-radius-bottomright:8px; -webkit-border-radius-bottomleft:8px; -webkit-border-radius-bottomright:8px; - border-radius-bottomleft:8px; - border-radius-bottomright:8px; + border-bottom-left-radius:8px; + border-bottom-right-radius:8px; -moz-box-shadow: #666666 1px 1px 2px; -webkit-box-shadow: #666666 1px 1px 2px; box-shadow: #666666 1px 1px 2px; @@ -238,8 +238,8 @@ div.fstabcontainer { -moz-border-radius-topright:8px; -webkit-border-radius-topleft:8px; -webkit-border-radius-topright:8px; - border-radius-topleft:8px; - border-radius-topright:8px; + border-top-left-radius:8px; + border-top-right-radius:8px; -moz-box-shadow: 1px 0px 1px #999999; -webkit-box-shadow: 1px 0px 1px #999999; box-shadow: 1px 0px 1px #999999; @@ -250,3 +250,31 @@ div.fstabcontainer { background-color:#f8f8f8; } +table.grid { + border: 1px solid #cccccc; + -moz-box-shadow: 1px 1px 2px #666666; + -webkit-box-shadow: 1px 1px 2px #666666; + box-shadow: 1px 1px 2px #666666; + filter: progid:DXImageTransform.Microsoft.Shadow(color='#666666', Direction=135, Strength=2); +} + +th.grid { + padding-left: 3px; + padding-right: 3px; + padding-bottom: 2px; + border: none; + empty-cells: show; +} + +td.grid { + padding-left: 3px; + padding-right: 3px; + padding-bottom: 2px; + border: none; + empty-cells: show; +} + +table.inv { border: none } +th.inv { border: none } +td.inv { border: none } + diff --git a/httemplate/elements/header.html b/httemplate/elements/header.html index d0ab3055d..c6ad3c387 100644 --- a/httemplate/elements/header.html +++ b/httemplate/elements/header.html @@ -42,6 +42,12 @@ Example: <% include('init_overlib.html') |n %> <% include('rs_init_object.html') |n %> <% include('logout.html') |n %> +% my $timeout = $conf->config('logout-timeout'); +% if ( $timeout && $timeout =~ /^\s*\d+\s*$/ ) { + <script type="text/javascript"> + setTimeout('logout()', <% 60000 * $timeout %>); + </script> +% } <% $head |n %> diff --git a/httemplate/elements/init_overlib.html b/httemplate/elements/init_overlib.html index d27ca3bda..986adec40 100644 --- a/httemplate/elements/init_overlib.html +++ b/httemplate/elements/init_overlib.html @@ -1,9 +1,16 @@ % for my $file (@files) { <SCRIPT TYPE="text/javascript" SRC="<%$fsurl%>elements/<%$file%>.js"></SCRIPT> % } +<%shared> +my $initialized = 0; #won't work if component is "preloaded"... so don't do that +</%shared> <%init> -my @files = map "overlibmws$_", ( '', qw( _iframe _draggable _crossframe ) ); -push @files, map { "${_}contentmws" } qw( iframe ajax ); +my @files = (); +if ( ! $initialized ) { + push @files, map "overlibmws$_", ( '', qw( _iframe _draggable _crossframe ) ); + push @files, map { "${_}contentmws" } qw( iframe ajax ); + $initialized++; +} </%init> diff --git a/httemplate/elements/location.html b/httemplate/elements/location.html index c606523f0..767231856 100644 --- a/httemplate/elements/location.html +++ b/httemplate/elements/location.html @@ -3,16 +3,16 @@ Example: include( '/elements/location.html', - 'object' => $cust_main, # or $cust_location - 'prefix' => $pre, #only for cust_main objects + 'object' => $cust_location + 'prefix' => $pre, # prefixed to form field names 'onchange' => $javascript, - 'disabled' => $disabled, - 'same_checked' => $same_checked, 'geocode' => $geocode, #passed through 'censustract' => $censustract, #passed through 'no_asterisks' => 0, #set true to disable the red asterisks next #to required fields 'address1_label' => 'Address', #label for address + 'enable_district' => 1, #show tax district field + 'enable_censustract' => 1, #show censustract field ) </%doc> @@ -40,12 +40,12 @@ Example: % } <TR> - <<%$th%> ALIGN="right"><%$r%><% $opt{'address1_label'} || emt('Address') %></<%$th%>> + <<%$th%> STYLE="width:16ex" ALIGN="right"><%$r%><% $opt{'address1_label'} || emt('Address') %></<%$th%>> <TD COLSPAN=7> <INPUT TYPE = "text" NAME = "<%$pre%>address1" ID = "<%$pre%>address1" - VALUE = "<% $object->get($pre.'address1') |h %>" + VALUE = "<% $object->get('address1') |h %>" SIZE = 54 onChange = "<% $onchange %>" <% $disabled %> @@ -62,7 +62,7 @@ Example: <INPUT TYPE = "text" NAME = "<%$pre%>address2" ID = "<%$pre%>address2" - VALUE = "<% $object->get($pre.'address2') |h %>" + VALUE = "<% $object->get('address2') |h %>" SIZE = 54 onChange = "<% $onchange %>" <% $disabled %> @@ -75,7 +75,7 @@ Example: <INPUT TYPE = "hidden" NAME = "<%$pre%>address2" - VALUE = "<% $object->get($pre.'address2') |h %>" + VALUE = "<% $object->get('address2') |h %>" > <TR> @@ -83,7 +83,7 @@ Example: <TD COLSPAN=7> % my $location_type = scalar($cgi->param('location_type')) -% || $object->get($pre.'location_type'); +% || $object->get('location_type'); % #my $location_number = scalar($cgi->param('location_number')) % # || $object->get($pre.'location_number'); % @@ -130,7 +130,7 @@ Example: <INPUT TYPE="text" NAME = "location_number" ID = "location_number" - VALUE = "<% scalar($cgi->param('location_number')) || $object->get($pre.'location_number') |h %>" + VALUE = "<% scalar($cgi->param('location_number')) || $object->get('location_number') |h %>" SIZE = "5" <% $disabled || ($location_type ? '' : 'DISABLED') %> <% $style %> @@ -161,7 +161,7 @@ Example: <INPUT TYPE = "text" NAME = "<%$pre%>zip" ID = "<%$pre%>zip" - VALUE = "<% $object->get($pre.'zip') |h %>" + VALUE = "<% $object->get('zip') |h %>" SIZE = 10 onChange = "<% $onchange %>" <% $disabled %> @@ -181,7 +181,7 @@ Example: <INPUT TYPE = "text" NAME = "<%$pre%>latitude" ID = "<%$pre%>latitude" - VALUE = "<% $object->get($pre.'latitude') |h %>" + VALUE = "<% $object->get('latitude') |h %>" <% $disabled %> <% $style %> > @@ -189,36 +189,44 @@ Example: <INPUT TYPE = "text" NAME = "<%$pre%>longitude" ID = "<%$pre%>longitude" - VALUE = "<% $object->get($pre.'longitude') |h %>" + VALUE = "<% $object->get('longitude') |h %>" <% $disabled %> <% $style %> > </TD> </TR> -<INPUT TYPE="hidden" NAME="<%$pre%>coord_auto" VALUE="<% $object->get($pre.'coord_auto') %>"> +<INPUT TYPE="hidden" NAME="<%$pre%>coord_auto" VALUE="<% $object->coord_auto %>"> -% if ( !$pre ) { - <INPUT TYPE="hidden" NAME="geocode" VALUE="<% $opt{geocode} %>"> +<INPUT TYPE="hidden" NAME="<%$pre%>geocode" VALUE="<% $object->geocode %>"> +<INPUT TYPE="hidden" NAME="<%$pre%>censusyear" VALUE="<% $object->censusyear %>"> +<TR> +% if ( $opt{enable_censustract} ) { + <TD ALIGN="right">Census tract</TD> + <TD COLSPAN=8> + <INPUT TYPE="text" SIZE=15 + NAME="<%$pre%>censustract" + VALUE="<% $object->censustract %>"> + <% '(automatic)' %> + </TD> % } else { -% if ( $pre eq 'ship_' && $conf->exists('cust_main-require_censustract') ) { - <TR><<%$th%> ALIGN="right">Census tract<BR>(automatic)</<%$th%>> - <TD> - <INPUT TYPE="text" NAME="censustract" VALUE="<% $opt{censustract} %>"> - <INPUT TYPE="hidden" NAME="censusyear" VALUE="<% $object->get('censusyear') %>"> - </TD> - </TR> + <INPUT TYPE="hidden" NAME="<%$pre%>censustract" VALUE="<% $object->censustract %>"> +% } +</TR> +% if ( $conf->config('tax_district_method') ) { + <TR> +% if ( $opt{enable_district} ) { + <TD ALIGN="right">Tax district</TD> + <TD COLSPAN=8> + <INPUT TYPE="text" SIZE=15 + NAME="<%$pre%>district" + VALUE="<% $object->district %>"> + <% '(automatic)' %> + </TD> % } else { - <INPUT TYPE="hidden" NAME="censustract" VALUE="<% $opt{censustract} %>"> -% } -% if ( $conf->config('tax_district_method') or $object->get('district') ) { - <TR> - <<%$th%> ALIGN="right">Tax district<BR>(automatic)</<%$th%>> - <TD> - <INPUT TYPE="text" NAME="district" VALUE="<%$object->get('district')%>"> - </TD> - </TR> + <INPUT TYPE="hidden" NAME="<%$pre%>district" VALUE="<% $object->district %>"> % } -% } + </TR> +% } <%init> @@ -233,16 +241,13 @@ my $conf = new FS::Conf; my $r = $opt{'no_asterisks'} ? '' : qq!<font color="#ff0000">*</font> !; -#false laziness with ship state my $countrydefault = $conf->config('countrydefault') || 'US'; -$object->set($pre.'country', $countrydefault ) - unless $object->get($pre.'country'); - -my $statedefault = $conf->config('statedefault') +my $statedefault = $conf->config('statedefault') || ($countrydefault eq 'US' ? 'CA' : ''); -$object->set($pre.'state', $statedefault ) - unless $object->get($pre.'state') - || $object->get($pre.'country') ne $countrydefault; +$object ||= FS::cust_location->new({ + 'country' => $countrydefault, + 'state' => $statedefault, +}); my $alt_err = ($opt{'alt_format'} && !$disabled) ? $object->alternize : ''; @@ -255,8 +260,8 @@ push @address2_label_style, 'visibility:hidden' || ! $conf->exists('cust_main-require_address2') || ( !$pre && !$opt{'same_checked'} ); -my @counties = counties( $object->get($pre.'state'), - $object->get($pre.'country'), +my @counties = counties( $object->get('state'), + $object->get('country'), ); my @county_style = (); push @county_style, 'display:none' # 'visibility:hidden' @@ -276,10 +281,10 @@ my $county_style = : ''; my %select_hash = ( - 'city' => $object->get($pre.'city'), - 'county' => $object->get($pre.'county'), - 'state' => $object->get($pre.'state'), - 'country' => $object->get($pre.'country'), + 'city' => $object->get('city'), + 'county' => $object->get('county'), + 'state' => $object->get('state'), + 'country' => $object->get('country'), 'prefix' => $pre, 'onchange' => $onchange, 'disabled' => $disabled, diff --git a/httemplate/elements/menu.html b/httemplate/elements/menu.html index 3b0969f5c..019afe94e 100644 --- a/httemplate/elements/menu.html +++ b/httemplate/elements/menu.html @@ -28,7 +28,7 @@ % 'width' => 300, % 'height' => 375, % 'color' => '#7e0079', -% 'scrolling' => 'no', +% #'scrolling' => 'no', % ); % $fs_popup =~ s/return false;//; function about_freeside() { @@ -106,12 +106,11 @@ $report_customers_lists{'with USPS-unvalidated addresses'} = [ $fsurl. 'search/c tie my %report_customers, 'Tie::IxHash'; $report_customers{'List customers'} = [ \%report_customers_lists, 'List customers' ] - if $curuser->access_right('List customers'); + if $curuser->access_right('List all customers'); $report_customers{'Zip code distribution'} = [ $fsurl. 'search/report_cust_main-zip.html', 'Zip codes by number of customers' ]; $report_customers{'Customer signup report'} = [ $fsurl. 'graph/report_cust_signup.html', 'New customer signups by date' ], $report_customers{'Advanced customer reports'} = [ $fsurl. 'search/report_cust_main.html', 'by status, signup date, agent, etc.' ] - if $curuser->access_right('List customers') - && $curuser->access_right('List packages'); + if $curuser->access_right('Advanced customer search'); tie my %report_invoices_open, 'Tie::IxHash', 'All open invoices' => [ $fsurl.'search/cust_bill.html?OPEN_date', 'All invoices with an unpaid balance' ], @@ -201,10 +200,10 @@ foreach my $svcdb ( FS::part_svc->svc_tables() ) { ]; } - if ( $svcdb =~ /^svc_(acct|broadband|hardware)$/ ) { $report_svc{"Advanced $lcsname reports"} = - [ $fsurl."search/report_$svcdb.html", '' ]; - } + [ $fsurl."search/report_$svcdb.html", '' ] + if $svcdb =~ /^svc_(acct|broadband|hardware)$/ + && $curuser->access_right("Services: $name: Advanced search"); if ( $svcdb eq 'svc_phone' ) { @@ -221,7 +220,8 @@ foreach my $svcdb ( FS::part_svc->svc_tables() ) { } - $report_services{$name} = [ \%report_svc, $longname ]; + $report_services{$name} = [ \%report_svc, $longname ] + if $curuser->access_right("Services: $name"); } @@ -238,9 +238,11 @@ if ( $curuser->access_right('Financial reports') ) { $report_packages{'separator2'} = ''; } $report_packages{'All customer packages'} = [ $fsurl.'search/cust_pkg.cgi?pkgnum', 'List all customer packages', ]; -$report_packages{'Package summary'} = [ $fsurl.'search/cust_pkg_summary.html', 'Show package sales summary', ]; +$report_packages{'Package summary'} = [ $fsurl.'search/cust_pkg_summary.html', 'Show package sales summary', ] + if $curuser->access_right('Summarize packages'); $report_packages{'Suspended customer packages'} = [ $fsurl.'search/cust_pkg.cgi?magic=suspended', 'List suspended packages' ]; -$report_packages{'Suspension summary'} = [ $fsurl.'search/cust_pkg_susp.html', 'Show suspension activity', ]; +$report_packages{'Suspension summary'} = [ $fsurl.'search/cust_pkg_susp.html', 'Show suspension activity', ] + if $curuser->access_right('Summarize packages'); $report_packages{'Customer packages with unconfigured services'} = [ $fsurl.'search/cust_pkg.cgi?APKG_pkgnum', 'List packages which have provisionable services' ]; $report_packages{'FCC Form 477 packages'} = [ $fsurl.'search/report_477.html', 'Summarize packages by census tract for particular types' ] if $conf->exists('cust_main-require_censustract'); @@ -251,14 +253,17 @@ tie my %report_inventory, 'Tie::IxHash', 'Inventory activity' => [ $fsurl.'search/report_h_inventory_item.html', '' ], ; -tie my %report_rating, 'Tie::IxHash', - 'RADIUS sessions' => [ $fsurl.'search/sqlradius.html', '' ], - 'Call Detail Records (CDRs)' => [ $fsurl.'search/report_cdr.html', '' ], - 'Unrateable CDRs' => [ $fsurl.'search/cdr.html?freesidestatus=failed'. - ';cdrbatchnum=_ALL_' ], - 'Time worked' => [ $fsurl.'search/report_rt_transaction.html', '' ], - 'Time worked summary' => [ $fsurl.'search/report_rt_ticket.html', '' ], -; +tie my %report_rating, 'Tie::IxHash'; +$report_rating{'RADIUS sessions'} = [ $fsurl.'search/sqlradius.html', '' ] + if $curuser->access_right("Usage: RADIUS sessions"); +$report_rating{'Call Detail Records (CDRs)'} = [ $fsurl.'search/report_cdr.html', '' ] + if $curuser->access_right("Usage: Call Detail Records (CDRs)"); +$report_rating{'Unrateable CDRs'} = [ $fsurl.'search/cdr.html?freesidestatus=failed;cdrbatchnum=_ALL_' ] + if $curuser->access_right("Usage: Unrateable CDRs"); +if ( $curuser->access_right("Usage: Time worked") ) { + $report_rating{'Time worked'} = [ $fsurl.'search/report_rt_transaction.html', '' ]; + $report_rating{'Time worked summary'} = [ $fsurl.'search/report_rt_ticket.html', '' ]; +} tie my %report_ticketing_statistics, 'Tie::IxHash', 'Tickets per day per Queue' => [ $fsurl.'rt/RTx/Statistics/CallsQueueDay', 'View the number of tickets created, resolved or deleted in a specific Queue, over the requested period of days' ], @@ -270,13 +275,14 @@ tie my %report_ticketing_statistics, 'Tie::IxHash', ; tie my %report_ticketing, 'Tie::IxHash', - 'Resolved by owner' => [ $fsurl.'rt/Tools/Reports/ResolvedByOwner.html', '' ], - 'Resolved in date range' => [ $fsurl.'rt/Tools/Reports/ResolvedByDates.html', '' ], - 'Created in date range' => [ $fsurl.'rt/Tools/Reports/CreatedByDates.html', '' ], - 'separator' => '', +# fix TimeToResolve extension? or redo in a more modern way? +# 'Resolved by owner' => [ $fsurl.'rt/Tools/Reports/ResolvedByOwner.html', '' ], +# 'Resolved in date range' => [ $fsurl.'rt/Tools/Reports/ResolvedByDates.html', '' ], +# 'Created in date range' => [ $fsurl.'rt/Tools/Reports/CreatedByDates.html', '' ], +# 'separator' => '', 'Statistics' => [ \%report_ticketing_statistics, '' ], 'separator2' => '', - 'Advanced ticket reports' => [ $fsurl.'rt/Search/Build.html', 'List tickets by any criteria' ], + 'Advanced ticket reports' => [ $fsurl.'rt/Search/Build.html?NewQuery=1', 'List tickets by any criteria' ], ; tie my %report_bill_event, 'Tie::IxHash', @@ -308,6 +314,7 @@ if($curuser->access_right('Financial reports')) { 'Daily Sales, Credits and Receipts' => [ $fsurl.'graph/report_money_time_daily.html', 'Sales, credits and receipts (broken down by day) summary graph' ], 'Sales Report' => [ $fsurl.'graph/report_cust_bill_pkg.html', 'Sales report and graph (by agent, package class and/or date range)' ], 'Rated Call Sales Report' => [ $fsurl.'graph/report_cust_bill_pkg_detail.html', 'Sales report and graph (by agent, package class, usage class and/or date range)' ], + 'Sales With Advertising Source' => [ $fsurl.'search/report_cust_bill_pkg_referral.html' ], 'Employee Commission Report' => [ $fsurl.'search/report_employee_commission.html', '' ], 'Credit Report' => [ $fsurl.'search/report_cust_credit.html', 'Credit report (by employee and/or date range)' ], 'Unapplied Credits' => [ $fsurl.'search/report_cust_credit.html?unapplied=1', 'Unapplied credit report (by type and/or date range)' ], @@ -385,10 +392,18 @@ tie my %tools_exporting, 'Tie::IxHash', 'Download database dump' => [ $fsurl. 'misc/dump.cgi', '' ], ; +tie my %tools_ticketing_articles, 'Tie::IxHash', + 'Overview' => [ $fsurl.'rt/Articles/index.html', '' ], + 'Search' => [ $fsurl.'rt/Articles/Article/Search.html', '' ], + 'Topics' => [ $fsurl.'rt/Articles/Topics.html', '' ], +; + tie my %tools_ticketing, 'Tie::IxHash', - 'Offline' => [ $fsurl.'rt/Tools/Offline.html', '' ], + 'Articles' => [ \%tools_ticketing_articles, '' ], 'My Day' => [ $fsurl.'rt/Tools/MyDay.html', '' ], - 'My Approvals' => [ $fsurl.'rt/Approvals/', '' ], + 'My Reminders' => [ $fsurl.'rt/Tools/MyReminders.html', '' ], + 'Offline' => [ $fsurl.'rt/Tools/Offline.html', '' ], + 'Approval' => [ $fsurl.'rt/Approvals/', '' ], ; $tools_ticketing{'Cron Tool'} = [ $fsurl.'rt/Developer/CronTool/', '' ] if $conf->exists('rt-crontool'); @@ -451,6 +466,7 @@ tie my %config_radius, 'Tie::IxHash', tie my %config_export_svc, 'Tie::IxHash', (); if ( $curuser->access_right('Configuration') ) { $config_export_svc{'Service definitions'} = [ $fsurl.'browse/part_svc.cgi', 'Services are items you offer to your customers' ]; + $config_export_svc{'Service classes'} = [ $fsurl.'browse/part_svc_class.html', 'Services classes are user-defined, informational types for services' ]; $config_export_svc{'Provisioning exports'} = [ $fsurl.'browse/part_export.cgi', 'Provisioning services to external machines, databases and APIs' ]; } $config_export_svc{'Dialup'} = [ \%config_dialup, '' ] @@ -504,6 +520,10 @@ tie my %config_agent, 'Tie::IxHash', 'Agent payment gateways' => [ $fsurl.'browse/payment_gateway.html', 'Credit card and electronic check processors for agent overrides' ]; ; +tie my %config_sales, 'Tie::IxHash', + 'Sales' => [ $fsurl.'browse/sales.cgi', 'Sales bring in new business.' ], +; + tie my %config_billing_rates, 'Tie::IxHash', 'Rate plans' => [ $fsurl.'browse/rate.cgi', 'Manage rate plans' ], 'Regions and prefixes' => [ $fsurl.'browse/rate_region.html', 'Manage regions and prefixes' ], @@ -539,12 +559,44 @@ if ( $curuser->access_right('Configuration') ) { $config_billing{'Credit reason types'} = [ $fsurl.'browse/reason_type.html?class=R', 'Credit reason types define groups of reasons.' ]; } +#XXX also to be unified +tie my %config_ticketing_groups, 'Tie::IxHash', + 'Select' => [ $fsurl.'rt/Admin/Groups', '' ], + 'Create' => [ $fsurl.'rt/Admin/Groups/Modify.html?Create=1', '' ], +; + +tie my %config_ticketing_queues, 'Tie::IxHash', + 'Select' => [ $fsurl.'rt/Admin/Queues', '' ], + 'Create' => [ $fsurl.'rt/Admin/Queues/Modify.html?Create=1', '' ], +; + +tie my %config_ticketing_customfields, 'Tie::IxHash', + 'Select' => [ $fsurl.'rt/Admin/CustomFields', '' ], + 'Create' => [ $fsurl.'rt/Admin/CustomFields/Modify.html?Create=1', '' ], +; + +tie my %config_ticketing_articles_classes, 'Tie::IxHash', + 'Select' => [ $fsurl.'rt/Admin/Articles/Classes/', '' ], + 'Create' => [ $fsurl.'rt/Admin/Articles/Classes/Modify.html?Create=1', '' ], +; + +tie my %config_ticketing_articles_customfields, 'Tie::IxHash', + 'Select' => [ $fsurl.'rt/Admin/CustomFields/index.html?type=RT%3A%3AClass-RT%3A%3AArticle', '' ], + 'Create' => [ $fsurl.'rt/Admin/CustomFields/Modify.html?Create=1&LookupType=RT%3A%3AClass-RT%3A%3AArticle', '' ], +; + +tie my %config_ticketing_articles, 'Tie::IxHash', + 'Classes' => [ \%config_ticketing_articles_classes, '' ], + 'Custom Fields' => [ \%config_ticketing_articles_customfields, '' ], +; + tie my %config_ticketing, 'Tie::IxHash', - 'Ticketing Users' => [ $fsurl.'rt/Admin/Users', 'View/Edit ticketing users' ], #XXX to be unified - 'Ticketing Groups' => [ $fsurl.'rt/Admin/Groups', 'View/Edit ticketing groups and group membership' ], #XXX to be unified - 'Ticketing Queues' => [ $fsurl.'rt/Admin/Queues', 'View/Edit ticketing queues and queue-specific properties' ], - 'Ticket Custom Fields' => [ $fsurl.'rt/Admin/CustomFields', 'View/Edit ticketing custom fields' ], - 'Ticketing Global' => [ $fsurl.'rt/Admin/Global', 'View/Edit ticketing configuration applicable to all queues' ], + 'Ticketing Users' => [ $fsurl.'rt/Admin/Users', 'Edit ticketing users' ], #XXX to be unified + 'Ticketing Groups' => [ \%config_ticketing_groups, 'View/Edit ticketing groups and group membership' ], #XXX to be unified + 'Ticketing Queues' => [ \%config_ticketing_queues, 'View/Edit ticketing queues and queue-specific properties' ], + 'Ticket Custom Fields' => [ \%config_ticketing_customfields, 'View/Edit ticketing custom fields' ], + 'Ticketing Global' => [ $fsurl.'rt/Admin/Global', 'View/Edit ticketing configuration applicable to all queues' ], #XXX the individual items + 'Ticketing Articles' => [ \%config_ticketing_articles, '' ], #"System Configuraiton"? useless, just makes people report errors about missing Module::Versions::Report #'Ticketing Tools' => [ $fsurl.'rt/Admin/Tools', '' ], ; @@ -554,9 +606,8 @@ tie my %config_nms, 'Tie::IxHash', tie my %config_misc, 'Tie::IxHash'; $config_misc{'Message templates'} = [ $fsurl.'browse/msg_template.html', 'Templates for customer notices' ] - if $curuser->access_right('Edit templates') - || $curuser->access_right('Edit global templates') - || $curuser->access_right('Configuration'); + if $curuser->access_right(['View templates', 'View global templates', + 'Edit templates', 'Edit global templates', ]); $config_misc{'Advertising sources'} = [ $fsurl.'browse/part_referral.html', 'Where a customer heard about your service.' ] if $curuser->access_right('Edit advertising sources') || $curuser->access_right('Edit global advertising sources'); @@ -569,6 +620,9 @@ $config_misc{'Inventory classes and inventory'} = [ $fsurl.'browse/inventory_cla || $curuser->access_right('Edit global inventory') || $curuser->access_right('Configuration'); +$config_misc{'FTP targets'} = [ $fsurl.'browse/ftp_target.html', 'FTP servers for billing and payment processing' ] + if $curuser->access_right('Configuration'); + tie my %config_menu, 'Tie::IxHash'; if ( $curuser->access_right('Configuration' ) ) { %config_menu = ( @@ -576,6 +630,7 @@ if ( $curuser->access_right('Configuration' ) ) { 'separator' => '', #its a separator! 'Employees' => [ \%config_employees, '' ], 'Resellers' => [ \%config_agent, '' ], + 'Sales People' => [ \%config_sales, '' ], 'separator2' => '', #its a separator! 'Customers' => [ \%config_cust, '' ], #or this? 'Customers and Contacts' => [ \%config_cust, '' ], @@ -620,17 +675,24 @@ my $doc_link = $conf->config('support-key') eval "use RT;" if $conf->config('ticket_system') eq 'RT_Internal'; -tie my %help_menu, 'Tie::IxHash', 'Billing documentation' => [ $doc_link, 'Freeside documentation' ]; -$help_menu{'Ticketing documentation'} = [ 'http://wiki.bestpractical.com/', 'Request Tracker Wiki' ] - if $conf->config('ticket_system') eq 'RT_Internal'; -$help_menu{'Networking monitoring documentation'} = [ 'http://torrus.org/userguide.pod.html', 'Torrus User Guide' ] - if $conf->config('network_monitoring_system') eq 'Torrus_Internal'; -$help_menu{'separator'} = ''; -$help_menu{"About Freeside v$FS::VERSION"} = [ "javascript:about_freeside()", '' ]; -$help_menu{"About RT v$RT::VERSION"} = [ 'http://www.bestpractical.com/rt', 'Request Tracker Homepage' ] - if $conf->config('ticket_system') eq 'RT_Internal'; -$help_menu{"About Torrus v1.0.9"} = [ 'http://www.torrus.org/', 'Torrus Homepage' ] #XXX manual version - if $conf->config('network_monitoring_system') eq 'Torrus_Internal'; +tie my %help_menu, 'Tie::IxHash'; +my $agentnum = $conf->config('brand-agent'); +if ( $agentnum ) { + my $company_name = $conf->config('company_name', $agentnum); + $help_menu{"About $company_name"} = [ "javascript:about_freeside()", '' ]; +} else { + $help_menu{'Billing documentation'} = [ $doc_link, 'Freeside documentation' ]; + $help_menu{'Ticketing documentation'} = [ 'http://wiki.bestpractical.com/', 'Request Tracker Wiki' ] + if $conf->config('ticket_system') eq 'RT_Internal'; + $help_menu{'Networking monitoring documentation'} = [ 'http://torrus.org/userguide.pod.html', 'Torrus User Guide' ] + if $conf->config('network_monitoring_system') eq 'Torrus_Internal'; + $help_menu{'separator'} = ''; + $help_menu{"About Freeside v$FS::VERSION"} = [ "javascript:about_freeside()", '' ]; + $help_menu{"About RT v$RT::VERSION"} = [ 'http://www.bestpractical.com/rt', 'Request Tracker Homepage' ] + if $conf->config('ticket_system') eq 'RT_Internal'; + $help_menu{"About Torrus v1.0.9"} = [ 'http://www.torrus.org/', 'Torrus Homepage' ] #XXX manual version + if $conf->config('network_monitoring_system') eq 'Torrus_Internal'; +} tie my %menu, 'Tie::IxHash'; diff --git a/httemplate/elements/order_pkg_link.html b/httemplate/elements/order_pkg_link.html new file mode 100644 index 000000000..d8aa8fd4e --- /dev/null +++ b/httemplate/elements/order_pkg_link.html @@ -0,0 +1,26 @@ +<& /elements/popup_link-cust_main.html, + 'action' => $p. 'misc/order_pkg.html', + 'label' => $opt{'label'} || emt('Order new package'), + 'actionlabel' => $opt{'actionlabel'} || emt('Order new package'), + 'color' => '#333399', + 'cust_main' => $opt{cust_main}, + 'prospect_main' => $opt{prospect_main}, + 'custnum' => $opt{custnum}, + 'prospectnum' => $opt{prospectnum}, + 'closetext' => emt('Close'), + 'width' => 960, #763, + 'height' => $height, + %optional, +&> +<%init> + +my(%opt) = @_; + +my %optional = + map { $_ => $opt{$_} } + grep $opt{$_}, + qw( lock_pkgpart lock_locationnum qualnum quotationnum svcpart ); + +my $height = $opt{'lock_locationnum'} ? 336 : 576; + +</%init> diff --git a/httemplate/elements/popup_link-cust_main.html b/httemplate/elements/popup_link-cust_main.html index 14137859f..541bb5837 100644 --- a/httemplate/elements/popup_link-cust_main.html +++ b/httemplate/elements/popup_link-cust_main.html @@ -22,7 +22,7 @@ Example: ) </%doc> -% if ( $params->{'cust_main'} ) { +% if ( $custnum || $prospectnum ) { <% include('/elements/popup_link.html', $params ) %>\ % } <%init> @@ -34,13 +34,26 @@ if (ref($_[0]) eq 'HASH') { } else { $params = { %$params, @_ }; } + +my $custnum = $params->{'cust_main'} + ? $params->{'cust_main'}->custnum + : $params->{'custnum'}; + +$params->{'action'} .= ( $params->{'action'} =~ /\?/ ? ';' : '?' ). + "custnum=$custnum" + if $custnum; + +#(maybe i should be called popup_link-cust_or_prospect_main.html now) +my $prospectnum = $params->{'prospect_main'} + ? $params->{'prospect_main'}->prospectnum + : $params->{'prospectnum'}; -$params->{'action'} .= - ( $params->{'action'} =~ /\?/ ? ';' : '?' ). - 'custnum='. $params->{'cust_main'}->custnum; +$params->{'action'} .= ( $params->{'action'} =~ /\?/ ? ';' : '?' ). + "prospectnum=$prospectnum" + if $prospectnum; $params->{'action'} .= ";$_=".$params->{$_} foreach grep $params->{$_}, - qw( lock_pkgpart lock_locationnum qualnum svcpart ); + qw( lock_pkgpart lock_locationnum qualnum quotationnum svcpart ); </%init> diff --git a/httemplate/elements/progress-init.html b/httemplate/elements/progress-init.html index 2ec248e32..7a282a34c 100644 --- a/httemplate/elements/progress-init.html +++ b/httemplate/elements/progress-init.html @@ -54,10 +54,7 @@ sub process_whatever { #class method ) %> -% if (!$noinit) { <& /elements/init_overlib.html &> -% $noinit = 1; -% } <SCRIPT TYPE="text/javascript"> @@ -117,9 +114,6 @@ function <%$key%>myCallback( jobnum ) { </SCRIPT> -<%once> -my $noinit = 0; -</%once> <%init> my( $formname, $fields, $action, $url_or_message, $key ) = @_; diff --git a/httemplate/elements/searchbar-ticket.html b/httemplate/elements/searchbar-ticket.html index 774ca9875..30624f7d3 100644 --- a/httemplate/elements/searchbar-ticket.html +++ b/httemplate/elements/searchbar-ticket.html @@ -2,7 +2,7 @@ <FORM ACTION="<% FS::TicketSystem->baseurl %>index.html" METHOD="GET" STYLE="margin:0"> <INPUT NAME="q" TYPE="text" VALUE="<% $ticketing_label |n %>" STYLE="width:<% $width %>" onFocus="clearhint_search_ticket(this);" onClick="clearhint_search_ticket(this);" CLASS="fstext"><BR> - <A HREF="<% FS::TicketSystem->baseurl %>Search/Build.html" CLASS="fslink" STYLE="font-size:11px"><% mt('Advanced') |h %></A> + <A HREF="<% FS::TicketSystem->baseurl %>Search/Build.html?NewQuery=1" CLASS="fslink" STYLE="font-size:11px"><% mt('Advanced') |h %></A> <INPUT TYPE="submit" VALUE="<% mt('Search tickets') |h %>" CLASS="fsblackbutton" onMouseOver="this.className='fsblackbuttonselected'; return true;" onMouseOut="this.className='fsblackbutton'; return true;" STYLE="font-size:11px"> </FORM> <% $menu_position eq 'left' ? '<BR>' : '' %> diff --git a/httemplate/elements/select-cust-part_pkg.html b/httemplate/elements/select-cust-part_pkg.html index 731beae2a..2d4cd183d 100644 --- a/httemplate/elements/select-cust-part_pkg.html +++ b/httemplate/elements/select-cust-part_pkg.html @@ -27,9 +27,9 @@ Example: my( %opt ) = @_; -my $cust_main = $opt{'cust_main'} - or die "cust_main not specified"; +my $cust_or_prospect_main = $opt{'cust_main'} || $opt{'prospect_main'} + or die "neither cust_main nor prospect_main specified"; -$opt{'extra_sql'} .= ' AND '. FS::part_pkg->agent_pkgs_sql( $cust_main->agent ); +$opt{'extra_sql'} .= ' AND '. FS::part_pkg->agent_pkgs_sql( $cust_or_prospect_main->agent ); </%init> diff --git a/httemplate/elements/select-part_svc_class.html b/httemplate/elements/select-part_svc_class.html new file mode 100644 index 000000000..280e3e17d --- /dev/null +++ b/httemplate/elements/select-part_svc_class.html @@ -0,0 +1,22 @@ +<% include( '/elements/select-table.html', + 'table' => 'part_svc_class', + 'name_col' => 'classname', + 'value' => $classnum, + 'empty_label' => '(none)', + 'hashref' => \%hash, + %opt, + ) +%> +<%init> + +my %opt = @_; +my $classnum = $opt{'curr_value'} || $opt{'value'}; + +my %hash = (); +$hash{'disabled'} = '' unless $opt{'showdisabled'}; + + +$opt{'records'} = delete $opt{'part_svc_class'} + if $opt{'part_svc_class'}; + +</%init> diff --git a/httemplate/elements/select-rt-customfield.html b/httemplate/elements/select-rt-customfield.html new file mode 100644 index 000000000..7a45bb14b --- /dev/null +++ b/httemplate/elements/select-rt-customfield.html @@ -0,0 +1,34 @@ +<SELECT NAME="<% $opt{name} %>"> +% while ( @fields ) { +<OPTION VALUE="<% shift @fields %>"><% shift @fields %></OPTION> +% } +</SELECT> +<%once> +RT::Init(); +</%once> +<%init> +my %opt = @_; +my $lookuptype = $opt{lookuptype}; +my $valuetype = $opt{valuetype}; +# get a list of TimeValue-type custom fields +my $CurrentUser = RT::CurrentUser->new(); +$CurrentUser->LoadByName($FS::CurrentUser::CurrentUser->username); +die "RT not configured" unless $CurrentUser->id; +my $CFs = RT::CustomFields->new($CurrentUser); + +$CFs->Limit(FIELD => 'LookupType', + OPERATOR => 'ENDSWITH', + VALUE => $lookuptype) + if $lookuptype; + +$CFs->Limit(FIELD => 'Type', + VALUE => $valuetype) + if $valuetype; + +my @fields; +push @fields, '', $opt{empty_label} if exists($opt{empty_label}); + +while (my $CF = $CFs->Next) { + push @fields, $CF->Name, ($CF->Description || $CF->Name); +} +</%init> diff --git a/httemplate/elements/select-table.html b/httemplate/elements/select-table.html index c0dde7414..127028ee5 100644 --- a/httemplate/elements/select-table.html +++ b/httemplate/elements/select-table.html @@ -93,10 +93,17 @@ Example: % ) % { % my $recvalue = $record->$key(); +% my $selected; +% if ( $opt{'all_selected'} ) { +% $selected = 1; +% } elsif ( $opt{'compare_sub'} && !ref($value) ) { +% $selected = &{ $opt{'compare_sub'} }( $value, $recvalue ); +% } else { +% $selected = ( ref($value) && $value->{$recvalue} ) +% || ( $value && $value eq $recvalue ); #not == because of value_col +% } <OPTION VALUE="<% $recvalue %>" - <% $opt{'all_selected'} || ref($value) && $value->{$recvalue} || $value && $value eq $recvalue # not == because of value_col - ? ' SELECTED' : '' - %> + <% $selected ? ' SELECTED' : '' %> % foreach my $att ( @{ $opt{'extra_option_attributes'} } ) { data-<% $att %>="<% $record->$att() |h %>" % } diff --git a/httemplate/elements/standardize_locations.js b/httemplate/elements/standardize_locations.js index e6a4aa607..86f8d2be8 100644 --- a/httemplate/elements/standardize_locations.js +++ b/httemplate/elements/standardize_locations.js @@ -10,7 +10,7 @@ function standardize_locations() { 'onlyship', 1, % } else { % if ( $withfirm ) { - 'company', cf.elements['<% $main_prefix %>company'].value, + 'company', cf.elements['company'].value, % } 'address1', cf.elements['<% $main_prefix %>address1'].value, 'address2', cf.elements['<% $main_prefix %>address2'].value, @@ -18,9 +18,6 @@ function standardize_locations() { 'state', state_el.options[ state_el.selectedIndex ].value, 'zip', cf.elements['<% $main_prefix %>zip'].value, % } -% if ( $withfirm ) { - 'ship_company', cf.elements['<% $ship_prefix %>company'].value, -% } 'ship_address1', cf.elements['<% $ship_prefix %>address1'].value, 'ship_address2', cf.elements['<% $ship_prefix %>address2'].value, 'ship_city', cf.elements['<% $ship_prefix %>city'].value, diff --git a/httemplate/elements/table-grid.html b/httemplate/elements/table-grid.html index 4d7deeaa4..4f4200570 100644 --- a/httemplate/elements/table-grid.html +++ b/httemplate/elements/table-grid.html @@ -1,15 +1,4 @@ -<STYLE TYPE="text/css"> - -.grid TH { padding-left: 3px; padding-right: 3px; padding-bottom: 2px; border: none; empty-cells: show } -.grid TD { padding-left: 3px; padding-right: 3px; padding-bottom: 2px; border: none; empty-cells: show } - -.inv table { border: none } -.inv TH { border: none } -.inv TD { border: none } - -</STYLE> - -<TABLE CLASS="grid" CELLSPACING=<% $opt{cellspacing} %> CELLPADDING=<% $opt{cellpadding} %> <% $opt{bgcolor} %> STYLE="border: 1px solid #cccccc;"> +<TABLE CLASS="grid" CELLSPACING=<% $opt{cellspacing} %> CELLPADDING=<% $opt{cellpadding} %> <% $opt{bgcolor} %>> <%init> diff --git a/httemplate/elements/table-tickets.html b/httemplate/elements/table-tickets.html new file mode 100644 index 000000000..6d1a45a0d --- /dev/null +++ b/httemplate/elements/table-tickets.html @@ -0,0 +1,159 @@ +<& /elements/form-create_ticket.html, object => $object &> + | +View +<A HREF="<% $open_link %>"><% mt($openlabel) |h %></A> | +<A HREF="<% $res_link %>"><% mt('resolved') |h %></A> + <BR> + +<& /elements/table-grid.html &> +% my $bgcolor1 = '#eeeeee'; +% my $bgcolor2 = '#ffffff'; +% my $bgcolor = ''; + +<TR> + <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('#') |h %></TH> + <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Subject') |h %></TH> + <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Status') |h %></TH> + <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Queue') |h %></TH> + <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Owner') |h %></TH> + <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Due') |h %></TH> + <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Estimated Time') |h %></TH> + <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Priority') |h %></TH> +% if ( $ss_priority ) { + <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Customer Priority') |h %></TH> +% } +% if ( $object->isa('FS::cust_main') ) { + <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Service') |h %></TH> +% } +</TR> + +% foreach my $ticket ( @tickets ) { +% my $href = FS::TicketSystem->href_ticket($ticket->{id}); +% if ( $bgcolor eq $bgcolor1 ) { +% $bgcolor = $bgcolor2; +% } else { +% $bgcolor = $bgcolor1; +% } + + <TR> + + <TD CLASS="grid" BGCOLOR="<% $bgcolor %>"> + <A HREF=<%$href%>><% $ticket->{id} %></A> + </TD> + + <TD CLASS="grid" BGCOLOR="<% $bgcolor %>"> + <A HREF=<%$href%>><% $ticket->{subject} %></A> + </TD> + + <TD CLASS="grid" BGCOLOR="<% $bgcolor %>"> + <% $ticket->{status} %> + </TD> + + <TD CLASS="grid" BGCOLOR="<% $bgcolor %>"> + <% $ticket->{queue} %> + </TD> + + <TD CLASS="grid" BGCOLOR="<% $bgcolor %>"> + <% $ticket->{owner} %> + </TD> + + <TD CLASS="grid" BGCOLOR="<% $bgcolor %>"> + <% $date_formatter->($ticket->{due}) %> + </TD> + + <TD ALIGN="right" CLASS="grid" BGCOLOR="<% $bgcolor %>"> + <% $ticket->{timeestimated} %> + </TD> + + <TD ALIGN="right" CLASS="grid" BGCOLOR="<% $bgcolor %>"> + <% $ticket->{content} + ? $ticket->{content}.' ('.$ticket->{priority}.')' + : $ticket->{priority} + %> + </TD> + +% if ( $ss_priority ) { + <TD ALIGN="right" CLASS="grid" BGCOLOR="<% $bgcolor %>"> + <% $ticket->{"CF.{$ss_priority}"} %> + </TD> +% } +% if ( $object->isa('FS::cust_main') ) { + <TD CLASS="grid" BGCOLOR="<% $bgcolor %>"><FONT SIZE=-1><B> +% foreach (@{ $ticket->{svcnums} }) { +% my $cust_svc = FS::cust_svc->by_key($_) or next; + <% FS::UI::Web::svc_label_link($m, $cust_svc->part_svc, $cust_svc) %> + <BR> +% } + </B></FONT></TD> +% } + + </TR> + +% } + +</TABLE> + +<%init> +use Date::Parse qw(str2time); +use Date::Format qw(time2str); + +my %opt = @_; +my $conf = new FS::Conf; + +my $object = $opt{'object'}; +$object = $object->cust_svc if $object->isa('FS::svc_Common'); +my( @tickets ) = $object->tickets; + +my ($openlabel, $open_link, $res_link, $thing); +$openlabel = join('/', FS::TicketSystem->statuses ); + +# not the nicest way to do this--FS::has_tickets_Common? +if ( $object->isa('FS::cust_main') ) { + $thing = 'customer'; + $open_link = FS::TicketSystem->href_customer_tickets($object->custnum); + + $res_link = FS::TicketSystem->href_customer_tickets( + $object->custnum, + { 'statuses' => [ 'resolved' ] } + ); +} +elsif ( $object->isa('FS::cust_svc') ) { + $thing = 'service'; + $open_link = FS::TicketSystem->href_service_tickets($object->svcnum); + + $res_link = FS::TicketSystem->href_service_tickets( + $object->svcnum, + { 'statuses' => [ 'resolved' ] } + ); +} + +my $ss_priority = FS::TicketSystem->selfservice_priority; +if ( $ss_priority ) { + my $dir = $conf->exists('ticket_system-priority_reverse') ? -1 : 1; + use sort 'stable'; + # sort in the following way: + @tickets = sort { + # within a severity level... + ( $a->{'content'} eq $b->{'content'} ) ? ( + # no-priority tickets sort last + ( + ($a->{'_selfservice_priority'} eq '') <=> + ($b->{'_selfservice_priority'} eq '') + ) || + # otherwise obey ticket_system-priority_reverse + ( $dir * + ($b->{'_selfservice_priority'} <=> $a->{'_selfservice_priority'}) + ) + ) : 0; # but don't rearrange between severity levels + } @tickets; +} + +my $format = $conf->config('date_format') || '%Y-%m-%d'; + +my $date_formatter = sub { + my $time = str2time($_[0], 'GMT'); + # exclude times within 24 hours of zero + ($time > 86400) ? time2str($format, $time) : ''; +}; + +</%init> diff --git a/httemplate/elements/tr-cust_svc.html b/httemplate/elements/tr-cust_svc.html index ca5de86b4..1ca22f6d4 100644 --- a/httemplate/elements/tr-cust_svc.html +++ b/httemplate/elements/tr-cust_svc.html @@ -24,7 +24,7 @@ Usage: <TD ALIGN="right" VALIGN="top"><% FS::UI::Web::svc_link($m, $part_svc, $cust_svc) %></TD> - <TD STYLE="padding-bottom:0px"><B><% + <TD STYLE="padding-bottom:0px"><B><% $cust_svc->agent_svcid ? $cust_svc->agent_svcid.': ' : '' %><% FS::UI::Web::svc_label_link($m, $part_svc, $cust_svc) %></B></TD> <TD ALIGN="right"><% FS::UI::Web::svc_export_links($m, $part_svc, $cust_svc) %> diff --git a/httemplate/elements/tr-fixed-cust_main.html b/httemplate/elements/tr-fixed-cust_main.html new file mode 100644 index 000000000..00bcb66d8 --- /dev/null +++ b/httemplate/elements/tr-fixed-cust_main.html @@ -0,0 +1,15 @@ +% if ( $cust_main ) { + <% include('tr-fixed.html', %opt ) %> +% } +<%init> + +my %opt = @_; + +my $value = $opt{'curr_value'} || $opt{'value'}; + +my $cust_main = $value ? qsearchs('cust_main', {custnum=>$value} ) + : ''; + +$opt{'formatted_value'} = $cust_main->name if $cust_main; + +</%init> diff --git a/httemplate/elements/tr-fixed-date.html b/httemplate/elements/tr-fixed-date.html new file mode 100644 index 000000000..716e5ceb8 --- /dev/null +++ b/httemplate/elements/tr-fixed-date.html @@ -0,0 +1,13 @@ +<% include('tr-fixed.html', %opt ) %> +<%init> + +my %opt = @_; + +my $value = $opt{'curr_value'} || $opt{'value'}; + +my $conf = new FS::Conf; +my $date_format = $conf->config('date_format') || '%m/%d/%Y'; + +$opt{'formatted_value'} = time2str($date_format, $value); + +</%init> diff --git a/httemplate/elements/tr-fixed-prospect_main.html b/httemplate/elements/tr-fixed-prospect_main.html new file mode 100644 index 000000000..8da0ffb84 --- /dev/null +++ b/httemplate/elements/tr-fixed-prospect_main.html @@ -0,0 +1,15 @@ +% if ( $prospect_main ) { + <% include('tr-fixed.html', %opt ) %> +% } +<%init> + +my %opt = @_; + +my $value = $opt{'curr_value'} || $opt{'value'}; + +my $prospect_main = $value ? qsearchs('prospect_main', {prospectnum=>$value} ) + : ''; + +$opt{'formatted_value'} = $prospect_main->name if $prospect_main; + +</%init> diff --git a/httemplate/elements/tr-fixed.html b/httemplate/elements/tr-fixed.html index f358343dd..dd07d90b6 100644 --- a/httemplate/elements/tr-fixed.html +++ b/httemplate/elements/tr-fixed.html @@ -13,13 +13,15 @@ my %opt = @_; my $style = $opt{'cell_style'} ? 'STYLE="'. $opt{'cell_style'}. '"' : ''; my $value = $opt{'formatted_value'} || $opt{'curr_value'} || $opt{'value'}; -#compatibility with select-table and friends -if ( $opt{'multiple'} ) { - $value = [ split(/\s*,\s*/, $value) ] if !ref $value; - $value = join('<BR>', map {encode_entities($_)} @$value); -} -else { - $value = encode_entities($value) + +unless ( $opt{'noescape'} ) { + #compatibility with select-table and friends + if ( $opt{'multiple'} ) { + $value = [ split(/\s*,\s*/, $value) ] if !ref $value; + $value = join('<BR>', map {encode_entities($_)} @$value); + } else { + $value = encode_entities($value) + } } </%init> diff --git a/httemplate/elements/tr-select-agent.html b/httemplate/elements/tr-select-agent.html index ce03c40f5..321bd6b32 100644 --- a/httemplate/elements/tr-select-agent.html +++ b/httemplate/elements/tr-select-agent.html @@ -22,7 +22,7 @@ Example: ); </%doc> -% if ( scalar(@agents) == 1 ) { +% if ( scalar(@agents) == 1 || $opt{'fixed'} ) { <INPUT TYPE = "hidden" NAME = "<% $opt{'field'} || 'agentnum' %>" @@ -30,9 +30,20 @@ Example: VALUE = "<% $agents[0]->agentnum %>" > -%# YUCK. empty row so we don't throw g_row in edit.html off :/ - <TR> - </TR> +% if ( scalar(@agents) != 1 ) { + <TR> + <TD ALIGN="right"><% $opt{'label'} || emt('Agent') %></TD> + <TD BGCOLOR="#dddddd" <% $colspan %>> +% my $agent = qsearchs('agent', { 'agentnum' => $agentnum }); + <% $agent ? $agent->agent : '(all)' |h %> + </TD> + </TR> + +% } else { # YUCK. empty row so we don't throw g_row in edit.html off :/ + <TR> + </TR> +% } +% % } else { <TR> diff --git a/httemplate/elements/tr-select-cust-part_pkg.html b/httemplate/elements/tr-select-cust-part_pkg.html index 767d23264..848ab0a4b 100644 --- a/httemplate/elements/tr-select-cust-part_pkg.html +++ b/httemplate/elements/tr-select-cust-part_pkg.html @@ -51,8 +51,11 @@ } - get_part_pkg( <% $cust_main->custnum %>, classnum, update_part_pkg ); - + get_part_pkg( <% $cust_main ? $cust_main->custnum : '0' %>, + <% $prospect_main ? $prospect_main->prospectnum : '0' %>, + classnum, + update_part_pkg + ); } </SCRIPT> @@ -74,10 +77,11 @@ <TH ALIGN="right"><% mt('Package') |h %></TH> <TD COLSPAN=7> <& /elements/select-cust-part_pkg.html, - 'curr_value' => $opt{'curr_value'}, #$pkgpart - 'classnum' => $opt{'classnum'}, - 'cust_main' => $opt{'cust_main'}, #$cust_main - 'onchange' => 'pkg_changed', + 'curr_value' => $opt{'curr_value'}, #$pkgpart + 'classnum' => $opt{'classnum'}, + 'cust_main' => $opt{'cust_main'}, #$cust_main + 'prospect_main' => $opt{'prospect_main'}, #$prospect_main + 'onchange' => 'pkg_changed', &> </TD> </TR> @@ -91,8 +95,13 @@ my %opt = @_; my $pre_label = $opt{'pre_label'} || ''; $pre_label .= ' ' if length($pre_label) && $pre_label =~ /\S$/; -my $cust_main = $opt{'cust_main'} - or die "cust_main not specified"; +my $cust_main = $opt{'cust_main'}; +my $prospect_main = $opt{'prospect_main'}; + +die "neither cust_main nor prospect_main specified" + unless $cust_main || $prospect_main; + +my $agent = $cust_main ? $cust_main->agent : $prospect_main->agent; #"normal" part_pkg agent virtualization (agentnum or type) my @part_pkg = qsearch({ @@ -101,7 +110,7 @@ my @part_pkg = qsearch({ 'hashref' => { 'disabled' => '' }, 'extra_sql' => ' AND '. $FS::CurrentUser::CurrentUser->agentnums_sql( 'null'=>1 ). - ' AND '. FS::part_pkg->agent_pkgs_sql( $opt{'cust_main'}->agent ), + ' AND '. FS::part_pkg->agent_pkgs_sql( $agent ), }); my @pkg_class = diff --git a/httemplate/elements/tr-select-cust_location.html b/httemplate/elements/tr-select-cust_location.html index 0ca255b3e..d9e3e9e27 100644 --- a/httemplate/elements/tr-select-cust_location.html +++ b/httemplate/elements/tr-select-cust_location.html @@ -11,7 +11,6 @@ Example: #optional 'empty_label' => '(default service address)', - 'disable_empty' => 0, #1 to disable ) </%doc> @@ -52,11 +51,12 @@ Example: var ftype = what.form.<%$_%>.tagName; if( ftype != 'SELECT') what.form.<%$_%>.style.backgroundColor = '#ffffff'; % } - +% if ( $opt{'alt_format'} ) { if ( what.form.location_type.options[what.form.location_type.selectedIndex].value ) { what.form.location_number.disabled = false; what.form.location_number.style.backgroundColor = '#ffffff'; } +% } } function locationnum_changed(what) { @@ -101,25 +101,8 @@ Example: return; } - if ( locationnum == 0 ) { //(default service address) -% if ( $cust_main ) { - what.form.address1.value = <% $cust_main->get($prefix.'address1') |js_string %>; - what.form.address2.value = <% $cust_main->get($prefix.'address2') |js_string %>; - what.form.city.value = <% $cust_main->get($prefix.'city') |js_string %>; - what.form.zip.value = <% $cust_main->get($prefix.'zip') |js_string %>; - - changeSelect(what.form.country, <% $cust_main->get($prefix.'country') | js_string %> ); - - country_changed( what.form.country, - fix_state_factory( <% $cust_main->get($prefix.'state') | js_string %>, - <% $cust_main->get($prefix.'county') | js_string %> - ) - ); -% } - - } else { - get_location( locationnum, update_location ); - } +%# default service address is now just another location + get_location( locationnum, update_location ); % if ( $editable ) { if ( locationnum == 0 ) { @@ -203,14 +186,16 @@ Example: ID = "locationnum" onChange = "locationnum_changed(this);" > -% if ( !$prospect_main && !$opt{'disable_empty'} ) { - <OPTION VALUE=""><% $opt{'empty_label'} || '(default service address)' |h %> +% if ( $cust_main ) { + <OPTION VALUE="<% $cust_main->ship_locationnum %>"><% $opt{'empty_label'} || '(default service address)' |h %> % } % if ( $opt{'is_optional'} ) { <OPTION VALUE="-2" <% $locationnum == -2 ? 'SELECTED' : ''%>><% $opt{'optional_label'} || '(not required)' |h %> % } % % foreach my $loc ( @cust_location ) { +% # don't show the ship_location redundantly +% next if $cust_main && $cust_main->ship_locationnum == $loc->locationnum; <OPTION VALUE="<% $loc->locationnum %>" <% $locationnum == $loc->locationnum ? 'SELECTED' : '' %> ><% $loc->line |h %> @@ -233,7 +218,9 @@ Example: 'alt_format' => $opt{'alt_format'}, ) %> - +<SCRIPT TYPE="text/javascript"> + locationnum_changed(document.getElementById('locationnum')); +</SCRIPT> <%init> my $conf = new FS::Conf; @@ -246,8 +233,7 @@ my $cgi = $opt{'cgi'}; my $cust_pkg = $opt{'cust_pkg'}; my $cust_main = $opt{'cust_main'}; my $prospect_main = $opt{'prospect_main'}; - -my $prefix = ($cust_main && length($cust_main->ship_last)) ? 'ship_' : ''; +die "cust_main or prospect_main required" unless $cust_main or $prospect_main; my $locationnum = ''; if ( $cgi->param('error') ) { @@ -259,9 +245,9 @@ if ( $cgi->param('error') ) { } elsif ($prospect_main) { my @cust_location = $prospect_main->cust_location; $locationnum = $cust_location[0]->locationnum if scalar(@cust_location)==1; - } else { #? + } else { #$cust_main $cgi->param('locationnum') =~ /^(\-?\d*)$/ or die "illegal locationnum"; - $locationnum = $1; + $locationnum = $1 || $cust_main->ship_locationnum; } } @@ -277,7 +263,7 @@ if ( $opt{'alt_format'} ) { push @location_fields, qw( location_type location_number location_kind ); } -my $cust_location; +my $cust_location; #the one that shows by default in the location edit space if ( $locationnum && $locationnum > 0 ) { $cust_location = qsearchs('cust_location', { 'locationnum' => $locationnum } ) or die "unknown locationnum"; @@ -290,7 +276,7 @@ if ( $locationnum && $locationnum > 0 ) { $cust_location->$_( $pkg_location->$_ ) foreach @location_fields; $opt{'empty_label'} ||= 'package address: '.$pkg_location->line; } elsif ( $cust_main ) { - $cust_location->$_( $cust_main->get($prefix.$_) ) foreach @location_fields; + $cust_location = $cust_main->ship_location; #I think } } @@ -301,7 +287,7 @@ my $location_sort = sub { or lc($a->address2) cmp lc($b->address2) }; -my @cust_location = (); +my @cust_location; push @cust_location, $cust_main->cust_location if $cust_main; push @cust_location, $prospect_main->cust_location if $prospect_main; push @cust_location, $cust_location @@ -311,14 +297,14 @@ push @cust_location, $cust_location @cust_location = sort $location_sort grep !$_->disabled, @cust_location; $cust_location = $cust_location[0] - if ( $prospect_main || $opt{'disable_empty'} ) + if ( $prospect_main ) && !$opt{'is_optional'} && @cust_location; my $disabled = ( $locationnum < 0 || ( $editable && $locationnum ) - || ( ( $prospect_main || $opt{'disable_empty'} ) + || ( $prospect_main && !$opt{'is_optional'} && !@cust_location && $addnew ) ) diff --git a/httemplate/elements/tr-select-cust_tag.html b/httemplate/elements/tr-select-cust_tag.html index b2b6d967e..5312644ef 100644 --- a/httemplate/elements/tr-select-cust_tag.html +++ b/httemplate/elements/tr-select-cust_tag.html @@ -28,7 +28,7 @@ my $cgi = $opt{'cgi'}; my $is_report = $opt{'is_report'}; my @curr_tagnum = (); -if ( $cgi->param('error') ) { +if ( $cgi && $cgi->param('error') ) { @curr_tagnum = $cgi->param('tagnum'); } elsif ( $opt{'custnum'} ) { @curr_tagnum = map $_->tagnum, diff --git a/httemplate/elements/tr-select-from_to.html b/httemplate/elements/tr-select-from_to.html index 100381234..a27412f99 100644 --- a/httemplate/elements/tr-select-from_to.html +++ b/httemplate/elements/tr-select-from_to.html @@ -39,7 +39,7 @@ my %hash = ( 'show_month_abbr' => 1, 'start_year' => '1999', - 'end_year' => '2012', #haha, well... + 'end_year' => '2013', #haha, well... @_, ); </%init> diff --git a/httemplate/elements/tr-select-part_svc_class.html b/httemplate/elements/tr-select-part_svc_class.html new file mode 100644 index 000000000..2f4b09381 --- /dev/null +++ b/httemplate/elements/tr-select-part_svc_class.html @@ -0,0 +1,27 @@ +% if ( scalar(@{ $opt{'part_svc_class'} }) == 0 ) { + + <INPUT TYPE="hidden" NAME="<% $opt{'element_name'} || $opt{'field'} || 'classnum' %>" VALUE=""> + +% } else { + + <TR> + <TD ALIGN="right"><% $opt{'label'} || 'Service class' %></TD> + <TD> + <% include( '/elements/select-part_svc_class.html', + 'curr_value' => $classnum, + %opt + ) + %> + </TD> + </TR> + +% } + +<%init> + +my %opt = @_; +my $classnum = $opt{'curr_value'} || $opt{'value'}; + +$opt{'part_svc_class'} ||= [ qsearch( 'part_svc_class', { disabled=>'' } ) ]; + +</%init> diff --git a/httemplate/elements/tr-select-router_block_ip.html b/httemplate/elements/tr-select-router_block_ip.html index ed8fe810f..95d1787b8 100644 --- a/httemplate/elements/tr-select-router_block_ip.html +++ b/httemplate/elements/tr-select-router_block_ip.html @@ -1,23 +1,34 @@ <script type="text/javascript"> var manual_addr_routernum = <% encode_json(\%manual_addr_routernum) %>; var ip_addr_curr_value = <% $opt{'ip_addr'} |js_string %>; -function lock_ip_addr(obj, i) { - var routernum = obj.value; - var select_blocknum = document.getElementsByName('blocknum')[0]; +var blocknum_curr_value = <% $opt{'blocknum'} |js_string %>; +function update_ip_addr(obj, i) { + var routernum = document.getElementById('router_select_0').value; + var select_blocknum = document.getElementById('router_select_1'); + var blocknum = select_blocknum.value; var input_ip_addr = document.getElementById('input_ip_addr'); if ( manual_addr_routernum[routernum] == 'Y' ) { -%# enable ip_addr, default it to its previous value, and hide block selection +%# hide block selection and default ip address to its previous value select_blocknum.style.display = 'none'; input_ip_addr.value = ip_addr_curr_value; - input_ip_addr.disabled = false; } else { %# the reverse select_blocknum.style.display = ''; - input_ip_addr.disabled = true; - input_ip_addr.value = '(automatic)'; +%# default ip address to null, unless the router/block are set to the +%# previous value, in which case default it to current value + if ( routernum == router_curr_values[0] && + blocknum == router_curr_values[1] ) { + input_ip_addr.value = ip_addr_curr_value; + } else { + input_ip_addr.value = <% mt('(automatic)') |js_string %>; + } } } +function clearhint_ip_addr (what) { + if ( what.value == <% mt('(automatic)') |js_string %> ) + what.value = ''; +} </script> <& /elements/tr-td-label.html, label => ($opt{'label'} || 'Router') &> <td> @@ -27,7 +38,7 @@ function lock_ip_addr(obj, i) { records => \@routers, name_col => 'routername', value_col => 'routernum', - onchange => 'lock_ip_addr', + onchange => 'update_ip_addr', curr_value=> $opt{'routernum'}, }, { @@ -39,6 +50,7 @@ function lock_ip_addr(obj, i) { name_col => 'cidr', link_col => 'routernum', empty_label => '(any)', + onchange => 'update_ip_addr', curr_value => $opt{'blocknum'}, }, ] @@ -52,12 +64,11 @@ function lock_ip_addr(obj, i) { % } % else { <input type="text" id="input_ip_addr" name="ip_addr" - value="<% $opt{'ip_addr'} |h%>"> + value="<% $opt{'ip_addr'} |h%>" onfocus="clearhint_ip_addr(this)"> % } </td> </tr> -<input type="hidden" name="prev_ip_addr" value="<% $opt{'ip_addr'} |h%>"> <script type="text/javascript"> -lock_ip_addr(document.getElementsByName('routernum')[0],0); +update_ip_addr(); </script> <%init> diff --git a/httemplate/elements/xmenu.css b/httemplate/elements/xmenu.css index 73699b6f9..e6a39f675 100644 --- a/httemplate/elements/xmenu.css +++ b/httemplate/elements/xmenu.css @@ -20,7 +20,7 @@ .webfx-menu { position: absolute; - z-index: 100; + z-index: 9999; visibility: hidden; border: 1px solid #7e0079; -moz-border-radius: 4px; diff --git a/httemplate/elements/xmenu.top.css b/httemplate/elements/xmenu.top.css index ff0d6f684..7a42254e4 100644 --- a/httemplate/elements/xmenu.top.css +++ b/httemplate/elements/xmenu.top.css @@ -20,7 +20,7 @@ .webfx-menu { position: absolute; - z-index: 100; + z-index: 9999; visibility: hidden; border: 1px solid #7e0079; -moz-border-radius: 4px; |
