diff --git a/.github/workflows/preview.yaml b/.github/workflows/preview.yaml index 3e119ccbf4a..7a508020b90 100644 --- a/.github/workflows/preview.yaml +++ b/.github/workflows/preview.yaml @@ -54,6 +54,8 @@ jobs: SENTRY_DSN: https://ea6017f8ee534468b308a2a6c949895a@o226447.ingest.sentry.io/6588620 AUTH0_DOMAIN: ${{ secrets.AUTH0_DOMAIN }} AUTH0_CLIENT_ID: ${{ secrets.AUTH0_CLIENT_ID }} + GIFT_APP_API_BASE: us-west-2.staging.shared.aws.tidbcloud.com + GIFT_TIDBCLOUD_BASE_URL: https://staging.tidbcloud.com OSSINSIGHT_PREVIEW: true TIDBCLOUD_HOST: staging.tidbcloud.com run: npm run build diff --git a/web/docusaurus.config.js b/web/docusaurus.config.js index b40fb963c55..5b1d590d45c 100644 --- a/web/docusaurus.config.js +++ b/web/docusaurus.config.js @@ -8,6 +8,8 @@ const fs = require('fs'); const HOST = process.env.APP_HOST || 'https://ossinsight.io'; const API_BASE = process.env.APP_API_BASE || 'https://api.ossinsight.io'; +const GIFT_APP_API_BASE = process.env.GIFT_APP_API_BASE || 'https://gift.ossinsight.io'; +const GIFT_TIDBCLOUD_BASE_URL = process.env.GIFT_TIDBCLOUD_BASE_URL || 'https://tidbcloud.com'; const DATABASE_URL = process.env.DATABASE_URL || ''; const SENTRY_DSN = process.env.SENTRY_DSN || ''; @@ -66,6 +68,8 @@ const config = { path.resolve(__dirname, 'plugins/define'), { 'process.env.APP_API_BASE': JSON.stringify(API_BASE), + 'process.env.GIFT_APP_API_BASE': JSON.stringify(GIFT_APP_API_BASE), + 'process.env.GIFT_TIDBCLOUD_BASE_URL': JSON.stringify(GIFT_TIDBCLOUD_BASE_URL), 'process.env.SENTRY_DSN': SENTRY_DSN ? JSON.stringify(SENTRY_DSN) : undefined, } ], diff --git a/web/package-lock.json b/web/package-lock.json index 846572481dc..a721322a29a 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -77,6 +77,7 @@ "eslint-plugin-n": "^15.4.0", "eslint-plugin-promise": "^6.1.1", "eslint-plugin-react": "^7.31.10", + "framer-motion": "^6.5.1", "human-format": "^1.0.0", "node-fetch": "^3.2.4", "param-case": "^3.0.4", @@ -3245,6 +3246,76 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/@motionone/animation": { + "version": "10.18.0", + "resolved": "https://registry.npmjs.org/@motionone/animation/-/animation-10.18.0.tgz", + "integrity": "sha512-9z2p5GFGCm0gBsZbi8rVMOAJCtw1WqBTIPw3ozk06gDvZInBPIsQcHgYogEJ4yuHJ+akuW8g1SEIOpTOvYs8hw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@motionone/easing": "^10.18.0", + "@motionone/types": "^10.17.1", + "@motionone/utils": "^10.18.0", + "tslib": "^2.3.1" + } + }, + "node_modules/@motionone/dom": { + "version": "10.12.0", + "resolved": "https://registry.npmjs.org/@motionone/dom/-/dom-10.12.0.tgz", + "integrity": "sha512-UdPTtLMAktHiqV0atOczNYyDd/d8Cf5fFsd1tua03PqTwwCe/6lwhLSQ8a7TbnQ5SN0gm44N1slBfj+ORIhrqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@motionone/animation": "^10.12.0", + "@motionone/generators": "^10.12.0", + "@motionone/types": "^10.12.0", + "@motionone/utils": "^10.12.0", + "hey-listen": "^1.0.8", + "tslib": "^2.3.1" + } + }, + "node_modules/@motionone/easing": { + "version": "10.18.0", + "resolved": "https://registry.npmjs.org/@motionone/easing/-/easing-10.18.0.tgz", + "integrity": "sha512-VcjByo7XpdLS4o9T8t99JtgxkdMcNWD3yHU/n6CLEz3bkmKDRZyYQ/wmSf6daum8ZXqfUAgFeCZSpJZIMxaCzg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@motionone/utils": "^10.18.0", + "tslib": "^2.3.1" + } + }, + "node_modules/@motionone/generators": { + "version": "10.18.0", + "resolved": "https://registry.npmjs.org/@motionone/generators/-/generators-10.18.0.tgz", + "integrity": "sha512-+qfkC2DtkDj4tHPu+AFKVfR/C30O1vYdvsGYaR13W/1cczPrrcjdvYCj0VLFuRMN+lP1xvpNZHCRNM4fBzn1jg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@motionone/types": "^10.17.1", + "@motionone/utils": "^10.18.0", + "tslib": "^2.3.1" + } + }, + "node_modules/@motionone/types": { + "version": "10.17.1", + "resolved": "https://registry.npmjs.org/@motionone/types/-/types-10.17.1.tgz", + "integrity": "sha512-KaC4kgiODDz8hswCrS0btrVrzyU2CSQKO7Ps90ibBVSQmjkrt2teqta6/sOG59v7+dPnKMAg13jyqtMKV2yJ7A==", + "dev": true, + "license": "MIT" + }, + "node_modules/@motionone/utils": { + "version": "10.18.0", + "resolved": "https://registry.npmjs.org/@motionone/utils/-/utils-10.18.0.tgz", + "integrity": "sha512-3XVF7sgyTSI2KWvTf6uLlBJ5iAgRgmvp3bpuOiQJvInd4nZ19ET8lX5unn30SlmRH7hXbBbH+Gxd0m0klJ3Xtw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@motionone/types": "^10.17.1", + "hey-listen": "^1.0.8", + "tslib": "^2.3.1" + } + }, "node_modules/@mui/base": { "version": "5.0.0-alpha.102", "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-alpha.102.tgz", @@ -10602,6 +10673,57 @@ "url": "https://www.patreon.com/infusion" } }, + "node_modules/framer-motion": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-6.5.1.tgz", + "integrity": "sha512-o1BGqqposwi7cgDrtg0dNONhkmPsUFDaLcKXigzuTFC5x58mE8iyTazxSudFzmT6MEyJKfjjU8ItoMe3W+3fiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@motionone/dom": "10.12.0", + "framesync": "6.0.1", + "hey-listen": "^1.0.8", + "popmotion": "11.0.3", + "style-value-types": "5.0.0", + "tslib": "^2.1.0" + }, + "optionalDependencies": { + "@emotion/is-prop-valid": "^0.8.2" + }, + "peerDependencies": { + "react": ">=16.8 || ^17.0.0 || ^18.0.0", + "react-dom": ">=16.8 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/framer-motion/node_modules/@emotion/is-prop-valid": { + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz", + "integrity": "sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emotion/memoize": "0.7.4" + } + }, + "node_modules/framer-motion/node_modules/@emotion/memoize": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.4.tgz", + "integrity": "sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/framesync": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/framesync/-/framesync-6.0.1.tgz", + "integrity": "sha512-fUY88kXvGiIItgNC7wcTOl0SNRCVXMKSWW2Yzfmn7EKNc+MpCzcz9DhdHcdjbrtN3c6R4H5dTY2jiCpPdysEjA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.1.0" + } + }, "node_modules/fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", @@ -11197,6 +11319,13 @@ "node": ">=8" } }, + "node_modules/hey-listen": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/hey-listen/-/hey-listen-1.0.8.tgz", + "integrity": "sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q==", + "dev": true, + "license": "MIT" + }, "node_modules/history": { "version": "4.10.1", "resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz", @@ -14766,6 +14895,19 @@ "node": ">=4" } }, + "node_modules/popmotion": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/popmotion/-/popmotion-11.0.3.tgz", + "integrity": "sha512-Y55FLdj3UxkR7Vl3s7Qr4e9m0onSnP8W7d/xQLsoJM40vs6UKHFdygs6SWryasTZYqugMjm3BepCF4CWXDiHgA==", + "dev": true, + "license": "MIT", + "dependencies": { + "framesync": "6.0.1", + "hey-listen": "^1.0.8", + "style-value-types": "5.0.0", + "tslib": "^2.1.0" + } + }, "node_modules/postcss": { "version": "8.4.18", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.18.tgz", @@ -18502,6 +18644,17 @@ "inline-style-parser": "0.1.1" } }, + "node_modules/style-value-types": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/style-value-types/-/style-value-types-5.0.0.tgz", + "integrity": "sha512-08yq36Ikn4kx4YU6RD7jWEv27v4V+PUsOGa4n/as8Et3CuODMJQ00ENeAVXAeydX4Z2j1XHZF1K2sX4mGl18fA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hey-listen": "^1.0.8", + "tslib": "^2.1.0" + } + }, "node_modules/stylehacks": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.1.0.tgz", @@ -23167,6 +23320,70 @@ "resolved": "https://registry.npmjs.org/@mdx-js/util/-/util-1.6.22.tgz", "integrity": "sha512-H1rQc1ZOHANWBvPcW+JpGwr+juXSxM8Q8YCkm3GhZd8REu1fHR3z99CErO1p9pkcfcxZnMdIZdIsXkOHY0NilA==" }, + "@motionone/animation": { + "version": "10.18.0", + "resolved": "https://registry.npmjs.org/@motionone/animation/-/animation-10.18.0.tgz", + "integrity": "sha512-9z2p5GFGCm0gBsZbi8rVMOAJCtw1WqBTIPw3ozk06gDvZInBPIsQcHgYogEJ4yuHJ+akuW8g1SEIOpTOvYs8hw==", + "dev": true, + "requires": { + "@motionone/easing": "^10.18.0", + "@motionone/types": "^10.17.1", + "@motionone/utils": "^10.18.0", + "tslib": "^2.3.1" + } + }, + "@motionone/dom": { + "version": "10.12.0", + "resolved": "https://registry.npmjs.org/@motionone/dom/-/dom-10.12.0.tgz", + "integrity": "sha512-UdPTtLMAktHiqV0atOczNYyDd/d8Cf5fFsd1tua03PqTwwCe/6lwhLSQ8a7TbnQ5SN0gm44N1slBfj+ORIhrqw==", + "dev": true, + "requires": { + "@motionone/animation": "^10.12.0", + "@motionone/generators": "^10.12.0", + "@motionone/types": "^10.12.0", + "@motionone/utils": "^10.12.0", + "hey-listen": "^1.0.8", + "tslib": "^2.3.1" + } + }, + "@motionone/easing": { + "version": "10.18.0", + "resolved": "https://registry.npmjs.org/@motionone/easing/-/easing-10.18.0.tgz", + "integrity": "sha512-VcjByo7XpdLS4o9T8t99JtgxkdMcNWD3yHU/n6CLEz3bkmKDRZyYQ/wmSf6daum8ZXqfUAgFeCZSpJZIMxaCzg==", + "dev": true, + "requires": { + "@motionone/utils": "^10.18.0", + "tslib": "^2.3.1" + } + }, + "@motionone/generators": { + "version": "10.18.0", + "resolved": "https://registry.npmjs.org/@motionone/generators/-/generators-10.18.0.tgz", + "integrity": "sha512-+qfkC2DtkDj4tHPu+AFKVfR/C30O1vYdvsGYaR13W/1cczPrrcjdvYCj0VLFuRMN+lP1xvpNZHCRNM4fBzn1jg==", + "dev": true, + "requires": { + "@motionone/types": "^10.17.1", + "@motionone/utils": "^10.18.0", + "tslib": "^2.3.1" + } + }, + "@motionone/types": { + "version": "10.17.1", + "resolved": "https://registry.npmjs.org/@motionone/types/-/types-10.17.1.tgz", + "integrity": "sha512-KaC4kgiODDz8hswCrS0btrVrzyU2CSQKO7Ps90ibBVSQmjkrt2teqta6/sOG59v7+dPnKMAg13jyqtMKV2yJ7A==", + "dev": true + }, + "@motionone/utils": { + "version": "10.18.0", + "resolved": "https://registry.npmjs.org/@motionone/utils/-/utils-10.18.0.tgz", + "integrity": "sha512-3XVF7sgyTSI2KWvTf6uLlBJ5iAgRgmvp3bpuOiQJvInd4nZ19ET8lX5unn30SlmRH7hXbBbH+Gxd0m0klJ3Xtw==", + "dev": true, + "requires": { + "@motionone/types": "^10.17.1", + "hey-listen": "^1.0.8", + "tslib": "^2.3.1" + } + }, "@mui/base": { "version": "5.0.0-alpha.102", "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-alpha.102.tgz", @@ -28749,6 +28966,49 @@ "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz", "integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==" }, + "framer-motion": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-6.5.1.tgz", + "integrity": "sha512-o1BGqqposwi7cgDrtg0dNONhkmPsUFDaLcKXigzuTFC5x58mE8iyTazxSudFzmT6MEyJKfjjU8ItoMe3W+3fiw==", + "dev": true, + "requires": { + "@emotion/is-prop-valid": "^0.8.2", + "@motionone/dom": "10.12.0", + "framesync": "6.0.1", + "hey-listen": "^1.0.8", + "popmotion": "11.0.3", + "style-value-types": "5.0.0", + "tslib": "^2.1.0" + }, + "dependencies": { + "@emotion/is-prop-valid": { + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz", + "integrity": "sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==", + "dev": true, + "optional": true, + "requires": { + "@emotion/memoize": "0.7.4" + } + }, + "@emotion/memoize": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.4.tgz", + "integrity": "sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==", + "dev": true, + "optional": true + } + } + }, + "framesync": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/framesync/-/framesync-6.0.1.tgz", + "integrity": "sha512-fUY88kXvGiIItgNC7wcTOl0SNRCVXMKSWW2Yzfmn7EKNc+MpCzcz9DhdHcdjbrtN3c6R4H5dTY2jiCpPdysEjA==", + "dev": true, + "requires": { + "tslib": "^2.1.0" + } + }, "fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", @@ -29183,6 +29443,12 @@ "resolved": "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz", "integrity": "sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g==" }, + "hey-listen": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/hey-listen/-/hey-listen-1.0.8.tgz", + "integrity": "sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q==", + "dev": true + }, "history": { "version": "4.10.1", "resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz", @@ -31734,6 +32000,18 @@ "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==" }, + "popmotion": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/popmotion/-/popmotion-11.0.3.tgz", + "integrity": "sha512-Y55FLdj3UxkR7Vl3s7Qr4e9m0onSnP8W7d/xQLsoJM40vs6UKHFdygs6SWryasTZYqugMjm3BepCF4CWXDiHgA==", + "dev": true, + "requires": { + "framesync": "6.0.1", + "hey-listen": "^1.0.8", + "style-value-types": "5.0.0", + "tslib": "^2.1.0" + } + }, "postcss": { "version": "8.4.18", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.18.tgz", @@ -34442,6 +34720,16 @@ "inline-style-parser": "0.1.1" } }, + "style-value-types": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/style-value-types/-/style-value-types-5.0.0.tgz", + "integrity": "sha512-08yq36Ikn4kx4YU6RD7jWEv27v4V+PUsOGa4n/as8Et3CuODMJQ00ENeAVXAeydX4Z2j1XHZF1K2sX4mGl18fA==", + "dev": true, + "requires": { + "hey-listen": "^1.0.8", + "tslib": "^2.1.0" + } + }, "stylehacks": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.1.0.tgz", diff --git a/web/package.json b/web/package.json index e4b97bc74f7..c36095f575a 100644 --- a/web/package.json +++ b/web/package.json @@ -4,7 +4,7 @@ "private": true, "scripts": { "docusaurus": "docusaurus", - "start": "docusaurus start", + "start": "docusaurus start --port 30000", "start-silence": "ENABLE_BUNDLER_ANALYZE=false docusaurus start --host 0.0.0.0 --port 30000 --no-open", "build": "docusaurus build", "swizzle": "docusaurus swizzle", @@ -95,6 +95,7 @@ "eslint-plugin-n": "^15.4.0", "eslint-plugin-promise": "^6.1.1", "eslint-plugin-react": "^7.31.10", + "framer-motion": "^6.5.1", "human-format": "^1.0.0", "node-fetch": "^3.2.4", "param-case": "^3.0.4", diff --git a/web/src/css/custom.css b/web/src/css/custom.css index a7faf45652d..e2eed17b15b 100644 --- a/web/src/css/custom.css +++ b/web/src/css/custom.css @@ -336,4 +336,9 @@ hr.MuiDivider-root { .event > .menu__link::before { content: "event"; background-color: rgba(0, 0, 0, 0.5); +} + +:root { + --color1: ; + --color2: ; } \ No newline at end of file diff --git a/web/src/pages/explore/_components/ExploreGlobalAds.tsx b/web/src/pages/explore/_components/ExploreGlobalAds.tsx index 656fd90c09f..d69aed0fa5e 100644 --- a/web/src/pages/explore/_components/ExploreGlobalAds.tsx +++ b/web/src/pages/explore/_components/ExploreGlobalAds.tsx @@ -23,7 +23,7 @@ export default function ExploreGlobalAds () { useEffect(() => { setAnchorEl(document.body); - if (hasClosed || /^\/(?:explore|blog)\/?$/.test(location.pathname) || location.pathname.startsWith('/blog/chat2query-tutorials')) { + if (hasClosed || /^\/(?:explore|blog|github-campaign)\/?$/.test(location.pathname) || location.pathname.startsWith('/blog/chat2query-tutorials')) { return; } safeSetTimeout(() => { diff --git a/web/src/pages/github-campaign/_components/ClaimForm.tsx b/web/src/pages/github-campaign/_components/ClaimForm.tsx new file mode 100644 index 00000000000..019cfec40cc --- /dev/null +++ b/web/src/pages/github-campaign/_components/ClaimForm.tsx @@ -0,0 +1,362 @@ +import { Box, Button, FormControl, FormControlLabel, FormLabel, Radio, RadioGroup, Skeleton, styled } from '@mui/material'; +import { giftClientWithoutCache } from '@site/src/api/client'; +import { TiDBCloudButton } from '@site/src/pages/github-campaign/_components/TiDBCloudButton'; +import { useResponsiveAuth0 } from '@site/src/theme/NavbarItem/useResponsiveAuth0'; +import { getErrorMessage } from '@site/src/utils/error'; +import React, { type ReactNode, useEffect, useState } from 'react'; +import useSWR from 'swr'; + +type Check = { + credits: string; + githubId: number; + isClaimed: boolean; + isEligible: boolean; +}; + +type Tenant = { + email: string; + id: string; + name: string; +}; + +export function ClaimForm () { + const [claimedThisSession, setClaimedThisSession] = useState(false); + const { getAccessTokenSilently } = useResponsiveAuth0(); + + const { data: check, mutate } = useSWR('/api/v1/serverless-credits-campaign/credits/check', async url => await giftClientWithoutCache.get(url, { + withCredentials: true, + headers: { + Authorization: `Bearer ${await getAccessTokenSilently({ connection: 'github' })}`, + }, + })); + + const { data: tenants } = useSWR('/api/v1/serverless-credits-campaign/tenants', async url => await giftClientWithoutCache.get(url, { + withCredentials: true, + headers: { + Authorization: `Bearer ${await getAccessTokenSilently({ connection: 'github' })}`, + }, + }), { revalidateOnFocus: false }); + + const handleClaim = async (id: string) => { + await giftClientWithoutCache.post('/api/v1/serverless-credits-campaign/credits/claim', { + selectedTenantId: id, + }, { + headers: { + Authorization: `Bearer ${await getAccessTokenSilently({ connection: 'github' })}`, + }, + }) + .then(() => { + setClaimedThisSession(true); + }) + .finally(() => { + void mutate(); + }); + }; + + let children: ReactNode; + + if (check && tenants) { + 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 = ; + } else { + children = ; + } + } + + // // DEBUG + // children = ( + // <> + // + //
+ // + //
+ // + //
+ // + //
+ // + //
+ // + //
+ // + // + // ); + } else { + children = ; + } + + return ( + + {children} + + ); +} + +function Checking () { + return ( + <> + + + + + + + + ); +} + +function ClaimedThisSession ({ check }: { check: Check }) { + const { user } = useResponsiveAuth0(); + + return ( + <> + {successIcon} + + Hi {user?.nickname ?? user?.name} +
+ Successfully claimed {check.credits} credits, you can go to +
+ TiDB Cloud to check it out and use it. +
+ + Start Building with TiDB Cloud! + + + ); +} + +function Claimed () { + const { user } = useResponsiveAuth0(); + + return ( + <> + {successIcon} + + Hi {user?.nickname ?? user?.name} +
+ You've already participated in this campaign. +
+ Thanks for being an open-source hero. +
+ Ready to build something amazing? +
+ + Start Building with TiDB Cloud! + + + ); +} + +function NotEligible ({ tenants }: { tenants: Tenant[] }) { + const { user } = useResponsiveAuth0(); + + return ( + <> + {badIcon} + + Hi {user?.nickname ?? user?.name} +
+ Thank you for your contributions to the open-source community. +
+ While you don't qualify for credits at this time, we encourage you to continue exploring the possibilities with TiDB Serverless. +
+ Login to your TiDB Cloud account to start building your next project. +
+ + 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(); + + return ( + <> + {starIcon} + + Hi {user?.nickname ?? user?.name} +
+ Great news! You're eligible for {check.credits} in TiDB Serverless credits for your contributions to the open-source community. +
+ Create a new TiDB Cloud account and your credits will be waiting for you. +
+ + Sign up to TiDB Cloud + + + + ); +} + +function Eligible ({ tenants, check, onClaim }: { tenants: Tenant[], check: Check, onClaim: (id: string) => Promise }) { + const { user } = useResponsiveAuth0(); + const [value, setValue] = useState(''); + const [claiming, setClaiming] = useState(false); + const [, setClaimError] = useState(); + + useEffect(() => { + if (tenants.length > 0) { + setValue(tenants[0].id); + } else { + setValue(''); + } + }, [tenants]); + + const handleClaim = () => { + if (value) { + setClaiming(true); + onClaim(value) + .catch(error => { + alert(getErrorMessage(error)); + setClaimError(error); + }) + .finally(() => { + setClaiming(false); + }); + } + }; + + return <> + {starIcon} + + Hi {user?.nickname ?? user?.name} +
+ Congratulations! You're eligible for {check.credits} in TiDB Serverless credits for your contributions to the open-source community. +
+ Please select your existing TiDB Cloud account to apply these credits. +
+ + Select your TiDB Cloud account to claim the credits + setValue(value)} + > + {tenants.map(tenant => ( + + {tenant.name} + {tenant.email} + + )} + control={} + /> + ))} + + + + ; +} + +const ClaimFormContainer = styled('div')` + background: #212122; + min-height: calc(100vh - 60px); + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 24; +`; + +const ClaimContent = styled('div')` + text-align: center; + font-size: 36px; + font-weight: 400; + line-height: 50px; + max-width: 1200px; + margin: 0 auto; + + strong { + font-weight: 700; + color: #FFE895; + } + + em { + color: #73D9B4; + font-style: normal; + } +`; + +const TenantName = styled('div')` + +`; + +const TenantEmail = styled('div')` + color: ${({ theme }) => theme.palette.grey['500']}; + font-size: 12px; +`; + +const starIcon = + + +; + +const badIcon = + + +; + +const successIcon = + + +; diff --git a/web/src/pages/github-campaign/_components/Collapse.tsx b/web/src/pages/github-campaign/_components/Collapse.tsx new file mode 100644 index 00000000000..d079c13401d --- /dev/null +++ b/web/src/pages/github-campaign/_components/Collapse.tsx @@ -0,0 +1,49 @@ +import { Button, styled } from '@mui/material'; +import { motion } from 'framer-motion'; +import React, { type ReactNode, useState } from 'react'; + +export function Collapse ({ children }: { children: ReactNode }) { + const [collapsed, setCollapsed] = useState(true); + + return ( + + + {children} + + + + + ); +} + +const variants = { + collapsed: { height: 240 }, + flatten: { height: 'auto' }, +}; + +const shadowEffectVariants = { + collapsed: { boxShadow: '0 0 40px 40px #141414' }, + flatten: { boxShadow: 'none' }, +}; + +const CollapseRoot = styled('div')` + border: 1px solid #565656; + background: #141414; + border-radius: 2px; + padding: 56px; +`; + +const CollapseContainer = motion(styled('div')` + overflow: hidden; + position: relative; +`); + +const ShadowEffect = motion(styled('div')` + position: absolute; + left: 0; + bottom: 0; + content: ' '; + display: block; + width: 100%; + height: 0; +`); diff --git a/web/src/pages/github-campaign/_components/Heading.tsx b/web/src/pages/github-campaign/_components/Heading.tsx new file mode 100644 index 00000000000..dcba51f8fa9 --- /dev/null +++ b/web/src/pages/github-campaign/_components/Heading.tsx @@ -0,0 +1,115 @@ +import { css, styled, Unstable_Grid2 as Grid } from '@mui/material'; + +export const HeadingContainer = styled('div')` + background-color: #212122; + ${({ theme }) => ({ + [theme.breakpoints.up('md')]: css` + height: calc(100vh - 60px); + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + `, + })} +`; + +export const Heading = styled(Grid)` + max-width: 1280px; + margin: 0 auto; +`; + +export const HeadingLeft = styled(Grid)` + ${({ theme }) => ({ + [theme.breakpoints.up('md')]: css` + position: relative; + + &:after { + display: block; + position: absolute; + right: 0; + top: 0; + height: 100%; + content: ' '; + border-right: 1px solid white; + } + `, + })} +`; + +export const HeadingRight = styled(Grid)` + ${({ theme }) => ({ + [theme.breakpoints.up('md')]: css` + display: flex; + flex-direction: column; + max-height: 100%; + `, + })} +`; + +export const HeadingTitlePrefix = styled('span')` + font-weight: 600; + line-height: 1; + color: white; +`; + +export const HeadingTitle = styled('h1')` + font-size: 36px; + line-height: 1.25; + font-weight: 900; + text-align: center; + color: #FFE895; + ${({ theme }) => ({ + [theme.breakpoints.up('md')]: css` + font-size: 54px; + text-align: right; + `, + })} +`; + +export const HeadingDescription = styled('p')` + color: #7C7C7C; + font-size: 16px; + line-height: 24px; + text-align: left; + margin-bottom: 0; + + ${({ theme }) => ({ + [theme.breakpoints.up('md')]: css` + text-align: right; + `, + })} +`; + +export const HeadingLogos = styled('div')` + display: flex; + align-items: center; + gap: 12px; + margin-bottom: 24px; + width: 100%; + justify-content: center; + + ${({ theme }) => ({ + [theme.breakpoints.up('md')]: css` + justify-content: start; + `, + })} +`; + +export const HeadingPrompt = styled('div')` + font-size: 18px; + line-height: 28px; + margin-top: 24px; + ${({ theme }) => ({ + [theme.breakpoints.up('md')]: css` + margin-top: 80px; + `, + })} +`; + +export const HeadingSpacing = styled('span')` + ${({ theme }) => ({ + [theme.breakpoints.up('md')]: css` + flex: 1; + `, + })} +`; diff --git a/web/src/pages/github-campaign/_components/Section.tsx b/web/src/pages/github-campaign/_components/Section.tsx new file mode 100644 index 00000000000..b48029588dd --- /dev/null +++ b/web/src/pages/github-campaign/_components/Section.tsx @@ -0,0 +1,31 @@ +import { styled } from '@mui/material'; + +export const Section = styled('section')<{ dark?: boolean }>` + background-color: ${({ dark }) => dark ? '#141414' : '#212122'}; + padding: 120px 12px; +`; +export const SectionContent = styled('div')` + max-width: 1400px; + margin: 0 auto; +`; + +export const SectionTitle = styled('h2')` + font-weight: 700; + font-size: 48px; + line-height: 58.09px; + text-align: center; +`; + +export const SectionDescription = styled('p')` + font-weight: 700; + font-size: 24px; + line-height: 38px; + color: #B1B1B1; + text-align: center; + max-width: 1200px; + margin: 0 auto; + + strong { + color: #73D9B4; + } +`; diff --git a/web/src/pages/github-campaign/_components/TiDBCloudButton.tsx b/web/src/pages/github-campaign/_components/TiDBCloudButton.tsx new file mode 100644 index 00000000000..af65d0ddf2e --- /dev/null +++ b/web/src/pages/github-campaign/_components/TiDBCloudButton.tsx @@ -0,0 +1,23 @@ +import { Button } from '@mui/material'; +import type { ButtonProps } from '@mui/material/Button'; +import React, { type ReactNode } from 'react'; + +export const GIFT_TIDBCLOUD_BASE_URL = (process.env.GIFT_TIDBCLOUD_BASE_URL ?? '') || 'https://tidbcloud.com'; + +const utm = '?utm_source=ossinsight&utm_medium=referral&utm_campaign=plg_OSScontribution_credit_05'; + +export function TiDBCloudButton ({ children, trial = true, mt = 8, ...props }: { children: ReactNode, mt?: number, trial?: boolean } & Pick, 'sx' | 'color' | 'variant'>) { + return ( + + ); +} diff --git a/web/src/pages/github-campaign/_components/ossi-logo.png b/web/src/pages/github-campaign/_components/ossi-logo.png new file mode 100644 index 00000000000..f831b829b08 Binary files /dev/null and b/web/src/pages/github-campaign/_components/ossi-logo.png differ diff --git a/web/src/pages/github-campaign/_components/tidb-logo.png b/web/src/pages/github-campaign/_components/tidb-logo.png new file mode 100644 index 00000000000..b38480486b4 Binary files /dev/null and b/web/src/pages/github-campaign/_components/tidb-logo.png differ diff --git a/web/src/pages/github-campaign/_sections/0-heading.tsx b/web/src/pages/github-campaign/_sections/0-heading.tsx new file mode 100644 index 00000000000..f0e13051b64 --- /dev/null +++ b/web/src/pages/github-campaign/_sections/0-heading.tsx @@ -0,0 +1,81 @@ +// noinspection CssUnresolvedCustomProperty + +import { Button } from '@mui/material'; +import { ClaimForm } from '@site/src/pages/github-campaign/_components/ClaimForm'; +import { Heading, HeadingContainer, HeadingDescription, HeadingLeft, HeadingLogos, HeadingPrompt, HeadingRight, HeadingSpacing, HeadingTitle, HeadingTitlePrefix } from '@site/src/pages/github-campaign/_components/Heading'; +import { useResponsiveAuth0 } from '@site/src/theme/NavbarItem/useResponsiveAuth0'; +import React, { useState } from 'react'; + +declare module 'react' { + interface CSSProperties { + '--color1'?: string; + '--color2'?: string; + } +} + +export function HeadingSection () { + const { user, isLoading, login } = useResponsiveAuth0(); + const [claiming, setClaiming] = useState(false); + + if (claiming) { + return ; + } else { + return { + if (isGithubSub(user?.sub)) { + setClaiming(true); + } else { + void login({ connection: 'github' }).then(() => { + setClaiming(true); + }); + } + }} + />; + } +} + +function PrimaryHeading ({ loading, onClickAction }: { loading: boolean, onClickAction: () => void }) { + return ( + + + +
+ + Fuel Your Next Big Idea: +
+ TiDB Serverless Credits for Open Source Heroes +
+ + TiDB loves open-source. We contribute code, sponsor projects arround open source community, such as OssInsight, and deeply appreciate developers who actively contribute to the communityhave. +
+ As a token of our appreciation, we're offering up to $1000 in free TiDB Serverless credits to fuel open-source hero's next big idea. +
+
+
+ + + Simply log in with your GitHub account to calculate and claim your credits. + + + + OSSInsight Logo + TiDB Logo + + + +
+
+ ); +} + +function isGithubSub (sub: string | undefined) { + if (!sub) { + return false; + } + return sub.startsWith('github|'); +} diff --git a/web/src/pages/github-campaign/_sections/1-how-it-works.tsx b/web/src/pages/github-campaign/_sections/1-how-it-works.tsx new file mode 100644 index 00000000000..1a71f02c11f --- /dev/null +++ b/web/src/pages/github-campaign/_sections/1-how-it-works.tsx @@ -0,0 +1,171 @@ +import { css, styled, type Theme, useMediaQuery } from '@mui/material'; +import { Section, SectionContent, SectionTitle } from '@site/src/pages/github-campaign/_components/Section'; +import { motion } from 'framer-motion'; +import React, { Fragment } from 'react'; + +export function HowItWorks () { + const isLarge = useMediaQuery(theme => theme.breakpoints.up('md')); + + return ( + + + + How it Works + + + {items.map((item, index) => ( + + {index > 0 && } + + {item.title} + + + + + + + {item.description} + + + + ))} + + + + ); +} + +const animations = { + initial: { opacity: 0, y: -26 }, + hover: { opacity: 1, y: 0 }, +}; + +const ThisSection = motion(styled(Section)` + ${({ theme }) => ({ + [theme.breakpoints.up('lg')]: css` + padding-top: 0; + `, + })} +`); + +const ThisSectionContent = styled(SectionContent)` + display: block; + ${({ theme }) => ({ + [theme.breakpoints.up('lg')]: css` + display: flex; + gap: 48px; + + h2 { + font-size: 24px; + line-height: 36px; + } + `, + })} +`; + +const Features = motion(styled('div')` + display: flex; + gap: 24px; + align-items: center; + justify-content: space-between; + padding: 0; + list-style: none; + flex-direction: column; + + ${({ theme }) => ({ + [theme.breakpoints.up('md')]: css` + display: flex; + flex-direction: row; + align-items: flex-start; + `, + })} +`); + +const FeatureSplitter = styled('li')` + flex: 0.6; + height: 1px; + background-color: #6E6E6E; + margin-top: 64px; + display: none; + + ${({ theme }) => ({ + [theme.breakpoints.up('md')]: css` + display: block; + `, + })} +`; + +const Feature = styled('div')` + flex: 1; + max-width: 344px; +`; + +const FeatureTitle = styled('h3')` + font-size: 24px; + line-height: 36px; +`; +const FeatureDescription = motion(styled('div')` + max-width: 100%; + overflow: hidden; + font-size: 18px; + line-height: 28px; +`); + +const FeatureIndicatorBar = styled('div')` + background-color: var(--color1); + height: 28px; + border-radius: 9999px; + padding: 5px; +`; + +const FeatureIndicatorInnerCircle = styled('div')` + width: 18px; + height: 18px; + border-radius: 9px; + border: 4px solid var(--color2); + background-color: white; +`; + +const FeatureDescriptionLine = styled('div')` + margin-left: 13px; + height: 32px; + width: 1px; + background-color: var(--color1); +`; + +const FeatureDescriptionCircle = styled('div')` + margin-left: 4px; + width: 18px; + height: 18px; + border-radius: 9px; + border: 4px solid var(--color1); + background-color: white; +`; + +type Item = { + title: string; + description: string; + color1: string; + color2: string; +}; + +const items: Item[] = [ + { + title: 'Link your Github', + description: 'Developers who actively contribute to open-source projects on GitHub are eligible. We\'ll consider factors like lines of code written, commits made, and pull requests submitted.', + color1: '#B2DFF2', + color2: '#238AB5', + }, + { + title: 'Claim your Credits', + description: 'Simply sign in OssInsight with Github account. We\'ll calculate your credit allocation based on your contributions. Just claim it with one click.', + color1: '#FFE895', + color2: '#A58927', + }, + { + title: 'Start Building', + description: 'Once you have your credits, use them to build any project you want on TiDB Serverless. TiDB Serverless provides a full set of on-boarding supports and a few sets of sample data to help you get started.', + color1: '#C1F6E2', + color2: '#73D9B4', + }, +]; diff --git a/web/src/pages/github-campaign/_sections/2-introduction.tsx b/web/src/pages/github-campaign/_sections/2-introduction.tsx new file mode 100644 index 00000000000..773ab440e0c --- /dev/null +++ b/web/src/pages/github-campaign/_sections/2-introduction.tsx @@ -0,0 +1,254 @@ +import { Button, css, styled } from '@mui/material'; +import { Section, SectionContent, SectionTitle } from '@site/src/pages/github-campaign/_components/Section'; +import { TiDBCloudButton } from '@site/src/pages/github-campaign/_components/TiDBCloudButton'; +import React from 'react'; + +export function IntroductionsSection () { + return ( +
+ + + With TiDB Serverless⚡️, you can: + + + {image1} +
+

+ TiDB Serverless is a highly scalable, vector search built-in, and cost-effective serverless database, which is dedicated to powering modern applications with simple solutions. Read more. +

+

+ With it, you can: +

+
    +
  • Build highly scalable applications with ease
  • +
  • Leverage advanced features like vector search
  • +
  • Enjoy seamless integration with what you use
  • +
  • Pay only for what you use, and only beyond free credits
  • +
+ Try Free +
+
+ + With TiDB Serverless credits 💰 , you can: + + + {image2} +
+

+ Firstly, you can always get started with $0. With TiDB Serverless's generous 25GiB free quota, you can get started any project with ease. +

+
    +
  • +

    With $5-10 💰, people have spinned up ...

    +

    Hackathon projects can be listed here?

    +
  • +
  • +

    With $10 - 100 💰 💰 💰, people are building ....

    +

    Anonymous case studies

    +
  • +
  • +

    With $ 100-300 💰 💰 💰 💰 💰, people can create .....

    +

    ...

    +
  • +
+ +
+
+
+
+ ); +} + +const Content = styled('div')<{ invert?: boolean }>` + ${({ theme }) => ({ + [theme.breakpoints.up('md')]: css` + display: flex; + gap: 120px; + `, + })} + margin-top: 80px; + + > article { + order: 2; + font-size: 24px; + line-height: 41px; + + strong { + color: #FFE895; + } + + a:not(.MuiButtonBase-root ) { + color: #FFE895; + text-decoration: underline; + } + } + + > svg { + flex-shrink: 0; + display: block; + margin: 0 auto; + order: ${({ invert }) => invert ? 3 : 1}; + } +`; + +const image1 = + + + + + + + + + + + + + + + + + + + + + + + + + +; + +const image2 = + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +; diff --git a/web/src/pages/github-campaign/_sections/3-reviews.tsx b/web/src/pages/github-campaign/_sections/3-reviews.tsx new file mode 100644 index 00000000000..22b693bed69 --- /dev/null +++ b/web/src/pages/github-campaign/_sections/3-reviews.tsx @@ -0,0 +1,212 @@ +import { Masonry } from '@mui/lab'; +import { styled } from '@mui/material'; +import { Section, SectionContent, SectionTitle } from '@site/src/pages/github-campaign/_components/Section'; +import React, { type ReactNode } from 'react'; + +export function ReviewsSection () { + return ( +
+ + + Build with TiDB + + + {reviews.map((review, index) => ( + + + {review.avatar} + + + {review.username} + + + {review.bio} + + + {review.tag} + + + + + {review.content} + + + ))} + + +
+ ); +} + +const ReviewCard = styled('li')` + background-color: #141414; + border-radius: 20px; + padding: 24px; +`; + +const ReviewHeading = styled('div')` + display: flex; + gap: 24px; +`; + +const ReviewHeadingInfo = styled('div')` + font-size: 12px; + font-weight: 700; + line-height: 24px; +`; + +const ReviewHeadingUsername = styled('div')` + color: white; +`; + +const ReviewHeadingBio = styled('div')` + color: #C6C6C6; + +`; + +const ReviewHeadingTag = styled('div')` + margin-top: 4px; + width: max-content; + padding: 4px 10px; + border-radius: 20px; + background-color: var(--color2); + font-size: 12px; + font-weight: 700; + line-height: 1; + color: var(--color1); +`; + +const ReviewContent = styled('p')` + margin-top: 16px; + margin-bottom: 0; + font-size: 14px; + font-style: italic; + line-height: 32px; + font-weight: 400; + strong { + color: var(--color1); + } +`; + +type Review = { + avatar: ReactNode; + username: string; + bio: string; + tag: string; + color: string; + content: ReactNode; +}; + +const reviews: Review[] = [ + { + avatar: + + + + , + username: '@ Kentaro Kitagawa', + bio: 'Senior DBA, LINE Corporation', + tag: 'Internet', + color: '#3BBDFB', + content: <> + Scale-in and scale-out in a cluster configuration is also easy, and the ecosystem is very rich, with operation monitoring tools such as Grafana being able to be installed immediately with the installation command (TiUP). + , + }, + { + avatar: + + + + , + username: '@ Thomas Yu ', + bio: 'Founding Engineer, Chaintool', + tag: 'Web 3', + color: '#AA95FF', + content: <>TiDB Serverless is especially beneficial for experimental or early-stage features. It's cost-effective for startups, scalable, and development-friendly. , + }, + { + avatar: + + + + , + username: '@ Sky Dong', + bio: 'Founding Engineer, Chaintool', + tag: 'Web 3', + color: '#FFE790', + content: <>The ease and comfort of getting started are paramount for us, and from this perspective, TiDB Serverless perfectly addresses our needs. Also, the design concept of TiDB has a technical flair that developers find very appealing. , + }, + { + avatar: + + + + + , + username: '@ Boris Savelev', + bio: 'SRE Manager, Bolt', + tag: 'Logistics', + color: '#FF8888', + content: <>In the following years, we will definitely migrate more clusters from MySQL to TiDB, use TiCDC to set up multi-region clusters on AWS for failover, and try TiFlash for instant analytical queries. , + }, + { + avatar: + + + + , + username: '@ Henry Qin', + bio: 'Software Engineer', + tag: 'Fintech', + color: '#52CC7A', + content: <>TiDB's architecture, sort of a SQL layer on top of a key value store, was more scalable and more likely to cause fewer problems down the line. With TiDB, we don't need to worry about cross-charge transactions. That's huge. , + }, + { + avatar: + + + + + , + username: '@ Kaustav Chakravorty', + bio: 'Senior Architect, Flipkart', + tag: 'E-Commerce', + color: '#6296FF', + content: <>The NO.1 benefit is simplicity.
With TiDB, our applications can retain their SQL data model and the ACID guarantees. We don’t have to implement any kind of shareding logic, and the database management becomes simpler too., + }, + { + avatar: + + + + , + username: '@ Godwin', + bio: 'Project Owner of AI-Mon', + tag: 'AI App', + color: '#1CCFBC', + content: <>With TiDB Serverless, setting up a database is as easy as clicking a button. It handles analytics seamlessly, without the need for manual scaling. , + }, + { + avatar: + + + + , + username: '@ Eliotte', + bio: 'a high-school student, the lead developer', + tag: 'AI App', + color: '#DD7514', + content: <>We heavily utilized TiDB's serverless feature to power our backend.
This allowed us to scale our backend to handle thousands of requests per second effortlessly while keeping costs low, as we only pay for what we use. , + }, + { + avatar: + + + , + username: '@ Thomas Yu ', + bio: 'Founding Engineer, Chaintool', + tag: 'Web 3', + color: '#A9C941', + content: <>TiDB Serverless's automatic scaling capabilities allow us to swiftly scale up to meet performance demands and scale down during quieter periods for optimizing costs. , + }, +]; diff --git a/web/src/pages/github-campaign/_sections/4-contributions.tsx b/web/src/pages/github-campaign/_sections/4-contributions.tsx new file mode 100644 index 00000000000..bd43a491d60 --- /dev/null +++ b/web/src/pages/github-campaign/_sections/4-contributions.tsx @@ -0,0 +1,112 @@ +import { styled } from '@mui/material'; +import { getRepo } from '@site/src/api/core'; +import { useRemoteData } from '@site/src/components/RemoteCharts/hook'; +import { Section, SectionContent, SectionDescription, SectionTitle } from '@site/src/pages/github-campaign/_components/Section'; +import { notNullish } from '@site/src/utils/value'; +import React from 'react'; +import useSWR from 'swr'; + +export function ContributionsSection () { + const { data } = useSWR(['pingcap/tidb', 'gh:repo'], getRepo); + const repoId = data?.id; + const { data: prOverview } = useRemoteData('analyze-repo-pr-overview', { repoId }, false, notNullish(repoId)); + + const items: Array<{ count: number | string, description: string, color: string }> = [ + { + count: data?.watchers ?? '-', + description: '✨ GitHub Stars', + color: '#73D9B4', + }, + { + count: prOverview?.data[0].pull_requests ?? '-', + description: '✏️ Pull Requests', + color: '#5DC1ED', + }, + { + count: 873, + description: '👫 Contributors', + color: '#5DC1ED', + }, + ]; + + return ( +
+ + + TiDB ❤️ Open Source + + + We take pride in our open-source roots. +
+ With the developer community, we align our product, to make sure it perfectly fits modern application developer's needs. +
+ + + + + + + + + + + + + + {items.map((item, index) => ( + + {item.count} + {item.description} + + ))} + + +
+
+ ); +} + +const Content = styled('div')` + padding: 36px; + display: flex; + background-color: #141414; + border-radius: 176px; + max-width: 1440px; + margin: 0 auto; + align-items: center; + + > svg { + flex-shrink: 0; + } +`; + +const Items = styled('div')` + flex: 1; + display: flex; + justify-content: space-around; + align-items: center; + flex-wrap: wrap; + gap: 24px; +`; + +const Item = styled('div')` + display: flex; + flex-direction: column; + align-items: center; +`; + +const ItemTitle = styled('div')` + font-size: 56px; + line-height: 84px; + font-weight: 700; + color: white; +`; + +const ItemDescription = styled('div')` + color: var(--color1); + font-size: 24px; + line-height: 36px; + font-weight: 500; +`; diff --git a/web/src/pages/github-campaign/_sections/5-faq.mdx b/web/src/pages/github-campaign/_sections/5-faq.mdx new file mode 100644 index 00000000000..1b5b876ffe4 --- /dev/null +++ b/web/src/pages/github-campaign/_sections/5-faq.mdx @@ -0,0 +1,42 @@ +### Why would I need TiDB Serverless Credit? +- What is TiDB Serverless? + - wip +- What are the advantages? + - wip + +### What can I use it for? +- A: Your credits can be used towards any TiDB Serverless service, which includes storage, queries, and other cloud-based functionalities. + +### Why would TiDB commite to the open source community? +- A: TiDB believes that open source fosters innovation, collaboration, and community-driven development. By actively contributing to and supporting open-source projects, TiDB aims to create a vibrant ecosystem that benefits all participants. + +### How do I know if I’m eligible for TiDB Serverless credits? +- A: Any developer with a verifiable open-source contribution on GitHub is eligible. Simply enter your GitHub ID on the landing page to check your eligibility. + +### How can I participate in this campaign? +- A: Simply enter your GitHub username on the campaign page, and the system will automatically calculate the credits you can earn based on your open-source contributions. + +### How are my credits calculated? +- A: Credits are calculated based on your contributions to open-source projects on GitHub. The more significant and numerous your contributions, the more credits you’ll receive. We primarily consider contributions in the following areas: + - Code contributions to TiDB or related open-source projects + - Active discussions and Q&A on community forums and GitHub issues + - Creation and maintenance of open-source projects + - etc... + +### How do I claim my credits? +1. A: Once you’ve logged in with your GitHub ID and your credits have been calculated, you can redeem them by logging into your OssInsight or TiDB Cloud account. The credits will be automatically applied to your account. + +### Do my credits expire? +- A: Yes, credits will expire on Oct 30, 2025. (Or expire 12 months from the date of issuance). Make sure to utilize them within this period. + +### What happens if I mistakenly enter the wrong GitHub ID? +- A: If you enter the wrong GitHub ID, you will need to restart the process with the correct ID. Once credits are issued, they cannot be reallocated. + +### Can I transfer my credits to another user? +- A: No, credits are non-transferable and must be used by the account to which they are assigned. + +### What if I have contributions to multiple GitHub accounts? +- • Answer: You will need to provide the GitHub ID with the most significant contributions to maximize your credits. We currently only accept one GitHub ID per TiDB Cloud account. + +### How can I contact support if I face issues redeeming my credits? +- • Answer: You can reach out to our support team through ....@tidb.com \ No newline at end of file diff --git a/web/src/pages/github-campaign/_sections/5-faq.tsx b/web/src/pages/github-campaign/_sections/5-faq.tsx new file mode 100644 index 00000000000..af5669c413e --- /dev/null +++ b/web/src/pages/github-campaign/_sections/5-faq.tsx @@ -0,0 +1,17 @@ +import { Section, SectionContent, SectionTitle } from '@site/src/pages/github-campaign/_components/Section'; +import React from 'react'; +// @ts-expect-error +import Faq from './5-faq.mdx'; + +export function FaqSection () { + return ( +
+ + + FAQ + + + +
+ ); +} diff --git a/web/src/pages/github-campaign/_sections/6-legal.mdx b/web/src/pages/github-campaign/_sections/6-legal.mdx new file mode 100644 index 00000000000..17d4fd8da3c --- /dev/null +++ b/web/src/pages/github-campaign/_sections/6-legal.mdx @@ -0,0 +1,26 @@ +### General Terms +By participating in this campaign, you agree to these terms. PingCAP can change or end the campaign at any time without notice. Follow all rules, laws, and GitHub's terms of service. + +### Who Can Participate +The campaign is open to anyone, except PingCAP employees, contractors, affiliates, and their immediate family members. + +### Contributions and Rights +All contributions to the TiDB project must comply with our Contributor License Agreement (CLA) (https://cla.pingcap.net/pingcap/tidb). By contributing, you give PingCAP permission to use, modify, and share your work. + +### Rewards +TiDB Cloud credits are valid for 12 months and cannot be transferred, refunded, or exchanged for cash. PingCAP may disqualify participants who violate these terms. + +### Privacy +By participating, you agree that PingCAP can use your personal data according to our Privacy Policy (https://www.pingcap.com/privacy-policy/). Your data will only be used to run this campaign and won't be shared without your consent, except as required by law. + +### No Guarantees +PingCAP does not guarantee the availability or operation of the TiDB software, the TiDB Cloud platform, or the credits offered in this campaign. Use them at your own risk. + +### Limitation of Liability +PingCAP is not responsible for any losses or damages that may happen from participating in this campaign or using the TiDB Cloud credits. + +### Legal Stuff +This campaign follows the laws of California. Any disputes will be resolved through arbitration in San Mateo, California, USA. + +### Contact Us +For questions or concerns, please contact at https://www.pingcap.com/contact-us/. diff --git a/web/src/pages/github-campaign/_sections/6-legal.tsx b/web/src/pages/github-campaign/_sections/6-legal.tsx new file mode 100644 index 00000000000..ebb3eb20b9b --- /dev/null +++ b/web/src/pages/github-campaign/_sections/6-legal.tsx @@ -0,0 +1,20 @@ +import { Section, SectionContent, SectionTitle } from '@site/src/pages/github-campaign/_components/Section'; +import React from 'react'; +import { Collapse } from '../_components/Collapse'; +// @ts-expect-error +import Legal from './6-legal.mdx'; + +export function LegalSection () { + return ( +
+ + + Legal Statement + + + + + +
+ ); +} diff --git a/web/src/pages/github-campaign/index.tsx b/web/src/pages/github-campaign/index.tsx new file mode 100644 index 00000000000..23ea3b63055 --- /dev/null +++ b/web/src/pages/github-campaign/index.tsx @@ -0,0 +1,27 @@ +import { HeadingSection } from '@site/src/pages/github-campaign/_sections/0-heading'; +import { HowItWorks } from '@site/src/pages/github-campaign/_sections/1-how-it-works'; +import { IntroductionsSection } from '@site/src/pages/github-campaign/_sections/2-introduction'; +import { ReviewsSection } from '@site/src/pages/github-campaign/_sections/3-reviews'; +import { ContributionsSection } from '@site/src/pages/github-campaign/_sections/4-contributions'; +import { FaqSection } from '@site/src/pages/github-campaign/_sections/5-faq'; +import { LegalSection } from '@site/src/pages/github-campaign/_sections/6-legal'; +import CustomPage from '@site/src/theme/CustomPage'; +import React from 'react'; + +export default function Page () { + return ( + + + + + + + + + + ); +}