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