mirror of
				https://github.com/louislam/uptime-kuma.git
				synced 2025-11-01 03:49:24 +08:00 
			
		
		
		
	Feat: Display recent ping chart
This commit is contained in:
		
							
								
								
									
										84
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										84
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							| @@ -1779,6 +1779,16 @@ | ||||
|       "integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==", | ||||
|       "dev": true | ||||
|     }, | ||||
|     "chart.js": { | ||||
|       "version": "3.5.0", | ||||
|       "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-3.5.0.tgz", | ||||
|       "integrity": "sha512-J1a4EAb1Gi/KbhwDRmoovHTRuqT8qdF0kZ4XgwxpGethJHUdDrkqyPYwke0a+BuvSeUxPf8Cos6AX2AB8H8GLA==" | ||||
|     }, | ||||
|     "chartjs-adapter-dayjs": { | ||||
|       "version": "1.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/chartjs-adapter-dayjs/-/chartjs-adapter-dayjs-1.0.0.tgz", | ||||
|       "integrity": "sha512-EnbVqTJGFKLpg1TROLdCEufrzbmIa2oeLGx8O2Wdjw2EoMudoOo9+YFu+6CM0Z0hQ/v3yq/e/Y6efQMu22n8Jg==" | ||||
|     }, | ||||
|     "chokidar": { | ||||
|       "version": "3.5.2", | ||||
|       "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", | ||||
| @@ -6814,11 +6824,85 @@ | ||||
|         "@vue/shared": "3.2.1" | ||||
|       } | ||||
|     }, | ||||
|     "vue-chart-3": { | ||||
|       "version": "0.5.7", | ||||
|       "resolved": "https://registry.npmjs.org/vue-chart-3/-/vue-chart-3-0.5.7.tgz", | ||||
|       "integrity": "sha512-BccfPv2rodY6IOppYHvMluVmIJE1CHfp5uW2DXrHrm1kIzaafLwpQ5SwdrxuCevn/QhKoi7azzcxwRcoWbX9hg==", | ||||
|       "requires": { | ||||
|         "@vue/runtime-core": "^3.2.1", | ||||
|         "@vue/runtime-dom": "^3.2.1", | ||||
|         "csstype": "^3.0.8", | ||||
|         "lodash": "^4.17.21", | ||||
|         "nanoid": "^3.1.23", | ||||
|         "vue-demi": "^0.10.1" | ||||
|       }, | ||||
|       "dependencies": { | ||||
|         "@vue/reactivity": { | ||||
|           "version": "3.2.1", | ||||
|           "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.2.1.tgz", | ||||
|           "integrity": "sha512-4Lja2KmyiKvuraDed6dXK2A6+r/7x7xGDA7vVR2Aqc8hQVu0+FWeVX+IBfiVOSpbZXFlHLNmCBFkbuWLQSlgxg==", | ||||
|           "requires": { | ||||
|             "@vue/shared": "3.2.1" | ||||
|           } | ||||
|         }, | ||||
|         "@vue/runtime-core": { | ||||
|           "version": "3.2.1", | ||||
|           "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.2.1.tgz", | ||||
|           "integrity": "sha512-IsgelRM/5hYeRhz5+ECi66XvYDdjG2t4lARjHvCXw5s9Q4N6uIbjLMwtLzAWRxYf3/y258BrD+ehxAi943ScJg==", | ||||
|           "requires": { | ||||
|             "@vue/reactivity": "3.2.1", | ||||
|             "@vue/shared": "3.2.1" | ||||
|           } | ||||
|         }, | ||||
|         "@vue/runtime-dom": { | ||||
|           "version": "3.2.1", | ||||
|           "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.2.1.tgz", | ||||
|           "integrity": "sha512-bUAHUSe49A5wYdHQ8wsLU1CMPXaG2fRuv2661mx/6Q9+20QxglT3ss8ZeL6AVRu16JNJMcdvTTsNpbnMbVc/lQ==", | ||||
|           "requires": { | ||||
|             "@vue/runtime-core": "3.2.1", | ||||
|             "@vue/shared": "3.2.1", | ||||
|             "csstype": "^2.6.8" | ||||
|           }, | ||||
|           "dependencies": { | ||||
|             "csstype": { | ||||
|               "version": "2.6.17", | ||||
|               "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.17.tgz", | ||||
|               "integrity": "sha512-u1wmTI1jJGzCJzWndZo8mk4wnPTZd1eOIYTYvuEyOQGfmDl3TrabCCfKnOC86FZwW/9djqTl933UF/cS425i9A==" | ||||
|             } | ||||
|           } | ||||
|         }, | ||||
|         "@vue/shared": { | ||||
|           "version": "3.2.1", | ||||
|           "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.1.tgz", | ||||
|           "integrity": "sha512-INN92dVBNgd0TW9BqfQQKx/HWGCHhUUbAV5EZ5FgSCiEdwuZsJbGt1mdnaD9IxGhpiyOjP2ClxGG8SFp7ELcWg==" | ||||
|         }, | ||||
|         "csstype": { | ||||
|           "version": "3.0.8", | ||||
|           "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.8.tgz", | ||||
|           "integrity": "sha512-jXKhWqXPmlUeoQnF/EhTtTl4C9SnrxSH/jZUih3jmO6lBKr99rP3/+FmrMj4EFpOXzMtXHAZkd3x0E6h6Fgflw==" | ||||
|         }, | ||||
|         "lodash": { | ||||
|           "version": "4.17.21", | ||||
|           "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", | ||||
|           "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" | ||||
|         }, | ||||
|         "nanoid": { | ||||
|           "version": "3.1.23", | ||||
|           "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.23.tgz", | ||||
|           "integrity": "sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw==" | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "vue-confirm-dialog": { | ||||
|       "version": "1.0.2", | ||||
|       "resolved": "https://registry.npmjs.org/vue-confirm-dialog/-/vue-confirm-dialog-1.0.2.tgz", | ||||
|       "integrity": "sha512-gTo1bMDWOLd/6ihmWv8VlPxhc9QaKoE5YqlsKydUOfrrQ3Q3taljF6yI+1TMtAtJLrvZ8DYrePhgBhY1VCJzbQ==" | ||||
|     }, | ||||
|     "vue-demi": { | ||||
|       "version": "0.10.1", | ||||
|       "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.10.1.tgz", | ||||
|       "integrity": "sha512-L6Oi+BvmMv6YXvqv5rJNCFHEKSVu7llpWWJczqmAQYOdmPPw5PNYoz1KKS//Fxhi+4QP64dsPjtmvnYGo1jemA==" | ||||
|     }, | ||||
|     "vue-eslint-parser": { | ||||
|       "version": "7.10.0", | ||||
|       "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-7.10.0.tgz", | ||||
|   | ||||
| @@ -31,11 +31,14 @@ | ||||
|         "@fortawesome/free-regular-svg-icons": "^5.15.4", | ||||
|         "@fortawesome/free-solid-svg-icons": "^5.15.4", | ||||
|         "@fortawesome/vue-fontawesome": "^3.0.0-4", | ||||
|         "@louislam/sqlite3": "^5.0.3", | ||||
|         "@popperjs/core": "^2.9.3", | ||||
|         "args-parser": "^1.3.0", | ||||
|         "axios": "^0.21.1", | ||||
|         "bcrypt": "^5.0.1", | ||||
|         "bootstrap": "^5.1.0", | ||||
|         "chart.js": "^3.5.0", | ||||
|         "chartjs-adapter-dayjs": "^1.0.0", | ||||
|         "command-exists": "^1.2.9", | ||||
|         "dayjs": "^1.10.6", | ||||
|         "express": "^4.17.1", | ||||
| @@ -50,10 +53,10 @@ | ||||
|         "redbean-node": "0.0.21", | ||||
|         "socket.io": "^4.1.3", | ||||
|         "socket.io-client": "^4.1.3", | ||||
|         "@louislam/sqlite3": "^5.0.3", | ||||
|         "tcp-ping": "^0.1.1", | ||||
|         "v-pagination-3": "^0.1.6", | ||||
|         "vue": "^3.2.1", | ||||
|         "vue-chart-3": "^0.5.7", | ||||
|         "vue-confirm-dialog": "^1.0.2", | ||||
|         "vue-multiselect": "^3.0.0-alpha.2", | ||||
|         "vue-router": "^4.0.10", | ||||
|   | ||||
							
								
								
									
										91
									
								
								src/components/PingChart.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								src/components/PingChart.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,91 @@ | ||||
| <template> | ||||
|     <LineChart :chart-data="chartData" :height="100" :options="chartOptions" /> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import { Chart, registerables } from "chart.js"; | ||||
| import dayjs from "dayjs"; | ||||
| import utc from "dayjs/plugin/utc"; | ||||
| import timezone from "dayjs/plugin/timezone"; | ||||
| import "chartjs-adapter-dayjs"; | ||||
| import { LineChart } from "vue-chart-3"; | ||||
| dayjs.extend(utc); | ||||
| dayjs.extend(timezone); | ||||
|  | ||||
| Chart.register(...registerables); | ||||
|  | ||||
| export default { | ||||
|     components: { LineChart }, | ||||
|     props: { | ||||
|         monitorId: { | ||||
|             type: Number, | ||||
|             required: true, | ||||
|         }, | ||||
|     }, | ||||
|     data() { | ||||
|         return { | ||||
|             chartPeriodHrs: 24, | ||||
|         }; | ||||
|     }, | ||||
|     computed: { | ||||
|         chartOptions() { | ||||
|             return { | ||||
|                 responsive: true, | ||||
|                 layout: { | ||||
|                     padding: { | ||||
|                         left: 10, | ||||
|                         right: 30, | ||||
|                         top: 30, | ||||
|                         bottom: 10, | ||||
|                     }, | ||||
|                 }, | ||||
|                 scales: { | ||||
|                     x: { | ||||
|                         type: "time", | ||||
|                         time: { | ||||
|                             stepSize: 30, | ||||
|                         }, | ||||
|                     }, | ||||
|                     y: { | ||||
|                         title: { | ||||
|                             display: true, | ||||
|                             text: "Response Time (ms)", | ||||
|                         }, | ||||
|                     } | ||||
|                 }, | ||||
|                 bounds: "ticks", | ||||
|                 plugins: { | ||||
|                     legend: { | ||||
|                         display: false, | ||||
|                     }, | ||||
|                 }, | ||||
|             } | ||||
|         }, | ||||
|         chartData() { | ||||
|             let data = []; | ||||
|             if (this.monitorId in this.$root.heartbeatList) { | ||||
|                 data = this.$root.heartbeatList[this.monitorId] | ||||
|                     .filter( | ||||
|                         (beat) => dayjs.utc(beat.time).tz(this.$root.timezone).isAfter(dayjs().subtract(this.chartPeriodHrs, "hours"))) | ||||
|                     .map((beat) => { | ||||
|                         return { | ||||
|                             x: dayjs.utc(beat.time).tz(this.$root.timezone).format("YYYY-MM-DD HH:mm:ss"), | ||||
|                             y: beat.ping, | ||||
|                         }; | ||||
|                     }); | ||||
|             } | ||||
|             return { | ||||
|                 datasets: [ | ||||
|                     { | ||||
|                         data: data, | ||||
|                         fill: "origin", | ||||
|                         tension: 0.2, | ||||
|                         borderColor: "#5CDD8B", | ||||
|                         backgroundColor: "#5CDD8B38", | ||||
|                     }, | ||||
|                 ], | ||||
|             }; | ||||
|         }, | ||||
|     }, | ||||
| }; | ||||
| </script> | ||||
| @@ -42,7 +42,11 @@ | ||||
|             <div class="col"> | ||||
|                 <h4>{{ pingTitle }}</h4> | ||||
|                 <p>(Current)</p> | ||||
|                 <span class="num"><CountUp :value="ping" /></span> | ||||
|                 <span class="num"> | ||||
|                     <a href="#" @click.prevent="showPingChartBox = !showPingChartBox"> | ||||
|                         <CountUp :value="ping" /> | ||||
|                     </a> | ||||
|                 </span> | ||||
|             </div> | ||||
|             <div class="col"> | ||||
|                 <h4>Avg. {{ pingTitle }}</h4> | ||||
| @@ -70,6 +74,14 @@ | ||||
|         </div> | ||||
|     </div> | ||||
|  | ||||
|     <div v-if="showPingChartBox" class="shadow-box big-padding text-center"> | ||||
|         <div class="row"> | ||||
|             <div class="col"> | ||||
|                 <PingChart :monitor-id="monitor.id" /> | ||||
|             </div> | ||||
|         </div> | ||||
|     </div> | ||||
|  | ||||
|     <div v-if="showCertInfoBox" class="shadow-box big-padding text-center"> | ||||
|         <div class="row"> | ||||
|             <div class="col"> | ||||
| @@ -164,6 +176,7 @@ import Datetime from "../components/Datetime.vue"; | ||||
| import CountUp from "../components/CountUp.vue"; | ||||
| import Uptime from "../components/Uptime.vue"; | ||||
| import Pagination from "v-pagination-3"; | ||||
| import PingChart from "../components/PingChart.vue"; | ||||
|  | ||||
| export default { | ||||
|     components: { | ||||
| @@ -174,6 +187,7 @@ export default { | ||||
|         Confirm, | ||||
|         Status, | ||||
|         Pagination, | ||||
|         PingChart, | ||||
|     }, | ||||
|     data() { | ||||
|         return { | ||||
| @@ -181,6 +195,7 @@ export default { | ||||
|             perPage: 25, | ||||
|             heartBeatList: [], | ||||
|             toggleCertInfoBox: false, | ||||
|             showPingChartBox: false, | ||||
|         } | ||||
|     }, | ||||
|     computed: { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user