Skip to content

Commit

Permalink
refactor(chart): ♻️ optimize chart init and updates (#53)
Browse files Browse the repository at this point in the history
* refactor(chart): ♻️ optimize chart init and updates

* more coverage

* test(chart): ✅ test bar chart
  • Loading branch information
cesarnml authored May 3, 2023
1 parent e962aaa commit 252ea6b
Show file tree
Hide file tree
Showing 14 changed files with 356 additions and 263 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
"test": "playwright test",
"vitest": "vitest --ui",
"test:unit": "vitest",
"test:ui": "playwright test --ui",
"coverage": "vitest run --coverage",
Expand Down Expand Up @@ -41,6 +42,7 @@
"@typescript-eslint/parser": "5.59.1",
"@vercel/analytics": "1.0.0",
"@vitest/coverage-istanbul": "0.30.1",
"@vitest/ui": "0.30.1",
"autoprefixer": "10.4.14",
"daisyui": "2.51.6",
"dayjs": "1.11.7",
Expand Down
26 changes: 23 additions & 3 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

66 changes: 66 additions & 0 deletions src/lib/components/BarChart/ barChartHelpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { ChartColor } from '$lib/constants'
import type * as echarts from 'echarts'
import zipObject from 'lodash/zipObject'
import { secPerHour } from '$lib/constants'

export const createBarChartOption = (
xValues: string[],
series: echarts.SeriesOption[],
): echarts.EChartsOption => ({
tooltip: {
valueFormatter: (value) => `${value}h`,
},
grid: { left: 50, right: 20, top: 50, bottom: 50 },
legend: {
type: 'scroll',
textStyle: {
color: ChartColor.Text,
},
pageIconColor: ChartColor.Icon,
pageTextStyle: {
color: ChartColor.Text,
},
},
xAxis: {
type: 'category',
data: xValues,
},
yAxis: {
type: 'value',
axisLabel: {
formatter: (value) => `${value}h`,
showMinLabel: false,
},
},
series,
})

export const createBarChartSeries = <T>(
xValues: string[],
itemsByXValues: T[][],
itemNames: string[],
) => {
const yDataByItem = zipObject(
itemNames,
JSON.parse(JSON.stringify(Array(itemNames.length).fill(Array(xValues.length).fill(0)))),
)

itemsByXValues.forEach((items, index) => {
items.forEach((item) => {
// @ts-expect-error tough type
yDataByItem[item.name][index] = Number((item.total_seconds / secPerHour).toFixed(1))
})
})

return itemNames.map((key) => {
return {
data: yDataByItem[key],
type: 'bar',
stack: 'total',
emphasis: {
focus: 'series',
},
name: key,
}
}) as echarts.SeriesOption[]
}
46 changes: 46 additions & 0 deletions src/lib/components/BarChart/CategoryBarChart.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<script lang="ts">
import { DateFormat } from '$lib/constants'
import type {
SummariesResult,
WakaCategory,
} from '$src/routes/api/wakatime/current/summaries/+server'
import dayjs from 'dayjs'
import * as echarts from 'echarts'
import { afterUpdate, onMount } from 'svelte'
import ChartTitle from '../ChartTitle.svelte'
import ChartContainer from '../ChartContainer.svelte'
import { createBarChartOption, createBarChartSeries } from './ barChartHelpers'
export let summaries: SummariesResult
export let title = 'Category vs Time'
let chartRef: HTMLDivElement
let chart: echarts.ECharts
let option: echarts.EChartsOption
$: xValues = summaries.data.map((item) => dayjs(item.range.date).format(DateFormat.Short))
$: categoriesByDate = summaries.data.map((item) => item.categories)
$: categoryNames = [
...new Set(
summaries.data.map((item) => item.categories.map((category) => category.name)).flat(),
),
]
$: series = createBarChartSeries<WakaCategory>(xValues, categoriesByDate, categoryNames)
$: option = createBarChartOption(xValues, series)
onMount(() => {
const handleResize = () => chart.resize()
chart = echarts.init(chartRef, 'dark', { renderer: 'svg' })
window.addEventListener('resize', handleResize, { passive: true })
return () => window.removeEventListener('resize', handleResize)
})
afterUpdate(() => {
chart.setOption(option)
})
</script>

<ChartContainer>
<ChartTitle>{title}</ChartTitle>
<div class="h-96 w-full" bind:this={chartRef} />
</ChartContainer>
167 changes: 0 additions & 167 deletions src/lib/components/CodingActivityChartByCategory.svelte

This file was deleted.

2 changes: 1 addition & 1 deletion src/lib/components/CodingActivityLineChart.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
export let summaries: SummariesResult
export let title = 'Coding Activity'
export let chartRef: HTMLDivElement
let chartRef: HTMLDivElement
let chart: echarts.ECharts
$: dates = summaries.data.map((summary) => dayjs(summary.range.date).format(DateFormat.Short))
Expand Down
Loading

1 comment on commit 252ea6b

@vercel
Copy link

@vercel vercel bot commented on 252ea6b May 3, 2023

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:

wakastats – ./

wakastats-cesarmejia.vercel.app
wakastats.vercel.app
wakastats-git-main-cesarmejia.vercel.app

Please sign in to comment.