mirror of
https://github.com/Unleash/unleash.git
synced 2025-02-23 00:22:19 +01:00
feat: onboarding can be now closed (#8215)
The boxes were merged and now the whole thing can be closed. 
This commit is contained in:
parent
f45b7a07b4
commit
9f5e909436
@ -33,17 +33,18 @@ import { useDefaultColumnVisibility } from './hooks/useDefaultColumnVisibility';
|
|||||||
import { TableEmptyState } from './TableEmptyState/TableEmptyState';
|
import { TableEmptyState } from './TableEmptyState/TableEmptyState';
|
||||||
import { useRowActions } from './hooks/useRowActions';
|
import { useRowActions } from './hooks/useRowActions';
|
||||||
import { useSelectedData } from './hooks/useSelectedData';
|
import { useSelectedData } from './hooks/useSelectedData';
|
||||||
import { FeatureOverviewCell } from '../../../common/Table/cells/FeatureOverviewCell/FeatureOverviewCell';
|
import { FeatureOverviewCell } from 'component/common/Table/cells/FeatureOverviewCell/FeatureOverviewCell';
|
||||||
import {
|
import {
|
||||||
useProjectFeatureSearch,
|
useProjectFeatureSearch,
|
||||||
useProjectFeatureSearchActions,
|
useProjectFeatureSearchActions,
|
||||||
} from './useProjectFeatureSearch';
|
} from './useProjectFeatureSearch';
|
||||||
import { AvatarCell } from './AvatarCell';
|
import { AvatarCell } from './AvatarCell';
|
||||||
import { ProjectOnboarding } from './ProjectOnboarding/ProjectOnboarding';
|
|
||||||
import { useUiFlag } from 'hooks/useUiFlag';
|
import { useUiFlag } from 'hooks/useUiFlag';
|
||||||
import { styled } from '@mui/material';
|
import { styled } from '@mui/material';
|
||||||
import useProjectOverview from 'hooks/api/getters/useProjectOverview/useProjectOverview';
|
import useProjectOverview from 'hooks/api/getters/useProjectOverview/useProjectOverview';
|
||||||
import { ConnectSdkDialog } from '../../../onboarding/ConnectSdkDialog';
|
import { ConnectSdkDialog } from '../../../onboarding/ConnectSdkDialog';
|
||||||
|
import { ProjectOnboarding } from './ProjectOnboarding/ProjectOnboarding';
|
||||||
|
import { useLocalStorageState } from 'hooks/useLocalStorageState';
|
||||||
|
|
||||||
interface IPaginatedProjectFeatureTogglesProps {
|
interface IPaginatedProjectFeatureTogglesProps {
|
||||||
environments: string[];
|
environments: string[];
|
||||||
@ -114,12 +115,19 @@ export const ProjectFeatureToggles = ({
|
|||||||
|
|
||||||
const isPlaceholder = Boolean(initialLoad || (loading && total));
|
const isPlaceholder = Boolean(initialLoad || (loading && total));
|
||||||
|
|
||||||
|
const [onboardingFlow, setOnboardingFlow] = useLocalStorageState<
|
||||||
|
'visible' | 'closed'
|
||||||
|
>(`onboarding-flow:v1-${projectId}`, 'visible');
|
||||||
|
|
||||||
const notOnboarding =
|
const notOnboarding =
|
||||||
!onboardingUIEnabled ||
|
!onboardingUIEnabled ||
|
||||||
(onboardingUIEnabled &&
|
(onboardingUIEnabled &&
|
||||||
project.onboardingStatus.status === 'onboarded');
|
project.onboardingStatus.status === 'onboarded') ||
|
||||||
|
onboardingFlow === 'closed';
|
||||||
const isOnboarding =
|
const isOnboarding =
|
||||||
onboardingUIEnabled && project.onboardingStatus.status !== 'onboarded';
|
onboardingUIEnabled &&
|
||||||
|
project.onboardingStatus.status !== 'onboarded' &&
|
||||||
|
onboardingFlow === 'visible';
|
||||||
const showFeaturesTable =
|
const showFeaturesTable =
|
||||||
(total !== undefined && total > 0) || notOnboarding;
|
(total !== undefined && total > 0) || notOnboarding;
|
||||||
|
|
||||||
@ -413,6 +421,7 @@ export const ProjectFeatureToggles = ({
|
|||||||
<ProjectOnboarding
|
<ProjectOnboarding
|
||||||
projectId={projectId}
|
projectId={projectId}
|
||||||
setConnectSdkOpen={setConnectSdkOpen}
|
setConnectSdkOpen={setConnectSdkOpen}
|
||||||
|
setOnboardingFlow={setOnboardingFlow}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { render } from 'utils/testRenderer';
|
import { render } from 'utils/testRenderer';
|
||||||
import { Route, Routes } from 'react-router-dom';
|
import { Route, Routes } from 'react-router-dom';
|
||||||
import { testServerRoute, testServerSetup } from 'utils/testServer';
|
import { testServerRoute, testServerSetup } from 'utils/testServer';
|
||||||
import { WelcomeToProject } from './WelcomeToProject';
|
import { ProjectOnboarding } from './ProjectOnboarding';
|
||||||
import { screen } from '@testing-library/react';
|
import { screen } from '@testing-library/react';
|
||||||
|
|
||||||
const server = testServerSetup();
|
const server = testServerSetup();
|
||||||
@ -18,9 +18,10 @@ test('Project can start onboarding', async () => {
|
|||||||
<Route
|
<Route
|
||||||
path={'/projects/:projectId'}
|
path={'/projects/:projectId'}
|
||||||
element={
|
element={
|
||||||
<WelcomeToProject
|
<ProjectOnboarding
|
||||||
projectId={projectId}
|
projectId={projectId}
|
||||||
setConnectSdkOpen={() => {}}
|
setConnectSdkOpen={() => {}}
|
||||||
|
setOnboardingFlow={() => {}}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
@ -45,9 +46,10 @@ test('Project can connect SDK', async () => {
|
|||||||
<Route
|
<Route
|
||||||
path={'/projects/:projectId'}
|
path={'/projects/:projectId'}
|
||||||
element={
|
element={
|
||||||
<WelcomeToProject
|
<ProjectOnboarding
|
||||||
projectId={projectId}
|
projectId={projectId}
|
||||||
setConnectSdkOpen={() => {}}
|
setConnectSdkOpen={() => {}}
|
||||||
|
setOnboardingFlow={() => {}}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
@ -1,29 +1,204 @@
|
|||||||
import { styled } from '@mui/material';
|
import { IconButton, styled, Tooltip, Typography } from '@mui/material';
|
||||||
import { WelcomeToProject } from './WelcomeToProject';
|
import Add from '@mui/icons-material/Add';
|
||||||
|
import { CREATE_FEATURE } from 'component/providers/AccessProvider/permissions';
|
||||||
|
import { FlagCreationButton } from '../ProjectFeatureTogglesHeader/ProjectFeatureTogglesHeader';
|
||||||
|
import ResponsiveButton from 'component/common/ResponsiveButton/ResponsiveButton';
|
||||||
|
import useProjectOverview from 'hooks/api/getters/useProjectOverview/useProjectOverview';
|
||||||
import { SdkExample } from './SdkExample';
|
import { SdkExample } from './SdkExample';
|
||||||
|
import CloseIcon from '@mui/icons-material/Close';
|
||||||
|
|
||||||
interface IProjectOnboardingProps {
|
interface IProjectOnboardingProps {
|
||||||
projectId: string;
|
projectId: string;
|
||||||
setConnectSdkOpen: (open: boolean) => void;
|
setConnectSdkOpen: (open: boolean) => void;
|
||||||
|
setOnboardingFlow: (status: 'visible' | 'closed') => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ICreateFlagProps {
|
||||||
|
projectId: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Container = styled('div')(({ theme }) => ({
|
const Container = styled('div')(({ theme }) => ({
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
width: '100%',
|
flexDirection: 'column',
|
||||||
|
backgroundColor: theme.palette.background.paper,
|
||||||
|
flexBasis: '70%',
|
||||||
|
borderRadius: theme.shape.borderRadiusLarge,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const TitleBox = styled('div')(({ theme }) => ({
|
||||||
|
padding: theme.spacing(2, 7, 2, 7),
|
||||||
|
borderBottom: '1px solid',
|
||||||
|
borderColor: theme.palette.divider,
|
||||||
|
minHeight: '80px',
|
||||||
|
}));
|
||||||
|
|
||||||
|
const Actions = styled('div')(({ theme }) => ({
|
||||||
|
display: 'flex',
|
||||||
|
flexGrow: 1,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const ActionBox = styled('div')(({ theme }) => ({
|
||||||
|
flexBasis: '50%',
|
||||||
|
padding: theme.spacing(3, 2, 6, 8),
|
||||||
|
display: 'flex',
|
||||||
|
gap: theme.spacing(3),
|
||||||
|
flexDirection: 'column',
|
||||||
|
}));
|
||||||
|
|
||||||
|
const TitleContainer = styled('div')(({ theme }) => ({
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'row',
|
||||||
gap: theme.spacing(2),
|
gap: theme.spacing(2),
|
||||||
|
alignItems: 'center',
|
||||||
|
fontSize: theme.spacing(1.75),
|
||||||
|
fontWeight: 'bold',
|
||||||
|
}));
|
||||||
|
|
||||||
|
const NeutralCircleContainer = styled('span')(({ theme }) => ({
|
||||||
|
width: '28px',
|
||||||
|
height: '28px',
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
backgroundColor: theme.palette.neutral.border,
|
||||||
|
borderRadius: '50%',
|
||||||
|
}));
|
||||||
|
|
||||||
|
const MainCircleContainer = styled(NeutralCircleContainer)(({ theme }) => ({
|
||||||
|
backgroundColor: theme.palette.primary.main,
|
||||||
|
color: theme.palette.background.paper,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const ExistingFlagContainer = styled('div')(({ theme }) => ({
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
gap: theme.spacing(3),
|
||||||
|
height: '100%',
|
||||||
|
}));
|
||||||
|
|
||||||
|
const SuccessContainer = styled('div')(({ theme }) => ({
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
|
||||||
|
fontSize: theme.spacing(1.75),
|
||||||
|
fontWeight: 'bold',
|
||||||
|
backgroundColor: theme.palette.success.light,
|
||||||
|
borderRadius: theme.shape.borderRadiusLarge,
|
||||||
|
padding: theme.spacing(2, 2, 2, 2),
|
||||||
|
}));
|
||||||
|
|
||||||
|
const TitleRow = styled('div')(({ theme }) => ({
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'row',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
alignItems: 'center',
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const ProjectOnboarding = ({
|
export const ProjectOnboarding = ({
|
||||||
projectId,
|
projectId,
|
||||||
setConnectSdkOpen,
|
setConnectSdkOpen,
|
||||||
|
setOnboardingFlow,
|
||||||
}: IProjectOnboardingProps) => {
|
}: IProjectOnboardingProps) => {
|
||||||
|
const { project } = useProjectOverview(projectId);
|
||||||
|
const isFirstFlagCreated =
|
||||||
|
project.onboardingStatus.status === 'first-flag-created';
|
||||||
|
|
||||||
|
const closeOnboardingFlow = () => {
|
||||||
|
setOnboardingFlow('closed');
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
<WelcomeToProject
|
<TitleBox>
|
||||||
projectId={projectId}
|
<TitleRow>
|
||||||
setConnectSdkOpen={setConnectSdkOpen}
|
<Typography fontWeight='bold'>
|
||||||
/>
|
Welcome to your project
|
||||||
<SdkExample />
|
</Typography>
|
||||||
|
<Tooltip title='Close' arrow>
|
||||||
|
<IconButton onClick={closeOnboardingFlow} size='small'>
|
||||||
|
<CloseIcon />
|
||||||
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
|
</TitleRow>
|
||||||
|
<Typography variant='body2'>
|
||||||
|
Complete the steps below to start working with this project
|
||||||
|
</Typography>
|
||||||
|
</TitleBox>
|
||||||
|
<Actions>
|
||||||
|
<ActionBox>
|
||||||
|
{project.onboardingStatus.status ===
|
||||||
|
'first-flag-created' ? (
|
||||||
|
<ExistingFlag />
|
||||||
|
) : (
|
||||||
|
<CreateFlag projectId={projectId} />
|
||||||
|
)}
|
||||||
|
</ActionBox>
|
||||||
|
<ActionBox>
|
||||||
|
<TitleContainer>
|
||||||
|
<NeutralCircleContainer>2</NeutralCircleContainer>
|
||||||
|
Connect an SDK
|
||||||
|
</TitleContainer>
|
||||||
|
<Typography>
|
||||||
|
Your project is not yet connected to any SDK. To start
|
||||||
|
using your feature flag, connect an SDK to the project.
|
||||||
|
</Typography>
|
||||||
|
<ResponsiveButton
|
||||||
|
onClick={() => {
|
||||||
|
setConnectSdkOpen(true);
|
||||||
|
}}
|
||||||
|
maxWidth='200px'
|
||||||
|
projectId={projectId}
|
||||||
|
Icon={Add}
|
||||||
|
disabled={!isFirstFlagCreated}
|
||||||
|
permission={CREATE_FEATURE}
|
||||||
|
>
|
||||||
|
Connect SDK
|
||||||
|
</ResponsiveButton>
|
||||||
|
</ActionBox>
|
||||||
|
<ActionBox>
|
||||||
|
<SdkExample />
|
||||||
|
</ActionBox>
|
||||||
|
</Actions>
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const CreateFlag = ({ projectId }: ICreateFlagProps) => {
|
||||||
|
const { refetch } = useProjectOverview(projectId);
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<TitleContainer>
|
||||||
|
<NeutralCircleContainer>1</NeutralCircleContainer>
|
||||||
|
Create a feature flag
|
||||||
|
</TitleContainer>
|
||||||
|
<Typography>
|
||||||
|
<div>The project currently holds no feature flags.</div>
|
||||||
|
<div>Create one to get started.</div>
|
||||||
|
</Typography>
|
||||||
|
<FlagCreationButton
|
||||||
|
text='Create flag'
|
||||||
|
skipNavigationOnComplete={true}
|
||||||
|
onSuccess={refetch}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const ExistingFlag = () => {
|
||||||
|
return (
|
||||||
|
<ExistingFlagContainer>
|
||||||
|
<TitleContainer>
|
||||||
|
<MainCircleContainer>✓</MainCircleContainer>
|
||||||
|
Create a feature flag
|
||||||
|
</TitleContainer>
|
||||||
|
<SuccessContainer>
|
||||||
|
<Typography fontWeight='bold' variant='body2'>
|
||||||
|
Congratulations! You have created your first flag
|
||||||
|
</Typography>
|
||||||
|
<Typography variant='body2'>
|
||||||
|
Click into the flag below to customize the flag further
|
||||||
|
</Typography>
|
||||||
|
</SuccessContainer>
|
||||||
|
</ExistingFlagContainer>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
@ -4,28 +4,13 @@ import Select from 'component/common/select';
|
|||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { allSdks } from '../../../../onboarding/sharedTypes';
|
import { allSdks } from '../../../../onboarding/sharedTypes';
|
||||||
|
|
||||||
const Container = styled('div')(({ theme }) => ({
|
const TitleContainer = styled('div')(({ theme }) => ({
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
flexDirection: 'column',
|
flexDirection: 'row',
|
||||||
backgroundColor: theme.palette.background.paper,
|
gap: theme.spacing(2),
|
||||||
flexBasis: '30%',
|
|
||||||
borderRadius: theme.shape.borderRadiusLarge,
|
|
||||||
}));
|
|
||||||
|
|
||||||
const TitleBox = styled('div')(({ theme }) => ({
|
|
||||||
padding: theme.spacing(2, 7, 2, 7),
|
|
||||||
borderBottom: '1px solid',
|
|
||||||
borderColor: theme.palette.divider,
|
|
||||||
minHeight: '80px',
|
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
display: 'flex',
|
fontSize: theme.spacing(1.75),
|
||||||
}));
|
fontWeight: 'bold',
|
||||||
|
|
||||||
const ContentBox = styled('div')(({ theme }) => ({
|
|
||||||
padding: theme.spacing(3, 2, 6, 8),
|
|
||||||
display: 'flex',
|
|
||||||
gap: theme.spacing(3),
|
|
||||||
flexDirection: 'column',
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const StyledLink = styled(Link)({
|
const StyledLink = styled(Link)({
|
||||||
@ -45,27 +30,22 @@ export const SdkExample = () => {
|
|||||||
setSelectedSdk(event.target.value);
|
setSelectedSdk(event.target.value);
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<Container>
|
<>
|
||||||
<TitleBox>
|
<TitleContainer>View SDK Example</TitleContainer>
|
||||||
<Typography fontWeight='bold'>View SDK Example</Typography>
|
<Typography>
|
||||||
</TitleBox>
|
Choose your preferred SDK to view an example
|
||||||
|
</Typography>
|
||||||
<ContentBox>
|
<Select
|
||||||
<Typography>
|
id='sdk-select'
|
||||||
See an example implementation of your preferred SDK.
|
name='sdk'
|
||||||
</Typography>
|
options={sdkOptions}
|
||||||
<Select
|
value={selectedSdk}
|
||||||
id='sdk-select'
|
onChange={onChange}
|
||||||
name='sdk'
|
style={{
|
||||||
options={sdkOptions}
|
width: '60%',
|
||||||
value={selectedSdk}
|
}}
|
||||||
onChange={onChange}
|
/>
|
||||||
style={{
|
<StyledLink to={``}>Go to example</StyledLink>
|
||||||
width: '60%',
|
</>
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<StyledLink to={``}>Go to example</StyledLink>
|
|
||||||
</ContentBox>
|
|
||||||
</Container>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,179 +0,0 @@
|
|||||||
import { styled, Typography } from '@mui/material';
|
|
||||||
import Add from '@mui/icons-material/Add';
|
|
||||||
import { CREATE_FEATURE } from 'component/providers/AccessProvider/permissions';
|
|
||||||
import { FlagCreationButton } from '../ProjectFeatureTogglesHeader/ProjectFeatureTogglesHeader';
|
|
||||||
import ResponsiveButton from 'component/common/ResponsiveButton/ResponsiveButton';
|
|
||||||
import useProjectOverview from 'hooks/api/getters/useProjectOverview/useProjectOverview';
|
|
||||||
|
|
||||||
interface IWelcomeToProjectProps {
|
|
||||||
projectId: string;
|
|
||||||
setConnectSdkOpen: (open: boolean) => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ICreateFlagProps {
|
|
||||||
projectId: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Container = styled('div')(({ theme }) => ({
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column',
|
|
||||||
backgroundColor: theme.palette.background.paper,
|
|
||||||
flexBasis: '70%',
|
|
||||||
borderRadius: theme.shape.borderRadiusLarge,
|
|
||||||
}));
|
|
||||||
|
|
||||||
const TitleBox = styled('div')(({ theme }) => ({
|
|
||||||
padding: theme.spacing(2, 7, 2, 7),
|
|
||||||
borderBottom: '1px solid',
|
|
||||||
borderColor: theme.palette.divider,
|
|
||||||
minHeight: '80px',
|
|
||||||
}));
|
|
||||||
|
|
||||||
const Actions = styled('div')(({ theme }) => ({
|
|
||||||
display: 'flex',
|
|
||||||
flexGrow: 1,
|
|
||||||
}));
|
|
||||||
|
|
||||||
const ActionBox = styled('div')(({ theme }) => ({
|
|
||||||
flexBasis: '50%',
|
|
||||||
padding: theme.spacing(3, 2, 6, 8),
|
|
||||||
display: 'flex',
|
|
||||||
gap: theme.spacing(3),
|
|
||||||
flexDirection: 'column',
|
|
||||||
}));
|
|
||||||
|
|
||||||
const TitleContainer = styled('div')(({ theme }) => ({
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'row',
|
|
||||||
gap: theme.spacing(2),
|
|
||||||
alignItems: 'center',
|
|
||||||
fontSize: theme.spacing(1.75),
|
|
||||||
fontWeight: 'bold',
|
|
||||||
}));
|
|
||||||
|
|
||||||
const NeutralCircleContainer = styled('span')(({ theme }) => ({
|
|
||||||
width: '28px',
|
|
||||||
height: '28px',
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'center',
|
|
||||||
backgroundColor: theme.palette.neutral.border,
|
|
||||||
borderRadius: '50%',
|
|
||||||
}));
|
|
||||||
|
|
||||||
const MainCircleContainer = styled(NeutralCircleContainer)(({ theme }) => ({
|
|
||||||
backgroundColor: theme.palette.primary.main,
|
|
||||||
color: theme.palette.background.paper,
|
|
||||||
}));
|
|
||||||
|
|
||||||
const ExistingFlagContainer = styled('div')(({ theme }) => ({
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column',
|
|
||||||
gap: theme.spacing(3),
|
|
||||||
height: '100%',
|
|
||||||
}));
|
|
||||||
|
|
||||||
const SuccessContainer = styled('div')(({ theme }) => ({
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column',
|
|
||||||
|
|
||||||
fontSize: theme.spacing(1.75),
|
|
||||||
fontWeight: 'bold',
|
|
||||||
backgroundColor: theme.palette.success.light,
|
|
||||||
borderRadius: theme.shape.borderRadiusLarge,
|
|
||||||
padding: theme.spacing(2, 2, 2, 2),
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const WelcomeToProject = ({
|
|
||||||
projectId,
|
|
||||||
setConnectSdkOpen,
|
|
||||||
}: IWelcomeToProjectProps) => {
|
|
||||||
const { project, refetch } = useProjectOverview(projectId);
|
|
||||||
const isFirstFlagCreated =
|
|
||||||
project.onboardingStatus.status === 'first-flag-created';
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Container>
|
|
||||||
<TitleBox>
|
|
||||||
<Typography fontWeight='bold'>
|
|
||||||
Welcome to your project
|
|
||||||
</Typography>
|
|
||||||
<Typography variant='body2'>
|
|
||||||
Complete the steps below to start working with this project
|
|
||||||
</Typography>
|
|
||||||
</TitleBox>
|
|
||||||
<Actions>
|
|
||||||
<ActionBox>
|
|
||||||
{project.onboardingStatus.status ===
|
|
||||||
'first-flag-created' ? (
|
|
||||||
<ExistingFlag />
|
|
||||||
) : (
|
|
||||||
<CreateFlag projectId={projectId} />
|
|
||||||
)}
|
|
||||||
</ActionBox>
|
|
||||||
<ActionBox>
|
|
||||||
<TitleContainer>
|
|
||||||
<NeutralCircleContainer>2</NeutralCircleContainer>
|
|
||||||
Connect an SDK
|
|
||||||
</TitleContainer>
|
|
||||||
<Typography>
|
|
||||||
Your project is not yet connected to any SDK. To start
|
|
||||||
using your feature flag, connect an SDK to the project.
|
|
||||||
</Typography>
|
|
||||||
<ResponsiveButton
|
|
||||||
onClick={() => {
|
|
||||||
setConnectSdkOpen(true);
|
|
||||||
}}
|
|
||||||
maxWidth='200px'
|
|
||||||
projectId={projectId}
|
|
||||||
Icon={Add}
|
|
||||||
disabled={!isFirstFlagCreated}
|
|
||||||
permission={CREATE_FEATURE}
|
|
||||||
>
|
|
||||||
Connect SDK
|
|
||||||
</ResponsiveButton>
|
|
||||||
</ActionBox>
|
|
||||||
</Actions>
|
|
||||||
</Container>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const CreateFlag = ({ projectId }: ICreateFlagProps) => {
|
|
||||||
const { refetch } = useProjectOverview(projectId);
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<TitleContainer>
|
|
||||||
<NeutralCircleContainer>1</NeutralCircleContainer>
|
|
||||||
Create a feature flag
|
|
||||||
</TitleContainer>
|
|
||||||
<Typography>
|
|
||||||
<div>The project currently holds no feature flags.</div>
|
|
||||||
<div>Create one to get started.</div>
|
|
||||||
</Typography>
|
|
||||||
<FlagCreationButton
|
|
||||||
text='Create flag'
|
|
||||||
skipNavigationOnComplete={true}
|
|
||||||
onSuccess={refetch}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const ExistingFlag = () => {
|
|
||||||
return (
|
|
||||||
<ExistingFlagContainer>
|
|
||||||
<TitleContainer>
|
|
||||||
<MainCircleContainer>✓</MainCircleContainer>
|
|
||||||
Create a feature flag
|
|
||||||
</TitleContainer>
|
|
||||||
<SuccessContainer>
|
|
||||||
<Typography fontWeight='bold' variant='body2'>
|
|
||||||
Congratulations! You have created your first flag
|
|
||||||
</Typography>
|
|
||||||
<Typography variant='body2'>
|
|
||||||
Click into the flag below to customize the flag further
|
|
||||||
</Typography>
|
|
||||||
</SuccessContainer>
|
|
||||||
</ExistingFlagContainer>
|
|
||||||
);
|
|
||||||
};
|
|
Loading…
Reference in New Issue
Block a user