diff --git a/package.json b/package.json index 5a2e77773d..7d9d660304 100644 --- a/package.json +++ b/package.json @@ -95,5 +95,5 @@ "svelte-preprocess" ] }, - "packageManager": "pnpm@10.15.1" + "packageManager": "pnpm@10.18.3" } diff --git a/src/lib/components/domains/cnameTable.svelte b/src/lib/components/domains/cnameTable.svelte index b198524da2..e6216c4dea 100644 --- a/src/lib/components/domains/cnameTable.svelte +++ b/src/lib/components/domains/cnameTable.svelte @@ -1,6 +1,7 @@ @@ -23,15 +37,25 @@ {domain} - {#if verified === true} + {#if ruleStatus === 'created'} + + {:else if ruleStatus === 'verifying'} + + {:else if ruleStatus === 'unverified'} + + {:else if verified === true} - {:else if verified === false} - {/if} - Add the following record on your DNS provider. Note that DNS changes may take time to - propagate fully. + Add the following {$regionalConsoleVariables._APP_DOMAIN_TARGET_CAA + ? 'records' + : 'record'} on your DNS provider. Note that DNS changes may take up to 48 hours to propagate + fully. @@ -43,7 +67,7 @@ CNAME - {subdomain} + {subdomain || '@'} + {#if $regionalConsoleVariables._APP_DOMAIN_TARGET_CAA} + + + + CAA + + + + @ + + + + + {/if} diff --git a/src/lib/components/domains/index.ts b/src/lib/components/domains/index.ts new file mode 100644 index 0000000000..8571098162 --- /dev/null +++ b/src/lib/components/domains/index.ts @@ -0,0 +1,5 @@ +export { default as ViewLogsModal } from './viewLogsModal.svelte'; +export { default as CnameTable } from './cnameTable.svelte'; +export { default as DnsRecordsAction } from './dnsRecordsAction.svelte'; +export { default as NameserverTable } from './nameserverTable.svelte'; +export { default as RecordTable } from './recordTable.svelte'; diff --git a/src/lib/components/domains/nameserverTable.svelte b/src/lib/components/domains/nameserverTable.svelte index a08de42080..57a08151ed 100644 --- a/src/lib/components/domains/nameserverTable.svelte +++ b/src/lib/components/domains/nameserverTable.svelte @@ -3,8 +3,15 @@ import { Badge, Layout, Typography, Table, InteractiveText } from '@appwrite.io/pink-svelte'; - export let domain: string; - export let verified = undefined; + let { + domain, + verified = undefined, + ruleStatus = undefined + }: { + domain: string; + verified?: boolean | undefined; + ruleStatus?: string | undefined; + } = $props(); const nameserverList = $regionalConsoleVariables?._APP_DOMAINS_NAMESERVERS ? $regionalConsoleVariables?._APP_DOMAINS_NAMESERVERS?.split(',') @@ -16,10 +23,18 @@ {domain} - {#if verified === true} + {#if ruleStatus === 'created'} + + {:else if ruleStatus === 'verifying'} + + {:else if ruleStatus === 'unverified'} + + {:else if verified === true} - {:else if verified === false} - {/if} diff --git a/src/lib/components/domains/recordTable.svelte b/src/lib/components/domains/recordTable.svelte index 14683b7218..d55ec16d91 100644 --- a/src/lib/components/domains/recordTable.svelte +++ b/src/lib/components/domains/recordTable.svelte @@ -9,20 +9,58 @@ Alert } from '@appwrite.io/pink-svelte'; import { regionalConsoleVariables } from '$routes/(console)/project-[region]-[project]/store'; + import { isCloud } from '$lib/system'; + import { getSubdomain } from '$lib/helpers/tlds'; - export let domain: string; - export let verified = undefined; - export let variant: 'cname' | 'a' | 'aaaa'; - export let service: 'sites' | 'general' = 'general'; + let { + domain, + verified = undefined, + variant, + service = 'general', + ruleStatus = undefined, + onNavigateToNameservers = () => {}, + onNavigateToA = () => {}, + onNavigateToAAAA = () => {} + }: { + domain: string; + verified?: boolean | undefined; + variant: 'cname' | 'a' | 'aaaa'; + service?: 'sites' | 'functions' | 'general'; + ruleStatus?: string | undefined; + onNavigateToNameservers?: () => void; + onNavigateToA?: () => void; + onNavigateToAAAA?: () => void; + } = $props(); - let subdomain = domain?.split('.')?.slice(0, -2)?.join('.'); + const subdomain = $derived(getSubdomain(domain)); + + const aTabVisible = $derived( + !isCloud && + Boolean($regionalConsoleVariables._APP_DOMAIN_TARGET_A) && + $regionalConsoleVariables._APP_DOMAIN_TARGET_A !== '127.0.0.1' + ); + const aaaaTabVisible = $derived( + !isCloud && + Boolean($regionalConsoleVariables._APP_DOMAIN_TARGET_AAAA) && + $regionalConsoleVariables._APP_DOMAIN_TARGET_AAAA !== '::1' + ); + + const caaText = $derived( + $regionalConsoleVariables._APP_DOMAIN_TARGET_CAA?.includes(' ') + ? $regionalConsoleVariables._APP_DOMAIN_TARGET_CAA + : `0 issue "${$regionalConsoleVariables._APP_DOMAIN_TARGET_CAA}"` + ); function setTarget() { switch (variant) { case 'cname': - return service === 'general' - ? $regionalConsoleVariables._APP_DOMAIN_TARGET_CNAME - : $regionalConsoleVariables._APP_DOMAIN_SITES; + if (service === 'sites') { + return $regionalConsoleVariables._APP_DOMAIN_SITES; + } else if (service === 'functions') { + return $regionalConsoleVariables._APP_DOMAIN_FUNCTIONS; + } else { + return $regionalConsoleVariables._APP_DOMAIN_TARGET_CNAME; + } case 'a': return $regionalConsoleVariables._APP_DOMAIN_TARGET_A; case 'aaaa': @@ -37,15 +75,25 @@ {domain} - {#if verified === true} + {#if ruleStatus === 'created'} + + {:else if ruleStatus === 'verifying'} + + {:else if ruleStatus === 'unverified'} + + {:else if verified === true} - {:else if verified === false} - {/if} - Add the following record on your DNS provider. Note that DNS changes may take time to - propagate fully. + Add the following {$regionalConsoleVariables._APP_DOMAIN_TARGET_CAA + ? 'records' + : 'record'} on your DNS provider. Note that DNS changes may take up to 48 hours to propagate + fully. @@ -62,17 +110,45 @@ + {#if $regionalConsoleVariables._APP_DOMAIN_TARGET_CAA} + + + + CAA + + + + @ + + + + + {/if} - {#if variant === 'cname'} - - If your domain uses CAA records, ensure certainly.com is authorized — otherwise, SSL - setup may fail. A list of all domain providers and their DNS setting is available here. - + {#if variant === 'cname' && !subdomain} + {#if isCloud} + + Since is an apex domain, + CNAME record is only supported by certain providers. If yours doesn't, please verify + using + nameservers instead. + + {:else if aTabVisible || aaaaTabVisible} + + Since is an apex domain, + CNAME record is only supported by certain providers. If yours doesn't, please verify + using + {#if aTabVisible} + A record + {#if aaaaTabVisible} + or AAAA record{/if} + {:else if aaaaTabVisible} + AAAA record + {/if} instead. + + {/if} {:else} A list of all domain providers and their DNS setting is available - + diff --git a/src/lib/components/index.ts b/src/lib/components/index.ts index df9a3ceeaf..6f8932f874 100644 --- a/src/lib/components/index.ts +++ b/src/lib/components/index.ts @@ -87,6 +87,7 @@ export { default as RegionEndpoint } from './regionEndpoint.svelte'; export { default as ExpirationInput } from './expirationInput.svelte'; export { default as EstimatedCard } from './estimatedCard.svelte'; export { default as SortButton, type SortDirection } from './sortButton.svelte'; +export * from './domains'; export { default as SendVerificationEmailModal } from './account/sendVerificationEmailModal.svelte'; export { default as MultiSelectionTable } from './multiSelectTable.svelte'; export * from './multiSelectTable.svelte'; diff --git a/src/lib/helpers/date.ts b/src/lib/helpers/date.ts index 2d56c1cb6a..78aa554948 100644 --- a/src/lib/helpers/date.ts +++ b/src/lib/helpers/date.ts @@ -206,6 +206,21 @@ export function timeFromNow(datetime: string): string { return dayjs().to(dayjs(datetime)); } +export function timeFromNowShort(datetime: string): string { + if (!datetime) { + return 'unknown time'; + } + if (!isValidDate(datetime)) { + return 'invalid date'; + } + + const timeStr = dayjs().to(dayjs(datetime)); + return timeStr + .replace('second', 'sec') // seconds > secs + .replace('minute', 'min') // minutes > mins + .replace('hour', 'hr'); // hours > hrs +} + export function hoursToDays(hours: number) { if (hours > 24) { return `${Math.floor(hours / 24)} days`; diff --git a/src/lib/helpers/tlds.ts b/src/lib/helpers/tlds.ts index 6de3c38887..84fabf2c39 100644 --- a/src/lib/helpers/tlds.ts +++ b/src/lib/helpers/tlds.ts @@ -4,7 +4,7 @@ import { parse } from 'tldts'; * Returns the apex/root domain from a full domain string. */ export function getApexDomain(domain: string): string | null { - return parse(domain).domain; + return parse(domain, { allowPrivateDomains: true }).domain; } /** @@ -13,8 +13,17 @@ export function getApexDomain(domain: string): string | null { export function isASubdomain(domain: string | null): boolean { if (!domain) return false; - const { domain: apex, subdomain } = parse(domain); + const { domain: apex, subdomain } = parse(domain, { allowPrivateDomains: true }); if (!apex) return false; return !!subdomain; } + +/** + * Returns the subdomain part from a full domain string. + */ +export function getSubdomain(domain: string): string { + if (!domain) return ''; + + return parse(domain, { allowPrivateDomains: true }).subdomain || ''; +} diff --git a/src/routes/(console)/organization-[organization]/domains/domain-[domain]/+page.svelte b/src/routes/(console)/organization-[organization]/domains/domain-[domain]/+page.svelte index d6ce25571b..b24836bad7 100644 --- a/src/routes/(console)/organization-[organization]/domains/domain-[domain]/+page.svelte +++ b/src/routes/(console)/organization-[organization]/domains/domain-[domain]/+page.svelte @@ -118,7 +118,7 @@ Navigate to your domain provider and update the nameservers to and . - Note that DNS changes may take time to propagate fully. + Note that DNS changes may take up to 48 hours to propagate fully. @@ -124,7 +148,7 @@
- {#if isSubDomain && !!$regionalConsoleVariables._APP_DOMAIN_TARGET_CNAME && $regionalConsoleVariables._APP_DOMAIN_TARGET_CNAME !== 'localhost'} + {#if !!$regionalConsoleVariables._APP_DOMAIN_FUNCTIONS && $regionalConsoleVariables._APP_DOMAIN_FUNCTIONS !== 'localhost'} (selectedTab = 'cname')} @@ -160,9 +184,20 @@
{#if selectedTab === 'nameserver'} - + {:else} - + (selectedTab = 'nameserver')} + onNavigateToA={() => (selectedTab = 'a')} + onNavigateToAAAA={() => (selectedTab = 'aaaa')} /> {/if} diff --git a/src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/add-domain/verify-[domain]/+page.ts b/src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/add-domain/verify-[domain]/+page.ts index b89c933306..4345a9f741 100644 --- a/src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/add-domain/verify-[domain]/+page.ts +++ b/src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/add-domain/verify-[domain]/+page.ts @@ -3,9 +3,14 @@ import { isCloud } from '$lib/system'; import { Dependencies } from '$lib/constants.js'; import { type Models, Query } from '@appwrite.io/console'; -export const load = async ({ depends, parent }) => { - const { organization } = await parent(); - depends(Dependencies.DOMAINS); +export const load = async ({ params, parent, depends, url }) => { + const { function: func, organization } = await parent(); + depends(Dependencies.FUNCTION_DOMAINS); + + const ruleId = url.searchParams.get('rule'); + if (!ruleId) { + throw new Error('Rule ID is required'); + } let domainsList: Models.DomainsList; if (isCloud) { @@ -14,7 +19,11 @@ export const load = async ({ depends, parent }) => { }); } + const proxyRule = await sdk.forProject(params.region, params.project).proxy.getRule({ ruleId }); + return { - domainsList + function: func, + domainsList, + proxyRule }; }; diff --git a/src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/retryDomainModal.svelte b/src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/retryDomainModal.svelte index 8ccd491e2b..d59bce63eb 100644 --- a/src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/retryDomainModal.svelte +++ b/src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/retryDomainModal.svelte @@ -6,9 +6,13 @@ import { invalidate } from '$app/navigation'; import { Submit, trackEvent, trackError } from '$lib/actions/analytics'; import { Dependencies } from '$lib/constants'; - import RecordsCard from './recordsCard.svelte'; import type { Models } from '@appwrite.io/console'; + import { Divider, Tabs } from '@appwrite.io/pink-svelte'; + import { isCloud } from '$lib/system'; import { page } from '$app/state'; + import NameserverTable from '$lib/components/domains/nameserverTable.svelte'; + import RecordTable from '$lib/components/domains/recordTable.svelte'; + import { regionalConsoleVariables } from '$routes/(console)/project-[region]-[project]/store'; let { show = $bindable(false), @@ -18,35 +22,117 @@ selectedProxyRule: Models.ProxyRule; } = $props(); + let selectedTab = $state<'cname' | 'nameserver' | 'a' | 'aaaa'>('nameserver'); + + $effect(() => { + if ($regionalConsoleVariables._APP_DOMAIN_FUNCTIONS) { + selectedTab = 'cname'; + } else if (!isCloud && $regionalConsoleVariables._APP_DOMAIN_TARGET_A) { + selectedTab = 'a'; + } else if (!isCloud && $regionalConsoleVariables._APP_DOMAIN_TARGET_AAAA) { + selectedTab = 'aaaa'; + } else { + selectedTab = 'nameserver'; + } + }); + + let verified = $state(false); + let retryError = $state(null); let error = $state(null); + + $effect(() => { + error = retryError || selectedProxyRule?.verificationLogs || null; + }); + async function retryProxyRule() { try { - await sdk + retryError = null; + const domain = await sdk .forProject(page.params.region, page.params.project) .proxy.updateRuleVerification({ ruleId: selectedProxyRule.$id }); + + verified = domain.status === 'verified'; await invalidate(Dependencies.FUNCTION_DOMAINS); - show = false; - addNotification({ - type: 'success', - message: `${selectedProxyRule.domain} has been verified` - }); + + if (verified) { + show = false; + addNotification({ + type: 'success', + message: `${selectedProxyRule.domain} has been verified` + }); + } else { + retryError = + 'Domain verification failed. Please check your domain settings or try again later'; + } trackEvent(Submit.DomainUpdateVerification); } catch (e) { - error = e.message; + retryError = + e.message ?? + 'Domain verification failed. Please check your domain settings or try again later'; trackError(e, Submit.DomainUpdateVerification); } } $effect(() => { if (!show) { - error = null; + retryError = null; } }); - {#if selectedProxyRule} - +
+ + {#if !!$regionalConsoleVariables._APP_DOMAIN_FUNCTIONS && $regionalConsoleVariables._APP_DOMAIN_FUNCTIONS !== 'localhost'} + (selectedTab = 'cname')} + active={selectedTab === 'cname'}> + CNAME + + {/if} + {#if isCloud} + (selectedTab = 'nameserver')} + active={selectedTab === 'nameserver'}> + Nameservers + + {/if} + {#if !isCloud && !!$regionalConsoleVariables._APP_DOMAIN_TARGET_A && $regionalConsoleVariables._APP_DOMAIN_TARGET_A !== '127.0.0.1'} + (selectedTab = 'a')} + active={selectedTab === 'a'}> + A + + {/if} + {#if !isCloud && !!$regionalConsoleVariables._APP_DOMAIN_TARGET_AAAA && $regionalConsoleVariables._APP_DOMAIN_TARGET_AAAA !== '::1'} + (selectedTab = 'aaaa')} + active={selectedTab === 'aaaa'}> + AAAA + + {/if} + + +
+ {#if selectedTab === 'nameserver'} + + {:else} + (selectedTab = 'nameserver')} + onNavigateToA={() => (selectedTab = 'a')} + onNavigateToAAAA={() => (selectedTab = 'aaaa')} /> {/if} diff --git a/src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/store.ts b/src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/store.ts index 902fb3e3e8..5f36c6bc17 100644 --- a/src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/store.ts +++ b/src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/store.ts @@ -7,7 +7,7 @@ export const columns = writable([ title: 'Domain', type: 'string', format: 'string', - width: { min: 200 } + width: { min: 300 } }, { @@ -15,5 +15,12 @@ export const columns = writable([ title: 'Target', type: 'string', width: { min: 120, max: 400 } + }, + + { + id: 'updated', + title: '', + type: 'string', + width: { min: 160, max: 180 } } ]); diff --git a/src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/table.svelte b/src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/table.svelte index 80f8663d44..c1ca0d71f4 100644 --- a/src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/table.svelte +++ b/src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/table.svelte @@ -3,10 +3,16 @@ import { Link } from '$lib/elements'; import { Button } from '$lib/elements/forms'; import type { Models } from '@appwrite.io/console'; - import { IconDotsHorizontal, IconRefresh, IconTrash } from '@appwrite.io/pink-icons-svelte'; + import { + IconDotsHorizontal, + IconRefresh, + IconTerminal, + IconTrash + } from '@appwrite.io/pink-icons-svelte'; import { ActionMenu, Badge, + Divider, Icon, Layout, Popover, @@ -15,9 +21,11 @@ } from '@appwrite.io/pink-svelte'; import DeleteDomainModal from './deleteDomainModal.svelte'; import RetryDomainModal from './retryDomainModal.svelte'; + import { ViewLogsModal } from '$lib/components'; import { columns } from './store'; import { regionalProtocol } from '$routes/(console)/project-[region]-[project]/store'; - import DnsRecordsAction from '$lib/components/domains/dnsRecordsAction.svelte'; + import { DnsRecordsAction } from '$lib/components'; + import { timeFromNowShort } from '$lib/helpers/date'; let { proxyRules, @@ -29,6 +37,7 @@ let showDelete = $state(false); let showRetry = $state(false); + let showLogs = $state(false); let selectedProxyRule: Models.ProxyRule = $state(null); const proxyTarget = (proxy: Models.ProxyRule) => { @@ -49,7 +58,7 @@ {/each} - {#each proxyRules.rules as proxyRule} + {#each proxyRules.rules as proxyRule (proxyRule.$id)} {#each $columns as column} @@ -57,24 +66,90 @@ {proxyRule.domain} - {#if proxyRule.status === 'verifying'} - - {:else if proxyRule.status !== 'verified'} - + {#if proxyRule.status === 'created'} + + + { + e.preventDefault(); + selectedProxyRule = proxyRule; + showRetry = true; + }}> + Retry + + + {:else if proxyRule.status === 'verifying'} + + + {#if proxyRule.logs && proxyRule.logs.length > 0} + { + e.preventDefault(); + selectedProxyRule = proxyRule; + showLogs = true; + }}> + View logs + + {/if} + + {:else if proxyRule.status === 'unverified'} + + + {#if proxyRule.logs && proxyRule.logs.length > 0} + { + e.preventDefault(); + selectedProxyRule = proxyRule; + showLogs = true; + }}> + View logs + + {/if} + {/if} {:else if column.id === 'target'} {proxyTarget(proxyRule)} + {:else if column.id === 'updated'} + + {#if proxyRule.status !== 'verified'} + + {#if proxyRule.status === 'created'} + Checked {timeFromNowShort(proxyRule.$updatedAt)} + {:else if proxyRule.status === 'verifying'} + Updated {timeFromNowShort(proxyRule.$updatedAt)} + {:else if proxyRule.status === 'unverified'} + Failed {timeFromNowShort(proxyRule.$updatedAt)} + {/if} + + {/if} + {/if} {/each} @@ -93,6 +168,17 @@ + {#if proxyRule.logs && proxyRule.logs.length > 0} + { + selectedProxyRule = proxyRule; + showLogs = true; + toggle(e); + }}> + View logs + + {/if} {#if proxyRule.status !== 'verified' && proxyRule.status !== 'verifying'} {/if} + {#if proxyRule.logs && proxyRule.logs.length > 0} +
+ +
+ {/if} {/if} + +{#if showLogs} + +{/if} + + diff --git a/src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/+page.svelte b/src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/+page.svelte index 90d5a21595..634f74a224 100644 --- a/src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/+page.svelte +++ b/src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/+page.svelte @@ -16,8 +16,6 @@ const routeBase = `${base}/project-${page.params.region}-${page.params.project}/settings/domains`; - let { data } = $props(); - let formComponent: Form; let isSubmitting = $state(writable(false)); let domainName = $state(''); @@ -30,25 +28,20 @@ async function addDomain() { const apexDomain = getApexDomain(domainName); - let domain = data.domains?.domains.find((d: Models.Domain) => d.domain === apexDomain); + let domain: Models.Domain; - if (apexDomain && !domain && isCloud) { - try { - domain = await sdk.forConsole.domains.create({ + if (isCloud && apexDomain) { + sdk.forConsole.domains + .create({ teamId: $project.teamId, domain: apexDomain + }) + .then((createdDomain) => { + domain = createdDomain; + }) + .catch(() => { + // Empty as domain creation error needs to be silent }); - } catch (error) { - // apex might already be added on organization level, skip. - const alreadyAdded = error?.type === 'domain_already_exists'; - if (!alreadyAdded) { - addNotification({ - type: 'error', - message: error.message - }); - return; - } - } } try { @@ -58,18 +51,13 @@ if (rule?.status === 'verified') { await goto(routeBase); await invalidate(Dependencies.DOMAINS); - } else { - let redirect = `${routeBase}/add-domain/verify-${domainName}?rule=${rule.$id}`; - - if (isCloud) { - /** - * Domains are only on cloud! - * Self-hosted instances have rules. - */ - redirect += `&domain=${domain.$id}`; + if (isCloud && domain) { + sdk.forConsole.domains.updateNameservers({ domainId: domain.$id }).catch(() => { + // Empty as domain update error needs to be silent + }); } - - await goto(redirect); + } else { + await goto(`${routeBase}/add-domain/verify-${domainName}?rule=${rule.$id}`); await invalidate(Dependencies.DOMAINS); } } catch (error) { diff --git a/src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/verify-[domain]/+page.svelte b/src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/verify-[domain]/+page.svelte index a6c23790f5..3695f3a4de 100644 --- a/src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/verify-[domain]/+page.svelte +++ b/src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/verify-[domain]/+page.svelte @@ -12,6 +12,7 @@ import { Button, Form } from '$lib/elements/forms'; import { sdk } from '$lib/stores/sdk'; import { organization } from '$lib/stores/organization'; + import type { Models } from '@appwrite.io/console'; import { addNotification } from '$lib/stores/notifications'; import { goto, invalidate } from '$app/navigation'; import { Dependencies } from '$lib/constants'; @@ -20,7 +21,7 @@ import Wizard from '$lib/layout/wizard.svelte'; import { base } from '$app/paths'; import { writable } from 'svelte/store'; - import { isASubdomain } from '$lib/helpers/tlds'; + import { getApexDomain } from '$lib/helpers/tlds'; import NameserverTable from '$lib/components/domains/nameserverTable.svelte'; import RecordTable from '$lib/components/domains/recordTable.svelte'; import { regionalConsoleVariables } from '$routes/(console)/project-[region]-[project]/store'; @@ -28,13 +29,11 @@ let { data } = $props(); const ruleId = page.url.searchParams.get('rule'); - const domainId = page.url.searchParams.get('domain'); - const isSubDomain = $derived.by(() => isASubdomain(page.params.domain)); let selectedTab = $state<'cname' | 'nameserver' | 'a' | 'aaaa'>('nameserver'); $effect(() => { - if ($regionalConsoleVariables._APP_DOMAIN_TARGET_CNAME && isSubDomain) { + if ($regionalConsoleVariables._APP_DOMAIN_TARGET_CNAME) { selectedTab = 'cname'; } else if (!isCloud && $regionalConsoleVariables._APP_DOMAIN_TARGET_A) { selectedTab = 'a'; @@ -50,30 +49,54 @@ const isSubmitting = writable(false); async function verify() { - const isNewDomain = - data.domainsList.domains.find((rule) => rule.domain === page.params.domain) === - undefined; try { - if (selectedTab !== 'nameserver') { - const ruleData = await sdk - .forProject(page.params.region, page.params.project) - .proxy.updateRuleVerification({ ruleId }); - verified = ruleData.status === 'verified'; - } else if (isNewDomain && isCloud) { - const domainData = await sdk.forConsole.domains.create({ - teamId: $organization.$id, - domain: page.params.domain - }); - verified = domainData.nameservers.toLowerCase() === 'appwrite'; - } else if (!isNewDomain && isCloud) { - const domain = await sdk.forConsole.domains.updateNameservers({ - domainId - }); - verified = domain.nameservers.toLowerCase() === 'appwrite'; - if (!verified) - throw new Error( - 'Domain verification failed. Please check your domain settings or try again later' + if (isCloud) { + const apexDomain = getApexDomain(data.proxyRule.domain); + console.log('apexDomain', apexDomain); + if (apexDomain) { + sdk.forConsole.domains + .create({ + teamId: $organization.$id, + domain: apexDomain + }) + .then((domainData) => { + if (domainData.nameservers.toLowerCase() === 'appwrite') { + verified = true; + } + }) + .catch(() => { + // Empty as domain creation error needs to be silent + }); + + const domain = data.domainsList.domains.find( + (d: Models.Domain) => d.domain === apexDomain ); + if (domain) { + sdk.forConsole.domains + .updateNameservers({ + domainId: domain.$id + }) + .then((output) => { + if (output.nameservers.toLowerCase() === 'appwrite') { + verified = true; + } + }) + .catch(() => { + // Empty as domain update error needs to be silent + }); + } + } + } + + const ruleData = await sdk + .forProject(page.params.region, page.params.project) + .proxy.updateRuleVerification({ ruleId }); + + verified = ruleData.status === 'verified'; + if (!verified) { + throw new Error( + 'Domain verification failed. Please check your domain settings or try again later' + ); } addNotification({ @@ -98,7 +121,7 @@ .forProject(page.params.region, page.params.project) .proxy.deleteRule({ ruleId }); } - await goto(`${routeBase}/add-domain?domain=${page.params.domain}`); + await goto(`${routeBase}/add-domain?domain=${data.proxyRule.domain}`); } @@ -115,7 +138,7 @@ - {page.params.domain} + {data.proxyRule.domain}
@@ -126,7 +149,7 @@
- {#if isSubDomain && !!$regionalConsoleVariables._APP_DOMAIN_TARGET_CNAME && $regionalConsoleVariables._APP_DOMAIN_TARGET_CNAME !== 'localhost'} + {#if !!$regionalConsoleVariables._APP_DOMAIN_TARGET_CNAME && $regionalConsoleVariables._APP_DOMAIN_TARGET_CNAME !== 'localhost'} (selectedTab = 'cname')} @@ -162,9 +185,19 @@
{#if selectedTab === 'nameserver'} - + {:else} - + (selectedTab = 'nameserver')} + onNavigateToA={() => (selectedTab = 'a')} + onNavigateToAAAA={() => (selectedTab = 'aaaa')} /> {/if} diff --git a/src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/verify-[domain]/+page.ts b/src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/verify-[domain]/+page.ts index b89c933306..a5c8d1ad14 100644 --- a/src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/verify-[domain]/+page.ts +++ b/src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/verify-[domain]/+page.ts @@ -3,10 +3,15 @@ import { isCloud } from '$lib/system'; import { Dependencies } from '$lib/constants.js'; import { type Models, Query } from '@appwrite.io/console'; -export const load = async ({ depends, parent }) => { - const { organization } = await parent(); +export const load = async ({ params, parent, depends, url }) => { + const { project, organization } = await parent(); depends(Dependencies.DOMAINS); + const ruleId = url.searchParams.get('rule'); + if (!ruleId) { + throw new Error('Rule ID is required'); + } + let domainsList: Models.DomainsList; if (isCloud) { domainsList = await sdk.forConsole.domains.list({ @@ -14,7 +19,11 @@ export const load = async ({ depends, parent }) => { }); } + const proxyRule = await sdk.forProject(params.region, params.project).proxy.getRule({ ruleId }); + return { - domainsList + project, + domainsList, + proxyRule }; }; diff --git a/src/routes/(console)/project-[region]-[project]/settings/domains/retryDomainModal.svelte b/src/routes/(console)/project-[region]-[project]/settings/domains/retryDomainModal.svelte index 844a2c94be..772fef3827 100644 --- a/src/routes/(console)/project-[region]-[project]/settings/domains/retryDomainModal.svelte +++ b/src/routes/(console)/project-[region]-[project]/settings/domains/retryDomainModal.svelte @@ -7,8 +7,12 @@ import { Submit, trackEvent, trackError } from '$lib/actions/analytics'; import { Dependencies } from '$lib/constants'; import type { Models } from '@appwrite.io/console'; - import CnameTable from '$lib/components/domains/cnameTable.svelte'; + import { Divider, Tabs } from '@appwrite.io/pink-svelte'; + import { isCloud } from '$lib/system'; import { page } from '$app/state'; + import NameserverTable from '$lib/components/domains/nameserverTable.svelte'; + import RecordTable from '$lib/components/domains/recordTable.svelte'; + import { regionalConsoleVariables } from '$routes/(console)/project-[region]-[project]/store'; let { show = $bindable(), @@ -18,37 +22,117 @@ selectedDomain: Models.ProxyRule; } = $props(); + let selectedTab = $state<'cname' | 'nameserver' | 'a' | 'aaaa'>('nameserver'); + + $effect(() => { + if ($regionalConsoleVariables._APP_DOMAIN_TARGET_CNAME) { + selectedTab = 'cname'; + } else if (!isCloud && $regionalConsoleVariables._APP_DOMAIN_TARGET_A) { + selectedTab = 'a'; + } else if (!isCloud && $regionalConsoleVariables._APP_DOMAIN_TARGET_AAAA) { + selectedTab = 'aaaa'; + } else { + selectedTab = 'nameserver'; + } + }); + + let verified = $state(false); + let retryError = $state(null); let error = $state(null); + + $effect(() => { + error = retryError || selectedDomain?.verificationLogs || null; + }); + async function retryDomain() { try { - await sdk + retryError = null; + const domain = await sdk .forProject(page.params.region, page.params.project) .proxy.updateRuleVerification({ ruleId: selectedDomain.$id }); + + verified = domain.status === 'verified'; await invalidate(Dependencies.DOMAINS); - show = false; - addNotification({ - type: 'success', - message: `${selectedDomain.domain} has been verified` - }); + + if (verified) { + show = false; + addNotification({ + type: 'success', + message: `${selectedDomain.domain} has been verified` + }); + } else { + retryError = + 'Domain verification failed. Please check your domain settings or try again later'; + } trackEvent(Submit.DomainUpdateVerification); } catch (e) { - error = e.message; + retryError = + e.message ?? + 'Domain verification failed. Please check your domain settings or try again later'; trackError(e, Submit.DomainUpdateVerification); } } $effect(() => { if (!show) { - error = null; + retryError = null; } }); - {#if selectedDomain} - + + {#if !!$regionalConsoleVariables._APP_DOMAIN_TARGET_CNAME && $regionalConsoleVariables._APP_DOMAIN_TARGET_CNAME !== 'localhost'} + (selectedTab = 'cname')} + active={selectedTab === 'cname'}> + CNAME + + {/if} + {#if isCloud} + (selectedTab = 'nameserver')} + active={selectedTab === 'nameserver'}> + Nameservers + + {/if} + {#if !isCloud && !!$regionalConsoleVariables._APP_DOMAIN_TARGET_A && $regionalConsoleVariables._APP_DOMAIN_TARGET_A !== '127.0.0.1'} + (selectedTab = 'a')} + active={selectedTab === 'a'}> + A + + {/if} + {#if !isCloud && !!$regionalConsoleVariables._APP_DOMAIN_TARGET_AAAA && $regionalConsoleVariables._APP_DOMAIN_TARGET_AAAA !== '::1'} + (selectedTab = 'aaaa')} + active={selectedTab === 'aaaa'}> + AAAA + + {/if} + + + + {#if selectedTab === 'nameserver'} + + {:else} + + ruleStatus={selectedDomain.status} + onNavigateToNameservers={() => (selectedTab = 'nameserver')} + onNavigateToA={() => (selectedTab = 'a')} + onNavigateToAAAA={() => (selectedTab = 'aaaa')} /> {/if} diff --git a/src/routes/(console)/project-[region]-[project]/settings/domains/table.svelte b/src/routes/(console)/project-[region]-[project]/settings/domains/table.svelte index e28db33a94..4471fcbeb8 100644 --- a/src/routes/(console)/project-[region]-[project]/settings/domains/table.svelte +++ b/src/routes/(console)/project-[region]-[project]/settings/domains/table.svelte @@ -3,10 +3,16 @@ import { Link } from '$lib/elements'; import { Button } from '$lib/elements/forms'; import type { Models } from '@appwrite.io/console'; - import { IconDotsHorizontal, IconRefresh, IconTrash } from '@appwrite.io/pink-icons-svelte'; + import { + IconDotsHorizontal, + IconRefresh, + IconTerminal, + IconTrash + } from '@appwrite.io/pink-icons-svelte'; import { ActionMenu, Badge, + Divider, Icon, Layout, Popover, @@ -15,8 +21,10 @@ } from '@appwrite.io/pink-svelte'; import DeleteDomainModal from './deleteDomainModal.svelte'; import RetryDomainModal from './retryDomainModal.svelte'; + import { ViewLogsModal } from '$lib/components'; import { regionalProtocol } from '../../store'; - import DnsRecordsAction from '$lib/components/domains/dnsRecordsAction.svelte'; + import { DnsRecordsAction } from '$lib/components'; + import { timeFromNowShort } from '$lib/helpers/date'; let { domains, @@ -28,6 +36,7 @@ let showDelete = $state(false); let showRetry = $state(false); + let showLogs = $state(false); let selectedDomain: Models.ProxyRule = $state(null); const columns = [ @@ -36,7 +45,13 @@ title: 'Domain', type: 'string', format: 'string', - width: { min: 200, max: 550 } + width: { min: 300, max: 550 } + }, + { + id: 'updated', + title: '', + type: 'string', + width: { min: 160, max: 180 } } ]; @@ -58,20 +73,86 @@ {domain.domain} - {#if domain.status === 'verifying'} - - {:else if domain.status !== 'verified'} - + {#if domain.status === 'created'} + + + { + e.preventDefault(); + selectedDomain = domain; + showRetry = true; + }}> + Retry + + + {:else if domain.status === 'verifying'} + + + {#if domain.logs && domain.logs.length > 0} + { + e.preventDefault(); + selectedDomain = domain; + showLogs = true; + }}> + View logs + + {/if} + + {:else if domain.status === 'unverified'} + + + {#if domain.logs && domain.logs.length > 0} + { + e.preventDefault(); + selectedDomain = domain; + showLogs = true; + }}> + View logs + + {/if} + + {/if} + + {:else if column.id === 'updated'} + + {#if domain.status !== 'verified'} + + {#if domain.status === 'created'} + Checked {timeFromNowShort(domain.$updatedAt)} + {:else if domain.status === 'verifying'} + Updated {timeFromNowShort(domain.$updatedAt)} + {:else if domain.status === 'unverified'} + Failed {timeFromNowShort(domain.$updatedAt)} + {/if} + {/if} {/if} @@ -92,6 +173,17 @@ + {#if domain.logs && domain.logs.length > 0} + { + selectedDomain = domain; + showLogs = true; + toggle(e); + }}> + View logs + + {/if} {#if domain.status !== 'verified' && domain.status !== 'verifying'} {/if} + {#if domain.logs && domain.logs.length > 0} +
+ +
+ {/if} {/if} + +{#if showLogs} + +{/if} + + diff --git a/src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/add-domain/+page.svelte b/src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/add-domain/+page.svelte index f0b6df34a3..07430eb9d8 100644 --- a/src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/add-domain/+page.svelte +++ b/src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/add-domain/+page.svelte @@ -57,27 +57,21 @@ async function addDomain() { const apexDomain = getApexDomain(domainName); - let domain = data.domains?.domains.find((d: Models.Domain) => d.domain === apexDomain); - + let domain: Models.Domain; const isSiteDomain = domainName.endsWith($regionalConsoleVariables._APP_DOMAIN_SITES); - if (isCloud && apexDomain && !domain && !isSiteDomain) { - try { - domain = await sdk.forConsole.domains.create({ + if (isCloud && apexDomain && !isSiteDomain) { + sdk.forConsole.domains + .create({ teamId: $project.teamId, domain: apexDomain + }) + .then((createdDomain) => { + domain = createdDomain; + }) + .catch(() => { + // Empty as domain creation error needs to be silent }); - } catch (error) { - // apex might already be added on organization level, skip. - const alreadyAdded = error?.type === 'domain_already_exists'; - if (!alreadyAdded) { - addNotification({ - type: 'error', - message: error.message - }); - return; - } - } } try { @@ -111,6 +105,11 @@ if (rule?.status === 'verified') { await goto(routeBase); await invalidate(Dependencies.SITES_DOMAINS); + if (isCloud && domain) { + sdk.forConsole.domains.updateNameservers({ domainId: domain.$id }).catch(() => { + // Empty as domain update error needs to be silent + }); + } } else { await goto(`${routeBase}/add-domain/verify-${domainName}?rule=${rule.$id}`); await invalidate(Dependencies.SITES_DOMAINS); diff --git a/src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/add-domain/verify-[domain]/+page.svelte b/src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/add-domain/verify-[domain]/+page.svelte index 8422d783a0..dad247b10f 100644 --- a/src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/add-domain/verify-[domain]/+page.svelte +++ b/src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/add-domain/verify-[domain]/+page.svelte @@ -12,6 +12,7 @@ import { Button, Form } from '$lib/elements/forms'; import { sdk } from '$lib/stores/sdk'; import { organization } from '$lib/stores/organization'; + import type { Models } from '@appwrite.io/console'; import { addNotification } from '$lib/stores/notifications'; import { goto, invalidate } from '$app/navigation'; import { Dependencies } from '$lib/constants'; @@ -20,7 +21,7 @@ import Wizard from '$lib/layout/wizard.svelte'; import { base } from '$app/paths'; import { writable } from 'svelte/store'; - import { isASubdomain } from '$lib/helpers/tlds'; + import { getApexDomain } from '$lib/helpers/tlds'; import RecordTable from '$lib/components/domains/recordTable.svelte'; import NameserverTable from '$lib/components/domains/nameserverTable.svelte'; import { regionalConsoleVariables } from '$routes/(console)/project-[region]-[project]/store'; @@ -28,12 +29,11 @@ let { data } = $props(); const ruleId = page.url.searchParams.get('rule'); - const isSubDomain = $derived.by(() => isASubdomain(page.params.domain)); let selectedTab = $state<'cname' | 'nameserver' | 'a' | 'aaaa'>('nameserver'); $effect(() => { - if ($regionalConsoleVariables._APP_DOMAIN_TARGET_CNAME && isSubDomain) { + if ($regionalConsoleVariables._APP_DOMAIN_SITES) { selectedTab = 'cname'; } else if (!isCloud && $regionalConsoleVariables._APP_DOMAIN_TARGET_A) { selectedTab = 'a'; @@ -50,23 +50,50 @@ let isSubmitting = $state(writable(false)); async function verify() { - const isNewDomain = - data.domainsList.domains.findIndex((rule) => rule.domain === page.params.domain) === -1; try { - if (selectedTab !== 'nameserver') { - const ruleData = await sdk - .forProject(page.params.region, page.params.project) - .proxy.updateRuleVerification({ ruleId }); - verified = ruleData.status === 'verified'; - throw new Error( - 'Domain verification failed. Please check your domain settings or try again later' - ); - } else if (isNewDomain && isCloud) { - const domainData = await sdk.forConsole.domains.create({ - teamId: $organization.$id, - domain: page.params.domain - }); - verified = domainData.nameservers.toLowerCase() === 'appwrite'; + if (isCloud) { + const apexDomain = getApexDomain(data.proxyRule.domain); + if (apexDomain) { + sdk.forConsole.domains + .create({ + teamId: $organization.$id, + domain: apexDomain + }) + .then((domainData) => { + if (domainData.nameservers.toLowerCase() === 'appwrite') { + verified = true; + } + }) + .catch(() => { + // Empty as domain creation error needs to be silent + }); + + const domain = data.domainsList.domains.find( + (d: Models.Domain) => d.domain === apexDomain + ); + if (domain) { + sdk.forConsole.domains + .updateNameservers({ + domainId: domain.$id + }) + .then((output) => { + if (output.nameservers.toLowerCase() === 'appwrite') { + verified = true; + } + }) + .catch(() => { + // Empty as domain update error needs to be silent + }); + } + } + } + + const ruleData = await sdk + .forProject(page.params.region, page.params.project) + .proxy.updateRuleVerification({ ruleId }); + + verified = ruleData.status === 'verified'; + if (!verified) { throw new Error( 'Domain verification failed. Please check your domain settings or try again later' ); @@ -95,7 +122,7 @@ .forProject(page.params.region, page.params.project) .proxy.deleteRule({ ruleId }); } - await goto(`${routeBase}/add-domain?domain=${page.params.domain}`); + await goto(`${routeBase}/add-domain?domain=${data.proxyRule.domain}`); } @@ -112,7 +139,7 @@ - {page.params.domain} + {data.proxyRule.domain}
@@ -123,7 +150,7 @@
- {#if isSubDomain && !!$regionalConsoleVariables._APP_DOMAIN_TARGET_CNAME && $regionalConsoleVariables._APP_DOMAIN_TARGET_CNAME !== 'localhost'} + {#if !!$regionalConsoleVariables._APP_DOMAIN_SITES && $regionalConsoleVariables._APP_DOMAIN_SITES !== 'localhost'} (selectedTab = 'cname')} @@ -159,13 +186,20 @@
{#if selectedTab === 'nameserver'} - + {:else} + domain={data.proxyRule.domain} + ruleStatus={data.proxyRule.status} + onNavigateToNameservers={() => (selectedTab = 'nameserver')} + onNavigateToA={() => (selectedTab = 'a')} + onNavigateToAAAA={() => (selectedTab = 'aaaa')} /> {/if} diff --git a/src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/add-domain/verify-[domain]/+page.ts b/src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/add-domain/verify-[domain]/+page.ts index 570e1b27a2..d16a243637 100644 --- a/src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/add-domain/verify-[domain]/+page.ts +++ b/src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/add-domain/verify-[domain]/+page.ts @@ -3,10 +3,15 @@ import { isCloud } from '$lib/system'; import { Dependencies } from '$lib/constants.js'; import { type Models, Query } from '@appwrite.io/console'; -export const load = async ({ parent, depends }) => { +export const load = async ({ params, parent, depends, url }) => { const { site, organization } = await parent(); depends(Dependencies.SITES_DOMAINS); + const ruleId = url.searchParams.get('rule'); + if (!ruleId) { + throw new Error('Rule ID is required'); + } + let domainsList: Models.DomainsList; if (isCloud) { domainsList = await sdk.forConsole.domains.list({ @@ -14,8 +19,11 @@ export const load = async ({ parent, depends }) => { }); } + const proxyRule = await sdk.forProject(params.region, params.project).proxy.getRule({ ruleId }); + return { site, - domainsList + domainsList, + proxyRule }; }; diff --git a/src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/retryDomainModal.svelte b/src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/retryDomainModal.svelte index 949d8079c9..a148830f02 100644 --- a/src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/retryDomainModal.svelte +++ b/src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/retryDomainModal.svelte @@ -10,7 +10,6 @@ import { Divider, Tabs } from '@appwrite.io/pink-svelte'; import { isCloud } from '$lib/system'; import { page } from '$app/state'; - import { isASubdomain } from '$lib/helpers/tlds'; import NameserverTable from '$lib/components/domains/nameserverTable.svelte'; import RecordTable from '$lib/components/domains/recordTable.svelte'; import { regionalConsoleVariables } from '$routes/(console)/project-[region]-[project]/store'; @@ -23,12 +22,10 @@ selectedProxyRule: Models.ProxyRule; } = $props(); - const isSubDomain = $derived.by(() => isASubdomain(selectedProxyRule?.domain)); - let selectedTab = $state<'cname' | 'nameserver' | 'a' | 'aaaa'>('nameserver'); $effect(() => { - if ($regionalConsoleVariables._APP_DOMAIN_TARGET_CNAME && isSubDomain) { + if ($regionalConsoleVariables._APP_DOMAIN_SITES) { selectedTab = 'cname'; } else if (!isCloud && $regionalConsoleVariables._APP_DOMAIN_TARGET_A) { selectedTab = 'a'; @@ -39,26 +36,37 @@ } }); - let error = $state(null); let verified = $state(false); + let retryError = $state(null); + let error = $state(null); + + $effect(() => { + error = retryError || selectedProxyRule?.verificationLogs || null; + }); async function retryDomain() { try { + retryError = null; const domain = await sdk .forProject(page.params.region, page.params.project) .proxy.updateRuleVerification({ ruleId: selectedProxyRule.$id }); - show = false; verified = domain.status === 'verified'; await invalidate(Dependencies.SITES_DOMAINS); - addNotification({ - type: 'success', - message: `${selectedProxyRule.domain} has been verified` - }); + if (verified) { + show = false; + addNotification({ + type: 'success', + message: `${selectedProxyRule.domain} has been verified` + }); + } else { + retryError = + 'Domain verification failed. Please check your domain settings or try again later'; + } trackEvent(Submit.DomainUpdateVerification); } catch (e) { - error = + retryError = e.message ?? 'Domain verification failed. Please check your domain settings or try again later'; trackError(e, Submit.DomainUpdateVerification); @@ -67,7 +75,7 @@ $effect(() => { if (!show) { - error = null; + retryError = null; } }); @@ -75,7 +83,7 @@
- {#if isSubDomain && !!$regionalConsoleVariables._APP_DOMAIN_TARGET_CNAME && $regionalConsoleVariables._APP_DOMAIN_TARGET_CNAME !== 'localhost'} + {#if !!$regionalConsoleVariables._APP_DOMAIN_SITES && $regionalConsoleVariables._APP_DOMAIN_SITES !== 'localhost'} (selectedTab = 'cname')} @@ -111,13 +119,20 @@
{#if selectedTab === 'nameserver'} - + {:else} + domain={selectedProxyRule.domain} + ruleStatus={selectedProxyRule.status} + onNavigateToNameservers={() => (selectedTab = 'nameserver')} + onNavigateToA={() => (selectedTab = 'a')} + onNavigateToAAAA={() => (selectedTab = 'aaaa')} /> {/if} diff --git a/src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/store.ts b/src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/store.ts index 902fb3e3e8..5f36c6bc17 100644 --- a/src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/store.ts +++ b/src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/store.ts @@ -7,7 +7,7 @@ export const columns = writable([ title: 'Domain', type: 'string', format: 'string', - width: { min: 200 } + width: { min: 300 } }, { @@ -15,5 +15,12 @@ export const columns = writable([ title: 'Target', type: 'string', width: { min: 120, max: 400 } + }, + + { + id: 'updated', + title: '', + type: 'string', + width: { min: 160, max: 180 } } ]); diff --git a/src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/table.svelte b/src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/table.svelte index b5b755480d..9c78f780eb 100644 --- a/src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/table.svelte +++ b/src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/table.svelte @@ -21,10 +21,11 @@ } from '@appwrite.io/pink-svelte'; import DeleteDomainModal from './deleteDomainModal.svelte'; import RetryDomainModal from './retryDomainModal.svelte'; - import ViewLogsModal from './viewLogsModal.svelte'; + import { ViewLogsModal } from '$lib/components'; import { columns } from './store'; import { regionalProtocol } from '$routes/(console)/project-[region]-[project]/store'; - import DnsRecordsAction from '$lib/components/domains/dnsRecordsAction.svelte'; + import { DnsRecordsAction } from '$lib/components'; + import { timeFromNowShort } from '$lib/helpers/date'; let { proxyRules, @@ -65,25 +66,91 @@ {rule.domain} - {#if rule.status === 'verifying'} - - {:else if rule.status !== 'verified'} - + {#if rule.status === 'created'} + + + { + e.preventDefault(); + selectedProxyRule = rule; + showRetry = true; + }}> + Retry + + + {:else if rule.status === 'verifying'} + + + {#if rule.logs && rule.logs.length > 0} + { + e.preventDefault(); + selectedProxyRule = rule; + showLogs = true; + }}> + View logs + + {/if} + + {:else if rule.status === 'unverified'} + + + {#if rule.logs && rule.logs.length > 0} + { + e.preventDefault(); + selectedProxyRule = rule; + showLogs = true; + }}> + View logs + + {/if} + {/if} {:else if column.id === 'target'} {proxyTarget(rule)} + {:else if column.id === 'updated'} + + {#if rule.status !== 'verified'} + + {#if rule.status === 'created'} + Checked {timeFromNowShort(rule.$updatedAt)} + {:else if rule.status === 'verifying'} + Updated {timeFromNowShort(rule.$updatedAt)} + {:else if rule.status === 'unverified'} + Failed {timeFromNowShort(rule.$updatedAt)} + {/if} + + {/if} + {/if} {/each} @@ -102,7 +169,7 @@ - {#if rule.logs && (rule.status === 'unverified' || rule.status === 'verifying')} + {#if rule.logs && rule.logs.length > 0} { @@ -125,7 +192,7 @@ {/if} - {#if rule.logs && (rule.status === 'unverified' || rule.status === 'verifying')} + {#if rule.logs && rule.logs.length > 0}