-
+
+
) : null;
}
diff --git a/apps/dashboard/src/components/report/chart/SerieIcon.urls.ts b/apps/dashboard/src/components/report/chart/SerieIcon.urls.ts
index d57450bc..4f0cdb04 100644
--- a/apps/dashboard/src/components/report/chart/SerieIcon.urls.ts
+++ b/apps/dashboard/src/components/report/chart/SerieIcon.urls.ts
@@ -8,9 +8,18 @@ const data = {
'vstat.info': 'https://vstat.info',
'yahoo!': 'https://yahoo.com',
android: 'https://image.similarpng.com/very-thumbnail/2020/08/Android-icon-on-transparent--background-PNG.png',
+ 'android browser': 'https://image.similarpng.com/very-thumbnail/2020/08/Android-icon-on-transparent--background-PNG.png',
+ 'silk': 'https://m.media-amazon.com/images/I/51VCjQCvF0L.png',
+ 'kakaotalk': 'https://www.kakaocorp.com/',
bing: 'https://bing.com',
+ 'electron': 'https://www.electronjs.org',
+ 'whale': 'https://whale.naver.com',
+ 'wechat': 'https://wechat.com',
chrome: 'https://upload.wikimedia.org/wikipedia/commons/e/e1/Google_Chrome_icon_%28February_2022%29.svg',
+ 'chrome webview': 'https://upload.wikimedia.org/wikipedia/commons/e/e1/Google_Chrome_icon_%28February_2022%29.svg',
+ 'chrome headless': 'https://upload.wikimedia.org/wikipedia/commons/e/e1/Google_Chrome_icon_%28February_2022%29.svg',
chromecast: 'https://upload.wikimedia.org/wikipedia/commons/archive/2/26/20161130022732%21Chromecast_cast_button_icon.svg',
+ webkit: 'https://webkit.org',
duckduckgo: 'https://duckduckgo.com',
ecosia: 'https://ecosia.com',
edge: 'https://upload.wikimedia.org/wikipedia/commons/7/7e/Microsoft_Edge_logo_%282019%29.png',
@@ -19,6 +28,7 @@ const data = {
github: 'https://github.com',
gmail: 'https://mail.google.com',
google: 'https://google.com',
+ gsa: 'https://google.com', // Google Search App
instagram: 'https://instagram.com',
ios: 'https://cdn0.iconfinder.com/data/icons/flat-round-system/512/apple-1024.png',
linkedin: 'https://linkedin.com',
diff --git a/apps/dashboard/src/components/report/chart/SerieName.tsx b/apps/dashboard/src/components/report/chart/SerieName.tsx
new file mode 100644
index 00000000..c53a0547
--- /dev/null
+++ b/apps/dashboard/src/components/report/chart/SerieName.tsx
@@ -0,0 +1,40 @@
+import { cn } from '@/utils/cn';
+import { ChevronRightIcon } from 'lucide-react';
+
+import { NOT_SET_VALUE } from '@openpanel/constants';
+
+import { useChartContext } from './ChartProvider';
+
+interface SerieNameProps {
+ name: string | string[];
+ className?: string;
+}
+
+export function SerieName({ name, className }: SerieNameProps) {
+ const chart = useChartContext();
+ if (Array.isArray(name)) {
+ if (chart.renderSerieName) {
+ return chart.renderSerieName(name);
+ }
+ return (
+
+ {name.map((n, index) => {
+ return (
+ <>
+ {n || NOT_SET_VALUE}
+ {name.length - 1 > index && (
+
+ )}
+ >
+ );
+ })}
+
+ );
+ }
+
+ if (chart.renderSerieName) {
+ return chart.renderSerieName([name]);
+ }
+
+ return <>{name}>;
+}
diff --git a/apps/dashboard/src/components/report/chart/index.tsx b/apps/dashboard/src/components/report/chart/index.tsx
index 595d0276..7032cae7 100644
--- a/apps/dashboard/src/components/report/chart/index.tsx
+++ b/apps/dashboard/src/components/report/chart/index.tsx
@@ -1,22 +1,47 @@
'use client';
+import { Suspense, useEffect, useState } from 'react';
+
import type { IChartProps } from '@openpanel/validation';
import { Funnel } from '../funnel';
import { Chart } from './Chart';
-import { withChartProivder } from './ChartProvider';
+import { ChartLoading } from './ChartLoading';
+import type { IChartContextType } from './ChartProvider';
+import { ChartProvider } from './ChartProvider';
+import { MetricCardLoading } from './MetricCard';
-export const ChartSwitch = withChartProivder(function ChartSwitch(
- props: IChartProps
-) {
- if (props.chartType === 'funnel') {
- return
;
+export type IChartRoot = IChartContextType;
+
+export function ChartRoot(props: IChartContextType) {
+ const [mounted, setMounted] = useState(false);
+
+ useEffect(() => {
+ setMounted(true);
+ }, []);
+
+ if (!mounted) {
+ return props.chartType === 'metric' ? (
+
+ ) : (
+
+ );
}
- return
;
-});
+ return (
+
:
+ }
+ >
+
+ {props.chartType === 'funnel' ? : }
+
+
+ );
+}
-interface ChartSwitchShortcutProps {
+interface ChartRootShortcutProps {
projectId: IChartProps['projectId'];
range?: IChartProps['range'];
previous?: IChartProps['previous'];
@@ -25,16 +50,16 @@ interface ChartSwitchShortcutProps {
events: IChartProps['events'];
}
-export const ChartSwitchShortcut = ({
+export const ChartRootShortcut = ({
projectId,
range = '7d',
previous = false,
chartType = 'linear',
interval = 'day',
events,
-}: ChartSwitchShortcutProps) => {
+}: ChartRootShortcutProps) => {
return (
-
);
-});
+}
diff --git a/apps/dashboard/src/components/ui/table.tsx b/apps/dashboard/src/components/ui/table.tsx
index cfa93b2d..77cb3a9a 100644
--- a/apps/dashboard/src/components/ui/table.tsx
+++ b/apps/dashboard/src/components/ui/table.tsx
@@ -75,7 +75,7 @@ const TableHead = React.forwardRef<