[freeside-commits] branch master updated. f041c3f6e17bdacf8ad6b0da87342ef84e7db404

Mark Wells mark at 420.am
Tue Dec 30 16:05:12 PST 2014


The branch, master has been updated
       via  f041c3f6e17bdacf8ad6b0da87342ef84e7db404 (commit)
       via  63e6a91136d87591d57a7f4e006dbfb41906a02c (commit)
      from  463e2e6d248db7c3787cfbe1074abdb84ce2010e (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit f041c3f6e17bdacf8ad6b0da87342ef84e7db404
Author: Mark Wells <mark at freeside.biz>
Date:   Tue Dec 30 16:04:48 2014 -0800

    import deployment zone census block list, #32625

diff --git a/FS/FS/Record.pm b/FS/FS/Record.pm
index 9fa8296..10b1cf6 100644
--- a/FS/FS/Record.pm
+++ b/FS/FS/Record.pm
@@ -1711,7 +1711,7 @@ Table name (required).
 
 =item params
 
-Listref of field names for static fields.  They will be given values from the
+Arrayref of field names for static fields.  They will be given values from the
 PARAMS hashref and passed as a "params" hashref to batch_import.
 
 =item formats
@@ -1760,10 +1760,10 @@ format_types).
 
 =back
 
-PARAMS is a base64-encoded Storable string containing the POSTed data as
-a hash ref.  It normally contains at least one field, "uploaded files",
-generated by /elements/file-upload.html and containing the list of uploaded
-files.  Currently only supports a single file named "file".
+PARAMS is a hashref (or base64-encoded Storable hashref) containing the 
+POSTed data.  It must contain the field "uploaded files", generated by 
+/elements/file-upload.html and containing the list of uploaded files.
+Currently only supports a single file named "file".
 
 =cut
 
diff --git a/FS/FS/deploy_zone.pm b/FS/FS/deploy_zone.pm
index 6142b91..38dd7dc 100644
--- a/FS/FS/deploy_zone.pm
+++ b/FS/FS/deploy_zone.pm
@@ -3,6 +3,8 @@ package FS::deploy_zone;
 use strict;
 use base qw( FS::o2m_Common FS::Record );
 use FS::Record qw( qsearch qsearchs dbh );
+use Storable qw(thaw);
+use MIME::Base64;
 
 =head1 NAME
 
@@ -265,6 +267,55 @@ sub deploy_zone_vertex {
   });
 }
 
+=back
+
+=head2 SUBROUTINES
+
+=over 4
+
+=item process_batch_import JOB, PARAMS
+
+=cut
+
+sub process_batch_import {
+  eval {
+    use FS::deploy_zone_block;
+    use FS::deploy_zone_vertex;
+  };
+  my $job = shift;
+  my $param = shift;
+  if (!ref($param)) {
+    $param = thaw(decode_base64($param));
+  }
+
+  # even if creating a new zone, the deploy_zone object should already
+  # be inserted by this point
+  my $zonenum = $param->{zonenum}
+    or die "zonenum required";
+  my $zone = FS::deploy_zone->by_key($zonenum)
+    or die "deploy_zone #$zonenum not found";
+  my $opt;
+  if ( $zone->zonetype eq 'B' ) {
+    $opt = { 'table'    => 'deploy_zone_block',
+             'params'   => [ 'zonenum', 'censusyear' ],
+             'formats'  => { 'plain' => [ 'censusblock' ] },
+             'default_csv' => 1,
+           };
+    $job->update_statustext('1,Inserting census blocks');
+  } elsif ( $zone->zonetype eq 'P' ) {
+    $opt = { 'table'    => 'deploy_zone_vertex',
+             'params'   => [ 'zonenum' ],
+             'formats'  => { 'plain' => [ 'latitude', 'longitude' ] },
+             'default_csv' => 1,
+           };
+  } else {
+    die "don't know how to import to zonetype ".$zone->zonetype;
+  }
+
+  FS::Record::process_batch_import( $job, $opt, $param );
+
+}
+        
 =head1 BUGS
 
 =head1 SEE ALSO
