This commit is contained in:
Gaspard Jankowiak 2026-06-06 20:45:13 +02:00 committed by gapato
commit 7d6f504dc5

View file

@ -55,9 +55,9 @@ async function downloadApplicantFilesWithProgress(applicantDetails, token, onPro
throw `Failed to download file ${afile.file_id} for applicant ${applicantDetails.id}` throw `Failed to download file ${afile.file_id} for applicant ${applicantDetails.id}`
} }
afile.blob = await response.blob() afile.bytes = await response.bytes()
completedDownloads += 1 completedDownloads += 1
downloadedBytes += afile.blob.size downloadedBytes += afile.bytes.length
onProgress({ downloaded: completedDownloads, total: files.length, bytes: downloadedBytes }) onProgress({ downloaded: completedDownloads, total: files.length, bytes: downloadedBytes })
})) }))
@ -120,7 +120,7 @@ async function getApplicants() {
return { return {
aid, aid,
token, token,
applicants: jsonData applicants: jsonData//.slice(0, 5)
} }
// return { aid, token, applicants: jsonData } // return { aid, token, applicants: jsonData }
}) })
@ -253,7 +253,7 @@ function createApplicantsCsv(applicantDetailsList) {
rows.push(values.join(",")) rows.push(values.join(","))
}) })
return rows.join("\n") return fflate.strToU8(rows.join("\n"))
} }
// Copy the standalone viewer HTML into the generated archive. // Copy the standalone viewer HTML into the generated archive.
@ -264,7 +264,7 @@ async function getArchiveViewerHtmlSource() {
throw new Error("Failed to load archive viewer HTML") throw new Error("Failed to load archive viewer HTML")
} }
return response.text() return response.bytes()
} }
// Bundle the viewer's fflate runtime so the exported archive can be browsed offline. // Bundle the viewer's fflate runtime so the exported archive can be browsed offline.
@ -275,7 +275,7 @@ async function getArchiveViewerFflateSource() {
throw new Error("Failed to load archive viewer dependency") throw new Error("Failed to load archive viewer dependency")
} }
return response.text() return response.bytes()
} }
function getFflate() { function getFflate() {
@ -286,37 +286,12 @@ function getFflate() {
return fflate return fflate
} }
async function createZipBlob(entries, onProgress = () => { }) { async function createZipBlob(archiveEntries) {
const { strToU8, zip } = getFflate()
const archiveEntries = {}
let processedEntries = 0
for (const entry of entries) { console.log(archiveEntries)
if (entry.data instanceof Blob) {
archiveEntries[entry.path] = new Uint8Array(await entry.data.arrayBuffer())
} else if (entry.data instanceof Uint8Array) {
archiveEntries[entry.path] = entry.data
} else {
archiveEntries[entry.path] = strToU8(String(entry.data ?? ""))
}
entry.data = null return new Promise((resolve, reject) => {
processedEntries += 1 fflate.zip(archiveEntries, { level: 0, consume: true }, (error, data) => {
onProgress({
phase: "preparing",
processedEntries,
totalEntries: entries.length
})
}
onProgress({
phase: "generating",
processedEntries,
totalEntries: entries.length
})
const archiveBytes = await new Promise((resolve, reject) => {
zip(archiveEntries, { level: 0, consume: true }, (error, data) => {
if (error != null) { if (error != null) {
reject(error) reject(error)
return return
@ -324,9 +299,12 @@ async function createZipBlob(entries, onProgress = () => { }) {
resolve(data) resolve(data)
}) })
// resolve(fflate.zipSync(archiveEntries, { level: 0, consume: true }))
}) })
.then((archiveBytes) => {
console.log("producing blob")
return new Blob([archiveBytes], { type: "application/zip" }) return new Blob([archiveBytes], { type: "application/zip" })
})
} }
function downloadBlob(blob, fileName) { function downloadBlob(blob, fileName) {
@ -515,8 +493,8 @@ function rip(event) {
console.log("Preparing zip archive...") console.log("Preparing zip archive...")
progressDialog.setStatus("Preparing zip archive...") progressDialog.setStatus("Preparing zip archive...")
const archiveEntries = []
const successfulApplicants = [] const successfulApplicants = []
const archiveEntries = {}
applicantDetailsResults.forEach((result) => { applicantDetailsResults.forEach((result) => {
if (result.status !== "fulfilled") { if (result.status !== "fulfilled") {
@ -530,10 +508,7 @@ function rip(event) {
archiveFiles.forEach((archiveFile, index) => { archiveFiles.forEach((archiveFile, index) => {
const afile = applicantDetails.application_files[index] const afile = applicantDetails.application_files[index]
archiveEntries.push({ archiveEntries[archiveFile.relativePath] = afile.bytes
path: archiveFile.relativePath,
data: afile.blob
})
}) })
}) })
@ -542,41 +517,25 @@ function rip(event) {
getArchiveViewerFflateSource() getArchiveViewerFflateSource()
]) ])
console.log("Creating applicants.csv") console.log("Creating applications.csv")
archiveEntries.push({ archiveEntries["applications.csv"] = createApplicantsCsv(successfulApplicants)
path: "applicants.csv",
data: createApplicantsCsv(successfulApplicants)
})
console.log("Creating index.html") console.log("Creating index.html")
archiveEntries.push({ archiveEntries["viewer.html"] = viewerHtmlSource
path: "viewer.html",
data: viewerHtmlSource
})
console.log("Adding viewer Javascript to archive") console.log("Adding viewer Javascript to archive")
archiveEntries.push({ archiveEntries["fflate.min.js"] = viewerFflateSource
path: "fflate.min.js",
data: viewerFflateSource
})
console.log("Generating zip archive...") console.log("Generating zip archive...")
const zipBlob = await createZipBlob(archiveEntries, ({ phase, processedEntries, totalEntries }) => { createZipBlob(archiveEntries)
if (phase === "preparing") { .then((zipBlob) => {
if (processedEntries === totalEntries || processedEntries === 1 || processedEntries % 10 === 0) {
progressDialog.setStatus(`Preparing zip archive (${processedEntries}/${totalEntries})...`)
}
return
}
progressDialog.setStatus("Generating zip archive in background... Firefox should stay responsive.")
})
console.log("Zip archive is ready.") console.log("Zip archive is ready.")
progressDialog.setStatus("Download ready.") progressDialog.setStatus("Download ready.")
downloadBlob(zipBlob, `applications_${aid}.zip`) downloadBlob(zipBlob, `procedure_${aid}.zip`)
btn.textContent = "done" btn.textContent = "done"
}) })
})
.catch((error) => { .catch((error) => {
console.error(error) console.error(error)
progressDialog.setStatus(`Failed: ${error}`) progressDialog.setStatus(`Failed: ${error}`)