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

[8.13] [Security Solution] Fix rule filters on the Rule Details page (#177081) #177242

Merged
merged 1 commit into from
Feb 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { useEuiTheme } from '@elastic/eui';
import { css } from '@emotion/css';
import { useMemo } from 'react';

export const useFiltersStyles = () => {
return useMemo(
() => ({
flexGroup: css`
max-width: 600px;
`,
}),
[]
);
};

export const useQueryStyles = () => {
return useMemo(
() => ({
content: css`
white-space: pre-wrap;
`,
}),
[]
);
};

export const useRequiredFieldsStyles = () => {
const { euiTheme } = useEuiTheme();
return useMemo(
() => ({
fieldTypeText: css({
fontFamily: euiTheme.font.familyCode,
display: 'inline',
}),
}),
[euiTheme.font.familyCode]
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,13 @@

import React from 'react';
import { isEmpty } from 'lodash/fp';
import styled from 'styled-components';
import {
EuiDescriptionList,
EuiText,
EuiFlexGrid,
EuiFlexItem,
EuiFlexGroup,
EuiLoadingSpinner,
EuiBadge,
} from '@elastic/eui';
import type { EuiDescriptionListProps } from '@elastic/eui';
import type {
Expand All @@ -25,9 +23,10 @@ import type {
import type { Filter } from '@kbn/es-query';
import type { SavedQuery } from '@kbn/data-plugin/public';
import { mapAndFlattenFilters } from '@kbn/data-plugin/public';
import type { DataView } from '@kbn/data-views-plugin/public';
import { FieldIcon } from '@kbn/react-field';
import { castEsToKbnFieldTypeName } from '@kbn/field-types';
import { FilterBadgeGroup } from '@kbn/unified-search-plugin/public';
import { FilterItems } from '@kbn/unified-search-plugin/public';
import type {
AlertSuppressionMissingFieldsStrategy,
RequiredFieldArray,
Expand Down Expand Up @@ -55,6 +54,11 @@ import { BadgeList } from './badge_list';
import { DEFAULT_DESCRIPTION_LIST_COLUMN_WIDTHS } from './constants';
import * as i18n from './translations';
import { useAlertSuppression } from '../../logic/use_alert_suppression';
import {
useFiltersStyles,
useQueryStyles,
useRequiredFieldsStyles,
} from './rule_definition_section.styles';

interface SavedQueryNameProps {
savedQueryName: string;
Expand All @@ -66,12 +70,6 @@ const SavedQueryName = ({ savedQueryName }: SavedQueryNameProps) => (
</EuiText>
);

const EuiBadgeWrap = styled(EuiBadge)`
.euiBadge__text {
white-space: pre-wrap !important;
}
`;

interface FiltersProps {
filters: Filter[];
dataViewId?: string;
Expand All @@ -80,51 +78,42 @@ interface FiltersProps {
}

const Filters = ({ filters, dataViewId, index, 'data-test-subj': dataTestSubj }: FiltersProps) => {
const flattenedFilters = mapAndFlattenFilters(filters);

const { indexPattern } = useRuleIndexPattern({
dataSourceType: dataViewId ? DataSourceType.DataView : DataSourceType.IndexPatterns,
index: index ?? [],
dataViewId,
});

const flattenedFilters = mapAndFlattenFilters(filters);
const styles = useFiltersStyles();

return (
<EuiFlexGroup wrap responsive={false} gutterSize="xs" data-test-subj={dataTestSubj}>
{flattenedFilters.map((filter, idx) => {
const displayContent = filter.meta.alias ? (
filter.meta.alias
) : (
<FilterBadgeGroup filters={[filter]} dataViews={[indexPattern]} />
);
return (
<EuiFlexItem
grow={false}
key={`filter-${idx}`}
css={{ width: '100%' }}
data-test-subj={`filterItem-${filter.meta.key}`}
>
<EuiBadgeWrap color="hollow">
{indexPattern != null ? displayContent : <EuiLoadingSpinner size="m" />}
</EuiBadgeWrap>
</EuiFlexItem>
);
})}
<EuiFlexGroup
data-test-subj={dataTestSubj}
className={styles.flexGroup}
wrap
responsive={false}
gutterSize="xs"
>
<FilterItems filters={flattenedFilters} indexPatterns={[indexPattern as DataView]} readOnly />
</EuiFlexGroup>
);
};

const QueryContent = styled.div`
white-space: pre-wrap;
`;

interface QueryProps {
query: string;
'data-test-subj'?: string;
}

const Query = ({ query, 'data-test-subj': dataTestSubj = 'query' }: QueryProps) => (
<QueryContent data-test-subj={dataTestSubj}>{query}</QueryContent>
);
const Query = ({ query, 'data-test-subj': dataTestSubj = 'query' }: QueryProps) => {
const styles = useQueryStyles();
return (
<div data-test-subj={dataTestSubj} className={styles.content}>
{query}
</div>
);
};

interface IndexProps {
index: string[];
Expand Down Expand Up @@ -260,42 +249,40 @@ const RuleType = ({ type }: RuleTypeProps) => (
<EuiText size="s">{getRuleTypeDescription(type)}</EuiText>
);

const StyledFieldTypeText = styled(EuiText)`
font-size: ${({ theme }) => theme.eui.euiFontSizeXS};
font-family: ${({ theme }) => theme.eui.euiCodeFontFamily};
display: inline;
`;

interface RequiredFieldsProps {
requiredFields: RequiredFieldArray;
}

const RequiredFields = ({ requiredFields }: RequiredFieldsProps) => (
<EuiFlexGrid gutterSize={'s'} data-test-subj="requiredFieldsPropertyValue">
{requiredFields.map((rF, index) => (
<EuiFlexItem grow={false} key={rF.name}>
<EuiFlexGroup alignItems="center" gutterSize={'xs'}>
<EuiFlexItem grow={false}>
<FieldIcon
data-test-subj="field-type-icon"
type={castEsToKbnFieldTypeName(rF.type)}
label={rF.type}
/>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<StyledFieldTypeText
grow={false}
size={'s'}
data-test-subj="requiredFieldsPropertyValueItem"
>
{` ${rF.name}${index + 1 !== requiredFields.length ? ', ' : ''}`}
</StyledFieldTypeText>
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlexItem>
))}
</EuiFlexGrid>
);
const RequiredFields = ({ requiredFields }: RequiredFieldsProps) => {
const styles = useRequiredFieldsStyles();
return (
<EuiFlexGrid data-test-subj="requiredFieldsPropertyValue" gutterSize={'s'}>
{requiredFields.map((rF, index) => (
<EuiFlexItem grow={false} key={rF.name}>
<EuiFlexGroup alignItems="center" gutterSize={'xs'}>
<EuiFlexItem grow={false}>
<FieldIcon
data-test-subj="field-type-icon"
type={castEsToKbnFieldTypeName(rF.type)}
label={rF.type}
/>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiText
data-test-subj="requiredFieldsPropertyValueItem"
className={styles.fieldTypeText}
grow={false}
size="xs"
>
{` ${rF.name}${index + 1 !== requiredFields.length ? ', ' : ''}`}
</EuiText>
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlexItem>
))}
</EuiFlexGrid>
);
};

interface TimelineTitleProps {
timelineTitle: string;
Expand Down
Loading