Added download option for assignment cards
Export PDF Download to hook Prevented some NaN's
This commit is contained in:
@@ -15,17 +15,14 @@ import { withIronSessionApiRoute } from "iron-session/next";
|
||||
import { sessionOptions } from "@/lib/session";
|
||||
import ReactPDF from "@react-pdf/renderer";
|
||||
import GroupTestReport from "@/exams/pdf/group.test.report";
|
||||
import { ref, uploadBytes } from "firebase/storage";
|
||||
import { ref, uploadBytes, getDownloadURL } from "firebase/storage";
|
||||
import { Stat } from "@/interfaces/user";
|
||||
import { User } from "@/interfaces/user";
|
||||
import { Module } from "@/interfaces";
|
||||
import { ModuleScore, StudentData } from "@/interfaces/module.scores";
|
||||
import qrcode from "qrcode";
|
||||
import { SkillExamDetails } from "@/exams/pdf/details/skill.exam";
|
||||
import { LevelExamDetails } from "@/exams/pdf/details/level.exam";
|
||||
import { calculateBandScore, getLevelScore } from "@/utils/score";
|
||||
import axios from "axios";
|
||||
import { moduleLabels } from "@/utils/moduleUtils";
|
||||
import {
|
||||
generateQRCode,
|
||||
getRadialProgressPNG,
|
||||
@@ -121,17 +118,25 @@ async function post(req: NextApiRequest, res: NextApiResponse) {
|
||||
results: any;
|
||||
exams: { module: Module }[];
|
||||
startDate: string;
|
||||
pdf?: string;
|
||||
};
|
||||
if (!data) {
|
||||
res.status(400).end();
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Reenable this
|
||||
// if (data.assigner !== req.session.user.id) {
|
||||
// res.status(401).json({ ok: false });
|
||||
// return;
|
||||
// }
|
||||
if (data.assigner !== req.session.user.id) {
|
||||
res.status(401).json({ ok: false });
|
||||
return;
|
||||
}
|
||||
if (data.pdf) {
|
||||
// if it does, return the pdf url
|
||||
const fileRef = ref(storage, data.pdf);
|
||||
const url = await getDownloadURL(fileRef);
|
||||
|
||||
res.status(200).end(url);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const docUser = await getDoc(doc(db, "users", req.session.user.id));
|
||||
@@ -185,9 +190,10 @@ async function post(req: NextApiRequest, res: NextApiResponse) {
|
||||
(e) => e.module === module
|
||||
);
|
||||
|
||||
const bandScore =
|
||||
const baseBandScore =
|
||||
moduleResults.reduce((accm, curr) => accm + curr.bandScore, 0) /
|
||||
moduleResults.length;
|
||||
const bandScore = isNaN(baseBandScore) ? 0 : baseBandScore;
|
||||
const { correct, total } = getScoreAndTotal(moduleResults);
|
||||
const png = getRadialProgressPNG("azul", correct, total);
|
||||
|
||||
@@ -203,7 +209,8 @@ async function post(req: NextApiRequest, res: NextApiResponse) {
|
||||
|
||||
const { correct: overallCorrect, total: overallTotal } =
|
||||
getScoreAndTotal(flattenResults);
|
||||
const overallResult = overallCorrect / overallTotal;
|
||||
const baseOverallResult = overallCorrect / overallTotal;
|
||||
const overallResult = isNaN(baseOverallResult) ? 0 : baseOverallResult;
|
||||
|
||||
const overallPNG = getRadialProgressPNG(
|
||||
"laranja",
|
||||
@@ -365,7 +372,8 @@ async function post(req: NextApiRequest, res: NextApiResponse) {
|
||||
|
||||
// generate the file ref for storage
|
||||
const fileName = `${Date.now().toString()}.pdf`;
|
||||
const fileRef = ref(storage, `assignment_report/${fileName}`);
|
||||
const refName = `assignment_report/${fileName}`;
|
||||
const fileRef = ref(storage, refName);
|
||||
|
||||
// upload the pdf to storage
|
||||
const pdfBuffer = await streamToBuffer(pdfStream);
|
||||
@@ -375,9 +383,10 @@ async function post(req: NextApiRequest, res: NextApiResponse) {
|
||||
|
||||
// update the stats entries with the pdf url to prevent duplication
|
||||
await updateDoc(docSnap.ref, {
|
||||
pdf: snapshot.ref.fullPath,
|
||||
pdf: refName,
|
||||
});
|
||||
res.status(200).end(snapshot.ref.fullPath);
|
||||
const url = await getDownloadURL(fileRef);
|
||||
res.status(200).end(url);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -407,7 +416,9 @@ async function get(req: NextApiRequest, res: NextApiResponse) {
|
||||
}
|
||||
|
||||
if (data.pdf) {
|
||||
return res.end(data.pdf);
|
||||
const fileRef = ref(storage, data.pdf);
|
||||
const url = await getDownloadURL(fileRef);
|
||||
return res.redirect(url);
|
||||
}
|
||||
|
||||
res.status(404).end();
|
||||
|
||||
@@ -24,9 +24,7 @@ import useGroups from "@/hooks/useGroups";
|
||||
import {shouldRedirectHome} from "@/utils/navigation.disabled";
|
||||
import useAssignments from "@/hooks/useAssignments";
|
||||
import {uuidv4} from "@firebase/util";
|
||||
import { BsFilePdf } from "react-icons/bs";
|
||||
import axios from "axios";
|
||||
import {toast} from "react-toastify";
|
||||
import { usePDFDownload } from "@/hooks/usePDFDownload";
|
||||
|
||||
export const getServerSideProps = withIronSessionSsr(({req, res}) => {
|
||||
const user = req.session.user;
|
||||
@@ -58,10 +56,6 @@ export const getServerSideProps = withIronSessionSsr(({req, res}) => {
|
||||
};
|
||||
}, sessionOptions);
|
||||
|
||||
type DownloadingPdf = {
|
||||
[key: string]: boolean;
|
||||
};
|
||||
|
||||
export default function History({user}: {user: User}) {
|
||||
const [statsUserId, setStatsUserId] = useState<string | undefined>(user.id);
|
||||
const [groupedStats, setGroupedStats] = useState<{[key: string]: Stat[]}>();
|
||||
@@ -76,8 +70,8 @@ export default function History({user}: {user: User}) {
|
||||
const setShowSolutions = useExamStore((state) => state.setShowSolutions);
|
||||
const setUserSolutions = useExamStore((state) => state.setUserSolutions);
|
||||
const setSelectedModules = useExamStore((state) => state.setSelectedModules);
|
||||
const [downloadingPdf, setDownloadingPdf] = useState<DownloadingPdf>({});
|
||||
const router = useRouter();
|
||||
const renderPdfIcon = usePDFDownload("stats");
|
||||
|
||||
useEffect(() => {
|
||||
if (stats && !isStatsLoading) {
|
||||
@@ -208,28 +202,6 @@ export default function History({user}: {user: User}) {
|
||||
correct / total < 0.3 && "text-mti-rose",
|
||||
);
|
||||
|
||||
const triggerDownload = async () => {
|
||||
try {
|
||||
setDownloadingPdf((prev) => ({...prev, [session]: true}));
|
||||
const res = await axios.post(`/api/stats/${session}/export`);
|
||||
toast.success("Report ready!");
|
||||
const link = document.createElement("a");
|
||||
link.href = res.data;
|
||||
// download should have worked but there are some CORS issues
|
||||
// https://firebase.google.com/docs/storage/web/download-files#cors_configuration
|
||||
// link.download="report.pdf";
|
||||
link.target = '_blank';
|
||||
link.rel="noreferrer"
|
||||
link.click();
|
||||
setDownloadingPdf((prev) => ({...prev, [session]: false}));
|
||||
} catch(err) {
|
||||
toast.error("Failed to display the report!");
|
||||
console.error(err);
|
||||
setDownloadingPdf((prev) => ({...prev, [session]: false}));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
const content = (
|
||||
<>
|
||||
<div className="w-full flex justify-between -md:items-center 2xl:items-center">
|
||||
@@ -248,32 +220,7 @@ export default function History({user}: {user: User}) {
|
||||
Level{" "}
|
||||
{(aggregatedLevels.reduce((accumulator, current) => accumulator + current.level, 0) / aggregatedLevels.length).toFixed(1)}
|
||||
</span>
|
||||
{/*<a
|
||||
href="https://firebasestorage.googleapis.com/v0/b/mti-ielts.appspot.com/o/exam_report%2F1704838712225.pdf?alt=media&token=0df9a50a-05a9-40a8-ba7c-4ff10ac5f3c8"
|
||||
//download="report.pdf"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
<BsFilePdf
|
||||
className={`${textColor} text-2xl cursor-pointer`}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
triggerDownload();
|
||||
}}
|
||||
/>
|
||||
</a>*/}
|
||||
{downloadingPdf[session] ?
|
||||
<span className={`${textColor} loading loading-infinity w-6`} /> :
|
||||
(
|
||||
<BsFilePdf
|
||||
className={`${textColor} text-2xl cursor-pointer`}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
triggerDownload();
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}
|
||||
{renderPdfIcon(session, textColor, textColor)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user