Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion ada-project-docs/wave_04.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ Answer the following questions. These questions will help you become familiar wi
- What are the _two_ _required_ arguments for this endpoint?
- How does this endpoint relate to the Slackbot API key (token) we just created?

Now, visit https://api.slack.com/methods/chat.postMessage/test.
Now, visit https://api.slack.com/methods/chat.postMessatge/test.

![](assets/api_test.png)

Expand Down
8 changes: 8 additions & 0 deletions app/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,13 @@ def create_app(test_config=None):
migrate.init_app(app, db)

# Register Blueprints here
# from .routes import task_list_bp
# app.register_blueprint(task_list_bp)

from .routes import tasks_bp
app.register_blueprint(tasks_bp)

from .routes import goals_bp
app.register_blueprint(goals_bp)

return app
25 changes: 24 additions & 1 deletion app/models/goal.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,29 @@
from flask import current_app
from app.models.task import Task
from app import db


class Goal(db.Model):
goal_id = db.Column(db.Integer, primary_key=True)
goal_id = db.Column(db.Integer, primary_key=True, autoincrement = True)
title = db.Column(db.String)
tasks = db.relationship('Task', backref = 'goal', lazy =True)

# def to_string(self):
# return f"{self.id}: {self.title} Description: {self.description} Completed at: {self.completed_at}"

def to_dict(self):
return {
"id": self.goal_id,
"title": self.title
}

def goal_with_tasks_dict(self):
return {
"id": self.goal_id,
"title": self.title,
"task_id": self.tasks.id,
"title": self.tasks.title,
"description": self.tasks.description,
"is_complete": self.tasks.completed_at
}

20 changes: 19 additions & 1 deletion app/models/task.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,22 @@


class Task(db.Model):
task_id = db.Column(db.Integer, primary_key=True)
id = db.Column(db.Integer, primary_key=True, autoincrement = True)
title = db.Column(db.String)
description = db.Column(db.String)
completed_at = db.Column(db.DateTime, nullable = True)
goal_id = db.Column(db.Integer, db.ForeignKey('goal.goal_id'), nullable = True)
#goal = db.relationship('Goal', back_populates = 'tasks', lazy = True) unnecessary because we have backref in goal model

def to_string(self):
return f"{self.id}: {self.title} Description: {self.description} Completed at: {self.completed_at}"

def combo_dict(self):
return {
"id": self.id,
"goal_id": self.goal_id,
"title": self.title,
"description": self.description,
"is_complete": self.completed_at is not None
}

282 changes: 281 additions & 1 deletion app/routes.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,282 @@
from flask import Blueprint
from flask.wrappers import Request
from app import db
from app.models.task import Task
from app.models.goal import Goal
from functools import wraps
from flask import Blueprint, jsonify, make_response, request
from datetime import datetime

#task_list_bp = Blueprint("task_list_bp", __name__)
tasks_bp = Blueprint("tasks", __name__, url_prefix = "/tasks")

# def require_task(endpoint):
# @wraps(endpoint)
# def fn(*args, task_id, **kwargs):
# task = Task.query.get(task_id)
# if not task:
# return jsonify(None), 404
# return endpoint(*args, task_id, **kwargs)
# return fn

@tasks_bp.route("", methods = ["GET"])
def manage_tasks():
#if request.method == "GET":
sort_query = request.args.get("sort")
if sort_query == "desc":
task = Task.query.order_by(Task.title.desc())
elif sort_query == "asc":
task = Task.query.order_by(Task.title.asc())
else:
task = Task.query.all()
tasks_response = []
for task in task:
tasks_response.append(
{
"id": task.id,
"title": task.title,
"description": task.description,
"is_complete": task.completed_at is not None
}
)
return jsonify(tasks_response), 200

@tasks_bp.route("", methods = ["POST"])
def post_tasks():
request_body = request.get_json()
if "title" not in request_body:
return{
"details": "Invalid data"
}, 400
if "description" not in request_body:
return jsonify({"details": "Invalid data"}), 400
if "completed_at" not in request_body:
return jsonify({"details": "Invalid data"}), 400
new_task = Task(
title = request_body["title"],
description = request_body["description"],
completed_at = request_body["completed_at"]
)
db.session.add(new_task)
db.session.commit()

response_body = {
"task":{
"id": new_task.id,
"title": new_task.title,
"description": new_task.description,
"is_complete": new_task.completed_at is not None
}
}
return jsonify(response_body), 201

@tasks_bp.route("/<task_id>", methods = ["GET", "PUT", "DELETE"])
def manage_task(task_id):
task = Task.query.get(task_id)
if not task:
return jsonify(None), 404
elif request.method == "GET":
if task.goal_id:
response_body = {"task":(task.combo_dict())}
else:
response_body = {
"task":{
"id": task.id,
"title": task.title,
"description": task.description,
"is_complete": task.completed_at is not None
}
}
return jsonify(response_body), 200
elif request.method == "PUT":
request_body = request.get_json()

