feat(global-search): add navigation routes and enhance search functionality

- Introduced a comprehensive set of navigation routes for quick access to key sections such as Dashboard, Servers, Projects, and more.
- Enhanced the search functionality to include a 'new' prefix for creating resources directly from the search input.
- Improved UI elements for search results, ensuring better visibility and interaction.
This commit is contained in:
Andras Bacsai 2025-10-08 19:50:30 +02:00
parent 640f753aae
commit c548013e2d
2 changed files with 156 additions and 9 deletions

View file

@ -585,8 +585,136 @@ private function loadSearchableItems()
];
});
// Add navigation routes
$navigation = collect([
[
'name' => 'Dashboard',
'type' => 'navigation',
'description' => 'Go to main dashboard',
'link' => route('dashboard'),
'search_text' => 'dashboard home main overview',
],
[
'name' => 'Servers',
'type' => 'navigation',
'description' => 'View all servers',
'link' => route('server.index'),
'search_text' => 'servers all list view',
],
[
'name' => 'Projects',
'type' => 'navigation',
'description' => 'View all projects',
'link' => route('project.index'),
'search_text' => 'projects all list view',
],
[
'name' => 'Destinations',
'type' => 'navigation',
'description' => 'View all destinations',
'link' => route('destination.index'),
'search_text' => 'destinations docker networks',
],
[
'name' => 'Security',
'type' => 'navigation',
'description' => 'Manage private keys and API tokens',
'link' => route('security.private-key.index'),
'search_text' => 'security private keys ssh api tokens',
],
[
'name' => 'Sources',
'type' => 'navigation',
'description' => 'Manage GitHub apps and Git sources',
'link' => route('source.all'),
'search_text' => 'sources github apps git repositories',
],
[
'name' => 'Storages',
'type' => 'navigation',
'description' => 'Manage S3 storage for backups',
'link' => route('storage.index'),
'search_text' => 'storages s3 backups',
],
[
'name' => 'Shared Variables',
'type' => 'navigation',
'description' => 'View all shared variables',
'link' => route('shared-variables.index'),
'search_text' => 'shared variables environment all',
],
[
'name' => 'Team Shared Variables',
'type' => 'navigation',
'description' => 'Manage team-wide shared variables',
'link' => route('shared-variables.team.index'),
'search_text' => 'shared variables team environment',
],
[
'name' => 'Project Shared Variables',
'type' => 'navigation',
'description' => 'Manage project shared variables',
'link' => route('shared-variables.project.index'),
'search_text' => 'shared variables project environment',
],
[
'name' => 'Environment Shared Variables',
'type' => 'navigation',
'description' => 'Manage environment shared variables',
'link' => route('shared-variables.environment.index'),
'search_text' => 'shared variables environment',
],
[
'name' => 'Tags',
'type' => 'navigation',
'description' => 'View resources by tags',
'link' => route('tags.show'),
'search_text' => 'tags labels organize',
],
[
'name' => 'Terminal',
'type' => 'navigation',
'description' => 'Access server terminal',
'link' => route('terminal'),
'search_text' => 'terminal ssh console shell command line',
],
[
'name' => 'Profile',
'type' => 'navigation',
'description' => 'Manage your profile and preferences',
'link' => route('profile'),
'search_text' => 'profile account user settings preferences',
],
[
'name' => 'Team',
'type' => 'navigation',
'description' => 'Manage team members and settings',
'link' => route('team.index'),
'search_text' => 'team settings members users invitations',
],
[
'name' => 'Notifications',
'type' => 'navigation',
'description' => 'Configure email, Discord, Telegram notifications',
'link' => route('notifications.email'),
'search_text' => 'notifications alerts email discord telegram slack pushover',
],
]);
// Add instance settings only for self-hosted and root team
if (! isCloud() && $team->id === 0) {
$navigation->push([
'name' => 'Settings',
'type' => 'navigation',
'description' => 'Instance settings and configuration',
'link' => route('settings.index'),
'search_text' => 'settings configuration instance',
]);
}
// Merge all collections
$items = $items->merge($applications)
$items = $items->merge($navigation)
->merge($applications)
->merge($services)
->merge($databases)
->merge($servers)

View file

