Skip to content

Commit eb285b9

Browse files
committed
New: Sort assignments
Upcoming assignments first nearest deadline at the top. Past due assignments after, colored red to make it easy to see the difference.
1 parent 80cd9f1 commit eb285b9

4 files changed

Lines changed: 59 additions & 9 deletions

File tree

bases/rsptx/assignment_server_api/routers/student.py

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,10 @@
6969
# ----------------
7070
@router.get("/chooseAssignment")
7171
async def get_assignments(
72-
request: Request, user=Depends(auth_manager), response_class=HTMLResponse
72+
request: Request,
73+
user=Depends(auth_manager),
74+
response_class=HTMLResponse,
75+
RS_info: Optional[str] = Cookie(None),
7376
):
7477
"""Create the chooseAssignment page for the user.
7578
@@ -100,7 +103,22 @@ async def get_assignments(
100103
if not user_is_instructor:
101104
assignments = [a for a in assignments if a.visible or a.id in assignment_ids]
102105

103-
assignments.sort(key=lambda x: x.duedate, reverse=True)
106+
parsed_js = json.loads(RS_info) if RS_info else {}
107+
timezoneoffset = parsed_js.get("tz_offset", None)
108+
109+
def sort_key(assignment):
110+
deadline = assignment.duedate
111+
if timezoneoffset:
112+
deadline = deadline + datetime.timedelta(hours=float(timezoneoffset))
113+
return (deadline < canonical_utcnow(), abs((deadline - canonical_utcnow()).total_seconds()))
114+
else:
115+
return (assignment.duedate < canonical_utcnow(), abs((assignment.duedate - canonical_utcnow()).total_seconds()))
116+
117+
# Sort assignments: upcoming assignments first (closest to current date), past due assignments last
118+
now = canonical_utcnow()
119+
assignments.sort(
120+
key=sort_key
121+
)
104122
stats_list = await fetch_all_assignment_stats(course.course_name, user.id)
105123
stats = {}
106124
for s in stats_list:
@@ -117,6 +135,7 @@ async def get_assignments(
117135
"is_instructor": user_is_instructor,
118136
"student_page": True,
119137
"lti1p1": is_lti1p1_course,
138+
"now": now,
120139
},
121140
)
122141

bases/rsptx/book_server_api/routers/course.py

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,13 @@
88
#
99
# Standard library
1010
# ----------------
11-
11+
import json
12+
import datetime
1213

1314
# Third-party imports
1415
# -------------------
15-
from fastapi import APIRouter, Request, Depends
16+
from typing import Optional
17+
from fastapi import APIRouter, Cookie, Request, Depends
1618
from fastapi.templating import Jinja2Templates
1719

1820
# Local application imports
@@ -33,7 +35,7 @@
3335
fetch_lti_version,
3436
)
3537
from rsptx.logging import rslogger
36-
from rsptx.response_helpers.core import make_json_response
38+
from rsptx.response_helpers.core import canonical_utcnow, make_json_response
3739
from rsptx.auth.session import is_instructor
3840
from rsptx.grading_helpers.core import adjust_deadlines
3941

@@ -52,7 +54,9 @@
5254

5355

5456
@router.api_route("/index", methods=["GET", "POST"])
55-
async def index(request: Request, user=Depends(auth_manager)):
57+
async def index(
58+
request: Request, user=Depends(auth_manager), RS_info: Optional[str] = Cookie(None)
59+
):
5660
"""Fetch current course information
5761
Fetch current assignment information
5862
@@ -93,7 +97,29 @@ async def index(request: Request, user=Depends(auth_manager)):
9397
if not user_is_instructor:
9498
assignments = [a for a in assignments if a.visible or a.id in assignment_ids]
9599
assignments = adjust_deadlines(assignments, accommodations)
96-
assignments.sort(key=lambda x: x.duedate, reverse=True)
100+
101+
parsed_js = json.loads(RS_info) if RS_info else {}
102+
timezoneoffset = parsed_js.get("tz_offset", None)
103+
104+
def sort_key(assignment):
105+
deadline = assignment.duedate
106+
if timezoneoffset:
107+
deadline = deadline + datetime.timedelta(hours=float(timezoneoffset))
108+
return (
109+
deadline < canonical_utcnow(),
110+
abs((deadline - canonical_utcnow()).total_seconds()),
111+
)
112+
else:
113+
return (
114+
assignment.duedate < canonical_utcnow(),
115+
abs((assignment.duedate - canonical_utcnow()).total_seconds()),
116+
)
117+
118+
now = canonical_utcnow()
119+
assignments.sort(
120+
key=sort_key
121+
)
122+
97123
stats_list = await fetch_all_assignment_stats(course_name, user.id)
98124
stats = {}
99125
for s in stats_list:
@@ -117,6 +143,7 @@ async def index(request: Request, user=Depends(auth_manager)):
117143
"is_instructor": user_is_instructor,
118144
"has_discussion_group": any([book.social_url for book in books]),
119145
"lti1p1": is_lti1p1_course,
146+
"now": now,
120147
},
121148
)
122149

components/rsptx/templates/assignment/student/assignment_block.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,8 @@ <h2>Assignments</h2>
5555
{% endif %}
5656
</td>
5757

58-
<td>{{assignment.duedate}}</td>
58+
59+
<td {% if assignment.duedate < now %}class="overdue"{% endif %}>{{assignment.duedate.strftime("%b %d, %Y %I:%M %p")}}</td>
5960
<td>
6061
{% if assignment.id in stats and stats[assignment.id].score != None %}
6162
{{ stats[assignment.id].score | round(2) }} / {{ assignment.points }}

components/rsptx/templates/staticAssets/index.css

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,5 +113,8 @@ input {
113113

114114
.overdue {
115115
color: #ff0000;
116-
font-size: larger;
116+
}
117+
118+
.duesoon {
119+
color: #11b70e;
117120
}

0 commit comments

Comments
 (0)