[#181] AP Client Count report was broken

The DB query was joining on the device_port_wireless table which as any fule
kno isn't using the device port subinterface name so there would always be
zero results (as wireless data is related to the subinterface).

Fixed the query to use the device_port_ssid table, and also added a dedicated
template so additional data can be displayed in the report.
This commit is contained in:
Oliver Gorwits
2015-01-25 12:28:35 +00:00
parent 26de31bbbf
commit 85ab6e15ec
7 changed files with 115 additions and 4 deletions

View File

@@ -15,6 +15,7 @@
* [#191] Fix error when stopping stopped web daemon
* [#174] LDAP users should not be able to change password
* [#182] SSID and PoE showing in wrong Device Port columns
* [#181] AP Client Count report was broken
2.030000 - 2015-01-08

View File

@@ -326,6 +326,8 @@ share/views/ajax/device/ports.tt
share/views/ajax/device/ports_csv.tt
share/views/ajax/report/apchanneldist.tt
share/views/ajax/report/apchanneldist_csv.tt
share/views/ajax/report/apclients.tt
share/views/ajax/report/apclients_csv.tt
share/views/ajax/report/apradiochannelpower.tt
share/views/ajax/report/apradiochannelpower_csv.tt
share/views/ajax/report/deviceaddrnodns.tt

View File

@@ -195,6 +195,20 @@ __PACKAGE__->might_have(
}
);
=head2 ssid
Returns a row from the C<device_port_ssid> table if one refers to this
device port.
=cut
__PACKAGE__->might_have(
ssid => 'App::Netdisco::DB::Result::DevicePortSsid',
{ 'foreign.ip' => 'self.ip',
'foreign.port' => 'self.port',
}
);
=head2 wireless
Returns a row from the C<device_port_wireless> table if one refers to this

View File

@@ -47,5 +47,21 @@ __PACKAGE__->belongs_to( port => 'App::Netdisco::DB::Result::DevicePort', {
'foreign.ip' => 'self.ip', 'foreign.port' => 'self.port',
});
=head2 nodes
Returns the set of Nodes whose MAC addresses are associated with this Device
Port SSID.
=cut
__PACKAGE__->has_many( nodes => 'App::Netdisco::DB::Result::Node',
{
'foreign.switch' => 'self.ip',
'foreign.port' => 'self.port',
},
{ join_type => 'LEFT',
cascade_copy => 0, cascade_update => 0, cascade_delete => 0 },
);
# You can replace this text with custom code or comments, and it will be preserved on regeneration
1;

View File

@@ -18,15 +18,16 @@ get '/ajax/content/report/apclients' => require_login sub {
my @results = schema('netdisco')->resultset('Device')->search(
{ 'nodes.time_last' => { '>=', \'me.last_macsuck' } },
{ select => [ 'ip', 'dns', 'name', 'model', 'location' ],
join => { 'ports' => { 'wireless' => 'nodes' } },
join => { 'ports' => { 'ssid' => 'nodes' } },
'+columns' => [
{ 'port' => 'ports.port' },
{ 'description' => 'ports.name' },
{ 'ssid' => 'ssid.ssid' },
{ 'mac_count' => { count => 'nodes.mac' } },
],
group_by => [
'me.ip', 'me.dns', 'me.name', 'me.model',
'me.location', 'ports.port', 'ports.descr', 'ports.name'
'me.location', 'ports.port', 'ports.descr', 'ports.name', 'ssid.ssid',
],
order_by => { -desc => [qw/count/] },
}
@@ -36,12 +37,12 @@ get '/ajax/content/report/apclients' => require_login sub {
if ( request->is_ajax ) {
my $json = to_json( \@results );
template 'ajax/report/portmultinodes.tt', { results => $json },
template 'ajax/report/apclients.tt', { results => $json },
{ layout => undef };
}
else {
header( 'Content-Type' => 'text/comma-separated-values' );
template 'ajax/report/portmultinodes_csv.tt',
template 'ajax/report/apclients_csv.tt',
{ results => \@results },
{ layout => undef };
}

View File

@@ -0,0 +1,63 @@
<table id="data-table" class="table table-striped table-bordered" width="100%" cellspacing="0">
<thead>
<tr>
<th>Device</th>
<th>Model</th>
<th>Location</th>
<th>Port</th>
<th>SSID</th>
<th>Node Count</th>
</tr>
</thead>
</table>
<script type="text/javascript">
$(document).ready(function() {
var table = $('#data-table').dataTable({
"deferRender": true,
"order": [[ 5, "desc" ]],
"data": [% results %],
"columns": [
{
"data": 'ip',
"render": function(data, type, row, meta) {
return type === 'display' ?
'<a href="[% uri_for('/device') %]?tab=details&q=' + encodeURIComponent(row.ip) + '">'
+ he.encode(row.dns || row.name || row.ip) + '</a>' :
data;
}
}, {
"data": 'model',
"render": function(data, type, row, meta) {
return he.encode(data || '');
}
}, {
"data": 'location',
"render": function(data, type, row, meta) {
return he.encode(data || '');
}
}, {
"data": 'port',
"type": 'portsort',
"render": function(data, type, row, meta) {
return type === 'display' ?
'<a href="[% device_ports %]&q=' + encodeURIComponent(row.ip) + '&f=' + encodeURIComponent(data) + '&c_nodes=on">' + he.encode(data) + '</a>' :
data;
}
}, {
"data": 'ssid',
"render": function(data, type, row, meta) {
return he.encode(data || '');
}
}, {
"data": 'mac_count',
"searchable": false,
"render": function(data, type, row, meta) {
return data.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
}
],
[% INCLUDE 'ajax/datatabledefaults.tt' -%]
});
});
</script>

View File

@@ -0,0 +1,14 @@
[% USE CSV -%]
[% CSV.dump([ 'Device' 'Model' 'Location' 'Port' 'SSID' 'Node Count' ]) %]
[% FOREACH row IN results %]
[% mylist = [] %]
[% mylist.push(row.dns || row.name || row.ip) %]
[% mylist.push(row.model) %]
[% mylist.push(row.location) %]
[% mylist.push(row.port) %]
[% mylist.push(row.ssid) %]
[% mylist.push(row.mac_count) %]
[% CSV.dump(mylist) %]
[% END %]