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