diff --git a/app/Http/Controllers/Maps/CustomMapController.php b/app/Http/Controllers/Maps/CustomMapController.php index 80ef1aee40..3ec37af651 100644 --- a/app/Http/Controllers/Maps/CustomMapController.php +++ b/app/Http/Controllers/Maps/CustomMapController.php @@ -47,6 +47,7 @@ class CustomMapController extends Controller return view('map.custom-manage', [ 'maps' => CustomMap::orderBy('name')->get(['custom_map_id', 'name']), 'name' => 'New Map', + 'menu_group' => null, 'node_align' => 10, 'edge_separation' => 10, 'reverse_arrows' => 0, @@ -101,6 +102,7 @@ class CustomMapController extends Controller 'edit' => false, 'map_id' => $map->custom_map_id, 'name' => $map->name, + 'menu_group' => $map->menu_group, 'reverse_arrows' => $map->reverse_arrows, 'legend' => $this->legendConfig($map), 'background' => (bool) $map->background_suffix, @@ -123,6 +125,7 @@ class CustomMapController extends Controller $data = [ 'map_id' => $map->custom_map_id, 'name' => $map->name, + 'menu_group' => $map->menu_group, 'node_align' => $map->node_align, 'edge_separation' => $map->edge_separation, 'reverse_arrows' => $map->reverse_arrows, @@ -163,6 +166,7 @@ class CustomMapController extends Controller return response()->json([ 'id' => $map->custom_map_id, 'name' => $map->name, + 'menu_group' => $map->menu_group, 'width' => $map->width, 'height' => $map->height, 'reverse_arrows' => $map->reverse_arrows, diff --git a/app/Http/Controllers/Select/CustomMapMenuGroupController.php b/app/Http/Controllers/Select/CustomMapMenuGroupController.php new file mode 100644 index 0000000000..89845f696d --- /dev/null +++ b/app/Http/Controllers/Select/CustomMapMenuGroupController.php @@ -0,0 +1,44 @@ +. + * + * @package LibreNMS + * @link http://librenms.org + * @copyright 2024 Tony Murray + * @author Tony Murray + */ + +namespace App\Http\Controllers\Select; + +use App\Models\CustomMap; +use Illuminate\Database\Eloquent\Builder; +use Illuminate\Http\Request; + +class CustomMapMenuGroupController extends SelectController +{ + protected function searchFields($request): array + { + return ['menu_group']; + } + + protected function baseQuery(Request $request): Builder + { + return CustomMap::query()->hasAccess($request->user()) + ->whereNotNull('menu_group')->select('menu_group')->groupBy('menu_group'); + } +} diff --git a/app/Http/Controllers/Select/DashboardController.php b/app/Http/Controllers/Select/DashboardController.php index 213caa586f..e46e719ee9 100644 --- a/app/Http/Controllers/Select/DashboardController.php +++ b/app/Http/Controllers/Select/DashboardController.php @@ -62,19 +62,18 @@ class DashboardController extends SelectController ]; } - public function formatResponse($paginator) + protected function prependItem(): array { - if (! request()->has('term')) { - $paginator->prepend((object) ['dashboard_id' => 0]); - } - - return parent::formatResponse($paginator); + return [ + 'id' => 0, + 'text' => __('No Default Dashboard'), + ]; } private function describe($dashboard): string { if ($dashboard->dashboard_id == 0) { - return 'No Default Dashboard'; + return $this->prependItem()['text']; } return "{$dashboard->username}: {$dashboard->dashboard_name} (" diff --git a/app/Http/Controllers/Select/PollerGroupController.php b/app/Http/Controllers/Select/PollerGroupController.php index 337b9739bf..ed2e66e841 100644 --- a/app/Http/Controllers/Select/PollerGroupController.php +++ b/app/Http/Controllers/Select/PollerGroupController.php @@ -39,16 +39,11 @@ class PollerGroupController extends SelectController return PollerGroup::query()->select(['id', 'group_name']); } - protected function formatResponse($paginator) + protected function prependItem(): array { - // prepend the default group, unless filtered out - if ($this->includeGeneral()) { - $general = new PollerGroup; - $general->id = 0; - $general->group_name = 'General'; - $paginator->prepend($general); - } - - return parent::formatResponse($paginator); + return [ + 'id' => 0, + 'text' => __('General'), + ]; } } diff --git a/app/Http/Controllers/Select/SelectController.php b/app/Http/Controllers/Select/SelectController.php index 4645cd57ab..033ffd936a 100644 --- a/app/Http/Controllers/Select/SelectController.php +++ b/app/Http/Controllers/Select/SelectController.php @@ -32,7 +32,6 @@ use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Query\Builder; use Illuminate\Http\Request; use Illuminate\Support\Collection; -use Illuminate\Support\Str; abstract class SelectController extends PaginatedAjaxController { @@ -78,8 +77,15 @@ abstract class SelectController extends PaginatedAjaxController */ protected function formatResponse($paginator) { + $results = collect($paginator->items())->map([$this, 'formatItem']); + + // prepend the initial item, unless filtered out + if ($this->canPrependFirstItem(request())) { + $results->prepend($this->prependItem()); + } + return response()->json([ - 'results' => collect($paginator->items())->map([$this, 'formatItem']), + 'results' => $results, 'pagination' => ['more' => $paginator->hasMorePages()], ]); } @@ -111,11 +117,28 @@ abstract class SelectController extends PaginatedAjaxController ]; } - protected function includeGeneral(): bool + protected function prependItem(): ?array { - if (request()->has('id') && request('id') !== 0) { + return null; + } + + protected function canPrependFirstItem(Request $request): bool + { + $item = $this->prependItem(); + + if (empty($item)) { return false; - } elseif (request()->has('term') && ! Str::contains('general', strtolower(request('term')))) { + } + + if ($request->page > 1) { + return false; + } + + if ($request->has('id') && $request->id != $item['id']) { // purposely loose comparison + return false; + } + + if ($request->has('term') && ! str_contains(strtolower($item['text']), strtolower($request->term))) { return false; } diff --git a/app/Http/Requests/CustomMapSettingsRequest.php b/app/Http/Requests/CustomMapSettingsRequest.php index fbc535fa10..b987c866b8 100644 --- a/app/Http/Requests/CustomMapSettingsRequest.php +++ b/app/Http/Requests/CustomMapSettingsRequest.php @@ -23,7 +23,8 @@ class CustomMapSettingsRequest extends FormRequest public function rules(): array { return [ - 'name' => 'required|string', + 'name' => 'required|string|max:100', + 'menu_group' => 'nullable|string|max:100', 'node_align' => 'integer', 'reverse_arrows' => 'boolean', 'edge_separation' => 'integer', diff --git a/app/Http/ViewComposers/MenuComposer.php b/app/Http/ViewComposers/MenuComposer.php index 60bdbd09a6..f640c31744 100644 --- a/app/Http/ViewComposers/MenuComposer.php +++ b/app/Http/ViewComposers/MenuComposer.php @@ -78,12 +78,6 @@ class MenuComposer //Dashboards $vars['dashboards'] = Dashboard::select('dashboard_id', 'dashboard_name')->allAvailable($user)->orderBy('dashboard_name')->get(); - //Maps - $vars['links'] = Link::exists(); - $vars['device_dependencies'] = \DB::table('device_relationships')->exists(); - $vars['device_group_dependencies'] = \DB::table('device_group_device')->exists(); - $vars['custommaps'] = CustomMap::select('custom_map_id', 'name')->hasAccess($user)->orderBy('name')->get(); - // Device menu $vars['device_groups'] = DeviceGroup::hasAccess($user)->orderBy('name')->get(['device_groups.id', 'name', 'desc']); $vars['package_count'] = Package::hasAccess($user)->count(); @@ -95,6 +89,12 @@ class MenuComposer new Collection(); $vars['show_vmwinfo'] = Vminfo::hasAccess($user)->exists(); + //Maps + $vars['links'] = Link::exists(); + $vars['device_dependencies'] = \DB::table('device_relationships')->exists(); + $vars['device_group_dependencies'] = $vars['device_groups']->isNotEmpty() && \DB::table('device_group_device')->exists(); + $vars['custommaps'] = CustomMap::select(['custom_map_id', 'name', 'menu_group'])->hasAccess($user)->orderBy('name')->get()->groupBy('menu_group')->sortKeys(); + // Service menu if (Config::get('show_services')) { $vars['service_counts'] = ObjectCache::serviceCounts(['warning', 'critical']); diff --git a/app/Models/CustomMap.php b/app/Models/CustomMap.php index f08f9075f7..3e5ebf5927 100644 --- a/app/Models/CustomMap.php +++ b/app/Models/CustomMap.php @@ -41,6 +41,7 @@ class CustomMap extends BaseModel ]; protected $fillable = [ 'name', + 'menu_group', 'width', 'height', 'node_align', diff --git a/database/migrations/2024_04_22_161711_custom_maps_add_group.php b/database/migrations/2024_04_22_161711_custom_maps_add_group.php new file mode 100644 index 0000000000..a06102fcfb --- /dev/null +++ b/database/migrations/2024_04_22_161711_custom_maps_add_group.php @@ -0,0 +1,28 @@ +string('menu_group', 100)->nullable(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('custom_maps', function (Blueprint $table) { + $table->dropColumn('menu_group'); + }); + } +}; diff --git a/html/js/librenms.js b/html/js/librenms.js index ecbe1b892c..66f6fb2d91 100644 --- a/html/js/librenms.js +++ b/html/js/librenms.js @@ -467,7 +467,6 @@ function init_select2(selector, type, data, selected, placeholder, config) { $select.select2(init); if (selected) { - console.log(selected); if (typeof selected !== 'object') { selected = {id: selected, text: selected}; } diff --git a/lang/en/map.php b/lang/en/map.php index 3a57a2c98f..e8e993ff87 100644 --- a/lang/en/map.php +++ b/lang/en/map.php @@ -33,6 +33,8 @@ return [ 'map' => [ 'settings_title' => 'Map Settings', 'name' => 'Name', + 'menu_group' => 'Menu Group', + 'no_group' => 'No Group', 'width' => 'Width', 'height' => 'Height', 'alignment' => 'Node Alignment', diff --git a/misc/db_schema.yaml b/misc/db_schema.yaml index e656fc9556..e414026c07 100644 --- a/misc/db_schema.yaml +++ b/misc/db_schema.yaml @@ -537,6 +537,7 @@ custom_maps: - { Field: newedgeconfig, Type: longtext, 'Null': false, Extra: '' } - { Field: created_at, Type: timestamp, 'Null': true, Extra: '' } - { Field: updated_at, Type: timestamp, 'Null': true, Extra: '' } + - { Field: menu_group, Type: varchar(100), 'Null': true, Extra: '' } Indexes: PRIMARY: { Name: PRIMARY, Columns: [custom_map_id], Unique: true, Type: BTREE } custom_map_backgrounds: diff --git a/resources/views/layouts/menu.blade.php b/resources/views/layouts/menu.blade.php index 4ad809c1b0..4db7f27c97 100644 --- a/resources/views/layouts/menu.blade.php +++ b/resources/views/layouts/menu.blade.php @@ -41,67 +41,6 @@ - @if(auth()->user()->isAdmin() || $has_v1_plugins || $has_v2_plugins) @endadmin + + +{{-- Maps --}} + {{-- Services --}} diff --git a/resources/views/map/custom-map-modal.blade.php b/resources/views/map/custom-map-modal.blade.php index 158e7b5257..5bb7dd8078 100644 --- a/resources/views/map/custom-map-modal.blade.php +++ b/resources/views/map/custom-map-modal.blade.php @@ -1,4 +1,4 @@ -