diff --git a/frontend/app/components/Dashboard/components/AddCardSection/AddCardSection.tsx b/frontend/app/components/Dashboard/components/AddCardSection/AddCardSection.tsx new file mode 100644 index 000000000..ca2378642 --- /dev/null +++ b/frontend/app/components/Dashboard/components/AddCardSection/AddCardSection.tsx @@ -0,0 +1,177 @@ +import React from 'react'; +import { FolderOutlined } from '@ant-design/icons'; +import { Segmented } from 'antd'; +import { + LineChart, + AlignStartVertical, + ArrowUpDown, + WifiOff, + Turtle, + FileStack, + AppWindow, + Combine, + Users, + ArrowDown10, + Sparkles, +} from 'lucide-react'; +import { Icon } from 'UI'; + +interface TabItem { + icon: React.ReactNode; + title: string; + description: string; +} +const tabItems: Record = { + product_analytics: [ + { + icon: , + title: 'Trends', + description: 'Track session trends over time.', + }, + { + icon: , + title: 'Funnel', + description: 'Visualize user progression through critical steps.', + }, + { + icon: , + title: 'Journeys', + description: 'Understand the paths users take through your product.', + }, + { + icon: , + title: 'Retention', + description: 'Analyze user retention over specific time periods.', + }, + { + icon: , + title: 'Heatmaps', + description: 'Generate a report using by asking AI.', + }, + ], + monitors: [ + { + icon: , + title: 'JS Errors', + description: 'Monitor JS errors affecting user experience.', + }, + { + icon: , + title: 'Top Network Requests', + description: 'Identify the most frequent network requests.', + }, + { + icon: , + title: '4xx/5xx Requests', + description: 'Track client and server errors for performance issues.', + }, + { + icon: , + title: 'Slow Network Requests', + description: 'Pinpoint the slowest network requests causing delays.', + }, + ], + web_analytics: [ + { + icon: , + title: 'Top Pages', + description: 'Discover the most visited pages on your site.', + }, + { + icon: , + title: 'Top Browsers', + description: 'Analyze the browsers your visitors are using the most.', + }, + { + icon: , + title: 'Top Referrer', + description: 'See where your traffic is coming from.', + }, + { + icon: , + title: 'Top Users', + description: 'Identify the users with the most interactions.', + }, + { + icon: , + title: 'Speed Index by Country', + description: 'Measure performance across different regions.', + }, + ], +}; + +function CategoryTab({ tab }: { tab: string }) { + const items = tabItems[tab]; + return ( +
+ {items.map((item, index) => ( +
+ {item.icon} +
+
{item.title}
+
+ {item.description} +
+
+
+ ))} +
+ ); +} + +function AddCardSection() { + const [tab, setTab] = React.useState('product_analytics'); + const options = [ + { label: 'Product Analytics', value: 'product_analytics' }, + { label: 'Monitors', value: 'monitors' }, + { label: 'Web Analytics', value: 'web_analytics' }, + ]; + + const originStr = window.env.ORIGIN || window.location.origin; + const isSaas = /api\.openreplay\.com/.test(originStr) + return ( +
+
+
Add a card to dashboard
+ {isSaas ? +
+ +
Ask AI
+
+ : null} +
+
+ setTab(value)} + /> +
+ +
+ +
Add existing card
+
+
+ ); +} + +export default AddCardSection; diff --git a/frontend/app/components/Dashboard/components/DashboardHeader/DashboardHeader.tsx b/frontend/app/components/Dashboard/components/DashboardHeader/DashboardHeader.tsx index 09f2348f6..793a858fc 100644 --- a/frontend/app/components/Dashboard/components/DashboardHeader/DashboardHeader.tsx +++ b/frontend/app/components/Dashboard/components/DashboardHeader/DashboardHeader.tsx @@ -1,5 +1,4 @@ import React from 'react'; -//import {Breadcrumb} from 'Shared/Breadcrumb'; import BackButton from '../../../shared/Breadcrumb/BackButton'; import { withSiteId } from 'App/routes'; import { withRouter, RouteComponentProps } from 'react-router-dom'; @@ -11,8 +10,6 @@ import DashboardOptions from '../DashboardOptions'; import withModal from 'App/components/Modal/withModal'; import { observer } from 'mobx-react-lite'; import DashboardEditModal from '../DashboardEditModal'; -import CreateDashboardButton from 'Components/Dashboard/components/CreateDashboardButton'; -import CreateCard from 'Components/Dashboard/components/DashboardList/NewDashModal/CreateCard'; import CreateCardButton from 'Components/Dashboard/components/CreateCardButton'; interface IProps { @@ -21,14 +18,12 @@ interface IProps { renderReport?: any; } - type Props = IProps & RouteComponentProps; const MAX_CARDS = 29; function DashboardHeader(props: Props) { - const { siteId, dashboardId } = props; + const { siteId } = props; const { dashboardStore } = useStore(); - const { showModal } = useModal(); const [focusTitle, setFocusedInput] = React.useState(true); const [showEditModal, setShowEditModal] = React.useState(false); const period = dashboardStore.period; @@ -47,7 +42,7 @@ function DashboardHeader(props: Props) { await confirm({ header: 'Delete Dashboard', confirmButton: 'Yes, delete', - confirmation: `Are you sure you want to permanently delete this Dashboard?` + confirmation: `Are you sure you want to permanently delete this Dashboard?`, }) ) { dashboardStore.deleteDashboard(dashboard).then(() => { @@ -56,32 +51,25 @@ function DashboardHeader(props: Props) { } }; return ( -
+ <> setShowEditModal(false)} focusTitle={focusTitle} /> -
-
- - - - {/* */} +
+
+ + {dashboard?.name} } @@ -89,45 +77,28 @@ function DashboardHeader(props: Props) { className="mr-3 select-none border-b border-b-borderColor-transparent hover:border-dashed hover:border-gray-medium cursor-pointer" />
-
- +
+ dashboardStore.setPeriod(period)} + right={true} + isAnt={true} + useButtonStyle={true} + /> -
- dashboardStore.setPeriod(period)} - right={true} - isAnt={true} - useButtonStyle={true} - /> -
- -
- -
+
-
- {/* @ts-ignore */} - -

