adds trail recommendation
This commit is contained in:
40
db/main.go
40
db/main.go
@@ -3,14 +3,17 @@ package main
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
"math/rand/v2"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/labstack/echo/v5"
|
"github.com/labstack/echo/v5"
|
||||||
"github.com/meilisearch/meilisearch-go"
|
"github.com/meilisearch/meilisearch-go"
|
||||||
"github.com/pocketbase/dbx"
|
"github.com/pocketbase/dbx"
|
||||||
"github.com/pocketbase/pocketbase"
|
"github.com/pocketbase/pocketbase"
|
||||||
|
"github.com/pocketbase/pocketbase/apis"
|
||||||
"github.com/pocketbase/pocketbase/core"
|
"github.com/pocketbase/pocketbase/core"
|
||||||
"github.com/pocketbase/pocketbase/forms"
|
"github.com/pocketbase/pocketbase/forms"
|
||||||
"github.com/pocketbase/pocketbase/models"
|
"github.com/pocketbase/pocketbase/models"
|
||||||
@@ -281,13 +284,13 @@ func changeUserEmailHandler(app *pocketbase.PocketBase) func(e *core.RecordReque
|
|||||||
|
|
||||||
func onBeforeServeHandler(app *pocketbase.PocketBase, client meilisearch.ServiceManager) func(e *core.ServeEvent) error {
|
func onBeforeServeHandler(app *pocketbase.PocketBase, client meilisearch.ServiceManager) func(e *core.ServeEvent) error {
|
||||||
return func(e *core.ServeEvent) error {
|
return func(e *core.ServeEvent) error {
|
||||||
registerRoutes(e, client)
|
registerRoutes(e, app, client)
|
||||||
return bootstrapData(app, client)
|
return bootstrapData(app, client)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func registerRoutes(e *core.ServeEvent, client meilisearch.ServiceManager) {
|
func registerRoutes(e *core.ServeEvent, app *pocketbase.PocketBase, client meilisearch.ServiceManager) {
|
||||||
e.Router.GET("/public/search/token", func(c echo.Context) error {
|
e.Router.GET("/public/search/token", func(c echo.Context) error {
|
||||||
searchRules := map[string]interface{}{
|
searchRules := map[string]interface{}{
|
||||||
"cities500": map[string]string{},
|
"cities500": map[string]string{},
|
||||||
@@ -301,6 +304,39 @@ func registerRoutes(e *core.ServeEvent, client meilisearch.ServiceManager) {
|
|||||||
}
|
}
|
||||||
return c.JSON(http.StatusOK, map[string]string{"token": token})
|
return c.JSON(http.StatusOK, map[string]string{"token": token})
|
||||||
})
|
})
|
||||||
|
e.Router.GET("/trail/recommend", func(c echo.Context) error {
|
||||||
|
qSize := c.QueryParam("size")
|
||||||
|
size, err := strconv.Atoi(qSize)
|
||||||
|
if err != nil {
|
||||||
|
size = 4
|
||||||
|
}
|
||||||
|
user, success := c.Get(apis.ContextAuthRecordKey).(*models.Record)
|
||||||
|
|
||||||
|
userId := ""
|
||||||
|
if success {
|
||||||
|
userId = user.Id
|
||||||
|
}
|
||||||
|
trails, err := app.Dao().FindRecordsByFilter(
|
||||||
|
"trails",
|
||||||
|
"author = {:userId} || public = true || ({:userId} != '' && trail_share_via_trail.user ?= {:userId})",
|
||||||
|
"",
|
||||||
|
-1,
|
||||||
|
0,
|
||||||
|
dbx.Params{"userId": userId},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if len(trails) < size {
|
||||||
|
size = len(trails)
|
||||||
|
}
|
||||||
|
rand.Shuffle(len(trails), func(i, j int) {
|
||||||
|
trails[i], trails[j] = trails[j], trails[i]
|
||||||
|
})
|
||||||
|
randomTrails := trails[:size]
|
||||||
|
return c.JSON(http.StatusOK, randomTrails)
|
||||||
|
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func bootstrapData(app *pocketbase.PocketBase, client meilisearch.ServiceManager) error {
|
func bootstrapData(app *pocketbase.PocketBase, client meilisearch.ServiceManager) error {
|
||||||
|
|||||||
@@ -122,9 +122,9 @@
|
|||||||
alt="Empty state"
|
alt="Empty state"
|
||||||
/>
|
/>
|
||||||
{:else}
|
{:else}
|
||||||
{#each { length: Math.min(data.trails.length, 4) } as _, i}
|
{#each data.trails as trail}
|
||||||
<a href="/trail/view/{data.trails[i].id}">
|
<a href="/trail/view/{trail.id}">
|
||||||
<TrailCard trail={data.trails[i]}></TrailCard></a
|
<TrailCard {trail}></TrailCard></a
|
||||||
>
|
>
|
||||||
{/each}
|
{/each}
|
||||||
{/if}
|
{/if}
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import type { Trail } from "$lib/models/trail";
|
import type { Trail } from "$lib/models/trail";
|
||||||
import { categories_index } from "$lib/stores/category_store";
|
import { categories_index } from "$lib/stores/category_store";
|
||||||
import { trails_index } from "$lib/stores/trail_store";
|
import { trails_recommend } from "$lib/stores/trail_store";
|
||||||
import type { ServerLoad } from "@sveltejs/kit";
|
import type { ServerLoad } from "@sveltejs/kit";
|
||||||
|
|
||||||
export const load: ServerLoad = async ({ params, locals, fetch }) => {
|
export const load: ServerLoad = async ({ params, locals, fetch }) => {
|
||||||
const trails: Trail[] = await trails_index(20, true, fetch)
|
const trails: Trail[] = await trails_recommend(4, fetch)
|
||||||
await categories_index(fetch)
|
await categories_index(fetch)
|
||||||
|
|
||||||
return {trails}
|
return { trails: trails ?? [] }
|
||||||
};
|
};
|
||||||
@@ -2,7 +2,7 @@ import { TrailCreateSchema } from '$lib/models/api/trail_schema';
|
|||||||
import type { Trail } from '$lib/models/trail';
|
import type { Trail } from '$lib/models/trail';
|
||||||
import { pb } from '$lib/pocketbase';
|
import { pb } from '$lib/pocketbase';
|
||||||
import { Collection, create, handleError, list } from '$lib/util/api_util';
|
import { Collection, create, handleError, list } from '$lib/util/api_util';
|
||||||
import { error, json, type RequestEvent } from '@sveltejs/kit';
|
import { json, type RequestEvent } from '@sveltejs/kit';
|
||||||
|
|
||||||
export async function GET(event: RequestEvent) {
|
export async function GET(event: RequestEvent) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { type TrailBoundingBox, type TrailFilterValues } from '$lib/models/trail';
|
import { type TrailBoundingBox, type TrailFilterValues } from '$lib/models/trail';
|
||||||
import { pb } from '$lib/pocketbase';
|
import { pb } from '$lib/pocketbase';
|
||||||
|
import { handleError } from '$lib/util/api_util';
|
||||||
import { error, json, type RequestEvent } from '@sveltejs/kit';
|
import { error, json, type RequestEvent } from '@sveltejs/kit';
|
||||||
|
|
||||||
export async function GET(event: RequestEvent) {
|
export async function GET(event: RequestEvent) {
|
||||||
@@ -15,6 +16,6 @@ export async function GET(event: RequestEvent) {
|
|||||||
const r = await pb.collection('trails_bounding_box').getOne<TrailBoundingBox>(pb.authStore.model!.id)
|
const r = await pb.collection('trails_bounding_box').getOne<TrailBoundingBox>(pb.authStore.model!.id)
|
||||||
return json(r)
|
return json(r)
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
throw error(e.status || 500, e);
|
throw handleError(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { type TrailFilterValues } from '$lib/models/trail';
|
import { type TrailFilterValues } from '$lib/models/trail';
|
||||||
import { pb } from '$lib/pocketbase';
|
import { pb } from '$lib/pocketbase';
|
||||||
|
import { handleError } from '$lib/util/api_util';
|
||||||
import { error, json, type RequestEvent } from '@sveltejs/kit';
|
import { error, json, type RequestEvent } from '@sveltejs/kit';
|
||||||
|
|
||||||
export async function GET(event: RequestEvent) {
|
export async function GET(event: RequestEvent) {
|
||||||
@@ -15,6 +16,6 @@ export async function GET(event: RequestEvent) {
|
|||||||
const r = await pb.collection('trails_filter').getOne<TrailFilterValues>(pb.authStore.model!.id)
|
const r = await pb.collection('trails_filter').getOne<TrailFilterValues>(pb.authStore.model!.id)
|
||||||
return json(r)
|
return json(r)
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
throw error(e.status || 500, e);
|
throw handleError(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
32
web/src/routes/api/v1/trail/recommend/+server.ts
Normal file
32
web/src/routes/api/v1/trail/recommend/+server.ts
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import { TrailRecommendSchema } from '$lib/models/api/trail_schema';
|
||||||
|
import type { Trail } from '$lib/models/trail';
|
||||||
|
import { pb } from '$lib/pocketbase';
|
||||||
|
import { handleError } from '$lib/util/api_util';
|
||||||
|
import { error, json, type RequestEvent } from '@sveltejs/kit';
|
||||||
|
|
||||||
|
export async function GET(event: RequestEvent) {
|
||||||
|
try {
|
||||||
|
const searchParams = Object.fromEntries(event.url.searchParams);
|
||||||
|
const safeSearchParams = TrailRecommendSchema.parse(searchParams);
|
||||||
|
|
||||||
|
const r = await event.fetch(pb.buildUrl("/trail/recommend?" + new URLSearchParams({
|
||||||
|
size: safeSearchParams.size?.toString() ?? ""
|
||||||
|
})));
|
||||||
|
|
||||||
|
const result: Trail[] = await r.json();
|
||||||
|
|
||||||
|
for (const t of result) {
|
||||||
|
if (!t.author || !pb.authStore.model) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!t.expand) {
|
||||||
|
t.expand = {} as any
|
||||||
|
}
|
||||||
|
t.expand!.author = await pb.collection("users_anonymous").getOne(t.author);
|
||||||
|
}
|
||||||
|
|
||||||
|
return json(result)
|
||||||
|
} catch (e: any) {
|
||||||
|
throw handleError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user