Skip to content

Commit 95722fc

Browse files
committed
Merge branch 'issue-1118'
2 parents 7c3e3ea + c37f4cd commit 95722fc

File tree

7 files changed

+40
-45
lines changed

7 files changed

+40
-45
lines changed

bases/rsptx/assignment_server_api/assignment_builder/src/componentFuncs.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ export async function renderRunestoneComponent(
7474
previewRef.current.innerHTML = `<p>Preview not available for ${componentKind}</p>`;
7575
} else {
7676
try {
77-
// Grab the preamble if it exists.
77+
// Grab the preamble if it exists.
7878
// add it to opt so that it can be used by the component factory
7979
// This is used for mathjax processing of the preview.
8080
let preamble = document.querySelector("div.hidden-content.process-math");
@@ -85,6 +85,12 @@ export async function renderRunestoneComponent(
8585
let res = window.component_factory[componentKind](opt);
8686
console.log("res", res);
8787

88+
// For components with async initialization (like selectquestion),
89+
// call initialize() method if it exists
90+
if (!!moreOpts.isCalledFromBuilder && res && typeof res.initialize === "function") {
91+
await res.initialize();
92+
}
93+
8894
res.multiGrader = moreOpts.multiGrader;
8995
if (componentKind === "activecode") {
9096
if (moreOpts.multiGrader) {
@@ -95,7 +101,7 @@ export async function renderRunestoneComponent(
95101
}
96102
// add a button to the preview to allow the user to flag this compenent for review
97103
let flagButton = document.createElement("button");
98-
console.log("res",res);
104+
console.log("res", res);
99105
flagButton.classList.add("flag-for-review");
100106
flagButton.textContent = "Flag for Review";
101107
flagButton.addEventListener("click", async function () {

bases/rsptx/assignment_server_api/assignment_builder/src/components/routes/AssignmentBuilder/components/exercises/components/CreateExercise/components/SelectQuestionExercise/SelectQuestionExercise.tsx

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { FC, useMemo, useRef } from "react";
1+
import { FC, useMemo } from "react";
22

33
import { CreateExerciseFormType } from "@/types/exercises";
44
import { QuestionWithLabel } from "@/types/exercises";
@@ -35,6 +35,7 @@ const getDefaultFormData = (): Partial<CreateExerciseFormType> => ({
3535
htmlsrc: "",
3636
question_type: "selectquestion",
3737
questionList: [],
38+
questionLabels: {},
3839
abExperimentName: "",
3940
toggleOptions: [],
4041
dataLimitBasecourse: false
@@ -52,13 +53,12 @@ export const SelectQuestionExercise: FC<ExerciseComponentProps> = ({
5253
onFormReset,
5354
isEdit = false
5455
}) => {
55-
const questionLabelsRef = useRef<Map<string, string>>(new Map());
56-
5756
const generatePreviewWithLabels = (data: Partial<CreateExerciseFormType>): string => {
5857
const stringList = data.questionList || [];
58+
const labels = data.questionLabels || {};
5959
const questionListWithLabels = stringList.map((questionId) => ({
6060
questionId,
61-
label: questionLabelsRef.current.get(questionId)
61+
label: labels[questionId]
6262
}));
6363

6464
return generateSelectQuestionPreview({
@@ -116,24 +116,26 @@ export const SelectQuestionExercise: FC<ExerciseComponentProps> = ({
116116

117117
const safeQuestionList = useMemo(() => {
118118
const stringList = formData.questionList || [];
119+
const labels = formData.questionLabels || {};
119120

120121
return stringList.map((questionId) => ({
121122
questionId,
122-
label: questionLabelsRef.current.get(questionId)
123+
label: labels[questionId]
123124
}));
124-
}, [formData.questionList]);
125+
}, [formData.questionList, formData.questionLabels]);
125126

126127
const handleQuestionListChange = (questionList: QuestionWithLabel[]) => {
127-
questionLabelsRef.current.clear();
128+
const labelsRecord: Record<string, string> = {};
128129
questionList.forEach((q) => {
129130
if (q.label) {
130-
questionLabelsRef.current.set(q.questionId, q.label);
131+
labelsRecord[q.questionId] = q.label;
131132
}
132133
});
133134

134135
const stringList = convertToStringArray(questionList);
135136

136137
updateFormData("questionList", stringList);
138+
updateFormData("questionLabels", labelsRecord);
137139
};
138140

139141
const handleABExperimentChange = (experimentName: string) => {

bases/rsptx/assignment_server_api/assignment_builder/src/components/routes/AssignmentBuilder/components/exercises/components/CreateExercise/components/SelectQuestionExercise/components/QuestionListEditor.tsx

Lines changed: 13 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -30,38 +30,37 @@ export const QuestionListEditor: FC<QuestionListEditorProps> = ({
3030

3131
const { exercises, onGlobalFilterChange, toggleBaseCourse } = useSmartExerciseSearch({
3232
use_base_course: dataLimitBasecourse,
33-
limit: 20
33+
limit: 20,
34+
assignment_id: undefined
3435
});
3536

3637
const existingQuestionIds = useMemo(() => questionList.map((q) => q.questionId), [questionList]);
3738

38-
const getAvailableExercises = useCallback(() => {
39-
return exercises.filter((ex) => ex.name && !existingQuestionIds.includes(ex.name));
40-
}, [exercises, existingQuestionIds]);
41-
42-
const createSuggestions = (filteredExercises: any[]) => {
39+
const createSuggestions = useCallback((filteredExercises: any[]) => {
4340
return filteredExercises.map((ex) => ({
4441
id: ex.name,
4542
name: ex.name,
4643
type: ex.question_type,
4744
topic: ex.topic,
4845
author: ex.author
4946
}));
50-
};
47+
}, []);
5148

5249
const updateSuggestions = useCallback(() => {
53-
const availableExercises = getAvailableExercises();
54-
50+
const availableExercises = exercises.filter(
51+
(ex) => ex.name && !existingQuestionIds.includes(ex.name)
52+
);
5553
setSuggestions(createSuggestions(availableExercises));
56-
}, [getAvailableExercises]);
54+
}, [exercises, existingQuestionIds, createSuggestions]);
5755

5856
useEffect(() => {
5957
toggleBaseCourse(dataLimitBasecourse);
60-
}, [dataLimitBasecourse, toggleBaseCourse]);
58+
// eslint-disable-next-line react-hooks/exhaustive-deps
59+
}, [dataLimitBasecourse]);
6160

6261
useEffect(() => {
6362
updateSuggestions();
64-
}, [exercises, questionList, updateSuggestions]);
63+
}, [updateSuggestions]);
6564

6665
const handleAddQuestion = () => {
6766
const trimmed = newQuestion.trim();
@@ -92,14 +91,9 @@ export const QuestionListEditor: FC<QuestionListEditorProps> = ({
9291
};
9392

9493
const handleAutocompleteSearch = (event: { query: string }) => {
95-
const query = event.query.toLowerCase();
96-
97-
if (query.length === 0) {
98-
updateSuggestions();
99-
return;
100-
}
101-
94+
const query = event.query.toLowerCase().trim();
10295
onGlobalFilterChange(query);
96+
updateSuggestions();
10397
};
10498

10599
const handleAutocompleteSelect = (event: { value: any }) => {
@@ -186,13 +180,6 @@ export const QuestionListEditor: FC<QuestionListEditorProps> = ({
186180
forceSelection={false}
187181
itemTemplate={suggestionTemplate}
188182
/>
189-
<Button
190-
label="Add"
191-
icon="pi pi-plus"
192-
onClick={handleAddQuestion}
193-
disabled={!newQuestion.trim() || existingQuestionIds.includes(newQuestion.trim())}
194-
className={styles.addButton}
195-
/>
196183
</div>
197184

198185
<div className="field-checkbox flex align-items-center gap-1 mt-1">

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ export const ExercisePreview = ({
1515
if (ref.current) {
1616
console.log("ref here");
1717
ref.current.innerHTML = htmlsrc;
18-
renderRunestoneComponent(ref, {}).then(forceUpdate);
18+
renderRunestoneComponent(ref, { isCalledFromBuilder: true }).then(forceUpdate);
1919
}
2020
}, [htmlsrc]);
2121

bases/rsptx/assignment_server_api/assignment_builder/src/types/exercises.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ export const supportedExerciseTypesToEdit = [
1313
"parsonsprob",
1414
"matching",
1515
"fillintheblank",
16-
"clickablearea"
16+
"clickablearea",
17+
"selectquestion"
1718
];
1819

1920
export const supportedExerciseTypes = [
@@ -96,6 +97,7 @@ export type QuestionJSON = Partial<{
9697
scale_max: number;
9798
forceCheckboxes: boolean;
9899
questionList: string[];
100+
questionLabels: Record<string, string>;
99101
abExperimentName: string;
100102
toggleOptions: string[];
101103
dataLimitBasecourse: boolean;

bases/rsptx/assignment_server_api/assignment_builder/src/utils/preview/selectQuestionPreview.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,9 @@ export const generateSelectQuestionPreview = ({
3434
? questionList.map((item) => (typeof item === "string" ? { questionId: item } : item))
3535
: [];
3636

37-
let html = '<div class="runestone sqcontainer %(optclass)s"><div data-component="selectquestion"';
37+
let html = '<div class="runestone sqcontainer"><div data-component="selectquestion"';
3838

39-
html += ` id=${safeId}`;
39+
html += ` id="${safeId}"`;
4040

4141
const questionListStr = questions.map((q) => q.questionId).join(", ");
4242

@@ -50,11 +50,7 @@ export const generateSelectQuestionPreview = ({
5050
const toggleStr = toggleOptions.join(", ");
5151

5252
html += ` data-toggleoptions="${toggleStr}"`;
53-
}
54-
55-
const hasAnyLabels = questions.some((q) => q.label);
5653

57-
if (hasAnyLabels) {
5854
const questionLabels = questions.map((q) => q.label || q.questionId).join(", ");
5955

6056
html += ` data-togglelabels="togglelabels: ${questionLabels}"`;

bases/rsptx/assignment_server_api/assignment_builder/src/utils/questionJson.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ export const buildQuestionJson = (data: CreateExerciseFormType) => {
5454
}),
5555
...(data.question_type === "selectquestion" && {
5656
questionList: data.questionList,
57+
questionLabels: data.questionLabels,
5758
abExperimentName: data.abExperimentName,
5859
toggleOptions: data.toggleOptions,
5960
dataLimitBasecourse: data.dataLimitBasecourse
@@ -117,6 +118,7 @@ export const mergeQuestionJsonWithDefaults = (
117118
parsonspersonalize:
118119
questionJson?.parsonspersonalize ??
119120
(defaultQuestionJson.parsonspersonalize as "" | "solution-level" | "block-and-solution"),
120-
parsonsexample: questionJson?.parsonsexample ?? defaultQuestionJson.parsonsexample
121+
parsonsexample: questionJson?.parsonsexample ?? defaultQuestionJson.parsonsexample,
122+
questionLabels: questionJson?.questionLabels ?? {}
121123
};
122124
};

0 commit comments

Comments
 (0)