Rework the relay detail page and edit screen

This commit is contained in:
Jon Staab
2026-03-03 10:54:14 -08:00
parent 7e577bf7ff
commit 0482c2710a
10 changed files with 520 additions and 235 deletions
+119 -21
View File
@@ -1,6 +1,6 @@
import { useParams, A } from "@solidjs/router"
import { useParams } from "@solidjs/router"
import { createResource, createSignal, Show } from "solid-js"
import { adminDeactivateRelay, adminGetRelay } from "../../lib/api"
import { adminDeactivateRelay, adminGetRelay, adminUpdateRelay, type RelayConfig } from "../../lib/api"
import BackLink from "../../components/BackLink"
import PageContainer from "../../components/PageContainer"
import RelayDetailCard from "../../components/RelayDetailCard"
@@ -10,10 +10,10 @@ import useMinLoading from "../../components/useMinLoading"
export default function AdminRelayDetail() {
const params = useParams()
const relayId = () => params.id ?? ""
const [relay, { refetch }] = createResource(relayId, adminGetRelay)
const [relay, { refetch, mutate }] = createResource(relayId, adminGetRelay)
const [busy, setBusy] = createSignal(false)
const [error, setError] = createSignal("")
const loading = useMinLoading(() => relay.loading)
const loading = useMinLoading(() => relay.loading && !relay())
async function handleDeactivate() {
if (busy()) return
@@ -29,6 +29,108 @@ export default function AdminRelayDetail() {
}
}
function withDefaults(config?: RelayConfig): RelayConfig {
return {
policy: {
public_join: config?.policy.public_join ?? false,
strip_signatures: config?.policy.strip_signatures ?? false,
},
groups: {
enabled: config?.groups.enabled ?? true,
auto_join: config?.groups.auto_join ?? true,
},
management: {
enabled: config?.management.enabled ?? true,
},
blossom: {
enabled: config?.blossom.enabled ?? (relay()?.plan !== "free"),
},
push: {
enabled: config?.push.enabled ?? true,
},
}
}
async function updateFlags(nextConfig: RelayConfig, previousConfig: RelayConfig) {
const current = relay()
if (!current) return
setError("")
const optimisticRelay = {
...current,
config: nextConfig,
}
mutate(optimisticRelay)
try {
await adminUpdateRelay(relayId(), {
name: current.name,
subdomain: current.subdomain,
icon: current.icon,
description: current.description,
config: nextConfig,
})
await refetch()
} catch (e) {
mutate({ ...current, config: previousConfig })
setError(e instanceof Error ? e.message : "Failed to update relay settings")
}
}
function togglePublicJoin() {
const config = withDefaults(relay()?.config)
const nextConfig = {
...config,
policy: { ...config.policy, public_join: !config.policy.public_join },
}
void updateFlags(nextConfig, config)
}
function toggleStripSignatures() {
const config = withDefaults(relay()?.config)
const nextConfig = {
...config,
policy: { ...config.policy, strip_signatures: !config.policy.strip_signatures },
}
void updateFlags(nextConfig, config)
}
function toggleGroups() {
const config = withDefaults(relay()?.config)
const nextConfig = {
...config,
groups: { ...config.groups, enabled: !config.groups.enabled },
}
void updateFlags(nextConfig, config)
}
function toggleManagement() {
const config = withDefaults(relay()?.config)
const nextConfig = {
...config,
management: { enabled: !config.management.enabled },
}
void updateFlags(nextConfig, config)
}
function toggleMediaStorage() {
const config = withDefaults(relay()?.config)
const nextConfig = {
...config,
blossom: { enabled: !config.blossom.enabled },
}
void updateFlags(nextConfig, config)
}
function togglePushNotifications() {
const config = withDefaults(relay()?.config)
const nextConfig = {
...config,
push: { enabled: !config.push.enabled },
}
void updateFlags(nextConfig, config)
}
return (
<PageContainer>
<BackLink href="/admin/relays" label="Relays" />
@@ -44,26 +146,22 @@ export default function AdminRelayDetail() {
<Show when={!loading() && relay()}>
{(r) => (
<div class="mb-6">
<RelayDetailCard relay={r()} showTenant />
<RelayDetailCard
relay={r()}
showTenant
editHref={`/admin/relays/${params.id}/edit`}
onDeactivate={handleDeactivate}
deactivating={busy()}
onTogglePublicJoin={togglePublicJoin}
onToggleStripSignatures={toggleStripSignatures}
onToggleGroups={toggleGroups}
onToggleManagement={toggleManagement}
onToggleMediaStorage={toggleMediaStorage}
onTogglePushNotifications={togglePushNotifications}
/>
</div>
)}
</Show>
<div class="flex gap-3">
<A
href={`/admin/relays/${params.id}/edit`}
class="py-2 px-4 border border-gray-300 text-gray-700 font-medium rounded-lg hover:bg-gray-50 transition-colors"
>
Edit
</A>
<button
class="py-2 px-4 border border-red-300 text-red-600 font-medium rounded-lg hover:bg-red-50 transition-colors disabled:opacity-50"
onClick={handleDeactivate}
disabled={busy()}
>
{busy() ? "Deactivating..." : "Deactivate"}
</button>
</div>
<Show when={error()}>
<p class="mt-3 text-sm text-red-600">{error()}</p>
</Show>
+1 -12
View File
@@ -2,7 +2,6 @@ import { useNavigate, useParams } from "@solidjs/router"
import { Show, createEffect, createResource, createSignal } from "solid-js"
import { adminGetRelay, adminUpdateRelay, type RelayConfig } from "../../lib/api"
import RelayForm from "../../components/RelayForm"
import { RELAY_PLAN_IDS, type RelayPlanId } from "../../lib/relayPlans"
import { slugify } from "../../lib/slugify"
import BackLink from "../../components/BackLink"
import PageContainer from "../../components/PageContainer"
@@ -28,8 +27,6 @@ export default function AdminRelayEdit() {
const [subdomain, setSubdomain] = createSignal("")
const [icon, setIcon] = createSignal("")
const [description, setDescription] = createSignal("")
const [plan, setPlan] = createSignal<RelayPlanId>("free")
const [config, setConfig] = createSignal<RelayConfig>(DEFAULT_CONFIG)
const [error, setError] = createSignal("")
const [submitting, setSubmitting] = createSignal(false)
@@ -40,8 +37,6 @@ export default function AdminRelayEdit() {
setSubdomain(data.subdomain)
setIcon(data.icon)
setDescription(data.description)
setPlan(RELAY_PLAN_IDS.includes(data.plan as RelayPlanId) ? (data.plan as RelayPlanId) : "free")
setConfig(data.config ?? DEFAULT_CONFIG)
})
async function handleSubmit(e: Event) {
@@ -54,8 +49,7 @@ export default function AdminRelayEdit() {
subdomain: slugify(subdomain()),
icon: icon().trim(),
description: description().trim(),
plan: plan(),
config: config(),
config: relay()?.config ?? DEFAULT_CONFIG,
})
navigate(`/admin/relays/${relayId()}`)
} catch (e) {
@@ -87,11 +81,6 @@ export default function AdminRelayEdit() {
setIcon={setIcon}
description={description()}
setDescription={setDescription}
plan={plan()}
setPlan={setPlan}
plans={RELAY_PLAN_IDS}
config={config()}
setConfig={setConfig}
onSubmit={handleSubmit}
submitting={submitting()}
error={error()}