1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-03-27 00:19:39 +01:00

feat: update UI to add hints about implicit ^ and $ (#4667)

This PR updates the UI to reflect the changes to the implicit ^ and $
that we now add. The changes are:

1. Show input adornments for ^ and $ when you create a pattern.
2. Mention that ^ and $ are added implicitly in description.
3. Checks the example you provide against the pattern with added ^ and $
+ adds a test for that.

Points 1 and 2:

![image](https://github.com/Unleash/unleash/assets/17786332/88c610b4-444b-4a83-a50a-4b7639614a86)


## Discussion point:

I have not touched the information about the pattern yet as the PR that
updates that is still in review (#4656), but it would be prudent to also
update that info to make it clearer. I can address that in a follow-up
PR.
This commit is contained in:
Thomas Heartman 2023-09-13 08:22:55 +02:00 committed by GitHub
parent 03d6ed0c32
commit f49cc8cd33
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 51 additions and 22 deletions

View File

@ -37,7 +37,7 @@ export const FeatureNamingPatternInfo: React.FC<Props> = ({
<dl id="feature-naming-pattern-info">
<dt>Pattern</dt>
<dd>
<code>{featureNaming.pattern}</code>
<code>^{featureNaming.pattern}$</code>
</dd>
<ConditionallyRender
condition={Boolean(featureNaming?.example)}

View File

@ -4,7 +4,6 @@ import { HelpIcon } from 'component/common/HelpIcon/HelpIcon';
export const FeatureFlagNamingTooltip: FC = () => {
const X = 'X';
const Y = 'Y';
const nx = 'n{X,}';
const nxy = 'n{X,Y}';
return (
@ -14,7 +13,7 @@ export const FeatureFlagNamingTooltip: FC = () => {
<Box>
<h3>Enforce a naming convention for feature flags</h3>
<hr />
<p>{`eg. ^[A-Za-z0-9]{2}[.][a-z]{4,12}$ matches 'a1.project'`}</p>
<p>{`eg. [A-Za-z0-9]{2}[.][a-z]{4,12} matches 'a1.project'`}</p>
<div className="scrollable">
<h3>Brackets:</h3>
<table>

View File

@ -4,7 +4,7 @@ import { StickinessSelect } from 'component/feature/StrategyTypes/FlexibleStrate
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
import Select from 'component/common/select';
import { ProjectMode } from '../hooks/useProjectForm';
import { Box, styled, TextField } from '@mui/material';
import { Box, InputAdornment, styled, TextField } from '@mui/material';
import { CollaborationModeTooltip } from './CollaborationModeTooltip';
import Input from 'component/common/Input/Input';
import { FeatureTogglesLimitTooltip } from './FeatureTogglesLimitTooltip';
@ -106,6 +106,10 @@ const StyledFlagNamingContainer = styled('div')(({ theme }) => ({
'& > *': { width: '100%' },
}));
const StyledPatternNamingExplanation = styled('div')(({ theme }) => ({
'p + p': { marginTop: theme.spacing(1) },
}));
export const validateFeatureNamingExample = ({
pattern,
example,
@ -118,7 +122,7 @@ export const validateFeatureNamingExample = ({
if (featureNamingPatternError || !example || !pattern) {
return { state: 'valid' };
} else if (example && pattern) {
const regex = new RegExp(pattern);
const regex = new RegExp(`^${pattern}$`);
const matches = regex.test(example);
if (!matches) {
return { state: 'invalid', reason: 'Example does not match regex' };
@ -354,29 +358,45 @@ const ProjectForm: React.FC<IProjectForm> = ({
<FeatureFlagNamingTooltip />
</Box>
<StyledSubtitle>
<p id="pattern-naming-description">
A feature flag naming pattern is a{' '}
<a
href={`https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions`}
target="_blank"
rel="noreferrer"
>
JavaScript RegEx
</a>{' '}
used to enforce feature flag names within
this project.
</p>
<p>
Leave it empty if you dont want to add a
naming pattern.
</p>
<StyledPatternNamingExplanation id="pattern-naming-description">
<p>
Define a{' '}
<a
href={`https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions`}
target="_blank"
rel="noreferrer"
>
JavaScript RegEx
</a>{' '}
used to enforce feature flag names
within this project. The regex will be
surrounded by a leading <code>^</code>{' '}
and a trailing <code>$</code>.
</p>
<p>
Leave it empty if you dont want to add
a naming pattern.
</p>
</StyledPatternNamingExplanation>
</StyledSubtitle>
<StyledFlagNamingContainer>
<StyledInput
label={'Naming Pattern'}
name="feature flag naming pattern"
aria-describedby="pattern-naming-description"
placeholder="^[A-Za-z]+\.[A-Za-z]+\.[A-Za-z0-9-]+$"
placeholder="[A-Za-z]+\.[A-Za-z]+\.[A-Za-z0-9-]+"
InputProps={{
startAdornment: (
<InputAdornment position="start">
^
</InputAdornment>
),
endAdornment: (
<InputAdornment position="end">
$
</InputAdornment>
),
}}
type={'text'}
value={featureNamingPattern || ''}
error={Boolean(errors.featureNamingPattern)}

View File

@ -47,4 +47,14 @@ describe('validateFeatureNaming', () => {
expect(result.state).toBe(state);
}
);
test('the pattern gets an implicit leading ^ and trailing $ added', () => {
const result = validateFeatureNamingExample({
pattern: '[a-z]+',
example: 'not.valid',
featureNamingPatternError: undefined,
});
expect(result.state).toBe('invalid');
});
});