mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	Feat: admin users (#266)
* fix: make it work * fix: cleanup add/update users a bit * fix: fix * fix: fine tune
This commit is contained in:
		
							parent
							
								
									45bce4576d
								
							
						
					
					
						commit
						5166198f07
					
				| @ -3,10 +3,20 @@ import { Dialog, DialogTitle, DialogActions, DialogContent, Button } from '@mate | ||||
| import PropTypes from 'prop-types'; | ||||
| import ConditionallyRender from '../ConditionallyRender/ConditionallyRender'; | ||||
| 
 | ||||
| const ConfirmDialogue = ({ children, open, onClick, onClose, title, primaryButtonText, secondaryButtonText }) => ( | ||||
| const ConfirmDialogue = ({ | ||||
|     children, | ||||
|     open, | ||||
|     onClick, | ||||
|     onClose, | ||||
|     title, | ||||
|     primaryButtonText, | ||||
|     secondaryButtonText, | ||||
|     fullWidth = false, | ||||
| }) => ( | ||||
|     <Dialog | ||||
|         open={open} | ||||
|         onClose={onClose} | ||||
|         fullWidth={fullWidth} | ||||
|         aria-labelledby={'simple-modal-title'} | ||||
|         aria-describedby={'simple-modal-description'} | ||||
|     > | ||||
| @ -32,6 +42,7 @@ ConfirmDialogue.propTypes = { | ||||
|     ariaLabel: PropTypes.string, | ||||
|     ariaDescription: PropTypes.string, | ||||
|     title: PropTypes.string, | ||||
|     fullWidth: PropTypes.bool, | ||||
| }; | ||||
| 
 | ||||
| export default ConfirmDialogue; | ||||
|  | ||||
| @ -7,10 +7,10 @@ import AddUser from '../add-user-component'; | ||||
| import ChangePassword from '../change-password-component'; | ||||
| import UpdateUser from '../update-user-component'; | ||||
| import DelUser from '../del-user-component'; | ||||
| import { showPermissions } from '../util'; | ||||
| import ConditionallyRender from '../../../../component/common/ConditionallyRender/ConditionallyRender'; | ||||
| 
 | ||||
| function UsersList({ | ||||
|     roles, | ||||
|     fetchUsers, | ||||
|     removeUser, | ||||
|     addUser, | ||||
| @ -68,6 +68,11 @@ function UsersList({ | ||||
|         // eslint-disable-next-line react-hooks/exhaustive-deps | ||||
|     }, []); | ||||
| 
 | ||||
|     const renderRole = roleId => { | ||||
|         const role = roles.find(r => r.id === roleId); | ||||
|         return role ? role.name : ''; | ||||
|     } | ||||
| 
 | ||||
|     return ( | ||||
|         <div> | ||||
|             <Table> | ||||
| @ -77,7 +82,7 @@ function UsersList({ | ||||
|                         <TableCell>Created</TableCell> | ||||
|                         <TableCell>Username</TableCell> | ||||
|                         <TableCell>Name</TableCell> | ||||
|                         <TableCell>Access</TableCell> | ||||
|                         <TableCell>Role</TableCell> | ||||
|                         <TableCell>{hasPermission('ADMIN') ? 'Action' : ''}</TableCell> | ||||
|                     </TableRow> | ||||
|                 </TableHead> | ||||
| @ -88,7 +93,7 @@ function UsersList({ | ||||
|                             <TableCell>{formatFullDateTimeWithLocale(item.createdAt, location.locale)}</TableCell> | ||||
|                             <TableCell style={{ textAlign: 'left' }}>{item.username || item.email}</TableCell> | ||||
|                             <TableCell style={{ textAlign: 'left' }}>{item.name}</TableCell> | ||||
|                             <TableCell>{showPermissions(item.permissions)}</TableCell> | ||||
|                             <TableCell>{renderRole(item.rootRole)}</TableCell> | ||||
|                             <ConditionallyRender | ||||
|                                 condition={hasPermission('ADMIN')} | ||||
|                                 show={ | ||||
| @ -104,34 +109,37 @@ function UsersList({ | ||||
|                                         </IconButton> | ||||
|                                     </TableCell> | ||||
|                                 } | ||||
|                                 elseShow={ | ||||
|                                     <TableCell> | ||||
|                                         <IconButton aria-label="Change password" title="Change password" onClick={openPwDialog(item)}> | ||||
|                                             <Icon>lock</Icon> | ||||
|                                         </IconButton> | ||||
|                                     </TableCell> | ||||
|                                 } | ||||
|                                 elseShow={<TableCell />} | ||||
|                             /> | ||||
|                         </TableRow> | ||||
|                     ))} | ||||
|                 </TableBody> | ||||
|             </Table> | ||||
|             <br /> | ||||
|             <Button variant="contained" color="primary" onClick={openDialog}> | ||||
|                 Add new user | ||||
|             </Button> | ||||
|             <ConditionallyRender | ||||
|                 condition={hasPermission('ADMIN')} | ||||
|                 show={ | ||||
|                     <Button variant="contained" color="primary" onClick={openDialog}> | ||||
|                         Add new user | ||||
|                     </Button> | ||||
|                 } | ||||
|                 elseShow={<small>PS! Only admins can add/remove users.</small>} | ||||
|             /> | ||||
| 
 | ||||
|             <AddUser | ||||
|                 showDialog={showDialog} | ||||
|                 closeDialog={closeDialog} | ||||
|                 addUser={addUser} | ||||
|                 validatePassword={validatePassword} | ||||
|                 roles={roles} | ||||
|             /> | ||||
|             <UpdateUser | ||||
|             {updateDialog.open && <UpdateUser | ||||
|                 showDialog={updateDialog.open} | ||||
|                 closeDialog={closeUpdateDialog} | ||||
|                 updateUser={updateUser} | ||||
|                 user={updateDialog.user} | ||||
|             /> | ||||
|                 roles={roles} | ||||
|             />} | ||||
|             <ChangePassword | ||||
|                 showDialog={pwDialog.open} | ||||
|                 closeDialog={closePwDialog} | ||||
| @ -155,6 +163,7 @@ function UsersList({ | ||||
| } | ||||
| 
 | ||||
| UsersList.propTypes = { | ||||
|     roles: PropTypes.array.isRequired, | ||||
|     users: PropTypes.array.isRequired, | ||||
|     fetchUsers: PropTypes.func.isRequired, | ||||
|     removeUser: PropTypes.func.isRequired, | ||||
|  | ||||
| @ -12,6 +12,7 @@ import { hasPermission } from '../../../../permissions'; | ||||
| 
 | ||||
| const mapStateToProps = state => ({ | ||||
|     users: state.userAdmin.toJS(), | ||||
|     roles: state.roles.get('root').toJS() || [], | ||||
|     location: state.settings.toJS().location || {}, | ||||
|     hasPermission: permission => hasPermission(state.user.get('profile'), permission), | ||||
| }); | ||||
|  | ||||
| @ -1,49 +1,28 @@ | ||||
| import React, { useState } from 'react'; | ||||
| import PropTypes from 'prop-types'; | ||||
| import Dialogue from '../../../component/common/Dialogue'; | ||||
| import { | ||||
|     TextField, | ||||
|     DialogTitle, | ||||
|     DialogContent, | ||||
|     RadioGroup, | ||||
|     Radio, | ||||
|     FormControl, | ||||
|     FormControlLabel, | ||||
|     FormLabel, | ||||
| } from '@material-ui/core'; | ||||
| import { trim } from '../../../component/common/util'; | ||||
| import commonStyles from '../../../component/common/common.module.scss'; | ||||
| import UserForm from './user-form'; | ||||
| 
 | ||||
| const EMPTY = { userType: 'regular' }; | ||||
| 
 | ||||
| function AddUser({ showDialog, closeDialog, addUser, validatePassword }) { | ||||
|     const [data, setData] = useState(EMPTY); | ||||
| function AddUser({ showDialog, closeDialog, addUser, roles }) { | ||||
|     const [data, setData] = useState({}); | ||||
|     const [error, setError] = useState({}); | ||||
| 
 | ||||
|     const updateField = e => { | ||||
|         setData({ | ||||
|             ...data, | ||||
|             [e.target.name]: e.target.value, | ||||
|         }); | ||||
|     }; | ||||
| 
 | ||||
|     const updateFieldWithTrim = e => { | ||||
|         setData({ | ||||
|             ...data, | ||||
|             [e.target.name]: trim(e.target.value), | ||||
|         }); | ||||
|     }; | ||||
| 
 | ||||
|     const submit = async e => { | ||||
|         e.preventDefault(); | ||||
|         if (!data.email) { | ||||
|             setError({ general: 'You must specify the email adress' }); | ||||
|             setError({ general: 'You must specify the email address' }); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         if (!data.rootRole) { | ||||
|             setError({ general: 'You must specify a role for the user' }); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         try { | ||||
|             await addUser(data); | ||||
|             setData(EMPTY); | ||||
|             setData({}); | ||||
|             setError({}); | ||||
|             closeDialog(); | ||||
|         } catch (error) { | ||||
|             const msg = error.message || 'Could not create user'; | ||||
| @ -51,22 +30,10 @@ function AddUser({ showDialog, closeDialog, addUser, validatePassword }) { | ||||
|         } | ||||
|     }; | ||||
| 
 | ||||
|     const onPasswordBlur = async e => { | ||||
|         e.preventDefault(); | ||||
|         setError({ password: '' }); | ||||
|         if (data.password) { | ||||
|             try { | ||||
|                 await validatePassword(data.password); | ||||
|             } catch (error) { | ||||
|                 const msg = error.message || ''; | ||||
|                 setError({ password: msg }); | ||||
|             } | ||||
|         } | ||||
|     }; | ||||
| 
 | ||||
|     const onCancel = e => { | ||||
|         e.preventDefault(); | ||||
|         setData(EMPTY); | ||||
|         setData({}); | ||||
|         setError({}); | ||||
|         closeDialog(); | ||||
|     }; | ||||
| 
 | ||||
| @ -79,61 +46,9 @@ function AddUser({ showDialog, closeDialog, addUser, validatePassword }) { | ||||
|             onClose={onCancel} | ||||
|             primaryButtonText="Add user" | ||||
|             secondaryButtonText="Cancel" | ||||
|             fullWidth | ||||
|         > | ||||
|             <form onSubmit={submit}> | ||||
|                 <DialogTitle>Add new user</DialogTitle> | ||||
| 
 | ||||
|                 <DialogContent | ||||
|                     className={commonStyles.contentSpacing} | ||||
|                     style={{ display: 'flex', flexDirection: 'column' }} | ||||
|                 > | ||||
|                     <p style={{ color: 'red' }}>{error.general}</p> | ||||
|                     <TextField | ||||
|                         label="Full name" | ||||
|                         name="name" | ||||
|                         value={data.name} | ||||
|                         error={error.name !== undefined} | ||||
|                         helperText={error.name} | ||||
|                         type="name" | ||||
|                         variant="outlined" | ||||
|                         size="small" | ||||
|                         onChange={updateField} | ||||
|                     /> | ||||
|                     <TextField | ||||
|                         label="Email" | ||||
|                         name="email" | ||||
|                         value={data.email} | ||||
|                         error={error.email !== undefined} | ||||
|                         helperText={error.email} | ||||
|                         type="email" | ||||
|                         variant="outlined" | ||||
|                         size="small" | ||||
|                         onChange={updateFieldWithTrim} | ||||
|                     /> | ||||
|                     <TextField | ||||
|                         label="Password" | ||||
|                         name="password" | ||||
|                         type="password" | ||||
|                         value={data.password} | ||||
|                         error={error.password !== undefined} | ||||
|                         helperText={error.password} | ||||
|                         variant="outlined" | ||||
|                         size="small" | ||||
|                         onChange={updateField} | ||||
|                         onBlur={onPasswordBlur} | ||||
|                     /> | ||||
|                     <br /> | ||||
|                     <br /> | ||||
|                     <FormControl> | ||||
|                         <FormLabel component="legend">User type</FormLabel> | ||||
|                         <RadioGroup name="userType" value={data.userType} onChange={updateField}> | ||||
|                             <FormControlLabel label="Regular" control={<Radio />} value="regular" /> | ||||
|                             <FormControlLabel label="Admin" control={<Radio />} value="admin" /> | ||||
|                             <FormControlLabel label="Read-only" control={<Radio />} value="read" /> | ||||
|                         </RadioGroup> | ||||
|                     </FormControl> | ||||
|                 </DialogContent> | ||||
|             </form> | ||||
|             <UserForm title="Add new user" data={data} setData={setData} roles={roles} submit={submit} error={error} /> | ||||
|         </Dialogue> | ||||
|     ); | ||||
| } | ||||
| @ -143,6 +58,7 @@ AddUser.propTypes = { | ||||
|     closeDialog: PropTypes.func.isRequired, | ||||
|     addUser: PropTypes.func.isRequired, | ||||
|     validatePassword: PropTypes.func.isRequired, | ||||
|     roles: PropTypes.array.isRequired, | ||||
| }; | ||||
| 
 | ||||
| export default AddUser; | ||||
|  | ||||
| @ -4,6 +4,7 @@ import { TextField, DialogTitle, DialogContent } from '@material-ui/core'; | ||||
| import { trim } from '../../../component/common/util'; | ||||
| import { modalStyles } from './util'; | ||||
| import Dialogue from '../../../component/common/Dialogue/Dialogue'; | ||||
| import commonStyles from '../../../component/common/common.module.scss'; | ||||
| 
 | ||||
| function ChangePassword({ showDialog, closeDialog, changePassword, validatePassword, user = {} }) { | ||||
|     const [data, setData] = useState({}); | ||||
| @ -67,11 +68,14 @@ function ChangePassword({ showDialog, closeDialog, changePassword, validatePassw | ||||
|         > | ||||
|             <form onSubmit={submit}> | ||||
|                 <DialogTitle>Update password</DialogTitle> | ||||
|                 <DialogContent> | ||||
|                 <DialogContent | ||||
|                     className={commonStyles.contentSpacing} | ||||
|                     style={{ display: 'flex', flexDirection: 'column' }} | ||||
|                 > | ||||
|                     <p>User: {user.username || user.email}</p> | ||||
|                     <p style={{ color: 'red' }}>{error.general}</p> | ||||
|                     <TextField | ||||
|                         label="New passord" | ||||
|                         label="New password" | ||||
|                         name="password" | ||||
|                         type="password" | ||||
|                         value={data.password} | ||||
| @ -83,7 +87,7 @@ function ChangePassword({ showDialog, closeDialog, changePassword, validatePassw | ||||
|                         size="small" | ||||
|                     /> | ||||
|                     <TextField | ||||
|                         label="Confirm passord" | ||||
|                         label="Confirm password" | ||||
|                         name="confirm" | ||||
|                         type="password" | ||||
|                         value={data.confirm} | ||||
|  | ||||
| @ -1,99 +1,60 @@ | ||||
| import React, { useState } from 'react'; | ||||
| import React, { useState, useEffect } from 'react'; | ||||
| import PropTypes from 'prop-types'; | ||||
| import { | ||||
|     Button, | ||||
|     TextField, | ||||
|     DialogTitle, | ||||
|     DialogContent, | ||||
|     DialogActions, | ||||
|     RadioGroup, | ||||
|     Radio, | ||||
|     Modal, | ||||
| } from '@material-ui/core'; | ||||
| import { showPermissions, modalStyles } from './util'; | ||||
| import Dialogue from '../../../component/common/Dialogue'; | ||||
| import UserForm from './user-form'; | ||||
| 
 | ||||
| function AddUser({ user, showDialog, closeDialog, updateUser }) { | ||||
|     const [data, setData] = useState(user); | ||||
| function AddUser({ user = {}, showDialog, closeDialog, updateUser, roles }) { | ||||
|     const [data, setData] = useState({}); | ||||
|     const [error, setError] = useState({}); | ||||
| 
 | ||||
|     useEffect(() => { | ||||
|         setData({ | ||||
|             id: user.id, | ||||
|             email: user.email || '', | ||||
|             rootRole: user.rootRole || '', | ||||
|             name: user.name || '', | ||||
|         }); | ||||
|     }, [user]) | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|     if (!user) { | ||||
|         return null; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     const updateField = e => { | ||||
|         setData({ | ||||
|             ...data, | ||||
|             [e.target.name]: e.target.value, | ||||
|         }); | ||||
|     }; | ||||
| 
 | ||||
|     const submit = async e => { | ||||
|         e.preventDefault(); | ||||
| 
 | ||||
|         try { | ||||
|             await updateUser(data); | ||||
|             setData({}); | ||||
|             setError({}); | ||||
|             closeDialog(); | ||||
|         } catch (error) { | ||||
|             setError({ general: 'Could not create user' }); | ||||
|             setError({ general: 'Could not update user' }); | ||||
|         } | ||||
|     }; | ||||
| 
 | ||||
|     const onCancel = e => { | ||||
|         e.preventDefault(); | ||||
|         setData({}); | ||||
|         setError({}); | ||||
|         closeDialog(); | ||||
|     }; | ||||
| 
 | ||||
|     const userType = data.userType || showPermissions(user.permissions); | ||||
| 
 | ||||
|     return ( | ||||
|         <Modal open={showDialog} style={modalStyles} onClose={onCancel}> | ||||
|             <form onSubmit={submit}> | ||||
|                 <DialogTitle>Edit user</DialogTitle> | ||||
| 
 | ||||
|                 <DialogContent> | ||||
|                     <p>{error.general}</p> | ||||
|                     <TextField | ||||
|                         label="Full name" | ||||
|                         name="name" | ||||
|                         value={data.name} | ||||
|                         error={error.name} | ||||
|                         type="name" | ||||
|                         onChange={updateField} | ||||
|                     /> | ||||
|                     <TextField | ||||
|                         label="Email" | ||||
|                         name="email" | ||||
|                         contentEditable="false" | ||||
|                         editable="false" | ||||
|                         readOnly | ||||
|                         value={data.email} | ||||
|                         type="email" | ||||
|                     /> | ||||
|                     <br /> | ||||
|                     <br /> | ||||
|                     <RadioGroup name="userType" value={userType} onChange={updateField} childContainer="div"> | ||||
|                         <Radio value="regular" ripple> | ||||
|                             Regular user | ||||
|                         </Radio> | ||||
|                         <Radio value="admin" ripple> | ||||
|                             Admin user | ||||
|                         </Radio> | ||||
|                         <Radio value="read" ripple> | ||||
|                             Read only | ||||
|                         </Radio> | ||||
|                     </RadioGroup> | ||||
|                 </DialogContent> | ||||
|                 <DialogActions> | ||||
|                     <Button raised colored type="submit"> | ||||
|                         Update | ||||
|                     </Button> | ||||
|                     <Button type="button" onClick={onCancel}> | ||||
|                         Cancel | ||||
|                     </Button> | ||||
|                 </DialogActions> | ||||
|             </form> | ||||
|         </Modal> | ||||
|         <Dialogue | ||||
|             onClick={e => { | ||||
|                 submit(e); | ||||
|             }} | ||||
|             open={showDialog} | ||||
|             onClose={onCancel} | ||||
|             primaryButtonText="Update user" | ||||
|             secondaryButtonText="Cancel" | ||||
|             fullWidth | ||||
|         > | ||||
|             <UserForm title="Update user" data={data} setData={setData} roles={roles} submit={submit} error={error} /> | ||||
|         </Dialogue> | ||||
|     ); | ||||
| } | ||||
| 
 | ||||
| @ -102,6 +63,7 @@ AddUser.propTypes = { | ||||
|     closeDialog: PropTypes.func.isRequired, | ||||
|     updateUser: PropTypes.func.isRequired, | ||||
|     user: PropTypes.object, | ||||
|     roles: PropTypes.array.isRequired, | ||||
| }; | ||||
| 
 | ||||
| export default AddUser; | ||||
|  | ||||
							
								
								
									
										103
									
								
								frontend/src/page/admin/users/user-form.jsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								frontend/src/page/admin/users/user-form.jsx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,103 @@ | ||||
| import React from 'react'; | ||||
| import PropTypes from 'prop-types'; | ||||
| import { | ||||
|     TextField, | ||||
|     DialogTitle, | ||||
|     DialogContent, | ||||
|     RadioGroup, | ||||
|     Radio, | ||||
|     FormControl, | ||||
|     FormLabel, | ||||
|     FormControlLabel, | ||||
| } from '@material-ui/core'; | ||||
| import commonStyles from '../../../component/common/common.module.scss'; | ||||
| import { trim } from '../../../component/common/util'; | ||||
| 
 | ||||
| function UserForm({ title, submit, data, error, setData, roles }) { | ||||
|     const updateField = e => { | ||||
|         setData({ | ||||
|             ...data, | ||||
|             [e.target.name]: e.target.value, | ||||
|         }); | ||||
|     }; | ||||
| 
 | ||||
|     const updateFieldWithTrim = e => { | ||||
|         setData({ | ||||
|             ...data, | ||||
|             [e.target.name]: trim(e.target.value), | ||||
|         }); | ||||
|     }; | ||||
| 
 | ||||
|     const updateNumberField = e => { | ||||
|         setData({ | ||||
|             ...data, | ||||
|             [e.target.name]: +e.target.value, | ||||
|         }); | ||||
|     }; | ||||
| 
 | ||||
|     return ( | ||||
|         <form onSubmit={submit}> | ||||
|             <DialogTitle>{title}</DialogTitle> | ||||
| 
 | ||||
|             <DialogContent className={commonStyles.contentSpacing} style={{ display: 'flex', flexDirection: 'column' }}> | ||||
|                 <p style={{ color: 'red' }}>{error.general}</p> | ||||
|                 <TextField | ||||
|                     label="Full name" | ||||
|                     name="name" | ||||
|                     value={data.name || ''} | ||||
|                     error={error.name !== undefined} | ||||
|                     helperText={error.name} | ||||
|                     type="name" | ||||
|                     variant="outlined" | ||||
|                     size="small" | ||||
|                     onChange={updateField} | ||||
|                 /> | ||||
|                 <TextField | ||||
|                     label="Email" | ||||
|                     name="email" | ||||
|                     required | ||||
|                     value={data.email || ''} | ||||
|                     error={error.email !== undefined} | ||||
|                     helperText={error.email} | ||||
|                     variant="outlined" | ||||
|                     size="small" | ||||
|                     type="email" | ||||
|                     onChange={updateFieldWithTrim} | ||||
|                 /> | ||||
|                 <br /> | ||||
|                 <br /> | ||||
|                 <FormControl> | ||||
|                     <FormLabel component="legend">Role</FormLabel> | ||||
|                     <RadioGroup name="rootRole" value={data.rootRole || ''} onChange={updateNumberField}> | ||||
|                         {roles.map(role => ( | ||||
|                             <FormControlLabel | ||||
|                                 key={`role-${role.id}`} | ||||
|                                 labelPlacement="end" | ||||
|                                 style={{ margin: '3px 0', border: '1px solid #EFEFEF' }} | ||||
|                                 label={ | ||||
|                                     <div> | ||||
|                                         <strong>{role.name}</strong> | ||||
|                                         <p>{role.description}</p> | ||||
|                                     </div> | ||||
|                                 } | ||||
|                                 control={<Radio />} | ||||
|                                 value={role.id} | ||||
|                             /> | ||||
|                         ))} | ||||
|                     </RadioGroup> | ||||
|                 </FormControl> | ||||
|             </DialogContent> | ||||
|         </form> | ||||
|     ); | ||||
| } | ||||
| 
 | ||||
| UserForm.propTypes = { | ||||
|     title: PropTypes.string.isRequired, | ||||
|     data: PropTypes.object.isRequired, | ||||
|     error: PropTypes.object.isRequired, | ||||
|     submit: PropTypes.func.isRequired, | ||||
|     setData: PropTypes.func.isRequired, | ||||
|     roles: PropTypes.array.isRequired, | ||||
| }; | ||||
| 
 | ||||
| export default UserForm; | ||||
| @ -1,13 +1,3 @@ | ||||
| export const showPermissions = permissions => { | ||||
|     if (!permissions || permissions.length === 0) { | ||||
|         return 'read'; | ||||
|     } else if (permissions.includes('ADMIN')) { | ||||
|         return 'admin'; | ||||
|     } else { | ||||
|         return 'regular'; | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| export const modalStyles = { | ||||
|     overlay: { | ||||
|         position: 'absolute', | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| import api from './api'; | ||||
| import { dispatchError } from '../util'; | ||||
| export const START_FETCH_USERS = 'START_FETCH_USERS'; | ||||
| export const RECIEVE_USERS = 'RECIEVE_USERS'; | ||||
| export const RECEIVE_USERS = 'RECEIVE_USERS'; | ||||
| export const ERROR_FETCH_USERS = 'ERROR_FETCH_USERS'; | ||||
| export const REMOVE_USER = 'REMOVE_USER'; | ||||
| export const REMOVE_USER_ERROR = 'REMOVE_USER_ERROR'; | ||||
| @ -15,7 +15,7 @@ export const VALIDATE_PASSWORD_ERROR = 'VALIDATE_PASSWORD_ERROR'; | ||||
| const debug = require('debug')('unleash:e-user-admin-actions'); | ||||
| 
 | ||||
| const gotUsers = value => ({ | ||||
|     type: RECIEVE_USERS, | ||||
|     type: RECEIVE_USERS, | ||||
|     value, | ||||
| }); | ||||
| 
 | ||||
|  | ||||
| @ -1,10 +1,10 @@ | ||||
| import { List } from 'immutable'; | ||||
| import { RECIEVE_USERS, ADD_USER, REMOVE_USER, UPDATE_USER } from './actions'; | ||||
| import { RECEIVE_USERS, ADD_USER, REMOVE_USER, UPDATE_USER } from './actions'; | ||||
| 
 | ||||
| const store = (state = new List(), action) => { | ||||
|     switch (action.type) { | ||||
|         case RECIEVE_USERS: | ||||
|             return new List(action.value); | ||||
|         case RECEIVE_USERS: | ||||
|             return new List(action.value.users); | ||||
|         case ADD_USER: | ||||
|             return state.push(action.user); | ||||
|         case UPDATE_USER: | ||||
|  | ||||
							
								
								
									
										19
									
								
								frontend/src/store/e-user-admin/roles-store.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								frontend/src/store/e-user-admin/roles-store.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | ||||
| import { List, fromJS } from 'immutable'; | ||||
| import { RECEIVE_USERS } from './actions'; | ||||
| 
 | ||||
| function getInitialState() { | ||||
|     return fromJS({ | ||||
|         root: [], | ||||
|     }); | ||||
| } | ||||
| 
 | ||||
| const store = (state = getInitialState(), action) => { | ||||
|     switch (action.type) { | ||||
|         case RECEIVE_USERS: | ||||
|             return state.set('root', new List(action.value.rootRoles)); | ||||
|         default: | ||||
|             return state; | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| export default store; | ||||
| @ -17,6 +17,7 @@ import context from './context'; | ||||
| import projects from './project'; | ||||
| import addons from './addons'; | ||||
| import userAdmin from './e-user-admin'; | ||||
| import roles from './e-user-admin/roles-store'; | ||||
| import apiAdmin from './e-api-admin'; | ||||
| import authAdmin from './e-admin-auth'; | ||||
| import apiCalls from './api-calls'; | ||||
| @ -40,6 +41,7 @@ const unleashStore = combineReducers({ | ||||
|     projects, | ||||
|     addons, | ||||
|     userAdmin, | ||||
|     roles, | ||||
|     apiAdmin, | ||||
|     authAdmin, | ||||
|     apiCalls, | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user