Skip to content

Commit 3521ab4

Browse files
committed
merge main into async-toggle and resolve conflicts
2 parents 1a9127d + 4e89301 commit 3521ab4

File tree

41 files changed

+2056
-192
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+2056
-192
lines changed

.pre-commit-config.yaml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
repos:
2+
- repo: https://github.com/psf/black
3+
rev: 24.4.2
4+
hooks:
5+
- id: black
6+
types: [python]
7+
files: ^(bases|components)/
8+
9+
- repo: https://github.com/astral-sh/ruff-pre-commit
10+
rev: v0.4.4
11+
hooks:
12+
- id: ruff
13+
types: [python]
14+
files: ^(bases|components)/

CHANGELOG.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,33 @@
11
# ChangeLog
22

3+
## Updates since last changelog entry (2026-02-21 → 2026-02-27)
4+
5+
Coverage: commits from **2026-02-21** through **2026-02-27** (i.e., changes after the prior cutoff on 2026-02-20).
6+
7+
### Highlights
8+
9+
- **Learning clues (prototype) + student context improvements:** initial prototype of “learning clues” integration landed, plus follow-on work to add context and automate lookup of book ids (primarily in `assignment_server_api/routers/student.py` and `bookfuncs.js`).
10+
- **Peer/LLM chat robustness:** improvements to async peer messaging (prompt + behavior), fixes for message ordering, and a key fix so the correct API token field is used and LLM peer lookup can retrieve keys at call time.
11+
- **LTI1p3 UX:** better messaging when an LMS rejects access to an **expired course**.
12+
- **UI theming iteration:** dark-mode dropdown styling changes were introduced and then reverted (net effect: continued iteration/experimentation in this area).
13+
- **Code quality + dependencies:** a broad pass fixing **Black/Ruff** issues and updating lock files / dependencies.
14+
15+
### Commit notes (for reference)
16+
17+
- 1a181c81 Initial prototype of learning clues integration
18+
- 3f42fae0 log todos
19+
- 5964439a Add context and automate lookup of book ids
20+
- c523c054 Fix API token field selection + make LLM peer lookup retrieve keys at call time
21+
- 8e375a9c Fix message ordering in async peer chat display
22+
- c34931a8 update prompt and async peer messaging
23+
- bde25ecd LTI1p3: better message when LMS rejects accessing an expired course
24+
- eca2ee17 fix dark mode for dropdown menu…
25+
- cacd4e49 Revert "fix dark mode for dropdown menu…"
26+
- 968f1cd9 Fix all black errors
27+
- 0b40954b Fix all black and ruff issues
28+
29+
---
30+
331
## Updates since last changelog entry (2026-02-12 → 2026-02-20)
432

533
Coverage: commits from **2026-02-12** through **2026-02-20** (i.e., changes after the prior cutoff on 2026-02-11).

bases/rsptx/admin_server_api/routers/instructor.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1081,6 +1081,7 @@ async def _copy_one_assignment(
10811081
course=target_course.id,
10821082
name=old_assignment.name,
10831083
duedate=due_date,
1084+
updated_date=datetime.datetime.now(),
10841085
description=old_assignment.description,
10851086
points=old_assignment.points,
10861087
threshold_pct=old_assignment.threshold_pct,

bases/rsptx/admin_server_api/routers/lti1p3.py

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@
7777
fetch_instructor_courses,
7878
validate_user_credentials,
7979
)
80+
from rsptx.db.crud.assignment import is_assignment_visible_to_students
8081

8182
from rsptx.configuration import settings
8283
from rsptx.logging import rslogger
@@ -445,7 +446,10 @@ async def launch(request: Request):
445446
status_code=400, detail=f"Assignment {lineitem_assign_id} not found"
446447
)
447448

