Skip to content

Commit d4249b0

Browse files
committed
design: widget form design updates (#16454)
1 parent d0468d7 commit d4249b0

14 files changed

+278
-127
lines changed

airbyte-webapp/src/components/ui/Button/Button.module.scss

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,12 @@ $clear-dark-background-color: transparent;
5252
$clear-dark-text-color-hover: colors.$grey-600;
5353
$clear-dark-text-color-active: colors.$grey-600;
5454

55+
// Clear Danger
56+
$clear-danger-text-color: colors.$red-400;
57+
$clear-danger-text-color-hover: colors.$red-600;
58+
$clear-danger-text-color-active: colors.$red-600;
59+
$clear-danger-background-color: transparent;
60+
5561
.button {
5662
display: inline-flex;
5763
align-items: center;
@@ -262,6 +268,20 @@ $clear-dark-text-color-active: colors.$grey-600;
262268
}
263269
}
264270

271+
&--clear-danger {
272+
background-color: $clear-danger-background-color;
273+
color: $clear-danger-text-color;
274+
padding: 0;
275+
276+
&:hover {
277+
color: $clear-danger-text-color-hover;
278+
}
279+
280+
&:active {
281+
color: $clear-danger-text-color-active;
282+
}
283+
}
284+
265285
&--clear-dark {
266286
background-color: $clear-dark-background-color;
267287
color: $clear-dark-text-color;

airbyte-webapp/src/components/ui/Button/Button.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ export const Button = React.forwardRef<HTMLButtonElement, ButtonProps>((props, r
3131
[styles["button--size-xs"]]: size === "xs",
3232
[styles["button--danger"]]: variant === "danger",
3333
[styles["button--clear"]]: variant === "clear",
34+
[styles["button--clear-danger"]]: variant === "clearDanger",
3435
[styles["button--magic"]]: variant === "magic",
3536
[styles["button--primary"]]: variant === "primary",
3637
[styles["button--secondary"]]: variant === "secondary",

airbyte-webapp/src/components/ui/Button/types.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ export type ButtonVariant =
1010
| "magic"
1111
| "clear"
1212
| "clearDark"
13+
| "clearDanger"
1314
| "primaryDark"
1415
| "secondaryDark"
1516
| "link";

airbyte-webapp/src/locales/en.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2484,16 +2484,18 @@
24842484
"partialUserConfig.update.tab": "Saved integrations",
24852485
"partialUserConfig.create.title": "Create integration",
24862486
"partialUserConfig.update.title": "Update your integration",
2487-
"partialUserConfig.buttonText": "Save integration",
2487+
"partialUserConfig.buttonText": "Save",
24882488
"partialUserConfig.create.success": "Source created successfully",
24892489
"partialUserConfig.update.success": "Source updated successfully",
24902490
"partialUserConfig.back": "Back",
24912491
"partialUserConfig.backToIntegrations": "Back to integrations",
24922492
"partialUserConfig.success.title": "Success!",
24932493
"partialUserConfig.success.description": "You've connected your account.",
2494-
"partialUserConfig.delete.success": "Integration deleted successfully",
2494+
"partialUserConfig.delete.success": "{connectorName} has been deleted.",
24952495
"partialUserConfig.delete.buttonText": "Delete integration",
24962496
"partialUserConfig.delete.warning": "Are you sure you want to delete this integration?",
2497+
"partialUserConfig.delete.warning.confirm": "Yes, delete this integration",
2498+
"partialUserConfig.delete.warning.cancel": "No, nevermind",
24972499
"partialUserConfig.delete.error": "There was an error deleting this integration. Please try again.",
24982500
"embedded.onboardingCopy": "Welcome to Airbyte Embedded.",
24992501
"embedded.envDescription": "Save a copy of the following environment variables in your application to begin integrating with Airbyte. See our Getting Started page for more information.",

airbyte-webapp/src/pages/embedded/EmbeddedSourceCreatePage/components/PartialUserConfigCreateForm.tsx

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { IsAirbyteEmbeddedContext } from "core/services/embedded";
44
import { ConnectorFormValues } from "views/Connector/ConnectorForm";
55

66
import { PartialUserConfigForm } from "./PartialUserConfigForm";
7+
import { PartialUserConfigSuccessView } from "./PartialUserConfigSuccessView";
78
import { useEmbeddedSourceParams } from "../hooks/useEmbeddedSourceParams";
89

910
export const PartialUserConfigCreateForm: React.FC = () => {
@@ -33,6 +34,16 @@ export const PartialUserConfigCreateForm: React.FC = () => {
3334
});
3435
};
3536

37+
if (isSuccess) {
38+
return (
39+
<PartialUserConfigSuccessView
40+
successType="create"
41+
connectorName={configTemplate.name}
42+
icon={configTemplate.icon}
43+
/>
44+
);
45+
}
46+
3647
return (
3748
<IsAirbyteEmbeddedContext.Provider value>
3849
<PartialUserConfigForm
@@ -41,7 +52,6 @@ export const PartialUserConfigCreateForm: React.FC = () => {
4152
icon={configTemplate.icon}
4253
onSubmit={onSubmit}
4354
sourceDefinitionSpecification={sourceDefinitionSpecification}
44-
showSuccessView={isSuccess}
4555
/>
4656
</IsAirbyteEmbeddedContext.Provider>
4757
);

airbyte-webapp/src/pages/embedded/EmbeddedSourceCreatePage/components/PartialUserConfigEditForm.tsx

Lines changed: 66 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,31 @@
11
import React from "react";
2-
import { FormattedMessage, useIntl } from "react-intl";
2+
import { FormattedMessage } from "react-intl";
33

4-
import { Text } from "components/ui/Text";
4+
import { Button } from "components/ui/Button";
5+
import { FlexContainer } from "components/ui/Flex";
56

67
import { useCurrentWorkspaceId } from "area/workspace/utils";
78
import { useDeletePartialUserConfig, useGetPartialUserConfig, useUpdatePartialUserConfig } from "core/api";
89
import { SourceDefinitionSpecification } from "core/api/types/AirbyteClient";
910
import { IsAirbyteEmbeddedContext } from "core/services/embedded";
10-
import { useConfirmationModalService } from "hooks/services/ConfirmationModal";
11-
import { useNotificationService } from "hooks/services/Notification";
1211
import { ConnectorFormValues } from "views/Connector/ConnectorForm";
1312

13+
import styles from "./PartialUserConfigEditForm.module.scss";
1414
import { PartialUserConfigForm } from "./PartialUserConfigForm";
15-
15+
import { PartialUserConfigHeader } from "./PartialUserConfigHeader";
16+
import { PartialUserConfigSuccessView } from "./PartialUserConfigSuccessView";
1617
export const PartialUserConfigEditForm: React.FC<{ selectedPartialConfigId: string }> = ({
1718
selectedPartialConfigId,
1819
}) => {
1920
const workspaceId = useCurrentWorkspaceId();
20-
const { mutate: updatePartialUserConfig, isSuccess } = useUpdatePartialUserConfig();
21-
const { mutateAsync: deletePartialUserConfig, isSuccess: isDeleteSuccess } = useDeletePartialUserConfig();
22-
const { openConfirmationModal, closeConfirmationModal } = useConfirmationModalService();
23-
const { registerNotification } = useNotificationService();
24-
const { formatMessage } = useIntl();
21+
const { mutate: updatePartialUserConfig, isSuccess: isUpdateSuccess } = useUpdatePartialUserConfig();
22+
const {
23+
mutateAsync: deletePartialUserConfig,
24+
isSuccess: isDeleteSuccess,
25+
isLoading: isDeleting,
26+
} = useDeletePartialUserConfig();
2527
const partialUserConfig = useGetPartialUserConfig(selectedPartialConfigId ?? "");
28+
const [confirmDelete, setConfirmDelete] = React.useState(false);
2629

2730
const sourceDefinitionSpecification: SourceDefinitionSpecification = {
2831
...partialUserConfig.configTemplate.configTemplateSpec,
@@ -51,29 +54,61 @@ export const PartialUserConfigEditForm: React.FC<{ selectedPartialConfigId: stri
5154
};
5255

5356
const onDeleteClick = () => {
54-
openConfirmationModal({
55-
title: <FormattedMessage id="partialUserConfig.delete.buttonText" />,
56-
text: (
57-
<Text>
58-
<FormattedMessage id="partialUserConfig.delete.warning" />
59-
</Text>
60-
),
61-
onSubmit: async () => {
62-
try {
63-
await deletePartialUserConfig(selectedPartialConfigId);
64-
closeConfirmationModal();
65-
} catch (e) {
66-
registerNotification({
67-
type: "error",
68-
id: `delete-integration-${selectedPartialConfigId}`,
69-
text: <FormattedMessage id="partialUserConfig.delete.error" />,
70-
});
71-
}
72-
},
73-
submitButtonText: formatMessage({ id: "partialUserConfig.delete.buttonText" }),
74-
});
57+
setConfirmDelete(true);
58+
};
59+
60+
const handleDelete = async () => {
61+
await deletePartialUserConfig(selectedPartialConfigId);
62+
setConfirmDelete(false);
7563
};
7664

65+
const handleCancelDelete = () => {
66+
setConfirmDelete(false);
67+
};
68+
69+
if (confirmDelete === true) {
70+
return (
71+
<FlexContainer direction="column" justifyContent="space-between" alignItems="center" className={styles.content}>
72+
<FlexContainer direction="column" gap="xl" alignItems="center">
73+
<PartialUserConfigHeader
74+
icon={partialUserConfig.configTemplate.icon}
75+
connectorName={partialUserConfig.configTemplate.name}
76+
/>
77+
78+
<FormattedMessage id="partialUserConfig.delete.warning" />
79+
</FlexContainer>
80+
<FlexContainer className={styles.buttonContainer} direction="column">
81+
<Button full variant="danger" onClick={handleDelete} isLoading={isDeleting}>
82+
<FormattedMessage id="partialUserConfig.delete.warning.confirm" />
83+
</Button>
84+
<Button full variant="clear" onClick={handleCancelDelete} disabled={isDeleting}>
85+
<FormattedMessage id="partialUserConfig.delete.warning.cancel" />
86+
</Button>
87+
</FlexContainer>
88+
</FlexContainer>
89+
);
90+
}
91+
92+
if (isDeleteSuccess) {
93+
return (
94+
<PartialUserConfigSuccessView
95+
successType="delete"
96+
connectorName={partialUserConfig.configTemplate.name}
97+
icon={partialUserConfig.configTemplate.icon}
98+
/>
99+
);
100+
}
101+
102+
if (isUpdateSuccess) {
103+
return (
104+
<PartialUserConfigSuccessView
105+
successType="update"
106+
connectorName={partialUserConfig.configTemplate.name}
107+
icon={partialUserConfig.configTemplate.icon}
108+
/>
109+
);
110+
}
111+
77112
const initialValues: Partial<ConnectorFormValues> = {
78113
name: partialUserConfig.configTemplate.name,
79114
connectionConfiguration: partialUserConfig.connectionConfiguration,
@@ -88,9 +123,7 @@ export const PartialUserConfigEditForm: React.FC<{ selectedPartialConfigId: stri
88123
onSubmit={onSubmit}
89124
initialValues={initialValues}
90125
sourceDefinitionSpecification={sourceDefinitionSpecification}
91-
showSuccessView={isSuccess}
92126
onDelete={onDeleteClick}
93-
isDeleteSuccess={isDeleteSuccess}
94127
/>
95128
</IsAirbyteEmbeddedContext.Provider>
96129
);

airbyte-webapp/src/pages/embedded/EmbeddedSourceCreatePage/components/PartialUserConfigForm.module.scss

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,6 @@
11
@use "scss/colors";
22
@use "scss/variables";
33

4-
.iconContainer {
5-
height: 56px;
6-
width: 56px;
7-
display: flex;
8-
align-items: center;
9-
justify-content: center;
10-
}
11-
124
.connectorName {
135
font-size: variables.$font-size-lg;
146
font-weight: 500;
Lines changed: 19 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,12 @@
1-
import { FormattedMessage } from "react-intl";
2-
3-
import { Button } from "components/ui/Button";
41
import { FlexContainer } from "components/ui/Flex";
5-
import { Icon } from "components/ui/Icon";
6-
import { Text } from "components/ui/Text";
72

8-
import { SvgIcon } from "area/connector/utils";
93
import { SourceDefinitionRead } from "core/api/types/AirbyteClient";
104
import { SourceDefinitionSpecificationDraft } from "core/domain/connector";
115
import { ConnectorForm, ConnectorFormValues } from "views/Connector/ConnectorForm";
126

137
import styles from "./PartialUserConfigForm.module.scss";
148
import { PartialUserConfigFormControls } from "./PartialUserConfigFormControls";
15-
import { useEmbeddedSourceParams } from "../hooks/useEmbeddedSourceParams";
9+
import { PartialUserConfigHeader } from "./PartialUserConfigHeader";
1610

1711
interface PartialUserConfigFormProps {
1812
connectorName: string;
@@ -21,8 +15,6 @@ interface PartialUserConfigFormProps {
2115
initialValues?: Partial<ConnectorFormValues>;
2216
sourceDefinitionSpecification: SourceDefinitionSpecificationDraft;
2317
isEditMode: boolean;
24-
showSuccessView: boolean;
25-
isDeleteSuccess?: boolean;
2618
onDelete?: () => void;
2719
}
2820

@@ -33,12 +25,8 @@ export const PartialUserConfigForm: React.FC<PartialUserConfigFormProps> = ({
3325
initialValues,
3426
sourceDefinitionSpecification,
3527
isEditMode,
36-
showSuccessView,
37-
isDeleteSuccess,
3828
onDelete,
3929
}) => {
40-
const { clearSelectedConfig, clearSelectedTemplate } = useEmbeddedSourceParams();
41-
4230
// The ConnectorForm needs a connector definition to get the connector name. We construct a dummy one here, since
4331
// Embedded users do not have access to APIs that return actual SourceDefinitionRead objects
4432
const sourceDefinition: SourceDefinitionRead = {
@@ -48,71 +36,24 @@ export const PartialUserConfigForm: React.FC<PartialUserConfigFormProps> = ({
4836
dockerImageTag: "not-set-for-embedded",
4937
};
5038

51-
const onClick = () => {
52-
clearSelectedConfig();
53-
clearSelectedTemplate();
54-
};
5539
return (
56-
<>
57-
{!showSuccessView && !isDeleteSuccess ? (
58-
<FlexContainer className={styles.content} direction="column">
59-
<FlexContainer alignItems="center" gap="sm" justifyContent="center">
60-
<FlexContainer className={styles.iconContainer} aria-hidden="true" alignItems="center">
61-
<SvgIcon src={icon} />
62-
</FlexContainer>
63-
<p>{connectorName}</p>
64-
</FlexContainer>
65-
66-
<ConnectorForm
67-
trackDirtyChanges
68-
isEditMode={isEditMode}
69-
formType="source"
70-
formValues={initialValues}
71-
selectedConnectorDefinition={sourceDefinition}
72-
selectedConnectorDefinitionSpecification={sourceDefinitionSpecification}
73-
onSubmit={async (values: ConnectorFormValues) => {
74-
try {
75-
await Promise.resolve(onSubmit(values));
76-
} catch (error) {
77-
console.error(error);
78-
}
79-
}}
80-
canEdit
81-
renderFooter={({ isSubmitting }) => (
82-
<PartialUserConfigFormControls onDelete={onDelete} isSubmitting={isSubmitting} />
83-
)}
84-
/>
85-
</FlexContainer>
86-
) : (
87-
<FlexContainer className={styles.content} direction="column" justifyContent="space-between">
88-
{!isDeleteSuccess && (
89-
<FlexContainer alignItems="center" gap="sm" justifyContent="center">
90-
<FlexContainer className={styles.iconContainer} aria-hidden="true" alignItems="center">
91-
<SvgIcon src={icon} />
92-
</FlexContainer>
93-
<p>{connectorName}</p>
94-
</FlexContainer>
95-
)}
96-
<FlexContainer direction="column" gap="lg" justifyContent="center" alignItems="center">
97-
<Icon size="xl" type="checkCircle" color="disabled" />
98-
<Text size="lg">
99-
<FormattedMessage id="partialUserConfig.success.title" />
100-
</Text>
101-
<Text size="md">
102-
{isDeleteSuccess ? (
103-
<FormattedMessage id="partialUserConfig.delete.success" />
104-
) : (
105-
<FormattedMessage id="partialUserConfig.success.description" />
106-
)}
107-
</Text>
108-
</FlexContainer>
109-
<div className={styles.buttonContainer}>
110-
<Button full onClick={onClick}>
111-
<FormattedMessage id="partialUserConfig.backToIntegrations" />
112-
</Button>
113-
</div>
114-
</FlexContainer>
115-
)}
116-
</>
40+
<FlexContainer className={styles.content} direction="column">
41+
<PartialUserConfigHeader icon={icon} connectorName={connectorName} />
42+
<ConnectorForm
43+
trackDirtyChanges
44+
isEditMode={isEditMode}
45+
formType="source"
46+
formValues={initialValues}
47+
selectedConnectorDefinition={sourceDefinition}
48+
selectedConnectorDefinitionSpecification={sourceDefinitionSpecification}
49+
onSubmit={async (values: ConnectorFormValues) => {
50+
await Promise.resolve(onSubmit(values));
51+
}}
52+
canEdit
53+
renderFooter={({ isSubmitting }) => (
54+
<PartialUserConfigFormControls onDelete={onDelete} isSubmitting={isSubmitting} />
55+
)}
56+
/>
57+
</FlexContainer>
11758
);
11859
};

0 commit comments

Comments
 (0)