Skip to content

Commit

Permalink
[maps] fix data driven style properties not working when cloned layer…
Browse files Browse the repository at this point in the history
… contains joins (#73124)

* [maps] fix data driven style properties not working when cloned layer contains joins

* tslint

* handle case where metrics is not provided

* tslint
  • Loading branch information
nreese authored Jul 23, 2020
1 parent aec1892 commit b5c0d5f
Show file tree
Hide file tree
Showing 3 changed files with 175 additions and 4 deletions.
2 changes: 1 addition & 1 deletion x-pack/plugins/maps/common/descriptor_types/sources.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ export type LayerDescriptor = {
__trackedLayerDescriptor?: LayerDescriptor;
alpha?: number;
id: string;
joins?: JoinDescriptor[];
label?: string | null;
areLabelsOnTop?: boolean;
minZoom?: number;
Expand All @@ -180,7 +181,6 @@ export type LayerDescriptor = {
};

export type VectorLayerDescriptor = LayerDescriptor & {
joins?: JoinDescriptor[];
style?: VectorStyleDescriptor;
};

Expand Down
128 changes: 128 additions & 0 deletions x-pack/plugins/maps/public/classes/layers/layer.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
/* eslint-disable max-classes-per-file */

import { AbstractLayer } from './layer';
import { ISource } from '../sources/source';
import { IStyle } from '../styles/style';
import { AGG_TYPE, FIELD_ORIGIN, LAYER_STYLE_TYPE, VECTOR_STYLES } from '../../../common/constants';
import { ESTermSourceDescriptor, VectorStyleDescriptor } from '../../../common/descriptor_types';
import { getDefaultDynamicProperties } from '../styles/vector/vector_style_defaults';

jest.mock('uuid/v4', () => {
return function () {
return '12345';
};
});

class MockLayer extends AbstractLayer {}

class MockSource {
cloneDescriptor() {
return {};
}

getDisplayName() {
return 'mySource';
}
}

class MockStyle {}

describe('cloneDescriptor', () => {
describe('with joins', () => {
const styleDescriptor = {
type: LAYER_STYLE_TYPE.VECTOR,
properties: {
...getDefaultDynamicProperties(),
},
} as VectorStyleDescriptor;
// @ts-expect-error
styleDescriptor.properties[VECTOR_STYLES.FILL_COLOR].options.field = {
name: '__kbnjoin__count__557d0f15',
origin: FIELD_ORIGIN.JOIN,
};
// @ts-expect-error
styleDescriptor.properties[VECTOR_STYLES.LINE_COLOR].options.field = {
name: 'bytes',
origin: FIELD_ORIGIN.SOURCE,
};
// @ts-expect-error
styleDescriptor.properties[VECTOR_STYLES.LABEL_BORDER_COLOR].options.field = {
name: '__kbnjoin__count__6666666666',
origin: FIELD_ORIGIN.JOIN,
};

test('Should update data driven styling properties using join fields', async () => {
const layerDescriptor = AbstractLayer.createDescriptor({
style: styleDescriptor,
joins: [
{
leftField: 'iso2',
right: {
id: '557d0f15',
indexPatternId: 'myIndexPattern',
indexPatternTitle: 'logs-*',
metrics: [{ type: AGG_TYPE.COUNT }],
term: 'myTermField',
type: 'joinSource',
},
},
],
});
const layer = new MockLayer({
layerDescriptor,
source: (new MockSource() as unknown) as ISource,
style: (new MockStyle() as unknown) as IStyle,
});
const clonedDescriptor = await layer.cloneDescriptor();
const clonedStyleProps = (clonedDescriptor.style as VectorStyleDescriptor).properties;
// Should update style field belonging to join
// @ts-expect-error
expect(clonedStyleProps[VECTOR_STYLES.FILL_COLOR].options.field.name).toEqual(
'__kbnjoin__count__12345'
);
// Should not update style field belonging to source
// @ts-expect-error
expect(clonedStyleProps[VECTOR_STYLES.LINE_COLOR].options.field.name).toEqual('bytes');
// Should not update style feild belonging to different join
// @ts-expect-error
expect(clonedStyleProps[VECTOR_STYLES.LABEL_BORDER_COLOR].options.field.name).toEqual(
'__kbnjoin__count__6666666666'
);
});

test('Should update data driven styling properties using join fields when metrics are not provided', async () => {
const layerDescriptor = AbstractLayer.createDescriptor({
style: styleDescriptor,
joins: [
{
leftField: 'iso2',
right: ({
id: '557d0f15',
indexPatternId: 'myIndexPattern',
indexPatternTitle: 'logs-*',
term: 'myTermField',
type: 'joinSource',
} as unknown) as ESTermSourceDescriptor,
},
],
});
const layer = new MockLayer({
layerDescriptor,
source: (new MockSource() as unknown) as ISource,
style: (new MockStyle() as unknown) as IStyle,
});
const clonedDescriptor = await layer.cloneDescriptor();
const clonedStyleProps = (clonedDescriptor.style as VectorStyleDescriptor).properties;
// Should update style field belonging to join
// @ts-expect-error
expect(clonedStyleProps[VECTOR_STYLES.FILL_COLOR].options.field.name).toEqual(
'__kbnjoin__count__12345'
);
});
});
});
49 changes: 46 additions & 3 deletions x-pack/plugins/maps/public/classes/layers/layer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,26 @@ import { i18n } from '@kbn/i18n';
import { FeatureCollection } from 'geojson';
import { DataRequest } from '../util/data_request';
import {
AGG_TYPE,
FIELD_ORIGIN,
MAX_ZOOM,
MB_SOURCE_ID_LAYER_ID_PREFIX_DELIMITER,
MIN_ZOOM,
SOURCE_DATA_REQUEST_ID,
STYLE_TYPE,
} from '../../../common/constants';
import { copyPersistentState } from '../../reducers/util';
import { LayerDescriptor, MapExtent, StyleDescriptor } from '../../../common/descriptor_types';
import {
AggDescriptor,
JoinDescriptor,
LayerDescriptor,
MapExtent,
StyleDescriptor,
} from '../../../common/descriptor_types';
import { Attribution, ImmutableSourceProperty, ISource, SourceEditorArgs } from '../sources/source';
import { DataRequestContext } from '../../actions';
import { IStyle } from '../styles/style';
import { getJoinAggKey } from '../../../common/get_agg_key';

export interface ILayer {
getBounds(dataRequestContext: DataRequestContext): Promise<MapExtent | null>;
Expand Down Expand Up @@ -157,10 +167,43 @@ export class AbstractLayer implements ILayer {
clonedDescriptor.sourceDescriptor = this.getSource().cloneDescriptor();

if (clonedDescriptor.joins) {
// @ts-expect-error
clonedDescriptor.joins.forEach((joinDescriptor) => {
clonedDescriptor.joins.forEach((joinDescriptor: JoinDescriptor) => {
const originalJoinId = joinDescriptor.right.id!;

// right.id is uuid used to track requests in inspector
joinDescriptor.right.id = uuid();

// Update all data driven styling properties using join fields
if (clonedDescriptor.style && 'properties' in clonedDescriptor.style) {
const metrics =
joinDescriptor.right.metrics && joinDescriptor.right.metrics.length
? joinDescriptor.right.metrics
: [{ type: AGG_TYPE.COUNT }];
metrics.forEach((metricsDescriptor: AggDescriptor) => {
const originalJoinKey = getJoinAggKey({
aggType: metricsDescriptor.type,
aggFieldName: metricsDescriptor.field ? metricsDescriptor.field : '',
rightSourceId: originalJoinId,
});
const newJoinKey = getJoinAggKey({
aggType: metricsDescriptor.type,
aggFieldName: metricsDescriptor.field ? metricsDescriptor.field : '',
rightSourceId: joinDescriptor.right.id!,
});

Object.keys(clonedDescriptor.style.properties).forEach((key) => {
const styleProp = clonedDescriptor.style.properties[key];
if (
styleProp.type === STYLE_TYPE.DYNAMIC &&
styleProp.options.field &&
styleProp.options.field.origin === FIELD_ORIGIN.JOIN &&
styleProp.options.field.name === originalJoinKey
) {
styleProp.options.field.name = newJoinKey;
}
});
});
}
});
}
return clonedDescriptor;
Expand Down

0 comments on commit b5c0d5f

Please sign in to comment.