Skip to content

Commit

Permalink
fix: rendering logic
Browse files Browse the repository at this point in the history
  • Loading branch information
FredrikOseberg committed Oct 24, 2023
1 parent 314a08b commit ee24ab7
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 57 deletions.
Original file line number Diff line number Diff line change
@@ -1,49 +1,50 @@
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
import TimeAgo from 'react-timeago';
import { LastSeenTooltip } from 'component/common/Table/cells/FeatureSeenCell/LastSeenTooltip';
import React, { FC, ReactElement } from 'react';
import { IEnvironments, IFeatureEnvironment } from 'interfaces/featureToggle';
import { TooltipResolver } from 'component/common/TooltipResolver/TooltipResolver';
import { Box, styled, SxProps } from '@mui/material';
import { ReactComponent as UsageLine } from 'assets/icons/usage-line.svg';
import { ReactComponent as UsageRate } from 'assets/icons/usage-rate.svg';
import { useLastSeenColors } from './useLastSeenColors';
import { ConditionallyRender } from "component/common/ConditionallyRender/ConditionallyRender";
import TimeAgo from "react-timeago";
import { LastSeenTooltip } from "component/common/Table/cells/FeatureSeenCell/LastSeenTooltip";
import React, { FC, ReactElement } from "react";
import { IEnvironments, IFeatureEnvironment } from "interfaces/featureToggle";
import { TooltipResolver } from "component/common/TooltipResolver/TooltipResolver";
import { Box, styled, SxProps } from "@mui/material";
import { ReactComponent as UsageLine } from "assets/icons/usage-line.svg";
import { ReactComponent as UsageRate } from "assets/icons/usage-rate.svg";
import { useLastSeenColors } from "./useLastSeenColors";
import { getLatestLastSeenAt } from "./getLatestLastSeenAt";

interface IFeatureEnvironmentSeenProps {
featureLastSeen: string | undefined;
environments: IEnvironments[] | IFeatureEnvironment[];
sx?: SxProps;
}

const StyledContainer = styled('div')(({ theme }) => ({
display: 'flex',
const StyledContainer = styled("div")(({ theme }) => ({
display: "flex",
padding: theme.spacing(1.5),
}));

const StyledBox = styled(Box)(({ theme }) => ({
width: '28px',
height: '28px',
background: 'transparent',
width: "28px",
height: "28px",
background: "transparent",
borderRadius: `${theme.shape.borderRadius}px`,
textAlign: 'center',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
textAlign: "center",
display: "flex",
alignItems: "center",
justifyContent: "center",
fontSize: theme.typography.body2.fontSize,
margin: '0 auto',
margin: "0 auto",
}));

const StyledIconWrapper = styled('div')(({ theme }) => ({
width: '20px',
height: '20px',
const StyledIconWrapper = styled("div")(({ theme }) => ({
width: "20px",
height: "20px",
background: theme.palette.background.paper,
borderRadius: `${theme.shape.borderRadius}px`,
textAlign: 'center',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
textAlign: "center",
display: "flex",
alignItems: "center",
justifyContent: "center",
fontSize: theme.typography.body2.fontSize,
margin: '0 auto',
margin: "0 auto",
}));

const TooltipContainer: FC<{
Expand All @@ -54,12 +55,12 @@ const TooltipContainer: FC<{
return (
<StyledContainer sx={sx}>
<TooltipResolver
variant='custom'
variant="custom"
titleComponent={tooltip}
arrow
describeChild
>
<StyledBox sx={{ '&:hover': { background: color } }}>
<StyledBox sx={{ "&:hover": { background: color } }}>
<StyledIconWrapper style={{ background: color }}>
{children}
</StyledIconWrapper>
Expand All @@ -75,39 +76,40 @@ export const FeatureEnvironmentSeen = ({
sx,
}: IFeatureEnvironmentSeenProps) => {
const getColor = useLastSeenColors();

const lastSeen = getLatestLastSeenAt(environments) || featureLastSeen;

return (
<ConditionallyRender
condition={Boolean(featureLastSeen)}
condition={Boolean(lastSeen)}
show={
featureLastSeen && (
<TimeAgo
date={featureLastSeen}
title=''
live={false}
formatter={(value: number, unit: string) => {
const [color, textColor] = getColor(unit);
return (
<TooltipContainer
sx={sx}
tooltip={
<LastSeenTooltip
featureLastSeen={featureLastSeen}
environments={environments}
/>
}
color={color}
>
<UsageRate stroke={textColor} />
</TooltipContainer>
);
}}
/>
)
<TimeAgo
date={lastSeen}
title=""
live={false}
formatter={(value: number, unit: string) => {
const [color, textColor] = getColor(unit);
return (
<TooltipContainer
sx={sx}
tooltip={
<LastSeenTooltip
featureLastSeen={lastSeen}
environments={environments}
/>
}
color={color}
>
<UsageRate stroke={textColor} />
</TooltipContainer>
);
}}
/>
}
elseShow={
<TooltipContainer
sx={sx}
tooltip='No usage reported from connected applications'
tooltip="No usage reported from connected applications"
>
<UsageLine />
</TooltipContainer>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { IEnvironments, IFeatureEnvironment } from 'interfaces/featureToggle';

import { getLatestLastSeenAt } from './getLatestLastSeenAt';

describe('getLatestLastSeenAt', () => {
test('should return the most recent lastSeenAt date', () => {
const input: IEnvironments[] = [
{
name: 'test1',
lastSeenAt: '2023-10-22T08:48:11.869Z',
enabled: false,
},
{
name: 'test2',
lastSeenAt: '2023-10-23T08:48:11.869Z',
enabled: true,
},
{
name: 'test3',
lastSeenAt: '2023-10-24T08:48:11.869Z',
enabled: true,
},
];
const expected = '2023-10-24T08:48:11.869Z';
expect(getLatestLastSeenAt(input)).toBe(expected);
});

test('should handle an empty array', () => {
const input: IEnvironments[] = [];
const expected = null;
expect(getLatestLastSeenAt(input)).toBe(expected);
});

test('should not fail with non-standard date formats', () => {
const input: IEnvironments[] = [
{ name: 'test', lastSeenAt: 'Some Invalid Date', enabled: true },
];
expect(() => getLatestLastSeenAt(input)).not.toThrow();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { IEnvironments, IFeatureEnvironment } from 'interfaces/featureToggle';

export const getLatestLastSeenAt = (
environments: IEnvironments[] | IFeatureEnvironment[],
) => {
try {
if (!Array.isArray(environments) || environments.length === 0) {
return null;
}

return environments
.filter((item) => Boolean(item.lastSeenAt))
.map((item) => new Date(item.lastSeenAt!))
.reduce((latest, current) => (current > latest ? current : latest))
.toISOString();
} catch (error) {
return null;
}
};
2 changes: 1 addition & 1 deletion frontend/src/interfaces/featureToggle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export interface IFeatureToggleListItem {
export interface IEnvironments {
name: string;
enabled: boolean;
variantCount: number;
variantCount?: number;
lastSeenAt?: string | null;
type?: string;
hasStrategies?: boolean;
Expand Down

0 comments on commit ee24ab7

Please sign in to comment.