mirror of
https://github.com/OneUptime/oneuptime
synced 2024-11-21 14:49:07 +00:00
Refactor form to allow dynamic children
This commit is contained in:
parent
02abfb53fa
commit
deed690345
8
Accounts/package-lock.json
generated
8
Accounts/package-lock.json
generated
@ -112,9 +112,7 @@
|
||||
"formik": "^2.2.9",
|
||||
"prop-types": "^15.8.1",
|
||||
"react": "^18.1.0",
|
||||
"react-dom": "^18.1.0",
|
||||
"react-router": "^6.3.0",
|
||||
"react-router-dom": "^6.3.0",
|
||||
"react-scripts": "5.0.1",
|
||||
"redux": "^4.2.0",
|
||||
"universal-cookie": "^4.0.4",
|
||||
"web-vitals": "^2.1.4",
|
||||
@ -18439,9 +18437,7 @@
|
||||
"formik": "^2.2.9",
|
||||
"prop-types": "^15.8.1",
|
||||
"react": "^18.1.0",
|
||||
"react-dom": "^18.1.0",
|
||||
"react-router": "^6.3.0",
|
||||
"react-router-dom": "^6.3.0",
|
||||
"react-scripts": "5.0.1",
|
||||
"redux": "^4.2.0",
|
||||
"universal-cookie": "^4.0.4",
|
||||
"web-vitals": "^2.1.4",
|
||||
|
@ -61,17 +61,10 @@ body {
|
||||
|
||||
.brand {
|
||||
position: absolute;
|
||||
top: 5%;
|
||||
top: -5%;
|
||||
left: 50%;
|
||||
transform: translateX(-55%);
|
||||
|
||||
@include responsive($xs) {
|
||||
top: 6%;
|
||||
}
|
||||
|
||||
@include responsive($lg) {
|
||||
top: 5%;
|
||||
}
|
||||
transform: translateX(-50%);
|
||||
margin-bottom: 20px;
|
||||
|
||||
img {
|
||||
width: 200px;
|
||||
@ -137,6 +130,19 @@ form {
|
||||
font-weight: 400;
|
||||
color: lighten($bgDark, 20%);
|
||||
margin-bottom: 5px;
|
||||
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
span:last-child {
|
||||
color: $lightBlue;
|
||||
cursor: pointer;
|
||||
transition: $transition;
|
||||
|
||||
&:hover {
|
||||
color: darken($lightBlue, 50%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
input {
|
||||
@ -248,6 +254,7 @@ form {
|
||||
|
||||
span {
|
||||
color: lighten($bgDark, 20%);
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
@ -282,7 +289,7 @@ form {
|
||||
cursor: pointer;
|
||||
|
||||
@include responsive($xs) {
|
||||
padding-bottom: 15px;
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
|
||||
a {
|
||||
|
@ -3,6 +3,7 @@ import { Link } from 'react-router-dom';
|
||||
import BasicModelForm from 'CommonUI/src/Components/Forms/BasicModelForm';
|
||||
import User from 'Common/Models/User';
|
||||
import FormValues from 'CommonUI/src/Components/Forms/Types/FormValues';
|
||||
import Route from 'Common/Types/API/Route';
|
||||
|
||||
const LoginPage: FunctionComponent = () => {
|
||||
const user: User = new User();
|
||||
@ -24,6 +25,11 @@ const LoginPage: FunctionComponent = () => {
|
||||
password: true,
|
||||
},
|
||||
title: 'Password',
|
||||
sideLink: {
|
||||
text: 'Forgot password?',
|
||||
url: new Route('/forgot-password'),
|
||||
openLinkInNewTab: true,
|
||||
},
|
||||
},
|
||||
]}
|
||||
onSubmit={(values: FormValues<User>) => {
|
||||
@ -31,7 +37,22 @@ const LoginPage: FunctionComponent = () => {
|
||||
}}
|
||||
submitButtonText={'Login'}
|
||||
title={'Sign in to your account'}
|
||||
/>
|
||||
>
|
||||
<div className="actions">
|
||||
<p>
|
||||
<Link to="/forgot-password">Forgot your password?</Link>
|
||||
</p>
|
||||
<p>
|
||||
<Link to="/login/sso">
|
||||
Use single sign-on (SSO) instead
|
||||
</Link>
|
||||
</p>
|
||||
<p>
|
||||
<span>Don't have an account? </span>{' '}
|
||||
<Link to="/register">Sign up</Link>
|
||||
</p>
|
||||
</div>
|
||||
</BasicModelForm>
|
||||
|
||||
<div className="footer">
|
||||
<p>
|
||||
|
5920
CommonUI/package-lock.json
generated
5920
CommonUI/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -18,15 +18,12 @@
|
||||
"Common": "file:../Common",
|
||||
"formik": "^2.2.9",
|
||||
"prop-types": "^15.8.1",
|
||||
"react": "^18.1.0",
|
||||
"react-scripts": "5.0.1",
|
||||
"redux": "^4.2.0",
|
||||
"universal-cookie": "^4.0.4",
|
||||
"web-vitals": "^2.1.4",
|
||||
"yup": "^0.32.11",
|
||||
"react": "^18.1.0",
|
||||
"react-dom": "^18.1.0",
|
||||
"react-router": "^6.3.0",
|
||||
"react-router-dom": "^6.3.0",
|
||||
"react-scripts": "5.0.1"
|
||||
"yup": "^0.32.11"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^17.0.23",
|
||||
|
@ -7,7 +7,6 @@ import Fields from './Types/Fields';
|
||||
import DataField from './Types/Field';
|
||||
import ButtonTypes from '../Basic/Button/ButtonTypes';
|
||||
import BadDataException from 'Common/Types/Exception/BadDataException';
|
||||
|
||||
export interface ComponentProps<T extends Object> {
|
||||
id: string;
|
||||
initialValues: FormValues<T>;
|
||||
@ -18,19 +17,36 @@ export interface ComponentProps<T extends Object> {
|
||||
model: T;
|
||||
submitButtonText?: string;
|
||||
title?: string;
|
||||
children: ReactElement;
|
||||
}
|
||||
|
||||
const BasicForm = <T extends Object>(
|
||||
props: ComponentProps<T>
|
||||
): ReactElement => {
|
||||
const getFormField = (field: DataField<T>, index: number): ReactElement => {
|
||||
let fieldType = 'text';
|
||||
const fieldType = 'text';
|
||||
if (Object.keys(field.field).length === 0) {
|
||||
throw new BadDataException('Object cannot be without Field');
|
||||
}
|
||||
return (
|
||||
<div key={index}>
|
||||
<label>{field.title}</label>
|
||||
<label>
|
||||
<span>{field.title}</span>
|
||||
{
|
||||
<span>
|
||||
<a
|
||||
href={field.sideLink?.url.toString()}
|
||||
target={`${
|
||||
field.sideLink?.openLinkInNewTab
|
||||
? '_blank'
|
||||
: '_self'
|
||||
}`}
|
||||
>
|
||||
{field.sideLink?.text}
|
||||
</a>
|
||||
</span>
|
||||
}
|
||||
</label>
|
||||
<p>{field.description}</p>
|
||||
<Field
|
||||
placeholder={field.placeholder}
|
||||
@ -60,35 +76,24 @@ const BasicForm = <T extends Object>(
|
||||
props.onSubmit(values);
|
||||
}}
|
||||
>
|
||||
{({ isSubmitting }) => (
|
||||
<Form>
|
||||
<h1>{props.title}</h1>
|
||||
{props.fields &&
|
||||
props.fields.map((field: DataField<T>, i) => {
|
||||
return getFormField(field, i);
|
||||
})}
|
||||
<div className="remember">
|
||||
<input type="checkbox" id="remember" />
|
||||
<label htmlFor="remember">
|
||||
Stay signed in for a week
|
||||
</label>
|
||||
</div>
|
||||
<Button
|
||||
title={props.submitButtonText || 'Submit'}
|
||||
disabled={isSubmitting}
|
||||
type={ButtonTypes.Submit}
|
||||
id={`${props.id}-submit-button`}
|
||||
/>
|
||||
<div className="actions">
|
||||
<p>Forgot your password?</p>
|
||||
<p>Use single sign-on (SSO) instead</p>
|
||||
<p>
|
||||
<span>Don't have an account? </span> Sign
|
||||
up
|
||||
</p>
|
||||
</div>
|
||||
</Form>
|
||||
)}
|
||||
{({ isSubmitting }) => {
|
||||
return (
|
||||
<Form>
|
||||
<h1>{props.title}</h1>
|
||||
{props.fields &&
|
||||
props.fields.map((field: DataField<T>, i) => {
|
||||
return getFormField(field, i);
|
||||
})}
|
||||
<Button
|
||||
title={props.submitButtonText || 'Submit'}
|
||||
disabled={isSubmitting}
|
||||
type={ButtonTypes.Submit}
|
||||
id={`${props.id}-submit-button`}
|
||||
/>
|
||||
{props.children}
|
||||
</Form>
|
||||
);
|
||||
}}
|
||||
</Formik>
|
||||
</div>
|
||||
);
|
||||
|
@ -13,6 +13,7 @@ export interface ComponentProps<T extends BaseModel> {
|
||||
fields: Fields<T>;
|
||||
submitButtonText?: string;
|
||||
title?: string;
|
||||
children: ReactElement;
|
||||
}
|
||||
|
||||
const BasicModelForm = <TBaseModel extends BaseModel>(
|
||||
@ -58,7 +59,9 @@ const BasicModelForm = <TBaseModel extends BaseModel>(
|
||||
model={props.model}
|
||||
submitButtonText={props.submitButtonText || 'Save'}
|
||||
title={props.title || ''}
|
||||
/>
|
||||
>
|
||||
{props.children}
|
||||
</BasicForm>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
import Route from 'Common/Types/API/Route';
|
||||
import URL from 'Common/Types/API/URL';
|
||||
import SelectFormFields from './SelectFormField';
|
||||
|
||||
export default interface Field<TEntity> {
|
||||
@ -5,4 +7,9 @@ export default interface Field<TEntity> {
|
||||
description?: string;
|
||||
field: SelectFormFields<TEntity>;
|
||||
placeholder?: string;
|
||||
sideLink?: {
|
||||
text: string;
|
||||
url: Route | URL;
|
||||
openLinkInNewTab?: boolean;
|
||||
};
|
||||
}
|
||||
|
@ -1,4 +1,6 @@
|
||||
import Hostname from 'Common/Types/API/Hostname';
|
||||
import Route from 'Common/Types/API/Route';
|
||||
import URL from 'Common/Types/API/URL';
|
||||
import Email from 'Common/Types/Email';
|
||||
import Name from 'Common/Types/Name';
|
||||
import ObjectID from 'Common/Types/ObjectID';
|
||||
@ -10,6 +12,8 @@ type FormFieldType =
|
||||
| ObjectID
|
||||
| Hostname
|
||||
| Email
|
||||
| Name;
|
||||
| Name
|
||||
| Route
|
||||
| URL;
|
||||
|
||||
export default FormFieldType;
|
||||
|
@ -3,6 +3,7 @@ enum FormType {
|
||||
Name,
|
||||
Hostname,
|
||||
URL,
|
||||
Route,
|
||||
String,
|
||||
Number,
|
||||
Password,
|
||||
|
Loading…
Reference in New Issue
Block a user