Image upload, better error handling, removed warnings,
fixed date field not rendering correct date during edit
This commit is contained in:
m0n02hz
2022-03-04 02:03:10 +05:30
parent e2d3ccfb7e
commit 5d2e29fc41
8 changed files with 2042 additions and 5120 deletions

7085
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -10,7 +10,7 @@
"dependencies": {
"@asseinfo/react-kanban": "2.2.0",
"@emotion/cache": "11.4.0",
"@emotion/react": "11.4.1",
"@emotion/react": "^11.4.1",
"@emotion/styled": "11.3.0",
"@fullcalendar/daygrid": "5.9.0",
"@fullcalendar/interaction": "5.9.0",

View File

@@ -1,4 +1,4 @@
import * as React from 'react';
import React, {useEffect, useState} from 'react';
import PropTypes from 'prop-types';
import Stack from '@mui/material/Stack';
import TextField from '@mui/material/TextField';
@@ -6,11 +6,15 @@ import AdapterDateFns from '@mui/lab/AdapterDateFns';
import LocalizationProvider from '@mui/lab/LocalizationProvider';
import DateTimePicker from '@mui/lab/DateTimePicker';
export default function DateTimeInput({ disabled }) {
const [value, setValue] = React.useState(new Date());
export default function DateTimeInput({ disabled, value }) {
const [date, setDate] = useState(value || new Date());
useEffect(() => {
setDate(value);
}, [value])
const handleChange = (newValue) => {
setValue(newValue);
setDate(newValue);
};
return (
@@ -19,7 +23,7 @@ export default function DateTimeInput({ disabled }) {
<DateTimePicker
disabled={disabled}
label=""
value={value}
value={date}
renderInput={(params) => <TextField {...params} />}
onChange={handleChange}
/>
@@ -29,5 +33,6 @@ export default function DateTimeInput({ disabled }) {
}
DateTimeInput.propTypes = {
disabled: PropTypes.bool
disabled: PropTypes.bool,
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.object])
};

View File

@@ -77,6 +77,7 @@ function CreateEditUser(props) {
const location = useLocation();
const [editedUser, setEditedUser] = useState(location?.state?.user);
const [selectedRoles, setSelectedRoles] = useState([]);
const [uploadedImg, setUploadedImg] = useState();
useEffect(() => {
if (context === 'edit') {
@@ -86,6 +87,7 @@ function CreateEditUser(props) {
} else {
setEditedUser(editedUser);
setSelectedRoles(editedUser.roles);
editedUser.image_url && setUploadedImg(editedUser.image_url);
}
}
}, []);
@@ -110,6 +112,7 @@ function CreateEditUser(props) {
actions: '',
visibilities: '',
isActive: true,
image: '',
createdBy: currentUser ? currentUser.fullName : '',
createdAt: new Date(),
updatedBy: currentUser ? currentUser.fullName : '',
@@ -125,6 +128,7 @@ function CreateEditUser(props) {
actions: editedUser?.permissions?.actions ? editedUser.permissions.actions.join(',') : '',
visibilities: editedUser?.permissions?.allowedUIModules ? editedUser.permissions.allowedUIModules.join(',') : '',
isActive: editedUser && editedUser.isActive !== undefined ? editedUser.isActive : true,
image: editedUser ? editedUser.image_url : EditIcon,
createdBy: editedUser ? editedUser.createdBy?.fullName : '',
createdAt: editedUser ? editedUser.createdAt : '',
updatedBy: editedUser ? editedUser.updatedBy?.fullName : '',
@@ -150,14 +154,20 @@ function CreateEditUser(props) {
delete valuesClone.warehouses;
delete valuesClone.actions;
delete valuesClone.visibilities;
return valuesClone;
valuesClone.permissions = JSON.stringify(valuesClone.permissions);
valuesClone.roles = selectedRoles && selectedRoles.length > 0 ? selectedRoles.map(role => role._id) : [];
const formData = new FormData();
Object.keys(valuesClone).forEach(key => formData.append(key, valuesClone[key]));
uploadedImg && formData.append('image', uploadedImg);
return formData;
};
values.roles = selectedRoles && selectedRoles.length > 0 ? selectedRoles.map(role => role._id) : [];
dispatch(
UsersActions.createUserAction({
loader: 'loading-request',
slug: context === 'edit' ? API.UPDATE_USER.replace(':id', editedUser._id): API.CREATE_USER,
method: 'post',
contentType: false,
processData: false,
data: adaptPayload(values),
onValidationFailed,
onSuccessfulSubmission,
@@ -181,6 +191,13 @@ function CreateEditUser(props) {
setSelectedRoles(uniqueRoles);
};
const handleFileChange = e => {
const [file] = e.target.files;
if (file) {
setUploadedImg(file);
}
};
return (
<DashboardLayout className={classes.createEditUserGlobal}>
<DashboardNavbar />
@@ -188,9 +205,13 @@ function CreateEditUser(props) {
<MDBox mx={4} sx={{ border: '1px solid #C4C4C4', borderRadius: '4px', padding: '30px' }}>
<MDBox sx={{ width: '50%', margin: 'auto' }}>
<MDBox sx={{ width: '120px', margin: 'auto', position: 'relative' }}>
<img src={UserIcon} alt='img' />
<MDBox sx={{ position: 'absolute', bottom: '0', right: '0', cursor: 'pointer' }}>
<img src={EditIcon} alt='img' />
<img src={uploadedImg ? typeof uploadedImg === 'string' ? uploadedImg : URL.createObjectURL(uploadedImg) : UserIcon} alt='img' width='120' height='120' style={{borderRadius: '50%'}} />
<MDBox sx={{ position: 'absolute', bottom: '0', right: '0' }}>
<label htmlFor="image" style={{ cursor: 'pointer' }}>
<img src={EditIcon} />
</label>
<input id='image' name='image' type="file" className='d-none' accept="image/png, image/gif, image/jpeg"
onChange={handleFileChange} />
</MDBox>
</MDBox>
<MDBox sx={{ marginBottom: '24px' }}>
@@ -296,7 +317,7 @@ function CreateEditUser(props) {
<Box component='div' className={classes.labelSize}>
Date &amp; Time
</Box>
<DateTimeInput disabled name='createdAt' value={formik.values.createdAt} />
<DateTimeInput disabled name='createdAt' value={new Date(formik.values.createdAt)} />
</Grid>
<Grid item xs={6}>
<Box component='div' className={classes.labelSize}>
@@ -308,7 +329,7 @@ function CreateEditUser(props) {
<Box component='div' className={classes.labelSize}>
Date &amp; Time
</Box>
<DateTimeInput disabled name='updatedAt' value={formik.values.updatedAt} />
<DateTimeInput disabled name='updatedAt' value={new Date(formik.values.updatedAt)} />
</Grid>
</Grid>
</Grid>

View File

@@ -165,9 +165,9 @@ function UserAccessScreen() {
}
}));
const rowRenders = userRecords && userRecords.map(record => {
const rowRenders = userRecords && userRecords.map((record, keyouter) => {
const canEdit = columnConfig => columnConfig.isEditAnchor && currentUser.email !== record.email;
return <StyledTableRow key={record.id}>
return <StyledTableRow key={record.id + '-' + keyouter}>
{userHeadCells.map((columnConfig, key) => <TableCell key={key} onClick={() => canEdit(columnConfig) && navigate('/setup/users-access/edit-user', {state: {user: record}})}>
{canEdit(columnConfig) ? <span className={classes.iconwrap}>
<EditIcon className={classes.iconSize}/>
@@ -218,8 +218,8 @@ function UserAccessScreen() {
>
<TableBody>
{rolesRecords &&
rolesRecords.map((item) => (
<StyledTableRow key={item.id}>
rolesRecords.map((item, key) => (
<StyledTableRow key={item.id + '-' + key}>
<TableCell>
<div className={classes.iconwrap}>
<EditIcon className={classes.iconSize} />

View File

@@ -34,7 +34,11 @@ export function* onCreateUserData({ payload }) {
ApiServices[payload?.method],
AuthorizedAPI,
payload?.slug,
payload?.data
payload?.data,
{
processData: false,
contentType: false
}
);
if (response?.status === 200) {
const data = response.data?.data;
@@ -48,8 +52,9 @@ export function* onCreateUserData({ payload }) {
})
);
} else {
toast('Something went wrong!');
payload.onValidationFailed(response.data?.error);
const error = response?.originalError?.response?.data?.error;
toast(error && error.indexOf('E11000') > -1 ? 'Email already exists!' : 'Something went wrong!');
payload.onValidationFailed();
yield put(
UsersActions.createUserFailure({
loader: payload?.loader,

View File

@@ -1,6 +1,6 @@
// REST API SERVICES
export default {
post: (API, slug, payload) => API.post(slug, payload),
post: (API, slug, payload, headers) => headers ? API.post(slug, payload, {headers}) : API.post(slug, payload),
get: (API, slug) => API.get(slug),
delete: (API, slug) => {
return API.delete(slug);

View File

@@ -68,6 +68,8 @@ const schema = {
createUser: Yup.object({
fullName: Yup.string('Enter Full Name').required('User Name is required'),
email: Yup.string('Enter Email').required('Email is required'),
password: Yup.string('Enter Password').required('Password is required'),
phoneNumber: Yup.string('Enter Phone Numbe').required('Phone Number is required'),
roles: Yup.string('Please select at least one role').required('At least one role is required')
})