1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-05-12 01:17:04 +02:00

Feat: feature view created by field - frontend (#7382)

add "Created by:" to feature overview meta and align other items
This commit is contained in:
Tymoteusz Czech 2024-06-13 13:00:57 +02:00 committed by GitHub
parent 906940948b
commit 582b33e121
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 65 additions and 2 deletions

View File

@ -25,7 +25,7 @@ interface IPermissionIconButtonProps {
edge?: IconButtonProps['edge']; edge?: IconButtonProps['edge'];
tooltipProps?: Omit<ITooltipResolverProps, 'children'>; tooltipProps?: Omit<ITooltipResolverProps, 'children'>;
sx?: IconButtonProps['sx']; sx?: IconButtonProps['sx'];
size?: string; size?: 'small' | 'medium' | 'large';
} }
interface IButtonProps extends IPermissionIconButtonProps { interface IButtonProps extends IPermissionIconButtonProps {
@ -87,7 +87,7 @@ const BasePermissionIconButton = ({
{...rest} {...rest}
disabled={!access || disabled} disabled={!access || disabled}
aria-labelledby={id} aria-labelledby={id}
size='large' size={rest.size || 'large'}
> >
{children} {children}
</IconButton> </IconButton>

View File

@ -107,12 +107,16 @@ export const DependencyRow: FC<{ feature: IFeatureToggle }> = ({ feature }) => {
<StyledDetail> <StyledDetail>
<StyledLabel>Dependency:</StyledLabel> <StyledLabel>Dependency:</StyledLabel>
<PermissionButton <PermissionButton
size='small'
permission={UPDATE_FEATURE_DEPENDENCY} permission={UPDATE_FEATURE_DEPENDENCY}
projectId={feature.project} projectId={feature.project}
variant='text' variant='text'
onClick={() => { onClick={() => {
setShowDependencyDialogue(true); setShowDependencyDialogue(true);
}} }}
sx={(theme) => ({
marginBottom: theme.spacing(0.4),
})}
> >
Add parent feature Add parent feature
</PermissionButton> </PermissionButton>

View File

@ -21,6 +21,7 @@ import { useShowDependentFeatures } from './useShowDependentFeatures';
import type { ILastSeenEnvironments } from 'interfaces/featureToggle'; import type { ILastSeenEnvironments } from 'interfaces/featureToggle';
import { FeatureLifecycle } from '../FeatureLifecycle/FeatureLifecycle'; import { FeatureLifecycle } from '../FeatureLifecycle/FeatureLifecycle';
import { MarkCompletedDialogue } from '../FeatureLifecycle/MarkCompletedDialogue'; import { MarkCompletedDialogue } from '../FeatureLifecycle/MarkCompletedDialogue';
import { UserAvatar } from 'component/common/UserAvatar/UserAvatar';
const StyledContainer = styled('div')(({ theme }) => ({ const StyledContainer = styled('div')(({ theme }) => ({
borderRadius: theme.shape.borderRadiusLarge, borderRadius: theme.shape.borderRadiusLarge,
@ -83,6 +84,10 @@ const StyledDescription = styled('p')({
wordBreak: 'break-word', wordBreak: 'break-word',
}); });
const StyledUserAvatar = styled(UserAvatar)(({ theme }) => ({
margin: theme.spacing(1),
}));
export const StyledLabel = styled('span')(({ theme }) => ({ export const StyledLabel = styled('span')(({ theme }) => ({
color: theme.palette.text.secondary, color: theme.palette.text.secondary,
marginRight: theme.spacing(1), marginRight: theme.spacing(1),
@ -98,6 +103,7 @@ const FeatureOverviewMetaData = () => {
const [showDelDialog, setShowDelDialog] = useState(false); const [showDelDialog, setShowDelDialog] = useState(false);
const [showMarkCompletedDialogue, setShowMarkCompletedDialogue] = const [showMarkCompletedDialogue, setShowMarkCompletedDialogue] =
useState(false); useState(false);
const flagCreatorEnabled = useUiFlag('flagCreator');
const { locationSettings } = useLocationSettings(); const { locationSettings } = useLocationSettings();
const showDependentFeatures = useShowDependentFeatures(feature.project); const showDependentFeatures = useShowDependentFeatures(feature.project);
@ -166,6 +172,7 @@ const FeatureOverviewMetaData = () => {
{description} {description}
</StyledDescription> </StyledDescription>
<PermissionIconButton <PermissionIconButton
size='medium'
projectId={projectId} projectId={projectId}
permission={UPDATE_FEATURE} permission={UPDATE_FEATURE}
component={Link} component={Link}
@ -184,6 +191,7 @@ const FeatureOverviewMetaData = () => {
<StyledDescriptionContainer> <StyledDescriptionContainer>
No description.{' '} No description.{' '}
<PermissionIconButton <PermissionIconButton
size='medium'
projectId={projectId} projectId={projectId}
permission={UPDATE_FEATURE} permission={UPDATE_FEATURE}
component={Link} component={Link}
@ -216,6 +224,24 @@ const FeatureOverviewMetaData = () => {
/> />
</StyledDetailsContainer> </StyledDetailsContainer>
</BodyItemWithIcon> </BodyItemWithIcon>
<ConditionallyRender
condition={
Boolean(feature.createdBy) && flagCreatorEnabled
}
show={() => (
<BodyItemWithIcon>
<StyledDetailsContainer>
<StyledDetail>
<StyledLabel>Created by:</StyledLabel>
<span>{feature.createdBy?.name}</span>
</StyledDetail>
<StyledUserAvatar
src={feature.createdBy?.imageUrl}
/>
</StyledDetailsContainer>
</BodyItemWithIcon>
)}
/>
<ConditionallyRender <ConditionallyRender
condition={showDependentFeatures} condition={showDependentFeatures}
show={<DependencyRow feature={feature} />} show={<DependencyRow feature={feature} />}

View File

@ -38,6 +38,9 @@ export type Lifecycle = {
enteredStageAt: string; enteredStageAt: string;
}; };
/**
* @deprecated use FeatureSchema from openapi
*/
export interface IFeatureToggle { export interface IFeatureToggle {
stale: boolean; stale: boolean;
archived: boolean; archived: boolean;
@ -57,6 +60,11 @@ export interface IFeatureToggle {
dependencies: Array<IDependency>; dependencies: Array<IDependency>;
lifecycle?: Lifecycle; lifecycle?: Lifecycle;
children: Array<string>; children: Array<string>;
createdBy?: {
id: string;
name: string;
imageUrl: string;
};
} }
export interface IDependency { export interface IDependency {

View File

@ -3,6 +3,7 @@
* Do not edit manually. * Do not edit manually.
* See `gen:api` script in package.json * See `gen:api` script in package.json
*/ */
import type { FeatureSchemaCreatedBy } from './featureSchemaCreatedBy';
import type { FeatureSchemaDependenciesItem } from './featureSchemaDependenciesItem'; import type { FeatureSchemaDependenciesItem } from './featureSchemaDependenciesItem';
import type { FeatureEnvironmentSchema } from './featureEnvironmentSchema'; import type { FeatureEnvironmentSchema } from './featureEnvironmentSchema';
import type { FeatureSchemaLifecycle } from './featureSchemaLifecycle'; import type { FeatureSchemaLifecycle } from './featureSchemaLifecycle';
@ -28,6 +29,8 @@ export interface FeatureSchema {
* @nullable * @nullable
*/ */
createdAt?: string | null; createdAt?: string | null;
/** User who created the feature flag */
createdBy?: FeatureSchemaCreatedBy;
/** The list of parent dependencies. This is an experimental field and may change. */ /** The list of parent dependencies. This is an experimental field and may change. */
dependencies?: FeatureSchemaDependenciesItem[]; dependencies?: FeatureSchemaDependenciesItem[];
/** /**

View File

@ -0,0 +1,17 @@
/**
* Generated by Orval
* Do not edit manually.
* See `gen:api` script in package.json
*/
/**
* User who created the feature flag
*/
export type FeatureSchemaCreatedBy = {
/** The user id */
id: number;
/** URL used for the user profile image */
imageUrl: string;
/** Name of the user */
name: string;
};

View File

@ -543,6 +543,7 @@ export * from './featureLifecycleSchemaItem';
export * from './featureLifecycleSchemaItemStage'; export * from './featureLifecycleSchemaItemStage';
export * from './featureMetricsSchema'; export * from './featureMetricsSchema';
export * from './featureSchema'; export * from './featureSchema';
export * from './featureSchemaCreatedBy';
export * from './featureSchemaDependenciesItem'; export * from './featureSchemaDependenciesItem';
export * from './featureSchemaLifecycle'; export * from './featureSchemaLifecycle';
export * from './featureSchemaLifecycleStage'; export * from './featureSchemaLifecycleStage';

View File

@ -21,6 +21,10 @@ export type SearchFeaturesParams = {
* The feature flag type to filter by. The type can be specified with an operator. The supported operators are IS, IS_NOT, IS_ANY_OF, IS_NONE_OF. * The feature flag type to filter by. The type can be specified with an operator. The supported operators are IS, IS_NOT, IS_ANY_OF, IS_NONE_OF.
*/ */
type?: string; type?: string;
/**
* The feature flag creator to filter by. The creators can be specified with an operator. The supported operators are IS, IS_NOT, IS_ANY_OF, IS_NONE_OF.
*/
createdBy?: string;
/** /**
* The list of feature tags to filter by. Feature tag has to specify a type and a value joined with a colon. * The list of feature tags to filter by. Feature tag has to specify a type and a value joined with a colon.
*/ */