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

[SecuritySolution] Replace dashboard listing with Kibana dashboard listing #155716

Closed
wants to merge 28 commits into from

Conversation

angorayc
Copy link
Contributor

@angorayc angorayc commented Apr 25, 2023

Summary

#155089

  • 1. Header styles fitted into SecuritySolution's layout.

  • 2. Allow for Non-Removable Security Solution Tags in Portable Dashboard Listing Page

For example here are all the dashboards and attached tags:
Screenshot 2023-05-18 at 15 11 06

Before:
https://kibana.siem.estc.dev/s/dashboard-test/app/security/dashboards?sourcerer=(default:(id:security-solution-dashboard-test,selectedPatterns:!(%27auditbeat-*%27,%27filebeat-*%27,%27logs-*%27,%27packetbeat-*%27,%27winlogbeat-*%27)))

Screenshot 2023-05-24 at 11 46 20

After:

Screen.Recording.2023-05-18.at.15.37.34.mov

This is the dashboards and tags I used to test. Please download it and rename txt to ndjson and import them from
stack management > saved objects

export.txt

Checklist

Delete any items that are not applicable to this PR.

@angorayc angorayc changed the title replace dashboard listing [SecuritySolution] Replace dashboard listing with Kibana dashboard listing Apr 25, 2023
@angorayc angorayc self-assigned this Apr 25, 2023
@angorayc angorayc added Team:Threat Hunting Security Solution Threat Hunting Team Team: SecuritySolution Security Solutions Team working on SIEM, Endpoint, Timeline, Resolver, etc. Team:Threat Hunting:Explore v8.9.0 labels Apr 25, 2023
Copy link
Contributor

@ThomThomson ThomThomson left a comment

Choose a reason for hiding this comment

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

Looked through the code and tested this locally by making sure that the Dashboard Listing page still works the same way, and by checking out the design of the Security dashboard listing page. Everything LGTM from the Presentation team side of things! Left a few followup comments and nits.

Also a note, I created a dashboard from the top right link in the security solution and it wasn't automatically assigned the security-solution tag at first. As I tried again a few more times it started being assigned consistently. Is that functionality flaky? I tested in 8.7 and when I navigated via the security solution create dashboard link the new dashboard was automatically assigned the security-solution tag every time.

