-
Notifications
You must be signed in to change notification settings - Fork 111
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
C17/Bahareh/Sharks #108
base: master
Are you sure you want to change the base?
C17/Bahareh/Sharks #108
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
web: gunicorn 'app:create_app()' |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,42 @@ | ||
from app import db | ||
|
||
|
||
|
||
class Task(db.Model): | ||
task_id = db.Column(db.Integer, primary_key=True) | ||
task_id = db.Column(db.Integer, primary_key=True, autoincrement=True, nullable=False) | ||
title = db.Column(db.String) | ||
description = db.Column(db.String) | ||
completed_at = db.Column(db.DateTime,default=None,nullable=True) | ||
goals = db.relationship("Goal") | ||
goal_id = db.Column(db.Integer, db.ForeignKey('goal.goal_id'), nullable=True) | ||
|
||
|
||
|
||
def to_json(self): | ||
if self.completed_at: | ||
is_completed=True | ||
else: | ||
is_completed=False | ||
task_dict= { | ||
"id": self.task_id, | ||
"title": self.title, | ||
"description": self.description, | ||
"is_complete": is_completed, | ||
} | ||
if self.goal_id: | ||
task_dict["goal_id"] = self.goal_id | ||
return task_dict | ||
|
||
def to_json_without_des(self): | ||
if self.completed_at: | ||
is_completed=True | ||
else: | ||
is_completed=False | ||
return { | ||
"id": self.task_id, | ||
"title": self.title, | ||
"description": "", | ||
"is_complete": is_completed, | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
@@ -1 +1,286 @@ | ||||||||||
from flask import Blueprint | ||||||||||
|
||||||||||
from app.models.task import Task | ||||||||||
from app.models.goal import Goal | ||||||||||
from app import db | ||||||||||
from flask import Blueprint, jsonify,abort,make_response,request | ||||||||||
from sqlalchemy.sql.functions import now | ||||||||||
import os | ||||||||||
import requests | ||||||||||
|
||||||||||
|
||||||||||
task_list_bp = Blueprint("task_list", __name__,url_prefix="/tasks") | ||||||||||
goal_list_bp = Blueprint("goal_list", __name__,url_prefix="/goals") | ||||||||||
Comment on lines
+11
to
+12
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. one thing we could do to help with too much in one file is by separating these two blueprints out into their own files. This can help bigger teams work on different tasks in a project without stepping on each other's toes. |
||||||||||
|
||||||||||
|
||||||||||
def validate_task(task_id): | ||||||||||
try: | ||||||||||
task_id = int(task_id) | ||||||||||
except: | ||||||||||
abort(make_response({"message":f"task {task_id} invalid"}, 400)) | ||||||||||
|
||||||||||
task = Task.query.get(task_id) | ||||||||||
|
||||||||||
if not task: | ||||||||||
abort(make_response({"message":f"task {task_id} not found"}, 404)) | ||||||||||
|
||||||||||
return task | ||||||||||
Comment on lines
+15
to
+26
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we could put this in a separate file to keep our routes file tidier |
||||||||||
|
||||||||||
|
||||||||||
|
||||||||||
Comment on lines
+27
to
+29
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||
|
||||||||||
#Get tasks sorted or get all tasks | ||||||||||
@task_list_bp.route("", methods=["GET"]) | ||||||||||
def get_tasks_sorted(): | ||||||||||
|
||||||||||
sort_query = request.args.get("sort") | ||||||||||
|
||||||||||
|
||||||||||
if sort_query and sort_query=="asc": | ||||||||||
tasks= Task.query.order_by(Task.title.asc()) | ||||||||||
elif sort_query and sort_query=="desc": | ||||||||||
tasks= Task.query.order_by(Task.title.desc()) | ||||||||||
else: | ||||||||||
tasks = Task.query.all() | ||||||||||
|
||||||||||
|
||||||||||
|
||||||||||
Comment on lines
+44
to
+46
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. be careful with too much blank lines! it can make code harder to read
Suggested change
|
||||||||||
task_response = [] | ||||||||||
for task in tasks: | ||||||||||
task_response.append(task.to_json()) | ||||||||||
return make_response( jsonify(task_response),200) | ||||||||||
|
||||||||||
|
||||||||||
|
||||||||||
Comment on lines
+51
to
+53
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||
|
||||||||||
#Get one task | ||||||||||
@task_list_bp.route("/<task_id>", methods=["GET"]) | ||||||||||
def get_one_task(task_id): | ||||||||||
|
||||||||||
task = Task.query.get(task_id) | ||||||||||
|
||||||||||
if task: | ||||||||||
return { | ||||||||||
"task": task.to_json() | ||||||||||
} | ||||||||||
Comment on lines
+62
to
+64
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this works, but don't forget your status code! every response we return to our client should be consistent and predictable
Suggested change
|
||||||||||
else: | ||||||||||
return make_response(jsonify(None), 404) | ||||||||||
|
||||||||||
|
||||||||||
|
||||||||||
#Create one task | ||||||||||
@task_list_bp.route("", methods=["POST"]) | ||||||||||
def create_new_task(): | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||||||||||
|
||||||||||
request_body = request.get_json() | ||||||||||
if "title" not in request_body or "description" not in request_body: | ||||||||||
return make_response({"details":f"Invalid data"}, 400) | ||||||||||
|
||||||||||
new_task = Task(title=request_body["title"], | ||||||||||
description=request_body["description"], | ||||||||||
) | ||||||||||
if "completed_at" in request_body: | ||||||||||
new_task.completed_at = request_body["completed_at"] | ||||||||||
|
||||||||||
|
||||||||||
db.session.add(new_task) | ||||||||||
db.session.commit() | ||||||||||
|
||||||||||
return jsonify({"task":new_task.to_json()}),201 | ||||||||||
|
||||||||||
|
||||||||||
|
||||||||||
#Update one task | ||||||||||
@task_list_bp.route("/<task_id>", methods=["PUT"]) | ||||||||||
def update_task(task_id): | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||||||||||
task = validate_task(task_id) | ||||||||||
|
||||||||||
request_body = request.get_json() | ||||||||||
|
||||||||||
task.title = request_body["title"] | ||||||||||
task.description = request_body["description"] | ||||||||||
|
||||||||||
db.session.commit() | ||||||||||
|
||||||||||
return jsonify({"task":task.to_json()}),200 | ||||||||||
|
||||||||||
|
||||||||||
#Delete one task | ||||||||||
@task_list_bp.route("/<task_id>", methods=["DELETE"]) | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||||||||||
def delete_task(task_id): | ||||||||||
task = validate_task(task_id) | ||||||||||
|
||||||||||
db.session.delete(task) | ||||||||||
db.session.commit() | ||||||||||
|
||||||||||
return make_response({"details":f'Task {task.task_id} \"{task.title}\" successfully deleted'}),200 | ||||||||||
|
||||||||||
|
||||||||||
|
||||||||||
|
||||||||||
#Mark complete for one task and use Slack API | ||||||||||
@task_list_bp.route('/<task_id>/mark_complete', methods=['PATCH']) | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||||||||||
def mark_complete(task_id): | ||||||||||
task=Task.query.get(task_id) | ||||||||||
if not task: | ||||||||||
abort(make_response({"message":f"task {task_id} not found"}, 404)) | ||||||||||
task.completed_at = now() | ||||||||||
db.session.add(task) | ||||||||||
db.session.commit() | ||||||||||
|
||||||||||
|
||||||||||
slack_api_url = "https://slack.com/api/chat.postMessage" | ||||||||||
params = { | ||||||||||
"channel" : "test-channel", | ||||||||||
"text" : f"Someone just completed the task {task.title}" | ||||||||||
} | ||||||||||
headers = { | ||||||||||
"Authorization" : f"Bearer {os.environ.get('SLACK_API_HEADER')}" | ||||||||||
} | ||||||||||
requests.get(url=slack_api_url, params=params, headers=headers) | ||||||||||
|
||||||||||
return make_response(jsonify({"task" : task.to_json()})) | ||||||||||
|
||||||||||
|
||||||||||
#Mark incomplete for one task | ||||||||||
@task_list_bp.route('/<task_id>/mark_incomplete', methods=['PATCH']) | ||||||||||
def mark_incomplete(task_id): | ||||||||||
task=Task.query.get(task_id) | ||||||||||
if not task: | ||||||||||
abort(make_response({"message":f"task {task_id} not found"}, 404)) | ||||||||||
task.completed_at = None | ||||||||||
db.session.add(task) | ||||||||||
db.session.commit() | ||||||||||
task_response={"task":{ | ||||||||||
"id": task.task_id, | ||||||||||
"title": task.title, | ||||||||||
"description": task.description, "is_complete": False | ||||||||||
}} | ||||||||||
Comment on lines
+153
to
+157
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we could turn this into a helper method |
||||||||||
return jsonify(task_response),200 | ||||||||||
|
||||||||||
#*******************************Goal_routes******************************************* | ||||||||||
|
||||||||||
def validate_goal(goal_id): | ||||||||||
try: | ||||||||||
goal_id = int(goal_id) | ||||||||||
except: | ||||||||||
abort(make_response({"message":f"goal {goal_id} invalid"}, 400)) | ||||||||||
|
||||||||||
goal = Goal.query.get(goal_id) | ||||||||||
|
||||||||||
if not goal: | ||||||||||
abort(make_response({"message":f"goal {goal_id} not found"}, 404)) | ||||||||||
|
||||||||||
return goal | ||||||||||
Comment on lines
+162
to
+173
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This would be another function we could move into another file |
||||||||||
|
||||||||||
|
||||||||||
#Create one goal | ||||||||||
@goal_list_bp.route("", methods=["post"]) | ||||||||||
def create_new_goal(): | ||||||||||
|
||||||||||
request_body = request.get_json() | ||||||||||
if "title" not in request_body: | ||||||||||
return { | ||||||||||
"details": "Invalid data" | ||||||||||
},400 | ||||||||||
new_goal = Goal(title=request_body["title"], | ||||||||||
) | ||||||||||
Comment on lines
+185
to
+186
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||
|
||||||||||
|
||||||||||
db.session.add(new_goal) | ||||||||||
db.session.commit() | ||||||||||
|
||||||||||
return {"goal":{"id":new_goal.goal_id, "title":new_goal.title}},201 | ||||||||||
|
||||||||||
|
||||||||||
|
||||||||||
#Get one goal | ||||||||||
@goal_list_bp.route("/<goal_id>", methods=["GET"]) | ||||||||||
def get_one_goal(goal_id): | ||||||||||
goal = validate_goal(goal_id) | ||||||||||
|
||||||||||
return{"goal": { | ||||||||||
"id": goal.goal_id, | ||||||||||
"title": goal.title, | ||||||||||
}} | ||||||||||
Comment on lines
+201
to
+204
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. don't forget your status code! |
||||||||||
|
||||||||||
|
||||||||||
#Get all goals | ||||||||||
@goal_list_bp.route("", methods=["GET"]) | ||||||||||
def get_all_goal(): | ||||||||||
goals = Goal.query.all() | ||||||||||
|
||||||||||
goal_response = [] | ||||||||||
for goal in goals: | ||||||||||
goal_response.append({ | ||||||||||
"id": goal.goal_id, | ||||||||||
"title": goal.title, | ||||||||||
|
||||||||||
}) | ||||||||||
return jsonify(goal_response),200 | ||||||||||
|
||||||||||
|
||||||||||
#Update one goal | ||||||||||
@goal_list_bp.route("/<goal_id>", methods=["PUT"]) | ||||||||||
def update_goal(goal_id): | ||||||||||
goal = validate_goal(goal_id) | ||||||||||
|
||||||||||
request_body = request.get_json() | ||||||||||
|
||||||||||
goal.title = request_body["title"] | ||||||||||
goal.decription = request_body["description"] | ||||||||||
|
||||||||||
|
||||||||||
db.session.commit() | ||||||||||
|
||||||||||
return make_response(jsonify(f"goal #{goal.goal_id} successfully updated")),200 | ||||||||||
|
||||||||||
|
||||||||||
#Delete one goal | ||||||||||
@goal_list_bp.route("/<goal_id>", methods=["DELETE"]) | ||||||||||
def delete_goal(goal_id): | ||||||||||
goal = validate_goal(goal_id) | ||||||||||
|
||||||||||
db.session.delete(goal) | ||||||||||
db.session.commit() | ||||||||||
|
||||||||||
return {"details":f"Goal {goal.goal_id} \"{goal.title}\" successfully deleted"} | ||||||||||
|
||||||||||
|
||||||||||
#********************************Nested routes************************************ | ||||||||||
|
||||||||||
#Show tasks for a goal | ||||||||||
@goal_list_bp.route("/<goal_id>/tasks", methods=["GET"]) | ||||||||||
def show_tasks_for_a_goal(goal_id): | ||||||||||
goal = validate_goal(goal_id) | ||||||||||
tasks = Task.query.filter_by(goal=goal) | ||||||||||
task_list = [] | ||||||||||
|
||||||||||
for task in tasks: | ||||||||||
task_list.append(task.to_json()) | ||||||||||
return make_response(jsonify({ | ||||||||||
"id": goal.goal_id, | ||||||||||
"title": goal.title, | ||||||||||
"tasks": task_list | ||||||||||
Comment on lines
+256
to
+263
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. just as we made a |
||||||||||
}), 200) | ||||||||||
|
||||||||||
|
||||||||||
#Post tasks to a goal | ||||||||||
@goal_list_bp.route("/<goal_id>/tasks", methods=["POST"]) | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||||||||||
def posts_tasks_to_a_goal(goal_id): | ||||||||||
goal = validate_goal(goal_id) | ||||||||||
|
||||||||||
|
||||||||||
|
||||||||||
Comment on lines
+271
to
+273
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||
request_body = request.get_json() | ||||||||||
for task_id in request_body["task_ids"]: | ||||||||||
task = Task.query.get(task_id) | ||||||||||
|
||||||||||
task.goal_id=goal.goal_id | ||||||||||
if not task: | ||||||||||
abort(make_response({"message":f"task {task_id} invalid"}, 400)) | ||||||||||
|
||||||||||
|
||||||||||
goal.tasks.append(task) | ||||||||||
db.session.commit() | ||||||||||
|
||||||||||
return make_response(jsonify({"id":goal.goal_id,"task_ids":request_body["task_ids"]}),200) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Generic single-database configuration. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 ohhh cool! Interesting way to separate out which tasks need which attributes! I wonder if we could combine these two methods back together with an if statement, though. Something to think about!