Added basic front-end for the search API for testing.
This commit is contained in:
parent
07be6b3878
commit
79084dbb9e
|
@ -11,10 +11,10 @@ import java.util.ArrayList;
|
||||||
public class DPackageSearch {
|
public class DPackageSearch {
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
Path indexPath = Path.of("package-index");
|
Path indexPath = Path.of("package-index");
|
||||||
startIndexerThread(new IndexGenerator(
|
// startIndexerThread(new IndexGenerator(
|
||||||
new DubRegistryPackageFetcher(),
|
// new DubRegistryPackageFetcher(),
|
||||||
() -> new LucenePackageIndexer(indexPath)
|
// () -> new LucenePackageIndexer(indexPath)
|
||||||
));
|
// ));
|
||||||
new WebApiRunner(new LucenePackageSearcher(indexPath)).run();
|
new WebApiRunner(new LucenePackageSearcher(indexPath)).run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ import org.eclipse.jetty.server.*;
|
||||||
import org.eclipse.jetty.util.Callback;
|
import org.eclipse.jetty.util.Callback;
|
||||||
import org.eclipse.jetty.util.thread.QueuedThreadPool;
|
import org.eclipse.jetty.util.thread.QueuedThreadPool;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.net.URLDecoder;
|
import java.net.URLDecoder;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
@ -63,6 +64,13 @@ public final class WebApiRunner extends Handler.Abstract implements Runnable {
|
||||||
byte[] responseBody = objectMapper.writeValueAsBytes(results);
|
byte[] responseBody = objectMapper.writeValueAsBytes(results);
|
||||||
response.write(true, ByteBuffer.wrap(responseBody), callback);
|
response.write(true, ByteBuffer.wrap(responseBody), callback);
|
||||||
}
|
}
|
||||||
|
} else if (uri.getPath().equalsIgnoreCase("/index.html") || uri.getPath().equalsIgnoreCase("/")) {
|
||||||
|
try (var in = WebApiRunner.class.getClassLoader().getResourceAsStream("index.html")) {
|
||||||
|
if (in == null) throw new IOException("Resource doesn't exist.");
|
||||||
|
response.setStatus(HttpStatus.OK_200);
|
||||||
|
response.getHeaders().add("Content-Type", "text/html; charset=utf-8");
|
||||||
|
response.write(true, ByteBuffer.wrap(in.readAllBytes()), callback);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
response.setStatus(HttpStatus.NOT_FOUND_404);
|
response.setStatus(HttpStatus.NOT_FOUND_404);
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,12 +55,14 @@ public class LucenePackageSearcher implements PackageSearcher {
|
||||||
BooleanQuery.Builder queryBuilder = new BooleanQuery.Builder();
|
BooleanQuery.Builder queryBuilder = new BooleanQuery.Builder();
|
||||||
String[] searchTerms = queryText.toLowerCase().split("\\s+");
|
String[] searchTerms = queryText.toLowerCase().split("\\s+");
|
||||||
|
|
||||||
|
// We define a set of weighted fields that we will add prefix queries for.
|
||||||
Map<String, Float> weightedFields = Map.of(
|
Map<String, Float> weightedFields = Map.of(
|
||||||
"name", 1f,
|
"name", 1f,
|
||||||
"description", 0.5f,
|
"description", 0.5f,
|
||||||
"readme", 0.25f
|
"readme", 0.25f
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Only consider the first 5 search terms, and add a prefix query for each term for them.
|
||||||
for (int i = 0; i < Math.min(5, searchTerms.length); i++) {
|
for (int i = 0; i < Math.min(5, searchTerms.length); i++) {
|
||||||
for (var entry : weightedFields.entrySet()) {
|
for (var entry : weightedFields.entrySet()) {
|
||||||
String fieldName = entry.getKey();
|
String fieldName = entry.getKey();
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>D Package Search</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<h1>D Package Search</h1>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Use this site to search for D packages!
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<input id="search-input" type="text" placeholder="Search for a package..."/>
|
||||||
|
|
||||||
|
<div id="result-container"></div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
async function fetchResults(query) {
|
||||||
|
const response = await fetch("/search?query=" + encodeURIComponent(query))
|
||||||
|
return await response.json();
|
||||||
|
}
|
||||||
|
|
||||||
|
function showResults(results) {
|
||||||
|
const container = document.getElementById("result-container");
|
||||||
|
container.innerHTML = "";
|
||||||
|
for (let i = 0; i < results.length; i++) {
|
||||||
|
const element = document.createElement("div");
|
||||||
|
const header = document.createElement("h3");
|
||||||
|
header.innerText = results[i].name;
|
||||||
|
element.appendChild(header);
|
||||||
|
const link = document.createElement("a");
|
||||||
|
link.href = results[i].url;
|
||||||
|
link.innerText = "Link to package";
|
||||||
|
element.appendChild(link);
|
||||||
|
container.appendChild(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const searchInput = document.getElementById("search-input");
|
||||||
|
searchInput.addEventListener("keyup", async () => {
|
||||||
|
const query = searchInput.value;
|
||||||
|
if (query.length < 1) {
|
||||||
|
showResults([]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const results = await fetchResults(query);
|
||||||
|
showResults(results);
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Reference in New Issue