1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-01-31 00:16:47 +01:00

ui: update design for feature naming pattern info (#4656)

This PR updates the design for the feature naming pattern info. In doing
so, I've extracted the information into a single component.

It also, on @nicolaesocaciu's behest, makes the new toggle form inputs
wider when they have room to grow.

Light mode:

![image](https://github.com/Unleash/unleash/assets/17786332/0923cf95-18e3-4524-8402-7f42a0ac94ec)


Dark mode:

![image](https://github.com/Unleash/unleash/assets/17786332/c2a07f73-8973-42d0-b94a-d7dc4ec38a25)

For copying features it looks like this:


![image](https://github.com/Unleash/unleash/assets/17786332/2a39f17b-4d86-408c-8f3b-5f2b24e82c81)
This commit is contained in:
Thomas Heartman 2023-09-13 08:05:58 +02:00 committed by GitHub
parent c39d815516
commit 03d6ed0c32
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 181 additions and 194 deletions

View File

@ -20,6 +20,7 @@ import { useFeature } from 'hooks/api/getters/useFeature/useFeature';
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
import { useChangeRequestsEnabled } from '../../../hooks/useChangeRequestsEnabled';
import useProject from 'hooks/api/getters/useProject/useProject';
import { FeatureNamingPatternInfo } from '../FeatureNamingPatternInfo/FeatureNamingPatternInfo';
const StyledPage = styled(Paper)(({ theme }) => ({
overflow: 'visible',
@ -141,41 +142,9 @@ export const CopyFeatureToggle = () => {
<ConditionallyRender
condition={displayFeatureNamingInfo}
show={
<>
<p>
This project has feature flag naming patterns
enabled, so the name must also match the
configured pattern.
</p>
<dl id="feature-naming-pattern-info">
<dt>Pattern</dt>
<dd>
<code>{featureNaming?.pattern}</code>
</dd>
<ConditionallyRender
condition={Boolean(featureNaming?.example)}
show={
<>
<dt>Example</dt>
<dd>{featureNaming?.example}</dd>
</>
}
/>
<ConditionallyRender
condition={Boolean(
featureNaming?.description
)}
show={
<>
<dt>Description</dt>
<dd>
{featureNaming?.description}
</dd>
</>
}
/>
</dl>
</>
<FeatureNamingPatternInfo
featureNaming={featureNaming!}
/>
}
/>
<StyledForm onSubmit={onSubmit}>

View File

@ -22,6 +22,7 @@ import { useNavigate } from 'react-router-dom';
import React from 'react';
import { useAuthPermissions } from 'hooks/api/getters/useAuth/useAuthPermissions';
import { FeatureNamingType } from 'interfaces/project';
import { FeatureNamingPatternInfo } from '../FeatureNamingPatternInfo/FeatureNamingPatternInfo';
interface IFeatureToggleForm {
type: string;
@ -44,15 +45,9 @@ interface IFeatureToggleForm {
}
const StyledForm = styled('form')({
display: 'flex',
flexDirection: 'column',
height: '100%',
});
const StyledContainer = styled('div')({
maxWidth: '400px',
});
const StyledInputDescription = styled('p')(({ theme }) => ({
marginBottom: theme.spacing(1),
}));
@ -82,11 +77,6 @@ const StyledTypeDescription = styled('p')(({ theme }) => ({
position: 'relative',
}));
const StyledFlagNamingInfo = styled('div')(({ theme }) => ({
fontSize: theme.fontSizes.smallBody,
color: theme.palette.text.secondary,
}));
const StyledButtonContainer = styled('div')({
marginTop: 'auto',
display: 'flex',
@ -147,156 +137,121 @@ const FeatureForm: React.FC<IFeatureToggleForm> = ({
return (
<StyledForm onSubmit={handleSubmit}>
<StyledContainer>
<StyledInputDescription>
What would you like to call your toggle?
</StyledInputDescription>
<ConditionallyRender
condition={displayFeatureNamingInfo}
show={
<StyledFlagNamingInfo>
<p>
This project has feature flag naming patterns
enabled.
</p>
<dl id="feature-naming-pattern-info">
<dt>Pattern</dt>
<dd>
<code>{featureNaming?.pattern}</code>
</dd>
<ConditionallyRender
condition={Boolean(featureNaming?.example)}
show={
<>
<dt>Example</dt>
<dd>{featureNaming?.example}</dd>
</>
}
/>
<ConditionallyRender
condition={Boolean(
featureNaming?.description
)}
show={
<>
<dt>Description</dt>
<dd>
{featureNaming?.description}
</dd>
</>
}
/>
</dl>
</StyledFlagNamingInfo>
}
/>
<StyledInput
autoFocus
disabled={mode === 'Edit'}
label="Name"
aria-details={
displayFeatureNamingInfo
? 'feature-naming-pattern-info'
: undefined
}
id="feature-toggle-name"
error={Boolean(errors.name)}
errorText={errors.name}
onFocus={() => clearErrors()}
value={name}
onChange={e => setName(trim(e.target.value))}
data-testid={CF_NAME_ID}
onBlur={validateToggleName}
/>
<StyledInputDescription>
What kind of feature toggle do you want?
</StyledInputDescription>
<FeatureTypeSelect
sx={styledSelectInput}
value={type}
onChange={setType}
label={'Toggle type'}
id="feature-type-select"
editable
data-testid={CF_TYPE_ID}
IconComponent={KeyboardArrowDownOutlined}
/>
<StyledTypeDescription>
{renderToggleDescription()}
</StyledTypeDescription>
<ConditionallyRender
condition={editable}
show={
<StyledInputDescription>
In which project do you want to save the toggle?
</StyledInputDescription>
}
/>
<FeatureProjectSelect
value={project}
onChange={projectId => {
setProject(projectId);
navigate(`/projects/${projectId}/create-toggle`, {
replace: true,
});
}}
enabled={editable}
filter={projectFilterGenerator(permissions, CREATE_FEATURE)}
IconComponent={KeyboardArrowDownOutlined}
sx={styledSelectInput}
/>
<StyledInputDescription>
What would you like to call your toggle?
</StyledInputDescription>
<ConditionallyRender
condition={displayFeatureNamingInfo}
show={
<FeatureNamingPatternInfo featureNaming={featureNaming!} />
}
/>
<StyledInput
autoFocus
disabled={mode === 'Edit'}
label="Name"
aria-details={
displayFeatureNamingInfo
? 'feature-naming-pattern-info'
: undefined
}
id="feature-toggle-name"
error={Boolean(errors.name)}
errorText={errors.name}
onFocus={() => clearErrors()}
value={name}
onChange={e => setName(trim(e.target.value))}
data-testid={CF_NAME_ID}
onBlur={validateToggleName}
/>
<StyledInputDescription>
What kind of feature toggle do you want?
</StyledInputDescription>
<FeatureTypeSelect
sx={styledSelectInput}
value={type}
onChange={setType}
label={'Toggle type'}
id="feature-type-select"
editable
data-testid={CF_TYPE_ID}
IconComponent={KeyboardArrowDownOutlined}
/>
<StyledTypeDescription>
{renderToggleDescription()}
</StyledTypeDescription>
<ConditionallyRender
condition={editable}
show={
<StyledInputDescription>
In which project do you want to save the toggle?
</StyledInputDescription>
}
/>
<FeatureProjectSelect
value={project}
onChange={projectId => {
setProject(projectId);
navigate(`/projects/${projectId}/create-toggle`, {
replace: true,
});
}}
enabled={editable}
filter={projectFilterGenerator(permissions, CREATE_FEATURE)}
IconComponent={KeyboardArrowDownOutlined}
sx={styledSelectInput}
/>
<StyledInputDescription>
How would you describe your feature toggle?
</StyledInputDescription>
<StyledInput
multiline
rows={4}
label="Description"
placeholder="A short description of the feature toggle"
value={description}
data-testid={CF_DESC_ID}
onChange={e => setDescription(e.target.value)}
/>
<StyledFormControl>
<Typography
variant="subtitle1"
sx={styledTypography}
data-loading
component="h2"
<StyledInputDescription>
How would you describe your feature toggle?
</StyledInputDescription>
<StyledInput
multiline
rows={4}
label="Description"
placeholder="A short description of the feature toggle"
value={description}
data-testid={CF_DESC_ID}
onChange={e => setDescription(e.target.value)}
/>
<StyledFormControl>
<Typography
variant="subtitle1"
sx={styledTypography}
data-loading
component="h2"
>
Impression Data
</Typography>
<p>
When you enable impression data for a feature toggle, your
client SDKs will emit events you can listen for every time
this toggle gets triggered. Learn more in{' '}
<Link
target="_blank"
rel="noopener noreferrer"
href="https://docs.getunleash.io/advanced/impression_data"
>
Impression Data
</Typography>
<p>
When you enable impression data for a feature toggle,
your client SDKs will emit events you can listen for
every time this toggle gets triggered. Learn more in{' '}
<Link
target="_blank"
rel="noopener noreferrer"
href="https://docs.getunleash.io/advanced/impression_data"
>
the impression data documentation
</Link>
</p>
<StyledRow>
<FormControlLabel
labelPlacement="start"
style={{ marginLeft: 0 }}
control={
<Switch
name="impressionData"
onChange={() =>
setImpressionData(!impressionData)
}
checked={impressionData}
/>
}
label="Enable impression data"
/>
</StyledRow>
</StyledFormControl>
</StyledContainer>
the impression data documentation
</Link>
</p>
<StyledRow>
<FormControlLabel
labelPlacement="start"
style={{ marginLeft: 0 }}
control={
<Switch
name="impressionData"
onChange={() =>
setImpressionData(!impressionData)
}
checked={impressionData}
/>
}
label="Enable impression data"
/>
</StyledRow>
</StyledFormControl>
<StyledButtonContainer>
{children}
<StyledCancelButton onClick={handleCancel}>

View File

@ -0,0 +1,63 @@
import { styled } from '@mui/material';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
import { FeatureNamingType } from 'interfaces/project';
const StyledFlagNamingInfo = styled('article')(({ theme }) => ({
fontSize: theme.fontSizes.smallBody,
padding: theme.spacing(2),
borderRadius: theme.shape.borderRadius,
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),
},
marginBlockEnd: theme.spacing(2),
}));
type Props = {
featureNaming: FeatureNamingType;
};
export const FeatureNamingPatternInfo: React.FC<Props> = ({
featureNaming,
}) => {
return (
<StyledFlagNamingInfo>
<p>This project has feature flag naming patterns enabled.</p>
<dl id="feature-naming-pattern-info">
<dt>Pattern</dt>
<dd>
<code>{featureNaming.pattern}</code>
</dd>
<ConditionallyRender
condition={Boolean(featureNaming?.example)}
show={
<>
<dt>Example</dt>
<dd>{featureNaming?.example}</dd>
</>
}
/>
<ConditionallyRender
condition={Boolean(featureNaming?.description)}
show={
<>
<dt>Description</dt>
<dd>{featureNaming?.description}</dd>
</>
}
/>
</dl>
</StyledFlagNamingInfo>
);
};