diff --git a/frontend/src/component/onboarding/dialog/ConnectSdkDialog.tsx b/frontend/src/component/onboarding/dialog/ConnectSdkDialog.tsx index c77be053b1..96c16b2784 100644 --- a/frontend/src/component/onboarding/dialog/ConnectSdkDialog.tsx +++ b/frontend/src/component/onboarding/dialog/ConnectSdkDialog.tsx @@ -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(null); const [apiKey, setApiKey] = useState(null); const [stage, setStage] = useState('select-sdk'); + const { project } = useProjectOverview(projectId, { refreshInterval: 1000, }); @@ -166,12 +169,7 @@ export const ConnectSdkDialog = ({ ) : null} - diff --git a/frontend/src/component/onboarding/dialog/ConnectionInformation.tsx b/frontend/src/component/onboarding/dialog/ConnectionInformation.tsx index d405eee820..c00335507e 100644 --- a/frontend/src/component/onboarding/dialog/ConnectionInformation.tsx +++ b/frontend/src/component/onboarding/dialog/ConnectionInformation.tsx @@ -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%', diff --git a/frontend/src/component/onboarding/dialog/Onboarding.test.tsx b/frontend/src/component/onboarding/dialog/Onboarding.test.tsx index b0cf4152b3..db66d4f818 100644 --- a/frontend/src/component/onboarding/dialog/Onboarding.test.tsx +++ b/frontend/src/component/onboarding/dialog/Onboarding.test.tsx @@ -36,6 +36,7 @@ test('Onboarding for SDK', async () => { open={true} environments={['development', 'production']} feature='featureA' + onFinish={() => {}} />, ); diff --git a/frontend/src/component/onboarding/flow/ProjectOnboarded.tsx b/frontend/src/component/onboarding/flow/ProjectOnboarded.tsx new file mode 100644 index 0000000000..138b48094e --- /dev/null +++ b/frontend/src/component/onboarding/flow/ProjectOnboarded.tsx @@ -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 ( + + + + + <Typography fontWeight='bold'>Setup completed</Typography> + <Typography variant='body2'>Next steps</Typography> + + + + + + + + + + + + Expose your feature flag to users + + + You can have fine grained control over who is exposed to + your feature flag by leveraging{' '} + + strategies + + . Visit the feature flag page to start adding strategies + to control exposure. + + + + + + Add members to your project + + + Unleash is best when collaborating with your co-workers.{' '} + + Add your co-workers to the project + + . + + + + + + Learn about unleash + + + Take a deep dive through our documentation,{' '} + + starting with the foundations of Unleash + + . + + + + + ); +}; diff --git a/frontend/src/component/project/Project/PaginatedProjectFeatureToggles/ProjectFeatureToggles.tsx b/frontend/src/component/project/Project/PaginatedProjectFeatureToggles/ProjectFeatureToggles.tsx index 095087c0b3..e28dc0bda2 100644 --- a/frontend/src/component/project/Project/PaginatedProjectFeatureToggles/ProjectFeatureToggles.tsx +++ b/frontend/src/component/project/Project/PaginatedProjectFeatureToggles/ProjectFeatureToggles.tsx @@ -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 = ({ /> } /> + { + setSetupCompletedState('hide-setup'); + }} + /> + } + /> { setConnectSdkOpen(false); }} + onFinish={() => { + setConnectSdkOpen(false); + setSetupCompletedState('show-setup'); + }} project={projectId} environments={environments} feature={