Skip to content

Commit 8cbfc91

Browse files
committed
Make everything as action
Publish no loop Update Publishing done Change Interface Update exports Exclude from search Fix assets for saas Fix Fix static publish Wait until published Remove local refresh Fix Improve Enable Fix button types Fix Fix publish Add tooltip support for checkboxes Add tooltip checkbox
1 parent 6e424c9 commit 8cbfc91

File tree

16 files changed

+594
-634
lines changed

16 files changed

+594
-634
lines changed

apps/builder/app/builder/features/topbar/add-domain.tsx

Lines changed: 37 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -7,65 +7,61 @@ import {
77
theme,
88
Text,
99
Grid,
10+
toast,
1011
} from "@webstudio-is/design-system";
1112
import { validateDomain } from "@webstudio-is/domain";
1213
import type { Project } from "@webstudio-is/project";
13-
import { useId, useState } from "react";
14+
import { useId, useOptimistic, useRef, useState } from "react";
1415
import { CustomCodeIcon } from "@webstudio-is/icons";
15-
import { trpcClient } from "~/shared/trpc/trpc-client";
16+
import { nativeClient } from "~/shared/trpc/trpc-client";
1617

1718
type DomainsAddProps = {
1819
projectId: Project["id"];
1920
onCreate: (domain: string) => void;
2021
onExportClick: () => void;
21-
refreshDomainResult: (
22-
input: { projectId: Project["id"] },
23-
onSuccess: () => void
24-
) => void;
25-
domainState: "idle" | "submitting";
26-
isPublishing: boolean;
22+
refresh: () => Promise<void>;
2723
};
2824

