[Maps] Get number of categories from palette (#66454)

This commit is contained in:
Thomas Neirynck 2020-05-15 14:06:06 -04:00 committed by GitHub
parent 915ff5db50
commit b2df052952
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 225 additions and 60 deletions

View file

@ -115,6 +115,7 @@ export type JoinDescriptor = {
// todo : this union type is incompatible with dynamic extensibility of sources.
// Reconsider using SourceDescriptor in type signatures for top-level classes
export type SourceDescriptor =
| AbstractSourceDescriptor
| XYZTMSSourceDescriptor
| WMSSourceDescriptor
| KibanaTilemapSourceDescriptor

View file

@ -20,6 +20,7 @@ export interface IField {
isValid(): boolean;
getOrdinalFieldMetaRequest(): Promise<unknown>;
getCategoricalFieldMetaRequest(size: number): Promise<unknown>;
supportsFieldMeta(): boolean;
}
export class AbstractField implements IField {

View file

@ -0,0 +1,78 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Should render categorical legend with breaks 1`] = `
<div>
<EuiSpacer
size="s"
/>
<EuiFlexGroup
direction="column"
gutterSize="none"
>
<Category
color="grey"
isLinesOnly={false}
isPointsOnly={true}
key="US"
label="US_format"
styleName="icon"
symbolId="circle"
/>
<Category
color="grey"
isLinesOnly={false}
isPointsOnly={true}
key="CN"
label="CN_format"
styleName="icon"
symbolId="marker"
/>
<Category
color="grey"
isLinesOnly={false}
isPointsOnly={true}
key="fallbackCategory"
label={
<EuiTextColor
color="secondary"
>
Other
</EuiTextColor>
}
styleName="icon"
symbolId="square"
/>
</EuiFlexGroup>
<EuiFlexGroup
gutterSize="xs"
justifyContent="spaceAround"
>
<EuiFlexItem
grow={false}
>
<EuiToolTip
content="foobar_label"
delay="regular"
position="top"
title="Icon"
>
<EuiText
className="eui-textTruncate"
size="xs"
style={
Object {
"maxWidth": "180px",
}
}
>
<small>
<strong>
foobar_label
</strong>
</small>
</EuiText>
</EuiToolTip>
</EuiFlexItem>
</EuiFlexGroup>
</div>
`;

View file

@ -0,0 +1,75 @@
/*
* 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-next-line max-classes-per-file
import { FIELD_ORIGIN } from '../../../../../../common/constants';
import { StyleMeta } from '../../style_meta';
import {
CategoryFieldMeta,
GeometryTypes,
RangeFieldMeta,
StyleMetaDescriptor,
} from '../../../../../../common/descriptor_types';
import { AbstractField, IField } from '../../../../fields/field';
class MockField extends AbstractField {
async getLabel(): Promise<string> {
return this.getName() + '_label';
}
supportsFieldMeta(): boolean {
return true;
}
}
export const mockField: IField = new MockField({
fieldName: 'foobar',
origin: FIELD_ORIGIN.SOURCE,
});
class MockStyle {
getStyleMeta(): StyleMeta {
const geomTypes: GeometryTypes = {
isPointsOnly: false,
isLinesOnly: false,
isPolygonsOnly: false,
};
const rangeFieldMeta: RangeFieldMeta = { min: 0, max: 100, delta: 100 };
const catFieldMeta: CategoryFieldMeta = {
categories: [
{
key: 'US',
count: 10,
},
{
key: 'CN',
count: 8,
},
],
};
const styleMetaDescriptor: StyleMetaDescriptor = {
geometryTypes: geomTypes,
fieldMeta: {
foobar: {
range: rangeFieldMeta,
categories: catFieldMeta,
},
},
};
return new StyleMeta(styleMetaDescriptor);
}
}
export class MockLayer {
getStyle() {
return new MockStyle();
}
getDataRequest() {
return null;
}
}

View file

@ -15,65 +15,8 @@ import React from 'react';
import { shallow } from 'enzyme';
import { DynamicColorProperty } from './dynamic_color_property';
import { StyleMeta } from '../style_meta';
import { COLOR_MAP_TYPE, FIELD_ORIGIN, VECTOR_STYLES } from '../../../../../common/constants';
const mockField = {
async getLabel() {
return 'foobar_label';
},
getName() {
return 'foobar';
},
getRootName() {
return 'foobar';
},
getOrigin() {
return FIELD_ORIGIN.SOURCE;
},
supportsFieldMeta() {
return true;
},
};
class MockStyle {
getStyleMeta() {
return new StyleMeta({
geometryTypes: {
isPointsOnly: false,
isLinesOnly: false,
isPolygonsOnly: false,
},
fieldMeta: {
foobar: {
range: { min: 0, max: 100 },
categories: {
categories: [
{
key: 'US',
count: 10,
},
{
key: 'CN',
count: 8,
},
],
},
},
},
});
}
}
class MockLayer {
getStyle() {
return new MockStyle();
}
getDataRequest() {
return null;
}
}
import { COLOR_MAP_TYPE, VECTOR_STYLES } from '../../../../../common/constants';
import { mockField, MockLayer } from './__tests__/test_util';
const makeProperty = (options, field = mockField) => {
return new DynamicColorProperty(options, VECTOR_STYLES.LINE_COLOR, field, new MockLayer(), () => {

View file

@ -29,6 +29,11 @@ export class DynamicIconProperty extends DynamicStyleProperty {
return true;
}
getNumberOfCategories() {
const palette = getIconPalette(this._options.iconPaletteId);
return palette ? palette.length : 0;
}
syncIconWithMb(symbolLayerId, mbMap, iconPixelSize) {
if (this._isIconDynamicConfigComplete()) {
mbMap.setLayoutProperty(

View file

@ -0,0 +1,61 @@
/*
* 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-next-line max-classes-per-file
import { shallow } from 'enzyme';
jest.mock('ui/new_platform');
jest.mock('../components/vector_style_editor', () => ({
VectorStyleEditor: () => {
return <div>mockVectorStyleEditor</div>;
},
}));
import React from 'react';
import { VECTOR_STYLES } from '../../../../../common/constants';
// @ts-ignore
import { DynamicIconProperty } from './dynamic_icon_property';
import { mockField, MockLayer } from './__tests__/test_util';
import { IconDynamicOptions } from '../../../../../common/descriptor_types';
import { IField } from '../../../fields/field';
const makeProperty = (options: Partial<IconDynamicOptions>, field: IField = mockField) => {
return new DynamicIconProperty(
{ ...options, fieldMetaOptions: { isEnabled: false } },
VECTOR_STYLES.ICON,
field,
new MockLayer(),
() => {
return (x: string) => x + '_format';
}
);
};
describe('DynamicIconProperty', () => {
it('should derive category number from palettes', async () => {
const filled = makeProperty({
iconPaletteId: 'filledShapes',
});
expect(filled.getNumberOfCategories()).toEqual(6);
const hollow = makeProperty({
iconPaletteId: 'hollowShapes',
});
expect(hollow.getNumberOfCategories()).toEqual(5);
});
});
test('Should render categorical legend with breaks', async () => {
const iconStyle = makeProperty({
iconPaletteId: 'filledShapes',
});
const legendRow = iconStyle.renderLegendDetailRow({ isPointsOnly: true, isLinesOnly: false });
const component = shallow(legendRow);
await new Promise(resolve => process.nextTick(resolve));
component.update();
expect(component).toMatchSnapshot();
});

View file

@ -148,7 +148,8 @@ export class DynamicStyleProperty extends AbstractStyleProperty {
if (this.isOrdinal()) {
return this._field.getOrdinalFieldMetaRequest();
} else if (this.isCategorical()) {
return this._field.getCategoricalFieldMetaRequest(this.getNumberOfCategories());
const numberOfCategories = this.getNumberOfCategories();
return this._field.getCategoricalFieldMetaRequest(numberOfCategories);
} else {
return null;
}