import { Segmented } from 'antd'; import {InfoCircleOutlined} from '@ant-design/icons' import cn from 'classnames'; import { observer } from 'mobx-react-lite'; import React, { useEffect } from 'react'; import { MobilePlayerContext, PlayerContext, } from 'App/components/Session/playerContext'; import { useStore } from 'App/mstore'; import SummaryBlock from 'Components/Session/Player/ReplayPlayer/SummaryBlock'; import { SummaryButton } from 'Components/Session_/Player/Controls/Controls'; import TimelineZoomButton from 'Components/Session_/Player/Controls/components/TimelineZoomButton'; import { Icon, NoContent } from 'UI'; import TabSelector from "../../shared/DevTools/TabSelector"; import BottomBlock from '../BottomBlock'; import EventRow from './components/EventRow'; import FeatureSelection, { HELP_MESSAGE, } from './components/FeatureSelection/FeatureSelection'; import OverviewPanelContainer from './components/OverviewPanelContainer'; import TimelinePointer from './components/TimelinePointer'; import TimelineScale from './components/TimelineScale'; import VerticalPointerLine, { VerticalPointerLineComp } from './components/VerticalPointerLine'; function MobileOverviewPanelCont() { const { aiSummaryStore, uiPlayerStore, sessionStore } = useStore(); const sessionId = sessionStore.current.sessionId; const issuesList = sessionStore.current.issues; const zoomEnabled = uiPlayerStore.timelineZoom.enabled; const zoomStartTs = uiPlayerStore.timelineZoom.startTs; const zoomEndTs = uiPlayerStore.timelineZoom.endTs; const setZoomTab = uiPlayerStore.setZoomTab; const zoomTab = uiPlayerStore.zoomTab; const { store, player } = React.useContext(MobilePlayerContext); const [dataLoaded, setDataLoaded] = React.useState(false); const [selectedFeatures, setSelectedFeatures] = React.useState([ 'PERFORMANCE', 'FRUSTRATIONS', 'ERRORS', 'NETWORK', ]); const { endTime, eventList: eventsList, frustrationsList, exceptionsList, fetchList, performanceChartData, performanceList, } = store.get(); const fetchPresented = fetchList.length > 0; const checkInZoomRange = (list: any[]) => { return list.filter((i) => zoomEnabled ? i.time >= zoomStartTs && i.time <= zoomEndTs : true ); }; const resources = { NETWORK: checkInZoomRange( fetchList.filter((r: any) => r.status >= 400 || r.isRed || r.isYellow) ), ERRORS: checkInZoomRange(exceptionsList), EVENTS: checkInZoomRange(eventsList), PERFORMANCE: checkInZoomRange(performanceChartData), FRUSTRATIONS: checkInZoomRange(frustrationsList), }; useEffect(() => { if (dataLoaded) { return; } if ( exceptionsList.length > 0 || eventsList.length > 0 || issuesList.length > 0 || performanceChartData.length > 0 || frustrationsList.length > 0 ) { setDataLoaded(true); } }, [ issuesList, exceptionsList, eventsList, performanceChartData, frustrationsList, ]); React.useEffect(() => { player.scale(); }, [selectedFeatures]); const originStr = window.env.ORIGIN || window.location.origin; const isSaas = /app\.openreplay\.com/.test(originStr); return ( aiSummaryStore.setToggleSummary(!aiSummaryStore.toggleSummary) } summaryChecked={aiSummaryStore.toggleSummary} setZoomTab={setZoomTab} zoomTab={zoomTab} /> ); } function WebOverviewPanelCont() { const { aiSummaryStore, uiPlayerStore, sessionStore } = useStore(); const sessionId = sessionStore.current.sessionId; const zoomEnabled = uiPlayerStore.timelineZoom.enabled; const zoomStartTs = uiPlayerStore.timelineZoom.startTs; const zoomEndTs = uiPlayerStore.timelineZoom.endTs; const setZoomTab = uiPlayerStore.setZoomTab; const zoomTab = uiPlayerStore.zoomTab; const { store } = React.useContext(PlayerContext); const [selectedFeatures, setSelectedFeatures] = React.useState([ 'PERFORMANCE', 'FRUSTRATIONS', 'ERRORS', 'NETWORK', ]); const { endTime, currentTab, tabStates } = store.get(); const tabValues = Object.values(tabStates); const dataSource = uiPlayerStore.dataSource; const showSingleTab = dataSource === 'current'; const { stackEventList = [], frustrationsList = [], exceptionsList = [], resourceListUnmap = [], fetchList = [], graphqlList = [], performanceChartData = [], } = React.useMemo(() => { if (showSingleTab) { const stackEventList = tabStates[currentTab].stackList; const frustrationsList = tabStates[currentTab].frustrationsList; const exceptionsList = tabStates[currentTab].exceptionsList; const resourceListUnmap = tabStates[currentTab].resourceList; const fetchList = tabStates[currentTab].fetchList; const graphqlList = tabStates[currentTab].graphqlList; const performanceChartData = tabStates[currentTab].performanceChartData; return { stackEventList, frustrationsList, exceptionsList, resourceListUnmap, fetchList, graphqlList, performanceChartData, } } else { const stackEventList = tabValues.flatMap((tab) => tab.stackList); // these two are global const frustrationsList = tabValues[0].frustrationsList; const exceptionsList = tabValues[0].exceptionsList; // we can't compute global chart data because some tabs coexist const performanceChartData: any = []; const resourceListUnmap = tabValues.flatMap((tab) => tab.resourceList); const fetchList = tabValues.flatMap((tab) => tab.fetchList); const graphqlList = tabValues.flatMap((tab) => tab.graphqlList); return { stackEventList, frustrationsList, exceptionsList, resourceListUnmap, fetchList, graphqlList, performanceChartData, } } }, [tabStates, currentTab, dataSource, tabValues]); const fetchPresented = fetchList.length > 0; const resourceList = resourceListUnmap .filter((r: any) => r.isRed || r.isYellow) // @ts-ignore .concat(fetchList.filter((i: any) => parseInt(i.status) >= 400)) // @ts-ignore .concat(graphqlList.filter((i: any) => parseInt(i.status) >= 400)) .filter((i: any) => i.type === 'fetch'); const checkInZoomRange = (list: any[]) => { return list.filter((i) => zoomEnabled ? i.time >= zoomStartTs && i.time <= zoomEndTs : true ); }; const resources: any = React.useMemo(() => { return { NETWORK: checkInZoomRange(resourceList), ERRORS: checkInZoomRange(exceptionsList), EVENTS: checkInZoomRange(stackEventList), PERFORMANCE: checkInZoomRange(performanceChartData), FRUSTRATIONS: checkInZoomRange(frustrationsList), }; }, [ tabStates, currentTab, zoomEnabled, zoomStartTs, zoomEndTs, resourceList.length, exceptionsList.length, stackEventList.length, performanceChartData.length, frustrationsList.length, ]); const originStr = window.env.ORIGIN || window.location.origin; const isSaas = /app\.openreplay\.com/.test(originStr); return ( aiSummaryStore.setToggleSummary(!aiSummaryStore.toggleSummary) } summaryChecked={aiSummaryStore.toggleSummary} sessionId={sessionId} setZoomTab={setZoomTab} zoomTab={zoomTab} showSingleTab={showSingleTab} /> ); } export function SpotOverviewPanelCont({ resourceList, exceptionsList, spotTime, spotEndTime, onClose, }: any) { const selectedFeatures = ['ERRORS', 'NETWORK']; const fetchPresented = false; // TODO const endTime = 0; // TODO const resources = { NETWORK: resourceList, ERRORS: exceptionsList, }; return ( ); } function PanelComponent({ selectedFeatures, endTime, resources, fetchPresented, setSelectedFeatures, isMobile, performanceList, showSummary, toggleSummary, summaryChecked, sessionId, zoomTab, setZoomTab, isSpot, spotTime, spotEndTime, onClose, showSingleTab, }: any) { return (
X-Ray {showSummary ? ( <> {summaryChecked ? ( setZoomTab(val)} options={[ { label: 'Overview', value: 'overview', }, { label: 'User journey', value: 'journey', }, { label: 'Issues', value: 'issues', }, { label: 'Suggestions', value: 'errors', }, ]} /> ) : null} ) : null}
{isSpot ? null : (
{!isMobile ? : null}
)}
{summaryChecked ? : null}
Select a debug option to visualize on timeline.
} > {isSpot ? ( ) : ( )} {selectedFeatures.map((feature: any, index: number) => (
( )} endTime={isSpot ? spotEndTime : endTime} message={HELP_MESSAGE[feature]} /> {isMobile && feature === 'PERFORMANCE' ? (
(
)} endTime={endTime} />
) : null}
))}
); } export const OverviewPanel = observer(WebOverviewPanelCont); export const MobileOverviewPanel = observer(MobileOverviewPanelCont);