Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support tidb cloud oauth #1806

Merged
merged 7 commits into from
Oct 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ Insights about the **code update frequency & degree of popularity** from reposit
</div>

**Examples**:

* [React](https://ossinsight.io/analyze/facebook/react)
* [TiDB](https://ossinsight.io/analyze/pingcap/tidb)
* [web3.js](https://ossinsight.io/analyze/web3/web3.js)
Expand Down
114 changes: 36 additions & 78 deletions web/src/pages/open-source-heroes/_components/ClaimForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ type Check = {
githubId: number;
isClaimed: boolean;
isEligible: boolean;
isLinkTiDBCloud: boolean;
claimedTenantId?: number;
};

type Tenant = {
Expand All @@ -23,6 +25,7 @@ type Tenant = {

export function ClaimForm () {
const [claimedThisSession, setClaimedThisSession] = useState(false);
const [shouldAutoClaim, setShouldAutoClaim] = useState(false);
const { getAccessTokenSilently } = useResponsiveAuth0();
const { gtagEvent } = useGtag();

Expand All @@ -37,12 +40,12 @@ export function ClaimForm () {
return res;
}));

const { data: tenants } = useSWR('/api/v1/serverless-credits-campaign/tenants', async url => await giftClientWithoutCache.get<any, Tenant[]>(url, {
const { data: tenants, isValidating: isTenantValidating } = useSWR(check?.isLinkTiDBCloud && '/api/v1/serverless-credits-campaign/tenants', async url => await giftClientWithoutCache.get<any, Tenant[]>(url, {
withCredentials: true,
headers: {
Authorization: `Bearer ${await getAccessTokenSilently({ connection: 'github' })}`,
},
}));
}), { errorRetryCount: 0 });

const handleClaim = async (id: string) => {
gtagEvent('github_campaign_claim', {});
Expand All @@ -61,26 +64,26 @@ export function ClaimForm () {
});
};

useEffect(() => {
if (shouldAutoClaim && check && tenants && tenants.length > 0 && !check.isClaimed) {
void handleClaim(tenants[0].id);
}
}, [check, tenants, shouldAutoClaim]);

let children: ReactNode;

if (check && tenants) {
if (check && (tenants != null || !isTenantValidating)) {
if (check.isClaimed) {
if (claimedThisSession) {
children = <ClaimedThisSession check={check} />;
} else {
children = <Claimed check={check} />;
}
} else if (check.isEligible) {
if (tenants.length === 0) {
children = <EligibleNoTenants check={check} />;
} else {
children = <Eligible check={check} onClaim={handleClaim} tenants={tenants} />;
}
} else {
if (tenants.length === 0) {
children = <NotEligibleNoTenant />;
if (tenants) {
children = <Eligible check={check} onClaim={handleClaim} tenants={tenants} />;
} else {
children = <NotEligible tenants={tenants} />;
children = <EligibleNoTenants check={check} onShouldAutoClaim={() => setShouldAutoClaim(true)} />;
}
}

Expand All @@ -95,10 +98,6 @@ export function ClaimForm () {
// <br />
// <Eligible check={check} onClaim={handleClaim} tenants={tenants} />
// <br />
// <NotEligibleNoTenant />
// <br />
// <NotEligible tenants={tenants} />
// <br />
// <Checking />
// </>
// );
Expand Down Expand Up @@ -141,7 +140,7 @@ function ClaimedThisSession ({ check }: { check: Check }) {
</ClaimContent>
<Box sx={{ position: 'relative', width: 'max-content', maxWidth: '100%', mt: 8, display: 'flex', flexDirection: 'column', gap: 2, px: 2, alignItems: 'center' }}>
<ShareButton />
<TiDBCloudButton variant="text">
<TiDBCloudButton variant="text" org={check.claimedTenantId}>
Start Building with TiDB Cloud!
</TiDBCloudButton>
</Box>
Expand All @@ -164,61 +163,15 @@ function Claimed ({ check }: { check: Check }) {
</ClaimContent>
<Box sx={{ position: 'relative', width: 'max-content', maxWidth: '100%', mt: 8, display: 'flex', flexDirection: 'column', gap: 2, px: 2, alignItems: 'center' }}>
<ShareButton />
<TiDBCloudButton variant="text">
<TiDBCloudButton variant="text" org={check.claimedTenantId}>
Start Building with TiDB Cloud!
</TiDBCloudButton>
</Box>
</>
);
}

function NotEligible ({ tenants }: { tenants: Tenant[] }) {
const { user } = useResponsiveAuth0();

return (
<>
{badIcon}
<ClaimContent>
Hi <em>{user?.nickname ?? user?.name}</em>
<br />
Thanks for being an open-source hero! As a token of our appreciation, you have 25GB of free storage and 250 million reads available on TiDB Serverless.
<br />
Share this great news with your friends and start building something amazing.
</ClaimContent>
<Box sx={{ position: 'relative', width: 'max-content', maxWidth: '100%', mt: 8, display: 'flex', flexDirection: 'column', gap: 2, px: 2, alignItems: 'center' }}>
<ShareButton />
<TiDBCloudButton variant="text">
Login to TiDB Cloud
</TiDBCloudButton>
</Box>
</>
);
}

function NotEligibleNoTenant () {
const { user } = useResponsiveAuth0();

return (
<>
{badIcon}
<ClaimContent>
Hi <em>{user?.nickname ?? user?.name}</em>
<br />
Want to try TiDB Serverless for free?
<br />
Create a new TiDB Cloud account and enjoy 25GB of free storage to start building your applications.
</ClaimContent>
<Box sx={{ position: 'relative', width: 'max-content', maxWidth: '100%', mt: 8, display: 'flex', gap: 2, px: 2, flexDirection: 'column', alignItems: 'center' }}>
<ShareButton />
<TiDBCloudButton variant="text">
Create TiDB Cloud Account
</TiDBCloudButton>
</Box>
</>
);
}

function EligibleNoTenants ({ check }: { check: Check }) {
function EligibleNoTenants ({ check, onShouldAutoClaim }: { check: Check, onShouldAutoClaim: () => void }) {
const { user } = useResponsiveAuth0();

return (
Expand All @@ -227,15 +180,20 @@ function EligibleNoTenants ({ check }: { check: Check }) {
<ClaimContent>
Hi <em>{user?.nickname ?? user?.name}</em>
<br />
Awesome! You&#39;re eligible for <strong>{check.credits} in TiDB Serverless</strong> credits for your contributions to the open-source community.
Awesome! You&#39;re eligible for <strong>{check.credits} in TiDB Serverless</strong> credits.
<br />
Create a new TiDB Cloud account and your credits will be waiting for you.
</ClaimContent>
<TiDBCloudButton
variant="contained"
sx={{ background: 'white', mt: 8, '&:hover': { background: 'rgba(255,255,255,0.8)', color: 'black' } }}
link
pop
onClick={() => {
onShouldAutoClaim();
}}
>
Sign up to TiDB Cloud
Connect to TiDB Cloud
</TiDBCloudButton>
<Button sx={{ mt: 4, px: 8 }} color="primary" variant="contained" disabled>
Claim Credits
Expand Down Expand Up @@ -277,7 +235,7 @@ function Eligible ({ tenants, check, onClaim }: { tenants: Tenant[], check: Chec
<ClaimContent>
Hi <em>{user?.nickname ?? user?.name}</em>
<br />
Congratulations! You&#39;re eligible for <strong>{check.credits} in TiDB Serverless</strong> credits for your contributions to the open-source community.
Congratulations! You&#39;re eligible for <strong>{check.credits} in TiDB Serverless</strong> credits.
<br />
Please select your existing TiDB Cloud account to apply these credits.
</ClaimContent>
Expand Down Expand Up @@ -315,7 +273,7 @@ function Eligible ({ tenants, check, onClaim }: { tenants: Tenant[], check: Chec
</RadioGroup>
</FormControl>
<Button sx={{ mt: 8, px: 8 }} color="primary" variant="contained" disabled={claiming || !value} onClick={handleClaim}>
Claim Credits
{claiming ? 'Claiming Credits...' : 'Claim Credits'}
</Button>
</>;
}
Expand All @@ -333,16 +291,23 @@ function ShareButton ({ check }: { check?: Check }) {
url = 'https://ossinsight.io/open-source-heroes/?utm_source=twitter&utm_medium=social&utm_campaign=plg_OSScontribution_credit_05';
}

const { gtagEvent } = useGtag();

return (
<Button
component="a"
target="_blank"
color="primary"
variant='contained'
variant="contained"
href={twitterLink(url, {
title,
hashtags,
})}>
})}
sx={{ '&:hover': { color: '#1C1E21' } }}
onClick={() => {
gtagEvent('github_campaign_share', { trigger_by: 'cta-share' });
}}
>
{'Share via X'}
</Button>
);
Expand Down Expand Up @@ -393,13 +358,6 @@ const starIcon = <svg style={{ display: 'block', margin: '0 auto' }} width="117"
fill="white" />
</svg>;

const badIcon = <svg width="117" height="117" viewBox="0 0 117 117" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="58.5" cy="58.5" r="58.5" fill="#04CB83" />
<path
d="M84.0378 48.4149C82.2492 46.0834 79.5263 44.7208 76.576 44.677L68.5364 44.552C69.1388 41.7267 69.3601 39.1889 69.1941 36.9761C68.9974 34.3321 68.2537 32.1193 66.9814 30.4129C66.1147 29.244 65.033 28.3439 63.7729 27.7501C62.4637 27.1313 61.3205 27 60.5891 27C56.1821 27 52.5987 30.3691 52.5987 34.5071C52.5987 41.2329 48.3453 46.7022 43.1085 46.7022H35.6713C33.0959 46.7022 31 48.8337 31 51.4528V77.2495C31 79.8685 33.0959 82 35.6713 82H72.0584C74.2588 82 76.4162 81.2499 78.1372 79.8935C79.8767 78.5246 81.106 76.5869 81.5977 74.4429L85.7588 56.2908C86.3919 53.5343 85.765 50.6652 84.0378 48.4149ZM40.902 77.4932H35.6713C35.5361 77.4932 35.4255 77.3807 35.4255 77.2432V51.4528C35.4255 51.3153 35.5361 51.2028 35.6713 51.2028H40.902V77.4932ZM81.4502 55.2657L77.289 73.4178C77.0247 74.5617 76.367 75.593 75.4328 76.3306C74.4801 77.0807 73.2877 77.4932 72.0645 77.4932H45.3274V50.9902C46.4829 50.7714 47.6016 50.3777 48.6834 49.8151C50.3491 48.9462 51.8304 47.7149 53.1027 46.1459C55.635 43.0143 57.0303 38.8826 57.0303 34.4946C57.0303 32.8382 58.6283 31.488 60.5952 31.488C60.7673 31.488 62.2793 31.5318 63.4533 33.1132C65.2297 35.5072 65.2788 40.1327 63.5885 46.1334C63.398 46.8085 63.5271 47.5336 63.9389 48.0961C64.3507 48.6587 64.9961 48.9962 65.6845 49.0025L76.5207 49.1713C78.1249 49.1963 79.6001 49.9276 80.5651 51.184C81.4625 52.3716 81.7821 53.8218 81.4502 55.2657Z"
fill="white" />
</svg>;

const successIcon = <svg width="117" height="117" viewBox="0 0 117 117" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="58.5" cy="58.5" r="58.5" fill="#E6A1B5" />
<path d="M51.7701 82C50.4492 82 49.1335 81.489 48.1258 80.4721L27.5076 59.5827C25.4975 57.5438 25.4975 54.2352 27.5076 52.1963C29.5229 50.1574 32.7861 50.1574 34.7963 52.1963L51.7701 69.3926L84.2037 36.5331C86.2138 34.489 89.477 34.489 91.4924 36.5331C93.5025 38.572 93.5025 41.8754 91.4924 43.9142L55.4145 80.4721C54.4068 81.489 53.0859 82 51.7701 82Z" fill="white" />
Expand Down
71 changes: 68 additions & 3 deletions web/src/pages/open-source-heroes/_components/TiDBCloudButton.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,89 @@
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import { Button } from '@mui/material';
import type { ButtonProps } from '@mui/material/Button';
import React, { type ReactNode } from 'react';
import { useGtag } from '@site/src/utils/ga';
import React, { type ReactNode, useState } from 'react';

const utm = '?utm_source=ossinsight&utm_medium=referral&utm_campaign=plg_OSScontribution_credit_05';

export function TiDBCloudButton ({ children, trial = true, mt, ...props }: { children: ReactNode, mt?: number, trial?: boolean } & Pick<ButtonProps<'a'>, 'sx' | 'color' | 'variant'>) {
interface TiDBCloudButtonProps extends Pick<ButtonProps<'a'>, 'sx' | 'color' | 'variant' | 'onClick'> {
children: ReactNode;
mt?: number;
trial?: boolean;
link?: boolean;
org?: number;
pop?: boolean;
}

const chars = 'abcdef1234567890';

export function TiDBCloudButton ({
children,
trial = true,
link,
org,
mt,
pop = false,
onClick,
...props
}: TiDBCloudButtonProps) {
const [state] = useState(() => Array(6).fill(0).map(_ => chars[Math.round(Math.random() * (chars.length - 1))]).join(''));

const {
siteConfig: { customFields },
} = useDocusaurusContext();

const { gtagEvent } = useGtag();

let href = `https://${customFields?.tidbcloud_host as string}`;
let tag: undefined | (() => any);

if (org != null) {
href += `/console/clusters/?orgId=${org}`;
tag = () => gtagEvent('github_campaign_start_building', { trigger_by: 'cta-start' });
} else if (link) {
href += '/oauth/authorize/';
tag = () => gtagEvent('github_campaign_connect', { trigger_by: 'cta-connect' });
} else if (trial) {
href += '/free-trial/';
tag = () => gtagEvent('github_campaign_try', { trigger_by: 'cta-try' });
} else {
href += '/';
}

href += utm;

if (link) {
href += `&response_type=code&client_id=OSSInsight&scope=org:owner&state=${state}&redirect_uri=${encodeURIComponent(location.origin + '/open-source-heroes/tidbcloud/oauth/callback/')}`;
}

return (
<Button
sx={{ mt, px: 8, textDecoration: 'underline', '&:hover': props.variant !== 'text' ? { color: '#1C1E21' } : {} }}
color="primary"
variant="outlined"
{...props}
component="a"
href={`https://${customFields?.tidbcloud_host as string}` + (trial ? '/free-trial/' : '/') + utm}
href={href}
target="_blank"
onClick={
pop
? (event) => {
onClick?.(event);
if (!event.isDefaultPrevented()) {
tag?.();
event.preventDefault();
const width = 600;
const height = 600;
const left = window.screenX + (window.innerWidth - width) / 2;
const top = window.screenY + (window.innerHeight - height) / 2;
window.open(href, 'Connnect to TiDB Cloud', `left=${left},top=${top},width=${width},height=${height},resizable,scrollbars=yes,status=1`);
}
}
: (event) => {
onClick?.(event);
tag?.();
}}
>
{children}
</Button>
Expand Down
19 changes: 15 additions & 4 deletions web/src/pages/open-source-heroes/_sections/0-heading.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,14 @@ declare module 'react' {
}
}

declare global {
interface Window {
__trigger?: string | undefined;
}
}

export function HeadingSection () {
const { user, isLoading, login } = useResponsiveAuth0();
const { user, isLoading, login, getIdTokenClaims } = useResponsiveAuth0();
const [claiming, setClaiming] = useState(false);
const { gtagEvent } = useGtag();

Expand All @@ -26,12 +32,17 @@ export function HeadingSection () {
return <PrimaryHeading
loading={isLoading}
onClickAction={() => {
gtagEvent('github_campaign_action', {});
const trigger = window.__trigger ?? 'cta-claim-top';
window.__trigger = undefined;
gtagEvent('github_campaign_action', { trigger_by: trigger });
if (isGithubSub(user?.sub)) {
setClaiming(true);
} else {
void login({ connection: 'github' }).then(() => {
setClaiming(true);
void login({ connection: 'github' }).then(async () => {
const idc = await getIdTokenClaims();
if (idc != null) {
setClaiming(true);
}
});
}
}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ export function IntroductionsSection () {
variant="contained"
onClick={() => {
window.scrollTo({ top: 0, behavior: 'smooth' });
window.__trigger = 'cta-claim-middle';
document.getElementById('start-claim-trigger')?.click();
}}
>
Expand Down
Loading
Loading