* feat tracker: add document titles to tabs * feat: titles for tabs * feat tracker: send initial title, parse titles better * feat ui: tab name styles * feat tracker: update changelogs * fix tracker: fix tests * fix tracker: fix failing tests, add some coverage * fix tracker: fix failing tests, add some coverage * Heatmaps (#2264) * feat ui: start heatmaps ui and tracker update * fix ui: drop clickmap from session * fix ui: refactor heatmap painter * fix ui: store click coords as int percent * feat(backend): insert normalized x and y to PG * feat(backend): insert normalized x and y to CH * feat(connector): added missing import * feat(backend): fixed different uint type issue * fix tracker: use max scrollable size for doc * fix gen files * fix ui: fix random crash, remove demo data generator * fix ui: rm some dead code --------- Co-authored-by: Alexander <zavorotynskiy@pm.me> * fix tracker: add heatmap changelog to tracker CHANGELOG.md * fix tracker: fix peerjs version to 1.5.4 (was 1.5.1) * fix document height calculation * Crossdomain tracking (#2277) * feat tracker: crossdomain tracking (start commit) * catch crossdomain messages, add nodeid placeholder * click scroll * frame placeholder number -> dynamic * click rewriter, fix scroll prop * some docs * some docs * fix options merging * CHANGELOG.md update * checking that crossdomain will not fire automatically * simplify func declaration * update test data * change clickmap document height calculation to scrollheight (which should be true height) --------- Co-authored-by: Alexander <zavorotynskiy@pm.me>
90 lines
3.3 KiB
TypeScript
90 lines
3.3 KiB
TypeScript
import React from 'react'
|
|
import { useStore } from 'App/mstore'
|
|
import { observer } from 'mobx-react-lite'
|
|
import ClickMapRenderer from 'App/components/Session/Player/ClickMapRenderer'
|
|
import { connect } from 'react-redux'
|
|
import { fetchInsights } from 'App/duck/sessions'
|
|
import { NoContent, Icon } from 'App/components/ui'
|
|
|
|
function ClickMapCard({
|
|
insights,
|
|
fetchInsights,
|
|
insightsFilters,
|
|
}: any) {
|
|
const [customSession, setCustomSession] = React.useState<any>(null)
|
|
const { metricStore, dashboardStore } = useStore();
|
|
const onMarkerClick = (s: string, innerText: string) => {
|
|
metricStore.changeClickMapSearch(s, innerText)
|
|
}
|
|
const mapUrl = metricStore.instance.series[0].filter.filters[0].value[0]
|
|
|
|
React.useEffect(() => {
|
|
return () => setCustomSession(null)
|
|
}, [])
|
|
|
|
React.useEffect(() => {
|
|
if (metricStore.instance.data.domURL) {
|
|
setCustomSession(null)
|
|
setTimeout(() => {
|
|
setCustomSession(metricStore.instance.data)
|
|
}, 100)
|
|
}
|
|
}, [metricStore.instance])
|
|
|
|
React.useEffect(() => {
|
|
const rangeValue = dashboardStore.drillDownPeriod.rangeValue
|
|
const startDate = dashboardStore.drillDownPeriod.start
|
|
const endDate = dashboardStore.drillDownPeriod.end
|
|
fetchInsights({ ...insightsFilters, url: mapUrl || '/', startDate, endDate, rangeValue, clickRage: metricStore.clickMapFilter })
|
|
}, [dashboardStore.drillDownPeriod.start, dashboardStore.drillDownPeriod.end, dashboardStore.drillDownPeriod.rangeValue, metricStore.clickMapFilter])
|
|
|
|
if (!metricStore.instance.data.domURL || insights.size === 0) {
|
|
return (
|
|
<NoContent
|
|
style={{ minHeight: 220 }}
|
|
title={
|
|
<div className="flex items-center relative">
|
|
<Icon name="info-circle" className="mr-2" size="18" />
|
|
No data for selected period or URL
|
|
<div style={{ position: 'absolute', right: -240, top: -110 }}>
|
|
<Icon name="pointer-sessions-search" size={250} width={240} />
|
|
</div>
|
|
</div>
|
|
}
|
|
show={true}
|
|
/>
|
|
)
|
|
}
|
|
|
|
if (!metricStore.instance.data || !customSession) {
|
|
return <div className="py-2">Loading session</div>
|
|
}
|
|
|
|
const jumpToEvent = metricStore.instance.data.events.find((evt: Record<string, any>) => {
|
|
if (mapUrl) return evt.path.includes(mapUrl)
|
|
return evt
|
|
}) || { timestamp: metricStore.instance.data.startTs }
|
|
|
|
const jumpTimestamp = (jumpToEvent.timestamp - metricStore.instance.data.startTs) + jumpToEvent.domBuildingTime + 99 // 99ms safety margin to give some time for the DOM to load
|
|
|
|
return (
|
|
<div id="clickmap-render">
|
|
<ClickMapRenderer
|
|
session={customSession}
|
|
jumpTimestamp={jumpTimestamp}
|
|
onMarkerClick={onMarkerClick}
|
|
/>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export default connect(
|
|
(state: any) => ({
|
|
insightsFilters: state.getIn(['sessions', 'insightFilters']),
|
|
visitedEvents: state.getIn(['sessions', 'visitedEvents']),
|
|
insights: state.getIn(['sessions', 'insights']),
|
|
host: state.getIn(['sessions', 'host']),
|
|
}),
|
|
{ fetchInsights, }
|
|
)
|
|
(observer(ClickMapCard))
|