From 9fb8f5a3e86bb8e262094915452a7bee921fcc7d Mon Sep 17 00:00:00 2001 From: Mini256 Date: Sat, 12 Oct 2024 15:22:20 +0800 Subject: [PATCH 1/6] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 2c6d3cfd536..3cea56659f0 100644 --- a/README.md +++ b/README.md @@ -137,6 +137,7 @@ Insights about the **code update frequency & degree of popularity** from reposit **Examples**: + * [React](https://ossinsight.io/analyze/facebook/react) * [TiDB](https://ossinsight.io/analyze/pingcap/tidb) * [web3.js](https://ossinsight.io/analyze/web3/web3.js) From 15b6a66d758c46255981af43a62fd06c41d92d27 Mon Sep 17 00:00:00 2001 From: Jagger <634750802@qq.com> Date: Tue, 15 Oct 2024 11:25:59 +0800 Subject: [PATCH 2/6] update --- .../_components/ClaimForm.tsx | 88 ++++--------------- .../_components/TiDBCloudButton.tsx | 43 ++++++++- .../tidbcloud/oauth/callback/index.tsx | 64 ++++++++++++++ web/src/utils/ga.ts | 3 + 4 files changed, 122 insertions(+), 76 deletions(-) create mode 100644 web/src/pages/open-source-heroes/tidbcloud/oauth/callback/index.tsx diff --git a/web/src/pages/open-source-heroes/_components/ClaimForm.tsx b/web/src/pages/open-source-heroes/_components/ClaimForm.tsx index c4bdea794c4..a0204e0d56a 100644 --- a/web/src/pages/open-source-heroes/_components/ClaimForm.tsx +++ b/web/src/pages/open-source-heroes/_components/ClaimForm.tsx @@ -13,6 +13,8 @@ type Check = { githubId: number; isClaimed: boolean; isEligible: boolean; + isLinkTiDBCloud: boolean; + claimedTenantId?: number; }; type Tenant = { @@ -37,12 +39,12 @@ export function ClaimForm () { return res; })); - const { data: tenants } = useSWR('/api/v1/serverless-credits-campaign/tenants', async url => await giftClientWithoutCache.get(url, { + const { data: tenants, isValidating: isTenantValidating } = useSWR(check?.isLinkTiDBCloud && '/api/v1/serverless-credits-campaign/tenants', async url => await giftClientWithoutCache.get(url, { withCredentials: true, headers: { Authorization: `Bearer ${await getAccessTokenSilently({ connection: 'github' })}`, }, - })); + }), { errorRetryCount: 0 }); const handleClaim = async (id: string) => { gtagEvent('github_campaign_claim', {}); @@ -63,24 +65,18 @@ export function ClaimForm () { let children: ReactNode; - if (check && tenants) { + if (check && (tenants != null || !isTenantValidating)) { if (check.isClaimed) { if (claimedThisSession) { children = ; } else { children = ; } - } else if (check.isEligible) { - if (tenants.length === 0) { - children = ; - } else { - children = ; - } } else { - if (tenants.length === 0) { - children = ; + if (tenants) { + children = ; } else { - children = ; + children = ; } } @@ -95,10 +91,6 @@ export function ClaimForm () { //
// //
- // - //
- // - //
// // // ); @@ -164,7 +156,7 @@ function Claimed ({ check }: { check: Check }) { - + Start Building with TiDB Cloud! @@ -172,52 +164,6 @@ function Claimed ({ check }: { check: Check }) { ); } -function NotEligible ({ tenants }: { tenants: Tenant[] }) { - const { user } = useResponsiveAuth0(); - - return ( - <> - {badIcon} - - Hi {user?.nickname ?? user?.name} -
- 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. -
- Share this great news with your friends and start building something amazing. -
- - - - Login to TiDB Cloud - - - - ); -} - -function NotEligibleNoTenant () { - const { user } = useResponsiveAuth0(); - - return ( - <> - {badIcon} - - Hi {user?.nickname ?? user?.name} -
- Want to try TiDB Serverless for free? -
- Create a new TiDB Cloud account and enjoy 25GB of free storage to start building your applications. -
- - - - Create TiDB Cloud Account - - - - ); -} - function EligibleNoTenants ({ check }: { check: Check }) { const { user } = useResponsiveAuth0(); @@ -234,8 +180,9 @@ function EligibleNoTenants ({ check }: { check: Check }) { - Sign up to TiDB Cloud + Connect to TiDB Cloud ); @@ -393,13 +342,6 @@ const starIcon = ; -const badIcon = - - -; - const successIcon = diff --git a/web/src/pages/open-source-heroes/_components/TiDBCloudButton.tsx b/web/src/pages/open-source-heroes/_components/TiDBCloudButton.tsx index 574afa274da..7884c6b0278 100644 --- a/web/src/pages/open-source-heroes/_components/TiDBCloudButton.tsx +++ b/web/src/pages/open-source-heroes/_components/TiDBCloudButton.tsx @@ -1,15 +1,52 @@ import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; import { Button } from '@mui/material'; import type { ButtonProps } from '@mui/material/Button'; -import React, { type ReactNode } from 'react'; +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, 'sx' | 'color' | 'variant'>) { +interface TiDBCloudButtonProps extends Pick, 'sx' | 'color' | 'variant'> { + children: ReactNode; + mt?: number; + trial?: boolean; + link?: boolean; + org?: number; +} + +const chars = 'abcdef1234567890'; + +export function TiDBCloudButton ({ + children, + trial = true, + link, + org, + mt, + ...props +}: TiDBCloudButtonProps) { + const [state] = useState(() => Array(6).fill(0).map(_ => chars[Math.round(Math.random() * (chars.length - 1))]).join('')); + const { siteConfig: { customFields }, } = useDocusaurusContext(); + let href = `https://${customFields?.tidbcloud_host as string}`; + + if (org != null) { + href += `/console/clusters/?orgId=${org}`; + } else if (link) { + href += '/oauth/authorize/'; + } else if (trial) { + href += '/free-trial/'; + } 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 (
Authorizing...
; + } + + return
+

{error.error}

+
{error.message}
+
; +} diff --git a/web/src/utils/ga.ts b/web/src/utils/ga.ts index 98d490a3865..82a0b3e0e19 100644 --- a/web/src/utils/ga.ts +++ b/web/src/utils/ga.ts @@ -58,6 +58,9 @@ type CustomEventMap = { github_campaign_action: GaEvent; github_campaign_claim: GaEvent; + + connect_tidb_cloud_succeed: GaEvent; + connect_tidb_cloud_failed: GaEvent; }; interface GtagEventApi { From 497adb228e837489f5dd963da4e33e277120fba0 Mon Sep 17 00:00:00 2001 From: Jagger <634750802@qq.com> Date: Tue, 15 Oct 2024 12:28:41 +0800 Subject: [PATCH 3/6] fix --- .../pages/open-source-heroes/_components/TiDBCloudButton.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/src/pages/open-source-heroes/_components/TiDBCloudButton.tsx b/web/src/pages/open-source-heroes/_components/TiDBCloudButton.tsx index 7884c6b0278..48b8c8c54f2 100644 --- a/web/src/pages/open-source-heroes/_components/TiDBCloudButton.tsx +++ b/web/src/pages/open-source-heroes/_components/TiDBCloudButton.tsx @@ -44,7 +44,7 @@ export function TiDBCloudButton ({ 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')}`; + href += `&response_type=code&client_id=OSSInsight&scope=org:owner&state=${state}&redirect_uri=${encodeURIComponent(location.origin + '/open-source-heroes/tidbcloud/oauth/callback/')}`; } return ( From 700b4fdbae23eecf2d35493ba738b455984fc4ff Mon Sep 17 00:00:00 2001 From: Mini256 Date: Tue, 15 Oct 2024 15:09:57 +0800 Subject: [PATCH 4/6] Update web/src/pages/open-source-heroes/tidbcloud/oauth/callback/index.tsx --- .../pages/open-source-heroes/tidbcloud/oauth/callback/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/src/pages/open-source-heroes/tidbcloud/oauth/callback/index.tsx b/web/src/pages/open-source-heroes/tidbcloud/oauth/callback/index.tsx index 7fbfd829e4f..051bb97dbd3 100644 --- a/web/src/pages/open-source-heroes/tidbcloud/oauth/callback/index.tsx +++ b/web/src/pages/open-source-heroes/tidbcloud/oauth/callback/index.tsx @@ -35,7 +35,7 @@ function Inner () { body: JSON.stringify({ code, state, - redirect_uri: location.origin + '/open-source-heroes/tidbcloud/oauth/callback', + redirect_uri: location.origin + '/open-source-heroes/tidbcloud/oauth/callback/', }), }); From 93cf76edadb16b0f787242e2d60ad17b2b79bf3a Mon Sep 17 00:00:00 2001 From: Jagger <634750802@qq.com> Date: Wed, 16 Oct 2024 11:10:30 +0800 Subject: [PATCH 5/6] update --- .../_components/ClaimForm.tsx | 21 +++++++++--- .../_components/TiDBCloudButton.tsx | 15 ++++++++- .../_sections/0-heading.tsx | 9 ++++-- .../tidbcloud/oauth/callback/index.tsx | 32 +++++++++++++++---- 4 files changed, 61 insertions(+), 16 deletions(-) diff --git a/web/src/pages/open-source-heroes/_components/ClaimForm.tsx b/web/src/pages/open-source-heroes/_components/ClaimForm.tsx index a0204e0d56a..ebf0b5d9401 100644 --- a/web/src/pages/open-source-heroes/_components/ClaimForm.tsx +++ b/web/src/pages/open-source-heroes/_components/ClaimForm.tsx @@ -25,6 +25,7 @@ type Tenant = { export function ClaimForm () { const [claimedThisSession, setClaimedThisSession] = useState(false); + const [shouldAutoClaim, setShouldAutoClaim] = useState(false); const { getAccessTokenSilently } = useResponsiveAuth0(); const { gtagEvent } = useGtag(); @@ -63,6 +64,12 @@ 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 != null || !isTenantValidating)) { @@ -76,7 +83,7 @@ export function ClaimForm () { if (tenants) { children = ; } else { - children = ; + children = setShouldAutoClaim(true)} />; } } @@ -164,7 +171,7 @@ function Claimed ({ check }: { check: Check }) { ); } -function EligibleNoTenants ({ check }: { check: Check }) { +function EligibleNoTenants ({ check, onShouldAutoClaim }: { check: Check, onShouldAutoClaim: () => void }) { const { user } = useResponsiveAuth0(); return ( @@ -173,7 +180,7 @@ function EligibleNoTenants ({ check }: { check: Check }) { Hi {user?.nickname ?? user?.name}
- Awesome! You're eligible for {check.credits} in TiDB Serverless credits for your contributions to the open-source community. + Awesome! You're eligible for {check.credits} in TiDB Serverless credits.
Create a new TiDB Cloud account and your credits will be waiting for you.
@@ -181,6 +188,10 @@ function EligibleNoTenants ({ check }: { check: Check }) { variant="contained" sx={{ background: 'white', mt: 8, '&:hover': { background: 'rgba(255,255,255,0.8)', color: 'black' } }} link + pop + onClick={() => { + onShouldAutoClaim(); + }} > Connect to TiDB Cloud @@ -224,7 +235,7 @@ function Eligible ({ tenants, check, onClaim }: { tenants: Tenant[], check: Chec Hi {user?.nickname ?? user?.name}
- Congratulations! You're eligible for {check.credits} in TiDB Serverless credits for your contributions to the open-source community. + Congratulations! You're eligible for {check.credits} in TiDB Serverless credits.
Please select your existing TiDB Cloud account to apply these credits.
@@ -262,7 +273,7 @@ function Eligible ({ tenants, check, onClaim }: { tenants: Tenant[], check: Chec ; } diff --git a/web/src/pages/open-source-heroes/_components/TiDBCloudButton.tsx b/web/src/pages/open-source-heroes/_components/TiDBCloudButton.tsx index 48b8c8c54f2..f96c2399366 100644 --- a/web/src/pages/open-source-heroes/_components/TiDBCloudButton.tsx +++ b/web/src/pages/open-source-heroes/_components/TiDBCloudButton.tsx @@ -5,12 +5,13 @@ import React, { type ReactNode, useState } from 'react'; const utm = '?utm_source=ossinsight&utm_medium=referral&utm_campaign=plg_OSScontribution_credit_05'; -interface TiDBCloudButtonProps extends Pick, 'sx' | 'color' | 'variant'> { +interface TiDBCloudButtonProps extends Pick, 'sx' | 'color' | 'variant' | 'onClick'> { children: ReactNode; mt?: number; trial?: boolean; link?: boolean; org?: number; + pop?: boolean; } const chars = 'abcdef1234567890'; @@ -21,6 +22,8 @@ export function TiDBCloudButton ({ 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('')); @@ -56,6 +59,16 @@ export function TiDBCloudButton ({ component="a" href={href} target="_blank" + onClick={ + pop + ? (event) => { + onClick?.(event); + if (!event.isDefaultPrevented()) { + event.preventDefault(); + window.open(href, 'Connnect to TiDB Cloud', 'width=600,height=600,resizable,scrollbars=yes,status=1'); + } + } + : onClick} > {children} diff --git a/web/src/pages/open-source-heroes/_sections/0-heading.tsx b/web/src/pages/open-source-heroes/_sections/0-heading.tsx index b1a27fa83ac..7a37dc2bbd3 100644 --- a/web/src/pages/open-source-heroes/_sections/0-heading.tsx +++ b/web/src/pages/open-source-heroes/_sections/0-heading.tsx @@ -16,7 +16,7 @@ declare module 'react' { } export function HeadingSection () { - const { user, isLoading, login } = useResponsiveAuth0(); + const { user, isLoading, login, getIdTokenClaims } = useResponsiveAuth0(); const [claiming, setClaiming] = useState(false); const { gtagEvent } = useGtag(); @@ -30,8 +30,11 @@ export function HeadingSection () { 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); + } }); } }} diff --git a/web/src/pages/open-source-heroes/tidbcloud/oauth/callback/index.tsx b/web/src/pages/open-source-heroes/tidbcloud/oauth/callback/index.tsx index 051bb97dbd3..a5715950f2a 100644 --- a/web/src/pages/open-source-heroes/tidbcloud/oauth/callback/index.tsx +++ b/web/src/pages/open-source-heroes/tidbcloud/oauth/callback/index.tsx @@ -11,8 +11,15 @@ export default function Page () { ); } +enum AuthorizeState { + AUTHORIZING, + AUTHORIZED, + FAILED, +} + function Inner () { const { getAccessTokenSilently } = useResponsiveAuth0(); + const [authorizeState, setAuthorizeState] = useState(AuthorizeState.AUTHORIZING); const [error, setError] = useState<{ error: string, message: string }>(); const { gtagEvent } = useGtag(); @@ -41,11 +48,13 @@ function Inner () { if (response.ok) { gtagEvent('connect_tidb_cloud_succeed', {}); + setAuthorizeState(AuthorizeState.AUTHORIZED); setTimeout(() => { window.close(); }, 1500); } else { gtagEvent('connect_tidb_cloud_failed', {}); + setAuthorizeState(AuthorizeState.FAILED); setError(await response.json()); } }; @@ -53,12 +62,21 @@ function Inner () { void execute(); }, []); - if (!error) { - return
Authorizing...
; + switch (authorizeState) { + case AuthorizeState.AUTHORIZING: + return
+

Authorizing

+
Please do not close this window.
+
; + case AuthorizeState.AUTHORIZED: + return
+

Authorized

+
This window will close in seconds. Go back to window.close()} style={{ textDecoration: 'underline' }}>OSSInsight.
+
; + case AuthorizeState.FAILED: + return
+

{error?.error ?? 'Authorization failed'}

+
{error?.message ?? 'Unknown error'}
+
; } - - return
-

{error.error}

-
{error.message}
-
; } From 78a947aea046a45211b63d864db13a159b9b8143 Mon Sep 17 00:00:00 2001 From: Jagger <634750802@qq.com> Date: Wed, 16 Oct 2024 16:09:37 +0800 Subject: [PATCH 6/6] update --- .../_components/ClaimForm.tsx | 7 ++++++- .../_components/TiDBCloudButton.tsx | 19 +++++++++++++++++-- .../_sections/0-heading.tsx | 10 +++++++++- .../_sections/2-introduction.tsx | 1 + web/src/utils/ga.ts | 8 +++++++- 5 files changed, 40 insertions(+), 5 deletions(-) diff --git a/web/src/pages/open-source-heroes/_components/ClaimForm.tsx b/web/src/pages/open-source-heroes/_components/ClaimForm.tsx index ebf0b5d9401..c060ba9e166 100644 --- a/web/src/pages/open-source-heroes/_components/ClaimForm.tsx +++ b/web/src/pages/open-source-heroes/_components/ClaimForm.tsx @@ -140,7 +140,7 @@ function ClaimedThisSession ({ check }: { check: Check }) { - + Start Building with TiDB Cloud! @@ -291,6 +291,8 @@ 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 ( diff --git a/web/src/pages/open-source-heroes/_components/TiDBCloudButton.tsx b/web/src/pages/open-source-heroes/_components/TiDBCloudButton.tsx index f96c2399366..e6321e29362 100644 --- a/web/src/pages/open-source-heroes/_components/TiDBCloudButton.tsx +++ b/web/src/pages/open-source-heroes/_components/TiDBCloudButton.tsx @@ -1,6 +1,7 @@ import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; import { Button } from '@mui/material'; import type { ButtonProps } from '@mui/material/Button'; +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'; @@ -32,14 +33,20 @@ export function TiDBCloudButton ({ 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 += '/'; } @@ -64,11 +71,19 @@ export function TiDBCloudButton ({ ? (event) => { onClick?.(event); if (!event.isDefaultPrevented()) { + tag?.(); event.preventDefault(); - window.open(href, 'Connnect to TiDB Cloud', 'width=600,height=600,resizable,scrollbars=yes,status=1'); + 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`); } } - : onClick} + : (event) => { + onClick?.(event); + tag?.(); + }} > {children} diff --git a/web/src/pages/open-source-heroes/_sections/0-heading.tsx b/web/src/pages/open-source-heroes/_sections/0-heading.tsx index 7a37dc2bbd3..ddf263665bd 100644 --- a/web/src/pages/open-source-heroes/_sections/0-heading.tsx +++ b/web/src/pages/open-source-heroes/_sections/0-heading.tsx @@ -15,6 +15,12 @@ declare module 'react' { } } +declare global { + interface Window { + __trigger?: string | undefined; + } +} + export function HeadingSection () { const { user, isLoading, login, getIdTokenClaims } = useResponsiveAuth0(); const [claiming, setClaiming] = useState(false); @@ -26,7 +32,9 @@ export function HeadingSection () { return { - 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 { diff --git a/web/src/pages/open-source-heroes/_sections/2-introduction.tsx b/web/src/pages/open-source-heroes/_sections/2-introduction.tsx index eb26a0681d3..c0e11080390 100644 --- a/web/src/pages/open-source-heroes/_sections/2-introduction.tsx +++ b/web/src/pages/open-source-heroes/_sections/2-introduction.tsx @@ -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(); }} > diff --git a/web/src/utils/ga.ts b/web/src/utils/ga.ts index 82a0b3e0e19..bcf19606354 100644 --- a/web/src/utils/ga.ts +++ b/web/src/utils/ga.ts @@ -17,6 +17,8 @@ type GAConfiguredDimensions = { errorMessage: string; // trigger-login, login-failed, login-success trigger_login_by: string | undefined; + + trigger_by: string | undefined; }; type GAConfiguredOptions = GAConfiguredDimensions & GAConfiguredMetrics; @@ -56,8 +58,12 @@ type CustomEventMap = { login_success: GaEvent<'trigger_login_by'>; trigger_login: GaEvent<'trigger_login_by'>; - github_campaign_action: GaEvent; + github_campaign_action: GaEvent<'trigger_by'>; github_campaign_claim: GaEvent; + github_campaign_try: GaEvent<'trigger_by'>; + github_campaign_share: GaEvent<'trigger_by'>; + github_campaign_start_building: GaEvent<'trigger_by'>; + github_campaign_connect: GaEvent<'trigger_by'>; connect_tidb_cloud_succeed: GaEvent; connect_tidb_cloud_failed: GaEvent;