Skip to content

Commit 7fb5b50

Browse files
committed
fix #5518 -- improve sorting of students in a course
1 parent 55f60cd commit 7fb5b50

File tree

2 files changed

+41
-19
lines changed

2 files changed

+41
-19
lines changed

src/packages/frontend/course/util.ts

Lines changed: 40 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -169,8 +169,8 @@ export function immutable_to_list<T, P>(
169169
): T extends TypedMap<infer S>
170170
? S[]
171171
: T extends Map<string, infer S>
172-
? S[]
173-
: any;
172+
? S[]
173+
: any;
174174
export function immutable_to_list(x: any, primary_key?): any {
175175
if (x == null || x == undefined) {
176176
return;
@@ -242,34 +242,56 @@ export function order_list<T extends { deleted: boolean }>(opts: {
242242
return { list, deleted: x, num_deleted: sorted_deleted.length };
243243
}
244244

245-
const sort_on_string_field = (field) => (a, b) =>
246-
cmp(a[field].toLowerCase(), b[field].toLowerCase());
245+
const cmp_strings = (a, b, field) => {
246+
return cmp(a[field]?.toLowerCase() ?? "", b[field]?.toLowerCase() ?? "");
247+
};
247248

248-
const sort_on_numerical_field = (field) => (a, b) =>
249-
cmp(a[field] * -1, b[field] * -1);
249+
// first sort by domain, then address at that domain... since there will be many students
250+
// at same domain, and '[email protected]' > '[email protected]' > '[email protected]' is true but not helpful
251+
const cmp_email = (a, b) => {
252+
const v = a.split("@");
253+
const w = b.split("@");
254+
const c = cmp(v[1], w[1]);
255+
if (c) {
256+
return c;
257+
}
258+
return cmp(v[0], w[0]);
259+
};
250260

251-
export enum StudentField {
252-
email = "email",
253-
first_name = "first_name",
254-
last_name = "last_name",
255-
last_active = "last_active",
256-
hosting = "hosting",
257-
}
261+
const sort_on_string_field = (field, field2) => (a, b) => {
262+
const c =
263+
field == "email_address"
264+
? cmp_email(a[field], b[field])
265+
: cmp_strings(a, b, field);
266+
return c != 0 ? c : cmp_strings(a, b, field2);
267+
};
268+
269+
const sort_on_numerical_field = (field, field2) => (a, b) => {
270+
const c = cmp((a[field] ?? 0) * -1, (b[field] ?? 0) * -1);
271+
return c != 0 ? c : cmp_strings(a, b, field2);
272+
};
273+
274+
type StudentField =
275+
| "email"
276+
| "first_name"
277+
| "last_name"
278+
| "last_active"
279+
| "hosting";
258280

259281
export function pick_student_sorter<T extends { column_name: StudentField }>(
260282
sort: T,
261283
) {
262284
switch (sort.column_name) {
263285
case "email":
264-
return sort_on_string_field("email_address");
286+
return sort_on_string_field("email_address", "last_name");
265287
case "first_name":
266-
return sort_on_string_field("first_name");
288+
return sort_on_string_field("first_name", "last_name");
267289
case "last_name":
268-
return sort_on_string_field("last_name");
290+
return sort_on_string_field("last_name", "first_name");
269291
case "last_active":
270-
return sort_on_numerical_field("last_active");
292+
return sort_on_numerical_field("last_active", "last_name");
271293
case "hosting":
272-
return sort_on_string_field("hosting");
294+
return sort_on_string_field("hosting", "email_address");
273295
}
274296
}
275297

src/packages/frontend/frame-editors/course-editor/course-panel-wrapper.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ const CoursePanelWrapper: React.FC<FrameProps> = React.memo(
195195
error={error}
196196
setError={(error) => {
197197
const actions = redux.getActions(name) as CourseActions;
198-
if (actions != null) actions.set_error("");
198+
actions?.set_error(error);
199199
}}
200200
/>
201201
);

0 commit comments

Comments
 (0)