Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
andrasbacsai committed Feb 12, 2025
1 parent 7f2ccd8 commit 094c5ca
Show file tree
Hide file tree
Showing 21 changed files with 660 additions and 130 deletions.
30 changes: 28 additions & 2 deletions app/Http/Controllers/InertiaController.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,47 @@
namespace App\Http\Controllers;

use App\Models\Project;
use App\Models\Server;
use Inertia\Inertia;

class InertiaController extends Controller
{
public function dashboard()
{
$servers = Server::isUsable()->get();

$destinations = collect($servers)->flatMap(function ($server) {
return $server->destinations();
});
$destinations = $destinations->map(function ($destination) {
return [
'name' => $destination->name,
'description' => $destination->description,
'uuid' => $destination->uuid,
'type' => get_class($destination),
];
});
$servers = $servers->map(function ($server) {
return [
'name' => $server->name,
'description' => $server->description,
'uuid' => $server->uuid,
];
});

return Inertia::render('Dashboard', [
'projects' => Project::ownedByCurrentTeam()->orderBy('created_at')->get(['name', 'description','uuid']),
'projects' => Project::ownedByCurrentTeam()->orderBy('created_at')->get(['name', 'description', 'uuid']),
// Should not add proxy
'servers' => $servers,
'sources' => currentTeam()->sources(),
'destinations' => $destinations,
]);
}

public function projects()
{
return Inertia::render('Projects', [
'user' => 'test',
'projects' => Project::ownedByCurrentTeam()->orderBy('created_at')->get(['name', 'description', 'uuid']),
]);
}
}
5 changes: 4 additions & 1 deletion app/Http/Middleware/HandleInertiaRequests.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,10 @@ public function version(Request $request): ?string
public function share(Request $request): array
{
return array_merge(parent::share($request), [
'user' => $request->user(),
'user' => [
'name' => $request->user()->name,
'email' => $request->user()->email,
],
]);
}
}
18 changes: 10 additions & 8 deletions resources/css/inertia.css
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
--muted: 215 27.9% 16.9%;
--muted-foreground: 217.9 10.6% 64.9%;

--accent: 215 27.9% 16.9%;
--accent: 0 0% 13%;
--accent-foreground: 210 20% 98%;

--destructive: 0 62.8% 30.6%;
Expand All @@ -76,13 +76,15 @@
--input-background: 0 0% 9.4%;
--ring: 271 83% 51%;

