mirror of
https://github.com/Unleash/unleash.git
synced 2025-07-26 13:48:33 +02:00
feat: display created by user in search (#7292)
This commit is contained in:
parent
e79d0707cf
commit
2cc4b5faab
@ -13,8 +13,13 @@ const setupApi = () => {
|
||||
name: 'featureA',
|
||||
tags: [{ type: 'backend', value: 'sdk' }],
|
||||
type: 'operational',
|
||||
createdBy: { id: 1, name: 'author' },
|
||||
},
|
||||
{
|
||||
name: 'featureB',
|
||||
type: 'release',
|
||||
createdBy: { id: 1, name: 'author' },
|
||||
},
|
||||
{ name: 'featureB', type: 'release' },
|
||||
];
|
||||
testServerRoute(server, '/api/admin/search/features', {
|
||||
features,
|
||||
|
@ -39,6 +39,7 @@ import {
|
||||
useProjectFeatureSearch,
|
||||
useProjectFeatureSearchActions,
|
||||
} from './useProjectFeatureSearch';
|
||||
import { UserAvatar } from '../../../common/UserAvatar/UserAvatar';
|
||||
|
||||
interface IPaginatedProjectFeatureTogglesProps {
|
||||
environments: string[];
|
||||
@ -101,6 +102,7 @@ export const ProjectFeatureToggles = ({
|
||||
const isPlaceholder = Boolean(initialLoad || (loading && total));
|
||||
|
||||
const featureLifecycleEnabled = useUiFlag('featureLifecycle');
|
||||
const flagCreatorEnabled = useUiFlag('flagCreator');
|
||||
|
||||
const columns = useMemo(
|
||||
() => [
|
||||
@ -167,6 +169,30 @@ export const ProjectFeatureToggles = ({
|
||||
width: '1%',
|
||||
},
|
||||
}),
|
||||
...(flagCreatorEnabled
|
||||
? [
|
||||
columnHelper.accessor('createdBy', {
|
||||
id: 'createdBy',
|
||||
header: 'By',
|
||||
cell: ({ row: { original } }) => {
|
||||
return (
|
||||
<UserAvatar
|
||||
user={{
|
||||
id: original.createdBy.id,
|
||||
name: original.createdBy.name,
|
||||
imageUrl: original.createdBy.imageUrl,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
},
|
||||
enableSorting: false,
|
||||
meta: {
|
||||
width: '1%',
|
||||
align: 'center',
|
||||
},
|
||||
}),
|
||||
]
|
||||
: []),
|
||||
columnHelper.accessor('lastSeenAt', {
|
||||
id: 'lastSeenAt',
|
||||
header: 'Last seen',
|
||||
@ -305,6 +331,11 @@ export const ProjectFeatureToggles = ({
|
||||
type: '-',
|
||||
name: `Feature name ${index}`,
|
||||
createdAt: new Date().toISOString(),
|
||||
createdBy: {
|
||||
id: 0,
|
||||
name: '',
|
||||
imageUrl: '',
|
||||
},
|
||||
dependencyType: null,
|
||||
favorite: false,
|
||||
impressionData: false,
|
||||
@ -404,6 +435,16 @@ export const ProjectFeatureToggles = ({
|
||||
id: 'createdAt',
|
||||
isVisible: columnVisibility.createdAt,
|
||||
},
|
||||
...(flagCreatorEnabled
|
||||
? [
|
||||
{
|
||||
header: 'By',
|
||||
id: 'createdBy',
|
||||
isVisible:
|
||||
columnVisibility.createdBy,
|
||||
},
|
||||
]
|
||||
: []),
|
||||
{
|
||||
header: 'Last seen',
|
||||
id: 'lastSeenAt',
|
||||
|
@ -57,6 +57,7 @@ export const useDefaultColumnVisibility = (allColumnIds: string[]) => {
|
||||
'lastSeenAt',
|
||||
...(featureLifecycleEnabled ? ['lifecycle'] : []),
|
||||
'createdAt',
|
||||
'createdBy',
|
||||
'type',
|
||||
'tags',
|
||||
...showEnvironments(3),
|
||||
|
@ -87,6 +87,7 @@ export type UiFlags = {
|
||||
enableLegacyVariants?: boolean;
|
||||
navigationSidebar?: boolean;
|
||||
commandBarUI?: boolean;
|
||||
flagCreator?: boolean;
|
||||
};
|
||||
|
||||
export interface IVersionInfo {
|
||||
|
@ -28,7 +28,7 @@ export interface FeatureSearchResponseSchema {
|
||||
*/
|
||||
createdAt: string | null;
|
||||
/** User who created the feature flag */
|
||||
createdBy?: FeatureSearchResponseSchemaCreatedBy;
|
||||
createdBy: FeatureSearchResponseSchemaCreatedBy;
|
||||
/**
|
||||
* The type of dependency. 'parent' means that the feature is a parent feature, 'child' means that the feature is a child feature.
|
||||
* @nullable
|
||||
|
@ -14,7 +14,7 @@ export type FeatureSearchResponseSchemaCreatedBy = {
|
||||
* URL used for the user profile image
|
||||
* @nullable
|
||||
*/
|
||||
imageUrl: string | null;
|
||||
imageUrl: string;
|
||||
/** Name of the user */
|
||||
name: string;
|
||||
};
|
||||
|
@ -122,6 +122,7 @@ exports[`should create default config 1`] = `
|
||||
},
|
||||
},
|
||||
"filterInvalidClientMetrics": false,
|
||||
"flagCreator": false,
|
||||
"googleAuthEnabled": false,
|
||||
"killInsightsUI": false,
|
||||
"killScheduledChangeRequestCache": false,
|
||||
|
@ -19,6 +19,7 @@ import type {
|
||||
} from '../feature-toggle/types/feature-toggle-strategies-store-type';
|
||||
import { applyGenericQueryParams, applySearchFilters } from './search-utils';
|
||||
import type { FeatureSearchEnvironmentSchema } from '../../openapi/spec/feature-search-environment-schema';
|
||||
import { generateImageUrl } from '../../util';
|
||||
|
||||
const sortEnvironments = (overview: IFeatureOverview[]) => {
|
||||
return overview.map((data: IFeatureOverview) => ({
|
||||
@ -404,6 +405,11 @@ class FeatureSearchStore implements IFeatureSearchStore {
|
||||
|
||||
if (!entry) {
|
||||
// Create a new entry
|
||||
const name =
|
||||
row.user_name ||
|
||||
row.user_username ||
|
||||
row.user_email ||
|
||||
'unknown';
|
||||
entry = {
|
||||
type: row.type,
|
||||
description: row.description,
|
||||
@ -419,12 +425,12 @@ class FeatureSearchStore implements IFeatureSearchStore {
|
||||
segments: row.segment_name ? [row.segment_name] : [],
|
||||
createdBy: {
|
||||
id: Number(row.user_id),
|
||||
name:
|
||||
row.user_name ||
|
||||
row.user_username ||
|
||||
row.user_email ||
|
||||
'unknown',
|
||||
imageUrl: row.user_image_url,
|
||||
name: name,
|
||||
imageUrl: generateImageUrl({
|
||||
id: row.user_id,
|
||||
email: row.user_email,
|
||||
username: name,
|
||||
}),
|
||||
},
|
||||
};
|
||||
if (featureLifecycleEnabled) {
|
||||
|
@ -175,11 +175,21 @@ test('should search matching features by name', async () => {
|
||||
features: [
|
||||
{
|
||||
name: 'my_feature_a',
|
||||
createdBy: { id: 1, name: 'user@getunleash.io' },
|
||||
createdBy: {
|
||||
id: 1,
|
||||
name: 'user@getunleash.io',
|
||||
imageUrl:
|
||||
'https://gravatar.com/avatar/3957b71c0a6d2528f03b423f432ed2efe855d263400f960248a1080493d9d68a?s=42&d=retro&r=g',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'my_feature_b',
|
||||
createdBy: { id: 1, name: 'user@getunleash.io' },
|
||||
createdBy: {
|
||||
id: 1,
|
||||
name: 'user@getunleash.io',
|
||||
imageUrl:
|
||||
'https://gravatar.com/avatar/3957b71c0a6d2528f03b423f432ed2efe855d263400f960248a1080493d9d68a?s=42&d=retro&r=g',
|
||||
},
|
||||
},
|
||||
],
|
||||
total: 2,
|
||||
|
@ -21,6 +21,7 @@ export const featureSearchResponseSchema = {
|
||||
'favorite',
|
||||
'impressionData',
|
||||
'createdAt',
|
||||
'createdBy',
|
||||
'environments',
|
||||
'segments',
|
||||
],
|
||||
@ -197,7 +198,6 @@ export const featureSearchResponseSchema = {
|
||||
description: `URL used for the user profile image`,
|
||||
type: 'string',
|
||||
example: 'https://example.com/242x200.png',
|
||||
nullable: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -62,7 +62,8 @@ export type IFlagKey =
|
||||
| 'enableLegacyVariants'
|
||||
| 'debugMetrics'
|
||||
| 'navigationSidebar'
|
||||
| 'commandBarUI';
|
||||
| 'commandBarUI'
|
||||
| 'flagCreator';
|
||||
|
||||
export type IFlags = Partial<{ [key in IFlagKey]: boolean | Variant }>;
|
||||
|
||||
@ -299,6 +300,10 @@ const flags: IFlags = {
|
||||
process.env.UNLEASH_EXPERIMENTAL_COMMAND_BAR_UI,
|
||||
false,
|
||||
),
|
||||
flagCreator: parseEnvVarBoolean(
|
||||
process.env.UNLEASH_EXPERIMENTAL_FLAG_CREATOR,
|
||||
false,
|
||||
),
|
||||
};
|
||||
|
||||
export const defaultExperimentalOptions: IExperimentalOptions = {
|
||||
|
@ -53,6 +53,7 @@ process.nextTick(async () => {
|
||||
createProjectWithEnvironmentConfig: true,
|
||||
manyStrategiesPagination: true,
|
||||
enableLegacyVariants: false,
|
||||
flagCreator: true,
|
||||
},
|
||||
},
|
||||
authentication: {
|
||||
|
Loading…
Reference in New Issue
Block a user