184 lines
5.6 KiB
JavaScript
184 lines
5.6 KiB
JavaScript
|
|
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: { },
|
|
storeUpload: {},
|
|
},
|
|
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
|
|
},
|
|
uploadStore() {
|
|
event.preventDefault()
|
|
this.apiPost('/public/store.tar', this.$refs.storeUpload.files[0], (v) => {
|
|
this.forms.store = {}
|
|
}, "application/tar")
|
|
},
|
|
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
|
|
}
|
|
}
|
|
})
|
|
},
|
|
uploadConfig() {
|
|
event.preventDefault()
|
|
this.apiPost('/configs', this.$refs.configUpload.files[0], (v) => {}, "text/vnd.yaml")
|
|
},
|
|
apiPost(action, data, onload, contentType = 'application/json') {
|
|
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 action 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', contentType)
|
|
if (this.session.token) {
|
|
xhr.setRequestHeader('Authorization', 'Bearer '+this.session.token)
|
|
}
|
|
|
|
if (contentType == "application/json") {
|
|
xhr.send(JSON.stringify(data))
|
|
} else {
|
|
xhr.send(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')
|
|
|