235 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			235 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| import React, { useEffect, useState } from 'react';
 | |
| import Admin from 'shared/components/Admin';
 | |
| import Select from 'shared/components/Select';
 | |
| import GlobalTopNavbar from 'App/TopNavbar';
 | |
| import {
 | |
|   useUsersQuery,
 | |
|   useDeleteUserAccountMutation,
 | |
|   useCreateUserAccountMutation,
 | |
|   UsersDocument,
 | |
|   UsersQuery,
 | |
| } from 'shared/generated/graphql';
 | |
| import Input from 'shared/components/Input';
 | |
| import styled from 'styled-components';
 | |
| import Button from 'shared/components/Button';
 | |
| import { useForm } from 'react-hook-form';
 | |
| import { usePopup, Popup } from 'shared/components/PopupMenu';
 | |
| import produce from 'immer';
 | |
| import updateApolloCache from 'shared/utils/cache';
 | |
| 
 | |
| const DeleteUserWrapper = styled.div`
 | |
|   display: flex;
 | |
|   flex-direction: column;
 | |
| `;
 | |
| 
 | |
| const DeleteUserDescription = styled.p`
 | |
|   font-size: 14px;
 | |
| `;
 | |
| 
 | |
| const DeleteUserButton = styled(Button)`
 | |
|   margin-top: 6px;
 | |
|   padding: 6px 12px;
 | |
|   width: 100%;
 | |
| `;
 | |
| 
 | |
| type DeleteUserPopupProps = {
 | |
|   onDeleteUser: () => void;
 | |
| };
 | |
| const DeleteUserPopup: React.FC<DeleteUserPopupProps> = ({ onDeleteUser }) => {
 | |
|   return (
 | |
|     <DeleteUserWrapper>
 | |
|       <DeleteUserDescription>Deleting this user will remove all user related data.</DeleteUserDescription>
 | |
|       <DeleteUserButton onClick={() => onDeleteUser()} color="danger">
 | |
|         Delete user
 | |
|       </DeleteUserButton>
 | |
|     </DeleteUserWrapper>
 | |
|   );
 | |
| };
 | |
| type CreateUserData = {
 | |
|   email: string;
 | |
|   username: string;
 | |
|   fullName: string;
 | |
|   initials: string;
 | |
|   password: string;
 | |
|   roleCode: string;
 | |
| };
 | |
| const CreateUserForm = styled.form`
 | |
|   display: flex;
 | |
|   flex-direction: column;
 | |
| `;
 | |
| const CreateUserButton = styled(Button)`
 | |
|   margin-top: 8px;
 | |
|   padding: 6px 12px;
 | |
|   width: 100%;
 | |
| `;
 | |
| 
 | |
| const AddUserInput = styled(Input)`
 | |
|   margin-bottom: 8px;
 | |
| `;
 | |
| 
 | |
| const InputError = styled.span`
 | |
|   color: rgba(${props => props.theme.colors.danger});
 | |
|   font-size: 12px;
 | |
| `;
 | |
| 
 | |
| type AddUserPopupProps = {
 | |
|   onAddUser: (user: CreateUserData) => void;
 | |
| };
 | |
| 
 | |
| const AddUserPopup: React.FC<AddUserPopupProps> = ({ onAddUser }) => {
 | |
|   const { register, handleSubmit, errors, setValue } = useForm<CreateUserData>();
 | |
|   const [role, setRole] = useState<string | null>(null);
 | |
|   register({ name: 'roleCode' }, { required: true });
 | |
| 
 | |
|   const createUser = (data: CreateUserData) => {
 | |
|     onAddUser(data);
 | |
|   };
 | |
|   return (
 | |
|     <CreateUserForm onSubmit={handleSubmit(createUser)}>
 | |
|       <AddUserInput
 | |
|         floatingLabel
 | |
|         width="100%"
 | |
|         label="Full Name"
 | |
|         id="fullName"
 | |
|         name="fullName"
 | |
|         variant="alternate"
 | |
|         ref={register({ required: 'Full name is required' })}
 | |
|       />
 | |
|       {errors.fullName && <InputError>{errors.fullName.message}</InputError>}
 | |
|       <AddUserInput
 | |
|         floatingLabel
 | |
|         width="100%"
 | |
|         label="Email"
 | |
|         id="email"
 | |
|         name="email"
 | |
|         variant="alternate"
 | |
|         ref={register({ required: 'Email is required' })}
 | |
|       />
 | |
|       <Select
 | |
|         label="Role"
 | |
|         value={role}
 | |
|         options={[
 | |
|           { label: 'Admin', value: 'admin' },
 | |
|           { label: 'Member', value: 'member' },
 | |
|         ]}
 | |
|         onChange={newRole => {
 | |
|           setRole(newRole);
 | |
|           setValue('roleCode', newRole.value);
 | |
|         }}
 | |
|       />
 | |
|       {errors.email && <InputError>{errors.email.message}</InputError>}
 | |
|       <AddUserInput
 | |
|         floatingLabel
 | |
|         width="100%"
 | |
|         label="Username"
 | |
|         id="username"
 | |
|         name="username"
 | |
|         variant="alternate"
 | |
|         ref={register({ required: 'Username is required' })}
 | |
|       />
 | |
|       {errors.username && <InputError>{errors.username.message}</InputError>}
 | |
|       <AddUserInput
 | |
|         floatingLabel
 | |
|         width="100%"
 | |
|         label="Initials"
 | |
|         id="initials"
 | |
|         name="initials"
 | |
|         variant="alternate"
 | |
|         ref={register({ required: 'Initials is required' })}
 | |
|       />
 | |
|       {errors.initials && <InputError>{errors.initials.message}</InputError>}
 | |
|       <AddUserInput
 | |
|         floatingLabel
 | |
|         width="100%"
 | |
|         label="Password"
 | |
|         id="password"
 | |
|         name="password"
 | |
|         variant="alternate"
 | |
|         ref={register({ required: 'Password is required' })}
 | |
|       />
 | |
|       {errors.password && <InputError>{errors.password.message}</InputError>}
 | |
|       <CreateUserButton type="submit">Create</CreateUserButton>
 | |
|     </CreateUserForm>
 | |
|   );
 | |
| };
 | |
