mirror of
https://github.com/pockethost/pockethost.git
synced 2025-03-30 15:08:30 +00:00
enh: overhaul dashboard nav and state management
This commit is contained in:
parent
a4ca2985f6
commit
c2fc64d66e
@ -7,7 +7,7 @@
|
||||
|
||||
<div class="drawer-content">
|
||||
<div class="flex items-center justify-between px-8 pt-1">
|
||||
<a href="/dashboard" class="flex gap-2 items-center justify-center">
|
||||
<a href="/" class="flex gap-2 items-center justify-center">
|
||||
<Logo hideLogoText={true} logoWidth="w-16" />
|
||||
</a>
|
||||
|
||||
|
@ -3,9 +3,11 @@
|
||||
import Logo from '$components/Logo.svelte'
|
||||
import MediaQuery from '$components/MediaQuery.svelte'
|
||||
import { DOCS_URL } from '$src/env'
|
||||
import InstancesGuard from '$src/routes/InstancesGuard.svelte'
|
||||
import { handleLogoutAndRedirect } from '$util/database'
|
||||
import { globalInstancesStore } from '$util/stores'
|
||||
import { values } from '@s-libs/micro-dash'
|
||||
import UserLoggedIn from './helpers/UserLoggedIn.svelte'
|
||||
|
||||
const linkClasses =
|
||||
'font-medium text-xl text-base-content btn btn-ghost capitalize justify-start'
|
||||
@ -22,47 +24,48 @@
|
||||
<aside class="p-4 min-w-[250px] flex flex-col h-screen">
|
||||
<MediaQuery query="(min-width: 1280px)" let:matches>
|
||||
{#if matches}
|
||||
<a href="/dashboard" class="flex gap-2 items-center justify-center">
|
||||
<a href="/" class="flex gap-2 items-center justify-center">
|
||||
<Logo hideLogoText={true} logoWidth="w-20" />
|
||||
</a>
|
||||
{/if}
|
||||
</MediaQuery>
|
||||
|
||||
<div class="flex flex-col gap-2 mb-auto">
|
||||
<a on:click={handleClick} href="/dashboard" class={linkClasses}>
|
||||
<a on:click={handleClick} href="/" class={linkClasses}>
|
||||
<i
|
||||
class="fa-regular fa-table-columns {$page.url.pathname ===
|
||||
'/dashboard' && 'text-primary'}"
|
||||
class="fa-regular fa-table-columns {$page.url.pathname === '/' &&
|
||||
'text-primary'}"
|
||||
></i> Dashboard
|
||||
</a>
|
||||
|
||||
<div class="pl-8 flex flex-col gap-4 mb-4">
|
||||
{#each values($globalInstancesStore) as app}
|
||||
<a
|
||||
href={`/app/instances/${app.id}`}
|
||||
on:click={handleClick}
|
||||
class={subLinkClasses}
|
||||
>
|
||||
{#if app.maintenance}
|
||||
<i class="fa-regular fa-triangle-person-digging text-warning"></i>
|
||||
{:else}
|
||||
<i
|
||||
class="fa-regular fa-server {$page.url.pathname ===
|
||||
`/app/instances/${app.id}` && 'text-primary'}"
|
||||
></i>
|
||||
{/if}
|
||||
<InstancesGuard>
|
||||
<div class="pl-8 flex flex-col gap-4 mb-4">
|
||||
{#each values($globalInstancesStore) as app}
|
||||
<a
|
||||
href={`/app/instances/${app.id}`}
|
||||
on:click={handleClick}
|
||||
class={subLinkClasses}
|
||||
>
|
||||
{#if app.maintenance}
|
||||
<i class="fa-regular fa-triangle-person-digging text-warning"></i>
|
||||
{:else}
|
||||
<i
|
||||
class="fa-regular fa-server {$page.url.pathname ===
|
||||
`/app/instances/${app.id}` && 'text-primary'}"
|
||||
></i>
|
||||
{/if}
|
||||
|
||||
{app.subdomain}
|
||||
{app.subdomain}
|
||||
</a>
|
||||
{/each}
|
||||
<a href="/app/new" on:click={handleClick} class={addNewAppClasses}>
|
||||
<i
|
||||
class="fa-regular fa-plus {$page.url.pathname === `/app/new` &&
|
||||
'text-primary'}"
|
||||
></i> Create A New App
|
||||
</a>
|
||||
{/each}
|
||||
|
||||
<a href="/app/new" on:click={handleClick} class={addNewAppClasses}>
|
||||
<i
|
||||
class="fa-regular fa-plus {$page.url.pathname === `/app/new` &&
|
||||
'text-primary'}"
|
||||
></i> Create A New App
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</InstancesGuard>
|
||||
|
||||
<a
|
||||
href="https://discord.gg/nVTxCMEcGT"
|
||||
@ -99,8 +102,13 @@
|
||||
></i></a
|
||||
>
|
||||
|
||||
<button type="button" class={linkClasses} on:click={handleLogoutAndRedirect}
|
||||
><i class="fa-regular fa-arrow-up-left-from-circle"></i> Logout</button
|
||||
>
|
||||
<UserLoggedIn>
|
||||
<button
|
||||
type="button"
|
||||
class={linkClasses}
|
||||
on:click={handleLogoutAndRedirect}
|
||||
><i class="fa-regular fa-arrow-up-left-from-circle"></i> Logout</button
|
||||
>
|
||||
</UserLoggedIn>
|
||||
</div>
|
||||
</aside>
|
||||
|
@ -1,4 +1,3 @@
|
||||
import { browser } from '$app/environment'
|
||||
import { MOTHERSHIP_URL } from '$src/env'
|
||||
import { LoggerService } from '@pockethost/common'
|
||||
import {
|
||||
@ -9,7 +8,6 @@ import {
|
||||
export const client = (() => {
|
||||
let clientInstance: PocketbaseClient | undefined
|
||||
return () => {
|
||||
if (!browser) throw new Error(`PocketBase client not supported in SSR`)
|
||||
if (clientInstance) return clientInstance
|
||||
const { info } = LoggerService()
|
||||
info(`Initializing pocketbase client`)
|
||||
|
@ -2,30 +2,28 @@
|
||||
import MediaQuery from '$components/MediaQuery.svelte'
|
||||
import MobileNavDrawer from '$components/MobileNavDrawer.svelte'
|
||||
import Navbar from '$components/Navbar.svelte'
|
||||
import AuthStateGuard from '$components/helpers/AuthStateGuard.svelte'
|
||||
import Meta from '$components/helpers/Meta.svelte'
|
||||
import Protect from '$components/helpers/Protect.svelte'
|
||||
import UserLoggedIn from '$components/helpers/UserLoggedIn.svelte'
|
||||
import '../app.css'
|
||||
import '../services'
|
||||
|
||||
import { getInstances } from '$util/getInstances'
|
||||
import { isUserLoggedIn } from '$util/stores'
|
||||
|
||||
getInstances()
|
||||
</script>
|
||||
|
||||
<Meta />
|
||||
|
||||
{#if $isUserLoggedIn}
|
||||
<AuthStateGuard>
|
||||
<div class="layout xl:flex">
|
||||
<MediaQuery query="(min-width: 1280px)" let:matches>
|
||||
{#if matches}
|
||||
<Navbar />
|
||||
{:else}
|
||||
<MobileNavDrawer>
|
||||
<UserLoggedIn>
|
||||
<MediaQuery query="(min-width: 1280px)" let:matches>
|
||||
{#if matches}
|
||||
<Navbar />
|
||||
</MobileNavDrawer>
|
||||
{/if}
|
||||
</MediaQuery>
|
||||
{:else}
|
||||
<MobileNavDrawer>
|
||||
<Navbar />
|
||||
</MobileNavDrawer>
|
||||
{/if}
|
||||
</MediaQuery>
|
||||
</UserLoggedIn>
|
||||
|
||||
<div class="lg:p-4 lg:pt-0 xl:pt-4 min-h-screen grow">
|
||||
<div
|
||||
@ -35,10 +33,4 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if !$isUserLoggedIn}
|
||||
<div>
|
||||
<slot />
|
||||
</div>
|
||||
{/if}
|
||||
</AuthStateGuard>
|
||||
|
2
packages/dashboard/src/routes/+layout.ts
Normal file
2
packages/dashboard/src/routes/+layout.ts
Normal file
@ -0,0 +1,2 @@
|
||||
const ssr = false
|
||||
export { ssr }
|
@ -1,30 +1,26 @@
|
||||
<script lang="ts">
|
||||
import Logo from '$components/Logo.svelte'
|
||||
import AuthStateGuard from '$components/helpers/AuthStateGuard.svelte'
|
||||
import UserLoggedIn from '$components/helpers/UserLoggedIn.svelte'
|
||||
import UserLoggedOut from '$components/helpers/UserLoggedOut.svelte'
|
||||
import InstanceGeneratorWidget from '$components/login-register/InstanceGeneratorWidget.svelte'
|
||||
import { isUserLoggedIn } from '$util/stores'
|
||||
import Dashboard from './dashboard/Dashboard.svelte'
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>Home - PocketHost</title>
|
||||
</svelte:head>
|
||||
|
||||
<div class="min-h-screen flex items-center justify-center">
|
||||
<div>
|
||||
<AuthStateGuard>
|
||||
<Logo />
|
||||
<div>
|
||||
<UserLoggedIn>
|
||||
<Dashboard />
|
||||
</UserLoggedIn>
|
||||
|
||||
{#if $isUserLoggedIn}
|
||||
<div class="">
|
||||
<a href="/dashboard" class="btn btn-primary"
|
||||
>Go to Your Dashboard <i class="bi bi-arrow-right-short" /></a
|
||||
>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if !$isUserLoggedIn}
|
||||
<UserLoggedOut>
|
||||
<div class="min-h-screen flex items-center justify-center">
|
||||
<div>
|
||||
<Logo />
|
||||
<InstanceGeneratorWidget />
|
||||
{/if}
|
||||
</AuthStateGuard>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</UserLoggedOut>
|
||||
</div>
|
||||
|
@ -1,20 +1,23 @@
|
||||
<script lang="ts">
|
||||
<script>
|
||||
import { page } from '$app/stores'
|
||||
import AuthStateGuard from '$components/helpers/AuthStateGuard.svelte'
|
||||
import { getSingleInstance } from '$util/getInstances'
|
||||
import { assertTruthy } from '@pockethost/common'
|
||||
import { globalInstancesStore } from '$util/stores'
|
||||
import { assert } from '@pockethost/common'
|
||||
import { instance } from './store'
|
||||
|
||||
// Run anytime the page params changes
|
||||
let isReady = false
|
||||
$: {
|
||||
const { instanceId } = $page.params
|
||||
assertTruthy(instanceId)
|
||||
getSingleInstance(instanceId)
|
||||
assert(instanceId)
|
||||
const _instance = $globalInstancesStore[instanceId]
|
||||
if (_instance) {
|
||||
instance.set(_instance)
|
||||
}
|
||||
isReady = !!_instance
|
||||
}
|
||||
</script>
|
||||
|
||||
<AuthStateGuard>
|
||||
{#if $instance}
|
||||
<slot />
|
||||
{/if}
|
||||
</AuthStateGuard>
|
||||
{#if isReady}
|
||||
<slot />
|
||||
{:else}
|
||||
<div>Instance not found</div>
|
||||
{/if}
|
||||
|
@ -1,4 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { page } from '$app/stores'
|
||||
import { INSTANCE_ADMIN_URL } from '$src/env'
|
||||
import { assertExists } from '@pockethost/common'
|
||||
import { slide } from 'svelte/transition'
|
||||
@ -13,6 +14,11 @@
|
||||
import UsageChart from './UsageChart.svelte'
|
||||
import { instance } from './store'
|
||||
|
||||
const { instanceId } = $page.params
|
||||
|
||||
console.log(instanceId)
|
||||
let isReady = false
|
||||
|
||||
$: ({ status, version, secondsThisMonth } = $instance)
|
||||
|
||||
assertExists($instance, `Expected instance here`)
|
||||
|
@ -2,15 +2,16 @@
|
||||
import Card from '$components/cards/Card.svelte'
|
||||
import CardHeader from '$components/cards/CardHeader.svelte'
|
||||
import { client } from '$src/pocketbase'
|
||||
import { mkCleanup } from '$util/componentCleanup'
|
||||
import {
|
||||
LoggerService,
|
||||
createCleanupManager,
|
||||
Unsubscribe,
|
||||
type InstanceLogFields,
|
||||
type RecordId,
|
||||
} from '@pockethost/common'
|
||||
import { values } from '@s-libs/micro-dash'
|
||||
import { onDestroy, onMount } from 'svelte'
|
||||
import { writable } from 'svelte/store'
|
||||
import { onMount } from 'svelte'
|
||||
import { derived, writable } from 'svelte/store'
|
||||
import { instance } from './store'
|
||||
|
||||
const { dbg, trace } = LoggerService().create(`Logging.svelte`)
|
||||
@ -46,28 +47,32 @@
|
||||
const logs = writable<{ [_: RecordId]: InstanceLogFields }>({})
|
||||
let logsArray: InstanceLogFields[] = []
|
||||
|
||||
const cm = createCleanupManager()
|
||||
const onDestroy = mkCleanup()
|
||||
|
||||
const instanceId = derived(instance, (instance) => instance.id)
|
||||
|
||||
onMount(async () => {
|
||||
dbg(`Watching instance log`)
|
||||
let unwatch: Unsubscribe | undefined
|
||||
const unsub = instanceId.subscribe((id) => {
|
||||
dbg(`Watching instance log ${id}`)
|
||||
unwatch?.()
|
||||
logs.set({})
|
||||
unwatch = client().watchInstanceLog(id, (newLog) => {
|
||||
trace(`Got new log`, newLog)
|
||||
|
||||
const unsub = client().watchInstanceLog(id, (newLog) => {
|
||||
trace(`Got new log`, newLog)
|
||||
logs.update((currentLogs) => {
|
||||
return { ...currentLogs, [newLog.id]: newLog }
|
||||
})
|
||||
|
||||
logs.update((currentLogs) => {
|
||||
return { ...currentLogs, [newLog.id]: newLog }
|
||||
logsArray = values($logs)
|
||||
.sort((a, b) => (a.created > b.created ? 1 : -1))
|
||||
.slice(0, 1000)
|
||||
.reverse()
|
||||
})
|
||||
|
||||
logsArray = values($logs)
|
||||
.sort((a, b) => (a.created > b.created ? 1 : -1))
|
||||
.slice(0, 1000)
|
||||
.reverse()
|
||||
})
|
||||
|
||||
cm.add(unsub)
|
||||
onDestroy(unsub)
|
||||
onDestroy(() => unwatch?.())
|
||||
})
|
||||
|
||||
onDestroy(cm.shutdown)
|
||||
</script>
|
||||
|
||||
<Card>
|
||||
|
@ -1,7 +1,10 @@
|
||||
<script lang="ts">
|
||||
import { SECRET_KEY_REGEX } from '@pockethost/common'
|
||||
import { items } from './stores.js'
|
||||
import { client } from '$src/pocketbase/index.js'
|
||||
import { SECRET_KEY_REGEX, SaveSecretsPayload } from '@pockethost/common'
|
||||
import { reduce } from '@s-libs/micro-dash'
|
||||
import { slide } from 'svelte/transition'
|
||||
import { instance } from '../store.js'
|
||||
import { items } from './stores.js'
|
||||
|
||||
// Keep track of the new key and value to be added
|
||||
let secretKey: string = ''
|
||||
@ -40,6 +43,18 @@
|
||||
|
||||
// Save to the database
|
||||
items.upsert({ name: secretKey, value: secretValue })
|
||||
await client().saveSecrets({
|
||||
instanceId: $instance.id,
|
||||
secrets: reduce(
|
||||
$items,
|
||||
(c, v) => {
|
||||
const { name, value } = v
|
||||
c[name] = value
|
||||
return c
|
||||
},
|
||||
{} as SaveSecretsPayload['secrets'],
|
||||
),
|
||||
})
|
||||
|
||||
// Reset the values when the POST is done
|
||||
secretKey = ''
|
||||
|
@ -1,15 +1,9 @@
|
||||
<script lang="ts">
|
||||
import CodeSample from '$components/CodeSample.svelte'
|
||||
import Card from '$components/cards/Card.svelte'
|
||||
import CardHeader from '$components/cards/CardHeader.svelte'
|
||||
import CodeSample from '$components/CodeSample.svelte'
|
||||
import { client } from '$src/pocketbase'
|
||||
import {
|
||||
createCleanupManager,
|
||||
LoggerService,
|
||||
type SaveSecretsPayload,
|
||||
} from '@pockethost/common'
|
||||
import { forEach, reduce } from '@s-libs/micro-dash'
|
||||
import { onDestroy, onMount } from 'svelte'
|
||||
import { LoggerService } from '@pockethost/common'
|
||||
import { forEach } from '@s-libs/micro-dash'
|
||||
import { instance } from '../store'
|
||||
import Form from './Form.svelte'
|
||||
import List from './List.svelte'
|
||||
@ -17,7 +11,14 @@
|
||||
|
||||
// TODO: Hot Reload is causing an infinite loop in the network tab for some reason. Wasn't able to figure out why
|
||||
|
||||
$: ({ id, secrets } = $instance)
|
||||
$: {
|
||||
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
|
||||
@ -28,44 +29,6 @@
|
||||
}
|
||||
|
||||
const { dbg } = LoggerService().create(`Secrets.svelte`)
|
||||
|
||||
const cm = createCleanupManager()
|
||||
|
||||
onMount(() => {
|
||||
items.clear()
|
||||
|
||||
forEach(secrets || {}, (value, name) => {
|
||||
items.upsert({ name, value })
|
||||
})
|
||||
|
||||
let initial = false
|
||||
|
||||
const unsub = items.subscribe(async (secrets) => {
|
||||
if (!initial) {
|
||||
initial = true
|
||||
return
|
||||
}
|
||||
|
||||
dbg(`Got change`, secrets)
|
||||
|
||||
await client().saveSecrets({
|
||||
instanceId: id,
|
||||
secrets: reduce(
|
||||
secrets,
|
||||
(c, v) => {
|
||||
const { name, value } = v
|
||||
c[name] = value
|
||||
return c
|
||||
},
|
||||
{} as SaveSecretsPayload['secrets'],
|
||||
),
|
||||
})
|
||||
})
|
||||
|
||||
cm.add(unsub)
|
||||
})
|
||||
|
||||
onDestroy(cm.shutdown)
|
||||
</script>
|
||||
|
||||
<Card>
|
||||
|
@ -75,7 +75,7 @@
|
||||
{/if}
|
||||
|
||||
<div class="flex items-center justify-center gap-4">
|
||||
<a href="/dashboard" class="btn">Cancel</a>
|
||||
<a href="/" class="btn">Cancel</a>
|
||||
|
||||
<button class="btn btn-primary" disabled={isFormButtonDisabled}>
|
||||
Create <i class="bi bi-arrow-right-short" />
|
||||
|
@ -1,5 +1,4 @@
|
||||
<script lang="ts">
|
||||
import { browser } from '$app/environment'
|
||||
import { page } from '$app/stores'
|
||||
import AlertBar from '$components/AlertBar.svelte'
|
||||
import { handleAccountConfirmation } from '$util/database'
|
||||
@ -9,15 +8,13 @@
|
||||
|
||||
// Check for a token in the URL
|
||||
$: {
|
||||
if (browser) {
|
||||
token = $page?.url?.searchParams?.get('token')
|
||||
token = $page?.url?.searchParams?.get('token')
|
||||
|
||||
if (token) {
|
||||
handleLoad()
|
||||
} else {
|
||||
// No token was found in the URL
|
||||
formError = 'Invalid link'
|
||||
}
|
||||
if (token) {
|
||||
handleLoad()
|
||||
} else {
|
||||
// No token was found in the URL
|
||||
formError = 'Invalid link'
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -38,7 +38,7 @@ export const handleLogin = async (
|
||||
await authViaEmail(email, password)
|
||||
|
||||
if (shouldRedirect) {
|
||||
await goto('/dashboard')
|
||||
await goto('/')
|
||||
}
|
||||
} catch (error) {
|
||||
if (!(error instanceof Error)) {
|
||||
@ -88,7 +88,7 @@ export const handleAccountConfirmation = async (
|
||||
try {
|
||||
await confirmVerification(token)
|
||||
|
||||
window.location.href = '/dashboard'
|
||||
window.location.href = '/'
|
||||
} catch (error: any) {
|
||||
handleFormError(error, setError)
|
||||
}
|
||||
@ -136,7 +136,7 @@ export const handleUnauthenticatedPasswordResetConfirm = async (
|
||||
try {
|
||||
await requestPasswordResetConfirm(token, password)
|
||||
|
||||
await goto('/dashboard')
|
||||
await goto('/')
|
||||
} catch (error: any) {
|
||||
handleFormError(error, setError)
|
||||
}
|
||||
|
@ -1,64 +0,0 @@
|
||||
import { browser } from '$app/environment'
|
||||
import { client } from '$src/pocketbase'
|
||||
import { instance } from '$src/routes/app/instances/[instanceId]/store'
|
||||
import { globalInstancesStore, isUserLoggedIn } from '$util/stores'
|
||||
import {
|
||||
LoggerService,
|
||||
assertExists,
|
||||
createCleanupManager,
|
||||
type InstanceFields,
|
||||
} from '@pockethost/common'
|
||||
import { onDestroy, onMount } from 'svelte'
|
||||
|
||||
export const getInstances = async () => {
|
||||
const { error } = LoggerService()
|
||||
|
||||
const cm = createCleanupManager()
|
||||
onMount(async () => {
|
||||
const unsub = isUserLoggedIn.subscribe(async (isLoggedIn) => {
|
||||
if (!isLoggedIn) return
|
||||
const { getAllInstancesById } = client()
|
||||
|
||||
const instances = await getAllInstancesById()
|
||||
|
||||
globalInstancesStore.set(instances)
|
||||
|
||||
const unsub = await client()
|
||||
.client.collection('instances')
|
||||
.subscribe<InstanceFields>('*', (data) => {
|
||||
globalInstancesStore.update((instances) => {
|
||||
instances[data.record.id] = data.record
|
||||
return instances
|
||||
})
|
||||
})
|
||||
cm.add(unsub)
|
||||
})
|
||||
cm.add(unsub)
|
||||
})
|
||||
|
||||
// Stop listening to the db if this component unmounts
|
||||
onDestroy(() => {
|
||||
cm.shutdown().catch(console.error)
|
||||
})
|
||||
}
|
||||
|
||||
export const getSingleInstance = async (instanceId: string) => {
|
||||
const cm = createCleanupManager()
|
||||
// Only run this on the browser
|
||||
if (browser) {
|
||||
const { dbg, error } = LoggerService().create(`layout.svelte`)
|
||||
|
||||
const { watchInstanceById } = client()
|
||||
|
||||
watchInstanceById(instanceId, (r) => {
|
||||
dbg(`Handling instance update`, r)
|
||||
const { action, record } = r
|
||||
assertExists(record, `Expected instance here`)
|
||||
|
||||
// Update the page state with the instance information
|
||||
instance.set(record)
|
||||
})
|
||||
.then(cm.add)
|
||||
.catch(error)
|
||||
}
|
||||
}
|
@ -1,47 +1,67 @@
|
||||
import { browser } from '$app/environment'
|
||||
import { client } from '$src/pocketbase'
|
||||
import type { AuthStoreProps } from '$src/pocketbase/PocketbaseClient'
|
||||
import {
|
||||
LoggerService,
|
||||
type InstanceFields,
|
||||
type InstanceId,
|
||||
} from '@pockethost/common'
|
||||
import { UnsubscribeFunc } from 'pocketbase'
|
||||
import { writable } from 'svelte/store'
|
||||
import '../services'
|
||||
|
||||
export const authStoreState = writable<AuthStoreProps>({
|
||||
isValid: false,
|
||||
model: null,
|
||||
token: '',
|
||||
})
|
||||
|
||||
export const isUserLoggedIn = writable(false)
|
||||
export const isUserVerified = writable(false)
|
||||
export const isAuthStateInitialized = writable(false)
|
||||
|
||||
if (browser) {
|
||||
const { onAuthChange } = client()
|
||||
const { onAuthChange } = client()
|
||||
|
||||
/**
|
||||
* Listen for auth change events. When we get at least one, the auth state is initialized.
|
||||
*/
|
||||
onAuthChange((authStoreProps) => {
|
||||
const { dbg } = LoggerService()
|
||||
dbg(`onAuthChange in store`, { ...authStoreProps })
|
||||
authStoreState.set(authStoreProps)
|
||||
isAuthStateInitialized.set(true)
|
||||
})
|
||||
|
||||
// Update derived stores when authStore changes
|
||||
authStoreState.subscribe((authStoreProps) => {
|
||||
const { dbg } = LoggerService()
|
||||
dbg(`subscriber change`, authStoreProps)
|
||||
isUserLoggedIn.set(authStoreProps.isValid)
|
||||
isUserVerified.set(!!authStoreProps.model?.verified)
|
||||
})
|
||||
}
|
||||
/**
|
||||
* Listen for auth change events. When we get at least one, the auth state is initialized.
|
||||
*/
|
||||
onAuthChange((authStoreProps) => {
|
||||
const { dbg } = LoggerService()
|
||||
dbg(`onAuthChange in store`, { ...authStoreProps })
|
||||
isUserLoggedIn.set(authStoreProps.isValid)
|
||||
isUserVerified.set(!!authStoreProps.model?.verified)
|
||||
isAuthStateInitialized.set(true)
|
||||
})
|
||||
|
||||
// This holds an array of all the user's instances and their data
|
||||
export const globalInstancesStore = writable<{
|
||||
[_: InstanceId]: InstanceFields
|
||||
}>({})
|
||||
|
||||
export const globalInstancesStoreReady = writable(false)
|
||||
|
||||
/**
|
||||
* Listen for instances
|
||||
*/
|
||||
isUserLoggedIn.subscribe(async (isLoggedIn) => {
|
||||
let unsub: UnsubscribeFunc | undefined
|
||||
if (!isLoggedIn) {
|
||||
globalInstancesStore.set({})
|
||||
globalInstancesStoreReady.set(false)
|
||||
unsub?.()
|
||||
.then(() => {
|
||||
unsub = undefined
|
||||
})
|
||||
.catch(console.error)
|
||||
return
|
||||
}
|
||||
const { getAllInstancesById } = client()
|
||||
|
||||
const instances = await getAllInstancesById()
|
||||
|
||||
globalInstancesStore.set(instances)
|
||||
globalInstancesStoreReady.set(true)
|
||||
|
||||
client()
|
||||
.client.collection('instances')
|
||||
.subscribe<InstanceFields>('*', (data) => {
|
||||
globalInstancesStore.update((instances) => {
|
||||
instances[data.record.id] = data.record
|
||||
return instances
|
||||
})
|
||||
})
|
||||
.then((u) => (unsub = u))
|
||||
.catch(console.error)
|
||||
})
|
||||
|
Loading…
x
Reference in New Issue
Block a user