diff --git a/components/Header.tsx b/components/Header.tsx index c1605ab..cfc5870 100644 --- a/components/Header.tsx +++ b/components/Header.tsx @@ -34,11 +34,9 @@ export default function Header() {
- + {items} - -
); diff --git a/components/MonitorDetail.tsx b/components/MonitorDetail.tsx new file mode 100644 index 0000000..e69de29 diff --git a/components/MonitorList.tsx b/components/MonitorList.tsx new file mode 100644 index 0000000..e4c3edd --- /dev/null +++ b/components/MonitorList.tsx @@ -0,0 +1,67 @@ +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)', + } + ], +}; + + +export default function MonitorList({ config, state }: { config: any, state: MonitorState }) { + + return ( +
+ + {config.monitors.map((monitor: MonitorTarget) => ( +
+ + {monitor.name} + + + +
+ ))} +
+
+ ); +} + diff --git a/components/OverallStatus.tsx b/components/OverallStatus.tsx index ca1b478..35351e9 100644 --- a/components/OverallStatus.tsx +++ b/components/OverallStatus.tsx @@ -1,32 +1,27 @@ -import { Center, Space, Title } from '@mantine/core' +import { Center, Title } from '@mantine/core' import { IconCircleCheck, IconAlertCircle } from '@tabler/icons-react' export default function OverallStatus({ state }: { state: { overallUp: number, overallDown: number, lastUpdate: number }}) { let statusString = '' - let icon = + let icon = if (state.overallUp === 0 && state.overallDown === 0) { statusString = 'No data yet' } else if (state.overallUp === 0) { - statusString = 'All down' + statusString = 'All systems not operational' } else if (state.overallDown === 0) { - statusString = 'All up' - icon = + statusString = 'All systems operational' + icon = } else { - statusString = `${state.overallUp} up, ${state.overallDown} down` + statusString = `Some systems not operational (${state.overallDown} out of ${state.overallUp + state.overallDown})` } return (<>
{icon}
- -
- {statusString} -
-
- Last updated on: {new Date(state.lastUpdate * 1000).toLocaleString()} -
+ {statusString} + Last updated on: {new Date(state.lastUpdate * 1000).toLocaleString()} ({Math.round(Date.now() / 1000) - state.lastUpdate} sec ago) ) } diff --git a/package-lock.json b/package-lock.json index 53665de..db8556f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,8 +13,10 @@ "@mantine/ds": "^7.1.3", "@mantine/hooks": "^7.1.3", "@tabler/icons-react": "^2.39.0", + "chart.js": "^4.4.0", "next": "13.5.4", "react": "^18", + "react-chartjs-2": "^5.2.0", "react-dom": "^18" }, "devDependencies": { @@ -664,6 +666,11 @@ "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", "dev": true }, + "node_modules/@kurkle/color": { + "version": "0.3.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/@kurkle/color/-/color-0.3.2.tgz", + "integrity": "sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw==" + }, "node_modules/@mantine/code-highlight": { "version": "7.1.3", "resolved": "https://mirrors.cloud.tencent.com/npm/@mantine/code-highlight/-/code-highlight-7.1.3.tgz", @@ -1534,6 +1541,17 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/chart.js": { + "version": "4.4.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/chart.js/-/chart.js-4.4.0.tgz", + "integrity": "sha512-vQEj6d+z0dcsKLlQvbKIMYFHd3t8W/7L2vfJIbYcfyPcRx92CsHqECpueN8qVGNlKyDcr5wBrYAYKnfu/9Q1hQ==", + "dependencies": { + "@kurkle/color": "^0.3.0" + }, + "engines": { + "pnpm": ">=7" + } + }, "node_modules/chokidar": { "version": "3.5.3", "resolved": "https://mirrors.cloud.tencent.com/npm/chokidar/-/chokidar-3.5.3.tgz", @@ -4007,6 +4025,15 @@ "node": ">=0.10.0" } }, + "node_modules/react-chartjs-2": { + "version": "5.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/react-chartjs-2/-/react-chartjs-2-5.2.0.tgz", + "integrity": "sha512-98iN5aguJyVSxp5U3CblRLH67J8gkfyGNbiK3c+l1QI/G4irHMPQw44aEPmjVag+YKTyQ260NcF82GTQ3bdscA==", + "peerDependencies": { + "chart.js": "^4.1.1", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/react-dom": { "version": "18.2.0", "resolved": "https://mirrors.cloud.tencent.com/npm/react-dom/-/react-dom-18.2.0.tgz", @@ -5489,6 +5516,11 @@ "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", "dev": true }, + "@kurkle/color": { + "version": "0.3.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/@kurkle/color/-/color-0.3.2.tgz", + "integrity": "sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw==" + }, "@mantine/code-highlight": { "version": "7.1.3", "resolved": "https://mirrors.cloud.tencent.com/npm/@mantine/code-highlight/-/code-highlight-7.1.3.tgz", @@ -6072,6 +6104,14 @@ "supports-color": "^7.1.0" } }, + "chart.js": { + "version": "4.4.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/chart.js/-/chart.js-4.4.0.tgz", + "integrity": "sha512-vQEj6d+z0dcsKLlQvbKIMYFHd3t8W/7L2vfJIbYcfyPcRx92CsHqECpueN8qVGNlKyDcr5wBrYAYKnfu/9Q1hQ==", + "requires": { + "@kurkle/color": "^0.3.0" + } + }, "chokidar": { "version": "3.5.3", "resolved": "https://mirrors.cloud.tencent.com/npm/chokidar/-/chokidar-3.5.3.tgz", @@ -7871,6 +7911,12 @@ "loose-envify": "^1.1.0" } }, + "react-chartjs-2": { + "version": "5.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/react-chartjs-2/-/react-chartjs-2-5.2.0.tgz", + "integrity": "sha512-98iN5aguJyVSxp5U3CblRLH67J8gkfyGNbiK3c+l1QI/G4irHMPQw44aEPmjVag+YKTyQ260NcF82GTQ3bdscA==", + "requires": {} + }, "react-dom": { "version": "18.2.0", "resolved": "https://mirrors.cloud.tencent.com/npm/react-dom/-/react-dom-18.2.0.tgz", diff --git a/package.json b/package.json index 7e54c78..e4b6969 100644 --- a/package.json +++ b/package.json @@ -14,8 +14,10 @@ "@mantine/ds": "^7.1.3", "@mantine/hooks": "^7.1.3", "@tabler/icons-react": "^2.39.0", + "chart.js": "^4.4.0", "next": "13.5.4", "react": "^18", + "react-chartjs-2": "^5.2.0", "react-dom": "^18" }, "devDependencies": { diff --git a/pages/index.tsx b/pages/index.tsx index 006b2de..d6e3262 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -1,3 +1,5 @@ +'use client' + import Head from 'next/head' import { Inter } from 'next/font/google' @@ -6,6 +8,7 @@ import { KVNamespace } from '@cloudflare/workers-types' import config from '@/uptime.config' import OverallStatus from '@/components/OverallStatus' import Header from '@/components/Header' +import MonitorList from '@/components/MonitorList' export const runtime = 'experimental-edge' const inter = Inter({ subsets: ['latin'] }) @@ -19,18 +22,10 @@ export default function Home({ state }: { state: MonitorState }) {
-
- - { - config.monitors.map(monitor => ( -
-

{monitor.name}

-
- )) - } -

{JSON.stringify(state)}

+ + {/*

{JSON.stringify(state)}

*/}
)