ui: Better layout for root team

This commit is contained in:
Andras Bacsai 2022-04-07 15:23:32 +02:00
parent 5bf14f4639
commit 2f8d0ee60c
12 changed files with 396 additions and 132 deletions

View File

@ -100,6 +100,7 @@ export const getUserDetails = async (event, isAdminRequired = true) => {
message: 'OK'
}
};
if (isAdminRequired && permission !== 'admin' && permission !== 'owner') {
payload.status = 401;
payload.body.message =

View File

@ -12,7 +12,7 @@
if (!session.userId) {
return {};
}
const endpoint = `/teams.json`;
const endpoint = `/dashboard.json`;
const res = await fetch(endpoint);
if (res.ok) {

View File

@ -8,6 +8,16 @@
const { id } = await post('/applications/new', {});
return await goto(`/applications/${id}`, { replaceState: true });
}
const ownApplications = applications.filter((application) => {
if (application.teams[0].id === $session.teamId) {
return application;
}
});
const otherApplications = applications.filter((application) => {
if (application.teams[0].id !== $session.teamId) {
return application;
}
});
</script>
<div class="flex space-x-1 p-6 font-bold">
@ -36,8 +46,23 @@
<div class="text-center text-xl font-bold">No applications found</div>
</div>
{:else}
{#each applications as application}
<div class="flex flex-col">
{#if $session.teamId === '0'}
<div class="text-xl font-bold pb-5 -ml-10">Your Team's Applications</div>
{/if}
<div class="flex flex-col md:flex-row">
{#each ownApplications as application}
<Application {application} />
{/each}
</div>
{#if otherApplications.length > 0 && $session.teamId === '0'}
<div class="text-xl font-bold pb-5 pt-10 -ml-10">Other Team's Applications</div>
<div class="flex">
{#each otherApplications as application}
<Application {application} />
{/each}
</div>
{/if}
</div>
{/if}
</div>

View File

@ -9,23 +9,28 @@ export const get: RequestHandler = async (event) => {
try {
const applicationsCount = await db.prisma.application.count({
where: { teams: { some: { id: teamId } } }
where: { teams: { some: { id: teamId === '0' ? undefined : teamId } } }
});
const sourcesCount = await db.prisma.gitSource.count({
where: { teams: { some: { id: teamId } } }
where: { teams: { some: { id: teamId === '0' ? undefined : teamId } } }
});
const destinationsCount = await db.prisma.destinationDocker.count({
where: { teams: { some: { id: teamId } } }
where: { teams: { some: { id: teamId === '0' ? undefined : teamId } } }
});
const teamsCount = await db.prisma.permission.count({ where: { userId } });
const databasesCount = await db.prisma.database.count({
where: { teams: { some: { id: teamId } } }
where: { teams: { some: { id: teamId === '0' ? undefined : teamId } } }
});
const servicesCount = await db.prisma.service.count({
where: { teams: { some: { id: teamId } } }
where: { teams: { some: { id: teamId === '0' ? undefined : teamId } } }
});
const teams = await db.prisma.permission.findMany({
where: { userId },
include: { team: { include: { _count: { select: { users: true } } } } }
});
return {
body: {
teams,
applicationsCount,
sourcesCount,
destinationsCount,

View File

@ -14,6 +14,16 @@
const { id } = await post('/databases/new', {});
return await goto(`/databases/${id}`, { replaceState: true });
}
const ownDatabases = databases.filter((database) => {
if (database.teams[0].id === $session.teamId) {
return database;
}
});
const otherDatabases = databases.filter((database) => {
if (database.teams[0].id !== $session.teamId) {
return database;
}
});
</script>
<div class="flex space-x-1 p-6 font-bold">
@ -41,7 +51,12 @@
<div class="text-center text-xl font-bold">No databases found</div>
</div>
{:else}
{#each databases as database}
<div class="flex flex-col">
{#if $session.teamId === '0'}
<div class="text-xl font-bold pb-5 -ml-10">Your Team's Databases</div>
{/if}
<div class="flex flex-col md:flex-row">
{#each ownDatabases as database}
<a href="/databases/{database.id}" class="no-underline p-2 w-96">
<div class="box-selection relative hover:bg-purple-600 group">
{#if database.type === 'clickhouse'}
@ -73,5 +88,44 @@
</div>
</a>
{/each}
</div>
{#if otherDatabases.length > 0 && $session.teamId === '0'}
<div class="text-xl font-bold pb-5 pt-10 -ml-10">Other Team's Databases</div>
<div class="flex">
{#each otherDatabases as database}
<a href="/databases/{database.id}" class="no-underline p-2 w-96">
<div class="box-selection relative hover:bg-purple-600 group">
{#if database.type === 'clickhouse'}
<Clickhouse isAbsolute />
{:else if database.type === 'couchdb'}
<CouchDB isAbsolute />
{:else if database.type === 'mongodb'}
<MongoDB isAbsolute />
{:else if database.type === 'mysql'}
<MySQL isAbsolute />
{:else if database.type === 'postgresql'}
<PostgreSQL isAbsolute />
{:else if database.type === 'redis'}
<Redis isAbsolute />
{/if}
<div class="font-bold text-xl text-center truncate">
{database.name}
</div>
{#if $session.teamId === '0'}
<div class="text-center truncate">Team {database.teams[0].name}</div>
{/if}
{#if !database.type}
<div class="font-bold text-center truncate text-red-500 group-hover:text-white">
Configuration missing
</div>
{:else}
<div class="text-center truncate">{database.type}</div>
{/if}
</div>
</a>
{/each}
</div>
{/if}
</div>
{/if}
</div>

View File

@ -24,6 +24,16 @@
import { session } from '$app/stores';
export let destinations: Prisma.DestinationDocker[];
const ownDestinations = destinations.filter((destination) => {
if (destination.teams[0].id === $session.teamId) {
return destination;
}
});
const otherDestinations = destinations.filter((destination) => {
if (destination.teams[0].id !== $session.teamId) {
return destination;
}
});
</script>
<div class="flex space-x-1 p-6 font-bold">
@ -52,8 +62,28 @@
<div class="text-center text-xl font-bold">No destination found</div>
</div>
{:else}
<div class="flex flex-wrap justify-center">
{#each destinations as destination}
<div class="flex flex-col">
{#if $session.teamId === '0'}
<div class="text-xl font-bold pb-5 -ml-10">Your Team's Destinations</div>
{/if}
<div class="flex flex-col md:flex-row">
{#each ownDestinations as destination}
<a href="/destinations/{destination.id}" class="no-underline p-2 w-96">
<div class="box-selection hover:bg-sky-600">
<div class="font-bold text-xl text-center truncate">{destination.name}</div>
{#if $session.teamId === '0'}
<div class="text-center truncate">Team {destination.teams[0].name}</div>
{/if}
<div class="text-center truncate">{destination.network}</div>
</div>
</a>
{/each}
</div>
{#if otherDestinations.length > 0 && $session.teamId === '0'}
<div class="text-xl font-bold pb-5 pt-10 -ml-10">Other Team's Destinations</div>
<div class="flex">
{#each otherDestinations as destination}
<a href="/destinations/{destination.id}" class="no-underline p-2 w-96">
<div class="box-selection hover:bg-sky-600">
<div class="font-bold text-xl text-center truncate">{destination.name}</div>
@ -66,4 +96,6 @@
{/each}
</div>
{/if}
</div>
{/if}
</div>

View File

@ -19,6 +19,16 @@
const { id } = await post('/services/new', {});
return await goto(`/services/${id}`, { replaceState: true });
}
const ownServices = services.filter((service) => {
if (service.teams[0].id === $session.teamId) {
return service;
}
});
const otherServices = services.filter((service) => {
if (service.teams[0].id !== $session.teamId) {
return service;
}
});
</script>
<div class="flex space-x-1 p-6 font-bold">
@ -46,7 +56,12 @@
<div class="text-center text-xl font-bold">No services found</div>
</div>
{:else}
{#each services as service}
<div class="flex flex-col">
{#if $session.teamId === '0'}
<div class="text-xl font-bold pb-5 -ml-10">Your Team's Applications</div>
{/if}
<div class="flex flex-col md:flex-row">
{#each ownServices as service}
<a href="/services/{service.id}" class="no-underline p-2 w-96">
<div class="box-selection relative hover:bg-pink-600 group">
{#if service.type === 'plausibleanalytics'}
@ -88,5 +103,54 @@
</div>
</a>
{/each}
</div>
{#if otherServices.length > 0 && $session.teamId === '0'}
<div class="text-xl font-bold pb-5 pt-10 -ml-10">Other Team's Applications</div>
<div class="flex">
{#each otherServices as service}
<a href="/services/{service.id}" class="no-underline p-2 w-96">
<div class="box-selection relative hover:bg-pink-600 group">
{#if service.type === 'plausibleanalytics'}
<PlausibleAnalytics isAbsolute />
{:else if service.type === 'nocodb'}
<NocoDb isAbsolute />
{:else if service.type === 'minio'}
<MinIo isAbsolute />
{:else if service.type === 'vscodeserver'}
<VsCodeServer isAbsolute />
{:else if service.type === 'wordpress'}
<Wordpress isAbsolute />
{:else if service.type === 'vaultwarden'}
<VaultWarden isAbsolute />
{:else if service.type === 'languagetool'}
<LanguageTool isAbsolute />
{:else if service.type === 'n8n'}
<N8n isAbsolute />
{:else if service.type === 'uptimekuma'}
<UptimeKuma isAbsolute />
{:else if service.type === 'ghost'}
<Ghost isAbsolute />
{:else if service.type === 'meilisearch'}
<MeiliSearch isAbsolute />
{/if}
<div class="font-bold text-xl text-center truncate">
{service.name}
</div>
{#if $session.teamId === '0'}
<div class="text-center truncate">Team {service.teams[0].name}</div>
{/if}
{#if !service.type || !service.fqdn}
<div class="font-bold text-center truncate text-red-500 group-hover:text-white">
Configuration missing
</div>
{:else}
<div class="text-center truncate">{service.type}</div>
{/if}
</div>
</a>
{/each}
</div>
{/if}
</div>
{/if}
</div>

View File

@ -5,9 +5,9 @@ import type { RequestHandler } from '@sveltejs/kit';
import { promises as dns } from 'dns';
export const get: RequestHandler = async (event) => {
const { status, body } = await getUserDetails(event);
const { teamId, status, body } = await getUserDetails(event);
if (status === 401) return { status, body };
if (teamId !== '0') return { status: 401, body: { message: 'You are not an admin.' } };
try {
const settings = await listSettings();
return {

View File

@ -11,7 +11,12 @@
}
};
}
if (res.status === 401) {
return {
status: 302,
redirect: '/databases'
};
}
return {
status: res.status,
error: new Error(`Could not load ${url}`)

View File

@ -22,6 +22,16 @@
<script lang="ts">
export let sources;
import { session } from '$app/stores';
const ownSources = sources.filter((source) => {
if (source.teams[0].id === $session.teamId) {
return source;
}
});
const otherSources = sources.filter((source) => {
if (source.teams[0].id !== $session.teamId) {
return source;
}
});
</script>
<div class="flex space-x-1 p-6 font-bold">
@ -50,8 +60,39 @@
<div class="text-center text-xl font-bold">No git sources found</div>
</div>
{:else}
<div class="flex flex-wrap justify-center">
{#each sources as source}
<div class="flex flex-col">
{#if $session.teamId === '0'}
<div class="text-xl font-bold pb-5 -ml-10">Your Team's Applications</div>
{/if}
<div class="flex flex-col md:flex-row">
{#each ownSources as source}
<a href="/sources/{source.id}" class="no-underline p-2 w-96">
<div
class="box-selection hover:bg-orange-600 group"
class:border-red-500={source.gitlabApp && !source.gitlabAppId}
class:border-0={source.gitlabApp && !source.gitlabAppId}
class:border-l-4={source.gitlabApp && !source.gitlabAppId}
>
<div class="font-bold text-xl text-center truncate">{source.name}</div>
{#if $session.teamId === '0'}
<div class="text-center truncate">Team {source.teams[0].name}</div>
{/if}
{#if (source.type === 'gitlab' && !source.gitlabAppId) || (source.type === 'github' && !source.githubAppId && !source.githubApp?.installationId)}
<div class="font-bold text-center truncate text-red-500 group-hover:text-white">
Configuration missing
</div>
{:else}
<div class="truncate text-center">{source.htmlUrl}</div>
{/if}
</div>
</a>
{/each}
</div>
{#if otherSources.length > 0 && $session.teamId === '0'}
<div class="text-xl font-bold pb-5 pt-10 -ml-10">Other Team's Applications</div>
<div class="flex">
{#each otherSources as source}
<a href="/sources/{source.id}" class="no-underline p-2 w-96">
<div
class="box-selection hover:bg-orange-600 group"
@ -75,4 +116,6 @@
{/each}
</div>
{/if}
</div>
{/if}
</div>

View File

@ -9,7 +9,7 @@ export const get: RequestHandler = async (event) => {
try {
const teams = await db.prisma.permission.findMany({
where: { userId: teamId === '0' ? undefined : teamId },
where: { userId: teamId === '0' ? undefined : userId },
include: { team: { include: { _count: { select: { users: true } } } } }
});

View File

@ -43,6 +43,16 @@
return errorNotification(error);
}
}
const ownTeams = teams.filter((team) => {
if (team.team.id === $session.teamId) {
return team;
}
});
const otherTeams = teams.filter((team) => {
if (team.team.id !== $session.teamId) {
return team;
}
});
</script>
<div class="flex space-x-1 p-6 font-bold">
@ -92,7 +102,10 @@
</div>
{/if}
<div class="flex flex-wrap justify-center">
{#each teams as team}
<div class="flex flex-col">
<div class="-ml-10 pb-5 text-xl font-bold">Current Team</div>
<div class="flex flex-col md:flex-row">
{#each ownTeams as team}
<a href="/teams/{team.teamId}" class="w-96 p-2 no-underline">
<div
class="box-selection relative"
@ -101,11 +114,33 @@
>
<div class="truncate text-center text-xl font-bold">
{team.team.name}
{team.team?.id === '0' ? '(root)' : ''}
{team.team?.id === '0' ? '(admin team)' : ''}
</div>
<div class="mt-1 text-center">{team.team._count.users} member(s)</div>
</div>
</a>
{/each}
</div>
<div class="-ml-10 pb-5 pt-10 text-xl font-bold">Other Teams</div>
<div class="flex">
{#each otherTeams as team}
<a href="/teams/{team.teamId}" class="w-96 p-2 no-underline">
<div
class="box-selection relative"
class:hover:bg-cyan-600={team.team?.id !== '0'}
class:hover:bg-red-500={team.team?.id === '0'}
>
<div class="truncate text-center text-xl font-bold">
{team.team.name}
{team.team?.id === '0' ? '(admin team)' : ''}
</div>
<div class="mt-1 text-center">{team.team._count.users} member(s)</div>
</div>
</a>
{/each}
</div>
</div>
</div>