Skip to content

Commit

Permalink
feat: add replay to omnisearch (PostHog#24978)
Browse files Browse the repository at this point in the history
  • Loading branch information
pauldambra authored Sep 15, 2024
1 parent e46f90d commit ac44668
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ import posthog from 'posthog-js'
import { newDashboardLogic } from 'scenes/dashboard/newDashboardLogic'
import { insightTypeURL } from 'scenes/insights/utils'
import { preflightLogic } from 'scenes/PreflightCheck/preflightLogic'
import { WATCH_RECORDINGS_OF_KEY, watchRecordingsOfCommand } from 'scenes/session-recordings/replayPaletteCommands'
import { teamLogic } from 'scenes/teamLogic'
import { urls } from 'scenes/urls'
import { userLogic } from 'scenes/userLogic'
Expand Down Expand Up @@ -119,7 +120,7 @@ export type RegExpCommandPairs = [RegExp | null, Command][]

const RESULTS_MAX = 5

const GLOBAL_COMMAND_SCOPE = 'global'
export const GLOBAL_COMMAND_SCOPE = 'global'

function resolveCommand(source: Command | CommandFlow, argument?: string, prefixApplied?: string): CommandResult[] {
// run resolver or use ready-made results
Expand Down Expand Up @@ -931,6 +932,7 @@ export const commandPaletteLogic = kea<commandPaletteLogicType>([
actions.registerCommand(toggleHedgehogMode)
actions.registerCommand(shortcuts)
actions.registerCommand(sidepanel)
actions.registerCommand(watchRecordingsOfCommand(push))
},
beforeUnmount: () => {
actions.deregisterCommand('go-to')
Expand All @@ -945,6 +947,7 @@ export const commandPaletteLogic = kea<commandPaletteLogicType>([
actions.deregisterCommand('toggle-hedgehog-mode')
actions.deregisterCommand('shortcuts')
actions.deregisterCommand('sidepanel')
actions.deregisterCommand(WATCH_RECORDINGS_OF_KEY)
},
})),
])
100 changes: 100 additions & 0 deletions frontend/src/scenes/session-recordings/replayPaletteCommands.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import { IconRewindPlay } from '@posthog/icons'
import { Command, GLOBAL_COMMAND_SCOPE } from 'lib/components/CommandPalette/commandPaletteLogic'
import { isURL } from 'lib/utils'
import { urls } from 'scenes/urls'

import {
FilterLogicalOperator,
PropertyFilterType,
PropertyOperator,
RecordingDurationFilter,
RecordingUniversalFilters,
ReplayTabs,
} from '~/types'

function isUUIDLike(candidate: string): boolean {
return candidate.length === 36 && !!candidate.toLowerCase().match(/^[0-9a-f-]+$/)?.length
}

export const WATCH_RECORDINGS_OF_KEY = 'watch-recordings-of'
export const watchRecordingsOfCommand = (
push: (
url: string,
searchInput?: string | Record<string, any> | undefined,
hashInput?: string | Record<string, any> | undefined
) => void
): Command => ({
key: WATCH_RECORDINGS_OF_KEY,
scope: GLOBAL_COMMAND_SCOPE,
resolver: (argument: string | undefined) => {
if (argument === undefined) {
return null
}

const replayFilter = (
key: 'snapshot_source' | 'visited_page',
value: string
): Partial<RecordingUniversalFilters> => ({
date_from: '-3d',
filter_group: {
type: FilterLogicalOperator.And,
values: [
{
type: FilterLogicalOperator.And,
values: [
{
key: key,
value: [value],
operator: PropertyOperator.Exact,
type: PropertyFilterType.Recording,
},
],
},
],
},
duration: [
{
type: PropertyFilterType.Recording,
key: 'duration',
value: 1,
operator: 'gt',
} as RecordingDurationFilter,
],
})

const words = argument.split(' ')
if (words.includes('web') || words.includes('mobile')) {
return {
icon: IconRewindPlay,
display: `Watch ${argument} recordings`,
executor: () => {
push(urls.replay(ReplayTabs.Home, replayFilter('snapshot_source', argument)))
},
}
}

const url = words.find((word) => isURL(word))
if (url) {
return {
icon: IconRewindPlay,
display: `Watch recordings of visits to ${url}`,
executor: () => {
push(urls.replay(ReplayTabs.Home, replayFilter('visited_page', url)))
},
}
}

const uuid = words.find((word) => isUUIDLike(word))
if (uuid) {
return {
icon: IconRewindPlay,
display: `Watch recording of session: ${uuid}`,
executor: () => {
push(urls.replaySingle(uuid))
},
}
}

return null
},
})

0 comments on commit ac44668

Please sign in to comment.