diff --git a/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricLineChart/CustomMetricLineChart.tsx b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricLineChart/CustomMetricLineChart.tsx index 8e7fcf321..618c6ed6b 100644 --- a/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricLineChart/CustomMetricLineChart.tsx +++ b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricLineChart/CustomMetricLineChart.tsx @@ -1,10 +1,5 @@ -import React, { useState } from 'react'; -import { formatTimeOrDate } from 'App/date'; -import { Button, Table } from 'antd'; -import type { TableProps } from 'antd'; +import React from 'react'; import CustomTooltip from "../CustomChartTooltip"; - -import { Eye, EyeOff } from 'lucide-react'; import { Styles } from '../../common'; import { ResponsiveContainer, @@ -16,7 +11,7 @@ import { Line, Legend, } from 'recharts'; -import cn from 'classnames'; +import { observer } from 'mobx-react-lite'; interface Props { data: any; @@ -34,7 +29,6 @@ function CustomMetricLineChart(props: Props) { const { data = { chart: [], namesMap: [] }, compData = { chart: [], namesMap: [] }, - params, colors, onClick = () => null, yaxis = { ...Styles.yaxis }, @@ -117,4 +111,4 @@ function CustomMetricLineChart(props: Props) { ); } -export default CustomMetricLineChart; +export default observer(CustomMetricLineChart); diff --git a/frontend/app/components/Dashboard/components/DashboardWidgetGrid/DashboardWidgetGrid.tsx b/frontend/app/components/Dashboard/components/DashboardWidgetGrid/DashboardWidgetGrid.tsx index 33908ee7f..ed241e8b5 100644 --- a/frontend/app/components/Dashboard/components/DashboardWidgetGrid/DashboardWidgetGrid.tsx +++ b/frontend/app/components/Dashboard/components/DashboardWidgetGrid/DashboardWidgetGrid.tsx @@ -1,7 +1,6 @@ import React from 'react'; import { useStore } from 'App/mstore'; import WidgetWrapperNew from 'Components/Dashboard/components/WidgetWrapper/WidgetWrapperNew'; -import { Loader } from 'UI'; import { observer } from 'mobx-react-lite'; import AddCardSection from '../AddCardSection/AddCardSection'; import cn from 'classnames'; diff --git a/frontend/app/components/Dashboard/components/WidgetChart/WidgetChart.tsx b/frontend/app/components/Dashboard/components/WidgetChart/WidgetChart.tsx index 931de3089..e430971df 100644 --- a/frontend/app/components/Dashboard/components/WidgetChart/WidgetChart.tsx +++ b/frontend/app/components/Dashboard/components/WidgetChart/WidgetChart.tsx @@ -52,6 +52,7 @@ function WidgetChart(props: Props) { const { isSaved = false, metric, isTemplate } = props; const { dashboardStore, metricStore } = useStore(); const _metric: any = metricStore.instance; + const data = _metric.data; const period = dashboardStore.period; const drillDownPeriod = dashboardStore.drillDownPeriod; const drillDownFilter = dashboardStore.drillDownFilter; @@ -61,7 +62,6 @@ function WidgetChart(props: Props) { const metricParams = _metric.params; const prevMetricRef = useRef(); const isMounted = useIsMounted(); - const [data, setData] = useState(metric.data); const [compData, setCompData] = useState(null); const [enabledRows, setEnabledRows] = useState([]); const isTableWidget = @@ -134,10 +134,7 @@ function WidgetChart(props: Props) { dashboardStore .fetchMetricChartData(metric, payload, isSaved, period, isComparison) .then((res: any) => { - if (isMounted()) { - if (isComparison) setCompData(res); - else setData(res); - } + if (isComparison) setCompData(res); }) .finally(() => { setLoading(false); @@ -210,13 +207,12 @@ function WidgetChart(props: Props) { ]); useEffect(loadPage, [_metric.page]); - const renderChart = () => { + const renderChart = React.useCallback(() => { const { metricType, metricOf } = metric; const viewType = metric.viewType; const metricWithData = { ...metric, data }; if (metricType === FUNNEL) { - console.log(data, compData); if (viewType === 'table') { return ( @@ -503,7 +499,7 @@ function WidgetChart(props: Props) { console.log('Unknown metric type', metricType, viewType); return
Unknown metric type
; - }; + }, [data, compData, enabledRows, metric]); return (
diff --git a/frontend/app/components/Dashboard/components/WidgetView/CardViewMenu.tsx b/frontend/app/components/Dashboard/components/WidgetView/CardViewMenu.tsx index bea20faf6..ff4c04f4d 100644 --- a/frontend/app/components/Dashboard/components/WidgetView/CardViewMenu.tsx +++ b/frontend/app/components/Dashboard/components/WidgetView/CardViewMenu.tsx @@ -1,98 +1,103 @@ -import {useHistory} from "react-router"; -import {useStore} from "App/mstore"; -import {useObserver} from "mobx-react-lite"; -import {Button, Dropdown, MenuProps, message, Modal} from "antd"; -import {BellIcon, EllipsisVertical, TrashIcon} from "lucide-react"; -import {toast} from "react-toastify"; -import React from "react"; -import {useModal} from "Components/ModalContext"; -import AlertFormModal from "Components/Alerts/AlertFormModal/AlertFormModal"; +import { useHistory } from 'react-router'; +import { useStore } from 'App/mstore'; +import { observer } from 'mobx-react-lite'; +import { Button, Dropdown, MenuProps, message, Modal } from 'antd'; +import { BellIcon, EllipsisVertical, TrashIcon } from 'lucide-react'; +import { toast } from 'react-toastify'; +import React from 'react'; +import { useModal } from 'Components/ModalContext'; +import AlertFormModal from 'Components/Alerts/AlertFormModal/AlertFormModal'; const CardViewMenu = () => { - const history = useHistory(); - const {alertsStore, dashboardStore, metricStore} = useStore(); - const widget = useObserver(() => metricStore.instance); - const {openModal, closeModal} = useModal(); + const history = useHistory(); + const { alertsStore, metricStore } = useStore(); + const widget = metricStore.instance; + const { openModal, closeModal } = useModal(); - const showAlertModal = () => { - const seriesId = widget.series[0] && widget.series[0].seriesId || ''; - alertsStore.init({query: {left: seriesId}}) - openModal(, { - // title: 'Set Alerts', - placement: 'right', - width: 620, + const showAlertModal = () => { + const seriesId = (widget.series[0] && widget.series[0].seriesId) || ''; + alertsStore.init({ query: { left: seriesId } }); + openModal(, { + // title: 'Set Alerts', + placement: 'right', + width: 620, + }); + }; + + const items: MenuProps['items'] = [ + { + key: 'alert', + label: 'Set Alerts', + icon: , + disabled: !widget.exists() || widget.metricType === 'predefined', + onClick: showAlertModal, + }, + { + key: 'remove', + label: 'Delete', + icon: , + onClick: () => { + Modal.confirm({ + title: 'Confirm Card Deletion', + icon: null, + content: + 'Are you sure you want to remove this card? This action is permanent and cannot be undone.', + footer: (_, { OkBtn, CancelBtn }) => ( + <> + + + + ), + onOk: () => { + metricStore + .delete(widget) + .then((r) => { + history.goBack(); + }) + .catch(() => { + toast.error('Failed to remove card'); + }); + }, }); - } + }, + }, + ]; - const items: MenuProps['items'] = [ - { - key: 'alert', - label: "Set Alerts", - icon: , - disabled: !widget.exists() || widget.metricType === 'predefined', - onClick: showAlertModal, - }, - { - key: 'remove', - label: 'Delete', - icon: , - onClick: () => { - Modal.confirm({ - title: 'Confirm Card Deletion', - icon: null, - content:'Are you sure you want to remove this card? This action is permanent and cannot be undone.', - footer: (_, {OkBtn, CancelBtn}) => ( - <> - - - - ), - onOk: () => { - metricStore.delete(widget).then(r => { - history.goBack(); - }).catch(() => { - toast.error('Failed to remove card'); - }); - }, - }) - } - }, - ]; - - const onClick: MenuProps['onClick'] = ({key}) => { - if (key === 'alert') { - message.info('Set Alerts'); - } else if (key === 'remove') { - Modal.confirm({ - title: 'Are you sure you want to remove this card?', - icon: null, - // content: 'Bla bla ...', - footer: (_, {OkBtn, CancelBtn}) => ( - <> - - - - ), - onOk: () => { - metricStore.delete(widget).then(r => { - history.goBack(); - }).catch(() => { - toast.error('Failed to remove card'); - }); - }, + const onClick: MenuProps['onClick'] = ({ key }) => { + if (key === 'alert') { + message.info('Set Alerts'); + } else if (key === 'remove') { + Modal.confirm({ + title: 'Are you sure you want to remove this card?', + icon: null, + // content: 'Bla bla ...', + footer: (_, { OkBtn, CancelBtn }) => ( + <> + + + + ), + onOk: () => { + metricStore + .delete(widget) + .then((r) => { + history.goBack(); }) - } - }; + .catch(() => { + toast.error('Failed to remove card'); + }); + }, + }); + } + }; - return ( -
- -
- ); + return ( +
+ +
+ ); }; -export default CardViewMenu; +export default observer(CardViewMenu); diff --git a/frontend/app/components/Dashboard/components/WidgetView/WidgetView.tsx b/frontend/app/components/Dashboard/components/WidgetView/WidgetView.tsx index ec6278a47..0b07145d3 100644 --- a/frontend/app/components/Dashboard/components/WidgetView/WidgetView.tsx +++ b/frontend/app/components/Dashboard/components/WidgetView/WidgetView.tsx @@ -3,7 +3,7 @@ import { useStore } from 'App/mstore'; import { Loader, NoContent } from 'UI'; import WidgetPreview from '../WidgetPreview'; import WidgetSessions from '../WidgetSessions'; -import { useObserver } from 'mobx-react-lite'; +import { observer } from 'mobx-react-lite'; import { dashboardMetricDetails, metricDetails, withSiteId } from 'App/routes'; import Breadcrumb from 'Shared/Breadcrumb'; import { FilterKey } from 'Types/filter/filterType'; @@ -16,7 +16,7 @@ import { FUNNEL, INSIGHTS, USER_PATH, - RETENTION + RETENTION, } from 'App/constants/card'; import CardUserList from '../CardUserList/CardUserList'; import WidgetViewHeader from 'Components/Dashboard/components/WidgetView/WidgetViewHeader'; @@ -34,16 +34,16 @@ interface Props { function WidgetView(props: Props) { const { match: { - params: { siteId, dashboardId, metricId } - } + params: { siteId, dashboardId, metricId }, + }, } = props; const { metricStore, dashboardStore } = useStore(); - const widget = useObserver(() => metricStore.instance); - const loading = useObserver(() => metricStore.isLoading); + const widget = metricStore.instance; + const loading = metricStore.isLoading; const [expanded, setExpanded] = useState(!metricId || metricId === 'create'); - const hasChanged = useObserver(() => widget.hasChanged); - const dashboards = useObserver(() => dashboardStore.dashboards); - const dashboard = useObserver(() => dashboards.find((d: any) => d.dashboardId == dashboardId)); + const hasChanged = widget.hasChanged; + const dashboards = dashboardStore.dashboards; + const dashboard = dashboards.find((d: any) => d.dashboardId == dashboardId); const dashboardName = dashboard ? dashboard.name : null; const [metricNotFound, setMetricNotFound] = useState(false); const history = useHistory(); @@ -83,24 +83,32 @@ function WidgetView(props: Props) { if (wasCreating) { if (parseInt(dashboardId, 10) > 0) { history.replace( - withSiteId(dashboardMetricDetails(dashboardId, savedMetric.metricId), siteId) + withSiteId( + dashboardMetricDetails(dashboardId, savedMetric.metricId), + siteId + ) ); void dashboardStore.addWidgetToDashboard( dashboardStore.getDashboard(parseInt(dashboardId, 10))!, [savedMetric.metricId] ); } else { - history.replace(withSiteId(metricDetails(savedMetric.metricId), siteId)); + history.replace( + withSiteId(metricDetails(savedMetric.metricId), siteId) + ); } } }; - return useObserver(() => ( + return ( { - if (location.pathname.includes('/metrics/') || location.pathname.includes('/metric/')) { + if ( + location.pathname.includes('/metrics/') || + location.pathname.includes('/metric/') + ) { return true; } return 'You have unsaved changes. Are you sure you want to leave?'; @@ -112,9 +120,11 @@ function WidgetView(props: Props) { items={[ { label: dashboardName ? dashboardName : 'Cards', - to: dashboardId ? withSiteId('/dashboard/' + dashboardId, siteId) : withSiteId('/metrics', siteId) + to: dashboardId + ? withSiteId('/dashboard/' + dashboardId, siteId) + : withSiteId('/metrics', siteId), }, - { label: widget.name } + { label: widget.name }, ]} /> - {widget.metricOf !== FilterKey.SESSIONS && widget.metricOf !== FilterKey.ERRORS && ( - (widget.metricType === TABLE - || widget.metricType === TIMESERIES - || widget.metricType === HEATMAP - || widget.metricType === INSIGHTS - || widget.metricType === FUNNEL - || widget.metricType === USER_PATH) ? - : null - )} + {widget.metricOf !== FilterKey.SESSIONS && + widget.metricOf !== FilterKey.ERRORS && + (widget.metricType === TABLE || + widget.metricType === TIMESERIES || + widget.metricType === HEATMAP || + widget.metricType === INSIGHTS || + widget.metricType === FUNNEL || + widget.metricType === USER_PATH ? ( + + ) : null)} {widget.metricType === RETENTION && }
- )); + ); } -export default WidgetView; +export default observer(WidgetView); diff --git a/frontend/app/mstore/metricStore.ts b/frontend/app/mstore/metricStore.ts index 670be040d..0b5868c1e 100644 --- a/frontend/app/mstore/metricStore.ts +++ b/frontend/app/mstore/metricStore.ts @@ -160,7 +160,17 @@ export default class MetricStore { } changeType(value: string) { - const obj: any = { metricType: value }; + const defaultData = { + sessionId: '', + sessions: [], + issues: [], + total: 0, + chart: [], + namesMap: {}, + avg: 0, + percentiles: [] + }; + const obj: any = { metricType: value, data: defaultData }; obj.series = this.instance.series; obj.series = obj.series.slice(0, 1); diff --git a/frontend/app/mstore/types/widget.ts b/frontend/app/mstore/types/widget.ts index 9a24b5399..0dd1a5a70 100644 --- a/frontend/app/mstore/types/widget.ts +++ b/frontend/app/mstore/types/widget.ts @@ -261,6 +261,7 @@ export default class Widget { } update(data: any) { + console.log(this.data, data.data) runInAction(() => { Object.assign(this, data); });