Skip to content

Commit

Permalink
🪟 🎨 🏁 Move editing connection name to Settings page (#6145)
Browse files Browse the repository at this point in the history
Co-authored-by: josephkmh <joseph@airbyte.io>
  • Loading branch information
teallarson and josephkmh committed Apr 25, 2023
1 parent bd0676c commit ac44a39
Show file tree
Hide file tree
Showing 8 changed files with 131 additions and 42 deletions.
Original file line number Diff line number Diff line change
@@ -1,17 +1,12 @@
@use "scss/variables";
@use "scss/colors";

.deleteBlock {
margin-top: variables.$spacing-md;
padding: variables.$spacing-xl;
display: flex;
align-items: center;
justify-content: space-between;
}

.text {
font-size: 11px;
line-height: 13px;
color: colors.$grey-300;
white-space: pre-line;
}
15 changes: 9 additions & 6 deletions airbyte-webapp/src/components/common/DeleteBlock/DeleteBlock.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import React from "react";
import { FormattedMessage } from "react-intl";

import { H5 } from "components/base/Titles";
import { Button } from "components/ui/Button";
import { Card } from "components/ui/Card";
import { FlexContainer } from "components/ui/Flex";
import { Text } from "components/ui/Text";

import { useDeleteModal } from "hooks/useDeleteModal";

Expand All @@ -20,12 +21,14 @@ export const DeleteBlock: React.FC<IProps> = ({ type, onDelete }) => {

return (
<Card className={styles.deleteBlock}>
<div className={styles.text}>
<H5 bold>
<FlexContainer direction="column" className={styles.text}>
<Text size="lg">
<FormattedMessage id={`tables.${type}Delete.title`} />
</H5>
<FormattedMessage id={`tables.${type}DataDelete`} />
</div>
</Text>
<Text size="xs" color="grey">
<FormattedMessage id={`tables.${type}DataDelete`} />
</Text>
</FlexContainer>
<Button variant="danger" onClick={onDeleteButtonClick} data-id="open-delete-modal">
<FormattedMessage id={`tables.${type}Delete`} />
</Button>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,19 @@ import { Heading } from "components/ui/Heading";
import { Input } from "components/ui/Input";

import { useConnectionEditService } from "hooks/services/ConnectionEdit/ConnectionEditService";
import { useExperiment } from "hooks/services/Experiment";
import withKeystrokeHandler from "utils/withKeystrokeHandler";

import styles from "./ConnectionName.module.scss";

const InputWithKeystroke = withKeystrokeHandler(Input);

export const ConnectionName: React.FC = () => {
// this component will be removed when the new connection flow is turned on as this component will be replaced
// for this interim state, we'll just serve a "readonly" version of this component when the flag is on
// the new component will be added in the main header redesign PR.

const isNewConnectionFlowEnabled = useExperiment("connection.updatedConnectionFlow", false);
const { connection, updateConnection } = useConnectionEditService();
const { name } = connection;
const [editingState, setEditingState] = useState(false);
Expand Down Expand Up @@ -67,31 +73,39 @@ export const ConnectionName: React.FC = () => {
};

return (
<div className={styles.container}>
{editingState ? (
<div className={styles.editingContainer}>
<div className={styles.inputContainer} onBlur={onBlur}>
<InputWithKeystroke
className={styles.input}
value={connectionName}
onChange={inputChange}
onEscape={onEscape}
onEnter={onEnter}
disabled={loading}
autoFocus
/>
</div>
</div>
<>
{isNewConnectionFlowEnabled ? (
<Heading as="h2" size="lg">
{name}
</Heading>
) : (
<button className={styles.nameContainer} onClick={() => setEditingState(true)}>
<div>
<Heading as="h2" size="lg">
{name}
</Heading>
</div>
<FontAwesomeIcon className={styles.icon} icon={faPenToSquare} />
</button>
<div className={styles.container}>
{editingState ? (
<div className={styles.editingContainer}>
<div className={styles.inputContainer} onBlur={onBlur}>
<InputWithKeystroke
className={styles.input}
value={connectionName}
onChange={inputChange}
onEscape={onEscape}
onEnter={onEnter}
disabled={loading}
autoFocus
/>
</div>
</div>
) : (
<button className={styles.nameContainer} onClick={() => setEditingState(true)}>
<div>
<Heading as="h2" size="lg">
{name}
</Heading>
</div>
<FontAwesomeIcon className={styles.icon} icon={faPenToSquare} />
</button>
)}
</div>
)}
</div>
</>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import React from "react";
import { useIntl } from "react-intl";
import * as yup from "yup";

import { Form, FormControl } from "components/forms";
import { FormSubmissionButtons } from "components/forms/FormSubmissionButtons";
import { Card } from "components/ui/Card";

import { useAppMonitoringService } from "hooks/services/AppMonitoringService";
import { useConnectionEditService } from "hooks/services/ConnectionEdit/ConnectionEditService";
import { useNotificationService } from "hooks/services/Notification";

const connectionNameFormSchema = yup.object({
connectionName: yup.string().required("form.empty.error"),
});

interface ConnectionNameFormValues {
connectionName: string;
}

export const UpdateConnectionName: React.FC = () => {
const { connection, updateConnection } = useConnectionEditService();
const { registerNotification } = useNotificationService();
const { trackError } = useAppMonitoringService();
const { formatMessage } = useIntl();

const onSuccess = () => {
registerNotification({
id: "connection_name_change_success",
text: formatMessage({ id: "form.changesSaved" }),
type: "success",
});
};

const onError = (e: Error, { connectionName }: ConnectionNameFormValues) => {
trackError(e, { connectionName });
registerNotification({
id: "connection_name_change_error",
text: formatMessage({ id: "connection.updateFailed" }),
type: "error",
});
};

return (
<Card withPadding>
<Form<ConnectionNameFormValues>
trackDirtyChanges
onSubmit={({ connectionName }) =>
updateConnection({
name: connectionName,
connectionId: connection.connectionId,
})
}
onError={onError}
onSuccess={onSuccess}
schema={connectionNameFormSchema}
defaultValues={{ connectionName: connection.name }}
>
<FormControl<ConnectionNameFormValues>
label={formatMessage({ id: "form.connectionName" })}
fieldType="input"
name="connectionName"
/>
<FormSubmissionButtons submitKey="settings.accountSettings.updateName" />
</Form>
</Card>
);
};
5 changes: 5 additions & 0 deletions airbyte-webapp/src/components/forms/Form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { ReactNode } from "react";
import { useForm, FormProvider, DeepPartial } from "react-hook-form";
import { SchemaOf } from "yup";

import { FormChangeTracker } from "components/common/FormChangeTracker";

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type FormValues = Record<string, any>;

Expand All @@ -13,6 +15,7 @@ interface FormProps<T extends FormValues> {
schema: SchemaOf<T>;
defaultValues: DeepPartial<T>;
children?: ReactNode | undefined;
trackDirtyChanges?: boolean;
}

export const Form = <T extends FormValues>({
Expand All @@ -22,6 +25,7 @@ export const Form = <T extends FormValues>({
onError,
defaultValues,
schema,
trackDirtyChanges = false,
}: FormProps<T>) => {
const methods = useForm<T>({
defaultValues,
Expand All @@ -41,6 +45,7 @@ export const Form = <T extends FormValues>({

return (
<FormProvider {...methods}>
{trackDirtyChanges && <FormChangeTracker changed={methods.formState.isDirty} />}
<form onSubmit={methods.handleSubmit((values) => processSubmission(values))}>{children}</form>
</FormProvider>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,5 @@ export interface Experiments {
"connector.form.sshSslImprovements": boolean;
"upcomingFeaturesPage.url": string;
"billing.newTrialPolicy": boolean;
"connection.updatedConnectionFlow": boolean;
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,15 @@ import { Navigate } from "react-router-dom";

import { DeleteBlock } from "components/common/DeleteBlock";
import { UpdateConnectionDataResidency } from "components/connection/UpdateConnectionDataResidency";
import { UpdateConnectionName } from "components/connection/UpdateConnectionName/UpdateConnectionName";
import { Button } from "components/ui/Button";
import { FlexContainer } from "components/ui/Flex";
import { Spinner } from "components/ui/Spinner";

import { ConnectionStatus } from "core/request/AirbyteClient";
import { PageTrackingCodes, useTrackPage } from "hooks/services/Analytics";
import { useConnectionEditService } from "hooks/services/ConnectionEdit/ConnectionEditService";
import { useExperiment } from "hooks/services/Experiment";
import { FeatureItem, useFeature } from "hooks/services/Feature";
import { useDeleteConnection } from "hooks/services/useConnectionHook";

Expand All @@ -25,15 +28,19 @@ export const ConnectionSettingsPageInner: React.FC = () => {
const { mutateAsync: deleteConnection } = useDeleteConnection();
const canUpdateDataResidency = useFeature(FeatureItem.AllowChangeDataGeographies);
const canSendSchemaUpdateNotifications = useFeature(FeatureItem.AllowAutoDetectSchema);
const isUpdatedConnectionFlow = useExperiment("connection.updatedConnectionFlow", false);

useTrackPage(PageTrackingCodes.CONNECTIONS_ITEM_SETTINGS);
const onDelete = () => deleteConnection(connection);

return (
<div className={styles.container}>
{canSendSchemaUpdateNotifications && <SchemaUpdateNotifications />}
{canUpdateDataResidency && <UpdateConnectionDataResidency />}
<DeleteBlock type="connection" onDelete={onDelete} />
<FlexContainer direction="column" justifyContent="flex-start">
{isUpdatedConnectionFlow && <UpdateConnectionName />}
{canSendSchemaUpdateNotifications && <SchemaUpdateNotifications />}
{canUpdateDataResidency && <UpdateConnectionDataResidency />}
<DeleteBlock type="connection" onDelete={onDelete} />
</FlexContainer>
<Disclosure>
{({ open }) => (
<>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
@use "scss/variables";
@use "scss/colors";

.container {
display: flex;
align-items: center;
margin-bottom: variables.$spacing-md;
}

0 comments on commit ac44a39

Please sign in to comment.