RT#34289: Flag service fields as mandatory
authorJonathan Prykop <jonathan@freeside.biz>
Tue, 5 May 2015 20:49:51 +0000 (15:49 -0500)
committerJonathan Prykop <jonathan@freeside.biz>
Thu, 21 May 2015 22:50:56 +0000 (17:50 -0500)
16 files changed:
FS/FS/part_svc.pm
FS/FS/svc_Common.pm
FS/FS/svc_acct.pm
FS/FS/svc_broadband.pm
FS/FS/svc_dish.pm
FS/FS/svc_domain.pm
FS/FS/svc_hardware.pm
httemplate/edit/elements/edit.html
httemplate/edit/elements/part_svc_column.html
httemplate/edit/elements/svc_Common.html
httemplate/edit/svc_acct.cgi
httemplate/edit/svc_acct/communigate.html
httemplate/edit/svc_broadband.cgi
httemplate/elements/tr-input-date-field.html
httemplate/elements/tr-select-hardware_type.html
httemplate/elements/tr-select-router_block_ip.html

index abeb28b..beea3f1 100644 (file)
@@ -143,56 +143,53 @@ sub insert {
   # add part_svc_column records
 
   my $svcdb = $self->svcdb;
-#  my @rows = map { /^${svcdb}__(.*)$/; $1 }
-#    grep ! /_flag$/,
-#      grep /^${svcdb}__/,
-#        fields('part_svc');
-  foreach my $field (
-    grep { $_ ne 'svcnum'
-           && ( defined( $self->getfield($svcdb.'__'.$_.'_flag') )
-                || defined($self->getfield($svcdb.'__'.$_.'_required'))
-                || $self->getfield($svcdb.'__'.$_.'_label') !~ /^\s*$/ )
-         } (fields($svcdb), @fields)
-  ) {
-    my $part_svc_column = $self->part_svc_column($field);
-    my $previous = qsearchs('part_svc_column', {
-      'svcpart'    => $self->svcpart,
-      'columnname' => $field,
-    } );
+  foreach my $field (fields($svcdb), @fields) {
+    next if $field eq 'svcnum';
+    my $prefix = $svcdb.'__';
+    if ( defined( $self->getfield($prefix.$_.'_flag'))
+      or defined($self->getfield($prefix.$_.'_required'))
+      or length($self->getfield($prefix.$_.'_label'))
+    ) {
+      my $part_svc_column = $self->part_svc_column($field);
+      my $previous = qsearchs('part_svc_column', {
+        'svcpart'    => $self->svcpart,
+        'columnname' => $field,
+      } );
 
-    my $flag  = $self->getfield($svcdb.'__'.$field.'_flag');
-    my $label = $self->getfield($svcdb.'__'.$field.'_label');
-    my $required = $self->getfield($svcdb.'__'.$field.'_required') ? 'Y' : '';
-    if ( uc($flag) =~ /^([A-Z])$/ || $label !~ /^\s*$/ ) {
-
-      if ( uc($flag) =~ /^([A-Z])$/ ) {
-        my $parser = FS::part_svc->svc_table_fields($svcdb)->{$field}->{parse}
-                     || sub { shift };
-        $part_svc_column->setfield('columnflag', $1);
-        $part_svc_column->setfield('columnvalue',
-          &$parser($self->getfield($svcdb.'__'.$field))
-        );
-      }
+      my $flag  = $self->getfield($prefix.$field.'_flag');
+      my $label = $self->getfield($prefix.$field.'_label');
+      my $required = $self->getfield($prefix.$field.'_required') ? 'Y' : '';
+      if ( uc($flag) =~ /^([A-Z])$/ || $label !~ /^\s*$/ ) {
 
-      $part_svc_column->setfield('columnlabel', $label)
-        if $label !~ /^\s*$/;
+        if ( uc($flag) =~ /^([A-Z])$/ ) {
+          my $parser = FS::part_svc->svc_table_fields($svcdb)->{$field}->{parse}
+                       || sub { shift };
+          $part_svc_column->setfield('columnflag', $1);
+          $part_svc_column->setfield('columnvalue',
+            &$parser($self->getfield($prefix.$field))
+          );
+        }
+
+        $part_svc_column->setfield('columnlabel', $label)
+          if $label !~ /^\s*$/;
 
-      $part_svc_column->setfield('required', $required);
+        $part_svc_column->setfield('required', $required);
+
+        if ( $previous ) {
+          $error = $part_svc_column->replace($previous);
+        } else {
+          $error = $part_svc_column->insert;
+        }
 
-      if ( $previous ) {
-        $error = $part_svc_column->replace($previous);
       } else {
-        $error = $part_svc_column->insert;
+        $error = $previous ? $previous->delete : '';
+      }
+      if ( $error ) {
+        $dbh->rollback if $oldAutoCommit;
+        return $error;
       }
 
-    } else {
-      $error = $previous ? $previous->delete : '';
-    }
-    if ( $error ) {
-      $dbh->rollback if $oldAutoCommit;
-      return $error;
     }
-
   }
 
   # add export_svc records
@@ -285,54 +282,54 @@ sub replace {
    # maintain part_svc_column records
 
     my $svcdb = $new->svcdb;
-    foreach my $field (
-      grep { $_ ne 'svcnum'
-             && ( defined( $new->getfield($svcdb.'__'.$_.'_flag') )
-                  || defined($new->getfield($svcdb.'__'.$_.'_required'))
-                  || $new->getfield($svcdb.'__'.$_.'_label') !~ /^\s*$/ )
-           } (fields($svcdb),@fields)
-    ) {
-
-      my $part_svc_column = $new->part_svc_column($field);
-      my $previous = qsearchs('part_svc_column', {
-        'svcpart'    => $new->svcpart,
-        'columnname' => $field,
-      } );
-
-      my $flag  = $new->getfield($svcdb.'__'.$field.'_flag');
-      my $label = $new->getfield($svcdb.'__'.$field.'_label');
-      my $required = $new->getfield($svcdb.'__'.$field.'_required') ? 'Y' : '';
+    foreach my $field (fields($svcdb),@fields) {
+      next if $field eq 'svcnum';
+      my $prefix = $svcdb.'__';
+      if ( defined( $new->getfield($prefix.$_.'_flag'))
+        or defined($new->getfield($prefix.$_.'_required'))
+        or length($new->getfield($prefix.$_.'_label'))
+      ) {
+        my $part_svc_column = $new->part_svc_column($field);
+        my $previous = qsearchs('part_svc_column', {
+          'svcpart'    => $new->svcpart,
+          'columnname' => $field,
+        } );
+
+        my $flag  = $new->getfield($svcdb.'__'.$field.'_flag');
+        my $label = $new->getfield($svcdb.'__'.$field.'_label');
+        my $required = $new->getfield($svcdb.'__'.$field.'_required') ? 'Y' : '';
  
-      if ( uc($flag) =~ /^([A-Z])$/ || $label !~ /^\s*$/ ) {
-
-        if ( uc($flag) =~ /^([A-Z])$/ ) {
-          $part_svc_column->setfield('columnflag', $1);
-          my $parser = FS::part_svc->svc_table_fields($svcdb)->{$field}->{parse}
-                     || sub { shift };
-          $part_svc_column->setfield('columnvalue',
-            &$parser($new->getfield($svcdb.'__'.$field))
-          );
-        } else {
-          $part_svc_column->setfield('columnflag',  '');
-          $part_svc_column->setfield('columnvalue', '');
-        }
+        if ( uc($flag) =~ /^([A-Z])$/ || $label !~ /^\s*$/ ) {
+
+          if ( uc($flag) =~ /^([A-Z])$/ ) {
+            $part_svc_column->setfield('columnflag', $1);
+            my $parser = FS::part_svc->svc_table_fields($svcdb)->{$field}->{parse}
+                       || sub { shift };
+            $part_svc_column->setfield('columnvalue',
+              &$parser($new->getfield($svcdb.'__'.$field))
+            );
+          } else {
+            $part_svc_column->setfield('columnflag',  '');
+            $part_svc_column->setfield('columnvalue', '');
+          }
 
-        $part_svc_column->setfield('columnlabel', $label)
-          if $label !~ /^\s*$/;
+          $part_svc_column->setfield('columnlabel', $label)
+            if $label !~ /^\s*$/;
 
-        $part_svc_column->setfield('required', $required);
+          $part_svc_column->setfield('required', $required);
 
-        if ( $previous ) {
-          $error = $part_svc_column->replace($previous);
+          if ( $previous ) {
+            $error = $part_svc_column->replace($previous);
+          } else {
+            $error = $part_svc_column->insert;
+          }
         } else {
-          $error = $part_svc_column->insert;
+          $error = $previous ? $previous->delete : '';
+        }
+        if ( $error ) {
+          $dbh->rollback if $oldAutoCommit;
+          return $error;
         }
-      } else {
-        $error = $previous ? $previous->delete : '';
-      }
-      if ( $error ) {
-        $dbh->rollback if $oldAutoCommit;
-        return $error;
       }
     }
 
@@ -606,6 +603,7 @@ sub svc_x {
 =cut
 
 my $svc_defs;
+my $svc_info;
 sub _svc_defs {
 
   return $svc_defs if $svc_defs; #cache
@@ -660,7 +658,14 @@ sub _svc_defs {
     sort { $info{$a}->{'display_weight'} <=> $info{$b}->{'display_weight'} }
     keys %info,
   ;
-  
+
+  tie my %svc_info, 'Tie::IxHash',
+    map  { $_ => $info{$_} }
+    sort { $info{$a}->{'display_weight'} <=> $info{$b}->{'display_weight'} }
+    keys %info,
+  ;
+    
+  $svc_info = \%svc_info; #access via svc_table_info  
   $svc_defs = \%svc_defs; #cache
   
 }
@@ -736,6 +741,27 @@ sub svc_table_fields {
   $def;
 }
 
+=item svc_table_info TABLE
+
+Returns table_info for TABLE from cache, or empty
+hashref if none is found.
+
+Caution:  caches table_info for ALL services when run;
+access a service's table_info directly unless you know
+you're loading them all.
+
+Caution:  does not standardize fields into hashrefs;
+use L</svc_table_fields> to access fields.
+
+=cut
+
+sub svc_table_info {
+  my $class = shift;
+  my $table = shift;
+  $class->_svc_defs; #creates cache if needed
+  return $svc_info->{$table} || {};
+}
+
 =back
 
 =head1 SUBROUTINES
index 34ae219..9853d5b 100644 (file)
@@ -170,28 +170,30 @@ sub check {
   my $required = {};
   my $labels = {};
   my $tinfo = $self->can('table_info') ? $self->table_info : {};
-  my $fields = $tinfo->{'fields'} || {};
-  foreach my $field (keys %$fields) {
-    if (ref($fields->{$field}) && $fields->{$field}->{'required'}) {
-      $required->{$field} = 1;
-      $labels->{$field} = $fields->{$field}->{'label'};
+  if ($tinfo->{'manual_require'}) {
+    my $fields = $tinfo->{'fields'} || {};
+    foreach my $field (keys %$fields) {
+      if (ref($fields->{$field}) && $fields->{$field}->{'required'}) {
+        $required->{$field} = 1;
+        $labels->{$field} = $fields->{$field}->{'label'};
+      }
     }
-  }
-  # add fields marked as required in database
-  foreach my $column (
-    qsearch('part_svc_column',{
-      'svcpart' => $self->svcpart,
-      'required' => 'Y'
-    })
-  ) {
-    $required->{$column->columnname} = 1;
-    $labels->{$column->columnname} = $column->columnlabel;
-  }
-  # do the actual checking
-  foreach my $field (keys %$required) {
-    unless ($self->$field) {
-      my $name = $labels->{$field} || $field;
-      return "Field $name is required\n"
+    # add fields marked as required in database
+    foreach my $column (
+      qsearch('part_svc_column',{
+        'svcpart' => $self->svcpart,
+        'required' => 'Y'
+      })
+    ) {
+      $required->{$column->columnname} = 1;
+      $labels->{$column->columnname} = $column->columnlabel;
+    }
+    # do the actual checking
+    foreach my $field (keys %$required) {
+      unless (length($self->get($field)) > 0) {
+        my $name = $labels->{$field} || $field;
+        return "Field $name is required\n"
+      }
     }
   }
 
index ffcadc9..9636b3e 100644 (file)
@@ -261,6 +261,7 @@ sub table_info {
     'display_weight' => 10,
     'cancel_weight'  => 50, 
     'ip_field' => 'slipip',
+    'manual_require' => 1,
     'fields' => {
         'dir'       => 'Home directory',
         'uid'       => {
index 40f2c9b..2cdc284 100755 (executable)
@@ -103,6 +103,7 @@ sub table_info {
     'display_weight' => 50,
     'cancel_weight'  => 70,
     'ip_field' => 'ip_addr',
+    'manual_require' => 1,
     'fields' => {
       'svcnum'      => 'Service',
       'description' => 'Descriptive label',
index 5c9e217..2d249d1 100644 (file)
@@ -63,9 +63,10 @@ sub table_info {
     'name'           => 'Dish service',
     'display_weight' => 58,
     'cancel_weight'  => 85,
+    'manual_require' => 1,
     'fields' => {
       'svcnum'    =>  { label => 'Service' },
-      'acctnum'   =>  { label => 'DISH account#', %opts },
+      'acctnum'   =>  { label => 'DISH account#', required => 1, %opts },
       'installdate' => { label => 'Install date', %opts },
       'note'      => { label => 'Installation notes', %opts },
     }
index 78556cf..b01d673 100644 (file)
@@ -134,10 +134,7 @@ sub table_info {
     'display_weight' => 20,
     'cancel_weight'  => 60,
     'fields' => {
-      'domain' => {
-                  label => 'Domain',
-                  required => 1,
-                },
+      'domain' => 'Domain',
       'parent_svcnum' => { 
                          label => 'Parent domain / Communigate administrator domain',
                          type  => 'select',
index d9c3c46..2be8954 100644 (file)
@@ -76,6 +76,7 @@ sub table_info {
     'name_plural'    => 'Hardware',
     'display_weight' => 59,
     'cancel_weight'  => 86,
+    'manual_require' => 1,
     'fields' => {
       'svcnum'    => { label => 'Service' },
       'typenum'   => { label => 'Device type',
@@ -84,6 +85,7 @@ sub table_info {
                        disable_fixed     => 1,
                        disable_default   => 1,
                        disable_inventory => 1,
+                       required => 1,
                      },
       'serial'    => { label => 'Serial number', %opts },
       'hw_addr'   => { label => 'Hardware address', %opts },
index c80cdae..c9eceb4 100644 (file)
@@ -395,6 +395,7 @@ Example:
 %                      'value' => $opt{curr_value},
 %                      'label' => $label,
 %                      'noinit' => $f->{noinit},
+%           'required' => $f->{'required'},
 %              }
 %      );
 %     }
index a6ccaf8..d950032 100644 (file)
@@ -77,7 +77,7 @@ that field.
     <TH BGCOLOR="#cccccc">Field</TH>
     <TH BGCOLOR="#cccccc">Label</TH>
     <TH BGCOLOR="#cccccc" COLSPAN=2>Modifier</TH>
-    <TH BGCOLOR="#cccccc">Required?</TH>
+    <TH BGCOLOR="#cccccc"><% $manual_require ? 'Required?' : '' %></TH>
   </TR>
 % $part_svc->set('svcpart' => $opt{'clone'}) if $opt{'clone'}; # for now
 % my $i = 0;
@@ -212,7 +212,9 @@ that field.
 %   }
     </TD>
     <TD>
-%   if (!$def->{'type'} || !(grep {$_ eq $def->{'type'}} ('checkbox','disabled'))) {
+%   if ($manual_require && 
+%       (!$def->{'type'} || !(grep {$_ eq $def->{'type'}} ('checkbox','disabled')))
+%   ) {
       <INPUT ID="<% $name.'_required' %>" TYPE="checkbox" NAME="<% $svcdb %>__<% $field %>_required" VALUE="Y" 
         <% ($part_svc_column->required || $def->{'required'}) ? 'CHECKED' : '' %> 
         <% $def->{'required'} ? 'DISABLED' : '' %>
@@ -310,4 +312,5 @@ if ( $svcdb eq 'svc_acct'
 }
 
 my @defs = map { FS::part_svc->svc_table_fields($svcdb)->{$_} } @fields;
+my $manual_require = FS::part_svc->svc_table_info($svcdb)->{'manual_require'};
 </%init>
index 97b630f..a4e345e 100644 (file)
                    my $columndef = $part_svc->part_svc_column($f->{'field'});
                    my $flag = $columndef->columnflag;
 
+                   $f->{'required'} = 1
+                     if $columndef->required;
+
                    if ( $flag eq 'F' ) { #fixed
                      $f->{'value'} = $columndef->columnvalue;
                      if (length($columndef->columnvalue)) {
index 90f4823..a5e7789 100755 (executable)
@@ -30,8 +30,9 @@
   <TD BGCOLOR="#eeeeee"><% $part_svc->svc %></TD>
 </TR>
 
-<TR>
-  <TD ALIGN="right"><% mt('Username') |h %></TD>
+<% include('/elements/tr-td-label.html',
+     'label'    => mt('Username'),
+     'required' => $part_svc->part_svc_column('username')->required ) %>
 % if ( $svcnum && $conf->exists('svc_acct-no_edit_username') ) {
     <TD BGCOLOR="#eeeeee"><% $svc_acct->username() %></TD>
     <INPUT TYPE="hidden" NAME="username" VALUE="<% $username %>">
 </TR>
 
 %if ( $part_svc->part_svc_column('_password')->columnflag ne 'F' ) {
-<TR>
 % #XXX eventually should require "Edit Password" ACL
-  <TD ALIGN="right"><% mt('Password') |h %></TD>
+<% include('/elements/tr-td-label.html',
+     'label'    => mt('Password'),
+     'required' => $part_svc->part_svc_column('_password')->required ) %>
   <TD>
     <INPUT TYPE="text" ID="clear_password" NAME="clear_password" VALUE="<% $password %>" SIZE=<% $pmax2 %> MAXLENGTH=<% $pmax %>>
     <& /elements/random_pass.html, 'clear_password' &>
@@ -60,8 +62,9 @@
 %if ( $conf->exists('security_phrase') 
 %  && $part_svc->part_svc_column('sec_phrase')->columnflag ne 'F' ) {
 
-  <TR>
-    <TD ALIGN="right"><% mt('Security phrase') |h %></TD>
+<% include('/elements/tr-td-label.html',
+     'label'    => mt('Security phrase'),
+     'required' => $part_svc->part_svc_column('sec_phrase')->required ) %>
     <TD>
       <INPUT TYPE="text" NAME="sec_phrase" VALUE="<% $sec_phrase %>" SIZE=32>
       (<% mt('for forgotten passwords') |h %>)
 %                                                )
 %                );
 
-  <TR>
-    <TD ALIGN="right"><% mt('Domain') |h %></TD>
+<% include('/elements/tr-td-label.html',
+     'label'    => mt('Domain'),
+     'required' => $part_svc->part_svc_column('domsvc')->required ) %>
     <TD>
       <SELECT NAME="domsvc" SIZE=1>
 % foreach my $svcnum (
   <INPUT TYPE="hidden" NAME="popnum" VALUE="<% $popnum %>">
 % } else { 
 
-  <TR>
-    <TD ALIGN="right"><% mt('Access number') |h %></TD>
+<% include('/elements/tr-td-label.html',
+     'label'    => mt('Access number'),
+     'required' => $part_svc->part_svc_column('popnum')->required ) %>
     <TD><% FS::svc_acct_pop::popselector($popnum) %></TD>
   </TR>
 % } 
          'curr_value' => $svc_acct->sectornum,
          #'part_svc'   => $part_svc,
          #'cust_pkg'   => $cust_pkg,
+         'required'   => $part_svc->part_svc_column('sectornum')->required,
     &>
 %} else {
     <INPUT TYPE="hidden" NAME="sectornum" VALUE="<% $svc_acct->sectornum %>">
 %  
 % if ( length($svc_acct->$xid()) ) { 
 
+<% include('/elements/tr-td-label.html',
+     'label'    => uc($xid),
+     'required' => $part_svc->part_svc_column($xid)->required ) %>
       <TR>
         <TD ALIGN="right"><% uc($xid) %></TD>
           <TD BGCOLOR="#eeeeee"><% $svc_acct->$xid() %></TD>
     <INPUT TYPE="hidden" NAME="<% $xid %>" VALUE="<% $svc_acct->$xid() %>">
 % } else { 
   
-    <TR>
-      <TD ALIGN="right"><% uc($xid) %></TD>
+<% include('/elements/tr-td-label.html',
+     'label'    => uc($xid),
+     'required' => $part_svc->part_svc_column($xid)->required ) %>
       <TD>
         <INPUT TYPE="text" NAME="<% $xid %>" SIZE=8 MAXLENGTH=6 VALUE="<% $svc_acct->$xid() %>">
       </TD>
 % } else { 
 
 
-  <TR>
-    <TD ALIGN="right"><% mt('Real Name') |h %></TD>
+<% include('/elements/tr-td-label.html',
+     'label'    => mt('Real Name'),
+     'required' => $part_svc->part_svc_column('finger')->required ) %>
     <TD>
       <INPUT TYPE="text" NAME="finger" VALUE="<% $svc_acct->finger %>">
     </TD>
 % } else {
 
 
-  <TR>
-    <TD ALIGN="right"><% mt('Home directory') |h %></TD>
+<% include('/elements/tr-td-label.html',
+     'label'    => mt('Home directory'),
+     'required' => $part_svc->part_svc_column('dir')->required ) %>
     <TD><INPUT TYPE="text" NAME="dir" VALUE="<% $svc_acct->dir %>"></TD>
   </TR>
 % } 
 % } else { 
 
 
-  <TR>
-    <TD ALIGN="right"><% mt('Shell') |h %></TD>
+<% include('/elements/tr-td-label.html',
+     'label'    => mt('Shell'),
+     'required' => $part_svc->part_svc_column('shell')->required ) %>
     <TD>
       <SELECT NAME="shell" SIZE=1>
 %
 %   # (should we show this if slipip is fixed?)
 <& /elements/tr-select-router_block_ip.html, 
   'object' => $svc_acct,
-  'ip_field' => 'slipip'
+  'ip_field' => 'slipip',
+  'required' => $part_svc->part_svc_column('routernum')->required,
+  'ip_addr_required' => $part_svc->part_svc_column('slipip')->required,
 &>
 % } else {
 %   # don't expose these to the user--they're only useful in the other case
 %   if ( $part_svc->part_svc_column('slipip')->columnflag =~ /^[FA]$/ ) { 
     <INPUT TYPE="hidden" NAME="slipip" VALUE="<% $svc_acct->slipip %>">
 %   } else { 
-    <TR>
-      <TD ALIGN="right"><% mt('IP') |h %></TD>
+<% include('/elements/tr-td-label.html',
+     'label'    => mt('IP'),
+     'required' => $part_svc->part_svc_column('slipip')->required ) %>
       <TD><INPUT TYPE="text" NAME="slipip" VALUE="<% $svc_acct->slipip %>"></TD>
     </TR>
 %   }
 % } 
 
 
-<TR>
-  <TD ALIGN="right"><% mt('RADIUS groups') |h %></TD>
+<% include('/elements/tr-td-label.html',
+     'label'    => mt('RADIUS groups'),
+     'required' => $part_svc->part_svc_column('usergroup')->required ) %>
 % if ( $part_svc_usergroup->columnflag eq 'F' ) { 
     <TD BGCOLOR="#eeeeee"><% join('<BR>', @groupnames) %></TD>
 % } else { 
index 6370a54..370bfb0 100644 (file)
@@ -47,8 +47,9 @@
   <INPUT TYPE="hidden" NAME="quota" VALUE="<% $svc_acct->quota %>">
 % } else {
 %   my $quota_label = $communigate ? 'Mail storage limit' : 'Quota';
-    <TR>
-      <TD ALIGN="right"><% $quota_label %></TD>
+<% include('/elements/tr-td-label.html',
+     'label'    => $quota_label,
+     'required' => $part_svc->part_svc_column('quota')->required ) %>
       <TD><INPUT TYPE="text" NAME="quota" VALUE="<% $svc_acct->quota %>"></TD>
     </TR>
 % }
index 1b85460..81c694a 100644 (file)
@@ -102,7 +102,16 @@ END
 my @fields = (
   qw( description speed_down speed_up ),
   { field=>'sectornum', type=>'select-tower_sector', },
-  { field=>'routernum', type=>'select-router_block_ip' },
+  { field=>'routernum', type=>'select-router_block_ip', 
+    include_opt_callback => sub { 
+      my $svc_broadband = shift;
+      my $part_svc = $svc_broadband->part_svc;
+      return () unless $part_svc; #sanity check
+      my $col = $part_svc->part_svc_column('ip_addr');
+      return () unless $col; #sanity check
+      return ('ip_addr_required' => $col->required);
+    },
+  },
   { field=>'mac_addr' , type=>'input-mac_addr' },
   qw(
       latitude longitude altitude
index ff98551..f2a570b 100644 (file)
@@ -13,6 +13,7 @@ Example:
           'usedatetime' => 1, #use DateTime->strftime to format the date
                               # instead of Date::Format->time2str
           'noinit'      => 1,          #first one on the page is enough
+          'required'    => 1,
        },
   &>
 
@@ -24,8 +25,9 @@ Example:
 <SCRIPT TYPE="text/javascript" SRC="<%$fsurl%>elements/calendar-setup.js"></SCRIPT>
 % }
 
-<TR>
-  <TD ALIGN="right"><% $label %></TD>
+<% include('/elements/tr-td-label.html',
+     'label'    => $label,
+     'required' => $required ) %>
   <TD COLSPAN=<% $colspan %>>
     <INPUT TYPE="text" NAME="<% $name %>" ID="<% $name %>_text" VALUE="<% $value %>">
     <IMG SRC="<%$fsurl%>images/calendar.png" ID="<% $name  %>_button" STYLE="cursor: pointer" TITLE="<% mt('Select date') |h %>">
@@ -48,7 +50,7 @@ Example:
 
 <%init>
 
-my($name, $value, $label, $format, $usedatetime, $noinit, $colspan);
+my($name, $value, $label, $format, $usedatetime, $noinit, $colspan, $required);
 if ( ref($_[0]) ) {
   my $opt = shift;
   $name        = $opt->{'name'};
@@ -58,6 +60,7 @@ if ( ref($_[0]) ) {
   $usedatetime = $opt->{'usedatetime'};
   $noinit      = $opt->{'noinit'};
   $colspan     = $opt->{'colspan'} || 1;
+  $required    = $opt->{'required'};
 } else {
   ($name, $value, $label, $format, $usedatetime) = @_;
   $colspan = 1;
index c306641..b51afc0 100644 (file)
@@ -1,5 +1,6 @@
-<TR>
-  <TD ALIGN="right"><% $opt{'label'} || 'Device type: ' %></TD>
+<% include('/elements/tr-td-label.html',
+     'label'    => $opt{'label'} || 'Device type: ',
+     'required' => $opt{'required'} ) %>
   <TD><% include('select-hardware_type.html', %opt) %></TD>
 </TR>
 
index 11f7c48..ee13568 100644 (file)
@@ -30,7 +30,7 @@ function clearhint_ip_addr (what) {
     what.value = '';
 }
 </script>
-<& /elements/tr-td-label.html, label => ($opt{'label'} || 'Router') &>
+<& /elements/tr-td-label.html, label => ($opt{'label'} || 'Router'), required => $opt{'required'} &>
 <td>
   <& /elements/select-tiered.html, prefix => 'router_', tiers => [
   {
@@ -56,9 +56,9 @@ function clearhint_ip_addr (what) {
 ]
 &>
 </td></tr>
-<& /elements/tr-td-label.html, label => 'IP address' &>
+<& /elements/tr-td-label.html, label => 'IP address', required => $opt{'ip_addr_required'} &>
 <td>
-% warn Dumper \%fixed;
+% #warn Dumper \%fixed;
 % if ( exists $fixed{$ip_field} ) {
   <input type="hidden" id="input_ip_addr" name="<% $ip_field %>" 
     value="<% $opt{'ip_addr'} |h%>"><% $opt{'ip_addr'} || '' %>