From b70481534015e9690bf4297e82da5dfe293f5674 Mon Sep 17 00:00:00 2001 From: nickofthyme Date: Wed, 20 Nov 2024 11:50:19 -0600 Subject: [PATCH 01/41] borealis visualization palettes --- package.json | 1 + .../kbn-coloring/src/palettes/utils.test.ts | 41 +++++++ packages/kbn-coloring/src/palettes/utils.ts | 40 ++++++- .../__stories__/color_mapping.stories.tsx | 11 +- .../categorical_color_mapping.tsx | 5 +- .../color_mapping/color/color_handling.ts | 36 +++--- .../components/assignment/assignment.tsx | 10 +- .../assignment/special_assignment.tsx | 11 +- .../components/color_picker/color_picker.tsx | 27 ++--- .../components/color_picker/color_swatch.tsx | 15 ++- .../color_picker/palette_colors.tsx | 26 ++--- .../components/color_picker/rgb_picker.tsx | 17 +-- .../components/container/assigments.tsx | 23 ++-- .../components/container/container.tsx | 21 +--- .../container/unassigned_terms_config.tsx | 15 +-- .../components/palette_selector/gradient.tsx | 16 +-- .../palette_selector/gradient_add_stop.tsx | 3 +- .../palette_selector/palette_selector.tsx | 33 +++--- .../components/palette_selector/scale.tsx | 8 +- .../color_mapping/config/assignments.ts | 8 +- .../config/default_color_mapping.ts | 41 +++---- .../shared_components/color_mapping/index.ts | 1 - .../color_mapping/palettes/elastic_brand.ts | 31 ----- .../color_mapping/palettes/eui_amsterdam.ts | 35 ------ .../color_mapping/palettes/index.ts | 38 ------- .../color_mapping/palettes/kibana_legacy.ts | 32 ------ .../color_mapping/palettes/neutral.ts | 24 ---- .../color_mapping/state/selectors.ts | 6 +- packages/kbn-palettes/README.md | 3 + .../classes/categorical_palette.ts | 32 ++++++ .../kbn-palettes/classes/color_fn_palette.ts | 32 ++++++ .../kbn-palettes/classes/gradient_palette.ts | 33 ++++++ packages/kbn-palettes/classes/index.ts | 11 ++ packages/kbn-palettes/classes/palette.ts | 50 +++++++++ packages/kbn-palettes/classes/palettes.ts | 44 ++++++++ packages/kbn-palettes/classes/types.ts | 52 +++++++++ packages/kbn-palettes/constants.ts | 90 +++++++++++++++ packages/kbn-palettes/hooks/index.ts | 10 ++ .../kbn-palettes/hooks/use_kbn_palettes.ts | 25 +++++ packages/kbn-palettes/index.ts | 14 +++ packages/kbn-palettes/jest.config.js | 14 +++ packages/kbn-palettes/kibana.jsonc | 5 + packages/kbn-palettes/package.json | 6 + .../palettes/categorical/elastic.ts | 56 +++++++++ .../palettes/categorical/index.ts | 11 ++ .../palettes/categorical/neutral.ts | 25 +++++ .../kbn-palettes/palettes/get_kbn_palettes.ts | 20 ++++ .../palettes/gradient/complementary.ts | 21 ++++ .../kbn-palettes/palettes/gradient/cool.ts | 21 ++++ .../kbn-palettes/palettes/gradient/gray.ts | 21 ++++ .../kbn-palettes/palettes/gradient/green.ts | 21 ++++ .../kbn-palettes/palettes/gradient/index.ts | 17 +++ .../kbn-palettes/palettes/gradient/red.ts | 21 ++++ .../kbn-palettes/palettes/gradient/status.ts | 21 ++++ .../palettes/gradient/temperature.ts | 21 ++++ .../kbn-palettes/palettes/gradient/warm.ts | 21 ++++ packages/kbn-palettes/palettes/index.ts | 46 ++++++++ .../legacy/categorical/elastic_classic.ts | 20 ++++ .../palettes/legacy/categorical/index.ts | 14 +++ .../palettes/legacy/categorical/kibana_4.ts | 20 ++++ .../palettes/legacy/categorical/kibana_7.ts | 56 +++++++++ .../categorical/kibana_7_behind_text.ts | 53 +++++++++ .../palettes/legacy/categorical/neutral.ts | 26 +++++ .../palettes/legacy/gradient/complementary.ts | 21 ++++ .../palettes/legacy/gradient/cool.ts | 21 ++++ .../palettes/legacy/gradient/gray.ts | 21 ++++ .../palettes/legacy/gradient/green.ts | 21 ++++ .../palettes/legacy/gradient/index.ts | 17 +++ .../palettes/legacy/gradient/red.ts | 21 ++++ .../palettes/legacy/gradient/status.ts | 21 ++++ .../palettes/legacy/gradient/temperature.ts | 21 ++++ .../palettes/legacy/gradient/warm.ts | 21 ++++ .../kbn-palettes/palettes/legacy/index.ts | 48 ++++++++ .../kbn-palettes/palettes/semantic/index.ts | 10 ++ .../palettes/semantic/log_level.ts | 40 +++++++ packages/kbn-palettes/tsconfig.json | 19 ++++ packages/kbn-palettes/types.ts | 10 ++ .../components/color_picker.tsx | 15 +-- .../react/kibana_context/common/tsconfig.json | 4 +- .../metric_vis_function.ts | 2 +- .../common/types/expression_renderers.ts | 3 +- .../public/components/metric_vis.tsx | 8 +- .../components/partition_vis_component.tsx | 4 + .../public/utils/layers/get_color.ts | 10 +- .../public/utils/layers/get_layers.ts | 33 +++--- .../public/components/tagcloud_component.tsx | 43 +++---- .../public/components/data_layers.tsx | 4 + .../public/components/xy_chart.tsx | 3 + .../public/expression_renderers/index.ts | 2 +- .../xy_chart_renderer.tsx | 8 +- .../helpers/color/color_mapping_accessor.ts | 5 +- .../public/helpers/data_layers.tsx | 12 +- .../expression_xy/public/plugin.ts | 6 +- src/plugins/charts/public/plugin.ts | 4 +- .../public/services/palettes/palettes.tsx | 106 +++++++----------- .../public/services/palettes/service.ts | 5 +- .../data_sets/ecommerce/saved_objects.ts | 2 +- .../data_sets/flights/saved_objects.ts | 2 +- .../data_sets/logs/saved_objects.ts | 2 +- src/plugins/vis_types/vega/public/plugin.ts | 11 ++ .../vega/public/vega_view/vega_base_view.js | 5 +- tsconfig.base.json | 2 + .../color_telemetry_helpers.ts | 7 +- .../coloring/color_mapping_accessor.ts | 17 +-- .../coloring/color_mapping_by_terms.tsx | 8 +- .../coloring/color_mapping_by_values.tsx | 2 +- .../coloring/get_cell_color_fn.ts | 4 +- .../shared_components/coloring/utils.test.ts | 48 +------- .../shared_components/coloring/utils.ts | 6 +- .../datatable/components/dimension_editor.tsx | 25 ++++- .../datatable/components/table_basic.tsx | 15 ++- .../datatable/visualization.tsx | 50 +++++++-- .../visualizations/gauge/dimension_editor.tsx | 9 +- .../visualizations/gauge/palette_config.tsx | 2 +- .../visualizations/gauge/visualization.tsx | 27 +++-- .../public/visualizations/heatmap/utils.ts | 4 +- .../visualizations/heatmap/visualization.tsx | 25 +++-- .../legacy_metric/dimension_editor.tsx | 9 +- .../legacy_metric/visualization.tsx | 27 +++-- .../metric/dimension_editor.tsx | 3 +- .../visualizations/metric/to_expression.ts | 23 +++- .../visualizations/metric/visualization.tsx | 28 +++-- .../partition/dimension_editor.tsx | 8 +- .../partition/visualization.tsx | 21 +++- .../tagcloud/tagcloud_visualization.tsx | 15 ++- .../tagcloud/tags_dimension_editor.tsx | 8 +- .../visualizations/xy/visualization.tsx | 20 ++-- .../xy/xy_config_panel/dimension_editor.tsx | 4 + .../reference_line_panel.tsx | 3 + yarn.lock | 4 + 130 files changed, 1883 insertions(+), 680 deletions(-) delete mode 100644 packages/kbn-coloring/src/shared_components/color_mapping/palettes/elastic_brand.ts delete mode 100644 packages/kbn-coloring/src/shared_components/color_mapping/palettes/eui_amsterdam.ts delete mode 100644 packages/kbn-coloring/src/shared_components/color_mapping/palettes/index.ts delete mode 100644 packages/kbn-coloring/src/shared_components/color_mapping/palettes/kibana_legacy.ts delete mode 100644 packages/kbn-coloring/src/shared_components/color_mapping/palettes/neutral.ts create mode 100644 packages/kbn-palettes/README.md create mode 100644 packages/kbn-palettes/classes/categorical_palette.ts create mode 100644 packages/kbn-palettes/classes/color_fn_palette.ts create mode 100644 packages/kbn-palettes/classes/gradient_palette.ts create mode 100644 packages/kbn-palettes/classes/index.ts create mode 100644 packages/kbn-palettes/classes/palette.ts create mode 100644 packages/kbn-palettes/classes/palettes.ts create mode 100644 packages/kbn-palettes/classes/types.ts create mode 100644 packages/kbn-palettes/constants.ts create mode 100644 packages/kbn-palettes/hooks/index.ts create mode 100644 packages/kbn-palettes/hooks/use_kbn_palettes.ts create mode 100644 packages/kbn-palettes/index.ts create mode 100644 packages/kbn-palettes/jest.config.js create mode 100644 packages/kbn-palettes/kibana.jsonc create mode 100644 packages/kbn-palettes/package.json create mode 100644 packages/kbn-palettes/palettes/categorical/elastic.ts create mode 100644 packages/kbn-palettes/palettes/categorical/index.ts create mode 100644 packages/kbn-palettes/palettes/categorical/neutral.ts create mode 100644 packages/kbn-palettes/palettes/get_kbn_palettes.ts create mode 100644 packages/kbn-palettes/palettes/gradient/complementary.ts create mode 100644 packages/kbn-palettes/palettes/gradient/cool.ts create mode 100644 packages/kbn-palettes/palettes/gradient/gray.ts create mode 100644 packages/kbn-palettes/palettes/gradient/green.ts create mode 100644 packages/kbn-palettes/palettes/gradient/index.ts create mode 100644 packages/kbn-palettes/palettes/gradient/red.ts create mode 100644 packages/kbn-palettes/palettes/gradient/status.ts create mode 100644 packages/kbn-palettes/palettes/gradient/temperature.ts create mode 100644 packages/kbn-palettes/palettes/gradient/warm.ts create mode 100644 packages/kbn-palettes/palettes/index.ts create mode 100644 packages/kbn-palettes/palettes/legacy/categorical/elastic_classic.ts create mode 100644 packages/kbn-palettes/palettes/legacy/categorical/index.ts create mode 100644 packages/kbn-palettes/palettes/legacy/categorical/kibana_4.ts create mode 100644 packages/kbn-palettes/palettes/legacy/categorical/kibana_7.ts create mode 100644 packages/kbn-palettes/palettes/legacy/categorical/kibana_7_behind_text.ts create mode 100644 packages/kbn-palettes/palettes/legacy/categorical/neutral.ts create mode 100644 packages/kbn-palettes/palettes/legacy/gradient/complementary.ts create mode 100644 packages/kbn-palettes/palettes/legacy/gradient/cool.ts create mode 100644 packages/kbn-palettes/palettes/legacy/gradient/gray.ts create mode 100644 packages/kbn-palettes/palettes/legacy/gradient/green.ts create mode 100644 packages/kbn-palettes/palettes/legacy/gradient/index.ts create mode 100644 packages/kbn-palettes/palettes/legacy/gradient/red.ts create mode 100644 packages/kbn-palettes/palettes/legacy/gradient/status.ts create mode 100644 packages/kbn-palettes/palettes/legacy/gradient/temperature.ts create mode 100644 packages/kbn-palettes/palettes/legacy/gradient/warm.ts create mode 100644 packages/kbn-palettes/palettes/legacy/index.ts create mode 100644 packages/kbn-palettes/palettes/semantic/index.ts create mode 100644 packages/kbn-palettes/palettes/semantic/log_level.ts create mode 100644 packages/kbn-palettes/tsconfig.json create mode 100644 packages/kbn-palettes/types.ts diff --git a/package.json b/package.json index 97b697d4bedf4..86a22e538813b 100644 --- a/package.json +++ b/package.json @@ -714,6 +714,7 @@ "@kbn/osquery-plugin": "link:x-pack/plugins/osquery", "@kbn/paertial-results-example-plugin": "link:examples/partial_results_example", "@kbn/painless-lab-plugin": "link:x-pack/plugins/painless_lab", + "@kbn/palettes": "link:packages/kbn-palettes", "@kbn/panel-loader": "link:packages/kbn-panel-loader", "@kbn/plugin-check": "link:packages/kbn-plugin-check", "@kbn/portable-dashboards-example": "link:examples/portable_dashboards_example", diff --git a/packages/kbn-coloring/src/palettes/utils.test.ts b/packages/kbn-coloring/src/palettes/utils.test.ts index 8292c7440063e..e7595a738bf11 100644 --- a/packages/kbn-coloring/src/palettes/utils.test.ts +++ b/packages/kbn-coloring/src/palettes/utils.test.ts @@ -9,6 +9,7 @@ import { getPaletteRegistry } from './mocks/palettes_registry'; import { + applyPaletteParams, getDataMinMax, getPaletteStops, getStepValue, @@ -312,3 +313,43 @@ describe('getStepValue', () => { ).toBe(1); }); }); + +describe('applyPaletteParams', () => { + const paletteRegistry = getPaletteRegistry(); + it('should return a palette stops array only by the name', () => { + expect( + applyPaletteParams( + paletteRegistry, + { name: 'default', type: 'palette', params: { name: 'default' } }, + { min: 0, max: 100 } + ) + ).toEqual([ + // stops are 0 and 50 by with a 20 offset (100 divided by 5 steps) for display + // the mock palette service has only 2 colors so tests are a bit off by that + { color: 'red', stop: 20 }, + { color: 'black', stop: 70 }, + ]); + }); + + it('should return a palette stops array reversed', () => { + expect( + applyPaletteParams( + paletteRegistry, + { name: 'default', type: 'palette', params: { name: 'default', reverse: true } }, + { min: 0, max: 100 } + ) + ).toEqual([ + { color: 'black', stop: 20 }, + { color: 'red', stop: 70 }, + ]); + }); + + it('should pick the default palette from the activePalette object when passed', () => { + expect( + applyPaletteParams(paletteRegistry, { name: 'mocked', type: 'palette' }, { min: 0, max: 100 }) + ).toEqual([ + { color: 'blue', stop: 20 }, + { color: 'yellow', stop: 70 }, + ]); + }); +}); diff --git a/packages/kbn-coloring/src/palettes/utils.ts b/packages/kbn-coloring/src/palettes/utils.ts index c10ef98f825af..505c0796fe06c 100644 --- a/packages/kbn-coloring/src/palettes/utils.ts +++ b/packages/kbn-coloring/src/palettes/utils.ts @@ -13,6 +13,7 @@ import { CustomPaletteParams, DataBounds, ColorStop, + PaletteOutput, } from './types'; import { @@ -20,9 +21,10 @@ import { DEFAULT_PALETTE_NAME, DEFAULT_MAX_STOP, DEFAULT_MIN_STOP, + CUSTOM_PALETTE, + COMPLEMENTARY_PALETTE, DEFAULT_FALLBACK_PALETTE, LEGACY_COMPLIMENTARY_PALETTE, - COMPLEMENTARY_PALETTE, } from './constants'; /** @internal **/ @@ -204,3 +206,39 @@ export function getActivePaletteName(name?: string): string { } return paletteName; } + +export function applyPaletteParams>( + palettes: PaletteRegistry, + activePalette: T, + dataBounds: DataBounds +) { + // make a copy of it as they have to be manipulated later on + const displayStops = getPaletteStops(palettes, activePalette?.params || {}, { + dataBounds, + defaultPaletteName: activePalette?.name, + }); + + if (activePalette?.params?.reverse && activePalette?.params?.name !== CUSTOM_PALETTE) { + return reversePalette(displayStops); + } + return displayStops; +} + +/** + * Returns color stops for given palette type: + * - custom - User has modified the stops in some way - return stops as is + * - non-custom - Default palette stops - Return new stops based on palette + * + * > This is needed for BWC when switching between kibana themes. + */ +export function getDefaultColorStops>( + paletteService: PaletteRegistry, + activePalette?: T +) { + return activePalette && activePalette.name !== CUSTOM_PALETTE + ? applyPaletteParams(paletteService, activePalette, { + min: activePalette.params?.rangeMin ?? 0, + max: activePalette.params?.rangeMax ?? 100, + }) + : activePalette?.params?.stops; +} diff --git a/packages/kbn-coloring/src/shared_components/color_mapping/__stories__/color_mapping.stories.tsx b/packages/kbn-coloring/src/shared_components/color_mapping/__stories__/color_mapping.stories.tsx index 3eebf74205a07..3ebc8064987b4 100644 --- a/packages/kbn-coloring/src/shared_components/color_mapping/__stories__/color_mapping.stories.tsx +++ b/packages/kbn-coloring/src/shared_components/color_mapping/__stories__/color_mapping.stories.tsx @@ -8,11 +8,11 @@ */ import React, { FC, useState } from 'react'; +import { getKbnPalettes } from '@kbn/palettes'; import { EuiFlyout, EuiForm, EuiPage, isColorDark } from '@elastic/eui'; import { ComponentStory } from '@storybook/react'; import { css } from '@emotion/react'; import { CategoricalColorMapping, ColorMappingProps } from '../categorical_color_mapping'; -import { AVAILABLE_PALETTES, getPalette, NeutralPalette } from '../palettes'; import { DEFAULT_COLOR_MAPPING_CONFIG } from '../config/default_color_mapping'; import { ColorMapping } from '../config'; import { getColorFactory } from '../color/color_handling'; @@ -30,9 +30,8 @@ const Template: ComponentStory> = (args) => { DEFAULT_COLOR_MAPPING_CONFIG ); - const getPaletteFn = getPalette(AVAILABLE_PALETTES, NeutralPalette); - - const colorFactory = getColorFactory(updatedModel, getPaletteFn, false, args.data); + const palettes = getKbnPalettes({ name: 'amsterdam', darkMode: false }); + const colorFactory = getColorFactory(updatedModel, palettes, false, args.data); return ( @@ -71,7 +70,7 @@ const Template: ComponentStory> = (args) => { ownFocus={false} > - + @@ -82,6 +81,7 @@ export const Default = Template.bind({}); Default.args = { model: { ...DEFAULT_COLOR_MAPPING_CONFIG, + paletteId: 'eui_amsterdam', colorMode: { type: 'categorical', @@ -119,7 +119,6 @@ Default.args = { ], }, - palettes: AVAILABLE_PALETTES, specialTokens: new Map(), // eslint-disable-next-line no-console onModelUpdate: (model) => console.log(model), diff --git a/packages/kbn-coloring/src/shared_components/color_mapping/categorical_color_mapping.tsx b/packages/kbn-coloring/src/shared_components/color_mapping/categorical_color_mapping.tsx index 668cdc7ce07fd..8bd006ba9c663 100644 --- a/packages/kbn-coloring/src/shared_components/color_mapping/categorical_color_mapping.tsx +++ b/packages/kbn-coloring/src/shared_components/color_mapping/categorical_color_mapping.tsx @@ -11,6 +11,7 @@ import React from 'react'; import { Provider } from 'react-redux'; import { type EnhancedStore, configureStore } from '@reduxjs/toolkit'; import { isEqual } from 'lodash'; +import { KbnPalettes } from '@kbn/palettes'; import { colorMappingReducer, updateModel } from './state/color_mapping'; import { Container } from './components/container/container'; import { ColorMapping } from './config'; @@ -43,8 +44,8 @@ export type ColorMappingInputData = export interface ColorMappingProps { /** The initial color mapping model, usually coming from a the visualization saved object */ model: ColorMapping.Config; - /** A map of paletteId and palette configuration */ - palettes: Map; + /** A collection of palette configurations */ + palettes: KbnPalettes; /** A data description of what needs to be colored */ data: ColorMappingInputData; /** Theme dark mode */ diff --git a/packages/kbn-coloring/src/shared_components/color_mapping/color/color_handling.ts b/packages/kbn-coloring/src/shared_components/color_mapping/color/color_handling.ts index 373e56e3cb8f6..0031ac81908c0 100644 --- a/packages/kbn-coloring/src/shared_components/color_mapping/color/color_handling.ts +++ b/packages/kbn-coloring/src/shared_components/color_mapping/color/color_handling.ts @@ -9,9 +9,9 @@ import chroma from 'chroma-js'; import { findLast } from 'lodash'; +import { KbnPalette, KbnPalettes } from '@kbn/palettes'; import { ColorMapping } from '../config'; import { changeAlpha, combineColors, getValidColor } from './color_math'; -import { getPalette, NeutralPalette } from '../palettes'; import { ColorMappingInputData } from '../categorical_color_mapping'; import { ruleMatch } from './rule_matching'; import { GradientColorMode } from '../config/types'; @@ -25,7 +25,7 @@ export function getAssignmentColor( color: | ColorMapping.Config['assignments'][number]['color'] | (ColorMapping.LoopColor & { paletteId: string; colorIndex: number }), - getPaletteFn: ReturnType, + palettes: KbnPalettes, isDarkMode: boolean, index: number, total: number @@ -34,12 +34,12 @@ export function getAssignmentColor( case 'colorCode': case 'categorical': case 'loop': - return getColor(color, getPaletteFn, isDarkMode); + return getColor(color, palettes); case 'gradient': { if (colorMode.type === 'categorical') { return 'red'; } - const colorScale = getGradientColorScale(colorMode, getPaletteFn, isDarkMode); + const colorScale = getGradientColorScale(colorMode, palettes, isDarkMode); return total === 0 ? 'red' : total === 1 ? colorScale(0) : colorScale(index / (total - 1)); } } @@ -50,19 +50,16 @@ export function getColor( | ColorMapping.ColorCode | ColorMapping.CategoricalColor | (ColorMapping.LoopColor & { paletteId: string; colorIndex: number }), - getPaletteFn: ReturnType, - isDarkMode: boolean + palettes: KbnPalettes ): string { return color.type === 'colorCode' ? color.colorCode - : getValidColor( - getPaletteFn(color.paletteId).getColor(color.colorIndex, isDarkMode, true) - ).hex(); + : getValidColor(palettes.get(color.paletteId).getColor(color.colorIndex)).hex(); } export function getColorFactory( { assignments, specialAssignments, colorMode, paletteId }: ColorMapping.Config, - getPaletteFn: ReturnType, + palettes: KbnPalettes, isDarkMode: boolean, data: ColorMappingInputData ): (category: string | string[]) => string { @@ -104,7 +101,7 @@ export function getColorFactory( return getAssignmentColor( colorMode, autoByOrderAssignments[nonAssignedCategoryIndex].color, - getPaletteFn, + palettes, isDarkMode, autoAssignmentIndex, assignments.length @@ -129,7 +126,7 @@ export function getColorFactory( paletteId, } : specialAssignments[DEFAULT_OTHER_ASSIGNMENT_INDEX].color, - getPaletteFn, + palettes, isDarkMode, indexIfGradient, totalColorsIfGradient @@ -146,7 +143,7 @@ export function getColorFactory( return getAssignmentColor( colorMode, assignment.color, - getPaletteFn, + palettes, isDarkMode, matchingAssignmentIndex, assignments.length @@ -155,30 +152,29 @@ export function getColorFactory( return getColor( { type: 'categorical', - paletteId: NeutralPalette.id, + paletteId: KbnPalette.Neutral, colorIndex: DEFAULT_NEUTRAL_PALETTE_INDEX, }, - getPaletteFn, - isDarkMode + palettes ); }; } export function getGradientColorScale( colorMode: GradientColorMode, - getPaletteFn: ReturnType, + palettes: KbnPalettes, isDarkMode: boolean ): (value: number) => string { const steps = colorMode.steps.length === 1 ? [ - getColor(colorMode.steps[0], getPaletteFn, isDarkMode), + getColor(colorMode.steps[0], palettes), combineColors( - changeAlpha(getColor(colorMode.steps[0], getPaletteFn, isDarkMode), 0.3), + changeAlpha(getColor(colorMode.steps[0], palettes), 0.3), isDarkMode ? 'black' : 'white' ), ] - : colorMode.steps.map((d) => getColor(d, getPaletteFn, isDarkMode)); + : colorMode.steps.map((d) => getColor(d, palettes)); steps.sort(() => (colorMode.sort === 'asc' ? -1 : 1)); const scale = chroma.scale(steps).mode('lab'); return (value: number) => scale(value).hex(); diff --git a/packages/kbn-coloring/src/shared_components/color_mapping/components/assignment/assignment.tsx b/packages/kbn-coloring/src/shared_components/color_mapping/components/assignment/assignment.tsx index 0606aa94e6aa8..5a629a18cf959 100644 --- a/packages/kbn-coloring/src/shared_components/color_mapping/components/assignment/assignment.tsx +++ b/packages/kbn-coloring/src/shared_components/color_mapping/components/assignment/assignment.tsx @@ -13,6 +13,7 @@ import { EuiButtonIcon, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { css } from '@emotion/react'; import { euiThemeVars } from '@kbn/ui-theme'; +import { IKbnPalette, KbnPalettes } from '@kbn/palettes'; import { removeAssignment, updateAssignmentColor, @@ -21,7 +22,6 @@ import { import { ColorMapping } from '../../config'; import { Range } from './range'; import { Match } from './match'; -import { getPalette } from '../../palettes'; import { ColorMappingInputData } from '../../categorical_color_mapping'; import { ColorSwatch } from '../color_picker/color_swatch'; @@ -33,8 +33,8 @@ export function Assignment({ index, total, palette, + palettes, colorMode, - getPaletteFn, isDarkMode, specialTokens, assignmentValuesCounter, @@ -45,8 +45,8 @@ export function Assignment({ colorMode: ColorMapping.Config['colorMode']; assignment: ColorMapping.Config['assignments'][number]; disableDelete: boolean; - palette: ColorMapping.CategoricalPalette; - getPaletteFn: ReturnType; + palette: IKbnPalette; + palettes: KbnPalettes; isDarkMode: boolean; specialTokens: Map; assignmentValuesCounter: Map; @@ -62,9 +62,9 @@ export function Assignment({ swatchShape="square" colorMode={colorMode} assignmentColor={assignment.color} - getPaletteFn={getPaletteFn} index={index} palette={palette} + palettes={palettes} total={total} onColorChange={(color) => { dispatch(updateAssignmentColor({ assignmentIndex: index, color })); diff --git a/packages/kbn-coloring/src/shared_components/color_mapping/components/assignment/special_assignment.tsx b/packages/kbn-coloring/src/shared_components/color_mapping/components/assignment/special_assignment.tsx index 3bdab18cbf19e..4834ccc57d822 100644 --- a/packages/kbn-coloring/src/shared_components/color_mapping/components/assignment/special_assignment.tsx +++ b/packages/kbn-coloring/src/shared_components/color_mapping/components/assignment/special_assignment.tsx @@ -9,8 +9,7 @@ import { useDispatch } from 'react-redux'; import React from 'react'; -import { ColorMapping } from '../../config'; -import { getPalette } from '../../palettes'; +import { IKbnPalette, KbnPalettes } from '@kbn/palettes'; import { ColorSwatch } from '../color_picker/color_swatch'; import { updateSpecialAssignmentColor } from '../../state/color_mapping'; import { ColorCode, CategoricalColor } from '../../config/types'; @@ -19,15 +18,15 @@ export function SpecialAssignment({ assignmentColor, index, palette, - getPaletteFn, + palettes, isDarkMode, total, }: { isDarkMode: boolean; index: number; assignmentColor: CategoricalColor | ColorCode; - palette: ColorMapping.CategoricalPalette; - getPaletteFn: ReturnType; + palette: IKbnPalette; + palettes: KbnPalettes; total: number; }) { const dispatch = useDispatch(); @@ -36,7 +35,7 @@ export function SpecialAssignment({ forType="specialAssignment" colorMode={{ type: 'categorical' }} assignmentColor={assignmentColor} - getPaletteFn={getPaletteFn} + palettes={palettes} index={index} palette={palette} total={total} diff --git a/packages/kbn-coloring/src/shared_components/color_mapping/components/color_picker/color_picker.tsx b/packages/kbn-coloring/src/shared_components/color_mapping/components/color_picker/color_picker.tsx index e4d42b9645698..eafa07793dd5c 100644 --- a/packages/kbn-coloring/src/shared_components/color_mapping/components/color_picker/color_picker.tsx +++ b/packages/kbn-coloring/src/shared_components/color_mapping/components/color_picker/color_picker.tsx @@ -10,32 +10,29 @@ import React, { useState } from 'react'; import { EuiButtonEmpty, EuiPopoverTitle, EuiTab, EuiTabs, EuiHorizontalRule } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; +import { IKbnPalette, KbnPalette, KbnPalettes } from '@kbn/palettes'; import { ColorMapping } from '../../config'; -import { getPalette } from '../../palettes'; import { PaletteColors } from './palette_colors'; import { RGBPicker } from './rgb_picker'; -import { NeutralPalette } from '../../palettes/neutral'; export function ColorPicker({ - palette, - getPaletteFn, color, + palette, + palettes, close, selectColor, - isDarkMode, deleteStep, }: { color: ColorMapping.CategoricalColor | ColorMapping.ColorCode; - getPaletteFn: ReturnType; - palette: ColorMapping.CategoricalPalette; - isDarkMode: boolean; + palette: IKbnPalette; + palettes: KbnPalettes; close: () => void; selectColor: (color: ColorMapping.CategoricalColor | ColorMapping.ColorCode) => void; deleteStep?: () => void; }) { const [tab, setTab] = useState( color.type === 'categorical' && - (color.paletteId === palette.id || color.paletteId === NeutralPalette.id) + (color.paletteId === palette.id || color.paletteId === KbnPalette.Neutral) ? 'palette' : 'custom' ); @@ -64,20 +61,12 @@ export function ColorPicker({ {tab === 'palette' ? ( ) : ( - + )} {deleteStep ? ( <> diff --git a/packages/kbn-coloring/src/shared_components/color_mapping/components/color_picker/color_swatch.tsx b/packages/kbn-coloring/src/shared_components/color_mapping/components/color_picker/color_swatch.tsx index 590d66018e803..b1af9d364efd4 100644 --- a/packages/kbn-coloring/src/shared_components/color_mapping/components/color_picker/color_swatch.tsx +++ b/packages/kbn-coloring/src/shared_components/color_mapping/components/color_picker/color_swatch.tsx @@ -18,10 +18,10 @@ import React from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { i18n } from '@kbn/i18n'; import { css } from '@emotion/react'; +import { IKbnPalette, KbnPalettes } from '@kbn/palettes'; import { ColorPicker } from './color_picker'; import { getAssignmentColor } from '../../color/color_handling'; import { ColorMapping } from '../../config'; -import { getPalette } from '../../palettes'; import { removeGradientColorStep } from '../../state/color_mapping'; import { selectColorPickerVisibility } from '../../state/selectors'; @@ -31,22 +31,23 @@ import { getValidColor } from '../../color/color_math'; interface ColorPickerSwatchProps { colorMode: ColorMapping.Config['colorMode']; assignmentColor: ColorMapping.Config['assignments'][number]['color']; - getPaletteFn: ReturnType; index: number; total: number; - palette: ColorMapping.CategoricalPalette; + palette: IKbnPalette; + palettes: KbnPalettes; onColorChange: (color: ColorMapping.CategoricalColor | ColorMapping.ColorCode) => void; swatchShape: 'square' | 'round'; isDarkMode: boolean; forType: 'assignment' | 'specialAssignment' | 'gradient'; } + export const ColorSwatch = ({ colorMode, assignmentColor, - getPaletteFn, index, total, palette, + palettes, onColorChange, swatchShape, isDarkMode, @@ -61,7 +62,7 @@ export const ColorSwatch = ({ const colorHex = getAssignmentColor( colorMode, assignmentColor, - getPaletteFn, + palettes, isDarkMode, index, total @@ -147,11 +148,9 @@ export const ColorSwatch = ({ } color={assignmentColor} palette={palette} - getPaletteFn={getPaletteFn} + palettes={palettes} close={() => dispatch(hideColorPickerVisibility())} - isDarkMode={isDarkMode} selectColor={(color) => { - // dispatch update onColorChange(color); }} deleteStep={ diff --git a/packages/kbn-coloring/src/shared_components/color_mapping/components/color_picker/palette_colors.tsx b/packages/kbn-coloring/src/shared_components/color_mapping/components/color_picker/palette_colors.tsx index 3f58ed5d564e9..0ed0d8d68bb63 100644 --- a/packages/kbn-coloring/src/shared_components/color_mapping/components/color_picker/palette_colors.tsx +++ b/packages/kbn-coloring/src/shared_components/color_mapping/components/color_picker/palette_colors.tsx @@ -19,35 +19,33 @@ import { EuiSpacer, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; +import { IKbnPalette, KbnPalette, KbnPalettes } from '@kbn/palettes'; import { ColorMapping } from '../../config'; -import { getPalette } from '../../palettes'; import { isSameColor } from '../../color/color_math'; -import { NeutralPalette } from '../../palettes/neutral'; export function PaletteColors({ palette, - isDarkMode, + palettes, color, - getPaletteFn, selectColor, }: { - palette: ColorMapping.CategoricalPalette; - isDarkMode: boolean; + palette: IKbnPalette; + palettes: KbnPalettes; color: ColorMapping.CategoricalColor | ColorMapping.ColorCode; - getPaletteFn: ReturnType; selectColor: (color: ColorMapping.CategoricalColor | ColorMapping.ColorCode) => void; }) { const colors = Array.from({ length: palette.colorCount }, (d, i) => { - return palette.getColor(i, isDarkMode, false); + return palette.getColor(i); }); - const neutralColors = Array.from({ length: NeutralPalette.colorCount }, (d, i) => { - return NeutralPalette.getColor(i, isDarkMode, false); + const neutralPalette = palettes.get(KbnPalette.Neutral); + const neutralColors = Array.from({ length: neutralPalette.colorCount }, (d, i) => { + return neutralPalette.getColor(i); }); const originalColor = color.type === 'categorical' - ? color.paletteId === NeutralPalette.id - ? NeutralPalette.getColor(color.colorIndex, isDarkMode, false) - : getPaletteFn(color.paletteId).getColor(color.colorIndex, isDarkMode, false) + ? color.paletteId === neutralPalette.id + ? neutralPalette.getColor(color.colorIndex) + : palettes.get(color.paletteId).getColor(color.colorIndex) : color.colorCode; return ( <> @@ -126,7 +124,7 @@ export function PaletteColors({ onClick={() => selectColor({ type: 'categorical', - paletteId: NeutralPalette.id, + paletteId: neutralPalette.id, colorIndex: index, }) } diff --git a/packages/kbn-coloring/src/shared_components/color_mapping/components/color_picker/rgb_picker.tsx b/packages/kbn-coloring/src/shared_components/color_mapping/components/color_picker/rgb_picker.tsx index 6c701fbfebacc..175d3ae36e71a 100644 --- a/packages/kbn-coloring/src/shared_components/color_mapping/components/color_picker/rgb_picker.tsx +++ b/packages/kbn-coloring/src/shared_components/color_mapping/components/color_picker/rgb_picker.tsx @@ -22,24 +22,19 @@ import chromajs from 'chroma-js'; import { css } from '@emotion/react'; import { euiThemeVars } from '@kbn/ui-theme'; import { i18n } from '@kbn/i18n'; +import { KbnPalettes } from '@kbn/palettes'; import { ColorMapping } from '../../config'; import { hasEnoughContrast } from '../../color/color_math'; -import { getPalette } from '../../palettes'; export function RGBPicker({ - isDarkMode, color, - getPaletteFn, + palettes, selectColor, - close, }: { - palette: ColorMapping.CategoricalPalette; - isDarkMode: boolean; color: ColorMapping.CategoricalColor | ColorMapping.ColorCode; - getPaletteFn: ReturnType; + palettes: KbnPalettes; selectColor: (color: ColorMapping.CategoricalColor | ColorMapping.ColorCode) => void; - close: () => void; }) { const [customColorMappingColor, setCustomColorMappingColor] = useState< ColorMapping.CategoricalColor | ColorMapping.ColorCode @@ -47,11 +42,7 @@ export function RGBPicker({ const customColorHex = customColorMappingColor.type === 'categorical' - ? getPaletteFn(customColorMappingColor.paletteId).getColor( - customColorMappingColor.colorIndex, - isDarkMode, - false - ) + ? palettes.get(customColorMappingColor.paletteId).getColor(customColorMappingColor.colorIndex) : customColorMappingColor.colorCode; const [colorTextInput, setColorTextInput] = useState(customColorHex); diff --git a/packages/kbn-coloring/src/shared_components/color_mapping/components/container/assigments.tsx b/packages/kbn-coloring/src/shared_components/color_mapping/components/container/assigments.tsx index 1f9c37b1c60b6..af4ceae80a0d9 100644 --- a/packages/kbn-coloring/src/shared_components/color_mapping/components/container/assigments.tsx +++ b/packages/kbn-coloring/src/shared_components/color_mapping/components/container/assigments.tsx @@ -29,6 +29,7 @@ import { euiThemeVars } from '@kbn/ui-theme'; import { i18n } from '@kbn/i18n'; import { useDispatch, useSelector } from 'react-redux'; import { findLast } from 'lodash'; +import { KbnPalettes } from '@kbn/palettes'; import { Assignment } from '../assignment/assignment'; import { addNewAssignment, @@ -38,7 +39,6 @@ import { import { selectColorMode, selectComputedAssignments, selectPalette } from '../../state/selectors'; import { ColorMappingInputData } from '../../categorical_color_mapping'; import { ColorMapping } from '../../config'; -import { getPalette, NeutralPalette } from '../../palettes'; import { ruleMatch } from '../../color/rule_matching'; export function AssignmentsConfig({ @@ -47,7 +47,7 @@ export function AssignmentsConfig({ isDarkMode, specialTokens, }: { - palettes: Map; + palettes: KbnPalettes; data: ColorMappingInputData; isDarkMode: boolean; /** map between original and formatted tokens used to handle special cases, like the Other bucket and the empty bucket */ @@ -56,8 +56,7 @@ export function AssignmentsConfig({ const [showOtherActions, setShowOtherActions] = useState(false); const dispatch = useDispatch(); - const getPaletteFn = getPalette(palettes, NeutralPalette); - const palette = useSelector(selectPalette(getPaletteFn)); + const palette = useSelector(selectPalette(palettes)); const colorMode = useSelector(selectColorMode); const assignments = useSelector(selectComputedAssignments); @@ -100,13 +99,13 @@ export function AssignmentsConfig({ ? { type: 'categorical', paletteId: palette.id, - colorIndex: nextCategoricalIndex % palette.colorCount, + colorIndex: nextCategoricalIndex % palette.colors.length, } : { type: 'gradient' }, touched: false, }) ); - }, [assignments, colorMode.type, data.type, dispatch, palette.colorCount, palette.id]); + }, [assignments, colorMode.type, data.type, dispatch, palette.colors.length, palette.id]); const onClickAddAllCurrentCategories = useCallback(() => { if (data.type === 'categories') { @@ -128,7 +127,7 @@ export function AssignmentsConfig({ ? { type: 'categorical', paletteId: palette.id, - colorIndex: (nextCategoricalIndex + i) % palette.colorCount, + colorIndex: (nextCategoricalIndex + i) % palette.colors.length, } : { type: 'gradient' }, touched: false, @@ -138,13 +137,13 @@ export function AssignmentsConfig({ dispatch(addNewAssignments(newAssignments)); } }, [ - dispatch, + data.type, assignments, + unmatchingCategories, + dispatch, colorMode.type, - data.type, - palette.colorCount, palette.id, - unmatchingCategories, + palette.colors.length, ]); return ( @@ -176,8 +175,8 @@ export function AssignmentsConfig({ total={assignments.length} colorMode={colorMode} palette={palette} + palettes={palettes} isDarkMode={isDarkMode} - getPaletteFn={getPaletteFn} assignment={assignment} disableDelete={false} specialTokens={specialTokens} diff --git a/packages/kbn-coloring/src/shared_components/color_mapping/components/container/container.tsx b/packages/kbn-coloring/src/shared_components/color_mapping/components/container/container.tsx index 5b5b7d5b08772..49ea5eb99caf8 100644 --- a/packages/kbn-coloring/src/shared_components/color_mapping/components/container/container.tsx +++ b/packages/kbn-coloring/src/shared_components/color_mapping/components/container/container.tsx @@ -12,15 +12,13 @@ import { useSelector, useDispatch } from 'react-redux'; import { EuiFlexGroup, EuiFlexItem, EuiFormRow, EuiButtonIcon, EuiToolTip } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { css } from '@emotion/react'; +import { KbnPalettes } from '@kbn/palettes'; import { PaletteSelector } from '../palette_selector/palette_selector'; import { changeGradientSortOrder } from '../../state/color_mapping'; -import { ColorMapping } from '../../config'; -import { getPalette } from '../../palettes'; import { selectColorMode, selectComputedAssignments, selectPalette } from '../../state/selectors'; import { ColorMappingInputData } from '../../categorical_color_mapping'; import { Gradient } from '../palette_selector/gradient'; -import { NeutralPalette } from '../../palettes/neutral'; import { ScaleMode } from '../palette_selector/scale'; import { UnassignedTermsConfig } from './unassigned_terms_config'; import { AssignmentsConfig } from './assigments'; @@ -31,17 +29,14 @@ export function Container({ isDarkMode, specialTokens, }: { - palettes: Map; + palettes: KbnPalettes; data: ColorMappingInputData; isDarkMode: boolean; /** map between original and formatted tokens used to handle special cases, like the Other bucket and the empty bucket */ specialTokens: Map; }) { const dispatch = useDispatch(); - - const getPaletteFn = getPalette(palettes, NeutralPalette); - - const palette = useSelector(selectPalette(getPaletteFn)); + const palette = useSelector(selectPalette(palettes)); const colorMode = useSelector(selectColorMode); const assignments = useSelector(selectComputedAssignments); @@ -55,14 +50,10 @@ export function Container({ gutterSize="s" > - + - + @@ -105,7 +96,7 @@ export function Container({ > diff --git a/packages/kbn-coloring/src/shared_components/color_mapping/components/container/unassigned_terms_config.tsx b/packages/kbn-coloring/src/shared_components/color_mapping/components/container/unassigned_terms_config.tsx index 3a7469d120f10..4ebaadeeb7b82 100644 --- a/packages/kbn-coloring/src/shared_components/color_mapping/components/container/unassigned_terms_config.tsx +++ b/packages/kbn-coloring/src/shared_components/color_mapping/components/container/unassigned_terms_config.tsx @@ -19,14 +19,13 @@ import { import { i18n } from '@kbn/i18n'; import { useDispatch, useSelector } from 'react-redux'; import { css } from '@emotion/react'; +import { KbnPalette, KbnPalettes } from '@kbn/palettes'; import { updateSpecialAssignmentColor } from '../../state/color_mapping'; -import { getPalette, NeutralPalette } from '../../palettes'; import { DEFAULT_NEUTRAL_PALETTE_INDEX, DEFAULT_OTHER_ASSIGNMENT_INDEX, } from '../../config/default_color_mapping'; import { SpecialAssignment } from '../assignment/special_assignment'; -import { ColorMapping } from '../../config'; import { selectColorMode, selectPalette, selectSpecialAssignments } from '../../state/selectors'; import { ColorMappingInputData } from '../../categorical_color_mapping'; @@ -35,15 +34,13 @@ export function UnassignedTermsConfig({ data, isDarkMode, }: { - palettes: Map; + palettes: KbnPalettes; data: ColorMappingInputData; isDarkMode: boolean; }) { const dispatch = useDispatch(); - - const getPaletteFn = getPalette(palettes, NeutralPalette); - - const palette = useSelector(selectPalette(getPaletteFn)); + const neutralPalette = palettes.get(KbnPalette.Neutral); + const palette = useSelector(selectPalette(palettes)); const colorMode = useSelector(selectColorMode); const specialAssignments = useSelector(selectSpecialAssignments); const otherAssignment = specialAssignments[DEFAULT_OTHER_ASSIGNMENT_INDEX]; @@ -99,7 +96,7 @@ export function UnassignedTermsConfig({ : { type: 'categorical', colorIndex: DEFAULT_NEUTRAL_PALETTE_INDEX, - paletteId: NeutralPalette.id, + paletteId: neutralPalette.id, }, }) ); @@ -122,7 +119,7 @@ export function UnassignedTermsConfig({ index={0} palette={palette} isDarkMode={isDarkMode} - getPaletteFn={getPaletteFn} + palettes={palettes} assignmentColor={otherAssignment.color} total={specialAssignments.length} /> diff --git a/packages/kbn-coloring/src/shared_components/color_mapping/components/palette_selector/gradient.tsx b/packages/kbn-coloring/src/shared_components/color_mapping/components/palette_selector/gradient.tsx index c08834fdd384a..5fc9dc40f1589 100644 --- a/packages/kbn-coloring/src/shared_components/color_mapping/components/palette_selector/gradient.tsx +++ b/packages/kbn-coloring/src/shared_components/color_mapping/components/palette_selector/gradient.tsx @@ -11,9 +11,9 @@ import React from 'react'; import { euiThemeVars } from '@kbn/ui-theme'; import { css } from '@emotion/react'; import { useDispatch } from 'react-redux'; +import { KbnPalettes } from '@kbn/palettes'; import { changeAlpha } from '../../color/color_math'; import { ColorMapping } from '../../config'; -import { getPalette } from '../../palettes'; import { getGradientColorScale } from '../../color/color_handling'; import { AddStop } from './gradient_add_stop'; import { ColorSwatch } from '../color_picker/color_swatch'; @@ -22,21 +22,21 @@ import { updateGradientColorStep } from '../../state/color_mapping'; export function Gradient({ paletteId, colorMode, - getPaletteFn, isDarkMode, + palettes, }: { paletteId: string; isDarkMode: boolean; colorMode: ColorMapping.Config['colorMode']; - getPaletteFn: ReturnType; + palettes: KbnPalettes; }) { const dispatch = useDispatch(); if (colorMode.type === 'categorical') { return null; } - const currentPalette = getPaletteFn(paletteId); - const gradientColorScale = getGradientColorScale(colorMode, getPaletteFn, isDarkMode); + const currentPalette = palettes.get(paletteId); + const gradientColorScale = getGradientColorScale(colorMode, palettes, isDarkMode); const startStepColor = colorMode.sort === 'asc' @@ -104,7 +104,7 @@ export function Gradient({ forType="gradient" colorMode={colorMode} assignmentColor={startStepColor} - getPaletteFn={getPaletteFn} + palettes={palettes} index={startStepIndex} palette={currentPalette} total={colorMode.steps.length} @@ -133,7 +133,7 @@ export function Gradient({ forType="gradient" colorMode={colorMode} assignmentColor={middleStepColor} - getPaletteFn={getPaletteFn} + palettes={palettes} index={middleStepIndex} palette={currentPalette} total={colorMode.steps.length} @@ -161,7 +161,7 @@ export function Gradient({ forType="gradient" colorMode={colorMode} assignmentColor={endStepColor} - getPaletteFn={getPaletteFn} + palettes={palettes} index={endStepIndex} palette={currentPalette} total={colorMode.steps.length} diff --git a/packages/kbn-coloring/src/shared_components/color_mapping/components/palette_selector/gradient_add_stop.tsx b/packages/kbn-coloring/src/shared_components/color_mapping/components/palette_selector/gradient_add_stop.tsx index 6b89f8143fb8f..1c6736262e217 100644 --- a/packages/kbn-coloring/src/shared_components/color_mapping/components/palette_selector/gradient_add_stop.tsx +++ b/packages/kbn-coloring/src/shared_components/color_mapping/components/palette_selector/gradient_add_stop.tsx @@ -20,6 +20,7 @@ import { import { useDispatch } from 'react-redux'; import { i18n } from '@kbn/i18n'; import { css } from '@emotion/react'; +import { IKbnPalette } from '@kbn/palettes'; import { ColorMapping } from '../../config'; import { addGradientColorStep } from '../../state/color_mapping'; import { colorPickerVisibility } from '../../state/ui'; @@ -30,7 +31,7 @@ export function AddStop({ at, }: { colorMode: ColorMapping.GradientColorMode; - currentPalette: ColorMapping.CategoricalPalette; + currentPalette: IKbnPalette; at: number; }) { const euiTheme = useEuiTheme(); diff --git a/packages/kbn-coloring/src/shared_components/color_mapping/components/palette_selector/palette_selector.tsx b/packages/kbn-coloring/src/shared_components/color_mapping/components/palette_selector/palette_selector.tsx index 1d909f000a417..54c6d05bbed18 100644 --- a/packages/kbn-coloring/src/shared_components/color_mapping/components/palette_selector/palette_selector.tsx +++ b/packages/kbn-coloring/src/shared_components/color_mapping/components/palette_selector/palette_selector.tsx @@ -7,25 +7,16 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -import React, { useCallback, useState } from 'react'; +import React, { useCallback, useState, useMemo } from 'react'; import { useSelector, useDispatch } from 'react-redux'; import { EuiColorPalettePicker, EuiConfirmModal, EuiFormRow } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; +import { KbnPalettes } from '@kbn/palettes'; import { RootState, updatePalette } from '../../state/color_mapping'; -import { ColorMapping } from '../../config'; import { updateAssignmentsPalette, updateColorModePalette } from '../../config/assignments'; -import { getPalette } from '../../palettes'; -export function PaletteSelector({ - palettes, - getPaletteFn, - isDarkMode, -}: { - getPaletteFn: ReturnType; - palettes: Map; - isDarkMode: boolean; -}) { +export function PaletteSelector({ palettes }: { palettes: KbnPalettes }) { const dispatch = useDispatch(); const model = useSelector((state: RootState) => state.colorMapping); @@ -38,7 +29,7 @@ export function PaletteSelector({ model.assignments, model.colorMode, selectedPaletteId, - getPaletteFn, + palettes, preserveColorChanges ), colorMode: updateColorModePalette( @@ -49,7 +40,7 @@ export function PaletteSelector({ }) ); }, - [getPaletteFn, model, dispatch] + [dispatch, model.assignments, model.colorMode, palettes] ); const [preserveModalPaletteId, setPreserveModalPaletteId] = useState(null); @@ -85,6 +76,11 @@ export function PaletteSelector({ ) : null; + const currentPaletteId = useMemo( + () => palettes.get(model.paletteId).id, // need to resolve aliased id + [model.paletteId, palettes] + ); + return ( <> {preserveChangesModal} @@ -97,14 +93,15 @@ export function PaletteSelector({ d.name !== 'Neutral') + palettes={palettes + .getAll() + .filter((d) => d.type === 'categorical') .map((palette) => ({ 'data-test-subj': `kbnColoring_ColorMapping_Palette-${palette.id}`, value: palette.id, title: palette.name, palette: Array.from({ length: palette.colorCount }, (_, i) => { - return palette.getColor(i, isDarkMode, false); + return palette.getColor(i); }), type: 'fixed', }))} @@ -118,7 +115,7 @@ export function PaletteSelector({ switchPaletteFn(selectedPaletteId, false); } }} - valueOfSelected={model.paletteId} + valueOfSelected={currentPaletteId} selectionDisplay={'palette'} compressed={true} /> diff --git a/packages/kbn-coloring/src/shared_components/color_mapping/components/palette_selector/scale.tsx b/packages/kbn-coloring/src/shared_components/color_mapping/components/palette_selector/scale.tsx index f7249aa12d576..42fea54d6fdb7 100644 --- a/packages/kbn-coloring/src/shared_components/color_mapping/components/palette_selector/scale.tsx +++ b/packages/kbn-coloring/src/shared_components/color_mapping/components/palette_selector/scale.tsx @@ -12,12 +12,12 @@ import { useSelector, useDispatch } from 'react-redux'; import { EuiButtonGroup, EuiConfirmModal, EuiFormRow } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; +import { KbnPalettes } from '@kbn/palettes'; import { RootState, updatePalette } from '../../state/color_mapping'; import { ColorMapping } from '../../config'; import { updateAssignmentsPalette } from '../../config/assignments'; -import { getPalette } from '../../palettes'; -export function ScaleMode({ getPaletteFn }: { getPaletteFn: ReturnType }) { +export function ScaleMode({ palettes }: { palettes: KbnPalettes }) { const dispatch = useDispatch(); const colorMode = useSelector((state: RootState) => state.colorMapping.colorMode); const model = useSelector((state: RootState) => state.colorMapping); @@ -46,12 +46,12 @@ export function ScaleMode({ getPaletteFn }: { getPaletteFn: ReturnType( diff --git a/packages/kbn-coloring/src/shared_components/color_mapping/config/assignments.ts b/packages/kbn-coloring/src/shared_components/color_mapping/config/assignments.ts index 3d30ce3c7f607..93c1140ea2b71 100644 --- a/packages/kbn-coloring/src/shared_components/color_mapping/config/assignments.ts +++ b/packages/kbn-coloring/src/shared_components/color_mapping/config/assignments.ts @@ -7,17 +7,17 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ +import { KbnPalettes } from '@kbn/palettes'; import type { ColorMapping } from '.'; -import { getPalette } from '../palettes'; export function updateAssignmentsPalette( assignments: ColorMapping.Config['assignments'], colorMode: ColorMapping.Config['colorMode'], paletteId: string, - getPaletteFn: ReturnType, + palettes: KbnPalettes, preserveColorChanges: boolean ): ColorMapping.Config['assignments'] { - const palette = getPaletteFn(paletteId); + const palette = palettes.get(paletteId); return assignments.map(({ rule, color, touched }, index) => { if (preserveColorChanges && touched) { return { rule, color, touched }; @@ -27,7 +27,7 @@ export function updateAssignmentsPalette( ? { type: 'categorical', paletteId, - colorIndex: index % palette.colorCount, + colorIndex: index % palette.colors.length, } : { type: 'gradient' }; return { diff --git a/packages/kbn-coloring/src/shared_components/color_mapping/config/default_color_mapping.ts b/packages/kbn-coloring/src/shared_components/color_mapping/config/default_color_mapping.ts index b613d0d76adb8..1005f5d89855a 100644 --- a/packages/kbn-coloring/src/shared_components/color_mapping/config/default_color_mapping.ts +++ b/packages/kbn-coloring/src/shared_components/color_mapping/config/default_color_mapping.ts @@ -7,11 +7,10 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ +import { KbnPalettes } from '@kbn/palettes'; import { ColorMapping } from '.'; -import { AVAILABLE_PALETTES, getPalette } from '../palettes'; -import { EUIAmsterdamColorBlindPalette } from '../palettes/eui_amsterdam'; -import { NeutralPalette } from '../palettes/neutral'; import { getColor, getGradientColorScale } from '../color/color_handling'; +import { DEFAULT_FALLBACK_PALETTE } from '../../../palettes'; export const DEFAULT_NEUTRAL_PALETTE_INDEX = 1; export const DEFAULT_OTHER_ASSIGNMENT_INDEX = 0; @@ -32,32 +31,31 @@ export const DEFAULT_COLOR_MAPPING_CONFIG: ColorMapping.Config = { touched: false, }, ], - paletteId: EUIAmsterdamColorBlindPalette.id, + paletteId: DEFAULT_FALLBACK_PALETTE, colorMode: { type: 'categorical', }, }; export function getPaletteColors( - isDarkMode: boolean, + palettes: KbnPalettes, colorMappings?: ColorMapping.Config ): string[] { const colorMappingModel = colorMappings ?? { ...DEFAULT_COLOR_MAPPING_CONFIG }; - const palette = getPalette(AVAILABLE_PALETTES, NeutralPalette)(colorMappingModel.paletteId); - return getPaletteColorsFromPaletteId(isDarkMode, palette.id); + const palette = palettes.get(colorMappingModel.paletteId); + return getPaletteColorsFromPaletteId(palettes, palette.id); } export function getPaletteColorsFromPaletteId( - isDarkMode: boolean, + palettes: KbnPalettes, paletteId: ColorMapping.Config['paletteId'] ): string[] { - const palette = getPalette(AVAILABLE_PALETTES, NeutralPalette)(paletteId); - return Array.from({ length: palette.colorCount }, (d, i) => - palette.getColor(i, isDarkMode, true) - ); + const palette = palettes.get(paletteId); + return Array.from({ length: palette.colorCount }, (d, i) => palette.getColor(i)); } export function getColorsFromMapping( + palettes: KbnPalettes, isDarkMode: boolean, colorMappings?: ColorMapping.Config ): string[] { @@ -65,27 +63,18 @@ export function getColorsFromMapping( ...DEFAULT_COLOR_MAPPING_CONFIG, }; - const getPaletteFn = getPalette(AVAILABLE_PALETTES, NeutralPalette); if (colorMode.type === 'gradient') { - const colorScale = getGradientColorScale(colorMode, getPaletteFn, isDarkMode); + const colorScale = getGradientColorScale(colorMode, palettes, isDarkMode); return Array.from({ length: 6 }, (d, i) => colorScale(i / 6)); } else { - const palette = getPaletteFn(paletteId); + const palette = palettes.get(paletteId); const otherColors = specialAssignments[DEFAULT_OTHER_ASSIGNMENT_INDEX].color.type === 'loop' - ? Array.from({ length: palette.colorCount }, (d, i) => - palette.getColor(i, isDarkMode, true) - ) - : [ - getColor( - specialAssignments[DEFAULT_OTHER_ASSIGNMENT_INDEX].color, - getPaletteFn, - isDarkMode - ), - ]; + ? Array.from({ length: palette.colorCount }, (d, i) => palette.getColor(i)) + : [getColor(specialAssignments[DEFAULT_OTHER_ASSIGNMENT_INDEX].color, palettes)]; return [ ...assignments.map((a) => { - return a.color.type === 'gradient' ? '' : getColor(a.color, getPaletteFn, isDarkMode); + return a.color.type === 'gradient' ? '' : getColor(a.color, palettes); }), ...otherColors, ].filter((color) => color !== ''); diff --git a/packages/kbn-coloring/src/shared_components/color_mapping/index.ts b/packages/kbn-coloring/src/shared_components/color_mapping/index.ts index 6337447c1038b..5cba53f0eadcc 100644 --- a/packages/kbn-coloring/src/shared_components/color_mapping/index.ts +++ b/packages/kbn-coloring/src/shared_components/color_mapping/index.ts @@ -15,7 +15,6 @@ export { } from './categorical_color_mapping'; export type { ColorMappingInputData } from './categorical_color_mapping'; export type { ColorMapping } from './config'; -export * from './palettes'; export * from './color/color_handling'; export { SPECIAL_TOKENS_STRING_CONVERSION, getSpecialString } from './color/rule_matching'; export { diff --git a/packages/kbn-coloring/src/shared_components/color_mapping/palettes/elastic_brand.ts b/packages/kbn-coloring/src/shared_components/color_mapping/palettes/elastic_brand.ts deleted file mode 100644 index bd8492823b4db..0000000000000 --- a/packages/kbn-coloring/src/shared_components/color_mapping/palettes/elastic_brand.ts +++ /dev/null @@ -1,31 +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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { ColorMapping } from '../config'; - -export const ELASTIC_BRAND_PALETTE_COLORS = [ - '#20377d', - '#7de2d1', - '#ff957d', - '#f04e98', - '#0077cc', - '#fec514', -]; - -export const ElasticBrandPalette: ColorMapping.CategoricalPalette = { - id: 'elastic_brand_2023', - name: 'Elastic Brand', - colorCount: ELASTIC_BRAND_PALETTE_COLORS.length, - type: 'categorical', - getColor(indexInRange, isDarkMode, loop) { - return ELASTIC_BRAND_PALETTE_COLORS[ - loop ? indexInRange % ELASTIC_BRAND_PALETTE_COLORS.length : indexInRange - ]; - }, -}; diff --git a/packages/kbn-coloring/src/shared_components/color_mapping/palettes/eui_amsterdam.ts b/packages/kbn-coloring/src/shared_components/color_mapping/palettes/eui_amsterdam.ts deleted file mode 100644 index 7a29bc9f343e0..0000000000000 --- a/packages/kbn-coloring/src/shared_components/color_mapping/palettes/eui_amsterdam.ts +++ /dev/null @@ -1,35 +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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { ColorMapping } from '../config'; - -export const EUI_AMSTERDAM_PALETTE_COLORS = [ - '#54b399', - '#6092c0', - '#d36086', - '#9170b8', - '#ca8eae', - '#d6bf57', - '#b9a888', - '#da8b45', - '#aa6556', - '#e7664c', -]; - -export const EUIAmsterdamColorBlindPalette: ColorMapping.CategoricalPalette = { - id: 'eui_amsterdam_color_blind', - name: 'Default', - colorCount: EUI_AMSTERDAM_PALETTE_COLORS.length, - type: 'categorical', - getColor(indexInRange, isDarkMode, loop) { - return EUI_AMSTERDAM_PALETTE_COLORS[ - loop ? indexInRange % EUI_AMSTERDAM_PALETTE_COLORS.length : indexInRange - ]; - }, -}; diff --git a/packages/kbn-coloring/src/shared_components/color_mapping/palettes/index.ts b/packages/kbn-coloring/src/shared_components/color_mapping/palettes/index.ts deleted file mode 100644 index ca3d5b9503885..0000000000000 --- a/packages/kbn-coloring/src/shared_components/color_mapping/palettes/index.ts +++ /dev/null @@ -1,38 +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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { ColorMapping } from '../config'; -import { ElasticBrandPalette } from './elastic_brand'; -import { EUIAmsterdamColorBlindPalette } from './eui_amsterdam'; -import { KibanaV7LegacyPalette } from './kibana_legacy'; -import { NeutralPalette } from './neutral'; - -export const AVAILABLE_PALETTES = new Map([ - [EUIAmsterdamColorBlindPalette.id, EUIAmsterdamColorBlindPalette], - [ElasticBrandPalette.id, ElasticBrandPalette], - [KibanaV7LegacyPalette.id, KibanaV7LegacyPalette], - [NeutralPalette.id, NeutralPalette], -]); - -/** - * This function should be instanciated once at the root of the component with the available palettes and - * a choosed default one and shared across components to keep a single point of truth of the available palettes and the default - * one. - */ -export function getPalette( - palettes: Map, - defaultPalette: ColorMapping.CategoricalPalette -): (paletteId: string) => ColorMapping.CategoricalPalette { - return (paletteId) => palettes.get(paletteId) ?? defaultPalette; -} - -export * from './eui_amsterdam'; -export * from './elastic_brand'; -export * from './kibana_legacy'; -export * from './neutral'; diff --git a/packages/kbn-coloring/src/shared_components/color_mapping/palettes/kibana_legacy.ts b/packages/kbn-coloring/src/shared_components/color_mapping/palettes/kibana_legacy.ts deleted file mode 100644 index c0c25049700fe..0000000000000 --- a/packages/kbn-coloring/src/shared_components/color_mapping/palettes/kibana_legacy.ts +++ /dev/null @@ -1,32 +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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { ColorMapping } from '../config'; - -export const KIBANA_V7_LEGACY_PALETTE_COLORS = [ - '#00a69b', - '#57c17b', - '#6f87d8', - '#663db8', - '#bc52bc', - '#9e3533', - '#daa05d', -]; - -export const KibanaV7LegacyPalette: ColorMapping.CategoricalPalette = { - id: 'kibana_v7_legacy', - name: 'Kibana Legacy', - colorCount: KIBANA_V7_LEGACY_PALETTE_COLORS.length, - type: 'categorical', - getColor(indexInRange, isDarkMode, loop) { - return KIBANA_V7_LEGACY_PALETTE_COLORS[ - loop ? indexInRange % KIBANA_V7_LEGACY_PALETTE_COLORS.length : indexInRange - ]; - }, -}; diff --git a/packages/kbn-coloring/src/shared_components/color_mapping/palettes/neutral.ts b/packages/kbn-coloring/src/shared_components/color_mapping/palettes/neutral.ts deleted file mode 100644 index 5d41ab0fa3c94..0000000000000 --- a/packages/kbn-coloring/src/shared_components/color_mapping/palettes/neutral.ts +++ /dev/null @@ -1,24 +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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { ColorMapping } from '../config'; - -const schemeGreys = ['#f2f4fb', '#d4d9e5', '#98a2b3', '#696f7d', '#353642']; -export const NEUTRAL_COLOR_LIGHT = schemeGreys.slice(); -export const NEUTRAL_COLOR_DARK = schemeGreys.slice().reverse(); - -export const NeutralPalette: ColorMapping.CategoricalPalette = { - id: 'neutral', - name: 'Neutral', - colorCount: NEUTRAL_COLOR_LIGHT.length, - type: 'categorical', - getColor(valueInRange, isDarkMode) { - return isDarkMode ? NEUTRAL_COLOR_DARK[valueInRange] : NEUTRAL_COLOR_LIGHT[valueInRange]; - }, -}; diff --git a/packages/kbn-coloring/src/shared_components/color_mapping/state/selectors.ts b/packages/kbn-coloring/src/shared_components/color_mapping/state/selectors.ts index 05454ead22a61..3f8053aa8e922 100644 --- a/packages/kbn-coloring/src/shared_components/color_mapping/state/selectors.ts +++ b/packages/kbn-coloring/src/shared_components/color_mapping/state/selectors.ts @@ -7,11 +7,11 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -import { getPalette } from '../palettes'; +import { KbnPalettes } from '@kbn/palettes'; import { RootState } from './color_mapping'; -export function selectPalette(getPaletteFn: ReturnType) { - return (state: RootState) => getPaletteFn(state.colorMapping.paletteId); +export function selectPalette(palettes: KbnPalettes) { + return (state: RootState) => palettes.get(state.colorMapping.paletteId); } export function selectColorMode(state: RootState) { return state.colorMapping.colorMode; diff --git a/packages/kbn-palettes/README.md b/packages/kbn-palettes/README.md new file mode 100644 index 0000000000000..d4c3913e33d24 --- /dev/null +++ b/packages/kbn-palettes/README.md @@ -0,0 +1,3 @@ +# @kbn/palettes + +Package containing shared visualization palette definitions diff --git a/packages/kbn-palettes/classes/categorical_palette.ts b/packages/kbn-palettes/classes/categorical_palette.ts new file mode 100644 index 0000000000000..6ffba90a64f3a --- /dev/null +++ b/packages/kbn-palettes/classes/categorical_palette.ts @@ -0,0 +1,32 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { Optional } from 'utility-types'; +import { KbnBasePalette, KbnBasePaletteConfig } from './palette'; +import { IKbnPalette } from './types'; + +export interface KbnCategoricalPaletteConfig extends Optional { + colors: string[]; +} + +export class KbnCategoricalPalette extends KbnBasePalette implements IKbnPalette { + public readonly type = 'categorical' as const; + + #colors: string[]; + + constructor({ colors, colorCount = colors.length, ...rest }: KbnCategoricalPaletteConfig) { + super({ ...rest, colorCount }); + + this.#colors = colors; + } + + public colors = (n?: number) => { + return this.#colors.slice(0, n); + }; +} diff --git a/packages/kbn-palettes/classes/color_fn_palette.ts b/packages/kbn-palettes/classes/color_fn_palette.ts new file mode 100644 index 0000000000000..2174645e1e7e2 --- /dev/null +++ b/packages/kbn-palettes/classes/color_fn_palette.ts @@ -0,0 +1,32 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { Optional } from 'utility-types'; +import { KbnBasePaletteConfig, KbnBasePalette } from './palette'; +import { IKbnPalette } from './types'; + +export interface KbnColorFnPaletteConfig extends Optional { + colorFn: (n: number) => string[]; +} + +export class KbnColorFnPalette extends KbnBasePalette implements IKbnPalette { + public readonly type = 'gradient' as const; + + #colorFn: (n: number) => string[]; + + constructor({ colorFn, colorCount = 10, ...rest }: KbnColorFnPaletteConfig) { + super({ ...rest, colorCount }); + + this.#colorFn = colorFn; + } + + public colors = (n: number = 10) => { + return this.#colorFn(n); + }; +} diff --git a/packages/kbn-palettes/classes/gradient_palette.ts b/packages/kbn-palettes/classes/gradient_palette.ts new file mode 100644 index 0000000000000..f542097a8889b --- /dev/null +++ b/packages/kbn-palettes/classes/gradient_palette.ts @@ -0,0 +1,33 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import chroma, { Scale } from 'chroma-js'; +import { Optional } from 'utility-types'; +import { IKbnPalette } from './types'; +import { KbnBasePalette, KbnBasePaletteConfig } from './palette'; + +export interface KbnGradientPaletteConfig extends Optional { + colors: string[]; +} + +export class KbnGradientPalette extends KbnBasePalette implements IKbnPalette { + public readonly type = 'gradient' as const; + + #scale: Scale; + + constructor({ colors, colorCount = 10, ...rest }: KbnGradientPaletteConfig) { + super({ ...rest, colorCount }); + + this.#scale = chroma.scale(colors).mode('lab'); + } + + public colors = (n?: number) => { + return this.#scale.colors(n, 'hex'); + }; +} diff --git a/packages/kbn-palettes/classes/index.ts b/packages/kbn-palettes/classes/index.ts new file mode 100644 index 0000000000000..6cc89dc1cc1fe --- /dev/null +++ b/packages/kbn-palettes/classes/index.ts @@ -0,0 +1,11 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +export * from './types'; +export { KbnPalettes } from './palettes'; diff --git a/packages/kbn-palettes/classes/palette.ts b/packages/kbn-palettes/classes/palette.ts new file mode 100644 index 0000000000000..8c707b1c3b7da --- /dev/null +++ b/packages/kbn-palettes/classes/palette.ts @@ -0,0 +1,50 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { Optional } from 'utility-types'; +import { IKbnPalette, KbnPaletteType } from './types'; + +export type KbnBasePaletteConfig = Optional< + Pick, + 'legacy' | 'aliases' +>; + +export abstract class KbnBasePalette implements IKbnPalette { + public abstract type: KbnPaletteType; + + public readonly id: string; + public readonly name: string; + public readonly colorCount: number; + public readonly legacy: boolean; + public readonly standalone: boolean; + public readonly aliases: string[]; + + constructor({ + id, + name, + colorCount, + aliases = [], + legacy = false, + standalone = false, + }: KbnBasePaletteConfig) { + this.id = id; + this.name = name; + this.colorCount = colorCount; + this.legacy = legacy; + this.standalone = standalone; + this.aliases = aliases; + } + + public abstract colors: (n?: number | undefined) => string[]; + + public getColor = (colorIndex: number, numberOfColors?: number) => { + const colors = this.colors(numberOfColors); + return colors[colorIndex % colors.length]; // ensure color is always returned + }; +} diff --git a/packages/kbn-palettes/classes/palettes.ts b/packages/kbn-palettes/classes/palettes.ts new file mode 100644 index 0000000000000..8b0ea42dd0724 --- /dev/null +++ b/packages/kbn-palettes/classes/palettes.ts @@ -0,0 +1,44 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { IKbnPalette } from './types'; + +export class KbnPalettes { + #palettes: Map; + #aliasMappings: Map; + #defaultPalette: IKbnPalette; + + constructor(palettes: IKbnPalette[], defaultPalette: IKbnPalette) { + this.#defaultPalette = defaultPalette; + this.#palettes = new Map(palettes.map((p) => [p.id, p])); + this.#aliasMappings = buildAliasMappings(palettes); + } + + query = (id: string) => { + const aliasedId = (this.#palettes.has(id) ? id : this.#aliasMappings.get(id)) ?? id; + return this.#palettes.get(aliasedId); + }; + + get = (id: string) => { + return this.query(id) ?? this.#defaultPalette; + }; + + getAll = () => { + return [...this.#palettes.values()].filter(({ standalone }) => !standalone); + }; +} + +function buildAliasMappings(palettes: IKbnPalette[]): Map { + return palettes.reduce((acc, { id, aliases }) => { + aliases.forEach((alias) => { + acc.set(alias, id); + }); + return acc; + }, new Map()); +} diff --git a/packages/kbn-palettes/classes/types.ts b/packages/kbn-palettes/classes/types.ts new file mode 100644 index 0000000000000..115c50dcfd4f9 --- /dev/null +++ b/packages/kbn-palettes/classes/types.ts @@ -0,0 +1,52 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +export type KbnPaletteType = 'categorical' | 'gradient'; + +/** + * Common palette definition used throughout kibana + */ +export interface IKbnPalette { + /** + * Unique identifier for the palette + */ + id: string; + /** + * Display name of this palette. + */ + name: string; + /** + * Type of pallette + */ + type: KbnPaletteType; + /** + * Number of colors to display + */ + colorCount: number; + /** + * Palette belongs to an outdated theme set + */ + legacy: boolean; + /** + * Alternate aliases/ids this palette matches + */ + aliases: string[]; + /** + * Excluded from `getAll` but can still query for palette with `get`/`query` + */ + standalone?: boolean; + /** + * Returns array of colors, optionally provide desired number of colors (`n`) + */ + colors: (n?: number) => string[]; + /** + * Returns color provided index and optional total number of colors + */ + getColor: (colorIndex: number, numberOfColors?: number) => string; +} diff --git a/packages/kbn-palettes/constants.ts b/packages/kbn-palettes/constants.ts new file mode 100644 index 0000000000000..137b6b22ada4c --- /dev/null +++ b/packages/kbn-palettes/constants.ts @@ -0,0 +1,90 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +export const DEFAULT_FALLBACK_PALETTE = 'default' as const; + +export const EUI_THEME_AMSTERDAM = 'EUI_THEME_AMSTERDAM'; +export const EUI_THEME_BOREALIS = 'EUI_THEME_BOREALIS'; + +const semantic = { + /** + * Log level palette + */ + LogLevel: 'log_level' as const, +}; + +const categorical = { + /** + * Default kibana theme + */ + Default: DEFAULT_FALLBACK_PALETTE, + /** + * Neutral palette + */ + Neutral: 'neutral' as const, + + // ---- Legacy Palettes ---- + /** + * Kibana legacy theme v7 to v9 + */ + Kibana7: 'eui_amsterdam' as const, + /** + * Kibana behind text legacy theme v7 to v9 + */ + Kibana7BehindText: 'behind_text' as const, + /** + * Kibana legacy theme v4 to v7 + */ + Kibana4: 'kibana_v7_legacy' as const, + /** + * Elastic classic color palette + */ + ElasticClassic: 'elastic_brand_2023' as const, +}; + +const gradient = { + Cool: 'cool' as const, + Gray: 'gray' as const, + Red: 'red' as const, + Green: 'green' as const, + Warm: 'warm' as const, + Temperature: 'temperature' as const, + Complementary: 'complementary' as const, + Status: 'status' as const, +}; + +/** + * Enum of all kbn palette ids, including by type + */ +export const KbnPalette = { + /** + * Categorical palettes + */ + _categorical: categorical, + ...categorical, + + /** + * Gradient palettes + */ + _gradient: gradient, + ...gradient, + + /** + * Semantic palettes + */ + _semantic: semantic, + ...semantic, + + // ---- Deprecated palettes ---- + /** + * Amsterdam theme + * @deprecated use `KbnPalette.kibana7` + */ + Amsterdam: 'eui_amsterdam_color_blind' as const, +}; diff --git a/packages/kbn-palettes/hooks/index.ts b/packages/kbn-palettes/hooks/index.ts new file mode 100644 index 0000000000000..b01c38728d15e --- /dev/null +++ b/packages/kbn-palettes/hooks/index.ts @@ -0,0 +1,10 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +export * from './use_kbn_palettes'; diff --git a/packages/kbn-palettes/hooks/use_kbn_palettes.ts b/packages/kbn-palettes/hooks/use_kbn_palettes.ts new file mode 100644 index 0000000000000..3c2e3afca4fdd --- /dev/null +++ b/packages/kbn-palettes/hooks/use_kbn_palettes.ts @@ -0,0 +1,25 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { useEuiTheme } from '@elastic/eui'; +import { getPalettes } from '../palettes'; +import { getLegacyPalettes } from '../palettes/legacy'; + +export function useKbnPalettes() { + const { + euiTheme: { themeName }, + colorMode, + } = useEuiTheme(); + + if (themeName === 'EUI_THEME_BOREALIS') { + return getPalettes(colorMode === 'DARK'); + } + + return getLegacyPalettes(colorMode === 'DARK'); +} diff --git a/packages/kbn-palettes/index.ts b/packages/kbn-palettes/index.ts new file mode 100644 index 0000000000000..361273837f9c9 --- /dev/null +++ b/packages/kbn-palettes/index.ts @@ -0,0 +1,14 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +export * from './palettes'; +export * from './classes'; +export { DEFAULT_FALLBACK_PALETTE, KbnPalette } from './constants'; + +export * from './hooks'; diff --git a/packages/kbn-palettes/jest.config.js b/packages/kbn-palettes/jest.config.js new file mode 100644 index 0000000000000..ba851fd1d70fa --- /dev/null +++ b/packages/kbn-palettes/jest.config.js @@ -0,0 +1,14 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +module.exports = { + preset: '@kbn/test', + rootDir: '../..', + roots: ['/packages/kbn-palettes'], +}; diff --git a/packages/kbn-palettes/kibana.jsonc b/packages/kbn-palettes/kibana.jsonc new file mode 100644 index 0000000000000..ab47c2a3b7231 --- /dev/null +++ b/packages/kbn-palettes/kibana.jsonc @@ -0,0 +1,5 @@ +{ + "type": "shared-common", + "id": "@kbn/palettes", + "owner": "@elastic/visualizations" +} diff --git a/packages/kbn-palettes/package.json b/packages/kbn-palettes/package.json new file mode 100644 index 0000000000000..6400900ccfba1 --- /dev/null +++ b/packages/kbn-palettes/package.json @@ -0,0 +1,6 @@ +{ + "name": "@kbn/palettes", + "private": true, + "version": "1.0.0", + "license": "Elastic License 2.0 OR AGPL-3.0-only OR SSPL-1.0" +} \ No newline at end of file diff --git a/packages/kbn-palettes/palettes/categorical/elastic.ts b/packages/kbn-palettes/palettes/categorical/elastic.ts new file mode 100644 index 0000000000000..e466a08c1423b --- /dev/null +++ b/packages/kbn-palettes/palettes/categorical/elastic.ts @@ -0,0 +1,56 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { i18n } from '@kbn/i18n'; +import { KbnCategoricalPalette } from '../../classes/categorical_palette'; +import { KbnPalette } from '../../constants'; + +export const elasticPalette = new KbnCategoricalPalette({ + id: KbnPalette.Default, + aliases: [ + 'elastic_borealis', // placeholder - not yet used + KbnPalette.Amsterdam, // to assign to existing default palettes + ], + colorCount: 10, + name: i18n.translate('palettes.elastic.name', { + defaultMessage: 'Elastic (default)', + }), + colors: [ + '#00BEB8', + '#93E5E0', + '#599DFF', + '#B4D5FF', + '#ED6BA2', + '#FFBED5', + '#F66D64', + '#FFC0B8', + '#ED9E00', + '#FFD569', + '#00CBC5', + '#C0F1EE', + '#78B0FF', + '#D2E7FF', + '#F588B3', + '#FFD9E7', + '#FC8A80', + '#FFDAD5', + '#F5AF00', + '#FCE8B0', + '#5DD8D2', + '#D9FDFB', + '#96C3FF', + '#E5F1FF', + '#FBA3C4', + '#FFEBF5', + '#FFA59C', + '#FFE9E5', + '#FEC514', + '#FFF1CC', + ], +}); diff --git a/packages/kbn-palettes/palettes/categorical/index.ts b/packages/kbn-palettes/palettes/categorical/index.ts new file mode 100644 index 0000000000000..63638c387f715 --- /dev/null +++ b/packages/kbn-palettes/palettes/categorical/index.ts @@ -0,0 +1,11 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +export * from './neutral'; +export * from './elastic'; diff --git a/packages/kbn-palettes/palettes/categorical/neutral.ts b/packages/kbn-palettes/palettes/categorical/neutral.ts new file mode 100644 index 0000000000000..9b4f3db681569 --- /dev/null +++ b/packages/kbn-palettes/palettes/categorical/neutral.ts @@ -0,0 +1,25 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { i18n } from '@kbn/i18n'; +import { KbnCategoricalPalette } from '../../classes/categorical_palette'; +import { KbnPalette } from '../../constants'; + +const lightColors = ['#F6F9FC', '#D0D4DA', '#989FAA', '#666D78', '#373D45']; +const darkColors = ['#F6F9FC', '#C9D4E6', '#89A0C4', '#546D95', '#283C5C']; + +export const getNeutralPalette = (darkMode: boolean) => + new KbnCategoricalPalette({ + id: KbnPalette.Neutral, + standalone: true, + name: i18n.translate('palettes.elastic.name', { + defaultMessage: 'Neutral', + }), + colors: darkMode ? darkColors : lightColors, + }); diff --git a/packages/kbn-palettes/palettes/get_kbn_palettes.ts b/packages/kbn-palettes/palettes/get_kbn_palettes.ts new file mode 100644 index 0000000000000..295e8f315a022 --- /dev/null +++ b/packages/kbn-palettes/palettes/get_kbn_palettes.ts @@ -0,0 +1,20 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import type { CoreTheme } from '@kbn/core-theme-browser'; +import { getPalettes } from '.'; +import { getLegacyPalettes } from './legacy'; + +export function getKbnPalettes({ name, darkMode }: CoreTheme) { + if (name === 'amsterdam') { + return getLegacyPalettes(darkMode); + } + + return getPalettes(darkMode); +} diff --git a/packages/kbn-palettes/palettes/gradient/complementary.ts b/packages/kbn-palettes/palettes/gradient/complementary.ts new file mode 100644 index 0000000000000..dcce7be4034be --- /dev/null +++ b/packages/kbn-palettes/palettes/gradient/complementary.ts @@ -0,0 +1,21 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { i18n } from '@kbn/i18n'; +import { euiPaletteComplementary } from '@elastic/eui'; +import { KbnColorFnPalette } from '../../classes/color_fn_palette'; +import { KbnPalette } from '../../constants'; + +export const complementaryPalette = new KbnColorFnPalette({ + id: KbnPalette.Complementary, + name: i18n.translate('palettes.complementary.name', { + defaultMessage: 'Complementary', + }), + colorFn: euiPaletteComplementary, +}); diff --git a/packages/kbn-palettes/palettes/gradient/cool.ts b/packages/kbn-palettes/palettes/gradient/cool.ts new file mode 100644 index 0000000000000..fb93d45288ddc --- /dev/null +++ b/packages/kbn-palettes/palettes/gradient/cool.ts @@ -0,0 +1,21 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { i18n } from '@kbn/i18n'; +import { euiPaletteCool } from '@elastic/eui'; +import { KbnColorFnPalette } from '../../classes/color_fn_palette'; +import { KbnPalette } from '../../constants'; + +export const coolPalette = new KbnColorFnPalette({ + id: KbnPalette.Cool, + name: i18n.translate('palettes.cool.name', { + defaultMessage: 'Cool', + }), + colorFn: euiPaletteCool, +}); diff --git a/packages/kbn-palettes/palettes/gradient/gray.ts b/packages/kbn-palettes/palettes/gradient/gray.ts new file mode 100644 index 0000000000000..cfa415fed6809 --- /dev/null +++ b/packages/kbn-palettes/palettes/gradient/gray.ts @@ -0,0 +1,21 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { i18n } from '@kbn/i18n'; +import { euiPaletteGray } from '@elastic/eui'; +import { KbnColorFnPalette } from '../../classes/color_fn_palette'; +import { KbnPalette } from '../../constants'; + +export const grayPalette = new KbnColorFnPalette({ + id: KbnPalette.Gray, + name: i18n.translate('palettes.gray.name', { + defaultMessage: 'Gray', + }), + colorFn: euiPaletteGray, +}); diff --git a/packages/kbn-palettes/palettes/gradient/green.ts b/packages/kbn-palettes/palettes/gradient/green.ts new file mode 100644 index 0000000000000..4ac719ca63796 --- /dev/null +++ b/packages/kbn-palettes/palettes/gradient/green.ts @@ -0,0 +1,21 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { i18n } from '@kbn/i18n'; +import { euiPaletteGreen } from '@elastic/eui'; +import { KbnColorFnPalette } from '../../classes/color_fn_palette'; +import { KbnPalette } from '../../constants'; + +export const greenPalette = new KbnColorFnPalette({ + id: KbnPalette.Green, + name: i18n.translate('palettes.green.name', { + defaultMessage: 'Positive', + }), + colorFn: euiPaletteGreen, +}); diff --git a/packages/kbn-palettes/palettes/gradient/index.ts b/packages/kbn-palettes/palettes/gradient/index.ts new file mode 100644 index 0000000000000..7781fdd5ec7a3 --- /dev/null +++ b/packages/kbn-palettes/palettes/gradient/index.ts @@ -0,0 +1,17 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +export * from './cool'; +export * from './gray'; +export * from './red'; +export * from './green'; +export * from './warm'; +export * from './temperature'; +export * from './complementary'; +export * from './status'; diff --git a/packages/kbn-palettes/palettes/gradient/red.ts b/packages/kbn-palettes/palettes/gradient/red.ts new file mode 100644 index 0000000000000..e51271cc3bc1f --- /dev/null +++ b/packages/kbn-palettes/palettes/gradient/red.ts @@ -0,0 +1,21 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { i18n } from '@kbn/i18n'; +import { euiPaletteRed } from '@elastic/eui'; +import { KbnColorFnPalette } from '../../classes/color_fn_palette'; +import { KbnPalette } from '../../constants'; + +export const redPalette = new KbnColorFnPalette({ + id: KbnPalette.Red, + name: i18n.translate('palettes.red.name', { + defaultMessage: 'Negative', + }), + colorFn: euiPaletteRed, +}); diff --git a/packages/kbn-palettes/palettes/gradient/status.ts b/packages/kbn-palettes/palettes/gradient/status.ts new file mode 100644 index 0000000000000..dbb36a4c4767c --- /dev/null +++ b/packages/kbn-palettes/palettes/gradient/status.ts @@ -0,0 +1,21 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { i18n } from '@kbn/i18n'; +import { euiPaletteForStatus } from '@elastic/eui'; +import { KbnColorFnPalette } from '../../classes/color_fn_palette'; +import { KbnPalette } from '../../constants'; + +export const statusPalette = new KbnColorFnPalette({ + id: KbnPalette.Status, + name: i18n.translate('palettes.status.name', { + defaultMessage: 'Status', + }), + colorFn: euiPaletteForStatus, +}); diff --git a/packages/kbn-palettes/palettes/gradient/temperature.ts b/packages/kbn-palettes/palettes/gradient/temperature.ts new file mode 100644 index 0000000000000..1d11a458a5fa7 --- /dev/null +++ b/packages/kbn-palettes/palettes/gradient/temperature.ts @@ -0,0 +1,21 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { i18n } from '@kbn/i18n'; +import { euiPaletteForTemperature } from '@elastic/eui'; +import { KbnColorFnPalette } from '../../classes/color_fn_palette'; +import { KbnPalette } from '../../constants'; + +export const temperaturePalette = new KbnColorFnPalette({ + id: KbnPalette.Temperature, + name: i18n.translate('palettes.temperature.name', { + defaultMessage: 'Temperature', + }), + colorFn: euiPaletteForTemperature, +}); diff --git a/packages/kbn-palettes/palettes/gradient/warm.ts b/packages/kbn-palettes/palettes/gradient/warm.ts new file mode 100644 index 0000000000000..211207a60d743 --- /dev/null +++ b/packages/kbn-palettes/palettes/gradient/warm.ts @@ -0,0 +1,21 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { i18n } from '@kbn/i18n'; +import { euiPaletteWarm } from '@elastic/eui'; +import { KbnColorFnPalette } from '../../classes/color_fn_palette'; +import { KbnPalette } from '../../constants'; + +export const warmPalette = new KbnColorFnPalette({ + id: KbnPalette.Warm, + name: i18n.translate('palettes.warm.name', { + defaultMessage: 'Warm', + }), + colorFn: euiPaletteWarm, +}); diff --git a/packages/kbn-palettes/palettes/index.ts b/packages/kbn-palettes/palettes/index.ts new file mode 100644 index 0000000000000..6ca0a44b78b7e --- /dev/null +++ b/packages/kbn-palettes/palettes/index.ts @@ -0,0 +1,46 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { KbnPalettes } from '../classes/palettes'; +import { elasticPalette, getNeutralPalette } from './categorical'; +import { elasticClassicPalette, kibana4Palette, kibana7Palette } from './legacy/categorical'; +import { + complementaryPalette, + coolPalette, + grayPalette, + greenPalette, + redPalette, + statusPalette, + temperaturePalette, + warmPalette, +} from './gradient'; +export { logLevelPalette } from './semantic'; + +export const getPalettes = (darkMode: boolean) => + new KbnPalettes( + [ + elasticPalette, + kibana7Palette, + kibana4Palette, + getNeutralPalette(darkMode), + complementaryPalette, + coolPalette, + grayPalette, + greenPalette, + redPalette, + statusPalette, + temperaturePalette, + warmPalette, + elasticClassicPalette, + ], + elasticPalette + ); + +export { elasticPalette } from './categorical'; +export * from './get_kbn_palettes'; diff --git a/packages/kbn-palettes/palettes/legacy/categorical/elastic_classic.ts b/packages/kbn-palettes/palettes/legacy/categorical/elastic_classic.ts new file mode 100644 index 0000000000000..5a4347b8b7cc2 --- /dev/null +++ b/packages/kbn-palettes/palettes/legacy/categorical/elastic_classic.ts @@ -0,0 +1,20 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { i18n } from '@kbn/i18n'; +import { KbnCategoricalPalette } from '../../../classes/categorical_palette'; +import { KbnPalette } from '../../../constants'; + +export const elasticClassicPalette = new KbnCategoricalPalette({ + id: KbnPalette.ElasticClassic, + name: i18n.translate('palettes.classic.name', { + defaultMessage: 'Elastic classic', + }), + colors: ['#20377d', '#7de2d1', '#ff957d', '#f04e98', '#0077cc', '#fec514'], +}); diff --git a/packages/kbn-palettes/palettes/legacy/categorical/index.ts b/packages/kbn-palettes/palettes/legacy/categorical/index.ts new file mode 100644 index 0000000000000..52e244344f20e --- /dev/null +++ b/packages/kbn-palettes/palettes/legacy/categorical/index.ts @@ -0,0 +1,14 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +export * from './kibana_7'; +export * from './kibana_7_behind_text'; +export * from './kibana_4'; +export * from './elastic_classic'; +export * from './neutral'; diff --git a/packages/kbn-palettes/palettes/legacy/categorical/kibana_4.ts b/packages/kbn-palettes/palettes/legacy/categorical/kibana_4.ts new file mode 100644 index 0000000000000..ff8019a8fb02f --- /dev/null +++ b/packages/kbn-palettes/palettes/legacy/categorical/kibana_4.ts @@ -0,0 +1,20 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { i18n } from '@kbn/i18n'; +import { KbnCategoricalPalette } from '../../../classes/categorical_palette'; +import { KbnPalette } from '../../../constants'; + +export const kibana4Palette = new KbnCategoricalPalette({ + id: KbnPalette.Kibana4, + name: i18n.translate('palettes.kibana4.name', { + defaultMessage: 'Kibana 4', + }), + colors: ['#00a69b', '#57c17b', '#6f87d8', '#663db8', '#bc52bc', '#9e3533', '#daa05d'], +}); diff --git a/packages/kbn-palettes/palettes/legacy/categorical/kibana_7.ts b/packages/kbn-palettes/palettes/legacy/categorical/kibana_7.ts new file mode 100644 index 0000000000000..75ec1c7073c6e --- /dev/null +++ b/packages/kbn-palettes/palettes/legacy/categorical/kibana_7.ts @@ -0,0 +1,56 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { i18n } from '@kbn/i18n'; +import { KbnCategoricalPalette } from '../../../classes/categorical_palette'; +import { KbnPalette } from '../../../constants'; + +export const kibana7Palette = new KbnCategoricalPalette({ + id: KbnPalette.Kibana7, + aliases: [ + KbnPalette.Default, // needed when switching between new and old themes + KbnPalette.Amsterdam, // to assign to existing default palettes + ], + name: i18n.translate('palettes.kibana7.name', { + defaultMessage: 'Kibana 7', + }), + colorCount: 10, + colors: [ + '#54b399', + '#6092c0', + '#d36086', + '#9170b8', + '#ca8eae', + '#d6bf57', + '#b9a888', + '#da8b45', + '#aa6556', + '#e7664c', + '#7fc6b3', + '#88aed0', + '#de88a5', + '#ad94ca', + '#d8abc3', + '#e1cf81', + '#cbbea6', + '#e4a874', + '#c08c81', + '#ed8d79', + '#aad9cc', + '#b0c9e0', + '#e9b0c3', + '#c8b8dc', + '#e5c7d7', + '#ebdfab', + '#dcd4c4', + '#edc5a2', + '#d5b2ab', + '#f3b3a6', + ], +}); diff --git a/packages/kbn-palettes/palettes/legacy/categorical/kibana_7_behind_text.ts b/packages/kbn-palettes/palettes/legacy/categorical/kibana_7_behind_text.ts new file mode 100644 index 0000000000000..578afcdff6284 --- /dev/null +++ b/packages/kbn-palettes/palettes/legacy/categorical/kibana_7_behind_text.ts @@ -0,0 +1,53 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { i18n } from '@kbn/i18n'; +import { KbnCategoricalPalette } from '../../../classes/categorical_palette'; +import { KbnPalette } from '../../../constants'; + +export const kibana7BehindText = new KbnCategoricalPalette({ + id: KbnPalette.Kibana7BehindText, + name: i18n.translate('palettes.kibana7BehindText.name', { + defaultMessage: 'Kibana 7 (behind text)', + }), + standalone: true, + colorCount: 10, + colors: [ + '#6dccb1', + '#79aad9', + '#ee789d', + '#a987d1', + '#e4a6c7', + '#f1d86f', + '#d2c0a0', + '#f5a35c', + '#c47c6c', + '#ff7e62', + '#98dfcc', + '#a0c7e9', + '#f8a0bd', + '#c6ace3', + '#f2c4dc', + '#fbe899', + '#e4d7be', + '#ffc08b', + '#daa498', + '#ffa590', + '#c3f3e5', + '#c9e2fa', + '#ffc9dc', + '#e1d1f6', + '#ffe0f1', + '#fff9c4', + '#f6eddd', + '#ffdeba', + '#efcbc4', + '#ffccbe', + ], +}); diff --git a/packages/kbn-palettes/palettes/legacy/categorical/neutral.ts b/packages/kbn-palettes/palettes/legacy/categorical/neutral.ts new file mode 100644 index 0000000000000..99bb21e42f395 --- /dev/null +++ b/packages/kbn-palettes/palettes/legacy/categorical/neutral.ts @@ -0,0 +1,26 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { i18n } from '@kbn/i18n'; +import { KbnCategoricalPalette } from '../../../classes/categorical_palette'; +import { KbnPalette } from '../../../constants'; + +const schemeGreys = ['#f2f4fb', '#d4d9e5', '#98a2b3', '#696f7d', '#353642']; +const NEUTRAL_COLOR_LIGHT = schemeGreys.slice(); +const NEUTRAL_COLOR_DARK = schemeGreys.slice().reverse(); + +export const getNeutralPalette = (darkMode: boolean) => + new KbnCategoricalPalette({ + id: KbnPalette.Neutral, + name: i18n.translate('palettes.elastic.name', { + defaultMessage: 'Neutral', + }), + standalone: true, + colors: darkMode ? NEUTRAL_COLOR_DARK : NEUTRAL_COLOR_LIGHT, + }); diff --git a/packages/kbn-palettes/palettes/legacy/gradient/complementary.ts b/packages/kbn-palettes/palettes/legacy/gradient/complementary.ts new file mode 100644 index 0000000000000..48be782b85466 --- /dev/null +++ b/packages/kbn-palettes/palettes/legacy/gradient/complementary.ts @@ -0,0 +1,21 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { i18n } from '@kbn/i18n'; +import { euiPaletteComplementary } from '@elastic/eui'; +import { KbnColorFnPalette } from '../../../classes/color_fn_palette'; +import { KbnPalette } from '../../../constants'; + +export const complementaryPalette = new KbnColorFnPalette({ + id: KbnPalette.Complementary, + name: i18n.translate('palettes.complementary.name', { + defaultMessage: 'Complementary', + }), + colorFn: euiPaletteComplementary, +}); diff --git a/packages/kbn-palettes/palettes/legacy/gradient/cool.ts b/packages/kbn-palettes/palettes/legacy/gradient/cool.ts new file mode 100644 index 0000000000000..3856f979cf35a --- /dev/null +++ b/packages/kbn-palettes/palettes/legacy/gradient/cool.ts @@ -0,0 +1,21 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { i18n } from '@kbn/i18n'; +import { euiPaletteCool } from '@elastic/eui'; +import { KbnColorFnPalette } from '../../../classes/color_fn_palette'; +import { KbnPalette } from '../../../constants'; + +export const coolPalette = new KbnColorFnPalette({ + id: KbnPalette.Cool, + name: i18n.translate('palettes.cool.name', { + defaultMessage: 'Cool', + }), + colorFn: euiPaletteCool, +}); diff --git a/packages/kbn-palettes/palettes/legacy/gradient/gray.ts b/packages/kbn-palettes/palettes/legacy/gradient/gray.ts new file mode 100644 index 0000000000000..9dc5c2c89aa8e --- /dev/null +++ b/packages/kbn-palettes/palettes/legacy/gradient/gray.ts @@ -0,0 +1,21 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { i18n } from '@kbn/i18n'; +import { euiPaletteGray } from '@elastic/eui'; +import { KbnColorFnPalette } from '../../../classes/color_fn_palette'; +import { KbnPalette } from '../../../constants'; + +export const grayPalette = new KbnColorFnPalette({ + id: KbnPalette.Gray, + name: i18n.translate('palettes.gray.name', { + defaultMessage: 'Gray', + }), + colorFn: euiPaletteGray, +}); diff --git a/packages/kbn-palettes/palettes/legacy/gradient/green.ts b/packages/kbn-palettes/palettes/legacy/gradient/green.ts new file mode 100644 index 0000000000000..91b280ae6af6f --- /dev/null +++ b/packages/kbn-palettes/palettes/legacy/gradient/green.ts @@ -0,0 +1,21 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { i18n } from '@kbn/i18n'; +import { euiPaletteGreen } from '@elastic/eui'; +import { KbnColorFnPalette } from '../../../classes/color_fn_palette'; +import { KbnPalette } from '../../../constants'; + +export const greenPalette = new KbnColorFnPalette({ + id: KbnPalette.Green, + name: i18n.translate('palettes.green.name', { + defaultMessage: 'Positive', + }), + colorFn: euiPaletteGreen, +}); diff --git a/packages/kbn-palettes/palettes/legacy/gradient/index.ts b/packages/kbn-palettes/palettes/legacy/gradient/index.ts new file mode 100644 index 0000000000000..7781fdd5ec7a3 --- /dev/null +++ b/packages/kbn-palettes/palettes/legacy/gradient/index.ts @@ -0,0 +1,17 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +export * from './cool'; +export * from './gray'; +export * from './red'; +export * from './green'; +export * from './warm'; +export * from './temperature'; +export * from './complementary'; +export * from './status'; diff --git a/packages/kbn-palettes/palettes/legacy/gradient/red.ts b/packages/kbn-palettes/palettes/legacy/gradient/red.ts new file mode 100644 index 0000000000000..60053f935b67b --- /dev/null +++ b/packages/kbn-palettes/palettes/legacy/gradient/red.ts @@ -0,0 +1,21 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { i18n } from '@kbn/i18n'; +import { euiPaletteRed } from '@elastic/eui'; +import { KbnColorFnPalette } from '../../../classes/color_fn_palette'; +import { KbnPalette } from '../../../constants'; + +export const redPalette = new KbnColorFnPalette({ + id: KbnPalette.Red, + name: i18n.translate('palettes.red.name', { + defaultMessage: 'Negative', + }), + colorFn: euiPaletteRed, +}); diff --git a/packages/kbn-palettes/palettes/legacy/gradient/status.ts b/packages/kbn-palettes/palettes/legacy/gradient/status.ts new file mode 100644 index 0000000000000..42e9d25be7db3 --- /dev/null +++ b/packages/kbn-palettes/palettes/legacy/gradient/status.ts @@ -0,0 +1,21 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { i18n } from '@kbn/i18n'; +import { euiPaletteForStatus } from '@elastic/eui'; +import { KbnColorFnPalette } from '../../../classes/color_fn_palette'; +import { KbnPalette } from '../../../constants'; + +export const statusPalette = new KbnColorFnPalette({ + id: KbnPalette.Status, + name: i18n.translate('palettes.status.name', { + defaultMessage: 'Status', + }), + colorFn: euiPaletteForStatus, +}); diff --git a/packages/kbn-palettes/palettes/legacy/gradient/temperature.ts b/packages/kbn-palettes/palettes/legacy/gradient/temperature.ts new file mode 100644 index 0000000000000..a02ff1c2baf26 --- /dev/null +++ b/packages/kbn-palettes/palettes/legacy/gradient/temperature.ts @@ -0,0 +1,21 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { i18n } from '@kbn/i18n'; +import { euiPaletteForTemperature } from '@elastic/eui'; +import { KbnColorFnPalette } from '../../../classes/color_fn_palette'; +import { KbnPalette } from '../../../constants'; + +export const temperaturePalette = new KbnColorFnPalette({ + id: KbnPalette.Temperature, + name: i18n.translate('palettes.temperature.name', { + defaultMessage: 'Temperature', + }), + colorFn: euiPaletteForTemperature, +}); diff --git a/packages/kbn-palettes/palettes/legacy/gradient/warm.ts b/packages/kbn-palettes/palettes/legacy/gradient/warm.ts new file mode 100644 index 0000000000000..5b78e6ad8aa66 --- /dev/null +++ b/packages/kbn-palettes/palettes/legacy/gradient/warm.ts @@ -0,0 +1,21 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { i18n } from '@kbn/i18n'; +import { euiPaletteWarm } from '@elastic/eui'; +import { KbnColorFnPalette } from '../../../classes/color_fn_palette'; +import { KbnPalette } from '../../../constants'; + +export const warmPalette = new KbnColorFnPalette({ + id: KbnPalette.Warm, + name: i18n.translate('palettes.warm.name', { + defaultMessage: 'Warm', + }), + colorFn: euiPaletteWarm, +}); diff --git a/packages/kbn-palettes/palettes/legacy/index.ts b/packages/kbn-palettes/palettes/legacy/index.ts new file mode 100644 index 0000000000000..0872bea5b27ed --- /dev/null +++ b/packages/kbn-palettes/palettes/legacy/index.ts @@ -0,0 +1,48 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { KbnPalettes } from '../../classes/palettes'; + +import { + kibana7Palette, + kibana4Palette, + elasticClassicPalette, + getNeutralPalette, + kibana7BehindText, +} from './categorical'; +import { + complementaryPalette, + coolPalette, + grayPalette, + greenPalette, + redPalette, + statusPalette, + temperaturePalette, + warmPalette, +} from './gradient'; + +export const getLegacyPalettes = (darkMode: boolean) => + new KbnPalettes( + [ + kibana7Palette, + kibana4Palette, + kibana7BehindText, + getNeutralPalette(darkMode), + complementaryPalette, + coolPalette, + grayPalette, + greenPalette, + redPalette, + statusPalette, + temperaturePalette, + warmPalette, + elasticClassicPalette, + ], + kibana7Palette + ); diff --git a/packages/kbn-palettes/palettes/semantic/index.ts b/packages/kbn-palettes/palettes/semantic/index.ts new file mode 100644 index 0000000000000..cfc7c779dacf4 --- /dev/null +++ b/packages/kbn-palettes/palettes/semantic/index.ts @@ -0,0 +1,10 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +export * from './log_level'; diff --git a/packages/kbn-palettes/palettes/semantic/log_level.ts b/packages/kbn-palettes/palettes/semantic/log_level.ts new file mode 100644 index 0000000000000..cbcbbdaee3def --- /dev/null +++ b/packages/kbn-palettes/palettes/semantic/log_level.ts @@ -0,0 +1,40 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { i18n } from '@kbn/i18n'; +import { $Keys } from 'utility-types'; +import { KbnPalette } from '../../constants'; + +// TODO: update colors to vis colors +const logLevelColors = { + Emerg: '#F66D64', + Alert: '#E78E76', + Crit: '#E7A584', + Error: '#E7BD91', + Warn: '#E8D297', + Notice: '#C7D59', + Info: '#9CB1D3', + Debug: '#718FBC', + Other: '#CED4DE', +}; +type LogLevelKeys = $Keys; + +/** + * Defines a palette to be used directly and does not fully implement IKbnPalette + */ +export const logLevelPalette = { + id: KbnPalette.LogLevel, + name: i18n.translate('palettes.logLevel.name', { + defaultMessage: 'Log Level', + }), + getColor: (key: LogLevelKeys) => { + return logLevelColors[key]; + }, + colors: logLevelColors, +}; diff --git a/packages/kbn-palettes/tsconfig.json b/packages/kbn-palettes/tsconfig.json new file mode 100644 index 0000000000000..dad708677fd87 --- /dev/null +++ b/packages/kbn-palettes/tsconfig.json @@ -0,0 +1,19 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "target/types", + "types": [ + "jest", + "node", + "react" + ] + }, + "include": [ + "**/*.ts", + "**/*.tsx", + ], + "exclude": [ + "target/**/*" + ], + "kbn_references": [] +} diff --git a/packages/kbn-palettes/types.ts b/packages/kbn-palettes/types.ts new file mode 100644 index 0000000000000..35c8ab6efa60b --- /dev/null +++ b/packages/kbn-palettes/types.ts @@ -0,0 +1,10 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +export type ThemeMode = 'LIGHT' | 'DARK' | 'DARKBLUE'; diff --git a/packages/kbn-visualization-ui-components/components/color_picker.tsx b/packages/kbn-visualization-ui-components/components/color_picker.tsx index 589066726300e..e3ca47e63e65f 100644 --- a/packages/kbn-visualization-ui-components/components/color_picker.tsx +++ b/packages/kbn-visualization-ui-components/components/color_picker.tsx @@ -10,14 +10,7 @@ import React, { useEffect, useRef, useState } from 'react'; import { i18n } from '@kbn/i18n'; import { TooltipWrapper } from '@kbn/visualization-utils'; -import { - EuiFormRow, - EuiColorPicker, - EuiColorPickerProps, - EuiToolTip, - EuiIcon, - euiPaletteColorBlind, -} from '@elastic/eui'; +import { EuiFormRow, EuiColorPicker, EuiColorPickerProps, EuiToolTip, EuiIcon } from '@elastic/eui'; import { getColorAlpha, makeColorWithAlpha } from '@kbn/coloring'; const tooltipContent = { @@ -38,6 +31,7 @@ export interface ColorPickerProps { disableHelpTooltip?: boolean; disabledMessage?: string; showAlpha?: boolean; + swatches: string[]; } export const ColorPicker = ({ @@ -49,6 +43,7 @@ export const ColorPicker = ({ disableHelpTooltip, disabledMessage, showAlpha, + swatches, }: ColorPickerProps) => { const [colorText, setColorText] = useState(overwriteColor || defaultColor); const [validatedColor, setValidatedColor] = useState(overwriteColor || defaultColor); @@ -112,8 +107,8 @@ export const ColorPicker = ({ showAlpha={showAlpha} swatches={ currentColorAlpha === 1 - ? euiPaletteColorBlind() - : euiPaletteColorBlind().map((c) => makeColorWithAlpha(c, currentColorAlpha).hex()) + ? swatches + : swatches.map((c) => makeColorWithAlpha(c, currentColorAlpha).hex()) } /> ); diff --git a/packages/react/kibana_context/common/tsconfig.json b/packages/react/kibana_context/common/tsconfig.json index 0d78dace105e1..16ee1eff00ab6 100644 --- a/packages/react/kibana_context/common/tsconfig.json +++ b/packages/react/kibana_context/common/tsconfig.json @@ -13,5 +13,7 @@ "exclude": [ "target/**/*" ], - "kbn_references": [] + "kbn_references": [ + "@kbn/core-ui-settings-common", + ] } diff --git a/src/plugins/chart_expressions/expression_metric/common/expression_functions/metric_vis_function.ts b/src/plugins/chart_expressions/expression_metric/common/expression_functions/metric_vis_function.ts index 5e4bd45c03f5d..0a00a0cbf73d0 100644 --- a/src/plugins/chart_expressions/expression_metric/common/expression_functions/metric_vis_function.ts +++ b/src/plugins/chart_expressions/expression_metric/common/expression_functions/metric_vis_function.ts @@ -212,7 +212,7 @@ export const metricVisFunction = (): MetricVisExpressionFunctionDefinition => ({ secondaryPrefix: args.secondaryPrefix, color: args.color, icon: args.icon, - palette: args.palette?.params, + palette: args.palette, progressDirection: args.progressDirection, titlesTextAlign: args.titlesTextAlign, valuesTextAlign: args.valuesTextAlign, diff --git a/src/plugins/chart_expressions/expression_metric/common/types/expression_renderers.ts b/src/plugins/chart_expressions/expression_metric/common/types/expression_renderers.ts index 2eae93f88c020..f07a8297540ed 100644 --- a/src/plugins/chart_expressions/expression_metric/common/types/expression_renderers.ts +++ b/src/plugins/chart_expressions/expression_metric/common/types/expression_renderers.ts @@ -10,6 +10,7 @@ import { ExpressionValueVisDimension } from '@kbn/visualizations-plugin/common'; import { CustomPaletteState } from '@kbn/charts-plugin/common'; import { LayoutDirection, MetricStyle } from '@elastic/charts'; +import { PaletteOutput } from '@kbn/coloring'; import { TrendlineResult } from './expression_functions'; export const visType = 'metric'; @@ -26,7 +27,7 @@ export interface MetricVisParam { secondaryPrefix?: string; color?: string; icon?: string; - palette?: CustomPaletteState; + palette?: PaletteOutput; progressDirection?: LayoutDirection; titlesTextAlign: MetricStyle['titlesTextAlign']; valuesTextAlign: MetricStyle['valuesTextAlign']; diff --git a/src/plugins/chart_expressions/expression_metric/public/components/metric_vis.tsx b/src/plugins/chart_expressions/expression_metric/public/components/metric_vis.tsx index edfee4f6df539..929456fc3a725 100644 --- a/src/plugins/chart_expressions/expression_metric/public/components/metric_vis.tsx +++ b/src/plugins/chart_expressions/expression_metric/public/components/metric_vis.tsx @@ -36,7 +36,7 @@ import { FieldFormatConvertFunction, SerializedFieldFormat, } from '@kbn/field-formats-plugin/common'; -import { CUSTOM_PALETTE } from '@kbn/coloring'; +import { CUSTOM_PALETTE, PaletteOutput } from '@kbn/coloring'; import { css } from '@emotion/react'; import { euiThemeVars } from '@kbn/ui-theme'; import { useResizeObserver, useEuiScrollBar, EuiIcon } from '@elastic/eui'; @@ -100,14 +100,14 @@ const getMetricFormatter = ( const getColor = ( value: number, - paletteParams: CustomPaletteState, + palette: PaletteOutput, accessors: { metric: string; max?: string; breakdownBy?: string }, data: Datatable, rowNumber: number ) => { const { min, max } = getDataBoundsForPalette(accessors, data, rowNumber); - return getPaletteService().get(CUSTOM_PALETTE)?.getColorForValue?.(value, paletteParams, { + return getPaletteService().get(CUSTOM_PALETTE)?.getColorForValue?.(value, palette.params, { min, max, }); @@ -236,7 +236,7 @@ export const MetricVis = ({ icon: config.metric?.icon ? getIcon(config.metric?.icon) : undefined, extra: renderSecondaryMetric(data.columns, row, config), color: - config.metric.palette && value != null + config.metric.palette?.params && value != null ? getColor( value, config.metric.palette, diff --git a/src/plugins/chart_expressions/expression_partition_vis/public/components/partition_vis_component.tsx b/src/plugins/chart_expressions/expression_partition_vis/public/components/partition_vis_component.tsx index 816a10509b425..549742b7e3401 100644 --- a/src/plugins/chart_expressions/expression_partition_vis/public/components/partition_vis_component.tsx +++ b/src/plugins/chart_expressions/expression_partition_vis/public/components/partition_vis_component.tsx @@ -41,6 +41,7 @@ import { } from '@kbn/expressions-plugin/public'; import type { FieldFormat } from '@kbn/field-formats-plugin/common'; import { getOverridesFor } from '@kbn/chart-expressions-common'; +import { useKbnPalettes } from '@kbn/palettes'; import { useAppFixedViewport } from '@kbn/core-rendering-browser'; import { consolidateMetricColumns } from '../../common/utils'; import { DEFAULT_PERCENT_DECIMALS } from '../../common/constants'; @@ -117,6 +118,7 @@ const PartitionVisComponent = (props: PartitionVisComponentProps) => { } = props; const visParams = useMemo(() => filterOutConfig(visType, preVisParams), [preVisParams, visType]); const chartBaseTheme = props.chartsThemeService.useChartsBaseTheme(); + const palettes = useKbnPalettes(); const { table: visData, @@ -312,6 +314,7 @@ const PartitionVisComponent = (props: PartitionVisComponentProps) => { { ...props.uiState?.get('vis.colors', {}), ...props.visParams.labels.colorOverrides }, visData.rows, props.palettesRegistry, + palettes, formatters, services.fieldFormats, syncColors, @@ -325,6 +328,7 @@ const PartitionVisComponent = (props: PartitionVisComponentProps) => { props.uiState, props.visParams.labels.colorOverrides, props.palettesRegistry, + palettes, formatters, services.fieldFormats, syncColors, diff --git a/src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_color.ts b/src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_color.ts index b6de7fc728ede..6bd8d188f78c5 100644 --- a/src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_color.ts +++ b/src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_color.ts @@ -75,7 +75,7 @@ const getDistinctColor = ( isSplitChart: boolean, overwriteColors: { [key: string]: string } = {}, visParams: PartitionVisParams, - palettes: PaletteRegistry | null, + paletteService: PaletteRegistry | null, syncColors: boolean, { parentSeries, allSeries }: DistinctSeries, formattedCategoricalKey: string @@ -93,7 +93,7 @@ const getDistinctColor = ( const index = allSeries.findIndex((d) => isEqual(d, categoricalKey)); const isSplitParentLayer = isSplitChart && parentSeries.includes(categoricalKey); - return palettes?.get(visParams.palette.name).getCategoricalColor( + return paletteService?.get(visParams.palette.name).getCategoricalColor( [ { name: categoricalKey, @@ -207,7 +207,7 @@ export const getColor = ( distinctSeries: DistinctSeries, { columnsLength, rowsLength }: { columnsLength: number; rowsLength: number }, visParams: PartitionVisParams, - palettes: PaletteRegistry | null, + paletteService: PaletteRegistry | null, byDataPalette: ReturnType | undefined, syncColors: boolean, isDarkMode: boolean, @@ -230,7 +230,7 @@ export const getColor = ( isSplitChart, overwriteColors, visParams, - palettes, + paletteService, syncColors, distinctSeries, name @@ -271,7 +271,7 @@ export const getColor = ( } } - const outputColor = palettes?.get(visParams.palette.name).getCategoricalColor( + const outputColor = paletteService?.get(visParams.palette.name).getCategoricalColor( seriesLayers, { behindText: visParams.labels.show || isTreemapOrMosaicChart(chartType), diff --git a/src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_layers.ts b/src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_layers.ts index c83353d4d8396..2fac3b2b25758 100644 --- a/src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_layers.ts +++ b/src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_layers.ts @@ -8,19 +8,14 @@ */ import { Datum, PartitionLayer } from '@elastic/charts'; -import { - PaletteRegistry, - getColorFactory, - getPalette, - AVAILABLE_PALETTES, - NeutralPalette, -} from '@kbn/coloring'; +import { PaletteRegistry, getColorFactory } from '@kbn/coloring'; import { i18n } from '@kbn/i18n'; import { FieldFormat } from '@kbn/field-formats-plugin/common'; import type { FieldFormatsStart } from '@kbn/field-formats-plugin/public'; import type { Datatable, DatatableRow } from '@kbn/expressions-plugin/public'; import { getColorCategories } from '@kbn/chart-expressions-common'; +import { KbnPalettes } from '@kbn/palettes'; import { getDistinctSeries } from '..'; import { BucketColumns, ChartTypes, PartitionVisParams } from '../../../common/types'; import { sortPredicateByType, sortPredicateSaveSourceOrder } from './sort_predicate'; @@ -41,7 +36,8 @@ export const getLayers = ( visData: Datatable, overwriteColors: { [key: string]: string } = {}, rows: DatatableRow[], - palettes: PaletteRegistry | null, + paletteService: PaletteRegistry | null, + palettes: KbnPalettes, formatters: Record, formatter: FieldFormatsStart, syncColors: boolean, @@ -59,11 +55,11 @@ export const getLayers = ( const isSplitChart = Boolean(visParams.dimensions.splitColumn || visParams.dimensions.splitRow); let byDataPalette: ReturnType; - if (!syncColors && columns[1]?.id && palettes && visParams.palette) { + if (!syncColors && columns[1]?.id && paletteService && visParams.palette) { byDataPalette = byDataColorPaletteMap( rows, columns[1], - palettes?.get(visParams.palette.name), + paletteService?.get(visParams.palette.name), visParams.palette, formatters, formatter @@ -79,6 +75,7 @@ export const getLayers = ( chartType, columns, rows, + palettes, isDarkMode, visParams ); @@ -110,7 +107,7 @@ export const getLayers = ( distinctSeries, { columnsLength: columns.length, rowsLength: rows.length }, visParams, - palettes, + paletteService, byDataPalette, syncColors, isDarkMode, @@ -131,6 +128,7 @@ function getColorFromMappingFactory( chartType: ChartTypes, columns: Array>, rows: DatatableRow[], + palettes: KbnPalettes, isDarkMode: boolean, visParams: PartitionVisParams ): undefined | ((category: string | string[]) => string) { @@ -157,13 +155,8 @@ function getColorFromMappingFactory( chartType === ChartTypes.MOSAIC && columns.length === 2 ? getColorCategories(rows, columns[1]?.id) : getColorCategories(rows, columns[0]?.id); - return getColorFactory( - JSON.parse(colorMapping), - getPalette(AVAILABLE_PALETTES, NeutralPalette), - isDarkMode, - { - type: 'categories', - categories, - } - ); + return getColorFactory(JSON.parse(colorMapping), palettes, isDarkMode, { + type: 'categories', + categories, + }); } diff --git a/src/plugins/chart_expressions/expression_tagcloud/public/components/tagcloud_component.tsx b/src/plugins/chart_expressions/expression_tagcloud/public/components/tagcloud_component.tsx index 12a7991a68adf..46064ebd6b6e2 100644 --- a/src/plugins/chart_expressions/expression_tagcloud/public/components/tagcloud_component.tsx +++ b/src/plugins/chart_expressions/expression_tagcloud/public/components/tagcloud_component.tsx @@ -23,19 +23,13 @@ import { WordCloudElementEvent, } from '@elastic/charts'; import { EmptyPlaceholder } from '@kbn/charts-plugin/public'; -import { - PaletteRegistry, - PaletteOutput, - getColorFactory, - getPalette, - AVAILABLE_PALETTES, - NeutralPalette, -} from '@kbn/coloring'; +import { PaletteRegistry, PaletteOutput, getColorFactory } from '@kbn/coloring'; import { IInterpreterRenderHandlers, DatatableRow } from '@kbn/expressions-plugin/public'; import { getColorCategories, getOverridesFor } from '@kbn/chart-expressions-common'; import type { AllowedSettingsOverrides, AllowedChartOverrides } from '@kbn/charts-plugin/common'; import { getColumnByAccessor, getFormatByAccessor } from '@kbn/visualizations-plugin/common/utils'; import { isMultiFieldKey } from '@kbn/data-plugin/common'; +import { KbnPalettes, useKbnPalettes } from '@kbn/palettes'; import { getFormatService } from '../format_service'; import { TagcloudRendererConfig } from '../../common/types'; import { ScaleOptions, Orientation } from '../../common/constants'; @@ -56,13 +50,13 @@ const calculateWeight = (value: number, x1: number, y1: number, x2: number, y2: ((value - x1) * (y2 - x2)) / (y1 - x1) + x2; const getColor = ( - palettes: PaletteRegistry, + paletteService: PaletteRegistry, activePalette: PaletteOutput, text: string, values: string[], syncColors: boolean ) => { - return palettes?.get(activePalette?.name)?.getCategoricalColor( + return paletteService?.get(activePalette?.name)?.getCategoricalColor( [ { name: text, @@ -106,6 +100,7 @@ export const TagCloudChart = ({ isDarkMode, }: TagCloudChartProps) => { const [warning, setWarning] = useState(false); + const palettes = useKbnPalettes(); const { bucket, metric, scale, palette, showLabel, orientation, colorMapping } = visParams; const bucketFormatter = useMemo(() => { @@ -128,6 +123,7 @@ export const TagCloudChart = ({ const colorFromMappingFn = getColorFromMappingFactory( tagColumn, visData.rows, + palettes, isDarkMode, colorMapping ); @@ -149,15 +145,16 @@ export const TagCloudChart = ({ }); }, [ bucket, - bucketFormatter, - metric, - palette, - palettesRegistry, - syncColors, visData.columns, visData.rows, - colorMapping, + metric, + palettes, isDarkMode, + colorMapping, + bucketFormatter, + palettesRegistry, + palette, + syncColors, ]); useEffect(() => { @@ -320,6 +317,7 @@ export { TagCloudChart as default }; function getColorFromMappingFactory( tagColumn: string | undefined, rows: DatatableRow[], + palettes: KbnPalettes, isDarkMode: boolean, colorMapping?: string ): undefined | ((category: string | string[]) => string) { @@ -327,13 +325,8 @@ function getColorFromMappingFactory( // return undefined, we will use the legacy color mapping instead return undefined; } - return getColorFactory( - JSON.parse(colorMapping), - getPalette(AVAILABLE_PALETTES, NeutralPalette), - isDarkMode, - { - type: 'categories', - categories: getColorCategories(rows, tagColumn), - } - ); + return getColorFactory(JSON.parse(colorMapping), palettes, isDarkMode, { + type: 'categories', + categories: getColorCategories(rows, tagColumn), + }); } diff --git a/src/plugins/chart_expressions/expression_xy/public/components/data_layers.tsx b/src/plugins/chart_expressions/expression_xy/public/components/data_layers.tsx index 3335f29029904..df51a0869ecea 100644 --- a/src/plugins/chart_expressions/expression_xy/public/components/data_layers.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/components/data_layers.tsx @@ -20,6 +20,7 @@ import { PaletteRegistry } from '@kbn/coloring'; import { FormatFactory } from '@kbn/field-formats-plugin/common'; import { getAccessorByDimension } from '@kbn/visualizations-plugin/common/utils'; import { PersistedState } from '@kbn/visualizations-plugin/public'; +import { KbnPalettes } from '@kbn/palettes'; import { CommonXYDataLayerConfig, EndValue, @@ -49,6 +50,7 @@ interface Props { fittingFunction?: FittingFunction; endValue?: EndValue | undefined; paletteService: PaletteRegistry; + palettes: KbnPalettes; formattedDatatables: DatatablesWithFormatInfo; syncColors: boolean; timeZone: string; @@ -75,6 +77,7 @@ export const DataLayers: FC = ({ minBarHeight, formatFactory, paletteService, + palettes, fittingFunction, emphasizeFitting, yAxesConfiguration, @@ -163,6 +166,7 @@ export const DataLayers: FC = ({ formatFactory, columnToLabelMap, paletteService, + palettes, formattedDatatableInfo, syncColors, yAxis, diff --git a/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx b/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx index 349af46eb101a..3ebc9efcd6c0a 100644 --- a/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx @@ -38,6 +38,7 @@ import { IconType } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { PaletteRegistry } from '@kbn/coloring'; import { RenderMode } from '@kbn/expressions-plugin/common'; +import { useKbnPalettes } from '@kbn/palettes'; import { ESQL_TABLE_TYPE } from '@kbn/data-plugin/common'; import type { DataPublicPluginStart } from '@kbn/data-plugin/public'; import { EmptyPlaceholder, LegendToggle } from '@kbn/charts-plugin/public'; @@ -233,6 +234,7 @@ export function XYChart({ const chartRef = useRef(null); const chartBaseTheme = chartsThemeService.useChartsBaseTheme(); const darkMode = chartsThemeService.useDarkMode(); + const palettes = useKbnPalettes(); const appFixedViewport = useAppFixedViewport(); const filteredLayers = getFilteredLayers(layers); const layersById = filteredLayers.reduce>( @@ -989,6 +991,7 @@ export function XYChart({ minBarHeight={args.minBarHeight} formatFactory={formatFactory} paletteService={paletteService} + palettes={palettes} fittingFunction={fittingFunction} emphasizeFitting={emphasizeFitting} yAxesConfiguration={yAxesConfiguration} diff --git a/src/plugins/chart_expressions/expression_xy/public/expression_renderers/index.ts b/src/plugins/chart_expressions/expression_xy/public/expression_renderers/index.ts index 650b8fba2a6d9..71b8bb35ac222 100644 --- a/src/plugins/chart_expressions/expression_xy/public/expression_renderers/index.ts +++ b/src/plugins/chart_expressions/expression_xy/public/expression_renderers/index.ts @@ -8,4 +8,4 @@ */ export { getXyChartRenderer } from './xy_chart_renderer'; -export type { GetStartDepsFn } from './xy_chart_renderer'; +export type { GetStartDeps } from './xy_chart_renderer'; diff --git a/src/plugins/chart_expressions/expression_xy/public/expression_renderers/xy_chart_renderer.tsx b/src/plugins/chart_expressions/expression_xy/public/expression_renderers/xy_chart_renderer.tsx index 57387a46388af..cb7a75fcdf691 100644 --- a/src/plugins/chart_expressions/expression_xy/public/expression_renderers/xy_chart_renderer.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/expression_renderers/xy_chart_renderer.tsx @@ -32,6 +32,7 @@ import { extractVisualizationType, } from '@kbn/chart-expressions-common'; +import { ThemeServiceSetup } from '@kbn/core/public'; import type { getDataLayers } from '../helpers'; import { LayerTypes, SeriesTypes } from '../../common/constants'; import type { CommonXYDataLayerConfig, XYChartProps } from '../../common'; @@ -43,10 +44,11 @@ import type { StartServices, } from '../types'; -export type GetStartDepsFn = () => Promise<{ +export interface GetStartDeps { data: DataPublicPluginStart; formatFactory: FormatFactory; theme: ChartsPluginStart['theme']; + kibanaTheme: ThemeServiceSetup; activeCursor: ChartsPluginStart['activeCursor']; paletteService: PaletteRegistry; timeZone: string; @@ -55,10 +57,10 @@ export type GetStartDepsFn = () => Promise<{ usageCollection?: UsageCollectionStart; timeFormat: string; startServices: StartServices; -}>; +} interface XyChartRendererDeps { - getStartDeps: GetStartDepsFn; + getStartDeps: () => Promise; } export const extractCounterEvents = ( diff --git a/src/plugins/chart_expressions/expression_xy/public/helpers/color/color_mapping_accessor.ts b/src/plugins/chart_expressions/expression_xy/public/helpers/color/color_mapping_accessor.ts index 6923a9a2f5409..93b498f5b57e1 100644 --- a/src/plugins/chart_expressions/expression_xy/public/helpers/color/color_mapping_accessor.ts +++ b/src/plugins/chart_expressions/expression_xy/public/helpers/color/color_mapping_accessor.ts @@ -10,13 +10,14 @@ import { SeriesColorAccessorFn } from '@elastic/charts'; import { getColorFactory, type ColorMapping, type ColorMappingInputData } from '@kbn/coloring'; import { MULTI_FIELD_KEY_SEPARATOR } from '@kbn/data-plugin/common'; +import { KbnPalettes } from '@kbn/palettes'; /** * Return a color accessor function for XY charts depending on the split accessors received. */ export function getColorSeriesAccessorFn( config: ColorMapping.Config, - getPaletteFn: (paletteId: string) => ColorMapping.CategoricalPalette, + palettes: KbnPalettes, isDarkMode: boolean, mappingData: ColorMappingInputData, fieldId: string, @@ -28,7 +29,7 @@ export function getColorSeriesAccessorFn( [...specialTokens.entries()].map((d) => [d[1], d[0]]) ); - const getColor = getColorFactory(config, getPaletteFn, isDarkMode, mappingData); + const getColor = getColorFactory(config, palettes, isDarkMode, mappingData); return ({ splitAccessors }) => { const splitValue = splitAccessors.get(fieldId); diff --git a/src/plugins/chart_expressions/expression_xy/public/helpers/data_layers.tsx b/src/plugins/chart_expressions/expression_xy/public/helpers/data_layers.tsx index 942909880f301..11cd6b05fc16b 100644 --- a/src/plugins/chart_expressions/expression_xy/public/helpers/data_layers.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/helpers/data_layers.tsx @@ -25,13 +25,9 @@ import { Datatable } from '@kbn/expressions-plugin/common'; import { getAccessorByDimension } from '@kbn/visualizations-plugin/common/utils'; import type { ExpressionValueVisDimension } from '@kbn/visualizations-plugin/common/expression_functions'; import { PaletteRegistry, SeriesLayer } from '@kbn/coloring'; -import { - getPalette, - AVAILABLE_PALETTES, - NeutralPalette, - SPECIAL_TOKENS_STRING_CONVERSION, -} from '@kbn/coloring'; +import { SPECIAL_TOKENS_STRING_CONVERSION } from '@kbn/coloring'; import { getColorCategories } from '@kbn/chart-expressions-common'; +import { KbnPalettes } from '@kbn/palettes'; import { isDataLayer } from '../../common/utils/layer_types_guards'; import { CommonXYDataLayerConfig, CommonXYLayerConfig, XScaleType } from '../../common'; import { AxisModes, SeriesTypes } from '../../common/constants'; @@ -54,6 +50,7 @@ type GetSeriesPropsFn = (config: { colorAssignments: ColorAssignments; columnToLabelMap: Record; paletteService: PaletteRegistry; + palettes: KbnPalettes; yAxis?: GroupsConfiguration[number]; xAxis?: GroupsConfiguration[number]; syncColors: boolean; @@ -392,6 +389,7 @@ export const getSeriesProps: GetSeriesPropsFn = ({ formatFactory, columnToLabelMap, paletteService, + palettes, syncColors, yAxis, xAxis, @@ -490,7 +488,7 @@ export const getSeriesProps: GetSeriesPropsFn = ({ layer.colorMapping && splitColumnIds.length > 0 ? getColorSeriesAccessorFn( JSON.parse(layer.colorMapping), // the color mapping is at this point just a stringified JSON - getPalette(AVAILABLE_PALETTES, NeutralPalette), + palettes, isDarkMode, { type: 'categories', diff --git a/src/plugins/chart_expressions/expression_xy/public/plugin.ts b/src/plugins/chart_expressions/expression_xy/public/plugin.ts index 04ba0ac2b3bc2..8415e2bc7d04c 100755 --- a/src/plugins/chart_expressions/expression_xy/public/plugin.ts +++ b/src/plugins/chart_expressions/expression_xy/public/plugin.ts @@ -31,7 +31,7 @@ import { extendedAnnotationLayerFunction, referenceLineDecorationConfigFunction, } from '../common/expression_functions'; -import { GetStartDepsFn, getXyChartRenderer } from './expression_renderers'; +import { GetStartDeps, getXyChartRenderer } from './expression_renderers'; import { eventAnnotationsResult } from '../common/expression_functions/event_annotations_result'; export interface XYPluginStartDependencies { @@ -71,7 +71,7 @@ export class ExpressionXyPlugin { expressions.registerFunction(xyVisFunction); expressions.registerFunction(layeredXyVisFunction); - const getStartDeps: GetStartDepsFn = async () => { + const getStartDeps = async () => { const [coreStart, deps] = await core.getStartServices(); const { data, @@ -100,7 +100,7 @@ export class ExpressionXyPlugin { timeZone: getTimeZone(core.uiSettings), timeFormat: core.uiSettings.get('dateFormat'), startServices: coreStart, - }; + } satisfies GetStartDeps; }; expressions.registerRenderer(getXyChartRenderer({ getStartDeps })); diff --git a/src/plugins/charts/public/plugin.ts b/src/plugins/charts/public/plugin.ts index f376a1664a514..6c4928baac85f 100644 --- a/src/plugins/charts/public/plugin.ts +++ b/src/plugins/charts/public/plugin.ts @@ -45,8 +45,8 @@ export class ChartsPlugin implements Plugin { - const colors = euiPaletteColorBlind({ rotations: 2 }); - const behindTextColors = euiPaletteColorBlindBehindText({ rotations: 2 }); +function buildRoundRobinCategoricalWithMappedColors( + id: string, + colors: string[], + behindTextColors?: string[] +): Omit { const behindTextColorMap: Record = Object.fromEntries( zip(colors, behindTextColors) ); @@ -49,9 +41,10 @@ function buildRoundRobinCategoricalWithMappedColors(): Omit euiPaletteColorBlind(), + getCategoricalColors: (size: number) => colors.slice(0, size), toExpression: () => ({ type: 'expression', chain: [ @@ -79,17 +72,14 @@ function buildRoundRobinCategoricalWithMappedColors(): Omit string[] -): Omit { +function buildGradient(id: string, palette: IKbnPalette): PaletteDefinition { function getColor( series: SeriesLayer[], chartConfiguration: ChartColorConfiguration = { behindText: false } ) { const totalSeriesAtDepth = series[0].totalSeriesAtDepth; const rankAtDepth = series[0].rankAtDepth; - const actualColors = colors(totalSeriesAtDepth); + const actualColors = palette.colors(totalSeriesAtDepth); const outputColor = actualColors[rankAtDepth]; if (!chartConfiguration.maxDepth || chartConfiguration.maxDepth === 1) { @@ -100,8 +90,9 @@ function buildGradient( } return { id, + title: palette.name, getCategoricalColor: getColor, - getCategoricalColors: colors, + getCategoricalColors: palette.colors, canDynamicColoring: true, toExpression: () => ({ type: 'expression', @@ -157,7 +148,7 @@ function buildSyncedKibanaPalette( }; } -function buildCustomPalette(): PaletteDefinition { +function buildCustomPalette(): PaletteDefinition { return { id: 'custom', getColorForValue: ( @@ -258,54 +249,35 @@ function buildCustomPalette(): PaletteDefinition { } as PaletteDefinition; } -export const buildPalettes: ( - legacyColorsService: LegacyColorsService -) => Record = (legacyColorsService) => { +export const buildPalettes = ( + legacyColorsService: LegacyColorsService, + theme: CoreTheme +): Record => { + const kbnPalettes = getKbnPalettes(theme); + const defaultPalette = kbnPalettes.get(KbnPalette.Default); return { default: { - title: i18n.translate('charts.palettes.defaultPaletteLabel', { defaultMessage: 'Default' }), - ...buildRoundRobinCategoricalWithMappedColors(), - }, - status: { - title: i18n.translate('charts.palettes.statusLabel', { defaultMessage: 'Status' }), - ...buildGradient('status', euiPaletteForStatus), - }, - temperature: { - title: i18n.translate('charts.palettes.temperatureLabel', { defaultMessage: 'Temperature' }), - ...buildGradient('temperature', euiPaletteForTemperature), - }, - complementary: { - title: i18n.translate('charts.palettes.complementaryLabel', { - defaultMessage: 'Complementary', - }), - ...buildGradient('complementary', euiPaletteComplementary), - }, - negative: { - title: i18n.translate('charts.palettes.negativeLabel', { defaultMessage: 'Negative' }), - ...buildGradient('negative', euiPaletteRed), - }, - positive: { - title: i18n.translate('charts.palettes.positiveLabel', { defaultMessage: 'Positive' }), - ...buildGradient('positive', euiPaletteGreen), - }, - cool: { - title: i18n.translate('charts.palettes.coolLabel', { defaultMessage: 'Cool' }), - ...buildGradient('cool', euiPaletteCool), - }, - warm: { - title: i18n.translate('charts.palettes.warmLabel', { defaultMessage: 'Warm' }), - ...buildGradient('warm', euiPaletteWarm), - }, - gray: { - title: i18n.translate('charts.palettes.grayLabel', { defaultMessage: 'Gray' }), - ...buildGradient('gray', euiPaletteGray), + title: defaultPalette.name, + ...buildRoundRobinCategoricalWithMappedColors( + 'default', // needs to match key of palette definition + defaultPalette.colors(), + kbnPalettes.query(KbnPalette.Kibana7BehindText)?.colors() + ), }, + status: buildGradient('status', kbnPalettes.get('status')), + temperature: buildGradient('temperature', kbnPalettes.get('temperature')), + complementary: buildGradient('complementary', kbnPalettes.get('complementary')), + negative: buildGradient('negative', kbnPalettes.get('red')), + positive: buildGradient('positive', kbnPalettes.get('green')), + cool: buildGradient('cool', kbnPalettes.get('cool')), + warm: buildGradient('warm', kbnPalettes.get('warm')), + gray: buildGradient('gray', kbnPalettes.get('gray')), kibana_palette: { title: i18n.translate('charts.palettes.kibanaPaletteLabel', { defaultMessage: 'Compatibility', }), ...buildSyncedKibanaPalette(legacyColorsService), }, - custom: buildCustomPalette() as PaletteDefinition, + custom: buildCustomPalette(), }; }; diff --git a/src/plugins/charts/public/services/palettes/service.ts b/src/plugins/charts/public/services/palettes/service.ts index 920486c9dcbb5..a8f798cff5408 100644 --- a/src/plugins/charts/public/services/palettes/service.ts +++ b/src/plugins/charts/public/services/palettes/service.ts @@ -10,6 +10,7 @@ import type { PaletteRegistry, PaletteDefinition } from '@kbn/coloring'; import { getActivePaletteName } from '@kbn/coloring'; import type { ExpressionsSetup } from '@kbn/expressions-plugin/public'; +import { CoreTheme } from '@kbn/core/public'; import type { ChartsPluginSetup } from '../..'; import type { LegacyColorsService } from '../legacy_colors'; @@ -22,12 +23,12 @@ export class PaletteService { private palettes: Record> | undefined = undefined; constructor() {} - public setup(colorsService: LegacyColorsService) { + public setup(colorsService: LegacyColorsService, theme: CoreTheme) { return { getPalettes: async (): Promise => { if (!this.palettes) { const { buildPalettes } = await import('./palettes'); - this.palettes = buildPalettes(colorsService); + this.palettes = buildPalettes(colorsService, theme); } return { get: (name: string) => { diff --git a/src/plugins/home/server/services/sample_data/data_sets/ecommerce/saved_objects.ts b/src/plugins/home/server/services/sample_data/data_sets/ecommerce/saved_objects.ts index 491664ef3fda7..6c53f7479789e 100644 --- a/src/plugins/home/server/services/sample_data/data_sets/ecommerce/saved_objects.ts +++ b/src/plugins/home/server/services/sample_data/data_sets/ecommerce/saved_objects.ts @@ -148,7 +148,7 @@ export const getSavedObjects = (): SavedObject[] => [ optionsJSON: '{"useMargins":true,"syncColors":false,"syncCursor":true,"syncTooltips":false,"hidePanelTitles":false}', panelsJSON: - '[{"version":"8.11.0","type":"lens","gridData":{"x":0,"y":21,"w":24,"h":10,"i":"5"},"panelIndex":"5","embeddableConfig":{"attributes":{"title":"[eCommerce] Promotion Tracking (converted)","visualizationType":"lnsXY","type":"lens","references":[{"type":"index-pattern","id":"ff959d40-b880-11e8-a6d9-e546fe2bba5f","name":"indexpattern-datasource-layer-e3b3cb5c-e3b1-497f-a5d5-fddb0dabc94e"},{"type":"index-pattern","id":"ff959d40-b880-11e8-a6d9-e546fe2bba5f","name":"indexpattern-datasource-layer-1d08a43c-8913-4692-a3e0-8d77902f6e46"},{"type":"index-pattern","id":"ff959d40-b880-11e8-a6d9-e546fe2bba5f","name":"indexpattern-datasource-layer-9725cdbd-a9f3-479f-a349-0f11244e5239"},{"type":"index-pattern","id":"ff959d40-b880-11e8-a6d9-e546fe2bba5f","name":"indexpattern-datasource-layer-2031d0f8-01fc-4009-b1ad-a7b7ca9266c0"},{"type":"index-pattern","id":"ff959d40-b880-11e8-a6d9-e546fe2bba5f","name":"xy-visualization-layer-192ad2e4-2bb7-44a9-b345-e96045fa6ccd"}],"state":{"visualization":{"legend":{"isVisible":true,"showSingleSeries":true,"position":"bottom","shouldTruncate":true,"maxLines":1},"valueLabels":"hide","fittingFunction":"None","fillOpacity":0,"yLeftExtent":{"mode":"full"},"yRightExtent":{"mode":"full"},"yLeftScale":"linear","yRightScale":"linear","axisTitlesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"tickLabelsVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"labelsOrientation":{"x":0,"yLeft":0,"yRight":0},"gridlinesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"preferredSeriesType":"bar_stacked","layers":[{"seriesType":"line","layerType":"data","layerId":"e3b3cb5c-e3b1-497f-a5d5-fddb0dabc94e","accessors":["a69956c9-43cd-4756-a3c0-e93cb1502a0b"],"yConfig":[{"forAccessor":"a69956c9-43cd-4756-a3c0-e93cb1502a0b","color":"rgba(211,96,134,1)","axisMode":"left"}],"xAccessor":"f3cc8168-6360-4727-a410-a57f5a325091","palette":{"name":"default","type":"palette"}},{"seriesType":"line","layerType":"data","layerId":"1d08a43c-8913-4692-a3e0-8d77902f6e46","accessors":["9a3d8abd-81a5-40ae-9616-020d5a5b2ee2"],"yConfig":[{"forAccessor":"9a3d8abd-81a5-40ae-9616-020d5a5b2ee2","color":"rgba(84,179,153,1)","axisMode":"left"}],"xAccessor":"644b06ea-73a3-47b1-9b40-3035844c4621","palette":{"name":"default","type":"palette"}},{"seriesType":"line","layerType":"data","layerId":"9725cdbd-a9f3-479f-a349-0f11244e5239","accessors":["b5588228-9c46-4a4b-92ee-d140c327bca0"],"yConfig":[{"forAccessor":"b5588228-9c46-4a4b-92ee-d140c327bca0","color":"rgba(96,146,192,1)","axisMode":"left"}],"xAccessor":"6749b404-4784-4fd6-8bf6-5712e84c7310","palette":{"name":"default","type":"palette"}},{"seriesType":"line","layerType":"data","layerId":"2031d0f8-01fc-4009-b1ad-a7b7ca9266c0","accessors":["985e05c0-3a0b-4e55-84bb-1f02128388a9"],"yConfig":[{"forAccessor":"985e05c0-3a0b-4e55-84bb-1f02128388a9","color":"rgba(202,142,174,1)","axisMode":"left"}],"xAccessor":"1b199cb1-b47f-48e6-b209-74eb81b303f5","palette":{"name":"default","type":"palette"}},{"layerId":"192ad2e4-2bb7-44a9-b345-e96045fa6ccd","layerType":"annotations","ignoreGlobalFilters":true,"annotations":[{"type":"query","id":"c8c30be0-b88f-11e8-a451-f37365e9f268","label":"Event","key":{"type":"point_in_time"},"color":"#194D33","timeField":"order_date","icon":"bell","filter":{"type":"kibana_query","query":"taxful_total_price:>250","language":"lucene"},"extraFields":["taxful_total_price"]}]}]},"query":{"query":"","language":"kuery"},"filters":[],"datasourceStates":{"formBased":{"layers":{"e3b3cb5c-e3b1-497f-a5d5-fddb0dabc94e":{"columns":{"f3cc8168-6360-4727-a410-a57f5a325091":{"label":"order_date","dataType":"date","operationType":"date_histogram","sourceField":"order_date","isBucketed":true,"scale":"interval","params":{"interval":"12h","includeEmptyRows":true,"dropPartials":false}},"a69956c9-43cd-4756-a3c0-e93cb1502a0b":{"label":"Revenue Trousers","dataType":"number","operationType":"sum","sourceField":"taxful_total_price","isBucketed":false,"scale":"ratio","filter":{"query":"products.product_name:*trouser*","language":"lucene"},"params":{"format":{"id":"number"},"emptyAsNull":true},"customLabel":true}},"columnOrder":["f3cc8168-6360-4727-a410-a57f5a325091","a69956c9-43cd-4756-a3c0-e93cb1502a0b"],"incompleteColumns":{}},"1d08a43c-8913-4692-a3e0-8d77902f6e46":{"columns":{"644b06ea-73a3-47b1-9b40-3035844c4621":{"label":"order_date","dataType":"date","operationType":"date_histogram","sourceField":"order_date","isBucketed":true,"scale":"interval","params":{"interval":"12h","includeEmptyRows":true,"dropPartials":false}},"9a3d8abd-81a5-40ae-9616-020d5a5b2ee2":{"label":"Revenue Watches","dataType":"number","operationType":"sum","sourceField":"taxful_total_price","isBucketed":false,"scale":"ratio","filter":{"query":"products.product_name:*watch*","language":"lucene"},"params":{"format":{"id":"number"},"emptyAsNull":true},"customLabel":true}},"columnOrder":["644b06ea-73a3-47b1-9b40-3035844c4621","9a3d8abd-81a5-40ae-9616-020d5a5b2ee2"],"incompleteColumns":{}},"9725cdbd-a9f3-479f-a349-0f11244e5239":{"columns":{"6749b404-4784-4fd6-8bf6-5712e84c7310":{"label":"order_date","dataType":"date","operationType":"date_histogram","sourceField":"order_date","isBucketed":true,"scale":"interval","params":{"interval":"12h","includeEmptyRows":true,"dropPartials":false}},"b5588228-9c46-4a4b-92ee-d140c327bca0":{"label":"Revenue Bags","dataType":"number","operationType":"sum","sourceField":"taxful_total_price","isBucketed":false,"scale":"ratio","filter":{"query":"products.product_name:*bag*","language":"lucene"},"params":{"format":{"id":"number"},"emptyAsNull":true},"customLabel":true}},"columnOrder":["6749b404-4784-4fd6-8bf6-5712e84c7310","b5588228-9c46-4a4b-92ee-d140c327bca0"],"incompleteColumns":{}},"2031d0f8-01fc-4009-b1ad-a7b7ca9266c0":{"columns":{"1b199cb1-b47f-48e6-b209-74eb81b303f5":{"label":"order_date","dataType":"date","operationType":"date_histogram","sourceField":"order_date","isBucketed":true,"scale":"interval","params":{"interval":"12h","includeEmptyRows":true,"dropPartials":false}},"985e05c0-3a0b-4e55-84bb-1f02128388a9":{"label":"Revenue Cocktail Dresses","dataType":"number","operationType":"sum","sourceField":"taxful_total_price","isBucketed":false,"scale":"ratio","filter":{"query":"products.product_name:*cocktail dress*","language":"lucene"},"params":{"format":{"id":"number"},"emptyAsNull":true},"customLabel":true}},"columnOrder":["1b199cb1-b47f-48e6-b209-74eb81b303f5","985e05c0-3a0b-4e55-84bb-1f02128388a9"],"incompleteColumns":{}}}},"textBased":{"layers":{}}},"internalReferences":[],"adHocDataViews":{}}},"hidePanelTitles":false,"enhancements":{}},"title":"[eCommerce] Promotion Tracking"},{"version":"8.11.0","type":"lens","gridData":{"x":36,"y":7,"w":12,"h":7,"i":"7"},"panelIndex":"7","embeddableConfig":{"attributes":{"title":"Sold Products per Day","description":"","visualizationType":"lnsMetric","type":"lens","references":[{"type":"index-pattern","id":"ff959d40-b880-11e8-a6d9-e546fe2bba5f","name":"indexpattern-datasource-layer-037375ae-9e23-4dd5-a4f0-5f117bb7dac1"}],"state":{"visualization":{"layerId":"037375ae-9e23-4dd5-a4f0-5f117bb7dac1","layerType":"data","metricAccessor":"c27bd77c-68e2-4d75-8fda-41c45d22f8d4","maxAccessor":"ce816876-e92d-4b1a-bbb0-ed7637fc0eea","showBar":true,"color":"#68BC00"},"query":{"query":"","language":"kuery"},"filters":[],"datasourceStates":{"formBased":{"layers":{"037375ae-9e23-4dd5-a4f0-5f117bb7dac1":{"ignoreGlobalFilters":false,"columns":{"c27bd77c-68e2-4d75-8fda-41c45d22f8d4X0":{"label":"Part of count() / (time_range() / 1000 / 60 / 60 / 24)","dataType":"number","operationType":"count","isBucketed":false,"scale":"ratio","sourceField":"___records___","params":{"emptyAsNull":false},"customLabel":true},"c27bd77c-68e2-4d75-8fda-41c45d22f8d4X1":{"label":"Part of count() / (time_range() / 1000 / 60 / 60 / 24)","dataType":"number","operationType":"time_range","isBucketed":false,"scale":"ratio","references":[],"customLabel":true},"c27bd77c-68e2-4d75-8fda-41c45d22f8d4X2":{"label":"Part of count() / (time_range() / 1000 / 60 / 60 / 24)","dataType":"number","operationType":"math","isBucketed":false,"scale":"ratio","params":{"tinymathAst":{"type":"function","name":"divide","args":["c27bd77c-68e2-4d75-8fda-41c45d22f8d4X0",{"type":"function","name":"divide","args":[{"type":"function","name":"divide","args":[{"type":"function","name":"divide","args":[{"type":"function","name":"divide","args":["c27bd77c-68e2-4d75-8fda-41c45d22f8d4X1",1000]},60]},60]},24],"location":{"min":11,"max":45},"text":"time_range() / 1000 / 60 / 60 / 24"}],"location":{"min":0,"max":46},"text":"count() / (time_range() / 1000 / 60 / 60 / 24)"}},"references":["c27bd77c-68e2-4d75-8fda-41c45d22f8d4X0","c27bd77c-68e2-4d75-8fda-41c45d22f8d4X1"],"customLabel":true},"c27bd77c-68e2-4d75-8fda-41c45d22f8d4":{"label":"Trxns / day","dataType":"number","operationType":"formula","isBucketed":false,"scale":"ratio","params":{"format":{"id":"number"},"formula":"count() / (time_range() / 1000 / 60 / 60 / 24)","isFormulaBroken":false},"references":["c27bd77c-68e2-4d75-8fda-41c45d22f8d4X2"],"customLabel":true},"ce816876-e92d-4b1a-bbb0-ed7637fc0eea":{"label":"Static value: 300","dataType":"number","operationType":"static_value","isStaticValue":true,"isBucketed":false,"scale":"ratio","params":{"value":"300"},"references":[]}},"columnOrder":["c27bd77c-68e2-4d75-8fda-41c45d22f8d4X0","c27bd77c-68e2-4d75-8fda-41c45d22f8d4X1","c27bd77c-68e2-4d75-8fda-41c45d22f8d4X2","c27bd77c-68e2-4d75-8fda-41c45d22f8d4","ce816876-e92d-4b1a-bbb0-ed7637fc0eea"],"incompleteColumns":{}}}},"indexpattern":{"layers":{}},"textBased":{"layers":{}}},"internalReferences":[],"adHocDataViews":{}}},"timeRange":{"from":"now-7d","to":"now"},"enhancements":{}}},{"version":"8.11.0","type":"search","gridData":{"x":0,"y":54,"w":48,"h":18,"i":"10"},"panelIndex":"10","embeddableConfig":{"enhancements":{}},"panelRefName":"panel_10"},{"version":"8.11.0","type":"map","gridData":{"x":0,"y":31,"w":24,"h":14,"i":"11"},"panelIndex":"11","embeddableConfig":{"isLayerTOCOpen":false,"hiddenLayers":[],"mapCenter":{"lat":45.88578,"lon":-15.07605,"zoom":2.11},"openTOCDetails":[],"enhancements":{}},"panelRefName":"panel_11"},{"version":"8.11.0","type":"visualization","gridData":{"x":0,"y":0,"w":24,"h":7,"i":"a71cf076-6895-491c-8878-63592e429ed5"},"panelIndex":"a71cf076-6895-491c-8878-63592e429ed5","embeddableConfig":{"enhancements":{}},"panelRefName":"panel_a71cf076-6895-491c-8878-63592e429ed5"},{"version":"8.11.0","type":"lens","gridData":{"x":24,"y":0,"w":12,"h":7,"i":"75283285-dffd-48a7-a0c2-2235184b5282"},"panelIndex":"75283285-dffd-48a7-a0c2-2235184b5282","embeddableConfig":{"enhancements":{},"attributes":{"visualizationType":"lnsMetric","state":{"visualization":{"layerId":"c7478794-6767-4286-9d65-1c0ecd909dd8","layerType":"data","metricAccessor":"041db33b-5c9c-47f3-a5d3-ef5e255d1663"},"query":{"language":"kuery","query":""},"filters":[],"datasourceStates":{"formBased":{"layers":{"c7478794-6767-4286-9d65-1c0ecd909dd8":{"columnOrder":["041db33b-5c9c-47f3-a5d3-ef5e255d1663"],"columns":{"041db33b-5c9c-47f3-a5d3-ef5e255d1663":{"customLabel":true,"dataType":"number","isBucketed":false,"label":"Sum of revenue","operationType":"sum","scale":"ratio","sourceField":"taxful_total_price","params":{}}},"incompleteColumns":{}}}}},"internalReferences":[],"adHocDataViews":{}},"references":[{"type":"index-pattern","id":"ff959d40-b880-11e8-a6d9-e546fe2bba5f","name":"indexpattern-datasource-layer-c7478794-6767-4286-9d65-1c0ecd909dd8"}]},"hidePanelTitles":true},"title":"Sum of revenue"},{"version":"8.11.0","type":"lens","gridData":{"x":36,"y":0,"w":12,"h":7,"i":"58774330-b1b3-42dd-a04c-fbce9cc4d288"},"panelIndex":"58774330-b1b3-42dd-a04c-fbce9cc4d288","embeddableConfig":{"enhancements":{},"attributes":{"title":"Median spending","visualizationType":"lnsMetric","type":"lens","references":[{"type":"index-pattern","id":"ff959d40-b880-11e8-a6d9-e546fe2bba5f","name":"indexpattern-datasource-layer-4fb42a8e-b133-43c8-805c-a38472053938"}],"state":{"visualization":{"layerId":"4fb42a8e-b133-43c8-805c-a38472053938","layerType":"data","metricAccessor":"020bbfdf-9ef8-4802-aa9e-342d2ea0bebf"},"query":{"language":"kuery","query":""},"filters":[],"datasourceStates":{"formBased":{"layers":{"4fb42a8e-b133-43c8-805c-a38472053938":{"columnOrder":["020bbfdf-9ef8-4802-aa9e-342d2ea0bebf"],"columns":{"020bbfdf-9ef8-4802-aa9e-342d2ea0bebf":{"customLabel":true,"dataType":"number","isBucketed":false,"label":"Median spending","operationType":"median","scale":"ratio","sourceField":"taxful_total_price","params":{}}},"incompleteColumns":{}}}}},"internalReferences":[],"adHocDataViews":{}}},"hidePanelTitles":true},"title":"Median spending"},{"version":"8.11.0","type":"lens","gridData":{"x":24,"y":7,"w":12,"h":7,"i":"b63ec47d-aace-4980-b928-6be8adafa5a4"},"panelIndex":"b63ec47d-aace-4980-b928-6be8adafa5a4","embeddableConfig":{"enhancements":{},"attributes":{"visualizationType":"lnsMetric","state":{"visualization":{"layerId":"667067a2-7cdf-4f0e-a9fe-eb4f4f1f2f17","layerType":"data","metricAccessor":"c52c2003-ae58-4604-bae7-52ba0fb38a01"},"query":{"language":"kuery","query":""},"filters":[],"datasourceStates":{"formBased":{"layers":{"667067a2-7cdf-4f0e-a9fe-eb4f4f1f2f17":{"columnOrder":["c52c2003-ae58-4604-bae7-52ba0fb38a01"],"columns":{"c52c2003-ae58-4604-bae7-52ba0fb38a01":{"customLabel":true,"dataType":"number","isBucketed":false,"label":"Avg. items sold","operationType":"average","params":{"format":{"id":"number","params":{"decimals":1,"compact":true}}},"scale":"ratio","sourceField":"total_quantity"}},"incompleteColumns":{}}}}},"internalReferences":[],"adHocDataViews":{}},"references":[{"type":"index-pattern","id":"ff959d40-b880-11e8-a6d9-e546fe2bba5f","name":"indexpattern-datasource-layer-667067a2-7cdf-4f0e-a9fe-eb4f4f1f2f17"}]},"hidePanelTitles":true},"title":"Avg. items sold"},{"version":"8.11.0","type":"lens","gridData":{"x":0,"y":14,"w":24,"h":7,"i":"d9495793-80ba-4a9a-b0e3-d1155ec99b09"},"panelIndex":"d9495793-80ba-4a9a-b0e3-d1155ec99b09","embeddableConfig":{"enhancements":{},"attributes":{"state":{"datasourceStates":{"formBased":{"layers":{"b6093a53-884f-42c2-9fcc-ba56cfb66c53":{"columnOrder":["15c45f89-a149-443a-a830-aa8c3a9317db","2b41b3d8-2f62-407a-a866-960f254c679d","eadae280-2da3-4d1d-a0e1-f9733f89c15b","ddc92e50-4d5c-413e-b91b-3e504889fa65","5e31e5d3-2aaa-4475-a130-3b69bf2f748a"],"columns":{"15c45f89-a149-443a-a830-aa8c3a9317db":{"dataType":"date","isBucketed":true,"label":"order_date","operationType":"date_histogram","params":{"interval":"1d","includeEmptyRows":true},"scale":"interval","sourceField":"order_date"},"2b41b3d8-2f62-407a-a866-960f254c679d":{"customLabel":true,"dataType":"number","isBucketed":false,"label":"Total items","operationType":"sum","scale":"ratio","sourceField":"products.quantity"},"5e31e5d3-2aaa-4475-a130-3b69bf2f748a":{"customLabel":true,"dataType":"number","isBucketed":false,"label":"Tx. last week","operationType":"count","scale":"ratio","sourceField":"___records___","timeShift":"1w"},"ddc92e50-4d5c-413e-b91b-3e504889fa65":{"customLabel":true,"dataType":"number","isBucketed":false,"label":"Transactions","operationType":"count","scale":"ratio","sourceField":"___records___"},"eadae280-2da3-4d1d-a0e1-f9733f89c15b":{"customLabel":true,"dataType":"number","isBucketed":false,"label":"Last week","operationType":"sum","scale":"ratio","sourceField":"products.quantity","timeShift":"1w"}},"incompleteColumns":{}}}}},"filters":[],"query":{"language":"kuery","query":""},"visualization":{"axisTitlesVisibilitySettings":{"x":false,"yLeft":false,"yRight":true},"curveType":"LINEAR","fittingFunction":"None","gridlinesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"layers":[{"accessors":["2b41b3d8-2f62-407a-a866-960f254c679d","eadae280-2da3-4d1d-a0e1-f9733f89c15b","5e31e5d3-2aaa-4475-a130-3b69bf2f748a","ddc92e50-4d5c-413e-b91b-3e504889fa65"],"layerId":"b6093a53-884f-42c2-9fcc-ba56cfb66c53","position":"top","seriesType":"line","showGridlines":false,"xAccessor":"15c45f89-a149-443a-a830-aa8c3a9317db","yConfig":[{"color":"#b6e0d5","forAccessor":"eadae280-2da3-4d1d-a0e1-f9733f89c15b"},{"color":"#edafc4","forAccessor":"5e31e5d3-2aaa-4475-a130-3b69bf2f748a"}],"layerType":"data"}],"legend":{"isVisible":true,"position":"right","legendSize":"auto"},"preferredSeriesType":"line","tickLabelsVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"valueLabels":"hide","yLeftExtent":{"mode":"full"},"yRightExtent":{"mode":"full"}}},"visualizationType":"lnsXY","references":[{"id":"ff959d40-b880-11e8-a6d9-e546fe2bba5f","name":"indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"ff959d40-b880-11e8-a6d9-e546fe2bba5f","name":"indexpattern-datasource-layer-b6093a53-884f-42c2-9fcc-ba56cfb66c53","type":"index-pattern"}]}},"title":"Transactions per day"},{"version":"8.11.0","type":"lens","gridData":{"x":24,"y":31,"w":24,"h":14,"i":"bda054f7-2d06-4936-b461-365d1be621fa"},"panelIndex":"bda054f7-2d06-4936-b461-365d1be621fa","embeddableConfig":{"enhancements":{},"attributes":{"state":{"datasourceStates":{"formBased":{"layers":{"0731ee8b-31c5-4be9-92d9-69ee760465d7":{"columnOrder":["7bf8f089-1542-40bd-b349-45fdfc309ac6","826b2f39-b616-40b2-a222-972fdc1d7596","cfd45c47-fc41-430c-9e7a-b71dc0c916b0","bf51c1af-443e-49f4-a21f-54c87bfc5677","bf51c1af-443e-49f4-a21f-54c87bfc5677X0","bf51c1af-443e-49f4-a21f-54c87bfc5677X1","bf51c1af-443e-49f4-a21f-54c87bfc5677X2"],"columns":{"7bf8f089-1542-40bd-b349-45fdfc309ac6":{"dataType":"date","isBucketed":true,"label":"order_date","operationType":"date_histogram","params":{"interval":"1d","includeEmptyRows":true},"scale":"interval","sourceField":"order_date"},"826b2f39-b616-40b2-a222-972fdc1d7596":{"customLabel":true,"dataType":"number","isBucketed":false,"label":"This week","operationType":"sum","scale":"ratio","sourceField":"taxful_total_price"},"bf51c1af-443e-49f4-a21f-54c87bfc5677":{"customLabel":true,"dataType":"number","isBucketed":false,"label":"Difference","operationType":"formula","params":{"format":{"id":"number","params":{"decimals":2}},"formula":"sum(taxful_total_price) - sum(taxful_total_price, shift=\'1w\')","isFormulaBroken":false},"references":["bf51c1af-443e-49f4-a21f-54c87bfc5677X2"],"scale":"ratio"},"bf51c1af-443e-49f4-a21f-54c87bfc5677X0":{"customLabel":true,"dataType":"number","isBucketed":false,"label":"Part of Difference","operationType":"sum","scale":"ratio","sourceField":"taxful_total_price"},"bf51c1af-443e-49f4-a21f-54c87bfc5677X1":{"customLabel":true,"dataType":"number","isBucketed":false,"label":"Part of Difference","operationType":"sum","scale":"ratio","sourceField":"taxful_total_price","timeShift":"1w"},"bf51c1af-443e-49f4-a21f-54c87bfc5677X2":{"customLabel":true,"dataType":"number","isBucketed":false,"label":"Part of Difference","operationType":"math","params":{"tinymathAst":{"args":["bf51c1af-443e-49f4-a21f-54c87bfc5677X0","bf51c1af-443e-49f4-a21f-54c87bfc5677X1"],"location":{"max":61,"min":0},"name":"subtract","text":"sum(taxful_total_price) - sum(taxful_total_price, shift=\'1w\')","type":"function"}},"references":["bf51c1af-443e-49f4-a21f-54c87bfc5677X0","bf51c1af-443e-49f4-a21f-54c87bfc5677X1"],"scale":"ratio"},"cfd45c47-fc41-430c-9e7a-b71dc0c916b0":{"customLabel":true,"dataType":"number","isBucketed":false,"label":"1 week ago","operationType":"sum","scale":"ratio","sourceField":"taxful_total_price","timeShift":"1w"}},"incompleteColumns":{}}}}},"filters":[],"query":{"language":"kuery","query":""},"visualization":{"columns":[{"columnId":"7bf8f089-1542-40bd-b349-45fdfc309ac6"},{"alignment":"left","columnId":"826b2f39-b616-40b2-a222-972fdc1d7596"},{"columnId":"cfd45c47-fc41-430c-9e7a-b71dc0c916b0"},{"colorMode":"text","columnId":"bf51c1af-443e-49f4-a21f-54c87bfc5677","isTransposed":false,"palette":{"name":"custom","params":{"colorStops":[{"color":"#D36086","stop":-10000},{"color":"#209280","stop":0}],"continuity":"above","name":"custom","rangeMax":0,"rangeMin":-10000,"rangeType":"number","steps":5,"stops":[{"color":"#D36086","stop":0},{"color":"#209280","stop":2249.03125}]},"type":"palette"}}],"layerId":"0731ee8b-31c5-4be9-92d9-69ee760465d7","layerType":"data","rowHeight":"single","rowHeightLines":1}},"visualizationType":"lnsDatatable","references":[{"id":"ff959d40-b880-11e8-a6d9-e546fe2bba5f","name":"indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"ff959d40-b880-11e8-a6d9-e546fe2bba5f","name":"indexpattern-datasource-layer-0731ee8b-31c5-4be9-92d9-69ee760465d7","type":"index-pattern"}]}},"title":"Daily comparison"},{"version":"8.11.0","type":"lens","gridData":{"x":0,"y":45,"w":24,"h":9,"i":"d68e91dd-1539-48b0-9279-b43bba2054fe"},"panelIndex":"d68e91dd-1539-48b0-9279-b43bba2054fe","embeddableConfig":{"hidePanelTitles":false,"enhancements":{},"attributes":{"state":{"datasourceStates":{"formBased":{"layers":{"5ed846c2-a70b-4d9c-a244-f254bef763b8":{"columnOrder":["d77cdd24-dedc-48dd-9a4b-d34c6f1a6c46","7ac31901-277a-46e2-8128-8d684b2c1127"],"columns":{"7ac31901-277a-46e2-8128-8d684b2c1127":{"customLabel":true,"dataType":"number","isBucketed":false,"label":"Items","operationType":"count","scale":"ratio","sourceField":"___records___"},"d77cdd24-dedc-48dd-9a4b-d34c6f1a6c46":{"customLabel":true,"dataType":"string","isBucketed":true,"label":"Product name","operationType":"terms","params":{"missingBucket":false,"orderBy":{"columnId":"7ac31901-277a-46e2-8128-8d684b2c1127","type":"column"},"orderDirection":"desc","otherBucket":false,"size":5,"parentFormat":{"id":"terms"}},"scale":"ordinal","sourceField":"products.product_name.keyword"}},"incompleteColumns":{}}}}},"filters":[],"query":{"language":"kuery","query":""},"visualization":{"axisTitlesVisibilitySettings":{"x":false,"yLeft":true,"yRight":true},"fittingFunction":"None","gridlinesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"layers":[{"accessors":["7ac31901-277a-46e2-8128-8d684b2c1127"],"layerId":"5ed846c2-a70b-4d9c-a244-f254bef763b8","position":"top","seriesType":"bar_horizontal","showGridlines":false,"xAccessor":"d77cdd24-dedc-48dd-9a4b-d34c6f1a6c46","layerType":"data"}],"legend":{"isVisible":true,"position":"right","legendSize":"auto"},"preferredSeriesType":"bar_horizontal","tickLabelsVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"valueLabels":"show","yLeftExtent":{"mode":"full"},"yRightExtent":{"mode":"full"}}},"visualizationType":"lnsXY","references":[{"id":"ff959d40-b880-11e8-a6d9-e546fe2bba5f","name":"indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"ff959d40-b880-11e8-a6d9-e546fe2bba5f","name":"indexpattern-datasource-layer-5ed846c2-a70b-4d9c-a244-f254bef763b8","type":"index-pattern"}]}},"title":"Top products this week"},{"version":"8.11.0","type":"lens","gridData":{"x":24,"y":45,"w":24,"h":9,"i":"39d96714-152f-414b-992c-ce2492fc69f3"},"panelIndex":"39d96714-152f-414b-992c-ce2492fc69f3","embeddableConfig":{"timeRange":{"from":"now-2w","to":"now-1w"},"hidePanelTitles":false,"enhancements":{},"attributes":{"state":{"datasourceStates":{"formBased":{"layers":{"5ed846c2-a70b-4d9c-a244-f254bef763b8":{"columnOrder":["d77cdd24-dedc-48dd-9a4b-d34c6f1a6c46","7ac31901-277a-46e2-8128-8d684b2c1127"],"columns":{"7ac31901-277a-46e2-8128-8d684b2c1127":{"customLabel":true,"dataType":"number","isBucketed":false,"label":"Items","operationType":"count","scale":"ratio","sourceField":"___records___"},"d77cdd24-dedc-48dd-9a4b-d34c6f1a6c46":{"customLabel":true,"dataType":"string","isBucketed":true,"label":"Product name","operationType":"terms","params":{"missingBucket":false,"orderBy":{"columnId":"7ac31901-277a-46e2-8128-8d684b2c1127","type":"column"},"orderDirection":"desc","otherBucket":false,"size":5,"parentFormat":{"id":"terms"}},"scale":"ordinal","sourceField":"products.product_name.keyword"}},"incompleteColumns":{}}}}},"filters":[],"query":{"language":"kuery","query":""},"visualization":{"axisTitlesVisibilitySettings":{"x":false,"yLeft":true,"yRight":true},"fittingFunction":"None","gridlinesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"layers":[{"accessors":["7ac31901-277a-46e2-8128-8d684b2c1127"],"layerId":"5ed846c2-a70b-4d9c-a244-f254bef763b8","position":"top","seriesType":"bar_horizontal","showGridlines":false,"xAccessor":"d77cdd24-dedc-48dd-9a4b-d34c6f1a6c46","layerType":"data"}],"legend":{"isVisible":true,"position":"right","legendSize":"auto"},"preferredSeriesType":"bar_horizontal","tickLabelsVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"valueLabels":"show","yLeftExtent":{"mode":"full"},"yRightExtent":{"mode":"full"}}},"visualizationType":"lnsXY","references":[{"id":"ff959d40-b880-11e8-a6d9-e546fe2bba5f","name":"indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"ff959d40-b880-11e8-a6d9-e546fe2bba5f","name":"indexpattern-datasource-layer-5ed846c2-a70b-4d9c-a244-f254bef763b8","type":"index-pattern"}]}},"title":"Top products last week"},{"version":"8.11.0","type":"lens","gridData":{"x":24,"y":14,"w":24,"h":17,"i":"cd47b7cb-0ac0-43e0-b8c6-53489648bdef"},"panelIndex":"cd47b7cb-0ac0-43e0-b8c6-53489648bdef","embeddableConfig":{"enhancements":{},"attributes":{"state":{"datasourceStates":{"formBased":{"layers":{"97c63ea6-9305-4755-97d1-0f26817c6f9a":{"columnOrder":["9f61a7df-198e-4754-b34c-81ed544136ba","ebcb19af-0900-4439-949f-d8cd9bccde19","5575214b-7f21-4b6c-8bc1-34433c6a0c58"],"columns":{"5575214b-7f21-4b6c-8bc1-34433c6a0c58":{"dataType":"number","isBucketed":false,"label":"Count of records","operationType":"count","scale":"ratio","sourceField":"___records___"},"9f61a7df-198e-4754-b34c-81ed544136ba":{"dataType":"string","isBucketed":true,"label":"Top values of category.keyword","operationType":"terms","params":{"missingBucket":false,"orderBy":{"columnId":"5575214b-7f21-4b6c-8bc1-34433c6a0c58","type":"column"},"orderDirection":"desc","otherBucket":true,"size":10,"parentFormat":{"id":"terms"}},"scale":"ordinal","sourceField":"category.keyword"},"ebcb19af-0900-4439-949f-d8cd9bccde19":{"dataType":"date","isBucketed":true,"label":"order_date","operationType":"date_histogram","params":{"interval":"1d","includeEmptyRows":true},"scale":"interval","sourceField":"order_date"}},"incompleteColumns":{}}}}},"filters":[],"query":{"language":"kuery","query":""},"visualization":{"axisTitlesVisibilitySettings":{"x":false,"yLeft":false,"yRight":true},"fittingFunction":"None","gridlinesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"layers":[{"accessors":["5575214b-7f21-4b6c-8bc1-34433c6a0c58"],"layerId":"97c63ea6-9305-4755-97d1-0f26817c6f9a","position":"top","seriesType":"bar_percentage_stacked","showGridlines":false,"splitAccessor":"9f61a7df-198e-4754-b34c-81ed544136ba","xAccessor":"ebcb19af-0900-4439-949f-d8cd9bccde19","layerType":"data"}],"legend":{"isVisible":true,"position":"right","legendSize":"auto"},"preferredSeriesType":"bar_percentage_stacked","tickLabelsVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"valueLabels":"show","yLeftExtent":{"mode":"full"},"yRightExtent":{"mode":"full"}}},"visualizationType":"lnsXY","references":[{"id":"ff959d40-b880-11e8-a6d9-e546fe2bba5f","name":"indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"ff959d40-b880-11e8-a6d9-e546fe2bba5f","name":"indexpattern-datasource-layer-97c63ea6-9305-4755-97d1-0f26817c6f9a","type":"index-pattern"}]}},"title":"Breakdown by category"},{"version":"8.11.0","type":"lens","gridData":{"x":0,"y":7,"w":24,"h":7,"i":"bdb525ab-270b-46f1-a847-dd29be19aadb"},"panelIndex":"bdb525ab-270b-46f1-a847-dd29be19aadb","embeddableConfig":{"enhancements":{},"hidePanelTitles":false,"attributes":{"state":{"datasourceStates":{"formBased":{"layers":{"c7478794-6767-4286-9d65-1c0ecd909dd8":{"columnOrder":["8289349e-6d1b-4abf-b164-0208183d2c34","041db33b-5c9c-47f3-a5d3-ef5e255d1663","041db33b-5c9c-47f3-a5d3-ef5e255d1663X0","041db33b-5c9c-47f3-a5d3-ef5e255d1663X1"],"columns":{"041db33b-5c9c-47f3-a5d3-ef5e255d1663":{"customLabel":true,"dataType":"number","isBucketed":false,"label":"% of target ($10k)","operationType":"formula","params":{"format":{"id":"percent","params":{"decimals":0}},"formula":"sum(taxful_total_price) / 10000 - 1","isFormulaBroken":false},"references":["041db33b-5c9c-47f3-a5d3-ef5e255d1663X1"],"scale":"ratio"},"041db33b-5c9c-47f3-a5d3-ef5e255d1663X0":{"customLabel":true,"dataType":"number","isBucketed":false,"label":"Part of Weekly revenue","operationType":"sum","scale":"ratio","sourceField":"taxful_total_price"},"041db33b-5c9c-47f3-a5d3-ef5e255d1663X1":{"customLabel":true,"dataType":"number","isBucketed":false,"label":"Part of Weekly revenue","operationType":"math","params":{"tinymathAst":{"args":[{"args":["041db33b-5c9c-47f3-a5d3-ef5e255d1663X0",10000],"location":{"max":32,"min":0},"name":"divide","text":"sum(taxful_total_price) / 10000 ","type":"function"},1],"location":{"max":35,"min":0},"name":"subtract","text":"sum(taxful_total_price) / 10000 - 1","type":"function"}},"references":["041db33b-5c9c-47f3-a5d3-ef5e255d1663X0"],"scale":"ratio"},"8289349e-6d1b-4abf-b164-0208183d2c34":{"dataType":"date","isBucketed":true,"label":"order_date","operationType":"date_histogram","params":{"interval":"1d","includeEmptyRows":true},"scale":"interval","sourceField":"order_date"}},"incompleteColumns":{}}}}},"filters":[],"query":{"language":"kuery","query":""},"visualization":{"axisTitlesVisibilitySettings":{"x":false,"yLeft":false,"yRight":true},"fittingFunction":"None","gridlinesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"layers":[{"accessors":["041db33b-5c9c-47f3-a5d3-ef5e255d1663"],"layerId":"c7478794-6767-4286-9d65-1c0ecd909dd8","seriesType":"bar_stacked","xAccessor":"8289349e-6d1b-4abf-b164-0208183d2c34","layerType":"data"}],"legend":{"isVisible":true,"position":"right","legendSize":"auto"},"preferredSeriesType":"bar_stacked","tickLabelsVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"valueLabels":"hide","yLeftExtent":{"mode":"full"},"yRightExtent":{"mode":"full"}}},"visualizationType":"lnsXY","references":[{"id":"ff959d40-b880-11e8-a6d9-e546fe2bba5f","name":"indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"ff959d40-b880-11e8-a6d9-e546fe2bba5f","name":"indexpattern-datasource-layer-c7478794-6767-4286-9d65-1c0ecd909dd8","type":"index-pattern"}]}},"title":"% of target revenue ($10k)"}]', + '[{"version":"8.11.0","type":"lens","gridData":{"x":0,"y":21,"w":24,"h":10,"i":"5"},"panelIndex":"5","embeddableConfig":{"attributes":{"title":"[eCommerce] Promotion Tracking (converted)","visualizationType":"lnsXY","type":"lens","references":[{"type":"index-pattern","id":"ff959d40-b880-11e8-a6d9-e546fe2bba5f","name":"indexpattern-datasource-layer-e3b3cb5c-e3b1-497f-a5d5-fddb0dabc94e"},{"type":"index-pattern","id":"ff959d40-b880-11e8-a6d9-e546fe2bba5f","name":"indexpattern-datasource-layer-1d08a43c-8913-4692-a3e0-8d77902f6e46"},{"type":"index-pattern","id":"ff959d40-b880-11e8-a6d9-e546fe2bba5f","name":"indexpattern-datasource-layer-9725cdbd-a9f3-479f-a349-0f11244e5239"},{"type":"index-pattern","id":"ff959d40-b880-11e8-a6d9-e546fe2bba5f","name":"indexpattern-datasource-layer-2031d0f8-01fc-4009-b1ad-a7b7ca9266c0"},{"type":"index-pattern","id":"ff959d40-b880-11e8-a6d9-e546fe2bba5f","name":"xy-visualization-layer-192ad2e4-2bb7-44a9-b345-e96045fa6ccd"}],"state":{"visualization":{"legend":{"isVisible":true,"showSingleSeries":true,"position":"bottom","shouldTruncate":true,"maxLines":1},"valueLabels":"hide","fittingFunction":"None","fillOpacity":0,"yLeftExtent":{"mode":"full"},"yRightExtent":{"mode":"full"},"yLeftScale":"linear","yRightScale":"linear","axisTitlesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"tickLabelsVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"labelsOrientation":{"x":0,"yLeft":0,"yRight":0},"gridlinesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"preferredSeriesType":"bar_stacked","layers":[{"seriesType":"line","layerType":"data","layerId":"e3b3cb5c-e3b1-497f-a5d5-fddb0dabc94e","accessors":["a69956c9-43cd-4756-a3c0-e93cb1502a0b"],"yConfig":[{"forAccessor":"a69956c9-43cd-4756-a3c0-e93cb1502a0b","axisMode":"left"}],"xAccessor":"f3cc8168-6360-4727-a410-a57f5a325091","palette":{"name":"default","type":"palette"}},{"seriesType":"line","layerType":"data","layerId":"1d08a43c-8913-4692-a3e0-8d77902f6e46","accessors":["9a3d8abd-81a5-40ae-9616-020d5a5b2ee2"],"yConfig":[{"forAccessor":"9a3d8abd-81a5-40ae-9616-020d5a5b2ee2","axisMode":"left"}],"xAccessor":"644b06ea-73a3-47b1-9b40-3035844c4621","palette":{"name":"default","type":"palette"}},{"seriesType":"line","layerType":"data","layerId":"9725cdbd-a9f3-479f-a349-0f11244e5239","accessors":["b5588228-9c46-4a4b-92ee-d140c327bca0"],"yConfig":[{"forAccessor":"b5588228-9c46-4a4b-92ee-d140c327bca0","axisMode":"left"}],"xAccessor":"6749b404-4784-4fd6-8bf6-5712e84c7310","palette":{"name":"default","type":"palette"}},{"seriesType":"line","layerType":"data","layerId":"2031d0f8-01fc-4009-b1ad-a7b7ca9266c0","accessors":["985e05c0-3a0b-4e55-84bb-1f02128388a9"],"yConfig":[{"forAccessor":"985e05c0-3a0b-4e55-84bb-1f02128388a9","axisMode":"left"}],"xAccessor":"1b199cb1-b47f-48e6-b209-74eb81b303f5","palette":{"name":"default","type":"palette"}},{"layerId":"192ad2e4-2bb7-44a9-b345-e96045fa6ccd","layerType":"annotations","ignoreGlobalFilters":true,"annotations":[{"type":"query","id":"c8c30be0-b88f-11e8-a451-f37365e9f268","label":"Event","key":{"type":"point_in_time"},"color":"#194D33","timeField":"order_date","icon":"bell","filter":{"type":"kibana_query","query":"taxful_total_price:>250","language":"lucene"},"extraFields":["taxful_total_price"]}]}]},"query":{"query":"","language":"kuery"},"filters":[],"datasourceStates":{"formBased":{"layers":{"e3b3cb5c-e3b1-497f-a5d5-fddb0dabc94e":{"columns":{"f3cc8168-6360-4727-a410-a57f5a325091":{"label":"order_date","dataType":"date","operationType":"date_histogram","sourceField":"order_date","isBucketed":true,"scale":"interval","params":{"interval":"12h","includeEmptyRows":true,"dropPartials":false}},"a69956c9-43cd-4756-a3c0-e93cb1502a0b":{"label":"Revenue Trousers","dataType":"number","operationType":"sum","sourceField":"taxful_total_price","isBucketed":false,"scale":"ratio","filter":{"query":"products.product_name:*trouser*","language":"lucene"},"params":{"format":{"id":"number"},"emptyAsNull":true},"customLabel":true}},"columnOrder":["f3cc8168-6360-4727-a410-a57f5a325091","a69956c9-43cd-4756-a3c0-e93cb1502a0b"],"incompleteColumns":{}},"1d08a43c-8913-4692-a3e0-8d77902f6e46":{"columns":{"644b06ea-73a3-47b1-9b40-3035844c4621":{"label":"order_date","dataType":"date","operationType":"date_histogram","sourceField":"order_date","isBucketed":true,"scale":"interval","params":{"interval":"12h","includeEmptyRows":true,"dropPartials":false}},"9a3d8abd-81a5-40ae-9616-020d5a5b2ee2":{"label":"Revenue Watches","dataType":"number","operationType":"sum","sourceField":"taxful_total_price","isBucketed":false,"scale":"ratio","filter":{"query":"products.product_name:*watch*","language":"lucene"},"params":{"format":{"id":"number"},"emptyAsNull":true},"customLabel":true}},"columnOrder":["644b06ea-73a3-47b1-9b40-3035844c4621","9a3d8abd-81a5-40ae-9616-020d5a5b2ee2"],"incompleteColumns":{}},"9725cdbd-a9f3-479f-a349-0f11244e5239":{"columns":{"6749b404-4784-4fd6-8bf6-5712e84c7310":{"label":"order_date","dataType":"date","operationType":"date_histogram","sourceField":"order_date","isBucketed":true,"scale":"interval","params":{"interval":"12h","includeEmptyRows":true,"dropPartials":false}},"b5588228-9c46-4a4b-92ee-d140c327bca0":{"label":"Revenue Bags","dataType":"number","operationType":"sum","sourceField":"taxful_total_price","isBucketed":false,"scale":"ratio","filter":{"query":"products.product_name:*bag*","language":"lucene"},"params":{"format":{"id":"number"},"emptyAsNull":true},"customLabel":true}},"columnOrder":["6749b404-4784-4fd6-8bf6-5712e84c7310","b5588228-9c46-4a4b-92ee-d140c327bca0"],"incompleteColumns":{}},"2031d0f8-01fc-4009-b1ad-a7b7ca9266c0":{"columns":{"1b199cb1-b47f-48e6-b209-74eb81b303f5":{"label":"order_date","dataType":"date","operationType":"date_histogram","sourceField":"order_date","isBucketed":true,"scale":"interval","params":{"interval":"12h","includeEmptyRows":true,"dropPartials":false}},"985e05c0-3a0b-4e55-84bb-1f02128388a9":{"label":"Revenue Cocktail Dresses","dataType":"number","operationType":"sum","sourceField":"taxful_total_price","isBucketed":false,"scale":"ratio","filter":{"query":"products.product_name:*cocktail dress*","language":"lucene"},"params":{"format":{"id":"number"},"emptyAsNull":true},"customLabel":true}},"columnOrder":["1b199cb1-b47f-48e6-b209-74eb81b303f5","985e05c0-3a0b-4e55-84bb-1f02128388a9"],"incompleteColumns":{}}}},"textBased":{"layers":{}}},"internalReferences":[],"adHocDataViews":{}}},"hidePanelTitles":false,"enhancements":{}},"title":"[eCommerce] Promotion Tracking"},{"version":"8.11.0","type":"lens","gridData":{"x":36,"y":7,"w":12,"h":7,"i":"7"},"panelIndex":"7","embeddableConfig":{"attributes":{"title":"Sold Products per Day","description":"","visualizationType":"lnsMetric","type":"lens","references":[{"type":"index-pattern","id":"ff959d40-b880-11e8-a6d9-e546fe2bba5f","name":"indexpattern-datasource-layer-037375ae-9e23-4dd5-a4f0-5f117bb7dac1"}],"state":{"visualization":{"layerId":"037375ae-9e23-4dd5-a4f0-5f117bb7dac1","layerType":"data","metricAccessor":"c27bd77c-68e2-4d75-8fda-41c45d22f8d4","maxAccessor":"ce816876-e92d-4b1a-bbb0-ed7637fc0eea","showBar":true,"palette":{"type":"palette","name":"status","params":{"name":"status","reverse":true,"rangeType":"percent","rangeMin":0,"rangeMax":100,"progression":"fixed","stops":[{"color":"#23be8f","stop":33.33},{"color":"#fcd279","stop":66.66},{"color":"#f66d64","stop":100}],"steps":3,"colorStops":[],"continuity":"all","maxSteps":5}}},"query":{"query":"","language":"kuery"},"filters":[],"datasourceStates":{"formBased":{"layers":{"037375ae-9e23-4dd5-a4f0-5f117bb7dac1":{"ignoreGlobalFilters":false,"columns":{"c27bd77c-68e2-4d75-8fda-41c45d22f8d4X0":{"label":"Part of count() / (time_range() / 1000 / 60 / 60 / 24)","dataType":"number","operationType":"count","isBucketed":false,"scale":"ratio","sourceField":"___records___","params":{"emptyAsNull":false},"customLabel":true},"c27bd77c-68e2-4d75-8fda-41c45d22f8d4X1":{"label":"Part of count() / (time_range() / 1000 / 60 / 60 / 24)","dataType":"number","operationType":"time_range","isBucketed":false,"scale":"ratio","references":[],"customLabel":true},"c27bd77c-68e2-4d75-8fda-41c45d22f8d4X2":{"label":"Part of count() / (time_range() / 1000 / 60 / 60 / 24)","dataType":"number","operationType":"math","isBucketed":false,"scale":"ratio","params":{"tinymathAst":{"type":"function","name":"divide","args":["c27bd77c-68e2-4d75-8fda-41c45d22f8d4X0",{"type":"function","name":"divide","args":[{"type":"function","name":"divide","args":[{"type":"function","name":"divide","args":[{"type":"function","name":"divide","args":["c27bd77c-68e2-4d75-8fda-41c45d22f8d4X1",1000]},60]},60]},24],"location":{"min":11,"max":45},"text":"time_range() / 1000 / 60 / 60 / 24"}],"location":{"min":0,"max":46},"text":"count() / (time_range() / 1000 / 60 / 60 / 24)"}},"references":["c27bd77c-68e2-4d75-8fda-41c45d22f8d4X0","c27bd77c-68e2-4d75-8fda-41c45d22f8d4X1"],"customLabel":true},"c27bd77c-68e2-4d75-8fda-41c45d22f8d4":{"label":"Trxns / day","dataType":"number","operationType":"formula","isBucketed":false,"scale":"ratio","params":{"format":{"id":"number"},"formula":"count() / (time_range() / 1000 / 60 / 60 / 24)","isFormulaBroken":false},"references":["c27bd77c-68e2-4d75-8fda-41c45d22f8d4X2"],"customLabel":true},"ce816876-e92d-4b1a-bbb0-ed7637fc0eea":{"label":"Static value: 300","dataType":"number","operationType":"static_value","isStaticValue":true,"isBucketed":false,"scale":"ratio","params":{"value":"300"},"references":[]}},"columnOrder":["c27bd77c-68e2-4d75-8fda-41c45d22f8d4X0","c27bd77c-68e2-4d75-8fda-41c45d22f8d4X1","c27bd77c-68e2-4d75-8fda-41c45d22f8d4X2","c27bd77c-68e2-4d75-8fda-41c45d22f8d4","ce816876-e92d-4b1a-bbb0-ed7637fc0eea"],"incompleteColumns":{}}}},"indexpattern":{"layers":{}},"textBased":{"layers":{}}},"internalReferences":[],"adHocDataViews":{}}},"timeRange":{"from":"now-7d","to":"now"},"enhancements":{}}},{"version":"8.11.0","type":"search","gridData":{"x":0,"y":54,"w":48,"h":18,"i":"10"},"panelIndex":"10","embeddableConfig":{"enhancements":{}},"panelRefName":"panel_10"},{"version":"8.11.0","type":"map","gridData":{"x":0,"y":31,"w":24,"h":14,"i":"11"},"panelIndex":"11","embeddableConfig":{"isLayerTOCOpen":false,"hiddenLayers":[],"mapCenter":{"lat":45.88578,"lon":-15.07605,"zoom":2.11},"openTOCDetails":[],"enhancements":{}},"panelRefName":"panel_11"},{"version":"8.11.0","type":"visualization","gridData":{"x":0,"y":0,"w":24,"h":7,"i":"a71cf076-6895-491c-8878-63592e429ed5"},"panelIndex":"a71cf076-6895-491c-8878-63592e429ed5","embeddableConfig":{"enhancements":{}},"panelRefName":"panel_a71cf076-6895-491c-8878-63592e429ed5"},{"version":"8.11.0","type":"lens","gridData":{"x":24,"y":0,"w":12,"h":7,"i":"75283285-dffd-48a7-a0c2-2235184b5282"},"panelIndex":"75283285-dffd-48a7-a0c2-2235184b5282","embeddableConfig":{"enhancements":{},"attributes":{"visualizationType":"lnsMetric","state":{"visualization":{"layerId":"c7478794-6767-4286-9d65-1c0ecd909dd8","layerType":"data","metricAccessor":"041db33b-5c9c-47f3-a5d3-ef5e255d1663"},"query":{"language":"kuery","query":""},"filters":[],"datasourceStates":{"formBased":{"layers":{"c7478794-6767-4286-9d65-1c0ecd909dd8":{"columnOrder":["041db33b-5c9c-47f3-a5d3-ef5e255d1663"],"columns":{"041db33b-5c9c-47f3-a5d3-ef5e255d1663":{"customLabel":true,"dataType":"number","isBucketed":false,"label":"Sum of revenue","operationType":"sum","scale":"ratio","sourceField":"taxful_total_price","params":{}}},"incompleteColumns":{}}}}},"internalReferences":[],"adHocDataViews":{}},"references":[{"type":"index-pattern","id":"ff959d40-b880-11e8-a6d9-e546fe2bba5f","name":"indexpattern-datasource-layer-c7478794-6767-4286-9d65-1c0ecd909dd8"}]},"hidePanelTitles":true},"title":"Sum of revenue"},{"version":"8.11.0","type":"lens","gridData":{"x":36,"y":0,"w":12,"h":7,"i":"58774330-b1b3-42dd-a04c-fbce9cc4d288"},"panelIndex":"58774330-b1b3-42dd-a04c-fbce9cc4d288","embeddableConfig":{"enhancements":{},"attributes":{"title":"Median spending","visualizationType":"lnsMetric","type":"lens","references":[{"type":"index-pattern","id":"ff959d40-b880-11e8-a6d9-e546fe2bba5f","name":"indexpattern-datasource-layer-4fb42a8e-b133-43c8-805c-a38472053938"}],"state":{"visualization":{"layerId":"4fb42a8e-b133-43c8-805c-a38472053938","layerType":"data","metricAccessor":"020bbfdf-9ef8-4802-aa9e-342d2ea0bebf"},"query":{"language":"kuery","query":""},"filters":[],"datasourceStates":{"formBased":{"layers":{"4fb42a8e-b133-43c8-805c-a38472053938":{"columnOrder":["020bbfdf-9ef8-4802-aa9e-342d2ea0bebf"],"columns":{"020bbfdf-9ef8-4802-aa9e-342d2ea0bebf":{"customLabel":true,"dataType":"number","isBucketed":false,"label":"Median spending","operationType":"median","scale":"ratio","sourceField":"taxful_total_price","params":{}}},"incompleteColumns":{}}}}},"internalReferences":[],"adHocDataViews":{}}},"hidePanelTitles":true},"title":"Median spending"},{"version":"8.11.0","type":"lens","gridData":{"x":24,"y":7,"w":12,"h":7,"i":"b63ec47d-aace-4980-b928-6be8adafa5a4"},"panelIndex":"b63ec47d-aace-4980-b928-6be8adafa5a4","embeddableConfig":{"enhancements":{},"attributes":{"visualizationType":"lnsMetric","state":{"visualization":{"layerId":"667067a2-7cdf-4f0e-a9fe-eb4f4f1f2f17","layerType":"data","metricAccessor":"c52c2003-ae58-4604-bae7-52ba0fb38a01"},"query":{"language":"kuery","query":""},"filters":[],"datasourceStates":{"formBased":{"layers":{"667067a2-7cdf-4f0e-a9fe-eb4f4f1f2f17":{"columnOrder":["c52c2003-ae58-4604-bae7-52ba0fb38a01"],"columns":{"c52c2003-ae58-4604-bae7-52ba0fb38a01":{"customLabel":true,"dataType":"number","isBucketed":false,"label":"Avg. items sold","operationType":"average","params":{"format":{"id":"number","params":{"decimals":1,"compact":true}}},"scale":"ratio","sourceField":"total_quantity"}},"incompleteColumns":{}}}}},"internalReferences":[],"adHocDataViews":{}},"references":[{"type":"index-pattern","id":"ff959d40-b880-11e8-a6d9-e546fe2bba5f","name":"indexpattern-datasource-layer-667067a2-7cdf-4f0e-a9fe-eb4f4f1f2f17"}]},"hidePanelTitles":true},"title":"Avg. items sold"},{"version":"8.11.0","type":"lens","gridData":{"x":0,"y":14,"w":24,"h":7,"i":"d9495793-80ba-4a9a-b0e3-d1155ec99b09"},"panelIndex":"d9495793-80ba-4a9a-b0e3-d1155ec99b09","embeddableConfig":{"enhancements":{},"attributes":{"state":{"datasourceStates":{"formBased":{"layers":{"b6093a53-884f-42c2-9fcc-ba56cfb66c53":{"columnOrder":["15c45f89-a149-443a-a830-aa8c3a9317db","2b41b3d8-2f62-407a-a866-960f254c679d","eadae280-2da3-4d1d-a0e1-f9733f89c15b","ddc92e50-4d5c-413e-b91b-3e504889fa65","5e31e5d3-2aaa-4475-a130-3b69bf2f748a"],"columns":{"15c45f89-a149-443a-a830-aa8c3a9317db":{"dataType":"date","isBucketed":true,"label":"order_date","operationType":"date_histogram","params":{"interval":"1d","includeEmptyRows":true},"scale":"interval","sourceField":"order_date"},"2b41b3d8-2f62-407a-a866-960f254c679d":{"customLabel":true,"dataType":"number","isBucketed":false,"label":"Total items","operationType":"sum","scale":"ratio","sourceField":"products.quantity"},"5e31e5d3-2aaa-4475-a130-3b69bf2f748a":{"customLabel":true,"dataType":"number","isBucketed":false,"label":"Tx. last week","operationType":"count","scale":"ratio","sourceField":"___records___","timeShift":"1w"},"ddc92e50-4d5c-413e-b91b-3e504889fa65":{"customLabel":true,"dataType":"number","isBucketed":false,"label":"Transactions","operationType":"count","scale":"ratio","sourceField":"___records___"},"eadae280-2da3-4d1d-a0e1-f9733f89c15b":{"customLabel":true,"dataType":"number","isBucketed":false,"label":"Last week","operationType":"sum","scale":"ratio","sourceField":"products.quantity","timeShift":"1w"}},"incompleteColumns":{}}}}},"filters":[],"query":{"language":"kuery","query":""},"visualization":{"axisTitlesVisibilitySettings":{"x":false,"yLeft":false,"yRight":true},"curveType":"LINEAR","fittingFunction":"None","gridlinesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"layers":[{"accessors":["2b41b3d8-2f62-407a-a866-960f254c679d","eadae280-2da3-4d1d-a0e1-f9733f89c15b","5e31e5d3-2aaa-4475-a130-3b69bf2f748a","ddc92e50-4d5c-413e-b91b-3e504889fa65"],"layerId":"b6093a53-884f-42c2-9fcc-ba56cfb66c53","position":"top","seriesType":"line","showGridlines":false,"xAccessor":"15c45f89-a149-443a-a830-aa8c3a9317db","yConfig":[],"layerType":"data"}],"legend":{"isVisible":true,"position":"right","legendSize":"auto"},"preferredSeriesType":"line","tickLabelsVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"valueLabels":"hide","yLeftExtent":{"mode":"full"},"yRightExtent":{"mode":"full"}}},"visualizationType":"lnsXY","references":[{"id":"ff959d40-b880-11e8-a6d9-e546fe2bba5f","name":"indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"ff959d40-b880-11e8-a6d9-e546fe2bba5f","name":"indexpattern-datasource-layer-b6093a53-884f-42c2-9fcc-ba56cfb66c53","type":"index-pattern"}]}},"title":"Transactions per day"},{"version":"8.11.0","type":"lens","gridData":{"x":24,"y":31,"w":24,"h":14,"i":"bda054f7-2d06-4936-b461-365d1be621fa"},"panelIndex":"bda054f7-2d06-4936-b461-365d1be621fa","embeddableConfig":{"enhancements":{},"attributes":{"state":{"datasourceStates":{"formBased":{"layers":{"0731ee8b-31c5-4be9-92d9-69ee760465d7":{"columnOrder":["7bf8f089-1542-40bd-b349-45fdfc309ac6","826b2f39-b616-40b2-a222-972fdc1d7596","cfd45c47-fc41-430c-9e7a-b71dc0c916b0","bf51c1af-443e-49f4-a21f-54c87bfc5677","bf51c1af-443e-49f4-a21f-54c87bfc5677X0","bf51c1af-443e-49f4-a21f-54c87bfc5677X1","bf51c1af-443e-49f4-a21f-54c87bfc5677X2"],"columns":{"7bf8f089-1542-40bd-b349-45fdfc309ac6":{"dataType":"date","isBucketed":true,"label":"order_date","operationType":"date_histogram","params":{"interval":"1d","includeEmptyRows":true},"scale":"interval","sourceField":"order_date"},"826b2f39-b616-40b2-a222-972fdc1d7596":{"customLabel":true,"dataType":"number","isBucketed":false,"label":"This week","operationType":"sum","scale":"ratio","sourceField":"taxful_total_price"},"bf51c1af-443e-49f4-a21f-54c87bfc5677":{"customLabel":true,"dataType":"number","isBucketed":false,"label":"Difference","operationType":"formula","params":{"format":{"id":"number","params":{"decimals":2}},"formula":"sum(taxful_total_price) - sum(taxful_total_price, shift=\'1w\')","isFormulaBroken":false},"references":["bf51c1af-443e-49f4-a21f-54c87bfc5677X2"],"scale":"ratio"},"bf51c1af-443e-49f4-a21f-54c87bfc5677X0":{"customLabel":true,"dataType":"number","isBucketed":false,"label":"Part of Difference","operationType":"sum","scale":"ratio","sourceField":"taxful_total_price"},"bf51c1af-443e-49f4-a21f-54c87bfc5677X1":{"customLabel":true,"dataType":"number","isBucketed":false,"label":"Part of Difference","operationType":"sum","scale":"ratio","sourceField":"taxful_total_price","timeShift":"1w"},"bf51c1af-443e-49f4-a21f-54c87bfc5677X2":{"customLabel":true,"dataType":"number","isBucketed":false,"label":"Part of Difference","operationType":"math","params":{"tinymathAst":{"args":["bf51c1af-443e-49f4-a21f-54c87bfc5677X0","bf51c1af-443e-49f4-a21f-54c87bfc5677X1"],"location":{"max":61,"min":0},"name":"subtract","text":"sum(taxful_total_price) - sum(taxful_total_price, shift=\'1w\')","type":"function"}},"references":["bf51c1af-443e-49f4-a21f-54c87bfc5677X0","bf51c1af-443e-49f4-a21f-54c87bfc5677X1"],"scale":"ratio"},"cfd45c47-fc41-430c-9e7a-b71dc0c916b0":{"customLabel":true,"dataType":"number","isBucketed":false,"label":"1 week ago","operationType":"sum","scale":"ratio","sourceField":"taxful_total_price","timeShift":"1w"}},"incompleteColumns":{}}}}},"filters":[],"query":{"language":"kuery","query":""},"visualization":{"columns":[{"columnId":"7bf8f089-1542-40bd-b349-45fdfc309ac6"},{"alignment":"left","columnId":"826b2f39-b616-40b2-a222-972fdc1d7596"},{"columnId":"cfd45c47-fc41-430c-9e7a-b71dc0c916b0"},{"colorMode":"text","columnId":"bf51c1af-443e-49f4-a21f-54c87bfc5677","isTransposed":false,"palette":{"type":"palette","name":"status","params":{"continuity":"above","name":"status","rangeMax":null,"rangeMin":-2284.2265625,"rangeType":"percent","steps":5,"stops":[{"color":"#23be8f","stop":0},{"color":"#9dedce","stop":20},{"color":"#fcd279","stop":40},{"color":"#ffc0b8","stop":60},{"color":"#f66d64","stop":80}],"reverse":true}}}],"layerId":"0731ee8b-31c5-4be9-92d9-69ee760465d7","layerType":"data","rowHeight":"single","rowHeightLines":1}},"visualizationType":"lnsDatatable","references":[{"id":"ff959d40-b880-11e8-a6d9-e546fe2bba5f","name":"indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"ff959d40-b880-11e8-a6d9-e546fe2bba5f","name":"indexpattern-datasource-layer-0731ee8b-31c5-4be9-92d9-69ee760465d7","type":"index-pattern"}]}},"title":"Daily comparison"},{"version":"8.11.0","type":"lens","gridData":{"x":0,"y":45,"w":24,"h":9,"i":"d68e91dd-1539-48b0-9279-b43bba2054fe"},"panelIndex":"d68e91dd-1539-48b0-9279-b43bba2054fe","embeddableConfig":{"hidePanelTitles":false,"enhancements":{},"attributes":{"state":{"datasourceStates":{"formBased":{"layers":{"5ed846c2-a70b-4d9c-a244-f254bef763b8":{"columnOrder":["d77cdd24-dedc-48dd-9a4b-d34c6f1a6c46","7ac31901-277a-46e2-8128-8d684b2c1127"],"columns":{"7ac31901-277a-46e2-8128-8d684b2c1127":{"customLabel":true,"dataType":"number","isBucketed":false,"label":"Items","operationType":"count","scale":"ratio","sourceField":"___records___"},"d77cdd24-dedc-48dd-9a4b-d34c6f1a6c46":{"customLabel":true,"dataType":"string","isBucketed":true,"label":"Product name","operationType":"terms","params":{"missingBucket":false,"orderBy":{"columnId":"7ac31901-277a-46e2-8128-8d684b2c1127","type":"column"},"orderDirection":"desc","otherBucket":false,"size":5,"parentFormat":{"id":"terms"}},"scale":"ordinal","sourceField":"products.product_name.keyword"}},"incompleteColumns":{}}}}},"filters":[],"query":{"language":"kuery","query":""},"visualization":{"axisTitlesVisibilitySettings":{"x":false,"yLeft":true,"yRight":true},"fittingFunction":"None","gridlinesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"layers":[{"accessors":["7ac31901-277a-46e2-8128-8d684b2c1127"],"layerId":"5ed846c2-a70b-4d9c-a244-f254bef763b8","position":"top","seriesType":"bar_horizontal","showGridlines":false,"xAccessor":"d77cdd24-dedc-48dd-9a4b-d34c6f1a6c46","layerType":"data"}],"legend":{"isVisible":true,"position":"right","legendSize":"auto"},"preferredSeriesType":"bar_horizontal","tickLabelsVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"valueLabels":"show","yLeftExtent":{"mode":"full"},"yRightExtent":{"mode":"full"}}},"visualizationType":"lnsXY","references":[{"id":"ff959d40-b880-11e8-a6d9-e546fe2bba5f","name":"indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"ff959d40-b880-11e8-a6d9-e546fe2bba5f","name":"indexpattern-datasource-layer-5ed846c2-a70b-4d9c-a244-f254bef763b8","type":"index-pattern"}]}},"title":"Top products this week"},{"version":"8.11.0","type":"lens","gridData":{"x":24,"y":45,"w":24,"h":9,"i":"39d96714-152f-414b-992c-ce2492fc69f3"},"panelIndex":"39d96714-152f-414b-992c-ce2492fc69f3","embeddableConfig":{"timeRange":{"from":"now-2w","to":"now-1w"},"hidePanelTitles":false,"enhancements":{},"attributes":{"state":{"datasourceStates":{"formBased":{"layers":{"5ed846c2-a70b-4d9c-a244-f254bef763b8":{"columnOrder":["d77cdd24-dedc-48dd-9a4b-d34c6f1a6c46","7ac31901-277a-46e2-8128-8d684b2c1127"],"columns":{"7ac31901-277a-46e2-8128-8d684b2c1127":{"customLabel":true,"dataType":"number","isBucketed":false,"label":"Items","operationType":"count","scale":"ratio","sourceField":"___records___"},"d77cdd24-dedc-48dd-9a4b-d34c6f1a6c46":{"customLabel":true,"dataType":"string","isBucketed":true,"label":"Product name","operationType":"terms","params":{"missingBucket":false,"orderBy":{"columnId":"7ac31901-277a-46e2-8128-8d684b2c1127","type":"column"},"orderDirection":"desc","otherBucket":false,"size":5,"parentFormat":{"id":"terms"}},"scale":"ordinal","sourceField":"products.product_name.keyword"}},"incompleteColumns":{}}}}},"filters":[],"query":{"language":"kuery","query":""},"visualization":{"axisTitlesVisibilitySettings":{"x":false,"yLeft":true,"yRight":true},"fittingFunction":"None","gridlinesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"layers":[{"accessors":["7ac31901-277a-46e2-8128-8d684b2c1127"],"layerId":"5ed846c2-a70b-4d9c-a244-f254bef763b8","position":"top","seriesType":"bar_horizontal","showGridlines":false,"xAccessor":"d77cdd24-dedc-48dd-9a4b-d34c6f1a6c46","layerType":"data"}],"legend":{"isVisible":true,"position":"right","legendSize":"auto"},"preferredSeriesType":"bar_horizontal","tickLabelsVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"valueLabels":"show","yLeftExtent":{"mode":"full"},"yRightExtent":{"mode":"full"}}},"visualizationType":"lnsXY","references":[{"id":"ff959d40-b880-11e8-a6d9-e546fe2bba5f","name":"indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"ff959d40-b880-11e8-a6d9-e546fe2bba5f","name":"indexpattern-datasource-layer-5ed846c2-a70b-4d9c-a244-f254bef763b8","type":"index-pattern"}]}},"title":"Top products last week"},{"version":"8.11.0","type":"lens","gridData":{"x":24,"y":14,"w":24,"h":17,"i":"cd47b7cb-0ac0-43e0-b8c6-53489648bdef"},"panelIndex":"cd47b7cb-0ac0-43e0-b8c6-53489648bdef","embeddableConfig":{"enhancements":{},"attributes":{"state":{"datasourceStates":{"formBased":{"layers":{"97c63ea6-9305-4755-97d1-0f26817c6f9a":{"columnOrder":["9f61a7df-198e-4754-b34c-81ed544136ba","ebcb19af-0900-4439-949f-d8cd9bccde19","5575214b-7f21-4b6c-8bc1-34433c6a0c58"],"columns":{"5575214b-7f21-4b6c-8bc1-34433c6a0c58":{"dataType":"number","isBucketed":false,"label":"Count of records","operationType":"count","scale":"ratio","sourceField":"___records___"},"9f61a7df-198e-4754-b34c-81ed544136ba":{"dataType":"string","isBucketed":true,"label":"Top values of category.keyword","operationType":"terms","params":{"missingBucket":false,"orderBy":{"columnId":"5575214b-7f21-4b6c-8bc1-34433c6a0c58","type":"column"},"orderDirection":"desc","otherBucket":true,"size":10,"parentFormat":{"id":"terms"}},"scale":"ordinal","sourceField":"category.keyword"},"ebcb19af-0900-4439-949f-d8cd9bccde19":{"dataType":"date","isBucketed":true,"label":"order_date","operationType":"date_histogram","params":{"interval":"1d","includeEmptyRows":true},"scale":"interval","sourceField":"order_date"}},"incompleteColumns":{}}}}},"filters":[],"query":{"language":"kuery","query":""},"visualization":{"axisTitlesVisibilitySettings":{"x":false,"yLeft":false,"yRight":true},"fittingFunction":"None","gridlinesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"layers":[{"accessors":["5575214b-7f21-4b6c-8bc1-34433c6a0c58"],"layerId":"97c63ea6-9305-4755-97d1-0f26817c6f9a","position":"top","seriesType":"bar_percentage_stacked","showGridlines":false,"splitAccessor":"9f61a7df-198e-4754-b34c-81ed544136ba","xAccessor":"ebcb19af-0900-4439-949f-d8cd9bccde19","layerType":"data"}],"legend":{"isVisible":true,"position":"right","legendSize":"auto"},"preferredSeriesType":"bar_percentage_stacked","tickLabelsVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"valueLabels":"show","yLeftExtent":{"mode":"full"},"yRightExtent":{"mode":"full"}}},"visualizationType":"lnsXY","references":[{"id":"ff959d40-b880-11e8-a6d9-e546fe2bba5f","name":"indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"ff959d40-b880-11e8-a6d9-e546fe2bba5f","name":"indexpattern-datasource-layer-97c63ea6-9305-4755-97d1-0f26817c6f9a","type":"index-pattern"}]}},"title":"Breakdown by category"},{"version":"8.11.0","type":"lens","gridData":{"x":0,"y":7,"w":24,"h":7,"i":"bdb525ab-270b-46f1-a847-dd29be19aadb"},"panelIndex":"bdb525ab-270b-46f1-a847-dd29be19aadb","embeddableConfig":{"enhancements":{},"hidePanelTitles":false,"attributes":{"state":{"datasourceStates":{"formBased":{"layers":{"c7478794-6767-4286-9d65-1c0ecd909dd8":{"columnOrder":["8289349e-6d1b-4abf-b164-0208183d2c34","041db33b-5c9c-47f3-a5d3-ef5e255d1663","041db33b-5c9c-47f3-a5d3-ef5e255d1663X0","041db33b-5c9c-47f3-a5d3-ef5e255d1663X1"],"columns":{"041db33b-5c9c-47f3-a5d3-ef5e255d1663":{"customLabel":true,"dataType":"number","isBucketed":false,"label":"% of target ($10k)","operationType":"formula","params":{"format":{"id":"percent","params":{"decimals":0}},"formula":"sum(taxful_total_price) / 10000 - 1","isFormulaBroken":false},"references":["041db33b-5c9c-47f3-a5d3-ef5e255d1663X1"],"scale":"ratio"},"041db33b-5c9c-47f3-a5d3-ef5e255d1663X0":{"customLabel":true,"dataType":"number","isBucketed":false,"label":"Part of Weekly revenue","operationType":"sum","scale":"ratio","sourceField":"taxful_total_price"},"041db33b-5c9c-47f3-a5d3-ef5e255d1663X1":{"customLabel":true,"dataType":"number","isBucketed":false,"label":"Part of Weekly revenue","operationType":"math","params":{"tinymathAst":{"args":[{"args":["041db33b-5c9c-47f3-a5d3-ef5e255d1663X0",10000],"location":{"max":32,"min":0},"name":"divide","text":"sum(taxful_total_price) / 10000 ","type":"function"},1],"location":{"max":35,"min":0},"name":"subtract","text":"sum(taxful_total_price) / 10000 - 1","type":"function"}},"references":["041db33b-5c9c-47f3-a5d3-ef5e255d1663X0"],"scale":"ratio"},"8289349e-6d1b-4abf-b164-0208183d2c34":{"dataType":"date","isBucketed":true,"label":"order_date","operationType":"date_histogram","params":{"interval":"1d","includeEmptyRows":true},"scale":"interval","sourceField":"order_date"}},"incompleteColumns":{}}}}},"filters":[],"query":{"language":"kuery","query":""},"visualization":{"axisTitlesVisibilitySettings":{"x":false,"yLeft":false,"yRight":true},"fittingFunction":"None","gridlinesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"layers":[{"accessors":["041db33b-5c9c-47f3-a5d3-ef5e255d1663"],"layerId":"c7478794-6767-4286-9d65-1c0ecd909dd8","seriesType":"bar_stacked","xAccessor":"8289349e-6d1b-4abf-b164-0208183d2c34","layerType":"data"}],"legend":{"isVisible":true,"position":"right","legendSize":"auto"},"preferredSeriesType":"bar_stacked","tickLabelsVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"valueLabels":"hide","yLeftExtent":{"mode":"full"},"yRightExtent":{"mode":"full"}}},"visualizationType":"lnsXY","references":[{"id":"ff959d40-b880-11e8-a6d9-e546fe2bba5f","name":"indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"ff959d40-b880-11e8-a6d9-e546fe2bba5f","name":"indexpattern-datasource-layer-c7478794-6767-4286-9d65-1c0ecd909dd8","type":"index-pattern"}]}},"title":"% of target revenue ($10k)"}]', timeFrom: 'now-7d', title: '[eCommerce] Revenue Dashboard', timeTo: 'now', diff --git a/src/plugins/home/server/services/sample_data/data_sets/flights/saved_objects.ts b/src/plugins/home/server/services/sample_data/data_sets/flights/saved_objects.ts index 0b072bd1a4389..3f4d7e2bc6ada 100644 --- a/src/plugins/home/server/services/sample_data/data_sets/flights/saved_objects.ts +++ b/src/plugins/home/server/services/sample_data/data_sets/flights/saved_objects.ts @@ -148,7 +148,7 @@ export const getSavedObjects = (): SavedObject[] => [ optionsJSON: '{"useMargins":true,"syncColors":false,"syncCursor":true,"syncTooltips":false,"hidePanelTitles":false}', panelsJSON: - '[{"version":"8.8.0","type":"search","gridData":{"x":0,"y":69,"w":48,"h":15,"i":"4"},"panelIndex":"4","embeddableConfig":{"enhancements":{}},"panelRefName":"panel_4"},{"version":"8.8.0","type":"lens","gridData":{"x":0,"y":16,"w":24,"h":9,"i":"7"},"panelIndex":"7","embeddableConfig":{"attributes":{"title":"[Flights] Delays & Cancellations (converted)","visualizationType":"lnsXY","type":"lens","references":[{"type":"index-pattern","id":"d3d7af60-4c81-11e8-b3d7-01146121b73d","name":"indexpattern-datasource-layer-dc8cf715-b56b-4dd7-a624-7c3ef9e2f2ce"},{"type":"index-pattern","id":"d3d7af60-4c81-11e8-b3d7-01146121b73d","name":"xy-visualization-layer-10fed425-accd-411b-a773-ee825bc3945b"}],"state":{"visualization":{"legend":{"isVisible":false,"showSingleSeries":false,"position":"bottom","shouldTruncate":true,"maxLines":1},"valueLabels":"hide","fittingFunction":"None","fillOpacity":0.5,"yLeftExtent":{"upperBound":1,"mode":"custom"},"yRightExtent":{"mode":"full"},"yLeftScale":"linear","yRightScale":"linear","axisTitlesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"tickLabelsVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"labelsOrientation":{"x":0,"yLeft":0,"yRight":0},"gridlinesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"preferredSeriesType":"bar_stacked","layers":[{"seriesType":"area","layerType":"data","layerId":"dc8cf715-b56b-4dd7-a624-7c3ef9e2f2ce","accessors":["b9d6187b-8a7e-4c49-bffd-7a60cc075a4a"],"yConfig":[{"forAccessor":"b9d6187b-8a7e-4c49-bffd-7a60cc075a4a","color":"rgba(0,156,224,1)","axisMode":"left"}],"xAccessor":"6944431b-f90a-4dab-a282-0961cb97edd1","palette":{"name":"default","type":"palette"}},{"layerId":"10fed425-accd-411b-a773-ee825bc3945b","layerType":"annotations","ignoreGlobalFilters":true,"annotations":[{"type":"query","id":"53b7dff0-4c89-11e8-a66a-6989ad5a0a39","label":"Event","key":{"type":"point_in_time"},"timeField":"timestamp","color":"#0062B1","icon":"alert","filter":{"type":"kibana_query","query":"FlightDelay:true AND Cancelled:true","language":"lucene"},"extraFields":["FlightDelay","Cancelled","Carrier"]}]}]},"query":{"query":"","language":"kuery"},"filters":[],"datasourceStates":{"formBased":{"layers":{"dc8cf715-b56b-4dd7-a624-7c3ef9e2f2ce":{"columns":{"6944431b-f90a-4dab-a282-0961cb97edd1":{"label":"timestamp","dataType":"date","operationType":"date_histogram","sourceField":"timestamp","isBucketed":true,"scale":"interval","params":{"interval":"auto","includeEmptyRows":true,"dropPartials":false}},"b9d6187b-8a7e-4c49-bffd-7a60cc075a4aX0":{"label":"Part of count(lucene=\'FlightDelay:true\') / count(kql=\'*\')","dataType":"number","operationType":"count","isBucketed":false,"scale":"ratio","sourceField":"___records___","filter":{"query":"FlightDelay:true","language":"lucene"},"params":{"emptyAsNull":false},"customLabel":true},"b9d6187b-8a7e-4c49-bffd-7a60cc075a4aX1":{"label":"Part of count(lucene=\'FlightDelay:true\') / count(kql=\'*\')","dataType":"number","operationType":"count","isBucketed":false,"scale":"ratio","sourceField":"___records___","filter":{"query":"*","language":"kuery"},"params":{"emptyAsNull":false},"customLabel":true},"b9d6187b-8a7e-4c49-bffd-7a60cc075a4aX2":{"label":"Part of count(lucene=\'FlightDelay:true\') / count(kql=\'*\')","dataType":"number","operationType":"math","isBucketed":false,"scale":"ratio","params":{"tinymathAst":{"type":"function","name":"divide","args":["b9d6187b-8a7e-4c49-bffd-7a60cc075a4aX0","b9d6187b-8a7e-4c49-bffd-7a60cc075a4aX1"],"location":{"min":0,"max":49},"text":"count(lucene=\'FlightDelay:true\') / count(kql=\'*\')"}},"references":["b9d6187b-8a7e-4c49-bffd-7a60cc075a4aX0","b9d6187b-8a7e-4c49-bffd-7a60cc075a4aX1"],"customLabel":true},"b9d6187b-8a7e-4c49-bffd-7a60cc075a4a":{"label":"Percent Delays","dataType":"number","operationType":"formula","isBucketed":false,"scale":"ratio","params":{"format":{"id":"percent"},"formula":"count(lucene=\'FlightDelay:true\') / count(kql=\'*\')","isFormulaBroken":false},"references":["b9d6187b-8a7e-4c49-bffd-7a60cc075a4aX2"],"customLabel":true}},"columnOrder":["6944431b-f90a-4dab-a282-0961cb97edd1","b9d6187b-8a7e-4c49-bffd-7a60cc075a4aX0","b9d6187b-8a7e-4c49-bffd-7a60cc075a4aX1","b9d6187b-8a7e-4c49-bffd-7a60cc075a4aX2","b9d6187b-8a7e-4c49-bffd-7a60cc075a4a"],"incompleteColumns":{}}}},"textBased":{"layers":{}}},"internalReferences":[],"adHocDataViews":{}}},"enhancements":{},"hidePanelTitles":false},"title":"[Flights] Delays & Cancellations"},{"version":"8.8.0","type":"lens","gridData":{"x":0,"y":58,"w":24,"h":11,"i":"10"},"panelIndex":"10","embeddableConfig":{"attributes":{"title":"[Flights] Delay Buckets (converted)","visualizationType":"lnsXY","type":"lens","references":[{"type":"index-pattern","id":"d3d7af60-4c81-11e8-b3d7-01146121b73d","name":"indexpattern-datasource-layer-247b176d-e81d-47dc-bbd1-4de85d098961"},{"type":"index-pattern","name":"c61f29fc-1ff3-4d46-a6c2-bde8a5b97f4a","id":"d3d7af60-4c81-11e8-b3d7-01146121b73d"}],"state":{"visualization":{"legend":{"isVisible":false,"position":"right","legendSize":"auto","shouldTruncate":true,"maxLines":1,"showSingleSeries":true},"valueLabels":"hide","curveType":"LINEAR","yTitle":"Count","yLeftExtent":{"mode":"full","enforce":true},"yLeftScale":"linear","yRightScale":"linear","axisTitlesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"tickLabelsVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"labelsOrientation":{"x":0,"yLeft":0,"yRight":-90},"gridlinesVisibilitySettings":{"x":false,"yLeft":false,"yRight":true},"preferredSeriesType":"bar_stacked","layers":[{"layerId":"247b176d-e81d-47dc-bbd1-4de85d098961","accessors":["c84f9fa9-e2a1-4845-8fcf-f5a34f5f92da"],"layerType":"data","seriesType":"bar_stacked","xAccessor":"c7936be7-e59b-424e-a912-69ba820d8e24","simpleView":false,"palette":{"type":"palette","name":"default"},"yConfig":[{"forAccessor":"c84f9fa9-e2a1-4845-8fcf-f5a34f5f92da","axisMode":"left","color":"#1F78C1"}],"xScaleType":"linear","isHistogram":true}]},"query":{"query":"","language":"kuery"},"filters":[{"meta":{"negate":true,"disabled":false,"alias":null,"type":"phrase","key":"FlightDelayMin","value":"0","params":{"query":0,"type":"phrase"},"index":"c61f29fc-1ff3-4d46-a6c2-bde8a5b97f4a"},"query":{"match":{"FlightDelayMin":{"query":0,"type":"phrase"}}},"$state":{"store":"appState"}}],"datasourceStates":{"formBased":{"layers":{"247b176d-e81d-47dc-bbd1-4de85d098961":{"columns":{"c7936be7-e59b-424e-a912-69ba820d8e24":{"label":"Flight Delay Minutes","dataType":"number","operationType":"range","sourceField":"FlightDelayMin","isBucketed":true,"scale":"interval","params":{"includeEmptyRows":false,"type":"histogram","ranges":[{"from":0,"to":1000,"label":""}],"maxBars":"auto"},"customLabel":true},"c84f9fa9-e2a1-4845-8fcf-f5a34f5f92da":{"label":"Count","dataType":"number","operationType":"count","isBucketed":false,"scale":"ratio","sourceField":"___records___","params":{"emptyAsNull":true},"customLabel":true}},"columnOrder":["c7936be7-e59b-424e-a912-69ba820d8e24","c84f9fa9-e2a1-4845-8fcf-f5a34f5f92da"],"incompleteColumns":{}}}},"textBased":{"layers":{}}},"internalReferences":[],"adHocDataViews":{}}},"enhancements":{},"hidePanelTitles":false},"title":"[Flights] Delay Buckets"},{"version":"8.8.0","type":"map","gridData":{"x":0,"y":36,"w":24,"h":22,"i":"23"},"panelIndex":"23","embeddableConfig":{"isLayerTOCOpen":true,"hiddenLayers":[],"mapCenter":{"lat":48.72307,"lon":-115.18171,"zoom":4.28},"openTOCDetails":[],"enhancements":{}},"panelRefName":"panel_23"},{"version":"8.8.0","type":"visualization","gridData":{"x":24,"y":36,"w":24,"h":22,"i":"31"},"panelIndex":"31","embeddableConfig":{"enhancements":{}},"panelRefName":"panel_31"},{"version":"8.8.0","type":"visualization","gridData":{"x":0,"y":0,"w":24,"h":8,"i":"6afc61f7-e2d5-45a3-9e7a-281160ad3eb9"},"panelIndex":"6afc61f7-e2d5-45a3-9e7a-281160ad3eb9","embeddableConfig":{"savedVis":{"title":"[Flights] Markdown Instructions","description":"","type":"markdown","params":{"fontSize":10,"openLinksInNewTab":true,"markdown":"## Sample Flight data\\nThis dashboard contains sample data for you to play with. You can view it, search it, and interact with the visualizations. For more information about Kibana, check our [docs](https://www.elastic.co/guide/en/kibana/current/index.html)."},"uiState":{},"data":{"aggs":[],"searchSource":{}}},"hidePanelTitles":true,"enhancements":{}}},{"version":"8.8.0","type":"lens","gridData":{"x":24,"y":0,"w":8,"h":8,"i":"392b4936-f753-47bc-a98d-a4e41a0a4cd4"},"panelIndex":"392b4936-f753-47bc-a98d-a4e41a0a4cd4","embeddableConfig":{"enhancements":{},"attributes":{"title":"[Flights] Total Flights","description":"","visualizationType":"lnsMetric","type":"lens","references":[{"type":"index-pattern","id":"d3d7af60-4c81-11e8-b3d7-01146121b73d","name":"indexpattern-datasource-layer-8fa993db-c147-4954-adf7-4ff264d42576"}],"state":{"visualization":{"layerId":"8fa993db-c147-4954-adf7-4ff264d42576","layerType":"data","metricAccessor":"81124c45-6ab6-42f4-8859-495d55eb8065"},"query":{"query":"","language":"kuery"},"filters":[],"datasourceStates":{"formBased":{"layers":{"8fa993db-c147-4954-adf7-4ff264d42576":{"columns":{"81124c45-6ab6-42f4-8859-495d55eb8065":{"label":"Total flights","dataType":"number","operationType":"count","isBucketed":false,"scale":"ratio","sourceField":"___records___","customLabel":true}},"columnOrder":["81124c45-6ab6-42f4-8859-495d55eb8065"],"incompleteColumns":{}}}}},"internalReferences":[],"adHocDataViews":{}}},"hidePanelTitles":true}},{"version":"8.8.0","type":"lens","gridData":{"x":32,"y":0,"w":8,"h":4,"i":"9271deff-5a61-4665-83fc-f9fdc6bf0c0b"},"panelIndex":"9271deff-5a61-4665-83fc-f9fdc6bf0c0b","embeddableConfig":{"attributes":{"title":"","visualizationType":"lnsMetric","type":"lens","references":[{"type":"index-pattern","id":"d3d7af60-4c81-11e8-b3d7-01146121b73d","name":"indexpattern-datasource-layer-b4712d43-1e84-4f5b-878d-8e38ba748317"}],"state":{"visualization":{"layerId":"b4712d43-1e84-4f5b-878d-8e38ba748317","layerType":"data","metricAccessor":"7e8fe9b1-f45c-4f3d-9561-30febcd357ec"},"query":{"query":"","language":"kuery"},"filters":[],"datasourceStates":{"formBased":{"layers":{"b4712d43-1e84-4f5b-878d-8e38ba748317":{"columns":{"7e8fe9b1-f45c-4f3d-9561-30febcd357ec":{"label":"Delayed","dataType":"number","operationType":"formula","isBucketed":false,"scale":"ratio","params":{"formula":"count(kql=\'FlightDelay : true\') / count()","isFormulaBroken":false,"format":{"id":"percent","params":{"decimals":1}}},"references":["7e8fe9b1-f45c-4f3d-9561-30febcd357ecX2"],"customLabel":true},"7e8fe9b1-f45c-4f3d-9561-30febcd357ecX0":{"label":"Part of count(kql=\'FlightDelay : true\') / count()","dataType":"number","operationType":"count","isBucketed":false,"scale":"ratio","sourceField":"___records___","filter":{"query":"FlightDelay : true","language":"kuery"},"customLabel":true},"7e8fe9b1-f45c-4f3d-9561-30febcd357ecX1":{"label":"Part of count(kql=\'FlightDelay : true\') / count()","dataType":"number","operationType":"count","isBucketed":false,"scale":"ratio","sourceField":"___records___","customLabel":true},"7e8fe9b1-f45c-4f3d-9561-30febcd357ecX2":{"label":"Part of count(kql=\'FlightDelay : true\') / count()","dataType":"number","operationType":"math","isBucketed":false,"scale":"ratio","params":{"tinymathAst":{"type":"function","name":"divide","args":["7e8fe9b1-f45c-4f3d-9561-30febcd357ecX0","7e8fe9b1-f45c-4f3d-9561-30febcd357ecX1"],"location":{"min":0,"max":41},"text":"count(kql=\'FlightDelay : true\') / count()"}},"references":["7e8fe9b1-f45c-4f3d-9561-30febcd357ecX0","7e8fe9b1-f45c-4f3d-9561-30febcd357ecX1"],"customLabel":true}},"columnOrder":["7e8fe9b1-f45c-4f3d-9561-30febcd357ec","7e8fe9b1-f45c-4f3d-9561-30febcd357ecX0","7e8fe9b1-f45c-4f3d-9561-30febcd357ecX1","7e8fe9b1-f45c-4f3d-9561-30febcd357ecX2"],"incompleteColumns":{}}}}},"internalReferences":[],"adHocDataViews":{}}},"enhancements":{}}},{"version":"8.8.0","type":"lens","gridData":{"x":40,"y":0,"w":8,"h":4,"i":"aa591c29-1a31-4ee1-a71d-b829c06fd162"},"panelIndex":"aa591c29-1a31-4ee1-a71d-b829c06fd162","embeddableConfig":{"attributes":{"title":"","visualizationType":"lnsMetric","type":"lens","references":[{"type":"index-pattern","id":"d3d7af60-4c81-11e8-b3d7-01146121b73d","name":"indexpattern-datasource-layer-b4712d43-1e84-4f5b-878d-8e38ba748317"},{"type":"index-pattern","name":"c804c161-375f-4d52-a1cc-2e98b966957d","id":"d3d7af60-4c81-11e8-b3d7-01146121b73d"}],"state":{"visualization":{"layerId":"b4712d43-1e84-4f5b-878d-8e38ba748317","layerType":"data","metricAccessor":"c7851241-5526-499a-960b-357af8c2ce5b"},"query":{"query":"","language":"kuery"},"filters":[{"meta":{"alias":null,"negate":false,"disabled":false,"type":"phrase","key":"FlightDelay","params":{"query":true},"index":"c804c161-375f-4d52-a1cc-2e98b966957d"},"query":{"match_phrase":{"FlightDelay":true}},"$state":{"store":"appState"}}],"datasourceStates":{"formBased":{"layers":{"b4712d43-1e84-4f5b-878d-8e38ba748317":{"columns":{"c7851241-5526-499a-960b-357af8c2ce5b":{"label":"Delayed vs 1 week earlier","dataType":"number","operationType":"formula","isBucketed":false,"scale":"ratio","params":{"formula":"count() / count(shift=\'1w\') - 1","isFormulaBroken":false,"format":{"id":"percent","params":{"decimals":1}}},"references":["c7851241-5526-499a-960b-357af8c2ce5bX2"],"customLabel":true},"c7851241-5526-499a-960b-357af8c2ce5bX2":{"label":"Part of Delayed","dataType":"number","operationType":"math","isBucketed":false,"scale":"ratio","params":{"tinymathAst":{"type":"function","name":"subtract","args":[{"type":"function","name":"divide","args":["c7851241-5526-499a-960b-357af8c2ce5bX0","c7851241-5526-499a-960b-357af8c2ce5bX1"],"location":{"min":0,"max":28},"text":"count() / count(shift=\'1w\') "},1],"location":{"min":0,"max":31},"text":"count() / count(shift=\'1w\') - 1"}},"references":["c7851241-5526-499a-960b-357af8c2ce5bX0","c7851241-5526-499a-960b-357af8c2ce5bX1"],"customLabel":true},"c7851241-5526-499a-960b-357af8c2ce5bX0":{"label":"Part of Delayed","dataType":"number","operationType":"count","isBucketed":false,"scale":"ratio","sourceField":"___records___","customLabel":true},"c7851241-5526-499a-960b-357af8c2ce5bX1":{"label":"Part of Delayed","dataType":"number","operationType":"count","isBucketed":false,"scale":"ratio","sourceField":"___records___","timeShift":"1w","customLabel":true}},"columnOrder":["c7851241-5526-499a-960b-357af8c2ce5b","c7851241-5526-499a-960b-357af8c2ce5bX2","c7851241-5526-499a-960b-357af8c2ce5bX0","c7851241-5526-499a-960b-357af8c2ce5bX1"],"incompleteColumns":{}}}}},"internalReferences":[],"adHocDataViews":{}}},"enhancements":{}}},{"version":"8.8.0","type":"lens","gridData":{"x":32,"y":4,"w":8,"h":4,"i":"b766e3b8-4544-46ed-99e6-9ecc4847e2a2"},"panelIndex":"b766e3b8-4544-46ed-99e6-9ecc4847e2a2","embeddableConfig":{"attributes":{"title":"","visualizationType":"lnsMetric","type":"lens","references":[{"type":"index-pattern","id":"d3d7af60-4c81-11e8-b3d7-01146121b73d","name":"indexpattern-datasource-layer-b4712d43-1e84-4f5b-878d-8e38ba748317"}],"state":{"visualization":{"layerId":"b4712d43-1e84-4f5b-878d-8e38ba748317","layerType":"data","metricAccessor":"7e8fe9b1-f45c-4f3d-9561-30febcd357ec"},"query":{"query":"","language":"kuery"},"filters":[],"datasourceStates":{"formBased":{"layers":{"b4712d43-1e84-4f5b-878d-8e38ba748317":{"columns":{"7e8fe9b1-f45c-4f3d-9561-30febcd357ec":{"label":"Cancelled","dataType":"number","operationType":"formula","isBucketed":false,"scale":"ratio","params":{"formula":"count(kql=\'Cancelled : true\') / count()","isFormulaBroken":false,"format":{"id":"percent","params":{"decimals":1}}},"references":["7e8fe9b1-f45c-4f3d-9561-30febcd357ecX2"],"customLabel":true},"7e8fe9b1-f45c-4f3d-9561-30febcd357ecX0":{"label":"Part of Cancelled","dataType":"number","operationType":"count","isBucketed":false,"scale":"ratio","sourceField":"___records___","filter":{"query":"Cancelled : true","language":"kuery"},"customLabel":true},"7e8fe9b1-f45c-4f3d-9561-30febcd357ecX1":{"label":"Part of Cancelled","dataType":"number","operationType":"count","isBucketed":false,"scale":"ratio","sourceField":"___records___","customLabel":true},"7e8fe9b1-f45c-4f3d-9561-30febcd357ecX2":{"label":"Part of Cancelled","dataType":"number","operationType":"math","isBucketed":false,"scale":"ratio","params":{"tinymathAst":{"type":"function","name":"divide","args":["7e8fe9b1-f45c-4f3d-9561-30febcd357ecX0","7e8fe9b1-f45c-4f3d-9561-30febcd357ecX1"],"location":{"min":0,"max":39},"text":"count(kql=\'Cancelled : true\') / count()"}},"references":["7e8fe9b1-f45c-4f3d-9561-30febcd357ecX0","7e8fe9b1-f45c-4f3d-9561-30febcd357ecX1"],"customLabel":true}},"columnOrder":["7e8fe9b1-f45c-4f3d-9561-30febcd357ec","7e8fe9b1-f45c-4f3d-9561-30febcd357ecX0","7e8fe9b1-f45c-4f3d-9561-30febcd357ecX1","7e8fe9b1-f45c-4f3d-9561-30febcd357ecX2"],"incompleteColumns":{}}}}},"internalReferences":[],"adHocDataViews":{}}},"enhancements":{}}},{"version":"8.8.0","type":"lens","gridData":{"x":40,"y":4,"w":8,"h":4,"i":"2e33ade5-96e5-40b4-b460-493e5d4fa834"},"panelIndex":"2e33ade5-96e5-40b4-b460-493e5d4fa834","embeddableConfig":{"attributes":{"title":"","visualizationType":"lnsMetric","type":"lens","references":[{"type":"index-pattern","id":"d3d7af60-4c81-11e8-b3d7-01146121b73d","name":"indexpattern-datasource-layer-b4712d43-1e84-4f5b-878d-8e38ba748317"},{"type":"index-pattern","name":"14cea722-a629-4c69-a06d-94a4a4c9a718","id":"d3d7af60-4c81-11e8-b3d7-01146121b73d"}],"state":{"visualization":{"layerId":"b4712d43-1e84-4f5b-878d-8e38ba748317","layerType":"data","metricAccessor":"c7851241-5526-499a-960b-357af8c2ce5b"},"query":{"query":"","language":"kuery"},"filters":[{"meta":{"alias":null,"negate":false,"disabled":false,"type":"phrase","key":"Cancelled","params":{"query":true},"index":"14cea722-a629-4c69-a06d-94a4a4c9a718"},"query":{"match_phrase":{"Cancelled":true}},"$state":{"store":"appState"}}],"datasourceStates":{"formBased":{"layers":{"b4712d43-1e84-4f5b-878d-8e38ba748317":{"columns":{"c7851241-5526-499a-960b-357af8c2ce5b":{"label":"Cancelled vs 1 week earlier","dataType":"number","operationType":"formula","isBucketed":false,"scale":"ratio","params":{"formula":"count() / count(shift=\'1w\') - 1","isFormulaBroken":false,"format":{"id":"percent","params":{"decimals":1}}},"references":["c7851241-5526-499a-960b-357af8c2ce5bX2"],"customLabel":true},"c7851241-5526-499a-960b-357af8c2ce5bX2":{"label":"Part of Delayed vs 1 week earlier","dataType":"number","operationType":"math","isBucketed":false,"scale":"ratio","params":{"tinymathAst":{"type":"function","name":"subtract","args":[{"type":"function","name":"divide","args":["c7851241-5526-499a-960b-357af8c2ce5bX0","c7851241-5526-499a-960b-357af8c2ce5bX1"],"location":{"min":0,"max":28},"text":"count() / count(shift=\'1w\') "},1],"location":{"min":0,"max":31},"text":"count() / count(shift=\'1w\') - 1"}},"references":["c7851241-5526-499a-960b-357af8c2ce5bX0","c7851241-5526-499a-960b-357af8c2ce5bX1"],"customLabel":true},"c7851241-5526-499a-960b-357af8c2ce5bX0":{"label":"Part of Delayed vs 1 week earlier","dataType":"number","operationType":"count","isBucketed":false,"scale":"ratio","sourceField":"___records___","customLabel":true},"c7851241-5526-499a-960b-357af8c2ce5bX1":{"label":"Part of Delayed vs 1 week earlier","dataType":"number","operationType":"count","isBucketed":false,"scale":"ratio","sourceField":"___records___","timeShift":"1w","customLabel":true}},"columnOrder":["c7851241-5526-499a-960b-357af8c2ce5b","c7851241-5526-499a-960b-357af8c2ce5bX2","c7851241-5526-499a-960b-357af8c2ce5bX0","c7851241-5526-499a-960b-357af8c2ce5bX1"],"incompleteColumns":{}}}}},"internalReferences":[],"adHocDataViews":{}}},"enhancements":{}}},{"version":"8.8.0","type":"lens","gridData":{"x":0,"y":8,"w":24,"h":8,"i":"086ac2e9-dd16-4b45-92b8-1e43ff7e3f65"},"panelIndex":"086ac2e9-dd16-4b45-92b8-1e43ff7e3f65","embeddableConfig":{"attributes":{"title":"","type":"lens","visualizationType":"lnsXY","state":{"datasourceStates":{"formBased":{"layers":{"03c34665-471c-49c7-acf1-5a11f517421c":{"columns":{"a5b94e30-4e77-4b0a-9187-1d8b13de1456":{"label":"timestamp","dataType":"date","operationType":"date_histogram","sourceField":"timestamp","isBucketed":true,"scale":"interval","params":{"interval":"auto","includeEmptyRows":true}},"3e267327-7317-4310-aee3-320e0f7c1e70":{"label":"Count of records","dataType":"number","operationType":"count","isBucketed":false,"scale":"ratio","sourceField":"___records___"}},"columnOrder":["a5b94e30-4e77-4b0a-9187-1d8b13de1456","3e267327-7317-4310-aee3-320e0f7c1e70"],"incompleteColumns":{}}}}},"visualization":{"legend":{"isVisible":true,"position":"right","legendSize":"auto"},"valueLabels":"hide","fittingFunction":"None","yLeftExtent":{"mode":"full"},"yRightExtent":{"mode":"custom","lowerBound":0,"upperBound":1},"axisTitlesVisibilitySettings":{"x":false,"yLeft":false,"yRight":true},"tickLabelsVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"gridlinesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"preferredSeriesType":"bar_stacked","layers":[{"layerId":"03c34665-471c-49c7-acf1-5a11f517421c","accessors":["3e267327-7317-4310-aee3-320e0f7c1e70"],"position":"top","seriesType":"bar_stacked","showGridlines":false,"xAccessor":"a5b94e30-4e77-4b0a-9187-1d8b13de1456","layerType":"data"}]},"query":{"query":"","language":"kuery"},"filters":[]},"references":[{"id":"d3d7af60-4c81-11e8-b3d7-01146121b73d","name":"indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"d3d7af60-4c81-11e8-b3d7-01146121b73d","name":"indexpattern-datasource-layer-03c34665-471c-49c7-acf1-5a11f517421c","type":"index-pattern"}]},"hidePanelTitles":false,"enhancements":{}},"title":"[Flights] Flight count"},{"version":"8.8.0","type":"lens","gridData":{"x":24,"y":8,"w":24,"h":28,"i":"fb86b32f-fb7a-45cf-9511-f366fef51bbd"},"panelIndex":"fb86b32f-fb7a-45cf-9511-f366fef51bbd","embeddableConfig":{"attributes":{"title":"Cities by delay, cancellation","type":"lens","visualizationType":"lnsDatatable","state":{"datasourceStates":{"formBased":{"layers":{"f26e8f7a-4118-4227-bea0-5c02d8b270f7":{"columns":{"3dd24cb4-45ef-4dd8-b22a-d7b802cb6da0":{"label":"Top values of OriginCityName","dataType":"string","operationType":"terms","scale":"ordinal","sourceField":"OriginCityName","isBucketed":true,"params":{"size":1000,"orderBy":{"type":"alphabetical","fallback":true},"orderDirection":"asc","otherBucket":true,"missingBucket":false}},"52f6f2e9-6242-4c44-be63-b799150e7e60X0":{"label":"Part of Delay %","dataType":"number","operationType":"count","isBucketed":false,"scale":"ratio","sourceField":"___records___","filter":{"query":"FlightDelay : true ","language":"kuery"},"customLabel":true},"52f6f2e9-6242-4c44-be63-b799150e7e60X1":{"label":"Part of Delay %","dataType":"number","operationType":"count","isBucketed":false,"scale":"ratio","sourceField":"___records___","customLabel":true},"52f6f2e9-6242-4c44-be63-b799150e7e60X2":{"label":"Part of Delay %","dataType":"number","operationType":"math","isBucketed":false,"scale":"ratio","params":{"tinymathAst":{"type":"function","name":"divide","args":["52f6f2e9-6242-4c44-be63-b799150e7e60X0","52f6f2e9-6242-4c44-be63-b799150e7e60X1"],"location":{"min":0,"max":42},"text":"count(kql=\'FlightDelay : true \') / count()"}},"references":["52f6f2e9-6242-4c44-be63-b799150e7e60X0","52f6f2e9-6242-4c44-be63-b799150e7e60X1"],"customLabel":true},"52f6f2e9-6242-4c44-be63-b799150e7e60":{"label":"Delay %","dataType":"number","operationType":"formula","isBucketed":false,"scale":"ratio","params":{"formula":"count(kql=\'FlightDelay : true \') / count()","isFormulaBroken":false,"format":{"id":"percent","params":{"decimals":0}}},"references":["52f6f2e9-6242-4c44-be63-b799150e7e60X2"],"customLabel":true},"7b9f3ece-9da3-4c27-b582-d3f8e8cc31d6X0":{"label":"Part of Cancel %","dataType":"number","operationType":"count","isBucketed":false,"scale":"ratio","sourceField":"___records___","filter":{"query":"Cancelled: true","language":"kuery"},"customLabel":true},"7b9f3ece-9da3-4c27-b582-d3f8e8cc31d6X1":{"label":"Part of Cancel %","dataType":"number","operationType":"count","isBucketed":false,"scale":"ratio","sourceField":"___records___","customLabel":true},"7b9f3ece-9da3-4c27-b582-d3f8e8cc31d6X2":{"label":"Part of Cancel %","dataType":"number","operationType":"math","isBucketed":false,"scale":"ratio","params":{"tinymathAst":{"type":"function","name":"divide","args":["7b9f3ece-9da3-4c27-b582-d3f8e8cc31d6X0","7b9f3ece-9da3-4c27-b582-d3f8e8cc31d6X1"],"location":{"min":0,"max":38},"text":"count(kql=\'Cancelled: true\') / count()"}},"references":["7b9f3ece-9da3-4c27-b582-d3f8e8cc31d6X0","7b9f3ece-9da3-4c27-b582-d3f8e8cc31d6X1"],"customLabel":true},"7b9f3ece-9da3-4c27-b582-d3f8e8cc31d6":{"label":"Cancel %","dataType":"number","operationType":"formula","isBucketed":false,"scale":"ratio","params":{"formula":"count(kql=\'Cancelled: true\') / count()","isFormulaBroken":false,"format":{"id":"percent","params":{"decimals":0}}},"references":["7b9f3ece-9da3-4c27-b582-d3f8e8cc31d6X2"],"customLabel":true}},"columnOrder":["3dd24cb4-45ef-4dd8-b22a-d7b802cb6da0","52f6f2e9-6242-4c44-be63-b799150e7e60","52f6f2e9-6242-4c44-be63-b799150e7e60X0","52f6f2e9-6242-4c44-be63-b799150e7e60X1","52f6f2e9-6242-4c44-be63-b799150e7e60X2","7b9f3ece-9da3-4c27-b582-d3f8e8cc31d6X0","7b9f3ece-9da3-4c27-b582-d3f8e8cc31d6X1","7b9f3ece-9da3-4c27-b582-d3f8e8cc31d6X2","7b9f3ece-9da3-4c27-b582-d3f8e8cc31d6"],"incompleteColumns":{}}}}},"visualization":{"columns":[{"isTransposed":false,"columnId":"3dd24cb4-45ef-4dd8-b22a-d7b802cb6da0","width":262.75},{"columnId":"52f6f2e9-6242-4c44-be63-b799150e7e60","isTransposed":false,"width":302.5,"colorMode":"cell","palette":{"name":"custom","type":"palette","params":{"steps":5,"stops":[{"color":"#f7e0b8","stop":0.6},{"color":"#e7664c","stop":1}],"name":"custom","colorStops":[{"color":"#f7e0b8","stop":0.2},{"color":"#e7664c","stop":0.6}],"rangeType":"number","rangeMin":0.2,"rangeMax":0.6}},"alignment":"center"},{"columnId":"7b9f3ece-9da3-4c27-b582-d3f8e8cc31d6","isTransposed":false,"alignment":"center","colorMode":"cell","palette":{"name":"custom","type":"palette","params":{"steps":5,"stops":[{"color":"#f7e0b8","stop":0.6},{"color":"#e7664c","stop":0.6666666666666666}],"rangeType":"number","name":"custom","colorStops":[{"color":"#f7e0b8","stop":0.2},{"color":"#e7664c","stop":0.6}],"rangeMin":0.2,"rangeMax":0.6}}}],"layerId":"f26e8f7a-4118-4227-bea0-5c02d8b270f7","sorting":{"columnId":"52f6f2e9-6242-4c44-be63-b799150e7e60","direction":"desc"},"layerType":"data","rowHeight":"single","rowHeightLines":1},"query":{"query":"","language":"kuery"},"filters":[]},"references":[{"id":"d3d7af60-4c81-11e8-b3d7-01146121b73d","name":"indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"d3d7af60-4c81-11e8-b3d7-01146121b73d","name":"indexpattern-datasource-layer-f26e8f7a-4118-4227-bea0-5c02d8b270f7","type":"index-pattern"}]},"enhancements":{},"hidePanelTitles":false},"title":"[Flights] Most delayed cities"},{"version":"8.8.0","type":"lens","gridData":{"x":0,"y":25,"w":24,"h":11,"i":"0cc42484-16f7-42ec-b38c-9bf8be69cde7"},"panelIndex":"0cc42484-16f7-42ec-b38c-9bf8be69cde7","embeddableConfig":{"attributes":{"title":"","type":"lens","visualizationType":"lnsXY","state":{"datasourceStates":{"formBased":{"layers":{"e80cc05e-c52a-4e5f-ac71-4b37274867f5":{"columns":{"caf7421e-93a3-439e-ab0a-fbdead93c21c":{"label":"Top values of FlightDelayType","dataType":"string","operationType":"terms","scale":"ordinal","sourceField":"FlightDelayType","isBucketed":true,"params":{"size":10,"orderBy":{"type":"column","columnId":"0233d302-ec81-4fbe-96cb-7fac84cf035c"},"orderDirection":"desc","otherBucket":true,"missingBucket":false}},"13ec79e3-9d73-4536-9056-3d92802bb30a":{"label":"timestamp","dataType":"date","operationType":"date_histogram","sourceField":"timestamp","isBucketed":true,"scale":"interval","params":{"interval":"auto","includeEmptyRows":true}},"0233d302-ec81-4fbe-96cb-7fac84cf035c":{"label":"Count of records","dataType":"number","operationType":"count","isBucketed":false,"scale":"ratio","sourceField":"___records___"}},"columnOrder":["caf7421e-93a3-439e-ab0a-fbdead93c21c","13ec79e3-9d73-4536-9056-3d92802bb30a","0233d302-ec81-4fbe-96cb-7fac84cf035c"],"incompleteColumns":{}}}}},"visualization":{"legend":{"isVisible":true,"position":"bottom","legendSize":"auto"},"valueLabels":"hide","fittingFunction":"None","yLeftExtent":{"mode":"full"},"yRightExtent":{"mode":"full"},"axisTitlesVisibilitySettings":{"x":true,"yLeft":false,"yRight":true},"tickLabelsVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"gridlinesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"preferredSeriesType":"bar_percentage_stacked","layers":[{"layerId":"e80cc05e-c52a-4e5f-ac71-4b37274867f5","accessors":["0233d302-ec81-4fbe-96cb-7fac84cf035c"],"position":"top","seriesType":"bar_percentage_stacked","showGridlines":false,"palette":{"type":"palette","name":"cool"},"xAccessor":"13ec79e3-9d73-4536-9056-3d92802bb30a","splitAccessor":"caf7421e-93a3-439e-ab0a-fbdead93c21c","layerType":"data"}]},"query":{"query":"","language":"kuery"},"filters":[]},"references":[{"id":"d3d7af60-4c81-11e8-b3d7-01146121b73d","name":"indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"d3d7af60-4c81-11e8-b3d7-01146121b73d","name":"indexpattern-datasource-layer-e80cc05e-c52a-4e5f-ac71-4b37274867f5","type":"index-pattern"}]},"hidePanelTitles":false,"enhancements":{}},"title":"[Flights] Delay Type"},{"version":"8.8.0","type":"lens","gridData":{"x":24,"y":58,"w":12,"h":11,"i":"5d53db36-2d5a-4adc-af7b-cec4c1a294e0"},"panelIndex":"5d53db36-2d5a-4adc-af7b-cec4c1a294e0","embeddableConfig":{"attributes":{"title":"","type":"lens","visualizationType":"lnsPie","state":{"datasourceStates":{"formBased":{"layers":{"0c8e136b-a822-4fb3-836d-e06cbea4eea4":{"columns":{"d1cee8bf-34cf-4141-99d7-ff043ee77b56":{"label":"Top values of FlightDelayType","dataType":"string","operationType":"terms","scale":"ordinal","sourceField":"FlightDelayType","isBucketed":true,"params":{"size":10,"orderBy":{"type":"column","columnId":"aa152ace-ee2d-447b-b86d-459bef4d7880"},"orderDirection":"desc","otherBucket":true,"missingBucket":false}},"aa152ace-ee2d-447b-b86d-459bef4d7880":{"label":"Count of records","dataType":"number","operationType":"count","isBucketed":false,"scale":"ratio","sourceField":"___records___"}},"columnOrder":["d1cee8bf-34cf-4141-99d7-ff043ee77b56","aa152ace-ee2d-447b-b86d-459bef4d7880"],"incompleteColumns":{}}}}},"visualization":{"shape":"pie","palette":{"type":"palette","name":"cool"},"layers":[{"layerId":"0c8e136b-a822-4fb3-836d-e06cbea4eea4","numberDisplay":"percent","categoryDisplay":"default","legendDisplay":"default","nestedLegend":false,"layerType":"data","legendSize":"auto","primaryGroups":["d1cee8bf-34cf-4141-99d7-ff043ee77b56"],"metrics":["aa152ace-ee2d-447b-b86d-459bef4d7880"]}]},"query":{"query":"","language":"kuery"},"filters":[{"meta":{"type":"phrase","key":"FlightDelayType","params":{"query":"No Delay"},"disabled":false,"negate":true,"alias":null,"index":"filter-index-pattern-0"},"query":{"match_phrase":{"FlightDelayType":"No Delay"}},"$state":{"store":"appState"}}]},"references":[{"id":"d3d7af60-4c81-11e8-b3d7-01146121b73d","name":"indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"d3d7af60-4c81-11e8-b3d7-01146121b73d","name":"indexpattern-datasource-layer-0c8e136b-a822-4fb3-836d-e06cbea4eea4","type":"index-pattern"},{"id":"d3d7af60-4c81-11e8-b3d7-01146121b73d","name":"filter-index-pattern-0","type":"index-pattern"}]},"enhancements":{},"hidePanelTitles":false},"title":"[Flights] Delay Type"},{"version":"8.8.0","type":"lens","gridData":{"x":36,"y":58,"w":12,"h":11,"i":"ecd89a7c-9124-4472-bdc6-9bdbd70d45d5"},"panelIndex":"ecd89a7c-9124-4472-bdc6-9bdbd70d45d5","embeddableConfig":{"attributes":{"title":"","visualizationType":"lnsXY","type":"lens","references":[{"type":"index-pattern","id":"d3d7af60-4c81-11e8-b3d7-01146121b73d","name":"indexpattern-datasource-layer-dffd86e7-01a9-4990-b974-3706608b5532"}],"state":{"visualization":{"title":"Empty XY chart","legend":{"isVisible":true,"position":"right"},"valueLabels":"hide","preferredSeriesType":"bar_horizontal","layers":[{"layerId":"dffd86e7-01a9-4990-b974-3706608b5532","accessors":["9d212159-afac-41f5-9303-5fb62ff04ba3"],"position":"top","seriesType":"bar_horizontal","showGridlines":false,"layerType":"data","splitAccessor":"d99ad4d7-26ff-4d65-a8ce-34656fdafa0a","palette":{"type":"palette","name":"temperature"}}]},"query":{"query":"","language":"kuery"},"filters":[],"datasourceStates":{"formBased":{"layers":{"dffd86e7-01a9-4990-b974-3706608b5532":{"columns":{"9d212159-afac-41f5-9303-5fb62ff04ba3":{"label":"Count of records","dataType":"number","operationType":"count","isBucketed":false,"scale":"ratio","sourceField":"___records___","params":{"emptyAsNull":true}},"d99ad4d7-26ff-4d65-a8ce-34656fdafa0a":{"label":"Top 10 values of DestWeather","dataType":"string","operationType":"terms","scale":"ordinal","sourceField":"DestWeather","isBucketed":true,"params":{"size":10,"orderBy":{"type":"column","columnId":"9d212159-afac-41f5-9303-5fb62ff04ba3"},"orderDirection":"desc","otherBucket":true,"missingBucket":false,"parentFormat":{"id":"terms"},"include":[],"exclude":[],"includeIsRegex":false,"excludeIsRegex":false}}},"columnOrder":["d99ad4d7-26ff-4d65-a8ce-34656fdafa0a","9d212159-afac-41f5-9303-5fb62ff04ba3"],"sampling":1,"incompleteColumns":{}}}},"textBased":{"layers":{}}},"internalReferences":[],"adHocDataViews":{}}},"enhancements":{}}}]', + '[{"version":"8.8.0","type":"search","gridData":{"x":0,"y":69,"w":48,"h":15,"i":"4"},"panelIndex":"4","embeddableConfig":{"enhancements":{}},"panelRefName":"panel_4"},{"version":"8.8.0","type":"lens","gridData":{"x":0,"y":16,"w":24,"h":9,"i":"7"},"panelIndex":"7","embeddableConfig":{"attributes":{"title":"[Flights] Delays & Cancellations (converted)","visualizationType":"lnsXY","type":"lens","references":[{"type":"index-pattern","id":"d3d7af60-4c81-11e8-b3d7-01146121b73d","name":"indexpattern-datasource-layer-dc8cf715-b56b-4dd7-a624-7c3ef9e2f2ce"},{"type":"index-pattern","id":"d3d7af60-4c81-11e8-b3d7-01146121b73d","name":"xy-visualization-layer-10fed425-accd-411b-a773-ee825bc3945b"}],"state":{"visualization":{"legend":{"isVisible":false,"showSingleSeries":false,"position":"bottom","shouldTruncate":true,"maxLines":1},"valueLabels":"hide","fittingFunction":"None","fillOpacity":0.5,"yLeftExtent":{"upperBound":1,"mode":"custom"},"yRightExtent":{"mode":"full"},"yLeftScale":"linear","yRightScale":"linear","axisTitlesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"tickLabelsVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"labelsOrientation":{"x":0,"yLeft":0,"yRight":0},"gridlinesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"preferredSeriesType":"bar_stacked","layers":[{"seriesType":"area","layerType":"data","layerId":"dc8cf715-b56b-4dd7-a624-7c3ef9e2f2ce","accessors":["b9d6187b-8a7e-4c49-bffd-7a60cc075a4a"],"yConfig":[{"forAccessor":"b9d6187b-8a7e-4c49-bffd-7a60cc075a4a","axisMode":"left"}],"xAccessor":"6944431b-f90a-4dab-a282-0961cb97edd1","palette":{"name":"default","type":"palette"}},{"layerId":"10fed425-accd-411b-a773-ee825bc3945b","layerType":"annotations","ignoreGlobalFilters":true,"annotations":[{"type":"query","id":"53b7dff0-4c89-11e8-a66a-6989ad5a0a39","label":"Event","key":{"type":"point_in_time"},"timeField":"timestamp","color":"#0062B1","icon":"alert","filter":{"type":"kibana_query","query":"FlightDelay:true AND Cancelled:true","language":"lucene"},"extraFields":["FlightDelay","Cancelled","Carrier"]}]}]},"query":{"query":"","language":"kuery"},"filters":[],"datasourceStates":{"formBased":{"layers":{"dc8cf715-b56b-4dd7-a624-7c3ef9e2f2ce":{"columns":{"6944431b-f90a-4dab-a282-0961cb97edd1":{"label":"timestamp","dataType":"date","operationType":"date_histogram","sourceField":"timestamp","isBucketed":true,"scale":"interval","params":{"interval":"auto","includeEmptyRows":true,"dropPartials":false}},"b9d6187b-8a7e-4c49-bffd-7a60cc075a4aX0":{"label":"Part of count(lucene=\'FlightDelay:true\') / count(kql=\'*\')","dataType":"number","operationType":"count","isBucketed":false,"scale":"ratio","sourceField":"___records___","filter":{"query":"FlightDelay:true","language":"lucene"},"params":{"emptyAsNull":false},"customLabel":true},"b9d6187b-8a7e-4c49-bffd-7a60cc075a4aX1":{"label":"Part of count(lucene=\'FlightDelay:true\') / count(kql=\'*\')","dataType":"number","operationType":"count","isBucketed":false,"scale":"ratio","sourceField":"___records___","filter":{"query":"*","language":"kuery"},"params":{"emptyAsNull":false},"customLabel":true},"b9d6187b-8a7e-4c49-bffd-7a60cc075a4aX2":{"label":"Part of count(lucene=\'FlightDelay:true\') / count(kql=\'*\')","dataType":"number","operationType":"math","isBucketed":false,"scale":"ratio","params":{"tinymathAst":{"type":"function","name":"divide","args":["b9d6187b-8a7e-4c49-bffd-7a60cc075a4aX0","b9d6187b-8a7e-4c49-bffd-7a60cc075a4aX1"],"location":{"min":0,"max":49},"text":"count(lucene=\'FlightDelay:true\') / count(kql=\'*\')"}},"references":["b9d6187b-8a7e-4c49-bffd-7a60cc075a4aX0","b9d6187b-8a7e-4c49-bffd-7a60cc075a4aX1"],"customLabel":true},"b9d6187b-8a7e-4c49-bffd-7a60cc075a4a":{"label":"Percent Delays","dataType":"number","operationType":"formula","isBucketed":false,"scale":"ratio","params":{"format":{"id":"percent"},"formula":"count(lucene=\'FlightDelay:true\') / count(kql=\'*\')","isFormulaBroken":false},"references":["b9d6187b-8a7e-4c49-bffd-7a60cc075a4aX2"],"customLabel":true}},"columnOrder":["6944431b-f90a-4dab-a282-0961cb97edd1","b9d6187b-8a7e-4c49-bffd-7a60cc075a4aX0","b9d6187b-8a7e-4c49-bffd-7a60cc075a4aX1","b9d6187b-8a7e-4c49-bffd-7a60cc075a4aX2","b9d6187b-8a7e-4c49-bffd-7a60cc075a4a"],"incompleteColumns":{}}}},"textBased":{"layers":{}}},"internalReferences":[],"adHocDataViews":{}}},"enhancements":{},"hidePanelTitles":false},"title":"[Flights] Delays & Cancellations"},{"version":"8.8.0","type":"lens","gridData":{"x":0,"y":58,"w":24,"h":11,"i":"10"},"panelIndex":"10","embeddableConfig":{"attributes":{"title":"[Flights] Delay Buckets (converted)","visualizationType":"lnsXY","type":"lens","references":[{"type":"index-pattern","id":"d3d7af60-4c81-11e8-b3d7-01146121b73d","name":"indexpattern-datasource-layer-247b176d-e81d-47dc-bbd1-4de85d098961"},{"type":"index-pattern","name":"c61f29fc-1ff3-4d46-a6c2-bde8a5b97f4a","id":"d3d7af60-4c81-11e8-b3d7-01146121b73d"}],"state":{"visualization":{"legend":{"isVisible":false,"position":"right","legendSize":"auto","shouldTruncate":true,"maxLines":1,"showSingleSeries":true},"valueLabels":"hide","curveType":"LINEAR","yTitle":"Count","yLeftExtent":{"mode":"full","enforce":true},"yLeftScale":"linear","yRightScale":"linear","axisTitlesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"tickLabelsVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"labelsOrientation":{"x":0,"yLeft":0,"yRight":-90},"gridlinesVisibilitySettings":{"x":false,"yLeft":false,"yRight":true},"preferredSeriesType":"bar_stacked","layers":[{"layerId":"247b176d-e81d-47dc-bbd1-4de85d098961","accessors":["c84f9fa9-e2a1-4845-8fcf-f5a34f5f92da"],"layerType":"data","seriesType":"bar_stacked","xAccessor":"c7936be7-e59b-424e-a912-69ba820d8e24","simpleView":false,"palette":{"type":"palette","name":"default"},"yConfig":[{"forAccessor":"c84f9fa9-e2a1-4845-8fcf-f5a34f5f92da","axisMode":"left","color":"#1F78C1"}],"xScaleType":"linear","isHistogram":true}]},"query":{"query":"","language":"kuery"},"filters":[{"meta":{"negate":true,"disabled":false,"alias":null,"type":"phrase","key":"FlightDelayMin","value":"0","params":{"query":0,"type":"phrase"},"index":"c61f29fc-1ff3-4d46-a6c2-bde8a5b97f4a"},"query":{"match":{"FlightDelayMin":{"query":0,"type":"phrase"}}},"$state":{"store":"appState"}}],"datasourceStates":{"formBased":{"layers":{"247b176d-e81d-47dc-bbd1-4de85d098961":{"columns":{"c7936be7-e59b-424e-a912-69ba820d8e24":{"label":"Flight Delay Minutes","dataType":"number","operationType":"range","sourceField":"FlightDelayMin","isBucketed":true,"scale":"interval","params":{"includeEmptyRows":false,"type":"histogram","ranges":[{"from":0,"to":1000,"label":""}],"maxBars":"auto"},"customLabel":true},"c84f9fa9-e2a1-4845-8fcf-f5a34f5f92da":{"label":"Count","dataType":"number","operationType":"count","isBucketed":false,"scale":"ratio","sourceField":"___records___","params":{"emptyAsNull":true},"customLabel":true}},"columnOrder":["c7936be7-e59b-424e-a912-69ba820d8e24","c84f9fa9-e2a1-4845-8fcf-f5a34f5f92da"],"incompleteColumns":{}}}},"textBased":{"layers":{}}},"internalReferences":[],"adHocDataViews":{}}},"enhancements":{},"hidePanelTitles":false},"title":"[Flights] Delay Buckets"},{"version":"8.8.0","type":"map","gridData":{"x":0,"y":36,"w":24,"h":22,"i":"23"},"panelIndex":"23","embeddableConfig":{"isLayerTOCOpen":true,"hiddenLayers":[],"mapCenter":{"lat":48.72307,"lon":-115.18171,"zoom":4.28},"openTOCDetails":[],"enhancements":{}},"panelRefName":"panel_23"},{"version":"8.8.0","type":"visualization","gridData":{"x":24,"y":36,"w":24,"h":22,"i":"31"},"panelIndex":"31","embeddableConfig":{"enhancements":{}},"panelRefName":"panel_31"},{"version":"8.8.0","type":"visualization","gridData":{"x":0,"y":0,"w":24,"h":8,"i":"6afc61f7-e2d5-45a3-9e7a-281160ad3eb9"},"panelIndex":"6afc61f7-e2d5-45a3-9e7a-281160ad3eb9","embeddableConfig":{"savedVis":{"title":"[Flights] Markdown Instructions","description":"","type":"markdown","params":{"fontSize":10,"openLinksInNewTab":true,"markdown":"## Sample Flight data\\nThis dashboard contains sample data for you to play with. You can view it, search it, and interact with the visualizations. For more information about Kibana, check our [docs](https://www.elastic.co/guide/en/kibana/current/index.html)."},"uiState":{},"data":{"aggs":[],"searchSource":{}}},"hidePanelTitles":true,"enhancements":{}}},{"version":"8.8.0","type":"lens","gridData":{"x":24,"y":0,"w":8,"h":8,"i":"392b4936-f753-47bc-a98d-a4e41a0a4cd4"},"panelIndex":"392b4936-f753-47bc-a98d-a4e41a0a4cd4","embeddableConfig":{"enhancements":{},"attributes":{"title":"[Flights] Total Flights","description":"","visualizationType":"lnsMetric","type":"lens","references":[{"type":"index-pattern","id":"d3d7af60-4c81-11e8-b3d7-01146121b73d","name":"indexpattern-datasource-layer-8fa993db-c147-4954-adf7-4ff264d42576"}],"state":{"visualization":{"layerId":"8fa993db-c147-4954-adf7-4ff264d42576","layerType":"data","metricAccessor":"81124c45-6ab6-42f4-8859-495d55eb8065"},"query":{"query":"","language":"kuery"},"filters":[],"datasourceStates":{"formBased":{"layers":{"8fa993db-c147-4954-adf7-4ff264d42576":{"columns":{"81124c45-6ab6-42f4-8859-495d55eb8065":{"label":"Total flights","dataType":"number","operationType":"count","isBucketed":false,"scale":"ratio","sourceField":"___records___","customLabel":true}},"columnOrder":["81124c45-6ab6-42f4-8859-495d55eb8065"],"incompleteColumns":{}}}}},"internalReferences":[],"adHocDataViews":{}}},"hidePanelTitles":true}},{"version":"8.8.0","type":"lens","gridData":{"x":32,"y":0,"w":8,"h":4,"i":"9271deff-5a61-4665-83fc-f9fdc6bf0c0b"},"panelIndex":"9271deff-5a61-4665-83fc-f9fdc6bf0c0b","embeddableConfig":{"attributes":{"title":"","visualizationType":"lnsMetric","type":"lens","references":[{"type":"index-pattern","id":"d3d7af60-4c81-11e8-b3d7-01146121b73d","name":"indexpattern-datasource-layer-b4712d43-1e84-4f5b-878d-8e38ba748317"}],"state":{"visualization":{"layerId":"b4712d43-1e84-4f5b-878d-8e38ba748317","layerType":"data","metricAccessor":"7e8fe9b1-f45c-4f3d-9561-30febcd357ec"},"query":{"query":"","language":"kuery"},"filters":[],"datasourceStates":{"formBased":{"layers":{"b4712d43-1e84-4f5b-878d-8e38ba748317":{"columns":{"7e8fe9b1-f45c-4f3d-9561-30febcd357ec":{"label":"Delayed","dataType":"number","operationType":"formula","isBucketed":false,"scale":"ratio","params":{"formula":"count(kql=\'FlightDelay : true\') / count()","isFormulaBroken":false,"format":{"id":"percent","params":{"decimals":1}}},"references":["7e8fe9b1-f45c-4f3d-9561-30febcd357ecX2"],"customLabel":true},"7e8fe9b1-f45c-4f3d-9561-30febcd357ecX0":{"label":"Part of count(kql=\'FlightDelay : true\') / count()","dataType":"number","operationType":"count","isBucketed":false,"scale":"ratio","sourceField":"___records___","filter":{"query":"FlightDelay : true","language":"kuery"},"customLabel":true},"7e8fe9b1-f45c-4f3d-9561-30febcd357ecX1":{"label":"Part of count(kql=\'FlightDelay : true\') / count()","dataType":"number","operationType":"count","isBucketed":false,"scale":"ratio","sourceField":"___records___","customLabel":true},"7e8fe9b1-f45c-4f3d-9561-30febcd357ecX2":{"label":"Part of count(kql=\'FlightDelay : true\') / count()","dataType":"number","operationType":"math","isBucketed":false,"scale":"ratio","params":{"tinymathAst":{"type":"function","name":"divide","args":["7e8fe9b1-f45c-4f3d-9561-30febcd357ecX0","7e8fe9b1-f45c-4f3d-9561-30febcd357ecX1"],"location":{"min":0,"max":41},"text":"count(kql=\'FlightDelay : true\') / count()"}},"references":["7e8fe9b1-f45c-4f3d-9561-30febcd357ecX0","7e8fe9b1-f45c-4f3d-9561-30febcd357ecX1"],"customLabel":true}},"columnOrder":["7e8fe9b1-f45c-4f3d-9561-30febcd357ec","7e8fe9b1-f45c-4f3d-9561-30febcd357ecX0","7e8fe9b1-f45c-4f3d-9561-30febcd357ecX1","7e8fe9b1-f45c-4f3d-9561-30febcd357ecX2"],"incompleteColumns":{}}}}},"internalReferences":[],"adHocDataViews":{}}},"enhancements":{}}},{"version":"8.8.0","type":"lens","gridData":{"x":40,"y":0,"w":8,"h":4,"i":"aa591c29-1a31-4ee1-a71d-b829c06fd162"},"panelIndex":"aa591c29-1a31-4ee1-a71d-b829c06fd162","embeddableConfig":{"attributes":{"title":"","visualizationType":"lnsMetric","type":"lens","references":[{"type":"index-pattern","id":"d3d7af60-4c81-11e8-b3d7-01146121b73d","name":"indexpattern-datasource-layer-b4712d43-1e84-4f5b-878d-8e38ba748317"},{"type":"index-pattern","name":"c804c161-375f-4d52-a1cc-2e98b966957d","id":"d3d7af60-4c81-11e8-b3d7-01146121b73d"}],"state":{"visualization":{"layerId":"b4712d43-1e84-4f5b-878d-8e38ba748317","layerType":"data","metricAccessor":"c7851241-5526-499a-960b-357af8c2ce5b"},"query":{"query":"","language":"kuery"},"filters":[{"meta":{"alias":null,"negate":false,"disabled":false,"type":"phrase","key":"FlightDelay","params":{"query":true},"index":"c804c161-375f-4d52-a1cc-2e98b966957d"},"query":{"match_phrase":{"FlightDelay":true}},"$state":{"store":"appState"}}],"datasourceStates":{"formBased":{"layers":{"b4712d43-1e84-4f5b-878d-8e38ba748317":{"columns":{"c7851241-5526-499a-960b-357af8c2ce5b":{"label":"Delayed vs 1 week earlier","dataType":"number","operationType":"formula","isBucketed":false,"scale":"ratio","params":{"formula":"count() / count(shift=\'1w\') - 1","isFormulaBroken":false,"format":{"id":"percent","params":{"decimals":1}}},"references":["c7851241-5526-499a-960b-357af8c2ce5bX2"],"customLabel":true},"c7851241-5526-499a-960b-357af8c2ce5bX2":{"label":"Part of Delayed","dataType":"number","operationType":"math","isBucketed":false,"scale":"ratio","params":{"tinymathAst":{"type":"function","name":"subtract","args":[{"type":"function","name":"divide","args":["c7851241-5526-499a-960b-357af8c2ce5bX0","c7851241-5526-499a-960b-357af8c2ce5bX1"],"location":{"min":0,"max":28},"text":"count() / count(shift=\'1w\') "},1],"location":{"min":0,"max":31},"text":"count() / count(shift=\'1w\') - 1"}},"references":["c7851241-5526-499a-960b-357af8c2ce5bX0","c7851241-5526-499a-960b-357af8c2ce5bX1"],"customLabel":true},"c7851241-5526-499a-960b-357af8c2ce5bX0":{"label":"Part of Delayed","dataType":"number","operationType":"count","isBucketed":false,"scale":"ratio","sourceField":"___records___","customLabel":true},"c7851241-5526-499a-960b-357af8c2ce5bX1":{"label":"Part of Delayed","dataType":"number","operationType":"count","isBucketed":false,"scale":"ratio","sourceField":"___records___","timeShift":"1w","customLabel":true}},"columnOrder":["c7851241-5526-499a-960b-357af8c2ce5b","c7851241-5526-499a-960b-357af8c2ce5bX2","c7851241-5526-499a-960b-357af8c2ce5bX0","c7851241-5526-499a-960b-357af8c2ce5bX1"],"incompleteColumns":{}}}}},"internalReferences":[],"adHocDataViews":{}}},"enhancements":{}}},{"version":"8.8.0","type":"lens","gridData":{"x":32,"y":4,"w":8,"h":4,"i":"b766e3b8-4544-46ed-99e6-9ecc4847e2a2"},"panelIndex":"b766e3b8-4544-46ed-99e6-9ecc4847e2a2","embeddableConfig":{"attributes":{"title":"","visualizationType":"lnsMetric","type":"lens","references":[{"type":"index-pattern","id":"d3d7af60-4c81-11e8-b3d7-01146121b73d","name":"indexpattern-datasource-layer-b4712d43-1e84-4f5b-878d-8e38ba748317"}],"state":{"visualization":{"layerId":"b4712d43-1e84-4f5b-878d-8e38ba748317","layerType":"data","metricAccessor":"7e8fe9b1-f45c-4f3d-9561-30febcd357ec"},"query":{"query":"","language":"kuery"},"filters":[],"datasourceStates":{"formBased":{"layers":{"b4712d43-1e84-4f5b-878d-8e38ba748317":{"columns":{"7e8fe9b1-f45c-4f3d-9561-30febcd357ec":{"label":"Cancelled","dataType":"number","operationType":"formula","isBucketed":false,"scale":"ratio","params":{"formula":"count(kql=\'Cancelled : true\') / count()","isFormulaBroken":false,"format":{"id":"percent","params":{"decimals":1}}},"references":["7e8fe9b1-f45c-4f3d-9561-30febcd357ecX2"],"customLabel":true},"7e8fe9b1-f45c-4f3d-9561-30febcd357ecX0":{"label":"Part of Cancelled","dataType":"number","operationType":"count","isBucketed":false,"scale":"ratio","sourceField":"___records___","filter":{"query":"Cancelled : true","language":"kuery"},"customLabel":true},"7e8fe9b1-f45c-4f3d-9561-30febcd357ecX1":{"label":"Part of Cancelled","dataType":"number","operationType":"count","isBucketed":false,"scale":"ratio","sourceField":"___records___","customLabel":true},"7e8fe9b1-f45c-4f3d-9561-30febcd357ecX2":{"label":"Part of Cancelled","dataType":"number","operationType":"math","isBucketed":false,"scale":"ratio","params":{"tinymathAst":{"type":"function","name":"divide","args":["7e8fe9b1-f45c-4f3d-9561-30febcd357ecX0","7e8fe9b1-f45c-4f3d-9561-30febcd357ecX1"],"location":{"min":0,"max":39},"text":"count(kql=\'Cancelled : true\') / count()"}},"references":["7e8fe9b1-f45c-4f3d-9561-30febcd357ecX0","7e8fe9b1-f45c-4f3d-9561-30febcd357ecX1"],"customLabel":true}},"columnOrder":["7e8fe9b1-f45c-4f3d-9561-30febcd357ec","7e8fe9b1-f45c-4f3d-9561-30febcd357ecX0","7e8fe9b1-f45c-4f3d-9561-30febcd357ecX1","7e8fe9b1-f45c-4f3d-9561-30febcd357ecX2"],"incompleteColumns":{}}}}},"internalReferences":[],"adHocDataViews":{}}},"enhancements":{}}},{"version":"8.8.0","type":"lens","gridData":{"x":40,"y":4,"w":8,"h":4,"i":"2e33ade5-96e5-40b4-b460-493e5d4fa834"},"panelIndex":"2e33ade5-96e5-40b4-b460-493e5d4fa834","embeddableConfig":{"attributes":{"title":"","visualizationType":"lnsMetric","type":"lens","references":[{"type":"index-pattern","id":"d3d7af60-4c81-11e8-b3d7-01146121b73d","name":"indexpattern-datasource-layer-b4712d43-1e84-4f5b-878d-8e38ba748317"},{"type":"index-pattern","name":"14cea722-a629-4c69-a06d-94a4a4c9a718","id":"d3d7af60-4c81-11e8-b3d7-01146121b73d"}],"state":{"visualization":{"layerId":"b4712d43-1e84-4f5b-878d-8e38ba748317","layerType":"data","metricAccessor":"c7851241-5526-499a-960b-357af8c2ce5b"},"query":{"query":"","language":"kuery"},"filters":[{"meta":{"alias":null,"negate":false,"disabled":false,"type":"phrase","key":"Cancelled","params":{"query":true},"index":"14cea722-a629-4c69-a06d-94a4a4c9a718"},"query":{"match_phrase":{"Cancelled":true}},"$state":{"store":"appState"}}],"datasourceStates":{"formBased":{"layers":{"b4712d43-1e84-4f5b-878d-8e38ba748317":{"columns":{"c7851241-5526-499a-960b-357af8c2ce5b":{"label":"Cancelled vs 1 week earlier","dataType":"number","operationType":"formula","isBucketed":false,"scale":"ratio","params":{"formula":"count() / count(shift=\'1w\') - 1","isFormulaBroken":false,"format":{"id":"percent","params":{"decimals":1}}},"references":["c7851241-5526-499a-960b-357af8c2ce5bX2"],"customLabel":true},"c7851241-5526-499a-960b-357af8c2ce5bX2":{"label":"Part of Delayed vs 1 week earlier","dataType":"number","operationType":"math","isBucketed":false,"scale":"ratio","params":{"tinymathAst":{"type":"function","name":"subtract","args":[{"type":"function","name":"divide","args":["c7851241-5526-499a-960b-357af8c2ce5bX0","c7851241-5526-499a-960b-357af8c2ce5bX1"],"location":{"min":0,"max":28},"text":"count() / count(shift=\'1w\') "},1],"location":{"min":0,"max":31},"text":"count() / count(shift=\'1w\') - 1"}},"references":["c7851241-5526-499a-960b-357af8c2ce5bX0","c7851241-5526-499a-960b-357af8c2ce5bX1"],"customLabel":true},"c7851241-5526-499a-960b-357af8c2ce5bX0":{"label":"Part of Delayed vs 1 week earlier","dataType":"number","operationType":"count","isBucketed":false,"scale":"ratio","sourceField":"___records___","customLabel":true},"c7851241-5526-499a-960b-357af8c2ce5bX1":{"label":"Part of Delayed vs 1 week earlier","dataType":"number","operationType":"count","isBucketed":false,"scale":"ratio","sourceField":"___records___","timeShift":"1w","customLabel":true}},"columnOrder":["c7851241-5526-499a-960b-357af8c2ce5b","c7851241-5526-499a-960b-357af8c2ce5bX2","c7851241-5526-499a-960b-357af8c2ce5bX0","c7851241-5526-499a-960b-357af8c2ce5bX1"],"incompleteColumns":{}}}}},"internalReferences":[],"adHocDataViews":{}}},"enhancements":{}}},{"version":"8.8.0","type":"lens","gridData":{"x":0,"y":8,"w":24,"h":8,"i":"086ac2e9-dd16-4b45-92b8-1e43ff7e3f65"},"panelIndex":"086ac2e9-dd16-4b45-92b8-1e43ff7e3f65","embeddableConfig":{"attributes":{"title":"","type":"lens","visualizationType":"lnsXY","state":{"datasourceStates":{"formBased":{"layers":{"03c34665-471c-49c7-acf1-5a11f517421c":{"columns":{"a5b94e30-4e77-4b0a-9187-1d8b13de1456":{"label":"timestamp","dataType":"date","operationType":"date_histogram","sourceField":"timestamp","isBucketed":true,"scale":"interval","params":{"interval":"auto","includeEmptyRows":true}},"3e267327-7317-4310-aee3-320e0f7c1e70":{"label":"Count of records","dataType":"number","operationType":"count","isBucketed":false,"scale":"ratio","sourceField":"___records___"}},"columnOrder":["a5b94e30-4e77-4b0a-9187-1d8b13de1456","3e267327-7317-4310-aee3-320e0f7c1e70"],"incompleteColumns":{}}}}},"visualization":{"legend":{"isVisible":true,"position":"right","legendSize":"auto"},"valueLabels":"hide","fittingFunction":"None","yLeftExtent":{"mode":"full"},"yRightExtent":{"mode":"custom","lowerBound":0,"upperBound":1},"axisTitlesVisibilitySettings":{"x":false,"yLeft":false,"yRight":true},"tickLabelsVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"gridlinesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"preferredSeriesType":"bar_stacked","layers":[{"layerId":"03c34665-471c-49c7-acf1-5a11f517421c","accessors":["3e267327-7317-4310-aee3-320e0f7c1e70"],"position":"top","seriesType":"bar_stacked","showGridlines":false,"xAccessor":"a5b94e30-4e77-4b0a-9187-1d8b13de1456","layerType":"data"}]},"query":{"query":"","language":"kuery"},"filters":[]},"references":[{"id":"d3d7af60-4c81-11e8-b3d7-01146121b73d","name":"indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"d3d7af60-4c81-11e8-b3d7-01146121b73d","name":"indexpattern-datasource-layer-03c34665-471c-49c7-acf1-5a11f517421c","type":"index-pattern"}]},"hidePanelTitles":false,"enhancements":{}},"title":"[Flights] Flight count"},{"version":"8.8.0","type":"lens","gridData":{"x":24,"y":8,"w":24,"h":28,"i":"fb86b32f-fb7a-45cf-9511-f366fef51bbd"},"panelIndex":"fb86b32f-fb7a-45cf-9511-f366fef51bbd","embeddableConfig":{"attributes":{"title":"Cities by delay, cancellation","type":"lens","visualizationType":"lnsDatatable","state":{"datasourceStates":{"formBased":{"layers":{"f26e8f7a-4118-4227-bea0-5c02d8b270f7":{"columns":{"3dd24cb4-45ef-4dd8-b22a-d7b802cb6da0":{"label":"Top values of OriginCityName","dataType":"string","operationType":"terms","scale":"ordinal","sourceField":"OriginCityName","isBucketed":true,"params":{"size":1000,"orderBy":{"type":"alphabetical","fallback":true},"orderDirection":"asc","otherBucket":true,"missingBucket":false}},"52f6f2e9-6242-4c44-be63-b799150e7e60X0":{"label":"Part of Delay %","dataType":"number","operationType":"count","isBucketed":false,"scale":"ratio","sourceField":"___records___","filter":{"query":"FlightDelay : true ","language":"kuery"},"customLabel":true},"52f6f2e9-6242-4c44-be63-b799150e7e60X1":{"label":"Part of Delay %","dataType":"number","operationType":"count","isBucketed":false,"scale":"ratio","sourceField":"___records___","customLabel":true},"52f6f2e9-6242-4c44-be63-b799150e7e60X2":{"label":"Part of Delay %","dataType":"number","operationType":"math","isBucketed":false,"scale":"ratio","params":{"tinymathAst":{"type":"function","name":"divide","args":["52f6f2e9-6242-4c44-be63-b799150e7e60X0","52f6f2e9-6242-4c44-be63-b799150e7e60X1"],"location":{"min":0,"max":42},"text":"count(kql=\'FlightDelay : true \') / count()"}},"references":["52f6f2e9-6242-4c44-be63-b799150e7e60X0","52f6f2e9-6242-4c44-be63-b799150e7e60X1"],"customLabel":true},"52f6f2e9-6242-4c44-be63-b799150e7e60":{"label":"Delay %","dataType":"number","operationType":"formula","isBucketed":false,"scale":"ratio","params":{"formula":"count(kql=\'FlightDelay : true \') / count()","isFormulaBroken":false,"format":{"id":"percent","params":{"decimals":0}}},"references":["52f6f2e9-6242-4c44-be63-b799150e7e60X2"],"customLabel":true},"7b9f3ece-9da3-4c27-b582-d3f8e8cc31d6X0":{"label":"Part of Cancel %","dataType":"number","operationType":"count","isBucketed":false,"scale":"ratio","sourceField":"___records___","filter":{"query":"Cancelled: true","language":"kuery"},"customLabel":true},"7b9f3ece-9da3-4c27-b582-d3f8e8cc31d6X1":{"label":"Part of Cancel %","dataType":"number","operationType":"count","isBucketed":false,"scale":"ratio","sourceField":"___records___","customLabel":true},"7b9f3ece-9da3-4c27-b582-d3f8e8cc31d6X2":{"label":"Part of Cancel %","dataType":"number","operationType":"math","isBucketed":false,"scale":"ratio","params":{"tinymathAst":{"type":"function","name":"divide","args":["7b9f3ece-9da3-4c27-b582-d3f8e8cc31d6X0","7b9f3ece-9da3-4c27-b582-d3f8e8cc31d6X1"],"location":{"min":0,"max":38},"text":"count(kql=\'Cancelled: true\') / count()"}},"references":["7b9f3ece-9da3-4c27-b582-d3f8e8cc31d6X0","7b9f3ece-9da3-4c27-b582-d3f8e8cc31d6X1"],"customLabel":true},"7b9f3ece-9da3-4c27-b582-d3f8e8cc31d6":{"label":"Cancel %","dataType":"number","operationType":"formula","isBucketed":false,"scale":"ratio","params":{"formula":"count(kql=\'Cancelled: true\') / count()","isFormulaBroken":false,"format":{"id":"percent","params":{"decimals":0}}},"references":["7b9f3ece-9da3-4c27-b582-d3f8e8cc31d6X2"],"customLabel":true}},"columnOrder":["3dd24cb4-45ef-4dd8-b22a-d7b802cb6da0","52f6f2e9-6242-4c44-be63-b799150e7e60","52f6f2e9-6242-4c44-be63-b799150e7e60X0","52f6f2e9-6242-4c44-be63-b799150e7e60X1","52f6f2e9-6242-4c44-be63-b799150e7e60X2","7b9f3ece-9da3-4c27-b582-d3f8e8cc31d6X0","7b9f3ece-9da3-4c27-b582-d3f8e8cc31d6X1","7b9f3ece-9da3-4c27-b582-d3f8e8cc31d6X2","7b9f3ece-9da3-4c27-b582-d3f8e8cc31d6"],"incompleteColumns":{}}}}},"visualization":{"columns":[{"isTransposed":false,"columnId":"3dd24cb4-45ef-4dd8-b22a-d7b802cb6da0","width":262.75},{"columnId":"52f6f2e9-6242-4c44-be63-b799150e7e60","isTransposed":false,"width":302.5,"colorMode":"cell","palette":{"type":"palette","name":"negative","params":{"steps":5,"stops":[{"color":"#fcdedc","stop":0},{"color":"#fec3bd","stop":0.2},{"color":"#fea79e","stop":0.4},{"color":"#fb8b81","stop":0.6},{"color":"#f66d64","stop":0.8}],"name":"negative","rangeType":"number","rangeMin":0,"rangeMax":null,"continuity":"above","reverse":false}},"alignment":"center"},{"columnId":"7b9f3ece-9da3-4c27-b582-d3f8e8cc31d6","isTransposed":false,"alignment":"center","colorMode":"cell","palette":{"type":"palette","name":"negative","params":{"steps":5,"stops":[{"color":"#fcdedc","stop":0},{"color":"#fec3bd","stop":0.2},{"color":"#fea79e","stop":0.4},{"color":"#fb8b81","stop":0.6},{"color":"#f66d64","stop":0.8}],"name":"negative","rangeType":"number","rangeMin":0,"rangeMax":null,"continuity":"above","reverse":false}}}],"layerId":"f26e8f7a-4118-4227-bea0-5c02d8b270f7","sorting":{"columnId":"52f6f2e9-6242-4c44-be63-b799150e7e60","direction":"desc"},"layerType":"data","rowHeight":"single","rowHeightLines":1},"query":{"query":"","language":"kuery"},"filters":[]},"references":[{"id":"d3d7af60-4c81-11e8-b3d7-01146121b73d","name":"indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"d3d7af60-4c81-11e8-b3d7-01146121b73d","name":"indexpattern-datasource-layer-f26e8f7a-4118-4227-bea0-5c02d8b270f7","type":"index-pattern"}]},"enhancements":{},"hidePanelTitles":false},"title":"[Flights] Most delayed cities"},{"version":"8.8.0","type":"lens","gridData":{"x":0,"y":25,"w":24,"h":11,"i":"0cc42484-16f7-42ec-b38c-9bf8be69cde7"},"panelIndex":"0cc42484-16f7-42ec-b38c-9bf8be69cde7","embeddableConfig":{"attributes":{"title":"","type":"lens","visualizationType":"lnsXY","state":{"datasourceStates":{"formBased":{"layers":{"e80cc05e-c52a-4e5f-ac71-4b37274867f5":{"columns":{"caf7421e-93a3-439e-ab0a-fbdead93c21c":{"label":"Top values of FlightDelayType","dataType":"string","operationType":"terms","scale":"ordinal","sourceField":"FlightDelayType","isBucketed":true,"params":{"size":10,"orderBy":{"type":"column","columnId":"0233d302-ec81-4fbe-96cb-7fac84cf035c"},"orderDirection":"desc","otherBucket":true,"missingBucket":false}},"13ec79e3-9d73-4536-9056-3d92802bb30a":{"label":"timestamp","dataType":"date","operationType":"date_histogram","sourceField":"timestamp","isBucketed":true,"scale":"interval","params":{"interval":"auto","includeEmptyRows":true}},"0233d302-ec81-4fbe-96cb-7fac84cf035c":{"label":"Count of records","dataType":"number","operationType":"count","isBucketed":false,"scale":"ratio","sourceField":"___records___"}},"columnOrder":["caf7421e-93a3-439e-ab0a-fbdead93c21c","13ec79e3-9d73-4536-9056-3d92802bb30a","0233d302-ec81-4fbe-96cb-7fac84cf035c"],"incompleteColumns":{}}}}},"visualization":{"legend":{"isVisible":true,"position":"bottom","legendSize":"auto"},"valueLabels":"hide","fittingFunction":"None","yLeftExtent":{"mode":"full"},"yRightExtent":{"mode":"full"},"axisTitlesVisibilitySettings":{"x":true,"yLeft":false,"yRight":true},"tickLabelsVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"gridlinesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"preferredSeriesType":"bar_percentage_stacked","layers":[{"layerId":"e80cc05e-c52a-4e5f-ac71-4b37274867f5","accessors":["0233d302-ec81-4fbe-96cb-7fac84cf035c"],"position":"top","seriesType":"bar_percentage_stacked","showGridlines":false,"palette":{"type":"palette","name":"cool"},"xAccessor":"13ec79e3-9d73-4536-9056-3d92802bb30a","splitAccessor":"caf7421e-93a3-439e-ab0a-fbdead93c21c","layerType":"data"}]},"query":{"query":"","language":"kuery"},"filters":[]},"references":[{"id":"d3d7af60-4c81-11e8-b3d7-01146121b73d","name":"indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"d3d7af60-4c81-11e8-b3d7-01146121b73d","name":"indexpattern-datasource-layer-e80cc05e-c52a-4e5f-ac71-4b37274867f5","type":"index-pattern"}]},"hidePanelTitles":false,"enhancements":{}},"title":"[Flights] Delay Type"},{"version":"8.8.0","type":"lens","gridData":{"x":24,"y":58,"w":12,"h":11,"i":"5d53db36-2d5a-4adc-af7b-cec4c1a294e0"},"panelIndex":"5d53db36-2d5a-4adc-af7b-cec4c1a294e0","embeddableConfig":{"attributes":{"title":"","type":"lens","visualizationType":"lnsPie","state":{"datasourceStates":{"formBased":{"layers":{"0c8e136b-a822-4fb3-836d-e06cbea4eea4":{"columns":{"d1cee8bf-34cf-4141-99d7-ff043ee77b56":{"label":"Top values of FlightDelayType","dataType":"string","operationType":"terms","scale":"ordinal","sourceField":"FlightDelayType","isBucketed":true,"params":{"size":10,"orderBy":{"type":"column","columnId":"aa152ace-ee2d-447b-b86d-459bef4d7880"},"orderDirection":"desc","otherBucket":true,"missingBucket":false}},"aa152ace-ee2d-447b-b86d-459bef4d7880":{"label":"Count of records","dataType":"number","operationType":"count","isBucketed":false,"scale":"ratio","sourceField":"___records___"}},"columnOrder":["d1cee8bf-34cf-4141-99d7-ff043ee77b56","aa152ace-ee2d-447b-b86d-459bef4d7880"],"incompleteColumns":{}}}}},"visualization":{"shape":"pie","palette":{"type":"palette","name":"cool"},"layers":[{"layerId":"0c8e136b-a822-4fb3-836d-e06cbea4eea4","numberDisplay":"percent","categoryDisplay":"default","legendDisplay":"default","nestedLegend":false,"layerType":"data","legendSize":"auto","primaryGroups":["d1cee8bf-34cf-4141-99d7-ff043ee77b56"],"metrics":["aa152ace-ee2d-447b-b86d-459bef4d7880"]}]},"query":{"query":"","language":"kuery"},"filters":[{"meta":{"type":"phrase","key":"FlightDelayType","params":{"query":"No Delay"},"disabled":false,"negate":true,"alias":null,"index":"filter-index-pattern-0"},"query":{"match_phrase":{"FlightDelayType":"No Delay"}},"$state":{"store":"appState"}}]},"references":[{"id":"d3d7af60-4c81-11e8-b3d7-01146121b73d","name":"indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"d3d7af60-4c81-11e8-b3d7-01146121b73d","name":"indexpattern-datasource-layer-0c8e136b-a822-4fb3-836d-e06cbea4eea4","type":"index-pattern"},{"id":"d3d7af60-4c81-11e8-b3d7-01146121b73d","name":"filter-index-pattern-0","type":"index-pattern"}]},"enhancements":{},"hidePanelTitles":false},"title":"[Flights] Delay Type"},{"version":"8.8.0","type":"lens","gridData":{"x":36,"y":58,"w":12,"h":11,"i":"ecd89a7c-9124-4472-bdc6-9bdbd70d45d5"},"panelIndex":"ecd89a7c-9124-4472-bdc6-9bdbd70d45d5","embeddableConfig":{"attributes":{"title":"","visualizationType":"lnsXY","type":"lens","references":[{"type":"index-pattern","id":"d3d7af60-4c81-11e8-b3d7-01146121b73d","name":"indexpattern-datasource-layer-dffd86e7-01a9-4990-b974-3706608b5532"}],"state":{"visualization":{"title":"Empty XY chart","legend":{"isVisible":true,"position":"right"},"valueLabels":"hide","preferredSeriesType":"bar_horizontal","layers":[{"layerId":"dffd86e7-01a9-4990-b974-3706608b5532","accessors":["9d212159-afac-41f5-9303-5fb62ff04ba3"],"position":"top","seriesType":"bar_horizontal","showGridlines":false,"layerType":"data","splitAccessor":"d99ad4d7-26ff-4d65-a8ce-34656fdafa0a","palette":{"type":"palette","name":"temperature"}}]},"query":{"query":"","language":"kuery"},"filters":[],"datasourceStates":{"formBased":{"layers":{"dffd86e7-01a9-4990-b974-3706608b5532":{"columns":{"9d212159-afac-41f5-9303-5fb62ff04ba3":{"label":"Count of records","dataType":"number","operationType":"count","isBucketed":false,"scale":"ratio","sourceField":"___records___","params":{"emptyAsNull":true}},"d99ad4d7-26ff-4d65-a8ce-34656fdafa0a":{"label":"Top 10 values of DestWeather","dataType":"string","operationType":"terms","scale":"ordinal","sourceField":"DestWeather","isBucketed":true,"params":{"size":10,"orderBy":{"type":"column","columnId":"9d212159-afac-41f5-9303-5fb62ff04ba3"},"orderDirection":"desc","otherBucket":true,"missingBucket":false,"parentFormat":{"id":"terms"},"include":[],"exclude":[],"includeIsRegex":false,"excludeIsRegex":false}}},"columnOrder":["d99ad4d7-26ff-4d65-a8ce-34656fdafa0a","9d212159-afac-41f5-9303-5fb62ff04ba3"],"sampling":1,"incompleteColumns":{}}}},"textBased":{"layers":{}}},"internalReferences":[],"adHocDataViews":{}}},"enhancements":{}}}]', timeFrom: 'now-7d', title: '[Flights] Global Flight Dashboard', timeTo: 'now', diff --git a/src/plugins/home/server/services/sample_data/data_sets/logs/saved_objects.ts b/src/plugins/home/server/services/sample_data/data_sets/logs/saved_objects.ts index a73979c88cb2e..19d59c35523f4 100644 --- a/src/plugins/home/server/services/sample_data/data_sets/logs/saved_objects.ts +++ b/src/plugins/home/server/services/sample_data/data_sets/logs/saved_objects.ts @@ -313,7 +313,7 @@ export const getSavedObjects = (): SavedObject[] => [ optionsJSON: '{"useMargins":true,"syncColors":false,"syncCursor":true,"syncTooltips":false,"hidePanelTitles":false}', panelsJSON: - '[{"version":"8.8.0","type":"map","gridData":{"x":0,"y":14,"w":24,"h":18,"i":"4"},"panelIndex":"4","embeddableConfig":{"isLayerTOCOpen":false,"hiddenLayers":[],"mapCenter":{"lat":42.16337,"lon":-88.92107,"zoom":3.64},"openTOCDetails":[],"enhancements":{}},"panelRefName":"panel_4"},{"version":"8.8.0","type":"lens","gridData":{"x":36,"y":0,"w":12,"h":7,"i":"11"},"panelIndex":"11","embeddableConfig":{"attributes":{"title":"","visualizationType":"lnsMetric","type":"lens","references":[{"type":"index-pattern","id":"90943e30-9a47-11e8-b64d-95841ca0b247","name":"indexpattern-datasource-layer-28b89898-3feb-415a-8dd9-74d755ac7c2a"}],"state":{"visualization":{"layerId":"28b89898-3feb-415a-8dd9-74d755ac7c2a","layerType":"data","metricAccessor":"f92c482e-1eee-4c2a-9338-64fb3eec286a","palette":{"name":"custom","type":"palette","params":{"steps":3,"name":"custom","reverse":false,"rangeType":"number","rangeMin":0,"rangeMax":null,"progression":"fixed","stops":[{"color":"#D23115","stop":500},{"color":"#FCC400","stop":1000},{"color":"#68BC00","stop":1658}],"colorStops":[{"color":"#D23115","stop":0},{"color":"#FCC400","stop":500},{"color":"#68BC00","stop":1000}],"continuity":"above","maxSteps":5}}},"query":{"query":"","language":"kuery"},"filters":[],"datasourceStates":{"formBased":{"layers":{"28b89898-3feb-415a-8dd9-74d755ac7c2a":{"columns":{"f92c482e-1eee-4c2a-9338-64fb3eec286a":{"label":"Unique Visitors","dataType":"number","operationType":"unique_count","scale":"ratio","sourceField":"clientip","isBucketed":false,"params":{"emptyAsNull":true},"customLabel":true}},"columnOrder":["f92c482e-1eee-4c2a-9338-64fb3eec286a"],"incompleteColumns":{}}}},"textBased":{"layers":{}}},"internalReferences":[],"adHocDataViews":{}}},"hidePanelTitles":true,"enhancements":{}}},{"version":"8.8.0","type":"visualization","gridData":{"x":24,"y":14,"w":24,"h":33,"i":"14"},"panelIndex":"14","embeddableConfig":{"enhancements":{}},"panelRefName":"panel_14"},{"version":"8.8.0","type":"lens","gridData":{"x":0,"y":7,"w":24,"h":7,"i":"15"},"panelIndex":"15","embeddableConfig":{"attributes":{"title":"[Logs] Response Codes Over Time + Annotations (converted)","visualizationType":"lnsXY","type":"lens","references":[{"type":"index-pattern","id":"90943e30-9a47-11e8-b64d-95841ca0b247","name":"indexpattern-datasource-layer-b38fe501-4b47-4de8-a423-6656d1162174"},{"type":"index-pattern","id":"90943e30-9a47-11e8-b64d-95841ca0b247","name":"xy-visualization-layer-f265e722-ae38-495c-903c-48aa7931fa82"}],"state":{"visualization":{"legend":{"isVisible":true,"showSingleSeries":true,"position":"bottom","shouldTruncate":true,"maxLines":1},"valueLabels":"hide","fittingFunction":"None","fillOpacity":0.5,"yLeftExtent":{"mode":"full"},"yRightExtent":{"mode":"full"},"yLeftScale":"linear","yRightScale":"linear","axisTitlesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"tickLabelsVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"labelsOrientation":{"x":0,"yLeft":0,"yRight":0},"gridlinesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"preferredSeriesType":"bar_stacked","layers":[{"seriesType":"area_percentage_stacked","layerType":"data","layerId":"b38fe501-4b47-4de8-a423-6656d1162174","accessors":["896c5eb2-81c5-44f1-a4a1-57344161ea62"],"yConfig":[{"forAccessor":"896c5eb2-81c5-44f1-a4a1-57344161ea62","color":"rgba(115,216,255,1)","axisMode":"left"}],"xAccessor":"8986e393-d24f-49b0-96ca-118fd66d75e5","splitAccessor":"43f5bb0f-c6da-43a0-8a0a-50e9838ed34b","palette":{"name":"default","type":"palette"}},{"layerId":"f265e722-ae38-495c-903c-48aa7931fa82","layerType":"annotations","ignoreGlobalFilters":true,"annotations":[{"type":"query","id":"bd7548a0-2223-11e8-832f-d5027f3c8a47","label":"Event","key":{"type":"point_in_time"},"color":"#D33115","timeField":"timestamp","icon":"asterisk","filter":{"type":"kibana_query","query":"tags:error AND tags:security","language":"lucene"},"extraFields":["geo.src"]}]}]},"query":{"query":"","language":"kuery"},"filters":[],"datasourceStates":{"formBased":{"layers":{"b38fe501-4b47-4de8-a423-6656d1162174":{"columns":{"8986e393-d24f-49b0-96ca-118fd66d75e5":{"label":"timestamp","dataType":"date","operationType":"date_histogram","sourceField":"timestamp","isBucketed":true,"scale":"interval","params":{"interval":"auto","includeEmptyRows":true,"dropPartials":false}},"43f5bb0f-c6da-43a0-8a0a-50e9838ed34b":{"label":"Filters","dataType":"string","operationType":"filters","scale":"ordinal","isBucketed":true,"params":{"filters":[{"input":{"query":"response.keyword >= 200 and response.keyword < 400","language":"kuery"},"label":"HTTP 2xx and 3xx"},{"input":{"query":"response.keyword >= 400 and response.keyword < 500","language":"kuery"},"label":"HTTP 4xx"},{"input":{"query":"response.keyword >= 500","language":"kuery"},"label":"HTTP 5xx"}]}},"896c5eb2-81c5-44f1-a4a1-57344161ea62":{"label":"Response Code Count","dataType":"number","operationType":"count","isBucketed":false,"scale":"ratio","sourceField":"___records___","params":{"emptyAsNull":true},"customLabel":true}},"columnOrder":["8986e393-d24f-49b0-96ca-118fd66d75e5","43f5bb0f-c6da-43a0-8a0a-50e9838ed34b","896c5eb2-81c5-44f1-a4a1-57344161ea62"],"incompleteColumns":{}}}},"textBased":{"layers":{}}},"internalReferences":[],"adHocDataViews":{}}},"enhancements":{},"hidePanelTitles":false},"title":"[Logs] Response Codes Over Time + Annotations"},{"version":"8.8.0","type":"visualization","gridData":{"x":0,"y":0,"w":24,"h":7,"i":"343f0bef-0b19-452e-b1c8-59beb18b6f0c"},"panelIndex":"343f0bef-0b19-452e-b1c8-59beb18b6f0c","embeddableConfig":{"savedVis":{"title":"[Logs] Markdown Instructions","description":"","type":"markdown","params":{"fontSize":12,"openLinksInNewTab":true,"markdown":"## Sample Logs Data\\nThis dashboard contains sample data for you to play with. You can view it, search it, and interact with the visualizations. For more information about Kibana, check our [docs](https://www.elastic.co/guide/en/kibana/current/index.html)."},"uiState":{},"data":{"aggs":[],"searchSource":{"query":{"query":"","language":"kuery"},"filter":[]}}},"enhancements":{},"hidePanelTitles":true}},{"version":"8.8.0","type":"lens","gridData":{"x":24,"y":0,"w":12,"h":7,"i":"bb94016e-f4a6-49ca-87a9-296a2869d570"},"panelIndex":"bb94016e-f4a6-49ca-87a9-296a2869d570","embeddableConfig":{"attributes":{"title":"","visualizationType":"lnsMetric","type":"lens","references":[{"type":"index-pattern","id":"90943e30-9a47-11e8-b64d-95841ca0b247","name":"indexpattern-datasource-layer-483defd2-775b-4a62-bdef-496c819bb8ed"}],"state":{"visualization":{"layerId":"483defd2-775b-4a62-bdef-496c819bb8ed","layerType":"data","metricAccessor":"37430d12-7452-4cc9-b035-5cfd4061edf0"},"query":{"query":"","language":"kuery"},"filters":[],"datasourceStates":{"formBased":{"layers":{"483defd2-775b-4a62-bdef-496c819bb8ed":{"columns":{"37430d12-7452-4cc9-b035-5cfd4061edf0":{"label":"Visits","dataType":"number","operationType":"count","isBucketed":false,"scale":"ratio","sourceField":"___records___","customLabel":true}},"columnOrder":["37430d12-7452-4cc9-b035-5cfd4061edf0"],"incompleteColumns":{}}}}},"internalReferences":[],"adHocDataViews":{}}},"enhancements":{}}},{"version":"8.8.0","type":"lens","gridData":{"x":36,"y":7,"w":12,"h":7,"i":"8c1456d4-1993-4ba2-b701-04aca02c9fef"},"panelIndex":"8c1456d4-1993-4ba2-b701-04aca02c9fef","embeddableConfig":{"attributes":{"title":"","visualizationType":"lnsMetric","type":"lens","references":[{"type":"index-pattern","id":"90943e30-9a47-11e8-b64d-95841ca0b247","name":"indexpattern-datasource-layer-f3793bb7-3971-4753-866d-4008e77a9f9a"}],"state":{"visualization":{"layerId":"f3793bb7-3971-4753-866d-4008e77a9f9a","layerType":"data","metricAccessor":"71c076a6-e782-4866-b8df-5fd85a41f08b"},"query":{"query":"","language":"kuery"},"filters":[],"datasourceStates":{"formBased":{"layers":{"f3793bb7-3971-4753-866d-4008e77a9f9a":{"columns":{"71c076a6-e782-4866-b8df-5fd85a41f08bX0":{"label":"Part of HTTP 5xx","dataType":"number","operationType":"count","isBucketed":false,"scale":"ratio","sourceField":"___records___","filter":{"query":"response.keyword >= 500","language":"kuery"},"params":{"emptyAsNull":false},"customLabel":true},"71c076a6-e782-4866-b8df-5fd85a41f08bX1":{"label":"Part of HTTP 5xx","dataType":"number","operationType":"count","isBucketed":false,"scale":"ratio","sourceField":"___records___","params":{"emptyAsNull":false},"customLabel":true},"71c076a6-e782-4866-b8df-5fd85a41f08bX2":{"label":"Part of HTTP 5xx","dataType":"number","operationType":"math","isBucketed":false,"scale":"ratio","params":{"tinymathAst":{"type":"function","name":"divide","args":["71c076a6-e782-4866-b8df-5fd85a41f08bX0","71c076a6-e782-4866-b8df-5fd85a41f08bX1"],"location":{"min":0,"max":46},"text":"count(kql=\'response.keyword >= 500\') / count()"}},"references":["71c076a6-e782-4866-b8df-5fd85a41f08bX0","71c076a6-e782-4866-b8df-5fd85a41f08bX1"],"customLabel":true},"71c076a6-e782-4866-b8df-5fd85a41f08b":{"label":"HTTP 5xx","dataType":"number","operationType":"formula","isBucketed":false,"scale":"ratio","params":{"formula":"count(kql=\'response.keyword >= 500\') / count()","isFormulaBroken":false,"format":{"id":"percent","params":{"decimals":1}}},"references":["71c076a6-e782-4866-b8df-5fd85a41f08bX2"],"customLabel":true}},"columnOrder":["71c076a6-e782-4866-b8df-5fd85a41f08b","71c076a6-e782-4866-b8df-5fd85a41f08bX0","71c076a6-e782-4866-b8df-5fd85a41f08bX1","71c076a6-e782-4866-b8df-5fd85a41f08bX2"],"incompleteColumns":{}}}}},"internalReferences":[],"adHocDataViews":{}}},"enhancements":{}}},{"version":"8.8.0","type":"lens","gridData":{"x":24,"y":7,"w":12,"h":7,"i":"01d8e435-91c0-484f-a11e-856747050b0a"},"panelIndex":"01d8e435-91c0-484f-a11e-856747050b0a","embeddableConfig":{"attributes":{"title":"","visualizationType":"lnsMetric","type":"lens","references":[{"type":"index-pattern","id":"90943e30-9a47-11e8-b64d-95841ca0b247","name":"indexpattern-datasource-layer-f3793bb7-3971-4753-866d-4008e77a9f9a"}],"state":{"visualization":{"layerId":"f3793bb7-3971-4753-866d-4008e77a9f9a","layerType":"data","metricAccessor":"71c076a6-e782-4866-b8df-5fd85a41f08b"},"query":{"query":"","language":"kuery"},"filters":[],"datasourceStates":{"formBased":{"layers":{"f3793bb7-3971-4753-866d-4008e77a9f9a":{"columns":{"71c076a6-e782-4866-b8df-5fd85a41f08bX0":{"label":"Part of HTTP 4xx","dataType":"number","operationType":"count","isBucketed":false,"scale":"ratio","sourceField":"___records___","filter":{"query":"response.keyword >= 400 and response.keyword < 500","language":"kuery"},"params":{"emptyAsNull":false},"customLabel":true},"71c076a6-e782-4866-b8df-5fd85a41f08bX1":{"label":"Part of HTTP 4xx","dataType":"number","operationType":"count","isBucketed":false,"scale":"ratio","sourceField":"___records___","params":{"emptyAsNull":false},"customLabel":true},"71c076a6-e782-4866-b8df-5fd85a41f08bX2":{"label":"Part of HTTP 4xx","dataType":"number","operationType":"math","isBucketed":false,"scale":"ratio","params":{"tinymathAst":{"type":"function","name":"divide","args":["71c076a6-e782-4866-b8df-5fd85a41f08bX0","71c076a6-e782-4866-b8df-5fd85a41f08bX1"],"location":{"min":0,"max":73},"text":"count(kql=\'response.keyword >= 400 and response.keyword < 500\') / count()"}},"references":["71c076a6-e782-4866-b8df-5fd85a41f08bX0","71c076a6-e782-4866-b8df-5fd85a41f08bX1"],"customLabel":true},"71c076a6-e782-4866-b8df-5fd85a41f08b":{"label":"HTTP 4xx","dataType":"number","operationType":"formula","isBucketed":false,"scale":"ratio","params":{"formula":"count(kql=\'response.keyword >= 400 and response.keyword < 500\') / count()","isFormulaBroken":false,"format":{"id":"percent","params":{"decimals":1}}},"references":["71c076a6-e782-4866-b8df-5fd85a41f08bX2"],"customLabel":true}},"columnOrder":["71c076a6-e782-4866-b8df-5fd85a41f08b","71c076a6-e782-4866-b8df-5fd85a41f08bX0","71c076a6-e782-4866-b8df-5fd85a41f08bX1","71c076a6-e782-4866-b8df-5fd85a41f08bX2"],"incompleteColumns":{}}}}},"internalReferences":[],"adHocDataViews":{}}},"enhancements":{}}},{"version":"8.8.0","type":"visualization","gridData":{"x":0,"y":32,"w":24,"h":15,"i":"8e59c7cf-6e42-4343-a113-c4a255fcf2ce"},"panelIndex":"8e59c7cf-6e42-4343-a113-c4a255fcf2ce","embeddableConfig":{"savedVis":{"title":"","description":"","type":"vega","params":{"spec":"{\\n $schema: https://vega.github.io/schema/vega-lite/v5.json\\n data: {\\n url: {\\n %context%: true\\n %timefield%: @timestamp\\n index: kibana_sample_data_logs\\n body: {\\n aggs: {\\n countries: {\\n terms: {\\n field: geo.src\\n size: 25\\n }\\n aggs: {\\n hours: {\\n histogram: {\\n field: hour_of_day\\n interval: 1\\n }\\n aggs: {\\n unique: {\\n cardinality: {\\n field: clientip\\n }\\n }\\n }\\n }\\n }\\n }\\n }\\n size: 0\\n }\\n }\\n format: {property: \\"aggregations.countries.buckets\\"}\\n }\\n \\n transform: [\\n {\\n flatten: [\\"hours.buckets\\"],\\n as: [\\"buckets\\"]\\n }\\n ]\\n\\n mark: {\\n type: rect\\n tooltip: true\\n }\\n\\n encoding: {\\n x: {\\n field: buckets.key\\n type: ordinal\\n axis: {\\n title: false\\n labelAngle: 0\\n }\\n }\\n y: {\\n field: key\\n type: nominal\\n sort: {\\n field: -buckets.unique.value\\n }\\n axis: {title: false}\\n }\\n color: {\\n field: buckets.unique.value\\n type: quantitative\\n axis: {title: false}\\n scale: {\\n scheme: reds\\n }\\n }\\n }\\n}\\n"},"uiState":{},"data":{"aggs":[],"searchSource":{"query":{"query":"","language":"kuery"},"filter":[]}}},"enhancements":{}},"panelRefName":"panel_8e59c7cf-6e42-4343-a113-c4a255fcf2ce"},{"version":"8.8.0","type":"lens","gridData":{"x":0,"y":47,"w":24,"h":13,"i":"21bb0939-ee09-4021-8848-6552b3a6a788"},"panelIndex":"21bb0939-ee09-4021-8848-6552b3a6a788","embeddableConfig":{"attributes":{"title":"","visualizationType":"lnsDatatable","type":"lens","references":[{"type":"index-pattern","id":"90943e30-9a47-11e8-b64d-95841ca0b247","name":"indexpattern-datasource-layer-c840e93e-2949-4723-ad35-6bdb2d724404"}],"state":{"visualization":{"columns":[{"columnId":"4e64d6d7-4f92-4d5e-abbb-13796604db30","isTransposed":false},{"columnId":"fb9a848d-76f3-4005-a067-4259a50b5621","isTransposed":false},{"columnId":"a2760bc2-9a6e-46a1-8595-86f61573c7cf","isTransposed":false},{"columnId":"2c8bd8d5-35ff-4386-8d27-3ba882b13e43","isTransposed":false,"colorMode":"text","palette":{"name":"custom","type":"palette","params":{"steps":5,"stops":[{"color":"#d23115","stop":1000},{"color":"#fcc400","stop":1500},{"color":"#68bc00","stop":1501}],"rangeType":"number","rangeMin":0,"rangeMax":null,"continuity":"above","colorStops":[{"color":"#d23115","stop":0},{"color":"#fcc400","stop":1000},{"color":"#68bc00","stop":1500}],"name":"custom"}}},{"columnId":"defa6f97-b874-4556-8438-056fb437787b","isTransposed":false,"colorMode":"text","palette":{"name":"custom","type":"palette","params":{"steps":5,"stops":[{"color":"#D23115","stop":10},{"color":"#FCC400","stop":25},{"color":"#68bc00","stop":26}],"rangeType":"number","rangeMin":0,"rangeMax":null,"continuity":"above","colorStops":[{"color":"#D23115","stop":0},{"color":"#FCC400","stop":10},{"color":"#68bc00","stop":25}],"name":"custom"}}}],"layerId":"c840e93e-2949-4723-ad35-6bdb2d724404","layerType":"data"},"query":{"query":"","language":"kuery"},"filters":[],"datasourceStates":{"formBased":{"layers":{"c840e93e-2949-4723-ad35-6bdb2d724404":{"columns":{"4e64d6d7-4f92-4d5e-abbb-13796604db30":{"label":"Type","dataType":"string","operationType":"terms","scale":"ordinal","sourceField":"extension.keyword","isBucketed":true,"params":{"size":10,"orderBy":{"type":"column","columnId":"fb9a848d-76f3-4005-a067-4259a50b5621"},"orderDirection":"desc","otherBucket":true,"missingBucket":false,"parentFormat":{"id":"terms"},"include":[],"exclude":[],"includeIsRegex":false,"excludeIsRegex":false},"customLabel":true},"fb9a848d-76f3-4005-a067-4259a50b5621":{"label":"Bytes (Total)","dataType":"number","operationType":"sum","sourceField":"bytes","isBucketed":false,"scale":"ratio","params":{"emptyAsNull":true,"format":{"id":"bytes","params":{"decimals":2}}},"customLabel":true},"a2760bc2-9a6e-46a1-8595-86f61573c7cf":{"label":"Bytes (Last Hour)","dataType":"number","operationType":"sum","sourceField":"bytes","isBucketed":false,"scale":"ratio","reducedTimeRange":"1h","params":{"emptyAsNull":true,"format":{"id":"bytes","params":{"decimals":2}}},"customLabel":true},"2c8bd8d5-35ff-4386-8d27-3ba882b13e43":{"label":"Unique Visits (Total)","dataType":"number","operationType":"unique_count","scale":"ratio","sourceField":"clientip","isBucketed":false,"params":{"emptyAsNull":true},"customLabel":true},"defa6f97-b874-4556-8438-056fb437787b":{"label":"Unique count of clientip","dataType":"number","operationType":"unique_count","scale":"ratio","sourceField":"clientip","isBucketed":false,"reducedTimeRange":"1h","params":{"emptyAsNull":true}}},"columnOrder":["4e64d6d7-4f92-4d5e-abbb-13796604db30","fb9a848d-76f3-4005-a067-4259a50b5621","a2760bc2-9a6e-46a1-8595-86f61573c7cf","2c8bd8d5-35ff-4386-8d27-3ba882b13e43","defa6f97-b874-4556-8438-056fb437787b"],"sampling":1,"incompleteColumns":{}}}},"textBased":{"layers":{}}},"internalReferences":[],"adHocDataViews":{}}},"enhancements":{}}},{"version":"8.8.0","type":"lens","gridData":{"x":24,"y":47,"w":24,"h":13,"i":"cbca842c-b9fa-4523-9ce0-14e350866e33"},"panelIndex":"cbca842c-b9fa-4523-9ce0-14e350866e33","embeddableConfig":{"hidePanelTitles":false,"enhancements":{}},"title":"[Logs] Bytes distribution","panelRefName":"panel_cbca842c-b9fa-4523-9ce0-14e350866e33"},{"version":"8.8.0","type":"lens","gridData":{"x":0,"y":60,"w":48,"h":19,"i":"1d5f0b3f-d9d2-4b26-997b-83bc5ca3090b"},"panelIndex":"1d5f0b3f-d9d2-4b26-997b-83bc5ca3090b","embeddableConfig":{"attributes":{"title":"","type":"lens","visualizationType":"lnsDatatable","state":{"datasourceStates":{"formBased":{"layers":{"c35dc8ee-50d1-4ef7-8b4b-9c21a7e7d3b0":{"columns":{"42783ad7-dbcf-4310-bc06-f21f4eaaac96":{"label":"URL","dataType":"string","operationType":"terms","scale":"ordinal","sourceField":"url.keyword","isBucketed":true,"params":{"size":1000,"orderBy":{"type":"column","columnId":"f7835375-4d5b-4839-95ea-41928192a319"},"orderDirection":"desc","otherBucket":true,"missingBucket":false},"customLabel":true},"f7835375-4d5b-4839-95ea-41928192a319":{"label":"Visits","dataType":"number","operationType":"count","isBucketed":false,"scale":"ratio","sourceField":"___records___","customLabel":true},"07fc84ca-4147-4ba9-879e-d1b4e086e1daX0":{"label":"Part of HTTP 4xx","dataType":"number","operationType":"count","isBucketed":false,"scale":"ratio","sourceField":"___records___","filter":{"query":"response.keyword >= 400 and response.keyword < 500","language":"kuery"},"customLabel":true},"07fc84ca-4147-4ba9-879e-d1b4e086e1daX1":{"label":"Part of HTTP 4xx","dataType":"number","operationType":"count","isBucketed":false,"scale":"ratio","sourceField":"___records___","customLabel":true},"07fc84ca-4147-4ba9-879e-d1b4e086e1daX2":{"label":"Part of HTTP 4xx","dataType":"number","operationType":"math","isBucketed":false,"scale":"ratio","params":{"tinymathAst":{"type":"function","name":"divide","args":["07fc84ca-4147-4ba9-879e-d1b4e086e1daX0","07fc84ca-4147-4ba9-879e-d1b4e086e1daX1"],"location":{"min":0,"max":73},"text":"count(kql=\'response.keyword >= 400 and response.keyword < 500\') / count()"}},"references":["07fc84ca-4147-4ba9-879e-d1b4e086e1daX0","07fc84ca-4147-4ba9-879e-d1b4e086e1daX1"],"customLabel":true},"07fc84ca-4147-4ba9-879e-d1b4e086e1da":{"label":"HTTP 4xx","dataType":"number","operationType":"formula","isBucketed":false,"scale":"ratio","params":{"formula":"count(kql=\'response.keyword >= 400 and response.keyword < 500\') / count()","isFormulaBroken":false,"format":{"id":"percent","params":{"decimals":1}}},"references":["07fc84ca-4147-4ba9-879e-d1b4e086e1daX2"],"customLabel":true},"791d5a5b-a7ba-4e9e-b533-51b33c7d7747":{"label":"Unique","dataType":"number","operationType":"unique_count","scale":"ratio","sourceField":"clientip","isBucketed":false,"customLabel":true},"611e3509-e834-4fdd-b573-44e959e95d27":{"label":"95th percentile of bytes","dataType":"number","operationType":"percentile","sourceField":"bytes","isBucketed":false,"scale":"ratio","params":{"percentile":95,"format":{"id":"bytes","params":{"decimals":0}}}},"9f79ecca-123f-4098-a658-6b0e998da003":{"label":"Median of bytes","dataType":"number","operationType":"median","sourceField":"bytes","isBucketed":false,"scale":"ratio","params":{"format":{"id":"bytes","params":{"decimals":0}}}},"491285fd-0196-402c-9b7f-4660fdc1c22aX0":{"label":"Part of HTTP 5xx","dataType":"number","operationType":"count","isBucketed":false,"scale":"ratio","sourceField":"___records___","filter":{"query":"response.keyword >= 500","language":"kuery"},"customLabel":true},"491285fd-0196-402c-9b7f-4660fdc1c22aX1":{"label":"Part of HTTP 5xx","dataType":"number","operationType":"count","isBucketed":false,"scale":"ratio","sourceField":"___records___","customLabel":true},"491285fd-0196-402c-9b7f-4660fdc1c22aX2":{"label":"Part of HTTP 5xx","dataType":"number","operationType":"math","isBucketed":false,"scale":"ratio","params":{"tinymathAst":{"type":"function","name":"divide","args":["491285fd-0196-402c-9b7f-4660fdc1c22aX0","491285fd-0196-402c-9b7f-4660fdc1c22aX1"],"location":{"min":0,"max":46},"text":"count(kql=\'response.keyword >= 500\') / count()"}},"references":["491285fd-0196-402c-9b7f-4660fdc1c22aX0","491285fd-0196-402c-9b7f-4660fdc1c22aX1"],"customLabel":true},"491285fd-0196-402c-9b7f-4660fdc1c22a":{"label":"HTTP 5xx","dataType":"number","operationType":"formula","isBucketed":false,"scale":"ratio","params":{"formula":"count(kql=\'response.keyword >= 500\') / count()","isFormulaBroken":false,"format":{"id":"percent","params":{"decimals":1}}},"references":["491285fd-0196-402c-9b7f-4660fdc1c22aX2"],"customLabel":true}},"columnOrder":["42783ad7-dbcf-4310-bc06-f21f4eaaac96","f7835375-4d5b-4839-95ea-41928192a319","791d5a5b-a7ba-4e9e-b533-51b33c7d7747","07fc84ca-4147-4ba9-879e-d1b4e086e1da","491285fd-0196-402c-9b7f-4660fdc1c22a","491285fd-0196-402c-9b7f-4660fdc1c22aX0","491285fd-0196-402c-9b7f-4660fdc1c22aX1","491285fd-0196-402c-9b7f-4660fdc1c22aX2","07fc84ca-4147-4ba9-879e-d1b4e086e1daX0","07fc84ca-4147-4ba9-879e-d1b4e086e1daX1","07fc84ca-4147-4ba9-879e-d1b4e086e1daX2","611e3509-e834-4fdd-b573-44e959e95d27","9f79ecca-123f-4098-a658-6b0e998da003"],"incompleteColumns":{}}}}},"visualization":{"layerId":"c35dc8ee-50d1-4ef7-8b4b-9c21a7e7d3b0","columns":[{"columnId":"42783ad7-dbcf-4310-bc06-f21f4eaaac96","width":650.6666666666666},{"columnId":"f7835375-4d5b-4839-95ea-41928192a319"},{"columnId":"491285fd-0196-402c-9b7f-4660fdc1c22a","isTransposed":false,"width":81.66666666666669,"colorMode":"cell","palette":{"name":"custom","type":"palette","params":{"steps":5,"stops":[{"color":"#fbddd6","stop":0.1},{"color":"#CC5642","stop":1}],"rangeType":"number","name":"custom","colorStops":[{"color":"#fbddd6","stop":0.05},{"color":"#CC5642","stop":0.1}],"rangeMin":0.05,"rangeMax":0.1}}},{"columnId":"07fc84ca-4147-4ba9-879e-d1b4e086e1da","isTransposed":false,"colorMode":"cell","palette":{"name":"custom","type":"palette","params":{"steps":5,"stops":[{"color":"#fbddd6","stop":0.1},{"color":"#cc5642","stop":1.1}],"name":"custom","colorStops":[{"color":"#fbddd6","stop":0.05},{"color":"#cc5642","stop":0.1}],"rangeType":"number","rangeMin":0.05,"rangeMax":0.1}}},{"columnId":"791d5a5b-a7ba-4e9e-b533-51b33c7d7747","isTransposed":false},{"columnId":"611e3509-e834-4fdd-b573-44e959e95d27","isTransposed":false},{"columnId":"9f79ecca-123f-4098-a658-6b0e998da003","isTransposed":false}],"sorting":{"columnId":"491285fd-0196-402c-9b7f-4660fdc1c22a","direction":"desc"},"layerType":"data","rowHeight":"single","rowHeightLines":1},"query":{"query":"","language":"kuery"},"filters":[]},"references":[{"id":"90943e30-9a47-11e8-b64d-95841ca0b247","name":"indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"90943e30-9a47-11e8-b64d-95841ca0b247","name":"indexpattern-datasource-layer-c35dc8ee-50d1-4ef7-8b4b-9c21a7e7d3b0","type":"index-pattern"}]},"enhancements":{"dynamicActions":{"events":[]}},"hidePanelTitles":false},"title":"[Logs] Errors by host"}]', + '[{"version":"8.8.0","type":"map","gridData":{"x":0,"y":14,"w":24,"h":18,"i":"4"},"panelIndex":"4","embeddableConfig":{"isLayerTOCOpen":false,"hiddenLayers":[],"mapCenter":{"lat":42.16337,"lon":-88.92107,"zoom":3.64},"openTOCDetails":[],"enhancements":{}},"panelRefName":"panel_4"},{"version":"8.8.0","type":"lens","gridData":{"x":36,"y":0,"w":12,"h":7,"i":"11"},"panelIndex":"11","embeddableConfig":{"attributes":{"title":"","visualizationType":"lnsMetric","type":"lens","references":[{"type":"index-pattern","id":"90943e30-9a47-11e8-b64d-95841ca0b247","name":"indexpattern-datasource-layer-28b89898-3feb-415a-8dd9-74d755ac7c2a"}],"state":{"visualization":{"layerId":"28b89898-3feb-415a-8dd9-74d755ac7c2a","layerType":"data","metricAccessor":"f92c482e-1eee-4c2a-9338-64fb3eec286a","palette":{"type":"palette","name":"status","params":{"steps":3,"rangeType":"number","rangeMin":0,"rangeMax":null,"progression":"fixed","stops":[{"color":"#23be8f","stop":0},{"color":"#fcd279","stop":608.66},{"color":"#f66d64","stop":1217.33}],"continuity":"above","maxSteps":5}}},"query":{"query":"","language":"kuery"},"filters":[],"datasourceStates":{"formBased":{"layers":{"28b89898-3feb-415a-8dd9-74d755ac7c2a":{"columns":{"f92c482e-1eee-4c2a-9338-64fb3eec286a":{"label":"Unique Visitors","dataType":"number","operationType":"unique_count","scale":"ratio","sourceField":"clientip","isBucketed":false,"params":{"emptyAsNull":true},"customLabel":true}},"columnOrder":["f92c482e-1eee-4c2a-9338-64fb3eec286a"],"incompleteColumns":{}}}},"textBased":{"layers":{}}},"internalReferences":[],"adHocDataViews":{}}},"hidePanelTitles":true,"enhancements":{}}},{"version":"8.8.0","type":"visualization","gridData":{"x":24,"y":14,"w":24,"h":33,"i":"14"},"panelIndex":"14","embeddableConfig":{"enhancements":{}},"panelRefName":"panel_14"},{"version":"8.8.0","type":"lens","gridData":{"x":0,"y":7,"w":24,"h":7,"i":"15"},"panelIndex":"15","embeddableConfig":{"attributes":{"title":"[Logs] Response Codes Over Time + Annotations (converted)","visualizationType":"lnsXY","type":"lens","references":[{"type":"index-pattern","id":"90943e30-9a47-11e8-b64d-95841ca0b247","name":"indexpattern-datasource-layer-b38fe501-4b47-4de8-a423-6656d1162174"},{"type":"index-pattern","id":"90943e30-9a47-11e8-b64d-95841ca0b247","name":"xy-visualization-layer-f265e722-ae38-495c-903c-48aa7931fa82"}],"state":{"visualization":{"legend":{"isVisible":true,"showSingleSeries":true,"position":"bottom","shouldTruncate":true,"maxLines":1},"valueLabels":"hide","fittingFunction":"None","fillOpacity":0.5,"yLeftExtent":{"mode":"full"},"yRightExtent":{"mode":"full"},"yLeftScale":"linear","yRightScale":"linear","axisTitlesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"tickLabelsVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"labelsOrientation":{"x":0,"yLeft":0,"yRight":0},"gridlinesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"preferredSeriesType":"bar_stacked","layers":[{"seriesType":"area_percentage_stacked","layerType":"data","layerId":"b38fe501-4b47-4de8-a423-6656d1162174","accessors":["896c5eb2-81c5-44f1-a4a1-57344161ea62"],"yConfig":[{"forAccessor":"896c5eb2-81c5-44f1-a4a1-57344161ea62","color":"rgba(115,216,255,1)","axisMode":"left"}],"xAccessor":"8986e393-d24f-49b0-96ca-118fd66d75e5","splitAccessor":"43f5bb0f-c6da-43a0-8a0a-50e9838ed34b","palette":{"name":"default","type":"palette"}},{"layerId":"f265e722-ae38-495c-903c-48aa7931fa82","layerType":"annotations","ignoreGlobalFilters":true,"annotations":[{"type":"query","id":"bd7548a0-2223-11e8-832f-d5027f3c8a47","label":"Event","key":{"type":"point_in_time"},"color":"#D33115","timeField":"timestamp","icon":"asterisk","filter":{"type":"kibana_query","query":"tags:error AND tags:security","language":"lucene"},"extraFields":["geo.src"]}]}]},"query":{"query":"","language":"kuery"},"filters":[],"datasourceStates":{"formBased":{"layers":{"b38fe501-4b47-4de8-a423-6656d1162174":{"columns":{"8986e393-d24f-49b0-96ca-118fd66d75e5":{"label":"timestamp","dataType":"date","operationType":"date_histogram","sourceField":"timestamp","isBucketed":true,"scale":"interval","params":{"interval":"auto","includeEmptyRows":true,"dropPartials":false}},"43f5bb0f-c6da-43a0-8a0a-50e9838ed34b":{"label":"Filters","dataType":"string","operationType":"filters","scale":"ordinal","isBucketed":true,"params":{"filters":[{"input":{"query":"response.keyword >= 200 and response.keyword < 400","language":"kuery"},"label":"HTTP 2xx and 3xx"},{"input":{"query":"response.keyword >= 400 and response.keyword < 500","language":"kuery"},"label":"HTTP 4xx"},{"input":{"query":"response.keyword >= 500","language":"kuery"},"label":"HTTP 5xx"}]}},"896c5eb2-81c5-44f1-a4a1-57344161ea62":{"label":"Response Code Count","dataType":"number","operationType":"count","isBucketed":false,"scale":"ratio","sourceField":"___records___","params":{"emptyAsNull":true},"customLabel":true}},"columnOrder":["8986e393-d24f-49b0-96ca-118fd66d75e5","43f5bb0f-c6da-43a0-8a0a-50e9838ed34b","896c5eb2-81c5-44f1-a4a1-57344161ea62"],"incompleteColumns":{}}}},"textBased":{"layers":{}}},"internalReferences":[],"adHocDataViews":{}}},"enhancements":{},"hidePanelTitles":false},"title":"[Logs] Response Codes Over Time + Annotations"},{"version":"8.8.0","type":"visualization","gridData":{"x":0,"y":0,"w":24,"h":7,"i":"343f0bef-0b19-452e-b1c8-59beb18b6f0c"},"panelIndex":"343f0bef-0b19-452e-b1c8-59beb18b6f0c","embeddableConfig":{"savedVis":{"title":"[Logs] Markdown Instructions","description":"","type":"markdown","params":{"fontSize":12,"openLinksInNewTab":true,"markdown":"## Sample Logs Data\\nThis dashboard contains sample data for you to play with. You can view it, search it, and interact with the visualizations. For more information about Kibana, check our [docs](https://www.elastic.co/guide/en/kibana/current/index.html)."},"uiState":{},"data":{"aggs":[],"searchSource":{"query":{"query":"","language":"kuery"},"filter":[]}}},"enhancements":{},"hidePanelTitles":true}},{"version":"8.8.0","type":"lens","gridData":{"x":24,"y":0,"w":12,"h":7,"i":"bb94016e-f4a6-49ca-87a9-296a2869d570"},"panelIndex":"bb94016e-f4a6-49ca-87a9-296a2869d570","embeddableConfig":{"attributes":{"title":"","visualizationType":"lnsMetric","type":"lens","references":[{"type":"index-pattern","id":"90943e30-9a47-11e8-b64d-95841ca0b247","name":"indexpattern-datasource-layer-483defd2-775b-4a62-bdef-496c819bb8ed"}],"state":{"visualization":{"layerId":"483defd2-775b-4a62-bdef-496c819bb8ed","layerType":"data","metricAccessor":"37430d12-7452-4cc9-b035-5cfd4061edf0"},"query":{"query":"","language":"kuery"},"filters":[],"datasourceStates":{"formBased":{"layers":{"483defd2-775b-4a62-bdef-496c819bb8ed":{"columns":{"37430d12-7452-4cc9-b035-5cfd4061edf0":{"label":"Visits","dataType":"number","operationType":"count","isBucketed":false,"scale":"ratio","sourceField":"___records___","customLabel":true}},"columnOrder":["37430d12-7452-4cc9-b035-5cfd4061edf0"],"incompleteColumns":{}}}}},"internalReferences":[],"adHocDataViews":{}}},"enhancements":{}}},{"version":"8.8.0","type":"lens","gridData":{"x":36,"y":7,"w":12,"h":7,"i":"8c1456d4-1993-4ba2-b701-04aca02c9fef"},"panelIndex":"8c1456d4-1993-4ba2-b701-04aca02c9fef","embeddableConfig":{"attributes":{"title":"","visualizationType":"lnsMetric","type":"lens","references":[{"type":"index-pattern","id":"90943e30-9a47-11e8-b64d-95841ca0b247","name":"indexpattern-datasource-layer-f3793bb7-3971-4753-866d-4008e77a9f9a"}],"state":{"visualization":{"layerId":"f3793bb7-3971-4753-866d-4008e77a9f9a","layerType":"data","metricAccessor":"71c076a6-e782-4866-b8df-5fd85a41f08b"},"query":{"query":"","language":"kuery"},"filters":[],"datasourceStates":{"formBased":{"layers":{"f3793bb7-3971-4753-866d-4008e77a9f9a":{"columns":{"71c076a6-e782-4866-b8df-5fd85a41f08bX0":{"label":"Part of HTTP 5xx","dataType":"number","operationType":"count","isBucketed":false,"scale":"ratio","sourceField":"___records___","filter":{"query":"response.keyword >= 500","language":"kuery"},"params":{"emptyAsNull":false},"customLabel":true},"71c076a6-e782-4866-b8df-5fd85a41f08bX1":{"label":"Part of HTTP 5xx","dataType":"number","operationType":"count","isBucketed":false,"scale":"ratio","sourceField":"___records___","params":{"emptyAsNull":false},"customLabel":true},"71c076a6-e782-4866-b8df-5fd85a41f08bX2":{"label":"Part of HTTP 5xx","dataType":"number","operationType":"math","isBucketed":false,"scale":"ratio","params":{"tinymathAst":{"type":"function","name":"divide","args":["71c076a6-e782-4866-b8df-5fd85a41f08bX0","71c076a6-e782-4866-b8df-5fd85a41f08bX1"],"location":{"min":0,"max":46},"text":"count(kql=\'response.keyword >= 500\') / count()"}},"references":["71c076a6-e782-4866-b8df-5fd85a41f08bX0","71c076a6-e782-4866-b8df-5fd85a41f08bX1"],"customLabel":true},"71c076a6-e782-4866-b8df-5fd85a41f08b":{"label":"HTTP 5xx","dataType":"number","operationType":"formula","isBucketed":false,"scale":"ratio","params":{"formula":"count(kql=\'response.keyword >= 500\') / count()","isFormulaBroken":false,"format":{"id":"percent","params":{"decimals":1}}},"references":["71c076a6-e782-4866-b8df-5fd85a41f08bX2"],"customLabel":true}},"columnOrder":["71c076a6-e782-4866-b8df-5fd85a41f08b","71c076a6-e782-4866-b8df-5fd85a41f08bX0","71c076a6-e782-4866-b8df-5fd85a41f08bX1","71c076a6-e782-4866-b8df-5fd85a41f08bX2"],"incompleteColumns":{}}}}},"internalReferences":[],"adHocDataViews":{}}},"enhancements":{}}},{"version":"8.8.0","type":"lens","gridData":{"x":24,"y":7,"w":12,"h":7,"i":"01d8e435-91c0-484f-a11e-856747050b0a"},"panelIndex":"01d8e435-91c0-484f-a11e-856747050b0a","embeddableConfig":{"attributes":{"title":"","visualizationType":"lnsMetric","type":"lens","references":[{"type":"index-pattern","id":"90943e30-9a47-11e8-b64d-95841ca0b247","name":"indexpattern-datasource-layer-f3793bb7-3971-4753-866d-4008e77a9f9a"}],"state":{"visualization":{"layerId":"f3793bb7-3971-4753-866d-4008e77a9f9a","layerType":"data","metricAccessor":"71c076a6-e782-4866-b8df-5fd85a41f08b"},"query":{"query":"","language":"kuery"},"filters":[],"datasourceStates":{"formBased":{"layers":{"f3793bb7-3971-4753-866d-4008e77a9f9a":{"columns":{"71c076a6-e782-4866-b8df-5fd85a41f08bX0":{"label":"Part of HTTP 4xx","dataType":"number","operationType":"count","isBucketed":false,"scale":"ratio","sourceField":"___records___","filter":{"query":"response.keyword >= 400 and response.keyword < 500","language":"kuery"},"params":{"emptyAsNull":false},"customLabel":true},"71c076a6-e782-4866-b8df-5fd85a41f08bX1":{"label":"Part of HTTP 4xx","dataType":"number","operationType":"count","isBucketed":false,"scale":"ratio","sourceField":"___records___","params":{"emptyAsNull":false},"customLabel":true},"71c076a6-e782-4866-b8df-5fd85a41f08bX2":{"label":"Part of HTTP 4xx","dataType":"number","operationType":"math","isBucketed":false,"scale":"ratio","params":{"tinymathAst":{"type":"function","name":"divide","args":["71c076a6-e782-4866-b8df-5fd85a41f08bX0","71c076a6-e782-4866-b8df-5fd85a41f08bX1"],"location":{"min":0,"max":73},"text":"count(kql=\'response.keyword >= 400 and response.keyword < 500\') / count()"}},"references":["71c076a6-e782-4866-b8df-5fd85a41f08bX0","71c076a6-e782-4866-b8df-5fd85a41f08bX1"],"customLabel":true},"71c076a6-e782-4866-b8df-5fd85a41f08b":{"label":"HTTP 4xx","dataType":"number","operationType":"formula","isBucketed":false,"scale":"ratio","params":{"formula":"count(kql=\'response.keyword >= 400 and response.keyword < 500\') / count()","isFormulaBroken":false,"format":{"id":"percent","params":{"decimals":1}}},"references":["71c076a6-e782-4866-b8df-5fd85a41f08bX2"],"customLabel":true}},"columnOrder":["71c076a6-e782-4866-b8df-5fd85a41f08b","71c076a6-e782-4866-b8df-5fd85a41f08bX0","71c076a6-e782-4866-b8df-5fd85a41f08bX1","71c076a6-e782-4866-b8df-5fd85a41f08bX2"],"incompleteColumns":{}}}}},"internalReferences":[],"adHocDataViews":{}}},"enhancements":{}}},{"version":"8.8.0","type":"visualization","gridData":{"x":0,"y":32,"w":24,"h":15,"i":"8e59c7cf-6e42-4343-a113-c4a255fcf2ce"},"panelIndex":"8e59c7cf-6e42-4343-a113-c4a255fcf2ce","embeddableConfig":{"savedVis":{"title":"","description":"","type":"vega","params":{"spec":"{\\n $schema: https://vega.github.io/schema/vega-lite/v5.json\\n data: {\\n url: {\\n %context%: true\\n %timefield%: @timestamp\\n index: kibana_sample_data_logs\\n body: {\\n aggs: {\\n countries: {\\n terms: {\\n field: geo.src\\n size: 25\\n }\\n aggs: {\\n hours: {\\n histogram: {\\n field: hour_of_day\\n interval: 1\\n }\\n aggs: {\\n unique: {\\n cardinality: {\\n field: clientip\\n }\\n }\\n }\\n }\\n }\\n }\\n }\\n size: 0\\n }\\n }\\n format: {property: \\"aggregations.countries.buckets\\"}\\n }\\n \\n transform: [\\n {\\n flatten: [\\"hours.buckets\\"],\\n as: [\\"buckets\\"]\\n }\\n ]\\n\\n mark: {\\n type: rect\\n tooltip: true\\n }\\n\\n encoding: {\\n x: {\\n field: buckets.key\\n type: ordinal\\n axis: {\\n title: false\\n labelAngle: 0\\n }\\n }\\n y: {\\n field: key\\n type: nominal\\n sort: {\\n field: -buckets.unique.value\\n }\\n axis: {title: false}\\n }\\n color: {\\n field: buckets.unique.value\\n type: quantitative\\n axis: {title: false}\\n scale: {\\n scheme: reds\\n }\\n }\\n }\\n}\\n"},"uiState":{},"data":{"aggs":[],"searchSource":{"query":{"query":"","language":"kuery"},"filter":[]}}},"enhancements":{}},"panelRefName":"panel_8e59c7cf-6e42-4343-a113-c4a255fcf2ce"},{"version":"8.8.0","type":"lens","gridData":{"x":0,"y":47,"w":24,"h":13,"i":"21bb0939-ee09-4021-8848-6552b3a6a788"},"panelIndex":"21bb0939-ee09-4021-8848-6552b3a6a788","embeddableConfig":{"attributes":{"title":"","visualizationType":"lnsDatatable","type":"lens","references":[{"type":"index-pattern","id":"90943e30-9a47-11e8-b64d-95841ca0b247","name":"indexpattern-datasource-layer-c840e93e-2949-4723-ad35-6bdb2d724404"}],"state":{"visualization":{"columns":[{"columnId":"4e64d6d7-4f92-4d5e-abbb-13796604db30","isTransposed":false},{"columnId":"fb9a848d-76f3-4005-a067-4259a50b5621","isTransposed":false},{"columnId":"a2760bc2-9a6e-46a1-8595-86f61573c7cf","isTransposed":false},{"columnId":"2c8bd8d5-35ff-4386-8d27-3ba882b13e43","isTransposed":false,"colorMode":"text","palette":{"type":"palette","name":"status","params":{"steps":5,"stops":[{"color":"#23be8f","stop":20},{"color":"#9dedce","stop":40},{"color":"#fcd279","stop":60},{"color":"#ffc0b8","stop":80},{"color":"#f66d64","stop":100}],"rangeType":"percent","rangeMin":20,"rangeMax":null,"continuity":"above","reverse":false}}},{"columnId":"defa6f97-b874-4556-8438-056fb437787b","isTransposed":false,"colorMode":"text","palette":{"type":"palette","name":"status","params":{"steps":5,"stops":[{"color":"#23be8f","stop":20},{"color":"#9dedce","stop":40},{"color":"#fcd279","stop":60},{"color":"#ffc0b8","stop":80},{"color":"#f66d64","stop":100}],"rangeType":"percent","rangeMin":20,"rangeMax":null,"continuity":"above","reverse":false}}}],"layerId":"c840e93e-2949-4723-ad35-6bdb2d724404","layerType":"data"},"query":{"query":"","language":"kuery"},"filters":[],"datasourceStates":{"formBased":{"layers":{"c840e93e-2949-4723-ad35-6bdb2d724404":{"columns":{"4e64d6d7-4f92-4d5e-abbb-13796604db30":{"label":"Type","dataType":"string","operationType":"terms","scale":"ordinal","sourceField":"extension.keyword","isBucketed":true,"params":{"size":10,"orderBy":{"type":"column","columnId":"fb9a848d-76f3-4005-a067-4259a50b5621"},"orderDirection":"desc","otherBucket":true,"missingBucket":false,"parentFormat":{"id":"terms"},"include":[],"exclude":[],"includeIsRegex":false,"excludeIsRegex":false},"customLabel":true},"fb9a848d-76f3-4005-a067-4259a50b5621":{"label":"Bytes (Total)","dataType":"number","operationType":"sum","sourceField":"bytes","isBucketed":false,"scale":"ratio","params":{"emptyAsNull":true,"format":{"id":"bytes","params":{"decimals":2}}},"customLabel":true},"a2760bc2-9a6e-46a1-8595-86f61573c7cf":{"label":"Bytes (Last Hour)","dataType":"number","operationType":"sum","sourceField":"bytes","isBucketed":false,"scale":"ratio","reducedTimeRange":"1h","params":{"emptyAsNull":true,"format":{"id":"bytes","params":{"decimals":2}}},"customLabel":true},"2c8bd8d5-35ff-4386-8d27-3ba882b13e43":{"label":"Unique Visits (Total)","dataType":"number","operationType":"unique_count","scale":"ratio","sourceField":"clientip","isBucketed":false,"params":{"emptyAsNull":true},"customLabel":true},"defa6f97-b874-4556-8438-056fb437787b":{"label":"Unique count of clientip","dataType":"number","operationType":"unique_count","scale":"ratio","sourceField":"clientip","isBucketed":false,"reducedTimeRange":"1h","params":{"emptyAsNull":true}}},"columnOrder":["4e64d6d7-4f92-4d5e-abbb-13796604db30","fb9a848d-76f3-4005-a067-4259a50b5621","a2760bc2-9a6e-46a1-8595-86f61573c7cf","2c8bd8d5-35ff-4386-8d27-3ba882b13e43","defa6f97-b874-4556-8438-056fb437787b"],"sampling":1,"incompleteColumns":{}}}},"textBased":{"layers":{}}},"internalReferences":[],"adHocDataViews":{}}},"enhancements":{}}},{"version":"8.8.0","type":"lens","gridData":{"x":24,"y":47,"w":24,"h":13,"i":"cbca842c-b9fa-4523-9ce0-14e350866e33"},"panelIndex":"cbca842c-b9fa-4523-9ce0-14e350866e33","embeddableConfig":{"hidePanelTitles":false,"enhancements":{}},"title":"[Logs] Bytes distribution","panelRefName":"panel_cbca842c-b9fa-4523-9ce0-14e350866e33"},{"version":"8.8.0","type":"lens","gridData":{"x":0,"y":60,"w":48,"h":19,"i":"1d5f0b3f-d9d2-4b26-997b-83bc5ca3090b"},"panelIndex":"1d5f0b3f-d9d2-4b26-997b-83bc5ca3090b","embeddableConfig":{"attributes":{"title":"","type":"lens","visualizationType":"lnsDatatable","state":{"datasourceStates":{"formBased":{"layers":{"c35dc8ee-50d1-4ef7-8b4b-9c21a7e7d3b0":{"columns":{"42783ad7-dbcf-4310-bc06-f21f4eaaac96":{"label":"URL","dataType":"string","operationType":"terms","scale":"ordinal","sourceField":"url.keyword","isBucketed":true,"params":{"size":1000,"orderBy":{"type":"column","columnId":"f7835375-4d5b-4839-95ea-41928192a319"},"orderDirection":"desc","otherBucket":true,"missingBucket":false},"customLabel":true},"f7835375-4d5b-4839-95ea-41928192a319":{"label":"Visits","dataType":"number","operationType":"count","isBucketed":false,"scale":"ratio","sourceField":"___records___","customLabel":true},"07fc84ca-4147-4ba9-879e-d1b4e086e1daX0":{"label":"Part of HTTP 4xx","dataType":"number","operationType":"count","isBucketed":false,"scale":"ratio","sourceField":"___records___","filter":{"query":"response.keyword >= 400 and response.keyword < 500","language":"kuery"},"customLabel":true},"07fc84ca-4147-4ba9-879e-d1b4e086e1daX1":{"label":"Part of HTTP 4xx","dataType":"number","operationType":"count","isBucketed":false,"scale":"ratio","sourceField":"___records___","customLabel":true},"07fc84ca-4147-4ba9-879e-d1b4e086e1daX2":{"label":"Part of HTTP 4xx","dataType":"number","operationType":"math","isBucketed":false,"scale":"ratio","params":{"tinymathAst":{"type":"function","name":"divide","args":["07fc84ca-4147-4ba9-879e-d1b4e086e1daX0","07fc84ca-4147-4ba9-879e-d1b4e086e1daX1"],"location":{"min":0,"max":73},"text":"count(kql=\'response.keyword >= 400 and response.keyword < 500\') / count()"}},"references":["07fc84ca-4147-4ba9-879e-d1b4e086e1daX0","07fc84ca-4147-4ba9-879e-d1b4e086e1daX1"],"customLabel":true},"07fc84ca-4147-4ba9-879e-d1b4e086e1da":{"label":"HTTP 4xx","dataType":"number","operationType":"formula","isBucketed":false,"scale":"ratio","params":{"formula":"count(kql=\'response.keyword >= 400 and response.keyword < 500\') / count()","isFormulaBroken":false,"format":{"id":"percent","params":{"decimals":1}}},"references":["07fc84ca-4147-4ba9-879e-d1b4e086e1daX2"],"customLabel":true},"791d5a5b-a7ba-4e9e-b533-51b33c7d7747":{"label":"Unique","dataType":"number","operationType":"unique_count","scale":"ratio","sourceField":"clientip","isBucketed":false,"customLabel":true},"611e3509-e834-4fdd-b573-44e959e95d27":{"label":"95th percentile of bytes","dataType":"number","operationType":"percentile","sourceField":"bytes","isBucketed":false,"scale":"ratio","params":{"percentile":95,"format":{"id":"bytes","params":{"decimals":0}}}},"9f79ecca-123f-4098-a658-6b0e998da003":{"label":"Median of bytes","dataType":"number","operationType":"median","sourceField":"bytes","isBucketed":false,"scale":"ratio","params":{"format":{"id":"bytes","params":{"decimals":0}}}},"491285fd-0196-402c-9b7f-4660fdc1c22aX0":{"label":"Part of HTTP 5xx","dataType":"number","operationType":"count","isBucketed":false,"scale":"ratio","sourceField":"___records___","filter":{"query":"response.keyword >= 500","language":"kuery"},"customLabel":true},"491285fd-0196-402c-9b7f-4660fdc1c22aX1":{"label":"Part of HTTP 5xx","dataType":"number","operationType":"count","isBucketed":false,"scale":"ratio","sourceField":"___records___","customLabel":true},"491285fd-0196-402c-9b7f-4660fdc1c22aX2":{"label":"Part of HTTP 5xx","dataType":"number","operationType":"math","isBucketed":false,"scale":"ratio","params":{"tinymathAst":{"type":"function","name":"divide","args":["491285fd-0196-402c-9b7f-4660fdc1c22aX0","491285fd-0196-402c-9b7f-4660fdc1c22aX1"],"location":{"min":0,"max":46},"text":"count(kql=\'response.keyword >= 500\') / count()"}},"references":["491285fd-0196-402c-9b7f-4660fdc1c22aX0","491285fd-0196-402c-9b7f-4660fdc1c22aX1"],"customLabel":true},"491285fd-0196-402c-9b7f-4660fdc1c22a":{"label":"HTTP 5xx","dataType":"number","operationType":"formula","isBucketed":false,"scale":"ratio","params":{"formula":"count(kql=\'response.keyword >= 500\') / count()","isFormulaBroken":false,"format":{"id":"percent","params":{"decimals":1}}},"references":["491285fd-0196-402c-9b7f-4660fdc1c22aX2"],"customLabel":true}},"columnOrder":["42783ad7-dbcf-4310-bc06-f21f4eaaac96","f7835375-4d5b-4839-95ea-41928192a319","791d5a5b-a7ba-4e9e-b533-51b33c7d7747","07fc84ca-4147-4ba9-879e-d1b4e086e1da","491285fd-0196-402c-9b7f-4660fdc1c22a","491285fd-0196-402c-9b7f-4660fdc1c22aX0","491285fd-0196-402c-9b7f-4660fdc1c22aX1","491285fd-0196-402c-9b7f-4660fdc1c22aX2","07fc84ca-4147-4ba9-879e-d1b4e086e1daX0","07fc84ca-4147-4ba9-879e-d1b4e086e1daX1","07fc84ca-4147-4ba9-879e-d1b4e086e1daX2","611e3509-e834-4fdd-b573-44e959e95d27","9f79ecca-123f-4098-a658-6b0e998da003"],"incompleteColumns":{}}}}},"visualization":{"layerId":"c35dc8ee-50d1-4ef7-8b4b-9c21a7e7d3b0","columns":[{"columnId":"42783ad7-dbcf-4310-bc06-f21f4eaaac96","width":650.6666666666666},{"columnId":"f7835375-4d5b-4839-95ea-41928192a319"},{"columnId":"491285fd-0196-402c-9b7f-4660fdc1c22a","isTransposed":false,"width":81.66666666666669,"colorMode":"cell","palette":{"type":"palette","name":"negative","params":{"steps":5,"stops":[{"color":"#fcdedc","stop":20},{"color":"#fec3bd","stop":40},{"color":"#fea79e","stop":60},{"color":"#fb8b81","stop":80},{"color":"#f66d64","stop":100}],"rangeType":"percent","rangeMin":20,"rangeMax":null,"continuity":"above","reverse":false}}},{"columnId":"07fc84ca-4147-4ba9-879e-d1b4e086e1da","isTransposed":false,"colorMode":"cell","palette":{"type":"palette","name":"negative","params":{"steps":5,"stops":[{"color":"#fcdedc","stop":20},{"color":"#fec3bd","stop":40},{"color":"#fea79e","stop":60},{"color":"#fb8b81","stop":80},{"color":"#f66d64","stop":100}],"rangeType":"percent","rangeMin":20,"rangeMax":null,"continuity":"above","reverse":false}}},{"columnId":"791d5a5b-a7ba-4e9e-b533-51b33c7d7747","isTransposed":false},{"columnId":"611e3509-e834-4fdd-b573-44e959e95d27","isTransposed":false},{"columnId":"9f79ecca-123f-4098-a658-6b0e998da003","isTransposed":false}],"sorting":{"columnId":"491285fd-0196-402c-9b7f-4660fdc1c22a","direction":"desc"},"layerType":"data","rowHeight":"single","rowHeightLines":1},"query":{"query":"","language":"kuery"},"filters":[]},"references":[{"id":"90943e30-9a47-11e8-b64d-95841ca0b247","name":"indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"90943e30-9a47-11e8-b64d-95841ca0b247","name":"indexpattern-datasource-layer-c35dc8ee-50d1-4ef7-8b4b-9c21a7e7d3b0","type":"index-pattern"}]},"enhancements":{"dynamicActions":{"events":[]}},"hidePanelTitles":false},"title":"[Logs] Errors by host"}]', timeFrom: 'now-7d/d', title: '[Logs] Web Traffic', timeTo: 'now', diff --git a/src/plugins/vis_types/vega/public/plugin.ts b/src/plugins/vis_types/vega/public/plugin.ts index e3d92425281b7..8816dd1ec7386 100644 --- a/src/plugins/vis_types/vega/public/plugin.ts +++ b/src/plugins/vis_types/vega/public/plugin.ts @@ -16,6 +16,8 @@ import { Setup as InspectorSetup } from '@kbn/inspector-plugin/public'; import type { MapsEmsPluginPublicStart } from '@kbn/maps-ems-plugin/public'; import { UsageCollectionStart } from '@kbn/usage-collection-plugin/public'; +import { KbnPalette, getKbnPalettes } from '@kbn/palettes'; +import { scheme } from 'vega'; import { setNotifications, setData, @@ -78,6 +80,15 @@ export class VegaPlugin implements Plugin { enableExternalUrls: this.initializerContext.config.get().enableExternalUrls, }); + core.theme.theme$ + .subscribe({ + next(theme) { + const palettes = getKbnPalettes(theme); + scheme('elastic', palettes.get(KbnPalette.Default).colors()); + }, + }) + .unsubscribe(); + const visualizationDependencies: Readonly = { core, plugins: { diff --git a/src/plugins/vis_types/vega/public/vega_view/vega_base_view.js b/src/plugins/vis_types/vega/public/vega_view/vega_base_view.js index d517e593e2227..89c2fbe8848c5 100644 --- a/src/plugins/vis_types/vega/public/vega_view/vega_base_view.js +++ b/src/plugins/vis_types/vega/public/vega_view/vega_base_view.js @@ -9,11 +9,10 @@ import moment from 'moment'; import dateMath from '@kbn/datemath'; -import { scheme, loader, logger, Warn, version as vegaVersion, expressionFunction } from 'vega'; +import { loader, logger, Warn, version as vegaVersion, expressionFunction } from 'vega'; import { expressionInterpreter } from 'vega-interpreter'; import { version as vegaLiteVersion } from 'vega-lite'; import { Utils } from '../data_model/utils'; -import { euiPaletteColorBlind } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { buildQueryFilter, compareFilters } from '@kbn/es-query'; import { TooltipHandler } from './vega_tooltip'; @@ -22,8 +21,6 @@ import { getEnableExternalUrls, getDataViews } from '../services'; import { extractIndexPatternsFromSpec } from '../lib/extract_index_pattern'; import { normalizeDate, normalizeString, normalizeObject } from './utils'; -scheme('elastic', euiPaletteColorBlind()); - // Vega's extension functions are global. When called, // we forward execution to the instance-specific handler // This functions must be declared in the VegaBaseView class diff --git a/tsconfig.base.json b/tsconfig.base.json index 3e1d80208f5b4..cb84a04f1706a 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -1362,6 +1362,8 @@ "@kbn/paertial-results-example-plugin/*": ["examples/partial_results_example/*"], "@kbn/painless-lab-plugin": ["x-pack/plugins/painless_lab"], "@kbn/painless-lab-plugin/*": ["x-pack/plugins/painless_lab/*"], + "@kbn/palettes": ["packages/kbn-palettes"], + "@kbn/palettes/*": ["packages/kbn-palettes/*"], "@kbn/panel-loader": ["packages/kbn-panel-loader"], "@kbn/panel-loader/*": ["packages/kbn-panel-loader/*"], "@kbn/peggy": ["packages/kbn-peggy"], diff --git a/x-pack/plugins/lens/public/lens_ui_telemetry/color_telemetry_helpers.ts b/x-pack/plugins/lens/public/lens_ui_telemetry/color_telemetry_helpers.ts index 049caea8fb12e..4f956e54c47f6 100644 --- a/x-pack/plugins/lens/public/lens_ui_telemetry/color_telemetry_helpers.ts +++ b/x-pack/plugins/lens/public/lens_ui_telemetry/color_telemetry_helpers.ts @@ -5,8 +5,9 @@ * 2.0. */ -import { ColorMapping, NeutralPalette, DEFAULT_OTHER_ASSIGNMENT_INDEX } from '@kbn/coloring'; +import { ColorMapping, DEFAULT_OTHER_ASSIGNMENT_INDEX } from '@kbn/coloring'; import { isEqual } from 'lodash'; +import { KbnPalette } from '@kbn/palettes'; import { nonNullable } from '../utils'; const COLOR_MAPPING_PREFIX = 'color_mapping_'; @@ -83,8 +84,8 @@ const getUnassignedTermsType = ( : specialAssignments[DEFAULT_OTHER_ASSIGNMENT_INDEX]?.color.type === 'loop' ? 'loop' : specialAssignments[DEFAULT_OTHER_ASSIGNMENT_INDEX]?.color.paletteId === - NeutralPalette.id - ? NeutralPalette.id + KbnPalette.Neutral + ? KbnPalette.Neutral : 'palette' }` : undefined; diff --git a/x-pack/plugins/lens/public/shared_components/coloring/color_mapping_accessor.ts b/x-pack/plugins/lens/public/shared_components/coloring/color_mapping_accessor.ts index 116b21bb2245d..7e3d076744d64 100644 --- a/x-pack/plugins/lens/public/shared_components/coloring/color_mapping_accessor.ts +++ b/x-pack/plugins/lens/public/shared_components/coloring/color_mapping_accessor.ts @@ -5,29 +5,20 @@ * 2.0. */ -import { - AVAILABLE_PALETTES, - getColorFactory, - getPalette, - NeutralPalette, - ColorMappingInputCategoricalData, -} from '@kbn/coloring'; +import { getColorFactory, ColorMappingInputCategoricalData } from '@kbn/coloring'; +import { KbnPalettes } from '@kbn/palettes'; import { CellColorFn } from './get_cell_color_fn'; /** * Return a color accessor function for XY charts depending on the split accessors received. */ export function getColorAccessorFn( + palettes: KbnPalettes, colorMapping: string, data: ColorMappingInputCategoricalData, isDarkMode: boolean ): CellColorFn { - const getColor = getColorFactory( - JSON.parse(colorMapping), - getPalette(AVAILABLE_PALETTES, NeutralPalette), - isDarkMode, - data - ); + const getColor = getColorFactory(JSON.parse(colorMapping), palettes, isDarkMode, data); return (value) => { if (value === undefined || value === null) return null; diff --git a/x-pack/plugins/lens/public/shared_components/coloring/color_mapping_by_terms.tsx b/x-pack/plugins/lens/public/shared_components/coloring/color_mapping_by_terms.tsx index 1eec5a4093275..ed07cd584824b 100644 --- a/x-pack/plugins/lens/public/shared_components/coloring/color_mapping_by_terms.tsx +++ b/x-pack/plugins/lens/public/shared_components/coloring/color_mapping_by_terms.tsx @@ -21,12 +21,12 @@ import { DEFAULT_COLOR_MAPPING_CONFIG, CategoricalColorMapping, SPECIAL_TOKENS_STRING_CONVERSION, - AVAILABLE_PALETTES, PaletteOutput, PaletteRegistry, CustomPaletteParams, } from '@kbn/coloring'; import { i18n } from '@kbn/i18n'; +import { KbnPalettes } from '@kbn/palettes'; import { trackUiCounterEvents } from '../../lens_ui_telemetry'; import { PalettePicker } from '../palette_picker'; import { PalettePanelContainer } from './palette_panel_container'; @@ -36,6 +36,7 @@ interface ColorMappingByTermsProps { isDarkMode: boolean; colorMapping?: ColorMapping.Config; palette?: PaletteOutput; + palettes: KbnPalettes; isInlineEditing?: boolean; setPalette: (palette: PaletteOutput) => void; setColorMapping: (colorMapping?: ColorMapping.Config) => void; @@ -48,6 +49,7 @@ export function ColorMappingByTerms({ isDarkMode, colorMapping, palette, + palettes, isInlineEditing, setPalette, setColorMapping, @@ -67,7 +69,7 @@ export function ColorMappingByTerms({ fullWidth > ) => void; paletteService: PaletteRegistry; panelRef: MutableRefObject; - dataBounds?: DataBounds; + dataBounds: DataBounds; } export function ColorMappingByValues({ diff --git a/x-pack/plugins/lens/public/shared_components/coloring/get_cell_color_fn.ts b/x-pack/plugins/lens/public/shared_components/coloring/get_cell_color_fn.ts index bb7e25220f793..f2db77f41b103 100644 --- a/x-pack/plugins/lens/public/shared_components/coloring/get_cell_color_fn.ts +++ b/x-pack/plugins/lens/public/shared_components/coloring/get_cell_color_fn.ts @@ -12,12 +12,14 @@ import { getSpecialString, } from '@kbn/coloring'; import { CustomPaletteState } from '@kbn/charts-plugin/common'; +import { KbnPalettes } from '@kbn/palettes'; import { getColorAccessorFn } from './color_mapping_accessor'; export type CellColorFn = (value?: number | string | null) => string | null; export function getCellColorFn( paletteService: PaletteRegistry, + palettes: KbnPalettes, data: ColorMappingInputData, colorByTerms: boolean, isDarkMode: boolean, @@ -37,7 +39,7 @@ export function getCellColorFn( if (colorByTerms && data.type === 'categories') { if (colorMapping) { - return getColorAccessorFn(colorMapping, data, isDarkMode); + return getColorAccessorFn(palettes, colorMapping, data, isDarkMode); } else if (palette) { return (category) => { if (category === undefined || category === null) return null; diff --git a/x-pack/plugins/lens/public/shared_components/coloring/utils.test.ts b/x-pack/plugins/lens/public/shared_components/coloring/utils.test.ts index cc6044fc0f624..27f17f3c72c66 100644 --- a/x-pack/plugins/lens/public/shared_components/coloring/utils.test.ts +++ b/x-pack/plugins/lens/public/shared_components/coloring/utils.test.ts @@ -5,53 +5,7 @@ * 2.0. */ -import { chartPluginMock } from '@kbn/charts-plugin/public/mocks'; -import { - applyPaletteParams, - findMinMaxByColumnId, - getContrastColor, - shouldColorByTerms, -} from './utils'; - -describe('applyPaletteParams', () => { - const paletteRegistry = chartPluginMock.createPaletteRegistry(); - it('should return a palette stops array only by the name', () => { - expect( - applyPaletteParams( - paletteRegistry, - { name: 'default', type: 'palette', params: { name: 'default' } }, - { min: 0, max: 100 } - ) - ).toEqual([ - // stops are 0 and 50 by with a 20 offset (100 divided by 5 steps) for display - // the mock palette service has only 2 colors so tests are a bit off by that - { color: 'red', stop: 20 }, - { color: 'black', stop: 70 }, - ]); - }); - - it('should return a palette stops array reversed', () => { - expect( - applyPaletteParams( - paletteRegistry, - { name: 'default', type: 'palette', params: { name: 'default', reverse: true } }, - { min: 0, max: 100 } - ) - ).toEqual([ - { color: 'black', stop: 20 }, - { color: 'red', stop: 70 }, - ]); - }); - - it('should pick the default palette from the activePalette object when passed', () => { - expect( - applyPaletteParams(paletteRegistry, { name: 'mocked', type: 'palette' }, { min: 0, max: 100 }) - ).toEqual([ - { color: 'blue', stop: 20 }, - { color: 'yellow', stop: 70 }, - ]); - }); -}); +import { findMinMaxByColumnId, getContrastColor, shouldColorByTerms } from './utils'; describe('getContrastColor', () => { it('should pick the light color when the passed one is dark', () => { diff --git a/x-pack/plugins/lens/public/shared_components/coloring/utils.ts b/x-pack/plugins/lens/public/shared_components/coloring/utils.ts index ae797c1daa6c6..b482aa83d4483 100644 --- a/x-pack/plugins/lens/public/shared_components/coloring/utils.ts +++ b/x-pack/plugins/lens/public/shared_components/coloring/utils.ts @@ -23,6 +23,7 @@ import { } from '@kbn/coloring'; import { getOriginalId } from '@kbn/transpose-utils'; import { Datatable, DatatableColumnType } from '@kbn/expressions-plugin/common'; +import { KbnPalettes } from '@kbn/palettes'; import { DataType } from '../../types'; /** @@ -30,17 +31,18 @@ import { DataType } from '../../types'; */ export function getColorStops( paletteService: PaletteRegistry, + palettes: KbnPalettes, isDarkMode: boolean, palette?: PaletteOutput, colorMapping?: ColorMapping.Config ): string[] { return colorMapping - ? getColorsFromMapping(isDarkMode, colorMapping) + ? getColorsFromMapping(palettes, isDarkMode, colorMapping) : palette?.name === CUSTOM_PALETTE ? palette?.params?.stops?.map(({ color }) => color) ?? [] : paletteService .get(palette?.name || DEFAULT_FALLBACK_PALETTE) - .getCategoricalColors(10, palette); + .getCategoricalColors(palette?.params?.steps || 10, palette); } /** diff --git a/x-pack/plugins/lens/public/visualizations/datatable/components/dimension_editor.tsx b/x-pack/plugins/lens/public/visualizations/datatable/components/dimension_editor.tsx index c67cf3cdb9b1a..90c644555d6f6 100644 --- a/x-pack/plugins/lens/public/visualizations/datatable/components/dimension_editor.tsx +++ b/x-pack/plugins/lens/public/visualizations/datatable/components/dimension_editor.tsx @@ -8,15 +8,22 @@ import React, { useCallback } from 'react'; import { i18n } from '@kbn/i18n'; import { EuiFormRow, EuiSwitch, EuiButtonGroup, htmlIdGenerator } from '@elastic/eui'; -import { PaletteRegistry, getFallbackDataBounds } from '@kbn/coloring'; +import { + CUSTOM_PALETTE, + CustomPaletteParams, + PaletteOutput, + PaletteRegistry, + applyPaletteParams, + getFallbackDataBounds, +} from '@kbn/coloring'; import { getColorCategories } from '@kbn/chart-expressions-common'; import { useDebouncedValue } from '@kbn/visualization-utils'; import { getOriginalId } from '@kbn/transpose-utils'; +import { KbnPalettes } from '@kbn/palettes'; import type { VisualizationDimensionEditorProps } from '../../../types'; import type { DatatableVisualizationState } from '../visualization'; import { - applyPaletteParams, defaultPaletteParams, findMinMaxByColumnId, shouldColorByTerms, @@ -54,6 +61,7 @@ function updateColumn( export type TableDimensionEditorProps = VisualizationDimensionEditorProps & { paletteService: PaletteRegistry; + palettes: KbnPalettes; isDarkMode: boolean; }; @@ -99,14 +107,24 @@ export function TableDimensionEditor(props: TableDimensionEditorProps) { const minMaxByColumnId = findMinMaxByColumnId(columnsToCheck, currentData); const currentMinMax = minMaxByColumnId.get(accessor) ?? getFallbackDataBounds(); - const activePalette = column?.palette ?? { + const activePalette: PaletteOutput = { type: 'palette', name: showColorByTerms ? 'default' : defaultPaletteParams.name, + ...column?.palette, + params: { ...column?.palette?.params }, }; // need to tell the helper that the colorStops are required to display const displayStops = applyPaletteParams(props.paletteService, activePalette, currentMinMax); const categories = getColorCategories(currentData?.rows ?? [], accessor, false, [null]); + if (activePalette.name !== CUSTOM_PALETTE && activePalette.params?.stops) { + activePalette.params.stops = applyPaletteParams( + props.paletteService, + activePalette, + currentMinMax + ); + } + return ( <> { updateColumnState(accessor, { palette }); diff --git a/x-pack/plugins/lens/public/visualizations/datatable/components/table_basic.tsx b/x-pack/plugins/lens/public/visualizations/datatable/components/table_basic.tsx index 0633c13b8097a..4dad3ec9b0bab 100644 --- a/x-pack/plugins/lens/public/visualizations/datatable/components/table_basic.tsx +++ b/x-pack/plugins/lens/public/visualizations/datatable/components/table_basic.tsx @@ -33,6 +33,8 @@ import { IconChartDatatable } from '@kbn/chart-icons'; import useObservable from 'react-use/lib/useObservable'; import { getColorCategories } from '@kbn/chart-expressions-common'; import { getOriginalId, isTransposeId } from '@kbn/transpose-utils'; +import { CoreTheme } from '@kbn/core/public'; +import { getKbnPalettes } from '@kbn/palettes'; import type { LensTableRowContextMenuEvent } from '../../../types'; import type { FormatFactory } from '../../../../common/types'; import { RowHeightMode } from '../../../../common/types'; @@ -80,10 +82,11 @@ export const DatatableComponent = (props: DatatableRenderProps) => { const dataGridRef = useRef(null); const isInteractive = props.interactive; - const isDarkMode = useObservable(props.theme.theme$, { + const theme = useObservable(props.theme.theme$, { darkMode: false, name: 'amsterdam', - }).darkMode; + }); + const palettes = getKbnPalettes(theme); const [columnConfig, setColumnConfig] = useState({ columns: props.args.columns, @@ -419,9 +422,10 @@ export const DatatableComponent = (props: DatatableRenderProps) => { }; const colorFn = getCellColorFn( props.paletteService, + palettes, data, colorByTerms, - isDarkMode, + theme.darkMode, syncColors, palette, colorMapping @@ -435,16 +439,17 @@ export const DatatableComponent = (props: DatatableRenderProps) => { formatters, columnConfig, DataContext, - isDarkMode, + theme.darkMode, getCellColor, props.args.fitRowToContent ); }, [ formatters, columnConfig, - isDarkMode, + theme.darkMode, props.args.fitRowToContent, props.paletteService, + palettes, firstLocalTable, bucketedColumns, minMaxByColumnId, diff --git a/x-pack/plugins/lens/public/visualizations/datatable/visualization.tsx b/x-pack/plugins/lens/public/visualizations/datatable/visualization.tsx index efe5a39458eed..c3aac8e48016c 100644 --- a/x-pack/plugins/lens/public/visualizations/datatable/visualization.tsx +++ b/x-pack/plugins/lens/public/visualizations/datatable/visualization.tsx @@ -8,8 +8,15 @@ import React from 'react'; import { Ast } from '@kbn/interpreter'; import { i18n } from '@kbn/i18n'; -import { PaletteRegistry, CUSTOM_PALETTE, PaletteOutput, CustomPaletteParams } from '@kbn/coloring'; -import { ThemeServiceStart } from '@kbn/core/public'; +import { CoreTheme, ThemeServiceStart } from '@kbn/core/public'; +import { + PaletteRegistry, + CUSTOM_PALETTE, + PaletteOutput, + CustomPaletteParams, + applyPaletteParams, + getDefaultColorStops, +} from '@kbn/coloring'; import { VIS_EVENT_TO_TRIGGER } from '@kbn/visualizations-plugin/public'; import { IconChartDatatable } from '@kbn/chart-icons'; import { getOriginalId } from '@kbn/transpose-utils'; @@ -17,6 +24,7 @@ import { LayerTypes } from '@kbn/expression-xy-plugin/public'; import { buildExpression, buildExpressionFunction } from '@kbn/expressions-plugin/common'; import useObservable from 'react-use/lib/useObservable'; import { getSortingCriteria } from '@kbn/sort-predicates'; +import { getKbnPalettes } from '@kbn/palettes'; import type { FormBasedPersistedState } from '../../datasources/form_based/types'; import type { SuggestionRequest, @@ -45,7 +53,6 @@ import { DEFAULT_ROW_HEIGHT, } from './components/constants'; import { - applyPaletteParams, defaultPaletteParams, findMinMaxByColumnId, getColorStops, @@ -268,7 +275,9 @@ export const getDatatableVisualization = ({ on the Metric dimension in cases where there are no numeric columns **/ getConfiguration({ state, frame }) { - const isDarkMode = kibanaTheme.getTheme().darkMode; + const theme = kibanaTheme.getTheme(); + const palettes = getKbnPalettes(theme); + const { sortedColumns, datasource } = getDatasourceAndSortedColumns( state, frame.datasourceLayers @@ -320,7 +329,13 @@ export const getDatatableVisualization = ({ hidden, collapseFn, } = columnMap[accessor] ?? {}; - const stops = getColorStops(paletteService, isDarkMode, palette, colorMapping); + const stops = getColorStops( + paletteService, + palettes, + theme.darkMode, + palette, + colorMapping + ); const hasColoring = colorMode !== 'none' && stops.length > 0; return { @@ -407,7 +422,13 @@ export const getDatatableVisualization = ({ colorMapping, hidden, } = columnMap[accessor] ?? {}; - const stops = getColorStops(paletteService, isDarkMode, palette, colorMapping); + const stops = getColorStops( + paletteService, + palettes, + theme.darkMode, + palette, + colorMapping + ); const hasColoring = colorMode !== 'none' && stops.length > 0; return { @@ -465,13 +486,19 @@ export const getDatatableVisualization = ({ }; }, DimensionEditorComponent(props) { - const isDarkMode = useObservable(kibanaTheme.theme$, { + const theme = useObservable(kibanaTheme.theme$, { darkMode: false, name: 'amsterdam', - }).darkMode; + }); + const palettes = getKbnPalettes(theme); return ( - + ); }, @@ -556,13 +583,14 @@ export const getDatatableVisualization = ({ columns: columns .filter((c) => !c.collapseFn) .map((column) => { + const colorStops = getDefaultColorStops(paletteService, column.palette); const paletteParams = { ...column.palette?.params, // rewrite colors and stops as two distinct arguments - colors: (column.palette?.params?.stops || []).map(({ color }) => color), + colors: colorStops?.map(({ color }) => color), stops: column.palette?.params?.name === RowHeightMode.custom - ? (column.palette?.params?.stops || []).map(({ stop }) => stop) + ? colorStops?.map(({ stop }) => stop) : [], reverse: false, // managed at UI level }; diff --git a/x-pack/plugins/lens/public/visualizations/gauge/dimension_editor.tsx b/x-pack/plugins/lens/public/visualizations/gauge/dimension_editor.tsx index fdbe6913d21c9..8c1d3bd96f2d3 100644 --- a/x-pack/plugins/lens/public/visualizations/gauge/dimension_editor.tsx +++ b/x-pack/plugins/lens/public/visualizations/gauge/dimension_editor.tsx @@ -8,12 +8,17 @@ import { EuiFormRow, EuiSwitchEvent, EuiSwitch, EuiIcon } from '@elastic/eui'; import React from 'react'; import { i18n } from '@kbn/i18n'; -import { PaletteRegistry, CustomizablePalette, CUSTOM_PALETTE } from '@kbn/coloring'; +import { + PaletteRegistry, + CustomizablePalette, + CUSTOM_PALETTE, + applyPaletteParams, +} from '@kbn/coloring'; import { GaugeTicksPositions, GaugeColorModes } from '@kbn/expression-gauge-plugin/common'; import { getMaxValue, getMinValue } from '@kbn/expression-gauge-plugin/public'; import { TooltipWrapper } from '@kbn/visualization-utils'; import { isNumericFieldForDatatable } from '../../../common/expressions/datatable/utils'; -import { applyPaletteParams, PalettePanelContainer } from '../../shared_components'; +import { PalettePanelContainer } from '../../shared_components'; import type { VisualizationDimensionEditorProps } from '../../types'; import type { GaugeVisualizationState } from './constants'; import { defaultPaletteParams } from './palette_config'; diff --git a/x-pack/plugins/lens/public/visualizations/gauge/palette_config.tsx b/x-pack/plugins/lens/public/visualizations/gauge/palette_config.tsx index a2399c897b39b..db8a9f14f46b1 100644 --- a/x-pack/plugins/lens/public/visualizations/gauge/palette_config.tsx +++ b/x-pack/plugins/lens/public/visualizations/gauge/palette_config.tsx @@ -40,7 +40,7 @@ export const transparentizePalettes = (palettes: PaletteRegistry) => { state?: unknown ) => addAlpha(palette.getCategoricalColor(series, chartConfiguration, state)), getCategoricalColors: (size: number, state?: unknown): string[] => - palette.getCategoricalColors(size, state).map(addAlpha), + palette.getCategoricalColors(size, state), }); return { diff --git a/x-pack/plugins/lens/public/visualizations/gauge/visualization.tsx b/x-pack/plugins/lens/public/visualizations/gauge/visualization.tsx index e1ef2b03e4264..19b871bfc089e 100644 --- a/x-pack/plugins/lens/public/visualizations/gauge/visualization.tsx +++ b/x-pack/plugins/lens/public/visualizations/gauge/visualization.tsx @@ -11,7 +11,14 @@ import { ThemeServiceStart } from '@kbn/core/public'; import { FormattedMessage } from '@kbn/i18n-react'; import { Ast } from '@kbn/interpreter'; import { buildExpressionFunction, DatatableRow } from '@kbn/expressions-plugin/common'; -import { PaletteRegistry, CustomPaletteParams, CUSTOM_PALETTE } from '@kbn/coloring'; +import { + PaletteRegistry, + CustomPaletteParams, + CUSTOM_PALETTE, + applyPaletteParams, + getDefaultColorStops, + PaletteOutput, +} from '@kbn/coloring'; import type { GaugeExpressionFunctionDefinition, GaugeShape, @@ -37,7 +44,6 @@ import type { import { getSuggestions } from './suggestions'; import { GROUP_ID, LENS_GAUGE_ID, GaugeVisualizationState } from './constants'; import { GaugeToolbar } from './toolbar_component'; -import { applyPaletteParams } from '../../shared_components'; import { GaugeDimensionEditor } from './dimension_editor'; import { generateId } from '../../id_generator'; import { getAccessorsFromState } from './utils'; @@ -61,12 +67,17 @@ export const isNumericMetric = (op: OperationMetadata) => export const isNumericDynamicMetric = (op: OperationMetadata) => isNumericMetric(op) && !op.isStaticValue; -function computePaletteParams(params: CustomPaletteParams) { +function computePaletteParams( + paletteService: PaletteRegistry, + palette: PaletteOutput +) { + const colorStops = getDefaultColorStops(paletteService, palette); + return { - ...params, + ...palette.params, // rewrite colors and stops as two distinct arguments - colors: (params?.stops || []).map(({ color }) => color), - stops: params?.name === 'custom' ? (params?.stops || []).map(({ stop }) => stop) : [], + colors: colorStops?.map(({ color }) => color), + stops: palette.params?.name === 'custom' ? colorStops?.map(({ stop }) => stop) : [], reverse: false, // managed at UI level }; } @@ -144,7 +155,9 @@ const toExpression = ( shape: state.shape ?? GaugeShapes.HORIZONTAL_BULLET, colorMode: state?.colorMode ?? 'none', palette: state.palette?.params - ? paletteService.get(CUSTOM_PALETTE).toExpression(computePaletteParams(state.palette.params)) + ? paletteService + .get(CUSTOM_PALETTE) + .toExpression(computePaletteParams(paletteService, state.palette)) : undefined, ticksPosition: state.ticksPosition ?? 'auto', labelMinor: state.labelMinor, diff --git a/x-pack/plugins/lens/public/visualizations/heatmap/utils.ts b/x-pack/plugins/lens/public/visualizations/heatmap/utils.ts index fe942dd40427c..66b2a10295016 100644 --- a/x-pack/plugins/lens/public/visualizations/heatmap/utils.ts +++ b/x-pack/plugins/lens/public/visualizations/heatmap/utils.ts @@ -5,9 +5,9 @@ * 2.0. */ -import type { PaletteRegistry } from '@kbn/coloring'; +import { applyPaletteParams, type PaletteRegistry } from '@kbn/coloring'; import type { Datatable } from '@kbn/expressions-plugin/common'; -import { applyPaletteParams, findMinMaxByColumnId } from '../../shared_components'; +import { findMinMaxByColumnId } from '../../shared_components'; import { DEFAULT_PALETTE_NAME } from './constants'; import type { HeatmapVisualizationState, Palette } from './types'; diff --git a/x-pack/plugins/lens/public/visualizations/heatmap/visualization.tsx b/x-pack/plugins/lens/public/visualizations/heatmap/visualization.tsx index 1fb747427a05d..e17e373a13870 100644 --- a/x-pack/plugins/lens/public/visualizations/heatmap/visualization.tsx +++ b/x-pack/plugins/lens/public/visualizations/heatmap/visualization.tsx @@ -11,7 +11,13 @@ import { FormattedMessage } from '@kbn/i18n-react'; import { Ast } from '@kbn/interpreter'; import { Position } from '@elastic/charts'; import { IconChartHeatmap } from '@kbn/chart-icons'; -import { CUSTOM_PALETTE, PaletteRegistry, CustomPaletteParams } from '@kbn/coloring'; +import { + CUSTOM_PALETTE, + PaletteRegistry, + CustomPaletteParams, + PaletteOutput, + getDefaultColorStops, +} from '@kbn/coloring'; import { ThemeServiceStart } from '@kbn/core/public'; import { VIS_EVENT_TO_TRIGGER } from '@kbn/visualizations-plugin/public'; import { LayerTypes } from '@kbn/expression-xy-plugin/public'; @@ -88,12 +94,17 @@ function getInitialState(): Omit +) { + const colorStops = getDefaultColorStops(paletteService, palette); + return { - ...params, + ...palette.params, // rewrite colors and stops as two distinct arguments - colors: (params?.stops || []).map(({ color }) => color), - stops: params?.name === 'custom' ? (params?.stops || []).map(({ stop }) => stop) : [], + colors: colorStops?.map(({ color }) => color), + stops: palette.params?.name === 'custom' ? colorStops?.map(({ stop }) => stop) : [], reverse: false, // managed at UI level }; } @@ -349,7 +360,7 @@ export const getHeatmapVisualization = ({ palette: state.palette?.params ? paletteService .get(CUSTOM_PALETTE) - .toExpression(computePaletteParams(state.palette?.params)) + .toExpression(computePaletteParams(paletteService, state.palette)) : paletteService.get(DEFAULT_PALETTE_NAME).toExpression(), legend: buildExpression([legendFn]), gridConfig: buildExpression([gridConfigFn]), @@ -407,7 +418,7 @@ export const getHeatmapVisualization = ({ palette: state.palette?.params ? paletteService .get(CUSTOM_PALETTE) - .toExpression(computePaletteParams(state.palette?.params)) + .toExpression(computePaletteParams(paletteService, state.palette)) : paletteService.get(DEFAULT_PALETTE_NAME).toExpression(), }); diff --git a/x-pack/plugins/lens/public/visualizations/legacy_metric/dimension_editor.tsx b/x-pack/plugins/lens/public/visualizations/legacy_metric/dimension_editor.tsx index c6eccd9a70727..e1821e6d292fb 100644 --- a/x-pack/plugins/lens/public/visualizations/legacy_metric/dimension_editor.tsx +++ b/x-pack/plugins/lens/public/visualizations/legacy_metric/dimension_editor.tsx @@ -5,13 +5,18 @@ * 2.0. */ import { EuiButtonGroup, EuiFormRow, htmlIdGenerator } from '@elastic/eui'; -import { PaletteRegistry, CustomizablePalette, CUSTOM_PALETTE } from '@kbn/coloring'; +import { + PaletteRegistry, + CustomizablePalette, + CUSTOM_PALETTE, + applyPaletteParams, +} from '@kbn/coloring'; import { i18n } from '@kbn/i18n'; import React from 'react'; import { ColorMode } from '@kbn/charts-plugin/common'; import type { LegacyMetricState } from '../../../common/types'; import { isNumericFieldForDatatable } from '../../../common/expressions/datatable/utils'; -import { applyPaletteParams, PalettePanelContainer } from '../../shared_components'; +import { PalettePanelContainer } from '../../shared_components'; import type { VisualizationDimensionEditorProps } from '../../types'; import { defaultPaletteParams } from './palette_config'; diff --git a/x-pack/plugins/lens/public/visualizations/legacy_metric/visualization.tsx b/x-pack/plugins/lens/public/visualizations/legacy_metric/visualization.tsx index 35983e52f80da..5ea4b57539461 100644 --- a/x-pack/plugins/lens/public/visualizations/legacy_metric/visualization.tsx +++ b/x-pack/plugins/lens/public/visualizations/legacy_metric/visualization.tsx @@ -7,7 +7,13 @@ import { i18n } from '@kbn/i18n'; import { euiThemeVars } from '@kbn/ui-theme'; import { Ast } from '@kbn/interpreter'; -import { PaletteOutput, PaletteRegistry, CUSTOM_PALETTE, shiftPalette } from '@kbn/coloring'; +import { + PaletteOutput, + PaletteRegistry, + CUSTOM_PALETTE, + shiftPalette, + getDefaultColorStops, +} from '@kbn/coloring'; import { ThemeServiceStart } from '@kbn/core/public'; import { ColorMode, CustomPaletteState } from '@kbn/charts-plugin/common'; import { VIS_EVENT_TO_TRIGGER } from '@kbn/visualizations-plugin/public'; @@ -65,20 +71,20 @@ const toExpression = ( const datasourceExpression = datasourceExpressionsByLayers[state.layerId]; const operation = datasource && datasource.getOperationForColumnId(state.accessor); - const stops = state.palette?.params?.stops || []; + const colorStops = getDefaultColorStops(paletteService, state.palette) ?? []; const isCustomPalette = state.palette?.params?.name === CUSTOM_PALETTE; const canColor = operation?.dataType === 'number'; const paletteParams = { ...state.palette?.params, - colors: stops.map(({ color }) => color), + colors: colorStops.map(({ color }) => color), stops: isCustomPalette || state.palette?.params?.rangeMax == null - ? stops.map(({ stop }) => stop) + ? colorStops.map(({ stop }) => stop) : shiftPalette( - stops, - Math.max(state.palette?.params?.rangeMax, ...stops.map(({ stop }) => stop)) + colorStops, + Math.max(state.palette?.params?.rangeMax, ...colorStops.map(({ stop }) => stop)) ).map(({ stop }) => stop), reverse: false, }; @@ -215,7 +221,8 @@ export const getLegacyMetricVisualization = ({ getConfiguration(props) { const hasColoring = props.state.palette != null; - const stops = props.state.palette?.params?.stops || []; + const colorStops = getDefaultColorStops(paletteService, props.state.palette); + return { groups: [ { @@ -236,7 +243,7 @@ export const getLegacyMetricVisualization = ({ { columnId: props.state.accessor, triggerIconType: hasColoring ? 'colorBy' : undefined, - palette: hasColoring ? stops.map(({ color }) => color) : undefined, + palette: hasColoring ? colorStops?.map(({ color }) => color) : undefined, }, ] : [], @@ -314,7 +321,7 @@ export const getLegacyMetricVisualization = ({ } const hasColoring = state.palette != null; - const stops = state.palette?.params?.stops || []; + const colorStops = getDefaultColorStops(paletteService, state.palette); return { layers: [ @@ -324,7 +331,7 @@ export const getLegacyMetricVisualization = ({ chartType: 'metric', ...this.getDescription(state), dimensions, - palette: hasColoring ? stops.map(({ color }) => color) : undefined, + palette: hasColoring ? colorStops?.map(({ color }) => color) : undefined, }, ], }; diff --git a/x-pack/plugins/lens/public/visualizations/metric/dimension_editor.tsx b/x-pack/plugins/lens/public/visualizations/metric/dimension_editor.tsx index 78fcd67f36431..5d98be54e23ed 100644 --- a/x-pack/plugins/lens/public/visualizations/metric/dimension_editor.tsx +++ b/x-pack/plugins/lens/public/visualizations/metric/dimension_editor.tsx @@ -24,6 +24,7 @@ import { CustomizablePalette, DEFAULT_MAX_STOP, DEFAULT_MIN_STOP, + applyPaletteParams, } from '@kbn/coloring'; import { getDataBoundsForPalette } from '@kbn/expression-metric-vis-plugin/public'; import { getColumnByAccessor } from '@kbn/visualizations-plugin/common/utils'; @@ -31,7 +32,7 @@ import { css } from '@emotion/react'; import { DebouncedInput, IconSelect } from '@kbn/visualization-ui-components'; import { useDebouncedValue } from '@kbn/visualization-utils'; import { isNumericFieldForDatatable } from '../../../common/expressions/datatable/utils'; -import { applyPaletteParams, PalettePanelContainer } from '../../shared_components'; +import { PalettePanelContainer } from '../../shared_components'; import type { VisualizationDimensionEditorProps } from '../../types'; import { defaultNumberPaletteParams, defaultPercentagePaletteParams } from './palette_config'; import { DEFAULT_MAX_COLUMNS, getDefaultColor, showingBar } from './visualization'; diff --git a/x-pack/plugins/lens/public/visualizations/metric/to_expression.ts b/x-pack/plugins/lens/public/visualizations/metric/to_expression.ts index 02292a4ddce0a..08739fb0a4a85 100644 --- a/x-pack/plugins/lens/public/visualizations/metric/to_expression.ts +++ b/x-pack/plugins/lens/public/visualizations/metric/to_expression.ts @@ -5,7 +5,13 @@ * 2.0. */ -import { CustomPaletteParams, CUSTOM_PALETTE, PaletteRegistry } from '@kbn/coloring'; +import { + CustomPaletteParams, + CUSTOM_PALETTE, + PaletteRegistry, + PaletteOutput, + getDefaultColorStops, +} from '@kbn/coloring'; import type { TrendlineExpressionFunctionDefinition, MetricVisExpressionFunctionDefinition, @@ -23,12 +29,17 @@ import { MetricVisualizationState } from './types'; import { metricStateDefaults } from './constants'; // TODO - deduplicate with gauges? -function computePaletteParams(params: CustomPaletteParams) { +function computePaletteParams( + paletteService: PaletteRegistry, + palette: PaletteOutput +) { + const colorStops = getDefaultColorStops(paletteService, palette); + return { - ...params, + ...palette.params, // rewrite colors and stops as two distinct arguments - colors: (params?.stops || []).map(({ color }) => color), - stops: params?.name === 'custom' ? (params?.stops || []).map(({ stop }) => stop) : [], + colors: colorStops?.map(({ color }) => color), + stops: palette.params?.name === 'custom' ? colorStops?.map(({ stop }) => stop) : [], reverse: false, // managed at UI level }; } @@ -162,7 +173,7 @@ export const toExpression = ( ? [ paletteService .get(CUSTOM_PALETTE) - .toExpression(computePaletteParams(state.palette.params as CustomPaletteParams)), + .toExpression(computePaletteParams(paletteService, state.palette)), ] : [], maxCols: state.maxCols ?? DEFAULT_MAX_COLUMNS, diff --git a/x-pack/plugins/lens/public/visualizations/metric/visualization.tsx b/x-pack/plugins/lens/public/visualizations/metric/visualization.tsx index 6d3bd42f26cfa..5a19c2364798c 100644 --- a/x-pack/plugins/lens/public/visualizations/metric/visualization.tsx +++ b/x-pack/plugins/lens/public/visualizations/metric/visualization.tsx @@ -7,7 +7,7 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; -import { PaletteRegistry } from '@kbn/coloring'; +import { PaletteRegistry, getDefaultColorStops } from '@kbn/coloring'; import { ThemeServiceStart } from '@kbn/core/public'; import { VIS_EVENT_TO_TRIGGER } from '@kbn/visualizations-plugin/public'; import { euiLightVars, euiThemeVars } from '@kbn/ui-theme'; @@ -60,6 +60,7 @@ export const metricLabel = i18n.translate('xpack.lens.metric.label', { }); const getMetricLayerConfiguration = ( + paletteService: PaletteRegistry, props: VisualizationConfigProps ): { groups: VisualizationDimensionGroupConfig[]; @@ -73,17 +74,20 @@ const getMetricLayerConfiguration = ( const getPrimaryAccessorDisplayConfig = (): Partial => { const hasDynamicColoring = Boolean(isMetricNumeric && props.state.palette); - const stops = props.state.palette?.params?.stops || []; - return hasDynamicColoring - ? { - triggerIconType: 'colorBy', - palette: stops.map(({ color }) => color), - } - : { - triggerIconType: 'color', - color: props.state.color ?? getDefaultColor(props.state, isMetricNumeric), - }; + if (hasDynamicColoring) { + const colorStops = getDefaultColorStops(paletteService, props.state.palette); + + return { + triggerIconType: 'colorBy', + palette: colorStops?.map(({ color }) => color), + }; + } + + return { + triggerIconType: 'color', + color: props.state.color ?? getDefaultColor(props.state, isMetricNumeric), + }; }; const isBucketed = (op: OperationMetadata) => op.isBucketed; @@ -354,7 +358,7 @@ export const getMetricVisualization = ({ getConfiguration(props) { return props.layerId === props.state.layerId - ? getMetricLayerConfiguration(props) + ? getMetricLayerConfiguration(paletteService, props) : getTrendlineLayerConfiguration(props); }, diff --git a/x-pack/plugins/lens/public/visualizations/partition/dimension_editor.tsx b/x-pack/plugins/lens/public/visualizations/partition/dimension_editor.tsx index 32f8f2e4c972a..387f2a6ff7a66 100644 --- a/x-pack/plugins/lens/public/visualizations/partition/dimension_editor.tsx +++ b/x-pack/plugins/lens/public/visualizations/partition/dimension_editor.tsx @@ -14,7 +14,6 @@ import { PaletteRegistry, ColorMapping, SPECIAL_TOKENS_STRING_CONVERSION, - AVAILABLE_PALETTES, getColorsFromMapping, } from '@kbn/coloring'; import { ColorPicker } from '@kbn/visualization-ui-components'; @@ -22,6 +21,7 @@ import { useDebouncedValue } from '@kbn/visualization-utils'; import { EuiFormRow, EuiFlexGroup, EuiFlexItem, EuiSwitch, EuiText, EuiBadge } from '@elastic/eui'; import { useState, useCallback } from 'react'; import { getColorCategories } from '@kbn/chart-expressions-common'; +import { KbnPalette, KbnPalettes } from '@kbn/palettes'; import { PieVisualizationState } from '../../../common/types'; import { VisualizationDimensionEditorProps } from '../../types'; import { PalettePanelContainer, PalettePicker } from '../../shared_components'; @@ -35,6 +35,7 @@ import { trackUiCounterEvents } from '../../lens_ui_telemetry'; type DimensionEditorProps = VisualizationDimensionEditorProps & { paletteService: PaletteRegistry; + palettes: KbnPalettes; isDarkMode: boolean; }; @@ -118,7 +119,7 @@ export function DimensionEditor(props: DimensionEditorProps) { }) : undefined; - const colors = getColorsFromMapping(props.isDarkMode, currentLayer.colorMapping); + const colors = getColorsFromMapping(props.palettes, props.isDarkMode, currentLayer.colorMapping); const table = props.frame.activeData?.[currentLayer.layerId]; const splitCategories = getColorCategories(table?.rows ?? [], props.accessor); @@ -183,7 +184,7 @@ export function DimensionEditor(props: DimensionEditorProps) { isDarkMode={props.isDarkMode} model={currentLayer.colorMapping ?? { ...DEFAULT_COLOR_MAPPING_CONFIG }} onModelUpdate={(model: ColorMapping.Config) => setColorMapping(model)} - palettes={AVAILABLE_PALETTES} + palettes={props.palettes} data={{ type: 'categories', categories: splitCategories, @@ -209,6 +210,7 @@ export function DimensionEditor(props: DimensionEditorProps) { {showColorPicker && ( (kibanaTheme.theme$, { darkMode: false, name: 'amsterdam', - }).darkMode; - return ; + }); + const palettes = getKbnPalettes(theme); + return ( + + ); }, DimensionEditorDataExtraComponent(props) { return ; diff --git a/x-pack/plugins/lens/public/visualizations/tagcloud/tagcloud_visualization.tsx b/x-pack/plugins/lens/public/visualizations/tagcloud/tagcloud_visualization.tsx index b457926fe373d..16ba1ecf61b75 100644 --- a/x-pack/plugins/lens/public/visualizations/tagcloud/tagcloud_visualization.tsx +++ b/x-pack/plugins/lens/public/visualizations/tagcloud/tagcloud_visualization.tsx @@ -7,7 +7,7 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; -import { ThemeServiceStart } from '@kbn/core/public'; +import { CoreTheme, ThemeServiceStart } from '@kbn/core/public'; import { VIS_EVENT_TO_TRIGGER } from '@kbn/visualizations-plugin/public'; import type { ExpressionTagcloudFunctionDefinition } from '@kbn/expression-tagcloud-plugin/common'; import { LayerTypes } from '@kbn/expression-xy-plugin/public'; @@ -20,6 +20,7 @@ import { PaletteRegistry, getColorsFromMapping } from '@kbn/coloring'; import { IconChartTagcloud } from '@kbn/chart-icons'; import { SystemPaletteExpressionFunctionDefinition } from '@kbn/charts-plugin/common'; import useObservable from 'react-use/lib/useObservable'; +import { getKbnPalettes } from '@kbn/palettes'; import type { OperationMetadata, Visualization } from '../..'; import { getColorMappingDefaults } from '../../utils'; import type { TagcloudState } from './types'; @@ -122,7 +123,8 @@ export const getTagcloudVisualization = ({ kibanaTheme.theme$ .subscribe({ next(theme) { - colors = getColorsFromMapping(theme.darkMode, state.colorMapping); + const palettes = getKbnPalettes(theme); + colors = getColorsFromMapping(palettes, theme.darkMode, state.colorMapping); }, }) .unsubscribe(); @@ -294,15 +296,18 @@ export const getTagcloudVisualization = ({ }, DimensionEditorComponent(props) { - const isDarkMode: boolean = useObservable(kibanaTheme.theme$, { + const theme = useObservable(kibanaTheme.theme$, { darkMode: false, name: 'amsterdam', - }).darkMode; + }); + const palettes = getKbnPalettes(theme); + if (props.groupId === TAG_GROUP_ID) { return ( void; frame: FramePublicAPI; @@ -42,6 +43,7 @@ export function TagsDimensionEditor({ setState, panelRef, isDarkMode, + palettes, paletteService, isInlineEditing, }: Props) { @@ -52,7 +54,7 @@ export function TagsDimensionEditor({ }); const [useNewColorMapping, setUseNewColorMapping] = useState(state.colorMapping ? true : false); - const colors = getColorsFromMapping(isDarkMode, state.colorMapping); + const colors = getColorsFromMapping(palettes, isDarkMode, state.colorMapping); const table = frame.activeData?.[state.layerId]; const splitCategories = getColorCategories(table?.rows ?? [], state.tagAccessor); @@ -136,7 +138,7 @@ export function TagsDimensionEditor({ isDarkMode={isDarkMode} model={state.colorMapping ?? { ...DEFAULT_COLOR_MAPPING_CONFIG }} onModelUpdate={(model: ColorMapping.Config) => setColorMapping(model)} - palettes={AVAILABLE_PALETTES} + palettes={palettes} data={{ type: 'categories', categories: splitCategories, diff --git a/x-pack/plugins/lens/public/visualizations/xy/visualization.tsx b/x-pack/plugins/lens/public/visualizations/xy/visualization.tsx index a01c26ece9c13..ceba71c4d4f35 100644 --- a/x-pack/plugins/lens/public/visualizations/xy/visualization.tsx +++ b/x-pack/plugins/lens/public/visualizations/xy/visualization.tsx @@ -12,7 +12,7 @@ import { i18n } from '@kbn/i18n'; import type { PaletteRegistry } from '@kbn/coloring'; import { IconChartBarReferenceLine, IconChartBarAnnotations } from '@kbn/chart-icons'; import { FieldFormatsStart } from '@kbn/field-formats-plugin/public'; -import { CoreStart, SavedObjectReference, ThemeServiceStart } from '@kbn/core/public'; +import { CoreStart, CoreTheme, SavedObjectReference, ThemeServiceStart } from '@kbn/core/public'; import { EventAnnotationServiceType } from '@kbn/event-annotation-plugin/public'; import { getAnnotationAccessor } from '@kbn/event-annotation-components'; import { VIS_EVENT_TO_TRIGGER } from '@kbn/visualizations-plugin/public'; @@ -29,6 +29,7 @@ import { getColorsFromMapping } from '@kbn/coloring'; import useObservable from 'react-use/lib/useObservable'; import { EuiPopover, EuiSelectable } from '@elastic/eui'; import { ToolbarButton } from '@kbn/shared-ux-button-toolbar'; +import { getKbnPalettes } from '@kbn/palettes'; import { generateId } from '../../id_generator'; import { isDraggedDataViewField, @@ -466,14 +467,14 @@ export const getXyVisualization = ({ kibanaTheme.theme$ .subscribe({ next(theme) { - colors = getColorsFromMapping(theme.darkMode, layer.colorMapping); + const palettes = getKbnPalettes(theme); + colors = getColorsFromMapping(palettes, theme.darkMode, layer.colorMapping); }, }) .unsubscribe(); } else { - colors = paletteService - .get(dataLayer.palette?.name || 'default') - .getCategoricalColors(10, dataLayer.palette?.params); + const palette = paletteService.get(dataLayer.palette?.name || 'default'); + colors = palette.getCategoricalColors(10, dataLayer.palette?.params); } return { @@ -742,17 +743,18 @@ export const getXyVisualization = ({ paletteService, }; - const isDarkMode: boolean = useObservable(kibanaTheme.theme$, { + const theme = useObservable(kibanaTheme.theme$, { darkMode: false, name: 'amsterdam', - }).darkMode; + }); + const palettes = getKbnPalettes(theme); const layer = props.state.layers.find((l) => l.layerId === props.layerId)!; const dimensionEditor = isReferenceLayer(layer) ? ( - + ) : isAnnotationsLayer(layer) ? ( ) : ( - + ); return dimensionEditor; diff --git a/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/dimension_editor.tsx b/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/dimension_editor.tsx index f06f2d861d865..994e254bea954 100644 --- a/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/dimension_editor.tsx +++ b/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/dimension_editor.tsx @@ -14,6 +14,7 @@ import { EuiButtonGroup, EuiFormRow, htmlIdGenerator } from '@elastic/eui'; import { PaletteRegistry, ColorMapping, PaletteOutput } from '@kbn/coloring'; import { getColorCategories } from '@kbn/chart-expressions-common'; import type { ValuesType } from 'utility-types'; +import { KbnPalette, KbnPalettes } from '@kbn/palettes'; import type { VisualizationDimensionEditorProps } from '../../../types'; import { State, XYState, XYDataLayerConfig, YConfig, YAxisMode } from '../types'; import { FormatFactory } from '../../../../common/types'; @@ -45,6 +46,7 @@ export function DataDimensionEditor( props: VisualizationDimensionEditorProps & { formatFactory: FormatFactory; paletteService: PaletteRegistry; + palettes: KbnPalettes; isDarkMode: boolean; } ) { @@ -144,6 +146,7 @@ export function DataDimensionEditor( setPalette={setPalette} setColorMapping={setColorMapping} paletteService={props.paletteService} + palettes={props.palettes} panelRef={props.panelRef} categories={splitCategories} /> @@ -165,6 +168,7 @@ export function DataDimensionEditor( overwriteColor={overwriteColor} defaultColor={assignedColor} disabledMessage={disabledMessage} + swatches={props.palettes.get(KbnPalette.Default).colors(10)} setConfig={setConfig} /> diff --git a/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/reference_line_config_panel/reference_line_panel.tsx b/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/reference_line_config_panel/reference_line_panel.tsx index cd9bb66443998..e36e19dd80c20 100644 --- a/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/reference_line_config_panel/reference_line_panel.tsx +++ b/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/reference_line_config_panel/reference_line_panel.tsx @@ -17,6 +17,7 @@ import { TextDecorationSetting, } from '@kbn/visualization-ui-components'; import { useDebouncedValue } from '@kbn/visualization-utils'; +import { KbnPalette, KbnPalettes } from '@kbn/palettes'; import { referenceLineIconsSet } from '../../../../shared_components/icon_set'; import type { VisualizationDimensionEditorProps } from '../../../../types'; import { State, XYState, XYReferenceLineLayerConfig, YConfig } from '../../types'; @@ -32,6 +33,7 @@ export const ReferenceLinePanel = ( props: VisualizationDimensionEditorProps & { formatFactory: FormatFactory; paletteService: PaletteRegistry; + palettes: KbnPalettes; } ) => { const { state, setState, layerId, accessor } = props; @@ -98,6 +100,7 @@ export const ReferenceLinePanel = ( defaultColor={defaultReferenceLineColor} setConfig={setConfig} disableHelpTooltip + swatches={props.palettes.get(KbnPalette.Default).colors(10)} label={i18n.translate('xpack.lens.xyChart.lineColor.label', { defaultMessage: 'Color', })} diff --git a/yarn.lock b/yarn.lock index d5acff31b563b..c0354c85bd102 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6510,6 +6510,10 @@ version "0.0.0" uid "" +"@kbn/palettes@link:packages/kbn-palettes": + version "0.0.0" + uid "" + "@kbn/panel-loader@link:packages/kbn-panel-loader": version "0.0.0" uid "" From 6682ac9d35c1740562c483fba380560679a82565 Mon Sep 17 00:00:00 2001 From: nickofthyme Date: Thu, 21 Nov 2024 11:11:01 -0600 Subject: [PATCH 02/41] chore: hardcode theme toggles [to be removed] --- .../core/ui-settings/core-ui-settings-common/src/theme.ts | 3 ++- .../core-ui-settings-server-internal/src/settings/theme.ts | 7 ++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/core/ui-settings/core-ui-settings-common/src/theme.ts b/packages/core/ui-settings/core-ui-settings-common/src/theme.ts index 73b465d5b192f..705695de9d9d9 100644 --- a/packages/core/ui-settings/core-ui-settings-common/src/theme.ts +++ b/packages/core/ui-settings/core-ui-settings-common/src/theme.ts @@ -35,7 +35,8 @@ export type ThemeTags = readonly ThemeTag[]; * An array of theme tags available in Kibana by default when not customized * using KBN_OPTIMIZER_THEMES environment variable. */ -export const DEFAULT_THEME_TAGS: ThemeTags = ThemeAmsterdamTags; +export const DEFAULT_THEME_TAGS: ThemeTags = SUPPORTED_THEME_TAGS; // TODO Nick put this back +// export const DEFAULT_THEME_TAGS: ThemeTags = ThemeAmsterdamTags; export const FALLBACK_THEME_TAG: ThemeTag = 'v8light'; diff --git a/packages/core/ui-settings/core-ui-settings-server-internal/src/settings/theme.ts b/packages/core/ui-settings/core-ui-settings-server-internal/src/settings/theme.ts index 36324f951952e..59eb6ebad1746 100644 --- a/packages/core/ui-settings/core-ui-settings-server-internal/src/settings/theme.ts +++ b/packages/core/ui-settings/core-ui-settings-server-internal/src/settings/theme.ts @@ -104,9 +104,10 @@ export const getThemeSettings = ( }), }, value: 'amsterdam', - readonly: Object.hasOwn(options, 'isThemeSwitcherEnabled') - ? !options.isThemeSwitcherEnabled - : true, + // TODO Nick put this back + // readonly: Object.hasOwn(options, 'isThemeSwitcherEnabled') + // ? !options.isThemeSwitcherEnabled + // : true, requiresPageReload: true, schema: schema.oneOf([ schema.literal('amsterdam'), From e28c66752e850d02a2cb32541bf8bfdb19ded9a0 Mon Sep 17 00:00:00 2001 From: nickofthyme Date: Thu, 21 Nov 2024 11:16:14 -0600 Subject: [PATCH 03/41] chore: add chart background color override --- .../charts/public/services/theme/theme.ts | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/plugins/charts/public/services/theme/theme.ts b/src/plugins/charts/public/services/theme/theme.ts index d7ec8c03e506c..9a846a3271f30 100644 --- a/src/plugins/charts/public/services/theme/theme.ts +++ b/src/plugins/charts/public/services/theme/theme.ts @@ -12,6 +12,7 @@ import { Observable, BehaviorSubject } from 'rxjs'; import { CoreSetup, CoreTheme } from '@kbn/core/public'; import { DARK_THEME, LIGHT_THEME, PartialTheme, Theme } from '@elastic/charts'; +import { euiThemeVars } from '@kbn/ui-theme'; export class ThemeService { /** Returns default charts theme */ @@ -102,8 +103,20 @@ export class ThemeService { */ public init(theme: CoreSetup['theme']) { this.theme$ = theme.theme$; - this.theme$.subscribe(({ darkMode }) => { - this._chartsBaseTheme$.next(darkMode ? DARK_THEME : LIGHT_THEME); + this.theme$.subscribe((newTheme) => { + this._chartsBaseTheme$.next(getChartTheme(newTheme)); }); } } + +// TODO: define these overrides in elastic/charts when Borealis becomes default +function getChartTheme(theme: CoreTheme): Theme { + const chartTheme = { ...(theme.darkMode ? DARK_THEME : LIGHT_THEME) }; + + if (theme.name !== 'amsterdam') { + const backgroundColor = euiThemeVars.euiColorEmptyShade; + chartTheme.background.color = backgroundColor; + } + + return chartTheme; +} From adea40a1b11b85a235763ca81084448619371348 Mon Sep 17 00:00:00 2001 From: nickofthyme Date: Fri, 22 Nov 2024 14:15:16 -0600 Subject: [PATCH 04/41] fix: color mappings, assign all button --- .../components/container/assigments.tsx | 16 ++++------------ .../color_mapping/config/assignments.ts | 2 +- 2 files changed, 5 insertions(+), 13 deletions(-) diff --git a/packages/kbn-coloring/src/shared_components/color_mapping/components/container/assigments.tsx b/packages/kbn-coloring/src/shared_components/color_mapping/components/container/assigments.tsx index af4ceae80a0d9..6abe702ca8bc3 100644 --- a/packages/kbn-coloring/src/shared_components/color_mapping/components/container/assigments.tsx +++ b/packages/kbn-coloring/src/shared_components/color_mapping/components/container/assigments.tsx @@ -99,13 +99,13 @@ export function AssignmentsConfig({ ? { type: 'categorical', paletteId: palette.id, - colorIndex: nextCategoricalIndex % palette.colors.length, + colorIndex: nextCategoricalIndex % palette.colors().length, } : { type: 'gradient' }, touched: false, }) ); - }, [assignments, colorMode.type, data.type, dispatch, palette.colors.length, palette.id]); + }, [assignments, colorMode.type, data.type, dispatch, palette]); const onClickAddAllCurrentCategories = useCallback(() => { if (data.type === 'categories') { @@ -127,7 +127,7 @@ export function AssignmentsConfig({ ? { type: 'categorical', paletteId: palette.id, - colorIndex: (nextCategoricalIndex + i) % palette.colors.length, + colorIndex: (nextCategoricalIndex + i) % palette.colors().length, } : { type: 'gradient' }, touched: false, @@ -136,15 +136,7 @@ export function AssignmentsConfig({ ); dispatch(addNewAssignments(newAssignments)); } - }, [ - data.type, - assignments, - unmatchingCategories, - dispatch, - colorMode.type, - palette.id, - palette.colors.length, - ]); + }, [data.type, assignments, unmatchingCategories, dispatch, colorMode.type, palette]); return ( Date: Fri, 22 Nov 2024 15:05:20 -0600 Subject: [PATCH 05/41] chore: add logic to use default eui base palette fn --- .../kbn-palettes/classes/color_fn_palette.ts | 22 +++++++++++++---- .../palettes/categorical/elastic.ts | 24 ++++++++++++++++++- .../palettes/gradient/complementary.ts | 1 + .../kbn-palettes/palettes/gradient/cool.ts | 1 + .../kbn-palettes/palettes/gradient/gray.ts | 1 + .../kbn-palettes/palettes/gradient/green.ts | 1 + .../kbn-palettes/palettes/gradient/red.ts | 1 + .../kbn-palettes/palettes/gradient/status.ts | 1 + .../palettes/gradient/temperature.ts | 1 + .../kbn-palettes/palettes/gradient/warm.ts | 1 + 10 files changed, 49 insertions(+), 5 deletions(-) diff --git a/packages/kbn-palettes/classes/color_fn_palette.ts b/packages/kbn-palettes/classes/color_fn_palette.ts index 2174645e1e7e2..707f82b8aae25 100644 --- a/packages/kbn-palettes/classes/color_fn_palette.ts +++ b/packages/kbn-palettes/classes/color_fn_palette.ts @@ -9,24 +9,38 @@ import { Optional } from 'utility-types'; import { KbnBasePaletteConfig, KbnBasePalette } from './palette'; -import { IKbnPalette } from './types'; +import { IKbnPalette, KbnPaletteType } from './types'; + +const DEFAULT_COLOR_COUNT = 10; export interface KbnColorFnPaletteConfig extends Optional { + type: KbnPaletteType; colorFn: (n: number) => string[]; + defaultNumberOfColors?: number; } export class KbnColorFnPalette extends KbnBasePalette implements IKbnPalette { - public readonly type = 'gradient' as const; + public readonly type: KbnPaletteType; #colorFn: (n: number) => string[]; + #defaultNumberOfColors: number; - constructor({ colorFn, colorCount = 10, ...rest }: KbnColorFnPaletteConfig) { + constructor({ + type, + colorFn, + defaultNumberOfColors, + colorCount = DEFAULT_COLOR_COUNT, + ...rest + }: KbnColorFnPaletteConfig) { super({ ...rest, colorCount }); + this.type = type; + this.#colorFn = colorFn; + this.#defaultNumberOfColors = defaultNumberOfColors ?? colorCount; } - public colors = (n: number = 10) => { + public colors = (n: number = this.#defaultNumberOfColors) => { return this.#colorFn(n); }; } diff --git a/packages/kbn-palettes/palettes/categorical/elastic.ts b/packages/kbn-palettes/palettes/categorical/elastic.ts index e466a08c1423b..5daeb5c98b09b 100644 --- a/packages/kbn-palettes/palettes/categorical/elastic.ts +++ b/packages/kbn-palettes/palettes/categorical/elastic.ts @@ -8,8 +8,30 @@ */ import { i18n } from '@kbn/i18n'; -import { KbnCategoricalPalette } from '../../classes/categorical_palette'; +import { euiPaletteColorBlind } from '@elastic/eui'; import { KbnPalette } from '../../constants'; +import { KbnColorFnPalette } from '../../classes/color_fn_palette'; +import { KbnCategoricalPalette } from '../../classes/categorical_palette'; + +/** + * This is not correctly returning the updated vis colors from eui. + * All gradient function work correctly. + */ +export const elasticPaletteBad = new KbnColorFnPalette({ + id: KbnPalette.Default, + type: 'categorical', + aliases: [ + 'elastic_borealis', // placeholder - not yet used + KbnPalette.Amsterdam, // to assign to existing default palettes + ], + colorCount: 10, + defaultNumberOfColors: 30, + name: i18n.translate('palettes.elastic.name', { + defaultMessage: 'Elastic (default)', + }), + // Return exact colors requested given enough rotations + colorFn: (n) => euiPaletteColorBlind({ rotations: Math.ceil(n / 10) }).slice(0, n), +}); export const elasticPalette = new KbnCategoricalPalette({ id: KbnPalette.Default, diff --git a/packages/kbn-palettes/palettes/gradient/complementary.ts b/packages/kbn-palettes/palettes/gradient/complementary.ts index dcce7be4034be..c61fc8d140d5d 100644 --- a/packages/kbn-palettes/palettes/gradient/complementary.ts +++ b/packages/kbn-palettes/palettes/gradient/complementary.ts @@ -14,6 +14,7 @@ import { KbnPalette } from '../../constants'; export const complementaryPalette = new KbnColorFnPalette({ id: KbnPalette.Complementary, + type: 'gradient', name: i18n.translate('palettes.complementary.name', { defaultMessage: 'Complementary', }), diff --git a/packages/kbn-palettes/palettes/gradient/cool.ts b/packages/kbn-palettes/palettes/gradient/cool.ts index fb93d45288ddc..2982cba8a35dd 100644 --- a/packages/kbn-palettes/palettes/gradient/cool.ts +++ b/packages/kbn-palettes/palettes/gradient/cool.ts @@ -14,6 +14,7 @@ import { KbnPalette } from '../../constants'; export const coolPalette = new KbnColorFnPalette({ id: KbnPalette.Cool, + type: 'gradient', name: i18n.translate('palettes.cool.name', { defaultMessage: 'Cool', }), diff --git a/packages/kbn-palettes/palettes/gradient/gray.ts b/packages/kbn-palettes/palettes/gradient/gray.ts index cfa415fed6809..24d6d2444ce57 100644 --- a/packages/kbn-palettes/palettes/gradient/gray.ts +++ b/packages/kbn-palettes/palettes/gradient/gray.ts @@ -14,6 +14,7 @@ import { KbnPalette } from '../../constants'; export const grayPalette = new KbnColorFnPalette({ id: KbnPalette.Gray, + type: 'gradient', name: i18n.translate('palettes.gray.name', { defaultMessage: 'Gray', }), diff --git a/packages/kbn-palettes/palettes/gradient/green.ts b/packages/kbn-palettes/palettes/gradient/green.ts index 4ac719ca63796..bb6655d575ea5 100644 --- a/packages/kbn-palettes/palettes/gradient/green.ts +++ b/packages/kbn-palettes/palettes/gradient/green.ts @@ -14,6 +14,7 @@ import { KbnPalette } from '../../constants'; export const greenPalette = new KbnColorFnPalette({ id: KbnPalette.Green, + type: 'gradient', name: i18n.translate('palettes.green.name', { defaultMessage: 'Positive', }), diff --git a/packages/kbn-palettes/palettes/gradient/red.ts b/packages/kbn-palettes/palettes/gradient/red.ts index e51271cc3bc1f..e2cd76df1e454 100644 --- a/packages/kbn-palettes/palettes/gradient/red.ts +++ b/packages/kbn-palettes/palettes/gradient/red.ts @@ -14,6 +14,7 @@ import { KbnPalette } from '../../constants'; export const redPalette = new KbnColorFnPalette({ id: KbnPalette.Red, + type: 'gradient', name: i18n.translate('palettes.red.name', { defaultMessage: 'Negative', }), diff --git a/packages/kbn-palettes/palettes/gradient/status.ts b/packages/kbn-palettes/palettes/gradient/status.ts index dbb36a4c4767c..db0c1931aae73 100644 --- a/packages/kbn-palettes/palettes/gradient/status.ts +++ b/packages/kbn-palettes/palettes/gradient/status.ts @@ -14,6 +14,7 @@ import { KbnPalette } from '../../constants'; export const statusPalette = new KbnColorFnPalette({ id: KbnPalette.Status, + type: 'gradient', name: i18n.translate('palettes.status.name', { defaultMessage: 'Status', }), diff --git a/packages/kbn-palettes/palettes/gradient/temperature.ts b/packages/kbn-palettes/palettes/gradient/temperature.ts index 1d11a458a5fa7..5cf802db6c1f2 100644 --- a/packages/kbn-palettes/palettes/gradient/temperature.ts +++ b/packages/kbn-palettes/palettes/gradient/temperature.ts @@ -14,6 +14,7 @@ import { KbnPalette } from '../../constants'; export const temperaturePalette = new KbnColorFnPalette({ id: KbnPalette.Temperature, + type: 'gradient', name: i18n.translate('palettes.temperature.name', { defaultMessage: 'Temperature', }), diff --git a/packages/kbn-palettes/palettes/gradient/warm.ts b/packages/kbn-palettes/palettes/gradient/warm.ts index 211207a60d743..16ada3059903c 100644 --- a/packages/kbn-palettes/palettes/gradient/warm.ts +++ b/packages/kbn-palettes/palettes/gradient/warm.ts @@ -14,6 +14,7 @@ import { KbnPalette } from '../../constants'; export const warmPalette = new KbnColorFnPalette({ id: KbnPalette.Warm, + type: 'gradient', name: i18n.translate('palettes.warm.name', { defaultMessage: 'Warm', }), From 9ce21f90344e05cf0ef53df54fef000ccd70ea06 Mon Sep 17 00:00:00 2001 From: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Date: Sat, 23 Nov 2024 17:08:08 +0000 Subject: [PATCH 06/41] [CI] Auto-commit changed files from 'node scripts/generate codeowners' --- .github/CODEOWNERS | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 5b27bc63d3647..46d214a075174 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -426,6 +426,7 @@ packages/kbn-openapi-generator @elastic/security-detection-rule-management packages/kbn-optimizer @elastic/kibana-operations packages/kbn-optimizer-webpack-helpers @elastic/kibana-operations packages/kbn-osquery-io-ts-types @elastic/security-asset-management +packages/kbn-palettes @elastic/visualizations packages/kbn-panel-loader @elastic/kibana-presentation packages/kbn-peggy @elastic/kibana-operations packages/kbn-peggy-loader @elastic/kibana-operations From 81b5885bace4c0d474654188d1f5fb0e98c4cee3 Mon Sep 17 00:00:00 2001 From: nickofthyme Date: Sat, 23 Nov 2024 15:35:12 -0600 Subject: [PATCH 07/41] chore: update elastic palette with colors from eui --- .../palettes/categorical/elastic.ts | 46 +++++++++---------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/packages/kbn-palettes/palettes/categorical/elastic.ts b/packages/kbn-palettes/palettes/categorical/elastic.ts index 5daeb5c98b09b..a4b025749b0f6 100644 --- a/packages/kbn-palettes/palettes/categorical/elastic.ts +++ b/packages/kbn-palettes/palettes/categorical/elastic.ts @@ -45,34 +45,34 @@ export const elasticPalette = new KbnCategoricalPalette({ }), colors: [ '#00BEB8', - '#93E5E0', + '#98E6E2', '#599DFF', '#B4D5FF', '#ED6BA2', '#FFBED5', '#F66D64', '#FFC0B8', - '#ED9E00', - '#FFD569', - '#00CBC5', - '#C0F1EE', - '#78B0FF', - '#D2E7FF', - '#F588B3', - '#FFD9E7', - '#FC8A80', - '#FFDAD5', - '#F5AF00', - '#FCE8B0', - '#5DD8D2', - '#D9FDFB', - '#96C3FF', - '#E5F1FF', - '#FBA3C4', - '#FFEBF5', - '#FFA59C', - '#FFE9E5', - '#FEC514', - '#FFF1CC', + '#E6AB01', + '#FCD279', + '#40CFCA', + '#B2EDEA', + '#83B6FF', + '#C7E0FF', + '#F290BA', + '#FFCFE0', + '#F9928B', + '#FFD0CA', + '#EDC041', + '#FDDE9B', + '#80DFDC', + '#CCF3F1', + '#ACCEFF', + '#DAEAFF', + '#F6B5D1', + '#FFDFEA', + '#FBB6B2', + '#FFE0DC', + '#F3D580', + '#FEE9BC', ], }); From 285588c1b0766b7ce6ae086433bbd48dca212029 Mon Sep 17 00:00:00 2001 From: nickofthyme Date: Sat, 23 Nov 2024 16:49:44 -0600 Subject: [PATCH 08/41] chore: fix type and jest errors --- .../categorical_color_mapping.test.tsx | 10 +- .../color/color_handling.test.ts | 168 ++++++++---------- .../color_mapping/config/types.ts | 8 - packages/kbn-coloring/tsconfig.json | 1 + .../annotation_editor_controls.tsx | 10 +- .../palettes/legacy/gradient/complementary.ts | 1 + .../palettes/legacy/gradient/cool.ts | 1 + .../palettes/legacy/gradient/gray.ts | 1 + .../palettes/legacy/gradient/green.ts | 1 + .../palettes/legacy/gradient/red.ts | 1 + .../palettes/legacy/gradient/status.ts | 1 + .../palettes/legacy/gradient/temperature.ts | 1 + .../palettes/legacy/gradient/warm.ts | 1 + packages/kbn-palettes/tsconfig.json | 7 +- .../public/components/metric_vis.test.tsx | 37 ++-- .../public/utils/layers/get_layers.test.ts | 5 + src/plugins/charts/public/mocks.ts | 5 +- .../services/palettes/palettes.test.tsx | 3 +- .../color_telemetry_helpers.test.ts | 15 +- .../coloring/color_mapping_accessor.test.ts | 5 +- .../components/dimension_editor.test.tsx | 2 + .../xy_config_panel/dimension_editor.test.tsx | 7 + .../apps/lens/group4/color_mapping.ts | 27 +-- .../functional/apps/lens/group4/colors.ts | 10 +- 24 files changed, 175 insertions(+), 153 deletions(-) diff --git a/packages/kbn-coloring/src/shared_components/color_mapping/categorical_color_mapping.test.tsx b/packages/kbn-coloring/src/shared_components/color_mapping/categorical_color_mapping.test.tsx index dd7b12305fdad..530f16f912d0d 100644 --- a/packages/kbn-coloring/src/shared_components/color_mapping/categorical_color_mapping.test.tsx +++ b/packages/kbn-coloring/src/shared_components/color_mapping/categorical_color_mapping.test.tsx @@ -10,9 +10,9 @@ import React from 'react'; import { mount } from 'enzyme'; import { CategoricalColorMapping, ColorMappingInputData } from './categorical_color_mapping'; -import { AVAILABLE_PALETTES } from './palettes'; import { DEFAULT_COLOR_MAPPING_CONFIG } from './config/default_color_mapping'; import { MULTI_FIELD_KEY_SEPARATOR } from '@kbn/data-plugin/common'; +import { getKbnPalettes } from '@kbn/palettes'; const ASSIGNMENTS_LIST = '[data-test-subj="lns-colorMapping-assignmentsList"]'; const ASSIGNMENTS_PROMPT = '[data-test-subj="lns-colorMapping-assignmentsPrompt"]'; @@ -20,6 +20,8 @@ const ASSIGNMENTS_PROMPT_ADD_ALL = '[data-test-subj="lns-colorMapping-assignment const ASSIGNMENT_ITEM = (i: number) => `[data-test-subj="lns-colorMapping-assignmentsItem${i}"]`; describe('color mapping', () => { + const palettes = getKbnPalettes({ name: 'amsterdam', darkMode: false }); + it('load a default color mapping', () => { const dataInput: ColorMappingInputData = { type: 'categories', @@ -31,7 +33,7 @@ describe('color mapping', () => { data={dataInput} isDarkMode={false} model={{ ...DEFAULT_COLOR_MAPPING_CONFIG }} - palettes={AVAILABLE_PALETTES} + palettes={palettes} onModelUpdate={onModelUpdateFn} specialTokens={new Map()} /> @@ -53,7 +55,7 @@ describe('color mapping', () => { data={dataInput} isDarkMode={false} model={{ ...DEFAULT_COLOR_MAPPING_CONFIG }} - palettes={AVAILABLE_PALETTES} + palettes={palettes} onModelUpdate={onModelUpdateFn} specialTokens={new Map()} /> @@ -81,7 +83,7 @@ describe('color mapping', () => { data={dataInput} isDarkMode={false} model={{ ...DEFAULT_COLOR_MAPPING_CONFIG }} - palettes={AVAILABLE_PALETTES} + palettes={palettes} onModelUpdate={onModelUpdateFn} specialTokens={ new Map([ diff --git a/packages/kbn-coloring/src/shared_components/color_mapping/color/color_handling.test.ts b/packages/kbn-coloring/src/shared_components/color_mapping/color/color_handling.test.ts index 627f39e5026ac..ce01e412172fa 100644 --- a/packages/kbn-coloring/src/shared_components/color_mapping/color/color_handling.test.ts +++ b/packages/kbn-coloring/src/shared_components/color_mapping/color/color_handling.test.ts @@ -12,64 +12,52 @@ import { DEFAULT_NEUTRAL_PALETTE_INDEX, } from '../config/default_color_mapping'; import { getColorFactory } from './color_handling'; -import { getPalette, AVAILABLE_PALETTES } from '../palettes'; -import { - EUIAmsterdamColorBlindPalette, - EUI_AMSTERDAM_PALETTE_COLORS, -} from '../palettes/eui_amsterdam'; -import { NeutralPalette, NEUTRAL_COLOR_DARK, NEUTRAL_COLOR_LIGHT } from '../palettes/neutral'; import { toHex } from './color_math'; -import { ColorMapping } from '../config'; +import { KbnPalette, getKbnPalettes } from '@kbn/palettes'; describe('Color mapping - color generation', () => { - const getPaletteFn = getPalette(AVAILABLE_PALETTES, NeutralPalette); + const palettes = getKbnPalettes({ name: 'amsterdam', darkMode: false }); + const neutralPaletteColors = palettes + .get(KbnPalette.Neutral) + .colors() + .map((c) => c.toLowerCase()); + const elasticPaletteColors = palettes + .get(KbnPalette.Default) + .colors() + .map((c) => c.toLowerCase()); it('returns EUI light colors from default config', () => { - const colorFactory = getColorFactory(DEFAULT_COLOR_MAPPING_CONFIG, getPaletteFn, false, { + const colorFactory = getColorFactory(DEFAULT_COLOR_MAPPING_CONFIG, palettes, false, { type: 'categories', categories: ['catA', 'catB', 'catC'], }); - expect(colorFactory('catA')).toBe(EUI_AMSTERDAM_PALETTE_COLORS[0]); - expect(colorFactory('catB')).toBe(EUI_AMSTERDAM_PALETTE_COLORS[1]); - expect(colorFactory('catC')).toBe(EUI_AMSTERDAM_PALETTE_COLORS[2]); + expect(colorFactory('catA')).toBe(elasticPaletteColors[0]); + expect(colorFactory('catB')).toBe(elasticPaletteColors[1]); + expect(colorFactory('catC')).toBe(elasticPaletteColors[2]); // if the category is not available in the `categories` list then a default netural is used // this is an edge case and ideally never happen expect(colorFactory('not_available_1')).toBe( - NEUTRAL_COLOR_LIGHT[DEFAULT_NEUTRAL_PALETTE_INDEX] + neutralPaletteColors[DEFAULT_NEUTRAL_PALETTE_INDEX] ); }); // currently there is no difference in the two colors, but this could change in the future // this test will catch the change it('returns EUI dark colors from default config', () => { - const colorFactory = getColorFactory(DEFAULT_COLOR_MAPPING_CONFIG, getPaletteFn, true, { + const colorFactory = getColorFactory(DEFAULT_COLOR_MAPPING_CONFIG, palettes, true, { type: 'categories', categories: ['catA', 'catB', 'catC'], }); - expect(colorFactory('catA')).toBe(EUI_AMSTERDAM_PALETTE_COLORS[0]); - expect(colorFactory('catB')).toBe(EUI_AMSTERDAM_PALETTE_COLORS[1]); - expect(colorFactory('catC')).toBe(EUI_AMSTERDAM_PALETTE_COLORS[2]); + expect(colorFactory('catA')).toBe(elasticPaletteColors[0]); + expect(colorFactory('catB')).toBe(elasticPaletteColors[1]); + expect(colorFactory('catC')).toBe(elasticPaletteColors[2]); // if the category is not available in the `categories` list then a default netural is used // this is an edge case and ideally never happen - expect(colorFactory('not_available')).toBe(NEUTRAL_COLOR_DARK[DEFAULT_NEUTRAL_PALETTE_INDEX]); + expect(colorFactory('not_available')).toBe(neutralPaletteColors[DEFAULT_NEUTRAL_PALETTE_INDEX]); }); it('by default loops colors defined in palette', () => { - const twoColorPalette: ColorMapping.CategoricalPalette = { - id: 'twoColors', - name: 'twoColors', - colorCount: 2, - type: 'categorical', - getColor(indexInRange, isDarkMode, loop) { - return ['red', 'blue'][loop ? indexInRange % 2 : indexInRange]; - }, - }; - - const simplifiedGetPaletteGn = getPalette( - new Map([[twoColorPalette.id, twoColorPalette]]), - NeutralPalette - ); const colorFactory = getColorFactory( { ...DEFAULT_COLOR_MAPPING_CONFIG, @@ -84,37 +72,26 @@ describe('Color mapping - color generation', () => { touched: false, }, ], - paletteId: twoColorPalette.id, + paletteId: KbnPalette.Neutral, }, - simplifiedGetPaletteGn, + palettes, false, { type: 'categories', - categories: ['cat1', 'cat2', 'cat3', 'cat4'], + categories: ['cat1', 'cat2', 'cat3', 'cat4', 'cat5', 'cat6', 'cat7'], } ); - expect(colorFactory('cat1')).toBe('#ff0000'); - expect(colorFactory('cat2')).toBe('#0000ff'); + expect(colorFactory('cat1')).toBe(neutralPaletteColors[0]); + expect(colorFactory('cat2')).toBe(neutralPaletteColors[1]); + expect(colorFactory('cat3')).toBe(neutralPaletteColors[2]); + expect(colorFactory('cat4')).toBe(neutralPaletteColors[3]); + expect(colorFactory('cat5')).toBe(neutralPaletteColors[4]); // the palette will loop depending on the number of colors available - expect(colorFactory('cat3')).toBe('#ff0000'); - expect(colorFactory('cat4')).toBe('#0000ff'); + expect(colorFactory('cat6')).toBe(neutralPaletteColors[0]); + expect(colorFactory('cat7')).toBe(neutralPaletteColors[1]); }); it('returns the unassigned color if configured statically', () => { - const twoColorPalette: ColorMapping.CategoricalPalette = { - id: 'twoColors', - name: 'twoColors', - colorCount: 2, - type: 'categorical', - getColor(indexInRange, darkMode, loop) { - return ['red', 'blue'][loop ? indexInRange % 2 : indexInRange]; - }, - }; - - const simplifiedGetPaletteGn = getPalette( - new Map([[twoColorPalette.id, twoColorPalette]]), - NeutralPalette - ); const colorFactory = getColorFactory( { ...DEFAULT_COLOR_MAPPING_CONFIG, @@ -122,7 +99,7 @@ describe('Color mapping - color generation', () => { { color: { type: 'categorical', - paletteId: NeutralPalette.id, + paletteId: KbnPalette.Neutral, colorIndex: DEFAULT_NEUTRAL_PALETTE_INDEX, }, rule: { @@ -131,33 +108,32 @@ describe('Color mapping - color generation', () => { touched: false, }, ], - paletteId: twoColorPalette.id, }, - simplifiedGetPaletteGn, + palettes, false, { type: 'categories', categories: ['cat1', 'cat2', 'cat3', 'cat4'], } ); - expect(colorFactory('cat1')).toBe(NEUTRAL_COLOR_LIGHT[DEFAULT_NEUTRAL_PALETTE_INDEX]); - expect(colorFactory('cat2')).toBe(NEUTRAL_COLOR_LIGHT[DEFAULT_NEUTRAL_PALETTE_INDEX]); - expect(colorFactory('cat3')).toBe(NEUTRAL_COLOR_LIGHT[DEFAULT_NEUTRAL_PALETTE_INDEX]); - expect(colorFactory('cat4')).toBe(NEUTRAL_COLOR_LIGHT[DEFAULT_NEUTRAL_PALETTE_INDEX]); + expect(colorFactory('cat1')).toBe(neutralPaletteColors[DEFAULT_NEUTRAL_PALETTE_INDEX]); + expect(colorFactory('cat2')).toBe(neutralPaletteColors[DEFAULT_NEUTRAL_PALETTE_INDEX]); + expect(colorFactory('cat3')).toBe(neutralPaletteColors[DEFAULT_NEUTRAL_PALETTE_INDEX]); + expect(colorFactory('cat4')).toBe(neutralPaletteColors[DEFAULT_NEUTRAL_PALETTE_INDEX]); // if the category is not available in the `categories` list then a default netural is used // this is an edge case and ideally never happen - expect(colorFactory('not_available')).toBe(NEUTRAL_COLOR_LIGHT[DEFAULT_NEUTRAL_PALETTE_INDEX]); + expect(colorFactory('not_available')).toBe(neutralPaletteColors[DEFAULT_NEUTRAL_PALETTE_INDEX]); }); it('handles special tokens, multi-field categories and non-trimmed whitespaces', () => { - const colorFactory = getColorFactory(DEFAULT_COLOR_MAPPING_CONFIG, getPaletteFn, false, { + const colorFactory = getColorFactory(DEFAULT_COLOR_MAPPING_CONFIG, palettes, false, { type: 'categories', categories: ['__other__', ['fieldA', 'fieldB'], '__empty__', ' with-whitespaces '], }); - expect(colorFactory('__other__')).toBe(EUI_AMSTERDAM_PALETTE_COLORS[0]); - // expect(colorFactory(['fieldA', 'fieldB'])).toBe(EUI_AMSTERDAM_PALETTE_COLORS[1]); - expect(colorFactory('__empty__')).toBe(EUI_AMSTERDAM_PALETTE_COLORS[2]); - expect(colorFactory(' with-whitespaces ')).toBe(EUI_AMSTERDAM_PALETTE_COLORS[3]); + expect(colorFactory('__other__')).toBe(elasticPaletteColors[0]); + // expect(colorFactory(['fieldA', 'fieldB'])).toBe(elasticPaletteColors[1]); + expect(colorFactory('__empty__')).toBe(elasticPaletteColors[2]); + expect(colorFactory(' with-whitespaces ')).toBe(elasticPaletteColors[3]); }); it('ignores configured assignments in loop mode', () => { @@ -172,17 +148,17 @@ describe('Color mapping - color generation', () => { }, ], }, - getPaletteFn, + palettes, false, { type: 'categories', categories: ['catA', 'catB', 'configuredAssignment', 'nextCat'], } ); - expect(colorFactory('catA')).toBe(EUI_AMSTERDAM_PALETTE_COLORS[0]); - expect(colorFactory('catB')).toBe(EUI_AMSTERDAM_PALETTE_COLORS[1]); + expect(colorFactory('catA')).toBe(elasticPaletteColors[0]); + expect(colorFactory('catB')).toBe(elasticPaletteColors[1]); expect(colorFactory('configuredAssignment')).toBe('red'); - expect(colorFactory('nextCat')).toBe(EUI_AMSTERDAM_PALETTE_COLORS[2]); + expect(colorFactory('nextCat')).toBe(elasticPaletteColors[2]); }); it('color with auto rule are assigned in order of the configured data input', () => { @@ -207,7 +183,7 @@ describe('Color mapping - color generation', () => { }, ], }, - getPaletteFn, + palettes, false, { type: 'categories', @@ -222,7 +198,7 @@ describe('Color mapping - color generation', () => { expect(colorFactory('greenCat')).toBe('green'); // if the category is not available in the `categories` list then a default netural is used // this is an edge case and ideally never happen - expect(colorFactory('not_available')).toBe(NEUTRAL_COLOR_LIGHT[DEFAULT_NEUTRAL_PALETTE_INDEX]); + expect(colorFactory('not_available')).toBe(neutralPaletteColors[DEFAULT_NEUTRAL_PALETTE_INDEX]); }); it('returns sequential gradient colors from darker to lighter [desc, lightMode]', () => { @@ -234,7 +210,7 @@ describe('Color mapping - color generation', () => { steps: [ { type: 'categorical', - paletteId: EUIAmsterdamColorBlindPalette.id, + paletteId: KbnPalette.Default, colorIndex: 0, touched: false, }, @@ -242,7 +218,7 @@ describe('Color mapping - color generation', () => { sort: 'desc', }, }, - getPaletteFn, + palettes, false, { type: 'categories', @@ -250,7 +226,7 @@ describe('Color mapping - color generation', () => { } ); // this matches exactly with the initial step selected - expect(toHex(colorFactory('cat1'))).toBe(toHex(EUI_AMSTERDAM_PALETTE_COLORS[0])); + expect(toHex(colorFactory('cat1'))).toBe(toHex(elasticPaletteColors[0])); expect(toHex(colorFactory('cat2'))).toBe('#93cebc'); expect(toHex(colorFactory('cat3'))).toBe('#cce8e0'); }); @@ -264,7 +240,7 @@ describe('Color mapping - color generation', () => { steps: [ { type: 'categorical', - paletteId: EUIAmsterdamColorBlindPalette.id, + paletteId: KbnPalette.Default, colorIndex: 0, touched: false, }, @@ -272,7 +248,7 @@ describe('Color mapping - color generation', () => { sort: 'asc', }, }, - getPaletteFn, + palettes, false, { type: 'categories', @@ -284,7 +260,7 @@ describe('Color mapping - color generation', () => { // mid green point expect(toHex(colorFactory('cat2'))).toBe('#93cebc'); // initial gradient color - expect(toHex(colorFactory('cat3'))).toBe(EUI_AMSTERDAM_PALETTE_COLORS[0]); + expect(toHex(colorFactory('cat3'))).toBe(elasticPaletteColors[0]); }); it('sequential gradients and static color from lighter to darker [asc, lightMode]', () => { const colorFactory = getColorFactory( @@ -300,7 +276,7 @@ describe('Color mapping - color generation', () => { steps: [ { type: 'categorical', - paletteId: EUIAmsterdamColorBlindPalette.id, + paletteId: KbnPalette.Default, colorIndex: 0, touched: false, }, @@ -312,7 +288,7 @@ describe('Color mapping - color generation', () => { color: { type: 'categorical', colorIndex: DEFAULT_NEUTRAL_PALETTE_INDEX, - paletteId: NeutralPalette.id, + paletteId: KbnPalette.Neutral, }, rule: { type: 'other', @@ -321,7 +297,7 @@ describe('Color mapping - color generation', () => { }, ], }, - getPaletteFn, + palettes, false, { type: 'categories', @@ -329,9 +305,9 @@ describe('Color mapping - color generation', () => { } ); expect(toHex(colorFactory('cat1'))).toBe('#cce8e0'); - expect(toHex(colorFactory('cat2'))).toBe(EUI_AMSTERDAM_PALETTE_COLORS[0]); + expect(toHex(colorFactory('cat2'))).toBe(elasticPaletteColors[0]); // this matches exactly with the initial step selected - expect(toHex(colorFactory('cat3'))).toBe(NEUTRAL_COLOR_LIGHT[DEFAULT_NEUTRAL_PALETTE_INDEX]); + expect(toHex(colorFactory('cat3'))).toBe(neutralPaletteColors[DEFAULT_NEUTRAL_PALETTE_INDEX]); }); it('returns 2 colors gradient [desc, lightMode]', () => { @@ -343,13 +319,13 @@ describe('Color mapping - color generation', () => { steps: [ { type: 'categorical', - paletteId: EUIAmsterdamColorBlindPalette.id, + paletteId: KbnPalette.Default, colorIndex: 0, touched: false, }, { type: 'categorical', - paletteId: EUIAmsterdamColorBlindPalette.id, + paletteId: KbnPalette.Default, colorIndex: 2, touched: false, }, @@ -357,16 +333,16 @@ describe('Color mapping - color generation', () => { sort: 'desc', }, }, - getPaletteFn, + palettes, false, { type: 'categories', categories: ['cat1', 'cat2', 'cat3'], } ); - expect(toHex(colorFactory('cat1'))).toBe(toHex(EUI_AMSTERDAM_PALETTE_COLORS[0])); // EUI green + expect(toHex(colorFactory('cat1'))).toBe(toHex(elasticPaletteColors[0])); // EUI green expect(toHex(colorFactory('cat2'))).toBe('#a4908f'); // red gray green - expect(toHex(colorFactory('cat3'))).toBe(toHex(EUI_AMSTERDAM_PALETTE_COLORS[2])); // EUI pink + expect(toHex(colorFactory('cat3'))).toBe(toHex(elasticPaletteColors[2])); // EUI pink }); it('returns divergent gradient [asc, darkMode]', () => { @@ -378,14 +354,14 @@ describe('Color mapping - color generation', () => { steps: [ { type: 'categorical', - paletteId: EUIAmsterdamColorBlindPalette.id, + paletteId: KbnPalette.Default, colorIndex: 0, touched: false, }, - { type: 'categorical', paletteId: NeutralPalette.id, colorIndex: 0, touched: false }, + { type: 'categorical', paletteId: KbnPalette.Neutral, colorIndex: 0, touched: false }, { type: 'categorical', - paletteId: EUIAmsterdamColorBlindPalette.id, + paletteId: KbnPalette.Default, colorIndex: 2, touched: false, }, @@ -393,18 +369,18 @@ describe('Color mapping - color generation', () => { sort: 'asc', // testing in ascending order }, }, - getPaletteFn, + palettes, true, // testing in dark mode { type: 'categories', categories: ['cat1', 'cat2', 'cat3'], } ); - expect(toHex(colorFactory('cat1'))).toBe(toHex(EUI_AMSTERDAM_PALETTE_COLORS[2])); // EUI pink - expect(toHex(colorFactory('cat2'))).toBe(NEUTRAL_COLOR_DARK[0]); // NEUTRAL LIGHT GRAY - expect(toHex(colorFactory('cat3'))).toBe(toHex(EUI_AMSTERDAM_PALETTE_COLORS[0])); // EUI green + expect(toHex(colorFactory('cat1'))).toBe(toHex(elasticPaletteColors[2])); // EUI pink + expect(toHex(colorFactory('cat2'))).toBe(neutralPaletteColors[0]); // NEUTRAL LIGHT GRAY + expect(toHex(colorFactory('cat3'))).toBe(toHex(elasticPaletteColors[0])); // EUI green // if the category is not available in the `categories` list then a default netural is used // this is an edge case and ideally never happen - expect(colorFactory('not_available')).toBe(NEUTRAL_COLOR_DARK[DEFAULT_NEUTRAL_PALETTE_INDEX]); + expect(colorFactory('not_available')).toBe(neutralPaletteColors[DEFAULT_NEUTRAL_PALETTE_INDEX]); }); }); diff --git a/packages/kbn-coloring/src/shared_components/color_mapping/config/types.ts b/packages/kbn-coloring/src/shared_components/color_mapping/config/types.ts index 1c8b984dc52dd..79be2aa615c3c 100644 --- a/packages/kbn-coloring/src/shared_components/color_mapping/config/types.ts +++ b/packages/kbn-coloring/src/shared_components/color_mapping/config/types.ts @@ -150,11 +150,3 @@ export interface Config { >; specialAssignments: Array>; } - -export interface CategoricalPalette { - id: string; - name: string; - type: 'categorical'; - colorCount: number; - getColor: (valueInRange: number, isDarkMode: boolean, loop: boolean) => string; -} diff --git a/packages/kbn-coloring/tsconfig.json b/packages/kbn-coloring/tsconfig.json index 3a97faa1b9d3a..c3be4a82e8baa 100644 --- a/packages/kbn-coloring/tsconfig.json +++ b/packages/kbn-coloring/tsconfig.json @@ -23,6 +23,7 @@ "@kbn/data-plugin", "@kbn/ui-theme", "@kbn/visualization-utils", + "@kbn/palettes", ], "exclude": [ "target/**/*", diff --git a/packages/kbn-event-annotation-components/components/annotation_editor_controls/annotation_editor_controls.tsx b/packages/kbn-event-annotation-components/components/annotation_editor_controls/annotation_editor_controls.tsx index de230ac617987..9053494071c03 100644 --- a/packages/kbn-event-annotation-components/components/annotation_editor_controls/annotation_editor_controls.tsx +++ b/packages/kbn-event-annotation-components/components/annotation_editor_controls/annotation_editor_controls.tsx @@ -11,7 +11,14 @@ import './index.scss'; import { isFieldLensCompatible } from '@kbn/visualization-ui-components'; import React, { useCallback, useEffect, useMemo } from 'react'; import { i18n } from '@kbn/i18n'; -import { EuiFormRow, EuiSwitch, EuiSwitchEvent, EuiButtonGroup, EuiSpacer } from '@elastic/eui'; +import { + EuiFormRow, + EuiSwitch, + EuiSwitchEvent, + EuiButtonGroup, + EuiSpacer, + euiPaletteColorBlind, +} from '@elastic/eui'; import { IconSelectSetting, DimensionEditorSection, @@ -339,6 +346,7 @@ const AnnotationEditorControls = ({ label={i18n.translate('eventAnnotationComponents.xyChart.lineColor.label', { defaultMessage: 'Color', })} + swatches={euiPaletteColorBlind()} /> { const convertFn = (v: unknown) => `${id}-${v}`; @@ -1160,12 +1161,16 @@ describe('MetricVisComponent', function () { // should be overridden color: 'static-color', palette: { - colors: [], - gradient: true, - stops: [], - range: 'number', - rangeMin: 2, - rangeMax: 10, + type: 'palette', + name: 'default', + params: { + colors: [], + gradient: true, + stops: [], + range: 'number', + rangeMin: 2, + rangeMax: 10, + }, }, }, }} @@ -1200,7 +1205,7 @@ describe('MetricVisComponent', function () { describe('percent-based', () => { const renderWithPalette = ( - palette: CustomPaletteState, + palette: PaletteOutput, dimensions: MetricVisComponentProps['config']['dimensions'] ) => shallow( @@ -1238,13 +1243,17 @@ describe('MetricVisComponent', function () { renderWithPalette( { - range: 'percent', - // the rest of these params don't matter - colors: [], - gradient: false, - stops: [], - rangeMin: 2, - rangeMax: 10, + type: 'palette', + name: 'default', + params: { + range: 'percent', + // the rest of these params don't matter + colors: [], + gradient: false, + stops: [], + rangeMin: 2, + rangeMax: 10, + }, }, dimensions as DimensionsVisParam ); diff --git a/src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_layers.test.ts b/src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_layers.test.ts index d6c6e7d315924..eb211ad481899 100644 --- a/src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_layers.test.ts +++ b/src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_layers.test.ts @@ -13,8 +13,11 @@ import { BucketColumns, ChartTypes } from '../../../common/types'; import { createMockPieParams, createMockVisData } from '../../mocks'; import { getPaletteRegistry } from '../../__mocks__/palettes'; import { getLayers } from './get_layers'; +import { getKbnPalettes } from '@kbn/palettes'; describe('getLayers', () => { + const palettes = getKbnPalettes({ name: 'amsterdam', darkMode: false }); + it('preserves slice order for multi-metric layer', () => { const visData = createMockVisData(); const columns: BucketColumns[] = [ @@ -43,6 +46,7 @@ describe('getLayers', () => { {}, [], getPaletteRegistry(), + palettes, {}, fieldFormatsMock, false, @@ -153,6 +157,7 @@ describe('getLayers', () => { {}, [], getPaletteRegistry(), + palettes, {}, fieldFormatsMock, false, diff --git a/src/plugins/charts/public/mocks.ts b/src/plugins/charts/public/mocks.ts index aa7518d1df9f1..db6bd2bab4212 100644 --- a/src/plugins/charts/public/mocks.ts +++ b/src/plugins/charts/public/mocks.ts @@ -7,6 +7,7 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ +import { createCoreSetupMock } from '@kbn/core-lifecycle-browser-mocks/src/core_setup.mock'; import { ChartsPlugin } from './plugin'; import { themeServiceMock } from './services/theme/mock'; import { activeCursorMock } from './services/active_cursor/mock'; @@ -19,13 +20,13 @@ export type Start = jest.Mocked>; const createSetupContract = (): Setup => ({ theme: themeServiceMock, - palettes: paletteServiceMock.setup(), + palettes: paletteServiceMock.setup(createCoreSetupMock().theme.getTheme()), }); const createStartContract = (): Start => ({ theme: themeServiceMock, activeCursor: activeCursorMock, - palettes: paletteServiceMock.setup(), + palettes: paletteServiceMock.setup(createCoreSetupMock().theme.getTheme()), }); export const chartPluginMock = { diff --git a/src/plugins/charts/public/services/palettes/palettes.test.tsx b/src/plugins/charts/public/services/palettes/palettes.test.tsx index a9567b0c12179..d091b5429755b 100644 --- a/src/plugins/charts/public/services/palettes/palettes.test.tsx +++ b/src/plugins/charts/public/services/palettes/palettes.test.tsx @@ -7,11 +7,12 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ +import { createCoreSetupMock } from '@kbn/core-lifecycle-browser-mocks/src/core_setup.mock'; import { buildPalettes } from './palettes'; import { euiPaletteColorBlind, euiPaletteColorBlindBehindText } from '@elastic/eui'; describe('palettes', () => { - const palettes = buildPalettes(); + const palettes = buildPalettes(createCoreSetupMock().theme.getTheme()); describe('default palette', () => { describe('syncColors: false', () => { diff --git a/x-pack/plugins/lens/public/lens_ui_telemetry/color_telemetry_helpers.test.ts b/x-pack/plugins/lens/public/lens_ui_telemetry/color_telemetry_helpers.test.ts index 47eba8b0252ef..24875907bbd45 100644 --- a/x-pack/plugins/lens/public/lens_ui_telemetry/color_telemetry_helpers.test.ts +++ b/x-pack/plugins/lens/public/lens_ui_telemetry/color_telemetry_helpers.test.ts @@ -8,12 +8,11 @@ import { getColorMappingTelemetryEvents } from './color_telemetry_helpers'; import { ColorMapping, - EUIAmsterdamColorBlindPalette, - ElasticBrandPalette, DEFAULT_COLOR_MAPPING_CONFIG, DEFAULT_OTHER_ASSIGNMENT_INDEX, } from '@kbn/coloring'; import faker from 'faker'; +import { KbnPalette } from '@kbn/palettes'; const exampleAssignment = ( valuesCount = 1, @@ -24,7 +23,7 @@ const exampleAssignment = ( type === 'categorical' ? { type: 'categorical', - paletteId: ElasticBrandPalette.id, + paletteId: KbnPalette.ElasticClassic, colorIndex: 0, } : { @@ -57,13 +56,13 @@ const MANUAL_COLOR_MAPPING_CONFIG: ColorMapping.Config = { }, color: { type: 'categorical', - paletteId: ElasticBrandPalette.id, + paletteId: KbnPalette.ElasticClassic, colorIndex: 2, }, touched: true, }, ], - paletteId: ElasticBrandPalette.id, + paletteId: KbnPalette.ElasticClassic, colorMode: { type: 'categorical', }, @@ -74,7 +73,7 @@ const specialAssignmentsPalette: ColorMapping.Config['specialAssignments'] = [ ...DEFAULT_COLOR_MAPPING_CONFIG.specialAssignments[DEFAULT_OTHER_ASSIGNMENT_INDEX], color: { type: 'categorical', - paletteId: EUIAmsterdamColorBlindPalette.id, + paletteId: KbnPalette.Kibana7, colorIndex: 0, }, }, @@ -112,7 +111,7 @@ describe('color_telemetry_helpers', () => { }); it('settings (default): unassigned terms loop, default palette returns correct events', () => { expect(getColorMappingTelemetryEvents(DEFAULT_COLOR_MAPPING_CONFIG)).toEqual([ - 'color_mapping_palette_eui_amsterdam_color_blind', + 'color_mapping_palette_default', 'color_mapping_unassigned_terms_loop', ]); }); @@ -126,7 +125,7 @@ describe('color_telemetry_helpers', () => { steps: [ { type: 'categorical', - paletteId: EUIAmsterdamColorBlindPalette.id, + paletteId: KbnPalette.Kibana7, colorIndex: 0, touched: false, }, diff --git a/x-pack/plugins/lens/public/shared_components/coloring/color_mapping_accessor.test.ts b/x-pack/plugins/lens/public/shared_components/coloring/color_mapping_accessor.test.ts index 139c6ced456bc..6ddbaff8d7b60 100644 --- a/x-pack/plugins/lens/public/shared_components/coloring/color_mapping_accessor.test.ts +++ b/x-pack/plugins/lens/public/shared_components/coloring/color_mapping_accessor.test.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { getKbnPalettes } from '@kbn/palettes'; import { getColorAccessorFn } from './color_mapping_accessor'; jest.mock('@kbn/coloring', () => ({ @@ -15,8 +16,10 @@ jest.mock('@kbn/coloring', () => ({ })); describe('getColorAccessorFn', () => { + const palettes = getKbnPalettes({ name: 'amsterdam', darkMode: false }); + // eslint-disable-next-line @typescript-eslint/no-explicit-any - const getColorAccessor = getColorAccessorFn('{}', {} as any, false); + const getColorAccessor = getColorAccessorFn(palettes, '{}', {} as any, false); it('should return null for null values', () => { expect(getColorAccessor(null)).toBe(null); diff --git a/x-pack/plugins/lens/public/visualizations/datatable/components/dimension_editor.test.tsx b/x-pack/plugins/lens/public/visualizations/datatable/components/dimension_editor.test.tsx index 738f7edab2a6e..ee8566df52ff0 100644 --- a/x-pack/plugins/lens/public/visualizations/datatable/components/dimension_editor.test.tsx +++ b/x-pack/plugins/lens/public/visualizations/datatable/components/dimension_editor.test.tsx @@ -20,6 +20,7 @@ import { ColumnState } from '../../../../common/expressions'; import { capitalize } from 'lodash'; import { I18nProvider } from '@kbn/i18n-react'; import { DatatableColumnType } from '@kbn/expressions-plugin/common'; +import { getKbnPalettes } from '@kbn/palettes'; describe('data table dimension editor', () => { let user: UserEvent; @@ -89,6 +90,7 @@ describe('data table dimension editor', () => { setState: jest.fn(), isDarkMode: false, paletteService: chartPluginMock.createPaletteRegistry(), + palettes: getKbnPalettes({ name: 'amsterdam', darkMode: false }), panelRef: React.createRef(), addLayer: jest.fn(), removeLayer: jest.fn(), diff --git a/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/dimension_editor.test.tsx b/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/dimension_editor.test.tsx index 08a83ef7e0176..42224fa5f0506 100644 --- a/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/dimension_editor.test.tsx +++ b/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/dimension_editor.test.tsx @@ -18,6 +18,7 @@ import { chartPluginMock } from '@kbn/charts-plugin/public/mocks'; import { EuiColorPicker } from '@elastic/eui'; import { LayerTypes } from '@kbn/expression-xy-plugin/public'; import { act } from 'react-dom/test-utils'; +import { getKbnPalettes } from '@kbn/palettes'; describe('XY Config panels', () => { let frame: FramePublicAPI; @@ -63,6 +64,7 @@ describe('XY Config panels', () => { }} formatFactory={jest.fn()} paletteService={chartPluginMock.createPaletteRegistry()} + palettes={getKbnPalettes({ name: 'amsterdam', darkMode: false })} panelRef={React.createRef()} addLayer={jest.fn()} removeLayer={jest.fn()} @@ -91,6 +93,7 @@ describe('XY Config panels', () => { state={state} formatFactory={jest.fn()} paletteService={chartPluginMock.createPaletteRegistry()} + palettes={getKbnPalettes({ name: 'amsterdam', darkMode: false })} panelRef={React.createRef()} addLayer={jest.fn()} removeLayer={jest.fn()} @@ -140,6 +143,7 @@ describe('XY Config panels', () => { state={state} formatFactory={jest.fn()} paletteService={chartPluginMock.createPaletteRegistry()} + palettes={getKbnPalettes({ name: 'amsterdam', darkMode: false })} panelRef={React.createRef()} addLayer={jest.fn()} removeLayer={jest.fn()} @@ -186,6 +190,7 @@ describe('XY Config panels', () => { state={state} formatFactory={jest.fn()} paletteService={chartPluginMock.createPaletteRegistry()} + palettes={getKbnPalettes({ name: 'amsterdam', darkMode: false })} panelRef={React.createRef()} addLayer={jest.fn()} removeLayer={jest.fn()} @@ -239,6 +244,7 @@ describe('XY Config panels', () => { state={state} formatFactory={jest.fn()} paletteService={chartPluginMock.createPaletteRegistry()} + palettes={getKbnPalettes({ name: 'amsterdam', darkMode: false })} panelRef={React.createRef()} addLayer={jest.fn()} removeLayer={jest.fn()} @@ -292,6 +298,7 @@ describe('XY Config panels', () => { state={state} formatFactory={jest.fn()} paletteService={chartPluginMock.createPaletteRegistry()} + palettes={getKbnPalettes({ name: 'amsterdam', darkMode: false })} panelRef={React.createRef()} addLayer={jest.fn()} removeLayer={jest.fn()} diff --git a/x-pack/test/functional/apps/lens/group4/color_mapping.ts b/x-pack/test/functional/apps/lens/group4/color_mapping.ts index 008ffa1cb53e1..d14505fb0b147 100644 --- a/x-pack/test/functional/apps/lens/group4/color_mapping.ts +++ b/x-pack/test/functional/apps/lens/group4/color_mapping.ts @@ -6,17 +6,15 @@ */ import expect from '@kbn/expect'; -import { - EUI_AMSTERDAM_PALETTE_COLORS, - ELASTIC_BRAND_PALETTE_COLORS, - EUIAmsterdamColorBlindPalette, - ElasticBrandPalette, -} from '@kbn/coloring/src/shared_components/color_mapping/palettes'; +import { getKbnPalettes, KbnPalette } from '@kbn/palettes'; import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const { visualize, lens } = getPageObjects(['visualize', 'lens']); const elasticChart = getService('elasticChart'); + const palettes = getKbnPalettes({ name: 'amsterdam', darkMode: false }); + const defaultPalette = palettes.get(KbnPalette.Default); + const classicPalette = palettes.get(KbnPalette.ElasticClassic); describe('lens color mapping', () => { before(async () => { @@ -34,7 +32,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { dimension: 'lnsXY_splitDimensionPanel > lns-empty-dimension', operation: 'terms', field: 'extension.raw', - palette: { mode: 'colorMapping', id: ElasticBrandPalette.id }, + palette: { mode: 'colorMapping', id: classicPalette.id }, keepOpen: true, }); }); @@ -43,18 +41,25 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const chart = await lens.getCurrentChartDebugState('xyVisChart'); const legendColors = chart?.legend?.items?.map((item) => item.color.toLowerCase()) ?? []; expect(legendColors).to.eql( - ELASTIC_BRAND_PALETTE_COLORS.slice(0, 5).map((c) => c.toLowerCase()) + classicPalette + .colors() + .slice(0, 5) + .map((c) => c.toLowerCase()) ); }); + it('should allow switching color mapping palette', async () => { await lens.changeColorMappingPalette( 'lnsXY_splitDimensionPanel > lnsLayerPanel-dimensionLink', - EUIAmsterdamColorBlindPalette.id + defaultPalette.id ); const chart = await lens.getCurrentChartDebugState('xyVisChart'); const legendColors = chart?.legend?.items?.map((item) => item.color.toLowerCase()) ?? []; expect(legendColors).to.eql( - EUI_AMSTERDAM_PALETTE_COLORS.slice(0, 5).map((c) => c.toLowerCase()) + defaultPalette + .colors() + .slice(0, 5) + .map((c) => c.toLowerCase()) ); }); @@ -66,7 +71,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { ); const chart = await lens.getCurrentChartDebugState('xyVisChart'); const firstLegendItemColor = chart?.legend?.items?.[0]?.color?.toLowerCase() ?? 'NONE'; - expect(firstLegendItemColor).to.eql(EUI_AMSTERDAM_PALETTE_COLORS[3].toLowerCase()); + expect(firstLegendItemColor).to.eql(defaultPalette.colors()[3].toLowerCase()); }); }); } diff --git a/x-pack/test/functional/apps/lens/group4/colors.ts b/x-pack/test/functional/apps/lens/group4/colors.ts index 5c5bbea4ba2c5..68e0ce9f88560 100644 --- a/x-pack/test/functional/apps/lens/group4/colors.ts +++ b/x-pack/test/functional/apps/lens/group4/colors.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { ElasticBrandPalette } from '@kbn/coloring'; +import { KbnPalette } from '@kbn/palettes'; import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getPageObjects }: FtrProviderContext) { @@ -57,25 +57,25 @@ export default function ({ getPageObjects }: FtrProviderContext) { dimension: 'lnsXY_splitDimensionPanel > lns-empty-dimension', operation: 'terms', field: '@message.raw', - palette: { mode: 'colorMapping', id: ElasticBrandPalette.id }, + palette: { mode: 'colorMapping', id: KbnPalette.ElasticClassic }, keepOpen: true, }); - await lens.assertPalette(ElasticBrandPalette.id, false); + await lens.assertPalette(KbnPalette.ElasticClassic, false); await lens.closeDimensionEditor(); }); it('should carry over palette to the pie chart', async () => { await lens.switchToVisualization('pie'); await lens.openDimensionEditor('lnsPie_sliceByDimensionPanel > lns-dimensionTrigger'); - await lens.assertPalette(ElasticBrandPalette.id, false); + await lens.assertPalette(KbnPalette.ElasticClassic, false); await lens.closeDimensionEditor(); }); it('should carry palette back to the bar chart', async () => { await lens.switchToVisualization('bar'); await lens.openDimensionEditor('lnsXY_splitDimensionPanel > lns-dimensionTrigger'); - await lens.assertPalette(ElasticBrandPalette.id, false); + await lens.assertPalette(KbnPalette.ElasticClassic, false); }); }); } From 3eca8c4640b51d7680910f0bd6dc28d8a653f375 Mon Sep 17 00:00:00 2001 From: nickofthyme Date: Sat, 23 Nov 2024 16:50:41 -0600 Subject: [PATCH 09/41] chore: update page load limits --- packages/kbn-optimizer/limits.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/kbn-optimizer/limits.yml b/packages/kbn-optimizer/limits.yml index e1e9b6aa81898..76a3b9c02e9cf 100644 --- a/packages/kbn-optimizer/limits.yml +++ b/packages/kbn-optimizer/limits.yml @@ -17,7 +17,7 @@ pageLoadAssetSize: cloudFullStory: 18493 cloudLinks: 55984 cloudSecurityPosture: 19109 - console: 46091 + console: 61528 contentManagement: 16254 controls: 60000 core: 564663 @@ -63,7 +63,7 @@ pageLoadAssetSize: expressionTagcloud: 27505 expressionXY: 45000 features: 21723 - fieldFormats: 65209 + fieldFormats: 81291 fieldsMetadata: 21885 files: 22673 filesManagement: 18683 @@ -189,7 +189,7 @@ pageLoadAssetSize: visTypeTagcloud: 37575 visTypeTimelion: 68883 visTypeTimeseries: 55203 - visTypeVega: 153573 + visTypeVega: 571074 visTypeVislib: 242838 visTypeXy: 46868 visualizations: 90000 From 60d3ea96c6be92474a6ff055cbc7cd46313faaee Mon Sep 17 00:00:00 2001 From: nickofthyme Date: Sat, 23 Nov 2024 16:54:07 -0600 Subject: [PATCH 10/41] chore: fix i18n errors --- x-pack/plugins/translations/translations/fr-FR.json | 9 --------- x-pack/plugins/translations/translations/ja-JP.json | 9 --------- x-pack/plugins/translations/translations/zh-CN.json | 9 --------- 3 files changed, 27 deletions(-) diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index 2da357aa68461..0988b2d7cb4e1 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -428,17 +428,8 @@ "charts.legend.toggleLegendButtonAriaLabel": "Afficher/Masquer la légende", "charts.legend.toggleLegendButtonTitle": "Afficher/Masquer la légende", "charts.noDataLabel": "Résultat introuvable", - "charts.palettes.complementaryLabel": "Complémentaire", - "charts.palettes.coolLabel": "Froide", "charts.palettes.customLabel": "Personnalisée", - "charts.palettes.defaultPaletteLabel": "Par défaut", - "charts.palettes.grayLabel": "Gris", "charts.palettes.kibanaPaletteLabel": "Compatibilité", - "charts.palettes.negativeLabel": "Négative", - "charts.palettes.positiveLabel": "Positive", - "charts.palettes.statusLabel": "Statut", - "charts.palettes.temperatureLabel": "Température", - "charts.palettes.warmLabel": "Chaude", "charts.partialData.bucketTooltipText": "La plage temporelle sélectionnée n'inclut pas ce compartiment en entier. Il se peut qu'elle contienne des données partielles.", "charts.warning.warningLabel": "{numberWarnings, number} {numberWarnings, plural, one {avertissement} other {avertissements}}", "cloud.connectionDetails.apiKeyFormat.beats.description": "Utilisé pour la configuration de Beats", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index b564cac6e8c13..2748f9df00635 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -428,17 +428,8 @@ "charts.legend.toggleLegendButtonAriaLabel": "凡例を切り替える", "charts.legend.toggleLegendButtonTitle": "凡例を切り替える", "charts.noDataLabel": "結果が見つかりませんでした", - "charts.palettes.complementaryLabel": "補完", - "charts.palettes.coolLabel": "Cool", "charts.palettes.customLabel": "カスタム", - "charts.palettes.defaultPaletteLabel": "デフォルト", - "charts.palettes.grayLabel": "グレー", "charts.palettes.kibanaPaletteLabel": "互換性", - "charts.palettes.negativeLabel": "負", - "charts.palettes.positiveLabel": "正", - "charts.palettes.statusLabel": "ステータス", - "charts.palettes.temperatureLabel": "温度", - "charts.palettes.warmLabel": "ウォーム", "charts.partialData.bucketTooltipText": "選択された時間範囲にはこのバケット全体は含まれていません。一部データが含まれている可能性があります。", "charts.warning.warningLabel": "{numberWarnings, number} {numberWarnings, plural, other {件の警告}}", "cloud.connectionDetails.apiKeyFormat.beats.description": "Beatsを構成するために使用", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 06b1b01869f63..21c3bebf73f59 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -424,17 +424,8 @@ "charts.legend.toggleLegendButtonAriaLabel": "切换图例", "charts.legend.toggleLegendButtonTitle": "切换图例", "charts.noDataLabel": "找不到结果", - "charts.palettes.complementaryLabel": "互补性", - "charts.palettes.coolLabel": "冷", "charts.palettes.customLabel": "定制", - "charts.palettes.defaultPaletteLabel": "默认", - "charts.palettes.grayLabel": "灰", "charts.palettes.kibanaPaletteLabel": "兼容性", - "charts.palettes.negativeLabel": "负", - "charts.palettes.positiveLabel": "正", - "charts.palettes.statusLabel": "状态", - "charts.palettes.temperatureLabel": "温度", - "charts.palettes.warmLabel": "暖", "charts.partialData.bucketTooltipText": "选定的时间范围不包括此整个存储桶。其可能包含部分数据。", "charts.warning.warningLabel": "{numberWarnings, number} 个{numberWarnings, plural, other {警告}}", "cloud.connectionDetails.apiKeyFormat.beats.description": "用于配置 Beats", From 027555718a9fd2ba5e3c5e26cc7cfa86cc5d1248 Mon Sep 17 00:00:00 2001 From: nickofthyme Date: Sat, 23 Nov 2024 16:55:09 -0600 Subject: [PATCH 11/41] fix: vis team name --- .github/CODEOWNERS | 2 +- packages/kbn-palettes/kibana.jsonc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 46d214a075174..6cf47775eb15a 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -426,7 +426,7 @@ packages/kbn-openapi-generator @elastic/security-detection-rule-management packages/kbn-optimizer @elastic/kibana-operations packages/kbn-optimizer-webpack-helpers @elastic/kibana-operations packages/kbn-osquery-io-ts-types @elastic/security-asset-management -packages/kbn-palettes @elastic/visualizations +packages/kbn-palettes @elastic/kibana-visualizations packages/kbn-panel-loader @elastic/kibana-presentation packages/kbn-peggy @elastic/kibana-operations packages/kbn-peggy-loader @elastic/kibana-operations diff --git a/packages/kbn-palettes/kibana.jsonc b/packages/kbn-palettes/kibana.jsonc index ab47c2a3b7231..940c34426c2bc 100644 --- a/packages/kbn-palettes/kibana.jsonc +++ b/packages/kbn-palettes/kibana.jsonc @@ -1,5 +1,5 @@ { "type": "shared-common", "id": "@kbn/palettes", - "owner": "@elastic/visualizations" + "owner": "@elastic/kibana-visualizations" } From bbe3409231954f19f3b7fbc320792434402a8c0d Mon Sep 17 00:00:00 2001 From: nickofthyme Date: Sat, 23 Nov 2024 17:00:38 -0600 Subject: [PATCH 12/41] fix: ts-config project references --- packages/react/kibana_context/common/tsconfig.json | 1 - .../chart_expressions/expression_partition_vis/tsconfig.json | 1 + src/plugins/chart_expressions/expression_tagcloud/tsconfig.json | 1 + src/plugins/chart_expressions/expression_xy/tsconfig.json | 1 + src/plugins/charts/tsconfig.json | 2 ++ src/plugins/vis_types/vega/tsconfig.json | 1 + x-pack/plugins/lens/tsconfig.json | 1 + x-pack/test/tsconfig.json | 2 +- 8 files changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/react/kibana_context/common/tsconfig.json b/packages/react/kibana_context/common/tsconfig.json index 16ee1eff00ab6..994137ade7df2 100644 --- a/packages/react/kibana_context/common/tsconfig.json +++ b/packages/react/kibana_context/common/tsconfig.json @@ -14,6 +14,5 @@ "target/**/*" ], "kbn_references": [ - "@kbn/core-ui-settings-common", ] } diff --git a/src/plugins/chart_expressions/expression_partition_vis/tsconfig.json b/src/plugins/chart_expressions/expression_partition_vis/tsconfig.json index 1d8c4c4098728..ec1ac8ee94edc 100644 --- a/src/plugins/chart_expressions/expression_partition_vis/tsconfig.json +++ b/src/plugins/chart_expressions/expression_partition_vis/tsconfig.json @@ -31,6 +31,7 @@ "@kbn/cell-actions", "@kbn/react-kibana-context-render", "@kbn/core-rendering-browser", + "@kbn/palettes", ], "exclude": [ "target/**/*", diff --git a/src/plugins/chart_expressions/expression_tagcloud/tsconfig.json b/src/plugins/chart_expressions/expression_tagcloud/tsconfig.json index 40caf4e3b00f0..485c561bda281 100644 --- a/src/plugins/chart_expressions/expression_tagcloud/tsconfig.json +++ b/src/plugins/chart_expressions/expression_tagcloud/tsconfig.json @@ -28,6 +28,7 @@ "@kbn/chart-icons", "@kbn/data-plugin", "@kbn/react-kibana-context-render", + "@kbn/palettes", ], "exclude": [ "target/**/*", diff --git a/src/plugins/chart_expressions/expression_xy/tsconfig.json b/src/plugins/chart_expressions/expression_xy/tsconfig.json index cd8bd4db90b89..5ffa2904e04b4 100644 --- a/src/plugins/chart_expressions/expression_xy/tsconfig.json +++ b/src/plugins/chart_expressions/expression_xy/tsconfig.json @@ -36,6 +36,7 @@ "@kbn/cell-actions", "@kbn/react-kibana-context-render", "@kbn/core-rendering-browser", + "@kbn/palettes", ], "exclude": [ "target/**/*", diff --git a/src/plugins/charts/tsconfig.json b/src/plugins/charts/tsconfig.json index 8ad33a8517031..0bd9814e55579 100644 --- a/src/plugins/charts/tsconfig.json +++ b/src/plugins/charts/tsconfig.json @@ -16,6 +16,8 @@ "@kbn/shared-ux-utility", "@kbn/config-schema", "@kbn/data-plugin", + "@kbn/core-lifecycle-browser-mocks", + "@kbn/palettes", ], "exclude": [ "target/**/*", diff --git a/src/plugins/vis_types/vega/tsconfig.json b/src/plugins/vis_types/vega/tsconfig.json index 172dd4c60fea7..3c980d413b1c5 100644 --- a/src/plugins/vis_types/vega/tsconfig.json +++ b/src/plugins/vis_types/vega/tsconfig.json @@ -41,6 +41,7 @@ "@kbn/code-editor", "@kbn/react-kibana-context-render", "@kbn/search-types", + "@kbn/palettes", ], "exclude": [ "target/**/*", diff --git a/x-pack/plugins/lens/tsconfig.json b/x-pack/plugins/lens/tsconfig.json index db249f19f3614..bd13226129d93 100644 --- a/x-pack/plugins/lens/tsconfig.json +++ b/x-pack/plugins/lens/tsconfig.json @@ -114,6 +114,7 @@ "@kbn/es-types", "@kbn/esql-datagrid", "@kbn/transpose-utils", + "@kbn/palettes", ], "exclude": ["target/**/*"] } diff --git a/x-pack/test/tsconfig.json b/x-pack/test/tsconfig.json index 9db41aecbb612..975a3bf201919 100644 --- a/x-pack/test/tsconfig.json +++ b/x-pack/test/tsconfig.json @@ -137,7 +137,6 @@ "@kbn/stack-connectors-plugin", "@kbn/stack-alerts-plugin", "@kbn/apm-data-access-plugin", - "@kbn/coloring", "@kbn/profiling-utils", "@kbn/profiling-data-access-plugin", "@kbn/coloring", @@ -188,5 +187,6 @@ "@kbn/ai-assistant-common", "@kbn/core-deprecations-common", "@kbn/usage-collection-plugin", + "@kbn/palettes", ] } From c9944c0323e7d41cb5c8bb1ea04a662848dc1a33 Mon Sep 17 00:00:00 2001 From: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Date: Sat, 23 Nov 2024 23:13:51 +0000 Subject: [PATCH 13/41] [CI] Auto-commit changed files from 'node scripts/lint_ts_projects --fix' --- x-pack/test/tsconfig.json | 1 - 1 file changed, 1 deletion(-) diff --git a/x-pack/test/tsconfig.json b/x-pack/test/tsconfig.json index 975a3bf201919..de33fa502e0bb 100644 --- a/x-pack/test/tsconfig.json +++ b/x-pack/test/tsconfig.json @@ -139,7 +139,6 @@ "@kbn/apm-data-access-plugin", "@kbn/profiling-utils", "@kbn/profiling-data-access-plugin", - "@kbn/coloring", "@kbn/es", "@kbn/metrics-data-access-plugin", "@kbn/dataset-quality-plugin", From 21e1b164c5bf6af39b055ae8028e24f647039705 Mon Sep 17 00:00:00 2001 From: nickofthyme Date: Tue, 26 Nov 2024 22:19:09 -0600 Subject: [PATCH 14/41] fix: get colors based on palette or color mapping --- .../visualizations/partition/dimension_editor.tsx | 11 ++++++++--- .../visualizations/tagcloud/tags_dimension_editor.tsx | 11 ++++++++--- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/lens/public/visualizations/partition/dimension_editor.tsx b/x-pack/plugins/lens/public/visualizations/partition/dimension_editor.tsx index 387f2a6ff7a66..efd2cb4a27fe6 100644 --- a/x-pack/plugins/lens/public/visualizations/partition/dimension_editor.tsx +++ b/x-pack/plugins/lens/public/visualizations/partition/dimension_editor.tsx @@ -14,7 +14,6 @@ import { PaletteRegistry, ColorMapping, SPECIAL_TOKENS_STRING_CONVERSION, - getColorsFromMapping, } from '@kbn/coloring'; import { ColorPicker } from '@kbn/visualization-ui-components'; import { useDebouncedValue } from '@kbn/visualization-utils'; @@ -24,7 +23,7 @@ import { getColorCategories } from '@kbn/chart-expressions-common'; import { KbnPalette, KbnPalettes } from '@kbn/palettes'; import { PieVisualizationState } from '../../../common/types'; import { VisualizationDimensionEditorProps } from '../../types'; -import { PalettePanelContainer, PalettePicker } from '../../shared_components'; +import { PalettePanelContainer, PalettePicker, getColorStops } from '../../shared_components'; import { CollapseSetting } from '../../shared_components/collapse_setting'; import { getDefaultColorForMultiMetricDimension, @@ -119,7 +118,13 @@ export function DimensionEditor(props: DimensionEditorProps) { }) : undefined; - const colors = getColorsFromMapping(props.palettes, props.isDarkMode, currentLayer.colorMapping); + const colors = getColorStops( + props.paletteService, + props.palettes, + props.isDarkMode, + props.state.palette, + currentLayer.colorMapping + ); const table = props.frame.activeData?.[currentLayer.layerId]; const splitCategories = getColorCategories(table?.rows ?? [], props.accessor); diff --git a/x-pack/plugins/lens/public/visualizations/tagcloud/tags_dimension_editor.tsx b/x-pack/plugins/lens/public/visualizations/tagcloud/tags_dimension_editor.tsx index 0f447e04bed58..70abbc10899d4 100644 --- a/x-pack/plugins/lens/public/visualizations/tagcloud/tags_dimension_editor.tsx +++ b/x-pack/plugins/lens/public/visualizations/tagcloud/tags_dimension_editor.tsx @@ -13,7 +13,6 @@ import { ColorMapping, SPECIAL_TOKENS_STRING_CONVERSION, PaletteOutput, - getColorsFromMapping, } from '@kbn/coloring'; import { i18n } from '@kbn/i18n'; import { EuiFlexGroup, EuiFlexItem, EuiSwitch, EuiFormRow, EuiText, EuiBadge } from '@elastic/eui'; @@ -22,7 +21,7 @@ import { useDebouncedValue } from '@kbn/visualization-utils'; import { getColorCategories } from '@kbn/chart-expressions-common'; import { KbnPalettes } from '@kbn/palettes'; import type { TagcloudState } from './types'; -import { PalettePanelContainer, PalettePicker } from '../../shared_components'; +import { PalettePanelContainer, PalettePicker, getColorStops } from '../../shared_components'; import { FramePublicAPI } from '../../types'; import { trackUiCounterEvents } from '../../lens_ui_telemetry'; @@ -54,7 +53,13 @@ export function TagsDimensionEditor({ }); const [useNewColorMapping, setUseNewColorMapping] = useState(state.colorMapping ? true : false); - const colors = getColorsFromMapping(palettes, isDarkMode, state.colorMapping); + const colors = getColorStops( + paletteService, + palettes, + isDarkMode, + state.palette, + state.colorMapping + ); const table = frame.activeData?.[state.layerId]; const splitCategories = getColorCategories(table?.rows ?? [], state.tagAccessor); From 70688cc456fe42c6693712d8995cd959efbc8750 Mon Sep 17 00:00:00 2001 From: nickofthyme Date: Tue, 26 Nov 2024 22:20:50 -0600 Subject: [PATCH 15/41] chore: add observable palettes to Lens xy charts --- .../palettes/categorical/elastic.ts | 4 +-- packages/kbn-palettes/palettes/index.ts | 1 + .../kbn-palettes/palettes/vis_state_colors.ts | 21 +++++++++++++ .../public/components/xy_chart.tsx | 8 ++++- .../xy_chart_renderer.tsx | 3 ++ .../expression_xy/public/plugin.ts | 1 + src/plugins/charts/public/plugin.ts | 9 +++--- .../public/services/palettes/service.ts | 31 ++++++++++++++++--- 8 files changed, 66 insertions(+), 12 deletions(-) create mode 100644 packages/kbn-palettes/palettes/vis_state_colors.ts diff --git a/packages/kbn-palettes/palettes/categorical/elastic.ts b/packages/kbn-palettes/palettes/categorical/elastic.ts index a4b025749b0f6..71f63bfd0b1e2 100644 --- a/packages/kbn-palettes/palettes/categorical/elastic.ts +++ b/packages/kbn-palettes/palettes/categorical/elastic.ts @@ -17,7 +17,7 @@ import { KbnCategoricalPalette } from '../../classes/categorical_palette'; * This is not correctly returning the updated vis colors from eui. * All gradient function work correctly. */ -export const elasticPaletteBad = new KbnColorFnPalette({ +export const elasticPalette = new KbnColorFnPalette({ id: KbnPalette.Default, type: 'categorical', aliases: [ @@ -33,7 +33,7 @@ export const elasticPaletteBad = new KbnColorFnPalette({ colorFn: (n) => euiPaletteColorBlind({ rotations: Math.ceil(n / 10) }).slice(0, n), }); -export const elasticPalette = new KbnCategoricalPalette({ +export const elasticPaletteCustom = new KbnCategoricalPalette({ id: KbnPalette.Default, aliases: [ 'elastic_borealis', // placeholder - not yet used diff --git a/packages/kbn-palettes/palettes/index.ts b/packages/kbn-palettes/palettes/index.ts index 6ca0a44b78b7e..ddb5e6ae0fa43 100644 --- a/packages/kbn-palettes/palettes/index.ts +++ b/packages/kbn-palettes/palettes/index.ts @@ -44,3 +44,4 @@ export const getPalettes = (darkMode: boolean) => export { elasticPalette } from './categorical'; export * from './get_kbn_palettes'; +export * from './vis_state_colors'; diff --git a/packages/kbn-palettes/palettes/vis_state_colors.ts b/packages/kbn-palettes/palettes/vis_state_colors.ts new file mode 100644 index 0000000000000..0c46f1183c1d3 --- /dev/null +++ b/packages/kbn-palettes/palettes/vis_state_colors.ts @@ -0,0 +1,21 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { EUI_VIS_COLOR_STORE } from '@elastic/eui'; +import { Observable } from 'rxjs'; + +export const euiVisColors$ = new Observable((subscriber) => { + const storeId = EUI_VIS_COLOR_STORE.subscribe('UPDATE', () => { + subscriber.next(); + }); + + return () => { + EUI_VIS_COLOR_STORE.unsubscribe('UPDATE', storeId); + }; +}); diff --git a/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx b/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx index 3ebc9efcd6c0a..d21b0a7561541 100644 --- a/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx @@ -33,6 +33,7 @@ import { SettingsProps, LEGACY_LIGHT_THEME, } from '@elastic/charts'; +import type { Observable } from 'rxjs'; import { partition } from 'lodash'; import { IconType } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; @@ -57,6 +58,7 @@ import { import { PersistedState } from '@kbn/visualizations-plugin/public'; import { getOverridesFor, ChartSizeSpec } from '@kbn/chart-expressions-common'; import { useAppFixedViewport } from '@kbn/core-rendering-browser'; +import useObservable from 'react-use/lib/useObservable'; import type { FilterEvent, BrushEvent, @@ -133,6 +135,7 @@ export type XYChartRenderProps = Omit & { chartsActiveCursorService: ChartsPluginStart['activeCursor']; data: DataPublicPluginStart; paletteService: PaletteRegistry; + palettes$: Observable; formatFactory: FormatFactory; timeZone: string; useLegacyTimeAxis: boolean; @@ -199,7 +202,8 @@ export function XYChart({ timeZone, chartsThemeService, chartsActiveCursorService, - paletteService, + palettes$, + paletteService: paletteServiceFallback, minInterval, onClickValue, onClickMultiValue, @@ -237,6 +241,8 @@ export function XYChart({ const palettes = useKbnPalettes(); const appFixedViewport = useAppFixedViewport(); const filteredLayers = getFilteredLayers(layers); + const paletteService = useObservable(palettes$, paletteServiceFallback); + const layersById = filteredLayers.reduce>( (hashMap, layer) => ({ ...hashMap, [layer.layerId]: layer }), {} diff --git a/src/plugins/chart_expressions/expression_xy/public/expression_renderers/xy_chart_renderer.tsx b/src/plugins/chart_expressions/expression_xy/public/expression_renderers/xy_chart_renderer.tsx index cb7a75fcdf691..eb441fffa0226 100644 --- a/src/plugins/chart_expressions/expression_xy/public/expression_renderers/xy_chart_renderer.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/expression_renderers/xy_chart_renderer.tsx @@ -33,6 +33,7 @@ import { } from '@kbn/chart-expressions-common'; import { ThemeServiceSetup } from '@kbn/core/public'; +import { Observable } from 'rxjs'; import type { getDataLayers } from '../helpers'; import { LayerTypes, SeriesTypes } from '../../common/constants'; import type { CommonXYDataLayerConfig, XYChartProps } from '../../common'; @@ -51,6 +52,7 @@ export interface GetStartDeps { kibanaTheme: ThemeServiceSetup; activeCursor: ChartsPluginStart['activeCursor']; paletteService: PaletteRegistry; + palettes$: Observable; timeZone: string; useLegacyTimeAxis: boolean; eventAnnotationService: EventAnnotationServiceType; @@ -271,6 +273,7 @@ export const getXyChartRenderer = ({ chartsActiveCursorService={deps.activeCursor} chartsThemeService={deps.theme} paletteService={deps.paletteService} + palettes$={deps.palettes$} timeZone={deps.timeZone} timeFormat={deps.timeFormat} eventAnnotationService={deps.eventAnnotationService} diff --git a/src/plugins/chart_expressions/expression_xy/public/plugin.ts b/src/plugins/chart_expressions/expression_xy/public/plugin.ts index 8415e2bc7d04c..ccecea70c58d9 100755 --- a/src/plugins/chart_expressions/expression_xy/public/plugin.ts +++ b/src/plugins/chart_expressions/expression_xy/public/plugin.ts @@ -95,6 +95,7 @@ export class ExpressionXyPlugin { usageCollection, activeCursor, paletteService, + palettes$: palettes.palettes$, useLegacyTimeAxis, eventAnnotationService, timeZone: getTimeZone(core.uiSettings), diff --git a/src/plugins/charts/public/plugin.ts b/src/plugins/charts/public/plugin.ts index 06a7236545aba..52fcdcf331f7f 100644 --- a/src/plugins/charts/public/plugin.ts +++ b/src/plugins/charts/public/plugin.ts @@ -7,7 +7,7 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -import { Plugin, CoreSetup } from '@kbn/core/public'; +import { Plugin, CoreSetup, CoreStart } from '@kbn/core/public'; import { ExpressionsSetup } from '@kbn/expressions-plugin/public'; import { palette, systemPalette } from '../common'; @@ -42,8 +42,7 @@ export class ChartsPlugin implements Plugin> | undefined = undefined; - constructor() {} - public setup(theme: CoreTheme) { + public setup(theme: ThemeServiceSetup) { + const palettes$ = new Observable((subscriber) => { + const subscription = combineLatest([theme.theme$, euiVisColors$]).subscribe({ + next: async ([newTheme, visColors]) => { + const { buildPalettes } = await import('./palettes'); + const palettes = buildPalettes(newTheme); + + subscriber.next({ + get: (name: string) => { + const paletteName = getActivePaletteName(name); + return palettes[paletteName]; + }, + getAll: () => Object.values(palettes), + }); + }, + error: (err) => subscriber.error(err), + complete: () => subscriber.complete(), + }); + + return () => subscription.unsubscribe(); + }); + return { + palettes$, getPalettes: async (): Promise => { if (!this.palettes) { const { buildPalettes } = await import('./palettes'); - this.palettes = buildPalettes(theme); + this.palettes = buildPalettes(theme.getTheme()); } return { get: (name: string) => { From fde389a4234b3884685ed0cef9de9b3391faa10c Mon Sep 17 00:00:00 2001 From: Lene Gadewoll Date: Wed, 27 Nov 2024 15:54:21 +0100 Subject: [PATCH 16/41] fix: ensure KibanaEuiProvider mounts with selected theme --- .../src/bootstrap/bootstrap_renderer.ts | 1 + .../src/bootstrap/render_template.ts | 3 +++ packages/react/kibana_context/common/types.ts | 1 + .../react/kibana_context/root/eui_provider.tsx | 14 ++++++++++---- 4 files changed, 15 insertions(+), 4 deletions(-) diff --git a/packages/core/rendering/core-rendering-server-internal/src/bootstrap/bootstrap_renderer.ts b/packages/core/rendering/core-rendering-server-internal/src/bootstrap/bootstrap_renderer.ts index 5b8c267532d0b..5dfc320070de0 100644 --- a/packages/core/rendering/core-rendering-server-internal/src/bootstrap/bootstrap_renderer.ts +++ b/packages/core/rendering/core-rendering-server-internal/src/bootstrap/bootstrap_renderer.ts @@ -111,6 +111,7 @@ export const bootstrapRendererFactory: BootstrapRendererFactory = ({ const body = renderTemplate({ themeTag, + themeName, jsDependencyPaths, publicPathMap, }); diff --git a/packages/core/rendering/core-rendering-server-internal/src/bootstrap/render_template.ts b/packages/core/rendering/core-rendering-server-internal/src/bootstrap/render_template.ts index da9ce12122664..90a6c1d60029d 100644 --- a/packages/core/rendering/core-rendering-server-internal/src/bootstrap/render_template.ts +++ b/packages/core/rendering/core-rendering-server-internal/src/bootstrap/render_template.ts @@ -9,12 +9,14 @@ export interface BootstrapTemplateData { themeTag: string; + themeName: string; jsDependencyPaths: string[]; publicPathMap: string; } export const renderTemplate = ({ themeTag, + themeName, jsDependencyPaths, publicPathMap, }: BootstrapTemplateData) => { @@ -51,6 +53,7 @@ function kbnBundlesLoader() { var kbnCsp = JSON.parse(document.querySelector('kbn-csp').getAttribute('data')); window.__kbnStrictCsp__ = kbnCsp.strictCsp; window.__kbnThemeTag__ = "${themeTag}"; +window.__euiTheme__ = "${themeName}"; window.__kbnPublicPath__ = ${publicPathMap}; window.__kbnBundles__ = kbnBundlesLoader(); diff --git a/packages/react/kibana_context/common/types.ts b/packages/react/kibana_context/common/types.ts index 05e7ab7a0c7d5..e6c15e3cb391f 100644 --- a/packages/react/kibana_context/common/types.ts +++ b/packages/react/kibana_context/common/types.ts @@ -35,4 +35,5 @@ export interface KibanaTheme { */ export interface ThemeServiceStart { theme$: Observable; + getTheme?(): KibanaTheme; } diff --git a/packages/react/kibana_context/root/eui_provider.tsx b/packages/react/kibana_context/root/eui_provider.tsx index 1e4e45c9f36f1..e0694fe0e01ca 100644 --- a/packages/react/kibana_context/root/eui_provider.tsx +++ b/packages/react/kibana_context/root/eui_provider.tsx @@ -63,16 +63,22 @@ const cache = { default: emotionCache, global: globalCache, utility: utilitiesCa * should not be used. Instead, refer to `KibanaRootContextProvider` to set up the root of Kibana. */ export const KibanaEuiProvider: FC> = ({ - theme: { theme$ }, + theme, globalStyles: globalStylesProp, colorMode: colorModeProp, modify, children, }) => { - const kibanaTheme = useObservable(theme$, defaultTheme); + const { theme$ } = theme; + + // use the selected theme if available before using the defaultTheme; this ensures that + // Kibana loads with the currently selected theme without additional updates from default to selected + const initialTheme = theme.getTheme?.() ?? defaultTheme; + + const kibanaTheme = useObservable(theme$, initialTheme); const themeColorMode = useMemo(() => getColorMode(kibanaTheme), [kibanaTheme]); - const theme = useMemo(() => { + const _theme = useMemo(() => { const config = getThemeConfigByName(kibanaTheme.name) || DEFAULT_THEME_CONFIG; return config.euiTheme; }, [kibanaTheme.name]); @@ -87,7 +93,7 @@ export const KibanaEuiProvider: FC> = return ( {children} From 890bcbfbc2ca4c0b0cc4d590801a42e3dbeec1cf Mon Sep 17 00:00:00 2001 From: nickofthyme Date: Mon, 2 Dec 2024 12:07:48 -0600 Subject: [PATCH 17/41] Revert "chore: add observable palettes to Lens xy charts" This reverts commit 70688cc456fe42c6693712d8995cd959efbc8750. --- .../palettes/categorical/elastic.ts | 4 +-- packages/kbn-palettes/palettes/index.ts | 1 - .../kbn-palettes/palettes/vis_state_colors.ts | 21 ------------- .../public/components/xy_chart.tsx | 8 +---- .../xy_chart_renderer.tsx | 3 -- .../expression_xy/public/plugin.ts | 1 - src/plugins/charts/public/plugin.ts | 9 +++--- .../public/services/palettes/service.ts | 31 +++---------------- 8 files changed, 12 insertions(+), 66 deletions(-) delete mode 100644 packages/kbn-palettes/palettes/vis_state_colors.ts diff --git a/packages/kbn-palettes/palettes/categorical/elastic.ts b/packages/kbn-palettes/palettes/categorical/elastic.ts index 71f63bfd0b1e2..a4b025749b0f6 100644 --- a/packages/kbn-palettes/palettes/categorical/elastic.ts +++ b/packages/kbn-palettes/palettes/categorical/elastic.ts @@ -17,7 +17,7 @@ import { KbnCategoricalPalette } from '../../classes/categorical_palette'; * This is not correctly returning the updated vis colors from eui. * All gradient function work correctly. */ -export const elasticPalette = new KbnColorFnPalette({ +export const elasticPaletteBad = new KbnColorFnPalette({ id: KbnPalette.Default, type: 'categorical', aliases: [ @@ -33,7 +33,7 @@ export const elasticPalette = new KbnColorFnPalette({ colorFn: (n) => euiPaletteColorBlind({ rotations: Math.ceil(n / 10) }).slice(0, n), }); -export const elasticPaletteCustom = new KbnCategoricalPalette({ +export const elasticPalette = new KbnCategoricalPalette({ id: KbnPalette.Default, aliases: [ 'elastic_borealis', // placeholder - not yet used diff --git a/packages/kbn-palettes/palettes/index.ts b/packages/kbn-palettes/palettes/index.ts index ddb5e6ae0fa43..6ca0a44b78b7e 100644 --- a/packages/kbn-palettes/palettes/index.ts +++ b/packages/kbn-palettes/palettes/index.ts @@ -44,4 +44,3 @@ export const getPalettes = (darkMode: boolean) => export { elasticPalette } from './categorical'; export * from './get_kbn_palettes'; -export * from './vis_state_colors'; diff --git a/packages/kbn-palettes/palettes/vis_state_colors.ts b/packages/kbn-palettes/palettes/vis_state_colors.ts deleted file mode 100644 index 0c46f1183c1d3..0000000000000 --- a/packages/kbn-palettes/palettes/vis_state_colors.ts +++ /dev/null @@ -1,21 +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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { EUI_VIS_COLOR_STORE } from '@elastic/eui'; -import { Observable } from 'rxjs'; - -export const euiVisColors$ = new Observable((subscriber) => { - const storeId = EUI_VIS_COLOR_STORE.subscribe('UPDATE', () => { - subscriber.next(); - }); - - return () => { - EUI_VIS_COLOR_STORE.unsubscribe('UPDATE', storeId); - }; -}); diff --git a/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx b/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx index d21b0a7561541..3ebc9efcd6c0a 100644 --- a/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx @@ -33,7 +33,6 @@ import { SettingsProps, LEGACY_LIGHT_THEME, } from '@elastic/charts'; -import type { Observable } from 'rxjs'; import { partition } from 'lodash'; import { IconType } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; @@ -58,7 +57,6 @@ import { import { PersistedState } from '@kbn/visualizations-plugin/public'; import { getOverridesFor, ChartSizeSpec } from '@kbn/chart-expressions-common'; import { useAppFixedViewport } from '@kbn/core-rendering-browser'; -import useObservable from 'react-use/lib/useObservable'; import type { FilterEvent, BrushEvent, @@ -135,7 +133,6 @@ export type XYChartRenderProps = Omit & { chartsActiveCursorService: ChartsPluginStart['activeCursor']; data: DataPublicPluginStart; paletteService: PaletteRegistry; - palettes$: Observable; formatFactory: FormatFactory; timeZone: string; useLegacyTimeAxis: boolean; @@ -202,8 +199,7 @@ export function XYChart({ timeZone, chartsThemeService, chartsActiveCursorService, - palettes$, - paletteService: paletteServiceFallback, + paletteService, minInterval, onClickValue, onClickMultiValue, @@ -241,8 +237,6 @@ export function XYChart({ const palettes = useKbnPalettes(); const appFixedViewport = useAppFixedViewport(); const filteredLayers = getFilteredLayers(layers); - const paletteService = useObservable(palettes$, paletteServiceFallback); - const layersById = filteredLayers.reduce>( (hashMap, layer) => ({ ...hashMap, [layer.layerId]: layer }), {} diff --git a/src/plugins/chart_expressions/expression_xy/public/expression_renderers/xy_chart_renderer.tsx b/src/plugins/chart_expressions/expression_xy/public/expression_renderers/xy_chart_renderer.tsx index eb441fffa0226..cb7a75fcdf691 100644 --- a/src/plugins/chart_expressions/expression_xy/public/expression_renderers/xy_chart_renderer.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/expression_renderers/xy_chart_renderer.tsx @@ -33,7 +33,6 @@ import { } from '@kbn/chart-expressions-common'; import { ThemeServiceSetup } from '@kbn/core/public'; -import { Observable } from 'rxjs'; import type { getDataLayers } from '../helpers'; import { LayerTypes, SeriesTypes } from '../../common/constants'; import type { CommonXYDataLayerConfig, XYChartProps } from '../../common'; @@ -52,7 +51,6 @@ export interface GetStartDeps { kibanaTheme: ThemeServiceSetup; activeCursor: ChartsPluginStart['activeCursor']; paletteService: PaletteRegistry; - palettes$: Observable; timeZone: string; useLegacyTimeAxis: boolean; eventAnnotationService: EventAnnotationServiceType; @@ -273,7 +271,6 @@ export const getXyChartRenderer = ({ chartsActiveCursorService={deps.activeCursor} chartsThemeService={deps.theme} paletteService={deps.paletteService} - palettes$={deps.palettes$} timeZone={deps.timeZone} timeFormat={deps.timeFormat} eventAnnotationService={deps.eventAnnotationService} diff --git a/src/plugins/chart_expressions/expression_xy/public/plugin.ts b/src/plugins/chart_expressions/expression_xy/public/plugin.ts index ccecea70c58d9..8415e2bc7d04c 100755 --- a/src/plugins/chart_expressions/expression_xy/public/plugin.ts +++ b/src/plugins/chart_expressions/expression_xy/public/plugin.ts @@ -95,7 +95,6 @@ export class ExpressionXyPlugin { usageCollection, activeCursor, paletteService, - palettes$: palettes.palettes$, useLegacyTimeAxis, eventAnnotationService, timeZone: getTimeZone(core.uiSettings), diff --git a/src/plugins/charts/public/plugin.ts b/src/plugins/charts/public/plugin.ts index 52fcdcf331f7f..06a7236545aba 100644 --- a/src/plugins/charts/public/plugin.ts +++ b/src/plugins/charts/public/plugin.ts @@ -7,7 +7,7 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -import { Plugin, CoreSetup, CoreStart } from '@kbn/core/public'; +import { Plugin, CoreSetup } from '@kbn/core/public'; import { ExpressionsSetup } from '@kbn/expressions-plugin/public'; import { palette, systemPalette } from '../common'; @@ -42,7 +42,8 @@ export class ChartsPlugin implements Plugin> | undefined = undefined; + constructor() {} - public setup(theme: ThemeServiceSetup) { - const palettes$ = new Observable((subscriber) => { - const subscription = combineLatest([theme.theme$, euiVisColors$]).subscribe({ - next: async ([newTheme, visColors]) => { - const { buildPalettes } = await import('./palettes'); - const palettes = buildPalettes(newTheme); - - subscriber.next({ - get: (name: string) => { - const paletteName = getActivePaletteName(name); - return palettes[paletteName]; - }, - getAll: () => Object.values(palettes), - }); - }, - error: (err) => subscriber.error(err), - complete: () => subscriber.complete(), - }); - - return () => subscription.unsubscribe(); - }); - + public setup(theme: CoreTheme) { return { - palettes$, getPalettes: async (): Promise => { if (!this.palettes) { const { buildPalettes } = await import('./palettes'); - this.palettes = buildPalettes(theme.getTheme()); + this.palettes = buildPalettes(theme); } return { get: (name: string) => { From fd10121067df720ab4b73f23e47edb803e43a051 Mon Sep 17 00:00:00 2001 From: nickofthyme Date: Mon, 2 Dec 2024 14:03:43 -0600 Subject: [PATCH 18/41] chore: use eui color blind palette function --- .../palettes/categorical/elastic.ts | 50 +++++++++---------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/packages/kbn-palettes/palettes/categorical/elastic.ts b/packages/kbn-palettes/palettes/categorical/elastic.ts index a4b025749b0f6..4cb7563154285 100644 --- a/packages/kbn-palettes/palettes/categorical/elastic.ts +++ b/packages/kbn-palettes/palettes/categorical/elastic.ts @@ -17,7 +17,7 @@ import { KbnCategoricalPalette } from '../../classes/categorical_palette'; * This is not correctly returning the updated vis colors from eui. * All gradient function work correctly. */ -export const elasticPaletteBad = new KbnColorFnPalette({ +export const elasticPalette = new KbnColorFnPalette({ id: KbnPalette.Default, type: 'categorical', aliases: [ @@ -33,7 +33,7 @@ export const elasticPaletteBad = new KbnColorFnPalette({ colorFn: (n) => euiPaletteColorBlind({ rotations: Math.ceil(n / 10) }).slice(0, n), }); -export const elasticPalette = new KbnCategoricalPalette({ +export const elasticPaletteCustom = new KbnCategoricalPalette({ id: KbnPalette.Default, aliases: [ 'elastic_borealis', // placeholder - not yet used @@ -45,34 +45,34 @@ export const elasticPalette = new KbnCategoricalPalette({ }), colors: [ '#00BEB8', - '#98E6E2', + '#93E5E0', '#599DFF', '#B4D5FF', '#ED6BA2', '#FFBED5', '#F66D64', '#FFC0B8', - '#E6AB01', - '#FCD279', - '#40CFCA', - '#B2EDEA', - '#83B6FF', - '#C7E0FF', - '#F290BA', - '#FFCFE0', - '#F9928B', - '#FFD0CA', - '#EDC041', - '#FDDE9B', - '#80DFDC', - '#CCF3F1', - '#ACCEFF', - '#DAEAFF', - '#F6B5D1', - '#FFDFEA', - '#FBB6B2', - '#FFE0DC', - '#F3D580', - '#FEE9BC', + '#ED9E00', + '#FFD569', + '#00CBC5', + '#C0F1EE', + '#78B0FF', + '#D2E7FF', + '#F588B3', + '#FFD9E7', + '#FC8A80', + '#FFDAD5', + '#F5AF00', + '#FCE8B0', + '#5DD8D2', + '#D9FDFB', + '#96C3FF', + '#E5F1FF', + '#FBA3C4', + '#FFEBF5', + '#FFA59C', + '#FFE9E5', + '#FEC514', + '#FFF1CC', ], }); From e1a22b5b2b1febbe8b79cc0a5bd2edfbc1356ea5 Mon Sep 17 00:00:00 2001 From: nickofthyme Date: Mon, 2 Dec 2024 14:27:15 -0600 Subject: [PATCH 19/41] chore: remove unused changes --- .../src/bootstrap/bootstrap_renderer.ts | 1 - .../src/bootstrap/render_template.ts | 3 --- 2 files changed, 4 deletions(-) diff --git a/packages/core/rendering/core-rendering-server-internal/src/bootstrap/bootstrap_renderer.ts b/packages/core/rendering/core-rendering-server-internal/src/bootstrap/bootstrap_renderer.ts index 5dfc320070de0..5b8c267532d0b 100644 --- a/packages/core/rendering/core-rendering-server-internal/src/bootstrap/bootstrap_renderer.ts +++ b/packages/core/rendering/core-rendering-server-internal/src/bootstrap/bootstrap_renderer.ts @@ -111,7 +111,6 @@ export const bootstrapRendererFactory: BootstrapRendererFactory = ({ const body = renderTemplate({ themeTag, - themeName, jsDependencyPaths, publicPathMap, }); diff --git a/packages/core/rendering/core-rendering-server-internal/src/bootstrap/render_template.ts b/packages/core/rendering/core-rendering-server-internal/src/bootstrap/render_template.ts index 90a6c1d60029d..da9ce12122664 100644 --- a/packages/core/rendering/core-rendering-server-internal/src/bootstrap/render_template.ts +++ b/packages/core/rendering/core-rendering-server-internal/src/bootstrap/render_template.ts @@ -9,14 +9,12 @@ export interface BootstrapTemplateData { themeTag: string; - themeName: string; jsDependencyPaths: string[]; publicPathMap: string; } export const renderTemplate = ({ themeTag, - themeName, jsDependencyPaths, publicPathMap, }: BootstrapTemplateData) => { @@ -53,7 +51,6 @@ function kbnBundlesLoader() { var kbnCsp = JSON.parse(document.querySelector('kbn-csp').getAttribute('data')); window.__kbnStrictCsp__ = kbnCsp.strictCsp; window.__kbnThemeTag__ = "${themeTag}"; -window.__euiTheme__ = "${themeName}"; window.__kbnPublicPath__ = ${publicPathMap}; window.__kbnBundles__ = kbnBundlesLoader(); From 4ef7bd8a8d172e37bb47fdef15c00a5e7e0a35ca Mon Sep 17 00:00:00 2001 From: nickofthyme Date: Mon, 2 Dec 2024 14:27:51 -0600 Subject: [PATCH 20/41] fix: vega color palette assignment --- src/plugins/vis_types/vega/public/plugin.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/plugins/vis_types/vega/public/plugin.ts b/src/plugins/vis_types/vega/public/plugin.ts index 8816dd1ec7386..c386de32dbdec 100644 --- a/src/plugins/vis_types/vega/public/plugin.ts +++ b/src/plugins/vis_types/vega/public/plugin.ts @@ -80,15 +80,6 @@ export class VegaPlugin implements Plugin { enableExternalUrls: this.initializerContext.config.get().enableExternalUrls, }); - core.theme.theme$ - .subscribe({ - next(theme) { - const palettes = getKbnPalettes(theme); - scheme('elastic', palettes.get(KbnPalette.Default).colors()); - }, - }) - .unsubscribe(); - const visualizationDependencies: Readonly = { core, plugins: { @@ -109,6 +100,15 @@ export class VegaPlugin implements Plugin { core: CoreStart, { data, mapsEms, dataViews, usageCollection }: VegaPluginStartDependencies ) { + core.theme.theme$ + .subscribe({ + next(theme) { + const palettes = getKbnPalettes(theme); + scheme('elastic', palettes.get(KbnPalette.Default).colors()); + }, + }) + .unsubscribe(); + setNotifications(core.notifications); setData(data); setDataViews(dataViews); From 75556ffb4c983d43a59be6ea398ff27ce7caa02f Mon Sep 17 00:00:00 2001 From: nickofthyme Date: Mon, 2 Dec 2024 17:09:34 -0600 Subject: [PATCH 21/41] test: update jest tests --- .../__snapshots__/xy_chart.test.tsx.snap | 70 +++++++++++++++++++ .../public/services/theme/theme.test.tsx | 8 +-- .../vega_visualization.test.tsx.snap | 6 +- .../vega/public/vega_visualization.test.tsx | 3 + .../lens/public/visualizations/gauge/index.ts | 5 +- .../gauge/palette_config.test.ts | 41 ----------- .../visualizations/gauge/palette_config.tsx | 29 +------- .../visualizations/gauge/visualization.tsx | 2 - .../visualizations/legacy_metric/index.ts | 4 +- .../legacy_metric/visualization.test.ts | 13 ++-- .../legacy_metric/visualization.tsx | 3 - .../__snapshots__/visualization.test.ts.snap | 5 +- .../metric/visualization.test.ts | 18 +++-- .../visualizations/xy/visualization.test.tsx | 2 +- 14 files changed, 113 insertions(+), 96 deletions(-) delete mode 100644 x-pack/plugins/lens/public/visualizations/gauge/palette_config.test.ts diff --git a/src/plugins/chart_expressions/expression_xy/public/components/__snapshots__/xy_chart.test.tsx.snap b/src/plugins/chart_expressions/expression_xy/public/components/__snapshots__/xy_chart.test.tsx.snap index 5cfd34c6c8b5a..c01267bf3acd7 100644 --- a/src/plugins/chart_expressions/expression_xy/public/components/__snapshots__/xy_chart.test.tsx.snap +++ b/src/plugins/chart_expressions/expression_xy/public/components/__snapshots__/xy_chart.test.tsx.snap @@ -1751,6 +1751,13 @@ exports[`XYChart component it renders area 1`] = ` "getAll": [MockFunction], } } + palettes={ + KbnPalettes { + "get": [Function], + "getAll": [Function], + "query": [Function], + } + } shouldShowValueLabels={true} syncColors={false} timeZone="UTC" @@ -3306,6 +3313,13 @@ exports[`XYChart component it renders bar 1`] = ` "getAll": [MockFunction], } } + palettes={ + KbnPalettes { + "get": [Function], + "getAll": [Function], + "query": [Function], + } + } shouldShowValueLabels={true} syncColors={false} timeZone="UTC" @@ -4861,6 +4875,13 @@ exports[`XYChart component it renders horizontal bar 1`] = ` "getAll": [MockFunction], } } + palettes={ + KbnPalettes { + "get": [Function], + "getAll": [Function], + "query": [Function], + } + } shouldShowValueLabels={true} syncColors={false} timeZone="UTC" @@ -6416,6 +6437,13 @@ exports[`XYChart component it renders line 1`] = ` "getAll": [MockFunction], } } + palettes={ + KbnPalettes { + "get": [Function], + "getAll": [Function], + "query": [Function], + } + } shouldShowValueLabels={true} syncColors={false} timeZone="UTC" @@ -7971,6 +7999,13 @@ exports[`XYChart component it renders stacked area 1`] = ` "getAll": [MockFunction], } } + palettes={ + KbnPalettes { + "get": [Function], + "getAll": [Function], + "query": [Function], + } + } shouldShowValueLabels={true} syncColors={false} timeZone="UTC" @@ -9526,6 +9561,13 @@ exports[`XYChart component it renders stacked bar 1`] = ` "getAll": [MockFunction], } } + palettes={ + KbnPalettes { + "get": [Function], + "getAll": [Function], + "query": [Function], + } + } shouldShowValueLabels={true} syncColors={false} timeZone="UTC" @@ -11081,6 +11123,13 @@ exports[`XYChart component it renders stacked horizontal bar 1`] = ` "getAll": [MockFunction], } } + palettes={ + KbnPalettes { + "get": [Function], + "getAll": [Function], + "query": [Function], + } + } shouldShowValueLabels={true} syncColors={false} timeZone="UTC" @@ -12862,6 +12911,13 @@ exports[`XYChart component split chart should render split chart if both, splitR "getAll": [MockFunction], } } + palettes={ + KbnPalettes { + "get": [Function], + "getAll": [Function], + "query": [Function], + } + } shouldShowValueLabels={true} syncColors={false} timeZone="UTC" @@ -14650,6 +14706,13 @@ exports[`XYChart component split chart should render split chart if splitColumnA "getAll": [MockFunction], } } + palettes={ + KbnPalettes { + "get": [Function], + "getAll": [Function], + "query": [Function], + } + } shouldShowValueLabels={true} syncColors={false} timeZone="UTC" @@ -16436,6 +16499,13 @@ exports[`XYChart component split chart should render split chart if splitRowAcce "getAll": [MockFunction], } } + palettes={ + KbnPalettes { + "get": [Function], + "getAll": [Function], + "query": [Function], + } + } shouldShowValueLabels={true} syncColors={false} timeZone="UTC" diff --git a/src/plugins/charts/public/services/theme/theme.test.tsx b/src/plugins/charts/public/services/theme/theme.test.tsx index da89ec475d577..9f3ae5dd433da 100644 --- a/src/plugins/charts/public/services/theme/theme.test.tsx +++ b/src/plugins/charts/public/services/theme/theme.test.tsx @@ -82,19 +82,19 @@ describe('ThemeService', () => { const { useChartsBaseTheme } = themeService; const { result } = renderHook(() => useChartsBaseTheme()); - expect(result.current).toBe(LIGHT_THEME); + expect(result.current).toStrictEqual(LIGHT_THEME); act(() => { setUpMockTheme.theme$ = createTheme$Mock(true); themeService.init(setUpMockTheme); }); - expect(result.current).toBe(DARK_THEME); + expect(result.current).toStrictEqual(DARK_THEME); act(() => { setUpMockTheme.theme$ = createTheme$Mock(false); themeService.init(setUpMockTheme); }); // act(() => darkMode$.next(false)); - expect(result.current).toBe(LIGHT_THEME); + expect(result.current).toStrictEqual(LIGHT_THEME); }); it('should not rerender when emitting the same value', () => { @@ -125,7 +125,7 @@ describe('ThemeService', () => { setUpMockTheme.theme$ = createTheme$Mock(true); themeService.init(setUpMockTheme); }); - expect(renderCounter).toHaveBeenCalledTimes(2); + expect(renderCounter).toHaveBeenCalledTimes(4); }); }); }); diff --git a/src/plugins/vis_types/vega/public/__snapshots__/vega_visualization.test.tsx.snap b/src/plugins/vis_types/vega/public/__snapshots__/vega_visualization.test.tsx.snap index dad12b304efdf..57b812cbe4d50 100644 --- a/src/plugins/vis_types/vega/public/__snapshots__/vega_visualization.test.tsx.snap +++ b/src/plugins/vis_types/vega/public/__snapshots__/vega_visualization.test.tsx.snap @@ -1,7 +1,7 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`VegaVisualizations VegaVisualization - basics should show vega graph (may fail in dev env) 1`] = `"
"`; +exports[`VegaVisualizations VegaVisualization - basics should show vega graph (may fail in dev env) 1`] = `"
"`; -exports[`VegaVisualizations VegaVisualization - basics should show vegalite graph and update on resize (may fail in dev env) 1`] = `"
  • \\"width\\" and \\"height\\" params are ignored because \\"autosize\\" is enabled. Set \\"autosize\\": \\"none\\" to disable
"`; +exports[`VegaVisualizations VegaVisualization - basics should show vegalite graph and update on resize (may fail in dev env) 1`] = `"
  • \\"width\\" and \\"height\\" params are ignored because \\"autosize\\" is enabled. Set \\"autosize\\": \\"none\\" to disable
"`; -exports[`VegaVisualizations VegaVisualization - basics should show vegalite graph and update on resize (may fail in dev env) 2`] = `"
  • \\"width\\" and \\"height\\" params are ignored because \\"autosize\\" is enabled. Set \\"autosize\\": \\"none\\" to disable
"`; +exports[`VegaVisualizations VegaVisualization - basics should show vegalite graph and update on resize (may fail in dev env) 2`] = `"
  • \\"width\\" and \\"height\\" params are ignored because \\"autosize\\" is enabled. Set \\"autosize\\": \\"none\\" to disable
"`; diff --git a/src/plugins/vis_types/vega/public/vega_visualization.test.tsx b/src/plugins/vis_types/vega/public/vega_visualization.test.tsx index ab51db562f4f2..2160c8c1b6275 100644 --- a/src/plugins/vis_types/vega/public/vega_visualization.test.tsx +++ b/src/plugins/vis_types/vega/public/vega_visualization.test.tsx @@ -25,6 +25,8 @@ import { dataViewPluginMocks } from '@kbn/data-views-plugin/public/mocks'; import { VegaVisualizationDependencies } from './plugin'; import React from 'react'; import { TimeCache } from './data_model/time_cache'; +import { euiPaletteColorBlind } from '@elastic/eui'; +import { scheme } from 'vega'; jest.mock('./default_spec', () => ({ getDefaultSpec: () => jest.requireActual('./test_utils/default.spec.json'), @@ -122,6 +124,7 @@ describe('VegaVisualizations', () => { test('should show vega graph (may fail in dev env)', async () => { let vegaVis; try { + scheme('elastic', ['blue', 'yellow']); vegaVis = new VegaVisualization(domNode, jest.fn()); const vegaParser = new VegaParser( JSON.stringify(vegaGraph), diff --git a/x-pack/plugins/lens/public/visualizations/gauge/index.ts b/x-pack/plugins/lens/public/visualizations/gauge/index.ts index 870b4f3b6b586..a08d6d43097e7 100644 --- a/x-pack/plugins/lens/public/visualizations/gauge/index.ts +++ b/x-pack/plugins/lens/public/visualizations/gauge/index.ts @@ -8,7 +8,6 @@ import type { CoreSetup } from '@kbn/core/public'; import type { ChartsPluginSetup } from '@kbn/charts-plugin/public'; import type { EditorFrameSetup } from '../../types'; -import { transparentizePalettes } from './palette_config'; export interface GaugeVisualizationPluginSetupPlugins { editorFrame: EditorFrameSetup; @@ -19,8 +18,8 @@ export class GaugeVisualization { setup(core: CoreSetup, { editorFrame, charts }: GaugeVisualizationPluginSetupPlugins) { editorFrame.registerVisualization(async () => { const { getGaugeVisualization } = await import('../../async_services'); - const palettes = transparentizePalettes(await charts.palettes.getPalettes()); - return getGaugeVisualization({ paletteService: palettes, theme: core.theme }); + const palettes = await charts.palettes.getPalettes(); + return getGaugeVisualization({ paletteService: palettes }); }); } } diff --git a/x-pack/plugins/lens/public/visualizations/gauge/palette_config.test.ts b/x-pack/plugins/lens/public/visualizations/gauge/palette_config.test.ts deleted file mode 100644 index f144a2f9f87f4..0000000000000 --- a/x-pack/plugins/lens/public/visualizations/gauge/palette_config.test.ts +++ /dev/null @@ -1,41 +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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { transparentizePalettes } from './palette_config'; -import { chartPluginMock } from '@kbn/charts-plugin/public/mocks'; - -const paletteServiceMock = chartPluginMock.createPaletteRegistry(); - -describe('transparentizePalettes', () => { - it('converts all colors to half-transparent', () => { - const newPalettes = transparentizePalettes(paletteServiceMock); - - const singlePalette = newPalettes.get('mocked'); - expect(singlePalette.getCategoricalColors(2)).toEqual(['#0000FF80', '#FFFF0080']); - expect( - singlePalette.getCategoricalColor([ - { - name: 'abc', - rankAtDepth: 0, - totalSeriesAtDepth: 5, - }, - ]) - ).toEqual('#0000FF80'); - - const firstPalette = newPalettes.getAll()[0]; - expect(firstPalette.getCategoricalColors(2)).toEqual(['#FF000080', '#00000080']); - expect( - firstPalette.getCategoricalColor([ - { - name: 'abc', - rankAtDepth: 0, - totalSeriesAtDepth: 5, - }, - ]) - ).toEqual('#00000080'); - }); -}); diff --git a/x-pack/plugins/lens/public/visualizations/gauge/palette_config.tsx b/x-pack/plugins/lens/public/visualizations/gauge/palette_config.tsx index db8a9f14f46b1..3d6bd9c94f01b 100644 --- a/x-pack/plugins/lens/public/visualizations/gauge/palette_config.tsx +++ b/x-pack/plugins/lens/public/visualizations/gauge/palette_config.tsx @@ -5,15 +5,8 @@ * 2.0. */ -import { - ChartColorConfiguration, - PaletteDefinition, - PaletteRegistry, - SeriesLayer, - RequiredPaletteParamTypes, -} from '@kbn/coloring'; +import { RequiredPaletteParamTypes } from '@kbn/coloring'; -import chroma from 'chroma-js'; import { defaultPaletteParams as sharedDefaultParams } from '../../shared_components'; export const DEFAULT_PALETTE_NAME = 'temperature'; @@ -29,23 +22,3 @@ export const defaultPaletteParams: RequiredPaletteParamTypes = { steps: DEFAULT_COLOR_STEPS, maxSteps: 5, }; - -export const transparentizePalettes = (palettes: PaletteRegistry) => { - const addAlpha = (c: string | null) => (c ? chroma(c).hex() + `80` : `000000`).toUpperCase(); - const transparentizePalette = (palette: PaletteDefinition) => ({ - ...palette, - getCategoricalColor: ( - series: SeriesLayer[], - chartConfiguration?: ChartColorConfiguration, - state?: unknown - ) => addAlpha(palette.getCategoricalColor(series, chartConfiguration, state)), - getCategoricalColors: (size: number, state?: unknown): string[] => - palette.getCategoricalColors(size, state), - }); - - return { - ...palettes, - get: (name: string) => transparentizePalette(palettes.get(name)), - getAll: () => palettes.getAll().map((singlePalette) => transparentizePalette(singlePalette)), - }; -}; diff --git a/x-pack/plugins/lens/public/visualizations/gauge/visualization.tsx b/x-pack/plugins/lens/public/visualizations/gauge/visualization.tsx index 19b871bfc089e..496ca057ed3da 100644 --- a/x-pack/plugins/lens/public/visualizations/gauge/visualization.tsx +++ b/x-pack/plugins/lens/public/visualizations/gauge/visualization.tsx @@ -7,7 +7,6 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; -import { ThemeServiceStart } from '@kbn/core/public'; import { FormattedMessage } from '@kbn/i18n-react'; import { Ast } from '@kbn/interpreter'; import { buildExpressionFunction, DatatableRow } from '@kbn/expressions-plugin/common'; @@ -58,7 +57,6 @@ import { interface GaugeVisualizationDeps { paletteService: PaletteRegistry; - theme: ThemeServiceStart; } export const isNumericMetric = (op: OperationMetadata) => diff --git a/x-pack/plugins/lens/public/visualizations/legacy_metric/index.ts b/x-pack/plugins/lens/public/visualizations/legacy_metric/index.ts index 933bf4dab6ae8..a624172264442 100644 --- a/x-pack/plugins/lens/public/visualizations/legacy_metric/index.ts +++ b/x-pack/plugins/lens/public/visualizations/legacy_metric/index.ts @@ -20,9 +20,9 @@ export class LegacyMetricVisualization { const { getLegacyMetricVisualization: getMetricVisualization } = await import( '../../async_services' ); - const palettes = await charts.palettes.getPalettes(); + const paletteService = await charts.palettes.getPalettes(); - return getMetricVisualization({ paletteService: palettes, theme: core.theme }); + return getMetricVisualization({ paletteService }); }); } } diff --git a/x-pack/plugins/lens/public/visualizations/legacy_metric/visualization.test.ts b/x-pack/plugins/lens/public/visualizations/legacy_metric/visualization.test.ts index d6a70ddbe7114..faf50074ee8f3 100644 --- a/x-pack/plugins/lens/public/visualizations/legacy_metric/visualization.test.ts +++ b/x-pack/plugins/lens/public/visualizations/legacy_metric/visualization.test.ts @@ -13,7 +13,7 @@ import { generateId } from '../../id_generator'; import { DatasourcePublicAPI, FramePublicAPI } from '../../types'; import { chartPluginMock } from '@kbn/charts-plugin/public/mocks'; import { ColorMode } from '@kbn/charts-plugin/common'; -import { themeServiceMock } from '@kbn/core/public/mocks'; +import { CUSTOM_PALETTE } from '@kbn/coloring'; jest.mock('../../id_generator'); @@ -37,7 +37,6 @@ function mockFrame(): FramePublicAPI { const metricVisualization = getLegacyMetricVisualization({ paletteService: chartPluginMock.createPaletteRegistry(), - theme: themeServiceMock.createStartContract(), }); describe('metric_visualization', () => { @@ -128,7 +127,13 @@ describe('metric_visualization', () => { layerType: LayerTypes.DATA, palette: { type: 'palette', - name: 'status', + name: CUSTOM_PALETTE, + params: { + stops: [ + { color: 'blue', stop: 0 }, + { color: 'yellow', stop: 100 }, + ], + }, }, }, layerId: 'l1', @@ -138,7 +143,7 @@ describe('metric_visualization', () => { groups: [ expect.objectContaining({ accessors: expect.arrayContaining([ - { columnId: 'a', triggerIconType: 'colorBy', palette: [] }, + { columnId: 'a', triggerIconType: 'colorBy', palette: ['blue', 'yellow'] }, ]), }), ], diff --git a/x-pack/plugins/lens/public/visualizations/legacy_metric/visualization.tsx b/x-pack/plugins/lens/public/visualizations/legacy_metric/visualization.tsx index 5ea4b57539461..49ca718fdf94d 100644 --- a/x-pack/plugins/lens/public/visualizations/legacy_metric/visualization.tsx +++ b/x-pack/plugins/lens/public/visualizations/legacy_metric/visualization.tsx @@ -14,7 +14,6 @@ import { shiftPalette, getDefaultColorStops, } from '@kbn/coloring'; -import { ThemeServiceStart } from '@kbn/core/public'; import { ColorMode, CustomPaletteState } from '@kbn/charts-plugin/common'; import { VIS_EVENT_TO_TRIGGER } from '@kbn/visualizations-plugin/public'; import { IconChartMetric } from '@kbn/chart-icons'; @@ -156,10 +155,8 @@ const toExpression = ( export const getLegacyMetricVisualization = ({ paletteService, - theme, }: { paletteService: PaletteRegistry; - theme: ThemeServiceStart; }): Visualization => ({ id: 'lnsLegacyMetric', diff --git a/x-pack/plugins/lens/public/visualizations/metric/__snapshots__/visualization.test.ts.snap b/x-pack/plugins/lens/public/visualizations/metric/__snapshots__/visualization.test.ts.snap index 2490904751e8c..6306758e256f0 100644 --- a/x-pack/plugins/lens/public/visualizations/metric/__snapshots__/visualization.test.ts.snap +++ b/x-pack/plugins/lens/public/visualizations/metric/__snapshots__/visualization.test.ts.snap @@ -7,7 +7,10 @@ Object { "accessors": Array [ Object { "columnId": "metric-col-id", - "palette": Array [], + "palette": Array [ + "blue", + "yellow", + ], "triggerIconType": "colorBy", }, ], diff --git a/x-pack/plugins/lens/public/visualizations/metric/visualization.test.ts b/x-pack/plugins/lens/public/visualizations/metric/visualization.test.ts index e4011ca8431a3..a696ab47a4871 100644 --- a/x-pack/plugins/lens/public/visualizations/metric/visualization.test.ts +++ b/x-pack/plugins/lens/public/visualizations/metric/visualization.test.ts @@ -6,7 +6,7 @@ */ import { chartPluginMock } from '@kbn/charts-plugin/public/mocks'; -import { CustomPaletteParams, PaletteOutput } from '@kbn/coloring'; +import { CUSTOM_PALETTE, CustomPaletteParams, PaletteOutput } from '@kbn/coloring'; import { ExpressionAstExpression, ExpressionAstFunction } from '@kbn/expressions-plugin/common'; import { euiLightVars, euiThemeVars } from '@kbn/ui-theme'; import { LayerTypes } from '@kbn/expression-xy-plugin/public'; @@ -36,9 +36,13 @@ describe('metric visualization', () => { const palette: PaletteOutput = { type: 'palette', - name: 'foo', + name: CUSTOM_PALETTE, params: { rangeType: 'percent', + stops: [ + { color: 'blue', stop: 0 }, + { color: 'yellow', stop: 100 }, + ], }, }; @@ -133,7 +137,10 @@ describe('metric visualization', () => { Array [ Object { "columnId": "metric-col-id", - "palette": Array [], + "palette": Array [ + "blue", + "yellow", + ], "triggerIconType": "colorBy", }, ] @@ -183,7 +190,10 @@ describe('metric visualization', () => { Array [ Object { "columnId": "metric-col-id", - "palette": Array [], + "palette": Array [ + "blue", + "yellow", + ], "triggerIconType": "colorBy", }, ] diff --git a/x-pack/plugins/lens/public/visualizations/xy/visualization.test.tsx b/x-pack/plugins/lens/public/visualizations/xy/visualization.test.tsx index e2c6ce25bd2e3..ecb3c16fb6dda 100644 --- a/x-pack/plugins/lens/public/visualizations/xy/visualization.test.tsx +++ b/x-pack/plugins/lens/public/visualizations/xy/visualization.test.tsx @@ -224,7 +224,7 @@ describe('xy_visualization', () => { "colorMode": Object { "type": "categorical", }, - "paletteId": "eui_amsterdam_color_blind", + "paletteId": "default", "specialAssignments": Array [ Object { "color": Object { From 3dec075528f6180ee180a7c097419cd011cf377d Mon Sep 17 00:00:00 2001 From: nickofthyme Date: Tue, 3 Dec 2024 11:13:22 -0600 Subject: [PATCH 22/41] fix: tagcloud RO loop --- .../public/components/tagcloud_component.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/plugins/chart_expressions/expression_tagcloud/public/components/tagcloud_component.tsx b/src/plugins/chart_expressions/expression_tagcloud/public/components/tagcloud_component.tsx index 46064ebd6b6e2..661c33744c310 100644 --- a/src/plugins/chart_expressions/expression_tagcloud/public/components/tagcloud_component.tsx +++ b/src/plugins/chart_expressions/expression_tagcloud/public/components/tagcloud_component.tsx @@ -143,12 +143,13 @@ export const TagCloudChart = ({ : getColor(palettesRegistry, palette, tag, values, syncColors) || 'rgba(0,0,0,0)', }; }); + // eslint-disable-next-line react-hooks/exhaustive-deps }, [ bucket, visData.columns, visData.rows, metric, - palettes, + // palettes, // somehow causes infinite update of RO isDarkMode, colorMapping, bucketFormatter, From 970df40bf63f197554ffcb7c7290c9de222fd1c4 Mon Sep 17 00:00:00 2001 From: nickofthyme Date: Tue, 3 Dec 2024 11:14:40 -0600 Subject: [PATCH 23/41] fix: color stops overrides for new theme --- packages/kbn-coloring/src/palettes/types.ts | 2 ++ packages/kbn-coloring/src/palettes/utils.ts | 21 ++++++++++++------- .../datatable/visualization.tsx | 8 +++---- .../visualizations/gauge/visualization.tsx | 8 +++---- .../visualizations/heatmap/visualization.tsx | 8 +++---- .../legacy_metric/dimension_editor.tsx | 6 +++--- .../legacy_metric/visualization.tsx | 20 +++++++++--------- .../visualizations/metric/to_expression.ts | 8 +++---- .../visualizations/metric/visualization.tsx | 6 +++--- 9 files changed, 48 insertions(+), 39 deletions(-) diff --git a/packages/kbn-coloring/src/palettes/types.ts b/packages/kbn-coloring/src/palettes/types.ts index b5e81a437f6da..5a43c65097960 100644 --- a/packages/kbn-coloring/src/palettes/types.ts +++ b/packages/kbn-coloring/src/palettes/types.ts @@ -140,7 +140,9 @@ export interface CustomPaletteParams { progression?: 'fixed'; rangeMin?: number; rangeMax?: number; + /** lower color stops */ stops?: ColorStop[]; + /** upper color stops */ colorStops?: ColorStop[]; steps?: number; maxSteps?: number | undefined; diff --git a/packages/kbn-coloring/src/palettes/utils.ts b/packages/kbn-coloring/src/palettes/utils.ts index 505c0796fe06c..a4a3c24f6a797 100644 --- a/packages/kbn-coloring/src/palettes/utils.ts +++ b/packages/kbn-coloring/src/palettes/utils.ts @@ -226,19 +226,26 @@ export function applyPaletteParams> /** * Returns color stops for given palette type: + * * - custom - User has modified the stops in some way - return stops as is * - non-custom - Default palette stops - Return new stops based on palette * * > This is needed for BWC when switching between kibana themes. */ -export function getDefaultColorStops>( +export function getOverridePaletteStops>( paletteService: PaletteRegistry, activePalette?: T ) { - return activePalette && activePalette.name !== CUSTOM_PALETTE - ? applyPaletteParams(paletteService, activePalette, { - min: activePalette.params?.rangeMin ?? 0, - max: activePalette.params?.rangeMax ?? 100, - }) - : activePalette?.params?.stops; + if (!activePalette || activePalette.name === CUSTOM_PALETTE || !activePalette.params?.stops) { + return activePalette?.params?.stops; + } + + const { stops, ...otherParams } = activePalette.params; + const colors = paletteService + .get(activePalette.name ?? DEFAULT_PALETTE_NAME) + .getCategoricalColors(stops.length, otherParams); + return stops.map((stop, i) => ({ + ...stop, + color: colors[i], + })); } diff --git a/x-pack/plugins/lens/public/visualizations/datatable/visualization.tsx b/x-pack/plugins/lens/public/visualizations/datatable/visualization.tsx index c3aac8e48016c..eae44802052b1 100644 --- a/x-pack/plugins/lens/public/visualizations/datatable/visualization.tsx +++ b/x-pack/plugins/lens/public/visualizations/datatable/visualization.tsx @@ -15,7 +15,7 @@ import { PaletteOutput, CustomPaletteParams, applyPaletteParams, - getDefaultColorStops, + getOverridePaletteStops, } from '@kbn/coloring'; import { VIS_EVENT_TO_TRIGGER } from '@kbn/visualizations-plugin/public'; import { IconChartDatatable } from '@kbn/chart-icons'; @@ -583,14 +583,14 @@ export const getDatatableVisualization = ({ columns: columns .filter((c) => !c.collapseFn) .map((column) => { - const colorStops = getDefaultColorStops(paletteService, column.palette); + const stops = getOverridePaletteStops(paletteService, column.palette); const paletteParams = { ...column.palette?.params, // rewrite colors and stops as two distinct arguments - colors: colorStops?.map(({ color }) => color), + colors: stops?.map(({ color }) => color), stops: column.palette?.params?.name === RowHeightMode.custom - ? colorStops?.map(({ stop }) => stop) + ? stops?.map(({ stop }) => stop) : [], reverse: false, // managed at UI level }; diff --git a/x-pack/plugins/lens/public/visualizations/gauge/visualization.tsx b/x-pack/plugins/lens/public/visualizations/gauge/visualization.tsx index 496ca057ed3da..957c1b16cf2b4 100644 --- a/x-pack/plugins/lens/public/visualizations/gauge/visualization.tsx +++ b/x-pack/plugins/lens/public/visualizations/gauge/visualization.tsx @@ -15,7 +15,7 @@ import { CustomPaletteParams, CUSTOM_PALETTE, applyPaletteParams, - getDefaultColorStops, + getOverridePaletteStops, PaletteOutput, } from '@kbn/coloring'; import type { @@ -69,13 +69,13 @@ function computePaletteParams( paletteService: PaletteRegistry, palette: PaletteOutput ) { - const colorStops = getDefaultColorStops(paletteService, palette); + const stops = getOverridePaletteStops(paletteService, palette); return { ...palette.params, // rewrite colors and stops as two distinct arguments - colors: colorStops?.map(({ color }) => color), - stops: palette.params?.name === 'custom' ? colorStops?.map(({ stop }) => stop) : [], + colors: stops?.map(({ color }) => color), + stops: palette.params?.name === 'custom' ? stops?.map(({ stop }) => stop) : [], reverse: false, // managed at UI level }; } diff --git a/x-pack/plugins/lens/public/visualizations/heatmap/visualization.tsx b/x-pack/plugins/lens/public/visualizations/heatmap/visualization.tsx index e17e373a13870..4dfb17241866f 100644 --- a/x-pack/plugins/lens/public/visualizations/heatmap/visualization.tsx +++ b/x-pack/plugins/lens/public/visualizations/heatmap/visualization.tsx @@ -16,7 +16,7 @@ import { PaletteRegistry, CustomPaletteParams, PaletteOutput, - getDefaultColorStops, + getOverridePaletteStops, } from '@kbn/coloring'; import { ThemeServiceStart } from '@kbn/core/public'; import { VIS_EVENT_TO_TRIGGER } from '@kbn/visualizations-plugin/public'; @@ -98,13 +98,13 @@ function computePaletteParams( paletteService: PaletteRegistry, palette: PaletteOutput ) { - const colorStops = getDefaultColorStops(paletteService, palette); + const stops = getOverridePaletteStops(paletteService, palette); return { ...palette.params, // rewrite colors and stops as two distinct arguments - colors: colorStops?.map(({ color }) => color), - stops: palette.params?.name === 'custom' ? colorStops?.map(({ stop }) => stop) : [], + colors: stops?.map(({ color }) => color), + stops: palette.params?.name === 'custom' ? stops?.map(({ stop }) => stop) : [], reverse: false, // managed at UI level }; } diff --git a/x-pack/plugins/lens/public/visualizations/legacy_metric/dimension_editor.tsx b/x-pack/plugins/lens/public/visualizations/legacy_metric/dimension_editor.tsx index e1821e6d292fb..552b5f0a52a3f 100644 --- a/x-pack/plugins/lens/public/visualizations/legacy_metric/dimension_editor.tsx +++ b/x-pack/plugins/lens/public/visualizations/legacy_metric/dimension_editor.tsx @@ -59,7 +59,7 @@ export function MetricDimensionEditor( }; // need to tell the helper that the colorStops are required to display - const displayStops = applyPaletteParams(props.paletteService, activePalette, currentMinMax); + const stops = applyPaletteParams(props.paletteService, activePalette, currentMinMax); return ( <> @@ -114,7 +114,7 @@ export function MetricDimensionEditor( // align this initial computation with same format for default // palettes in the panel. This to avoid custom computation issue with metric // fake data range - stops: displayStops.map((v, i, array) => ({ + stops: stops.map((v, i, array) => ({ ...v, stop: currentMinMax.min + (i === 0 ? 0 : array[i - 1].stop), })), @@ -142,7 +142,7 @@ export function MetricDimensionEditor( })} > color)} + palette={stops.map(({ color }) => color)} siblingRef={props.panelRef} isInlineEditing={isInlineEditing} title={i18n.translate('xpack.lens.paletteMetricGradient.label', { diff --git a/x-pack/plugins/lens/public/visualizations/legacy_metric/visualization.tsx b/x-pack/plugins/lens/public/visualizations/legacy_metric/visualization.tsx index 49ca718fdf94d..74f1642cb0965 100644 --- a/x-pack/plugins/lens/public/visualizations/legacy_metric/visualization.tsx +++ b/x-pack/plugins/lens/public/visualizations/legacy_metric/visualization.tsx @@ -12,7 +12,7 @@ import { PaletteRegistry, CUSTOM_PALETTE, shiftPalette, - getDefaultColorStops, + getOverridePaletteStops, } from '@kbn/coloring'; import { ColorMode, CustomPaletteState } from '@kbn/charts-plugin/common'; import { VIS_EVENT_TO_TRIGGER } from '@kbn/visualizations-plugin/public'; @@ -70,20 +70,20 @@ const toExpression = ( const datasourceExpression = datasourceExpressionsByLayers[state.layerId]; const operation = datasource && datasource.getOperationForColumnId(state.accessor); - const colorStops = getDefaultColorStops(paletteService, state.palette) ?? []; + const stops = getOverridePaletteStops(paletteService, state.palette) ?? []; const isCustomPalette = state.palette?.params?.name === CUSTOM_PALETTE; const canColor = operation?.dataType === 'number'; const paletteParams = { ...state.palette?.params, - colors: colorStops.map(({ color }) => color), + colors: stops.map(({ color }) => color), stops: isCustomPalette || state.palette?.params?.rangeMax == null - ? colorStops.map(({ stop }) => stop) + ? stops.map(({ stop }) => stop) : shiftPalette( - colorStops, - Math.max(state.palette?.params?.rangeMax, ...colorStops.map(({ stop }) => stop)) + stops, + Math.max(state.palette?.params?.rangeMax, ...stops.map(({ stop }) => stop)) ).map(({ stop }) => stop), reverse: false, }; @@ -218,7 +218,7 @@ export const getLegacyMetricVisualization = ({ getConfiguration(props) { const hasColoring = props.state.palette != null; - const colorStops = getDefaultColorStops(paletteService, props.state.palette); + const stops = getOverridePaletteStops(paletteService, props.state.palette); return { groups: [ @@ -240,7 +240,7 @@ export const getLegacyMetricVisualization = ({ { columnId: props.state.accessor, triggerIconType: hasColoring ? 'colorBy' : undefined, - palette: hasColoring ? colorStops?.map(({ color }) => color) : undefined, + palette: hasColoring ? stops?.map(({ color }) => color) : undefined, }, ] : [], @@ -318,7 +318,7 @@ export const getLegacyMetricVisualization = ({ } const hasColoring = state.palette != null; - const colorStops = getDefaultColorStops(paletteService, state.palette); + const stops = getOverridePaletteStops(paletteService, state.palette); return { layers: [ @@ -328,7 +328,7 @@ export const getLegacyMetricVisualization = ({ chartType: 'metric', ...this.getDescription(state), dimensions, - palette: hasColoring ? colorStops?.map(({ color }) => color) : undefined, + palette: hasColoring ? stops?.map(({ color }) => color) : undefined, }, ], }; diff --git a/x-pack/plugins/lens/public/visualizations/metric/to_expression.ts b/x-pack/plugins/lens/public/visualizations/metric/to_expression.ts index 08739fb0a4a85..09e1de6192472 100644 --- a/x-pack/plugins/lens/public/visualizations/metric/to_expression.ts +++ b/x-pack/plugins/lens/public/visualizations/metric/to_expression.ts @@ -10,7 +10,7 @@ import { CUSTOM_PALETTE, PaletteRegistry, PaletteOutput, - getDefaultColorStops, + getOverridePaletteStops, } from '@kbn/coloring'; import type { TrendlineExpressionFunctionDefinition, @@ -33,13 +33,13 @@ function computePaletteParams( paletteService: PaletteRegistry, palette: PaletteOutput ) { - const colorStops = getDefaultColorStops(paletteService, palette); + const stops = getOverridePaletteStops(paletteService, palette); return { ...palette.params, // rewrite colors and stops as two distinct arguments - colors: colorStops?.map(({ color }) => color), - stops: palette.params?.name === 'custom' ? colorStops?.map(({ stop }) => stop) : [], + colors: stops?.map(({ color }) => color), + stops: palette.params?.name === 'custom' ? stops?.map(({ stop }) => stop) : [], reverse: false, // managed at UI level }; } diff --git a/x-pack/plugins/lens/public/visualizations/metric/visualization.tsx b/x-pack/plugins/lens/public/visualizations/metric/visualization.tsx index 5a19c2364798c..eb16bd36e683e 100644 --- a/x-pack/plugins/lens/public/visualizations/metric/visualization.tsx +++ b/x-pack/plugins/lens/public/visualizations/metric/visualization.tsx @@ -7,7 +7,7 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; -import { PaletteRegistry, getDefaultColorStops } from '@kbn/coloring'; +import { PaletteRegistry, getOverridePaletteStops } from '@kbn/coloring'; import { ThemeServiceStart } from '@kbn/core/public'; import { VIS_EVENT_TO_TRIGGER } from '@kbn/visualizations-plugin/public'; import { euiLightVars, euiThemeVars } from '@kbn/ui-theme'; @@ -76,11 +76,11 @@ const getMetricLayerConfiguration = ( const hasDynamicColoring = Boolean(isMetricNumeric && props.state.palette); if (hasDynamicColoring) { - const colorStops = getDefaultColorStops(paletteService, props.state.palette); + const stops = getOverridePaletteStops(paletteService, props.state.palette); return { triggerIconType: 'colorBy', - palette: colorStops?.map(({ color }) => color), + palette: stops?.map(({ color }) => color), }; } From 4dfc1abdec36b0a6696d8d2534ee6bd797ccec4d Mon Sep 17 00:00:00 2001 From: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Date: Tue, 3 Dec 2024 17:46:28 +0000 Subject: [PATCH 24/41] [CI] Auto-commit changed files from 'node scripts/eslint --no-cache --fix' --- src/plugins/vis_types/vega/public/vega_visualization.test.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/plugins/vis_types/vega/public/vega_visualization.test.tsx b/src/plugins/vis_types/vega/public/vega_visualization.test.tsx index 2160c8c1b6275..bd1e8d1b12b34 100644 --- a/src/plugins/vis_types/vega/public/vega_visualization.test.tsx +++ b/src/plugins/vis_types/vega/public/vega_visualization.test.tsx @@ -25,7 +25,6 @@ import { dataViewPluginMocks } from '@kbn/data-views-plugin/public/mocks'; import { VegaVisualizationDependencies } from './plugin'; import React from 'react'; import { TimeCache } from './data_model/time_cache'; -import { euiPaletteColorBlind } from '@elastic/eui'; import { scheme } from 'vega'; jest.mock('./default_spec', () => ({ From ed1291aebec8a5ef5cf26aea5b89efd0cc2e8ba7 Mon Sep 17 00:00:00 2001 From: nickofthyme Date: Tue, 3 Dec 2024 14:00:50 -0600 Subject: [PATCH 25/41] chore: fix linting and type errors --- .../vega/public/vega_visualization.test.tsx | 1 - .../gauge/visualization.test.ts | 116 ++++-------------- 2 files changed, 24 insertions(+), 93 deletions(-) diff --git a/src/plugins/vis_types/vega/public/vega_visualization.test.tsx b/src/plugins/vis_types/vega/public/vega_visualization.test.tsx index 2160c8c1b6275..bd1e8d1b12b34 100644 --- a/src/plugins/vis_types/vega/public/vega_visualization.test.tsx +++ b/src/plugins/vis_types/vega/public/vega_visualization.test.tsx @@ -25,7 +25,6 @@ import { dataViewPluginMocks } from '@kbn/data-views-plugin/public/mocks'; import { VegaVisualizationDependencies } from './plugin'; import React from 'react'; import { TimeCache } from './data_model/time_cache'; -import { euiPaletteColorBlind } from '@elastic/eui'; import { scheme } from 'vega'; jest.mock('./default_spec', () => ({ diff --git a/x-pack/plugins/lens/public/visualizations/gauge/visualization.test.ts b/x-pack/plugins/lens/public/visualizations/gauge/visualization.test.ts index e5b908a6f4c76..e240b5ef8a51d 100644 --- a/x-pack/plugins/lens/public/visualizations/gauge/visualization.test.ts +++ b/x-pack/plugins/lens/public/visualizations/gauge/visualization.test.ts @@ -13,7 +13,6 @@ import type { DatasourceLayers, OperationDescriptor } from '../../types'; import { chartPluginMock } from '@kbn/charts-plugin/public/mocks'; import { LayerTypes } from '@kbn/expression-xy-plugin/public'; import type { GaugeVisualizationState } from './constants'; -import { themeServiceMock } from '@kbn/core/public/mocks'; function exampleState(): GaugeVisualizationState { return { @@ -25,8 +24,9 @@ function exampleState(): GaugeVisualizationState { }; } -const paletteService = chartPluginMock.createPaletteRegistry(); -const theme = themeServiceMock.createStartContract(); +const deps = { + paletteService: chartPluginMock.createPaletteRegistry(), +}; describe('gauge', () => { let frame: ReturnType; @@ -37,7 +37,7 @@ describe('gauge', () => { describe('#intialize', () => { test('returns a default state', () => { - expect(getGaugeVisualization({ paletteService, theme }).initialize(() => 'l1')).toEqual({ + expect(getGaugeVisualization(deps).initialize(() => 'l1')).toEqual({ layerId: 'l1', layerType: LayerTypes.DATA, shape: 'horizontalBullet', @@ -47,12 +47,9 @@ describe('gauge', () => { }); test('returns persisted state', () => { - expect( - getGaugeVisualization({ paletteService, theme }).initialize( - () => 'test-layer', - exampleState() - ) - ).toEqual(exampleState()); + expect(getGaugeVisualization(deps).initialize(() => 'test-layer', exampleState())).toEqual( + exampleState() + ); }); }); @@ -89,10 +86,7 @@ describe('gauge', () => { }; expect( - getGaugeVisualization({ - paletteService, - theme, - }).getConfiguration({ state, frame, layerId: 'first' }) + getGaugeVisualization(deps).getConfiguration({ state, frame, layerId: 'first' }) ).toEqual({ groups: [ { @@ -175,10 +169,7 @@ describe('gauge', () => { minAccessor: 'min-accessor', }; expect( - getGaugeVisualization({ - paletteService, - theme, - }).getConfiguration({ state, frame, layerId: 'first' }) + getGaugeVisualization(deps).getConfiguration({ state, frame, layerId: 'first' }) ).toEqual({ groups: [ { @@ -267,10 +258,7 @@ describe('gauge', () => { frame.activeData = undefined; expect( - getGaugeVisualization({ - paletteService, - theme, - }).getConfiguration({ state, frame, layerId: 'first' }) + getGaugeVisualization(deps).getConfiguration({ state, frame, layerId: 'first' }) ).toEqual({ groups: [ { @@ -355,10 +343,7 @@ describe('gauge', () => { maxAccessor: 'max-accessor', }; expect( - getGaugeVisualization({ - paletteService, - theme, - }).setDimension({ + getGaugeVisualization(deps).setDimension({ prevState, layerId: 'first', columnId: 'new-min-accessor', @@ -383,10 +368,7 @@ describe('gauge', () => { }; test('removes metric correctly', () => { expect( - getGaugeVisualization({ - paletteService, - theme, - }).removeDimension({ + getGaugeVisualization(deps).removeDimension({ prevState, layerId: 'first', columnId: 'metric-accessor', @@ -399,10 +381,7 @@ describe('gauge', () => { }); test('removes min correctly', () => { expect( - getGaugeVisualization({ - paletteService, - theme, - }).removeDimension({ + getGaugeVisualization(deps).removeDimension({ prevState, layerId: 'first', columnId: 'min-accessor', @@ -419,12 +398,7 @@ describe('gauge', () => { }); describe('#getSupportedLayers', () => { it('should return a single layer type', () => { - expect( - getGaugeVisualization({ - paletteService, - theme, - }).getSupportedLayers() - ).toHaveLength(1); + expect(getGaugeVisualization(deps).getSupportedLayers()).toHaveLength(1); }); }); describe('#getLayerType', () => { @@ -434,10 +408,7 @@ describe('gauge', () => { minAccessor: 'min-accessor', goalAccessor: 'value-accessor', }; - const instance = getGaugeVisualization({ - paletteService, - theme, - }); + const instance = getGaugeVisualization(deps); expect(instance.getLayerType('test-layer', state)).toEqual(LayerTypes.DATA); expect(instance.getLayerType('foo', state)).toBeUndefined(); }); @@ -465,12 +436,7 @@ describe('gauge', () => { maxAccessor: 'max-accessor', labelMinor: 'Subtitle', }; - expect( - getGaugeVisualization({ - paletteService, - theme, - }).toExpression(state, datasourceLayers) - ).toEqual({ + expect(getGaugeVisualization(deps).toExpression(state, datasourceLayers)).toEqual({ type: 'expression', chain: [ { @@ -497,12 +463,7 @@ describe('gauge', () => { layerId: 'first', minAccessor: 'min-accessor', }; - expect( - getGaugeVisualization({ - paletteService, - theme, - }).toExpression(state, datasourceLayers) - ).toEqual(null); + expect(getGaugeVisualization(deps).toExpression(state, datasourceLayers)).toEqual(null); }); }); @@ -543,12 +504,8 @@ describe('gauge', () => { }, }; - expect( - getGaugeVisualization({ - paletteService, - theme, - }).getUserMessages!(localState, { frame }) - ).toMatchInlineSnapshot(` + expect(getGaugeVisualization(deps).getUserMessages!(localState, { frame })) + .toMatchInlineSnapshot(` Array [ Object { "displayLocations": Array [ @@ -587,12 +544,7 @@ describe('gauge', () => { }, }; - expect( - getGaugeVisualization({ - paletteService, - theme, - }).getUserMessages!(state, { frame }) - ).toHaveLength(0); + expect(getGaugeVisualization(deps).getUserMessages!(state, { frame })).toHaveLength(0); }); it('should warn when minimum value is greater than metric value', () => { frame.activeData = { @@ -610,12 +562,7 @@ describe('gauge', () => { }, }; - expect( - getGaugeVisualization({ - paletteService, - theme, - }).getUserMessages!(state, { frame }) - ).toHaveLength(1); + expect(getGaugeVisualization(deps).getUserMessages!(state, { frame })).toHaveLength(1); }); it('should warn when metric value is greater than maximum value', () => { @@ -633,12 +580,7 @@ describe('gauge', () => { }, }; - expect( - getGaugeVisualization({ - paletteService, - theme, - }).getUserMessages!(state, { frame }) - ).toHaveLength(1); + expect(getGaugeVisualization(deps).getUserMessages!(state, { frame })).toHaveLength(1); }); it('should warn when goal value is greater than maximum value', () => { frame.activeData = { @@ -656,12 +598,7 @@ describe('gauge', () => { }, }; - expect( - getGaugeVisualization({ - paletteService, - theme, - }).getUserMessages!(state, { frame }) - ).toHaveLength(1); + expect(getGaugeVisualization(deps).getUserMessages!(state, { frame })).toHaveLength(1); }); it('should warn when minimum value is greater than goal value', () => { frame.activeData = { @@ -679,12 +616,7 @@ describe('gauge', () => { }, }; - expect( - getGaugeVisualization({ - paletteService, - theme, - }).getUserMessages!(state, { frame }) - ).toHaveLength(1); + expect(getGaugeVisualization(deps).getUserMessages!(state, { frame })).toHaveLength(1); }); }); }); From 658a7748055c602700ad3ebc45536ef02580205b Mon Sep 17 00:00:00 2001 From: nickofthyme Date: Tue, 3 Dec 2024 14:02:26 -0600 Subject: [PATCH 26/41] chore: apply sequential colors for partition charts --- .../public/utils/layers/get_layers.ts | 2 +- .../public/services/palettes/palettes.tsx | 18 ++++++++++++++---- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_layers.ts b/src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_layers.ts index 2fac3b2b25758..be10a25771064 100644 --- a/src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_layers.ts +++ b/src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_layers.ts @@ -149,7 +149,7 @@ function getColorFromMappingFactory( } // the mosaic configures the main categories in the second column, instead of the first // as it happens in all the other partition types. - // Independentely from the bucket aggregation used, the categories will always be casted + // Independently from the bucket aggregation used, the categories will always be casted // as string to make it nicely working with a text input field, avoiding a field const categories = chartType === ChartTypes.MOSAIC && columns.length === 2 diff --git a/src/plugins/charts/public/services/palettes/palettes.tsx b/src/plugins/charts/public/services/palettes/palettes.tsx index c3b578a24d5e5..19d4581fc3c1a 100644 --- a/src/plugins/charts/public/services/palettes/palettes.tsx +++ b/src/plugins/charts/public/services/palettes/palettes.tsx @@ -40,16 +40,26 @@ function buildRoundRobinCategoricalWithMappedColors( const mappedColor = mappedColors.get(colorKey); outputColor = chartConfiguration.behindText ? behindTextColorMap[mappedColor] : mappedColor; } else { - outputColor = - chartConfiguration.behindText && behindTextColors - ? behindTextColors[series[0].rankAtDepth % behindTextColors.length] - : colors[series[0].rankAtDepth % colors.length]; + if (id === KbnPalette.Default) { + // no behind color for new default palette + outputColor = colors[series[0].rankAtDepth % 10]; + } else { + outputColor = + chartConfiguration.behindText && behindTextColors + ? behindTextColors[series[0].rankAtDepth % behindTextColors.length] + : colors[series[0].rankAtDepth % colors.length]; + } } if (!chartConfiguration.maxDepth || chartConfiguration.maxDepth === 1) { return outputColor; } + if (id === KbnPalette.Default) { + // divides palette into 3 - 10 color levels and assigns color round robin + const colorIndex = series[0].rankAtDepth % 10; + return colors[(series.length - 1) * 10 + colorIndex]; // max series count of 3 + } return lightenColor(outputColor, series.length, chartConfiguration.maxDepth); } return { From 0b959a490a615c0d507d33f0e525e60ffdaf3ee0 Mon Sep 17 00:00:00 2001 From: nickofthyme Date: Tue, 3 Dec 2024 16:44:42 -0600 Subject: [PATCH 27/41] fix: test failures --- .../flyout_service.test.tsx.snap | 30 ++- .../__snapshots__/modal_service.test.tsx.snap | 222 +++++++++++++++++- .../services/palettes/palettes.test.tsx | 3 +- .../public/services/palettes/palettes.tsx | 8 +- .../vega_visualization.test.tsx.snap | 4 +- 5 files changed, 248 insertions(+), 19 deletions(-) diff --git a/packages/core/overlays/core-overlays-browser-internal/src/flyout/__snapshots__/flyout_service.test.tsx.snap b/packages/core/overlays/core-overlays-browser-internal/src/flyout/__snapshots__/flyout_service.test.tsx.snap index a41da1f45af56..d6fb911043ee7 100644 --- a/packages/core/overlays/core-overlays-browser-internal/src/flyout/__snapshots__/flyout_service.test.tsx.snap +++ b/packages/core/overlays/core-overlays-browser-internal/src/flyout/__snapshots__/flyout_service.test.tsx.snap @@ -150,7 +150,20 @@ Array [ } theme={ Object { - "getTheme": [MockFunction], + "getTheme": [MockFunction] { + "calls": Array [ + Array [], + ], + "results": Array [ + Object { + "type": "return", + "value": Object { + "darkMode": false, + "name": "amsterdam", + }, + }, + ], + }, "theme$": Observable { "_subscribe": [Function], }, @@ -260,7 +273,20 @@ Array [ } theme={ Object { - "getTheme": [MockFunction], + "getTheme": [MockFunction] { + "calls": Array [ + Array [], + ], + "results": Array [ + Object { + "type": "return", + "value": Object { + "darkMode": false, + "name": "amsterdam", + }, + }, + ], + }, "theme$": Observable { "_subscribe": [Function], }, diff --git a/packages/core/overlays/core-overlays-browser-internal/src/modal/__snapshots__/modal_service.test.tsx.snap b/packages/core/overlays/core-overlays-browser-internal/src/modal/__snapshots__/modal_service.test.tsx.snap index 5b1bb22336493..956c9e5979781 100644 --- a/packages/core/overlays/core-overlays-browser-internal/src/modal/__snapshots__/modal_service.test.tsx.snap +++ b/packages/core/overlays/core-overlays-browser-internal/src/modal/__snapshots__/modal_service.test.tsx.snap @@ -102,7 +102,20 @@ Array [ } theme={ Object { - "getTheme": [MockFunction], + "getTheme": [MockFunction] { + "calls": Array [ + Array [], + ], + "results": Array [ + Object { + "type": "return", + "value": Object { + "darkMode": false, + "name": "amsterdam", + }, + }, + ], + }, "theme$": Observable { "_subscribe": [Function], }, @@ -370,7 +383,28 @@ Array [ } theme={ Object { - "getTheme": [MockFunction], + "getTheme": [MockFunction] { + "calls": Array [ + Array [], + Array [], + ], + "results": Array [ + Object { + "type": "return", + "value": Object { + "darkMode": false, + "name": "amsterdam", + }, + }, + Object { + "type": "return", + "value": Object { + "darkMode": false, + "name": "amsterdam", + }, + }, + ], + }, "theme$": Observable { "_subscribe": [Function], }, @@ -695,7 +729,36 @@ Array [ } theme={ Object { - "getTheme": [MockFunction], + "getTheme": [MockFunction] { + "calls": Array [ + Array [], + Array [], + Array [], + ], + "results": Array [ + Object { + "type": "return", + "value": Object { + "darkMode": false, + "name": "amsterdam", + }, + }, + Object { + "type": "return", + "value": Object { + "darkMode": false, + "name": "amsterdam", + }, + }, + Object { + "type": "return", + "value": Object { + "darkMode": false, + "name": "amsterdam", + }, + }, + ], + }, "theme$": Observable { "_subscribe": [Function], }, @@ -939,7 +1002,36 @@ Array [ } theme={ Object { - "getTheme": [MockFunction], + "getTheme": [MockFunction] { + "calls": Array [ + Array [], + Array [], + Array [], + ], + "results": Array [ + Object { + "type": "return", + "value": Object { + "darkMode": false, + "name": "amsterdam", + }, + }, + Object { + "type": "return", + "value": Object { + "darkMode": false, + "name": "amsterdam", + }, + }, + Object { + "type": "return", + "value": Object { + "darkMode": false, + "name": "amsterdam", + }, + }, + ], + }, "theme$": Observable { "_subscribe": [Function], }, @@ -1188,7 +1280,36 @@ Array [ } theme={ Object { - "getTheme": [MockFunction], + "getTheme": [MockFunction] { + "calls": Array [ + Array [], + Array [], + Array [], + ], + "results": Array [ + Object { + "type": "return", + "value": Object { + "darkMode": false, + "name": "amsterdam", + }, + }, + Object { + "type": "return", + "value": Object { + "darkMode": false, + "name": "amsterdam", + }, + }, + Object { + "type": "return", + "value": Object { + "darkMode": false, + "name": "amsterdam", + }, + }, + ], + }, "theme$": Observable { "_subscribe": [Function], }, @@ -1432,7 +1553,36 @@ Array [ } theme={ Object { - "getTheme": [MockFunction], + "getTheme": [MockFunction] { + "calls": Array [ + Array [], + Array [], + Array [], + ], + "results": Array [ + Object { + "type": "return", + "value": Object { + "darkMode": false, + "name": "amsterdam", + }, + }, + Object { + "type": "return", + "value": Object { + "darkMode": false, + "name": "amsterdam", + }, + }, + Object { + "type": "return", + "value": Object { + "darkMode": false, + "name": "amsterdam", + }, + }, + ], + }, "theme$": Observable { "_subscribe": [Function], }, @@ -1626,7 +1776,20 @@ Array [ } theme={ Object { - "getTheme": [MockFunction], + "getTheme": [MockFunction] { + "calls": Array [ + Array [], + ], + "results": Array [ + Object { + "type": "return", + "value": Object { + "darkMode": false, + "name": "amsterdam", + }, + }, + ], + }, "theme$": Observable { "_subscribe": [Function], }, @@ -1736,7 +1899,20 @@ Array [ } theme={ Object { - "getTheme": [MockFunction], + "getTheme": [MockFunction] { + "calls": Array [ + Array [], + ], + "results": Array [ + Object { + "type": "return", + "value": Object { + "darkMode": false, + "name": "amsterdam", + }, + }, + ], + }, "theme$": Observable { "_subscribe": [Function], }, @@ -1851,7 +2027,20 @@ Array [ } theme={ Object { - "getTheme": [MockFunction], + "getTheme": [MockFunction] { + "calls": Array [ + Array [], + ], + "results": Array [ + Object { + "type": "return", + "value": Object { + "darkMode": false, + "name": "amsterdam", + }, + }, + ], + }, "theme$": Observable { "_subscribe": [Function], }, @@ -1961,7 +2150,20 @@ Array [ } theme={ Object { - "getTheme": [MockFunction], + "getTheme": [MockFunction] { + "calls": Array [ + Array [], + ], + "results": Array [ + Object { + "type": "return", + "value": Object { + "darkMode": false, + "name": "amsterdam", + }, + }, + ], + }, "theme$": Observable { "_subscribe": [Function], }, diff --git a/src/plugins/charts/public/services/palettes/palettes.test.tsx b/src/plugins/charts/public/services/palettes/palettes.test.tsx index d091b5429755b..a962da6776c4e 100644 --- a/src/plugins/charts/public/services/palettes/palettes.test.tsx +++ b/src/plugins/charts/public/services/palettes/palettes.test.tsx @@ -7,12 +7,11 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -import { createCoreSetupMock } from '@kbn/core-lifecycle-browser-mocks/src/core_setup.mock'; import { buildPalettes } from './palettes'; import { euiPaletteColorBlind, euiPaletteColorBlindBehindText } from '@elastic/eui'; describe('palettes', () => { - const palettes = buildPalettes(createCoreSetupMock().theme.getTheme()); + const palettes = buildPalettes({ name: 'amsterdam', darkMode: false }); describe('default palette', () => { describe('syncColors: false', () => { diff --git a/src/plugins/charts/public/services/palettes/palettes.tsx b/src/plugins/charts/public/services/palettes/palettes.tsx index 19d4581fc3c1a..4f5ba6f8cbdc1 100644 --- a/src/plugins/charts/public/services/palettes/palettes.tsx +++ b/src/plugins/charts/public/services/palettes/palettes.tsx @@ -21,7 +21,8 @@ import { workoutColorForValue } from './helpers'; function buildRoundRobinCategoricalWithMappedColors( id: string, colors: string[], - behindTextColors?: string[] + behindTextColors?: string[], + isNewTheme?: boolean ): Omit { const behindTextColorMap: Record = Object.fromEntries( zip(colors, behindTextColors) @@ -40,7 +41,7 @@ function buildRoundRobinCategoricalWithMappedColors( const mappedColor = mappedColors.get(colorKey); outputColor = chartConfiguration.behindText ? behindTextColorMap[mappedColor] : mappedColor; } else { - if (id === KbnPalette.Default) { + if (isNewTheme && id === KbnPalette.Default) { // no behind color for new default palette outputColor = colors[series[0].rankAtDepth % 10]; } else { @@ -228,7 +229,8 @@ export const buildPalettes = (theme: CoreTheme): Record
"`; -exports[`VegaVisualizations VegaVisualization - basics should show vegalite graph and update on resize (may fail in dev env) 1`] = `"
  • \\"width\\" and \\"height\\" params are ignored because \\"autosize\\" is enabled. Set \\"autosize\\": \\"none\\" to disable
"`; +exports[`VegaVisualizations VegaVisualization - basics should show vegalite graph and update on resize (may fail in dev env) 1`] = `"
  • \\"width\\" and \\"height\\" params are ignored because \\"autosize\\" is enabled. Set \\"autosize\\": \\"none\\" to disable
"`; -exports[`VegaVisualizations VegaVisualization - basics should show vegalite graph and update on resize (may fail in dev env) 2`] = `"
  • \\"width\\" and \\"height\\" params are ignored because \\"autosize\\" is enabled. Set \\"autosize\\": \\"none\\" to disable
"`; +exports[`VegaVisualizations VegaVisualization - basics should show vegalite graph and update on resize (may fail in dev env) 2`] = `"
  • \\"width\\" and \\"height\\" params are ignored because \\"autosize\\" is enabled. Set \\"autosize\\": \\"none\\" to disable
"`; From 62c3b1a6556cdf96a110a8d8a5e8db7fa684f280 Mon Sep 17 00:00:00 2001 From: nickofthyme Date: Wed, 4 Dec 2024 15:21:31 -0600 Subject: [PATCH 28/41] fix: vega page bundle size --- packages/kbn-optimizer/limits.yml | 5 ++--- src/plugins/vis_types/vega/public/plugin.ts | 5 +++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/kbn-optimizer/limits.yml b/packages/kbn-optimizer/limits.yml index a799fa44b248d..47106357a2aea 100644 --- a/packages/kbn-optimizer/limits.yml +++ b/packages/kbn-optimizer/limits.yml @@ -2,10 +2,9 @@ pageLoadAssetSize: actions: 20000 advancedSettings: 27596 aiAssistantManagementSelection: 19146 - aiops: 17680 + aiops: 32733 alerting: 106936 apm: 64385 - assetInventory: 18478 banners: 17946 bfetch: 22837 canvas: 29355 @@ -193,7 +192,7 @@ pageLoadAssetSize: visTypeTagcloud: 37575 visTypeTimelion: 68883 visTypeTimeseries: 55203 - visTypeVega: 571074 + visTypeVega: 153573 visTypeVislib: 242838 visTypeXy: 46868 visualizations: 90000 diff --git a/src/plugins/vis_types/vega/public/plugin.ts b/src/plugins/vis_types/vega/public/plugin.ts index c386de32dbdec..d36a547a9d6ed 100644 --- a/src/plugins/vis_types/vega/public/plugin.ts +++ b/src/plugins/vis_types/vega/public/plugin.ts @@ -17,7 +17,6 @@ import { Setup as InspectorSetup } from '@kbn/inspector-plugin/public'; import type { MapsEmsPluginPublicStart } from '@kbn/maps-ems-plugin/public'; import { UsageCollectionStart } from '@kbn/usage-collection-plugin/public'; import { KbnPalette, getKbnPalettes } from '@kbn/palettes'; -import { scheme } from 'vega'; import { setNotifications, setData, @@ -102,7 +101,9 @@ export class VegaPlugin implements Plugin { ) { core.theme.theme$ .subscribe({ - next(theme) { + async next(theme) { + const { scheme } = await import('vega'); + const palettes = getKbnPalettes(theme); scheme('elastic', palettes.get(KbnPalette.Default).colors()); }, From d5f234a07e416407d9cf9577b0f031b929d6e9c7 Mon Sep 17 00:00:00 2001 From: nickofthyme Date: Wed, 4 Dec 2024 17:49:32 -0600 Subject: [PATCH 29/41] chore: apply lightening for partition color logic - removed sequential color logic - add util to reduce opacity as opaque color - apply new helper function to palettes and color mapping --- .../utils/colors/color_mapping_accessors.ts | 6 +-- .../public/utils/layers/get_layers.ts | 8 ++-- src/plugins/charts/public/index.ts | 3 +- .../palettes/decrease_opacity.test.ts | 37 +++++++++++++++++++ .../services/palettes/decrease_opacity.ts | 30 +++++++++++++++ .../public/services/palettes/lighten_color.ts | 1 + .../public/services/palettes/palettes.tsx | 32 +++++----------- 7 files changed, 87 insertions(+), 30 deletions(-) create mode 100644 src/plugins/charts/public/services/palettes/decrease_opacity.test.ts create mode 100644 src/plugins/charts/public/services/palettes/decrease_opacity.ts diff --git a/src/plugins/chart_expressions/expression_partition_vis/public/utils/colors/color_mapping_accessors.ts b/src/plugins/chart_expressions/expression_partition_vis/public/utils/colors/color_mapping_accessors.ts index dcfcccaa3b53e..8368e98b83715 100644 --- a/src/plugins/chart_expressions/expression_partition_vis/public/utils/colors/color_mapping_accessors.ts +++ b/src/plugins/chart_expressions/expression_partition_vis/public/utils/colors/color_mapping_accessors.ts @@ -8,7 +8,7 @@ */ import { NodeColorAccessor, PATH_KEY } from '@elastic/charts'; -import { lightenColor } from '@kbn/charts-plugin/public'; +import { decreaseOpacity } from '@kbn/charts-plugin/public'; import { MultiFieldKey } from '@kbn/data-plugin/common'; import { getColorFactory } from '@kbn/coloring'; import { isMultiFieldKey } from '@kbn/data-plugin/common'; @@ -34,8 +34,8 @@ const getPieFillColor = // first two are: small multiple and pie whole center. const category = getCategoryKeys(path[2].value); const color = getColorFn(category); - // increase the lightness of the color on each layer. - return lightenColor(color, layerIndex + 1, numOfLayers); + // progressively decrease opacity of base color on each layer. + return decreaseOpacity(color, layerIndex + 1, numOfLayers); }; /** diff --git a/src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_layers.ts b/src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_layers.ts index be10a25771064..4346dd6ae4928 100644 --- a/src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_layers.ts +++ b/src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_layers.ts @@ -76,8 +76,8 @@ export const getLayers = ( columns, rows, palettes, - isDarkMode, - visParams + visParams, + isDarkMode ); return columns.map((col, layerIndex) => { @@ -129,8 +129,8 @@ function getColorFromMappingFactory( columns: Array>, rows: DatatableRow[], palettes: KbnPalettes, - isDarkMode: boolean, - visParams: PartitionVisParams + visParams: PartitionVisParams, + isDarkMode: boolean ): undefined | ((category: string | string[]) => string) { const { colorMapping, dimensions } = visParams; diff --git a/src/plugins/charts/public/index.ts b/src/plugins/charts/public/index.ts index 6b70018ac5901..711f38b7d92f7 100644 --- a/src/plugins/charts/public/index.ts +++ b/src/plugins/charts/public/index.ts @@ -22,7 +22,8 @@ export const plugin = () => new ChartsPlugin(); export type { ChartsPluginSetup, ChartsPluginStart } from './plugin'; export * from './static'; -export { lightenColor } from './services/palettes/lighten_color'; +export * from './services/palettes/lighten_color'; +export * from './services/palettes/decrease_opacity'; export { useActiveCursor } from './services/active_cursor'; export interface ClickTriggerEvent { diff --git a/src/plugins/charts/public/services/palettes/decrease_opacity.test.ts b/src/plugins/charts/public/services/palettes/decrease_opacity.test.ts new file mode 100644 index 0000000000000..845021e768755 --- /dev/null +++ b/src/plugins/charts/public/services/palettes/decrease_opacity.test.ts @@ -0,0 +1,37 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import chroma from 'chroma-js'; +import { decreaseOpacity } from './decrease_opacity'; + +describe('decrease_opacity', () => { + it('should keep existing color if there is a single color step', () => { + expect(decreaseOpacity('#FF0000', 1, 1)).toEqual('#FF0000'); + }); + + it('should keep existing color for the first step', () => { + expect(decreaseOpacity('#FF0000', 1, 10)).toEqual('#FF0000'); + }); + + it('should decrease color opacity', () => { + const baseColor = '#FF0000'; + + const color1 = chroma(decreaseOpacity(baseColor, 2, 4)); + const color2 = chroma(decreaseOpacity(baseColor, 3, 4)); + + expect(chroma(baseColor).luminance()).toBeLessThan(color1.luminance()); + expect(color1.luminance()).toBeLessThan(color2.luminance()); + }); + + it('should not exceed top luminance', () => { + const result = decreaseOpacity('#000', 12, 10); + + expect(chroma(result).luminance()).toBeLessThan(0.8); + }); +}); diff --git a/src/plugins/charts/public/services/palettes/decrease_opacity.ts b/src/plugins/charts/public/services/palettes/decrease_opacity.ts new file mode 100644 index 0000000000000..bd49ba66b1707 --- /dev/null +++ b/src/plugins/charts/public/services/palettes/decrease_opacity.ts @@ -0,0 +1,30 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import chroma from 'chroma-js'; +import { euiThemeVars } from '@kbn/ui-theme'; + +const MIN_OPACITY = 0.2; + +/** + * Reduces color opacity, by mixing color with background color. + * + * This is used when the resulting color needs to be opaque (i.e. alpha of 1). + */ +export function decreaseOpacity(baseColor: string, step: number, totalSteps: number) { + if (totalSteps === 1) { + return baseColor; + } + + const backgroundColor = euiThemeVars.euiColorEmptyShade; + const ratio = Math.min(0.2 * (step - 1), 1 - MIN_OPACITY); + const color = chroma(baseColor).mix(backgroundColor, ratio, 'lch'); + + return color.hex().toUpperCase(); +} diff --git a/src/plugins/charts/public/services/palettes/lighten_color.ts b/src/plugins/charts/public/services/palettes/lighten_color.ts index 80298f5c8b531..b7c1908375ebd 100644 --- a/src/plugins/charts/public/services/palettes/lighten_color.ts +++ b/src/plugins/charts/public/services/palettes/lighten_color.ts @@ -23,5 +23,6 @@ export function lightenColor(baseColor: string, step: number, totalSteps: number const currentLevelTargetLightness = outputColorLightness + lightnessSpace * ((step - 1) / (totalSteps - 1)); const lightenedColor = hslColor.lightness(currentLevelTargetLightness); + return lightenedColor.hex(); } diff --git a/src/plugins/charts/public/services/palettes/palettes.tsx b/src/plugins/charts/public/services/palettes/palettes.tsx index 4f5ba6f8cbdc1..4858bf0547d46 100644 --- a/src/plugins/charts/public/services/palettes/palettes.tsx +++ b/src/plugins/charts/public/services/palettes/palettes.tsx @@ -14,15 +14,14 @@ import type { ChartColorConfiguration, PaletteDefinition, SeriesLayer } from '@k import { flatten, zip } from 'lodash'; import { CoreTheme } from '@kbn/core/public'; import { createColorPalette as createLegacyColorPalette } from '../..'; -import { lightenColor } from './lighten_color'; import { MappedColors } from '../mapped_colors'; import { workoutColorForValue } from './helpers'; +import { decreaseOpacity } from './decrease_opacity'; function buildRoundRobinCategoricalWithMappedColors( id: string, colors: string[], - behindTextColors?: string[], - isNewTheme?: boolean + behindTextColors?: string[] ): Omit { const behindTextColorMap: Record = Object.fromEntries( zip(colors, behindTextColors) @@ -41,27 +40,17 @@ function buildRoundRobinCategoricalWithMappedColors( const mappedColor = mappedColors.get(colorKey); outputColor = chartConfiguration.behindText ? behindTextColorMap[mappedColor] : mappedColor; } else { - if (isNewTheme && id === KbnPalette.Default) { - // no behind color for new default palette - outputColor = colors[series[0].rankAtDepth % 10]; - } else { - outputColor = - chartConfiguration.behindText && behindTextColors - ? behindTextColors[series[0].rankAtDepth % behindTextColors.length] - : colors[series[0].rankAtDepth % colors.length]; - } + outputColor = + chartConfiguration.behindText && behindTextColors + ? behindTextColors[series[0].rankAtDepth % behindTextColors.length] + : colors[series[0].rankAtDepth % colors.length]; } if (!chartConfiguration.maxDepth || chartConfiguration.maxDepth === 1) { return outputColor; } - if (id === KbnPalette.Default) { - // divides palette into 3 - 10 color levels and assigns color round robin - const colorIndex = series[0].rankAtDepth % 10; - return colors[(series.length - 1) * 10 + colorIndex]; // max series count of 3 - } - return lightenColor(outputColor, series.length, chartConfiguration.maxDepth); + return decreaseOpacity(outputColor, series.length, chartConfiguration.maxDepth); } return { id, @@ -96,7 +85,7 @@ function buildGradient(id: string, palette: IKbnPalette): PaletteDefinition { return outputColor; } - return lightenColor(outputColor, series.length, chartConfiguration.maxDepth); + return decreaseOpacity(outputColor, series.length, chartConfiguration.maxDepth); } return { id, @@ -153,7 +142,7 @@ function buildCustomPalette(): PaletteDefinition { return outputColor; } - return lightenColor(outputColor, series.length, chartConfiguration.maxDepth); + return decreaseOpacity(outputColor, series.length, chartConfiguration.maxDepth); }, internal: true, title: i18n.translate('charts.palettes.customLabel', { defaultMessage: 'Custom' }), @@ -229,8 +218,7 @@ export const buildPalettes = (theme: CoreTheme): Record Date: Wed, 4 Dec 2024 19:18:33 -0600 Subject: [PATCH 30/41] chore: remove hardcoded theming --- .../core/ui-settings/core-ui-settings-common/src/theme.ts | 3 +-- .../core-ui-settings-server-internal/src/settings/theme.ts | 7 +++---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/packages/core/ui-settings/core-ui-settings-common/src/theme.ts b/packages/core/ui-settings/core-ui-settings-common/src/theme.ts index 705695de9d9d9..73b465d5b192f 100644 --- a/packages/core/ui-settings/core-ui-settings-common/src/theme.ts +++ b/packages/core/ui-settings/core-ui-settings-common/src/theme.ts @@ -35,8 +35,7 @@ export type ThemeTags = readonly ThemeTag[]; * An array of theme tags available in Kibana by default when not customized * using KBN_OPTIMIZER_THEMES environment variable. */ -export const DEFAULT_THEME_TAGS: ThemeTags = SUPPORTED_THEME_TAGS; // TODO Nick put this back -// export const DEFAULT_THEME_TAGS: ThemeTags = ThemeAmsterdamTags; +export const DEFAULT_THEME_TAGS: ThemeTags = ThemeAmsterdamTags; export const FALLBACK_THEME_TAG: ThemeTag = 'v8light'; diff --git a/packages/core/ui-settings/core-ui-settings-server-internal/src/settings/theme.ts b/packages/core/ui-settings/core-ui-settings-server-internal/src/settings/theme.ts index 59eb6ebad1746..36324f951952e 100644 --- a/packages/core/ui-settings/core-ui-settings-server-internal/src/settings/theme.ts +++ b/packages/core/ui-settings/core-ui-settings-server-internal/src/settings/theme.ts @@ -104,10 +104,9 @@ export const getThemeSettings = ( }), }, value: 'amsterdam', - // TODO Nick put this back - // readonly: Object.hasOwn(options, 'isThemeSwitcherEnabled') - // ? !options.isThemeSwitcherEnabled - // : true, + readonly: Object.hasOwn(options, 'isThemeSwitcherEnabled') + ? !options.isThemeSwitcherEnabled + : true, requiresPageReload: true, schema: schema.oneOf([ schema.literal('amsterdam'), From 8598e07a82556bb9ff6e6ef36403408067d48ee3 Mon Sep 17 00:00:00 2001 From: nickofthyme Date: Thu, 21 Nov 2024 11:11:01 -0600 Subject: [PATCH 31/41] chore: hardcode theme toggles [to be removed] --- .../core/ui-settings/core-ui-settings-common/src/theme.ts | 3 ++- .../core-ui-settings-server-internal/src/settings/theme.ts | 7 ++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/core/ui-settings/core-ui-settings-common/src/theme.ts b/packages/core/ui-settings/core-ui-settings-common/src/theme.ts index 73b465d5b192f..705695de9d9d9 100644 --- a/packages/core/ui-settings/core-ui-settings-common/src/theme.ts +++ b/packages/core/ui-settings/core-ui-settings-common/src/theme.ts @@ -35,7 +35,8 @@ export type ThemeTags = readonly ThemeTag[]; * An array of theme tags available in Kibana by default when not customized * using KBN_OPTIMIZER_THEMES environment variable. */ -export const DEFAULT_THEME_TAGS: ThemeTags = ThemeAmsterdamTags; +export const DEFAULT_THEME_TAGS: ThemeTags = SUPPORTED_THEME_TAGS; // TODO Nick put this back +// export const DEFAULT_THEME_TAGS: ThemeTags = ThemeAmsterdamTags; export const FALLBACK_THEME_TAG: ThemeTag = 'v8light'; diff --git a/packages/core/ui-settings/core-ui-settings-server-internal/src/settings/theme.ts b/packages/core/ui-settings/core-ui-settings-server-internal/src/settings/theme.ts index 36324f951952e..59eb6ebad1746 100644 --- a/packages/core/ui-settings/core-ui-settings-server-internal/src/settings/theme.ts +++ b/packages/core/ui-settings/core-ui-settings-server-internal/src/settings/theme.ts @@ -104,9 +104,10 @@ export const getThemeSettings = ( }), }, value: 'amsterdam', - readonly: Object.hasOwn(options, 'isThemeSwitcherEnabled') - ? !options.isThemeSwitcherEnabled - : true, + // TODO Nick put this back + // readonly: Object.hasOwn(options, 'isThemeSwitcherEnabled') + // ? !options.isThemeSwitcherEnabled + // : true, requiresPageReload: true, schema: schema.oneOf([ schema.literal('amsterdam'), From 8f01fae7ceb966341411ba21962c3e55b7dea547 Mon Sep 17 00:00:00 2001 From: nickofthyme Date: Wed, 4 Dec 2024 20:55:03 -0600 Subject: [PATCH 32/41] Revert "chore: hardcode theme toggles [to be removed]" This reverts commit 8598e07a82556bb9ff6e6ef36403408067d48ee3. --- .../core/ui-settings/core-ui-settings-common/src/theme.ts | 3 +-- .../core-ui-settings-server-internal/src/settings/theme.ts | 7 +++---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/packages/core/ui-settings/core-ui-settings-common/src/theme.ts b/packages/core/ui-settings/core-ui-settings-common/src/theme.ts index 705695de9d9d9..73b465d5b192f 100644 --- a/packages/core/ui-settings/core-ui-settings-common/src/theme.ts +++ b/packages/core/ui-settings/core-ui-settings-common/src/theme.ts @@ -35,8 +35,7 @@ export type ThemeTags = readonly ThemeTag[]; * An array of theme tags available in Kibana by default when not customized * using KBN_OPTIMIZER_THEMES environment variable. */ -export const DEFAULT_THEME_TAGS: ThemeTags = SUPPORTED_THEME_TAGS; // TODO Nick put this back -// export const DEFAULT_THEME_TAGS: ThemeTags = ThemeAmsterdamTags; +export const DEFAULT_THEME_TAGS: ThemeTags = ThemeAmsterdamTags; export const FALLBACK_THEME_TAG: ThemeTag = 'v8light'; diff --git a/packages/core/ui-settings/core-ui-settings-server-internal/src/settings/theme.ts b/packages/core/ui-settings/core-ui-settings-server-internal/src/settings/theme.ts index 59eb6ebad1746..36324f951952e 100644 --- a/packages/core/ui-settings/core-ui-settings-server-internal/src/settings/theme.ts +++ b/packages/core/ui-settings/core-ui-settings-server-internal/src/settings/theme.ts @@ -104,10 +104,9 @@ export const getThemeSettings = ( }), }, value: 'amsterdam', - // TODO Nick put this back - // readonly: Object.hasOwn(options, 'isThemeSwitcherEnabled') - // ? !options.isThemeSwitcherEnabled - // : true, + readonly: Object.hasOwn(options, 'isThemeSwitcherEnabled') + ? !options.isThemeSwitcherEnabled + : true, requiresPageReload: true, schema: schema.oneOf([ schema.literal('amsterdam'), From 7778db2d94a47dacd282efac84a10467446ae45f Mon Sep 17 00:00:00 2001 From: nickofthyme Date: Wed, 4 Dec 2024 21:22:31 -0600 Subject: [PATCH 33/41] revert: bundle limit changes --- packages/kbn-optimizer/limits.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/kbn-optimizer/limits.yml b/packages/kbn-optimizer/limits.yml index 47106357a2aea..b1b4cb38d3f19 100644 --- a/packages/kbn-optimizer/limits.yml +++ b/packages/kbn-optimizer/limits.yml @@ -2,9 +2,10 @@ pageLoadAssetSize: actions: 20000 advancedSettings: 27596 aiAssistantManagementSelection: 19146 - aiops: 32733 + aiops: 17680 alerting: 106936 apm: 64385 + assetInventory: 18478 banners: 17946 bfetch: 22837 canvas: 29355 @@ -17,7 +18,7 @@ pageLoadAssetSize: cloudFullStory: 18493 cloudLinks: 55984 cloudSecurityPosture: 19109 - console: 61528 + console: 46091 contentManagement: 16254 controls: 60000 core: 564663 @@ -64,7 +65,7 @@ pageLoadAssetSize: expressionTagcloud: 27505 expressionXY: 45000 features: 21723 - fieldFormats: 81291 + fieldFormats: 65209 fieldsMetadata: 21885 files: 22673 filesManagement: 18683 From dd190f11bb441debafa7221796cd9ccf88fe2e6b Mon Sep 17 00:00:00 2001 From: nickofthyme Date: Thu, 5 Dec 2024 11:30:22 -0600 Subject: [PATCH 34/41] test: fix jest async errors --- .../actions/open_modal.test.tsx | 40 +++++++++++-------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/x-pack/plugins/cases/public/components/visualizations/actions/open_modal.test.tsx b/x-pack/plugins/cases/public/components/visualizations/actions/open_modal.test.tsx index e8fc0b6f16951..d701635cbbbec 100644 --- a/x-pack/plugins/cases/public/components/visualizations/actions/open_modal.test.tsx +++ b/x-pack/plugins/cases/public/components/visualizations/actions/open_modal.test.tsx @@ -113,7 +113,7 @@ describe('openModal', () => { }); }); - it('should have correct onClose handler - when close modal clicked', () => { + it('should have correct onClose handler - when close modal clicked', async () => { openModal( getMockLensApi(), 'myAppId', @@ -121,12 +121,14 @@ describe('openModal', () => { getMockServices() ); - const onClose = mockUseCasesAddToExistingCaseModal.mock.calls[0][0].onClose; - onClose(); - expect(unmountComponentAtNode as jest.Mock).toHaveBeenCalled(); + await waitFor(() => { + const onClose = mockUseCasesAddToExistingCaseModal.mock.calls[0][0].onClose; + onClose(); + expect(unmountComponentAtNode as jest.Mock).toHaveBeenCalled(); + }); }); - it('should have correct onClose handler - when case selected', () => { + it('should have correct onClose handler - when case selected', async () => { openModal( getMockLensApi(), 'myAppId', @@ -134,12 +136,14 @@ describe('openModal', () => { getMockServices() ); - const onClose = mockUseCasesAddToExistingCaseModal.mock.calls[0][0].onClose; - onClose({ id: 'case-id', title: 'case-title' }); - expect(unmountComponentAtNode as jest.Mock).toHaveBeenCalled(); + await waitFor(() => { + const onClose = mockUseCasesAddToExistingCaseModal.mock.calls[0][0].onClose; + onClose({ id: 'case-id', title: 'case-title' }); + expect(unmountComponentAtNode as jest.Mock).toHaveBeenCalled(); + }); }); - it('should have correct onClose handler - when case created', () => { + it('should have correct onClose handler - when case created', async () => { openModal( getMockLensApi(), 'myAppId', @@ -147,12 +151,14 @@ describe('openModal', () => { getMockServices() ); - const onClose = mockUseCasesAddToExistingCaseModal.mock.calls[0][0].onClose; - onClose(null, true); - expect(unmountComponentAtNode as jest.Mock).not.toHaveBeenCalled(); + await waitFor(() => { + const onClose = mockUseCasesAddToExistingCaseModal.mock.calls[0][0].onClose; + onClose(null, true); + expect(unmountComponentAtNode as jest.Mock).not.toHaveBeenCalled(); + }); }); - it('should have correct onSuccess handler', () => { + it('should have correct onSuccess handler', async () => { openModal( getMockLensApi(), 'myAppId', @@ -160,9 +166,11 @@ describe('openModal', () => { getMockServices() ); - const onSuccess = mockUseCasesAddToExistingCaseModal.mock.calls[0][0].onSuccess; - onSuccess(); - expect(unmountComponentAtNode as jest.Mock).toHaveBeenCalled(); + await waitFor(() => { + const onSuccess = mockUseCasesAddToExistingCaseModal.mock.calls[0][0].onSuccess; + onSuccess(); + expect(unmountComponentAtNode as jest.Mock).toHaveBeenCalled(); + }); }); it('should open modal with an attachment with the time range in absolute values', async () => { From 016f1615074a66354d91174004f5b9ea31ef4a56 Mon Sep 17 00:00:00 2001 From: nickofthyme Date: Tue, 10 Dec 2024 16:56:55 -0600 Subject: [PATCH 35/41] chore: address simple pr comments --- .../color/color_handling.test.ts | 14 ++++---- .../classes/categorical_palette.ts | 4 +-- .../kbn-palettes/classes/color_fn_palette.ts | 2 +- .../kbn-palettes/classes/gradient_palette.ts | 33 ------------------- packages/kbn-palettes/classes/types.ts | 2 ++ packages/kbn-palettes/constants.ts | 15 ++------- .../palettes/categorical/neutral.ts | 33 ++++++++++++------- packages/kbn-palettes/types.ts | 10 ------ .../coloring/color_mapping_by_terms.tsx | 10 ++++-- .../shared_components/coloring/utils.ts | 2 +- .../datatable/visualization.test.tsx | 10 +++--- .../datatable/visualization.tsx | 6 ++-- .../partition/dimension_editor.tsx | 8 +++-- .../tagcloud/tags_dimension_editor.tsx | 8 +++-- 14 files changed, 66 insertions(+), 91 deletions(-) delete mode 100644 packages/kbn-palettes/classes/gradient_palette.ts delete mode 100644 packages/kbn-palettes/types.ts diff --git a/packages/kbn-coloring/src/shared_components/color_mapping/color/color_handling.test.ts b/packages/kbn-coloring/src/shared_components/color_mapping/color/color_handling.test.ts index ce01e412172fa..c97100781e005 100644 --- a/packages/kbn-coloring/src/shared_components/color_mapping/color/color_handling.test.ts +++ b/packages/kbn-coloring/src/shared_components/color_mapping/color/color_handling.test.ts @@ -340,9 +340,9 @@ describe('Color mapping - color generation', () => { categories: ['cat1', 'cat2', 'cat3'], } ); - expect(toHex(colorFactory('cat1'))).toBe(toHex(elasticPaletteColors[0])); // EUI green - expect(toHex(colorFactory('cat2'))).toBe('#a4908f'); // red gray green - expect(toHex(colorFactory('cat3'))).toBe(toHex(elasticPaletteColors[2])); // EUI pink + expect(toHex(colorFactory('cat1'))).toBe(toHex(elasticPaletteColors[0])); + expect(toHex(colorFactory('cat2'))).toBe('#a4908f'); + expect(toHex(colorFactory('cat3'))).toBe(toHex(elasticPaletteColors[2])); }); it('returns divergent gradient [asc, darkMode]', () => { @@ -376,10 +376,10 @@ describe('Color mapping - color generation', () => { categories: ['cat1', 'cat2', 'cat3'], } ); - expect(toHex(colorFactory('cat1'))).toBe(toHex(elasticPaletteColors[2])); // EUI pink - expect(toHex(colorFactory('cat2'))).toBe(neutralPaletteColors[0]); // NEUTRAL LIGHT GRAY - expect(toHex(colorFactory('cat3'))).toBe(toHex(elasticPaletteColors[0])); // EUI green - // if the category is not available in the `categories` list then a default netural is used + expect(toHex(colorFactory('cat1'))).toBe(toHex(elasticPaletteColors[2])); + expect(toHex(colorFactory('cat2'))).toBe(neutralPaletteColors[0]); + expect(toHex(colorFactory('cat3'))).toBe(toHex(elasticPaletteColors[0])); + // if the category is not available in the `categories` list then a default neutral is used // this is an edge case and ideally never happen expect(colorFactory('not_available')).toBe(neutralPaletteColors[DEFAULT_NEUTRAL_PALETTE_INDEX]); }); diff --git a/packages/kbn-palettes/classes/categorical_palette.ts b/packages/kbn-palettes/classes/categorical_palette.ts index 6ffba90a64f3a..44b05d86b6271 100644 --- a/packages/kbn-palettes/classes/categorical_palette.ts +++ b/packages/kbn-palettes/classes/categorical_palette.ts @@ -26,7 +26,7 @@ export class KbnCategoricalPalette extends KbnBasePalette implements IKbnPalette this.#colors = colors; } - public colors = (n?: number) => { - return this.#colors.slice(0, n); + public colors = (n: number = 1) => { + return this.#colors.slice(0, Math.max(1, n)); }; } diff --git a/packages/kbn-palettes/classes/color_fn_palette.ts b/packages/kbn-palettes/classes/color_fn_palette.ts index 707f82b8aae25..7e0580ee2ac40 100644 --- a/packages/kbn-palettes/classes/color_fn_palette.ts +++ b/packages/kbn-palettes/classes/color_fn_palette.ts @@ -41,6 +41,6 @@ export class KbnColorFnPalette extends KbnBasePalette implements IKbnPalette { } public colors = (n: number = this.#defaultNumberOfColors) => { - return this.#colorFn(n); + return this.#colorFn(Math.max(1, n)); }; } diff --git a/packages/kbn-palettes/classes/gradient_palette.ts b/packages/kbn-palettes/classes/gradient_palette.ts deleted file mode 100644 index f542097a8889b..0000000000000 --- a/packages/kbn-palettes/classes/gradient_palette.ts +++ /dev/null @@ -1,33 +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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import chroma, { Scale } from 'chroma-js'; -import { Optional } from 'utility-types'; -import { IKbnPalette } from './types'; -import { KbnBasePalette, KbnBasePaletteConfig } from './palette'; - -export interface KbnGradientPaletteConfig extends Optional { - colors: string[]; -} - -export class KbnGradientPalette extends KbnBasePalette implements IKbnPalette { - public readonly type = 'gradient' as const; - - #scale: Scale; - - constructor({ colors, colorCount = 10, ...rest }: KbnGradientPaletteConfig) { - super({ ...rest, colorCount }); - - this.#scale = chroma.scale(colors).mode('lab'); - } - - public colors = (n?: number) => { - return this.#scale.colors(n, 'hex'); - }; -} diff --git a/packages/kbn-palettes/classes/types.ts b/packages/kbn-palettes/classes/types.ts index 115c50dcfd4f9..345978a409a51 100644 --- a/packages/kbn-palettes/classes/types.ts +++ b/packages/kbn-palettes/classes/types.ts @@ -39,6 +39,8 @@ export interface IKbnPalette { aliases: string[]; /** * Excluded from `getAll` but can still query for palette with `get`/`query` + * + * An example would be `KbnPalette.Neutral` palette. I want to exclude it from the list of all available palettes, but I still want to `get`/`query` the palette. */ standalone?: boolean; /** diff --git a/packages/kbn-palettes/constants.ts b/packages/kbn-palettes/constants.ts index 137b6b22ada4c..13ac550577e59 100644 --- a/packages/kbn-palettes/constants.ts +++ b/packages/kbn-palettes/constants.ts @@ -63,22 +63,13 @@ const gradient = { * Enum of all kbn palette ids, including by type */ export const KbnPalette = { - /** - * Categorical palettes - */ - _categorical: categorical, + // Categorical palettes ...categorical, - /** - * Gradient palettes - */ - _gradient: gradient, + // Gradient palettes ...gradient, - /** - * Semantic palettes - */ - _semantic: semantic, + // Semantic palettes ...semantic, // ---- Deprecated palettes ---- diff --git a/packages/kbn-palettes/palettes/categorical/neutral.ts b/packages/kbn-palettes/palettes/categorical/neutral.ts index 9b4f3db681569..13de3a45cb94a 100644 --- a/packages/kbn-palettes/palettes/categorical/neutral.ts +++ b/packages/kbn-palettes/palettes/categorical/neutral.ts @@ -8,18 +8,29 @@ */ import { i18n } from '@kbn/i18n'; -import { KbnCategoricalPalette } from '../../classes/categorical_palette'; +import { + KbnCategoricalPalette, + KbnCategoricalPaletteConfig, +} from '../../classes/categorical_palette'; import { KbnPalette } from '../../constants'; -const lightColors = ['#F6F9FC', '#D0D4DA', '#989FAA', '#666D78', '#373D45']; -const darkColors = ['#F6F9FC', '#C9D4E6', '#89A0C4', '#546D95', '#283C5C']; +const commonProps = { + id: KbnPalette.Neutral, + standalone: true, + name: i18n.translate('palettes.elastic.name', { + defaultMessage: 'Neutral', + }), +} satisfies Omit; + +const lightNeutralPalette = new KbnCategoricalPalette({ + ...commonProps, + colors: ['#F6F9FC', '#D0D4DA', '#989FAA', '#666D78', '#373D45'], +}); + +const darkNeutralPalette = new KbnCategoricalPalette({ + ...commonProps, + colors: ['#F6F9FC', '#C9D4E6', '#89A0C4', '#546D95', '#283C5C'], +}); export const getNeutralPalette = (darkMode: boolean) => - new KbnCategoricalPalette({ - id: KbnPalette.Neutral, - standalone: true, - name: i18n.translate('palettes.elastic.name', { - defaultMessage: 'Neutral', - }), - colors: darkMode ? darkColors : lightColors, - }); + darkMode ? darkNeutralPalette : lightNeutralPalette; diff --git a/packages/kbn-palettes/types.ts b/packages/kbn-palettes/types.ts deleted file mode 100644 index 35c8ab6efa60b..0000000000000 --- a/packages/kbn-palettes/types.ts +++ /dev/null @@ -1,10 +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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -export type ThemeMode = 'LIGHT' | 'DARK' | 'DARKBLUE'; diff --git a/x-pack/plugins/lens/public/shared_components/coloring/color_mapping_by_terms.tsx b/x-pack/plugins/lens/public/shared_components/coloring/color_mapping_by_terms.tsx index ed07cd584824b..ffc23d68bc54a 100644 --- a/x-pack/plugins/lens/public/shared_components/coloring/color_mapping_by_terms.tsx +++ b/x-pack/plugins/lens/public/shared_components/coloring/color_mapping_by_terms.tsx @@ -30,7 +30,7 @@ import { KbnPalettes } from '@kbn/palettes'; import { trackUiCounterEvents } from '../../lens_ui_telemetry'; import { PalettePicker } from '../palette_picker'; import { PalettePanelContainer } from './palette_panel_container'; -import { getColorStops } from './utils'; +import { getPaletteDisplayColors } from './utils'; interface ColorMappingByTermsProps { isDarkMode: boolean; @@ -69,7 +69,13 @@ export function ColorMappingByTerms({ fullWidth > { return { ...jest.requireActual('../../shared_components/coloring'), - getColorStops: jest.fn().mockReturnValue([]), + getPaletteDisplayColors: jest.fn().mockReturnValue([]), }; }); @@ -438,7 +438,7 @@ describe('Datatable Visualization', () => { let params: VisualizationConfigProps; beforeEach(() => { - (getColorStops as jest.Mock).mockReturnValue(mockStops); + (getPaletteDisplayColors as jest.Mock).mockReturnValue(mockStops); }); describe('rows', () => { @@ -483,7 +483,7 @@ describe('Datatable Visualization', () => { it.each(['cell', 'text'])( 'should not include palette if colorMode is %s but stops is empty', (colorMode) => { - (getColorStops as jest.Mock).mockReturnValue([]); + (getPaletteDisplayColors as jest.Mock).mockReturnValue([]); params.state.columns[0].colorMode = colorMode; expect(datatableVisualization.getConfiguration(params).groups[0].accessors).toEqual([ { columnId: 'b' }, @@ -532,7 +532,7 @@ describe('Datatable Visualization', () => { it.each(['cell', 'text'])( 'should not include palette if colorMode is %s but stops is empty', (colorMode) => { - (getColorStops as jest.Mock).mockReturnValue([]); + (getPaletteDisplayColors as jest.Mock).mockReturnValue([]); params.state.columns[0].colorMode = colorMode; expect(datatableVisualization.getConfiguration(params).groups[2].accessors).toEqual([ { columnId: 'b' }, diff --git a/x-pack/plugins/lens/public/visualizations/datatable/visualization.tsx b/x-pack/plugins/lens/public/visualizations/datatable/visualization.tsx index eae44802052b1..23d8d432ce2d6 100644 --- a/x-pack/plugins/lens/public/visualizations/datatable/visualization.tsx +++ b/x-pack/plugins/lens/public/visualizations/datatable/visualization.tsx @@ -55,7 +55,7 @@ import { import { defaultPaletteParams, findMinMaxByColumnId, - getColorStops, + getPaletteDisplayColors, shouldColorByTerms, } from '../../shared_components'; import { getColorMappingTelemetryEvents } from '../../lens_ui_telemetry/color_telemetry_helpers'; @@ -329,7 +329,7 @@ export const getDatatableVisualization = ({ hidden, collapseFn, } = columnMap[accessor] ?? {}; - const stops = getColorStops( + const stops = getPaletteDisplayColors( paletteService, palettes, theme.darkMode, @@ -422,7 +422,7 @@ export const getDatatableVisualization = ({ colorMapping, hidden, } = columnMap[accessor] ?? {}; - const stops = getColorStops( + const stops = getPaletteDisplayColors( paletteService, palettes, theme.darkMode, diff --git a/x-pack/plugins/lens/public/visualizations/partition/dimension_editor.tsx b/x-pack/plugins/lens/public/visualizations/partition/dimension_editor.tsx index efd2cb4a27fe6..21cd550d4f53d 100644 --- a/x-pack/plugins/lens/public/visualizations/partition/dimension_editor.tsx +++ b/x-pack/plugins/lens/public/visualizations/partition/dimension_editor.tsx @@ -23,7 +23,11 @@ import { getColorCategories } from '@kbn/chart-expressions-common'; import { KbnPalette, KbnPalettes } from '@kbn/palettes'; import { PieVisualizationState } from '../../../common/types'; import { VisualizationDimensionEditorProps } from '../../types'; -import { PalettePanelContainer, PalettePicker, getColorStops } from '../../shared_components'; +import { + PalettePanelContainer, + PalettePicker, + getPaletteDisplayColors, +} from '../../shared_components'; import { CollapseSetting } from '../../shared_components/collapse_setting'; import { getDefaultColorForMultiMetricDimension, @@ -118,7 +122,7 @@ export function DimensionEditor(props: DimensionEditorProps) { }) : undefined; - const colors = getColorStops( + const colors = getPaletteDisplayColors( props.paletteService, props.palettes, props.isDarkMode, diff --git a/x-pack/plugins/lens/public/visualizations/tagcloud/tags_dimension_editor.tsx b/x-pack/plugins/lens/public/visualizations/tagcloud/tags_dimension_editor.tsx index 70abbc10899d4..5dea1057c3712 100644 --- a/x-pack/plugins/lens/public/visualizations/tagcloud/tags_dimension_editor.tsx +++ b/x-pack/plugins/lens/public/visualizations/tagcloud/tags_dimension_editor.tsx @@ -21,7 +21,11 @@ import { useDebouncedValue } from '@kbn/visualization-utils'; import { getColorCategories } from '@kbn/chart-expressions-common'; import { KbnPalettes } from '@kbn/palettes'; import type { TagcloudState } from './types'; -import { PalettePanelContainer, PalettePicker, getColorStops } from '../../shared_components'; +import { + PalettePanelContainer, + PalettePicker, + getPaletteDisplayColors, +} from '../../shared_components'; import { FramePublicAPI } from '../../types'; import { trackUiCounterEvents } from '../../lens_ui_telemetry'; @@ -53,7 +57,7 @@ export function TagsDimensionEditor({ }); const [useNewColorMapping, setUseNewColorMapping] = useState(state.colorMapping ? true : false); - const colors = getColorStops( + const colors = getPaletteDisplayColors( paletteService, palettes, isDarkMode, From a0532c983b3b65ca53e3b02dea1e52cd3b14b450 Mon Sep 17 00:00:00 2001 From: nickofthyme Date: Tue, 10 Dec 2024 18:03:52 -0600 Subject: [PATCH 36/41] fix: color method min color enforcement --- packages/kbn-palettes/classes/categorical_palette.ts | 5 +++-- packages/kbn-palettes/classes/color_fn_palette.ts | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/kbn-palettes/classes/categorical_palette.ts b/packages/kbn-palettes/classes/categorical_palette.ts index 44b05d86b6271..fc352e7b45b35 100644 --- a/packages/kbn-palettes/classes/categorical_palette.ts +++ b/packages/kbn-palettes/classes/categorical_palette.ts @@ -26,7 +26,8 @@ export class KbnCategoricalPalette extends KbnBasePalette implements IKbnPalette this.#colors = colors; } - public colors = (n: number = 1) => { - return this.#colors.slice(0, Math.max(1, n)); + public colors = (n?: number) => { + const end = n === undefined ? n : Math.max(1, n); + return this.#colors.slice(0, end); }; } diff --git a/packages/kbn-palettes/classes/color_fn_palette.ts b/packages/kbn-palettes/classes/color_fn_palette.ts index 7e0580ee2ac40..1be211ea4ff51 100644 --- a/packages/kbn-palettes/classes/color_fn_palette.ts +++ b/packages/kbn-palettes/classes/color_fn_palette.ts @@ -41,6 +41,6 @@ export class KbnColorFnPalette extends KbnBasePalette implements IKbnPalette { } public colors = (n: number = this.#defaultNumberOfColors) => { - return this.#colorFn(Math.max(1, n)); + return this.#colorFn(n === undefined ? n : Math.max(1, n)); }; } From 978251de6dc366043f584d4cf73a073c5c737ff4 Mon Sep 17 00:00:00 2001 From: nickofthyme Date: Tue, 10 Dec 2024 18:05:13 -0600 Subject: [PATCH 37/41] fix: export static palettes --- .../kbn-palettes/hooks/use_kbn_palettes.ts | 4 +- .../palettes/categorical/elastic.ts | 45 -------------- .../kbn-palettes/palettes/get_kbn_palettes.ts | 4 +- packages/kbn-palettes/palettes/index.ts | 58 ++++++++++++------ .../kbn-palettes/palettes/legacy/index.ts | 59 +++++++++++++------ 5 files changed, 83 insertions(+), 87 deletions(-) diff --git a/packages/kbn-palettes/hooks/use_kbn_palettes.ts b/packages/kbn-palettes/hooks/use_kbn_palettes.ts index 3c2e3afca4fdd..f78c70ad2ba3e 100644 --- a/packages/kbn-palettes/hooks/use_kbn_palettes.ts +++ b/packages/kbn-palettes/hooks/use_kbn_palettes.ts @@ -9,7 +9,7 @@ import { useEuiTheme } from '@elastic/eui'; import { getPalettes } from '../palettes'; -import { getLegacyPalettes } from '../palettes/legacy'; +import { getLegacyKbnPalettes } from '../palettes/legacy'; export function useKbnPalettes() { const { @@ -21,5 +21,5 @@ export function useKbnPalettes() { return getPalettes(colorMode === 'DARK'); } - return getLegacyPalettes(colorMode === 'DARK'); + return getLegacyKbnPalettes(colorMode === 'DARK'); } diff --git a/packages/kbn-palettes/palettes/categorical/elastic.ts b/packages/kbn-palettes/palettes/categorical/elastic.ts index 4cb7563154285..239b1c009d5de 100644 --- a/packages/kbn-palettes/palettes/categorical/elastic.ts +++ b/packages/kbn-palettes/palettes/categorical/elastic.ts @@ -11,7 +11,6 @@ import { i18n } from '@kbn/i18n'; import { euiPaletteColorBlind } from '@elastic/eui'; import { KbnPalette } from '../../constants'; import { KbnColorFnPalette } from '../../classes/color_fn_palette'; -import { KbnCategoricalPalette } from '../../classes/categorical_palette'; /** * This is not correctly returning the updated vis colors from eui. @@ -32,47 +31,3 @@ export const elasticPalette = new KbnColorFnPalette({ // Return exact colors requested given enough rotations colorFn: (n) => euiPaletteColorBlind({ rotations: Math.ceil(n / 10) }).slice(0, n), }); - -export const elasticPaletteCustom = new KbnCategoricalPalette({ - id: KbnPalette.Default, - aliases: [ - 'elastic_borealis', // placeholder - not yet used - KbnPalette.Amsterdam, // to assign to existing default palettes - ], - colorCount: 10, - name: i18n.translate('palettes.elastic.name', { - defaultMessage: 'Elastic (default)', - }), - colors: [ - '#00BEB8', - '#93E5E0', - '#599DFF', - '#B4D5FF', - '#ED6BA2', - '#FFBED5', - '#F66D64', - '#FFC0B8', - '#ED9E00', - '#FFD569', - '#00CBC5', - '#C0F1EE', - '#78B0FF', - '#D2E7FF', - '#F588B3', - '#FFD9E7', - '#FC8A80', - '#FFDAD5', - '#F5AF00', - '#FCE8B0', - '#5DD8D2', - '#D9FDFB', - '#96C3FF', - '#E5F1FF', - '#FBA3C4', - '#FFEBF5', - '#FFA59C', - '#FFE9E5', - '#FEC514', - '#FFF1CC', - ], -}); diff --git a/packages/kbn-palettes/palettes/get_kbn_palettes.ts b/packages/kbn-palettes/palettes/get_kbn_palettes.ts index 295e8f315a022..0519a2d4bf9a9 100644 --- a/packages/kbn-palettes/palettes/get_kbn_palettes.ts +++ b/packages/kbn-palettes/palettes/get_kbn_palettes.ts @@ -9,11 +9,11 @@ import type { CoreTheme } from '@kbn/core-theme-browser'; import { getPalettes } from '.'; -import { getLegacyPalettes } from './legacy'; +import { getLegacyKbnPalettes } from './legacy'; export function getKbnPalettes({ name, darkMode }: CoreTheme) { if (name === 'amsterdam') { - return getLegacyPalettes(darkMode); + return getLegacyKbnPalettes(darkMode); } return getPalettes(darkMode); diff --git a/packages/kbn-palettes/palettes/index.ts b/packages/kbn-palettes/palettes/index.ts index 6ca0a44b78b7e..5f70cafaa6b2c 100644 --- a/packages/kbn-palettes/palettes/index.ts +++ b/packages/kbn-palettes/palettes/index.ts @@ -22,25 +22,45 @@ import { } from './gradient'; export { logLevelPalette } from './semantic'; -export const getPalettes = (darkMode: boolean) => - new KbnPalettes( - [ - elasticPalette, - kibana7Palette, - kibana4Palette, - getNeutralPalette(darkMode), - complementaryPalette, - coolPalette, - grayPalette, - greenPalette, - redPalette, - statusPalette, - temperaturePalette, - warmPalette, - elasticClassicPalette, - ], - elasticPalette - ); +const darkKbnPalettes = new KbnPalettes( + [ + elasticPalette, + kibana7Palette, + kibana4Palette, + getNeutralPalette(true), + complementaryPalette, + coolPalette, + grayPalette, + greenPalette, + redPalette, + statusPalette, + temperaturePalette, + warmPalette, + elasticClassicPalette, + ], + elasticPalette +); + +const lightKbnPalettes = new KbnPalettes( + [ + elasticPalette, + kibana7Palette, + kibana4Palette, + getNeutralPalette(true), + complementaryPalette, + coolPalette, + grayPalette, + greenPalette, + redPalette, + statusPalette, + temperaturePalette, + warmPalette, + elasticClassicPalette, + ], + elasticPalette +); + +export const getPalettes = (darkMode: boolean) => (darkMode ? darkKbnPalettes : lightKbnPalettes); export { elasticPalette } from './categorical'; export * from './get_kbn_palettes'; diff --git a/packages/kbn-palettes/palettes/legacy/index.ts b/packages/kbn-palettes/palettes/legacy/index.ts index 0872bea5b27ed..ced72336fc370 100644 --- a/packages/kbn-palettes/palettes/legacy/index.ts +++ b/packages/kbn-palettes/palettes/legacy/index.ts @@ -27,22 +27,43 @@ import { warmPalette, } from './gradient'; -export const getLegacyPalettes = (darkMode: boolean) => - new KbnPalettes( - [ - kibana7Palette, - kibana4Palette, - kibana7BehindText, - getNeutralPalette(darkMode), - complementaryPalette, - coolPalette, - grayPalette, - greenPalette, - redPalette, - statusPalette, - temperaturePalette, - warmPalette, - elasticClassicPalette, - ], - kibana7Palette - ); +const darkLegacyKbnPalettes = new KbnPalettes( + [ + kibana7Palette, + kibana4Palette, + kibana7BehindText, + getNeutralPalette(true), + complementaryPalette, + coolPalette, + grayPalette, + greenPalette, + redPalette, + statusPalette, + temperaturePalette, + warmPalette, + elasticClassicPalette, + ], + kibana7Palette +); + +const lightLegacyKbnPalettes = new KbnPalettes( + [ + kibana7Palette, + kibana4Palette, + kibana7BehindText, + getNeutralPalette(true), + complementaryPalette, + coolPalette, + grayPalette, + greenPalette, + redPalette, + statusPalette, + temperaturePalette, + warmPalette, + elasticClassicPalette, + ], + kibana7Palette +); + +export const getLegacyKbnPalettes = (darkMode: boolean) => + darkMode ? darkLegacyKbnPalettes : lightLegacyKbnPalettes; From 1dc23ab2e158b14810dd794640f02c826eb240a4 Mon Sep 17 00:00:00 2001 From: nickofthyme Date: Tue, 10 Dec 2024 19:07:47 -0600 Subject: [PATCH 38/41] chore: add description for `defaultNumberOfColors` --- packages/kbn-palettes/classes/color_fn_palette.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/kbn-palettes/classes/color_fn_palette.ts b/packages/kbn-palettes/classes/color_fn_palette.ts index 1be211ea4ff51..4be79355f110f 100644 --- a/packages/kbn-palettes/classes/color_fn_palette.ts +++ b/packages/kbn-palettes/classes/color_fn_palette.ts @@ -16,6 +16,11 @@ const DEFAULT_COLOR_COUNT = 10; export interface KbnColorFnPaletteConfig extends Optional { type: KbnPaletteType; colorFn: (n: number) => string[]; + /** + * Default number of colors returned from `colors` method. + * + * @default `colorCount` + */ defaultNumberOfColors?: number; } From 292f3dec368d9d9e3ca3b8212a2f2f8fc5d6de98 Mon Sep 17 00:00:00 2001 From: nickofthyme Date: Tue, 10 Dec 2024 19:35:35 -0600 Subject: [PATCH 39/41] test: fix duplicate render --- src/plugins/charts/public/services/theme/theme.test.tsx | 2 +- src/plugins/charts/public/services/theme/theme.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/charts/public/services/theme/theme.test.tsx b/src/plugins/charts/public/services/theme/theme.test.tsx index 9f3ae5dd433da..df0acfbede1cf 100644 --- a/src/plugins/charts/public/services/theme/theme.test.tsx +++ b/src/plugins/charts/public/services/theme/theme.test.tsx @@ -125,7 +125,7 @@ describe('ThemeService', () => { setUpMockTheme.theme$ = createTheme$Mock(true); themeService.init(setUpMockTheme); }); - expect(renderCounter).toHaveBeenCalledTimes(4); + expect(renderCounter).toHaveBeenCalledTimes(2); }); }); }); diff --git a/src/plugins/charts/public/services/theme/theme.ts b/src/plugins/charts/public/services/theme/theme.ts index 9a846a3271f30..8d776215fec2e 100644 --- a/src/plugins/charts/public/services/theme/theme.ts +++ b/src/plugins/charts/public/services/theme/theme.ts @@ -111,7 +111,7 @@ export class ThemeService { // TODO: define these overrides in elastic/charts when Borealis becomes default function getChartTheme(theme: CoreTheme): Theme { - const chartTheme = { ...(theme.darkMode ? DARK_THEME : LIGHT_THEME) }; + const chartTheme = theme.darkMode ? DARK_THEME : LIGHT_THEME; if (theme.name !== 'amsterdam') { const backgroundColor = euiThemeVars.euiColorEmptyShade; From 4c7c09c100f4a9a980599263207612c62dcbeba4 Mon Sep 17 00:00:00 2001 From: nickofthyme Date: Tue, 10 Dec 2024 19:39:53 -0600 Subject: [PATCH 40/41] chore: add `fallbackColor` theme override --- src/plugins/charts/public/services/theme/theme.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/charts/public/services/theme/theme.ts b/src/plugins/charts/public/services/theme/theme.ts index 8d776215fec2e..765daf957e74d 100644 --- a/src/plugins/charts/public/services/theme/theme.ts +++ b/src/plugins/charts/public/services/theme/theme.ts @@ -116,6 +116,7 @@ function getChartTheme(theme: CoreTheme): Theme { if (theme.name !== 'amsterdam') { const backgroundColor = euiThemeVars.euiColorEmptyShade; chartTheme.background.color = backgroundColor; + chartTheme.background.fallbackColor = backgroundColor; } return chartTheme; From 600912fbbde5baafa72e444394749c426538ab86 Mon Sep 17 00:00:00 2001 From: nickofthyme Date: Tue, 10 Dec 2024 20:22:20 -0600 Subject: [PATCH 41/41] chore: remove eslint override on tagcloud --- .../public/components/tagcloud_component.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/plugins/chart_expressions/expression_tagcloud/public/components/tagcloud_component.tsx b/src/plugins/chart_expressions/expression_tagcloud/public/components/tagcloud_component.tsx index 661c33744c310..46064ebd6b6e2 100644 --- a/src/plugins/chart_expressions/expression_tagcloud/public/components/tagcloud_component.tsx +++ b/src/plugins/chart_expressions/expression_tagcloud/public/components/tagcloud_component.tsx @@ -143,13 +143,12 @@ export const TagCloudChart = ({ : getColor(palettesRegistry, palette, tag, values, syncColors) || 'rgba(0,0,0,0)', }; }); - // eslint-disable-next-line react-hooks/exhaustive-deps }, [ bucket, visData.columns, visData.rows, metric, - // palettes, // somehow causes infinite update of RO + palettes, isDarkMode, colorMapping, bucketFormatter,