Skip to content
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

Merged
merged 9 commits into from
Jul 14, 2020

Conversation

oatkiller
Copy link
Contributor

@oatkiller oatkiller commented Jul 13, 2020

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 a4a496b 96e642e
hiding_footer_good_v3 mov

BEFORE

image
image

Checklist

For maintainers

@oatkiller oatkiller requested review from a team as code owners July 13, 2020 19:17
@oatkiller oatkiller added release_note:skip Skip the PR/issue when compiling release notes v7.9.0 labels Jul 13, 2020
@oatkiller oatkiller requested a review from marrasherrier July 13, 2020 19:45
@@ -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';
Copy link
Contributor Author

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. */
Copy link
Contributor Author

@oatkiller oatkiller Jul 13, 2020

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
Copy link
Contributor Author

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}
Copy link
Contributor Author

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(
Copy link
Contributor Author

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.

Copy link
Contributor Author

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
Copy link
Contributor Author

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) && (
Copy link
Contributor Author

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
Copy link
Contributor

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?

Copy link
Contributor

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.

Copy link
Contributor

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.

Copy link
Contributor Author

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 has graphEventId 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"
Copy link
Contributor Author

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"
Copy link
Contributor Author

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) =>
Copy link
Contributor Author

@oatkiller oatkiller Jul 13, 2020

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 graphEventIds truthy/falsiness. The extra abstraction didn't seem helpful.

@oatkiller
Copy link
Contributor Author

@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 graphEventId for the stateful event viewer. My thoughts:

  1. Create a store w/ a different default state, pass that into the mock provider
  2. Test the EventViewer directly (not the stateful one). This would require mocking all of the props which are normally defined in the connect function.

Do either of these seem like a good idea? Is the test necessary? ty

@@ -34,6 +34,7 @@ jest.mock('react-redux', () => {
};
});
jest.mock('../../../../common/components/link_to');
jest.mock('../../graph_overlay');
Copy link
Contributor Author

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);
Copy link
Contributor Author

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.

Copy link
Contributor Author

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

Copy link
Contributor

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-subjs, 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.

Copy link
Contributor Author

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.

Copy link
Contributor

@andrew-goldstein andrew-goldstein left a 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;
Copy link
Contributor Author

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.

@kibanamachine
Copy link
Contributor

💚 Build Succeeded

Build metrics

✅ unchanged

History

To update your PR or re-run it, just comment with:
@elasticmachine merge upstream

@oatkiller oatkiller merged commit 97afee5 into elastic:master Jul 14, 2020
oatkiller pushed a commit to oatkiller/kibana that referenced this pull request Jul 14, 2020
…ic#71516)

* Hide the Timeline footer, in the event viewer, if Resolver is showing
gmmorris added a commit to gmmorris/kibana that referenced this pull request Jul 14, 2020
* 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)
  ...
oatkiller pushed a commit that referenced this pull request Jul 14, 2020
… (#71640)

* Hide the Timeline footer, in the event viewer, if Resolver is showing
@oatkiller oatkiller deleted the hide-timeline-footer branch March 31, 2022 11:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
release_note:skip Skip the PR/issue when compiling release notes v7.9.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants