Skip to content

Commit

Permalink
examGroupManager: Add per-exam practice exam variation
Browse files Browse the repository at this point in the history
  • Loading branch information
dezhidki committed Feb 19, 2025
1 parent aafe415 commit d2e36d3
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 13 deletions.
27 changes: 21 additions & 6 deletions timApp/plugin/examGroupManager/examGroupManager.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,14 +107,19 @@ class Exam:
url: str | None = None


@dataclass
class ExamWithPractice(Exam):
practice: Exam | None = None


@dataclass
class ExamGroupManagerMarkup(GenericMarkupModel):
groupsPath: str | Missing = missing
extraInfoTitle: str | Missing = missing
showAllGroups: bool = False
show: ViewOptionsMarkup = field(default_factory=ViewOptionsMarkup)
groupNamePrefix: str | Missing = missing
exams: list[Exam] = field(default_factory=list)
exams: list[ExamWithPractice] = field(default_factory=list)
practiceExam: Exam | Missing = missing


Expand Down Expand Up @@ -760,16 +765,26 @@ def print_login_codes(
users = _get_exam_group_members_json(ug)

plugin, _ = _get_plugin_markup(GlobalParId(doc_id, par_id))
if practice and not plugin.practiceExam:
raise NotExist(gettext("Practice exam not set in the plugin markup."))

exams_by_doc_id = {e.docId: e for e in plugin.exams}

exam = (
exam: Exam | None = (
exams_by_doc_id.get(extra_data.examDocId, None)
if not practice and not isinstance(extra_data.examDocId, Missing)
else plugin.practiceExam
if not isinstance(extra_data.examDocId, Missing)
else None
)

if practice:
exam = exam.practice if isinstance(exam, ExamWithPractice) else None
if not exam and isinstance(plugin.practiceExam, Exam):
exam = plugin.practiceExam

if practice and not exam:
raise NotExist(gettext("Practice exam not set in the plugin markup."))

if not exam:
raise NotExist(gettext("Exam info not found in the plugin markup."))

exam_url: str | None = None
exam_title: str | None = None
if exam and not isinstance(exam, Missing):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,13 +122,22 @@ const ExamT = t.type({
url: t.union([t.string, t.null]),
});

const ExamWithPracticeT = t.intersection([
ExamT,
t.partial({
practice: t.union([ExamT, t.null]),
}),
]);

export interface Exam extends t.TypeOf<typeof ExamT> {}

export interface ExamWithPractice extends t.TypeOf<typeof ExamWithPracticeT> {}

const ExamManagerMarkup = t.intersection([
t.type({
groupsPath: withDefault(t.string, ""),
showAllGroups: withDefault(t.boolean, false),
exams: withDefault(t.array(ExamT), []),
exams: withDefault(t.array(ExamWithPracticeT), []),
}),
t.partial({
extraInfoTitle: t.string,
Expand Down Expand Up @@ -393,7 +402,7 @@ export class ToggleComponent {
i18n>
Print login codes (Main exam)
</button>
<button class="timButton" *ngIf="markup['practiceExam']"
<button class="timButton" *ngIf="examByDocId.get(group.examDocId ?? -1)?.practice ?? markup['practiceExam']"
(click)="printLoginCodes(group, true)" i18n>
Print login codes (Practice exam)
</button>
Expand Down Expand Up @@ -430,9 +439,9 @@ export class ToggleComponent {
<select id="current-exam-doc-{{group.id}}" name="current-exam-doc-{{group.id}}" class="form-control"
[ngModel]="group.currentExamDoc"
(ngModelChange)="confirmSelectExam(group, $event)">
<option *ngIf="markup['practiceExam']"
[ngValue]="markup['practiceExam'].docId">
{{ markup['practiceExam'].name }}
<option *ngIf="examByDocId.get(group.examDocId ?? -1) ?? markup['practiceExam']"
[ngValue]="examByDocId.get(group.examDocId ?? -1)?.practice?.docId ?? markup['practiceExam']?.docId ?? -1">
{{ examByDocId.get(group.examDocId ?? -1)?.practice?.name ?? markup['practiceExam']?.name ?? "" }}
</option>
<option *ngIf="group.examDocId && examByDocId.get(group.examDocId)"
[ngValue]="examByDocId.get(group.examDocId)?.docId">
Expand Down Expand Up @@ -741,7 +750,7 @@ export class ExamGroupManagerComponent
// Members visible on the currently active group tab (in the group members table)
members: Record<string, GroupMember[]> = {};
error?: string;
examByDocId = new Map<number, Exam>();
examByDocId = new Map<number, ExamWithPractice>();

allowRestrictedAccess: boolean = false;

Expand Down Expand Up @@ -770,6 +779,9 @@ export class ExamGroupManagerComponent

for (const exam of this.markup.exams) {
this.examByDocId.set(exam.docId, exam);
if (exam.practice) {
this.examByDocId.set(exam.practice.docId, exam.practice);
}
}
if (this.markup.practiceExam) {
this.examByDocId.set(
Expand Down Expand Up @@ -1454,7 +1466,7 @@ export class ExamGroupManagerComponent
return undefined;
}

getExamUrl(exam?: Exam) {
getExamUrl(exam?: ExamWithPractice) {
if (!exam) {
return "";
}
Expand Down

0 comments on commit d2e36d3

Please sign in to comment.