Skip to content

[Cases] Lens as persistable state attachment type#159004

Merged
cnasikas merged 20 commits intoelastic:mainfrom
cnasikas:lens_as_attachment
Jun 16, 2023
Merged

[Cases] Lens as persistable state attachment type#159004
cnasikas merged 20 commits intoelastic:mainfrom
cnasikas:lens_as_attachment

Conversation

@cnasikas
Copy link
Copy Markdown
Member

@cnasikas cnasikas commented Jun 5, 2023

Summary

This PR registers the lens attachment type using the cases attachment framework.

Testing scenarios

  1. Attaching a lens visualization to the markdown editor works as expected
  2. Attaching a lens visualization from the dashboard creates a lens attachment (persistable state)
  3. Attaching a lens visualization from the security solution dashboard (Security solution -> Dashboards -> Create dashboard) creates a lens attachment (persistable state).
  4. Attaching a lens visualization from the security solution overview dashboard (Security solution -> Dashboards -> Overview) creates a lens attachment (persistable state).
Screenshot 2023-06-13 at 3 10 50 PM

Checklist

Delete any items that are not applicable to this PR.

For maintainers

@cnasikas cnasikas added Team:ResponseOps Platform ResponseOps team (formerly the Cases and Alerting teams) t// Feature:Cases Cases feature labels Jun 5, 2023
@cnasikas cnasikas self-assigned this Jun 5, 2023
@cnasikas cnasikas force-pushed the lens_as_attachment branch from 59525ef to 3b4bad4 Compare June 8, 2023 20:23
@cnasikas cnasikas added the v8.9.0 label Jun 8, 2023
@cnasikas cnasikas marked this pull request as ready for review June 13, 2023 06:39
@cnasikas cnasikas requested review from a team as code owners June 13, 2023 06:39
@elasticmachine
Copy link
Copy Markdown
Contributor

Pinging @elastic/response-ops (Team:ResponseOps)

@elasticmachine
Copy link
Copy Markdown
Contributor

Pinging @elastic/response-ops-cases (Feature:Cases)

@cnasikas cnasikas added the release_note:skip Skip the PR/issue when compiling release notes label Jun 13, 2023
import { LensParser } from './parser';
import { LensMarkDownRenderer } from './processor';
import { VISUALIZATION } from './translations';
import LensRenderer from '../../../visualizations/lens_renderer';
Copy link
Copy Markdown
Member Author

@cnasikas cnasikas Jun 13, 2023

Choose a reason for hiding this comment

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

Same code as before. Moved to the visualization folder.

export const LensRenderer = React.memo(LensRendererComponent);

// eslint-disable-next-line import/no-default-export
export { LensRenderer as default };
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Same code as before. Different naming.

import type { LensProps } from './types';
import { OpenLensButton } from './open_lens_button';

function getOpenLensButton(attachmentId: string, props: LensProps) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Lazy loading here would decrease the page bundle size iirc

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I think it is ok as we do not import any new component from other plugins and the OpenLensButton component is already in the bundle as it is used by the markdown editor.

persistableStateAttachmentState as unknown as LensProps;

return {
event: 'added visualization',
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Translation missing for the event

const { LensRenderer } = await import('./lens_renderer');

return {
// eslint-disable-next-line react/display-name
Copy link
Copy Markdown
Contributor

@adcoelho adcoelho Jun 13, 2023

Choose a reason for hiding this comment

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

nit: could you avoid this comment with the below?

Suggested change
// eslint-disable-next-line react/display-name
const my_function = (props: PersistableStateAttachmentViewProps) => {
const { attributes, timeRange } = props.persistableStateAttachmentState as unknown as LensProps;
return <LensRenderer attributes={attributes} timeRange={timeRange} />;
}
return {
default: React.memo(my_function,
...

});
});

