From 48b8b68f90724627c4d1779af917d783eb0edb29 Mon Sep 17 00:00:00 2001 From: Musiker15 Date: Thu, 29 Oct 2026 06:43:27 +0100 Subject: [PATCH] Show when removing the custom domain fails remove() in the domain form ignored the response: a failed DELETE cleared the field, closed the dialog and refreshed, so it looked as if the domain was gone while it was still configured. The response is checked now. On failure the dialog stays open and shows the reason (the API's message, or "Could not remove the domain."), so the owner can retry or cancel. --- apps/web/src/components/domain/domain-form.tsx | 17 +++++++++++++++-- apps/web/src/i18n/dictionaries.ts | 7 +++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/apps/web/src/components/domain/domain-form.tsx b/apps/web/src/components/domain/domain-form.tsx index 7a2ad45..cd4505c 100644 --- a/apps/web/src/components/domain/domain-form.tsx +++ b/apps/web/src/components/domain/domain-form.tsx @@ -45,6 +45,7 @@ export function DomainForm({ const [error, setError] = useState(null); const [verifyMsg, setVerifyMsg] = useState(null); const [confirmRemove, setConfirmRemove] = useState(false); + const [removeError, setRemoveError] = useState(null); const records = initial.domain && initial.token @@ -93,12 +94,20 @@ export function DomainForm({ } async function remove() { + setRemoveError(null); setBusy("remove"); try { - await fetch(`/api/guilds/${guildId}/domain`, { method: "DELETE" }); + const res = await fetch(`/api/guilds/${guildId}/domain`, { method: "DELETE" }); + if (!res.ok) { + const data = (await res.json().catch(() => null)) as { error?: string } | null; + throw new Error(data?.error ?? t.errRemove); + } setDomain(""); setConfirmRemove(false); router.refresh(); + } catch (err) { + // The dialog stays open with the reason, so the domain is not shown as gone. + setRemoveError(err instanceof Error ? err.message : t.errRemove); } finally { setBusy(null); } @@ -197,7 +206,10 @@ export function DomainForm({ { - if (busy !== "remove") setConfirmRemove(false); + if (busy !== "remove") { + setConfirmRemove(false); + setRemoveError(null); + } }} onConfirm={remove} title={t.remove} @@ -206,6 +218,7 @@ export function DomainForm({ cancelLabel={t.cancel} tone="danger" busy={busy === "remove"} + error={removeError} typeToConfirm={{ expected: initial.domain, label: t.typeDomain.replace("{domain}", initial.domain), diff --git a/apps/web/src/i18n/dictionaries.ts b/apps/web/src/i18n/dictionaries.ts index a020a61..7fd6c3f 100644 --- a/apps/web/src/i18n/dictionaries.ts +++ b/apps/web/src/i18n/dictionaries.ts @@ -898,6 +898,7 @@ const en = { removeConfirm: "Remove this custom domain? Your forms will go back to the default URL.", cancel: "Cancel", errSave: "Could not save the domain.", + errRemove: "Could not remove the domain.", step1: "1. Point your domain to us with a CNAME record:", step2: "2. Prove ownership with a TXT record:", recordName: "Name", @@ -2210,6 +2211,7 @@ const de: Dictionary = { "Diese Domain entfernen? Deine Formulare sind dann wieder unter der Standard-URL erreichbar.", cancel: "Abbrechen", errSave: "Domain konnte nicht gespeichert werden.", + errRemove: "Die Domain konnte nicht entfernt werden.", step1: "1. Zeige mit einem CNAME-Eintrag auf uns:", step2: "2. Weise den Besitz mit einem TXT-Eintrag nach:", recordName: "Name", @@ -3521,6 +3523,7 @@ const hu: Dictionary = { "Eltávolítod ezt a domaint? Az űrlapjaid újra az alapértelmezett URL-en lesznek elérhetők.", cancel: "Mégse", errSave: "A domain mentése sikertelen.", + errRemove: "Nem sikerült eltávolítani a domaint.", step1: "1. Mutass ránk egy CNAME rekorddal:", step2: "2. Igazold a tulajdonjogot egy TXT rekorddal:", recordName: "Név", @@ -4826,6 +4829,7 @@ const fr: Dictionary = { "Supprimer ce domaine personnalisé ? Vos formulaires reviendront à l'URL par défaut.", cancel: "Annuler", errSave: "Impossible d'enregistrer le domaine.", + errRemove: "Impossible de supprimer le domaine.", step1: "1. Pointez votre domaine vers nous avec un enregistrement CNAME :", step2: "2. Prouvez la propriété avec un enregistrement TXT :", recordName: "Nom", @@ -6133,6 +6137,7 @@ const es: Dictionary = { "¿Eliminar este dominio personalizado? Tus formularios volverán a la URL predeterminada.", cancel: "Cancelar", errSave: "No se pudo guardar el dominio.", + errRemove: "No se pudo quitar el dominio.", step1: "1. Apunta tu dominio hacia nosotros con un registro CNAME:", step2: "2. Prueba la propiedad con un registro TXT:", recordName: "Nombre", @@ -7433,6 +7438,7 @@ const pt: Dictionary = { removeConfirm: "Remover este domínio personalizado? Seus formulários voltarão à URL padrão.", cancel: "Cancelar", errSave: "Não foi possível salvar o domínio.", + errRemove: "Não foi possível remover o domínio.", step1: "1. Aponte seu domínio para nós com um registro CNAME:", step2: "2. Prove a propriedade com um registro TXT:", recordName: "Nome", @@ -8729,6 +8735,7 @@ const pl: Dictionary = { removeConfirm: "Usunąć tę domenę? Twoje formularze wrócą pod domyślny adres URL.", cancel: "Anuluj", errSave: "Nie udało się zapisać domeny.", + errRemove: "Nie udało się usunąć domeny.", step1: "1. Wskaż na nas domenę rekordem CNAME:", step2: "2. Potwierdź własność rekordem TXT:", recordName: "Nazwa",