This commit is contained in:
Hartmut Bauer committed 2026-10-11 23:51:14 +02:00
1 parent b6c68f5045
commit 6ab9a59597
7 files changed
+113 -65

No files matched your search

+2 -2
View File
@@ -1,3 +1,3 @@
#auto generated #auto generated
#Sun Oct 11 01:02:04 CEST 2026 #Sun Oct 11 23:49:03 CEST 2026
build.number=551 build.number=582
+6 -6
View File
@@ -4,13 +4,13 @@ import net.keinekekse.version.Version
object VERSION: Version { object VERSION: Version {
override val version = "0.2.0-alpha" override val version = "0.2.0-alpha"
override val fullVersion = "0.2.0-alpha+build.551" override val fullVersion = "0.2.0-alpha+build.582"
override val major = 0 override val major = 0
override val minor = 2 override val minor = 2
override val patch = 0 override val patch = 0
override val preRelease = "alpha" override val preRelease = "alpha"
override val buildMetadata = "build.551" override val buildMetadata = "build.582"
override val buildDate = "2026-10-10T23:02:04.857293Z" override val buildDate = "2026-10-11T21:49:03.887757Z"
override val displayName = "Application Server" override val displayName = "Application Server"
override val copyright = "Copyright (c) 2026 Hartmut Bauer" override val copyright = "Copyright (c) 2026 Hartmut Bauer"
override val name = "server" override val name = "server"
@@ -18,13 +18,13 @@ object VERSION: Version {
} }
object VERSION_books: Version { object VERSION_books: Version {
override val version = "0.2.0-alpha" override val version = "0.2.0-alpha"
override val fullVersion = "0.2.0-alpha+build.551" override val fullVersion = "0.2.0-alpha+build.582"
override val major = 0 override val major = 0
override val minor = 2 override val minor = 2
override val patch = 0 override val patch = 0
override val preRelease = "alpha" override val preRelease = "alpha"
override val buildMetadata = "build.551" override val buildMetadata = "build.582"
override val buildDate = "2026-10-10T23:02:04.857387Z" override val buildDate = "2026-10-11T21:49:03.887855Z"
override val displayName = "Books-DB" override val displayName = "Books-DB"
override val copyright = "Copyright (c) 2026 Hartmut Bauer" override val copyright = "Copyright (c) 2026 Hartmut Bauer"
override val name = "books" override val name = "books"
@@ -110,9 +110,9 @@ fun Application.configureRouting(
} }
hx.post(navBooksEdit.second) { hx.post(navBooksEdit.second) {
call.application.log.info("Edit book form OK") call.application.log.info("## Edit book form OK")
call.receiveParameters().forEach { param: String, value: List<String> -> call.receiveParameters().forEach { param: String, value: List<String> ->
call.application.log.info("param: $param, value: $value") call.application.log.info("## param: $param, value: $value")
} }
call.respondHtmlPartial(HttpStatusCode.OK) { call.respondHtmlPartial(HttpStatusCode.OK) {
+81 -39
View File
@@ -22,7 +22,6 @@ fun FlowContent.bookEdit(book: Book, booksRepo: BookRepository) {
booksRepo.allTags() booksRepo.allTags()
} }
var tabCount = 1
div(classes = "flex flex-col m-8") { div(classes = "flex flex-col m-8") {
form { form {
attributes.hx { attributes.hx {
@@ -30,6 +29,9 @@ fun FlowContent.bookEdit(book: Book, booksRepo: BookRepository) {
target = "#response" target = "#response"
swap = "innerHTML" swap = "innerHTML"
} }
input(type = InputType.hidden, name = "bookId") {
value = book.id.toString()
}
div(classes = "flex flex-row mb-5 h-9") { div(classes = "flex flex-row mb-5 h-9") {
div(classes = "w-30 content-center") { div(classes = "w-30 content-center") {
@@ -37,7 +39,7 @@ fun FlowContent.bookEdit(book: Book, booksRepo: BookRepository) {
} }
select(classes = "$cssTextInput w-40") { select(classes = "$cssTextInput w-40") {
name = "type" name = "type"
tabIndex = tabCount++.toString() autoFocus = true
for (type in BookType.entries) { for (type in BookType.entries) {
option { option {
@@ -55,7 +57,6 @@ fun FlowContent.bookEdit(book: Book, booksRepo: BookRepository) {
} }
input(classes = "$cssTextInput w-150") { input(classes = "$cssTextInput w-150") {
name = "title" name = "title"
tabIndex = tabCount++.toString()
value = book.title value = book.title
} }
@@ -66,7 +67,6 @@ fun FlowContent.bookEdit(book: Book, booksRepo: BookRepository) {
} }
input(classes = "$cssTextInput w-150") { input(classes = "$cssTextInput w-150") {
name = "originaltitle" name = "originaltitle"
tabIndex = tabCount++.toString()
value = book.originalTitle ?: "" value = book.originalTitle ?: ""
} }
@@ -77,7 +77,6 @@ fun FlowContent.bookEdit(book: Book, booksRepo: BookRepository) {
} }
input(classes = "$cssTextInput w-150") { input(classes = "$cssTextInput w-150") {
name = "subtitle" name = "subtitle"
tabIndex = tabCount++.toString()
value = book.subTitle ?: "" value = book.subTitle ?: ""
} }
} }
@@ -87,7 +86,6 @@ fun FlowContent.bookEdit(book: Book, booksRepo: BookRepository) {
} }
select(classes = "$cssTextInput w-16") { select(classes = "$cssTextInput w-16") {
name = "language" name = "language"
tabIndex = tabCount++.toString()
for (language in Languages.entries) { for (language in Languages.entries) {
option { option {
@@ -104,7 +102,6 @@ fun FlowContent.bookEdit(book: Book, booksRepo: BookRepository) {
} }
input(classes = "$cssTextInput w-16") { input(classes = "$cssTextInput w-16") {
name = "year" name = "year"
tabIndex = tabCount++.toString()
value = book.year.toString() value = book.year.toString()
} }
@@ -113,7 +110,6 @@ fun FlowContent.bookEdit(book: Book, booksRepo: BookRepository) {
} }
input(classes = "$cssTextInput w-16") { input(classes = "$cssTextInput w-16") {
name = "originalyear" name = "originalyear"
tabIndex = tabCount++.toString()
value = book.originalYear?.toString() ?: "" value = book.originalYear?.toString() ?: ""
} }
@@ -124,7 +120,6 @@ fun FlowContent.bookEdit(book: Book, booksRepo: BookRepository) {
} }
input(classes = "$cssTextInput w-40") { input(classes = "$cssTextInput w-40") {
name = "isbn" name = "isbn"
tabIndex = tabCount++.toString()
value = book.isbn value = book.isbn
} }
@@ -133,7 +128,6 @@ fun FlowContent.bookEdit(book: Book, booksRepo: BookRepository) {
} }
select(classes = "$cssTextInput w-74") { select(classes = "$cssTextInput w-74") {
name = "publisher" name = "publisher"
tabIndex = tabCount++.toString()
option { option {
value = "0" value = "0"
@@ -141,16 +135,20 @@ fun FlowContent.bookEdit(book: Book, booksRepo: BookRepository) {
} }
for (pub in publishers) { for (pub in publishers) {
option { option {
if (pub == book.publisher) if (pub.id == book.publisher.id)
selected = true selected = true
value = pub.id.toString() value = pub.id.toString()
+pub.name +pub.name
} }
} }
} }
a(classes = cssFormIcon) { button(classes = cssFormIcon) {
tabIndex = tabCount++.toString()
title = "Verlag hinzufügen" title = "Verlag hinzufügen"
// TODO
onClick = "document.getElementById('publisherDialog').showModal()"
// attributes["command"] = "show-modal"
// attributes["commandfor"] = "publisherDialog" //id
materialSymbolFormButton("add_box") materialSymbolFormButton("add_box")
} }
@@ -162,7 +160,6 @@ fun FlowContent.bookEdit(book: Book, booksRepo: BookRepository) {
} }
select(classes = "$cssTextInput w-98") { select(classes = "$cssTextInput w-98") {
name = "series" name = "series"
tabIndex = tabCount++.toString()
option { option {
value = "0" value = "0"
@@ -170,15 +167,14 @@ fun FlowContent.bookEdit(book: Book, booksRepo: BookRepository) {
} }
for (serie in series) { for (serie in series) {
option { option {
if (serie == book.series) if (book.series != null && serie.id == book.series.id)
selected = true selected = true
value = serie.id.toString() value = serie.id.toString()
+serie.name +serie.name
} }
} }
} }
a(classes = cssFormIcon) { button(classes = cssFormIcon) {
tabIndex = tabCount++.toString()
title = "Serie hinzufügen" title = "Serie hinzufügen"
materialSymbolFormButton("add_box") materialSymbolFormButton("add_box")
} }
@@ -188,24 +184,23 @@ fun FlowContent.bookEdit(book: Book, booksRepo: BookRepository) {
} }
input(classes = "$cssTextInput w-16") { input(classes = "$cssTextInput w-16") {
name = "seriesindex" name = "seriesindex"
tabIndex = tabCount++.toString()
value = book.seriesIndex?.toString() ?: "" value = book.seriesIndex?.toString() ?: ""
} }
} }
div(classes = "flex flex-row mb-5") { div(classes = "flex flex-row mb-7") {
div(classes = "w-30 content-center") { div(classes = "w-30 content-center") {
+"Künstler" +"Künstler"
} }
div(classes = "overflow-auto px-1 pb-1 h-40") { div(classes = "overflow-auto px-1 pb-1 h-40") {
tabIndex = "-1" // overflow setzt sonst einen Tabstopp
table { table {
thead(classes = "$cssFixedTHead ") { thead(classes = "$cssFixedTHead ") {
tr { tr {
th(classes = "py-3 px-2") { +"Name" } th(classes = "py-3 px-2") { +"Name" }
th(classes = "py-3 px-2") { +"Rolle" } th(classes = "py-3 px-2") { +"Rolle" }
th(classes = "py-3 px-2") { th(classes = "py-3 px-2") {
a(classes = cssFormIcon) { button(classes = cssFormIcon) {
tabIndex = tabCount++.toString()
title = "Künstler hinzufügen" title = "Künstler hinzufügen"
materialSymbolFormButton("add_box") materialSymbolFormButton("add_box")
} }
@@ -223,41 +218,88 @@ fun FlowContent.bookEdit(book: Book, booksRepo: BookRepository) {
+role.role +role.role
} }
td(classes = "border-t-1 $borderTable px-2 py-1") { td(classes = "border-t-1 $borderTable px-2 py-1") {
a(classes = cssFormIcon) { button(classes = cssFormIcon) {
tabIndex = tabCount++.toString()
// href = "${navBooksEdit.second}/${book.id}" // href = "${navBooksEdit.second}/${book.id}"
materialSymbolFormButton("Edit") materialSymbolFormButton("Edit")
} }
a(classes = cssFormIcon) { button(classes = cssFormIcon) {
tabIndex = tabCount++.toString()
materialSymbolFormButton("Delete") materialSymbolFormButton("Delete")
} }
} }
} }
} }
} }
}
}
div(classes = "ml-10 pr-8 content-center") {
+"Tags"
}
div(classes = "overflow-auto px-1 pb-1 h-40") {
tabIndex = "-1" // overflow setzt sonst einen Tabstopp
table {
thead(classes = "$cssFixedTHead ") {
tr {
th(classes = "py-3 px-2") { +"Tag" }
th(classes = "py-3 px-2") {
button(classes = cssFormIcon) {
title = "Tag hinzufügen"
materialSymbolFormButton("add_box")
}
}
}
}
tbody {
for (tag in book.tags) {
tr {
td(classes = "border-t-1 $borderTable px-2 py-1") {
+tag.tag
}
td(classes = "border-t-1 $borderTable px-2 py-1") {
button(classes = cssFormIcon) {
materialSymbolFormButton("Delete")
}
}
}
}
}
}
} }
} }
// artists tags div(classes = "flex flex-row mb-5") {
// | | | | div(classes = "w-30 content-center") {
// | | | | +"Kommentar"
} }
textArea(classes = "$cssTextInput w-150 h-18 resize-none") {
div(classes = "flex flex-row mb-5 h-9") { name = "comment"
// evtl. switch spellCheck = true
+book.comments
}
}
// TODO parent
// evtl. switch oder <detail>
// Teil von Sammelband _____v / enthält (-> Link) // Teil von Sammelband _____v / enthält (-> Link)
// comment
div(classes = "flex flex-row mb-5 mr-2 justify-end") {
button(classes = "$cssButtonStd block mt-8 mr-10") {
type = ButtonType.button
onClick =
"window.history.back()"
+"Abbrechen"
}
button(classes = "$cssButtonPri block mt-8") {
type = ButtonType.submit
+"Speichern"
}
}
} }
// TODO
button(classes = "$cssButtonPri block mt-8") { dialog {
tabIndex = tabCount++.toString() id = "publisherDialog"
type = ButtonType.submit attributes["closedby"] = "any"
+"Save" div {
+"Test-Verlag"
} }
} }
div { div {
@@ -51,7 +51,6 @@ fun HTML.booksPage(title: String, breadcrumbs: Map<String, String>, block: DIV.(
programName() programName()
div(classes = "ml-10 flex self-end pr-5 pt-2 border-t-1 items-baseline") { div(classes = "ml-10 flex self-end pr-5 pt-2 border-t-1 items-baseline") {
a(classes = cssHeaderLink) { a(classes = cssHeaderLink) {
tabIndex = "0"
href = "/" href = "/"
materialSymbol("home") materialSymbol("home")
// +"Start" // +"Start"
@@ -61,7 +60,6 @@ fun HTML.booksPage(title: String, breadcrumbs: Map<String, String>, block: DIV.(
breadcrumbs.forEach { (name, url) -> breadcrumbs.forEach { (name, url) ->
if (url.isNotEmpty()) { if (url.isNotEmpty()) {
a(classes = cssHeaderLink) { a(classes = cssHeaderLink) {
tabIndex = "0"
href = url href = url
+name +name
} }
@@ -16,11 +16,28 @@ fun HTML.importEditPage(bookInfo: CalibreBookInfo?, booksRepo: BookRepository) {
navBooksScanEdit.first, navBooksScanEdit.first,
mapOf(navBooks, navBooksNew, Pair(navBooksScanEdit.first, "")) mapOf(navBooks, navBooksNew, Pair(navBooksScanEdit.first, ""))
) { ) {
div(classes = "flex flex-col flex-auto") { div(classes = "flex flex-row flex-auto") {
div(classes = "flex flex-row h-60 m-8 w-3/4") {
img(classes = "inline-block h-60 pr-6 ") { bookEdit(
Book(
title = bookInfo?.title ?: "",
year = bookInfo?.published ?: 0,
isbn = bookInfo?.isbn ?: "",
publisher = Publisher(0, ""),
language = bookInfo?.language ?: Languages.DE
), booksRepo
)
div(classes = "flex flex-col m-8 ") {
div(classes = "text-2xl mx-8") {
+"Daten aus ISBN-Import"
}
div(classes = "flex flex-row h-60 m-8 w-7/8") {
if (dataUrl.isNotEmpty()) {
img(classes = "inline-block h-60 pr-8") {
src = dataUrl src = dataUrl
} }
}
div { div {
div { div {
span(classes = "inline-block w-25 ") { +"ISBN: " } span(classes = "inline-block w-25 ") { +"ISBN: " }
@@ -57,16 +74,7 @@ fun HTML.importEditPage(bookInfo: CalibreBookInfo?, booksRepo: BookRepository) {
} }
} }
}
bookEdit(
Book(
title = bookInfo?.title ?: "",
year = bookInfo?.published ?: 0,
isbn = bookInfo?.isbn ?: "",
publisher = Publisher(0, ""),
language = bookInfo?.language ?: Languages.DE
), booksRepo
)
} }
} }
} }
@@ -150,7 +150,7 @@ suspend fun Application.configureSecurity() {
call.application.log.info("#### exit refresh (!?)") call.application.log.info("#### exit refresh (!?)")
return@Custom null return@Custom null
} }
val stale = expiresAt != null && expiresAt <= now + 1.minutes val stale = expiresAt != null && expiresAt <= now + 5.minutes
val refreshToken = token.refreshToken val refreshToken = token.refreshToken
if (stale && refreshToken != null) { if (stale && refreshToken != null) {
call.application.log.info("#### Refreshing token with refresh token") call.application.log.info("#### Refreshing token with refresh token")