From 22c107a317927b69891efceaff194343f2c076f2 Mon Sep 17 00:00:00 2001 From: Edmundo Ruiz Ghanem <168664+edmundito@users.noreply.github.com> Date: Thu, 28 Jul 2022 04:10:33 -0700 Subject: [PATCH] =?UTF-8?q?=F0=9F=AA=9F=20=F0=9F=8E=A8=20Update=20layout?= =?UTF-8?q?=20of=20create=20connection=20and=20replication=20settings=20pa?= =?UTF-8?q?ges=20to=20mach=20design=20(#14946)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update ConnectionForm to match design * Split sections into cards * Update connection name label to heading * Move create/edit buttons outside of card * Fix spacing to match design * Remove noTitles prop from CreateConnectionContent component * Update OperationsSection title to match the rest of the sections * Update connection name text to show that it's required * Divide streams into sections, center dont worry teext * Wrap SyncCatalogField in a div to prevent style impact from parent * Remove don't worry message from create connection page * Update resizing of left fields and right fields to match design. Now fields should stop at certain width of page * Move replication and tarnsformation section in connection form to its own card * Move OperationSection within same render condition as CreateControls * Apply design changes to main page with scroll, connection page title, and status main info * Update main page with scroll to only scroll x on the content, not the whole page * Update connection page title to all SCSS, add xl horizontal padding to match content * Update status main info to be more flexible on window resize * Remove extra div from status view that was adding extra horizontal margin to the card * Fix minor issues Co-authored-by: Tim Roes --- .../CreateConnectionContent.tsx | 35 ++- .../MainPageWithScroll.module.scss | 6 + .../MainPageWithScroll/MainPageWithScroll.tsx | 4 +- airbyte-webapp/src/locales/en.json | 4 +- .../ConnectionPageTitle.module.scss | 14 ++ .../components/ConnectionPageTitle.tsx | 84 +++---- .../components/ReplicationView.tsx | 42 ++-- .../components/StatusMainInfo.module.scss | 25 +- .../components/StatusMainInfo.tsx | 50 ++-- .../components/StatusView.tsx | 44 ++-- .../components/ConnectionStep.tsx | 1 - .../ConnectionForm/ConnectionForm.tsx | 226 ++++++++++-------- .../components/CreateControls.tsx | 2 +- .../components/OperationsSection.tsx | 23 +- .../components/SyncCatalogField.tsx | 52 ++-- 15 files changed, 329 insertions(+), 283 deletions(-) diff --git a/airbyte-webapp/src/components/CreateConnectionContent/CreateConnectionContent.tsx b/airbyte-webapp/src/components/CreateConnectionContent/CreateConnectionContent.tsx index fce61d499393..3a0eebf33a34 100644 --- a/airbyte-webapp/src/components/CreateConnectionContent/CreateConnectionContent.tsx +++ b/airbyte-webapp/src/components/CreateConnectionContent/CreateConnectionContent.tsx @@ -1,5 +1,4 @@ import React, { Suspense, useMemo, useState } from "react"; -import { FormattedMessage } from "react-intl"; import styled from "styled-components"; import { ContentCard } from "components"; @@ -32,7 +31,6 @@ interface CreateConnectionContentProps { source: SourceRead; destination: DestinationRead; afterSubmitConnection?: (connection: WebBackendConnectionRead) => void; - noTitles?: boolean; } const CreateConnectionContent: React.FC = ({ @@ -40,7 +38,6 @@ const CreateConnectionContent: React.FC = ({ destination, afterSubmitConnection, additionBottomControls, - noTitles, }) => { const { mutateAsync: createConnection } = useCreateConnection(); const trackNewConnectionAction = useTrackAction( @@ -108,7 +105,7 @@ const CreateConnectionContent: React.FC = ({ if (schemaErrorStatus) { const job = LogsRequestError.extractJobInfo(schemaErrorStatus); return ( - }> + {additionBottomControls}} @@ -118,23 +115,19 @@ const CreateConnectionContent: React.FC = ({ ); } - return ( - }> - {isLoading ? ( - - ) : ( - }> - - - )} - + return isLoading ? ( + + ) : ( + }> + + ); }; diff --git a/airbyte-webapp/src/components/MainPageWithScroll/MainPageWithScroll.module.scss b/airbyte-webapp/src/components/MainPageWithScroll/MainPageWithScroll.module.scss index 36bc15088afe..efe49b75b84d 100644 --- a/airbyte-webapp/src/components/MainPageWithScroll/MainPageWithScroll.module.scss +++ b/airbyte-webapp/src/components/MainPageWithScroll/MainPageWithScroll.module.scss @@ -2,11 +2,17 @@ .page { overflow-y: hidden; + width: 100%; height: 100%; display: flex; flex-direction: column; } +.contentContainer { + max-width: 100%; + overflow-x: auto; +} + .content { overflow-y: auto; height: 100%; diff --git a/airbyte-webapp/src/components/MainPageWithScroll/MainPageWithScroll.tsx b/airbyte-webapp/src/components/MainPageWithScroll/MainPageWithScroll.tsx index 7b233f31e1f4..58bcb7fc00ef 100644 --- a/airbyte-webapp/src/components/MainPageWithScroll/MainPageWithScroll.tsx +++ b/airbyte-webapp/src/components/MainPageWithScroll/MainPageWithScroll.tsx @@ -19,7 +19,9 @@ const MainPageWithScroll: React.FC = ({ headTitle, page {headTitle} {pageTitle} -
{children}
+
+
{children}
+
); }; diff --git a/airbyte-webapp/src/locales/en.json b/airbyte-webapp/src/locales/en.json index 8dcf26305a3b..93c417d86ee2 100644 --- a/airbyte-webapp/src/locales/en.json +++ b/airbyte-webapp/src/locales/en.json @@ -34,7 +34,7 @@ "form.noConnectorFound": "No matching connector found", "form.sourceName.placeholder": "Your source name", "form.destinationName.placeholder": "Your destination name", - "form.connectionName": "Name", + "form.connectionName": "Connection name*", "form.connectionName.placeholder": "Name", "form.name": "Name *", "form.sourceName.message": "Pick a name to help you identify this source in Airbyte", @@ -50,7 +50,6 @@ "form.cursorField": "Cursor field", "form.dataSync": "Activate the streams you want to sync", "form.dataSync.readonly": "Activated streams", - "form.dataSync.message": "Don’t worry! You’ll be able to change this later on.", "form.cancel": "Cancel", "form.canceling": "Canceling", "form.submit": "Submit", @@ -202,7 +201,6 @@ "onboarding.destinationSetUp": "Set up the destination", "onboarding.destinationSetUp.buttonText": "Set up destination", "onboarding.setUpConnection": "Set up connection", - "onboarding.setConnection": "Set up the connection", "onboarding.instructionsLink": "See full instructions how to connect {name}", "onboarding.fetchingSchema": "We are fetching the schema of your data source. \nThis should take less than a minute, but may take a few minutes on slow internet connections or data sources with a large amount of tables.", "onboarding.tutorial": "Check how you can sync PostgreSQL databases in minutes", diff --git a/airbyte-webapp/src/pages/ConnectionPage/pages/ConnectionItemPage/components/ConnectionPageTitle.module.scss b/airbyte-webapp/src/pages/ConnectionPage/pages/ConnectionItemPage/components/ConnectionPageTitle.module.scss index 7290547bc3d4..ff4391e20ec5 100644 --- a/airbyte-webapp/src/pages/ConnectionPage/pages/ConnectionItemPage/components/ConnectionPageTitle.module.scss +++ b/airbyte-webapp/src/pages/ConnectionPage/pages/ConnectionItemPage/components/ConnectionPageTitle.module.scss @@ -1,6 +1,20 @@ @use "../../../../../scss/variables" as vars; +.container { + text-align: center; + padding: vars.$spacing-lg vars.$spacing-xl; +} + .connectionDeleted { max-width: vars.$width-modal-md; margin: vars.$spacing-lg auto; } + +.statusContainer { + margin: 18px 0; + font-size: 15px; + font-weight: bold; + display: flex; + align-items: center; + justify-content: center; +} diff --git a/airbyte-webapp/src/pages/ConnectionPage/pages/ConnectionItemPage/components/ConnectionPageTitle.tsx b/airbyte-webapp/src/pages/ConnectionPage/pages/ConnectionItemPage/components/ConnectionPageTitle.tsx index 145fb3024f0b..dee77d5d9e68 100644 --- a/airbyte-webapp/src/pages/ConnectionPage/pages/ConnectionItemPage/components/ConnectionPageTitle.tsx +++ b/airbyte-webapp/src/pages/ConnectionPage/pages/ConnectionItemPage/components/ConnectionPageTitle.tsx @@ -1,7 +1,6 @@ import { faTrash } from "@fortawesome/free-solid-svg-icons"; -import React from "react"; +import React, { useCallback, useMemo } from "react"; import { FormattedMessage } from "react-intl"; -import styled from "styled-components"; import { H6 } from "components"; import { InfoBox } from "components/InfoBox"; @@ -23,20 +22,6 @@ interface ConnectionPageTitleProps { onStatusUpdating?: (updating: boolean) => void; } -const Title = styled.div` - text-align: center; - padding: 21px 0 10px; -`; - -const Links = styled.div` - margin: 18px 0; - font-size: 15px; - font-weight: bold; - display: flex; - align-items: center; - justify-content: center; -`; - const ConnectionPageTitle: React.FC = ({ source, destination, @@ -46,37 +31,44 @@ const ConnectionPageTitle: React.FC = ({ }) => { const { push } = useRouter<{ id: string }>(); - const steps = [ - { - id: ConnectionSettingsRoutes.STATUS, - name: , - }, - { - id: ConnectionSettingsRoutes.REPLICATION, - name: , - }, - { - id: ConnectionSettingsRoutes.TRANSFORMATION, - name: , - }, - ]; + const steps = useMemo(() => { + const steps = [ + { + id: ConnectionSettingsRoutes.STATUS, + name: , + }, + { + id: ConnectionSettingsRoutes.REPLICATION, + name: , + }, + { + id: ConnectionSettingsRoutes.TRANSFORMATION, + name: , + }, + ]; + + connection.status !== ConnectionStatus.deprecated && + steps.push({ + id: ConnectionSettingsRoutes.SETTINGS, + name: , + }); - connection.status !== ConnectionStatus.deprecated && - steps.push({ - id: ConnectionSettingsRoutes.SETTINGS, - name: , - }); + return steps; + }, [connection.status]); - const onSelectStep = (id: string) => { - if (id === ConnectionSettingsRoutes.STATUS) { - push(""); - } else { - push(id); - } - }; + const onSelectStep = useCallback( + (id: string) => { + if (id === ConnectionSettingsRoutes.STATUS) { + push(""); + } else { + push(id); + } + }, + [push] + ); return ( - + <div className={styles.container}> {connection.status === ConnectionStatus.deprecated && ( <InfoBox className={styles.connectionDeleted} icon={faTrash}> <FormattedMessage id="connection.connectionDeletedView" /> @@ -86,16 +78,16 @@ const ConnectionPageTitle: React.FC<ConnectionPageTitleProps> = ({ <FormattedMessage id="connection.title" /> </H6> <ConnectionName connection={connection} /> - <Links> + <div className={styles.statusContainer}> <StatusMainInfo connection={connection} source={source} destination={destination} onStatusUpdating={onStatusUpdating} /> - </Links> + </div> <StepsMenu lightMode data={steps} onSelect={onSelectStep} activeStep={currentStep} /> - + ); }; diff --git a/airbyte-webapp/src/pages/ConnectionPage/pages/ConnectionItemPage/components/ReplicationView.tsx b/airbyte-webapp/src/pages/ConnectionPage/pages/ConnectionItemPage/components/ReplicationView.tsx index 99d0a1a540de..81a6ac960531 100644 --- a/airbyte-webapp/src/pages/ConnectionPage/pages/ConnectionItemPage/components/ReplicationView.tsx +++ b/airbyte-webapp/src/pages/ConnectionPage/pages/ConnectionItemPage/components/ReplicationView.tsx @@ -5,7 +5,7 @@ import { FormattedMessage, useIntl } from "react-intl"; import { useAsyncFn, useUnmount } from "react-use"; import styled from "styled-components"; -import { Button, Card, LabeledSwitch, ModalBody, ModalFooter } from "components"; +import { Button, LabeledSwitch, ModalBody, ModalFooter } from "components"; import LoadingSchema from "components/LoadingSchema"; import { toWebBackendConnectionUpdate } from "core/domain/connection"; @@ -187,27 +187,25 @@ export const ReplicationView: React.FC = ({ onAfterSaveSch return ( - - {!isRefreshingCatalog && connection ? ( - } - onCancel={onCancelConnectionFormEdit} - canSubmitUntouchedForm={activeUpdatingSchemaMode} - additionalSchemaControl={ - - } - onChangeValues={setConnectionFormValues} - /> - ) : ( - - )} - + {!isRefreshingCatalog && connection ? ( + } + onCancel={onCancelConnectionFormEdit} + canSubmitUntouchedForm={activeUpdatingSchemaMode} + additionalSchemaControl={ + + } + onChangeValues={setConnectionFormValues} + /> + ) : ( + + )} ); }; diff --git a/airbyte-webapp/src/pages/ConnectionPage/pages/ConnectionItemPage/components/StatusMainInfo.module.scss b/airbyte-webapp/src/pages/ConnectionPage/pages/ConnectionItemPage/components/StatusMainInfo.module.scss index 93959bcf3899..7a738023b764 100644 --- a/airbyte-webapp/src/pages/ConnectionPage/pages/ConnectionItemPage/components/StatusMainInfo.module.scss +++ b/airbyte-webapp/src/pages/ConnectionPage/pages/ConnectionItemPage/components/StatusMainInfo.module.scss @@ -11,12 +11,31 @@ } } -.container { - width: 650px; +.container, +.pathContainer { display: flex; + flex-wrap: wrap; + flex-direction: row; justify-content: space-between; + align-items: center; +} + +.pathContainer, +.pathContainer > *, +.enabledControlContainer { + flex-grow: 1; +} + +.container { + width: 650px; + flex-wrap: wrap; padding: variables.$spacing-md variables.$spacing-xl; background-color: white; border-radius: 10px; - align-items: center; +} + +.enabledControlContainer { + display: flex; + justify-content: space-around; + padding: variables.$spacing-md; } diff --git a/airbyte-webapp/src/pages/ConnectionPage/pages/ConnectionItemPage/components/StatusMainInfo.tsx b/airbyte-webapp/src/pages/ConnectionPage/pages/ConnectionItemPage/components/StatusMainInfo.tsx index cf4bcefa91e2..66c67affbae2 100644 --- a/airbyte-webapp/src/pages/ConnectionPage/pages/ConnectionItemPage/components/StatusMainInfo.tsx +++ b/airbyte-webapp/src/pages/ConnectionPage/pages/ConnectionItemPage/components/StatusMainInfo.tsx @@ -39,30 +39,34 @@ export const StatusMainInfo: React.FC = ({ return (
- - - - - - - +
+ + + + + + + +
{connection.status !== ConnectionStatus.deprecated && ( - +
+ +
)}
); diff --git a/airbyte-webapp/src/pages/ConnectionPage/pages/ConnectionItemPage/components/StatusView.tsx b/airbyte-webapp/src/pages/ConnectionPage/pages/ConnectionItemPage/components/StatusView.tsx index f30153b47e57..7cc3f06a4541 100644 --- a/airbyte-webapp/src/pages/ConnectionPage/pages/ConnectionItemPage/components/StatusView.tsx +++ b/airbyte-webapp/src/pages/ConnectionPage/pages/ConnectionItemPage/components/StatusView.tsx @@ -23,10 +23,6 @@ interface StatusViewProps { isStatusUpdating?: boolean; } -const Content = styled.div` - margin: 0 10px; -`; - const StyledContentCard = styled(ContentCard)` margin-bottom: 20px; `; @@ -109,27 +105,25 @@ const StatusView: React.FC = ({ connection, isStatusUpdating }) ); return ( - - - - {connection.status === ConnectionStatus.active && ( -
- - - - - - -
- )} - - } - > - {jobs.length ? : } />} -
-
+ + + {connection.status === ConnectionStatus.active && ( +
+ + + + + + +
+ )} + + } + > + {jobs.length ? : } />} +
); }; diff --git a/airbyte-webapp/src/pages/OnboardingPage/components/ConnectionStep.tsx b/airbyte-webapp/src/pages/OnboardingPage/components/ConnectionStep.tsx index 67a7bf3e000e..95e860691a5a 100644 --- a/airbyte-webapp/src/pages/OnboardingPage/components/ConnectionStep.tsx +++ b/airbyte-webapp/src/pages/OnboardingPage/components/ConnectionStep.tsx @@ -15,7 +15,6 @@ const ConnectionStep: React.FC = ({ onNextStep: afterSubmitConnection }) return ( div:not(:last-child) { - margin-bottom: 20px; + &:not(:last-child) { + box-shadow: 0 1px 0 rgba(139, 139, 160, 0.25); } `; -const Header = styled(H5)` - margin-bottom: 16px; +interface SectionProps { + title?: React.ReactNode; +} + +const LabelHeading = styled(H5)` + line-height: 16px; + display: inline; `; -const Section: React.FC<{ title: React.ReactNode }> = (props) => ( - -
{props.title}
- {props.children} -
+const Section: React.FC = ({ title, children }) => ( + + + {title &&
{title}
} + {children} +
+
); const FormContainer = styled(Form)` - & > ${StyledSection}:not(:last-child) { - box-shadow: 0 1px 0 rgba(139, 139, 160, 0.25); - } + display: flex; + flex-direction: column; + gap: 10px; `; export interface ConnectionFormSubmitResult { @@ -193,7 +202,7 @@ const ConnectionForm: React.FC = ({ {!isEditMode && ( - +
{({ field, meta }: FieldProps) => ( @@ -201,9 +210,11 @@ const ConnectionForm: React.FC = ({ + + + } message={formatMessage({ id: "form.connectionName.message", })} @@ -223,7 +234,7 @@ const ConnectionForm: React.FC = ({ )} - +
)}
}> @@ -256,104 +267,113 @@ const ConnectionForm: React.FC = ({ )}
-
}> - - - - {values.namespaceDefinition === NamespaceDefinitionType.customformat && ( - - {({ field, meta }: FieldProps) => ( + + +
+ +
+ + + + {values.namespaceDefinition === NamespaceDefinitionType.customformat && ( + + {({ field, meta }: FieldProps) => ( + + + } + message={} + /> + + + + + + )} + + )} + + {({ field }: FieldProps) => ( - } - message={} + label={formatMessage({ + id: "form.prefix", + })} + message={formatMessage({ + id: "form.prefix.message", + })} /> - + )} - )} - - {({ field }: FieldProps) => ( - - - - - - - - - )} - - + + + +
+ {mode === "edit" && ( + { + resetForm(); + onCancel?.(); + }} + successMessage={successMessage} + errorMessage={errorMessage || !isValid ? formatMessage({ id: "connectionForm.validation.error" }) : null} + enableControls={canSubmitUntouchedForm} /> - {mode === "edit" && ( - + ( + + {children} + + )} + destDefinition={destDefinition} + onStartEditTransformation={toggleEditingTransformation} + onEndEditTransformation={toggleEditingTransformation} + /> + { - resetForm(); - onCancel?.(); - }} - successMessage={successMessage} + isValid={isValid && !editingTransformation} errorMessage={ errorMessage || !isValid ? formatMessage({ id: "connectionForm.validation.error" }) : null } - enableControls={canSubmitUntouchedForm} /> - )} - {mode === "create" && ( - <> - - } /> - - - )} -
+ + )} )} diff --git a/airbyte-webapp/src/views/Connection/ConnectionForm/components/CreateControls.tsx b/airbyte-webapp/src/views/Connection/ConnectionForm/components/CreateControls.tsx index 1df5e6f30d4d..a8eaea1c0c83 100644 --- a/airbyte-webapp/src/views/Connection/ConnectionForm/components/CreateControls.tsx +++ b/airbyte-webapp/src/views/Connection/ConnectionForm/components/CreateControls.tsx @@ -12,7 +12,7 @@ interface CreateControlsProps { } const ButtonContainer = styled.div` - margin-top: 34px; + padding: 15px 0; display: flex; align-items: center; justify-content: space-between; diff --git a/airbyte-webapp/src/views/Connection/ConnectionForm/components/OperationsSection.tsx b/airbyte-webapp/src/views/Connection/ConnectionForm/components/OperationsSection.tsx index 1f5090b43abc..70e6bf60f739 100644 --- a/airbyte-webapp/src/views/Connection/ConnectionForm/components/OperationsSection.tsx +++ b/airbyte-webapp/src/views/Connection/ConnectionForm/components/OperationsSection.tsx @@ -1,7 +1,8 @@ import { Field, FieldArray } from "formik"; import React from "react"; import { useIntl } from "react-intl"; -import styled from "styled-components"; + +import { H5 } from "components"; import { FeatureItem, useFeature } from "hooks/services/Feature"; @@ -10,22 +11,18 @@ import { useDefaultTransformation } from "../formConfig"; import { NormalizationField } from "./NormalizationField"; import { TransformationField } from "./TransformationField"; -const SectionTitle = styled.div` - font-weight: bold; - font-size: 14px; - line-height: 17px; -`; - interface OperationsSectionProps { destDefinition: DestinationDefinitionSpecificationRead; onStartEditTransformation?: () => void; onEndEditTransformation?: () => void; + wrapper: React.ComponentType; } export const OperationsSection: React.FC = ({ destDefinition, onStartEditTransformation, onEndEditTransformation, + wrapper: Wrapper, }) => { const { formatMessage } = useIntl(); @@ -34,17 +31,21 @@ export const OperationsSection: React.FC = ({ const defaultTransformation = useDefaultTransformation(); + if (!supportsNormalization && !supportsTransformations) { + return null; + } + return ( - <> + {supportsNormalization || supportsTransformations ? ( - +
{[ supportsNormalization && formatMessage({ id: "connectionForm.normalization.title" }), supportsTransformations && formatMessage({ id: "connectionForm.transformation.title" }), ] .filter(Boolean) .join(" & ")} - +
) : null} {supportsNormalization && } {supportsTransformations && ( @@ -59,6 +60,6 @@ export const OperationsSection: React.FC = ({ )} )} - +
); }; diff --git a/airbyte-webapp/src/views/Connection/ConnectionForm/components/SyncCatalogField.tsx b/airbyte-webapp/src/views/Connection/ConnectionForm/components/SyncCatalogField.tsx index ca70f384fe3e..270142379ea2 100644 --- a/airbyte-webapp/src/views/Connection/ConnectionForm/components/SyncCatalogField.tsx +++ b/airbyte-webapp/src/views/Connection/ConnectionForm/components/SyncCatalogField.tsx @@ -4,7 +4,7 @@ import React, { useCallback, useMemo, useState } from "react"; import { FormattedMessage } from "react-intl"; import styled from "styled-components"; -import { CheckBox } from "components"; +import { CheckBox, H5 } from "components"; import { Cell, Header } from "components/SimpleTableComponents"; import { useConfig } from "config"; @@ -209,28 +209,34 @@ const SyncCatalogField: React.FC = ({ return ( - - {mode !== "readonly" ? ( - <> - - {additionalControl} - - ) : ( - - )} - - {mode !== "readonly" && } - - - - - - +
+ + {mode !== "readonly" ? ( + <> +
+ +
+ {additionalControl} + + ) : ( +
+ +
+ )} +
+ {mode !== "readonly" && } + + + + + + +
); };