diff --git a/config/clusev.php b/config/clusev.php index a9d35aa..37fb1e1 100644 --- a/config/clusev.php +++ b/config/clusev.php @@ -19,6 +19,11 @@ return [ // is the fallback so a domain set during install still gets automatic TLS. 'domain' => env('APP_DOMAIN'), + // Public documentation site. The dashboard's "Hilfe" entry (sidebar + command palette + + // the `g h` shortcut) opens this instead of duplicating docs in-panel. Canonical for every + // install; env-overridable for a private/mirrored docs host. + 'docs_url' => env('CLUSEV_DOCS_URL', 'https://docs.clusev.com'), + // Update source. Defaults to the PUBLIC repo (safe to ship — it is public). install.sh overrides // it via CLUSEV_REPOSITORY, derived from the clone origin: dev points at Gitea, staging at the // GitHub-private mirror, public users at the public repo. Private (Gitea/GitHub-private) URLs live diff --git a/resources/js/app.js b/resources/js/app.js index 91af45f..e0b5a94 100644 --- a/resources/js/app.js +++ b/resources/js/app.js @@ -525,7 +525,9 @@ document.addEventListener('alpine:init', () => { // translated via __()), so the palette stays in sync with the active locale. // CMDK_GO maps leader-key mnemonics to routes (i=dIenste, l=Log, // e=Einstellungen, y=sYstem — d/s already taken) and stays in JS. - const CMDK_GO = { d: '/', s: '/servers', i: '/services', f: '/files', l: '/audit', e: '/settings', y: '/system', v: '/versions', h: '/help', t: '/terminal' }; + // `h` (Help) is intentionally absent — it resolves via the config-driven nav list in go() + // so it can point at the external docs URL instead of an in-app route. + const CMDK_GO = { d: '/', s: '/servers', i: '/services', f: '/files', l: '/audit', e: '/settings', y: '/system', v: '/versions', t: '/terminal' }; window.Alpine.data('cmdk', (nav = [], actions = [], servers = [], failMsg = '') => ({ nav, @@ -613,6 +615,8 @@ document.addEventListener('alpine:init', () => { navigate(href) { this.close(); + // Absolute URLs (e.g. the online docs) open in a new tab; in-app routes use SPA nav. + if (/^https?:\/\//i.test(href)) { window.open(href, '_blank', 'noopener'); return; } if (window.Livewire?.navigate) window.Livewire.navigate(href); else window.location.href = href; }, @@ -629,7 +633,11 @@ document.addEventListener('alpine:init', () => { }, go(key) { - if (CMDK_GO[key]) this.navigate(CMDK_GO[key]); + if (CMDK_GO[key]) { this.navigate(CMDK_GO[key]); return; } + // Keys not in the static map resolve via the (translated, config-driven) nav list — + // e.g. "g h" → the Help entry, whose href points at the online docs. + const item = this.nav.find((n) => n.hint === `g ${key}`); + if (item?.href) this.navigate(item.href); }, onKey(e) { diff --git a/resources/views/components/command-palette.blade.php b/resources/views/components/command-palette.blade.php index 6185b51..57150fe 100644 --- a/resources/views/components/command-palette.blade.php +++ b/resources/views/components/command-palette.blade.php @@ -28,7 +28,7 @@ ['label' => __('shell.nav_settings'), 'href' => '/settings', 'hint' => 'g e'], ['label' => __('shell.nav_system'), 'href' => '/system', 'hint' => 'g y'], ['label' => __('shell.nav_versions'), 'href' => '/versions', 'hint' => 'g v'], - ['label' => __('shell.nav_help'), 'href' => '/help', 'hint' => 'g h'], + ['label' => __('shell.nav_help'), 'href' => config('clusev.docs_url'), 'hint' => 'g h'], ]; $actions = [ diff --git a/resources/views/components/sidebar.blade.php b/resources/views/components/sidebar.blade.php index 674957a..99d4c18 100644 --- a/resources/views/components/sidebar.blade.php +++ b/resources/views/components/sidebar.blade.php @@ -45,7 +45,8 @@ {{ __('release.nav') }} @endif - {{ __('shell.nav_help') }} + {{-- Help opens the online docs (docs.clusev.com) in a new tab — no in-panel duplication. --}} + {{ __('shell.nav_help') }} {{-- User --}}