import React, { useState, useEffect } from 'react'; import { useStore } from 'App/mstore'; import { Loader, NavPrompt } from 'UI'; import WidgetPreview from '../WidgetPreview'; import WidgetSessions from '../WidgetSessions'; import { observer } from 'mobx-react-lite'; import { dashboardMetricDetails, metricDetails, withSiteId } from 'App/routes'; import Breadcrumb from 'Shared/Breadcrumb'; import { FilterKey } from 'Types/filter/filterType'; import { useNavigate, useLocation } from 'react-router'; import { TIMESERIES, TABLE, HEATMAP, FUNNEL, INSIGHTS, USER_PATH, RETENTION } from 'App/constants/card'; import CardUserList from '../CardUserList/CardUserList'; import WidgetViewHeader from 'Components/Dashboard/components/WidgetView/WidgetViewHeader'; import WidgetFormNew from 'Components/Dashboard/components/WidgetForm/WidgetFormNew'; import { Space, Segmented, Tooltip } from 'antd'; import { renderClickmapThumbnail } from 'Components/Dashboard/components/WidgetForm/renderMap'; import Widget from 'App/mstore/types/widget'; import { LayoutPanelTop, LayoutPanelLeft } from 'lucide-react'; import cn from 'classnames'; import { CARD_LIST, CardType } from 'Components/Dashboard/components/DashboardList/NewDashModal/ExampleCards'; import FilterSeries from '@/mstore/types/filterSeries'; interface Props { match: any; siteId: any; } const LAYOUT_KEY = '$__metric_form__layout__$'; function getDefaultState() { return localStorage.getItem(LAYOUT_KEY) || 'flex-row'; } function WidgetView({ match: { params: { siteId, dashboardId, metricId } } }: Props) { const [layout, setLayout] = useState(getDefaultState); const { metricStore, dashboardStore, settingsStore } = useStore(); const widget = metricStore.instance; const loading = metricStore.isLoading; const [expanded] = useState(!metricId || metricId === 'create'); const hasChanged = widget.hasChanged; const dashboard = dashboardStore.dashboards.find((d: any) => d.dashboardId == dashboardId); const dashboardName = dashboard ? dashboard.name : null; const [metricNotFound, setMetricNotFound] = useState(false); const navigate = useNavigate(); const location = useLocation(); const [initialInstance, setInitialInstance] = useState(); const isClickMap = widget.metricType === HEATMAP; useEffect(() => { if (!metricId || metricId === 'create') { const params = new URLSearchParams(location.search); const mk = params.get('mk'); if (mk) { metricStore.init(); const selectedCard = CARD_LIST.find(c => c.key === mk) as CardType; if (selectedCard) { const cardData: any = { metricType: selectedCard.cardType, name: selectedCard.title, metricOf: selectedCard.metricOf, category: mk, viewType: selectedCard.viewType ? selectedCard.viewType : selectedCard.cardType === FUNNEL ? 'chart' : 'lineChart', }; if (selectedCard.filters) { cardData.series = [ new FilterSeries().fromJson({ name: 'Series 1', filter: { filters: selectedCard.filters } }) ]; } if (selectedCard.cardType === FUNNEL) { cardData.series = [new FilterSeries()]; cardData.series[0].filter.addFunnelDefaultFilters(); cardData.series[0].filter.eventsOrder = 'then'; cardData.series[0].filter.eventsOrderSupport = ['then']; } metricStore.merge(cardData); } } } }, [metricId, location.search, metricStore]); useEffect(() => { if (metricId && metricId !== 'create') { metricStore.fetch(metricId, dashboardStore.period).catch(e => { if (e.response.status === 404 || e.response.status === 422) { setMetricNotFound(true); } }); } else if (!metricStore.instance) { metricStore.init(); } const wasCollapsed = settingsStore.menuCollapsed; settingsStore.updateMenuCollapsed(true); return () => { if (!wasCollapsed) settingsStore.updateMenuCollapsed(false); }; }, [metricId, metricStore, dashboardStore.period, settingsStore]); useEffect(() => { if (metricNotFound) { navigate(withSiteId('/metrics', siteId), { replace: true }); } }, [metricNotFound, siteId]); const undoChanges = () => { const w = new Widget(); metricStore.merge(w.fromJson(initialInstance), false); }; const onSave = async () => { const wasCreating = !widget.exists(); if (isClickMap) { try { widget.thumbnail = await renderClickmapThumbnail(); } catch (e) { console.error(e); } } const savedMetric = await metricStore.save(widget); setInitialInstance(widget.toJson()); if (wasCreating) { if (parseInt(dashboardId, 10) > 0) { navigate( withSiteId(dashboardMetricDetails(dashboardId, savedMetric.metricId), siteId) , { replace: true }); void dashboardStore.addWidgetToDashboard( dashboardStore.getDashboard(parseInt(dashboardId, 10))!, [savedMetric.metricId] ); } else { navigate(withSiteId(metricDetails(savedMetric.metricId), siteId), { replace: true }); } } }; const updateLayout = (val: string) => { localStorage.setItem(LAYOUT_KEY, val); setLayout(val); }; return ( loc.pathname.includes('/metrics/') || loc.pathname.includes('/metric/') ? true : 'You have unsaved changes. Are you sure you want to leave?' } />
) }, { value: 'flex-col', icon: ( ) }, { value: 'flex-row-reverse', icon: (
) } ]} /> } />
{widget.metricOf !== FilterKey.SESSIONS && widget.metricOf !== FilterKey.ERRORS && ([TABLE, TIMESERIES, HEATMAP, INSIGHTS, FUNNEL, USER_PATH].includes(widget.metricType) ? ( ) : null)} {widget.metricType === RETENTION && }
); } export default observer(WidgetView);