fix basic form.

This commit is contained in:
Simon Larsen
2022-05-14 14:50:58 +01:00
parent 31b6ed1609
commit dc0f271f88
72 changed files with 1172 additions and 557 deletions

6
Accounts/.babelrc Normal file
View File

@@ -0,0 +1,6 @@
{
"presets": ["es2015", "stage-0", "react"],
"plugins": [
["transform-decorators-legacy"]
]
}

File diff suppressed because it is too large Load Diff

View File

@@ -3,6 +3,8 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"@babel/plugin-proposal-class-properties": "^7.16.7",
"@babel/plugin-proposal-decorators": "^7.17.9",
"@testing-library/jest-dom": "^5.16.4",
"@testing-library/react": "^13.2.0",
"@testing-library/user-event": "^13.5.0",
@@ -10,13 +12,14 @@
"@types/node": "^16.11.35",
"@types/react": "^18.0.9",
"@types/react-dom": "^18.0.4",
"react": "^18.1.0",
"react-dom": "^18.1.0",
"react-scripts": "5.0.1",
"typescript": "^4.6.4",
"Common": "file:../Common",
"CommonServer": "file:../CommonServer",
"CommonUI": "file:../CommonUI"
"CommonUI": "file:../CommonUI",
"react": "^18.1.0",
"react-dom": "^18.1.0",
"react-router-dom": "^6.3.0",
"react-scripts": "5.0.1",
"typescript": "^4.6.4"
},
"scripts": {
"dev": "PORT=3003 react-scripts start",
@@ -46,5 +49,8 @@
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"babel-plugin-transform-decorators-legacy": "^1.3.5"
}
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,24 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg">
<metadata>Copyright (C) 2017 by original authors @ fontello.com</metadata>
<defs>
<font id="rw-widgets" horiz-adv-x="1000" >
<font-face font-family="rw-widgets" font-weight="400" font-stretch="normal" units-per-em="1000" ascent="850" descent="-150" />
<missing-glyph horiz-adv-x="1000" />
<glyph glyph-name="up-dir" unicode="&#xe800;" d="M571 171q0-14-10-25t-25-10h-500q-15 0-25 10t-11 25 11 26l250 250q10 10 25 10t25-10l250-250q10-11 10-26z" horiz-adv-x="571.4" />
<glyph glyph-name="search" unicode="&#xe801;" d="M643 386q0 103-73 176t-177 74-177-74-73-176 73-177 177-73 177 73 73 177z m286-465q0-29-22-50t-50-21q-30 0-50 21l-191 191q-100-69-223-69-80 0-153 31t-125 84-84 125-31 153 31 152 84 126 125 84 153 31 153-31 125-84 84-126 31-152q0-123-69-223l191-191q21-21 21-51z" horiz-adv-x="928.6" />
<glyph glyph-name="down-dir" unicode="&#xe803;" d="M571 457q0-14-10-25l-250-250q-11-11-25-11t-25 11l-250 250q-11 11-11 25t11 25 25 11h500q14 0 25-11t10-25z" horiz-adv-x="571.4" />
<glyph glyph-name="calendar" unicode="&#xe804;" d="M71-79h161v161h-161v-161z m197 0h178v161h-178v-161z m-197 197h161v178h-161v-178z m197 0h178v178h-178v-178z m-197 214h161v161h-161v-161z m411-411h179v161h-179v-161z m-214 411h178v161h-178v-161z m428-411h161v161h-161v-161z m-214 197h179v178h-179v-178z m-196 482v161q0 7-6 12t-12 6h-36q-7 0-12-6t-6-12v-161q0-7 6-13t12-5h36q7 0 12 5t6 13z m410-482h161v178h-161v-178z m-214 214h179v161h-179v-161z m214 0h161v161h-161v-161z m18 268v161q0 7-5 12t-13 6h-35q-7 0-13-6t-5-12v-161q0-7 5-13t13-5h35q8 0 13 5t5 13z m215 36v-715q0-29-22-50t-50-21h-786q-29 0-50 21t-21 50v715q0 29 21 50t50 21h72v54q0 37 26 63t63 26h36q37 0 63-26t26-63v-54h214v54q0 37 27 63t63 26h35q37 0 64-26t26-63v-54h71q29 0 50-21t22-50z" horiz-adv-x="928.6" />
<glyph glyph-name="clock" unicode="&#xe805;" d="M500 546v-250q0-7-5-12t-13-5h-178q-8 0-13 5t-5 12v36q0 8 5 13t13 5h125v196q0 8 5 13t12 5h36q8 0 13-5t5-13z m232-196q0 83-41 152t-110 111-152 41-153-41-110-111-41-152 41-152 110-111 153-41 152 41 110 111 41 152z m125 0q0-117-57-215t-156-156-215-58-216 58-155 156-58 215 58 215 155 156 216 58 215-58 156-156 57-215z" horiz-adv-x="857.1" />
<glyph glyph-name="angle-left" unicode="&#xf104;" d="M350 546q0-7-6-12l-219-220 219-219q6-6 6-13t-6-13l-28-28q-5-5-12-5t-13 5l-260 261q-6 5-6 12t6 13l260 260q5 6 13 6t12-6l28-28q6-5 6-13z" horiz-adv-x="357.1" />
<glyph glyph-name="angle-right" unicode="&#xf105;" d="M332 314q0-7-5-12l-261-261q-5-5-12-5t-13 5l-28 28q-6 6-6 13t6 13l219 219-219 220q-6 5-6 12t6 13l28 28q5 6 13 6t12-6l261-260q5-5 5-13z" horiz-adv-x="357.1" />
</font>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 764 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 870 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 902 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 924 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<browserconfig>
<msapplication>
<tile>
<square150x150logo src="/mstile-150x150.png"/>
<TileColor>#121212</TileColor>
</tile>
</msapplication>
</browserconfig>

