diff --git a/webclient/package.json b/webclient/package.json
index 48f15c7..6d69b2d 100644
--- a/webclient/package.json
+++ b/webclient/package.json
@@ -13,6 +13,7 @@
"react-quill": "^1.3.3",
"react-router-dom": "^5.1.2",
"react-scripts": "3.3.0",
+ "react-to-print": "^2.5.1",
"semantic-ui-react": "^0.88.2",
"serialize-javascript": "^2.1.2"
},
diff --git a/webclient/src/InstructorClasses.js b/webclient/src/InstructorClasses.js
index 0b7febe..27f5d0b 100644
--- a/webclient/src/InstructorClasses.js
+++ b/webclient/src/InstructorClasses.js
@@ -1,5 +1,6 @@
-import React, { useState, useEffect } from 'react';
+import React, { useState, useEffect, useRef } from 'react';
import { BrowserRouter as Router, Switch, Route, Link, useParams, useHistory } from 'react-router-dom';
+import ReactToPrint from 'react-to-print';
import * as Datetime from 'react-datetime';
import 'react-datetime/css/react-datetime.css';
import moment from 'moment';
@@ -8,6 +9,62 @@ import { Button, Container, Checkbox, Divider, Dropdown, Form, Grid, Header, Ico
import { BasicTable, staticUrl, requester } from './utils.js';
import { MembersDropdown } from './Members.js';
+class AttendanceSheet extends React.Component {
+ render() {
+ const clazz = this.props.clazz;
+ const num = clazz.students.length;
+
+ return (
+
+
{clazz.course_name} Attendance
+
+ {moment.utc(clazz.datetime).local().format('llll')}
+ {num >= 2 ? ', '+num+' students sorted by registration time.' : '.'}
+
+
+
+
+
+ {clazz.students
+ .filter(x => x.attendance_status !== 'Withdrawn')
+ .slice(0, 15)
+ .map(x =>
+
+
+
+
+
+ {x.student_name}
+
+
+ )
+ }
+
+
+
+
+ {clazz.students
+ .filter(x => x.attendance_status !== 'Withdrawn')
+ .slice(15)
+ .map(x =>
+
+
+
+
+
+ {x.student_name}
+
+
+ )
+ }
+
+
+
+
+ );
+ }
+}
+
function AttendanceRow(props) {
const { student, token, refreshClass } = props;
const [error, setError] = useState(false);
@@ -67,6 +124,7 @@ export function InstructorClassAttendance(props) {
const [input, setInput] = useState({});
const [error, setError] = useState(false);
const [loading, setLoading] = useState(false);
+ const printRef = useRef();
const handleValues = (e, v) => setInput({ ...input, [v.name]: v.value });
@@ -106,6 +164,16 @@ export function InstructorClassAttendance(props) {
+ {!!clazz.students.length &&
+
+
}
+ content={() => printRef.current}
+ />
+ }
+
{clazz.students.length ?
clazz.students.map(x =>
diff --git a/webclient/yarn.lock b/webclient/yarn.lock
index aa372f2..828b2c4 100644
--- a/webclient/yarn.lock
+++ b/webclient/yarn.lock
@@ -8724,6 +8724,13 @@ react-scripts@3.3.0:
optionalDependencies:
fsevents "2.1.2"
+react-to-print@^2.5.1:
+ version "2.5.1"
+ resolved "https://registry.yarnpkg.com/react-to-print/-/react-to-print-2.5.1.tgz#eaaff4248910f179788ab15a593ceb3e07527b8c"
+ integrity sha512-HhuujwTmuGYB+yBq52y1pwiv0aooaLTqksMJ6cGKWy+aT+x6zponitZd54swiAeILndxJ7oO+X1F/93XyfT/JA==
+ dependencies:
+ prop-types "^15.7.2"
+
react@^16.12.0:
version "16.12.0"
resolved "https://registry.yarnpkg.com/react/-/react-16.12.0.tgz#0c0a9c6a142429e3614834d5a778e18aa78a0b83"