mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 09:19:04 -04:00
[Lens] Fix Heatmap in dashboard with numeric color stops (#111117)
* 🐛 Fix heatmap numeric stops problem + tests * 🏷️ Fix type issue * ✅ Add dashboard functional tests for this issue * ✅ Simplify functional test * ✅ fix functional test Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
6a958a5e83
commit
b36ffc98fc
6 changed files with 150 additions and 20 deletions
|
@ -64,7 +64,7 @@ export function HeatmapDimensionEditor(
|
|||
<EuiFlexItem>
|
||||
<EuiColorPaletteDisplay
|
||||
data-test-subj="lnsHeatmap_dynamicColoring_palette"
|
||||
palette={getStopsForFixedMode(displayStops, activePalette.params?.colorStops)}
|
||||
palette={getStopsForFixedMode(displayStops, activePalette?.params?.colorStops)}
|
||||
type={FIXED_PROGRESSION}
|
||||
onClick={() => {
|
||||
setIsPaletteOpen(!isPaletteOpen);
|
||||
|
|
|
@ -14,9 +14,12 @@ import type { HeatmapVisualizationState } from './types';
|
|||
export function getSafePaletteParams(
|
||||
paletteService: PaletteRegistry,
|
||||
currentData: Datatable | undefined,
|
||||
accessor: string,
|
||||
accessor: string | undefined,
|
||||
activePalette?: HeatmapVisualizationState['palette']
|
||||
) {
|
||||
if (currentData == null || accessor == null) {
|
||||
return { displayStops: [], activePalette: {} as HeatmapVisualizationState['palette'] };
|
||||
}
|
||||
const finalActivePalette: HeatmapVisualizationState['palette'] = activePalette ?? {
|
||||
type: 'palette',
|
||||
name: DEFAULT_PALETTE_NAME,
|
||||
|
|
|
@ -98,7 +98,12 @@ describe('heatmap', () => {
|
|||
};
|
||||
});
|
||||
|
||||
test('resolves configuration from complete state', () => {
|
||||
afterEach(() => {
|
||||
// some tests manipulate it, so restore a pristine version
|
||||
frame = createMockFramePublicAPI();
|
||||
});
|
||||
|
||||
test('resolves configuration from complete state and available data', () => {
|
||||
const state: HeatmapVisualizationState = {
|
||||
...exampleState(),
|
||||
layerId: 'first',
|
||||
|
@ -107,6 +112,8 @@ describe('heatmap', () => {
|
|||
valueAccessor: 'v-accessor',
|
||||
};
|
||||
|
||||
frame.activeData = { first: { type: 'datatable', columns: [], rows: [] } };
|
||||
|
||||
expect(
|
||||
getHeatmapVisualization({
|
||||
paletteService,
|
||||
|
@ -204,6 +211,63 @@ describe('heatmap', () => {
|
|||
],
|
||||
});
|
||||
});
|
||||
|
||||
test("resolves configuration when there's no access to active data in frame", () => {
|
||||
const state: HeatmapVisualizationState = {
|
||||
...exampleState(),
|
||||
layerId: 'first',
|
||||
xAccessor: 'x-accessor',
|
||||
yAccessor: 'y-accessor',
|
||||
valueAccessor: 'v-accessor',
|
||||
};
|
||||
|
||||
frame.activeData = undefined;
|
||||
|
||||
expect(
|
||||
getHeatmapVisualization({
|
||||
paletteService,
|
||||
}).getConfiguration({ state, frame, layerId: 'first' })
|
||||
).toEqual({
|
||||
groups: [
|
||||
{
|
||||
layerId: 'first',
|
||||
groupId: GROUP_ID.X,
|
||||
groupLabel: 'Horizontal axis',
|
||||
accessors: [{ columnId: 'x-accessor' }],
|
||||
filterOperations: filterOperationsAxis,
|
||||
supportsMoreColumns: false,
|
||||
required: true,
|
||||
dataTestSubj: 'lnsHeatmap_xDimensionPanel',
|
||||
},
|
||||
{
|
||||
layerId: 'first',
|
||||
groupId: GROUP_ID.Y,
|
||||
groupLabel: 'Vertical axis',
|
||||
accessors: [{ columnId: 'y-accessor' }],
|
||||
filterOperations: filterOperationsAxis,
|
||||
supportsMoreColumns: false,
|
||||
required: false,
|
||||
dataTestSubj: 'lnsHeatmap_yDimensionPanel',
|
||||
},
|
||||
{
|
||||
layerId: 'first',
|
||||
groupId: GROUP_ID.CELL,
|
||||
groupLabel: 'Cell value',
|
||||
accessors: [
|
||||
{
|
||||
columnId: 'v-accessor',
|
||||
triggerIcon: 'none',
|
||||
},
|
||||
],
|
||||
filterOperations: isCellValueSupported,
|
||||
supportsMoreColumns: false,
|
||||
required: true,
|
||||
dataTestSubj: 'lnsHeatmap_cellPanel',
|
||||
enableDimensionEditor: true,
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#setDimension', () => {
|
||||
|
|
|
@ -158,16 +158,12 @@ export const getHeatmapVisualization = ({
|
|||
return { groups: [] };
|
||||
}
|
||||
|
||||
const { displayStops, activePalette } = state.valueAccessor
|
||||
? getSafePaletteParams(
|
||||
paletteService,
|
||||
frame.activeData?.[state.layerId],
|
||||
state.valueAccessor,
|
||||
state?.palette && state.palette.accessor === state.valueAccessor
|
||||
? state.palette
|
||||
: undefined
|
||||
)
|
||||
: { displayStops: [], activePalette: {} as HeatmapVisualizationState['palette'] };
|
||||
const { displayStops, activePalette } = getSafePaletteParams(
|
||||
paletteService,
|
||||
frame.activeData?.[state.layerId],
|
||||
state.valueAccessor,
|
||||
state?.palette && state.palette.accessor === state.valueAccessor ? state.palette : undefined
|
||||
);
|
||||
|
||||
return {
|
||||
groups: [
|
||||
|
@ -199,11 +195,21 @@ export const getHeatmapVisualization = ({
|
|||
}),
|
||||
accessors: state.valueAccessor
|
||||
? [
|
||||
{
|
||||
columnId: state.valueAccessor,
|
||||
triggerIcon: 'colorBy',
|
||||
palette: getStopsForFixedMode(displayStops, activePalette?.params?.colorStops),
|
||||
},
|
||||
// When data is not available and the range type is numeric, return a placeholder while refreshing
|
||||
displayStops.length &&
|
||||
(frame.activeData || activePalette?.params?.rangeType !== 'number')
|
||||
? {
|
||||
columnId: state.valueAccessor,
|
||||
triggerIcon: 'colorBy',
|
||||
palette: getStopsForFixedMode(
|
||||
displayStops,
|
||||
activePalette?.params?.colorStops
|
||||
),
|
||||
}
|
||||
: {
|
||||
columnId: state.valueAccessor,
|
||||
triggerIcon: 'none',
|
||||
},
|
||||
]
|
||||
: [],
|
||||
filterOperations: isCellValueSupported,
|
||||
|
|
|
@ -75,11 +75,14 @@ export function CustomizablePalette({
|
|||
showContinuity = true,
|
||||
}: {
|
||||
palettes: PaletteRegistry;
|
||||
activePalette: PaletteOutput<CustomPaletteParams>;
|
||||
activePalette?: PaletteOutput<CustomPaletteParams>;
|
||||
setPalette: (palette: PaletteOutput<CustomPaletteParams>) => void;
|
||||
dataBounds: { min: number; max: number };
|
||||
dataBounds?: { min: number; max: number };
|
||||
showContinuity?: boolean;
|
||||
}) {
|
||||
if (!dataBounds || !activePalette) {
|
||||
return null;
|
||||
}
|
||||
const isCurrentPaletteCustom = activePalette.params?.name === CUSTOM_PALETTE;
|
||||
|
||||
const colorStopsToShow = roundStopValues(
|
||||
|
|
|
@ -235,6 +235,60 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
expect(panelCount).to.eql(2);
|
||||
});
|
||||
|
||||
// issue #111104
|
||||
it('should add a Lens heatmap to the dashboard', async () => {
|
||||
await PageObjects.common.navigateToApp('dashboard');
|
||||
await PageObjects.dashboard.clickNewDashboard();
|
||||
|
||||
await PageObjects.dashboard.saveDashboard('My Wonderful Heatmap dashboard');
|
||||
await PageObjects.dashboard.gotoDashboardLandingPage();
|
||||
await listingTable.searchAndExpectItemsCount(
|
||||
'dashboard',
|
||||
'My Wonderful Heatmap dashboard',
|
||||
1
|
||||
);
|
||||
|
||||
await PageObjects.visualize.navigateToNewVisualization();
|
||||
await PageObjects.visualize.clickVisType('lens');
|
||||
await PageObjects.lens.goToTimeRange();
|
||||
|
||||
await PageObjects.lens.configureDimension({
|
||||
dimension: 'lnsXY_xDimensionPanel > lns-empty-dimension',
|
||||
operation: 'terms',
|
||||
field: 'ip',
|
||||
});
|
||||
|
||||
await PageObjects.lens.configureDimension({
|
||||
dimension: 'lnsXY_yDimensionPanel > lns-empty-dimension',
|
||||
operation: 'average',
|
||||
field: 'bytes',
|
||||
});
|
||||
|
||||
await PageObjects.lens.waitForVisualization();
|
||||
|
||||
await PageObjects.lens.switchToVisualization('heatmap', 'heatmap');
|
||||
|
||||
await PageObjects.lens.waitForVisualization();
|
||||
await PageObjects.lens.openDimensionEditor('lnsHeatmap_cellPanel > lns-dimensionTrigger');
|
||||
await PageObjects.lens.openPalettePanel('lnsHeatmap');
|
||||
await testSubjects.click('lnsPalettePanel_dynamicColoring_rangeType_groups_number');
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
|
||||
await PageObjects.lens.save(
|
||||
'New Lens Heatmap',
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
'existing',
|
||||
'My Wonderful Heatmap dashboard'
|
||||
);
|
||||
|
||||
await PageObjects.dashboard.waitForRenderComplete();
|
||||
|
||||
const panelCount = await PageObjects.dashboard.getPanelCount();
|
||||
expect(panelCount).to.eql(1);
|
||||
});
|
||||
|
||||
describe('Capabilities', function capabilitiesTests() {
|
||||
describe('dashboard no-access privileges', () => {
|
||||
before(async () => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue