diff --git a/UI/app/components/BooksList.js b/UI/app/components/BooksList.js index ca0e591..09737ff 100644 --- a/UI/app/components/BooksList.js +++ b/UI/app/components/BooksList.js @@ -38,7 +38,7 @@ const BooksList = ({ setFiles, jsonFiles, projectName, - licenseData + licenseData, }) => { const [books, setBooks] = useState([]); const [bookData, setBookData] = useState(null); @@ -229,7 +229,6 @@ const BooksList = ({ // Resolve book updates and update states const resolvedBookUpdates = await Promise.all(bookUpdates); - // Update chapter statuses setChapterStatuses(statuses); @@ -885,7 +884,7 @@ const BooksList = ({ {inProgressVerse[ `${selectedBook}-${verse.chapterNumber}-${verse.verseNumber}` ] ? ( - + ) : verse?.generatedAudio ? ( playingAudio?.key === `${selectedBook}-${verse.chapterNumber}-${verse.verseNumber}` ? ( @@ -910,7 +909,13 @@ const BooksList = ({ /> ) ) : ( - + )} @@ -988,7 +993,15 @@ const BooksList = ({ > Reset Project - + ); diff --git a/UI/app/components/DownloadProject.js b/UI/app/components/DownloadProject.js index 947e913..e579b38 100644 --- a/UI/app/components/DownloadProject.js +++ b/UI/app/components/DownloadProject.js @@ -1,3 +1,4 @@ +import { useState, useEffect } from "react"; import { Button } from "@mui/material"; import { styles } from "../StyledComponents"; import JSZip from "jszip"; @@ -7,12 +8,81 @@ import Swal from "sweetalert2"; const DownloadProject = ({ projectName, projectInstance, + books, jsonFiles, licenseData, + isConverting, + isTranscribing, }) => { + const [isDownloadReady, setIsDownloadReady] = useState(false); + + useEffect(() => { + const validateBooksCompletion = async () => { + try { + const keys = await projectInstance.keys(); + const fetchedData = ( + await Promise.all(keys.map((key) => projectInstance.getItem(key))) + ).filter((data) => data !== null); + + const bookDataMap = {}; + fetchedData.forEach((data) => { + if (!data.book) return; + if (!bookDataMap[data.book]) { + bookDataMap[data.book] = []; + } + bookDataMap[data.book].push(data); + }); + + const areBooksDownloadable = books.map((book) => { + const records = bookDataMap[book.name] || []; + + const chaptersStatus = book.displayChapters.map((chapter) => { + const chapterRecords = records.filter( + (record) => record.chapter === chapter.chapterNumber + ); + + const totalVersesInChapter = chapter.verses.length; + const completedVerses = chapterRecords.filter( + (record) => record.transcribedText && record.generatedAudio + ).length; + const approvedVerses = chapterRecords.filter( + (record) => + record.transcribedText && + record.generatedAudio && + record.isApproved + ).length; + + return { + chapterNumber: chapter.chapterNumber, + isConvertible: completedVerses === totalVersesInChapter, + isApproved: approvedVerses === totalVersesInChapter, + }; + }); + + const isBookReady = chaptersStatus.some( + (status) => status.isConvertible || status.isApproved + ); + + return isBookReady; + }); + + setIsDownloadReady(areBooksDownloadable.some((ready) => ready)); + } catch (error) { + console.error("Error validating book completion:", error); + setIsDownloadReady(false); + } + }; + + if (books.length > 0) { + validateBooksCompletion(); + } else { + setIsDownloadReady(false); + } + }, [books, projectInstance]); + + const downloadProject = async () => { const zip = new JSZip(); - // const projectFolder = zip.folder(projectName); const textFolder = zip.folder("text-1"); const audioFolder = zip.folder("audio"); const audioIngredientsFolder = audioFolder?.folder("ingredients"); @@ -21,9 +91,6 @@ const DownloadProject = ({ let versification; let projectSetting; - console.log("json files", jsonFiles); - console.log("licenseData", licenseData); - if (licenseData) { textIngredientsFolder?.file("license.md", licenseData); audioIngredientsFolder?.file("license.md", licenseData); @@ -70,14 +137,9 @@ const DownloadProject = ({ await Promise.all(keys.map((key) => projectInstance.getItem(key))) ).filter((data) => data !== null); - console.log("fetched data from indexed db", fetchedData); - for (const data of fetchedData) { if (!data?.book) continue; - console.log("processing data for book:", data.book); - - // const bookTextFolder = textFolder?.folder(data.book); const usfmBookData = await processUSFM( projectInstance, data.book, @@ -101,8 +163,8 @@ const DownloadProject = ({ const bookAudioFolder = audioIngredientsFolder?.folder(data.book); const chapterFolder = bookAudioFolder?.folder(data.chapter); const audioBlob = await data.generatedAudio.arrayBuffer(); - const audioExtension = data.generatedAudio.name.split('.').pop(); - const audioFileName = `${data.chapter}_${data.verse}.${audioExtension}` + const audioExtension = data.generatedAudio.name.split(".").pop(); + const audioFileName = `${data.chapter}_${data.verse}.${audioExtension}`; chapterFolder?.file(audioFileName, audioBlob); } } @@ -134,6 +196,7 @@ const DownloadProject = ({ variant="contained" sx={styles.downloadButton} onClick={downloadProject} + disabled={!isDownloadReady || isConverting || isTranscribing} > Download Project diff --git a/UI/app/components/TextToAudioConversion.js b/UI/app/components/TextToAudioConversion.js index 28a8e3e..1bdcf6f 100644 --- a/UI/app/components/TextToAudioConversion.js +++ b/UI/app/components/TextToAudioConversion.js @@ -120,6 +120,7 @@ const TextToAudioConversion = ({ }; const updateBookStatus = (chapterNumber, status) => { + chapterNumber = parseInt(chapterNumber, 10); const bookChapterKey = `${selectedBook}-${chapterNumber}`; setChapterStatuses((prev) => ({ @@ -142,7 +143,7 @@ const TextToAudioConversion = ({ arrays.forEach((arr) => { updatedBook[arr] = - updatedBook[arr]?.filter((ch) => ch !== chapterNumber) || []; + updatedBook[arr]?.filter((ch) => parseInt(ch) !== chapterNumber) || []; }); if (status === "converting") { @@ -151,8 +152,10 @@ const TextToAudioConversion = ({ updatedBook.converted.push(chapterNumber); } else if (status === "Failed") { updatedBook.failed.push(chapterNumber); - // updatedBook.status = "Transcribed" } + const allChaptersConverted = + updatedBook.totalChapters === updatedBook.converted.length; + updatedBook.status = allChaptersConverted ? "Done" : updatedBook.status; return updatedBook; }) diff --git a/UI/app/components/useAudioTranscription.js b/UI/app/components/useAudioTranscription.js index d42be65..8b98223 100644 --- a/UI/app/components/useAudioTranscription.js +++ b/UI/app/components/useAudioTranscription.js @@ -27,6 +27,7 @@ const useAudioTranscription = ({ const updateBookStatus = useCallback( (chapterNumber, status) => { + chapterNumber = parseInt(chapterNumber, 10); const bookChapterKey = `${selectedBook}-${chapterNumber}`; setChapterStatuses((prev) => ({ @@ -48,7 +49,7 @@ const useAudioTranscription = ({ ]; arrays.forEach((arr) => { updatedBook[arr] = - updatedBook[arr]?.filter((ch) => ch !== chapterNumber) || []; + updatedBook[arr]?.filter((ch) => parseInt(ch) !== chapterNumber) || []; }); switch (status) { @@ -219,7 +220,7 @@ const useAudioTranscription = ({ setBooks((prevBooks) => prevBooks.map((book) => book.name === selectedBook - ? { ...book, status: "Transcribed", hasDownload: true } + ? { ...book, status: "Transcribed" } : book ) );