diff --git a/components/MonitorDetail.tsx b/components/MonitorDetail.tsx
index e69de29..0b21c06 100644
--- a/components/MonitorDetail.tsx
+++ b/components/MonitorDetail.tsx
@@ -0,0 +1,93 @@
+
+import { Line } from "react-chartjs-2"
+import { Text } from "@mantine/core"
+import { Chart as ChartJS, CategoryScale, LinearScale, PointElement, LineElement, Title, Tooltip, Legend, TimeScale } from 'chart.js'
+import { MonitorState, MonitorTarget } from "@/uptime.types";
+import 'chartjs-adapter-moment'
+import { IconAlertCircle, IconCircleCheck } from "@tabler/icons-react";
+
+ChartJS.register(
+ CategoryScale,
+ LinearScale,
+ PointElement,
+ LineElement,
+ Title,
+ Tooltip,
+ Legend,
+ TimeScale
+)
+
+
+export default function MonitorDetail({ monitor, state }: { monitor: MonitorTarget, state: MonitorState }) {
+
+ if (!state.latency[monitor.id]) return (
+ <>
+ {monitor.name}
+ No data available, please make sure you have deployed your workers with latest config and check your worker status!
+ >
+ )
+
+ const statusIcon = (state.incident[monitor.id].slice(-1)[0] ?? { end: 'dummy' }).end === undefined ? :
+
+ const latencyData = state.latency[monitor.id].recent.map((point) => ({ x: point.time * 1000, y: point.ping, loc: point.loc }))
+
+ let data = {
+ datasets: [
+ {
+ data: latencyData,
+ borderColor: 'rgb(112, 119, 140)',
+ borderWidth: 2,
+ radius: 0,
+ cubicInterpolationMode: 'monotone' as const,
+ tension: 0.4
+ }
+ ]
+ }
+
+ let options = {
+ responsive: true,
+ maintainAspectRatio: false,
+ interaction: {
+ mode: 'index' as const,
+ intersect: false,
+ },
+ plugins: {
+ tooltip: {
+ callbacks: {
+ label: (item: any) => {
+ if (item.parsed.y) {
+ return `${item.parsed.y}ms (${item.raw.loc})`
+ }
+ }
+ }
+ },
+ legend: {
+ display: false
+ },
+ title: {
+ display: true,
+ text: 'Response times(ms)',
+ align: 'start' as const
+ },
+ },
+ scales: {
+ x: {
+ type: 'time' as const,
+ ticks: {
+ source: 'auto' as const,
+ maxRotation: 0,
+ autoSkip: true
+ }
+ }
+ }
+ }
+
+ return (
+ <>
+ {statusIcon} {monitor.name}
+
+
+
+ >
+ )
+}
\ No newline at end of file
diff --git a/components/MonitorList.tsx b/components/MonitorList.tsx
index e4c3edd..dd16a00 100644
--- a/components/MonitorList.tsx
+++ b/components/MonitorList.tsx
@@ -1,50 +1,6 @@
import { MonitorState, MonitorTarget } from "@/uptime.types";
-import { Card, Center, Divider, Text } from "@mantine/core";
-import { Chart as ChartJS, CategoryScale, LinearScale, PointElement, LineElement, Title, Tooltip, Legend } from 'chart.js';
-import { Line } from "react-chartjs-2";
-
-ChartJS.register(
- CategoryScale,
- LinearScale,
- PointElement,
- LineElement,
- Title,
- Tooltip,
- Legend
-);
-
-
-export const options = {
- responsive: true,
- interaction: {
- mode: 'index' as const,
- intersect: false,
- },
- plugins: {
- legend: {
- position: 'top' as const,
- },
- title: {
- display: true,
- text: 'Response times',
- align: 'start' as const
- },
- },
-};
-
-const labels = ['January', 'February', 'March', 'April', 'May', 'June', 'July'];
-
-export const data = {
- labels,
- datasets: [
- {
- data: labels.map(() => Math.round(Math.random() * 1000)),
- borderColor: 'rgb(255, 99, 132)',
- backgroundColor: 'rgba(255, 99, 132, 0.5)',
- }
- ],
-};
-
+import { Card, Center, Divider } from "@mantine/core";
+import MonitorDetail from "./MonitorDetail";
export default function MonitorList({ config, state }: { config: any, state: MonitorState }) {
@@ -53,15 +9,14 @@ export default function MonitorList({ config, state }: { config: any, state: Mon
{config.monitors.map((monitor: MonitorTarget) => (
))}
- );
+ )
}
diff --git a/package-lock.json b/package-lock.json
index db8556f..b523866 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -14,6 +14,8 @@
"@mantine/hooks": "^7.1.3",
"@tabler/icons-react": "^2.39.0",
"chart.js": "^4.4.0",
+ "chartjs-adapter-moment": "^1.0.1",
+ "moment": "^2.29.4",
"next": "13.5.4",
"react": "^18",
"react-chartjs-2": "^5.2.0",
@@ -1552,6 +1554,15 @@
"pnpm": ">=7"
}
},
+ "node_modules/chartjs-adapter-moment": {
+ "version": "1.0.1",
+ "resolved": "https://mirrors.cloud.tencent.com/npm/chartjs-adapter-moment/-/chartjs-adapter-moment-1.0.1.tgz",
+ "integrity": "sha512-Uz+nTX/GxocuqXpGylxK19YG4R3OSVf8326D+HwSTsNw1LgzyIGRo+Qujwro1wy6X+soNSnfj5t2vZ+r6EaDmA==",
+ "peerDependencies": {
+ "chart.js": ">=3.0.0",
+ "moment": "^2.10.2"
+ }
+ },
"node_modules/chokidar": {
"version": "3.5.3",
"resolved": "https://mirrors.cloud.tencent.com/npm/chokidar/-/chokidar-3.5.3.tgz",
@@ -3480,6 +3491,14 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/moment": {
+ "version": "2.29.4",
+ "resolved": "https://mirrors.cloud.tencent.com/npm/moment/-/moment-2.29.4.tgz",
+ "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==",
+ "engines": {
+ "node": "*"
+ }
+ },
"node_modules/ms": {
"version": "2.1.2",
"resolved": "https://mirrors.cloud.tencent.com/npm/ms/-/ms-2.1.2.tgz",
@@ -6112,6 +6131,12 @@
"@kurkle/color": "^0.3.0"
}
},
+ "chartjs-adapter-moment": {
+ "version": "1.0.1",
+ "resolved": "https://mirrors.cloud.tencent.com/npm/chartjs-adapter-moment/-/chartjs-adapter-moment-1.0.1.tgz",
+ "integrity": "sha512-Uz+nTX/GxocuqXpGylxK19YG4R3OSVf8326D+HwSTsNw1LgzyIGRo+Qujwro1wy6X+soNSnfj5t2vZ+r6EaDmA==",
+ "requires": {}
+ },
"chokidar": {
"version": "3.5.3",
"resolved": "https://mirrors.cloud.tencent.com/npm/chokidar/-/chokidar-3.5.3.tgz",
@@ -7563,6 +7588,11 @@
"integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
"dev": true
},
+ "moment": {
+ "version": "2.29.4",
+ "resolved": "https://mirrors.cloud.tencent.com/npm/moment/-/moment-2.29.4.tgz",
+ "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w=="
+ },
"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 e4b6969..e7b109e 100644
--- a/package.json
+++ b/package.json
@@ -15,6 +15,8 @@
"@mantine/hooks": "^7.1.3",
"@tabler/icons-react": "^2.39.0",
"chart.js": "^4.4.0",
+ "chartjs-adapter-moment": "^1.0.1",
+ "moment": "^2.29.4",
"next": "13.5.4",
"react": "^18",
"react-chartjs-2": "^5.2.0",
diff --git a/pages/index.tsx b/pages/index.tsx
index d6e3262..95afc44 100644
--- a/pages/index.tsx
+++ b/pages/index.tsx
@@ -35,6 +35,6 @@ export default function Home({ state }: { state: MonitorState }) {
export async function getServerSideProps() {
const { UPTIMEFLARE_STATE } = process.env as unknown as { UPTIMEFLARE_STATE: KVNamespace }
const state = await UPTIMEFLARE_STATE.get('state', 'json') as unknown as MonitorState
-
+
return { props: { state } }
}
diff --git a/uptime.config.ts b/uptime.config.ts
index ad5f279..0ef7021 100644
--- a/uptime.config.ts
+++ b/uptime.config.ts
@@ -28,12 +28,33 @@ const config = {
method: 'GET',
target: 'https://cloudflare.com',
expectedCode: [200],
- timeout: 5,
+ timeout: 10000,
headers: {
"User-Agent": "Uptimeflare"
},
body: undefined
},
+ {
+ id: 'blog',
+ name: 'My Blog',
+ method: 'GET',
+ target: 'https://blog.lyc8503.site',
+ timeout: 10000
+ },
+ {
+ id: 'pan',
+ name: 'My Fileshare',
+ method: 'GET',
+ target: 'https://pan.lyc8503.site',
+ timeout: 10000
+ },
+ {
+ id: 'server',
+ name: 'My Aliyun Server',
+ method: 'GET',
+ target: 'https://server.lyc8503.site',
+ timeout: 10000
+ },
{
id: 'broken-test',
name: 'Ping 1.1.1.1',