diff --git a/src/site/SF-Pro-Rounded-Light.otf b/src/site/SF-Pro-Rounded-Light.otf new file mode 100755 index 0000000..94584f4 Binary files /dev/null and b/src/site/SF-Pro-Rounded-Light.otf differ diff --git a/src/site/fetchLogsAndGenerateTable.js b/src/site/fetchLogsAndGenerateTable.js new file mode 100644 index 0000000..3574655 --- /dev/null +++ b/src/site/fetchLogsAndGenerateTable.js @@ -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() \ No newline at end of file diff --git a/src/site/fetchUptimeAndGenerateBarGraph.js b/src/site/fetchUptimeAndGenerateBarGraph.js new file mode 100644 index 0000000..ef1adbc --- /dev/null +++ b/src/site/fetchUptimeAndGenerateBarGraph.js @@ -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) \ No newline at end of file diff --git a/src/site/index.html b/src/site/index.html new file mode 100644 index 0000000..3ce12dd --- /dev/null +++ b/src/site/index.html @@ -0,0 +1,57 @@ + + + + ISP downtime monitor + + + + +

Nedetid rapport

+
+

Oppetid

+
+ +
+ +
+ + Uptime + + + Downtime +
+
+ +

Indicent log

+
+ + + + + + + + + + + + + + + + + + + + + + +
DateIncident messageDuration
31 Mai 2020 22:34OK6d 4t 32min
31 Mai 2020 22:34OK6d 4t 32min
31 Mai 2020 22:34OK6d 4t 32min
+
+ +
+ + + + + \ No newline at end of file diff --git a/src/site/style.css b/src/site/style.css new file mode 100644 index 0000000..ace05fe --- /dev/null +++ b/src/site/style.css @@ -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; +} \ No newline at end of file