this patch resets all pseudo devices to have no layer3 support but adds a feature to the pseudo devices admin panel to enable layer3 support. it also changes arpnip and arpwalk behaviour to always permit the action if layer3 is available (ignoring the vendor). documentation will need updating to tell users to create pseudo devices with layer3 support when they want to arpnip an unsupported platform. arpnip with ssh/cli against a supported platform (one that can be discovered) will continue to work normally. Squashed commit of the following: commit9dad5be81dAuthor: Oliver Gorwits <oliver@cpan.org> Date: Tue Sep 3 09:03:53 2019 +0100 allow pseudo with layer 3 to run arpnip commit7d97943fcdAuthor: Oliver Gorwits <oliver@cpan.org> Date: Tue Sep 3 08:59:10 2019 +0100 allow pseudo devices with layer 2/3 capability commitd1fdf574e3Author: Oliver Gorwits <oliver@cpan.org> Date: Tue Sep 3 08:55:41 2019 +0100 move pseudo and layer checks to is_able from is_able_now commite0f72ef67dAuthor: Oliver Gorwits <oliver@cpan.org> Date: Tue Sep 3 08:51:42 2019 +0100 ports defaults to one commit86ba01270cAuthor: Oliver Gorwits <oliver@cpan.org> Date: Tue Sep 3 08:50:45 2019 +0100 add tooltip for arpnip toggle commitcdd2470228Author: Oliver Gorwits <oliver@cpan.org> Date: Tue Sep 3 08:34:46 2019 +0100 simplify template commit46236d68eaAuthor: Oliver Gorwits <oliver@cpan.org> Date: Sun Sep 1 23:53:56 2019 +0100 a fix up for pseudo devices which need layer 3 commit016d249efcAuthor: Oliver Gorwits <oliver@cpan.org> Date: Sun Sep 1 20:37:11 2019 +0100 do not wrap buttons commit1ec1402e0cAuthor: Oliver Gorwits <oliver@cpan.org> Date: Sun Sep 1 20:33:03 2019 +0100 implement user settable layer-three service for pseudo devices commita267efa3d8Author: Oliver Gorwits <oliver@cpan.org> Date: Sun Sep 1 18:39:22 2019 +0100 only set layer if successful action commitb108be5e23Author: Oliver Gorwits <oliver@cpan.org> Date: Sun Sep 1 18:32:19 2019 +0100 should defer SNMP against pseudo devices commit897ba3a629Merge:e0ddbaaba7348900Author: Oliver Gorwits <oliver@cpan.org> Date: Sun Sep 1 14:54:36 2019 +0100 Merge branch 'master' into og-pseudo-vs-cli-arpnip commite0ddbaab08Author: Oliver Gorwits <oliver@cpan.org> Date: Mon Aug 26 11:35:13 2019 +0100 as last commit, for discover commit61f9c89040Author: Oliver Gorwits <oliver@cpan.org> Date: Sun Aug 25 23:55:38 2019 +0100 move pseudo and layer checks into is_*able functions commit8b010d4023Author: Oliver Gorwits <oliver@cpan.org> Date: Sun Aug 25 18:38:11 2019 +0100 any device completing macsuck/arpnip must have that layer commita11bce7863Author: Oliver Gorwits <oliver@cpan.org> Date: Sun Aug 25 18:33:27 2019 +0100 clean up device layers commitd2661bff61Author: Oliver Gorwits <oliver@cpan.org> Date: Sun Aug 25 18:18:02 2019 +0100 first make arpnip behave like other jobs towards pseudo devices
This commit is contained in:
@@ -79,6 +79,19 @@ sub jq_warm_thrusters {
|
|||||||
actionset => $actionset{$_},
|
actionset => $actionset{$_},
|
||||||
}, { key => 'primary' }) for keys %actionset;
|
}, { key => 'primary' }) for keys %actionset;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
# fix up the pseudo devices which need layer 3
|
||||||
|
# TODO remove this after next release
|
||||||
|
schema('netdisco')->txn_do(sub {
|
||||||
|
my @hosts = grep { defined }
|
||||||
|
map { schema('netdisco')->resultset('Device')->search_for_device($_->{only}) }
|
||||||
|
grep { exists $_->{only} and ref '' eq ref $_->{only} }
|
||||||
|
grep { exists $_->{driver} and $_->{driver} eq 'cli' }
|
||||||
|
@{ setting('device_auth') };
|
||||||
|
|
||||||
|
$_->update({ layers => \[q{overlay(layers placing '1' from 6 for 1)}] })
|
||||||
|
for @hosts;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
sub jq_getsome {
|
sub jq_getsome {
|
||||||
|
|||||||
@@ -58,8 +58,11 @@ Returns C<undef> if the connection fails.
|
|||||||
sub reader_for {
|
sub reader_for {
|
||||||
my ($class, $ip, $useclass) = @_;
|
my ($class, $ip, $useclass) = @_;
|
||||||
my $device = get_device($ip) or return undef;
|
my $device = get_device($ip) or return undef;
|
||||||
|
return undef if $device->in_storage and $device->is_pseudo;
|
||||||
|
|
||||||
my $readers = $class->instance->readers or return undef;
|
my $readers = $class->instance->readers or return undef;
|
||||||
return $readers->{$device->ip} if exists $readers->{$device->ip};
|
return $readers->{$device->ip} if exists $readers->{$device->ip};
|
||||||
|
|
||||||
debug sprintf 'snmp reader cache warm: [%s]', $device->ip;
|
debug sprintf 'snmp reader cache warm: [%s]', $device->ip;
|
||||||
return ($readers->{$device->ip}
|
return ($readers->{$device->ip}
|
||||||
= _snmp_connect_generic('read', $device, $useclass));
|
= _snmp_connect_generic('read', $device, $useclass));
|
||||||
@@ -104,8 +107,11 @@ Returns C<undef> if the connection fails.
|
|||||||
sub writer_for {
|
sub writer_for {
|
||||||
my ($class, $ip, $useclass) = @_;
|
my ($class, $ip, $useclass) = @_;
|
||||||
my $device = get_device($ip) or return undef;
|
my $device = get_device($ip) or return undef;
|
||||||
|
return undef if $device->in_storage and $device->is_pseudo;
|
||||||
|
|
||||||
my $writers = $class->instance->writers or return undef;
|
my $writers = $class->instance->writers or return undef;
|
||||||
return $writers->{$device->ip} if exists $writers->{$device->ip};
|
return $writers->{$device->ip} if exists $writers->{$device->ip};
|
||||||
|
|
||||||
debug sprintf 'snmp writer cache warm: [%s]', $device->ip;
|
debug sprintf 'snmp writer cache warm: [%s]', $device->ip;
|
||||||
return ($writers->{$device->ip}
|
return ($writers->{$device->ip}
|
||||||
= _snmp_connect_generic('write', $device, $useclass));
|
= _snmp_connect_generic('write', $device, $useclass));
|
||||||
|
|||||||
@@ -158,6 +158,8 @@ If C<$device_type> is also given, then C<discover_no_type> will be checked.
|
|||||||
Also respects C<discover_phones> and C<discover_waps> if either are set to
|
Also respects C<discover_phones> and C<discover_waps> if either are set to
|
||||||
false.
|
false.
|
||||||
|
|
||||||
|
Also checks if the device is a pseudo device (vendor is C<netdisco>).
|
||||||
|
|
||||||
Returns false if the host is not permitted to discover the target device.
|
Returns false if the host is not permitted to discover the target device.
|
||||||
|
|
||||||
=cut
|
=cut
|
||||||
@@ -168,6 +170,9 @@ sub is_discoverable {
|
|||||||
$remote_type ||= '';
|
$remote_type ||= '';
|
||||||
$remote_cap ||= [];
|
$remote_cap ||= [];
|
||||||
|
|
||||||
|
return _bail_msg("is_discoverable: $device is pseudo-device")
|
||||||
|
if $device->is_pseudo;
|
||||||
|
|
||||||
return _bail_msg("is_discoverable: $device matches wap_platforms but discover_waps is not enabled")
|
return _bail_msg("is_discoverable: $device matches wap_platforms but discover_waps is not enabled")
|
||||||
if ((not setting('discover_waps')) and
|
if ((not setting('discover_waps')) and
|
||||||
(match_to_setting($remote_type, 'wap_platforms') or
|
(match_to_setting($remote_type, 'wap_platforms') or
|
||||||
@@ -192,9 +197,8 @@ sub is_discoverable {
|
|||||||
|
|
||||||
=head2 is_discoverable_now( $ip, $device_type? )
|
=head2 is_discoverable_now( $ip, $device_type? )
|
||||||
|
|
||||||
Same as C<is_discoverable>, but also checks the last_discover field if the
|
Same as C<is_discoverable>, but also compares the C<last_discover> field
|
||||||
device is in storage, and returns false if that host has been too recently
|
of the C<device> to the C<discover_min_age> configuration.
|
||||||
discovered.
|
|
||||||
|
|
||||||
Returns false if the host is not permitted to discover the target device.
|
Returns false if the host is not permitted to discover the target device.
|
||||||
|
|
||||||
@@ -222,6 +226,8 @@ the local configuration to arpnip the device.
|
|||||||
The configuration items C<arpnip_no> and C<arpnip_only> are checked
|
The configuration items C<arpnip_no> and C<arpnip_only> are checked
|
||||||
against the given IP.
|
against the given IP.
|
||||||
|
|
||||||
|
Also checks if the device reports layer 3 capability.
|
||||||
|
|
||||||
Returns false if the host is not permitted to arpnip the target device.
|
Returns false if the host is not permitted to arpnip the target device.
|
||||||
|
|
||||||
=cut
|
=cut
|
||||||
@@ -230,6 +236,9 @@ sub is_arpnipable {
|
|||||||
my $ip = shift;
|
my $ip = shift;
|
||||||
my $device = get_device($ip) or return 0;
|
my $device = get_device($ip) or return 0;
|
||||||
|
|
||||||
|
return _bail_msg("is_arpnipable: $device has no layer 3 capability")
|
||||||
|
unless $device->has_layer(3);
|
||||||
|
|
||||||
return _bail_msg("is_arpnipable: $device matched arpnip_no")
|
return _bail_msg("is_arpnipable: $device matched arpnip_no")
|
||||||
if check_acl_no($device, 'arpnip_no');
|
if check_acl_no($device, 'arpnip_no');
|
||||||
|
|
||||||
@@ -241,9 +250,8 @@ sub is_arpnipable {
|
|||||||
|
|
||||||
=head2 is_arpnipable_now( $ip )
|
=head2 is_arpnipable_now( $ip )
|
||||||
|
|
||||||
Same as C<is_arpnipable>, but also checks the last_arpnip field if the
|
Same as C<is_arpnipable>, but also compares the C<last_arpnip> field
|
||||||
device is in storage, and returns false if that host has been too recently
|
of the C<device> to the C<arpnip_min_age> configuration.
|
||||||
arpnipped.
|
|
||||||
|
|
||||||
Returns false if the host is not permitted to arpnip the target device.
|
Returns false if the host is not permitted to arpnip the target device.
|
||||||
|
|
||||||
@@ -271,6 +279,8 @@ the local configuration to macsuck the device.
|
|||||||
The configuration items C<macsuck_no> and C<macsuck_only> are checked
|
The configuration items C<macsuck_no> and C<macsuck_only> are checked
|
||||||
against the given IP.
|
against the given IP.
|
||||||
|
|
||||||
|
Also checks if the device reports layer 2 capability.
|
||||||
|
|
||||||
Returns false if the host is not permitted to macsuck the target device.
|
Returns false if the host is not permitted to macsuck the target device.
|
||||||
|
|
||||||
=cut
|
=cut
|
||||||
@@ -279,6 +289,9 @@ sub is_macsuckable {
|
|||||||
my $ip = shift;
|
my $ip = shift;
|
||||||
my $device = get_device($ip) or return 0;
|
my $device = get_device($ip) or return 0;
|
||||||
|
|
||||||
|
return _bail_msg("is_macsuckable: $device has no layer 2 capability")
|
||||||
|
unless $device->has_layer(2);
|
||||||
|
|
||||||
return _bail_msg("is_macsuckable: $device matched macsuck_no")
|
return _bail_msg("is_macsuckable: $device matched macsuck_no")
|
||||||
if check_acl_no($device, 'macsuck_no');
|
if check_acl_no($device, 'macsuck_no');
|
||||||
|
|
||||||
@@ -290,9 +303,8 @@ sub is_macsuckable {
|
|||||||
|
|
||||||
=head2 is_macsuckable_now( $ip )
|
=head2 is_macsuckable_now( $ip )
|
||||||
|
|
||||||
Same as C<is_macsuckable>, but also checks the last_macsuck field if the
|
Same as C<is_macsuckable>, but also compares the C<last_macsuck> field
|
||||||
device is in storage, and returns false if that host has been too recently
|
of the C<device> to the C<macsuck_min_age> configuration.
|
||||||
macsucked.
|
|
||||||
|
|
||||||
Returns false if the host is not permitted to macsuck the target device.
|
Returns false if the host is not permitted to macsuck the target device.
|
||||||
|
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ ajax '/ajax/control/admin/pseudodevice/add' => require_role admin => sub {
|
|||||||
ip => param('ip'),
|
ip => param('ip'),
|
||||||
dns => param('dns'),
|
dns => param('dns'),
|
||||||
vendor => 'netdisco',
|
vendor => 'netdisco',
|
||||||
layers => '00000100',
|
layers => param('layers'),
|
||||||
last_discover => \'now()',
|
last_discover => \'now()',
|
||||||
});
|
});
|
||||||
return unless $device;
|
return unless $device;
|
||||||
@@ -87,6 +87,9 @@ ajax '/ajax/control/admin/pseudodevice/update' => require_role admin => sub {
|
|||||||
})->delete;
|
})->delete;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# also set layers
|
||||||
|
$device->update({layers => param('layers')});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -16,9 +16,6 @@ register_worker({ phase => 'check' }, sub {
|
|||||||
return Status->error("arpnip skipped: $device not yet discovered")
|
return Status->error("arpnip skipped: $device not yet discovered")
|
||||||
unless $device->in_storage;
|
unless $device->in_storage;
|
||||||
|
|
||||||
return Status->info("arpnip skipped: $device has no layer 3 capability")
|
|
||||||
unless $device->has_layer(3);
|
|
||||||
|
|
||||||
return Status->info("arpnip skipped: $device is not arpnipable")
|
return Status->info("arpnip skipped: $device is not arpnipable")
|
||||||
unless is_arpnipable_now($device);
|
unless is_arpnipable_now($device);
|
||||||
|
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ register_worker({ phase => 'main', driver => 'snmp' }, sub {
|
|||||||
push @{ vars->{'v6arps'} },
|
push @{ vars->{'v6arps'} },
|
||||||
@{get_arps_snmp($device, $snmp->ipv6_n2p_mac, $snmp->ipv6_n2p_addr) };
|
@{get_arps_snmp($device, $snmp->ipv6_n2p_mac, $snmp->ipv6_n2p_addr) };
|
||||||
|
|
||||||
|
$device->update({layers => \[q{overlay(layers placing '1' from 6 for 1)}]});
|
||||||
return Status->done("Gathered arp caches from $device");
|
return Status->done("Gathered arp caches from $device");
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -82,24 +83,25 @@ sub get_arps_snmp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
register_worker({ phase => 'main', driver => 'cli' }, sub {
|
register_worker({ phase => 'main', driver => 'cli' }, sub {
|
||||||
my ($job, $workerconf) = @_;
|
my ($job, $workerconf) = @_;
|
||||||
|
|
||||||
my $device = $job->device;
|
my $device = $job->device;
|
||||||
my $cli = App::Netdisco::Transport::SSH->session_for($device)
|
my $cli = App::Netdisco::Transport::SSH->session_for($device)
|
||||||
or return Status->defer("arpnip failed: could not SSH connect to $device");
|
or return Status->defer("arpnip failed: could not SSH connect to $device");
|
||||||
|
|
||||||
# should be both v4 and v6
|
# should be both v4 and v6
|
||||||
my @arps = @{ get_arps_cli($device, [$cli->arpnip]) };
|
my @arps = @{ get_arps_cli($device, [$cli->arpnip]) };
|
||||||
|
|
||||||
# cache v4 arp table
|
# cache v4 arp table
|
||||||
push @{ vars->{'v4arps'} },
|
push @{ vars->{'v4arps'} },
|
||||||
grep { NetAddr::IP::Lite->new($_->{ip})->bits == 32 } @arps;
|
grep { NetAddr::IP::Lite->new($_->{ip})->bits == 32 } @arps;
|
||||||
|
|
||||||
# cache v6 neighbor cache
|
# cache v6 neighbor cache
|
||||||
push @{ vars->{'v6arps'} },
|
push @{ vars->{'v6arps'} },
|
||||||
grep { NetAddr::IP::Lite->new($_->{ip})->bits == 128 } @arps;
|
grep { NetAddr::IP::Lite->new($_->{ip})->bits == 128 } @arps;
|
||||||
|
|
||||||
return Status->done("Gathered arp caches from $device");
|
$device->update({layers => \[q{overlay(layers placing '1' from 6 for 1)}]});
|
||||||
|
return Status->done("Gathered arp caches from $device");
|
||||||
});
|
});
|
||||||
|
|
||||||
sub get_arps_cli {
|
sub get_arps_cli {
|
||||||
|
|||||||
@@ -16,9 +16,6 @@ register_worker({ phase => 'check' }, sub {
|
|||||||
return Status->error("discover failed: no device param (need -d ?)")
|
return Status->error("discover failed: no device param (need -d ?)")
|
||||||
if $device->ip eq '0.0.0.0';
|
if $device->ip eq '0.0.0.0';
|
||||||
|
|
||||||
return Status->info("discover skipped: $device is pseudo-device")
|
|
||||||
if $device->is_pseudo;
|
|
||||||
|
|
||||||
# runner has already called get_device to promote $job->device
|
# runner has already called get_device to promote $job->device
|
||||||
return $job->cancel("fresh discover cancelled: $device already known")
|
return $job->cancel("fresh discover cancelled: $device already known")
|
||||||
if $device->in_storage
|
if $device->in_storage
|
||||||
|
|||||||
@@ -16,12 +16,6 @@ register_worker({ phase => 'check' }, sub {
|
|||||||
return Status->error("macsuck skipped: $device not yet discovered")
|
return Status->error("macsuck skipped: $device not yet discovered")
|
||||||
unless $device->in_storage;
|
unless $device->in_storage;
|
||||||
|
|
||||||
return Status->info("macsuck skipped: $device is pseudo-device")
|
|
||||||
if $device->is_pseudo;
|
|
||||||
|
|
||||||
return Status->info("macsuck skipped: $device has no layer 2 capability")
|
|
||||||
unless $device->has_layer(2);
|
|
||||||
|
|
||||||
return Status->info("macsuck skipped: $device is not macsuckable")
|
return Status->info("macsuck skipped: $device is not macsuckable")
|
||||||
unless is_macsuckable_now($device);
|
unless is_macsuckable_now($device);
|
||||||
|
|
||||||
|
|||||||
@@ -245,6 +245,13 @@ td > form.nd_inline-form {
|
|||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* badge for pseudo devices layer three toggle */
|
||||||
|
.nd_layer-three-link {
|
||||||
|
text-decoration: none !important;
|
||||||
|
display: inline-block;
|
||||||
|
margin-left: -4px;
|
||||||
|
}
|
||||||
|
|
||||||
/* for the job control admin page play/pause links */
|
/* for the job control admin page play/pause links */
|
||||||
#nd_countdown-refresh:hover, #nd_countdown-control:hover {
|
#nd_countdown-refresh:hover, #nd_countdown-control:hover {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
|||||||
@@ -2,4 +2,10 @@ BEGIN;
|
|||||||
|
|
||||||
ALTER TABLE users ADD COLUMN "radius" boolean DEFAULT false;
|
ALTER TABLE users ADD COLUMN "radius" boolean DEFAULT false;
|
||||||
|
|
||||||
|
UPDATE device SET layers = NULL WHERE vendor = 'netdisco';
|
||||||
|
|
||||||
|
UPDATE device SET layers = '00000000' WHERE layers IS NULL;
|
||||||
|
|
||||||
|
ALTER TABLE device ALTER layers SET DEFAULT '00000000';
|
||||||
|
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
<th class="nd_center-cell">Device Name</th>
|
<th class="nd_center-cell">Device Name</th>
|
||||||
<th class="nd_center-cell">Device IP</th>
|
<th class="nd_center-cell">Device IP</th>
|
||||||
<th class="nd_center-cell">Number of Ports</th>
|
<th class="nd_center-cell">Number of Ports</th>
|
||||||
|
<th class="nd_center-cell">Services</th>
|
||||||
<th class="nd_center-cell">Action</th>
|
<th class="nd_center-cell">Action</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
@@ -11,7 +12,12 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td class="nd_center-cell"><input data-form="add" name="dns" type="text"></td>
|
<td class="nd_center-cell"><input data-form="add" name="dns" type="text"></td>
|
||||||
<td class="nd_center-cell"><input data-form="add" name="ip" type="text"></td>
|
<td class="nd_center-cell"><input data-form="add" name="ip" type="text"></td>
|
||||||
<td class="nd_center-cell"><input data-form="add" name="ports" type="number"></td>
|
<td class="nd_center-cell"><input data-form="add" name="ports" type="number" value="1"></td>
|
||||||
|
<td class="nd_center-cell">
|
||||||
|
<span class="badge"> </span><span class="badge"> </span>
|
||||||
|
<a class="nd_layer-three-link" href="#" rel="tooltip" data-placement="bottom" data-offset="3" data-title="Enable Arpnip"><span class="badge">3</span></a><span class="badge"> </span><span class="badge"> </span><span class="badge"> </span><span class="badge"> </span>
|
||||||
|
<input data-form="add" name="layers" type="hidden" value="00000000">
|
||||||
|
</td>
|
||||||
<td class="nd_center-cell">
|
<td class="nd_center-cell">
|
||||||
<button class="btn btn-small nd_adminbutton" name="add" type="submit"><i class="icon-plus-sign"></i> Add</button>
|
<button class="btn btn-small nd_adminbutton" name="add" type="submit"><i class="icon-plus-sign"></i> Add</button>
|
||||||
</td>
|
</td>
|
||||||
@@ -26,6 +32,11 @@
|
|||||||
<td class="nd_center-cell">
|
<td class="nd_center-cell">
|
||||||
<input data-form="update" name="ports" type="number" value="[% row.port_count | html_entity %]">
|
<input data-form="update" name="ports" type="number" value="[% row.port_count | html_entity %]">
|
||||||
</td>
|
</td>
|
||||||
|
<td class="nd_center-cell">
|
||||||
|
<span class="badge"> </span><span class="badge"> </span>
|
||||||
|
<a class="nd_layer-three-link" href="#" rel="tooltip" data-placement="bottom" data-offset="3" data-title="Enable Arpnip"><span class="badge[% ' badge-success' IF row.layers.substr(5,1) %]">3</span></a><span class="badge"> </span><span class="badge"> </span><span class="badge"> </span><span class="badge"> </span>
|
||||||
|
<input data-form="update" name="layers" type="hidden" value="[% row.layers | html_entity %]">
|
||||||
|
</td>
|
||||||
<td class="nd_center-cell">
|
<td class="nd_center-cell">
|
||||||
<input data-form="update" name="dns" type="hidden" value="[% row.dns | html_entity %]">
|
<input data-form="update" name="dns" type="hidden" value="[% row.dns | html_entity %]">
|
||||||
<input data-form="update" name="ip" type="hidden" value="[% row.ip | html_entity %]">
|
<input data-form="update" name="ip" type="hidden" value="[% row.ip | html_entity %]">
|
||||||
@@ -68,6 +79,17 @@ $(document).ready(function() {
|
|||||||
} ],
|
} ],
|
||||||
[% INCLUDE 'ajax/datatabledefaults.tt' -%]
|
[% INCLUDE 'ajax/datatabledefaults.tt' -%]
|
||||||
} );
|
} );
|
||||||
|
$('.nd_layer-three-link').click(function() {
|
||||||
|
var badge = $(this).children('span').first();
|
||||||
|
var layers = $(this).parent().children('input').first();
|
||||||
|
$(badge).toggleClass('badge-success');
|
||||||
|
if ($(badge).hasClass('badge-success')) {
|
||||||
|
$(layers).attr('value', '00000100');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$(layers).attr('value', '00000000');
|
||||||
|
}
|
||||||
|
});
|
||||||
} );
|
} );
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
<td class="nd_center-cell"></td>
|
<td class="nd_center-cell"></td>
|
||||||
<td class="nd_center-cell"></td>
|
<td class="nd_center-cell"></td>
|
||||||
<td class="nd_center-cell"><input class="span2" data-form="add" name="note" type="text"></td>
|
<td class="nd_center-cell"><input class="span2" data-form="add" name="note" type="text"></td>
|
||||||
<td class="nd_center-cell">
|
<td nowrap class="nd_center-cell">
|
||||||
<button class="btn btn-small nd_adminbutton" name="add" type="submit"><i class="icon-plus-sign"></i> Add</button>
|
<button class="btn btn-small nd_adminbutton" name="add" type="submit"><i class="icon-plus-sign"></i> Add</button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -62,7 +62,7 @@
|
|||||||
<input class="span2" data-form="update" name="note" type="text" value="[% row.note | html_entity %]">
|
<input class="span2" data-form="update" name="note" type="text" value="[% row.note | html_entity %]">
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td class="nd_center-cell">
|
<td nowrap class="nd_center-cell">
|
||||||
<button class="btn nd_adminbutton" name="update" type="submit"><i class="icon-save text-warning"></i></button>
|
<button class="btn nd_adminbutton" name="update" type="submit"><i class="icon-save text-warning"></i></button>
|
||||||
|
|
||||||
<button class="btn" data-toggle="modal"
|
<button class="btn" data-toggle="modal"
|
||||||
|
|||||||
@@ -71,8 +71,9 @@
|
|||||||
,minLength: 0
|
,minLength: 0
|
||||||
});
|
});
|
||||||
|
|
||||||
// activate modals
|
// activate modals and tooltips
|
||||||
$('.nd_modal').modal({show: false});
|
$('.nd_modal').modal({show: false});
|
||||||
|
$("[rel=tooltip]").tooltip({live: true});
|
||||||
}
|
}
|
||||||
|
|
||||||
// on load, establish global delegations for now and future
|
// on load, establish global delegations for now and future
|
||||||
|
|||||||
Reference in New Issue
Block a user