mirror of
https://github.com/Unleash/unleash.git
synced 2025-01-01 00:08:27 +01:00
fix: display feature naming patterns in dialog (#7837)
Updates the dialog form template to include a `namingPattern` prop that can be used to display the naming pattern of whatever the form is used for. Also updates the create feature dialog to display the naming pattern in the current project. The naming pattern component re-uses the pattern that we have in place for feature naming patterns, but puts it in an expandable dialog instead. Screenies: Naming pattern closed: ![image](https://github.com/user-attachments/assets/145e4268-1aa0-4c1b-8f08-97857447e2f5) ![image](https://github.com/user-attachments/assets/1613c846-e7d4-41c8-a1c8-a66ab87b6e5f) Naming pattern open: ![image](https://github.com/user-attachments/assets/1aa37162-500b-4b83-926f-07aa777e8017)
This commit is contained in:
parent
6f9492ef12
commit
bc1f261cf2
@ -33,11 +33,14 @@ export const StyledHeader = styled(Typography)({
|
|||||||
fontWeight: 'lighter',
|
fontWeight: 'lighter',
|
||||||
});
|
});
|
||||||
|
|
||||||
export const ProjectNameContainer = styled('div')({
|
export const NameContainer = styled('div')(({ theme }) => ({
|
||||||
gridArea: 'project-name',
|
gridArea: 'project-name',
|
||||||
});
|
display: 'flex',
|
||||||
|
flexFlow: 'column nowrap',
|
||||||
|
gap: theme.spacing(2),
|
||||||
|
}));
|
||||||
|
|
||||||
export const ProjectDescriptionContainer = styled('div')({
|
export const DescriptionContainer = styled('div')({
|
||||||
gridArea: 'project-description',
|
gridArea: 'project-description',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -2,8 +2,8 @@ import type { FormEventHandler } from 'react';
|
|||||||
import theme from 'themes/theme';
|
import theme from 'themes/theme';
|
||||||
import {
|
import {
|
||||||
ConfigButtons,
|
ConfigButtons,
|
||||||
ProjectDescriptionContainer,
|
DescriptionContainer,
|
||||||
ProjectNameContainer,
|
NameContainer,
|
||||||
StyledForm,
|
StyledForm,
|
||||||
StyledHeader,
|
StyledHeader,
|
||||||
StyledInput,
|
StyledInput,
|
||||||
@ -15,6 +15,11 @@ import {
|
|||||||
import { Button } from '@mui/material';
|
import { Button } from '@mui/material';
|
||||||
import { CreateButton } from 'component/common/CreateButton/CreateButton';
|
import { CreateButton } from 'component/common/CreateButton/CreateButton';
|
||||||
import type { IPermissionButtonProps } from 'component/common/PermissionButton/PermissionButton';
|
import type { IPermissionButtonProps } from 'component/common/PermissionButton/PermissionButton';
|
||||||
|
import type { FeatureNamingType } from 'interfaces/project';
|
||||||
|
import { ConditionallyRender } from '../ConditionallyRender/ConditionallyRender';
|
||||||
|
import { NamingPatternInfo } from './NamingPatternInfo';
|
||||||
|
|
||||||
|
type NamingPattern = FeatureNamingType;
|
||||||
|
|
||||||
type FormProps = {
|
type FormProps = {
|
||||||
createButtonProps: IPermissionButtonProps;
|
createButtonProps: IPermissionButtonProps;
|
||||||
@ -30,12 +35,14 @@ type FormProps = {
|
|||||||
setDescription: (newDescription: string) => void;
|
setDescription: (newDescription: string) => void;
|
||||||
setName: (newName: string) => void;
|
setName: (newName: string) => void;
|
||||||
validateName?: () => void;
|
validateName?: () => void;
|
||||||
|
namingPattern?: NamingPattern;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const DialogFormTemplate: React.FC<FormProps> = ({
|
export const DialogFormTemplate: React.FC<FormProps> = ({
|
||||||
Limit,
|
Limit,
|
||||||
handleSubmit,
|
handleSubmit,
|
||||||
name,
|
name,
|
||||||
|
namingPattern,
|
||||||
setName,
|
setName,
|
||||||
description,
|
description,
|
||||||
setDescription,
|
setDescription,
|
||||||
@ -47,15 +54,22 @@ export const DialogFormTemplate: React.FC<FormProps> = ({
|
|||||||
createButtonProps,
|
createButtonProps,
|
||||||
validateName = () => {},
|
validateName = () => {},
|
||||||
}) => {
|
}) => {
|
||||||
|
const displayNamingPattern = Boolean(namingPattern?.pattern);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledForm onSubmit={handleSubmit}>
|
<StyledForm onSubmit={handleSubmit}>
|
||||||
<TopGrid>
|
<TopGrid>
|
||||||
<IconWrapper>{Icon}</IconWrapper>
|
<IconWrapper>{Icon}</IconWrapper>
|
||||||
<StyledHeader variant='h2'>Create {resource}</StyledHeader>
|
<StyledHeader variant='h2'>Create {resource}</StyledHeader>
|
||||||
<ProjectNameContainer>
|
<NameContainer>
|
||||||
<StyledInput
|
<StyledInput
|
||||||
label={`${resource} name`}
|
label={`${resource} name`}
|
||||||
aria-required
|
aria-required
|
||||||
|
aria-details={
|
||||||
|
displayNamingPattern
|
||||||
|
? 'naming-pattern-info'
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
value={name}
|
value={name}
|
||||||
onChange={(e) => setName(e.target.value)}
|
onChange={(e) => setName(e.target.value)}
|
||||||
error={Boolean(errors.name)}
|
error={Boolean(errors.name)}
|
||||||
@ -74,8 +88,13 @@ export const DialogFormTemplate: React.FC<FormProps> = ({
|
|||||||
data-testid='FORM_NAME_INPUT'
|
data-testid='FORM_NAME_INPUT'
|
||||||
size='medium'
|
size='medium'
|
||||||
/>
|
/>
|
||||||
</ProjectNameContainer>
|
|
||||||
<ProjectDescriptionContainer>
|
<ConditionallyRender
|
||||||
|
condition={displayNamingPattern}
|
||||||
|
show={<NamingPatternInfo naming={namingPattern!} />}
|
||||||
|
/>
|
||||||
|
</NameContainer>
|
||||||
|
<DescriptionContainer>
|
||||||
<StyledInput
|
<StyledInput
|
||||||
size='medium'
|
size='medium'
|
||||||
className='description'
|
className='description'
|
||||||
@ -92,7 +111,7 @@ export const DialogFormTemplate: React.FC<FormProps> = ({
|
|||||||
}}
|
}}
|
||||||
data-testid='FORM_DESCRIPTION_INPUT'
|
data-testid='FORM_DESCRIPTION_INPUT'
|
||||||
/>
|
/>
|
||||||
</ProjectDescriptionContainer>
|
</DescriptionContainer>
|
||||||
</TopGrid>
|
</TopGrid>
|
||||||
|
|
||||||
<ConfigButtons>{configButtons}</ConfigButtons>
|
<ConfigButtons>{configButtons}</ConfigButtons>
|
||||||
|
@ -0,0 +1,83 @@
|
|||||||
|
import {
|
||||||
|
Accordion,
|
||||||
|
AccordionDetails,
|
||||||
|
AccordionSummary,
|
||||||
|
styled,
|
||||||
|
} from '@mui/material';
|
||||||
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
|
import type { FeatureNamingType } from 'interfaces/project';
|
||||||
|
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
|
||||||
|
|
||||||
|
const StyledFlagNamingInfo = styled('article')(({ theme }) => ({
|
||||||
|
fontSize: theme.typography.body2.fontSize,
|
||||||
|
borderRadius: theme.shape.borderRadius,
|
||||||
|
marginInlineStart: theme.spacing(1.5),
|
||||||
|
backgroundColor: `${theme.palette.background.elevation2}`,
|
||||||
|
dl: {
|
||||||
|
display: 'grid',
|
||||||
|
gridTemplateColumns: 'max-content auto',
|
||||||
|
rowGap: theme.spacing(1),
|
||||||
|
columnGap: 0,
|
||||||
|
},
|
||||||
|
dt: {
|
||||||
|
color: theme.palette.text.secondary,
|
||||||
|
'&::after': { content: '":"' },
|
||||||
|
},
|
||||||
|
dd: {
|
||||||
|
marginInlineStart: theme.spacing(2),
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
const StyledAccordion = styled(Accordion)(({ theme }) => ({
|
||||||
|
backgroundColor: 'inherit',
|
||||||
|
boxShadow: 'none',
|
||||||
|
margin: 0,
|
||||||
|
}));
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
naming: FeatureNamingType;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const NamingPatternInfo: React.FC<Props> = ({ naming }) => {
|
||||||
|
const controlId = 'naming-pattern-info-summary';
|
||||||
|
return (
|
||||||
|
<StyledFlagNamingInfo>
|
||||||
|
<StyledAccordion>
|
||||||
|
<AccordionSummary
|
||||||
|
id={controlId}
|
||||||
|
aria-controls={controlId}
|
||||||
|
expandIcon={<ExpandMoreIcon />}
|
||||||
|
>
|
||||||
|
Name must match: <code>^{naming.pattern}$</code>
|
||||||
|
</AccordionSummary>
|
||||||
|
<AccordionDetails>
|
||||||
|
<p>The name must match this pattern:</p>
|
||||||
|
<dl id='naming-pattern-info'>
|
||||||
|
<dt>Pattern</dt>
|
||||||
|
<dd>
|
||||||
|
<code>^{naming.pattern}$</code>
|
||||||
|
</dd>
|
||||||
|
<ConditionallyRender
|
||||||
|
condition={Boolean(naming?.example)}
|
||||||
|
show={
|
||||||
|
<>
|
||||||
|
<dt>Example</dt>
|
||||||
|
<dd>{naming?.example}</dd>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<ConditionallyRender
|
||||||
|
condition={Boolean(naming?.description)}
|
||||||
|
show={
|
||||||
|
<>
|
||||||
|
<dt>Description</dt>
|
||||||
|
<dd>{naming?.description}</dd>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</dl>
|
||||||
|
</AccordionDetails>
|
||||||
|
</StyledAccordion>
|
||||||
|
</StyledFlagNamingInfo>
|
||||||
|
);
|
||||||
|
};
|
@ -227,6 +227,7 @@ const CreateFeatureDialogContent = ({
|
|||||||
tooltipProps: { title: limitMessage, arrow: true },
|
tooltipProps: { title: limitMessage, arrow: true },
|
||||||
}}
|
}}
|
||||||
description={description}
|
description={description}
|
||||||
|
namingPattern={projectInfo.featureNaming}
|
||||||
errors={errors}
|
errors={errors}
|
||||||
handleSubmit={handleSubmit}
|
handleSubmit={handleSubmit}
|
||||||
Icon={<FlagIcon />}
|
Icon={<FlagIcon />}
|
||||||
|
Loading…
Reference in New Issue
Block a user