Skip to content

Commit b98b5e7

Browse files
wrap ff around connect with linkedin (#17195)
* wrap ff around connect with linkedin * Fallback to setting profile email w/ primary email
1 parent 837b12a commit b98b5e7

File tree

5 files changed

+51
-24
lines changed

5 files changed

+51
-24
lines changed

components/dashboard/src/components/Button.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import classNames from "classnames";
88
import { FC, RefObject } from "react";
99
import SpinnerWhite from "../icons/SpinnerWhite.svg";
1010

11-
type Props = {
11+
export type ButtonProps = {
1212
// TODO: determine if we want danger.secondary
1313
type?: "primary" | "secondary" | "danger" | "danger.secondary";
1414
// TODO: determine how to handle small/medium (block does w-full atm)
@@ -25,7 +25,7 @@ type Props = {
2525
// Allow w/ or w/o handling event argument
2626
type ButtonOnClickHandler = React.DOMAttributes<HTMLButtonElement>["onClick"] | (() => void);
2727

28-
export const Button: FC<Props> = ({
28+
export const Button: FC<ButtonProps> = ({
2929
type = "primary",
3030
className,
3131
htmlType,

components/dashboard/src/contexts/FeatureFlagContext.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ const defaultFeatureFlags = {
3131
userGitAuthProviders: false,
3232
switchToPAYG: false,
3333
newSignupFlow: false,
34+
linkedinConnectionForOnboarding: false,
3435
};
3536

3637
const FeatureFlagContext = createContext<FeatureFlagsType>(defaultFeatureFlags);
@@ -51,6 +52,7 @@ const FeatureFlagContextProvider: React.FC = ({ children }) => {
5152
const [userGitAuthProviders, setUserGitAuthProviders] = useState<boolean>(false);
5253
const [switchToPAYG, setSwitchToPAYG] = useState<boolean>(false);
5354
const [newSignupFlow, setNewSignupFlow] = useState<boolean>(false);
55+
const [linkedinConnectionForOnboarding, setLinkedinConnectionForOnboarding] = useState<boolean>(false);
5456

5557
useEffect(() => {
5658
if (!user) return;
@@ -71,6 +73,7 @@ const FeatureFlagContextProvider: React.FC = ({ children }) => {
7173
userGitAuthProviders: { defaultValue: false, setter: setUserGitAuthProviders },
7274
switchToPAYG: { defaultValue: false, setter: setSwitchToPAYG },
7375
newSignupFlow: { defaultValue: false, setter: setNewSignupFlow },
76+
linkedinConnectionForOnboarding: { defaultValue: false, setter: setLinkedinConnectionForOnboarding },
7477
};
7578

7679
for (const [flagName, config] of Object.entries(featureFlags)) {
@@ -120,10 +123,12 @@ const FeatureFlagContextProvider: React.FC = ({ children }) => {
120123
userGitAuthProviders,
121124
newSignupFlow,
122125
switchToPAYG,
126+
linkedinConnectionForOnboarding,
123127
};
124128
}, [
125129
enablePersonalAccessTokens,
126130
isUsageBasedBillingEnabled,
131+
linkedinConnectionForOnboarding,
127132
newSignupFlow,
128133
oidcServiceEnabled,
129134
orgGitAuthProviders,

components/dashboard/src/onboarding/OnboardingStep.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
import { FC, FormEvent, useCallback } from "react";
88
import Alert from "../components/Alert";
9-
import { Button } from "../components/Button";
9+
import { Button, ButtonProps } from "../components/Button";
1010
import { Heading2, Subheading } from "../components/typography/headings";
1111

1212
type Props = {
@@ -17,7 +17,7 @@ type Props = {
1717
error?: string;
1818
onSubmit(): void;
1919
submitButtonText?: string;
20-
submitButtonType?: "primary" | "secondary" | "danger" | "danger.secondary";
20+
submitButtonType?: ButtonProps["type"];
2121
};
2222
export const OnboardingStep: FC<Props> = ({
2323
title,

components/dashboard/src/onboarding/StepUserInfo.tsx

Lines changed: 41 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,14 @@ import { useUpdateCurrentUserMutation } from "../data/current-user/update-mutati
1111
import { useOnBlurError } from "../hooks/use-onblur-error";
1212
import { OnboardingStep } from "./OnboardingStep";
1313
import { LinkedInBanner } from "./LinkedInBanner";
14+
import { useFeatureFlags } from "../contexts/FeatureFlagContext";
1415

1516
type Props = {
1617
user: User;
1718
onComplete(user: User): void;
1819
};
1920
export const StepUserInfo: FC<Props> = ({ user, onComplete }) => {
21+
const { linkedinConnectionForOnboarding } = useFeatureFlags();
2022
const updateUser = useUpdateCurrentUserMutation();
2123
// attempt to split provided name for default input values
2224
const { first, last } = getInitialNameParts(user);
@@ -37,7 +39,8 @@ export const StepUserInfo: FC<Props> = ({ user, onComplete }) => {
3739
...additionalData,
3840
profile: {
3941
...profile,
40-
emailAddress,
42+
// If still no email provided, default to "primary" email
43+
emailAddress: emailAddress || User.getPrimaryEmail(user),
4144
lastUpdatedDetailsNudge: new Date().toISOString(),
4245
},
4346
},
@@ -49,25 +52,32 @@ export const StepUserInfo: FC<Props> = ({ user, onComplete }) => {
4952
} catch (e) {
5053
console.error(e);
5154
}
52-
}, [emailAddress, firstName, lastName, onComplete, updateUser, user.additionalData]);
53-
54-
const onLinkedInSuccess = async (profile: LinkedInProfile) => {
55-
if (!firstName && profile.firstName) {
56-
setFirstName(profile.firstName);
57-
}
58-
if (!lastName && profile.lastName) {
59-
setLastName(profile.lastName);
60-
}
61-
if (!emailAddress && profile.emailAddress) {
62-
setEmailAddress(profile.emailAddress);
63-
}
64-
handleSubmit();
65-
};
55+
}, [emailAddress, firstName, lastName, onComplete, updateUser, user]);
56+
57+
const onLinkedInSuccess = useCallback(
58+
async (profile: LinkedInProfile) => {
59+
if (!firstName && profile.firstName) {
60+
setFirstName(profile.firstName);
61+
}
62+
if (!lastName && profile.lastName) {
63+
setLastName(profile.lastName);
64+
}
65+
if (!emailAddress && profile.emailAddress) {
66+
setEmailAddress(profile.emailAddress);
67+
}
68+
handleSubmit();
69+
},
70+
[emailAddress, firstName, handleSubmit, lastName],
71+
);
6672

6773
const firstNameError = useOnBlurError("Please enter a value", !!firstName);
6874
const lastNameError = useOnBlurError("Please enter a value", !!lastName);
75+
const emailError = useOnBlurError("Please enter your email address", !!emailAddress);
6976

70-
const isValid = [firstNameError, lastNameError].every((e) => e.isValid);
77+
const isValid =
78+
[firstNameError, lastNameError].every((e) => e.isValid) &&
79+
// If we're using LinkedIn, we don't need to validate the email input, otherwise we do
80+
(linkedinConnectionForOnboarding || (!linkedinConnectionForOnboarding && emailError.isValid));
7181

7282
return (
7383
<OnboardingStep
@@ -77,8 +87,8 @@ export const StepUserInfo: FC<Props> = ({ user, onComplete }) => {
7787
isValid={isValid}
7888
isSaving={updateUser.isLoading}
7989
onSubmit={handleSubmit}
80-
submitButtonText="Continue with 100 credits per month"
81-
submitButtonType="secondary"
90+
submitButtonText={linkedinConnectionForOnboarding ? "Continue with 100 credits per month" : undefined}
91+
submitButtonType={linkedinConnectionForOnboarding ? "secondary" : undefined}
8292
>
8393
{user.avatarUrl && (
8494
<div className="my-4 flex justify-center">
@@ -108,7 +118,19 @@ export const StepUserInfo: FC<Props> = ({ user, onComplete }) => {
108118
/>
109119
</div>
110120

111-
<LinkedInBanner onSuccess={onLinkedInSuccess} />
121+
{linkedinConnectionForOnboarding ? (
122+
<LinkedInBanner onSuccess={onLinkedInSuccess} />
123+
) : (
124+
<TextInputField
125+
value={emailAddress}
126+
label="Work Email"
127+
type="email"
128+
error={emailError.message}
129+
onBlur={emailError.onBlur}
130+
onChange={setEmailAddress}
131+
required
132+
/>
133+
)}
112134
</OnboardingStep>
113135
);
114136
};

components/dashboard/src/onboarding/UserOnboarding.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
*/
66

77
import { User } from "@gitpod/gitpod-protocol";
8-
import { FunctionComponent, useCallback, useContext, useEffect, useState } from "react";
8+
import { FunctionComponent, useCallback, useContext, useState } from "react";
99
import gitpodIcon from "../icons/gitpod.svg";
1010
import { Separator } from "../components/Separator";
1111
import { useHistory, useLocation } from "react-router";

0 commit comments

Comments
 (0)