Skip to content

Commit

Permalink
TEMP COMMIT. REBASE ME
Browse files Browse the repository at this point in the history
  • Loading branch information
banderror committed Dec 30, 2021
1 parent 95f66dc commit 7084ec6
Show file tree
Hide file tree
Showing 20 changed files with 226 additions and 207 deletions.
21 changes: 2 additions & 19 deletions x-pack/plugins/security_solution/common/detection_engine/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* 2.0.
*/

import { isEmpty, capitalize } from 'lodash';
import { isEmpty } from 'lodash';

import type {
EntriesArray,
Expand All @@ -16,7 +16,7 @@ import type {
import { Type } from '@kbn/securitysolution-io-ts-alerting-types';
import { hasLargeValueList } from '@kbn/securitysolution-list-utils';

import { RuleExecutionStatus, Threshold, ThresholdNormalized } from './schemas/common';
import { Threshold, ThresholdNormalized } from './schemas/common';

export const hasLargeValueItem = (
exceptionItems: Array<ExceptionListItemSchema | CreateExceptionListItemSchema>
Expand Down Expand Up @@ -64,20 +64,3 @@ export const normalizeThresholdObject = (threshold: Threshold): ThresholdNormali

export const normalizeMachineLearningJobIds = (value: string | string[]): string[] =>
Array.isArray(value) ? value : [value];

export const getRuleStatusText = (
value: RuleExecutionStatus | null | undefined
): RuleExecutionStatus | null =>
value === RuleExecutionStatus['partial failure']
? RuleExecutionStatus.warning
: value != null
? value
: null;

export const getCapitalizedRuleStatusText = (
value: RuleExecutionStatus | null | undefined
): string | null => {
const status = getRuleStatusText(value);

return status != null ? capitalize(status) : null;
};
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,9 @@
* 2.0.
*/

import { getStatusColor } from './helpers';
export * from './rule_status';
export * from './rule_status_badge';
export * from './rule_status_failed_callout';

describe('rule_status helpers', () => {
it('getStatusColor returns subdued if null was provided', () => {
expect(getStatusColor(null)).toBe('subdued');
});
});
// TODO: https://github.com/elastic/kibana/pull/121644 clean up
export * as ruleStatusI18n from './translations';
Original file line number Diff line number Diff line change
Expand Up @@ -5,38 +5,41 @@
* 2.0.
*/

import React from 'react';
import { EuiFlexItem, EuiHealth, EuiText } from '@elastic/eui';
import React, { memo } from 'react';

import { RuleExecutionStatus } from '../../../../../common/detection_engine/schemas/common';

import { FormattedDate } from '../../../../common/components/formatted_date';
import { getEmptyTagValue } from '../../../../common/components/empty_value';
import { getStatusColor } from './helpers';
import { getStatusColor, normalizeRuleExecutionStatus } from './utils';
import * as i18n from './translations';
import { RuleExecutionStatus } from '../../../../../common/detection_engine/schemas/common';

interface RuleStatusProps {
children: React.ReactNode | null | undefined;
statusDate: string | null | undefined;
status: RuleExecutionStatus | null | undefined;
date: string | null | undefined;
children: React.ReactNode | null | undefined;
}

const RuleStatusComponent: React.FC<RuleStatusProps> = ({ children, statusDate, status }) => {
const RuleStatusComponent: React.FC<RuleStatusProps> = ({ status, date, children }) => {
const normalizedStatus = normalizeRuleExecutionStatus(status);
const statusColor = getStatusColor(normalizedStatus);
return (
<>
<EuiFlexItem grow={false}>
<EuiHealth color={getStatusColor(status ?? null)}>
<EuiHealth color={statusColor}>
<EuiText data-test-subj="ruleStatus" size="xs">
{status ?? getEmptyTagValue()}
{normalizedStatus ?? getEmptyTagValue()}
</EuiText>
</EuiHealth>
</EuiFlexItem>
{statusDate != null && status != null && (
{date != null && normalizedStatus != null && (
<>
<EuiFlexItem grow={false}>
<>{i18n.STATUS_AT}</>
</EuiFlexItem>
<EuiFlexItem grow={true}>
<FormattedDate value={statusDate} fieldName={i18n.STATUS_DATE} />
<FormattedDate value={date} fieldName={i18n.STATUS_DATE} />
</EuiFlexItem>
</>
)}
Expand All @@ -45,4 +48,5 @@ const RuleStatusComponent: React.FC<RuleStatusProps> = ({ children, statusDate,
);
};

export const RuleStatus = memo(RuleStatusComponent);
export const RuleStatus = React.memo(RuleStatusComponent);
RuleStatus.displayName = 'RuleStatus';
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,12 @@
import React from 'react';
import { render, screen } from '@testing-library/react';

import { RuleExecutionStatusBadge } from '.';

import { RuleExecutionStatus } from '../../../../../common/detection_engine/schemas/common';
import { RuleStatusBadge } from './rule_status_badge';

describe('Component RuleExecutionStatus', () => {
it('should render component correctly with capitalized status text', () => {
render(<RuleExecutionStatusBadge status={RuleExecutionStatus.succeeded} />);
describe('RuleStatusBadge', () => {
it('renders capitalized status text', () => {
render(<RuleStatusBadge status={RuleExecutionStatus.succeeded} />);

expect(screen.getByText('Succeeded')).toBeInTheDocument();
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,32 +9,31 @@ import React from 'react';

import { getEmptyTagValue } from '../../../../common/components/empty_value';
import { HealthTruncateText } from '../../../../common/components/health_truncate_text';
import { getStatusColor } from '../rule_status/helpers';
import { getCapitalizedRuleStatusText, getStatusColor } from './utils';

import { getCapitalizedRuleStatusText } from '../../../../../common/detection_engine/utils';
import type { RuleExecutionStatus } from '../../../../../common/detection_engine/schemas/common';

interface RuleExecutionStatusBadgeProps {
interface RuleStatusBadgeProps {
status: RuleExecutionStatus | null | undefined;
}

/**
* Shows rule execution status
* @param status - rule execution status
*/
const RuleExecutionStatusBadgeComponent = ({ status }: RuleExecutionStatusBadgeProps) => {
const displayStatus = getCapitalizedRuleStatusText(status);
const RuleStatusBadgeComponent = ({ status }: RuleStatusBadgeProps) => {
const statusText = getCapitalizedRuleStatusText(status);
const statusColor = getStatusColor(status ?? null);
return (
<HealthTruncateText
tooltipContent={displayStatus}
healthColor={getStatusColor(status ?? null)}
tooltipContent={statusText}
healthColor={statusColor}
dataTestSubj="ruleExecutionStatus"
>
{displayStatus ?? getEmptyTagValue()}
{statusText ?? getEmptyTagValue()}
</HealthTruncateText>
);
};

export const RuleExecutionStatusBadge = React.memo(RuleExecutionStatusBadgeComponent);

RuleExecutionStatusBadge.displayName = 'RuleExecutionStatusBadge';
export const RuleStatusBadge = React.memo(RuleStatusBadgeComponent);
RuleStatusBadge.displayName = 'RuleStatusBadge';
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,15 @@
import React from 'react';
import { shallow } from 'enzyme';

import { RuleStatusFailedCallOut } from './status_failed_callout';
import { RuleStatusFailedCallOut } from './rule_status_failed_callout';

describe('RuleStatusFailedCallOut', () => {
it('renders correctly', () => {
const wrapper = shallow(<RuleStatusFailedCallOut date="date" message="message" />);

expect(wrapper.find('EuiCallOut')).toHaveLength(1);
});

it('renders correctly with optional params', () => {
const wrapper = shallow(
<RuleStatusFailedCallOut date="date" message="message" color="warning" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* 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 { EuiCallOut, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
import { FormattedDate } from '../../../../common/components/formatted_date';

import { RuleExecutionStatus } from '../../../../../common/detection_engine/schemas/common';
import { normalizeRuleExecutionStatus } from './utils';

import * as i18n from './translations';

interface RuleStatusFailedCallOutProps {
status: RuleExecutionStatus | null | undefined;
date: string;
message: string;
}

const RuleStatusFailedCallOutComponent: React.FC<RuleStatusFailedCallOutProps> = ({
status,
date,
message,
}) => {
const props = getPropsByStatus(status);
if (!props) {
// we will not show this callout for this status
return null;
}

return (
<EuiCallOut
title={
<EuiFlexGroup gutterSize="xs" alignItems="center" justifyContent="flexStart">
<EuiFlexItem grow={false}>{props.title}</EuiFlexItem>
<EuiFlexItem grow={true}>
<FormattedDate value={date} fieldName="last_failure_at" />
</EuiFlexItem>
</EuiFlexGroup>
}
color={props.color}
iconType="alert"
>
<p>{message}</p>
</EuiCallOut>
);
};

export const RuleStatusFailedCallOut = React.memo(RuleStatusFailedCallOutComponent);
RuleStatusFailedCallOut.displayName = 'RuleStatusFailedCallOut';

// -------------------------------------------------------------------------------------------------
// Helpers

interface HelperProps {
color: 'danger' | 'warning';
title: string;
}

const getPropsByStatus = (status: RuleExecutionStatus | null | undefined): HelperProps | null => {
const normalizedStatus = normalizeRuleExecutionStatus(status);
switch (normalizedStatus) {
case RuleExecutionStatus.failed:
return {
color: 'danger',
title: i18n.ERROR_CALLOUT_TITLE,
};
case RuleExecutionStatus.warning:
return {
color: 'warning',
title: i18n.PARTIAL_FAILURE_CALLOUT_TITLE,
};
default:
return null;
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,17 @@ export const REFRESH = i18n.translate(
defaultMessage: 'Refresh',
}
);

export const ERROR_CALLOUT_TITLE = i18n.translate(
'xpack.securitySolution.detectionEngine.ruleStatus.errorCalloutTitle',
{
defaultMessage: 'Rule failure at',
}
);

export const PARTIAL_FAILURE_CALLOUT_TITLE = i18n.translate(
'xpack.securitySolution.detectionEngine.ruleStatus.partialErrorCalloutTitle',
{
defaultMessage: 'Warning at',
}
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*
* 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 { getStatusColor } from './utils';

describe('Rule execution status utils', () => {
describe('getStatusColor', () => {
it('returns "subdued" if null was provided', () => {
expect(getStatusColor(null)).toBe('subdued');
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,25 @@
* 2.0.
*/

import { capitalize } from 'lodash';
import { RuleExecutionStatus } from '../../../../../common/detection_engine/schemas/common';

export const normalizeRuleExecutionStatus = (
value: RuleExecutionStatus | null | undefined
): RuleExecutionStatus | null =>
value === RuleExecutionStatus['partial failure']
? RuleExecutionStatus.warning
: value != null
? value
: null;

export const getCapitalizedRuleStatusText = (
value: RuleExecutionStatus | null | undefined
): string | null => {
const status = normalizeRuleExecutionStatus(value);
return status != null ? capitalize(status) : null;
};

export const getStatusColor = (status: RuleExecutionStatus | string | null) =>
status == null
? 'subdued'
Expand Down
Loading

0 comments on commit 7084ec6

Please sign in to comment.