custom fields on devices and ports in the web from config (#945)

* custom device field web display and edit

* make display work; relies on T::T calling dict slot or method with same syntax

* add storing port custom fields

* use resultset method instead, use cf_ prefix

* update Pg min ver for jsonb

* allow override of position and default for port custom fields

* support hidden for custom fields

* update description of Objects API class

* allow left and mid position for custom fields

* add custom fields in csv

* change port control sidebar label

* fix default missing bug on backend jobs
This commit is contained in:
Oliver Gorwits
2022-12-09 10:20:26 +00:00
committed by GitHub
parent d03eab02db
commit 1c7c749f0e
15 changed files with 225 additions and 44 deletions

View File

@@ -0,0 +1,86 @@
package App::Netdisco::Web::CustomFields;
use Dancer ':syntax';
use Dancer::Plugin::DBIC;
use App::Netdisco::DB::ResultSet::Device;
use App::Netdisco::DB::ResultSet::DevicePort;
use App::Netdisco::Web::Plugin;
my @inline_device_actions = ();
my @inline_device_port_actions = ();
foreach my $config (@{ setting('custom_fields')->{'device'} || [] }) {
if (! $config->{'name'}) {
error 'custom_field missing name';
next;
}
register_device_details({
%{ $config },
field => ('cf_' . $config->{'name'}),
label => ($config->{'label'} || ucfirst $config->{'name'}),
}) unless $config->{'hidden'};
push @inline_device_actions, $config->{'name'};
}
foreach my $config (@{ setting('custom_fields')->{'device_port'} || [] }) {
if (! $config->{'name'}) {
error 'custom_field missing name';
next;
}
register_device_port_column({
position => 'right', # or "mid" or "right"
default => undef, # or undef
%{ $config },
field => ('cf_' . $config->{'name'}),
label => ($config->{'label'} || ucfirst $config->{'name'}),
}) unless $config->{'hidden'};
push @inline_device_port_actions, $config->{'name'};
}
{
package App::Netdisco::DB::ResultSet::Device;
sub with_custom_fields {
my ($rs, $cond, $attrs) = @_;
return $rs
->search_rs($cond, $attrs)
->search({},
{ '+columns' => {
map {( ('cf_'. $_) => \[ 'me.custom_fields ->> ?' => $_ ] )}
@inline_device_actions
}});
}
}
{
package App::Netdisco::DB::ResultSet::DevicePort;
sub with_custom_fields {
my ($rs, $cond, $attrs) = @_;
return $rs
->search_rs($cond, $attrs)
->search({},
{ '+columns' => {
map {( ('cf_'. $_) => \[ 'me.custom_fields ->> ?' => $_ ] )}
@inline_device_port_actions
}});
}
}
set('_inline_actions' => [
map {'cf_' . $_} (@inline_device_actions, @inline_device_port_actions)
]);
true;

View File

@@ -23,8 +23,7 @@ ajax '/ajax/content/device/details' => require_login sub {
'+as' => ['has_snapshot'],
join => 'snapshot',
},
)->with_times()
->hri->all;
)->with_times->with_custom_fields->hri->all;
my @power
= schema(vars->{'tenant'})->resultset('DevicePower')

View File

@@ -20,7 +20,7 @@ get '/ajax/content/device/ports' => require_login sub {
my $device = schema(vars->{'tenant'})->resultset('Device')
->search_for_device($q) or send_error('Bad device', 400);
my $set = $device->ports->with_properties;
my $set = $device->ports->with_properties->with_custom_fields;
# refine by ports if requested
my $f = param('f');

View File

@@ -24,7 +24,7 @@ ajax '/ajax/portcontrol' => require_any_role [qw(admin port_control)] => sub {
'c_power' => 'power',
);
my $action = $action_map{ param('field') };
my $action = ($action_map{ param('field') } || param('field') || '');
my $subaction = ($action =~ m/^(?:power|portcontrol)/
? (param('action') ."-other")
: param('value'));
@@ -34,6 +34,7 @@ ajax '/ajax/portcontrol' => require_any_role [qw(admin port_control)] => sub {
my $act = "$action $subaction";
$act =~ s/-other$//;
$act =~ s/^portcontrol/port/;
$act =~ s/^device_port_custom_field_/custom_field: /;
schema(vars->{'tenant'})->resultset('DevicePortLog')->create({
ip => param('device'),