Path: blob/master/src/packages/frontend/course/assignments/assignment-student-list.tsx
5961 views
/*1* This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.2* License: MS-RSL – see LICENSE.md for details3*/45import { useIntl } from "react-intl";67// CoCalc libraries8import { AppRedux, useMemo, useRedux } from "@cocalc/frontend/app-framework";9import ScrollableList from "@cocalc/frontend/components/scrollable-list";10import { search_match, search_split, trunc_middle } from "@cocalc/util/misc";11import { StudentAssignmentInfo } from "../common";12import type {13AssignmentRecord,14CourseStore,15IsGradingMap,16NBgraderRunInfo,17SortDescription,18} from "../store";19import {20assignment_identifier,21parse_students,22pick_student_sorter,23} from "../util";2425interface StudentListForAssignmentProps {26frame_id?: string;27name: string;28redux: AppRedux;29assignment: AssignmentRecord;30students: any;31user_map: any;32active_feedback_edits: IsGradingMap;33nbgrader_run_info?: NBgraderRunInfo;34search: string;35}3637export function StudentListForAssignment({38frame_id,39name,40redux,41assignment,42students,43user_map,44active_feedback_edits,45nbgrader_run_info,46search,47}: StudentListForAssignmentProps) {48const intl = useIntl();4950const active_student_sort: SortDescription = useRedux(51name,52"active_student_sort",53);54const student_list: string[] = useMemo(() => {55const v0 = parse_students(students, user_map, redux, intl);56const store = get_store();5758// Remove deleted students or students not matching the search59const terms = search_split(search);60const v1: any[] = [];61for (const x of v0) {62if (x.deleted) continue;63if (64terms.length > 0 &&65!search_match(store.get_student_name(x.student_id).toLowerCase(), terms)66) {67continue;68}69v1.push(x);70}7172v1.sort(pick_student_sorter(active_student_sort.toJS()));7374return v1.map((x) => x.student_id);75}, [76students,77user_map,78active_student_sort,79active_feedback_edits,80nbgrader_run_info,81search,82]);8384function get_store(): CourseStore {85return redux.getStore(name) as any;86}8788function render_student_info(student_id: string) {89const store = get_store();90const student = store.get_student(student_id);91if (student == null) return; // no such student92const key = assignment_identifier(93assignment.get("assignment_id"),94student_id,95);96const edited_feedback = active_feedback_edits.get(key);97return (98<StudentAssignmentInfo99key={student_id}100title={trunc_middle(store.get_student_name(student_id), 40)}101name={name}102student={student}103assignment={assignment}104grade={store.get_grade(assignment.get("assignment_id"), student_id)}105nbgrader_scores={store.get_nbgrader_scores(106assignment.get("assignment_id"),107student_id,108)}109nbgrader_score_ids={store.get_nbgrader_score_ids(110assignment.get("assignment_id"),111)}112comments={store.get_comments(113assignment.get("assignment_id"),114student_id,115)}116info={store.student_assignment_info(117student_id,118assignment.get("assignment_id"),119)}120is_editing={!!edited_feedback}121nbgrader_run_info={nbgrader_run_info}122/>123);124}125126function render_students() {127return (128<ScrollableList129virtualize130rowCount={student_list.length}131rowRenderer={({ key }) => render_student_info(key)}132rowKey={(index) => student_list[index]}133cacheId={`course-assignment-${assignment.get(134"assignment_id",135)}-${name}-${frame_id}`}136/>137);138}139140return (141<div style={{ height: "70vh", display: "flex", flexDirection: "column" }}>142{render_students()}143</div>144);145}146147148