Advertisement
Guest User

Untitled

a guest
Apr 6th, 2020
488
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import React, { Component, ChangeEvent, KeyboardEvent, CSSProperties } from 'react';
  2. import { WithStyles, CircularProgress, Snackbar } from '@material-ui/core';
  3. import classNames from 'classnames';
  4. import Button from '@material-ui/core/Button';
  5. import Paper from '@material-ui/core/Paper';
  6. import TextField from '@material-ui/core/TextField';
  7. import Scrollbars from 'react-custom-scrollbars';
  8. import { Theme, withStyles } from '@material-ui/core/styles';
  9. import { BigAvatar } from 'src/Component/Avatar';
  10. import { Query, MutationFn, Mutation } from 'react-apollo';
  11. import { GET_ME } from 'src/Graphql/User/query';
  12. import UserInterface from 'src/Interface/UserInterface';
  13. import { EDIT_ACCOUNT, CREATE_PRESIGNED_URL } from 'src/Graphql/Authentication/mutation';
  14. import { DataProxy } from 'apollo-cache';
  15. import axios from 'axios';
  16. import mime from 'mime-types';
  17. import uuid from 'uuid/v4';
  18. import { ReturnLink } from '../All/ReturnLink';
  19. import { REMOVE_USER } from 'src/Graphql/User/mutations';
  20.  
  21.  
  22. const styles = (theme: Theme): Record<string, CSSProperties | Record<string, CSSProperties>> => ({
  23.   col: {
  24.     boxSizing: 'border-box' as 'border-box',
  25.     display: 'flex',
  26.     flex: '0 1 auto',
  27.     flexDirection: 'column' as 'column',
  28.     msFlex: '0 1 auto',
  29.     WebkitFlex: '0 1 auto',
  30.   },
  31.   row: {
  32.     boxSizing: 'border-box' as 'border-box',
  33.     display: 'flex',
  34.     flex: '0 1 auto',
  35.     flexDirection: 'row' as 'row',
  36.     msFlex: '0 1 auto',
  37.     WebkitFlex: '0 1 auto',
  38.   },
  39.   justifyEnd: {
  40.     justifyContent: 'flex-end',
  41.     padding: '0 44px 44px',
  42.   },
  43.   submitButtonWrapper: {
  44.     marginTop: 0,
  45.   },
  46.   justifyCenter: {
  47.     justifyContent: 'center',
  48.   },
  49.   contentEditAccount: {
  50.     marginTop: 28,
  51.   },
  52.   paper: {
  53.     '@media (max-width: 600px)': {
  54.       width: '100%',
  55.     },
  56.     width: 454,
  57.     margin: '0 auto',
  58.     boxShadow:
  59.       ' 0px 0px 1px 0px rgba(0,0,0,0.2), 0px 0px 0px 0px rgba(0,0,0,.1), 0px 0px 0px 0px rgba(0,0,0,0.12)',
  60.     borderRadius: 0,
  61.     paddingBottom: 20,
  62.   },
  63.   inputAvatar: {
  64.     display: 'none',
  65.   },
  66.   wrapper: {
  67.     position: 'relative' as 'relative',
  68.     marginTop: 20,
  69.   },
  70.   buttonProgress: {
  71.     color: theme.customPalette.primary.main,
  72.     position: 'absolute' as 'absolute',
  73.     top: '50%',
  74.     left: '50%',
  75.     marginTop: -8,
  76.     marginLeft: -12,
  77.   },
  78.   contentForm: {
  79.     margin: '14px 0 24px',
  80.     padding: '0 44px',
  81.     '@media (max-width: 600px)': {
  82.       padding: '0 24px',
  83.     },
  84.   },
  85.   textField: {
  86.     width: '100%',
  87.     margin: '20px 0 8px',
  88.     fontWeight: 500,
  89.     fontSize: 60,
  90.   },
  91.   actionButton: {
  92.     color: 'white',
  93.   },
  94.   button: {
  95.     margin: '0px 4px',
  96.     padding: '14px 53px',
  97.     textTransform: 'capitalize' as 'capitalize',
  98.     fontWeight: 400,
  99.     fontSize: 11,
  100.   },
  101.   input: {
  102.     fontSize: 60,
  103.   },
  104.   title: {
  105.     fontSize: 24,
  106.     marginTop: 28,
  107.     fontWeight: 400,
  108.   },
  109.   buttonSupressEmail: {
  110.     backgroundColor: 'red',
  111.   },
  112. });
  113.  
  114. interface EditAccountProps {
  115.   classes: any;
  116. }
  117. interface EditAccountStates {
  118.  
  119.   position?: string;
  120.   isLoading: boolean;
  121.   snackBarMessage?: string;
  122.   username?: string;
  123.   avatar?: string;
  124.   avatarFile?: File;
  125.   avatarName?: string;
  126. }
  127.  
  128. class EditAccount extends Component<EditAccountProps & WithStyles<any>, EditAccountStates> {
  129.   inputFile: any;
  130.   oldUser?: UserInterface;
  131.  
  132.   constructor(props: any) {
  133.     super(props);
  134.     this.state = {
  135.       isLoading: false,
  136.     };
  137.   }
  138.  
  139.  
  140.  
  141.   handleCloseSnackbar = () => {
  142.     this.setState({ snackBarMessage: undefined });
  143.   };
  144.  
  145.   preventDefaultKeyPress = (evt: KeyboardEvent<any>) => {
  146.     evt.preventDefault();
  147.   };
  148.  
  149.   handleChangeInput = (evt: ChangeEvent<HTMLInputElement>) => {
  150.     this.setState({ ...this.state, [evt.target.id]: evt.target.value });
  151.   };
  152.  
  153.   showSnackMessage = (snackBarMessage: string) => {
  154.     this.setState({ snackBarMessage });
  155.   };
  156.  
  157.   trigClickInInputFile = () => {
  158.     this.inputFile.click();
  159.   };
  160.  
  161.   handleDeleteAccount = async (
  162.     mutationDeleteAccount: MutationFn<any, any>
  163.   ) => {
  164.     if (confirm('Do you really want to delete your account?')) {
  165.       if (!this.oldUser) {
  166.         return;
  167.       }
  168.  
  169.       this.setState({ isLoading: true });
  170.  
  171.       mutationDeleteAccount({
  172.         variables: {
  173.           id: this.oldUser.id,
  174.         },
  175.       })
  176.         .then(() => {
  177.           this.showSnackMessage('Successfully modified');
  178.         })
  179.         .catch(err => {
  180.           this.showSnackMessage('An error occurred');
  181.         })
  182.         .finally(() => {
  183.           this.setState({ isLoading: false });
  184.         });
  185.  
  186.     }
  187.   }
  188.  
  189.   handleAvatarChange = (e: ChangeEvent<HTMLInputElement>) => {
  190.     e.stopPropagation();
  191.  
  192.     const files = e.target.files;
  193.     if (files && files[0]) {
  194.       const reader = new FileReader();
  195.       reader.onload = () => {
  196.         const avatarFile = files[0];
  197.         this.setState({
  198.           avatar: reader.result as string,
  199.           avatarFile,
  200.           avatarName: `${uuid().replace(/-/g, '')}.${mime.extension(avatarFile.type)}`,
  201.         });
  202.       };
  203.  
  204.       reader.readAsDataURL(files[0]);
  205.     }
  206.   };
  207.  
  208.   handleSubmit = async (
  209.     mutationEditAccount: MutationFn<any, any>,
  210.     mutationCreatePresignedUrl: MutationFn<any, any>,
  211.   ) => {
  212.     if (!this.oldUser) {
  213.       return;
  214.     }
  215.  
  216.     const { position, username, avatarFile, avatarName } = this.state;
  217.  
  218.     if (
  219.       (position !== undefined && !position.trim()) ||
  220.       (username !== undefined && !username.trim())
  221.     ) {
  222.       return;
  223.     }
  224.  
  225.     this.setState({ isLoading: true });
  226.  
  227.     let signedUrl = null;
  228.     if (avatarName) {
  229.       await mutationCreatePresignedUrl({ variables: { filePath: avatarName } })
  230.         .then((rep: any) => (signedUrl = rep.data.createPresignedPutUrl))
  231.         .catch(() => this.showSnackMessage('An error occurred'));
  232.     }
  233.  
  234.     if (signedUrl && avatarFile) {
  235.       const file = avatarFile;
  236.       await axios
  237.         .put(signedUrl, avatarFile, {
  238.           headers: { 'Content-Type': file.type },
  239.         })
  240.         .catch(() => this.showSnackMessage('An error occurred'));
  241.     }
  242.  
  243.     const avatar = avatarName || null;
  244.     mutationEditAccount({
  245.       variables: {
  246.         username: username || this.oldUser.username,
  247.         avatar,
  248.         email: this.oldUser.email,
  249.         position: position || this.oldUser.position,
  250.       },
  251.     })
  252.       .then(() => {
  253.         this.showSnackMessage('Successfully modified');
  254.       })
  255.       .catch(err => {
  256.         this.showSnackMessage('An error occurred');
  257.       })
  258.       .finally(() => {
  259.         this.setState({ isLoading: false });
  260.       });
  261.   };
  262.  
  263.   updateCache = (cache: DataProxy, editAccountResult: any) => {
  264.     const data = cache.readQuery<{ me: UserInterface }>({ query: GET_ME });
  265.     if (data) {
  266.       const newUser: UserInterface = editAccountResult.data.editAccount;
  267.       data.me = { ...data.me, ...newUser };
  268.       cache.writeQuery({
  269.         query: GET_ME,
  270.         data,
  271.       });
  272.     }
  273.   };
  274.  
  275.   handleKeyPress = (
  276.     mutationEditAccount: MutationFn<any, any>,
  277.     mutationCreatePresignedUrl: MutationFn<any, any>,
  278.     evt: KeyboardEvent<HTMLFormElement>,
  279.   ) => {
  280.     if (evt.key === 'Enter') {
  281.       this.handleSubmit(mutationEditAccount, mutationCreatePresignedUrl);
  282.     }
  283.   };
  284.  
  285.   render() {
  286.     const { classes } = this.props;
  287.     const { isLoading, snackBarMessage, position, username, avatar } = this.state;
  288.     return (
  289.       <Query query={GET_ME}>
  290.         {({ data, loading, error }) => {
  291.           if (loading) {
  292.             return 'Loading...';
  293.           }
  294.           if (error) {
  295.             return 'Error';
  296.           }
  297.           this.oldUser = data.me;
  298.           return (
  299.             <Mutation mutation={CREATE_PRESIGNED_URL}>
  300.               {mutationCreatePresignedUrl => (
  301.                 <Mutation mutation={EDIT_ACCOUNT} update={this.updateCache}>
  302.                   {mutationEditAccount => (
  303.                     <Scrollbars
  304.                       style={{ height: '100vh' }}
  305.                       autoHide={true}
  306.                       autoHideTimeout={500}
  307.                       autoHideDuration={50}
  308.                     >
  309.                       <Snackbar
  310.                         open={!!snackBarMessage}
  311.                         message={snackBarMessage}
  312.                         onClose={this.handleCloseSnackbar}
  313.                         autoHideDuration={5000}
  314.                       />
  315.                       <div className={classes.contentEditAccount}>
  316.                         <ReturnLink />
  317.                         <Paper className={classes.paper} elevation={1}>
  318.                           <div
  319.                             className={classNames(
  320.                               classes.row,
  321.                               classes.submitButtonWrapper,
  322.                               classes.justifyCenter,
  323.                             )}
  324.                           >
  325.                             <div className={classes.wrapper}>
  326.                               <Button
  327.                                 className={classNames(classes.actionButton, classes.button)}
  328.                                 variant="contained"
  329.                                 color="primary"
  330.                                 id="btn-save"
  331.                                 onClick={this.handleSubmit.bind(
  332.                                   this,
  333.                                   mutationEditAccount,
  334.                                   mutationCreatePresignedUrl,
  335.                                 )}
  336.                                 disabled={isLoading}
  337.                               >
  338.                                 Save
  339.                               </Button>
  340.                               {isLoading && (
  341.                                 <CircularProgress size={21} className={classes.buttonProgress} />
  342.                               )}
  343.                             </div>
  344.                           </div>
  345.                           <div
  346.                             className={classNames(
  347.                               classes.row,
  348.                               classes.avatarInput,
  349.                               classes.justifyCenter,
  350.                             )}
  351.                           >
  352.                             <input
  353.                               accept="image/*"
  354.                               className={classes.inputAvatar}
  355.                               id="icon-button-avatar"
  356.                               type="file"
  357.                               ref={ref => {
  358.                                 this.inputFile = ref;
  359.                               }}
  360.                               onChange={this.handleAvatarChange}
  361.                             />
  362.                             <label htmlFor="icon-button-file">
  363.                               <BigAvatar
  364.                                 onClick={this.trigClickInInputFile}
  365.                                 disabled={isLoading}
  366.                                 alt={this.oldUser!.username || undefined}
  367.                                 src={avatar || this.oldUser!.avatar}
  368.                               />
  369.                             </label>
  370.                           </div>
  371.                           <form
  372.                             className={classes.contentForm}
  373.                             onKeyPress={this.handleKeyPress.bind(
  374.                               this,
  375.                               mutationEditAccount,
  376.                               mutationCreatePresignedUrl,
  377.                             )}
  378.                           >
  379.                             <TextField
  380.                               autoFocus={true}
  381.                               className={classNames(classes.textField, 'Edit-account-input')}
  382.                               margin="dense"
  383.                               id="username"
  384.                               label="Username"
  385.                               value={
  386.                                 username !== undefined ? username : this.oldUser!.username || ''
  387.                               }
  388.                               onChange={this.handleChangeInput}
  389.                               error={username !== undefined && !username.trim()}
  390.                               fullWidth={true}
  391.                               autoComplete="off"
  392.                             />
  393.                             <TextField
  394.                               className={classNames(classes.textField, 'Edit-account-input')}
  395.                               margin="dense"
  396.                               id="position"
  397.                               color="primary"
  398.                               label="Function"
  399.                               onChange={this.handleChangeInput}
  400.                               value={
  401.                                 (position !== undefined ? position : this.oldUser!.position) || ''
  402.                               }
  403.                               error={position !== undefined && !position.trim()}
  404.                               fullWidth={true}
  405.                               autoComplete="off"
  406.                             />
  407.                             <TextField
  408.                               className={classNames(classes.textField, 'Edit-account-input')}
  409.                               margin="dense"
  410.                               id="email"
  411.                               color="primary"
  412.                               label="Email"
  413.                               type="email"
  414.                               value={this.oldUser!.email || ''}
  415.                               fullWidth={true}
  416.                               autoComplete="off"
  417.                               disabled={true}
  418.                             />
  419.                             <div style={{ flex: 1 }} />
  420.                             <Mutation mutation={REMOVE_USER} >
  421.                               {mutationDeleteAccount => (
  422.                                 <Button
  423.                                   className={classNames(classes.actionButton)}
  424.                                   variant="flat"
  425.                                   size="small"
  426.                                   onClick={this.handleDeleteAccount.bind(
  427.                                     this,
  428.                                     mutationDeleteAccount,
  429.                                   )}
  430.                                   style={{ backgroundColor: 'red' }}
  431.                                   id="btn-save"
  432.  
  433.                                   disabled={isLoading}
  434.                                 >
  435.                                   Delete Account
  436.                                 </Button>
  437.                               )}
  438.                             </Mutation>
  439.                           </form>
  440.  
  441.  
  442.                         </Paper>
  443.                       </div>
  444.                     </Scrollbars>
  445.                   )}
  446.                 </Mutation>
  447.               )}
  448.             </Mutation>
  449.           );
  450.         }}
  451.       </Query>
  452.     );
  453.   }
  454. }
  455.  
  456. export default withStyles(styles as any)(EditAccount);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement