User Reports via config, without requiring HTML or Perl
This commit is contained in:
@@ -1,4 +1,10 @@
|
||||
2.024001 -
|
||||
2.024002 - 2014-02-27
|
||||
|
||||
[NEW FEATURES]
|
||||
|
||||
* User Reports via config, without requiring HTML or Perl
|
||||
|
||||
2.024001 - 2014-02-25
|
||||
|
||||
[BUG FIXES]
|
||||
|
||||
|
||||
13
Netdisco/lib/App/Netdisco/DB/Result/Virtual/GenericReport.pm
Normal file
13
Netdisco/lib/App/Netdisco/DB/Result/Virtual/GenericReport.pm
Normal file
@@ -0,0 +1,13 @@
|
||||
package App::Netdisco::DB::Result::Virtual::GenericReport;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use base 'DBIx::Class::Core';
|
||||
|
||||
__PACKAGE__->table_class('DBIx::Class::ResultSource::View');
|
||||
__PACKAGE__->table("generic_report");
|
||||
__PACKAGE__->result_source_instance->is_virtual(1);
|
||||
__PACKAGE__->result_source_instance->view_definition(q{});
|
||||
|
||||
1;
|
||||
@@ -222,6 +222,50 @@ Value: List of Modules. Default: Empty List.
|
||||
List of additional L<App::Netdisco::Web::Plugin> names to load. See also the
|
||||
C<web_plugins> setting.
|
||||
|
||||
=head3 C<reports>
|
||||
|
||||
Value: Dictionary of Reports Hashes. Default: None.
|
||||
|
||||
Use this configuration to add reports to Netdisco without writing any Perl
|
||||
code or HTML templates. For example:
|
||||
|
||||
reports:
|
||||
power_inventory:
|
||||
category: Device
|
||||
label: 'Power Supply Inventory'
|
||||
columns:
|
||||
- {name: 'Name'}
|
||||
- {ps1_type: 'PS1 Type'}
|
||||
- {ps1_status: 'PS1 Status'}
|
||||
query: |
|
||||
SELECT d.name, d.ps1_type, d.ps1_status
|
||||
FROM device d
|
||||
ORDER BY name
|
||||
|
||||
Each key of the C<reports> configuration is an alias for the report, and
|
||||
becomes part of the web path. Within the tree you must provide each of the
|
||||
keys shown:
|
||||
|
||||
=head4 C<category>
|
||||
|
||||
Section of the Reports menu where this report will appear. See
|
||||
L<WritingPlugins|App::Netdisco::Manual::WritingPlugins> for the full list.
|
||||
|
||||
=head4 C<label>
|
||||
|
||||
Title for the Report.
|
||||
|
||||
=head4 C<columns>
|
||||
|
||||
List of single-key Hashes which map database column (field) name to table
|
||||
heading.
|
||||
|
||||
=head4 C<query>
|
||||
|
||||
SQL which returns the data. Make sure that the columns are named the same as
|
||||
the keys of the C<columns> configuration. Note the way the SQL is specified in
|
||||
the example above, using the pipe symbol and then indenting the query text.
|
||||
|
||||
=head3 C<jobqueue_refresh>
|
||||
|
||||
Value: Integer Number. Default: 5.
|
||||
|
||||
@@ -118,7 +118,11 @@ the name of the registration helper sub:
|
||||
=head1 Reports
|
||||
|
||||
Report components contain pre-canned searches which the user community have
|
||||
found to be useful. The implementation is very similar to one of the Search
|
||||
found to be useful. Before you go further, it might be the case that you can
|
||||
generate the report without any Perl or HTML: see the L<Reports
|
||||
Configuration|App::Netdisco::Manual::Configuration/reports> for details.
|
||||
|
||||
Otherwise, the typical implementation is very similar to one of the Search
|
||||
and Device page Tabs, so please read that documentation above, first.
|
||||
|
||||
Report plugins usually live in the C<App::Netdisco::Web::Plugin::Report>
|
||||
|
||||
@@ -22,6 +22,7 @@ use App::Netdisco::Web::TypeAhead;
|
||||
use App::Netdisco::Web::PortControl;
|
||||
use App::Netdisco::Web::Statistics;
|
||||
use App::Netdisco::Web::Password;
|
||||
use App::Netdisco::Web::GenericReport;
|
||||
|
||||
sub _load_web_plugins {
|
||||
my $plugin_list = shift;
|
||||
|
||||
50
Netdisco/lib/App/Netdisco/Web/GenericReport.pm
Normal file
50
Netdisco/lib/App/Netdisco/Web/GenericReport.pm
Normal file
@@ -0,0 +1,50 @@
|
||||
package App::Netdisco::Web::GenericReport;
|
||||
|
||||
use Dancer ':syntax';
|
||||
use Dancer::Plugin::Ajax;
|
||||
use Dancer::Plugin::DBIC;
|
||||
use Dancer::Plugin::Auth::Extensible;
|
||||
|
||||
use App::Netdisco::Web::Plugin;
|
||||
|
||||
foreach my $r (keys %{setting('reports')}) {
|
||||
my $report = setting('reports')->{$r};
|
||||
|
||||
register_report({
|
||||
tag => $r,
|
||||
label => $report->{label},
|
||||
category => $report->{category},
|
||||
provides_csv => true,
|
||||
});
|
||||
|
||||
get "/ajax/content/report/$r" => require_login sub {
|
||||
my $rs = schema('netdisco')->resultset('Virtual::GenericReport')->result_source;
|
||||
|
||||
# this should be done by creating a new Virtual Result class on the fly
|
||||
# (package...) and then calling DBIC register_class on it.
|
||||
$rs->view_definition($report->{query});
|
||||
$rs->remove_columns($rs->columns);
|
||||
$rs->add_columns(map {keys %{$_}} @{$report->{columns}});
|
||||
|
||||
my $set = schema('netdisco')->resultset('Virtual::GenericReport');
|
||||
return unless $set->count;
|
||||
|
||||
if (request->is_ajax) {
|
||||
template 'ajax/report/generic_report.tt',
|
||||
{ results => $set,
|
||||
headings => [map {values %{$_}} @{$report->{columns}}],
|
||||
columns => [$rs->columns] },
|
||||
{ layout => undef };
|
||||
}
|
||||
else {
|
||||
header( 'Content-Type' => 'text/comma-separated-values' );
|
||||
template 'ajax/report/generic_report_csv.tt',
|
||||
{ results => $set,
|
||||
headings => [map {values %{$_}} @{$report->{columns}}],
|
||||
columns => [$rs->columns] },
|
||||
{ layout => undef };
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
true;
|
||||
@@ -55,7 +55,7 @@ safe_password_store: true
|
||||
# when: '20 23 * * *'
|
||||
|
||||
# increase the performance of parallel DNS resolution for node
|
||||
# names (the default is max_outstanding: 10)
|
||||
# names (the default is max_outstanding: 50)
|
||||
# ````````````````````````````````````````````````````````````
|
||||
#dns:
|
||||
# max_outstanding: 100
|
||||
|
||||
18
Netdisco/share/views/ajax/report/generic_report.tt
Normal file
18
Netdisco/share/views/ajax/report/generic_report.tt
Normal file
@@ -0,0 +1,18 @@
|
||||
<table class="table table-bordered table-condensed table-striped nd_floatinghead">
|
||||
<thead>
|
||||
<tr>
|
||||
[% FOREACH hdr IN headings %]
|
||||
<th>[% hdr | html_entity %]</th>
|
||||
[% END %]
|
||||
</tr>
|
||||
</thead>
|
||||
</tbody>
|
||||
[% WHILE (row = results.next) %]
|
||||
<tr>
|
||||
[% FOREACH col IN columns %]
|
||||
<td>[% row.get_column(col) | html_entity %]</td>
|
||||
[% END %]
|
||||
</tr>
|
||||
[% END %]
|
||||
</tbody>
|
||||
</table>
|
||||
11
Netdisco/share/views/ajax/report/generic_report_csv.tt
Normal file
11
Netdisco/share/views/ajax/report/generic_report_csv.tt
Normal file
@@ -0,0 +1,11 @@
|
||||
[% USE CSV %]
|
||||
[% CSV.dump(headings) %]
|
||||
|
||||
[% FOREACH row IN results.all %]
|
||||
[% mylist = [] %]
|
||||
[% FOREACH col IN columns %]
|
||||
[% mylist.push(row.get_column(col)) %]
|
||||
[% END %]
|
||||
[% CSV.dump(mylist) %]
|
||||
|
||||
[% END %]
|
||||
Reference in New Issue
Block a user