diff --git a/apps/ssb/script.js b/apps/ssb/script.js index 8f1ab8a8..6f4301a1 100644 --- a/apps/ssb/script.js +++ b/apps/ssb/script.js @@ -13,4 +13,5 @@ import * as tf_tab_news from './tf-tab-news.js'; import * as tf_tab_news_feed from './tf-tab-news-feed.js'; import * as tf_tab_search from './tf-tab-search.js'; import * as tf_tab_connections from './tf-tab-connections.js'; +import * as tf_tab_query from './tf-tab-query.js'; import * as tf_tag from './tf-tag.js'; \ No newline at end of file diff --git a/apps/ssb/tf-app.js b/apps/ssb/tf-app.js index bc1bf2fe..01d4fb9a 100644 --- a/apps/ssb/tf-app.js +++ b/apps/ssb/tf-app.js @@ -68,6 +68,8 @@ class TfElement extends LitElement { this.tab = 'connections'; } else if (this.hash === '#mentions') { this.tab = 'mentions'; + } else if (this.hash.startsWith('#sql=')) { + this.tab = 'query'; } else { this.tab = 'news'; } @@ -310,6 +312,10 @@ class TfElement extends LitElement { return html` `; + } else if (this.tab === 'query') { + return html` + + `; } } @@ -321,6 +327,8 @@ class TfElement extends LitElement { await tfrpc.rpc.setHash('#connections'); } else if (tab === 'mentions') { await tfrpc.rpc.setHash('#mentions'); + } else if (tab === 'query') { + await tfrpc.rpc.setHash('#sql='); } } @@ -340,6 +348,7 @@ class TfElement extends LitElement { self.set_tab('connections')}> self.set_tab('mentions')}> self.set_tab('search')}> + self.set_tab('query')}> `; let contents = diff --git a/apps/ssb/tf-tab-query.js b/apps/ssb/tf-tab-query.js new file mode 100644 index 00000000..bec5a7d8 --- /dev/null +++ b/apps/ssb/tf-tab-query.js @@ -0,0 +1,111 @@ +import {LitElement, html, unsafeHTML} from './lit-all.min.js'; +import * as tfrpc from '/static/tfrpc.js'; +import {styles} from './tf-styles.js'; + +class TfTabQueryElement extends LitElement { + static get properties() { + return { + whoami: {type: String}, + users: {type: Object}, + following: {type: Array}, + query: {type: String}, + expanded: {type: Object}, + results: {type: Array}, + error: {type: Object}, + duration: {type: Number}, + }; + } + + static styles = styles; + + constructor() { + super(); + let self = this; + this.whoami = null; + this.users = {}; + this.following = []; + this.expanded = {}; + this.duration = undefined; + } + + async search(query) { + console.log('Searching...', this.whoami, query); + this.results = []; + this.error = undefined; + this.duration = undefined; + let search = this.renderRoot.getElementById('search'); + if (search) { + search.value = query; + search.focus(); + } + await tfrpc.rpc.setHash('#sql=' + encodeURIComponent(query)); + let start_time = new Date(); + try { + this.results = await tfrpc.rpc.query(query, []) + } catch (error) { + this.error = error; + } + let end_time = new Date(); + this.duration = (end_time - start_time).valueOf(); + console.log('Done.'); + search = this.renderRoot.getElementById('search'); + if (search) { + search.value = query; + search.focus(); + } + } + + search_keydown(event) { + if (event.keyCode == 13 && event.ctrlKey) { + this.query = this.renderRoot.getElementById('search').value; + event.preventDefault(); + } + } + + 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); + } + } + + render_results() { + if (!this.results?.length) { + return html`
No results.
`; + } else { + let keys = Object.keys(this.results[0]).sort(); + return html` + ${keys.map(key => html``)} + ${this.results.map(row => html`${keys.map(key => html``)}`)} +
${key}
${row[key]}
`; + } + } + + render_error() { + return html`
${JSON.stringify(this.error, null, 2)}
`; + } + + render() { + if (this.query !== this.last_query) { + this.last_query = this.query; + this.search(this.query); + } + let self = this; + return html` +
+ + self.search(self.renderRoot.getElementById('search').value)}> +
+
Took ${this.duration / 1000.0} seconds.
+
Executing...
+ ${this.render_error()} + ${this.render_results()} + `; + } +} + +customElements.define('tf-tab-query', TfTabQueryElement); \ No newline at end of file