/Pixtagram

Primary LanguagePython

Pixtagram

Pixtagram is a pixel perfect clone of dark themed Instagram where users can share posts with other users. They can show their support by liking and commenting other's posts.

Check out Pixtagram

Index

MVP Feature List | Database Scheme | User Stories | React Components | Routes

Sign Up

Sign up feature

User Profile

Profile

Comments and Likes

Comments and Likes

Search

Search

Technologies Used

Getting started

  1. Clone this repository:

    git clone https://github.com/BriRob/Pixtagram.git
  2. Install dependencies with the following:

    pipenv install --dev -r dev-requirements.txt && pipenv install -r requirements.txt
  3. Create a .env file using the .envexample provided

  4. Setup your PostgreSQL user, password and database and make sure it matches your .env file

  5. Get into your pipenv, migrate your database, seed your database, and run your flask app

    pipenv shell
    flask db upgrade
    flask seed all
    flask run
  6. Now you can use the Demo User or Create an account

Amazon Web Services S3

  • For setting up your AWS refer to this guide

Deploy to Heroku

This repo comes configured with Github Actions. When you push to your main branch, Github will automatically pull your code, package and push it to Heroku, and then release the new image and run db migrations.

  1. Write your Dockerfile. In order for the Github action to work effectively, it must have a configured Dockerfile. Follow the comments found in this Dockerfile to write your own!

  2. Create a new project on Heroku.

  3. Under Resources click "Find more add-ons" and add the add on called "Heroku Postgres".

  4. Configure production environment variables. In your Heroku app settings -> config variables you should have two environment variables set:

    Key Value
    DATABASE_URL Autogenerated when adding postgres to Heroku app
    SECRET_KEY Random string full of entropy
  5. Generate a Heroku OAuth token for your Github Action. To do so, log in to Heroku via your command line with heroku login. Once you are logged in, run heroku authorizations:create. Copy the GUID value for the Token key.

  6. In your Github Actions Secrets you should have two environment variables set. You can set these variables via your Github repository settings -> secrets -> actions. Click "New respository secret" to create each of the following variables:

    Key Value
    HEROKU_API_KEY Heroku Oauth Token (from step 6)
    HEROKU_APP_NAME Heroku app name
  7. Push to your main branch! This will trigger the Github Action to build your Docker image and deploy your application to the Heroku container registry. Please note that the Github Action will automatically upgrade your production database with flask db upgrade. However, it will not automatically seed your database. You must manually seed your production database if/when you so choose (see step 8).

  8. Attention! Please run this command only if you wish to seed your production database: heroku run -a HEROKU_APP_NAME flask seed all

Helpful commands

Command Purpose
pipenv shell Open your terminal in the virtual environment and be able to run flask commands without a prefix
pipenv run Run a command from the context of the virtual environment without actually entering into it. You can use this as a prefix for flask commands
flask db upgrade Check in with the database and run any needed migrations
flask db downgrade Check in with the database and revert any needed migrations
flask seed all Just a helpful syntax to run queries against the db to seed data. See the app/seeds folder for reference and more details
heroku login -i Authenticate your heroku-cli using the command line. Drop the -i to authenticate via the browser
heroku authorizations:create Once authenticated, use this to generate an Oauth token
heroku run -a <app name> Run a command from within the deployed container on Heroku

Features

Users

  • Guest users can create a new account
  • Logged in users can read/view other user accounts
  • Logged in users can update/edit their profile details and upload a profile photo
  • Logged in users can delete their profile

Posts

  • Users can create a post on Pixtagram
  • Users can read/view other posts
  • Users can update their posts
  • Users can delete their posts

Comment

  • Users can create comments on posts
  • users can read/view all of the comments on a post
  • Users can delete their comments on a posts
  • Help me

Likes

  • Users can like posts
  • Users can remove likes on posts

Search

  • Dynamic search bar. The search bar will change as the user types.
  • Search-bar will send users to profile. Search is based on usernames

Future Features

Following

Logged-in Users can

  • Follow other users
  • Be followed by other users
  • Tag other users in posts/comments
  • Hashtags for posts

Technical Implementation

  • the search bar was particularly difficult to figure out. I had to work with creating a div that opens in a fixed position and displays items within it dynamically. I was able to find a react component download that helps with autocomplete and search functionality. It was difficult to use as it has its own attributes and ways of using CSS. It took me about a day of tinkering to figure it out and get it to work. Overall, it works more smoothly than building a custom component from scratch, and I was able to add my own style of code to that component. I will definitely be reusing that experience for future experiences.
<Autocomplete
                id="users-search"
                getOptionLabel={(jsonResults) => `${jsonResults.username}`}
                options={jsonResults.length === 0 ? [] : jsonResults}
                noOptionsText={'NO PEOPLE FOUND'}
                style={{ width: 250, margin:15, 'postion': 'relative', 'left': 10 }}
                renderOption={(option) => (
                    <div onClick={() => { history.push(`/users/${option.id}`) }}>
                        <React.Fragment >

                            <span
                                style={{ cursor: 'pointer' }}
                            >
                                {`${option.username}`}
                            </span>
                        </React.Fragment>
                    </div>
                )}
                renderInput={(params) => (
                    <TextField
                        {...params}
                        id='text-field'
                        placeholder='Search...'
                    />)}
            />