diff --git a/frontend/src/components/AppShell.tsx b/frontend/src/components/AppShell.tsx index 26ec95f..c4e5801 100644 --- a/frontend/src/components/AppShell.tsx +++ b/frontend/src/components/AppShell.tsx @@ -50,7 +50,7 @@ export default function AppShell(props: { children?: any }) { if (!query) return list const fuse = new Fuse(list, { - keys: ["name", "subdomain"], + keys: ["info_name", "subdomain"], threshold: 0.35, ignoreLocation: true, }) @@ -224,7 +224,7 @@ export default function AppShell(props: { children?: any }) { class="block rounded-lg border border-gray-200 bg-white p-3" onClick={closeSearchModal} > -

{relay.name}

+

{relay.info_name || relay.subdomain}

{relay.subdomain}.spaces.coracle.social

diff --git a/frontend/src/components/RelayDetailCard.tsx b/frontend/src/components/RelayDetailCard.tsx index 79e2ec5..30ea4c7 100644 --- a/frontend/src/components/RelayDetailCard.tsx +++ b/frontend/src/components/RelayDetailCard.tsx @@ -97,7 +97,11 @@ type RelayDetailCardProps = { export default function RelayDetailCard(props: RelayDetailCardProps) { const r = () => props.relay - const cfg = () => r().config + const flag = (value: number, fallback: boolean) => { + if (value === 0) return false + if (value === 1) return true + return fallback + } const [menuOpen, setMenuOpen] = createSignal(false) const [planModalOpen, setPlanModalOpen] = createSignal(false) const [selectedPlan, setSelectedPlan] = createSignal("free") @@ -170,19 +174,19 @@ export default function RelayDetailCard(props: RelayDetailCardProps) { {/* Header */}
- - + +
-

{r().name}

+

{r().info_name || r().subdomain}

wss://{r().subdomain}.spaces.coracle.social - -

{r().description}

+ +

{r().info_description}

@@ -233,13 +237,13 @@ export default function RelayDetailCard(props: RelayDetailCardProps) { @@ -250,19 +254,19 @@ export default function RelayDetailCard(props: RelayDetailCardProps) { @@ -270,7 +274,7 @@ export default function RelayDetailCard(props: RelayDetailCardProps) { }> + }> @@ -303,7 +307,7 @@ export default function RelayDetailCard(props: RelayDetailCardProps) { }> + }> diff --git a/frontend/src/lib/api.ts b/frontend/src/lib/api.ts index a812e5a..5176aed 100644 --- a/frontend/src/lib/api.ts +++ b/frontend/src/lib/api.ts @@ -20,6 +20,11 @@ type EventSigner = { signEvent(event: UnsignedEvent): Promise } +type ApiOk = { + data: T + code: string +} + export class ApiError extends Error { status: number @@ -36,6 +41,12 @@ function getActiveSigner(): EventSigner { return account.signer } +function getActivePubkey(): string { + const account = accounts.getActive() as { pubkey?: string } | undefined + if (!account?.pubkey) throw new Error("Not logged in") + return account.pubkey +} + async function createNip98Header(url: string, method: string): Promise { const signer = getActiveSigner() const event = await signer.signEvent({ @@ -75,69 +86,63 @@ async function request(path: string, init?: RequestInit): Promise { } catch { // ignored } - if (response.status === 403 && path.startsWith("/admin/") && typeof window !== "undefined") { - window.location.replace("/relays") - } throw new ApiError(message, response.status) } - if (response.status === 204) { - return undefined as T - } - - return response.json() as Promise + if (response.status === 204) return undefined as T + const body = await response.json() as ApiOk + return body.data } -export type RelayConfig = { - policy: { - public_join: boolean - strip_signatures: boolean - } - groups: { - enabled: boolean - auto_join: boolean - } - management: { - enabled: boolean - - } - blossom: { - enabled: boolean - } - livekit: { - enabled: boolean - } - push: { - enabled: boolean +async function ensureTenant() { + try { + await request("/tenants", { method: "POST" }) + } catch (e) { + if (e instanceof ApiError && e.status === 422) return + throw e } } export type Relay = { id: string tenant: string - name: string - subdomain: string schema: string - icon: string - description: string + subdomain: string plan: string status: string - config: RelayConfig + sync_error: string + info_name: string + info_icon: string + info_description: string + policy_public_join: number + policy_strip_signatures: number + groups_enabled: number + management_enabled: number + blossom_enabled: number + livekit_enabled: number + push_enabled: number } export type Tenant = { pubkey: string - status: string - tenant_nwc_url: string + nwc_url: string + created_at: number + billing_anchor: number } export type Invoice = { id: string tenant: string - amount: number status: string - created_at: string - invoice: string + created_at: number + attempted_at: number + error: string + closed_at: number + sent_at: number + paid_at: number + bolt11: string + period_start: number + period_end: number } export type TenantDetail = { @@ -145,12 +150,34 @@ export type TenantDetail = { relays: Relay[] } -export type UpdateRelayInput = { - name: string +export type CreateRelayInput = { subdomain: string - icon: string - description: string - config: RelayConfig + plan: string + info_name?: string + info_icon?: string + info_description?: string + policy_public_join?: number + policy_strip_signatures?: number + groups_enabled?: number + management_enabled?: number + blossom_enabled?: number + livekit_enabled?: number + push_enabled?: number +} + +export type UpdateRelayInput = { + subdomain?: string + plan?: string + info_name?: string + info_icon?: string + info_description?: string + policy_public_join?: number + policy_strip_signatures?: number + groups_enabled?: number + management_enabled?: number + blossom_enabled?: number + livekit_enabled?: number + push_enabled?: number } export type AdminCheck = { @@ -158,100 +185,101 @@ export type AdminCheck = { } export function listTenantRelays() { - return request("/tenant/relays") + return request("/relays") } -export function getTenant() { - return request("/tenant") +export async function getTenant() { + const pubkey = getActivePubkey() + await ensureTenant() + return request(`/tenants/${pubkey}`) } -export type CreateRelayInput = { - name: string - subdomain: string - icon: string - description: string - plan: string - config: RelayConfig -} - -export function createTenantRelay(input: CreateRelayInput) { - return request("/tenant/relays", { +export async function createTenantRelay(input: CreateRelayInput) { + await ensureTenant() + return request("/relays", { method: "POST", - body: JSON.stringify(input), + body: JSON.stringify({ tenant: getActivePubkey(), ...input }), }) } export function getTenantRelay(id: string) { - return request(`/tenant/relays/${id}`) + return request(`/relays/${id}`) } export function updateTenantRelay(id: string, input: UpdateRelayInput) { - return request(`/tenant/relays/${id}`, { + return request(`/relays/${id}`, { method: "PUT", body: JSON.stringify(input), }) } export function updateTenantRelayPlan(id: string, plan: string) { - return request(`/tenant/relays/${id}/plan`, { - method: "PUT", - body: JSON.stringify({ plan }), - }) + return updateTenantRelay(id, { plan }) } export function deactivateTenantRelay(id: string) { - return request(`/tenant/relays/${id}/deactivate`, { + return request(`/relays/${id}/deactivate`, { method: "POST", }) } -export function listTenantInvoices() { - return request("/tenant/invoices") +export async function listTenantInvoices() { + await ensureTenant() + return request("/invoices") } -export function updateTenantBilling(tenant_nwc_url: string) { - return request("/tenant/billing", { +export function updateTenantBilling(nwc_url: string) { + return request<{ nwc_url: string }>(`/tenants/${getActivePubkey()}/billing`, { method: "PUT", - body: JSON.stringify({ tenant_nwc_url }), + body: JSON.stringify({ nwc_url }), }) } export function adminListTenants() { - return request("/admin/tenants") + return request("/tenants") } -export function adminCheck() { - return request("/admin/check") +export async function adminCheck() { + try { + await request("/tenants") + return { is_admin: true } + } catch (e) { + if (e instanceof ApiError && e.status === 403) return { is_admin: false } + throw e + } } -export function adminGetTenant(pubkey: string) { - return request(`/admin/tenants/${pubkey}`) +export async function adminGetTenant(pubkey: string) { + const [tenant, relays] = await Promise.all([ + request(`/tenants/${pubkey}`), + request(`/relays?tenant=${encodeURIComponent(pubkey)}`), + ]) + return { tenant, relays } } export function adminUpdateTenantStatus(pubkey: string, status: string) { - return request(`/admin/tenants/${pubkey}`, { - method: "PUT", - body: JSON.stringify({ status }), - }) + void pubkey + void status + throw new Error("Tenant status updates are not supported by this API") } export function adminListRelays() { - return request("/admin/relays") + return request("/relays") } export function adminGetRelay(id: string) { - return request(`/admin/relays/${id}`) + return request(`/relays/${id}`) } export function adminUpdateRelay(id: string, input: UpdateRelayInput) { - return request(`/admin/relays/${id}`, { + return request(`/relays/${id}`, { method: "PUT", body: JSON.stringify(input), }) } export function adminDeactivateRelay(id: string) { - return request(`/admin/relays/${id}/deactivate`, { + return request(`/relays/${id}/deactivate`, { method: "POST", }) } diff --git a/frontend/src/pages/Account.tsx b/frontend/src/pages/Account.tsx index 83004b3..c5dd54a 100644 --- a/frontend/src/pages/Account.tsx +++ b/frontend/src/pages/Account.tsx @@ -13,13 +13,13 @@ export default function Account() { const invoicesLoading = useMinLoading(() => invoices.loading) const hasBillingChanges = createMemo(() => { - const current = tenant()?.tenant_nwc_url?.trim() ?? "" + const current = tenant()?.nwc_url?.trim() ?? "" const next = nwcUrl().trim() return current !== next }) createEffect(() => { - setNwcUrl(tenant()?.tenant_nwc_url ?? "") + setNwcUrl(tenant()?.nwc_url ?? "") }) async function saveBilling() { @@ -47,7 +47,7 @@ export default function Account() { {(t) => ( - {t().status} + tenant )} @@ -93,11 +93,11 @@ export default function Account() { {(invoice) => (
  • - {invoice.amount.toLocaleString()} sats + {invoice.status}
    -

    {new Date(invoice.created_at).toLocaleString()}

    -

    {invoice.invoice}

    +

    {new Date(invoice.created_at * 1000).toLocaleString()}

    +

    {invoice.bolt11}

  • )} diff --git a/frontend/src/pages/admin/AdminRelayDetail.tsx b/frontend/src/pages/admin/AdminRelayDetail.tsx index d32776a..bf2755c 100644 --- a/frontend/src/pages/admin/AdminRelayDetail.tsx +++ b/frontend/src/pages/admin/AdminRelayDetail.tsx @@ -1,6 +1,6 @@ import { useParams } from "@solidjs/router" import { createResource, createSignal, Show } from "solid-js" -import { adminDeactivateRelay, adminGetRelay, adminUpdateRelay, type RelayConfig } from "../../lib/api" +import { adminDeactivateRelay, adminGetRelay, adminUpdateRelay, type Relay } from "../../lib/api" import BackLink from "../../components/BackLink" import PageContainer from "../../components/PageContainer" import RelayDetailCard from "../../components/RelayDetailCard" @@ -29,118 +29,100 @@ 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"), - }, - livekit: { - enabled: config?.livekit.enabled ?? (relay()?.plan !== "free"), - }, - push: { - enabled: config?.push.enabled ?? true, - }, - } + function toBool(value: number | undefined, fallback: boolean): boolean { + if (value === 0) return false + if (value === 1) return true + return fallback } - async function updateFlags(nextConfig: RelayConfig, previousConfig: RelayConfig) { + function toInt(value: boolean): number { + return value ? 1 : 0 + } + + async function updateRelay(next: Relay, previous: Relay) { const current = relay() if (!current) return setError("") - const optimisticRelay = { - ...current, - config: nextConfig, - } - mutate(optimisticRelay) + mutate(next) try { - await adminUpdateRelay(relayId(), { - name: current.name, - subdomain: current.subdomain, - icon: current.icon, - description: current.description, - config: nextConfig, - }) + await adminUpdateRelay(relayId(), next) await refetch() } catch (e) { - mutate({ ...current, config: previousConfig }) + mutate(previous) 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 }, + const current = relay() + if (!current) return + const next = { + ...current, + policy_public_join: toInt(!toBool(current.policy_public_join, false)), } - void updateFlags(nextConfig, config) + void updateRelay(next, current) } function toggleStripSignatures() { - const config = withDefaults(relay()?.config) - const nextConfig = { - ...config, - policy: { ...config.policy, strip_signatures: !config.policy.strip_signatures }, + const current = relay() + if (!current) return + const next = { + ...current, + policy_strip_signatures: toInt(!toBool(current.policy_strip_signatures, false)), } - void updateFlags(nextConfig, config) + void updateRelay(next, current) } function toggleGroups() { - const config = withDefaults(relay()?.config) - const nextConfig = { - ...config, - groups: { ...config.groups, enabled: !config.groups.enabled }, + const current = relay() + if (!current) return + const next = { + ...current, + groups_enabled: toInt(!toBool(current.groups_enabled, true)), } - void updateFlags(nextConfig, config) + void updateRelay(next, current) } function toggleManagement() { - const config = withDefaults(relay()?.config) - const nextConfig = { - ...config, - management: { enabled: !config.management.enabled }, + const current = relay() + if (!current) return + const next = { + ...current, + management_enabled: toInt(!toBool(current.management_enabled, true)), } - void updateFlags(nextConfig, config) + void updateRelay(next, current) } function toggleMediaStorage() { - const config = withDefaults(relay()?.config) - const nextConfig = { - ...config, - blossom: { enabled: !config.blossom.enabled }, + const current = relay() + if (!current) return + const next = { + ...current, + blossom_enabled: toInt(!toBool(current.blossom_enabled, current.plan !== "free")), } - void updateFlags(nextConfig, config) + void updateRelay(next, current) } function togglePushNotifications() { - const config = withDefaults(relay()?.config) - const nextConfig = { - ...config, - push: { enabled: !config.push.enabled }, + const current = relay() + if (!current) return + const next = { + ...current, + push_enabled: toInt(!toBool(current.push_enabled, true)), } - void updateFlags(nextConfig, config) + void updateRelay(next, current) } function toggleLivekitSupport() { - const config = withDefaults(relay()?.config) - const nextConfig = { - ...config, - livekit: { enabled: !config.livekit.enabled }, + const current = relay() + if (!current) return + const next = { + ...current, + livekit_enabled: toInt(!toBool(current.livekit_enabled, current.plan !== "free")), } - void updateFlags(nextConfig, config) + void updateRelay(next, current) } return ( diff --git a/frontend/src/pages/admin/AdminRelayEdit.tsx b/frontend/src/pages/admin/AdminRelayEdit.tsx index 0f7eac2..11b893c 100644 --- a/frontend/src/pages/admin/AdminRelayEdit.tsx +++ b/frontend/src/pages/admin/AdminRelayEdit.tsx @@ -1,6 +1,6 @@ import { useNavigate, useParams } from "@solidjs/router" import { Show, createEffect, createResource, createSignal } from "solid-js" -import { adminGetRelay, adminUpdateRelay, type RelayConfig } from "../../lib/api" +import { adminGetRelay, adminUpdateRelay } from "../../lib/api" import RelayForm from "../../components/RelayForm" import { slugify } from "../../lib/slugify" import BackLink from "../../components/BackLink" @@ -8,15 +8,6 @@ import PageContainer from "../../components/PageContainer" import ResourceState from "../../components/ResourceState" import useMinLoading from "../../components/useMinLoading" -const DEFAULT_CONFIG: RelayConfig = { - policy: { public_join: false, strip_signatures: false }, - groups: { enabled: false, auto_join: false }, - management: { enabled: false }, - blossom: { enabled: false }, - livekit: { enabled: false }, - push: { enabled: false }, -} - export default function AdminRelayEdit() { const navigate = useNavigate() const params = useParams() @@ -34,10 +25,10 @@ export default function AdminRelayEdit() { createEffect(() => { const data = relay() if (!data) return - setName(data.name) + setName(data.info_name) setSubdomain(data.subdomain) - setIcon(data.icon) - setDescription(data.description) + setIcon(data.info_icon) + setDescription(data.info_description) }) async function handleSubmit(e: Event) { @@ -46,11 +37,10 @@ export default function AdminRelayEdit() { setSubmitting(true) try { await adminUpdateRelay(relayId(), { - name: name().trim(), subdomain: slugify(subdomain()), - icon: icon().trim(), - description: description().trim(), - config: relay()?.config ?? DEFAULT_CONFIG, + info_name: name().trim(), + info_icon: icon().trim(), + info_description: description().trim(), }) navigate(`/admin/relays/${relayId()}`) } catch (e) { diff --git a/frontend/src/pages/admin/AdminRelayList.tsx b/frontend/src/pages/admin/AdminRelayList.tsx index 8105625..d302042 100644 --- a/frontend/src/pages/admin/AdminRelayList.tsx +++ b/frontend/src/pages/admin/AdminRelayList.tsx @@ -18,7 +18,7 @@ export default function AdminRelayList() { if (!q) return list return new Fuse(list, { - keys: ["name", "subdomain", "tenant"], + keys: ["info_name", "subdomain", "tenant"], threshold: 0.35, ignoreLocation: true, }).search(q).map((result) => result.item) @@ -60,7 +60,7 @@ export default function AdminRelayList() {
    -

    {relay.name}

    +

    {relay.info_name || relay.subdomain}

    {relay.subdomain}.spaces.coracle.social

    Tenant: {relay.tenant}

    diff --git a/frontend/src/pages/admin/AdminTenantDetail.tsx b/frontend/src/pages/admin/AdminTenantDetail.tsx index 3cb51a2..fc6e613 100644 --- a/frontend/src/pages/admin/AdminTenantDetail.tsx +++ b/frontend/src/pages/admin/AdminTenantDetail.tsx @@ -1,6 +1,6 @@ import { useParams, A } from "@solidjs/router" -import { createResource, createSignal, For, Show } from "solid-js" -import { adminGetTenant, adminUpdateTenantStatus } from "../../lib/api" +import { createResource, For, Show } from "solid-js" +import { adminGetTenant } from "../../lib/api" import BackLink from "../../components/BackLink" import PageContainer from "../../components/PageContainer" import ResourceState from "../../components/ResourceState" @@ -9,25 +9,9 @@ import useMinLoading from "../../components/useMinLoading" export default function AdminTenantDetail() { const params = useParams() const tenantId = () => params.id ?? "" - const [detail, { refetch }] = createResource(tenantId, adminGetTenant) - const [busy, setBusy] = createSignal(false) - const [error, setError] = createSignal("") + const [detail] = createResource(tenantId, adminGetTenant) const loading = useMinLoading(() => detail.loading) - async function setStatus(status: string) { - if (busy()) return - setBusy(true) - setError("") - try { - await adminUpdateTenantStatus(tenantId(), status) - await refetch() - } catch (e) { - setError(e instanceof Error ? e.message : "Failed to update tenant") - } finally { - setBusy(false) - } - } - return ( @@ -49,24 +33,8 @@ export default function AdminTenantDetail() { {(d) => (

    - Current: {d().tenant.status} + Current: tenant

    -
    - - -
    )} @@ -82,7 +50,7 @@ export default function AdminTenantDetail() {
    -

    {relay.name}

    +

    {relay.info_name || relay.subdomain}

    {relay.subdomain}.spaces.coracle.social

    {relay.status} @@ -94,9 +62,6 @@ export default function AdminTenantDetail() { - -

    {error()}

    -
    diff --git a/frontend/src/pages/admin/AdminTenantList.tsx b/frontend/src/pages/admin/AdminTenantList.tsx index 9ce0d6e..3758448 100644 --- a/frontend/src/pages/admin/AdminTenantList.tsx +++ b/frontend/src/pages/admin/AdminTenantList.tsx @@ -115,7 +115,7 @@ export default function AdminTenantList() {

    {tenant.pubkey}

    -

    {tenant.status}

    +

    tenant

    diff --git a/frontend/src/pages/relays/RelayDetail.tsx b/frontend/src/pages/relays/RelayDetail.tsx index 1ab7b33..54678a5 100644 --- a/frontend/src/pages/relays/RelayDetail.tsx +++ b/frontend/src/pages/relays/RelayDetail.tsx @@ -1,6 +1,6 @@ import { useParams } from "@solidjs/router" import { createMemo, createResource, createSignal, Show } from "solid-js" -import { deactivateTenantRelay, getRelayMemberCount, getTenantRelay, updateTenantRelay, updateTenantRelayPlan, type RelayConfig } from "../../lib/api" +import { deactivateTenantRelay, getRelayMemberCount, getTenantRelay, updateTenantRelay, updateTenantRelayPlan, type Relay } from "../../lib/api" import type { RelayPlanId } from "../../lib/relayPlans" import BackLink from "../../components/BackLink" import PageContainer from "../../components/PageContainer" @@ -35,114 +35,100 @@ export default function RelayDetail() { } } - 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"), - }, - livekit: { - enabled: config?.livekit.enabled ?? (relay()?.plan !== "free"), - }, - push: { - enabled: config?.push.enabled ?? true, - }, - } + function toBool(value: number | undefined, fallback: boolean): boolean { + if (value === 0) return false + if (value === 1) return true + return fallback } - async function updateFlags(nextConfig: RelayConfig, previousConfig: RelayConfig) { + function toInt(value: boolean): number { + return value ? 1 : 0 + } + + async function updateRelay(next: Relay, previous: Relay) { const current = relay() if (!current) return setError("") - mutate({ ...current, config: nextConfig }) + mutate(next) try { - await updateTenantRelay(relayId(), { - name: current.name, - subdomain: current.subdomain, - icon: current.icon, - description: current.description, - config: nextConfig, - }) + await updateTenantRelay(relayId(), next) await refetch() } catch (e) { - mutate({ ...current, config: previousConfig }) + mutate(previous) 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 }, + const current = relay() + if (!current) return + const next = { + ...current, + policy_public_join: toInt(!toBool(current.policy_public_join, false)), } - void updateFlags(nextConfig, config) + void updateRelay(next, current) } function toggleStripSignatures() { - const config = withDefaults(relay()?.config) - const nextConfig = { - ...config, - policy: { ...config.policy, strip_signatures: !config.policy.strip_signatures }, + const current = relay() + if (!current) return + const next = { + ...current, + policy_strip_signatures: toInt(!toBool(current.policy_strip_signatures, false)), } - void updateFlags(nextConfig, config) + void updateRelay(next, current) } function toggleGroups() { - const config = withDefaults(relay()?.config) - const nextConfig = { - ...config, - groups: { ...config.groups, enabled: !config.groups.enabled }, + const current = relay() + if (!current) return + const next = { + ...current, + groups_enabled: toInt(!toBool(current.groups_enabled, true)), } - void updateFlags(nextConfig, config) + void updateRelay(next, current) } function toggleManagement() { - const config = withDefaults(relay()?.config) - const nextConfig = { - ...config, - management: { enabled: !config.management.enabled }, + const current = relay() + if (!current) return + const next = { + ...current, + management_enabled: toInt(!toBool(current.management_enabled, true)), } - void updateFlags(nextConfig, config) + void updateRelay(next, current) } function toggleMediaStorage() { - const config = withDefaults(relay()?.config) - const nextConfig = { - ...config, - blossom: { enabled: !config.blossom.enabled }, + const current = relay() + if (!current) return + const next = { + ...current, + blossom_enabled: toInt(!toBool(current.blossom_enabled, current.plan !== "free")), } - void updateFlags(nextConfig, config) + void updateRelay(next, current) } function togglePushNotifications() { - const config = withDefaults(relay()?.config) - const nextConfig = { - ...config, - push: { enabled: !config.push.enabled }, + const current = relay() + if (!current) return + const next = { + ...current, + push_enabled: toInt(!toBool(current.push_enabled, true)), } - void updateFlags(nextConfig, config) + void updateRelay(next, current) } function toggleLivekitSupport() { - const config = withDefaults(relay()?.config) - const nextConfig = { - ...config, - livekit: { enabled: !config.livekit.enabled }, + const current = relay() + if (!current) return + const next = { + ...current, + livekit_enabled: toInt(!toBool(current.livekit_enabled, current.plan !== "free")), } - void updateFlags(nextConfig, config) + void updateRelay(next, current) } async function handleUpdatePlan(plan: RelayPlanId) { @@ -152,13 +138,14 @@ export default function RelayDetail() { const previous = current setError("") - const nextConfig = withDefaults(current.config) + const next = { ...current } if (plan === "free") { - nextConfig.blossom = { enabled: false } - nextConfig.livekit = { enabled: false } + next.blossom_enabled = 0 + next.livekit_enabled = 0 } - mutate({ ...current, plan, config: nextConfig }) + next.plan = plan + mutate(next) try { await updateTenantRelayPlan(relayId(), plan) diff --git a/frontend/src/pages/relays/RelayEdit.tsx b/frontend/src/pages/relays/RelayEdit.tsx index 78a08b7..80542dc 100644 --- a/frontend/src/pages/relays/RelayEdit.tsx +++ b/frontend/src/pages/relays/RelayEdit.tsx @@ -1,6 +1,6 @@ import { useNavigate, useParams } from "@solidjs/router" import { Show, createEffect, createResource, createSignal } from "solid-js" -import { getTenantRelay, updateTenantRelay, type RelayConfig } from "../../lib/api" +import { getTenantRelay, updateTenantRelay } from "../../lib/api" import RelayForm from "../../components/RelayForm" import { slugify } from "../../lib/slugify" import BackLink from "../../components/BackLink" @@ -8,15 +8,6 @@ import PageContainer from "../../components/PageContainer" import ResourceState from "../../components/ResourceState" import useMinLoading from "../../components/useMinLoading" -const DEFAULT_CONFIG: RelayConfig = { - policy: { public_join: false, strip_signatures: false }, - groups: { enabled: false, auto_join: false }, - management: { enabled: false }, - blossom: { enabled: false }, - livekit: { enabled: false }, - push: { enabled: false }, -} - export default function RelayEdit() { const navigate = useNavigate() const params = useParams() @@ -34,10 +25,10 @@ export default function RelayEdit() { createEffect(() => { const data = relay() if (!data) return - setName(data.name) + setName(data.info_name) setSubdomain(data.subdomain) - setIcon(data.icon) - setDescription(data.description) + setIcon(data.info_icon) + setDescription(data.info_description) }) async function handleSubmit(e: Event) { @@ -46,11 +37,10 @@ export default function RelayEdit() { setSubmitting(true) try { await updateTenantRelay(relayId(), { - name: name().trim(), subdomain: slugify(subdomain()), - icon: icon().trim(), - description: description().trim(), - config: relay()?.config ?? DEFAULT_CONFIG, + info_name: name().trim(), + info_icon: icon().trim(), + info_description: description().trim(), }) navigate(`/relays/${relayId()}`) } catch (e) { diff --git a/frontend/src/pages/relays/RelayList.tsx b/frontend/src/pages/relays/RelayList.tsx index 53d1078..137d27b 100644 --- a/frontend/src/pages/relays/RelayList.tsx +++ b/frontend/src/pages/relays/RelayList.tsx @@ -17,7 +17,7 @@ export default function RelayList() { const q = query().trim() const searched = q ? new Fuse(list, { - keys: ["name", "subdomain"], + keys: ["info_name", "subdomain"], threshold: 0.35, ignoreLocation: true, }).search(q).map((result) => result.item) @@ -90,7 +90,7 @@ export default function RelayList() { >
    -

    {relay.name}

    +

    {relay.info_name || relay.subdomain}

    https://{relay.subdomain}.spaces.coracle.social

    {relay.status}

    diff --git a/frontend/src/pages/relays/RelayNew.tsx b/frontend/src/pages/relays/RelayNew.tsx index f29d3d1..ce8e3ee 100644 --- a/frontend/src/pages/relays/RelayNew.tsx +++ b/frontend/src/pages/relays/RelayNew.tsx @@ -1,6 +1,6 @@ import { Show, createSignal } from "solid-js" import { useNavigate } from "@solidjs/router" -import { createTenantRelay, type RelayConfig } from "../../lib/api" +import { createTenantRelay } from "../../lib/api" import { slugify } from "../../lib/slugify" const PLANS = [ @@ -11,15 +11,6 @@ const PLANS = [ type PlanId = (typeof PLANS)[number]["id"] -const DEFAULT_CONFIG: RelayConfig = { - policy: { public_join: false, strip_signatures: false }, - groups: { enabled: true, auto_join: true }, - management: { enabled: true }, - blossom: { enabled: false }, - livekit: { enabled: false }, - push: { enabled: true }, -} - export default function RelayNew() { const navigate = useNavigate() const [name, setName] = createSignal("") @@ -44,16 +35,18 @@ export default function RelayNew() { try { const relay = await createTenantRelay({ - name: name().trim(), subdomain: slugify(subdomain()), - icon: icon().trim(), - description: description().trim(), plan: plan(), - config: { - ...DEFAULT_CONFIG, - blossom: { enabled: plan() !== "free" }, - livekit: { enabled: plan() !== "free" }, - }, + info_name: name().trim(), + info_icon: icon().trim(), + info_description: description().trim(), + policy_public_join: 0, + policy_strip_signatures: 0, + groups_enabled: 1, + management_enabled: 1, + blossom_enabled: plan() === "free" ? 0 : 1, + livekit_enabled: plan() === "free" ? 0 : 1, + push_enabled: 1, }) navigate(`/relays/${relay.id}`) } catch (e) {