package be.simplenotes.app.views import be.simplenotes.app.utils.StaticFileResolver import be.simplenotes.app.views.components.* import be.simplenotes.domain.model.PersistedNote import be.simplenotes.domain.model.PersistedNoteMetadata import be.simplenotes.domain.security.JwtPayload import io.konform.validation.ValidationError import kotlinx.html.* class NoteView(staticFileResolver: StaticFileResolver) : View(staticFileResolver) { fun noteEditor( jwtPayload: JwtPayload, error: String? = null, textarea: String? = null, validationErrors: List = emptyList(), ) = renderPage(title = "New note", jwtPayload = jwtPayload) { div("container mx-auto p-4") { // TODO: error error?.let { alert(Alert.Warning, error) } validationErrors.forEach { alert(Alert.Warning, it.dataPath.substringAfter('.') + ": " + it.message) } form(method = FormMethod.post) { textArea(classes = "w-full bg-gray-800 p-5 outline-none font-mono") { attributes.also { it["rows"] = "20" it["id"] = "markdown" it["name"] = "markdown" it["aria-label"] = "markdown text area" it["spellcheck"] = "false" } textarea?.let { +it } ?: +""" |--- |title: '' |tags: [] |--- | """.trimMargin("|") } submitButton("Save") } } } fun notes( jwtPayload: JwtPayload, notes: List, currentPage: Int, numberOfPages: Int, tag: String?, ) = renderPage(title = "Notes", jwtPayload = jwtPayload) { div("container mx-auto p-4") { div("flex justify-between mb-4") { h1("text-2xl underline") { +"Notes" } span { a( href = "/notes/trash", classes = "underline font-semibold" ) { +"Trash" } a( href = "/notes/new", classes = "ml-2 btn btn-green" ) { +"New" } } } if (notes.isNotEmpty()) noteTable(notes) else span { if (numberOfPages > 1) +"You went too far" else +"No notes yet" } if (numberOfPages > 1) pagination(currentPage, numberOfPages, tag) } } fun trash( jwtPayload: JwtPayload, notes: List, currentPage: Int, numberOfPages: Int ) = renderPage(title = "Notes", jwtPayload = jwtPayload) { div("container mx-auto p-4") { div("flex justify-between mb-4") { h1("text-2xl underline") { +"Deleted notes" } } if (notes.isNotEmpty()) deletedNoteTable(notes) else span { if (numberOfPages > 1) +"You went too far" else +"No deleted notes" } if (numberOfPages > 1) pagination(currentPage, numberOfPages, null) } } private fun DIV.pagination(currentPage: Int, numberOfPages: Int, tag: String?) { val links = mutableListOf>() // if (currentPage > 1) links += "Previous" to "?page=${currentPage - 1}" links += (1..numberOfPages).map { page -> "$page" to (tag?.let { "?page=$page&tag=$it" } ?: "?page=$page") } // if (currentPage < numberOfPages) links += "Next" to "?page=${currentPage + 1}" nav("pages") { links.forEach { (name, href) -> a(href, classes = if (name == currentPage.toString()) "active" else null) { +name } } } } fun renderedNote(jwtPayload: JwtPayload, note: PersistedNote) = renderPage(note.meta.title, jwtPayload = jwtPayload) { div("container mx-auto p-4") { div("flex items-center justify-between mb-4") { h1("text-3xl fond-bold underline") { +note.meta.title } span("space-x-2") { note.meta.tags.forEach { a(href = "/notes?tag=$it", classes = "tag") { +"#$it" } } } } span("flex space-x-2 justify-end mb-4") { a( href = "/notes/${note.uuid}/edit", classes = "btn btn-teal" ) { +"Edit" } form(method = FormMethod.post, classes = "inline") { button( type = ButtonType.submit, name = "delete", classes = "btn btn-red" ) { +"Delete" } } } div { attributes["id"] = "note" unsafe { +note.html } } } } }