From e08a941c625f3f4d9e6d0acf5c2b0ccbd3ea0e3c Mon Sep 17 00:00:00 2001 From: Hartmut Bauer Date: Mon, 19 Oct 2026 01:04:50 +0200 Subject: [PATCH] progress --- server/buildnumber.properties | 4 +- server/src/main/kotlin/Version.kt | 12 +-- .../src/main/kotlin/books/config/Routing.kt | 63 ++++++++++++-- .../main/kotlin/books/edit/BooksSession.kt | 41 ++++++++-- server/src/main/kotlin/books/ui/BookEdit.kt | 82 ++++++++++++------- .../src/main/kotlin/books/ui/BookEditPage.kt | 10 ++- server/src/main/kotlin/books/ui/BooksPage.kt | 2 +- .../src/main/kotlin/books/ui/BooksTemplate.kt | 4 +- server/src/main/kotlin/books/ui/Helpers.kt | 15 ++-- .../main/kotlin/books/ui/ImportEditPage.kt | 23 ++++-- server/src/main/kotlin/books/ui/ImportPage.kt | 2 +- server/src/main/kotlin/books/ui/TestPage.kt | 2 +- server/src/main/kotlin/core/auth/Sessions.kt | 41 ++++------ server/src/main/kotlin/core/ui/LandingPage.kt | 23 +++++- .../src/main/kotlin/core/ui/PageTemplate.kt | 2 +- 15 files changed, 223 insertions(+), 103 deletions(-) diff --git a/server/buildnumber.properties b/server/buildnumber.properties index 5ae9b2d..d307f4f 100644 --- a/server/buildnumber.properties +++ b/server/buildnumber.properties @@ -1,3 +1,3 @@ #auto generated -#Sun Oct 11 23:49:03 CEST 2026 -build.number=582 +#Mon Oct 19 00:45:22 CEST 2026 +build.number=633 diff --git a/server/src/main/kotlin/Version.kt b/server/src/main/kotlin/Version.kt index c9cc9b3..5394b59 100644 --- a/server/src/main/kotlin/Version.kt +++ b/server/src/main/kotlin/Version.kt @@ -4,13 +4,13 @@ import net.keinekekse.version.Version object VERSION: Version { override val version = "0.2.0-alpha" - override val fullVersion = "0.2.0-alpha+build.582" + override val fullVersion = "0.2.0-alpha+build.633" override val major = 0 override val minor = 2 override val patch = 0 override val preRelease = "alpha" - override val buildMetadata = "build.582" - override val buildDate = "2026-10-11T21:49:03.887757Z" + override val buildMetadata = "build.633" + override val buildDate = "2026-10-18T22:45:22.165046Z" override val displayName = "Application Server" override val copyright = "Copyright (c) 2026 Hartmut Bauer" override val name = "server" @@ -18,13 +18,13 @@ object VERSION: Version { } object VERSION_books: Version { override val version = "0.2.0-alpha" - override val fullVersion = "0.2.0-alpha+build.582" + override val fullVersion = "0.2.0-alpha+build.633" override val major = 0 override val minor = 2 override val patch = 0 override val preRelease = "alpha" - override val buildMetadata = "build.582" - override val buildDate = "2026-10-11T21:49:03.887855Z" + override val buildMetadata = "build.633" + override val buildDate = "2026-10-18T22:45:22.165140Z" override val displayName = "Books-DB" override val copyright = "Copyright (c) 2026 Hartmut Bauer" override val name = "books" diff --git a/server/src/main/kotlin/books/config/Routing.kt b/server/src/main/kotlin/books/config/Routing.kt index 740a510..ba17722 100644 --- a/server/src/main/kotlin/books/config/Routing.kt +++ b/server/src/main/kotlin/books/config/Routing.kt @@ -17,6 +17,8 @@ import kotlinx.html.span import net.keinekekse.app.books.db.BookRepository import net.keinekekse.app.books.db.CalibreBookInfoRepositoryImpl import net.keinekekse.app.books.db.schema.emptyBook +import net.keinekekse.app.books.edit.getSession +import net.keinekekse.app.books.edit.newSession import net.keinekekse.app.books.scan.getCover import net.keinekekse.app.books.scan.getIsbnFromCalibre import net.keinekekse.app.books.ui.* @@ -75,8 +77,9 @@ fun Application.configureRouting( get("${navBooksScanEdit.second}/{id}") { val id = call.parameters["id"]?.toInt() ?: 0 val bookInfo = CalibreBookInfoRepositoryImpl(db).readBookInfo(id) + val session = newSession(call.principal.userId, sessions) call.respondHtml { - importEditPage(bookInfo, booksRepo) + importEditPage(bookInfo, booksRepo, session) } } delete("${navBooksScanEdit.second}/{id}") { @@ -108,21 +111,71 @@ fun Application.configureRouting( get("${navBooksEdit.second}/{id}") { val id = call.parameters["id"]?.toInt() ?: 0 val book = booksRepo.bookById(id) ?: emptyBook() - call.respondHtml { bookEditPage(book, booksRepo) } + val session = newSession(call.principal.userId, sessions) + session.data.book = book + call.respondHtml { bookEditPage(booksRepo, session) } } hx.post(navBooksEdit.second) { - call.application.log.info("## Edit book form OK") - call.receiveParameters().forEach { param: String, value: List -> + call.application.log.info("## Edit book form OK ") + val receiveParameters = call.receiveParameters() + receiveParameters.forEach { param: String, value: List -> call.application.log.info("## param: $param, value: $value") } + val session = + getSession(receiveParameters["sessionId"], sessions, call.principal.userId) call.respondHtmlPartial(HttpStatusCode.OK) { p { - +"OK" + +"OK ${session.sessionId}" } } } + hx.post("${navBooksEdit.second}/addpublisher") { + val receiveParameters = call.receiveParameters() + val session = + getSession(receiveParameters["sessionId"], sessions, call.principal.userId) + } + hx.post("${navBooksEdit.second}/addseries") { + val receiveParameters = call.receiveParameters() + val session = + getSession(receiveParameters["sessionId"], sessions, call.principal.userId) + } + hx.post("${navBooksEdit.second}/addtag") { + val receiveParameters = call.receiveParameters() + val session = + getSession(receiveParameters["sessionId"], sessions, call.principal.userId) + } + hx.post("${navBooksEdit.second}/addnewtag") { + val receiveParameters = call.receiveParameters() + val session = + getSession(receiveParameters["sessionId"], sessions, call.principal.userId) + } + hx.post("${navBooksEdit.second}/rmtag") { + val receiveParameters = call.receiveParameters() + val session = + getSession(receiveParameters["sessionId"], sessions, call.principal.userId) + } + hx.post("${navBooksEdit.second}/addartist") { + val receiveParameters = call.receiveParameters() + val session = + getSession(receiveParameters["sessionId"], sessions, call.principal.userId) + } + hx.post("${navBooksEdit.second}/addnewartist") { + val receiveParameters = call.receiveParameters() + val session = + getSession(receiveParameters["sessionId"], sessions, call.principal.userId) + } + hx.post("${navBooksEdit.second}/rmartist") { + val receiveParameters = call.receiveParameters() + val session = + getSession(receiveParameters["sessionId"], sessions, call.principal.userId) + } + hx.post("${navBooksEdit.second}/changeartistrole") { + val receiveParameters = call.receiveParameters() + val session = + getSession(receiveParameters["sessionId"], sessions, call.principal.userId) + } // hx.get("/isbnlookupreset") { // call.respondHtmlPartial(HttpStatusCode.OK) { diff --git a/server/src/main/kotlin/books/edit/BooksSession.kt b/server/src/main/kotlin/books/edit/BooksSession.kt index bf6028d..cbddc0f 100644 --- a/server/src/main/kotlin/books/edit/BooksSession.kt +++ b/server/src/main/kotlin/books/edit/BooksSession.kt @@ -1,14 +1,43 @@ package net.keinekekse.app.books.edit +import net.keinekekse.app.books.model.* +import net.keinekekse.app.core.auth.Sessions import net.keinekekse.app.core.auth.UserSession -class BooksSession( - override val userId: String, - override val sessionId: String, - override var data: BooksSessionData -) : UserSession +fun newSession(uid: String, sessions: Sessions): UserSession { + val session = UserSession(uid, Sessions.newSessionId(), BooksSessionData()) + sessions.newSession(session) + return session +} +fun getSession(sessionId: String?, sessions: Sessions, uid: String): UserSession { +// TODO besseres Fehlerhandling + if (sessionId == null) throw IllegalArgumentException("sessionId is required") + val session = + sessions.getSession(sessionId) + ?: throw IllegalArgumentException("no session for sessionId ${sessionId}") + if (session.userId != uid) throw IllegalArgumentException("session is invalid: userId != ${uid}") + if (session.data is BooksSessionData) { + return session as UserSession + } + throw IllegalArgumentException("session.data has wrong type") +} -class BooksSessionData() { +class BooksSessionData { + lateinit var book: Book + lateinit var publisherList: List + lateinit var seriesList: List + lateinit var artistList: List + lateinit var tagList: List + + var newPublisherList: MutableList = mutableListOf() + var newSeriesList: MutableList = mutableListOf() + var addTagList: MutableList = mutableListOf() + var newTagList: MutableList = mutableListOf() + var rmTagList: MutableList = mutableListOf() + var addArtistList: MutableList = mutableListOf() + var newArtistList: MutableList = mutableListOf() + var rmArtistList: MutableList = mutableListOf() + var changeArtistRoleList: MutableList = mutableListOf() } diff --git a/server/src/main/kotlin/books/ui/BookEdit.kt b/server/src/main/kotlin/books/ui/BookEdit.kt index 22d22a4..8fea2ec 100644 --- a/server/src/main/kotlin/books/ui/BookEdit.kt +++ b/server/src/main/kotlin/books/ui/BookEdit.kt @@ -4,21 +4,26 @@ import io.ktor.htmx.html.* import kotlinx.coroutines.runBlocking import kotlinx.html.* import net.keinekekse.app.books.db.BookRepository -import net.keinekekse.app.books.model.* -import net.keinekekse.app.books.model.Tag +import net.keinekekse.app.books.edit.BooksSessionData +import net.keinekekse.app.books.model.BookType +import net.keinekekse.app.books.model.Languages +import net.keinekekse.app.core.auth.UserSession -fun FlowContent.bookEdit(book: Book, booksRepo: BookRepository) { +fun FlowContent.bookEdit( + booksRepo: BookRepository, + session: UserSession, +) { - val publishers: List = runBlocking { + session.data.publisherList = runBlocking { booksRepo.allPublishers() } - val series: List = runBlocking { + session.data.seriesList = runBlocking { booksRepo.allSeries() } - val artists: List = runBlocking { + session.data.artistList = runBlocking { booksRepo.allArtists() } - val tags: List = runBlocking { + session.data.tagList = runBlocking { booksRepo.allTags() } @@ -29,8 +34,11 @@ fun FlowContent.bookEdit(book: Book, booksRepo: BookRepository) { target = "#response" swap = "innerHTML" } + input(type = InputType.hidden, name = "sessionId") { + value = session.sessionId + } input(type = InputType.hidden, name = "bookId") { - value = book.id.toString() + value = session.data.book.id.toString() } div(classes = "flex flex-row mb-5 h-9") { @@ -43,7 +51,7 @@ fun FlowContent.bookEdit(book: Book, booksRepo: BookRepository) { for (type in BookType.entries) { option { - if (type == book.type) + if (type == session.data.book.type) selected = true value = type.ordinal.toString() +type.name @@ -57,7 +65,7 @@ fun FlowContent.bookEdit(book: Book, booksRepo: BookRepository) { } input(classes = "$cssTextInput w-150") { name = "title" - value = book.title + value = session.data.book.title } } @@ -67,7 +75,7 @@ fun FlowContent.bookEdit(book: Book, booksRepo: BookRepository) { } input(classes = "$cssTextInput w-150") { name = "originaltitle" - value = book.originalTitle ?: "" + value = session.data.book.originalTitle ?: "" } } @@ -77,7 +85,7 @@ fun FlowContent.bookEdit(book: Book, booksRepo: BookRepository) { } input(classes = "$cssTextInput w-150") { name = "subtitle" - value = book.subTitle ?: "" + value = session.data.book.subTitle ?: "" } } div(classes = "flex flex-row mb-5 h-9") { @@ -89,7 +97,7 @@ fun FlowContent.bookEdit(book: Book, booksRepo: BookRepository) { for (language in Languages.entries) { option { - if (language == book.language) + if (language == session.data.book.language) selected = true value = language.ordinal.toString() +language.name @@ -102,7 +110,7 @@ fun FlowContent.bookEdit(book: Book, booksRepo: BookRepository) { } input(classes = "$cssTextInput w-16") { name = "year" - value = book.year.toString() + value = session.data.book.year.toString() } div(classes = "ml-8 pr-3 content-center") { @@ -110,7 +118,7 @@ fun FlowContent.bookEdit(book: Book, booksRepo: BookRepository) { } input(classes = "$cssTextInput w-16") { name = "originalyear" - value = book.originalYear?.toString() ?: "" + value = session.data.book.originalYear?.toString() ?: "" } } @@ -120,7 +128,7 @@ fun FlowContent.bookEdit(book: Book, booksRepo: BookRepository) { } input(classes = "$cssTextInput w-40") { name = "isbn" - value = book.isbn + value = session.data.book.isbn } div(classes = "ml-14 pr-3 content-center") { @@ -133,9 +141,9 @@ fun FlowContent.bookEdit(book: Book, booksRepo: BookRepository) { value = "0" +"---" } - for (pub in publishers) { + for (pub in session.data.publisherList) { option { - if (pub.id == book.publisher.id) + if (pub.id == session.data.book.publisher.id) selected = true value = pub.id.toString() +pub.name @@ -145,9 +153,15 @@ fun FlowContent.bookEdit(book: Book, booksRepo: BookRepository) { button(classes = cssFormIcon) { title = "Verlag hinzufügen" // TODO - onClick = "document.getElementById('publisherDialog').showModal()" -// attributes["command"] = "show-modal" -// attributes["commandfor"] = "publisherDialog" //id + /* + type = ButtonType.button -> sonst wird "submit" angenommen und dann funktioniert + es nicht! + */ + type = ButtonType.button +// attributes["popovertarget"] = "publisherDialog" +// onClick = "document.getElementById('publisherDialog').showModal()" + attributes["command"] = "show-modal" + attributes["commandfor"] = "publisherDialog" //id materialSymbolFormButton("add_box") } @@ -165,9 +179,9 @@ fun FlowContent.bookEdit(book: Book, booksRepo: BookRepository) { value = "0" +"---" } - for (serie in series) { + for (serie in session.data.seriesList) { option { - if (book.series != null && serie.id == book.series.id) + if (session.data.book.series != null && serie.id == session.data.book.series!!.id) selected = true value = serie.id.toString() +serie.name @@ -184,7 +198,7 @@ fun FlowContent.bookEdit(book: Book, booksRepo: BookRepository) { } input(classes = "$cssTextInput w-16") { name = "seriesindex" - value = book.seriesIndex?.toString() ?: "" + value = session.data.book.seriesIndex?.toString() ?: "" } } @@ -209,7 +223,7 @@ fun FlowContent.bookEdit(book: Book, booksRepo: BookRepository) { } tbody { - for ((artist, role) in book.artists) { + for ((artist, role) in session.data.book.artists) { tr { td(classes = "border-t-1 $borderTable px-2 py-1") { +"${artist.name}, ${artist.givenName}" @@ -249,7 +263,7 @@ fun FlowContent.bookEdit(book: Book, booksRepo: BookRepository) { } } tbody { - for (tag in book.tags) { + for (tag in session.data.book.tags) { tr { td(classes = "border-t-1 $borderTable px-2 py-1") { +tag.tag @@ -273,7 +287,7 @@ fun FlowContent.bookEdit(book: Book, booksRepo: BookRepository) { textArea(classes = "$cssTextInput w-150 h-18 resize-none") { name = "comment" spellCheck = true - +book.comments + +session.data.book.comments } } // TODO parent @@ -295,13 +309,23 @@ fun FlowContent.bookEdit(book: Book, booksRepo: BookRepository) { } // TODO - dialog { + dialog( + classes = "m-auto h-fit w-full max-w-md rounded-lg shadow-2xl border-2 " + + "$borderTable px-3 py-2 $bgBody $textBody $bgDialogBackdrop" + ) { id = "publisherDialog" - attributes["closedby"] = "any" +// attributes["popover"] = "true" +// attributes["closedby"] = "any" div { +"Test-Verlag" } + button(classes = cssButtonStd) { + attributes["commandfor"] = "publisherDialog" + attributes["command"] = "close" + +"Close" + } } + output { } div { id = "response" } diff --git a/server/src/main/kotlin/books/ui/BookEditPage.kt b/server/src/main/kotlin/books/ui/BookEditPage.kt index b122f10..2856117 100644 --- a/server/src/main/kotlin/books/ui/BookEditPage.kt +++ b/server/src/main/kotlin/books/ui/BookEditPage.kt @@ -2,16 +2,20 @@ package net.keinekekse.app.books.ui import kotlinx.html.HTML import net.keinekekse.app.books.db.BookRepository -import net.keinekekse.app.books.model.Book +import net.keinekekse.app.books.edit.BooksSessionData +import net.keinekekse.app.core.auth.UserSession -fun HTML.bookEditPage(book: Book, booksRepo: BookRepository) { +fun HTML.bookEditPage( + booksRepo: BookRepository, + session: UserSession, +) { booksPage( navBooksEdit.first, mapOf(navBooks, Pair(navBooksEdit.first, "")) ) { - bookEdit(book, booksRepo) + bookEdit(booksRepo, session) } } diff --git a/server/src/main/kotlin/books/ui/BooksPage.kt b/server/src/main/kotlin/books/ui/BooksPage.kt index a1c995e..75d810e 100644 --- a/server/src/main/kotlin/books/ui/BooksPage.kt +++ b/server/src/main/kotlin/books/ui/BooksPage.kt @@ -15,7 +15,7 @@ fun HTML.booksPage(booksRepo: BookRepository) { } // content right - div(classes = "flex flex-auto $bgRightColumn") { + div(classes = "flex flex-auto $bgBody") { div(classes = "flex flex-col flex-auto") { // div { // +"some heading" diff --git a/server/src/main/kotlin/books/ui/BooksTemplate.kt b/server/src/main/kotlin/books/ui/BooksTemplate.kt index 5d0479b..3c48947 100644 --- a/server/src/main/kotlin/books/ui/BooksTemplate.kt +++ b/server/src/main/kotlin/books/ui/BooksTemplate.kt @@ -43,7 +43,7 @@ fun HTML.booksPage(title: String, breadcrumbs: Map, block: DIV.( body { // page - div(classes = "$cssFullscreen flex-col") { + div(classes = "$cssFullscreen flex-col $textBody") { // header div(classes = "flex flex-row justify-between py-2 px-5 $bgHeader $textHeader") { // header left @@ -80,7 +80,7 @@ fun HTML.booksPage(title: String, breadcrumbs: Map, block: DIV.( // } } - div(classes = "flex flex-row flex-auto overflow-hidden") { + div(classes = "flex flex-row flex-auto overflow-hidden $bgBody") { block() diff --git a/server/src/main/kotlin/books/ui/Helpers.kt b/server/src/main/kotlin/books/ui/Helpers.kt index edbc517..835f38a 100644 --- a/server/src/main/kotlin/books/ui/Helpers.kt +++ b/server/src/main/kotlin/books/ui/Helpers.kt @@ -14,15 +14,16 @@ const val textHeader = "text-orange-100" const val bgHeaderIcon = "bg-orange-100" const val bgFooter = "bg-orange-50" -const val bgLeftColumn = "bg-slate-200" -const val bgRightColumn = "bg-slate-50" -const val bgThead = "bg-slate-200" - +const val bgBody = "bg-taupe-100" +const val textBody = "text-taupe-900" +const val bgLeftColumn = "bg-taupe-200" +const val bgThead = "bg-taupe-200" +const val bgDialogBackdrop = "backdrop:bg-taupe-400/40" const val borderTable = "border-slate-400" -const val bgStdButton = "bg-taupe-500" -const val bgStdButtonHover = "hover:bg-taupe-700" -const val bgStdButtonFocus = "focus:bg-taupe-700" +const val bgStdButton = "bg-taupe-400" +const val bgStdButtonHover = "hover:bg-taupe-500" +const val bgStdButtonFocus = "focus:bg-taupe-500" const val bgPriButton = "bg-orange-400" const val bgPriButtonHover = "hover:bg-orange-600" const val bgPriButtonFocus = "focus:bg-orange-600" diff --git a/server/src/main/kotlin/books/ui/ImportEditPage.kt b/server/src/main/kotlin/books/ui/ImportEditPage.kt index 5c87cc8..dccd416 100644 --- a/server/src/main/kotlin/books/ui/ImportEditPage.kt +++ b/server/src/main/kotlin/books/ui/ImportEditPage.kt @@ -5,12 +5,18 @@ import kotlinx.html.div import kotlinx.html.img import kotlinx.html.span import net.keinekekse.app.books.db.BookRepository +import net.keinekekse.app.books.edit.BooksSessionData import net.keinekekse.app.books.model.Book import net.keinekekse.app.books.model.CalibreBookInfo import net.keinekekse.app.books.model.Languages import net.keinekekse.app.books.model.Publisher +import net.keinekekse.app.core.auth.UserSession -fun HTML.importEditPage(bookInfo: CalibreBookInfo?, booksRepo: BookRepository) { +fun HTML.importEditPage( + bookInfo: CalibreBookInfo?, + booksRepo: BookRepository, + session: UserSession, +) { val dataUrl = embedImageURL(bookInfo?.cover) booksPage( navBooksScanEdit.first, @@ -18,15 +24,14 @@ fun HTML.importEditPage(bookInfo: CalibreBookInfo?, booksRepo: BookRepository) { ) { div(classes = "flex flex-row flex-auto") { - bookEdit( - Book( - title = bookInfo?.title ?: "", - year = bookInfo?.published ?: 0, - isbn = bookInfo?.isbn ?: "", - publisher = Publisher(0, ""), - language = bookInfo?.language ?: Languages.DE - ), booksRepo + session.data.book = Book( + title = bookInfo?.title ?: "", + year = bookInfo?.published ?: 0, + isbn = bookInfo?.isbn ?: "", + publisher = Publisher(0, ""), + language = bookInfo?.language ?: Languages.DE ) + bookEdit(booksRepo, session) div(classes = "flex flex-col m-8 ") { div(classes = "text-2xl mx-8") { diff --git a/server/src/main/kotlin/books/ui/ImportPage.kt b/server/src/main/kotlin/books/ui/ImportPage.kt index e31c0d4..7d5889f 100644 --- a/server/src/main/kotlin/books/ui/ImportPage.kt +++ b/server/src/main/kotlin/books/ui/ImportPage.kt @@ -23,7 +23,7 @@ fun HTML.importPage(books: List) { } // content right - div(classes = "flex flex-auto $bgRightColumn") { + div(classes = "flex flex-auto $bgBody") { div(classes = "flex flex-col flex-auto") { div { // +"some heading" diff --git a/server/src/main/kotlin/books/ui/TestPage.kt b/server/src/main/kotlin/books/ui/TestPage.kt index 1ba7582..8d7f954 100644 --- a/server/src/main/kotlin/books/ui/TestPage.kt +++ b/server/src/main/kotlin/books/ui/TestPage.kt @@ -211,7 +211,7 @@ fun HTML.testPage(booksDb: Database) { } } // content right - div(classes = "flex flex-auto $bgRightColumn") { + div(classes = "flex flex-auto $bgBody") { div(classes = "flex flex-col flex-auto") { // div { // +"some heading" diff --git a/server/src/main/kotlin/core/auth/Sessions.kt b/server/src/main/kotlin/core/auth/Sessions.kt index b27a2a5..687f19a 100644 --- a/server/src/main/kotlin/core/auth/Sessions.kt +++ b/server/src/main/kotlin/core/auth/Sessions.kt @@ -5,40 +5,29 @@ import kotlin.uuid.Uuid class Sessions { - var sessions: MutableMap>> = mutableMapOf() + var sessions: MutableMap> = mutableMapOf() - @OptIn(ExperimentalUuidApi::class) - fun newSessionId(): String { - return Uuid.generateV4().toHexDashString() + companion object { + @OptIn(ExperimentalUuidApi::class) + fun newSessionId(): String { + return Uuid.generateV4().toHexDashString() + } } - fun getUserSessions(uid: String): MutableMap>? { - return sessions.get(uid) + fun getSession(sessionId: String): UserSession<*>? { + return sessions[sessionId] } - fun getUserSession(uid: String, sessionId: String): UserSession<*>? { - return sessions.get(uid)?.get(sessionId) + fun newSession(data: UserSession<*>) { + sessions[data.sessionId] = data } - - fun setUserSession(uid: String, sessionId: String, data: UserSession<*>) { - sessions.getOrPut(uid) { mutableMapOf() }[sessionId] = data - } - -// fun addSession(uid: String) { -// sessions[uid] = BooksSession(uid, "", "") -// } -// -// fun addTestSession(uid: String) { -// sessions[uid] = TestSession(uid, "", 0) -// } } -interface UserSession { - val userId: String - val sessionId: String - - var data: T -} +data class UserSession( + val userId: String, + val sessionId: String, + var data: T, +) //data class BooksSession( // override val userId: String, diff --git a/server/src/main/kotlin/core/ui/LandingPage.kt b/server/src/main/kotlin/core/ui/LandingPage.kt index 026900a..cae15cc 100644 --- a/server/src/main/kotlin/core/ui/LandingPage.kt +++ b/server/src/main/kotlin/core/ui/LandingPage.kt @@ -7,6 +7,7 @@ import kotlinx.html.* import net.keinekekse.app.VERSION_books import net.keinekekse.app.books.ui.materialSymbol import net.keinekekse.app.books.ui.navBooks +import net.keinekekse.app.books.ui.navBooksScan import net.keinekekse.app.core.config.LOGIN_PATH import net.keinekekse.app.core.config.LOGOUT_PATH @@ -37,11 +38,25 @@ fun HTML.landingPage(loggedOn: Boolean) { } } } + } + div(classes = "lg:hidden p-8") { + a(classes = "inline-flex $cssMainLink") { + href = navBooksScan.second -// a(classes = "p-2 text-xl font-bold text-sky-500 hover:text-sky-700 hover:bg-sky-100 cursor-pointer") { -// href = "/books" -// +VERSION_books.description -// } + img(classes = "h-14 my-2") { + src = "/static/books.png" + } + div(classes = "self-center text-right ml-3") { + div { + div { + +"Scan Books" + } +// div(classes = "text-xs") { +// +VERSION_books.version +// } + } + } + } } div(classes = "m-8") { a(classes = cssMainLink) { diff --git a/server/src/main/kotlin/core/ui/PageTemplate.kt b/server/src/main/kotlin/core/ui/PageTemplate.kt index f9e305a..cd13d9d 100644 --- a/server/src/main/kotlin/core/ui/PageTemplate.kt +++ b/server/src/main/kotlin/core/ui/PageTemplate.kt @@ -47,7 +47,7 @@ fun HTML.mainApplicationPage(block: DIV.() -> Unit = {}) { } } // body - div(classes = "inline-flex $bgMainBody py-10 h-full overflow-hidden w-full rounded-b-lg") { + div(classes = "inline-flex $bgMainBody py-10 h-full overflow-auto w-full rounded-b-lg") { block()