diff --git a/frontend/src/component/onboarding/ConnectSdkDialog.tsx b/frontend/src/component/onboarding/ConnectSdkDialog.tsx index 53fa95cf82bd..ec4b9e3305a4 100644 --- a/frontend/src/component/onboarding/ConnectSdkDialog.tsx +++ b/frontend/src/component/onboarding/ConnectSdkDialog.tsx @@ -7,8 +7,8 @@ import { useTheme, } from '@mui/material'; import { GenrateApiKeyConcepts, GenerateApiKey } from './GenerateApiKey'; -import { useState } from 'react'; -import { SelectSdk } from './SelectSdk'; +import { useEffect, useState } from 'react'; +import { type Sdk, SelectSdk } from './SelectSdk'; interface IConnectSDKDialogProps { open: boolean; @@ -57,7 +57,7 @@ const NextStepSectionSpacedContainer = styled('div')(({ theme }) => ({ type OnboardingStage = | { name: 'select-sdk' } - | { name: 'generate-api-key'; sdkType: 'CLIENT' | 'FRONTEND' } + | { name: 'generate-api-key' } | { name: 'test-connection' }; export const ConnectSdkDialog = ({ @@ -68,25 +68,48 @@ export const ConnectSdkDialog = ({ }: IConnectSDKDialogProps) => { const theme = useTheme(); const isLargeScreen = useMediaQuery(theme.breakpoints.up('lg')); + const [sdk, setSdk] = useState(null); + const [environment, setEnvironment] = useState(null); const [stage, setStage] = useState({ name: 'select-sdk' }); + useEffect(() => { + if (environments.length > 0) { + setEnvironment(environments[0]); + } + }, [JSON.stringify(environments)]); + return ( - {stage.name === 'select-sdk' ? : null} - {stage.name === 'generate-api-key' ? ( + {stage.name === 'select-sdk' ? ( + { + setSdk(sdk); + setStage({ name: 'generate-api-key' }); + }} + /> + ) : null} + {stage.name === 'generate-api-key' && sdk && environment ? ( ) : null} {stage.name === 'generate-api-key' ? ( - diff --git a/frontend/src/component/onboarding/GenerateApiKey.tsx b/frontend/src/component/onboarding/GenerateApiKey.tsx index 985a44b15e2c..e4b7385e1fff 100644 --- a/frontend/src/component/onboarding/GenerateApiKey.tsx +++ b/frontend/src/component/onboarding/GenerateApiKey.tsx @@ -1,4 +1,3 @@ -import { useEffect, useState } from 'react'; import { useProjectApiTokens } from '../../hooks/api/getters/useProjectApiTokens/useProjectApiTokens'; import useProjectApiTokensApi from '../../hooks/api/actions/useProjectApiTokensApi/useProjectApiTokensApi'; import { parseToken } from './parseToken'; @@ -263,26 +262,22 @@ export const GenrateApiKeyConcepts = () => ( interface GenerateApiKeyProps { project: string; environments: string[]; - sdkType: 'CLIENT' | 'FRONTEND'; + environment: string; + sdkType: 'client' | 'frontend'; + onEnvSelect: (env: string) => void; } export const GenerateApiKey = ({ environments, + environment, project, sdkType, + onEnvSelect, }: GenerateApiKeyProps) => { - const [environment, setEnvironment] = useState(''); - - useEffect(() => { - if (environments.length > 0) { - setEnvironment(environments[0]); - } - }, [JSON.stringify(environments)]); - const { tokens, refetch: refreshTokens } = useProjectApiTokens(project); const { createToken, loading: creatingToken } = useProjectApiTokensApi(); const currentEnvironmentToken = tokens.find( - (token) => token.environment === environment, + (token) => token.environment === environment && token.type === sdkType, ); const parsedToken = parseToken(currentEnvironmentToken?.secret); @@ -318,7 +313,7 @@ export const GenerateApiKey = ({ ) : null} diff --git a/frontend/src/component/onboarding/SelectSdk.tsx b/frontend/src/component/onboarding/SelectSdk.tsx index 3f18e1423960..3e0c165c99bc 100644 --- a/frontend/src/component/onboarding/SelectSdk.tsx +++ b/frontend/src/component/onboarding/SelectSdk.tsx @@ -1,24 +1,117 @@ -import { Box, styled, Typography } from '@mui/material'; +import { Box, Link, styled, Typography } from '@mui/material'; +import type { FC } from 'react'; const SpacedContainer = styled('div')(({ theme }) => ({ - padding: theme.spacing(5, 8, 3, 8), + padding: theme.spacing(5, 8, 8, 8), display: 'flex', flexDirection: 'column', gap: theme.spacing(3), })); -const SectionHeader = styled('div')(({ theme }) => ({ +const PrimarySectionHeader = styled('div')(({ theme }) => ({ fontWeight: theme.fontWeight.bold, marginBottom: theme.spacing(1), fontSize: theme.fontSizes.bodySize, })); -export const SelectSdk = () => { +const SecondarySectionHeader = styled('div')(({ theme }) => ({ + marginTop: theme.spacing(4), + marginBottom: theme.spacing(2), + fontSize: theme.fontSizes.bodySize, +})); + +const SdkListSection = styled('div')(({ theme }) => ({ + backgroundColor: theme.palette.background.elevation1, + borderRadius: theme.shape.borderRadius, + padding: theme.spacing(3, 6), + display: 'flex', + gap: theme.spacing(2), + alignItems: 'center', + justifyContent: 'flex-start', + flexWrap: 'wrap', +})); + +const SdkTile = styled('div')(({ theme }) => ({ + fontSize: theme.fontSizes.smallBody, + backgroundColor: theme.palette.common.white, + borderRadius: theme.shape.borderRadius, + padding: theme.spacing(2), + display: 'flex', + justifyContent: 'space-between', + width: '170px', +})); + +const serverSdks = [ + { name: 'Node' }, + { name: 'Golang' }, + { name: 'Ruby' }, + { name: 'PHP' }, + { name: 'Rust' }, + { name: 'DotNet' }, + { name: 'Java' }, + { name: 'Python' }, +]; + +const clientSdks = [ + { name: 'Javascript' }, + { name: 'React' }, + { name: 'Vue' }, + { name: 'Svelte' }, + { name: 'Swift' }, + { name: 'Android' }, + { name: 'Flutter' }, +]; + +type SdkType = 'client' | 'frontend'; +export type Sdk = { name: string; type: SdkType }; +interface ISelectSdkProps { + onSelect: (sdk: Sdk) => void; +} +export const SelectSdk: FC = ({ onSelect }) => { return ( Connect an SDK to Unleash - Select SDK + Select SDK + + Server side SDKs + + + {serverSdks.map((sdk) => ( + + {sdk.name}{' '} + + onSelect({ name: sdk.name, type: 'client' }) + } + component='button' + > + Select + + + ))} + + + Client side SDKs + + + {clientSdks.map((sdk) => ( + + {sdk.name}{' '} + + onSelect({ + name: sdk.name, + type: 'frontend', + }) + } + component='button' + > + Select + + + ))} + );