mirror of
https://github.com/Unleash/unleash.git
synced 2025-01-25 00:07:47 +01:00
Feat/change form order (#784)
* 4.9.0-beta.1 * 4.9.0-beta.2 * fix: mobile guidance WIP * fix: add autofocus * feat: update forms * refactor: mobile guidance * fix: add relative as common class * fix: add max height to codebox
This commit is contained in:
parent
e7b2ab3a68
commit
228a72d637
3
frontend/src/assets/img/mobile-guidance-bg.svg
Normal file
3
frontend/src/assets/img/mobile-guidance-bg.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg width="48" height="50" viewBox="0 0 48 50" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M0.5 0.000193412C11 2.00019 17 9 18 18C19 27 23.5 31.5 30.5 34C37.5 36.5 47.34 41.4 48 49.5L48 12.0012C48 5.37332 42.6309 0.000381623 36.003 0.000366343C24.1359 0.000338986 8.66406 -0.000263908 0.5 0.000193412Z" fill="#6C65E5"/>
|
||||
</svg>
|
After Width: | Height: | Size: 341 B |
@ -19,6 +19,9 @@ export const useCommonStyles = makeStyles(theme => ({
|
||||
marginLeft: '0.8rem !important',
|
||||
},
|
||||
},
|
||||
relative: {
|
||||
position: 'relative',
|
||||
},
|
||||
divider: {
|
||||
margin: '1rem 0',
|
||||
backgroundColor: theme.palette.division.main,
|
||||
|
@ -34,13 +34,6 @@ export const useStyles = makeStyles(theme => ({
|
||||
inputDescription: {
|
||||
marginBottom: '0.5rem',
|
||||
},
|
||||
formHeader: {
|
||||
fontWeight: 'normal',
|
||||
marginTop: '0',
|
||||
},
|
||||
header: {
|
||||
fontWeight: 'normal',
|
||||
},
|
||||
permissionErrorContainer: {
|
||||
position: 'relative',
|
||||
},
|
||||
|
@ -65,8 +65,6 @@ const ApiTokenForm: React.FC<IApiTokenFormProps> = ({
|
||||
|
||||
return (
|
||||
<form onSubmit={handleSubmit} className={styles.form}>
|
||||
<h3 className={styles.formHeader}>Token information</h3>
|
||||
|
||||
<div className={styles.container}>
|
||||
<p className={styles.inputDescription}>
|
||||
Who are you generating the token for?
|
||||
|
@ -84,7 +84,7 @@ const EnvironmentPermissionAccordion = ({
|
||||
color="primary"
|
||||
/>
|
||||
}
|
||||
label={permission.displayName || 'Dummy permission'}
|
||||
label={permission.displayName}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@ -128,8 +128,6 @@ const ProjectRoleForm: React.FC<IProjectRoleForm> = ({
|
||||
|
||||
return (
|
||||
<form onSubmit={handleSubmit}>
|
||||
<h3 className={styles.formHeader}>Role information</h3>
|
||||
|
||||
<div className={styles.container}>
|
||||
<p className={styles.inputDescription}>
|
||||
What is your role name?
|
||||
|
@ -27,13 +27,6 @@ export const useStyles = makeStyles(theme => ({
|
||||
inputDescription: {
|
||||
marginBottom: '0.5rem',
|
||||
},
|
||||
formHeader: {
|
||||
fontWeight: 'normal',
|
||||
marginTop: '0',
|
||||
},
|
||||
header: {
|
||||
fontWeight: 'normal',
|
||||
},
|
||||
permissionErrorContainer: {
|
||||
position: 'relative',
|
||||
},
|
||||
|
@ -63,8 +63,6 @@ const UserForm: React.FC<IUserForm> = ({
|
||||
|
||||
return (
|
||||
<form onSubmit={handleSubmit} className={styles.form}>
|
||||
<h3 className={styles.formHeader}>User information</h3>
|
||||
|
||||
<div className={styles.container}>
|
||||
<p className={styles.inputDescription}>
|
||||
Who is the new Unleash user?
|
||||
|
@ -6,6 +6,8 @@ export const useStyles = makeStyles(theme => ({
|
||||
padding: '1rem',
|
||||
borderRadius: '3px',
|
||||
position: 'relative',
|
||||
maxHeight: '500px',
|
||||
overflow: 'auto',
|
||||
},
|
||||
code: {
|
||||
margin: 0,
|
||||
|
@ -122,6 +122,7 @@ export const ConstraintAccordionEditHeader = ({
|
||||
id="context-field-select"
|
||||
name="contextName"
|
||||
label="Context Field"
|
||||
autoFocus
|
||||
options={constraintNameOptions}
|
||||
value={localConstraint.contextName || ''}
|
||||
onChange={(
|
||||
|
@ -28,8 +28,7 @@ export const useStyles = makeStyles(theme => ({
|
||||
},
|
||||
},
|
||||
title: {
|
||||
color: '#fff',
|
||||
marginBottom: '1rem',
|
||||
marginBottom: '1.5rem',
|
||||
fontWeight: 'normal',
|
||||
},
|
||||
subtitle: {
|
||||
@ -70,4 +69,25 @@ export const useStyles = makeStyles(theme => ({
|
||||
},
|
||||
},
|
||||
icon: { fill: '#fff' },
|
||||
mobileGuidanceBgContainer: {
|
||||
position: 'absolute',
|
||||
right: '-3px',
|
||||
top: '-3px',
|
||||
backgroundColor: theme.palette.primary.light,
|
||||
},
|
||||
mobileGuidanceBackground: {
|
||||
position: 'absolute',
|
||||
right: '-3px',
|
||||
top: '-3px',
|
||||
width: '75px',
|
||||
height: '75px',
|
||||
},
|
||||
mobileGuidanceButton: {
|
||||
position: 'absolute',
|
||||
zIndex: 400,
|
||||
right: 0,
|
||||
},
|
||||
infoIcon: {
|
||||
fill: '#fff',
|
||||
},
|
||||
}));
|
||||
|
@ -1,14 +1,16 @@
|
||||
import { useStyles } from './FormTemplate.styles';
|
||||
import MenuBookIcon from '@material-ui/icons/MenuBook';
|
||||
import Codebox from '../Codebox/Codebox';
|
||||
import { IconButton, useMediaQuery } from '@material-ui/core';
|
||||
import { FileCopy } from '@material-ui/icons';
|
||||
import { Collapse, IconButton, useMediaQuery } from '@material-ui/core';
|
||||
import { FileCopy, Info } from '@material-ui/icons';
|
||||
import ConditionallyRender from '../ConditionallyRender';
|
||||
import Loader from '../Loader/Loader';
|
||||
import copy from 'copy-to-clipboard';
|
||||
import useToast from '../../../hooks/useToast';
|
||||
import React from 'react';
|
||||
import React, { useState } from 'react';
|
||||
import classNames from 'classnames';
|
||||
import { ReactComponent as MobileGuidanceBG } from '../../../assets/img/mobile-guidance-bg.svg';
|
||||
import { useCommonStyles } from 'common.styles';
|
||||
|
||||
interface ICreateProps {
|
||||
title: string;
|
||||
@ -19,6 +21,11 @@ interface ICreateProps {
|
||||
formatApiCode: () => string;
|
||||
}
|
||||
|
||||
// Components in this file:
|
||||
// FormTemplate
|
||||
// MobileGuidance
|
||||
// Guidance
|
||||
|
||||
const FormTemplate: React.FC<ICreateProps> = ({
|
||||
title,
|
||||
description,
|
||||
@ -30,6 +37,7 @@ const FormTemplate: React.FC<ICreateProps> = ({
|
||||
}) => {
|
||||
const { setToastData } = useToast();
|
||||
const styles = useStyles();
|
||||
const commonStyles = useCommonStyles();
|
||||
const smallScreen = useMediaQuery(`(max-width:${900}px)`);
|
||||
|
||||
const copyCommand = () => {
|
||||
@ -56,45 +64,114 @@ const FormTemplate: React.FC<ICreateProps> = ({
|
||||
<section
|
||||
className={classNames(styles.container, modal && styles.modal)}
|
||||
>
|
||||
<aside className={styles.sidebar}>
|
||||
<h2 className={styles.title}>{title}</h2>
|
||||
<p className={styles.description}>{description}</p>
|
||||
|
||||
<div className={styles.linkContainer}>
|
||||
<MenuBookIcon className={styles.linkIcon} />
|
||||
<a
|
||||
className={styles.documentationLink}
|
||||
href={documentationLink}
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Learn more
|
||||
</a>
|
||||
</div>
|
||||
<ConditionallyRender
|
||||
condition={!smallScreen}
|
||||
show={
|
||||
<>
|
||||
<h3 className={styles.subtitle}>
|
||||
API Command{' '}
|
||||
<IconButton onClick={copyCommand}>
|
||||
<FileCopy className={styles.icon} />
|
||||
</IconButton>
|
||||
</h3>
|
||||
<Codebox text={formatApiCode()} />
|
||||
</>
|
||||
}
|
||||
/>
|
||||
</aside>
|
||||
<ConditionallyRender
|
||||
condition={smallScreen}
|
||||
show={
|
||||
<div className={commonStyles.relative}>
|
||||
<MobileGuidance
|
||||
description={description}
|
||||
documentationLink={documentationLink}
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
<div className={styles.formContent}>
|
||||
<ConditionallyRender
|
||||
condition={loading || false}
|
||||
show={<Loader />}
|
||||
elseShow={<>{children}</>}
|
||||
elseShow={
|
||||
<>
|
||||
<h2 className={styles.title}>{title}</h2>
|
||||
{children}
|
||||
</>
|
||||
}
|
||||
/>{' '}
|
||||
</div>
|
||||
<ConditionallyRender
|
||||
condition={!smallScreen}
|
||||
show={
|
||||
<Guidance
|
||||
description={description}
|
||||
documentationLink={documentationLink}
|
||||
>
|
||||
<h3 className={styles.subtitle}>
|
||||
API Command{' '}
|
||||
<IconButton onClick={copyCommand}>
|
||||
<FileCopy className={styles.icon} />
|
||||
</IconButton>
|
||||
</h3>
|
||||
<Codebox text={formatApiCode()} />
|
||||
</Guidance>
|
||||
}
|
||||
/>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
interface IMobileGuidance {
|
||||
description: string;
|
||||
documentationLink: string;
|
||||
}
|
||||
|
||||
const MobileGuidance = ({
|
||||
description,
|
||||
documentationLink,
|
||||
}: IMobileGuidance) => {
|
||||
const [open, setOpen] = useState(false);
|
||||
const styles = useStyles();
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className={styles.mobileGuidanceBgContainer}>
|
||||
<MobileGuidanceBG className={styles.mobileGuidanceBackground} />
|
||||
</div>
|
||||
<IconButton
|
||||
className={styles.mobileGuidanceButton}
|
||||
onClick={() => setOpen(prev => !prev)}
|
||||
>
|
||||
<Info className={styles.infoIcon} />
|
||||
</IconButton>
|
||||
<Collapse in={open} timeout={500}>
|
||||
<Guidance
|
||||
description={description}
|
||||
documentationLink={documentationLink}
|
||||
/>
|
||||
</Collapse>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
interface IGuidanceProps {
|
||||
description: string;
|
||||
documentationLink: string;
|
||||
}
|
||||
|
||||
const Guidance: React.FC<IGuidanceProps> = ({
|
||||
description,
|
||||
children,
|
||||
documentationLink,
|
||||
}) => {
|
||||
const styles = useStyles();
|
||||
|
||||
return (
|
||||
<aside className={styles.sidebar}>
|
||||
<p className={styles.description}>{description}</p>
|
||||
|
||||
<div className={styles.linkContainer}>
|
||||
<MenuBookIcon className={styles.linkIcon} />
|
||||
<a
|
||||
className={styles.documentationLink}
|
||||
href={documentationLink}
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Learn more
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{children}
|
||||
</aside>
|
||||
);
|
||||
};
|
||||
|
||||
export default FormTemplate;
|
||||
|
@ -14,6 +14,7 @@ export interface ISelectMenuProps {
|
||||
id: string;
|
||||
value?: string;
|
||||
label?: string;
|
||||
autoFocus?: boolean;
|
||||
options: ISelectOption[];
|
||||
style?: object;
|
||||
onChange?: OnGeneralSelectChange;
|
||||
@ -38,6 +39,7 @@ const GeneralSelect: React.FC<ISelectMenuProps> = ({
|
||||
defaultValue,
|
||||
id,
|
||||
disabled = false,
|
||||
autoFocus,
|
||||
className,
|
||||
classes,
|
||||
fullWidth,
|
||||
@ -70,6 +72,7 @@ const GeneralSelect: React.FC<ISelectMenuProps> = ({
|
||||
onChange={onChange}
|
||||
className={className}
|
||||
label={label}
|
||||
autoFocus={autoFocus}
|
||||
id={id}
|
||||
value={value}
|
||||
IconComponent={KeyboardArrowDownOutlined}
|
||||
|
@ -5,6 +5,7 @@ export const useStyles = makeStyles(() => ({
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
height: '100vh',
|
||||
maxWidth: 1300,
|
||||
overflow: 'auto',
|
||||
|
@ -37,7 +37,7 @@ const StringTruncator = ({
|
||||
</span>
|
||||
</Tooltip>
|
||||
}
|
||||
elseShow={<>{text}</>}
|
||||
elseShow={<span className={className}>{text}</span>}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
@ -43,13 +43,6 @@ export const useStyles = makeStyles(theme => ({
|
||||
inputDescription: {
|
||||
marginBottom: '0.5rem',
|
||||
},
|
||||
formHeader: {
|
||||
fontWeight: 'normal',
|
||||
marginTop: '0',
|
||||
},
|
||||
header: {
|
||||
fontWeight: 'normal',
|
||||
},
|
||||
permissionErrorContainer: {
|
||||
position: 'relative',
|
||||
},
|
||||
|
@ -93,8 +93,6 @@ export const ContextForm: React.FC<IContextForm> = ({
|
||||
|
||||
return (
|
||||
<form onSubmit={submit} className={styles.form}>
|
||||
<h3 className={styles.formHeader}>Context information</h3>
|
||||
|
||||
<div className={styles.container}>
|
||||
<p className={styles.inputDescription}>
|
||||
What is your context name?
|
||||
|
@ -14,6 +14,7 @@ export const useStyles = makeStyles(theme => ({
|
||||
display: 'grid',
|
||||
gridTemplateColumns: 'auto 1fr',
|
||||
gridGap: '.5rem',
|
||||
fontSize: theme.fontSizes.subHeader,
|
||||
},
|
||||
icon: {
|
||||
color: theme.palette.primary.main,
|
||||
|
@ -27,13 +27,6 @@ export const useStyles = makeStyles(theme => ({
|
||||
inputDescription: {
|
||||
marginBottom: '0.5rem',
|
||||
},
|
||||
formHeader: {
|
||||
fontWeight: 'normal',
|
||||
marginTop: '0',
|
||||
},
|
||||
header: {
|
||||
fontWeight: 'normal',
|
||||
},
|
||||
permissionErrorContainer: {
|
||||
position: 'relative',
|
||||
},
|
@ -1,6 +1,6 @@
|
||||
import Input from '../../../common/Input/Input';
|
||||
import { TextField, Button } from '@material-ui/core';
|
||||
import { useStyles } from './ProjectForm.style';
|
||||
import { useStyles } from './ProjectForm.styles';
|
||||
import React from 'react';
|
||||
import { trim } from '../../../common/util';
|
||||
|
||||
@ -38,8 +38,6 @@ const ProjectForm: React.FC<IProjectForm> = ({
|
||||
|
||||
return (
|
||||
<form onSubmit={handleSubmit} className={styles.form}>
|
||||
<h3 className={styles.formHeader}>Project Information</h3>
|
||||
|
||||
<div className={styles.container}>
|
||||
<p className={styles.inputDescription}>
|
||||
What is your project Id?
|
||||
|
@ -9,6 +9,7 @@ export const useStyles = makeStyles(theme => ({
|
||||
flexDirection: 'column',
|
||||
height: '100%',
|
||||
},
|
||||
|
||||
input: { width: '100%', marginBottom: '1rem' },
|
||||
selectInput: {
|
||||
marginBottom: '1rem',
|
||||
@ -43,13 +44,6 @@ export const useStyles = makeStyles(theme => ({
|
||||
top: '-13px',
|
||||
position: 'relative',
|
||||
},
|
||||
formHeader: {
|
||||
fontWeight: 'normal',
|
||||
marginTop: '0',
|
||||
},
|
||||
header: {
|
||||
fontWeight: 'normal',
|
||||
},
|
||||
errorMessage: {
|
||||
fontSize: theme.fontSizes.smallBody,
|
||||
color: theme.palette.error.main,
|
||||
|
@ -52,8 +52,6 @@ export const StrategyForm: React.FC<IStrategyFormProps> = ({
|
||||
|
||||
return (
|
||||
<form onSubmit={handleSubmit} className={styles.form}>
|
||||
<h3 className={styles.formHeader}>Strategy type information</h3>
|
||||
|
||||
<div className={styles.container}>
|
||||
<p className={styles.inputDescription}>
|
||||
What would you like to call your strategy?
|
||||
|
@ -15,7 +15,7 @@ export const StrategyParameters = ({
|
||||
setParams,
|
||||
errors,
|
||||
}: IStrategyParametersProps) => (
|
||||
<div>
|
||||
<div style={{ marginTop: '0.5rem' }}>
|
||||
{input.map((item, index) => (
|
||||
<StrategyParameter
|
||||
params={input}
|
||||
|
@ -27,13 +27,6 @@ export const useStyles = makeStyles(theme => ({
|
||||
inputDescription: {
|
||||
marginBottom: '0.5rem',
|
||||
},
|
||||
formHeader: {
|
||||
fontWeight: 'normal',
|
||||
marginTop: '0',
|
||||
},
|
||||
header: {
|
||||
fontWeight: 'normal',
|
||||
},
|
||||
permissionErrorContainer: {
|
||||
position: 'relative',
|
||||
},
|
||||
|
@ -36,8 +36,6 @@ const TagTypeForm: React.FC<ITagTypeForm> = ({
|
||||
|
||||
return (
|
||||
<form onSubmit={handleSubmit} className={styles.form}>
|
||||
<h3 className={styles.formHeader}>Tag information</h3>
|
||||
|
||||
<div className={styles.container}>
|
||||
<p className={styles.inputDescription}>
|
||||
What is your tag name?
|
||||
|
Loading…
Reference in New Issue
Block a user