diff --git a/httemplate/edit/deploy_zone-fixed.html b/httemplate/edit/deploy_zone-fixed.html
index fb26c49..90d1b66 100644
--- a/httemplate/edit/deploy_zone-fixed.html
+++ b/httemplate/edit/deploy_zone-fixed.html
@@ -16,6 +16,8 @@
         'is_business'     => 'Business/government',
         'blocknum'        => '',
         'active_date'     => 'Active since',
+        'file'            => 'Import blocks from text file',
+        'censusyear'      => 'as census year',
     },
     'fields'        => [
         { field         => 'zonetype',
@@ -54,6 +56,19 @@
         'cir_speed_up',
 
         { type => 'tablebreak-tr-title', value => 'Census blocks'},
+        { field => 'file',
+          type  => 'file-upload',
+        },
+        { field => 'format',
+          type  => 'hidden',
+          value => 'plain',
+        },
+        { field => 'censusyear',
+          type  => 'select',
+          options => [ '', qw( 2013 2012 2011 ) ],
+        },
+
+        { type => 'tablebreak-tr-title', value => '', },
         { field => 'blocknum',
           type              => 'deploy_zone_block',
           o2m_table         => 'deploy_zone_block',
diff --git a/httemplate/edit/process/deploy_zone-fixed.html b/httemplate/edit/process/deploy_zone-fixed.html
index c14c81c..eae3a74 100644
--- a/httemplate/edit/process/deploy_zone-fixed.html
+++ b/httemplate/edit/process/deploy_zone-fixed.html
@@ -1,9 +1,14 @@
 <& elements/process.html, 
-    error_redirect => popurl(2).'deploy_zone-fixed.html?',
+    debug => 1,
+    error_redirect => popurl(2).'deploy_zone-fixed.html',
     table       => 'deploy_zone',
     viewall_dir => 'browse',
-    process_o2m => 
-      { 'table'  => 'deploy_zone_block',
-                     'fields' => [qw( censusblock censusyear )]
-      },
+    process_o2m => {
+      'table'  => 'deploy_zone_block',
+      'fields' => [qw( censusblock censusyear )]
+    },
+    process_upload => {
+      'process' => 'misc/process/deploy_zone-import.html',
+      'fields' => [qw( censusyear format )],
+    },
 &>
diff --git a/httemplate/edit/process/deploy_zone-mobile.html b/httemplate/edit/process/deploy_zone-mobile.html
index c913c5c..7b8f911 100644
--- a/httemplate/edit/process/deploy_zone-mobile.html
+++ b/httemplate/edit/process/deploy_zone-mobile.html
@@ -1,5 +1,5 @@
 <& elements/process.html, 
-    error_redirect => popurl(2).'deploy_zone-mobile.html?',
+    error_redirect => popurl(2).'deploy_zone-mobile.html',
     table       => 'deploy_zone',
     viewall_dir => 'browse',
     process_o2m => 
diff --git a/httemplate/edit/process/elements/process.html b/httemplate/edit/process/elements/process.html
index 0439d4e..eba0304 100644
--- a/httemplate/edit/process/elements/process.html
+++ b/httemplate/edit/process/elements/process.html
@@ -62,6 +62,13 @@ Example:
                       'fields' => [qw( fieldname fieldname2 )],
                     },
 
+   'process_upload' => {
+                         'process'  => 'misc/mytable-import.html',
+                          # fields to pass to the back end job, besides the 
+                          # primary key of the object
+                         'fields'   => [qw( fieldname fieldname2 )],
+                       },
+
    'skip_process' => 0, #boolean, if set true, will skip the main table
                         #add/edit processing and only run any linked table
                         #process_ items
@@ -94,9 +101,6 @@ Example:
 </%doc>
 %if ( $error ) {
 %
-%  my $edit_ext = $opt{'edit_ext'} || 'html';
-%  my $url = $opt{'error_redirect'} || popurl(2)."$table.$edit_ext";
-
 %  #my $query = $m->scomp('/elements/create_uri_query');
 %  #$cgi->redirect("$url?$query");
 %  if ( length($cgi->query_string) > 1920 ) { #stupid IE 2083 URL limit
@@ -114,16 +118,48 @@ Example:
 %          " attempting to set redirect$session to ". $cgi->query_string."\n";
 %    }
 %
-<% $cgi->redirect("$url?redirect=$session") %>
+<% $cgi->redirect("$error_redirect?redirect=$session") %>
 %
 %  } else {
 %
-<% $cgi->redirect("$url?". $cgi->query_string ) %>
+<% $cgi->redirect("$error_redirect?". $cgi->query_string ) %>
 %
-%  } 
+%  }
 %
 % #different ways of handling success
 %
+%} elsif ( $opt{'process_upload'} and @uploaded_files ) {
+%
+% # construct a form to pass all the requested fields, the 
+%
+<& /elements/header.html &>
+<form name="UploadForm">
+%   my $job_fields = $opt{'process_upload'}{'fields'};
+%   foreach my $field ( @$job_fields ) {
+  <input type="hidden" name="<% $field %>" value="<% $cgi->param($field) |h %>">
+%   }
+%   push @$job_fields, 'uploaded_files', $pkey;
+%
+  <input type="hidden" name="uploaded_files" value="<% join(',', @uploaded_files) %>">
+  <input type="hidden" name="<% $pkey %>" value="<% $new->get($pkey) %>">
+<& /elements/progress-init.html,
+  'UploadForm',
+  $job_fields,
+  $fsurl . $opt{'process_upload'}{'process'},
+  {
+    url => $redirect,
+    error_url => "$error_redirect?$new_pkey"
+  },
+&>
+<input type="submit" style="display:none">
+</form>
+<script>
+<&| /elements/onload.js &>
+process();
+</&>
+</script>
+<& /elements/footer.html &>
+
 %} elsif ( $opt{'popup_reload'} ) {
 
   <% include('/elements/header-popup.html', $opt{'popup_reload'} ) %>
@@ -136,26 +172,8 @@ Example:
   </HTML>
 
 %} else {
-%  
-%  $opt{'redirect'} = &{$opt{'redirect'}}($cgi, $new)
-%    if ref($opt{'redirect'}) eq 'CODE';
-%
-%  if ( $opt{'redirect'} ) {
-%
-<% $cgi->redirect( $opt{'redirect'}. $new_pkey) %>
-%
-%  } else { 
-%
-%    my $ext = $opt{'viewall_ext'} || 'html';
-%    my $viewall_dir = $opt{'viewall_dir'} || 'search';
-%    my $viewall_url = $opt{'viewall_url'} || ($viewall_dir . "/$table.$ext");
-%
-%#<% $cgi->redirect( popurl(3). ($opt{viewall_dir}||'search'). "/$table.$ext" ) %>
-<% $cgi->redirect( popurl(3) . $viewall_url ) %>
-%  }
-%
+<% $cgi->redirect($redirect) %>
 %}
