mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[Observability:RulesPage] [TriggerActions:RulesList] Allow filtering of Rules via Rule Param (#154258)
Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
e41936662e
commit
cd90b11e97
12 changed files with 214 additions and 95 deletions
|
@ -62,14 +62,16 @@ export function RulesPage() {
|
|||
useHashQuery: false,
|
||||
});
|
||||
|
||||
const { lastResponse, search, status, type } = urlStateStorage.get<{
|
||||
const { lastResponse, params, search, status, type } = urlStateStorage.get<{
|
||||
lastResponse: string[];
|
||||
params: Record<string, string | number | object>;
|
||||
search: string;
|
||||
status: RuleStatus[];
|
||||
type: string[];
|
||||
}>('_a') || { lastResponse: [], search: '', status: [], type: [] };
|
||||
}>('_a') || { lastResponse: [], params: {}, search: '', status: [], type: [] };
|
||||
|
||||
const [stateLastResponse, setLastResponse] = useState<string[]>(lastResponse);
|
||||
const [stateParams, setParams] = useState<Record<string, string | number | object>>(params);
|
||||
const [stateSearch, setSearch] = useState<string>(search);
|
||||
const [stateStatus, setStatus] = useState<RuleStatus[]>(status);
|
||||
const [stateType, setType] = useState<string[]>(type);
|
||||
|
@ -80,23 +82,28 @@ export function RulesPage() {
|
|||
|
||||
const handleStatusFilterChange = (newStatus: RuleStatus[]) => {
|
||||
setStatus(newStatus);
|
||||
urlStateStorage.set('_a', { lastResponse, search, status: newStatus, type });
|
||||
urlStateStorage.set('_a', { lastResponse, params, search, status: newStatus, type });
|
||||
};
|
||||
|
||||
const handleLastRunOutcomeFilterChange = (newLastResponse: string[]) => {
|
||||
setRefresh(new Date());
|
||||
setLastResponse(newLastResponse);
|
||||
urlStateStorage.set('_a', { lastResponse: newLastResponse, search, status, type });
|
||||
urlStateStorage.set('_a', { lastResponse: newLastResponse, params, search, status, type });
|
||||
};
|
||||
|
||||
const handleTypeFilterChange = (newType: string[]) => {
|
||||
setType(newType);
|
||||
urlStateStorage.set('_a', { lastResponse, search, status, type: newType });
|
||||
urlStateStorage.set('_a', { lastResponse, params, search, status, type: newType });
|
||||
};
|
||||
|
||||
const handleSearchFilterChange = (newSearch: string) => {
|
||||
setSearch(newSearch);
|
||||
urlStateStorage.set('_a', { lastResponse, search: newSearch, status, type });
|
||||
urlStateStorage.set('_a', { lastResponse, params, search: newSearch, status, type });
|
||||
};
|
||||
|
||||
const handleRuleParamFilterChange = (newParams: Record<string, string | number | object>) => {
|
||||
setParams(newParams);
|
||||
urlStateStorage.set('_a', { lastResponse, params: newParams, search, status, type });
|
||||
};
|
||||
|
||||
return (
|
||||
|
@ -143,6 +150,7 @@ export function RulesPage() {
|
|||
refresh={stateRefresh}
|
||||
ruleDetailsRoute="alerts/rules/:ruleId"
|
||||
rulesListKey="observability_rulesListColumns"
|
||||
ruleParamFilter={stateParams}
|
||||
showActionFilter={false}
|
||||
statusFilter={stateStatus}
|
||||
searchFilter={stateSearch}
|
||||
|
@ -155,6 +163,7 @@ export function RulesPage() {
|
|||
'ruleExecutionState',
|
||||
]}
|
||||
onLastRunOutcomeFilterChange={handleLastRunOutcomeFilterChange}
|
||||
onRuleParamFilterChange={handleRuleParamFilterChange}
|
||||
onSearchFilterChange={handleSearchFilterChange}
|
||||
onStatusFilterChange={handleStatusFilterChange}
|
||||
onTypeFilterChange={handleTypeFilterChange}
|
||||
|
|
|
@ -68,6 +68,7 @@ describe('useLoadRuleAggregations', () => {
|
|||
ruleExecutionStatuses: [],
|
||||
ruleLastRunOutcomes: [],
|
||||
ruleStatuses: [],
|
||||
ruleParams: {},
|
||||
tags: [],
|
||||
},
|
||||
enabled: true,
|
||||
|
@ -105,6 +106,7 @@ describe('useLoadRuleAggregations', () => {
|
|||
types: ['type1', 'type2'],
|
||||
actionTypes: ['action1', 'action2'],
|
||||
ruleExecutionStatuses: ['status1', 'status2'],
|
||||
ruleParams: {},
|
||||
ruleStatuses: ['enabled', 'snoozed'] as RuleStatus[],
|
||||
tags: ['tag1', 'tag2'],
|
||||
ruleLastRunOutcomes: ['outcome1', 'outcome2'],
|
||||
|
@ -145,6 +147,7 @@ describe('useLoadRuleAggregations', () => {
|
|||
types: [],
|
||||
actionTypes: [],
|
||||
ruleExecutionStatuses: [],
|
||||
ruleParams: {},
|
||||
ruleLastRunOutcomes: [],
|
||||
ruleStatuses: [],
|
||||
tags: [],
|
||||
|
|
|
@ -272,6 +272,7 @@ describe('useLoadRules', () => {
|
|||
types: [],
|
||||
actionTypes: [],
|
||||
ruleExecutionStatuses: [],
|
||||
ruleParams: {},
|
||||
ruleLastRunOutcomes: [],
|
||||
ruleStatuses: [],
|
||||
tags: [],
|
||||
|
@ -328,6 +329,7 @@ describe('useLoadRules', () => {
|
|||
types: ['type1', 'type2'],
|
||||
actionTypes: ['action1', 'action2'],
|
||||
ruleExecutionStatuses: ['status1', 'status2'],
|
||||
ruleParams: {},
|
||||
ruleLastRunOutcomes: ['outcome1', 'outcome2'],
|
||||
ruleStatuses: ['enabled', 'snoozed'] as RuleStatus[],
|
||||
tags: ['tag1', 'tag2'],
|
||||
|
@ -355,6 +357,7 @@ describe('useLoadRules', () => {
|
|||
actionTypesFilter: ['action1', 'action2'],
|
||||
ruleExecutionStatusesFilter: ['status1', 'status2'],
|
||||
ruleLastRunOutcomesFilter: ['outcome1', 'outcome2'],
|
||||
ruleParamsFilter: {},
|
||||
ruleStatusesFilter: ['enabled', 'snoozed'],
|
||||
tagsFilter: ['tag1', 'tag2'],
|
||||
sort: { field: 'name', direction: 'asc' },
|
||||
|
@ -378,6 +381,7 @@ describe('useLoadRules', () => {
|
|||
types: [],
|
||||
actionTypes: [],
|
||||
ruleExecutionStatuses: [],
|
||||
ruleParams: {},
|
||||
ruleLastRunOutcomes: [],
|
||||
ruleStatuses: [],
|
||||
tags: [],
|
||||
|
@ -415,6 +419,7 @@ describe('useLoadRules', () => {
|
|||
types: [],
|
||||
actionTypes: [],
|
||||
ruleExecutionStatuses: [],
|
||||
ruleParams: {},
|
||||
ruleLastRunOutcomes: [],
|
||||
ruleStatuses: [],
|
||||
tags: [],
|
||||
|
@ -444,6 +449,7 @@ describe('useLoadRules', () => {
|
|||
types: [],
|
||||
actionTypes: [],
|
||||
ruleExecutionStatuses: [],
|
||||
ruleParams: {},
|
||||
ruleLastRunOutcomes: [],
|
||||
ruleStatuses: [],
|
||||
tags: [],
|
||||
|
@ -477,6 +483,7 @@ describe('useLoadRules', () => {
|
|||
types: ['some-kind-of-filter'],
|
||||
actionTypes: [],
|
||||
ruleExecutionStatuses: [],
|
||||
ruleParams: {},
|
||||
ruleLastRunOutcomes: [],
|
||||
ruleStatuses: [],
|
||||
tags: [],
|
||||
|
|
|
@ -44,6 +44,7 @@ export const useLoadRulesQuery = (props: UseLoadRulesQueryProps) => {
|
|||
filters.actionTypes,
|
||||
filters.ruleStatuses,
|
||||
filters.ruleLastRunOutcomes,
|
||||
filters.ruleParams,
|
||||
page,
|
||||
sort,
|
||||
{
|
||||
|
@ -59,6 +60,7 @@ export const useLoadRulesQuery = (props: UseLoadRulesQueryProps) => {
|
|||
actionTypesFilter: filters.actionTypes,
|
||||
ruleExecutionStatusesFilter: filters.ruleExecutionStatuses,
|
||||
ruleLastRunOutcomesFilter: filters.ruleLastRunOutcomes,
|
||||
ruleParamsFilter: filters.ruleParams,
|
||||
ruleStatusesFilter: filters.ruleStatuses,
|
||||
tagsFilter: filters.tags,
|
||||
sort,
|
||||
|
|
|
@ -13,6 +13,7 @@ export const mapFiltersToKueryNode = ({
|
|||
actionTypesFilter,
|
||||
ruleExecutionStatusesFilter,
|
||||
ruleLastRunOutcomesFilter,
|
||||
ruleParamsFilter,
|
||||
ruleStatusesFilter,
|
||||
tagsFilter,
|
||||
searchText,
|
||||
|
@ -22,6 +23,7 @@ export const mapFiltersToKueryNode = ({
|
|||
tagsFilter?: string[];
|
||||
ruleExecutionStatusesFilter?: string[];
|
||||
ruleLastRunOutcomesFilter?: string[];
|
||||
ruleParamsFilter?: Record<string, string | number | object>;
|
||||
ruleStatusesFilter?: RuleStatus[];
|
||||
searchText?: string;
|
||||
}): KueryNode | null => {
|
||||
|
@ -63,6 +65,19 @@ export const mapFiltersToKueryNode = ({
|
|||
);
|
||||
}
|
||||
|
||||
if (ruleParamsFilter && Object.keys(ruleParamsFilter).length) {
|
||||
filterKueryNode.push(
|
||||
nodeBuilder.and(
|
||||
Object.keys(ruleParamsFilter).map((ruleParam) =>
|
||||
nodeBuilder.is(
|
||||
`alert.attributes.params.${ruleParam}`,
|
||||
String(ruleParamsFilter[ruleParam])
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (ruleStatusesFilter && ruleStatusesFilter.length) {
|
||||
const snoozedFilter = nodeBuilder.or([
|
||||
fromKueryExpression('alert.attributes.muteAll: true'),
|
||||
|
|
|
@ -19,6 +19,7 @@ export interface LoadRulesProps {
|
|||
tagsFilter?: string[];
|
||||
ruleExecutionStatusesFilter?: string[];
|
||||
ruleLastRunOutcomesFilter?: string[];
|
||||
ruleParamsFilter?: Record<string, string | number | object>;
|
||||
ruleStatusesFilter?: RuleStatus[];
|
||||
sort?: Sorting;
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ export async function loadRulesWithKueryFilter({
|
|||
actionTypesFilter,
|
||||
ruleExecutionStatusesFilter,
|
||||
ruleLastRunOutcomesFilter,
|
||||
ruleParamsFilter,
|
||||
ruleStatusesFilter,
|
||||
tagsFilter,
|
||||
sort = { field: 'name', direction: 'asc' },
|
||||
|
@ -34,6 +35,7 @@ export async function loadRulesWithKueryFilter({
|
|||
tagsFilter,
|
||||
ruleExecutionStatusesFilter,
|
||||
ruleLastRunOutcomesFilter,
|
||||
ruleParamsFilter,
|
||||
ruleStatusesFilter,
|
||||
searchText,
|
||||
});
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
/* eslint-disable react-hooks/exhaustive-deps */
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { capitalize, isEmpty, sortBy } from 'lodash';
|
||||
import { capitalize, isEmpty, isEqual, sortBy } from 'lodash';
|
||||
import { KueryNode } from '@kbn/es-query';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import React, {
|
||||
|
@ -75,6 +75,7 @@ import './rules_list.scss';
|
|||
import { CreateRuleButton } from './create_rule_button';
|
||||
import { ManageLicenseModal } from './manage_license_modal';
|
||||
import { getIsExperimentalFeatureEnabled } from '../../../../common/get_experimental_features';
|
||||
import { RulesListClearRuleFilterBanner } from './rules_list_clear_rule_filter_banner';
|
||||
import { RulesListTable, convertRulesToTableItems } from './rules_list_table';
|
||||
import { RulesListDocLink } from './rules_list_doc_link';
|
||||
import { UpdateApiKeyModalConfirmation } from '../../../components/update_api_key_modal_confirmation';
|
||||
|
@ -107,23 +108,26 @@ const RuleEdit = lazy(() => import('../../rule_form/rule_edit'));
|
|||
|
||||
export interface RulesListProps {
|
||||
filteredRuleTypes?: string[];
|
||||
showActionFilter?: boolean;
|
||||
ruleDetailsRoute?: string;
|
||||
showCreateRuleButtonInPrompt?: boolean;
|
||||
setHeaderActions?: (components?: React.ReactNode[]) => void;
|
||||
statusFilter?: RuleStatus[];
|
||||
onStatusFilterChange?: (status: RuleStatus[]) => void;
|
||||
lastResponseFilter?: string[];
|
||||
onLastResponseFilterChange?: (lastResponse: string[]) => void;
|
||||
lastRunOutcomeFilter?: string[];
|
||||
onLastRunOutcomeFilterChange?: (lastRunOutcome: string[]) => void;
|
||||
typeFilter?: string[];
|
||||
onTypeFilterChange?: (type: string[]) => void;
|
||||
searchFilter?: string;
|
||||
onSearchFilterChange?: (search: string) => void;
|
||||
refresh?: Date;
|
||||
ruleDetailsRoute?: string;
|
||||
ruleParamFilter?: Record<string, string | number | object>;
|
||||
rulesListKey?: string;
|
||||
searchFilter?: string;
|
||||
showActionFilter?: boolean;
|
||||
showCreateRuleButtonInPrompt?: boolean;
|
||||
showSearchBar?: boolean;
|
||||
statusFilter?: RuleStatus[];
|
||||
typeFilter?: string[];
|
||||
visibleColumns?: string[];
|
||||
onLastResponseFilterChange?: (lastResponse: string[]) => void;
|
||||
onLastRunOutcomeFilterChange?: (lastRunOutcome: string[]) => void;
|
||||
onRuleParamFilterChange?: (ruleParams: Record<string, string | number | object>) => void;
|
||||
onSearchFilterChange?: (search: string) => void;
|
||||
onStatusFilterChange?: (status: RuleStatus[]) => void;
|
||||
onTypeFilterChange?: (type: string[]) => void;
|
||||
setHeaderActions?: (components?: React.ReactNode[]) => void;
|
||||
}
|
||||
|
||||
export const percentileFields = {
|
||||
|
@ -142,47 +146,51 @@ const EMPTY_ARRAY: string[] = [];
|
|||
|
||||
export const RulesList = ({
|
||||
filteredRuleTypes = EMPTY_ARRAY,
|
||||
showActionFilter = true,
|
||||
ruleDetailsRoute,
|
||||
showCreateRuleButtonInPrompt = false,
|
||||
statusFilter,
|
||||
onStatusFilterChange,
|
||||
lastResponseFilter,
|
||||
onLastResponseFilterChange,
|
||||
lastRunOutcomeFilter,
|
||||
onLastRunOutcomeFilterChange,
|
||||
refresh,
|
||||
ruleDetailsRoute,
|
||||
ruleParamFilter,
|
||||
rulesListKey,
|
||||
searchFilter = '',
|
||||
onSearchFilterChange,
|
||||
showActionFilter = true,
|
||||
showCreateRuleButtonInPrompt = false,
|
||||
showSearchBar = true,
|
||||
statusFilter,
|
||||
typeFilter,
|
||||
visibleColumns,
|
||||
onLastResponseFilterChange,
|
||||
onLastRunOutcomeFilterChange,
|
||||
onRuleParamFilterChange,
|
||||
onSearchFilterChange,
|
||||
onStatusFilterChange,
|
||||
onTypeFilterChange,
|
||||
setHeaderActions,
|
||||
refresh,
|
||||
rulesListKey,
|
||||
visibleColumns,
|
||||
}: RulesListProps) => {
|
||||
const history = useHistory();
|
||||
const {
|
||||
http,
|
||||
notifications: { toasts },
|
||||
application: { capabilities },
|
||||
ruleTypeRegistry,
|
||||
actionTypeRegistry,
|
||||
application: { capabilities },
|
||||
http,
|
||||
kibanaFeatures,
|
||||
notifications: { toasts },
|
||||
ruleTypeRegistry,
|
||||
} = useKibana().services;
|
||||
const canExecuteActions = hasExecuteActionsCapability(capabilities);
|
||||
const [isPerformingAction, setIsPerformingAction] = useState<boolean>(false);
|
||||
const [page, setPage] = useState<Pagination>({ index: 0, size: DEFAULT_SEARCH_PAGE_SIZE });
|
||||
const [inputText, setInputText] = useState<string>(searchFilter);
|
||||
|
||||
const [filters, setFilters] = useState<RulesListFilters>(() => ({
|
||||
searchText: searchFilter || '',
|
||||
types: typeFilter || [],
|
||||
const [filters, setFilters] = useState<RulesListFilters>({
|
||||
actionTypes: [],
|
||||
ruleExecutionStatuses: lastResponseFilter || [],
|
||||
ruleLastRunOutcomes: lastRunOutcomeFilter || [],
|
||||
ruleParams: ruleParamFilter || {},
|
||||
ruleStatuses: statusFilter || [],
|
||||
searchText: searchFilter || '',
|
||||
tags: [],
|
||||
}));
|
||||
types: typeFilter || [],
|
||||
});
|
||||
|
||||
const [ruleFlyoutVisible, setRuleFlyoutVisibility] = useState<boolean>(false);
|
||||
const [editFlyoutVisible, setEditFlyoutVisibility] = useState<boolean>(false);
|
||||
|
@ -357,6 +365,9 @@ export const RulesList = ({
|
|||
case 'ruleLastRunOutcomes':
|
||||
onLastRunOutcomeFilterChange?.(value as string[]);
|
||||
break;
|
||||
case 'ruleParams':
|
||||
onRuleParamFilterChange?.(value as Record<string, string | number | object>);
|
||||
break;
|
||||
case 'searchText':
|
||||
onSearchFilterChange?.(value as string);
|
||||
break;
|
||||
|
@ -389,6 +400,8 @@ export const RulesList = ({
|
|||
[setFilters, handleUpdateFiltersEffect]
|
||||
);
|
||||
|
||||
const handleClearRuleParamFilter = () => updateFilters({ filter: 'ruleParams', value: {} });
|
||||
|
||||
useEffect(() => {
|
||||
if (statusFilter) {
|
||||
updateFilters({ filter: 'ruleStatuses', value: statusFilter });
|
||||
|
@ -407,6 +420,12 @@ export const RulesList = ({
|
|||
}
|
||||
}, [lastRunOutcomeFilter]);
|
||||
|
||||
useEffect(() => {
|
||||
if (ruleParamFilter && !isEqual(ruleParamFilter, filters.ruleParams)) {
|
||||
updateFilters({ filter: 'ruleParams', value: ruleParamFilter });
|
||||
}
|
||||
}, [ruleParamFilter]);
|
||||
|
||||
useEffect(() => {
|
||||
if (typeof searchFilter === 'string') {
|
||||
updateFilters({ filter: 'searchText', value: searchFilter });
|
||||
|
@ -783,26 +802,36 @@ export const RulesList = ({
|
|||
/>
|
||||
)}
|
||||
<EuiSpacer size="xs" />
|
||||
|
||||
{showSearchBar && !isEmpty(filters.ruleParams) ? (
|
||||
<RulesListClearRuleFilterBanner onClickClearFilter={handleClearRuleParamFilter} />
|
||||
) : null}
|
||||
|
||||
{showRulesList && (
|
||||
<>
|
||||
<RulesListFiltersBar
|
||||
inputText={inputText}
|
||||
filters={filters}
|
||||
showActionFilter={showActionFilter}
|
||||
rulesStatusesTotal={rulesStatusesTotal}
|
||||
rulesLastRunOutcomesTotal={rulesLastRunOutcomesTotal}
|
||||
tags={tags}
|
||||
filterOptions={filterOptions}
|
||||
actionTypes={actionTypes}
|
||||
lastUpdate={lastUpdate}
|
||||
showErrors={showErrors}
|
||||
updateFilters={updateFilters}
|
||||
setInputText={setInputText}
|
||||
onClearSelection={onClearSelection}
|
||||
onRefreshRules={refreshRules}
|
||||
onToggleRuleErrors={toggleRuleErrors}
|
||||
/>
|
||||
<EuiSpacer size="s" />
|
||||
{showSearchBar ? (
|
||||
<>
|
||||
<RulesListFiltersBar
|
||||
actionTypes={actionTypes}
|
||||
filterOptions={filterOptions}
|
||||
filters={filters}
|
||||
inputText={inputText}
|
||||
lastUpdate={lastUpdate}
|
||||
rulesLastRunOutcomesTotal={rulesLastRunOutcomesTotal}
|
||||
rulesStatusesTotal={rulesStatusesTotal}
|
||||
setInputText={setInputText}
|
||||
showActionFilter={showActionFilter}
|
||||
showErrors={showErrors}
|
||||
tags={tags}
|
||||
updateFilters={updateFilters}
|
||||
onClearSelection={onClearSelection}
|
||||
onRefreshRules={refreshRules}
|
||||
onToggleRuleErrors={toggleRuleErrors}
|
||||
/>
|
||||
<EuiSpacer size="s" />
|
||||
</>
|
||||
) : null}
|
||||
|
||||
<RulesListTable
|
||||
items={tableItems}
|
||||
isLoading={isRulesTableLoading}
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* 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 React from 'react';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import { EuiCallOut, EuiIcon, EuiLink, EuiSpacer } from '@elastic/eui';
|
||||
|
||||
interface RulesListClearRuleFilterProps {
|
||||
onClickClearFilter: () => void;
|
||||
}
|
||||
|
||||
export const RulesListClearRuleFilterBanner = ({
|
||||
onClickClearFilter,
|
||||
}: RulesListClearRuleFilterProps) => {
|
||||
return (
|
||||
<>
|
||||
<EuiCallOut color="primary" size="s" data-test-subj="rulesListClearRuleFilterBanner">
|
||||
<p>
|
||||
<EuiIcon color="primary" type="iInCircle" />{' '}
|
||||
<FormattedMessage
|
||||
id="xpack.triggersActionsUI.sections.rulesList.ruleParamBannerTitle"
|
||||
defaultMessage="Rule list filtered by url parameters."
|
||||
/>{' '}
|
||||
<EuiLink color="primary" onClick={onClickClearFilter}>
|
||||
<FormattedMessage
|
||||
id="xpack.triggersActionsUI.sections.rulesList.ruleParamBannerButton"
|
||||
defaultMessage="Show all"
|
||||
/>
|
||||
</EuiLink>
|
||||
</p>
|
||||
</EuiCallOut>
|
||||
<EuiSpacer size="s" />
|
||||
</>
|
||||
);
|
||||
};
|
|
@ -6,16 +6,16 @@
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import {
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiButton,
|
||||
EuiFilterGroup,
|
||||
EuiFieldSearch,
|
||||
EuiSpacer,
|
||||
EuiLink,
|
||||
EuiFieldSearch,
|
||||
} from '@elastic/eui';
|
||||
import { ActionType, RulesListFilters, UpdateFiltersProps } from '../../../../types';
|
||||
import { getIsExperimentalFeatureEnabled } from '../../../../common/get_experimental_features';
|
||||
|
@ -29,43 +29,42 @@ import { ActionTypeFilter } from './action_type_filter';
|
|||
import { RuleTagFilter } from './rule_tag_filter';
|
||||
import { RuleStatusFilter } from './rule_status_filter';
|
||||
|
||||
const ENTER_KEY = 13;
|
||||
|
||||
interface RulesListFiltersBarProps {
|
||||
inputText: string;
|
||||
filters: RulesListFilters;
|
||||
showActionFilter: boolean;
|
||||
rulesStatusesTotal: Record<string, number>;
|
||||
rulesLastRunOutcomesTotal: Record<string, number>;
|
||||
tags: string[];
|
||||
filterOptions: TypeFilterProps['options'];
|
||||
actionTypes: ActionType[];
|
||||
filterOptions: TypeFilterProps['options'];
|
||||
filters: RulesListFilters;
|
||||
inputText: string;
|
||||
lastUpdate: string;
|
||||
rulesLastRunOutcomesTotal: Record<string, number>;
|
||||
rulesStatusesTotal: Record<string, number>;
|
||||
showActionFilter: boolean;
|
||||
showErrors: boolean;
|
||||
updateFilters: (updateFiltersProps: UpdateFiltersProps) => void;
|
||||
setInputText: (text: string) => void;
|
||||
tags: string[];
|
||||
onClearSelection: () => void;
|
||||
onRefreshRules: () => void;
|
||||
onToggleRuleErrors: () => void;
|
||||
setInputText: (text: string) => void;
|
||||
updateFilters: (updateFiltersProps: UpdateFiltersProps) => void;
|
||||
}
|
||||
|
||||
const ENTER_KEY = 13;
|
||||
export const RulesListFiltersBar = React.memo((props: RulesListFiltersBarProps) => {
|
||||
const {
|
||||
filters,
|
||||
inputText,
|
||||
showActionFilter = true,
|
||||
rulesStatusesTotal,
|
||||
rulesLastRunOutcomesTotal,
|
||||
tags,
|
||||
actionTypes,
|
||||
filterOptions,
|
||||
filters,
|
||||
inputText,
|
||||
lastUpdate,
|
||||
showErrors,
|
||||
updateFilters,
|
||||
setInputText,
|
||||
onClearSelection,
|
||||
onRefreshRules,
|
||||
onToggleRuleErrors,
|
||||
rulesLastRunOutcomesTotal,
|
||||
rulesStatusesTotal,
|
||||
setInputText,
|
||||
showActionFilter = true,
|
||||
showErrors,
|
||||
tags,
|
||||
updateFilters,
|
||||
} = props;
|
||||
|
||||
const isRuleTagFilterEnabled = getIsExperimentalFeatureEnabled('ruleTagFilter');
|
||||
|
@ -136,6 +135,19 @@ export const RulesListFiltersBar = React.memo((props: RulesListFiltersBarProps)
|
|||
...getRuleTagFilter(),
|
||||
];
|
||||
|
||||
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setInputText(e.target.value);
|
||||
if (e.target.value === '') {
|
||||
updateFilters({ filter: 'searchText', value: e.target.value });
|
||||
}
|
||||
};
|
||||
|
||||
const handleKeyup = (e: React.KeyboardEvent<HTMLInputElement>) => {
|
||||
if (e.keyCode === ENTER_KEY) {
|
||||
updateFilters({ filter: 'searchText', value: inputText });
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<RulesListErrorBanner
|
||||
|
@ -150,25 +162,16 @@ export const RulesListFiltersBar = React.memo((props: RulesListFiltersBarProps)
|
|||
<EuiFlexGroup gutterSize="s">
|
||||
<EuiFlexItem>
|
||||
<EuiFieldSearch
|
||||
data-test-subj="ruleSearchField"
|
||||
fullWidth
|
||||
isClearable
|
||||
data-test-subj="ruleSearchField"
|
||||
value={inputText}
|
||||
onChange={(e) => {
|
||||
setInputText(e.target.value);
|
||||
if (e.target.value === '') {
|
||||
updateFilters({ filter: 'searchText', value: e.target.value });
|
||||
}
|
||||
}}
|
||||
onKeyUp={(e) => {
|
||||
if (e.keyCode === ENTER_KEY) {
|
||||
updateFilters({ filter: 'searchText', value: inputText });
|
||||
}
|
||||
}}
|
||||
placeholder={i18n.translate(
|
||||
'xpack.triggersActionsUI.sections.rulesList.searchPlaceholderTitle',
|
||||
{ defaultMessage: 'Search' }
|
||||
)}
|
||||
value={inputText}
|
||||
onChange={handleChange}
|
||||
onKeyUp={handleKeyup}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>{renderRuleStatusFilter()}</EuiFlexItem>
|
||||
|
|
|
@ -374,6 +374,11 @@ export interface RuleTypeParamsExpressionProps<
|
|||
unifiedSearch: UnifiedSearchPublicPluginStart;
|
||||
}
|
||||
|
||||
export type RuleParamsForRules = Record<
|
||||
string,
|
||||
Array<{ label: string; value: string | number | object }>
|
||||
>;
|
||||
|
||||
export interface RuleTypeModel<Params extends RuleTypeParams = RuleTypeParams> {
|
||||
id: string;
|
||||
description: string;
|
||||
|
@ -688,13 +693,14 @@ export interface ConnectorServices {
|
|||
}
|
||||
|
||||
export interface RulesListFilters {
|
||||
searchText: string;
|
||||
types: string[];
|
||||
actionTypes: string[];
|
||||
ruleExecutionStatuses: string[];
|
||||
ruleLastRunOutcomes: string[];
|
||||
ruleParams: Record<string, string | number | object>;
|
||||
ruleStatuses: RuleStatus[];
|
||||
searchText: string;
|
||||
tags: string[];
|
||||
types: string[];
|
||||
}
|
||||
|
||||
export type UpdateFiltersProps =
|
||||
|
@ -709,6 +715,10 @@ export type UpdateFiltersProps =
|
|||
| {
|
||||
filter: 'types' | 'actionTypes' | 'ruleExecutionStatuses' | 'ruleLastRunOutcomes' | 'tags';
|
||||
value: string[];
|
||||
}
|
||||
| {
|
||||
filter: 'ruleParams';
|
||||
value: Record<string, string | number | object>;
|
||||
};
|
||||
|
||||
export interface RulesPageContainerState {
|
||||
|
|
|
@ -44,7 +44,6 @@
|
|||
"@kbn/ui-theme",
|
||||
"@kbn/datemath",
|
||||
"@kbn/core-capabilities-common",
|
||||
"@kbn/safer-lodash-set",
|
||||
"@kbn/shared-ux-router",
|
||||
"@kbn/alerts-ui-shared",
|
||||
"@kbn/safer-lodash-set",
|
||||
|
@ -52,7 +51,7 @@
|
|||
"@kbn/field-types",
|
||||
"@kbn/ecs",
|
||||
"@kbn/alerts-as-data-utils",
|
||||
"@kbn/core-ui-settings-common"
|
||||
"@kbn/core-ui-settings-common",
|
||||
],
|
||||
"exclude": ["target/**/*"]
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue