Bit.ASICmon-py/index.js

224 lines
4.1 KiB
JavaScript
Raw Normal View History

2024-03-25 12:32:11 +08:00
const sprintf = (...[string, ...args]) => {
return string.replace(/{(\d+)}/g, (match, number) => args[number] ?? match);
}
const getJSON = async url => {
const resp = await fetch(url)
const json = await resp.json()
return json;
}
const createPopup = async id => {
const asics = await getJSON('/api/asictypes')
asicoptions = ''
asics.forEach(elem => {
asicoptions += sprintf('<option value="{0}">{1}</option>', elem['key'], elem['value'])
})
document.querySelector('body').innerHTML += sprintf(popup, id, asicoptions, 'content')
}
const deletePopup = id => {
document.querySelector('#popup-' + id).remove()
}
const update = async () => {
let inner = await getStats()
document.querySelector('.grid').innerHTML = inner
}
const datafn = async () => {
// return await getJSON('/api/webinit')
}
const data = datafn()
console.log(data)
const cols = 40
const rows = 40
const css =
`<style>
@import url('https://fonts.googleapis.com/css2?family=Source+Code+Pro:wght@400;500;600;700&display=swap');
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Source Code Pro', monospace;
}
body {
background: #000;
}
input,
select {
border: 1px solid #fff;
background: #000;
color: #fff;
padding: 5px 10px;
}
.green {
background: #0b0 !important;
}
.yellow {
background: #ff0 !important;
}
.red {
background: #f11 !important;
}
.darkred {
background: #300 !important;
}
.header {
height: 60px;
background: #222;
text-align: center;
margin: 0 0 1px 0;
display: grid;
justify-items: center;
align-content: center;
}
.header-info {
color: #bbb;
font-weight: 700;
}
.grid {
display: grid;
grid-template-columns: repeat(${cols}, 30px);
grid-template-rows: repeat(${rows}, 30px);
grid-gap: 1px;
margin: auto;
width: max-content;
}
.cell {
position: relative;
background: #111;
font-size: 9px;
}
.cell:hover {
cursor: pointer;
}
.cell:hover::after {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
background: #ffffff33;
}
.popup {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
display: grid;
justify-items: center;
align-content: center;
}
.popup-bg {
position: absolute;
width: 100%;
height: 100%;
background: #00000033;
z-index: 98;
}
.popup-window {
position: relative;
height: max-content;
max-height: 90vh;
width: max-content;
max-width: 90vw;
padding: 40px;
background: #222;
z-index: 99;
}
</style>
`
const header =
'<div class="header">'
+ '<div class="header-info">'
+ 'Всего устройств: {0}, Предупреждений, {1}, Ошибки: {2}, В сети: {3}, Не в сети: {4}'
+ '</div>'
+ '</div>'
const cell =
'<div class="cell {1}" id="cell-{0}" onclick="createPopup({0})">'
+ '{2}'
+ '</div>'
const grid =
'<div class="grid">'
+ '{0}'
+ '</div>'
const popup =
'<div class="popup" id="popup-{0}">'
+ '<div class="popup-bg" onclick="deletePopup({0})"></div>'
+ '<div class="popup-window">'
+ '<div class="row">'
+ '<select>'
+ '<option value="none">Свободно</option>'
+ '{1}'
+ '</select>'
+ '<input type="text" placeholder="Адрес...">'
+ '</div>'
+ '{2}'
+ '</div>'
+ '</div>'
const getStats = async () => {
let cells = ''
let info = await getJSON('/curstatus.json')
for(let i = 1; i <= cols * rows; i++) {
if(info.asics[i]?.status == "ok")
cells += sprintf(cell, i, 'green', info.asics[i]?.hashrate)
else if(info.asics[i]?.status == "warn")
cells += sprintf(cell, i, 'yellow', info.asics[i]?.hashrate)
else if(info.asics[i]?.status == "crit")
cells += sprintf(cell, i, 'red', info.asics[i]?.hashrate)
else if(info.asics[i]?.status == "off")
cells += sprintf(cell, i, 'darkred', '')
else
cells += sprintf(cell, i, '', '')
}
return cells
}
const run = async () => {
document.querySelector('body').innerHTML += css
document.querySelector('body').innerHTML += sprintf(header)
let inner = sprintf(grid, await getStats())
document.querySelector('body').innerHTML += inner
setInterval(async () => {
await update()
}, 10000)
}
run()