import { Box, Divider, styled, Typography, useTheme } from '@mui/material'; import { ArcherContainer, ArcherElement } from 'react-archer'; import { useNavigate } from 'react-router-dom'; import { type FC, useLayoutEffect, useRef, useState } from 'react'; import type { ApplicationOverviewEnvironmentSchema, ApplicationOverviewSchema, } from 'openapi'; import { useRequiredPathParam } from 'hooks/useRequiredPathParam'; import { HelpIcon } from '../common/HelpIcon/HelpIcon'; import CheckCircle from '@mui/icons-material/CheckCircle'; import CloudCircle from '@mui/icons-material/CloudCircle'; import Flag from '@mui/icons-material/Flag'; import WarningAmberRounded from '@mui/icons-material/WarningAmberRounded'; import TimeAgo from 'react-timeago'; import { usePlausibleTracker } from 'hooks/usePlausibleTracker'; import { getApplicationIssues } from './ApplicationIssues/ApplicationIssues'; const StyledTable = styled('table')(({ theme }) => ({ fontSize: theme.fontSizes.smallerBody, marginTop: theme.spacing(1), })); const StyledCell = styled('td')(({ theme }) => ({ verticalAlign: 'top', paddingLeft: 0, paddingRight: theme.spacing(1), })); const StyleApplicationContainer = styled(Box)(({ theme }) => ({ marginBottom: theme.spacing(18), display: 'flex', justifyContent: 'center', })); const StyledApplicationBox = styled(Box)<{ mode: 'success' | 'warning'; }>(({ theme, mode }) => ({ borderRadius: theme.shape.borderRadiusMedium, border: '1px solid', borderColor: theme.palette[mode].border, backgroundColor: theme.palette[mode].light, display: 'flex', flexDirection: 'column', alignItems: 'center', padding: theme.spacing(1.5, 3, 2, 3), })); const StyledEnvironmentBox = styled(Box)<{ mode: 'success' | 'warning'; }>(({ theme, mode }) => ({ borderRadius: theme.shape.borderRadiusMedium, border: '1px solid', borderColor: theme.palette[mode === 'success' ? 'secondary' : 'warning'].border, backgroundColor: theme.palette[mode === 'success' ? 'secondary' : 'warning'].light, display: 'inline-block', padding: theme.spacing(1.5, 1.5, 1.5, 1.5), zIndex: 1, opacity: 0.9, })); const StyledDivider = styled(Divider)(({ theme }) => ({ marginTop: theme.spacing(2), marginBottom: theme.spacing(2), width: '100%', })); const StyledEnvironmentsContainer = styled(Box)({ display: 'flex', justifyContent: 'center', flexWrap: 'wrap', gap: '60px 20px', }); const EnvironmentHeader = styled(Typography)(({ theme }) => ({ fontSize: theme.fontSizes.smallerBody, fontWeight: theme.fontWeight.bold, })); const StyledStatus = styled(Typography)<{ mode: 'success' | 'warning'; }>(({ theme, mode }) => ({ gap: theme.spacing(1), fontSize: theme.fontSizes.smallBody, color: theme.palette[mode].dark, display: 'flex', alignItems: 'center', })); const StyledIconRow = styled(Box)(({ theme }) => ({ display: 'flex', gap: theme.spacing(3), color: theme.palette.secondary.main, paddingTop: theme.spacing(2), })); const StyledIconContainer = styled(Box)(({ theme }) => ({ display: 'flex', gap: theme.spacing(0.5), })); const StyledText = styled(Box)(({ theme }) => ({ color: theme.palette.text.primary, display: 'flex', alignItems: 'center', })); interface IApplicationChartProps { data: ApplicationOverviewSchema; } interface IApplicationCountersProps { environmentCount: number; featureCount: number; } const useElementWidth = () => { const elementRef = useRef(null); const [width, setWidth] = useState('100%'); useLayoutEffect(() => { setWidth(`${elementRef.current?.scrollWidth}px`); }, [elementRef, setWidth]); return { elementRef, width, }; }; const SuccessStatus = () => ( ({ color: theme.palette.success.main, })} />{' '} Everything looks good! ); const WarningStatus: FC = ({ children }) => ( ({ color: theme.palette.warning.main, })} />{' '} {children} ); const ApplicationCounters = ({ environmentCount, featureCount, }: IApplicationCountersProps) => { return ( {environmentCount} {featureCount} ); }; const useTracking = () => { const { trackEvent } = usePlausibleTracker(); return () => { trackEvent('sdk-reporting', { props: { eventType: 'environment box clicked', }, }); }; }; const getEnvironmentMode = ( environment: ApplicationOverviewEnvironmentSchema, ) => { return environment.issues.missingFeatures.length + environment.issues.outdatedSdks.length === 0 ? 'success' : 'warning'; }; export const ApplicationChart = ({ data }: IApplicationChartProps) => { const trackClick = useTracking(); const applicationName = useRequiredPathParam('name'); const { elementRef, width } = useElementWidth(); const navigate = useNavigate(); const theme = useTheme(); const mode = getApplicationIssues(data); return ( ({ targetId: environment.name, targetAnchor: 'top', sourceAnchor: 'bottom', style: { strokeColor: getEnvironmentMode(environment) === 'success' ? theme.palette.secondary.border : theme.palette.warning.border, }, }))} > ({ fontSize: theme.fontSizes.smallerBody, })} color='text.secondary' > Application ({ fontSize: theme.fontSizes.bodySize, fontWeight: theme.fontWeight.bold, })} > {applicationName} {mode.applicationMode === 'success' ? ( ) : ( {mode.issueCount} issues detected )} {data.environments.map((environment) => ( { trackClick(); navigate( `/applications/${applicationName}/instances?environment=${environment.name}`, ); }} > {environment.name} environment Instances:{' '} {environment.instanceCount} SDK: {environment.sdks.map((sdk) => (
{sdk}
))}
Last seen: {environment.lastSeen && ( )}
))}
); };