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:
parent
c39d815516
commit
03d6ed0c32
@ -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}>
|
||||
|
@ -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}>
|
||||
|
@ -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>
|
||||
);
|
||||
};
|
Loading…
Reference in New Issue
Block a user