[8.7] [Infrastructure UI] Fix inventory table pagination navigation (#153849) (#153920)

# Backport

This will backport the following commits from `main` to `8.7`:
- [[Infrastructure UI] Fix inventory table pagination navigation
(#153849)](https://github.com/elastic/kibana/pull/153849)

<!--- Backport version: 8.9.7 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sqren/backport)

<!--BACKPORT [{"author":{"name":"Marco Antonio
Ghiani","email":"marcoantonio.ghiani01@gmail.com"},"sourceCommit":{"committedDate":"2023-03-29T07:44:24Z","message":"[Infrastructure
UI] Fix inventory table pagination navigation (#153849)\n\n## 📓
Summary\r\n\r\nCloses #153739 \r\n\r\nEach time the whole inventory
table was rerendering due to a click on an\r\nentry, a new list of items
was regenerated, reinitializing the in-memory\r\ntable component from
the first page.\r\n\r\nMemoizing the generated items solves the issue
and the table work as\r\nexpected.\r\n\r\nThis PR also solve another
issue occurring when multiple table entries\r\nwere clicked, which
resulted in many popovers opened and a blocked UI as\r\nper the
following screenshot:\r\n\r\n<img width=\"1267\"
alt=\"multi-popover\"\r\nsrc=\"https://user-images.githubusercontent.com/34506779/228196645-9c0444b7-9114-47c2-8e5d-0bec29ed5305.png\">\r\n\r\n##
🧪 Testing\r\n- Navigate to `Inventory` and select the `Kubernetes Pods`
option from\r\nthe **Show** filter.\r\n- Switch the view to a table with
the top-right selector\r\n- Verify the popover correctly opens on any
entry of the first table\r\npage, then switch to different pages and
check the behaviour is\r\nmaintained and there are no reinitializations
for the table.\r\n- Verify the same from the `Docker Containers`
list.\r\n\r\n\r\n\r\nhttps://user-images.githubusercontent.com/34506779/228198613-afafe3fe-f714-4c88-a288-fc4c95ca801a.mov\r\n\r\nCo-authored-by:
Marco Antonio Ghiani
<marcoantonio.ghiani@elastic.co>","sha":"f17457b86e2137f8c84171583a5291835c5b7d62","branchLabelMapping":{"^v8.8.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:fix","Team:Infra
Monitoring
UI","backport:prev-minor","v8.8.0"],"number":153849,"url":"https://github.com/elastic/kibana/pull/153849","mergeCommit":{"message":"[Infrastructure
UI] Fix inventory table pagination navigation (#153849)\n\n## 📓
Summary\r\n\r\nCloses #153739 \r\n\r\nEach time the whole inventory
table was rerendering due to a click on an\r\nentry, a new list of items
was regenerated, reinitializing the in-memory\r\ntable component from
the first page.\r\n\r\nMemoizing the generated items solves the issue
and the table work as\r\nexpected.\r\n\r\nThis PR also solve another
issue occurring when multiple table entries\r\nwere clicked, which
resulted in many popovers opened and a blocked UI as\r\nper the
following screenshot:\r\n\r\n<img width=\"1267\"
alt=\"multi-popover\"\r\nsrc=\"https://user-images.githubusercontent.com/34506779/228196645-9c0444b7-9114-47c2-8e5d-0bec29ed5305.png\">\r\n\r\n##
🧪 Testing\r\n- Navigate to `Inventory` and select the `Kubernetes Pods`
option from\r\nthe **Show** filter.\r\n- Switch the view to a table with
the top-right selector\r\n- Verify the popover correctly opens on any
entry of the first table\r\npage, then switch to different pages and
check the behaviour is\r\nmaintained and there are no reinitializations
for the table.\r\n- Verify the same from the `Docker Containers`
list.\r\n\r\n\r\n\r\nhttps://user-images.githubusercontent.com/34506779/228198613-afafe3fe-f714-4c88-a288-fc4c95ca801a.mov\r\n\r\nCo-authored-by:
Marco Antonio Ghiani
<marcoantonio.ghiani@elastic.co>","sha":"f17457b86e2137f8c84171583a5291835c5b7d62"}},"sourceBranch":"main","suggestedTargetBranches":[],"targetPullRequestStates":[{"branch":"main","label":"v8.8.0","labelRegex":"^v8.8.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/153849","number":153849,"mergeCommit":{"message":"[Infrastructure
UI] Fix inventory table pagination navigation (#153849)\n\n## 📓
Summary\r\n\r\nCloses #153739 \r\n\r\nEach time the whole inventory
table was rerendering due to a click on an\r\nentry, a new list of items
was regenerated, reinitializing the in-memory\r\ntable component from
the first page.\r\n\r\nMemoizing the generated items solves the issue
and the table work as\r\nexpected.\r\n\r\nThis PR also solve another
issue occurring when multiple table entries\r\nwere clicked, which
resulted in many popovers opened and a blocked UI as\r\nper the
following screenshot:\r\n\r\n<img width=\"1267\"
alt=\"multi-popover\"\r\nsrc=\"https://user-images.githubusercontent.com/34506779/228196645-9c0444b7-9114-47c2-8e5d-0bec29ed5305.png\">\r\n\r\n##
🧪 Testing\r\n- Navigate to `Inventory` and select the `Kubernetes Pods`
option from\r\nthe **Show** filter.\r\n- Switch the view to a table with
the top-right selector\r\n- Verify the popover correctly opens on any
entry of the first table\r\npage, then switch to different pages and
check the behaviour is\r\nmaintained and there are no reinitializations
for the table.\r\n- Verify the same from the `Docker Containers`
list.\r\n\r\n\r\n\r\nhttps://user-images.githubusercontent.com/34506779/228198613-afafe3fe-f714-4c88-a288-fc4c95ca801a.mov\r\n\r\nCo-authored-by:
Marco Antonio Ghiani
<marcoantonio.ghiani@elastic.co>","sha":"f17457b86e2137f8c84171583a5291835c5b7d62"}}]}]
BACKPORT-->
This commit is contained in:
Marco Antonio Ghiani 2023-03-29 11:24:21 +02:00 committed by GitHub
parent 85a8f79b88
commit da88da012d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 40 additions and 56 deletions

View file

@ -7,8 +7,6 @@
import { APP_WRAPPER_CLASS } from '@kbn/core/public';
export const CONTAINER_CLASSNAME = 'infra-container-element';
export const prepareMountElement = (element: HTMLElement, testSubject?: string) => {
// Ensure all wrapping elements have the APP_WRAPPER_CLASS so that the KinanaPageTemplate works as expected
element.classList.add(APP_WRAPPER_CLASS);

View file

@ -9,7 +9,7 @@ import { EuiButtonEmpty, EuiInMemoryTable, EuiToolTip, EuiBasicTableColumn } fro
import { i18n } from '@kbn/i18n';
import { last, first } from 'lodash';
import React, { useState, useCallback, useEffect } from 'react';
import React, { useState, useMemo } from 'react';
import { EuiPopover } from '@elastic/eui';
import { createWaffleMapNode } from '../lib/nodes_to_wafflemap';
import { InfraWaffleMapNode, InfraWaffleMapOptions } from '../../../../lib/lib';
@ -17,7 +17,6 @@ import { fieldToName } from '../lib/field_to_display_name';
import { NodeContextMenu } from './waffle/node_context_menu';
import { InventoryItemType } from '../../../../../common/inventory_models/types';
import { SnapshotNode, SnapshotNodePath } from '../../../../../common/http_api/snapshot_api';
import { CONTAINER_CLASSNAME } from '../../../../apps/common_styles';
interface Props {
nodes: SnapshotNode[];
@ -28,6 +27,13 @@ interface Props {
onFilter: (filter: string) => void;
}
const initialSorting = {
sort: {
field: 'value',
direction: 'desc',
},
} as const;
const getGroupPaths = (path: SnapshotNodePath[]) => {
switch (path.length) {
case 3:
@ -41,33 +47,10 @@ const getGroupPaths = (path: SnapshotNodePath[]) => {
export const TableView = (props: Props) => {
const { nodes, options, formatter, currentTime, nodeType } = props;
const [openPopovers, setOpenPopovers] = useState<string[]>([]);
const openPopoverFor = useCallback(
(id: string) => () => {
setOpenPopovers([...openPopovers, id]);
},
[openPopovers]
);
const closePopoverFor = useCallback(
(id: string) => () => {
if (openPopovers.includes(id)) {
setOpenPopovers(openPopovers.filter((subject) => subject !== id));
}
},
[openPopovers]
);
const [openPopoverId, setOpenPopoverId] = useState<string | null>(null);
useEffect(() => {
const el = document.getElementsByClassName(CONTAINER_CLASSNAME)[0];
if (el instanceof HTMLElement) {
if (openPopovers.length > 0) {
el.style.overflowY = 'hidden';
} else {
el.style.overflowY = 'auto';
}
}
}, [openPopovers]);
const closePopover = () => setOpenPopoverId(null);
const columns: Array<EuiBasicTableColumn<typeof items[number]>> = [
{
@ -84,15 +67,20 @@ export const TableView = (props: Props) => {
const uniqueID = [...item.node.path.map((p) => p.value), item.node.name].join(':');
const button = (
<EuiToolTip content={tooltipText}>
<EuiButtonEmpty onClick={openPopoverFor(uniqueID)}>{value}</EuiButtonEmpty>
<EuiButtonEmpty
data-test-subj="infraColumnsButton"
onClick={() => setOpenPopoverId(uniqueID)}
>
{value}
</EuiButtonEmpty>
</EuiToolTip>
);
return (
<EuiPopover
button={button}
isOpen={openPopovers.includes(uniqueID)}
closePopover={closePopoverFor(uniqueID)}
isOpen={openPopoverId === uniqueID}
closePopover={closePopover}
anchorPosition="rightCenter"
>
<NodeContextMenu
@ -148,30 +136,28 @@ export const TableView = (props: Props) => {
},
];
const items = nodes.map((node) => {
const name = last(node.path);
const metric = first(node.metrics);
return {
name: (name && name.label) || 'unknown',
...getGroupPaths(node.path).reduce(
(acc, path, index) => ({
...acc,
[`group_${index}`]: path.label,
}),
{}
),
value: (metric && metric.value) || 0,
avg: (metric && metric.avg) || 0,
max: (metric && metric.max) || 0,
node: createWaffleMapNode(node),
};
});
const initialSorting = {
sort: {
field: 'value',
direction: 'desc',
},
} as const;
const items = useMemo(
() =>
nodes.map((node) => {
const name = last(node.path);
const metric = first(node.metrics);
return {
name: (name && name.label) || 'unknown',
...getGroupPaths(node.path).reduce(
(acc, path, index) => ({
...acc,
[`group_${index}`]: path.label,
}),
{}
),
value: (metric && metric.value) || 0,
avg: (metric && metric.avg) || 0,
max: (metric && metric.max) || 0,
node: createWaffleMapNode(node),
};
}),
[nodes]
);
return (
<EuiInMemoryTable pagination={true} sorting={initialSorting} items={items} columns={columns} />