--sidebar-background: 240 5.9% 100%;
--sidebar-foreground: 240 4.8% 95.9%;
--sidebar-primary: 224.3 76.3% 48%;
--sidebar-background: 0 0% 7%;
--sidebar-foreground: 210 20% 98%;
--sidebar-primary: 0 0% 7%;
--sidebar-primary-foreground: 0 0% 100%;
--sidebar-accent: 240 3.7% 15.9%;
--sidebar-accent-foreground: 240 4.8% 95.9%;
--sidebar-border: 240 3.7% 15.9%;
--sidebar-accent: 0 0% 13%;
--sidebar-accent-foreground: 210 20% 98%;
--sidebar-border: 0 0% 13%;
--sidebar-border-foreground: 210 20% 98%;
--sidebar-ring: 217.2 91.2% 59.8%;
--sidebar-ring-foreground: 210 20% 98%;
}
}
}
230 changes: 212 additions & 18 deletions resources/js/Pages/Dashboard.vue
Original file line number Diff line number Diff line change
@@ -1,37 +1,231 @@
<script setup lang="ts">
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
import { ScrollArea, ScrollBar } from '@/components/ui/scroll-area'
import { Link, WhenVisible } from '@inertiajs/vue3'
import MainView from '@/components/MainView.vue'
import { Link } from '@inertiajs/vue3'
import { ref, inject } from 'vue'
import type { User } from '@/types/UserType'
import type { Project } from '@/types/ProjectType'
import { ref, inject } from 'vue'
import { Input } from '@/components/ui/input'
import { useDebounceFn } from '@vueuse/core'
const props = defineProps<{ user: User, projects: Project[] }>()
import type { Server } from '@/types/ServerType'
import type { CustomBreadcrumbItem } from '@/types/BreadcrumbsType'
const route = inject('route') as (name: string) => string
const props = defineProps<{
user: User,
projects: Project[],
servers: Server[],
sources: any[],
destinations: any[]
}>()
let currentTab = ref(new URL(window.location.href).searchParams.get('tab') || 'projects')
const projects = ref(props.projects)
const servers = ref(props.servers)
const sources = ref(props.sources)
const destinations = ref(props.destinations)
const search = ref('')
const debouncedSearch = useDebounceFn(searchProjects, 100)
const route = inject('route')
console.log(route('projects'))
function searchProjects() {
projects.value = props.projects.filter(project => project.name.toLowerCase().includes(search.value.toLowerCase()))
function capitalize(word: string) {
return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()
}
function saveCurrentTab(tab: string) {
currentTab.value = tab
window.history.pushState({}, '', window.location.pathname + '?tab=' + tab)
breadcrumb.value = [
{
label: 'Dashboard',
href: route('dashboard')
},
{
label: capitalize(tab),
href: route('dashboard')
}
]
}
function searchProjects(value: string) {
search.value = value
if (!value) {
projects.value = props.projects
servers.value = props.servers
sources.value = props.sources
destinations.value = props.destinations
return
}
projects.value = props.projects.filter(project => project.name.toLowerCase().includes(value.toLowerCase()) || project.description.toLowerCase().includes(value.toLowerCase()))
servers.value = props.servers.filter(server => server.name.toLowerCase().includes(value.toLowerCase()) || server.description.toLowerCase().includes(value.toLowerCase()))
sources.value = props.sources.filter(source => source.name.toLowerCase().includes(value.toLowerCase()) || source.description.toLowerCase().includes(value.toLowerCase()))
destinations.value = props.destinations.filter(destination => destination.name.toLowerCase().includes(value.toLowerCase() || destination.description.toLowerCase().includes(value.toLowerCase())))
}
const breadcrumb = ref<CustomBreadcrumbItem[]>([
{
label: 'Dashboard',
href: route('dashboard')
},
{
label: capitalize(currentTab.value),
href: route('dashboard')
}
])
</script>

<template>
<MainView>
<MainView @search="searchProjects" :breadcrumb="breadcrumb">
<template #title>
Dashboard
</template>
<template #subtitle>Your self-hosted infrastructure.</template>
<Input size="xs" v-model="search" placeholder="Search" @update:model-value="debouncedSearch" />
<div v-for="project in projects" :key="project.uuid">
<Link :href="route('projects')" class="flex flex-col bg-coolgray-100 rounded-lg p-4 border dark:border-black hover:bg-coolgray-200 transition-all duration-300 cursor-pointer">
<h3 class="text-lg font-bold">{{ project.name }}</h3>
<p class="text-sm text-muted-foreground">{{ project.description }}</p>
</Link>
<div v-if="search">
<Tabs :default-value="currentTab" class="pb-2 opacity-50">
<ScrollArea>
<TabsList>
<TabsTrigger value="projects" disabled>
Projects
</TabsTrigger>
<TabsTrigger value="servers" disabled>
Servers
</TabsTrigger>
<TabsTrigger value="git-sources" disabled>
Git Sources
</TabsTrigger>
<TabsTrigger value="destinations" disabled>
Destinations
</TabsTrigger>
<TabsTrigger value="keys" disabled>
Keys & Tokens
</TabsTrigger>
</TabsList>
<ScrollBar orientation="horizontal" />
</ScrollArea>
</Tabs>

<div v-if="projects.length > 0 || servers.length > 0 || sources.length > 0">
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-2">
<div v-for="project in projects" :key="project.uuid">
<Link :href="route('projects')"
class="flex flex-col bg-coolgray-100 rounded-lg p-4 border dark:border-black hover:bg-coollabs transition-all cursor-pointer h-24 group">
<div class="text-sm font-bold text-foreground">{{ project.name }}</div>
<p class="text-xs text-muted-foreground group-hover:dark:text-white font-bold">{{ project.description
}}</p>
</Link>
</div>
<div v-for="server in servers" :key="server.uuid">
<Link :href="route('projects')"
class="flex flex-col bg-coolgray-100 rounded-lg p-4 border dark:border-black hover:bg-coollabs transition-all cursor-pointer h-24 group">
<div class="text-sm font-bold text-foreground">{{ server.name }}</div>
<p class="text-xs text-muted-foreground group-hover:dark:text-white font-bold">{{ server.description
}}</p>
</Link>
</div>
<div v-for="source in sources" :key="source.uuid">
<Link :href="route('projects')"
class="flex flex-col bg-coolgray-100 rounded-lg p-4 border dark:border-black hover:bg-coollabs transition-all cursor-pointer h-24 group">
<div class="text-sm font-bold text-foreground">{{ source.name }}</div>
<p class="text-xs text-muted-foreground group-hover:dark:text-white font-bold">{{ source.description
}}</p>
</Link>
</div>
<div v-for="destination in destinations" :key="destination.uuid">
<Link :href="route('projects')"
class="flex flex-col bg-coolgray-100 rounded-lg p-4 border dark:border-black hover:bg-coollabs transition-all cursor-pointer h-24 group">
<div class="text-sm font-bold text-foreground">{{ destination.name }}</div>
<p class="text-xs text-muted-foreground group-hover:dark:text-white font-bold">{{ destination.description
}}</p>
</Link>
</div>
</div>
</div>
<div v-else>
<p class="text-sm text-muted-foreground">Nothing found.</p>
</div>
</div>
<div v-else>
<Tabs :default-value="currentTab" orientation="vertical">
<TabsList class="bg-transparent text-left">
<TabsTrigger value="projects" @click="saveCurrentTab('projects')">
Projects
</TabsTrigger>
<TabsTrigger value="servers" @click="saveCurrentTab('servers')">
Servers
</TabsTrigger>
<TabsTrigger value="git-sources" @click="saveCurrentTab('git-sources')">
Git Sources
</TabsTrigger>
<TabsTrigger value="destinations" @click="saveCurrentTab('destinations')">
Destinations
</TabsTrigger>
<TabsTrigger value="keys" @click="saveCurrentTab('keys')">
Keys & Tokens
</TabsTrigger>
</TabsList>
<TabsContent value="projects">
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-2 text-left">
<div v-for="project in projects" :key="project.uuid">
<Link :href="route('projects')"
class="flex flex-col bg-coolgray-100 rounded-lg p-4 border dark:border-black hover:bg-coollabs transition-all cursor-pointer h-24 group">
<div class="text-sm font-bold text-foreground">{{ project.name }}</div>
<p class="text-xs text-muted-foreground group-hover:dark:text-white font-bold">{{ project.description
}}</p>
</Link>
</div>
</div>
</TabsContent>
<TabsContent value="servers">
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-2 text-left">
<div v-for="server in servers" :key="server.uuid">
<Link :href="route('projects')"
class="flex flex-col bg-coolgray-100 rounded-lg p-4 border dark:border-black hover:bg-coollabs transition-all cursor-pointer h-24 group">
<div class="text-sm font-bold text-foreground">{{ server.name }}</div>
<p class="text-xs text-muted-foreground group-hover:dark:text-white font-bold">{{ server.description
}}</p>
</Link>
</div>
</div>
</TabsContent>
<TabsContent value="git-sources">
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-2 text-left">
<div v-for="source in sources" :key="source.uuid">
<Link :href="route('projects')"
class="flex flex-col bg-coolgray-100 rounded-lg p-4 border dark:border-black hover:bg-coollabs transition-all cursor-pointer h-24 group">
<div class="text-sm font-bold text-foreground">{{ source.name }}</div>
<p class="text-xs text-muted-foreground group-hover:dark:text-white font-bold">{{ source.description
}}</p>
</Link>
</div>
</div>
</TabsContent>
<TabsContent value="destinations">
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-2 text-left">
<div v-for="destination in destinations" :key="destination.uuid">
<Link :href="route('projects')"
class="flex flex-col bg-coolgray-100 rounded-lg p-4 border dark:border-black hover:bg-coollabs transition-all cursor-pointer h-24 group">
<div class="text-sm font-bold text-foreground">{{ destination.name }}</div>
<p class="text-xs text-muted-foreground group-hover:dark:text-white font-bold">{{
destination.description
}}</p>
</Link>
</div>
</div>
</TabsContent>
<!-- <TabsContent value="keys">
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-2 text-left">
<div v-for="server in servers" :key="server.uuid">
<Link :href="route('projects')"
class="flex flex-col bg-coolgray-100 rounded-lg p-4 border dark:border-black hover:bg-coollabs transition-all cursor-pointer h-24 group">
<div class="text-sm font-bold text-foreground">{{ server.name }}</div>
<p class="text-xs text-muted-foreground group-hover:dark:text-white font-bold">{{ server.description
}}</p>
</Link>
</div>
</div>
</TabsContent> -->
</Tabs>
</div>
</MainView>
</template>
</template>
40 changes: 38 additions & 2 deletions resources/js/Pages/Projects.vue
Original file line number Diff line number Diff line change
@@ -1,13 +1,49 @@
<script setup lang="ts">
import MainView from '@/components/MainView.vue'
defineProps({ user: Object })
import { ref } from 'vue'
import type { CustomBreadcrumbItem } from '@/types/BreadcrumbsType'
import type { Project } from '@/types/ProjectType'
const props = defineProps<{
projects: Project[]
}>()
const projects = ref(props.projects)
function searchProjects(value: string) {
projects.value = props.projects.filter(project => project.name.toLowerCase().includes(value.toLowerCase()))
}
const breadcrumb = ref<CustomBreadcrumbItem[]>([
{
label: 'Projects',
href: route('projects')
}
])
</script>

<template>
<MainView>
<MainView @search="searchProjects" :breadcrumb="breadcrumb">
<template #title>
Projects
</template>
<template #subtitle>Manage your projects.</template>

<div v-if="projects.length > 0">
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-2">
<div v-for="project in projects" :key="project.uuid">
<Link :href="route('projects')"
class="flex flex-col bg-coolgray-100 rounded-lg p-4 border dark:border-black hover:bg-coollabs transition-all cursor-pointer h-24 group">
<h3 class="text-lg font-bold">{{ project.name }}</h3>
<p class="text-sm text-muted-foreground group-hover:dark:text-white">{{ project.description
}}</p>
</Link>
</div>
</div>
</div>
<div v-else>
<p class="text-sm text-muted-foreground">No projects found.</p>
</div>
</MainView>
</template>
Loading

0 comments on commit 094c5ca

Please sign in to comment.