Skip to content

Commit

Permalink
rename state to status, added tests
Browse files Browse the repository at this point in the history
  • Loading branch information
JiaweiWu committed Apr 28, 2022
1 parent 6f1b580 commit c18a582
Show file tree
Hide file tree
Showing 28 changed files with 391 additions and 301 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export function useFetchRules({
page,
searchText,
typesFilter: typesFilter.length > 0 ? typesFilter : OBSERVABILITY_RULE_TYPES,
ruleStatusesFilter: ruleLastResponseFilter,
ruleExecutionStatusesFilter: ruleLastResponseFilter,
sort,
});
setRulesState((oldState) => ({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export const allowedExperimentalValues = Object.freeze({
rulesListDatagrid: true,
internalAlertsTable: false,
internalShareableComponentsSandbox: false,
ruleStateFilter: false,
ruleStatusFilter: false,
rulesDetailLogs: true,
});

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* 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, { useState } from 'react';
import { RuleStatusFilterProps } from '../../../types';
import { getRuleStatusFilterLazy } from '../../../common/get_rule_status_filter';

export const RuleStatusFilterSandbox = () => {
const [selectedStatuses, setSelectedStatuses] = useState<
RuleStatusFilterProps['selectedStatuses']
>([]);

return (
<div style={{ flex: 1 }}>
{getRuleStatusFilterLazy({
selectedStatuses,
onChange: setSelectedStatuses,
})}
<div>Selected states: {JSON.stringify(selectedStatuses)}</div>
</div>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@

import React from 'react';
import { RuleStatusDropdownSandbox } from './rule_status_dropdown_sandbox';
import { RuleStateFilterSandbox } from './rule_state_filter_sandbox';
import { RuleStatusFilterSandbox } from './rule_status_filter_sandbox';

export const InternalShareableComponentsSandbox: React.FC<{}> = () => {
return (
<>
<RuleStatusDropdownSandbox />
<RuleStateFilterSandbox />
<RuleStatusFilterSandbox />
</>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,15 @@ export async function loadRuleAggregations({
searchText,
typesFilter,
actionTypesFilter,
ruleStatusesFilter,
ruleExecutionStatusesFilter,
}: {
http: HttpSetup;
searchText?: string;
typesFilter?: string[];
actionTypesFilter?: string[];
ruleStatusesFilter?: string[];
ruleExecutionStatusesFilter?: string[];
}): Promise<RuleAggregations> {
const filters = mapFiltersToKql({ typesFilter, actionTypesFilter, ruleStatusesFilter });
const filters = mapFiltersToKql({ typesFilter, actionTypesFilter, ruleExecutionStatusesFilter });
const res = await http.get<AsApiContract<RuleAggregations>>(
`${INTERNAL_BASE_ALERTING_API_PATH}/rules/_aggregate`,
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,34 +32,34 @@ describe('mapFiltersToKql', () => {
]);
});

test('should handle ruleStatusesFilter', () => {
test('should handle ruleExecutionStatusesFilter', () => {
expect(
mapFiltersToKql({
ruleStatusesFilter: ['alert', 'statuses', 'filter'],
ruleExecutionStatusesFilter: ['alert', 'statuses', 'filter'],
})
).toEqual(['alert.attributes.executionStatus.status:(alert or statuses or filter)']);
});

test('should handle ruleStateFilter', () => {
test('should handle ruleStatusesFilter', () => {
expect(
mapFiltersToKql({
ruleStateFilter: ['enabled', 'snoozed'],
ruleStatusesFilter: ['enabled', 'snoozed'],
})
).toEqual([
'alert.attributes.enabled:(true) or (alert.attributes.muteAll:true OR alert.attributes.snoozeEndTime > now)',
]);

expect(
mapFiltersToKql({
ruleStateFilter: ['enabled'],
ruleStatusesFilter: ['enabled'],
})
).toEqual([
'alert.attributes.enabled:(true) and not (alert.attributes.muteAll:true OR alert.attributes.snoozeEndTime > now)',
]);

expect(
mapFiltersToKql({
ruleStateFilter: ['enabled', 'disabled', 'snoozed'],
ruleStatusesFilter: ['enabled', 'disabled', 'snoozed'],
})
).toEqual([
'alert.attributes.enabled:(true or false) or (alert.attributes.muteAll:true OR alert.attributes.snoozeEndTime > now)',
Expand All @@ -78,12 +78,12 @@ describe('mapFiltersToKql', () => {
]);
});

test('should handle typesFilter, actionTypesFilter and ruleStatusesFilter', () => {
test('should handle typesFilter, actionTypesFilter and ruleExecutionStatusesFilter', () => {
expect(
mapFiltersToKql({
typesFilter: ['type', 'filter'],
actionTypesFilter: ['action', 'types', 'filter'],
ruleStatusesFilter: ['alert', 'statuses', 'filter'],
ruleExecutionStatusesFilter: ['alert', 'statuses', 'filter'],
})
).toEqual([
'alert.attributes.alertTypeId:(type or filter)',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@

import { RuleStatus } from '../../../types';

const getEnablementFilter = (ruleStateFilter: RuleStatus[] = []) => {
const enablementFilters = ruleStateFilter.reduce<string[]>((result, filter) => {
const getEnablementFilter = (ruleStatusFilter: RuleStatus[] = []) => {
const enablementFilters = ruleStatusFilter.reduce<string[]>((result, filter) => {
if (filter === 'enabled') {
return [...result, 'true'];
}
Expand All @@ -23,13 +23,13 @@ const getEnablementFilter = (ruleStateFilter: RuleStatus[] = []) => {
export const mapFiltersToKql = ({
typesFilter,
actionTypesFilter,
ruleExecutionStatusesFilter,
ruleStatusesFilter,
ruleStateFilter,
}: {
typesFilter?: string[];
actionTypesFilter?: string[];
ruleStatusesFilter?: string[];
ruleStateFilter?: RuleStatus[];
ruleExecutionStatusesFilter?: string[];
ruleStatusesFilter?: RuleStatus[];
}): string[] => {
const filters = [];

Expand All @@ -47,16 +47,18 @@ export const mapFiltersToKql = ({
].join('')
);
}
if (ruleStatusesFilter && ruleStatusesFilter.length) {
filters.push(`alert.attributes.executionStatus.status:(${ruleStatusesFilter.join(' or ')})`);
if (ruleExecutionStatusesFilter && ruleExecutionStatusesFilter.length) {
filters.push(
`alert.attributes.executionStatus.status:(${ruleExecutionStatusesFilter.join(' or ')})`
);
}

if (ruleStateFilter && ruleStateFilter.length) {
const enablementFilter = getEnablementFilter(ruleStateFilter);
if (ruleStatusesFilter && ruleStatusesFilter.length) {
const enablementFilter = getEnablementFilter(ruleStatusesFilter);
const snoozedFilter = `(alert.attributes.muteAll:true OR alert.attributes.snoozeEndTime > now)`;
const hasEnablement =
ruleStateFilter.includes('enabled') || ruleStateFilter.includes('disabled');
const hasSnoozed = ruleStateFilter.includes('snoozed');
ruleStatusesFilter.includes('enabled') || ruleStatusesFilter.includes('disabled');
const hasSnoozed = ruleStatusesFilter.includes('snoozed');

if (hasEnablement && !hasSnoozed) {
filters.push(`${enablementFilter} and not ${snoozedFilter}`);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ describe('loadRules', () => {
`);
});

test('should call find API with ruleStateFilter', async () => {
test('should call find API with ruleStatusesilter', async () => {
const resolvedValue = {
page: 1,
per_page: 10,
Expand All @@ -251,7 +251,7 @@ describe('loadRules', () => {

let result = await loadRules({
http,
ruleStateFilter: ['enabled', 'snoozed'],
ruleStatusesFilter: ['enabled', 'snoozed'],
page: { index: 0, size: 10 },
});
expect(result).toEqual({
Expand Down Expand Up @@ -280,7 +280,7 @@ describe('loadRules', () => {

result = await loadRules({
http,
ruleStateFilter: ['disabled'],
ruleStatusesFilter: ['disabled'],
page: { index: 0, size: 10 },
});
expect(result).toEqual({
Expand Down Expand Up @@ -309,7 +309,7 @@ describe('loadRules', () => {

result = await loadRules({
http,
ruleStateFilter: ['enabled', 'disabled', 'snoozed'],
ruleStatusesFilter: ['enabled', 'disabled', 'snoozed'],
page: { index: 0, size: 10 },
});
expect(result).toEqual({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,17 @@ export async function loadRules({
searchText,
typesFilter,
actionTypesFilter,
ruleExecutionStatusesFilter,
ruleStatusesFilter,
ruleStateFilter,
sort = { field: 'name', direction: 'asc' },
}: {
http: HttpSetup;
page: Pagination;
searchText?: string;
typesFilter?: string[];
actionTypesFilter?: string[];
ruleStatusesFilter?: string[];
ruleStateFilter?: RuleStatus[];
ruleExecutionStatusesFilter?: string[];
ruleStatusesFilter?: RuleStatus[];
sort?: Sorting;
}): Promise<{
page: number;
Expand All @@ -42,8 +42,8 @@ export async function loadRules({
const filters = mapFiltersToKql({
typesFilter,
actionTypesFilter,
ruleExecutionStatusesFilter,
ruleStatusesFilter,
ruleStateFilter,
});
const res = await http.get<
AsApiContract<{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,6 @@ export const ActionForm = suspendedComponentWithProps(
export const RuleStatusDropdown = suspendedComponentWithProps(
lazy(() => import('./rules_list/components/rule_status_dropdown'))
);
export const RuleStateFilter = suspendedComponentWithProps(
lazy(() => import('./rules_list/components/rule_state_filter'))
export const RuleStatusFilter = suspendedComponentWithProps(
lazy(() => import('./rules_list/components/rule_status_filter'))
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/*
* 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, { useEffect, useState } from 'react';
import { FormattedMessage } from '@kbn/i18n-react';
import {
EuiFilterGroup,
EuiPopover,
EuiFilterButton,
EuiFilterSelectItem,
EuiHealth,
} from '@elastic/eui';
import { RuleExecutionStatuses, RuleExecutionStatusValues } from '@kbn/alerting-plugin/common';
import { rulesStatusesTranslationsMapping } from '../translations';

interface RuleExecutionStatusFilterProps {
selectedStatuses: string[];
onChange?: (selectedRuleStatusesIds: string[]) => void;
}

export const RuleExecutionStatusFilter: React.FunctionComponent<RuleExecutionStatusFilterProps> = ({
selectedStatuses,
onChange,
}: RuleExecutionStatusFilterProps) => {
const [selectedValues, setSelectedValues] = useState<string[]>(selectedStatuses);
const [isPopoverOpen, setIsPopoverOpen] = useState<boolean>(false);

useEffect(() => {
if (onChange) {
onChange(selectedValues);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [selectedValues]);

useEffect(() => {
setSelectedValues(selectedStatuses);
}, [selectedStatuses]);

return (
<EuiFilterGroup>
<EuiPopover
isOpen={isPopoverOpen}
closePopover={() => setIsPopoverOpen(false)}
button={
<EuiFilterButton
iconType="arrowDown"
hasActiveFilters={selectedValues.length > 0}
numActiveFilters={selectedValues.length}
numFilters={selectedValues.length}
onClick={() => setIsPopoverOpen(!isPopoverOpen)}
data-test-subj="ruleExecutionStatusFilterButton"
>
<FormattedMessage
id="xpack.triggersActionsUI.sections.rulesList.ruleExecutionStatusFilterLabel"
defaultMessage="Last response"
/>
</EuiFilterButton>
}
>
<div className="euiFilterSelect__items">
{[...RuleExecutionStatusValues].sort().map((item: RuleExecutionStatuses) => {
const healthColor = getHealthColor(item);
return (
<EuiFilterSelectItem
key={item}
style={{ textTransform: 'capitalize' }}
onClick={() => {
const isPreviouslyChecked = selectedValues.includes(item);
if (isPreviouslyChecked) {
setSelectedValues(selectedValues.filter((val) => val !== item));
} else {
setSelectedValues(selectedValues.concat(item));
}
}}
checked={selectedValues.includes(item) ? 'on' : undefined}
data-test-subj={`ruleExecutionStatus${item}FilterOption`}
>
<EuiHealth color={healthColor}>{rulesStatusesTranslationsMapping[item]}</EuiHealth>
</EuiFilterSelectItem>
);
})}
</div>
</EuiPopover>
</EuiFilterGroup>
);
};

export function getHealthColor(status: RuleExecutionStatuses) {
switch (status) {
case 'active':
return 'success';
case 'error':
return 'danger';
case 'ok':
return 'primary';
case 'pending':
return 'accent';
case 'warning':
return 'warning';
default:
return 'subdued';
}
}
Loading

0 comments on commit c18a582

Please sign in to comment.