-%
 <%init>
 
 my $me = 'process.html:';
@@ -207,6 +225,8 @@ if ( $bfield ) {
   #warn join(',', @values);
 }
 
+my @uploaded_files;
+
 my $new;
 my $new_pkey = '';
 foreach my $value ( @values ) {
@@ -345,6 +365,47 @@ foreach my $value ( @values ) {
   }
 
 
+  if ( !$error and $opt{'process_upload'} ) {
+    # mostly duplicates misc/file-upload.html
+    $cgi->param('upload_fields') =~ /^([,\w]+)$/
+      or $error = "invalid upload_fields";
+    my $fields = $1;
+
+    my $dir = $FS::UID::cache_dir. "/cache.". $FS::UID::datasrc;
+
+    foreach my $field (split /,/, $fields) {
+      next if $error;
+      my $source_name = $cgi->param($field);
+
+      if ( $opt{'debug'} ) {
+        warn "$me processing upload: $source_name\n";
+      }
+      my $fh = $cgi->upload( $field ); # if no file provided, that's fine
+      next if !$fh;
+
+      my $suffix = '';
+      if ( $source_name =~ /(\.\w+)$/ ) {
+        $suffix = lc($1);
+      }
+
+      my $sh = File::Temp->new( TEMPLATE => 'upload.XXXXXXXX',
+                                SUFFIX   => $suffix,
+                                DIR      => $dir,
+                                UNLINK   => 0,
+                              )
+        or $error ||= "can't open temporary file to store upload: $!\n";
+      next if $error;
+      while(<$fh>) {
+        print $sh $_;
+      }
+      $sh->filename =~ m!.*/([.\w]+)$!;
+      push @uploaded_files, "$field:$1";
+      if ( $opt{'debug'} ) {
+        warn "uploaded as $1\n";
+      }
+    }
+  }
+
   if ( $error ) {
 
     $cgi->param('error', $error);
@@ -365,4 +426,30 @@ foreach my $value ( @values ) {
   last if $error;
 
 }
+
+# set up redirect URLs
+
+my $redirect;
+if ( !$error ) {
+  $opt{'redirect'} = &{$opt{'redirect'}}($cgi, $new)
+    if ref($opt{'redirect'}) eq 'CODE';
+
+  if ( $opt{'redirect'} ) {
+
+    $redirect = $opt{'redirect'} . $new_pkey;
+
+  } else { 
+
+    my $ext = $opt{'viewall_ext'} || 'html';
+    my $viewall_dir = $opt{'viewall_dir'} || 'search';
+    my $viewall_url = $opt{'viewall_url'} || ($viewall_dir . "/$table.$ext");
+
+    $redirect = popurl(3) . $viewall_url;
+  
+  }
+}
+
+my $edit_ext = $opt{'edit_ext'} || 'html';
+my $error_redirect = $opt{'error_redirect'}
+                     || popurl(2)."$table.$edit_ext";
 </%init>
diff --git a/httemplate/elements/file-upload.html b/httemplate/elements/file-upload.html
index 034eaec..f69df34 100644
--- a/httemplate/elements/file-upload.html
+++ b/httemplate/elements/file-upload.html
@@ -47,6 +47,11 @@
     }
   }
 
