mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
[Lens] update defaults for metric vis (#129968)
This commit is contained in:
parent
dbb6b1a75b
commit
88336719a2
9 changed files with 118 additions and 20 deletions
|
@ -15,6 +15,8 @@ export interface TitlePositionProps {
|
|||
setState: (newState: MetricState) => void;
|
||||
}
|
||||
|
||||
export const DEFAULT_TEXT_ALIGNMENT = 'left';
|
||||
|
||||
const alignButtonIcons = [
|
||||
{
|
||||
id: `left`,
|
||||
|
@ -46,7 +48,7 @@ export const AlignOptions: React.FC<TitlePositionProps> = ({ state, setState })
|
|||
defaultMessage: 'Align',
|
||||
})}
|
||||
options={alignButtonIcons}
|
||||
idSelected={state.textAlign ?? 'center'}
|
||||
idSelected={state.textAlign ?? DEFAULT_TEXT_ALIGNMENT}
|
||||
onChange={(id) => {
|
||||
setState({ ...state, textAlign: id as MetricState['textAlign'] });
|
||||
}}
|
||||
|
|
|
@ -15,6 +15,8 @@ export interface TitlePositionProps {
|
|||
setState: (newState: MetricState) => void;
|
||||
}
|
||||
|
||||
export const DEFAULT_TITLE_SIZE = 'm';
|
||||
|
||||
const titleSizes = [
|
||||
{
|
||||
id: 'xs',
|
||||
|
@ -55,7 +57,9 @@ const titleSizes = [
|
|||
];
|
||||
|
||||
export const SizeOptions: React.FC<TitlePositionProps> = ({ state, setState }) => {
|
||||
const currSizeIndex = titleSizes.findIndex((size) => size.id === (state.size || 'xl'));
|
||||
const currSizeIndex = titleSizes.findIndex(
|
||||
(size) => size.id === (state.size || DEFAULT_TITLE_SIZE)
|
||||
);
|
||||
|
||||
const changeSize = (change: number) => {
|
||||
setState({ ...state, size: titleSizes[currSizeIndex + change].id });
|
||||
|
@ -86,7 +90,7 @@ export const SizeOptions: React.FC<TitlePositionProps> = ({ state, setState }) =
|
|||
inputDisplay: position.label,
|
||||
};
|
||||
})}
|
||||
valueOfSelected={state.size ?? 'xl'}
|
||||
valueOfSelected={state.size ?? DEFAULT_TITLE_SIZE}
|
||||
onChange={(value) => {
|
||||
setState({ ...state, size: value });
|
||||
}}
|
||||
|
|
|
@ -15,9 +15,19 @@ export interface TitlePositionProps {
|
|||
setState: (newState: MetricState) => void;
|
||||
}
|
||||
|
||||
export const DEFAULT_TITLE_POSITION = 'top';
|
||||
|
||||
const titlePositions = [
|
||||
{ id: 'top', label: 'Top' },
|
||||
{ id: 'bottom', label: 'Bottom' },
|
||||
{
|
||||
id: 'top',
|
||||
label: i18n.translate('xpack.lens.metricChart.titlePositions.top', { defaultMessage: 'Top' }),
|
||||
},
|
||||
{
|
||||
id: 'bottom',
|
||||
label: i18n.translate('xpack.lens.metricChart.titlePositions.bottom', {
|
||||
defaultMessage: 'Bottom',
|
||||
}),
|
||||
},
|
||||
];
|
||||
|
||||
export const TitlePositionOptions: React.FC<TitlePositionProps> = ({ state, setState }) => {
|
||||
|
@ -38,7 +48,7 @@ export const TitlePositionOptions: React.FC<TitlePositionProps> = ({ state, setS
|
|||
data-test-subj="lnsMissingValuesSelect"
|
||||
legend="This is a basic group"
|
||||
options={titlePositions}
|
||||
idSelected={state.titlePosition ?? 'bottom'}
|
||||
idSelected={state.titlePosition ?? DEFAULT_TITLE_POSITION}
|
||||
onChange={(value) => {
|
||||
setState({ ...state, titlePosition: value as MetricState['titlePosition'] });
|
||||
}}
|
||||
|
|
|
@ -301,13 +301,13 @@ describe('metric_visualization', () => {
|
|||
Object {
|
||||
"arguments": Object {
|
||||
"align": Array [
|
||||
"center",
|
||||
"left",
|
||||
],
|
||||
"lHeight": Array [
|
||||
127.5,
|
||||
82.5,
|
||||
],
|
||||
"size": Array [
|
||||
85,
|
||||
55,
|
||||
],
|
||||
"sizeUnit": Array [
|
||||
"px",
|
||||
|
@ -329,13 +329,13 @@ describe('metric_visualization', () => {
|
|||
Object {
|
||||
"arguments": Object {
|
||||
"align": Array [
|
||||
"center",
|
||||
"left",
|
||||
],
|
||||
"lHeight": Array [
|
||||
40.5,
|
||||
24,
|
||||
],
|
||||
"size": Array [
|
||||
27,
|
||||
16,
|
||||
],
|
||||
"sizeUnit": Array [
|
||||
"px",
|
||||
|
@ -349,7 +349,7 @@ describe('metric_visualization', () => {
|
|||
},
|
||||
],
|
||||
"labelPosition": Array [
|
||||
"bottom",
|
||||
"top",
|
||||
],
|
||||
"metric": Array [
|
||||
Object {
|
||||
|
|
|
@ -22,6 +22,9 @@ import type { MetricState } from '../../common/types';
|
|||
import { layerTypes } from '../../common';
|
||||
import { MetricDimensionEditor } from './dimension_editor';
|
||||
import { MetricToolbar } from './metric_config_panel';
|
||||
import { DEFAULT_TITLE_POSITION } from './metric_config_panel/title_position_option';
|
||||
import { DEFAULT_TITLE_SIZE } from './metric_config_panel/size_options';
|
||||
import { DEFAULT_TEXT_ALIGNMENT } from './metric_config_panel/align_options';
|
||||
|
||||
interface MetricConfig extends Omit<MetricState, 'palette' | 'colorMode'> {
|
||||
title: string;
|
||||
|
@ -82,7 +85,7 @@ const toExpression = (
|
|||
xxl: getFontSizeAndUnit(euiThemeVars.euiFontSizeXXL),
|
||||
};
|
||||
|
||||
const labelFont = fontSizes[state?.size || 'xl'];
|
||||
const labelFont = fontSizes[state?.size || DEFAULT_TITLE_SIZE];
|
||||
const labelToMetricFontSizeMap: Record<string, number> = {
|
||||
xs: fontSizes.xs.size * 2,
|
||||
s: fontSizes.m.size * 2.5,
|
||||
|
@ -91,7 +94,7 @@ const toExpression = (
|
|||
xl: fontSizes.xxl.size * 2.5,
|
||||
xxl: fontSizes.xxl.size * 3,
|
||||
};
|
||||
const metricFontSize = labelToMetricFontSizeMap[state?.size || 'xl'];
|
||||
const metricFontSize = labelToMetricFontSizeMap[state?.size || DEFAULT_TITLE_SIZE];
|
||||
|
||||
return {
|
||||
type: 'expression',
|
||||
|
@ -100,7 +103,7 @@ const toExpression = (
|
|||
type: 'function',
|
||||
function: 'metricVis',
|
||||
arguments: {
|
||||
labelPosition: [state?.titlePosition || 'bottom'],
|
||||
labelPosition: [state?.titlePosition || DEFAULT_TITLE_POSITION],
|
||||
font: [
|
||||
{
|
||||
type: 'expression',
|
||||
|
@ -109,7 +112,7 @@ const toExpression = (
|
|||
type: 'function',
|
||||
function: 'font',
|
||||
arguments: {
|
||||
align: [state?.textAlign || 'center'],
|
||||
align: [state?.textAlign || DEFAULT_TEXT_ALIGNMENT],
|
||||
size: [metricFontSize],
|
||||
weight: ['600'],
|
||||
lHeight: [metricFontSize * 1.5],
|
||||
|
@ -127,7 +130,7 @@ const toExpression = (
|
|||
type: 'function',
|
||||
function: 'font',
|
||||
arguments: {
|
||||
align: [state?.textAlign || 'center'],
|
||||
align: [state?.textAlign || DEFAULT_TEXT_ALIGNMENT],
|
||||
size: [labelFont.size],
|
||||
lHeight: [labelFont.size * 1.5],
|
||||
sizeUnit: [labelFont.sizeUnit],
|
||||
|
|
|
@ -14,6 +14,7 @@ import {
|
|||
import { DOC_TYPE } from '../../common';
|
||||
import {
|
||||
commonEnhanceTableRowHeight,
|
||||
commonLockOldMetricVisSettings,
|
||||
commonMakeReversePaletteAsCustom,
|
||||
commonRemoveTimezoneDateHistogramParam,
|
||||
commonRenameFilterReferences,
|
||||
|
@ -103,6 +104,14 @@ export const makeLensEmbeddableFactory =
|
|||
attributes: migratedLensState,
|
||||
} as unknown as SerializableRecord;
|
||||
},
|
||||
'8.3.0': (state) => {
|
||||
const lensState = state as unknown as { attributes: LensDocShape810<VisState810> };
|
||||
const migratedLensState = commonLockOldMetricVisSettings(lensState.attributes);
|
||||
return {
|
||||
...lensState,
|
||||
attributes: migratedLensState,
|
||||
} as unknown as SerializableRecord;
|
||||
},
|
||||
}),
|
||||
getLensCustomVisualizationMigrations(customVisualizationMigrations)
|
||||
),
|
||||
|
|
|
@ -28,7 +28,7 @@ import {
|
|||
CustomVisualizationMigrations,
|
||||
LensDocShape810,
|
||||
} from './types';
|
||||
import { DOCUMENT_FIELD_NAME, layerTypes } from '../../common';
|
||||
import { DOCUMENT_FIELD_NAME, layerTypes, MetricState } from '../../common';
|
||||
import { LensDocShape } from './saved_object_migrations';
|
||||
|
||||
export const commonRenameOperationsForFormula = (
|
||||
|
@ -239,6 +239,21 @@ export const commonSetIncludeEmptyRowsDateHistogram = (
|
|||
return newAttributes;
|
||||
};
|
||||
|
||||
export const commonLockOldMetricVisSettings = (
|
||||
attributes: LensDocShape810
|
||||
): LensDocShape810<VisState820> => {
|
||||
const newAttributes = cloneDeep(attributes);
|
||||
if (newAttributes.visualizationType !== 'lnsMetric') {
|
||||
return newAttributes;
|
||||
}
|
||||
|
||||
const visState = newAttributes.state.visualization as MetricState;
|
||||
visState.textAlign = visState.textAlign ?? 'center';
|
||||
visState.titlePosition = visState.titlePosition ?? 'bottom';
|
||||
visState.size = visState.size ?? 'xl';
|
||||
return newAttributes;
|
||||
};
|
||||
|
||||
const getApplyCustomVisualizationMigrationToLens = (id: string, migration: MigrateFunction) => {
|
||||
return (savedObject: { attributes: LensDocShape }) => {
|
||||
if (savedObject.attributes.visualizationType !== id) return savedObject;
|
||||
|
|
|
@ -22,7 +22,7 @@ import {
|
|||
VisState810,
|
||||
VisState820,
|
||||
} from './types';
|
||||
import { layerTypes } from '../../common';
|
||||
import { layerTypes, MetricState } from '../../common';
|
||||
import { Filter } from '@kbn/es-query';
|
||||
|
||||
describe('Lens migrations', () => {
|
||||
|
@ -2064,4 +2064,53 @@ describe('Lens migrations', () => {
|
|||
expect(layer2Columns['4'].params).toHaveProperty('includeEmptyRows', true);
|
||||
});
|
||||
});
|
||||
describe('8.3.0 old metric visualization defaults', () => {
|
||||
const context = { log: { warning: () => {} } } as unknown as SavedObjectMigrationContext;
|
||||
const example = {
|
||||
type: 'lens',
|
||||
id: 'mocked-saved-object-id',
|
||||
attributes: {
|
||||
savedObjectId: '1',
|
||||
title: 'MyRenamedOps',
|
||||
description: '',
|
||||
visualizationType: 'lnsMetric',
|
||||
state: {
|
||||
visualization: {},
|
||||
},
|
||||
},
|
||||
} as unknown as SavedObjectUnsanitizedDoc<LensDocShape810>;
|
||||
|
||||
it('preserves current config for existing visualizations that are using the DEFAULTS', () => {
|
||||
const result = migrations['8.3.0'](example, context) as ReturnType<
|
||||
SavedObjectMigrationFn<LensDocShape, LensDocShape>
|
||||
>;
|
||||
const visState = result.attributes.state.visualization as MetricState;
|
||||
expect(visState.textAlign).toBe('center');
|
||||
expect(visState.titlePosition).toBe('bottom');
|
||||
expect(visState.size).toBe('xl');
|
||||
});
|
||||
|
||||
it('preserves current config for existing visualizations that are using CUSTOM settings', () => {
|
||||
const result = migrations['8.3.0'](
|
||||
{
|
||||
...example,
|
||||
attributes: {
|
||||
...example.attributes,
|
||||
state: {
|
||||
visualization: {
|
||||
textAlign: 'right',
|
||||
titlePosition: 'top',
|
||||
size: 's',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
context
|
||||
) as ReturnType<SavedObjectMigrationFn<LensDocShape, LensDocShape>>;
|
||||
const visState = result.attributes.state.visualization as MetricState;
|
||||
expect(visState.textAlign).toBe('right');
|
||||
expect(visState.titlePosition).toBe('top');
|
||||
expect(visState.size).toBe('s');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -44,6 +44,7 @@ import {
|
|||
commonSetLastValueShowArrayValues,
|
||||
commonEnhanceTableRowHeight,
|
||||
commonSetIncludeEmptyRowsDateHistogram,
|
||||
commonLockOldMetricVisSettings,
|
||||
} from './common_migrations';
|
||||
|
||||
interface LensDocShapePre710<VisualizationState = unknown> {
|
||||
|
@ -485,6 +486,10 @@ const setIncludeEmptyRowsDateHistogram: SavedObjectMigrationFn<LensDocShape810,
|
|||
return { ...doc, attributes: commonSetIncludeEmptyRowsDateHistogram(doc.attributes) };
|
||||
};
|
||||
|
||||
const lockOldMetricVisSettings: SavedObjectMigrationFn<LensDocShape810, LensDocShape810> = (
|
||||
doc
|
||||
) => ({ ...doc, attributes: commonLockOldMetricVisSettings(doc.attributes) });
|
||||
|
||||
const lensMigrations: SavedObjectMigrationMap = {
|
||||
'7.7.0': removeInvalidAccessors,
|
||||
// The order of these migrations matter, since the timefield migration relies on the aggConfigs
|
||||
|
@ -504,6 +509,7 @@ const lensMigrations: SavedObjectMigrationMap = {
|
|||
setIncludeEmptyRowsDateHistogram,
|
||||
enhanceTableRowHeight
|
||||
),
|
||||
'8.3.0': lockOldMetricVisSettings,
|
||||
};
|
||||
|
||||
export const getAllMigrations = (
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue