This repository has been archived on 2024-06-03. You can view files and clone it, but cannot push or open issues or pull requests.
quickstatus/public/index.js
2019-03-01 22:00:53 +02:00

208 lines
5.7 KiB
JavaScript

(function () {
let app = document.getElementById('app')
function httpGet (url) {
let request = new XMLHttpRequest()
return new Promise(function (resolve, reject) {
request.onreadystatechange = function () {
if (this.readyState === 4) {
if (this.status === 200) {
resolve(this.responseText)
} else if (this.response == null && this.status === 0) {
reject(new Error('The status server appears to be offile.'))
}
}
}
request.open("GET", url, true)
request.send(null)
})
}
function bytesToSize (bytes) {
let sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB']
if (bytes == 0) return '0 Byte'
let i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)))
return Math.round(bytes / Math.pow(1024, i), 2) + ' ' + sizes[i]
}
// Add a zero in front of single-digit numbers
function zf (v) {
if (v > 9) {
return '' + v
} else {
return '0' + v
}
}
// Convert seconds into years days hours minutes seconds(.milliseconds)
function readableTime (timems, ignoreMs) {
var time = timems | 0
var ms = ignoreMs ? '' : '.' + zf((timems * 100) % 100 | 0)
if (time < 60) return zf(time) + ms + 's'
else if (time < 3600) return zf(time / 60 | 0) + 'm ' + zf(time % 60) + ms + 's'
else if (time < 86400) return zf(time / 3600 | 0) + 'h ' + zf((time % 3600) / 60 | 0) + 'm ' + zf((time % 3600) % 60) + ms + 's'
else if (time < 31536000) return (time / 86400 | 0) + 'd ' + zf((time % 86400) / 3600 | 0) + 'h ' + zf((time % 3600) / 60 | 0) + 'm ' + zf((time % 3600) % 60) + 's'
else return (time / 31536000 | 0) + 'y ' + zf((time % 31536000) / 86400 | 0) + 'd ' + zf((time % 86400) / 3600 | 0) + 'h ' + zf((time % 3600) / 60 | 0) + 'm ' + zf((time % 3600) % 60) + 's'
}
function e (element, content, cl) {
let el = document.createElement(element)
if (cl) el.className = cl
el.innerHTML = content
return el.outerHTML
}
function box (type, content) {
return e('div', content, type)
}
function bar (metric, value, percentage, low, high) {
return box('bar-outer',
e('span', metric, 'bar-name') +
box('bar-inner',
'<div class="bar-progress" style="width: ' + percentage + '%;"></div>'
) +
box('bar-stats',
e('span', low, 'stat-low') +
e('span', value, 'stat-now') +
e('span', high, 'stat-high')
)
)
}
function renderPage (data) {
let title = 'Welcome to ' + data.hostname + ' on ' + data.kernel
document.title = title
app.innerHTML = ''
app.innerHTML += box('infobox-row',
box('general infobox',
box('header',
e('h2', 'General')
) +
box('content',
box('row',
e('label', 'Hostname') +
e('span', data.hostname)
) + box('row',
e('label', 'Uptime') +
e('span', readableTime(data.uptime))
) + box('row',
e('label', 'Kernel version') +
e('span', data.kernel)
) + box('row',
e('label', 'Processes') +
e('span', data.cpu.processes)
)
)
) +
// CPU usage
box('cpu infobox',
box('header',
e('h2', 'CPU')
) +
box('content',
box('row',
e('label', 'Model') +
e('span', data.cpu.model)
) +
box('row',
e('label', 'Num. cores') +
e('span', data.cpu.count)
) +
box('row',
e('label', 'Usage') +
e('span', Math.floor(data.cpu.usage) + ' %')
) + box('row',
e('label', 'Load averages') +
e('span', data.cpu.loadAverage[0].toFixed(2) + ', ' + data.cpu.loadAverage[1].toFixed(2) + ', ' + data.cpu.loadAverage[2].toFixed(2))
)
)
))
// Memory usage
let memuse = (data.memory.total - data.memory.free)
app.innerHTML += box('memory infobox',
box('header',
e('h2', 'Memory')
) +
box('content',
bar('Memory usage', bytesToSize(memuse), memuse * 100 / data.memory.total, '0 Bytes', bytesToSize(data.memory.total))
)
)
// Network interfaces
let interfaces = ''
for (let int in data.network) {
if (int === 'lo') continue
let iface = data.network[int]
let ips = []
for (let ip in iface.addresses) {
ips.push(e('span', iface.addresses[ip], 'ip-addr'))
}
interfaces += box('interface',
e('h3', int) +
ips.join('') +
e('h4', 'Bandwidth', 'sec-info') +
box('row',
e('label', 'Download') +
e('span', bytesToSize(iface.download))
) + box('row',
e('label', 'Upload') +
e('span', bytesToSize(iface.upload))
)
)
}
// Disks
let disks = ''
for (let mount in data.disk) {
let disk = data.disk[mount]
disks += box('disk',
e('h3', 'Mounted on ' + mount) +
box('row',
e('label', 'Free space') +
e('span', disk.freeGb + ' GB')
) +
bar('Disk usage', disk.usedGb + ' GB', disk.usedPercentage, '0 GB', disk.totalGb + ' GB')
)
}
app.innerHTML += box('infobox-row',
box('network infobox',
box('header',
e('h2', 'Network Interfaces')
) +
box('content',
box('interfaces', interfaces)
)
)+
box('disk infobox',
box('header',
e('h2', 'Disk Drives')
) +
box('content',
box('disks', disks)
)
)
)
}
function update () {
httpGet('/status').then(function (data) {
try {
renderPage(JSON.parse(data))
} catch (e) {
console.error(e)
}
}, function (e) {
console.error(e)
})
}
update()
})()