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

[maps] Lens choropleth chart #126819

Merged
merged 52 commits into from
Mar 17, 2022
Merged
Show file tree
Hide file tree
Changes from 47 commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
f2f3559
register expression
nreese Feb 22, 2022
02b00c9
renderer
nreese Feb 22, 2022
4959058
Merge branch 'main' of github.com:elastic/kibana into lens_choropleth…
nreese Feb 23, 2022
b60c288
register visualization
nreese Feb 23, 2022
b76e0da
tslint
nreese Feb 24, 2022
3c5b2af
Merge branch 'main' of github.com:elastic/kibana into lens_choropleth…
nreese Feb 24, 2022
08eaa00
clean up
nreese Feb 24, 2022
a84f571
refactor
nreese Feb 24, 2022
78fa318
Merge branch 'main' of github.com:elastic/kibana into lens_choropleth…
nreese Feb 28, 2022
1550021
auto suggest
nreese Feb 28, 2022
e9cca48
Merge branch 'main' of github.com:elastic/kibana into lens_choropleth…
nreese Mar 2, 2022
7ec795d
update chart on change
nreese Mar 2, 2022
dd9431b
fix line color
nreese Mar 2, 2022
32ddd37
fix accessor labels
nreese Mar 2, 2022
3dda6a0
remove console.logs
nreese Mar 2, 2022
fc99247
use valueAccessor label in layer label
nreese Mar 3, 2022
1f0d4b9
region key editor
nreese Mar 3, 2022
fe1ad61
fix suggestions
nreese Mar 3, 2022
99a61d9
eslint
nreese Mar 3, 2022
93c4d54
revert unneeded change
nreese Mar 3, 2022
55e704a
fix i18n and clearLayer
nreese Mar 3, 2022
6621700
fix jest test
nreese Mar 3, 2022
fbe4d3a
tslint
nreese Mar 3, 2022
bb20197
fix ems_autosuggest jest test
nreese Mar 4, 2022
8318b0e
lower suggestions score after first match
nreese Mar 4, 2022
7cbc903
functional test
nreese Mar 4, 2022
f241fbe
let lens render preview icon by not returning an expression
nreese Mar 4, 2022
9b43685
functional test tslint
nreese Mar 4, 2022
e17b3d0
avoid multiple suggestions with multiple layers
nreese Mar 7, 2022
d32b03c
Merge branch 'main' into lens_choropleth_chart
kibanamachine Mar 7, 2022
621559e
suggestion cleanup
nreese Mar 7, 2022
9060147
Merge branch 'lens_choropleth_chart' of github.com:nreese/kibana into…
nreese Mar 7, 2022
2240d72
Merge branch 'main' into lens_choropleth_chart
kibanamachine Mar 8, 2022
671b176
review feedback
nreese Mar 8, 2022
49089ef
merge with main
nreese Mar 9, 2022
2b2aa0c
rename Choropleth to Region map
nreese Mar 9, 2022
e695300
Merge branch 'main' into lens_choropleth_chart
kibanamachine Mar 10, 2022
8f5cfc5
review feedback
nreese Mar 10, 2022
4b7427f
Merge branch 'main' into lens_choropleth_chart
kibanamachine Mar 10, 2022
23c52cd
merge with main
nreese Mar 14, 2022
412d4f6
remove merge conflicts
nreese Mar 14, 2022
ce57a9c
Merge branch 'main' into lens_choropleth_chart
kibanamachine Mar 15, 2022
e95e457
revert change to x-pack/plugins/lens/public/editor_frame_service/edit…
nreese Mar 15, 2022
8eb1ceb
Merge branch 'main' into lens_choropleth_chart
kibanamachine Mar 15, 2022
6019eb6
fix functional test
nreese Mar 15, 2022
00a25b1
Merge branch 'main' into lens_choropleth_chart
kibanamachine Mar 15, 2022
497b462
Merge branch 'main' into lens_choropleth_chart
kibanamachine Mar 17, 2022
dfbaf5b
log table data
nreese Mar 17, 2022
b714030
Merge branch 'main' into lens_choropleth_chart
kibanamachine Mar 17, 2022
91467e6
expose common/expressions as extra public dir
nreese Mar 17, 2022
cc7c419
Merge branch 'lens_choropleth_chart' of github.com:nreese/kibana into…
nreese Mar 17, 2022
5b6b26c
revert log table data
nreese Mar 17, 2022
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
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,8 @@ export function getSuggestions({
currentVisualizationState,
subVisualizationId,
palette,
visualizeTriggerFieldContext && 'isVisualizeAction' in visualizeTriggerFieldContext
visualizeTriggerFieldContext && 'isVisualizeAction' in visualizeTriggerFieldContext,
activeData
);
});
})
Expand Down Expand Up @@ -207,7 +208,8 @@ function getVisualizationSuggestions(
currentVisualizationState: unknown,
subVisualizationId?: string,
mainPalette?: PaletteOutput,
isFromContext?: boolean
isFromContext?: boolean,
activeData?: Record<string, Datatable>
) {
return visualization
.getSuggestions({
Expand All @@ -217,6 +219,7 @@ function getVisualizationSuggestions(
subVisualizationId,
mainPalette,
isFromContext,
activeData,
})
.map(({ state, ...visualizationSuggestion }) => ({
...visualizationSuggestion,
Expand Down
10 changes: 9 additions & 1 deletion x-pack/plugins/lens/public/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,15 @@ export type {
TypedLensByValueInput,
} from './embeddable/embeddable_component';
export type { XYState } from './xy_visualization/types';
export type { DataType, OperationMetadata, Visualization } from './types';
export type {
DatasourcePublicAPI,
DataType,
OperationMetadata,
SuggestionRequest,
TableSuggestion,
Visualization,
VisualizationSuggestion,
} from './types';
export type {
AxesSettingsConfig,
XYLayerConfig,
Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/lens/public/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -643,6 +643,7 @@ export interface SuggestionRequest<T = unknown> {
* Different suggestions can be generated for each subtype of the visualization
*/
subVisualizationId?: string;
activeData?: Record<string, Datatable>;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ export type TiledSingleLayerVectorSourceDescriptor = AbstractSourceDescriptor &

export type InlineFieldDescriptor = {
name: string;
label?: string;
type: 'string' | 'number';
};

Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/maps/common/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export {
MAX_ZOOM,
MIN_ZOOM,
VECTOR_SHAPE_TYPE,
VECTOR_STYLES,
} from './constants';

export type { FieldFormatter } from './constants';
Expand Down
2 changes: 2 additions & 0 deletions x-pack/plugins/maps/kibana.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@
"kibanaVersion": "kibana",
"configPath": ["xpack", "maps"],
"requiredPlugins": [
"lens",
nreese marked this conversation as resolved.
Show resolved Hide resolved
"licensing",
"features",
"inspector",
"data",
"fieldFormats",
"fileUpload",
"uiActions",
"navigation",
Expand Down
25 changes: 24 additions & 1 deletion x-pack/plugins/maps/public/actions/layer_actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
getLayerListRaw,
getMapColors,
getMapReady,
getMapSettings,
getSelectedLayerId,
} from '../selectors/map_selectors';
import { FLYOUT_STATE } from '../reducers/ui';
Expand All @@ -35,12 +36,18 @@ import {
SET_SELECTED_LAYER,
SET_WAITING_FOR_READY_HIDDEN_LAYERS,
TRACK_CURRENT_LAYER_STATE,
UPDATE_LAYER,
UPDATE_LAYER_ORDER,
UPDATE_LAYER_PROP,
UPDATE_LAYER_STYLE,
UPDATE_SOURCE_PROP,
} from './map_action_constants';
import { clearDataRequests, syncDataForLayerId, updateStyleMeta } from './data_request_actions';
import {
autoFitToBounds,
clearDataRequests,
syncDataForLayerId,
updateStyleMeta,
} from './data_request_actions';
import { updateTooltipStateForLayer } from './tooltip_actions';
import {
Attribution,
Expand Down Expand Up @@ -117,6 +124,22 @@ export function replaceLayerList(newLayerList: LayerDescriptor[]) {
};
}

export function updateLayerById(layerDescriptor: LayerDescriptor) {
return async (
dispatch: ThunkDispatch<MapStoreState, void, AnyAction>,
getState: () => MapStoreState
) => {
dispatch({
type: UPDATE_LAYER,
layer: layerDescriptor,
});
await dispatch(syncDataForLayerId(layerDescriptor.id, false));
if (getMapSettings(getState()).autoFitToDataBounds) {
dispatch(autoFitToBounds());
}
};
}

export function cloneLayer(layerId: string) {
return async (
dispatch: ThunkDispatch<MapStoreState, void, AnyAction>,
Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/maps/public/actions/map_action_constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export const LAYER_DATA_LOAD_ERROR = 'LAYER_DATA_LOAD_ERROR';
export const UPDATE_SOURCE_DATA_REQUEST = 'UPDATE_SOURCE_DATA_REQUEST';
export const SET_JOINS = 'SET_JOINS';
export const SET_QUERY = 'SET_QUERY';
export const UPDATE_LAYER = 'UPDATE_LAYER';
export const UPDATE_LAYER_PROP = 'UPDATE_LAYER_PROP';
export const UPDATE_LAYER_STYLE = 'UPDATE_LAYER_STYLE';
export const SET_LAYER_STYLE_META = 'SET_LAYER_STYLE_META';
Expand Down
6 changes: 5 additions & 1 deletion x-pack/plugins/maps/public/classes/fields/inline_field.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,25 @@ import { IField, AbstractField } from './field';
import { IVectorSource } from '../sources/vector_source';

export class InlineField<T extends IVectorSource> extends AbstractField implements IField {
private readonly _label?: string;
private readonly _source: T;
private readonly _dataType: string;

constructor({
fieldName,
label,
source,
origin,
dataType,
}: {
fieldName: string;
label?: string;
source: T;
origin: FIELD_ORIGIN;
dataType: string;
}) {
super({ fieldName, origin });
this._label = label;
this._source = source;
this._dataType = dataType;
}
Expand All @@ -42,7 +46,7 @@ export class InlineField<T extends IVectorSource> extends AbstractField implemen
}

async getLabel(): Promise<string> {
return this.getName();
return this._label ? this._label : this.getName();
}

async getDataType(): Promise<string> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ export class GeoJsonVectorLayer extends AbstractVectorLayer {
}

const joinStates = await this._syncJoins(syncContext, style);
performInnerJoins(
await performInnerJoins(
sourceResult,
joinStates,
syncContext.updateSourceData,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,8 @@
import sinon from 'sinon';
import _ from 'lodash';
import { FeatureCollection } from 'geojson';
import { ESTermSourceDescriptor } from '../../../../../common/descriptor_types';
import {
AGG_TYPE,
FEATURE_VISIBLE_PROPERTY_NAME,
SOURCE_TYPES,
} from '../../../../../common/constants';
import { TableSourceDescriptor } from '../../../../../common/descriptor_types';
import { FEATURE_VISIBLE_PROPERTY_NAME, SOURCE_TYPES } from '../../../../../common/constants';
import { performInnerJoins } from './perform_inner_joins';
import { InnerJoin } from '../../../joins/inner_join';
import { IVectorSource } from '../../../sources/vector_source';
Expand Down Expand Up @@ -53,18 +49,21 @@ const featureCollection = {
const joinDescriptor = {
leftField: LEFT_FIELD,
right: {
applyGlobalQuery: true,
applyGlobalTime: true,
id: 'd3625663-5b34-4d50-a784-0d743f676a0c',
indexPatternId: 'myIndexPattern',
metrics: [
__rows: [],
__columns: [
{
type: AGG_TYPE.COUNT,
name: 'rightKey',
type: 'string',
},
{
name: COUNT_PROPERTY_NAME,
type: 'number',
},
],
term: 'rightKey',
type: SOURCE_TYPES.ES_TERM_SOURCE,
} as ESTermSourceDescriptor,
type: SOURCE_TYPES.TABLE_SOURCE,
} as TableSourceDescriptor,
};
const mockVectorSource = {
getInspectorAdapters: () => {
Expand All @@ -75,18 +74,21 @@ const mockVectorSource = {
getName: () => {
return LEFT_FIELD;
},
} as IField;
getLabel: () => {
return LEFT_FIELD;
},
} as unknown as IField;
},
} as unknown as IVectorSource;
const innerJoin = new InnerJoin(joinDescriptor, mockVectorSource);
const propertiesMap = new Map<string, Record<string | number, unknown>>();
propertiesMap.set('alpha', { [COUNT_PROPERTY_NAME]: 1 });

test('should skip join when no state has changed', () => {
test('should skip join when no state has changed', async () => {
const updateSourceData = sinon.spy();
const onJoinError = sinon.spy();

performInnerJoins(
await performInnerJoins(
{
refreshed: false,
featureCollection: _.cloneDeep(featureCollection) as FeatureCollection,
Expand All @@ -105,11 +107,11 @@ test('should skip join when no state has changed', () => {
expect(onJoinError.notCalled);
});

test('should perform join when features change', () => {
test('should perform join when features change', async () => {
const updateSourceData = sinon.spy();
const onJoinError = sinon.spy();

performInnerJoins(
await performInnerJoins(
{
refreshed: true,
featureCollection: _.cloneDeep(featureCollection) as FeatureCollection,
Expand All @@ -128,11 +130,11 @@ test('should perform join when features change', () => {
expect(onJoinError.notCalled);
});

test('should perform join when join state changes', () => {
test('should perform join when join state changes', async () => {
const updateSourceData = sinon.spy();
const onJoinError = sinon.spy();

performInnerJoins(
await performInnerJoins(
{
refreshed: false,
featureCollection: _.cloneDeep(featureCollection) as FeatureCollection,
Expand All @@ -151,11 +153,11 @@ test('should perform join when join state changes', () => {
expect(onJoinError.notCalled);
});

test('should call updateSourceData with feature collection with updated feature visibility and join properties', () => {
test('should call updateSourceData with feature collection with updated feature visibility and join properties', async () => {
const updateSourceData = sinon.spy();
const onJoinError = sinon.spy();

performInnerJoins(
await performInnerJoins(
{
refreshed: true,
featureCollection: _.cloneDeep(featureCollection) as FeatureCollection,
Expand Down Expand Up @@ -204,11 +206,11 @@ test('should call updateSourceData with feature collection with updated feature
expect(onJoinError.notCalled);
});

test('should call updateSourceData when no results returned from terms aggregation', () => {
test('should call updateSourceData when no results returned from terms aggregation', async () => {
const updateSourceData = sinon.spy();
const onJoinError = sinon.spy();

performInnerJoins(
await performInnerJoins(
{
refreshed: false,
featureCollection: _.cloneDeep(featureCollection) as FeatureCollection,
Expand Down Expand Up @@ -256,15 +258,15 @@ test('should call updateSourceData when no results returned from terms aggregati
expect(onJoinError.notCalled);
});

test('should call onJoinError when there are no matching features', () => {
test('should call onJoinError when there are no matching features', async () => {
const updateSourceData = sinon.spy();
const onJoinError = sinon.spy();

// instead of returning military alphabet like "alpha" or "bravo", mismatched key returns numbers, like '1'
const propertiesMapFromMismatchedKey = new Map<string, Record<string | number, unknown>>();
propertiesMapFromMismatchedKey.set('1', { [COUNT_PROPERTY_NAME]: 1 });

performInnerJoins(
await performInnerJoins(
{
refreshed: false,
featureCollection: _.cloneDeep(featureCollection) as FeatureCollection,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export interface JoinState {
propertiesMap?: PropertiesMap;
}

export function performInnerJoins(
export async function performInnerJoins(
sourceResult: SourceResult,
joinStates: JoinState[],
updateSourceData: DataRequestContext['updateSourceData'],
Expand Down Expand Up @@ -102,7 +102,11 @@ export function performInnerJoins(
}

const joinStatus = joinStatusesWithoutAnyMatches[0];
const leftFieldName = joinStatus.joinState.join.getLeftField().getName();
const leftFieldName = await joinStatus.joinState.join.getLeftField().getLabel();
const rightFieldName = await joinStatus.joinState.join
.getRightJoinSource()
.getTermField()
.getLabel();
const reason =
joinStatus.keys.length === 0
? i18n.translate('xpack.maps.vectorLayer.joinError.noLeftFieldValuesMsg', {
Expand All @@ -114,10 +118,7 @@ export function performInnerJoins(
values: {
leftFieldName,
leftFieldValues: prettyPrintArray(joinStatus.keys),
rightFieldName: joinStatus.joinState.join
.getRightJoinSource()
.getTermField()
.getName(),
rightFieldName,
rightFieldValues: prettyPrintArray(
Array.from(joinStatus.joinState.propertiesMap!.keys())
),
Expand Down
Loading