onEdit(false)} - > - {/* {dashboard?.description || 'Describe the purpose of this dashboard'} */} -

-
-
-
+ ); } diff --git a/frontend/app/components/Dashboard/components/DashboardView/DashboardView.tsx b/frontend/app/components/Dashboard/components/DashboardView/DashboardView.tsx index 35672205f..936eff98b 100644 --- a/frontend/app/components/Dashboard/components/DashboardView/DashboardView.tsx +++ b/frontend/app/components/Dashboard/components/DashboardView/DashboardView.tsx @@ -98,7 +98,7 @@ function DashboardView(props: Props) { const isSaas = /app\.openreplay\.com/.test(originStr); return ( -
+
{/* @ts-ignore */} {isSaas ? : null} diff --git a/frontend/app/components/Dashboard/components/DashboardWidgetGrid/DashboardWidgetGrid.tsx b/frontend/app/components/Dashboard/components/DashboardWidgetGrid/DashboardWidgetGrid.tsx index 7720101c0..62e9253f0 100644 --- a/frontend/app/components/Dashboard/components/DashboardWidgetGrid/DashboardWidgetGrid.tsx +++ b/frontend/app/components/Dashboard/components/DashboardWidgetGrid/DashboardWidgetGrid.tsx @@ -1,10 +1,9 @@ import React from 'react'; import { useStore } from 'App/mstore'; import WidgetWrapperNew from 'Components/Dashboard/components/WidgetWrapper/WidgetWrapperNew'; -import { Empty } from 'antd'; -import { NoContent, Loader } from 'UI'; -import { useObserver } from 'mobx-react-lite'; -import AnimatedSVG, { ICONS } from 'Shared/AnimatedSVG/AnimatedSVG'; +import { Loader } from 'UI'; +import { observer } from 'mobx-react-lite'; +import AddCardSection from "../AddCardSection/AddCardSection"; interface Props { siteId: string; @@ -16,32 +15,16 @@ interface Props { function DashboardWidgetGrid(props: Props) { const { dashboardId, siteId } = props; const { dashboardStore } = useStore(); - const loading = useObserver(() => dashboardStore.isLoading); + const loading = dashboardStore.isLoading; const dashboard = dashboardStore.selectedDashboard; - const list = useObserver(() => dashboard?.widgets); + const list = dashboard?.widgets; - return useObserver(() => ( + return ( { list?.length === 0 ? ( -
- -
- -
-
- There are no cards in this dashboard -
-
- Create a card by clicking the "Add Card" button to visualize insights here. -
-
- } - /> +
+
) : (
@@ -65,7 +48,7 @@ function DashboardWidgetGrid(props: Props) { ) } - )); + ); } -export default DashboardWidgetGrid; +export default observer(DashboardWidgetGrid); diff --git a/frontend/app/components/shared/Breadcrumb/BackButton.tsx b/frontend/app/components/shared/Breadcrumb/BackButton.tsx index a93ad705f..ef046d5a0 100644 --- a/frontend/app/components/shared/Breadcrumb/BackButton.tsx +++ b/frontend/app/components/shared/Breadcrumb/BackButton.tsx @@ -1,16 +1,20 @@ import React from 'react'; import { Button } from 'antd'; import { useHistory } from 'react-router-dom'; -import { LeftOutlined } from '@ant-design/icons'; +import { LeftOutlined, ArrowLeftOutlined } from '@ant-design/icons'; -function BackButton() { +function BackButton({ compact }: { compact?: boolean }) { const history = useHistory(); const siteId = location.pathname.split('/')[1]; const handleBackClick = () => { history.push(`/${siteId}/dashboard`); }; - + if (compact) { + return ( +