React -> Upgrade forms & simple fixes
parent
d7bc10f938
commit
9e5fe8790b
|
|
@ -13,48 +13,58 @@ export const FormGenerator = ({
|
|||
|
||||
const handler = async (event) => {
|
||||
event.preventDefault()
|
||||
for ( let i = 0; i < refList.length; i++ ) {
|
||||
if (
|
||||
refList[i].current.value === ''
|
||||
for (let i = 0; i < refList.length; i++) {
|
||||
if (refList[i].current.value === ''
|
||||
&& inputList[0].action !== 'Update'
|
||||
|| i === 0 && refList.length !== 1
|
||||
|| i === 0
|
||||
&& refList.length !== 1
|
||||
) {
|
||||
refList[i].current.focus()
|
||||
} else if ( i === refList.length - 1 ) {
|
||||
await action( refList )
|
||||
} else if (i === refList.length - 1) {
|
||||
await action(refList)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
let info
|
||||
|
||||
return (
|
||||
<form onSubmit={ event => handler( event ) }>
|
||||
{
|
||||
inputList.map( (input, key) => {
|
||||
|
||||
if ( input.type === 'info' ) {
|
||||
<form onSubmit={event => handler(event)}>
|
||||
{
|
||||
inputList.map((input, key) => {
|
||||
|
||||
if (input.type === 'info') {
|
||||
info = input
|
||||
} else if ( input.type === 'text' ) {
|
||||
return (
|
||||
<TextInputGenerator
|
||||
input={ input }
|
||||
info={ info }
|
||||
key={ key }
|
||||
/>
|
||||
)
|
||||
} else if ( input.type === 'file' ) {
|
||||
} else if (input.type === 'text') {
|
||||
return (
|
||||
<UploadInputGenerator
|
||||
input={ input }
|
||||
info={ info }
|
||||
key={ key }
|
||||
<TextInputGenerator
|
||||
input={input}
|
||||
info={info}
|
||||
key={key}
|
||||
/>
|
||||
)
|
||||
} else if (input.type === 'password') {
|
||||
return (
|
||||
<PasswordInputGenerator
|
||||
input={input}
|
||||
info={info}
|
||||
key={key}
|
||||
/>
|
||||
)
|
||||
} else if (input.type === 'file') {
|
||||
return (
|
||||
<UploadInputGenerator
|
||||
input={input}
|
||||
info={info}
|
||||
key={key}
|
||||
/>
|
||||
)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
<button type='submit' />
|
||||
<button type='submit'>
|
||||
{ info.button_value }
|
||||
</button>
|
||||
</form>
|
||||
)
|
||||
}
|
||||
|
|
@ -74,16 +84,47 @@ export const FormGenerator = ({
|
|||
* endpoint: 'Album'
|
||||
* } } info - information about form
|
||||
*/
|
||||
const TextInputGenerator = ({
|
||||
const TextInputGenerator = ({
|
||||
input, info
|
||||
}) => {
|
||||
return (
|
||||
<div>
|
||||
{ input.name + ':' }
|
||||
<input
|
||||
id={ input.name + info.action + info.endpoint + 'Input' }
|
||||
{input.name + ':'}
|
||||
<input
|
||||
id={input.name + info.action + info.endpoint + 'Input'}
|
||||
autoComplete='off'
|
||||
ref={ input.ref }
|
||||
ref={input.ref}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Text input generator, example:
|
||||
* @param {
|
||||
* {
|
||||
* type: 'password',
|
||||
* name: 'name',
|
||||
* ref: React.createRef()
|
||||
* } } input - basic text input
|
||||
* @param {
|
||||
* {
|
||||
* type: 'info',
|
||||
* action: 'Update'
|
||||
* endpoint: 'Album'
|
||||
* } } info - information about form
|
||||
*/
|
||||
const PasswordInputGenerator = ({
|
||||
input, info
|
||||
}) => {
|
||||
return (
|
||||
<div>
|
||||
{input.name + ':'}
|
||||
<input
|
||||
id={input.name + info.action + info.endpoint + 'Input'}
|
||||
autoComplete='off'
|
||||
ref={input.ref}
|
||||
type='password'
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
|
|
@ -101,55 +142,55 @@ const TextInputGenerator = ({
|
|||
* file: file, setFile: setFile() #useState
|
||||
* } } input -
|
||||
*/
|
||||
const UploadInputGenerator = ({
|
||||
const UploadInputGenerator = ({
|
||||
input, info
|
||||
}) => {
|
||||
|
||||
const onLoadFile = async ( event ) => {
|
||||
|
||||
const onLoadFile = async (event) => {
|
||||
event.preventDefault()
|
||||
let data = event.target.files[0]
|
||||
input.setFile( await toBase64( data ) )
|
||||
input.setFile(await toBase64(data))
|
||||
setDropInfos(data.name, data.size)
|
||||
}
|
||||
|
||||
const onLoadFileDrop = async ( event ) => {
|
||||
const onLoadFileDrop = async (event) => {
|
||||
event.preventDefault()
|
||||
event.persist()
|
||||
let data = event.dataTransfer.files[0]
|
||||
input.setFile( await toBase64( data ) )
|
||||
input.setFile(await toBase64(data))
|
||||
setDropInfos(data.name, data.size)
|
||||
}
|
||||
|
||||
const toBase64 = ( file ) => new Promise( (resolve, reject) => {
|
||||
const toBase64 = (file) => new Promise((resolve, reject) => {
|
||||
let fileReader = new FileReader()
|
||||
fileReader.readAsDataURL( file )
|
||||
fileReader.onload = () => resolve( fileReader.result )
|
||||
fileReader.onerror = error => reject( error )
|
||||
fileReader.readAsDataURL(file)
|
||||
fileReader.onload = () => resolve(fileReader.result)
|
||||
fileReader.onerror = error => reject(error)
|
||||
})
|
||||
|
||||
const setDropInfos = (name, size) => {
|
||||
input.setDropInfo(
|
||||
'name: "'
|
||||
+ name
|
||||
+ '"\nsize: '
|
||||
+ (Math.round(size / 100 + 'e-2') / 100 )
|
||||
+ ' MB'
|
||||
input.setDropInfo(
|
||||
'name: "'
|
||||
+ name
|
||||
+ '"\nsize: '
|
||||
+ (Math.round(size / 100 + 'e-2') / 100)
|
||||
+ ' MB'
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div onDrop={ event => onLoadFileDrop( event ) } >
|
||||
<pre style={ {marginTop: '25px', marginLeft: '40px'} }>
|
||||
{ input.dropInfo }
|
||||
<div onDrop={event => onLoadFileDrop(event)} >
|
||||
<pre style={{ marginTop: '25px', marginLeft: '40px' }}>
|
||||
{input.dropInfo}
|
||||
</pre>
|
||||
<input
|
||||
style={ { marginTop: '-55px' } }
|
||||
id={ input.name + info.action + info.endpoint + 'Input' }
|
||||
<input
|
||||
style={{ marginTop: '-55px' }}
|
||||
id={input.name + info.action + info.endpoint + 'Input'}
|
||||
className='uploadInput'
|
||||
type='file'
|
||||
accept={ input.fileType + '/*' }
|
||||
accept={input.fileType + '/*'}
|
||||
autoComplete='off'
|
||||
onChange={ event => onLoadFile( event ) }
|
||||
onChange={event => onLoadFile(event)}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,66 @@
|
|||
import React, { useState, useEffect } from 'react'
|
||||
|
||||
import { useSelector, useDispatch } from 'react-redux'
|
||||
|
||||
import { userAuthSelector } from '../../../redux/slices/userAuthSlice'
|
||||
import userAuthAsyncThunk from '../../../redux/asyncThunks/userAuthAsyncThunk'
|
||||
|
||||
import FormGenerator from '../formGenerator'
|
||||
|
||||
|
||||
const UserLoginForm = () => {
|
||||
|
||||
const usernameInput = React.createRef()
|
||||
const passwordInput = React.createRef()
|
||||
|
||||
const dispatch = useDispatch()
|
||||
|
||||
let refList = [
|
||||
usernameInput,
|
||||
passwordInput
|
||||
]
|
||||
|
||||
let inputList = [
|
||||
{
|
||||
type: 'info',
|
||||
action: 'Create',
|
||||
endpint: 'user/auth/login',
|
||||
button_value: 'Sign In'
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
name: 'Username',
|
||||
ref: usernameInput
|
||||
},
|
||||
{
|
||||
type: 'password',
|
||||
name: 'Password',
|
||||
ref: passwordInput
|
||||
}
|
||||
]
|
||||
|
||||
const login = async ( refs ) => {
|
||||
let pass = {
|
||||
username: refs[0].current.value,
|
||||
password: refs[1].current.value
|
||||
}
|
||||
dispatch(
|
||||
userAuthAsyncThunk.fetchLogin(
|
||||
pass
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<FormGenerator
|
||||
inputList={ inputList }
|
||||
refList={ refList }
|
||||
action={ login }
|
||||
/>
|
||||
</>
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
export default UserLoginForm
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
import React, { useState, useEffect } from 'react'
|
||||
|
||||
import { useSelector, useDispatch } from 'react-redux'
|
||||
|
||||
import { userCrudSelector } from '../../../redux/slices/userCrudSlice'
|
||||
import userCrudAsyncThunk from '../../../redux/asyncThunks/userCrudAsyncThunk'
|
||||
|
||||
import FormGenerator from '../formGenerator'
|
||||
|
||||
|
||||
const UserRegisterForm = () => {
|
||||
|
||||
const usernameInput = React.createRef()
|
||||
const passwordInput = React.createRef()
|
||||
const emailInput = React.createRef()
|
||||
|
||||
const dispatch = useDispatch()
|
||||
|
||||
let refList = [
|
||||
usernameInput,
|
||||
passwordInput,
|
||||
emailInput
|
||||
]
|
||||
|
||||
let inputList = [
|
||||
{
|
||||
type: 'info',
|
||||
action: 'Create',
|
||||
endpint: 'user/auth/login',
|
||||
button_value: 'Sign In'
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
name: 'Username',
|
||||
ref: usernameInput
|
||||
},
|
||||
{
|
||||
type: 'password',
|
||||
name: 'Password',
|
||||
ref: passwordInput
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
name: 'Email',
|
||||
ref: emailInput
|
||||
}
|
||||
]
|
||||
|
||||
const register = async ( refs ) => {
|
||||
let pass = {
|
||||
username: refs[0].current.value,
|
||||
password: refs[1].current.value,
|
||||
email: refs[2].current.value,
|
||||
}
|
||||
dispatch(
|
||||
userCrudAsyncThunk.fetchRegister(
|
||||
pass
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<FormGenerator
|
||||
inputList={ inputList }
|
||||
refList={ refList }
|
||||
action={ register }
|
||||
/>
|
||||
</>
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
export default UserRegisterForm
|
||||
|
|
@ -80,7 +80,7 @@ const __verifyUserSession = (token, user) => {
|
|||
if ( user.id !== 0 && user.username !== '' && user.email !== '' && token !== '' )
|
||||
return true
|
||||
else
|
||||
return true
|
||||
return false
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,13 @@
|
|||
import React, { useState, useEffect } from 'react'
|
||||
|
||||
import UserLoginForm from '../../../components/forms/user_auth/userLogin'
|
||||
|
||||
|
||||
const UserAuthIndex = () => {
|
||||
|
||||
return (
|
||||
<div>
|
||||
<UserLoginForm />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,31 +74,53 @@ const responseAbstract = async (endpoint, method, token, body) => {
|
|||
|
||||
const headerBuilder = (url, method, token, body) => {
|
||||
let headers_r = {
|
||||
'Authorization': token,
|
||||
'authorization': token,
|
||||
'x-csrftoken': getCookie('csrftoken'),
|
||||
'accept': 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
'content-type': 'application/json',
|
||||
}
|
||||
if ('file' in body) {
|
||||
headers_r = {
|
||||
'Authorization': token,
|
||||
'authorization': token,
|
||||
'x-csrftoken': getCookie('csrftoken'),
|
||||
'accept': 'multipart/form-data',
|
||||
'Content-Type': 'multipart/form-data',
|
||||
'content-type': 'multipart/form-data',
|
||||
}
|
||||
}
|
||||
let headers = {
|
||||
url: url,
|
||||
method: method,
|
||||
headers: headers_r
|
||||
headers: headers_r,
|
||||
credentials: 'same-origin'
|
||||
}
|
||||
if (method === 'PUT' || method === 'POST' || method === 'PATCH') {
|
||||
headers = Object.assign({}, headers, {
|
||||
data: JSON.stringify(body),
|
||||
withCredentials: true,
|
||||
})
|
||||
}
|
||||
console.log(headers)
|
||||
return headers
|
||||
}
|
||||
|
||||
/**
|
||||
* get cookie method for CSRF verification
|
||||
* @param {string} name - name of handled cookie
|
||||
*/
|
||||
const getCookie = (name) => {
|
||||
if (!document.cookie) {
|
||||
return null;
|
||||
}
|
||||
const token = document.cookie.split(';')
|
||||
.map(c => c.trim())
|
||||
.filter(c => c.startsWith(name + '='));
|
||||
|
||||
if (token.length === 0) {
|
||||
return null;
|
||||
}
|
||||
return decodeURIComponent(token[0].split('=')[1]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
export default {
|
||||
APIAddress,
|
||||
|
|
|
|||
|
|
@ -15,11 +15,15 @@ const userAuthSlice = createSlice(
|
|||
reducers: {},
|
||||
extraReducers: {
|
||||
[userAuthAsyncThunk.fetchLogin.fulfilled.type]: (state, action) => {
|
||||
state.token = action.payload.data.Authorization
|
||||
state.user.id = action.payload.data.user.id
|
||||
state.user.username = action.payload.data.user.username
|
||||
state.user.email = action.payload.data.user.email
|
||||
state.info = 'login success'
|
||||
try {
|
||||
state.token = action.payload.data.Authorization
|
||||
state.user.id = action.payload.data.user.id
|
||||
state.user.username = action.payload.data.user.username
|
||||
state.user.email = action.payload.data.user.email
|
||||
state.info = 'login success'
|
||||
} catch {
|
||||
state.info = 'login failed'
|
||||
}
|
||||
},
|
||||
[userAuthAsyncThunk.fetchLogout.fulfilled.type]: (state, action) => {
|
||||
state.token = ''
|
||||
|
|
|
|||
Loading…
Reference in New Issue