2021-12-21 14:32:47 +01:00
|
|
|
<script lang="ts">
|
|
|
|
import debounce from "lodash/debounce";
|
2022-08-01 21:08:34 +02:00
|
|
|
import { type Readable, readable } from "svelte/store";
|
2022-01-30 16:50:23 +01:00
|
|
|
import type { UpListing } from "upend";
|
2022-01-14 22:05:17 +01:00
|
|
|
import Spinner from "../components/utils/Spinner.svelte";
|
|
|
|
import UpEntryDisplay from "../components/display/UpEntry.svelte";
|
|
|
|
import UpObjectCard from "../components/display/UpObjectCard.svelte";
|
2022-01-16 19:53:40 +01:00
|
|
|
import { useNavigate } from "svelte-navigator";
|
2022-03-20 22:35:34 +01:00
|
|
|
import { baseSearch, createLabelled } from "../util/search";
|
2022-02-04 22:44:40 +01:00
|
|
|
import { updateTitle } from "../util/title";
|
2022-03-02 09:21:51 +01:00
|
|
|
import { query as queryFn } from "../lib/entity";
|
2022-03-20 22:35:34 +01:00
|
|
|
import AttributeView from "../components/AttributeView.svelte";
|
|
|
|
import { queryOnce } from "../lib/api";
|
2022-09-04 23:29:41 +02:00
|
|
|
import EntryList from "../components/widgets/EntryList.svelte";
|
|
|
|
import Gallery from "../components/widgets/Gallery.svelte";
|
|
|
|
import type { Widget } from "src/lib/types";
|
2022-09-05 00:04:44 +02:00
|
|
|
import { matchSorter } from "match-sorter";
|
2022-01-16 19:53:40 +01:00
|
|
|
const navigate = useNavigate();
|
|
|
|
|
2021-12-21 14:32:47 +01:00
|
|
|
export let query: string;
|
|
|
|
|
|
|
|
let debouncedQuery = "";
|
|
|
|
const updateQuery = debounce((query: string) => {
|
|
|
|
debouncedQuery = query;
|
|
|
|
}, 200);
|
|
|
|
$: updateQuery(query);
|
|
|
|
|
2022-03-02 09:21:51 +01:00
|
|
|
$: looksLikeQuery =
|
|
|
|
debouncedQuery.startsWith("(") && debouncedQuery.endsWith(")");
|
|
|
|
|
2021-12-21 14:32:47 +01:00
|
|
|
let result: Readable<UpListing> = readable();
|
|
|
|
let error: Readable<unknown> = readable();
|
|
|
|
$: if (debouncedQuery.length) {
|
2022-03-02 09:21:51 +01:00
|
|
|
({ result, error } = looksLikeQuery
|
|
|
|
? queryFn(debouncedQuery)
|
|
|
|
: baseSearch(debouncedQuery));
|
2022-01-27 20:56:00 +01:00
|
|
|
exactHits = [];
|
2022-01-14 22:05:17 +01:00
|
|
|
}
|
2022-01-16 19:29:15 +01:00
|
|
|
|
2022-03-20 22:35:34 +01:00
|
|
|
$: objects = ($result?.entries || []).filter((e) => e.attribute === "LBL");
|
2022-09-05 00:04:44 +02:00
|
|
|
$: sortedObjects = matchSorter(objects, debouncedQuery, {
|
|
|
|
keys: ["value.c"],
|
|
|
|
});
|
2022-03-20 22:35:34 +01:00
|
|
|
|
|
|
|
let exactHits: string[] = [];
|
|
|
|
$: {
|
2022-03-30 10:20:27 +02:00
|
|
|
const addressesString = objects.map((e) => `@${e.entity}`).join(" ");
|
2022-03-20 22:35:34 +01:00
|
|
|
queryOnce(`(matches (in ${addressesString}) "LBL" ? )`).then(
|
|
|
|
(labelListing) => {
|
|
|
|
exactHits = labelListing.entries
|
|
|
|
.filter(
|
|
|
|
(e) => String(e.value.c).toLowerCase() === query.toLowerCase()
|
|
|
|
)
|
|
|
|
.map((e) => e.entity);
|
2022-01-16 19:29:15 +01:00
|
|
|
}
|
2022-03-20 22:35:34 +01:00
|
|
|
);
|
2022-01-16 19:29:15 +01:00
|
|
|
}
|
2022-01-16 19:53:40 +01:00
|
|
|
|
|
|
|
async function create() {
|
2022-01-27 20:56:00 +01:00
|
|
|
const createdAddress = await createLabelled(query);
|
|
|
|
navigate(`/browse/${createdAddress}`);
|
2022-01-16 19:53:40 +01:00
|
|
|
}
|
2022-02-04 22:44:40 +01:00
|
|
|
|
|
|
|
$: updateTitle("Search", query);
|
2022-03-20 22:35:34 +01:00
|
|
|
|
2022-09-04 23:29:41 +02:00
|
|
|
const searchWidgets: Widget[] = [
|
|
|
|
{
|
|
|
|
name: "list-table",
|
|
|
|
icon: "list-ul",
|
|
|
|
components: [
|
|
|
|
{
|
2022-09-05 00:04:44 +02:00
|
|
|
component: Gallery,
|
|
|
|
props: (entries) => {
|
|
|
|
return {
|
|
|
|
entities: entries.map((e) => e.entity),
|
|
|
|
sort: false,
|
|
|
|
thumbnails: false,
|
|
|
|
};
|
2022-09-04 23:29:41 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
],
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "gallery-view",
|
|
|
|
icon: "image",
|
|
|
|
components: [
|
|
|
|
{
|
|
|
|
component: Gallery,
|
|
|
|
props: (entries) => {
|
|
|
|
return {
|
|
|
|
entities: entries.map((e) => e.entity),
|
2022-09-05 00:04:44 +02:00
|
|
|
sort: false,
|
|
|
|
thumbnails: true,
|
2022-09-04 23:29:41 +02:00
|
|
|
};
|
|
|
|
},
|
|
|
|
},
|
|
|
|
],
|
|
|
|
},
|
|
|
|
];
|
2022-09-05 00:07:23 +02:00
|
|
|
let lastWidget: string;
|
2021-12-21 14:32:47 +01:00
|
|
|
</script>
|
|
|
|
|
|
|
|
<div>
|
2022-01-14 22:05:17 +01:00
|
|
|
{#if !$error}
|
2022-03-02 09:21:51 +01:00
|
|
|
{#if !looksLikeQuery}
|
|
|
|
<section class="exact">
|
|
|
|
{#if exactHits.length}
|
|
|
|
<ul>
|
|
|
|
{#each exactHits as address}
|
|
|
|
<li>
|
|
|
|
<UpObjectCard {address} --width="100%" --height="100%" />
|
|
|
|
</li>
|
|
|
|
{/each}
|
|
|
|
</ul>
|
|
|
|
{:else}
|
|
|
|
<div class="create">
|
|
|
|
<div>Create new object?</div>
|
|
|
|
<button class="create-object" on:click={create}>"{query}"</button>
|
|
|
|
</div>
|
|
|
|
{/if}
|
|
|
|
</section>
|
|
|
|
{/if}
|
2022-01-14 22:05:17 +01:00
|
|
|
{#if $result}
|
2022-01-16 18:53:18 +01:00
|
|
|
<section class="objects">
|
2022-09-05 00:04:44 +02:00
|
|
|
{#if sortedObjects.length}
|
2022-01-16 19:53:40 +01:00
|
|
|
<h2>Objects</h2>
|
2022-09-05 00:04:44 +02:00
|
|
|
<AttributeView
|
|
|
|
--current-background="var(--background)"
|
|
|
|
entries={sortedObjects}
|
|
|
|
widgets={searchWidgets}
|
2022-09-05 00:07:23 +02:00
|
|
|
initialWidget={lastWidget}
|
|
|
|
on:widgetSwitched={(ev) => {
|
|
|
|
lastWidget = ev.detail;
|
|
|
|
}}
|
2022-09-05 00:04:44 +02:00
|
|
|
/>
|
|
|
|
{/if}
|
2022-01-16 18:53:18 +01:00
|
|
|
</section>
|
|
|
|
|
2022-01-16 19:53:40 +01:00
|
|
|
<section class="raw">
|
2022-01-27 20:56:00 +01:00
|
|
|
{#if $result?.entries.length}
|
2022-01-14 22:05:17 +01:00
|
|
|
<h2>Raw results</h2>
|
|
|
|
<ul>
|
2022-01-27 20:56:00 +01:00
|
|
|
{#each $result.entries as entry}
|
2022-03-23 12:36:35 +01:00
|
|
|
<li><UpEntryDisplay {entry} resolve={false} /></li>
|
2022-01-14 22:05:17 +01:00
|
|
|
{/each}
|
|
|
|
</ul>
|
2022-01-16 19:53:40 +01:00
|
|
|
{:else}
|
|
|
|
<div class="global">No results found.</div>
|
|
|
|
{/if}
|
|
|
|
</section>
|
2022-01-14 22:05:17 +01:00
|
|
|
{:else}
|
|
|
|
<div class="global">
|
2022-02-06 12:20:56 +01:00
|
|
|
<Spinner centered />
|
2022-01-14 22:05:17 +01:00
|
|
|
</div>
|
|
|
|
{/if}
|
|
|
|
{:else}
|
2022-01-16 19:53:40 +01:00
|
|
|
<div class="error global">
|
2022-01-14 22:05:17 +01:00
|
|
|
{$error}
|
|
|
|
</div>
|
2021-12-21 14:32:47 +01:00
|
|
|
{/if}
|
|
|
|
</div>
|
2022-01-13 19:08:36 +01:00
|
|
|
|
|
|
|
<style lang="scss">
|
|
|
|
h2 {
|
|
|
|
text-align: center;
|
|
|
|
}
|
|
|
|
|
|
|
|
ul {
|
|
|
|
list-style: none;
|
|
|
|
margin: 0;
|
2022-01-14 22:05:17 +01:00
|
|
|
padding: 0;
|
2022-01-13 19:08:36 +01:00
|
|
|
}
|
2022-01-14 22:05:17 +01:00
|
|
|
|
2022-01-16 19:29:15 +01:00
|
|
|
.exact {
|
2022-01-17 16:59:12 +01:00
|
|
|
margin-top: 1rem;
|
|
|
|
|
2022-01-16 18:53:18 +01:00
|
|
|
ul {
|
2022-01-16 19:29:15 +01:00
|
|
|
display: flex;
|
2022-01-16 18:53:18 +01:00
|
|
|
gap: 1rem;
|
2022-01-16 19:29:15 +01:00
|
|
|
justify-content: center;
|
|
|
|
flex-wrap: wrap;
|
2022-01-16 18:53:18 +01:00
|
|
|
|
|
|
|
margin: 0 1rem;
|
|
|
|
}
|
|
|
|
|
|
|
|
li {
|
|
|
|
width: 14rem;
|
|
|
|
height: 8rem;
|
|
|
|
}
|
2022-01-16 19:29:15 +01:00
|
|
|
|
|
|
|
.create {
|
|
|
|
text-align: center;
|
|
|
|
}
|
2022-01-16 19:53:40 +01:00
|
|
|
|
|
|
|
.create-object {
|
|
|
|
display: inline-block;
|
|
|
|
color: var(--foreground);
|
|
|
|
background: var(--background-lighter);
|
|
|
|
border: 1px solid var(--foreground);
|
|
|
|
border-radius: 4px;
|
|
|
|
padding: 0.2em;
|
|
|
|
font-size: 1.25em;
|
|
|
|
cursor: pointer;
|
2022-01-17 16:59:12 +01:00
|
|
|
margin-top: 1rem;
|
2022-01-16 19:53:40 +01:00
|
|
|
}
|
2022-01-16 19:29:15 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
.objects {
|
2022-03-20 22:35:34 +01:00
|
|
|
max-width: 66em;
|
|
|
|
margin: auto;
|
2022-01-16 18:53:18 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
.raw {
|
|
|
|
li {
|
|
|
|
margin: 1em auto;
|
|
|
|
max-width: 66em;
|
|
|
|
}
|
2022-01-14 22:05:17 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
.global {
|
|
|
|
font-size: 48px;
|
|
|
|
position: absolute;
|
|
|
|
top: 50%;
|
|
|
|
left: 50%;
|
|
|
|
transform: translate(-50%, -50%);
|
2022-01-13 19:08:36 +01:00
|
|
|
}
|
|
|
|
</style>
|