Skip to content

Commit

Permalink
Axon 72 new onboarding auth UI (#116)
Browse files Browse the repository at this point in the history
* 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]>
  • Loading branch information
cabella-dot and bwieger-atlassian-com authored Feb 14, 2025
1 parent e592f09 commit 8b7878e
Show file tree
Hide file tree
Showing 20 changed files with 788 additions and 102 deletions.
13 changes: 13 additions & 0 deletions images/arrow-left.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 13 additions & 0 deletions images/arrow-right.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 images/vscode-logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
79 changes: 75 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -1414,6 +1414,7 @@
"@material-ui/styles": "^4.10.0",
"@segment/analytics-node": "^2.1.3",
"@types/mustache": "^4.0.1",
"@vscode/webview-ui-toolkit": "^1.4.0",
"awesome-debounce-promise": "^2.1.0",
"axios": "^1.7.4",
"axios-curlirize": "^1.3.4",
Expand Down
20 changes: 6 additions & 14 deletions src/container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -219,20 +219,12 @@ export class Container {
analyticsApi: VSCAnalyticsApi,
bitbucketHelper: CheckoutHelper,
) {
FeatureFlagClient.checkGate(Features.EnableNewUriHandler)
.then((enabled) => {
if (enabled) {
console.log('Using new URI handler');
context.subscriptions.push(AtlascodeUriHandler.create(analyticsApi, bitbucketHelper));
} else {
context.subscriptions.push(new LegacyAtlascodeUriHandler(analyticsApi, bitbucketHelper));
}
})
.catch((err) => {
// Not likely that we'd land here - but if anything goes wrong, default to legacy handler
console.error(`Error checking feature flag ${Features.EnableNewUriHandler}: ${err}`);
context.subscriptions.push(new LegacyAtlascodeUriHandler(analyticsApi, bitbucketHelper));
});
if (FeatureFlagClient.checkGate(Features.EnableNewUriHandler)) {
console.log('Using new URI handler');
context.subscriptions.push(AtlascodeUriHandler.create(analyticsApi, bitbucketHelper));
} else {
context.subscriptions.push(new LegacyAtlascodeUriHandler(analyticsApi, bitbucketHelper));
}
}

static initializeBitbucket(bbCtx: BitbucketContext) {
Expand Down
2 changes: 2 additions & 0 deletions src/lib/ipc/fromUI/onboarding.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export enum OnboardingActionType {
ViewPullRequest = 'viewPullRequest',
ClosePage = 'closePage',
OpenSettings = 'openSettings',
Error = 'error',
}

export type OnboardingAction =
Expand All @@ -25,6 +26,7 @@ export type OnboardingAction =
| ReducerAction<OnboardingActionType.ViewPullRequest>
| ReducerAction<OnboardingActionType.ClosePage>
| ReducerAction<OnboardingActionType.OpenSettings, OpenSettingsAction>
| ReducerAction<OnboardingActionType.Error, { error: Error }>
| CommonAction;

export interface AuthAction {
Expand Down
4 changes: 3 additions & 1 deletion src/lib/ipc/toUI/onboarding.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ export enum OnboardingMessageType {
Init = 'init',
Update = 'configUpdate',
SitesUpdate = 'sitesAvailableUpdate',
LoginResponse = 'loginResponse',
}

export type OnboardingMessage =
| ReducerAction<OnboardingMessageType.Init, OnboardingInitMessage>
| ReducerAction<OnboardingMessageType.Update, OnboardingInitMessage>
| ReducerAction<OnboardingMessageType.SitesUpdate, SitesUpdateMessage>;
| ReducerAction<OnboardingMessageType.SitesUpdate, SitesUpdateMessage>
| ReducerAction<OnboardingMessageType.LoginResponse>;

export type OnboardingResponse = any;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,9 @@ export class OnboardingWebviewController implements WebviewController<SectionCha
});
}
} else {
this._api.authenticateCloud(msg.siteInfo, this._onboardingUrl);
await this._api.authenticateCloud(msg.siteInfo, this._onboardingUrl);
}
this.postMessage({ type: OnboardingMessageType.LoginResponse });
this._analytics.fireAuthenticateButtonEvent(id, msg.siteInfo, isCloud);
break;
}
Expand Down Expand Up @@ -158,7 +159,11 @@ export class OnboardingWebviewController implements WebviewController<SectionCha
this._analytics.fireMoreSettingsButtonEvent(id);
break;
}

