CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
sagemathinc

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: sagemathinc/cocalc
Path: blob/master/src/packages/frontend/course/assignments/assignment-student-list.tsx
Views: 687
1
/*
2
* This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.
3
* License: MS-RSL – see LICENSE.md for details
4
*/
5
6
import { useIntl } from "react-intl";
7
8
// CoCalc libraries
9
import { AppRedux, useMemo } from "@cocalc/frontend/app-framework";
10
import ScrollableList from "@cocalc/frontend/components/scrollable-list";
11
import { search_match, search_split, trunc_middle } from "@cocalc/util/misc";
12
import { StudentAssignmentInfo, StudentAssignmentInfoHeader } from "../common";
13
import {
14
AssignmentRecord,
15
CourseStore,
16
IsGradingMap,
17
NBgraderRunInfo,
18
SortDescription,
19
} from "../store";
20
import * as util from "../util";
21
22
interface StudentListForAssignmentProps {
23
frame_id?: string;
24
name: string;
25
redux: AppRedux;
26
assignment: AssignmentRecord;
27
students: any;
28
user_map: any;
29
background?: string;
30
active_student_sort: SortDescription;
31
active_feedback_edits: IsGradingMap;
32
nbgrader_run_info?: NBgraderRunInfo;
33
search: string;
34
}
35
36
export function StudentListForAssignment({
37
frame_id,
38
name,
39
redux,
40
assignment,
41
students,
42
user_map,
43
background,
44
active_student_sort,
45
active_feedback_edits,
46
nbgrader_run_info,
47
search,
48
}: StudentListForAssignmentProps) {
49
const intl = useIntl();
50
51
const student_list: string[] = useMemo(() => {
52
const v0 = util.parse_students(students, user_map, redux, intl);
53
const store = get_store();
54
55
// Remove deleted students or students not matching the search
56
const terms = search_split(search);
57
const v1: any[] = [];
58
for (const x of v0) {
59
if (x.deleted) continue;
60
if (
61
terms.length > 0 &&
62
!search_match(store.get_student_name(x.student_id).toLowerCase(), terms)
63
) {
64
continue;
65
}
66
v1.push(x);
67
}
68
69
v1.sort(util.pick_student_sorter(active_student_sort.toJS()));
70
71
if (active_student_sort.get("is_descending")) {
72
v1.reverse();
73
}
74
75
return v1.map((x) => x.student_id);
76
}, [
77
assignment,
78
students,
79
user_map,
80
background,
81
active_student_sort,
82
active_feedback_edits,
83
nbgrader_run_info,
84
search,
85
]);
86
87
function get_store(): CourseStore {
88
return redux.getStore(name) as any;
89
}
90
91
function is_peer_graded(): boolean {
92
const peer_info = assignment.get("peer_grade");
93
return peer_info ? peer_info.get("enabled") : false;
94
}
95
96
function render_student_info(student_id: string) {
97
const store = get_store();
98
const student = store.get_student(student_id);
99
if (student == null) return; // no such student
100
const key = util.assignment_identifier(
101
assignment.get("assignment_id"),
102
student_id,
103
);
104
const edited_feedback = active_feedback_edits.get(key);
105
return (
106
<StudentAssignmentInfo
107
key={student_id}
108
title={trunc_middle(store.get_student_name(student_id), 40)}
109
name={name}
110
student={student}
111
assignment={assignment}
112
grade={store.get_grade(assignment.get("assignment_id"), student_id)}
113
nbgrader_scores={store.get_nbgrader_scores(
114
assignment.get("assignment_id"),
115
student_id,
116
)}
117
nbgrader_score_ids={store.get_nbgrader_score_ids(
118
assignment.get("assignment_id"),
119
)}
120
comments={store.get_comments(
121
assignment.get("assignment_id"),
122
student_id,
123
)}
124
info={store.student_assignment_info(
125
student_id,
126
assignment.get("assignment_id"),
127
)}
128
is_editing={!!edited_feedback}
129
nbgrader_run_info={nbgrader_run_info}
130
/>
131
);
132
}
133
134
function render_students() {
135
return (
136
<ScrollableList
137
virtualize
138
rowCount={student_list.length}
139
rowRenderer={({ key }) => render_student_info(key)}
140
rowKey={(index) => student_list[index]}
141
cacheId={`course-assignment-${assignment.get(
142
"assignment_id",
143
)}-${name}-${frame_id}`}
144
/>
145
);
146
}
147
148
return (
149
<div style={{ height: "70vh", display: "flex", flexDirection: "column" }}>
150
<StudentAssignmentInfoHeader
151
key="header"
152
title="Student"
153
peer_grade={is_peer_graded()}
154
/>
155
{render_students()}
156
</div>
157
);
158
}
159
160