aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xbackend/server.py13
-rw-r--r--src/components/SearchModal.vue26
2 files changed, 27 insertions, 12 deletions
diff --git a/backend/server.py b/backend/server.py
index 15d0960..0786ee8 100755
--- a/backend/server.py
+++ b/backend/server.py
@@ -11,6 +11,7 @@ dbFile = "data/data.db"
imgDir = "../public/img/"
NODE_REQ_DEPTH = 1
# For a /node?name=name1 request, respond with name1's node, and descendent nodes in a subtree to some depth > 0
+SEARCH_SUGG_LIMIT = 5
usageInfo = f"usage: {sys.argv[0]}\n"
usageInfo += "Starts a server that listens for GET requests to http://" + hostname + ":" + str(port) + ".\n"
@@ -62,9 +63,15 @@ def nodeNameToFile(name, cur):
def lookupName(name):
cur = dbCon.cursor()
results = []
- for row in cur.execute("SELECT name, alt_name FROM names WHERE alt_name = ?", (name,)):
- results.append(row[0])
- return json.dumps(results)
+ hasMore = False
+ for row in cur.execute(
+ "SELECT DISTINCT name, alt_name FROM names WHERE alt_name LIKE ? LIMIT ?",
+ (name + "%", SEARCH_SUGG_LIMIT + 1)):
+ results.append({"name": row[0], "altName": row[1]})
+ if len(results) > SEARCH_SUGG_LIMIT:
+ hasMore = True
+ del results[-1]
+ return json.dumps([results, hasMore])
class DbServer(BaseHTTPRequestHandler):
def do_GET(self):
diff --git a/src/components/SearchModal.vue b/src/components/SearchModal.vue
index 1005b14..6d23dc2 100644
--- a/src/components/SearchModal.vue
+++ b/src/components/SearchModal.vue
@@ -4,11 +4,15 @@ import SearchIcon from './icon/SearchIcon.vue';
import {LayoutNode} from '../layout';
import type {TolMap} from '../tol';
+type SearchSugg = {name: string, altName: string}; // Represents a search string suggestion
+type SearchSuggResponse = [SearchSugg[], boolean]; // Holds search suggestions and an indication of if there was more
+
// Displays a search box, and sends search requests
export default defineComponent({
data(){
return {
- searchSuggs: [] as string[], // Holds suggestions for the search string
+ searchSuggs: [] as SearchSugg[],
+ searchHasMoreSuggs: false,
focusedSuggIdx: null as null | number, // Denotes a search-suggestion selected using the arrow keys
lastSuggReqId: 0, // Used to prevent late search-suggestion server-responses from taking effect
};
@@ -26,10 +30,10 @@ export default defineComponent({
onEnter(){
// Check for a focused search-suggestion
if (this.focusedSuggIdx != null){
- this.resolveSearch(this.searchSuggs[this.focusedSuggIdx]);
+ this.resolveSearch(this.searchSuggs[this.focusedSuggIdx].name);
return;
}
- // Ask server if input valid is valid name
+ // Get tol-node-name from server
let input = this.$refs.searchInput as HTMLInputElement;
let url = new URL(window.location.href);
url.pathname = '/data/search';
@@ -44,7 +48,7 @@ export default defineComponent({
input.offsetWidth; // Triggers reflow
input.classList.add('animate-red-then-fade');
} else {
- this.resolveSearch(results[0])
+ this.resolveSearch(results[0].name)
}
})
.catch(error => {
@@ -74,6 +78,7 @@ export default defineComponent({
// Check for empty input
if (input.value.length == 0){
this.searchSuggs = [];
+ this.searchHasMoreSuggs = false;
this.focusedSuggIdx = null;
return;
}
@@ -85,9 +90,10 @@ export default defineComponent({
let suggsId = this.lastSuggReqId;
fetch(url.toString())
.then(response => response.json())
- .then(results => {
+ .then((results: SearchSuggResponse) => {
if (this.lastSuggReqId == suggsId){
- this.searchSuggs = results;
+ this.searchSuggs = results[0];
+ this.searchHasMoreSuggs = results[1];
this.focusedSuggIdx = null;
}
})
@@ -130,11 +136,13 @@ export default defineComponent({
@keyup.enter="onEnter" @keyup.esc="onCloseClick"
@input="onInput" @keydown.down.prevent="onDownKey" @keydown.up.prevent="onUpKey"/>
<div class="absolute top-[100%] w-full">
- <div v-for="(item, idx) of searchSuggs" :key="item"
+ <div v-for="(sugg, idx) of searchSuggs"
:style="{backgroundColor: idx == focusedSuggIdx ? '#a3a3a3' : 'white'}"
- class="bg-white border p-1 hover:underline hover:cursor-pointer" @click="resolveSearch(item)">
- {{item}}
+ class="bg-white border p-1 hover:underline hover:cursor-pointer"
+ @click="resolveSearch(sugg.name)">
+ {{sugg.name == sugg.altName ? sugg.name : `${sugg.altName} (aka ${sugg.name})`}}
</div>
+ <div v-if="searchHasMoreSuggs" class="bg-white px-1 text-center border">...</div>
</div>
</div>
<search-icon @click.stop="onEnter" ref="searchIcon"