Plugins can have CSS and Javascript loaded within <head>
This commit is contained in:
@@ -12,7 +12,9 @@
|
|||||||
* Job Queue view and delete page
|
* Job Queue view and delete page
|
||||||
* Empty device table prompts initial discover on homepage
|
* Empty device table prompts initial discover on homepage
|
||||||
* Support for App::NetdiscoX::Web::Plugin namespace
|
* Support for App::NetdiscoX::Web::Plugin namespace
|
||||||
|
* Plugins can add columns to Device Ports display
|
||||||
* Observium Sparklines port column plugin
|
* Observium Sparklines port column plugin
|
||||||
|
* Plugins can have CSS and Javascript loaded within <head>
|
||||||
|
|
||||||
[ENHANCEMENTS]
|
[ENHANCEMENTS]
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ use HTML::Entities (); # to ensure dependency is met
|
|||||||
use URI::QueryParam (); # part of URI, to add helper methods
|
use URI::QueryParam (); # part of URI, to add helper methods
|
||||||
|
|
||||||
use App::Netdisco::Web::AuthN;
|
use App::Netdisco::Web::AuthN;
|
||||||
|
use App::Netdisco::Web::Static;
|
||||||
use App::Netdisco::Web::Search;
|
use App::Netdisco::Web::Search;
|
||||||
use App::Netdisco::Web::Device;
|
use App::Netdisco::Web::Device;
|
||||||
use App::Netdisco::Web::Report;
|
use App::Netdisco::Web::Report;
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ hook 'before' => sub {
|
|||||||
if (session('user') && session->id) {
|
if (session('user') && session->id) {
|
||||||
var(user => schema('netdisco')->resultset('User')
|
var(user => schema('netdisco')->resultset('User')
|
||||||
->find(session('user')));
|
->find(session('user')));
|
||||||
|
var('user')->port_control(0)
|
||||||
|
if setting('no_port_control');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ use Dancer ':syntax';
|
|||||||
use Dancer::Plugin;
|
use Dancer::Plugin;
|
||||||
|
|
||||||
set(
|
set(
|
||||||
|
'_additional_css' => [],
|
||||||
|
'_additional_javascript' => [],
|
||||||
'_extra_device_port_cols' => [],
|
'_extra_device_port_cols' => [],
|
||||||
'_navbar_items' => [],
|
'_navbar_items' => [],
|
||||||
'_search_tabs' => [],
|
'_search_tabs' => [],
|
||||||
@@ -30,6 +32,32 @@ register 'register_template_path' => sub {
|
|||||||
$path;
|
$path;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
sub _register_include {
|
||||||
|
my ($type, $plugin) = @_;
|
||||||
|
|
||||||
|
if (!length $type) {
|
||||||
|
error "bad type to _register_include";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!length $plugin) {
|
||||||
|
error "bad plugin name to register_$type";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
push @{ setting("_additional_$type") }, $plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
register 'register_css' => sub {
|
||||||
|
my ($self, $plugin) = plugin_args(@_);
|
||||||
|
_register_include('css', $plugin);
|
||||||
|
};
|
||||||
|
|
||||||
|
register 'register_javascript' => sub {
|
||||||
|
my ($self, $plugin) = plugin_args(@_);
|
||||||
|
_register_include('javascript', $plugin);
|
||||||
|
};
|
||||||
|
|
||||||
register 'register_device_port_column' => sub {
|
register 'register_device_port_column' => sub {
|
||||||
my ($self, $config) = plugin_args(@_);
|
my ($self, $config) = plugin_args(@_);
|
||||||
$config->{default} ||= '';
|
$config->{default} ||= '';
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ ajax '/ajax/content/device/ports' => sub {
|
|||||||
template 'ajax/device/ports.tt', {
|
template 'ajax/device/ports.tt', {
|
||||||
results => $results,
|
results => $results,
|
||||||
nodes => $nodes_name,
|
nodes => $nodes_name,
|
||||||
device => $device->ip,
|
device => $device,
|
||||||
}, { layout => undef };
|
}, { layout => undef };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
30
Netdisco/lib/App/Netdisco/Web/Static.pm
Normal file
30
Netdisco/lib/App/Netdisco/Web/Static.pm
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
package App::Netdisco::Web::Static;
|
||||||
|
|
||||||
|
use Dancer ':syntax';
|
||||||
|
use Path::Class;
|
||||||
|
|
||||||
|
get '/plugin/*/*.js' => sub {
|
||||||
|
my ($plugin) = splat;
|
||||||
|
|
||||||
|
my $content = template
|
||||||
|
"plugin/$plugin/$plugin.js", {},
|
||||||
|
{ layout => undef };
|
||||||
|
|
||||||
|
send_file \$content,
|
||||||
|
content_type => 'application/javascript',
|
||||||
|
filename => "$plugin.js";
|
||||||
|
};
|
||||||
|
|
||||||
|
get '/plugin/*/*.css' => sub {
|
||||||
|
my ($plugin) = splat;
|
||||||
|
|
||||||
|
my $content = template
|
||||||
|
"plugin/$plugin/$plugin.css", {},
|
||||||
|
{ layout => undef };
|
||||||
|
|
||||||
|
send_file \$content,
|
||||||
|
content_type => 'text/css',
|
||||||
|
filename => "$plugin.css";
|
||||||
|
};
|
||||||
|
|
||||||
|
true;
|
||||||
@@ -5,11 +5,17 @@ use Dancer::Plugin::DBIC;
|
|||||||
|
|
||||||
use App::Netdisco::Web::Plugin;
|
use App::Netdisco::Web::Plugin;
|
||||||
|
|
||||||
|
use File::ShareDir 'dist_dir';
|
||||||
|
use Path::Class;
|
||||||
|
|
||||||
register_device_port_column({
|
register_device_port_column({
|
||||||
name => 'c_observiumsparklines',
|
name => 'observiumsparklines',
|
||||||
position => 'mid',
|
position => 'mid',
|
||||||
label => 'Traffic',
|
label => 'Traffic',
|
||||||
default => 'on',
|
default => 'on',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
register_css('observiumsparklines');
|
||||||
|
register_javascript('observiumsparklines');
|
||||||
|
|
||||||
true;
|
true;
|
||||||
|
|||||||
1
Netdisco/share/public/css/jquery.qtip.min.css
vendored
Normal file
1
Netdisco/share/public/css/jquery.qtip.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
2
Netdisco/share/public/javascripts/jquery.qtip.min.js
vendored
Normal file
2
Netdisco/share/public/javascripts/jquery.qtip.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -32,7 +32,7 @@
|
|||||||
[% NEXT UNLESS config.position == 'left' AND params.${config.name} %]
|
[% NEXT UNLESS config.position == 'left' AND params.${config.name} %]
|
||||||
<td>
|
<td>
|
||||||
[% TRY %]
|
[% TRY %]
|
||||||
[% INCLUDE "plugin/device_port_column/${config.name}.tt" %]
|
[% INCLUDE "plugin/${config.name}/device_port_column.tt" %]
|
||||||
[% CATCH %]
|
[% CATCH %]
|
||||||
<!-- dummy content required by Template Toolkit TRY -->
|
<!-- dummy content required by Template Toolkit TRY -->
|
||||||
[% END %]
|
[% END %]
|
||||||
@@ -43,13 +43,13 @@
|
|||||||
[% IF vars.user.port_control AND params.c_admin %]
|
[% IF vars.user.port_control AND params.c_admin %]
|
||||||
[% IF row.up_admin == 'up' %]
|
[% IF row.up_admin == 'up' %]
|
||||||
<td nowrap class="nd_editable-cell" data-action="down"
|
<td nowrap class="nd_editable-cell" data-action="down"
|
||||||
data-field="c_port" data-for-device="[% device | html_entity %]" data-for-port="[% row.port | html_entity %]">
|
data-field="c_port" data-for-device="[% device.ip | html_entity %]" data-for-port="[% row.port | html_entity %]">
|
||||||
<i class="icon-hand-down nd_hand-icon"
|
<i class="icon-hand-down nd_hand-icon"
|
||||||
rel="tooltip" data-placement="top" data-offset="3"
|
rel="tooltip" data-placement="top" data-offset="3"
|
||||||
data-animation="" data-title="Click to Disable"></i>
|
data-animation="" data-title="Click to Disable"></i>
|
||||||
[% ELSE %]
|
[% ELSE %]
|
||||||
<td nowrap class="nd_editable-cell" data-action="up"
|
<td nowrap class="nd_editable-cell" data-action="up"
|
||||||
data-field="c_port" data-for-device="[% device | html_entity %]" data-for-port="[% row.port | html_entity %]">
|
data-field="c_port" data-for-device="[% device.ip | html_entity %]" data-for-port="[% row.port | html_entity %]">
|
||||||
<i class="icon-hand-up nd_hand-icon"
|
<i class="icon-hand-up nd_hand-icon"
|
||||||
rel="tooltip" data-placement="top" data-offset="3"
|
rel="tooltip" data-placement="top" data-offset="3"
|
||||||
data-animation="" data-title="Click to Enable"></i>
|
data-animation="" data-title="Click to Enable"></i>
|
||||||
@@ -66,13 +66,9 @@
|
|||||||
[% FOREACH config IN settings._extra_device_port_cols %]
|
[% FOREACH config IN settings._extra_device_port_cols %]
|
||||||
[% NEXT UNLESS config.position == 'mid' AND params.${config.name} %]
|
[% NEXT UNLESS config.position == 'mid' AND params.${config.name} %]
|
||||||
<td>
|
<td>
|
||||||
[% TRY %]
|
[% INCLUDE "plugin/${config.name}/device_port_column.tt" %]
|
||||||
[% INCLUDE "plugin/device_port_column/${config.name}.tt" %]
|
|
||||||
[% CATCH %]
|
|
||||||
<!-- dummy content required by Template Toolkit TRY -->
|
|
||||||
[% END %]
|
|
||||||
</td>
|
</td>
|
||||||
[% END %]
|
[% END -%]
|
||||||
|
|
||||||
[% IF params.c_descr %]
|
[% IF params.c_descr %]
|
||||||
<td nowrap>[% row.descr | html_entity %]</td>
|
<td nowrap>[% row.descr | html_entity %]</td>
|
||||||
@@ -97,7 +93,7 @@
|
|||||||
[% IF params.c_name %]
|
[% IF params.c_name %]
|
||||||
[% IF vars.user.port_control AND params.c_admin %]
|
[% IF vars.user.port_control AND params.c_admin %]
|
||||||
<td nowrap class="nd_editable-cell" contenteditable="true"
|
<td nowrap class="nd_editable-cell" contenteditable="true"
|
||||||
data-field="c_name" data-for-device="[% device | html_entity %]" data-for-port="[% row.port | html_entity %]">
|
data-field="c_name" data-for-device="[% device.ip | html_entity %]" data-for-port="[% row.port | html_entity %]">
|
||||||
<i class="icon-edit nd_edit-icon"></i>
|
<i class="icon-edit nd_edit-icon"></i>
|
||||||
[% ELSE %]
|
[% ELSE %]
|
||||||
<td nowrap>
|
<td nowrap>
|
||||||
@@ -123,7 +119,7 @@
|
|||||||
[% IF params.c_vlan %]
|
[% IF params.c_vlan %]
|
||||||
[% IF vars.user.port_control AND params.c_admin %]
|
[% IF vars.user.port_control AND params.c_admin %]
|
||||||
<td class="nd_editable-cell" contenteditable="true"
|
<td class="nd_editable-cell" contenteditable="true"
|
||||||
data-field="c_vlan" data-for-device="[% device | html_entity %]" data-for-port="[% row.port | html_entity %]">
|
data-field="c_vlan" data-for-device="[% device.ip | html_entity %]" data-for-port="[% row.port | html_entity %]">
|
||||||
<i class="icon-edit nd_edit-icon"></i>
|
<i class="icon-edit nd_edit-icon"></i>
|
||||||
<div class="nd_editable-cell-content">
|
<div class="nd_editable-cell-content">
|
||||||
[% IF row.vlan %][% row.vlan | html_entity %][% END %]
|
[% IF row.vlan %][% row.vlan | html_entity %][% END %]
|
||||||
@@ -164,7 +160,7 @@
|
|||||||
[% IF row.power.admin == 'true' %]
|
[% IF row.power.admin == 'true' %]
|
||||||
[% IF vars.user.port_control AND params.c_admin %]
|
[% IF vars.user.port_control AND params.c_admin %]
|
||||||
<td nowrap data-action="false"
|
<td nowrap data-action="false"
|
||||||
data-field="c_power" data-for-device="[% device | html_entity %]"
|
data-field="c_power" data-for-device="[% device.ip | html_entity %]"
|
||||||
data-for-port="[% row.port | html_entity %]">
|
data-for-port="[% row.port | html_entity %]">
|
||||||
|
|
||||||
<i class="icon-off nd_power-icon nd_power-on"
|
<i class="icon-off nd_power-icon nd_power-on"
|
||||||
@@ -184,7 +180,7 @@
|
|||||||
[% ELSE %]
|
[% ELSE %]
|
||||||
[% IF vars.user.port_control AND params.c_admin %]
|
[% IF vars.user.port_control AND params.c_admin %]
|
||||||
<td nowrap data-action="true"
|
<td nowrap data-action="true"
|
||||||
data-field="c_power" data-for-device="[% device | html_entity %]"
|
data-field="c_power" data-for-device="[% device.ip | html_entity %]"
|
||||||
data-for-port="[% row.port | html_entity %]">
|
data-for-port="[% row.port | html_entity %]">
|
||||||
|
|
||||||
<i class="icon-off nd_power-icon"
|
<i class="icon-off nd_power-icon"
|
||||||
@@ -256,7 +252,7 @@
|
|||||||
[% NEXT UNLESS config.position == 'right' AND params.${config.name} %]
|
[% NEXT UNLESS config.position == 'right' AND params.${config.name} %]
|
||||||
<td>
|
<td>
|
||||||
[% TRY %]
|
[% TRY %]
|
||||||
[% INCLUDE "plugin/device_port_column/${config.name}.tt" %]
|
[% INCLUDE "plugin/${config.name}/device_port_column.tt" %]
|
||||||
[% CATCH %]
|
[% CATCH %]
|
||||||
<!-- dummy content required by Template Toolkit TRY -->
|
<!-- dummy content required by Template Toolkit TRY -->
|
||||||
[% END %]
|
[% END %]
|
||||||
|
|||||||
@@ -17,26 +17,34 @@
|
|||||||
<script type="text/javascript" src="[% uri_base %]/javascripts/jquery-history.js"></script>
|
<script type="text/javascript" src="[% uri_base %]/javascripts/jquery-history.js"></script>
|
||||||
<script type="text/javascript" src="[% uri_base %]/javascripts/jquery-deserialize.js"></script>
|
<script type="text/javascript" src="[% uri_base %]/javascripts/jquery-deserialize.js"></script>
|
||||||
<script type="text/javascript" src="[% uri_base %]/javascripts/bootstrap.min.js"></script>
|
<script type="text/javascript" src="[% uri_base %]/javascripts/bootstrap.min.js"></script>
|
||||||
|
<script type="text/javascript" src="[% uri_base %]/javascripts/jquery.qtip.min.js"></script>
|
||||||
<script type="text/javascript" src="[% uri_base %]/javascripts/d3.min.js"></script>
|
<script type="text/javascript" src="[% uri_base %]/javascripts/d3.min.js"></script>
|
||||||
|
<script type="text/javascript" src="[% uri_base %]/javascripts/toastr.js"></script>
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
var uri_base = '[% uri_base %]';
|
var uri_base = '[% uri_base %]';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script type="text/javascript" src="[% uri_base %]/javascripts/netdisco.js"></script>
|
<script type="text/javascript" src="[% uri_base %]/javascripts/netdisco.js"></script>
|
||||||
|
|
||||||
[% IF vars.user.port_control %]
|
[% IF vars.user.port_control %]
|
||||||
<script type="text/javascript" src="[% uri_base %]/javascripts/toastr.js"></script>
|
|
||||||
<script type="text/javascript" src="[% uri_base %]/javascripts/netdisco_portcontrol.js"></script>
|
<script type="text/javascript" src="[% uri_base %]/javascripts/netdisco_portcontrol.js"></script>
|
||||||
|
[% END %]
|
||||||
|
|
||||||
<link rel="stylesheet" href="[% uri_base %]/css/toastr.css"/>
|
[% FOREACH add_js IN settings._additional_javascript %]
|
||||||
|
<script type="text/javascript" src="[% uri_base %]/plugin/[% add_js %]/[% add_js %].js"></script>
|
||||||
[% END %]
|
[% END %]
|
||||||
|
|
||||||
<link rel="stylesheet" href="[% uri_base %]/css/bootstrap.min.css"/>
|
<link rel="stylesheet" href="[% uri_base %]/css/bootstrap.min.css"/>
|
||||||
|
<link rel="stylesheet" href="[% uri_base %]/css/jquery.qtip.min.css"/>
|
||||||
<link rel="stylesheet" href="[% uri_base %]/css/smoothness/jquery-ui.custom.min.css"/>
|
<link rel="stylesheet" href="[% uri_base %]/css/smoothness/jquery-ui.custom.min.css"/>
|
||||||
<link rel="stylesheet" href="[% uri_base %]/css/font-awesome.min.css"/>
|
<link rel="stylesheet" href="[% uri_base %]/css/font-awesome.min.css"/>
|
||||||
|
<link rel="stylesheet" href="[% uri_base %]/css/toastr.css"/>
|
||||||
<link rel="stylesheet" href="[% uri_base %]/css/netdisco.css"/>
|
<link rel="stylesheet" href="[% uri_base %]/css/netdisco.css"/>
|
||||||
<link rel="stylesheet" href="[% uri_base %]/css/nd_print.css" media="print"/>
|
<link rel="stylesheet" href="[% uri_base %]/css/nd_print.css" media="print"/>
|
||||||
|
|
||||||
|
[% FOREACH add_css IN settings._additional_css %]
|
||||||
|
<link rel="stylesheet" href="[% uri_base %]/plugin/[% add_css %]/[% add_css %].css"/>
|
||||||
|
[% END %]
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
<!-- not yet a hyperlink as observium does not support device details page by device-name -->
|
|
||||||
<img src="http://[% settings.plugin_c_observiumsparklines.webhost | html_entity %]/graph.php?type=port_bits&device=[% device | uri %]&port=[% row.port | uri %]&from=-1d&to=now&width=100&height=20&legend=no"/>
|
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
<button class="btn" rel="popover" data-trigger="hover" data-html="true" data-content='
|
||||||
|
<img src="http://[% settings.plugin_observiumsparklines.webhost | html_entity %]/graph.php?type=port_bits&device=[% device.dns || device.name | uri %]&port=[% row.port | uri %]&from=-1w&to=now&width=208&height=100&title=yes"/>
|
||||||
|
'
|
||||||
|
><i class="icon-bar-chart"></i></button>
|
||||||
Reference in New Issue
Block a user