mirror of
https://github.com/KevinMidboe/ISPDowntimeMonitor.git
synced 2025-10-29 09:40:12 +00:00
/site contains static start of frontend.
Started a frontend for displaying the information collected. - Need dynamic data. - Needs a webserver to serve page.
This commit is contained in:
BIN
src/site/SF-Pro-Rounded-Light.otf
Executable file
BIN
src/site/SF-Pro-Rounded-Light.otf
Executable file
Binary file not shown.
52
src/site/fetchLogsAndGenerateTable.js
Normal file
52
src/site/fetchLogsAndGenerateTable.js
Normal file
@@ -0,0 +1,52 @@
|
||||
|
||||
let indicentLogs = [
|
||||
{
|
||||
id: 1,
|
||||
date: new Date('2020/05/30 01:20:38').toISOString(),
|
||||
message: 'Vi har en feil i mobilnettet på denne adressen. Vi jobber med å løse problemet.',
|
||||
duration: '6d 4t 32min'
|
||||
}, {
|
||||
id: 2,
|
||||
date: new Date('2020/04/22 13:47:25').toISOString(),
|
||||
message: 'Vi har en feil i internett på denne adressen. Vi jobber med å løse problemet.',
|
||||
duration: '1d 2t 54min'
|
||||
}
|
||||
]
|
||||
indicentLogs = indicentLogs.reverse()
|
||||
|
||||
const newDiv = () => document.createElement('div');
|
||||
|
||||
const closePopover = () => document.getElementById('popover').remove();
|
||||
|
||||
const tableRowFromLog = (log, table) => {
|
||||
const row = table.insertRow(0);
|
||||
row.setAttribute('incident-id', log.id)
|
||||
row.onclick = clickRowPopupIncident;
|
||||
row.insertCell(0).innerHTML = log.date;
|
||||
row.insertCell(1).innerHTML = log.message;
|
||||
row.insertCell(2).innerHTML = log.duration;
|
||||
}
|
||||
|
||||
const clickRowPopupIncident = (event) => {
|
||||
const cell = event.toElement;
|
||||
const row = cell.parentElement;
|
||||
const indicentId = row.getAttribute('incident-id');
|
||||
|
||||
const popover = newDiv()
|
||||
const container = newDiv()
|
||||
popover.id = 'popover'
|
||||
popover.onclick = closePopover;
|
||||
container.className = 'container'
|
||||
container.innerText = Object.values(indicentLogs[indicentId]).join('\n')
|
||||
popover.appendChild(container)
|
||||
document.body.appendChild(popover);
|
||||
}
|
||||
|
||||
function fetchLogsAndGenerateTable() {
|
||||
const table = document.getElementById('log-table');
|
||||
const tableBody = table.tBodies[0];
|
||||
|
||||
indicentLogs.map(log => tableRowFromLog(log, tableBody))
|
||||
}
|
||||
|
||||
fetchLogsAndGenerateTable()
|
||||
28
src/site/fetchUptimeAndGenerateBarGraph.js
Normal file
28
src/site/fetchUptimeAndGenerateBarGraph.js
Normal file
@@ -0,0 +1,28 @@
|
||||
|
||||
const createEvent = () => {
|
||||
const event = document.createElement('div')
|
||||
event.className = 'event';
|
||||
const tooltip = document.createElement('span');
|
||||
tooltip.className = 'tooltip';
|
||||
const tooltipContent = new Date().toLocaleString()
|
||||
tooltip.innerText = tooltipContent;
|
||||
|
||||
event.appendChild(tooltip);
|
||||
return event;
|
||||
}
|
||||
|
||||
function fetchUptimeAndGenerateBarGraph(instances=10) {
|
||||
const graph = document.getElementById('bar-graph');
|
||||
|
||||
const event = createEvent()
|
||||
|
||||
for (var i = instances; i >= 0; i--) {
|
||||
const clone = event.cloneNode(true)
|
||||
Math.random() > 0.95 ? clone.className += ' error' : null;
|
||||
graph.appendChild(clone)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// fetchUptimeAndGenerateBarGraph(20)
|
||||
fetchUptimeAndGenerateBarGraph(60)
|
||||
57
src/site/index.html
Normal file
57
src/site/index.html
Normal file
@@ -0,0 +1,57 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>ISP downtime monitor</title>
|
||||
<meta charset="UTF-8">
|
||||
<link href="style.css" type="text/css" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
<h1>Nedetid rapport</h1>
|
||||
<div class="page-container">
|
||||
<h2>Oppetid</h2>
|
||||
<div class="container" id="bar-graph">
|
||||
<!-- BAR GRAPH -->
|
||||
</div>
|
||||
|
||||
<div class="color-indicators">
|
||||
<label class="color-indicator-box green"></label>
|
||||
<span>Uptime</span>
|
||||
|
||||
<label class="color-indicator-box red"></label>
|
||||
<span>Downtime</span>
|
||||
</div>
|
||||
<hr />
|
||||
|
||||
<h2>Indicent log</h2>
|
||||
<div class="container" id="indicent-logs">
|
||||
<table id="log-table">
|
||||
<thead><tr>
|
||||
<th>Date</th>
|
||||
<th>Incident message</th>
|
||||
<th>Duration</th>
|
||||
</tr></thead>
|
||||
|
||||
<tbody><tr>
|
||||
<td>31 Mai 2020 22:34</td>
|
||||
<td>OK</td>
|
||||
<td>6d 4t 32min</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>31 Mai 2020 22:34</td>
|
||||
<td>OK</td>
|
||||
<td>6d 4t 32min</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>31 Mai 2020 22:34</td>
|
||||
<td>OK</td>
|
||||
<td>6d 4t 32min</td>
|
||||
</tr></tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
|
||||
<script src="fetchLogsAndGenerateTable.js" type="text/javascript"></script>
|
||||
<script src="fetchUptimeAndGenerateBarGraph.js" type="text/javascript"></script>
|
||||
</html>
|
||||
216
src/site/style.css
Normal file
216
src/site/style.css
Normal file
@@ -0,0 +1,216 @@
|
||||
/**/
|
||||
:root {
|
||||
color-scheme: light;
|
||||
--text-color: black;
|
||||
--background-color: white;
|
||||
--page-background-color: #ebeceb;
|
||||
--page-background-color-40: rgba(247,249,249,0.4);
|
||||
--page-background-color-80: rgba(247,249,249,0.8);
|
||||
--green: #7bed9f;
|
||||
--red: #ff4757;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
color-scheme: light dark;
|
||||
--text-color: white;
|
||||
--background-color: #1c1d1e;
|
||||
--page-background-color: black;
|
||||
--page-background-color-40: rgba(0,0,0,0.4);
|
||||
--page-background-color-80: rgba(0,0,0,0.8);
|
||||
}
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: AppleSF;
|
||||
src: url(SF-Pro-Rounded-Light.otf);
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: AppleSF;
|
||||
background-color: var(--page-background-color);
|
||||
padding: 0 1rem;
|
||||
margin: 1rem;
|
||||
}
|
||||
|
||||
.page-container {
|
||||
background-color: var(--background-color);
|
||||
border-radius: 0.5rem;
|
||||
min-height: 60vh;
|
||||
height: 100%;
|
||||
padding: .1px 2rem 1.5rem 2rem;
|
||||
}
|
||||
|
||||
h1,h2,h3,h4 {
|
||||
margin: 1.5rem 0;
|
||||
padding: 0;
|
||||
}
|
||||
h1 {
|
||||
font-size: 3rem;
|
||||
}
|
||||
h2 {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.container {
|
||||
border-radius: 0.5rem;
|
||||
}
|
||||
|
||||
hr {
|
||||
margin: 2.5rem 1rem;
|
||||
height: 1px;
|
||||
background-color: var(--text-color);
|
||||
border: none
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#bar-graph {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 55px;
|
||||
display: flex;
|
||||
flex-direction: row-reverse;
|
||||
border-radius: 0.4rem;
|
||||
/*overflow: hidden;*/
|
||||
/*margin: 2rem 0;*/
|
||||
background-color: var(--page-background-color-40);
|
||||
}
|
||||
|
||||
.event.error {
|
||||
/* position: absolute;
|
||||
height: 100%;
|
||||
width: 0.5rem;*/
|
||||
background-color: var(--red);
|
||||
}
|
||||
|
||||
.event {
|
||||
height: 100%;
|
||||
width: 1rem;
|
||||
background-color: var(--green);
|
||||
position: relative;
|
||||
transition: transform 0.1s ease;
|
||||
}
|
||||
.event:not(:last-of-type) {
|
||||
margin-left: 1px;
|
||||
}
|
||||
|
||||
.event .tooltip {
|
||||
visibility: hidden;
|
||||
background-color: var(--page-background-color-80);
|
||||
text-align: center;
|
||||
padding: 0.4rem;
|
||||
border-radius: 0.2rem;
|
||||
position: absolute;
|
||||
width: max-content;
|
||||
top: calc(100% + 1rem);
|
||||
left: 50%;
|
||||
margin-left: -5rem;
|
||||
}
|
||||
.event:hover {
|
||||
transform: scale(1.2);
|
||||
z-index: 1;
|
||||
box-shadow: -2px -2px 4px rgba(0,0,0,0.4),
|
||||
2px 2px 4px rgba(0,0,0,0.4);
|
||||
}
|
||||
.event:hover .tooltip {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
/*.error:nth-of-type(1) {
|
||||
left: 2rem;
|
||||
}
|
||||
.error:nth-of-type(2) {
|
||||
left: 22rem;
|
||||
}
|
||||
.error:nth-of-type(3) {
|
||||
right: 12rem;
|
||||
}*/
|
||||
|
||||
.color-indicators {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
margin: 1rem 0;
|
||||
}
|
||||
|
||||
.color-indicator-box {
|
||||
display: block;
|
||||
width: 1.1rem;
|
||||
height: 1.1rem;
|
||||
border-radius: 0.2rem;
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
|
||||
.color-indicators .color-indicator-box:not(:first-of-type) {
|
||||
margin-left: 1.5rem;
|
||||
}
|
||||
.color-indicators span {
|
||||
font-size: 1.1rem;
|
||||
font-weight: 500;
|
||||
letter-spacing: 1.5px;
|
||||
}
|
||||
/*.color-indicator-box:first-child) {
|
||||
background-color: red;
|
||||
}*/
|
||||
|
||||
.green {
|
||||
background-color: var(--green);
|
||||
}
|
||||
.red {
|
||||
background-color: var(--red);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#log-table {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
th {
|
||||
text-align: left;
|
||||
padding: 0.2rem 0.4rem;
|
||||
}
|
||||
|
||||
tr {
|
||||
font-size: 1.2rem;
|
||||
margin: 0.3rem 0;
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
td {
|
||||
padding: 0.6rem 0.4rem;
|
||||
}
|
||||
|
||||
tr td:first-child {
|
||||
border-radius: 0.3rem 0 0 0.3rem;
|
||||
}
|
||||
tr td:last-child {
|
||||
border-radius: 0 0.3rem 0.3rem 0;
|
||||
}
|
||||
tbody tr:hover {
|
||||
background-color: var(--page-background-color);
|
||||
transform: scale(1.01);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#popover {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
background-color: var(--page-background-color-40);
|
||||
}
|
||||
#popover .container {
|
||||
width: 70%;
|
||||
height: 80%;
|
||||
background-color: var(--background-color);
|
||||
border-radius: 0.75rem;
|
||||
}
|
||||
Reference in New Issue
Block a user