mirror of
https://github.com/pockethost/pockethost.git
synced 2025-05-19 13:26:42 +00:00
Instance UI refactor
This commit is contained in:
parent
dcf0138dde
commit
59cf4e4956
@ -1,6 +1,8 @@
|
||||
<script>
|
||||
import { page } from '$app/stores'
|
||||
import AlertBar from '$components/AlertBar.svelte'
|
||||
import { assert } from '$shared'
|
||||
import { INSTANCE_ADMIN_URL } from '$src/env'
|
||||
import { globalInstancesStore } from '$util/stores'
|
||||
import { instance } from './store'
|
||||
|
||||
@ -14,9 +16,77 @@
|
||||
}
|
||||
isReady = !!_instance
|
||||
}
|
||||
|
||||
console.log($page.url)
|
||||
|
||||
$: ({ status, version, id } = $instance || {})
|
||||
</script>
|
||||
|
||||
{#if isReady}
|
||||
<div
|
||||
class="flex md:flex-row flex-col items-center justify-between mb-6 gap-4"
|
||||
>
|
||||
<div>
|
||||
<h2
|
||||
class="text-4xl md:text-left text-center text-base-content font-bold capitalize mb-3 break-words"
|
||||
>
|
||||
{$instance.subdomain}
|
||||
</h2>
|
||||
|
||||
<div class="flex flex-wrap md:justify-start justify-center gap-2">
|
||||
<div class="badge badge-accent badge-outline">
|
||||
Status: <span class="capitalize">{status}</span>
|
||||
</div>
|
||||
|
||||
<div class="badge badge-accent badge-outline">Version: {version}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<a
|
||||
href={INSTANCE_ADMIN_URL($instance.subdomain)}
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
class="btn btn-primary"
|
||||
>
|
||||
<img
|
||||
src="/images/pocketbase-logo.svg"
|
||||
alt="PocketBase Logo"
|
||||
class="w-6"
|
||||
/>
|
||||
Admin
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{#if $instance.maintenance}
|
||||
<AlertBar
|
||||
message="This instance is in Maintenance Mode and will not respond to requests"
|
||||
type="warning"
|
||||
/>
|
||||
{/if}
|
||||
|
||||
<div role="tablist" class="tabs tabs-boxed">
|
||||
<a
|
||||
role="tab"
|
||||
class="tab {$page.url.pathname.endsWith(id) ? `tab-active` : ``}"
|
||||
href="/app/instances/{id}">Overview</a
|
||||
>
|
||||
<a
|
||||
role="tab"
|
||||
class="tab {$page.url.pathname.endsWith(`logs`) ? `tab-active` : ``}"
|
||||
href="/app/instances/{id}/logs">Logs</a
|
||||
>
|
||||
<a
|
||||
role="tab"
|
||||
class="tab {$page.url.pathname.endsWith(`secrets`) ? `tab-active` : ``}"
|
||||
href="/app/instances/{id}/secrets">Secrets</a
|
||||
>
|
||||
<a
|
||||
role="tab"
|
||||
class="tab {$page.url.pathname.endsWith(`settings`) ? `tab-active` : ``}"
|
||||
href="/app/instances/{id}/settings">Settings</a
|
||||
>
|
||||
</div>
|
||||
|
||||
<slot />
|
||||
{:else}
|
||||
<div>Instance not found</div>
|
||||
|
@ -1,85 +1,20 @@
|
||||
<script lang="ts">
|
||||
import { assertExists } from '$shared'
|
||||
import { INSTANCE_ADMIN_URL } from '$src/env'
|
||||
import Code from './Code.svelte'
|
||||
import AdminSync from './Danger/AdminSync.svelte'
|
||||
import DangerZoneTitle from './Danger/DangerZoneTitle.svelte'
|
||||
import DeleteInstance from './Danger/DeleteInstance.svelte'
|
||||
import Maintenance from './Danger/Maintenance.svelte'
|
||||
import RenameInstance from './Danger/RenameInstance.svelte'
|
||||
import VersionChange from './Danger/VersionChange/VersionChange.svelte'
|
||||
import Ftp from './Ftpx.svelte'
|
||||
import Logging from './Logging.svelte'
|
||||
import Secrets from './Secrets/Secrets.svelte'
|
||||
import { instance } from './store'
|
||||
import AlertBar from '$components/AlertBar.svelte'
|
||||
|
||||
$: ({ status, version } = $instance)
|
||||
$: ({ status, version, id } = $instance)
|
||||
|
||||
assertExists($instance, `Expected instance here`)
|
||||
const { subdomain } = $instance
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>{subdomain} details - PocketHost</title>
|
||||
<title>{subdomain} overview - PocketHost</title>
|
||||
</svelte:head>
|
||||
|
||||
<div class="flex md:flex-row flex-col items-center justify-between mb-6 gap-4">
|
||||
<div>
|
||||
<h2
|
||||
class="text-4xl md:text-left text-center text-base-content font-bold capitalize mb-3 break-words"
|
||||
>
|
||||
{$instance.subdomain}
|
||||
</h2>
|
||||
|
||||
<div class="flex flex-wrap md:justify-start justify-center gap-2">
|
||||
<div class="badge badge-accent badge-outline">
|
||||
Status: <span class="capitalize">{status}</span>
|
||||
</div>
|
||||
|
||||
<div class="badge badge-accent badge-outline">Version: {version}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<a
|
||||
href={INSTANCE_ADMIN_URL($instance.subdomain)}
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
class="btn btn-primary"
|
||||
>
|
||||
<img src="/images/pocketbase-logo.svg" alt="PocketBase Logo" class="w-6" />
|
||||
Admin
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{#if $instance.maintenance}
|
||||
<AlertBar
|
||||
message="This instance is in Maintenance Mode and will not respond to requests"
|
||||
type="warning"
|
||||
/>
|
||||
{/if}
|
||||
|
||||
<div class="grid lg:grid-cols-2 grid-cols-1 gap-4 mb-4">
|
||||
<Code />
|
||||
<Logging />
|
||||
</div>
|
||||
|
||||
<div class="grid lg:grid-cols-2 grid-cols-1 gap-4 mb-16">
|
||||
<Ftp />
|
||||
|
||||
<Secrets />
|
||||
</div>
|
||||
|
||||
<DangerZoneTitle />
|
||||
|
||||
<div class="grid lg:grid-cols-3 gap-4 mb-4">
|
||||
<RenameInstance />
|
||||
|
||||
<Maintenance />
|
||||
|
||||
<VersionChange />
|
||||
|
||||
<AdminSync />
|
||||
|
||||
<DeleteInstance />
|
||||
</div>
|
||||
|
@ -1,82 +0,0 @@
|
||||
<script lang="ts">
|
||||
import CodeSample from '$components/CodeSample.svelte'
|
||||
import Card from '$components/cards/Card.svelte'
|
||||
import CardHeader from '$components/cards/CardHeader.svelte'
|
||||
import { forEach } from '@s-libs/micro-dash'
|
||||
import { instance } from '../store'
|
||||
import Form from './Form.svelte'
|
||||
import List from './List.svelte'
|
||||
import { items } from './stores'
|
||||
|
||||
// TODO: Hot Reload is causing an infinite loop in the network tab for some reason. Wasn't able to figure out why
|
||||
|
||||
$: {
|
||||
const { id, secrets } = $instance
|
||||
items.clear()
|
||||
|
||||
forEach(secrets || {}, (value, name) => {
|
||||
items.upsert({ name, value })
|
||||
})
|
||||
}
|
||||
|
||||
// Keep track of which tab the user has selected
|
||||
let activeTab = 0
|
||||
|
||||
// Toggle between the tabs on click
|
||||
const handleTabChange = (id: number) => {
|
||||
activeTab = id
|
||||
}
|
||||
</script>
|
||||
|
||||
<Card>
|
||||
<CardHeader>Secrets</CardHeader>
|
||||
|
||||
<p class="mb-4">
|
||||
These secrets are passed into your <code>pocketbase</code> executable and
|
||||
can be accessed from <code>pb_hooks</code> JS hooks.
|
||||
</p>
|
||||
|
||||
<!-- If the user has any secrets, render them in a code block -->
|
||||
{#if $items.length > 0}
|
||||
<div class="mb-8">
|
||||
<CodeSample code={`const YOUR_KEY = process.env.YOUR_KEY`} />
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if $items.length === 0}
|
||||
<div class="alert border-2 border-neutral mb-8">
|
||||
<i class="fa-regular fa-shield-keyhole"></i>
|
||||
<span>No Environment Variables Found</span>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div class="tabs mb-4 border-b-[1px] border-neutral">
|
||||
<button
|
||||
on:click={() => handleTabChange(0)}
|
||||
type="button"
|
||||
class="tab border-b-2 {activeTab === 0
|
||||
? 'tab-active font-bold border-base-content'
|
||||
: 'border-neutral'}"
|
||||
><i class="fa-regular fa-plus mr-2"></i> Add New</button
|
||||
>
|
||||
|
||||
<button
|
||||
on:click={() => handleTabChange(1)}
|
||||
type="button"
|
||||
class="tab border-b-2 {activeTab === 1
|
||||
? 'tab-active font-bold border-base-content'
|
||||
: 'border-neutral'}"
|
||||
><i class="fa-regular fa-list mr-2"></i> Current List</button
|
||||
>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
{#if activeTab === 0}
|
||||
<Form />
|
||||
{/if}
|
||||
|
||||
{#if activeTab === 1}
|
||||
<List />
|
||||
{/if}
|
||||
</div>
|
||||
</Card>
|
@ -0,0 +1,16 @@
|
||||
<script lang="ts">
|
||||
import { assertExists } from '$shared'
|
||||
import { instance } from '../store'
|
||||
import LoggingInner from './LoggingInner.svelte'
|
||||
|
||||
$: ({ status, version, id } = $instance)
|
||||
|
||||
assertExists($instance, `Expected instance here`)
|
||||
const { subdomain } = $instance
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>{subdomain} logging - PocketHost</title>
|
||||
</svelte:head>
|
||||
|
||||
<LoggingInner />
|
@ -0,0 +1,11 @@
|
||||
<script lang="ts">
|
||||
import Card from '$components/cards/Card.svelte'
|
||||
import CardHeader from '$components/cards/CardHeader.svelte'
|
||||
import LoggingInner from './LoggingInner.svelte'
|
||||
</script>
|
||||
|
||||
<Card>
|
||||
<CardHeader>Instance Logging</CardHeader>
|
||||
|
||||
<LoggingInner /></Card
|
||||
>
|
@ -1,12 +1,10 @@
|
||||
<script lang="ts">
|
||||
import Card from '$components/cards/Card.svelte'
|
||||
import CardHeader from '$components/cards/CardHeader.svelte'
|
||||
import { StreamNames, Unsubscribe, type InstanceLogFields } from '$shared'
|
||||
import { client } from '$src/pocketbase-client'
|
||||
import { mkCleanup } from '$util/componentCleanup'
|
||||
import { onMount } from 'svelte'
|
||||
import { derived, writable } from 'svelte/store'
|
||||
import { instance } from './store'
|
||||
import { instance } from '../store'
|
||||
|
||||
$: ({ id } = $instance)
|
||||
|
||||
@ -57,15 +55,12 @@
|
||||
})
|
||||
</script>
|
||||
|
||||
<Card>
|
||||
<CardHeader>Instance Logging</CardHeader>
|
||||
|
||||
<p class="mb-4">
|
||||
<p class="mb-4">
|
||||
Instance logs appear here in realtime, including <code>console.log</code> from
|
||||
JavaScript hooks.
|
||||
</p>
|
||||
</p>
|
||||
|
||||
<dialog id="loggingFullscreenModal" class="modal backdrop-blur">
|
||||
<dialog id="loggingFullscreenModal" class="modal backdrop-blur">
|
||||
<div class="modal-box max-w-[90vw] h-[90vh]">
|
||||
<h3 class="font-bold text-lg">Instance Logging</h3>
|
||||
|
||||
@ -94,9 +89,9 @@
|
||||
<form method="dialog" class="modal-backdrop">
|
||||
<button>close</button>
|
||||
</form>
|
||||
</dialog>
|
||||
</dialog>
|
||||
|
||||
<div class="mockup-code">
|
||||
<div class="mockup-code">
|
||||
<button
|
||||
class="btn btn-sm absolute top-[6px] right-[6px]"
|
||||
on:click={handleFullScreenModal}
|
||||
@ -104,10 +99,7 @@
|
||||
>
|
||||
<div class="h-[450px] flex flex-col overflow-y-scroll gap-3">
|
||||
{#each $logs as log}
|
||||
<div
|
||||
class="px-4 text-[11px] font-mono flex align-center"
|
||||
data-prefix=">"
|
||||
>
|
||||
<div class="px-4 text-[11px] font-mono flex align-center" data-prefix=">">
|
||||
<span class="mr-2"
|
||||
><i class="fa-regular fa-angle-right text-accent"></i></span
|
||||
>
|
||||
@ -122,5 +114,4 @@
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
@ -0,0 +1,16 @@
|
||||
<script lang="ts">
|
||||
import { assertExists } from '$shared'
|
||||
import { instance } from '../store'
|
||||
import SecretsInner from './SecretsInner.svelte'
|
||||
|
||||
$: ({ status, version, id } = $instance)
|
||||
|
||||
assertExists($instance, `Expected instance here`)
|
||||
const { subdomain } = $instance
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>{subdomain} secrets - PocketHost</title>
|
||||
</svelte:head>
|
||||
|
||||
<SecretsInner />
|
@ -0,0 +1,11 @@
|
||||
<script lang="ts">
|
||||
import Card from '$components/cards/Card.svelte'
|
||||
import CardHeader from '$components/cards/CardHeader.svelte'
|
||||
import SecretsInner from './SecretsInner.svelte'
|
||||
</script>
|
||||
|
||||
<Card>
|
||||
<CardHeader>Secrets</CardHeader>
|
||||
|
||||
<SecretsInner />
|
||||
</Card>
|
@ -0,0 +1,76 @@
|
||||
<script lang="ts">
|
||||
import CodeSample from '$components/CodeSample.svelte'
|
||||
import { forEach } from '@s-libs/micro-dash'
|
||||
import { instance } from '../store'
|
||||
import Form from './Form.svelte'
|
||||
import List from './List.svelte'
|
||||
import { items } from './stores'
|
||||
|
||||
// TODO: Hot Reload is causing an infinite loop in the network tab for some reason. Wasn't able to figure out why
|
||||
|
||||
$: {
|
||||
const { id, secrets } = $instance
|
||||
items.clear()
|
||||
|
||||
forEach(secrets || {}, (value, name) => {
|
||||
items.upsert({ name, value })
|
||||
})
|
||||
}
|
||||
|
||||
// Keep track of which tab the user has selected
|
||||
let activeTab = 0
|
||||
|
||||
// Toggle between the tabs on click
|
||||
const handleTabChange = (id: number) => {
|
||||
activeTab = id
|
||||
}
|
||||
</script>
|
||||
|
||||
<p class="mb-4">
|
||||
These secrets are passed into your <code>pocketbase</code> executable and can
|
||||
be accessed from <code>pb_hooks</code> JS hooks.
|
||||
</p>
|
||||
|
||||
<!-- If the user has any secrets, render them in a code block -->
|
||||
{#if $items.length > 0}
|
||||
<div class="mb-8">
|
||||
<CodeSample code={`const YOUR_KEY = process.env.YOUR_KEY`} />
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if $items.length === 0}
|
||||
<div class="alert border-2 border-neutral mb-8">
|
||||
<i class="fa-regular fa-shield-keyhole"></i>
|
||||
<span>No Environment Variables Found</span>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div class="tabs mb-4 border-b-[1px] border-neutral">
|
||||
<button
|
||||
on:click={() => handleTabChange(0)}
|
||||
type="button"
|
||||
class="tab border-b-2 {activeTab === 0
|
||||
? 'tab-active font-bold border-base-content'
|
||||
: 'border-neutral'}"
|
||||
><i class="fa-regular fa-plus mr-2"></i> Add New</button
|
||||
>
|
||||
|
||||
<button
|
||||
on:click={() => handleTabChange(1)}
|
||||
type="button"
|
||||
class="tab border-b-2 {activeTab === 1
|
||||
? 'tab-active font-bold border-base-content'
|
||||
: 'border-neutral'}"
|
||||
><i class="fa-regular fa-list mr-2"></i> Current List</button
|
||||
>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
{#if activeTab === 0}
|
||||
<Form />
|
||||
{/if}
|
||||
|
||||
{#if activeTab === 1}
|
||||
<List />
|
||||
{/if}
|
||||
</div>
|
@ -0,0 +1,33 @@
|
||||
<script lang="ts">
|
||||
import { assertExists } from '$shared'
|
||||
import { instance } from '../store'
|
||||
import AdminSync from './AdminSync.svelte'
|
||||
import DangerZoneTitle from './DangerZoneTitle.svelte'
|
||||
import DeleteInstance from './DeleteInstance.svelte'
|
||||
import Maintenance from './Maintenance.svelte'
|
||||
import RenameInstance from './RenameInstance.svelte'
|
||||
import VersionChange from './VersionChange/VersionChange.svelte'
|
||||
|
||||
$: ({ status, version, id } = $instance)
|
||||
|
||||
assertExists($instance, `Expected instance here`)
|
||||
const { subdomain } = $instance
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>{subdomain} overview - PocketHost</title>
|
||||
</svelte:head>
|
||||
|
||||
<DangerZoneTitle />
|
||||
|
||||
<div class="grid lg:grid-cols-3 gap-4 mb-4">
|
||||
<RenameInstance />
|
||||
|
||||
<Maintenance />
|
||||
|
||||
<VersionChange />
|
||||
|
||||
<AdminSync />
|
||||
|
||||
<DeleteInstance />
|
||||
</div>
|
Loading…
x
Reference in New Issue
Block a user