mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
[Maps] Get number of categories from palette (#66454)
This commit is contained in:
parent
915ff5db50
commit
b2df052952
8 changed files with 225 additions and 60 deletions
|
@ -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
|
||||
|
|
|
@ -20,6 +20,7 @@ export interface IField {
|
|||
isValid(): boolean;
|
||||
getOrdinalFieldMetaRequest(): Promise<unknown>;
|
||||
getCategoricalFieldMetaRequest(size: number): Promise<unknown>;
|
||||
supportsFieldMeta(): boolean;
|
||||
}
|
||||
|
||||
export class AbstractField implements IField {
|
||||
|
|
|
@ -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>
|
||||
`;
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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(), () => {
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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();
|
||||
});
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue