portal/web/portal.mjs

140 lines
3.5 KiB
JavaScript

import * as Stat from "./stat.mjs"
const Millisecond = 1
const Second = 1000 * Millisecond
const Minute = 60 * Second
class StatApp {
constructor(parent) {
this.parent= parent
this.stat = new Stat.Stat()
this.chart = new Stat.PieChart(parent, this.stat)
setInterval(()=>this.update(), 2 * Second)
setTimeout(()=>this.update(), 500 * Millisecond)
this.update()
}
async update() {
// Use non-standard checkVisibility method to avoid a pointless update
if (this.parent.checkVisibility && !this.parent.checkVisibility()) {
return
}
await this.stat.update()
this.chart.update()
}
}
let frames = {}
function activate(event, element) {
event.preventDefault()
let parent = element.parentElement
for (let e of parent.getElementsByClassName("active")) {
e.classList.remove("active")
}
element.classList.add("active")
let href = element.href
let app = document.querySelector("#app")
let frame = frames[href]
if (frame) {
frame.dispatchEvent(new Event("load"))
} else {
frame = app.appendChild(document.createElement("iframe"))
frame.addEventListener("load", e => frameLoaded(frame))
frame.src = href
frames[href] = frame
}
for (let fhref in frames) {
let f = frames[fhref]
if (fhref == href) {
f.classList.remove("hidden")
} else {
f.classList.add("hidden")
}
}
}
function frameLoaded(frame) {
let doc = frame.contentDocument
if (doc.title.length > 0) {
document.title = doc.title
}
let icon = document.querySelector("link[rel~='icon']")
let dicon = doc.querySelector("link[rel~='icon']")
if (dicon) {
icon.href = dicon.href
} else {
icon.href = defaultIcon
}
}
let defaultIcon = null
async function init() {
let doc = document.querySelector("iframe").contentDocument
defaultIcon = document.querySelector("link[rel~='icon']").href
for (let l of document.head.querySelectorAll("style")) {
doc.head.appendChild(l.cloneNode(true))
}
for (let l of document.head.querySelectorAll("link[rel='stylesheet']")) {
doc.head.appendChild(l.cloneNode())
}
for (let f of document.querySelectorAll("#app iframe")) {
frames[f.src] = f
}
let icons = doc.body.appendChild(doc.createElement("section"))
icons.classList.add("icons")
let nav = document.querySelector("nav")
let resp = await fetch("portal.json")
let obj = await resp.json()
for (let app of obj) {
let hlink = null
if (app.target != "_blank") {
hlink = nav.appendChild(document.createElement("a"))
hlink.href = app.href
hlink.textContent = app.title
if (app.target) {
hlink.target = app.target
} else {
hlink.addEventListener("click", event => activate(event, hlink))
}
}
let dlink = icons.appendChild(doc.createElement("a"))
dlink.href = app.href
if (app.target) {
dlink.target = app.target
} else {
dlink.addEventListener("click", event => activate(event, hlink))
}
if (app.icon) {
let icon = dlink.appendChild(doc.createElement("img"))
icon.src = app.icon
icon.alt = app.title
icon.title = app.title
icon.style.objectFit = "cover"
} else if (app.app) {
if (app.app == "stat") {
new StatApp(dlink)
}
} else {
let text = dlink.appendChild(doc.createElement("div"))
text.textContent = app.title
}
}
}
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", init)
} else {
init()
}