Skip to content

Commit

Permalink
replace alerts donut charts
Browse files Browse the repository at this point in the history
  • Loading branch information
angorayc committed Dec 29, 2022
1 parent c31b77d commit 785712e
Show file tree
Hide file tree
Showing 8 changed files with 452 additions and 75 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@
* 2.0.
*/

import type { EuiFlexGroupProps } from '@elastic/eui';
import { EuiFlexGroup, EuiFlexItem, EuiText, EuiToolTip, useEuiTheme } from '@elastic/eui';
import React, { useMemo } from 'react';

import type { Datum, NodeColorAccessor, PartialTheme, ElementClickListener } from '@elastic/charts';
import type { Datum, NodeColorAccessor, PartialTheme } from '@elastic/charts';
import {
Chart,
Partition,
Expand Down Expand Up @@ -48,42 +49,47 @@ export interface DonutChartProps {
legendItems?: LegendItem[] | null | undefined;
title: React.ReactElement | string | number | null;
totalCount: number | null | undefined;
onElementClick?: ElementClickListener;
}

export interface DonutChartWrapperProps {
children?: React.ReactElement;
dataExists: boolean;
label: React.ReactElement | string;
title: React.ReactElement | string | number | null;
isChartEmbeddablesEnabled?: boolean;
}

/* Make this position absolute in order to overlap the text onto the donut */
const DonutTextWrapper = styled(EuiFlexGroup)`
top: 34%;
export const DonutTextWrapper = styled(EuiFlexGroup)<
EuiFlexGroupProps & { $isChartEmbeddablesEnabled?: boolean; $dataExists?: boolean }
>`
top: ${({ $isChartEmbeddablesEnabled, $dataExists }) =>
$isChartEmbeddablesEnabled && $dataExists ? `34%;` : `66%`};
width: 100%;
max-width: 77px;
position: absolute;
z-index: 1;
`;

const StyledEuiFlexItem = styled(EuiFlexItem)`
export const StyledEuiFlexItem = styled(EuiFlexItem)`
position: relative;
align-items: center;
`;

export const DonutChart = ({
data,
fillColor,
height = 90,
const DonutChartWrapperComponent: React.FC<DonutChartWrapperProps> = ({
dataExists,
label,
legendItems,
children,
title,
totalCount,
onElementClick,
}: DonutChartProps) => {
const theme = useTheme();
isChartEmbeddablesEnabled,
}) => {
const { euiTheme } = useEuiTheme();
const emptyLabelStyle = useMemo(
() => ({
color: euiTheme.colors.disabled,
}),
[euiTheme.colors.disabled]
);

return (
<EuiFlexGroup
alignItems="center"
Expand All @@ -92,31 +98,54 @@ export const DonutChart = ({
gutterSize="l"
data-test-subj="donut-chart"
>
<StyledEuiFlexItem grow={false}>
<StyledEuiFlexItem grow={isChartEmbeddablesEnabled}>
<DonutTextWrapper
direction="column"
gutterSize="none"
alignItems="center"
justifyContent="center"
$isChartEmbeddablesEnabled={isChartEmbeddablesEnabled}
$dataExists={dataExists}
>
<EuiFlexItem>{title}</EuiFlexItem>
<EuiFlexItem className="eui-textTruncate">
<EuiFlexItem className={isChartEmbeddablesEnabled ? undefined : 'eui-textTruncate'}>
<EuiToolTip content={label}>
<EuiText
className="eui-textTruncate"
className={isChartEmbeddablesEnabled ? undefined : 'eui-textTruncate'}
size="s"
style={data ? undefined : emptyLabelStyle}
style={dataExists ? undefined : emptyLabelStyle}
>
{label}
</EuiText>
</EuiToolTip>
</EuiFlexItem>
</DonutTextWrapper>
{children}
</StyledEuiFlexItem>
</EuiFlexGroup>
);
};
export const DonutChartWrapper = React.memo(DonutChartWrapperComponent);

export const DonutChart = ({
data,
height = 90,
fillColor,
label,
legendItems,
title,
totalCount,
}: DonutChartProps) => {
const theme = useTheme();

return (
<DonutChartWrapper dataExists={data != null && data.length > 0} label={label} title={title}>
<>
{data == null || totalCount == null || totalCount === 0 ? (
<DonutChartEmpty size={height} />
) : (
<Chart size={height}>
<Settings theme={donutTheme} baseTheme={theme} onElementClick={onElementClick} />
<Settings theme={donutTheme} baseTheme={theme} />
<Partition
id="donut-chart"
data={data}
Expand All @@ -135,12 +164,13 @@ export const DonutChart = ({
/>
</Chart>
)}
</StyledEuiFlexItem>
{legendItems && legendItems?.length > 0 && (
<EuiFlexItem>
<DraggableLegend legendItems={legendItems} height={height} />
</EuiFlexItem>
)}
</EuiFlexGroup>

{legendItems && legendItems?.length > 0 && (
<EuiFlexItem>
<DraggableLegend legendItems={legendItems} height={height} />
</EuiFlexItem>
)}
</>
</DonutChartWrapper>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
/*
* 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 type { GetLensAttributes, LensAttributes } from '../../../types';

export const getAlertsBySeverityAttributes: GetLensAttributes = (
stackByField = 'kibana.alert.workflow_status',
extraOptions
) =>
({
title: 'Alerts',
description: '',
visualizationType: 'lnsPie',
state: {
visualization: {
shape: 'donut',
layers: [
{
layerId: '51ed355e-6e23-4038-a417-f653a1160370',
primaryGroups: ['a9b43606-7ff7-46ae-a47c-85bed80fab9a'],
metrics: ['21cc4a49-3780-4b1a-be28-f02fa5303d24'],
numberDisplay: 'value',
categoryDisplay: 'hide',
legendDisplay: 'hide',
nestedLegend: true,
layerType: 'data',
emptySizeRatio: 0.85,
percentDecimals: 2,
},
],
},
query: {
query: '',
language: 'kuery',
},
filters: [
{
meta: {
disabled: false,
negate: false,
alias: null,
index: 'a1aaa83b-5026-444e-9465-50e0afade01c',
key: stackByField,
field: stackByField,
params: {
query: extraOptions?.status,
},
type: 'phrase',
},
query: {
match_phrase: {
[stackByField]: extraOptions?.status,
},
},
},
{
meta: {
type: 'phrases',
key: '_index',
params: ['.alerts-security.alerts-default'],
alias: null,
negate: false,
disabled: false,
},
query: {
bool: {
should: [
{
match_phrase: {
_index: '.alerts-security.alerts-default',
},
},
],
minimum_should_match: 1,
},
},
},
],
datasourceStates: {
formBased: {
layers: {
'51ed355e-6e23-4038-a417-f653a1160370': {
columns: {
'a9b43606-7ff7-46ae-a47c-85bed80fab9a': {
label: 'Filters',
dataType: 'string',
operationType: 'filters',
scale: 'ordinal',
isBucketed: true,
params: {
filters: [
{
input: {
query: 'kibana.alert.severity: "critical"',
language: 'kuery',
},
label: 'Critical',
},
{
label: 'High',
input: {
query: 'kibana.alert.severity : "high" ',
language: 'kuery',
},
},
{
input: {
query: 'kibana.alert.severity: "medium"',
language: 'kuery',
},
label: 'Medium',
},
{
input: {
query: 'kibana.alert.severity : "low" ',
language: 'kuery',
},
label: 'Low',
},
],
},
},
'21cc4a49-3780-4b1a-be28-f02fa5303d24': {
label: 'Count of records',
dataType: 'number',
operationType: 'count',
isBucketed: false,
scale: 'ratio',
sourceField: '___records___',
filter: {
query: '',
language: 'kuery',
},
params: {
emptyAsNull: true,
},
},
},
columnOrder: [
'a9b43606-7ff7-46ae-a47c-85bed80fab9a',
'21cc4a49-3780-4b1a-be28-f02fa5303d24',
],
sampling: 1,
incompleteColumns: {},
},
},
},
textBased: {
layers: {},
},
},
internalReferences: [],
adHocDataViews: {},
},
references: [
{
type: 'index-pattern',
id: '{dataViewId}',
name: 'indexpattern-datasource-layer-51ed355e-6e23-4038-a417-f653a1160370',
},
{
type: 'index-pattern',
name: 'a1aaa83b-5026-444e-9465-50e0afade01c',
id: '{dataViewId}',
},
],
} as LensAttributes);
Loading

0 comments on commit 785712e

Please sign in to comment.