-
Notifications
You must be signed in to change notification settings - Fork 71
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
Rock Saharai Cante #66
base: master
Are you sure you want to change the base?
Changes from all commits
2120c26
f78215b
f720cd4
da7cf01
8745c8a
e9759d8
8075c48
9266d9e
fb62a4c
32dd814
a5a09db
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 |
---|---|---|
@@ -1,6 +1,21 @@ | ||
from flask import current_app | ||
from sqlalchemy.orm import relationship | ||
from app import db | ||
from app.models.task import Task | ||
from sqlalchemy import Table, Column, Integer, ForeignKey | ||
from sqlalchemy.orm import relationship | ||
from sqlalchemy.ext.declarative import declarative_base | ||
Comment on lines
+4
to
+7
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. hm... |
||
|
||
Base = declarative_base() | ||
|
||
|
||
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) | ||
|
||
#helper function-returns goal attributes in corrected format | ||
def goal_to_json(self): | ||
goal_dict={"id": self.goal_id, | ||
"title": self.title} | ||
return goal_dict | ||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -1,6 +1,41 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
from flask import current_app | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
from sqlalchemy.orm import backref | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
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) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
title= db.Column(db.String) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
description= db.Column(db.String) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
completed_at=db.Column(db.DateTime, nullable=True, default=None) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
#establishing one to many relationship with Goal | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
goal_id = db.Column(db.Integer,db.ForeignKey('goal.goal_id'), nullable=True) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
goal = db.relationship("Goal",backref=db.backref('tasks'),lazy=True) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
#returns True when there is a task completed | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
def is_complete(self): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
if self.completed_at==None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
return False | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
else: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
return True | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
#runs to determine which body to return based on goal bool status | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
def to_json(self): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
if self.goal_id == None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
task_dict={ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
"id": self.task_id, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
"title": self.title, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
"description": self.description, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
"is_complete": self.is_complete() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
else: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
task_dict={ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
"id": self.task_id, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
"goal_id": self.goal_id, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
"title": self.title, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
"description": self.description, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
"is_complete": self.is_complete() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
return task_dict | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+25
to
+40
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. Nice! Great job Saharai. You could refactor this into a single dictionary like so:
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -1,2 +1,293 @@ | ||||||||||||||||||||||
from flask import Blueprint | ||||||||||||||||||||||
from flask import request,Blueprint,make_response,jsonify | ||||||||||||||||||||||
from werkzeug.datastructures import Authorization | ||||||||||||||||||||||
|
||||||||||||||||||||||
from app import db | ||||||||||||||||||||||
from app.models.task import Task | ||||||||||||||||||||||
from datetime import datetime | ||||||||||||||||||||||
import requests | ||||||||||||||||||||||
import os | ||||||||||||||||||||||
|
||||||||||||||||||||||
|
||||||||||||||||||||||
|
||||||||||||||||||||||
task_bp = Blueprint("task", __name__, url_prefix="/tasks") | ||||||||||||||||||||||
|
||||||||||||||||||||||
@task_bp.route("", methods=["GET"]) | ||||||||||||||||||||||
def get_tasks(): | ||||||||||||||||||||||
|
||||||||||||||||||||||
title_query = request.args.get("title") | ||||||||||||||||||||||
if title_query: | ||||||||||||||||||||||
tasks = Task.query.filter_by(title=title_query) | ||||||||||||||||||||||
|
||||||||||||||||||||||
else: | ||||||||||||||||||||||
tasks = Task.query.all() | ||||||||||||||||||||||
|
||||||||||||||||||||||
tasks_response = [] | ||||||||||||||||||||||
for task in tasks: | ||||||||||||||||||||||
tasks_response.append(task.to_json()) | ||||||||||||||||||||||
|
||||||||||||||||||||||
if "asc" in request.full_path: | ||||||||||||||||||||||
sort_tasks=sorted(tasks_response, key = lambda i: i['title']) | ||||||||||||||||||||||
return jsonify(sort_tasks) | ||||||||||||||||||||||
|
||||||||||||||||||||||
elif "desc" in request.full_path: | ||||||||||||||||||||||
sort_tasks=sorted(tasks_response, key = lambda i: i['title'], reverse=True) | ||||||||||||||||||||||
return jsonify(sort_tasks) | ||||||||||||||||||||||
|
||||||||||||||||||||||
else: | ||||||||||||||||||||||
return jsonify(tasks_response) | ||||||||||||||||||||||
Comment on lines
+15
to
+37
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. beautiful sort by title function! |
||||||||||||||||||||||
|
||||||||||||||||||||||
@task_bp.route("", methods=["POST"]) | ||||||||||||||||||||||
def post_tasks(): | ||||||||||||||||||||||
|
||||||||||||||||||||||
request_body = request.get_json() | ||||||||||||||||||||||
|
||||||||||||||||||||||
if all(keys in request_body for keys in ("title","description","completed_at"))== False: | ||||||||||||||||||||||
return { | ||||||||||||||||||||||
"details": "Invalid data" | ||||||||||||||||||||||
},400 | ||||||||||||||||||||||
Comment on lines
+44
to
+47
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. Clever way of checking for values in the request body ! |
||||||||||||||||||||||
else: | ||||||||||||||||||||||
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() | ||||||||||||||||||||||
|
||||||||||||||||||||||
task = Task.query.get(new_task.task_id) | ||||||||||||||||||||||
return { | ||||||||||||||||||||||
"task": task.to_json() | ||||||||||||||||||||||
}, 201 | ||||||||||||||||||||||
|
||||||||||||||||||||||
|
||||||||||||||||||||||
@task_bp.route("/<task_id>", methods=["GET"]) | ||||||||||||||||||||||
def get_task(task_id): | ||||||||||||||||||||||
task = Task.query.get(task_id) | ||||||||||||||||||||||
|
||||||||||||||||||||||
if task is None: | ||||||||||||||||||||||
return make_response ("",404) | ||||||||||||||||||||||
else: | ||||||||||||||||||||||
return {"task":task.to_json()},200 | ||||||||||||||||||||||
Comment on lines
+66
to
+71
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. You can refine this function into a fewer lines by using Flask's own
Suggested change
|
||||||||||||||||||||||
|
||||||||||||||||||||||
|
||||||||||||||||||||||
@task_bp.route("/<task_id>", methods=["PUT"]) | ||||||||||||||||||||||
def put_task(task_id): | ||||||||||||||||||||||
task = Task.query.get(task_id) | ||||||||||||||||||||||
|
||||||||||||||||||||||
if task is None: | ||||||||||||||||||||||
return make_response ("",404) | ||||||||||||||||||||||
else: | ||||||||||||||||||||||
form_data = request.get_json() | ||||||||||||||||||||||
|
||||||||||||||||||||||
task.title=form_data["title"] | ||||||||||||||||||||||
task.description=form_data["description"] | ||||||||||||||||||||||
task.completed_at=form_data["completed_at"] | ||||||||||||||||||||||
|
||||||||||||||||||||||
db.session.commit() | ||||||||||||||||||||||
|
||||||||||||||||||||||
return { | ||||||||||||||||||||||
"task": task.to_json() | ||||||||||||||||||||||
}, 200 | ||||||||||||||||||||||
|
||||||||||||||||||||||
@task_bp.route("/<task_id>", methods=["DELETE"]) | ||||||||||||||||||||||
def delete_task(task_id): | ||||||||||||||||||||||
task = Task.query.get(task_id) | ||||||||||||||||||||||
|
||||||||||||||||||||||
if task is None: | ||||||||||||||||||||||
return make_response ("",404) | ||||||||||||||||||||||
else: | ||||||||||||||||||||||
|
||||||||||||||||||||||
db.session.delete(task) | ||||||||||||||||||||||
|
||||||||||||||||||||||
db.session.commit() | ||||||||||||||||||||||
|
||||||||||||||||||||||
|
||||||||||||||||||||||
return make_response({ | ||||||||||||||||||||||
"details": f'Task {task.task_id} \"{task.title}\" successfully deleted' | ||||||||||||||||||||||
}, 200) | ||||||||||||||||||||||
|
||||||||||||||||||||||
@task_bp.route("/<task_id>/mark_incomplete", methods=["PATCH"]) | ||||||||||||||||||||||
def mark_incomplete(task_id): | ||||||||||||||||||||||
task = Task.query.get(task_id) | ||||||||||||||||||||||
if task is None: | ||||||||||||||||||||||
return make_response ("",404) | ||||||||||||||||||||||
|
||||||||||||||||||||||
task.completed_at=None | ||||||||||||||||||||||
db.session.commit() | ||||||||||||||||||||||
|
||||||||||||||||||||||
return { | ||||||||||||||||||||||
"task": task.to_json() | ||||||||||||||||||||||
}, 200 | ||||||||||||||||||||||
Comment on lines
+111
to
+121
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. Nice this function is really clean! |
||||||||||||||||||||||
|
||||||||||||||||||||||
|
||||||||||||||||||||||
@task_bp.route("/<task_id>/mark_complete", methods=["PATCH"]) | ||||||||||||||||||||||
def mark_complete(task_id): | ||||||||||||||||||||||
task = Task.query.get(task_id) | ||||||||||||||||||||||
if task is None: | ||||||||||||||||||||||
return make_response ("",404) | ||||||||||||||||||||||
|
||||||||||||||||||||||
task.completed_at=datetime.utcnow() | ||||||||||||||||||||||
db.session.commit() | ||||||||||||||||||||||
|
||||||||||||||||||||||
|
||||||||||||||||||||||
url = f"https://slack.com/api/chat.postMessage?channel=task-notifications&text=Someone just completed the task {task.title}" | ||||||||||||||||||||||
|
||||||||||||||||||||||
|
||||||||||||||||||||||
|
||||||||||||||||||||||
token=os.environ.get("bot_user_token") | ||||||||||||||||||||||
|
||||||||||||||||||||||
|
||||||||||||||||||||||
headers_dict={"Authorization":token} | ||||||||||||||||||||||
response = requests.request("POST", url, headers=headers_dict) | ||||||||||||||||||||||
return { | ||||||||||||||||||||||
"task": { | ||||||||||||||||||||||
"id": task.task_id, | ||||||||||||||||||||||
"title": task.title, | ||||||||||||||||||||||
"description":task.description, | ||||||||||||||||||||||
"is_complete": task.is_complete() | ||||||||||||||||||||||
} | ||||||||||||||||||||||
}, 200 | ||||||||||||||||||||||
Comment on lines
+134
to
+150
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. Great job in getting your slack bot to work. A future refactor can include putting this logic into a helper function. |
||||||||||||||||||||||
|
||||||||||||||||||||||
|
||||||||||||||||||||||
|
||||||||||||||||||||||
from app.models.goal import Goal | ||||||||||||||||||||||
goal_bp = Blueprint("goal", __name__, url_prefix="/goals") | ||||||||||||||||||||||
|
||||||||||||||||||||||
@goal_bp.route("", methods=["GET"]) | ||||||||||||||||||||||
def get_goals(): | ||||||||||||||||||||||
|
||||||||||||||||||||||
title_query = request.args.get("title") | ||||||||||||||||||||||
if title_query: | ||||||||||||||||||||||
goals = Goal.query.filter_by(title=title_query) | ||||||||||||||||||||||
|
||||||||||||||||||||||
else: | ||||||||||||||||||||||
goals = Goal.query.all() | ||||||||||||||||||||||
|
||||||||||||||||||||||
goals_response = [] | ||||||||||||||||||||||
for goal in goals: | ||||||||||||||||||||||
goals_response.append(goal.goal_to_json()) | ||||||||||||||||||||||
|
||||||||||||||||||||||
if "asc" in request.full_path: | ||||||||||||||||||||||
|
||||||||||||||||||||||
sort_goals=sorted(goals_response, key = lambda i: i['title']) | ||||||||||||||||||||||
|
||||||||||||||||||||||
return jsonify(sort_goals) | ||||||||||||||||||||||
|
||||||||||||||||||||||
elif "desc" in request.full_path: | ||||||||||||||||||||||
sort_goals=sorted(goals_response, key = lambda i: i['title'], reverse=True) | ||||||||||||||||||||||
Comment on lines
+173
to
+178
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. LOVING the use of |
||||||||||||||||||||||
return jsonify(sort_goals) | ||||||||||||||||||||||
|
||||||||||||||||||||||
else: | ||||||||||||||||||||||
return jsonify(goals_response) | ||||||||||||||||||||||
|
||||||||||||||||||||||
@goal_bp.route("", methods=["POST"]) | ||||||||||||||||||||||
def post_goals(): | ||||||||||||||||||||||
|
||||||||||||||||||||||
request_body = request.get_json() | ||||||||||||||||||||||
|
||||||||||||||||||||||
if "title" not in request_body: | ||||||||||||||||||||||
return { | ||||||||||||||||||||||
"details": "Invalid data" | ||||||||||||||||||||||
},400 | ||||||||||||||||||||||
else: | ||||||||||||||||||||||
new_goal = Goal(title=request_body["title"]) | ||||||||||||||||||||||
|
||||||||||||||||||||||
db.session.add(new_goal) | ||||||||||||||||||||||
db.session.commit() | ||||||||||||||||||||||
|
||||||||||||||||||||||
get_goal = Goal.query.get(new_goal.goal_id) | ||||||||||||||||||||||
|
||||||||||||||||||||||
return { | ||||||||||||||||||||||
"goal": get_goal.goal_to_json() | ||||||||||||||||||||||
}, 201 | ||||||||||||||||||||||
|
||||||||||||||||||||||
|
||||||||||||||||||||||
@goal_bp.route("/<goal_id>", methods=["GET"]) | ||||||||||||||||||||||
def get_goal(goal_id): | ||||||||||||||||||||||
goal = Goal.query.get(goal_id) | ||||||||||||||||||||||
|
||||||||||||||||||||||
if goal is None: | ||||||||||||||||||||||
return make_response ("",404) | ||||||||||||||||||||||
else: | ||||||||||||||||||||||
return { | ||||||||||||||||||||||
"goal": goal.goal_to_json() | ||||||||||||||||||||||
}, 200 | ||||||||||||||||||||||
|
||||||||||||||||||||||
@goal_bp.route("/<goal_id>", methods=["PUT"]) | ||||||||||||||||||||||
def put_goal(goal_id): | ||||||||||||||||||||||
goal = Goal.query.get(goal_id) | ||||||||||||||||||||||
|
||||||||||||||||||||||
if goal is None: | ||||||||||||||||||||||
return make_response ("",404) | ||||||||||||||||||||||
else: | ||||||||||||||||||||||
form_data = request.get_json() | ||||||||||||||||||||||
|
||||||||||||||||||||||
goal.title=form_data["title"] | ||||||||||||||||||||||
|
||||||||||||||||||||||
|
||||||||||||||||||||||
#db.session.add(new_data) #adding data to db(a record/row) i.e git add | ||||||||||||||||||||||
db.session.commit() | ||||||||||||||||||||||
#new_task = Task.query.get(new_data.task_id) | ||||||||||||||||||||||
return { | ||||||||||||||||||||||
"goal": goal.goal_to_json() | ||||||||||||||||||||||
}, 200 | ||||||||||||||||||||||
|
||||||||||||||||||||||
|
||||||||||||||||||||||
@goal_bp.route("/<goal_id>", methods=["DELETE"]) | ||||||||||||||||||||||
def delete_goal(goal_id): | ||||||||||||||||||||||
goal = Goal.query.get(goal_id) | ||||||||||||||||||||||
|
||||||||||||||||||||||
if goal is None: | ||||||||||||||||||||||
return make_response ("",404) | ||||||||||||||||||||||
else: | ||||||||||||||||||||||
db.session.delete(goal) | ||||||||||||||||||||||
|
||||||||||||||||||||||
db.session.commit() | ||||||||||||||||||||||
|
||||||||||||||||||||||
return make_response({ | ||||||||||||||||||||||
"details": f'Goal {goal.goal_id} \"{goal.title}\" successfully deleted' | ||||||||||||||||||||||
}, 200) | ||||||||||||||||||||||
|
||||||||||||||||||||||
@goal_bp.route("/<goal_id>/tasks", methods=["POST"]) | ||||||||||||||||||||||
def post_task_id_to_goal(goal_id): | ||||||||||||||||||||||
request_body=request.get_json() #information passed in given in json | ||||||||||||||||||||||
goal=Goal.query.get(goal_id) #grab my goal from db and bring it back | ||||||||||||||||||||||
|
||||||||||||||||||||||
|
||||||||||||||||||||||
if not goal: | ||||||||||||||||||||||
return make_response("",404) | ||||||||||||||||||||||
else: | ||||||||||||||||||||||
for task_id in request_body["task_ids"]: | ||||||||||||||||||||||
task=Task.query.get(task_id) | ||||||||||||||||||||||
task.goal_id=goal_id | ||||||||||||||||||||||
db.session.commit() | ||||||||||||||||||||||
|
||||||||||||||||||||||
return { | ||||||||||||||||||||||
"id": goal.goal_id, | ||||||||||||||||||||||
"task_ids": request_body["task_ids"] | ||||||||||||||||||||||
},200 | ||||||||||||||||||||||
|
||||||||||||||||||||||
|
||||||||||||||||||||||
@goal_bp.route("/<goal_id>/tasks", methods=["GET"]) | ||||||||||||||||||||||
def get_tasks_for_goal(goal_id): | ||||||||||||||||||||||
|
||||||||||||||||||||||
goal=Goal.query.get(goal_id) | ||||||||||||||||||||||
task = Task.query.get(goal_id) | ||||||||||||||||||||||
|
||||||||||||||||||||||
|
||||||||||||||||||||||
if not goal: | ||||||||||||||||||||||
return make_response("",404) | ||||||||||||||||||||||
else: | ||||||||||||||||||||||
|
||||||||||||||||||||||
outer_dict=goal.goal_to_json() | ||||||||||||||||||||||
if task==None: | ||||||||||||||||||||||
outer_dict['tasks']=[] | ||||||||||||||||||||||
else: | ||||||||||||||||||||||
inner_dict=task.to_json() | ||||||||||||||||||||||
|
||||||||||||||||||||||
inner_dict["goal_id"]=goal.goal_id | ||||||||||||||||||||||
outer_dict['tasks']=[inner_dict] | ||||||||||||||||||||||
db.session.commit() | ||||||||||||||||||||||
return outer_dict,200 | ||||||||||||||||||||||
Comment on lines
+275
to
+292
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. Great job! This was a very clean way of getting the tasks for a specific goal_id |
||||||||||||||||||||||
|
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.
You can combine imports like so: