From ddd503952b2807f1843702f1292259804c05e0f3 Mon Sep 17 00:00:00 2001
From: Tymoteusz Czech <2625371+Tymek@users.noreply.github.com>
Date: Fri, 1 Aug 2025 10:22:32 +0200
Subject: [PATCH] feat: add lifecycle stage filter to project feature toggles
(#10448)
Backend API is already implemented and ready to be used.
[issue/CTO-244](https://linear.app/unleash/issue/CTO-244/filter-by-lifecycle-on-project-page)
---
.../ProjectFeatureToggles.test.tsx | 31 +++++++++++++++++++
.../ProjectFeatureToggles.tsx | 1 +
.../ProjectOverviewFilters.tsx | 13 ++++++++
.../useProjectFeatureSearch.ts | 1 +
4 files changed, 46 insertions(+)
diff --git a/frontend/src/component/project/Project/PaginatedProjectFeatureToggles/ProjectFeatureToggles.test.tsx b/frontend/src/component/project/Project/PaginatedProjectFeatureToggles/ProjectFeatureToggles.test.tsx
index 19f4441408..bcd455c3e8 100644
--- a/frontend/src/component/project/Project/PaginatedProjectFeatureToggles/ProjectFeatureToggles.test.tsx
+++ b/frontend/src/component/project/Project/PaginatedProjectFeatureToggles/ProjectFeatureToggles.test.tsx
@@ -207,3 +207,34 @@ test('Project is not onboarded', async () => {
);
await screen.findByText('Welcome to your project');
});
+
+test('renders lifecycle filters', async () => {
+ setupApi();
+
+ render(
+
+
+ }
+ />
+ ,
+ {
+ route: '/projects/default',
+ },
+ );
+
+ const addFilter = await screen.findByText('Filter');
+ fireEvent.click(addFilter);
+
+ const lifecycleFilter = await screen.findByText('Lifecycle stage');
+ fireEvent.click(lifecycleFilter);
+
+ await screen.findByText('Define');
+ await screen.findByText('Develop');
+ await screen.findByText('Rollout production');
+ await screen.findByText('Cleanup');
+});
diff --git a/frontend/src/component/project/Project/PaginatedProjectFeatureToggles/ProjectFeatureToggles.tsx b/frontend/src/component/project/Project/PaginatedProjectFeatureToggles/ProjectFeatureToggles.tsx
index cca3070422..03a6127891 100644
--- a/frontend/src/component/project/Project/PaginatedProjectFeatureToggles/ProjectFeatureToggles.tsx
+++ b/frontend/src/component/project/Project/PaginatedProjectFeatureToggles/ProjectFeatureToggles.tsx
@@ -113,6 +113,7 @@ export const ProjectFeatureToggles = ({
state: tableState.state,
createdBy: tableState.createdBy,
archived: tableState.archived,
+ lifecycle: tableState.lifecycle,
};
const { favorite, unfavorite } = useFavoriteFeaturesApi();
diff --git a/frontend/src/component/project/Project/PaginatedProjectFeatureToggles/ProjectOverviewFilters.tsx b/frontend/src/component/project/Project/PaginatedProjectFeatureToggles/ProjectOverviewFilters.tsx
index 8380743795..017ca188cc 100644
--- a/frontend/src/component/project/Project/PaginatedProjectFeatureToggles/ProjectOverviewFilters.tsx
+++ b/frontend/src/component/project/Project/PaginatedProjectFeatureToggles/ProjectOverviewFilters.tsx
@@ -111,6 +111,19 @@ export const ProjectOverviewFilters: VFC = ({
singularOperators: ['IS'],
pluralOperators: ['IS_ANY_OF'],
},
+ {
+ label: 'Lifecycle stage',
+ icon: 'model_training',
+ options: [
+ { label: 'Define', value: 'initial' },
+ { label: 'Develop', value: 'pre-live' },
+ { label: 'Rollout production', value: 'live' },
+ { label: 'Cleanup', value: 'completed' },
+ ],
+ filterKey: 'lifecycle',
+ singularOperators: ['IS', 'IS_NOT'],
+ pluralOperators: ['IS_ANY_OF', 'IS_NONE_OF'],
+ },
];
setAvailableFilters(availableFilters);
diff --git a/frontend/src/component/project/Project/PaginatedProjectFeatureToggles/useProjectFeatureSearch.ts b/frontend/src/component/project/Project/PaginatedProjectFeatureToggles/useProjectFeatureSearch.ts
index 29976c741f..c1cfb6e969 100644
--- a/frontend/src/component/project/Project/PaginatedProjectFeatureToggles/useProjectFeatureSearch.ts
+++ b/frontend/src/component/project/Project/PaginatedProjectFeatureToggles/useProjectFeatureSearch.ts
@@ -41,6 +41,7 @@ export const useProjectFeatureSearch = (
type: FilterItemParam,
createdBy: FilterItemParam,
archived: FilterItemParam,
+ lifecycle: FilterItemParam,
};
const [tableState, setTableState] = usePersistentTableState(
`${storageKey}-${projectId}`,