- {row.name || row.title}
+
+ {formatNumberedLabel(
+ row.sub_chapter_name || row.title || row.name || row.subchapter,
+ [row.chapter_num, row.sub_chapter_num]
+ )}
{row.subchapter}
diff --git a/bases/rsptx/assignment_server_api/assignment_builder/src/components/routes/AssignmentBuilder/components/reading/components/ChooseReadingsButton.spec.tsx b/bases/rsptx/assignment_server_api/assignment_builder/src/components/routes/AssignmentBuilder/components/reading/components/ChooseReadingsButton.spec.tsx
index c90c66768..13aa9f6dd 100644
--- a/bases/rsptx/assignment_server_api/assignment_builder/src/components/routes/AssignmentBuilder/components/reading/components/ChooseReadingsButton.spec.tsx
+++ b/bases/rsptx/assignment_server_api/assignment_builder/src/components/routes/AssignmentBuilder/components/reading/components/ChooseReadingsButton.spec.tsx
@@ -12,10 +12,10 @@ const { mockUpdate, mockReadingsSelector, updatingHolder, READINGS_TREE } = vi.h
READINGS_TREE: [
{
key: "chapter-1",
- data: { title: "Chapter 1" },
+ data: { title: "Chapter 1", chapter_num: 1 },
children: [
- { key: "sec-1", data: { title: "Section 1", id: 11 } },
- { key: "sec-2", data: { title: "Section 2", id: 12 } }
+ { key: "sec-1", data: { title: "Section 1", id: 11, chapter_num: 1, sub_chapter_num: 1 } },
+ { key: "sec-2", data: { title: "Section 2", id: 12, chapter_num: 1, sub_chapter_num: 2 } }
]
}
] as TreeNode[]
@@ -46,18 +46,18 @@ describe("ChooseReadingsButton", () => {
it("reveals the readings tree when the button is clicked", async () => {
renderWithMantine();
- expect(screen.queryByText("Chapter 1")).not.toBeInTheDocument();
+ expect(screen.queryByText("1 Chapter 1")).not.toBeInTheDocument();
await userEvent.click(screen.getByRole("button", { name: "Choose readings" }));
- expect(screen.getByText("Chapter 1")).toBeInTheDocument();
+ expect(screen.getByText("1 Chapter 1")).toBeInTheDocument();
});
it("adds the selected leaf readings on select", async () => {
renderWithMantine();
await userEvent.click(screen.getByRole("button", { name: "Choose readings" }));
- await userEvent.click(screen.getByRole("button", { name: "Expand Chapter 1" }));
+ await userEvent.click(screen.getByRole("button", { name: "Expand 1 Chapter 1" }));
- await userEvent.click(screen.getByRole("checkbox", { name: "Select Section 1" }));
+ await userEvent.click(screen.getByRole("checkbox", { name: "Select 1.1 Section 1" }));
expect(mockUpdate).toHaveBeenCalledWith({ idsToAdd: [11], isReading: true });
});
@@ -70,9 +70,9 @@ describe("ChooseReadingsButton", () => {
renderWithMantine();
await userEvent.click(screen.getByRole("button", { name: "Choose readings" }));
- await userEvent.click(screen.getByRole("button", { name: "Expand Chapter 1" }));
+ await userEvent.click(screen.getByRole("button", { name: "Expand 1 Chapter 1" }));
- await userEvent.click(screen.getByRole("checkbox", { name: "Select Section 1" }));
+ await userEvent.click(screen.getByRole("checkbox", { name: "Select 1.1 Section 1" }));
expect(mockUpdate).toHaveBeenCalledWith({ idsToRemove: [99], isReading: true });
});
@@ -100,9 +100,9 @@ describe("ChooseReadingsButton", () => {
renderWithMantine();
await userEvent.click(screen.getByRole("button", { name: "Choose readings" }));
- await userEvent.click(screen.getByRole("button", { name: "Expand Chapter 1" }));
+ await userEvent.click(screen.getByRole("button", { name: "Expand 1 Chapter 1" }));
- await userEvent.click(screen.getByRole("checkbox", { name: "Select Section 1" }));
+ await userEvent.click(screen.getByRole("checkbox", { name: "Select 1.1 Section 1" }));
expect(mockUpdate).not.toHaveBeenCalled();
});
diff --git a/bases/rsptx/assignment_server_api/assignment_builder/src/components/routes/AssignmentBuilder/components/reading/components/ChooseReadingsButton.tsx b/bases/rsptx/assignment_server_api/assignment_builder/src/components/routes/AssignmentBuilder/components/reading/components/ChooseReadingsButton.tsx
index d739ca10e..5d894a9a1 100644
--- a/bases/rsptx/assignment_server_api/assignment_builder/src/components/routes/AssignmentBuilder/components/reading/components/ChooseReadingsButton.tsx
+++ b/bases/rsptx/assignment_server_api/assignment_builder/src/components/routes/AssignmentBuilder/components/reading/components/ChooseReadingsButton.tsx
@@ -13,10 +13,29 @@ import { getLeafNodes } from "@/utils/exercise";
import styles from "./ChooseReadingsButton.module.css";
+type NumberedNodeData = Partial & {
+ chapter_num?: number;
+ sub_chapter_num?: number;
+};
+
+const formatNumberedNodeLabel = (node: TreeNode): string => {
+ const data = node.data as NumberedNodeData | undefined;
+ const title = data?.title ?? String(node.key);
+ const numbers =
+ data?.sub_chapter_num !== null && data?.sub_chapter_num !== undefined
+ ? [data.chapter_num, data.sub_chapter_num]
+ : [data?.chapter_num ?? data?.num];
+ const prefix = numbers
+ .filter((value): value is number => value !== null && value !== undefined)
+ .join(".");
+
+ return prefix ? [prefix, title].filter(Boolean).join(" ") : title;
+};
+
const READINGS_COLUMNS: TreeTableColumn[] = [
{
header: "Select readings",
- render: (node) => {(node.data as Exercise)?.title}
+ render: (node) => {formatNumberedNodeLabel(node)}
}
];
@@ -83,7 +102,7 @@ export const ChooseReadingsButton = () => {
onSelect={onSelect}
onUnselect={onUnselect}
ariaLabel="Choose readings"
- getNodeLabel={(node) => (node.data as Exercise)?.title ?? String(node.key)}
+ getNodeLabel={formatNumberedNodeLabel}
/>
diff --git a/bases/rsptx/assignment_server_api/assignment_builder/src/types/exercises.ts b/bases/rsptx/assignment_server_api/assignment_builder/src/types/exercises.ts
index 0b8bcbbf8..911699cb9 100644
--- a/bases/rsptx/assignment_server_api/assignment_builder/src/types/exercises.ts
+++ b/bases/rsptx/assignment_server_api/assignment_builder/src/types/exercises.ts
@@ -68,6 +68,10 @@ export type Exercise = {
owner: string;
tags: string;
num: number;
+ chapter_num?: number;
+ sub_chapter_num?: number;
+ chapter_name?: string;
+ sub_chapter_name?: string;
numQuestions: number;
required: boolean;
title: string;
diff --git a/bases/rsptx/assignment_server_api/routers/instructor.py b/bases/rsptx/assignment_server_api/routers/instructor.py
index af0d2010f..5d68448d5 100644
--- a/bases/rsptx/assignment_server_api/routers/instructor.py
+++ b/bases/rsptx/assignment_server_api/routers/instructor.py
@@ -966,6 +966,10 @@ async def get_assignment_questions(
# augment the assignment question with additional question data
aq["name"] = q["name"]
aq["subchapter"] = q["subchapter"]
+ aq["chapter_num"] = row.Chapter.chapter_num
+ aq["sub_chapter_num"] = row.SubChapter.sub_chapter_num
+ aq["chapter_name"] = row.Chapter.chapter_name
+ aq["sub_chapter_name"] = row.SubChapter.sub_chapter_name
aq["chapter"] = q["chapter"]
aq["base_course"] = q["base_course"]
aq["htmlsrc"] = q["htmlsrc"]
diff --git a/components/rsptx/build_tools/core.py b/components/rsptx/build_tools/core.py
index 077b3bb9b..2cfcd8e65 100644
--- a/components/rsptx/build_tools/core.py
+++ b/components/rsptx/build_tools/core.py
@@ -734,7 +734,7 @@ def _process_single_chapter(sess, db_context, chapter, chap_counter, course_name
db_context["chapters"]
.insert()
.values(
- chapter_name=f"{cnum} {chapter.find('./title').text}",
+ chapter_name=f"{chapter.find('./title').text}",
course_id=course_name,
chapter_label=chapter.find("./id").text,
chapter_num=cnum,
@@ -808,7 +808,7 @@ def _process_single_subchapter(
titletext = " ".join(
[ET.tostring(y).decode("utf8") for y in subchapter.findall("./title/*")]
)
- titletext = f"{scnum} {titletext.strip()}"
+ titletext = f"{titletext.strip()}"
# Insert subchapter
ins = (
diff --git a/components/rsptx/db/crud/question.py b/components/rsptx/db/crud/question.py
index b414c04f0..3bc8df729 100644
--- a/components/rsptx/db/crud/question.py
+++ b/components/rsptx/db/crud/question.py
@@ -823,6 +823,10 @@ def find_page_id(chapter, subchapter):
"num": chapters[chapter]["sub_chapters"][subchapter][
"sub_chapter_num"
],
+ "chapter_num": chapters[chapter]["chapter_num"],
+ "sub_chapter_num": chapters[chapter]["sub_chapters"][
+ subchapter
+ ]["sub_chapter_num"],
"chapter": chapter,
"subchapter": subchapter,
"id": find_page_id(chapter, subchapter),
@@ -835,7 +839,16 @@ def find_page_id(chapter, subchapter):
),
},
"children": [
- {"key": q.name, "data": q.dict()}
+ {
+ "key": q.name,
+ "data": {
+ **q.dict(),
+ "chapter_num": chapters[chapter]["chapter_num"],
+ "sub_chapter_num": chapters[chapter][
+ "sub_chapters"
+ ][subchapter]["sub_chapter_num"],
+ },
+ }
for q in questions[chapter][subchapter]
],
}
@@ -846,6 +859,7 @@ def find_page_id(chapter, subchapter):
"data": {
"title": chapters[chapter]["chapter_name"],
"num": chapters[chapter]["chapter_num"],
+ "chapter_num": chapters[chapter]["chapter_num"],
},
"children": subs,
}