[freeside-commits] branch master updated. 04c717c096f556a9ba0e8c4a137e867029c78a1b

Mitch Jackson mitch at freeside.biz
Tue Jun 26 16:22:42 PDT 2018


The branch, master has been updated
       via  04c717c096f556a9ba0e8c4a137e867029c78a1b (commit)
       via  211865a049969b1b539988cc8558ee35e8cb5945 (commit)
      from  7b56ddf363cbd15acab7e7098a7769e7a33640a3 (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 04c717c096f556a9ba0e8c4a137e867029c78a1b
Author: Mitch Jackson <mitch at freeside.biz>
Date:   Tue Jun 26 18:18:51 2018 -0500

    RT# 30783 Clean up IP utility code

diff --git a/FS/FS/IP_Mixin.pm b/FS/FS/IP_Mixin.pm
index 2d69d9cc1..b68b0b624 100644
--- a/FS/FS/IP_Mixin.pm
+++ b/FS/FS/IP_Mixin.pm
@@ -264,45 +264,27 @@ sub router {
   FS::router->by_key($self->routernum);
 }
 
-=item used_addresses [ BLOCK ]
+=item used_addresses [ FS::addr_block ]
 
-Returns a list of all addresses that are in use by a service.  If called as an
-instance method, excludes that instance from the search.
+Returns a list of all addresses in use within the given L<FS::addr_block>.
 
-Does not filter by block, will return ALL used addresses. ref:f197bdbaa1
+If called as an instance method, excludes that instance from the search.
 
 =cut
 
 sub used_addresses {
-  my $self = shift;
-  my $block = shift;
-  return ( map { $_->_used_addresses($block, $self) } @subclasses );
-}
-
-sub _used_addresses {
-  my $class = shift;
-  die "$class->_used_addresses not implemented";
-}
-
-=item used_addresses_in_block [ FS::addr_block ]
-
-Returns a list of all addresses in use within the given L<FS::addr_block>
-
-=cut
-
-sub used_addresses_in_block {
   my ($self, $block) = @_;
 
   (
     $block->ip_gateway ? $block->ip_gateway : (),
     $block->NetAddr->broadcast->addr,
-    map { $_->_used_addresses_in_block($block, $self ) } @subclasses
+    map { $_->_used_addresses($block, $self ) } @subclasses
   );
 }
 
-sub _used_addresses_in_block {
+sub _used_addresses {
   my $class = shift;
-  die "$class->_used_addresses_in_block not implemented";
+  die "$class->_used_addresses not implemented";
 }
 
 =item is_used ADDRESS
diff --git a/FS/FS/addr_block.pm b/FS/FS/addr_block.pm
index 74c372e29..5fd64bf7a 100755
--- a/FS/FS/addr_block.pm
+++ b/FS/FS/addr_block.pm
@@ -218,7 +218,7 @@ sub free_addrs {
 
   my %used_addr_map =
     map {$_ => 1}
-    FS::IP_Mixin->used_addresses_in_block($self),
+    FS::IP_Mixin->used_addresses($self),
     FS::Conf->new()->config('exclude_ip_addr');
 
   [
@@ -254,7 +254,7 @@ sub next_free_addr {
     $selfaddr->addr,
     $selfaddr->network->addr,
     $selfaddr->broadcast->addr,
-    FS::IP_Mixin->used_addresses_in_block($self)
+    FS::IP_Mixin->used_addresses($self)
   );
 
   # just do a linear search of the block
diff --git a/FS/FS/svc_IP_Mixin.pm b/FS/FS/svc_IP_Mixin.pm
index 4266a2a5e..0fce86c1d 100644
--- a/FS/FS/svc_IP_Mixin.pm
+++ b/FS/FS/svc_IP_Mixin.pm
@@ -91,38 +91,21 @@ sub svc_ip_check {
 }
 
 sub _used_addresses {
+  my ($class, $block, $exclude_svc) = @_;
 
-  # Returns all addresses in use.  Does not filter with $block. ref:f197bdbaa1
-
-  my ($class, $block, $exclude) = @_;
-  my $ip_field = $class->table_info->{'ip_field'}
-    or return ();
-  # if the service doesn't have an ip_field, then it has no IP addresses 
-  # in use, yes? 
-
-  my %hash = ( $ip_field => { op => '!=', value => '' } );
-  #$hash{'blocknum'} = $block->blocknum if $block;
-  $hash{'svcnum'} = { op => '!=', value => $exclude->svcnum } if ref $exclude;
-  map { my $na = $_->NetAddr; $na ? $na->addr : () }
-    qsearch({
-        table     => $class->table,
-        hashref   => \%hash,
-        extra_sql => " AND $ip_field != '0e0'",
-    });
-}
-
-sub _used_addresses_in_block {
-  my ($class, $block) = @_;
-
-  croak "_used_addresses_in_block() requires an FS::addr_block parameter"
+  croak "_used_addresses() requires an FS::addr_block parameter"
     unless ref $block && $block->isa('FS::addr_block');
 
   my $ip_field = $class->table_info->{'ip_field'};
   if ( !$ip_field ) {
-    carp "_used_addresses_in_block() skipped, no ip_field";
+    carp "_used_addresses() skipped, no ip_field";
     return;
   }
 
+  my %qsearch = ( $ip_field => { op => '!=', value => '' });
+  $qsearch{svcnum} = { op => '!=', value => $exclude_svc->svcnum }
+    if ref $exclude_svc && $exclude_svc->svcnum;
+
   my $block_na = $block->NetAddr;
 
   my $octets;
@@ -152,7 +135,7 @@ sub _used_addresses_in_block {
   my %qsearch = (
       table     => $class->table,
       select    => $ip_field,
-      hashref   => { $ip_field => { op => '!=', value => '' }},
+      hashref   => \%qsearch,
       extra_sql => " AND $ip_field != '0e0' ",
   );
   if ( $octets ) {

commit 211865a049969b1b539988cc8558ee35e8cb5945
Author: Mitch Jackson <mitch at freeside.biz>
Date:   Tue Jun 26 17:34:50 2018 -0500

    RT# 30783 Selectbox of available IPs when provisioning

diff --git a/FS/FS/addr_block.pm b/FS/FS/addr_block.pm
index eb84dafc3..74c372e29 100755
--- a/FS/FS/addr_block.pm
+++ b/FS/FS/addr_block.pm
@@ -209,7 +209,7 @@ sub cidr {
 
 =item free_addrs
 
-Returns a sorted list of free addresses in the block.
+Returns an aref sorted list of free addresses in the block.
 
 =cut
 
@@ -221,7 +221,11 @@ sub free_addrs {
     FS::IP_Mixin->used_addresses_in_block($self),
     FS::Conf->new()->config('exclude_ip_addr');
 
-  grep { !exists $used_addr_map{$_} } map { $_->addr } $self->NetAddr->hostenum;
+  [
+    grep { !exists $used_addr_map{$_} }
+    map { $_->addr }
+    $self->NetAddr->hostenum
+  ];
 }
 
 =item next_free_addr
diff --git a/httemplate/elements/tr-select-router_block_ip.html b/httemplate/elements/tr-select-router_block_ip.html
index 2aa715e29..535e953c4 100644
--- a/httemplate/elements/tr-select-router_block_ip.html
+++ b/httemplate/elements/tr-select-router_block_ip.html
@@ -2,34 +2,110 @@
 var manual_addr_routernum = <% encode_json(\%manual_addr_routernum) %>;
 var ip_addr_curr_value = <% $opt{'ip_addr'} |js_string %>;
 var blocknum_curr_value = <% $opt{'blocknum'} |js_string %>;
-function update_ip_addr(obj, i) {
-  var routernum = document.getElementById('router_select_0').value;
-  var select_blocknum = document.getElementById('router_select_1');
-  var blocknum = select_blocknum.value;
-  var input_ip_addr = document.getElementById('input_ip_addr');
+
+function update_ip_addr() {
+  var routernum = $('#router_select_0').val();
+  var blocknum  = $('#router_select_1').val();
+  var e_input_ip_addr = $('#input_ip_addr');
+  var e_router_select_1 = $('#router_select_1');
+
+  <% # Is block is automatically selected for this router? %>
   if ( manual_addr_routernum[routernum] == 'Y' ) {
-%# hide block selection and default ip address to its previous value
-    select_blocknum.style.display = 'none';
-    input_ip_addr.value = ip_addr_curr_value;
-  }
-  else {
-%# the reverse
-    select_blocknum.style.display = '';
-%# default ip address to null, unless the router/block are set to the 
-%# previous value, in which case default it to current value
+    show_ip_input();
+    hide_ip_select();
+    e_router_select_1.hide();
+    e_input_ip_addr.val( ip_addr_curr_value );
+  } else {
+    e_router_select_1.show();
+    e_input_ip_addr.attr('placeholder', <% mt('(automatic)') | js_string %> );
     if ( routernum == router_curr_values[0] &&
-         blocknum  == router_curr_values[1] ) {
-      input_ip_addr.value = ip_addr_curr_value;
+         blocknum == router_curr_values[1] ) {
+      e_input_ip_addr.val( ip_addr_curr_value );
     } else {
-      input_ip_addr.value = <% mt('(automatic)') |js_string %>;
+      e_input_ip_addr.val('');
     }
   }
+  show_or_hide_toggle_ip();
+  populate_ip_select();
+}
+
+function toggle_ip_input() {
+  if ( $('#input_ip_addr').is(':hidden') ) {
+    show_ip_input();
+  } else {
+    show_ip_select();
+  }
+}
+
+function show_ip_input() {
+  $('#input_ip_addr').show();
+  $('#select_ip_addr').hide();
+  depopulate_ip_select();
+}
+
+function show_ip_select() {
+  var e_input_ip_addr = $('#input_ip_addr');
+  var e_select_ip_addr = $('#select_ip_addr');
+
+  e_select_ip_addr.width( e_input_ip_addr.width() );
+  e_input_ip_addr.hide();
+  e_select_ip_addr.show();
+  populate_ip_select();
+}
+
+function populate_ip_select() {
+  depopulate_ip_select();
+  var e = $('#select_ip_addr');
+  var blocknum = $('#router_select_1').val();
+
+  var opts = [ '<option value="">loading...</option>' ];
+  e.html(opts.join(''));
+
+% if ( $opt{ip_addr} ) {
+  opts = [
+    '<option value="<% $opt{ip_addr} |h %>"><% $opt{ip_addr} |h %></option>',
+    '<option value="">-----------</option>'
+  ];
+% } else {
+  opts = [ '<option value=""><% mt('(automatic)') |h %></option>' ];
+% }
+  if ( blocknum && $.isNumeric(blocknum) && ! e.is(':hidden')) {
+    $.getJSON(
+      '<% $p %>json/free_addresses_in_block.json.html',
+      {blocknum: blocknum},
+      function(ip_json) {
+        $.each( ip_json, function(idx, val) {
+          opts.push(
+            '<option' + (val == ip_addr_curr_value ? 'selected' : '') + '>'
+            + val
+            + '</option>'
+          );
+        });
+        e.html(opts.join(''));
+      }
+    );
+  }
 }
-function clearhint_ip_addr (what) {
-  if ( what.value == <% mt('(automatic)') |js_string %> )
-    what.value = '';
+
+function depopulate_ip_select() {
+  $('#select_ip_addr').children().remove();
 }
+
+function propogate_ip_select() {
+  $('#input_ip_addr').val( $('#select_ip_addr').val() );
+}
+
+function show_or_hide_toggle_ip() {
+  if ( $('#router_select_1').val() ) {
+    $('#toggle_ip').show();
+  } else {
+    show_ip_input();
+    $('#toggle_ip').hide();
+  }
+}
+
 </script>
+
 <& /elements/tr-td-label.html, label => ($opt{'label'} || 'Router'), required => $opt{'required'} &>
 <td>
   <& /elements/select-tiered.html, prefix => 'router_', tiers => [
@@ -58,14 +134,20 @@ function clearhint_ip_addr (what) {
 </td></tr>
 <& /elements/tr-td-label.html, label => ($opt{'ip_addr_label'} || 'IP address'), required => $opt{'ip_addr_required'} &>
 <td>
-% #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'} || '' %>
 % }
 % else {
-  <input type="text" id="input_ip_addr" name="<% $ip_field %>" 
-  value="<% $opt{'ip_addr'} |h%>" onfocus="clearhint_ip_addr(this)">
+    <input type="text"
+           id="input_ip_addr"
+           name="<% $ip_field %>"
+           value="<% $opt{'ip_addr'} | h %>"
+           onfocus="clearhint_ip_addr(this)">
+    <select id="select_ip_addr" style="display: none;" onChange='javascript:propogate_ip_select();'>
+      <option><% mt('loading') |h %>...</option>
+    </select>
+    <button type="button" onClick='javascript:toggle_ip_input();' id="toggle_ip" style="display: none;">▼</button>
 % }
 </td> </tr>
 <script type="text/javascript">
diff --git a/httemplate/json/free_addresses_in_block.json.html b/httemplate/json/free_addresses_in_block.json.html
new file mode 100644
index 000000000..6785aac6b
--- /dev/null
+++ b/httemplate/json/free_addresses_in_block.json.html
@@ -0,0 +1,18 @@
+<%doc>
+  Return a json array containing all free ip addresses within a given block
+  Unless block is larger than /24 - Does somebody really want to populate
+  65k addresses into a HTML selectbox?
+</%doc>
+<% encode_rest($json) %>\
+<%init>
+
+my $json = [];
+
+my $blocknum = $cgi->param('blocknum');
+
+my $addr_block = qsearchs( addr_block => { blocknum => $blocknum });
+
+$json = $addr_block->free_addrs
+  if ref $addr_block && $addr_block->ip_netmask >= 24;
+
+</%init>

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

Summary of changes:
 FS/FS/IP_Mixin.pm                                  |  30 +----
 FS/FS/addr_block.pm                                |  12 +-
 FS/FS/svc_IP_Mixin.pm                              |  33 ++----
 httemplate/elements/tr-select-router_block_ip.html | 128 +++++++++++++++++----
 httemplate/json/free_addresses_in_block.json.html  |  18 +++
 5 files changed, 145 insertions(+), 76 deletions(-)
 create mode 100644 httemplate/json/free_addresses_in_block.json.html




More information about the freeside-commits mailing list