Skip to content

Commit 6f4a335

Browse files
murrantStyleCIBot
andauthored
Replace legacy ossuggest Ajax call with select2 (librenms#18451)
* Replace OS suggest Use select2 instead of typeahead * Include prefix matching for better results * Style * Apply fixes from StyleCI --------- Co-authored-by: StyleCI Bot <[email protected]>
1 parent 00f729c commit 6f4a335

File tree

5 files changed

+65
-159
lines changed

5 files changed

+65
-159
lines changed
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<?php
2+
3+
namespace App\Http\Controllers\Select;
4+
5+
use App\Facades\LibrenmsConfig;
6+
use Illuminate\Http\JsonResponse;
7+
use Illuminate\Http\Request;
8+
9+
class OsController
10+
{
11+
public function __invoke(Request $request): JsonResponse
12+
{
13+
$request->validate([
14+
'limit' => 'int',
15+
'page' => 'int',
16+
'term' => 'nullable|string',
17+
]);
18+
19+
$results = array_map(
20+
fn ($os) => ['id' => $os['os'], 'text' => $os['text']],
21+
LibrenmsConfig::get('os', [])
22+
);
23+
24+
if ($term = $request->string('term')->trim()->value()) {
25+
$results = $this->sortAndFilterBySimilarity($term, $results);
26+
}
27+
28+
return response()->json([
29+
'results' => array_values($results),
30+
'pagination' => ['more' => false],
31+
]);
32+
}
33+
34+
private function sortAndFilterBySimilarity(string $term, array $items): array
35+
{
36+
$term = strtolower($term);
37+
38+
$scored = array_map(function ($item) use ($term) {
39+
$id = strtolower($item['id']);
40+
$text = strtolower($item['text']);
41+
42+
return [
43+
'item' => $item,
44+
'hasPrefix' => str_starts_with($id, $term) || str_starts_with($text, $term),
45+
'distance' => min(
46+
levenshtein($term, $id, 1, 10, 10),
47+
levenshtein($term, $text, 1, 10, 10)
48+
),
49+
];
50+
}, $items);
51+
52+
usort($scored, fn ($a, $b) => ($b['hasPrefix'] <=> $a['hasPrefix'])
53+
?: ($a['distance'] <=> $b['distance']));
54+
55+
return array_column($scored, 'item');
56+
}
57+
}

html/ajax_ossuggest.php

Lines changed: 0 additions & 73 deletions
This file was deleted.

includes/html/pages/addhost.inc.php

Lines changed: 3 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
$additional = [];
4343
if (! $snmp_enabled) {
4444
$new_device->snmp_disable = 1;
45-
$new_device->os = $_POST['os'] ? strip_tags($_POST['os_id']) : 'ping';
45+
$new_device->os = $_POST['os'] ? strip_tags($_POST['os']) : 'ping';
4646
$new_device->hardware = strip_tags($_POST['hardware']);
4747
$new_device->sysName = strip_tags($_POST['sysName']);
4848
} elseif ($_POST['snmpver'] === 'v2c' || $_POST['snmpver'] === 'v1') {
@@ -137,8 +137,7 @@
137137
<div class='form-group'>
138138
<label for='os' class='col-sm-3 control-label'>OS (optional)</label>
139139
<div class='col-sm-9'>
140-
<input id='os' class='form-control' name='os' placeholder="OS (optional)"/>
141-
<input type='hidden' id='os_id' class='form-control' name='os_id' />
140+
<select id='os' class='form-control' name='os' placeholder="OS (optional)"></select>
142141
</div>
143142
</div>
144143
</div>
@@ -329,46 +328,7 @@ function disableSnmp(e) {
329328
}
330329
}
331330

332-
var os_suggestions = new Bloodhound({
333-
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('text'),
334-
queryTokenizer: Bloodhound.tokenizers.whitespace,
335-
remote: {
336-
url: "ajax_ossuggest.php?term=%QUERY",
337-
filter: function (output) {
338-
return $.map(output, function (item) {
339-
return {
340-
text: item.text,
341-
os: item.os,
342-
};
343-
});
344-
},
345-
wildcard: "%QUERY"
346-
}
347-
});
348-
os_suggestions.initialize();
349-
$('#os').typeahead({
350-
hint: true,
351-
highlight: true,
352-
minLength: 1,
353-
classNames: {
354-
menu: 'typeahead-left'
355-
}
356-
},
357-
{
358-
source: os_suggestions.ttAdapter(),
359-
async: true,
360-
displayKey: 'text',
361-
valueKey: 'os',
362-
templates: {
363-
suggestion: Handlebars.compile('<p>&nbsp;{{text}}</p>')
364-
},
365-
limit: 20
366-
});
367-
368-
$("#os").on("typeahead:selected typeahead:autocompleted", function(e,datum) {
369-
$("#os_id").val(datum.os);
370-
$("#os").html('<mark>' + datum.text + '</mark>');
371-
});
331+
init_select2('#os', 'os', {}, null, 'OS (optional)');
372332

373333
$("[name='snmp']").bootstrapSwitch('offColor','danger');
374334
$("[name='force_add']").bootstrapSwitch();

includes/html/pages/device/edit/snmp.inc.php

Lines changed: 4 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
$device->features = null;
4040
$device->hardware = $_POST['hardware'];
4141
$device->icon = null;
42-
$device->os = $_POST['os'] ? strip_tags($_POST['os_id']) : 'ping';
42+
$device->os = $_POST['os'] ? strip_tags($_POST['os']) : 'ping';
4343
$device->snmp_disable = 1;
4444
$device->sysName = $_POST['sysName'] ?: null;
4545
$device->version = null;
@@ -209,8 +209,7 @@
209209
<div class='form-group'>
210210
<label for='os' class='col-sm-2 control-label'>OS (optional)</label>
211211
<div class='col-sm-4'>
212-
<input id='os' class='form-control' name='os' value='" . htmlspecialchars(LibrenmsConfig::get("os.{$device->os}.text")) . "'/>
213-
<input type='hidden' id='os_id' class='form-control' name='os_id' value='" . htmlspecialchars($device->os) . "'/>
212+
<select id='os' class='form-control' name='os'></select>
214213
</div>
215214
</div>
216215
</div>
@@ -427,46 +426,8 @@ function disableSnmp(e) {
427426
}
428427
}
429428

