diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsBy/ByBrowser.tsx b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsBy/ByBrowser.tsx
index 2416c7768..3f83e8e0a 100644
--- a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsBy/ByBrowser.tsx
+++ b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsBy/ByBrowser.tsx
@@ -5,7 +5,7 @@ import { Icon } from 'UI';
import ExCard from '../ExCard';
import ByComponent from './Component';
-function ByBrowser({ onCard }: { onCard: (card: string) => void }) {
+function ByBrowser(props: any) {
const rows = [
{
label: 'Chrome',
@@ -42,9 +42,7 @@ function ByBrowser({ onCard }: { onCard: (card: string) => void }) {
const lineWidth = 200;
return (
diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsBy/ByCountry.tsx b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsBy/ByCountry.tsx
index 920258f6e..61381824b 100644
--- a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsBy/ByCountry.tsx
+++ b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsBy/ByCountry.tsx
@@ -4,7 +4,7 @@ import { Icon } from 'UI';
import ByComponent from './Component';
-function ByCountry({ onCard }: { onCard: (card: string) => void }) {
+function ByCountry(props: any) {
const rows = [
{
label: 'United States',
@@ -41,10 +41,8 @@ function ByCountry({ onCard }: { onCard: (card: string) => void }) {
return (
);
}
diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsBy/BySystem.tsx b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsBy/BySystem.tsx
index 5700d568f..21a138315 100644
--- a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsBy/BySystem.tsx
+++ b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsBy/BySystem.tsx
@@ -4,7 +4,7 @@ import { Icon } from 'UI';
import ByComponent from './Component';
-function BySystem({ onCard }: { onCard: (card: string) => void }) {
+function BySystem(props: any) {
const rows = [
{
label: 'Windows',
@@ -41,9 +41,7 @@ function BySystem({ onCard }: { onCard: (card: string) => void }) {
const lineWidth = 200;
return (
diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsBy/ByUrl.tsx b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsBy/ByUrl.tsx
index f648beef9..1b2de44e2 100644
--- a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsBy/ByUrl.tsx
+++ b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsBy/ByUrl.tsx
@@ -5,7 +5,7 @@ import React from 'react';
import { Circle } from '../Count';
import ExCard from '../ExCard';
-function ByUrl({ onCard }: { onCard: (card: string) => void }) {
+function ByUrl(props: any) {
const [mode, setMode] = React.useState(0);
const rows = [
{
@@ -48,11 +48,10 @@ function ByUrl({ onCard }: { onCard: (card: string) => void }) {
const lineWidth = 240;
return (
- Sessions by
+ {props.title}
void }) {
+function SessionsByErrors(props: any) {
return (
);
}
-export default SessionsByErrors
\ No newline at end of file
+export default SessionsByErrors
diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsByIssues.tsx b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsByIssues.tsx
index 044f4c4c3..ab8ec58c2 100644
--- a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsByIssues.tsx
+++ b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsByIssues.tsx
@@ -2,16 +2,14 @@ import React from 'react'
import ExCard from "./ExCard";
import { Frustrations } from "./Count";
-function SessionsByIssues({ onCard }: { onCard: (card: string) => void }) {
+function SessionsByIssues(props: any) {
return (
);
}
-export default SessionsByIssues
\ No newline at end of file
+export default SessionsByIssues
diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/SlowestDomain.tsx b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/SlowestDomain.tsx
index 3f055b078..d39062eb2 100644
--- a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/SlowestDomain.tsx
+++ b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/SlowestDomain.tsx
@@ -4,7 +4,7 @@ import React from 'react';
import { Circle } from './Count';
import ExCard from './ExCard';
-function SlowestDomain({ onCard }: { onCard: (card: string) => void }) {
+function SlowestDomain(props: any) {
const rows = [
{
label: 'kroger.com',
@@ -42,9 +42,7 @@ function SlowestDomain({ onCard }: { onCard: (card: string) => void }) {
return (
{rows.map((r) => (
diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/Tabs/CoreWebVitals.tsx b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/Tabs/CoreWebVitals.tsx
new file mode 100644
index 000000000..3cd3d7603
--- /dev/null
+++ b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/Tabs/CoreWebVitals.tsx
@@ -0,0 +1,20 @@
+import React from 'react';
+import PerfBreakdown from '../PerfBreakdown';
+import SlowestDomain from '../SlowestDomain';
+import SessionsByIssues from '../SessionsByIssues';
+import SessionsByErrors from '../SessionsByErrors';
+
+interface ExampleProps {
+ onCard: (card: string) => void;
+}
+
+const CoreWebVitals: React.FC
= ({onCard}) => (
+ <>
+
+
+
+
+ >
+);
+
+export default CoreWebVitals;
diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/Tabs/PerformanceMonitoring.tsx b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/Tabs/PerformanceMonitoring.tsx
new file mode 100644
index 000000000..2836f706a
--- /dev/null
+++ b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/Tabs/PerformanceMonitoring.tsx
@@ -0,0 +1,20 @@
+import React from 'react';
+import PerfBreakdown from '../PerfBreakdown';
+import SlowestDomain from '../SlowestDomain';
+import SessionsByErrors from '../SessionsByErrors';
+import SessionsByIssues from '../SessionsByIssues';
+
+interface ExampleProps {
+ onCard: (card: string) => void;
+}
+
+const PerformanceMonitoring: React.FC = ({onCard}) => (
+ <>
+
+
+
+
+ >
+);
+
+export default PerformanceMonitoring;
diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/Tabs/ProductAnalytics.tsx b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/Tabs/ProductAnalytics.tsx
new file mode 100644
index 000000000..d0f0c1caf
--- /dev/null
+++ b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/Tabs/ProductAnalytics.tsx
@@ -0,0 +1,20 @@
+import React from 'react';
+import ExampleFunnel from '../Funnel';
+import ExamplePath from '../Path';
+import ExampleTrend from '../Trend';
+import ExampleCount from '../Count';
+
+interface ExampleProps {
+ onCard: (card: string) => void;
+}
+
+const ProductAnalytics: React.FC = ({ onCard }) => (
+ <>
+
+
+
+
+ >
+);
+
+export default ProductAnalytics;
diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/Tabs/WebAnalytics.tsx b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/Tabs/WebAnalytics.tsx
new file mode 100644
index 000000000..3fef1ab7a
--- /dev/null
+++ b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/Tabs/WebAnalytics.tsx
@@ -0,0 +1,20 @@
+import React from 'react';
+import ByBrowser from '../SessionsBy/ByBrowser';
+import BySystem from '../SessionsBy/BySystem';
+import ByCountry from '../SessionsBy/ByCountry';
+import ByUrl from '../SessionsBy/ByUrl';
+
+interface ExampleProps {
+ onCard: (card: string) => void;
+}
+
+const WebAnalytics: React.FC = ({onCard}) => (
+ <>
+
+
+
+
+ >
+);
+
+export default WebAnalytics;
diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/Trend.tsx b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/Trend.tsx
index c9b925ba9..5de714619 100644
--- a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/Trend.tsx
+++ b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/Trend.tsx
@@ -3,18 +3,19 @@ import React from 'react';
import ExCard from './ExCard';
-function ExampleTrend({ onCard }: { onCard: (card: string) => void }) {
+function ExampleTrend(props: any) {
const rows = [50, 40, 30, 20, 10];
const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May'];
const [isMulti, setIsMulti] = React.useState(false);
return (
- Trend
+ {props.title}
void;
+ open: boolean;
+}
+
+const NewDashboardModal: React.FC = ({onClose, open}) => {
+ const [step, setStep] = React.useState(0);
+ const [selectedCard, setSelectedCard] = React.useState('trend-single');
+ const {metricStore} = useStore();
+
+ const onCard = (card: any) => {
+ setStep(step + 1);
+ // setSelectedCard(card);
+ // console.log('Selected card:', card)
+ console.log('Selected card:', card)
+ metricStore.merge({
+ name: card.title,
+ });
+ metricStore.changeType(card.cardType);
+ };
+
+ const [modalOpen, setModalOpen] = React.useState(false);
+
+ useEffect(() => {
+ return () => {
+ setStep(1);
+ }
+ }, [open]);
+
+ return (
+ <>
+
+
+
+ {step === 0 && }
+ {step === 1 && setStep(0)}/>}
+
+
+
+ >
+ );
+};
+
+export default NewDashboardModal;
diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Option.tsx b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Option.tsx
new file mode 100644
index 000000000..7c08512ca
--- /dev/null
+++ b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Option.tsx
@@ -0,0 +1,16 @@
+import React from 'react';
+import {LucideIcon} from "lucide-react";
+
+interface OptionProps {
+ label: string;
+ Icon: LucideIcon;
+}
+
+const Option: React.FC = ({label, Icon}) => (
+
+);
+
+export default Option;
diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/SelectCard.tsx b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/SelectCard.tsx
new file mode 100644
index 000000000..0e4af66f3
--- /dev/null
+++ b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/SelectCard.tsx
@@ -0,0 +1,228 @@
+import React, {useMemo} from 'react';
+import {Segmented} from 'antd';
+import Option from './Option';
+// import ProductAnalytics from './Examples/ProductAnalytics';
+// import PerformanceMonitoring from './Examples/PerformanceMonitoring';
+// import WebAnalytics from './Examples/WebAnalytics';
+// import CoreWebVitals from './Examples/CoreWebVitals';
+import {TrendingUp, Activity, BarChart, TableCellsMerge} from "lucide-react";
+import ExampleFunnel from "Components/Dashboard/components/DashboardList/NewDashModal/Examples/Funnel";
+import ExamplePath from "Components/Dashboard/components/DashboardList/NewDashModal/Examples/Path";
+import ExampleTrend from "Components/Dashboard/components/DashboardList/NewDashModal/Examples/Trend";
+import ExampleCount from "Components/Dashboard/components/DashboardList/NewDashModal/Examples/Count";
+import PerfBreakdown from "Components/Dashboard/components/DashboardList/NewDashModal/Examples/PerfBreakdown";
+import SlowestDomain from "Components/Dashboard/components/DashboardList/NewDashModal/Examples/SlowestDomain";
+import SessionsByErrors from "Components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsByErrors";
+import SessionsByIssues from "Components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsByIssues";
+import ByBrowser from "Components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsBy/ByBrowser";
+import BySystem from "Components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsBy/BySystem";
+import ByCountry from "Components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsBy/ByCountry";
+import ByUrl from "Components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsBy/ByUrl";
+import {ERRORS, FUNNEL, TIMESERIES, USER_PATH} from "App/constants/card";
+
+interface SelectCardProps {
+ onClose: () => void;
+ onCard: (card: any) => void;
+}
+
+const CARD_CATEGORY = {
+ PRODUCT_ANALYTICS: 'product-analytics',
+ PERFORMANCE_MONITORING: 'performance-monitoring',
+ WEB_ANALYTICS: 'web-analytics',
+ CORE_WEB_VITALS: 'core-web-vitals',
+}
+
+const segmentedOptions = [
+ {label: 'Product Analytics', Icon: TrendingUp, value: CARD_CATEGORY.PRODUCT_ANALYTICS},
+ {label: 'Performance Monitoring', Icon: Activity, value: CARD_CATEGORY.PERFORMANCE_MONITORING},
+ {label: 'Web Analytics', Icon: BarChart, value: CARD_CATEGORY.WEB_ANALYTICS},
+ {label: 'Core Web Vitals', Icon: TableCellsMerge, value: CARD_CATEGORY.CORE_WEB_VITALS},
+];
+
+const TYPE = {
+ FUNNEL: 'funnel',
+ PATH_FINDER: 'path-finder',
+ TREND: 'trend',
+ SESSIONS_BY: 'sessions-by',
+ BREAKDOWN: 'breakdown',
+ SLOWEST_DOMAIN: 'slowest-domain',
+ SESSIONS_BY_ERRORS: 'sessions-by-errors',
+ SESSIONS_BY_ISSUES: 'sessions-by-issues',
+ SESSIONS_BY_BROWSER: 'sessions-by-browser',
+ SESSIONS_BY_SYSTEM: 'sessions-by-system',
+ SESSIONS_BY_COUNTRY: 'sessions-by-country',
+ SESSIONS_BY_URL: 'sessions-by-url',
+}
+
+const CARD_TYPE_MAP = {
+ [TYPE.FUNNEL]: FUNNEL,
+ [TYPE.PATH_FINDER]: USER_PATH,
+ [TYPE.TREND]: TIMESERIES,
+ [TYPE.SESSIONS_BY]: TIMESERIES,
+ [TYPE.BREAKDOWN]: TIMESERIES,
+ [TYPE.SLOWEST_DOMAIN]: TIMESERIES,
+ [TYPE.SESSIONS_BY_ERRORS]: ERRORS,
+ [TYPE.SESSIONS_BY_ISSUES]: TIMESERIES,
+ [TYPE.SESSIONS_BY_BROWSER]: TIMESERIES,
+ [TYPE.SESSIONS_BY_SYSTEM]: TIMESERIES,
+ [TYPE.SESSIONS_BY_COUNTRY]: TIMESERIES,
+ [TYPE.SESSIONS_BY_URL]: TIMESERIES,
+}
+
+export const CARD_LIST = [
+ {
+ title: 'Funnel',
+ key: TYPE.FUNNEL,
+ cardType: FUNNEL,
+ category: CARD_CATEGORY.PRODUCT_ANALYTICS,
+ example: ExampleFunnel,
+ },
+ {
+ title: 'Path Finder',
+ key: TYPE.PATH_FINDER,
+ cardType: USER_PATH,
+ category: CARD_CATEGORY.PRODUCT_ANALYTICS,
+ example: ExamplePath,
+ },
+ {
+ title: 'Trend',
+ key: TYPE.TREND,
+ cardType: TIMESERIES,
+ category: CARD_CATEGORY.PRODUCT_ANALYTICS,
+ example: ExampleTrend,
+ },
+ {
+ title: 'Sessions by',
+ key: TYPE.SESSIONS_BY,
+ cardType: TIMESERIES,
+ category: CARD_CATEGORY.PRODUCT_ANALYTICS,
+ example: ExampleCount,
+ },
+ {
+ title: 'Breakdown',
+ key: TYPE.BREAKDOWN,
+ cardType: TIMESERIES,
+ category: CARD_CATEGORY.PERFORMANCE_MONITORING,
+ example: PerfBreakdown,
+ },
+ {
+ title: 'Slowest Domain',
+ key: TYPE.SLOWEST_DOMAIN,
+ cardType: TIMESERIES,
+ category: CARD_CATEGORY.PERFORMANCE_MONITORING,
+ example: SlowestDomain,
+ },
+ {
+ title: 'Sessions by Errors',
+ key: TYPE.SESSIONS_BY_ERRORS,
+ cardType: TIMESERIES,
+ category: CARD_CATEGORY.PERFORMANCE_MONITORING,
+ example: SessionsByErrors,
+ },
+ {
+ title: 'Sessions by Issues',
+ key: TYPE.SESSIONS_BY_ISSUES,
+ cardType: TIMESERIES,
+ category: CARD_CATEGORY.PERFORMANCE_MONITORING,
+ example: SessionsByIssues,
+ },
+
+ {
+ title: 'Sessions by Browser',
+ key: TYPE.SESSIONS_BY_BROWSER,
+ cardType: TIMESERIES,
+ category: CARD_CATEGORY.WEB_ANALYTICS,
+ example: ByBrowser,
+ },
+ {
+ title: 'Sessions by System',
+ key: TYPE.SESSIONS_BY_SYSTEM,
+ cardType: TIMESERIES,
+ category: CARD_CATEGORY.WEB_ANALYTICS,
+ example: BySystem,
+ },
+ {
+ title: 'Sessions by Country',
+ key: TYPE.SESSIONS_BY_COUNTRY,
+ cardType: TIMESERIES,
+ category: CARD_CATEGORY.WEB_ANALYTICS,
+ example: ByCountry,
+ },
+ {
+ title: 'Sessions by URL',
+ key: TYPE.SESSIONS_BY_URL,
+ cardType: TIMESERIES,
+ category: CARD_CATEGORY.WEB_ANALYTICS,
+ example: ByUrl,
+ },
+
+ // {
+ // title: 'Breakdown',
+ // key: TYPE.BREAKDOWN,
+ // category: CARD_CATEGORY.CORE_WEB_VITALS,
+ // example: PerfBreakdown,
+ // },
+ // {
+ // title: 'Slowest Domain',
+ // key: TYPE.SLOWEST_DOMAIN,
+ // category: CARD_CATEGORY.CORE_WEB_VITALS,
+ // example: SlowestDomain,
+ // },
+ // {
+ // title: 'Sessions by Issues',
+ // key: TYPE.SESSIONS_BY_ISSUES,
+ // category: CARD_CATEGORY.CORE_WEB_VITALS,
+ // example: SessionsByIssues,
+ // },
+ // {
+ // title: 'Sessions by Errors',
+ // key: TYPE.SESSIONS_BY_ISSUES,
+ // category: CARD_CATEGORY.CORE_WEB_VITALS,
+ // example: SessionsByErrors,
+ // },
+]
+
+const SelectCard: React.FC = (props: SelectCardProps) => {
+ const [selected, setSelected] = React.useState('product-analytics');
+ // const item = getSelectedItem(selected, onCard);
+
+ const onCard = (card: string) => {
+ const _card = CARD_LIST.find((c) => c.key === card);
+ props.onCard(_card);
+ // props.onClose();
+ }
+
+
+ const item = useMemo(() => {
+ return CARD_LIST.filter((card) => card.category === selected).map((card) => (
+
+
+
+ ));
+ }, [selected]);
+
+ return (
+ <>
+
+
+ Select your first card type to add to the dashboard
+
+
+
+ ({
+ label: ,
+ value,
+ }))}
+ onChange={setSelected}
+ />
+
+
+ {item}
+
+ >
+ );
+};
+
+export default SelectCard;
diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/index.ts b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/index.ts
new file mode 100644
index 000000000..8854c0779
--- /dev/null
+++ b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/index.ts
@@ -0,0 +1 @@
+export {default} from './NewDashboardModal';
diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/index.tsx b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/index.tsx
deleted file mode 100644
index 42b7714a2..000000000
--- a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/index.tsx
+++ /dev/null
@@ -1,174 +0,0 @@
-import { Segmented } from 'antd';
-import { Activity, BarChart, TableCellsMerge, TrendingUp } from 'lucide-react';
-import React from 'react';
-
-import { Modal } from 'UI';
-
-import ExampleCount from './Examples/Count';
-import ExampleFunnel from './Examples/Funnel';
-import ExamplePath from './Examples/Path';
-import PerfBreakdown from './Examples/PerfBreakdown';
-import ByBrowser from './Examples/SessionsBy/ByBrowser';
-import ByCountry from './Examples/SessionsBy/ByCountry';
-import BySystem from './Examples/SessionsBy/BySystem';
-import ByUrl from './Examples/SessionsBy/ByUrl';
-import SessionsByErrors from './Examples/SessionsByErrors';
-import SessionsByIssues from './Examples/SessionsByIssues';
-import SlowestDomain from './Examples/SlowestDomain';
-import ExampleTrend from './Examples/Trend';
-
-function NewDashboardModal(props: { onClose: () => void; open: boolean }) {
- const [step, setStep] = React.useState(0);
-
- const onCard = (card: string) => {
- console.log(card);
- };
- return (
-
-
-
- {step === 0 ? (
-
- ) : null}
-
-
-
- );
-}
-
-function SelectCard({
- onClose,
- onCard,
-}: {
- onClose: () => void;
- onCard: (card: string) => void;
-}) {
- const initial = 'product-analytics';
- const [selected, setSelected] = React.useState(initial);
- let item;
- switch (selected) {
- case 'product-analytics':
- item = ;
- break;
- case 'performance-monitoring':
- item = ;
- break;
- case 'web-analytics':
- item = ;
- break;
- case 'core-web-vitals':
- item = ;
- break;
- default:
- item = under construction
;
- break;
- }
- return (
- <>
-
-
- Select your first card type to add to the dashboard
-
-
- Close
-
-
-
-
-
- Product Analytics
-
- ),
- value: 'product-analytics',
- },
- {
- label: (
-
-
-
Performance Monitoring
-
- ),
- value: 'performance-monitoring',
- },
- {
- label: (
-
- ),
- value: 'web-analytics',
- },
- {
- label: (
-
- ),
- value: 'core-web-vitals',
- },
- ]}
- onChange={(v) => setSelected(v)}
- />
-
-
- {item}
-
-
- >
- );
-}
-
-function ProductAnalytics({ onCard }: { onCard: (card: string) => void }) {
- return (
- <>
-
-
-
-
- >
- );
-}
-
-function PerformanceMonitoring({ onCard }: { onCard: (card: string) => void }) {
- return (
- <>
-
-
-
-
- >
- );
-}
-
-function WebAnalytics({ onCard }: { onCard: (card: string) => void }) {
- return (
- <>
-
-
-
-
- >
- );
-}
-
-function CoreWebVitals({ onCard }: { onCard: (card: string) => void }) {
- return (
- <>
-
-
-
-
- >
- );
-}
-
-export default NewDashboardModal;
diff --git a/frontend/app/components/Dashboard/components/WidgetForm/CardBuilder.tsx b/frontend/app/components/Dashboard/components/WidgetForm/CardBuilder.tsx
new file mode 100644
index 000000000..464a3d2f5
--- /dev/null
+++ b/frontend/app/components/Dashboard/components/WidgetForm/CardBuilder.tsx
@@ -0,0 +1,292 @@
+import React, {useEffect, useState, useCallback} from 'react';
+import {observer} from 'mobx-react-lite';
+import {useStore} from 'App/mstore';
+import {metricOf, issueOptions, issueCategories} from 'App/constants/filterOptions';
+import {FilterKey} from 'Types/filter/filterType';
+import {withSiteId, dashboardMetricDetails, metricDetails} from 'App/routes';
+import {Icon, confirm} from 'UI';
+import {Card, Input, Space, Button} from 'antd';
+import {AudioWaveform} from "lucide-react";
+import FilterSeries from '../FilterSeries';
+import Select from 'Shared/Select';
+import MetricTypeDropdown from './components/MetricTypeDropdown';
+import MetricSubtypeDropdown from './components/MetricSubtypeDropdown';
+import {eventKeys} from 'App/types/filter/newFilter';
+import {renderClickmapThumbnail} from './renderMap';
+import FilterItem from 'Shared/Filters/FilterItem';
+import {
+ TIMESERIES, TABLE, CLICKMAP, FUNNEL, ERRORS, RESOURCE_MONITORING,
+ PERFORMANCE, WEB_VITALS, INSIGHTS, USER_PATH, RETENTION
+} from 'App/constants/card';
+import {useParams} from 'react-router-dom';
+import {useHistory} from "react-router";
+
+const AIInput = ({value, setValue, placeholder, onEnter}) => (
+ setValue(e.target.value)}
+ className='w-full mb-2'
+ onKeyDown={(e) => e.key === 'Enter' && onEnter()}
+ />
+);
+
+const PredefinedMessage = () => (
+
+
+
Filtering and drill-downs will be supported soon for this card type.
+
+);
+
+const MetricOptions = ({metric, writeOption}) => {
+ const isUserPath = metric.metricType === USER_PATH;
+
+ return (
+
+
+ Card showing
+
+
+ {isUserPath && (
+ <>
+
+
+ showing
+
+ >
+ )}
+ {metric.metricOf === FilterKey.ISSUE && metric.metricType === TABLE && (
+ <>
+ issue type
+
+ >
+ )}
+ {metric.metricType === INSIGHTS && (
+ <>
+ of
+
+ >
+ )}
+ {metric.metricType === TABLE &&
+ !(metric.metricOf === FilterKey.ERRORS || metric.metricOf === FilterKey.SESSIONS) && (
+ <>
+ showing
+
+ >
+ )}
+
+
+ );
+};
+
+const PathAnalysisFilter = ({metric}) => (
+
+ {metric.startType === 'start' ? 'Start Point' : 'End Point'}
+ metric.updateStartPoint(val)}
+ onRemoveFilter={() => {
+ }}
+ />
+
+);
+
+const SeriesList = observer(() => {
+ const {metricStore, dashboardStore, aiFiltersStore} = useStore();
+ const metric = metricStore.instance;
+ const excludeFilterKeys = [CLICKMAP, USER_PATH].includes(metric.metricType) ? eventKeys : [];
+ const hasSeries = ![TABLE, FUNNEL, CLICKMAP, INSIGHTS, USER_PATH, RETENTION].includes(metric.metricType);
+ const canAddSeries = metric.series.length < 3;
+
+ return (
+
+ {metric.series.length > 0 && metric.series
+ .slice(0, hasSeries ? metric.series.length : 1)
+ .map((series, index) => (
+
+ metric.updateKey('hasChanged', true)}
+ hideHeader={[TABLE, CLICKMAP, INSIGHTS, USER_PATH, FUNNEL].includes(metric.metricType)}
+ seriesIndex={index}
+ series={series}
+ onRemoveSeries={() => metric.removeSeries(index)}
+ canDelete={metric.series.length > 1}
+ emptyMessage={
+ metric.metricType === TABLE
+ ? 'Filter data using any event or attribute. Use Add Step button below to do so.'
+ : 'Add user event or filter to define the series by clicking Add Step.'
+ }
+ />
+
+ ))}
+ {hasSeries && (
+
+ metric.addSeries()}
+ disabled={!canAddSeries}
+ size="small"
+ >
+
+
+ New Chart Series
+
+
+
+ )}
+
+ );
+});
+
+interface RouteParams {
+ siteId: string;
+ dashboardId: string;
+ metricId: string;
+}
+
+const CardBuilder = observer(() => {
+ const history = useHistory();
+ const {siteId, dashboardId} = useParams();
+ console.log('siteId', siteId);
+ const {metricStore, dashboardStore, aiFiltersStore} = useStore();
+ const [aiQuery, setAiQuery] = useState('');
+ const [aiAskChart, setAiAskChart] = useState('');
+ const [initialInstance, setInitialInstance] = useState(null);
+ const metric = metricStore.instance;
+ const timeseriesOptions = metricOf.filter(i => i.type === 'timeseries');
+ const tableOptions = metricOf.filter(i => i.type === 'table');
+ const isPredefined = [ERRORS, PERFORMANCE, RESOURCE_MONITORING, WEB_VITALS].includes(metric.metricType);
+ const testingKey = localStorage.getItem('__mauricio_testing_access') === 'true';
+
+
+ useEffect(() => {
+ if (metric && !initialInstance) setInitialInstance(metric.toJson());
+ }, [metric]);
+
+ const writeOption = useCallback(({value, name}) => {
+ value = Array.isArray(value) ? value : value.value;
+ const obj: any = {[name]: value};
+ if (name === 'metricType') {
+ if (value === TIMESERIES) obj.metricOf = timeseriesOptions[0].value;
+ if (value === TABLE) obj.metricOf = tableOptions[0].value;
+ }
+ metricStore.merge(obj);
+ }, [metricStore, timeseriesOptions, tableOptions]);
+
+ const onSave = useCallback(async () => {
+ const wasCreating = !metric.exists();
+ if (metric.metricType === CLICKMAP) {
+ try {
+ metric.thumbnail = await renderClickmapThumbnail();
+ } catch (e) {
+ console.error(e);
+ }
+ }
+ const savedMetric = await metricStore.save(metric);
+ setInitialInstance(metric.toJson());
+ if (wasCreating) {
+ const route = parseInt(dashboardId, 10) > 0
+ ? withSiteId(dashboardMetricDetails(dashboardId, savedMetric.metricId), siteId)
+ : withSiteId(metricDetails(savedMetric.metricId), siteId);
+ history.replace(route);
+ if (parseInt(dashboardId, 10) > 0) {
+ dashboardStore.addWidgetToDashboard(
+ dashboardStore.getDashboard(parseInt(dashboardId, 10)),
+ [savedMetric.metricId]
+ );
+ }
+ }
+ }, [dashboardId, dashboardStore, history, metric, metricStore, siteId]);
+
+ const onDelete = useCallback(async () => {
+ if (await confirm({
+ header: 'Confirm',
+ confirmButton: 'Yes, delete',
+ confirmation: 'Are you sure you want to permanently delete this card?'
+ })) {
+ metricStore.delete(metric).then(onDelete);
+ }
+ }, [metric, metricStore]);
+
+ const undoChanges = useCallback(() => {
+ const w = new Widget();
+ metricStore.merge(w.fromJson(initialInstance), false);
+ }, [initialInstance, metricStore]);
+
+ const fetchResults = useCallback(() => aiFiltersStore.getCardFilters(aiQuery, metric.metricType)
+ .then(f => metric.createSeries(f.filters)), [aiFiltersStore, aiQuery, metric]);
+
+ const fetchChartData = useCallback(() => aiFiltersStore.getCardData(aiAskChart, metric.toJson()),
+ [aiAskChart, aiFiltersStore, metric]);
+
+ return (
+
+
+ {metric.metricType === USER_PATH &&
}
+ {isPredefined && }
+ {testingKey && (
+ <>
+
+
+ >
+ )}
+ {aiFiltersStore.isLoading && (
+
+ )}
+ {!isPredefined && }
+
+ );
+});
+
+export default CardBuilder;