Skip to content

Commit

Permalink
feat: show filters on group page (#23018)
Browse files Browse the repository at this point in the history
  • Loading branch information
daibhin authored Jun 17, 2024
1 parent f1be4b2 commit 1690aaf
Show file tree
Hide file tree
Showing 8 changed files with 335 additions and 243 deletions.
109 changes: 109 additions & 0 deletions frontend/src/scenes/error-tracking/ErrorTrackingFilters.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import { LemonSelect } from '@posthog/lemon-ui'
import { useActions, useValues } from 'kea'
import { DateFilter } from 'lib/components/DateFilter/DateFilter'
import { TaxonomicFilterGroupType } from 'lib/components/TaxonomicFilter/types'
import UniversalFilters from 'lib/components/UniversalFilters/UniversalFilters'
import { universalFiltersLogic } from 'lib/components/UniversalFilters/universalFiltersLogic'
import { TestAccountFilter } from 'scenes/insights/filters/TestAccountFilter'

import { AnyPropertyFilter } from '~/types'

import { errorTrackingLogic } from './errorTrackingLogic'
import { errorTrackingSceneLogic } from './errorTrackingSceneLogic'

export const ErrorTrackingFilters = ({ showOrder = true }: { showOrder?: boolean }): JSX.Element => {
const { dateRange, filterGroup, filterTestAccounts } = useValues(errorTrackingLogic)
const { setDateRange, setFilterGroup, setFilterTestAccounts } = useActions(errorTrackingLogic)
const { order } = useValues(errorTrackingSceneLogic)
const { setOrder } = useActions(errorTrackingSceneLogic)

return (
<UniversalFilters
rootKey="session-recordings"
group={filterGroup}
taxonomicGroupTypes={[TaxonomicFilterGroupType.PersonProperties, TaxonomicFilterGroupType.Cohorts]}
onChange={(filterGroup) => {
setFilterGroup(filterGroup)
}}
>
<div className="divide-y bg-bg-light rounded border">
<div className="flex flex-1 items-center space-x-2 px-2 py-1.5">
<RecordingsUniversalFilterGroup />
<UniversalFilters.AddFilterButton type="secondary" size="small" />
</div>
<div className="flex space-x-1 justify-between px-2 py-1.5">
<div className="flex space-x-1">
<DateFilter
dateFrom={dateRange.date_from}
dateTo={dateRange.date_to}
onChange={(changedDateFrom, changedDateTo) => {
setDateRange({ date_from: changedDateFrom, date_to: changedDateTo })
}}
size="small"
/>
{showOrder && (
<LemonSelect
onSelect={setOrder}
onChange={setOrder}
value={order}
options={[
{
value: 'last_seen',
label: 'Last seen',
},
{
value: 'first_seen',
label: 'First seen',
},
{
value: 'unique_occurrences',
label: 'Occurrences',
},
{
value: 'unique_users',
label: 'Users',
},
{
value: 'unique_sessions',
label: 'Sessions',
},
]}
size="small"
/>
)}
</div>
<div>
<TestAccountFilter
filters={{ filter_test_accounts: filterTestAccounts }}
onChange={({ filter_test_accounts }) => {
setFilterTestAccounts(filter_test_accounts || false)
}}
size="small"
/>
</div>
</div>
</div>
</UniversalFilters>
)
}

const RecordingsUniversalFilterGroup = (): JSX.Element => {
const { filterGroup } = useValues(universalFiltersLogic)
const { replaceGroupValue, removeGroupValue } = useActions(universalFiltersLogic)

const values = filterGroup.values as AnyPropertyFilter[]

return (
<>
{values.map((filter, index) => (
<UniversalFilters.Value
key={index}
index={index}
filter={filter}
onRemove={() => removeGroupValue(index)}
onChange={(value) => replaceGroupValue(index, value)}
/>
))}
</>
)
}
81 changes: 47 additions & 34 deletions frontend/src/scenes/error-tracking/ErrorTrackingGroupScene.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { PersonDisplay } from '@posthog/apps-common'
import { LemonButton, LemonTabs, Spinner } from '@posthog/lemon-ui'
import { useValues } from 'kea'
import { ErrorDisplay } from 'lib/components/Errors/ErrorDisplay'
Expand All @@ -7,9 +8,8 @@ import { useState } from 'react'
import { SceneExport } from 'scenes/sceneTypes'
import { SessionRecordingsPlaylist } from 'scenes/session-recordings/playlist/SessionRecordingsPlaylist'

import { EventType } from '~/types'

import { errorTrackingGroupSceneLogic } from './errorTrackingGroupSceneLogic'
import { ErrorTrackingFilters } from './ErrorTrackingFilters'
import { errorTrackingGroupSceneLogic, ExceptionEventType } from './errorTrackingGroupSceneLogic'

export const scene: SceneExport = {
component: ErrorTrackingGroupScene,
Expand All @@ -20,59 +20,72 @@ export const scene: SceneExport = {
}

export function ErrorTrackingGroupScene(): JSX.Element {
const { eventProperties, eventPropertiesLoading } = useValues(errorTrackingGroupSceneLogic)
const { events, eventsLoading } = useValues(errorTrackingGroupSceneLogic)
const [activeTab, setActiveTab] = useState<'details' | 'recordings'>('details')

return eventPropertiesLoading ? (
<Spinner />
) : eventProperties && eventProperties.length > 0 ? (
<LemonTabs
tabs={[
{
key: 'details',
label: 'Details',
content: <ExceptionDetails eventProperties={eventProperties} />,
},
{
key: 'recordings',
label: 'Recordings',
content: (
<ExceptionRecordings sessionIds={eventProperties.map((p) => p.$session_id).filter(Boolean)} />
),
},
]}
activeKey={activeTab}
onChange={setActiveTab}
/>
return eventsLoading ? (
<Spinner className="self-align-center justify-self-center" />
) : events && events.length > 0 ? (
<div>
<ErrorTrackingFilters showOrder={false} />
<LemonTabs
tabs={[
{
key: 'details',
label: 'Details',
content: <ExceptionDetails events={events} />,
},
{
key: 'recordings',
label: 'Recordings',
content: (
<ExceptionRecordings
sessionIds={events.map((e) => e.properties.$session_id).filter(Boolean)}
/>
),
},
]}
activeKey={activeTab}
onChange={setActiveTab}
/>
</div>
) : (
<NotFound object="exception" />
)
}

const ExceptionDetails = ({ eventProperties }: { eventProperties: EventType['properties'] }): JSX.Element => {
const [activeEventId, setActiveEventId] = useState<number>(eventProperties.length - 1)
const ExceptionDetails = ({ events }: { events: ExceptionEventType[] }): JSX.Element => {
const [activeEventId, setActiveEventId] = useState<number>(events.length - 1)

const event = events[activeEventId]

return (
<div>
{eventProperties.length > 1 && (
<div className="flex justify-end space-x-1">
<div className="space-y-4">
{events.length > 1 && (
<div className="flex space-x-1 items-center">
<LemonButton
size="small"
size="xsmall"
type="secondary"
icon={<IconChevronLeft />}
onClick={() => setActiveEventId(activeEventId - 1)}
disabledReason={activeEventId <= 0 && 'No earlier examples'}
/>
<LemonButton
size="small"
size="xsmall"
type="secondary"
icon={<IconChevronRight />}
onClick={() => setActiveEventId(activeEventId + 1)}
disabledReason={activeEventId >= eventProperties.length - 1 && 'No newer examples'}
disabledReason={activeEventId >= events.length - 1 && 'No newer examples'}
/>
<span>
{activeEventId + 1} of {events.length}
</span>
</div>
)}
<ErrorDisplay eventProperties={eventProperties[activeEventId]} />
<div className="bg-bg-light border rounded p-2">
<PersonDisplay person={event.person} withIcon />
</div>
<ErrorDisplay eventProperties={event.properties} />
</div>
)
}
Expand Down
Loading

0 comments on commit 1690aaf

Please sign in to comment.