From 6b637b28072c008f7f67b14d93c23e3bc68fc92c Mon Sep 17 00:00:00 2001 From: Saeed Vaziry Date: Fri, 2 Oct 2026 11:17:50 +0200 Subject: [PATCH 1/2] Remove Ziggy and use frontend URL paths --- .claude/skills/inertia-table/SKILL.md | 6 +- .github/instructions/frontend.instructions.md | 5 +- .prettierignore | 1 - app/Actions/Ziggy/GetZiggyRoutes.php | 74 --------------- .../Controllers/ZiggyRoutesController.php | 31 ------- app/Http/Middleware/HandleInertiaRequests.php | 9 -- composer.json | 3 +- composer.lock | 72 +-------------- config/inertia-table.php | 5 ++ docs/4.x/prologue/release-notes.md | 7 +- resources/js/components/app-command.tsx | 11 +-- .../js/components/app-sidebar-nested.tsx | 56 ++++++------ resources/js/components/app-sidebar.tsx | 32 +++---- .../components/dialogs/log-viewer-dialog.tsx | 2 +- resources/js/components/project-select.tsx | 2 +- resources/js/components/project-switch.tsx | 2 +- resources/js/components/server-banners.tsx | 6 +- resources/js/components/server-switch.tsx | 2 +- resources/js/components/site-banners.tsx | 18 ++-- resources/js/components/site-switch.tsx | 2 +- resources/js/components/user-menu-content.tsx | 4 +- resources/js/components/vito-table.tsx | 9 +- resources/js/hooks/use-log-content.ts | 2 +- resources/js/layouts/admin/layout.tsx | 8 +- resources/js/layouts/auth/layout.tsx | 2 +- resources/js/layouts/database/layout.tsx | 4 +- resources/js/layouts/network/layout.tsx | 14 +-- resources/js/layouts/server/layout.tsx | 90 +++++++++---------- resources/js/layouts/settings/layout.tsx | 18 ++-- resources/js/lib/utils.ts | 3 +- .../js/pages/api-keys/components/columns.tsx | 2 +- .../api-keys/components/create-api-key.tsx | 2 +- .../components/app-with-deployment.tsx | 12 +-- .../components/auto-deployment.tsx | 7 +- .../pages/application/components/deploy.tsx | 2 +- .../components/deployment-script.tsx | 4 +- .../js/pages/application/components/env.tsx | 22 ++--- .../application/components/load-balancer.tsx | 2 +- .../backups/components/backup-actions.tsx | 6 +- .../backups/components/create-backup.tsx | 2 +- .../pages/backups/components/edit-backup.tsx | 2 +- .../pages/backups/components/file-columns.tsx | 2 +- .../backups/components/restore-backup.tsx | 6 +- resources/js/pages/backups/files.tsx | 2 +- .../js/pages/commands/components/columns.tsx | 8 +- .../commands/components/create-command.tsx | 2 +- .../commands/components/edit-command.tsx | 2 +- .../js/pages/commands/components/execute.tsx | 2 +- resources/js/pages/commands/show.tsx | 4 +- .../js/pages/cronjobs/components/columns.tsx | 17 +--- .../js/pages/cronjobs/components/form.tsx | 11 +-- .../cronjobs/components/sync-cronjobs.tsx | 2 +- .../components/create-database-user.tsx | 2 +- .../components/database-user-select.tsx | 2 +- .../components/edit-database-user.tsx | 2 +- .../database-users/components/link-dialog.tsx | 2 +- .../database-users/components/sync-users.tsx | 2 +- resources/js/pages/database-users/index.tsx | 2 +- .../databases/components/create-database.tsx | 6 +- .../databases/components/database-select.tsx | 2 +- .../js/pages/databases/components/delete.tsx | 2 +- .../databases/components/sync-databases.tsx | 2 +- .../components/connect-dns-provider.tsx | 2 +- .../pages/dns-providers/components/delete.tsx | 2 +- .../dns-providers/components/edit-dialog.tsx | 2 +- .../pages/domains/components/add-domain.tsx | 10 +-- .../js/pages/domains/components/columns.tsx | 4 +- .../domains/components/record-columns.tsx | 2 +- .../pages/domains/components/record-form.tsx | 4 +- .../pages/domains/components/sync-records.tsx | 2 +- resources/js/pages/domains/show.tsx | 4 +- .../js/pages/firewall/components/delete.tsx | 2 +- .../js/pages/firewall/components/form.tsx | 4 +- resources/js/pages/github-app/index.tsx | 8 +- .../components/create-hosted-domain.tsx | 5 +- .../components/edit-hosted-domain.tsx | 6 +- .../hosted-domains/hooks/use-ssl-matching.ts | 2 +- resources/js/pages/hosted-domains/index.tsx | 40 +++------ .../pages/monitoring/components/actions.tsx | 2 +- .../components/data-retention-dialog.tsx | 2 +- .../monitoring/components/metrics-cards.tsx | 6 +- .../monitoring/components/use-metrics.ts | 6 +- resources/js/pages/monitoring/index.tsx | 2 +- .../js/pages/networks/components/add-peer.tsx | 2 +- .../pages/networks/components/add-server.tsx | 2 +- .../networks/components/create-network.tsx | 2 +- .../components/edit-network-server.tsx | 2 +- .../components/firewall-rule-form.tsx | 4 +- .../pages/networks/components/log-columns.tsx | 2 +- .../pages/networks/components/peer-config.tsx | 4 +- .../networks/components/private-ip-select.tsx | 2 +- resources/js/pages/networks/firewall.tsx | 2 +- resources/js/pages/networks/index.tsx | 4 +- resources/js/pages/networks/peers.tsx | 6 +- resources/js/pages/networks/servers.tsx | 6 +- resources/js/pages/networks/settings.tsx | 4 +- .../connect-notification-channel.tsx | 2 +- .../components/delete.tsx | 2 +- .../components/edit-dialog.tsx | 2 +- .../js/pages/php/components/default-cli.tsx | 2 +- .../php/components/extensions-dialog.tsx | 2 +- .../js/pages/php/components/ini-dialog.tsx | 13 +-- .../plugins/components/check-updates.tsx | 2 +- .../pages/plugins/components/delete-logs.tsx | 2 +- .../js/pages/plugins/components/disable.tsx | 2 +- .../js/pages/plugins/components/enable.tsx | 2 +- .../plugins/components/install-dialog.tsx | 2 +- .../js/pages/plugins/components/install.tsx | 2 +- .../plugins/components/quick-install.tsx | 2 +- .../js/pages/plugins/components/uninstall.tsx | 2 +- .../js/pages/plugins/components/update.tsx | 2 +- .../js/pages/redirects/components/columns.tsx | 2 +- .../redirects/components/create-redirect.tsx | 2 +- .../redirects/components/edit-redirect.tsx | 2 +- .../js/pages/scripts/components/columns.tsx | 6 +- .../js/pages/scripts/components/execute.tsx | 2 +- .../scripts/components/execution-columns.tsx | 2 +- .../js/pages/scripts/components/form.tsx | 4 +- resources/js/pages/scripts/show.tsx | 4 +- .../security/components/fail2ban-form.tsx | 4 +- resources/js/pages/security/index.tsx | 14 +-- .../components/feature-action.tsx | 6 +- resources/js/pages/server-features/index.tsx | 2 +- .../pages/server-logs/components/columns.tsx | 6 +- .../js/pages/server-logs/components/form.tsx | 4 +- .../server-logs/components/instant-logs.tsx | 4 +- .../js/pages/server-logs/components/logs.tsx | 2 +- resources/js/pages/server-logs/services.tsx | 9 +- .../server-network/components/delete.tsx | 2 +- .../pages/server-network/components/form.tsx | 2 +- .../server-network/components/set-primary.tsx | 2 +- resources/js/pages/server-network/index.tsx | 2 +- .../components/connect-server-provider.tsx | 2 +- .../server-providers/components/delete.tsx | 2 +- .../components/edit-dialog.tsx | 2 +- .../components/server-provider-select.tsx | 2 +- resources/js/pages/server-settings/index.tsx | 2 +- .../server-ssh-keys/components/delete.tsx | 2 +- .../server-ssh-keys/components/deploy-key.tsx | 2 +- .../components/activate-dialog.tsx | 2 +- .../pages/server-ssls/components/columns.tsx | 4 +- .../components/create-server-ssl.tsx | 2 +- .../js/pages/servers/components/actions.tsx | 10 +-- .../servers/components/create-server.tsx | 8 +- .../servers/components/delete-server.tsx | 2 +- .../js/pages/servers/components/header.tsx | 4 +- .../servers/components/server-select.tsx | 2 +- .../js/pages/servers/components/templates.tsx | 8 +- .../servers/components/transfer-server.tsx | 2 +- resources/js/pages/servers/console.tsx | 2 +- resources/js/pages/servers/index.tsx | 2 +- .../js/pages/services/components/action.tsx | 2 +- .../components/config-file-dialog.tsx | 12 +-- .../js/pages/services/components/install.tsx | 2 +- .../services/components/networking-dialog.tsx | 10 +-- .../services/components/resync-stats.tsx | 2 +- .../components/service-version-select.tsx | 4 +- .../pages/services/components/uninstall.tsx | 2 +- resources/js/pages/services/index.tsx | 2 +- .../components/feature-action.tsx | 7 +- resources/js/pages/site-features/index.tsx | 4 +- .../site-settings/components/basic-auth.tsx | 2 +- .../pages/site-settings/components/branch.tsx | 2 +- .../site-settings/components/delete-site.tsx | 2 +- .../components/php-settings-dialog.tsx | 2 +- .../site-settings/components/php-version.tsx | 2 +- .../pages/site-settings/components/port.tsx | 2 +- .../components/source-control.tsx | 2 +- .../components/start-command.tsx | 2 +- .../site-settings/components/stats-toggle.tsx | 3 +- .../components/vhost-preview.tsx | 5 +- .../pages/site-settings/components/vhost.tsx | 11 +-- .../components/web-directory.tsx | 2 +- .../site-tooling/components/tooling-table.tsx | 4 +- .../js/pages/sites/components/create-site.tsx | 4 +- .../sites/components/isolated-user-select.tsx | 2 +- .../js/pages/sites/components/site-select.tsx | 2 +- .../pages/sites/components/use-site-stats.ts | 2 +- resources/js/pages/sites/index.tsx | 2 +- resources/js/pages/sites/stats.tsx | 2 +- .../source-controls/components/columns.tsx | 2 +- .../components/connect-source-control.tsx | 2 +- .../components/edit-dialog.tsx | 2 +- .../components/select-branch.tsx | 7 +- .../components/select-repo.tsx | 4 +- .../components/source-control-select.tsx | 2 +- resources/js/pages/source-controls/index.tsx | 2 +- .../pages/ssh-keys/components/add-ssh-key.tsx | 2 +- .../js/pages/ssh-keys/components/delete.tsx | 2 +- .../ssh-keys/components/ssh-key-select.tsx | 2 +- .../components/connect-storage-provider.tsx | 8 +- .../storage-providers/components/delete.tsx | 2 +- .../components/edit-dialog.tsx | 2 +- .../components/storage-provider-select.tsx | 2 +- .../js/pages/users/components/delete-user.tsx | 2 +- .../js/pages/users/components/user-form.tsx | 4 +- .../js/pages/users/components/user-select.tsx | 2 +- .../pages/vito-settings/components/export.tsx | 2 +- .../pages/vito-settings/components/import.tsx | 2 +- .../js/pages/workers/components/columns.tsx | 2 +- .../pages/workers/components/env-dialog.tsx | 8 +- .../js/pages/workers/components/form.tsx | 4 +- .../pages/workers/components/logs-dialog.tsx | 2 +- .../workers/components/worker-row-actions.tsx | 2 +- resources/js/pages/workers/index.tsx | 5 +- .../pages/workflow-runs/components/logs.tsx | 2 +- resources/js/pages/workflow-runs/index.tsx | 6 +- resources/js/pages/workflow-runs/show.tsx | 6 +- .../workflows/components/create-workflow.tsx | 2 +- .../workflows/components/delete-workflow.tsx | 2 +- .../js/pages/workflows/components/run.tsx | 2 +- resources/js/pages/workflows/index.tsx | 4 +- resources/js/pages/workflows/show.tsx | 2 +- resources/js/ssr.tsx | 23 +---- resources/js/stores/bootstrap-store.ts | 2 +- resources/js/stores/socket-store.ts | 2 +- resources/js/types/global.d.ts | 5 -- resources/js/types/index.d.ts | 2 - resources/views/app.blade.php | 1 - tests/ArchTestCase.php | 2 - tests/Feature/Auth/AuthenticationTest.php | 19 +++- tests/Feature/ServerTest.php | 19 ++++ tsconfig.json | 3 - vite.config.ts | 1 - 224 files changed, 491 insertions(+), 782 deletions(-) delete mode 100644 app/Actions/Ziggy/GetZiggyRoutes.php delete mode 100644 app/Http/Controllers/ZiggyRoutesController.php create mode 100644 config/inertia-table.php delete mode 100644 resources/js/types/global.d.ts diff --git a/.claude/skills/inertia-table/SKILL.md b/.claude/skills/inertia-table/SKILL.md index 52c9bd6a7..b86409fcb 100644 --- a/.claude/skills/inertia-table/SKILL.md +++ b/.claude/skills/inertia-table/SKILL.md @@ -99,7 +99,7 @@ export default function Index({ servers }: { servers: InertiaTableData }) { tableData={servers} actions={(row) => ( <> - + )} @@ -213,7 +213,7 @@ Global hooks (`Table::globalBeforeQuery`, `Table::globalAfterData`) already exis **Settings → frontend hooks:** `->withSettings(['polling' => 5])` ships arbitrary data; on the React side register a hook with `registerTableHook('polling', ({ value, refresh }) => { const id = setInterval(refresh, value*1000); return () => clearInterval(id); })`. -**Row click to detail page:** ` router.visit(route('servers.show', row.id as number))} />`. The component already skips clicks on `a, button, input, select, textarea, [role="button"]`. +**Row click to detail page:** `` router.visit(`/servers/${row.id}`)} />``. The component already skips clicks on `a, button, input, select, textarea, [role="button"]`. **External search input** (e.g. in a page header instead of the toolbar): pass `searchRef={inputRef}` — the built-in search bar hides and the table watches that input. @@ -222,7 +222,7 @@ Global hooks (`Table::globalBeforeQuery`, `Table::globalAfterData`) already exis 1. **Every row needs an `id`.** Add `Column::data('id')` if `id` isn't otherwise included. 2. **Dot-notation columns get a `_`-prefixed name** in the row payload (e.g. `provider.name` → row key `_provider_name`). Use the column's display value; don't reach into the row by the dotted path from the frontend. 3. **Sort key vs display name:** for computed columns, set `->accessor('real_db_column')` or sort will target the wrong field. -4. **Ziggy** is a peer dep — Vito4 uses it, so leave `use_ziggy => true`. If you ever turn it off, link columns send pre-resolved URLs. +4. **Link URLs** are resolved server-side. Keep `use_ziggy => false` in `config/inertia-table.php`; frontend link cells read the pre-resolved URL from `href_key`. 5. **TypeScript prop type** for an Inertia page is `InertiaTableData`, not the row type. Cast `row.id` (it's `string | number`). 6. **`ActionsColumn`** does nothing on its own — you must pass `actions={(row) => ...}` to ``. 7. **`registerCellComponent` / `registerIcon` must run before render.** Put them in `app.tsx` (or a module imported there), not inside the page component. diff --git a/.github/instructions/frontend.instructions.md b/.github/instructions/frontend.instructions.md index 2156a598f..d4c81174c 100644 --- a/.github/instructions/frontend.instructions.md +++ b/.github/instructions/frontend.instructions.md @@ -7,6 +7,7 @@ description: "React, Inertia, Tailwind v4, and TypeScript frontend standards" ## Inertia & React +- Use root-relative URL paths (`/settings/profile`, `/servers/${server.id}`) for frontend navigation and requests. Encode string path segments and pass query parameters via Axios `params` or `URLSearchParams`. - Inertia pages live in `resources/js/pages/`. Use `Inertia::render()` from Laravel controllers. - React components in `resources/js/components/`. Use functional components and hooks. - Use the `useForm` helper for forms — follow existing patterns in the codebase. @@ -37,7 +38,7 @@ dialog.confirm.open({ variant: 'destructive', confirmLabel: 'Delete', method: 'delete', - url: route('firewall.destroy', { server: rule.server_id, firewallRule: rule }), + url: `/servers/${rule.server_id}/firewall/${rule.id}`, }); ``` @@ -67,7 +68,7 @@ export default function FirewallRuleForm({ const form = useForm({ /* seed from props */ }); const submit = (e: FormEvent) => { e.preventDefault(); - form.post(route('firewall.store', { server: serverId }), { onSuccess: () => onOpenChange(false) }); + form.post(`/servers/${serverId}/firewall`, { onSuccess: () => onOpenChange(false) }); }; return ( diff --git a/.prettierignore b/.prettierignore index db8957b31..3409b01ac 100644 --- a/.prettierignore +++ b/.prettierignore @@ -15,5 +15,4 @@ sail resources/views/ssh/ resources/views/wireguard/ resources/views/scribe/ -resources/js/ziggy.js resources/views/mail/* diff --git a/app/Actions/Ziggy/GetZiggyRoutes.php b/app/Actions/Ziggy/GetZiggyRoutes.php deleted file mode 100644 index d6422f883..000000000 --- a/app/Actions/Ziggy/GetZiggyRoutes.php +++ /dev/null @@ -1,74 +0,0 @@ -cachedScript !== null) { - return $this->cachedScript; - } - - if (! app()->isProduction()) { - return $this->cachedScript = $this->buildScript(); - } - - return $this->cachedScript = Cache::rememberForever( - self::SCRIPT_CACHE_KEY, - fn (): string => $this->buildScript(), - ); - } - - public function version(): string - { - if ($this->cachedVersion !== null) { - return $this->cachedVersion; - } - - if (! app()->isProduction()) { - return $this->cachedVersion = substr(md5($this->script()), 0, 16); - } - - return $this->cachedVersion = Cache::rememberForever( - self::VERSION_CACHE_KEY, - fn (): string => substr(md5($this->script()), 0, 16), - ); - } - - public function url(): string - { - return route('ziggy.routes', ['version' => $this->version()]); - } - - public static function forgetCache(): void - { - Cache::forget(self::SCRIPT_CACHE_KEY); - Cache::forget(self::VERSION_CACHE_KEY); - } - - private function buildScript(): string - { - $payload = (new Ziggy)->toJson(); - $routeFunctionPath = base_path('vendor/tightenco/ziggy/dist/route.umd.js'); - $routeFunction = file_get_contents($routeFunctionPath); - - if ($routeFunction === false) { - throw new RuntimeException("Failed to read Ziggy route function from {$routeFunctionPath}"); - } - - return "window.Ziggy={$payload};{$routeFunction}"; - } -} diff --git a/app/Http/Controllers/ZiggyRoutesController.php b/app/Http/Controllers/ZiggyRoutesController.php deleted file mode 100644 index f5d608adf..000000000 --- a/app/Http/Controllers/ZiggyRoutesController.php +++ /dev/null @@ -1,31 +0,0 @@ -script(), 200, [ - 'Content-Type' => 'application/javascript; charset=utf-8', - 'Cache-Control' => 'public, max-age=31536000, immutable', - ]); - } -} diff --git a/app/Http/Middleware/HandleInertiaRequests.php b/app/Http/Middleware/HandleInertiaRequests.php index 795233003..8f67af10e 100644 --- a/app/Http/Middleware/HandleInertiaRequests.php +++ b/app/Http/Middleware/HandleInertiaRequests.php @@ -15,7 +15,6 @@ use Illuminate\Foundation\Inspiring; use Illuminate\Http\Request; use Inertia\Middleware; -use Tighten\Ziggy\Ziggy; class HandleInertiaRequests extends Middleware { @@ -49,8 +48,6 @@ public function share(Request $request): array { [$message, $author] = str(Inspiring::quotes()->random())->explode('-'); - $ssrEnabled = (bool) config('inertia.ssr.enabled'); - /** @var ?User $user */ $user = $request->user(); $currentProject = $user?->currentProject; @@ -111,12 +108,6 @@ public function share(Request $request): array ] : null, 'csrf_token' => csrf_token(), 'bootstrap_version' => app(GetBootstrap::class)->version(), - ...($ssrEnabled ? [ - 'ziggy' => fn (): array => [ - ...(new Ziggy)->toArray(), - 'location' => $request->url(), - ], - ] : []), 'flash' => [ 'success' => fn () => $request->session()->get('success'), 'error' => fn () => $request->session()->get('error'), diff --git a/composer.json b/composer.json index 5345477dc..95eabdf58 100644 --- a/composer.json +++ b/composer.json @@ -28,8 +28,7 @@ "react/event-loop": "^1.5", "react/socket": "^1.17", "spatie/laravel-route-attributes": "^1.24", - "symfony/yaml": "^8.0", - "tightenco/ziggy": "^2.5" + "symfony/yaml": "^8.0" }, "require-dev": { "fakerphp/faker": "^1.9.1", diff --git a/composer.lock b/composer.lock index e348fa36f..f4d876edc 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "ffa2c365bbb1da4e8d29787360bf8d98", + "content-hash": "c0403521d2ec32c379f59ccfd95e7898", "packages": [ { "name": "aws/aws-crt-php", @@ -8877,76 +8877,6 @@ ], "time": "2026-08-21T12:16:08+00:00" }, - { - "name": "tightenco/ziggy", - "version": "v2.6.4", - "source": { - "type": "git", - "url": "https://github.com/tighten/ziggy.git", - "reference": "c32a3eaad1574df8b953281680bba89bd3217dc2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/tighten/ziggy/zipball/c32a3eaad1574df8b953281680bba89bd3217dc2", - "reference": "c32a3eaad1574df8b953281680bba89bd3217dc2", - "shasum": "" - }, - "require": { - "ext-json": "*", - "laravel/framework": ">=9.0", - "php": ">=8.1" - }, - "require-dev": { - "laravel/folio": "^1.1", - "orchestra/testbench": "^8.0 || ^9.0 || ^10.0 || ^11.0", - "pestphp/pest": "^2.0 || ^3.0 || ^4.0", - "pestphp/pest-plugin-laravel": "^2.0 || ^3.0 || ^4.0" - }, - "type": "library", - "extra": { - "laravel": { - "providers": [ - "Tighten\\Ziggy\\ZiggyServiceProvider" - ] - } - }, - "autoload": { - "psr-4": { - "Tighten\\Ziggy\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Daniel Coulbourne", - "email": "daniel@tighten.co" - }, - { - "name": "Jake Bathman", - "email": "jake@tighten.co" - }, - { - "name": "Jacob Baker-Kretzmar", - "email": "jacob@tighten.co" - } - ], - "description": "Use your Laravel named routes in JavaScript.", - "homepage": "https://github.com/tighten/ziggy", - "keywords": [ - "Ziggy", - "javascript", - "laravel", - "routes" - ], - "support": { - "issues": "https://github.com/tighten/ziggy/issues", - "source": "https://github.com/tighten/ziggy/tree/v2.6.4" - }, - "time": "2026-08-18T17:28:45+00:00" - }, { "name": "tijsverkoyen/css-to-inline-styles", "version": "v2.4.0", diff --git a/config/inertia-table.php b/config/inertia-table.php new file mode 100644 index 000000000..f1d19d3b5 --- /dev/null +++ b/config/inertia-table.php @@ -0,0 +1,5 @@ + false, +]; diff --git a/docs/4.x/prologue/release-notes.md b/docs/4.x/prologue/release-notes.md index 5d9417607..1e091cbd7 100644 --- a/docs/4.x/prologue/release-notes.md +++ b/docs/4.x/prologue/release-notes.md @@ -8,9 +8,10 @@ releases. ### Inertia context shrinking -Inertia responses previously shipped ~120 KB+ of mostly-static shared data on every request (the -Ziggy route table, the provider/service catalogue, and more). A new cached bootstrap endpoint now -serves this once and hydrates it on the frontend, cutting typical responses down to a few KB. +Inertia responses previously shipped ~120 KB+ of mostly-static shared data on every request. The +frontend now uses URL paths directly, without a client-side route catalogue or route-script cache. +A cached bootstrap endpoint serves the provider/service catalogue once and hydrates it on the +frontend, cutting typical responses down to a few KB. ## Realtime websocket Updates diff --git a/resources/js/components/app-command.tsx b/resources/js/components/app-command.tsx index 3b02f5cf2..389631b25 100644 --- a/resources/js/components/app-command.tsx +++ b/resources/js/components/app-command.tsx @@ -46,7 +46,7 @@ export default function AppCommand() { const query = useQuery({ queryKey: ['search'], queryFn: async () => { - const response = await axios.get(route('search', { query: queryText })); + const response = await axios.get('/search', { params: { query: queryText } }); return response.data.data; }, retry: false, @@ -100,16 +100,13 @@ export default function AppCommand() { value={`result-${index}`} onSelect={() => { if (result.type === 'server') { - router.post(route('servers.switch', { server: result.id })); + router.post(`/servers/${result.id}/switch`); } else if (result.type === 'project') { router.patch( - route('projects.switch', { - project: result.id, - currentPath: window.location.pathname, - }), + `/settings/projects/switch/${result.id}?${new URLSearchParams({ currentPath: window.location.pathname })}`, ); } else if (result.type === 'site') { - router.post(route('sites.switch', { server: result.parent_id, site: result.id })); + router.post(`/servers/${result.parent_id}/sites/${result.id}/switch`); } setOpen(false); }} diff --git a/resources/js/components/app-sidebar-nested.tsx b/resources/js/components/app-sidebar-nested.tsx index 659598a35..313900f78 100644 --- a/resources/js/components/app-sidebar-nested.tsx +++ b/resources/js/components/app-sidebar-nested.tsx @@ -55,56 +55,56 @@ export function AppSidebar() { const mainNavItems: NavItem[] = [ { title: 'Servers', - href: route('servers'), + href: '/servers', icon: ServerIcon, children: [ { title: 'Overview', - href: route('servers.show', { server: page.props.server?.id || 0 }), - onlyActivePath: route('servers.show', { server: page.props.server?.id || 0 }), + href: `/servers/${page.props.server?.id || 0}`, + onlyActivePath: `/servers/${page.props.server?.id || 0}`, icon: HomeIcon, isDisabled: isServerMenuDisabled, }, { title: 'Database', - href: route('databases', { server: page.props.server?.id || 0 }), + href: `/servers/${page.props.server?.id || 0}/database`, icon: DatabaseIcon, isDisabled: isServerMenuDisabled, children: [ { title: 'Databases', - href: route('databases', { server: page.props.server?.id || 0 }), - onlyActivePath: route('databases', { server: page.props.server?.id || 0 }), + href: `/servers/${page.props.server?.id || 0}/database`, + onlyActivePath: `/servers/${page.props.server?.id || 0}/database`, icon: DatabaseIcon, }, { title: 'Users', - href: route('database-users', { server: page.props.server?.id || 0 }), + href: `/servers/${page.props.server?.id || 0}/database/users`, icon: UsersIcon, }, { title: 'Backups', - href: route('backups', { server: page.props.server?.id || 0 }), + href: `/servers/${page.props.server?.id || 0}/backups`, icon: CloudUploadIcon, }, ], }, { title: 'Sites', - href: route('sites', { server: page.props.server?.id || 0 }), + href: `/servers/${page.props.server?.id || 0}/sites`, icon: MousePointerClickIcon, isDisabled: isServerMenuDisabled, children: page.props.site ? [ { title: 'All sites', - href: route('sites', { server: page.props.server?.id || 0 }), - onlyActivePath: route('sites', { server: page.props.server?.id || 0 }), + href: `/servers/${page.props.server?.id || 0}/sites`, + onlyActivePath: `/servers/${page.props.server?.id || 0}/sites`, icon: ArrowLeftIcon, }, { title: 'Application', - href: route('application', { server: page.props.server?.id || 0, site: page.props.site?.id || 0 }), + href: `/servers/${page.props.server?.id || 0}/sites/${page.props.site?.id || 0}`, icon: RocketIcon, }, ] @@ -112,13 +112,13 @@ export function AppSidebar() { }, { title: 'Firewall', - href: route('firewall', { server: page.props.server?.id || 0 }), + href: `/servers/${page.props.server?.id || 0}/firewall`, icon: FlameIcon, isDisabled: isServerMenuDisabled, }, { title: 'CronJobs', - href: route('cronjobs', { server: page.props.server?.id || 0 }), + href: `/servers/${page.props.server?.id || 0}/cronjobs`, icon: ClockIcon, isDisabled: isServerMenuDisabled, }, @@ -161,62 +161,62 @@ export function AppSidebar() { }, { title: 'Sites', - href: route('sites.all'), + href: '/sites', icon: MousePointerClickIcon, }, { title: 'Settings', - href: route('settings'), + href: '/settings', icon: CogIcon, children: [ { title: 'Profile', - href: route('profile'), + href: '/settings/profile', icon: UserIcon, }, { title: 'Users', - href: route('users'), + href: '/admin/users', icon: UsersIcon, }, { title: 'Projects', - href: route('projects'), + href: '/settings/projects', icon: ListIcon, }, { title: 'Server Providers', - href: route('server-providers'), + href: '/settings/server-providers', icon: CloudIcon, }, { title: 'Source Controls', - href: route('source-controls'), + href: '/settings/source-controls', icon: CodeIcon, }, { title: 'Storage Providers', - href: route('storage-providers'), + href: '/settings/storage-providers', icon: DatabaseIcon, }, { title: 'Notification Channels', - href: route('notification-channels'), + href: '/settings/notification-channels', icon: BellIcon, }, { title: 'SSH Keys', - href: route('ssh-keys'), + href: '/settings/ssh-keys', icon: KeyIcon, }, { title: 'Tags', - href: route('tags'), + href: '/tags', icon: TagIcon, }, { title: 'API Keys', - href: route('api-keys'), + href: '/settings/api-keys', icon: PlugIcon, }, ], @@ -238,7 +238,7 @@ export function AppSidebar() { const getMenuItems = (items: NavItem[]) => { return items.map((item) => { - const isActive = item.onlyActivePath ? currentPath() === item.href : window.location.href.startsWith(item.href); + const isActive = item.onlyActivePath ? currentPath() === item.href : currentPath().startsWith(item.href); if (item.children && item.children.length > 0) { return ( @@ -276,7 +276,7 @@ export function AppSidebar() { - + diff --git a/resources/js/components/app-sidebar.tsx b/resources/js/components/app-sidebar.tsx index d53cc84da..e2d5e551b 100644 --- a/resources/js/components/app-sidebar.tsx +++ b/resources/js/components/app-sidebar.tsx @@ -42,47 +42,47 @@ export function AppSidebar({ secondNavItems, secondNavTitle }: { secondNavItems? const mainNavItems: NavItem[] = [ { title: 'Networks', - href: route('networks'), + href: '/networks', icon: NetworkIcon, }, { title: 'Servers', - href: route('servers'), + href: '/servers', icon: ServerIcon, }, { title: 'Sites', - href: route('sites.all'), + href: '/sites', icon: MousePointerClickIcon, }, { title: 'Backups', - href: route('backups.all'), + href: '/backups', icon: CloudUploadIcon, }, { title: 'Scripts', - href: route('scripts'), + href: '/scripts', icon: ZapIcon, }, { title: 'Workflows', - href: route('workflows'), + href: '/workflows', icon: WorkflowIcon, }, { title: 'Domains', - href: route('domains'), + href: '/domains', icon: Globe, }, { title: 'Settings', - href: route('settings'), + href: '/settings', icon: CogIcon, }, { title: 'Admin', - href: route('admin'), + href: '/admin', icon: Settings2Icon, hidden: !page.props.auth.user?.is_admin, }, @@ -91,13 +91,13 @@ export function AppSidebar({ secondNavItems, secondNavTitle }: { secondNavItems? const footerNavItems: NavItem[] = [ { title: 'Horizon Dashboard', - href: route('horizon.index'), + href: '/horizon', icon: ListEndIcon, hidden: !page.props.auth.user?.is_admin, }, { title: 'Vito Logs', - href: route('log-viewer.index'), + href: '/logs', icon: LogsIcon, hidden: !page.props.auth.user?.is_admin, }, @@ -123,7 +123,7 @@ export function AppSidebar({ secondNavItems, secondNavTitle }: { secondNavItems? - + @@ -143,7 +143,7 @@ export function AppSidebar({ secondNavItems, secondNavTitle }: { secondNavItems?