Skip to content

vtwoptwo/ie-frontend

Repository files navigation

Frontend for Recipe Manager

Contributors Forks Stargazers Issues MIT License LinkedIn


Logo

Frontend

An end to end process to develop, test, and deploy a small scale application using CI/CD, GitHub Actions, and Docker. The application is built using two repositories: one for the frontend and one for the backend.


See the Backend» · See the project» · How to use this repo · Report Bug · Request Feature

Table of Contents
  1. About The Project
  2. Getting Started
  3. Usage
  4. Roadmap
  5. Contributing
  6. License
  7. Contact
  8. Acknowledgments

About The Project

This project is to practice end-to-end development using best practice implementations of early functional as well as unit testing, CI/CD and Dockerization of applicatins.

I am also making this repo explicity detailed so that anyone can follow it from start to finish.

General description



Implement an anonymous web application for managing cooking recipes. Single page application.

Functional requirements:

  • The user must be able to create, read, update, and delete recipes (CRUD).
  • The user must be able to rate recipes from 1 to 5 stars.
  • The user must be able to mark recipes as Favorite with a checkbox.
  • The user must be able to create and edit recipes in a modal view.
  • User authentication is not needed.

(back to top)

Built With

  • VueJs
  • Postgres
  • Flask
  • Bicep

Tools Used

  • Postman
  • Docker
  • Azure

(back to top)

Getting Started

Make sure you know about the following concepts before starting:

RestAPI

  • REST (Representational State Transfer) is a software architectural style that defines a set of constraints to be used for creating web services.

  • A REST API (Application Programming Interface) is a set of rules that defines how two systems can interact over the internet, using the HTTP protocol.

  • A REST API defines a set of functions that a developer can use to send requests and receive responses. The requests and responses are typically in the form of JSON (JavaScript Object Notation) or XML (Extensible Markup Language) messages.

Flask

Flask is a web (micro)framework for Python:

  • Multiple extensions available to enhance features
  • It makes programming a website much easier than usingplain HTTPServer.
  • Integrated support for unit testing
  • Contains development server and debugger
  • Relies on Jinja templating engine to ease HTML creation

Postgres / PgAdmin

The Database:

  • PGAdmin is a PostgreSQL Management Tool used to interact with the Postgres database sessions, both locally and remote servers as well. You can use PGAdmin to perform any sort of database administration required for a Postgres database.
  • PostgreSQL, also known as Postgres, is a free and open-source relational database management system emphasizing extensibility and SQL compliance. It is designed to handle a range of workloads, from single machines to data warehouses or Web services with many concurrent users. It is the default database for macOS Server, and is also available for Linux, FreeBSD, OpenBSD, and Windows.

Prerequisites

You will need the following software downloaded on your workstation:

Installation

  1. Clone the backend repo
    git clone https://github.com/vtwoptwo/ie-backend.git
  2. Clone the frontend repo
    git clone https://github.com/vtwoptwo/ie-frontend.git

(back to top)

Usage

Roadmap in Steps

Make sure you have everything downloaded from the pre-requisites before continuing.

Set-Up

  1. Create project repository in Github
Name: Backend | Access: Public |                         Add .gitignore template: None
  1. Open VSCode and select "Clone Github Repository"
  2. Install Virtualenv:
pip install virtualenv
#I had an error for so run this command just in case before starting
python -m pip install psycopg2 
  1. Create new virtualenv:
py –m venv .venv
  1. Activate new virtual environment
.venv/scripts/activate
  1. Install Flask
pip install flask, flask_sqlalchemy, python-dotenv, flask_cors

Implementing the Flask API

  1. In your PGAdmin right click on databases and create a new database. The following is the table we will create in the dabase using code-first architecture.
Attribute Type Description
Name String Name of recipe
Ingredients String Required Ingredients
Steps String Instructions on creating the recipe
Rating Int 1-5 Star Rating
Favorite bool Marked as either a favorite or not

  1. In your requirements make sure you have the following requirements set:
Flask==2.2.2
Flask-Cors==3.0.10
Flask-SQLAlchemy==2.5.1
psycopg2==2.9.3
python-dotenv==0.21.0
SQLAlchemy==1.4.41
pytest
pytest-cov
pip install -r ./requirements.txt
  1. Implementing the "Code-First Approach" with the DB

Creating a table model for our recipe tracker (in models.py)

class Recipe(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(32), nullable=False)
    ingredients = db.Column(db.String(500), nullable=False)
    instructions = db.Column(db.String(500), nullable=False)
    favorite = db.Column(db.Boolean, default=False)
    rating = db.Column(db.Integer, default=0)
    date_created = db.Column(db.DateTime, default=datetime.utcnow)

    def __repr__(self):
        return f'{self.name}'
    
    def __init__(self, name, ingredients, instructions, favorite, rating):
        self.name = name
        self.ingredients = ingredients
        self.instructions = instructions
        self.favorite = favorite
        self.rating = rating

In the python CLI to test the code/database:

from app import app,db,Recipe
with app.app_context():
  db.create_all()
r1 = Recipe(name="Soup", ingredients="veggies,vegeta,water,chicken", instructions=("Boil all ingredients for a few hours"), favorite=True, rating=5) 
>>> with app.app_context():
  db.session.add(r1)
  db.session.commit()

run the backend

py ./run.py

Frontend

Implementing vue.js

  1. In your frontend folder run the following:
$ npm install -g @vue/cli
$ vue create frontend

