Changes new file upload target to "new document".

This commit is contained in:
Stefan Schallerl 2025-02-07 09:27:19 +01:00
parent caa63fdc71
commit 07c8758182
6 changed files with 131 additions and 73 deletions

View file

@ -95,3 +95,8 @@ enum class State(val code: Int) {
} }
} }
} }
/**
* Tuple for internal and external ID.
*/
data class IdPair(val id: Long, val extId: ExtId)

View file

@ -10,8 +10,6 @@ import java.time.format.FormatStyle
class LimboController(val modifiers: TemplateModifiers, val repository: SqliteRepository) { class LimboController(val modifiers: TemplateModifiers, val repository: SqliteRepository) {
private val dtf = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM, FormatStyle.SHORT)
fun formLimbo(ctx: Context) { fun formLimbo(ctx: Context) {
val session = ctx.requireSession() val session = ctx.requireSession()

View file

@ -12,24 +12,45 @@ class UploadController(val modifiers: TemplateModifiers, val repository: SqliteR
val accountid = session.id val accountid = session.id
val target = ctx.queryParam("target")
val files = ctx.uploadedFiles() val files = ctx.uploadedFiles()
files.forEach { when (target) {
println("filename: " + it.filename()) "document" -> {
println("ext: " + it.extension()) val extIds = files.map {
println("contentType: " + it.contentType()) // mime it.contentAndClose { content ->
println("size: " + it.size()) repository.addFileToLimbo(accountid, it.filename(), it.contentType(), it.size(), content).extId
}
}
ctx.status(200)
ctx.json(
Result(
files = files.size,
redirect = "/document/new?${extIds.joinToString("&") { "file_id=$it" }}"
)
)
}
"limbo" -> {
files.forEach {
it.contentAndClose { content -> it.contentAndClose { content ->
repository.addFileToLimbo(accountid, it.filename(), it.contentType(), it.size(), content) repository.addFileToLimbo(accountid, it.filename(), it.contentType(), it.size(), content)
} }
} }
ctx.status(200) ctx.status(200)
ctx.json(Result(files = files.size)) ctx.json(
Result(
files = files.size,
redirect = "/limbo"
)
)
}
}
} }
data class Result( data class Result(
val files: Int val files: Int,
val redirect: String
) )
} }

View file

