Skip to content

Commit 070fac2

Browse files
Merge branch 'deprecation_message' of https://github.com/nreese/kibana into maps/es_mvt_grids
2 parents 9fce05d + 45d587b commit 070fac2

File tree

14 files changed

+535
-71
lines changed

14 files changed

+535
-71
lines changed

src/plugins/tile_map/kibana.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
"expressions",
1111
"mapsLegacy",
1212
"kibanaLegacy",
13-
"data"
13+
"data",
14+
"share"
1415
],
1516
"requiredBundles": [
1617
"kibanaUtils",
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
/*
2+
* Licensed to Elasticsearch B.V. under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch B.V. licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
import React from 'react';
21+
import { EuiButton, EuiLink } from '@elastic/eui';
22+
import { FormattedMessage } from '@kbn/i18n/react';
23+
import { getCoreService, getQueryService, getShareService } from './services';
24+
import { indexPatterns } from '../../data/public';
25+
import { Vis } from '../../visualizations/public';
26+
27+
export function getDeprecationMessage(vis: Vis) {
28+
const mapsTileMapUrlGenerator = getShareService().urlGenerators.getUrlGenerator(
29+
'MAPS_APP_TILE_MAP_URL_GENERATOR'
30+
);
31+
32+
let action;
33+
if (!mapsTileMapUrlGenerator) {
34+
action = (
35+
<FormattedMessage
36+
id="tileMap.vis.defaultDistributionMessage"
37+
defaultMessage="To get Maps, upgrade to the {defaultDistribution} of Elasticsearch and Kibana."
38+
values={{
39+
defaultDistribution: (
40+
<EuiLink
41+
color="accent"
42+
external
43+
href="https://www.elastic.co/downloads/kibana"
44+
target="_blank"
45+
>
46+
default distribution
47+
</EuiLink>
48+
),
49+
}}
50+
/>
51+
);
52+
} else {
53+
action = (
54+
<div>
55+
<EuiButton
56+
onClick={async (e: React.MouseEvent<HTMLButtonElement>) => {
57+
e.preventDefault();
58+
59+
const query = getQueryService();
60+
const createUrlParams = {
61+
title: vis.title,
62+
mapType: vis.params.mapType,
63+
colorSchema: vis.params.colorSchema,
64+
indexPatternId: vis.data.indexPattern?.id,
65+
metricAgg: 'count',
66+
filters: query.filterManager.getFilters(),
67+
query: query.queryString.getQuery(),
68+
timeRange: query.timefilter.timefilter.getTime(),
69+
};
70+
71+
const bucketAggs = vis.data?.aggs?.byType('buckets');
72+
if (bucketAggs?.length && bucketAggs[0].type.dslName === 'geohash_grid') {
73+
createUrlParams.geoFieldName = bucketAggs[0].getField()?.name;
74+
} else if (vis.data.indexPattern) {
75+
// attempt to default to first geo point field when geohash is not configured yet
76+
const geoField = vis.data.indexPattern.fields.find((field) => {
77+
return (
78+
!indexPatterns.isNestedField(field) &&
79+
field.aggregatable &&
80+
field.type === 'geo_point'
81+
);
82+
});
83+
if (geoField) {
84+
createUrlParams.geoFieldName = geoField.name;
85+
}
86+
}
87+
88+
const metricAggs = vis.data?.aggs?.byType('metrics');
89+
if (metricAggs?.length) {
90+
createUrlParams.metricAgg = metricAggs[0].type.dslName;
91+
createUrlParams.metricFieldName = metricAggs[0].getField()?.name;
92+
}
93+
94+
const url = await mapsTileMapUrlGenerator.createUrl(createUrlParams);
95+
getCoreService().application.navigateToUrl(url);
96+
}}
97+
size="s"
98+
>
99+
<FormattedMessage id="tileMap.vis.viewInMaps" defaultMessage="View in Maps" />
100+
</EuiButton>
101+
</div>
102+
);
103+
}
104+
105+
return (
106+
<FormattedMessage
107+
id="tileMap.vis.deprecationMessage"
108+
defaultMessage="Coordinate map will migrate to Maps in 8.0. With Maps, you can add multiple layers and indices, plot individual documents, symbolize features from data values, and more. {action}"
109+
values={{ action }}
110+
/>
111+
);
112+
}

src/plugins/tile_map/public/plugin.ts

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,15 @@ import { createTileMapFn } from './tile_map_fn';
3434
import { createTileMapTypeDefinition } from './tile_map_type';
3535
import { IServiceSettings, MapsLegacyPluginSetup } from '../../maps_legacy/public';
3636
import { DataPublicPluginStart } from '../../data/public';
37-
import { setFormatService, setQueryService, setKibanaLegacy } from './services';
37+
import {
38+
setCoreService,
39+
setFormatService,
40+
setQueryService,
41+
setKibanaLegacy,
42+
setShareService,
43+
} from './services';
3844
import { KibanaLegacyStart } from '../../kibana_legacy/public';
45+
import { SharePluginStart } from '../../share/public';
3946

4047
export interface TileMapConfigType {
4148
tilemap: any;
@@ -61,6 +68,7 @@ export interface TileMapPluginSetupDependencies {
6168
export interface TileMapPluginStartDependencies {
6269
data: DataPublicPluginStart;
6370
kibanaLegacy: KibanaLegacyStart;
71+
share: SharePluginStart;
6472
}
6573

6674
export interface TileMapPluginSetup {
@@ -100,10 +108,12 @@ export class TileMapPlugin implements Plugin<TileMapPluginSetup, TileMapPluginSt
100108
};
101109
}
102110

103-
public start(core: CoreStart, { data, kibanaLegacy }: TileMapPluginStartDependencies) {
104-
setFormatService(data.fieldFormats);
105-
setQueryService(data.query);
106-
setKibanaLegacy(kibanaLegacy);
111+
public start(core: CoreStart, plugins: TileMapPluginStartDependencies) {
112+
setFormatService(plugins.data.fieldFormats);
113+
setQueryService(plugins.data.query);
114+
setKibanaLegacy(plugins.kibanaLegacy);
115+
setShareService(plugins.share);
116+
setCoreService(core);
107117
return {};
108118
}
109119
}

src/plugins/tile_map/public/services.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,13 @@
1717
* under the License.
1818
*/
1919

20+
import { CoreStart } from 'kibana/public';
2021
import { createGetterSetter } from '../../kibana_utils/public';
2122
import { DataPublicPluginStart } from '../../data/public';
2223
import { KibanaLegacyStart } from '../../kibana_legacy/public';
24+
import { SharePluginStart } from '../../share/public';
25+
26+
export const [getCoreService, setCoreService] = createGetterSetter<CoreStart>('Core');
2327

2428
export const [getFormatService, setFormatService] = createGetterSetter<
2529
DataPublicPluginStart['fieldFormats']
@@ -29,6 +33,8 @@ export const [getQueryService, setQueryService] = createGetterSetter<
2933
DataPublicPluginStart['query']
3034
>('Query');
3135

36+
export const [getShareService, setShareService] = createGetterSetter<SharePluginStart>('Share');
37+
3238
export const [getKibanaLegacy, setKibanaLegacy] = createGetterSetter<KibanaLegacyStart>(
3339
'KibanaLegacy'
3440
);

src/plugins/tile_map/public/tile_map_type.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,16 @@ import { createTileMapVisualization } from './tile_map_visualization';
2525
import { TileMapOptions } from './components/tile_map_options';
2626
import { supportsCssFilters } from './css_filters';
2727
import { truncatedColorSchemas } from '../../charts/public';
28+
import { getDeprecationMessage } from './get_deprecation_message';
2829

2930
export function createTileMapTypeDefinition(dependencies) {
3031
const CoordinateMapsVisualization = createTileMapVisualization(dependencies);
3132
const { uiSettings, serviceSettings } = dependencies;
3233

3334
return {
3435
name: 'tile_map',
36+
isDeprecated: true,
37+
getDeprecationMessage,
3538
title: i18n.translate('tileMap.vis.mapTitle', {
3639
defaultMessage: 'Coordinate Map',
3740
}),

src/plugins/visualizations/public/vis_types/base_vis_type.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,11 @@
1818
*/
1919

2020
import _ from 'lodash';
21+
import { ReactElement } from 'react';
2122
import { VisToExpressionAst, VisualizationControllerConstructor } from '../types';
2223
import { TriggerContextMapping } from '../../../ui_actions/public';
2324
import { Adapters } from '../../../inspector/public';
25+
import { Vis } from '../vis';
2426

2527
export interface BaseVisTypeOptions {
2628
name: string;
@@ -43,6 +45,8 @@ export interface BaseVisTypeOptions {
4345
useCustomNoDataScreen?: boolean;
4446
inspectorAdapters?: Adapters | (() => Adapters);
4547
toExpressionAst?: VisToExpressionAst;
48+
isDeprecated?: boolean;
49+
getDeprecationMessage?: (vis: Vis) => ReactElement<any>;
4650
}
4751

4852
export class BaseVisType {
@@ -68,6 +72,8 @@ export class BaseVisType {
6872
useCustomNoDataScreen: boolean;
6973
inspectorAdapters?: Adapters | (() => Adapters);
7074
toExpressionAst?: VisToExpressionAst;
75+
isDeprecated: boolean;
76+
getDeprecationMessage?: (vis: Vis) => ReactElement<any>;
7177

7278
constructor(opts: BaseVisTypeOptions) {
7379
if (!opts.icon && !opts.image) {
@@ -105,6 +111,8 @@ export class BaseVisType {
105111
this.useCustomNoDataScreen = opts.useCustomNoDataScreen || false;
106112
this.inspectorAdapters = opts.inspectorAdapters;
107113
this.toExpressionAst = opts.toExpressionAst;
114+
this.isDeprecated = opts.isDeprecated || false;
115+
this.getDeprecationMessage = opts.getDeprecationMessage;
108116
}
109117

110118
public get schemas() {
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Licensed to Elasticsearch B.V. under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch B.V. licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
import React, { ReactElement } from 'react';
21+
import { EuiCallOut } from '@elastic/eui';
22+
23+
export function DeprecatedVisInfo({ message }: { message: ReactElement<any> }) {
24+
return (
25+
<EuiCallOut
26+
className="hide-for-sharing"
27+
data-test-subj="deprecatedVisInfo"
28+
size="s"
29+
title={message}
30+
/>
31+
);
32+
}

src/plugins/visualize/public/application/components/visualize_editor_common.tsx

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import { FormattedMessage } from '@kbn/i18n/react';
2222
import { EuiScreenReaderOnly } from '@elastic/eui';
2323
import { VisualizeTopNav } from './visualize_top_nav';
2424
import { ExperimentalVisInfo } from './experimental_vis_info';
25+
import { DeprecatedVisInfo } from './deprecated_vis_info';
2526
import {
2627
SavedVisInstance,
2728
VisualizeAppState,
@@ -79,28 +80,34 @@ export const VisualizeEditorCommon = ({
7980
/>
8081
)}
8182
{visInstance?.vis?.type?.isExperimental && <ExperimentalVisInfo />}
83+
{visInstance?.vis?.type?.isDeprecated && visInstance?.vis?.type?.getDeprecationMessage && (
84+
<DeprecatedVisInfo message={visInstance.vis.type.getDeprecationMessage(visInstance?.vis)} />
85+
)}
8286
{visInstance && (
8387
<EuiScreenReaderOnly>
8488
<h1>
85-
{'savedVis' in visInstance && visInstance.savedVis.id ? (
86-
<FormattedMessage
87-
id="visualize.pageHeading"
88-
defaultMessage="{chartName} {chartType} visualization"
89-
values={{
90-
chartName: (visInstance as SavedVisInstance).savedVis.title,
91-
chartType: (visInstance as SavedVisInstance).vis.type.title,
92-
}}
93-
/>
94-
) : (
95-
<FormattedMessage
96-
id="visualize.byValue_pageHeading"
97-
defaultMessage="Visualization of type {chartType} embedded into {originatingApp} app"
98-
values={{
99-
chartType: visInstance.vis.type.title,
100-
originatingApp: originatingApp || 'dashboards',
101-
}}
102-
/>
103-
)}
89+
{
90+
// @ts-expect-error
91+
'savedVis' in visInstance && visInstance.savedVis.id ? (
92+
<FormattedMessage
93+
id="visualize.pageHeading"
94+
defaultMessage="{chartName} {chartType} visualization"
95+
values={{
96+
chartName: (visInstance as SavedVisInstance).savedVis.title,
97+
chartType: (visInstance as SavedVisInstance).vis.type.title,
98+
}}
99+
/>
100+
) : (
101+
<FormattedMessage
102+
id="visualize.byValue_pageHeading"
103+
defaultMessage="Visualization of type {chartType} embedded into {originatingApp} app"
104+
values={{
105+
chartType: visInstance.vis.type.title,
106+
originatingApp: originatingApp || 'dashboards',
107+
}}
108+
/>
109+
)
110+
}
104111
</h1>
105112
</EuiScreenReaderOnly>
106113
)}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
import { createAggDescriptor } from './create_tile_map_layer_descriptor';
8+
9+
describe('createAggDescriptor', () => {
10+
test('Should allow supported metric aggs', () => {
11+
expect(createAggDescriptor('Scaled Circle Markers', 'sum', 'bytes')).toEqual({
12+
type: 'sum',
13+
field: 'bytes',
14+
});
15+
});
16+
17+
test('Should fallback to count when field not provided', () => {
18+
expect(createAggDescriptor('Scaled Circle Markers', 'sum', undefined)).toEqual({
19+
type: 'count',
20+
});
21+
});
22+
23+
test('Should fallback to count when metric agg is not supported in maps', () => {
24+
expect(createAggDescriptor('Scaled Circle Markers', 'top_hits', 'bytes')).toEqual({
25+
type: 'count',
26+
});
27+
});
28+
29+
describe('heatmap', () => {
30+
test('Should allow countable metric aggs', () => {
31+
expect(createAggDescriptor('Heatmap', 'sum', 'bytes')).toEqual({
32+
type: 'sum',
33+
field: 'bytes',
34+
});
35+
});
36+
37+
test('Should fallback to count for non-countable metric aggs', () => {
38+
expect(createAggDescriptor('Heatmap', 'avg', 'bytes')).toEqual({
39+
type: 'count',
40+
});
41+
});
42+
});
43+
});

0 commit comments

Comments
 (0)