Skip to content

Commit

Permalink
fix: player meta links
Browse files Browse the repository at this point in the history
  • Loading branch information
pauldambra committed Dec 5, 2023
1 parent 9cc2c22 commit 40029b3
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 91 deletions.
108 changes: 48 additions & 60 deletions frontend/src/scenes/session-recordings/player/PlayerMeta.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { Link } from '@posthog/lemon-ui'
import clsx from 'clsx'
import { useValues } from 'kea'
import { CopyToClipboardInline } from 'lib/components/CopyToClipboard'
import { PropertyIcon } from 'lib/components/PropertyIcon'
import { TZLabel } from 'lib/components/TZLabel'
import { dayjs } from 'lib/dayjs'
import { useResizeBreakpoints } from 'lib/hooks/useResizeObserver'
Expand All @@ -17,6 +16,7 @@ import { asDisplay } from 'scenes/persons/person-utils'
import { PersonDisplay } from 'scenes/persons/PersonDisplay'
import { IconWindow } from 'scenes/session-recordings/player/icons'
import { playerMetaLogic } from 'scenes/session-recordings/player/playerMetaLogic'
import { gatherIconProperties, PropertyIcons } from 'scenes/session-recordings/playlist/SessionRecordingPreview'
import { urls } from 'scenes/urls'

import { getCurrentExporterData } from '~/exporter/exporterViewLogic'
Expand All @@ -30,49 +30,55 @@ function SessionPropertyMeta(props: {
iconProperties: Record<string, any>
predicate: (x: string) => boolean
}): JSX.Element {
const gatheredProperties = gatherIconProperties(props.iconProperties)

return (
<div className="flex flex-row flex-nowrap shrink-0 gap-2 text-muted-alt">
<span className="flex items-center gap-1 whitespace-nowrap">
<PropertyIcon
noTooltip={!props.fullScreen}
property="$browser"
value={props.iconProperties['$browser']}
/>
{!props.fullScreen ? props.iconProperties['$browser'] : null}
</span>
<span className="flex items-center gap-1 whitespace-nowrap">
<PropertyIcon
noTooltip={!props.fullScreen}
property="$device_type"
value={props.iconProperties['$device_type'] || props.iconProperties['$initial_device_type']}
/>
{!props.fullScreen
? props.iconProperties['$device_type'] || props.iconProperties['$initial_device_type']
: null}
</span>
<span className="flex items-center gap-1 whitespace-nowrap">
<PropertyIcon noTooltip={!props.fullScreen} property="$os" value={props.iconProperties['$os']} />
{!props.fullScreen ? props.iconProperties['$os'] : null}
</span>
{props.iconProperties['$geoip_country_code'] && (
<span className="flex items-center gap-1 whitespace-nowrap">
<PropertyIcon
noTooltip={!props.fullScreen}
property="$geoip_country_code"
value={props.iconProperties['$geoip_country_code']}
<PropertyIcons
recordingProperties={gatheredProperties}
iconClassnames={'text-muted-alt'}
showTooltip={false}
showLabel={(key) => (props.fullScreen ? key === '$geoip_country_code' : key !== '$geoip_country_code')}
/>
)
}

function URLOrScreen({ lastUrl }: { lastUrl: string | undefined }): JSX.Element | null {
if (!lastUrl) {
return null
}

// re-using the rrweb web schema means that this might be a mobile replay screen name
let isValidUrl = false
try {
new URL(lastUrl || '')
isValidUrl = true
} catch (_e) {
// no valid url
}

return (
<span className="flex items-center gap-2 truncate">
<span>·</span>
<span className="flex items-center gap-1 truncate">
{isValidUrl ? (
<Tooltip title="Click to open url">
<Link to={lastUrl} target="_blank" className="truncate">
{lastUrl}
</Link>
</Tooltip>
) : (
lastUrl
)}
<span className="flex items-center">
<CopyToClipboardInline
description={lastUrl}
explicitValue={lastUrl}
iconStyle={{ color: 'var(--muted-alt)' }}
selectable={true}
/>
{
props.fullScreen &&
[
props.iconProperties['$geoip_city_name'],
props.iconProperties['$geoip_subdivision_1_code'],
]
.filter(props.predicate)
.join(', ') /* [city, state] */
}
</span>
)}
</div>
</span>
</span>
)
}

