mirror of
https://github.com/Unleash/unleash.git
synced 2024-12-22 19:07:54 +01:00
UI: make project settings / creation form full-width (#4675)
This PR makes the project settings / creation forms grow to take up the full available width, so that it is in line with the new designs.
This commit is contained in:
parent
f49cc8cd33
commit
43878230b7
@ -44,16 +44,10 @@ const PROJECT_NAME_INPUT = 'PROJECT_NAME_INPUT';
|
||||
const PROJECT_DESCRIPTION_INPUT = 'PROJECT_DESCRIPTION_INPUT';
|
||||
|
||||
const StyledForm = styled('form')(({ theme }) => ({
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
height: '100%',
|
||||
paddingBottom: theme.spacing(4),
|
||||
}));
|
||||
|
||||
const StyledContainer = styled('div')(() => ({
|
||||
maxWidth: '400px',
|
||||
}));
|
||||
|
||||
const StyledDescription = styled('p')(({ theme }) => ({
|
||||
marginBottom: theme.spacing(1),
|
||||
marginRight: theme.spacing(1),
|
||||
@ -215,243 +209,234 @@ const ProjectForm: React.FC<IProjectForm> = ({
|
||||
|
||||
return (
|
||||
<StyledForm onSubmit={handleSubmit}>
|
||||
<StyledContainer>
|
||||
<StyledDescription>What is your project Id?</StyledDescription>
|
||||
<StyledInput
|
||||
label="Project Id"
|
||||
value={projectId}
|
||||
onChange={e => setProjectId(trim(e.target.value))}
|
||||
error={Boolean(errors.id)}
|
||||
errorText={errors.id}
|
||||
onFocus={() => clearErrors()}
|
||||
onBlur={validateProjectId}
|
||||
disabled={mode === 'Edit'}
|
||||
data-testid={PROJECT_ID_INPUT}
|
||||
autoFocus
|
||||
required
|
||||
/>
|
||||
<StyledDescription>What is your project Id?</StyledDescription>
|
||||
<StyledInput
|
||||
label="Project Id"
|
||||
value={projectId}
|
||||
onChange={e => setProjectId(trim(e.target.value))}
|
||||
error={Boolean(errors.id)}
|
||||
errorText={errors.id}
|
||||
onFocus={() => clearErrors()}
|
||||
onBlur={validateProjectId}
|
||||
disabled={mode === 'Edit'}
|
||||
data-testid={PROJECT_ID_INPUT}
|
||||
autoFocus
|
||||
required
|
||||
/>
|
||||
|
||||
<StyledDescription>
|
||||
What is your project name?
|
||||
</StyledDescription>
|
||||
<StyledInput
|
||||
label="Project name"
|
||||
value={projectName}
|
||||
onChange={e => setProjectName(e.target.value)}
|
||||
error={Boolean(errors.name)}
|
||||
errorText={errors.name}
|
||||
onFocus={() => {
|
||||
delete errors.name;
|
||||
<StyledDescription>What is your project name?</StyledDescription>
|
||||
<StyledInput
|
||||
label="Project name"
|
||||
value={projectName}
|
||||
onChange={e => setProjectName(e.target.value)}
|
||||
error={Boolean(errors.name)}
|
||||
errorText={errors.name}
|
||||
onFocus={() => {
|
||||
delete errors.name;
|
||||
}}
|
||||
data-testid={PROJECT_NAME_INPUT}
|
||||
required
|
||||
/>
|
||||
|
||||
<StyledDescription>
|
||||
What is your project description?
|
||||
</StyledDescription>
|
||||
<StyledTextField
|
||||
label="Project description"
|
||||
variant="outlined"
|
||||
multiline
|
||||
maxRows={4}
|
||||
value={projectDesc}
|
||||
onChange={e => setProjectDesc(e.target.value)}
|
||||
data-testid={PROJECT_DESCRIPTION_INPUT}
|
||||
/>
|
||||
|
||||
<ConditionallyRender
|
||||
condition={setProjectStickiness != null}
|
||||
show={
|
||||
<>
|
||||
<StyledDescription>
|
||||
What is the default stickiness for the project?
|
||||
</StyledDescription>
|
||||
<StickinessSelect
|
||||
label="Stickiness"
|
||||
value={projectStickiness}
|
||||
data-testid={PROJECT_STICKINESS_SELECT}
|
||||
onChange={e =>
|
||||
setProjectStickiness &&
|
||||
setProjectStickiness(e.target.value)
|
||||
}
|
||||
editable
|
||||
/>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
<>
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
marginBottom: 1,
|
||||
gap: 1,
|
||||
}}
|
||||
data-testid={PROJECT_NAME_INPUT}
|
||||
required
|
||||
/>
|
||||
|
||||
<StyledDescription>
|
||||
What is your project description?
|
||||
</StyledDescription>
|
||||
<StyledTextField
|
||||
label="Project description"
|
||||
variant="outlined"
|
||||
multiline
|
||||
maxRows={4}
|
||||
value={projectDesc}
|
||||
onChange={e => setProjectDesc(e.target.value)}
|
||||
data-testid={PROJECT_DESCRIPTION_INPUT}
|
||||
/>
|
||||
|
||||
<ConditionallyRender
|
||||
condition={setProjectStickiness != null}
|
||||
show={
|
||||
<>
|
||||
<StyledDescription>
|
||||
What is the default stickiness for the project?
|
||||
</StyledDescription>
|
||||
<StickinessSelect
|
||||
label="Stickiness"
|
||||
value={projectStickiness}
|
||||
data-testid={PROJECT_STICKINESS_SELECT}
|
||||
onChange={e =>
|
||||
setProjectStickiness &&
|
||||
setProjectStickiness(e.target.value)
|
||||
}
|
||||
editable
|
||||
/>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
<>
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
marginBottom: 1,
|
||||
gap: 1,
|
||||
}}
|
||||
>
|
||||
<p>What is your project collaboration mode?</p>
|
||||
<CollaborationModeTooltip />
|
||||
</Box>
|
||||
<StyledSelect
|
||||
id="project-mode"
|
||||
value={projectMode}
|
||||
label="Project collaboration mode"
|
||||
name="Project collaboration mode"
|
||||
onChange={e => {
|
||||
setProjectMode?.(e.target.value as ProjectMode);
|
||||
}}
|
||||
options={[
|
||||
{ key: 'open', label: 'open' },
|
||||
{ key: 'protected', label: 'protected' },
|
||||
]}
|
||||
></StyledSelect>
|
||||
</>
|
||||
<>
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
marginBottom: 1,
|
||||
gap: 1,
|
||||
}}
|
||||
>
|
||||
<p>Feature flag limit?</p>
|
||||
<FeatureTogglesLimitTooltip />
|
||||
</Box>
|
||||
<StyledSubtitle>
|
||||
Leave it empty if you don’t want to add a limit
|
||||
</StyledSubtitle>
|
||||
<StyledInputContainer>
|
||||
<StyledInput
|
||||
label={'Limit'}
|
||||
name="value"
|
||||
type={'number'}
|
||||
value={featureLimit}
|
||||
onChange={e => setFeatureLimit(e.target.value)}
|
||||
/>
|
||||
<ConditionallyRender
|
||||
condition={
|
||||
featureCount !== undefined &&
|
||||
Boolean(featureLimit)
|
||||
}
|
||||
show={
|
||||
<Box>
|
||||
({featureCount} of {featureLimit} used)
|
||||
</Box>
|
||||
}
|
||||
/>
|
||||
</StyledInputContainer>
|
||||
</>
|
||||
<ConditionallyRender
|
||||
condition={Boolean(shouldShowFlagNaming)}
|
||||
show={
|
||||
<StyledFieldset>
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
marginBottom: 1,
|
||||
gap: 1,
|
||||
}}
|
||||
>
|
||||
<legend>Feature flag naming pattern?</legend>
|
||||
<FeatureFlagNamingTooltip />
|
||||
>
|
||||
<p>What is your project collaboration mode?</p>
|
||||
<CollaborationModeTooltip />
|
||||
</Box>
|
||||
<StyledSelect
|
||||
id="project-mode"
|
||||
value={projectMode}
|
||||
label="Project collaboration mode"
|
||||
name="Project collaboration mode"
|
||||
onChange={e => {
|
||||
setProjectMode?.(e.target.value as ProjectMode);
|
||||
}}
|
||||
options={[
|
||||
{ key: 'open', label: 'open' },
|
||||
{ key: 'protected', label: 'protected' },
|
||||
]}
|
||||
></StyledSelect>
|
||||
</>
|
||||
<>
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
marginBottom: 1,
|
||||
gap: 1,
|
||||
}}
|
||||
>
|
||||
<p>Feature flag limit?</p>
|
||||
<FeatureTogglesLimitTooltip />
|
||||
</Box>
|
||||
<StyledSubtitle>
|
||||
Leave it empty if you don’t want to add a limit
|
||||
</StyledSubtitle>
|
||||
<StyledInputContainer>
|
||||
<StyledInput
|
||||
label={'Limit'}
|
||||
name="value"
|
||||
type={'number'}
|
||||
value={featureLimit}
|
||||
onChange={e => setFeatureLimit(e.target.value)}
|
||||
/>
|
||||
<ConditionallyRender
|
||||
condition={
|
||||
featureCount !== undefined && Boolean(featureLimit)
|
||||
}
|
||||
show={
|
||||
<Box>
|
||||
({featureCount} of {featureLimit} used)
|
||||
</Box>
|
||||
}
|
||||
/>
|
||||
</StyledInputContainer>
|
||||
</>
|
||||
<ConditionallyRender
|
||||
condition={Boolean(shouldShowFlagNaming)}
|
||||
show={
|
||||
<StyledFieldset>
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
marginBottom: 1,
|
||||
gap: 1,
|
||||
}}
|
||||
>
|
||||
<legend>Feature flag naming pattern?</legend>
|
||||
<FeatureFlagNamingTooltip />
|
||||
</Box>
|
||||
<StyledSubtitle>
|
||||
<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 don’t 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-]+"
|
||||
InputProps={{
|
||||
startAdornment: (
|
||||
<InputAdornment position="start">
|
||||
^
|
||||
</InputAdornment>
|
||||
),
|
||||
endAdornment: (
|
||||
<InputAdornment position="end">
|
||||
$
|
||||
</InputAdornment>
|
||||
),
|
||||
}}
|
||||
type={'text'}
|
||||
value={featureNamingPattern || ''}
|
||||
error={Boolean(errors.featureNamingPattern)}
|
||||
errorText={errors.featureNamingPattern}
|
||||
onChange={e =>
|
||||
onSetFeatureNamingPattern(e.target.value)
|
||||
}
|
||||
/>
|
||||
<StyledSubtitle>
|
||||
<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 don’t want to add
|
||||
a naming pattern.
|
||||
</p>
|
||||
</StyledPatternNamingExplanation>
|
||||
<p id="pattern-additional-description">
|
||||
The example and description will be shown to
|
||||
users when they create a new feature flag in
|
||||
this project.
|
||||
</p>
|
||||
</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-]+"
|
||||
InputProps={{
|
||||
startAdornment: (
|
||||
<InputAdornment position="start">
|
||||
^
|
||||
</InputAdornment>
|
||||
),
|
||||
endAdornment: (
|
||||
<InputAdornment position="end">
|
||||
$
|
||||
</InputAdornment>
|
||||
),
|
||||
}}
|
||||
type={'text'}
|
||||
value={featureNamingPattern || ''}
|
||||
error={Boolean(errors.featureNamingPattern)}
|
||||
errorText={errors.featureNamingPattern}
|
||||
onChange={e =>
|
||||
onSetFeatureNamingPattern(
|
||||
e.target.value
|
||||
)
|
||||
}
|
||||
/>
|
||||
<StyledSubtitle>
|
||||
<p id="pattern-additional-description">
|
||||
The example and description will be
|
||||
shown to users when they create a new
|
||||
feature flag in this project.
|
||||
</p>
|
||||
</StyledSubtitle>
|
||||
|
||||
<StyledInput
|
||||
label={'Naming Example'}
|
||||
name="feature flag naming example"
|
||||
type={'text'}
|
||||
aria-describedby="pattern-additional-description"
|
||||
value={featureNamingExample || ''}
|
||||
placeholder="dx.feature1.1-135"
|
||||
error={Boolean(errors.namingExample)}
|
||||
errorText={errors.namingExample}
|
||||
onChange={e =>
|
||||
onSetFeatureNamingExample(
|
||||
e.target.value
|
||||
)
|
||||
}
|
||||
/>
|
||||
<StyledTextField
|
||||
label={'Naming pattern description'}
|
||||
name="feature flag naming description"
|
||||
type={'text'}
|
||||
aria-describedby="pattern-additional-description"
|
||||
placeholder={`<project>.<featureName>.<ticket>
|
||||
<StyledInput
|
||||
label={'Naming Example'}
|
||||
name="feature flag naming example"
|
||||
type={'text'}
|
||||
aria-describedby="pattern-additional-description"
|
||||
value={featureNamingExample || ''}
|
||||
placeholder="dx.feature1.1-135"
|
||||
error={Boolean(errors.namingExample)}
|
||||
errorText={errors.namingExample}
|
||||
onChange={e =>
|
||||
onSetFeatureNamingExample(e.target.value)
|
||||
}
|
||||
/>
|
||||
<StyledTextField
|
||||
label={'Naming pattern description'}
|
||||
name="feature flag naming description"
|
||||
type={'text'}
|
||||
aria-describedby="pattern-additional-description"
|
||||
placeholder={`<project>.<featureName>.<ticket>
|
||||
|
||||
The flag name should contain the project name, the feature name, and the ticket number, each separated by a dot.`}
|
||||
multiline
|
||||
minRows={5}
|
||||
value={featureNamingDescription || ''}
|
||||
onChange={e =>
|
||||
onSetFeatureNamingDescription(
|
||||
e.target.value
|
||||
)
|
||||
}
|
||||
/>
|
||||
</StyledFlagNamingContainer>
|
||||
</StyledFieldset>
|
||||
}
|
||||
/>
|
||||
</StyledContainer>
|
||||
multiline
|
||||
minRows={5}
|
||||
value={featureNamingDescription || ''}
|
||||
onChange={e =>
|
||||
onSetFeatureNamingDescription(
|
||||
e.target.value
|
||||
)
|
||||
}
|
||||
/>
|
||||
</StyledFlagNamingContainer>
|
||||
</StyledFieldset>
|
||||
}
|
||||
/>
|
||||
<StyledButtonContainer>{children}</StyledButtonContainer>
|
||||
</StyledForm>
|
||||
);
|
||||
|
Loading…
Reference in New Issue
Block a user