package be.simplenotes.app.controllers import be.simplenotes.app.extensions.html import be.simplenotes.app.extensions.redirect import be.simplenotes.app.utils.parseSearchTerms 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 be.simplenotes.types.LoggedInUser import be.simplenotes.views.NoteView 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, loggedInUser: LoggedInUser): Response { if (request.method == Method.GET) return Response(OK).html(view.noteEditor(loggedInUser)) val markdownForm = request.form("markdown") ?: "" return noteService.create(loggedInUser.userId, markdownForm).fold( { val html = when (it) { MissingMeta -> view.noteEditor( loggedInUser, error = "Missing note metadata", textarea = markdownForm ) InvalidMeta -> view.noteEditor( loggedInUser, error = "Invalid note metadata", textarea = markdownForm ) is ValidationError -> view.noteEditor( loggedInUser, validationErrors = it.validationErrors, textarea = markdownForm ) } Response(BAD_REQUEST).html(html) }, { Response.redirect("/notes/${it.uuid}") } ) } fun list(request: Request, loggedInUser: LoggedInUser): Response { val currentPage = request.query("page")?.toIntOrNull()?.let(::abs) ?: 1 val tag = request.query("tag") val (pages, notes) = noteService.paginatedNotes(loggedInUser.userId, currentPage, tag = tag) val deletedCount = noteService.countDeleted(loggedInUser.userId) return Response(OK).html(view.notes(loggedInUser, notes, currentPage, pages, deletedCount, tag = tag)) } fun search(request: Request, loggedInUser: LoggedInUser): Response { val query = request.form("search") ?: "" val terms = parseSearchTerms(query) val notes = noteService.search(loggedInUser.userId, terms) val deletedCount = noteService.countDeleted(loggedInUser.userId) return Response(OK).html(view.search(loggedInUser, notes, query, deletedCount)) } fun note(request: Request, loggedInUser: LoggedInUser): Response { val noteUuid = request.uuidPath() ?: return Response(NOT_FOUND) if (request.method == Method.POST) { if (request.form("delete") != null) { return if (noteService.trash(loggedInUser.userId, noteUuid)) Response.redirect("/notes") // TODO: flash cookie to show success ? else Response(NOT_FOUND) // TODO: show an error } if (request.form("public") != null) { if (!noteService.makePublic(loggedInUser.userId, noteUuid)) return Response(NOT_FOUND) } else if (request.form("private") != null) { if (!noteService.makePrivate(loggedInUser.userId, noteUuid)) return Response(NOT_FOUND) } } val note = noteService.find(loggedInUser.userId, noteUuid) ?: return Response(NOT_FOUND) return Response(OK).html(view.renderedNote(loggedInUser, note, shared = false)) } fun public(request: Request, loggedInUser: LoggedInUser?): Response { val noteUuid = request.uuidPath() ?: return Response(NOT_FOUND) val note = noteService.findPublic(noteUuid) ?: return Response(NOT_FOUND) return Response(OK).html(view.renderedNote(loggedInUser, note, shared = true)) } fun edit(request: Request, loggedInUser: LoggedInUser): Response { val noteUuid = request.uuidPath() ?: return Response(NOT_FOUND) val note = noteService.find(loggedInUser.userId, noteUuid) ?: return Response(NOT_FOUND) if (request.method == Method.GET) { return Response(OK).html(view.noteEditor(loggedInUser, textarea = note.markdown)) } val markdownForm = request.form("markdown") ?: "" return noteService.update(loggedInUser.userId, note.uuid, markdownForm).fold( { val html = when (it) { MissingMeta -> view.noteEditor( loggedInUser, error = "Missing note metadata", textarea = markdownForm ) InvalidMeta -> view.noteEditor( loggedInUser, error = "Invalid note metadata", textarea = markdownForm ) is ValidationError -> view.noteEditor( loggedInUser, validationErrors = it.validationErrors, textarea = markdownForm ) } Response(BAD_REQUEST).html(html) }, { Response.redirect("/notes/${note.uuid}") } ) } fun trash(request: Request, loggedInUser: LoggedInUser): Response { val currentPage = request.query("page")?.toIntOrNull()?.let(::abs) ?: 1 val tag = request.query("tag") val (pages, notes) = noteService.paginatedNotes(loggedInUser.userId, currentPage, tag = tag, deleted = true) return Response(OK).html(view.trash(loggedInUser, notes, currentPage, pages)) } fun deleted(request: Request, loggedInUser: LoggedInUser): Response { val uuid = request.uuidPath() ?: return Response(NOT_FOUND) return if (request.form("delete") != null) if (noteService.delete(loggedInUser.userId, uuid)) Response.redirect("/notes/trash") else Response(NOT_FOUND) else if (noteService.restore(loggedInUser.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 } } }