mirror of
https://github.com/sofiaritz/aybWeb
synced 2023-12-10 14:23:29 +00:00
More things
This commit is contained in:
parent
ebd9f7ae36
commit
85e1c86739
17 changed files with 456 additions and 103 deletions
|
@ -5,7 +5,7 @@
|
|||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>aybWeb</title>
|
||||
</head>
|
||||
<body>
|
||||
<body class="dark:bg-gray-900 dark:text-white">
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
</body>
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
"vite": "^5.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@dicebear/collection": "^7.0.1",
|
||||
"@dicebear/core": "^7.0.1",
|
||||
"pattern.css": "^1.0.0"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,9 +5,10 @@
|
|||
import Redirect from "./lib/components/Redirect.svelte"
|
||||
import Login from "./routes/Login.svelte"
|
||||
import Confirm from "./routes/Confirm.svelte"
|
||||
import Home from "./routes/Home.svelte";
|
||||
import DatabaseOverview from "./routes/DatabaseOverview.svelte";
|
||||
import DatabaseQuery from "./routes/DatabaseQuery.svelte";
|
||||
import Home from "./routes/Home.svelte"
|
||||
import DatabaseOverview from "./routes/DatabaseOverview.svelte"
|
||||
import DatabaseQuery from "./routes/DatabaseQuery.svelte"
|
||||
import UserPage from "./routes/UserPage.svelte"
|
||||
</script>
|
||||
|
||||
<Router>
|
||||
|
@ -16,12 +17,15 @@
|
|||
<main class="flex w-[95vw] flex-col items-center md:w-[60vw]">
|
||||
{#if $loggedIn}
|
||||
<Route path="/"><Home /></Route>
|
||||
<Route path="/database/:entity/:slug/overview" let:params>
|
||||
<Route path="/u/:entity/:slug/overview" let:params>
|
||||
<DatabaseOverview entity={params.entity} slug={params.slug} />
|
||||
</Route>
|
||||
<Route path="/database/:entity/:slug/query" let:params>
|
||||
<Route path="/u/:entity/:slug/query" let:params>
|
||||
<DatabaseQuery entity={params.entity} slug={params.slug} />
|
||||
</Route>
|
||||
<Route path="/u/:entity" let:params>
|
||||
<UserPage entity={params.entity} />
|
||||
</Route>
|
||||
<Route path="/auth/login"><Redirect to="/" /></Route>
|
||||
<Route path="/auth/confirm"><Redirect to="/" /></Route>
|
||||
<Route path="/auth/confirm/:token">
|
||||
|
|
|
@ -32,6 +32,6 @@
|
|||
|
||||
@layer components {
|
||||
a {
|
||||
@apply text-blue-700 underline hover:text-blue-800;
|
||||
@apply text-blue-700 underline hover:text-blue-800 dark:text-blue-400 dark:hover:text-blue-500;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -83,6 +83,7 @@ export async function confirm(token: string, auth: UserInstanceData) {
|
|||
})
|
||||
}
|
||||
|
||||
// TODO(sofiaritz): Check method
|
||||
export async function createDatabase(slug: string, databaseType: DBType, auth: UserInstanceData) {
|
||||
return request<DatabaseCreation>(`/v1/${slug}/create`, auth, {
|
||||
headers: {
|
||||
|
|
13
src/lib/components/Avatar.svelte
Normal file
13
src/lib/components/Avatar.svelte
Normal file
|
@ -0,0 +1,13 @@
|
|||
<script lang="ts">
|
||||
import { createAvatar } from "@dicebear/core"
|
||||
import { identicon } from "@dicebear/collection"
|
||||
|
||||
export let slug: string
|
||||
export let className: string | undefined = undefined
|
||||
|
||||
const avatar = createAvatar(identicon, {
|
||||
seed: slug,
|
||||
})
|
||||
</script>
|
||||
|
||||
<img src={avatar.toDataUriSync()} alt={`${slug}'s avatar`} class={className} />
|
|
@ -3,12 +3,16 @@
|
|||
import { Link } from "svelte-routing"
|
||||
</script>
|
||||
|
||||
<header class="flex items-center justify-between rounded-b-2xl bg-gray-100 p-4">
|
||||
<header class="flex items-center justify-between bg-gray-100 p-4 dark:bg-gray-950 dark:text-white">
|
||||
<h1 class="text-xl">
|
||||
<Link class="text-black no-underline hover:text-gray-800" to="/">aybWeb</Link>
|
||||
<Link
|
||||
class="text-black no-underline hover:text-black dark:text-white dark:hover:text-white"
|
||||
to="/">aybWeb</Link
|
||||
>
|
||||
</h1>
|
||||
{#if $loggedIn}
|
||||
<span>Logged in as <code>{$userInfo.slug}</code></span>
|
||||
<span>Logged in as <code><Link to="/u/{$userInfo.slug}">{$userInfo.slug}</Link></code></span
|
||||
>
|
||||
{:else}
|
||||
<Link
|
||||
class="rounded bg-blue-600 px-3 py-1.5 text-white no-underline hover:bg-blue-700 hover:text-white"
|
||||
|
|
18
src/lib/components/common/Textarea.svelte
Normal file
18
src/lib/components/common/Textarea.svelte
Normal file
|
@ -0,0 +1,18 @@
|
|||
<script lang="ts">
|
||||
export let name: string = ""
|
||||
export let id: string = ""
|
||||
export let rows: string = ""
|
||||
export let placeholder: string = ""
|
||||
export let value: string = ""
|
||||
export let disabled: boolean = false
|
||||
</script>
|
||||
|
||||
<textarea
|
||||
class="block w-full rounded-lg border border-gray-300 bg-gray-50 p-2.5 text-sm text-gray-900 focus:border-blue-500 focus:ring-blue-500 disabled:bg-gray-100 disabled:font-mono"
|
||||
{name}
|
||||
{id}
|
||||
{placeholder}
|
||||
{value}
|
||||
{disabled}
|
||||
{rows}
|
||||
/>
|
|
@ -1,6 +1,6 @@
|
|||
<script lang="ts">
|
||||
import { DBType } from "../../api/types";
|
||||
import { Link } from "svelte-routing";
|
||||
import { DBType } from "../../api/types"
|
||||
import { Link } from "svelte-routing"
|
||||
|
||||
export let entity: string
|
||||
export let slug: string
|
||||
|
@ -17,19 +17,15 @@
|
|||
}
|
||||
|
||||
const background = async (slug: string) => {
|
||||
const utf8 = new TextEncoder().encode(slug);
|
||||
let hash = await crypto.subtle.digest('SHA-256', utf8).then((hashBuffer) => {
|
||||
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
||||
return hashArray
|
||||
.map((bytes) => bytes.toString(16).padStart(2, '0'))
|
||||
.join('');
|
||||
const utf8 = new TextEncoder().encode(slug)
|
||||
let hash = await crypto.subtle.digest("SHA-256", utf8).then((hashBuffer) => {
|
||||
const hashArray = Array.from(new Uint8Array(hashBuffer))
|
||||
return hashArray.map((bytes) => bytes.toString(16).padStart(2, "0")).join("")
|
||||
})
|
||||
|
||||
let hashCode = [...hash].reduce((acc, char) => char.charCodeAt(0) + ((acc << 5) - acc), 0);
|
||||
let hashCode = [...hash].reduce((acc, char) => char.charCodeAt(0) + ((acc << 5) - acc), 0)
|
||||
let primaryColor = (() => {
|
||||
let c = (hashCode & 0x00FFFFFF)
|
||||
.toString(16)
|
||||
.toUpperCase()
|
||||
let c = (hashCode & 0x00ffffff).toString(16).toUpperCase()
|
||||
|
||||
return "00000".substring(0, 6 - c.length) + c
|
||||
})()
|
||||
|
@ -60,9 +56,13 @@
|
|||
}
|
||||
</script>
|
||||
|
||||
<Link to={`/database/${entity}/${slug}/overview`} role="button" class="border border-gray-300 rounded no-underline text-black hover:text-black">
|
||||
<Link
|
||||
to={`/u/${entity}/${slug}/overview`}
|
||||
role="button"
|
||||
class="rounded border border-gray-300 text-black no-underline hover:text-black dark:border-gray-800 dark:text-white dark:hover:text-white"
|
||||
>
|
||||
{#await background(slug)}
|
||||
<div class="h-24 pattern-checks-sm"></div>
|
||||
<div class="pattern-checks-sm h-24"></div>
|
||||
{:then result}
|
||||
<div class={`h-24 ${result[0]}`} style={result[1]}></div>
|
||||
{/await}
|
||||
|
@ -70,5 +70,5 @@
|
|||
<div class="p-2">
|
||||
<span>{slug.split(".")[0]}</span>
|
||||
</div>
|
||||
<span class="block px-2 mb-2">Database type: {displayType(type)}</span>
|
||||
<span class="mb-2 block px-2 dark:text-gray-400">Database type: {displayType(type)}</span>
|
||||
</Link>
|
||||
|
|
|
@ -1,27 +1,27 @@
|
|||
<script lang="ts">
|
||||
import { Link } from "svelte-routing";
|
||||
import { Link } from "svelte-routing"
|
||||
|
||||
export let entity: string
|
||||
export let slug: string
|
||||
export let selected: "overview" | "query" | "settings" = "overview"
|
||||
</script>
|
||||
|
||||
<div class="flex flex-col w-32 gap-2">
|
||||
<div class="flex w-32 flex-col gap-2">
|
||||
{#if selected === "overview"}
|
||||
<span>Overview</span>
|
||||
{:else}
|
||||
<Link to={`/database/${entity}/${slug}/overview`}>Overview</Link>
|
||||
<Link to={`/u/${entity}/${slug}/overview`}>Overview</Link>
|
||||
{/if}
|
||||
|
||||
{#if selected === "query"}
|
||||
<span>Query</span>
|
||||
{:else}
|
||||
<Link to={`/database/${entity}/${slug}/query`}>Query</Link>
|
||||
<Link to={`/u/${entity}/${slug}/query`}>Query</Link>
|
||||
{/if}
|
||||
|
||||
{#if selected === "settings"}
|
||||
<span>Settings</span>
|
||||
{:else}
|
||||
<Link to={`/database/${entity}/${slug}/settings`}>Settings</Link>
|
||||
<Link to={`/u/${entity}/${slug}/settings`}>Settings</Link>
|
||||
{/if}
|
||||
</div>
|
||||
|
|
|
@ -1,22 +1,22 @@
|
|||
<script lang="ts">
|
||||
import type { DatabaseQuery } from "../../api/types";
|
||||
import type { DatabaseQuery } from "../../api/types"
|
||||
|
||||
export let data: DatabaseQuery
|
||||
</script>
|
||||
|
||||
<table class="border-gray-400 border p-3 w-full">
|
||||
<table class="w-full border border-gray-400 p-3">
|
||||
<thead>
|
||||
<tr class="border-gray-400 border text-left">
|
||||
<tr class="border border-gray-400 text-left">
|
||||
{#each data.fields as field}
|
||||
<th class="border-gray-400 border px-2">{field}</th>
|
||||
<th class="border border-gray-400 px-2">{field}</th>
|
||||
{/each}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{#each data.rows as row}
|
||||
<tr class="border-gray-400 border">
|
||||
<tr class="border border-gray-400">
|
||||
{#each row as value}
|
||||
<td class="px-2 border-gray-400 border">{value}</td>
|
||||
<td class="border border-gray-400 px-2">{value}</td>
|
||||
{/each}
|
||||
</tr>
|
||||
{/each}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script lang="ts">
|
||||
import DatabasePagesHeader from "../lib/components/database/DatabasePagesHeader.svelte";
|
||||
import DatabasePagesHeader from "../lib/components/database/DatabasePagesHeader.svelte"
|
||||
|
||||
export let entity: string
|
||||
export let slug: string
|
||||
|
@ -7,24 +7,29 @@
|
|||
|
||||
<div class="flex gap-6 md:w-8/12">
|
||||
<DatabasePagesHeader selected="overview" {slug} {entity} />
|
||||
<div class="flex flex-col w-full">
|
||||
<div class="flex w-full flex-col">
|
||||
<h1 class="text-2xl">Congratulations, you've got your database set-up!</h1>
|
||||
<div class="flex gap-6">
|
||||
<div class="border border-gray-300 rounded p-6 mt-6 w-full">
|
||||
<div class="mt-6 w-full rounded border border-gray-300 p-6">
|
||||
<h2 class="text-xl">Documentation</h2>
|
||||
<span class="text-gray-500 block mt-1">Check out the link below for more information about ayb</span>
|
||||
<span class="mt-1 block text-gray-500"
|
||||
>Check out the link below for more information about ayb</span
|
||||
>
|
||||
<a class="mt-1 block" href="https://git.sofiaritz.com/sofia/wip">ayb.host/docs</a>
|
||||
</div>
|
||||
<div class="border border-gray-300 rounded p-6 mt-6 w-full">
|
||||
<div class="mt-6 w-full rounded border border-gray-300 p-6">
|
||||
<h2 class="text-xl">Getting help</h2>
|
||||
<span class="text-gray-500 block mt-1">Contact the instance owner for support</span>
|
||||
<a class="mt-1 block" href="https://git.sofiaritz.com/sofia/wip">ayb.host/support</a>
|
||||
<span class="mt-1 block text-gray-500">Contact the instance owner for support</span>
|
||||
<a class="mt-1 block" href="https://git.sofiaritz.com/sofia/wip">ayb.host/support</a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex gap-6">
|
||||
<div class="border border-gray-300 rounded p-6 mt-6 w-full">
|
||||
<div class="mt-6 w-full rounded border border-gray-300 p-6">
|
||||
<h2 class="text-xl">Usage limits</h2>
|
||||
<span class="text-gray-500 block mt-1">You are not subject to usage limits right now</span>
|
||||
<span class="mt-1 block text-gray-500"
|
||||
>You are not subject to usage limits right now</span
|
||||
>
|
||||
<a class="mt-1 block" href="https://git.sofiaritz.com/sofia/wip">ayb.host/limits</a>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
<script lang="ts">
|
||||
import { login, queryDatabase, unwrapResponse } from "../lib/api";
|
||||
import { userInstanceData } from "../lib/auth/stores";
|
||||
import DatabaseResult from "../lib/components/database/DatabaseQueryResult.svelte";
|
||||
import DatabasePagesHeader from "../lib/components/database/DatabasePagesHeader.svelte";
|
||||
import { createForm } from "felte";
|
||||
import { Input } from "../lib/components/common";
|
||||
import Button from "../lib/components/common/Button.svelte";
|
||||
import { login, queryDatabase, unwrapResponse } from "../lib/api"
|
||||
import { userInstanceData } from "../lib/auth/stores"
|
||||
import DatabaseResult from "../lib/components/database/DatabaseQueryResult.svelte"
|
||||
import DatabasePagesHeader from "../lib/components/database/DatabasePagesHeader.svelte"
|
||||
import { createForm } from "felte"
|
||||
import { Input } from "../lib/components/common"
|
||||
import Button from "../lib/components/common/Button.svelte"
|
||||
import Textarea from "../lib/components/common/Textarea.svelte"
|
||||
|
||||
export let entity: string
|
||||
export let slug: string
|
||||
|
@ -16,14 +17,20 @@
|
|||
const { form } = createForm({
|
||||
onSubmit: async (values) => {
|
||||
let lowercaseQuery = values["query"].toLowerCase()
|
||||
if (lowercaseQuery.includes("delete") || lowercaseQuery.includes("drop") || lowercaseQuery.includes("truncate")) {
|
||||
let confirmed = confirm("Your query can potentially perform destructive actions. Do you want to continue?")
|
||||
if (!confirmed) return;
|
||||
if (
|
||||
lowercaseQuery.includes("delete") ||
|
||||
lowercaseQuery.includes("drop") ||
|
||||
lowercaseQuery.includes("truncate")
|
||||
) {
|
||||
let confirmed = confirm(
|
||||
"Your query can potentially perform destructive actions. Do you want to continue?",
|
||||
)
|
||||
if (!confirmed) return
|
||||
}
|
||||
|
||||
result = { status: "loading" }
|
||||
let query = values["query"].trim()
|
||||
if (!query.endsWith(";")) query += ";";
|
||||
if (!query.endsWith(";")) query += ";"
|
||||
|
||||
return await queryDatabase(`${entity}/${slug}`, query, $userInstanceData)
|
||||
},
|
||||
|
@ -35,7 +42,7 @@
|
|||
|
||||
<div class="flex gap-6 md:w-8/12">
|
||||
<DatabasePagesHeader selected="query" {slug} {entity} />
|
||||
<div class="flex flex-col w-full">
|
||||
<div class="flex w-full flex-col">
|
||||
<h1 class="text-2xl">Start querying your database</h1>
|
||||
<div class="flex gap-2 pt-4">
|
||||
<label for="big-mode mb-0">Big mode enabled</label>
|
||||
|
@ -44,16 +51,24 @@
|
|||
<form class="mt-2 gap-6" use:form>
|
||||
{#if bigMode === true}
|
||||
<div class="flex flex-col gap-6">
|
||||
<textarea name="query" rows="5" placeholder="SELECT
|
||||
<Textarea
|
||||
name="query"
|
||||
rows="5"
|
||||
placeholder="SELECT
|
||||
id,
|
||||
name,
|
||||
score
|
||||
FROM favorite_databases"/>
|
||||
FROM favorite_databases"
|
||||
/>
|
||||
<Button type="submit">Query</Button>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="flex gap-6">
|
||||
<Input name="query" type="text" placeholder="SELECT * FROM favorite_databases"/>
|
||||
<Input
|
||||
name="query"
|
||||
type="text"
|
||||
placeholder="SELECT * FROM favorite_databases"
|
||||
/>
|
||||
<Button type="submit">Query</Button>
|
||||
</div>
|
||||
{/if}
|
||||
|
@ -62,17 +77,20 @@ FROM favorite_databases"/>
|
|||
{#if result != null}
|
||||
{#if result.message != null}
|
||||
<span><span class="pr-2 text-red-600">Error</span>{result.message}</span>
|
||||
{:else if ((result.fields != null && result.rows != null) && result.rows.length > 0)}
|
||||
{:else if result.fields != null && result.rows != null && result.rows.length > 0}
|
||||
<DatabaseResult data={result} />
|
||||
{:else if (result.fields != null && result.rows != null)}
|
||||
<span class="text-gray-500 block">No rows returned</span>
|
||||
{:else if result.fields != null && result.rows != null}
|
||||
<span class="block text-gray-500">No rows returned</span>
|
||||
{:else if result.status === "loading"}
|
||||
<span class="text-gray-500 block">Loading...</span>
|
||||
<span class="block text-gray-500">Loading...</span>
|
||||
{:else}
|
||||
<span><span class="pr-2 text-red-600">Error</span>Unknown response from the server</span>
|
||||
<span
|
||||
><span class="pr-2 text-red-600">Error</span>Unknown response from the
|
||||
server</span
|
||||
>
|
||||
{/if}
|
||||
{:else}
|
||||
<span class="text-gray-500 block">Waiting for your query...</span>
|
||||
<span class="block text-gray-500">Waiting for your query...</span>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,25 +1,53 @@
|
|||
<script lang="ts">
|
||||
import { userInfo } from "../lib/auth/stores";
|
||||
import DatabaseCard from "../lib/components/database/DatabaseCard.svelte";
|
||||
import { Link } from "svelte-routing";
|
||||
import { userInfo } from "../lib/auth/stores"
|
||||
import DatabaseCard from "../lib/components/database/DatabaseCard.svelte"
|
||||
import { Link } from "svelte-routing"
|
||||
import Avatar from "../lib/components/Avatar.svelte"
|
||||
</script>
|
||||
|
||||
<div class="md:w-8/12">
|
||||
<h1 class="text-2xl">Your databases</h1>
|
||||
<div class="flex flex-col gap-6 md:w-8/12">
|
||||
<div class="flex flex-col gap-3">
|
||||
<h1 class="text-2xl">Organizations</h1>
|
||||
<div class="flex gap-6">
|
||||
<a
|
||||
href={`/u/${$userInfo.slug}`}
|
||||
class="flex flex-col items-center gap-1 text-black no-underline hover:text-black dark:text-white dark:hover:text-white"
|
||||
>
|
||||
<Avatar
|
||||
className="w-12 rounded border-gray-300 dark:border-gray-700 dark:border-2 bg-white border"
|
||||
slug={$userInfo.slug}
|
||||
/>
|
||||
<span class="text-sm">{$userInfo.slug}</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col gap-3">
|
||||
<h1 class="text-2xl">Databases</h1>
|
||||
{#if $userInfo.databases.length > 0}
|
||||
<div class="grid grid-cols-2 gap-6 mt-5">
|
||||
<div class="grid grid-cols-2 gap-6">
|
||||
{#each $userInfo.databases as database (database.slug)}
|
||||
<DatabaseCard entity={$userInfo.slug} slug={database.slug} type={database.database_type}/>
|
||||
<DatabaseCard
|
||||
entity={$userInfo.slug}
|
||||
slug={database.slug}
|
||||
type={database.database_type}
|
||||
/>
|
||||
{/each}
|
||||
</div>
|
||||
{:else}
|
||||
<div class="flex mt-5">
|
||||
<Link to="/database/new" role="button" class="flex flex-col gap-3 justify-center items-center h-60 w-full border border-gray-300 rounded p-2 no-underline text-black hover:text-black">
|
||||
<div class="mt-5 flex">
|
||||
<Link
|
||||
to="/database/new"
|
||||
role="button"
|
||||
class="flex h-60 w-full flex-col items-center justify-center gap-3 rounded border border-gray-300 p-2 text-black no-underline hover:text-black"
|
||||
>
|
||||
<span class="text-4xl">+</span>
|
||||
<h2 class="font-bold text-xl">Create a new database</h2>
|
||||
<span class="text-gray-500 block">The instance owner hasn't set any limits for your account</span>
|
||||
<h2 class="text-xl font-bold">Create a new database</h2>
|
||||
<span class="block text-gray-500"
|
||||
>The instance owner hasn't set any limits for your account</span
|
||||
>
|
||||
</Link>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -49,7 +49,7 @@
|
|||
<h1 class="text-2xl text-red">Error</h1>
|
||||
<span>{error.toString()}</span>
|
||||
{:else if state === State.Waiting}
|
||||
<h1 class="mb-6 text-2xl font-bold text-gray-900">Login</h1>
|
||||
<h1 class="mb-6 text-2xl font-bold text-gray-900 dark:text-white">Login</h1>
|
||||
<form class="flex flex-col gap-3.5" use:form>
|
||||
<label class="block" for="instance-input">
|
||||
Instance
|
||||
|
@ -59,7 +59,7 @@
|
|||
id="instance-input"
|
||||
placeholder="https://ayb.sofiaritz.com"
|
||||
/>
|
||||
<span class="text-sm text-gray-700"
|
||||
<span class="text-sm text-gray-700 dark:text-gray-400"
|
||||
>You can find an updated instance list at <a
|
||||
href="https://git.sofiaritz.com/sofia/wip">ayb.host/instances</a
|
||||
></span
|
||||
|
|
44
src/routes/UserPage.svelte
Normal file
44
src/routes/UserPage.svelte
Normal file
|
@ -0,0 +1,44 @@
|
|||
<script lang="ts">
|
||||
import { entityInfo, unwrapResponse } from "../lib/api"
|
||||
import { userInstanceData } from "../lib/auth/stores"
|
||||
import Avatar from "../lib/components/Avatar.svelte"
|
||||
import DatabaseCard from "../lib/components/database/DatabaseCard.svelte"
|
||||
|
||||
export let entity: string
|
||||
|
||||
const fetchEntity = async (entity: string) =>
|
||||
unwrapResponse(await entityInfo(entity, $userInstanceData))
|
||||
const isNotFound = (message: string) =>
|
||||
message.trim().toLowerCase().startsWith("entity not found")
|
||||
</script>
|
||||
|
||||
{#await fetchEntity(entity)}
|
||||
<h1 class="text-2xl">Loading...</h1>
|
||||
{:then entity}
|
||||
<div class="mb-6 flex w-full gap-9">
|
||||
<div class="flex w-2/12 flex-col gap-6">
|
||||
<Avatar
|
||||
className="w-full border-gray-300 dark:border-gray-700 dark:border-2 bg-white border rounded"
|
||||
slug={entity.slug}
|
||||
/>
|
||||
<h1 class="text-2xl">{entity.slug}</h1>
|
||||
</div>
|
||||
<div class="flex w-full flex-col gap-6">
|
||||
{#each entity.databases as database (database.slug)}
|
||||
<DatabaseCard
|
||||
entity={entity.slug}
|
||||
slug={database.slug}
|
||||
type={database.database_type}
|
||||
/>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
{:catch error}
|
||||
{#if isNotFound(error.message)}
|
||||
<h1 class="mb-5 text-5xl">404</h1>
|
||||
<h1 class="text-sm">
|
||||
The entity you are trying to see either does not exist or you are not authorized to view
|
||||
it.
|
||||
</h1>
|
||||
{/if}
|
||||
{/await}
|
216
yarn.lock
216
yarn.lock
|
@ -15,6 +15,196 @@
|
|||
"@jridgewell/gen-mapping" "^0.3.0"
|
||||
"@jridgewell/trace-mapping" "^0.3.9"
|
||||
|
||||
"@dicebear/adventurer-neutral@7.0.1":
|
||||
version "7.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@dicebear/adventurer-neutral/-/adventurer-neutral-7.0.1.tgz#2ff2b2334e11e8d1540ff9187e90f920e65b4dc2"
|
||||
integrity sha512-dZfyaUFS8qQv7Lv+OXNTHVkercDCh+VqGSJU8jIf3FFbtFbFF79FXZJwJ8V3+pr0xKcZWa8i+8hXLtU3gqZ18g==
|
||||
|
||||
"@dicebear/adventurer@7.0.1":
|
||||
version "7.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@dicebear/adventurer/-/adventurer-7.0.1.tgz#0f175f0bff38de4f3251d36912a2c80ae17610fe"
|
||||
integrity sha512-eqbHHAQO8HjG8YNMl8xgklxphC7HvfDtqVr1rkJWP98e7r2AdQpu0cPYIOZPV4uv9gxl1ncaErQjdjvIvFRGiA==
|
||||
|
||||
"@dicebear/avataaars-neutral@7.0.1":
|
||||
version "7.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@dicebear/avataaars-neutral/-/avataaars-neutral-7.0.1.tgz#0eea134753e1f8ea459a3444fc3ba1e071377782"
|
||||
integrity sha512-e3XwK3xup4ifJ/BUNjR5rcrw9982SC75UTJlPsKuuOM/Lwx3MtUe3+dqeDSyYbrC7KoWespX70oDZK1+2dBQFw==
|
||||
|
||||
"@dicebear/avataaars@7.0.1":
|
||||
version "7.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@dicebear/avataaars/-/avataaars-7.0.1.tgz#33240f6bb2f1d9694265ac8786e1b149aa10903a"
|
||||
integrity sha512-U7JJLDFJsbVyQl3j1SqtTxi5h+I5JXL8CGfwAOPtQTnk/tKQFXM9WF/zdHegtxbxYAxQaYJtyprdwTJHx5ELnw==
|
||||
|
||||
"@dicebear/big-ears-neutral@7.0.1":
|
||||
version "7.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@dicebear/big-ears-neutral/-/big-ears-neutral-7.0.1.tgz#472120f04e07411e18576d8e25466633d49ff8ed"
|
||||
integrity sha512-2QK9HVmApoGFLi3ONW9mh0Tk/PPyHx9rvzUvcT5H/mb80ooBqIVMPYYq4rVlGVP6wAtsNHdoxzzlKja0DG+vvQ==
|
||||
|
||||
"@dicebear/big-ears@7.0.1":
|
||||
version "7.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@dicebear/big-ears/-/big-ears-7.0.1.tgz#c62cafb9812828c52080b03a6b706a4cfafc6bb7"
|
||||
integrity sha512-ITI0IQCwdn5s5/kUrNdO488TQvZdiCljnzKpqbQ1hqfsxZ0C+eZs+cudZ0bqLftYxM+WBvmaJwrh3pXNAz1h+w==
|
||||
|
||||
"@dicebear/big-smile@7.0.1":
|
||||
version "7.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@dicebear/big-smile/-/big-smile-7.0.1.tgz#f16b526a7559abb5f032f82351e7e8d25d7dd5a9"
|
||||
integrity sha512-hVAhUMZ0LUhMFvtmUDR8GU7v2ufl5pOcVPiVSC3oV8nyywFp7s1ZqYGhi6rBCEG3qsMR54JfMFWkjV88j4Yrmg==
|
||||
|
||||
"@dicebear/bottts-neutral@7.0.1":
|
||||
version "7.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@dicebear/bottts-neutral/-/bottts-neutral-7.0.1.tgz#ee272b0bb4af0fb5cff0d3a6c1b8492ec1c8a2f9"
|
||||
integrity sha512-1T1NEKAEvqyGlUprkO1Q1btITZnMBiCP5YeCy6wYyM7qJsPVDSySsjASJ1j/+IZFi8ePgWReFIbigFiHdo7iLA==
|
||||
|
||||
"@dicebear/bottts@7.0.1":
|
||||
version "7.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@dicebear/bottts/-/bottts-7.0.1.tgz#050c6a13388e8c7002c4d275525169e271c55dcb"
|
||||
integrity sha512-k0adSvnT9+gFDO7/Cmts9TM3CSWYrZrxZe1WpELjTvwe4QOqdn3LgrYR9JXU/2hRz3GaXtP02SHNd85CkadYVw==
|
||||
|
||||
"@dicebear/collection@^7.0.1":
|
||||
version "7.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@dicebear/collection/-/collection-7.0.1.tgz#822edfed1309ab7aa3588a7d1cb635afd4b8579b"
|
||||
integrity sha512-Y5xzjU2hiklYUkqsSr5VBpVPG++iUUTm1UDJLPM+iXg3lMF3PQuifXoaAxcuoBvvnKfJKNHf5wP1Bq6nRUl4NA==
|
||||
dependencies:
|
||||
"@dicebear/adventurer" "7.0.1"
|
||||
"@dicebear/adventurer-neutral" "7.0.1"
|
||||
"@dicebear/avataaars" "7.0.1"
|
||||
"@dicebear/avataaars-neutral" "7.0.1"
|
||||
"@dicebear/big-ears" "7.0.1"
|
||||
"@dicebear/big-ears-neutral" "7.0.1"
|
||||
"@dicebear/big-smile" "7.0.1"
|
||||
"@dicebear/bottts" "7.0.1"
|
||||
"@dicebear/bottts-neutral" "7.0.1"
|
||||
"@dicebear/croodles" "7.0.1"
|
||||
"@dicebear/croodles-neutral" "7.0.1"
|
||||
"@dicebear/fun-emoji" "7.0.1"
|
||||
"@dicebear/icons" "7.0.1"
|
||||
"@dicebear/identicon" "7.0.1"
|
||||
"@dicebear/initials" "7.0.1"
|
||||
"@dicebear/lorelei" "7.0.1"
|
||||
"@dicebear/lorelei-neutral" "7.0.1"
|
||||
"@dicebear/micah" "7.0.1"
|
||||
"@dicebear/miniavs" "7.0.1"
|
||||
"@dicebear/notionists" "7.0.1"
|
||||
"@dicebear/notionists-neutral" "7.0.1"
|
||||
"@dicebear/open-peeps" "7.0.1"
|
||||
"@dicebear/personas" "7.0.1"
|
||||
"@dicebear/pixel-art" "7.0.1"
|
||||
"@dicebear/pixel-art-neutral" "7.0.1"
|
||||
"@dicebear/rings" "7.0.1"
|
||||
"@dicebear/shapes" "7.0.1"
|
||||
"@dicebear/thumbs" "7.0.1"
|
||||
|
||||
"@dicebear/converter@7.0.1":
|
||||
version "7.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@dicebear/converter/-/converter-7.0.1.tgz#3ff9049c0cecb015d0f4549454c62f211a0dab0a"
|
||||
integrity sha512-CEIF6ZKi1FAE9kW10FvuPUjA6HLi+LcuB/GRFct/Bv28llzTel9xwbmfOEa1aIM8Nnp8BuT4U7tBIytksf+ptw==
|
||||
dependencies:
|
||||
"@types/json-schema" "^7.0.11"
|
||||
tmp-promise "^3.0.3"
|
||||
|
||||
"@dicebear/core@^7.0.1":
|
||||
version "7.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@dicebear/core/-/core-7.0.1.tgz#a43bfa851e00f522a0f50fc7b5aaad117389000a"
|
||||
integrity sha512-jaJG693c+myLocgG3kKXdHa+WJ+S6OcD31SEr9Oby7hhOzALQYD+LcJ15oBWwI7SLHJcGPYTOLyx2eDr8YhXCQ==
|
||||
dependencies:
|
||||
"@dicebear/converter" "7.0.1"
|
||||
"@types/json-schema" "^7.0.11"
|
||||
|
||||
"@dicebear/croodles-neutral@7.0.1":
|
||||
version "7.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@dicebear/croodles-neutral/-/croodles-neutral-7.0.1.tgz#f3fcda48aa4e9dfd9366013cb53e2806dae6907b"
|
||||
integrity sha512-u09YylowZcbSAVyKJ4I8BCo1ehluqg3onYCclx++8mOWcEo+XGsGKIeN7osayaflNY/qtA9Jt2JsPgiS8KpQ5A==
|
||||
|
||||
"@dicebear/croodles@7.0.1":
|
||||
version "7.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@dicebear/croodles/-/croodles-7.0.1.tgz#6ceee52434046dfbeb8ff674f240a307c6d5a006"
|
||||
integrity sha512-uauBTUvKFvsiaT+LWYKCEboEeOJy2Pk055nsdczi13UgHHfj+Qvy0/ky/uzYn+WC/1gewqQ6w/yS1WfpgPtIpg==
|
||||
|
||||
"@dicebear/fun-emoji@7.0.1":
|
||||
version "7.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@dicebear/fun-emoji/-/fun-emoji-7.0.1.tgz#e6ac7bbe755ae34a03a5dee4646a5b7ae5622ab6"
|
||||
integrity sha512-oJj5sb4rakro4e0lZTCkcKkiClHxDWr6+NWTwoU5L1HYRkXV6ngk4s7xSdOrYBQpYjLhdu+Lpx1VHYNpLUu2vg==
|
||||
|
||||
"@dicebear/icons@7.0.1":
|
||||
version "7.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@dicebear/icons/-/icons-7.0.1.tgz#b02cfb4fc5f527c085dca4d26a7f23f36cca1aa4"
|
||||
integrity sha512-juHS4feScGCz4YdiwjxR60RJ2G7Z6W+tdUqNHN9ufMvY/FpJTfrQvzvrJfJfc84QZwIrqI/96WV3JIBEIO2AwQ==
|
||||
|
||||
"@dicebear/identicon@7.0.1":
|
||||
version "7.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@dicebear/identicon/-/identicon-7.0.1.tgz#b8b7031c18606a7aee9c961b8abde30917d84a52"
|
||||
integrity sha512-9W9pqqhvpMsZmOkjuLwlw0iift56A3VFq7eNpJPB1mm6gytfqgxozgOVLDFgug9VXgUVI2Jrk/XnXGIFVIeVQA==
|
||||
|
||||
"@dicebear/initials@7.0.1":
|
||||
version "7.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@dicebear/initials/-/initials-7.0.1.tgz#a53b6352c879a140add756de0c9d427ae6693059"
|
||||
integrity sha512-zCI6fky4odM5ezl/GlhcSdnu+oNfmBbIghFB5NzgB/wV5nHmw2okONRC+Mgmxv8P8EpFb9z5hEOnh8xwW8htow==
|
||||
|
||||
"@dicebear/lorelei-neutral@7.0.1":
|
||||
version "7.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@dicebear/lorelei-neutral/-/lorelei-neutral-7.0.1.tgz#e985886dfe42ddc73f9411e7cc591ad7d9b15911"
|
||||
integrity sha512-4XaqE5v1dhE4TYrKSGG/VNUFqA31ADlqOnr6bd27E5MnaJLlY8ZAm3sue7EI9kEJ/i5KYov+Q4uS7JNDA5+cag==
|
||||
|
||||
"@dicebear/lorelei@7.0.1":
|
||||
version "7.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@dicebear/lorelei/-/lorelei-7.0.1.tgz#3106ae79123eb1d1684ea29e82d614d26d72c7b0"
|
||||
integrity sha512-3pyI2JF70PlqZUZEs5pVxmQWDJ2/bWmGG/iFtwsEh9HivtF8Zon4Er0NrsEoiKDvScyY4VGwl4LyUBc8JvNb9w==
|
||||
|
||||
"@dicebear/micah@7.0.1":
|
||||
version "7.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@dicebear/micah/-/micah-7.0.1.tgz#7637beac297171694123d6f4722814aebc800d10"
|
||||
integrity sha512-zHnEewRaREZGNTqnlZiSoha/wNFxEsVQ3E5QYpe9KB3rcLW4CVUgFAHjb449vniG6NfsAWzyAkOfhy4N6Zzw0g==
|
||||
|
||||
"@dicebear/miniavs@7.0.1":
|
||||
version "7.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@dicebear/miniavs/-/miniavs-7.0.1.tgz#7e3fdc6085448caf08b43c8390e9691a7d990662"
|
||||
integrity sha512-v0n2JT0N1I7vAGoi4NQ98IKtn4JgjwD2Gkqq7l5QAy0jzl1v289FfTng0cOrthroMGBQ5jPS0wUyI0TluoFZRw==
|
||||
|
||||
"@dicebear/notionists-neutral@7.0.1":
|
||||
version "7.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@dicebear/notionists-neutral/-/notionists-neutral-7.0.1.tgz#6a916d0fd5b0d6d9ccca0bf3b14f8eec48a7bbc0"
|
||||
integrity sha512-jRA7u2UU1I9EXzqBZL3vwI/V7pdDT60yB3bBjyD5J4TznT7bMwt7qEm1eV31U37mn3H+LTFiPD9/4G6whiU3nQ==
|
||||
|
||||
"@dicebear/notionists@7.0.1":
|
||||
version "7.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@dicebear/notionists/-/notionists-7.0.1.tgz#83d635ddc8842f76dc9d45b9322e929c20cc7975"
|
||||
integrity sha512-uEYBywouoUmvWtWARyeqAoQWX1DpvKL33dVxZ5K/ulYd/nXu9WHeFCPaP4tqE5II1XPS4khwneimFN6F1HA5NQ==
|
||||
|
||||
"@dicebear/open-peeps@7.0.1":
|
||||
version "7.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@dicebear/open-peeps/-/open-peeps-7.0.1.tgz#eb78d2f02600dea4a55d21ec73ae3f321553c9cc"
|
||||
integrity sha512-z1gXzd7XXLzSZpOrDPZmnJDXySCUEKmunRdRuWBSRrfIcVkgStZM0y8uuSrs3LpR8U2xcNJN9yO2wNRRWKmFEw==
|
||||
|
||||
"@dicebear/personas@7.0.1":
|
||||
version "7.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@dicebear/personas/-/personas-7.0.1.tgz#74e494a401ac6126bb22d63ad398e44e3833fd5c"
|
||||
integrity sha512-6/nsrN7JIlMqdH7UwhrACVoCEM3IVHkpMq2I0A1JbhmYp240TI8kM5xYSF0KRdOyAPbyDH/TEB8Uld4LKE+3wQ==
|
||||
|
||||
"@dicebear/pixel-art-neutral@7.0.1":
|
||||
version "7.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@dicebear/pixel-art-neutral/-/pixel-art-neutral-7.0.1.tgz#1c1b11928afd9b8d789e5e885d37bf02b2dea880"
|
||||
integrity sha512-+9RS0ohGDbPu+W2eGGk3LyzvFbM5qsuhCQR4qO7YIcvmODyNFPJ7eW9g/MHFVPLQXq60SCEUF5CEKY0xs4baUQ==
|
||||
|
||||
"@dicebear/pixel-art@7.0.1":
|
||||
version "7.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@dicebear/pixel-art/-/pixel-art-7.0.1.tgz#3027b02feb5f8f3b9b56b24504ae11ea9539596d"
|
||||
integrity sha512-9f17Ze4533CbHp23E+gRSSZdCUAB5/PieRq6/ZtVOnPI/PfglhhKMKSxQIm/H267gE2Y+VVhHpUTwGlbAgh1Lg==
|
||||
|
||||
"@dicebear/rings@7.0.1":
|
||||
version "7.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@dicebear/rings/-/rings-7.0.1.tgz#643ca6499a8864174abd14e44549c158200ff9eb"
|
||||
integrity sha512-6wsLE4kbkBGeaaEA/afIV0eNYYfIVXo60XgApJA7JdcwyvdTa9LE5Wcp2VBEsZYXdsT9Ml7BC4er/QyMqCayUw==
|
||||
|
||||
"@dicebear/shapes@7.0.1":
|
||||
version "7.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@dicebear/shapes/-/shapes-7.0.1.tgz#77ca1e85a104378c9f18a6ab346cca7799de3e34"
|
||||
integrity sha512-/ol+SazDlJYYe5pYaqKcnYDBjux+2Ny57hIrkHhonV0z4ny3Pq6c4Lq+hN3MnTBpKJszCXLrSP3uCbSQpjnkOg==
|
||||
|
||||
"@dicebear/thumbs@7.0.1":
|
||||
version "7.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@dicebear/thumbs/-/thumbs-7.0.1.tgz#5e3883ea5ece77d9e6dbf906a4a3de15467b7e50"
|
||||
integrity sha512-eQYVJ8NN9buPfbd2Va0fY8sHRq9n1d7FJt/dL9xwimRGlpWh9lqS6gcHazuSHhSgnRHsHLANEiyboIcyhWh2Hg==
|
||||
|
||||
"@esbuild/android-arm64@0.19.8":
|
||||
version "0.19.8"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.19.8.tgz#fb7130103835b6d43ea499c3f30cfb2b2ed58456"
|
||||
|
@ -280,6 +470,11 @@
|
|||
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4"
|
||||
integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==
|
||||
|
||||
"@types/json-schema@^7.0.11":
|
||||
version "7.0.15"
|
||||
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841"
|
||||
integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==
|
||||
|
||||
"@types/pug@^2.0.6":
|
||||
version "2.0.10"
|
||||
resolved "https://registry.yarnpkg.com/@types/pug/-/pug-2.0.10.tgz#52f8dbd6113517aef901db20b4f3fca543b88c1f"
|
||||
|
@ -987,6 +1182,13 @@ rimraf@^2.5.2:
|
|||
dependencies:
|
||||
glob "^7.1.3"
|
||||
|
||||
rimraf@^3.0.0:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a"
|
||||
integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==
|
||||
dependencies:
|
||||
glob "^7.1.3"
|
||||
|
||||
rollup@^4.2.0:
|
||||
version "4.6.1"
|
||||
resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.6.1.tgz#351501c86b5b4f976dde8c5837516452b59921f8"
|
||||
|
@ -1165,6 +1367,20 @@ thenify-all@^1.0.0:
|
|||
dependencies:
|
||||
any-promise "^1.0.0"
|
||||
|
||||
tmp-promise@^3.0.3:
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/tmp-promise/-/tmp-promise-3.0.3.tgz#60a1a1cc98c988674fcbfd23b6e3367bdeac4ce7"
|
||||
integrity sha512-RwM7MoPojPxsOBYnyd2hy0bxtIlVrihNs9pj5SUvY8Zz1sQcQG2tG1hSr8PDxfgEB8RNKDhqbIlroIarSNDNsQ==
|
||||
dependencies:
|
||||
tmp "^0.2.0"
|
||||
|
||||
tmp@^0.2.0:
|
||||
version "0.2.1"
|
||||
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14"
|
||||
integrity sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==
|
||||
dependencies:
|
||||
rimraf "^3.0.0"
|
||||
|
||||
to-regex-range@^5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
|
||||
|
|
Loading…
Reference in a new issue