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 | 6x 6x 6x 6x 6x 6x | import * as React from "react";
import Box from "@mui/material/Box";
import Paper from "@mui/material/Paper";
import Stack from "@mui/material/Stack";
import Typography from "@mui/material/Typography";
import Alert from "@mui/material/Alert";
import AlertTitle from "@mui/material/AlertTitle";
import Button from "@mui/material/Button";
import CheckCircleOutlineIcon from "@mui/icons-material/CheckCircleOutline";
/**
* What actually happened, after a commit.
*
* A partial result is reported as a partial result. The API returns `partial: true` when
* some questions were written and others were not, and saying "done" in that case would
* leave a teacher unable to tell which questions reached their bank.
*
* The same principle governs the two reasons a question can be found and not created.
* "Removed during review" was accurate when the teacher deleting a row was the only way
* to lose one. Duplicate skipping added a second reason, and it landed in the same
* derived bucket -- so an import of a question already in the bank told the teacher they
* had removed something they never touched. The counts are separated here because the
* two need different actions from them: one is their own edit, the other is a question
* they already own.
*
* Developer: Allan Ninal
*/
export default function ImportResults({ committed, rowErrors = [], questionsFound = 0, onDone }) {
const created = committed?.created ?? 0;
const failed = committed?.failed ?? 0;
const partial = Boolean(committed?.partial);
// Reported by the API, not derived: it knows WHY it skipped these.
const skippedDuplicates = committed?.skipped_duplicates ?? 0;
// What is left over once the explained outcomes are accounted for is what the
// teacher actually removed on the review screen.
const removedInReview = Math.max(questionsFound - created - failed - skippedDuplicates, 0);
return (
<Box data-testid="import-results">
<Paper variant="outlined" sx={{ p: 3 }}>
<Stack spacing={2}>
{partial ? (
<Alert severity="warning" data-testid="partial-result">
<AlertTitle>Some questions were not added</AlertTitle>
{created} of {created + failed} were added to your question bank. The rest were not —
nothing was lost, but you will need to try those again.
</Alert>
) : (
<Alert
// Nothing added is not a success, and a green tick over
// "Added 0 questions" reads as one.
severity={created > 0 ? "success" : "info"}
icon={created > 0 ? <CheckCircleOutlineIcon fontSize="inherit" /> : undefined}
data-testid="success-result"
>
<AlertTitle>
Added {created} question{created === 1 ? "" : "s"}
</AlertTitle>
{created > 0
? "They are in your question bank now."
: "Nothing new was added to your question bank."}
</Alert>
)}
{failed > 0 && (
<Box>
<Typography variant="subtitle2" gutterBottom>
Not added
</Typography>
{(committed?.failures ?? []).map((failure, i) => (
<Typography key={i} variant="body2" color="text.secondary">
Question {failure.question}: {failure.message}
</Typography>
))}
</Box>
)}
{rowErrors.length > 0 && (
<Typography variant="body2" color="text.secondary">
{rowErrors.length} row{rowErrors.length === 1 ? "" : "s"} in your file could not be read and
were not imported.
</Typography>
)}
{skippedDuplicates > 0 && (
<Typography variant="body2" color="text.secondary" data-testid="skipped-duplicates">
{skippedDuplicates} question{skippedDuplicates === 1 ? " was" : "s were"} skipped
{skippedDuplicates === 1 ? " because it is" : " because they are"} already in your bank.
</Typography>
)}
{removedInReview > 0 && (
<Typography variant="body2" color="text.secondary" data-testid="removed-in-review">
{removedInReview} question{removedInReview === 1 ? " was" : "s were"} removed during review.
</Typography>
)}
<Stack direction="row" justifyContent="flex-end">
<Button variant="contained" onClick={onDone} data-testid="results-done">
Back to my questions
</Button>
</Stack>
</Stack>
</Paper>
</Box>
);
}
|