diff --git a/frontend/src/component/feature/FeatureView/FeatureOverview/FeatureLifecycle/FeatureLifecycleStageIcon.tsx b/frontend/src/component/feature/FeatureView/FeatureOverview/FeatureLifecycle/FeatureLifecycleStageIcon.tsx index 34d26247f893..fc88d78821b9 100644 --- a/frontend/src/component/feature/FeatureView/FeatureOverview/FeatureLifecycle/FeatureLifecycleStageIcon.tsx +++ b/frontend/src/component/feature/FeatureView/FeatureOverview/FeatureLifecycle/FeatureLifecycleStageIcon.tsx @@ -5,22 +5,7 @@ import { ReactComponent as LiveStageIcon } from 'assets/icons/stage-live.svg'; import { ReactComponent as CompletedStageIcon } from 'assets/icons/stage-completed.svg'; import { ReactComponent as CompletedDiscardedStageIcon } from 'assets/icons/stage-completed-discarded.svg'; import { ReactComponent as ArchivedStageIcon } from 'assets/icons/stage-archived.svg'; - -export type LifecycleStage = - | { name: 'initial' } - | { - name: 'pre-live'; - environments: Array<{ name: string; lastSeenAt: string }>; - } - | { - name: 'live'; - environments: Array<{ name: string; lastSeenAt: string }>; - } - | { - name: 'completed'; - status: 'kept' | 'discarded'; - } - | { name: 'archived' }; +import type { LifecycleStage } from './LifecycleStage'; export const FeatureLifecycleStageIcon: FC<{ stage: LifecycleStage }> = ({ stage, diff --git a/frontend/src/component/feature/FeatureView/FeatureOverview/FeatureLifecycle/FeatureLifecycleTooltip.tsx b/frontend/src/component/feature/FeatureView/FeatureOverview/FeatureLifecycle/FeatureLifecycleTooltip.tsx index 72717fd8ffea..53c28f8e2e9d 100644 --- a/frontend/src/component/feature/FeatureView/FeatureOverview/FeatureLifecycle/FeatureLifecycleTooltip.tsx +++ b/frontend/src/component/feature/FeatureView/FeatureOverview/FeatureLifecycle/FeatureLifecycleTooltip.tsx @@ -11,14 +11,13 @@ import { ReactComponent as CompletedDiscardedStageIcon } from 'assets/icons/stag import { ReactComponent as ArchivedStageIcon } from 'assets/icons/stage-archived.svg'; import CloudCircle from '@mui/icons-material/CloudCircle'; import { ReactComponent as UsageRate } from 'assets/icons/usage-rate.svg'; -import { - FeatureLifecycleStageIcon, - type LifecycleStage, -} from './FeatureLifecycleStageIcon'; -import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender'; +import { FeatureLifecycleStageIcon } from './FeatureLifecycleStageIcon'; import TimeAgo from 'react-timeago'; import { StyledIconWrapper } from '../../FeatureEnvironmentSeen/FeatureEnvironmentSeen'; 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'; const TimeLabel = styled('span')(({ theme }) => ({ color: theme.palette.text.secondary, @@ -204,52 +203,78 @@ const CenteredBox = styled(Box)(({ theme }) => ({ gap: theme.spacing(1), })); -const LiveStageDescription: FC<{ - name: 'live' | 'pre-live'; +const Environments: FC<{ environments: Array<{ name: string; lastSeenAt: string }>; -}> = ({ name, environments }) => { +}> = ({ environments }) => { + return ( + + {environments.map((environment) => { + return ( + + + + {environment.name} + + + + + + + ); + })} + + ); +}; + +const PreLiveStageDescription: FC = ({ children }) => { return ( <> - - We've seen the feature flag in the following - non-production environments: - - } - /> - - Users have been exposed to this feature in the following - production environments: - - } - /> + + We've seen the feature flag in the following non-production + environments: + - - {environments.map((environment) => { - return ( - - - - {environment.name} - - - - - - - ); - })} - + {children} + + ); +}; + +const BoldTitle = styled(Typography)(({ theme }) => ({ + marginTop: theme.spacing(1), + marginBottom: theme.spacing(1), + fontSize: theme.fontSizes.smallBody, + fontWeight: theme.fontWeight.bold, +})); + +const LiveStageDescription: FC = ({ children }) => { + return ( + <> + Is this feature complete? + + Marking the feature as complete does not affect any + configuration, but it moves the feature into it’s next life + cycle stage and is an indication that you have learned what you + needed in order to progress with the feature. It serves as a + reminder to start cleaning up the flag and removing it from the + code. + + + Mark Completed + + + Users have been exposed to this feature in the following + production environments: + + + {children} ); }; @@ -292,11 +317,15 @@ export const FeatureLifecycleTooltip: FC<{ {stage.name === 'initial' && } - {(stage.name === 'pre-live' || stage.name === 'live') && ( - + {stage.name === 'pre-live' && ( + + + + )} + {stage.name === 'live' && ( + + + )} diff --git a/frontend/src/component/feature/FeatureView/FeatureOverview/FeatureLifecycle/LifecycleStage.tsx b/frontend/src/component/feature/FeatureView/FeatureOverview/FeatureLifecycle/LifecycleStage.tsx new file mode 100644 index 000000000000..79a1bf78e7c0 --- /dev/null +++ b/frontend/src/component/feature/FeatureView/FeatureOverview/FeatureLifecycle/LifecycleStage.tsx @@ -0,0 +1,15 @@ +export type LifecycleStage = + | { name: 'initial' } + | { + name: 'pre-live'; + environments: Array<{ name: string; lastSeenAt: string }>; + } + | { + name: 'live'; + environments: Array<{ name: string; lastSeenAt: string }>; + } + | { + name: 'completed'; + status: 'kept' | 'discarded'; + } + | { name: 'archived' }; diff --git a/frontend/src/component/feature/FeatureView/FeatureOverview/FeatureOverviewMetaData/FeatureOverviewMetaData.tsx b/frontend/src/component/feature/FeatureView/FeatureOverview/FeatureOverviewMetaData/FeatureOverviewMetaData.tsx index 816b86f2cca7..f391dfd8c127 100644 --- a/frontend/src/component/feature/FeatureView/FeatureOverview/FeatureOverviewMetaData/FeatureOverviewMetaData.tsx +++ b/frontend/src/component/feature/FeatureView/FeatureOverview/FeatureOverviewMetaData/FeatureOverviewMetaData.tsx @@ -10,6 +10,7 @@ import { useRequiredPathParam } from 'hooks/useRequiredPathParam'; import { useUiFlag } from 'hooks/useUiFlag'; import { FeatureLifecycleTooltip } from '../FeatureLifecycle/FeatureLifecycleTooltip'; import { FeatureLifecycleStageIcon } from '../FeatureLifecycle/FeatureLifecycleStageIcon'; +import type { LifecycleStage } from '../FeatureLifecycle/LifecycleStage'; const StyledContainer = styled('div')(({ theme }) => ({ borderRadius: theme.shape.borderRadiusLarge, @@ -81,6 +82,17 @@ const FeatureOverviewMetaData = () => { const IconComponent = getFeatureTypeIcons(type); + const currentStage: LifecycleStage = { + name: 'live', + environments: [ + { name: 'production', lastSeenAt: new Date().toISOString() }, + { + name: 'staging', + lastSeenAt: new Date().toISOString(), + }, + ], + }; + return ( @@ -109,11 +121,9 @@ const FeatureOverviewMetaData = () => { show={ Lifecycle: - +