From 54fe6c49ca232baca844774f9c80fb5303834490 Mon Sep 17 00:00:00 2001
From: querwurzel <>
Date: Wed, 8 Nov 2023 21:38:42 +0100
Subject: [PATCH] set search contract
---
.../binpastes/paste/api/PasteController.java | 16 +++---
.../binpastes/paste/api/model/ListView.java | 4 +-
.../binpastes/paste/api/model/SearchView.java | 51 +++++++++++++++++++
.../binpastes/paste/api/model/SingleView.java | 2 +-
.../domain/SimpleFullTextSupportImpl.java | 4 +-
frontend/src/api/client.ts | 3 +-
frontend/src/api/model/PasteListView.ts | 4 --
frontend/src/api/model/PasteSearchView.ts | 9 ++++
frontend/src/pages/Search.tsx | 28 +++++++++-
9 files changed, 103 insertions(+), 18 deletions(-)
create mode 100644 backend/src/main/java/com/github/binpastes/paste/api/model/SearchView.java
create mode 100644 frontend/src/api/model/PasteSearchView.ts
diff --git a/backend/src/main/java/com/github/binpastes/paste/api/PasteController.java b/backend/src/main/java/com/github/binpastes/paste/api/PasteController.java
index 7a6f5ed..59e2ae9 100644
--- a/backend/src/main/java/com/github/binpastes/paste/api/PasteController.java
+++ b/backend/src/main/java/com/github/binpastes/paste/api/PasteController.java
@@ -2,6 +2,8 @@
import com.github.binpastes.paste.api.model.CreateCmd;
import com.github.binpastes.paste.api.model.ListView;
+import com.github.binpastes.paste.api.model.SearchView;
+import com.github.binpastes.paste.api.model.SearchView.SearchItemView;
import com.github.binpastes.paste.api.model.SingleView;
import com.github.binpastes.paste.domain.Paste;
import com.github.binpastes.paste.domain.PasteService;
@@ -61,7 +63,7 @@ public Mono findPaste(@PathVariable("pasteId") String pasteId, Serve
response.getHeaders().add(HttpHeaders.CACHE_CONTROL, "max-age=300");
}
})
- .map(reference -> SingleView.from(reference, remoteAddress(request)))
+ .map(reference -> SingleView.of(reference, remoteAddress(request)))
.switchIfEmpty(Mono.error(new ResponseStatusException(HttpStatus.NOT_FOUND)));
}
@@ -69,18 +71,18 @@ public Mono findPaste(@PathVariable("pasteId") String pasteId, Serve
public Mono findPastes() {
return pasteService
.findAll()
- .map(ListItemView::from)
+ .map(ListItemView::of)
.collectList()
- .map(ListView::from);
+ .map(ListView::of);
}
@GetMapping("/search")
- public Mono searchPastes(@RequestParam("term") @NotBlank @Size(min = 3) @Pattern(regexp = "[\\pL\\pN\\s]+") String term) {
+ public Mono searchPastes(@RequestParam("term") @NotBlank @Size(min = 3) @Pattern(regexp = "[\\pL\\pN\\s]+") String term) {
return pasteService
.findByFullText(term)
- .map(ListItemView::from)
+ .map(paste -> SearchItemView.of(paste, term))
.collectList()
- .map(ListView::from);
+ .map(SearchView::of);
}
@PostMapping
@@ -95,7 +97,7 @@ public Mono createPaste(@Valid @RequestBody Mono createCm
cmd.pasteExposure(),
remoteAddress(request)
))
- .map((Paste reference) -> SingleView.from(reference, remoteAddress(request)));
+ .map((Paste reference) -> SingleView.of(reference, remoteAddress(request)));
}
@DeleteMapping("/{pasteId:[a-zA-Z0-9]{40}}")
diff --git a/backend/src/main/java/com/github/binpastes/paste/api/model/ListView.java b/backend/src/main/java/com/github/binpastes/paste/api/model/ListView.java
index c87e219..5ae7839 100644
--- a/backend/src/main/java/com/github/binpastes/paste/api/model/ListView.java
+++ b/backend/src/main/java/com/github/binpastes/paste/api/model/ListView.java
@@ -8,7 +8,7 @@
public record ListView(
List pastes
) {
- public static ListView from(List pastes) {
+ public static ListView of(final List pastes) {
return new ListView(pastes);
}
@@ -20,7 +20,7 @@ public record ListItemView (
LocalDateTime dateCreated,
LocalDateTime dateOfExpiry
) {
- public static ListItemView from(Paste reference) {
+ public static ListItemView of(final Paste reference) {
return new ListItemView(
reference.getId(),
reference.getTitle(),
diff --git a/backend/src/main/java/com/github/binpastes/paste/api/model/SearchView.java b/backend/src/main/java/com/github/binpastes/paste/api/model/SearchView.java
new file mode 100644
index 0000000..921fbf3
--- /dev/null
+++ b/backend/src/main/java/com/github/binpastes/paste/api/model/SearchView.java
@@ -0,0 +1,51 @@
+package com.github.binpastes.paste.api.model;
+
+import com.github.binpastes.paste.domain.Paste;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+public record SearchView(
+ List pastes
+) {
+
+ public static SearchView of(List pastes) {
+ return new SearchView(pastes);
+ }
+
+ public record SearchItemView(
+ String id,
+ String title,
+ String highlight,
+ int sizeInBytes,
+ LocalDateTime dateCreated,
+ LocalDateTime dateOfExpiry
+ ) {
+
+ private static final short HIGHLIGHT_RANGE = 25;
+
+ public static SearchItemView of(final Paste reference, final String term) {
+ return new SearchItemView(
+ reference.getId(),
+ reference.getTitle(),
+ highlight(reference.getContent(), term),
+ reference.getContent().getBytes().length,
+ reference.getDateCreated(),
+ reference.getDateOfExpiry()
+ );
+ }
+
+ public static String highlight(final String content, final String term) {
+ final int idx = content.indexOf(term);
+
+ if (idx == -1) {
+ return content;
+ }
+
+ return content.substring(
+ Math.max(0, idx - HIGHLIGHT_RANGE),
+ Math.min(content.length(), idx + term.length() + HIGHLIGHT_RANGE)
+ );
+ }
+ }
+}
diff --git a/backend/src/main/java/com/github/binpastes/paste/api/model/SingleView.java b/backend/src/main/java/com/github/binpastes/paste/api/model/SingleView.java
index f315327..bab583f 100644
--- a/backend/src/main/java/com/github/binpastes/paste/api/model/SingleView.java
+++ b/backend/src/main/java/com/github/binpastes/paste/api/model/SingleView.java
@@ -18,7 +18,7 @@ public record SingleView(
LocalDateTime lastViewed,
long views
) {
- public static SingleView from(Paste reference, String remoteAddress) {
+ public static SingleView of(final Paste reference, final String remoteAddress) {
return new SingleView(
reference.getId(),
reference.getTitle(),
diff --git a/backend/src/main/java/com/github/binpastes/paste/domain/SimpleFullTextSupportImpl.java b/backend/src/main/java/com/github/binpastes/paste/domain/SimpleFullTextSupportImpl.java
index 2ee8c0a..0e93b05 100644
--- a/backend/src/main/java/com/github/binpastes/paste/domain/SimpleFullTextSupportImpl.java
+++ b/backend/src/main/java/com/github/binpastes/paste/domain/SimpleFullTextSupportImpl.java
@@ -32,9 +32,9 @@ public Flux searchByFullText(final String text) {
.or(PasteSchema.DATE_OF_EXPIRY).greaterThan(LocalDateTime.now())
)
.and(Criteria
- .where(PasteSchema.TITLE).like(text + '%')
+ .where(PasteSchema.TITLE).like('%' + text + '%')
.or(Criteria
- .where(PasteSchema.CONTENT).like(text + '%')
+ .where(PasteSchema.CONTENT).like('%' + text + '%')
.and(PasteSchema.IS_ENCRYPTED).isFalse()
)
);
diff --git a/frontend/src/api/client.ts b/frontend/src/api/client.ts
index 2782383..94ba078 100644
--- a/frontend/src/api/client.ts
+++ b/frontend/src/api/client.ts
@@ -1,6 +1,7 @@
import {PasteCreateCmd} from './model/PasteCreateCmd';
import {PasteListView} from './model/PasteListView';
import {PasteView} from './model/PasteView';
+import {PasteSearchView} from './model/PasteSearchView';
const HOST_DEVELOPMENT = 'localhost:3000';
@@ -53,7 +54,7 @@ const findAll = (): Promise> => {
.then(value => value.pastes);
}
-const searchAll = (term: string): Promise> => {
+const searchAll = (term: string): Promise> => {
const params = new URLSearchParams([['term', term]]);
const url = new URL('/api/v1/paste/search?' + params.toString(), apiBaseUrl());
diff --git a/frontend/src/api/model/PasteListView.ts b/frontend/src/api/model/PasteListView.ts
index 4ef1f6c..9764a9a 100644
--- a/frontend/src/api/model/PasteListView.ts
+++ b/frontend/src/api/model/PasteListView.ts
@@ -7,7 +7,3 @@ export type PasteListView = {
dateCreated: string
dateOfExpiry?: string
}
-
-export type = PasteList {
- pastes: Array
-}
diff --git a/frontend/src/api/model/PasteSearchView.ts b/frontend/src/api/model/PasteSearchView.ts
new file mode 100644
index 0000000..3c3fc9b
--- /dev/null
+++ b/frontend/src/api/model/PasteSearchView.ts
@@ -0,0 +1,9 @@
+
+export type PasteSearchView = {
+ id: string
+ title?: string
+ highlight: string
+ sizeInBytes: number
+ dateCreated: string
+ dateOfExpiry?: string
+}
diff --git a/frontend/src/pages/Search.tsx b/frontend/src/pages/Search.tsx
index 860a2b1..3e6fd88 100644
--- a/frontend/src/pages/Search.tsx
+++ b/frontend/src/pages/Search.tsx
@@ -1,9 +1,35 @@
-import {JSX} from 'solid-js';
+import {JSX, createResource} from 'solid-js';
+import {A, useNavigate, useLocation} from '@solidjs/router';
+import ApiClient from '../api/client';
+import {toDateTimeString} from '../datetime/DateTimeUtil';
const Search: () => JSX.Element = () => {
+
+ const navigate = useNavigate();
+
+ const location = useLocation();
+
+ const [pastes, { mutate, refetch }] = createResource(() => location.query.q, (term) => ApiClient.searchAll(term));
+
return (
<>
Search
+ Nothing found
}>
+
+ {item =>
+ -
+
{item.title || 'Untitled' }
+
+ Created: |
+ Expires: |
+ Size: {item.sizeInBytes} bytes
+
+ {item.content}
+
+ }
+
+
+
>
)
}