210 lines
3.7 KiB
JavaScript
210 lines
3.7 KiB
JavaScript
|
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 = 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 = () => {
|
|||
|
// console.log(getJSON('/api/'))
|
|||
|
}
|
|||
|
|
|||
|
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;
|
|||
|
}
|
|||
|
|
|||
|
.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;
|
|||
|
}
|
|||
|
|
|||
|
.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})">'
|
|||
|
+ ''
|
|||
|
+ '</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 toNodes = html => {
|
|||
|
return new DOMParser().parseFromString(html, 'text/html').body
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
const getStats = async () => {
|
|||
|
let cells = ''
|
|||
|
let info = await getJSON('/api/getstats')
|
|||
|
for(let i = 0; i < cols * rows; i++) {
|
|||
|
if(info.asics[i]) // FIND!!!
|
|||
|
cells += sprintf(cell, i, 'green')
|
|||
|
else
|
|||
|
cells += sprintf(cell, i)
|
|||
|
|
|||
|
}
|
|||
|
return cells
|
|||
|
}
|
|||
|
|
|||
|
const run = async () => {
|
|||
|
let inner = sprintf(grid, await getStats())
|
|||
|
|
|||
|
document.querySelector('body').innerHTML += css
|
|||
|
document.querySelector('body').innerHTML += sprintf(header)
|
|||
|
document.querySelector('body').innerHTML += inner
|
|||
|
|
|||
|
update()
|
|||
|
setInterval(() => {
|
|||
|
update()
|
|||
|
}, 10000)
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
run()
|