describe('createCommentUserActionBuilder', () => {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: should this be createRegisteredAttachmentUserActionBuilder?

createCommentUserActionBuilder is in x-pack/plugins/cases/public/components/user_actions/comment/comment.test.tsx

Copy link
Copy Markdown
Member Author

@cnasikas cnasikas Jun 15, 2023

Choose a reason for hiding this comment

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

Bad copy paste 🙂

});
});

it('builds the action correctly', async () => {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Could you please also add a test for when hideDefaultActions is true?

type: CommentType.persistableState as const,
},
];
] as CaseAttachmentsWithoutOwner;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Could you please add the test below to its test file:

const mockOpenCaseFlyout = jest.fn();
const mockGetUseCasesAddToNewCaseFlyout = jest.fn().mockReturnValue({ open: mockOpenCaseFlyout });


it('should open create case flyout', () => {
    const mockClick = jest.fn();
    const { result } = renderHook(() =>
      useAddToNewCase({
        lensAttributes: kpiHostMetricLensAttributes,
        timeRange,
        onClick: mockClick,
      })
    );
    result.current.onAddToNewCaseClicked();
    expect(mockOpenCaseFlyout).toHaveBeenCalledWith({
      attachments: [
        {
          persistableStateAttachmentState: { attributes: kpiHostMetricLensAttributes, timeRange },
          persistableStateAttachmentTypeId: LENS_ATTACHMENT_TYPE,
          type: CommentType.persistableState as const,
        },
      ],
    });
    expect(mockClick).toHaveBeenCalled();
  });

type: CommentType.persistableState as const,
},
];
] as CaseAttachmentsWithoutOwner;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Please add the test to its test file:

const mockOpenCaseModal = jest.fn();

const mockGetUseCasesAddToExistingCaseModal = jest
  .fn()
  .mockReturnValue({ open: mockOpenCaseModal });

it('should open add to existing case modal', () => {
    const mockClick = jest.fn();
    const { result } = renderHook(() =>
      useAddToExistingCase({
        lensAttributes: kpiHostMetricLensAttributes,
        timeRange,
        onAddToCaseClicked: mockClick,
      })
    );
    result.current.onAddToExistingCaseClicked();
    const attachments = mockOpenCaseModal.mock.calls[0][0].getAttachments();
    expect(attachments).toEqual([
      {
        persistableStateAttachmentState: {
          attributes: kpiHostMetricLensAttributes,
          timeRange,
        },
        persistableStateAttachmentTypeId: LENS_ATTACHMENT_TYPE,
        type: CommentType.persistableState as const,
      },
    ]);
    expect(mockClick).toHaveBeenCalled();
  });

Copy link
Copy Markdown
Contributor

@jonathan-buttner jonathan-buttner left a comment

Choose a reason for hiding this comment

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

Looking good, left a few comments. Is there a way we can test the deferred migrations for user actions and comments? Or do our tests already cover it?

"children": <React.Suspense
fallback={<EuiLoadingSpinner />}
>
<UNDEFINED
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Is this supposed to be undefined 🤔

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Probably because the registered component does not have a displayName. I find it weird tbh.


