diff --git a/src/components/Solutions/Speaking.tsx b/src/components/Solutions/Speaking.tsx index d498c5c1..17248e5f 100644 --- a/src/components/Solutions/Speaking.tsx +++ b/src/components/Solutions/Speaking.tsx @@ -20,6 +20,9 @@ export default function Speaking({id, type, title, video_url, text, prompts, use useEffect(() => { if (userSolutions && userSolutions.length > 0 && userSolutions[0].solution) { + const solution = userSolutions[0].solution; + + if (solution.startsWith("https://")) return setSolutionURL(solution); axios.post(`/api/speaking`, {path: userSolutions[0].solution}, {responseType: "arraybuffer"}).then(({data}) => { const blob = new Blob([data], {type: "audio/wav"}); const url = URL.createObjectURL(blob); diff --git a/src/pages/(exam)/ExamPage.tsx b/src/pages/(exam)/ExamPage.tsx index ed6253f5..e52cc51d 100644 --- a/src/pages/(exam)/ExamPage.tsx +++ b/src/pages/(exam)/ExamPage.tsx @@ -266,7 +266,7 @@ export default function ExamPage({page}: Props) { return Object.assign(exam, {exercises}); }; - const onFinish = (solutions: UserSolution[]) => { + const onFinish = async (solutions: UserSolution[]) => { const solutionIds = solutions.map((x) => x.exercise); const solutionExams = solutions.map((x) => x.exam); @@ -276,7 +276,7 @@ export default function ExamPage({page}: Props) { setHasBeenUploaded(true); setIsEvaluationLoading(true); - Promise.all( + await Promise.all( exam.exercises.map(async (exercise) => { const evaluationID = uuidv4(); if (exercise.type === "writing") @@ -288,7 +288,7 @@ export default function ExamPage({page}: Props) { ) .then((responses) => { setStatsAwaitingEvaluation((prev) => [...prev, ...responses.filter((x) => !!x).map((r) => (r as any).id)]); - setUserSolutions([...userSolutions, ...responses.filter((x) => !!x)] as any); + setUserSolutions([...userSolutions.filter((x) => !solutionIds.includes(x.exercise)), ...responses.filter((x) => !!x)] as any); }) .finally(() => { setHasBeenUploaded(false); @@ -297,7 +297,8 @@ export default function ExamPage({page}: Props) { axios.get("/api/stats/update"); - setUserSolutions([...userSolutions.filter((x) => !solutionIds.includes(x.exercise)), ...solutions]); + if (exam && exam.module !== "writing" && exam.module !== "speaking") + setUserSolutions([...userSolutions.filter((x) => !solutionIds.includes(x.exercise)), ...solutions]); setModuleIndex(moduleIndex + 1); setPartIndex(-1); diff --git a/src/pages/api/evaluate/speaking.ts b/src/pages/api/evaluate/speaking.ts index 81842e45..fed39170 100644 --- a/src/pages/api/evaluate/speaking.ts +++ b/src/pages/api/evaluate/speaking.ts @@ -4,7 +4,7 @@ import {withIronSessionApiRoute} from "iron-session/next"; import {sessionOptions} from "@/lib/session"; import axios, {AxiosResponse} from "axios"; import formidable from "formidable-serverless"; -import {ref, uploadBytes} from "firebase/storage"; +import {getDownloadURL, ref, uploadBytes} from "firebase/storage"; import fs from "fs"; import {app, storage} from "@/firebase"; import {doc, getDoc, getFirestore, setDoc} from "firebase/firestore"; @@ -25,16 +25,17 @@ async function handler(req: NextApiRequest, res: NextApiResponse) { if (err) console.log(err); const audioFile = files.audio; - const audioFileRef = ref(storage, `speaking_recordings/${(audioFile as any).path.replace("upload_", "")}`); + const audioFileRef = ref(storage, `speaking_recordings/${fields.id}.wav`); const binary = fs.readFileSync((audioFile as any).path).buffer; const snapshot = await uploadBytes(audioFileRef, binary); + const url = await getDownloadURL(snapshot.ref); + const path = snapshot.metadata.fullPath; res.status(200).json(null); console.log("🌱 - Still processing"); - const backendRequest = await evaluate({answers: [{question: fields.question, answer: snapshot.metadata.fullPath}]}); - fs.rmSync((audioFile as any).path); + const backendRequest = await evaluate({answers: [{question: fields.question, answer: path}]}); console.log("🌱 - Process complete"); const correspondingStat = (await getDoc(doc(db, "stats", fields.id))).data() as Stat; @@ -42,7 +43,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) { const solutions = correspondingStat.solutions.map((x) => ({ ...x, evaluation: backendRequest.data, - solution: snapshot.metadata.fullPath, + solution: url, })); await setDoc(