refactor: improve periodic usage charts

This commit is contained in:
harsh mahajan
2026-05-05 12:24:15 +05:30
parent 9193921bd5
commit dada7e16f6
3 changed files with 110 additions and 31 deletions
+40 -19
View File
@@ -1,19 +1,47 @@
<script lang="ts">
import { BarChart, Legend, type LegendData } from '$lib/charts';
import { accumulateFromEndingTotal } from '$lib/layout/usage.svelte';
import { Card, SecondaryTabs, SecondaryTabsItem } from '$lib/components';
import { page } from '$app/state';
import { BarChart, Legend, type LegendData } from '$lib/charts';
import { Card, SecondaryTabs, SecondaryTabsItem } from '$lib/components';
import { clampMin, formatNumberWithCommas } from '$lib/helpers/numbers';
import { accumulateFromEndingTotal } from '$lib/layout/usage.svelte';
import { type Models } from '@appwrite.io/console';
import { formatNumberWithCommas, clampMin } from '$lib/helpers/numbers';
import { Layout, Typography } from '@appwrite.io/pink-svelte';
import type { EChartsOption } from 'echarts';
export let title: string;
export let total: number[];
export let path: string = null;
export let count: Models.Metric[][];
export let legendData: LegendData[];
export let showHeader: boolean = true;
export let legendNumberFormat: 'comma' | 'abbreviate' = 'comma';
type Props = {
title: string;
total: number[];
path?: string | null;
count: Models.Metric[][];
legendData: LegendData[];
showHeader?: boolean;
legendNumberFormat?: 'comma' | 'abbreviate';
isCumulative?: boolean;
options?: EChartsOption | null;
};
let {
title,
total,
path = null,
count,
legendData,
showHeader = true,
legendNumberFormat = 'comma',
isCumulative = true,
options = null
}: Props = $props();
const formatted = $derived(page.params.period === '24h' ? 'hours' : 'days');
const totalCount = $derived(clampMin(total.reduce((a, b) => a + b, 0)));
const series = $derived(
count.map((metrics, index) => ({
name: legendData[index].name,
data: isCumulative
? accumulateFromEndingTotal(metrics, total[index])
: metrics.map((metric) => [metric.date, metric.value])
}))
);
</script>
<div>
@@ -41,19 +69,12 @@
<Card>
{#if count}
{@const totalCount = clampMin(total.reduce((a, b) => a + b, 0))}
<Layout.Stack gap="xs">
<Typography.Title>{formatNumberWithCommas(totalCount)}</Typography.Title>
<Typography.Text>Total {title.toLocaleLowerCase()}</Typography.Text>
</Layout.Stack>
<div class="multiple-chart-container u-flex-vertical u-gap-16">
<BarChart
formatted={page.params.period === '24h' ? 'hours' : 'days'}
series={count.map((c, index) => ({
name: legendData[index].name,
data: accumulateFromEndingTotal(c, total[index])
}))} />
<BarChart {formatted} {options} {series} />
{#if legendData}
<Legend
@@ -1,21 +1,38 @@
<script lang="ts">
import { base } from '$app/paths';
import { page } from '$app/state';
import { clampMin } from '$lib/helpers/numbers';
import { formatNum } from '$lib/helpers/string';
import { Container, UsageMultiple } from '$lib/layout';
import type { PageProps } from './$types';
export let data;
let { data }: PageProps = $props();
$: reads = data.databaseReads;
$: readsTotal = data.databaseReadsTotal;
const reads = $derived(data.databaseReads ?? []);
const readsTotal = $derived(clampMin(reads.reduce((sum, item) => sum + item.value, 0)));
$: writes = data.databaseWrites;
$: writesTotal = data.databaseWritesTotal;
const writes = $derived(data.databaseWrites ?? []);
const writesTotal = $derived(clampMin(writes.reduce((sum, item) => sum + item.value, 0)));
const usagePath = $derived(
`${base}/project-${page.params.region}-${page.params.project}/databases/database-${page.params.database}/usage`
);
</script>
<Container databasesMainScreen>
<UsageMultiple
title="Reads and writes"
showHeader={false}
path={usagePath}
total={[readsTotal, writesTotal]}
count={[reads, writes]}
isCumulative={false}
options={{
yAxis: {
axisLabel: {
formatter: formatNum
}
}
}}
legendNumberFormat="abbreviate"
legendData={[
{ name: 'Reads', value: readsTotal },
@@ -1,24 +1,65 @@
<script lang="ts">
import { goto } from '$app/navigation';
import { base } from '$app/paths';
import { page } from '$app/state';
import { Container, UsageMultiple } from '$lib/layout';
import { InputSelect } from '$lib/elements/forms';
import { clampMin } from '$lib/helpers/numbers';
import { formatNum } from '$lib/helpers/string';
import { Layout } from '@appwrite.io/pink-svelte';
import type { PageData } from './$types';
import type { PageProps } from './$types';
export let data: PageData;
let { data }: PageProps = $props();
$: reads = data.databasesReads;
$: readsTotal = data.databasesReadsTotal;
const reads = $derived(data.databasesReads ?? []);
const readsTotal = $derived(clampMin(reads.reduce((sum, item) => sum + item.value, 0)));
$: writes = data.databasesWrites;
$: writesTotal = data.databasesWritesTotal;
const writes = $derived(data.databasesWrites ?? []);
const writesTotal = $derived(clampMin(writes.reduce((sum, item) => sum + item.value, 0)));
const usagePath = $derived(
`${base}/project-${page.params.region}-${page.params.project}/databases/usage`
);
</script>
<Container>
<Layout.Stack gap="l">
<div
style:max-width="250px"
style:--input-background-color="var(--bgcolor-neutral-primary)">
<InputSelect
on:change={(e) => goto(`${usagePath}/${e.detail}`)}
id="period"
options={[
{
label: '24 hours',
value: '24h'
},
{
label: '30 days',
value: '30d'
},
{
label: '90 days',
value: '90d'
}
]}
value={page.params.period ?? '30d'} />
</div>
<UsageMultiple
title="Reads and writes"
showHeader={false}
total={[readsTotal, writesTotal]}
count={[reads, writes]}
isCumulative={false}
options={{
yAxis: {
axisLabel: {
formatter: formatNum
}
}
}}
legendNumberFormat="abbreviate"
legendData={[
{ name: 'Reads', value: readsTotal },