1
0
mirror of https://github.com/Unleash/unleash.git synced 2024-12-22 19:07:54 +01:00

Feat: toggle overview env last seen (#4445)

<!-- Thanks for creating a PR! To make it easier for reviewers and
everyone else to understand what your changes relate to, please add some
relevant content to the headings below. Feel free to ignore or delete
sections that you don't think are relevant. Thank you! ❤️ -->
Adds last seen by environment to FeatureOverview

- Refactored FeatureEnvironmentSeen component for reusability


<!-- Does it close an issue? Multiple? -->
Closes #
[1-1223](https://linear.app/unleash/issue/1-1223/toggle-overview-add-last-seen-by-environment)
![Screenshot 2023-08-08 at 14 12
29](https://github.com/Unleash/unleash/assets/104830839/cfb29492-863b-491c-8f6f-e1133246dcb3)

---------

Signed-off-by: andreas-unleash <andreas@getunleash.ai>
This commit is contained in:
andreas-unleash 2023-08-08 15:56:32 +03:00 committed by GitHub
parent e7ae1ff714
commit 839c36d547
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 159 additions and 108 deletions

View File

@ -1,108 +1,19 @@
import React, { FC, ReactElement, VFC } from 'react';
import { Box, styled } from '@mui/material';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
import { TooltipResolver } from 'component/common/TooltipResolver/TooltipResolver';
import { LastSeenTooltip } from './LastSeenTooltip';
import React, { VFC } from 'react';
import { IFeatureToggleListItem } from 'interfaces/featureToggle';
import { ReactComponent as UsageLine } from 'assets/icons/usage-line.svg';
import { ReactComponent as UsageRate } from 'assets/icons/usage-rate.svg';
import TimeAgo from 'react-timeago';
import { useLastSeenColors } from './useLastSeenColors';
const StyledContainer = styled('div')(({ theme }) => ({
display: 'flex',
padding: theme.spacing(1.5),
}));
const StyledBox = styled(Box)(({ theme }) => ({
width: '28px',
height: '28px',
background: 'transparent',
borderRadius: `${theme.shape.borderRadius}px`,
textAlign: 'center',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
fontSize: theme.typography.body2.fontSize,
margin: '0 auto',
}));
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',
fontSize: theme.typography.body2.fontSize,
margin: '0 auto',
}));
import { FeatureEnvironmentSeen } from 'component/feature/FeatureView/FeatureEnvironmentSeen/FeatureEnvironmentSeen';
interface IFeatureSeenCellProps {
feature: IFeatureToggleListItem;
}
const TooltipContainer: FC<{
color?: string;
tooltip: ReactElement | string;
}> = ({ tooltip, color, children }) => {
return (
<StyledContainer>
<TooltipResolver
variant="custom"
titleComponent={tooltip}
arrow
describeChild
>
<StyledBox sx={{ '&:hover': { background: color } }}>
<StyledIconWrapper style={{ background: color }}>
{children}
</StyledIconWrapper>
</StyledBox>
</TooltipResolver>
</StyledContainer>
);
};
export const FeatureEnvironmentSeenCell: VFC<IFeatureSeenCellProps> = ({
feature,
}) => {
const getColor = useLastSeenColors();
const environments = Object.values(feature.environments);
return (
<ConditionallyRender
condition={Boolean(feature.lastSeenAt)}
show={
feature.lastSeenAt && (
<TimeAgo
date={feature.lastSeenAt}
title=""
live={false}
formatter={(value: number, unit: string) => {
const [color, textColor] = getColor(unit);
return (
<TooltipContainer
tooltip={
<LastSeenTooltip
environments={environments}
/>
}
color={color}
>
<UsageRate stroke={textColor} />
</TooltipContainer>
);
}}
/>
)
}
elseShow={
<TooltipContainer tooltip="No usage reported from connected applications">
<UsageLine />
</TooltipContainer>
}
<FeatureEnvironmentSeen
featureLastSeen={feature.lastSeenAt}
environments={environments}
/>
);
};

View File

