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

Upgrade EUI to v93.1.1 #176762

Merged
merged 9 commits into from
Feb 20, 2024
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@
"@elastic/ecs": "^8.11.1",
"@elastic/elasticsearch": "npm:@elastic/elasticsearch-canary@8.9.1-canary.1",
"@elastic/ems-client": "8.5.1",
"@elastic/eui": "93.0.0",
"@elastic/eui": "93.1.1",
"@elastic/filesaver": "1.1.2",
"@elastic/node-crypto": "1.2.1",
"@elastic/numeral": "^2.5.1",
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -1737,11 +1737,6 @@ export const getEuiContextMapping = (): EuiTokensObject => {
values: { status, number },
description: 'Screen reader text describing the state of a tour step',
}),
'euiTreeView.ariaLabel': ({ nodeLabel, ariaLabel }: EuiValues) =>
i18n.translate('core.euiTreeView.ariaLabel', {
defaultMessage: '{nodeLabel} child of {ariaLabel}',
values: { nodeLabel, ariaLabel },
}),
'euiTreeView.listNavigationInstructions': i18n.translate(
'core.euiTreeView.listNavigationInstructions',
{
Expand Down
2 changes: 1 addition & 1 deletion src/dev/license_checker/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ export const LICENSE_OVERRIDES = {
'jsts@1.6.2': ['Eclipse Distribution License - v 1.0'], // cf. https://github.com/bjornharrtell/jsts
'@mapbox/jsonlint-lines-primitives@2.0.2': ['MIT'], // license in readme https://github.com/tmcw/jsonlint
'@elastic/ems-client@8.5.1': ['Elastic License 2.0'],
'@elastic/eui@93.0.0': ['SSPL-1.0 OR Elastic License 2.0'],
'@elastic/eui@93.1.1': ['SSPL-1.0 OR Elastic License 2.0'],
'language-subtag-registry@0.3.21': ['CC-BY-4.0'], // retired ODC‑By license https://github.com/mattcg/language-subtag-registry
'buffers@0.1.1': ['MIT'], // license in importing module https://www.npmjs.com/package/binary
'@bufbuild/protobuf@1.2.1': ['Apache-2.0'], // license (Apache-2.0 AND BSD-3-Clause)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ export function UnifiedSearchBar({
const onRefreshChange = ({
isPaused,
refreshInterval,
}: OnRefreshChangeProps) => {
}: Partial<OnRefreshChangeProps>) => {
const existingQueryParams = toQuery(location.search);
const updatedQueryParams = {
...existingQueryParams,
Expand Down
6 changes: 6 additions & 0 deletions x-pack/plugins/kubernetes_security/common/translations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ export const TREE_NAVIGATION_LOADING = i18n.translate(
defaultMessage: 'Loading',
}
);
export const TREE_NAVIGATION_EMPTY = i18n.translate(
'xpack.kubernetesSecurity.treeNavigation.empty',
{
defaultMessage: 'No data available',
}
);
export const TREE_NAVIGATION_SHOW_MORE = (name: string) =>
i18n.translate('xpack.kubernetesSecurity.treeNavigation.loadMore', {
values: { name },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ describe('DynamicTreeView component', () => {
},
},
]}
aria-label="Logical Tree View"
onSelect={(selectionDepth, key, type) => {}}
{...props}
/>
Expand Down
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@opauloh Please feel free to pull down and QA this component locally. I'm fairly sure with the local data given that this still looks/works as expected, but would appreciate someone more familiar with production end-usage testing it!

Copy link
Contributor

Choose a reason for hiding this comment

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

Hi @cee-chen

Tested the Kubernetes TreeView with more data and the functionality looks good. There are two clusters with data from other integrations and it now shows the no data available message, thanks for adding that!

I only found one bug, when there were a lot of nested children it gets oddly positioned among the other elements of the tree, here's the screen recording:

Screen.Recording.2024-02-15.at.4.28.21.PM.mov

Tried to quickly figure out what was possibly causing the issue, looks like there's a max block size set to 100vh, and removing it seems to fix the issue.

Screen.Recording.2024-02-15.at.4.29.02.PM.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.

@opauloh 100vh override was pushed up in 740a1fb, let me know if that fixes the issue for you!

Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,24 @@
* 2.0.
*/

import React, { useEffect, useState, useRef, MouseEvent, KeyboardEvent, useMemo } from 'react';
import React, { useEffect, useState, useRef, KeyboardEvent, useMemo } from 'react';
import {
EuiIcon,
EuiTreeView,
EuiText,
EuiI18n,
EuiScreenReaderOnly,
EuiBadge,
keys,
EuiLoadingSpinner,
EuiToolTip,
useEuiTheme,
} from '@elastic/eui';
// @ts-expect-error style types not defined, but they exist
import { euiTreeViewStyles } from '@elastic/eui/lib/components/tree_view/tree_view.styles';

import {
TREE_NAVIGATION_LOADING,
TREE_NAVIGATION_EMPTY,
TREE_NAVIGATION_SHOW_MORE,
} from '../../../../common/translations';
import { useFetchDynamicTreeView } from './hooks';
Expand Down Expand Up @@ -64,17 +69,17 @@ export const DynamicTreeView = ({
onSelect,
selected = '',
expanded = true,
...props
onKeyDown,
}: DynamicTreeViewProps) => {
const styles = useStyles(depth);
const euiStyles = euiTreeViewStyles(useEuiTheme());
const euiTreeViewCss = [euiStyles.euiTreeView, euiStyles.default];

const { indexPattern, setNoResults, setTreeNavSelection } = useTreeViewContext();

const { data, fetchNextPage, isFetchingNextPage, hasNextPage, isLoading } =
useFetchDynamicTreeView(query, tree[depth].key, indexPattern, expanded);

const ariaLabel = props['aria-label'];

const onLoadMoreKeydown = (event: React.KeyboardEvent) => {
switch (event.key) {
case keys.ARROW_DOWN: {
Expand Down Expand Up @@ -135,17 +140,7 @@ export const DynamicTreeView = ({
}, [data?.pages]);

return (
<EuiText
size="s"
className={`euiTreeView__wrapper ${!expanded ? 'euiTreeView__wrapper--hidden' : ''}`}
css={styles.treeViewWrapper(expanded)}
>
{isLoading && (
<div>
<EuiLoadingSpinner size="s" />
<span css={styles.loadMoreTextLeft}>{TREE_NAVIGATION_LOADING}</span>
</div>
)}
<EuiText size="s" css={styles.euiTreeViewWrapper} hidden={!expanded} onKeyDown={onKeyDown}>
{depth === 0 && (
<EuiI18n
token="euiTreeView.listNavigationInstructions"
Expand All @@ -159,10 +154,24 @@ export const DynamicTreeView = ({
</EuiI18n>
)}
<ul
className="euiTreeView"
css={euiTreeViewCss}
aria-describedby={data?.pages?.length ? 'dynamicTreeViewInstructionId' : undefined}
aria-label={ariaLabel}
>
{isLoading && (
<EuiTreeView.Item
id="dynamicTreeViewLoading"
css={styles.nonInteractiveItem}
icon={<EuiLoadingSpinner size="s" />}
label={TREE_NAVIGATION_LOADING}
/>
)}
{!isLoading && !itemList.length && (
<EuiTreeView.Item
id="dynamicTreeViewEmpty"
css={styles.nonInteractiveItem}
label={TREE_NAVIGATION_EMPTY}
/>
)}
{itemList.map((aggData) => {
const queryFilter = {
...query,
Expand All @@ -179,7 +188,6 @@ export const DynamicTreeView = ({
{({ isExpanded, onToggleExpand }) => (
<DynamicTreeViewItem
aggData={aggData}
aria-label={ariaLabel}
depth={depth}
expanded={expanded}
isExpanded={isExpanded}
Expand All @@ -195,26 +203,25 @@ export const DynamicTreeView = ({
);
})}
{hasNextPage && (
<li key="load_more" className="euiTreeView__node" css={styles.loadMoreButtonWrapper}>
<EuiBadge
css={styles.loadMoreButton}
onClickAriaLabel={TREE_NAVIGATION_SHOW_MORE(tree[depth].namePlural)}
data-test-subj={BUTTON_TEST_ID}
onKeyDown={(event: React.KeyboardEvent) => onLoadMoreKeydown(event)}
onClick={onClickNextPageHandler}
>
<span css={styles.loadMoreText}>
<EuiTreeView.Item
id="dynamicTreeViewLoadMore"
css={styles.loadMoreButton}
aria-label={TREE_NAVIGATION_SHOW_MORE(tree[depth].namePlural)}
data-test-subj={BUTTON_TEST_ID}
onKeyDown={(event: React.KeyboardEvent) => onLoadMoreKeydown(event)}
onClick={onClickNextPageHandler}
label={
<EuiBadge
css={styles.loadMoreBadge}
iconSide="right"
iconType={isFetchingNextPage ? EuiLoadingSpinner : 'arrowDown'}
>
{isFetchingNextPage
? TREE_NAVIGATION_LOADING
: TREE_NAVIGATION_SHOW_MORE(tree[depth].namePlural)}
</span>
{isFetchingNextPage ? (
<EuiLoadingSpinner size="s" />
) : (
<EuiIcon size="s" type="arrowDown" />
)}
</EuiBadge>
</li>
</EuiBadge>
}
/>
)}
</ul>
</EuiText>
Expand All @@ -232,10 +239,8 @@ const DynamicTreeViewItem = ({
selected,
expanded,
query,
...props
}: DynamicTreeViewItemProps) => {
const isLastNode = depth === tree.length - 1;
const styles = useStyles(depth);
const buttonRef = useRef<Record<string, any>>({});

const handleSelect = () => {
Expand All @@ -254,17 +259,10 @@ const DynamicTreeViewItem = ({
};

const onButtonToggle = () => {
if (!isLastNode && !isExpanded) {
onToggleExpand();
}
handleSelect();
};

const onArrowToggle = (event: MouseEvent<SVGElement>) => {
disableEventDefaults(event);
if (!isLastNode) {
onToggleExpand();
}
handleSelect();
};

// Enable keyboard navigation
Expand Down Expand Up @@ -303,73 +301,44 @@ const DynamicTreeViewItem = ({
}
};

const isSelected = useMemo(() => {
return (
selected ===
Object.entries({
...selectionDepth,
[tree[depth].type]: aggData.key,
...(tree[depth].type === 'clusterId' &&
aggData.key_as_string && {
clusterName: aggData.key_as_string,
}),
})
.map(([k, v]) => `${k}.${v}`)
.join()
);
}, [aggData.key, aggData.key_as_string, depth, selected, selectionDepth, tree]);

const clusterLevel = BREADCRUMBS_CLUSTER_TREE_VIEW_LEVELS[tree[depth].type];

return (
<li
className={`euiTreeView__node
${isExpanded ? 'euiTreeView__node--expanded' : ''}
${isSelected ? 'euiTreeView__node--selected' : ''}
`}
>
<button
data-test-subj={expanded ? BUTTON_TEST_ID : ''}
className="euiTreeView__nodeInner euiTreeView__nodeInner--withArrows"
onClick={onButtonToggle}
onKeyDown={onKeyDown}
ref={(el) => (buttonRef.current[aggData.key] = el)}
css={isLastNode ? styles.leafNodeButton : undefined}
>
{!isLastNode && (
<EuiIcon
className="euiTreeView__expansionArrow"
type={isExpanded ? 'arrowDown' : 'arrowRight'}
onClick={onArrowToggle}
/>
)}
<TreeViewIcon {...tree[depth].iconProps} css={styles.labelIcon} />
<EuiToolTip content={`${clusterLevel}: ${aggData.key}`}>
<span className="euiTreeView__nodeLabel">{aggData.key_as_string || aggData.key}</span>
<EuiTreeView.Item
id={aggData.key_as_string || `${aggData.key}`}
hasArrow={!isLastNode}
isExpanded={isExpanded}
onClick={onButtonToggle}
onKeyDown={onKeyDown}
icon={<TreeViewIcon {...tree[depth].iconProps} />}
label={
<EuiToolTip anchorClassName="eui-textTruncate" content={`${clusterLevel}: ${aggData.key}`}>
<span>{aggData.key_as_string || aggData.key}</span>
</EuiToolTip>
</button>
<div
onKeyDown={(event: React.KeyboardEvent) => onChildrenKeydown(event, aggData.key.toString())}
>
{!isLastNode && (
<DynamicTreeView
expanded={isExpanded}
query={query}
depth={depth + 1}
selectionDepth={{
...selectionDepth,
[tree[depth].type]: aggData.key,
...(tree[depth].type === 'clusterId' && {
clusterName: aggData.key_as_string,
}),
}}
tree={tree}
onSelect={onSelect}
selected={selected}
aria-label={`${aggData.key} child of ${props['aria-label']}`}
/>
)}
</div>
</li>
}
buttonRef={(el: HTMLButtonElement) => (buttonRef.current[aggData.key] = el)}
data-test-subj={expanded ? BUTTON_TEST_ID : ''}
>
{!isLastNode && (
<DynamicTreeView
expanded={isExpanded}
query={query}
depth={depth + 1}
selectionDepth={{
...selectionDepth,
[tree[depth].type]: aggData.key,
...(tree[depth].type === 'clusterId' && {
clusterName: aggData.key_as_string,
}),
}}
tree={tree}
onSelect={onSelect}
selected={selected}
onKeyDown={(event: React.KeyboardEvent) =>
onChildrenKeydown(event, aggData.key.toString())
}
/>
)}
</EuiTreeView.Item>
);
};
Loading