2925
export const AddDomain = ({
3026
projectId,
3127
onCreate,
32-
refreshDomainResult,
33-
domainState,
34-
isPublishing,
28+
refresh,
3529
onExportClick,
3630
}: DomainsAddProps) => {
3731
const id = useId();
38-
const {
39-
send: create,
40-
state: сreateState,
41-
error: сreateSystemError,
42-
} = trpcClient.domain.create.useMutation();
4332
const [isOpen, setIsOpen] = useState(false);
44-
const [domain, setDomain] = useState("");
4533
const [error, setError] = useState<string>();
34+
const buttonRef = useRef<HTMLButtonElement>(null);
35+
const [isPending, setIsPendingOptimistic] = useOptimistic(false);
4636

47-
const handleCreate = () => {
48-
setError(undefined);
37+
const handleCreateDomain = async (formData: FormData) => {
38+
// Will be automatically reset on action end
39+
setIsPendingOptimistic(true);
4940

41+
const domain = formData.get("domain")?.toString() ?? "";
5042
const validationResult = validateDomain(domain);
5143

5244
if (validationResult.success === false) {
5345
setError(validationResult.error);
5446
return;
5547
}
5648

57-
create({ domain: validationResult.domain, projectId }, (data) => {
58-
if (data.success === false) {
59-
setError(data.error);
60-
return;
61-
}
62-
63-
refreshDomainResult({ projectId }, () => {
64-
setDomain("");
65-
setIsOpen(false);
66-
onCreate(validationResult.domain);
67-
});
49+
const result = await nativeClient.domain.create.mutate({
50+
domain,
51+
projectId,
6852
});
53+
54+
if (result.success === false) {
55+
toast.error(result.error);
56+
setError(result.error);
57+
return;
58+
}
59+
60+
onCreate(domain);
61+
62+
await refresh();
63+
64+
setIsOpen(false);
6965
};
7066

7167
return (
@@ -81,7 +77,6 @@ export const AddDomain = ({
8177
direction={"column"}
8278
onKeyDown={(event) => {
8379
if (event.key === "Escape") {
84-
setDomain("");
8580
setIsOpen(false);
8681
event.preventDefault();
8782
}
@@ -94,56 +89,43 @@ export const AddDomain = ({
9489
</Label>
9590
<InputField
9691
id={id}
92+
name="domain"
9793
autoFocus
9894
placeholder="your-domain.com"
99-
value={domain}
100-
disabled={
101-
isPublishing || сreateState !== "idle" || domainState !== "idle"
102-
}
95+
disabled={isPending}
10396
onKeyDown={(event) => {
10497
if (event.key === "Enter") {
105-
handleCreate();
98+
buttonRef.current
99+
?.closest("form")
100+
?.requestSubmit(buttonRef.current);
106101
}
107102
if (event.key === "Escape") {
108-
setDomain("");
109103
setIsOpen(false);
110104
event.preventDefault();
111105
}
112106
}}
113-
onChange={(event) => {
114-
setError(undefined);
115-
setDomain(event.target.value);
116-
}}
117107
color={error !== undefined ? "error" : undefined}
118108
/>
119109
{error !== undefined && (
120110
<>
121111
<Text color="destructive">{error}</Text>
122112
</>
123113
)}
124-
{сreateSystemError !== undefined && (
125-
<>
126-
{/* Something happened with network, api etc */}
127-
<Text color="destructive">{сreateSystemError}</Text>
128-
<Text color="subtle">Please try again later</Text>
129-
</>
130-
)}
131114
</>
132115
)}
133116

134117
<Grid gap={2} columns={2}>
135118
<Button
136-
disabled={
137-
isPublishing || сreateState !== "idle" || domainState !== "idle"
138-
}
119+
ref={buttonRef}
120+
formAction={handleCreateDomain}
121+
state={isPending ? "pending" : undefined}
139122
color={isOpen ? "primary" : "neutral"}
140-
onClick={() => {
123+
onClick={(event) => {
141124
if (isOpen === false) {
142125
setIsOpen(true);
126+
event.preventDefault();
143127
return;
144128
}
145-
146-
handleCreate();
147129
}}
148130
>
149131
{isOpen ? "Add domain" : "Add a new domain"}
@@ -152,6 +134,7 @@ export const AddDomain = ({
152134
<Button
153135
color={"dark"}
154136
prefix={<CustomCodeIcon />}
137+
type="button"
155138
onClick={onExportClick}
156139
>
157140
Export

apps/builder/app/builder/features/topbar/collapsible-domain-section.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
Label,
55
theme,
66
SectionTitle,
7+
Grid,
78
} from "@webstudio-is/design-system";
89
import { useEffect, useRef, useState, type ReactNode } from "react";
910
import { CollapsibleSectionRoot } from "~/builder/shared/collapsible-section";
@@ -13,9 +14,11 @@ export const CollapsibleDomainSection = ({
1314
children,
1415
title,
1516
suffix,
17+
prefix,
1618
}: {
1719
initiallyOpen?: boolean;
1820
children: ReactNode;
21+
prefix: ReactNode;
1922
suffix: ReactNode;
2023
title: string;
2124
}) => {
@@ -53,7 +56,10 @@ export const CollapsibleDomainSection = ({
5356
</Box>
5457
}
5558
>
56-
<Label truncate>{title}</Label>
59+
<Grid flow={"column"} align="center" justify={"start"}>
60+
{prefix}
61+
<Label truncate>{title}</Label>
62+
</Grid>
5763
</SectionTitle>
5864
}
5965
>
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import { useStore } from "@nanostores/react";
2+
import {
3+
Flex,
4+
Tooltip,
5+
Text,
6+
theme,
7+
Link,
8+
buttonStyle,
9+
Checkbox,
10+
} from "@webstudio-is/design-system";
11+
import { $userPlanFeatures } from "~/builder/shared/nano-states";
12+
13+
export const domainToPublishName = "domainToPublish[]";
14+
15+
interface DomainCheckboxProps {
16+
defaultChecked?: boolean;
17+
domain: string;
18+
buildId: string | undefined;
19+
disabled?: boolean;
20+
}
21+
22+
const DomainCheckbox = (props: DomainCheckboxProps) => {
23+
const hasProPlan = useStore($userPlanFeatures).hasProPlan;
24+
25+
const tooltipContentForFreeUsers = hasProPlan ? undefined : (
26+
<Flex direction="column" gap="2" css={{ maxWidth: theme.spacing[28] }}>
27+
<Text variant="titles">Publish to Staging</Text>
28+
<Text>
29+
<Flex direction="column">
30+
Staging allows you to preview a production version of your site
31+
without potentially breaking what production site visitors will see.
32+
<>
33+
<br />
34+
<br />
35+
Upgrade to Pro to be able to publish to each domain individually.
36+
<br /> <br />
37+
<Link
38+
className={buttonStyle({ color: "gradient" })}
39+
color="contrast"
40+
underline="none"
41+
href="https://webstudio.is/pricing"
42+
target="_blank"
43+
>
44+
Upgrade
45+
</Link>
46+
</>
47+
</Flex>
48+
</Text>
49+
</Flex>
50+
);
51+
52+
const defaultChecked = hasProPlan ? props.defaultChecked : true;
53+
const disabled = hasProPlan ? props.disabled : true;
54+
55+
return (
56+
<Tooltip content={tooltipContentForFreeUsers} variant="wrapped">
57+
<Checkbox
58+
disabled={disabled}
59+
key={props.buildId ?? "-"}
60+
defaultChecked={defaultChecked}
61+
css={{ pointerEvents: "all" }}
62+
name={domainToPublishName}
63+
value={props.domain}
64+
/>
65+
</Tooltip>
66+
);
67+
};
68+
69+
export default DomainCheckbox;

0 commit comments

Comments
 (0)