coolify/resources/views/components/navbar.blade.php
rosslh d95d2a6c0c chore: remove broken feedback form and all entrypoints
The feedback form relies on instance SMTP being configured, which
MapleDeploy customers won't do. Without SMTP it silently logs to
the server and shows a misleading success message. Removed the
navbar button, onboarding modal, subscription page link, API
endpoint, and all associated dead code.
2026-02-17 16:02:01 -08:00

366 lines
24 KiB
PHP

<nav class="flex flex-col flex-1 px-2 bg-white border-r dark:border-coolgray-200 border-neutral-300 dark:bg-base"
x-data="{
switchWidth() {
if (this.full === 'full') {
localStorage.setItem('pageWidth', 'center');
} else {
localStorage.setItem('pageWidth', 'full');
}
window.location.reload();
},
setZoom(zoom) {
localStorage.setItem('zoom', zoom);
window.location.reload();
},
init() {
this.full = localStorage.getItem('pageWidth');
this.zoom = localStorage.getItem('zoom');
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', e => {
const userSettings = localStorage.getItem('theme');
if (userSettings !== 'system') {
return;
}
if (e.matches) {
document.documentElement.classList.add('dark');
} else {
document.documentElement.classList.remove('dark');
}
});
this.queryTheme();
this.checkZoom();
},
setTheme(type) {
this.theme = type;
localStorage.setItem('theme', type);
this.queryTheme();
},
queryTheme() {
const darkModePreference = window.matchMedia('(prefers-color-scheme: dark)').matches;
const userSettings = localStorage.getItem('theme') || 'dark';
localStorage.setItem('theme', userSettings);
if (userSettings === 'dark') {
document.documentElement.classList.add('dark');
this.theme = 'dark';
} else if (userSettings === 'light') {
document.documentElement.classList.remove('dark');
this.theme = 'light';
} else if (darkModePreference) {
this.theme = 'system';
document.documentElement.classList.add('dark');
} else if (!darkModePreference) {
this.theme = 'system';
document.documentElement.classList.remove('dark');
}
},
checkZoom() {
if (this.zoom === null) {
this.setZoom(100);
}
if (this.zoom === '90') {
const style = document.createElement('style');
style.textContent = `
html {
font-size: 93.75%;
}
:root {
--vh: 1vh;
}
@media (min-width: 1024px) {
html {
font-size: 87.5%;
}
}
`;
document.head.appendChild(style);
}
}
}">
<div class="flex lg:pt-6 pt-4 pb-4 pl-2">
{{-- MapleDeploy branding --}}
<div class="flex flex-col w-full">
<a href="/" {{ wireNavigate() }} class="hover:opacity-80 transition-opacity">
<img src="https://mapledeploy.ca/api/logo/lockup?height=40" alt="MapleDeploy" class="h-6 w-auto dark:hidden" />
<img src="https://mapledeploy.ca/api/logo/lockup?height=40&dark=true" alt="MapleDeploy" class="hidden h-6 w-auto dark:block" />
</a>
<span class="text-xs opacity-75 dark:text-neutral-400">Powered by Coolify</span>
</div>
<div>
<!-- Search button that triggers global search modal -->
<button @click="$dispatch('open-global-search')" type="button" title="Search (Press / or ⌘K)"
class="flex items-center gap-1.5 px-2.5 py-1.5 bg-neutral-100 dark:bg-coolgray-100 border border-neutral-300 dark:border-coolgray-200 rounded-md hover:bg-neutral-200 dark:hover:bg-coolgray-200 transition-colors">
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 text-neutral-500 dark:text-neutral-400"
fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
</svg>
<kbd
class="px-1 py-0.5 text-xs font-semibold text-neutral-500 dark:text-neutral-400 bg-neutral-200 dark:bg-coolgray-200 rounded">/</kbd>
</button>
</div>
<livewire:settings-dropdown />
</div>
<div class="px-2 pt-2 pb-7">
<livewire:switch-team />
</div>
<ul role="list" class="flex flex-col flex-1 gap-y-7">
<li class="flex-1 overflow-x-hidden">
<ul role="list" class="flex flex-col h-full space-y-1.5">
@if (isSubscribed() || !isCloud())
<li>
<a title="Dashboard" href="/" {{ wireNavigate() }}
class="{{ request()->is('/') ? 'menu-item-active menu-item' : 'menu-item' }}">
<svg xmlns="http://www.w3.org/2000/svg" class="menu-item-icon" fill="none" viewBox="0 0 24 24"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6" />
</svg>
<span class="menu-item-label">Dashboard</span>
</a>
</li>
<li>
<a title="Projects" {{ wireNavigate() }}
class="{{ request()->is('project/*') || request()->is('projects') ? 'menu-item menu-item-active' : 'menu-item' }}"
href="/projects">
<svg xmlns="http://www.w3.org/2000/svg" class="menu-item-icon" viewBox="0 0 24 24"
stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round"
stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path d="M12 4l-8 4l8 4l8 -4l-8 -4" />
<path d="M4 12l8 4l8 -4" />
<path d="M4 16l8 4l8 -4" />
</svg>
<span class="menu-item-label">Projects</span>
</a>
</li>
<li>
<a title="Servers" {{ wireNavigate() }}
class="{{ request()->is('server/*') || request()->is('servers') ? 'menu-item menu-item-active' : 'menu-item' }}"
href="/servers">
<svg xmlns="http://www.w3.org/2000/svg" class="menu-item-icon" viewBox="0 0 24 24"
stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round"
stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path
d="M3 4m0 3a3 3 0 0 1 3 -3h12a3 3 0 0 1 3 3v2a3 3 0 0 1 -3 3h-12a3 3 0 0 1 -3 -3z" />
<path d="M15 20h-9a3 3 0 0 1 -3 -3v-2a3 3 0 0 1 3 -3h12" />
<path d="M7 8v.01" />
<path d="M7 16v.01" />
<path d="M20 15l-2 3h3l-2 3" />
</svg>
<span class="menu-item-label">Servers</span>
</a>
</li>
<li>
<a title="Sources" {{ wireNavigate() }}
class="{{ request()->is('source*') ? 'menu-item-active menu-item' : 'menu-item' }}"
href="{{ route('source.all') }}">
<svg class="menu-item-icon" viewBox="0 0 15 15" xmlns="http://www.w3.org/2000/svg">
<path fill="currentColor"
d="m6.793 1.207l.353.354l-.353-.354ZM1.207 6.793l-.353-.354l.353.354Zm0 1.414l.354-.353l-.354.353Zm5.586 5.586l-.354.353l.354-.353Zm1.414 0l-.353-.354l.353.354Zm5.586-5.586l.353.354l-.353-.354Zm0-1.414l-.354.353l.354-.353ZM8.207 1.207l.354-.353l-.354.353ZM6.44.854L.854 6.439l.707.707l5.585-5.585L6.44.854ZM.854 8.56l5.585 5.585l.707-.707l-5.585-5.585l-.707.707Zm7.707 5.585l5.585-5.585l-.707-.707l-5.585 5.585l.707.707Zm5.585-7.707L8.561.854l-.707.707l5.585 5.585l.707-.707Zm0 2.122a1.5 1.5 0 0 0 0-2.122l-.707.707a.5.5 0 0 1 0 .708l.707.707ZM6.44 14.146a1.5 1.5 0 0 0 2.122 0l-.707-.707a.5.5 0 0 1-.708 0l-.707.707ZM.854 6.44a1.5 1.5 0 0 0 0 2.122l.707-.707a.5.5 0 0 1 0-.708L.854 6.44Zm6.292-4.878a.5.5 0 0 1 .708 0L8.56.854a1.5 1.5 0 0 0-2.122 0l.707.707Zm-2 1.293l1 1l.708-.708l-1-1l-.708.708ZM7.5 5a.5.5 0 0 1-.5-.5H6A1.5 1.5 0 0 0 7.5 6V5Zm.5-.5a.5.5 0 0 1-.5.5v1A1.5 1.5 0 0 0 9 4.5H8ZM7.5 4a.5.5 0 0 1 .5.5h1A1.5 1.5 0 0 0 7.5 3v1Zm0-1A1.5 1.5 0 0 0 6 4.5h1a.5.5 0 0 1 .5-.5V3Zm.646 2.854l1.5 1.5l.707-.708l-1.5-1.5l-.707.708ZM10.5 8a.5.5 0 0 1-.5-.5H9A1.5 1.5 0 0 0 10.5 9V8Zm.5-.5a.5.5 0 0 1-.5.5v1A1.5 1.5 0 0 0 12 7.5h-1Zm-.5-.5a.5.5 0 0 1 .5.5h1A1.5 1.5 0 0 0 10.5 6v1Zm0-1A1.5 1.5 0 0 0 9 7.5h1a.5.5 0 0 1 .5-.5V6ZM7 5.5v4h1v-4H7Zm.5 5.5a.5.5 0 0 1-.5-.5H6A1.5 1.5 0 0 0 7.5 12v-1Zm.5-.5a.5.5 0 0 1-.5.5v1A1.5 1.5 0 0 0 9 10.5H8Zm-.5-.5a.5.5 0 0 1 .5.5h1A1.5 1.5 0 0 0 7.5 9v1Zm0-1A1.5 1.5 0 0 0 6 10.5h1a.5.5 0 0 1 .5-.5V9Z" />
</svg>
<span class="menu-item-label">Sources</span>
</a>
</li>
<li>
<a title="Destinations" {{ wireNavigate() }}
class="{{ request()->is('destination*') ? 'menu-item-active menu-item' : 'menu-item' }}"
href="{{ route('destination.index') }}">
<svg xmlns="http://www.w3.org/2000/svg" class="menu-item-icon" viewBox="0 0 24 24">
<path fill="none" stroke="currentColor" stroke-linecap="round"
stroke-linejoin="round" stroke-width="2"
d="M9 4L3 8v12l6-3l6 3l6-4V4l-6 3l-6-3zm-2 8.001V12m4 .001V12m3-2l2 2m2 2l-2-2m0 0l2-2m-2 2l-2 2" />
</svg>
<span class="menu-item-label">Destinations</span>
</a>
</li>
<li>
<a title="S3 Storages" {{ wireNavigate() }}
class="{{ request()->is('storages*') ? 'menu-item-active menu-item' : 'menu-item' }}"
href="{{ route('storage.index') }}">
<svg xmlns="http://www.w3.org/2000/svg" class="menu-item-icon" viewBox="0 0 24 24">
<g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
stroke-width="2">
<path d="M4 6a8 3 0 1 0 16 0A8 3 0 1 0 4 6" />
<path d="M4 6v6a8 3 0 0 0 16 0V6" />
<path d="M4 12v6a8 3 0 0 0 16 0v-6" />
</g>
</svg>
<span class="menu-item-label">S3 Storages</span>
</a>
</li>
<li>
<a title="Shared variables" {{ wireNavigate() }}
class="{{ request()->is('shared-variables*') ? 'menu-item-active menu-item' : 'menu-item' }}"
href="{{ route('shared-variables.index') }}">
<svg xmlns="http://www.w3.org/2000/svg" class="menu-item-icon" viewBox="0 0 24 24">
<g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
stroke-width="2">
<path
d="M5 4C2.5 9 2.5 14 5 20M19 4c2.5 5 2.5 10 0 16M9 9h1c1 0 1 1 2.016 3.527C13 15 13 16 14 16h1" />
<path d="M8 16c1.5 0 3-2 4-3.5S14.5 9 16 9" />
</g>
</svg>
<span class="menu-item-label">Shared Variables</span>
</a>
</li>
<li>
<a title="Notifications" {{ wireNavigate() }}
class="{{ request()->is('notifications*') ? 'menu-item-active menu-item' : 'menu-item' }}"
href="{{ route('notifications.email') }}">
<svg class="menu-item-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path fill="none" stroke="currentColor" stroke-linecap="round"
stroke-linejoin="round" stroke-width="2"
d="M10 5a2 2 0 1 1 4 0a7 7 0 0 1 4 6v3a4 4 0 0 0 2 3H4a4 4 0 0 0 2-3v-3a7 7 0 0 1 4-6M9 17v1a3 3 0 0 0 6 0v-1" />
</svg>
<span class="menu-item-label">Notifications</span>
</a>
</li>
<li>
<a title="Keys & Tokens" {{ wireNavigate() }}
class="{{ request()->is('security*') ? 'menu-item-active menu-item' : 'menu-item' }}"
href="{{ route('security.private-key.index') }}">
<svg class="menu-item-icon" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path fill="none" stroke="currentColor" stroke-linecap="round"
stroke-linejoin="round" stroke-width="2"
d="m16.555 3.843l3.602 3.602a2.877 2.877 0 0 1 0 4.069l-2.643 2.643a2.877 2.877 0 0 1-4.069 0l-.301-.301l-6.558 6.558a2 2 0 0 1-1.239.578L5.172 21H4a1 1 0 0 1-.993-.883L3 20v-1.172a2 2 0 0 1 .467-1.284l.119-.13L4 17h2v-2h2v-2l2.144-2.144l-.301-.301a2.877 2.877 0 0 1 0-4.069l2.643-2.643a2.877 2.877 0 0 1 4.069 0zM15 9h.01" />
</svg>
<span class="menu-item-label">Keys & Tokens</span>
</a>
</li>
<li>
<a title="Tags" {{ wireNavigate() }}
class="{{ request()->is('tags*') ? 'menu-item-active menu-item' : 'menu-item' }}"
href="{{ route('tags.show') }}">
<svg class="menu-item-icon" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<g fill="none" stroke="currentColor" stroke-linecap="round"
stroke-linejoin="round" stroke-width="2">
<path
d="M3 8v4.172a2 2 0 0 0 .586 1.414l5.71 5.71a2.41 2.41 0 0 0 3.408 0l3.592-3.592a2.41 2.41 0 0 0 0-3.408l-5.71-5.71A2 2 0 0 0 9.172 6H5a2 2 0 0 0-2 2" />
<path d="m18 19l1.592-1.592a4.82 4.82 0 0 0 0-6.816L15 6m-8 4h-.01" />
</g>
</svg>
<span class="menu-item-label">Tags</span>
</a>
</li>
@can('canAccessTerminal')
<li>
<a title="Terminal"
class="{{ request()->is('terminal*') ? 'menu-item-active menu-item' : 'menu-item' }}"
href="{{ route('terminal') }}">
<svg class="menu-item-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"
stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round"
stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path d="M5 7l5 5l-5 5" />
<path d="M12 19l7 0" />
</svg>
<span class="menu-item-label">Terminal</span>
</a>
</li>
@endcan
<li>
<a title="Profile" {{ wireNavigate() }}
class="{{ request()->is('profile*') ? 'menu-item-active menu-item' : 'menu-item' }}"
href="{{ route('profile') }}">
<svg class="menu-item-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"
stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round"
stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path d="M12 12m-9 0a9 9 0 1 0 18 0a9 9 0 1 0 -18 0" />
<path d="M12 10m-3 0a3 3 0 1 0 6 0a3 3 0 1 0 -6 0" />
<path d="M6.168 18.849a4 4 0 0 1 3.832 -2.849h4a4 4 0 0 1 3.834 2.855" />
</svg>
<span class="menu-item-label">Profile</span>
</a>
</li>
<li>
<a title="Teams" {{ wireNavigate() }}
class="{{ request()->is('team*') ? 'menu-item-active menu-item' : 'menu-item' }}"
href="{{ route('team.index') }}">
<svg class="menu-item-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"
stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round"
stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path d="M10 13a2 2 0 1 0 4 0a2 2 0 0 0 -4 0" />
<path d="M8 21v-1a2 2 0 0 1 2 -2h4a2 2 0 0 1 2 2v1" />
<path d="M15 5a2 2 0 1 0 4 0a2 2 0 0 0 -4 0" />
<path d="M17 10h2a2 2 0 0 1 2 2v1" />
<path d="M5 5a2 2 0 1 0 4 0a2 2 0 0 0 -4 0" />
<path d="M3 13v-1a2 2 0 0 1 2 -2h2" />
</svg>
<span class="menu-item-label">Teams</span>
</a>
</li>
{{-- MapleDeploy branding: Cloud subscription menu removed --}}
@if (isInstanceAdmin())
<li>
<a title="Settings" {{ wireNavigate() }}
class="{{ request()->is('settings*') ? 'menu-item-active menu-item' : 'menu-item' }}"
href="/settings">
<svg class="menu-item-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"
stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round"
stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path
d="M10.325 4.317c.426 -1.756 2.924 -1.756 3.35 0a1.724 1.724 0 0 0 2.573 1.066c1.543 -.94 3.31 .826 2.37 2.37a1.724 1.724 0 0 0 1.065 2.572c1.756 .426 1.756 2.924 0 3.35a1.724 1.724 0 0 0 -1.066 2.573c.94 1.543 -.826 3.31 -2.37 2.37a1.724 1.724 0 0 0 -2.572 1.065c-.426 1.756 -2.924 1.756 -3.35 0a1.724 1.724 0 0 0 -2.573 -1.066c-1.543 .94 -3.31 -.826 -2.37 -2.37a1.724 1.724 0 0 0 -1.065 -2.572c-1.756 -.426 -1.756 -2.924 0 -3.35a1.724 1.724 0 0 0 1.066 -2.573c-.94 -1.543 .826 -3.31 2.37 -2.37c1 .608 2.296 .07 2.572 -1.065z" />
<path d="M9 12a3 3 0 1 0 6 0a3 3 0 0 0 -6 0" />
</svg>
<span class="menu-item-label">Settings</span>
</a>
</li>
@endif
{{-- MapleDeploy branding: Cloud admin menu removed --}}
<div class="flex-1"></div>
@if (isInstanceAdmin() && !isCloud())
@persist('upgrade')
<li>
<livewire:upgrade />
</li>
@endpersist
@endif
{{-- <li>
<a title="Onboarding"
class="{{ request()->is('onboarding*') ? 'menu-item-active menu-item' : 'menu-item' }}"
href="{{ route('onboarding') }}">
<svg class="menu-item-icon" viewBox="0 0 256 256" xmlns="http://www.w3.org/2000/svg">
<path fill="currentColor"
d="M224 128a8 8 0 0 1-8 8h-88a8 8 0 0 1 0-16h88a8 8 0 0 1 8 8m-96-56h88a8 8 0 0 0 0-16h-88a8 8 0 0 0 0 16m88 112h-88a8 8 0 0 0 0 16h88a8 8 0 0 0 0-16M82.34 42.34L56 68.69L45.66 58.34a8 8 0 0 0-11.32 11.32l16 16a8 8 0 0 0 11.32 0l32-32a8 8 0 0 0-11.32-11.32m0 64L56 132.69l-10.34-10.35a8 8 0 0 0-11.32 11.32l16 16a8 8 0 0 0 11.32 0l32-32a8 8 0 0 0-11.32-11.32m0 64L56 196.69l-10.34-10.35a8 8 0 0 0-11.32 11.32l16 16a8 8 0 0 0 11.32 0l32-32a8 8 0 0 0-11.32-11.32" />
</svg>
Onboarding
</a>
</li> --}}
{{-- MapleDeploy branding: AGPL source code link (license requirement) --}}
<li>
<a title="Source code (AGPL-3.0)" class="menu-item" href="https://forgejo.mapledeploy.ca/rosslh/coolify"
target="_blank">
<svg class="menu-item-icon" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path fill="none" stroke="currentColor" stroke-linecap="round"
stroke-linejoin="round" stroke-width="2"
d="M16 18l6-6-6-6M8 6l-6 6 6 6" />
</svg>
<span class="menu-item-label">Source code</span>
</a>
</li>
@endif
<li>
<form action="/logout" method="POST">
@csrf
<button title="Logout" type="submit" class="gap-2 mb-6 menu-item">
<svg class="menu-item-icon mr-1" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path fill="currentColor"
d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2a9.985 9.985 0 0 1 8 4h-2.71a8 8 0 1 0 .001 12h2.71A9.985 9.985 0 0 1 12 22m7-6v-3h-8v-2h8V8l5 4z" />
</svg>
<span>Logout</span>
</button>
</form>
</li>
</ul>
</li>
</ul>
</nav>