const props = {
...getAttachmentViewProps(),
attachmentId: userAction.id,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should this be attachmentId: comment.id?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

hmm, good point. I will change it.

{
comment: `!{lens${JSON.stringify({
timeRange: mockTimeRange,
persistableStateAttachmentState: {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: I know this isn't your change but I wonder if we should do a more exact check instead of expect.objectContaining. Or are there other fields that aren't represented here?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I removed it and it seems that only these fields are the expected ones. Not sure why it was there in the first place.

context,
error,
docType: 'user action persistable lens attachment',
docKey: 'comment',
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should this be user-action or something similar?

return mergeSavedObjectMigrationMaps(userActionsMigrations, embeddableMigrationsToMerge);
};

export const lensMigratorFactory = (
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think it's fine if we want to migrate the user actions. But just to make sure I'm understanding correctly, we still aren't migrating the user actions where a lens embeddable is within the comment via a json blob (aka not a persistable attachment)?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

As we discussed offline, I removed the lens migrations in user actions.

@js-jankisalvi
Copy link
Copy Markdown
Contributor

Testing scenarios

  1. Attaching a lens visualization to the markdown editor works as expected ✅
  2. Attaching a lens visualization from the dashboard creates a lens attachment (persistable state) ✅
  3. Attaching a lens visualization from the security solution dashboard (Security solution -> Dashboards -> Create dashboard) creates a lens attachment (persistable state). ✅
  4. Attaching a lens visualization from the security solution overview dashboard (Security solution -> Dashboards -> Overview) creates a lens attachment (persistable state). ✅

Verified all 4 scenarios, works as expected 👍

Copy link
Copy Markdown
Contributor

@shahzad31 shahzad31 left a comment

Choose a reason for hiding this comment

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

Uptime changes LGTM !!

@cnasikas
Copy link
Copy Markdown
Member Author

Is there a way we can test the deferred migrations for user actions and comments? Or do our tests already cover it?

I don't think so as there are no 8.9+ migrations registered by the lens team yet. The unit tests should cover all scenarios. Wdyt?

@jonathan-buttner
Copy link
Copy Markdown
Contributor

Is there a way we can test the deferred migrations for user actions and comments? Or do our tests already cover it?

I don't think so as there are no 8.9+ migrations registered by the lens team yet. The unit tests should cover all scenarios. Wdyt?

Sounds good.

Copy link
Copy Markdown
Contributor

@jonathan-buttner jonathan-buttner left a comment

Choose a reason for hiding this comment

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

Looks good!

@cnasikas cnasikas added the ci:skip-cypress-osquery Skips osquery cypress checks label Jun 15, 2023
@cnasikas
Copy link
Copy Markdown
Member Author

@elasticmachine merge upstream

@kibana-ci
Copy link
Copy Markdown

💛 Build succeeded, but was flaky

Failed CI Steps

Test Failures

  • [job] [logs] Security Solution Tests #7 / Prebuilt rules Actions with prebuilt rules Rules table "before each" hook for "Allows to delete all rules at once"

Metrics [docs]

Module Count

Fewer modules leads to a faster build time

id before after diff
cases 639 643 +4

Public APIs missing comments

Total count of every public API that lacks a comment. Target amount is 0. Run node scripts/build_api_docs --plugin [yourplugin] --stats comments for more detailed information.

id before after diff
cases 64 65 +1

Async chunks

Total size of all lazy-loaded chunks that will be downloaded as the user navigates the app

id before after diff
cases 416.8KB 415.4KB -1.4KB
exploratoryView 199.6KB 199.6KB +80.0B
securitySolution 10.8MB 10.8MB +480.0B
total -903.0B

Page load bundle

Size of the bundles that are downloaded on every page load. Target size is below 100kb

id before after diff
cases 135.7KB 139.1KB +3.4KB
exploratoryView 44.8KB 44.9KB +135.0B
total +3.6KB
Unknown metric groups

API count

id before after diff
cases 79 80 +1

ESLint disabled line counts

id before after diff
cases 57 58 +1
enterpriseSearch 13 15 +2
securitySolution 411 415 +4
total +7

Total ESLint disabled count

id before after diff
cases 74 75 +1
enterpriseSearch 14 16 +2
securitySolution 494 498 +4
total +7

History

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

cc @cnasikas

@cnasikas cnasikas merged commit 5df612e into elastic:main Jun 16, 2023
@cnasikas cnasikas deleted the lens_as_attachment branch June 16, 2023 09:46
@kibanamachine kibanamachine added the backport:skip This PR does not require backporting label Jun 16, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport:skip This PR does not require backporting ci:skip-cypress-osquery Skips osquery cypress checks Feature:Cases Cases feature release_note:skip Skip the PR/issue when compiling release notes Team:ResponseOps Platform ResponseOps team (formerly the Cases and Alerting teams) t// v8.9.0

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants