mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[Maps] Separate layer wizards for Clusters and heatmap (#60870)
* [Maps] source registry and register seperate clusters and heat map sources * split into to registries * add EMS file source * add geojson upload layer * register rest of sources * i18n changes * ts lint errors * fix jest test * fix pew-pew source * review feedback * import registires in plugin so they exist in embeddable * remove order parameter and move all layer registies into single file * fix functionalt est * pass constructor to sourceREgistry instead of factory * review feedback Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
This commit is contained in:
parent
325f8e0ad5
commit
467f27b600
36 changed files with 635 additions and 422 deletions
|
@ -5,13 +5,12 @@
|
|||
*/
|
||||
|
||||
import React, { Fragment } from 'react';
|
||||
import { GeojsonFileSource } from '../../../layers/sources/client_file_source';
|
||||
import { EuiSpacer, EuiPanel, EuiButtonEmpty } from '@elastic/eui';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
import { uploadLayerWizardConfig } from '../../../layers/sources/client_file_source';
|
||||
|
||||
export const ImportEditor = ({ clearSource, isIndexingTriggered, ...props }) => {
|
||||
const editorProperties = getEditorProperties({ isIndexingTriggered, ...props });
|
||||
const editor = GeojsonFileSource.renderEditor(editorProperties);
|
||||
return (
|
||||
<Fragment>
|
||||
{isIndexingTriggered ? null : (
|
||||
|
@ -25,7 +24,9 @@ export const ImportEditor = ({ clearSource, isIndexingTriggered, ...props }) =>
|
|||
<EuiSpacer size="s" />
|
||||
</Fragment>
|
||||
)}
|
||||
<EuiPanel style={{ position: 'relative' }}>{editor}</EuiPanel>
|
||||
<EuiPanel style={{ position: 'relative' }}>
|
||||
{uploadLayerWizardConfig.renderWizard(editorProperties)}
|
||||
</EuiPanel>
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -5,28 +5,20 @@
|
|||
*/
|
||||
|
||||
import React, { Fragment } from 'react';
|
||||
import { ALL_SOURCES } from '../../../layers/sources/all_sources';
|
||||
import { EuiSpacer, EuiPanel, EuiButtonEmpty } from '@elastic/eui';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
|
||||
export const SourceEditor = ({
|
||||
clearSource,
|
||||
sourceType,
|
||||
layerWizard,
|
||||
isIndexingTriggered,
|
||||
inspectorAdapters,
|
||||
previewLayer,
|
||||
}) => {
|
||||
const editorProperties = {
|
||||
onPreviewSource: previewLayer,
|
||||
inspectorAdapters,
|
||||
};
|
||||
const Source = ALL_SOURCES.find(Source => {
|
||||
return Source.type === sourceType;
|
||||
});
|
||||
if (!Source) {
|
||||
throw new Error(`Unexpected source type: ${sourceType}`);
|
||||
if (!layerWizard) {
|
||||
return null;
|
||||
}
|
||||
const editor = Source.renderEditor(editorProperties);
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
{isIndexingTriggered ? null : (
|
||||
|
@ -40,7 +32,9 @@ export const SourceEditor = ({
|
|||
<EuiSpacer size="s" />
|
||||
</Fragment>
|
||||
)}
|
||||
<EuiPanel>{editor}</EuiPanel>
|
||||
<EuiPanel>
|
||||
{layerWizard.renderWizard({ onPreviewSource: previewLayer, inspectorAdapters })}
|
||||
</EuiPanel>
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -5,30 +5,33 @@
|
|||
*/
|
||||
|
||||
import React, { Fragment } from 'react';
|
||||
import { ALL_SOURCES } from '../../../layers/sources/all_sources';
|
||||
import { getLayerWizards } from '../../../layers/layer_wizard_registry';
|
||||
import { EuiTitle, EuiSpacer, EuiCard, EuiIcon } from '@elastic/eui';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
import _ from 'lodash';
|
||||
|
||||
export function SourceSelect({ updateSourceSelection }) {
|
||||
const sourceCards = ALL_SOURCES.map(Source => {
|
||||
const icon = Source.icon ? <EuiIcon type={Source.icon} size="l" /> : null;
|
||||
const sourceCards = getLayerWizards().map(layerWizard => {
|
||||
const icon = layerWizard.icon ? <EuiIcon type={layerWizard.icon} size="l" /> : null;
|
||||
|
||||
const sourceTitle = Source.title;
|
||||
const onClick = () => {
|
||||
updateSourceSelection({
|
||||
layerWizard: layerWizard,
|
||||
isIndexingSource: !!layerWizard.isIndexingSource,
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<Fragment key={Source.type}>
|
||||
<Fragment key={layerWizard.title}>
|
||||
<EuiSpacer size="s" />
|
||||
<EuiCard
|
||||
className="mapLayerAddpanel__card"
|
||||
title={sourceTitle}
|
||||
title={layerWizard.title}
|
||||
icon={icon}
|
||||
onClick={() =>
|
||||
updateSourceSelection({ type: Source.type, isIndexingSource: Source.isIndexingSource })
|
||||
}
|
||||
description={Source.description}
|
||||
onClick={onClick}
|
||||
description={layerWizard.description}
|
||||
layout="horizontal"
|
||||
data-test-subj={_.camelCase(Source.title)}
|
||||
data-test-subj={_.camelCase(layerWizard.title)}
|
||||
/>
|
||||
</Fragment>
|
||||
);
|
||||
|
|
|
@ -14,7 +14,7 @@ import { i18n } from '@kbn/i18n';
|
|||
|
||||
export class AddLayerPanel extends Component {
|
||||
state = {
|
||||
sourceType: null,
|
||||
layerWizard: null,
|
||||
layer: null,
|
||||
importView: false,
|
||||
layerImportAddReady: false,
|
||||
|
@ -35,9 +35,9 @@ export class AddLayerPanel extends Component {
|
|||
}
|
||||
|
||||
_getPanelDescription() {
|
||||
const { sourceType, importView, layerImportAddReady } = this.state;
|
||||
const { layerWizard, importView, layerImportAddReady } = this.state;
|
||||
let panelDescription;
|
||||
if (!sourceType) {
|
||||
if (!layerWizard) {
|
||||
panelDescription = i18n.translate('xpack.maps.addLayerPanel.selectSource', {
|
||||
defaultMessage: 'Select source',
|
||||
});
|
||||
|
@ -85,13 +85,13 @@ export class AddLayerPanel extends Component {
|
|||
|
||||
this.setState({
|
||||
layer: null,
|
||||
...(!keepSourceType ? { sourceType: null, importView: false } : {}),
|
||||
...(!keepSourceType ? { layerWizard: null, importView: false } : {}),
|
||||
});
|
||||
this.props.removeTransientLayer();
|
||||
};
|
||||
|
||||
_onSourceSelectionChange = ({ type, isIndexingSource }) => {
|
||||
this.setState({ sourceType: type, importView: isIndexingSource });
|
||||
_onSourceSelectionChange = ({ layerWizard, isIndexingSource }) => {
|
||||
this.setState({ layerWizard, importView: isIndexingSource });
|
||||
};
|
||||
|
||||
_layerAddHandler = () => {
|
||||
|
@ -118,8 +118,8 @@ export class AddLayerPanel extends Component {
|
|||
};
|
||||
|
||||
_renderAddLayerPanel() {
|
||||
const { sourceType, importView } = this.state;
|
||||
if (!sourceType) {
|
||||
const { layerWizard, importView } = this.state;
|
||||
if (!layerWizard) {
|
||||
return <SourceSelect updateSourceSelection={this._onSourceSelectionChange} />;
|
||||
}
|
||||
if (importView) {
|
||||
|
@ -134,7 +134,7 @@ export class AddLayerPanel extends Component {
|
|||
return (
|
||||
<SourceEditor
|
||||
clearSource={this._clearLayerData}
|
||||
sourceType={sourceType}
|
||||
layerWizard={layerWizard}
|
||||
previewLayer={this._viewLayer}
|
||||
/>
|
||||
);
|
||||
|
@ -148,7 +148,7 @@ export class AddLayerPanel extends Component {
|
|||
|
||||
return (
|
||||
<FlyoutFooter
|
||||
showNextButton={!!this.state.sourceType}
|
||||
showNextButton={!!this.state.layerWizard}
|
||||
disableNextButton={!buttonEnabled}
|
||||
onClick={this._layerAddHandler}
|
||||
nextButtonText={buttonDescription}
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* 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 @typescript-eslint/consistent-type-definitions */
|
||||
|
||||
type LayerWizard = {
|
||||
description: string;
|
||||
icon: string;
|
||||
isIndexingSource?: boolean;
|
||||
renderWizard({
|
||||
onPreviewSource,
|
||||
inspectorAdapters,
|
||||
}: {
|
||||
onPreviewSource: () => void;
|
||||
inspectorAdapters: unknown;
|
||||
}): unknown;
|
||||
title: string;
|
||||
};
|
||||
|
||||
const registry: LayerWizard[] = [];
|
||||
|
||||
export function registerLayerWizard(layerWizard: LayerWizard) {
|
||||
registry.push(layerWizard);
|
||||
}
|
||||
|
||||
export function getLayerWizards(): LayerWizard[] {
|
||||
return [...registry];
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import { registerLayerWizard } from './layer_wizard_registry';
|
||||
import { uploadLayerWizardConfig } from './sources/client_file_source';
|
||||
import { esDocumentsLayerWizardConfig } from './sources/es_search_source';
|
||||
import { clustersLayerWizardConfig, heatmapLayerWizardConfig } from './sources/es_geo_grid_source';
|
||||
import { point2PointLayerWizardConfig } from './sources/es_pew_pew_source/es_pew_pew_source';
|
||||
import { emsBoundariesLayerWizardConfig } from './sources/ems_file_source';
|
||||
import { emsBaseMapLayerWizardConfig } from './sources/ems_tms_source';
|
||||
import { kibanaRegionMapLayerWizardConfig } from './sources/kibana_regionmap_source';
|
||||
import { kibanaBasemapLayerWizardConfig } from './sources/kibana_tilemap_source';
|
||||
import { tmsLayerWizardConfig } from './sources/xyz_tms_source';
|
||||
import { wmsLayerWizardConfig } from './sources/wms_source';
|
||||
|
||||
// Registration order determines display order
|
||||
registerLayerWizard(uploadLayerWizardConfig);
|
||||
registerLayerWizard(esDocumentsLayerWizardConfig);
|
||||
registerLayerWizard(clustersLayerWizardConfig);
|
||||
registerLayerWizard(heatmapLayerWizardConfig);
|
||||
registerLayerWizard(point2PointLayerWizardConfig);
|
||||
registerLayerWizard(emsBoundariesLayerWizardConfig);
|
||||
registerLayerWizard(emsBaseMapLayerWizardConfig);
|
||||
registerLayerWizard(kibanaRegionMapLayerWizardConfig);
|
||||
registerLayerWizard(kibanaBasemapLayerWizardConfig);
|
||||
registerLayerWizard(tmsLayerWizardConfig);
|
||||
registerLayerWizard(wmsLayerWizardConfig);
|
|
@ -1,29 +0,0 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import { EMSFileSource } from './ems_file_source';
|
||||
import { GeojsonFileSource } from './client_file_source';
|
||||
import { KibanaRegionmapSource } from './kibana_regionmap_source';
|
||||
import { XYZTMSSource } from './xyz_tms_source';
|
||||
import { EMSTMSSource } from './ems_tms_source';
|
||||
import { WMSSource } from './wms_source';
|
||||
import { KibanaTilemapSource } from './kibana_tilemap_source';
|
||||
import { ESGeoGridSource } from './es_geo_grid_source';
|
||||
import { ESSearchSource } from './es_search_source';
|
||||
import { ESPewPewSource } from './es_pew_pew_source/es_pew_pew_source';
|
||||
|
||||
export const ALL_SOURCES = [
|
||||
GeojsonFileSource,
|
||||
ESSearchSource,
|
||||
ESGeoGridSource,
|
||||
ESPewPewSource,
|
||||
EMSFileSource,
|
||||
EMSTMSSource,
|
||||
KibanaRegionmapSource,
|
||||
KibanaTilemapSource,
|
||||
XYZTMSSource,
|
||||
WMSSource,
|
||||
];
|
|
@ -16,16 +16,11 @@ import { ESSearchSource } from '../es_search_source';
|
|||
import uuid from 'uuid/v4';
|
||||
import _ from 'lodash';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { registerSource } from '../source_registry';
|
||||
|
||||
export class GeojsonFileSource extends AbstractVectorSource {
|
||||
static type = GEOJSON_FILE;
|
||||
static title = i18n.translate('xpack.maps.source.geojsonFileTitle', {
|
||||
defaultMessage: 'Uploaded GeoJSON',
|
||||
});
|
||||
static description = i18n.translate('xpack.maps.source.geojsonFileDescription', {
|
||||
defaultMessage: 'Upload and index GeoJSON data in Elasticsearch',
|
||||
});
|
||||
static icon = 'importAction';
|
||||
|
||||
static isIndexingSource = true;
|
||||
|
||||
static createDescriptor(geoJson, name) {
|
||||
|
@ -59,90 +54,6 @@ export class GeojsonFileSource extends AbstractVectorSource {
|
|||
};
|
||||
}
|
||||
|
||||
static viewIndexedData = (
|
||||
addAndViewSource,
|
||||
inspectorAdapters,
|
||||
importSuccessHandler,
|
||||
importErrorHandler
|
||||
) => {
|
||||
return (indexResponses = {}) => {
|
||||
const { indexDataResp, indexPatternResp } = indexResponses;
|
||||
|
||||
const indexCreationFailed = !(indexDataResp && indexDataResp.success);
|
||||
const allDocsFailed = indexDataResp.failures.length === indexDataResp.docCount;
|
||||
const indexPatternCreationFailed = !(indexPatternResp && indexPatternResp.success);
|
||||
|
||||
if (indexCreationFailed || allDocsFailed || indexPatternCreationFailed) {
|
||||
importErrorHandler(indexResponses);
|
||||
return;
|
||||
}
|
||||
const { fields, id } = indexPatternResp;
|
||||
const geoFieldArr = fields.filter(field =>
|
||||
Object.values(ES_GEO_FIELD_TYPE).includes(field.type)
|
||||
);
|
||||
const geoField = _.get(geoFieldArr, '[0].name');
|
||||
const indexPatternId = id;
|
||||
if (!indexPatternId || !geoField) {
|
||||
addAndViewSource(null);
|
||||
} else {
|
||||
// Only turn on bounds filter for large doc counts
|
||||
const filterByMapBounds = indexDataResp.docCount > DEFAULT_MAX_RESULT_WINDOW;
|
||||
const source = new ESSearchSource(
|
||||
{
|
||||
id: uuid(),
|
||||
indexPatternId,
|
||||
geoField,
|
||||
filterByMapBounds,
|
||||
},
|
||||
inspectorAdapters
|
||||
);
|
||||
addAndViewSource(source);
|
||||
importSuccessHandler(indexResponses);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
static previewGeojsonFile = (onPreviewSource, inspectorAdapters) => {
|
||||
return (geojsonFile, name) => {
|
||||
if (!geojsonFile) {
|
||||
onPreviewSource(null);
|
||||
return;
|
||||
}
|
||||
const sourceDescriptor = GeojsonFileSource.createDescriptor(geojsonFile, name);
|
||||
const source = new GeojsonFileSource(sourceDescriptor, inspectorAdapters);
|
||||
onPreviewSource(source);
|
||||
};
|
||||
};
|
||||
|
||||
static renderEditor({
|
||||
onPreviewSource,
|
||||
inspectorAdapters,
|
||||
addAndViewSource,
|
||||
isIndexingTriggered,
|
||||
onRemove,
|
||||
onIndexReady,
|
||||
importSuccessHandler,
|
||||
importErrorHandler,
|
||||
}) {
|
||||
return (
|
||||
<ClientFileCreateSourceEditor
|
||||
previewGeojsonFile={GeojsonFileSource.previewGeojsonFile(
|
||||
onPreviewSource,
|
||||
inspectorAdapters
|
||||
)}
|
||||
isIndexingTriggered={isIndexingTriggered}
|
||||
onIndexingComplete={GeojsonFileSource.viewIndexedData(
|
||||
addAndViewSource,
|
||||
inspectorAdapters,
|
||||
importSuccessHandler,
|
||||
importErrorHandler
|
||||
)}
|
||||
onRemove={onRemove}
|
||||
onIndexReady={onIndexReady}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
async getGeoJsonWithMeta() {
|
||||
return {
|
||||
data: this._descriptor.__featureCollection,
|
||||
|
@ -162,3 +73,99 @@ export class GeojsonFileSource extends AbstractVectorSource {
|
|||
return GeojsonFileSource.isIndexingSource;
|
||||
}
|
||||
}
|
||||
|
||||
const viewIndexedData = (
|
||||
addAndViewSource,
|
||||
inspectorAdapters,
|
||||
importSuccessHandler,
|
||||
importErrorHandler
|
||||
) => {
|
||||
return (indexResponses = {}) => {
|
||||
const { indexDataResp, indexPatternResp } = indexResponses;
|
||||
|
||||
const indexCreationFailed = !(indexDataResp && indexDataResp.success);
|
||||
const allDocsFailed = indexDataResp.failures.length === indexDataResp.docCount;
|
||||
const indexPatternCreationFailed = !(indexPatternResp && indexPatternResp.success);
|
||||
|
||||
if (indexCreationFailed || allDocsFailed || indexPatternCreationFailed) {
|
||||
importErrorHandler(indexResponses);
|
||||
return;
|
||||
}
|
||||
const { fields, id } = indexPatternResp;
|
||||
const geoFieldArr = fields.filter(field =>
|
||||
Object.values(ES_GEO_FIELD_TYPE).includes(field.type)
|
||||
);
|
||||
const geoField = _.get(geoFieldArr, '[0].name');
|
||||
const indexPatternId = id;
|
||||
if (!indexPatternId || !geoField) {
|
||||
addAndViewSource(null);
|
||||
} else {
|
||||
// Only turn on bounds filter for large doc counts
|
||||
const filterByMapBounds = indexDataResp.docCount > DEFAULT_MAX_RESULT_WINDOW;
|
||||
const source = new ESSearchSource(
|
||||
{
|
||||
id: uuid(),
|
||||
indexPatternId,
|
||||
geoField,
|
||||
filterByMapBounds,
|
||||
},
|
||||
inspectorAdapters
|
||||
);
|
||||
addAndViewSource(source);
|
||||
importSuccessHandler(indexResponses);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
const previewGeojsonFile = (onPreviewSource, inspectorAdapters) => {
|
||||
return (geojsonFile, name) => {
|
||||
if (!geojsonFile) {
|
||||
onPreviewSource(null);
|
||||
return;
|
||||
}
|
||||
const sourceDescriptor = GeojsonFileSource.createDescriptor(geojsonFile, name);
|
||||
const source = new GeojsonFileSource(sourceDescriptor, inspectorAdapters);
|
||||
onPreviewSource(source);
|
||||
};
|
||||
};
|
||||
|
||||
registerSource({
|
||||
ConstructorFunction: GeojsonFileSource,
|
||||
type: GEOJSON_FILE,
|
||||
});
|
||||
|
||||
export const uploadLayerWizardConfig = {
|
||||
description: i18n.translate('xpack.maps.source.geojsonFileDescription', {
|
||||
defaultMessage: 'Index GeoJSON data in Elasticsearch',
|
||||
}),
|
||||
icon: 'importAction',
|
||||
isIndexingSource: true,
|
||||
renderWizard: ({
|
||||
onPreviewSource,
|
||||
inspectorAdapters,
|
||||
addAndViewSource,
|
||||
isIndexingTriggered,
|
||||
onRemove,
|
||||
onIndexReady,
|
||||
importSuccessHandler,
|
||||
importErrorHandler,
|
||||
}) => {
|
||||
return (
|
||||
<ClientFileCreateSourceEditor
|
||||
previewGeojsonFile={previewGeojsonFile(onPreviewSource, inspectorAdapters)}
|
||||
isIndexingTriggered={isIndexingTriggered}
|
||||
onIndexingComplete={viewIndexedData(
|
||||
addAndViewSource,
|
||||
inspectorAdapters,
|
||||
importSuccessHandler,
|
||||
importErrorHandler
|
||||
)}
|
||||
onRemove={onRemove}
|
||||
onIndexReady={onIndexReady}
|
||||
/>
|
||||
);
|
||||
},
|
||||
title: i18n.translate('xpack.maps.source.geojsonFileTitle', {
|
||||
defaultMessage: 'Upload GeoJSON',
|
||||
}),
|
||||
};
|
||||
|
|
|
@ -4,4 +4,4 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
export { GeojsonFileSource } from './geojson_file_source';
|
||||
export { GeojsonFileSource, uploadLayerWizardConfig } from './geojson_file_source';
|
||||
|
|
|
@ -14,16 +14,14 @@ import { i18n } from '@kbn/i18n';
|
|||
import { getDataSourceLabel } from '../../../../common/i18n_getters';
|
||||
import { UpdateSourceEditor } from './update_source_editor';
|
||||
import { EMSFileField } from '../../fields/ems_file_field';
|
||||
import { registerSource } from '../source_registry';
|
||||
|
||||
const sourceTitle = i18n.translate('xpack.maps.source.emsFileTitle', {
|
||||
defaultMessage: 'EMS Boundaries',
|
||||
});
|
||||
|
||||
export class EMSFileSource extends AbstractVectorSource {
|
||||
static type = EMS_FILE;
|
||||
static title = i18n.translate('xpack.maps.source.emsFileTitle', {
|
||||
defaultMessage: 'EMS Boundaries',
|
||||
});
|
||||
static description = i18n.translate('xpack.maps.source.emsFileDescription', {
|
||||
defaultMessage: 'Administrative boundaries from Elastic Maps Service',
|
||||
});
|
||||
static icon = 'emsApp';
|
||||
|
||||
static createDescriptor({ id, tooltipProperties = [] }) {
|
||||
return {
|
||||
|
@ -33,15 +31,6 @@ export class EMSFileSource extends AbstractVectorSource {
|
|||
};
|
||||
}
|
||||
|
||||
static renderEditor({ onPreviewSource, inspectorAdapters }) {
|
||||
const onSourceConfigChange = sourceConfig => {
|
||||
const sourceDescriptor = EMSFileSource.createDescriptor(sourceConfig);
|
||||
const source = new EMSFileSource(sourceDescriptor, inspectorAdapters);
|
||||
onPreviewSource(source);
|
||||
};
|
||||
return <EMSFileCreateSourceEditor onSourceConfigChange={onSourceConfigChange} />;
|
||||
}
|
||||
|
||||
constructor(descriptor, inspectorAdapters) {
|
||||
super(EMSFileSource.createDescriptor(descriptor), inspectorAdapters);
|
||||
this._tooltipFields = this._descriptor.tooltipProperties.map(propertyKey =>
|
||||
|
@ -118,7 +107,7 @@ export class EMSFileSource extends AbstractVectorSource {
|
|||
return [
|
||||
{
|
||||
label: getDataSourceLabel(),
|
||||
value: EMSFileSource.title,
|
||||
value: sourceTitle,
|
||||
},
|
||||
{
|
||||
label: i18n.translate('xpack.maps.source.emsFile.layerLabel', {
|
||||
|
@ -167,3 +156,24 @@ export class EMSFileSource extends AbstractVectorSource {
|
|||
return [VECTOR_SHAPE_TYPES.POLYGON];
|
||||
}
|
||||
}
|
||||
|
||||
registerSource({
|
||||
ConstructorFunction: EMSFileSource,
|
||||
type: EMS_FILE,
|
||||
});
|
||||
|
||||
export const emsBoundariesLayerWizardConfig = {
|
||||
description: i18n.translate('xpack.maps.source.emsFileDescription', {
|
||||
defaultMessage: 'Administrative boundaries from Elastic Maps Service',
|
||||
}),
|
||||
icon: 'emsApp',
|
||||
renderWizard: ({ onPreviewSource, inspectorAdapters }) => {
|
||||
const onSourceConfigChange = sourceConfig => {
|
||||
const sourceDescriptor = EMSFileSource.createDescriptor(sourceConfig);
|
||||
const source = new EMSFileSource(sourceDescriptor, inspectorAdapters);
|
||||
onPreviewSource(source);
|
||||
};
|
||||
return <EMSFileCreateSourceEditor onSourceConfigChange={onSourceConfigChange} />;
|
||||
},
|
||||
title: sourceTitle,
|
||||
};
|
||||
|
|
|
@ -4,4 +4,4 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
export { EMSFileSource } from './ems_file_source';
|
||||
export { EMSFileSource, emsBoundariesLayerWizardConfig } from './ems_file_source';
|
||||
|
|
|
@ -16,16 +16,14 @@ import { i18n } from '@kbn/i18n';
|
|||
import { getDataSourceLabel } from '../../../../common/i18n_getters';
|
||||
import { EMS_TMS } from '../../../../common/constants';
|
||||
import { getInjectedVarFunc, getUiSettings } from '../../../kibana_services';
|
||||
import { registerSource } from '../source_registry';
|
||||
|
||||
const sourceTitle = i18n.translate('xpack.maps.source.emsTileTitle', {
|
||||
defaultMessage: 'EMS Basemaps',
|
||||
});
|
||||
|
||||
export class EMSTMSSource extends AbstractTMSSource {
|
||||
static type = EMS_TMS;
|
||||
static title = i18n.translate('xpack.maps.source.emsTileTitle', {
|
||||
defaultMessage: 'EMS Basemaps',
|
||||
});
|
||||
static description = i18n.translate('xpack.maps.source.emsTileDescription', {
|
||||
defaultMessage: 'Tile map service from Elastic Maps Service',
|
||||
});
|
||||
static icon = 'emsApp';
|
||||
|
||||
static createDescriptor(sourceConfig) {
|
||||
return {
|
||||
|
@ -35,16 +33,6 @@ export class EMSTMSSource extends AbstractTMSSource {
|
|||
};
|
||||
}
|
||||
|
||||
static renderEditor({ onPreviewSource, inspectorAdapters }) {
|
||||
const onSourceConfigChange = sourceConfig => {
|
||||
const descriptor = EMSTMSSource.createDescriptor(sourceConfig);
|
||||
const source = new EMSTMSSource(descriptor, inspectorAdapters);
|
||||
onPreviewSource(source);
|
||||
};
|
||||
|
||||
return <TileServiceSelect onTileSelect={onSourceConfigChange} />;
|
||||
}
|
||||
|
||||
constructor(descriptor, inspectorAdapters) {
|
||||
super(
|
||||
{
|
||||
|
@ -69,7 +57,7 @@ export class EMSTMSSource extends AbstractTMSSource {
|
|||
return [
|
||||
{
|
||||
label: getDataSourceLabel(),
|
||||
value: EMSTMSSource.title,
|
||||
value: sourceTitle,
|
||||
},
|
||||
{
|
||||
label: i18n.translate('xpack.maps.source.emsTile.serviceId', {
|
||||
|
@ -157,3 +145,25 @@ export class EMSTMSSource extends AbstractTMSSource {
|
|||
return isDarkMode ? emsTileLayerId.dark : emsTileLayerId.bright;
|
||||
}
|
||||
}
|
||||
|
||||
registerSource({
|
||||
ConstructorFunction: EMSTMSSource,
|
||||
type: EMS_TMS,
|
||||
});
|
||||
|
||||
export const emsBaseMapLayerWizardConfig = {
|
||||
description: i18n.translate('xpack.maps.source.emsTileDescription', {
|
||||
defaultMessage: 'Tile map service from Elastic Maps Service',
|
||||
}),
|
||||
icon: 'emsApp',
|
||||
renderWizard: ({ onPreviewSource, inspectorAdapters }) => {
|
||||
const onSourceConfigChange = sourceConfig => {
|
||||
const descriptor = EMSTMSSource.createDescriptor(sourceConfig);
|
||||
const source = new EMSTMSSource(descriptor, inspectorAdapters);
|
||||
onPreviewSource(source);
|
||||
};
|
||||
|
||||
return <TileServiceSelect onTileSelect={onSourceConfigChange} />;
|
||||
},
|
||||
title: sourceTitle,
|
||||
};
|
||||
|
|
|
@ -4,4 +4,4 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
export { EMSTMSSource } from './ems_tms_source';
|
||||
export { EMSTMSSource, emsBaseMapLayerWizardConfig } from './ems_tms_source';
|
||||
|
|
|
@ -14,32 +14,12 @@ import { getIndexPatternService, getIndexPatternSelectComponent } from '../../..
|
|||
import { NoIndexPatternCallout } from '../../../components/no_index_pattern_callout';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
import { EuiFormRow, EuiComboBox, EuiSpacer } from '@elastic/eui';
|
||||
import { EuiFormRow, EuiSpacer } from '@elastic/eui';
|
||||
import {
|
||||
AGGREGATABLE_GEO_FIELD_TYPES,
|
||||
getAggregatableGeoFields,
|
||||
} from '../../../index_pattern_util';
|
||||
|
||||
const requestTypeOptions = [
|
||||
{
|
||||
label: i18n.translate('xpack.maps.source.esGeoGrid.gridRectangleDropdownOption', {
|
||||
defaultMessage: 'grid rectangles',
|
||||
}),
|
||||
value: RENDER_AS.GRID,
|
||||
},
|
||||
{
|
||||
label: i18n.translate('xpack.maps.source.esGeoGrid.heatmapDropdownOption', {
|
||||
defaultMessage: 'heat map',
|
||||
}),
|
||||
value: RENDER_AS.HEATMAP,
|
||||
},
|
||||
{
|
||||
label: i18n.translate('xpack.maps.source.esGeoGrid.pointsDropdownOption', {
|
||||
defaultMessage: 'clusters',
|
||||
}),
|
||||
value: RENDER_AS.POINT,
|
||||
},
|
||||
];
|
||||
import { RenderAsSelect } from './render_as_select';
|
||||
|
||||
export class CreateSourceEditor extends Component {
|
||||
static propTypes = {
|
||||
|
@ -50,7 +30,7 @@ export class CreateSourceEditor extends Component {
|
|||
isLoadingIndexPattern: false,
|
||||
indexPatternId: '',
|
||||
geoField: '',
|
||||
requestType: requestTypeOptions[0],
|
||||
requestType: this.props.requestType,
|
||||
noGeoIndexPatternsExist: false,
|
||||
};
|
||||
|
||||
|
@ -126,10 +106,10 @@ export class CreateSourceEditor extends Component {
|
|||
);
|
||||
};
|
||||
|
||||
_onRequestTypeSelect = selectedOptions => {
|
||||
_onRequestTypeSelect = newValue => {
|
||||
this.setState(
|
||||
{
|
||||
requestType: selectedOptions[0],
|
||||
requestType: newValue,
|
||||
},
|
||||
this.previewLayer
|
||||
);
|
||||
|
@ -139,9 +119,7 @@ export class CreateSourceEditor extends Component {
|
|||
const { indexPatternId, geoField, requestType } = this.state;
|
||||
|
||||
const sourceConfig =
|
||||
indexPatternId && geoField
|
||||
? { indexPatternId, geoField, requestType: requestType.value }
|
||||
: null;
|
||||
indexPatternId && geoField ? { indexPatternId, geoField, requestType } : null;
|
||||
this.props.onSourceConfigChange(sourceConfig);
|
||||
};
|
||||
|
||||
|
@ -176,28 +154,13 @@ export class CreateSourceEditor extends Component {
|
|||
);
|
||||
}
|
||||
|
||||
_renderLayerSelect() {
|
||||
if (!this.state.indexPattern) {
|
||||
_renderRenderAsSelect() {
|
||||
if (this.state.requestType === RENDER_AS.HEATMAP || !this.state.indexPattern) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<EuiFormRow
|
||||
label={i18n.translate('xpack.maps.source.esGeoGrid.showAsLabel', {
|
||||
defaultMessage: 'Show as',
|
||||
})}
|
||||
>
|
||||
<EuiComboBox
|
||||
placeholder={i18n.translate('xpack.maps.source.esGeoGrid.showAsPlaceholder', {
|
||||
defaultMessage: 'Select a single option',
|
||||
})}
|
||||
singleSelection={{ asPlainText: true }}
|
||||
options={requestTypeOptions}
|
||||
selectedOptions={[this.state.requestType]}
|
||||
onChange={this._onRequestTypeSelect}
|
||||
isClearable={false}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
<RenderAsSelect renderAs={this.state.requestType} onChange={this._onRequestTypeSelect} />
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -243,7 +206,7 @@ export class CreateSourceEditor extends Component {
|
|||
{this._renderNoIndexPatternWarning()}
|
||||
{this._renderIndexPatternSelect()}
|
||||
{this._renderGeoSelect()}
|
||||
{this._renderLayerSelect()}
|
||||
{this._renderRenderAsSelect()}
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -32,17 +32,20 @@ import { AbstractESAggSource } from '../es_agg_source';
|
|||
import { DynamicStyleProperty } from '../../styles/vector/properties/dynamic_style_property';
|
||||
import { StaticStyleProperty } from '../../styles/vector/properties/static_style_property';
|
||||
import { DataRequestAbortError } from '../../util/data_request';
|
||||
import { registerSource } from '../source_registry';
|
||||
|
||||
export const MAX_GEOTILE_LEVEL = 29;
|
||||
|
||||
const clustersTitle = i18n.translate('xpack.maps.source.esGridClustersTitle', {
|
||||
defaultMessage: 'Clusters and grids',
|
||||
});
|
||||
|
||||
const heatmapTitle = i18n.translate('xpack.maps.source.esGridHeatmapTitle', {
|
||||
defaultMessage: 'Heat map',
|
||||
});
|
||||
|
||||
export class ESGeoGridSource extends AbstractESAggSource {
|
||||
static type = ES_GEO_GRID;
|
||||
static title = i18n.translate('xpack.maps.source.esGridTitle', {
|
||||
defaultMessage: 'Grid aggregation',
|
||||
});
|
||||
static description = i18n.translate('xpack.maps.source.esGridDescription', {
|
||||
defaultMessage: 'Geospatial data grouped in grids with metrics for each gridded cell',
|
||||
});
|
||||
|
||||
static createDescriptor({ indexPatternId, geoField, requestType, resolution }) {
|
||||
return {
|
||||
|
@ -55,21 +58,6 @@ export class ESGeoGridSource extends AbstractESAggSource {
|
|||
};
|
||||
}
|
||||
|
||||
static renderEditor({ onPreviewSource, inspectorAdapters }) {
|
||||
const onSourceConfigChange = sourceConfig => {
|
||||
if (!sourceConfig) {
|
||||
onPreviewSource(null);
|
||||
return;
|
||||
}
|
||||
|
||||
const sourceDescriptor = ESGeoGridSource.createDescriptor(sourceConfig);
|
||||
const source = new ESGeoGridSource(sourceDescriptor, inspectorAdapters);
|
||||
onPreviewSource(source);
|
||||
};
|
||||
|
||||
return <CreateSourceEditor onSourceConfigChange={onSourceConfigChange} />;
|
||||
}
|
||||
|
||||
renderSourceSettingsEditor({ onChange }) {
|
||||
return (
|
||||
<UpdateSourceEditor
|
||||
|
@ -94,7 +82,7 @@ export class ESGeoGridSource extends AbstractESAggSource {
|
|||
return [
|
||||
{
|
||||
label: getDataSourceLabel(),
|
||||
value: ESGeoGridSource.title,
|
||||
value: this._descriptor.requestType === RENDER_AS.HEATMAP ? heatmapTitle : clustersTitle,
|
||||
},
|
||||
{
|
||||
label: i18n.translate('xpack.maps.source.esGrid.indexPatternLabel', {
|
||||
|
@ -108,12 +96,6 @@ export class ESGeoGridSource extends AbstractESAggSource {
|
|||
}),
|
||||
value: this._descriptor.geoField,
|
||||
},
|
||||
{
|
||||
label: i18n.translate('xpack.maps.source.esGrid.showasFieldLabel', {
|
||||
defaultMessage: 'Show as',
|
||||
}),
|
||||
value: this._descriptor.requestType,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -429,3 +411,62 @@ export class ESGeoGridSource extends AbstractESAggSource {
|
|||
return [VECTOR_SHAPE_TYPES.POINT];
|
||||
}
|
||||
}
|
||||
|
||||
registerSource({
|
||||
ConstructorFunction: ESGeoGridSource,
|
||||
type: ES_GEO_GRID,
|
||||
});
|
||||
|
||||
export const clustersLayerWizardConfig = {
|
||||
description: i18n.translate('xpack.maps.source.esGridClustersDescription', {
|
||||
defaultMessage: 'Geospatial data grouped in grids with metrics for each gridded cell',
|
||||
}),
|
||||
icon: 'logoElasticsearch',
|
||||
renderWizard: ({ onPreviewSource, inspectorAdapters }) => {
|
||||
const onSourceConfigChange = sourceConfig => {
|
||||
if (!sourceConfig) {
|
||||
onPreviewSource(null);
|
||||
return;
|
||||
}
|
||||
|
||||
const sourceDescriptor = ESGeoGridSource.createDescriptor(sourceConfig);
|
||||
const source = new ESGeoGridSource(sourceDescriptor, inspectorAdapters);
|
||||
onPreviewSource(source);
|
||||
};
|
||||
|
||||
return (
|
||||
<CreateSourceEditor
|
||||
requestType={RENDER_AS.POINT}
|
||||
onSourceConfigChange={onSourceConfigChange}
|
||||
/>
|
||||
);
|
||||
},
|
||||
title: clustersTitle,
|
||||
};
|
||||
|
||||
export const heatmapLayerWizardConfig = {
|
||||
description: i18n.translate('xpack.maps.source.esGridHeatmapDescription', {
|
||||
defaultMessage: 'Geospatial data grouped in grids to show density',
|
||||
}),
|
||||
icon: 'logoElasticsearch',
|
||||
renderWizard: ({ onPreviewSource, inspectorAdapters }) => {
|
||||
const onSourceConfigChange = sourceConfig => {
|
||||
if (!sourceConfig) {
|
||||
onPreviewSource(null);
|
||||
return;
|
||||
}
|
||||
|
||||
const sourceDescriptor = ESGeoGridSource.createDescriptor(sourceConfig);
|
||||
const source = new ESGeoGridSource(sourceDescriptor, inspectorAdapters);
|
||||
onPreviewSource(source);
|
||||
};
|
||||
|
||||
return (
|
||||
<CreateSourceEditor
|
||||
requestType={RENDER_AS.HEATMAP}
|
||||
onSourceConfigChange={onSourceConfigChange}
|
||||
/>
|
||||
);
|
||||
},
|
||||
title: heatmapTitle,
|
||||
};
|
||||
|
|
|
@ -4,4 +4,8 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
export { ESGeoGridSource } from './es_geo_grid_source';
|
||||
export {
|
||||
ESGeoGridSource,
|
||||
clustersLayerWizardConfig,
|
||||
heatmapLayerWizardConfig,
|
||||
} from './es_geo_grid_source';
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { EuiFormRow, EuiComboBox, EuiComboBoxOptionOption } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { RENDER_AS } from '../../../../common/constants';
|
||||
|
||||
const options = [
|
||||
{
|
||||
label: i18n.translate('xpack.maps.source.esGeoGrid.pointsDropdownOption', {
|
||||
defaultMessage: 'clusters',
|
||||
}),
|
||||
value: RENDER_AS.POINT,
|
||||
},
|
||||
{
|
||||
label: i18n.translate('xpack.maps.source.esGeoGrid.gridRectangleDropdownOption', {
|
||||
defaultMessage: 'grids',
|
||||
}),
|
||||
value: RENDER_AS.GRID,
|
||||
},
|
||||
];
|
||||
|
||||
export function RenderAsSelect(props: {
|
||||
renderAs: RENDER_AS;
|
||||
onChange: (newValue: RENDER_AS) => void;
|
||||
}) {
|
||||
function onChange(selectedOptions: Array<EuiComboBoxOptionOption<RENDER_AS>>) {
|
||||
if (!selectedOptions || !selectedOptions.length) {
|
||||
return;
|
||||
}
|
||||
props.onChange(selectedOptions[0].value as RENDER_AS);
|
||||
}
|
||||
|
||||
const selectedOptions = [];
|
||||
const selectedOption = options.find(option => option.value === props.renderAs);
|
||||
if (selectedOption) {
|
||||
selectedOptions.push(selectedOption);
|
||||
}
|
||||
|
||||
return (
|
||||
<EuiFormRow
|
||||
label={i18n.translate('xpack.maps.source.esGeoGrid.showAsLabel', {
|
||||
defaultMessage: 'Show as',
|
||||
})}
|
||||
>
|
||||
<EuiComboBox
|
||||
singleSelection={{ asPlainText: true }}
|
||||
options={options}
|
||||
selectedOptions={selectedOptions}
|
||||
onChange={onChange}
|
||||
isClearable={false}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
);
|
||||
}
|
|
@ -26,17 +26,16 @@ import { AbstractESAggSource } from '../es_agg_source';
|
|||
import { DynamicStyleProperty } from '../../styles/vector/properties/dynamic_style_property';
|
||||
import { COLOR_GRADIENTS } from '../../styles/color_utils';
|
||||
import { indexPatterns } from '../../../../../../../../src/plugins/data/public';
|
||||
import { registerSource } from '../source_registry';
|
||||
|
||||
const MAX_GEOTILE_LEVEL = 29;
|
||||
|
||||
const sourceTitle = i18n.translate('xpack.maps.source.pewPewTitle', {
|
||||
defaultMessage: 'Point to point',
|
||||
});
|
||||
|
||||
export class ESPewPewSource extends AbstractESAggSource {
|
||||
static type = ES_PEW_PEW;
|
||||
static title = i18n.translate('xpack.maps.source.pewPewTitle', {
|
||||
defaultMessage: 'Point to point',
|
||||
});
|
||||
static description = i18n.translate('xpack.maps.source.pewPewDescription', {
|
||||
defaultMessage: 'Aggregated data paths between the source and destination',
|
||||
});
|
||||
|
||||
static createDescriptor({ indexPatternId, sourceGeoField, destGeoField }) {
|
||||
return {
|
||||
|
@ -48,21 +47,6 @@ export class ESPewPewSource extends AbstractESAggSource {
|
|||
};
|
||||
}
|
||||
|
||||
static renderEditor({ onPreviewSource, inspectorAdapters }) {
|
||||
const onSourceConfigChange = sourceConfig => {
|
||||
if (!sourceConfig) {
|
||||
onPreviewSource(null);
|
||||
return;
|
||||
}
|
||||
|
||||
const sourceDescriptor = ESPewPewSource.createDescriptor(sourceConfig);
|
||||
const source = new ESPewPewSource(sourceDescriptor, inspectorAdapters);
|
||||
onPreviewSource(source);
|
||||
};
|
||||
|
||||
return <CreateSourceEditor onSourceConfigChange={onSourceConfigChange} />;
|
||||
}
|
||||
|
||||
renderSourceSettingsEditor({ onChange }) {
|
||||
return (
|
||||
<UpdateSourceEditor
|
||||
|
@ -102,7 +86,7 @@ export class ESPewPewSource extends AbstractESAggSource {
|
|||
return [
|
||||
{
|
||||
label: getDataSourceLabel(),
|
||||
value: ESPewPewSource.title,
|
||||
value: sourceTitle,
|
||||
},
|
||||
{
|
||||
label: i18n.translate('xpack.maps.source.pewPew.indexPatternLabel', {
|
||||
|
@ -245,3 +229,30 @@ export class ESPewPewSource extends AbstractESAggSource {
|
|||
return await this.filterAndFormatPropertiesToHtmlForMetricFields(properties);
|
||||
}
|
||||
}
|
||||
|
||||
registerSource({
|
||||
ConstructorFunction: ESPewPewSource,
|
||||
type: ES_PEW_PEW,
|
||||
});
|
||||
|
||||
export const point2PointLayerWizardConfig = {
|
||||
description: i18n.translate('xpack.maps.source.pewPewDescription', {
|
||||
defaultMessage: 'Aggregated data paths between the source and destination',
|
||||
}),
|
||||
icon: 'logoElasticsearch',
|
||||
renderWizard: ({ onPreviewSource, inspectorAdapters }) => {
|
||||
const onSourceConfigChange = sourceConfig => {
|
||||
if (!sourceConfig) {
|
||||
onPreviewSource(null);
|
||||
return;
|
||||
}
|
||||
|
||||
const sourceDescriptor = ESPewPewSource.createDescriptor(sourceConfig);
|
||||
const source = new ESPewPewSource(sourceDescriptor, inspectorAdapters);
|
||||
onPreviewSource(source);
|
||||
};
|
||||
|
||||
return <CreateSourceEditor onSourceConfigChange={onSourceConfigChange} />;
|
||||
},
|
||||
title: sourceTitle,
|
||||
};
|
||||
|
|
|
@ -32,6 +32,11 @@ import { BlendedVectorLayer } from '../../blended_vector_layer';
|
|||
import { DEFAULT_FILTER_BY_MAP_BOUNDS } from './constants';
|
||||
import { ESDocField } from '../../fields/es_doc_field';
|
||||
import { getField, addFieldToDSL } from '../../util/es_agg_utils';
|
||||
import { registerSource } from '../source_registry';
|
||||
|
||||
const sourceTitle = i18n.translate('xpack.maps.source.esSearchTitle', {
|
||||
defaultMessage: 'Documents',
|
||||
});
|
||||
|
||||
function getDocValueAndSourceFields(indexPattern, fieldNames) {
|
||||
const docValueFields = [];
|
||||
|
@ -65,31 +70,6 @@ function getDocValueAndSourceFields(indexPattern, fieldNames) {
|
|||
|
||||
export class ESSearchSource extends AbstractESSource {
|
||||
static type = ES_SEARCH;
|
||||
static title = i18n.translate('xpack.maps.source.esSearchTitle', {
|
||||
defaultMessage: 'Documents',
|
||||
});
|
||||
static description = i18n.translate('xpack.maps.source.esSearchDescription', {
|
||||
defaultMessage: 'Vector data from a Kibana index pattern',
|
||||
});
|
||||
|
||||
static renderEditor({ onPreviewSource, inspectorAdapters }) {
|
||||
const onSourceConfigChange = sourceConfig => {
|
||||
if (!sourceConfig) {
|
||||
onPreviewSource(null);
|
||||
return;
|
||||
}
|
||||
|
||||
const source = new ESSearchSource(
|
||||
{
|
||||
id: uuid(),
|
||||
...sourceConfig,
|
||||
},
|
||||
inspectorAdapters
|
||||
);
|
||||
onPreviewSource(source);
|
||||
};
|
||||
return <CreateSourceEditor onSourceConfigChange={onSourceConfigChange} />;
|
||||
}
|
||||
|
||||
constructor(descriptor, inspectorAdapters) {
|
||||
super(
|
||||
|
@ -206,7 +186,7 @@ export class ESSearchSource extends AbstractESSource {
|
|||
return [
|
||||
{
|
||||
label: getDataSourceLabel(),
|
||||
value: ESSearchSource.title,
|
||||
value: sourceTitle,
|
||||
},
|
||||
{
|
||||
label: i18n.translate('xpack.maps.source.esSearch.indexPatternLabel', {
|
||||
|
@ -587,3 +567,34 @@ export class ESSearchSource extends AbstractESSource {
|
|||
};
|
||||
}
|
||||
}
|
||||
|
||||
registerSource({
|
||||
ConstructorFunction: ESSearchSource,
|
||||
type: ES_SEARCH,
|
||||
});
|
||||
|
||||
export const esDocumentsLayerWizardConfig = {
|
||||
description: i18n.translate('xpack.maps.source.esSearchDescription', {
|
||||
defaultMessage: 'Vector data from a Kibana index pattern',
|
||||
}),
|
||||
icon: 'logoElasticsearch',
|
||||
renderWizard: ({ onPreviewSource, inspectorAdapters }) => {
|
||||
const onSourceConfigChange = sourceConfig => {
|
||||
if (!sourceConfig) {
|
||||
onPreviewSource(null);
|
||||
return;
|
||||
}
|
||||
|
||||
const source = new ESSearchSource(
|
||||
{
|
||||
id: uuid(),
|
||||
...sourceConfig,
|
||||
},
|
||||
inspectorAdapters
|
||||
);
|
||||
onPreviewSource(source);
|
||||
};
|
||||
return <CreateSourceEditor onSourceConfigChange={onSourceConfigChange} />;
|
||||
},
|
||||
title: sourceTitle,
|
||||
};
|
||||
|
|
|
@ -4,4 +4,4 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
export { ESSearchSource } from './es_search_source';
|
||||
export { ESSearchSource, esDocumentsLayerWizardConfig } from './es_search_source';
|
||||
|
|
|
@ -23,8 +23,6 @@ import { DataRequestAbortError } from '../util/data_request';
|
|||
import { expandToTileBoundaries } from './es_geo_grid_source/geo_tile_utils';
|
||||
|
||||
export class AbstractESSource extends AbstractVectorSource {
|
||||
static icon = 'logoElasticsearch';
|
||||
|
||||
constructor(descriptor, inspectorAdapters) {
|
||||
super(
|
||||
{
|
||||
|
|
|
@ -4,4 +4,4 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
export { KibanaRegionmapSource } from './kibana_regionmap_source';
|
||||
export { KibanaRegionmapSource, kibanaRegionMapLayerWizardConfig } from './kibana_regionmap_source';
|
||||
|
|
|
@ -10,18 +10,16 @@ import { CreateSourceEditor } from './create_source_editor';
|
|||
import { getKibanaRegionList } from '../../../meta';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { getDataSourceLabel } from '../../../../common/i18n_getters';
|
||||
import { FIELD_ORIGIN } from '../../../../common/constants';
|
||||
import { FIELD_ORIGIN, REGIONMAP_FILE } from '../../../../common/constants';
|
||||
import { KibanaRegionField } from '../../fields/kibana_region_field';
|
||||
import { registerSource } from '../source_registry';
|
||||
|
||||
const sourceTitle = i18n.translate('xpack.maps.source.kbnRegionMapTitle', {
|
||||
defaultMessage: 'Configured GeoJSON',
|
||||
});
|
||||
|
||||
export class KibanaRegionmapSource extends AbstractVectorSource {
|
||||
static type = 'REGIONMAP_FILE';
|
||||
static title = i18n.translate('xpack.maps.source.kbnRegionMapTitle', {
|
||||
defaultMessage: 'Configured GeoJSON',
|
||||
});
|
||||
static description = i18n.translate('xpack.maps.source.kbnRegionMapDescription', {
|
||||
defaultMessage: 'Vector data from hosted GeoJSON configured in kibana.yml',
|
||||
});
|
||||
static icon = 'logoKibana';
|
||||
static type = REGIONMAP_FILE;
|
||||
|
||||
static createDescriptor({ name }) {
|
||||
return {
|
||||
|
@ -30,16 +28,6 @@ export class KibanaRegionmapSource extends AbstractVectorSource {
|
|||
};
|
||||
}
|
||||
|
||||
static renderEditor = ({ onPreviewSource, inspectorAdapters }) => {
|
||||
const onSourceConfigChange = sourceConfig => {
|
||||
const sourceDescriptor = KibanaRegionmapSource.createDescriptor(sourceConfig);
|
||||
const source = new KibanaRegionmapSource(sourceDescriptor, inspectorAdapters);
|
||||
onPreviewSource(source);
|
||||
};
|
||||
|
||||
return <CreateSourceEditor onSourceConfigChange={onSourceConfigChange} />;
|
||||
};
|
||||
|
||||
createField({ fieldName }) {
|
||||
return new KibanaRegionField({
|
||||
fieldName,
|
||||
|
@ -52,7 +40,7 @@ export class KibanaRegionmapSource extends AbstractVectorSource {
|
|||
return [
|
||||
{
|
||||
label: getDataSourceLabel(),
|
||||
value: KibanaRegionmapSource.title,
|
||||
value: sourceTitle,
|
||||
},
|
||||
{
|
||||
label: i18n.translate('xpack.maps.source.kbnRegionMap.vectorLayerLabel', {
|
||||
|
@ -108,3 +96,25 @@ export class KibanaRegionmapSource extends AbstractVectorSource {
|
|||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
registerSource({
|
||||
ConstructorFunction: KibanaRegionmapSource,
|
||||
type: REGIONMAP_FILE,
|
||||
});
|
||||
|
||||
export const kibanaRegionMapLayerWizardConfig = {
|
||||
description: i18n.translate('xpack.maps.source.kbnRegionMapDescription', {
|
||||
defaultMessage: 'Vector data from hosted GeoJSON configured in kibana.yml',
|
||||
}),
|
||||
icon: 'logoKibana',
|
||||
renderWizard: ({ onPreviewSource, inspectorAdapters }) => {
|
||||
const onSourceConfigChange = sourceConfig => {
|
||||
const sourceDescriptor = KibanaRegionmapSource.createDescriptor(sourceConfig);
|
||||
const source = new KibanaRegionmapSource(sourceDescriptor, inspectorAdapters);
|
||||
onPreviewSource(source);
|
||||
};
|
||||
|
||||
return <CreateSourceEditor onSourceConfigChange={onSourceConfigChange} />;
|
||||
},
|
||||
title: sourceTitle,
|
||||
};
|
||||
|
|
|
@ -4,4 +4,4 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
export { KibanaTilemapSource } from './kibana_tilemap_source';
|
||||
export { KibanaTilemapSource, kibanaBasemapLayerWizardConfig } from './kibana_tilemap_source';
|
||||
|
|
|
@ -11,17 +11,15 @@ import { getKibanaTileMap } from '../../../meta';
|
|||
import { i18n } from '@kbn/i18n';
|
||||
import { getDataSourceLabel } from '../../../../common/i18n_getters';
|
||||
import _ from 'lodash';
|
||||
import { KIBANA_TILEMAP } from '../../../../common/constants';
|
||||
import { registerSource } from '../source_registry';
|
||||
|
||||
const sourceTitle = i18n.translate('xpack.maps.source.kbnTMSTitle', {
|
||||
defaultMessage: 'Configured Tile Map Service',
|
||||
});
|
||||
|
||||
export class KibanaTilemapSource extends AbstractTMSSource {
|
||||
static type = 'KIBANA_TILEMAP';
|
||||
static title = i18n.translate('xpack.maps.source.kbnTMSTitle', {
|
||||
defaultMessage: 'Configured Tile Map Service',
|
||||
});
|
||||
static description = i18n.translate('xpack.maps.source.kbnTMSDescription', {
|
||||
defaultMessage: 'Tile map service configured in kibana.yml',
|
||||
});
|
||||
|
||||
static icon = 'logoKibana';
|
||||
static type = KIBANA_TILEMAP;
|
||||
|
||||
static createDescriptor() {
|
||||
return {
|
||||
|
@ -29,20 +27,11 @@ export class KibanaTilemapSource extends AbstractTMSSource {
|
|||
};
|
||||
}
|
||||
|
||||
static renderEditor = ({ onPreviewSource, inspectorAdapters }) => {
|
||||
const onSourceConfigChange = () => {
|
||||
const sourceDescriptor = KibanaTilemapSource.createDescriptor();
|
||||
const source = new KibanaTilemapSource(sourceDescriptor, inspectorAdapters);
|
||||
onPreviewSource(source);
|
||||
};
|
||||
return <CreateSourceEditor onSourceConfigChange={onSourceConfigChange} />;
|
||||
};
|
||||
|
||||
async getImmutableProperties() {
|
||||
return [
|
||||
{
|
||||
label: getDataSourceLabel(),
|
||||
value: KibanaTilemapSource.title,
|
||||
value: sourceTitle,
|
||||
},
|
||||
{
|
||||
label: i18n.translate('xpack.maps.source.kbnTMS.urlLabel', {
|
||||
|
@ -94,3 +83,24 @@ export class KibanaTilemapSource extends AbstractTMSSource {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
registerSource({
|
||||
ConstructorFunction: KibanaTilemapSource,
|
||||
type: KIBANA_TILEMAP,
|
||||
});
|
||||
|
||||
export const kibanaBasemapLayerWizardConfig = {
|
||||
description: i18n.translate('xpack.maps.source.kbnTMSDescription', {
|
||||
defaultMessage: 'Tile map service configured in kibana.yml',
|
||||
}),
|
||||
icon: 'logoKibana',
|
||||
renderWizard: ({ onPreviewSource, inspectorAdapters }) => {
|
||||
const onSourceConfigChange = () => {
|
||||
const sourceDescriptor = KibanaTilemapSource.createDescriptor();
|
||||
const source = new KibanaTilemapSource(sourceDescriptor, inspectorAdapters);
|
||||
onPreviewSource(source);
|
||||
};
|
||||
return <CreateSourceEditor onSourceConfigChange={onSourceConfigChange} />;
|
||||
},
|
||||
title: sourceTitle,
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
/* eslint-disable @typescript-eslint/consistent-type-definitions */
|
||||
|
||||
import { AbstractSourceDescriptor } from '../../../common/descriptor_types';
|
||||
import { ISource } from './source';
|
||||
|
||||
type SourceRegistryEntry = {
|
||||
ConstructorFunction: new (
|
||||
sourceDescriptor: AbstractSourceDescriptor,
|
||||
inspectorAdapters: unknown
|
||||
) => ISource;
|
||||
type: string;
|
||||
};
|
||||
|
||||
const registry: SourceRegistryEntry[] = [];
|
||||
|
||||
export function registerSource(entry: SourceRegistryEntry) {
|
||||
const sourceTypeExists = registry.some(({ type }: SourceRegistryEntry) => {
|
||||
return entry.type === type;
|
||||
});
|
||||
if (sourceTypeExists) {
|
||||
throw new Error(
|
||||
`Unable to register source type ${entry.type}. ${entry.type} has already been registered`
|
||||
);
|
||||
}
|
||||
registry.push(entry);
|
||||
}
|
||||
|
||||
export function getSourceByType(sourceType: string): SourceRegistryEntry | undefined {
|
||||
return registry.find((source: SourceRegistryEntry) => source.type === sourceType);
|
||||
}
|
|
@ -4,4 +4,4 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
export { WMSSource } from './wms_source';
|
||||
export { WMSSource, wmsLayerWizardConfig } from './wms_source';
|
||||
|
|
|
@ -12,16 +12,15 @@ import { WMSCreateSourceEditor } from './wms_create_source_editor';
|
|||
import { i18n } from '@kbn/i18n';
|
||||
import { getDataSourceLabel, getUrlLabel } from '../../../../common/i18n_getters';
|
||||
import { WmsClient } from './wms_client';
|
||||
import { WMS } from '../../../../common/constants';
|
||||
import { registerSource } from '../source_registry';
|
||||
|
||||
const sourceTitle = i18n.translate('xpack.maps.source.wmsTitle', {
|
||||
defaultMessage: 'Web Map Service',
|
||||
});
|
||||
|
||||
export class WMSSource extends AbstractTMSSource {
|
||||
static type = 'WMS';
|
||||
static title = i18n.translate('xpack.maps.source.wmsTitle', {
|
||||
defaultMessage: 'Web Map Service',
|
||||
});
|
||||
static description = i18n.translate('xpack.maps.source.wmsDescription', {
|
||||
defaultMessage: 'Maps from OGC Standard WMS',
|
||||
});
|
||||
static icon = 'grid';
|
||||
static type = WMS;
|
||||
|
||||
static createDescriptor({ serviceUrl, layers, styles, attributionText, attributionUrl }) {
|
||||
return {
|
||||
|
@ -34,23 +33,9 @@ export class WMSSource extends AbstractTMSSource {
|
|||
};
|
||||
}
|
||||
|
||||
static renderEditor({ onPreviewSource, inspectorAdapters }) {
|
||||
const onSourceConfigChange = sourceConfig => {
|
||||
if (!sourceConfig) {
|
||||
onPreviewSource(null);
|
||||
return;
|
||||
}
|
||||
|
||||
const sourceDescriptor = WMSSource.createDescriptor(sourceConfig);
|
||||
const source = new WMSSource(sourceDescriptor, inspectorAdapters);
|
||||
onPreviewSource(source);
|
||||
};
|
||||
return <WMSCreateSourceEditor onSourceConfigChange={onSourceConfigChange} />;
|
||||
}
|
||||
|
||||
async getImmutableProperties() {
|
||||
return [
|
||||
{ label: getDataSourceLabel(), value: WMSSource.title },
|
||||
{ label: getDataSourceLabel(), value: sourceTitle },
|
||||
{ label: getUrlLabel(), value: this._descriptor.serviceUrl },
|
||||
{
|
||||
label: i18n.translate('xpack.maps.source.wms.layersLabel', {
|
||||
|
@ -104,3 +89,29 @@ export class WMSSource extends AbstractTMSSource {
|
|||
return client.getUrlTemplate(this._descriptor.layers, this._descriptor.styles || '');
|
||||
}
|
||||
}
|
||||
|
||||
registerSource({
|
||||
ConstructorFunction: WMSSource,
|
||||
type: WMS,
|
||||
});
|
||||
|
||||
export const wmsLayerWizardConfig = {
|
||||
description: i18n.translate('xpack.maps.source.wmsDescription', {
|
||||
defaultMessage: 'Maps from OGC Standard WMS',
|
||||
}),
|
||||
icon: 'grid',
|
||||
renderWizard: ({ onPreviewSource, inspectorAdapters }) => {
|
||||
const onSourceConfigChange = sourceConfig => {
|
||||
if (!sourceConfig) {
|
||||
onPreviewSource(null);
|
||||
return;
|
||||
}
|
||||
|
||||
const sourceDescriptor = WMSSource.createDescriptor(sourceConfig);
|
||||
const source = new WMSSource(sourceDescriptor, inspectorAdapters);
|
||||
onPreviewSource(source);
|
||||
};
|
||||
return <WMSCreateSourceEditor onSourceConfigChange={onSourceConfigChange} />;
|
||||
},
|
||||
title: sourceTitle,
|
||||
};
|
||||
|
|
|
@ -13,16 +13,14 @@ import { i18n } from '@kbn/i18n';
|
|||
import { getDataSourceLabel, getUrlLabel } from '../../../common/i18n_getters';
|
||||
import _ from 'lodash';
|
||||
import { EMS_XYZ } from '../../../common/constants';
|
||||
import { registerSource } from './source_registry';
|
||||
|
||||
const sourceTitle = i18n.translate('xpack.maps.source.ems_xyzTitle', {
|
||||
defaultMessage: 'Tile Map Service',
|
||||
});
|
||||
|
||||
export class XYZTMSSource extends AbstractTMSSource {
|
||||
static type = EMS_XYZ;
|
||||
static title = i18n.translate('xpack.maps.source.ems_xyzTitle', {
|
||||
defaultMessage: 'Tile Map Service',
|
||||
});
|
||||
static description = i18n.translate('xpack.maps.source.ems_xyzDescription', {
|
||||
defaultMessage: 'Tile map service configured in interface',
|
||||
});
|
||||
static icon = 'grid';
|
||||
|
||||
static createDescriptor({ urlTemplate, attributionText, attributionUrl }) {
|
||||
return {
|
||||
|
@ -33,18 +31,9 @@ export class XYZTMSSource extends AbstractTMSSource {
|
|||
};
|
||||
}
|
||||
|
||||
static renderEditor({ onPreviewSource, inspectorAdapters }) {
|
||||
const onSourceConfigChange = sourceConfig => {
|
||||
const sourceDescriptor = XYZTMSSource.createDescriptor(sourceConfig);
|
||||
const source = new XYZTMSSource(sourceDescriptor, inspectorAdapters);
|
||||
onPreviewSource(source);
|
||||
};
|
||||
return <XYZTMSEditor onSourceConfigChange={onSourceConfigChange} />;
|
||||
}
|
||||
|
||||
async getImmutableProperties() {
|
||||
return [
|
||||
{ label: getDataSourceLabel(), value: XYZTMSSource.title },
|
||||
{ label: getDataSourceLabel(), value: sourceTitle },
|
||||
{ label: getUrlLabel(), value: this._descriptor.urlTemplate },
|
||||
];
|
||||
}
|
||||
|
@ -175,3 +164,24 @@ class XYZTMSEditor extends React.Component {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
registerSource({
|
||||
ConstructorFunction: XYZTMSSource,
|
||||
type: EMS_XYZ,
|
||||
});
|
||||
|
||||
export const tmsLayerWizardConfig = {
|
||||
description: i18n.translate('xpack.maps.source.ems_xyzDescription', {
|
||||
defaultMessage: 'Tile map service configured in interface',
|
||||
}),
|
||||
icon: 'grid',
|
||||
renderWizard: ({ onPreviewSource, inspectorAdapters }) => {
|
||||
const onSourceConfigChange = sourceConfig => {
|
||||
const sourceDescriptor = XYZTMSSource.createDescriptor(sourceConfig);
|
||||
const source = new XYZTMSSource(sourceDescriptor, inspectorAdapters);
|
||||
onPreviewSource(source);
|
||||
};
|
||||
return <XYZTMSEditor onSourceConfigChange={onSourceConfigChange} />;
|
||||
},
|
||||
title: sourceTitle,
|
||||
};
|
||||
|
|
|
@ -4,6 +4,10 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import './layers/layer_wizard_registry';
|
||||
import './layers/sources/source_registry';
|
||||
import './layers/load_layer_wizards';
|
||||
|
||||
import { Plugin, CoreStart, CoreSetup } from 'src/core/public';
|
||||
// @ts-ignore
|
||||
import { wrapInI18nContext } from 'ui/i18n';
|
||||
|
|
|
@ -11,7 +11,6 @@ import { VectorTileLayer } from '../layers/vector_tile_layer';
|
|||
import { VectorLayer } from '../layers/vector_layer';
|
||||
import { HeatmapLayer } from '../layers/heatmap_layer';
|
||||
import { BlendedVectorLayer } from '../layers/blended_vector_layer';
|
||||
import { ALL_SOURCES } from '../layers/sources/all_sources';
|
||||
import { getTimeFilter } from '../kibana_services';
|
||||
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
|
||||
import { getInspectorAdapters } from '../../../../../plugins/maps/public/reducers/non_serializable_instances';
|
||||
|
@ -21,6 +20,7 @@ import {
|
|||
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
|
||||
} from '../../../../../plugins/maps/public/reducers/util';
|
||||
import { InnerJoin } from '../layers/joins/inner_join';
|
||||
import { getSourceByType } from '../layers/sources/source_registry';
|
||||
|
||||
function createLayerInstance(layerDescriptor, inspectorAdapters) {
|
||||
const source = createSourceInstance(layerDescriptor.sourceDescriptor, inspectorAdapters);
|
||||
|
@ -49,13 +49,11 @@ function createLayerInstance(layerDescriptor, inspectorAdapters) {
|
|||
}
|
||||
|
||||
function createSourceInstance(sourceDescriptor, inspectorAdapters) {
|
||||
const Source = ALL_SOURCES.find(Source => {
|
||||
return Source.type === sourceDescriptor.type;
|
||||
});
|
||||
if (!Source) {
|
||||
const source = getSourceByType(sourceDescriptor.type);
|
||||
if (!source) {
|
||||
throw new Error(`Unrecognized sourceType ${sourceDescriptor.type}`);
|
||||
}
|
||||
return new Source(sourceDescriptor, inspectorAdapters);
|
||||
return new source.ConstructorFunction(sourceDescriptor, inspectorAdapters);
|
||||
}
|
||||
|
||||
export const getOpenTooltips = ({ map }) => {
|
||||
|
|
|
@ -8,7 +8,6 @@ jest.mock('../layers/vector_layer', () => {});
|
|||
jest.mock('../layers/blended_vector_layer', () => {});
|
||||
jest.mock('../layers/heatmap_layer', () => {});
|
||||
jest.mock('../layers/vector_tile_layer', () => {});
|
||||
jest.mock('../layers/sources/all_sources', () => {});
|
||||
jest.mock('../layers/joins/inner_join', () => {});
|
||||
jest.mock('../../../../../plugins/maps/public/reducers/non_serializable_instances', () => ({
|
||||
getInspectorAdapters: () => {
|
||||
|
|
|
@ -62,6 +62,9 @@ export const ES_GEO_GRID = 'ES_GEO_GRID';
|
|||
export const ES_SEARCH = 'ES_SEARCH';
|
||||
export const ES_PEW_PEW = 'ES_PEW_PEW';
|
||||
export const EMS_XYZ = 'EMS_XYZ'; // identifies a custom TMS source. Name is a little unfortunate.
|
||||
export const WMS = 'WMS';
|
||||
export const KIBANA_TILEMAP = 'KIBANA_TILEMAP';
|
||||
export const REGIONMAP_FILE = 'REGIONMAP_FILE';
|
||||
|
||||
export enum FIELD_ORIGIN {
|
||||
SOURCE = 'source',
|
||||
|
|
|
@ -7137,12 +7137,10 @@
|
|||
"xpack.maps.source.esGeoGrid.geofieldLabel": "地理空間フィールド",
|
||||
"xpack.maps.source.esGeoGrid.geofieldPlaceholder": "ジオフィールドを選択",
|
||||
"xpack.maps.source.esGeoGrid.gridRectangleDropdownOption": "グリッド四角",
|
||||
"xpack.maps.source.esGeoGrid.heatmapDropdownOption": "ヒートマップ",
|
||||
"xpack.maps.source.esGeoGrid.indexPatternLabel": "インデックスパターン",
|
||||
"xpack.maps.source.esGeoGrid.indexPatternPlaceholder": "インデックスパターンを選択",
|
||||
"xpack.maps.source.esGeoGrid.pointsDropdownOption": "点",
|
||||
"xpack.maps.source.esGeoGrid.showAsLabel": "表示形式",
|
||||
"xpack.maps.source.esGeoGrid.showAsPlaceholder": "1 つのオプションを選択",
|
||||
"xpack.maps.source.esGrid.coarseDropdownOption": "粗い",
|
||||
"xpack.maps.source.esGrid.fineDropdownOption": "細かい",
|
||||
"xpack.maps.source.esGrid.finestDropdownOption": "最も細かい",
|
||||
|
@ -7151,9 +7149,6 @@
|
|||
"xpack.maps.source.esGrid.metricsLabel": "メトリック",
|
||||
"xpack.maps.source.esGrid.noIndexPatternErrorMessage": "インデックスパターン {id} が見つかりません",
|
||||
"xpack.maps.source.esGrid.resolutionParamErrorMessage": "グリッド解像度パラメーターが認識されません: {resolution}",
|
||||
"xpack.maps.source.esGrid.showasFieldLabel": "表示形式",
|
||||
"xpack.maps.source.esGridDescription": "それぞれのグリッド付きセルのメトリックでグリッドにグループ分けされた地理空間データです。",
|
||||
"xpack.maps.source.esGridTitle": "グリッド集約",
|
||||
"xpack.maps.source.esSearch.convertToGeoJsonErrorMsg": "検索への応答を geoJson 機能コレクションに変換できません。エラー: {errorMsg}",
|
||||
"xpack.maps.source.esSearch.extentFilterLabel": "マップの表示範囲でデータを動的にフィルタリング",
|
||||
"xpack.maps.source.esSearch.geofieldLabel": "地理空間フィールド",
|
||||
|
|
|
@ -7137,12 +7137,10 @@
|
|||
"xpack.maps.source.esGeoGrid.geofieldLabel": "地理空间字段",
|
||||
"xpack.maps.source.esGeoGrid.geofieldPlaceholder": "选择地理字段",
|
||||
"xpack.maps.source.esGeoGrid.gridRectangleDropdownOption": "网格矩形",
|
||||
"xpack.maps.source.esGeoGrid.heatmapDropdownOption": "热图",
|
||||
"xpack.maps.source.esGeoGrid.indexPatternLabel": "索引模式",
|
||||
"xpack.maps.source.esGeoGrid.indexPatternPlaceholder": "选择索引模式",
|
||||
"xpack.maps.source.esGeoGrid.pointsDropdownOption": "磅",
|
||||
"xpack.maps.source.esGeoGrid.showAsLabel": "显示为",
|
||||
"xpack.maps.source.esGeoGrid.showAsPlaceholder": "选择单个选项",
|
||||
"xpack.maps.source.esGrid.coarseDropdownOption": "粗糙",
|
||||
"xpack.maps.source.esGrid.fineDropdownOption": "精致",
|
||||
"xpack.maps.source.esGrid.finestDropdownOption": "最精致化",
|
||||
|
@ -7151,9 +7149,6 @@
|
|||
"xpack.maps.source.esGrid.metricsLabel": "指标",
|
||||
"xpack.maps.source.esGrid.noIndexPatternErrorMessage": "找不到索引模式 {id}",
|
||||
"xpack.maps.source.esGrid.resolutionParamErrorMessage": "无法识别网格分辨率参数:{resolution}",
|
||||
"xpack.maps.source.esGrid.showasFieldLabel": "显示为",
|
||||
"xpack.maps.source.esGridDescription": "地理空间数据在网格中进行分组,每个网格单元格都具有指标",
|
||||
"xpack.maps.source.esGridTitle": "网格聚合",
|
||||
"xpack.maps.source.esSearch.convertToGeoJsonErrorMsg": "无法将搜索响应转换成 geoJson 功能集合,错误:{errorMsg}",
|
||||
"xpack.maps.source.esSearch.extentFilterLabel": "在可见地图区域中动态筛留数据",
|
||||
"xpack.maps.source.esSearch.geofieldLabel": "地理空间字段",
|
||||
|
|
|
@ -511,7 +511,7 @@ export function GisPageProvider({ getService, getPageObjects }) {
|
|||
|
||||
async selectGeoJsonUploadSource() {
|
||||
log.debug(`Select upload geojson source`);
|
||||
await testSubjects.click('uploadedGeoJson');
|
||||
await testSubjects.click('uploadGeoJson');
|
||||
}
|
||||
|
||||
async uploadJsonFileForIndexing(path) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue