-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
chore: separate aifilter into subcomponents and make it nicer #28735
Conversation
…stHog/posthog into chore/sr/chat-with-recordings
…stHog/posthog into chore/sr/chat-with-recordings
Some of the files I guess changed because of the "ruff check --fix" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PR Summary
This PR refactors the AI filter component in the session recordings interface, improving its organization and user experience while adding validation for filters.
- Moved AI filter from a collapse element to a button-based interface in
/frontend/src/scenes/session-recordings/components/AiFilter/AiFilter.tsx
- Added validation in
sessionRecordingsPlaylistLogic.ts
to ensure filters meet type requirements before being applied - Created new
AiFilterIntro
component with FilmCameraHog icon and consent popover for better UX - Replaced hardcoded property definitions with dynamic taxonomy data from
posthog.taxonomy.taxonomy
inai_filter_prompts.py
- Added preference rules for property type selection (event > session > person) when handling ambiguous cases
14 file(s) reviewed, 8 comment(s)
Edit PR Review Bot Settings | Greptile
{' '} | ||
{typeof content === 'function' ? content({ activeItem }) : content} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
syntax: unnecessary whitespace character before content rendering
{' '} | |
{typeof content === 'function' ? content({ activeItem }) : content} | |
{typeof content === 'function' ? content({ activeItem }) : content} |
> | ||
<DraggableToNotebook href={notebooksHref}>{filterActions}</DraggableToNotebook> | ||
|
||
<div className="flex flex-col relative w-full bg-bg-light overflow-hidden h-full Playlist__list"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
style: duplicate class name 'Playlist__list' applied to nested div, may cause styling conflicts
return ( | ||
<> | ||
<div className="flex"> | ||
<AIConsentPopoverWrapper placement="right-end" middleware={[offset(-12)]} showArrow> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
style: offset(-12) seems like a magic number. Consider defining this as a constant with a descriptive name to explain its purpose.
posthog/api/decide.py
Outdated
@@ -264,8 +264,7 @@ def get_decide(request: HttpRequest): | |||
request, | |||
generate_exception_response( | |||
"decide", | |||
f"Team with ID {team.id} cannot access the /decide endpoint." | |||
f"Please contact us at [email protected]", | |||
f"Team with ID {team.id} cannot access the /decide endpoint.Please contact us at [email protected]", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
style: Missing space after period in error message which may affect readability
if ('duration' in filters) { | ||
if (!Array.isArray(filters.duration)) { | ||
return false | ||
} | ||
if ( | ||
filters.duration.length > 0 && | ||
(!filters.duration[0]?.type || !filters.duration[0]?.key || !filters.duration[0]?.operator) | ||
) { | ||
return false | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
logic: Duration validation could be more robust - currently only checks first element's properties but array could contain invalid elements after index 0
if ('filter_group' in filters) { | ||
const group = filters.filter_group | ||
if (!group || typeof group !== 'object') { | ||
return false | ||
} | ||
if (!('type' in group) || !('values' in group) || !Array.isArray(group.values)) { | ||
return false | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
logic: filter_group validation should also check that 'type' is a valid FilterLogicalOperator value
if (!isValidRecordingFilters(filters)) { | ||
console.error('Invalid filters provided:', filters) | ||
return state | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
style: Consider throwing an error or showing a user-facing notification instead of just logging to console when invalid filters are provided
Full list of available properties and their definitions: | ||
{json.dumps(CORE_FILTER_DEFINITIONS_BY_GROUP, indent=2)} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
style: Using f-strings with json.dumps() could potentially cause issues if the JSON contains curly braces. Consider using a different string formatting approach or escaping the braces
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we should probably prompt "when there is a choice prefer event properties over session properties and session properties over person properties"
event properties are faster and generally better match people's expected results better
Size Change: 0 B Total Size: 1.21 MB ℹ️ View Unchanged
|
📸 UI snapshots have been updated16 snapshot changes in total. 0 added, 16 modified, 0 deleted:
Triggered by this commit. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is the pop up here expected?
…stHog/posthog into chore/sr/chat-with-recordings
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
quick pass
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same popping in here
frontend/src/scenes/session-recordings/components/AiFilter/AiFilterInput.tsx
Outdated
Show resolved
Hide resolved
@@ -83,6 +88,8 @@ export function Playlist({ | |||
750: 'medium', | |||
}) | |||
|
|||
const [isExpanded, setIsExpanded] = useState(false) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
really this should be on a kea logic but I'll pretend not to notice 😉
className={clsx('Playlist h-full min-h-96 w-full min-w-96 lg:min-w-[560px] order-first xl:order-none', { | ||
'Playlist--wide': size !== 'small', | ||
'Playlist--embedded': embedded, | ||
className={clsx('flex flex-col w-full gap-2 h-full', { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
are we sure we're not using the wide and embedded classes?
they might be necessary when shared or full screen?
ref={playlistRef} | ||
data-attr={dataAttr} | ||
className={clsx('Playlist w-full min-w-60 min-h-96', { | ||
'Playlist--wide': size !== 'small', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah, they're down here 🤣
* @param filters - The filters to check. | ||
* @returns True if the filters are valid, false otherwise. | ||
*/ | ||
export function isValidRecordingFilters(filters: Partial<RecordingUniversalFilters>): boolean { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
export function isValidRecordingFilters(filters: Partial<RecordingUniversalFilters>): boolean { | |
export function isValidRecordingFilters(filters: Partial<RecordingUniversalFilters>): x is Partial<RecordingUniversalFilters> { |
can do this so TS can do type narrowing
Full list of available properties and their definitions: | ||
{json.dumps(CORE_FILTER_DEFINITIONS_BY_GROUP, indent=2)} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we should probably prompt "when there is a choice prefer event properties over session properties and session properties over person properties"
event properties are faster and generally better match people's expected results better
…ilterInput.tsx Co-authored-by: Paul D'Ambra <[email protected]>
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Peter Kirkham <[email protected]> Co-authored-by: Paul D'Ambra <[email protected]>
Before:
![Screenshot 2025-02-14 at 17 40 28](https://private-user-images.githubusercontent.com/13624984/413396725-4cef6b85-b0a7-4632-a278-b906572dac11.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzk5ODQ0MTYsIm5iZiI6MTczOTk4NDExNiwicGF0aCI6Ii8xMzYyNDk4NC80MTMzOTY3MjUtNGNlZjZiODUtYjBhNy00NjMyLWEyNzgtYjkwNjU3MmRhYzExLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNTAyMTklMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjUwMjE5VDE2NTUxNlomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWJiNGUyMDIyMmNhZjM1NDIwZDM5NDFkODRjNGE0OTI3YTUyZmFhYmRiNzY2Y2Q0YzQ3YzQ1ZWI3MTEzMjdiYTgmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0In0.09fCPT_fEcQfTu_FzgqhXr1Utynf5NQUfo-S2ZJFOzg)
After:
![Screenshot 2025-02-14 at 17 40 53](https://private-user-images.githubusercontent.com/13624984/413396886-3a806395-6538-4f3f-b5cc-c8840a911a80.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzk5ODQ0MTYsIm5iZiI6MTczOTk4NDExNiwicGF0aCI6Ii8xMzYyNDk4NC80MTMzOTY4ODYtM2E4MDYzOTUtNjUzOC00ZjNmLWI1Y2MtYzg4NDBhOTExYTgwLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNTAyMTklMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjUwMjE5VDE2NTUxNlomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTlhMmI1M2YzNjY0ZjhlYzIwMDVlMTgzMGMzNmVjMDdkNmE5NTVlMjc0YWI0YmQxZTc0YzQwY2IzOGRlZDEzOTAmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0In0.QCXY-Epb27kOBj-gjJzwcvLHH1jfi44Z00bT2ybgoHg)