Skip to content

Commit 3ac3b67

Browse files
committed
course: modern style code
- change all component definitions to use the format of the official react tutorials - get rid of all memoization: it leads to subtle bugs and virtualization (which we have) is a better approach to efficiency - no excessive return type typing -- that's a newbie typescript mistake I use to make, especially with "Rendered"
1 parent 59ae4e6 commit 3ac3b67

35 files changed

+4537
-4868
lines changed

src/packages/frontend/course/assignments/assignment-student-list.tsx

Lines changed: 111 additions & 140 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,9 @@
44
*/
55

66
// CoCalc libraries
7-
import {
8-
AppRedux,
9-
React,
10-
Rendered,
11-
useMemo,
12-
} from "@cocalc/frontend/app-framework";
7+
import { AppRedux, useMemo } from "@cocalc/frontend/app-framework";
138
import ScrollableList from "@cocalc/frontend/components/scrollable-list";
14-
import {
15-
is_different,
16-
search_match,
17-
search_split,
18-
trunc_middle,
19-
} from "@cocalc/util/misc";
9+
import { search_match, search_split, trunc_middle } from "@cocalc/util/misc";
2010
import { StudentAssignmentInfo, StudentAssignmentInfoHeader } from "../common";
2111
import {
2212
AssignmentRecord,
@@ -41,142 +31,123 @@ interface StudentListForAssignmentProps {
4131
search: string;
4232
}
4333

44-
function isSame(prev, next): boolean {
45-
return !is_different(prev, next, [
46-
"assignment",
47-
"students",
48-
"user_map",
49-
"background",
50-
"active_student_sort",
51-
"active_feedback_edits",
52-
"nbgrader_run_info",
53-
"search",
54-
]);
55-
}
56-
57-
export const StudentListForAssignment: React.FC<StudentListForAssignmentProps> =
58-
React.memo((props: StudentListForAssignmentProps) => {
59-
const {
60-
frame_id,
61-
name,
62-
redux,
63-
assignment,
64-
students,
65-
user_map,
66-
background,
67-
active_student_sort,
68-
active_feedback_edits,
69-
nbgrader_run_info,
70-
search,
71-
} = props;
34+
export function StudentListForAssignment({
35+
frame_id,
36+
name,
37+
redux,
38+
assignment,
39+
students,
40+
user_map,
41+
background,
42+
active_student_sort,
43+
active_feedback_edits,
44+
nbgrader_run_info,
45+
search,
46+
}: StudentListForAssignmentProps) {
47+
const student_list: string[] = useMemo(() => {
48+
const v0 = util.parse_students(students, user_map, redux);
49+
const store = get_store();
7250

73-
const student_list: string[] = useMemo(() => {
74-
const v0 = util.parse_students(students, user_map, redux);
75-
const store = get_store();
76-
77-
// Remove deleted students or students not matching the search
78-
const terms = search_split(search);
79-
const v1: any[] = [];
80-
for (const x of v0) {
81-
if (x.deleted) continue;
82-
if (
83-
terms.length > 0 &&
84-
!search_match(
85-
store.get_student_name(x.student_id).toLowerCase(),
86-
terms,
87-
)
88-
) {
89-
continue;
90-
}
91-
v1.push(x);
92-
}
93-
94-
v1.sort(util.pick_student_sorter(active_student_sort.toJS()));
95-
96-
if (active_student_sort.get("is_descending")) {
97-
v1.reverse();
51+
// Remove deleted students or students not matching the search
52+
const terms = search_split(search);
53+
const v1: any[] = [];
54+
for (const x of v0) {
55+
if (x.deleted) continue;
56+
if (
57+
terms.length > 0 &&
58+
!search_match(store.get_student_name(x.student_id).toLowerCase(), terms)
59+
) {
60+
continue;
9861
}
62+
v1.push(x);
63+
}
9964

100-
return v1.map((x) => x.student_id);
101-
}, [
102-
assignment,
103-
students,
104-
user_map,
105-
background,
106-
active_student_sort,
107-
active_feedback_edits,
108-
nbgrader_run_info,
109-
search,
110-
]);
65+
v1.sort(util.pick_student_sorter(active_student_sort.toJS()));
11166

112-
function get_store(): CourseStore {
113-
return redux.getStore(name) as any;
67+
if (active_student_sort.get("is_descending")) {
68+
v1.reverse();
11469
}
11570

116-
function is_peer_graded(): boolean {
117-
const peer_info = assignment.get("peer_grade");
118-
return peer_info ? peer_info.get("enabled") : false;
119-
}
71+
return v1.map((x) => x.student_id);
72+
}, [
73+
assignment,
74+
students,
75+
user_map,
76+
background,
77+
active_student_sort,
78+
active_feedback_edits,
79+
nbgrader_run_info,
80+
search,
81+
]);
12082

121-
function render_student_info(student_id: string): Rendered {
122-
const store = get_store();
123-
const student = store.get_student(student_id);
124-
if (student == null) return; // no such student
125-
const key = util.assignment_identifier(
126-
assignment.get("assignment_id"),
127-
student_id,
128-
);
129-
const edited_feedback = active_feedback_edits.get(key);
130-
return (
131-
<StudentAssignmentInfo
132-
key={student_id}
133-
title={trunc_middle(store.get_student_name(student_id), 40)}
134-
name={name}
135-
student={student}
136-
assignment={assignment}
137-
grade={store.get_grade(assignment.get("assignment_id"), student_id)}
138-
nbgrader_scores={store.get_nbgrader_scores(
139-
assignment.get("assignment_id"),
140-
student_id,
141-
)}
142-
nbgrader_score_ids={store.get_nbgrader_score_ids(
143-
assignment.get("assignment_id"),
144-
)}
145-
comments={store.get_comments(
146-
assignment.get("assignment_id"),
147-
student_id,
148-
)}
149-
info={store.student_assignment_info(
150-
student_id,
151-
assignment.get("assignment_id"),
152-
)}
153-
is_editing={!!edited_feedback}
154-
nbgrader_run_info={nbgrader_run_info}
155-
/>
156-
);
157-
}
83+
function get_store(): CourseStore {
84+
return redux.getStore(name) as any;
85+
}
15886

159-
function render_students(): Rendered {
160-
return (
161-
<ScrollableList
162-
rowCount={student_list.length}
163-
rowRenderer={({ key }) => render_student_info(key)}
164-
rowKey={(index) => student_list[index]}
165-
cacheId={`course-assignment-${assignment.get(
166-
"assignment_id",
167-
)}-${name}-${frame_id}`}
168-
/>
169-
);
170-
}
87+
function is_peer_graded(): boolean {
88+
const peer_info = assignment.get("peer_grade");
89+
return peer_info ? peer_info.get("enabled") : false;
90+
}
91+
92+
function render_student_info(student_id: string) {
93+
const store = get_store();
94+
const student = store.get_student(student_id);
95+
if (student == null) return; // no such student
96+
const key = util.assignment_identifier(
97+
assignment.get("assignment_id"),
98+
student_id,
99+
);
100+
const edited_feedback = active_feedback_edits.get(key);
101+
return (
102+
<StudentAssignmentInfo
103+
key={student_id}
104+
title={trunc_middle(store.get_student_name(student_id), 40)}
105+
name={name}
106+
student={student}
107+
assignment={assignment}
108+
grade={store.get_grade(assignment.get("assignment_id"), student_id)}
109+
nbgrader_scores={store.get_nbgrader_scores(
110+
assignment.get("assignment_id"),
111+
student_id,
112+
)}
113+
nbgrader_score_ids={store.get_nbgrader_score_ids(
114+
assignment.get("assignment_id"),
115+
)}
116+
comments={store.get_comments(
117+
assignment.get("assignment_id"),
118+
student_id,
119+
)}
120+
info={store.student_assignment_info(
121+
student_id,
122+
assignment.get("assignment_id"),
123+
)}
124+
is_editing={!!edited_feedback}
125+
nbgrader_run_info={nbgrader_run_info}
126+
/>
127+
);
128+
}
171129

130+
function render_students() {
172131
return (
173-
<div style={{ height: "70vh", display: "flex", flexDirection: "column" }}>
174-
<StudentAssignmentInfoHeader
175-
key="header"
176-
title="Student"
177-
peer_grade={is_peer_graded()}
178-
/>
179-
{render_students()}
180-
</div>
132+
<ScrollableList
133+
rowCount={student_list.length}
134+
rowRenderer={({ key }) => render_student_info(key)}
135+
rowKey={(index) => student_list[index]}
136+
cacheId={`course-assignment-${assignment.get(
137+
"assignment_id",
138+
)}-${name}-${frame_id}`}
139+
/>
181140
);
182-
}, isSame);
141+
}
142+
143+
return (
144+
<div style={{ height: "70vh", display: "flex", flexDirection: "column" }}>
145+
<StudentAssignmentInfoHeader
146+
key="header"
147+
title="Student"
148+
peer_grade={is_peer_graded()}
149+
/>
150+
{render_students()}
151+
</div>
152+
);
153+
}

0 commit comments

Comments
 (0)