diff --git a/apps/web/package-lock.json b/apps/web/package-lock.json index 6198064..26c3714 100644 --- a/apps/web/package-lock.json +++ b/apps/web/package-lock.json @@ -33,6 +33,7 @@ "clsx": "^2.1.1", "cmdk": "^1.0.4", "date-fns": "^4.1.0", + "echarts-for-react": "^3.0.2", "init": "^0.1.2", "lucide-react": "^0.469.0", "next": "^15.1.3", @@ -3156,6 +3157,20 @@ "zrender": "5.6.1" } }, + "node_modules/echarts-for-react": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/echarts-for-react/-/echarts-for-react-3.0.2.tgz", + "integrity": "sha512-DRwIiTzx8JfwPOVgGttDytBqdp5VzCSyMRIxubgU/g2n9y3VLUmF2FK7Icmg/sNVkv4+rktmrLN9w22U2yy3fA==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "size-sensor": "^1.0.1" + }, + "peerDependencies": { + "echarts": "^3.0.0 || ^4.0.0 || ^5.0.0", + "react": "^15.0.0 || >=16.0.0" + } + }, "node_modules/echarts/node_modules/tslib": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz", @@ -3853,7 +3868,6 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true, "license": "MIT" }, "node_modules/fast-equals": { @@ -7270,6 +7284,12 @@ "is-arrayish": "^0.3.1" } }, + "node_modules/size-sensor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/size-sensor/-/size-sensor-1.0.2.tgz", + "integrity": "sha512-2NCmWxY7A9pYKGXNBfteo4hy14gWu47rg5692peVMst6lQLPKrVjhY+UTEsPI5ceFRJSl3gVgMYaUi/hKuaiKw==", + "license": "ISC" + }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", diff --git a/apps/web/package.json b/apps/web/package.json index 9e6ce95..2678e2f 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -35,6 +35,7 @@ "clsx": "^2.1.1", "cmdk": "^1.0.4", "date-fns": "^4.1.0", + "echarts-for-react": "^3.0.2", "init": "^0.1.2", "lucide-react": "^0.469.0", "next": "^15.1.3", diff --git a/apps/web/pnpm-lock.yaml b/apps/web/pnpm-lock.yaml index d7dbecf..110918f 100644 --- a/apps/web/pnpm-lock.yaml +++ b/apps/web/pnpm-lock.yaml @@ -83,6 +83,9 @@ importers: date-fns: specifier: ^4.1.0 version: 4.1.0 + echarts-for-react: + specifier: ^3.0.2 + version: 3.0.2(echarts@5.6.0)(react@19.0.0) init: specifier: ^0.1.2 version: 0.1.2 @@ -1384,6 +1387,12 @@ packages: eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + echarts-for-react@3.0.2: + resolution: {integrity: sha512-DRwIiTzx8JfwPOVgGttDytBqdp5VzCSyMRIxubgU/g2n9y3VLUmF2FK7Icmg/sNVkv4+rktmrLN9w22U2yy3fA==} + peerDependencies: + echarts: ^3.0.0 || ^4.0.0 || ^5.0.0 + react: ^15.0.0 || >=16.0.0 + echarts@5.6.0: resolution: {integrity: sha512-oTbVTsXfKuEhxftHqL5xprgLoc0k7uScAwtryCgWF6hPYFLRwOUHiFmHGCBKP5NPFNkDVopOieyUqYGH8Fa3kA==} @@ -2494,6 +2503,9 @@ packages: simple-swizzle@0.2.2: resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} + size-sensor@1.0.2: + resolution: {integrity: sha512-2NCmWxY7A9pYKGXNBfteo4hy14gWu47rg5692peVMst6lQLPKrVjhY+UTEsPI5ceFRJSl3gVgMYaUi/hKuaiKw==} + source-map-js@1.2.1: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} @@ -3990,6 +4002,13 @@ snapshots: eastasianwidth@0.2.0: {} + echarts-for-react@3.0.2(echarts@5.6.0)(react@19.0.0): + dependencies: + echarts: 5.6.0 + fast-deep-equal: 3.1.3 + react: 19.0.0 + size-sensor: 1.0.2 + echarts@5.6.0: dependencies: tslib: 2.3.0 @@ -5457,6 +5476,8 @@ snapshots: is-arrayish: 0.3.2 optional: true + size-sensor@1.0.2: {} + source-map-js@1.2.1: {} space-separated-tokens@2.0.2: {} diff --git a/apps/web/src/components/tools/auth0/cumulative-signups-chart.tsx b/apps/web/src/components/tools/auth0/cumulative-signups-chart.tsx index 715c0f3..6785564 100644 --- a/apps/web/src/components/tools/auth0/cumulative-signups-chart.tsx +++ b/apps/web/src/components/tools/auth0/cumulative-signups-chart.tsx @@ -1,6 +1,10 @@ 'use client' -import { BarChart } from '@tinybirdco/charts' + +import { useQuery } from '@tinybirdco/charts' +import ReactECharts from 'echarts-for-react' +import * as echarts from 'echarts' +import { format } from 'date-fns' export function Auth0CumulativeSignups(params: { client_id?: string @@ -10,14 +14,137 @@ export function Auth0CumulativeSignups(params: { date_from?: string date_to?: string }) { - return + const { data, meta, error, loading } = useQuery({ + endpoint: `${process.env.NEXT_PUBLIC_TINYBIRD_API_HOST}/v0/pipes/auth0_cumulative_users.json`, + token: params.token ?? '', + params: { + client_id: params.client_id ?? '', + connection_id: params.connection_id ?? '', + tenant_name: params.tenant_name ?? '', + date_from: params.date_from ?? '', + date_to: params.date_to ?? '' + } + }) + + if (loading) return
Loading...
+ if (error) return
Error: {error}
+ + const option = { + color: ['rgb(128, 255, 165)', 'rgb(255, 0, 135)'], + tooltip: { + trigger: 'axis', + axisPointer: { + type: 'cross', + label: { + backgroundColor: '#6a7985' + } + } + }, + legend: { + data: ['Cumulative Users', 'New Users'] + }, + toolbox: { + feature: { + saveAsImage: {}, + dataView: {}, + magicType: { + type: ['line', 'bar', 'stack'] + }, + brush: { + type: ['rect', 'polygon', 'lineX', 'lineY'] + } + } + }, + grid: { + left: '3%', + right: '4%', + bottom: '3%', + containLabel: true + }, + xAxis: [ + { + type: 'category', + boundaryGap: false, + data: data?.map((item: any) => item.day) ?? [] + } + ], + yAxis: [ + { + type: 'value' + } + ], + series: [ + { + name: 'Cumulative Users', + type: 'line', + // stack: 'Total', + smooth: true, + lineStyle: { + width: 2, + color: 'rgb(138 98 235)' + }, + showSymbol: false, + areaStyle: { + opacity: 0.8, + color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ + { + offset: 0, + color: 'rgb(138, 98, 235, 0.7)' + }, + { + offset: 0.5, + color: 'rgba(138, 98, 235, 0.3)' + }, + { + offset: 1, + color: 'rgba(138, 98, 235, 0)' + } + ]), + // shadowOffsetX: 0, + // shadowOffsetY: 10, + // shadowBlur: 20 + }, + emphasis: { + focus: 'series' + }, + data: data?.map((item: any) => item.cumulative_users) ?? [] + }, + { + name: 'New Users', + type: 'line', + // stack: 'Total', + smooth: true, + lineStyle: { + width: 0 + }, + showSymbol: false, + areaStyle: { + opacity: 0.8, + color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ + { + offset: 0, + color: 'rgb(255, 0, 135)' + }, + { + offset: 1, + color: 'rgb(135, 0, 157)' + } + ]), + // shadowOffsetX: 0, + // shadowOffsetY: 10, + // shadowBlur: 20 + }, + emphasis: { + focus: 'series', + lineStyle: { + width: 20 + } + }, + data: data?.map((item: any) => item.new_users) ?? [] + } + ] + }; + + return + } \ No newline at end of file diff --git a/apps/web/src/components/tools/auth0/dau-chart.tsx b/apps/web/src/components/tools/auth0/dau-chart.tsx index a4f0ee0..2e597fc 100644 --- a/apps/web/src/components/tools/auth0/dau-chart.tsx +++ b/apps/web/src/components/tools/auth0/dau-chart.tsx @@ -1,6 +1,8 @@ "use client" import { AreaChart } from '@tinybirdco/charts' +import { format } from 'date-fns' +import * as echarts from 'echarts' export function Auth0Dau(params: { client_id?: string @@ -18,6 +20,124 @@ export function Auth0Dau(params: { categories={['active']} height="200px" params={params} - colorPalette={['#000000']} + stacked={true} + colorPalette={['#a2a2a2']} + options={{ + toolbox: { + feature: { + saveAsImage: {}, + magicType: { + type: ['line', 'bar'] + } + } + }, + tooltip: { + trigger: 'axis', + axisPointer: { + type: 'cross', + label: { + backgroundColor: '#6a7985', + } + }, + formatter: (parameters: any) => { + const data = parameters[0]; + if (params.time_range === 'daily') { + return `${format(data.value[0], 'MMM dd, yyyy')}\n${data.value[1].toLocaleString()} active users`; + } else if (params.time_range === 'hourly') { + return `${format(data.value[0], 'MMM dd, yyyy HH:mm')}\n${data.value[1].toLocaleString()} active users`; + } + return `${format(data.value[0], 'MMM yyyy')}\n${data.value[1].toLocaleString()} active users`; + } + }, + grid: { + left: '3%', + right: '4%', + bottom: '3%', + containLabel: true + }, + xAxis: { + type: 'time', + axisLine: { + lineStyle: { color: '#e2e8f0' } + }, + axisTick: { + show: true + }, + axisLabel: { + color: '#64748b', + fontSize: 12, + formatter: (function() { + let prevMonth = ''; + let prevMonthMonth = ''; + let index = 0; + return (value: number) => { + const date = new Date(value); + if (params.time_range === 'daily') { + const month = format(date, 'MMM'); + const day = format(date, 'dd'); + if (month !== prevMonth) { + prevMonth = month; + return `${month} ${day}`; + } + return day; + } else if (params.time_range === 'hourly') { + return format(date, 'MMM dd, HH:mm'); + } + const month = format(date, 'MMM'); + if (month !== prevMonthMonth && index !== 0) { + prevMonthMonth = month; + return month; + } + index++; + return ''; + }; + })() + }, + splitLine: { + show: true, + lineStyle: { + color: '#e2e8f0', + type: 'dotted' + } + } + }, + yAxis: { + type: 'value', + axisLine: { show: false }, + axisTick: { show: false }, + axisLabel: { + color: '#64748b', + fontSize: 12 + }, + splitLine: { + lineStyle: { + color: '#e2e8f0', + type: 'dotted' + } + } + }, + // series: [{ + // name: 'Active Users', + // type: 'line', + // smooth: true, + // lineStyle: { + // width: 0 + // }, + // showSymbol: false, + // areaStyle: { + // opacity: 0.8, + // color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ + // { + // offset: 0, + // color: 'rgb(55, 162, 255)' + // }, + // { + // offset: 1, + // color: 'rgb(116, 21, 219)' + // } + // ]) + // } + // }] + }} /> } \ No newline at end of file