1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-05-31 01:16:01 +02:00

fix: last seen at rendering logic (#5136)

This PR fixes a bug where the rendering in the frontend would only
render the last seen component if feature.lastSeenAt was set, the new
changes considers whether or not environments last seen at is present
and takes precedent over the legacy last seen at field.
This commit is contained in:
Fredrik Strand Oseberg 2023-10-24 13:58:55 +02:00 committed by GitHub
parent da2c46d8c3
commit 5acf691845
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 121 additions and 39 deletions

View File

@ -1,6 +1,6 @@
import { styled, SxProps, Theme, Typography } from '@mui/material';
import TimeAgo from 'react-timeago';
import { IEnvironments, IFeatureEnvironment } from 'interfaces/featureToggle';
import { ILastSeenEnvironments } from 'interfaces/featureToggle';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
import { useLastSeenColors } from 'component/feature/FeatureView/FeatureEnvironmentSeen/useLastSeenColors';
@ -56,7 +56,7 @@ const StyledValue = styled('div', {
interface ILastSeenTooltipProps {
featureLastSeen: string;
environments?: IEnvironments[] | IFeatureEnvironment[];
environments?: ILastSeenEnvironments[];
className?: string;
sx?: SxProps<Theme>;
}

View File

@ -1,17 +1,18 @@
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 { FC, ReactElement } from 'react';
import { ILastSeenEnvironments } 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[];
environments: ILastSeenEnvironments[];
sx?: SxProps;
}
@ -75,43 +76,42 @@ export const FeatureEnvironmentSeen = ({
sx,
}: IFeatureEnvironmentSeenProps) => {
const getColor = useLastSeenColors();
const lastSeen = getLatestLastSeenAt(environments) || featureLastSeen;
return (
<ConditionallyRender
condition={Boolean(featureLastSeen)}
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>
);
}}
/>
)
}
elseShow={
<>
{lastSeen ? (
<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>
);
}}
/>
) : (
<TooltipContainer
sx={sx}
tooltip='No usage reported from connected applications'
>
<UsageLine />
</TooltipContainer>
}
/>
)}
</>
);
};

View File

@ -0,0 +1,48 @@
import { IEnvironments } 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,
variantCount: 0,
},
{
name: 'test2',
lastSeenAt: '2023-10-23T08:48:11.869Z',
enabled: true,
variantCount: 0,
},
{
name: 'test3',
lastSeenAt: '2023-10-24T08:48:11.869Z',
enabled: true,
variantCount: 0,
},
];
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,
variantCount: 0,
},
];
expect(() => getLatestLastSeenAt(input)).not.toThrow();
});
});

View File

@ -0,0 +1,19 @@
import { ILastSeenEnvironments } from 'interfaces/featureToggle';
export const getLatestLastSeenAt = (
environments: ILastSeenEnvironments[],
): string | null => {
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;
}
};

View File

@ -1,4 +1,7 @@
import { IFeatureToggle } from 'interfaces/featureToggle';
import {
IFeatureToggle,
ILastSeenEnvironments,
} from 'interfaces/featureToggle';
import { styled } from '@mui/material';
import { useLocationSettings } from 'hooks/useLocationSettings';
import { formatDateYMD } from 'utils/formatDate';
@ -34,6 +37,13 @@ export const FeatureOverviewSidePanelDetails = ({
uiConfig.flags.lastSeenByEnvironment,
);
const lastSeenEnvironments: ILastSeenEnvironments[] =
feature.environments?.map((env) => ({
name: env.name,
lastSeenAt: env.lastSeenAt,
enabled: env.enabled,
}));
return (
<StyledContainer>
{header}
@ -50,7 +60,7 @@ export const FeatureOverviewSidePanelDetails = ({
{showLastSeenByEnvironment && (
<FeatureEnvironmentSeen
featureLastSeen={feature.lastSeenAt}
environments={feature.environments}
environments={lastSeenEnvironments}
sx={{ p: 0 }}
/>
)}

View File

@ -22,6 +22,11 @@ export interface IEnvironments {
hasEnabledStrategies?: boolean;
}
export type ILastSeenEnvironments = Pick<
IEnvironments,
'name' | 'enabled' | 'lastSeenAt'
>;
export interface IFeatureToggle {
stale: boolean;
archived: boolean;
@ -52,7 +57,7 @@ export interface IFeatureEnvironment {
enabled: boolean;
strategies: IFeatureStrategy[];
variants?: IFeatureVariant[];
lastSeenAt?: Date;
lastSeenAt?: string;
}
export interface IFeatureEnvironmentWithCrEnabled extends IFeatureEnvironment {