User Reports via config, without requiring HTML or Perl

This commit is contained in:
Oliver Gorwits
2014-02-27 16:51:08 +00:00
parent 49d8c67f9e
commit 9f558482e0
9 changed files with 150 additions and 3 deletions

View File

@@ -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] [BUG FIXES]

View 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;

View File

@@ -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 List of additional L<App::Netdisco::Web::Plugin> names to load. See also the
C<web_plugins> setting. 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> =head3 C<jobqueue_refresh>
Value: Integer Number. Default: 5. Value: Integer Number. Default: 5.

View File

@@ -118,7 +118,11 @@ the name of the registration helper sub:
=head1 Reports =head1 Reports
Report components contain pre-canned searches which the user community have 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. and Device page Tabs, so please read that documentation above, first.
Report plugins usually live in the C<App::Netdisco::Web::Plugin::Report> Report plugins usually live in the C<App::Netdisco::Web::Plugin::Report>

View File

@@ -22,6 +22,7 @@ use App::Netdisco::Web::TypeAhead;
use App::Netdisco::Web::PortControl; use App::Netdisco::Web::PortControl;
use App::Netdisco::Web::Statistics; use App::Netdisco::Web::Statistics;
use App::Netdisco::Web::Password; use App::Netdisco::Web::Password;
use App::Netdisco::Web::GenericReport;
sub _load_web_plugins { sub _load_web_plugins {
my $plugin_list = shift; my $plugin_list = shift;

View 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;

View File

@@ -55,7 +55,7 @@ safe_password_store: true
# when: '20 23 * * *' # when: '20 23 * * *'
# increase the performance of parallel DNS resolution for node # increase the performance of parallel DNS resolution for node
# names (the default is max_outstanding: 10) # names (the default is max_outstanding: 50)
# ```````````````````````````````````````````````````````````` # ````````````````````````````````````````````````````````````
#dns: #dns:
# max_outstanding: 100 # max_outstanding: 100

View 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>

View 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 %]