Skip to content

Commit 396df66

Browse files
committed
Load registrar earlier
1 parent 67f30ea commit 396df66

File tree

1 file changed

+126
-141
lines changed

1 file changed

+126
-141
lines changed

apps/builder/app/builder/features/topbar/domains.tsx

Lines changed: 126 additions & 141 deletions
Original file line numberDiff line numberDiff line change
@@ -166,136 +166,28 @@ const StatusIcon = (props: { projectDomain: Domain; isLoading: boolean }) => {
166166
);
167167
};
168168

169-
const DomainConfig = ({
169+
const DomainItem = ({
170+
initiallyOpen,
170171
projectDomain,
171-
onUpdateStatus,
172+
project,
173+
refresh,
172174
}: {
173-
projectDomain: Domain;
174-
onUpdateStatus: () => void;
175-
}) => {
176-
const { load: findDomainRegistrar, data: registrar } =
177-
trpcClient.domain.findDomainRegistrar.useQuery();
178-
const cname = extractCname(projectDomain.domain);
179-
useEffect(() => {
180-
if (cname === "@") {
181-
findDomainRegistrar({ domain: projectDomain.domain });
182-
}
183-
}, [projectDomain.domain, cname]);
184-
const publisherHost = useStore($publisherHost);
185-
186-
const cnameRecord = {
187-
// use alias for domain root when supported to avoid conflicting
188-
// with MX, NS etc records
189-
type: cname === "@" && registrar?.alias ? "ALIAS" : "CNAME",
190-
host: cname,
191-
value: `${projectDomain.cname}.customers.${publisherHost}`,
192-
ttl: 300,
193-
} as const;
194-
195-
const txtRecord = {
196-
type: "TXT",
197-
host: cname === "@" ? "_webstudio_is" : `_webstudio_is.${cname}`,
198-
value: projectDomain.expectedTxtRecord,
199-
ttl: 300,
200-
} as const;
201-
202-
const dnsRecords = [cnameRecord, txtRecord];
203-
204-
return (
205-
<>
206-
<Text color="subtle">
207-
<strong>To verify your domain:</strong>
208-
<br />
209-
Visit the admin console of your domain registrar (the website you
210-
purchased your domain from) and create one <strong>CNAME</strong> record
211-
and one <strong>TXT</strong> record with the values shown below:
212-
</Text>
213-
214-
<Grid
215-
gap={2}
216-
css={{ gridTemplateColumns: `${theme.spacing[18]} 1fr 1fr` }}
217-
>
218-
<Text color="subtle" variant="titles">
219-
TYPE
220-
</Text>
221-
<Text color="subtle" variant="titles">
222-
NAME
223-
</Text>
224-
<Text color="subtle" variant="titles">
225-
VALUE
226-
</Text>
227-
228-
{dnsRecords.map((record, index) => (
229-
<Fragment key={index}>
230-
<InputEllipsis readOnly value={record.type} />
231-
<InputEllipsis
232-
readOnly
233-
value={record.host}
234-
suffix={
235-
<CopyToClipboard text={record.host}>
236-
<NestedInputButton type="button">
237-
<CopyIcon />
238-
</NestedInputButton>
239-
</CopyToClipboard>
240-
}
241-
/>
242-
<InputEllipsis
243-
readOnly
244-
value={record.value}
245-
suffix={
246-
<CopyToClipboard text={record.value}>
247-
<NestedInputButton type="button">
248-
<CopyIcon />
249-
</NestedInputButton>
250-
</CopyToClipboard>
251-
}
252-
/>
253-
</Fragment>
254-
))}
255-
</Grid>
256-
257-
<Grid
258-
gap={2}
259-
align={"center"}
260-
css={{
261-
gridTemplateColumns: `1fr auto 1fr`,
262-
}}
263-
>
264-
<Separator css={{ alignSelf: "unset" }} />
265-
<Text color="main">OR</Text>
266-
<Separator css={{ alignSelf: "unset" }} />
267-
</Grid>
268-
269-
<Entri
270-
dnsRecords={dnsRecords}
271-
domain={projectDomain.domain}
272-
onClose={() => {
273-
// Sometimes Entri modal dialog hangs even if it's successful,
274-
// until they fix that, we'll just refresh the status here on every onClose event
275-
onUpdateStatus();
276-
}}
277-
/>
278-
</>
279-
);
280-
};
281-
282-
const DomainItem = (props: {
283175
initiallyOpen: boolean;
284176
projectDomain: Domain;
285-
refresh: () => Promise<void>;
286177
project: Project;
178+
refresh: () => Promise<void>;
287179
}) => {
288180
const timeSinceLastUpdateMs =
289-
Date.now() - new Date(props.projectDomain.updatedAt).getTime();
181+
Date.now() - new Date(projectDomain.updatedAt).getTime();
290182

291183
const DAY_IN_MS = 24 * 60 * 60 * 1000;
292184

293-
const status = props.projectDomain.verified
294-
? (`VERIFIED_${props.projectDomain.status}` as `VERIFIED_${DomainStatus}`)
185+
const status = projectDomain.verified
186+
? (`VERIFIED_${projectDomain.status}` as `VERIFIED_${DomainStatus}`)
295187
: `UNVERIFIED`;
296188

297189
const [isStatusLoading, setIsStatusLoading] = useState(
298-
props.initiallyOpen ||
190+
initiallyOpen ||
299191
status === "VERIFIED_ACTIVE" ||
300192
timeSinceLastUpdateMs > DAY_IN_MS
301193
? false
@@ -310,16 +202,16 @@ const DomainItem = (props: {
310202
const handleRemoveDomain = async () => {
311203
setIsRemoveInProgress(true);
312204
const result = await nativeClient.domain.remove.mutate({
313-
projectId: props.projectDomain.projectId,
314-
domainId: props.projectDomain.domainId,
205+
projectId: projectDomain.projectId,
206+
domainId: projectDomain.domainId,
315207
});
316208

317209
if (result.success === false) {
318210
toast.error(result.error);
319211
return;
320212
}
321213

322-
await props.refresh();
214+
await refresh();
323215
};
324216

325217
const [verifyError, setVerifyError] = useState<string | undefined>(undefined);
@@ -329,16 +221,16 @@ const DomainItem = (props: {
329221
setIsCheckStateInProgress(true);
330222

331223
const verifyResult = await nativeClient.domain.verify.mutate({
332-
projectId: props.projectDomain.projectId,
333-
domainId: props.projectDomain.domainId,
224+
projectId: projectDomain.projectId,
225+
domainId: projectDomain.domainId,
334226
});
335227

336228
if (verifyResult.success === false) {
337229
setVerifyError(verifyResult.error);
338230
return;
339231
}
340232

341-
await props.refresh();
233+
await refresh();
342234
});
343235

344236
const [updateStatusError, setUpdateStatusError] = useState<
@@ -350,8 +242,8 @@ const DomainItem = (props: {
350242
setIsCheckStateInProgress(true);
351243

352244
const updateStatusResult = await nativeClient.domain.updateStatus.mutate({
353-
projectId: props.projectDomain.projectId,
354-
domain: props.projectDomain.domain,
245+
projectId: projectDomain.projectId,
246+
domain: projectDomain.domain,
355247
});
356248

357249
setIsStatusLoading(false);
@@ -361,7 +253,7 @@ const DomainItem = (props: {
361253
return;
362254
}
363255

364-
await props.refresh();
256+
await refresh();
365257
});
366258

367259
const onceRef = useRef(false);
@@ -387,43 +279,69 @@ const DomainItem = (props: {
387279
});
388280
}, [status, handleVerify, handleUpdateStatus, isStatusLoading]);
389281

390-
const domainStatus = getStatus(props.projectDomain);
282+
const domainStatus = getStatus(projectDomain);
391283

392284
const { isVerifiedActive, text } = getStatusText({
393-
projectDomain: props.projectDomain,
285+
projectDomain,
394286
isLoading: false,
395287
});
396288

289+
const publisherHost = useStore($publisherHost);
290+
const { load: findDomainRegistrar, data: registrar } =
291+
trpcClient.domain.findDomainRegistrar.useQuery();
292+
const cname = extractCname(projectDomain.domain);
293+
useEffect(() => {
294+
if (cname === "@") {
295+
findDomainRegistrar({ domain: projectDomain.domain });
296+
}
297+
}, [projectDomain.domain, cname]);
298+
const dnsRecords = [
299+
{
300+
// use alias for domain root when supported to avoid conflicting
301+
// with MX, NS etc records
302+
type: cname === "@" && registrar?.alias ? "ALIAS" : "CNAME",
303+
host: cname,
304+
value: `${projectDomain.cname}.customers.${publisherHost}`,
305+
ttl: 300,
306+
} as const,
307+
{
308+
type: "TXT",
309+
host: cname === "@" ? "_webstudio_is" : `_webstudio_is.${cname}`,
310+
value: projectDomain.expectedTxtRecord,
311+
ttl: 300,
312+
} as const,
313+
];
314+
397315
return (
398316
<CollapsibleDomainSection
399317
prefix={
400318
<DomainCheckbox
401-
buildId={props.projectDomain.latestBuildVirtual?.buildId}
319+
buildId={projectDomain.latestBuildVirtual?.buildId}
402320
defaultChecked={
403-
props.projectDomain.latestBuildVirtual?.buildId != null &&
404-
props.projectDomain.latestBuildVirtual?.buildId ===
405-
props.project.latestBuildVirtual?.buildId
321+
projectDomain.latestBuildVirtual?.buildId != null &&
322+
projectDomain.latestBuildVirtual?.buildId ===
323+
project.latestBuildVirtual?.buildId
406324
}
407-
domain={props.projectDomain.domain}
325+
domain={projectDomain.domain}
408326
disabled={domainStatus !== "VERIFIED_ACTIVE"}
409327
/>
410328
}
411-
initiallyOpen={props.initiallyOpen}
412-
title={props.projectDomain.domain}
329+
initiallyOpen={initiallyOpen}
330+
title={projectDomain.domain}
413331
suffix={
414332
<Grid flow="column">
415333
<StatusIcon
416334
isLoading={isStatusLoading}
417-
projectDomain={props.projectDomain}
335+
projectDomain={projectDomain}
418336
/>
419337

420-
<Tooltip content={`Proceed to ${props.projectDomain.domain}`}>
338+
<Tooltip content={`Proceed to ${projectDomain.domain}`}>
421339
<IconButton
422340
type="button"
423341
tabIndex={-1}
424342
disabled={status !== "VERIFIED_ACTIVE"}
425343
onClick={(event) => {
426-
const url = new URL(`https://${props.projectDomain.domain}`);
344+
const url = new URL(`https://${projectDomain.domain}`);
427345
window.open(url.href, "_blank");
428346
event.preventDefault();
429347
}}
@@ -503,9 +421,76 @@ const DomainItem = (props: {
503421
)}
504422
</Grid>
505423

506-
<DomainConfig
507-
projectDomain={props.projectDomain}
508-
onUpdateStatus={() => {
424+
<Text color="subtle">
425+
<strong>To verify your domain:</strong>
426+
<br />
427+
Visit the admin console of your domain registrar (the website you
428+
purchased your domain from) and create one <strong>CNAME</strong>{" "}
429+
record and one <strong>TXT</strong> record with the values shown
430+
below:
431+
</Text>
432+
433+
<Grid
434+
gap={2}
435+
css={{ gridTemplateColumns: `${theme.spacing[18]} 1fr 1fr` }}
436+
>
437+
<Text color="subtle" variant="titles">
438+
TYPE
439+
</Text>
440+
<Text color="subtle" variant="titles">
441+
NAME
442+
</Text>
443+
<Text color="subtle" variant="titles">
444+
VALUE
445+
</Text>
446+
447+
{dnsRecords.map((record, index) => (
448+
<Fragment key={index}>
449+
<InputEllipsis readOnly value={record.type} />
450+
<InputEllipsis
451+
readOnly
452+
value={record.host}
453+
suffix={
454+
<CopyToClipboard text={record.host}>
455+
<NestedInputButton type="button">
456+
<CopyIcon />
457+
</NestedInputButton>
458+
</CopyToClipboard>
459+
}
460+
/>
461+
<InputEllipsis
462+
readOnly
463+
value={record.value}
464+
suffix={
465+
<CopyToClipboard text={record.value}>
466+
<NestedInputButton type="button">
467+
<CopyIcon />
468+
</NestedInputButton>
469+
</CopyToClipboard>
470+
}
471+
/>
472+
</Fragment>
473+
))}
474+
</Grid>
475+
476+
<Grid
477+
gap={2}
478+
align={"center"}
479+
css={{
480+
gridTemplateColumns: `1fr auto 1fr`,
481+
}}
482+
>
483+
<Separator css={{ alignSelf: "unset" }} />
484+
<Text color="main">OR</Text>
485+
<Separator css={{ alignSelf: "unset" }} />
486+
</Grid>
487+
488+
<Entri
489+
dnsRecords={dnsRecords}
490+
domain={projectDomain.domain}
491+
onClose={() => {
492+
// Sometimes Entri modal dialog hangs even if it's successful,
493+
// until they fix that, we'll just refresh the status here on every onClose event
509494
if (status === "UNVERIFIED") {
510495
startTransition(async () => {
511496
await handleVerify();

0 commit comments

Comments
 (0)