Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 47x 47x 47x 47x 47x 47x 47x 47x 47x 47x 1x 1x 1x 1x 47x 1x 1x 1x 47x 47x 47x 47x 47x 1x 1x 47x 2x 2x 2x 2x 2x 2x 2x 2x 2x 47x 2x 2x 1x 1x 2x 2x 2x 2x 47x 47x 47x 47x 47x 2x 2x 47x 47x 47x 47x 47x 47x 47x 47x 47x 47x 47x 47x 47x 47x 47x 47x 47x 47x 47x 47x 47x 47x 47x 47x 47x 47x | import { toast } from "react-toastify";
import { useBackend, useBackendMutation } from "main/utils/useBackend";
import React, { useState } from "react";
import { Button, Modal } from "react-bootstrap";
import StaffCSVUploadForm from "main/components/Staff/StaffCSVUploadForm";
import StaffForm from "main/components/Staff/StaffForm";
import StaffTable from "main/components/Staff/StaffTable";
// The Staff tab of a course's admin page: adding staff (individually or via
// CSV roster upload) is scoped to this courseId, not a free-standing admin
// page with a course-picker. See issue #251.
export default function StaffTabComponent({ courseId, currentUser }) {
const [showAddModal, setShowAddModal] = useState(false);
const [showCsvModal, setShowCsvModal] = useState(false);
const queryKey = [`/api/staff/course/${courseId}`];
// Stryker disable all
const { data: staff } = useBackend(
queryKey,
{ method: "GET", url: `/api/staff/course/${courseId}` },
[],
);
// Stryker restore all
const objectToAxiosParamsAdd = (staffMember) => ({
url: "/api/staff",
method: "POST",
data: { ...staffMember, courseId },
});
const onAddSuccess = () => {
toast("Staff member added successfully.");
setShowAddModal(false);
};
const addMutation = useBackendMutation(
objectToAxiosParamsAdd,
{ onSuccess: onAddSuccess },
queryKey,
);
const submitAddForm = (data) => {
addMutation.mutate(data);
};
const objectToAxiosParamsCsv = (formData) => {
const file = new FormData();
file.append("file", formData.upload[0]);
return {
url: "/api/staff/upload/csv",
method: "POST",
params: { courseId },
data: file,
};
};
const onCsvSuccess = (result) => {
const skipped = result.skippedEmails.length;
const skippedMessage = skipped
? `, ${skipped} skipped (already on roster)`
: "";
toast(
`Roster uploaded: ${result.created} staff member(s) added${skippedMessage}.`,
);
setShowCsvModal(false);
};
const csvMutation = useBackendMutation(
objectToAxiosParamsCsv,
{ onSuccess: onCsvSuccess },
queryKey,
);
const submitCsvForm = (formData) => {
csvMutation.mutate(formData);
};
return (
<div data-testid="StaffTabComponent">
<Modal show={showAddModal} onHide={() => setShowAddModal(false)}>
<Modal.Header closeButton>
<Modal.Title>Add Individual Staff Member</Modal.Title>
</Modal.Header>
<Modal.Body>
<StaffForm submitAction={submitAddForm} cancelDisabled={true} />
</Modal.Body>
</Modal>
<Modal show={showCsvModal} onHide={() => setShowCsvModal(false)}>
<Modal.Header closeButton>
<Modal.Title>Upload CSV Roster</Modal.Title>
</Modal.Header>
<Modal.Body>
<StaffCSVUploadForm submitAction={submitCsvForm} />
</Modal.Body>
</Modal>
<Button
variant="primary"
className="mb-3 me-2"
data-testid="StaffTabComponent-add-button"
onClick={() => setShowAddModal(true)}
>
Add Individual Staff Member
</Button>
<Button
variant="secondary"
className="mb-3"
data-testid="StaffTabComponent-csv-button"
onClick={() => setShowCsvModal(true)}
>
Upload CSV Roster
</Button>
<StaffTable staff={staff} currentUser={currentUser} courseId={courseId} />
</div>
);
}
|