Refactor project environment and resource management UI

- Removed unnecessary SVG icons from the environment edit view for cleaner UI.
- Deleted the environment select component as it was no longer needed.
- Enhanced the project resource index view with a dropdown for environments and resources, improving navigation.
- Implemented dynamic dropdowns for environments and their associated resources, allowing for better user interaction.
- Added transitions and hover effects for a more responsive design.
- Updated the layout to ensure a consistent user experience across different project resources.
This commit is contained in:
Andras Bacsai 2025-12-15 16:45:30 +01:00
parent 2646fb81eb
commit f763c3aa8b
5 changed files with 601 additions and 216 deletions

View file

@ -1,35 +0,0 @@
<?php
namespace App\Livewire\Project\Resource;
use Illuminate\Database\Eloquent\Collection;
use Livewire\Component;
class EnvironmentSelect extends Component
{
public Collection $environments;
public string $project_uuid = '';
public string $selectedEnvironment = '';
public function mount()
{
$this->selectedEnvironment = request()->route('environment_uuid');
$this->project_uuid = request()->route('project_uuid');
}
public function updatedSelectedEnvironment($value)
{
if ($value === 'edit') {
return redirect()->route('project.show', [
'project_uuid' => $this->project_uuid,
]);
} else {
return redirect()->route('project.resource.index', [
'project_uuid' => $this->project_uuid,
'environment_uuid' => $value,
]);
}
}
}

View file

