From 1bcb0dfc0198b903805d14c1e1483718e0e2ff71 Mon Sep 17 00:00:00 2001 From: Shekar Siri Date: Mon, 20 Jun 2022 12:02:28 +0200 Subject: [PATCH] feat(ui) - funnels more steps --- .../Errors/ErrorListItem/ErrorListItem.tsx | 21 +++-- .../Funnels/FunnelIssues/FunnelIssues.tsx | 20 +---- .../FunnelIssuesDropdown.tsx | 35 ++++++-- .../FunnelIssuesList/FunnelIssuesList.tsx | 19 ++++- .../components/WidgetChart/WidgetChart.tsx | 5 +- .../components/WidgetForm/WidgetForm.tsx | 2 +- .../WidgetPreview/WidgetPreview.tsx | 15 +++- .../WidgetSessions/WidgetSessions.tsx | 62 +++++++------- .../components/WidgetView/WidgetView.tsx | 4 +- .../Funnels/FunnelWidget/FunnelWidget.tsx | 83 +++++++++++++++---- frontend/app/mstore/dashboardStore.ts | 15 +++- frontend/app/mstore/metricStore.ts | 15 ++-- frontend/app/mstore/types/widget.ts | 19 ++++- frontend/app/types/app/period.js | 8 ++ 14 files changed, 212 insertions(+), 111 deletions(-) diff --git a/frontend/app/components/Dashboard/components/Errors/ErrorListItem/ErrorListItem.tsx b/frontend/app/components/Dashboard/components/Errors/ErrorListItem/ErrorListItem.tsx index 95ce3f021..8ce3e8fad 100644 --- a/frontend/app/components/Dashboard/components/Errors/ErrorListItem/ErrorListItem.tsx +++ b/frontend/app/components/Dashboard/components/Errors/ErrorListItem/ErrorListItem.tsx @@ -18,10 +18,10 @@ function ErrorListItem(props: Props) { const { error, className = '' } = props; return (
-
+
- - - - } /> - - +
+ + + + } /> + + +
); diff --git a/frontend/app/components/Dashboard/components/Funnels/FunnelIssues/FunnelIssues.tsx b/frontend/app/components/Dashboard/components/Funnels/FunnelIssues/FunnelIssues.tsx index e053f2562..bbc2aab7e 100644 --- a/frontend/app/components/Dashboard/components/Funnels/FunnelIssues/FunnelIssues.tsx +++ b/frontend/app/components/Dashboard/components/Funnels/FunnelIssues/FunnelIssues.tsx @@ -1,24 +1,19 @@ import React, { useEffect, useState } from 'react'; import { useStore } from 'App/mstore'; import { useObserver } from 'mobx-react-lite'; -import { NoContent, Loader } from 'UI'; +import { Loader } from 'UI'; import FunnelIssuesDropdown from '../FunnelIssuesDropdown'; import FunnelIssuesSort from '../FunnelIssuesSort'; import FunnelIssuesList from '../FunnelIssuesList'; import { DateTime } from 'luxon'; import { debounce } from 'App/utils'; import useIsMounted from 'App/hooks/useIsMounted'; -import AnimatedSVG, { ICONS } from 'Shared/AnimatedSVG/AnimatedSVG'; function FunnelIssues() { const { metricStore, dashboardStore } = useStore(); const [data, setData] = useState({ issues: [] }); const [loading, setLoading] = useState(false); const isMounted = useIsMounted() - // const funnel = useObserver(() => funnelStore.instance); - // const funnel = useObserver(() => metricStore.instance); - // const issues = useObserver(() => funnelStore.issues); - // const loading = useObserver(() => funnelStore.isLoadingIssues); const fetchIssues = (filter: any) => { if (!isMounted()) return; @@ -35,7 +30,6 @@ function FunnelIssues() { const startTime = DateTime.fromMillis(filter.startTimestamp).toFormat('LLL dd, yyyy HH:mm a'); const endTime = DateTime.fromMillis(filter.endTimestamp).toFormat('LLL dd, yyyy HH:mm a'); const debounceRequest: any = React.useCallback(debounce(fetchIssues, 1000), []); - const depsString = JSON.stringify(widget.series); useEffect(() => { @@ -54,17 +48,7 @@ function FunnelIssues() {
- - -
No issues found
- - } - > - -
+
)); diff --git a/frontend/app/components/Dashboard/components/Funnels/FunnelIssuesDropdown/FunnelIssuesDropdown.tsx b/frontend/app/components/Dashboard/components/Funnels/FunnelIssuesDropdown/FunnelIssuesDropdown.tsx index 547e896ed..361337443 100644 --- a/frontend/app/components/Dashboard/components/Funnels/FunnelIssuesDropdown/FunnelIssuesDropdown.tsx +++ b/frontend/app/components/Dashboard/components/Funnels/FunnelIssuesDropdown/FunnelIssuesDropdown.tsx @@ -1,9 +1,10 @@ -import React, { Component, ReactNode, FunctionComponent, useEffect } from 'react'; +import React, { useEffect } from 'react'; import Select from 'Shared/Select' import { components } from 'react-select'; import { Icon } from 'UI'; import FunnelIssuesSelectedFilters from '../FunnelIssuesSelectedFilters'; import { useStore } from 'App/mstore'; +import OutsideClickDetectingDiv from 'Shared/OutsideClickDetectingDiv'; const options = [ { value: "click_rage", label: "Click Rage" }, @@ -20,7 +21,7 @@ const options = [ { value: "js_error", label: "Error" } ] -function FunnelIssuesDropdown(props) { +function FunnelIssuesDropdown() { const { funnelStore } = useStore(); const [isOpen, setIsOpen] = React.useState(false); const [selectedValues, setSelectedValues] = React.useState([]); @@ -48,12 +49,20 @@ function FunnelIssuesDropdown(props) { } } + const onClickOutside = () => { + if (isOpen) { + setTimeout(() => { + setIsOpen(false); + }, 0); + } + } + return (
dashboardStore.period); const metric: any = useObserver(() => metricStore.instance); const isTimeSeries = metric.metricType === 'timeseries'; const isTable = metric.metricType === 'table'; + // const drillDownFilter = useObserver(() => dashboardStore.drillDownFilter); const disableVisualization = useObserver(() => metric.metricOf === FilterKey.SESSIONS || metric.metricOf === FilterKey.ERRORS); + const period = useObserver(() => dashboardStore.drillDownPeriod); const chagneViewType = (e, { name, value }: any) => { metric.update({ [ name ]: value }); } + const onChangePeriod = (period: any) => { + dashboardStore.setDrillDownPeriod(period); + } + return useObserver(() => (
@@ -39,8 +45,8 @@ function WidgetPreview(props: Props) { onSelect={ chagneViewType } value={{ value: metric.viewType }} list={ [ - { value: 'lineChart', name: 'Chart', icon: 'graph-up-arrow' }, - { value: 'progress', name: 'Progress', icon: 'hash' }, + { value: 'lineChart', name: 'Chart', icon: 'graph-up-arrow' }, + { value: 'progress', name: 'Progress', icon: 'hash' }, ]} /> @@ -69,7 +75,8 @@ function WidgetPreview(props: Props) { Time Range dashboardStore.setPeriod(period)} + // onChange={(period: any) => metric.setPeriod(period)} + onChange={onChangePeriod} right={true} />
diff --git a/frontend/app/components/Dashboard/components/WidgetSessions/WidgetSessions.tsx b/frontend/app/components/Dashboard/components/WidgetSessions/WidgetSessions.tsx index 09adadc36..411bdab4a 100644 --- a/frontend/app/components/Dashboard/components/WidgetSessions/WidgetSessions.tsx +++ b/frontend/app/components/Dashboard/components/WidgetSessions/WidgetSessions.tsx @@ -1,5 +1,5 @@ import React, { useEffect, useState } from 'react'; -import { NoContent, Dropdown, Icon, Loader, Pagination } from 'UI'; +import { NoContent, Loader, Pagination } from 'UI'; import Select from 'Shared/Select'; import cn from 'classnames'; import { useStore } from 'App/mstore'; @@ -15,19 +15,29 @@ interface Props { } function WidgetSessions(props: Props) { const { className = '' } = props; + const [activeSeries, setActiveSeries] = useState('all'); const [data, setData] = useState([]); - const isMounted = useIsMounted() + const isMounted = useIsMounted(); const [loading, setLoading] = useState(false); + const filteredSessions = getListSessionsBySeries(data, activeSeries); + const { dashboardStore, metricStore } = useStore(); + const filter = useObserver(() => dashboardStore.drillDownFilter); + const widget: any = useObserver(() => metricStore.instance); + const drillDownPeriod = useObserver(() => dashboardStore.drillDownPeriod); + const startTime = DateTime.fromMillis(filter.startTimestamp).toFormat('LLL dd, yyyy HH:mm a'); + const endTime = DateTime.fromMillis(filter.endTimestamp).toFormat('LLL dd, yyyy HH:mm a'); + const [timestamps, setTimestamps] = useState({ + startTimestamp: 0, + endTimestamp: 0, + }); const [seriesOptions, setSeriesOptions] = useState([ { label: 'All', value: 'all' }, ]); - const [activeSeries, setActiveSeries] = useState('all'); - - const writeOption = (e, { name, value }) => setActiveSeries(value.value); + const writeOption = ({ value }: any) => setActiveSeries(value.value); useEffect(() => { if (!data) return; - const seriesOptions = data.map(item => ({ + const seriesOptions = data.map((item: any) => ({ label: item.seriesName, value: item.seriesId, })); @@ -37,22 +47,15 @@ function WidgetSessions(props: Props) { ]); }, [data]); - const fetchSessions = (metricId, filter) => { + const fetchSessions = (metricId: any, filter: any) => { if (!isMounted()) return; setLoading(true) - widget.fetchSessions(metricId, filter).then(res => { + widget.fetchSessions(metricId, filter).then((res: any) => { setData(res) }).finally(() => { setLoading(false) }); } - - const filteredSessions = getListSessionsBySeries(data, activeSeries); - const { dashboardStore, metricStore } = useStore(); - const filter = useObserver(() => dashboardStore.drillDownFilter); - const widget: any = useObserver(() => metricStore.instance); - const startTime = DateTime.fromMillis(filter.startTimestamp).toFormat('LLL dd, yyyy HH:mm a'); - const endTime = DateTime.fromMillis(filter.endTimestamp).toFormat('LLL dd, yyyy HH:mm a'); const debounceRequest: any = React.useCallback(debounce(fetchSessions, 1000), []); const depsString = JSON.stringify(widget.series); @@ -60,6 +63,12 @@ function WidgetSessions(props: Props) { debounceRequest(widget.metricId, { ...filter, series: widget.toJsonDrilldown(), page: metricStore.sessionsPage, limit: metricStore.sessionsPageSize }); }, [filter.startTimestamp, filter.endTimestamp, filter.filters, depsString, metricStore.sessionsPage]); + useEffect(() => { + const timestamps = drillDownPeriod.toTimestamps(); + console.log('timestamps', timestamps); + debounceRequest(widget.metricId, { startTime: timestamps.startTimestamp, endTime: timestamps.endTimestamp, series: widget.toJsonDrilldown(), page: metricStore.sessionsPage, limit: metricStore.sessionsPageSize }); + }, [drillDownPeriod]); + return useObserver(() => (
@@ -71,18 +80,6 @@ function WidgetSessions(props: Props) { { widget.metricType !== 'table' && (
Series - {/* } - /> */}