#Manually select features (Babel, Router)
#Version: 2.x
#History mode for router: yes
#Config: dedicated config files
#Save for future projects: No

to run the vue application run:

cd frontend
npm run serve

To create a production build, run

npm run build

To quit running it

crtl + c
  1. Install the following libraries
npm i axios
npm install bootstrap@4.6.0 --save

  1. Testing the API by opening up POSTMAN and sending in requests to http://127.0.0.1:5000/recipes

Request = GET

{
    "name": "Tortilla de patata",
    "ingredients": "potatoes,onions,salt,eggs",
    "instructions": "if u dont know how to make it google it",
    "favorite": false,
    "rating": 4
}

Request = POST

{
    "name": "Tortilla de patata",
    "ingredients": "potatoes,onions,salt,eggs",
    "instructions": "if u dont know how to make it google it",
    "favorite": True,
    "rating": 4
}
  1. Ensure that your index folder has the same routes as your backend_api/routes.py
const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home
  }, 

  {
    path: '/skull',
    name: 'Skull',
    component: Skull
  },
  {
    path: '/recipes',
    name: 'AppRecipes',
    component: AppRecipes
  }
]
  1. Your main.js initiates the App.vue app: ensure that any extra components frome vue that you use are imported in the main.js file

More documentation is available here:

Vue JS Boostrap Components

import Vue from 'vue'
import 'bootstrap-vue'
import App from './App.vue'
import router from './router'
import 'bootstrap/dist/css/bootstrap.css'
import { BootstrapVue } from 'bootstrap-vue'
import { BFormRating } from 'bootstrap-vue'
Vue.component('b-form-rating', BFormRating)
import { IconsPlugin } from 'bootstrap-vue'
Vue.use(IconsPlugin)
Vue.use(BootstrapVue)
  1. Understanding the routing in VUE using CRUD
Description GET POST PUT DELETE
Functions RESTgetRecipes() RESTcreateRecipe(payload) RESTupdateRecipe(payload, recipeId) RESTdeleteRecipe(id)
Action Reads all recipes Creates new recipes by using a payload variable. These are variables which are mapped to the attribute variables in the database in order to create a new instance. Updates an existing recipe by using the recipe id to identify it and the payload to change specific values. Any values not changed remain the same. Deletes a recipe using the recipe id
Responses* 200 200 200 200
*note i did not put up specific response codes
  1. Understanding the routing between pages or components in the app
Function Description
gotohome() initForm() gonSubmit(evt) onSubmitUpdate(evt) deleteRecipe(recipe) editRecipe(recipe)
Switches back to the Home.vue page Initialized the forms using the HTML Modal Code event tracking of Submit Button to create a Recipe event tracking of Submit Button to edit a Recipe event tracking of Delete Button to delete a Recipe event tracking of Update to initialize update form

Implementing CI/CD

  • Workflows stored as yml files
  • fullly integrated with GitHub
  • Respond to GitHub events
  • Live logs and visualized workflow execution
  • community powered workflows
  • GitHub hosted or self-hosted runners
  • Built-in secret store

To understand the infrastructure see the following diagram:

To see the infrastructure as code written in Bicep, refer to: IaC

Within the bicep file, in order to launch two webapps at once I implemented the following for loop:

param names array = [ 'FE', 'BE' ]
  module appService 'modules/appModule.bicep' = [  for i in range(0,2): {
    name: 'appService${names[i]}'
    params: {
      location: location
      appServiceAppName:'${appServiceAppName}${names[i]}'
      appServicePlanName: appServicePlanName
      environmentType: environmentType
      dbhost: dbhost
      dbuser: dbuser
      dbpass: dbpass
      dbname: dbname
    }
  }]

 // output using loop

  output appServiceAppHostName array = [ for i in range(0,2): {
    name: 'appService${names[i]}'
    value: appService[i].outputs.appServiceAppHostName
  }]
 

See the IaC Repository for more info.

2. GitHub Actions

Frontend:

For the Frontend Workflow, I had to figure out a way to push different environment variables to the .env file that vue.js reads automatically. Since both webapps were being deployed as a production slot, the dev webapp did not recognize the correct environment file. To fix this I implemented the following code in the yml workflow:

      - name: Create .env for development
        if: github.ref == 'refs/heads/dev'
        run: |
          echo "${{ secrets.ENV_DEV_FILE }}" > .env.production
      - name: Create .env for production
        if: github.ref == 'refs/heads/main'
        run: |
          echo "${{ secrets.ENV_PROD_FILE }}" > .env.production

I set the VUE_ENV_ROOT_URL={url of backend} as two separate repository secrets in GitHub and call either file to be the official .env.production file based on which branched was pushed.

To increase the deployment efficiency, I deployed using release.zip format.

Backend:

For the Backend Workflow, I implemented a pytest job in the build of the application, and then conditional deployments depending on which branch was pushed.

The testing was implemented as follows:

    - name: Test with pytest
      run: |
        python -m pytest --cov=backend_api -v

See the open issues for a full list of proposed features (and known issues).

(back to top)

Contributing

The idea is to create a nice and simple repo for CPP Basic Rules, information, definitions, best practices etc. Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are greatly appreciated.

If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement".

Don't forget to give the project a star! Thanks again!

  1. Fork the Project
  2. Create your Feature Branch (git checkout -b feature/AmazingFeature)
  3. Commit your Changes (git commit -m 'Add some AmazingFeature')
  4. Push to the Branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

(back to top)

License

Distributed under the MIT License. See LICENSE.txt for more information.

(back to top)

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published