diff --git a/x-pack/plugins/security_solution/public/common/utils/shorten_count_into_string.test.ts b/x-pack/plugins/security_solution/public/common/utils/shorten_count_into_string.test.ts new file mode 100644 index 00000000000000..13699f5dc30607 --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/utils/shorten_count_into_string.test.ts @@ -0,0 +1,38 @@ +/* + * 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 { shortenCountIntoString } from './shorten_count_into_string'; + +describe('utils', () => { + describe('shortenCountIntoString', () => { + it('should not change small numbers', () => { + expect(shortenCountIntoString(0)).toBe('0'); + expect(shortenCountIntoString(9999)).toBe('9999'); + }); + + it('should add K when appropriate', () => { + expect(shortenCountIntoString(10000)).toBe('10K'); + expect(shortenCountIntoString(109000)).toBe('109K'); + expect(shortenCountIntoString(109800)).toBe('109.8K'); + expect(shortenCountIntoString(109897)).toBe('109.8K'); + }); + + it('should add M when appropriate', () => { + expect(shortenCountIntoString(10000000)).toBe('10M'); + expect(shortenCountIntoString(109000000)).toBe('109M'); + expect(shortenCountIntoString(109800000)).toBe('109.8M'); + expect(shortenCountIntoString(109890000)).toBe('109.8M'); + }); + + it('should add B when appropriate', () => { + expect(shortenCountIntoString(10000000000)).toBe('10B'); + expect(shortenCountIntoString(109000000000)).toBe('109B'); + expect(shortenCountIntoString(109800000000)).toBe('109.8B'); + expect(shortenCountIntoString(109890000000)).toBe('109.8B'); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/public/common/utils/shorten_count_into_string.ts b/x-pack/plugins/security_solution/public/common/utils/shorten_count_into_string.ts new file mode 100644 index 00000000000000..63d2c8f597911b --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/utils/shorten_count_into_string.ts @@ -0,0 +1,35 @@ +/* + * 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. + */ + +export const shortenCountIntoString = (count: number): string => { + if (count < 10000) { + return count.toString(); + } + const abbreviations = [ + { magnitude: 1e18, unit: 'E' }, + { magnitude: 1e15, unit: 'P' }, + { magnitude: 1e12, unit: 'T' }, + { magnitude: 1e9, unit: 'B' }, + { magnitude: 1e6, unit: 'M' }, + { magnitude: 1e3, unit: 'K' }, + ]; + const { magnitude, unit } = abbreviations.find( + (abbreviation) => count >= abbreviation.magnitude + ) ?? { + magnitude: 1, + unit: '', + }; + + return ( + toFixedWithoutRounding(count / magnitude, 1).replace(/\.0+$|(\.[0-9]*[1-9])0+$/, '$1') + unit + ); +}; + +const toFixedWithoutRounding = (n: number, p: number) => { + const result = n.toFixed(p); + return +result <= n ? result : (+result - Math.pow(0.1, p)).toFixed(p); +}; diff --git a/x-pack/plugins/security_solution/public/overview/components/overview_cti_links/cti_no_events.test.tsx b/x-pack/plugins/security_solution/public/overview/components/overview_cti_links/cti_no_events.test.tsx index 5e1697279dd4c7..f00e1053e80822 100644 --- a/x-pack/plugins/security_solution/public/overview/components/overview_cti_links/cti_no_events.test.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/overview_cti_links/cti_no_events.test.tsx @@ -69,7 +69,7 @@ describe('CtiNoEvents', () => { ); expect(wrapper.find('[data-test-subj="cti-total-event-count"]').text()).toEqual( - 'Showing: 0 events' + 'Showing: 0 indicators' ); }); }); diff --git a/x-pack/plugins/security_solution/public/overview/components/overview_cti_links/cti_with_events.test.tsx b/x-pack/plugins/security_solution/public/overview/components/overview_cti_links/cti_with_events.test.tsx index 3b03b9c418a1cd..fac05bb72df38f 100644 --- a/x-pack/plugins/security_solution/public/overview/components/overview_cti_links/cti_with_events.test.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/overview_cti_links/cti_with_events.test.tsx @@ -51,7 +51,7 @@ describe('CtiWithEvents', () => { ); expect(wrapper.find('[data-test-subj="cti-total-event-count"]').text()).toEqual( - `Showing: ${mockCtiWithEventsProps.totalCount} events` + `Showing: ${mockCtiWithEventsProps.totalCount} indicators` ); }); }); diff --git a/x-pack/plugins/security_solution/public/overview/components/overview_cti_links/threat_intel_panel_view.test.tsx b/x-pack/plugins/security_solution/public/overview/components/overview_cti_links/threat_intel_panel_view.test.tsx index 59ee1e5447ba30..f0e3bcaaec6e02 100644 --- a/x-pack/plugins/security_solution/public/overview/components/overview_cti_links/threat_intel_panel_view.test.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/overview_cti_links/threat_intel_panel_view.test.tsx @@ -141,7 +141,7 @@ describe('ThreatIntelPanelView', () => { ); expect(wrapper.find('[data-test-subj="cti-total-event-count"]').text()).toEqual( - `Showing: ${mockThreatIntelPanelViewProps.totalEventCount} events` + `Showing: ${mockThreatIntelPanelViewProps.totalEventCount} indicators` ); }); }); diff --git a/x-pack/plugins/security_solution/public/overview/components/overview_cti_links/threat_intel_panel_view.tsx b/x-pack/plugins/security_solution/public/overview/components/overview_cti_links/threat_intel_panel_view.tsx index 51ce06762ddf92..babbd5d13224f1 100644 --- a/x-pack/plugins/security_solution/public/overview/components/overview_cti_links/threat_intel_panel_view.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/overview_cti_links/threat_intel_panel_view.tsx @@ -25,6 +25,7 @@ import { CtiListItem } from '../../containers/overview_cti_links/helpers'; import { useKibana } from '../../../common/lib/kibana'; import { CtiInnerPanel } from './cti_inner_panel'; import * as i18n from './translations'; +import { shortenCountIntoString } from '../../../common/utils/shorten_count_into_string'; const DashboardLink = styled.li` margin: 0 ${({ theme }) => theme.eui.paddingSizes.s} 0 ${({ theme }) => theme.eui.paddingSizes.m}; @@ -84,7 +85,7 @@ export const ThreatIntelPanelView: React.FC = ({ () => ( @@ -160,7 +161,7 @@ export const ThreatIntelPanelView: React.FC = ({ justifyContent="flexEnd" > - {count} + {shortenCountIntoString(count)} {path ? (