@ -5,7 +5,10 @@
])
@php
$projects = auth()->user()->currentTeam()->projects()->get();
$environments = $resource->environment->project->environments()->with(['applications', 'services'])->get();
$environments = $resource->environment->project
->environments()
->with(['applications', 'services'])
->get();
$currentProjectUuid = data_get($resource, 'environment.project.uuid');
$currentEnvironmentUuid = data_get($resource, 'environment.uuid');
$currentResourceUuid = data_get($resource, 'uuid');
@ -20,17 +23,17 @@
{{ data_get($resource, 'environment.project.name', 'Undefined Name') }}
</a>
<span class="px-1 text-warning">
<svg class="w-4 h-4 transition-transform" :class="{ 'rotate-down': projectOpen }" fill="none"
<svg class="w-3 h-3 transition-transform" :class="{ 'rotate-down': projectOpen }" fill="none"
stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="4" d="M9 5l7 7-7 7"></path>
</svg>
</span>
<!-- Project Dropdown -->
<div x-show="projectOpen"
x-transition:enter="transition ease-out duration-200" x-transition:enter-start="opacity-0 scale-95"
x-transition:enter-end="opacity-100 scale-100" x-transition:leave="transition ease-in duration-75"
x-transition:leave-start="opacity-100 scale-100" x-transition:leave-end="opacity-0 scale-95"
<div x-show="projectOpen" x-transition:enter="transition ease-out duration-200"
x-transition:enter-start="opacity-0 scale-95" x-transition:enter-end="opacity-100 scale-100"
x-transition:leave="transition ease-in duration-75" x-transition:leave-start="opacity-100 scale-100"
x-transition:leave-end="opacity-0 scale-95"
class="absolute z-20 top-full mt-1 w-56 -ml-2 bg-white dark:bg-coolgray-100 rounded-md shadow-lg py-1 border border-coolgray-200 max-h-96 overflow-y-auto scrollbar">
@foreach ($projects as $project)
<a href="{{ route('project.show', ['project_uuid' => $project->uuid]) }}"
@ -45,7 +48,8 @@ class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-cool
<!-- Environment Level -->
<li class="inline-flex items-center" x-data="{ envOpen: false, activeEnv: null, activeRes: null, activeMenuEnv: null }">
<div class="flex items-center relative" @mouseenter="envOpen = true" @mouseleave="envOpen = false; activeEnv = null; activeRes = null; activeMenuEnv = null">
<div class="flex items-center relative" @mouseenter="envOpen = true"
@mouseleave="envOpen = false; activeEnv = null; activeRes = null; activeMenuEnv = null">
<a class="text-xs truncate lg:text-sm hover:text-warning"
href="{{ route('project.resource.index', [
'environment_uuid' => $currentEnvironmentUuid,
@ -54,28 +58,41 @@ class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-cool
{{ data_get($resource, 'environment.name') }}
</a>
<span class="px-1 text-warning">
<svg class="w-4 h-4 transition-transform" :class="{ 'rotate-down': envOpen }" fill="none"
<svg class="w-3 h-3 transition-transform" :class="{ 'rotate-down': envOpen }" fill="none"
stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="4" d="M9 5l7 7-7 7"></path>
</svg>
</span>
<!-- Environment Dropdown Container -->
<div x-show="envOpen"
x-transition:enter="transition ease-out duration-200" x-transition:enter-start="opacity-0 scale-95"
x-transition:enter-end="opacity-100 scale-100" x-transition:leave="transition ease-in duration-75"
x-transition:leave-start="opacity-100 scale-100" x-transition:leave-end="opacity-0 scale-95"
class="absolute z-20 top-full mt-1 flex items-start">
<div x-show="envOpen" x-transition:enter="transition ease-out duration-200"
x-transition:enter-start="opacity-0 scale-95" x-transition:enter-end="opacity-100 scale-100"
x-transition:leave="transition ease-in duration-75" x-transition:leave-start="opacity-100 scale-100"
x-transition:leave-end="opacity-0 scale-95" class="absolute z-20 top-full mt-1 flex items-start">
<!-- Environment List -->
<div class="w-48 bg-white dark:bg-coolgray-100 rounded-md shadow-lg py-1 border border-coolgray-200 max-h-96 overflow-y-auto scrollbar">
<div
class="w-48 bg-white dark:bg-coolgray-100 rounded-md shadow-lg py-1 border border-coolgray-200 max-h-96 overflow-y-auto scrollbar">
@foreach ($environments as $environment)
@php
$envResources = collect()
->merge($environment->applications->map(fn($app) => ['type' => 'application', 'resource' => $app]))
->merge($environment->databases()->map(fn($db) => ['type' => 'database', 'resource' => $db]))
->merge($environment->services->map(fn($svc) => ['type' => 'service', 'resource' => $svc]));
->merge(
$environment->applications->map(
fn($app) => ['type' => 'application', 'resource' => $app],
),
)
->merge(
$environment
->databases()
->map(fn($db) => ['type' => 'database', 'resource' => $db]),
)
->merge(
$environment->services->map(
fn($svc) => ['type' => 'service', 'resource' => $svc],
),
);
@endphp
<div @mouseenter="activeEnv = '{{ $environment->uuid }}'; activeRes = null" @mouseleave="activeEnv = null">
<div @mouseenter="activeEnv = '{{ $environment->uuid }}'; activeRes = null"
@mouseleave="activeEnv = null">
<a href="{{ route('project.resource.index', [
'environment_uuid' => $environment->uuid,
'project_uuid' => $currentProjectUuid,
@ -84,36 +101,61 @@ class="flex items-center justify-between gap-2 px-4 py-2 text-sm hover:bg-coolgr
title="{{ $environment->name }}">
<span class="truncate">{{ $environment->name }}</span>
@if ($envResources->count() > 0)
<svg class="w-4 h-4 shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path>
<svg class="w-3 h-3 shrink-0" fill="none" stroke="currentColor"
viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="4"
d="M9 5l7 7-7 7"></path>
</svg>
@endif
</a>
</div>
@endforeach
<div class="border-t border-coolgray-200 mt-1 pt-1">
<a href="{{ route('project.show', ['project_uuid' => $currentProjectUuid]) }}"
class="flex items-center gap-2 px-4 py-2 text-sm hover:bg-coolgray-200 dark:hover:bg-coolgray-200">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z">
</path>
</svg>
Create / Edit
</a>
</div>
</div>
<!-- Resources Sub-dropdown (2nd level) -->
@foreach ($environments as $environment)
@php
$envResources = collect()
->merge($environment->applications->map(fn($app) => ['type' => 'application', 'resource' => $app]))
->merge($environment->databases()->map(fn($db) => ['type' => 'database', 'resource' => $db]))
->merge($environment->services->map(fn($svc) => ['type' => 'service', 'resource' => $svc]));
->merge(
$environment->applications->map(
fn($app) => ['type' => 'application', 'resource' => $app],
),
)
->merge(
$environment
->databases()
->map(fn($db) => ['type' => 'database', 'resource' => $db]),
)
->merge(
$environment->services->map(fn($svc) => ['type' => 'service', 'resource' => $svc]),
);
@endphp
@if ($envResources->count() > 0)
<div x-show="activeEnv === '{{ $environment->uuid }}'"
x-transition:enter="transition ease-out duration-150" x-transition:enter-start="opacity-0"
x-transition:enter-end="opacity-100" x-transition:leave="transition ease-in duration-100"
x-transition:enter="transition ease-out duration-150"
x-transition:enter-start="opacity-0" x-transition:enter-end="opacity-100"
x-transition:leave="transition ease-in duration-100"
x-transition:leave-start="opacity-100" x-transition:leave-end="opacity-0"
@mouseenter="activeEnv = '{{ $environment->uuid }}'" @mouseleave="activeEnv = null; activeRes = null"
class="ml-1 flex items-start">
<div class="w-48 bg-white dark:bg-coolgray-100 rounded-md shadow-lg py-1 border border-coolgray-200 max-h-96 overflow-y-auto scrollbar">
@mouseenter="activeEnv = '{{ $environment->uuid }}'"
@mouseleave="activeEnv = null; activeRes = null" class="ml-1 flex items-start">
<div
class="w-48 bg-white dark:bg-coolgray-100 rounded-md shadow-lg py-1 border border-coolgray-200 max-h-96 overflow-y-auto scrollbar">
@foreach ($envResources as $envResource)
@php
$resType = $envResource['type'];
$res = $envResource['resource'];
$resRoute = match($resType) {
$resRoute = match ($resType) {
'application' => route('project.application.configuration', [
'project_uuid' => $currentProjectUuid,
'environment_uuid' => $environment->uuid,
@ -132,13 +174,16 @@ class="ml-1 flex items-start">
};
$isCurrentResource = $res->uuid === $currentResourceUuid;
@endphp
<div @mouseenter="activeRes = '{{ $environment->uuid }}-{{ $res->uuid }}'" @mouseleave="activeRes = null">
<div @mouseenter="activeRes = '{{ $environment->uuid }}-{{ $res->uuid }}'"
@mouseleave="activeRes = null">
<a href="{{ $resRoute }}"
class="flex items-center justify-between gap-2 px-4 py-2 text-sm hover:bg-coolgray-200 dark:hover:bg-coolgray-200 {{ $isCurrentResource ? 'dark:text-warning font-semibold' : '' }}"
title="{{ $res->name }}">
<span class="truncate">{{ $res->name }}</span>
<svg class="w-4 h-4 shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path>
<svg class="w-3 h-3 shrink-0" fill="none" stroke="currentColor"
viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round"
stroke-width="4" d="M9 5l7 7-7 7"></path>
</svg>
</a>
</div>
@ -164,110 +209,182 @@ class="flex items-center justify-between gap-2 px-4 py-2 text-sm hover:bg-coolgr
$resKey = $environment->uuid . '-' . $res->uuid;
@endphp
<div x-show="activeRes === '{{ $resKey }}'"
x-transition:enter="transition ease-out duration-150" x-transition:enter-start="opacity-0"
x-transition:enter-end="opacity-100" x-transition:leave="transition ease-in duration-100"
x-transition:enter="transition ease-out duration-150"
x-transition:enter-start="opacity-0" x-transition:enter-end="opacity-100"
x-transition:leave="transition ease-in duration-100"
x-transition:leave-start="opacity-100" x-transition:leave-end="opacity-0"
@mouseenter="activeRes = '{{ $resKey }}'" @mouseleave="activeRes = null; activeMenuEnv = null"
@mouseenter="activeRes = '{{ $resKey }}'"
@mouseleave="activeRes = null; activeMenuEnv = null"
class="ml-1 flex items-start">
<!-- Main Menu List -->
<div class="w-48 bg-white dark:bg-coolgray-100 rounded-md shadow-lg py-1 border border-coolgray-200">
<div
class="w-48 bg-white dark:bg-coolgray-100 rounded-md shadow-lg py-1 border border-coolgray-200">
@if ($resType === 'application')
<div @mouseenter="activeMenuEnv = '{{ $resKey }}-config'" @mouseleave="activeMenuEnv = null">
<div @mouseenter="activeMenuEnv = '{{ $resKey }}-config'"
@mouseleave="activeMenuEnv = null">
<a href="{{ route('project.application.configuration', $resParams) }}"
class="flex items-center justify-between gap-2 px-4 py-2 text-sm hover:bg-coolgray-200 dark:hover:bg-coolgray-200">
<span>Configuration</span>
<svg class="w-4 h-4 shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path>
<svg class="w-3 h-3 shrink-0" fill="none"
stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round"
stroke-width="4" d="M9 5l7 7-7 7"></path>
</svg>
</a>
</div>
<a href="{{ route('project.application.deployment.index', $resParams) }}" class="block px-4 py-2 text-sm hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Deployments</a>
<a href="{{ route('project.application.logs', $resParams) }}" class="block px-4 py-2 text-sm hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Logs</a>
<a href="{{ route('project.application.deployment.index', $resParams) }}"
class="block px-4 py-2 text-sm hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Deployments</a>
<a href="{{ route('project.application.logs', $resParams) }}"
class="block px-4 py-2 text-sm hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Logs</a>
@can('canAccessTerminal')
<a href="{{ route('project.application.command', $resParams) }}" class="block px-4 py-2 text-sm hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Terminal</a>
<a href="{{ route('project.application.command', $resParams) }}"
class="block px-4 py-2 text-sm hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Terminal</a>
@endcan
@elseif ($resType === 'service')
<div @mouseenter="activeMenuEnv = '{{ $resKey }}-config'" @mouseleave="activeMenuEnv = null">
<div @mouseenter="activeMenuEnv = '{{ $resKey }}-config'"
@mouseleave="activeMenuEnv = null">
<a href="{{ route('project.service.configuration', $resParams) }}"
class="flex items-center justify-between gap-2 px-4 py-2 text-sm hover:bg-coolgray-200 dark:hover:bg-coolgray-200">
<span>Configuration</span>
<svg class="w-4 h-4 shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path>
<svg class="w-3 h-3 shrink-0" fill="none"
stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round"
stroke-width="4" d="M9 5l7 7-7 7"></path>
</svg>
</a>
</div>
<a href="{{ route('project.service.logs', $resParams) }}" class="block px-4 py-2 text-sm hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Logs</a>
<a href="{{ route('project.service.logs', $resParams) }}"
class="block px-4 py-2 text-sm hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Logs</a>
@can('canAccessTerminal')
<a href="{{ route('project.service.command', $resParams) }}" class="block px-4 py-2 text-sm hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Terminal</a>
<a href="{{ route('project.service.command', $resParams) }}"
class="block px-4 py-2 text-sm hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Terminal</a>
@endcan
@else
<div @mouseenter="activeMenuEnv = '{{ $resKey }}-config'" @mouseleave="activeMenuEnv = null">
<div @mouseenter="activeMenuEnv = '{{ $resKey }}-config'"
@mouseleave="activeMenuEnv = null">
<a href="{{ route('project.database.configuration', $resParams) }}"
class="flex items-center justify-between gap-2 px-4 py-2 text-sm hover:bg-coolgray-200 dark:hover:bg-coolgray-200">
<span>Configuration</span>
<svg class="w-4 h-4 shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path>
<svg class="w-3 h-3 shrink-0" fill="none"
stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round"
stroke-width="2" d="M9 5l7 7-7 7"></path>
</svg>
</a>
</div>
<a href="{{ route('project.database.logs', $resParams) }}" class="block px-4 py-2 text-sm hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Logs</a>
<a href="{{ route('project.database.logs', $resParams) }}"
class="block px-4 py-2 text-sm hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Logs</a>
@can('canAccessTerminal')
<a href="{{ route('project.database.command', $resParams) }}" class="block px-4 py-2 text-sm hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Terminal</a>
<a href="{{ route('project.database.command', $resParams) }}"
class="block px-4 py-2 text-sm hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Terminal</a>
@endcan
@if (
$res->getMorphClass() === 'App\Models\StandalonePostgresql' ||
$res->getMorphClass() === 'App\Models\StandaloneMongodb' ||
$res->getMorphClass() === 'App\Models\StandaloneMysql' ||
$res->getMorphClass() === 'App\Models\StandaloneMariadb')
<a href="{{ route('project.database.backup.index', $resParams) }}" class="block px-4 py-2 text-sm hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Backups</a>
$res->getMorphClass() === 'App\Models\StandaloneMongodb' ||
$res->getMorphClass() === 'App\Models\StandaloneMysql' ||
$res->getMorphClass() === 'App\Models\StandaloneMariadb')
<a href="{{ route('project.database.backup.index', $resParams) }}"
class="block px-4 py-2 text-sm hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Backups</a>
@endif
@endif
</div>
<!-- Configuration Sub-menu (4th level) -->
<div x-show="activeMenuEnv === '{{ $resKey }}-config'"
x-transition:enter="transition ease-out duration-150" x-transition:enter-start="opacity-0"
x-transition:enter-end="opacity-100" x-transition:leave="transition ease-in duration-100"
x-transition:enter="transition ease-out duration-150"
x-transition:enter-start="opacity-0" x-transition:enter-end="opacity-100"
x-transition:leave="transition ease-in duration-100"
x-transition:leave-start="opacity-100" x-transition:leave-end="opacity-0"
@mouseenter="activeMenuEnv = '{{ $resKey }}-config'" @mouseleave="activeMenuEnv = null"
@mouseenter="activeMenuEnv = '{{ $resKey }}-config'"
@mouseleave="activeMenuEnv = null"
class="ml-1 w-52 bg-white dark:bg-coolgray-100 rounded-md shadow-lg py-1 border border-coolgray-200 max-h-96 overflow-y-auto scrollbar">
@if ($resType === 'application')
<a href="{{ route('project.application.configuration', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">General</a>
<a href="{{ route('project.application.environment-variables', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Environment Variables</a>
<a href="{{ route('project.application.persistent-storage', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Persistent Storage</a>
<a href="{{ route('project.application.source', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Source</a>
<a href="{{ route('project.application.servers', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Servers</a>
<a href="{{ route('project.application.scheduled-tasks.show', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Scheduled Tasks</a>
<a href="{{ route('project.application.webhooks', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Webhooks</a>
<a href="{{ route('project.application.preview-deployments', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Preview Deployments</a>
<a href="{{ route('project.application.healthcheck', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Healthcheck</a>
<a href="{{ route('project.application.rollback', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Rollback</a>
<a href="{{ route('project.application.resource-limits', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Resource Limits</a>
<a href="{{ route('project.application.resource-operations', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Resource Operations</a>
<a href="{{ route('project.application.metrics', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Metrics</a>
<a href="{{ route('project.application.tags', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Tags</a>
<a href="{{ route('project.application.advanced', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Advanced</a>
<a href="{{ route('project.application.danger', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200 text-red-500">Danger Zone</a>
<a href="{{ route('project.application.configuration', $resParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">General</a>
<a href="{{ route('project.application.environment-variables', $resParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Environment
Variables</a>
<a href="{{ route('project.application.persistent-storage', $resParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Persistent
Storage</a>
<a href="{{ route('project.application.source', $resParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Source</a>
<a href="{{ route('project.application.servers', $resParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Servers</a>
<a href="{{ route('project.application.scheduled-tasks.show', $resParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Scheduled
Tasks</a>
<a href="{{ route('project.application.webhooks', $resParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Webhooks</a>
<a href="{{ route('project.application.preview-deployments', $resParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Preview
Deployments</a>
<a href="{{ route('project.application.healthcheck', $resParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Healthcheck</a>
<a href="{{ route('project.application.rollback', $resParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Rollback</a>
<a href="{{ route('project.application.resource-limits', $resParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Resource
Limits</a>
<a href="{{ route('project.application.resource-operations', $resParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Resource
Operations</a>
<a href="{{ route('project.application.metrics', $resParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Metrics</a>
<a href="{{ route('project.application.tags', $resParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Tags</a>
<a href="{{ route('project.application.advanced', $resParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Advanced</a>
<a href="{{ route('project.application.danger', $resParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200 text-red-500">Danger
Zone</a>
@elseif ($resType === 'service')
<a href="{{ route('project.service.configuration', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">General</a>
<a href="{{ route('project.service.environment-variables', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Environment Variables</a>
<a href="{{ route('project.service.storages', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Storages</a>
<a href="{{ route('project.service.scheduled-tasks.show', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Scheduled Tasks</a>
<a href="{{ route('project.service.webhooks', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Webhooks</a>
<a href="{{ route('project.service.resource-operations', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Resource Operations</a>
<a href="{{ route('project.service.tags', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Tags</a>
<a href="{{ route('project.service.danger', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200 text-red-500">Danger Zone</a>
<a href="{{ route('project.service.configuration', $resParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">General</a>
<a href="{{ route('project.service.environment-variables', $resParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Environment
Variables</a>
<a href="{{ route('project.service.storages', $resParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Storages</a>
<a href="{{ route('project.service.scheduled-tasks.show', $resParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Scheduled
Tasks</a>
<a href="{{ route('project.service.webhooks', $resParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Webhooks</a>
<a href="{{ route('project.service.resource-operations', $resParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Resource
Operations</a>
<a href="{{ route('project.service.tags', $resParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Tags</a>
<a href="{{ route('project.service.danger', $resParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200 text-red-500">Danger
Zone</a>
@else
<a href="{{ route('project.database.configuration', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">General</a>
<a href="{{ route('project.database.environment-variables', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Environment Variables</a>
<a href="{{ route('project.database.servers', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Servers</a>
<a href="{{ route('project.database.persistent-storage', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Persistent Storage</a>
<a href="{{ route('project.database.webhooks', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Webhooks</a>
<a href="{{ route('project.database.resource-limits', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Resource Limits</a>
<a href="{{ route('project.database.resource-operations', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Resource Operations</a>
<a href="{{ route('project.database.metrics', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Metrics</a>
<a href="{{ route('project.database.tags', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Tags</a>
<a href="{{ route('project.database.danger', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200 text-red-500">Danger Zone</a>
<a href="{{ route('project.database.configuration', $resParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">General</a>
<a href="{{ route('project.database.environment-variables', $resParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Environment
Variables</a>
<a href="{{ route('project.database.servers', $resParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Servers</a>
<a href="{{ route('project.database.persistent-storage', $resParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Persistent
Storage</a>
<a href="{{ route('project.database.webhooks', $resParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Webhooks</a>
<a href="{{ route('project.database.resource-limits', $resParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Resource
Limits</a>
<a href="{{ route('project.database.resource-operations', $resParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Resource
Operations</a>
<a href="{{ route('project.database.metrics', $resParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Metrics</a>
<a href="{{ route('project.database.tags', $resParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Tags</a>
<a href="{{ route('project.database.danger', $resParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200 text-red-500">Danger
Zone</a>
@endif
</div>
</div>
@ -299,7 +416,8 @@ class="ml-1 w-52 bg-white dark:bg-coolgray-100 rounded-md shadow-lg py-1 border
}
@endphp
<li class="inline-flex items-center" x-data="{ resourceOpen: false, activeMenu: null }">
<div class="flex items-center relative" @mouseenter="resourceOpen = true" @mouseleave="resourceOpen = false; activeMenu = null">
<div class="flex items-center relative" @mouseenter="resourceOpen = true"
@mouseleave="resourceOpen = false; activeMenu = null">
<a class="text-xs truncate lg:text-sm hover:text-warning"
href="{{ $isApplication
? route('project.application.configuration', $routeParams)
@ -309,28 +427,32 @@ class="ml-1 w-52 bg-white dark:bg-coolgray-100 rounded-md shadow-lg py-1 border
{{ data_get($resource, 'name') }}
</a>
<span class="px-1 text-warning">
<svg class="w-4 h-4 transition-transform" :class="{ 'rotate-down': resourceOpen }" fill="none"
<svg class="w-3 h-3 transition-transform" :class="{ 'rotate-down': resourceOpen }" fill="none"
stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="4" d="M9 5l7 7-7 7">
</path>
</svg>
</span>
<!-- Resource Dropdown Container -->
<div x-show="resourceOpen"
x-transition:enter="transition ease-out duration-200" x-transition:enter-start="opacity-0 scale-95"
x-transition:enter-end="opacity-100 scale-100" x-transition:leave="transition ease-in duration-75"
<div x-show="resourceOpen" x-transition:enter="transition ease-out duration-200"
x-transition:enter-start="opacity-0 scale-95" x-transition:enter-end="opacity-100 scale-100"
x-transition:leave="transition ease-in duration-75"
x-transition:leave-start="opacity-100 scale-100" x-transition:leave-end="opacity-0 scale-95"
class="absolute z-20 top-full mt-1 flex items-start">
<!-- Main Menu List -->
<div class="w-48 bg-white dark:bg-coolgray-100 rounded-md shadow-lg py-1 border border-coolgray-200">
<div
class="w-48 bg-white dark:bg-coolgray-100 rounded-md shadow-lg py-1 border border-coolgray-200">
@if ($isApplication)
<!-- Application Main Menus -->
<div @mouseenter="activeMenu = 'config'" @mouseleave="activeMenu = null">
<a href="{{ route('project.application.configuration', $routeParams) }}"
class="flex items-center justify-between gap-2 px-4 py-2 text-sm hover:bg-coolgray-200 dark:hover:bg-coolgray-200">
<span>Configuration</span>
<svg class="w-4 h-4 shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path>
<svg class="w-3 h-3 shrink-0" fill="none" stroke="currentColor"
viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="4"
d="M9 5l7 7-7 7"></path>
</svg>
</a>
</div>
@ -354,8 +476,10 @@ class="block px-4 py-2 text-sm hover:bg-coolgray-200 dark:hover:bg-coolgray-200"
<a href="{{ route('project.service.configuration', $routeParams) }}"
class="flex items-center justify-between gap-2 px-4 py-2 text-sm hover:bg-coolgray-200 dark:hover:bg-coolgray-200">
<span>Configuration</span>
<svg class="w-4 h-4 shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path>
<svg class="w-4 h-4 shrink-0" fill="none" stroke="currentColor"
viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M9 5l7 7-7 7"></path>
</svg>
</a>
</div>
@ -375,8 +499,10 @@ class="block px-4 py-2 text-sm hover:bg-coolgray-200 dark:hover:bg-coolgray-200"
<a href="{{ route('project.database.configuration', $routeParams) }}"
class="flex items-center justify-between gap-2 px-4 py-2 text-sm hover:bg-coolgray-200 dark:hover:bg-coolgray-200">
<span>Configuration</span>
<svg class="w-4 h-4 shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path>
<svg class="w-4 h-4 shrink-0" fill="none" stroke="currentColor"
viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M9 5l7 7-7 7"></path>
</svg>
</a>
</div>
@ -392,9 +518,9 @@ class="block px-4 py-2 text-sm hover:bg-coolgray-200 dark:hover:bg-coolgray-200"
@endcan
@if (
$resourceType === 'App\Models\StandalonePostgresql' ||
$resourceType === 'App\Models\StandaloneMongodb' ||
$resourceType === 'App\Models\StandaloneMysql' ||
$resourceType === 'App\Models\StandaloneMariadb')
$resourceType === 'App\Models\StandaloneMongodb' ||
$resourceType === 'App\Models\StandaloneMysql' ||
$resourceType === 'App\Models\StandaloneMariadb')
<a href="{{ route('project.database.backup.index', $routeParams) }}"
class="block px-4 py-2 text-sm hover:bg-coolgray-200 dark:hover:bg-coolgray-200">
Backups
@ -404,49 +530,99 @@ class="block px-4 py-2 text-sm hover:bg-coolgray-200 dark:hover:bg-coolgray-200"
</div>
<!-- Configuration Sub-menu -->
<div x-show="activeMenu === 'config'"
x-transition:enter="transition ease-out duration-150" x-transition:enter-start="opacity-0"
x-transition:enter-end="opacity-100" x-transition:leave="transition ease-in duration-100"
x-transition:leave-start="opacity-100" x-transition:leave-end="opacity-0"
@mouseenter="activeMenu = 'config'" @mouseleave="activeMenu = null"
<div x-show="activeMenu === 'config'" x-transition:enter="transition ease-out duration-150"
x-transition:enter-start="opacity-0" x-transition:enter-end="opacity-100"
x-transition:leave="transition ease-in duration-100" x-transition:leave-start="opacity-100"
x-transition:leave-end="opacity-0" @mouseenter="activeMenu = 'config'"
@mouseleave="activeMenu = null"
class="ml-1 w-52 bg-white dark:bg-coolgray-100 rounded-md shadow-lg py-1 border border-coolgray-200 max-h-96 overflow-y-auto scrollbar">
@if ($isApplication)
<a href="{{ route('project.application.configuration', $routeParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">General</a>
<a href="{{ route('project.application.environment-variables', $routeParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Environment Variables</a>
<a href="{{ route('project.application.persistent-storage', $routeParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Persistent Storage</a>
<a href="{{ route('project.application.source', $routeParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Source</a>
<a href="{{ route('project.application.servers', $routeParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Servers</a>
<a href="{{ route('project.application.scheduled-tasks.show', $routeParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Scheduled Tasks</a>
<a href="{{ route('project.application.webhooks', $routeParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Webhooks</a>
<a href="{{ route('project.application.preview-deployments', $routeParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Preview Deployments</a>
<a href="{{ route('project.application.healthcheck', $routeParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Healthcheck</a>
<a href="{{ route('project.application.rollback', $routeParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Rollback</a>
<a href="{{ route('project.application.resource-limits', $routeParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Resource Limits</a>
<a href="{{ route('project.application.resource-operations', $routeParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Resource Operations</a>
<a href="{{ route('project.application.metrics', $routeParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Metrics</a>
<a href="{{ route('project.application.tags', $routeParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Tags</a>
<a href="{{ route('project.application.advanced', $routeParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Advanced</a>
<a href="{{ route('project.application.danger', $routeParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200 text-red-500">Danger Zone</a>
<a href="{{ route('project.application.configuration', $routeParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">General</a>
<a href="{{ route('project.application.environment-variables', $routeParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Environment
Variables</a>
<a href="{{ route('project.application.persistent-storage', $routeParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Persistent
Storage</a>
<a href="{{ route('project.application.source', $routeParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Source</a>
<a href="{{ route('project.application.servers', $routeParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Servers</a>
<a href="{{ route('project.application.scheduled-tasks.show', $routeParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Scheduled
Tasks</a>
<a href="{{ route('project.application.webhooks', $routeParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Webhooks</a>
<a href="{{ route('project.application.preview-deployments', $routeParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Preview
Deployments</a>
<a href="{{ route('project.application.healthcheck', $routeParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Healthcheck</a>
<a href="{{ route('project.application.rollback', $routeParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Rollback</a>
<a href="{{ route('project.application.resource-limits', $routeParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Resource
Limits</a>
<a href="{{ route('project.application.resource-operations', $routeParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Resource
Operations</a>
<a href="{{ route('project.application.metrics', $routeParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Metrics</a>
<a href="{{ route('project.application.tags', $routeParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Tags</a>
<a href="{{ route('project.application.advanced', $routeParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Advanced</a>
<a href="{{ route('project.application.danger', $routeParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200 text-red-500">Danger
Zone</a>
@elseif ($isService)
<a href="{{ route('project.service.configuration', $routeParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">General</a>
<a href="{{ route('project.service.environment-variables', $routeParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Environment Variables</a>
<a href="{{ route('project.service.storages', $routeParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Storages</a>
<a href="{{ route('project.service.scheduled-tasks.show', $routeParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Scheduled Tasks</a>
<a href="{{ route('project.service.webhooks', $routeParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Webhooks</a>
<a href="{{ route('project.service.resource-operations', $routeParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Resource Operations</a>
<a href="{{ route('project.service.tags', $routeParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Tags</a>
<a href="{{ route('project.service.danger', $routeParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200 text-red-500">Danger Zone</a>
<a href="{{ route('project.service.configuration', $routeParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">General</a>
<a href="{{ route('project.service.environment-variables', $routeParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Environment
Variables</a>
<a href="{{ route('project.service.storages', $routeParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Storages</a>
<a href="{{ route('project.service.scheduled-tasks.show', $routeParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Scheduled
Tasks</a>
<a href="{{ route('project.service.webhooks', $routeParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Webhooks</a>
<a href="{{ route('project.service.resource-operations', $routeParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Resource
Operations</a>
<a href="{{ route('project.service.tags', $routeParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Tags</a>
<a href="{{ route('project.service.danger', $routeParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200 text-red-500">Danger
Zone</a>
@else
<a href="{{ route('project.database.configuration', $routeParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">General</a>
<a href="{{ route('project.database.environment-variables', $routeParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Environment Variables</a>
<a href="{{ route('project.database.servers', $routeParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Servers</a>
<a href="{{ route('project.database.persistent-storage', $routeParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Persistent Storage</a>
<a href="{{ route('project.database.webhooks', $routeParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Webhooks</a>
<a href="{{ route('project.database.resource-limits', $routeParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Resource Limits</a>
<a href="{{ route('project.database.resource-operations', $routeParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Resource Operations</a>
<a href="{{ route('project.database.metrics', $routeParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Metrics</a>
<a href="{{ route('project.database.tags', $routeParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Tags</a>
<a href="{{ route('project.database.danger', $routeParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200 text-red-500">Danger Zone</a>
<a href="{{ route('project.database.configuration', $routeParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">General</a>
<a href="{{ route('project.database.environment-variables', $routeParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Environment
Variables</a>
<a href="{{ route('project.database.servers', $routeParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Servers</a>
<a href="{{ route('project.database.persistent-storage', $routeParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Persistent
Storage</a>
<a href="{{ route('project.database.webhooks', $routeParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Webhooks</a>
<a href="{{ route('project.database.resource-limits', $routeParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Resource
Limits</a>
<a href="{{ route('project.database.resource-operations', $routeParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Resource
Operations</a>
<a href="{{ route('project.database.metrics', $routeParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Metrics</a>
<a href="{{ route('project.database.tags', $routeParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Tags</a>
<a href="{{ route('project.database.danger', $routeParams) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200 text-red-500">Danger
Zone</a>
@endif
</div>
</div>