Binary file not shown.

After

Width:  |  Height:  |  Size: 804 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -0,0 +1,9 @@
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="194x194" href="/favicon-194x194.png">
<link rel="icon" type="image/png" sizes="192x192" href="/android-chrome-192x192.png">
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
<link rel="manifest" href="/site.webmanifest">
<link rel="mask-icon" href="/safari-pinned-tab.svg" color="#5bbad5">
<meta name="msapplication-TileColor" content="#121212">
<meta name="theme-color" content="#121212">

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -0,0 +1,31 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="700.000000pt" height="700.000000pt" viewBox="0 0 700.000000 700.000000"
preserveAspectRatio="xMidYMid meet">
<metadata>
Created by potrace 1.14, written by Peter Selinger 2001-2017
</metadata>
<g transform="translate(0.000000,700.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<path d="M864 4667 c-7 -19 2 -1540 9 -1567 4 -13 9 -42 12 -63 14 -91 70
-225 138 -331 28 -44 106 -121 162 -162 103 -73 173 -100 368 -144 72 -16 315
-4 402 19 268 72 459 246 551 498 31 85 41 129 59 253 5 34 10 1314 6 1482
l-1 27 -210 -1 c-208 0 -210 0 -211 -22 0 -11 -2 -340 -4 -731 -1 -390 -5
-728 -9 -750 -29 -182 -125 -315 -258 -361 -74 -26 -252 -26 -325 -1 -135 47
-231 205 -249 409 -4 45 -8 391 -8 768 l-1 685 -213 2 c-154 1 -215 -2 -218
-10z"/>
<path d="M3663 4169 c-125 -14 -257 -70 -354 -149 l-46 -38 -38 40 c-68 69
-161 105 -294 114 l-87 6 -42 -154 c-23 -84 -45 -167 -48 -184 l-6 -31 50 5
c62 5 118 -12 134 -41 9 -17 13 -257 14 -992 1 -533 2 -972 3 -975 0 -3 94 -5
208 -5 l208 1 0 359 c1 198 4 361 8 362 4 2 35 -10 69 -26 114 -51 159 -62
283 -66 169 -7 323 46 454 155 310 258 414 756 241 1161 -131 309 -435 493
-757 458z m169 -412 c75 -34 140 -102 182 -191 46 -97 60 -163 59 -286 0 -251
-105 -431 -280 -483 -57 -17 -157 -16 -221 2 -44 12 -139 66 -181 102 l-25 20
0 357 -1 357 30 28 c50 47 114 88 168 107 75 27 193 21 269 -13z"/>
<path d="M4932 4013 c-18 -6 -35 -13 -36 -15 -24 -27 -26 -83 -26 -688 l0
-642 29 -29 29 -29 650 0 649 0 26 25 c13 14 26 36 28 48 3 12 4 303 4 647 -1
587 -2 627 -19 653 -10 15 -30 30 -43 33 -49 13 -1255 10 -1291 -3z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@@ -0,0 +1,56 @@
{
"name": "OneUptime Account",
"short_name": "OneUptime",
"icons": [
{
"src": "/accounts/assets/img/favicons/android-chrome-36x36.png",
"sizes": "36x36",
"type": "image/png"
},
{
"src": "/accounts/assets/img/favicons/android-chrome-48x48.png",
"sizes": "48x48",
"type": "image/png"
},
{
"src": "/accounts/assets/img/favicons/android-chrome-72x72.png",
"sizes": "72x72",
"type": "image/png"
},
{
"src": "/accounts/assets/img/favicons/android-chrome-96x96.png",
"sizes": "96x96",
"type": "image/png"
},
{
"src": "/accounts/assets/img/favicons/android-chrome-144x144.png",
"sizes": "144x144",
"type": "image/png"
},
{
"src": "/accounts/assets/img/favicons/android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/accounts/assets/img/favicons/android-chrome-256x256.png",
"sizes": "256x256",
"type": "image/png"
},
{
"src": "/accounts/assets/img/favicons/android-chrome-384x384.png",
"sizes": "384x384",
"type": "image/png"
},
{
"src": "/accounts/assets/img/favicons/android-chrome-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"start_url": ".",
"theme_color": "#121212",
"background_color": "#121212",
"display": "standalone"
}

View File

@@ -0,0 +1,11 @@
$(document).ready(function() {
setTimeout(()=>{
$('div.bar').tipsy({
gravity: 'se',
html: true,
offset: 1
});
},1000);
});

View File

@@ -9,7 +9,52 @@
name="description"
content="Web site created using create-react-app"
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta charSet='utf-8' />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="theme-color" content="#000000">
<meta name="slack-app-id" content="ACVBMTPJQ">
<meta name="description" content="This is the login page for OneUptime Dashboard">
<link rel="manifest" href="/accounts/manifest.json">
<link rel="apple-touch-icon" sizes="180x180" href="/accounts/assests/img/favicons/apple-touch-icon.png">
<link rel="shortcut icon" href="/accounts/favicon.ico">
<link rel="icon" type="image/png" sizes="32x32" href="/accounts/assests/img/favicons/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="194x194" href="/accounts/assests/img/favicons/favicon-194x194.png">
<link rel="icon" type="image/png" sizes="192x192" href="/accounts/assests/img/favicons/android-chrome-192x192.png">
<link rel="icon" type="image/png" sizes="16x16" href="/accounts/assests/img/favicons/favicon-16x16.png">
<link rel="mask-icon" href="/accounts/assests/img/favicons/safari-pinned-tab.svg" color="#5bbad5">
<meta name="msapplication-TileColor" content="#121212">
<meta name="msapplication-TileImage" content="/accounts/assests/img/favicons/mstile-144x144.png">
<meta name="theme-color" content="#121212">
<title>OneUptime Accounts</title>
<link rel="stylesheet" href="/accounts/assets/css/dashboard.css" media="none" onload="if(media!='all')media='all'">
<link rel="stylesheet" href="/accounts/assets/css/dashboard.css">
<link rel="stylesheet" href="/accounts/assets/css/newdashboard.css" media="none" onload="if(media!='all')media='all'">
<link rel="stylesheet" href="/accounts/assets/css/newdashboard.css">
<link rel="stylesheet" href="/accounts/assets/css/sail.css" media="none" onload="if(media!='all')media='all'">
<link rel="stylesheet" href="/accounts/assets/css/sail.css">
<link rel="stylesheet" href="/accounts/assets/css/loader.css" media="none" onload="if(media!='all')media='all'">
<link rel="stylesheet" href="/accounts/assets/css/loader.css">
<link rel="stylesheet" href="/accounts/assets/css/blockchart.css" media="none" onload="if(media!='all')media='all'">
<link rel="stylesheet" href="/accounts/assets/css/blockchart.css">
<link rel="stylesheet" href="/accounts/assets/css/Selector.css" media="none" onload="if(media!='all')media='all'">
<link rel="stylesheet" href="/accounts/assets/css/Selector.css">
<link rel="stylesheet" href="/accounts/assets/css/tutorial.css" media="none" onload="if(media!='all')media='all'">
<link rel="stylesheet" href="/accounts/assets/css/tutorial.css">
<link rel="stylesheet" href="/accounts/assets/css/reactwidgets.css" media="none" onload="if(media!='all')media='all'">
<link rel="stylesheet" href="/accounts/assets/css/reactwidgets.css">
<!-- Preload light, regular, medium and bold, which are fonts that are used on home -->
<link rel="preload" href="/accounts/assets/fonts/camphor/font1.woff2" as="font" type="font/woff2" crossorigin="">
<link rel="preload" href="/accounts/assets/fonts/camphor/font2.woff2" as="font" type="font/woff2" crossorigin="">
<link rel="preload" href="/accounts/assets/fonts/camphor/font3.woff2" as="font" type="font/woff2" crossorigin="">
<link rel="preload" href="/accounts/assets/fonts/camphor/font4.woff2" as="font" type="font/woff2" crossorigin="">
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
@@ -24,7 +69,7 @@
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
<title>OneUptime | Account</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>

View File

@@ -1,22 +1,24 @@
import React from 'react';
import './App.css';
import {
BrowserRouter as Router,
Routes,
Route,
} from "react-router-dom";
import LoginPage from './Pages/Login';
function App() {
return (
<div className="App">
<header className="App-header">
<p>
Edit <code>src/App.tsx</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
<Router>
<Routes>
<Route path="/login" element={<LoginPage/>}/>
<Route path="/forgot-password" element={<LoginPage />} />
<Route path="/register" element={<LoginPage />} />
<Route path="/login/sso" element={<LoginPage />} />
<Route path="/verify-email" element={<LoginPage />} />
</Routes>
</Router>
</div>
);
}

View File

@@ -0,0 +1,7 @@
import React from 'react';
const ForgotPasswordPage = () => {
return (<div>ForgotPassword</div>)
};
export default ForgotPasswordPage;

View File

@@ -0,0 +1,32 @@
import React from 'react';
import BasicModelForm from 'CommonUI/src/Components/Forms/BasicModelForm';
import User from 'Common/Models/User';
import FormValues from 'CommonUI/src/Components/Forms/Types/FormValues';
const LoginPage = () => {
const user: User = new User();
return (
<BasicModelForm
model={user}
id="login-form"
fields={[
{
field: {
email: true
}
},
{
field: {
password: true
}
}
]}
onSubmit={(values: FormValues<User>) => {
console.log(values);
}}
/>
)
};
export default LoginPage;

View File

View File

View File

View File

@@ -14,28 +14,29 @@ import { JSONArray, JSONObject } from '../Types/JSON';
import ObjectID from '../Types/ObjectID';
export default class BaseModel extends BaseEntity {
@TableColumn()
@TableColumn({title: "ID"})
@PrimaryGeneratedColumn('uuid')
public _id!: string;
@TableColumn()
@TableColumn({title: "Created"})
@CreateDateColumn()
public createdAt!: Date;
@TableColumn()
@TableColumn({title: "Updated"})
@UpdateDateColumn()
public updatedAt!: Date;
@TableColumn()
@TableColumn({title: "Deleted"})
@DeleteDateColumn()
public deletedAt?: Date;
@TableColumn()
@TableColumn({title: "Version"})
@VersionColumn()
public version!: number;
private displayColumnAs: Dictionary<string> = {};
private displayColumnTitleAs: Dictionary<string> = {};
private displayColumnDescriptionAs: Dictionary<string> = {};
private encryptedColumns: Columns = new Columns([]);
private uniqueColumns: Columns = new Columns([]);
@@ -131,13 +132,25 @@ export default class BaseModel extends BaseEntity {
return this.hashedColumns;
}
public addDisplayColumnAs(columnName: string, displayAs: string): void {
this.displayColumnAs[columnName] = displayAs;
public addDisplayColumnTitleAs(columnName: string, title: string): void {
this.displayColumnTitleAs[columnName] = title;
}
public getDisplayColumnAs(columnName: string): string | null {
if (this.displayColumnAs[columnName]) {
return this.displayColumnAs[columnName] as string;
public getDisplayColumnTitleAs(columnName: string): string | null {
if (this.displayColumnTitleAs[columnName]) {
return this.displayColumnTitleAs[columnName] as string;
}
return null;
}
public addDisplayColumnDescriptionAs(columnName: string, description: string): void {
this.displayColumnDescriptionAs[columnName] = description;
}
public getDisplayColumnDescriptionAs(columnName: string): string | null {
if (this.displayColumnDescriptionAs[columnName]) {
return this.displayColumnDescriptionAs[columnName] as string;
}
return null;

View File

@@ -1,8 +1,16 @@
import BaseModel from '../../Models/BaseModel';
export default () => {
export default (props?: {title?: string, description?: string}) => {
return (target: Object, propertyKey: string) => {
const baseModel: BaseModel = target as BaseModel;
baseModel.addTableColumn(propertyKey);
if (props && props.title) {
baseModel.addDisplayColumnTitleAs(propertyKey, props.title);
}
if (props && props.description) {
baseModel.addDisplayColumnTitleAs(propertyKey, props.description);
}
};
};

View File

@@ -1,6 +1,7 @@
import React, { FunctionComponent, ReactElement, useEffect } from 'react';
import { MouseOnClick, KeyboardEventProp } from '../../../Types/HtmlEvents';
import ShortcutKey from '../ShortcutKey/ShortcutKey';
import ButtonType from './ButtonTypes';
export interface ComponentProps {
title: string;

View File

@@ -2,4 +2,6 @@ enum ButtonType {
Submit = "submit",
Reset = "reset",
Button = "button"
}
}
export default ButtonType;

View File

@@ -1,25 +1,46 @@
import React, { FunctionComponent } from 'react';
import React, { ReactElement } from 'react';
import { Formik, Form, Field, ErrorMessage, FormikErrors } from 'formik';
import Button from '../Basic/Button/Button';
import FormValues from './Types/FormValues'
import RequiredFormFields from './Types/RequiredFormFields';
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> {
id: string,
initialValues: FormValues<T>,
onSubmit: (values: FormValues<T>) => void
onValidate: (values: FormValues<T>) => FormikErrors<FormValues<T>>,
onSubmit: (values: FormValues<T>) => void
onValidate?: (values: FormValues<T>) => FormikErrors<FormValues<T>>,
requiredfields: RequiredFormFields<T>,
fields: Array<keyof T>
fields: Fields<T>,
model: T
}
const BasicForm = <T,>(props: ComponentProps<T>) => {
const getFormField = (field: DataField<T>): ReactElement => {
let fieldType = "text";
if (Object.keys(field.field).length === 0) {
throw new BadDataException("Object cannot be without Field")
}
return (<div>
<Field type={fieldType} name={Object.keys(field.field)[0] as string} />
<ErrorMessage name={Object.keys(field.field)[0] as string} component="div" />
</div>)
}
return (<div>
<Formik
initialValues={props.initialValues}
validate={(values: FormValues<T>) => {
return props.onValidate(values);
if (props.onValidate) {
return props.onValidate(values);
}
return {};
}}
onSubmit={(values: FormValues<T>) => {
props.onSubmit(values);
@@ -28,11 +49,10 @@ const BasicForm = <T,>(props: ComponentProps<T>) => {
{({ isSubmitting }) => (
<Form>
<Field type="email" name="email" />
<ErrorMessage name="email" component="div" />
<Field type="password" name="password" />
<ErrorMessage name="password" component="div" />
<Button title='Submit' disabled={isSubmitting} type={ButtonType.Submit} id={`${props.id}-submit-button`} />
{props.fields && props.fields.map((field: DataField<T>) => {
return getFormField(field);
})}
<Button title='Submit' disabled={isSubmitting} type={ButtonTypes.Submit} id={`${props.id}-submit-button`} />
</Form>
)}
</Formik>

View File

@@ -1,47 +1,45 @@
import React, { FunctionComponent } from 'react';
import { Formik, Form, Field, ErrorMessage, FormikErrors } from 'formik';
import Button from '../Basic/Button/Button';
import React from 'react';
import { FormikErrors } from 'formik';
import BaseModel from 'Common/Models/BaseModel';
import Columns from 'Common/Types/Database/Columns';
import Dictionary from 'Common/Types/Dictionary';
import FormValues from './FormValues';
import FormValues from './Types/FormValues';
import Fields from './Types/Fields';
import BasicForm from './BasicForm';
export interface ComponentProps<T extends BaseModel> {
model: T,
id: string,
fieldsInForm: Dictionary<boolean>,
initialValues: Dictionary<string | number>,
onSubmit: (values: FormValues) => void
onValidate: (values: FormValues) => FormikErrors<FormValues>
onSubmit: (values: FormValues<T>) => void
onValidate?: (values: FormValues<T>) => FormikErrors<FormValues<T>>,
fields: Fields<T>
}
const BasicForm: FunctionComponent = <TBaseModel extends BaseModel>(props: ComponentProps<TBaseModel>) => {
const BasicModelForm = <TBaseModel extends BaseModel>(props: ComponentProps<TBaseModel>) => {
const columns: Columns = props.model.getTableColumns();
const requiredColumns: Columns = props.model.getTableColumns();
const initialValues: FormValues<TBaseModel> = {};
return (<div>
<Formik
initialValues={{ email: '', password: '' }}
validate={(values: FormValues) => {
return props.onValidate(values);
}}
onSubmit={(values: FormValues) => {
props.onSubmit(values);
}}
>
{({ isSubmitting }) => (
<Form>
<Field type="email" name="email" />
<ErrorMessage name="email" component="div" />
<Field type="password" name="password" />
<ErrorMessage name="password" component="div" />
<Button title='Submit' disabled={isSubmitting} type={ButtonType.Submit} id={`${props.id}-submit-button`} />
</Form>
)}
</Formik>
</div>)
// Prep
for (const field of props.fields) {
if (Object.keys(field.field).length > 0){
if (props.model.getDisplayColumnTitleAs(Object.keys(field.field)[0] as string)) {
field.title = props.model.getDisplayColumnTitleAs(Object.keys(field.field)[0] as string) as string;
}
if (props.model.getDisplayColumnDescriptionAs(Object.keys(field.field)[0] as string)) {
field.description = props.model.getDisplayColumnDescriptionAs(Object.keys(field.field)[0] as string) as string;
}
}
}
return (<BasicForm
fields={props.fields}
id={props.id}
onSubmit={props.onSubmit}
initialValues={initialValues}
requiredfields={{}}
model={props.model}
/>)
};
export default BasicForm;
export default BasicModelForm;

View File

@@ -0,0 +1,7 @@
import SelectFormFields from './SelectFormField';
export default interface Field<TEntity> {
title?: string,
description?: string,
field: SelectFormFields<TEntity>
}

View File

@@ -0,0 +1,5 @@
import Field from "./Field"
type Fields<T> = Array<Field<T>>
export default Fields

View File

@@ -1,11 +1,11 @@
import FormFieldSchemaTypes from './FormFieldType'
type FormFields<Property> = Property extends FormFieldSchemaTypes
export type FormField<Property> = Property extends FormFieldSchemaTypes
? Property
: unknown;
declare type FormValues<Entity> = {
[P in keyof Entity]?: FormFields<NonNullable<Entity[P]>>;
[P in keyof Entity]?: FormField<NonNullable<Entity[P]>>;
};
export default FormValues;

View File

@@ -1,6 +1,6 @@
import FormFieldSchemaTypes from "./FormFieldType";
type SelectFormField<Property> = Property extends FormFieldSchemaTypes
export type SelectFormField<Property> = Property extends FormFieldSchemaTypes
? boolean
: unknown;