summaryrefslogtreecommitdiff
path: root/httemplate/elements
diff options
context:
space:
mode:
Diffstat (limited to 'httemplate/elements')
-rw-r--r--httemplate/elements/contact.html2
-rw-r--r--httemplate/elements/cust_pkg_usageprice.html9
-rw-r--r--httemplate/elements/email-link.html3
-rw-r--r--httemplate/elements/form-create_ticket.html2
-rw-r--r--httemplate/elements/form-file_upload.html1
-rw-r--r--httemplate/elements/htmlarea.html4
-rw-r--r--httemplate/elements/images/ui-icons_ef8c08_256x240.pngbin0 -> 4369 bytes
-rw-r--r--httemplate/elements/menu.html4
-rw-r--r--httemplate/elements/order_pkg.js68
-rw-r--r--httemplate/elements/polygon.html127
-rw-r--r--httemplate/elements/popup_link-send_report_batch.html28
-rw-r--r--httemplate/elements/schedule-appointment.html3
-rw-r--r--httemplate/elements/select-terms.html2
-rw-r--r--httemplate/elements/select-tower_sector.html7
-rw-r--r--httemplate/elements/template_image-dialog.html279
-rw-r--r--httemplate/elements/tr-pkg_svc.html67
-rw-r--r--httemplate/elements/tr-polygon.html5
-rw-r--r--httemplate/elements/tr-select-months.html1
-rw-r--r--httemplate/elements/tr-td-label.html2
19 files changed, 518 insertions, 96 deletions
diff --git a/httemplate/elements/contact.html b/httemplate/elements/contact.html
index ef74481c0..87e15debe 100644
--- a/httemplate/elements/contact.html
+++ b/httemplate/elements/contact.html
@@ -135,7 +135,7 @@ tie my %label, 'Tie::IxHash',
my $first = 0;
foreach my $phone_type ( qsearch({table=>'phone_type', order_by=>'weight'}) ) {
- next if $phone_type->typename eq 'Home';
+ next if $phone_type->typename =~ /^(Home|Fax)$/;
my $f = 'phonetypenum'.$phone_type->phonetypenum;
$label{$f} = $phone_type->typename. ' phone';
$size{$f} = $first++ ? 10 : 15;
diff --git a/httemplate/elements/cust_pkg_usageprice.html b/httemplate/elements/cust_pkg_usageprice.html
index 729099320..74b7842be 100644
--- a/httemplate/elements/cust_pkg_usageprice.html
+++ b/httemplate/elements/cust_pkg_usageprice.html
@@ -23,15 +23,16 @@
>
% my $info = $part_pkg_usageprice->target_info;
% my $amount = $part_pkg_usageprice->amount / ($info->{multiplier}||1);
- <OPTION VALUE="">Additional <% $info->{label} %>
+ <OPTION VALUE="">Additional <% $info->{label} %></OPTION>
% for (1..100) { #100? arbitrary.
- <OPTION VALUE="<% $_ %>"><%
+% my $selected = ($opt{'curr_quantity'} == $_) ? ' SELECTED' : '';
+ <OPTION VALUE="<% $_ %>"<% $selected %>><%
$money_char. sprintf('%.2f', $_ * $part_pkg_usageprice->price ).
' '.
'for'. #( $part_pkg_usageprice->action eq 'increment' ? 'per' : 'for' ).
' '.
( $_ * $amount ). ' '. $info->{label}
- %>
+ %></OPTION>
% }
</SELECT>
</TD>
@@ -42,8 +43,6 @@
% }
<%init>
-#my $targets = FS::part_pkg_usageprice->targets;
-
my( %opt ) = @_;
my $conf = new FS::Conf;
diff --git a/httemplate/elements/email-link.html b/httemplate/elements/email-link.html
index 2612faabb..16935cf98 100644
--- a/httemplate/elements/email-link.html
+++ b/httemplate/elements/email-link.html
@@ -10,7 +10,8 @@ die "'table' required" if !$table;
die "'search_hash' required" if !$search_hash;
my $uri = new URI;
-$uri->query_form($search_hash);
+my @params = map { $_, $search_hash->{$_} } sort keys %$search_hash;
+$uri->query_form(@params);
my $query = $uri->query;
my $label = ($opt{'label'} || 'Email a notice to these customers');
</%init>
diff --git a/httemplate/elements/form-create_ticket.html b/httemplate/elements/form-create_ticket.html
index 362e82397..d76c0d83e 100644
--- a/httemplate/elements/form-create_ticket.html
+++ b/httemplate/elements/form-create_ticket.html
@@ -6,7 +6,7 @@ function updateTicketLink() {
link.href = "<% $new_base.'?'.
join(';', map(
{ ($_ eq 'Queue') ? () : "$_=$new_param{$_}"}
- keys %new_param),'Queue=') %>" + selector.options[selector.selectedIndex].value;
+ sort keys %new_param),'Queue=') %>" + selector.options[selector.selectedIndex].value;
}
</SCRIPT>
<A NAME="tickets"><FONT CLASS="fsinnerbox-title">Tickets</FONT></A>
diff --git a/httemplate/elements/form-file_upload.html b/httemplate/elements/form-file_upload.html
index 45b6c97f2..3542a5a8e 100644
--- a/httemplate/elements/form-file_upload.html
+++ b/httemplate/elements/form-file_upload.html
@@ -69,6 +69,7 @@ Example:
<div style="display:none:" id="uploadError"></div>
<FORM NAME = "<% $opt{name} %>"
+ ID = "<% $opt{id} %>"
ACTION = "<% $fsurl %>misc/file-upload.html"
METHOD = "POST"
ENCTYPE = "multipart/form-data"
diff --git a/httemplate/elements/htmlarea.html b/httemplate/elements/htmlarea.html
index 7c40e61c7..d8b25121a 100644
--- a/httemplate/elements/htmlarea.html
+++ b/httemplate/elements/htmlarea.html
@@ -12,7 +12,7 @@ Example:
</%doc>
% #init
-<SCRIPT TYPE="text/javascript" src="<% $p %>elements/ckeditor/ckeditor.js">
+<SCRIPT TYPE="text/javascript" src="<% $fsurl %>elements/ckeditor/ckeditor.js">
</SCRIPT>
% #editor
@@ -35,7 +35,7 @@ my $config = {
'skin' => 'kama',
'toolbarCanCollapse' => JSON::true,
'removePlugins' => 'elementspath',
- 'basePath' => $p.'elements/ckeditor/',
+ 'basePath' => $fsurl.'elements/ckeditor/',
'enterMode' => 2,
%{ $opt{config} || {} },
};
diff --git a/httemplate/elements/images/ui-icons_ef8c08_256x240.png b/httemplate/elements/images/ui-icons_ef8c08_256x240.png
new file mode 100644
index 000000000..85e63e9f6
--- /dev/null
+++ b/httemplate/elements/images/ui-icons_ef8c08_256x240.png
Binary files differ
diff --git a/httemplate/elements/menu.html b/httemplate/elements/menu.html
index a5fb15bc2..ea6933198 100644
--- a/httemplate/elements/menu.html
+++ b/httemplate/elements/menu.html
@@ -381,6 +381,8 @@ if( $curuser->access_right('Financial reports') ) {
$report_financial{'Tax Liability (vendor tax data)'} = [ $fsurl.'search/report_newtax.html', 'Tax liability report (vendor tax data)' ]
if $taxproducts;
+ $report_financial{'Monthly Sales and Taxes'} = [$fsurl.'search/tax_sales.html', 'Monthly sales and taxes report'];
+
# most sites don't need this but there isn't really a config to enable it
$report_financial{'E911 Fee Summary'} = [ $fsurl.'search/report_e911.html', 'E911 fee summary' ];
@@ -767,7 +769,7 @@ 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' ]
+$config_misc{'Message templates'} = [ $fsurl.'browse/msg_template/email.html', 'Templates for customer notices' ]
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.' ]
diff --git a/httemplate/elements/order_pkg.js b/httemplate/elements/order_pkg.js
index 3586a54cb..a850d2193 100644
--- a/httemplate/elements/order_pkg.js
+++ b/httemplate/elements/order_pkg.js
@@ -1,10 +1,12 @@
function pkg_changed () {
var form = document.OrderPkgForm;
var discountnum = form.discountnum;
+ var opt = form.pkgpart.options[form.pkgpart.selectedIndex];
+
+ usageprice_pkg_changed( opt.value );
if ( form.pkgpart.selectedIndex > 0 ) {
- var opt = form.pkgpart.options[form.pkgpart.selectedIndex];
var date_button = document.getElementById('start_date_button');
var date_button_disabled = document.getElementById('start_date_disabled');
var date_text = document.getElementById('start_date_text');
@@ -68,78 +70,14 @@ function pkg_changed () {
}
}
- get_part_pkg_usageprice( opt.value, update_part_pkg_usageprice );
-
} else {
form.submitButton.disabled = true;
if ( discountnum ) { form.discountnum.disabled = true; }
discountnum_changed(form.discountnum);
}
-}
-
-function update_part_pkg_usageprice(part_pkg_usageprice) {
-
- var table = document.getElementById('cust_pkg_usageprice_table');
-
- // black the current usage price rows
- for ( var r = table.rows.length - 1; r >= 0; r-- ) {
- table.deleteRow(r);
- }
-
- // add the new usage price rows
- var rownum = 0;
- var usagepriceArray = eval('(' + part_pkg_usageprice + ')' );
- for ( var s = 0; s < usagepriceArray.length; s=s+2 ) {
- //surely this should be some kind of JSON structure
- var html = usagepriceArray[s+0];
- var javascript = usagepriceArray[s+1];
-
- // a lot like ("inspiried by") edit/elements/edit.html function spawn_<%$field%>
-
- // XXX evaluate the javascript
- //if (window.ActiveXObject) {
- // window.execScript(newfunc);
- //} else { /* (window.XMLHttpRequest) */
- // //window.eval(newfunc);
- // setTimeout(newfunc, 0);
- //}
-
- var row = table.insertRow(rownum++);
-
- //var label_cell = document.createElement('TD');
-
- //label_cell.id = '<% $field %>_label' + <%$field%>_fieldnum;
-
- //label_cell.style.textAlign = "right";
- //label_cell.style.verticalAlign = "top";
- //label_cell.style.borderTop = "1px solid black";
- //label_cell.style.paddingTop = "5px";
-
- //label_cell.innerHTML = '<% $label %>';
-
- //row.appendChild(label_cell);
-
- var widget_cell = document.createElement('TD');
-
- //widget_cell.style.borderTop = "1px solid black";
- widget_cell.style.paddingTop = "3px";
- widget_cell.colSpan = "2";
-
- widget_cell.innerHTML = html;
-
- row.appendChild(widget_cell);
-
- }
-
- if ( rownum > 0 ) {
- document.getElementById('cust_pkg_usageprice_title').style.display = '';
- } else {
- document.getElementById('cust_pkg_usageprice_title').style.display = 'none';
- }
}
-
function standardize_new_location() {
var form = document.OrderPkgForm;
var loc = form.locationnum;
diff --git a/httemplate/elements/polygon.html b/httemplate/elements/polygon.html
new file mode 100644
index 000000000..c26e98546
--- /dev/null
+++ b/httemplate/elements/polygon.html
@@ -0,0 +1,127 @@
+<%init>
+my %opt = @_;
+my $field = $opt{'field'};
+my $id = $opt{'id'} || $opt{'field'};
+my $div_id = "div_$id";
+
+my $vertices_json = $opt{'curr_value'} || '[]';
+</%init>
+<& hidden.html, %opt &>
+<div id="<% $div_id %>" style="height: 600px; width: 600px"></div>
+
+<script src="https://maps.googleapis.com/maps/api/js?libraries=drawing"></script>
+<script>
+var map;
+var drawingManager;
+
+function updateFormInput(event) {
+ var path = window.polygon.getPath();
+ var vertices = []; // array of arrays, geoJSON style
+ for (var i =0; i < path.getLength(); i++) {
+ var xy = path.getAt(i);
+ vertices[i] = [ xy.lat(), xy.lng() ];
+ }
+ console.log(vertices); //XXX
+ $('#<% $field %>').prop('value', JSON.stringify(vertices));
+}
+
+$(function() {
+ mapOptions = {
+ zoom: 4,
+ center: {lat: 39.40114, lng: -96.57127}, // continental U.S.
+ mapTypeId: google.maps.MapTypeId.ROADMAP,
+ panControl: true,
+ scaleControl: true,
+ streetViewControl: false,
+ };
+ map = new google.maps.Map($('#<% $div_id %>')[0], mapOptions);
+
+ var polygonComplete = function(p) {
+ window.polygon = p;
+ if (drawingManager) {
+ drawingManager.setDrawingMode(null);
+ drawingManager.setOptions({ drawingControl: false });
+ }
+ // double click to delete a vertex (so long as it remains a polygon)
+ p.addListener('dblclick', function (mev) {
+ if (mev.vertex != null && window.polygon.getPath().length > 3) {
+ p.getPath().removeAt(mev.vertex);
+ }
+ });
+ // any time the polygon is modified, update the vertex list
+ p.getPath().addListener('set_at', updateFormInput);
+ p.getPath().addListener('insert_at', updateFormInput);
+ p.getPath().addListener('remove_at', updateFormInput);
+
+ // and also now
+ updateFormInput();
+ };
+
+ var polygonOptions = {
+ fillColor: '#0000a0',
+ fillOpacity: 0.2,
+ strokeColor: '#0000a0',
+ strokeWeight: 2,
+ clickable: false,
+ editable: true,
+ zIndex: 1,
+ map: map,
+ };
+
+ var vertex_array = <% $vertices_json %>;
+ if ( vertex_array.length > 2 ) {
+ // then we already have a polygon. make it acceptable to google maps,
+ // and also create a bounding box for it and fit the map to that.
+
+ var path = [];
+ var bounds = new google.maps.LatLngBounds();
+ for (var i = 0; i < vertex_array.length; i++) {
+ var xy = new google.maps.LatLng(vertex_array[i][0], vertex_array[i][1]);
+ path.push(xy);
+ bounds.extend(xy);
+ }
+
+ polygonOptions.paths = [ path ];
+ polygonComplete(new google.maps.Polygon(polygonOptions));
+ map.fitBounds(bounds);
+
+ } else {
+ // there are no vertices, or not enough to make a polygon, so
+ // enable drawing mode to create a new one
+
+ drawingManager = new google.maps.drawing.DrawingManager({
+ drawingMode: google.maps.drawing.OverlayType.POLYGON,
+ drawingControl: true,
+ drawingControlOptions: {
+ position: google.maps.ControlPosition.TOP_CENTER,
+ drawingModes: [
+ google.maps.drawing.OverlayType.POLYGON,
+ ]
+ },
+ polygonOptions: polygonOptions,
+ });
+
+ // after a single polygon is drawn: remember it, add a listener to let
+ // nodes be deleted, and exit drawing mode
+ drawingManager.addListener('polygoncomplete', polygonComplete);
+ drawingManager.setMap(map);
+
+ // center the map on the user (for lack of a better choice)
+ if (navigator.geolocation) {
+ navigator.geolocation.getCurrentPosition(function(position) {
+ var pos = {
+ lat: position.coords.latitude,
+ lng: position.coords.longitude
+ };
+
+ map.setCenter(pos);
+ map.setZoom(12);
+ });
+ } // on error, or if geolocation isn't available, do nothing
+ }
+
+});
+
+ </script>
+ </body>
+</html>
diff --git a/httemplate/elements/popup_link-send_report_batch.html b/httemplate/elements/popup_link-send_report_batch.html
new file mode 100644
index 000000000..5f4471054
--- /dev/null
+++ b/httemplate/elements/popup_link-send_report_batch.html
@@ -0,0 +1,28 @@
+<%doc>
+
+Example:
+
+<& /elements/popup_link-send_report_batch.html,
+ reportname => 'sales_commission_pkg',
+ label => 'Click here to send reports by email',
+&>
+</%doc>
+<& /elements/popup_link.html, $params &>\
+<%init>
+
+my $params = { 'closetext' => emt('Close') };
+
+if (ref($_[0]) eq 'HASH') {
+ $params = { %$params, %{ $_[0] } };
+} else {
+ $params = { %$params, @_ };
+}
+
+$params->{'label'} ||= emt('Send reports by email');
+$params->{'actionlabel'} ||= emt('Send reports');
+#$params->{'width'} ||= 350;
+$params->{'height'} ||= 650;
+
+$params->{'action'} = $fsurl. 'misc/send-report.html?reportname='. $params->{'reportname'};
+
+</%init>
diff --git a/httemplate/elements/schedule-appointment.html b/httemplate/elements/schedule-appointment.html
index 45a8a5bab..69b9f422b 100644
--- a/httemplate/elements/schedule-appointment.html
+++ b/httemplate/elements/schedule-appointment.html
@@ -12,7 +12,8 @@ my $custnum = encode_entities( $cgi->param('custnum') );
my $query = join('&', map "username=$_", @username).
"&LengthMin=$LengthMin".
- "&custnum=$custnum";
+ "&custnum=$custnum".
+ "&RedirectToBasics=1";
#XXX '&pkgnum=$pkgnum";need to be for specific package/location, not just for a customer... default to active(/ordered) package in a pkg_class w/ticketing_queueid, otherwise, a popup? we're getting complicated like form-creat_ticket.html
my $url = $p. 'rt/Search/Schedule.html?'. $query;
diff --git a/httemplate/elements/select-terms.html b/httemplate/elements/select-terms.html
index 716832f52..a330df17c 100644
--- a/httemplate/elements/select-terms.html
+++ b/httemplate/elements/select-terms.html
@@ -36,7 +36,7 @@ my $empty_value = $opt{'empty_value'} || '';
my @terms = ( emt('Payable upon receipt'),
( map "Net $_",
- 0, 3, 5, 9, 10, 14, 15, 18, 20, 21, 25, 30, 45, 60, 90 ),
+ 0, 3, 5, 7, 9, 10, 14, 15, 18, 20, 21, 25, 30, 45, 60, 90 ),
);
my @pre_options = $opt{pre_options} ? @{ $opt{pre_options} } : ();
diff --git a/httemplate/elements/select-tower_sector.html b/httemplate/elements/select-tower_sector.html
index a16d3bfa0..76ff25223 100644
--- a/httemplate/elements/select-tower_sector.html
+++ b/httemplate/elements/select-tower_sector.html
@@ -2,6 +2,8 @@
<& /elements/select-table.html,
table => 'tower_sector',
name_col => 'description',
+ addl_from => 'JOIN tower USING (towernum)',
+ extra_sql => q(WHERE disabled = '' OR disabled IS NULL),
order_by => 'ORDER BY towernum,sectorname',
empty_label => ' ',
@_
@@ -11,8 +13,9 @@
<& /elements/select-table.html,
table => 'tower',
name_col => 'towername',
+ hashref => { 'disabled' => '', },
id => 'towernum',
- field => 'dummy_towernum',
+ field => 'towernum',
onchange => 'change_towernum(this.value);',
element_etc => 'STYLE="vertical-align:top"',
&>
@@ -63,5 +66,5 @@ foreach my $towernum (keys %sectors_of) {
}
}
-my $empty_label = $opt{'empty_label'} || 'Include services with no tower/sector';
+my $empty_label = $opt{'empty_label'} || 'Include services with no sector';
</%init>
diff --git a/httemplate/elements/template_image-dialog.html b/httemplate/elements/template_image-dialog.html
new file mode 100644
index 000000000..b471d28da
--- /dev/null
+++ b/httemplate/elements/template_image-dialog.html
@@ -0,0 +1,279 @@
+<%doc>
+
+Creates a jquery dialog box that opens when javascript function insertImageDialog
+is called, allows user to select an image and specify attributes for it, then passes
+img tag with base64 encoded data url to a callback javascript function.
+
+Accepts the following options:
+
+callback - pass the html for the selected img to this javascript function;
+if omitted, will only include fields for viewing/uploading image
+
+url - to redirect to after upload, otherwise just refreshes dialog window
+
+</%doc>
+
+<% include('/elements/xmlhttp.html',
+ 'url' => $fsurl.'misc/xmlhttp-template_image.cgi',
+ 'subs' => [ 'get_template_image' ],
+ ) %>
+
+<DIV ID="insert_image_dialog" title="Template Images">
+
+<TABLE BORDER="0" STYLE="width: 100%"><TR><TD>
+
+<FORM ID="insert_image_form">
+
+<% &ntable("#cccccc", 2) %>
+
+ <TR>
+ <TH>Image</TH>
+ <TD>
+ <SELECT ID="insert_image_imgnum" ONCHANGE="insertImageDialog($('#insert_image_imgnum').val())">
+ <OPTION VALUE="">(select an image)</OPTION>
+ </SELECT>
+ </TD>
+ </TR>
+% if ($opt{'callback'}) {
+ <TR>
+ <TH>Width</TH>
+ <TD><INPUT TYPE="text" SIZE="5" ID="insert_image_width" ONCHANGE="previewInsertImage()"></TD>
+ </TR>
+ <TR>
+ <TH>Height</TH>
+ <TD><INPUT TYPE="text" SIZE="5" ID="insert_image_height" ONCHANGE="previewInsertImage()"></TD>
+ </TR>
+ <TR>
+ <TH>Align</TH>
+ <TD>
+ <SELECT ID="insert_image_float" ONCHANGE="previewInsertImage()">
+ <OPTION VALUE="none">inline</OPTION>
+ <OPTION VALUE="left">left</OPTION>
+ <OPTION VALUE="right">right</OPTION>
+ </SELECT>
+ </TD>
+ </TR>
+ <TR>
+ <TH>Alt Text</TH>
+ <TD><INPUT TYPE="text" SIZE="20" ID="insert_image_alt" ONCHANGE="previewInsertImage()"></TD>
+ </TR>
+ <TR>
+ <TD COLSPAN="2" ALIGN="center" STYLE="padding-top:6px">
+ <INPUT TYPE="button" ID="insert_image_button" VALUE="Insert Image" ONCLICK="insertImage()">
+ </TD>
+ </TR>
+% } # if $opt{'callback'}
+
+</TABLE>
+
+</FORM>
+
+% if ($canedit) {
+
+<P><B><% emt('Upload New Image') %></B></P>
+
+<% include('/elements/form-file_upload.html',
+ 'name' => 'TemplateImageUploadForm',
+ 'id' => 'TemplateImageUploadForm',
+ 'action' => $fsurl.'misc/process/template_image-upload.cgi',
+ 'num_files' => 1,
+ 'fields' => [ 'name', 'agentnum' ],
+ 'url' => $opt{'url'} || 'javascript:refreshImageList(1)',
+ )
+ %>
+
+ <% &ntable("#cccccc", 2) %>
+
+ <% include( '/elements/tr-input-text.html',
+ 'field' => 'name',
+ 'label' => 'Name',
+ 'required' => 1,
+ 'id' => 'upload_form_name',
+ )
+ %>
+
+ <% include( '/elements/tr-select-agent.html',
+ 'label' => "<B>Agent</B>",
+ 'empty_label' => '(global)',
+ 'agent_virt' => 1,
+ 'agent_null_right' => 'Edit global templates',
+ )
+ %>
+
+ <% include( '/elements/tr-file-upload.html',
+ 'field' => 'file',
+ 'label' => 'File',
+ )
+ %>
+
+ <TR>
+ <TD COLSPAN="2" ALIGN="center" STYLE="padding-top:6px">
+ <INPUT TYPE = "submit"
+ NAME = "submitButton"
+ ID = "submitButton"
+ VALUE = "Upload image"
+ >
+ </TD>
+ </TR>
+
+</TABLE>
+
+</FORM>
+
+% } #if canedit
+
+</TD><TD width="100%">
+
+<DIV ID="insert_image_preview_box">
+ <P><B><% emt('Image Preview') %></B></P>
+ <SPAN ID="insert_image_loading"><B>(<% emt('Loading image...') %>)</B></SPAN>
+ <IMG SRC="" ID="insert_image_preview">
+</DIV>
+
+</TD></TR></TABLE>
+</DIV>
+
+<SCRIPT>
+
+// initialize & close dialog window, initialize imgobj cache && image list
+$( '#insert_image_dialog' ).dialog({
+ width: 800,
+ height: 550,
+ resizable: true,
+ autoOpen: false,
+});
+var imgobj = new Object;
+refreshImageList(0);
+
+// this is the main func to invoke from links outside this file.
+// opens dialog if needed
+// updates dialog with passed imgnum
+// caches image info through an xmlhttp request if needed
+// pass 'upload' as imgnum for upload-only view
+function insertImageDialog (imgnum) {
+ if (imgnum == 'upload') {
+ $('#insert_image_form').hide();
+ $('#insert_image_preview_box').hide();
+ imgnum = undefined;
+ } else {
+ $('#insert_image_form').show();
+ $('#insert_image_preview_box').show();
+ }
+ if (imgnum && !imgobj[imgnum]) {
+ clearInsertImageDialog();
+ $('#insert_image_loading').show();
+ $('#insert_image_imgnum').val(imgnum);
+ get_template_image('imgnum',imgnum,
+ function (result) {
+ var images = JSON.parse(result) || [];
+ for (i = 0; i < images.length; i++) {
+ imgobj[images[i].imgnum] = images[i];
+ }
+ updateInsertImageDialog();
+ }
+ );
+ } else if (imgnum) {
+ $('#insert_image_imgnum').val(imgnum);
+ updateInsertImageDialog();
+ } else {
+ clearInsertImageDialog();
+ }
+ if (!$( '#insert_image_dialog' ).dialog( 'isOpen' )) {
+ $( '#insert_image_dialog' ).dialog( 'open' );
+ }
+}
+
+// sets dialog values to a default "Loading..." state, including imgnum
+function clearInsertImageDialog () {
+ $('#insert_image_imgnum').val('');
+ $('#insert_image_preview').attr('src','');
+ $('#insert_image_loading').hide();
+}
+
+// updates preview src from cache based on imgnum from form
+// then calls previewInsertImage
+function updateInsertImageDialog () {
+ var imgnum = $('#insert_image_imgnum').val();
+ $('#insert_image_loading').hide();
+ $('#insert_image_preview').attr('src',imgobj[imgnum].src);
+ previewInsertImage();
+}
+
+// updates preview width/height/alt/float based on current form values
+function previewInsertImage () {
+ $('#insert_image_preview').css('width',$('#insert_image_width').val());
+ $('#insert_image_preview').css('height',$('#insert_image_height').val());
+ $('#insert_image_preview').css('float',$('#insert_image_float').val());
+ $('#insert_image_preview').attr('alt',$('#insert_image_alt').val());
+}
+
+// constructs html based on the form contents,
+// passes it to callback & closes dialog
+function insertImage() {
+ var imgnum = $('#insert_image_imgnum').val();
+ if (!(imgnum && imgobj[imgnum])) {
+ return '';
+ }
+ var width = $('#insert_image_width').val() || '';
+ var height = $('#insert_image_height').val() || '';
+ var alt = $('#insert_image_alt').val() || '';
+ var float = $('#insert_image_float').val();
+ var imgtag = '<IMG SRC="' + imgobj[imgnum].src + '"';
+ if (width) {
+ imgtag += ' WIDTH="' + width + '"';
+ }
+ if (height) {
+ imgtag += ' HEIGHT="' + height + '"';
+ }
+ if (alt) {
+ imgtag += ' ALT="' + alt + '"';
+ }
+ if (float) {
+ imgtag += ' STYLE="float: ' + float + '"';
+ }
+ imgtag += '>';
+ <% $opt{'callback'} %>(imgtag);
+ $( '#insert_image_dialog' ).dialog( 'close' );
+}
+
+// uses xmlhttp request to initialize image list & refresh it after uploads
+function refreshImageList (fromupload) {
+ get_template_image('no_src','1',
+ function (result) {
+ if (fromupload) {
+ $("#TemplateImageUploadForm")[0].reset();
+ }
+ var images = JSON.parse(result) || [];
+ var latest;
+ for (i = 0; i < images.length; i++) {
+ if ( $("#insert_image_imgnum option[value='" + images[i].imgnum + "']").length == 0 ) {
+ $("#insert_image_imgnum").append('<OPTION VALUE="'+images[i].imgnum+'">'+images[i].name+'</OPTION>');
+ latest = images[i].imgnum;
+ }
+ }
+ if (fromupload) {
+ location.hash = "insert_image_dialog";
+ if (latest) {
+ // small risk of a race condition with other newly-uploaded images,
+ // but does no real damage (our image still shows up in the list)
+ insertImageDialog(latest);
+ }
+ }
+ }
+ );
+}
+
+</SCRIPT>
+
+<%init>
+my %opt = @_;
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+die "access denied"
+ unless $curuser->access_right([ 'View templates', 'View global templates',
+ 'Edit templates', 'Edit global templates', ]);
+
+my $canedit = $curuser->access_right([ 'Edit templates', 'Edit global templates' ]);
+</%init>
+
diff --git a/httemplate/elements/tr-pkg_svc.html b/httemplate/elements/tr-pkg_svc.html
index cfef51ce2..de3f95a3a 100644
--- a/httemplate/elements/tr-pkg_svc.html
+++ b/httemplate/elements/tr-pkg_svc.html
@@ -1,8 +1,13 @@
<TR>
<TD CLASS="background" COLSPAN=99>
+<SCRIPT>
+var provision_hold_td = [];
+var provision_hold_input = [];
+</SCRIPT>
+
<% itable('', 4, 1) %><TR><TD VALIGN="top">
-<% $thead %>
+<% pkg_svc_thead() %>
%foreach my $part_svc ( @part_svc ) {
% my $svcpart = $part_svc->svcpart;
@@ -78,24 +83,52 @@
<INPUT TYPE="checkbox" NAME="no_bulk_skip<% $svcpart %>" VALUE="Y"<% $bulk_skip =~ /^Y/i ? '' : ' CHECKED' %>>
</TD>
- <TD ALIGN="center">
- <INPUT TYPE="checkbox" NAME="provision_hold<% $svcpart %>" VALUE="Y"<% $provision_hold =~ /^Y/i ? ' CHECKED' : ''%>>
+ <TD ALIGN="center" ID="td_provision_hold<% $svcpart %>">
+ <INPUT TYPE="checkbox" ID="input_provision_hold<% $svcpart %>" NAME="provision_hold<% $svcpart %>" VALUE="Y"<% $provision_hold =~ /^Y/i ? ' CHECKED' : ''%>>
</TD>
+<SCRIPT>
+provision_hold_td.push(document.getElementById('td_provision_hold<% $svcpart %>'));
+provision_hold_input.push(document.getElementById('input_provision_hold<% $svcpart %>'));
+</SCRIPT>
</TR>
% foreach ( 1 .. $columns-1 ) {
% if ( $count == int( $_ * scalar(@part_svc) / $columns ) ) {
%
- </TABLE></TD><TD VALIGN="top"><% $thead %>
+ </TABLE></TD><TD VALIGN="top"><% pkg_svc_thead() %>
% }
% }
% $count++;
%
-% }
+% } # foreach $part_svc
</TR></TABLE></TD></TR></TABLE>
+<SCRIPT>
+// start_on_hold from edit/part_pkg.cgi
+// toggles display of provision_hold checkboxes when that changes
+function provision_hold_check () {
+ var start_on_hold = document.getElementById('start_on_hold');
+ if (start_on_hold) {
+ for (i = 0; i < provision_hold_td.length; i++) {
+ provision_hold_td[i].style.display = start_on_hold.checked ? '' : 'none';
+ }
+ for (i = 0; i < provision_hold_input.length; i++) {
+ provision_hold_input[i].disabled = start_on_hold.checked ? false : true;
+ }
+ }
+}
+function provision_hold_init () {
+ var start_on_hold = document.getElementById('start_on_hold');
+ if (start_on_hold) {
+ start_on_hold.onchange = provision_hold_check;
+ provision_hold_check();
+ }
+}
+provision_hold_init();
+</SCRIPT>
+
% if ( scalar(@possible_exports) > 0 || scalar(@mapped_exports) > 0 ) {
<TABLE><TR>
<TH BGCOLOR="#dcdcdc">Export</TH>
@@ -130,15 +163,21 @@
my %opt = @_;
my $cgi = $opt{'cgi'};
-my $thead = "\n\n". ntable('#cccccc', 2).
- '<TR>'.
- '<TH BGCOLOR="#dcdcdc"><FONT SIZE=-1>Quan.</FONT></TH>'.
- '<TH BGCOLOR="#dcdcdc"><FONT SIZE=-1>Primary</FONT></TH>'.
- '<TH BGCOLOR="#dcdcdc">Service</TH>'.
- '<TH BGCOLOR="#dcdcdc"><FONT SIZE=-1>Hide<BR>from<BR>Invoices</FONT></TH>'.
- '<TH BGCOLOR="#dcdcdc"><FONT SIZE=-1>Bulk<BR>Charge</FONT></TH>'.
- '<TH BGCOLOR="#dcdcdc"><FONT SIZE=-1>Hold<BR>Until<BR>Provision</FONT></TH>'.
- '</TR>';
+my $thead_count = 0;
+sub pkg_svc_thead {
+ $thead_count += 1;
+ return "\n\n". ntable('#cccccc', 2).
+ '<TR>'.
+ '<TH BGCOLOR="#dcdcdc"><FONT SIZE=-1>Quan.</FONT></TH>'.
+ '<TH BGCOLOR="#dcdcdc"><FONT SIZE=-1>Primary</FONT></TH>'.
+ '<TH BGCOLOR="#dcdcdc">Service</TH>'.
+ '<TH BGCOLOR="#dcdcdc"><FONT SIZE=-1>Hide<BR>from<BR>Invoices</FONT></TH>'.
+ '<TH BGCOLOR="#dcdcdc"><FONT SIZE=-1>Bulk<BR>Charge</FONT></TH>'.
+ '<TH BGCOLOR="#dcdcdc" ID="th_provision_hold' . $thead_count . '"><FONT SIZE=-1>Remove Hold After Provisioning</FONT></TH>'.
+ '</TR>'.
+ qq!<SCRIPT>provision_hold_td.push(document.getElementById('th_provision_hold$thead_count'))</SCRIPT>!;
+;
+}
my $part_pkg = $opt{'object'};
my $pkgpart = $part_pkg->pkgpart;
diff --git a/httemplate/elements/tr-polygon.html b/httemplate/elements/tr-polygon.html
new file mode 100644
index 000000000..6990d3da6
--- /dev/null
+++ b/httemplate/elements/tr-polygon.html
@@ -0,0 +1,5 @@
+<tr>
+<td colspan=2>
+<& polygon.html, @_ &>
+</td>
+</tr>
diff --git a/httemplate/elements/tr-select-months.html b/httemplate/elements/tr-select-months.html
index 3ff28f99b..b90ce1ed7 100644
--- a/httemplate/elements/tr-select-months.html
+++ b/httemplate/elements/tr-select-months.html
@@ -7,6 +7,5 @@ $opt{labels} = { '' => '',
map { $_ => emt('[quant,_1,month]', $_) } 1 .. $max
};
-warn Dumper(\%opt);
</%init>
<& tr-select.html, %opt &>
diff --git a/httemplate/elements/tr-td-label.html b/httemplate/elements/tr-td-label.html
index 78690f1fb..f7067221b 100644
--- a/httemplate/elements/tr-td-label.html
+++ b/httemplate/elements/tr-td-label.html
@@ -9,7 +9,7 @@ Actually <TR> <TH> $label </TH>
VALIGN = "<% $opt{'valign'} || 'top' %>"
STYLE = "<% $style %>"
ID = "<% $opt{label_id} || $opt{id}. '_label0' %>"
- ><% $required %><% $opt{label} %></TD>
+ ><% $required %><% $opt{label} %></TH>
<%init>