package be.simplenotes.app.controllers import be.simplenotes.app.extensions.html import be.simplenotes.app.extensions.redirect import be.simplenotes.app.views.NoteView import be.simplenotes.domain.security.JwtPayload import be.simplenotes.domain.usecases.NoteService import be.simplenotes.domain.usecases.markdown.InvalidMeta import be.simplenotes.domain.usecases.markdown.MissingMeta import be.simplenotes.domain.usecases.markdown.ValidationError import org.http4k.core.Method import org.http4k.core.Request import org.http4k.core.Response import org.http4k.core.Status.Companion.BAD_REQUEST import org.http4k.core.Status.Companion.NOT_FOUND import org.http4k.core.Status.Companion.OK import org.http4k.core.body.form import org.http4k.routing.path import java.util.* import kotlin.math.abs class NoteController( private val view: NoteView, private val noteService: NoteService, ) { fun new(request: Request, jwtPayload: JwtPayload): Response { if (request.method == Method.GET) return Response(OK).html(view.noteEditor(jwtPayload)) val markdownForm = request.form("markdown") ?: "" return noteService.create(jwtPayload.userId, markdownForm).fold( { val html = when (it) { MissingMeta -> view.noteEditor(jwtPayload, error = "Missing note metadata", textarea = markdownForm) InvalidMeta -> view.noteEditor(jwtPayload, error = "Invalid note metadata", textarea = markdownForm) is ValidationError -> view.noteEditor(jwtPayload, validationErrors = it.validationErrors, textarea = markdownForm) } Response(BAD_REQUEST).html(html) }, { Response.redirect("/notes/${it.uuid}") } ) } fun list(request: Request, jwtPayload: JwtPayload): Response { val currentPage = request.query("page")?.toIntOrNull()?.let(::abs) ?: 1 val tag = request.query("tag") val (pages, notes) = noteService.paginatedNotes(jwtPayload.userId, currentPage, tag = tag) return Response(OK).html(view.notes(jwtPayload, notes, currentPage, pages, tag = tag)) } fun note(request: Request, jwtPayload: JwtPayload): Response { val noteUuid = request.uuidPath() ?: return Response(NOT_FOUND) if (request.method == Method.POST && request.form("delete") != null) { return if (noteService.trash(jwtPayload.userId, noteUuid)) Response.redirect("/notes") // TODO: flash cookie to show success ? else Response(NOT_FOUND) // TODO: show an error } val note = noteService.find(jwtPayload.userId, noteUuid) ?: return Response(NOT_FOUND) return Response(OK).html(view.renderedNote(jwtPayload, note)) } fun edit(request: Request, jwtPayload: JwtPayload): Response { val noteUuid = request.uuidPath() ?: return Response(NOT_FOUND) val note = noteService.find(jwtPayload.userId, noteUuid) ?: return Response(NOT_FOUND) if (request.method == Method.GET) { return Response(OK).html(view.noteEditor(jwtPayload, textarea = note.markdown)) } val markdownForm = request.form("markdown") ?: "" return noteService.update(jwtPayload.userId, note.uuid, markdownForm).fold( { val html = when (it) { MissingMeta -> view.noteEditor(jwtPayload, error = "Missing note metadata", textarea = markdownForm) InvalidMeta -> view.noteEditor(jwtPayload, error = "Invalid note metadata", textarea = markdownForm) is ValidationError -> view.noteEditor(jwtPayload, validationErrors = it.validationErrors, textarea = markdownForm) } Response(BAD_REQUEST).html(html) }, { Response.redirect("/notes/${note.uuid}") } ) } fun trash(request: Request, jwtPayload: JwtPayload): Response { val currentPage = request.query("page")?.toIntOrNull()?.let(::abs) ?: 1 val tag = request.query("tag") val (pages, notes) = noteService.paginatedNotes(jwtPayload.userId, currentPage, tag = tag, deleted = true) return Response(OK).html(view.trash(jwtPayload, notes, currentPage, pages)) } fun deleted(request: Request, jwtPayload: JwtPayload): Response { val uuid = request.uuidPath() ?: return Response(NOT_FOUND) return if (request.form("delete") != null) if (noteService.delete(jwtPayload.userId, uuid)) Response.redirect("/notes/trash") else Response(NOT_FOUND) else if (noteService.restore(jwtPayload.userId, uuid)) Response.redirect("/notes/$uuid") else Response(NOT_FOUND) } private fun Request.uuidPath(): UUID? { val uuidPath = path("uuid")!! return try { UUID.fromString(uuidPath)!! } catch (e: IllegalArgumentException) { null } } }