chore: remove lifecycle v2 flag (#9224)
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
Before Width: | Height: | Size: 903 B After Width: | Height: | Size: 903 B |
Before Width: | Height: | Size: 391 B After Width: | Height: | Size: 391 B |
Before Width: | Height: | Size: 799 B After Width: | Height: | Size: 799 B |
Before Width: | Height: | Size: 595 B After Width: | Height: | Size: 595 B |
@ -1,8 +0,0 @@
|
|||||||
<svg width="40" height="20" viewBox="0 0 40 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path d="M0 4C0 1.79086 1.79086 0 4 0H36C38.2091 0 40 1.79086 40 4V16C40 18.2091 38.2091 20 36 20H4C1.79086 20 0 18.2091 0 16V4Z" fill="#F3F3FD"/>
|
|
||||||
<path d="M8.48149 4.7716C9.27968 3.84038 10.7203 3.84038 11.5185 4.7716L14.8844 8.69842C15.5263 9.4474 15.5263 10.5526 14.8844 11.3016L11.5185 15.2284C10.7203 16.1596 9.27968 16.1596 8.48149 15.2284L5.11564 11.3016C4.47366 10.5526 4.47366 9.4474 5.11564 8.69842L8.48149 4.7716Z" fill="#9F9FA1"/>
|
|
||||||
<path d="M17.2778 4.12081C16.0805 2.72397 13.9195 2.72397 12.7222 4.12081L9.35639 8.04763C8.39341 9.17109 8.39341 10.8289 9.35639 11.9524L12.7222 15.8792C13.9195 17.276 16.0805 17.276 17.2778 15.8792L20.6436 11.9524C21.6066 10.8289 21.6066 9.1711 20.6436 8.04763L17.2778 4.12081Z" fill="#9F9FA1" stroke="#F3F3FD" stroke-width="2"/>
|
|
||||||
<path d="M22.2778 4.12081C21.0805 2.72397 18.9195 2.72397 17.7222 4.12081L14.3564 8.04763C13.3934 9.17109 13.3934 10.8289 14.3564 11.9524L17.7222 15.8792C18.9195 17.276 21.0805 17.276 22.2778 15.8792L25.6436 11.9524C26.6066 10.8289 26.6066 9.1711 25.6436 8.04763L22.2778 4.12081Z" fill="#9F9FA1" stroke="#F3F3FD" stroke-width="2"/>
|
|
||||||
<path d="M27.2778 4.12081C26.0805 2.72397 23.9195 2.72397 22.7222 4.12081L19.3564 8.04763C18.3934 9.17109 18.3934 10.8289 19.3564 11.9524L22.7222 15.8792C23.9195 17.276 26.0805 17.276 27.2778 15.8792L30.6436 11.9524C31.6066 10.8289 31.6066 9.17109 30.6436 8.04763L27.2778 4.12081Z" fill="#9F9FA1" stroke="#F3F3FD" stroke-width="2"/>
|
|
||||||
<path d="M32.2778 4.12081C31.0805 2.72397 28.9195 2.72397 27.7222 4.12081L24.3564 8.04763C23.3934 9.17109 23.3934 10.8289 24.3564 11.9524L27.7222 15.8792C28.9195 17.276 31.0805 17.276 32.2778 15.8792L35.6436 11.9524C36.6066 10.8289 36.6066 9.17109 35.6436 8.04763L32.2778 4.12081Z" fill="#6E6E70" stroke="#F3F3FD" stroke-width="2"/>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 1.9 KiB |
@ -1,7 +0,0 @@
|
|||||||
<svg width="40" height="20" viewBox="0 0 40 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path d="M0 4C0 1.79086 1.79086 0 4 0H36C38.2091 0 40 1.79086 40 4V16C40 18.2091 38.2091 20 36 20H4C1.79086 20 0 18.2091 0 16V4Z" fill="#FFF2F3"/>
|
|
||||||
<path d="M10.4815 4.7716C11.2797 3.84038 12.7203 3.84038 13.5185 4.7716L16.8844 8.69842C17.5263 9.4474 17.5263 10.5526 16.8844 11.3016L13.5185 15.2284C12.7203 16.1596 11.2797 16.1596 10.4815 15.2284L7.11564 11.3016C6.47366 10.5526 6.47366 9.4474 7.11564 8.69842L10.4815 4.7716Z" fill="#FEB0B7"/>
|
|
||||||
<path d="M19.2778 4.12081C18.0805 2.72397 15.9195 2.72397 14.7222 4.12081L11.3564 8.04763C10.3934 9.17109 10.3934 10.8289 11.3564 11.9524L14.7222 15.8792C15.9195 17.276 18.0805 17.276 19.2778 15.8792L22.6436 11.9524C23.6066 10.8289 23.6066 9.1711 22.6436 8.04763L19.2778 4.12081Z" fill="#FEB0B7" stroke="#F3F3FD" stroke-width="2"/>
|
|
||||||
<path d="M24.2778 4.12081C23.0805 2.72397 20.9195 2.72397 19.7222 4.12081L16.3564 8.04763C15.3934 9.17109 15.3934 10.8289 16.3564 11.9524L19.7222 15.8792C20.9195 17.276 23.0805 17.276 24.2778 15.8792L27.6436 11.9524C28.6066 10.8289 28.6066 9.17109 27.6436 8.04763L24.2778 4.12081Z" fill="#FEB0B7" stroke="#F3F3FD" stroke-width="2"/>
|
|
||||||
<path d="M29.2778 4.12081C28.0805 2.72397 25.9195 2.72397 24.7222 4.12081L21.3564 8.04763C20.3934 9.17109 20.3934 10.8289 21.3564 11.9524L24.7222 15.8792C25.9195 17.276 28.0805 17.276 29.2778 15.8792L32.6436 11.9524C33.6066 10.8289 33.6066 9.1711 32.6436 8.04763L29.2778 4.12081Z" fill="#D93644" stroke="#F3F3FD" stroke-width="2"/>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 1.5 KiB |
@ -1,7 +0,0 @@
|
|||||||
<svg width="40" height="20" viewBox="0 0 40 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path d="M0 4C0 1.79086 1.79086 0 4 0H36C38.2091 0 40 1.79086 40 4V16C40 18.2091 38.2091 20 36 20H4C1.79086 20 0 18.2091 0 16V4Z" fill="#F4FAEB"/>
|
|
||||||
<path d="M10.4815 4.7716C11.2797 3.84038 12.7203 3.84038 13.5185 4.7716L16.8844 8.69842C17.5263 9.4474 17.5263 10.5526 16.8844 11.3016L13.5185 15.2284C12.7203 16.1596 11.2797 16.1596 10.4815 15.2284L7.11564 11.3016C6.47366 10.5526 6.47366 9.4474 7.11564 8.69842L10.4815 4.7716Z" fill="#B0D182"/>
|
|
||||||
<path d="M19.2778 4.12081C18.0805 2.72397 15.9195 2.72397 14.7222 4.12081L11.3564 8.04763C10.3934 9.17109 10.3934 10.8289 11.3564 11.9524L14.7222 15.8792C15.9195 17.276 18.0805 17.276 19.2778 15.8792L22.6436 11.9524C23.6066 10.8289 23.6066 9.1711 22.6436 8.04763L19.2778 4.12081Z" fill="#B0D182" stroke="#F3F3FD" stroke-width="2"/>
|
|
||||||
<path d="M24.2778 4.12081C23.0805 2.72397 20.9195 2.72397 19.7222 4.12081L16.3564 8.04763C15.3934 9.17109 15.3934 10.8289 16.3564 11.9524L19.7222 15.8792C20.9195 17.276 23.0805 17.276 24.2778 15.8792L27.6436 11.9524C28.6066 10.8289 28.6066 9.1711 27.6436 8.04763L24.2778 4.12081Z" fill="#B0D182" stroke="#F3F3FD" stroke-width="2"/>
|
|
||||||
<path d="M29.2778 4.12081C28.0805 2.72397 25.9195 2.72397 24.7222 4.12081L21.3564 8.04763C20.3934 9.17109 20.3934 10.8289 21.3564 11.9524L24.7222 15.8792C25.9195 17.276 28.0805 17.276 29.2778 15.8792L32.6436 11.9524C33.6066 10.8289 33.6066 9.1711 32.6436 8.04763L29.2778 4.12081Z" fill="#68A611" stroke="#F3F3FD" stroke-width="2"/>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 1.5 KiB |
@ -1,4 +0,0 @@
|
|||||||
<svg width="40" height="20" viewBox="0 0 40 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<rect x="0.5" y="0.5" width="39" height="19" rx="3.5" stroke="#BDBDBF" stroke-dasharray="2 2"/>
|
|
||||||
<path d="M18.8611 5.09699C19.4598 4.39858 20.5402 4.39858 21.1389 5.09699L24.5047 9.02381C24.9862 9.58555 24.9862 10.4145 24.5047 10.9762L21.1389 14.903C20.5402 15.6014 19.4598 15.6014 18.8611 14.903L15.4953 10.9762C15.0138 10.4145 15.0138 9.58555 15.4953 9.02381L18.8611 5.09699Z" stroke="#78787A"/>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 508 B |
@ -1,6 +0,0 @@
|
|||||||
<svg width="40" height="20" viewBox="0 0 40 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path d="M0 4C0 1.79086 1.79086 0 4 0H36C38.2091 0 40 1.79086 40 4V16C40 18.2091 38.2091 20 36 20H4C1.79086 20 0 18.2091 0 16V4Z" fill="#F3F3FD"/>
|
|
||||||
<path d="M12.4815 4.7716C13.2797 3.84038 14.7203 3.84038 15.5185 4.7716L18.8844 8.69842C19.5263 9.4474 19.5263 10.5526 18.8844 11.3016L15.5185 15.2284C14.7203 16.1596 13.2797 16.1596 12.4815 15.2284L9.11564 11.3016C8.47366 10.5526 8.47366 9.4474 9.11564 8.69842L12.4815 4.7716Z" fill="#BEBBF3"/>
|
|
||||||
<path d="M22.2778 4.12081C21.0805 2.72397 18.9195 2.72397 17.7222 4.12081L14.3564 8.04763C13.3934 9.17109 13.3934 10.8289 14.3564 11.9524L17.7222 15.8792C18.9195 17.276 21.0805 17.276 22.2778 15.8792L25.6436 11.9524C26.6066 10.8289 26.6066 9.1711 25.6436 8.04763L22.2778 4.12081Z" fill="#BEBBF3" stroke="#F3F3FD" stroke-width="2"/>
|
|
||||||
<path d="M28.2778 4.12081C27.0805 2.72397 24.9195 2.72397 23.7222 4.12081L20.3564 8.04763C19.3934 9.17109 19.3934 10.8289 20.3564 11.9524L23.7222 15.8792C24.9195 17.276 27.0805 17.276 28.2778 15.8792L31.6436 11.9524C32.6066 10.8289 32.6066 9.1711 31.6436 8.04763L28.2778 4.12081Z" fill="#817AFE" stroke="#F3F3FD" stroke-width="2"/>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 1.2 KiB |
@ -1,5 +0,0 @@
|
|||||||
<svg width="40" height="20" viewBox="0 0 40 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<rect x="0.5" y="0.5" width="39" height="19" rx="3.5" stroke="#BDBDBF" stroke-dasharray="2 2"/>
|
|
||||||
<path d="M15.4815 4.7716C16.2797 3.84038 17.7203 3.84038 18.5185 4.7716L21.8844 8.69842C22.5263 9.4474 22.5263 10.5526 21.8844 11.3016L18.5185 15.2284C17.7203 16.1596 16.2797 16.1596 15.4815 15.2284L12.1156 11.3016C11.4737 10.5526 11.4737 9.4474 12.1156 8.69842L15.4815 4.7716Z" fill="#BDBDBF"/>
|
|
||||||
<path d="M25.2778 4.12081C24.0805 2.72397 21.9195 2.72397 20.7222 4.12081L17.3564 8.04763C16.3934 9.17109 16.3934 10.8289 17.3564 11.9524L20.7222 15.8792C21.9195 17.276 24.0805 17.276 25.2778 15.8792L28.6436 11.9524C29.6066 10.8289 29.6066 9.1711 28.6436 8.04763L25.2778 4.12081Z" fill="#78787A" stroke="#F7F7FA" stroke-width="2"/>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 839 B |
@ -1,47 +1,25 @@
|
|||||||
import type { FC } from 'react';
|
import type { FC } from 'react';
|
||||||
import { ReactComponent as InitialStageIcon } from 'assets/icons/stage-initial.svg';
|
import { ReactComponent as CreatedIcon } from 'assets/icons/lifecycle/stage-created.svg';
|
||||||
import { ReactComponent as PreLiveStageIcon } from 'assets/icons/stage-pre-live.svg';
|
import { ReactComponent as PreLiveIcon } from 'assets/icons/lifecycle/stage-prelive.svg';
|
||||||
import { ReactComponent as LiveStageIcon } from 'assets/icons/stage-live.svg';
|
import { ReactComponent as LiveIcon } from 'assets/icons/lifecycle/stage-live.svg';
|
||||||
import { ReactComponent as CompletedStageIcon } from 'assets/icons/stage-completed.svg';
|
import { ReactComponent as CompletedIcon } from 'assets/icons/lifecycle/stage-completed.svg';
|
||||||
import { ReactComponent as ArchivedStageIcon } from 'assets/icons/stage-archived.svg';
|
import { ReactComponent as ArchivedIcon } from 'assets/icons/lifecycle/stage-archived.svg';
|
||||||
import { ReactComponent as Stage1 } from 'assets/icons/lifecycle/stage-1.svg';
|
|
||||||
import { ReactComponent as Stage2 } from 'assets/icons/lifecycle/stage-2.svg';
|
|
||||||
import { ReactComponent as Stage3 } from 'assets/icons/lifecycle/stage-3.svg';
|
|
||||||
import { ReactComponent as Stage4 } from 'assets/icons/lifecycle/stage-4.svg';
|
|
||||||
import { ReactComponent as Stage5 } from 'assets/icons/lifecycle/stage-5.svg';
|
|
||||||
import type { LifecycleStage } from '../../feature/FeatureView/FeatureOverview/FeatureLifecycle/LifecycleStage';
|
import type { LifecycleStage } from '../../feature/FeatureView/FeatureOverview/FeatureLifecycle/LifecycleStage';
|
||||||
import { useUiFlag } from 'hooks/useUiFlag';
|
|
||||||
|
|
||||||
export const FeatureLifecycleStageIcon: FC<{
|
export const FeatureLifecycleStageIcon: FC<{
|
||||||
stage: Pick<LifecycleStage, 'name'>;
|
stage: Pick<LifecycleStage, 'name'>;
|
||||||
}> = ({ stage, ...props }) => {
|
}> = ({ stage, ...props }) => {
|
||||||
const newIcons = useUiFlag('lifecycleImprovements');
|
|
||||||
|
|
||||||
if (stage.name === 'archived') {
|
if (stage.name === 'archived') {
|
||||||
return newIcons ? (
|
return <ArchivedIcon {...props} />;
|
||||||
<Stage5 {...props} />
|
|
||||||
) : (
|
|
||||||
<ArchivedStageIcon {...props} />
|
|
||||||
);
|
|
||||||
} else if (stage.name === 'pre-live') {
|
|
||||||
return newIcons ? (
|
|
||||||
<Stage2 {...props} />
|
|
||||||
) : (
|
|
||||||
<PreLiveStageIcon {...props} />
|
|
||||||
);
|
|
||||||
} else if (stage.name === 'live') {
|
|
||||||
return newIcons ? <Stage3 {...props} /> : <LiveStageIcon {...props} />;
|
|
||||||
} else if (stage.name === 'completed') {
|
|
||||||
return newIcons ? (
|
|
||||||
<Stage4 {...props} />
|
|
||||||
) : (
|
|
||||||
<CompletedStageIcon {...props} />
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return newIcons ? (
|
|
||||||
<Stage1 {...props} />
|
|
||||||
) : (
|
|
||||||
<InitialStageIcon {...props} />
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
if (stage.name === 'pre-live') {
|
||||||
|
return <PreLiveIcon {...props} />;
|
||||||
|
}
|
||||||
|
if (stage.name === 'live') {
|
||||||
|
return <LiveIcon {...props} />;
|
||||||
|
}
|
||||||
|
if (stage.name === 'completed') {
|
||||||
|
return <CompletedIcon {...props} />;
|
||||||
|
}
|
||||||
|
return <CreatedIcon {...props} />;
|
||||||
};
|
};
|
||||||
|
@ -1,12 +1,10 @@
|
|||||||
import { FeatureLifecycleStageIcon } from 'component/common/FeatureLifecycle/FeatureLifecycleStageIcon';
|
import { FeatureLifecycleStageIcon } from 'component/common/FeatureLifecycle/FeatureLifecycleStageIcon';
|
||||||
import { FeatureLifecycleTooltip as LegacyFeatureLifecycleTooltip } from './LegacyFeatureLifecycleTooltip';
|
|
||||||
import { FeatureLifecycleTooltip } from './FeatureLifecycleTooltip';
|
import { FeatureLifecycleTooltip } from './FeatureLifecycleTooltip';
|
||||||
import useFeatureLifecycleApi from 'hooks/api/actions/useFeatureLifecycleApi/useFeatureLifecycleApi';
|
import useFeatureLifecycleApi from 'hooks/api/actions/useFeatureLifecycleApi/useFeatureLifecycleApi';
|
||||||
import { populateCurrentStage } from './populateCurrentStage';
|
import { populateCurrentStage } from './populateCurrentStage';
|
||||||
import type { FC } from 'react';
|
import type { FC } from 'react';
|
||||||
import type { Lifecycle } from 'interfaces/featureToggle';
|
import type { Lifecycle } from 'interfaces/featureToggle';
|
||||||
import { usePlausibleTracker } from 'hooks/usePlausibleTracker';
|
import { usePlausibleTracker } from 'hooks/usePlausibleTracker';
|
||||||
import { useUiFlag } from 'hooks/useUiFlag';
|
|
||||||
|
|
||||||
export interface LifecycleFeature {
|
export interface LifecycleFeature {
|
||||||
lifecycle?: Lifecycle;
|
lifecycle?: Lifecycle;
|
||||||
@ -29,7 +27,6 @@ export const FeatureLifecycle: FC<{
|
|||||||
const currentStage = populateCurrentStage(feature);
|
const currentStage = populateCurrentStage(feature);
|
||||||
const { markFeatureUncompleted, loading } = useFeatureLifecycleApi();
|
const { markFeatureUncompleted, loading } = useFeatureLifecycleApi();
|
||||||
const { trackEvent } = usePlausibleTracker();
|
const { trackEvent } = usePlausibleTracker();
|
||||||
const isLifecycleImprovementsEnabled = useUiFlag('lifecycleImprovements');
|
|
||||||
|
|
||||||
const onUncompleteHandler = async () => {
|
const onUncompleteHandler = async () => {
|
||||||
await markFeatureUncompleted(feature.name, feature.project);
|
await markFeatureUncompleted(feature.name, feature.project);
|
||||||
@ -41,7 +38,6 @@ export const FeatureLifecycle: FC<{
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
if (isLifecycleImprovementsEnabled) {
|
|
||||||
return currentStage ? (
|
return currentStage ? (
|
||||||
<FeatureLifecycleTooltip
|
<FeatureLifecycleTooltip
|
||||||
stage={currentStage!}
|
stage={currentStage!}
|
||||||
@ -54,18 +50,4 @@ export const FeatureLifecycle: FC<{
|
|||||||
<FeatureLifecycleStageIcon stage={currentStage} />
|
<FeatureLifecycleStageIcon stage={currentStage} />
|
||||||
</FeatureLifecycleTooltip>
|
</FeatureLifecycleTooltip>
|
||||||
) : null;
|
) : null;
|
||||||
}
|
|
||||||
|
|
||||||
return currentStage ? (
|
|
||||||
<LegacyFeatureLifecycleTooltip
|
|
||||||
stage={currentStage!}
|
|
||||||
project={feature.project}
|
|
||||||
onArchive={onArchive}
|
|
||||||
onComplete={onComplete}
|
|
||||||
onUncomplete={onUncompleteHandler}
|
|
||||||
loading={loading}
|
|
||||||
>
|
|
||||||
<FeatureLifecycleStageIcon stage={currentStage} />
|
|
||||||
</LegacyFeatureLifecycleTooltip>
|
|
||||||
) : null;
|
|
||||||
};
|
};
|
||||||
|
@ -1,526 +0,0 @@
|
|||||||
import { Box, styled, Typography } from '@mui/material';
|
|
||||||
import { Badge } from 'component/common/Badge/Badge';
|
|
||||||
import { HtmlTooltip } from 'component/common/HtmlTooltip/HtmlTooltip';
|
|
||||||
import type * as React from 'react';
|
|
||||||
import type { FC } from 'react';
|
|
||||||
import CloudCircle from '@mui/icons-material/CloudCircle';
|
|
||||||
import { ReactComponent as UsageRate } from 'assets/icons/usage-rate.svg';
|
|
||||||
import { FeatureLifecycleStageIcon } from 'component/common/FeatureLifecycle/FeatureLifecycleStageIcon';
|
|
||||||
import { TimeAgo } from 'component/common/TimeAgo/TimeAgo';
|
|
||||||
import { StyledIconWrapper } from '../../FeatureEnvironmentSeen/FeatureEnvironmentSeen';
|
|
||||||
import { useLastSeenColors } from '../../FeatureEnvironmentSeen/useLastSeenColors';
|
|
||||||
import type { LifecycleStage } from './LifecycleStage';
|
|
||||||
import PermissionButton from 'component/common/PermissionButton/PermissionButton';
|
|
||||||
import {
|
|
||||||
DELETE_FEATURE,
|
|
||||||
UPDATE_FEATURE,
|
|
||||||
} from 'component/providers/AccessProvider/permissions';
|
|
||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
|
||||||
import { isSafeToArchive } from './isSafeToArchive';
|
|
||||||
import { useLocationSettings } from 'hooks/useLocationSettings';
|
|
||||||
import { formatDateYMDHMS } from 'utils/formatDate';
|
|
||||||
import { formatDistanceToNow, parseISO } from 'date-fns';
|
|
||||||
|
|
||||||
const TimeLabel = styled('span')(({ theme }) => ({
|
|
||||||
color: theme.palette.text.secondary,
|
|
||||||
}));
|
|
||||||
|
|
||||||
const InfoText = styled('p')(({ theme }) => ({
|
|
||||||
paddingBottom: theme.spacing(1),
|
|
||||||
}));
|
|
||||||
|
|
||||||
const MainLifecycleRow = styled(Box)(({ theme }) => ({
|
|
||||||
display: 'flex',
|
|
||||||
justifyContent: 'space-between',
|
|
||||||
marginBottom: theme.spacing(2),
|
|
||||||
}));
|
|
||||||
|
|
||||||
const TimeLifecycleRow = styled(Box)(({ theme }) => ({
|
|
||||||
display: 'flex',
|
|
||||||
justifyContent: 'space-between',
|
|
||||||
marginBottom: theme.spacing(1.5),
|
|
||||||
}));
|
|
||||||
|
|
||||||
const IconsRow = styled(Box)(({ theme }) => ({
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
marginTop: theme.spacing(4),
|
|
||||||
marginBottom: theme.spacing(6),
|
|
||||||
}));
|
|
||||||
|
|
||||||
const Line = styled(Box)(({ theme }) => ({
|
|
||||||
height: '1px',
|
|
||||||
background: theme.palette.divider,
|
|
||||||
flex: 1,
|
|
||||||
}));
|
|
||||||
|
|
||||||
const StageBox = styled(Box, {
|
|
||||||
shouldForwardProp: (prop) => prop !== 'active',
|
|
||||||
})<{
|
|
||||||
active?: boolean;
|
|
||||||
}>(({ theme, active }) => ({
|
|
||||||
position: 'relative',
|
|
||||||
// speech bubble triangle for active stage
|
|
||||||
...(active && {
|
|
||||||
'&:before': {
|
|
||||||
content: '""',
|
|
||||||
position: 'absolute',
|
|
||||||
display: 'block',
|
|
||||||
borderStyle: 'solid',
|
|
||||||
borderColor: `${theme.palette.primary.light} transparent`,
|
|
||||||
borderWidth: '0 6px 6px',
|
|
||||||
top: theme.spacing(3.25),
|
|
||||||
left: theme.spacing(1.75),
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
// stage name text
|
|
||||||
'&:after': {
|
|
||||||
content: 'attr(data-after-content)',
|
|
||||||
display: 'block',
|
|
||||||
position: 'absolute',
|
|
||||||
top: theme.spacing(4),
|
|
||||||
left: theme.spacing(-1.25),
|
|
||||||
right: theme.spacing(-1.25),
|
|
||||||
textAlign: 'center',
|
|
||||||
whiteSpace: 'nowrap',
|
|
||||||
fontSize: theme.spacing(1.25),
|
|
||||||
padding: theme.spacing(0.25, 0),
|
|
||||||
color: theme.palette.text.secondary,
|
|
||||||
// active wrapper for stage name text
|
|
||||||
...(active && {
|
|
||||||
backgroundColor: theme.palette.primary.light,
|
|
||||||
color: theme.palette.primary.contrastText,
|
|
||||||
fontWeight: theme.typography.fontWeightBold,
|
|
||||||
borderRadius: theme.spacing(0.5),
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
|
|
||||||
const ColorFill = styled(Box)(({ theme }) => ({
|
|
||||||
backgroundColor: theme.palette.primary.light,
|
|
||||||
color: theme.palette.primary.contrastText,
|
|
||||||
borderRadius: `0 0 ${theme.shape.borderRadiusMedium}px ${theme.shape.borderRadiusMedium}px`, // has to match the parent tooltip container
|
|
||||||
margin: theme.spacing(-1, -1.5), // has to match the parent tooltip container
|
|
||||||
padding: theme.spacing(2, 3),
|
|
||||||
}));
|
|
||||||
|
|
||||||
const LastSeenIcon: FC<{
|
|
||||||
lastSeen: string;
|
|
||||||
}> = ({ lastSeen }) => {
|
|
||||||
const getColor = useLastSeenColors();
|
|
||||||
const { text, background } = getColor(lastSeen);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<StyledIconWrapper style={{ background }}>
|
|
||||||
<UsageRate stroke={text} />
|
|
||||||
</StyledIconWrapper>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const InitialStageDescription: FC = () => {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<InfoText>
|
|
||||||
This feature flag is currently in the initial phase of its
|
|
||||||
lifecycle.
|
|
||||||
</InfoText>
|
|
||||||
<InfoText>
|
|
||||||
This means that the flag has been created, but it has not yet
|
|
||||||
been seen in any environment.
|
|
||||||
</InfoText>
|
|
||||||
<InfoText>
|
|
||||||
Once we detect metrics for a non-production environment it will
|
|
||||||
move into pre-live.
|
|
||||||
</InfoText>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const StageTimeline: FC<{
|
|
||||||
stage: LifecycleStage;
|
|
||||||
}> = ({ stage }) => {
|
|
||||||
return (
|
|
||||||
<IconsRow>
|
|
||||||
<StageBox
|
|
||||||
data-after-content='Initial'
|
|
||||||
active={stage.name === 'initial'}
|
|
||||||
>
|
|
||||||
<FeatureLifecycleStageIcon stage={{ name: 'initial' }} />
|
|
||||||
</StageBox>
|
|
||||||
|
|
||||||
<Line />
|
|
||||||
|
|
||||||
<StageBox
|
|
||||||
data-after-content='Pre-live'
|
|
||||||
active={stage.name === 'pre-live'}
|
|
||||||
>
|
|
||||||
<FeatureLifecycleStageIcon stage={{ name: 'pre-live' }} />
|
|
||||||
</StageBox>
|
|
||||||
|
|
||||||
<Line />
|
|
||||||
|
|
||||||
<StageBox data-after-content='Live' active={stage.name === 'live'}>
|
|
||||||
<FeatureLifecycleStageIcon stage={{ name: 'live' }} />
|
|
||||||
</StageBox>
|
|
||||||
|
|
||||||
<Line />
|
|
||||||
|
|
||||||
<StageBox
|
|
||||||
data-after-content='Completed'
|
|
||||||
active={stage.name === 'completed'}
|
|
||||||
>
|
|
||||||
<FeatureLifecycleStageIcon stage={{ name: 'completed' }} />
|
|
||||||
</StageBox>
|
|
||||||
|
|
||||||
<Line />
|
|
||||||
|
|
||||||
<StageBox
|
|
||||||
data-after-content='Archived'
|
|
||||||
active={stage.name === 'archived'}
|
|
||||||
>
|
|
||||||
<FeatureLifecycleStageIcon stage={{ name: 'archived' }} />
|
|
||||||
</StageBox>
|
|
||||||
</IconsRow>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const EnvironmentLine = styled(Box)(({ theme }) => ({
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'space-between',
|
|
||||||
marginTop: theme.spacing(1),
|
|
||||||
marginBottom: theme.spacing(2),
|
|
||||||
}));
|
|
||||||
|
|
||||||
const CenteredBox = styled(Box)(({ theme }) => ({
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
gap: theme.spacing(1),
|
|
||||||
}));
|
|
||||||
|
|
||||||
const Environments: FC<{
|
|
||||||
environments: Array<{
|
|
||||||
name: string;
|
|
||||||
lastSeenAt: string;
|
|
||||||
}>;
|
|
||||||
}> = ({ environments }) => {
|
|
||||||
return (
|
|
||||||
<Box>
|
|
||||||
{environments.map((environment) => {
|
|
||||||
return (
|
|
||||||
<EnvironmentLine key={environment.name}>
|
|
||||||
<CenteredBox>
|
|
||||||
<CloudCircle />
|
|
||||||
<Box>{environment.name}</Box>
|
|
||||||
</CenteredBox>
|
|
||||||
<CenteredBox>
|
|
||||||
<TimeAgo date={environment.lastSeenAt} />
|
|
||||||
<LastSeenIcon lastSeen={environment.lastSeenAt} />
|
|
||||||
</CenteredBox>
|
|
||||||
</EnvironmentLine>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const PreLiveStageDescription: FC<{ children?: React.ReactNode }> = ({
|
|
||||||
children,
|
|
||||||
}) => {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<InfoText>
|
|
||||||
We've seen the feature flag in the following environments:
|
|
||||||
</InfoText>
|
|
||||||
|
|
||||||
{children}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const ArchivedStageDescription = () => {
|
|
||||||
return (
|
|
||||||
<InfoText>
|
|
||||||
Your feature has been archived, it is now safe to delete it.
|
|
||||||
</InfoText>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const BoldTitle = styled(Typography)(({ theme }) => ({
|
|
||||||
marginTop: theme.spacing(1),
|
|
||||||
marginBottom: theme.spacing(1),
|
|
||||||
fontSize: theme.typography.body2.fontSize,
|
|
||||||
fontWeight: theme.typography.fontWeightBold,
|
|
||||||
}));
|
|
||||||
|
|
||||||
const LiveStageDescription: FC<{
|
|
||||||
onComplete: () => void;
|
|
||||||
loading: boolean;
|
|
||||||
children?: React.ReactNode;
|
|
||||||
project: string;
|
|
||||||
}> = ({ children, onComplete, loading, project }) => {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<BoldTitle>Is this feature complete?</BoldTitle>
|
|
||||||
<InfoText sx={{ mb: 1 }}>
|
|
||||||
Marking the feature flag as complete does not affect any
|
|
||||||
configuration; however, it moves the feature flag to its next
|
|
||||||
lifecycle stage and indicates that you have learned what you
|
|
||||||
needed in order to progress with the feature. It serves as a
|
|
||||||
reminder to start cleaning up the feature flag and removing it
|
|
||||||
from the code.
|
|
||||||
</InfoText>
|
|
||||||
<PermissionButton
|
|
||||||
color='inherit'
|
|
||||||
variant='outlined'
|
|
||||||
permission={UPDATE_FEATURE}
|
|
||||||
size='small'
|
|
||||||
onClick={onComplete}
|
|
||||||
disabled={loading}
|
|
||||||
projectId={project}
|
|
||||||
>
|
|
||||||
Mark completed
|
|
||||||
</PermissionButton>
|
|
||||||
<InfoText sx={{ mt: 3 }}>
|
|
||||||
Users have been exposed to this feature in the following
|
|
||||||
production environments:
|
|
||||||
</InfoText>
|
|
||||||
|
|
||||||
{children}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const SafeToArchive: FC<{
|
|
||||||
onArchive: () => void;
|
|
||||||
onUncomplete: () => void;
|
|
||||||
loading: boolean;
|
|
||||||
project: string;
|
|
||||||
}> = ({ onArchive, onUncomplete, loading, project }) => {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<BoldTitle>Safe to archive</BoldTitle>
|
|
||||||
<InfoText
|
|
||||||
sx={{
|
|
||||||
mt: 2,
|
|
||||||
mb: 1,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
We haven’t seen this feature flag in any environment for at
|
|
||||||
least two days. It’s likely that it’s safe to archive this flag.
|
|
||||||
</InfoText>
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'row',
|
|
||||||
flexWrap: 'wrap',
|
|
||||||
gap: 2,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<PermissionButton
|
|
||||||
color='inherit'
|
|
||||||
variant='outlined'
|
|
||||||
permission={UPDATE_FEATURE}
|
|
||||||
size='small'
|
|
||||||
onClick={onUncomplete}
|
|
||||||
disabled={loading}
|
|
||||||
projectId={project}
|
|
||||||
>
|
|
||||||
Revert to live
|
|
||||||
</PermissionButton>
|
|
||||||
<PermissionButton
|
|
||||||
color='inherit'
|
|
||||||
variant='outlined'
|
|
||||||
permission={DELETE_FEATURE}
|
|
||||||
size='small'
|
|
||||||
sx={{ mb: 2 }}
|
|
||||||
onClick={onArchive}
|
|
||||||
projectId={project}
|
|
||||||
>
|
|
||||||
Archive feature
|
|
||||||
</PermissionButton>
|
|
||||||
</Box>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const ActivelyUsed: FC<{
|
|
||||||
onUncomplete: () => void;
|
|
||||||
loading: boolean;
|
|
||||||
children?: React.ReactNode;
|
|
||||||
}> = ({ children, onUncomplete, loading }) => (
|
|
||||||
<>
|
|
||||||
<InfoText
|
|
||||||
sx={{
|
|
||||||
mt: 1,
|
|
||||||
mb: 1,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
This feature has been successfully completed, but we are still
|
|
||||||
seeing usage. Clean up the feature flag from your code before
|
|
||||||
archiving it:
|
|
||||||
</InfoText>
|
|
||||||
{children}
|
|
||||||
<InfoText
|
|
||||||
sx={{
|
|
||||||
mt: 1,
|
|
||||||
mb: 1,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
If you think this feature was completed too early you can revert to
|
|
||||||
the live stage:
|
|
||||||
</InfoText>
|
|
||||||
<PermissionButton
|
|
||||||
color='inherit'
|
|
||||||
variant='outlined'
|
|
||||||
permission={UPDATE_FEATURE}
|
|
||||||
size='small'
|
|
||||||
sx={{ mb: 2 }}
|
|
||||||
onClick={onUncomplete}
|
|
||||||
disabled={loading}
|
|
||||||
>
|
|
||||||
Revert to live
|
|
||||||
</PermissionButton>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
|
|
||||||
const CompletedStageDescription: FC<{
|
|
||||||
onArchive: () => void;
|
|
||||||
onUncomplete: () => void;
|
|
||||||
loading: boolean;
|
|
||||||
environments: Array<{
|
|
||||||
name: string;
|
|
||||||
lastSeenAt: string;
|
|
||||||
}>;
|
|
||||||
children?: React.ReactNode;
|
|
||||||
project: string;
|
|
||||||
}> = ({
|
|
||||||
children,
|
|
||||||
environments,
|
|
||||||
onArchive,
|
|
||||||
onUncomplete,
|
|
||||||
loading,
|
|
||||||
project,
|
|
||||||
}) => {
|
|
||||||
return (
|
|
||||||
<ConditionallyRender
|
|
||||||
condition={isSafeToArchive(environments)}
|
|
||||||
show={
|
|
||||||
<SafeToArchive
|
|
||||||
onArchive={onArchive}
|
|
||||||
onUncomplete={onUncomplete}
|
|
||||||
loading={loading}
|
|
||||||
project={project}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
elseShow={
|
|
||||||
<ActivelyUsed onUncomplete={onUncomplete} loading={loading}>
|
|
||||||
{children}
|
|
||||||
</ActivelyUsed>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const FormatTime: FC<{
|
|
||||||
time: string;
|
|
||||||
}> = ({ time }) => {
|
|
||||||
const { locationSettings } = useLocationSettings();
|
|
||||||
|
|
||||||
return <span>{formatDateYMDHMS(time, locationSettings.locale)}</span>;
|
|
||||||
};
|
|
||||||
|
|
||||||
const FormatElapsedTime: FC<{
|
|
||||||
time: string;
|
|
||||||
}> = ({ time }) => {
|
|
||||||
const pastTime = parseISO(time);
|
|
||||||
const elapsedTime = formatDistanceToNow(pastTime, { addSuffix: false });
|
|
||||||
return <span>{elapsedTime}</span>;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const FeatureLifecycleTooltip: FC<{
|
|
||||||
children: React.ReactElement<any, any>;
|
|
||||||
stage: LifecycleStage;
|
|
||||||
project: string;
|
|
||||||
onArchive: () => void;
|
|
||||||
onComplete: () => void;
|
|
||||||
onUncomplete: () => void;
|
|
||||||
loading: boolean;
|
|
||||||
}> = ({
|
|
||||||
children,
|
|
||||||
stage,
|
|
||||||
project,
|
|
||||||
onArchive,
|
|
||||||
onComplete,
|
|
||||||
onUncomplete,
|
|
||||||
loading,
|
|
||||||
}) => (
|
|
||||||
<HtmlTooltip
|
|
||||||
maxHeight={800}
|
|
||||||
maxWidth={350}
|
|
||||||
arrow
|
|
||||||
tabIndex={0}
|
|
||||||
title={
|
|
||||||
<Box>
|
|
||||||
<Box sx={(theme) => ({ padding: theme.spacing(2) })}>
|
|
||||||
<MainLifecycleRow>
|
|
||||||
<Typography variant='h3'>Lifecycle</Typography>
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
gap: 1,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Badge sx={{ textTransform: 'capitalize' }}>
|
|
||||||
{stage.name}
|
|
||||||
</Badge>
|
|
||||||
<FeatureLifecycleStageIcon stage={stage} />
|
|
||||||
</Box>
|
|
||||||
</MainLifecycleRow>
|
|
||||||
<TimeLifecycleRow>
|
|
||||||
<TimeLabel>Stage entered at</TimeLabel>
|
|
||||||
|
|
||||||
<FormatTime time={stage.enteredStageAt} />
|
|
||||||
</TimeLifecycleRow>
|
|
||||||
<TimeLifecycleRow>
|
|
||||||
<TimeLabel>Time spent in stage</TimeLabel>
|
|
||||||
<FormatElapsedTime time={stage.enteredStageAt} />
|
|
||||||
</TimeLifecycleRow>
|
|
||||||
<StageTimeline stage={stage} />
|
|
||||||
</Box>
|
|
||||||
<ColorFill>
|
|
||||||
{stage.name === 'initial' && <InitialStageDescription />}
|
|
||||||
{stage.name === 'pre-live' && (
|
|
||||||
<PreLiveStageDescription>
|
|
||||||
<Environments environments={stage.environments} />
|
|
||||||
</PreLiveStageDescription>
|
|
||||||
)}
|
|
||||||
{stage.name === 'live' && (
|
|
||||||
<LiveStageDescription
|
|
||||||
onComplete={onComplete}
|
|
||||||
loading={loading}
|
|
||||||
project={project}
|
|
||||||
>
|
|
||||||
<Environments environments={stage.environments} />
|
|
||||||
</LiveStageDescription>
|
|
||||||
)}
|
|
||||||
{stage.name === 'completed' && (
|
|
||||||
<CompletedStageDescription
|
|
||||||
environments={stage.environments}
|
|
||||||
onArchive={onArchive}
|
|
||||||
onUncomplete={onUncomplete}
|
|
||||||
loading={loading}
|
|
||||||
project={project}
|
|
||||||
>
|
|
||||||
<Environments environments={stage.environments} />
|
|
||||||
</CompletedStageDescription>
|
|
||||||
)}
|
|
||||||
{stage.name === 'archived' && <ArchivedStageDescription />}
|
|
||||||
</ColorFill>
|
|
||||||
</Box>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<CenteredBox>{children}</CenteredBox>
|
|
||||||
</HtmlTooltip>
|
|
||||||
);
|
|
@ -19,10 +19,8 @@ import {
|
|||||||
import { usePlausibleTracker } from 'hooks/usePlausibleTracker';
|
import { usePlausibleTracker } from 'hooks/usePlausibleTracker';
|
||||||
import { ReactComponent as SignalsPreview } from 'assets/img/signals.svg';
|
import { ReactComponent as SignalsPreview } from 'assets/img/signals.svg';
|
||||||
import LifecycleStagesImage from 'assets/img/lifecycle-stages.png';
|
import LifecycleStagesImage from 'assets/img/lifecycle-stages.png';
|
||||||
import LinearScaleIcon from '@mui/icons-material/LinearScale';
|
|
||||||
import MonitorHeartIcon from '@mui/icons-material/MonitorHeartOutlined';
|
import MonitorHeartIcon from '@mui/icons-material/MonitorHeartOutlined';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import { useHighlightContext } from 'component/common/Highlight/HighlightContext';
|
|
||||||
import { formatAssetPath } from 'utils/formatPath';
|
import { formatAssetPath } from 'utils/formatPath';
|
||||||
|
|
||||||
const StyledNewInUnleash = styled('div')(({ theme }) => ({
|
const StyledNewInUnleash = styled('div')(({ theme }) => ({
|
||||||
@ -75,10 +73,6 @@ const StyledSignalsIcon = styled(Signals)(({ theme }) => ({
|
|||||||
color: theme.palette.primary.main,
|
color: theme.palette.primary.main,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const StyledLinearScaleIcon = styled(LinearScaleIcon)(({ theme }) => ({
|
|
||||||
color: theme.palette.primary.main,
|
|
||||||
}));
|
|
||||||
|
|
||||||
const StyledImg = styled('img')(() => ({
|
const StyledImg = styled('img')(() => ({
|
||||||
maxWidth: '100%',
|
maxWidth: '100%',
|
||||||
}));
|
}));
|
||||||
@ -93,7 +87,6 @@ export const NewInUnleash = ({
|
|||||||
onMiniModeClick,
|
onMiniModeClick,
|
||||||
}: INewInUnleashProps) => {
|
}: INewInUnleashProps) => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { highlight } = useHighlightContext();
|
|
||||||
const { trackEvent } = usePlausibleTracker();
|
const { trackEvent } = usePlausibleTracker();
|
||||||
const [seenItems, setSeenItems] = useLocalStorageState(
|
const [seenItems, setSeenItems] = useLocalStorageState(
|
||||||
'new-in-unleash-seen:v1',
|
'new-in-unleash-seen:v1',
|
||||||
@ -101,7 +94,6 @@ export const NewInUnleash = ({
|
|||||||
);
|
);
|
||||||
const { isEnterprise } = useUiConfig();
|
const { isEnterprise } = useUiConfig();
|
||||||
const signalsEnabled = useUiFlag('signals');
|
const signalsEnabled = useUiFlag('signals');
|
||||||
const improvedLifecycleEnabled = useUiFlag('lifecycleImprovements');
|
|
||||||
|
|
||||||
const items: NewInUnleashItemDetails[] = [
|
const items: NewInUnleashItemDetails[] = [
|
||||||
{
|
{
|
||||||
@ -116,7 +108,7 @@ export const NewInUnleash = ({
|
|||||||
),
|
),
|
||||||
docsLink:
|
docsLink:
|
||||||
'https://docs.getunleash.io/reference/feature-toggles#feature-flag-lifecycle',
|
'https://docs.getunleash.io/reference/feature-toggles#feature-flag-lifecycle',
|
||||||
show: improvedLifecycleEnabled,
|
show: true,
|
||||||
longDescription: (
|
longDescription: (
|
||||||
<p>
|
<p>
|
||||||
We have updated the names, icons, and colors for the
|
We have updated the names, icons, and colors for the
|
||||||
|
@ -9,7 +9,6 @@ import type { ProjectStatusSchemaLifecycleSummary } from 'openapi';
|
|||||||
import { HtmlTooltip } from 'component/common/HtmlTooltip/HtmlTooltip';
|
import { HtmlTooltip } from 'component/common/HtmlTooltip/HtmlTooltip';
|
||||||
import { lifecycleMessages } from './LifecycleMessages';
|
import { lifecycleMessages } from './LifecycleMessages';
|
||||||
import InfoIcon from '@mui/icons-material/Info';
|
import InfoIcon from '@mui/icons-material/Info';
|
||||||
import { useUiFlag } from 'hooks/useUiFlag';
|
|
||||||
import { getFeatureLifecycleName } from 'component/common/FeatureLifecycle/getFeatureLifecycleName';
|
import { getFeatureLifecycleName } from 'component/common/FeatureLifecycle/getFeatureLifecycleName';
|
||||||
|
|
||||||
const LifecycleBoxContent = styled('div')(({ theme }) => ({
|
const LifecycleBoxContent = styled('div')(({ theme }) => ({
|
||||||
@ -145,8 +144,6 @@ const BigNumber: FC<{ value?: number }> = ({ value }) => {
|
|||||||
export const ProjectLifecycleSummary = () => {
|
export const ProjectLifecycleSummary = () => {
|
||||||
const projectId = useRequiredPathParam('projectId');
|
const projectId = useRequiredPathParam('projectId');
|
||||||
const { data, loading } = useProjectStatus(projectId);
|
const { data, loading } = useProjectStatus(projectId);
|
||||||
const isLifecycleImprovementsEnabled = useUiFlag('lifecycleImprovements');
|
|
||||||
|
|
||||||
const loadingRef = useLoading<HTMLUListElement>(
|
const loadingRef = useLoading<HTMLUListElement>(
|
||||||
loading,
|
loading,
|
||||||
'[data-loading-project-lifecycle-summary=true]',
|
'[data-loading-project-lifecycle-summary=true]',
|
||||||
@ -155,18 +152,10 @@ export const ProjectLifecycleSummary = () => {
|
|||||||
const flagWord = (stage: keyof ProjectStatusSchemaLifecycleSummary) => {
|
const flagWord = (stage: keyof ProjectStatusSchemaLifecycleSummary) => {
|
||||||
const hasOneFlag = data?.lifecycleSummary[stage].currentFlags === 1;
|
const hasOneFlag = data?.lifecycleSummary[stage].currentFlags === 1;
|
||||||
|
|
||||||
if (hasOneFlag) {
|
return hasOneFlag ? 'Flag' : 'Flags';
|
||||||
return isLifecycleImprovementsEnabled ? 'Flag' : 'flag';
|
|
||||||
}
|
|
||||||
|
|
||||||
return isLifecycleImprovementsEnabled ? 'Flags' : 'flags';
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const stageName = (stage: keyof ProjectStatusSchemaLifecycleSummary) => {
|
const stageName = (stage: keyof ProjectStatusSchemaLifecycleSummary) => {
|
||||||
if (!isLifecycleImprovementsEnabled) {
|
|
||||||
return `${flagWord('initial')} in ${stage}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
const lifecycleStageName = stage === 'preLive' ? 'pre-live' : stage;
|
const lifecycleStageName = stage === 'preLive' ? 'pre-live' : stage;
|
||||||
return (
|
return (
|
||||||
<StyledStageTitle>
|
<StyledStageTitle>
|
||||||
|
@ -92,7 +92,6 @@ export type UiFlags = {
|
|||||||
flagOverviewRedesign?: boolean;
|
flagOverviewRedesign?: boolean;
|
||||||
granularAdminPermissions?: boolean;
|
granularAdminPermissions?: boolean;
|
||||||
sortProjectRoles?: boolean;
|
sortProjectRoles?: boolean;
|
||||||
lifecycleImprovements?: boolean;
|
|
||||||
frontendHeaderRedesign?: boolean;
|
frontendHeaderRedesign?: boolean;
|
||||||
dataUsageMultiMonthView?: boolean;
|
dataUsageMultiMonthView?: boolean;
|
||||||
uiGlobalFontSize?: Variant;
|
uiGlobalFontSize?: Variant;
|
||||||
|
@ -62,7 +62,6 @@ export type IFlagKey =
|
|||||||
| 'deltaApi'
|
| 'deltaApi'
|
||||||
| 'uniqueSdkTracking'
|
| 'uniqueSdkTracking'
|
||||||
| 'sortProjectRoles'
|
| 'sortProjectRoles'
|
||||||
| 'lifecycleImprovements'
|
|
||||||
| 'frontendHeaderRedesign'
|
| 'frontendHeaderRedesign'
|
||||||
| 'dataUsageMultiMonthView'
|
| 'dataUsageMultiMonthView'
|
||||||
| 'uiGlobalFontSize';
|
| 'uiGlobalFontSize';
|
||||||
@ -298,10 +297,6 @@ const flags: IFlags = {
|
|||||||
process.env.UNLEASH_EXPERIMENTAL_SORT_PROJECT_ROLES,
|
process.env.UNLEASH_EXPERIMENTAL_SORT_PROJECT_ROLES,
|
||||||
false,
|
false,
|
||||||
),
|
),
|
||||||
lifecycleImprovements: parseEnvVarBoolean(
|
|
||||||
process.env.UNLEASH_EXPERIMENTAL_LIFECYCLE_IMPROVEMENTS,
|
|
||||||
false,
|
|
||||||
),
|
|
||||||
frontendHeaderRedesign: parseEnvVarBoolean(
|
frontendHeaderRedesign: parseEnvVarBoolean(
|
||||||
process.env.UNLEASH_EXPERIMENTAL_FRONTEND_HEADER_REDESIGN,
|
process.env.UNLEASH_EXPERIMENTAL_FRONTEND_HEADER_REDESIGN,
|
||||||
false,
|
false,
|
||||||
|
@ -57,7 +57,6 @@ process.nextTick(async () => {
|
|||||||
sortProjectRoles: true,
|
sortProjectRoles: true,
|
||||||
deltaApi: true,
|
deltaApi: true,
|
||||||
uniqueSdkTracking: true,
|
uniqueSdkTracking: true,
|
||||||
lifecycleImprovements: true,
|
|
||||||
frontendHeaderRedesign: true,
|
frontendHeaderRedesign: true,
|
||||||
dataUsageMultiMonthView: true,
|
dataUsageMultiMonthView: true,
|
||||||
},
|
},
|
||||||
|