Skip to the content.

Sprint 5 - Review

  • Improvements, Next Steps, Glows n Grows
  • Purpose of my group’s program

    The purpose of our groups program was to provide readers a space to talk to other readers, provide reviews, and find new books to read.

    Purpose of my individual feature(s)

    The purpose of my feature was to allow users react to books with emojis to show if the book made them feel happy, sad, etc. This is not as quick as a rating, but not quite a review, instead it just allows readers to express how the book made them feel in a simple manner. The program retrieves data from a backend API and displays it in an interactive UI. Users can:

    • Add new items using an input field with an emoji selection feature.
    • Update existing items by modifying their content and saving changes.
    • Delete items when they are no longer needed.
    • The UI dynamically updates based on user actions without requiring a page reload.

    A combination of event listeners and API calls (GET, POST, PUT, DELETE) ensures that the frontend remains synchronized with the backend.

    Input/Output requests. (live)

    List requests

    Lists

    There are two rows created from this list as static data. Then the rows also correspond to columns - user_id, reaction_type, post_id.

    emotions = [
            Emotion(user_id=1, reaction_type='😢', title_id="Catcher in the Rye", author_id="J.D."),
            Emotion(user_id=1, reaction_type='❤️', title_id="Hunger Games", author_id="Suzanne Collins")
        ]
    

    Dictionaries

    There are three columns generated from dictionary - reaction_type, user_id, and post_id. These three columns

    return {
            "reaction_type": self.reaction_type,
            "user_id": self.user_id,
            "title_id": self.title_id,
            "author_id": self.author_id
        }
    

    Response data formatting

        return jsonify({
            "message": "Reaction updated successfully", 
            "reaction": {
            "user_id": emotion.user_id,
            "title_id": emotion.title_id,
            "reaction_type": emotion.reaction_type,
            "author_id": emotion.author_id
                }
            }), 200 
    
        document.getElementById('updateEmotionButton').addEventListener('click', async () => {
            const userId = document.getElementById('updateUserId').value;
            const titleId = document.getElementById('updateTitleId').value;
            const reactionType = document.getElementById('updateReactionType').value;
            const authorId = document.getElementById('updateAuthorIdUpdate').value;
    

    The queries are provided by SQL Alchemy, which is a 3rd party library.

    @emotion_api.route('/<title_id>', methods=['GET'])   #/It
    def get_emotion(title_id):
        try:
            # Query reactions for the specific book
            emotions = Emotion.query.filter_by(title_id=title_id).all()
    
            # Format the data to return
            emotion_data = [
                {
                    'user_id': emo.user_id,
                    'reaction_type': emo.reaction_type,
    #                'author_id': emo.author_id
                }
                for emo in emotions
            ]
            return jsonify({
                'title_id': title_id,
                'emotions': emotion_data
            }), 200
        except Exception as e:
            return jsonify({'error': 'Failed to get reactions', 'message': str(e)}), 500
    

    CRUD

    class Emotion(db.Model):
        __tablename__ = 'emotion'
        id = db.Column(Integer, primary_key=True)
        user_id = db.Column(String, db.ForeignKey('users.id'), nullable=False) #person
        title_id = db.Column(String, nullable=False) #book title/series
        author_id = db.Column(String, nullable=False) #author
        reaction_type = db.Column(String, nullable=False) #reaction
    
        def __init__(self, reaction_type, user_id, title_id, author_id):
            self.reaction_type = reaction_type
            self.user_id = user_id
            self.title_id = title_id
            self.author_id = author_id
    
        def add_reaction(reaction_type, user_id, title_id, author_id):
            new_reaction = Emotion (
                reaction_type=reaction_type,
                user_id=user_id,
                title_id=title_id,
                author_id=author_id
            )
    
            try:
                db.session.add(new_reaction)
                db.session.commit()
            except Exception as e:
                db.session.rollback()
                raise e
    
        def __repr__(self):
            return f"<Reaction {self.reaction_type}>"
        
        def create(self):
            db.session.add(self)
            db.session.commit()
            
        def delete(self):  
            try:
                db.session.delete(self)
                db.session.commit()
            except Exception as e:
                db.session.rollback()
                raise e
            
        def read(self):
            """
            Retrieve the vote data as a dictionary.
    
            Returns:
                dict: Dictionary with vote information.
            """
            return {
                "reaction_type": self.reaction_type,
                "user_id": self.user_id,
                "title_id": self.title_id,
                "author_id": self.author_id
            }
        
        @staticmethod
        def restore(data):
            restored_reactions = {}
    
            for reaction_data in data:
                # Remove 'id' from the data if it exists (because id will be auto-generated)
                _ = reaction_data.pop('id', None)
    
                # Check if the book already exists based on title
                existing_user_id = Emotion.query.filter_by(title=reaction_data.get("title")).first()
                if existing_user_id:
                    # Update the existing book with new data
                    existing_user_id.reaction_type = existing_user_id.get('reaction_type', existing_user_id.reaction_type)
                    existing_user_id.user_id = existing_user_id.get('user_id', existing_user_id.user_id)
                    existing_user_id.title_id = existing_user_id.get('title_id', existing_user_id.title_id)
                    existing_user_id.author_id = existing_user_id.get('author_id', existing_user_id.author_id)
            
                    db.session.commit()
                    restored_reactions[existing_user_id.id] = existing_user_id
                else:
                    # Create a new suggested book
                    new_book = Emotion(**existing_user_id)
                    new_book.create()
                    restored_reactions[new_book.id] = new_book
    
            return restored_reactions
    

    Algorithmic code request.

    code blocks to handle requests

    # Create - Endpoint to add a reaction to a message
    @emotion_api.route('', methods=['POST']) #{"user_id": 2, "title_id": "It", "author_id" : "Stephen King", "reaction_type": "🎉"}
    def add_emotion():
        data = request.json
    
        user_id = data.get("user_id")
        reaction_type = data.get("reaction_type")
        title_id = data.get("title_id")
        author_id = data.get("author_id")
    
        try:
            # Create and add the message_reaction
            message_emotion = Emotion(reaction_type=reaction_type, user_id=user_id, title_id=title_id, author_id=author_id)
            message_emotion.create()
            return jsonify({'message': 'Emotion added successfully to post'}), 201
        except Exception as e:
            return jsonify({'error': 'Failed to add emotion', 'message': str(e)}), 500
        
    # Read - Get all reactions for a specific book
    @emotion_api.route('/<title_id>', methods=['GET'])   #/It
    def get_emotion(title_id):
        try:
            # Query reactions for the specific book
            emotions = Emotion.query.filter_by(title_id=title_id).all()
    
            # Format the data to return
            emotion_data = [
                {
                    'user_id': emo.user_id,
                    'reaction_type': emo.reaction_type,
    #                'author_id': emo.author_id
                }
                for emo in emotions
            ]
            return jsonify({
                'title_id': title_id,
                'emotions': emotion_data
            }), 200
        except Exception as e:
            return jsonify({'error': 'Failed to get reactions', 'message': str(e)}), 500
    
    # Update - Update a user's reaction on a post
    @emotion_api.route('/update', methods=['PUT']) #{"user_id": 2, "title_id": "It", "reaction_type": "👍", "author_id": "Stephen King"}
    def update_emotion():
        data = request.json
        user_id = data.get("user_id")
        title_id = data.get("title_id")
        new_reaction_type = data.get("reaction_type")
        author_id = data.get("author_id")
    
        # validate input
        if not user_id or not title_id or not new_reaction_type or not author_id:
            return jsonify({"error": "All fields (user_id, title_id, reaction_type, author_id) are required"}), 400
    
        try:
            # Fetch the reaction from the database
            emotion = Emotion.query.filter_by(user_id=user_id, title_id=title_id, author_id=author_id).first()
    
            # If the reaction does not exist, return an error
            if not emotion:
                return jsonify({"error": "Reaction not found"}), 404
    
            # Update the reaction type
            emotion.reaction_type = new_reaction_type
    
            db.session.commit()
    
            return jsonify({
                "message": "Reaction updated successfully", 
                "reaction": {
                    "user_id": emotion.user_id,
                    "title_id": emotion.title_id,
                    "reaction_type": emotion.reaction_type,
                    "author_id": emotion.author_id
                }
            }), 200 
        except Exception as e:
            return jsonify({'error': 'Failed to update reaction', 'message': str(e)}), 500
      
    # Delete - Remove a specific reaction
    @emotion_api.route('/delete', methods=['DELETE']) #{"user_id": 2, "title_id": "It", "reaction_type": "👍", "author_id": "Stephen King"}
    def delete_emotion():
        data = request.json
        user_id = data.get("user_id")
        title_id = data.get("title_id")
    
        if not user_id or not title_id:
            return jsonify({"error": "Both user_id and post_id are required"}), 400
    
        # Query the Reaction model to find the reaction by user_id and post_id
        emotion = Emotion.query.filter_by(user_id=user_id, title_id=title_id).first()
    
        if not emotion:
            return jsonify({"error": "Reaction not found"}), 404
        
        # Delete the reaction from te database
        db.session.delete(emotion)
        db.session.commit()
    
        return jsonify({"message": "Reaction deleted successfully"}), 200
    
    

    Method Containing Sequencing, Selection, Iteration

    The POST method demonstrates sequencing, selection, and iteration:

    • Sequencing: Executes statements in a specific order, such as extracting JSON data, validating input, and updating the dataset.
    • Selection: Uses conditional checks (e.g., if key and value) to ensure only valid input is processed.
    • Iteration: Although the method itself does not directly iterate, similar logic could be applied to iterate over keys in a batch operation.

    Call to Algorithm request.

    Definition of code block to make a request

    from flask import Blueprint, request, jsonify
    def add_emotion():
        data = request.json
    ...
    

    Call/Request to the Method

    When calling the ‘post’ endpoint, the

    • Endpoint URL: The URL to which the POST request is sent.
    • Data Object: The data to be sent in the request body, which is converted to a JSON string.
    • Fetch Options:
      • method: Specifies the HTTP method (POST in this case).
      • headers: Sets the request headers, including Content-Type to application/json.
      • body: Contains the JSON stringified data.
    • Sending the Request: The fetch function sends the request with the specified options.
    • Handling the Response:
      • The response is checked for success.
      • The response JSON is parsed and handled.
      • Any errors are caught and logge

    return/response from the method

    To make a POST request using the fetch API in JavaScript:

    • Define the Endpoint URL: Specify the URL to send the request to.
    • Create the Data Object: Prepare the data to send in the request body.
    • Set Up Fetch Options: Configure the method, headers, and body.
    • Send the Request: Use fetch with the configured options.
    • Handle the Response: Check for success, parse the JSON, and handle any errors.

    Changing data triggers different responses

    Post

    • Normal: {“user_id”: 2, “title_id”: “It”, “author_id” : “Stephen King”, “reaction_type”: “🎉”}
      try:
        # Create and add the message_reaction
        message_emotion = Emotion(reaction_type=reaction_type, user_id=user_id, title_id=title_id, author_id=author_id)
        message_emotion.create()
        return jsonify({'message': 'Emotion added successfully to post'}), 201
      
    • Error: {“user_id”: 2, “title_id”: “It”, “reaction_type”: “🎉”}
      except Exception as e:
            return jsonify({'error': 'Failed to add emotion', 'message': str(e)}), 500
      

    COLLEGE BOARD REQUIREMENTS

    • sequencing, list, dictionaries, iteration

    Improvements, Next Steps, Glows n Grows

    • Glows: Gabi mentioned college board requirements of sequencing + interation - shows she was looking into it on her own, without someone telling her to.
    • Grows:
      • Sequencing is just order of steps
      • Your sequencing/selection (e.g. if), iteration(), should be in one method because you have to call it
      • Use Mr. Morts fetch options
      • D: ): I need to talk more, I don’t talk enough apparently …
    • Improvements: update should be autofilled, shouldn’t be like reading and deleting and posting. frontend isn’t very appealling, hard to understand
    • Next Steps: redo update so more user friendly, make a better user interface