Skip to content

Commit 8b7878e

Browse files
Axon 72 new onboarding auth UI (#116)
* Checkpoint * UX works, but Auth not set up yet * callbacks for signin * call back working correctly * Cloud auth * server auth * AXON-72: updated auth flow styles * AXON-72: fix linting errors * AXON-72: add logo and use vscode native components * AXON-72: logo files * AXON-72: fixed stepping bug and handle back bug * AXON-72: added error logging when invalid sign in flow * AXON-72: remove console logs * AXON-72: clean up for readability + use constant values --------- Co-authored-by: Bryan Wieger <[email protected]>
1 parent e592f09 commit 8b7878e

20 files changed

+788
-102
lines changed

images/arrow-left.svg

+13
Loading

images/arrow-right.svg

+13
Loading

images/vscode-logo.png

42.3 KB
Loading

package-lock.json

+75-4
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -1414,6 +1414,7 @@
14141414
"@material-ui/styles": "^4.10.0",
14151415
"@segment/analytics-node": "^2.1.3",
14161416
"@types/mustache": "^4.0.1",
1417+
"@vscode/webview-ui-toolkit": "^1.4.0",
14171418
"awesome-debounce-promise": "^2.1.0",
14181419
"axios": "^1.7.4",
14191420
"axios-curlirize": "^1.3.4",

src/container.ts

+6-14
Original file line numberDiff line numberDiff line change
@@ -219,20 +219,12 @@ export class Container {
219219
analyticsApi: VSCAnalyticsApi,
220220
bitbucketHelper: CheckoutHelper,
221221
) {
222-
FeatureFlagClient.checkGate(Features.EnableNewUriHandler)
223-
.then((enabled) => {
224-
if (enabled) {
225-
console.log('Using new URI handler');
226-
context.subscriptions.push(AtlascodeUriHandler.create(analyticsApi, bitbucketHelper));
227-
} else {
228-
context.subscriptions.push(new LegacyAtlascodeUriHandler(analyticsApi, bitbucketHelper));
229-
}
230-
})
231-
.catch((err) => {
232-
// Not likely that we'd land here - but if anything goes wrong, default to legacy handler
233-
console.error(`Error checking feature flag ${Features.EnableNewUriHandler}: ${err}`);
234-
context.subscriptions.push(new LegacyAtlascodeUriHandler(analyticsApi, bitbucketHelper));
235-
});
222+
if (FeatureFlagClient.checkGate(Features.EnableNewUriHandler)) {
223+
console.log('Using new URI handler');
224+
context.subscriptions.push(AtlascodeUriHandler.create(analyticsApi, bitbucketHelper));
225+
} else {
226+
context.subscriptions.push(new LegacyAtlascodeUriHandler(analyticsApi, bitbucketHelper));
227+
}
236228
}
237229

238230
static initializeBitbucket(bbCtx: BitbucketContext) {

src/lib/ipc/fromUI/onboarding.ts

+2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export enum OnboardingActionType {
1313
ViewPullRequest = 'viewPullRequest',
1414
ClosePage = 'closePage',
1515
OpenSettings = 'openSettings',
16+
Error = 'error',
1617
}
1718

1819
export type OnboardingAction =
@@ -25,6 +26,7 @@ export type OnboardingAction =
2526
| ReducerAction<OnboardingActionType.ViewPullRequest>
2627
| ReducerAction<OnboardingActionType.ClosePage>
2728
| ReducerAction<OnboardingActionType.OpenSettings, OpenSettingsAction>
29+
| ReducerAction<OnboardingActionType.Error, { error: Error }>
2830
| CommonAction;
2931

3032
export interface AuthAction {

src/lib/ipc/toUI/onboarding.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,14 @@ export enum OnboardingMessageType {
88
Init = 'init',
99
Update = 'configUpdate',
1010
SitesUpdate = 'sitesAvailableUpdate',
11+
LoginResponse = 'loginResponse',
1112
}
1213

1314
export type OnboardingMessage =
1415
| ReducerAction<OnboardingMessageType.Init, OnboardingInitMessage>
1516
| ReducerAction<OnboardingMessageType.Update, OnboardingInitMessage>
16-
| ReducerAction<OnboardingMessageType.SitesUpdate, SitesUpdateMessage>;
17+
| ReducerAction<OnboardingMessageType.SitesUpdate, SitesUpdateMessage>
18+
| ReducerAction<OnboardingMessageType.LoginResponse>;
1719

1820
export type OnboardingResponse = any;
1921

src/lib/webview/controller/onboarding/onboardingWebviewController.ts

+7-2
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,9 @@ export class OnboardingWebviewController implements WebviewController<SectionCha
108108
});
109109
}
110110
} else {
111-
this._api.authenticateCloud(msg.siteInfo, this._onboardingUrl);
111+
await this._api.authenticateCloud(msg.siteInfo, this._onboardingUrl);
112112
}
113+
this.postMessage({ type: OnboardingMessageType.LoginResponse });
113114
this._analytics.fireAuthenticateButtonEvent(id, msg.siteInfo, isCloud);
114115
break;
115116
}
@@ -158,7 +159,11 @@ export class OnboardingWebviewController implements WebviewController<SectionCha
158159
this._analytics.fireMoreSettingsButtonEvent(id);
159160
break;
160161
}
161-
162+
case OnboardingActionType.Error: {
163+
this._logger.error(msg.error);
164+
this.postMessage({ type: CommonMessageType.Error, reason: formatError(msg.error, 'Onboarding Error') });
165+
break;
166+
}
162167
case CommonActionType.SendAnalytics:
163168
case CommonActionType.CopyLink:
164169
case CommonActionType.OpenJiraIssue:
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
import React, { useCallback } from 'react';
2+
import { Container, Typography, Box, Card, CardActionArea, CardContent } from '@material-ui/core';
3+
import { Product } from './types';
4+
import { VSCodeRadio, VSCodeButton } from '@vscode/webview-ui-toolkit/react';
5+
import { BitbucketOnboardingLogo } from '../icons/BitbucketOnboardingLogo';
6+
import { JiraOnboardingLogo } from '../icons/JiraOnboardingLogo';
7+
8+
type Props = {
9+
product: Product;
10+
handleOptionChange: (value: string) => void;
11+
executeSetup: () => void;
12+
handleBack?: () => void;
13+
signInText: string;
14+
valueSet: {
15+
cloud: string;
16+
server: string;
17+
none: string;
18+
};
19+
};
20+
const OnboardingRadio = ({
21+
checked,
22+
handleValueChange,
23+
value,
24+
title,
25+
description,
26+
}: {
27+
checked: string;
28+
handleValueChange: (v: string) => void;
29+
value: string;
30+
title: string;
31+
description?: string;
32+
}) => {
33+
return (
34+
<Card variant="outlined" style={{ width: '100%' }}>
35+
<CardActionArea
36+
onClick={() => {
37+
handleValueChange(value);
38+
}}
39+
>
40+
<CardContent style={formControlStyles}>
41+
<VSCodeRadio checked={checked === value} />
42+
<Box flexDirection={'column'}>
43+
<Typography style={{ fontWeight: 'bold' }}>{title}</Typography>
44+
{description && <Typography>{description}</Typography>}
45+
</Box>
46+
</CardContent>
47+
</CardActionArea>
48+
</Card>
49+
);
50+
};
51+
52+
export const JiraBitbucketOnboarding: React.FC<Props> = ({
53+
product,
54+
handleOptionChange,
55+
executeSetup,
56+
handleBack,
57+
signInText,
58+
valueSet,
59+
}) => {
60+
const [checked, setChecked] = React.useState(valueSet.cloud);
61+
62+
const handleValueChange = useCallback(
63+
(value: string) => {
64+
setChecked(value);
65+
handleOptionChange(value);
66+
},
67+
[handleOptionChange],
68+
);
69+
70+
return (
71+
<Container style={{ justifyContent: 'center' }} maxWidth="xs">
72+
<Box style={wrapperStyles} flexDirection="column">
73+
{product === 'Jira' ? <JiraOnboardingLogo /> : <BitbucketOnboardingLogo />}
74+
<Typography variant="h2">What version of {product} do you use?</Typography>
75+
<Box flexDirection="column" style={radioGroupStyles}>
76+
<OnboardingRadio
77+
checked={checked}
78+
handleValueChange={handleValueChange}
79+
value={valueSet.cloud}
80+
title="Cloud"
81+
description="For most of our users. The URL for accessing your site will typically be in the format mysite.atlassian.net"
82+
/>
83+
<OnboardingRadio
84+
checked={checked}
85+
handleValueChange={handleValueChange}
86+
value={valueSet.server}
87+
title="Server"
88+
description="For users with a custom site. The URL is usually a custom domain or IP address set up by your organization"
89+
/>
90+
<OnboardingRadio
91+
checked={checked}
92+
handleValueChange={handleValueChange}
93+
value={valueSet.none}
94+
title={product === 'Jira' ? "I don't have Jira" : "I don't have Bitbucket"}
95+
/>
96+
</Box>
97+
<Box
98+
style={{
99+
display: 'flex',
100+
justifyContent: 'space-between',
101+
alignItems: 'flex-start',
102+
alignSelf: 'stretch',
103+
}}
104+
>
105+
<VSCodeButton
106+
disabled={!handleBack}
107+
onClick={() => {
108+
handleBack && handleBack();
109+
}}
110+
appearance="secondary"
111+
>
112+
Back
113+
</VSCodeButton>
114+
<VSCodeButton
115+
onClick={() => {
116+
executeSetup();
117+
}}
118+
>
119+
{signInText}
120+
</VSCodeButton>
121+
</Box>
122+
</Box>
123+
</Container>
124+
);
125+
};
126+
127+
const wrapperStyles = {
128+
display: 'flex',
129+
justifyContent: 'center',
130+
alignItems: 'center',
131+
gap: '24px',
132+
};
133+
134+
const formControlStyles = {
135+
display: 'flex',
136+
padding: '12px',
137+
alignItems: 'flex-start',
138+
gap: '8px',
139+
alignSelf: 'stretch',
140+
borderRadius: '4px',
141+
};
142+
143+
const radioGroupStyles = {
144+
display: 'flex',
145+
gap: '8px',
146+
alignItems: 'flex-start',
147+
alignSelf: 'stretch',
148+
};

src/react/atlascode/common/types.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export type Product = 'Jira' | 'Bitbucket';

0 commit comments

Comments
 (0)