generated from prof-rossetti/flask-sheets-template-2023
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* assignments now viewable * assignments now viewable
- Loading branch information
1 parent
58d7212
commit 8342237
Showing
6 changed files
with
124 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,18 +14,20 @@ | |
import gspread | ||
from gspread.exceptions import SpreadsheetNotFound | ||
|
||
import time | ||
|
||
|
||
load_dotenv() | ||
|
||
DEFAULT_FILEPATH = os.path.join(os.path.dirname(__file__), "..", "gradebook-hero-google-credentials.json") | ||
GOOGLE_CREDENTIALS_FILEPATH = os.getenv("GOOGLE_CREDENTIALS_FILEPATH", default=DEFAULT_FILEPATH) | ||
|
||
GOOGLE_SHEETS_DOCUMENT_ID = os.getenv("GOOGLE_SHEETS_DOCUMENT_ID", default="OOPS Please get the spreadsheet identifier from its URL, and set the 'GOOGLE_SHEETS_DOCUMENT_ID' environment variable accordingly...") | ||
GOOGLE_SHEETS_MASTER_DOCUMENT_ID = os.getenv("GOOGLE_SHEETS_MASTER_DOCUMENT_ID", default="OOPS Please get the spreadsheet identifier from its URL, and set the 'GOOGLE_SHEETS_DOCUMENT_ID' environment variable accordingly...") | ||
|
||
|
||
class SpreadsheetService: | ||
|
||
def __init__(self, credentials_filepath=GOOGLE_CREDENTIALS_FILEPATH, document_id=GOOGLE_SHEETS_DOCUMENT_ID): | ||
def __init__(self, credentials_filepath=GOOGLE_CREDENTIALS_FILEPATH, document_id=GOOGLE_SHEETS_MASTER_DOCUMENT_ID): | ||
print("INITIALIZING NEW SPREADSHEET SERVICE...") | ||
self.client = gspread.service_account(filename=credentials_filepath) | ||
self.document_id = document_id | ||
|
@@ -43,32 +45,80 @@ def parse_timestamp(ts:str): | |
date_format = "%Y-%m-%d %H:%M:%S.%f%z" | ||
return datetime.strptime(ts, date_format) | ||
|
||
@staticmethod | ||
def to_pct(frac): | ||
return f'{float(frac)*100:.2f}%' | ||
|
||
@property | ||
def doc(self): | ||
"""note: this will make an API call each time, to get the new data""" | ||
return self.client.open_by_key(self.document_id) #> <class 'gspread.models.Spreadsheet'> | ||
|
||
def set_active_document(self, document_id): | ||
self.document_id = document_id | ||
|
||
def get_sheet(self, sheet_name): | ||
return self.doc.worksheet(sheet_name) | ||
|
||
def get_final_grade(self, username): | ||
""" | ||
Gets all records from a sheet, | ||
""" | ||
#print(f"GETTING RECORDS FROM SHEET: '{sheet_name}'") | ||
sheet = self.get_sheet("gradebook-final") #> <class 'gspread.models.Worksheet'> | ||
row_index = sheet.col_values(1).index(f'#{username}') + 1 | ||
return sheet.row_values(row_index) | ||
|
||
def get_assignment_grade(self, username, assignment_name): | ||
sheet = self.get_sheet(f"{assignment_name}-mjr") #> <class 'gspread.models.Worksheet'> | ||
row_index = sheet.col_values(3).index(username) + 1 | ||
return sheet.row_values(row_index) | ||
##################### | ||
# COURSES FUNCTIONS # | ||
##################### | ||
|
||
def get_student_courses(self, email:str) -> list: | ||
self.set_active_document(GOOGLE_SHEETS_MASTER_DOCUMENT_ID) | ||
students_sheet = self.get_sheet("students_roster") | ||
all_student_course_ids = students_sheet.get_all_records() | ||
student_course_ids = [course["COURSE_ID"] for course in all_student_course_ids if course["STUDENT_EMAIL"] == email] | ||
|
||
courses_sheet = self.get_sheet("courses") | ||
all_courses = courses_sheet.get_all_records() | ||
|
||
student_courses_info = [course_info for course_info in all_courses if course_info["COURSE_ID"] in student_course_ids] | ||
|
||
return student_courses_info | ||
|
||
|
||
def get_course_assignments(self, student_email:str, course_id:str) -> list: | ||
#if coming from "courses" page, the active document will be "MASTER" | ||
#we want to change that to the document ID of the specific course | ||
if self.doc.id == GOOGLE_SHEETS_MASTER_DOCUMENT_ID: | ||
courses_sheet = self.get_sheet("courses") | ||
courses_records = courses_sheet.get_all_records() | ||
|
||
course_document_id_list = [c["SHEETS_DOCUMENT_ID"] for c in courses_records if c["COURSE_ID"] == int(course_id)] | ||
|
||
if len(course_document_id_list) == 0: | ||
raise Exception("course not found...") | ||
#TODO: handle within the route | ||
if len(course_document_id_list) > 1: | ||
raise Exception("course duplicate found...error") | ||
#TODO: handle within the route | ||
|
||
self.set_active_document(course_document_id_list[0]) | ||
|
||
# now, get the assignments from the sheet | ||
assignments_sheet = self.get_sheet("ASSIGNMENT_MASTER") | ||
assignments_records = assignments_sheet.get_all_records() | ||
|
||
|
||
#assign the student email to the sheet that calculates scores... | ||
scores_sheet = self.get_sheet("STUDENT_SCORES") | ||
scores_sheet.update_acell("K2", student_email) | ||
|
||
#find the assignment scores... | ||
for i in range(len(assignments_records)): | ||
del assignments_records[i]["SHEET_NAME"] | ||
assignments_records[i]["GRADE"] = self.to_pct(scores_sheet.cell(i + 2, 9).value) | ||
|
||
#clear the email | ||
scores_sheet.update_acell("K2", "") | ||
|
||
return assignments_records | ||
|
||
|
||
|
||
if __name__ == "__main__": | ||
|
||
ss = SpreadsheetService() | ||
|
||
ss.get_assignment_grade("mb6244", "stocks") | ||
ss.get_course_assignments("[email protected]", "12345") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
from flask import Blueprint, render_template, flash, redirect, current_app, url_for, session, request #, jsonify | ||
|
||
courses_routes = Blueprint("courses_routes", __name__) | ||
|
||
from web_app.routes.wrappers import student_authenticated_route | ||
|
||
@courses_routes.route("/courses/<course_id>") | ||
@student_authenticated_route | ||
def course(course_id): | ||
ss = current_app.config["SPREADSHEET_SERVICE"] | ||
current_user = session.get("current_user") | ||
email = current_user["email"] | ||
#TODO: change hard coded email to "email" fetched from session | ||
assignments_list = ss.get_course_assignments("[email protected]", course_id) | ||
return render_template("assignments.html", assignments=assignments_list) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
{% extends "bootstrap_5_layout.html" %} | ||
{% set active_page = "courses" %} | ||
|
||
{% block content %} | ||
|
||
<h1>My Assignments</h1> | ||
|
||
<table class="table table-hover text-center"> | ||
<thead> | ||
<tr> | ||
<th scope="col">Assignment</th> | ||
<th scope="col">Due Date</th> | ||
<th scope="col">Points</th> | ||
<th scope="col">Grade</th> | ||
</tr> | ||
<tbody> | ||
{% for a in assignments %} | ||
<tr> | ||
<td> | ||
{{ a.NAME }} | ||
</td> | ||
<td> | ||
{{ a.DUE_DATE }} | ||
</td> | ||
<td> | ||
{{ a.POINTS }} | ||
</td> | ||
<td> | ||
{{ a.GRADE }} | ||
</td> | ||
</tr> | ||
{% endfor %} | ||
</tbody> | ||
</thead> | ||
</table> | ||
|
||
{% endblock %} |