diff --git a/components/DetailBar.tsx b/components/DetailBar.tsx index 1f63748..18d90a0 100644 --- a/components/DetailBar.tsx +++ b/components/DetailBar.tsx @@ -1,5 +1,10 @@ import { MonitorState, MonitorTarget } from '@/uptime.types' +import { getColor } from '@/util/color' import { Box, Tooltip } from '@mantine/core' +import { useResizeObserver } from '@mantine/hooks' +import { useLayoutEffect, useRef, useState } from 'react' +const moment = require('moment') +require('moment-precise-range-plugin') export default function DetailBar({ monitor, @@ -8,29 +13,59 @@ export default function DetailBar({ monitor: MonitorTarget state: MonitorState }) { - // const day = new Date() - // day.setHours(0, 0, 0, 0) - // const dayStart = day.getTime() + const [barRef, barRect] = useResizeObserver() const overlapLen = (x1: number, x2: number, y1: number, y2: number) => { - return Math.max(0, Math.min(x2, y2) - Math.max(x1, y1) + 1) + return Math.max(0, Math.min(x2, y2) - Math.max(x1, y1)) } const uptimePercentBars = [] - for (let i = 89; i > 0; i--) { - let dayDownTime = 0 - let dayTotalTime = 0 + const currentTime = Math.round(Date.now() / 1000) + const montiorStartTime = state.incident[monitor.id][0].start[0] - // if (state.incident[monitor.id][0].end) + const todayStart = new Date() + todayStart.setHours(0, 0, 0, 0) + + for (let i = 89; i > 0; i--) { + const dayStart = Math.round(todayStart.getTime() / 1000) - i * 86400 + const dayEnd = dayStart + 86400 + + const dayMonitorTime = overlapLen(dayStart, dayEnd, montiorStartTime, currentTime) + let dayDownTime = 0 + + for (let incident of state.incident[monitor.id]) { + const incidentStart = incident.start[0] + const incidentEnd = incident.end ?? currentTime + + dayDownTime += overlapLen(dayStart, dayEnd, incidentStart, incidentEnd) + } + + const dayPercent = (((dayMonitorTime - dayDownTime) / dayMonitorTime) * 100).toPrecision(4) uptimePercentBars.push( - + +
{dayPercent + '%'}
+ {dayDownTime > 0 && ( +
{`Down for ${moment.preciseDiff(moment(0), moment(dayDownTime * 1000))}`}
+ )} + {/* TODO: lantency detail for each bar */} + + ) + } + >
- {uptimePercentBars} + {uptimePercentBars.slice(Math.floor(Math.max(9 * 90 - barRect.width, 0) / 9), 90)} - - {/* - {uptimePercentBars.slice(-60)} - - - - {uptimePercentBars.slice(-30)} - */} ) } diff --git a/components/MonitorDetail.tsx b/components/MonitorDetail.tsx index 03166e8..da78228 100644 --- a/components/MonitorDetail.tsx +++ b/components/MonitorDetail.tsx @@ -3,19 +3,7 @@ import { MonitorState, MonitorTarget } from '@/uptime.types' import { IconAlertCircle, IconCircleCheck } from '@tabler/icons-react' import DetailChart from './DetailChart' import DetailBar from './DetailBar' - -function getColor(percent: number | string, darker: boolean): string { - percent = Number(percent) - if (percent >= 99.9) { - return darker ? '#059669' : '#3bd671' - } else if (percent >= 99) { - return darker ? '#3bd671' : '#9deab8' - } else if (percent >= 95) { - return '#f29030' - } else { - return '#df484a' - } -} +import { getColor } from '@/util/color' export default function MonitorDetail({ monitor, @@ -50,8 +38,6 @@ export default function MonitorDetail({ downTime += (incident.end ?? Date.now() / 1000) - incident.start[0] } - console.log(totalTime) - console.log(downTime) const uptimePercent = (((totalTime - downTime) / totalTime) * 100).toPrecision(4) return ( diff --git a/package-lock.json b/package-lock.json index 15e5e29..1a8e07a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,9 +13,11 @@ "@mantine/ds": "^7.1.3", "@mantine/hooks": "^7.1.3", "@tabler/icons-react": "^2.39.0", + "@types/moment-precise-range-plugin": "^0.2.2", "chart.js": "^4.4.0", "chartjs-adapter-moment": "^1.0.1", "moment": "^2.29.4", + "moment-precise-range-plugin": "^1.3.0", "next": "13.5.4", "react": "^18", "react-chartjs-2": "^5.2.0", @@ -972,6 +974,14 @@ "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", "dev": true }, + "node_modules/@types/moment-precise-range-plugin": { + "version": "0.2.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/moment-precise-range-plugin/-/moment-precise-range-plugin-0.2.2.tgz", + "integrity": "sha512-Iof7Z9Ej/LbeE2++cap0SaSpDzMen9hT/ced3BwPhyUl5PWAgxR7sDxx4i0hYTOYshaMqH8hjXD0+CVBBYhEpw==", + "dependencies": { + "moment": ">=2.14.0" + } + }, "node_modules/@types/node": { "version": "20.8.4", "resolved": "https://mirrors.cloud.tencent.com/npm/@types/node/-/node-20.8.4.tgz", @@ -3500,6 +3510,14 @@ "node": "*" } }, + "node_modules/moment-precise-range-plugin": { + "version": "1.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/moment-precise-range-plugin/-/moment-precise-range-plugin-1.3.0.tgz", + "integrity": "sha1-YKwHX9/RRon20QKvdR0XGoC0q2A=", + "peerDependencies": { + "moment": ">=2.9.0" + } + }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://mirrors.cloud.tencent.com/npm/ms/-/ms-2.1.2.tgz", @@ -5728,6 +5746,14 @@ "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", "dev": true }, + "@types/moment-precise-range-plugin": { + "version": "0.2.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/moment-precise-range-plugin/-/moment-precise-range-plugin-0.2.2.tgz", + "integrity": "sha512-Iof7Z9Ej/LbeE2++cap0SaSpDzMen9hT/ced3BwPhyUl5PWAgxR7sDxx4i0hYTOYshaMqH8hjXD0+CVBBYhEpw==", + "requires": { + "moment": ">=2.14.0" + } + }, "@types/node": { "version": "20.8.4", "resolved": "https://mirrors.cloud.tencent.com/npm/@types/node/-/node-20.8.4.tgz", @@ -7609,6 +7635,12 @@ "resolved": "https://mirrors.cloud.tencent.com/npm/moment/-/moment-2.29.4.tgz", "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==" }, + "moment-precise-range-plugin": { + "version": "1.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/moment-precise-range-plugin/-/moment-precise-range-plugin-1.3.0.tgz", + "integrity": "sha1-YKwHX9/RRon20QKvdR0XGoC0q2A=", + "requires": {} + }, "ms": { "version": "2.1.2", "resolved": "https://mirrors.cloud.tencent.com/npm/ms/-/ms-2.1.2.tgz", diff --git a/package.json b/package.json index de7aada..dc93dbb 100644 --- a/package.json +++ b/package.json @@ -14,9 +14,11 @@ "@mantine/ds": "^7.1.3", "@mantine/hooks": "^7.1.3", "@tabler/icons-react": "^2.39.0", + "@types/moment-precise-range-plugin": "^0.2.2", "chart.js": "^4.4.0", "chartjs-adapter-moment": "^1.0.1", "moment": "^2.29.4", + "moment-precise-range-plugin": "^1.3.0", "next": "13.5.4", "react": "^18", "react-chartjs-2": "^5.2.0", diff --git a/util/color.ts b/util/color.ts new file mode 100644 index 0000000..6fce3e7 --- /dev/null +++ b/util/color.ts @@ -0,0 +1,16 @@ +function getColor(percent: number | string, darker: boolean): string { + percent = Number(percent) + if (percent >= 99.9) { + return darker ? '#059669' : '#3bd671' + } else if (percent >= 99) { + return darker ? '#3bd671' : '#9deab8' + } else if (percent >= 95) { + return '#f29030' + } else if (Number.isNaN(percent)) { + return 'gray' + } else { + return '#df484a' + } +} + +export { getColor }