React -> Upgrade forms & simple fixes

feature/2_forms
TBS093A 2021-02-17 23:13:39 +01:00
parent b2565641e5
commit b2ecdfb807
7 changed files with 279 additions and 68 deletions

View File

@ -14,10 +14,10 @@ export const FormGenerator = ({
const handler = async (event) => { const handler = async (event) => {
event.preventDefault() event.preventDefault()
for (let i = 0; i < refList.length; i++) { for (let i = 0; i < refList.length; i++) {
if ( if (refList[i].current.value === ''
refList[i].current.value === ''
&& inputList[0].action !== 'Update' && inputList[0].action !== 'Update'
|| i === 0 && refList.length !== 1 || i === 0
&& refList.length !== 1
) { ) {
refList[i].current.focus() refList[i].current.focus()
} else if (i === refList.length - 1) { } else if (i === refList.length - 1) {
@ -43,6 +43,14 @@ export const FormGenerator = ({
key={key} key={key}
/> />
) )
} else if (input.type === 'password') {
return (
<PasswordInputGenerator
input={input}
info={info}
key={key}
/>
)
} else if (input.type === 'file') { } else if (input.type === 'file') {
return ( return (
<UploadInputGenerator <UploadInputGenerator
@ -54,7 +62,9 @@ export const FormGenerator = ({
} }
}) })
} }
<button type='submit' /> <button type='submit'>
{ info.button_value }
</button>
</form> </form>
) )
} }
@ -89,6 +99,37 @@ const TextInputGenerator = ({
) )
} }
/**
* 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>
)
}
/** /**
* Upload file input generator, example: * Upload file input generator, example:
* @param { * @param {

View File

@ -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

View File

@ -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

View File

@ -80,7 +80,7 @@ const __verifyUserSession = (token, user) => {
if ( user.id !== 0 && user.username !== '' && user.email !== '' && token !== '' ) if ( user.id !== 0 && user.username !== '' && user.email !== '' && token !== '' )
return true return true
else else
return true return false
} }

View File

@ -1,9 +1,13 @@
import React, { useState, useEffect } from 'react' import React, { useState, useEffect } from 'react'
import UserLoginForm from '../../../components/forms/user_auth/userLogin'
const UserAuthIndex = () => { const UserAuthIndex = () => {
return ( return (
<div> <div>
<UserLoginForm />
</div> </div>
) )
} }

View File

@ -74,31 +74,53 @@ const responseAbstract = async (endpoint, method, token, body) => {
const headerBuilder = (url, method, token, body) => { const headerBuilder = (url, method, token, body) => {
let headers_r = { let headers_r = {
'Authorization': token, 'authorization': token,
'x-csrftoken': getCookie('csrftoken'),
'accept': 'application/json', 'accept': 'application/json',
'Content-Type': 'application/json', 'content-type': 'application/json',
} }
if ('file' in body) { if ('file' in body) {
headers_r = { headers_r = {
'Authorization': token, 'authorization': token,
'x-csrftoken': getCookie('csrftoken'),
'accept': 'multipart/form-data', 'accept': 'multipart/form-data',
'Content-Type': 'multipart/form-data', 'content-type': 'multipart/form-data',
} }
} }
let headers = { let headers = {
url: url, url: url,
method: method, method: method,
headers: headers_r headers: headers_r,
credentials: 'same-origin'
} }
if (method === 'PUT' || method === 'POST' || method === 'PATCH') { if (method === 'PUT' || method === 'POST' || method === 'PATCH') {
headers = Object.assign({}, headers, { headers = Object.assign({}, headers, {
data: JSON.stringify(body), data: JSON.stringify(body),
withCredentials: true,
}) })
} }
console.log(headers)
return 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 { export default {
APIAddress, APIAddress,

View File

@ -15,11 +15,15 @@ const userAuthSlice = createSlice(
reducers: {}, reducers: {},
extraReducers: { extraReducers: {
[userAuthAsyncThunk.fetchLogin.fulfilled.type]: (state, action) => { [userAuthAsyncThunk.fetchLogin.fulfilled.type]: (state, action) => {
try {
state.token = action.payload.data.Authorization state.token = action.payload.data.Authorization
state.user.id = action.payload.data.user.id state.user.id = action.payload.data.user.id
state.user.username = action.payload.data.user.username state.user.username = action.payload.data.user.username
state.user.email = action.payload.data.user.email state.user.email = action.payload.data.user.email
state.info = 'login success' state.info = 'login success'
} catch {
state.info = 'login failed'
}
}, },
[userAuthAsyncThunk.fetchLogout.fulfilled.type]: (state, action) => { [userAuthAsyncThunk.fetchLogout.fulfilled.type]: (state, action) => {
state.token = '' state.token = ''