import { observer } from 'mobx-react-lite'; import React from 'react'; import { connect } from 'react-redux'; import { useStore } from 'App/mstore'; import { debounce } from 'App/utils'; import { IResourceRequest, IResourceTiming } from "../../../../../player"; import { WsChannel } from "../../../../../player/web/messages"; import { PlayerContext } from "../../../playerContext"; let debounceUpdate: any = () => {}; const userBehaviorRegex = /User\s+(\w+\s+)?Behavior/i; const issuesErrorsRegex = /Issues\s+(and\s+|,?\s+)?(\w+\s+)?Errors/i; function isTitleLine(line: string): boolean { return userBehaviorRegex.test(line) || issuesErrorsRegex.test(line); } function SummaryBlock({ sessionId, zoomEnabled, zoomStartTs, zoomEndTs, zoomTab, duration, }: { sessionId: string; zoomEnabled: boolean; zoomStartTs: number; zoomEndTs: number; zoomTab: 'overview' | 'journey' | 'issues' | 'errors'; duration: any; }) { const { store } = React.useContext(PlayerContext) const { tabStates } = store.get(); const { aiSummaryStore } = useStore(); React.useEffect(() => { debounceUpdate = debounce( ( sessionId: string, events: any[], feat: 'journey' | 'issues' | 'errors', startTs: number, endTs: number ) => aiSummaryStore.getDetailedSummary(sessionId, events, feat, startTs, endTs), 500 ); }, []); React.useEffect(() => { if (zoomTab === 'overview') { void aiSummaryStore.getSummary(sessionId); } else { const totalFetchList: IResourceRequest[] = []; const totalResourceList: IResourceTiming[] = []; const totalWebsocketList: WsChannel[] = []; Object.values(tabStates).forEach(({ fetchList, resourceList, websocketList, }) => { totalFetchList.push(...fetchList); totalResourceList.push(...resourceList); totalWebsocketList.push(...websocketList); }) const resultingEvents = [ ...totalFetchList, ...totalResourceList, ...totalWebsocketList, ] const range = !zoomEnabled ? [0, duration] : [zoomStartTs, zoomEndTs]; void debounceUpdate(sessionId, resultingEvents, zoomTab, range[0], range[1]); } }, [zoomTab]); const formattedText = aiSummaryStore.text.split('\n').map((line) => { if (isTitleLine(line)) { return
{line}
; } if (line.startsWith('*')) { return (
  • ); } return (
    ); }); return (
    {aiSummaryStore.text ? (
    <>{formattedText.map((v) => v)}
    ) : ( )}
    ); } function TextPlaceholder() { return (
    ); } const CodeStringFormatter = ({ text }: { text: string }) => { const parts = text.split(/(`[^`]*`)/).map((part, index) => part.startsWith('`') && part.endsWith('`') ? (
    {part.substring(1, part.length - 1)}
    ) : ( {part} ) ); return <>{parts}; }; const summaryBlockStyle: React.CSSProperties = { background: 'linear-gradient(180deg, #E8EBFF -24.14%, rgba(236, 254, 255, 0.00) 100%)', width: '100%', maxHeight: '25vh', overflow: 'auto', display: 'flex', flexDirection: 'column', gap: '0.5rem', padding: '1rem', }; export default connect((state: Record) => ({ zoomEnabled: state.getIn(['components', 'player']).timelineZoom.enabled, zoomStartTs: state.getIn(['components', 'player']).timelineZoom.startTs, zoomEndTs: state.getIn(['components', 'player']).timelineZoom.endTs, zoomTab: state.getIn(['components', 'player']).zoomTab, duration: state.getIn(['sessions', 'current']).durationSeconds, }))(observer(SummaryBlock));