upend/webui/src/views/Search.svelte

178 lines
3.9 KiB
Svelte
Raw Normal View History

2021-12-21 14:32:47 +01:00
<script lang="ts">
import debounce from "lodash/debounce";
import { Readable, readable } from "svelte/store";
2022-01-14 22:05:17 +01:00
import type { UpEntry, UpListing, UpObject } from "upend";
import Spinner from "../components/utils/Spinner.svelte";
import UpEntryDisplay from "../components/display/UpEntry.svelte";
import UpObjectDisplay from "../components/display/UpObject.svelte";
import UpObjectCard from "../components/display/UpObjectCard.svelte";
2022-01-16 19:53:40 +01:00
import { useNavigate } from "svelte-navigator";
import { baseSearch, createLabelled, getObjects } from "../util/search";
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);
let result: Readable<UpListing> = readable();
let error: Readable<unknown> = readable();
$: if (debouncedQuery.length) {
({ result, error } = baseSearch(debouncedQuery));
exactHits = [];
2022-01-14 22:05:17 +01:00
}
2022-01-16 19:29:15 +01:00
2022-01-14 22:05:17 +01:00
$: objects = getObjects($result?.entries || []);
2022-01-16 19:29:15 +01:00
let exactHits = [];
2022-01-16 19:29:15 +01:00
function onResolved(address: string, ids: string[]) {
if (ids.some((id) => id.toLowerCase() === query.toLowerCase())) {
if (!exactHits.includes(address)) {
exactHits.push(address);
exactHits = exactHits;
}
}
}
2022-01-16 19:53:40 +01:00
async function create() {
const createdAddress = await createLabelled(query);
navigate(`/browse/${createdAddress}`);
2022-01-16 19:53:40 +01:00
}
2021-12-21 14:32:47 +01:00
</script>
<div>
2022-01-14 22:05:17 +01:00
{#if !$error}
2022-01-17 16:59:12 +01:00
<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>
2022-01-14 22:05:17 +01:00
{#if $result}
2022-01-16 18:53:18 +01:00
<section class="objects">
{#await objects}
2022-01-16 19:53:40 +01:00
<h2>Objects</h2>
2022-01-14 22:05:17 +01:00
<Spinner />
2022-01-16 18:53:18 +01:00
{:then objects}
2022-01-16 19:53:40 +01:00
{#if objects.length}
<h2>Objects</h2>
<ul>
{#each objects as [address, _]}
2022-01-16 19:53:40 +01:00
<li>
<UpObjectDisplay
{address}
2022-01-16 19:55:09 +01:00
link
2022-01-16 19:53:40 +01:00
on:resolved={(ids) => onResolved(address, ids.detail)}
/>
</li>
{/each}
</ul>
{/if}
2022-01-16 18:53:18 +01:00
{/await}
</section>
2022-01-16 19:53:40 +01:00
<section class="raw">
{#if $result?.entries.length}
2022-01-14 22:05:17 +01:00
<h2>Raw results</h2>
<ul>
{#each $result.entries as entry}
2022-01-14 22:05:17 +01:00
<li><UpEntryDisplay {entry} /></li>
{/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">
<Spinner />
</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 {
li {
margin: 0.5em auto;
max-width: 66em;
}
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>