SanderCokart

TagContext

Sep 10th, 2020 (edited)
95
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import React, {createContext} from 'react';
  2. import {withAlertContext} from './AlertContext';
  3. import axios from 'axios';
  4.  
  5. export const NewTagContext = createContext();
  6.  
  7. class NewTagContextProvider extends React.Component {
  8.     constructor(props) {
  9.         super(props);
  10.         this.state = {
  11.             tags:         null,
  12.             processing:   false,
  13.             read:         this.read.bind(this),
  14.             create:       this.create.bind(this),
  15.             delete:       this.delete.bind(this),
  16.             update:       this.update.bind(this),
  17.             resetTag:     this.resetTag.bind(this),
  18.             handleChange: this.handleChange.bind(this),
  19.         };
  20.     };
  21.  
  22.  
  23.     render() {
  24.         return (
  25.             <NewTagContext.Provider value={{
  26.                 ...this.state,
  27.             }}>
  28.                 {this.props.children}
  29.             </NewTagContext.Provider>
  30.         );
  31.     }
  32.  
  33.     /**
  34.      * Takes an array of tags and finds the highest number of the id's, adds +1 to it and returns that
  35.      * @param {[]} [array=this.state.tags] - array of tags
  36.      * @returns {number} - generated id
  37.      */
  38.     findHighestId(array = this.state.tags) {
  39.         let max = 0;
  40.         for (let i = 0, len = array.length; i < len; i++) {
  41.             if (array[i].id > max) max = array[i].id;
  42.         }
  43.         return max + 1;
  44.     }
  45.  
  46.     /**
  47.      * EDIT TAG HANDLER
  48.      * @param {object} oldTag - original tag
  49.      * @param {object} e - event
  50.      */
  51.     handleChange(oldTag, e) {
  52.         // find and replace
  53.         const TAGS_COPY = this.state.tags.slice();
  54.         const TAG_COPY = TAGS_COPY.find(tag => tag.id === oldTag.id);
  55.         TAG_COPY.name = e.target.value;
  56.         this.setState({tags: TAGS_COPY});
  57.     }
  58.  
  59.     /**
  60.      * TODO work out a better solution
  61.      * @param oldTag
  62.      */
  63.     resetTag(oldTag) {
  64.         //copy state
  65.         // const tags = [...this.state.tags];
  66.         //find tag in copy
  67.         let tag = this.state.tags.find(tag => tag.id === oldTag.id);
  68.         //replace new name to the old name
  69.         tag.name = oldTag.name;
  70.         //overwrite the state
  71.         // this.setState({
  72.         //     tags: tags,
  73.         // });
  74.     }
  75.  
  76.     /**
  77.      * @param {object} createdTag - a new tag created by the user
  78.      * @param {string} createdTag.name - name of the created tag
  79.      */
  80.     async create(createdTag) {
  81.         // INITIATE
  82.         if (this.state.processing) return;
  83.         else this.setState({processing: true});
  84.  
  85.         // PREPARATION START
  86.         const INITIAL_TAGS = this.state.tags.slice();
  87.         const RESET = () => this.setState({tags: INITIAL_TAGS, processing: false});
  88.         const {alertContext} = this.props;
  89.         // PREPARATION END
  90.  
  91.         if (INITIAL_TAGS)
  92.             try {
  93.                 // CLIENT OPTIMIZATION START
  94.                 const NEW_TAG_FROM_CLIENT_WITH_ID = {...createdTag, id: this.findHighestId()};
  95.                 this.setState({tags: this.state.tags.concat(NEW_TAG_FROM_CLIENT_WITH_ID)});
  96.                 // CLIENT OPTIMIZATION END
  97.  
  98.                 // REQUEST START
  99.                 const r = await axios.post('/api/tag/create', NEW_TAG_FROM_CLIENT_WITH_ID);
  100.                 const {alert: ALERT, tag: NEW_TAG_FROM_SERVER} = r.data;
  101.                 // REQUEST END
  102.  
  103.                 // PROCESS ALERT
  104.                 alertContext.setAlert(ALERT);
  105.  
  106.                 // SERVER SIDE ERROR CATCHER START
  107.                 if (ALERT.level !== 'success') {
  108.                     RESET();
  109.                     return;
  110.                 }
  111.                 // SERVER SIDE ERROR CATCHER END
  112.  
  113.                 // IF SERVER SIDE IS SUCCESSFUL
  114.  
  115.                 // CHECK IF SERVER DATA MATCHES CLIENT DATA START
  116.                 if (NEW_TAG_FROM_SERVER.id !== NEW_TAG_FROM_CLIENT_WITH_ID.id) {
  117.                     // CORRECT THE DATA
  118.                     this.setState((state) => {
  119.                         const TAGS = state.tags.slice();
  120.                         const TAG = TAGS.find(tag => tag.id === NEW_TAG_FROM_CLIENT_WITH_ID.id);
  121.                         TAG.id = NEW_TAG_FROM_SERVER.id;
  122.                         return {tags: TAGS, processing: false};
  123.                     });
  124.                 }
  125.                 // CHECK IF SERVER DATA MATCHES CLIENT DATA END
  126.  
  127.                 else {
  128.                     this.setState({processing: false});
  129.                 }
  130.  
  131.             } catch (e) {
  132.                 alertContext.setAlert({
  133.                     text:  [
  134.                         e,
  135.                         'Something went wrong while trying to create a tag.',
  136.                         'Check your internet connection to make sure you didn\'t lose it or perhaps our servers may be down for maintenance.',
  137.                     ],
  138.                     level: 'error',
  139.                 });
  140.                 RESET();
  141.             }
  142.     }
  143.  
  144.     /**
  145.      * Gets all tags from the database
  146.      * @returns {Promise<void>}
  147.      */
  148.     async read() {
  149.         // INITIATE
  150.         if (this.state.processing) return;
  151.         else this.setState({processing: true});
  152.  
  153.         // PREPARATION START
  154.         const {alertContext} = this.props;
  155.         // PREPARATION END
  156.  
  157.         try {
  158.             //REQUEST
  159.             const r = await axios.get('/api/tag/read');
  160.             //HANDLE REQUEST
  161.             this.setState({tags: r.data, processing: false});
  162.         } catch (e) {
  163.             //CLIENT SIDE ERROR START
  164.             alertContext.setAlert({
  165.                 text:  [
  166.                     e,
  167.                     'Something went wrong while trying to get the tags from the database.',
  168.                     'Check your internet connection to make sure you didn\'t lose it or perhaps our servers may be down for maintenance.',
  169.                 ],
  170.                 level: 'error',
  171.             });
  172.             this.setState({tags: [], processing: false});
  173.             //CLIENT SIDE ERROR END
  174.         }
  175.     }
  176.  
  177.     /**
  178.      * Updates a tag by replacing the name key of the tag object
  179.      * @param {object} originalTag
  180.      * @param {number} originalTag.id
  181.      * @param {string} originalTag.name
  182.      * @returns {Promise<void>}
  183.      */
  184.     async update(originalTag) {
  185.         // PREPARATION START
  186.         const INITIAL_TAGS = this.state.tags.slice();
  187.         const RESET = () => {this.setState({tags: INITIAL_TAGS, processing: false});};
  188.         const {alertContext} = this.props;
  189.         // PREPARATION END
  190.  
  191.         try {
  192.             // UPDATE CLIENT START
  193.             const TAG_COPY = INITIAL_TAGS.slice().find(tag => tag.id === originalTag.id);
  194.             if (TAG_COPY.name === originalTag.name) {
  195.                 alertContext.setAlert({text: 'There was no change to the tag.', level: 'info'});
  196.                 this.setState({processing: false});
  197.                 return;
  198.             }
  199.             // UPDATE CLIENT END
  200.  
  201.             // REQUEST START
  202.             const r = await axios.put('/api/tag/update/' + originalTag.id, TAG_COPY);
  203.             const {alert: ALERT} = r.data;
  204.             alertContext.setAlert(ALERT);
  205.             // REQUEST END
  206.  
  207.             // SERVER SIDE ERROR START
  208.             if (ALERT.level !== 'success')
  209.                 RESET();
  210.             else
  211.                 this.setState({processing: false});
  212.             // SERVER SIDE ERROR END
  213.         } catch (e) {
  214.             // CLIENT SIDE ERROR START
  215.             alertContext.setAlert({
  216.                 text:  [
  217.                     e,
  218.                     'Something went wrong while trying to update the tag.',
  219.                     'Check your internet connection to make sure you didn\'t lose it or perhaps our servers may be down for maintenance.',
  220.                 ],
  221.                 level: 'error',
  222.             });
  223.             RESET();
  224.             // CLIENT SIDE ERROR END
  225.         }
  226.     }
  227.  
  228.     /**
  229.      * Removes a tag from the state, in case it could not be removed from the database: undo
  230.      * @param {object} tag
  231.      * @param {number} tag.id
  232.      * @param {string} tag.name
  233.      */
  234.     async delete(tag) {
  235.         // INITIATE
  236.         if (this.state.processing) return;
  237.         else this.setState({processing: true});
  238.  
  239.         //PREPARATION START
  240.         const INITIAL_TAGS = this.state.tags.slice();
  241.         const RESET = () => {this.setState({tags: INITIAL_TAGS, processing: false});};
  242.         const {alertContext} = this.props;
  243.         //PREPARATION END
  244.  
  245.         try {
  246.             // DELETE ON CLIENT SIDE START
  247.             const FILTERED_TAGS = INITIAL_TAGS.slice().filter(initialTag => initialTag.id !== tag.id);
  248.             this.setState({tags: FILTERED_TAGS});
  249.             // DELETE ON CLIENT SIDE END
  250.  
  251.             // REQUEST START
  252.             const r = await axios.delete('/api/tag/delete/' + tag.id);
  253.             const {alert: ALERT} = r.data;
  254.             // REQUEST END
  255.  
  256.             // PROCESS ALERT
  257.             alertContext.setAlert(ALERT);
  258.  
  259.             // SERVER SIDE ERROR START
  260.             if (ALERT.level !== 'success')
  261.                 RESET();
  262.             else
  263.                 this.setState({processing: false});
  264.             // SERVER SIDE ERROR END
  265.         } catch (e) {
  266.             alertContext.setAlert({
  267.                 text:  [
  268.                     e,
  269.                     'Something went wrong while trying to delete the tag.',
  270.                     'Check your internet connection to make sure you didn\'t lose it or perhaps our servers may be down for maintenance.',
  271.                 ],
  272.                 level: 'error',
  273.             });
  274.             RESET();
  275.         }
  276.     }
  277. }
  278.  
  279. export default withAlertContext(NewTagContextProvider);
Add Comment
Please, Sign In to add comment