View file

@ -17,12 +17,6 @@
<a class="text-xs truncate lg:text-sm"
href="{{ route('project.show', ['project_uuid' => $project->uuid]) }}">
{{ $project->name }}</a>
<svg aria-hidden="true" class="w-4 h-4 mx-1 font-bold dark:text-warning" fill="currentColor"
viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd"
d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z"
clip-rule="evenodd"></path>
</svg>
</div>
</li>
<li>
@ -35,7 +29,7 @@
</li>
<li>
<div class="flex items-center">
<svg aria-hidden="true" class="w-4 h-4 mx-1 font-bold dark:text-warning" fill="currentColor"
<svg aria-hidden="true" class="w-3 h-3 mx-1 font-bold dark:text-warning" fill="currentColor"
viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd"
d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z"

View file

@ -1,7 +0,0 @@
<x-forms.select wire:model.live="selectedEnvironment">
@foreach ($environments as $environment)
<option value="{{ $environment->uuid }}">{{ $environment->name }}</option>
@endforeach
<option disabled>-----</option>
<option value="edit">Create / Edit</option>
</x-forms.select>

View file

@ -29,23 +29,277 @@ class="button">+
<livewire:project.delete-environment :disabled="!$environment->isEmpty()" :environment_id="$environment->id" />
@endcan
</div>
@php
$projects = auth()->user()->currentTeam()->projects()->get();
@endphp
<nav class="flex pt-2 pb-6">
<ol class="flex items-center">
<li class="inline-flex items-center">
<a class="text-xs truncate lg:text-sm"
href="{{ route('project.show', ['project_uuid' => data_get($parameters, 'project_uuid')]) }}">
{{ $project->name }}</a>
</li>
<li>
<div class="flex items-center">
<svg aria-hidden="true" class="w-4 h-4 mx-1 font-bold dark:text-warning" fill="currentColor"
viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd"
d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z"
clip-rule="evenodd"></path>
</svg>
<li class="inline-flex items-center" x-data="{ projectOpen: false }">
<div class="flex items-center relative" @mouseenter="projectOpen = true" @mouseleave="projectOpen = false">
<a class="text-xs truncate lg:text-sm hover:text-warning"
href="{{ route('project.show', ['project_uuid' => data_get($parameters, 'project_uuid')]) }}">
{{ $project->name }}</a>
<span class="px-1 text-warning">
<svg class="w-3 h-3 transition-transform" :class="{ 'rotate-90': projectOpen }" fill="none"
stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="4" d="M9 5l7 7-7 7"></path>
</svg>
</span>
<livewire:project.resource.environment-select :environments="$project->environments" />
<div x-show="projectOpen" x-transition:enter="transition ease-out duration-200"
x-transition:enter-start="opacity-0 scale-95" x-transition:enter-end="opacity-100 scale-100"
x-transition:leave="transition ease-in duration-75" x-transition:leave-start="opacity-100 scale-100"
x-transition:leave-end="opacity-0 scale-95"
class="absolute z-20 top-full mt-1 w-56 -ml-2 bg-white dark:bg-coolgray-100 rounded-md shadow-lg py-1 border border-coolgray-200 max-h-96 overflow-y-auto scrollbar">
@foreach ($projects as $proj)
<a href="{{ route('project.show', ['project_uuid' => $proj->uuid]) }}"
class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200 {{ $proj->uuid === $project->uuid ? 'dark:text-warning font-semibold' : '' }}"
title="{{ $proj->name }}">
{{ $proj->name }}
</a>
@endforeach
</div>
</div>
</li>
@php
$allEnvironments = $project->environments()->with(['applications', 'services'])->get();
@endphp
<li class="inline-flex items-center" x-data="{ envOpen: false, activeEnv: null, activeRes: null, activeMenuEnv: null }">
<div class="flex items-center relative" @mouseenter="envOpen = true" @mouseleave="envOpen = false; activeEnv = null; activeRes = null; activeMenuEnv = null">
<a class="text-xs truncate lg:text-sm hover:text-warning"
href="{{ route('project.resource.index', ['project_uuid' => data_get($parameters, 'project_uuid'), 'environment_uuid' => $environment->uuid]) }}">
{{ $environment->name }}
</a>
<span class="px-1 text-warning">
<svg class="w-3 h-3 transition-transform" :class="{ 'rotate-90': envOpen }" fill="none"
stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="4" d="M9 5l7 7-7 7"></path>
</svg>
</span>
<!-- Environment Dropdown Container -->
<div x-show="envOpen" x-transition:enter="transition ease-out duration-200"
x-transition:enter-start="opacity-0 scale-95" x-transition:enter-end="opacity-100 scale-100"
x-transition:leave="transition ease-in duration-75" x-transition:leave-start="opacity-100 scale-100"
x-transition:leave-end="opacity-0 scale-95"
class="absolute z-20 top-full mt-1 flex items-start">
<!-- Environment List -->
<div class="w-48 bg-white dark:bg-coolgray-100 rounded-md shadow-lg py-1 border border-coolgray-200 max-h-96 overflow-y-auto scrollbar">
@foreach ($allEnvironments as $env)
@php
$envResources = collect()
->merge($env->applications->map(fn($app) => ['type' => 'application', 'resource' => $app]))
->merge($env->databases()->map(fn($db) => ['type' => 'database', 'resource' => $db]))
->merge($env->services->map(fn($svc) => ['type' => 'service', 'resource' => $svc]));
@endphp
<div @mouseenter="activeEnv = '{{ $env->uuid }}'; activeRes = null" @mouseleave="activeEnv = null">
<a href="{{ route('project.resource.index', ['project_uuid' => data_get($parameters, 'project_uuid'), 'environment_uuid' => $env->uuid]) }}"
class="flex items-center justify-between gap-2 px-4 py-2 text-sm hover:bg-coolgray-200 dark:hover:bg-coolgray-200 {{ $env->uuid === $environment->uuid ? 'dark:text-warning font-semibold' : '' }}"
title="{{ $env->name }}">
<span class="truncate">{{ $env->name }}</span>
@if ($envResources->count() > 0)
<svg class="w-3 h-3 shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="4" d="M9 5l7 7-7 7"></path>
</svg>
@endif
</a>
</div>
@endforeach
<div class="border-t border-coolgray-200 mt-1 pt-1">
<a href="{{ route('project.show', ['project_uuid' => data_get($parameters, 'project_uuid')]) }}"
class="flex items-center gap-2 px-4 py-2 text-sm hover:bg-coolgray-200 dark:hover:bg-coolgray-200">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z">
</path>
</svg>
Create / Edit
</a>
</div>
</div>
<!-- Resources Sub-dropdown (2nd level) -->
@foreach ($allEnvironments as $env)
@php
$envResources = collect()
->merge($env->applications->map(fn($app) => ['type' => 'application', 'resource' => $app]))
->merge($env->databases()->map(fn($db) => ['type' => 'database', 'resource' => $db]))
->merge($env->services->map(fn($svc) => ['type' => 'service', 'resource' => $svc]));
@endphp
@if ($envResources->count() > 0)
<div x-show="activeEnv === '{{ $env->uuid }}'"
x-transition:enter="transition ease-out duration-150" x-transition:enter-start="opacity-0"
x-transition:enter-end="opacity-100" x-transition:leave="transition ease-in duration-100"
x-transition:leave-start="opacity-100" x-transition:leave-end="opacity-0"
@mouseenter="activeEnv = '{{ $env->uuid }}'" @mouseleave="activeEnv = null; activeRes = null"
class="ml-1 flex items-start">
<div class="w-48 bg-white dark:bg-coolgray-100 rounded-md shadow-lg py-1 border border-coolgray-200 max-h-96 overflow-y-auto scrollbar">
@foreach ($envResources as $envResource)
@php
$resType = $envResource['type'];
$res = $envResource['resource'];
$resRoute = match($resType) {
'application' => route('project.application.configuration', [
'project_uuid' => $project->uuid,
'environment_uuid' => $env->uuid,
'application_uuid' => $res->uuid,
]),
'service' => route('project.service.configuration', [
'project_uuid' => $project->uuid,
'environment_uuid' => $env->uuid,
'service_uuid' => $res->uuid,
]),
'database' => route('project.database.configuration', [
'project_uuid' => $project->uuid,
'environment_uuid' => $env->uuid,
'database_uuid' => $res->uuid,
]),
};
@endphp
<div @mouseenter="activeRes = '{{ $env->uuid }}-{{ $res->uuid }}'" @mouseleave="activeRes = null">
<a href="{{ $resRoute }}"
class="flex items-center justify-between gap-2 px-4 py-2 text-sm hover:bg-coolgray-200 dark:hover:bg-coolgray-200"
title="{{ $res->name }}">
<span class="truncate">{{ $res->name }}</span>
<svg class="w-3 h-3 shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="4" d="M9 5l7 7-7 7"></path>
</svg>
</a>
</div>
@endforeach
</div>
<!-- Main Menu Sub-dropdown (3rd level) -->
@foreach ($envResources as $envResource)
@php
$resType = $envResource['type'];
$res = $envResource['resource'];
$resParams = [
'project_uuid' => $project->uuid,
'environment_uuid' => $env->uuid,
];
if ($resType === 'application') {
$resParams['application_uuid'] = $res->uuid;
} elseif ($resType === 'service') {
$resParams['service_uuid'] = $res->uuid;
} else {
$resParams['database_uuid'] = $res->uuid;
}
$resKey = $env->uuid . '-' . $res->uuid;
@endphp
<div x-show="activeRes === '{{ $resKey }}'"
x-transition:enter="transition ease-out duration-150" x-transition:enter-start="opacity-0"
x-transition:enter-end="opacity-100" x-transition:leave="transition ease-in duration-100"
x-transition:leave-start="opacity-100" x-transition:leave-end="opacity-0"
@mouseenter="activeRes = '{{ $resKey }}'" @mouseleave="activeRes = null; activeMenuEnv = null"
class="ml-1 flex items-start">
<!-- Main Menu List -->
<div class="w-48 bg-white dark:bg-coolgray-100 rounded-md shadow-lg py-1 border border-coolgray-200">
@if ($resType === 'application')
<div @mouseenter="activeMenuEnv = '{{ $resKey }}-config'" @mouseleave="activeMenuEnv = null">
<a href="{{ route('project.application.configuration', $resParams) }}"
class="flex items-center justify-between gap-2 px-4 py-2 text-sm hover:bg-coolgray-200 dark:hover:bg-coolgray-200">
<span>Configuration</span>
<svg class="w-3 h-3 shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="4" d="M9 5l7 7-7 7"></path>
</svg>
</a>
</div>
<a href="{{ route('project.application.deployment.index', $resParams) }}" class="block px-4 py-2 text-sm hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Deployments</a>
<a href="{{ route('project.application.logs', $resParams) }}" class="block px-4 py-2 text-sm hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Logs</a>
@can('canAccessTerminal')
<a href="{{ route('project.application.command', $resParams) }}" class="block px-4 py-2 text-sm hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Terminal</a>
@endcan
@elseif ($resType === 'service')
<div @mouseenter="activeMenuEnv = '{{ $resKey }}-config'" @mouseleave="activeMenuEnv = null">
<a href="{{ route('project.service.configuration', $resParams) }}"
class="flex items-center justify-between gap-2 px-4 py-2 text-sm hover:bg-coolgray-200 dark:hover:bg-coolgray-200">
<span>Configuration</span>
<svg class="w-3 h-3 shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="4" d="M9 5l7 7-7 7"></path>
</svg>
</a>
</div>
<a href="{{ route('project.service.logs', $resParams) }}" class="block px-4 py-2 text-sm hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Logs</a>
@can('canAccessTerminal')
<a href="{{ route('project.service.command', $resParams) }}" class="block px-4 py-2 text-sm hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Terminal</a>
@endcan
@else
<div @mouseenter="activeMenuEnv = '{{ $resKey }}-config'" @mouseleave="activeMenuEnv = null">
<a href="{{ route('project.database.configuration', $resParams) }}"
class="flex items-center justify-between gap-2 px-4 py-2 text-sm hover:bg-coolgray-200 dark:hover:bg-coolgray-200">
<span>Configuration</span>
<svg class="w-3 h-3 shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="4" d="M9 5l7 7-7 7"></path>
</svg>
</a>
</div>
<a href="{{ route('project.database.logs', $resParams) }}" class="block px-4 py-2 text-sm hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Logs</a>
@can('canAccessTerminal')
<a href="{{ route('project.database.command', $resParams) }}" class="block px-4 py-2 text-sm hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Terminal</a>
@endcan
@if (
$res->getMorphClass() === 'App\Models\StandalonePostgresql' ||
$res->getMorphClass() === 'App\Models\StandaloneMongodb' ||
$res->getMorphClass() === 'App\Models\StandaloneMysql' ||
$res->getMorphClass() === 'App\Models\StandaloneMariadb')
<a href="{{ route('project.database.backup.index', $resParams) }}" class="block px-4 py-2 text-sm hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Backups</a>
@endif
@endif
</div>
<!-- Configuration Sub-menu (4th level) -->
<div x-show="activeMenuEnv === '{{ $resKey }}-config'"
x-transition:enter="transition ease-out duration-150" x-transition:enter-start="opacity-0"
x-transition:enter-end="opacity-100" x-transition:leave="transition ease-in duration-100"
x-transition:leave-start="opacity-100" x-transition:leave-end="opacity-0"
@mouseenter="activeMenuEnv = '{{ $resKey }}-config'" @mouseleave="activeMenuEnv = null"
class="ml-1 w-52 bg-white dark:bg-coolgray-100 rounded-md shadow-lg py-1 border border-coolgray-200 max-h-96 overflow-y-auto scrollbar">
@if ($resType === 'application')
<a href="{{ route('project.application.configuration', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">General</a>
<a href="{{ route('project.application.environment-variables', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Environment Variables</a>
<a href="{{ route('project.application.persistent-storage', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Persistent Storage</a>
<a href="{{ route('project.application.source', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Source</a>
<a href="{{ route('project.application.servers', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Servers</a>
<a href="{{ route('project.application.scheduled-tasks.show', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Scheduled Tasks</a>
<a href="{{ route('project.application.webhooks', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Webhooks</a>
<a href="{{ route('project.application.preview-deployments', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Preview Deployments</a>
<a href="{{ route('project.application.healthcheck', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Healthcheck</a>
<a href="{{ route('project.application.rollback', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Rollback</a>
<a href="{{ route('project.application.resource-limits', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Resource Limits</a>
<a href="{{ route('project.application.resource-operations', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Resource Operations</a>
<a href="{{ route('project.application.metrics', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Metrics</a>
<a href="{{ route('project.application.tags', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Tags</a>
<a href="{{ route('project.application.advanced', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Advanced</a>
<a href="{{ route('project.application.danger', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200 text-red-500">Danger Zone</a>
@elseif ($resType === 'service')
<a href="{{ route('project.service.configuration', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">General</a>
<a href="{{ route('project.service.environment-variables', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Environment Variables</a>
<a href="{{ route('project.service.storages', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Storages</a>
<a href="{{ route('project.service.scheduled-tasks.show', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Scheduled Tasks</a>
<a href="{{ route('project.service.webhooks', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Webhooks</a>
<a href="{{ route('project.service.resource-operations', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Resource Operations</a>
<a href="{{ route('project.service.tags', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Tags</a>
<a href="{{ route('project.service.danger', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200 text-red-500">Danger Zone</a>
@else
<a href="{{ route('project.database.configuration', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">General</a>
<a href="{{ route('project.database.environment-variables', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Environment Variables</a>
<a href="{{ route('project.database.servers', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Servers</a>
<a href="{{ route('project.database.persistent-storage', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Persistent Storage</a>
<a href="{{ route('project.database.webhooks', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Webhooks</a>
<a href="{{ route('project.database.resource-limits', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Resource Limits</a>
<a href="{{ route('project.database.resource-operations', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Resource Operations</a>
<a href="{{ route('project.database.metrics', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Metrics</a>
<a href="{{ route('project.database.tags', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200">Tags</a>
<a href="{{ route('project.database.danger', $resParams) }}" class="block px-4 py-2 text-sm truncate hover:bg-coolgray-200 dark:hover:bg-coolgray-200 text-red-500">Danger Zone</a>
@endif
</div>
</div>
@endforeach
</div>
@endif
@endforeach
</div>
</div>
</li>
</ol>
@ -118,7 +372,8 @@ class="grid grid-cols-1 gap-4 pt-4 lg:grid-cols-2 xl:grid-cols-3">
<div class="max-w-full px-4 truncate box-description" x-text="item.description"></div>
<div class="max-w-full px-4 truncate box-description" x-text="item.fqdn"></div>
<template x-if="item.server_status == false">
<div class="px-4 text-xs font-bold text-error">Server is unreachable or misconfigured
<div class="px-4 text-xs font-bold text-error">Server is unreachable or
misconfigured
</div>
</template>
</div>
@ -167,7 +422,8 @@ class="grid grid-cols-1 gap-4 pt-4 lg:grid-cols-2 xl:grid-cols-3">
<div class="max-w-full px-4 truncate box-description" x-text="item.description"></div>
<div class="max-w-full px-4 truncate box-description" x-text="item.fqdn"></div>
<template x-if="item.server_status == false">
<div class="px-4 text-xs font-bold text-error">Server is unreachable or misconfigured
<div class="px-4 text-xs font-bold text-error">Server is unreachable or
misconfigured
</div>
</template>
</div>
@ -216,7 +472,8 @@ class="grid grid-cols-1 gap-4 pt-4 lg:grid-cols-2 xl:grid-cols-3">
<div class="max-w-full px-4 truncate box-description" x-text="item.description"></div>
<div class="max-w-full px-4 truncate box-description" x-text="item.fqdn"></div>
<template x-if="item.server_status == false">
<div class="px-4 text-xs font-bold text-error">Server is unreachable or misconfigured
<div class="px-4 text-xs font-bold text-error">Server is unreachable or
misconfigured
</div>
</template>
</div>