Skip to content

Commit

Permalink
[Lens][Table] Add color by terms with color mappings (#189895)
Browse files Browse the repository at this point in the history
Adds support for coloring Table cells by terms with color mapping assignments. Supported for both `Rows` and `Metric` dimensions.
  • Loading branch information
nickofthyme authored Aug 28, 2024
1 parent 7944c19 commit a994629
Show file tree
Hide file tree
Showing 77 changed files with 1,928 additions and 837 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,26 @@ import { Container } from './components/container/container';
import { ColorMapping } from './config';
import { uiReducer } from './state/ui';

export interface ColorMappingInputCategoricalData {
type: 'categories';
/** an ORDERED array of categories rendered in the visualization */
categories: Array<string | string[]>;
}

export interface ColorMappingInputContinuousData {
type: 'ranges';
min: number;
max: number;
bins: number;
}

/**
* A configuration object that is required to populate correctly the visible categories
* or the ranges in the CategoricalColorMapping component
*/
export type ColorMappingInputData =
| {
type: 'categories';
/** an ORDERED array of categories rendered in the visualization */
categories: Array<string | string[]>;
}
| {
type: 'ranges';
min: number;
max: number;
bins: number;
};
| ColorMappingInputCategoricalData
| ColorMappingInputContinuousData;

/**
* The props of the CategoricalColorMapping component
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ export function getColorFactory(
})
: [];

// find all categories that doesn't match with an assignment
// find all categories that don't match with an assignment
const notAssignedCategories =
data.type === 'categories'
? data.categories.filter((category) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export function rangeMatch(rule: ColorMapping.RuleRange, value: number) {
}

// TODO: move in some data/table related package
export const SPECIAL_TOKENS_STRING_CONVERTION = new Map([
export const SPECIAL_TOKENS_STRING_CONVERSION = new Map([
[
'__other__',
i18n.translate('coloring.colorMapping.terms.otherBucketLabel', {
Expand All @@ -55,3 +55,9 @@ export const SPECIAL_TOKENS_STRING_CONVERTION = new Map([
}),
],
]);

/**
* Returns special string for sake of color mapping/syncing
*/
export const getSpecialString = (value: string) =>
SPECIAL_TOKENS_STRING_CONVERSION.get(value) ?? value;
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ export function Assignment({
css={
!disableDelete
? css`
color: ${euiThemeVars.euiTextSubduedColor};
color: ${euiThemeVars.euiTextColor};
transition: ${euiThemeVars.euiAnimSpeedFast} ease-in-out;
transition-property: color;
&:hover,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ export const Match: React.FC<{
return (
<EuiFlexItem style={{ minWidth: 1, width: 1 }}>
<EuiComboBox
isClearable
data-test-subj={`lns-colorMapping-assignmentsItem${index}`}
fullWidth={true}
aria-label={i18n.translate('coloring.colorMapping.assignments.autoAssignedTermAriaLabel', {
Expand All @@ -82,7 +83,7 @@ export const Match: React.FC<{
placeholder={i18n.translate(
'coloring.colorMapping.assignments.autoAssignedTermPlaceholder',
{
defaultMessage: 'Auto assigned',
defaultMessage: 'Auto assigning term',
}
)}
options={convertedOptions}
Expand All @@ -103,7 +104,6 @@ export const Match: React.FC<{
}
}}
isCaseSensitive
isClearable={false}
compressed
/>
</EuiFlexItem>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,7 @@
*/

import React, { useState } from 'react';
import {
EuiButtonEmpty,
EuiPopoverTitle,
EuiTab,
EuiTabs,
EuiTitle,
EuiHorizontalRule,
} from '@elastic/eui';
import { EuiButtonEmpty, EuiPopoverTitle, EuiTab, EuiTabs, EuiHorizontalRule } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { ColorMapping } from '../../config';
import { getPalette } from '../../palettes';
Expand Down Expand Up @@ -56,22 +49,14 @@ export function ColorPicker({
>
<EuiTabs size="m" expand>
<EuiTab onClick={() => setTab('palette')} isSelected={tab === 'palette'}>
<EuiTitle size="xxxs">
<span>
{i18n.translate('coloring.colorMapping.colorPicker.paletteTabLabel', {
defaultMessage: 'Colors',
})}
</span>
</EuiTitle>
{i18n.translate('coloring.colorMapping.colorPicker.paletteTabLabel', {
defaultMessage: 'Colors',
})}
</EuiTab>
<EuiTab onClick={() => setTab('custom')} isSelected={tab === 'custom'}>
<EuiTitle size="xxxs">
<span>
{i18n.translate('coloring.colorMapping.colorPicker.customTabLabel', {
defaultMessage: 'Custom',
})}
</span>
</EuiTitle>
{i18n.translate('coloring.colorMapping.colorPicker.customTabLabel', {
defaultMessage: 'Custom',
})}
</EuiTab>
</EuiTabs>
</EuiPopoverTitle>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,15 +124,14 @@ export const ColorSwatch = ({
css={css`
&::after {
content: '';
width: 0;
height: 0;
border-left: 3px solid transparent;
border-right: 3px solid transparent;
border-top: 4px solid ${colorIsDark ? 'white' : 'black'};
margin: 0;
bottom: 2px;
background-color: ${colorIsDark ? 'white' : 'black'};
// custom arrowDown svg
mask-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI3IiBoZWlnaHQ9IjQiIHZpZXdCb3g9IjAgMCA3IDQiPgogIDxwYXRoIGQ9Ik0uMTQ2LjE0N2EuNS41IDAgMCAxIC43MDggMEwzLjUgMi43OTQgNi4xNDYuMTQ3YS41LjUgMCAxIDEgLjcwOC43MDhsLTMgM2EuNS41IDAgMCAxLS43MDggMGwtMy0zYS41LjUgMCAwIDEgMC0uNzA4WiIvPgo8L3N2Zz4K');
height: 4px;
width: 7px;
bottom: 6px;
right: 4px;
position: absolute;
right: 2px;
}
`}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ import {
EuiFlexItem,
EuiHorizontalRule,
EuiIcon,
EuiText,
EuiTitle,
EuiToolTip,
EuiSpacer,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { ColorMapping } from '../../config';
Expand Down Expand Up @@ -50,13 +51,14 @@ export function PaletteColors({
<>
<EuiFlexGroup direction="column" style={{ padding: 8 }}>
<EuiFlexItem>
<EuiText size="s">
<strong>
<EuiTitle size="xxxs">
<h6>
{i18n.translate('coloring.colorMapping.colorPicker.paletteColorsLabel', {
defaultMessage: 'Palette colors',
})}
</strong>
</EuiText>
</h6>
</EuiTitle>
<EuiSpacer size="s" />
<EuiFlexGroup
direction="row"
gutterSize="s"
Expand Down Expand Up @@ -84,22 +86,26 @@ export function PaletteColors({
<EuiHorizontalRule margin="xs" />
<EuiFlexGroup style={{ padding: 8, paddingTop: 0 }}>
<EuiFlexItem>
<EuiText size="s">
<strong>
<EuiTitle size="xxxs">
<h6>
{i18n.translate('coloring.colorMapping.colorPicker.themeAwareColorsLabel', {
defaultMessage: 'Neutral colors',
})}
</strong>
<EuiToolTip
position="bottom"
content={i18n.translate('coloring.colorMapping.colorPicker.themeAwareColorsTooltip', {
defaultMessage:
'The provided neutral colors are theme-aware and will change appropriately when switching between light and dark themes.',
})}
>
<EuiIcon tabIndex={0} type="questionInCircle" />
</EuiToolTip>
</EuiText>
<EuiToolTip
position="bottom"
content={i18n.translate(
'coloring.colorMapping.colorPicker.themeAwareColorsTooltip',
{
defaultMessage:
'The provided neutral colors are theme-aware and will change appropriately when switching between light and dark themes.',
}
)}
>
<EuiIcon tabIndex={0} type="questionInCircle" />
</EuiToolTip>
</h6>
</EuiTitle>
<EuiSpacer size="s" />
<EuiFlexGroup
direction="row"
gutterSize="s"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ export function AssignmentsConfig({
return (
<EuiPanel
color="subdued"
borderRadius="none"
borderRadius="m"
hasShadow={false}
paddingSize="none"
css={css`
Expand Down Expand Up @@ -195,7 +195,7 @@ export function AssignmentsConfig({
'coloring.colorMapping.container.mapValuesPromptDescription.mapValuesPromptDetail',
{
defaultMessage:
'Add new assignments to begin associating terms in your data with specified colors.',
'Add a new assignment to manually associate terms with specified colors.',
}
)}
</p>
Expand All @@ -214,7 +214,6 @@ export function AssignmentsConfig({
</EuiButton>,
<EuiButtonEmpty
data-test-subj="lns-colorMapping-assignmentsPromptAddAll"
color="primary"
size="xs"
onClick={onClickAddAllCurrentCategories}
>
Expand All @@ -228,13 +227,14 @@ export function AssignmentsConfig({
</EuiFlexGroup>
</div>
{assignments.length > 0 && <EuiHorizontalRule margin="none" />}
<div
css={css`
padding: ${euiThemeVars.euiPanelPaddingModifiers.paddingSmall};
overflow: hidden;
`}
>
{assignments.length > 0 && (

{assignments.length > 0 && (
<div
css={css`
padding: ${euiThemeVars.euiPanelPaddingModifiers.paddingSmall};
overflow: hidden;
`}
>
<EuiFlexGroup
direction="row"
alignItems="center"
Expand All @@ -251,6 +251,7 @@ export function AssignmentsConfig({
button={
<EuiButtonIcon
iconType="boxesVertical"
color="text"
aria-label={i18n.translate(
'coloring.colorMapping.container.OpenAdditionalActionsButtonLabel',
{
Expand Down Expand Up @@ -308,7 +309,9 @@ export function AssignmentsConfig({
setShowOtherActions(false);
dispatch(removeAllAssignments());
}}
color="danger"
css={css`
color: ${euiThemeVars.euiColorDanger};
`}
>
{i18n.translate(
'coloring.colorMapping.container.clearAllAssignmentsButtonLabel',
Expand All @@ -322,8 +325,8 @@ export function AssignmentsConfig({
</EuiPopover>
)}
</EuiFlexGroup>
)}
</div>
</div>
)}
</EuiPanel>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ export function Container({
>
<EuiButtonIcon
data-test-subj="lns-colorMapping-invertGradient"
color="text"
iconType="merge"
size="xs"
aria-label={i18n.translate(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ export function ScaleMode({ getPaletteFn }: { getPaletteFn: ReturnType<typeof ge
>
<EuiButtonGroup
legend="Mode"
buttonSize="compressed"
data-test-subj="lns_colorMapping_scaleSwitch"
options={[
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,17 @@
* Side Public License, v 1.
*/

export { CategoricalColorMapping, type ColorMappingProps } from './categorical_color_mapping';
export {
CategoricalColorMapping,
type ColorMappingProps,
type ColorMappingInputCategoricalData,
type ColorMappingInputContinuousData,
} 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_CONVERTION } from './color/rule_matching';
export { SPECIAL_TOKENS_STRING_CONVERSION, getSpecialString } from './color/rule_matching';
export {
DEFAULT_COLOR_MAPPING_CONFIG,
DEFAULT_OTHER_ASSIGNMENT_INDEX,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,9 @@ export function PalettePicker({
}) {
const palettesToShow: EuiColorPalettePickerPaletteProps[] = palettes
.getAll()
.filter(({ internal, canDynamicColoring }) =>
showDynamicColorOnly ? canDynamicColoring : !internal
)
.filter(({ internal, canDynamicColoring }) => {
return showDynamicColorOnly ? canDynamicColoring && !internal : !internal;
})
.map(({ id, title, getCategoricalColors }) => {
const colors = getCategoricalColors(
activePalette?.params?.steps || DEFAULT_COLOR_STEPS,
Expand Down
2 changes: 1 addition & 1 deletion packages/kbn-optimizer/limits.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ pageLoadAssetSize:
expressionLegacyMetricVis: 23121
expressionMetric: 22238
expressionMetricVis: 23121
expressionPartitionVis: 29700
expressionPartitionVis: 44888
expressionRepeatImage: 22341
expressionRevealImage: 25675
expressions: 140958
Expand Down
Loading

0 comments on commit a994629

Please sign in to comment.