filemure/app/src/main/kotlin/net/h34t/filemure/controller/DocumentController.kt

238 lines
No EOL
8.5 KiB
Kotlin

package net.h34t.filemure.controller
import io.javalin.http.BadRequestResponse
import io.javalin.http.Context
import io.javalin.http.ForbiddenResponse
import io.javalin.http.Header
import net.h34t.filemure.*
import net.h34t.filemure.repository.SqliteRepository
import net.h34t.filemure.tpl.*
import net.h34t.filemure.tpl.Document
import java.io.File
import java.time.LocalDateTime
class DocumentController(val modifiers: TemplateModifiers, val repository: SqliteRepository) {
fun documentDetail(ctx: Context) {
val session = ctx.requireSession()
val extId = ExtId(ctx.pathParam("extId"))
val document = repository.getDocumentByExtId(accountId = session.id, extId = extId, state = State.ACTIVE)
ctx.tempolin(
Frame(
modifiers = modifiers,
title = document.title,
target = "document-${document.extId}",
back = "/",
logout = true,
content = Document(
modifiers = modifiers,
extId = document.extId.value,
referenceDate = document.referenceDate.formatHumanLong(),
tags = { document.tags.map { TagsBlock(tag = it.value) }.asSequence() },
description = document.description.ifBlank { "-" },
files = FileList(
modifiers = modifiers,
delete = true,
files = {
document.files.map { file ->
FilesBlock(
extId = file.extId.value,
filename = file.filename,
contentType = file.contentType ?: "?",
size = formatHumanReadableSize(file.fileSize),
delete = true,
)
}.asSequence()
}),
)
)
)
}
fun createDocumentForm(ctx: Context) {
val session = ctx.requireSession()
val fileIds = ctx.queryParams("file_id").map { ExtId(it) }
val limboFiles = repository.getFilesInLimbo(session.id)
val limboFileIds = limboFiles.map { it.extId }
if (!fileIds.all { it in limboFileIds }) {
throw ForbiddenResponse("Mismatched file ids.")
}
val selectedFiles = limboFiles.filter { it.extId in fileIds }
val title = selectedFiles.firstOrNull()?.filename ?: "new document"
val referenceDates = selectedFiles.mapNotNull { DateGuesser.guess(it.filename) }
val referenceDate = referenceDates.firstOrNull()
?: LocalDateTime.now()
val tags = selectedFiles.map { File(it.filename).extension }.distinct().asSequence()
val description = ""
ctx.tempolin(
Frame(
modifiers = modifiers,
title = "new document",
// TODO enable target for new documents in form
target = "",
back = "/",
logout = true,
content = DocumentCreateForm(
modifiers = modifiers,
title = title,
referenceDate = referenceDate.formatHtmlForm(),
tags = { tags.map { TagsBlock(it) } },
description = description,
fileId = { selectedFiles.map { FileIdBlock(it.extId.value) }.asSequence() },
files = FileList(
modifiers = modifiers,
delete = true,
files = {
selectedFiles.map { file ->
FilesBlock(
extId = file.extId.value,
filename = file.filename,
contentType = file.contentType ?: "?",
size = formatHumanReadableSize(file.fileSize),
delete = true,
)
}.asSequence()
}),
)
)
)
}
fun createDocument(ctx: Context) {
val session = ctx.requireSession()
val title = ctx.formParam("title")
?: throw BadRequestResponse("")
val referenceDate = ctx.formParam("reference_date")?.let { LocalDateTime.parse(it, formDtf) }
?: throw BadRequestResponse("")
val tags = Tag.parse(ctx.formParam("tags"))
val description = ctx.formParam("description")
?: throw BadRequestResponse("")
val fileExtIds = ctx.formParams("file_id")
val extId =
repository.addDocument(
session.id,
title,
referenceDate,
tags,
description,
fileExtIds.map { ExtId(it) })
ctx.redirectPRG("/document/$extId")
}
fun downloadDocument(ctx: Context) {
// TODO pack all files in a zip
}
fun downloadFile(ctx: Context) {
val session = ctx.requireSession()
val extId = ctx.pathParam("extId")
val file = repository.loadFile(accountId = session.id, extId = ExtId(extId))
file.contentType?.also { ctx.header(Header.CONTENT_TYPE, it) }
ctx.result(file.content)
}
fun deleteFileAction(ctx: Context) {
val session = ctx.requireSession()
val extId = ExtId(ctx.pathParam("extId"))
val ret = ctx.queryParam("return")
repository.setFileState(session.id, extId = extId, state = State.ARCHIVED)
when (ret) {
"limbo" -> ctx.redirectPRG("/limbo")
else -> ctx.redirectPRG("/")
}
}
fun editDocumentForm(ctx: Context) {
val session = ctx.requireSession()
val extId = ctx.pathParam("extId")
val document = repository.getDocumentByExtId(accountId = session.id, extId = ExtId(extId), state = State.ACTIVE)
ctx.tempolin(
Frame(
modifiers = modifiers,
title = document.title,
target = "",
back = "/document/$extId",
logout = true,
content = DocumentEditForm(
modifiers = modifiers,
extId = extId,
title = document.title,
referenceDate = formDtf.format(document.referenceDate),
tags = {
document.tags.map { tag -> TagsBlock(tag = tag.value) }.asSequence()
},
description = document.description,
files = FileList(
modifiers = modifiers,
delete = true,
files = {
document.files.map { file ->
FilesBlock(
extId = file.extId.value,
filename = file.filename,
contentType = file.contentType ?: "?",
size = formatHumanReadableSize(file.fileSize),
delete = true,
)
}.asSequence()
}),
)
)
)
}
fun editDocumentAction(ctx: Context) {
val session = ctx.requireSession()
val extId = ctx.pathParam("extId")
val document = repository.getDocumentByExtId(
accountId = session.id,
extId = ExtId(extId),
state = State.ACTIVE
)
val title = ctx.formParam("title")
val referenceDate = ctx.formParam("reference_date")
val description = ctx.formParam("description") ?: ""
val tags = ctx.formParam("tags")
repository.updateDocument(
accountId = session.id,
id = document.id,
title = title ?: "",
referenceDate = LocalDateTime.parse(referenceDate ?: "", formDtf),
tags = TagAdapter.parse(tags),
description = description
)
ctx.redirectPRG("/document/$extId")
}
fun deleteDocumentAction(ctx: Context) {
val session = ctx.requireSession()
val extId = ExtId(ctx.pathParam("extId"))
repository.setDocumentState(accountId = session.id, extId = extId, State.DELETED)
ctx.redirectPRG("/")
}
}