448-
if not rs_assign.visible and not message_launch.check_teacher_access():
449+
if (
450+
not is_assignment_visible_to_students(rs_assign)
451+
and not message_launch.check_teacher_access()
452+
):
449453
raise HTTPException(
450454
status_code=400,
451455
detail=f"Assignment {rs_assign.name} is not open for students",
@@ -874,10 +878,19 @@ async def dynamic_link_entry(request: Request):
874878
assignments.sort(key=lambda a: a.name)
875879
assignments.sort(key=lambda a: a.duedate)
876880

877-
# all lineitems in the LMS
878-
ags = message_launch.get_ags()
879-
l_items = await ags.get_lineitems()
881+
try:
882+
# all lineitems in the LMS - may be rejected if course is closed in LMS
883+
ags = message_launch.get_ags()
884+
l_items = await ags.get_lineitems()
885+
except LtiServiceException as e:
886+
rslogger.error(f"LTI1p3 - Error accessing course line items: {e}")
887+
raise HTTPException(
888+
status_code=422,
889+
detail="This course appears to be closed in your Learning Management System.",
890+
)
891+
880892
l_items.sort(key=lambda li: li.get("label"))
893+
881894
# build lookup dicts for line items
882895
l_items_resourceId_dict = {li.get("resourceId"): li for li in l_items}
883896
l_items_label_dict = {li.get("label"): li for li in l_items}

bases/rsptx/assignment_server_api/assignment_builder/package-lock.json

Lines changed: 94 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

bases/rsptx/assignment_server_api/assignment_builder/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
"prismjs": "^1.30.0",
5555
"quill": "^2.0.3",
5656
"react": "^18.2.0",
57+
"react-datepicker": "^7.6.0",
5758
"react-dom": "^18.2.0",
5859
"react-hook-form": "^7.53.2",
5960
"react-hot-toast": "^2.4.1",

bases/rsptx/assignment_server_api/assignment_builder/src/components/routes/AssignmentBuilder/AssignmentBuilder.module.css

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,6 @@
350350
.formField textarea,
351351
.formField :global(.p-inputtext),
352352
.formField :global(.p-inputtextarea),
353-
.formField :global(.p-calendar),
354353
.formField :global(.p-inputnumber),
355354
.formField :global(.p-selectbutton) {
356355
width: 100%;

bases/rsptx/assignment_server_api/assignment_builder/src/components/routes/AssignmentBuilder/AssignmentBuilder.tsx

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ export const AssignmentBuilder = () => {
9696
// Event handlers
9797
const handleCreateNew = () => {
9898
navigateToCreate("basic");
99-
reset(defaultAssignment);
99+
reset(defaultAssignment as unknown as Assignment);
100100
};
101101

102102
const handleEdit = (assignment: Assignment) => {
@@ -108,18 +108,6 @@ export const AssignmentBuilder = () => {
108108
await duplicateAssignment(assignment.id);
109109
};
110110

111-
const handleVisibilityChange = async (assignment: Assignment, visible: boolean) => {
112-
try {
113-
await updateAssignment({
114-
...assignment,
115-
visible
116-
});
117-
toast.success(`Assignment ${visible ? "visible" : "hidden"} for students`);
118-
} catch (error) {
119-
toast.error("Failed to update assignment visibility");
120-
}
121-
};
122-
123111
const handleReleasedChange = async (assignment: Assignment, released: boolean) => {
124112
try {
125113
await updateAssignment({
@@ -156,6 +144,21 @@ export const AssignmentBuilder = () => {
156144
}
157145
};
158146

147+
const handleVisibilityChange = async (
148+
assignment: Assignment,
149+
data: { visible: boolean; visible_on: string | null; hidden_on: string | null }
150+
) => {
151+
try {
152+
await updateAssignment({
153+
...assignment,
154+
...data
155+
});
156+
toast.success("Visibility updated");
157+
} catch (error) {
158+
toast.error("Failed to update visibility");
159+
}
160+
};
161+
159162
const handleWizardComplete = async () => {
160163
const formValues = getValues();
161164
const payload: CreateAssignmentPayload = {
@@ -168,7 +171,9 @@ export const AssignmentBuilder = () => {
168171
nofeedback: formValues.nofeedback,
169172
nopause: formValues.nopause,
170173
peer_async_visible: formValues.peer_async_visible,
171-
visible: false,
174+
visible: formValues.visible,
175+
visible_on: formValues.visible_on || null,
176+
hidden_on: formValues.hidden_on || null,
172177
released: true,
173178
enforce_due: formValues.enforce_due || false
174179
};
@@ -204,10 +209,10 @@ export const AssignmentBuilder = () => {
204209
onCreateNew={handleCreateNew}
205210
onEdit={handleEdit}
206211
onDuplicate={handleDuplicate}
207-
onVisibilityChange={handleVisibilityChange}
208212
onReleasedChange={handleReleasedChange}
209213
onEnforceDueChange={handleEnforceDueChange}
210214
onPeerAsyncChange={handlePeerAsyncChange}
215+
onVisibilityChange={handleVisibilityChange}
211216
onRemove={onRemove}
212217
/>
213218
)}
@@ -218,13 +223,21 @@ export const AssignmentBuilder = () => {
218223
nameError={nameError}
219224
canProceed={canProceed}
220225
onBack={() => {
221-
if (wizardStep === "type") {
226+
if (wizardStep === "visibility") {
227+
updateWizardStep("type");
228+
} else if (wizardStep === "type") {
222229
updateWizardStep("basic");
223230
} else {
224231
navigateToList();
225232
}
226233
}}
227-
onNext={() => updateWizardStep("type")}
234+
onNext={() => {
235+
if (wizardStep === "basic") {
236+
updateWizardStep("type");
237+
} else if (wizardStep === "type") {
238+
updateWizardStep("visibility");
239+
}
240+
}}
228241
onComplete={handleWizardComplete}
229242
onNameChange={handleNameChange}
230243
onTypeSelect={(type) => handleTypeSelect(type, setValue)}

0 commit comments

Comments
 (0)