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}`,