Expand Down Expand Up @@ -224,25 +230,7 @@ export function PlayerMeta(): JSX.Element {
<IconWindow value={currentWindowIndex + 1} className="text-muted-alt" />
</Tooltip>

{lastUrl && (
<span className="flex items-center gap-2 truncate">
<span>·</span>
<span className="flex items-center gap-1 truncate">
<Tooltip title="Click to open url">
<Link to={lastUrl} target="_blank" className="truncate">
{lastUrl}
</Link>
</Tooltip>
<span className="flex items-center">
<CopyToClipboardInline
description="current url"
explicitValue={lastUrl}
iconStyle={{ color: 'var(--muted-alt)' }}
/>
</span>
</span>
</span>
)}
<URLOrScreen lastUrl={lastUrl} />
{lastPageviewEvent?.properties?.['$screen_name'] && (
<span className="flex items-center gap-2 truncate">
<span>·</span>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,79 +58,92 @@ function RecordingDuration({
interface GatheredProperty {
property: string
value: string | undefined
label: string | undefined
tooltipValue: string
}

const browserIconPropertyKeys = ['$geoip_country_code', '$browser', '$device_type', '$os']
const mobileIconPropertyKeys = ['$geoip_country_code', '$device_type', '$os_name']

function gatherIconProperties(
export function gatherIconProperties(
recordingProperties: Record<string, any> | undefined,
recording: SessionRecordingType
recording?: SessionRecordingType
): GatheredProperty[] {
const iconProperties =
recordingProperties && Object.keys(recordingProperties).length > 0
? recordingProperties
: recording.person?.properties || {}
: recording?.person?.properties || {}

const deviceType = iconProperties['$device_type'] || iconProperties['$initial_device_type']
const iconPropertyKeys = deviceType === 'Mobile' ? mobileIconPropertyKeys : browserIconPropertyKeys

return iconPropertyKeys.map((property) => {
return iconPropertyKeys.flatMap((property) => {
let value = iconProperties?.[property]
let label = value
if (property === '$device_type') {
value = iconProperties?.['$device_type'] || iconProperties?.['$initial_device_type']
}

let tooltipValue = value
if (property === '$geoip_country_code') {
tooltipValue = `${iconProperties?.['$geoip_country_name']} (${value})`
label = [iconProperties?.['$geoip_city_name'], iconProperties?.['$geoip_subdivision_1_code']]
.filter(Boolean)
.join(', ')
}
return { property, value, tooltipValue }
return { property, value, tooltipValue, label }
})
}

export interface PropertyIconsProps {
recordingProperties: GatheredProperty[]
loading: boolean
loading?: boolean
onPropertyClick?: (property: string, value?: string) => void
iconClassnames: string
iconClassnames?: string
showTooltip?: boolean
showLabel?: (key: string) => boolean
}

export function PropertyIcons({
recordingProperties,
loading,
onPropertyClick,
iconClassnames,
showTooltip = true,
showLabel = undefined,
}: PropertyIconsProps): JSX.Element {
return (
<div className="flex flex-row flex-nowrap shrink-0 gap-1 h-6 ph-no-capture">
{!loading ? (
recordingProperties.map(({ property, value, tooltipValue }) => {
<div className="flex flex-row flex-nowrap shrink-0 gap-1 h-6 ph-no-capture items-center">
{loading ? (
<LemonSkeleton className="w-18 h-4 my-1" />
) : (
recordingProperties.map(({ property, value, tooltipValue, label }) => {
return (
<PropertyIcon
key={property}
onClick={(e) => {
if (e.altKey) {
e.stopPropagation()
onPropertyClick?.(property, value)
}
}}
className={iconClassnames}
property={property}
value={value}
tooltipTitle={() => (
<div className="text-center">
<code>Alt + Click</code> to filter for
<br />
<span className="font-medium">{tooltipValue ?? 'N/A'}</span>
</div>
)}
/>
<>
<PropertyIcon
key={property}
onClick={(e) => {
if (e.altKey) {
e.stopPropagation()
onPropertyClick?.(property, value)
}
}}
className={iconClassnames}
property={property}
value={value}
noTooltip={!showTooltip}
tooltipTitle={() => (
<div className="text-center">
<code>Alt + Click</code> to filter for
<br />
<span className="font-medium">{tooltipValue ?? 'N/A'}</span>
</div>
)}
/>
{showLabel?.(property) && <span className="text-xs text-muted-alt">{label || value}</span>}
</>
)
})
) : (
<LemonSkeleton className="w-18 h-4 my-1" />
)}
</div>
)
Expand Down

0 comments on commit 40029b3

Please sign in to comment.