| 
 | |
| const AdminRoute = () => {
 | |
|   useEffect(() => {
 | |
|     document.title = 'Citadel | Admin';
 | |
|   }, []);
 | |
|   const { loading, data } = useUsersQuery();
 | |
|   const { showPopup, hidePopup } = usePopup();
 | |
|   const [deleteUser] = useDeleteUserAccountMutation({
 | |
|     update: (client, response) => {
 | |
|       updateApolloCache<UsersQuery>(client, UsersDocument, cache =>
 | |
|         produce(cache, draftCache => {
 | |
|           draftCache.users = cache.users.filter(u => u.id !== response.data.deleteUserAccount.userAccount.id);
 | |
|         }),
 | |
|       );
 | |
|     },
 | |
|   });
 | |
|   const [createUser] = useCreateUserAccountMutation({
 | |
|     update: (client, createData) => {
 | |
|       const cacheData: any = client.readQuery({
 | |
|         query: UsersDocument,
 | |
|       });
 | |
|       console.log(cacheData);
 | |
|       console.log(createData);
 | |
|       const newData = produce(cacheData, (draftState: any) => {
 | |
|         draftState.users = [...draftState.users, { ...createData.data.createUserAccount }];
 | |
|       });
 | |
| 
 | |
|       client.writeQuery({
 | |
|         query: UsersDocument,
 | |
|         data: {
 | |
|           ...newData,
 | |
|         },
 | |
|       });
 | |
|     },
 | |
|   });
 | |
|   if (loading) {
 | |
|     return <GlobalTopNavbar projectID={null} onSaveProjectName={() => {}} name={null} />;
 | |
|   }
 | |
|   if (data) {
 | |
|     return (
 | |
|       <>
 | |
|         <GlobalTopNavbar projectID={null} onSaveProjectName={() => {}} name={null} />
 | |
|         <Admin
 | |
|           initialTab={1}
 | |
|           users={data.users}
 | |
|           onInviteUser={() => {}}
 | |
|           onDeleteUser={($target, userID) => {
 | |
|             showPopup(
 | |
|               $target,
 | |
|               <Popup tab={0} title="Delete user?" onClose={() => hidePopup()}>
 | |
|                 <DeleteUserPopup
 | |
|                   onDeleteUser={() => {
 | |
|                     deleteUser({ variables: { userID } });
 | |
|                     hidePopup();
 | |
|                   }}
 | |
|                 />
 | |
|               </Popup>,
 | |
|             );
 | |
|           }}
 | |
|           onAddUser={$target => {
 | |
|             showPopup(
 | |
|               $target,
 | |
|               <Popup tab={0} title="Add member" onClose={() => hidePopup()}>
 | |
|                 <AddUserPopup
 | |
|                   onAddUser={user => {
 | |
|                     createUser({ variables: { ...user } });
 | |
|                     hidePopup();
 | |
|                   }}
 | |
|                 />
 | |
|               </Popup>,
 | |
|             );
 | |
|           }}
 | |
|         />
 | |
|       </>
 | |
|     );
 | |
|   }
 | |
|   return <span>error</span>;
 | |
| };
 | |
| 
 | |
| export default AdminRoute;
 |