Skip to content

Commit

Permalink
Jamakase/update onboarding flow (airbytehq#5656)
Browse files Browse the repository at this point in the history
  • Loading branch information
jamakase authored Sep 16, 2021
1 parent 39e77f3 commit 8b40e13
Show file tree
Hide file tree
Showing 58 changed files with 1,592 additions and 200 deletions.
3 changes: 0 additions & 3 deletions airbyte-e2e-testing/cypress/integration/onboarding.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,6 @@ describe("Onboarding actions", () => {

cy.submit();

cy.url().should("include", `${Cypress.config().baseUrl}/onboarding`);
cy.get("button[data-id='skip-onboarding']").click();

cy.url().should("equal", `${Cypress.config().baseUrl}/`);
});
});
Binary file modified airbyte-webapp/public/newsletter.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions airbyte-webapp/public/play.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions airbyte-webapp/public/process-arrow.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions airbyte-webapp/public/rectangle.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added airbyte-webapp/public/rocket.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 11 additions & 0 deletions airbyte-webapp/public/stars-background.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions airbyte-webapp/public/video-background.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added airbyte-webapp/public/videoCover.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 4 additions & 1 deletion airbyte-webapp/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
usePickFirstWorkspace,
} from "hooks/services/useWorkspace";
import { Feature, FeatureService } from "hooks/services/Feature";
import { OnboardingServiceProvider } from "hooks/services/Onboarding";
import { ServicesProvider } from "core/servicesProvider";
import { useApiServices } from "core/defaultServices";
import { envConfigProvider, windowConfigProvider } from "./config";
Expand Down Expand Up @@ -97,7 +98,9 @@ const App: React.FC = () => {
<NotificationService>
<AppServices>
<AnalyticsInitializer>
<Routing />
<OnboardingServiceProvider>
<Routing />
</OnboardingServiceProvider>
</AnalyticsInitializer>
</AppServices>
</NotificationService>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import styled from "styled-components";

import { Button } from "components";
const BigButton = styled(Button)`
const BigButton = styled(Button)<{ shadow?: boolean }>`
font-size: 16px;
line-height: 19px;
padding: 10px 27px;
font-weight: 500;
box-shadow: ${({ shadow }) =>
shadow ? "0 8px 5px -5px rgba(0, 0, 0, 0.2)" : "none"};
`;

export default BigButton;
3 changes: 2 additions & 1 deletion airbyte-webapp/src/components/ContentCard/ContentCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ type IProps = {
title?: string | React.ReactNode;
className?: string;
onClick?: () => void;
full?: boolean;
};

const Title = styled(H5)`
Expand All @@ -19,7 +20,7 @@ const Title = styled(H5)`
`;

const ContentCard: React.FC<IProps> = (props) => (
<Card className={props.className} onClick={props.onClick}>
<Card className={props.className} onClick={props.onClick} full={props.full}>
{props.title ? <Title>{props.title}</Title> : null}
{props.children}
</Card>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,15 @@ type IProps = {
source: Source;
destination: Destination;
afterSubmitConnection?: () => void;
noTitles?: boolean;
};

const CreateConnectionContent: React.FC<IProps> = ({
source,
destination,
afterSubmitConnection,
additionBottomControls,
noTitles,
}) => {
const { createConnection } = useConnection();
const analyticsService = useAnalytics();
Expand Down Expand Up @@ -80,15 +82,23 @@ const CreateConnectionContent: React.FC<IProps> = ({

if (isLoading) {
return (
<ContentCard title={<FormattedMessage id="onboarding.setConnection" />}>
<ContentCard
title={
noTitles ? null : <FormattedMessage id="onboarding.setConnection" />
}
>
<LoadingSchema />
</ContentCard>
);
}

if (schemaErrorStatus) {
return (
<ContentCard title={<FormattedMessage id="onboarding.setConnection" />}>
<ContentCard
title={
noTitles ? null : <FormattedMessage id="onboarding.setConnection" />
}
>
<TryAfterErrorBlock
onClick={onDiscoverSchema}
additionControl={<SkipButton>{additionBottomControls}</SkipButton>}
Expand Down Expand Up @@ -130,7 +140,11 @@ const CreateConnectionContent: React.FC<IProps> = ({
};

return (
<ContentCard title={<FormattedMessage id="onboarding.setConnection" />}>
<ContentCard
title={
noTitles ? null : <FormattedMessage id="onboarding.setConnection" />
}
>
<Suspense fallback={<LoadingSchema />}>
<ConnectionForm
connection={connection}
Expand Down
14 changes: 11 additions & 3 deletions airbyte-webapp/src/components/Modal/Modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import ContentCard from "components/ContentCard";
export type IProps = {
title?: string | React.ReactNode;
onClose?: () => void;
clear?: boolean;
closeOnBackground?: boolean;
};

const fadeIn = keyframes`
Expand All @@ -27,7 +29,13 @@ const Overlay = styled.div`
z-index: 10;
`;

const Modal: React.FC<IProps> = ({ children, title, onClose }) => {
const Modal: React.FC<IProps> = ({
children,
title,
onClose,
clear,
closeOnBackground,
}) => {
const handleUserKeyPress = useCallback((event, closeModal) => {
const { keyCode } = event;
if (keyCode === 27) {
Expand All @@ -50,8 +58,8 @@ const Modal: React.FC<IProps> = ({ children, title, onClose }) => {
}, [handleUserKeyPress, onClose]);

return createPortal(
<Overlay>
<ContentCard title={title}>{children}</ContentCard>
<Overlay onClick={() => (closeOnBackground && onClose ? onClose() : null)}>
{clear ? children : <ContentCard title={title}>{children}</ContentCard>}
</Overlay>,
document.body
);
Expand Down
3 changes: 2 additions & 1 deletion airbyte-webapp/src/components/base/Card/Card.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import styled from "styled-components";

export const Card = styled.div`
export const Card = styled.div<{ full?: boolean }>`
width: ${({ full }) => (full ? "100%" : "auto")};
background: ${({ theme }) => theme.whiteColor};
border-radius: 10px;
box-shadow: 0 2px 4px ${({ theme }) => theme.cardShadowColor};
Expand Down
4 changes: 3 additions & 1 deletion airbyte-webapp/src/components/base/Titles/Titles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import styled from "styled-components";
type IProps = {
center?: boolean;
bold?: boolean;
parentColor?: boolean;
};

export const H1 = styled.h1<IProps>`
Expand All @@ -12,7 +13,8 @@ export const H1 = styled.h1<IProps>`
font-weight: ${(props) => (props.bold ? 600 : 500)};
display: block;
text-align: ${(props) => (props.center ? "center" : "left")};
color: ${({ theme }) => theme.textColor};
color: ${({ theme, parentColor }) =>
parentColor ? "inherid" : theme.textColor};
margin: 0;
`;

Expand Down
7 changes: 7 additions & 0 deletions airbyte-webapp/src/config/casesConfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[
"replicateMySQL",
"consolidateMarketing",
"consolidatePayment",
"buildDashboard",
"zoomCalls"
]
55 changes: 55 additions & 0 deletions airbyte-webapp/src/hooks/services/Onboarding/OnboardingService.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import React, { useContext, useMemo } from "react";
import { useLocalStorage } from "react-use";
import useWorkspace from "hooks/services/useWorkspace";
import casesConfig from "config/casesConfig.json";

type Context = {
feedbackPassed?: boolean;
passFeedback: () => void;
useCases?: string[];
skipCase: (skipId: string) => void;
};

export const OnboardingServiceContext = React.createContext<Context | null>(
null
);

export const OnboardingServiceProvider: React.FC = ({ children }) => {
const { workspace } = useWorkspace();
const [feedbackPassed, setFeedbackPassed] = useLocalStorage<boolean>(
`${workspace.workspaceId}/passFeedback`,
false
);
const [useCases, setUseCases] = useLocalStorage<string[]>(
`${workspace.workspaceId}/useCases`,
casesConfig
);

const ctx = useMemo<Context>(
() => ({
feedbackPassed,
passFeedback: () => setFeedbackPassed(true),
useCases,
skipCase: (skipId: string) =>
setUseCases(useCases?.filter((item) => item !== skipId)),
}),
[feedbackPassed, useCases]
);

return (
<OnboardingServiceContext.Provider value={ctx}>
{children}
</OnboardingServiceContext.Provider>
);
};

export const useOnboardingService = (): Context => {
const onboardingService = useContext(OnboardingServiceContext);
if (!onboardingService) {
throw new Error(
"useOnboardingService must be used within a OnboardingServiceProvider."
);
}

return onboardingService;
};
1 change: 1 addition & 0 deletions airbyte-webapp/src/hooks/services/Onboarding/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./OnboardingService";
32 changes: 28 additions & 4 deletions airbyte-webapp/src/hooks/services/useConnectionHook.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,11 @@ const useConnection = (): {
updateConnection: (conn: UpdateConnection) => Promise<Connection>;
updateStateConnection: (conn: UpdateStateConnection) => Promise<void>;
resetConnection: (connId: string) => Promise<void>;
syncConnection: (conn: Connection) => Promise<void>;
deleteConnection: (payload: { connectionId: string }) => Promise<void>;
} => {
const { push } = useRouter();
const { finishOnboarding, workspace } = useWorkspace();
const { workspace } = useWorkspace();
const analyticsService = useAnalytics();

const createConnectionResource = useFetcher(ConnectionResource.createShape());
Expand All @@ -116,6 +117,7 @@ const useConnection = (): {
);
const deleteConnectionResource = useFetcher(ConnectionResource.deleteShape());
const resetConnectionResource = useFetcher(ConnectionResource.reset());
const syncConnectionResource = useFetcher(ConnectionResource.syncShape());

const createConnection = async ({
values,
Expand Down Expand Up @@ -163,9 +165,6 @@ const useConnection = (): {
connector_destination_definition_id:
destinationDefinition?.destinationDefinitionId,
});
if (workspace.displaySetupWizard) {
await finishOnboarding();
}

return result;
} catch (e) {
Expand Down Expand Up @@ -229,12 +228,37 @@ const useConnection = (): {
[resetConnectionResource]
);

const syncConnection = async (connection: Connection) => {
analyticsService.track("Source - Action", {
action: "Full refresh sync",
connector_source: connection.source?.sourceName,
connector_source_id: connection.source?.sourceDefinitionId,
connector_destination: connection.destination?.name,
connector_destination_definition_id:
connection.destination?.destinationDefinitionId,
frequency: connection.schedule,
});
await syncConnectionResource({
connectionId: connection.connectionId,
});
};

return {
createConnection,
updateConnection,
updateStateConnection,
resetConnection,
deleteConnection,
syncConnection,
};
};

const useConnectionList = (): { connections: Connection[] } => {
const { workspace } = useWorkspace();
return useResource(ConnectionResource.listShape(), {
workspaceId: workspace.workspaceId,
});
};

export { useConnectionList };
export default useConnection;
30 changes: 30 additions & 0 deletions airbyte-webapp/src/hooks/services/useWorkspace.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import NotificationsResource, {
} from "core/resources/Notifications";
import { useGetService } from "core/servicesProvider";
import { useAnalytics } from "../useAnalytics";
import { Source } from "core/resources/Source";
import { Destination } from "core/resources/Destination";

export const usePickFirstWorkspace = (): Workspace => {
const { workspaces } = useResource(WorkspaceResource.listShape(), {});
Expand Down Expand Up @@ -44,6 +46,15 @@ const useWorkspace = (): {
securityUpdates: boolean;
}) => Promise<Workspace>;
finishOnboarding: (skipStep?: string) => Promise<void>;
sendFeedback: ({
feedback,
source,
destination,
}: {
feedback: string;
source: Source;
destination: Destination;
}) => Promise<void>;
} => {
const updateWorkspace = useFetcher(WorkspaceResource.updateShape());
const tryWebhookUrl = useFetcher(NotificationsResource.tryShape());
Expand Down Expand Up @@ -71,6 +82,24 @@ const useWorkspace = (): {
);
};

const sendFeedback = async ({
feedback,
source,
destination,
}: {
feedback: string;
source: Source;
destination: Destination;
}) => {
analyticsService.track("Onboarding Feedback", {
feedback,
connector_source_definition: source?.sourceName,
connector_source_definition_id: source?.sourceDefinitionId,
connector_destination_definition: destination?.destinationName,
connector_destination_definition_id: destination?.destinationDefinitionId,
});
};

const setInitialSetupConfig = async (data: {
email: string;
anonymousDataCollection: boolean;
Expand Down Expand Up @@ -147,6 +176,7 @@ const useWorkspace = (): {
updatePreferences,
updateWebhook,
testWebhook,
sendFeedback,
};
};

Expand Down
Loading

0 comments on commit 8b40e13

Please sign in to comment.