task.title = request_body["title"]
task.description = request_body["description"]
#task.completed_at = request_body["completed_at"]

db.session.commit()
response_body = {
"task":{
"id": task.id,
"title": task.title,
"description": task.description,
"is_complete": task.completed_at is not None
}
}
return jsonify(response_body), 200
elif request.method == "DELETE":
db.session.delete(task)
db.session.commit()
return jsonify(
{
"details":f'Task {task.id} "{task.title}" successfully deleted'
}
), 200

@tasks_bp.route("/<task_id>/mark_complete", methods = ["PATCH"]) #datetime.now function
def patch_complete(task_id):
task = Task.query.get(task_id)
# request_body = request.get_json()
# if "title" not in request_body or "description" not in request_body: #or "completed_at" not in request_body:
if not task:
return jsonify(None), 404
task.completed_at = datetime.utcnow()
db.session.commit()
response_body = {
"task":{
"id": task.id,
"title": task.title,
"description": task.description,
"is_complete": True #in the wild maybe don't hardcode True #if statement and then you don't need an opposite function
}
}
return jsonify(response_body), 200

@tasks_bp.route("/<task_id>/mark_incomplete", methods = ["PATCH"]) #datetime.now function
def patch_incomplete(task_id):
task = Task.query.get(task_id)
#request_body = request.get_json() #test doesn't have 'request_body'
# task_id.completed_at = False
# if "title" not in request_body or "description" not in request_body: #or "completed_at" not in request_body:
# return{
# "details": "Invalid data"
# }, 400
#db.session.add(task_id)
if not task:
return jsonify(None), 404
task.completed_at = None
db.session.commit()
response_body = {
"task":{
"id": task.id,
"title": task.title,
"description": task.description,
"is_complete": False
}}
return jsonify(response_body), 200



#wave 5
goals_bp = Blueprint("goals", __name__, url_prefix = "/goals")

@goals_bp.route("", methods = ["GET"])
def manage_goals():
goal = Goal.query.all()
goals_response = []
for goal in goal:
goals_response.append(
{
"id": goal.goal_id,
"title": goal.title,
}
)
return jsonify(goals_response), 200

@goals_bp.route("", methods = ["POST"])
def post_goals():
request_body = request.get_json()
if "title" not in request_body:
return{
"details": "Invalid data"
}, 400
new_goal = Goal(
title = request_body["title"],
)
db.session.add(new_goal)
db.session.commit()
response_body = {
"goal":{
"id": new_goal.goal_id,
"title": new_goal.title,
}
}
return jsonify(response_body), 201

@goals_bp.route("/<goal_id>", methods = ["GET", "PUT", "DELETE"])
def whatever_goal(goal_id):
goal = Goal.query.get(goal_id)
request_body = request.get_json()
if not goal:
return jsonify(None), 404
if request.method == "GET":
response_body = {
"goal":{
"id": goal.goal_id,
"title": goal.title,
}
}
return jsonify(response_body), 200
elif request.method == "PUT":
request_body = request.get_json()
goal.title = request_body["title"]
db.session.commit()
response_body = {
"goal":{
"id": goal.goal_id,
"title": goal.title,
}
}
return jsonify(response_body), 201
elif request.method == "DELETE":
db.session.delete(goal)
db.session.commit()
return jsonify(
{
"details":f'Goal {goal.goal_id} "{goal.title}" successfully deleted'
}
), 200

@goals_bp.route("goals/<goal_id>/mark_complete", methods = ["PATCH"])
def goal_patch_complete(goal, goal_id):
request_body = request.get_json()
goal.completed_at = True
if "title" not in request_body:
return{
"details": "Invalid data"
}, 400
db.session.add(goal)
db.session.commit()
response_body = {
"goal":{
"id": goal.goal_id,
"title": goal.title,
}}
return jsonify(response_body), 201

#wave 6
@goals_bp.route("/<goal_id>/tasks", methods = ["GET", "POST"])
def task_list_to_goal(goal_id):
goal = Goal.query.get(goal_id)
request_body = request.get_json()
if goal == None:
return jsonify(None), 404
elif request.method == "GET":
return jsonify(goal.goal_with_tasks_dict()), 200
elif request.method == "POST":
request_body = request.get_json()
task_ids = request_body["task_ids"]
for id in task_ids:
task = Task.query.get(id)
task.goal_id = goal_id
db.session.commit()
new_tasks = []
for task in goal.tasks:
new_tasks.append(task.id)
response_body = {
"id": int(goal_id),
"task_ids": new_tasks
}
return jsonify(response_body), 200












2 changes: 1 addition & 1 deletion tests/test_wave_01.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ def test_update_task_not_found(client):
assert response_body == None


def test_delete_task(client, one_task):
def test_delete_task(client, one_task): #anything that looks like a param in a test is actually the name of a fixture that gets run before the test runs; see line 31 in conftest.py
# Act
response = client.delete("/tasks/1")
response_body = response.get_json()
Expand Down
Loading