Mercurial > code > home > repos > sco-bot
view web/src/main.ts @ 14:b9c2b7fedbcd
fix up deployment and connect ui to server again
author | drewp@bigasterisk.com |
---|---|
date | Thu, 11 Jul 2024 22:11:41 -0700 |
parents | f23b21bd0fce |
children |
line wrap: on
line source
import { SlTextarea, setBasePath } from "@shoelace-style/shoelace"; import "@shoelace-style/shoelace/dist/themes/light.css"; import { LitElement, PropertyValueMap, css, html } from "lit"; import { customElement, queryAsync, state } from "lit/decorators.js"; import { unsafeHTML } from "lit/directives/unsafe-html.js"; setBasePath("@fs/opt/node_modules/@shoelace-style/shoelace/dist"); interface Doc { sourceTitle: string phrase: string snippetHtml: string } @customElement("sco-search-page") export class ScoSearchPage extends LitElement { static styles = [ css` :host { display: flex; flex-direction: column; height: 100vh; } form { display: flex; flex-direction: row; align-items: flex-end; margin: 0 10% 0 100px; } sl-textarea { width: 100%; } :host > * { padding: 5px; } section#results { background-color: #ffffffde; flex-grow: 1; display: flex; flex-direction: column; overflow: hidden; margin-bottom: 15px; margin-left: 110px; } img.bot { width: 237px; position: absolute; left: -33px; top: -22px; z-index: -1; } dt { color: blue; } dd { margin-bottom: 25px; } `, ]; @state() query: string = "climate"; @state() results: Doc[] = []; @state() queryError: string = ""; @queryAsync("sl-textarea") queryEl?: Promise<SlTextarea>; protected async firstUpdated(_changedProperties: PropertyValueMap<any> | Map<PropertyKey, unknown>) { super.firstUpdated(_changedProperties); await this.pressingEnterSubmitsForm(); this.queryParamToProperty(); window.addEventListener("popstate", (event) => { this.queryParamToProperty(); }); this.submit().catch(console.error); } private async pressingEnterSubmitsForm() { const ta = (await this.queryEl)?.shadowRoot?.querySelector("textarea"); ta?.addEventListener("keydown", (event: KeyboardEvent) => { if (event.code == "Enter" && !event.shiftKey) { event.preventDefault(); this.submit(); } }); } private queryParamToProperty() { const urlParams = new URLSearchParams(window.location.search); const qParam = urlParams.get("q"); if (qParam) { this.query = qParam; } } private async propertyToQueryParam() { const currentUrl = new URL(window.location.href); const q = await this.getCurrentQuery(); if (currentUrl.searchParams.get("q") !== q) { currentUrl.searchParams.set("q", q); const newUrl = currentUrl.toString(); history.pushState({}, document.title, newUrl); } } render() { return html` <section id="query"> <img class="bot" src="sco-bot.jpg" /> <form> <sl-textarea .value=${this.query} rows="1" resize="auto" label="Query" enterkeyhint="search" autocapitalize="off" autofocus="true"></sl-textarea> <sl-button variant="primary" @click=${this.submit}>Submit</sl-button> <div>${this.queryError}</div> </form> </section> <section id="results"> <dl> ${this.results.map( (r: Doc) => html`<dt>${r.sourceTitle}</dt> <dd>${unsafeHTML(r.snippetHtml)}</dd>` )} </dl> <div>Matching results: ${this.results.length}</div> </section> `; } async getCurrentQuery(): Promise<string> { return (await this.queryEl)!.value || ""; } async submit() { await this.propertyToQueryParam(); this.results = []; const sentQ = await this.getCurrentQuery(); const resp = await fetch("query?" + new URLSearchParams({ q: sentQ })); if (sentQ != (await this.getCurrentQuery())) { // old result- ignore return; } this.results = (await resp.json()).results; this.requestUpdate(); } }