Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
f2f4380
initial changes to get dev local server running
henryschoemer Nov 17, 2025
03affe3
Made the passowrd requirements less stict. Started
No-ha63 Nov 19, 2025
30da845
some qol changes to get a delete account feature in
henryschoemer Nov 21, 2025
94bee94
Edited canvasrequests.py to fix get data from data
No-ha63 Nov 25, 2025
9ab77e4
Changed the task that considered not completed are
No-ha63 Nov 25, 2025
e8e9c89
task detection automated
rwind13 Nov 29, 2025
3d4c520
Canvas assignments are categorized. Give different level candies base…
rwind13 Nov 30, 2025
deee323
Rescaled images, added brown and white dog stills/gifs.
dominiquebissey Dec 1, 2025
46b22de
Updated Dependecies to current technology versions
ericeleam Dec 1, 2025
cf11ffa
Task are now ordered by due date. And the calender
No-ha63 Dec 2, 2025
aac839e
Added in a "Past Due" tab, and also fixed a bug
No-ha63 Dec 2, 2025
058529b
Made changes to update landing page.
dominiquebissey Dec 3, 2025
182d8b3
Made changes to Login/Registration page, and added dog options to the…
dominiquebissey Dec 3, 2025
b9cb80a
Added more specific logic for selecting courses based on end dates an…
No-ha63 Dec 3, 2025
25f79c1
Changed name to Task Pet, and made chnages to the tutorial pages.
dominiquebissey Dec 3, 2025
a942175
Made dots under days that have tasks due on CalendarPageDeskop.js and…
No-ha63 Dec 3, 2025
8b2c78a
delete account functionality implemented
henryschoemer Dec 3, 2025
77ad410
Added dogs into main page, and made changes to the main task page lay…
dominiquebissey Dec 4, 2025
75248fe
Added new background, images for click reaction, icon image, and made…
dominiquebissey Dec 5, 2025
75990b1
Assigment Reminder Email File
oswaynesmith Dec 5, 2025
ac2ccbd
Added automatic send for the assignment reminder
oswaynesmith Dec 5, 2025
e4717b0
Merge pull request #2 from dominiquebissey/CSSChanges
No-ha63 Dec 5, 2025
487d08b
More added for automatic reminder email
oswaynesmith Dec 5, 2025
4414ea6
comment edits
oswaynesmith Dec 5, 2025
4519895
Merge pull request #1 from dominiquebissey/public-facing-server
dominiquebissey Dec 5, 2025
dae26b5
Merge pull request #4 from dominiquebissey/CanvasAPIFixtures
dominiquebissey Dec 5, 2025
3f4f3e9
Merge pull request #3 from dominiquebissey/difficulty-automation
dominiquebissey Dec 5, 2025
6cd1de8
Merge pull request #5 from dominiquebissey/reminder-email
dominiquebissey Dec 5, 2025
713d56e
Fix for canvas view
oswaynesmith Dec 5, 2025
3ed4b15
Merge branch 'main' into reminder-email
henryschoemer Dec 5, 2025
ca7724b
Merge pull request #6 from dominiquebissey/reminder-email
henryschoemer Dec 5, 2025
0b22091
Merge branch 'main' into dependTest-merged
ericeleam Dec 7, 2025
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: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
node_modules
pocs-capstone/backend/.env
pocs-capstone/backend/tutorial-env/
pocs-capstone/backend/henry_env/
pocs-capstone/backend/db/__pycache__/
pocs-capstone/backend/db/migrations/
pocs-capstone/backend/backend/__pycache__/
Expand Down Expand Up @@ -121,3 +122,4 @@ pocs-capstone/frontend/src/components/Tutorial/Tutorial-screenshots/original scr
pocs-capstone/frontend/src/components/Tutorial/Tutorial-screenshots/original screenshots/calendar.png
pocs-capstone/frontend/src/components/Tutorial/Tutorial-screenshots/original screenshots/completed-tasks.png
pocs-capstone/frontend/src/components/Tutorial/Tutorial-screenshots/original screenshots/inventory.png
pocs-capstone/backend/venv/*
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ cd <your-path>/sb/frontend
```bash
npm install
npm run build
nmp start
npm start
```
8. In your browser, navigate in the search bar to <a href="http://localhost:3000">http://localhost:3000</a>.

Expand Down
Empty file.
10 changes: 10 additions & 0 deletions pocs-capstone/backend/backend/db/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from django.contrib import admin

# Register your models here.
"""
from .models import Question
from .models import Note

admin.site.register(Question)
admin.site.register(Note)
"""
6 changes: 6 additions & 0 deletions pocs-capstone/backend/backend/db/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from django.apps import AppConfig


class DbConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'db'
33 changes: 33 additions & 0 deletions pocs-capstone/backend/backend/db/authenticate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
from rest_framework_simplejwt.authentication import JWTAuthentication
from django.conf import settings

from rest_framework.authentication import CSRFCheck
from rest_framework import exceptions

def enforce_csrf(request):
"""
Enforce CSRF validation.
"""
check = CSRFCheck()
# populates request.META['CSRF_COOKIE'], which is used in process_view()
check.process_request(request)
reason = check.process_view(request, None, (), {})
if reason:
# CSRF failed, bail with explicit error message
raise exceptions.PermissionDenied('CSRF Failed: %s' % reason)

class CustomAuthentication(JWTAuthentication):

def authenticate(self, request):
header = self.get_header(request)

if header is None:
raw_token = request.COOKIES.get(settings.SIMPLE_JWT['AUTH_COOKIE']) or None
else:
raw_token = self.get_raw_token(header)
if raw_token is None:
return None

validated_token = self.get_validated_token(raw_token)
enforce_csrf(request)
return self.get_user(validated_token), validated_token
232 changes: 232 additions & 0 deletions pocs-capstone/backend/backend/db/canvasrequests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,232 @@

import requests
import bs4 as bs
import pprint
# import re
# from dateutil import parser
pp = pprint.PrettyPrinter(indent=2)

# Static settings
BASE_URL = 'https://templeu.instructure.com/api/v1'


'''Returns the response from a GET request to the Canvas API'''


def canvas_request(url, headers, params):
try:
response = requests.get(url=url, headers=headers, params=params)
status = response.status_code
except Exception as e:
return e, 500 # this is an internal service error due to failed request to external resource
return response.json(), status # convert to json


'''Return a list of all Canvas courses' IDs'''


def get_courses(canvas_token): # later we'll add userId as a parameter
auth_header = {'Authorization': 'Bearer ' + canvas_token}
courses_params = {
"per_page": 100,
"enrollment_state": "active",
"workflow_state": "available",
"enrollment_type": "student"
}

courses_data, status = canvas_request(
BASE_URL + '/courses', auth_header, courses_params)

if status == 200:
course_id_list = [] # a list of all the user's courses (their ids)

for course_entry in courses_data:
course = (course_entry['id'], course_entry['name'])
course_id_list.append(course)

return course_id_list, status
return None, status


'''Given a course ID, return a list of all assignments' IDs'''


def get_assignments(canvas_token, course_id):
auth_header = {'Authorization': 'Bearer ' + canvas_token}
assignment_params = {
"per_page": 5000,
"include": "submission"
}

assignments_data, status = canvas_request(
BASE_URL + '/courses/' + str(course_id) + '/assignments', auth_header, assignment_params)

assignment_id_list = [] # a list of all the user's courses (their ids)
for assignment_entry in assignments_data:
try:
assignment_id_list.append(assignment_entry['id'])
except Exception as e:
print(e)

return assignment_id_list, assignments_data


'''Given a course ID, return a json object of course information for that particular course'''


def get_course_info(canvas_token, course_id):
auth_header = {'Authorization': 'Bearer ' + canvas_token}
course_url = BASE_URL + '/courses/' + str(course_id)
return canvas_request(url=course_url, headers=auth_header, params={})


'''Given a course ID and assignment ID, return a dict of assignment information for that particular assignment'''


def get_assignment_info(canvas_token, course_id, assignment_id):
auth_header = {'Authorization': 'Bearer ' + canvas_token}

# TODO - This needs to move further back in the procedure
user_url = BASE_URL + '/users/self'
user_id = None

try:
b, bstatus = canvas_request(
url=user_url, headers=auth_header, params={})
if bstatus == 200:
user_id = b['id']
except Exception as e:
print(e)
return None

assignment_url = BASE_URL + '/courses/' + \
str(course_id) + '/assignments/' + str(assignment_id)
a, status = canvas_request(url=assignment_url, headers=auth_header, params={
"include[]": ['submission']})
submission_details = {}

if status == 200:
due = a['due_at']
submission_details = a['submission']
submitted = submission_details['submitted_at']
else:
due = None

if due != None:
due = due[0:10] # hack into a string UwU
if submitted != None:
submitted = submitted[0:10] # hack into a string UwU

try:
description = bs.BeautifulSoup(a['description'], 'lxml').get_text()
except Exception as e:
description = ""

return {'title': a['name'] or "No title.",
'due_date': due,

'task_type': 'S',
# 'task_level': 1, # TODO - this should be set here!
# 'recurring': 'false',
# 'recurring_time_delta': 0,
'completed_date': submitted,
'description': description,
'course_id': a['course_id'],
'assignment_id': a['id']
}


'''Given a course ID, return a list of all assignments' IDs'''


def get_assignments(canvas_token, course_info):
course_id = course_info[0]
auth_header = {'Authorization': 'Bearer ' + canvas_token}
assignment_params = {
"per_page": 5000,
"include": "submission"
}

assignments_data, status = canvas_request(
BASE_URL + '/courses/' + str(course_id) + '/assignments', auth_header, assignment_params)

assignment_id_list = [] # a list of all the user's courses (their ids)
for assignment_entry in assignments_data:
try:
assignment_id_list.append(assignment_entry['id'])
except Exception as e:
print(e)

return assignment_id_list, assignments_data


'''Given a course ID, return a json object of course information for that particular course'''


def get_course_info(canvas_token, course_id):
auth_header = {'Authorization': 'Bearer ' + canvas_token}
course_url = BASE_URL + '/courses/' + str(course_id)
return canvas_request(url=course_url, headers=auth_header, params={})


'''Given a course ID and assignment ID, return a dict of assignment information for that particular assignment'''


def parse_assignments(assignments, course_title):

tasks = []

for a in assignments:
submission_details = {}

due = a['due_at']
submission_details = a['submission']

submitted = submission_details['submitted_at']

if due != None:
due = due[0:10] # hack into a string UwU
if submitted != None:
submitted = submitted[0:10] # hack into a string UwU

try:
description = bs.BeautifulSoup(a['description'], 'lxml').get_text()
except Exception as e:
description = ""

tasks.append({'title': a['name'] or "No title.",
'due_date': due,

'task_type': 'S',
# 'task_level': 1, # TODO - this should be set here!
# 'recurring': 'false',
# 'recurring_time_delta': 0,
'course_title': course_title,
'completed_date': submitted,
'description': description,
'course_id': a['course_id'],
'assignment_id': a['id'],
})
return tasks


'''Given a list of assignment IDs, return a list where each entry is a dict of assignment information corresponding to those IDs'''


def get_all_assignments(canvas_token):
all_assignments = [] # list of all assignment IDs for all courses

course_info, status = get_courses(canvas_token) # all course IDs
if status != 200:
return None, status
for course in course_info:
# all assignment IDs for one specific course
assignment_ids, assignments = get_assignments(canvas_token, course)

# for assignment_id in assignment_ids:
# assignment_info = get_assignment_info(canvas_token, course_id, assignment_id)
# all_assignments.append(assignment_info) # add each assignment dict from this course to list
_assignments = parse_assignments(assignments, course[1])
all_assignments = all_assignments+_assignments

return all_assignments, status
Loading