adds list search

This commit is contained in:
Christian Beutel
2025-01-26 17:28:38 +01:00
parent eda94f3003
commit f34fd7afed
20 changed files with 413 additions and 98 deletions

View File

@@ -5,6 +5,7 @@ import { type ListResult } from "pocketbase";
import { writable, type Writable } from "svelte/store";
import { fetchGPX } from "./trail_store";
import { APIError } from "$lib/util/api_util";
import type { Hits } from "meilisearch";
let lists: List[] = []
export const list: Writable<List | null> = writable(null)
@@ -34,6 +35,59 @@ export async function lists_index(filter?: ListFilter, page: number = 1, perPage
lists = result;
return { ...fetchedLists, items: result };
}
export async function lists_search_filter(filter: ListFilter, page: number = 1, perPage: number = 5, f: (url: RequestInfo | URL, config?: RequestInit) => Promise<Response> = fetch): Promise<ListResult<List>> {
const filterText = buildSearchFilterText(filter)
let r = await f("/api/v1/search/lists", {
method: "POST",
body: JSON.stringify({
q: filter.q,
options: {
filter: filterText, sort: filter.sort && filter.sortOrder ? [`${filter.sort}:${filter.sortOrder == "+" ? "asc" : "desc"}`] : [],
hitsPerPage: perPage,
page: page
}
}),
});
if (!r.ok) {
const response = await r.json();
throw new APIError(r.status, response.message, response.detail)
}
const searchResult: { page: number, totalPages: number, hits: Hits<Record<string, any>> } = await r.json();
const listIds = searchResult.hits.map((h: Record<string, any>) => h.id);
if (listIds.length == 0) {
return { items: [], page: searchResult.page, perPage, totalItems: 0, totalPages: searchResult.totalPages };
}
r = await f('/api/v1/list?' + new URLSearchParams({
expand: "trails,trails.waypoints,trails.category,list_share_via_list",
filter: `'${listIds.join(',')}'~id`,
sort: filter.sort && filter.sortOrder ? `${filter.sortOrder}${filter.sort}` : ''
}), {
method: 'GET',
})
if (!r.ok) {
const response = await r.json();
throw new APIError(r.status, response.message, response.detail)
}
const fetchedLists: ListResult<List> = await r.json();
const result = page > 1 ? [...lists, ...fetchedLists.items] : fetchedLists.items
lists = result;
return { ...fetchedLists, items: result };
}
@@ -78,7 +132,7 @@ export async function lists_create(list: List, avatar?: File) {
body: JSON.stringify(list),
})
if (!r.ok) {
if (!r.ok) {
const response = await r.json();
throw new APIError(r.status, response.message, response.detail)
}
@@ -181,17 +235,12 @@ export async function lists_delete(list: List) {
}
}
function buildFilterText(filter: ListFilter): string {
let filterText = `(name~"${filter.q}"||description~"${filter.q}")`
if (filter.author?.length) {
filterText += `&&author="${filter.author}"`
}
if (pb.authStore.model) {
if (filter.public === false && filter.shared === false) {
filterText += `&&author="${pb.authStore.model.id}"`
@@ -201,6 +250,40 @@ function buildFilterText(filter: ListFilter): string {
filterText += `&&(public=false||list_share_via_list.user="${pb.authStore.model.id}"||author="${pb.authStore.model.id}")`
}
}
return filterText
}
function buildSearchFilterText(filter: ListFilter): string {
let filterText: string = "";
if (filter.author?.length) {
filterText += `author = ${filter.author}`
}
if (filter.public !== undefined || filter.shared !== undefined) {
if (filterText.length) {
filterText += " AND "
}
filterText += "("
if (filter.public !== undefined) {
filterText += `(public = ${filter.public}`
if (!filter.author?.length || filter.author == pb.authStore.model?.id) {
filterText += ` OR author = ${pb.authStore.model?.id}`
}
filterText += ")"
}
if (filter.shared !== undefined) {
if (filter.shared === true) {
filterText += ` OR shares = ${pb.authStore.model?.id}`
} else {
filterText += ` AND NOT shares = ${pb.authStore.model?.id}`
}
}
filterText += ")"
}
return filterText
}

View File

@@ -17,7 +17,7 @@ export type TrailSearchResult = {
lat: number,
lon: number
}
auhtor: string;
author: string;
category: string;
completed: boolean;
created: number;
@@ -33,6 +33,16 @@ export type TrailSearchResult = {
public: boolean;
}
export type ListSearchResult = {
id: string;
author: string;
created: number;
description: string;
name: string;
public: boolean;
trails: string[]
}
type NominatimResponse = {
type: string
licence: string