Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Snow Leopards C18 - Anna Lord, Bukunmi Gesinde, Emily Son, Katherine Abrikian #17

Open
wants to merge 44 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
f4c04b4
Organize models into folder, create model and connect bp for boards.
Jan 4, 2023
d6cffa6
Update: Refactored card model
bukunmig Jan 4, 2023
2f35335
Updated: moved routes
bukunmig Jan 4, 2023
7ca48d3
Draft for board_routes.
Jan 4, 2023
dfbce98
Merge branch 'main' of https://github.com/EmilyIsCoding/back-end-insp…
Jan 4, 2023
7b415aa
Update: refactored card model
bukunmig Jan 4, 2023
c5cd102
Clean up Boards to make Owner mandatory, create User model.
Jan 5, 2023
01e495b
Merge branch 'main' of https://github.com/EmilyIsCoding/back-end-insp…
Jan 5, 2023
bb94999
Remove user/owner and refactor card to_dict.
Jan 5, 2023
f042243
Fix models and GET route works for Board.
Jan 6, 2023
bd77ab0
Create error in User routes.
Jan 6, 2023
959c1c6
fix user taken validation in user_routes
annalord Jan 17, 2023
2117c58
Finish user_routes with PUT and GET requests.
Jan 17, 2023
cebab8f
Work on book_routes, troubleshoot Create Book.
Jan 17, 2023
c6b407d
fixes board route bugs
annalord Jan 17, 2023
93ac4db
updated owner to author
bukunmig Jan 17, 2023
fa058f3
Merge branch 'main' of https://github.com/EmilyIsCoding/back-end-insp…
bukunmig Jan 17, 2023
7f875c6
updated Card to_dict and from_dict
Jan 17, 2023
20800d1
route outlines for Card
Jan 18, 2023
d434aaf
Updated board and card routes
bukunmig Jan 18, 2023
dd6467a
Updated card route with GET req
bukunmig Jan 18, 2023
27230a1
Updated card route for getting all cards on board
bukunmig Jan 18, 2023
9856cd0
Updated card routes
bukunmig Jan 18, 2023
2febd12
added number of cards on board to board dict
Jan 18, 2023
a64d71b
Set up Heroku.
Jan 18, 2023
9a949b3
Update branch for Heroku.
Jan 18, 2023
2adaf1b
Change GET all Users to return Ids.
Jan 18, 2023
b3e05c2
Fix indent in Board.py from_dict.
Jan 18, 2023
05e7634
updates to board and user to support FE connection
Jan 18, 2023
34d363e
Update card_color column in PSQL.
Jan 18, 2023
5c1d1db
updated board from dict
Jan 18, 2023
0cbe97b
stupid comma
Jan 18, 2023
42fc9d0
Missed a comma in boards.
Jan 18, 2023
4ddacc0
Merge branch 'main' of https://github.com/EmilyIsCoding/back-end-insp…
Jan 18, 2023
35768b6
Create test_routes, finish GET.
Jan 19, 2023
cf811f5
updated test_routes
Jan 19, 2023
18f116f
Create Test Database, run into errors running it.
Jan 19, 2023
c4df290
3 tests passing
Jan 19, 2023
cd94e23
changed the environment variable name for test db
Jan 19, 2023
b97a87e
fixed one test
Jan 19, 2023
b3a6b1f
test get_one_board passing
Jan 19, 2023
46b651b
all board route tests passing
Jan 19, 2023
0885491
End my suffering.
Jan 19, 2023
1e0afb8
Update README.md
EmilyIsCoding Mar 8, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
## Overview
Part of a full-stack project involving four team members. Completed in 8 days (including planning time) over three weeks.<br /><br />
**Front-end owners:** [@kalawac](https://github.com/kalawac/), [@annalord](https://github.com/annalord/)<br />
**Back-end owners:** [@emilyiscoding](https://github.com/EmilyIsCoding/), [@bukunmig](https://github.com/BukunmiG/)<br />
### Related Links
- [Deployed project](http://hackspoboard.herokuapp.com/)
- [Front-end repo](https://github.com/kalawac/front-end-inspiration-board)<br />
- [Back-end repo](https://github.com/EmilyIsCoding/back-end-inspiration-board/)<br />
- [Ada C-18 repo with general full-stack project overview and requirements](https://github.com/Ada-C18/full-stack-inspiration-board)

# Inspiration Board: Back-end Layer

This scaffold includes the following:
Expand Down
23 changes: 17 additions & 6 deletions app/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,33 @@
load_dotenv()


def create_app():
def create_app(test_config=None):
app = Flask(__name__)
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False

app.config["SQLALCHEMY_DATABASE_URI"] = os.environ.get(
"SQLALCHEMY_DATABASE_URI")
if not test_config:
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
app.config["SQLALCHEMY_DATABASE_URI"] = os.environ.get(
"SQLALCHEMY_DATABASE_URI")
else:
app.config["TESTING"] = True
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
app.config["SQLALCHEMY_DATABASE_URI"] = os.environ.get("SQLALCHEMY_TEST_DATABASE_URI")

# Import models here for Alembic setup
# from app.models.ExampleModel import ExampleModel
from app.models.board import Board
from app.models.card import Card
from app.models.user import User


db.init_app(app)
migrate.init_app(app, db)

# Register Blueprints here
# from .routes import example_bp
# app.register_blueprint(example_bp)
from . import board_routes, card_routes, user_routes
app.register_blueprint(board_routes.bp)
app.register_blueprint(card_routes.bp)
app.register_blueprint(user_routes.bp)

CORS(app)
return app
71 changes: 71 additions & 0 deletions app/board_routes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
from flask import Blueprint, request, jsonify, make_response, abort
from app import db
from app.models.board import Board
from datetime import datetime


bp = Blueprint("boards_bp", __name__, url_prefix="/boards")

def validate_model(cls, model_id):
try:
model_id = int(model_id)
except:
abort(make_response({"message":f"{cls.__name__} {model_id} invalid"}, 400))

model = cls.query.get(model_id)

if not model:
abort(make_response({"message":f"{cls.__name__} {model_id} not found"}, 404))

return model

@bp.route("", methods=["POST"])
def create_board():
request_body = request.get_json()

if request_body["title"] is None:
abort(make_response({"message":"Please include a title"}, 400))

# if request_body["owner"] is None:
# abort(make_response({"message":"Please include an owner"}, 400))
# Since we have a login, they can't encounter this error in the first place

date = str(datetime.utcnow())

new_board = Board.from_dict({'date_created': date, 'title':request_body["title"],
'owner_id':request_body['user_id'], 'card_color': request_body['card_color'], 'visible':True})

db.session.add(new_board)
db.session.commit()

return make_response(jsonify(new_board.to_dict()), 201)

@bp.route("", methods=["GET"])
def read_all_boards():

title_query = request.args.get("title")
if title_query:
boards = Board.query.filter_by(title=title_query)
else:
boards = Board.query.all()

boards_response = []

for board in boards:
boards_response.append(board.to_dict())

return jsonify(boards_response)

@bp.route("<board_id>", methods=["GET"])
def read_one_board(board_id):
board = validate_model(Board, board_id)
return board.to_dict()

@bp.route("<board_id>", methods=["DELETE"])
def delete_board(board_id):
board = validate_model(Board, board_id)

db.session.delete(board)
db.session.commit()

return make_response(jsonify(f"Board #{board.id} successfully deleted"))
81 changes: 81 additions & 0 deletions app/card_routes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
from flask import Blueprint, request, jsonify, make_response, abort
from app import db
from app.models.card import Card
from datetime import datetime
from app.board_routes import validate_model
from app.models.board import Board


bp = Blueprint("cards_bp", __name__, url_prefix="/cards")

# Create a card [POST]
@bp.route("", methods=["POST"])
def create_card():
request_body = request.get_json()

if not request_body["user_id"]:
abort(make_response({"message": "No user ID present"}, 400))

if not request_body["message"]:
abort(make_response({"message": "No message in card"}, 400))

date = str(datetime.utcnow())

new_card = Card.from_dict({'date_created': date,
'likes': 0 ,
'message':request_body["message"],
'board_id': request_body["board_id"],
'author_id':request_body['user_id']})
db.session.add(new_card)
db.session.commit()

return make_response(jsonify(new_card.to_dict()), 201)

# Get information on a card by ID [GET] 200 will come automatically
@bp.route("/<id>", methods=["GET"])
def read_card(id):
card = validate_model(Card, id)
return card.to_dict()

# Get information on all cards associated with a board [GET]
@bp.route("/board/<board_id>", methods=["GET"])
def read_all_cards_on_board(board_id):
board = validate_model(Board, board_id)

cards = board.cards

cards_response = []

for card in cards:
cards_response.append(card.to_dict())

return jsonify(cards_response)


# Update information on a card [PUT] &[PATCH]
@bp.route("/<id>", methods=["PUT"])
def update_card(id):
card = validate_model(Card, id)
request_body = request.get_json()

card.message = request_body["message"]
db.session.commit()
return jsonify(card.to_dict())


@bp.route("/<id>/like", methods=["PATCH"])
def update_card_likes(id):
card = validate_model(Card, id)
card.likes += 1

db.session.commit()
return jsonify(card.to_dict())


# Delete card from database / board [DELETE]
@bp.route("/<id>", methods=["DELETE"])
def delete_card(id):
card = validate_model(Card, id)
db.session.delete(card)
db.session.commit()
return make_response(f"card {id} deleted", 200)
36 changes: 36 additions & 0 deletions app/models/board.py
Original file line number Diff line number Diff line change
@@ -1 +1,37 @@
from app import db

class Board(db.Model):
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
date_created = db.Column(db.DateTime)
title = db.Column(db.String)
visible = db.Column(db.Boolean)
cards = db.relationship("Card", back_populates="board")
owner_id = db.Column(db.Integer, db.ForeignKey("user.id"))
owner = db.relationship("User", back_populates="boards")
card_color = db.Column(db.String)

def to_dict(self):
board_dict = {
"id": self.id,
"date_created": self.date_created,
"title": self.title,
"visible": self.visible,
"owner": self.owner.name,
"num_cards": (len(self.cards) if self.cards else 0)
}
if self.card_color:
board_dict["card_color"] = self.card_color

return board_dict

@classmethod
def from_dict(cls, board_data):
new_board = Board(
date_created=board_data["date_created"],
title=board_data["title"],
visible=board_data["visible"],
owner_id=board_data["owner_id"],
card_color=board_data["card_color"]
)

return new_board
35 changes: 35 additions & 0 deletions app/models/card.py
Original file line number Diff line number Diff line change
@@ -1 +1,36 @@
from app import db

class Card(db.Model):
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
date_created = db.Column(db.DateTime)
likes = db.Column(db.Integer)
message = db.Column(db.String)
board_id = db.Column(db.Integer, db.ForeignKey('board.id'))
board = db.relationship("Board", back_populates="cards")
author_id = db.Column(db.Integer, db.ForeignKey("user.id"))
author = db.relationship("User", back_populates="cards")

def to_dict(self):
card_dict = {
"id": self.id,
"date_created": self.date_created,
"likes": self.likes,
"message": self.message,
"author_id": self.author_id,
}

if self.board:
card_dict["board_id"] = self.board.id

return card_dict

@classmethod
def from_dict(cls, card_data):
new_card = Card(
date_created=card_data["date_created"],
likes = card_data["likes"],
message = card_data["message"],
board_id = card_data["board_id"],
author_id = card_data["author_id"])

return new_card
7 changes: 7 additions & 0 deletions app/models/user.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from app import db

class User(db.Model):
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
name = db.Column(db.String)
boards = db.relationship("Board", back_populates="owner")
cards = db.relationship("Card", back_populates="author")
4 changes: 0 additions & 4 deletions app/routes.py

This file was deleted.

54 changes: 54 additions & 0 deletions app/user_routes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
from flask import Blueprint, request, jsonify, make_response, abort
from app import db
from app.models.user import User

bp = Blueprint("users_bp", __name__, url_prefix="/users")

def validate_model(cls, name):
model = cls.query.filter(cls.name == name).one_or_none()

if not model:
abort(make_response({"message":f"{cls.__name__} {name} not found"}, 404))

return model

@bp.route("", methods=["POST"])
def create_user():
request_body = request.get_json()

if request_body["name"] == "":
abort(make_response({"message":"Please include a name"}, 400))

users = User.query.all()

for user in users:
if request_body["name"] == user.name:
abort(make_response({"message":f"{request_body['name']} is taken. Please choose another name."}, 400))

new_user = User(name=request_body["name"])

db.session.add(new_user)
db.session.commit()

return make_response(jsonify({"id": new_user.id, "name": new_user.name}), 201)

@bp.route("", methods=["GET"])
def read_all_users():
users = User.query.all()

users_response = []
for user in users:
users_response.append(
{
"id": user.id,
"name": user.name
}
)
return jsonify(users_response)

@bp.route("/<name>", methods=["GET"])
def read_one_user(name):
user = validate_model(User, name)

return make_response(jsonify({"id": user.id, "name": user.name}), 200)

1 change: 1 addition & 0 deletions migrations/README
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Generic single-database configuration.
Loading