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/configure-peer.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
/*
7
Panel for configuring peer grading.
8
*/
9
10
import {
11
DateTimePicker,
12
Icon,
13
MarkdownInput,
14
} from "@cocalc/frontend/components";
15
import { server_days_ago } from "@cocalc/util/misc";
16
import { Button, Card, Col, InputNumber, Row, Switch, Typography } from "antd";
17
import { CourseActions } from "../actions";
18
import { AssignmentRecord } from "../store";
19
import {
20
PEER_GRADING_GUIDE_FILENAME,
21
PEER_GRADING_GUIDELINES_GRADE_MARKER,
22
PEER_GRADING_DEFAULT_GUIDELINES,
23
} from "./consts";
24
25
interface Props {
26
assignment: AssignmentRecord;
27
actions: CourseActions;
28
}
29
30
export function ConfigurePeerGrading({ assignment, actions }: Props) {
31
const peer_info = assignment.get("peer_grade");
32
const config: { enabled: boolean; number: number } = {
33
number: 1,
34
enabled: false,
35
...peer_info?.toJS(),
36
};
37
38
function render_configure_peer_checkbox(config) {
39
return (
40
<Row style={{ marginTop: "10px" }}>
41
<Col span={12}>
42
<Switch
43
checked={config.enabled}
44
onChange={(checked) => set_peer_grade({ enabled: checked })}
45
style={{ display: "inline-block", verticalAlign: "middle" }}
46
/>
47
</Col>
48
<Col span={12}>Enable Peer Grading</Col>
49
</Row>
50
);
51
}
52
53
function peer_due(date): Date | undefined {
54
if (date != null) {
55
return new Date(date);
56
} else {
57
return server_days_ago(-7);
58
}
59
}
60
61
function set_peer_grade(config) {
62
if (config.enabled && !config.guidelines?.trim()) {
63
config.guidelines = PEER_GRADING_DEFAULT_GUIDELINES;
64
}
65
actions.assignments.set_peer_grade(assignment.get("assignment_id"), config);
66
}
67
68
function peer_due_change(date) {
69
const due_date = peer_due(date);
70
set_peer_grade({
71
due_date: due_date?.toISOString(),
72
});
73
}
74
75
function render_configure_peer_due(config) {
76
const label = (
77
<Typography.Paragraph
78
ellipsis={{ expandable: true, rows: 1, symbol: "more info" }}
79
>
80
Due date:{" "}
81
<Typography.Text type={"secondary"}>
82
Set the due date for grading this assignment. Note: you must
83
explicitly click a button to collect graded assignments – they are not
84
automatically collected on the due date. A file is included in the
85
student peer grading assignment telling them when they should finish
86
their grading.
87
</Typography.Text>
88
</Typography.Paragraph>
89
);
90
return (
91
<Row style={{ marginTop: "10px" }}>
92
<Col span={12}>{label}</Col>
93
<Col span={12}>
94
<DateTimePicker
95
style={{ width: "100%" }}
96
placeholder={"Set Peer Grading Due Date"}
97
value={peer_due(config.due_date)}
98
onChange={peer_due_change}
99
/>
100
</Col>
101
</Row>
102
);
103
}
104
105
function render_configure_peer_number(config) {
106
const store = actions.get_store();
107
const maxVal = (store?.num_students() ?? 2) - 1;
108
return (
109
<Row style={{ marginTop: "10px" }}>
110
<Col span={12}>Number of students who will grade each assignment</Col>
111
<Col span={12}>
112
<InputNumber
113
onChange={(n) => set_peer_grade({ number: n })}
114
min={1}
115
max={maxVal}
116
value={config.number}
117
/>
118
</Col>
119
</Row>
120
);
121
}
122
123
function render_configure_grading_guidelines(config) {
124
return (
125
<Row style={{ marginTop: "10px" }}>
126
<Col span={12}>
127
<Typography.Paragraph
128
ellipsis={{ expandable: true, rows: 1, symbol: "more info" }}
129
>
130
Grading guidelines:{" "}
131
<Typography.Text type={"secondary"}>
132
This text will be made available to students in their grading
133
folder in a file <code>{PEER_GRADING_GUIDE_FILENAME}</code>. Tell
134
your students how to grade each problem. Since this is a markdown
135
file, you might also provide a link to a publicly shared file or
136
directory with additional guidelines. If you keep the default "
137
{PEER_GRADING_GUIDELINES_GRADE_MARKER}" text, then the grade the
138
student puts after that will be parsed from the file and the
139
default grade assigned to the student will be the average of the
140
peer grades. You can edit the grade before returning the graded
141
assignment to the student.
142
</Typography.Text>
143
</Typography.Paragraph>
144
</Col>
145
<Col span={12}>
146
<div
147
style={{
148
background: "white",
149
padding: "10px",
150
border: "1px solid #ccc",
151
borderRadius: "3px",
152
}}
153
>
154
<MarkdownInput
155
persist_id={
156
assignment.get("path") +
157
assignment.get("assignment_id") +
158
"grading-guidelines"
159
}
160
attach_to={actions.name}
161
rows={16}
162
placeholder="Enter your grading guidelines for this assignment..."
163
default_value={config.guidelines}
164
on_save={(x) => set_peer_grade({ guidelines: x })}
165
/>
166
</div>
167
</Col>
168
</Row>
169
);
170
}
171
172
function render_configure_grid(config) {
173
return (
174
<>
175
{render_configure_peer_number(config)}
176
{render_configure_peer_due(config)}
177
{render_configure_grading_guidelines(config)}
178
</>
179
);
180
}
181
182
return (
183
<Card
184
style={{ background: "#fcf8e3", whiteSpace: "normal" }}
185
title={
186
<h3>
187
<Icon name="users" /> Peer grading
188
</h3>
189
}
190
>
191
<Typography.Text type="secondary">
192
Use peer grading to randomly (and anonymously) redistribute collected
193
homework to your students, so that they can grade it for you.
194
</Typography.Text>
195
196
{render_configure_peer_checkbox(config)}
197
{config.enabled ? render_configure_grid(config) : undefined}
198
<div style={{ marginTop: "10px" }}>
199
<Button
200
onClick={() =>
201
actions.toggle_item_expansion(
202
"peer_config",
203
assignment.get("assignment_id"),
204
)
205
}
206
>
207
Close
208
</Button>
209
</div>
210
</Card>
211
);
212
}
213
214