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:
-
+