mirror of
https://github.com/Unleash/unleash.git
synced 2025-02-23 00:22:19 +01:00
feat: archived features can be searched now (#8568)
Archived features can be searched now. This is the backend and small parts of frontend preparing to add filters, buttons etc in next PR. --------- Co-authored-by: Thomas Heartman <thomas@getunleash.io>
This commit is contained in:
parent
30c14ff995
commit
28e062b5cf
@ -92,6 +92,7 @@ export const ProjectFeatureToggles = ({
|
|||||||
type: tableState.type,
|
type: tableState.type,
|
||||||
state: tableState.state,
|
state: tableState.state,
|
||||||
createdBy: tableState.createdBy,
|
createdBy: tableState.createdBy,
|
||||||
|
archived: tableState.archived,
|
||||||
};
|
};
|
||||||
|
|
||||||
const { favorite, unfavorite } = useFavoriteFeaturesApi();
|
const { favorite, unfavorite } = useFavoriteFeaturesApi();
|
||||||
|
@ -40,6 +40,7 @@ export const useProjectFeatureSearch = (
|
|||||||
createdAt: FilterItemParam,
|
createdAt: FilterItemParam,
|
||||||
type: FilterItemParam,
|
type: FilterItemParam,
|
||||||
createdBy: FilterItemParam,
|
createdBy: FilterItemParam,
|
||||||
|
archived: FilterItemParam,
|
||||||
};
|
};
|
||||||
const [tableState, setTableState] = usePersistentTableState(
|
const [tableState, setTableState] = usePersistentTableState(
|
||||||
`${storageKey}-${projectId}`,
|
`${storageKey}-${projectId}`,
|
||||||
|
@ -102,6 +102,7 @@ export default class FeatureSearchController extends Controller {
|
|||||||
state,
|
state,
|
||||||
status,
|
status,
|
||||||
favoritesFirst,
|
favoritesFirst,
|
||||||
|
archived,
|
||||||
sortBy,
|
sortBy,
|
||||||
} = req.query;
|
} = req.query;
|
||||||
const userId = req.user.id;
|
const userId = req.user.id;
|
||||||
@ -131,6 +132,7 @@ export default class FeatureSearchController extends Controller {
|
|||||||
['enabled', 'disabled'].includes(tag[1]),
|
['enabled', 'disabled'].includes(tag[1]),
|
||||||
);
|
);
|
||||||
const normalizedFavoritesFirst = favoritesFirst === 'true';
|
const normalizedFavoritesFirst = favoritesFirst === 'true';
|
||||||
|
const normalizedArchived = archived === 'IS:true';
|
||||||
const { features, total } = await this.featureSearchService.search({
|
const { features, total } = await this.featureSearchService.search({
|
||||||
searchParams: normalizedQuery,
|
searchParams: normalizedQuery,
|
||||||
project,
|
project,
|
||||||
@ -147,6 +149,7 @@ export default class FeatureSearchController extends Controller {
|
|||||||
limit: normalizedLimit,
|
limit: normalizedLimit,
|
||||||
sortOrder: normalizedSortOrder,
|
sortOrder: normalizedSortOrder,
|
||||||
favoritesFirst: normalizedFavoritesFirst,
|
favoritesFirst: normalizedFavoritesFirst,
|
||||||
|
archived: normalizedArchived,
|
||||||
});
|
});
|
||||||
|
|
||||||
this.openApiService.respondWithValidation(
|
this.openApiService.respondWithValidation(
|
||||||
|
@ -101,6 +101,7 @@ class FeatureSearchStore implements IFeatureSearchStore {
|
|||||||
limit,
|
limit,
|
||||||
sortOrder,
|
sortOrder,
|
||||||
sortBy,
|
sortBy,
|
||||||
|
archived,
|
||||||
favoritesFirst,
|
favoritesFirst,
|
||||||
}: IFeatureSearchParams,
|
}: IFeatureSearchParams,
|
||||||
queryParams: IQueryParam[],
|
queryParams: IQueryParam[],
|
||||||
@ -188,9 +189,8 @@ class FeatureSearchStore implements IFeatureSearchStore {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
query
|
query
|
||||||
.modify(FeatureToggleStore.filterByArchived, false)
|
.modify(FeatureToggleStore.filterByArchived, archived)
|
||||||
.leftJoin(
|
.leftJoin(
|
||||||
'feature_environments',
|
'feature_environments',
|
||||||
'feature_environments.feature_name',
|
'feature_environments.feature_name',
|
||||||
|
@ -57,16 +57,23 @@ afterAll(async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
|
await db.stores.dependentFeaturesStore.deleteAll();
|
||||||
await db.stores.featureToggleStore.deleteAll();
|
await db.stores.featureToggleStore.deleteAll();
|
||||||
await db.stores.segmentStore.deleteAll();
|
await db.stores.segmentStore.deleteAll();
|
||||||
});
|
});
|
||||||
|
|
||||||
const searchFeatures = async (
|
const searchFeatures = async (
|
||||||
{ query = '', project = 'IS:default' }: FeatureSearchQueryParameters,
|
{
|
||||||
|
query = '',
|
||||||
|
project = 'IS:default',
|
||||||
|
archived = 'IS:false',
|
||||||
|
}: FeatureSearchQueryParameters,
|
||||||
expectedCode = 200,
|
expectedCode = 200,
|
||||||
) => {
|
) => {
|
||||||
return app.request
|
return app.request
|
||||||
.get(`/api/admin/search/features?query=${query}&project=${project}`)
|
.get(
|
||||||
|
`/api/admin/search/features?query=${query}&project=${project}&archived=${archived}`,
|
||||||
|
)
|
||||||
.expect(expectedCode);
|
.expect(expectedCode);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1128,3 +1135,38 @@ test('should return dependencyType', async () => {
|
|||||||
],
|
],
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should return archived when query param set', async () => {
|
||||||
|
await app.createFeature({
|
||||||
|
name: 'my_feature_a',
|
||||||
|
createdAt: '2023-01-29T15:21:39.975Z',
|
||||||
|
});
|
||||||
|
await app.createFeature({
|
||||||
|
name: 'my_feature_b',
|
||||||
|
createdAt: '2023-01-29T15:21:39.975Z',
|
||||||
|
archived: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const { body } = await searchFeatures({
|
||||||
|
query: 'my_feature',
|
||||||
|
});
|
||||||
|
expect(body).toMatchObject({
|
||||||
|
features: [
|
||||||
|
{
|
||||||
|
name: 'my_feature_a',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
const { body: archivedFeatures } = await searchFeatures({
|
||||||
|
query: 'my_feature',
|
||||||
|
archived: 'IS:true',
|
||||||
|
});
|
||||||
|
expect(archivedFeatures).toMatchObject({
|
||||||
|
features: [
|
||||||
|
{
|
||||||
|
name: 'my_feature_b',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
@ -33,6 +33,7 @@ export interface IFeatureSearchParams {
|
|||||||
status?: string[][];
|
status?: string[][];
|
||||||
offset: number;
|
offset: number;
|
||||||
favoritesFirst?: boolean;
|
favoritesFirst?: boolean;
|
||||||
|
archived?: boolean;
|
||||||
limit: number;
|
limit: number;
|
||||||
sortBy?: string;
|
sortBy?: string;
|
||||||
sortOrder: 'asc' | 'desc';
|
sortOrder: 'asc' | 'desc';
|
||||||
|
@ -146,6 +146,16 @@ export const featureSearchQueryParameters = [
|
|||||||
'The flag to indicate if the favorite features should be returned first. By default it is set to false.',
|
'The flag to indicate if the favorite features should be returned first. By default it is set to false.',
|
||||||
in: 'query',
|
in: 'query',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'archived',
|
||||||
|
schema: {
|
||||||
|
type: 'string',
|
||||||
|
example: 'IS:true',
|
||||||
|
},
|
||||||
|
description:
|
||||||
|
'Whether to get results for archived feature flags or active feature flags. If `true`, Unleash will return only archived flags. If `false`, it will return only active flags.',
|
||||||
|
in: 'query',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'createdAt',
|
name: 'createdAt',
|
||||||
schema: {
|
schema: {
|
||||||
|
Loading…
Reference in New Issue
Block a user