201 lines
6.7 KiB
Kotlin

package be.simplenotes.views
import be.simplenotes.types.LoggedInUser
import be.simplenotes.types.PersistedNote
import be.simplenotes.types.PersistedNoteMetadata
import be.simplenotes.views.components.*
import io.konform.validation.ValidationError
import kotlinx.html.*
class NoteView(styles: String) : View(styles) {
fun noteEditor(
loggedInUser: LoggedInUser,
error: String? = null,
textarea: String? = null,
validationErrors: List<ValidationError> = emptyList(),
) = renderPage(title = "New note", loggedInUser = loggedInUser) {
div("container mx-auto p-4") {
error?.let { alert(Alert.Warning, error) }
validationErrors.forEach {
alert(Alert.Warning, it.dataPath.substringAfter('.') + ": " + it.message)
}
form(method = FormMethod.post) {
textArea {
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(
loggedInUser: LoggedInUser,
notes: List<PersistedNoteMetadata>,
currentPage: Int,
numberOfPages: Int,
numberOfDeletedNotes: Int,
tag: String?,
) = renderPage(title = "Notes", loggedInUser = loggedInUser) {
div("container mx-auto p-4") {
noteListHeader(numberOfDeletedNotes)
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 search(
loggedInUser: LoggedInUser,
notes: List<PersistedNoteMetadata>,
query: String,
numberOfDeletedNotes: Int,
) = renderPage("Notes", loggedInUser = loggedInUser) {
div("container mx-auto p-4") {
noteListHeader(numberOfDeletedNotes, query)
noteTable(notes)
}
}
fun trash(
loggedInUser: LoggedInUser,
notes: List<PersistedNoteMetadata>,
currentPage: Int,
numberOfPages: Int,
) = renderPage(title = "Notes", loggedInUser = loggedInUser) {
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<Pair<String, String>>()
// 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(loggedInUser: LoggedInUser?, note: PersistedNote, shared: Boolean) = renderPage(
note.meta.title,
loggedInUser = loggedInUser,
scripts = listOf("/highlight.10.1.2.js", "/init-highlight.0.0.1.js")
) {
div("container mx-auto p-4") {
if (shared) {
p("p-4 bg-gray-800") {
+"You are viewing a public note "
}
hr { }
}
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"
}
}
}
}
if (!shared) {
noteActionForm(note)
if (note.public) {
p("my-4") {
+"You can share this link : "
a(href = "/notes/public/${note.uuid}", classes = "text-blue-300 underline") {
+"/notes/public/${note.uuid}"
}
}
hr { }
}
}
div {
attributes["id"] = "note"
unsafe {
+note.html
}
}
}
}
private fun DIV.noteActionForm(note: PersistedNote) {
form(method = FormMethod.post, classes = "inline flex space-x-2 justify-end mb-4") {
a(
href = "/notes/${note.uuid}/edit",
classes = "btn btn-green"
) { +"Edit" }
span {
button(
type = ButtonType.submit,
name = if (note.public) "private" else "public",
classes = "font-semibold border-b-4 ${if (note.public) "border-teal-200" else "border-green-500"}" +
" p-2 rounded-l bg-teal-200 text-gray-800"
) {
+"Private"
}
button(
type = ButtonType.submit,
name = if (note.public) "private" else "public",
classes = "font-semibold border-b-4 " +
if (!note.public) "border-teal-200" else "border-green-500" +
" p-2 rounded-r bg-teal-200 text-gray-800"
) {
+"Public"
}
}
button(
type = ButtonType.submit,
name = "delete",
classes = "btn btn-red"
) { +"Delete" }
}
}
}