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