mirror of
https://github.com/Unleash/unleash.git
synced 2025-01-25 00:07:47 +01:00
feat: Sdk snippets in test connection phase (#8082)
This commit is contained in:
parent
5c4d0bf99b
commit
ff31013c6d
@ -8,8 +8,15 @@ import {
|
||||
} from '@mui/material';
|
||||
import { GenerateApiKey } from './GenerateApiKey';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { type Sdk, SelectSdk } from './SelectSdk';
|
||||
import { GenrateApiKeyConcepts, SelectSdkConcepts } from './UnleashConcepts';
|
||||
import { SelectSdk } from './SelectSdk';
|
||||
import {
|
||||
ConceptsDefinitionsWrapper,
|
||||
GenrateApiKeyConcepts,
|
||||
SelectSdkConcepts,
|
||||
} from './UnleashConcepts';
|
||||
import { TestSdkConnection } from './TestSdkConnection';
|
||||
|
||||
import type { Sdk } from './sharedTypes';
|
||||
|
||||
interface IConnectSDKDialogProps {
|
||||
open: boolean;
|
||||
@ -107,7 +114,9 @@ export const ConnectSdkDialog = ({
|
||||
}}
|
||||
/>
|
||||
) : null}
|
||||
{isTestConnectionStage ? <div>Last stage</div> : null}
|
||||
{isTestConnectionStage ? (
|
||||
<TestSdkConnection sdk={sdk} apiKey={apiKey} />
|
||||
) : null}
|
||||
|
||||
{stage === 'generate-api-key' ? (
|
||||
<Navigation>
|
||||
@ -163,6 +172,9 @@ export const ConnectSdkDialog = ({
|
||||
{isLargeScreen && isGenerateApiKeyStage ? (
|
||||
<GenrateApiKeyConcepts />
|
||||
) : null}
|
||||
{isLargeScreen && isTestConnectionStage ? (
|
||||
<ConceptsDefinitionsWrapper />
|
||||
) : null}
|
||||
</Box>
|
||||
</StyledDialog>
|
||||
);
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { useProjectApiTokens } from '../../hooks/api/getters/useProjectApiTokens/useProjectApiTokens';
|
||||
import useProjectApiTokensApi from '../../hooks/api/actions/useProjectApiTokensApi/useProjectApiTokensApi';
|
||||
import { useProjectApiTokens } from 'hooks/api/getters/useProjectApiTokens/useProjectApiTokens';
|
||||
import useProjectApiTokensApi from 'hooks/api/actions/useProjectApiTokensApi/useProjectApiTokensApi';
|
||||
import { parseToken } from './parseToken';
|
||||
import useToast from '../../hooks/useToast';
|
||||
import { formatUnknownError } from '../../utils/formatUnknownError';
|
||||
import useToast from 'hooks/useToast';
|
||||
import { formatUnknownError } from 'utils/formatUnknownError';
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
@ -15,6 +15,7 @@ import { SingleSelectConfigButton } from '../common/DialogFormTemplate/ConfigBut
|
||||
import EnvironmentsIcon from '@mui/icons-material/CloudCircle';
|
||||
import { ArcherContainer, ArcherElement } from 'react-archer';
|
||||
import { useEffect } from 'react';
|
||||
import { SectionHeader } from './SharedComponents';
|
||||
|
||||
const ChooseEnvironment = ({
|
||||
environments,
|
||||
@ -79,12 +80,6 @@ const TokenExplanationBox = styled(Box)(({ theme }) => ({
|
||||
flexWrap: 'wrap',
|
||||
}));
|
||||
|
||||
const SectionHeader = styled('div')(({ theme }) => ({
|
||||
fontWeight: theme.typography.fontWeightBold,
|
||||
marginBottom: theme.spacing(1),
|
||||
fontSize: theme.typography.body1.fontSize,
|
||||
}));
|
||||
|
||||
const SectionDescription = styled('p')(({ theme }) => ({
|
||||
color: theme.palette.text.secondary,
|
||||
fontSize: theme.typography.body2.fontSize,
|
||||
|
@ -16,6 +16,8 @@ import rust from 'assets/icons/sdks/Logo-rust.svg';
|
||||
import svelte from 'assets/icons/sdks/Logo-svelte.svg';
|
||||
import vue from 'assets/icons/sdks/Logo-vue.svg';
|
||||
import { formatAssetPath } from 'utils/formatPath';
|
||||
import { SectionHeader } from './SharedComponents';
|
||||
import type { ClientSdkName, Sdk, ServerSdkName } from './sharedTypes';
|
||||
|
||||
const SpacedContainer = styled('div')(({ theme }) => ({
|
||||
padding: theme.spacing(5, 8, 8, 8),
|
||||
@ -24,12 +26,6 @@ const SpacedContainer = styled('div')(({ theme }) => ({
|
||||
gap: theme.spacing(3),
|
||||
}));
|
||||
|
||||
const PrimarySectionHeader = styled('div')(({ theme }) => ({
|
||||
fontWeight: theme.typography.fontWeightBold,
|
||||
marginBottom: theme.spacing(1),
|
||||
fontSize: theme.typography.body1.fontSize,
|
||||
}));
|
||||
|
||||
const SecondarySectionHeader = styled('div')(({ theme }) => ({
|
||||
marginTop: theme.spacing(4),
|
||||
marginBottom: theme.spacing(2),
|
||||
@ -71,7 +67,7 @@ const StyledAvatar = styled(Avatar)(({ theme }) => ({
|
||||
boxShadow: theme.shadows[2],
|
||||
}));
|
||||
|
||||
const serverSdks = [
|
||||
const serverSdks: { name: ServerSdkName; icon: string }[] = [
|
||||
{ name: 'Node', icon: node },
|
||||
{ name: 'Golang', icon: go },
|
||||
{ name: 'Ruby', icon: ruby },
|
||||
@ -82,7 +78,7 @@ const serverSdks = [
|
||||
{ name: 'Python', icon: python },
|
||||
];
|
||||
|
||||
const clientSdks = [
|
||||
const clientSdks: { name: ClientSdkName; icon: string }[] = [
|
||||
{ name: 'Javascript', icon: javascript },
|
||||
{ name: 'React', icon: react },
|
||||
{ name: 'Vue', icon: vue },
|
||||
@ -92,8 +88,6 @@ const clientSdks = [
|
||||
{ name: 'Flutter', icon: flutter },
|
||||
];
|
||||
|
||||
type SdkType = 'client' | 'frontend';
|
||||
export type Sdk = { name: string; type: SdkType };
|
||||
interface ISelectSdkProps {
|
||||
onSelect: (sdk: Sdk) => void;
|
||||
}
|
||||
@ -102,7 +96,7 @@ export const SelectSdk: FC<ISelectSdkProps> = ({ onSelect }) => {
|
||||
<SpacedContainer>
|
||||
<Typography variant='h2'>Connect an SDK to Unleash</Typography>
|
||||
<Box sx={{ mt: 4 }}>
|
||||
<PrimarySectionHeader>Select SDK</PrimarySectionHeader>
|
||||
<SectionHeader>Select SDK</SectionHeader>
|
||||
<SecondarySectionHeader>
|
||||
Server side SDKs
|
||||
</SecondarySectionHeader>
|
||||
@ -155,5 +149,3 @@ export const SelectSdk: FC<ISelectSdkProps> = ({ onSelect }) => {
|
||||
</SpacedContainer>
|
||||
);
|
||||
};
|
||||
|
||||
export const SelectSdkConcepts = () => {};
|
||||
|
7
frontend/src/component/onboarding/SharedComponents.tsx
Normal file
7
frontend/src/component/onboarding/SharedComponents.tsx
Normal file
@ -0,0 +1,7 @@
|
||||
import { styled } from '@mui/material';
|
||||
|
||||
export const SectionHeader = styled('div')(({ theme }) => ({
|
||||
fontWeight: theme.typography.fontWeightBold,
|
||||
marginBottom: theme.spacing(1),
|
||||
fontSize: theme.typography.body1.fontSize,
|
||||
}));
|
60
frontend/src/component/onboarding/TestSdkConnection.tsx
Normal file
60
frontend/src/component/onboarding/TestSdkConnection.tsx
Normal file
@ -0,0 +1,60 @@
|
||||
import type { FC } from 'react';
|
||||
import { Box, styled, Typography } from '@mui/material';
|
||||
import { SectionHeader } from './SharedComponents';
|
||||
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
||||
import type { Sdk } from './sharedTypes';
|
||||
import { codeSnippets, installCommands } from './sdkSnippets';
|
||||
|
||||
const SpacedContainer = styled('div')(({ theme }) => ({
|
||||
padding: theme.spacing(5, 8, 8, 8),
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
gap: theme.spacing(3),
|
||||
}));
|
||||
|
||||
const StyledCodeBlock = styled('pre')(({ theme }) => ({
|
||||
backgroundColor: theme.palette.background.elevation1,
|
||||
padding: theme.spacing(2),
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
overflow: 'auto',
|
||||
fontSize: theme.typography.body2.fontSize,
|
||||
wordBreak: 'break-all',
|
||||
whiteSpace: 'pre-wrap',
|
||||
}));
|
||||
|
||||
interface ITestSdkConnectionProps {
|
||||
sdk: Sdk;
|
||||
apiKey: string;
|
||||
}
|
||||
export const TestSdkConnection: FC<ITestSdkConnectionProps> = ({
|
||||
sdk,
|
||||
apiKey,
|
||||
}) => {
|
||||
const { uiConfig } = useUiConfig();
|
||||
|
||||
const clientApiUrl = `${uiConfig.unleashUrl}/api/`;
|
||||
const frontendApiUrl = `${uiConfig.unleashUrl}/api/frontend/`;
|
||||
const apiUrl = sdk.type === 'client' ? clientApiUrl : frontendApiUrl;
|
||||
const codeSnippet =
|
||||
codeSnippets[sdk.name] || `No snippet found for the ${sdk.name} SDK`;
|
||||
const installCommand =
|
||||
installCommands[sdk.name] ||
|
||||
`No install command found for the ${sdk.name} SDK`;
|
||||
|
||||
return (
|
||||
<SpacedContainer>
|
||||
<Typography variant='h2'>Connect an SDK to Unleash</Typography>
|
||||
<Box sx={{ mt: 4 }}>
|
||||
<SectionHeader>Setup the SDK</SectionHeader>
|
||||
<p>1. Install the SDK</p>
|
||||
<StyledCodeBlock>{installCommand}</StyledCodeBlock>
|
||||
<p>2. Initialize the SDK</p>
|
||||
<StyledCodeBlock>
|
||||
{codeSnippet
|
||||
.replace('<YOUR_API_TOKEN>', apiKey)
|
||||
.replace('<YOUR_API_URL>', apiUrl)}
|
||||
</StyledCodeBlock>
|
||||
</Box>
|
||||
</SpacedContainer>
|
||||
);
|
||||
};
|
@ -3,7 +3,7 @@ import { ProjectIcon } from '../common/ProjectIcon/ProjectIcon';
|
||||
import EnvironmentsIcon from '@mui/icons-material/CloudCircle';
|
||||
import CodeIcon from '@mui/icons-material/Code';
|
||||
|
||||
const ConceptsDefinitionsWrapper = styled('div')(({ theme }) => ({
|
||||
export const ConceptsDefinitionsWrapper = styled('div')(({ theme }) => ({
|
||||
backgroundColor: theme.palette.background.sidebar,
|
||||
padding: theme.spacing(12, 6, 6, 6),
|
||||
flex: 0,
|
||||
|
183
frontend/src/component/onboarding/sdkSnippets.ts
Normal file
183
frontend/src/component/onboarding/sdkSnippets.ts
Normal file
@ -0,0 +1,183 @@
|
||||
import type { SdkName } from './sharedTypes';
|
||||
|
||||
export const installCommands: Record<SdkName, string> = {
|
||||
Node: ' npm install unleash-client',
|
||||
Golang: 'go get github.com/Unleash/unleash-client-go/v3',
|
||||
Ruby: 'gem install unleash',
|
||||
PHP: 'composer require unleash/client',
|
||||
Rust: 'cargo add unleash-client',
|
||||
DotNet: `dotnet add package unleash.client
|
||||
// If you do not have a json library in your project:
|
||||
dotnet add package Newtonsoft.Json`,
|
||||
Java: `<dependency>
|
||||
<groupId>io.getunleash</groupId>
|
||||
<artifactId>unleash-client-java</artifactId>
|
||||
<version>Latest version here</version>
|
||||
</dependency>`,
|
||||
Python: 'pip install UnleashClient',
|
||||
Javascript: 'npm install unleash-proxy-client',
|
||||
React: 'npm install @unleash/proxy-client-react unleash-proxy-client',
|
||||
Vue: 'npm install @unleash/proxy-client-vue',
|
||||
Svelte: 'npm install @unleash/proxy-client-svelte',
|
||||
Swift: 'https://github.com/Unleash/unleash-proxy-client-swift',
|
||||
Android:
|
||||
'implementation("io.getunleash:unleash-android:${unleash.sdk.version}")',
|
||||
Flutter: 'flutter pub add unleash_proxy_client_flutter',
|
||||
};
|
||||
|
||||
export const codeSnippets: Record<SdkName, string> = {
|
||||
Node: `import { initialize } from 'unleash-client';
|
||||
|
||||
const unleash = initialize({
|
||||
url: '<YOUR_API_URL>',
|
||||
appName: 'unleash-onboarding-node',
|
||||
customHeaders: { Authorization: '<YOUR_API_TOKEN>' },
|
||||
});
|
||||
`,
|
||||
Golang: `import (
|
||||
"github.com/Unleash/unleash-client-go/v3"
|
||||
)
|
||||
|
||||
func init() {
|
||||
unleash.Initialize(
|
||||
unleash.WithListener(&unleash.DebugListener{}),
|
||||
unleash.WithAppName("unleash-onboarding-golang"),
|
||||
unleash.WithUrl("<YOUR_API_URL>"),
|
||||
unleash.WithCustomHeaders(http.Header{"Authorization": {"<YOUR_API_TOKEN>"}}),
|
||||
)
|
||||
}`,
|
||||
Ruby: `Unleash.configure do |config|
|
||||
config.app_name = 'unleash-onboarding-ruby'
|
||||
config.url = '<YOUR_API_URL>'
|
||||
config.custom_http_headers = {'Authorization': '<YOUR_API_TOKEN>'}
|
||||
end`,
|
||||
PHP: `<?php
|
||||
|
||||
use Unleash\\Client\\UnleashBuilder;
|
||||
|
||||
$unleash = UnleashBuilder::create()
|
||||
->withAppName('unleash-onboarding-php')
|
||||
->withAppUrl('<YOUR_API_URL>')
|
||||
->withHeader('Authorization', '<YOUR_API_TOKEN>')
|
||||
->withInstanceId('unleash-onboarding-instance')
|
||||
->build();`,
|
||||
Rust: `let client = client::ClientBuilder::default()
|
||||
.interval(500)
|
||||
.into_client::<UserFeatures, reqwest::Client>(
|
||||
"<YOUR_API_URL>",
|
||||
"unleash-onboarding-rust",
|
||||
"unleash-onboarding-instance",
|
||||
"<YOUR_API_TOKEN>",
|
||||
)?;
|
||||
client.register().await?;`,
|
||||
DotNet: `using Unleash;
|
||||
var settings = new UnleashSettings()
|
||||
{
|
||||
AppName = "unleash-onboarding-dotnet",
|
||||
UnleashApi = new Uri("<YOUR_API_URL>"),
|
||||
CustomHttpHeaders = new Dictionary<string, string>()
|
||||
{
|
||||
{"Authorization","<YOUR_API_TOKEN>" }
|
||||
}
|
||||
};`,
|
||||
Java: `UnleashConfig config = UnleashConfig.builder()
|
||||
.appName("unleash-onboarding-java")
|
||||
.instanceId("unleash-onboarding-instance")
|
||||
.unleashAPI("<YOUR_API_URL>")
|
||||
.apiKey("<YOUR_API_TOKEN>")
|
||||
.build();
|
||||
|
||||
Unleash unleash = new DefaultUnleash(config);`,
|
||||
Python: `from UnleashClient import UnleashClient
|
||||
|
||||
client = UnleashClient(
|
||||
url="<YOUR_API_URL>",
|
||||
app_name="unleash-onboarding-python",
|
||||
custom_headers={'Authorization': '<YOUR_API_TOKEN>"'})
|
||||
|
||||
client.initialize_client()`,
|
||||
Javascript: `import { UnleashClient } from 'unleash-proxy-client';
|
||||
|
||||
const unleash = new UnleashClient({
|
||||
url: '<YOUR_API_URL>',
|
||||
clientKey: '<YOUR_API_TOKEN>',
|
||||
appName: 'unleash-onboarding-javascript',
|
||||
});
|
||||
|
||||
// Start the background polling
|
||||
unleash.start();`,
|
||||
React: `import { createRoot } from 'react-dom/client';
|
||||
import { FlagProvider } from '@unleash/proxy-client-react';
|
||||
|
||||
const config = {
|
||||
url: '<YOUR_API_URL>',
|
||||
clientKey: '<YOUR_API_TOKEN>',
|
||||
refreshInterval: 15,
|
||||
appName: 'unleash-onboarding-react',
|
||||
};
|
||||
|
||||
const root = createRoot(document.getElementById('root'));
|
||||
|
||||
root.render(
|
||||
<React.StrictMode>
|
||||
<FlagProvider config={config}>
|
||||
<App />
|
||||
</FlagProvider>
|
||||
</React.StrictMode>
|
||||
);`,
|
||||
Vue: `import { createApp } from 'vue'
|
||||
import { plugin as unleashPlugin } from '@unleash/proxy-client-vue'
|
||||
// import the root component App from a single-file component.
|
||||
import App from './App.vue'
|
||||
|
||||
const config = {
|
||||
url: '<YOUR_API_URL>'',
|
||||
clientKey: '<YOUR_API_TOKEN>',
|
||||
refreshInterval: 15,
|
||||
appName: 'unleash-onboarding-vue',
|
||||
}
|
||||
|
||||
const app = createApp(App)
|
||||
app.use(unleashPlugin, { config })
|
||||
app.mount('#app')`,
|
||||
Svelte: `<script lang="ts">
|
||||
import { FlagProvider } from '@unleash/proxy-client-svelte';
|
||||
|
||||
const config = {
|
||||
url: '<YOUR_API_URL>',
|
||||
clientKey: '<YOUR_API_TOKEN>',
|
||||
refreshInterval: 15,
|
||||
appName: 'unleash-onboarding-svelte'
|
||||
};
|
||||
</script>
|
||||
|
||||
<FlagProvider {config}>
|
||||
<App />
|
||||
</FlagProvider>`,
|
||||
Swift: `import SwiftUI
|
||||
import UnleashProxyClientSwift
|
||||
|
||||
var unleash = UnleashProxyClientSwift.UnleashClient(
|
||||
unleashUrl: "<YOUR_API_URL>",
|
||||
clientKey: "<YOUR_API_TOKEN>",
|
||||
refreshInterval: 15,
|
||||
appName: "unleash-onboarding-swift",
|
||||
context: [:])
|
||||
|
||||
unleash.start()`,
|
||||
Android: `val unleash = DefaultUnleash(
|
||||
androidContext = applicationContext, // likely a reference to your Android application context
|
||||
unleashConfig = UnleashConfig.newBuilder(appName = "unleash-onboarding-android")
|
||||
.proxyUrl("<YOUR_API_URL>")
|
||||
.clientKey("<YOUR_API_TOKEN>")
|
||||
.pollingStrategy.interval(3000)
|
||||
.metricsStrategy.interval(3000)
|
||||
.build()
|
||||
)`,
|
||||
Flutter: `import 'package:unleash_proxy_client_flutter/unleash_proxy_client_flutter.dart';
|
||||
|
||||
final unleash = UnleashClient(
|
||||
url: Uri.parse('<YOUR_API_URL>'),
|
||||
clientKey: '<YOUR_API_TOKEN>',
|
||||
appName: 'unleash-onboarding-flutter');`,
|
||||
};
|
20
frontend/src/component/onboarding/sharedTypes.ts
Normal file
20
frontend/src/component/onboarding/sharedTypes.ts
Normal file
@ -0,0 +1,20 @@
|
||||
export type SdkType = 'client' | 'frontend';
|
||||
export type Sdk = { name: SdkName; type: SdkType };
|
||||
export type ServerSdkName =
|
||||
| 'Node'
|
||||
| 'Golang'
|
||||
| 'Ruby'
|
||||
| 'PHP'
|
||||
| 'Rust'
|
||||
| 'DotNet'
|
||||
| 'Java'
|
||||
| 'Python';
|
||||
export type ClientSdkName =
|
||||
| 'Javascript'
|
||||
| 'React'
|
||||
| 'Vue'
|
||||
| 'Svelte'
|
||||
| 'Swift'
|
||||
| 'Android'
|
||||
| 'Flutter';
|
||||
export type SdkName = ServerSdkName | ClientSdkName;
|
Loading…
Reference in New Issue
Block a user