Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Lens] Heatmap / Swim lane integration #97978

Merged
merged 83 commits into from
Jun 4, 2021
Merged
Changes from 1 commit
Commits
Show all changes
83 commits
Select commit Hold shift + click to select a range
d67fad6
heatmap wip
darnautov Mar 29, 2021
381240e
format values on X axis
darnautov Mar 30, 2021
415b567
format values for cells
darnautov Mar 30, 2021
9fbca6a
show labels
darnautov Mar 30, 2021
c25cf3e
support legend configuration
darnautov Mar 31, 2021
2c65a8d
render preview
darnautov Apr 1, 2021
54e96a0
add icon
darnautov Apr 2, 2021
38a5a6d
Merge remote-tracking branch 'upstream/master' into lens-heatmap-chart
darnautov Apr 22, 2021
cd912c2
[ML] update visualization
darnautov Apr 22, 2021
c5d02d0
[ML] init suggestions
darnautov Apr 22, 2021
2b40fe3
Merge remote-tracking branch 'upstream/master' into lens-heatmap-chart
darnautov May 5, 2021
7aaeccd
[ML] fix preview
darnautov May 5, 2021
bb4910c
[ML] fix groupPosition for the legend control
darnautov May 5, 2021
48bbad0
[ML] add formatter for Y-axis
darnautov May 5, 2021
398b92f
[ML] filterOperations for cell value
darnautov May 5, 2021
d25f7e9
[ML] fill all available height
darnautov May 5, 2021
1e6d858
[ML] delete unused file
darnautov May 6, 2021
a8b3be4
[ML] fix suggestion state
darnautov May 6, 2021
3d89c72
Merge remote-tracking branch 'upstream/master' into lens-heatmap-chart
darnautov May 10, 2021
62db0f2
[ML] update suggestion, add hiding logic
darnautov May 11, 2021
d7b6d01
[ML] suggestions unit tests
darnautov May 11, 2021
c252224
[ML] rename legend interface
darnautov May 11, 2021
5583f3b
[ML] unit tests for visualization, add error messages
darnautov May 11, 2021
b8ac2d3
[ML] fix typos in xy visualization tests
darnautov May 11, 2021
ab10566
[ML] support click event
darnautov May 12, 2021
1b9d09f
[ML] add xDomain for time series data
darnautov May 12, 2021
f7b53ce
[ML] support empty Y axis
darnautov May 12, 2021
75d3440
[ML] change legend default position
darnautov May 12, 2021
f402b58
[ML] getTimeZone util
darnautov May 12, 2021
7b57130
[ML] hide suggestions for reorder
darnautov May 12, 2021
4f32606
[ML] support brush event
darnautov May 12, 2021
b9faf1c
[ML] update unit tests
darnautov May 12, 2021
deb0436
Merge remote-tracking branch 'upstream/master' into lens-heatmap-chart
darnautov May 12, 2021
ed0bee2
Merge remote-tracking branch 'upstream/master' into lens-heatmap-chart
darnautov May 19, 2021
b581f1c
[ML] render grid lines in preview
darnautov May 19, 2021
c31d336
[ML] don't display errors on init
darnautov May 20, 2021
4548731
[ML] utilize chartsThemeService
darnautov May 20, 2021
e236ff1
[ML] support histogram for the vertical axis
darnautov May 20, 2021
6283fb0
[ML] fix clearLayer
darnautov May 20, 2021
cf62bc8
Merge remote-tracking branch 'upstream/master' into lens-heatmap-chart
darnautov May 25, 2021
5ed1d2e
[ML] show empty placeholder on no data
darnautov May 25, 2021
356109c
[ML] fix X domain min
darnautov May 25, 2021
2cde585
[ML] reject suggestions for 3 or more buckets
darnautov May 25, 2021
60c0caa
[ML] suggestions for histograms and histogram for Y-axis
darnautov May 25, 2021
1c4ba88
[ML] fix unit tests
darnautov May 25, 2021
9c0c0ff
[ML] update suggestions for active heatmap
darnautov May 26, 2021
abab529
[ML] chart data test for heatmap
darnautov May 26, 2021
9c97eae
[ML] test for transitioning from heatmap to barchart
darnautov May 26, 2021
bbb088e
Merge remote-tracking branch 'upstream/master' into lens-heatmap-chart
darnautov May 27, 2021
1477b7d
[ML] disable xDomain
darnautov May 27, 2021
f684b0a
[ML] support intervals in axes configurations
darnautov May 27, 2021
721c9d8
[ML] hide label on the vertical axis when there is only a horizontal …
darnautov May 27, 2021
9e0ac07
[ML] set min cell height for better suggestions preview rendering
darnautov May 27, 2021
4f4cb04
[ML] fix tooltip for empty vertical axis config
darnautov May 27, 2021
1d1c387
[ML] fix click and brushing for empty Y axis
darnautov May 27, 2021
9853d29
[ML] update functional test
darnautov May 27, 2021
e7d2637
Merge remote-tracking branch 'upstream/master' into lens-heatmap-chart
darnautov May 28, 2021
faf208c
Merge remote-tracking branch 'upstream/master' into lens-heatmap-chart
darnautov May 31, 2021
fce4288
[ML] show beta label
darnautov May 31, 2021
017fc97
[ML] fix legend control
darnautov May 31, 2021
67e52b4
[ML] dataIndex sort by default for the X axis
darnautov May 31, 2021
e8da895
[ML] use euiPaletteForTemperature with quantize color scale
darnautov May 31, 2021
d26f954
[ML] hide all suggestions
darnautov May 31, 2021
224c792
[ML] fix chart data extension issue
darnautov May 31, 2021
41523c5
[ML] fix the caret symbol positioning
darnautov May 31, 2021
067d782
[ML] update unit tests for the heatmap suggestions
darnautov Jun 1, 2021
3c645c5
Merge remote-tracking branch 'upstream/master' into lens-heatmap-chart
darnautov Jun 2, 2021
f90fe8f
[ML] replace EuiBetaBadge with EuiBadge
darnautov Jun 2, 2021
685a5bf
[ML] update functional test
darnautov Jun 2, 2021
edd83a3
[ML] fix chart switch styles
darnautov Jun 2, 2021
1021d1c
[ML] fix functional test
darnautov Jun 3, 2021
c7b46b2
[ML] return null instead of expression with a missing value accessor
darnautov Jun 3, 2021
cc47903
[ML] use table id as a chart id
darnautov Jun 3, 2021
645e34f
[ML] fix scale type for a single row of data
darnautov Jun 3, 2021
feb2b45
[ML] filter out undefined values
darnautov Jun 3, 2021
3a4443f
Merge branch 'master' into lens-heatmap-chart
kibanamachine Jun 3, 2021
3cb6b14
[ML] fix isXAxisLabelVisible
darnautov Jun 3, 2021
d699e9e
[ML] update chart_switch styles
darnautov Jun 4, 2021
4cb2f40
show warning message for the array values
darnautov Jun 4, 2021
9bb03df
remove unused code
darnautov Jun 4, 2021
ef95471
replace ts-ignore with manual type casting
darnautov Jun 4, 2021
5a25c36
add unit tests for error and warning messages
darnautov Jun 4, 2021
6d35fb7
add css class for append, conditional flex group
darnautov Jun 4, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
format values on X axis
darnautov committed Apr 6, 2021
commit 381240e7ed751cedd6d9bcc1576b711fb04a1f7d
109 changes: 61 additions & 48 deletions x-pack/plugins/lens/public/heatmap_visualization/chart_component.tsx
Original file line number Diff line number Diff line change
@@ -5,7 +5,7 @@
* 2.0.
*/