+<&| onload.js &>
+// force the form to submit as multipart
+var thisform = document.getElementById('uploaded_files').form;
+thisform.enctype = 'multipart/form-data';
+</&>
 </SCRIPT>
 
 <INPUT TYPE="hidden" NAME="uploaded_files" ID="uploaded_files" VALUE="" />
diff --git a/httemplate/elements/progress-init.html b/httemplate/elements/progress-init.html
index cef54b8..5b42aa1 100644
--- a/httemplate/elements/progress-init.html
+++ b/httemplate/elements/progress-init.html
@@ -17,6 +17,9 @@ In misc/something.html:
          # redirecting to the URL.
          #or { popup_url => $p.'popup_contents.html' }
          # which loads that URL into the popup after completion
+         #or { url => $p.'where_to_go.html',
+               error_url => $p.'where_we_just_were.html' }
+         # to redirect somewhere different on error
          ) %>
   </FORM>
   <SCRIPT TYPE="text/javascript>process();</SCRIPT>
@@ -45,6 +48,33 @@ sub process_whatever { #class method
   return 'this value will be ignored';
 }
 
+Internal notes:
+
+This component creates two JS functions: process(), which starts the 
+submission process, and start_job(), which starts the job on the 
+server side.
+
+process() does the following:
+- disable the form submit button
+- for all form fields named in "fields", collect their values into an array
+- declare a callback function "myCallback"
+- pass the array and callback to start_job()
+
+start_job() is an xmlhttp standard function that turns the array of values 
+into a JSON string, posts it to the location given in $action, receives a 
+job number back, and then invokes the callback with the job number as an 
+argument. Normally, the post target script will use FS::UI::Web::JSRPC to insert
+a queue job (with the form field values as arguments), and return its
+job number.
+
+myCallback() opens an Overlib popup containing progress-popup.html, with 
+the job number, form name, and destination options (url, message, popup_url,
+error_url) as URL parameters. This popup will poll the server for the status
+of the job, display a progress bar, and on completion, either redirect to 
+'url' or 'popup_url', display 'message' in the popup window, or (on failure)
+display the job statustext as an error message. If 'error_url' is specified,
+the "Close" button in the popup will then redirect the user to that location.
+
 </%doc>
 <% include('/elements/xmlhttp.html',
               'method' => 'POST',
@@ -108,7 +138,9 @@ function <%$key%>process () {
 
 function <%$key%>myCallback( jobnum ) {
 
-  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 );
+  var url = <% $progress_url->as_string |js_string %>;
+  url = url.replace('_JOBNUM_', jobnum);
+  overlib( OLiframeContent(url, 444, 168, '<% $popup_name %>'), CAPTION, 'Please wait...', STICKY, AUTOSTATUSCAP, CLOSETEXT, '', CLOSECLICK, MIDX, 0, MIDY, 0 );
 
 }
 
@@ -119,18 +151,23 @@ function <%$key%>myCallback( jobnum ) {
 my( $formname, $fields, $action, $url_or_message, $key ) = @_;
 $key = '' unless defined $key;
 
-my $url_or_message_link;
+my %dest_info;
 if ( ref($url_or_message) ) { #its a message or something
-  $url_or_message_link = 'message='. uri_escape( $url_or_message->{'message'} );
-  $url_or_message_link .= ';url='.   uri_escape( $url_or_message->{'url'} )
-    if $url_or_message->{'url'};
-  $url_or_message_link = 'popup_url=' .uri_escape( $url_or_message->{'popup_url'} )
-    if $url_or_message->{'popup_url'};
-
+  %dest_info = map { $_ => $url_or_message->{$_} }
+               grep { $url_or_message->{$_} }
+               qw( message url popup_url error_url );
 } else {
-  $url_or_message_link = "url=$url_or_message";
+  # it can also just be a url
+  %dest_info = ( 'url' => $url_or_message );
 }
 
+my $progress_url = URI->new($fsurl.'elements/progress-popup.html');
+$progress_url->query_form(
+  'jobnum'    => '_JOBNUM_',
+  'formname'  => $formname,
+  %dest_info,
+);
+
 #stupid safari is caching the "location" of popup iframs, and submitting them
 #instead of displaying them.  this should prevent that.
 my $popup_name = 'popup-'.time. "-$$-". rand() * 2**32;
diff --git a/httemplate/elements/progress-popup.html b/httemplate/elements/progress-popup.html
index 2d27388..a37cf24 100644
--- a/httemplate/elements/progress-popup.html
+++ b/httemplate/elements/progress-popup.html
@@ -4,6 +4,7 @@
 %  my $message = $cgi->param('message');
 %  my $popup_url = $cgi->param('popup_url');
 %  my $formname = scalar($cgi->param('formname'));
+%  my $error_url = $cgi->param('error_url');
 %
 
 <HTML>
@@ -62,7 +63,7 @@ function updateStatus( status_statustext ) {
         }
 %   }
 
-% } elsif ( $url ) { 
+% } elsif ( $url ) {
     parent.nd(1);
     window.top.location.href = '<% $url %>';
 % } elsif ( $popup_url ) {
@@ -81,9 +82,16 @@ function updateStatus( status_statustext ) {
     window.top.location.href = statustext.substr(8, statustext.length-18);
 
   } else if ( status.indexOf('error') > -1 ) {
+%
+% # default behavior: just close the popup
+% my $onClick = 'parent.nd(1);';
+% if ( $error_url ) { # then on clicking to confirm, redirect somewhere
+%   $onClick = "window.top.location.href = \\'$error_url\\';";
+% }
+
     document.getElementById("progress_message").innerHTML = '<FONT SIZE="+1" COLOR="#FF0000">Error: ' + statustext + '</FONT>';
     document.getElementById("progress_bar").innerHTML = '';
-    document.getElementById("progress_percent").innerHTML = '<INPUT TYPE="button" VALUE="OK" onClick="parent.nd(1);">';
+    document.getElementById("progress_percent").innerHTML = '<INPUT TYPE="button" VALUE="OK" onClick="<% $onClick %>">';
     document.getElementById("progress_jobnum").innerHTML = '';
     if ( parent.document.<%$formname%>.submit.disabled == true ) {
       parent.document.<%$formname%>.submit.disabled=false;
diff --git a/httemplate/elements/tr-file-upload.html b/httemplate/elements/tr-file-upload.html
new file mode 100644
index 0000000..c50e4cb
--- /dev/null
+++ b/httemplate/elements/tr-file-upload.html
@@ -0,0 +1 @@
+<& file-upload.html, @_ &>
diff --git a/httemplate/misc/process/deploy_zone-import.html b/httemplate/misc/process/deploy_zone-import.html
new file mode 100644
index 0000000..a0f1717
--- /dev/null
+++ b/httemplate/misc/process/deploy_zone-import.html
@@ -0,0 +1,9 @@
+<% $server->process %>
+<%init>
+
+die "access denied"
+  unless $FS::CurrentUser::CurrentUser->access_right('Import');
+
+my $server = new FS::UI::Web::JSRPC 'FS::deploy_zone::process_batch_import', $cgi;
+
+</%init>

commit 63e6a91136d87591d57a7f4e006dbfb41906a02c
Author: Mark Wells <mark at freeside.biz>
Date:   Tue Dec 30 16:02:56 2014 -0800

    fix misspelling of cache directory, #31834

diff --git a/FS/FS/part_export/voip_ms.pm b/FS/FS/part_export/voip_ms.pm
index 44ce908..53a4926 100644
--- a/FS/FS/part_export/voip_ms.pm
+++ b/FS/FS/part_export/voip_ms.pm
@@ -503,7 +503,7 @@ sub cache {
   my $province = shift;
 
   $CACHE ||= Cache::FileCache->new({
-    'cache_root' => $FS::UID::cache_dir.'/cache'.$FS::UID::datasrc,
+    'cache_root' => $FS::UID::cache_dir.'/cache.'.$FS::UID::datasrc,
     'namespace'  => __PACKAGE__,
     'default_expires_in' => $cache_timeout,
   });

-----------------------------------------------------------------------

Summary of changes:
 FS/FS/Record.pm                                    |   10 +-
 FS/FS/deploy_zone.pm                               |   51 ++++++++
 FS/FS/part_export/voip_ms.pm                       |    2 +-
 httemplate/edit/deploy_zone-fixed.html             |   15 +++
 httemplate/edit/process/deploy_zone-fixed.html     |   15 ++-
 httemplate/edit/process/deploy_zone-mobile.html    |    2 +-
 httemplate/edit/process/elements/process.html      |  137 ++++++++++++++++----
 httemplate/elements/file-upload.html               |    5 +
 httemplate/elements/progress-init.html             |   55 ++++++--
 httemplate/elements/progress-popup.html            |   12 +-
 httemplate/elements/tr-file-upload.html            |    1 +
 ..._device-import.html => deploy_zone-import.html} |    2 +-
 12 files changed, 258 insertions(+), 49 deletions(-)
 create mode 100644 httemplate/elements/tr-file-upload.html
 copy httemplate/misc/process/{part_device-import.html => deploy_zone-import.html} (69%)




More information about the freeside-commits mailing list