Revert "Add Locale URL"

This reverts commit d910b21185.
This commit is contained in:
Restray
2022-04-02 19:29:22 +02:00
parent 92d1f5aa55
commit 943300509b
187 changed files with 539 additions and 690 deletions

View File

@@ -0,0 +1,77 @@
<script lang="ts">
export let app;
import { onMount } from 'svelte';
import { page } from '$app/stores';
const { id } = $page.params;
let loading = true;
async function checkApp() {
const form = new FormData();
form.append('name', app.name);
form.append('domain', app.domain);
form.append('projectId', app.projectId);
form.append('repository', app.repository);
form.append('branch', app.branch);
const response = await fetch(`/destinations/${id}/scan.json`, {
method: 'POST',
headers: {
accept: 'application/json'
},
body: form
});
if (response.ok) {
const { by, name } = await response.json();
if (by === 'domain') {
app.foundByDomain = true;
} else if (by === 'repository') {
app.foundByRepository = true;
}
app.foundName = name;
}
}
onMount(async () => {
await checkApp();
loading = false;
});
async function addToCoolify() {
const form = new FormData();
form.append('name', app.name);
form.append('domain', app.domain);
if (app.port) form.append('port', app.port);
if (app.buildCommand) form.append('buildCommand', app.buildCommand);
if (app.startCommand) form.append('startCommand', app.startCommand);
if (app.installCommand) form.append('installCommand', app.installCommand);
const response = await fetch(`/new/application/import.json`, {
method: 'POST',
headers: {
accept: 'application/json'
},
body: form
});
if (response.ok) {
const { id } = await response.json();
window.location.replace(`/applications/${id}`);
}
}
</script>
<div class="box-selection hover:border-transparent hover:bg-coolgray-200">
<div class="truncate pb-2 text-center text-xl font-bold">{app.domain}</div>
{#if loading}
<div class="w-full text-center font-bold">Loading...</div>
{:else if app.foundByDomain}
<div class="w-full bg-coolgray-200 text-xs">
<span class="text-red-500">Domain</span> already used for
<span class="text-red-500">{app.foundName}</span>
</div>
{:else if app.foundByRepository}
<div class="w-full bg-coolgray-200 text-xs">
<span class="text-red-500">Repository</span> already used for
<span class="text-red-500">{app.foundName}</span>
</div>
{:else}
<button class="bg-green-600 hover:bg-green-500 w-full" on:click={addToCoolify}
>Add to Coolify</button
>
{/if}
</div>

View File

@@ -0,0 +1,224 @@
<script lang="ts">
export let destination;
export let settings;
export let state;
import { toast } from '@zerodevx/svelte-toast';
import { page, session } from '$app/stores';
import Setting from '$lib/components/Setting.svelte';
import { errorNotification } from '$lib/form';
import { post } from '$lib/api';
import CopyPasswordField from '$lib/components/CopyPasswordField.svelte';
import { onMount } from 'svelte';
const { id } = $page.params;
let cannotDisable = settings.fqdn && destination.engine === '/var/run/docker.sock';
// let scannedApps = [];
let loading = false;
let restarting = false;
async function handleSubmit() {
loading = true;
try {
return await post(`/destinations/${id}.json`, { ...destination });
} catch ({ error }) {
return errorNotification(error);
} finally {
loading = false;
}
}
// async function scanApps() {
// scannedApps = [];
// const data = await fetch(`/destinations/${id}/scan.json`);
// const { containers } = await data.json();
// scannedApps = containers;
// }
onMount(async () => {
if (state === false && destination.isCoolifyProxyUsed === true) {
destination.isCoolifyProxyUsed = !destination.isCoolifyProxyUsed;
try {
await post(`/destinations/${id}/settings.json`, {
isCoolifyProxyUsed: destination.isCoolifyProxyUsed,
engine: destination.engine
});
await stopProxy();
} catch ({ error }) {
return errorNotification(error);
}
} else if (state === true && destination.isCoolifyProxyUsed === false) {
destination.isCoolifyProxyUsed = !destination.isCoolifyProxyUsed;
try {
await post(`/destinations/${id}/settings.json`, {
isCoolifyProxyUsed: destination.isCoolifyProxyUsed,
engine: destination.engine
});
await startProxy();
} catch ({ error }) {
return errorNotification(error);
}
}
});
async function changeProxySetting() {
if (!cannotDisable) {
const isProxyActivated = destination.isCoolifyProxyUsed;
if (isProxyActivated) {
const sure = confirm(
`Are you sure you want to ${
destination.isCoolifyProxyUsed ? 'disable' : 'enable'
} Coolify proxy? It will remove the proxy for all configured networks and all deployments on '${
destination.engine
}'! Nothing will be reachable if you do it!`
);
if (!sure) return;
}
destination.isCoolifyProxyUsed = !destination.isCoolifyProxyUsed;
try {
await post(`/destinations/${id}/settings.json`, {
isCoolifyProxyUsed: destination.isCoolifyProxyUsed,
engine: destination.engine
});
if (isProxyActivated) {
await stopProxy();
} else {
await startProxy();
}
} catch ({ error }) {
return errorNotification(error);
}
}
}
async function stopProxy() {
try {
await post(`/destinations/${id}/stop.json`, { engine: destination.engine });
return toast.push('Coolify Proxy stopped!');
} catch ({ error }) {
return errorNotification(error);
}
}
async function startProxy() {
try {
await post(`/destinations/${id}/start.json`, { engine: destination.engine });
return toast.push('Coolify Proxy started!');
} catch ({ error }) {
return errorNotification(error);
}
}
async function forceRestartProxy() {
const sure = confirm(
'Are you sure you want to restart the proxy? Everything will be reconfigured in ~10 secs.'
);
if (sure) {
try {
restarting = true;
toast.push('Coolify Proxy restarting...');
await post(`/destinations/${id}/restart.json`, {
engine: destination.engine,
fqdn: settings.fqdn
});
} catch ({ error }) {
setTimeout(() => {
window.location.reload();
}, 5000);
} finally {
restarting = false;
}
}
}
</script>
<form on:submit|preventDefault={handleSubmit} class="grid grid-flow-row gap-2 py-4">
<div class="flex space-x-1 pb-5">
<div class="title font-bold">Configuration</div>
{#if $session.isAdmin}
<button
type="submit"
class="bg-sky-600 hover:bg-sky-500"
class:bg-sky-600={!loading}
class:hover:bg-sky-500={!loading}
disabled={loading}
>{loading ? 'Saving...' : 'Save'}
</button>
<button
class={restarting ? '' : 'bg-red-600 hover:bg-red-500'}
disabled={restarting}
on:click|preventDefault={forceRestartProxy}
>{restarting ? 'Restarting... please wait...' : 'Force restart proxy'}</button
>
{/if}
<!-- <button type="button" class="bg-coollabs hover:bg-coollabs-100" on:click={scanApps}
>Scan for applications</button
> -->
</div>
<div class="grid grid-cols-2 items-center px-10 ">
<label for="name" class="text-base font-bold text-stone-100">Name</label>
<input
name="name"
placeholder="name"
disabled={!$session.isAdmin}
readonly={!$session.isAdmin}
bind:value={destination.name}
/>
</div>
<div class="grid grid-cols-2 items-center px-10">
<label for="engine" class="text-base font-bold text-stone-100">Engine</label>
<CopyPasswordField
id="engine"
readonly
disabled
name="engine"
placeholder="eg: /var/run/docker.sock"
value={destination.engine}
/>
</div>
<!-- <div class="flex items-center">
<label for="remoteEngine">Remote Engine?</label>
<input name="remoteEngine" type="checkbox" bind:checked={payload.remoteEngine} />
</div> -->
<div class="grid grid-cols-2 items-center px-10">
<label for="network" class="text-base font-bold text-stone-100">Network</label>
<CopyPasswordField
id="network"
readonly
disabled
name="network"
placeholder="default: coolify"
value={destination.network}
/>
</div>
<div class="grid grid-cols-2 items-center">
<Setting
disabled={cannotDisable}
bind:setting={destination.isCoolifyProxyUsed}
on:click={changeProxySetting}
title="Use Coolify Proxy?"
description={`This will install a proxy on the destination to allow you to access your applications and services without any manual configuration. Databases will have their own proxy. <br><br>${
cannotDisable
? '<span class="font-bold text-white">You cannot disable this proxy as FQDN is configured for Coolify.</span>'
: ''
}`}
/>
</div>
</form>
<!-- <div class="flex justify-center">
{#if payload.isCoolifyProxyUsed}
{#if state}
<button on:click={stopProxy}>Stop proxy</button>
{:else}
<button on:click={startProxy}>Start proxy</button>
{/if}
{/if}
</div> -->
<!-- {#if scannedApps.length > 0}
<div class="flex justify-center px-6 pb-10">
<div class="flex space-x-2 h-8 items-center">
<div class="font-bold text-xl text-white">Found applications</div>
</div>
</div>
<div class="max-w-4xl mx-auto px-6">
<div class="flex space-x-2 justify-center">
{#each scannedApps as app}
<FoundApp {app} />
{/each}
</div>
</div>
{/if} -->

View File

@@ -0,0 +1,225 @@
<script lang="ts">
export let destination;
export let settings;
export let state;
import { toast } from '@zerodevx/svelte-toast';
import { page, session } from '$app/stores';
import Setting from '$lib/components/Setting.svelte';
import { errorNotification } from '$lib/form';
import { post } from '$lib/api';
import CopyPasswordField from '$lib/components/CopyPasswordField.svelte';
import { onMount } from 'svelte';
import { generateRemoteEngine } from '$lib/components/common';
const { id } = $page.params;
let cannotDisable = settings.fqdn && destination.engine === '/var/run/docker.sock';
// let scannedApps = [];
let loading = false;
let restarting = false;
async function handleSubmit() {
loading = true;
try {
return await post(`/destinations/${id}.json`, { ...destination });
} catch ({ error }) {
return errorNotification(error);
} finally {
loading = false;
}
}
// async function scanApps() {
// scannedApps = [];
// const data = await fetch(`/destinations/${id}/scan.json`);
// const { containers } = await data.json();
// scannedApps = containers;
// }
onMount(async () => {
if (state === false && destination.isCoolifyProxyUsed === true) {
destination.isCoolifyProxyUsed = !destination.isCoolifyProxyUsed;
try {
await post(`/destinations/${id}/settings.json`, {
isCoolifyProxyUsed: destination.isCoolifyProxyUsed,
engine: destination.engine
});
await stopProxy();
} catch ({ error }) {
return errorNotification(error);
}
} else if (state === true && destination.isCoolifyProxyUsed === false) {
destination.isCoolifyProxyUsed = !destination.isCoolifyProxyUsed;
try {
await post(`/destinations/${id}/settings.json`, {
isCoolifyProxyUsed: destination.isCoolifyProxyUsed,
engine: destination.engine
});
await startProxy();
} catch ({ error }) {
return errorNotification(error);
}
}
});
async function changeProxySetting() {
if (!cannotDisable) {
const isProxyActivated = destination.isCoolifyProxyUsed;
if (isProxyActivated) {
const sure = confirm(
`Are you sure you want to ${
destination.isCoolifyProxyUsed ? 'disable' : 'enable'
} Coolify proxy? It will remove the proxy for all configured networks and all deployments on '${
destination.engine
}'! Nothing will be reachable if you do it!`
);
if (!sure) return;
}
destination.isCoolifyProxyUsed = !destination.isCoolifyProxyUsed;
try {
await post(`/destinations/${id}/settings.json`, {
isCoolifyProxyUsed: destination.isCoolifyProxyUsed,
engine: destination.engine
});
if (isProxyActivated) {
await stopProxy();
} else {
await startProxy();
}
} catch ({ error }) {
return errorNotification(error);
}
}
}
async function stopProxy() {
try {
const engine = generateRemoteEngine(destination);
await post(`/destinations/${id}/stop.json`, { engine });
return toast.push('Coolify Proxy stopped!');
} catch ({ error }) {
return errorNotification(error);
}
}
async function startProxy() {
try {
const engine = generateRemoteEngine(destination);
await post(`/destinations/${id}/start.json`, { engine });
return toast.push('Coolify Proxy started!');
} catch ({ error }) {
return errorNotification(error);
}
}
async function forceRestartProxy() {
const sure = confirm(
'Are you sure you want to restart the proxy? Everything will be reconfigured in ~10 secs.'
);
if (sure) {
try {
restarting = true;
toast.push('Coolify Proxy restarting...');
await post(`/destinations/${id}/restart.json`, {
engine: destination.engine,
fqdn: settings.fqdn
});
} catch ({ error }) {
setTimeout(() => {
window.location.reload();
}, 5000);
}
}
}
</script>
<form on:submit|preventDefault={handleSubmit} class="grid grid-flow-row gap-2 py-4">
<div class="flex space-x-1 pb-5">
<div class="title font-bold">Configuration</div>
{#if $session.isAdmin}
<button
type="submit"
class="bg-sky-600 hover:bg-sky-500"
class:bg-sky-600={!loading}
class:hover:bg-sky-500={!loading}
disabled={loading}
>{loading ? 'Saving...' : 'Save'}
</button>
<button
class={restarting ? '' : 'bg-red-600 hover:bg-red-500'}
disabled={restarting}
on:click|preventDefault={forceRestartProxy}
>{restarting ? 'Restarting... please wait...' : 'Force restart proxy'}</button
>
{/if}
<!-- <button type="button" class="bg-coollabs hover:bg-coollabs-100" on:click={scanApps}
>Scan for applications</button
> -->
</div>
<div class="grid grid-cols-2 items-center px-10 ">
<label for="name" class="text-base font-bold text-stone-100">Name</label>
<input
name="name"
placeholder="name"
disabled={!$session.isAdmin}
readonly={!$session.isAdmin}
bind:value={destination.name}
/>
</div>
<div class="grid grid-cols-2 items-center px-10">
<label for="engine" class="text-base font-bold text-stone-100">Engine</label>
<CopyPasswordField
id="engine"
readonly
disabled
name="engine"
placeholder="eg: /var/run/docker.sock"
value={destination.engine}
/>
</div>
<!-- <div class="flex items-center">
<label for="remoteEngine">Remote Engine?</label>
<input name="remoteEngine" type="checkbox" bind:checked={payload.remoteEngine} />
</div> -->
<div class="grid grid-cols-2 items-center px-10">
<label for="network" class="text-base font-bold text-stone-100">Network</label>
<CopyPasswordField
id="network"
readonly
disabled
name="network"
placeholder="default: coolify"
value={destination.network}
/>
</div>
<div class="grid grid-cols-2 items-center">
<Setting
disabled={cannotDisable}
bind:setting={destination.isCoolifyProxyUsed}
on:click={changeProxySetting}
title="Use Coolify Proxy?"
description={`This will install a proxy on the destination to allow you to access your applications and services without any manual configuration. Databases will have their own proxy. <br><br>${
cannotDisable
? '<span class="font-bold text-white">You cannot disable this proxy as FQDN is configured for Coolify.</span>'
: ''
}`}
/>
</div>
</form>
<!-- <div class="flex justify-center">
{#if payload.isCoolifyProxyUsed}
{#if state}
<button on:click={stopProxy}>Stop proxy</button>
{:else}
<button on:click={startProxy}>Start proxy</button>
{/if}
{/if}
</div> -->
<!-- {#if scannedApps.length > 0}
<div class="flex justify-center px-6 pb-10">
<div class="flex space-x-2 h-8 items-center">
<div class="font-bold text-xl text-white">Found applications</div>
</div>
</div>
<div class="max-w-4xl mx-auto px-6">
<div class="flex space-x-2 justify-center">
{#each scannedApps as app}
<FoundApp {app} />
{/each}
</div>
</div>
{/if} -->

View File

@@ -0,0 +1,68 @@
<script context="module" lang="ts">
import type { Load } from '@sveltejs/kit';
export const load: Load = async ({ fetch, params }) => {
const url = `/destinations/${params.id}.json`;
const res = await fetch(url);
if (res.ok) {
const { destination, state, settings } = await res.json();
if (!destination || Object.entries(destination).length === 0) {
return {
status: 302,
redirect: '/destinations'
};
}
return {
props: {
destination,
state
},
stuff: {
destination,
settings,
state
}
};
}
return {
status: 302,
redirect: '/destinations'
};
};
</script>
<script>
import { session } from '$app/stores';
import { errorNotification } from '$lib/form';
import DeleteIcon from '$lib/components/DeleteIcon.svelte';
import { del } from '$lib/api';
import { goto } from '$app/navigation';
export let destination;
async function deleteDestination(destination) {
const sure = confirm(`Are you sure you would like to delete '${destination.name}'?`);
if (sure) {
try {
await del(`/destinations/${destination.id}.json`, { id: destination.id });
return await goto('/destinations');
} catch ({ error }) {
return errorNotification(error);
}
}
}
</script>
<nav class="nav-side">
<button
on:click={() => deleteDestination(destination)}
title="Delete Destination"
type="submit"
disabled={!$session.isAdmin}
class:hover:text-red-500={$session.isAdmin}
class="icons tooltip-bottom bg-transparent text-sm"
data-tooltip={$session.isAdmin
? 'Delete Destination'
: 'You do not have permission to delete this destination'}><DeleteIcon /></button
>
</nav>
<slot />

View File

@@ -0,0 +1,68 @@
import { asyncExecShell, getUserDetails } from '$lib/common';
import { generateRemoteEngine } from '$lib/components/common';
import * as db from '$lib/database';
import { ErrorHandler } from '$lib/database';
import { checkContainer } from '$lib/haproxy';
import type { RequestHandler } from '@sveltejs/kit';
export const get: RequestHandler = async (event) => {
const { teamId, status, body } = await getUserDetails(event);
if (status === 401) return { status, body };
const { id } = event.params;
try {
const destination = await db.getDestination({ id, teamId });
const settings = await db.listSettings();
let payload = {
destination,
settings,
state: false
};
if (destination.remoteEngine) {
// const { stdout } = await asyncExecShell(
// `ssh -p ${destination.port} ${destination.user}@${destination.ipAddress} "docker ps -a"`
// );
// console.log(stdout)
// const engine = await generateRemoteEngine(destination);
// // await saveSshKey(destination);
// payload.state = await checkContainer(engine, 'coolify-haproxy');
} else {
payload.state =
destination?.engine && (await checkContainer(destination.engine, 'coolify-haproxy'));
}
return {
status: 200,
body: { ...payload }
};
} catch (error) {
return ErrorHandler(error);
}
};
export const post: RequestHandler = async (event) => {
const { teamId, status, body } = await getUserDetails(event);
if (status === 401) return { status, body };
const { id } = event.params;
const { name, engine, network } = await event.request.json();
try {
await db.updateDestination({ id, name, engine, network });
return { status: 200 };
} catch (error) {
return ErrorHandler(error);
}
};
export const del: RequestHandler = async (event) => {
const { teamId, status, body } = await getUserDetails(event);
if (status === 401) return { status, body };
const { id } = event.params;
try {
await db.removeDestination({ id });
return { status: 200 };
} catch (error) {
return ErrorHandler(error);
}
};

View File

@@ -0,0 +1,53 @@
<script context="module" lang="ts">
import type { Load } from '@sveltejs/kit';
export const load: Load = async ({ fetch, params, stuff }) => {
if (stuff?.destination.id) {
return {
props: {
destination: stuff.destination,
state: stuff.state,
settings: stuff.settings
}
};
}
const url = `/destinations/${params.id}.json`;
const res = await fetch(url);
if (res.ok) {
return {
props: {
...(await res.json())
}
};
}
return {
status: res.status,
error: new Error(`Could not load ${url}`)
};
};
</script>
<script lang="ts">
export let destination: Prisma.DestinationDocker;
export let settings;
export let state;
import type Prisma from '@prisma/client';
import LocalDocker from './_LocalDocker.svelte';
import RemoteDocker from './_RemoteDocker.svelte';
</script>
<div class="flex space-x-1 p-6 text-2xl font-bold">
<div class="tracking-tight">Destination</div>
<span class="arrow-right-applications px-1">></span>
<span class="pr-2">{destination.name}</span>
</div>
<div class="mx-auto max-w-4xl px-6">
{#if destination.remoteEngine}
<RemoteDocker bind:destination {settings} {state} />
{:else}
<LocalDocker bind:destination {settings} {state} />
{/if}
</div>

View File

@@ -0,0 +1,23 @@
import { getUserDetails } from '$lib/common';
import { ErrorHandler } from '$lib/database';
import * as db from '$lib/database';
import { startCoolifyProxy, stopCoolifyProxy } from '$lib/haproxy';
import type { RequestHandler } from '@sveltejs/kit';
export const post: RequestHandler = async (event) => {
const { teamId, status, body } = await getUserDetails(event);
if (status === 401) return { status, body };
const { engine } = await event.request.json();
try {
await stopCoolifyProxy(engine);
await startCoolifyProxy(engine);
await db.setDestinationSettings({ engine, isCoolifyProxyUsed: true });
return {
status: 200
};
} catch (error) {
return ErrorHandler(error);
}
};

View File

@@ -0,0 +1,64 @@
import { asyncExecShell, getTeam, getUserDetails } from '$lib/common';
import * as db from '$lib/database';
import { ErrorHandler } from '$lib/database';
import { dockerInstance } from '$lib/docker';
import type { RequestHandler } from '@sveltejs/kit';
export const get: RequestHandler = async (request) => {
const { teamId, status, body } = await getUserDetails(request);
if (status === 401) return { status, body };
const { id } = request.params;
const destinationDocker = await db.getDestination({ id, teamId });
const docker = dockerInstance({ destinationDocker });
const listContainers = await docker.engine.listContainers({
filters: { network: [destinationDocker.network] }
});
const containers = listContainers.filter((container) => {
return container.Labels['coolify.configuration'];
});
const jsonContainers = containers
.map((container) =>
JSON.parse(Buffer.from(container.Labels['coolify.configuration'], 'base64').toString())
)
.filter((container) => container.type === 'manual');
return {
body: {
containers: jsonContainers
}
};
};
export const post: RequestHandler = async (event) => {
const { teamId, status, body } = await getUserDetails(event);
if (status === 401) return { status, body };
let { fqdn, projectId, repository, branch } = await event.request.json();
if (fqdn) fqdn = fqdn.toLowerCase();
if (projectId) projectId = Number(projectId);
try {
const foundByDomain = await db.prisma.application.findFirst({ where: { fqdn } });
const foundByRepository = await db.prisma.application.findFirst({
where: { repository, branch, projectId }
});
if (foundByDomain) {
return {
status: 200,
body: { by: 'domain', name: foundByDomain.name }
};
}
if (foundByRepository) {
return {
status: 200,
body: { by: 'repository', name: foundByRepository.name }
};
}
return {
status: 404
};
} catch (error) {
return ErrorHandler(error);
}
};

View File

@@ -0,0 +1,18 @@
import { getUserDetails } from '$lib/common';
import * as db from '$lib/database';
import { ErrorHandler } from '$lib/database';
import type { RequestHandler } from '@sveltejs/kit';
export const post: RequestHandler = async (event) => {
const { status, body } = await getUserDetails(event);
if (status === 401) return { status, body };
const { engine, isCoolifyProxyUsed } = await event.request.json();
try {
await db.setDestinationSettings({ engine, isCoolifyProxyUsed });
return { status: 200 };
} catch (error) {
return ErrorHandler(error);
}
};

View File

@@ -0,0 +1,21 @@
import { getUserDetails } from '$lib/common';
import { ErrorHandler } from '$lib/database';
import { startCoolifyProxy, stopCoolifyProxy } from '$lib/haproxy';
import type { RequestHandler } from '@sveltejs/kit';
export const post: RequestHandler = async (event) => {
const { teamId, status, body } = await getUserDetails(event);
if (status === 401) return { status, body };
const { engine } = await event.request.json();
try {
await startCoolifyProxy(engine);
return {
status: 200
};
} catch (error) {
await stopCoolifyProxy(engine);
return ErrorHandler(error);
}
};

View File

@@ -0,0 +1,19 @@
import { getUserDetails } from '$lib/common';
import { ErrorHandler } from '$lib/database';
import { stopCoolifyProxy } from '$lib/haproxy';
import type { RequestHandler } from '@sveltejs/kit';
export const post: RequestHandler = async (event) => {
const { teamId, status, body } = await getUserDetails(event);
if (status === 401) return { status, body };
const { engine } = await event.request.json();
try {
await stopCoolifyProxy(engine);
return {
status: 200
};
} catch (error) {
return ErrorHandler(error);
}
};

View File

@@ -0,0 +1,19 @@
import { getTeam, getUserDetails } from '$lib/common';
import * as db from '$lib/database';
import { ErrorHandler } from '$lib/database';
import type { RequestHandler } from '@sveltejs/kit';
export const get: RequestHandler = async (request) => {
const { teamId, status, body } = await getUserDetails(request);
if (status === 401) return { status, body };
try {
return {
body: {
destinations: await db.listDestinations(teamId)
}
};
} catch (error) {
return ErrorHandler(error);
}
};

View File

@@ -0,0 +1,66 @@
<script context="module" lang="ts">
import type { Load } from '@sveltejs/kit';
export const load: Load = async ({ fetch }) => {
const url = `/destinations.json`;
const res = await fetch(url);
if (res.ok) {
return {
props: {
...(await res.json())
}
};
}
return {
status: res.status,
error: new Error(`Could not load ${url}`)
};
};
</script>
<script lang="ts">
import type Prisma from '@prisma/client';
import { session } from '$app/stores';
export let destinations: Prisma.DestinationDocker[];
</script>
<div class="flex space-x-1 p-6 font-bold">
<div class="mr-4 text-2xl tracking-tight">Destinations</div>
{#if $session.isAdmin}
<a href="/new/destination" class="add-icon bg-sky-600 hover:bg-sky-500">
<svg
class="w-6"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
><path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M12 6v6m0 0v6m0-6h6m-6 0H6"
/></svg
>
</a>
{/if}
</div>
<div class="flex justify-center">
{#if !destinations || destinations.length === 0}
<div class="flex-col">
<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}
<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>
<div class="text-center truncate">{destination.network}</div>
</div>
</a>
{/each}
</div>
{/if}
</div>