mirror of
https://github.com/pockethost/pockethost.git
synced 2026-03-13 11:54:59 +00:00
dashboard UI cosmetic updates
This commit is contained in:
@@ -1,3 +1,14 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
.prose :where(pre):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
|
||||
@apply mb-1 mt-1;
|
||||
}
|
||||
.prose :where(code):not(:where([class~='not-prose'] *)) {
|
||||
@apply bg-transparent;
|
||||
}
|
||||
|
||||
.prose :where(p):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
|
||||
@apply mt-0 mb-0;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
<script>
|
||||
<script lang="ts">
|
||||
import { page } from '$app/stores'
|
||||
import AlertBar from '$components/AlertBar.svelte'
|
||||
import { INSTANCE_ADMIN_URL } from '$src/env'
|
||||
import { globalInstancesStore } from '$util/stores'
|
||||
import { assert } from 'pockethost/common'
|
||||
import { instance } from './store'
|
||||
import { client } from '$src/pocketbase-client'
|
||||
import { InstanceId } from 'pockethost/common'
|
||||
import Toggle from './Toggle.svelte'
|
||||
|
||||
let isReady = false
|
||||
$: {
|
||||
@@ -17,7 +20,23 @@
|
||||
isReady = !!_instance
|
||||
}
|
||||
|
||||
$: ({ status, version, id } = $instance || {})
|
||||
$: ({ id } = $instance || {})
|
||||
|
||||
const { updateInstance } = client()
|
||||
|
||||
const handleMaintenanceChange = (id: InstanceId) => (isChecked: boolean) => {
|
||||
const maintenance = !isChecked
|
||||
|
||||
// Update the database with the new value
|
||||
updateInstance({ id, fields: { maintenance } })
|
||||
.then(() => 'saved')
|
||||
.catch((error) => {
|
||||
error.data.message || error.message
|
||||
})
|
||||
}
|
||||
|
||||
$: isActive = (path: string) => $page.url.pathname.endsWith(path)
|
||||
$: activeClass = (path: string) => (isActive(path) ? 'text-primary' : '')
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
@@ -27,93 +46,100 @@
|
||||
</svelte:head>
|
||||
|
||||
{#if isReady}
|
||||
<div
|
||||
class="flex md:flex-row flex-col items-center justify-between mb-6 gap-4"
|
||||
>
|
||||
<div class="flex flex-row 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"
|
||||
class="text-4xl md:text-left text-center text-base-content font-bold mb-3 break-words"
|
||||
>
|
||||
{$instance.subdomain}
|
||||
{$instance.subdomain}<span class="text-xs text-gray-400"
|
||||
>.pockethost.io</span
|
||||
>
|
||||
<span class="text-xs text-gray-400">v{$instance.version}</span>
|
||||
</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)}
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
class="btn btn-primary"
|
||||
>
|
||||
<img
|
||||
src="/images/pocketbase-logo.svg"
|
||||
alt="PocketBase Logo"
|
||||
class="w-6"
|
||||
<div>
|
||||
<Toggle
|
||||
title="Power"
|
||||
checked={!$instance.maintenance}
|
||||
onChange={handleMaintenanceChange($instance.id)}
|
||||
/>
|
||||
Admin
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{#if $instance.maintenance}
|
||||
<AlertBar
|
||||
message="This instance is in Maintenance Mode and will not respond to requests"
|
||||
message="This instance is turned off and will not respond to requests"
|
||||
type="warning"
|
||||
/>
|
||||
{/if}
|
||||
|
||||
<div role="tablist" class="tabs tabs-bordered gap-4 mb-4 p-4">
|
||||
<a
|
||||
role="tab"
|
||||
class="tab h-auto md:h-8 flex gap-2 font-bold {$page.url.pathname.endsWith(
|
||||
id,
|
||||
)
|
||||
? `tab-active`
|
||||
: ``}"
|
||||
href="/app/instances/{id}"
|
||||
><i class="fa-light fa-sparkles"></i> Overview</a
|
||||
>
|
||||
<a
|
||||
role="tab"
|
||||
class="tab h-auto md:h-8 flex gap-2 font-bold {$page.url.pathname.endsWith(
|
||||
`logs`,
|
||||
)
|
||||
? `tab-active`
|
||||
: ``}"
|
||||
href="/app/instances/{id}/logs"
|
||||
><i class="fa-light fa-terminal"></i> Logs</a
|
||||
>
|
||||
<a
|
||||
role="tab"
|
||||
class="tab h-auto md:h-8 flex gap-2 font-bold {$page.url.pathname.endsWith(
|
||||
`secrets`,
|
||||
)
|
||||
? `tab-active`
|
||||
: ``}"
|
||||
href="/app/instances/{id}/secrets"
|
||||
><i class="fa-light fa-shield"></i> Secrets</a
|
||||
>
|
||||
<a
|
||||
role="tab"
|
||||
class="tab h-auto md:h-8 flex gap-2 font-bold {$page.url.pathname.endsWith(
|
||||
`settings`,
|
||||
)
|
||||
? `tab-active`
|
||||
: ``}"
|
||||
href="/app/instances/{id}/settings"
|
||||
><i class="fa-light fa-gear"></i> Settings</a
|
||||
>
|
||||
</div>
|
||||
<div class="flex gap-4">
|
||||
<div class="w-48">
|
||||
<ul>
|
||||
<li>
|
||||
<a href={`/app/instances/${id}`} class={activeClass(id)}>Overview</a>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href={`/app/instances/${id}/secrets`}
|
||||
class={activeClass(`secrets`)}>Secrets</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href={`/app/instances/${id}/logs`} class={activeClass(`logs`)}
|
||||
>Logs</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href={`/app/instances/${id}/ftp`} class={activeClass(`ftp`)}
|
||||
>FTP Access</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href={INSTANCE_ADMIN_URL($instance)}
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
<img
|
||||
src="/images/pocketbase-logo.svg"
|
||||
alt="PocketBase Logo"
|
||||
class="w-6 inline-block"
|
||||
/>
|
||||
Admin
|
||||
<i class="fa-solid fa-external-link-alt text-xs"></i>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="divider"></div>
|
||||
<div class="mt-2 mb-2">
|
||||
<i class="fa-solid fa-siren-on text-error"></i>
|
||||
<span class=" font-bold text-error">Danger Zone</span>
|
||||
<i class="fa-solid fa-siren-on text-error"></i>
|
||||
</div>
|
||||
<ul>
|
||||
<li><a href={`/app/instances/${id}/version`}>Change Version</a></li>
|
||||
<li><a href={`/app/instances/${id}/domain`}>Custom Domain</a></li>
|
||||
<li><a href={`/app/instances/${id}/admin-sync`}>Admin Sync</a></li>
|
||||
<li><a href={`/app/instances/${id}/dev`}>Dev Mode</a></li>
|
||||
<li><a href={`/app/instances/${id}/rename`}>Rename</a></li>
|
||||
<li>
|
||||
<a href={`/app/instances/${id}/delete`} class="btn btn-error btn-xs"
|
||||
>Delete</a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
{#key $page.url.pathname}
|
||||
<slot />
|
||||
{/key}
|
||||
<div class="w-full">
|
||||
{#key $page.url.pathname}
|
||||
<article class="prose">
|
||||
<slot />
|
||||
</article>
|
||||
{/key}
|
||||
</div>
|
||||
</div>
|
||||
{:else}
|
||||
<div>Instance not found</div>
|
||||
{/if}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { assertExists } from 'pockethost/common'
|
||||
import Code from './Code.svelte'
|
||||
import Ftp from './Ftpx.svelte'
|
||||
import Ftp from './ftp/+page.svelte'
|
||||
import { instance } from './store'
|
||||
|
||||
$: ({ status, version, id } = $instance)
|
||||
@@ -10,7 +10,4 @@
|
||||
const { subdomain } = $instance
|
||||
</script>
|
||||
|
||||
<div class="grid lg:grid-cols-2 grid-cols-1 gap-4 mb-4">
|
||||
<Code />
|
||||
<Ftp />
|
||||
</div>
|
||||
<Code />
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<script lang="ts">
|
||||
import CodeSample from '$components/CodeSample.svelte'
|
||||
import Card from '$components/cards/Card.svelte'
|
||||
import CardHeader from '$components/cards/CardHeader.svelte'
|
||||
import { DISCORD_URL, INSTANCE_URL } from '$src/env'
|
||||
import { instance } from './store'
|
||||
|
||||
@@ -19,56 +17,54 @@
|
||||
});`
|
||||
</script>
|
||||
|
||||
<Card>
|
||||
<CardHeader>Getting Started</CardHeader>
|
||||
<h2>Overview</h2>
|
||||
|
||||
<div class="mb-4">
|
||||
<p>Your PocketBase URL is</p>
|
||||
<CodeSample code={url} />
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<p>Your PocketBase URL is</p>
|
||||
<CodeSample code={url} />
|
||||
</div>
|
||||
|
||||
<div class="mb-4">
|
||||
<p>Installing PocketBase</p>
|
||||
<CodeSample code={installSnippet} />
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<p>Installing PocketBase</p>
|
||||
<CodeSample code={installSnippet} />
|
||||
</div>
|
||||
|
||||
<div class="mb-4">
|
||||
<p>Connecting to Your Instance</p>
|
||||
{#if $instance.cname}
|
||||
{#if $instance.cname_active}
|
||||
<div class="text-accent">Notice: You are in Custom Domain mode</div>
|
||||
{:else}
|
||||
<div class="text-error">
|
||||
Notice: You are in Custom Domain mode but it is not active and will
|
||||
not work. Go find <a href={DISCORD_URL} target="_blank" class="link"
|
||||
>@noaxis on Discord</a
|
||||
> to get set up.
|
||||
</div>
|
||||
{/if}
|
||||
<div class="mb-4">
|
||||
<p>Connecting to Your Instance</p>
|
||||
{#if $instance.cname}
|
||||
{#if $instance.cname_active}
|
||||
<div class="text-accent">Notice: You are in Custom Domain mode</div>
|
||||
{:else}
|
||||
<div class="text-error">
|
||||
Notice: You are in Custom Domain mode but it is not active and will not
|
||||
work. Go find <a href={DISCORD_URL} target="_blank" class="link"
|
||||
>@noaxis on Discord</a
|
||||
> to get set up.
|
||||
</div>
|
||||
{/if}
|
||||
<CodeSample code={connectionSnippet} />
|
||||
</div>
|
||||
{/if}
|
||||
<CodeSample code={connectionSnippet} />
|
||||
</div>
|
||||
|
||||
<div class="mb-4">
|
||||
<p>Making Your First Query</p>
|
||||
<CodeSample code={firstQuerySnippet} />
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<p>Making Your First Query</p>
|
||||
<CodeSample code={firstQuerySnippet} />
|
||||
</div>
|
||||
|
||||
<p>Additional Resources:</p>
|
||||
<ul class="list-disc pl-4">
|
||||
<li>
|
||||
<a
|
||||
href={`https://pocketbase.io/docs/api-records/`}
|
||||
target="_blank"
|
||||
class="link">PocketBase Web APIs</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="https://www.npmjs.com/package/pocketbase"
|
||||
target="_blank"
|
||||
class="link">PocketBase NPM Package</a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
</Card>
|
||||
<p>Additional Resources:</p>
|
||||
<ul class="list-disc pl-4">
|
||||
<li>
|
||||
<a
|
||||
href={`https://pocketbase.io/docs/api-records/`}
|
||||
target="_blank"
|
||||
class="link">PocketBase Web APIs</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="https://www.npmjs.com/package/pocketbase"
|
||||
target="_blank"
|
||||
class="link">PocketBase NPM Package</a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@@ -1,63 +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 { DOCS_URL, FTP_URL } from '$src/env'
|
||||
import { client } from '$src/pocketbase-client'
|
||||
import { bash } from 'svelte-highlight/languages'
|
||||
|
||||
const { user } = client()
|
||||
const { email } = user() || {}
|
||||
|
||||
// This will hide the component if the email was not found
|
||||
if (!email) {
|
||||
throw new Error(`Email expected here`)
|
||||
}
|
||||
const ftpUrl = FTP_URL(email)
|
||||
</script>
|
||||
|
||||
<Card>
|
||||
<CardHeader documentation={DOCS_URL(`/usage/ftp`)}>FTP Access</CardHeader>
|
||||
|
||||
<p class="mb-8">
|
||||
Securely access your instance files via FTPS. Use your PocketHost account
|
||||
login and password.
|
||||
</p>
|
||||
|
||||
<p>Bash:</p>
|
||||
|
||||
<div class="mb-12">
|
||||
<CodeSample code={`ftp ${ftpUrl}`} language={bash} />
|
||||
</div>
|
||||
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="border-b-2 border-neutral">Directory</th>
|
||||
<th class="border-b-2 border-neutral">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>pb_data</th>
|
||||
<td
|
||||
>The PocketBase data directory, including upload storage and database
|
||||
backups</td
|
||||
>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>pb_public</th>
|
||||
<td>Public files, such as a web frontend</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>pb_migrations</th>
|
||||
<td>The PocketBase migrations directory</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>pb_hooks</th>
|
||||
<td>The PocketBase JS hooks directory</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</Card>
|
||||
@@ -0,0 +1,35 @@
|
||||
<script lang="ts">
|
||||
export let checked = false
|
||||
export let title = ''
|
||||
export let onClass = 'success'
|
||||
export let offClass = 'red-500'
|
||||
export let onText = 'on'
|
||||
export let offText = 'off'
|
||||
export let onChange = (isChecked: boolean) => {}
|
||||
|
||||
const handleChange = (e: Event) => {
|
||||
const target = e.target as HTMLInputElement
|
||||
const isChecked = target.checked
|
||||
e.preventDefault()
|
||||
onChange(isChecked)
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="form-control w-fit">
|
||||
<label class="label cursor-pointer">
|
||||
<span class="label-text mr-2"
|
||||
>{title} is
|
||||
<span class="text-{checked ? onClass : offClass}"
|
||||
>{checked ? onText : offText}</span
|
||||
></span
|
||||
>
|
||||
<input
|
||||
type="checkbox"
|
||||
class="toggle bg-{checked ? onClass : offClass} hover:bg-{checked
|
||||
? onClass
|
||||
: offClass}"
|
||||
{checked}
|
||||
on:change={handleChange}
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
@@ -0,0 +1,36 @@
|
||||
<script lang="ts">
|
||||
import Card from '$components/cards/Card.svelte'
|
||||
import CardHeader from '$components/cards/CardHeader.svelte'
|
||||
import { DOCS_URL } from '$src/env'
|
||||
import { client } from '$src/pocketbase-client'
|
||||
import { instance } from '../store'
|
||||
import ErrorMessage from '../settings/ErrorMessage.svelte'
|
||||
import Toggle from '../Toggle.svelte'
|
||||
|
||||
const { updateInstance } = client()
|
||||
|
||||
$: ({ id, syncAdmin } = $instance)
|
||||
|
||||
let errorMessage = ''
|
||||
|
||||
const handleChange = (isChecked: boolean) => {
|
||||
// Update the database with the new value
|
||||
updateInstance({ id, fields: { syncAdmin: isChecked } })
|
||||
.then(() => 'saved')
|
||||
.catch((error) => {
|
||||
errorMessage = error.data.message || error.message
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<CardHeader documentation={DOCS_URL(`/usage/admin-sync`)}>
|
||||
Admin Sync
|
||||
</CardHeader>
|
||||
|
||||
<p class="mb-8">
|
||||
Your instance will have an admin login that matches your pockethost.io login.
|
||||
</p>
|
||||
|
||||
<ErrorMessage message={errorMessage} />
|
||||
|
||||
<Toggle title="Admin Sync" checked={!!syncAdmin} onChange={handleChange} />
|
||||
@@ -6,7 +6,8 @@
|
||||
import { client } from '$src/pocketbase-client'
|
||||
import { globalInstancesStore } from '$util/stores'
|
||||
import { instance } from '../store'
|
||||
import ErrorMessage from './ErrorMessage.svelte'
|
||||
import ErrorMessage from '../settings/ErrorMessage.svelte'
|
||||
import AlertBar from '$src/components/AlertBar.svelte'
|
||||
|
||||
$: ({ id, maintenance, version } = $instance)
|
||||
|
||||
@@ -63,37 +64,41 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<Card>
|
||||
<CardHeader documentation={DOCS_URL(`/usage/delete`)}>
|
||||
Delete Instance
|
||||
</CardHeader>
|
||||
<CardHeader documentation={DOCS_URL(`/usage/delete`)}>
|
||||
Delete Instance
|
||||
</CardHeader>
|
||||
|
||||
<div class="mb-8">
|
||||
Deleting your instance will immediately and permanently delete your
|
||||
instance:
|
||||
<ul class="ml-10 text-error">
|
||||
<li>Your subdomain</li>
|
||||
<li><pre>pb_data/*</pre></li>
|
||||
<li><pre>pb_public/*</pre></li>
|
||||
<li><pre>pb_migrations/*</pre></li>
|
||||
<li><pre>pb_static/*</pre></li>
|
||||
</ul>
|
||||
If you are storing files on S3, you must delete them separately.
|
||||
</div>
|
||||
{#if !maintenance}
|
||||
<AlertBar
|
||||
message="Instance must be powered off before deleting."
|
||||
type="error"
|
||||
/>
|
||||
{/if}
|
||||
|
||||
<ErrorMessage message={errorMessage} />
|
||||
<div class="mb-8">
|
||||
Deleting your instance will immediately and permanently delete your instance:
|
||||
<ul class="ml-10 text-error">
|
||||
<li>Your subdomain</li>
|
||||
<li><pre>pb_data/*</pre></li>
|
||||
<li><pre>pb_public/*</pre></li>
|
||||
<li><pre>pb_migrations/*</pre></li>
|
||||
<li><pre>pb_static/*</pre></li>
|
||||
</ul>
|
||||
If you are storing files on S3, you must delete them separately.
|
||||
</div>
|
||||
|
||||
<form
|
||||
class="flex change-version-form-container-query gap-4"
|
||||
on:submit={handleSave}
|
||||
<ErrorMessage message={errorMessage} />
|
||||
|
||||
<form
|
||||
class="flex change-version-form-container-query gap-4"
|
||||
on:submit={handleSave}
|
||||
>
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-error"
|
||||
disabled={!maintenance || isButtonDisabled}>Delete Instance</button
|
||||
>
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-error"
|
||||
disabled={!maintenance || isButtonDisabled}>Delete Instance</button
|
||||
>
|
||||
</form>
|
||||
</Card>
|
||||
</form>
|
||||
|
||||
<style>
|
||||
.change-version-form-container-query {
|
||||
@@ -0,0 +1,39 @@
|
||||
<script lang="ts">
|
||||
import Card from '$components/cards/Card.svelte'
|
||||
import CardHeader from '$components/cards/CardHeader.svelte'
|
||||
import { DOCS_URL } from '$src/env'
|
||||
import { client } from '$src/pocketbase-client'
|
||||
import { instance } from '../store'
|
||||
import ErrorMessage from '../settings/ErrorMessage.svelte'
|
||||
import Toggle from '../Toggle.svelte'
|
||||
|
||||
const { updateInstance } = client()
|
||||
|
||||
$: ({ id, dev } = $instance)
|
||||
|
||||
let errorMessage = ''
|
||||
|
||||
const handleChange = (isChecked: boolean) => {
|
||||
updateInstance({ id, fields: { dev: isChecked } })
|
||||
.then(() => 'saved')
|
||||
.catch((error) => {
|
||||
errorMessage = error.data.message || error.message
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<CardHeader documentation={DOCS_URL(`/usage/dev-mode`)}>Dev Mode</CardHeader>
|
||||
|
||||
<p class="mb-8">
|
||||
Starting with PocketBase v0.20.1, your instance will show debugging output in
|
||||
the instance logs. Performance is degraded while Dev Mode is active.
|
||||
</p>
|
||||
|
||||
<ErrorMessage message={errorMessage} />
|
||||
|
||||
<Toggle
|
||||
title="Dev Mode"
|
||||
onChange={handleChange}
|
||||
checked={!!dev}
|
||||
onClass="warning"
|
||||
/>
|
||||
@@ -31,7 +31,9 @@
|
||||
/^(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,24}$/
|
||||
|
||||
$: {
|
||||
isButtonDisabled = !!formCname.trim() && !regex.test(formCname)
|
||||
isButtonDisabled =
|
||||
(!!formCname.trim() && !regex.test(formCname)) ||
|
||||
(!formCname.trim() && !cname.trim())
|
||||
}
|
||||
const onRename = (e: Event) => {
|
||||
e.preventDefault()
|
||||
@@ -76,54 +78,52 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<Card>
|
||||
<CardHeader documentation={DOCS_URL(`/usage/custom-domain`)}>
|
||||
Custom Domain (CNAME)
|
||||
</CardHeader>
|
||||
<CardHeader documentation={DOCS_URL(`/usage/custom-domain`)}>
|
||||
Custom Domain (CNAME)
|
||||
</CardHeader>
|
||||
|
||||
<div class="mb-8">
|
||||
Use a custom domain (CNAME) with your PocketHost instance.
|
||||
</div>
|
||||
{#if formCname && regex.test(formCname.trim())}
|
||||
<div class="mb-8">Go to your DNS provider and add a CNAME entry.</div>
|
||||
<div class="mb-4">
|
||||
<CodeSample
|
||||
code={`${formCname} CNAME ${INSTANCE_BARE_HOST($instance)}`}
|
||||
language={dns}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<AlertBar message={successMessage} type="success" />
|
||||
<AlertBar message={errorMessage} type="error" />
|
||||
|
||||
{#if cname}
|
||||
{#if !cname_active}
|
||||
<AlertBar
|
||||
message={`Your custom domain name is pending. Go find <a class='btn btn-primary' target='_blank' href="https://discord.com/channels/1128192380500193370/1189948945967882250">@noaxis on Discord</a> to complete setup.`}
|
||||
type="warning"
|
||||
/>
|
||||
{:else}
|
||||
<AlertBar message={`Your custom domain name is active.`} type="success" />
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
<form
|
||||
class="flex rename-instance-form-container-query gap-4"
|
||||
on:submit={onRename}
|
||||
>
|
||||
<input
|
||||
title="Only valid domain name patterns are allowed"
|
||||
type="text"
|
||||
bind:value={formCname}
|
||||
class="input input-bordered w-full"
|
||||
<div class="mb-8">
|
||||
Use a custom domain (CNAME) with your PocketHost instance.
|
||||
</div>
|
||||
{#if formCname && regex.test(formCname.trim())}
|
||||
<div class="mb-8">Go to your DNS provider and add a CNAME entry.</div>
|
||||
<div class="mb-4">
|
||||
<CodeSample
|
||||
code={`${formCname} CNAME ${INSTANCE_BARE_HOST($instance)}`}
|
||||
language={dns}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<button type="submit" class="btn btn-error" disabled={isButtonDisabled}
|
||||
>Update Custom Domain</button
|
||||
>
|
||||
</form>
|
||||
</Card>
|
||||
<AlertBar message={successMessage} type="success" />
|
||||
<AlertBar message={errorMessage} type="error" />
|
||||
|
||||
{#if cname}
|
||||
{#if !cname_active}
|
||||
<AlertBar
|
||||
message={`Your custom domain name is pending. Go find <a class='btn btn-primary' target='_blank' href="https://discord.com/channels/1128192380500193370/1189948945967882250">@noaxis on Discord</a> to complete setup.`}
|
||||
type="warning"
|
||||
/>
|
||||
{:else}
|
||||
<AlertBar message={`Your custom domain name is active.`} type="success" />
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
<form
|
||||
class="flex rename-instance-form-container-query gap-4"
|
||||
on:submit={onRename}
|
||||
>
|
||||
<input
|
||||
title="Only valid domain name patterns are allowed"
|
||||
type="text"
|
||||
bind:value={formCname}
|
||||
class="input input-bordered w-full"
|
||||
/>
|
||||
|
||||
<button type="submit" class="btn btn-error" disabled={isButtonDisabled}
|
||||
>Update Custom Domain</button
|
||||
>
|
||||
</form>
|
||||
|
||||
<style>
|
||||
.rename-instance-form-container-query {
|
||||
@@ -0,0 +1,58 @@
|
||||
<script lang="ts">
|
||||
import CodeSample from '$components/CodeSample.svelte'
|
||||
import Card from '$components/cards/Card.svelte'
|
||||
import CardHeader from '$components/cards/CardHeader.svelte'
|
||||
import { DOCS_URL, FTP_URL } from '$src/env'
|
||||
import { client } from '$src/pocketbase-client'
|
||||
import { bash } from 'svelte-highlight/languages'
|
||||
|
||||
const { user } = client()
|
||||
const { email } = user() || {}
|
||||
|
||||
// This will hide the component if the email was not found
|
||||
if (!email) {
|
||||
throw new Error(`Email expected here`)
|
||||
}
|
||||
const ftpUrl = FTP_URL(email)
|
||||
</script>
|
||||
|
||||
<h2>FTP Access</h2>
|
||||
<div class="mb-8">
|
||||
Securely access your instance files via FTPS. Use your PocketHost account
|
||||
login and password.
|
||||
</div>
|
||||
|
||||
<div class="mb-12">
|
||||
<CodeSample code={`ftp ${ftpUrl}`} language={bash} />
|
||||
</div>
|
||||
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="border-b-2 border-neutral">Directory</th>
|
||||
<th class="border-b-2 border-neutral">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>pb_data</th>
|
||||
<td
|
||||
>The PocketBase data directory, including upload storage and database
|
||||
backups</td
|
||||
>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>pb_public</th>
|
||||
<td>Public files, such as a web frontend</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>pb_migrations</th>
|
||||
<td>The PocketBase migrations directory</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>pb_hooks</th>
|
||||
<td>The PocketBase JS hooks directory</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
@@ -82,10 +82,12 @@
|
||||
})
|
||||
</script>
|
||||
|
||||
<p class="mb-4">
|
||||
<h2>Logs</h2>
|
||||
|
||||
<div class="mb-4">
|
||||
Instance logs appear here in realtime, including <code>console.log</code> from
|
||||
JavaScript hooks.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<dialog id="loggingFullscreenModal" class="modal backdrop-blur">
|
||||
<div class="modal-box max-w-[90vw] h-[90vh]">
|
||||
|
||||
@@ -56,37 +56,35 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<Card>
|
||||
<CardHeader documentation={DOCS_URL(`/usage/rename-instance`)}>
|
||||
Rename Instance
|
||||
</CardHeader>
|
||||
<CardHeader documentation={DOCS_URL(`/usage/rename-instance`)}>
|
||||
Rename Instance
|
||||
</CardHeader>
|
||||
|
||||
<p class="mb-8">
|
||||
Renaming your instance will cause it to become <strong class="text-error"
|
||||
>inaccessible</strong
|
||||
> by the old instance name. You also may not be able to change it back if someone
|
||||
else choose it.
|
||||
</p>
|
||||
<p class="mb-8">
|
||||
Renaming your instance will cause it to become <strong class="text-error"
|
||||
>inaccessible</strong
|
||||
> by the old instance name. You also may not be able to change it back if someone
|
||||
else choose it.
|
||||
</p>
|
||||
|
||||
<AlertBar message={errorMessage} type="error" />
|
||||
<AlertBar message={errorMessage} type="error" />
|
||||
|
||||
<form
|
||||
class="flex rename-instance-form-container-query gap-4"
|
||||
on:submit={onRename}
|
||||
<form
|
||||
class="flex rename-instance-form-container-query gap-4"
|
||||
on:submit={onRename}
|
||||
>
|
||||
<input
|
||||
title="Only letters and dashes are allowed"
|
||||
required
|
||||
type="text"
|
||||
bind:value={formSubdomain}
|
||||
class="input input-bordered w-full"
|
||||
/>
|
||||
|
||||
<button type="submit" class="btn btn-error" disabled={isButtonDisabled}
|
||||
>Rename Instance</button
|
||||
>
|
||||
<input
|
||||
title="Only letters and dashes are allowed"
|
||||
required
|
||||
type="text"
|
||||
bind:value={formSubdomain}
|
||||
class="input input-bordered w-full"
|
||||
/>
|
||||
|
||||
<button type="submit" class="btn btn-error" disabled={isButtonDisabled}
|
||||
>Rename Instance</button
|
||||
>
|
||||
</form>
|
||||
</Card>
|
||||
</form>
|
||||
|
||||
<style>
|
||||
.rename-instance-form-container-query {
|
||||
@@ -13,4 +13,5 @@
|
||||
<title>{subdomain} secrets - PocketHost</title>
|
||||
</svelte:head>
|
||||
|
||||
<h2>Secrets</h2>
|
||||
<SecretsInner />
|
||||
|
||||
@@ -79,34 +79,33 @@
|
||||
</script>
|
||||
|
||||
<div class="mb-8">
|
||||
<h4 class="flex items-center font-bold h-9 text-lg mb-3">
|
||||
Add an Environment Variable
|
||||
</h4>
|
||||
{#if successfulSave}
|
||||
<AlertBar
|
||||
message="Your new environment variable has been saved."
|
||||
type="success"
|
||||
/>
|
||||
{/if}
|
||||
|
||||
<AlertBar message={errorMessage} type="error" />
|
||||
|
||||
<form on:submit={handleSubmit} class="mb-4">
|
||||
<div class="grid grid-cols-2 gap-4 mb-4">
|
||||
<div>
|
||||
<label class="label" for="secret-key">
|
||||
<span class="label-text">Key</span>
|
||||
</label>
|
||||
|
||||
<input
|
||||
id="secret-key"
|
||||
type="text"
|
||||
bind:value={secretKey}
|
||||
placeholder="KEY"
|
||||
class="input input-bordered w-full max-w-xs"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="label" for="secret-value">
|
||||
<span class="label-text">Value</span>
|
||||
</label>
|
||||
|
||||
<input
|
||||
id="secret-value"
|
||||
type="text"
|
||||
bind:value={secretValue}
|
||||
placeholder="VALUE"
|
||||
class="input input-bordered w-full max-w-xs"
|
||||
/>
|
||||
</div>
|
||||
@@ -125,13 +124,4 @@
|
||||
>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
{#if successfulSave}
|
||||
<AlertBar
|
||||
message="Your new environment variable has been saved."
|
||||
type="success"
|
||||
/>
|
||||
{/if}
|
||||
|
||||
<AlertBar message={errorMessage} type="error" />
|
||||
</div>
|
||||
|
||||
@@ -6,8 +6,6 @@
|
||||
import { reduce } from '@s-libs/micro-dash'
|
||||
import { logger, UpdateInstancePayload } from 'pockethost'
|
||||
|
||||
let showSecretKeys = false
|
||||
|
||||
const handleDelete = (name: string) => async (e: Event) => {
|
||||
e.preventDefault()
|
||||
logger().debug(`Deleting ${name}`)
|
||||
@@ -29,21 +27,6 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="flex items-center justify-between mb-3 h-9">
|
||||
<h4 class="font-bold text-lg">Current Environment Variables</h4>
|
||||
|
||||
<div class="form-control">
|
||||
<label class="label cursor-pointer">
|
||||
<span class="label-text text-accent mr-2">Show Secrets</span>
|
||||
<input
|
||||
type="checkbox"
|
||||
class="toggle toggle-sm"
|
||||
bind:checked={showSecretKeys}
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -58,10 +41,8 @@
|
||||
<tr transition:fade>
|
||||
<th>{item.name}</th>
|
||||
<td
|
||||
>{showSecretKeys
|
||||
? item.value
|
||||
: item.value.slice(0, 2) +
|
||||
item.value.slice(2).replaceAll(/./g, '*')}</td
|
||||
>{item.value.slice(0, 2) +
|
||||
item.value.slice(2).replaceAll(/./g, '*')}</td
|
||||
>
|
||||
<td class="text-right">
|
||||
<button
|
||||
|
||||
@@ -6,8 +6,6 @@
|
||||
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()
|
||||
@@ -17,24 +15,27 @@
|
||||
})
|
||||
}
|
||||
|
||||
// Keep track of which tab the user has selected
|
||||
let activeTab = 0
|
||||
|
||||
// Toggle between the tabs on click
|
||||
const handleTabChange = (id: number) => {
|
||||
activeTab = id
|
||||
}
|
||||
$: code =
|
||||
`// pb_hooks/env-test.pb.js\n\n` +
|
||||
($items.length > 0
|
||||
? $items
|
||||
.map(
|
||||
({ name, value }) =>
|
||||
`const ${name} = process.env.${name}\nconsole.log("${name}: ", ${name})`,
|
||||
)
|
||||
.join('\n')
|
||||
: `const YOUR_KEY = process.env.YOUR_KEY`)
|
||||
</script>
|
||||
|
||||
<p class="mb-4">
|
||||
<div class="mb-4">
|
||||
These secrets are forwarded to your <code>pocketbase</code> as environment
|
||||
variables, which are also accessible from any <code>pb_hooks</code> you have created.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- 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`} />
|
||||
<CodeSample {code} />
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
@@ -45,32 +46,5 @@
|
||||
</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>
|
||||
<List />
|
||||
<Form />
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
<script lang="ts">
|
||||
import { assertExists } from 'pockethost/common'
|
||||
import { instance } from '../store'
|
||||
import AdminSync from './AdminSync.svelte'
|
||||
import CustomDomain from './CustomDomain.svelte'
|
||||
import AdminSync from '../admin-sync/+page.svelte'
|
||||
import CustomDomain from '../domain/+page.svelte'
|
||||
import DangerZoneTitle from './DangerZoneTitle.svelte'
|
||||
import DeleteInstance from './DeleteInstance.svelte'
|
||||
import DevMode from './DevMode.svelte'
|
||||
import Maintenance from './Maintenance.svelte'
|
||||
import RenameInstance from './RenameInstance.svelte'
|
||||
import VersionChange from './VersionChange/VersionChange.svelte'
|
||||
import DeleteInstance from '../delete/+page.svelte'
|
||||
import DevMode from '../dev/+page.svelte'
|
||||
import RenameInstance from '../rename/+page.svelte'
|
||||
import VersionChange from '../version/+page.svelte'
|
||||
|
||||
$: ({ status, version, id } = $instance)
|
||||
|
||||
@@ -25,8 +24,6 @@
|
||||
<div class="grid lg:grid-cols-3 gap-4 mb-4">
|
||||
<RenameInstance />
|
||||
|
||||
<Maintenance />
|
||||
|
||||
<VersionChange />
|
||||
|
||||
<AdminSync />
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
<script lang="ts">
|
||||
import Card from '$components/cards/Card.svelte'
|
||||
import CardHeader from '$components/cards/CardHeader.svelte'
|
||||
import { DOCS_URL } from '$src/env'
|
||||
import { client } from '$src/pocketbase-client'
|
||||
import { instance } from '../store'
|
||||
import ErrorMessage from './ErrorMessage.svelte'
|
||||
|
||||
const { updateInstance } = client()
|
||||
|
||||
$: ({ id, syncAdmin } = $instance)
|
||||
|
||||
let errorMessage = ''
|
||||
|
||||
const handleChange = (e: Event) => {
|
||||
const target = e.target as HTMLInputElement
|
||||
const isChecked = target.checked
|
||||
|
||||
// Update the database with the new value
|
||||
updateInstance({ id, fields: { syncAdmin: isChecked } })
|
||||
.then(() => 'saved')
|
||||
.catch((error) => {
|
||||
errorMessage = error.data.message || error.message
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<Card>
|
||||
<CardHeader documentation={DOCS_URL(`/usage/admin-sync`)}>
|
||||
Admin Sync
|
||||
</CardHeader>
|
||||
|
||||
<p class="mb-8">
|
||||
Your instance will have an admin login that matches your pockethost.io
|
||||
login.
|
||||
</p>
|
||||
|
||||
<ErrorMessage message={errorMessage} />
|
||||
|
||||
<label class="label cursor-pointer justify-center gap-4">
|
||||
<span class="label-text">Admin Sync</span>
|
||||
<input
|
||||
type="checkbox"
|
||||
class="toggle toggle-warning"
|
||||
checked={!!syncAdmin}
|
||||
on:change={handleChange}
|
||||
/>
|
||||
</label>
|
||||
</Card>
|
||||
@@ -1,47 +0,0 @@
|
||||
<script lang="ts">
|
||||
import Card from '$components/cards/Card.svelte'
|
||||
import CardHeader from '$components/cards/CardHeader.svelte'
|
||||
import { DOCS_URL } from '$src/env'
|
||||
import { client } from '$src/pocketbase-client'
|
||||
import { instance } from '../store'
|
||||
import ErrorMessage from './ErrorMessage.svelte'
|
||||
|
||||
const { updateInstance } = client()
|
||||
|
||||
$: ({ id, dev } = $instance)
|
||||
|
||||
let errorMessage = ''
|
||||
|
||||
const handleChange = (e: Event) => {
|
||||
const target = e.target as HTMLInputElement
|
||||
const isChecked = target.checked
|
||||
|
||||
// Update the database with the new value
|
||||
updateInstance({ id, fields: { dev: isChecked } })
|
||||
.then(() => 'saved')
|
||||
.catch((error) => {
|
||||
errorMessage = error.data.message || error.message
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<Card>
|
||||
<CardHeader documentation={DOCS_URL(`/usage/dev-mode`)}>Dev Mode</CardHeader>
|
||||
|
||||
<p class="mb-8">
|
||||
Starting with PocketBase v0.20.1, your instance will show debugging output
|
||||
in the instance logs. Performance is degraded while Dev Mode is active.
|
||||
</p>
|
||||
|
||||
<ErrorMessage message={errorMessage} />
|
||||
|
||||
<label class="label cursor-pointer justify-center gap-4">
|
||||
<span class="label-text">Dev Mode</span>
|
||||
<input
|
||||
type="checkbox"
|
||||
class="toggle toggle-warning"
|
||||
checked={!!dev}
|
||||
on:change={handleChange}
|
||||
/>
|
||||
</label>
|
||||
</Card>
|
||||
@@ -1,78 +0,0 @@
|
||||
<script lang="ts">
|
||||
import Card from '$components/cards/Card.svelte'
|
||||
import CardHeader from '$components/cards/CardHeader.svelte'
|
||||
import { DOCS_URL } from '$src/env'
|
||||
import { client } from '$src/pocketbase-client'
|
||||
import { userStore } from '$util/stores'
|
||||
import { instance } from '../store'
|
||||
import ErrorMessage from './ErrorMessage.svelte'
|
||||
|
||||
const { updateInstance } = client()
|
||||
|
||||
let errorMessage = ''
|
||||
|
||||
$: ({ id, maintenance, notifyMaintenanceMode } = $instance)
|
||||
|
||||
const handleMaintenanceChange = (e: Event) => {
|
||||
const target = e.target as HTMLInputElement
|
||||
const maintenance = target.checked
|
||||
|
||||
// Update the database with the new value
|
||||
updateInstance({ id, fields: { maintenance } })
|
||||
.then(() => 'saved')
|
||||
.catch((error) => {
|
||||
error.data.message || error.message
|
||||
})
|
||||
}
|
||||
|
||||
const handleNotifyMaintenanceChange = (e: Event) => {
|
||||
const target = e.target as HTMLInputElement
|
||||
const notifyMaintenanceMode = target.checked
|
||||
|
||||
// Update the database with the new value
|
||||
updateInstance({ id, fields: { notifyMaintenanceMode } })
|
||||
.then(() => 'saved')
|
||||
.catch((error) => {
|
||||
error.data.message || error.message
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<Card>
|
||||
<CardHeader documentation={DOCS_URL(`/usage/maintenance`)}>
|
||||
Maintenance Mode
|
||||
</CardHeader>
|
||||
|
||||
<p class="mb-8">
|
||||
Your PocketHost instance will not be accessible while in maintenance mode.
|
||||
Use this when you are upgrading, downgrading, or backing up your data.
|
||||
</p>
|
||||
|
||||
<ErrorMessage message={errorMessage} />
|
||||
|
||||
<label class="label cursor-pointer justify-center gap-4">
|
||||
<span class="label-text">Maintenance Mode</span>
|
||||
<input
|
||||
type="checkbox"
|
||||
class="toggle toggle-warning"
|
||||
checked={!!maintenance}
|
||||
on:change={handleMaintenanceChange}
|
||||
/>
|
||||
</label>
|
||||
|
||||
<label class="label cursor-pointer justify-center gap-4">
|
||||
<span class="label-text">Email on Maintenance Mode</span>
|
||||
<input
|
||||
type="checkbox"
|
||||
class="toggle toggle-success"
|
||||
checked={!!notifyMaintenanceMode}
|
||||
on:change={handleNotifyMaintenanceChange}
|
||||
/>
|
||||
</label>
|
||||
{#if !$userStore?.notifyMaintenanceMode}
|
||||
<div class="text-error">
|
||||
Warning: Maintenance Mode is globally deactivated. This setting will have
|
||||
no effect. See account settings.
|
||||
</div>
|
||||
{/if}
|
||||
</Card>
|
||||
@@ -3,7 +3,7 @@
|
||||
import CardHeader from '$components/cards/CardHeader.svelte'
|
||||
import { DOCS_URL } from '$src/env'
|
||||
import { client } from '$src/pocketbase-client'
|
||||
import { instance } from '../../store'
|
||||
import { instance } from '../store'
|
||||
import VersionPicker from './VersionPicker.svelte'
|
||||
import AlertBar from '$components/AlertBar.svelte'
|
||||
|
||||
@@ -58,35 +58,39 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<Card>
|
||||
<CardHeader documentation={DOCS_URL(`/usage/upgrading`)}>
|
||||
Version Change
|
||||
</CardHeader>
|
||||
<CardHeader documentation={DOCS_URL(`/usage/upgrading`)}>
|
||||
Version Change
|
||||
</CardHeader>
|
||||
|
||||
<p class="mb-8">
|
||||
Changing your version can only be done when the instance is in maintenance
|
||||
mode. We recommend you <strong>do a full backup</strong> before making a
|
||||
change. We support
|
||||
<a href="https://github.com/pocketbase/pocketbase/releases" class="link"
|
||||
>every release</a
|
||||
> of PocketBase.
|
||||
</p>
|
||||
{#if !maintenance}
|
||||
<AlertBar
|
||||
message="Your instance must be powered off to change the version."
|
||||
type="error"
|
||||
/>
|
||||
{/if}
|
||||
|
||||
<AlertBar message={errorMessage} type="error" />
|
||||
<div class="mb-8">
|
||||
We recommend you <strong>do a full backup</strong>
|
||||
before making a change. We support the latest patch of
|
||||
<a href="https://github.com/pocketbase/pocketbase/releases" class="link"
|
||||
>every minor release</a
|
||||
> of PocketBase.
|
||||
</div>
|
||||
|
||||
<form
|
||||
class="flex change-version-form-container-query gap-4"
|
||||
on:submit={handleSave}
|
||||
<AlertBar message={errorMessage} type="error" />
|
||||
|
||||
<form
|
||||
class="flex change-version-form-container-query gap-4"
|
||||
on:submit={handleSave}
|
||||
>
|
||||
<VersionPicker bind:selectedVersion />
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-error"
|
||||
disabled={!maintenance || isButtonDisabled}>Change Version</button
|
||||
>
|
||||
<VersionPicker bind:selectedVersion disabled={!maintenance} />
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-error"
|
||||
disabled={!maintenance || isButtonDisabled}>Change Version</button
|
||||
>
|
||||
</form>
|
||||
</Card>
|
||||
</form>
|
||||
|
||||
<style>
|
||||
.change-version-form-container-query {
|
||||
@@ -10,8 +10,12 @@
|
||||
|
||||
// Function to fetch versions - replace with your actual fetch logic
|
||||
async function fetchVersions(): Promise<string[]> {
|
||||
const { versions } = await client().client.send(`/api/versions`, {})
|
||||
return versions
|
||||
const { versions } = await client().client.send<{ versions: string[] }>(
|
||||
`/api/versions`,
|
||||
{},
|
||||
)
|
||||
|
||||
return versions.filter((v) => v.endsWith('*'))
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
@@ -34,7 +34,7 @@
|
||||
<input
|
||||
type="checkbox"
|
||||
class="toggle {instance.maintenance
|
||||
? 'toggle-error'
|
||||
? 'bg-red-500 hover:bg-red-500'
|
||||
: 'toggle-success'}"
|
||||
checked={!instance.maintenance}
|
||||
on:change={handleMaintenanceChange(instance.id)}
|
||||
@@ -42,8 +42,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-wrap gap-2"></div>
|
||||
<div class="card-actions">
|
||||
<div class="card-actions flex justify-between mt-5">
|
||||
<a href={`/app/instances/${instance.id}`} class="btn btn-primary">
|
||||
<i class="fa-regular fa-circle-info"></i>
|
||||
<span>Details</span>
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
module.exports = {
|
||||
content: ['./src/**/*.{svelte,js,ts,md}'],
|
||||
safelist: [`lg:pl-72`, `toggle-error`, `toggle-success`],
|
||||
safelist: [
|
||||
'lg:pl-72',
|
||||
{
|
||||
pattern: /(toggle|text|bg)-(error|success|warning|red-500)/,
|
||||
variants: ['responsive', 'hover'],
|
||||
},
|
||||
],
|
||||
theme: {
|
||||
extend: {
|
||||
animation: {
|
||||
|
||||
Reference in New Issue
Block a user