Skip to content

Commit

Permalink
feat: add "1 Hour" and "24 Hours" time periods
Browse files Browse the repository at this point in the history
  • Loading branch information
guanzo committed Jul 20, 2022
1 parent 7783050 commit c93e94f
Show file tree
Hide file tree
Showing 9 changed files with 80 additions and 67 deletions.
3 changes: 2 additions & 1 deletion src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,12 @@ export async function wfetch (resource: RequestInfo | URL, opts: RequestInit = {
return response
}

export async function fetchMetrics (filAddress: string, startDate: Date, endDate: Date) {
export async function fetchMetrics (filAddress: string, startDate: Date, endDate: Date, step: string) {
const url = new URL(METRICS_ORIGIN)
url.searchParams.set('filAddress', filAddress)
url.searchParams.set('startDate', `${startDate.getTime()}`)
url.searchParams.set('endDate', `${endDate.getTime()}`)
url.searchParams.set('step', step)

const res: MetricsResponse = await wfetch(url).then(r => r.json())

Expand Down
5 changes: 3 additions & 2 deletions src/api.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,11 @@ export interface RequestInit extends globalThis.RequestInit {
}

export enum TimePeriod {
// DAY = '24 Hours',
HOUR = '1 Hour',
DAY = '24 Hours',
WEEK = '7 Days',
TWO_WEEK = '14 Days',
MONTH = '30 Days',
// MONTH = '30 Days',
// TODO: Need to optimize db for 6 month query.
// SIX_MONTH = '6 Months'
}
11 changes: 0 additions & 11 deletions src/chartjs-dayjs-adapter.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,22 @@
// Copied from https://gitlab.com/mmillerbkg/chartjs-adapter-dayjs/-/blob/master/src/index.ts

import { _adapters } from 'chart.js'

import dayjs, { QUnitType } from 'dayjs'

import type { TimeUnit } from 'chart.js'

// Needed to handle the custom parsing
import CustomParseFormat from 'dayjs/plugin/customParseFormat'

// Needed to handle quarter format
import AdvancedFormat from 'dayjs/plugin/advancedFormat'

// Needed to handle adding/subtracting quarter
import QuarterOfYear from 'dayjs/plugin/quarterOfYear'

// Needed to handle localization format
import LocalizedFormat from 'dayjs/plugin/localizedFormat'

import isoWeek from 'dayjs/plugin/isoWeek'

dayjs.extend(AdvancedFormat)

dayjs.extend(QuarterOfYear)

dayjs.extend(LocalizedFormat)

dayjs.extend(CustomParseFormat)

dayjs.extend(isoWeek)

const FORMATS = {
Expand Down
15 changes: 4 additions & 11 deletions src/dashboard/BandwidthChart.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import bytes from 'bytes'
import dayjs from 'dayjs'
import { Line } from 'react-chartjs-2'

import { Metric } from '@/api.types'
Expand All @@ -11,7 +10,7 @@ interface BandwidthChartProps extends ChartProps {
}

export default function BandwidthChart (props: BandwidthChartProps) {
const { dateRange, metrics, isLoading } = props
const { xScale, metrics, isLoading, spanGaps } = props

const options: ChartOptions<'line'> = {
plugins: {
Expand All @@ -26,14 +25,7 @@ export default function BandwidthChart (props: BandwidthChartProps) {
}
},
scales: {
x: {
type: 'time',
time: {
unit: 'day'
},
min: dateRange.startDate.getTime(),
max: dayjs.utc(dateRange.endDate).subtract(1, 'day').valueOf()
},
x: xScale,
y: {
ticks: {
callback: val => bytes(Number(val), { unitSeparator: ' ' })
Expand All @@ -46,7 +38,8 @@ export default function BandwidthChart (props: BandwidthChartProps) {
labels: metrics.map(m => m.startTime),
datasets: [
{
data: metrics.map(m => m.numBytes)
data: metrics.map(m => m.numBytes),
spanGaps
}
]
}
Expand Down
4 changes: 3 additions & 1 deletion src/dashboard/ChartContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ export interface ChartProps {
dateRange: {
startDate: Date
endDate: Date
}
},
xScale: object,
spanGaps: number
}

export interface ChartContainerProps {
Expand Down
74 changes: 56 additions & 18 deletions src/dashboard/Dashboard.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import bytes from 'bytes'
import dayjs from 'dayjs'
import type { DurationUnitType } from 'dayjs/plugin/duration'
import { Dispatch, ReactNode, SetStateAction, useEffect, useState } from 'react'
import { useParams } from 'react-router-dom'

Expand All @@ -7,25 +10,62 @@ import { pastDateRange } from '@/date-utils'
import RequestsChart from './RequestsChart'
import BandwidthChart from './BandwidthChart'
import EarningsChart from './EarningsChart'
import bytes from 'bytes'

interface OverviewProps {
metricsRes: MetricsResponse
address: string
children?: ReactNode
}

function periodToDateRange (period: TimePeriod) {
function periodToDateOptions (period: TimePeriod) {
let dateRange
let step: DurationUnitType

switch (period) {
case TimePeriod.HOUR:
dateRange = pastDateRange('hour')
step = 'minute'
break
case TimePeriod.WEEK:
return pastDateRange('week')
dateRange = pastDateRange('week')
step = 'day'
break
case TimePeriod.TWO_WEEK:
return pastDateRange('week', 2)
case TimePeriod.MONTH:
return pastDateRange('month')
// case TimePeriod.SIX_MONTH:
// return pastDateRange('month', 6)
dateRange = pastDateRange('week', 2)
step = 'day'
break
case TimePeriod.DAY:
default:
dateRange = pastDateRange('day')
step = 'hour'
break
// case TimePeriod.MONTH:
// dateRange = pastDateRange('month')
// break
}

return { dateRange, step }
}

function createChartProps (
dateRange: { startDate: Date, endDate: Date },
unit: DurationUnitType,
isLoading: boolean
) {
const xScale = {
type: 'time',
time: {
unit
},
min: dateRange.startDate.getTime(),
max: dateRange.endDate.getTime()
}

// https://github.com/chartjs/Chart.js/pull/6993
// Break the line chart when missing a data point.
const spanGaps = dayjs.duration(1, unit).asMilliseconds()

return { dateRange, xScale, spanGaps, isLoading }
}

function SelectTimePeriod (
Expand Down Expand Up @@ -87,12 +127,12 @@ function Dashboard () {
] = useState<MetricsResponse>({ earnings: [], nodes: [], metrics: [] })

const [period, setPeriod] = useState<TimePeriod>(TimePeriod.WEEK)
const dateRange = periodToDateRange(period)
const { dateRange, step } = periodToDateOptions(period)
const { startDate, endDate } = dateRange

// Don't update chart axes until data is fetched.
// It looks weird if axes update immediately.
const [chartDateRange, setChartDateRange] = useState(dateRange)
// Don't update charts until data is fetched.
// It looks weird if charts update immediately.
const [chartOpts, setChartOpts] = useState({ dateRange, step })

const fetchData = async () => {
if (!address) { return }
Expand All @@ -102,9 +142,9 @@ function Dashboard () {
setError(null)

const metricsRes = await api.fetchMetrics(
address, startDate, endDate)
address, startDate, endDate, step)
setMetricsRes(metricsRes)
setChartDateRange(dateRange)
setChartOpts({ dateRange, step })
} catch (err) {
if (err instanceof Error) {
setError(err?.message ?? 'Error retrieving metrics.')
Expand All @@ -114,12 +154,10 @@ function Dashboard () {
}
}

useEffect(() => {
fetchData()
}, [address, startDate.getTime(), endDate.getTime()])
useEffect(() => { fetchData() }, [address, period])

const { earnings, metrics } = metricsRes
const chartProps = { dateRange: chartDateRange, isLoading }
const chartProps = createChartProps(chartOpts.dateRange, chartOpts.step, isLoading)

return (
<div className="flex-1 flex flex-col gap-4 mt-8">
Expand Down
14 changes: 3 additions & 11 deletions src/dashboard/EarningsChart.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import dayjs from 'dayjs'
import { Line } from 'react-chartjs-2'

import { Earning } from '@/api.types'
Expand All @@ -10,7 +9,7 @@ interface EarningsChartProps extends ChartProps {
}

export default function EarningsChart (props: EarningsChartProps) {
const { earnings, dateRange, isLoading } = props
const { earnings, xScale, isLoading, spanGaps } = props
const options: ChartOptions<'line'> = {
plugins: {
title: {
Expand All @@ -24,14 +23,7 @@ export default function EarningsChart (props: EarningsChartProps) {
}
},
scales: {
x: {
type: 'time',
time: {
unit: 'day'
},
min: dateRange.startDate.getTime(),
max: dayjs.utc(dateRange.endDate).subtract(1, 'day').valueOf()
},
x: xScale,
y: {
ticks: {
callback: val => `${val} FIL`
Expand All @@ -45,7 +37,7 @@ export default function EarningsChart (props: EarningsChartProps) {
datasets: [
{
data: earnings.map(e => e.filAmount),
spanGaps: 1000 * 60 * 60 * 24 // 1 day,
spanGaps
}
]
}
Expand Down
15 changes: 4 additions & 11 deletions src/dashboard/RequestsChart.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import dayjs from 'dayjs'
import { Line } from 'react-chartjs-2'

import { Metric } from '@/api.types'
Expand All @@ -10,7 +9,7 @@ interface RequestsChartProps extends ChartProps {
}

export default function RequestsChart (props: RequestsChartProps) {
const { metrics, dateRange, isLoading } = props
const { metrics, xScale, isLoading, spanGaps } = props
const options: ChartOptions<'line'> = {
plugins: {
title: {
Expand All @@ -19,22 +18,16 @@ export default function RequestsChart (props: RequestsChartProps) {
}
},
scales: {
x: {
type: 'time',
time: {
unit: 'day'
},
min: dateRange.startDate.getTime(),
max: dayjs.utc(dateRange.endDate).subtract(1, 'day').valueOf()
}
x: xScale
}
}

const data = {
labels: metrics.map(m => m.startTime),
datasets: [
{
data: metrics.map(m => m.numRequests)
data: metrics.map(m => m.numRequests),
spanGaps
}
]
}
Expand Down
6 changes: 5 additions & 1 deletion src/date-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,22 @@
// you must install dayjs.

import dayjs, { ManipulateType } from 'dayjs'
import duration from 'dayjs/plugin/duration'
import utc from 'dayjs/plugin/utc'

if (!dayjs.prototype.utc) {
dayjs.extend(utc)
}
if (!dayjs.prototype.duration) {
dayjs.extend(duration)
}

export const startOfToday = () => dayjs.utc().startOf('day').toDate()

export const endOfDay = (date: Date) => dayjs.utc(date).endOf('day').toDate()

export function pastDateRange (unit: ManipulateType = 'week', count = 1) {
const endDateObj = dayjs.utc().add(1, 'day').startOf('day')
const endDateObj = dayjs.utc().startOf('minute')
const endDate = endDateObj.toDate()
const startDate = endDateObj.subtract(count, unit).toDate()

Expand Down

0 comments on commit c93e94f

Please sign in to comment.