import {LitElement, html, keyed} from './lit-all.min.js'; import * as tfrpc from '/static/tfrpc.js'; class TfCollectionsAppElement extends LitElement { static get properties() { return { ids: {type: Array}, owner_ids: {type: Array}, whoami: {type: String}, following: {type: Array}, wikis: {type: Object}, wiki_docs: {type: Object}, wiki: {type: Object}, wiki_doc: {type: Object}, hash: {type: String}, adding_editor: {type: Boolean}, expand_editors: {type: Boolean}, }; } constructor() { super(); this.ids = []; this.owner_ids = []; this.following = []; this.load(); let self = this; tfrpc.register(function hash_changed(hash) { self.notify_hash_changed(hash); }); tfrpc.rpc.get_hash().then(hash => self.notify_hash_changed(hash)); } async load() { this.ids = await tfrpc.rpc.getIdentities(); this.owner_ids = await tfrpc.rpc.getOwnerIdentities(); this.whoami = await tfrpc.rpc.localStorageGet('collections_whoami'); let ids = [...new Set([...this.owner_ids, this.whoami])].sort(); this.following = Object.keys(await tfrpc.rpc.following(ids, 1)).sort(); await this.read_wikis(); await this.read_Wiki_docs(); } async read_wikis() { let max_rowid; let wikis; let start_whoami = this.whoami; while (true) { console.log('read_wikis', this.whoami); [max_rowid, wikis] = await tfrpc.rpc.collection(this.following, 'wiki', undefined, max_rowid, wikis, false); console.log('read ->', wikis); if (this.whoami !== start_whoami) { break; } console.log('wikis =>', wikis); this.wikis = wikis; this.update_wiki(); } } async read_wiki_docs() { if (!this.wiki?.id) { return; } let start_id = this.wiki.id; let max_rowid; let wiki_docs; while (true) { [max_rowid, wiki_docs] = await tfrpc.rpc.collection(this.wiki?.editors, 'wiki-doc', this.wiki?.id, max_rowid, wiki_docs); if (this.wiki?.id !== start_id) { break; } this.wiki_docs = wiki_docs; this.update_wiki_doc(); } } hash_wiki() { let hash = this.hash ?? ''; hash = hash.charAt(0) == '#' ? hash.substring(1) : hash; let parts = hash.split('/'); return parts[0]; } hash_wiki_doc() { let hash = this.hash ?? ''; hash = hash.charAt(0) == '#' ? hash.substring(1) : hash; let slash = hash.indexOf('/'); return slash != -1 ? hash.substring(slash + 1) : undefined; } update_wiki() { let want_wiki = this.hash_wiki(); for (let wiki of Object.values(this.wikis ?? {})) { if (wiki.name === want_wiki) { this.wiki = wiki; this.read_wiki_docs(); break; } } } update_wiki_doc() { let want_wiki_doc = this.hash_wiki_doc(); for (let wiki_doc of Object.values(this.wiki_docs ?? {})) { if (wiki_doc.name === want_wiki_doc) { this.wiki_doc = wiki_doc; } } } notify_hash_changed(hash) { this.hash = hash; this.update_wiki(); this.update_wiki_doc(); } async on_whoami_changed(event) { let new_id = event.srcElement.selected; await tfrpc.rpc.localStorageSet('collections_whoami', new_id); this.whoami = new_id; } update_hash() { tfrpc.rpc.set_hash(this.wiki_doc ? `${this.wiki.name}/${this.wiki_doc.name}` : `${this.wiki.name}`); } async on_wiki_changed(event) { this.wiki = event.detail.value; this.wiki_doc = undefined; this.wiki_docs = undefined; this.adding_editor = false; this.update_hash(); this.read_wiki_docs(); } async on_wiki_create(event) { await tfrpc.rpc.appendMessage(this.whoami, { type: 'wiki', name: event.detail.name, }); } async on_wiki_rename(event) { await tfrpc.rpc.appendMessage(this.whoami, { type: 'wiki', key: event.detail.id, name: event.detail.name, }); } async on_add_editor(event) { let id = this.shadowRoot.getElementById('add_editor').value; let editors = [...this.wiki.editors]; if (editors.indexOf(id) == -1) { editors.push(id); editors.sort(); } await tfrpc.rpc.appendMessage(this.whoami, { type: 'wiki', key: this.wiki.id, editors: editors, }); this.adding_editor = false; } async on_remove_editor(id) { if (confirm(`Are you sure you want to remove ${id} as an editor?`)) { let editors = [...this.wiki.editors]; if (editors.indexOf(id) != -1) { editors = editors.filter(x => x !== id); } await tfrpc.rpc.appendMessage(this.whoami, { type: 'wiki', key: this.wiki.id, editors: editors, }); } } async on_wiki_tombstone(event) { await tfrpc.rpc.appendMessage(this.whoami, { type: 'wiki', key: event.detail.id, tombstone: { date: new Date().valueOf(), reason: 'tombstoned by user', }, }); } async on_wiki_doc_create(event) { await tfrpc.rpc.appendMessage(this.whoami, { type: 'wiki-doc', parent: this.wiki.id, name: event.detail.name, }); } async on_wiki_doc_rename(event) { await tfrpc.rpc.appendMessage(this.whoami, { type: 'wiki-doc', parent: this.wiki.id, key: event.detail.id, name: event.detail.name, }); } async on_wiki_doc_tombstone(event) { await tfrpc.rpc.appendMessage(this.whoami, { type: 'wiki-doc', parent: this.wiki.id, key: event.detail.id, tombstone: { date: new Date().valueOf(), reason: 'tombstoned by user', }, }); } async on_wiki_doc_changed(event) { this.wiki_doc = event.detail.value; this.update_hash(); } updated(changed_properties) { if (changed_properties.has('whoami')) { this.wikis = {}; this.wiki_docs = {}; this.read_wikis(); } } render() { let self = this; return html`
${keyed(this.whoami, html``)} ${keyed(this.wiki_doc?.id, html``)}
    ${this.wiki?.editors.map(id => html`
  • ${id}
  • `)}
${Object.values(this.wikis || {}).map(wiki => html`
self.on_wiki_changed({detail: {value: wiki}})}>${wiki.name}
`)}
${this.wiki_doc && this.wiki_doc.parent === this.wiki?.id ? html` ` : undefined}
`; } } customElements.define('tf-collections-app', TfCollectionsAppElement);