don't allow deleting config managed domains

This commit is contained in:
miloschwartz 2025-07-15 13:20:44 -07:00
parent ffe8593a07
commit 83a4677026
No known key found for this signature in database
5 changed files with 40 additions and 21 deletions

View file

@ -1161,7 +1161,7 @@
"selectDomainTypeNsDescription": "This domain and all its subdomains. Use this when you want to control an entire domain zone.", "selectDomainTypeNsDescription": "This domain and all its subdomains. Use this when you want to control an entire domain zone.",
"selectDomainTypeCnameName": "Single Domain (CNAME)", "selectDomainTypeCnameName": "Single Domain (CNAME)",
"selectDomainTypeCnameDescription": "Just this specific domain. Use this for individual subdomains or specific domain entries.", "selectDomainTypeCnameDescription": "Just this specific domain. Use this for individual subdomains or specific domain entries.",
"selectDomainTypeWildcardName": "Wildcard Domain (CNAME)", "selectDomainTypeWildcardName": "Wildcard Domain",
"selectDomainTypeWildcardDescription": "This domain and its first level of subdomains.", "selectDomainTypeWildcardDescription": "This domain and its first level of subdomains.",
"domainDelegation": "Single Domain", "domainDelegation": "Single Domain",
"selectType": "Select a type", "selectType": "Select a type",

View file

@ -42,6 +42,7 @@ async function queryDomains(orgId: string, limit: number, offset: number) {
type: domains.type, type: domains.type,
failed: domains.failed, failed: domains.failed,
tries: domains.tries, tries: domains.tries,
configManaged: domains.configManaged
}) })
.from(orgDomains) .from(orgDomains)
.where(eq(orgDomains.orgId, orgId)) .where(eq(orgDomains.orgId, orgId))

View file

@ -23,6 +23,7 @@ export type DomainRow = {
verified: boolean; verified: boolean;
failed: boolean; failed: boolean;
tries: number; tries: number;
configManaged: boolean;
}; };
type Props = { type Props = {
@ -36,7 +37,9 @@ export default function DomainsTable({ domains }: Props) {
null null
); );
const [isRefreshing, setIsRefreshing] = useState(false); const [isRefreshing, setIsRefreshing] = useState(false);
const [restartingDomains, setRestartingDomains] = useState<Set<string>>(new Set()); const [restartingDomains, setRestartingDomains] = useState<Set<string>>(
new Set()
);
const api = createApiClient(useEnvContext()); const api = createApiClient(useEnvContext());
const router = useRouter(); const router = useRouter();
const t = useTranslations(); const t = useTranslations();
@ -46,6 +49,7 @@ export default function DomainsTable({ domains }: Props) {
const refreshData = async () => { const refreshData = async () => {
setIsRefreshing(true); setIsRefreshing(true);
try { try {
await new Promise((resolve) => setTimeout(resolve, 200));
router.refresh(); router.refresh();
} catch (error) { } catch (error) {
toast({ toast({
@ -77,12 +81,14 @@ export default function DomainsTable({ domains }: Props) {
}; };
const restartDomain = async (domainId: string) => { const restartDomain = async (domainId: string) => {
setRestartingDomains(prev => new Set(prev).add(domainId)); setRestartingDomains((prev) => new Set(prev).add(domainId));
try { try {
await api.post(`/org/${org.org.orgId}/domain/${domainId}/restart`); await api.post(`/org/${org.org.orgId}/domain/${domainId}/restart`);
toast({ toast({
title: t("success"), title: t("success"),
description: t("domainRestartedDescription", { fallback: "Domain verification restarted successfully" }) description: t("domainRestartedDescription", {
fallback: "Domain verification restarted successfully"
})
}); });
refreshData(); refreshData();
} catch (e) { } catch (e) {
@ -92,7 +98,7 @@ export default function DomainsTable({ domains }: Props) {
variant: "destructive" variant: "destructive"
}); });
} finally { } finally {
setRestartingDomains(prev => { setRestartingDomains((prev) => {
const newSet = new Set(prev); const newSet = new Set(prev);
newSet.delete(domainId); newSet.delete(domainId);
return newSet; return newSet;
@ -172,7 +178,11 @@ export default function DomainsTable({ domains }: Props) {
if (verified) { if (verified) {
return <Badge variant="green">{t("verified")}</Badge>; return <Badge variant="green">{t("verified")}</Badge>;
} else if (failed) { } else if (failed) {
return <Badge variant="destructive">{t("failed", { fallback: "Failed" })}</Badge>; return (
<Badge variant="destructive">
{t("failed", { fallback: "Failed" })}
</Badge>
);
} else { } else {
return <Badge variant="yellow">{t("pending")}</Badge>; return <Badge variant="yellow">{t("pending")}</Badge>;
} }
@ -193,9 +203,14 @@ export default function DomainsTable({ domains }: Props) {
onClick={() => restartDomain(domain.domainId)} onClick={() => restartDomain(domain.domainId)}
disabled={isRestarting} disabled={isRestarting}
> >
{isRestarting ? t("restarting", { fallback: "Restarting..." }) : t("restart", { fallback: "Restart" })} {isRestarting
? t("restarting", {
fallback: "Restarting..."
})
: t("restart", { fallback: "Restart" })}
</Button> </Button>
)} )}
{!domain.configManaged && (
<Button <Button
variant="secondary" variant="secondary"
size="sm" size="sm"
@ -206,6 +221,7 @@ export default function DomainsTable({ domains }: Props) {
> >
{t("delete")} {t("delete")}
</Button> </Button>
)}
</div> </div>
); );
} }

View file

@ -26,7 +26,6 @@ import { toast } from "@app/hooks/useToast";
import { formatAxiosError } from "@app/lib/api"; import { formatAxiosError } from "@app/lib/api";
import { createApiClient } from "@app/lib/api"; import { createApiClient } from "@app/lib/api";
import { useEnvContext } from "@app/hooks/useEnvContext"; import { useEnvContext } from "@app/hooks/useEnvContext";
import CreateSiteFormModal from "./CreateSiteModal";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import { parseDataSize } from "@app/lib/dataSize"; import { parseDataSize } from "@app/lib/dataSize";
import { Badge } from "@app/components/ui/badge"; import { Badge } from "@app/components/ui/badge";
@ -68,8 +67,10 @@ export default function SitesTable({ sites, orgId }: SitesTableProps) {
}, [sites]); }, [sites]);
const refreshData = async () => { const refreshData = async () => {
console.log("Data refreshed");
setIsRefreshing(true); setIsRefreshing(true);
try { try {
await new Promise((resolve) => setTimeout(resolve, 200));
router.refresh(); router.refresh();
} catch (error) { } catch (error) {
toast({ toast({

View file

@ -111,9 +111,10 @@ export function DataTable<TData, TValue>({
variant="outline" variant="outline"
onClick={onRefresh} onClick={onRefresh}
disabled={isRefreshing} disabled={isRefreshing}
loading={isRefreshing}
> >
<RefreshCw className={`mr-2 h-4 w-4 ${isRefreshing ? 'animate-spin' : ''}`} /> <RefreshCw
className={`mr-2 h-4 w-4 ${isRefreshing ? "animate-spin" : ""}`}
/>
{t("refresh")} {t("refresh")}
</Button> </Button>
)} )}