mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	feat: connection status bubble (#8099)
Fully working cycle 
This commit is contained in:
		
							parent
							
								
									397b44bfd3
								
							
						
					
					
						commit
						01fb748c01
					
				@ -0,0 +1,44 @@
 | 
			
		||||
import { alpha, Avatar, styled } from '@mui/material';
 | 
			
		||||
 | 
			
		||||
export const PulsingAvatar = styled(Avatar, {
 | 
			
		||||
    shouldForwardProp: (prop) => prop !== 'active',
 | 
			
		||||
})<{ active: boolean }>(({ theme, active }) => ({
 | 
			
		||||
    transition: 'background-color 0.5s ease',
 | 
			
		||||
    color: theme.palette.common.white,
 | 
			
		||||
    backgroundColor: active
 | 
			
		||||
        ? theme.palette.primary.main
 | 
			
		||||
        : theme.palette.divider,
 | 
			
		||||
    '@keyframes pulse': {
 | 
			
		||||
        '0%': {
 | 
			
		||||
            boxShadow: `0 0 0 0px ${alpha(theme.palette.primary.main, 0.7)}`,
 | 
			
		||||
        },
 | 
			
		||||
        '100%': {
 | 
			
		||||
            boxShadow: `0 0 0 20px ${alpha(theme.palette.primary.main, 0.0)}`,
 | 
			
		||||
        },
 | 
			
		||||
    },
 | 
			
		||||
    animation: active ? 'pulse 2s infinite' : '',
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Temporary component until we decide how all the colors will look like
 | 
			
		||||
 * Then we can use PulsingAvatar with a color prop perhaps
 | 
			
		||||
 * PulsingAvatar was not working nicely on purple background
 | 
			
		||||
 */
 | 
			
		||||
export const WhitePulsingAvatar = styled(Avatar, {
 | 
			
		||||
    shouldForwardProp: (prop) => prop !== 'active',
 | 
			
		||||
})<{ active: boolean }>(({ theme, active }) => ({
 | 
			
		||||
    transition: 'background-color 0.5s ease',
 | 
			
		||||
    color: theme.palette.primary.main,
 | 
			
		||||
    backgroundColor: active
 | 
			
		||||
        ? theme.palette.background.default
 | 
			
		||||
        : theme.palette.divider,
 | 
			
		||||
    '@keyframes pulse': {
 | 
			
		||||
        '0%': {
 | 
			
		||||
            boxShadow: `0 0 0 0px ${alpha(theme.palette.background.default, 0.7)}`,
 | 
			
		||||
        },
 | 
			
		||||
        '100%': {
 | 
			
		||||
            boxShadow: `0 0 0 20px ${alpha(theme.palette.background.default, 0.0)}`,
 | 
			
		||||
        },
 | 
			
		||||
    },
 | 
			
		||||
    animation: active ? 'pulse 2s infinite' : '',
 | 
			
		||||
}));
 | 
			
		||||
@ -9,14 +9,11 @@ import {
 | 
			
		||||
import { GenerateApiKey } from './GenerateApiKey';
 | 
			
		||||
import { useEffect, useState } from 'react';
 | 
			
		||||
import { SelectSdk } from './SelectSdk';
 | 
			
		||||
import {
 | 
			
		||||
    ConceptsDefinitionsWrapper,
 | 
			
		||||
    GenrateApiKeyConcepts,
 | 
			
		||||
    SelectSdkConcepts,
 | 
			
		||||
} from './UnleashConcepts';
 | 
			
		||||
import { GenerateApiKeyConcepts, SelectSdkConcepts } from './UnleashConcepts';
 | 
			
		||||
import { TestSdkConnection } from './TestSdkConnection';
 | 
			
		||||
 | 
			
		||||
import type { Sdk } from './sharedTypes';
 | 
			
		||||
import { ConnectionInformation } from './ConnectionInformation';
 | 
			
		||||
 | 
			
		||||
interface IConnectSDKDialogProps {
 | 
			
		||||
    open: boolean;
 | 
			
		||||
@ -180,10 +177,15 @@ export const ConnectSdkDialog = ({
 | 
			
		||||
                    <SelectSdkConcepts />
 | 
			
		||||
                ) : null}
 | 
			
		||||
                {isLargeScreen && isGenerateApiKeyStage ? (
 | 
			
		||||
                    <GenrateApiKeyConcepts />
 | 
			
		||||
                    <GenerateApiKeyConcepts />
 | 
			
		||||
                ) : null}
 | 
			
		||||
                {isLargeScreen && isTestConnectionStage ? (
 | 
			
		||||
                    <ConceptsDefinitionsWrapper />
 | 
			
		||||
                    <ConnectionInformation
 | 
			
		||||
                        projectId={project}
 | 
			
		||||
                        sdk={sdk.name}
 | 
			
		||||
                        environment={environment}
 | 
			
		||||
                        onConnection={onClose}
 | 
			
		||||
                    />
 | 
			
		||||
                ) : null}
 | 
			
		||||
            </Box>
 | 
			
		||||
        </StyledDialog>
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										113
									
								
								frontend/src/component/onboarding/ConnectionInformation.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										113
									
								
								frontend/src/component/onboarding/ConnectionInformation.tsx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,113 @@
 | 
			
		||||
import { styled, Typography, useTheme } from '@mui/material';
 | 
			
		||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
 | 
			
		||||
import { WhitePulsingAvatar } from 'component/common/PulsingAvatar/PulsingAvatar';
 | 
			
		||||
import Pending from '@mui/icons-material/Pending';
 | 
			
		||||
import useProjectOverview from 'hooks/api/getters/useProjectOverview/useProjectOverview';
 | 
			
		||||
import { useEffect } from 'react';
 | 
			
		||||
 | 
			
		||||
interface IConnectionInformationProps {
 | 
			
		||||
    onConnection: () => void;
 | 
			
		||||
    projectId: string;
 | 
			
		||||
    sdk: string;
 | 
			
		||||
    environment: string;
 | 
			
		||||
}
 | 
			
		||||
export const Container = styled('div')(({ theme }) => ({
 | 
			
		||||
    backgroundColor: theme.palette.background.sidebar,
 | 
			
		||||
    padding: theme.spacing(6, 9, 6, 9),
 | 
			
		||||
    minWidth: '400px',
 | 
			
		||||
    display: 'flex',
 | 
			
		||||
    flexDirection: 'column',
 | 
			
		||||
    color: theme.palette.primary.contrastText,
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
export const Title = styled(Typography)(({ theme }) => ({
 | 
			
		||||
    display: 'flex',
 | 
			
		||||
    alignItems: 'center',
 | 
			
		||||
    justifyContent: 'center',
 | 
			
		||||
    fontWeight: theme.typography.fontWeightBold,
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
export const SdkInfo = styled('div')(({ theme }) => ({
 | 
			
		||||
    display: 'flex',
 | 
			
		||||
    flexDirection: 'row',
 | 
			
		||||
    padding: theme.spacing(4, 0, 12, 0),
 | 
			
		||||
    justifyContent: 'space-between',
 | 
			
		||||
    fontSize: theme.spacing(1),
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
export const Info = styled('div')(({ theme }) => ({
 | 
			
		||||
    display: 'flex',
 | 
			
		||||
    gap: theme.spacing(1),
 | 
			
		||||
    flexDirection: 'column',
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
export const ConnectionStatus = styled('div')(({ theme }) => ({
 | 
			
		||||
    alignItems: 'center',
 | 
			
		||||
    justifyContent: 'center',
 | 
			
		||||
    display: 'flex',
 | 
			
		||||
    gap: theme.spacing(2),
 | 
			
		||||
    flexDirection: 'column',
 | 
			
		||||
    fontSize: theme.fontSizes.smallBody,
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
export const ConnectionInformation = ({
 | 
			
		||||
    onConnection,
 | 
			
		||||
    projectId,
 | 
			
		||||
    sdk,
 | 
			
		||||
    environment,
 | 
			
		||||
}: IConnectionInformationProps) => {
 | 
			
		||||
    const theme = useTheme();
 | 
			
		||||
    const { project } = useProjectOverview(projectId, {
 | 
			
		||||
        refreshInterval: 1000,
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    const onboarded = project.onboardingStatus.status === 'onboarded';
 | 
			
		||||
 | 
			
		||||
    useEffect(() => {
 | 
			
		||||
        if (onboarded) {
 | 
			
		||||
            onConnection();
 | 
			
		||||
        }
 | 
			
		||||
    }, [onboarded]);
 | 
			
		||||
 | 
			
		||||
    return (
 | 
			
		||||
        <Container>
 | 
			
		||||
            <Title>Connection information</Title>
 | 
			
		||||
            <SdkInfo>
 | 
			
		||||
                <Info>
 | 
			
		||||
                    <Typography fontWeight='bold' variant='body2'>
 | 
			
		||||
                        Environment
 | 
			
		||||
                    </Typography>
 | 
			
		||||
                    <Typography variant='body2'>{environment}</Typography>
 | 
			
		||||
                </Info>
 | 
			
		||||
                <Info>
 | 
			
		||||
                    <Typography fontWeight='bold' variant='body2'>
 | 
			
		||||
                        SDK
 | 
			
		||||
                    </Typography>
 | 
			
		||||
                    <Typography variant='body2'>{sdk}</Typography>
 | 
			
		||||
                </Info>
 | 
			
		||||
            </SdkInfo>
 | 
			
		||||
            <ConnectionStatus>
 | 
			
		||||
                <Typography fontWeight='bold' variant='body2'>
 | 
			
		||||
                    Connection status
 | 
			
		||||
                </Typography>
 | 
			
		||||
                <Typography sx={{ mb: theme.spacing(4) }} variant='body2'>
 | 
			
		||||
                    Waiting for SDK data...
 | 
			
		||||
                </Typography>
 | 
			
		||||
                <ConditionallyRender
 | 
			
		||||
                    condition={true}
 | 
			
		||||
                    show={
 | 
			
		||||
                        <WhitePulsingAvatar
 | 
			
		||||
                            sx={{
 | 
			
		||||
                                width: 80,
 | 
			
		||||
                                height: 80,
 | 
			
		||||
                            }}
 | 
			
		||||
                            active={true}
 | 
			
		||||
                        >
 | 
			
		||||
                            <Pending fontSize='large' />
 | 
			
		||||
                        </WhitePulsingAvatar>
 | 
			
		||||
                    }
 | 
			
		||||
                />
 | 
			
		||||
            </ConnectionStatus>
 | 
			
		||||
        </Container>
 | 
			
		||||
    );
 | 
			
		||||
};
 | 
			
		||||
@ -40,7 +40,7 @@ const ConceptSummary = styled('div')(({ theme }) => ({
 | 
			
		||||
    marginBottom: theme.spacing(2),
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
export const GenrateApiKeyConcepts = () => (
 | 
			
		||||
export const GenerateApiKeyConcepts = () => (
 | 
			
		||||
    <ConceptsDefinitionsWrapper>
 | 
			
		||||
        <ConceptItem>
 | 
			
		||||
            <StyledProjectIcon />
 | 
			
		||||
 | 
			
		||||
@ -1,20 +0,0 @@
 | 
			
		||||
import { alpha, Avatar, styled } from '@mui/material';
 | 
			
		||||
 | 
			
		||||
export const PulsingAvatar = styled(Avatar, {
 | 
			
		||||
    shouldForwardProp: (prop) => prop !== 'active',
 | 
			
		||||
})<{ active: boolean }>(({ theme, active }) => ({
 | 
			
		||||
    transition: 'background-color 0.5s ease',
 | 
			
		||||
    color: theme.palette.common.white,
 | 
			
		||||
    backgroundColor: active
 | 
			
		||||
        ? theme.palette.primary.main
 | 
			
		||||
        : theme.palette.divider,
 | 
			
		||||
    '@keyframes pulse': {
 | 
			
		||||
        '0%': {
 | 
			
		||||
            boxShadow: `0 0 0 0px ${alpha(theme.palette.primary.main, 0.7)}`,
 | 
			
		||||
        },
 | 
			
		||||
        '100%': {
 | 
			
		||||
            boxShadow: `0 0 0 20px ${alpha(theme.palette.primary.main, 0.0)}`,
 | 
			
		||||
        },
 | 
			
		||||
    },
 | 
			
		||||
    animation: active ? 'pulse 2s infinite' : '',
 | 
			
		||||
}));
 | 
			
		||||
@ -9,7 +9,7 @@ import {
 | 
			
		||||
} from '@mui/material';
 | 
			
		||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
 | 
			
		||||
import { StyledFileDropZone } from './StyledFileDropZone';
 | 
			
		||||
import { PulsingAvatar } from '../PulsingAvatar';
 | 
			
		||||
import { PulsingAvatar } from 'component/common/PulsingAvatar/PulsingAvatar';
 | 
			
		||||
import ArrowUpward from '@mui/icons-material/ArrowUpward';
 | 
			
		||||
import { ImportExplanation } from './ImportExplanation';
 | 
			
		||||
import { type FC, type ReactNode, useState } from 'react';
 | 
			
		||||
 | 
			
		||||
@ -8,7 +8,7 @@ import { ActionsContainer } from '../ActionsContainer';
 | 
			
		||||
import Check from '@mui/icons-material/Check';
 | 
			
		||||
import ErrorIcon from '@mui/icons-material/Error';
 | 
			
		||||
import Pending from '@mui/icons-material/Pending';
 | 
			
		||||
import { PulsingAvatar } from '../PulsingAvatar';
 | 
			
		||||
import { PulsingAvatar } from 'component/common/PulsingAvatar/PulsingAvatar';
 | 
			
		||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
 | 
			
		||||
import { Box } from '@mui/system';
 | 
			
		||||
import { useChangeRequestsEnabled } from 'hooks/useChangeRequestsEnabled';
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user