import React, { FC, useEffect, useMemo, useState } from 'react';
import React, { FC, useEffect, useState } from 'react';
import {
Chart,
Heatmap,
@@ -28,59 +28,74 @@ declare global {
}
}

export const HeatmapComponent: FC<HeatmapRenderProps> = ({ data, args }) => {
export const HeatmapComponent: FC<HeatmapRenderProps> = ({
data,
args,
timeZone,
formatFactory,
}) => {
const isDarkTheme = false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dark mode should be set dynamically, not statically, by using chartsThemeService.useDarkMode(). Otherwise the text and border color is not high contrast in dark mode.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 4548731

const onElementClick = () => {};

console.log(args, '___args___');
const table = Object.values(data.tables)[0];

const chartData = Object.values(data.tables)[0].rows;
console.log(chartData, '___data___');
const chartData = table.rows;

const config: HeatmapSpec['config'] = useMemo(() => {
return {
onBrushEnd: (e: HeatmapBrushEvent) => {},
grid: {
cellHeight: {
min: 30,
max: 30,
},
stroke: {
width: 1,
color: '#D3DAE6',
},
},
cell: {
maxWidth: 'fill',
maxHeight: 'fill',
label: {
visible: false,
},
border: {
stroke: '#D3DAE6',
strokeWidth: 0,
},
},
yAxisLabel: {
visible: true,
// eui color subdued
fill: `#6a717d`,
padding: 8,
const xAxis = table.columns.find((v) => v.id === args.xAccessor);

if (!xAxis) {
// Chart is not ready
return null;
}

const xAxisMeta = xAxis.meta;
const xScaleType = xAxisMeta.type === 'date' ? ScaleType.Time : ScaleType.Ordinal;

const xValuesFormatter = formatFactory(xAxisMeta.params);

const config: HeatmapSpec['config'] = {
onBrushEnd: (e: HeatmapBrushEvent) => {},
grid: {
cellHeight: {
min: 30,
max: 30,
},
xAxisLabel: {
visible: true,
// eui color subdued
fill: `#98A2B3`,
stroke: {
width: 1,
color: '#D3DAE6',
},
brushMask: {
fill: isDarkTheme ? 'rgb(30,31,35,80%)' : 'rgb(247,247,247,50%)',
},
cell: {
maxWidth: 'fill',
maxHeight: 'fill',
label: {
visible: false,
},
brushArea: {
stroke: isDarkTheme ? 'rgb(255, 255, 255)' : 'rgb(105, 112, 125)',
border: {
stroke: '#D3DAE6',
strokeWidth: 0,
},
timeZone: 'UTC',
};
}, [isDarkTheme]);
},
yAxisLabel: {
visible: true,
// eui color subdued
fill: `#6a717d`,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be imported from eui and take into account the currently used theme - otherwise it won't render right on dark mode

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 4548731

padding: 8,
},
xAxisLabel: {
visible: true,
// eui color subdued
fill: `#98A2B3`,
formatter: (v: number | string) => xValuesFormatter.convert(v),
},
brushMask: {
fill: isDarkTheme ? 'rgb(30,31,35,80%)' : 'rgb(247,247,247,50%)',
},
brushArea: {
stroke: isDarkTheme ? 'rgb(255, 255, 255)' : 'rgb(105, 112, 125)',
},
timeZone,
};

return (
<Chart>
@@ -103,7 +118,7 @@ export const HeatmapComponent: FC<HeatmapRenderProps> = ({ data, args }) => {
xAccessor={args.xAccessor}
yAccessor={args.yAccessor}
valueAccessor={args.valueAccessor}
xScaleType={ScaleType.Time}
xScaleType={xScaleType}
ySortPredicate="dataIndex"
config={config}
/>
@@ -124,8 +139,6 @@ export function HeatmapChartReportable(props: HeatmapRenderProps) {
setState({ isReady: true });
}, [setState]);

console.log(props, '___props___');

return (
<VisualizationContainer
className="lnsHeatmapExpression__container"
22 changes: 17 additions & 5 deletions x-pack/plugins/lens/public/heatmap_visualization/expression.tsx
Original file line number Diff line number Diff line change
@@ -13,7 +13,7 @@ import {
ExpressionFunctionDefinition,
IInterpreterRenderHandlers,
} from '../../../../../src/plugins/expressions';
import { FormatFactory, LensFilterEvent, LensMultiTable } from '../types';
import { FormatFactory, LensMultiTable } from '../types';
import { FUNCTION_NAME, LENS_HEATMAP_RENDERER } from './constants';
import { HeatmapExpressionArgs, HeatmapExpressionProps, HeatmapRender } from './types';
import { ChartsPluginSetup, PaletteRegistry } from '../../../../../src/plugins/charts/public';
@@ -57,11 +57,14 @@ export const heatmap: ExpressionFunctionDefinition<
types: ['string'],
help: '',
},
palette: {
default: `{theme "palette" default={system_palette name="default"} }`,
help: '',
types: ['palette'],
},
},
inputTypes: ['lens_multitable'],
fn(data: LensMultiTable, args: HeatmapExpressionArgs) {
console.log(data, '___data___');
console.log(args, '___args___');
return {
type: 'render',
as: LENS_HEATMAP_RENDERER,
@@ -77,6 +80,7 @@ export const getHeatmapRenderer = (dependencies: {
formatFactory: Promise<FormatFactory>;
chartsThemeService: ChartsPluginSetup['theme'];
paletteService: PaletteRegistry;
timeZone: string;
}) => ({
name: LENS_HEATMAP_RENDERER,
displayName: i18n.translate('xpack.lens.heatmap.visualizationName', {
@@ -90,9 +94,17 @@ export const getHeatmapRenderer = (dependencies: {
config: HeatmapExpressionProps,
handlers: IInterpreterRenderHandlers
) => {
console.log(config, '___config___');
const formatFactory = await dependencies.formatFactory;
ReactDOM.render(
<I18nProvider>{<HeatmapChartReportable {...config} />}</I18nProvider>,
<I18nProvider>
{
<HeatmapChartReportable
{...config}
timeZone={dependencies.timeZone}
formatFactory={formatFactory}
/>
}
</I18nProvider>,
domNode,
() => {
handlers.done();
3 changes: 3 additions & 0 deletions x-pack/plugins/lens/public/heatmap_visualization/index.ts
Original file line number Diff line number Diff line change
@@ -25,6 +25,8 @@ export class HeatmapVisualization {
{ expressions, formatFactory, editorFrame, charts }: HeatmapVisualizationPluginSetupPlugins
) {
editorFrame.registerVisualization(async () => {
const timeZone = await core.uiSettings.get('dateFormat:tz');

const { getHeatmapVisualization, heatmap, getHeatmapRenderer } = await import(
'../async_services'
);
@@ -37,6 +39,7 @@ export class HeatmapVisualization {
formatFactory,
chartsThemeService: charts.theme,
paletteService: palettes,
timeZone,
})
);
return getHeatmapVisualization({ paletteService: palettes });
3 changes: 2 additions & 1 deletion x-pack/plugins/lens/public/heatmap_visualization/types.ts
Original file line number Diff line number Diff line change
@@ -7,7 +7,7 @@

import { Position } from '@elastic/charts';
import { PaletteOutput } from '../../../../../src/plugins/charts/common';
import { LensMultiTable } from '../types';
import { FormatFactory, LensMultiTable } from '../types';
import { CHART_SHAPES, LENS_HEATMAP_RENDERER } from './constants';

export type ChartShapes = typeof CHART_SHAPES[keyof typeof CHART_SHAPES];
@@ -47,4 +47,5 @@ export interface HeatmapExpressionProps {

export type HeatmapRenderProps = HeatmapExpressionProps & {
timeZone: string;
formatFactory: FormatFactory;
};
56 changes: 11 additions & 45 deletions x-pack/plugins/lens/public/heatmap_visualization/visualization.tsx
Original file line number Diff line number Diff line change
@@ -6,15 +6,12 @@
*/

import { i18n } from '@kbn/i18n';
import { Position } from '@elastic/charts';
import { LensIconChartBar } from '../assets/chart_bar';
import { PaletteRegistry } from '../../../../../src/plugins/charts/public';
import { AccessorConfig, OperationMetadata, Visualization } from '../types';
import { HeatmapLayerState, HeatmapVisualizationState } from './types';
import { OperationMetadata, Visualization } from '../types';
import { HeatmapVisualizationState } from './types';
import { suggestions } from './suggestions';
import { toExpression, toPreviewExpression, getSortedAccessors } from './to_expression';
import { CHART_NAMES, CHART_SHAPES, FUNCTION_NAME, GROUP_ID, LENS_HEATMAP_ID } from './constants';
import { ColumnState } from '../datatable_visualization/visualization';

const groupLabelForBar = i18n.translate('xpack.lens.heatmapVisualization.heatmapGroupLabel', {
defaultMessage: 'Heatmap',
@@ -37,9 +34,11 @@ function getAxisName(axis: 'x' | 'y') {
return vertical;
}

const isTimeBucket = (op: OperationMetadata) => op.dataType === 'date';
const isBucketed = (op: OperationMetadata) => op.isBucketed;
const isNumericMetric = (op: OperationMetadata) => !op.isBucketed && op.dataType === 'number';
const filterOperationsXAxis = (op: OperationMetadata) => isTime(op) || isBucketed(op);

const isTime = (op: OperationMetadata) => op.dataType === 'date';
const isBucketed = (op: OperationMetadata) => op.isBucketed && op.scale === 'ordinal';
const isNumericMetric = (op: OperationMetadata) => op.dataType === 'number';

export const getHeatmapVisualization = ({
paletteService,
@@ -97,18 +96,14 @@ export const getHeatmapVisualization = ({
return { groups: [] };
}

// console.log(originalOrder, '___originalOrder___');

// console.log(originalOrder, '___originalOrder___');

return {
groups: [
{
layerId: state.layerId,
groupId: GROUP_ID.X,
groupLabel: getAxisName(GROUP_ID.X),
accessors: state.xAccessor ? [{ columnId: state.xAccessor }] : [],
filterOperations: isTimeBucket,
filterOperations: filterOperationsXAxis,
supportsMoreColumns: true,
required: true,
dataTestSubj: 'lnsHeatmap_xDimensionPanel',
@@ -142,16 +137,7 @@ export const getHeatmapVisualization = ({
},

setDimension({ prevState, layerId, columnId, groupId, previousColumn }) {
// if (!newLayer) {
// return prevState;
// }
//
//
// console.log(prevState, '___prevState___');
// console.log(columnId, '___columnId___');
// console.log(groupId, '___groupId___');

const update = {};
const update: Partial<HeatmapVisualizationState> = {};
if (groupId === GROUP_ID.X) {
update.xAccessor = columnId;
}
@@ -161,7 +147,6 @@ export const getHeatmapVisualization = ({
if (groupId === GROUP_ID.CELL) {
update.valueAccessor = columnId;
}

return {
...prevState,
...update,
@@ -184,33 +169,16 @@ export const getHeatmapVisualization = ({
return update;
},

toExpression: (state, datasourceLayers, attributes) => {
toExpression(state, datasourceLayers, attributes): Ast | null {
const datasource = datasourceLayers[state.layerId];

const originalOrder = datasource.getTableSpec().map(({ columnId }) => columnId);
// When we add a column it could be empty, and therefore have no order

console.log(state, '___state___');

if (!originalOrder) {
return { groups: [] };
return null;
}

const sortedColumns = originalOrder;

// if (
// sortedColumns?.length &&
// sortedColumns.filter((c) => !datasource!.getOperationForColumnId(c)?.isBucketed).length === 0
// ) {
// return null;
// }

// console.log(state, '___state___');
// console.log(datasource, '___datasource___');
// console.log(originalOrder, '___originalOrder___');

console.log(attributes, '___attributes___');

return {
type: 'expression',
chain: [
@@ -229,8 +197,6 @@ export const getHeatmapVisualization = ({
};
},

// toPreviewExpression: (state, layers) => toPreviewExpression(state, layers, paletteService),

getErrorMessages(state) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error messages here start as soon as you open the heatmap configuration. There should be a special case for a completely empty chart so that it's only an error if there's partial config, but a fully empty config is fine.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in c31d336

// not possible to break it?
return undefined;
Original file line number Diff line number Diff line change
@@ -354,10 +354,6 @@ export const SwimlaneContainer: FC<SwimlaneProps> = ({
[swimlaneData?.fieldName]
);

console.log(swimLanePoints, '___swimLanePoints___');

console.log(swimlaneData.interval * 1000, '___swimlaneData.interval * 1000___');

// A resize observer is required to compute the bucket span based on the chart width to fetch the data accordingly
return (
<EuiResizeObserver onResize={resizeHandler}>