Skip to content

Commit

Permalink
feat: Completed stage UI (#6917)
Browse files Browse the repository at this point in the history
  • Loading branch information
kwasniew authored Apr 24, 2024
1 parent e91d471 commit 9c883ca
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -279,6 +284,52 @@ const LiveStageDescription: FC = ({ children }) => {
);
};

const SafeToArchive: FC = () => {
return (
<>
<BoldTitle>Safe to archive</BoldTitle>
<InfoText sx={{ mt: 2, mb: 1 }}>
We haven’t seen this feature flag in production for at least two
days. It’s likely that it’s 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;
Expand Down Expand Up @@ -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>
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export type LifecycleStage =
}
| {
name: 'completed';
environments: Array<{ name: string; lastSeenAt: string }>;
status: 'kept' | 'discarded';
}
| { name: 'archived' };
Original file line number Diff line number Diff line change
@@ -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);
});
});
Original file line number Diff line number Diff line change
@@ -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);
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -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() },
{
Expand Down

0 comments on commit 9c883ca

Please sign in to comment.