2022-09-11 17:42:41 +00:00
|
|
|
import {LitElement, html, unsafeHTML} from './lit-all.min.js';
|
|
|
|
import * as tfrpc from '/static/tfrpc.js';
|
|
|
|
import {styles} from './tf-styles.js';
|
|
|
|
|
|
|
|
class TfTabSearchElement extends LitElement {
|
|
|
|
static get properties() {
|
|
|
|
return {
|
2024-09-11 20:25:55 -04:00
|
|
|
drafts: {type: Object},
|
2022-09-11 17:42:41 +00:00
|
|
|
whoami: {type: String},
|
|
|
|
users: {type: Object},
|
|
|
|
following: {type: Array},
|
2022-09-15 00:16:37 +00:00
|
|
|
query: {type: String},
|
2023-06-14 16:39:08 +00:00
|
|
|
expanded: {type: Object},
|
2025-10-22 18:21:22 -04:00
|
|
|
messages: {type: Array},
|
|
|
|
results: {type: Array},
|
|
|
|
error: {type: Object},
|
2023-03-29 22:02:12 +00:00
|
|
|
};
|
2022-09-11 17:42:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static styles = styles;
|
|
|
|
|
|
|
|
constructor() {
|
|
|
|
super();
|
|
|
|
let self = this;
|
|
|
|
this.whoami = null;
|
|
|
|
this.users = {};
|
|
|
|
this.following = [];
|
2023-06-14 16:39:08 +00:00
|
|
|
this.expanded = {};
|
2024-09-11 20:25:55 -04:00
|
|
|
this.drafts = {};
|
|
|
|
tfrpc.rpc.localStorageGet('drafts').then(function (d) {
|
|
|
|
self.drafts = JSON.parse(d || '{}');
|
|
|
|
});
|
2022-09-11 17:42:41 +00:00
|
|
|
}
|
|
|
|
|
2022-09-15 00:16:37 +00:00
|
|
|
async search(query) {
|
2022-09-11 17:42:41 +00:00
|
|
|
console.log('Searching...', this.whoami, query);
|
2022-09-15 00:16:37 +00:00
|
|
|
let search = this.renderRoot.getElementById('search');
|
2024-02-24 11:09:34 -05:00
|
|
|
if (search) {
|
2022-09-15 00:16:37 +00:00
|
|
|
search.value = query;
|
|
|
|
search.focus();
|
|
|
|
search.select();
|
|
|
|
}
|
|
|
|
await tfrpc.rpc.setHash('#q=' + encodeURIComponent(query));
|
2025-10-22 18:21:22 -04:00
|
|
|
this.error = undefined;
|
|
|
|
this.results = [];
|
|
|
|
this.messages = [];
|
|
|
|
if (query.startsWith('sql:')) {
|
|
|
|
this.messages = [];
|
|
|
|
try {
|
|
|
|
this.results = await tfrpc.rpc.query(
|
|
|
|
query.substring('sql:'.length),
|
|
|
|
[]
|
|
|
|
);
|
|
|
|
} catch (e) {
|
|
|
|
this.results = [];
|
|
|
|
this.error = e;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
let results = await tfrpc.rpc.query(
|
|
|
|
`
|
|
|
|
SELECT messages.id, messages.previous, messages.author, messages.sequence, messages.timestamp, messages.hash, json(messages.content) AS content, messages.signature
|
|
|
|
FROM messages_fts(?)
|
|
|
|
JOIN messages ON messages.rowid = messages_fts.rowid
|
|
|
|
JOIN json_each(?) AS following ON messages.author = following.value
|
|
|
|
ORDER BY timestamp DESC limit 100
|
|
|
|
`,
|
|
|
|
['"' + query.replace('"', '""') + '"', JSON.stringify(this.following)]
|
|
|
|
);
|
|
|
|
console.log('Done.');
|
|
|
|
search = this.renderRoot.getElementById('search');
|
|
|
|
if (search) {
|
|
|
|
search.value = query;
|
|
|
|
search.focus();
|
|
|
|
search.select();
|
|
|
|
}
|
|
|
|
this.messages = results;
|
2022-09-15 00:16:37 +00:00
|
|
|
}
|
2022-09-11 17:42:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
search_keydown(event) {
|
|
|
|
if (event.keyCode == 13) {
|
2022-09-15 00:16:37 +00:00
|
|
|
this.query = this.renderRoot.getElementById('search').value;
|
2022-09-11 17:42:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-14 16:39:08 +00:00
|
|
|
on_expand(event) {
|
|
|
|
if (event.detail.expanded) {
|
|
|
|
let expand = {};
|
|
|
|
expand[event.detail.id] = true;
|
|
|
|
this.expanded = Object.assign({}, this.expanded, expand);
|
|
|
|
} else {
|
|
|
|
delete this.expanded[event.detail.id];
|
|
|
|
this.expanded = Object.assign({}, this.expanded);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-09-11 20:25:55 -04:00
|
|
|
draft(event) {
|
|
|
|
let id = event.detail.id || '';
|
|
|
|
let previous = this.drafts[id];
|
|
|
|
if (event.detail.draft !== undefined) {
|
|
|
|
this.drafts[id] = event.detail.draft;
|
|
|
|
} else {
|
|
|
|
delete this.drafts[id];
|
|
|
|
}
|
|
|
|
this.drafts = Object.assign({}, this.drafts);
|
|
|
|
tfrpc.rpc.localStorageSet('drafts', JSON.stringify(this.drafts));
|
|
|
|
}
|
|
|
|
|
2025-10-22 18:21:22 -04:00
|
|
|
render_results() {
|
|
|
|
if (this.error) {
|
|
|
|
return html`<h2 style="color: red">${this.error.message}</h2>
|
|
|
|
<pre style="color: red">${this.error.stack}</pre>`;
|
|
|
|
} else if (this.messages?.length) {
|
|
|
|
return html`<tf-news
|
|
|
|
id="news"
|
|
|
|
whoami=${this.whoami}
|
|
|
|
.messages=${this.messages}
|
|
|
|
.users=${this.users}
|
|
|
|
.expanded=${this.expanded}
|
|
|
|
.drafts=${this.drafts}
|
|
|
|
@tf-expand=${this.on_expand}
|
|
|
|
@tf-draft=${this.draft}
|
|
|
|
></tf-news>`;
|
|
|
|
} else if (this.results?.length) {
|
|
|
|
let keys = Object.keys(this.results[0]).sort();
|
|
|
|
return html`<table style="width: 100%; max-width: 100%">
|
|
|
|
<tr>
|
|
|
|
${keys.map((key) => html`<th>${key}</th>`)}
|
|
|
|
</tr>
|
|
|
|
${this.results.map(
|
|
|
|
(row) =>
|
|
|
|
html`<tr>
|
|
|
|
${keys.map((key) => html`<td>${row[key]}</td>`)}
|
|
|
|
</tr>`
|
|
|
|
)}
|
|
|
|
</table>`;
|
|
|
|
} else {
|
|
|
|
return html`<div>No results.</div>`;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-11 17:42:41 +00:00
|
|
|
render() {
|
2022-09-15 00:16:37 +00:00
|
|
|
if (this.query !== this.last_query) {
|
2023-06-14 16:39:08 +00:00
|
|
|
this.last_query = this.query;
|
2022-09-15 00:16:37 +00:00
|
|
|
this.search(this.query);
|
|
|
|
}
|
|
|
|
let self = this;
|
2022-09-11 17:42:41 +00:00
|
|
|
return html`
|
2025-10-22 18:21:22 -04:00
|
|
|
<div class="w3-padding">
|
|
|
|
<div style="display: flex; flex-direction: row; gap: 4px">
|
|
|
|
<input type="text" class="w3-input w3-theme-d1" id="search" value=${this.query} style="flex: 1" @keydown=${this.search_keydown}></input>
|
|
|
|
<button class="w3-button w3-theme-d1" @click=${(event) => self.search(self.renderRoot.getElementById('search').value)}>Search</button>
|
|
|
|
</div>
|
|
|
|
${this.render_results()}
|
2022-09-15 00:16:37 +00:00
|
|
|
</div>
|
2022-09-11 17:42:41 +00:00
|
|
|
`;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-24 11:09:34 -05:00
|
|
|
customElements.define('tf-tab-search', TfTabSearchElement);
|