case OnboardingActionType.Error: {
this._logger.error(msg.error);
this.postMessage({ type: CommonMessageType.Error, reason: formatError(msg.error, 'Onboarding Error') });
break;
}
case CommonActionType.SendAnalytics:
case CommonActionType.CopyLink:
case CommonActionType.OpenJiraIssue:
Expand Down
148 changes: 148 additions & 0 deletions src/react/atlascode/common/JiraBitbucketOnboarding.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
import React, { useCallback } from 'react';
import { Container, Typography, Box, Card, CardActionArea, CardContent } from '@material-ui/core';
import { Product } from './types';
import { VSCodeRadio, VSCodeButton } from '@vscode/webview-ui-toolkit/react';
import { BitbucketOnboardingLogo } from '../icons/BitbucketOnboardingLogo';
import { JiraOnboardingLogo } from '../icons/JiraOnboardingLogo';

type Props = {
product: Product;
handleOptionChange: (value: string) => void;
executeSetup: () => void;
handleBack?: () => void;
signInText: string;
valueSet: {
cloud: string;
server: string;
none: string;
};
};
const OnboardingRadio = ({
checked,
handleValueChange,
value,
title,
description,
}: {
checked: string;
handleValueChange: (v: string) => void;
value: string;
title: string;
description?: string;
}) => {
return (
<Card variant="outlined" style={{ width: '100%' }}>
<CardActionArea
onClick={() => {
handleValueChange(value);
}}
>
<CardContent style={formControlStyles}>
<VSCodeRadio checked={checked === value} />
<Box flexDirection={'column'}>
<Typography style={{ fontWeight: 'bold' }}>{title}</Typography>
{description && <Typography>{description}</Typography>}
</Box>
</CardContent>
</CardActionArea>
</Card>
);
};

export const JiraBitbucketOnboarding: React.FC<Props> = ({
product,
handleOptionChange,
executeSetup,
handleBack,
signInText,
valueSet,
}) => {
const [checked, setChecked] = React.useState(valueSet.cloud);

const handleValueChange = useCallback(
(value: string) => {
setChecked(value);
handleOptionChange(value);
},
[handleOptionChange],
);

return (
<Container style={{ justifyContent: 'center' }} maxWidth="xs">
<Box style={wrapperStyles} flexDirection="column">
{product === 'Jira' ? <JiraOnboardingLogo /> : <BitbucketOnboardingLogo />}
<Typography variant="h2">What version of {product} do you use?</Typography>
<Box flexDirection="column" style={radioGroupStyles}>
<OnboardingRadio
checked={checked}
handleValueChange={handleValueChange}
value={valueSet.cloud}
title="Cloud"
description="For most of our users. The URL for accessing your site will typically be in the format mysite.atlassian.net"
/>
<OnboardingRadio
checked={checked}
handleValueChange={handleValueChange}
value={valueSet.server}
title="Server"
description="For users with a custom site. The URL is usually a custom domain or IP address set up by your organization"
/>
<OnboardingRadio
checked={checked}
handleValueChange={handleValueChange}
value={valueSet.none}
title={product === 'Jira' ? "I don't have Jira" : "I don't have Bitbucket"}
/>
</Box>
<Box
style={{
display: 'flex',
justifyContent: 'space-between',
alignItems: 'flex-start',
alignSelf: 'stretch',
}}
>
<VSCodeButton
disabled={!handleBack}
onClick={() => {
handleBack && handleBack();
}}
appearance="secondary"
>
Back
</VSCodeButton>
<VSCodeButton
onClick={() => {
executeSetup();
}}
>
{signInText}
</VSCodeButton>
</Box>
</Box>
</Container>
);
};

const wrapperStyles = {
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
gap: '24px',
};

const formControlStyles = {
display: 'flex',
padding: '12px',
alignItems: 'flex-start',
gap: '8px',
alignSelf: 'stretch',
borderRadius: '4px',
};

const radioGroupStyles = {
display: 'flex',
gap: '8px',
alignItems: 'flex-start',
alignSelf: 'stretch',
};
1 change: 1 addition & 0 deletions src/react/atlascode/common/types.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export type Product = 'Jira' | 'Bitbucket';
Loading

0 comments on commit 8b7878e

Please sign in to comment.