-
Notifications
You must be signed in to change notification settings - Fork 8.2k
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
Hide timeline footer when Resolver is open #71516
Conversation
@@ -34,6 +34,7 @@ import { | |||
} from '../../../../../../../src/plugins/data/public'; | |||
import { inputsModel } from '../../store'; | |||
import { useManageTimeline } from '../../../timelines/components/manage_timeline'; | |||
import { showGraphView } from '../../../timelines/components/timeline/body/helpers'; |
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.
this was defined here, but perhaps i should move it if im using it this way? looking for guidance from SIEM team.
tieBreaker={getOr(null, 'endCursor.tiebreaker', pageInfo)} | ||
/> | ||
{ | ||
/** Hide the footer if Resolver is showing. */ |
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.
Add a guard statement and remove data-test-subj
@@ -237,5 +246,6 @@ export const EventsViewer = React.memo( | |||
deepEqual(prevProps.query, nextProps.query) && | |||
prevProps.start === nextProps.start && | |||
prevProps.sort === nextProps.sort && | |||
prevProps.utilityBar === nextProps.utilityBar | |||
prevProps.utilityBar === nextProps.utilityBar && | |||
prevProps.graphEventId === nextProps.graphEventId |
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.
This seems to be required for it to work.
@@ -135,6 +137,7 @@ const StatefulEventsViewerComponent: React.FC<Props> = ({ | |||
sort={sort} | |||
toggleColumn={toggleColumn} | |||
utilityBar={utilityBar} | |||
graphEventId={graphEventId} |
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.
Pass the new prop to the unconnected event viewer
@@ -174,6 +178,11 @@ const makeMapStateToProps = () => { | |||
query: getGlobalQuerySelector(state), | |||
sort, | |||
showCheckboxes, | |||
// Used to determine whether the footer should show (since it is hidden if the graph is showing.) | |||
graphEventId: /** `getTimeline` actually returns `TimelineModel | undefined` */ (getTimeline( |
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.
i was confused looking at the types in my editor. Basically, getTimeline
returns TimelineModel | undefined
but is typed as TimelineModel
.
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.
Not sure if this is working correctly or not. Perhaps it's worth investigating?
@@ -213,6 +222,7 @@ export const StatefulEventsViewer = connector( | |||
deepEqual(prevProps.pageFilters, nextProps.pageFilters) && | |||
prevProps.showCheckboxes === nextProps.showCheckboxes && | |||
prevProps.start === nextProps.start && | |||
prevProps.utilityBar === nextProps.utilityBar | |||
prevProps.utilityBar === nextProps.utilityBar && | |||
prevProps.graphEventId === nextProps.graphEventId |
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.
required for rendering to work correctly
</StyledEuiFlyoutFooter> | ||
{ | ||
/** Hide the footer if Resolver is showing. */ | ||
!showGraphView(graphEventId) && ( |
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.
only change here is to add the guard. props are the same
@@ -67,6 +68,8 @@ interface Props { | |||
sort: Sort; | |||
toggleColumn: (column: ColumnHeaderOptions) => void; | |||
utilityBar?: (refetch: inputsModel.Refetch, totalCount: number) => React.ReactNode; | |||
// If truthy, the graph viewer (Resolver) is showing |
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.
❔ Should this come from a selector like shouldShowResolver
?
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.
I only ask because I've done sparse business logic like this before and have been asked to move it to a selector to make it more readable.
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.
I see later maybe there is a selector? It's not clear from reading this the way the comment is written.
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.
i'm changing some existing code here, but my thoughts:
- There is a selector (that this uses) that gets the
TimelineModel
. TimelineModel
hasgraphEventId
as a field- If
graphEventId
is falsy, there is no 'graphEvent' (aka resolver) - If
graphEventId
ts truthy, the value is the_id
of the document that Resolver should use.
The existing code doesn't have a specific selector for graphEventId
. Instead it exposes the TimelineModel
interface throughout the view. If there was a desire to encapsulate the logic of "given a TimelineModel
, how do I know if the graph view should show" then I would add a method to the TimelineModel
. I don't think that would fit the code style of the SIEM team, but I'm open to changing it if they want that.
className="timeline-flyout-footer" | ||
> | ||
<Footer | ||
data-test-subj="timeline-footer" |
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.
Added this data-test-subj
. The same data-test-subj was already defined (on the source of Footer
) but not used. I moved it here.
@@ -2,7 +2,6 @@ | |||
|
|||
exports[`Footer Timeline Component rendering it renders the default timeline footer 1`] = ` | |||
<FooterContainer | |||
data-test-subj="timeline-footer" |
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.
this wasn't being used so i took it. Enzyme didn't seem to render this far. I expected it to (the call was to mount
.) But I've never used enzyme so I'm probably goofing it up. This works, but if anyone has improvement suggestions let me know.
@@ -103,9 +103,6 @@ export const getEventType = (event: Ecs): Omit<EventType, 'all'> => { | |||
return 'raw'; | |||
}; | |||
|
|||
export const showGraphView = (graphEventId?: string) => |
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.
I removed this function. Instead i'm just using the graphEventId
s truthy/falsiness. The extra abstraction didn't seem helpful.
@andrew-goldstein I tried to put a test in this file: https://github.com/elastic/kibana/blob/master/x-pack/plugins/security_solution/public/common/components/events_viewer/index.test.tsx I couldn't find an easy way to change the value of
Do either of these seem like a good idea? Is the test necessary? ty |
…prop on TimelineBody
@@ -34,6 +34,7 @@ jest.mock('react-redux', () => { | |||
}; | |||
}); | |||
jest.mock('../../../../common/components/link_to'); | |||
jest.mock('../../graph_overlay'); |
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.
prevents resolver from rendering.
<Body {...props} /> | ||
</TestProviders> | ||
); | ||
expect(wrapper.find(TimelineBody).props().visible).toBe(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.
the timeline body still renders, but it gets a display: none
style via styled-components
.
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.
Passing the component (function) reference here. Seems neat. Is this a good thing to do in enzyme? ty
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.
Passing the component reference is a totally valid thing to do in Enzyme, however we generally prefer to instrument with data-test-subj
s, and them for selection in Enzyme tests.
The rational for standardizing on data-test-subj
means we can instrument the code under test "once", and then use the same test id in both enyzme and functional / Cypress tests.
Consider replacing the use of TimelineBody
for selection with a data-test-subj
.
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.
thanks for the explanation. i took your advice.
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.
Thanks for this addition @oatkiller!
Tested locally with agent.type: endpoint
data
LGTM 🚀
// The first TimelineBody component | ||
const timelineBody: TimelineBodyEnzymeWrapper = wrapper | ||
.find('[data-test-subj="timeline-body"]') | ||
.first() as TimelineBodyEnzymeWrapper; |
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.
These tests render 2 things that match .find('[data-test-subj="timeline-body"]')
, get the first
.
💚 Build SucceededBuild metrics
History
To update your PR or re-run it, just comment with: |
…ic#71516) * Hide the Timeline footer, in the event viewer, if Resolver is showing
* master: (21 commits) [Maps] 7.9 design improvements (elastic#71563) [ML] Changing all calls to ML endpoints to use internal user (elastic#70487) [eventLog] prevent log writing when initialization fails (elastic#71339) [Observability] landing page always being displayed (elastic#71494) [IM] Address data stream copy feedback (elastic#71615) [Logs UI] Anomalies page dataset filtering (elastic#71110) [data.search.aggs] Remove `use_field_mapping` from top hits agg (elastic#71168) [ML] Anomaly swim lane embeddable navigation and filter actions (elastic#71082) Fixes typo in siem_cloudtrail job description (elastic#71569) Require granted API Keys to have a name (elastic#71623) Update getUsageForCollection (elastic#71609) Only fetch saved elements once (elastic#71310) [SecuritySolution][Resolver] Adding siem index and guarding process ancestry (elastic#71570) [APM] Additional data telemetry changes (elastic#71112) [Visualize] Fix export table for table export links (elastic#71249) [Search] Server side search API (elastic#70446) use inclusive language (elastic#71607) [Security Solution] Hide timeline footer when Resolver is open (elastic#71516) [Index template wizard] Remove shadow and use border for components panels (elastic#71606) [ML] Kibana API endpoint for histogram chart data (elastic#70976) ...
… (#71640) * Hide the Timeline footer, in the event viewer, if Resolver is showing
Summary
When Resolver opens up, the Timeline footer is still visible. A user might think that the timeline footer controls Resolver. This PR hides the footer when Resolver is open.
The footer (pagination) is now hidden when Resolver is visible
Edit: new gif for
a4a496b96e642eBEFORE
Checklist
For maintainers