1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-01-25 00:07:47 +01:00

feat: Completed stage UI (#6917)

This commit is contained in:
Mateusz Kwasniewski 2024-04-24 11:00:21 +02:00 committed by GitHub
parent e91d471d17
commit 9c883ca37d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 119 additions and 2 deletions

View File

@ -17,7 +17,12 @@ import { StyledIconWrapper } from '../../FeatureEnvironmentSeen/FeatureEnvironme
import { useLastSeenColors } from '../../FeatureEnvironmentSeen/useLastSeenColors';
import type { LifecycleStage } from './LifecycleStage';
import PermissionButton from 'component/common/PermissionButton/PermissionButton';
import { UPDATE_FEATURE } from 'component/providers/AccessProvider/permissions';
import {
DELETE_FEATURE,
UPDATE_FEATURE,
} from 'component/providers/AccessProvider/permissions';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
import { isSafeToArchive } from './isSafeToArchive';
const TimeLabel = styled('span')(({ theme }) => ({
color: theme.palette.text.secondary,
@ -279,6 +284,52 @@ const LiveStageDescription: FC = ({ children }) => {
);
};
const SafeToArchive: FC = () => {
return (
<>
<BoldTitle>Safe to archive</BoldTitle>
<InfoText sx={{ mt: 2, mb: 1 }}>
We havent seen this feature flag in production for at least two
days. Its likely that its safe to archive this flag.
</InfoText>
<PermissionButton
color='inherit'
variant='outlined'
permission={DELETE_FEATURE}
size='small'
sx={{ mb: 2 }}
>
Archive feature
</PermissionButton>
</>
);
};
const ActivelyUsed: FC = ({ children }) => {
return (
<>
<InfoText sx={{ mt: 1, mb: 1 }}>
This feature has been successfully completed, but we are still
seeing usage in production. Clean up the feature flag from your
code before archiving it:
</InfoText>
{children}
</>
);
};
const CompletedStageDescription: FC<{
environments: Array<{ name: string; lastSeenAt: string }>;
}> = ({ children, environments }) => {
return (
<ConditionallyRender
condition={isSafeToArchive(environments)}
show={<SafeToArchive />}
elseShow={<ActivelyUsed>{children}</ActivelyUsed>}
/>
);
};
export const FeatureLifecycleTooltip: FC<{
children: React.ReactElement<any, any>;
stage: LifecycleStage;
@ -327,6 +378,13 @@ export const FeatureLifecycleTooltip: FC<{
<Environments environments={stage.environments} />
</LiveStageDescription>
)}
{stage.name === 'completed' && (
<CompletedStageDescription
environments={stage.environments}
>
<Environments environments={stage.environments} />
</CompletedStageDescription>
)}
</ColorFill>
</Box>
}

View File

@ -10,6 +10,7 @@ export type LifecycleStage =
}
| {
name: 'completed';
environments: Array<{ name: string; lastSeenAt: string }>;
status: 'kept' | 'discarded';
}
| { name: 'archived' };

View File

@ -0,0 +1,44 @@
import { isSafeToArchive } from './isSafeToArchive'; // Update the import path accordingly
import { subDays } from 'date-fns';
describe('isSafeToArchive', () => {
it('should return true if all environments were last seen more than two days ago', () => {
const now = new Date();
const environments = [
{ name: 'Production', lastSeenAt: subDays(now, 3).toISOString() },
{ name: 'Staging', lastSeenAt: subDays(now, 4).toISOString() },
];
const result = isSafeToArchive(environments);
expect(result).toBe(true);
});
it('should return false if any environment was seen within the last two days', () => {
const now = new Date();
const environments = [
{ name: 'Production', lastSeenAt: subDays(now, 3).toISOString() },
{ name: 'Staging', lastSeenAt: subDays(now, 1).toISOString() },
];
const result = isSafeToArchive(environments);
expect(result).toBe(false);
});
it('should return false if all environments were seen within the last two days', () => {
const now = new Date();
const environments = [
{ name: 'Production', lastSeenAt: subDays(now, 0).toISOString() },
{ name: 'Staging', lastSeenAt: subDays(now, 1).toISOString() },
];
const result = isSafeToArchive(environments);
expect(result).toBe(false);
});
it('should return true for an empty array of environments', () => {
const environments: Array<{ name: string; lastSeenAt: string }> = [];
const result = isSafeToArchive(environments);
expect(result).toBe(true);
});
});

View File

@ -0,0 +1,13 @@
import { isBefore, parseISO, subDays } from 'date-fns';
export function isSafeToArchive(
environments: Array<{ name: string; lastSeenAt: string }>,
) {
const twoDaysAgo = subDays(new Date(), 2);
return environments.every((env) => {
const lastSeenDate = parseISO(env.lastSeenAt);
return isBefore(lastSeenDate, twoDaysAgo);
});
}

View File

@ -83,7 +83,8 @@ const FeatureOverviewMetaData = () => {
const IconComponent = getFeatureTypeIcons(type);
const currentStage: LifecycleStage = {
name: 'live',
name: 'completed',
status: 'kept',
environments: [
{ name: 'production', lastSeenAt: new Date().toISOString() },
{