@@ -143,7 +152,7 @@ export const TagFilterPanel: FC<Props> = ({
renderOption={(option) => option.view}
emptyMessage="There aren't any tags"
noMatchesMessage="No tag matches the search"
onChange={onSelectChange}
onChange={!disableActions ? onSelectChange : noop}
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe as a future enhancement here instead of disabling the actions entirely, we could treat the fixedTag as a special entry, not allowing it to be de-selected, but allowing all other tag systems to work.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Screen.Recording.2023-05-18.at.15.37.34.mov

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yup, updated, rest of the tags are still listed and working.

@angorayc angorayc marked this pull request as ready for review May 18, 2023 14:41
@angorayc angorayc requested a review from a team as a code owner May 18, 2023 14:41
@angorayc angorayc requested review from a team as code owners May 18, 2023 14:41
@elasticmachine
Copy link
Contributor

Pinging @elastic/security-threat-hunting (Team:Threat Hunting)

@elasticmachine
Copy link
Contributor

Pinging @elastic/security-solution (Team: SecuritySolution)

clearTagSelection={clearTagSelection}
tableSort={tableSort}
tagsToTableItemMap={tagsToTableItemMap}
fixedTagReferences={fixedTagReferences}
Copy link
Contributor

Choose a reason for hiding this comment

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

It seems that you wanted to sort the props by alphabetic order.. but added the new prop at the end 😊 Is that correct? Is there any new prop to the component?

Copy link
Contributor

@sebelga sebelga May 18, 2023

Choose a reason for hiding this comment

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

IMO it would be easier to review if prop order was not changed (here or in the Props interface)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sorry for the confusion, fixedTagReferences is the new prop.

@kibana-ci
Copy link
Collaborator

💚 Build Succeeded

Metrics [docs]

Module Count

Fewer modules leads to a faster build time

id before after diff
securitySolution 3873 3869 -4

Async chunks

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

id before after diff
dashboard 436.4KB 437.8KB +1.4KB
filesManagement 87.6KB 88.7KB +1.1KB
graph 453.9KB 455.0KB +1.1KB
maps 2.8MB 2.8MB +1.1KB
securitySolution 9.2MB 9.2MB -1.4KB
visualizations 260.2KB 261.3KB +1.1KB
total +4.2KB
Unknown metric groups

ESLint disabled line counts

id before after diff
enterpriseSearch 19 21 +2
securitySolution 400 404 +4
total +6

Total ESLint disabled count

id before after diff
enterpriseSearch 20 22 +2
securitySolution 480 484 +4
total +6

History

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

cc @angorayc

Copy link
Contributor

@sebelga sebelga left a comment

Choose a reason for hiding this comment

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

I'm half way through the code review and I have some concerns with the UX of the feature.

Rendering a tag in the tag panel that is not actionable seems like a UX bug. The user will wonder "Why can't I unselect this tag?"

I think a better UI would be to:

  • filter out the "fixed" tags from the tag panel list.
  • not to fill the search bar with the "tag:("Security Solution")" text
  • hide the tags in the table row (here too, those tags are actionable but now don't do anything)

The prop to configure the table could be withTags

<DashboardListingTable
  withTags={{
    tags: [tag1, tag2],
    hideFromTable: true, // default "true"
    hideFromSearch: true, // default "true"
  }}
  disableCreateDashboardButton={loadingCreateDashboardUrl}
  getDashboardUrl={getSecuritySolutionDashboardUrl}
  ...

The <TableListView /> is already a bloated component (I know, it should be refactored). I wouldn't just push another prop to block behaviour but think how a nice UX would be if it is used in a new context.

Here what we really want is a table with specific items that can't be removed and we use the tag mechanism for this filtering. Let's hide our internals (the "Security Solution" tag) from the user. 😊

@@ -53,21 +64,31 @@ export const useTagFilterPanel = ({
const [isInUse, setIsInUse] = useState(false);
const [options, setOptions] = useState<TagOptionItem[]>([]);
const [tagSelection, setTagSelection] = useState<TagSelection>({});
const totalActiveFilters = Object.keys(tagSelection).length;
const totalActiveFilters = useMemo(
() => getTotalActiveFilters(options, fixedTagReferences),
Copy link
Contributor

Choose a reason for hiding this comment

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

Why do we pass options and not tagSelection ? I would also pass an array if fixedTagReferences is undefined or null to make getTotalActiveFilters simpler

const getTotalActiveFilters = (
  tagSelection: TagSelection,
  fixedTagReferences: TagReference[]
) =>
  Math.max(
    fixedTagReferences.length,
    Object.keys(tagSelection).length
  );

const totalActiveFilters = useMemo(
  () => getTotalActiveFilters(tagSelection, fixedTagReferences ?? []),
  [fixedTagReferences, tagSelection]
);
...

Copy link
Contributor

Choose a reason for hiding this comment

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

It could really just be this

const totalActiveFilters = useMemo(() => (
    Math.max((fixedTagReferences ?? []).length, Object.keys(tagSelection).length)
  )),
  [fixedTagReferences, tagSelection]
);
...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

As the tagSelection seemed to have problem displaying the actual count when a few tags sharing the same name.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Screenshot 2023-05-23 at 15 30 45

Copy link
Contributor

@stephmilovic stephmilovic left a comment

Choose a reason for hiding this comment

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

Nice work, excellent job on test coverage. Desk testing went perfectly, LGTM. Thanks @angorayc

@angorayc
Copy link
Contributor Author

I'm half way through the code review and I have some concerns with the UX of the feature.

Rendering a tag in the tag panel that is not actionable seems like a UX bug. The user will wonder "Why can't I unselect this tag?"

Thanks for your review. As the listing is used under Security Solution, so it'd make more sense if users couldn't remove the default selected Security Solution tag.

I think a better UI would be to:

  • filter out the "fixed" tags from the tag panel list.
  • not to fill the search bar with the "tag:("Security Solution")" text

I tried the Kibana Dashboard listing and found the status filter and query were aligned, so I would leaning towards keeping this behaviour.

Screenshot 2023-05-23 at 15 32 25
  • hide the tags in the table row (here too, those tags are actionable but now don't do anything)

Given that we have default selected tags, I'd like to keep the tags in each row so users could understand how the filter affects the table. If the tag is one of the unremovable tags, I'd disable it's filter behaviour.

The prop to configure the table could be withTags

<DashboardListingTable
  withTags={{
    tags: [tag1, tag2],
    hideFromTable: true, // default "true"
    hideFromSearch: true, // default "true"
  }}
  disableCreateDashboardButton={loadingCreateDashboardUrl}
  getDashboardUrl={getSecuritySolutionDashboardUrl}
  ...

The <TableListView /> is already a bloated component (I know, it should be refactored). I wouldn't just push another prop to block behaviour but think how a nice UX would be if it is used in a new context.

Sure, I'll rename the prop to withTags.

Here what we really want is a table with specific items that can't be removed and we use the tag mechanism for this filtering. Let's hide our internals (the "Security Solution" tag) from the user. 😊

@angorayc
Copy link
Contributor Author

angorayc commented Jun 22, 2023

After talking to the team, we decide to give the non-removable tag request. What we will do is to select Security Solution tag by default but users are still able to remove the selection. #160540

@angorayc angorayc added v8.10.0 backport:skip This commit does not require backporting and removed v8.9.0 labels Jun 26, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backport:skip This commit does not require backporting release_note:enhancement Team: SecuritySolution Security Solutions Team working on SIEM, Endpoint, Timeline, Resolver, etc. Team:Threat Hunting:Explore Team:Threat Hunting Security Solution Threat Hunting Team v8.10.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants