Partial search on Device Port MAC address

Implement sql_match helper func for wildcard translation.
This commit is contained in:
Oliver Gorwits
2014-03-02 19:09:31 +00:00
parent 16643045ce
commit 80ffbd5963
5 changed files with 56 additions and 9 deletions

View File

@@ -1,3 +1,9 @@
2.024003_001 - 2014-03-02
[ENHANCEMENTS]
* Partial search on Device Port MAC address
2.024003 - 2014-02-27 2.024003 - 2014-02-27
[BUG FIXES] [BUG FIXES]

View File

@@ -8,7 +8,7 @@ use Time::Piece;
use Time::Seconds; use Time::Seconds;
our @EXPORT = (); our @EXPORT = ();
our @EXPORT_OK = qw/ our @EXPORT_OK = qw/
sort_port sort_modules interval_to_daterange sort_port sort_modules interval_to_daterange sql_match
/; /;
our %EXPORT_TAGS = (all => \@EXPORT_OK); our %EXPORT_TAGS = (all => \@EXPORT_OK);
@@ -25,6 +25,35 @@ subroutines.
=head1 EXPORT_OK =head1 EXPORT_OK
=head2 sql_match( $value, $exact? )
Convert wildcard characters "C<*>" and "C<?>" to "C<%>" and "C<_>"
respectively.
Pass a true value to C<$exact> to only substitute the existing wildcards, and
not also add "C<*>" to each end of the value.
In list context, returns two values, the translated value, and also an
L<SQL::Abstract> LIKE clause.
=cut
sub sql_match {
my ($text, $exact) = @_;
return unless $text;
$text =~ s/^\s+//;
$text =~ s/\s+$//;
$text =~ s/[*]+/%/g;
$text =~ s/[?]/_/g;
$text = '%'. $text . '%' unless $exact;
$text =~ s/\%+/%/g;
return ( wantarray ? ($text, {-ilike => $text}) : $text );
}
=head2 sort_port( $a, $b ) =head2 sort_port( $a, $b )
Sort port names of various types used by device vendors. Interface is as Sort port names of various types used by device vendors. Interface is as

View File

@@ -5,6 +5,7 @@ use Dancer::Plugin::DBIC;
use Dancer::Plugin::Auth::Extensible; use Dancer::Plugin::Auth::Extensible;
use App::Netdisco::Web::Plugin; use App::Netdisco::Web::Plugin;
use App::Netdisco::Util::Web 'sql_match';
register_search_tab({ tag => 'port', label => 'Port', provides_csv => 1 }); register_search_tab({ tag => 'port', label => 'Port', provides_csv => 1 });
@@ -19,13 +20,14 @@ get '/ajax/content/search/port' => require_login sub {
->search({vlan => $q}); ->search({vlan => $q});
} }
else { else {
my $query = $q; my ($likeval, $likeclause) = sql_match($q);
if (param('partial')) {
$q = "\%$q\%" if $q !~ m/%/;
$query = { -ilike => $q };
}
$set = schema('netdisco')->resultset('DevicePort') $set = schema('netdisco')->resultset('DevicePort')
->search({name => $query}); ->search({-or => [
{name => (param('partial') ? $likeclause : $q)},
(length $q == 17 ? {mac => $q}
: \['mac::text ILIKE ?', $likeval]),
]});
} }
return unless $set->count; return unless $set->count;

View File

@@ -5,6 +5,8 @@ use Dancer::Plugin::Ajax;
use Dancer::Plugin::DBIC; use Dancer::Plugin::DBIC;
use Dancer::Plugin::Auth::Extensible; use Dancer::Plugin::Auth::Extensible;
use App::Netdisco::Util::Web 'sql_match';
hook 'before' => sub { hook 'before' => sub {
# view settings for node options # view settings for node options
var('node_options' => [ var('node_options' => [
@@ -75,6 +77,7 @@ get '/search' => require_login sub {
} }
else { else {
my $nd = $s->resultset('Device')->search_fuzzy($q); my $nd = $s->resultset('Device')->search_fuzzy($q);
my ($likeval, $likeclause) = sql_match($q);
if ($nd and $nd->count) { if ($nd and $nd->count) {
if ($nd->count == 1) { if ($nd->count == 1) {
@@ -90,7 +93,14 @@ get '/search' => require_login sub {
params->{'tab'} = 'device'; params->{'tab'} = 'device';
} }
elsif ($s->resultset('DevicePort') elsif ($s->resultset('DevicePort')
->search({name => "\%$q\%"})->count) { ->search({
-or => [
{name => $likeclause},
(length $q == 17 ? {mac => $q}
: \['mac::text ILIKE ?', $likeval]),
],
})->count) {
params->{'tab'} = 'port'; params->{'tab'} = 'port';
} }
} }

View File

@@ -7,7 +7,7 @@
name="partial"[% ' checked="checked"' IF params.partial %]/> name="partial"[% ' checked="checked"' IF params.partial %]/>
</label> </label>
<label class="nd_checkboxlabel" for="port_partial"> <label class="nd_checkboxlabel" for="port_partial">
<span class="nd_searchcheckbox uneditable-input">Partial Name</span> <span class="nd_searchcheckbox uneditable-input">Partial Match</span>
</label> </label>
</div> </div>
<button id="[% tab.tag %]_submit" type="submit" class="btn btn-info"> <button id="[% tab.tag %]_submit" type="submit" class="btn btn-info">