[freeside-commits] branch master updated. f413badbfe4676563d11b528838a21d9ceb8da14

Mark Wells mark at 420.am
Wed Jul 6 11:53:29 PDT 2016


The branch, master has been updated
       via  f413badbfe4676563d11b528838a21d9ceb8da14 (commit)
       via  df43a12a1c219709f27297ad6b53f6662b56c10c (commit)
       via  2a0b5339081a439a8c5ec1f2b9cd28b63fd3fa49 (commit)
      from  1e63ee17a4f08d65f163bfa0bae4b8490cb4fae3 (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 f413badbfe4676563d11b528838a21d9ceb8da14
Author: Mark Wells <mark at freeside.biz>
Date:   Wed Jul 6 11:53:13 2016 -0700

    service label localization, internals and UI, #71347

diff --git a/FS/FS/Mason.pm b/FS/FS/Mason.pm
index 24ddf79..d625fbd 100644
--- a/FS/FS/Mason.pm
+++ b/FS/FS/Mason.pm
@@ -412,6 +412,7 @@ if ( -e $addl_handler_use_file ) {
   use FS::fiber_olt;
   use FS::olt_site;
   use FS::access_user_page_pref;
+  use FS::part_svc_msgcat;
   # Sammath Naur
 
   if ( $FS::Mason::addl_handler_use ) {
diff --git a/FS/FS/Schema.pm b/FS/FS/Schema.pm
index a50b551..f88fea9 100644
--- a/FS/FS/Schema.pm
+++ b/FS/FS/Schema.pm
@@ -3682,6 +3682,24 @@ sub tables_hashref {
                         ],
     },
 
+    'part_svc_msgcat' => {
+      'columns' => [
+        'svcpartmsgnum',  'serial',     '',        '', '', '',
+        'svcpart',           'int',     '',        '', '', '',
+        'locale',        'varchar',     '',        16, '', '',
+        'svc',           'varchar',     '',   $char_d, '', '',
+      ],
+      'primary_key'  => 'svcpartmsgnum',
+      'unique'       => [ [ 'svcpart', 'locale' ] ],
+      'index'        => [],
+      'foreign_keys' => [
+                          { columns    => [ 'svcpart' ],
+                            table      => 'part_svc',
+                          },
+                        ],
+    },
+
+
     #(this should be renamed to part_pop)
     'svc_acct_pop' => {
       'columns' => [
diff --git a/FS/FS/part_svc.pm b/FS/FS/part_svc.pm
index 621a554..dcc7843 100644
--- a/FS/FS/part_svc.pm
+++ b/FS/FS/part_svc.pm
@@ -1,5 +1,5 @@
 package FS::part_svc;
-use base qw(FS::Record);
+use base qw(FS::o2m_Common FS::Record);
 
 use strict;
 use vars qw( $DEBUG );
@@ -11,6 +11,7 @@ use FS::part_export;
 use FS::export_svc;
 use FS::cust_svc;
 use FS::part_svc_class;
+use FS::part_svc_msgcat;
 
 FS::UID->install_callback(sub {
     # preload the cache and make sure all modules load
@@ -621,6 +622,24 @@ sub svc_x {
   map { $_->svc_x } $self->cust_svc;
 }
 
+=item svc_locale LOCALE
+
+Returns a customer-viewable service definition label in the chosen LOCALE.
+If there is no entry for that locale or if LOCALE is empty, returns
+part_svc.svc.
+
+=cut
+
+sub svc_locale {
+  my( $self, $locale ) = @_;
+  return $self->svc unless $locale;
+  my $part_svc_msgcat = qsearchs('part_svc_msgcat', {
+    svcpart => $self->svcpart,
+    locale  => $locale
+  }) or return $self->svc;
+  $part_svc_msgcat->svc;
+}
+
 =back
 
 =head1 CLASS METHODS
@@ -883,6 +902,12 @@ sub process {
     $param->{'svcpart'} = $new->getfield('svcpart');
   }
 
+  $error ||= $new->process_o2m(
+    'table'   => 'part_svc_msgcat',
+    'params'  => $param,
+    'fields'  => [ 'locale', 'svc' ],
+  );
+
   die "$error\n" if $error;
 }
 
diff --git a/FS/FS/part_svc_msgcat.pm b/FS/FS/part_svc_msgcat.pm
new file mode 100644
index 0000000..6d69198
--- /dev/null
+++ b/FS/FS/part_svc_msgcat.pm
@@ -0,0 +1,131 @@
+package FS::part_svc_msgcat;
+use base qw( FS::Record );
+
+use strict;
+use FS::Locales;
+
+=head1 NAME
+
+FS::part_svc_msgcat - Object methods for part_svc_msgcat records
+
+=head1 SYNOPSIS
+
+  use FS::part_svc_msgcat;
+
+  $record = new FS::part_svc_msgcat \%hash;
+  $record = new FS::part_svc_msgcat { 'column' => 'value' };
+
+  $error = $record->insert;
+
+  $error = $new_record->replace($old_record);
+
+  $error = $record->delete;
+
+  $error = $record->check;
+
+=head1 DESCRIPTION
+
+An FS::part_svc_msgcat object represents localized labels of a service 
+definition.  FS::part_svc_msgcat inherits from FS::Record.  The following
+fields are currently supported:
+
+=over 4
+
+=item svcpartmsgnum
+
+primary key
+
+=item svcpart
+
+Service definition
+
+=item locale
+
+locale
+
+=item svc
+
+Localized service name (customer-viewable)
+
+=back
+
+=head1 METHODS
+
+=over 4
+
+=item new HASHREF
+
+Creates a new record.  To add the record to the database, see L<"insert">.
+
+Note that this stores the hash reference, not a distinct copy of the hash it
+points to.  You can ask the object for a copy with the I<hash> method.
+
+=cut
+
+# the new method can be inherited from FS::Record, if a table method is defined
+
+sub table { 'part_svc_msgcat'; }
+
+=item insert
+
+Adds this record to the database.  If there is an error, returns the error,
+otherwise returns false.
+
+=cut
+
+# the insert method can be inherited from FS::Record
+
+=item delete
+
+Delete this record from the database.
+
+=cut
+
+# the delete method can be inherited from FS::Record
+
+=item replace OLD_RECORD
+
+Replaces the OLD_RECORD with this one in the database.  If there is an error,
+returns the error, otherwise returns false.
+
+=cut
+
+# the replace method can be inherited from FS::Record
+
+=item check
+
+Checks all fields to make sure this is a valid record.  If there is
+an error, returns the error, otherwise returns false.  Called by the insert
+and replace methods.
+
+=cut
+
+# the check method should currently be supplied - FS::Record contains some
+# data checking routines
+
+sub check {
+  my $self = shift;
+
+  my $error = 
+    $self->ut_numbern('svcpartmsgnum')
+    || $self->ut_foreign_key('svcpart', 'part_svc', 'svcpart')
+    || $self->ut_enum('locale', [ FS::Locales->locales ] )
+    || $self->ut_text('svc')
+  ;
+  return $error if $error;
+
+  $self->SUPER::check;
+}
+
+=back
+
+=head1 BUGS
+
+=head1 SEE ALSO
+
+L<FS::part_svc>, L<FS::Record>, schema.html from the base documentation.
+
+=cut
+
+1;
+
diff --git a/httemplate/browse/part_svc.cgi b/httemplate/browse/part_svc.cgi
index dee4394..b947463 100755
--- a/httemplate/browse/part_svc.cgi
+++ b/httemplate/browse/part_svc.cgi
@@ -112,8 +112,24 @@ function part_export_areyousure(href) {
     </TD>
 % } 
 
-    <TD ROWSPAN=<% $rowspan %> CLASS="grid" BGCOLOR="<% $bgcolor %>"><A HREF="<% $url %>">
-      <% $part_svc->svc %></A></TD>
+    <TD ROWSPAN=<% $rowspan %> CLASS="grid" BGCOLOR="<% $bgcolor %>">
+      <A HREF="<% $url %>">
+        <% $part_svc->svc %>
+      </A>
+%   # any alternate names of the service
+%   my %msgcat = map { $_->locale => $_ } $part_svc->part_svc_msgcat;
+%   my %labels = map { $_ => FS::Locales->description($_) } keys %msgcat;
+%   my @locales = sort { $labels{$a} cmp $labels{$b} } keys %msgcat;
+%   if ( @locales ) {
+      <BR>
+      <FONT SIZE="-1">
+%     foreach my $locale (@locales) {
+        <% $labels{$locale} %>: <% $msgcat{$locale}->get('svc') %>
+        <BR>
+%     }
+      </FONT>
+%   }
+    </TD>
 
     <TD ROWSPAN=<% $rowspan %> CLASS="grid" BGCOLOR="<% $bgcolor %>">
       <% $svcdb %></TD>
diff --git a/httemplate/edit/elements/part_svc_column.html b/httemplate/edit/elements/part_svc_column.html
index 4e112c0..816f342 100644
--- a/httemplate/edit/elements/part_svc_column.html
+++ b/httemplate/edit/elements/part_svc_column.html
@@ -267,8 +267,9 @@ my %communigate_fields = (
 <& /elements/progress-init.html,
   $svcdb, #form name
   [ # form fields to send
-    qw(svc svcpart classnum selfservice_access disabled preserve exportnum),
-    @fields
+    'ALL'
+#    qw(svc svcpart classnum selfservice_access disabled preserve exportnum),
+#    @fields
   ],
   'process/part_svc.cgi',   # target
   $p.'browse/part_svc.cgi', # redirect landing
diff --git a/httemplate/edit/part_pkg.cgi b/httemplate/edit/part_pkg.cgi
index 80a61f8..f2c4aac 100755
--- a/httemplate/edit/part_pkg.cgi
+++ b/httemplate/edit/part_pkg.cgi
@@ -92,7 +92,7 @@
                    { type => 'columnstart' },
                    
                      { field     => 'pkg',
-                       type      => 'text',
+                       type      => 'input-locale-text',
                        size      => 40, #32
                        maxlength => 50,
                      },
@@ -495,42 +495,6 @@ my $recur_show_zero_disabled = 1;
 
 my $pkgpart = '';
 
-my $splice_locale_fields = sub {
-  my( $fields, $pkey_value_callback, $pkg_value_callback ) = @_;
-
-  my $n = 0;
-  my @locale_fields = (
-    map { 
-          my $pkey_value= $pkey_value_callback ? &$pkey_value_callback($_) : '';
-          my $pkg_value = $pkg_value_callback
-                            ? $pkg_value_callback eq 'cgiparam'
-                                ? $cgi->param('pkgpartmsgnum'. $n. '_pkg')
-                                : &$pkg_value_callback($_)
-                            : '';
-          (
-            { field     => 'pkgpartmsgnum'. $n,
-              type      => 'hidden',
-              value     => $pkey_value,
-            },
-            { field     => 'pkgpartmsgnum'. $n. '_locale',
-              type      => 'hidden',
-              value     => $_,
-            },
-            { field     => 'pkgpartmsgnum'. $n++. '_pkg',
-              type      => 'text',
-              size      => 40,
-              #maxlength => 50,
-              value     => $pkg_value,
-            },
-          );
-  
-        }
-      @locales
-  );
-  splice(@$fields, 7, 0, @locale_fields); #XXX 7 is arbitrary above
-
-};
-
 my $error_callback = sub {
   my($cgi, $object, $fields, $opt ) = @_;
 
@@ -579,16 +543,6 @@ my $error_callback = sub {
 
   $pkgpart = $object->pkgpart;
 
-  &$splice_locale_fields(
-    $fields,
-    sub {
-          my $locale = shift;
-          my $part_pkg_msgcat = $object->part_pkg_msgcat($locale);
-          $part_pkg_msgcat ? $part_pkg_msgcat->pkgpartmsgnum : '';
-        },
-    'cgiparam'
-  );
-
   if ( $cgi->param('error') =~ / is suggested with / ) {
     #yeah, detection is a shitty kludge, but we don't have exception objects
     $opt->{form_init} = '<INPUT TYPE="checkbox" NAME="part_pkg_restrict_soft_override" VALUE="Y"> Override suggestion<BR><BR>';
@@ -665,20 +619,6 @@ my $edit_callback = sub {
 
   $pkgpart = $object->pkgpart;
 
-  &$splice_locale_fields(
-    $fields,
-    sub {
-          my $locale = shift;
-          my $part_pkg_msgcat = $object->part_pkg_msgcat($locale);
-          $part_pkg_msgcat ? $part_pkg_msgcat->pkgpartmsgnum : '';
-        },
-    sub {
-          my $locale = shift;
-          my $part_pkg_msgcat = $object->part_pkg_msgcat($locale);
-          $part_pkg_msgcat ? $part_pkg_msgcat->pkg : '';
-        }
-  );
-
 };
 
 my $new_callback = sub {
@@ -692,8 +632,6 @@ my $new_callback = sub {
 
   $options{'suspend_bill'}=1 if $conf->exists('part_pkg-default_suspend_bill');
 
-  &$splice_locale_fields($fields, '', '');
-
 };
 
 my $clone_callback = sub {
@@ -732,17 +670,6 @@ my $clone_callback = sub {
       foreach keys %part_pkg_currency;
   }
 
-  $recur_disabled = $object->freq ? 0 : 1;
-
-  &$splice_locale_fields(
-    $fields,
-    '',
-    sub {
-      my $locale = shift;
-      my $part_pkg_msgcat = $object->part_pkg_msgcat($locale);
-      $part_pkg_msgcat ? $part_pkg_msgcat->pkg : '';
-    }
-  );
 };
 
 my $discount_error_callback = sub {
diff --git a/httemplate/edit/part_svc.cgi b/httemplate/edit/part_svc.cgi
index a07fc60..fed2125 100755
--- a/httemplate/edit/part_svc.cgi
+++ b/httemplate/edit/part_svc.cgi
@@ -36,9 +36,26 @@
 }
 </STYLE>
 <SCRIPT TYPE="text/javascript">
+// copy all fields from the outer form (svc and its localizations, plus
+// preserve, selfservice_access, etc.) into the inner form, creating hidden
+// inputs if needed
 function fixup_submit(layer) {
-  document.forms[layer].submit.disabled = true;
-  fixup(document.forms[layer]);
+  var layer_form = $(document.forms[layer]);
+  var main_form = $(document.forms['SvcEditMain']);
+  var data = main_form.serializeArray();
+  for (var i = 0; i < data.length; i++) {
+    var input = layer_form.children('[name=' + data[i].name + ']');
+    if (input[0]) {
+      input.prop('value', data[i].value);
+    } else {
+      $( '<input type="hidden">' )
+        .attr('name', data[i].name)
+        .prop('value', data[i].value)
+        .appendTo(layer_form);
+    }
+  }
+  layer_form[0]['submit'].disabled = true;
+  //fixup(document.forms[layer]);
   window[layer+'process'].call();
 }
 
@@ -141,19 +158,26 @@ window.onload = function() {
 
 </SCRIPT>
 
-<FORM NAME="dummy">
+<FORM NAME="SvcEditMain">
 
 <FONT CLASS="fsinnerbox-title">Service Part #<% $part_svc->svcpart ? $part_svc->svcpart : "(NEW)" %></FONT>
 <TABLE CLASS="fsinnerbox">
-<TR>
-  <TD ALIGN="right">Service</TD>
-  <TD><INPUT TYPE="text" NAME="svc" VALUE="<% $hashref->{svc} %>"></TD>
-<TR>
+<& /elements/tr-input-locale-text.html,
+  'object' => $part_svc,
+  'cgi'    => $cgi,
+  'field'  => 'svc',
+  'label'  => 'Service',
+  'curr_value' => $hashref->{svc},
+&>
+%#<TR>
+%#  <TD ALIGN="right">Service</TD>
+%#  <TD><INPUT TYPE="text" NAME="svc" VALUE="<% $hashref->{svc} %>"></TD>
+%#<TR>
 
 <& /elements/tr-select-part_svc_class.html, curr_value=>$hashref->{classnum} &>
 
 <TR>
-  <TD ALIGN="right">Self-service access</TD>
+  <TH ALIGN="right">Self-service access</TD>
   <TD>
     <SELECT NAME="selfservice_access">
 % tie my %selfservice_access, 'Tie::IxHash', #false laziness w/browse/part_svc
@@ -172,12 +196,12 @@ window.onload = function() {
 
 
 <TR>
-  <TD ALIGN="right">Disable new orders</TD>
+  <TH ALIGN="right">Disable new orders</TD>
   <TD><INPUT TYPE="checkbox" NAME="disabled" VALUE="Y"<% $hashref->{disabled} eq 'Y' ? ' CHECKED' : '' %>></TD>
 </TR>
 
 <TR>
-  <TD ALIGN="right">Preserve this service on package cancellation</TD>
+  <TH ALIGN="right">Preserve this service on package cancellation</TD>
   <TD><INPUT TYPE="checkbox" NAME="preserve" VALUE="Y"<% $hashref->{'preserve'} eq 'Y' ? ' CHECKED' : '' %>> </TD>
 </TR>
 
@@ -240,12 +264,12 @@ my $widget = new HTML::Widgets::SelectLayers(
   #'selected_layer' => $p_svcdb,
   'selected_layer' => $hashref->{svcdb} || 'svc_acct',
   'options'        => \%svcdb,
-  'form_name'      => 'dummy',
+  'form_name'      => 'SvcEditMain',
   #'form_action'    => 'process/part_svc.cgi',
   'form_action'    => 'part_svc.cgi', #self
-  'form_elements'  => [qw( svc svcpart classnum selfservice_access
-                           disabled preserve
-                      )],
+#  'form_elements'  => [qw( svc svcpart classnum selfservice_access
+#                           disabled preserve
+#                      )],
   'html_between'   => $help,
   'layer_callback' => sub {
     include('elements/part_svc_column.html',
diff --git a/httemplate/edit/process/elements/process.html b/httemplate/edit/process/elements/process.html
index fd12c61..60aaf74 100644
--- a/httemplate/edit/process/elements/process.html
+++ b/httemplate/edit/process/elements/process.html
@@ -62,6 +62,8 @@ Example:
                       'fields' => [qw( fieldname fieldname2 )],
                     },
 
+   'process_locale' => 'fieldname', # update entries in the _msgcat table
+
    'process_upload' => {
                          'process'  => 'misc/mytable-import.html',
                           # fields to pass to the back end job, besides the 
@@ -363,12 +365,21 @@ foreach my $value ( @values ) {
 
   }
 
-  if ( !$error && $opt{'process_o2m'} ) {
-
-    my @process_o2m = ref($opt{'process_o2m'}) eq 'ARRAY'
-                           ? @{ $opt{'process_o2m'} }
-                           :  ( $opt{'process_o2m'} );
+  my @process_o2m;
+  if ( $opt{'process_o2m'} ) {
+    @process_o2m = ref($opt{'process_o2m'}) eq 'ARRAY'
+                        ? @{ $opt{'process_o2m'} }
+                        :  ( $opt{'process_o2m'} );
+  }
+  if ( $opt{'process_locale'} ) {
+    push @process_o2m,
+    {
+      'table'  => $table . '_msgcat',
+      'fields' => [ 'locale', $opt{'process_locale'} ],
+    };
+  }
 
+  if ( !$error ) {
 
     foreach my $process_o2m (@process_o2m) {
 
diff --git a/httemplate/edit/process/part_pkg.cgi b/httemplate/edit/process/part_pkg.cgi
index b804202..c4d150b 100755
--- a/httemplate/edit/process/part_pkg.cgi
+++ b/httemplate/edit/process/part_pkg.cgi
@@ -9,6 +9,7 @@
               'edit_ext'          => 'cgi',
               'precheck_callback' => $precheck_callback,
               'args_callback'     => $args_callback,
+              'process_locale'    => 'pkg',
               'process_m2m'       => \@process_m2m,
               'process_o2m'       => \@process_o2m,
           )
@@ -310,10 +311,6 @@ foreach my $amount_param ( grep /^usagepricepart(\d+)_amount$/, $cgi->param ) {
 
 my @process_o2m = (
   {
-    'table'  => 'part_pkg_msgcat',
-    'fields' => [qw( locale pkg )],
-  },
-  {
     'table'  => 'part_pkg_usageprice',
     'fields' => [qw( price currency action target amount )],
 
diff --git a/httemplate/elements/freeside.css b/httemplate/elements/freeside.css
index fb5e7d9..cc104a1 100644
--- a/httemplate/elements/freeside.css
+++ b/httemplate/elements/freeside.css
@@ -235,7 +235,7 @@ div.fstabcontainer {
 .fsinnerbox th {
   font-weight:normal;
   font-size:80%;
-  valign: bottom;
+  vertical-align: bottom;
   color: #666666;
 }
 
diff --git a/httemplate/elements/progress-init.html b/httemplate/elements/progress-init.html
index e38dde6..0c2b816 100644
--- a/httemplate/elements/progress-init.html
+++ b/httemplate/elements/progress-init.html
@@ -98,14 +98,14 @@ function <%$key%>process () {
 
   overlib( 'Submitting job to server...', WIDTH, 444, HEIGHT, 168, CAPTION, 'Please wait...', STICKY, AUTOSTATUSCAP, CLOSETEXT, '', CLOSECLICK, MIDX, 0, MIDY, 0 );
 
+  // jQuery .serializeArray() maybe?
+  var copy_fields = <% encode_json(\%copy_fields) %>;
   var Hash = new Array();
   var x = 0;
   var fieldName;
   for (var i = 0; i<document.<%$formname%>.elements.length; i++) {
     field  = document.<%$formname%>.elements[i];
-    if ( <% join(' || ', map { "(field.name.indexOf('$_') > -1)" } @$fields ) %>
-       )
-    {
+    if ( <% $all_fields %> || copy_fields[ field.name ] ) {
         if ( field.type == 'select-multiple' ) {
           //alert('select-multiple ' + field.name);
           for (var j=0; j < field.options.length; j++) {
@@ -168,6 +168,14 @@ $progress_url->query_form(
   %dest_info,
 );
 
+my $all_fields = 0;
+my %copy_fields;
+if (grep '/^ALL$/', @$fields) {
+  $all_fields = 1;
+} else {
+  %copy_fields = map { $_ => 1 } @$fields;
+}
+
 #stupid safari is caching the "location" of popup iframs, and submitting them
 #instead of displaying them.  this should prevent that.
 my $popup_name = 'popup-'.random_id();
diff --git a/httemplate/elements/tr-input-locale-text.html b/httemplate/elements/tr-input-locale-text.html
new file mode 100644
index 0000000..110a8aa
--- /dev/null
+++ b/httemplate/elements/tr-input-locale-text.html
@@ -0,0 +1,120 @@
+<%doc>
+Usage:
+
+In edit/foo.html:
+
+<& /elements/tr-input-locale-text.html,
+  cgi     => $cgi, # needed to preserve values in error redirect
+  object  => $record,
+  field   => 'myfield',
+  label   => 'My Field',
+&>
+
+And in edit/process/foo.html:
+<& elements/process.html,
+  ...
+  process_locale => 'myfield',
+&>
+
+'object' needs to be an FS::Record subclass instance for a table that has
+a '_msgcat' localization table. For a table "foo" where "foo.myfield"
+contains some customer-visible label (in the default locale),
+"foo_msgcat.myfield" contains the translation of that label for a customer
+locale. The foreign key in foo_msgcat must have the same name as the primary
+key of foo.
+
+Currently only a single field can be localized this way; including this
+element more than once in the form will lead to conflicts. This is how
+it should work; if at some point we need to localize several fields of the
+same record, we should modify this element to show multiple inputs for each
+locale.
+
+</%doc>
+<%init>
+
+my %opt = @_;
+my $object = delete $opt{object};
+my $field = delete $opt{field};
+
+# identify our locales
+my $conf = FS::Conf->new;
+my $default_locale = $conf->config('locale') || 'en_';
+my @locales = grep { ! /^$default_locale/ } $conf->config('available-locales');
+
+my $label = delete $opt{label};
+my %labels = map { $_ => "$label—".FS::Locales->description($_) }
+              @locales;
+ at locales = sort { $labels{$a} cmp $labels{$b} } @locales;
+my %curr_values;
+
+# where are the msgcat records?
+my $msgcat_table = $object->table . '_msgcat';
+my $msgcat_pkey = dbdef->table($msgcat_table)->primary_key;
+my %msgcat_pkeyvals;
+
+# find existing msgcat records, if any, and record their message values
+# and pkeys
+my $pkey = $object->primary_key;
+my $pkeyval = $object->get($pkey);
+if ($pkeyval) { # of course if this is a new record there won't be any
+  my @linked = qsearch($msgcat_table, { $pkey => $pkeyval });
+  foreach (@linked) {
+    $curr_values{ $_->locale } = $_->get( $field );
+    $msgcat_pkeyvals{ $_->locale } = $_->get( $msgcat_pkey );
+  }
+}
+
+# sticky-on-error the locale inputs
+if( my $cgi = $opt{cgi} ) {
+  my $i = 0;
+  # they're named 'foomsgnum0_locale' and 'foomsgnum0_myfield'
+  while ( my $locale = $cgi->param($msgcat_pkey . $i . '_locale') ) {
+    my $value = $cgi->param($msgcat_pkey . $i . '_' . $field);
+    $curr_values{ $locale } = $value;
+    $i++;
+  }
+}
+
+# compat with tr-input-text for styling
+my $cell_style = $opt{'cell_style'} ? 'STYLE="'. $opt{'cell_style'}. '"' : '';
+
+my $colspan = $opt{'colspan'} ? 'COLSPAN="'.$opt{'colspan'}.'"' : '';
+
+
+</%init>
+% # pass through %opt on all of these to retain formatting
+% # one tr, td, and input for the default locale
+<& tr-input-text.html,
+  %opt,
+  'label' => $label,
+  'field' => $field
+&>
+% # and one for each of the others 
+% my $i = 0;
+% foreach my $locale (@locales) {
+%   my $basename = $msgcat_pkey . $i;
+%   my $lfield = $basename . '_' . $field;
+<& tr-td-label.html,
+  %opt,
+  'id' => $lfield, # uniqueness
+  'label' => $labels{$locale}
+&>
+  <TD <% $colspan %><% $cell_style %> ID="<% $lfield %>_input0">
+    <& hidden.html,
+      'field' => $basename,
+      'curr_value' => $msgcat_pkeyvals{$locale},
+      # will be empty if this is a new record and/or new locale, that's fine
+    &>
+    <& hidden.html,
+      'field' => $basename . '_locale',
+      'curr_value' => $locale,
+    &>
+    <& input-text.html,
+      %opt,
+      'field' => $lfield,
+      'curr_value' => $curr_values{$locale},
+    &>
+  </TD>
+</TR>
+%   $i++;
+% } # foreach $locale

commit df43a12a1c219709f27297ad6b53f6662b56c10c
Merge: 2a0b533 1e63ee1
Author: Mark Wells <mark at freeside.biz>
Date:   Wed Jul 6 11:48:45 2016 -0700

    Merge branch 'master' of git.freeside.biz:/home/git/freeside


commit 2a0b5339081a439a8c5ec1f2b9cd28b63fd3fa49
Author: Mark Wells <mark at freeside.biz>
Date:   Tue Jul 5 16:41:25 2016 -0700

    UTF-8 form input vs. xmlhttp, #71347

diff --git a/httemplate/elements/xmlhttp.html b/httemplate/elements/xmlhttp.html
index 2f4f0d5..e708711 100644
--- a/httemplate/elements/xmlhttp.html
+++ b/httemplate/elements/xmlhttp.html
@@ -44,7 +44,7 @@ my %initialized = ();#won't work if component is "preloaded"... so don't do that
             len = args.length - 1;
         }
         for (var i = 0; i < len; i++) 
-            content = content + "&arg=" + escape(args[i]);
+            content = content + "&arg=" + encodeURIComponent(args[i]);
         content = content.replace( /[+]/g, '%2B'); // fix unescaped plus signs 
 
         if ( '<%$method%>' == 'GET' ) {

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

Summary of changes:
 FS/FS/Mason.pm                                   |    1 +
 FS/FS/Schema.pm                                  |   18 ++++
 FS/FS/part_svc.pm                                |   27 ++++-
 FS/FS/{part_pkg_msgcat.pm => part_svc_msgcat.pm} |   39 +++----
 httemplate/browse/part_svc.cgi                   |   20 +++-
 httemplate/edit/elements/part_svc_column.html    |    5 +-
 httemplate/edit/part_pkg.cgi                     |   75 +-------------
 httemplate/edit/part_svc.cgi                     |   52 +++++++---
 httemplate/edit/process/elements/process.html    |   21 +++-
 httemplate/edit/process/part_pkg.cgi             |    5 +-
 httemplate/elements/freeside.css                 |    2 +-
 httemplate/elements/progress-init.html           |   14 ++-
 httemplate/elements/tr-input-locale-text.html    |  120 ++++++++++++++++++++++
 httemplate/elements/xmlhttp.html                 |    2 +-
 14 files changed, 272 insertions(+), 129 deletions(-)
 copy FS/FS/{part_pkg_msgcat.pm => part_svc_msgcat.pm} (68%)
 create mode 100644 httemplate/elements/tr-input-locale-text.html




More information about the freeside-commits mailing list