mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
Upgrade elastic charts v43.1.1 (#121593)
This commit is contained in:
parent
9575ebbcaf
commit
71e9c609fc
39 changed files with 1150 additions and 953 deletions
|
@ -103,7 +103,7 @@
|
|||
"@elastic/apm-rum": "^5.10.1",
|
||||
"@elastic/apm-rum-react": "^1.3.3",
|
||||
"@elastic/apm-synthtrace": "link:bazel-bin/packages/elastic-apm-synthtrace",
|
||||
"@elastic/charts": "40.2.0",
|
||||
"@elastic/charts": "43.1.1",
|
||||
"@elastic/datemath": "link:bazel-bin/packages/elastic-datemath",
|
||||
"@elastic/elasticsearch": "npm:@elastic/elasticsearch-canary@8.1.0-canary.2",
|
||||
"@elastic/ems-client": "8.0.0",
|
||||
|
|
|
@ -4,11 +4,11 @@ exports[`GaugeComponent renders the chart 1`] = `
|
|||
<Chart
|
||||
renderer="canvas"
|
||||
>
|
||||
<Connect(SpecInstance)
|
||||
<Settings
|
||||
debugState={false}
|
||||
theme={Object {}}
|
||||
/>
|
||||
<Connect(SpecInstance)
|
||||
<Component
|
||||
actual={3}
|
||||
bandFillColor={[Function]}
|
||||
bands={
|
||||
|
|
|
@ -20,6 +20,7 @@ import {
|
|||
TooltipProps,
|
||||
ESFixedIntervalUnit,
|
||||
ESCalendarIntervalUnit,
|
||||
PartialTheme,
|
||||
} from '@elastic/charts';
|
||||
import type { CustomPaletteState } from '../../../../charts/public';
|
||||
import { search } from '../../../../data/public';
|
||||
|
@ -381,62 +382,61 @@ export const HeatmapComponent: FC<HeatmapRenderProps> = memo(
|
|||
}
|
||||
};
|
||||
|
||||
const config: HeatmapSpec['config'] = {
|
||||
grid: {
|
||||
stroke: {
|
||||
width:
|
||||
args.gridConfig.strokeWidth ?? chartTheme.axes?.gridLine?.horizontal?.strokeWidth ?? 1,
|
||||
color:
|
||||
args.gridConfig.strokeColor ??
|
||||
chartTheme.axes?.gridLine?.horizontal?.stroke ??
|
||||
'#D3DAE6',
|
||||
},
|
||||
cellHeight: {
|
||||
max: 'fill',
|
||||
min: 1,
|
||||
const themeOverrides: PartialTheme = {
|
||||
legend: {
|
||||
labelOptions: {
|
||||
maxLines: args.legend.shouldTruncate ? args.legend?.maxLines ?? 1 : 0,
|
||||
},
|
||||
},
|
||||
cell: {
|
||||
maxWidth: 'fill',
|
||||
maxHeight: 'fill',
|
||||
label: {
|
||||
visible: args.gridConfig.isCellLabelVisible ?? false,
|
||||
minFontSize: 8,
|
||||
maxFontSize: 18,
|
||||
useGlobalMinFontSize: true, // override the min if there's a different directive upstream
|
||||
heatmap: {
|
||||
grid: {
|
||||
stroke: {
|
||||
width:
|
||||
args.gridConfig.strokeWidth ??
|
||||
chartTheme.axes?.gridLine?.horizontal?.strokeWidth ??
|
||||
1,
|
||||
color:
|
||||
args.gridConfig.strokeColor ??
|
||||
chartTheme.axes?.gridLine?.horizontal?.stroke ??
|
||||
'#D3DAE6',
|
||||
},
|
||||
cellHeight: {
|
||||
max: 'fill',
|
||||
min: 1,
|
||||
},
|
||||
},
|
||||
border: {
|
||||
strokeWidth: 0,
|
||||
cell: {
|
||||
maxWidth: 'fill',
|
||||
maxHeight: 'fill',
|
||||
label: {
|
||||
visible: args.gridConfig.isCellLabelVisible ?? false,
|
||||
minFontSize: 8,
|
||||
maxFontSize: 18,
|
||||
useGlobalMinFontSize: true, // override the min if there's a different directive upstream
|
||||
},
|
||||
border: {
|
||||
strokeWidth: 0,
|
||||
},
|
||||
},
|
||||
yAxisLabel: {
|
||||
visible: !!yAxisColumn && args.gridConfig.isYAxisLabelVisible,
|
||||
// eui color subdued
|
||||
textColor: chartTheme.axes?.tickLabel?.fill ?? '#6a717d',
|
||||
padding: yAxisColumn?.name ? 8 : 0,
|
||||
},
|
||||
xAxisLabel: {
|
||||
visible: Boolean(args.gridConfig.isXAxisLabelVisible && xAxisColumn),
|
||||
// eui color subdued
|
||||
textColor: chartTheme.axes?.tickLabel?.fill ?? `#6a717d`,
|
||||
padding: xAxisColumn?.name ? 8 : 0,
|
||||
},
|
||||
brushMask: {
|
||||
fill: isDarkTheme ? 'rgb(30,31,35,80%)' : 'rgb(247,247,247,50%)',
|
||||
},
|
||||
brushArea: {
|
||||
stroke: isDarkTheme ? 'rgb(255, 255, 255)' : 'rgb(105, 112, 125)',
|
||||
},
|
||||
},
|
||||
yAxisLabel: {
|
||||
visible: !!yAxisColumn && args.gridConfig.isYAxisLabelVisible,
|
||||
// eui color subdued
|
||||
textColor: chartTheme.axes?.tickLabel?.fill ?? '#6a717d',
|
||||
padding: yAxisColumn?.name ? 8 : 0,
|
||||
name: yAxisColumn?.name ?? '',
|
||||
...(yAxisColumn
|
||||
? {
|
||||
formatter: (v: number | string) =>
|
||||
`${formatFactory(yAxisColumn.meta.params).convert(v) ?? ''}`,
|
||||
}
|
||||
: {}),
|
||||
},
|
||||
xAxisLabel: {
|
||||
visible: Boolean(args.gridConfig.isXAxisLabelVisible && xAxisColumn),
|
||||
// eui color subdued
|
||||
textColor: chartTheme.axes?.tickLabel?.fill ?? `#6a717d`,
|
||||
padding: xAxisColumn?.name ? 8 : 0,
|
||||
formatter: (v: number | string) => `${xValuesFormatter.convert(v) ?? ''}`,
|
||||
name: xAxisColumn?.name ?? '',
|
||||
},
|
||||
brushMask: {
|
||||
fill: isDarkTheme ? 'rgb(30,31,35,80%)' : 'rgb(247,247,247,50%)',
|
||||
},
|
||||
brushArea: {
|
||||
stroke: isDarkTheme ? 'rgb(255, 255, 255)' : 'rgb(105, 112, 125)',
|
||||
},
|
||||
timeZone,
|
||||
};
|
||||
|
||||
return (
|
||||
|
@ -456,14 +456,7 @@ export const HeatmapComponent: FC<HeatmapRenderProps> = memo(
|
|||
legendColorPicker={uiState ? legendColorPicker : undefined}
|
||||
debugState={window._echDebugStateFlag ?? false}
|
||||
tooltip={tooltip}
|
||||
theme={{
|
||||
...chartTheme,
|
||||
legend: {
|
||||
labelOptions: {
|
||||
maxLines: args.legend.shouldTruncate ? args.legend?.maxLines ?? 1 : 0,
|
||||
},
|
||||
},
|
||||
}}
|
||||
theme={[themeOverrides, chartTheme]}
|
||||
xDomain={{
|
||||
min:
|
||||
dateHistogramMeta && dateHistogramMeta.timeRange
|
||||
|
@ -483,6 +476,7 @@ export const HeatmapComponent: FC<HeatmapRenderProps> = memo(
|
|||
type: 'bands',
|
||||
bands,
|
||||
}}
|
||||
timeZone={timeZone}
|
||||
data={chartData}
|
||||
xAccessor={xAccessor}
|
||||
yAccessor={yAccessor || 'unifiedY'}
|
||||
|
@ -490,8 +484,15 @@ export const HeatmapComponent: FC<HeatmapRenderProps> = memo(
|
|||
valueFormatter={valueFormatter}
|
||||
xScale={xScale}
|
||||
ySortPredicate={yAxisColumn ? getSortPredicate(yAxisColumn) : 'dataIndex'}
|
||||
config={config}
|
||||
xSortPredicate={xAxisColumn ? getSortPredicate(xAxisColumn) : 'dataIndex'}
|
||||
xAxisLabelName={xAxisColumn?.name}
|
||||
yAxisLabelName={yAxisColumn?.name}
|
||||
xAxisLabelFormatter={(v) => `${xValuesFormatter.convert(v) ?? ''}`}
|
||||
yAxisLabelFormatter={
|
||||
yAxisColumn
|
||||
? (v) => `${formatFactory(yAxisColumn.meta.params).convert(v) ?? ''}`
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
</Chart>
|
||||
</>
|
||||
|
|
|
@ -18,6 +18,7 @@ import {
|
|||
TooltipProps,
|
||||
TooltipType,
|
||||
SeriesIdentifier,
|
||||
PartitionLayout,
|
||||
} from '@elastic/charts';
|
||||
import { useEuiTheme } from '@elastic/eui';
|
||||
import {
|
||||
|
@ -47,7 +48,7 @@ import {
|
|||
canFilter,
|
||||
getFilterClickData,
|
||||
getFilterEventData,
|
||||
getConfig,
|
||||
getPartitionTheme,
|
||||
getColumns,
|
||||
getSplitDimensionAccessor,
|
||||
getColumnByAccessor,
|
||||
|
@ -251,8 +252,8 @@ const PieComponent = (props: PieComponentProps) => {
|
|||
return 1;
|
||||
}, [visData.rows, metricColumn]);
|
||||
|
||||
const config = useMemo(
|
||||
() => getConfig(visParams, chartTheme, dimensions, rescaleFactor),
|
||||
const themeOverrides = useMemo(
|
||||
() => getPartitionTheme(visParams, chartTheme, dimensions, rescaleFactor),
|
||||
[chartTheme, visParams, dimensions, rescaleFactor]
|
||||
);
|
||||
const tooltip: TooltipProps = {
|
||||
|
@ -369,7 +370,9 @@ const PieComponent = (props: PieComponentProps) => {
|
|||
)}
|
||||
theme={[
|
||||
// Chart background should be transparent for the usage at Canvas.
|
||||
{ ...chartTheme, background: { color: 'transparent' } },
|
||||
{ background: { color: 'transparent' } },
|
||||
themeOverrides,
|
||||
chartTheme,
|
||||
{
|
||||
legend: {
|
||||
labelOptions: {
|
||||
|
@ -385,6 +388,8 @@ const PieComponent = (props: PieComponentProps) => {
|
|||
id="pie"
|
||||
smallMultiples={SMALL_MULTIPLES_ID}
|
||||
data={visData.rows}
|
||||
layout={PartitionLayout.sunburst}
|
||||
specialFirstInnermostSector={false}
|
||||
valueAccessor={(d: Datum) => getSliceValue(d, metricColumn)}
|
||||
percentFormatter={(d: number) => percentFormatter.convert(d / 100)}
|
||||
valueGetter={
|
||||
|
@ -400,7 +405,6 @@ const PieComponent = (props: PieComponentProps) => {
|
|||
: metricFieldFormatter.convert(d)
|
||||
}
|
||||
layers={layers}
|
||||
config={config}
|
||||
topGroove={!visParams.labels.show ? 0 : undefined}
|
||||
/>
|
||||
</Chart>
|
||||
|
|
|
@ -1,81 +0,0 @@
|
|||
/*
|
||||
* 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 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { PartitionConfig, PartitionLayout, RecursivePartial, Theme } from '@elastic/charts';
|
||||
import { LabelPositions, PieVisParams, PieContainerDimensions } from '../../common/types';
|
||||
|
||||
const MAX_SIZE = 1000;
|
||||
|
||||
export const getConfig = (
|
||||
visParams: PieVisParams,
|
||||
chartTheme: RecursivePartial<Theme>,
|
||||
dimensions?: PieContainerDimensions,
|
||||
rescaleFactor: number = 1
|
||||
): RecursivePartial<PartitionConfig> => {
|
||||
// On small multiples we want the labels to only appear inside
|
||||
const isSplitChart = Boolean(visParams.dimensions.splitColumn || visParams.dimensions.splitRow);
|
||||
const usingMargin =
|
||||
dimensions && !isSplitChart
|
||||
? {
|
||||
margin: {
|
||||
top: (1 - Math.min(1, MAX_SIZE / dimensions?.height)) / 2,
|
||||
bottom: (1 - Math.min(1, MAX_SIZE / dimensions?.height)) / 2,
|
||||
left: (1 - Math.min(1, MAX_SIZE / dimensions?.width)) / 2,
|
||||
right: (1 - Math.min(1, MAX_SIZE / dimensions?.width)) / 2,
|
||||
},
|
||||
}
|
||||
: null;
|
||||
|
||||
const usingOuterSizeRatio =
|
||||
dimensions && !isSplitChart
|
||||
? {
|
||||
outerSizeRatio:
|
||||
// Cap the ratio to 1 and then rescale
|
||||
rescaleFactor * Math.min(MAX_SIZE / Math.min(dimensions?.width, dimensions?.height), 1),
|
||||
}
|
||||
: null;
|
||||
const config: RecursivePartial<PartitionConfig> = {
|
||||
partitionLayout: PartitionLayout.sunburst,
|
||||
fontFamily: chartTheme.barSeriesStyle?.displayValue?.fontFamily,
|
||||
...usingOuterSizeRatio,
|
||||
specialFirstInnermostSector: false,
|
||||
minFontSize: 10,
|
||||
maxFontSize: 16,
|
||||
linkLabel: {
|
||||
maxCount: 5,
|
||||
fontSize: 11,
|
||||
textColor: chartTheme.axes?.axisTitle?.fill,
|
||||
maxTextLength: visParams.labels.truncate ?? undefined,
|
||||
},
|
||||
sectorLineStroke: chartTheme.lineSeriesStyle?.point?.fill,
|
||||
sectorLineWidth: 1.5,
|
||||
circlePadding: 4,
|
||||
emptySizeRatio: visParams.isDonut ? visParams.emptySizeRatio : 0,
|
||||
...usingMargin,
|
||||
};
|
||||
if (!visParams.labels.show) {
|
||||
// Force all labels to be linked, then prevent links from showing
|
||||
config.linkLabel = { maxCount: 0, maximumSection: Number.POSITIVE_INFINITY };
|
||||
}
|
||||
|
||||
if (visParams.labels.last_level && visParams.labels.show) {
|
||||
config.linkLabel = {
|
||||
maxCount: Number.POSITIVE_INFINITY,
|
||||
maximumSection: Number.POSITIVE_INFINITY,
|
||||
maxTextLength: visParams.labels.truncate ?? undefined,
|
||||
};
|
||||
}
|
||||
|
||||
if (
|
||||
(visParams.labels.position === LabelPositions.INSIDE || isSplitChart) &&
|
||||
visParams.labels.show
|
||||
) {
|
||||
config.linkLabel = { maxCount: 0 };
|
||||
}
|
||||
return config;
|
||||
};
|
|
@ -6,13 +6,7 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import {
|
||||
Datum,
|
||||
PartitionFillLabel,
|
||||
PartitionLayer,
|
||||
ShapeTreeNode,
|
||||
ArrayEntry,
|
||||
} from '@elastic/charts';
|
||||
import { Datum, PartitionLayer, ShapeTreeNode, ArrayEntry } from '@elastic/charts';
|
||||
import { isEqual } from 'lodash';
|
||||
import type { FieldFormatsStart } from 'src/plugins/field_formats/public';
|
||||
import { SeriesLayer, PaletteRegistry, lightenColor } from '../../../../charts/public';
|
||||
|
@ -137,7 +131,7 @@ export const getLayers = (
|
|||
formatter: FieldFormatsStart,
|
||||
syncColors: boolean
|
||||
): PartitionLayer[] => {
|
||||
const fillLabel: Partial<PartitionFillLabel> = {
|
||||
const fillLabel: PartitionLayer['fillLabel'] = {
|
||||
valueFont: {
|
||||
fontWeight: 700,
|
||||
},
|
||||
|
|
|
@ -6,19 +6,21 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { getConfig } from './get_config';
|
||||
import { getPartitionTheme } from './get_partition_theme';
|
||||
import { createMockPieParams } from '../mocks';
|
||||
|
||||
const visParams = createMockPieParams();
|
||||
|
||||
describe('getConfig', () => {
|
||||
it('should cap the outerSizeRatio to 1', () => {
|
||||
expect(getConfig(visParams, {}, { width: 400, height: 400 }).outerSizeRatio).toBe(1);
|
||||
expect(
|
||||
getPartitionTheme(visParams, {}, { width: 400, height: 400 }).partition?.outerSizeRatio
|
||||
).toBe(1);
|
||||
});
|
||||
|
||||
it('should not have outerSizeRatio for split chart', () => {
|
||||
expect(
|
||||
getConfig(
|
||||
getPartitionTheme(
|
||||
{
|
||||
...visParams,
|
||||
dimensions: {
|
||||
|
@ -37,11 +39,11 @@ describe('getConfig', () => {
|
|||
},
|
||||
{},
|
||||
{ width: 400, height: 400 }
|
||||
).outerSizeRatio
|
||||
).partition?.outerSizeRatio
|
||||
).toBeUndefined();
|
||||
|
||||
expect(
|
||||
getConfig(
|
||||
getPartitionTheme(
|
||||
{
|
||||
...visParams,
|
||||
dimensions: {
|
||||
|
@ -60,11 +62,11 @@ describe('getConfig', () => {
|
|||
},
|
||||
{},
|
||||
{ width: 400, height: 400 }
|
||||
).outerSizeRatio
|
||||
).partition?.outerSizeRatio
|
||||
).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should not set outerSizeRatio if dimensions are not defined', () => {
|
||||
expect(getConfig(visParams, {}).outerSizeRatio).toBeUndefined();
|
||||
expect(getPartitionTheme(visParams, {}).partition?.outerSizeRatio).toBeUndefined();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* 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 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { PartialTheme } from '@elastic/charts';
|
||||
import { Required } from '@kbn/utility-types';
|
||||
import { LabelPositions, PieVisParams, PieContainerDimensions } from '../../common/types';
|
||||
|
||||
const MAX_SIZE = 1000;
|
||||
|
||||
export const getPartitionTheme = (
|
||||
visParams: PieVisParams,
|
||||
chartTheme: PartialTheme,
|
||||
dimensions?: PieContainerDimensions,
|
||||
rescaleFactor: number = 1
|
||||
): PartialTheme => {
|
||||
// On small multiples we want the labels to only appear inside
|
||||
const isSplitChart = Boolean(visParams.dimensions.splitColumn || visParams.dimensions.splitRow);
|
||||
const paddingProps: PartialTheme | null =
|
||||
dimensions && !isSplitChart
|
||||
? {
|
||||
chartPaddings: {
|
||||
// TODO: simplify ratio logic to be static px units
|
||||
top: ((1 - Math.min(1, MAX_SIZE / dimensions?.height)) / 2) * dimensions?.height,
|
||||
bottom: ((1 - Math.min(1, MAX_SIZE / dimensions?.height)) / 2) * dimensions?.height,
|
||||
left: ((1 - Math.min(1, MAX_SIZE / dimensions?.width)) / 2) * dimensions?.height,
|
||||
right: ((1 - Math.min(1, MAX_SIZE / dimensions?.width)) / 2) * dimensions?.height,
|
||||
},
|
||||
}
|
||||
: null;
|
||||
|
||||
const outerSizeRatio: PartialTheme['partition'] | null =
|
||||
dimensions && !isSplitChart
|
||||
? {
|
||||
outerSizeRatio:
|
||||
// Cap the ratio to 1 and then rescale
|
||||
rescaleFactor * Math.min(MAX_SIZE / Math.min(dimensions?.width, dimensions?.height), 1),
|
||||
}
|
||||
: null;
|
||||
const theme: Required<PartialTheme, 'partition'> = {
|
||||
chartMargins: { top: 0, bottom: 0, left: 0, right: 0 },
|
||||
...paddingProps,
|
||||
partition: {
|
||||
fontFamily: chartTheme.barSeriesStyle?.displayValue?.fontFamily,
|
||||
...outerSizeRatio,
|
||||
minFontSize: 10,
|
||||
maxFontSize: 16,
|
||||
linkLabel: {
|
||||
maxCount: 5,
|
||||
fontSize: 11,
|
||||
textColor: chartTheme.axes?.axisTitle?.fill,
|
||||
maxTextLength: visParams.labels.truncate ?? undefined,
|
||||
},
|
||||
sectorLineStroke: chartTheme.lineSeriesStyle?.point?.fill,
|
||||
sectorLineWidth: 1.5,
|
||||
circlePadding: 4,
|
||||
emptySizeRatio: visParams.isDonut ? visParams.emptySizeRatio : 0,
|
||||
},
|
||||
};
|
||||
if (!visParams.labels.show) {
|
||||
// Force all labels to be linked, then prevent links from showing
|
||||
theme.partition.linkLabel = { maxCount: 0, maximumSection: Number.POSITIVE_INFINITY };
|
||||
}
|
||||
|
||||
if (visParams.labels.last_level && visParams.labels.show) {
|
||||
theme.partition.linkLabel = {
|
||||
maxCount: Number.POSITIVE_INFINITY,
|
||||
maximumSection: Number.POSITIVE_INFINITY,
|
||||
maxTextLength: visParams.labels.truncate ?? undefined,
|
||||
};
|
||||
}
|
||||
|
||||
if (
|
||||
(visParams.labels.position === LabelPositions.INSIDE || isSplitChart) &&
|
||||
visParams.labels.show
|
||||
) {
|
||||
theme.partition.linkLabel = { maxCount: 0 };
|
||||
}
|
||||
|
||||
return theme;
|
||||
};
|
|
@ -10,7 +10,7 @@ export { getLayers } from './get_layers';
|
|||
export { getColorPicker } from './get_color_picker';
|
||||
export { getLegendActions } from './get_legend_actions';
|
||||
export { canFilter, getFilterClickData, getFilterEventData } from './filter_helpers';
|
||||
export { getConfig } from './get_config';
|
||||
export { getPartitionTheme } from './get_partition_theme';
|
||||
export { getColumns } from './get_columns';
|
||||
export { getSplitDimensionAccessor } from './get_split_dimension_accessor';
|
||||
export { getDistinctSeries } from './get_distinct_series';
|
||||
|
|
|
@ -12,11 +12,11 @@ import { take } from 'rxjs/operators';
|
|||
import { renderHook, act } from '@testing-library/react-hooks';
|
||||
import { render, act as renderAct } from '@testing-library/react';
|
||||
|
||||
import { LIGHT_THEME, DARK_THEME } from '@elastic/charts';
|
||||
import { EUI_CHARTS_THEME_DARK, EUI_CHARTS_THEME_LIGHT } from '@elastic/eui/dist/eui_charts_theme';
|
||||
|
||||
import { ThemeService } from './theme';
|
||||
import { coreMock } from '../../../../../core/public/mocks';
|
||||
import { LIGHT_THEME, DARK_THEME } from '@elastic/charts';
|
||||
|
||||
const { uiSettings: setupMockUiSettings } = coreMock.createSetup();
|
||||
|
||||
|
|
|
@ -89,9 +89,8 @@ export class ThemeService {
|
|||
public init(uiSettings: CoreSetup['uiSettings']) {
|
||||
this._uiSettingsDarkMode$ = uiSettings.get$<boolean>('theme:darkMode');
|
||||
this._uiSettingsDarkMode$.subscribe((darkMode) => {
|
||||
this._chartsTheme$.next(
|
||||
darkMode ? EUI_CHARTS_THEME_DARK.theme : EUI_CHARTS_THEME_LIGHT.theme
|
||||
);
|
||||
const theme = darkMode ? EUI_CHARTS_THEME_DARK.theme : EUI_CHARTS_THEME_LIGHT.theme;
|
||||
this._chartsTheme$.next(theme);
|
||||
this._chartsBaseTheme$.next(darkMode ? DARK_THEME : LIGHT_THEME);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -28,19 +28,21 @@ export interface BrushTriggerEvent {
|
|||
data: RangeSelectContext['data'];
|
||||
}
|
||||
|
||||
type AllSeriesAccessors = Array<[accessor: Accessor | AccessorFn, value: string | number]>;
|
||||
type AllSeriesAccessors<D = any> = Array<
|
||||
[accessor: Accessor<D> | AccessorFn<D>, value: string | number]
|
||||
>;
|
||||
|
||||
/**
|
||||
* returns accessor value from string or function accessor
|
||||
* @param datum
|
||||
* @param accessor
|
||||
*/
|
||||
function getAccessorValue(datum: Datum, accessor: Accessor | AccessorFn) {
|
||||
function getAccessorValue<D>(datum: D, accessor: Accessor<D> | AccessorFn<D>) {
|
||||
if (typeof accessor === 'function') {
|
||||
return accessor(datum);
|
||||
}
|
||||
|
||||
return datum[accessor];
|
||||
return (datum as Datum)[accessor];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -259,9 +261,11 @@ export const getFilterFromSeriesFn =
|
|||
/**
|
||||
* Helper function to transform `@elastic/charts` brush event into brush action event
|
||||
*/
|
||||
export const getBrushFromChartBrushEventFn =
|
||||
(table: Datatable, xAccessor: Accessor | AccessorFn) =>
|
||||
({ x: selectedRange }: XYBrushEvent): BrushTriggerEvent => {
|
||||
export function getBrushFromChartBrushEventFn<D = never>(
|
||||
table: Datatable,
|
||||
xAccessor: Accessor<D> | AccessorFn<D>
|
||||
) {
|
||||
return ({ x: selectedRange }: XYBrushEvent): BrushTriggerEvent => {
|
||||
const [start, end] = selectedRange ?? [0, 0];
|
||||
const range: [number, number] = [start, end];
|
||||
const column = table.columns.findIndex(({ id }) => validateAccessorId(id, xAccessor));
|
||||
|
@ -275,3 +279,4 @@ export const getBrushFromChartBrushEventFn =
|
|||
name: 'brush',
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -38,30 +38,32 @@ const getPointFillColor = (points: VisSeries['points'], color: string | undefine
|
|||
);
|
||||
};
|
||||
|
||||
const getAreaSeriesStyle = ({ color, lines, points }: AreaSeriesComponentProps['visData']) =>
|
||||
({
|
||||
line: {
|
||||
opacity: isShowLines(lines, points) ? 1 : 0,
|
||||
stroke: color,
|
||||
strokeWidth: lines?.lineWidth !== undefined ? Number(lines.lineWidth) : 3,
|
||||
visible: isShowLines(lines, points),
|
||||
},
|
||||
area: {
|
||||
fill: color,
|
||||
opacity: lines?.fill ?? 0,
|
||||
visible: lines?.show ?? points?.show ?? true,
|
||||
},
|
||||
point: {
|
||||
fill: getPointFillColor(points, color),
|
||||
opacity: 1,
|
||||
radius: points?.radius ?? 3,
|
||||
stroke: color,
|
||||
strokeWidth: points?.lineWidth ?? 2,
|
||||
visible: points?.show ?? false,
|
||||
shape: points?.symbol === 'cross' ? PointShape.X : points?.symbol,
|
||||
},
|
||||
curve: lines?.steps ? CurveType.CURVE_STEP : CurveType.LINEAR,
|
||||
} as RecursivePartial<AreaSeriesStyle>);
|
||||
const getAreaSeriesStyle = ({
|
||||
color,
|
||||
lines,
|
||||
points,
|
||||
}: AreaSeriesComponentProps['visData']): RecursivePartial<AreaSeriesStyle> => ({
|
||||
line: {
|
||||
opacity: isShowLines(lines, points) ? 1 : 0,
|
||||
stroke: color,
|
||||
strokeWidth: lines?.lineWidth !== undefined ? Number(lines.lineWidth) : 3,
|
||||
visible: isShowLines(lines, points),
|
||||
},
|
||||
area: {
|
||||
fill: color,
|
||||
opacity: lines?.fill ?? 0,
|
||||
visible: lines?.show ?? points?.show ?? true,
|
||||
},
|
||||
point: {
|
||||
fill: getPointFillColor(points, color),
|
||||
opacity: 1,
|
||||
radius: points?.radius ?? 3,
|
||||
stroke: color,
|
||||
strokeWidth: points?.lineWidth ?? 2,
|
||||
visible: points?.show ?? false,
|
||||
shape: points?.symbol === 'cross' ? PointShape.X : points?.symbol,
|
||||
},
|
||||
});
|
||||
|
||||
export const AreaSeriesComponent = ({ index, groupId, visData }: AreaSeriesComponentProps) => (
|
||||
<AreaSeries
|
||||
|
@ -75,6 +77,7 @@ export const AreaSeriesComponent = ({ index, groupId, visData }: AreaSeriesCompo
|
|||
data={visData._hide ? [] : visData.data}
|
||||
sortIndex={index}
|
||||
color={visData.color}
|
||||
curve={visData.lines?.steps ? CurveType.CURVE_STEP : CurveType.LINEAR}
|
||||
stackAccessors={visData.stack ? [0] : undefined}
|
||||
areaSeriesStyle={getAreaSeriesStyle(visData)}
|
||||
/>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`src/legacy/core_plugins/metrics/public/visualizations/views/timeseries/decorators/area_decorator.js <AreaSeriesDecorator /> should render and match a snapshot 1`] = `
|
||||
<Connect(SpecInstance)
|
||||
<AreaSeries
|
||||
areaSeriesStyle={
|
||||
Object {
|
||||
"area": Object {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`src/legacy/core_plugins/metrics/public/visualizations/views/timeseries/decorators/bar_decorator.js <BarSeriesDecorator /> should render and match a snapshot 1`] = `
|
||||
<Connect(SpecInstance)
|
||||
<BarSeries
|
||||
barSeriesStyle={
|
||||
Object {
|
||||
"rect": Object {
|
||||
|
|
|
@ -11,7 +11,7 @@ import React, { FC } from 'react';
|
|||
import {
|
||||
Direction,
|
||||
Settings,
|
||||
SettingsSpecProps,
|
||||
SettingsProps,
|
||||
DomainRange,
|
||||
Position,
|
||||
PartialTheme,
|
||||
|
@ -50,7 +50,7 @@ type XYSettingsProps = Pick<
|
|||
| 'xAxis'
|
||||
| 'orderBucketsBySum'
|
||||
> & {
|
||||
onPointerUpdate: SettingsSpecProps['onPointerUpdate'];
|
||||
onPointerUpdate: SettingsProps['onPointerUpdate'];
|
||||
xDomain?: DomainRange;
|
||||
adjustedXDomain?: DomainRange;
|
||||
showLegend: boolean;
|
||||
|
|
|
@ -255,7 +255,7 @@ export class VisualizeChartPageObject extends FtrService {
|
|||
|
||||
if (isVisTypeHeatmapChart) {
|
||||
const legendItems =
|
||||
(await this.getEsChartDebugState(heatmapChartSelector))?.legend!.items ?? [];
|
||||
(await this.getEsChartDebugState(heatmapChartSelector))?.legend?.items ?? [];
|
||||
return legendItems.map(({ name }) => name);
|
||||
}
|
||||
|
||||
|
|
|
@ -121,6 +121,8 @@ export function PageLoadDistChart({
|
|||
fit={Fit.Linear}
|
||||
id={'PagesPercentage'}
|
||||
name={I18LABELS.overall}
|
||||
xAccessor="x"
|
||||
yAccessors={['y']}
|
||||
xScaleType={ScaleType.Linear}
|
||||
yScaleType={ScaleType.Linear}
|
||||
data={data?.pageLoadDistribution ?? []}
|
||||
|
|
|
@ -38,9 +38,15 @@ interface Props {
|
|||
}
|
||||
|
||||
const theme: PartialTheme = {
|
||||
chartMargins: { top: 0, bottom: 0, left: 0, right: 0 },
|
||||
legend: {
|
||||
verticalWidth: 100,
|
||||
},
|
||||
partition: {
|
||||
linkLabel: { maximumSection: Infinity, maxCount: 0 },
|
||||
outerSizeRatio: 1, // - 0.5 * Math.random(),
|
||||
circlePadding: 4,
|
||||
},
|
||||
};
|
||||
|
||||
export function VisitorBreakdownChart({ loading, options }: Props) {
|
||||
|
@ -64,6 +70,8 @@ export function VisitorBreakdownChart({ loading, options }: Props) {
|
|||
data={
|
||||
options?.length ? options : [{ count: 1, name: I18LABELS.noData }]
|
||||
}
|
||||
layout={PartitionLayout.sunburst}
|
||||
clockwiseSectors={false}
|
||||
valueAccessor={(d: Datum) => d.count as number}
|
||||
valueGetter="percent"
|
||||
percentFormatter={(d: number) =>
|
||||
|
@ -78,14 +86,6 @@ export function VisitorBreakdownChart({ loading, options }: Props) {
|
|||
},
|
||||
},
|
||||
]}
|
||||
config={{
|
||||
partitionLayout: PartitionLayout.sunburst,
|
||||
linkLabel: { maximumSection: Infinity, maxCount: 0 },
|
||||
margin: { top: 0, bottom: 0, left: 0, right: 0 },
|
||||
outerSizeRatio: 1, // - 0.5 * Math.random(),
|
||||
circlePadding: 4,
|
||||
clockwiseSectors: false,
|
||||
}}
|
||||
/>
|
||||
</Chart>
|
||||
</StyleChart>
|
||||
|
|
|
@ -54,6 +54,8 @@ export function BreakdownSeries({
|
|||
id={`${field}-${value}-${name}`}
|
||||
key={`${field}-${value}-${name}`}
|
||||
name={name}
|
||||
xAccessor="x"
|
||||
yAccessors={['y']}
|
||||
xScaleType={ScaleType.Linear}
|
||||
yScaleType={ScaleType.Linear}
|
||||
curve={CurveType.CURVE_CATMULL_ROM}
|
||||
|
|
|
@ -12,6 +12,7 @@ import {
|
|||
PrimitiveValue,
|
||||
Settings,
|
||||
TooltipInfo,
|
||||
PartialTheme,
|
||||
} from '@elastic/charts';
|
||||
import {
|
||||
EuiCheckbox,
|
||||
|
@ -286,6 +287,18 @@ export function ServiceProfilingFlamegraph({
|
|||
}, [points, highlightFilter, data]);
|
||||
|
||||
const chartTheme = useChartTheme();
|
||||
const themeOverrides: PartialTheme = {
|
||||
chartMargins: { top: 0, bottom: 0, left: 0, right: 0 },
|
||||
partition: {
|
||||
fillLabel: {
|
||||
fontFamily: theme.eui.euiCodeFontFamily,
|
||||
clipText: true,
|
||||
},
|
||||
fontFamily: theme.eui.euiCodeFontFamily,
|
||||
minFontSize: 9,
|
||||
maxFontSize: 9,
|
||||
},
|
||||
};
|
||||
|
||||
const chartSize = {
|
||||
height: layers.length * 20,
|
||||
|
@ -305,7 +318,7 @@ export function ServiceProfilingFlamegraph({
|
|||
<EuiFlexItem grow>
|
||||
<Chart size={chartSize}>
|
||||
<Settings
|
||||
theme={chartTheme}
|
||||
theme={[themeOverrides, ...chartTheme]}
|
||||
tooltip={{
|
||||
customTooltip: (info) => (
|
||||
<CustomTooltip
|
||||
|
@ -320,20 +333,11 @@ export function ServiceProfilingFlamegraph({
|
|||
id="profile_graph"
|
||||
data={points}
|
||||
layers={layers}
|
||||
drilldown
|
||||
maxRowCount={1}
|
||||
layout={PartitionLayout.icicle}
|
||||
valueAccessor={(d: Datum) => d.value as number}
|
||||
valueFormatter={() => ''}
|
||||
config={{
|
||||
fillLabel: {
|
||||
fontFamily: theme.eui.euiCodeFontFamily,
|
||||
clipText: true,
|
||||
},
|
||||
drilldown: true,
|
||||
fontFamily: theme.eui.euiCodeFontFamily,
|
||||
minFontSize: 9,
|
||||
maxFontSize: 9,
|
||||
maxRowCount: 1,
|
||||
partitionLayout: PartitionLayout.icicle,
|
||||
}}
|
||||
/>
|
||||
</Chart>
|
||||
</EuiFlexItem>
|
||||
|
|
|
@ -98,6 +98,7 @@ export function ServiceProfilingTimeline({
|
|||
xScaleType={ScaleType.Time}
|
||||
yScaleType={ScaleType.Linear}
|
||||
xAccessor="x"
|
||||
yAccessors={['y']}
|
||||
stackAccessors={['x']}
|
||||
/>
|
||||
))}
|
||||
|
|
|
@ -171,7 +171,12 @@ export function BreakdownChart({
|
|||
})
|
||||
) : (
|
||||
// When timeseries is empty, loads an AreaSeries chart to show the default empty message.
|
||||
<AreaSeries id="empty_chart" data={[]} />
|
||||
<AreaSeries
|
||||
id="empty_chart"
|
||||
xAccessor="x"
|
||||
yAccessors={['y']}
|
||||
data={[]}
|
||||
/>
|
||||
)}
|
||||
</Chart>
|
||||
</ChartContainer>
|
||||
|
|
|
@ -10,11 +10,11 @@ import {
|
|||
Chart,
|
||||
CurveType,
|
||||
LineSeries,
|
||||
PartialTheme,
|
||||
ScaleType,
|
||||
Settings,
|
||||
} from '@elastic/charts';
|
||||
import { EuiFlexGroup, EuiFlexItem, EuiIcon } from '@elastic/eui';
|
||||
import { merge } from 'lodash';
|
||||
import React from 'react';
|
||||
import { useChartTheme } from '../../../../../../observability/public';
|
||||
import { Coordinate } from '../../../../../typings/timeseries';
|
||||
|
@ -60,7 +60,7 @@ export function SparkPlot({
|
|||
const comparisonChartTheme = getComparisonChartTheme(theme);
|
||||
const hasComparisonSeries = !!comparisonSeries?.length;
|
||||
|
||||
const sparkplotChartTheme = merge({}, defaultChartTheme, {
|
||||
const sparkplotChartTheme: PartialTheme = {
|
||||
chartMargins: { left: 0, right: 0, top: 0, bottom: 0 },
|
||||
lineSeriesStyle: {
|
||||
point: { opacity: 0 },
|
||||
|
@ -69,7 +69,7 @@ export function SparkPlot({
|
|||
point: { opacity: 0 },
|
||||
},
|
||||
...(hasComparisonSeries ? comparisonChartTheme : {}),
|
||||
});
|
||||
};
|
||||
|
||||
const colorValue = theme.eui[color];
|
||||
|
||||
|
@ -95,7 +95,7 @@ export function SparkPlot({
|
|||
{hasValidTimeseries(series) ? (
|
||||
<Chart size={chartSize}>
|
||||
<Settings
|
||||
theme={sparkplotChartTheme}
|
||||
theme={[sparkplotChartTheme, ...defaultChartTheme]}
|
||||
showLegend={false}
|
||||
tooltip="none"
|
||||
/>
|
||||
|
|
|
@ -126,13 +126,15 @@ export function TimeseriesChart({
|
|||
onBrushEnd={(event) =>
|
||||
onBrushEnd({ x: (event as XYBrushEvent).x, history })
|
||||
}
|
||||
theme={{
|
||||
...chartTheme,
|
||||
areaSeriesStyle: {
|
||||
line: { visible: false },
|
||||
theme={[
|
||||
customTheme,
|
||||
{
|
||||
areaSeriesStyle: {
|
||||
line: { visible: false },
|
||||
},
|
||||
},
|
||||
...customTheme,
|
||||
}}
|
||||
...chartTheme,
|
||||
]}
|
||||
onPointerUpdate={setPointerEvent}
|
||||
externalPointerEvents={{
|
||||
tooltip: { visible: true },
|
||||
|
|
|
@ -156,28 +156,31 @@ export function TransactionDistributionChart({
|
|||
<Chart>
|
||||
<Settings
|
||||
rotation={0}
|
||||
theme={{
|
||||
theme={[
|
||||
{
|
||||
legend: {
|
||||
spacingBuffer: 100,
|
||||
},
|
||||
areaSeriesStyle: {
|
||||
line: {
|
||||
visible: true,
|
||||
},
|
||||
},
|
||||
axes: {
|
||||
tickLine: {
|
||||
visible: true,
|
||||
size: 5,
|
||||
padding: 10,
|
||||
},
|
||||
tickLabel: {
|
||||
fontSize: 10,
|
||||
fill: euiTheme.eui.euiColorMediumShade,
|
||||
padding: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
...chartTheme,
|
||||
legend: {
|
||||
spacingBuffer: 100,
|
||||
},
|
||||
areaSeriesStyle: {
|
||||
line: {
|
||||
visible: true,
|
||||
},
|
||||
},
|
||||
axes: {
|
||||
...chartTheme.axes,
|
||||
tickLine: {
|
||||
size: 5,
|
||||
},
|
||||
tickLabel: {
|
||||
fontSize: 10,
|
||||
fill: euiTheme.eui.euiColorMediumShade,
|
||||
padding: 0,
|
||||
},
|
||||
},
|
||||
}}
|
||||
]}
|
||||
showLegend={true}
|
||||
legendPosition={Position.Bottom}
|
||||
onBrushEnd={onChartSelection}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { PartialTheme } from '@elastic/charts';
|
||||
import moment from 'moment';
|
||||
import { EuiTheme } from 'src/plugins/kibana_react/common';
|
||||
import {
|
||||
|
@ -13,7 +14,7 @@ import {
|
|||
} from '../../../../common/runtime_types/comparison_type_rt';
|
||||
import { getDateDifference } from '../../../../common/utils/formatters';
|
||||
|
||||
export function getComparisonChartTheme(theme: EuiTheme) {
|
||||
export function getComparisonChartTheme(theme: EuiTheme): PartialTheme {
|
||||
return {
|
||||
areaSeriesStyle: {
|
||||
area: {
|
||||
|
|
|
@ -102,7 +102,9 @@ export const MetricDistributionChart: FC<Props> = ({
|
|||
yScaleType={ScaleType.Linear}
|
||||
xAccessor="x"
|
||||
yAccessors={['y']}
|
||||
data={chartData.length > 0 ? chartData : [{ x: 0, y: 0 }]}
|
||||
data={
|
||||
chartData.length > 0 ? chartData : [{ x: 0, y: 0, dataMin: 0, dataMax: 0, percent: 0 }]
|
||||
}
|
||||
curve={CurveType.CURVE_STEP_AFTER}
|
||||
/>
|
||||
</Chart>
|
||||
|
|
|
@ -14,6 +14,7 @@ import {
|
|||
ShapeTreeNode,
|
||||
HierarchyOfArrays,
|
||||
Chart,
|
||||
PartialTheme,
|
||||
} from '@elastic/charts';
|
||||
import { shallow } from 'enzyme';
|
||||
import type { LensMultiTable } from '../../common';
|
||||
|
@ -110,7 +111,7 @@ describe('PieVisualization component', () => {
|
|||
|
||||
test('it sets the correct lines per legend item', () => {
|
||||
const component = shallow(<PieComponent args={args} {...getDefaultArgs()} />);
|
||||
expect(component.find(Settings).prop('theme')).toEqual({
|
||||
expect(component.find(Settings).prop<PartialTheme[]>('theme')[0]).toMatchObject({
|
||||
background: {
|
||||
color: undefined,
|
||||
},
|
||||
|
@ -395,7 +396,9 @@ describe('PieVisualization component', () => {
|
|||
const component = shallow(
|
||||
<PieComponent args={args} {...getDefaultArgs()} data={emptyData} />
|
||||
);
|
||||
expect(component.find(Partition).prop('config')?.outerSizeRatio).toBeCloseTo(1 / 1.05);
|
||||
expect(
|
||||
component.find(Settings).prop<PartialTheme[]>('theme')[0].partition?.outerSizeRatio
|
||||
).toBeCloseTo(1 / 1.05);
|
||||
});
|
||||
|
||||
test('it should bound the shrink the chart area to ~20% when some small slices are detected', () => {
|
||||
|
@ -419,7 +422,9 @@ describe('PieVisualization component', () => {
|
|||
const component = shallow(
|
||||
<PieComponent args={args} {...getDefaultArgs()} data={emptyData} />
|
||||
);
|
||||
expect(component.find(Partition).prop('config')?.outerSizeRatio).toBeCloseTo(1 / 1.2);
|
||||
expect(
|
||||
component.find(Settings).prop<PartialTheme[]>('theme')[0].partition?.outerSizeRatio
|
||||
).toBeCloseTo(1 / 1.2);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -8,19 +8,18 @@
|
|||
import { uniq } from 'lodash';
|
||||
import React from 'react';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import { Required } from '@kbn/utility-types';
|
||||
import { EuiText } from '@elastic/eui';
|
||||
import {
|
||||
Chart,
|
||||
Datum,
|
||||
LayerValue,
|
||||
Partition,
|
||||
PartitionConfig,
|
||||
PartitionLayer,
|
||||
PartitionFillLabel,
|
||||
RecursivePartial,
|
||||
Position,
|
||||
Settings,
|
||||
ElementClickListener,
|
||||
PartialTheme,
|
||||
} from '@elastic/charts';
|
||||
import { RenderMode } from 'src/plugins/expressions';
|
||||
import type { LensFilterEvent } from '../types';
|
||||
|
@ -99,7 +98,7 @@ export function PieComponent(
|
|||
});
|
||||
}
|
||||
|
||||
const fillLabel: Partial<PartitionFillLabel> = {
|
||||
const fillLabel: PartitionLayer['fillLabel'] = {
|
||||
valueFont: {
|
||||
fontWeight: 700,
|
||||
},
|
||||
|
@ -202,42 +201,52 @@ export function PieComponent(
|
|||
};
|
||||
});
|
||||
|
||||
const { legend, partitionType: partitionLayout, label: chartType } = PartitionChartsMeta[shape];
|
||||
const { legend, partitionType, label: chartType } = PartitionChartsMeta[shape];
|
||||
|
||||
const config: RecursivePartial<PartitionConfig> = {
|
||||
partitionLayout,
|
||||
fontFamily: chartTheme.barSeriesStyle?.displayValue?.fontFamily,
|
||||
outerSizeRatio: 1,
|
||||
specialFirstInnermostSector: true,
|
||||
minFontSize: 10,
|
||||
maxFontSize: 16,
|
||||
// Labels are added outside the outer ring when the slice is too small
|
||||
linkLabel: {
|
||||
maxCount: 5,
|
||||
fontSize: 11,
|
||||
// Dashboard background color is affected by dark mode, which we need
|
||||
// to account for in outer labels
|
||||
// This does not handle non-dashboard embeddables, which are allowed to
|
||||
// have different backgrounds.
|
||||
textColor: chartTheme.axes?.axisTitle?.fill,
|
||||
const themeOverrides: Required<PartialTheme, 'partition'> = {
|
||||
chartMargins: { top: 0, bottom: 0, left: 0, right: 0 },
|
||||
background: {
|
||||
color: undefined, // removes background for embeddables
|
||||
},
|
||||
legend: {
|
||||
labelOptions: { maxLines: truncateLegend ? legendMaxLines ?? 1 : 0 },
|
||||
},
|
||||
partition: {
|
||||
fontFamily: chartTheme.barSeriesStyle?.displayValue?.fontFamily,
|
||||
outerSizeRatio: 1,
|
||||
minFontSize: 10,
|
||||
maxFontSize: 16,
|
||||
// Labels are added outside the outer ring when the slice is too small
|
||||
linkLabel: {
|
||||
maxCount: 5,
|
||||
fontSize: 11,
|
||||
// Dashboard background color is affected by dark mode, which we need
|
||||
// to account for in outer labels
|
||||
// This does not handle non-dashboard embeddables, which are allowed to
|
||||
// have different backgrounds.
|
||||
textColor: chartTheme.axes?.axisTitle?.fill,
|
||||
},
|
||||
sectorLineStroke: chartTheme.lineSeriesStyle?.point?.fill,
|
||||
sectorLineWidth: 1.5,
|
||||
circlePadding: 4,
|
||||
},
|
||||
sectorLineStroke: chartTheme.lineSeriesStyle?.point?.fill,
|
||||
sectorLineWidth: 1.5,
|
||||
circlePadding: 4,
|
||||
};
|
||||
if (isTreemapOrMosaicShape(shape)) {
|
||||
if (hideLabels || categoryDisplay === 'hide') {
|
||||
config.fillLabel = { textColor: 'rgba(0,0,0,0)' };
|
||||
themeOverrides.partition.fillLabel = { textColor: 'rgba(0,0,0,0)' };
|
||||
}
|
||||
} else {
|
||||
config.emptySizeRatio = shape === 'donut' ? emptySizeRatio : 0;
|
||||
themeOverrides.partition.emptySizeRatio = shape === 'donut' ? emptySizeRatio : 0;
|
||||
|
||||
if (hideLabels || categoryDisplay === 'hide') {
|
||||
// Force all labels to be linked, then prevent links from showing
|
||||
config.linkLabel = { maxCount: 0, maximumSection: Number.POSITIVE_INFINITY };
|
||||
themeOverrides.partition.linkLabel = {
|
||||
maxCount: 0,
|
||||
maximumSection: Number.POSITIVE_INFINITY,
|
||||
};
|
||||
} else if (categoryDisplay === 'inside') {
|
||||
// Prevent links from showing
|
||||
config.linkLabel = { maxCount: 0 };
|
||||
themeOverrides.partition.linkLabel = { maxCount: 0 };
|
||||
} else {
|
||||
// if it contains any slice below 2% reduce the ratio
|
||||
// first step: sum it up the overall sum
|
||||
|
@ -246,7 +255,7 @@ export function PieComponent(
|
|||
const smallSlices = slices.filter((value) => value < 0.02).length;
|
||||
if (smallSlices) {
|
||||
// shrink up to 20% to give some room for the linked values
|
||||
config.outerSizeRatio = 1 / (1 + Math.min(smallSlices * 0.05, 0.2));
|
||||
themeOverrides.partition.outerSizeRatio = 1 / (1 + Math.min(smallSlices * 0.05, 0.2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -322,27 +331,19 @@ export function PieComponent(
|
|||
legendMaxDepth={nestedLegend ? undefined : 1 /* Color is based only on first layer */}
|
||||
onElementClick={props.interactive ?? true ? onElementClickHandler : undefined}
|
||||
legendAction={props.interactive ? getLegendAction(firstTable, onClickValue) : undefined}
|
||||
theme={{
|
||||
...chartTheme,
|
||||
background: {
|
||||
...chartTheme.background,
|
||||
color: undefined, // removes background for embeddables
|
||||
},
|
||||
legend: {
|
||||
labelOptions: { maxLines: truncateLegend ? legendMaxLines ?? 1 : 0 },
|
||||
},
|
||||
}}
|
||||
theme={[themeOverrides, chartTheme]}
|
||||
baseTheme={chartBaseTheme}
|
||||
/>
|
||||
<Partition
|
||||
id={shape}
|
||||
data={firstTable.rows}
|
||||
layout={partitionType}
|
||||
specialFirstInnermostSector
|
||||
valueAccessor={(d: Datum) => getSliceValue(d, metricColumn)}
|
||||
percentFormatter={(d: number) => percentFormatter.convert(d / 100)}
|
||||
valueGetter={hideLabels || numberDisplay === 'value' ? undefined : 'percent'}
|
||||
valueFormatter={(d: number) => (hideLabels ? '' : formatters[metricColumn.id].convert(d))}
|
||||
layers={layers}
|
||||
config={config}
|
||||
topGroove={hideLabels || categoryDisplay === 'hide' ? 0 : undefined}
|
||||
/>
|
||||
</Chart>
|
||||
|
|
|
@ -4,7 +4,7 @@ exports[`xy_expression XYChart component it renders area 1`] = `
|
|||
<Chart
|
||||
renderer="canvas"
|
||||
>
|
||||
<Connect(SpecInstance)
|
||||
<Settings
|
||||
allowBrushingLastHistogramBin={false}
|
||||
baseTheme={Object {}}
|
||||
debugState={false}
|
||||
|
@ -43,7 +43,7 @@ exports[`xy_expression XYChart component it renders area 1`] = `
|
|||
}
|
||||
}
|
||||
/>
|
||||
<Connect(SpecInstance)
|
||||
<Component
|
||||
gridLine={
|
||||
Object {
|
||||
"strokeWidth": 1,
|
||||
|
@ -70,7 +70,7 @@ exports[`xy_expression XYChart component it renders area 1`] = `
|
|||
timeAxisLayerCount={0}
|
||||
title="c"
|
||||
/>
|
||||
<Connect(SpecInstance)
|
||||
<Component
|
||||
domain={
|
||||
Object {
|
||||
"fit": false,
|
||||
|
@ -108,7 +108,7 @@ exports[`xy_expression XYChart component it renders area 1`] = `
|
|||
darkMode={false}
|
||||
histogramMode={false}
|
||||
/>
|
||||
<Connect(SpecInstance)
|
||||
<AreaSeries
|
||||
areaSeriesStyle={
|
||||
Object {
|
||||
"point": Object {
|
||||
|
@ -168,7 +168,7 @@ exports[`xy_expression XYChart component it renders area 1`] = `
|
|||
}
|
||||
yScaleType="linear"
|
||||
/>
|
||||
<Connect(SpecInstance)
|
||||
<AreaSeries
|
||||
areaSeriesStyle={
|
||||
Object {
|
||||
"point": Object {
|
||||
|
@ -235,7 +235,7 @@ exports[`xy_expression XYChart component it renders bar 1`] = `
|
|||
<Chart
|
||||
renderer="canvas"
|
||||
>
|
||||
<Connect(SpecInstance)
|
||||
<Settings
|
||||
allowBrushingLastHistogramBin={false}
|
||||
baseTheme={Object {}}
|
||||
debugState={false}
|
||||
|
@ -274,7 +274,7 @@ exports[`xy_expression XYChart component it renders bar 1`] = `
|
|||
}
|
||||
}
|
||||
/>
|
||||
<Connect(SpecInstance)
|
||||
<Component
|
||||
gridLine={
|
||||
Object {
|
||||
"strokeWidth": 1,
|
||||
|
@ -301,7 +301,7 @@ exports[`xy_expression XYChart component it renders bar 1`] = `
|
|||
timeAxisLayerCount={0}
|
||||
title="c"
|
||||
/>
|
||||
<Connect(SpecInstance)
|
||||
<Component
|
||||
domain={
|
||||
Object {
|
||||
"fit": false,
|
||||
|
@ -339,7 +339,7 @@ exports[`xy_expression XYChart component it renders bar 1`] = `
|
|||
darkMode={false}
|
||||
histogramMode={false}
|
||||
/>
|
||||
<Connect(SpecInstance)
|
||||
<BarSeries
|
||||
areaSeriesStyle={
|
||||
Object {
|
||||
"point": Object {
|
||||
|
@ -406,7 +406,7 @@ exports[`xy_expression XYChart component it renders bar 1`] = `
|
|||
}
|
||||
yScaleType="linear"
|
||||
/>
|
||||
<Connect(SpecInstance)
|
||||
<BarSeries
|
||||
areaSeriesStyle={
|
||||
Object {
|
||||
"point": Object {
|
||||
|
@ -480,7 +480,7 @@ exports[`xy_expression XYChart component it renders horizontal bar 1`] = `
|
|||
<Chart
|
||||
renderer="canvas"
|
||||
>
|
||||
<Connect(SpecInstance)
|
||||
<Settings
|
||||
allowBrushingLastHistogramBin={false}
|
||||
baseTheme={Object {}}
|
||||
debugState={false}
|
||||
|
@ -519,7 +519,7 @@ exports[`xy_expression XYChart component it renders horizontal bar 1`] = `
|
|||
}
|
||||
}
|
||||
/>
|
||||
<Connect(SpecInstance)
|
||||
<Component
|
||||
gridLine={
|
||||
Object {
|
||||
"strokeWidth": 1,
|
||||
|
@ -546,7 +546,7 @@ exports[`xy_expression XYChart component it renders horizontal bar 1`] = `
|
|||
timeAxisLayerCount={0}
|
||||
title="c"
|
||||
/>
|
||||
<Connect(SpecInstance)
|
||||
<Component
|
||||
domain={
|
||||
Object {
|
||||
"fit": false,
|
||||
|
@ -584,7 +584,7 @@ exports[`xy_expression XYChart component it renders horizontal bar 1`] = `
|
|||
darkMode={false}
|
||||
histogramMode={false}
|
||||
/>
|
||||
<Connect(SpecInstance)
|
||||
<BarSeries
|
||||
areaSeriesStyle={
|
||||
Object {
|
||||
"point": Object {
|
||||
|
@ -651,7 +651,7 @@ exports[`xy_expression XYChart component it renders horizontal bar 1`] = `
|
|||
}
|
||||
yScaleType="linear"
|
||||
/>
|
||||
<Connect(SpecInstance)
|
||||
<BarSeries
|
||||
areaSeriesStyle={
|
||||
Object {
|
||||
"point": Object {
|
||||
|
@ -725,7 +725,7 @@ exports[`xy_expression XYChart component it renders line 1`] = `
|
|||
<Chart
|
||||
renderer="canvas"
|
||||
>
|
||||
<Connect(SpecInstance)
|
||||
<Settings
|
||||
allowBrushingLastHistogramBin={false}
|
||||
baseTheme={Object {}}
|
||||
debugState={false}
|
||||
|
@ -764,7 +764,7 @@ exports[`xy_expression XYChart component it renders line 1`] = `
|
|||
}
|
||||
}
|
||||
/>
|
||||
<Connect(SpecInstance)
|
||||
<Component
|
||||
gridLine={
|
||||
Object {
|
||||
"strokeWidth": 1,
|
||||
|
@ -791,7 +791,7 @@ exports[`xy_expression XYChart component it renders line 1`] = `
|
|||
timeAxisLayerCount={0}
|
||||
title="c"
|
||||
/>
|
||||
<Connect(SpecInstance)
|
||||
<Component
|
||||
domain={
|
||||
Object {
|
||||
"fit": false,
|
||||
|
@ -829,7 +829,7 @@ exports[`xy_expression XYChart component it renders line 1`] = `
|
|||
darkMode={false}
|
||||
histogramMode={false}
|
||||
/>
|
||||
<Connect(SpecInstance)
|
||||
<LineSeries
|
||||
areaSeriesStyle={
|
||||
Object {
|
||||
"point": Object {
|
||||
|
@ -889,7 +889,7 @@ exports[`xy_expression XYChart component it renders line 1`] = `
|
|||
}
|
||||
yScaleType="linear"
|
||||
/>
|
||||
<Connect(SpecInstance)
|
||||
<LineSeries
|
||||
areaSeriesStyle={
|
||||
Object {
|
||||
"point": Object {
|
||||
|
@ -956,7 +956,7 @@ exports[`xy_expression XYChart component it renders stacked area 1`] = `
|
|||
<Chart
|
||||
renderer="canvas"
|
||||
>
|
||||
<Connect(SpecInstance)
|
||||
<Settings
|
||||
allowBrushingLastHistogramBin={false}
|
||||
baseTheme={Object {}}
|
||||
debugState={false}
|
||||
|
@ -995,7 +995,7 @@ exports[`xy_expression XYChart component it renders stacked area 1`] = `
|
|||
}
|
||||
}
|
||||
/>
|
||||
<Connect(SpecInstance)
|
||||
<Component
|
||||
gridLine={
|
||||
Object {
|
||||
"strokeWidth": 1,
|
||||
|
@ -1022,7 +1022,7 @@ exports[`xy_expression XYChart component it renders stacked area 1`] = `
|
|||
timeAxisLayerCount={0}
|
||||
title="c"
|
||||
/>
|
||||
<Connect(SpecInstance)
|
||||
<Component
|
||||
domain={
|
||||
Object {
|
||||
"fit": false,
|
||||
|
@ -1060,7 +1060,7 @@ exports[`xy_expression XYChart component it renders stacked area 1`] = `
|
|||
darkMode={false}
|
||||
histogramMode={false}
|
||||
/>
|
||||
<Connect(SpecInstance)
|
||||
<AreaSeries
|
||||
areaSeriesStyle={
|
||||
Object {
|
||||
"point": Object {
|
||||
|
@ -1124,7 +1124,7 @@ exports[`xy_expression XYChart component it renders stacked area 1`] = `
|
|||
}
|
||||
yScaleType="linear"
|
||||
/>
|
||||
<Connect(SpecInstance)
|
||||
<AreaSeries
|
||||
areaSeriesStyle={
|
||||
Object {
|
||||
"point": Object {
|
||||
|
@ -1195,7 +1195,7 @@ exports[`xy_expression XYChart component it renders stacked bar 1`] = `
|
|||
<Chart
|
||||
renderer="canvas"
|
||||
>
|
||||
<Connect(SpecInstance)
|
||||
<Settings
|
||||
allowBrushingLastHistogramBin={false}
|
||||
baseTheme={Object {}}
|
||||
debugState={false}
|
||||
|
@ -1234,7 +1234,7 @@ exports[`xy_expression XYChart component it renders stacked bar 1`] = `
|
|||
}
|
||||
}
|
||||
/>
|
||||
<Connect(SpecInstance)
|
||||
<Component
|
||||
gridLine={
|
||||
Object {
|
||||
"strokeWidth": 1,
|
||||
|
@ -1261,7 +1261,7 @@ exports[`xy_expression XYChart component it renders stacked bar 1`] = `
|
|||
timeAxisLayerCount={0}
|
||||
title="c"
|
||||
/>
|
||||
<Connect(SpecInstance)
|
||||
<Component
|
||||
domain={
|
||||
Object {
|
||||
"fit": false,
|
||||
|
@ -1299,7 +1299,7 @@ exports[`xy_expression XYChart component it renders stacked bar 1`] = `
|
|||
darkMode={false}
|
||||
histogramMode={false}
|
||||
/>
|
||||
<Connect(SpecInstance)
|
||||
<BarSeries
|
||||
areaSeriesStyle={
|
||||
Object {
|
||||
"point": Object {
|
||||
|
@ -1370,7 +1370,7 @@ exports[`xy_expression XYChart component it renders stacked bar 1`] = `
|
|||
}
|
||||
yScaleType="linear"
|
||||
/>
|
||||
<Connect(SpecInstance)
|
||||
<BarSeries
|
||||
areaSeriesStyle={
|
||||
Object {
|
||||
"point": Object {
|
||||
|
@ -1448,7 +1448,7 @@ exports[`xy_expression XYChart component it renders stacked horizontal bar 1`] =
|
|||
<Chart
|
||||
renderer="canvas"
|
||||
>
|
||||
<Connect(SpecInstance)
|
||||
<Settings
|
||||
allowBrushingLastHistogramBin={false}
|
||||
baseTheme={Object {}}
|
||||
debugState={false}
|
||||
|
@ -1487,7 +1487,7 @@ exports[`xy_expression XYChart component it renders stacked horizontal bar 1`] =
|
|||
}
|
||||
}
|
||||
/>
|
||||
<Connect(SpecInstance)
|
||||
<Component
|
||||
gridLine={
|
||||
Object {
|
||||
"strokeWidth": 1,
|
||||
|
@ -1514,7 +1514,7 @@ exports[`xy_expression XYChart component it renders stacked horizontal bar 1`] =
|
|||
timeAxisLayerCount={0}
|
||||
title="c"
|
||||
/>
|
||||
<Connect(SpecInstance)
|
||||
<Component
|
||||
domain={
|
||||
Object {
|
||||
"fit": false,
|
||||
|
@ -1552,7 +1552,7 @@ exports[`xy_expression XYChart component it renders stacked horizontal bar 1`] =
|
|||
darkMode={false}
|
||||
histogramMode={false}
|
||||
/>
|
||||
<Connect(SpecInstance)
|
||||
<BarSeries
|
||||
areaSeriesStyle={
|
||||
Object {
|
||||
"point": Object {
|
||||
|
@ -1623,7 +1623,7 @@ exports[`xy_expression XYChart component it renders stacked horizontal bar 1`] =
|
|||
}
|
||||
yScaleType="linear"
|
||||
/>
|
||||
<Connect(SpecInstance)
|
||||
<BarSeries
|
||||
areaSeriesStyle={
|
||||
Object {
|
||||
"point": Object {
|
||||
|
|
|
@ -33,6 +33,9 @@ import {
|
|||
RecursivePartial,
|
||||
AxisStyle,
|
||||
ScaleType,
|
||||
AreaSeriesProps,
|
||||
BarSeriesProps,
|
||||
LineSeriesProps,
|
||||
} from '@elastic/charts';
|
||||
import { I18nProvider } from '@kbn/i18n-react';
|
||||
import type {
|
||||
|
@ -83,10 +86,7 @@ declare global {
|
|||
}
|
||||
}
|
||||
|
||||
type InferPropType<T> = T extends React.FunctionComponent<infer P> ? P : T;
|
||||
type SeriesSpec = InferPropType<typeof LineSeries> &
|
||||
InferPropType<typeof BarSeries> &
|
||||
InferPropType<typeof AreaSeries>;
|
||||
type SeriesSpec = LineSeriesProps & BarSeriesProps & AreaSeriesProps;
|
||||
|
||||
export type XYChartRenderProps = XYChartProps & {
|
||||
chartsThemeService: ChartsPluginSetup['theme'];
|
||||
|
|
|
@ -18,7 +18,7 @@ import {
|
|||
RecursivePartial,
|
||||
AxisStyle,
|
||||
PartialTheme,
|
||||
BarSeriesSpec,
|
||||
BarSeriesProps,
|
||||
} from '@elastic/charts';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { euiLightVars as euiVars } from '@kbn/ui-theme';
|
||||
|
@ -100,13 +100,18 @@ export const FeatureImportanceSummaryPanel: FC<FeatureImportanceSummaryPanelProp
|
|||
services: { docLinks },
|
||||
} = useMlKibana();
|
||||
|
||||
const [plotData, barSeriesSpec, showLegend, chartHeight] = useMemo(() => {
|
||||
let sortedData: Array<{
|
||||
featureName: string;
|
||||
meanImportance: number;
|
||||
className?: FeatureImportanceClassName;
|
||||
}> = [];
|
||||
let _barSeriesSpec: Partial<BarSeriesSpec> = {
|
||||
interface Datum {
|
||||
featureName: string;
|
||||
meanImportance: number;
|
||||
className?: FeatureImportanceClassName;
|
||||
}
|
||||
type PlotData = Datum[];
|
||||
type SeriesProps = Omit<BarSeriesProps, 'id' | 'xScaleType' | 'yScaleType' | 'data'>;
|
||||
const [plotData, barSeriesSpec, showLegend, chartHeight] = useMemo<
|
||||
[plotData: PlotData, barSeriesSpec: SeriesProps, showLegend?: boolean, chartHeight?: number]
|
||||
>(() => {
|
||||
let sortedData: PlotData = [];
|
||||
let _barSeriesSpec: SeriesProps = {
|
||||
xAccessor: 'featureName',
|
||||
yAccessors: ['meanImportance'],
|
||||
name: i18n.translate(
|
||||
|
@ -122,7 +127,7 @@ export const FeatureImportanceSummaryPanel: FC<FeatureImportanceSummaryPanelProp
|
|||
| 'regression'
|
||||
| '' = '';
|
||||
if (totalFeatureImportance.length < 1) {
|
||||
return [sortedData, _barSeriesSpec];
|
||||
return [sortedData, _barSeriesSpec, undefined, undefined];
|
||||
}
|
||||
|
||||
if (isClassificationTotalFeatureImportance(totalFeatureImportance[0])) {
|
||||
|
|
|
@ -28,6 +28,7 @@ import {
|
|||
HeatmapBrushEvent,
|
||||
Position,
|
||||
ScaleType,
|
||||
PartialTheme,
|
||||
} from '@elastic/charts';
|
||||
import moment from 'moment';
|
||||
|
||||
|
@ -276,66 +277,59 @@ export const SwimlaneContainer: FC<SwimlaneProps> = ({
|
|||
|
||||
const showBrush = !!onCellsSelection;
|
||||
|
||||
const swimLaneConfig = useMemo<HeatmapSpec['config']>(() => {
|
||||
const themeOverrides = useMemo<PartialTheme>(() => {
|
||||
if (!showSwimlane) return {};
|
||||
|
||||
const config: HeatmapSpec['config'] = {
|
||||
grid: {
|
||||
cellHeight: {
|
||||
min: CELL_HEIGHT,
|
||||
max: CELL_HEIGHT,
|
||||
const theme: PartialTheme = {
|
||||
heatmap: {
|
||||
grid: {
|
||||
cellHeight: {
|
||||
min: CELL_HEIGHT,
|
||||
max: CELL_HEIGHT,
|
||||
},
|
||||
stroke: {
|
||||
width: 1,
|
||||
color: euiTheme.euiBorderColor,
|
||||
},
|
||||
},
|
||||
stroke: {
|
||||
width: 1,
|
||||
color: euiTheme.euiBorderColor,
|
||||
cell: {
|
||||
maxWidth: 'fill',
|
||||
maxHeight: 'fill',
|
||||
label: {
|
||||
visible: false,
|
||||
},
|
||||
border: {
|
||||
stroke: euiTheme.euiBorderColor,
|
||||
strokeWidth: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
cell: {
|
||||
maxWidth: 'fill',
|
||||
maxHeight: 'fill',
|
||||
label: {
|
||||
visible: false,
|
||||
yAxisLabel: {
|
||||
visible: showYAxis,
|
||||
width: Y_AXIS_LABEL_WIDTH,
|
||||
textColor: euiTheme.euiTextSubduedColor,
|
||||
padding: Y_AXIS_LABEL_PADDING,
|
||||
fontSize: parseInt(euiTheme.euiFontSizeXS, 10),
|
||||
},
|
||||
border: {
|
||||
stroke: euiTheme.euiBorderColor,
|
||||
strokeWidth: 0,
|
||||
xAxisLabel: {
|
||||
visible: showTimeline,
|
||||
textColor: euiTheme.euiTextSubduedColor,
|
||||
fontSize: parseInt(euiTheme.euiFontSizeXS, 10),
|
||||
// Required to calculate where the swimlane ends
|
||||
width: X_AXIS_RIGHT_OVERFLOW * 2,
|
||||
},
|
||||
},
|
||||
yAxisLabel: {
|
||||
visible: showYAxis,
|
||||
width: Y_AXIS_LABEL_WIDTH,
|
||||
textColor: euiTheme.euiTextSubduedColor,
|
||||
padding: Y_AXIS_LABEL_PADDING,
|
||||
formatter: (laneLabel: string) => {
|
||||
return laneLabel === '' ? EMPTY_FIELD_VALUE_LABEL : laneLabel;
|
||||
brushMask: {
|
||||
visible: showBrush,
|
||||
fill: isDarkTheme ? 'rgb(30,31,35,80%)' : 'rgb(247,247,247,50%)',
|
||||
},
|
||||
fontSize: parseInt(euiTheme.euiFontSizeXS, 10),
|
||||
},
|
||||
xAxisLabel: {
|
||||
visible: showTimeline,
|
||||
textColor: euiTheme.euiTextSubduedColor,
|
||||
formatter: (v: number) => {
|
||||
timeBuckets.setInterval(`${swimlaneData.interval}s`);
|
||||
const scaledDateFormat = timeBuckets.getScaledDateFormat();
|
||||
return moment(v).format(scaledDateFormat);
|
||||
brushArea: {
|
||||
visible: showBrush,
|
||||
stroke: isDarkTheme ? 'rgb(255, 255, 255)' : 'rgb(105, 112, 125)',
|
||||
},
|
||||
fontSize: parseInt(euiTheme.euiFontSizeXS, 10),
|
||||
// Required to calculate where the swimlane ends
|
||||
width: X_AXIS_RIGHT_OVERFLOW * 2,
|
||||
...(showLegend ? { maxLegendHeight: LEGEND_HEIGHT } : {}),
|
||||
},
|
||||
brushMask: {
|
||||
visible: showBrush,
|
||||
fill: isDarkTheme ? 'rgb(30,31,35,80%)' : 'rgb(247,247,247,50%)',
|
||||
},
|
||||
brushArea: {
|
||||
visible: showBrush,
|
||||
stroke: isDarkTheme ? 'rgb(255, 255, 255)' : 'rgb(105, 112, 125)',
|
||||
},
|
||||
...(showLegend ? { maxLegendHeight: LEGEND_HEIGHT } : {}),
|
||||
timeZone: 'UTC',
|
||||
};
|
||||
|
||||
return config;
|
||||
return theme;
|
||||
}, [
|
||||
showSwimlane,
|
||||
swimlaneType,
|
||||
|
@ -427,6 +421,7 @@ export const SwimlaneContainer: FC<SwimlaneProps> = ({
|
|||
{showSwimlane && !isLoading && (
|
||||
<Chart className={'mlSwimLaneContainer'}>
|
||||
<Settings
|
||||
theme={themeOverrides}
|
||||
onElementClick={onElementClick}
|
||||
showLegend={showLegend}
|
||||
legendPosition={Position.Top}
|
||||
|
@ -438,6 +433,7 @@ export const SwimlaneContainer: FC<SwimlaneProps> = ({
|
|||
|
||||
<Heatmap
|
||||
id={id}
|
||||
timeZone="UTC"
|
||||
colorScale={{
|
||||
type: 'bands',
|
||||
bands: [
|
||||
|
@ -485,7 +481,14 @@ export const SwimlaneContainer: FC<SwimlaneProps> = ({
|
|||
},
|
||||
}}
|
||||
ySortPredicate="dataIndex"
|
||||
config={swimLaneConfig}
|
||||
yAxisLabelFormatter={(laneLabel) => {
|
||||
return laneLabel === '' ? EMPTY_FIELD_VALUE_LABEL : String(laneLabel);
|
||||
}}
|
||||
xAxisLabelFormatter={(v) => {
|
||||
timeBuckets.setInterval(`${swimlaneData.interval}s`);
|
||||
const scaledDateFormat = timeBuckets.getScaledDateFormat();
|
||||
return moment(v).format(scaledDateFormat);
|
||||
}}
|
||||
/>
|
||||
</Chart>
|
||||
)}
|
||||
|
|
|
@ -5,34 +5,34 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { PartialTheme } from '@elastic/charts';
|
||||
import { EUI_CHARTS_THEME_DARK, EUI_CHARTS_THEME_LIGHT } from '@elastic/eui/dist/eui_charts_theme';
|
||||
import { useTheme } from './use_theme';
|
||||
|
||||
export function useChartTheme() {
|
||||
export function useChartTheme(): PartialTheme[] {
|
||||
const theme = useTheme();
|
||||
const baseChartTheme = theme.darkMode
|
||||
? EUI_CHARTS_THEME_DARK.theme
|
||||
: EUI_CHARTS_THEME_LIGHT.theme;
|
||||
|
||||
return {
|
||||
...baseChartTheme,
|
||||
chartMargins: {
|
||||
left: 10,
|
||||
right: 10,
|
||||
top: 10,
|
||||
bottom: 10,
|
||||
return [
|
||||
{
|
||||
chartMargins: {
|
||||
left: 10,
|
||||
right: 10,
|
||||
top: 10,
|
||||
bottom: 10,
|
||||
},
|
||||
background: {
|
||||
color: 'transparent',
|
||||
},
|
||||
lineSeriesStyle: {
|
||||
point: { visible: false },
|
||||
},
|
||||
areaSeriesStyle: {
|
||||
point: { visible: false },
|
||||
},
|
||||
},
|
||||
background: {
|
||||
...baseChartTheme.background,
|
||||
color: 'transparent',
|
||||
},
|
||||
lineSeriesStyle: {
|
||||
...baseChartTheme.lineSeriesStyle,
|
||||
point: { visible: false },
|
||||
},
|
||||
areaSeriesStyle: {
|
||||
...baseChartTheme.areaSeriesStyle,
|
||||
point: { visible: false },
|
||||
},
|
||||
};
|
||||
baseChartTheme,
|
||||
];
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ import {
|
|||
Rendering,
|
||||
Rotation,
|
||||
ScaleType,
|
||||
SettingsSpecProps,
|
||||
SettingsProps,
|
||||
TickFormatter,
|
||||
Position,
|
||||
BrushEndListener,
|
||||
|
@ -52,7 +52,7 @@ export interface ChartSeriesConfigs {
|
|||
tickSize?: number | undefined;
|
||||
};
|
||||
yAxisTitle?: string | undefined;
|
||||
settings?: Partial<SettingsSpecProps>;
|
||||
settings?: SettingsProps;
|
||||
}
|
||||
|
||||
export interface ChartSeriesData {
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -9,7 +9,7 @@ import { EuiFlexGroup, EuiFlexItem, EuiIcon } from '@elastic/eui';
|
|||
import React, { useContext } from 'react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import styled from 'styled-components';
|
||||
import { Chart, Datum, Partition, Settings, PartitionLayout } from '@elastic/charts';
|
||||
import { Chart, Datum, Partition, Settings, PartitionLayout, PartialTheme } from '@elastic/charts';
|
||||
import { DonutChartLegend } from './donut_chart_legend';
|
||||
import { UptimeThemeContext } from '../../../contexts';
|
||||
|
||||
|
@ -28,6 +28,19 @@ export const GreenCheckIcon = styled(EuiIcon)`
|
|||
position: absolute;
|
||||
`;
|
||||
|
||||
const themeOverrides: PartialTheme = {
|
||||
chartMargins: { top: 0, bottom: 0, left: 0, right: 0 },
|
||||
partition: {
|
||||
linkLabel: {
|
||||
maximumSection: Infinity,
|
||||
},
|
||||
idealFontSizeJump: 1.1,
|
||||
outerSizeRatio: 0.9,
|
||||
emptySizeRatio: 0.4,
|
||||
circlePadding: 4,
|
||||
},
|
||||
};
|
||||
|
||||
export const DonutChart = ({ height, down, up }: DonutChartProps) => {
|
||||
const {
|
||||
colors: { danger, gray },
|
||||
|
@ -44,15 +57,18 @@ export const DonutChart = ({ height, down, up }: DonutChartProps) => {
|
|||
'Pie chart showing the current status. {down} of {total} monitors are down.',
|
||||
values: { down, total: up + down },
|
||||
})}
|
||||
{...chartTheme}
|
||||
>
|
||||
<Settings />
|
||||
<Settings
|
||||
theme={[themeOverrides, chartTheme.theme ?? {}]}
|
||||
baseTheme={chartTheme.baseTheme}
|
||||
/>
|
||||
<Partition
|
||||
id="spec_1"
|
||||
data={[
|
||||
{ value: down, label: 'Down' },
|
||||
{ value: up, label: 'Up' },
|
||||
]}
|
||||
layout={PartitionLayout.sunburst}
|
||||
valueAccessor={(d: Datum) => d.value as number}
|
||||
layers={[
|
||||
{
|
||||
|
@ -65,17 +81,6 @@ export const DonutChart = ({ height, down, up }: DonutChartProps) => {
|
|||
},
|
||||
},
|
||||
]}
|
||||
config={{
|
||||
partitionLayout: PartitionLayout.sunburst,
|
||||
linkLabel: {
|
||||
maximumSection: Infinity,
|
||||
},
|
||||
margin: { top: 0, bottom: 0, left: 0, right: 0 },
|
||||
idealFontSizeJump: 1.1,
|
||||
outerSizeRatio: 0.9,
|
||||
emptySizeRatio: 0.4,
|
||||
circlePadding: 4,
|
||||
}}
|
||||
/>
|
||||
</Chart>
|
||||
{down === 0 && <GreenCheckIcon className="greenCheckIcon" type="checkInCircleFilled" />}
|
||||
|
|
|
@ -1431,10 +1431,10 @@
|
|||
dependencies:
|
||||
object-hash "^1.3.0"
|
||||
|
||||
"@elastic/charts@40.2.0":
|
||||
version "40.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@elastic/charts/-/charts-40.2.0.tgz#2e329ce4f495731f478cbaf2f8f3b89b5167a65b"
|
||||
integrity sha512-N0t7YK58Kce/s9LEgaocrD75NYuFMwrcI1QNIPcwZ9IAOHY8/9yRHD5Ipoz0caGibAgOE8OunGkpyPY/NHKB5Q==
|
||||
"@elastic/charts@43.1.1":
|
||||
version "43.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@elastic/charts/-/charts-43.1.1.tgz#2a9cd4bbde9397b86a45d8aa604a1950ae0997c0"
|
||||
integrity sha512-lYTdwpARIDXD15iC4cujKplBhGXb3zriBATp0wFsqgT9XE9TMOzlQ9dgylWQ+2x6OlataZLrOMnWXiFQ3uJqqQ==
|
||||
dependencies:
|
||||
"@popperjs/core" "^2.4.0"
|
||||
chroma-js "^2.1.0"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue