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/handouts/handouts-info-panel.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
// CoCalc libraries
7
// React Libraries
8
import { Button, Col, Row, Space } from "antd";
9
import { useState } from "react";
10
import { useIntl } from "react-intl";
11
12
import { Icon, Tip } from "@cocalc/frontend/components";
13
import ShowError from "@cocalc/frontend/components/error";
14
import { COPY_TIMEOUT_MS } from "@cocalc/frontend/course/consts";
15
import { labels } from "@cocalc/frontend/i18n";
16
import { webapp_client } from "@cocalc/frontend/webapp-client";
17
import { to_json } from "@cocalc/util/misc";
18
import { CourseActions } from "../actions";
19
import { BigTime } from "../common";
20
import { LastCopyInfo } from "../store";
21
22
interface StudentHandoutInfoProps {
23
actions: CourseActions;
24
info: { handout_id: string; student_id: string; status?: LastCopyInfo };
25
title: string;
26
}
27
28
export function StudentHandoutInfo({
29
actions,
30
info,
31
title,
32
}: StudentHandoutInfoProps) {
33
const intl = useIntl();
34
35
const [recopy, setRecopy] = useState<boolean>(false);
36
37
function open(handout_id: string, student_id: string): void {
38
actions.handouts.open_handout(handout_id, student_id);
39
}
40
41
function copy(handout_id: string, student_id: string): void {
42
actions.handouts.copy_handout_to_student(handout_id, student_id, false);
43
}
44
45
function stop(handout_id: string, student_id: string): void {
46
actions.handouts.stop_copying_handout(handout_id, student_id);
47
}
48
49
function render_last_time(time) {
50
return (
51
<div key="time" style={{ color: "#666" }}>
52
(<BigTime date={time} />)
53
</div>
54
);
55
}
56
57
function render_open_recopy_confirm(name, copy, copy_tip) {
58
if (recopy) {
59
const v: any[] = [];
60
v.push(
61
<Button key="copy_cancel" onClick={() => setRecopy(false)}>
62
{intl.formatMessage(labels.cancel)}
63
</Button>,
64
);
65
v.push(
66
<Button
67
key="copy_confirm"
68
danger
69
onClick={() => {
70
setRecopy(false);
71
return copy();
72
}}
73
>
74
<Icon name="share-square" /> Yes, {name.toLowerCase()} again
75
</Button>,
76
);
77
return <Space wrap>{v}</Space>;
78
} else {
79
return (
80
<Button type="dashed" key="copy" onClick={() => setRecopy(true)}>
81
<Tip title={name} tip={<span>{copy_tip}</span>}>
82
<Icon name="share-square" /> {name}...
83
</Tip>
84
</Button>
85
);
86
}
87
}
88
89
function render_open_recopy(name, open, copy, copy_tip, open_tip) {
90
return (
91
<Space key="open_recopy">
92
{render_open_recopy_confirm(name, copy, copy_tip)}
93
<Button key="open" onClick={open}>
94
<Tip title="Open Folder" tip={open_tip}>
95
<Icon name="folder-open" /> Open directory...
96
</Tip>
97
</Button>
98
</Space>
99
);
100
}
101
102
function render_open_copying(open, stop) {
103
return (
104
<Space key="open_copying">
105
<Button key="copy" type="primary" disabled={true}>
106
<Icon name="cocalc-ring" spin /> Working...
107
</Button>
108
<Button key="stop" danger onClick={stop}>
109
<Icon name="times" />
110
</Button>
111
<Button key="open" onClick={open}>
112
<Icon name="folder-open" /> Open
113
</Button>
114
</Space>
115
);
116
}
117
118
function render_copy(name, copy, copy_tip) {
119
return (
120
<Tip key="copy" title={name} tip={copy_tip}>
121
<Button onClick={copy} type="primary">
122
<Icon name="share-square" /> {name}
123
</Button>
124
</Tip>
125
);
126
}
127
128
function render_error(name, error) {
129
if (typeof error !== "string") {
130
error = to_json(error);
131
}
132
if (error.indexOf("No such file or directory") !== -1) {
133
error = `Somebody may have moved the folder that should have contained the handout.\n${error}`;
134
} else {
135
error = `Try to ${name.toLowerCase()} again:\n` + error;
136
}
137
return (
138
<ShowError
139
key="error"
140
error={error}
141
style={{ marginTop: "5px", maxHeight: "140px", overflow: "auto" }}
142
/>
143
);
144
}
145
146
function render_last(name, obj, info, enable_copy, copy_tip, open_tip) {
147
const do_open = () => open(info.handout_id, info.student_id);
148
const do_copy = () => copy(info.handout_id, info.student_id);
149
const do_stop = () => stop(info.handout_id, info.student_id);
150
if (obj == null) {
151
obj = {};
152
}
153
const v: any[] = [];
154
if (enable_copy) {
155
if (webapp_client.server_time() - (obj.start ?? 0) < COPY_TIMEOUT_MS) {
156
v.push(render_open_copying(do_open, do_stop));
157
} else if (obj.time) {
158
v.push(render_open_recopy(name, do_open, do_copy, copy_tip, open_tip));
159
} else {
160
v.push(render_copy(name, do_copy, copy_tip));
161
}
162
}
163
if (obj.time) {
164
v.push(render_last_time(obj.time));
165
}
166
if (obj.error) {
167
v.push(render_error(name, obj.error));
168
}
169
return v;
170
}
171
172
return (
173
<div>
174
<Row
175
style={{
176
borderTop: "1px solid #aaa",
177
paddingTop: "5px",
178
paddingBottom: "5px",
179
}}
180
>
181
<Col md={4} key="title">
182
{title}
183
</Col>
184
<Col md={20} key="rest">
185
<Row>
186
<Col md={24} key="last_handout">
187
{render_last(
188
"Distribute",
189
info.status,
190
info,
191
true,
192
"Copy the handout from your project to this student's project.",
193
"Open the student's copy of this handout directly in their project. You will be able to see them type, chat with them, answer questions, etc.",
194
)}
195
</Col>
196
</Row>
197
</Col>
198
</Row>
199
</div>
200
);
201
}
202
203