mirror of
				https://github.com/KevinMidboe/ISPDowntimeMonitor.git
				synced 2025-10-29 17:50: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