Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ export interface DataSourceTableProps<T extends Record<string, any>> {
dataSource: BuiltLogic<DataSourceLogic<T>>
className?: string
children?: React.ReactNode
embedded?: boolean
embedded?: LemonTableProps<T>['embedded']
stealth?: LemonTableProps<T>['stealth']
expandable?: LemonTableProps<T>['expandable']
onRowClick?: (item: T, evt: MouseEvent) => void
rowRibbonColor?: LemonTableProps<T>['rowRibbonColor']
Expand All @@ -20,6 +21,7 @@ export function DataSourceTable<T extends Record<string, any>>({
dataSource,
className,
embedded = false,
stealth = false,
onRowClick,
rowRibbonColor,
expandable,
Expand Down Expand Up @@ -62,6 +64,7 @@ export function DataSourceTable<T extends Record<string, any>>({
columns={columns}
loading={itemsLoading}
embedded={embedded}
stealth={stealth}
onRow={onRow}
className={className}
footer={<DataSourceTableFooter dataSource={dataSource} />}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,14 @@ export interface EventsTableProps {
onEventSelect: (event: ErrorEventType | null) => void
}

export function EventsTable({ query, queryKey, onEventSelect }: EventsTableProps): JSX.Element {
export function EventsTable({ query, queryKey, onEventSelect, selectedEvent }: EventsTableProps): JSX.Element {
const tagRenderer = useErrorTagRenderer()
const dataSource = eventsSourceLogic({ queryKey, query })

function isEventSelected(record: ErrorEventType): boolean {
return selectedEvent ? selectedEvent.uuid === record.uuid : false
}

function renderTitle(record: ErrorEventType): JSX.Element {
return (
<LemonTableLink
Expand Down Expand Up @@ -74,13 +78,24 @@ export function EventsTable({ query, queryKey, onEventSelect }: EventsTableProps
return <TZLabel time={record.timestamp} />
}

function renderUUID(record: ErrorEventType): JSX.Element {
// Click event is caught at the row level
return (
<div className="flex items-center">
<input type="radio" className="cursor-pointer" checked={isEventSelected(record)} onChange={() => {}} />
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: missing name attribute on radio button prevents it from being part of a radio group

Prompt To Fix With AI
This is a comment left during a code review.
Path: products/error_tracking/frontend/components/EventsTable/EventsTable.tsx
Line: 85:85

Comment:
**logic:** missing `name` attribute on radio button prevents it from being part of a radio group

How can I resolve this? If you propose a fix, please make it concise.

Copy link

Copilot AI Nov 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The radio button should have a name attribute to group related radio buttons together. All radio buttons in this table should share the same name to ensure proper radio button behavior where only one can be selected at a time.

Additionally, the radio button lacks an accessible label. Consider adding an aria-label attribute for screen readers.

Suggested change
<input type="radio" className="cursor-pointer" checked={isEventSelected(record)} onChange={() => {}} />
<input
type="radio"
className="cursor-pointer"
checked={isEventSelected(record)}
onChange={() => {}}
name={`event-select-${queryKey}`}
aria-label={`Select event ${record.uuid}`}
/>

Copilot uses AI. Check for mistakes.
</div>
)
}

return (
<DataSourceTable<ErrorEventType>
dataSource={dataSource}
embedded
onRowClick={undefined}
stealth
onRowClick={(record) => onEventSelect(record)}
className="overflow-auto"
>
<DataSourceTableColumn<ErrorEventType> width="10px" cellRenderer={renderUUID} />
<DataSourceTableColumn<ErrorEventType> title="Exception" cellRenderer={renderTitle} />
<DataSourceTableColumn<ErrorEventType> title="Labels" align="right" cellRenderer={renderAttributes} />
<DataSourceTableColumn<ErrorEventType> title="Actions" align="right" cellRenderer={Actions} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import { ErrorPropertiesLogicProps, errorPropertiesLogic } from 'lib/components/
import { ErrorEventType } from 'lib/components/Errors/types'
import { TZLabel } from 'lib/components/TZLabel'
import { TabsPrimitive, TabsPrimitiveList, TabsPrimitiveTrigger } from 'lib/ui/TabsPrimitive/TabsPrimitive'
import { cn } from 'lib/utils/css-classes'

import { ErrorTrackingRelationalIssue } from '~/queries/schema/schema-general'

Expand Down Expand Up @@ -64,7 +63,7 @@ function ExceptionCardContent({ issue, issueLoading, timestamp, label }: Excepti
const { setCurrentTab } = useActions(exceptionCardLogic)

return (
<LemonCard hoverEffect={false} className={cn('p-0 relative overflow-y-auto w-full')}>
<LemonCard hoverEffect={false} className="p-0 relative overflow-y-auto w-full border-0 rounded-none">
<TabsPrimitive value={currentTab} onValueChange={setCurrentTab}>
<div className="flex justify-between h-[2rem] items-center w-full px-2 border-b">
<TabsPrimitiveList className="flex justify-between w-full h-full items-center">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { useEffect } from 'react'
import { useRef } from 'react'

import { IconFilter, IconList, IconSearch } from '@posthog/icons'
import { LemonCollapse, LemonDivider } from '@posthog/lemon-ui'
import { LemonDivider } from '@posthog/lemon-ui'

import { Resizer } from 'lib/components/Resizer/Resizer'
import { ResizerLogicProps, resizerLogic } from 'lib/components/Resizer/resizerLogic'
Expand Down Expand Up @@ -66,33 +66,36 @@ export function ErrorTrackingIssueScene(): JSX.Element {
<ErrorTrackingSetupPrompt>
<BindLogic logic={issueFiltersLogic} props={{ logicKey: ERROR_TRACKING_ISSUE_SCENE_LOGIC_KEY }}>
{issue && (
<div className="px-4">
<SceneTitleSection
canEdit
name={issue.name}
onNameChange={updateName}
description={null}
resourceType={{ type: 'error_tracking' }}
actions={
<div className="flex items-center gap-1">
<IssueAssigneeSelect
assignee={issue.assignee}
onChange={updateAssignee}
disabled={issue.status != 'active'}
/>
<IssueStatusSelect status={issue.status} onChange={updateStatus} />
</div>
}
/>

<>
<div className="px-4">
<SceneTitleSection
canEdit
name={issue.name}
onNameChange={updateName}
description={null}
resourceType={{ type: 'error_tracking' }}
actions={
<div className="flex items-center gap-1">
<IssueAssigneeSelect
assignee={issue.assignee}
onChange={updateAssignee}
disabled={issue.status != 'active'}
/>
<IssueStatusSelect status={issue.status} onChange={updateStatus} />
</div>
}
/>
</div>
<ErrorTrackingIssueScenePanel issue={issue} />
</div>
)}

<div className="ErrorTrackingIssue flex h-[calc(100vh-var(--scene-layout-header-height)-50px)]">
<LeftHandColumn />
<RightHandColumn />
</div>
<div className="ErrorTrackingIssue h-[calc(100vh-var(--scene-layout-header-height)-50px)] flex">
<div className="flex flex-1 h-full">
<LeftHandColumn />
<RightHandColumn />
</div>
</div>
</>
)}
</BindLogic>
</ErrorTrackingSetupPrompt>
)
Expand All @@ -103,7 +106,7 @@ const RightHandColumn = (): JSX.Element => {
const tagRenderer = useErrorTagRenderer()

return (
<div className="flex flex-1 gap-y-1 px-4 py-3 overflow-y-auto min-w-[375px]">
<div className="flex flex-1 gap-y-1 overflow-y-auto min-w-[375px]">
<PostHogSDKIssueBanner event={selectedEvent} />

<ExceptionCard
Expand Down Expand Up @@ -139,7 +142,7 @@ const LeftHandColumn = (): JSX.Element => {
width: desiredSize ?? '30%',
minWidth: 320,
}}
className="flex flex-col relative bg-bg-light"
className="flex flex-col relative bg-surface-primary"
>
<TabsPrimitive
value={category}
Expand All @@ -148,7 +151,7 @@ const LeftHandColumn = (): JSX.Element => {
>
<div>
<ScrollableShadows direction="horizontal" className="border-b" hideScrollbars>
<TabsPrimitiveList className="flex justify-between space-x-2">
<TabsPrimitiveList className="flex justify-between space-x-0.5">
<TabsPrimitiveTrigger className="flex items-center px-2 py-1.5" value="exceptions">
<IconList className="mr-1" />
<span className="text-nowrap">Exceptions</span>
Expand Down Expand Up @@ -195,35 +198,26 @@ const LeftHandColumn = (): JSX.Element => {
}

const ExceptionsTab = (): JSX.Element => {
const { eventsQuery, eventsQueryKey } = useValues(errorTrackingIssueSceneLogic)
const { eventsQuery, eventsQueryKey, selectedEvent } = useValues(errorTrackingIssueSceneLogic)
const { selectEvent } = useActions(errorTrackingIssueSceneLogic)

return (
<div className="flex flex-col h-full">
<LemonCollapse
embedded
panels={[
{
key: 'filters',
header: 'Add filters',
content: (
<ErrorFilters.Root>
<div className="flex gap-2 justify-between flex-wrap">
<ErrorFilters.DateRange />
<ErrorFilters.InternalAccounts />
</div>
<ErrorFilters.FilterGroup />
</ErrorFilters.Root>
),
},
]}
/>
<div className="px-2 py-3">
<ErrorFilters.Root>
<div className="flex gap-2 justify-between flex-wrap">
<ErrorFilters.DateRange />
<ErrorFilters.InternalAccounts />
</div>
<ErrorFilters.FilterGroup />
</ErrorFilters.Root>
</div>
<LemonDivider className="my-0" />
<Metadata className="flex flex-col overflow-y-auto">
<EventsTable
query={eventsQuery}
queryKey={eventsQueryKey}
selectedEvent={null}
selectedEvent={selectedEvent}
onEventSelect={(selectedEvent) => {
if (selectedEvent) {
selectEvent(selectedEvent)
Expand Down
Loading