mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[Actionable Observability] - Rule Details Page - Update tag component to show tags out of the popover as an option (#134468)
* Add spread prop to tag * Use spread prop in Rule Details page * Add unit test for spread prop * Update tag props type * Fix type guard * use generic type to make code cleaner * Updating var name * Update data test obj * [Code Review] Fix lazy import Co-authored-by: Xavier Mouligneau <xavier.mouligneau@elastic.co>
This commit is contained in:
parent
5989f1df49
commit
6aa6a50e30
9 changed files with 76 additions and 37 deletions
|
@ -4,7 +4,7 @@
|
|||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
import React, { useState } from 'react';
|
||||
import React from 'react';
|
||||
import moment from 'moment';
|
||||
import { EuiText, EuiFlexGroup, EuiFlexItem, EuiBadge, EuiSpacer } from '@elastic/eui';
|
||||
import { PageHeaderProps } from '../types';
|
||||
|
@ -14,12 +14,7 @@ import { getHealthColor } from '../../rules/config';
|
|||
|
||||
export function PageTitle({ rule }: PageHeaderProps) {
|
||||
const { triggersActionsUi } = useKibana().services;
|
||||
const [isTagsPopoverOpen, setIsTagsPopoverOpen] = useState<boolean>(false);
|
||||
const tagsClicked = () =>
|
||||
setIsTagsPopoverOpen(
|
||||
(oldStateIsTagsPopoverOpen) => rule.tags.length > 0 && !oldStateIsTagsPopoverOpen
|
||||
);
|
||||
const closeTagsPopover = () => setIsTagsPopoverOpen(false);
|
||||
|
||||
return (
|
||||
<>
|
||||
<EuiFlexGroup alignItems="center">
|
||||
|
@ -37,7 +32,7 @@ export function PageTitle({ rule }: PageHeaderProps) {
|
|||
</EuiText>
|
||||
<EuiSpacer size="s" />
|
||||
</EuiFlexItem>
|
||||
<EuiFlexGroup alignItems="baseline">
|
||||
<EuiFlexGroup direction="column" alignItems="flexStart">
|
||||
<EuiFlexItem component="span" grow={false}>
|
||||
<EuiText color="subdued" size="xs">
|
||||
<b>{LAST_UPDATED_MESSAGE}</b> {BY_WORD} {rule.updatedBy} {ON_WORD}
|
||||
|
@ -46,15 +41,14 @@ export function PageTitle({ rule }: PageHeaderProps) {
|
|||
{moment(rule.createdAt).format('ll')}
|
||||
</EuiText>
|
||||
</EuiFlexItem>
|
||||
|
||||
{rule.tags.length > 0 &&
|
||||
triggersActionsUi.getRuleTagBadge({
|
||||
isOpen: isTagsPopoverOpen,
|
||||
tags: rule.tags,
|
||||
onClick: () => tagsClicked(),
|
||||
onClose: () => closeTagsPopover(),
|
||||
})}
|
||||
<EuiSpacer size="xs" />
|
||||
</EuiFlexGroup>
|
||||
{rule.tags.length > 0 &&
|
||||
triggersActionsUi.getRuleTagBadge<'tagsOutPopover'>({
|
||||
tagsOutPopover: true,
|
||||
tags: rule.tags,
|
||||
})}
|
||||
<EuiSpacer size="xs" />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -199,7 +199,7 @@ function RulesPage() {
|
|||
'data-test-subj': 'rulesTableCell-tagsPopover',
|
||||
render: (ruleTags: string[], item: RuleTableItem) => {
|
||||
return ruleTags.length > 0
|
||||
? triggersActionsUi.getRuleTagBadge({
|
||||
? triggersActionsUi.getRuleTagBadge<'default'>({
|
||||
isOpen: tagPopoverOpenIndex === item.index,
|
||||
tags: ruleTags,
|
||||
onClick: () => setTagPopoverOpenIndex(item.index),
|
||||
|
|
|
@ -40,9 +40,6 @@ export const RuleTagFilter = suspendedComponentWithProps(
|
|||
export const RuleStatusFilter = suspendedComponentWithProps(
|
||||
lazy(() => import('./rules_list/components/rule_status_filter'))
|
||||
);
|
||||
export const RuleTagBadge = suspendedComponentWithProps(
|
||||
lazy(() => import('./rules_list/components/rule_tag_badge'))
|
||||
);
|
||||
export const RuleEventLogList = suspendedComponentWithProps(
|
||||
lazy(() => import('./rule_details/components/rule_event_log_list'))
|
||||
);
|
||||
|
@ -52,3 +49,6 @@ export const RulesList = suspendedComponentWithProps(
|
|||
export const RulesListNotifyBadge = suspendedComponentWithProps(
|
||||
lazy(() => import('./rules_list/components/rules_list_notify_badge'))
|
||||
);
|
||||
export const RuleTagBadge = suspendedComponentWithProps(
|
||||
lazy(() => import('./rules_list/components/rule_tag_badge'))
|
||||
);
|
||||
|
|
|
@ -56,4 +56,12 @@ describe('RuleTagBadge', () => {
|
|||
|
||||
expect(onClickMock).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
it('shows all the tags without clicking when passing "spread" props with "true"', () => {
|
||||
const wrapper = mountWithIntl(<RuleTagBadge tags={tags} tagsOutPopover={true} />);
|
||||
expect(wrapper.find('[data-test-subj="tagsOutPopover"]').exists()).toBeTruthy();
|
||||
expect(wrapper.find('[data-test-subj="ruleTagBadgeItem-a"]').exists()).toBeTruthy();
|
||||
expect(wrapper.find('[data-test-subj="ruleTagBadgeItem-b"]').exists()).toBeTruthy();
|
||||
expect(wrapper.find('[data-test-subj="ruleTagBadgeItem-c"]').exists()).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
import React, { useMemo } from 'react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { EuiPopover, EuiBadge, EuiPopoverTitle } from '@elastic/eui';
|
||||
import { EuiPopover, EuiBadge, EuiPopoverTitle, EuiFlexGroup } from '@elastic/eui';
|
||||
|
||||
const tagTitle = i18n.translate(
|
||||
'xpack.triggersActionsUI.sections.rules_list.rules_tag_badge.tagTitle',
|
||||
|
@ -16,32 +16,43 @@ const tagTitle = i18n.translate(
|
|||
}
|
||||
);
|
||||
|
||||
export interface RuleTagBadgeProps {
|
||||
export type RuleTagBadgeOptions = 'tagsOutPopover' | 'default';
|
||||
|
||||
export interface RuleTagBadgeBasicOptions {
|
||||
isOpen: boolean;
|
||||
tags: string[];
|
||||
onClick: React.MouseEventHandler<HTMLButtonElement>;
|
||||
onClose: () => void;
|
||||
}
|
||||
|
||||
export interface RuleTagBadgeCommonProps {
|
||||
tagsOutPopover?: boolean;
|
||||
tags: string[];
|
||||
badgeDataTestSubj?: string;
|
||||
titleDataTestSubj?: string;
|
||||
tagItemDataTestSubj?: (tag: string) => string;
|
||||
}
|
||||
|
||||
export type RuleTagBadgeProps<T extends RuleTagBadgeOptions = 'default'> = T extends 'default'
|
||||
? RuleTagBadgeBasicOptions & RuleTagBadgeCommonProps
|
||||
: T extends 'tagsOutPopover'
|
||||
? RuleTagBadgeCommonProps
|
||||
: never;
|
||||
|
||||
const containerStyle = {
|
||||
width: '300px',
|
||||
};
|
||||
|
||||
const getTagItemDataTestSubj = (tag: string) => `ruleTagBadgeItem-${tag}`;
|
||||
|
||||
export const RuleTagBadge = (props: RuleTagBadgeProps) => {
|
||||
export const RuleTagBadge = <T extends RuleTagBadgeOptions>(props: RuleTagBadgeProps<T>) => {
|
||||
const {
|
||||
isOpen = false,
|
||||
tagsOutPopover = false,
|
||||
tags = [],
|
||||
onClick,
|
||||
onClose,
|
||||
badgeDataTestSubj = 'ruleTagBadge',
|
||||
titleDataTestSubj = 'ruleTagPopoverTitle',
|
||||
tagItemDataTestSubj = getTagItemDataTestSubj,
|
||||
} = props;
|
||||
const { isOpen, onClose, onClick } = props as RuleTagBadgeBasicOptions;
|
||||
|
||||
const badge = useMemo(() => {
|
||||
return (
|
||||
|
@ -59,7 +70,7 @@ export const RuleTagBadge = (props: RuleTagBadgeProps) => {
|
|||
{tags.length}
|
||||
</EuiBadge>
|
||||
);
|
||||
}, [tags, badgeDataTestSubj, onClick]);
|
||||
}, [badgeDataTestSubj, onClick, tags.length]);
|
||||
|
||||
const tagBadges = useMemo(
|
||||
() =>
|
||||
|
@ -76,9 +87,22 @@ export const RuleTagBadge = (props: RuleTagBadgeProps) => {
|
|||
)),
|
||||
[tags, tagItemDataTestSubj]
|
||||
);
|
||||
if (tagsOutPopover) {
|
||||
return (
|
||||
// Put 0 to fix negative left margin value.
|
||||
<EuiFlexGroup data-test-subj="tagsOutPopover" style={{ marginLeft: 0 }} wrap={true}>
|
||||
{tagBadges}
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<EuiPopover button={badge} anchorPosition="upCenter" isOpen={isOpen} closePopover={onClose}>
|
||||
<EuiPopover
|
||||
button={badge}
|
||||
anchorPosition="upCenter"
|
||||
isOpen={isOpen} // The props exists as it's required in props types
|
||||
closePopover={onClose}
|
||||
>
|
||||
<EuiPopoverTitle data-test-subj={titleDataTestSubj}>{tagTitle}</EuiPopoverTitle>
|
||||
<div style={containerStyle}>{tagBadges}</div>
|
||||
</EuiPopover>
|
||||
|
|
|
@ -6,9 +6,13 @@
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
import {
|
||||
RuleTagBadgeProps,
|
||||
RuleTagBadgeOptions,
|
||||
} from '../application/sections/rules_list/components/rule_tag_badge';
|
||||
import { RuleTagBadge } from '../application/sections';
|
||||
import type { RuleTagBadgeProps } from '../application/sections/rules_list/components/rule_tag_badge';
|
||||
|
||||
export const getRuleTagBadgeLazy = (props: RuleTagBadgeProps) => {
|
||||
export const getRuleTagBadgeLazy = <T extends RuleTagBadgeOptions = 'default'>(
|
||||
props: RuleTagBadgeProps<T>
|
||||
) => {
|
||||
return <RuleTagBadge {...props} />;
|
||||
};
|
||||
|
|
|
@ -21,6 +21,8 @@ import {
|
|||
RuleTypeModel,
|
||||
AlertsTableProps,
|
||||
AlertsTableConfigurationRegistry,
|
||||
RuleTagBadgeOptions,
|
||||
RuleTagBadgeProps,
|
||||
} from './types';
|
||||
import { getAlertsTableLazy } from './common/get_alerts_table';
|
||||
import { getRuleStatusDropdownLazy } from './common/get_rule_status_dropdown';
|
||||
|
@ -90,8 +92,8 @@ function createStartMock(): TriggersAndActionsUIPublicPluginStart {
|
|||
getRuleStatusFilter: (props) => {
|
||||
return getRuleStatusFilterLazy(props);
|
||||
},
|
||||
getRuleTagBadge: (props) => {
|
||||
return getRuleTagBadgeLazy(props);
|
||||
getRuleTagBadge: <T extends RuleTagBadgeOptions>(props: RuleTagBadgeProps<T>) => {
|
||||
return getRuleTagBadgeLazy<T>(props);
|
||||
},
|
||||
getRuleEventLogList: (props) => {
|
||||
return getRuleEventLogListLazy(props);
|
||||
|
|
|
@ -54,6 +54,7 @@ import type {
|
|||
RuleTagFilterProps,
|
||||
RuleStatusFilterProps,
|
||||
RuleTagBadgeProps,
|
||||
RuleTagBadgeOptions,
|
||||
RuleEventLogListProps,
|
||||
RulesListNotifyBadgeProps,
|
||||
AlertsTableConfigurationRegistry,
|
||||
|
@ -98,7 +99,9 @@ export interface TriggersAndActionsUIPublicPluginStart {
|
|||
getRuleStatusDropdown: (props: RuleStatusDropdownProps) => ReactElement<RuleStatusDropdownProps>;
|
||||
getRuleTagFilter: (props: RuleTagFilterProps) => ReactElement<RuleTagFilterProps>;
|
||||
getRuleStatusFilter: (props: RuleStatusFilterProps) => ReactElement<RuleStatusFilterProps>;
|
||||
getRuleTagBadge: (props: RuleTagBadgeProps) => ReactElement<RuleTagBadgeProps>;
|
||||
getRuleTagBadge: <T extends RuleTagBadgeOptions>(
|
||||
props: RuleTagBadgeProps<T>
|
||||
) => ReactElement<RuleTagBadgeProps<T>>;
|
||||
getRuleEventLogList: (props: RuleEventLogListProps) => ReactElement<RuleEventLogListProps>;
|
||||
getRulesListNotifyBadge: (
|
||||
props: RulesListNotifyBadgeProps
|
||||
|
@ -305,7 +308,7 @@ export class Plugin
|
|||
getRuleStatusFilter: (props: RuleStatusFilterProps) => {
|
||||
return getRuleStatusFilterLazy(props);
|
||||
},
|
||||
getRuleTagBadge: (props: RuleTagBadgeProps) => {
|
||||
getRuleTagBadge: <T extends RuleTagBadgeOptions>(props: RuleTagBadgeProps<T>) => {
|
||||
return getRuleTagBadgeLazy(props);
|
||||
},
|
||||
getRuleEventLogList: (props: RuleEventLogListProps) => {
|
||||
|
|
|
@ -50,7 +50,10 @@ import { TypeRegistry } from './application/type_registry';
|
|||
import type { ComponentOpts as RuleStatusDropdownProps } from './application/sections/rules_list/components/rule_status_dropdown';
|
||||
import type { RuleTagFilterProps } from './application/sections/rules_list/components/rule_tag_filter';
|
||||
import type { RuleStatusFilterProps } from './application/sections/rules_list/components/rule_status_filter';
|
||||
import type { RuleTagBadgeProps } from './application/sections/rules_list/components/rule_tag_badge';
|
||||
import type {
|
||||
RuleTagBadgeProps,
|
||||
RuleTagBadgeOptions,
|
||||
} from './application/sections/rules_list/components/rule_tag_badge';
|
||||
import type { RuleEventLogListProps } from './application/sections/rule_details/components/rule_event_log_list';
|
||||
import type { CreateConnectorFlyoutProps } from './application/sections/action_connector_form/create_connector_flyout';
|
||||
import type { EditConnectorFlyoutProps } from './application/sections/action_connector_form/edit_connector_flyout';
|
||||
|
@ -90,6 +93,7 @@ export type {
|
|||
RuleTagFilterProps,
|
||||
RuleStatusFilterProps,
|
||||
RuleTagBadgeProps,
|
||||
RuleTagBadgeOptions,
|
||||
RuleEventLogListProps,
|
||||
CreateConnectorFlyoutProps,
|
||||
EditConnectorFlyoutProps,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue