Path: blob/master/src/packages/frontend/course/configuration/actions-panel.tsx
5984 views
/*1* This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.2* License: MS-RSL – see LICENSE.md for details3*/45import { Button, Card, Col, Row, Space } from "antd";6import { FormattedMessage, useIntl } from "react-intl";78import { useActions, useStore } from "@cocalc/frontend/app-framework";9import { Icon, Paragraph } from "@cocalc/frontend/components";10import { course } from "@cocalc/frontend/i18n";11import type { ProjectMap } from "@cocalc/frontend/todo-types";12import { RESEND_INVITE_INTERVAL_DAYS } from "@cocalc/util/consts/invites";13import { CourseActions } from "../actions";14import { CourseStore } from "../store";15import { DeleteAllStudentProjects } from "./delete-all-student-projects";16import { DeleteAllStudents } from "./delete-all-students";17import EmptyTrash from "./empty-trash";18import { StudentProjectsStartStopPanel } from "./start-stop-panel";19import { TerminalCommandPanel } from "./terminal-command";2021interface Props {22name: string;23project_map: ProjectMap;24configuring_projects?: boolean;25reinviting_students?: boolean;26}2728export function ActionsPanel({29name,30project_map,31configuring_projects,32reinviting_students,33}: Props) {34const actions = useActions<CourseActions>({ name });3536return (37<div className="smc-vfill" style={{ overflowY: "scroll" }}>38<Row>39<Col md={12} style={{ padding: "15px 15px 15px 0" }}>40<StartAllProjects name={name} project_map={project_map} />41<br />42<ReconfigureAllProjects43configuring_projects={configuring_projects}44actions={actions}45/>46<br />47<TerminalCommandPanel name={name} />48<br />49<ExportGrades actions={actions} />50</Col>51<Col md={12} style={{ padding: "15px" }}>52<ResendInvites53actions={actions}54reinviting_students={reinviting_students}55/>56<br />57<CopyMissingHandoutsAndAssignments actions={actions} />58<br />59<EmptyTrash />60<br />61<DeleteAllStudentProjects actions={actions} />62<br />63<DeleteAllStudents actions={actions} />64</Col>65</Row>66</div>67);68}6970export function StartAllProjects({ name, project_map }) {71const store = useStore<CourseStore>({ name });72const r = store.num_running_projects(project_map);73const n = store.num_students();74return (75<StudentProjectsStartStopPanel76name={name}77num_running_projects={r}78num_students={n}79/>80);81}8283export function ExportGrades({ actions, close }: { actions; close? }) {84const intl = useIntl();8586async function save_grades_to_csv() {87await actions.export.to_csv();88close?.();89}9091async function save_grades_to_py() {92await actions.export.to_py();93close?.();94}9596async function save_grades_to_json() {97await actions.export.to_json();98close?.();99}100101return (102<Card103title={104<>105<Icon name="table" /> {intl.formatMessage(course.export_grades)}106</>107}108>109<Paragraph style={{ marginBottom: "10px" }}>110<FormattedMessage111id="course.actions-panel.export-grades.title"112defaultMessage="Save grades to..."113/>114</Paragraph>115<Space>116<Button onClick={save_grades_to_csv}>117<Icon name="csv" /> CSV file...118</Button>119<Button onClick={save_grades_to_json}>120<Icon name="file-code" /> JSON file...121</Button>122<Button onClick={save_grades_to_py}>123<Icon name="file-code" /> Python file...124</Button>125</Space>126<hr />127<Paragraph type="secondary">128<FormattedMessage129id="course.actions-panel.export-grades.info"130defaultMessage={`Export all the grades you have recorded for students in your course131to a CSV or Python file.132{br}133In Microsoft Excel, you can <A>import the CSV file</A>.`}134values={{135A: (c) => (136<a137target="_blank"138rel="noopener noreferrer"139href="https://support.microsoft.com/en-us/office/import-or-export-text-txt-or-csv-files-5250ac4c-663c-47ce-937b-339e391393ba?ui=en-us&rs=en-us&ad=us"140>141{c}142</a>143),144br: <br />,145}}146/>147</Paragraph>148</Card>149);150}151152export function ReconfigureAllProjects({153actions,154configuring_projects,155}: {156actions;157configuring_projects?: boolean;158}) {159const intl = useIntl();160161return (162<Card163title={164<>165<Icon name="envelope" />{" "}166{intl.formatMessage(course.reconfigure_all_projects)}167</>168}169>170<FormattedMessage171id="course.actions-panel.reconfigure-all-projects.info"172defaultMessage={`Ensure all projects have the correct students and TA's,173titles and descriptions set, etc.174This will also resend any outstanding email invitations.`}175/>176<hr />177<Button178disabled={configuring_projects}179onClick={() => {180actions.configuration.configure_all_projects();181}}182>183{configuring_projects ? <Icon name="cocalc-ring" spin /> : undefined}{" "}184{intl.formatMessage(course.reconfigure_all_projects)}185</Button>186</Card>187);188}189190export function ResendInvites({191actions,192reinviting_students,193}: {194actions;195reinviting_students?;196}) {197const intl = useIntl();198199return (200<Card201title={202<>203<Icon name="envelope" /> {intl.formatMessage(course.resend_invites)}204</>205}206>207<FormattedMessage208id="course.actions-panel.resend-invite.info"209defaultMessage={`Send another email to every student who didn't sign up yet.210This sends a maximum of one email every {days}211{days, plural, one {day} other {days}}.`}212values={{ days: RESEND_INVITE_INTERVAL_DAYS }}213/>214<hr />215<Button216disabled={reinviting_students}217onClick={() => {218actions.student_projects.reinvite_oustanding_students();219}}220>221{reinviting_students ? <Icon name="cocalc-ring" spin /> : undefined}{" "}222<FormattedMessage223id="course.actions-panel.resend-invite.button"224defaultMessage={"Reinvite students"}225description={"Resending email invitiatons to students in a course."}226/>227</Button>228</Card>229);230}231232export function CopyMissingHandoutsAndAssignments({ actions }) {233const intl = useIntl();234return (235<Card236title={237<>238<Icon name="share-square" />{" "}239{intl.formatMessage(course.copy_missing_handouts_assignments)}240</>241}242>243<FormattedMessage244id="course.actions-panel.copy-missing-handouts-assignments"245defaultMessage={`If you <b>add new students</b> to your course,246you can click this button to ensure they have all the assignments and handouts247that you have already assigned to other students in the course.`}248/>249<hr />250<Button251onClick={() => {252actions.configuration.push_missing_handouts_and_assignments();253}}254>255<Icon name="share-square" />{" "}256{intl.formatMessage(course.copy_missing_handouts_assignments)}257</Button>258</Card>259);260}261262263