Show pages for app,env,org plus navigation, servers wip
This commit is contained in:
@@ -8,8 +8,7 @@ class ApplicationController extends Controller
|
|||||||
{
|
{
|
||||||
public function show(Request $request)
|
public function show(Request $request)
|
||||||
{
|
{
|
||||||
return inertia('Applications/Show', [
|
$id = $request->route('application');
|
||||||
// 'application' => $request->route('application'),
|
return inertia('applications/Show');
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
17
app/Http/Controllers/EnvironmentController.php
Normal file
17
app/Http/Controllers/EnvironmentController.php
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Models\Environment;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
class EnvironmentController extends Controller
|
||||||
|
{
|
||||||
|
public function show(Request $request)
|
||||||
|
{
|
||||||
|
$id = $request->route('environment');
|
||||||
|
return inertia('environments/Show', [
|
||||||
|
'environment' => Environment::findOrFail($id),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,5 +6,8 @@ use Illuminate\Http\Request;
|
|||||||
|
|
||||||
class OrganisationController extends Controller
|
class OrganisationController extends Controller
|
||||||
{
|
{
|
||||||
//
|
public function show()
|
||||||
|
{
|
||||||
|
return inertia('organisations/Show');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
17
app/Http/Controllers/ServerController.php
Normal file
17
app/Http/Controllers/ServerController.php
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Models\Organisation;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
class ServerController extends Controller
|
||||||
|
{
|
||||||
|
public function index(Request $request)
|
||||||
|
{
|
||||||
|
$organisation = Organisation::findOrFail($request->route('organisation'));
|
||||||
|
return inertia('servers/Index', [
|
||||||
|
'servers' => $organisation->servers()->paginate(30),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -30,9 +30,9 @@ class HandleInertiaRequests extends Middleware
|
|||||||
...parent::share($request),
|
...parent::share($request),
|
||||||
'name' => config('app.name'),
|
'name' => config('app.name'),
|
||||||
'organisation' => $request->route('organisation') ? Organisation::with('applications')->findOrFail($request->route('organisation')) : null,
|
'organisation' => $request->route('organisation') ? Organisation::with('applications')->findOrFail($request->route('organisation')) : null,
|
||||||
'application' => $request->route('application') ? Application::findOrFail($request->route('application')) : null,
|
'application' => $request->route('application') ? Application::with('environments')->findOrFail($request->route('application')) : null,
|
||||||
'auth' => [
|
'auth' => [
|
||||||
'user' => $request->user()->load('organisations'),
|
'user' => $request->user()?->load('organisations'),
|
||||||
],
|
],
|
||||||
'ziggy' => [
|
'ziggy' => [
|
||||||
...(new Ziggy)->toArray(),
|
...(new Ziggy)->toArray(),
|
||||||
|
|||||||
@@ -26,6 +26,11 @@ class Organisation extends Model
|
|||||||
->withTimestamps();
|
->withTimestamps();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function servers(): HasMany
|
||||||
|
{
|
||||||
|
return $this->hasMany(Server::class);
|
||||||
|
}
|
||||||
|
|
||||||
public function applications(): HasMany
|
public function applications(): HasMany
|
||||||
{
|
{
|
||||||
return $this->hasMany(Application::class);
|
return $this->hasMany(Application::class);
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ namespace App\Models;
|
|||||||
use App\Enums\ServerProvider;
|
use App\Enums\ServerProvider;
|
||||||
use App\Enums\ServerStatus;
|
use App\Enums\ServerStatus;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
|
|
||||||
class Server extends Model
|
class Server extends Model
|
||||||
@@ -19,6 +20,11 @@ class Server extends Model
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function organisation(): BelongsTo
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Organisation::class);
|
||||||
|
}
|
||||||
|
|
||||||
public function services(): HasMany
|
public function services(): HasMany
|
||||||
{
|
{
|
||||||
return $this->hasMany(Service::class);
|
return $this->hasMany(Service::class);
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use App\Models\Organisation;
|
||||||
use Illuminate\Database\Migrations\Migration;
|
use Illuminate\Database\Migrations\Migration;
|
||||||
use Illuminate\Database\Schema\Blueprint;
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
use Illuminate\Support\Facades\Schema;
|
use Illuminate\Support\Facades\Schema;
|
||||||
@@ -10,6 +11,7 @@ return new class extends Migration
|
|||||||
{
|
{
|
||||||
Schema::create('servers', function (Blueprint $table) {
|
Schema::create('servers', function (Blueprint $table) {
|
||||||
$table->id();
|
$table->id();
|
||||||
|
$table->foreignIdFor(Organisation::class);
|
||||||
$table->string('name');
|
$table->string('name');
|
||||||
$table->string('provider');
|
$table->string('provider');
|
||||||
$table->string('provider_id');
|
$table->string('provider_id');
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import NavMain from '@/components/NavMain.vue';
|
|||||||
import NavUser from '@/components/NavUser.vue';
|
import NavUser from '@/components/NavUser.vue';
|
||||||
import { Sidebar, SidebarContent, SidebarFooter, SidebarHeader, SidebarMenu, SidebarMenuButton, SidebarMenuItem } from '@/components/ui/sidebar';
|
import { Sidebar, SidebarContent, SidebarFooter, SidebarHeader, SidebarMenu, SidebarMenuButton, SidebarMenuItem } from '@/components/ui/sidebar';
|
||||||
import { type NavItem } from '@/types';
|
import { type NavItem } from '@/types';
|
||||||
import { Link } from '@inertiajs/vue3';
|
import { Link, usePage } from '@inertiajs/vue3';
|
||||||
import { BookOpen, Folder, LayoutGrid } from 'lucide-vue-next';
|
import { LayoutGrid, Server } from 'lucide-vue-next';
|
||||||
import AppLogo from './AppLogo.vue';
|
import AppLogo from './AppLogo.vue';
|
||||||
|
|
||||||
const mainNavItems: NavItem[] = [
|
const mainNavItems: NavItem[] = [
|
||||||
@@ -16,18 +16,19 @@ const mainNavItems: NavItem[] = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const footerNavItems: NavItem[] = [
|
const organisation = usePage().props.organisation;
|
||||||
{
|
|
||||||
title: 'Github Repo',
|
if (organisation) {
|
||||||
href: 'https://github.com/laravel/vue-starter-kit',
|
mainNavItems.push({
|
||||||
icon: Folder,
|
title: 'Servers',
|
||||||
},
|
href: route('servers.index', {
|
||||||
{
|
organisation: organisation.id,
|
||||||
title: 'Documentation',
|
}),
|
||||||
href: 'https://laravel.com/docs/starter-kits',
|
icon: Server,
|
||||||
icon: BookOpen,
|
});
|
||||||
},
|
}
|
||||||
];
|
|
||||||
|
const footerNavItems: NavItem[] = [];
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|||||||
@@ -11,8 +11,9 @@ defineProps<{
|
|||||||
breadcrumbs?: BreadcrumbItemType[];
|
breadcrumbs?: BreadcrumbItemType[];
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const organisation = usePage().props.organisation ?? { name: 'Select Organisation' };
|
const organisation = usePage().props.organisation ?? null;
|
||||||
const application = usePage().props.application ?? { name: 'Select Application' };
|
const application = usePage().props.application ?? null;
|
||||||
|
const environment = usePage().props.environment ?? null;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -22,8 +23,8 @@ const application = usePage().props.application ?? { name: 'Select Application'
|
|||||||
<div class="flex items-center gap-4">
|
<div class="flex items-center gap-4">
|
||||||
<SidebarTrigger class="-ml-1" />
|
<SidebarTrigger class="-ml-1" />
|
||||||
<div class="gap-0.25 flex items-center">
|
<div class="gap-0.25 flex items-center">
|
||||||
<Button :as="Link" :href="route('organisations.show', { organisation: organisation?.id })" variant="ghost" size="xs">
|
<Button :as="organisation ? Link : 'button'" :href="organisation ? route('organisations.show', { organisation: organisation?.id }) : null" variant="ghost" size="xs">
|
||||||
{{ organisation?.name }}
|
{{ organisation?.name ?? 'Select Organisation' }}
|
||||||
</Button>
|
</Button>
|
||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
<DropdownMenuTrigger :as="Button" size="iconxs" variant="ghost">
|
<DropdownMenuTrigger :as="Button" size="iconxs" variant="ghost">
|
||||||
@@ -39,14 +40,14 @@ const application = usePage().props.application ?? { name: 'Select Application'
|
|||||||
</DropdownMenuContent>
|
</DropdownMenuContent>
|
||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
</div>
|
</div>
|
||||||
<div class="gap-0.25 flex items-center">
|
<div v-if="organisation" class="gap-0.25 flex items-center">
|
||||||
<Button
|
<Button
|
||||||
:as="Link"
|
:as="application ? Link : 'button'"
|
||||||
:href="route('applications.show', { organisation: application.organisation_id, application: application.id })"
|
:href="application ? route('applications.show', { organisation: application.organisation_id, application: application.id }) : null"
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
size="xs"
|
size="xs"
|
||||||
>
|
>
|
||||||
{{ application?.name }}
|
{{ application?.name ?? 'Select Application' }}
|
||||||
</Button>
|
</Button>
|
||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
<DropdownMenuTrigger :as="Button" size="iconxs" variant="ghost">
|
<DropdownMenuTrigger :as="Button" size="iconxs" variant="ghost">
|
||||||
@@ -62,9 +63,32 @@ const application = usePage().props.application ?? { name: 'Select Application'
|
|||||||
</DropdownMenuContent>
|
</DropdownMenuContent>
|
||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-if="application" class="gap-0.25 flex items-center">
|
||||||
|
<Button
|
||||||
|
:as="environment ? Link : 'button'"
|
||||||
|
:href="environment ? route('environments.show', { organisation: application.organisation_id, application: application.id, environment: environment.id }) : null"
|
||||||
|
variant="ghost"
|
||||||
|
size="xs"
|
||||||
|
>
|
||||||
|
{{ environment?.name ?? 'Select Environment' }}
|
||||||
|
</Button>
|
||||||
|
<DropdownMenu>
|
||||||
|
<DropdownMenuTrigger :as="Button" size="iconxs" variant="ghost">
|
||||||
|
<ChevronsUpDown class="size-3" />
|
||||||
|
</DropdownMenuTrigger>
|
||||||
|
<DropdownMenuContent>
|
||||||
|
<DropdownMenuItem
|
||||||
|
v-for="env in application?.environments"
|
||||||
|
:as="Link"
|
||||||
|
:href="route('environments.show', { organisation: application.organisation_id, application: application.id, environment: env.id })"
|
||||||
|
>{{ env.name }}</DropdownMenuItem
|
||||||
|
>
|
||||||
|
</DropdownMenuContent>
|
||||||
|
</DropdownMenu>
|
||||||
|
</div>
|
||||||
<template v-if="breadcrumbs.length > 0">
|
<template v-if="breadcrumbs.length > 0">
|
||||||
<Breadcrumbs :breadcrumbs="breadcrumbs" />
|
<Breadcrumbs :breadcrumbs="breadcrumbs" />
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
23
resources/js/pages/environments/Show.vue
Normal file
23
resources/js/pages/environments/Show.vue
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import AppLayout from '@/layouts/AppLayout.vue';
|
||||||
|
import { type BreadcrumbItem } from '@/types';
|
||||||
|
import { Head } from '@inertiajs/vue3';
|
||||||
|
import PlaceholderPattern from '../components/PlaceholderPattern.vue';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
environment: {
|
||||||
|
type: Object,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Head :title="environment.name" />
|
||||||
|
|
||||||
|
<AppLayout>
|
||||||
|
<div class="flex h-full flex-1 flex-col gap-4 rounded-xl p-4">
|
||||||
|
{{ environment }}
|
||||||
|
</div>
|
||||||
|
</AppLayout>
|
||||||
|
</template>
|
||||||
23
resources/js/pages/organisations/Show.vue
Normal file
23
resources/js/pages/organisations/Show.vue
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import AppLayout from '@/layouts/AppLayout.vue';
|
||||||
|
import { type BreadcrumbItem } from '@/types';
|
||||||
|
import { Head } from '@inertiajs/vue3';
|
||||||
|
import PlaceholderPattern from '../components/PlaceholderPattern.vue';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
organisation: {
|
||||||
|
type: Object,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Head :title="organisation.name" />
|
||||||
|
|
||||||
|
<AppLayout>
|
||||||
|
<div class="flex h-full flex-1 flex-col gap-4 rounded-xl p-4">
|
||||||
|
{{ organisation }}
|
||||||
|
</div>
|
||||||
|
</AppLayout>
|
||||||
|
</template>
|
||||||
14
resources/js/pages/servers/Create.vue
Normal file
14
resources/js/pages/servers/Create.vue
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import AppLayout from '@/layouts/AppLayout.vue';
|
||||||
|
import { Head } from '@inertiajs/vue3';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Head title="Create Server" />
|
||||||
|
|
||||||
|
<AppLayout>
|
||||||
|
<div class="flex h-full flex-1 flex-col gap-4 rounded-xl p-4">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</AppLayout>
|
||||||
|
</template>
|
||||||
23
resources/js/pages/servers/Index.vue
Normal file
23
resources/js/pages/servers/Index.vue
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import AppLayout from '@/layouts/AppLayout.vue';
|
||||||
|
import { Head } from '@inertiajs/vue3';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
servers: {
|
||||||
|
type: [Array, null],
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Head title="Dashboard" />
|
||||||
|
|
||||||
|
<AppLayout>
|
||||||
|
<div class="flex h-full flex-1 flex-col gap-4 rounded-xl p-4">
|
||||||
|
{{ servers.data }}
|
||||||
|
|
||||||
|
<div>@todo pagination</div>
|
||||||
|
</div>
|
||||||
|
</AppLayout>
|
||||||
|
</template>
|
||||||
@@ -1,7 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
use App\Http\Controllers\ApplicationController;
|
use App\Http\Controllers\ApplicationController;
|
||||||
|
use App\Http\Controllers\EnvironmentController;
|
||||||
use App\Http\Controllers\OrganisationController;
|
use App\Http\Controllers\OrganisationController;
|
||||||
|
use App\Http\Controllers\ServerController;
|
||||||
use Illuminate\Support\Facades\Route;
|
use Illuminate\Support\Facades\Route;
|
||||||
use Inertia\Inertia;
|
use Inertia\Inertia;
|
||||||
|
|
||||||
@@ -14,9 +16,22 @@ Route::middleware(['auth', 'verified'])->group(function () {
|
|||||||
|
|
||||||
Route::prefix('organisations/{organisation}')->group(function () {
|
Route::prefix('organisations/{organisation}')->group(function () {
|
||||||
Route::get('/', [OrganisationController::class, 'show'])->name('organisations.show');
|
Route::get('/', [OrganisationController::class, 'show'])->name('organisations.show');
|
||||||
|
|
||||||
|
Route::resource('servers', ServerController::class)
|
||||||
|
->only('index', 'create', 'store')
|
||||||
|
->name('index', 'servers.index')
|
||||||
|
->name('create', 'servers.create')
|
||||||
|
->name('store', 'servers.store');
|
||||||
|
|
||||||
Route::resource('applications', ApplicationController::class)
|
Route::resource('applications', ApplicationController::class)
|
||||||
->only('show')
|
->only('show')
|
||||||
->name('show', 'applications.show');
|
->name('show', 'applications.show');
|
||||||
|
|
||||||
|
Route::prefix('applications/{application}')->group(function () {
|
||||||
|
Route::resource('environments', EnvironmentController::class)
|
||||||
|
->only('show')
|
||||||
|
->name('show', 'environments.show');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user