Mercurial > code > home > repos > sco-bot
annotate 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 |
rev | line source |
---|---|
6 | 1 import { SlTextarea, setBasePath } from "@shoelace-style/shoelace"; |
2 import "@shoelace-style/shoelace/dist/themes/light.css"; | |
3 import { LitElement, PropertyValueMap, css, html } from "lit"; | |
4 import { customElement, queryAsync, state } from "lit/decorators.js"; | |
5 import { unsafeHTML } from "lit/directives/unsafe-html.js"; | |
6 setBasePath("@fs/opt/node_modules/@shoelace-style/shoelace/dist"); | |
7 | |
14
b9c2b7fedbcd
fix up deployment and connect ui to server again
drewp@bigasterisk.com
parents:
8
diff
changeset
|
8 interface Doc { |
b9c2b7fedbcd
fix up deployment and connect ui to server again
drewp@bigasterisk.com
parents:
8
diff
changeset
|
9 sourceTitle: string |
b9c2b7fedbcd
fix up deployment and connect ui to server again
drewp@bigasterisk.com
parents:
8
diff
changeset
|
10 phrase: string |
b9c2b7fedbcd
fix up deployment and connect ui to server again
drewp@bigasterisk.com
parents:
8
diff
changeset
|
11 snippetHtml: string |
b9c2b7fedbcd
fix up deployment and connect ui to server again
drewp@bigasterisk.com
parents:
8
diff
changeset
|
12 } |
b9c2b7fedbcd
fix up deployment and connect ui to server again
drewp@bigasterisk.com
parents:
8
diff
changeset
|
13 |
6 | 14 @customElement("sco-search-page") |
15 export class ScoSearchPage extends LitElement { | |
16 static styles = [ | |
17 css` | |
18 :host { | |
19 display: flex; | |
20 flex-direction: column; | |
21 height: 100vh; | |
22 } | |
23 form { | |
24 display: flex; | |
25 flex-direction: row; | |
26 align-items: flex-end; | |
27 | |
28 margin: 0 10% 0 100px; | |
29 } | |
30 sl-textarea { | |
31 width: 100%; | |
32 } | |
33 :host > * { | |
34 padding: 5px; | |
35 } | |
36 section#results { | |
37 background-color: #ffffffde; | |
38 flex-grow: 1; | |
39 display: flex; | |
40 flex-direction: column; | |
41 overflow: hidden; | |
42 margin-bottom: 15px; | |
43 margin-left: 110px; | |
44 } | |
45 img.bot { | |
46 width: 237px; | |
47 position: absolute; | |
48 left: -33px; | |
49 top: -22px; | |
50 z-index: -1; | |
51 } | |
8 | 52 dt { |
53 color: blue; | |
54 } | |
55 dd { | |
56 margin-bottom: 25px; | |
57 } | |
6 | 58 `, |
59 ]; | |
60 @state() query: string = "climate"; | |
14
b9c2b7fedbcd
fix up deployment and connect ui to server again
drewp@bigasterisk.com
parents:
8
diff
changeset
|
61 @state() results: Doc[] = []; |
6 | 62 @state() queryError: string = ""; |
63 @queryAsync("sl-textarea") queryEl?: Promise<SlTextarea>; | |
64 protected async firstUpdated(_changedProperties: PropertyValueMap<any> | Map<PropertyKey, unknown>) { | |
65 super.firstUpdated(_changedProperties); | |
66 | |
67 await this.pressingEnterSubmitsForm(); | |
68 | |
69 this.queryParamToProperty(); | |
70 | |
71 window.addEventListener("popstate", (event) => { | |
72 this.queryParamToProperty(); | |
73 }); | |
74 | |
75 this.submit().catch(console.error); | |
76 } | |
77 | |
78 private async pressingEnterSubmitsForm() { | |
79 const ta = (await this.queryEl)?.shadowRoot?.querySelector("textarea"); | |
80 ta?.addEventListener("keydown", (event: KeyboardEvent) => { | |
81 if (event.code == "Enter" && !event.shiftKey) { | |
82 event.preventDefault(); | |
83 this.submit(); | |
84 } | |
85 }); | |
86 } | |
87 | |
88 private queryParamToProperty() { | |
89 const urlParams = new URLSearchParams(window.location.search); | |
90 const qParam = urlParams.get("q"); | |
91 | |
92 if (qParam) { | |
93 this.query = qParam; | |
94 } | |
95 } | |
96 | |
97 private async propertyToQueryParam() { | |
98 const currentUrl = new URL(window.location.href); | |
99 | |
100 const q = await this.getCurrentQuery(); | |
101 if (currentUrl.searchParams.get("q") !== q) { | |
102 currentUrl.searchParams.set("q", q); | |
103 | |
104 const newUrl = currentUrl.toString(); | |
105 | |
106 history.pushState({}, document.title, newUrl); | |
107 } | |
108 } | |
109 | |
110 render() { | |
111 return html` | |
112 <section id="query"> | |
113 <img class="bot" src="sco-bot.jpg" /> | |
114 <form> | |
115 <sl-textarea .value=${this.query} rows="1" resize="auto" label="Query" enterkeyhint="search" autocapitalize="off" autofocus="true"></sl-textarea> | |
116 <sl-button variant="primary" @click=${this.submit}>Submit</sl-button> | |
117 <div>${this.queryError}</div> | |
118 </form> | |
119 </section> | |
120 <section id="results"> | |
8 | 121 <dl> |
122 ${this.results.map( | |
14
b9c2b7fedbcd
fix up deployment and connect ui to server again
drewp@bigasterisk.com
parents:
8
diff
changeset
|
123 (r: Doc) => |
b9c2b7fedbcd
fix up deployment and connect ui to server again
drewp@bigasterisk.com
parents:
8
diff
changeset
|
124 html`<dt>${r.sourceTitle}</dt> |
8 | 125 <dd>${unsafeHTML(r.snippetHtml)}</dd>` |
14
b9c2b7fedbcd
fix up deployment and connect ui to server again
drewp@bigasterisk.com
parents:
8
diff
changeset
|
126 )} |
8 | 127 </dl> |
6 | 128 <div>Matching results: ${this.results.length}</div> |
129 </section> | |
130 `; | |
131 } | |
132 | |
133 async getCurrentQuery(): Promise<string> { | |
134 return (await this.queryEl)!.value || ""; | |
135 } | |
136 | |
137 async submit() { | |
138 await this.propertyToQueryParam(); | |
139 | |
140 this.results = []; | |
141 | |
142 const sentQ = await this.getCurrentQuery(); | |
143 | |
8 | 144 const resp = await fetch("query?" + new URLSearchParams({ q: sentQ })); |
145 if (sentQ != (await this.getCurrentQuery())) { | |
146 // old result- ignore | |
147 return; | |
148 } | |
149 this.results = (await resp.json()).results; | |
6 | 150 this.requestUpdate(); |
151 } | |
152 } |