Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion src/plugins/data/common/search/aggs/agg_configs.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ describe('AggConfigs', () => {
ac.createAggConfig(
new AggConfig(ac, {
enabled: true,
type: typesRegistry.get('terms'),
type: typesRegistry.get('terms')!,
params: {},
schema: 'split',
})
Expand Down
30 changes: 24 additions & 6 deletions src/plugins/data/common/search/aggs/agg_types_registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export type AggTypesRegistryStart = ReturnType<AggTypesRegistry['start']>;
export class AggTypesRegistry {
private readonly bucketAggs = new Map();
private readonly metricAggs = new Map();
private readonly legacyAggs = new Map();

setup = () => {
return {
Expand Down Expand Up @@ -44,13 +45,28 @@ export class AggTypesRegistry {
}
this.metricAggs.set(name, type);
},
registerLegacy: <
N extends string,
T extends (deps: AggTypesDependencies) => BucketAggType<any> | MetricAggType<any>
>(
name: N,
type: T
): void => {
if (this.legacyAggs.get(name) || this.legacyAggs.get(name)) {
throw new Error(`Agg has already been registered with name: ${name}`);
}
this.legacyAggs.set(name, type);
},
};
};

start = (aggTypesDependencies: AggTypesDependencies) => {
const initializedAggTypes = new Map();

const getInitializedFromCache = <T = unknown>(key: string, agg: any): T => {
const getInitializedFromCache = <T = unknown>(
key: string,
agg: (aggTypesDependencies: AggTypesDependencies) => T
): T => {
if (initializedAggTypes.has(key)) {
return initializedAggTypes.get(key);
}
Expand All @@ -60,11 +76,13 @@ export class AggTypesRegistry {
};

return {
get: (name: string) =>
getInitializedFromCache<BucketAggType<any> | MetricAggType<any>>(
name,
this.bucketAggs.get(name) || this.metricAggs.get(name)
),
get: (name: string) => {
const agg =
this.bucketAggs.get(name) || this.metricAggs.get(name) || this.legacyAggs.get(name);
return agg
? getInitializedFromCache<BucketAggType<any> | MetricAggType<any>>(name, agg)
: undefined;
},
getAll: () => ({
buckets: Array.from(this.bucketAggs.entries()).map(([key, value]) =>
getInitializedFromCache<BucketAggType<any>>(key, value)
Expand Down
2 changes: 1 addition & 1 deletion src/plugins/data/common/search/aggs/aggs_service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ describe('Aggs service', () => {
test('types registry returns initialized type providers', () => {
service.setup(setupDeps);
const start = service.start(startDeps);
expect(start.types.get('terms').name).toBe('terms');
expect(start.types.get('terms')?.name).toBe('terms');
});
});
});
20 changes: 10 additions & 10 deletions src/plugins/data/common/search/search_source/search_source.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1236,7 +1236,7 @@ describe('SearchSource', () => {

test('doesnt call any post flight requests if disabled', async () => {
const typesRegistry = mockAggTypesRegistry();
typesRegistry.get('avg').postFlightRequest = jest.fn();
typesRegistry.get('avg')!.postFlightRequest = jest.fn();
const ac = getAggConfigs(typesRegistry, false);

searchSource = new SearchSource({}, searchSourceDependencies);
Expand All @@ -1251,12 +1251,12 @@ describe('SearchSource', () => {
expect(fetchSub.error).toHaveBeenCalledTimes(0);
expect(searchSourceDependencies.onResponse).toBeCalledTimes(1);

expect(typesRegistry.get('avg').postFlightRequest).toHaveBeenCalledTimes(0);
expect(typesRegistry.get('avg')!.postFlightRequest).toHaveBeenCalledTimes(0);
});

test('doesnt call any post flight if searchsource has error', async () => {
const typesRegistry = mockAggTypesRegistry();
typesRegistry.get('avg').postFlightRequest = jest.fn();
typesRegistry.get('avg')!.postFlightRequest = jest.fn();
const ac = getAggConfigs(typesRegistry, true);

searchSourceDependencies.search = jest.fn().mockImplementation(() =>
Expand All @@ -1278,12 +1278,12 @@ describe('SearchSource', () => {
expect(fetchSub.complete).toHaveBeenCalledTimes(0);
expect(fetchSub.error).toHaveBeenNthCalledWith(1, 1);

expect(typesRegistry.get('avg').postFlightRequest).toHaveBeenCalledTimes(0);
expect(typesRegistry.get('avg')!.postFlightRequest).toHaveBeenCalledTimes(0);
});

test('calls post flight requests, fires 1 extra response, returns last response', async () => {
const typesRegistry = mockAggTypesRegistry();
typesRegistry.get('avg').postFlightRequest = jest.fn().mockResolvedValue({
typesRegistry.get('avg')!.postFlightRequest = jest.fn().mockResolvedValue({
other: 5,
});

Expand Down Expand Up @@ -1325,12 +1325,12 @@ describe('SearchSource', () => {
expect(fetchSub.complete).toHaveBeenCalledTimes(1);
expect(fetchSub.error).toHaveBeenCalledTimes(0);
expect(resp.rawResponse).toStrictEqual({ other: 5 });
expect(typesRegistry.get('avg').postFlightRequest).toHaveBeenCalledTimes(3);
expect(typesRegistry.get('avg')!.postFlightRequest).toHaveBeenCalledTimes(3);
});

test('calls post flight requests only once, with multiple subs (shareReplay)', async () => {
const typesRegistry = mockAggTypesRegistry();
typesRegistry.get('avg').postFlightRequest = jest.fn().mockResolvedValue({
typesRegistry.get('avg')!.postFlightRequest = jest.fn().mockResolvedValue({
other: 5,
});

Expand Down Expand Up @@ -1366,12 +1366,12 @@ describe('SearchSource', () => {

expect(fetchSub.next).toHaveBeenCalledTimes(3);
expect(fetchSub.complete).toHaveBeenCalledTimes(1);
expect(typesRegistry.get('avg').postFlightRequest).toHaveBeenCalledTimes(1);
expect(typesRegistry.get('avg')!.postFlightRequest).toHaveBeenCalledTimes(1);
});

test('calls post flight requests, handles error', async () => {
const typesRegistry = mockAggTypesRegistry();
typesRegistry.get('avg').postFlightRequest = jest.fn().mockRejectedValue(undefined);
typesRegistry.get('avg')!.postFlightRequest = jest.fn().mockRejectedValue(undefined);
const ac = getAggConfigs(typesRegistry, true);

searchSource = new SearchSource({}, searchSourceDependencies);
Expand All @@ -1385,7 +1385,7 @@ describe('SearchSource', () => {
expect(fetchSub.next).toHaveBeenCalledTimes(2);
expect(fetchSub.complete).toHaveBeenCalledTimes(0);
expect(fetchSub.error).toHaveBeenCalledTimes(1);
expect(typesRegistry.get('avg').postFlightRequest).toHaveBeenCalledTimes(1);
expect(typesRegistry.get('avg')!.postFlightRequest).toHaveBeenCalledTimes(1);
});
});
});
Expand Down
2 changes: 1 addition & 1 deletion src/plugins/data/common/search/tabify/tabify.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ describe('tabifyAggResponse Integration', () => {

describe(`scaleMetricValues performance check${getTitlePostfix()}`, () => {
beforeAll(() => {
typesRegistry.get('count').params.push({
typesRegistry.get('count')!.params.push({
name: 'scaleMetricValues',
default: false,
write: () => {},
Expand Down
2 changes: 1 addition & 1 deletion src/plugins/data/public/search/aggs/aggs_service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ describe('AggsService - public', () => {
service.setup(setupDeps);
const start = service.start(startDeps);

expect(start.types.get('terms').name).toBe('terms');
expect(start.types.get('terms')?.name).toBe('terms');
});

test('registers default agg types', () => {
Expand Down
1 change: 1 addition & 0 deletions src/plugins/data/public/search/aggs/mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ const aggTypeConfigMock = () => ({
export const aggTypesRegistrySetupMock = (): AggTypesRegistrySetup => ({
registerBucket: jest.fn(),
registerMetric: jest.fn(),
registerLegacy: jest.fn(),
});

export const aggTypesRegistryStartMock = (): AggTypesRegistryStart => ({
Expand Down
2 changes: 1 addition & 1 deletion src/plugins/data/server/search/aggs/aggs_service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ describe('AggsService - server', () => {
{} as ElasticsearchClient
);

expect(start.types.get('terms').name).toBe('terms');
expect(start.types.get('terms')?.name).toBe('terms');
});

test('registers default agg types', async () => {
Expand Down
1 change: 1 addition & 0 deletions src/plugins/data/server/search/aggs/mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ const aggTypeConfigMock = () => ({
export const aggTypesRegistrySetupMock = (): AggTypesRegistrySetup => ({
registerBucket: jest.fn(),
registerMetric: jest.fn(),
registerLegacy: jest.fn(),
});

export const aggTypesRegistryStartMock = (): AggTypesRegistryStart => ({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export type LensPagesizeAction = LensEditEvent<typeof LENS_EDIT_PAGESIZE_ACTION>
export type DatatableRenderProps = DatatableProps & {
formatFactory: FormatFactory;
dispatchEvent: ILensInterpreterRenderHandlers['event'];
getType: (name: string) => IAggType;
getType: (name: string) => IAggType | undefined;
renderMode: RenderMode;
paletteService: PaletteRegistry;
uiSettings: IUiSettingsClient;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ export async function getColumnCellValueActions(

export const getDatatableRenderer = (dependencies: {
formatFactory: FormatFactory;
getType: Promise<(name: string) => IAggType>;
getType: Promise<(name: string) => IAggType | undefined>;
paletteService: PaletteRegistry;
uiSettings: IUiSettingsClient;
theme: ThemeServiceStart;
Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/maps/public/legacy_visualizations/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* 2.0.
*/

export { GEOHASH_GRID, getGeoHashBucketAgg } from './tile_map';
export { createRegionMapFn, regionMapRenderer, regionMapVisType } from './region_map';
export { createTileMapFn, tileMapRenderer, tileMapVisType } from './tile_map';
export { isLegacyMap } from './is_legacy_map';
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { KBN_FIELD_TYPES } from '@kbn/field-types';
import { BucketAggType, type IBucketAggConfig } from '@kbn/data-plugin/common';

export const GEOHASH_GRID = 'geohash_grid';

export const getGeoHashBucketAgg = () =>
new BucketAggType<IBucketAggConfig>({
name: GEOHASH_GRID,
expressionName: '',
title: GEOHASH_GRID,
makeLabel: () => GEOHASH_GRID,
params: [
{
name: 'field',
type: 'field',
filterFieldTypes: KBN_FIELD_TYPES.GEO_POINT,
},
],
getRequestAggs(agg) {
return [];
},
});
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* 2.0.
*/

export { GEOHASH_GRID, getGeoHashBucketAgg } from './geo_hash';
export { tileMapVisType } from './tile_map_vis_type';
export { createTileMapFn } from './tile_map_fn';
export { tileMapRenderer } from './tile_map_renderer';
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { Vis } from '@kbn/visualizations-plugin/public';
import { indexPatterns } from '@kbn/data-plugin/public';
import { TileMapVisParams } from './types';
import { title } from './tile_map_vis_type';
import { GEOHASH_GRID } from './geo_hash';

export function extractLayerDescriptorParams(vis: Vis<TileMapVisParams>) {
const params: { [key: string]: any } = {
Expand All @@ -20,7 +21,7 @@ export function extractLayerDescriptorParams(vis: Vis<TileMapVisParams>) {
};

const bucketAggs = vis.data?.aggs?.byType('buckets');
if (bucketAggs?.length && bucketAggs[0].type.dslName === 'geohash_grid') {
if (bucketAggs?.length && bucketAggs[0].type.dslName === GEOHASH_GRID) {
params.geoFieldName = bucketAggs[0].getField()?.name;
} else if (vis.data.indexPattern) {
// attempt to default to first geo point field when geohash is not configured yet
Expand Down
6 changes: 5 additions & 1 deletion x-pack/plugins/maps/public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import type { EmbeddableSetup, EmbeddableStart } from '@kbn/embeddable-plugin/pu
import { CONTEXT_MENU_TRIGGER } from '@kbn/embeddable-plugin/public';
import type { SharePluginSetup, SharePluginStart } from '@kbn/share-plugin/public';
import type { MapsEmsPluginPublicStart } from '@kbn/maps-ems-plugin/public';
import type { DataPublicPluginStart } from '@kbn/data-plugin/public';
import type { DataPublicPluginSetup, DataPublicPluginStart } from '@kbn/data-plugin/public';
import type { UnifiedSearchPublicPluginStart } from '@kbn/unified-search-plugin/public';
import type { LicensingPluginSetup, LicensingPluginStart } from '@kbn/licensing-plugin/public';
import type { FileUploadPluginStart } from '@kbn/file-upload-plugin/public';
Expand All @@ -44,6 +44,8 @@ import type { LensPublicSetup } from '@kbn/lens-plugin/public';
import { ScreenshotModePluginSetup } from '@kbn/screenshot-mode-plugin/public';
import {
createRegionMapFn,
GEOHASH_GRID,
getGeoHashBucketAgg,
regionMapRenderer,
regionMapVisType,
createTileMapFn,
Expand Down Expand Up @@ -81,6 +83,7 @@ import { setupLensChoroplethChart } from './lens';

export interface MapsPluginSetupDependencies {
cloud?: CloudSetup;
data: DataPublicPluginSetup;
expressions: ReturnType<ExpressionsPublicPlugin['setup']>;
inspector: InspectorSetupContract;
home?: HomePublicPluginSetup;
Expand Down Expand Up @@ -201,6 +204,7 @@ export class MapsPlugin
setupLensChoroplethChart(core, plugins.expressions, plugins.lens);

// register wrapper around legacy tile_map and region_map visualizations
plugins.data.search.aggs.types.registerLegacy(GEOHASH_GRID, getGeoHashBucketAgg);
plugins.expressions.registerFunction(createRegionMapFn);
plugins.expressions.registerRenderer(regionMapRenderer);
plugins.visualizations.createBaseVisualization(regionMapVisType);
Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/maps/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
"@kbn/config-schema",
"@kbn/controls-plugin",
"@kbn/shared-ux-router",
"@kbn/field-types",
],
"exclude": [
"target/**/*",
Expand Down
1 change: 1 addition & 0 deletions x-pack/test/functional/apps/maps/group4/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,5 +71,6 @@ export default function ({ loadTestFile, getService }) {
loadTestFile(require.resolve('./discover'));
loadTestFile(require.resolve('./geofile_wizard_auto_open'));
loadTestFile(require.resolve('./lens'));
loadTestFile(require.resolve('./tile_map'));
});
}
35 changes: 35 additions & 0 deletions x-pack/test/functional/apps/maps/group4/tile_map.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import expect from '@kbn/expect';
import { FtrProviderContext } from '../../../ftr_provider_context';

export default function ({ getPageObjects }: FtrProviderContext) {
const PageObjects = getPageObjects(['common', 'visualize', 'lens', 'maps', 'timePicker']);

describe('tile_map visualization', () => {
before(async () => {
await PageObjects.common.navigateToApp('visualize');
await PageObjects.visualize.loadSavedVisualization('Visualization TileMap', {
navigateToVisualize: false,
});
await PageObjects.timePicker.setAbsoluteRange(
PageObjects.timePicker.defaultStartTime,
PageObjects.timePicker.defaultEndTime
);
await PageObjects.maps.waitForLayersToLoad();
});

it('should render tile_map with map embeddable', async () => {
await PageObjects.maps.openLegend();
await PageObjects.maps.waitForLayersToLoad();

expect(await PageObjects.maps.getNumberOfLayers()).to.eql(2);
expect(await PageObjects.maps.doesLayerExist('Visualization TileMap')).to.be(true);
});
});
}
27 changes: 27 additions & 0 deletions x-pack/test/functional/fixtures/kbn_archiver/maps.json
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,33 @@
"version": "WzM2LDJd"
}

{
"attributes": {
"description": "TileMap",
"kibanaSavedObjectMeta": {
"searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"
},
"title": "Visualization TileMap",
"uiStateJSON": "{}",
"version": 1,
"visState": "{\"title\":\"New Visualization\",\"type\":\"tile_map\",\"params\":{\"mapType\":\"Scaled Circle Markers\",\"isDesaturated\":true,\"addTooltip\":true,\"heatMaxZoom\":16,\"heatMinOpacity\":0.1,\"heatRadius\":25,\"heatBlur\":15,\"heatNormalizeData\":true,\"wms\":{\"enabled\":false,\"url\":\"https://basemap.nationalmap.gov/arcgis/services/USGSTopo/MapServer/WMSServer\",\"options\":{\"version\":\"1.3.0\",\"layers\":\"0\",\"format\":\"image/png\",\"transparent\":true,\"attribution\":\"Maps provided by USGS\",\"styles\":\"\"}}},\"aggs\":[{\"id\":\"1\",\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"type\":\"geohash_grid\",\"schema\":\"segment\",\"params\":{\"field\":\"geo.coordinates\",\"autoPrecision\":true,\"precision\":2}}],\"listeners\":{}}"
},
"coreMigrationVersion": "8.4.0",
"id": "Visualization-TileMap",
"migrationVersion": {
"visualization": "8.3.0"
},
"references": [
{
"id": "c698b940-e149-11e8-a35a-370a8516603a",
"name": "kibanaSavedObjectMeta.searchSourceJSON.index",
"type": "index-pattern"
}
],
"type": "visualization",
"version": "WzE1LDJd"
}

{
"attributes": {
"description": "",
Expand Down