Skip to content

Commit 1aefd80

Browse files
committed
update: manage domains differently on studio.
1 parent 023a670 commit 1aefd80

File tree

10 files changed

+550
-145
lines changed

10 files changed

+550
-145
lines changed

pnpm-lock.yaml

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/lib/stores/domains.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
1-
import { writable } from 'svelte/store';
21
import { StatusCode } from '@appwrite.io/console';
32

4-
export const hideTypes = writable<boolean>(false);
5-
63
export const statusCodeOptions = [
74
{
85
label: '301 Moved permanently',
Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
<script lang="ts">
2+
import { base } from '$app/paths';
3+
import { page } from '$app/state';
4+
import { Button, Form, InputDomain, InputSelect, InputURL } from '$lib/elements/forms';
5+
import { Wizard } from '$lib/layout';
6+
import { addNotification } from '$lib/stores/notifications';
7+
import { RuleTrigger, RuleType, sdk } from '$lib/stores/sdk';
8+
import {
9+
Fieldset,
10+
Layout,
11+
Tooltip,
12+
Icon,
13+
Input,
14+
Alert,
15+
Skeleton
16+
} from '@appwrite.io/pink-svelte';
17+
import { afterNavigate, goto, invalidate } from '$app/navigation';
18+
import { Dependencies } from '$lib/constants';
19+
import { LabelCard } from '$lib/components';
20+
import { sortBranches } from '$lib/stores/vcs';
21+
import { IconInfo } from '@appwrite.io/pink-icons-svelte';
22+
import {
23+
Adapter,
24+
BuildRuntime,
25+
Framework,
26+
type Models,
27+
ProxyResourceType,
28+
Query,
29+
StatusCode
30+
} from '@appwrite.io/console';
31+
import { statusCodeOptions } from '$lib/stores/domains';
32+
import { writable } from 'svelte/store';
33+
import { onMount } from 'svelte';
34+
import {
35+
project,
36+
regionalConsoleVariables
37+
} from '$routes/(console)/project-[region]-[project]/store';
38+
import { isCloud } from '$lib/system';
39+
import { getApexDomain } from '$lib/helpers/tlds';
40+
import { organization } from '$lib/stores/organization';
41+
42+
let {
43+
siteId,
44+
onDomainAdded,
45+
show = $bindable(false)
46+
}: {
47+
show: boolean;
48+
siteId: string;
49+
onDomainAdded: (rule: string, domain: Models.Domain, verified: boolean) => void;
50+
} = $props();
51+
52+
let formComponent: Form;
53+
let domainName = $state('');
54+
55+
let rules = $state<Models.ProxyRuleList | null>(null);
56+
let domains = $state<Models.DomainsList | null>(null);
57+
58+
let loading = $state(true);
59+
let isSubmitting = $state(writable(false));
60+
61+
async function loadRules() {
62+
try {
63+
rules = await sdk.forProject(page.params.region, page.params.project).proxy.listRules({
64+
queries: [
65+
Query.equal('type', RuleType.DEPLOYMENT),
66+
Query.equal('trigger', RuleTrigger.MANUAL)
67+
]
68+
});
69+
} catch (error) {
70+
show = false;
71+
addNotification({
72+
type: 'error',
73+
message: error.message
74+
});
75+
}
76+
}
77+
78+
async function loadDomains() {
79+
try {
80+
domains = await sdk.forConsole.domains.list({
81+
queries: [Query.equal('teamId', $organization.$id)]
82+
});
83+
} catch (error) {
84+
show = false;
85+
addNotification({
86+
type: 'error',
87+
message: error.message
88+
});
89+
}
90+
}
91+
92+
async function addDomain() {
93+
const apexDomain = getApexDomain(domainName);
94+
let domain = domains?.domains.find((d: Models.Domain) => d.domain === apexDomain);
95+
96+
const isSiteDomain = domainName.endsWith($regionalConsoleVariables._APP_DOMAIN_SITES);
97+
98+
if (isCloud && apexDomain && !domain && !isSiteDomain) {
99+
try {
100+
domain = await sdk.forConsole.domains.create({
101+
teamId: $project.teamId,
102+
domain: apexDomain
103+
});
104+
} catch (error) {
105+
// apex might already be added on organization level, skip.
106+
const alreadyAdded = error?.type === 'domain_already_exists';
107+
if (!alreadyAdded) {
108+
addNotification({
109+
type: 'error',
110+
message: error.message
111+
});
112+
return;
113+
}
114+
}
115+
}
116+
117+
try {
118+
const rule = await sdk
119+
.forProject(page.params.region, page.params.project)
120+
.proxy.createSiteRule({
121+
domain: domainName,
122+
siteId
123+
});
124+
125+
const verified = rule?.status === 'verified';
126+
onDomainAdded(rule.$id, domain, verified);
127+
if (verified) await invalidate(Dependencies.SITES_DOMAINS);
128+
129+
show = false;
130+
} catch (error) {
131+
addNotification({
132+
type: 'error',
133+
message: error.message
134+
});
135+
}
136+
}
137+
138+
$effect(() => {
139+
if (show) {
140+
loading = true;
141+
Promise.all([loadRules(), loadDomains()]).then(() => {
142+
loading = false;
143+
});
144+
} else {
145+
rules = null;
146+
domains = null;
147+
loading = false;
148+
domainName = null;
149+
}
150+
});
151+
</script>
152+
153+
{#if show}
154+
<Wizard title="Add domain" column columnSize="s" confirmExit onExit={() => (show = false)}>
155+
<Form bind:this={formComponent} onSubmit={addDomain} bind:isSubmitting>
156+
<Fieldset legend="Domain">
157+
{#if loading}
158+
<Layout.Stack gap="s">
159+
<Skeleton variant="line" height={20} width="10%" />
160+
<Skeleton variant="line" height={32} width="100%" />
161+
</Layout.Stack>
162+
{:else}
163+
<InputDomain
164+
required
165+
id="domain"
166+
label="Domain"
167+
bind:value={domainName}
168+
placeholder="appwrite.example.com" />
169+
{/if}
170+
</Fieldset>
171+
</Form>
172+
173+
<svelte:fragment slot="footer">
174+
{#if !loading}
175+
<Button secondary on:click={() => (show = false)}>Cancel</Button>
176+
<Button
177+
forceShowLoader
178+
bind:disabled={$isSubmitting}
179+
submissionLoader={$isSubmitting}
180+
on:click={() => formComponent.triggerSubmit()}>
181+
Add
182+
</Button>
183+
{/if}
184+
</svelte:fragment>
185+
</Wizard>
186+
{/if}

src/lib/studio/domainsTable.svelte renamed to src/lib/studio/domains/manage/table.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@
2323
Divider
2424
} from '@appwrite.io/pink-svelte';
2525
import { resolve } from '$app/paths';
26+
import { goto } from '$app/navigation';
2627
import { Click, trackEvent } from '$lib/actions/analytics';
2728
import { regionalProtocol } from '$routes/(console)/project-[region]-[project]/store';
28-
import { goto } from '$app/navigation';
2929
import DeleteDomainModal from '$routes/(console)/project-[region]-[project]/sites/site-[site]/domains/deleteDomainModal.svelte';
3030
import RetryDomainModal from '$routes/(console)/project-[region]-[project]/sites/site-[site]/domains/retryDomainModal.svelte';
3131
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<script lang="ts">
2+
import { Link } from '$lib/elements';
3+
import DomainsTable from './table.svelte';
4+
import { IconExternalLink } from '@appwrite.io/pink-icons-svelte';
5+
import { Layout, Typography, Icon } from '@appwrite.io/pink-svelte';
6+
import SideSheet from '$routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/layout/sidesheet.svelte';
7+
8+
let {
9+
show = $bindable(false),
10+
domain,
11+
siteId,
12+
region,
13+
projectId
14+
}: {
15+
show: boolean;
16+
domain: string;
17+
siteId: string;
18+
region: string;
19+
projectId: string;
20+
} = $props();
21+
</script>
22+
23+
<SideSheet title="Domains" bind:show>
24+
<Layout.Stack gap="xl">
25+
<Layout.Stack gap="xxs">
26+
<Typography.Text color="--fgcolor-neutral-tertiary">Active domain</Typography.Text>
27+
28+
<Typography.Text>
29+
<Link size="m" external variant="quiet" href={domain}>
30+
<Layout.Stack
31+
direction="row"
32+
gap="xxs"
33+
alignItems="center"
34+
alignContent="center">
35+
{domain}
36+
37+
<Icon size="s" icon={IconExternalLink} />
38+
</Layout.Stack>
39+
</Link>
40+
</Typography.Text>
41+
</Layout.Stack>
42+
43+
<DomainsTable {siteId} {region} {projectId} />
44+
</Layout.Stack>
45+
</SideSheet>

0 commit comments

Comments
 (0)