Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemathinc
GitHub Repository: sagemathinc/cocalc
Path: blob/master/src/packages/frontend/course/common/course-unit-strings.tsx
10799 views
1
/*
2
* This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.
3
* License: MS-RSL – see LICENSE.md for details
4
*/
5
6
import { ReactNode } from "react";
7
import type { IntlShape } from "react-intl";
8
9
import { labels } from "@cocalc/frontend/i18n";
10
11
import type { AssignmentCopyStep, AssignmentStep } from "../types";
12
13
export type UnitLabel = "assignment" | "handout";
14
15
interface ControlMessages {
16
label: string;
17
title: string;
18
tip: string;
19
}
20
21
interface DeleteConfirmMessages {
22
title: string;
23
body: string;
24
}
25
26
interface NoContentMessages {
27
message: string;
28
description: (openDirLink: (chunks: ReactNode) => ReactNode) => ReactNode;
29
}
30
31
export function openFolderMessages(
32
intl: IntlShape,
33
unitLabel: UnitLabel,
34
): ControlMessages {
35
return {
36
label: intl.formatMessage(labels.open),
37
title: intl.formatMessage({
38
id: "course.unit_strings.open_folder.title",
39
defaultMessage: "Open Folder",
40
}),
41
tip:
42
unitLabel === "assignment"
43
? intl.formatMessage({
44
id: "course.unit_strings.open_folder.tip.assignment",
45
defaultMessage:
46
"Open the directory in the current project that contains the original files for this assignment. Edit files in this folder to create the content that your students will see when they receive this assignment.",
47
})
48
: intl.formatMessage({
49
id: "course.unit_strings.open_folder.tip.handout",
50
defaultMessage:
51
"Open the directory in the current project that contains the original files for this handout. Edit files in this folder to create the content that your students will see when they receive this handout.",
52
}),
53
};
54
}
55
56
export function fileActivityMessages(
57
intl: IntlShape,
58
unitLabel: UnitLabel,
59
): ControlMessages {
60
return {
61
label: intl.formatMessage({
62
id: "course.unit_strings.file_activity.label",
63
defaultMessage: "File Activity",
64
}),
65
title: intl.formatMessage({
66
id: "course.unit_strings.file_activity.title",
67
defaultMessage: "Export File Activity Data",
68
}),
69
tip: intl.formatMessage(
70
{
71
id: "course.unit_strings.file_activity.tip",
72
defaultMessage:
73
"Export a JSON file containing detailed information about when students have opened or edited files in this {unitLabel, select, assignment {assignment} other {handout}}. The JSON file opens in a new tab; {accessField} (milliseconds since the UNIX epoch) indicate when files were opened, and {editField} indicate when they were changed in CoCalc's web editor.",
74
description:
75
"{accessField} and {editField} are literal JSON field names and should not be translated. {unitLabel} is 'assignment' or 'handout'.",
76
},
77
{
78
unitLabel,
79
accessField: "access_times",
80
editField: "edit_times",
81
},
82
),
83
};
84
}
85
86
export function exportCollectedMessages(intl: IntlShape): ControlMessages {
87
return {
88
label: intl.formatMessage({
89
id: "course.unit_strings.export.label",
90
defaultMessage: "Export",
91
description:
92
"Button label in assignment header; exports collected student files as a zip archive",
93
}),
94
title: intl.formatMessage({
95
id: "course.unit_strings.export_collected.title",
96
defaultMessage: "Export Collected Files",
97
}),
98
tip: intl.formatMessage({
99
id: "course.unit_strings.export_collected.tip",
100
defaultMessage:
101
"Export a zip file containing all collected student assignments. This may take a while for large classes.",
102
}),
103
};
104
}
105
106
export function undeleteMessages(
107
intl: IntlShape,
108
unitLabel: UnitLabel,
109
): ControlMessages {
110
return {
111
label: intl.formatMessage({
112
id: "course.unit_strings.undelete.label",
113
defaultMessage: "Undelete",
114
description:
115
"Button label in course unit header; restores a previously deleted assignment or handout",
116
}),
117
title:
118
unitLabel === "assignment"
119
? intl.formatMessage({
120
id: "course.unit_strings.undelete.title.assignment",
121
defaultMessage: "Undelete Assignment",
122
})
123
: intl.formatMessage({
124
id: "course.unit_strings.undelete.title.handout",
125
defaultMessage: "Undelete Handout",
126
}),
127
tip:
128
unitLabel === "assignment"
129
? intl.formatMessage({
130
id: "course.unit_strings.undelete.tip.assignment",
131
defaultMessage:
132
"Make the assignment visible again in the assignment list and in student grade lists.",
133
})
134
: intl.formatMessage({
135
id: "course.unit_strings.undelete.tip.handout",
136
defaultMessage:
137
"Make the handout visible again in the handout list.",
138
}),
139
};
140
}
141
142
export function deleteConfirmMessages(
143
intl: IntlShape,
144
unitLabel: UnitLabel,
145
path: string,
146
): DeleteConfirmMessages {
147
return {
148
title: intl.formatMessage(
149
{
150
id: "course.unit_strings.delete_confirm.title",
151
defaultMessage: 'Are you sure you want to delete "{path}"?',
152
},
153
{ path },
154
),
155
body:
156
unitLabel === "assignment"
157
? intl.formatMessage({
158
id: "course.unit_strings.delete_confirm.body.assignment",
159
defaultMessage:
160
'This removes it from the assignment list and student grade lists, but does not delete any files from disk. You can always undelete it later by clicking "Show deleted assignments".',
161
})
162
: intl.formatMessage({
163
id: "course.unit_strings.delete_confirm.body.handout",
164
defaultMessage:
165
'This removes it from the handout list, but does not delete any files from disk. You can always undelete it later by clicking "Show deleted handouts".',
166
}),
167
};
168
}
169
170
export function deleteLabel(intl: IntlShape): string {
171
return intl.formatMessage({
172
id: "course.unit_strings.delete.label",
173
defaultMessage: "Delete...",
174
description:
175
"Button label in course unit header; opens confirmation to remove assignment or handout from the list",
176
});
177
}
178
179
export function dueDateMessages(intl: IntlShape): ControlMessages {
180
return {
181
label: intl.formatMessage({
182
id: "course.unit_strings.due.label",
183
defaultMessage: "Due:",
184
description:
185
"Inline label before the due date/time picker in unit header",
186
}),
187
title: intl.formatMessage({
188
id: "course.unit_strings.due_date.title",
189
defaultMessage: "Due Date",
190
description: "Tooltip title for the due date/time picker in unit header",
191
}),
192
tip: intl.formatMessage(
193
{
194
id: "course.unit_strings.due_date.tip",
195
defaultMessage:
196
"Set the due date for this assignment. This changes how assignments are sorted. Assignments are not automatically collected when due; you must collect them explicitly. CoCalc also writes the due date to {dueDateFile} in the assignment folder.",
197
description:
198
"{dueDateFile} is a literal filename and should not be translated",
199
},
200
{ dueDateFile: "DUE_DATE.txt" },
201
),
202
};
203
}
204
205
export function skipStepMessages(intl: IntlShape): ControlMessages {
206
return {
207
label: intl.formatMessage({
208
id: "course.unit_strings.skip_step.label",
209
defaultMessage: "Skip",
210
description: "Short label shown on the skip toggle in step headers",
211
}),
212
title: intl.formatMessage({
213
id: "course.unit_strings.skip_step.title",
214
defaultMessage: "Skip This Step",
215
description: "Tooltip title for the skip toggle in step headers",
216
}),
217
tip: intl.formatMessage({
218
id: "course.unit_strings.skip_step.tip",
219
defaultMessage:
220
"Toggle to allow proceeding to the next step without completing this one.",
221
}),
222
};
223
}
224
225
export function filterPlaceholder(intl: IntlShape): string {
226
return intl.formatMessage({
227
id: "course.unit_strings.filter_students.placeholder",
228
defaultMessage: "Filter students...",
229
description:
230
"Placeholder text in input used to filter the student list by name",
231
});
232
}
233
234
export function noteMessages(intl: IntlShape, unitLabel: UnitLabel) {
235
return {
236
title:
237
unitLabel === "assignment"
238
? intl.formatMessage({
239
id: "course.assignments.assignment_notes.tooltip.title",
240
defaultMessage: "Notes about this assignment",
241
})
242
: intl.formatMessage({
243
id: "course.handouts.handout_notes.tooltip.title",
244
defaultMessage: "Notes about this handout",
245
}),
246
tip:
247
unitLabel === "assignment"
248
? intl.formatMessage({
249
id: "course.assignments.assignment_notes.tooltip.tooltip",
250
defaultMessage: `Record notes about this assignment here.
251
These notes are only visible to you, not to your students.
252
Put any instructions to students about assignments in a file in the directory
253
that contains the assignment.`,
254
})
255
: intl.formatMessage({
256
id: "course.handouts.handout_notes.tooltip.tooltip",
257
defaultMessage: `Record notes about this handout here.
258
These notes are only visible to you, not to your students.
259
Put any instructions to students about handouts in a file in the directory
260
that contains the handout.`,
261
}),
262
placeholder:
263
unitLabel === "assignment"
264
? intl.formatMessage({
265
id: "course.assignments.assignment_notes.placeholder",
266
defaultMessage:
267
"Private notes about this assignment (not visible to students)",
268
})
269
: intl.formatMessage({
270
id: "course.handouts.handout_notes.placeholder",
271
defaultMessage:
272
"Private notes about this handout (not visible to students)",
273
}),
274
};
275
}
276
277
export function noContentMessages(
278
intl: IntlShape,
279
unitLabel: UnitLabel,
280
): NoContentMessages {
281
return {
282
message:
283
unitLabel === "assignment"
284
? intl.formatMessage({
285
id: "course.unit_strings.no_content.message.assignment",
286
defaultMessage: "No files in this assignment yet",
287
description:
288
"Warning message in assignment card when assignment directory has no files",
289
})
290
: intl.formatMessage({
291
id: "course.unit_strings.no_content.message.handout",
292
defaultMessage: "No files in this handout yet",
293
description:
294
"Warning message in handout card when handout directory has no files",
295
}),
296
description: (openDirLink) =>
297
unitLabel === "assignment"
298
? intl.formatMessage(
299
{
300
id: "course.unit_strings.no_content.description.assignment",
301
defaultMessage:
302
"Please <openDirLink>open the directory</openDirLink> for this assignment, then create, upload, or copy any content you want into that directory. You will then be able to send it to all of your students.",
303
description:
304
"Warning description in assignment card when assignment directory has no files",
305
},
306
{ openDirLink },
307
)
308
: intl.formatMessage(
309
{
310
id: "course.unit_strings.no_content.description.handout",
311
defaultMessage:
312
"Please <openDirLink>open the directory</openDirLink> for this handout, then create, upload, or copy any content you want into that directory. You will then be able to send it to all of your students.",
313
description:
314
"Warning description in handout card when handout directory has no files",
315
},
316
{ openDirLink },
317
),
318
};
319
}
320
321
export function runAllAriaLabel(intl: IntlShape, step: AssignmentStep): string {
322
switch (step) {
323
case "assignment":
324
return intl.formatMessage({
325
id: "course.run_all.aria.assignment",
326
defaultMessage: "Assign to all students options",
327
});
328
case "collect":
329
return intl.formatMessage({
330
id: "course.run_all.aria.collect",
331
defaultMessage: "Collect from all students options",
332
});
333
case "peer_assignment":
334
return intl.formatMessage({
335
id: "course.run_all.aria.peer_assignment",
336
defaultMessage: "Assign for peer grading options",
337
});
338
case "peer_collect":
339
return intl.formatMessage({
340
id: "course.run_all.aria.peer_collect",
341
defaultMessage: "Collect peer feedback options",
342
});
343
case "return_graded":
344
return intl.formatMessage({
345
id: "course.run_all.aria.return_graded",
346
defaultMessage: "Return to all students options",
347
});
348
case "grade":
349
return intl.formatMessage({
350
id: "course.run_all.aria.grade",
351
defaultMessage: "Autograde options",
352
});
353
case "distribution":
354
return intl.formatMessage({
355
id: "course.run_all.aria.distribution",
356
defaultMessage: "Distribute to all students options",
357
});
358
default:
359
return intl.formatMessage({
360
id: "course.run_all.aria.default",
361
defaultMessage: "Run all options",
362
});
363
}
364
}
365
366
export function peerGradingMessages(intl: IntlShape) {
367
return {
368
label: intl.formatMessage({
369
id: "course.unit_strings.peer_grading.label",
370
defaultMessage: "Peer Grading...",
371
description: "Button label in assignment header to configure peer grading",
372
}),
373
disabledTooltip: intl.formatMessage(
374
{
375
id: "course.unit_strings.peer_disabled.tooltip",
376
defaultMessage:
377
"Peer grading is disabled because {pkg} notebooks were detected",
378
description: "{pkg} is a package name and should not be translated",
379
},
380
{ pkg: "nbgrader" },
381
),
382
disabledAlert: intl.formatMessage(
383
{
384
id: "course.unit_strings.peer_disabled.alert",
385
defaultMessage:
386
"Peer grading was disabled because {pkg} notebooks were detected. Remove {pkg} metadata to re-enable peer grading.",
387
description: "{pkg} is a package name and should not be translated",
388
},
389
{ pkg: "nbgrader" },
390
),
391
};
392
}
393
394
export function copyConfirmAllCaution(
395
intl: IntlShape,
396
step: AssignmentCopyStep,
397
): ReactNode {
398
switch (step) {
399
case "assignment":
400
return intl.formatMessage(
401
{
402
id: "course.unit_strings.copy_confirm_all.assignment",
403
defaultMessage:
404
'CAUTION: All files will be copied again. If you updated a file that a student has also worked on, it will get copied to a backup file ending in a tilde (~), or possibly only be available in snapshots. Select "Replace student files!" if you do <b>not</b> want to create any backups and want to <b>delete</b> all other files in the assignment folder of student projects. <detailsLink>Details</detailsLink>',
405
description:
406
"Warning shown before recopying assignment files for all students",
407
},
408
{
409
b: (chunks) => <b>{chunks}</b>,
410
detailsLink: (chunks) => (
411
<a
412
rel="noopener noreferrer"
413
target="_blank"
414
href="https://doc.cocalc.com/teaching-tips_and_tricks.html#how-exactly-are-assignments-copied-to-students"
415
>
416
{chunks}
417
</a>
418
),
419
},
420
);
421
case "collect":
422
case "peer_collect":
423
return intl.formatMessage({
424
id: "course.unit_strings.copy_confirm_all.collect",
425
defaultMessage:
426
"CAUTION: All files will be copied again. If you have graded or edited a file that a student has updated, it will get copied to a backup file ending in a tilde (~), or possibly only be available in snapshots.",
427
});
428
case "peer_assignment":
429
return intl.formatMessage({
430
id: "course.unit_strings.copy_confirm_all.peer_assignment",
431
defaultMessage:
432
"CAUTION: All files will be copied again. If a student worked on a previously assigned file, it will get copied to a backup file ending in a tilde (~), or possibly only be available in snapshots.",
433
});
434
case "return_graded":
435
return intl.formatMessage({
436
id: "course.unit_strings.copy_confirm_all.return_graded",
437
defaultMessage:
438
"CAUTION: All files will be copied again. If a student edited a previously returned file, it will get copied to a backup file ending in a tilde (~), or possibly only be available in snapshots.",
439
});
440
}
441
}
442
443
export function handoutCopyConfirmAllCaution(intl: IntlShape): string {
444
return intl.formatMessage({
445
id: "course.unit_strings.copy_confirm_all.handout",
446
defaultMessage:
447
'This will copy all files to all students again. CAUTION: if you update a file that a student has also worked on, their work will get copied to a backup file ending in a tilde, or possibly only be available in snapshots. Select "Replace student files!" if you do not want to create any backups and also delete all other files in the handout directory of their projects.',
448
});
449
}
450
451
export function nbgraderMessages(intl: IntlShape) {
452
return {
453
intro: intl.formatMessage(
454
{
455
id: "course.unit_strings.nbgrader_run_all.intro",
456
defaultMessage: "Autograde this assignment using {pkg} for",
457
description:
458
"{pkg} is a package name and should not be translated. This phrase is followed by a button label like 'The 5 students not yet autograded'.",
459
},
460
{
461
pkg: "nbgrader",
462
},
463
),
464
remainingButton: (todo: number) =>
465
intl.formatMessage(
466
{
467
id: "course.unit_strings.nbgrader_run_all.remaining",
468
defaultMessage:
469
"The {count, plural, one {# student not yet autograded} other {# students not yet autograded}}",
470
},
471
{ count: todo },
472
),
473
allButton: (total: number) =>
474
intl.formatMessage(
475
{
476
id: "course.unit_strings.nbgrader_run_all.all_button",
477
defaultMessage:
478
"All {count, plural, one {# student} other {# students}}...",
479
},
480
{ count: total },
481
),
482
confirmAllPrompt: (total: number) =>
483
intl.formatMessage(
484
{
485
id: "course.unit_strings.nbgrader_run_all.confirm_prompt",
486
defaultMessage:
487
"Are you sure you want to autograde ALL {count, plural, one {# student} other {# students}}?",
488
},
489
{ count: total },
490
),
491
confirmAllAction: (total: number) =>
492
intl.formatMessage(
493
{
494
id: "course.unit_strings.nbgrader_run_all.confirm_action",
495
defaultMessage:
496
"Autograde all {count, plural, one {# student} other {# students}}",
497
},
498
{ count: total },
499
),
500
syncButton: intl.formatMessage({
501
id: "course.unit_strings.nbgrader_run_all.sync_button",
502
defaultMessage: "Sync grades...",
503
description:
504
"Button label in nbgrader run-all popover; opens confirmation to sync nbgrader scores into assigned grades for all students",
505
}),
506
syncPrompt: intl.formatMessage(
507
{
508
id: "course.unit_strings.nbgrader_run_all.sync_prompt",
509
defaultMessage:
510
"Force-sync {pkg} scores to assigned grades for all students, including submissions with ungraded manual items or errors?",
511
description: "{pkg} is a package name and should not be translated",
512
},
513
{
514
pkg: "nbgrader",
515
},
516
),
517
syncAction: intl.formatMessage({
518
id: "course.unit_strings.nbgrader_run_all.sync_action",
519
defaultMessage: "Sync grades for all students",
520
}),
521
back: intl.formatMessage({
522
id: "course.unit_strings.nbgrader_run_all.back",
523
defaultMessage: "Back",
524
description:
525
"Button label in nbgrader run-all popover; returns from confirmation view to previous options",
526
}),
527
};
528
}
529
530