import { createApp } from './vue.esm-browser.js'; import Cluster from './Cluster.js'; import Host from './Host.js'; createApp({ components: { Cluster, Host }, data() { return { forms: { store: { }, }, session: {}, error: null, publicState: null, uiHash: null, watchingState: false, state: null, } }, mounted() { this.session = JSON.parse(sessionStorage.state || "{}") this.watchPublicState() }, watch: { session: { deep: true, handler(v) { sessionStorage.state = JSON.stringify(v) if (v.token && !this.watchingState) { this.watchState() this.watchingState = true } } }, publicState: { deep: true, handler(v) { if (v) { if (this.uiHash && v.UIHash != this.uiHash) { console.log("reloading") location.reload() } else { this.uiHash = v.UIHash } } }, } }, methods: { copyText(text) { event.preventDefault() window.navigator.clipboard.writeText(text) }, setToken() { event.preventDefault() this.session.token = this.forms.setToken this.forms.setToken = null }, storeAddKey() { this.apiPost('/store/add-key', this.forms.store.pass1, (v) => { this.forms.store = {} }) }, unlockStore() { this.apiPost('/public/unlock-store', this.forms.store.pass1, (v) => { this.forms.store = {} if (v) { this.session.token = v if (!this.watchingState) { this.watchState() this.watchingState = true } } }) }, apiPost(action, data, onload) { event.preventDefault() if (data === undefined) { throw("action " + action + ": no data") } /* TODO fetch(action, { method: 'POST', body: JSON.stringify(data), }) .then((response) => response.json()) .then((result) => onload) // */ var xhr = new XMLHttpRequest() xhr.responseType = 'json' // TODO spinner, pending aciton notification, or something xhr.onerror = () => { // this.actionResults.splice(idx, 1, {...item, done: true, failed: true }) } xhr.onload = (r) => { if (xhr.status != 200) { this.error = xhr.response return } // this.actionResults.splice(idx, 1, {...item, done: true, resp: xhr.responseText}) this.error = null if (onload) { onload(xhr.response) } } xhr.open("POST", action) xhr.setRequestHeader('Accept', 'application/json') xhr.setRequestHeader('Content-Type', 'application/json') if (this.session.token) { xhr.setRequestHeader('Authorization', 'Bearer '+this.session.token) } xhr.send(JSON.stringify(data)) }, download(url) { event.target.target = '_blank' event.target.href = this.downloadLink(url) }, downloadLink(url) { // TODO once-shot download link return url + '?token=' + this.session.token }, watchPublicState() { this.watchStream('publicState', '/public-state') }, watchState() { this.watchStream('state', '/state', true) }, watchStream(field, path, withToken) { let evtSrc = new EventSource(path + (withToken ? '?token='+this.session.token : '')); evtSrc.onmessage = (e) => { let update = JSON.parse(e.data) console.log("watch "+path+":", update) if (update.err) { console.log("watch error from server:", err) } if (update.set) { this[field] = update.set } if (update.p) { // patch new jsonpatch.JSONPatch(update.p, true).apply(this[field]) } } evtSrc.onerror = (e) => { // console.log("event source " + path + " error:", e) if (evtSrc) evtSrc.close() this[field] = null window.setTimeout(() => { this.watchStream(field, path, withToken) }, 1000) } }, } }).mount('#app')