@ -36,6 +36,12 @@
return this.creatableItems.filter(item => {
const searchText = `${item.name} ${item.description} ${item.type} ${item.category}`.toLowerCase();
if (query.startsWith('new ')) {
const queryWithoutNew = query.substring(4);
return searchText.includes(queryWithoutNew) || searchText.includes(query);
}
return searchText.includes(query);
});
},
@ -339,8 +345,8 @@ class="flex items-center gap-3 p-3 bg-neutral-50 dark:bg-coolgray-200 rounded-lg
@foreach ($availableServers as $index => $server)
<button type="button"
wire:click="selectServer({{ $server['id'] }}, true)"
class="search-result-item w-full text-left block px-4 py-3 hover:bg-yellow-50 dark:hover:bg-yellow-900/20 transition-colors focus:outline-none focus:bg-yellow-100 dark:focus:bg-yellow-900/30">
<div class="flex items-center justify-between gap-3">
class="search-result-item w-full text-left block px-4 py-3 min-h-[4rem] hover:bg-yellow-50 dark:hover:bg-yellow-900/20 transition-colors focus:outline-none focus:bg-yellow-100 dark:focus:bg-yellow-900/30 border-b border-neutral-100 dark:border-coolgray-300 last:border-0">
<div class="flex items-center justify-between gap-3 min-h-[2.5rem]">
<div class="flex-1 min-w-0">
<div class="font-medium text-neutral-900 dark:text-white">
{{ $server['name'] }}
@ -350,6 +356,10 @@ class="search-result-item w-full text-left block px-4 py-3 hover:bg-yellow-50 da
class="text-xs text-neutral-500 dark:text-neutral-400">
{{ $server['description'] }}
</div>
@else
<div class="text-xs text-transparent select-none">
&nbsp;
</div>
@endif
</div>
<svg xmlns="http://www.w3.org/2000/svg"
@ -414,8 +424,8 @@ class="flex items-center gap-3 p-3 bg-neutral-50 dark:bg-coolgray-200 rounded-lg
@foreach ($availableDestinations as $index => $destination)
<button type="button"
wire:click="selectDestination('{{ $destination['uuid'] }}', true)"
class="search-result-item w-full text-left block px-4 py-3 hover:bg-yellow-50 dark:hover:bg-yellow-900/20 transition-colors focus:outline-none focus:bg-yellow-100 dark:focus:bg-yellow-900/30">
<div class="flex items-center justify-between gap-3">
class="search-result-item w-full text-left block px-4 py-3 min-h-[4rem] hover:bg-yellow-50 dark:hover:bg-yellow-900/20 transition-colors focus:outline-none focus:bg-yellow-100 dark:focus:bg-yellow-900/30 border-b border-neutral-100 dark:border-coolgray-300 last:border-0">
<div class="flex items-center justify-between gap-3 min-h-[2.5rem]">
<div class="flex-1 min-w-0">
<div class="font-medium text-neutral-900 dark:text-white">
{{ $destination['name'] }}
@ -487,8 +497,8 @@ class="flex items-center gap-3 p-3 bg-neutral-50 dark:bg-coolgray-200 rounded-lg
@foreach ($availableProjects as $index => $project)
<button type="button"
wire:click="selectProject('{{ $project['uuid'] }}', true)"
class="search-result-item w-full text-left block px-4 py-3 hover:bg-yellow-50 dark:hover:bg-yellow-900/20 transition-colors focus:outline-none focus:bg-yellow-100 dark:focus:bg-yellow-900/30">
<div class="flex items-center justify-between gap-3">
class="search-result-item w-full text-left block px-4 py-3 min-h-[4rem] hover:bg-yellow-50 dark:hover:bg-yellow-900/20 transition-colors focus:outline-none focus:bg-yellow-100 dark:focus:bg-yellow-900/30 border-b border-neutral-100 dark:border-coolgray-300 last:border-0">
<div class="flex items-center justify-between gap-3 min-h-[2.5rem]">
<div class="flex-1 min-w-0">
<div class="font-medium text-neutral-900 dark:text-white">
{{ $project['name'] }}
@ -498,6 +508,10 @@ class="search-result-item w-full text-left block px-4 py-3 hover:bg-yellow-50 da
class="text-xs text-neutral-500 dark:text-neutral-400">
{{ $project['description'] }}
</div>
@else
<div class="text-xs text-transparent select-none">
&nbsp;
</div>
@endif
</div>
<svg xmlns="http://www.w3.org/2000/svg"
@ -562,8 +576,8 @@ class="flex items-center gap-3 p-3 bg-neutral-50 dark:bg-coolgray-200 rounded-lg
@foreach ($availableEnvironments as $index => $environment)
<button type="button"
wire:click="selectEnvironment('{{ $environment['uuid'] }}', true)"
class="search-result-item w-full text-left block px-4 py-3 hover:bg-yellow-50 dark:hover:bg-yellow-900/20 transition-colors focus:outline-none focus:bg-yellow-100 dark:focus:bg-yellow-900/30">
<div class="flex items-center justify-between gap-3">
class="search-result-item w-full text-left block px-4 py-3 min-h-[4rem] hover:bg-yellow-50 dark:hover:bg-yellow-900/20 transition-colors focus:outline-none focus:bg-yellow-100 dark:focus:bg-yellow-900/30 border-b border-neutral-100 dark:border-coolgray-300 last:border-0">
<div class="flex items-center justify-between gap-3 min-h-[2.5rem]">
<div class="flex-1 min-w-0">
<div class="font-medium text-neutral-900 dark:text-white">
{{ $environment['name'] }}
@ -573,6 +587,10 @@ class="search-result-item w-full text-left block px-4 py-3 hover:bg-yellow-50 da
class="text-xs text-neutral-500 dark:text-neutral-400">
{{ $environment['description'] }}
</div>
@else
<div class="text-xs text-transparent select-none">
&nbsp;
</div>
@endif
</div>
<svg xmlns="http://www.w3.org/2000/svg"
@ -745,6 +763,7 @@ class="search-result-item block px-4 py-3 hover:bg-neutral-50 dark:hover:bg-cool
</span>
<span
class="px-2 py-0.5 text-xs rounded-full bg-neutral-100 dark:bg-coolgray-300 text-neutral-700 dark:text-neutral-300 shrink-0">
<span x-show="result.type === 'navigation'">Navigation</span>
<span x-show="result.type === 'application'">Application</span>
<span x-show="result.type === 'service'">Service</span>
<span x-show="result.type === 'database'"