430-
var os_suggestions = new Bloodhound({
431-
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('text'),
432-
queryTokenizer: Bloodhound.tokenizers.whitespace,
433-
remote: {
434-
url: "ajax_ossuggest.php?term=%QUERY",
435-
filter: function (output) {
436-
return $.map(output, function (item) {
437-
return {
438-
text: item.text,
439-
os: item.os,
440-
};
441-
});
442-
},
443-
wildcard: "%QUERY"
444-
}
445-
});
446-
os_suggestions.initialize();
447-
$('#os').typeahead({
448-
hint: true,
449-
highlight: true,
450-
minLength: 1,
451-
classNames: {
452-
menu: 'typeahead-left'
453-
}
454-
},
455-
{
456-
source: os_suggestions.ttAdapter(),
457-
async: true,
458-
displayKey: 'text',
459-
valueKey: 'os',
460-
templates: {
461-
suggestion: Handlebars.compile('<p>&nbsp;{{text}}</p>')
462-
},
463-
limit: 20
464-
});
465-
466-
$("#os").on("typeahead:selected typeahead:autocompleted", function(e,datum) {
467-
$("#os_id").val(datum.os);
468-
$("#os").html('<mark>' + datum.text + '</mark>');
469-
});
429+
var current_os = <?php echo json_encode(['id' => $device->os, 'text' => LibrenmsConfig::get("os.{$device->os}.text")], JSON_HEX_QUOT|JSON_HEX_TAG|JSON_HEX_AMP|JSON_HEX_APOS) ?>;
430+
init_select2('#os', 'os', {}, current_os, 'OS (optional)');
470431

471432
$("[name='snmp']").bootstrapSwitch('offColor','danger');
472433

routes/web.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,7 @@
273273
Route::get('syslog', Select\SyslogController::class)->name('ajax.select.syslog');
274274
Route::get('location', Select\LocationController::class)->name('ajax.select.location');
275275
Route::get('munin', Select\MuninPluginController::class)->name('ajax.select.munin');
276+
Route::get('os', Select\OsController::class)->name('ajax.select.os');
276277
Route::get('role', Select\RoleController::class)->name('ajax.select.role');
277278
Route::get('service', Select\ServiceController::class)->name('ajax.select.service');
278279
Route::get('customoid', Select\CustomoidController::class)->name('ajax.select.customoid');

0 commit comments

Comments
 (0)