mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	feat: after onboarding show success box with resources (#8278)

This commit is contained in:
		
							parent
							
								
									547e41e566
								
							
						
					
					
						commit
						86e7bbc85d
					
				@ -19,6 +19,7 @@ import useProjectOverview from 'hooks/api/getters/useProjectOverview/useProjectO
 | 
			
		||||
interface IConnectSDKDialogProps {
 | 
			
		||||
    open: boolean;
 | 
			
		||||
    onClose: () => void;
 | 
			
		||||
    onFinish: () => void;
 | 
			
		||||
    project: string;
 | 
			
		||||
    environments: string[];
 | 
			
		||||
    feature?: string;
 | 
			
		||||
@ -66,6 +67,7 @@ type OnboardingStage = 'select-sdk' | 'generate-api-key' | 'test-connection';
 | 
			
		||||
export const ConnectSdkDialog = ({
 | 
			
		||||
    open,
 | 
			
		||||
    onClose,
 | 
			
		||||
    onFinish,
 | 
			
		||||
    environments,
 | 
			
		||||
    project: projectId,
 | 
			
		||||
    feature,
 | 
			
		||||
@ -76,6 +78,7 @@ export const ConnectSdkDialog = ({
 | 
			
		||||
    const [environment, setEnvironment] = useState<string | null>(null);
 | 
			
		||||
    const [apiKey, setApiKey] = useState<string | null>(null);
 | 
			
		||||
    const [stage, setStage] = useState<OnboardingStage>('select-sdk');
 | 
			
		||||
 | 
			
		||||
    const { project } = useProjectOverview(projectId, {
 | 
			
		||||
        refreshInterval: 1000,
 | 
			
		||||
    });
 | 
			
		||||
@ -166,12 +169,7 @@ export const ConnectSdkDialog = ({
 | 
			
		||||
                                    </Button>
 | 
			
		||||
                                ) : null}
 | 
			
		||||
 | 
			
		||||
                                <Button
 | 
			
		||||
                                    variant='contained'
 | 
			
		||||
                                    onClick={() => {
 | 
			
		||||
                                        onClose();
 | 
			
		||||
                                    }}
 | 
			
		||||
                                >
 | 
			
		||||
                                <Button variant='contained' onClick={onFinish}>
 | 
			
		||||
                                    Next
 | 
			
		||||
                                </Button>
 | 
			
		||||
                            </NextStepSectionSpacedContainer>
 | 
			
		||||
 | 
			
		||||
@ -9,7 +9,7 @@ interface IConnectionInformationProps {
 | 
			
		||||
    sdk: string;
 | 
			
		||||
    environment: string;
 | 
			
		||||
}
 | 
			
		||||
export const Container = styled('div')(({ theme }) => ({
 | 
			
		||||
const Container = styled('div')(({ theme }) => ({
 | 
			
		||||
    backgroundColor: theme.palette.background.sidebar,
 | 
			
		||||
    padding: theme.spacing(6, 9, 6, 9),
 | 
			
		||||
    minWidth: '400px',
 | 
			
		||||
@ -18,14 +18,14 @@ export const Container = styled('div')(({ theme }) => ({
 | 
			
		||||
    color: theme.palette.primary.contrastText,
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
export const Title = styled(Typography)(({ theme }) => ({
 | 
			
		||||
const Title = styled(Typography)(({ theme }) => ({
 | 
			
		||||
    display: 'flex',
 | 
			
		||||
    alignItems: 'center',
 | 
			
		||||
    justifyContent: 'center',
 | 
			
		||||
    fontWeight: theme.typography.fontWeightBold,
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
export const SdkInfo = styled('div')(({ theme }) => ({
 | 
			
		||||
const SdkInfo = styled('div')(({ theme }) => ({
 | 
			
		||||
    display: 'flex',
 | 
			
		||||
    flexDirection: 'row',
 | 
			
		||||
    padding: theme.spacing(4, 0, 12, 0),
 | 
			
		||||
@ -33,13 +33,13 @@ export const SdkInfo = styled('div')(({ theme }) => ({
 | 
			
		||||
    fontSize: theme.spacing(1),
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
export const Info = styled('div')(({ theme }) => ({
 | 
			
		||||
const Info = styled('div')(({ theme }) => ({
 | 
			
		||||
    display: 'flex',
 | 
			
		||||
    gap: theme.spacing(1),
 | 
			
		||||
    flexDirection: 'column',
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
export const ConnectionStatus = styled('div')(({ theme }) => ({
 | 
			
		||||
const ConnectionStatus = styled('div')(({ theme }) => ({
 | 
			
		||||
    alignItems: 'center',
 | 
			
		||||
    justifyContent: 'center',
 | 
			
		||||
    display: 'flex',
 | 
			
		||||
@ -48,7 +48,7 @@ export const ConnectionStatus = styled('div')(({ theme }) => ({
 | 
			
		||||
    fontSize: theme.fontSizes.smallBody,
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
export const StyledCheck = styled(Check)(({ theme }) => ({
 | 
			
		||||
const StyledCheck = styled(Check)(({ theme }) => ({
 | 
			
		||||
    color: theme.palette.primary.main,
 | 
			
		||||
    backgroundColor: theme.palette.background.paper,
 | 
			
		||||
    borderRadius: '50%',
 | 
			
		||||
 | 
			
		||||
@ -36,6 +36,7 @@ test('Onboarding for SDK', async () => {
 | 
			
		||||
            open={true}
 | 
			
		||||
            environments={['development', 'production']}
 | 
			
		||||
            feature='featureA'
 | 
			
		||||
            onFinish={() => {}}
 | 
			
		||||
        />,
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										153
									
								
								frontend/src/component/onboarding/flow/ProjectOnboarded.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										153
									
								
								frontend/src/component/onboarding/flow/ProjectOnboarded.tsx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,153 @@
 | 
			
		||||
import { IconButton, styled, Tooltip, Typography } from '@mui/material';
 | 
			
		||||
import CloseIcon from '@mui/icons-material/Close';
 | 
			
		||||
import Check from '@mui/icons-material/Check';
 | 
			
		||||
import People from '@mui/icons-material/People';
 | 
			
		||||
import MenuBook from '@mui/icons-material/MenuBook';
 | 
			
		||||
import { Link } from 'react-router-dom';
 | 
			
		||||
 | 
			
		||||
interface IProjectOnboardedProps {
 | 
			
		||||
    projectId: string;
 | 
			
		||||
    onClose: () => void;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const Container = styled('div')(({ theme }) => ({
 | 
			
		||||
    display: 'flex',
 | 
			
		||||
    flexDirection: 'column',
 | 
			
		||||
    backgroundColor: theme.palette.background.paper,
 | 
			
		||||
    flexBasis: '70%',
 | 
			
		||||
    borderRadius: theme.shape.borderRadiusLarge,
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
const TitleRow = styled('div')(({ theme }) => ({
 | 
			
		||||
    padding: theme.spacing(2, 4, 2, 7),
 | 
			
		||||
    borderBottom: '1px solid',
 | 
			
		||||
    borderColor: theme.palette.divider,
 | 
			
		||||
    display: 'flex',
 | 
			
		||||
    flexDirection: 'row',
 | 
			
		||||
    justifyContent: 'flex-start',
 | 
			
		||||
    gap: theme.spacing(3),
 | 
			
		||||
    alignItems: 'center',
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
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 Title = styled('div')(({ theme }) => ({
 | 
			
		||||
    display: 'flex',
 | 
			
		||||
    flexDirection: 'column',
 | 
			
		||||
    justifyContent: 'space-between',
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
const StyledCheck = styled(Check)(({ theme }) => ({
 | 
			
		||||
    backgroundColor: theme.palette.primary.main,
 | 
			
		||||
    color: theme.palette.background.paper,
 | 
			
		||||
    borderRadius: '50%',
 | 
			
		||||
    padding: theme.spacing(0.5),
 | 
			
		||||
    width: '28px',
 | 
			
		||||
    height: '28px',
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
const ColoredPeople = styled(People)(({ theme }) => ({
 | 
			
		||||
    color: theme.palette.primary.main,
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
const ColoredMenuBook = styled(MenuBook)(({ theme }) => ({
 | 
			
		||||
    color: theme.palette.primary.main,
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
export const ProjectOnboarded = ({
 | 
			
		||||
    projectId,
 | 
			
		||||
    onClose,
 | 
			
		||||
}: IProjectOnboardedProps) => {
 | 
			
		||||
    return (
 | 
			
		||||
        <Container>
 | 
			
		||||
            <TitleRow>
 | 
			
		||||
                <StyledCheck />
 | 
			
		||||
                <Title>
 | 
			
		||||
                    <Typography fontWeight='bold'>Setup completed</Typography>
 | 
			
		||||
                    <Typography variant='body2'>Next steps</Typography>
 | 
			
		||||
                </Title>
 | 
			
		||||
 | 
			
		||||
                <Tooltip title='Close' arrow sx={{ ml: 'auto' }}>
 | 
			
		||||
                    <IconButton onClick={onClose} size='small'>
 | 
			
		||||
                        <CloseIcon />
 | 
			
		||||
                    </IconButton>
 | 
			
		||||
                </Tooltip>
 | 
			
		||||
            </TitleRow>
 | 
			
		||||
            <Actions>
 | 
			
		||||
                <ActionBox>
 | 
			
		||||
                    <TitleContainer>
 | 
			
		||||
                        Expose your feature flag to users
 | 
			
		||||
                    </TitleContainer>
 | 
			
		||||
                    <Typography>
 | 
			
		||||
                        You can have fine grained control over who is exposed to
 | 
			
		||||
                        your feature flag by leveraging{' '}
 | 
			
		||||
                        <Link
 | 
			
		||||
                            className='unleash-action-button'
 | 
			
		||||
                            to={`https://docs.getunleash.io/reference/activation-strategies`}
 | 
			
		||||
                            target='_blank'
 | 
			
		||||
                            rel='noopener noreferrer'
 | 
			
		||||
                        >
 | 
			
		||||
                            strategies
 | 
			
		||||
                        </Link>
 | 
			
		||||
                        . Visit the feature flag page to start adding strategies
 | 
			
		||||
                        to control exposure.
 | 
			
		||||
                    </Typography>
 | 
			
		||||
                </ActionBox>
 | 
			
		||||
                <ActionBox>
 | 
			
		||||
                    <TitleContainer>
 | 
			
		||||
                        <ColoredPeople />
 | 
			
		||||
                        Add members to your project
 | 
			
		||||
                    </TitleContainer>
 | 
			
		||||
                    <Typography>
 | 
			
		||||
                        Unleash is best when collaborating with your co-workers.{' '}
 | 
			
		||||
                        <Link
 | 
			
		||||
                            className='unleash-action-button'
 | 
			
		||||
                            to={`/projects/${projectId}/settings/access`}
 | 
			
		||||
                        >
 | 
			
		||||
                            Add your co-workers to the project
 | 
			
		||||
                        </Link>
 | 
			
		||||
                        .
 | 
			
		||||
                    </Typography>
 | 
			
		||||
                </ActionBox>
 | 
			
		||||
                <ActionBox>
 | 
			
		||||
                    <TitleContainer>
 | 
			
		||||
                        <ColoredMenuBook />
 | 
			
		||||
                        Learn about unleash
 | 
			
		||||
                    </TitleContainer>
 | 
			
		||||
                    <Typography>
 | 
			
		||||
                        Take a deep dive through our documentation,{' '}
 | 
			
		||||
                        <Link
 | 
			
		||||
                            className='unleash-action-button'
 | 
			
		||||
                            to={`https://docs.getunleash.io/unleash-academy/foundational`}
 | 
			
		||||
                            target='_blank'
 | 
			
		||||
                            rel='noopener noreferrer'
 | 
			
		||||
                        >
 | 
			
		||||
                            starting with the foundations of Unleash
 | 
			
		||||
                        </Link>
 | 
			
		||||
                        .
 | 
			
		||||
                    </Typography>
 | 
			
		||||
                </ActionBox>
 | 
			
		||||
            </Actions>
 | 
			
		||||
        </Container>
 | 
			
		||||
    );
 | 
			
		||||
};
 | 
			
		||||
@ -45,6 +45,7 @@ import useProjectOverview from 'hooks/api/getters/useProjectOverview/useProjectO
 | 
			
		||||
import { ConnectSdkDialog } from '../../../onboarding/dialog/ConnectSdkDialog';
 | 
			
		||||
import { ProjectOnboarding } from '../../../onboarding/flow/ProjectOnboarding';
 | 
			
		||||
import { useLocalStorageState } from 'hooks/useLocalStorageState';
 | 
			
		||||
import { ProjectOnboarded } from 'component/onboarding/flow/ProjectOnboarded';
 | 
			
		||||
 | 
			
		||||
interface IPaginatedProjectFeatureTogglesProps {
 | 
			
		||||
    environments: string[];
 | 
			
		||||
@ -118,6 +119,9 @@ export const ProjectFeatureToggles = ({
 | 
			
		||||
    const [onboardingFlow, setOnboardingFlow] = useLocalStorageState<
 | 
			
		||||
        'visible' | 'closed'
 | 
			
		||||
    >(`onboarding-flow:v1-${projectId}`, 'visible');
 | 
			
		||||
    const [setupCompletedState, setSetupCompletedState] = useLocalStorageState<
 | 
			
		||||
        'hide-setup' | 'show-setup'
 | 
			
		||||
    >(`onboarding-state:v1-${projectId}`, 'hide-setup');
 | 
			
		||||
 | 
			
		||||
    const notOnboarding =
 | 
			
		||||
        !onboardingUIEnabled ||
 | 
			
		||||
@ -425,6 +429,17 @@ export const ProjectFeatureToggles = ({
 | 
			
		||||
                    />
 | 
			
		||||
                }
 | 
			
		||||
            />
 | 
			
		||||
            <ConditionallyRender
 | 
			
		||||
                condition={setupCompletedState === 'show-setup'}
 | 
			
		||||
                show={
 | 
			
		||||
                    <ProjectOnboarded
 | 
			
		||||
                        projectId={projectId}
 | 
			
		||||
                        onClose={() => {
 | 
			
		||||
                            setSetupCompletedState('hide-setup');
 | 
			
		||||
                        }}
 | 
			
		||||
                    />
 | 
			
		||||
                }
 | 
			
		||||
            />
 | 
			
		||||
            <ConditionallyRender
 | 
			
		||||
                condition={showFeaturesTable}
 | 
			
		||||
                show={
 | 
			
		||||
@ -539,6 +554,10 @@ export const ProjectFeatureToggles = ({
 | 
			
		||||
                onClose={() => {
 | 
			
		||||
                    setConnectSdkOpen(false);
 | 
			
		||||
                }}
 | 
			
		||||
                onFinish={() => {
 | 
			
		||||
                    setConnectSdkOpen(false);
 | 
			
		||||
                    setSetupCompletedState('show-setup');
 | 
			
		||||
                }}
 | 
			
		||||
                project={projectId}
 | 
			
		||||
                environments={environments}
 | 
			
		||||
                feature={
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user