adds meilisearch
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
<script lang="ts">
|
||||
import type { Trail } from "$lib/models/trail";
|
||||
import { currentUser } from "$lib/stores/user_store";
|
||||
import { formatMeters, formatTimeHHMM } from "$lib/util/format_util";
|
||||
import Dropdown from "../base/dropdown.svelte";
|
||||
|
||||
@@ -19,7 +20,9 @@
|
||||
<div>
|
||||
<div class="flex justify-between items-center">
|
||||
<h4 class="font-semibold text-lg">{trail.name}</h4>
|
||||
<Dropdown on:change items={dropdownItems}></Dropdown>
|
||||
{#if $currentUser && $currentUser.id == trail.author}
|
||||
<Dropdown on:change items={dropdownItems}></Dropdown>
|
||||
{/if}
|
||||
</div>
|
||||
<h5><i class="fa fa-location-dot mr-3"></i>{trail.location}</h5>
|
||||
</div>
|
||||
|
||||
10
web/src/lib/meilisearch.ts
Normal file
10
web/src/lib/meilisearch.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { PUBLIC_MEILISEARCH_URL } from '$env/static/public'
|
||||
import { PUBLIC_MEILISEARCH_API_KEY } from '$env/static/public'
|
||||
|
||||
import { MeiliSearch } from 'meilisearch'
|
||||
|
||||
export function createInstance() {
|
||||
return new MeiliSearch({ host: PUBLIC_MEILISEARCH_URL, apiKey: PUBLIC_MEILISEARCH_API_KEY })
|
||||
}
|
||||
|
||||
export const ms = createInstance()
|
||||
@@ -11,6 +11,8 @@ class Trail {
|
||||
distance?: number;
|
||||
elevation_gain?: number;
|
||||
duration?: number;
|
||||
lat?: number;
|
||||
lon?: number;
|
||||
thumbnail?: string;
|
||||
photos: string[];
|
||||
gpx?: string;
|
||||
@@ -22,6 +24,7 @@ class Trail {
|
||||
}
|
||||
tags?: string[];
|
||||
description?: string;
|
||||
author?: string;
|
||||
|
||||
_photoFiles: File[]
|
||||
|
||||
@@ -33,6 +36,8 @@ class Trail {
|
||||
distance?: number,
|
||||
elevation_gain?: number,
|
||||
duration?: number,
|
||||
lat?:number,
|
||||
lon?: number,
|
||||
thumbnail?: string,
|
||||
photos?: string[],
|
||||
gpx?: string,
|
||||
@@ -51,6 +56,8 @@ class Trail {
|
||||
this.distance = params?.distance;
|
||||
this.elevation_gain = params?.elevation_gain;
|
||||
this.duration = params?.duration;
|
||||
this.lat = params?.lat;
|
||||
this.lon = params?.lon;
|
||||
this.thumbnail = params?.thumbnail;
|
||||
this.photos = params?.photos ?? [];
|
||||
this.gpx = params?.gpx;
|
||||
|
||||
@@ -7,6 +7,7 @@ import { util } from "$lib/vendor/svelte-form-lib/util";
|
||||
import { writable, type Writable } from "svelte/store";
|
||||
import { summit_logs_create, summit_logs_delete, summit_logs_update } from "./summit_log_store";
|
||||
import { waypoints_create, waypoints_delete, waypoints_update } from "./waypoint_store";
|
||||
import { ms } from "$lib/meilisearch";
|
||||
|
||||
export const trails: Writable<Trail[]> = writable([])
|
||||
export const trail: Writable<Trail> = writable(new Trail(""));
|
||||
@@ -26,7 +27,7 @@ export async function trails_index() {
|
||||
}
|
||||
|
||||
export async function trails_show(id: string, loadGPX?: boolean) {
|
||||
const response: Trail = await pb.collection('trails').getOne<Trail>(id, { expand: "category,waypoints,summit_logs" })
|
||||
const response: Trail = await pb.collection('trails').getOne<Trail>(id, { expand: "category,waypoints,summit_logs" })
|
||||
|
||||
if (loadGPX) {
|
||||
const gpxData: string = await fetchGPX(response);
|
||||
@@ -91,6 +92,8 @@ export async function trails_create(trail: Trail, formData: { [key: string]: any
|
||||
.collection("trails")
|
||||
.update<Trail>(model.id!, { thumbnail: thumbnail });
|
||||
|
||||
index_trail(model);
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
@@ -169,7 +172,9 @@ export async function trails_update(oldTrail: Trail, newTrail: Trail, formData:
|
||||
|
||||
trail.set(model);
|
||||
|
||||
// return model;
|
||||
index_trail(model);
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
|
||||
@@ -231,3 +236,21 @@ function compareObjectArrays<T extends { id?: string }>(oldArray: T[], newArray:
|
||||
};
|
||||
}
|
||||
|
||||
function index_trail(trail: Trail) {
|
||||
ms.index('trails').addDocuments([
|
||||
{
|
||||
"id": trail.id,
|
||||
"name": trail.name,
|
||||
"description": trail.description,
|
||||
"location": trail.location,
|
||||
"distance": trail.distance,
|
||||
"elevation_gain": trail.elevation_gain,
|
||||
"duration": trail.duration,
|
||||
"category": trail.expand.category?.name,
|
||||
"_geo": {
|
||||
"lat": trail.lat,
|
||||
"lng": trail.lon,
|
||||
}
|
||||
}]);
|
||||
}
|
||||
|
||||
|
||||
@@ -27,14 +27,14 @@
|
||||
</script>
|
||||
|
||||
<section class="hero flex justify-center items-center" style="height: 50vh">
|
||||
<div class="relative text-gray-600">
|
||||
<div class="relative text-gray-600 mx-4">
|
||||
<span class="absolute inset-y-0 left-0 flex items-center pl-4">
|
||||
<i class="fa fa-search text-2xl"></i>
|
||||
</span>
|
||||
<input
|
||||
type="search"
|
||||
name="q"
|
||||
class="py-4 rounded-2xl pl-14 focus:outline-none text-2xl text-primary"
|
||||
class="w-80 sm:w-96 md:w-[32rem] py-4 rounded-2xl pl-14 focus:outline-none text-xl text-primary "
|
||||
placeholder="Search trails..."
|
||||
autocomplete="off"
|
||||
/>
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
import SummitLogModal from "$lib/components/summit_log/summit_log_modal.svelte";
|
||||
import WaypointCard from "$lib/components/waypoint/waypoint_card.svelte";
|
||||
import WaypointModal from "$lib/components/waypoint/waypoint_modal.svelte";
|
||||
import { ms } from "$lib/meilisearch";
|
||||
import { SummitLog } from "$lib/models/summit_log";
|
||||
import { Trail, trailSchema } from "$lib/models/trail";
|
||||
import { Waypoint } from "$lib/models/waypoint";
|
||||
@@ -105,63 +106,69 @@
|
||||
});
|
||||
|
||||
function addGPXLayer(gpx: string, addWaypoints: boolean = true) {
|
||||
gpxLayer?.remove();
|
||||
gpxLayer = new L.GPX(gpx, {
|
||||
async: true,
|
||||
gpx_options: {
|
||||
parseElements: [
|
||||
"track",
|
||||
"route",
|
||||
...(addWaypoints ? ["waypoint"] : []),
|
||||
],
|
||||
},
|
||||
marker_options: {
|
||||
wptIcons: {
|
||||
"": L.AwesomeMarkers.icon({
|
||||
icon: "circle",
|
||||
return new Promise<void>(function (resolve, reject) {
|
||||
gpxLayer?.remove();
|
||||
gpxLayer = new L.GPX(gpx, {
|
||||
async: true,
|
||||
gpx_options: {
|
||||
parseElements: [
|
||||
"track",
|
||||
"route",
|
||||
...(addWaypoints ? ["waypoint"] : []),
|
||||
],
|
||||
},
|
||||
marker_options: {
|
||||
wptIcons: {
|
||||
"": L.AwesomeMarkers.icon({
|
||||
icon: "circle",
|
||||
prefix: "fa",
|
||||
markerColor: "cadetblue",
|
||||
iconColor: "white",
|
||||
}) as Icon,
|
||||
},
|
||||
startIcon: L.AwesomeMarkers.icon({
|
||||
icon: "circle-half-stroke",
|
||||
prefix: "fa",
|
||||
markerColor: "cadetblue",
|
||||
iconColor: "white",
|
||||
}) as Icon,
|
||||
endIcon: L.AwesomeMarkers.icon({
|
||||
icon: "flag-checkered",
|
||||
prefix: "fa",
|
||||
markerColor: "cadetblue",
|
||||
iconColor: "white",
|
||||
}) as Icon,
|
||||
startIconUrl: "",
|
||||
endIconUrl: "",
|
||||
shadowUrl: "",
|
||||
},
|
||||
startIcon: L.AwesomeMarkers.icon({
|
||||
icon: "circle-half-stroke",
|
||||
prefix: "fa",
|
||||
markerColor: "cadetblue",
|
||||
iconColor: "white",
|
||||
}) as Icon,
|
||||
endIcon: L.AwesomeMarkers.icon({
|
||||
icon: "flag-checkered",
|
||||
prefix: "fa",
|
||||
markerColor: "cadetblue",
|
||||
iconColor: "white",
|
||||
}) as Icon,
|
||||
startIconUrl: "",
|
||||
endIconUrl: "",
|
||||
shadowUrl: "",
|
||||
},
|
||||
})
|
||||
.on("addpoint", function (e: any) {
|
||||
if (e.point_type === "start") {
|
||||
e.point.setZIndexOffset(1000);
|
||||
} else if (e.point_type === "waypoint") {
|
||||
const waypoint = new Waypoint(
|
||||
e.point._latlng.lat,
|
||||
e.point._latlng.lng,
|
||||
{ name: e.point.options.title, marker: e.point },
|
||||
);
|
||||
if (!$form.expand.waypoints) {
|
||||
})
|
||||
.on("addpoint", function (e: any) {
|
||||
if (e.point_type === "start") {
|
||||
e.point.setZIndexOffset(1000);
|
||||
$form.lat = e.point._latlng.lat;
|
||||
$form.lon = e.point._latlng.lng;
|
||||
} else if (e.point_type === "waypoint") {
|
||||
const waypoint = new Waypoint(
|
||||
e.point._latlng.lat,
|
||||
e.point._latlng.lng,
|
||||
{ name: e.point.options.title, marker: e.point },
|
||||
);
|
||||
if (!$form.expand.waypoints) {
|
||||
}
|
||||
$form.expand.waypoints.push(waypoint);
|
||||
}
|
||||
$form.expand.waypoints.push(waypoint);
|
||||
}
|
||||
})
|
||||
.on("loaded", function (e: LeafletEvent) {
|
||||
map.fitBounds(e.target.getBounds());
|
||||
$form.distance = e.target.get_distance();
|
||||
$form.elevation_gain = e.target.get_elevation_gain();
|
||||
$form.duration = e.target.get_total_time() / 1000 / 60;
|
||||
})
|
||||
.addTo(map);
|
||||
})
|
||||
.on("loaded", function (e: LeafletEvent) {
|
||||
map.fitBounds(e.target.getBounds());
|
||||
$form.distance = e.target.get_distance();
|
||||
$form.elevation_gain = e.target.get_elevation_gain();
|
||||
$form.duration = e.target.get_total_time() / 1000 / 60;
|
||||
resolve();
|
||||
})
|
||||
.on("error", reject)
|
||||
.addTo(map);
|
||||
});
|
||||
}
|
||||
|
||||
function openFileBrowser() {
|
||||
@@ -184,9 +191,14 @@
|
||||
|
||||
reader.readAsText(selectedFile);
|
||||
|
||||
reader.onload = function (e) {
|
||||
reader.onload = async function (e) {
|
||||
trail.set(new Trail(""));
|
||||
addGPXLayer(e.target?.result as string);
|
||||
await addGPXLayer(e.target?.result as string);
|
||||
console.log(await
|
||||
ms.index("cities500").search("", {
|
||||
filter: [`_geoRadius(${$form.lat}, ${$form.lon}, 100000000000)`],
|
||||
}),
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -368,6 +380,8 @@
|
||||
>
|
||||
<input type="hidden" name="duration" value={$form.duration} />
|
||||
</div>
|
||||
<input type="hidden" name="lat" value={$form.lat} />
|
||||
<input type="hidden" name="lon" value={$form.lon} />
|
||||
</div>
|
||||
<TextField
|
||||
name="name"
|
||||
|
||||
@@ -11,7 +11,7 @@ export const load: Load = async ({ params }) => {
|
||||
|
||||
let trail: Trail;
|
||||
if (params.id === "new") {
|
||||
trail = new Trail("", { category: categories[0] });
|
||||
trail = new Trail("", {category: categories[0]});
|
||||
} else {
|
||||
trail = await trails_show(params.id, true);
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
trails_delete,
|
||||
trails_index,
|
||||
} from "$lib/stores/trail_store";
|
||||
import { currentUser } from "$lib/stores/user_store";
|
||||
import { formatMeters, formatTimeHHMM } from "$lib/util/format_util";
|
||||
import { createMarkerFromWaypoint } from "$lib/util/leaflet_util";
|
||||
import type { Icon, Marker } from "leaflet";
|
||||
@@ -150,13 +151,15 @@
|
||||
{$trail.location}
|
||||
</h3>
|
||||
</div>
|
||||
<div class="absolute text-white bottom-8 right-8">
|
||||
<Dropdown
|
||||
size="2xl"
|
||||
items={dropdownItems}
|
||||
on:change={(e) => handleDropdownClick(e.detail)}
|
||||
></Dropdown>
|
||||
</div>
|
||||
{#if $currentUser && $currentUser.id == $trail.author}
|
||||
<div class="absolute text-white bottom-8 right-8">
|
||||
<Dropdown
|
||||
size="2xl"
|
||||
items={dropdownItems}
|
||||
on:change={(e) => handleDropdownClick(e.detail)}
|
||||
></Dropdown>
|
||||
</div>
|
||||
{/if}
|
||||
</section>
|
||||
<section
|
||||
class="grid grid-cols-2 sm:grid-cols-4 gap-y-4 justify-around py-8"
|
||||
|
||||
Reference in New Issue
Block a user