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) {
private val dtf = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM, FormatStyle.SHORT)
fun formLimbo(ctx: Context) {
val session = ctx.requireSession()

View file

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

View file

@ -69,16 +69,52 @@ class SqliteRepository(url: String) {
)
}
fun addFileToLimbo(accountId: Long, filename: String, contentType: String?, size: Long, content: InputStream) {
database.databaseQueries.insertFileIntoLimbo(
account_id = accountId,
ext_id = ExtId.generate(),
filename = filename,
content_type = contentType,
file_size = size,
content = content.readAllBytes()
)
}
fun addFileToLimbo(
accountId: Long,
filename: String,
contentType: String?,
size: Long,
content: InputStream
): IdPair =
database.databaseQueries.transactionWithResult {
val extId = ExtId.generate()
database.databaseQueries.insertFileIntoLimbo(
account_id = accountId,
ext_id = extId,
filename = filename,
content_type = contentType,
file_size = size,
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 {
return database.databaseQueries.getLimboFileCount(account_id = accountId, state = state)
@ -273,4 +309,6 @@ class SqliteRepository(url: String) {
fun setFileState(accountId: Long, extId: 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);
---
insertFileForDocument:
INSERT INTO file (account_id, document_id, ext_id, filename, content_type, file_size, content) VALUES (?, ?,?,?,?,?,?);
insertFileIntoLimbo:
INSERT INTO file (account_id, ext_id, filename, content_type, file_size, content) VALUES (?,?,?,?,?,?);

View file

@ -1,73 +1,66 @@
document.addEventListener("DOMContentLoaded", function() {
console.log("filemure ready")
document.addEventListener("DOMContentLoaded", function () {
const dropzone = document.querySelector('html');
let progressDialog = document.querySelector('#upload_progress_dialog')
let progressBar = document.querySelector('#upload_progress')
// window.addEventListener
// Prevent default behavior for drag-over and drop
dropzone.addEventListener('dragover', (e) => {
console.log("over")
e.preventDefault();
dropzone.classList.add('dragactive');
});
dropzone.addEventListener('dragleave', (e) => {
console.log("out")
dropzone.classList.remove('dragactive');
});
dropzone.addEventListener('drop', (e) => {
console.log("drop")
e.preventDefault();
dropzone.classList.remove('dragactive');
e.preventDefault();
dropzone.classList.remove('dragactive');
// Handle dropped files
const files = e.dataTransfer.files;
if (files.length > 0) {
console.log('Files dropped:', files);
// Handle dropped files
const files = e.dataTransfer.files;
if (files.length > 0) {
console.log('Files dropped:', files);
// Process the files
for (const file of files) {
progressDialog.showModal();
console.log('File name:', file.name);
console.log('File size:', file.size, 'bytes');
console.log('File type:', file.type);
for (const file of files) {
// show progress dialog
// warning: this way the progress dialog is shown for each file individually
progressDialog.showModal();
const formData = new FormData();
formData.append('file', file);
const formData = new FormData();
formData.append('file', file);
const xhr = new XMLHttpRequest();
xhr.upload.addEventListener("progress", (event) => {
if (event.lengthComputable) {
// console.log("upload progress:", event.loaded / event.total);
progressBar.value = 100.0 * event.loaded / event.total;
}
});
xhr.addEventListener("progress", (event) => {
if (event.lengthComputable) {
// console.log("download progress:", event.loaded / event.total);
progressBar.value = event.loaded / event.total;
}
});
xhr.addEventListener("load", (event) => {
console.log(xhr.readyState, xhr.status)
progressDialog.close();
let res = JSON.parse(xhr.response);
window.location = res.redirect;
});
const xhr = new XMLHttpRequest();
xhr.upload.addEventListener("progress", (event) => {
if (event.lengthComputable) {
console.log("upload progress:", event.loaded / event.total);
progressBar.value = 100.0 * event.loaded / event.total;
}
});
xhr.addEventListener("progress", (event) => {
if (event.lengthComputable) {
console.log("download progress:", event.loaded / event.total);
progressBar.value = event.loaded / event.total;
}
});
xhr.addEventListener("loadend", () => {
console.log(xhr.readyState, xhr.status)
progressDialog.close();
});
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', false);
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));
xhr.open('POST', '/upload?target=document', false);
xhr.send(formData);
}
}
}
});
});