From f284a2becbec3aa1a95c515f6667d5de0c769774 Mon Sep 17 00:00:00 2001 From: Amardeepsingh Siglani Date: Tue, 1 Aug 2023 20:39:13 -0700 Subject: [PATCH] UI polish for correlations and custom log types (#683) * fixed abbreviations Signed-off-by: Amardeepsingh Siglani * fixed log type name validation Signed-off-by: Amardeepsingh Siglani --------- Signed-off-by: Amardeepsingh Siglani (cherry picked from commit b54bb36229da42ae7f37a41d2aec78e75a0b5a45) --- .../Correlations/components/FindingCard.tsx | 53 +++++-------------- .../containers/CorrelationsContainer.tsx | 9 ++-- public/pages/Correlations/utils/constants.tsx | 6 +-- .../LogTypes/components/LogTypeDetails.tsx | 2 + .../components/LogTypeDetectionRules.tsx | 25 ++++++++- .../pages/LogTypes/components/LogTypeForm.tsx | 6 +-- .../LogTypes/containers/CreateLogType.tsx | 8 +-- public/pages/Rules/utils/constants.ts | 2 +- public/store/LogTypeStore.ts | 4 +- public/utils/validation.ts | 11 +++- 10 files changed, 57 insertions(+), 69 deletions(-) diff --git a/public/pages/Correlations/components/FindingCard.tsx b/public/pages/Correlations/components/FindingCard.tsx index 6e597606d..fe1d3698c 100644 --- a/public/pages/Correlations/components/FindingCard.tsx +++ b/public/pages/Correlations/components/FindingCard.tsx @@ -16,12 +16,7 @@ import { EuiToolTip, EuiDescriptionList, } from '@elastic/eui'; -import { - getAbbrFromLogType, - getSeverityLabel, - getSeverityColor, - getLabelFromLogType, -} from '../utils/constants'; +import { getSeverityLabel, getSeverityColor, getLabelFromLogType } from '../utils/constants'; import { DataStore } from '../../../store/DataStore'; import { CorrelationFinding } from '../../../../types'; @@ -31,7 +26,6 @@ export interface FindingCardProps { timestamp: string; detectionRule: { name: string; severity: string }; correlationData?: { - // ruleName: string; score: string; onInspect: (findingId: string, logType: string) => void; }; @@ -90,43 +84,20 @@ export const FindingCard: React.FC = ({ return ( {correlationHeader} - - -
-
+ +
+ - {getAbbrFromLogType(logType)} -
- {getSeverityLabel(detectionRule.severity) ? ( - - {getSeverityLabel(detectionRule.severity)} - - ) : null} + {getSeverityLabel(detectionRule.severity)} + + + {getLabelFromLogType(logType)} +
- - {getLabelFromLogType(logType)} - {!correlationData && ( diff --git a/public/pages/Correlations/containers/CorrelationsContainer.tsx b/public/pages/Correlations/containers/CorrelationsContainer.tsx index 5647dcad9..ec1b57b77 100644 --- a/public/pages/Correlations/containers/CorrelationsContainer.tsx +++ b/public/pages/Correlations/containers/CorrelationsContainer.tsx @@ -9,7 +9,6 @@ import { getDefaultLogTypeFilterItemOptions, defaultSeverityFilterItemOptions, emptyGraphData, - getAbbrFromLogType, getLabelFromLogType, getSeverityColor, getSeverityLabel, @@ -255,12 +254,9 @@ export class Correlations extends React.Component${getAbbrFromLogType( - finding.logType - )}\n${finding.detectionRule.severity.slice(0, 4)}`, title: this.createNodeTooltip(finding), color: { - background: 'white', + background: borderColor, border: borderColor, highlight: { background: '#e7f5ff', @@ -272,7 +268,7 @@ export class Correlations extends React.Component { - return ruleTypes.find((ruleType) => ruleType.value === logType)?.abbr || '-'; -}; - export const getLabelFromLogType = (logType: string) => { - return ruleTypes.find((ruleType) => ruleType.value === logType)?.label || '-'; + return ruleTypes.find((ruleType) => ruleType.value === logType)?.label || logType; }; export const getSeverityLabel = (sev: string) => { diff --git a/public/pages/LogTypes/components/LogTypeDetails.tsx b/public/pages/LogTypes/components/LogTypeDetails.tsx index 5b4090a20..375b7c598 100644 --- a/public/pages/LogTypes/components/LogTypeDetails.tsx +++ b/public/pages/LogTypes/components/LogTypeDetails.tsx @@ -10,6 +10,7 @@ import { LogTypeItem } from '../../../../types'; import { DataStore } from '../../../store/DataStore'; import { LogTypeForm } from './LogTypeForm'; import { NotificationsStart } from 'opensearch-dashboards/public'; +import { successNotificationToast } from '../../../utils/helpers'; export interface LogTypeDetailsProps { initialLogTypeDetails: LogTypeItem; @@ -31,6 +32,7 @@ export const LogTypeDetails: React.FC = ({ const onUpdateLogType = async () => { const success = await DataStore.logTypes.updateLogType(logTypeDetails); if (success) { + successNotificationToast(notifications, 'updated', `log type ${logTypeDetails.name}`); setIsEditMode(false); } }; diff --git a/public/pages/LogTypes/components/LogTypeDetectionRules.tsx b/public/pages/LogTypes/components/LogTypeDetectionRules.tsx index 8d2b4fd90..88f789fe3 100644 --- a/public/pages/LogTypes/components/LogTypeDetectionRules.tsx +++ b/public/pages/LogTypes/components/LogTypeDetectionRules.tsx @@ -7,7 +7,7 @@ import React from 'react'; import { RulesTable } from '../../Rules/components/RulesTable/RulesTable'; import { RuleTableItem } from '../../Rules/utils/helpers'; import { ContentPanel } from '../../../components/ContentPanel'; -import { EuiButton } from '@elastic/eui'; +import { EuiButton, EuiFlexGroup, EuiFlexItem, EuiIcon, EuiSpacer, EuiText } from '@elastic/eui'; export interface LogTypeDetectionRulesProps { rules: RuleTableItem[]; @@ -26,7 +26,28 @@ export const LogTypeDetectionRules: React.FC = ({ hideHeaderBorder={true} actions={[Refresh]} > - {}} /> + {rules.length === 0 ? ( + + + +

There are no detection rules associated with this log type.

+
+
+ + + Create detection rule  + + + + +
+ ) : ( + {}} /> + )} ); }; diff --git a/public/pages/LogTypes/components/LogTypeForm.tsx b/public/pages/LogTypes/components/LogTypeForm.tsx index 56d6a98f3..49fc9eb13 100644 --- a/public/pages/LogTypes/components/LogTypeForm.tsx +++ b/public/pages/LogTypes/components/LogTypeForm.tsx @@ -16,7 +16,7 @@ import { } from '@elastic/eui'; import { LogTypeItem } from '../../../../types'; import React from 'react'; -import { validateName } from '../../../utils/validation'; +import { LOG_TYPE_NAME_REGEX, validateName } from '../../../utils/validation'; import { NotificationsStart } from 'opensearch-dashboards/public'; import { useState } from 'react'; @@ -42,7 +42,7 @@ export const LogTypeForm: React.FC = ({ const [nameError, setNameError] = useState(''); const updateErrors = (details = logTypeDetails) => { - const nameInvalid = !validateName(details.name); + const nameInvalid = !validateName(details.name, LOG_TYPE_NAME_REGEX, false /* shouldTrim */); setNameError(nameInvalid ? 'Invalid name' : ''); return { nameInvalid }; @@ -68,7 +68,7 @@ export const LogTypeForm: React.FC = ({ label="Name" helpText={ isEditMode && - 'Must contain 5-50 characters. Valid characters are a-z, A-Zm 0-9, hyphens, spaces, and underscores' + 'Must contain 2-50 characters. Valid characters are a-z, 0-9, hyphens, and underscores' } isInvalid={!!nameError} error={nameError} diff --git a/public/pages/LogTypes/containers/CreateLogType.tsx b/public/pages/LogTypes/containers/CreateLogType.tsx index 01d4d8d1e..aaf47b297 100644 --- a/public/pages/LogTypes/containers/CreateLogType.tsx +++ b/public/pages/LogTypes/containers/CreateLogType.tsx @@ -3,7 +3,6 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { EuiLink } from '@elastic/eui'; import { ContentPanel } from '../../../components/ContentPanel'; import React, { useContext, useState } from 'react'; import { LogTypeForm } from '../components/LogTypeForm'; @@ -38,12 +37,7 @@ export const CreateLogType: React.FC = ({ history, notificat - Create log type to categorize and identify detection rules for your data sources.  {' '} - - Learn more - -

+

Create log type to categorize and identify detection rules for your data sources.

} hideHeaderBorder={true} > diff --git a/public/pages/Rules/utils/constants.ts b/public/pages/Rules/utils/constants.ts index f587d1338..a3780d277 100644 --- a/public/pages/Rules/utils/constants.ts +++ b/public/pages/Rules/utils/constants.ts @@ -5,7 +5,7 @@ import { euiPaletteForStatus } from '@elastic/eui'; -export const ruleTypes: { label: string; value: string; abbr: string }[] = []; +export const ruleTypes: { label: string; value: string; id: string }[] = []; const paletteColors = euiPaletteForStatus(5); diff --git a/public/store/LogTypeStore.ts b/public/store/LogTypeStore.ts index a3538916c..c9bb34ada 100644 --- a/public/store/LogTypeStore.ts +++ b/public/store/LogTypeStore.ts @@ -53,8 +53,8 @@ export class LogTypeStore { ruleTypes.length, ...logTypes.map((logType) => ({ label: logType.name, - value: logType.id, - abbr: '', + value: logType.name, + id: logType.id, })) ); diff --git a/public/utils/validation.ts b/public/utils/validation.ts index 83361e848..2dc9c306f 100644 --- a/public/utils/validation.ts +++ b/public/utils/validation.ts @@ -10,6 +10,8 @@ export const MAX_NAME_CHARACTERS = 50; // numbers 0-9, hyphens, spaces, and underscores. export const NAME_REGEX = new RegExp(/^[a-zA-Z0-9 _-]{5,50}$/); +export const LOG_TYPE_NAME_REGEX = new RegExp(/^[a-z0-9_-]{2,50}$/); + // This regex pattern support MIN to MAX character limit, capital and lowercase letters, // numbers 0-9, hyphens, dot, and underscores. export const DETECTION_NAME_REGEX = new RegExp(/^[a-zA-Z0-9_.-]{5,50}$/); @@ -28,8 +30,13 @@ export const AUTHOR_REGEX = new RegExp(/^[a-zA-Z0-9 _,-.]{5,50}$/); * @param regex * @return TRUE if valid; else FALSE. */ -export function validateName(name: string, regex: RegExp = NAME_REGEX): boolean { - return name.trim().match(regex) !== null; +export function validateName( + name: string, + regex: RegExp = NAME_REGEX, + shouldTrimName: boolean = true +): boolean { + const toValidate = shouldTrimName ? name.trim() : name; + return toValidate.match(regex) !== null; } export function validateDetectionFieldName(