@ -69,15 +69,51 @@ class SqliteRepository(url: String) {
) )
} }
fun addFileToLimbo(accountId: Long, filename: String, contentType: String?, size: Long, content: InputStream) { fun addFileToLimbo(
accountId: Long,
filename: String,
contentType: String?,
size: Long,
content: InputStream
): IdPair =
database.databaseQueries.transactionWithResult {
val extId = ExtId.generate()
database.databaseQueries.insertFileIntoLimbo( database.databaseQueries.insertFileIntoLimbo(
account_id = accountId, account_id = accountId,
ext_id = ExtId.generate(), ext_id = extId,
filename = filename, filename = filename,
content_type = contentType, content_type = contentType,
file_size = size, file_size = size,
content = content.readAllBytes() content = content.readAllBytes()
) )
IdPair(
id = lastInsertedId(),
extId = extId
)
}
fun addNewFileToDocument(
accountId: Long,
documentId: Long,
filename: String,
contentType: String?,
size: Long,
content: InputStream
) =
database.databaseQueries.transactionWithResult {
ExtId.generate().let { extId ->
database.databaseQueries.insertFileForDocument(
account_id = accountId,
document_id = documentId,
ext_id = extId,
filename = filename,
content_type = contentType,
file_size = size,
content = content.readAllBytes()
)
IdPair(id = lastInsertedId(), extId = extId)
}
} }
fun getLimboFileCount(accountId: Long, state: State = State.ACTIVE): Long { fun getLimboFileCount(accountId: Long, state: State = State.ACTIVE): Long {
@ -273,4 +309,6 @@ class SqliteRepository(url: String) {
fun setFileState(accountId: Long, extId: ExtId, state: State) { fun setFileState(accountId: Long, extId: ExtId, state: State) {
database.databaseQueries.setFileState(account_id = accountId, ext_id = extId, state = state) database.databaseQueries.setFileState(account_id = accountId, ext_id = extId, state = state)
} }
private fun lastInsertedId() = database.databaseQueries.getLastInsertRowId().executeAsOne()
} }

View file

@ -60,6 +60,9 @@ CREATE INDEX file_state_IDX ON file (state);
CREATE UNIQUE INDEX file_ext_id_IDX ON file (ext_id); CREATE UNIQUE INDEX file_ext_id_IDX ON file (ext_id);
--- ---
insertFileForDocument:
INSERT INTO file (account_id, document_id, ext_id, filename, content_type, file_size, content) VALUES (?, ?,?,?,?,?,?);
insertFileIntoLimbo: insertFileIntoLimbo:
INSERT INTO file (account_id, ext_id, filename, content_type, file_size, content) VALUES (?,?,?,?,?,?); INSERT INTO file (account_id, ext_id, filename, content_type, file_size, content) VALUES (?,?,?,?,?,?);

View file

@ -1,26 +1,19 @@
document.addEventListener("DOMContentLoaded", function () { document.addEventListener("DOMContentLoaded", function () {
console.log("filemure ready")
const dropzone = document.querySelector('html'); const dropzone = document.querySelector('html');
let progressDialog = document.querySelector('#upload_progress_dialog') let progressDialog = document.querySelector('#upload_progress_dialog')
let progressBar = document.querySelector('#upload_progress') let progressBar = document.querySelector('#upload_progress')
// window.addEventListener
// Prevent default behavior for drag-over and drop
dropzone.addEventListener('dragover', (e) => { dropzone.addEventListener('dragover', (e) => {
console.log("over")
e.preventDefault(); e.preventDefault();
dropzone.classList.add('dragactive'); dropzone.classList.add('dragactive');
}); });
dropzone.addEventListener('dragleave', (e) => { dropzone.addEventListener('dragleave', (e) => {
console.log("out")
dropzone.classList.remove('dragactive'); dropzone.classList.remove('dragactive');
}); });
dropzone.addEventListener('drop', (e) => { dropzone.addEventListener('drop', (e) => {
console.log("drop")
e.preventDefault(); e.preventDefault();
dropzone.classList.remove('dragactive'); dropzone.classList.remove('dragactive');
@ -29,44 +22,44 @@ document.addEventListener("DOMContentLoaded", function() {
if (files.length > 0) { if (files.length > 0) {
console.log('Files dropped:', files); console.log('Files dropped:', files);
// Process the files
for (const file of files) { for (const file of files) {
// show progress dialog
// warning: this way the progress dialog is shown for each file individually
progressDialog.showModal(); progressDialog.showModal();
console.log('File name:', file.name);
console.log('File size:', file.size, 'bytes');
console.log('File type:', file.type);
const formData = new FormData(); const formData = new FormData();
formData.append('file', file); formData.append('file', file);
const xhr = new XMLHttpRequest(); const xhr = new XMLHttpRequest();
xhr.upload.addEventListener("progress", (event) => { xhr.upload.addEventListener("progress", (event) => {
if (event.lengthComputable) { if (event.lengthComputable) {
console.log("upload progress:", event.loaded / event.total); // console.log("upload progress:", event.loaded / event.total);
progressBar.value = 100.0 * event.loaded / event.total; progressBar.value = 100.0 * event.loaded / event.total;
} }
}); });
xhr.addEventListener("progress", (event) => { xhr.addEventListener("progress", (event) => {
if (event.lengthComputable) { if (event.lengthComputable) {
console.log("download progress:", event.loaded / event.total); // console.log("download progress:", event.loaded / event.total);
progressBar.value = event.loaded / event.total; progressBar.value = event.loaded / event.total;
} }
}); });
xhr.addEventListener("loadend", () => { xhr.addEventListener("load", (event) => {
console.log(xhr.readyState, xhr.status) console.log(xhr.readyState, xhr.status)
progressDialog.close(); progressDialog.close();
let res = JSON.parse(xhr.response);
window.location = res.redirect;
}); });
xhr.open('POST', '/upload', false); xhr.addEventListener("error", event => {
progressDialog.close();
alert("An error occurred.")
});
xhr.addEventListener("abort", event => {
progressDialog.close();
alert("Upload has been cancelled.")
});
xhr.open('POST', '/upload?target=document', false);
xhr.send(formData); xhr.send(formData);
// fetch('/upload', {
// method: 'POST',
// body: formData,
// })
// .then(response => response.json())
// .then(data => console.log('Upload successful:', data))
// .catch(error => console.error('Upload failed:', error));
} }
} }
}); });