Add search terms parser + tests

This commit is contained in:
2020-08-19 18:19:34 +02:00
parent 12619f6550
commit 315a01ea18
7 changed files with 122 additions and 16 deletions
@@ -2,12 +2,14 @@ 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.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 be.simplenotes.search.SearchTerms
import org.http4k.core.Method
import org.http4k.core.Request
import org.http4k.core.Response
@@ -34,7 +36,9 @@ class NoteController(
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)
is ValidationError -> view.noteEditor(jwtPayload,
validationErrors = it.validationErrors,
textarea = markdownForm)
}
Response(BAD_REQUEST).html(html)
},
@@ -52,6 +56,13 @@ class NoteController(
return Response(OK).html(view.notes(jwtPayload, notes, currentPage, pages, deletedCount, tag = tag))
}
fun search(request: Request, jwtPayload: JwtPayload): Response {
val terms = request.searchTerms()
val notes = noteService.search(jwtPayload.userId, terms)
val deletedCount = noteService.countDeleted(jwtPayload.userId)
return Response(OK).html(view.search(jwtPayload, notes, deletedCount))
}
fun note(request: Request, jwtPayload: JwtPayload): Response {
val noteUuid = request.uuidPath() ?: return Response(NOT_FOUND)
@@ -121,4 +132,6 @@ class NoteController(
null
}
}
private fun Request.searchTerms(): SearchTerms = parseSearchTerms(form("search") ?: "")
}
+1
View File
@@ -48,6 +48,7 @@ class Router(
"/settings" bind POST to { protected(it, settingsController::settings) },
"/export" bind POST to { protected(it, settingsController::export) },
"/notes" bind GET to { protected(it, noteController::list) },
"/notes" bind POST to { protected(it, noteController::search) },
"/notes/new" bind GET to { protected(it, noteController::new) },
"/notes/new" bind POST to { protected(it, noteController::new) },
"/notes/trash" bind GET to { protected(it, noteController::trash) },
@@ -0,0 +1,33 @@
package be.simplenotes.app.utils
import be.simplenotes.search.SearchTerms
private val titleRe = """title:['"](?<title>.*?)['"]""".toRegex()
private val outerTitleRe = """(?<title>title:['"].*?['"])""".toRegex()
private val tagRe = """tag:['"](?<tag>.*?)['"]""".toRegex()
private val outerTagRe = """(?<tag>tag:['"].*?['"])""".toRegex()
fun parseSearchTerms(input: String): SearchTerms {
val title: String? = titleRe.find(input)?.groups?.get("title")?.value
val tag: String? = tagRe.find(input)?.groups?.get("tag")?.value
var c: String = input
if (title != null) {
val titleGroup = outerTitleRe.find(input)?.groups?.get("title")?.value
titleGroup?.let { c = c.replace(it, "") }
}
if (tag != null) {
val tagGroup = outerTagRe.find(input)?.groups?.get("tag")?.value
tagGroup?.let { c = c.replace(it, "") }
}
val content = c.trim().ifEmpty { null }
return SearchTerms(
title = title,
tag = tag,
content = content
)
}
+13 -15
View File
@@ -55,20 +55,7 @@ class NoteView(staticFileResolver: StaticFileResolver) : View(staticFileResolver
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 ($numberOfDeletedNotes)" }
a(
href = "/notes/new",
classes = "ml-2 btn btn-green"
) { +"New" }
}
}
noteListHeader(numberOfDeletedNotes)
if (notes.isNotEmpty())
noteTable(notes)
else
@@ -81,11 +68,22 @@ class NoteView(staticFileResolver: StaticFileResolver) : View(staticFileResolver
}
}
fun search(
jwtPayload: JwtPayload,
notes: List<PersistedNoteMetadata>,
numberOfDeletedNotes: Int,
) = renderPage("Notes", jwtPayload = jwtPayload) {
div("container mx-auto p-4") {
noteListHeader(numberOfDeletedNotes)
noteTable(notes)
}
}
fun trash(
jwtPayload: JwtPayload,
notes: List<PersistedNoteMetadata>,
currentPage: Int,
numberOfPages: Int
numberOfPages: Int,
) = renderPage(title = "Notes", jwtPayload = jwtPayload) {
div("container mx-auto p-4") {
div("flex justify-between mb-4") {
@@ -0,0 +1,19 @@
package be.simplenotes.app.views.components
import kotlinx.html.*
fun DIV.noteListHeader(numberOfDeletedNotes: Int) {
div("flex justify-between mb-4") {
h1("text-2xl underline") { +"Notes" }
span {
a(
href = "/notes/trash",
classes = "underline font-semibold"
) { +"Trash ($numberOfDeletedNotes)" }
a(
href = "/notes/new",
classes = "ml-2 btn btn-green"
) { +"New" }
}
}
}