summaryrefslogtreecommitdiff
path: root/httemplate/elements
diff options
context:
space:
mode:
Diffstat (limited to 'httemplate/elements')
-rw-r--r--httemplate/elements/auto-table.html63
-rw-r--r--httemplate/elements/change_history_common.html15
-rw-r--r--httemplate/elements/change_password.html41
-rw-r--r--httemplate/elements/checkbox-tristate.html78
-rw-r--r--httemplate/elements/contact.html6
-rw-r--r--httemplate/elements/dashboard-toplist.html3
-rw-r--r--httemplate/elements/fckeditor/fckeditor.js2
-rw-r--r--httemplate/elements/location.html7
-rw-r--r--httemplate/elements/menu.html23
-rw-r--r--httemplate/elements/order_pkg.js1
-rw-r--r--httemplate/elements/progress-init.html2
-rw-r--r--httemplate/elements/random_pass.html17
-rw-r--r--httemplate/elements/search-svc_broadband.html204
-rw-r--r--httemplate/elements/select-areacode.html4
-rw-r--r--httemplate/elements/select-did.html167
-rw-r--r--httemplate/elements/select-exchange.html4
-rw-r--r--httemplate/elements/select-mac.html2
-rw-r--r--httemplate/elements/select-part_svc.html5
-rw-r--r--httemplate/elements/select-phonenum.html4
-rw-r--r--httemplate/elements/select-region.html4
-rw-r--r--httemplate/elements/select-table.html3
-rw-r--r--httemplate/elements/select-tiered.html7
-rw-r--r--httemplate/elements/selectlayers.html2
-rw-r--r--httemplate/elements/standardize_locations.js51
-rw-r--r--httemplate/elements/tr-cust_svc.html3
-rw-r--r--httemplate/elements/tr-input-beginning_ending.html2
-rw-r--r--httemplate/elements/tr-search-svc_broadband.html15
-rw-r--r--httemplate/elements/tr-select-contact.html204
-rw-r--r--httemplate/elements/tr-select-cust_location.html33
-rw-r--r--httemplate/elements/tr-select-did.html4
-rw-r--r--httemplate/elements/tr-select-discount_term.html4
-rw-r--r--httemplate/elements/tr-select-from_to.html2
-rw-r--r--httemplate/elements/tr-select-inventory_item.html48
-rw-r--r--httemplate/elements/tr-select-part_svc.html7
-rwxr-xr-xhttemplate/elements/tr-select-reason.html5
-rw-r--r--httemplate/elements/tr-select-voip_class.html3
36 files changed, 917 insertions, 128 deletions
diff --git a/httemplate/elements/auto-table.html b/httemplate/elements/auto-table.html
index 9aff94e67..5118b91ff 100644
--- a/httemplate/elements/auto-table.html
+++ b/httemplate/elements/auto-table.html
@@ -50,7 +50,7 @@ var <%$pre%>next_rownum;
var <%$pre%>set_rownum;
var <%$pre%>addRow;
var <%$pre%>deleteRow;
-var <%$pre%>fieldorder = <% to_json($fieldorder) %>;
+var <%$pre%>fieldorder = <% encode_json($fieldorder) %>;
function <%$pre%>possiblyAddRow_factory(obj) {
var callback = obj.onchange;
@@ -70,8 +70,8 @@ function <%$pre%>set_rownum(obj, rownum) {
if ( obj.id ) {
obj.id = obj.id + rownum;
}
- if ( obj.name ) {
- obj.name = obj.name + rownum;
+ if ( obj.getAttribute('name') ) {
+ obj.setAttribute('name', obj.getAttribute('name') + rownum);
// also, in this case it's a form field that will be part of the record
// so set up an onchange handler
obj.onchange = <%$pre%>possiblyAddRow_factory(obj);
@@ -96,17 +96,32 @@ function <%$pre%>addRow(data) {
<%$pre%>set_rownum(row, this_rownum);
if(data instanceof Array) {
for (i = 0; i < data.length && i < <%$pre%>fieldorder.length; i++) {
- var el = document.getElementsByName(<%$pre%>fieldorder[i] + this_rownum)[0];
+ var el = document.getElementsByName(<%$pre |js_string%> +
+ <%$pre%>fieldorder[i] +
+ this_rownum)[0];
if (el) {
- el.value = data[i];
+ if ( el.tagName.toLowerCase() == 'span' ) {
+ el.innerHTML = data[i];
+ } else if ( el.type == 'checkbox' ) {
+ el.checked = (el.value == data[i]);
+ } else {
+ el.value = data[i];
+ }
}
}
} else if (data instanceof Object) {
for (var field in data) {
- var el = document.getElementsByName(field + this_rownum)[0];
+ var el = document.getElementsByName(<%$pre |js_string%> +
+ field +
+ this_rownum)[0];
if (el) {
- el.value = data[field];
-% # doesn't work for checkbox
+ if ( el.tagName.toLowerCase() == 'span' ) {
+ el.innerHTML = data[field];
+ } else if ( el.type == 'checkbox' ) {
+ el.checked = (el.value == data[field]);
+ } else {
+ el.value = data[field];
+ }
}
}
} // else nothing
@@ -123,6 +138,20 @@ function <%$pre%>deleteRow(rownum) {
<%$pre%>tbody.removeChild(r);
}
+function <%$pre%>set_prefix(obj) {
+ if ( obj.id ) {
+ obj.id = <%$pre |js_string%> + obj.id;
+ }
+ if ( obj.getAttribute('name') ) {
+ obj.setAttribute('name', <%$pre |js_string%> + obj.getAttribute('name'));
+ }
+ for (var i = 0; i < obj.children.length; i++) {
+ if ( obj.children[i] instanceof Node ) {
+ <%$pre%>set_prefix(obj.children[i]);
+ }
+ }
+}
+
function <%$pre%>init() {
<%$pre%>template = document.getElementById(<% $template_row |js_string%>);
<%$pre%>tbody = document.getElementById('<%$pre%>autotable');
@@ -131,8 +160,10 @@ function <%$pre%>init() {
var table = <%$pre%>template.parentNode;
table.removeChild(<%$pre%>template);
// give it an id
- <%$pre%>template.id = <%$pre |js_string%> + 'row';
- // and a magic identifier so we know it's been submitted
+ <%$pre%>template.id = 'row';
+ // prefix the ids and names of the TR object and all its descendants
+ <%$pre%>set_prefix(<%$pre%>template);
+ // add a magic identifier so we know it's been submitted
var magic = document.createElement('INPUT');
magic.setAttribute('type', 'hidden');
magic.setAttribute('name', '<%$pre%>magic');
@@ -140,18 +171,26 @@ function <%$pre%>init() {
// and a delete button
%# should this be enclosed in an actual <button> for aesthetics?
var delete_button = document.createElement('IMG');
- delete_button.id = 'delete_button';
+ delete_button.id = '<%$pre%>delete_button';
delete_button.src = '<%$fsurl%>images/cross.png';
delete_button.alt = 'X';
// use an inline string for this so that it will be cloned properly
delete_button.setAttribute('onclick', "<%$pre%>deleteRow(this.rownum);");
+ // and an error display
+ var error_span = document.createElement('SPAN');
+ error_span.className = 'error';
+ error_span.style.color = '#FF0000';
+ error_span.setAttribute('name', '<%$pre%>error');
+ error_span.style.padding = '5px';
var delete_cell = document.createElement('TD');
+ delete_cell.style.textAlign = 'left';
delete_cell.appendChild(delete_button);
delete_cell.appendChild(magic); // it has to go somewhere
+ delete_cell.appendChild(error_span);
<%$pre%>template.appendChild(delete_cell);
// preload rows
- var rows = <% to_json(\@rows) %>;
+ var rows = <% encode_json(\@rows) %>;
for (var i = 0; i < rows.length; i++) {
<%$pre%>addRow(rows[i]);
}
diff --git a/httemplate/elements/change_history_common.html b/httemplate/elements/change_history_common.html
index 232664e39..34ce70b6c 100644
--- a/httemplate/elements/change_history_common.html
+++ b/httemplate/elements/change_history_common.html
@@ -15,13 +15,7 @@
<TH CLASS="grid" BGCOLOR="#cccccc">Description</TH>
</TR>
-% foreach my $item ( sort { $a->history_date <=> $b->history_date
-% #|| table order
-% || $a->historynum <=> $b->historynum
-% }
-% @history
-% )
-% {
+% foreach my $item ( @history ) {
% my $history_other = '';
% my $act = $item->history_action;
% if ( $act =~ /^replace/ ) {
@@ -196,4 +190,11 @@ $cust_pkg_date_format .= ' %l:%M:%S%P'
if $conf->exists('cust_pkg-display_times')
|| $curuser->option('cust_pkg-display_times');
+@history = sort { $a->history_date <=> $b->history_date
+ || $a->historynum <=> $b->historynum } @history;
+
+if ( $curuser->option('history_order') eq 'newest' ) {
+ @history = reverse @history;
+}
+
</%init>
diff --git a/httemplate/elements/change_password.html b/httemplate/elements/change_password.html
new file mode 100644
index 000000000..625ba1fb5
--- /dev/null
+++ b/httemplate/elements/change_password.html
@@ -0,0 +1,41 @@
+<STYLE>
+.passwordbox {
+ border: 1px solid #7e0079;
+ padding: 2px;
+ position: absolute;
+ font-size: 80%;
+ background-color: #ffffff;
+ display: none;
+}
+</STYLE>
+<A ID="<%$pre%>link" HREF="#" onclick="<%$pre%>toggle(true)">(<% mt('change') %>)</A>
+<DIV ID="<%$pre%>form" CLASS="passwordbox">
+ <FORM METHOD="POST" ACTION="<%$fsurl%>misc/process/change-password.html">
+ <INPUT TYPE="hidden" NAME="svcnum" VALUE="<% $svc_acct->svcnum |h%>">
+ <INPUT TYPE="text" ID="<%$pre%>password" NAME="password" VALUE="<% $curr_value |h%>">
+ <& /elements/random_pass.html, $pre.'password', 'randomize' &>
+ <INPUT TYPE="submit" VALUE="change">
+ <INPUT TYPE="button" VALUE="cancel" onclick="<%$pre%>toggle(false)">
+% if ( $error ) {
+ <BR><SPAN STYLE="color: #ff0000"><% $error |h %></SPAN>
+% }
+ </FORM>
+</DIV>
+<SCRIPT TYPE="text/javascript">
+function <%$pre%>toggle(val) {
+ document.getElementById('<%$pre%>form').style.display =
+ val ? 'inline-block' : 'none';
+ document.getElementById('<%$pre%>link').style.display =
+ val ? 'none' : 'inline';
+}
+% if ( $error ) {
+<%$pre%>toggle(true);
+% }
+</SCRIPT>
+<%init>
+my %opt = @_;
+my $svc_acct = $opt{'svc_acct'};
+my $curr_value = $opt{'curr_value'} || '';
+my $pre = 'changepw'.$svc_acct->svcnum.'_';
+my $error = $cgi->param($pre.'error');
+</%init>
diff --git a/httemplate/elements/checkbox-tristate.html b/httemplate/elements/checkbox-tristate.html
new file mode 100644
index 000000000..4c26ed74e
--- /dev/null
+++ b/httemplate/elements/checkbox-tristate.html
@@ -0,0 +1,78 @@
+<%doc>
+A tristate checkbox (with three values: true, false, and null).
+Internally, this creates a checkbox, coupled via javascript to a hidden
+field that actually contains the value. For now, the only values these
+can have are 1, 0, and empty. Clicking the checkbox cycles between them.
+</%doc>
+<%shared>
+my $init = 0;
+</%shared>
+% if ( !$init ) {
+% $init = 1;
+<SCRIPT TYPE="text/javascript">
+function tristate_onclick() {
+ var checkbox = this;
+ var input = checkbox.input;
+ if ( input.value == "" ) {
+ input.value = "0";
+ checkbox.checked = false;
+ checkbox.indeterminate = false;
+ } else if ( input.value == "0" ) {
+ input.value = "1";
+ checkbox.checked = true;
+ checkbox.indeterminate = false;
+ } else if ( input.value == "1" ) {
+ input.value = "";
+ checkbox.checked = true;
+ checkbox.indeterminate = true
+ }
+}
+
+var tristates = [];
+var tristate_boxes = [];
+window.onload = function() { // don't do this until all of the checkboxes exist
+%# tristates = document.getElementsByClassName('tristate'); # curse you, IE8
+ var all_inputs = document.getElementsByTagName('input');
+ for (var i=0; i < all_inputs.length; i++) {
+ if ( all_inputs[i].className == 'tristate' ) {
+ tristates.push(all_inputs[i]);
+ }
+ }
+ for (var i=0; i < tristates.length; i++) {
+ tristate_boxes[i] =
+ document.getElementById('checkbox_' + tristates[i].name);
+ // make sure they can find each other
+ tristate_boxes[i].input = tristates[i];
+ tristates[i].checkbox = tristate_boxes[i];
+ // set event handler
+ tristate_boxes[i].onclick = tristate_onclick;
+ // set initial value
+ if ( tristates[i].value == "" ) {
+ tristate_boxes[i].indeterminate = true
+ }
+ if ( tristates[i].value != "0" ) {
+ tristate_boxes[i].checked = true;
+ }
+ }
+};
+</SCRIPT>
+% } # end of $init
+<INPUT TYPE="hidden" NAME="<% $opt{field} %>"
+ ID="<% $opt{id} %>"
+ VALUE="<% $curr_value %>"
+ CLASS="tristate">
+<INPUT TYPE="checkbox" ID="checkbox_<%$opt{field}%>" CLASS="partial">
+<%init>
+
+my %opt = @_;
+
+# might be useful but I'm not implementing it yet
+#my $onchange = $opt{'onchange'}
+# ? 'onChange="'. $opt{'onchange'}. '(this)"'
+# : '';
+
+$opt{'id'} ||= 'hidden_'.$opt{'field'};
+my $curr_value = $opt{curr_value};
+$curr_value = undef
+ unless $curr_value eq '0' or $curr_value eq '1';
+</%init>
diff --git a/httemplate/elements/contact.html b/httemplate/elements/contact.html
index 490ba2303..3d5177612 100644
--- a/httemplate/elements/contact.html
+++ b/httemplate/elements/contact.html
@@ -2,9 +2,9 @@
<INPUT TYPE="hidden" NAME="<%$name%>" ID="<%$id%>" VALUE="<% $curr_value %>">
- <TABLE>
+ <TABLE STYLE="display:inline">
<TR>
-% if ( @contact_class ) {
+% if ( @contact_class && ! $opt{name_only} ) {
<TD>
<SELECT NAME="<%$name%>_classnum" <% $onchange %>>
<OPTION VALUE="">
@@ -106,6 +106,6 @@ foreach my $phone_type ( qsearch({table=>'phone_type', order_by=>'weight'}) ) {
$label{'comment'} = 'Comment';
-my @fields = keys %label;
+my @fields = $opt{'name_only'} ? qw( first last ) : keys %label;
</%init>
diff --git a/httemplate/elements/dashboard-toplist.html b/httemplate/elements/dashboard-toplist.html
index f4a372519..b80af7883 100644
--- a/httemplate/elements/dashboard-toplist.html
+++ b/httemplate/elements/dashboard-toplist.html
@@ -169,7 +169,6 @@ if ( $FS::TicketSystem::system eq 'RT_Internal'
ObjectCustomFieldValues.ObjectId = cust_tickets.Id
)
GROUP BY cust_tickets.custnum, ObjectCustomFieldValues.Content";
- #warn $sql."\n";
} else { # no custom_priority_field
$sql =
"SELECT cust_tickets.custnum,
@@ -181,10 +180,8 @@ if ( $FS::TicketSystem::system eq 'RT_Internal'
my $sth = dbh->prepare($sql) or die dbh->errstr;
$sth->execute or die $sth->errstr;
while ( my $row = $sth->fetchrow_hashref ) {
- #warn to_json($row)."\n";
$num_tickets_by_priority{ $row->{priority} }->{ $row->{custnum} } =
$row->{num_tickets};
}
}
-#warn Dumper \%num_tickets_by_priority;
</%init>
diff --git a/httemplate/elements/fckeditor/fckeditor.js b/httemplate/elements/fckeditor/fckeditor.js
index 8e0126bae..eb7d339af 100644
--- a/httemplate/elements/fckeditor/fckeditor.js
+++ b/httemplate/elements/fckeditor/fckeditor.js
@@ -304,7 +304,7 @@ function FCKeditor_IsCompatibleBrowser()
// Internet Explorer 5.5+
if ( /*@cc_on!@*/false && sAgent.indexOf("mac") == -1 )
{
- var sBrowserVersion = navigator.appVersion.match(/MSIE (.\..)/)[1] ;
+ var sBrowserVersion = navigator.appVersion.match(/MSIE ([\d.]+)/)[1] ;
return ( sBrowserVersion >= 5.5 ) ;
}
diff --git a/httemplate/elements/location.html b/httemplate/elements/location.html
index 873fe1621..685523314 100644
--- a/httemplate/elements/location.html
+++ b/httemplate/elements/location.html
@@ -200,7 +200,7 @@ Example:
</TR>
% } else {
% foreach (qw(latitude longitude)) {
-<INPUT TYPE="hidden" NAME="<% $_ %>" VALUE="<% $object->get($_) |h%>">
+<INPUT TYPE="hidden" NAME="<% $_ %>" ID="<% $_ %>" VALUE="<% $object->get($_) |h%>">
% }
% }
<INPUT TYPE="hidden" NAME="<%$pre%>coord_auto" VALUE="<% $object->coord_auto %>">
@@ -226,12 +226,13 @@ Example:
<TD COLSPAN=8>
<INPUT TYPE="text" SIZE=15
NAME="<%$pre%>district"
+ ID="<%$pre%>district"
VALUE="<% $object->district |h %>">
<% '(automatic)' %>
</TD>
</TR>
% } else {
- <INPUT TYPE="hidden" NAME="<%$pre%>district" VALUE="<% $object->district %>">
+ <INPUT TYPE="hidden" ID="<%$pre%>" NAME="<%$pre%>district" VALUE="<% $object->district %>">
% }
% }
@@ -239,7 +240,7 @@ Example:
%# keep a clean copy of the address so we know if we need
%# to re-standardize
% foreach (qw(address1 city state country zip latitude
-% longitude censustract addr_clean) ) {
+% longitude censustract district addr_clean) ) {
<INPUT TYPE="hidden" NAME="old_<%$pre.$_%>" ID="old_<%$pre.$_%>" VALUE="<% $object->get($_) |h%>">
% }
%# Placeholders
diff --git a/httemplate/elements/menu.html b/httemplate/elements/menu.html
index 4e6109687..5689b12d2 100644
--- a/httemplate/elements/menu.html
+++ b/httemplate/elements/menu.html
@@ -194,7 +194,7 @@ foreach my $svcdb ( FS::part_svc->svc_tables() ) {
} elsif ( $svcdb eq 'svc_phone' ) {
$report_svc{"${name}' total usage by time period"} =
- [ $fsurl. 'search/report_svc_phone.html',
+ [ $fsurl. 'search/report_svc_phone_usage.html',
'Total usage (minutes, and amount billed) for the specified time period, per phone number.',
];
@@ -209,7 +209,7 @@ foreach my $svcdb ( FS::part_svc->svc_tables() ) {
$report_svc{"Advanced $lcsname reports"} =
[ $fsurl."search/report_$svcdb.html", '' ]
- if $svcdb =~ /^svc_(acct|broadband|hardware)$/
+ if $svcdb =~ /^svc_(acct|broadband|hardware|phone)$/
&& $curuser->access_right("Services: $name: Advanced search");
if ( $svcdb eq 'svc_phone' ) {
@@ -236,7 +236,7 @@ tie my %report_packages, 'Tie::IxHash';
$report_packages{'Package definitions (by # active)'} = [ $fsurl.'browse/part_pkg.cgi?active=1', 'Package definitions by number of active packages' ]
if $curuser->access_right('Edit package definitions')
|| $curuser->access_right('Edit global package definitions');
-$report_packages{'Package Costs Report'} = [ $fsurl.'graph/report_cust_pkg_cost.html', 'Package setup and recurring costs graph' ]
+$report_packages{'Package costs'} = [ $fsurl.'graph/report_cust_pkg_cost.html', 'Package setup and recurring costs graph' ]
if $curuser->access_right('Financial reports');
$report_packages{'separator'} = ''
if keys %report_packages;
@@ -294,9 +294,11 @@ tie my %report_ticketing, 'Tie::IxHash',
'Advanced ticket reports' => [ $fsurl.'rt/Search/Build.html?NewQuery=1', 'List tickets by any criteria' ],
;
-tie my %report_employees, 'Tie::IxHash',
- 'Employee Commission Report' => [ $fsurl.'search/report_employee_commission.html', '' ],
- 'Employee Audit Report' => [ $fsurl.'search/report_employee_audit.html', 'Employee audit report' ],
+tie my %report_employees, 'Tie::IxHash';
+$report_employees{'Employee Commission Report'} = [ $fsurl.'search/report_employee_commission.html', '' ]
+ if $curuser->access_right('Employees: Commission Report');
+$report_employees{'Employee Audit Report'} = [ $fsurl.'search/report_employee_audit.html', 'Employee audit report' ]
+ if $curuser->access_right('Employees: Audit Report');
;
tie my %report_bill_event, 'Tie::IxHash',
@@ -336,7 +338,8 @@ tie my %report_sales, 'Tie::IxHash',
'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' ],
+ 'Sales with Advertising Source' => [ $fsurl.'search/report_cust_bill_pkg_referral.html' ],
+ 'Sales with Agent Commissions' => [ $fsurl.'search/report_agent_commission.html' ],
;
tie my %report_financial, 'Tie::IxHash';
@@ -396,7 +399,7 @@ $report_menu{'Tickets'} = [ \%report_ticketing, 'Ticket reports' ]
if $conf->config('ticket_system')
;#&& FS::TicketSystem->access_right(\%session, 'Something');
$report_menu{'Employees'} = [ \%report_employees, 'Employee reports' ]
- if $curuser->access_right('Financial reports');
+ if keys %report_employees;
$report_menu{'Billing events'} = [ \%report_bill_event, 'Billing events' ]
if $curuser->access_right('Billing event reports');
$report_menu{'Financial'} = [ \%report_financial, 'Financial reports' ]
@@ -463,6 +466,8 @@ $tools_menu{'Job Queue'} = [ $fsurl.'search/queue.html', 'View pending job queu
if $curuser->access_right('Job queue');
$tools_menu{'Ticketing'} = [ \%tools_ticketing, 'Ticketing tools' ]
if $conf->config('ticket_system');
+$tools_menu{'Customer email settings'} = [ $fsurl.'misc/manage_cust_email.html' ]
+ if $curuser->access_right('Edit customer');
$tools_menu{'Business card scan'} = [ $fsurl.'edit/prospect_main-upload.html' ]
if $curuser->access_right('New prospect');
$tools_menu{'Time Queue'} = [ $fsurl.'search/report_timeworked.html', 'View pending support time' ]
@@ -649,7 +654,7 @@ $config_misc{'Advertising sources'} = [ $fsurl.'browse/part_referral.html', 'Whe
|| $curuser->access_right('Edit global advertising sources');
if ( $curuser->access_right('Configuration') ) {
$config_misc{'Custom fields'} = [ $fsurl.'browse/part_virtual_field.html', 'Locally defined fields', ];
- $config_misc{'Message catalog'} = [ $fsurl.'browse/msgcat.html', 'Change error messages and other customizable labels for each locale' ];
+ $config_misc{'Translation strings'} = [ $fsurl.'browse/msgcat.html', 'Translations and other customizable labels for each locale' ];
}
$config_misc{'Inventory classes and inventory'} = [ $fsurl.'browse/inventory_class.html', 'Setup inventory classes and stock inventory' ]
if $curuser->access_right('Edit inventory')
diff --git a/httemplate/elements/order_pkg.js b/httemplate/elements/order_pkg.js
index 8c1efd93a..1069a0ee4 100644
--- a/httemplate/elements/order_pkg.js
+++ b/httemplate/elements/order_pkg.js
@@ -44,4 +44,5 @@ function standardize_new_location() {
function submit_abort() {
document.OrderPkgForm.submitButton.disabled = false;
+ nd(1);
}
diff --git a/httemplate/elements/progress-init.html b/httemplate/elements/progress-init.html
index 7a282a34c..cef54b824 100644
--- a/httemplate/elements/progress-init.html
+++ b/httemplate/elements/progress-init.html
@@ -108,7 +108,7 @@ function <%$key%>process () {
function <%$key%>myCallback( jobnum ) {
- overlib( OLiframeContent('<%$p%>elements/progress-popup.html?jobnum=' + jobnum + ';<%$url_or_message_link%>;formname=<%$formname%>' , 444, 168, '<% $popup_name %>'), CAPTION, 'Please wait...', STICKY, AUTOSTATUSCAP, CLOSETEXT, '', CLOSECLICK, MIDX, 0, MIDY, 0 );
+ overlib( OLiframeContent('<%$fsurl%>elements/progress-popup.html?jobnum=' + jobnum + ';<%$url_or_message_link%>;formname=<%$formname%>' , 444, 168, '<% $popup_name %>'), CAPTION, 'Please wait...', STICKY, AUTOSTATUSCAP, CLOSETEXT, '', CLOSECLICK, MIDX, 0, MIDY, 0 );
}
diff --git a/httemplate/elements/random_pass.html b/httemplate/elements/random_pass.html
new file mode 100644
index 000000000..b215b77d9
--- /dev/null
+++ b/httemplate/elements/random_pass.html
@@ -0,0 +1,17 @@
+<INPUT TYPE="button" VALUE="<% emt($label) %>" onclick="randomPass()">
+<SCRIPT TYPE="text/javascript">
+function randomPass() {
+ var i=0;
+ var pw_set='<% join('', 'a'..'z', 'A'..'Z', '0'..'9' ) %>';
+ var pass='';
+ while(i < 8) {
+ i++;
+ pass += pw_set.charAt(Math.floor(Math.random() * pw_set.length));
+ }
+ document.getElementById('<% $id %>').value = pass;
+}
+</SCRIPT>
+<%init>
+my $id = shift;
+my $label = shift || 'Generate';
+</%init>
diff --git a/httemplate/elements/search-svc_broadband.html b/httemplate/elements/search-svc_broadband.html
new file mode 100644
index 000000000..d83516172
--- /dev/null
+++ b/httemplate/elements/search-svc_broadband.html
@@ -0,0 +1,204 @@
+<%doc>
+
+Example:
+
+ include( '/elements/search-svc_broadband.html,
+ 'field' => 'svcnum',
+ #slightly deprecated old synonym for field#'field_name'=>'svcnum',
+ 'find_button' => 1, #add a "find" button to the field
+ 'curr_value' => 54, #current value
+ 'value => 32, #deprecated synonym for curr_value
+ );
+
+</%doc>
+<INPUT TYPE="hidden" NAME="<% $field %>" ID="<% $field %>" VALUE="<% $value %>">
+
+<!-- some false laziness w/ misc/batch-cust_pay.html, though not as bad as i'd thought at first... -->
+
+<INPUT TYPE = "text"
+ NAME = "<% $field %>_search"
+ ID = "<% $field %>_search"
+ SIZE = "32"
+ VALUE="<% $svc_broadband ? $svc_broadband->label : '(svcnum, ip or mac)' %>"
+ onFocus="clearhint_<% $field %>_search(this);"
+ onClick="clearhint_<% $field %>_search(this);"
+ onChange="smart_<% $field %>_search(this);"
+>
+
+% if ( $opt{'find_button'} ) {
+ <INPUT TYPE = "button"
+ VALUE = 'Find',
+ NAME = "<% $field %>_findbutton"
+ onClick = "smart_<% $field %>_search(this.form.<% $field %>_search);"
+ >
+% }
+
+<SELECT NAME="<% $field %>_select" ID="<% $field %>_select" STYLE="color:#ff0000; display:none" onChange="select_<% $field %>(this);">
+</SELECT>
+
+<% include('/elements/xmlhttp.html',
+ 'url' => $p. 'misc/xmlhttp-svc_broadband-search.cgi',
+ 'subs' => [ 'smart_search' ],
+ )
+%>
+
+<SCRIPT TYPE="text/javascript">
+
+ function clearhint_<% $field %>_search (what) {
+
+ what.style.color = '#000000';
+
+ if ( what.value == '(svcnum, ip or mac)' )
+ what.value = '';
+
+ if ( what.value.indexOf('Service not found: ') == 0 )
+ what.value = what.value.substr(20);
+
+ }
+
+ var <% $field %>_search_active = false;
+
+ function smart_<% $field %>_search(what) {
+
+ if ( <% $field %>_search_active )
+ return;
+
+ var service = what.value;
+
+ if ( service == 'searching...' || service == ''
+ || service.indexOf('Service not found: ') == 0 )
+ return;
+
+ if ( what.getAttribute('magic') == 'nosearch' ) {
+ what.setAttribute('magic', '');
+ return;
+ }
+
+ //what.value = 'searching...'
+ what.disabled = true;
+ what.style.color= '#000000';
+ what.style.backgroundColor = '#dddddd';
+
+ var service_select = document.getElementById('<% $field %>_select');
+
+ //alert("search for customer " + customer);
+
+ function <% $field %>_search_update(services) {
+
+ //alert('customers returned: ' + customers);
+
+ var serviceArray = eval('(' + services + ')');
+
+ what.disabled = false;
+ what.style.backgroundColor = '#ffffff';
+
+ if ( serviceArray.length == 0 ) {
+
+ what.form.<% $field %>.value = '';
+
+ what.value = 'Service not found: ' + what.value;
+ what.style.color = '#ff0000';
+
+ what.style.display = '';
+ service_select.style.display = 'none';
+
+ } else if ( serviceArray.length == 1 ) {
+
+ //alert('one customer found: ' + customerArray[0]);
+
+ what.form.<% $field %>.value = serviceArray[0][0];
+ what.value = serviceArray[0][1];
+
+ what.style.display = '';
+ service_select.style.display = 'none';
+
+ } else {
+
+ //alert('multiple customers found, have to create select dropdown');
+
+ //blank the current list
+ for ( var i = service_select.length; i >= 0; i-- )
+ service_select.options[i] = null;
+
+ opt(service_select, '', 'Multiple services match "' + service + '" - select one', '#ff0000');
+
+ //add the multiple services
+ for ( var s = 0; s < serviceArray.length; s++ )
+ opt(service_select, serviceArray[s][0], serviceArray[s][1], '#000000');
+
+ opt(service_select, 'cancel', '(Edit search string)', '#000000');
+
+ what.style.display = 'none';
+ service_select.style.display = '';
+
+ }
+
+ <% $field %>_search_active = false;
+
+ }
+
+ <% $field %>_search_active = true;
+
+ smart_search( service, <% $field %>_search_update );
+
+
+ }
+
+ function select_<% $field %> (what) {
+
+ var svcnum = what.options[what.selectedIndex].value;
+ var service = what.options[what.selectedIndex].text;
+
+ var service_obj = document.getElementById('<% $field %>_search');
+
+ if ( svcnum == '' ) {
+ //what.style.color = '#ff0000';
+
+ } else if ( svcnum == 'cancel' ) {
+
+ service_obj.style.color = '#000000';
+
+ what.style.display = 'none';
+ service_obj.style.display = '';
+ service_obj.focus();
+
+ } else {
+
+ what.form.<% $field %>.value = svcnum;
+
+ service_obj.value = service;
+ service_obj.style.color = '#000000';
+
+ what.style.display = 'none';
+ service_obj.style.display = '';
+
+ }
+
+ }
+
+ function opt(what,value,text,color) {
+ var optionName = new Option(text, value, false, false);
+ optionName.style.color = color;
+ var length = what.length;
+ what.options[length] = optionName;
+ }
+
+</SCRIPT>
+<%init>
+
+my( %opt ) = @_;
+
+my $field = $opt{'field'} || $opt{'field_name'} || 'svcnum';
+
+my $value = $opt{'curr_value'} || $opt{'value'};
+
+my $svc_broadband = '';
+if ( $value ) {
+ $svc_broadband = qsearchs({
+ 'table' => 'svc_broadband',
+ 'hashref' => { 'svcnum' => $value },
+ #have to join to cust_main for an agentnum 'extra_sql' => " AND ". $FS::CurrentUser::CurrentUser->agentnums_sql,
+ });
+}
+
+</%init>
diff --git a/httemplate/elements/select-areacode.html b/httemplate/elements/select-areacode.html
index a302befc2..f0f56d56d 100644
--- a/httemplate/elements/select-areacode.html
+++ b/httemplate/elements/select-areacode.html
@@ -17,7 +17,7 @@
what.form.<% $opt{'prefix'} %>areacode.disabled = 'disabled';
what.form.<% $opt{'prefix'} %>areacode.style.display = 'none';
var areacodewait = document.getElementById('<% $opt{'prefix'} %>areacodewait');
- areacodewait.style.display = '';
+ areacodewait.style.display = 'inline';
var areacodeerror = document.getElementById('<% $opt{'prefix'} %>areacodeerror');
areacodeerror.style.display = 'none';
@@ -61,7 +61,7 @@
what.form.<% $opt{'prefix'} %>areacode.style.display = '';
} else {
var areacodeerror = document.getElementById('<% $opt{'prefix'} %>areacodeerror');
- areacodeerror.style.display = '';
+ areacodeerror.style.display = 'inline';
}
//run the callback
diff --git a/httemplate/elements/select-did.html b/httemplate/elements/select-did.html
index 6e205d8ff..c39603156 100644
--- a/httemplate/elements/select-did.html
+++ b/httemplate/elements/select-did.html
@@ -18,6 +18,28 @@ Example:
<TABLE>
<TR>
+% my( $phonenum_checked, $manual_checked ) = ( '', '' );
+% if ( $export->get_dids_can_manual ) {
+% #not 100% perfect UI on error handling, but it'll do
+% if ( $opt{'curr_value'} ) {
+% $phonenum_checked = '';
+% $manual_checked = 'CHECKED';
+% } else {
+% $phonenum_checked = 'CHECKED';
+% $manual_checked = '';
+% }
+
+ <TD VALIGN="top">
+ <INPUT TYPE = "radio"
+ NAME = "phonenum_which"
+ VALUE = "phonenum"
+ onChange = "phonenum_which_changed(this)"
+ onClick = "phonenum_which_changed(this)"
+ <% $phonenum_checked %>
+ > Inventory
+ </TD>
+% }
+
% if ( $export->get_dids_npa_select ) {
<TD VALIGN="top">
@@ -27,9 +49,10 @@ Example:
'svcpart' => $svcpart,
'disable_empty' => 0,
'empty_label' => 'Select state',
+ 'disabled' => ( $manual_checked ? 1 : 0 ),
)
%>
- <BR><FONT SIZE="-1">State</FONT>
+ <BR><FONT SIZE="-1" ID="phonenum_state_label" <% $manual_checked ? 'STYLE="color:#999999"' : '' %>>State</FONT>
</TD>
<TD VALIGN="top">
@@ -39,19 +62,24 @@ Example:
'empty' => 'Select area code',
)
%>
- <BR><FONT SIZE="-1">Area code</FONT>
+ <BR><FONT SIZE="-1" ID="areacode_label" <% $manual_checked ? 'STYLE="color:#999999"' : '' %>>Area code</FONT>
</TD>
<TD VALIGN="top">
<% include('/elements/select-exchange.html',
- 'svcpart' => $svcpart,
- 'empty' => 'Select exchange',
+ 'svcpart' => $svcpart,
+ 'empty' => 'Select exchange',
)
%>
- <BR><FONT SIZE="-1">City / Exchange</FONT>
+ <BR><FONT SIZE="-1" ID="exchange_label" <% $manual_checked ? 'STYLE="color:#999999"' : '' %>>City / Exchange</FONT>
</TD>
% } else {
+%
+% #this code path currently only being used by fibernetics
+% # should change "Province" label to "State" or make it configurable
+% # if/when other folks need an areacode-less DID selector that goes
+% # directly from state to region
<TD VALIGN="top">
<% include('/elements/select.html',
@@ -60,9 +88,10 @@ Example:
'options' => [ '', @{ $export->get_dids } ],
'labels' => { '' => 'Select province' },
'onchange' => 'phonenum_state_changed(this);',
+ 'disabled' => ( $manual_checked ? 1 : 0 ),
)
%>
- <BR><FONT SIZE="-1">Province</FONT>
+ <BR><FONT SIZE="-1" ID="phonenum_state_label" <% $manual_checked ? 'STYLE="color:#999999"' : '' %>>Province</FONT>
</TD>
<TD VALIGN="top">
@@ -72,7 +101,7 @@ Example:
'empty' => 'Select region',
)
%>
- <BR><FONT SIZE="-1">Region</FONT>
+ <BR><FONT SIZE="-1" ID="region_label" <% $manual_checked ? 'STYLE="color:#999999"' : '' %>>Region</FONT>
</TD>
% }
@@ -86,10 +115,132 @@ Example:
'region' => ! $export->get_dids_npa_select,
)
%>
- <BR><FONT SIZE="-1">Phone number</FONT>
+ <BR><FONT SIZE="-1" ID="phonenum_phonenum_label" <% $manual_checked ? 'STYLE="color:#999999"' : '' %>>Phone number</FONT>
</TD>
</TR>
+
+% if ( $export->get_dids_can_manual ) {
+ <TR>
+
+ <TD VALIGN="top">
+ <INPUT TYPE = "radio"
+ NAME = "phonenum_which"
+ VALUE = "phonenum_manual"
+ onChange = "phonenum_which_changed(this)"
+ onClick = "phonenum_which_changed(this)"
+ <% $manual_checked %>
+ > Manual entry
+ </TD>
+
+ <TD VALIGN="top" COLSPAN=4>
+ <& /elements/input-text.html,
+ %opt,
+ field => 'phonenum_manual',
+ id => 'phonenum_manual',
+ type => 'text',
+ disabled => ( $phonenum_checked ? 1 : 0 ),
+ &>
+ </TD>
+ </TR>
+
+ <SCRIPT TYPE="text/javascript">
+ function phonenum_which_changed(what) {
+
+ if ( what.value == 'phonenum' && what.checked ) {
+
+ what.form.phonenum_manual.disabled = true;
+ what.form.phonenum_manual.style.backgroundColor = '#dddddd';
+
+ what.form.phonenum_state.disabled = false;
+
+ document.getElementById('phonenum_state_label').style.color = '#000000';
+ if ( document.getElementById('areacode_label') ) {
+ document.getElementById('areacode_label').style.color = '#000000';
+ }
+ if ( document.getElementById('exchange_label') ) {
+ document.getElementById('exchange_label').style.color = '#000000';
+ }
+ if ( document.getElementById('region_label') ) {
+ document.getElementById('region_label').style.color = '#000000';
+ }
+ document.getElementById('phonenum_phonenum_label').style.color = '#000000';
+
+ var value = what.form.phonenum_state.options[ what.form.phonenum_state.selectedIndex].value;
+
+ if ( value != '' ) {
+
+ if ( what.form.areacode ) {
+ what.form.areacode.disabled = false;
+
+ var areacode_value = what.form.areacode.options[ what.form.areacode.selectedIndex].value;
+
+ if ( areacode_value != '' ) {
+ what.form.exchange.disabled = false;
+
+ var exchange_value = what.form.exchange.options[ what.form.exchange.selectedIndex].value;
+
+ if ( exchange_value != '' ) {
+ what.form.phonenum.disabled = false;
+ }
+
+ }
+
+ }
+ if ( what.form.region ) {
+ what.form.region.disabled = false;
+
+ var region_value = what.form.region.options[ what.form.region.selectedIndex].value;
+
+ if ( region_value != '' ) {
+ what.form.phonenum.disabled = false;
+ }
+
+ }
+
+ }
+
+ }
+
+ if ( what.value == 'phonenum_manual' && what.checked ) {
+
+ what.form.phonenum_manual.disabled = false;
+ what.form.phonenum_manual.style.backgroundColor = '#ffffff';
+
+ what.form.phonenum_state.disabled = true;
+
+ document.getElementById('phonenum_state_label').style.color = '#999999';
+ if ( document.getElementById('areacode_label') ) {
+ document.getElementById('areacode_label').style.color = '#999999';
+ }
+ if ( document.getElementById('exchange_label') ) {
+ document.getElementById('exchange_label').style.color = '#999999';
+ }
+ if ( document.getElementById('region_label') ) {
+ document.getElementById('region_label').style.color = '#999999';
+ }
+ document.getElementById('phonenum_phonenum_label').style.color = '#999999';
+
+ if ( what.form.areacode ) {
+ what.form.areacode.disabled = true;
+ }
+
+ if ( what.form.exchange ) {
+ what.form.exchange.disabled = true;
+ }
+
+ if ( what.form.region ) {
+ what.form.region.disabled = true;
+ }
+
+ what.form.phonenum.disabled = true;
+ }
+
+ }
+ </SCRIPT>
+
+% }
+
</TABLE>
% }
diff --git a/httemplate/elements/select-exchange.html b/httemplate/elements/select-exchange.html
index 9e4b5ce97..b9677094a 100644
--- a/httemplate/elements/select-exchange.html
+++ b/httemplate/elements/select-exchange.html
@@ -17,7 +17,7 @@
what.form.<% $opt{'prefix'} %>exchange.disabled = 'disabled';
what.form.<% $opt{'prefix'} %>exchange.style.display = 'none';
var exchangewait = document.getElementById('<% $opt{'prefix'} %>exchangewait');
- exchangewait.style.display = '';
+ exchangewait.style.display = 'inline';
var exchangeerror = document.getElementById('<% $opt{'prefix'} %>exchangeerror');
exchangeerror.style.display = 'none';
@@ -56,7 +56,7 @@
what.form.<% $opt{'prefix'} %>exchange.style.display = '';
} else {
var exchangeerror = document.getElementById('<% $opt{'prefix'} %>exchangeerror');
- exchangeerror.style.display = '';
+ exchangeerror.style.display = 'inline';
}
//run the callback
diff --git a/httemplate/elements/select-mac.html b/httemplate/elements/select-mac.html
index 8b1c71fea..4b406fce0 100644
--- a/httemplate/elements/select-mac.html
+++ b/httemplate/elements/select-mac.html
@@ -7,7 +7,7 @@
<% include( '/elements/input-text.html', %opt, 'type'=>'text' ) %>
<SELECT ID="<% $opt{'prefix'} %>sel_mac_addr" NAME="<% $opt{'prefix'} %>sel_mac_addr"
- notonChange="<% $opt{'prefix'} %>mac_addr_changed(this); <% $opt{'onchange'} %>"
+%# notonChange="<% $opt{'prefix'} %>mac_addr_changed(this); <% $opt{'onchange'} %>"
<% $opt{'disabled'} %> STYLE="display: none">
<OPTION VALUE="">Select MAC address</OPTION>
</SELECT>
diff --git a/httemplate/elements/select-part_svc.html b/httemplate/elements/select-part_svc.html
index 72ab7f6b0..743b2852e 100644
--- a/httemplate/elements/select-part_svc.html
+++ b/httemplate/elements/select-part_svc.html
@@ -13,6 +13,9 @@ my( %opt ) = @_;
$opt{'records'} = delete $opt{'part_svc'}
if $opt{'part_svc'};
-$opt{'records'} ||= [ qsearch( 'part_svc', {} ) ]; # { disabled=>'' } )
+my %hash = ();
+$hash{'svcdb'} = $opt{'svcdb'} if $opt{'svcdb'};
+
+$opt{'records'} ||= [ qsearch( 'part_svc', \%hash ) ]; # { disabled=>'' } )
</%init>
diff --git a/httemplate/elements/select-phonenum.html b/httemplate/elements/select-phonenum.html
index 18abe3dea..a8d9a7c3e 100644
--- a/httemplate/elements/select-phonenum.html
+++ b/httemplate/elements/select-phonenum.html
@@ -17,7 +17,7 @@
what.form.<% $opt{'prefix'} %>phonenum.disabled = 'disabled';
what.form.<% $opt{'prefix'} %>phonenum.style.display = 'none';
var phonenumwait = document.getElementById('<% $opt{'prefix'} %>phonenumwait');
- phonenumwait.style.display = '';
+ phonenumwait.style.display = 'inline';
var phonenumerror = document.getElementById('<% $opt{'prefix'} %>phonenumerror');
phonenumerror.style.display = 'none';
@@ -54,7 +54,7 @@
what.form.<% $opt{'prefix'} %>phonenum.style.display = '';
} else {
var phonenumerror = document.getElementById('<% $opt{'prefix'} %>phonenumerror');
- phonenumerror.style.display = '';
+ phonenumerror.style.display = 'inline';
}
//run the callback
diff --git a/httemplate/elements/select-region.html b/httemplate/elements/select-region.html
index 9823290db..7ed959269 100644
--- a/httemplate/elements/select-region.html
+++ b/httemplate/elements/select-region.html
@@ -17,7 +17,7 @@
what.form.<% $opt{'prefix'} %>region.disabled = 'disabled';
what.form.<% $opt{'prefix'} %>region.style.display = 'none';
var regionwait = document.getElementById('<% $opt{'prefix'} %>regionwait');
- regionwait.style.display = '';
+ regionwait.style.display = 'inline';
var regionerror = document.getElementById('<% $opt{'prefix'} %>regionerror');
regionerror.style.display = 'none';
@@ -56,7 +56,7 @@
what.form.<% $opt{'prefix'} %>region.style.display = '';
} else {
var regionerror = document.getElementById('<% $opt{'prefix'} %>regionerror');
- regionerror.style.display = '';
+ regionerror.style.display = 'inline';
}
//run the callback
diff --git a/httemplate/elements/select-table.html b/httemplate/elements/select-table.html
index c0cd7a50b..b6c1573d1 100644
--- a/httemplate/elements/select-table.html
+++ b/httemplate/elements/select-table.html
@@ -8,7 +8,7 @@ Example:
# required
##
'table' => 'table_name',
- 'name_col' => 'name_column',
+ 'name_col' => 'name_column', #or method if you pass an order_by
#strongly recommended (you want your forms to be "sticky" on errors, right?)
'curr_value' => 'current_value',
@@ -111,6 +111,7 @@ Example:
<% $opt{'label_callback'}
? &{ $opt{'label_callback'} }( $record )
: $record->$name_col()
+ |h
%>
% }
diff --git a/httemplate/elements/select-tiered.html b/httemplate/elements/select-tiered.html
index e332eeff8..3ff5471ae 100644
--- a/httemplate/elements/select-tiered.html
+++ b/httemplate/elements/select-tiered.html
@@ -124,13 +124,6 @@ my %opt = @_;
my $pre = $opt{prefix} || '';
my $tiers = $opt{tiers} or die "no tiers defined";
-#my $json = JSON->new()->canonical(); #sort
-# something super weird and broken going on with JSON's auto-loading, just
-# using JSON alone errors out with
-# Can't locate object method "new" via package "null" (perhaps you forgot to
-# load "null"?)
-# yes, "null", not "JSON". so instead, using JSON::XS explicity...
-use JSON::XS;
my $json = JSON::XS->new();
$json->canonical;
diff --git a/httemplate/elements/selectlayers.html b/httemplate/elements/selectlayers.html
index 01fd590ca..cb1d2d619 100644
--- a/httemplate/elements/selectlayers.html
+++ b/httemplate/elements/selectlayers.html
@@ -236,7 +236,7 @@ sub layer_callback {
$date_noinit = 1;
}
else {
- $include = "input-$include" if $include =~ /^(text|money)$/;
+ $include = "input-$include" if $include =~ /^(text|money|percentage)$/;
$include = "tr-$include" unless $include eq 'hidden';
$html .= include( "/elements/$include.html",
%$lf,
diff --git a/httemplate/elements/standardize_locations.js b/httemplate/elements/standardize_locations.js
index 15c5761a0..e98039d9d 100644
--- a/httemplate/elements/standardize_locations.js
+++ b/httemplate/elements/standardize_locations.js
@@ -7,8 +7,8 @@ function status_message(text, caption) {
function form_address_info() {
var cf = document.<% $formname %>;
- var returnobj = { onlyship: <% $onlyship ? 1 : 0 %> };
-% if ( !$onlyship ) {
+ var returnobj = { billship: <% $billship %> };
+% if ( $billship ) {
returnobj['same'] = cf.elements['same'].checked;
% }
% if ( $withfirm ) {
@@ -59,16 +59,12 @@ function standardize_locations() {
cf.elements['<% $pre %>coord_auto'].value = 'Y';
changed = true;
}
-
-% } #foreach $pre
-
// standardize if the old address wasn't clean
- if ( cf.elements['old_ship_addr_clean'].value == '' ||
- cf.elements['old_bill_addr_clean'].value == '' ) {
-
+ if ( cf.elements['<% $pre %>addr_clean'].value == '' ) {
changed = true;
-
}
+% } #foreach $pre
+
// or if it was clean but has been changed
for (var key in address_info) {
var old_el = cf.elements['old_'+key];
@@ -81,7 +77,7 @@ function standardize_locations() {
% # If address hasn't been changed, auto-confirm the existing value of
% # censustract so that we don't ask the user to confirm it again.
- if ( !changed ) {
+ if ( !changed && <% $withcensus %> ) {
if ( address_info['same'] ) {
cf.elements['bill_censustract'].value =
address_info['bill_censustract'];
@@ -195,12 +191,14 @@ function post_standardization() {
% if ( $conf->exists('enable_taxproducts') ) {
+ var cf = document.<% $formname %>;
+
if ( new String(cf.elements['<% $taxpre %>zip'].value).length < 10 )
{
var country_el = cf.elements['<% $taxpre %>country'];
var country = country_el.options[ country_el.selectedIndex ].value;
- var geocode = cf.elements['geocode'].value;
+ var geocode = cf.elements['bill_geocode'].value;
if ( country == 'CA' || country == 'US' ) {
@@ -222,14 +220,14 @@ function post_standardization() {
} else {
- cf.elements['geocode'].value = 'DEFAULT';
+ cf.elements['bill_geocode'].value = 'DEFAULT';
<% $post_geocode %>;
}
} else {
- cf.elements['geocode'].value = '';
+ cf.elements['bill_geocode'].value = '';
<% $post_geocode %>;
}
@@ -254,14 +252,14 @@ function update_geocode() {
cf.elements['<% $taxpre %>city'].value = argsHash['city'];
setselect(cf.elements['<% $taxpre %>state'], argsHash['state']);
cf.elements['<% $taxpre %>zip'].value = argsHash['zip'];
- cf.elements['geocode'].value = argsHash['geocode'];
+ cf.elements['bill_geocode'].value = argsHash['geocode'];
<% $post_geocode %>;
}
// popup a chooser
- overlib( OLresponseAJAX, CAPTION, 'Select tax location', STICKY, AUTOSTATUSCAP, CLOSETEXT, '', MIDX, 0, MIDY, 0, DRAGGABLE, WIDTH, 576, HEIGHT, 268, BGCOLOR, '#333399', CGCOLOR, '#333399', TEXTSIZE, 3 );
+ overlib( OLresponseAJAX, CAPTION, 'Select tax location', STICKY, AUTOSTATUSCAP, CLOSETEXT, '', MIDX, 0, MIDY, 0, WIDTH, 576, HEIGHT, 268, BGCOLOR, '#333399', CGCOLOR, '#333399', TEXTSIZE, 3 );
}
@@ -279,21 +277,18 @@ function setselect(el, value) {
my %opt = @_;
my $conf = new FS::Conf;
-my $withfirm = 1;
-my $withcensus = 1;
+my $withfirm = $opt{'with_firm'} ? 1 : 0;
+my $withcensus = $opt{'with_census'} ? 1 : 0;
+
+my @prefixes = '';
+my $billship = $opt{'billship'} ? 1 : 0; # whether to have bill_ and ship_ prefixes
+my $taxpre = '';
+if ($billship) {
+ @prefixes = qw(bill_ ship_);
+ $taxpre = $conf->exists('tax-ship_address') ? 'ship_' : 'bill_';
+}
my $formname = $opt{form} || 'CustomerForm';
-my $onlyship = $opt{onlyship} || '';
-#my $main_prefix = $opt{main_prefix} || '';
-#my $ship_prefix = $opt{ship_prefix} || ($onlyship ? '' : 'ship_');
-# The prefixes are now 'ship_' and 'bill_'.
-my $taxpre = 'bill_';
-$taxpre = 'ship_' if ( $conf->exists('tax-ship_address') || $onlyship );
my $post_geocode = $opt{callback} || 'post_geocode();';
-$withfirm = 0 if $opt{no_company};
-$withcensus = 0 if $opt{no_census};
-
-my @prefixes = ('ship_');
-unshift @prefixes, 'bill_' unless $onlyship;
</%init>
diff --git a/httemplate/elements/tr-cust_svc.html b/httemplate/elements/tr-cust_svc.html
index 1ca22f6d4..b66654f38 100644
--- a/httemplate/elements/tr-cust_svc.html
+++ b/httemplate/elements/tr-cust_svc.html
@@ -96,7 +96,8 @@ my $svc_unprovision_link =
my $manage_link = $opt{'manage_link'};
my $manage_target = '';
if ( $part_svc->svcdb eq 'svc_broadband' and $manage_link ) {
- my $ip_addr = $svc_x->ip_addr; #substitution for $manage_link
+ my $ip_addr = $svc_x->ip_addr; #substitution for $manage_link
+ my $mac_addr = $svc_x->mac_addr; # ditto
$manage_link = eval(qq("$manage_link"));
$opt{'manage_link_text'} ||= mt('Manage Device');
$opt{'manage_link_loc'} ||= 'bottom';
diff --git a/httemplate/elements/tr-input-beginning_ending.html b/httemplate/elements/tr-input-beginning_ending.html
index 7481c9bb6..ffc903875 100644
--- a/httemplate/elements/tr-input-beginning_ending.html
+++ b/httemplate/elements/tr-input-beginning_ending.html
@@ -74,7 +74,7 @@ my( $input_time, $time_format, $time_hint ) = ( '', '', '' );
my( $size, $maxlength ) = ( 11, 10 );
if ( $opt{'input_time'} ) {
$input_time = ', showsTime: true, timeFormat: "12"'; # http://www.dynarch.com/demos/jscalendar/doc/html/reference.html#node_sec_2.3
- $time_format = ' %k:%M:%S'; # http://www.dynarch.com/demos/jscalendar/doc/html/reference.html#node_sec_5.3.5
+ $time_format = ' %H:%M:%S'; # http://www.dynarch.com/demos/jscalendar/doc/html/reference.html#node_sec_5.3.5
$time_hint = ' h:m:s';
$size = 21;
$maxlength = 27;
diff --git a/httemplate/elements/tr-search-svc_broadband.html b/httemplate/elements/tr-search-svc_broadband.html
new file mode 100644
index 000000000..cd7c11500
--- /dev/null
+++ b/httemplate/elements/tr-search-svc_broadband.html
@@ -0,0 +1,15 @@
+<& tr-td-label.html, @_ &>
+
+ <TD <% $colspan %> <% $cell_style %> ID="<% $opt{input_id} || $opt{id}.'_input0' %>"><& search-svc_broadband.html, @_ &></TD>
+
+</TR>
+
+<%init>
+
+my %opt = @_;
+
+my $cell_style = $opt{'cell_style'} ? 'STYLE="'. $opt{'cell_style'}. '"' : '';
+
+my $colspan = $opt{'colspan'} ? 'COLSPAN="'.$opt{'colspan'}.'"' : '';
+
+</%init>
diff --git a/httemplate/elements/tr-select-contact.html b/httemplate/elements/tr-select-contact.html
new file mode 100644
index 000000000..d6bc67f36
--- /dev/null
+++ b/httemplate/elements/tr-select-contact.html
@@ -0,0 +1,204 @@
+<%doc>
+
+Example:
+
+ include('/elements/tr-select-contact.html',
+ 'cgi' => $cgi,
+
+ 'cust_main' => $cust_main,
+ #or
+ 'prospect_main' => $prospect_main,
+
+ #optional
+ 'empty_label' => '(default contact)',
+ )
+
+</%doc>
+
+<SCRIPT TYPE="text/javascript">
+
+ function contact_disable(what) {
+% for (@contact_fields) {
+ what.form.<%$_%>.disabled = true;
+ var ftype = what.form.<%$_%>.tagName;
+ if( ftype == 'SELECT') changeSelect(what.form.<%$_%>, '');
+ else what.form.<%$_%>.value = '';
+ if( ftype != 'SELECT') what.form.<%$_%>.style.backgroundColor = '#dddddd';
+% }
+ }
+
+ function contact_clear(what) {
+% for (@contact_fields) {
+ var ftype = what.form.<%$_%>.tagName;
+ if( ftype == 'INPUT' ) what.form.<%$_%>.value = '';
+% }
+ }
+
+ function contact_enable(what) {
+% for (@contact_fields) {
+ what.form.<%$_%>.disabled = false;
+ var ftype = what.form.<%$_%>.tagName;
+ if( ftype != 'SELECT') what.form.<%$_%>.style.backgroundColor = '#ffffff';
+% }
+ }
+
+ function contactnum_changed(what) {
+ var contactnum = what.options[what.selectedIndex].value;
+ if ( contactnum == -1 ) { //Add new contact
+ contact_clear(what);
+
+ contact_enable(what);
+ return;
+ }
+
+% if ( $editable ) {
+ if ( contactnum == 0 ) {
+% }
+
+% #sleep/wait until dropdowns are updated?
+ contact_disable(what);
+
+% if ( $editable ) {
+ } else {
+
+% #sleep/wait until dropdowns are updated?
+ contact_enable(what);
+
+ }
+% }
+
+ }
+
+ function changeSelect(what, value) {
+ for ( var i=0; i<what.length; i++) {
+ if ( what.options[i].value == value ) {
+ what.selectedIndex = i;
+ }
+ }
+ }
+
+</SCRIPT>
+
+<TR>
+ <<%$th%> ALIGN="right" VALIGN="top"><% $opt{'label'} || emt('Service contact') %></<%$th%>>
+ <TD VALIGN="top" COLSPAN=7>
+ <SELECT NAME = "contactnum"
+ ID = "contactnum"
+ STYLE = "vertical-align:top;margin:3px"
+ onchange = "contactnum_changed(this);"
+ >
+% if ( $cust_main ) {
+ <OPTION VALUE=""><% $opt{'empty_label'} || '(customer default)' |h %>
+% }
+%
+% foreach my $contact ( @contact ) {
+ <OPTION VALUE="<% $contact->contactnum %>"
+ <% $contactnum == $contact->contactnum ? 'SELECTED' : '' %>
+ ><% $contact->line |h %>
+% }
+% if ( $addnew ) {
+ <OPTION VALUE="-1"
+ <% $contactnum == -1 ? 'SELECTED' : '' %>
+ >New contact
+% }
+ </SELECT>
+
+<% include('/elements/contact.html',
+ 'object' => $contact,
+ #'onchange' ? probably not
+ 'disabled' => $disabled,
+ 'name_only' => 1,
+ )
+%>
+
+ </TD>
+</TR>
+
+<SCRIPT TYPE="text/javascript">
+ contactnum_changed(document.getElementById('contactnum'));
+</SCRIPT>
+<%init>
+
+#based on / kinda false laziness w/tr-select-cust_contact.html
+
+my $conf = new FS::Conf;
+
+my %opt = @_;
+my $cgi = $opt{'cgi'};
+my $cust_pkg = $opt{'cust_pkg'};
+my $cust_main = $opt{'cust_main'};
+my $prospect_main = $opt{'prospect_main'};
+die "cust_main or prospect_main required" unless $cust_main or $prospect_main;
+
+my $contactnum = '';
+if ( $cgi->param('error') ) {
+ $cgi->param('contactnum') =~ /^(\-?\d*)$/ or die "illegal contactnum";
+ $contactnum = $1;
+} else {
+ if ( length($opt{'curr_value'}) ) {
+ $contactnum = $opt{'curr_value'};
+ } elsif ($prospect_main) {
+ my @cust_contact = $prospect_main->cust_contact;
+ $contactnum = $cust_contact[0]->contactnum if scalar(@cust_contact)==1;
+ } else { #$cust_main
+ $cgi->param('contactnum') =~ /^(\-?\d*)$/ or die "illegal contactnum";
+ $contactnum = $1;
+ }
+}
+
+##probably could use explicit controls
+#my $editable = $cust_main ? 0 : 1; #could use explicit control
+my $editable = 0;
+my $addnew = $cust_main ? 1 : ( $contactnum>0 ? 0 : 1 );
+
+my @contact_fields = map "contactnum_$_", qw( first last );
+
+my $contact; #the one that shows by default in the contact edit space
+if ( $contactnum && $contactnum > 0 ) {
+ $contact = qsearchs('contact', { 'contactnum' => $contactnum } )
+ or die "unknown contactnum";
+} else {
+ $contact = new FS::contact;
+ if ( $contactnum == -1 ) {
+ $contact->$_( $cgi->param($_) ) foreach @contact_fields; #XXX
+ } elsif ( $cust_pkg && $cust_pkg->contactnum ) {
+ my $pkg_contact = $cust_pkg->contact_obj;
+ $contact->$_( $pkg_contact->$_ ) foreach @contact_fields; #XXX why are we making a new one gagain??
+ $opt{'empty_label'} ||= 'package contact: '.$pkg_contact->line;
+ } elsif ( $cust_main ) {
+ $contact = new FS::contact; #I think
+ }
+}
+
+my $contact_sort = sub {
+ lc($a->last) cmp lc($b->last)
+ or lc($a->first) cmp lc($b->first)
+};
+
+my @contact;
+push @contact, $cust_main->cust_contact if $cust_main;
+push @contact, $prospect_main->contact if $prospect_main;
+push @contact, $contact
+ if !$cust_main && $contact && $contact->contactnum > 0
+ && ! grep { $_->contactnum == $contact->contactnum } @contact;
+
+@contact = sort $contact_sort grep !$_->disabled, @contact;
+
+$contact = $contact[0]
+ if ( $prospect_main )
+ && !$opt{'is_optional'}
+ && @contact;
+
+my $disabled =
+ ( $contactnum < 0
+ || ( $editable && $contactnum )
+ || ( $prospect_main
+ && !$opt{'is_optional'} && !@contact && $addnew
+ )
+ )
+ ? ''
+ : 'DISABLED';
+
+my $th = $opt{'no_bold'} ? 'TD' : 'TH';
+
+</%init>
diff --git a/httemplate/elements/tr-select-cust_location.html b/httemplate/elements/tr-select-cust_location.html
index 7ffbd6c14..780bf96ad 100644
--- a/httemplate/elements/tr-select-cust_location.html
+++ b/httemplate/elements/tr-select-cust_location.html
@@ -153,25 +153,16 @@ Example:
}
}
+ var location_fields = <% encode_json(\@location_fields) %>;
function update_location( string ) {
- var hash = eval('('+string+')');
- document.getElementById('address1').value = hash['address1'];
- document.getElementById('city').value = hash['city'];
- document.getElementById('zip').value = hash['zip'];
-
-% if ( $opt{'alt_format'} ) {
- changeSelect( document.getElementById('location_kind'), hash['location_kind']);
- changeSelect( document.getElementById('location_type'), hash['location_type']);
- document.getElementById('location_number').value = hash['location_number'];
-% } else {
- document.getElementById('address2').value = hash['address2'];
-% }
-
- var country_el = document.getElementById('country');
-
- changeSelect( country_el, hash['country'] );
-
- country_changed( country_el,
+ var hash = JSON.parse(string);
+ for(var i = 0; i < location_fields.length; i++) {
+ var f = location_fields[i];
+ if (hash[f] && document.getElementById(f)) {
+ document.getElementById(f).value = hash[f];
+ }
+ }
+ country_changed( document.getElementById('country'),
fix_state_factory( hash['state'],
hash['county']
)
@@ -185,7 +176,7 @@ Example:
<TD COLSPAN=7>
<SELECT NAME = "locationnum"
ID = "locationnum"
- onChange = "locationnum_changed(this);"
+ onchange = "locationnum_changed(this);"
>
% if ( $cust_main ) {
<OPTION VALUE="<% $cust_main->ship_locationnum %>"><% $opt{'empty_label'} || '(default service address)' |h %>
@@ -258,9 +249,7 @@ if ( $cgi->param('error') ) {
my $editable = $cust_main ? 0 : 1; #could use explicit control
my $addnew = $cust_main ? 1 : ( $locationnum>0 ? 0 : 1 );
-my @location_fields = qw( address1 address2 city county state zip country
- latitude longitude
- );
+my @location_fields = FS::cust_main->location_fields;
if ( $opt{'alt_format'} ) {
push @location_fields, qw( location_type location_number location_kind );
}
diff --git a/httemplate/elements/tr-select-did.html b/httemplate/elements/tr-select-did.html
index 987ade689..2aa712f79 100644
--- a/httemplate/elements/tr-select-did.html
+++ b/httemplate/elements/tr-select-did.html
@@ -1,6 +1,6 @@
<% include('tr-td-label.html', @_ ) %>
-% if ( $opt{'curr_value'} ne '' && $use_selector ) {
+% if ( $use_selector && $opt{'curr_value'} ne '' && ! $can_edit ) {
<TD BGCOLOR="#dddddd" <% $cell_style %>><% $opt{'formatted_value'} || $opt{'curr_value'} || $opt{'value'} |h %></TD>
@@ -38,4 +38,6 @@ if ( scalar(@exports) > 1 ) {
my $use_selector = scalar(@exports) ? 1 : 0;
+my $can_edit = scalar(@exports) && $exports[0]->get_dids_can_edit;
+
</%init>
diff --git a/httemplate/elements/tr-select-discount_term.html b/httemplate/elements/tr-select-discount_term.html
index e9faeb228..d4218f848 100644
--- a/httemplate/elements/tr-select-discount_term.html
+++ b/httemplate/elements/tr-select-discount_term.html
@@ -24,7 +24,9 @@ function change_discount_term(what) {
id => 'discount_term',
options => [ '', @discount_term ],
labels => { '' => mt('1 month'),
- map { $_ => mt('[_1] months', $_) } @discount_term },
+ map { $_ => mt('[_1] months', sprintf('%.0f', $_)) }
+ @discount_term
+ },
curr_value => '',
onchange => $amount_id ? 'change_discount_term(this)' : '',
&>
diff --git a/httemplate/elements/tr-select-from_to.html b/httemplate/elements/tr-select-from_to.html
index a27412f99..ad9b40a6b 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' => '2013', #haha, well...
+ 'end_year' => '2014',
@_,
);
</%init>
diff --git a/httemplate/elements/tr-select-inventory_item.html b/httemplate/elements/tr-select-inventory_item.html
new file mode 100644
index 000000000..669e85f27
--- /dev/null
+++ b/httemplate/elements/tr-select-inventory_item.html
@@ -0,0 +1,48 @@
+% if ( scalar(@classnums) == 0 ) {
+<& tr-fixed.html, %opt &>
+% } elsif ( scalar(@classnums) == 1 ) {
+% $opt{'extra_sql'} .= ' AND '.$classnum_sql;
+<& tr-select-table.html,
+ 'table' => 'inventory_item',
+ 'name_col' => 'item',
+ 'value_col' => 'item',
+ %opt
+&>
+% } else {
+<& tr-td-label.html, %opt &>
+<TD>
+<& select-tiered.html,
+ 'prefix' => $opt{'field'}.'_',
+ 'tiers' => [
+ {
+ field => $opt{'field'}.'_classnum',
+ table => 'inventory_class',
+ extra_sql => "WHERE $classnum_sql",
+ name_col => 'classname',
+ empty_label => '(all)',
+ },
+ {
+ field => $opt{'field'},
+ table => 'inventory_item',
+ name_col => 'item',
+ value_col => 'item',
+ link_col => 'classnum',
+ extra_sql => delete($opt{'extra_sql'}),
+ disable_empty => 1,
+ },
+ ],
+ %opt,
+&>
+</TD>
+</TR>
+% }
+<%init>
+my %opt = @_;
+my @classnums;
+if (ref($opt{'classnum'})) {
+ @classnums = @{ $opt{'classnum'} };
+} else {
+ @classnums = split(',', $opt{'classnum'});
+}
+my $classnum_sql = 'classnum IN('.join(',', @classnums).')';
+</%init>
diff --git a/httemplate/elements/tr-select-part_svc.html b/httemplate/elements/tr-select-part_svc.html
index af5148749..959ac8dd9 100644
--- a/httemplate/elements/tr-select-part_svc.html
+++ b/httemplate/elements/tr-select-part_svc.html
@@ -5,7 +5,7 @@
% } else {
<TR>
- <TD ALIGN="right"><% $opt{'label'} || 'Package definition' %></TD>
+ <TD ALIGN="right"><% $opt{'label'} || 'Service definition' %></TD>
<TD>
<% include( '/elements/select-part_svc.html',
'multiple' => 1,
@@ -21,6 +21,9 @@
my( %opt ) = @_;
-$opt{'part_svc'} ||= [ qsearch( 'part_svc', {} ) ]; # { disabled=>'' } )
+my %hash = ();
+$hash{'svcdb'} = $opt{'svcdb'} if $opt{'svcdb'};
+
+$opt{'part_svc'} ||= [ qsearch( 'part_svc', \%hash ) ]; # { disabled=>'' } )
</%init>
diff --git a/httemplate/elements/tr-select-reason.html b/httemplate/elements/tr-select-reason.html
index c1df10b94..9a670a26b 100755
--- a/httemplate/elements/tr-select-reason.html
+++ b/httemplate/elements/tr-select-reason.html
@@ -154,15 +154,12 @@ my $controlledbutton = $opt{'control_button'};
my $id = $opt{'id'} || $func_suffix;
-my( $add_access_right, $access_right );
+my $add_access_right;
if ($class eq 'C') {
- $access_right = 'Cancel customer';
$add_access_right = 'Add on-the-fly cancel reason';
} elsif ($class eq 'S') {
- $access_right = 'Suspend customer package';
$add_access_right = 'Add on-the-fly suspend reason';
} elsif ($class eq 'R') {
- $access_right = 'Post credit';
$add_access_right = 'Add on-the-fly credit reason';
} else {
die "illegal class: $class";
diff --git a/httemplate/elements/tr-select-voip_class.html b/httemplate/elements/tr-select-voip_class.html
index dcc1487cc..afd3e1f8a 100644
--- a/httemplate/elements/tr-select-voip_class.html
+++ b/httemplate/elements/tr-select-voip_class.html
@@ -18,7 +18,8 @@ my @options = (
'' => '',
1 => 'VoIP without Broadband',
2 => 'VoIP with Broadband',
- 3 => 'Wholesale VoIP'
+ 3 => 'Wholesale VoIP',
+ 4 => 'Local Exchange (non-VoIP)',
);
</%init>