Skip to content

Commit

Permalink
Merge pull request #55 from Magickbase/monitor_page_skeleton
Browse files Browse the repository at this point in the history
feat: add loading skeleton
  • Loading branch information
PainterPuppets authored Jan 9, 2024
2 parents 91f193c + 9ba4861 commit 39ca058
Show file tree
Hide file tree
Showing 8 changed files with 191 additions and 41 deletions.
1 change: 1 addition & 0 deletions packages/status/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"@trpc/server": "^10.28.2",
"@uidotdev/usehooks": "^2.4.1",
"classnames": "2.3.2",
"dayjs": "^1.11.10",
"i18next": "^22.5.0",
"next": "13.5.6",
"next-i18next": "^13.2.2",
Expand Down
22 changes: 22 additions & 0 deletions packages/status/src/components/Layout/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { Footer, Header } from '@magickbase-website/shared'
import { api } from '@/utils/api'
import { PropsWithChildren } from 'react'

export const Layout: React.FC<PropsWithChildren> = ({ children }) => {
const aggregateStateQuery = api.uptime.aggregateState.useQuery()

return (
<>
<Header
navMenuGroupName='Status'
navMenus={[
{ name: 'Home', link: '/' },
{ name: 'Index', link: '/stat' },
{ name: 'History Events', link: '/events' },
]}
/>
{children}
<Footer className="snap-always snap-center" serviceState={aggregateStateQuery.data} serviceLink="/status" />
</>
)
}
5 changes: 2 additions & 3 deletions packages/status/src/components/StatusResource/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,8 @@ export const StatusResource: React.FC<StatusResourceProps> = ({ link, resource,
<span className="flex-1 pr-2 mr-2 border-r border-solid border-[#333333]">{link}</span>
<CopyIcon
className="cursor-pointer fill-white hover:fill-[#00CC9B] transition-all"
onClick={() => {
console.log('onclick')
copyToClipboard(link).catch(() => {})
onClick={async () => {
await copyToClipboard(link)
toast.success('copied!')
}}
/>
Expand Down
89 changes: 89 additions & 0 deletions packages/status/src/pages/events.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import dayjs from 'dayjs'
import { FC, useState } from 'react'
import classnames from 'classnames'
import { api } from '@/utils/api'
import { Layout } from '@/components/Layout'

const EventPage: FC<{ page?: number }> = ({ page = 1 }) => {
const incidentsQuery = api.uptime.listStatusIncidents.useQuery({ page })

if (!incidentsQuery.data) {
return new Array(10).fill('').map((_, index) => (
<div key={`skeleton-${index}`} className='skeleton h-[129px] md:h-[41px] w-full' />
))
}

return incidentsQuery.data?.map(incident => {
const intraday =
dayjs(incident.attributes.started_at).format('YYYY-MM-DD') ===
dayjs(incident.attributes.resolved_at).format('YYYY-MM-DD')

return (
<div key={incident.id} className='flex flex-col md:flex-row md:justify-between text-[#F5F5F5] pb-4 border-b border-[#FFFFFF33]'>
<div className='text-nowrap truncate mb-2 md:mb-0'>
{dayjs(incident.attributes.started_at).format('YYYY-MM-DD hh:mm')} ~{' '}
{dayjs(incident.attributes.resolved_at).format(intraday ? 'hh:mm' : 'YYYY-MM-DD hh:mm')}
</div>
<div className='md:text-nowrap md:truncate mb-2 md:mb-0 text-[#999999]'>{incident.attributes.name} is down due to {incident.attributes.cause}</div>

<div className='flex'>
<div className='mr-2 md:hidden'>{incident.attributes.name}</div>
<div className='py-[2px] px-4 rounded-md bg-[#F62A2A] text-sm'>Downtime</div>
</div>
</div>
)
})
}

export default function Event() {
const [page, setPage] = useState(1)
const incidentPages = api.uptime.countIncidentPages.useQuery()

return (
<Layout>
<div className="container mx-auto mb-20 flex flex-col">
<div className="text-xl mb-4 text-[600]">History Events</div>
<div className="border border-[#FFFFFF33] border-solid rounded-3xl p-4 bg-gradient-to-b from-[#36363666] to-[#1D1D1D33]">
<div className='flex flex-col gap-4 mb-8'>
<EventPage key={page} page={page} />
</div>
{incidentPages.data && incidentPages.data > 1 && (
<div className="flex gap-2 justify-center">
<button className={classnames('btn btn-outline hidden md:block')} onClick={() => setPage(1)} disabled={page === 1}>
First
</button>

<button
className={classnames('btn btn-outline')}
onClick={() => setPage(prev => prev - 1)}
disabled={page === 1}
>
Previous
</button>

<button className={classnames('btn btn-outline')} disabled>
Page {page} of {incidentPages.data}
</button>

<button
className={classnames('btn btn-outline')}
onClick={() => setPage(prev => prev + 1)}
disabled={page === incidentPages.data}
>
Next
</button>

<button
className={classnames('btn btn-outline hidden md:block')}
onClick={() => setPage(incidentPages.data)}
disabled={page === incidentPages.data}
>
Last
</button>
</div>
)}
</div>
</div>
</Layout>
)
}
27 changes: 14 additions & 13 deletions packages/status/src/pages/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Footer, Header } from '@magickbase-website/shared'
import { api } from '@/utils/api'
import { TailwindToaster } from '@/components/Toaster'
import { StatusResource } from '@/components/StatusResource'
import { Layout } from '@/components/Layout'
import classNames from 'classnames'

const LinkMap: Record<string, string> = {
Expand All @@ -15,19 +15,11 @@ const LinkMap: Record<string, string> = {
}

export default function Home() {
const aggregateStateQuery = api.uptime.aggregateState.useQuery()
const resourceQuery = api.uptime.listStatusPageResources.useQuery()
const sectionQuery = api.uptime.listStatusPageSections.useQuery()

return (
<>
<Header
githubLink=''
navMenus={[
{ name: 'Home', link: '/' },
{ name: 'Index', link: '/stat' },
]}
/>
<Layout>
<div className="container mx-auto mb-20">
<div className="flex flex-col md:flex-row md:items-center mb-12">
<span className="mr-4 text-4xl font-bold">Service Monitor</span>
Expand All @@ -40,14 +32,24 @@ export default function Home() {
/>
</div>
<div className="flex flex-col gap-12">
{resourceQuery.isLoading && [
<div key='1'>
<div className="text-xl mb-6 skeleton w-40 h-[28px]" />
<div className="w-full h-80 skeleton rounded-3xl" />
</div>,
<div key='2'>
<div className="text-xl mb-6 skeleton w-40 h-[28px]" />
<div className="w-full h-80 skeleton rounded-3xl" />
</div>,
]}
{sectionQuery.data?.map(section => (
<div key={section.attributes.status_page_id}>
<div className="text-xl mb-6">{section.attributes.name}</div>

<div
className={classNames(
'border border-[#FFFFFF33] border-solid rounded-3xl p-6 flex flex-col gap-8',
'bg-gradient-to-b from-[#36363666] to-[#1D1D1D33]',
'bg-gradient-to-b from-[#36363666] to-[rgba(29,29,29,0.2)]',
)}
>
{resourceQuery.data
Expand All @@ -65,7 +67,6 @@ export default function Home() {
</div>
</div>
<TailwindToaster />
<Footer className="snap-always snap-center" serviceState={aggregateStateQuery.data} serviceLink="/status" />
</>
</Layout>
)
}
34 changes: 11 additions & 23 deletions packages/status/src/pages/stat.tsx
Original file line number Diff line number Diff line change
@@ -1,38 +1,28 @@
import { Footer, Header } from '@magickbase-website/shared'
import { Layout } from '@/components/Layout'
import { StatCard } from '@/components/StatCard'
import { api } from '../utils/api'

export default function Stat() {
const aggregateStateQuery = api.uptime.aggregateState.useQuery()

return (
<>
<Header
githubLink=""
navMenus={[
{ name: 'Home', link: '/' },
{ name: 'Index', link: '/stat' },
]}
/>
<Layout>
<div className="container mx-auto mb-20 flex flex-col gap-8">
<div>
<div className="mb-8 text-xl text-[600]">CKB Explorer · Mainnet</div>
<div className="gap-4 grid grid-cols-1 md:grid-cols-3">
<StatCard title="Tip Block Time">
<iframe
src="https://grafana.layerview.io/d-solo/gEWc1Gq4k/ckb-dashboard?orgId=1&refresh=5s&panelId=19"
className="w-full h-full"
className="w-full h-full skeleton"
/>
</StatCard>
<StatCard title="Block Height">
<iframe
src="https://grafana.layerview.io/d-solo/gEWc1Gq4k/ckb-dashboard?orgId=1&refresh=5s&panelId=10"
className="w-full h-full"
className="w-full h-full skeleton"
/>
</StatCard>
<StatCard title="RPC&API Status">
<iframe
className="w-full h-full"
className="w-full h-full skeleton"
src="https://grafana.layerview.io/d-solo/gEWc1Gq4k/ckb-dashboard?orgId=1&refresh=5s&panelId=20"
/>
</StatCard>
Expand All @@ -42,23 +32,22 @@ export default function Stat() {
<div>
<div className="mb-8 text-xl text-[600]">CKB Explorer · Testnet</div>
<div className="gap-4 grid grid-cols-1 md:grid-cols-3">
{' '}
<StatCard title="Tip Block Time">
<iframe
src="https://grafana.layerview.io/d-solo/gEWc1Gq4k/ckb-dashboard?orgId=1&refresh=5s&panelId=18"
className="w-full h-full"
className="w-full h-full skeleton"
/>
</StatCard>
<StatCard title="Block Height">
<iframe
src="https://grafana.layerview.io/d-solo/gEWc1Gq4k/ckb-dashboard?orgId=1&refresh=5s&panelId=16"
className="w-full h-full"
className="w-full h-full skeleton"
/>
</StatCard>
<StatCard title="RPC&API Status">
<iframe
src="https://grafana.layerview.io/d-solo/gEWc1Gq4k/ckb-dashboard?orgId=1&refresh=5s&panelId=17"
className="w-full h-full"
className="w-full h-full skeleton"
/>
</StatCard>
</div>
Expand All @@ -70,19 +59,18 @@ export default function Stat() {
<StatCard title="Mainnet Block Height">
<iframe
src="https://grafana.layerview.io/d-solo/gEWc1Gq4k/ckb-dashboard?orgId=1&refresh=5s&panelId=23"
className="w-full h-full"
className="w-full h-full skeleton"
/>
</StatCard>
<StatCard title="Testnet Block Height">
<iframe
src="https://grafana.layerview.io/d-solo/gEWc1Gq4k/ckb-dashboard?orgId=1&refresh=5s&panelId=24"
className="w-full h-full"
className="w-full h-full skeleton"
/>
</StatCard>
</div>
</div>
</div>
<Footer className="snap-always snap-center" serviceState={aggregateStateQuery.data} serviceLink="/status" />
</>
</Layout>
)
}
46 changes: 44 additions & 2 deletions packages/status/src/server/api/routers/uptime.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { z } from 'zod'
import { UPTIME_KEY } from '../../../utils'
import { createTRPCRouter, publicProcedure } from '../trpc'
import type { StatusPageResponse, StatusResourceResponse, StatusSection } from '../../../types';
import type { StatusPageResponse, StatusResourceResponse, StatusSection, StatusIncident } from '../../../types'

export const uptimeRouter = createTRPCRouter({
// TODO: need cache?
Expand Down Expand Up @@ -69,5 +70,46 @@ export const uptimeRouter = createTRPCRouter({
}

return resData.data
})
}),
countIncidentPages: publicProcedure.query(async () => {
const resp = await fetch(`https://uptime.betterstack.com/api/v2/incidents`, {
headers: {
Authorization: `Bearer ${UPTIME_KEY}`,
},
})

const resData = (await resp.json()) as {
data: StatusIncident[]
pagination: {
first: string,
last: string,
prev: string,
next: string,
}
}

if (!resData.pagination.last) return 1;

const lastPage = Number(resData.pagination.last.split('=')[1]);
return lastPage;
}),
listStatusIncidents: publicProcedure
.input(
z.object({
page: z.number(),
})
)
.query(async opts => {
const resp = await fetch(`https://uptime.betterstack.com/api/v2/incidents?page=${opts.input.page}`, {
headers: {
Authorization: `Bearer ${UPTIME_KEY}`,
},
})

const resData = (await resp.json()) as {
data: StatusIncident[]
}

return resData.data
}),
})
8 changes: 8 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2336,6 +2336,7 @@ __metadata:
"@uidotdev/usehooks": ^2.4.1
classnames: 2.3.2
daisyui: latest
dayjs: ^1.11.10
eslint: ^8.56.0
i18next: ^22.5.0
next: 13.5.6
Expand Down Expand Up @@ -5612,6 +5613,13 @@ __metadata:
languageName: node
linkType: hard

"dayjs@npm:^1.11.10":
version: 1.11.10
resolution: "dayjs@npm:1.11.10"
checksum: a6b5a3813b8884f5cd557e2e6b7fa569f4c5d0c97aca9558e38534af4f2d60daafd3ff8c2000fed3435cfcec9e805bcebd99f90130c6d1c5ef524084ced588c4
languageName: node
linkType: hard

"de-indent@npm:^1.0.2":
version: 1.0.2
resolution: "de-indent@npm:1.0.2"
Expand Down

3 comments on commit 39ca058

@vercel
Copy link

@vercel vercel bot commented on 39ca058 Jan 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vercel
Copy link

@vercel vercel bot commented on 39ca058 Jan 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

status-website – ./packages/status

status-website-git-master-magickbase.vercel.app
status-website-magickbase.vercel.app
status-website-delta.vercel.app

@vercel
Copy link

@vercel vercel bot commented on 39ca058 Jan 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

magickbase-website – ./packages/magickbase

magickbase.vercel.app
magickbase-website-magickbase.vercel.app
magickbase-website-git-master-magickbase.vercel.app
magickbase.com
www.magickbase.com

Please sign in to comment.