mirror of
https://github.com/Unleash/unleash.git
synced 2025-01-11 00:08:30 +01:00
fix: reducing of features will not break order anymore (#5654)
This commit is contained in:
parent
8283edfc0a
commit
dafec2e672
@ -19,8 +19,8 @@ import {
|
||||
} from '../feature-toggle/types/feature-toggle-strategies-store-type';
|
||||
import FeatureStrategiesStore from '../feature-toggle/feature-toggle-strategies-store';
|
||||
|
||||
const sortEnvironments = (overview: IFeatureOverview) => {
|
||||
return Object.values(overview).map((data: IFeatureOverview) => ({
|
||||
const sortEnvironments = (overview: IFeatureOverview[]) => {
|
||||
return overview.map((data: IFeatureOverview) => ({
|
||||
...data,
|
||||
environments: data.environments
|
||||
.filter((f) => f.name)
|
||||
@ -296,34 +296,16 @@ class FeatureSearchStore implements IFeatureSearchStore {
|
||||
};
|
||||
}
|
||||
|
||||
getAggregatedSearchData(rows): IFeatureOverview {
|
||||
return rows.reduce((acc, row) => {
|
||||
if (acc[row.feature_name] !== undefined) {
|
||||
const environmentExists = acc[
|
||||
row.feature_name
|
||||
].environments.some(
|
||||
(existingEnvironment) =>
|
||||
existingEnvironment.name === row.environment,
|
||||
);
|
||||
if (!environmentExists) {
|
||||
acc[row.feature_name].environments.push(
|
||||
FeatureSearchStore.getEnvironment(row),
|
||||
);
|
||||
}
|
||||
getAggregatedSearchData(rows): IFeatureOverview[] {
|
||||
const entriesMap: Map<string, IFeatureOverview> = new Map();
|
||||
const orderedEntries: IFeatureOverview[] = [];
|
||||
|
||||
const segmentExists = acc[row.feature_name].segments.includes(
|
||||
row.segment_name,
|
||||
);
|
||||
rows.forEach((row) => {
|
||||
let entry = entriesMap.get(row.feature_name);
|
||||
|
||||
if (row.segment_name && !segmentExists) {
|
||||
acc[row.feature_name].segments.push(row.segment_name);
|
||||
}
|
||||
|
||||
if (this.isNewTag(acc[row.feature_name], row)) {
|
||||
this.addTag(acc[row.feature_name], row);
|
||||
}
|
||||
} else {
|
||||
acc[row.feature_name] = {
|
||||
if (!entry) {
|
||||
// Create a new entry
|
||||
entry = {
|
||||
type: row.type,
|
||||
description: row.description,
|
||||
project: row.project,
|
||||
@ -333,24 +315,41 @@ class FeatureSearchStore implements IFeatureSearchStore {
|
||||
stale: row.stale,
|
||||
impressionData: row.impression_data,
|
||||
lastSeenAt: row.last_seen_at,
|
||||
environments: [FeatureSearchStore.getEnvironment(row)],
|
||||
environments: [],
|
||||
segments: row.segment_name ? [row.segment_name] : [],
|
||||
};
|
||||
entriesMap.set(row.feature_name, entry);
|
||||
orderedEntries.push(entry);
|
||||
}
|
||||
|
||||
if (this.isNewTag(acc[row.feature_name], row)) {
|
||||
this.addTag(acc[row.feature_name], row);
|
||||
}
|
||||
// Add environment if not already present
|
||||
if (!entry.environments.some((e) => e.name === row.environment)) {
|
||||
entry.environments.push(FeatureSearchStore.getEnvironment(row));
|
||||
}
|
||||
const featureRow = acc[row.feature_name];
|
||||
|
||||
// Add segment if not already present
|
||||
if (
|
||||
featureRow.lastSeenAt === undefined ||
|
||||
new Date(row.env_last_seen_at) >
|
||||
new Date(featureRow.last_seen_at)
|
||||
row.segment_name &&
|
||||
!entry.segments.includes(row.segment_name)
|
||||
) {
|
||||
featureRow.lastSeenAt = row.env_last_seen_at;
|
||||
entry.segments.push(row.segment_name);
|
||||
}
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
// Add tag if new
|
||||
if (this.isNewTag(entry, row)) {
|
||||
this.addTag(entry, row);
|
||||
}
|
||||
|
||||
// Update lastSeenAt if more recent
|
||||
if (
|
||||
!entry.lastSeenAt ||
|
||||
new Date(row.env_last_seen_at) > new Date(entry.lastSeenAt)
|
||||
) {
|
||||
entry.lastSeenAt = row.env_last_seen_at;
|
||||
}
|
||||
});
|
||||
|
||||
return orderedEntries;
|
||||
}
|
||||
|
||||
private addTag(
|
||||
@ -369,13 +368,16 @@ class FeatureSearchStore implements IFeatureSearchStore {
|
||||
};
|
||||
}
|
||||
|
||||
private isTagRow(row: Record<string, any>): boolean {
|
||||
return row.tag_type && row.tag_value;
|
||||
}
|
||||
|
||||
private isNewTag(
|
||||
featureToggle: Record<string, any>,
|
||||
row: Record<string, any>,
|
||||
): boolean {
|
||||
return (
|
||||
row.tag_type &&
|
||||
row.tag_value &&
|
||||
this.isTagRow(row) &&
|
||||
!featureToggle.tags?.some(
|
||||
(tag) =>
|
||||
tag.type === row.tag_type && tag.value === row.tag_value,
|
||||
|
@ -477,6 +477,31 @@ test('should sort features', async () => {
|
||||
total: 3,
|
||||
});
|
||||
});
|
||||
|
||||
test('should sort features when feature names are numbers', async () => {
|
||||
await app.createFeature('my_feature_a');
|
||||
await app.createFeature('my_feature_c');
|
||||
await app.createFeature('my_feature_b');
|
||||
await app.createFeature('1234');
|
||||
await app.favoriteFeature('my_feature_b');
|
||||
|
||||
const { body: favoriteSortByName } = await sortFeatures({
|
||||
sortBy: 'name',
|
||||
sortOrder: 'asc',
|
||||
favoritesFirst: 'true',
|
||||
});
|
||||
|
||||
expect(favoriteSortByName).toMatchObject({
|
||||
features: [
|
||||
{ name: 'my_feature_b' },
|
||||
{ name: '1234' },
|
||||
{ name: 'my_feature_a' },
|
||||
{ name: 'my_feature_c' },
|
||||
],
|
||||
total: 4,
|
||||
});
|
||||
});
|
||||
|
||||
test('should paginate correctly when using tags', async () => {
|
||||
await app.createFeature('my_feature_a');
|
||||
await app.createFeature('my_feature_b');
|
||||
|
@ -205,6 +205,11 @@ export interface IEnvironmentOverview extends IEnvironmentBase {
|
||||
|
||||
export interface IFeatureOverview {
|
||||
name: string;
|
||||
description: string;
|
||||
project: string;
|
||||
favorite: boolean;
|
||||
impressionData: boolean;
|
||||
segments: string[];
|
||||
type: string;
|
||||
stale: boolean;
|
||||
createdAt: Date;
|
||||
|
Loading…
Reference in New Issue
Block a user