@ -1,9 +1,9 @@
import { styled, SxProps, Theme } from '@mui/material';
import TimeAgo from 'react-timeago';
import { IEnvironments } from 'interfaces/featureToggle';
import { IEnvironments, IFeatureEnvironment } from 'interfaces/featureToggle';
import React from 'react';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
import { useLastSeenColors } from './useLastSeenColors';
import { useLastSeenColors } from 'component/feature/FeatureView/FeatureEnvironmentSeen/useLastSeenColors';
const StyledDescription = styled(
'div',
@ -56,7 +56,7 @@ const StyledValue = styled('div', {
}));
interface ILastSeenTooltipProps {
environments?: IEnvironments[];
environments?: IEnvironments[] | IFeatureEnvironment[];
className?: string;
sx?: SxProps<Theme>;
}
@ -66,7 +66,7 @@ export const LastSeenTooltip = ({
...rest
}: ILastSeenTooltipProps) => {
const getColor = useLastSeenColors();
const [defaultColor] = getColor();
const [, defaultTextColor] = getColor();
return (
<StyledDescription {...rest}>
<StyledDescriptionHeader sx={{ mb: 0 }}>
@ -107,7 +107,7 @@ export const LastSeenTooltip = ({
/>
}
elseShow={
<StyledValue color={defaultColor}>
<StyledValue color={defaultTextColor}>
no usage
</StyledValue>
}

View File

@ -0,0 +1,113 @@
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';
interface IFeatureEnvironmentSeenProps {
featureLastSeen: string | undefined;
environments: IEnvironments[] | IFeatureEnvironment[];
sx?: SxProps;
}
const StyledContainer = styled('div')(({ theme }) => ({
display: 'flex',
padding: theme.spacing(1.5),
}));
const StyledBox = styled(Box)(({ theme }) => ({
width: '28px',
height: '28px',
background: 'transparent',
borderRadius: `${theme.shape.borderRadius}px`,
textAlign: 'center',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
fontSize: theme.typography.body2.fontSize,
margin: '0 auto',
}));
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',
fontSize: theme.typography.body2.fontSize,
margin: '0 auto',
}));
const TooltipContainer: FC<{
color?: string;
tooltip: ReactElement | string;
sx?: SxProps;
}> = ({ sx, tooltip, color, children }) => {
return (
<StyledContainer sx={sx}>
<TooltipResolver
variant="custom"
titleComponent={tooltip}
arrow
describeChild
>
<StyledBox sx={{ '&:hover': { background: color } }}>
<StyledIconWrapper style={{ background: color }}>
{children}
</StyledIconWrapper>
</StyledBox>
</TooltipResolver>
</StyledContainer>
);
};
export const FeatureEnvironmentSeen = ({
featureLastSeen,
environments,
sx,
}: IFeatureEnvironmentSeenProps) => {
const getColor = useLastSeenColors();
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
environments={environments}
/>
}
color={color}
>
<UsageRate stroke={textColor} />
</TooltipContainer>
);
}}
/>
)
}
elseShow={
<TooltipContainer tooltip="No usage reported from connected applications">
<UsageLine />
</TooltipContainer>
}
/>
);
};

View File

@ -3,6 +3,8 @@ import { styled } from '@mui/material';
import { useLocationSettings } from 'hooks/useLocationSettings';
import { formatDateYMD } from 'utils/formatDate';
import { parseISO } from 'date-fns';
import { FeatureEnvironmentSeen } from '../../../FeatureEnvironmentSeen/FeatureEnvironmentSeen';
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
const StyledContainer = styled('div')(({ theme }) => ({
display: 'flex',
@ -21,24 +23,49 @@ interface IFeatureOverviewSidePanelDetailsProps {
header: React.ReactNode;
}
const FlexRow = styled('div')({
display: 'flex',
flexDirection: 'row',
justifyContent: 'space-between',
});
const StyledDetail = styled('div')(({ theme }) => ({
justifyContent: 'center',
paddingTop: theme.spacing(0.75),
}));
export const FeatureOverviewSidePanelDetails = ({
feature,
header,
}: IFeatureOverviewSidePanelDetailsProps) => {
const { locationSettings } = useLocationSettings();
const { uiConfig } = useUiConfig();
const showLastSeenByEnvironment = Boolean(
uiConfig.flags.lastSeenByEnvironment
);
return (
<StyledContainer>
{header}
<div data-loading>
<StyledLabel>Created at:</StyledLabel>
<span>
{formatDateYMD(
parseISO(feature.createdAt),
locationSettings.locale
)}
</span>
</div>
<FlexRow>
<StyledDetail>
<StyledLabel>Created at:</StyledLabel>
<span>
{formatDateYMD(
parseISO(feature.createdAt),
locationSettings.locale
)}
</span>
</StyledDetail>
{showLastSeenByEnvironment && (
<FeatureEnvironmentSeen
featureLastSeen={feature.lastSeenAt}
environments={feature.environments}
sx={{ pt: 0 }}
/>
)}
</FlexRow>
</StyledContainer>
);
};