Skip to content

Commit 2ebee3c

Browse files
authored
Filter handle empty and not empty better (librenms#19756)
* Filter handle empty and not empty better select filters allow none/any pass value = 1 so the url is correctly updated handle relationship empty/not empty filters more correctly * Additional tests
1 parent 5a789d1 commit 2ebee3c

6 files changed

Lines changed: 41 additions & 6 deletions

File tree

app/Models/Traits/Filterable.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,14 @@ protected function applyRelationFilter(Builder $query, string $field, mixed $val
178178

179179
$not = $config['not'] ?? false;
180180

181+
if ($config['null'] ?? false) {
182+
$not
183+
? ($boolean === 'or' ? $query->orWhereHas($relation) : $query->whereHas($relation))
184+
: ($boolean === 'or' ? $query->orWhereDoesntHave($relation) : $query->whereDoesntHave($relation));
185+
186+
return;
187+
}
188+
181189
// Callback to apply the logic inside the relationship scope
182190
$callback = function (Builder $q) use ($column, $value, $config): void {
183191
// When negating a relation (whereDoesntHave), we must use "positive" internal logic
Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

html/build/manifest.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,12 @@
2020
"src": "html/fonts/glyphicons-halflings-regular.woff2"
2121
},
2222
"resources/js/app.js": {
23-
"file": "assets/app-cKVbOGPL.js",
23+
"file": "assets/app-BGqBXSzO.js",
2424
"name": "app",
2525
"src": "resources/js/app.js",
2626
"isEntry": true,
2727
"css": [
28-
"assets/app-FZ2QWJRi.css"
28+
"assets/app-CTohBva2.css"
2929
],
3030
"assets": [
3131
"assets/glyphicons-halflings-regular-BUJKDMgK.eot",

resources/js/components/alpine/filterBarComponent.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ export default function filterBarComponent({
4646
{ v: "neq", s: "≠", l: "Is Not" },
4747
{ v: "in", s: "∈", l: "Is Any Of" },
4848
{ v: "not_in", s: "∉", l: "Is Not Any Of" },
49+
{ v: "is_empty", s: "∅", l: "None" },
50+
{ v: "is_not_empty", s: "∃", l: "Any" },
4951
],
5052
},
5153

@@ -345,8 +347,7 @@ export default function filterBarComponent({
345347

346348
this.current = field;
347349
this.op = existing?.op || this.ops()[0].v;
348-
this.value =
349-
existing?.value ?? (this.isMulti() ? [] : "");
350+
this.value = existing?.value ?? (this.isMulti() ? [] : "");
350351
this.display = existing?.display ?? this.value;
351352

352353
this.snapshot = {

tests/Unit/Models/Traits/FilterableTest.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,32 @@ public function test_relation_neq_includes_records_with_no_relation(): void
393393
$this->assertContains('orphan-gw', $hostnames);
394394
}
395395

396+
public function test_relation_is_empty_finds_records_without_relationship(): void
397+
{
398+
$this->device(['hostname' => 'connected-gw'], 'London');
399+
$this->device(['hostname' => 'unassigned-gw', 'location_id' => null]);
400+
401+
$results = FilterableDevice::applyFilters([
402+
'location.location' => ['is_empty' => '1'],
403+
])->get();
404+
405+
$this->assertCount(1, $results);
406+
$this->assertEquals('unassigned-gw', $results->first()->hostname);
407+
}
408+
409+
public function test_relation_is_not_empty_finds_records_with_relationship(): void
410+
{
411+
$this->device(['hostname' => 'connected-gw'], 'Paris');
412+
$this->device(['hostname' => 'unassigned-gw', 'location_id' => null]);
413+
414+
$results = FilterableDevice::applyFilters([
415+
'location.location' => ['is_not_empty' => '1'],
416+
])->get();
417+
418+
$this->assertCount(1, $results);
419+
$this->assertEquals('connected-gw', $results->first()->hostname);
420+
}
421+
396422
// -------------------------------------------------------------------------
397423
// applyFilterSearch helper
398424
// -------------------------------------------------------------------------

0 commit comments

Comments
 (0)