mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[Maps] Cleanup sources (#63175)
- Introduces additional TS typing for sources - Organizes sources in sub-directories by type - migrates XYZTMSSource to TS
This commit is contained in:
parent
36b4ad9888
commit
bbd501ea51
34 changed files with 392 additions and 270 deletions
|
@ -87,6 +87,8 @@ export function buildMapsTelemetry({
|
|||
const mapsCount = layerLists.length;
|
||||
|
||||
const dataSourcesCount = layerLists.map(lList => {
|
||||
// todo: not every source-descriptor has an id
|
||||
// @ts-ignore
|
||||
const sourceIdList = lList.map((layer: LayerDescriptor) => layer.sourceDescriptor.id);
|
||||
return _.uniq(sourceIdList).length;
|
||||
});
|
||||
|
|
|
@ -9,6 +9,11 @@ import { AGG_TYPE, GRID_RESOLUTION, RENDER_AS, SORT_ORDER, SCALING_TYPES } from
|
|||
import { VectorStyleDescriptor } from './style_property_descriptor_types';
|
||||
import { DataRequestDescriptor } from './data_request_descriptor_types';
|
||||
|
||||
export type AttributionDescriptor = {
|
||||
attributionText?: string;
|
||||
attributionUrl?: string;
|
||||
};
|
||||
|
||||
export type AbstractSourceDescriptor = {
|
||||
id?: string;
|
||||
type: string;
|
||||
|
@ -84,17 +89,26 @@ export type WMSSourceDescriptor = {
|
|||
attributionUrl: string;
|
||||
};
|
||||
|
||||
export type XYZTMSSourceDescriptor = {
|
||||
id: string;
|
||||
type: string;
|
||||
urlTemplate: string;
|
||||
};
|
||||
export type XYZTMSSourceDescriptor = AbstractSourceDescriptor &
|
||||
AttributionDescriptor & {
|
||||
urlTemplate: string;
|
||||
};
|
||||
|
||||
export type JoinDescriptor = {
|
||||
leftField: string;
|
||||
right: ESTermSourceDescriptor;
|
||||
};
|
||||
|
||||
export type SourceDescriptor =
|
||||
| XYZTMSSourceDescriptor
|
||||
| WMSSourceDescriptor
|
||||
| KibanaTilemapSourceDescriptor
|
||||
| KibanaRegionmapSourceDescriptor
|
||||
| ESTermSourceDescriptor
|
||||
| ESSearchSourceDescriptor
|
||||
| ESGeoGridSourceDescriptor
|
||||
| EMSFileSourceDescriptor;
|
||||
|
||||
export type LayerDescriptor = {
|
||||
__dataRequests?: DataRequestDescriptor[];
|
||||
__isInErrorState?: boolean;
|
||||
|
@ -104,7 +118,7 @@ export type LayerDescriptor = {
|
|||
label?: string;
|
||||
minZoom?: number;
|
||||
maxZoom?: number;
|
||||
sourceDescriptor: AbstractSourceDescriptor;
|
||||
sourceDescriptor: SourceDescriptor;
|
||||
type?: string;
|
||||
visible?: boolean;
|
||||
};
|
||||
|
|
|
@ -34,6 +34,7 @@ import {
|
|||
VectorStyleDescriptor,
|
||||
SizeDynamicOptions,
|
||||
DynamicStylePropertyOptions,
|
||||
VectorLayerDescriptor,
|
||||
} from '../../common/descriptor_types';
|
||||
|
||||
const ACTIVE_COUNT_DATA_ID = 'ACTIVE_COUNT_DATA_ID';
|
||||
|
@ -147,7 +148,10 @@ function getClusterStyleDescriptor(
|
|||
export class BlendedVectorLayer extends VectorLayer implements IVectorLayer {
|
||||
static type = LAYER_TYPE.BLENDED_VECTOR;
|
||||
|
||||
static createDescriptor(options: VectorLayerArguments, mapColors: string[]) {
|
||||
static createDescriptor(
|
||||
options: VectorLayerDescriptor,
|
||||
mapColors: string[]
|
||||
): VectorLayerDescriptor {
|
||||
const layerDescriptor = VectorLayer.createDescriptor(options, mapColors);
|
||||
layerDescriptor.type = BlendedVectorLayer.type;
|
||||
return layerDescriptor;
|
||||
|
|
1
x-pack/plugins/maps/public/layers/layer.d.ts
vendored
1
x-pack/plugins/maps/public/layers/layer.d.ts
vendored
|
@ -25,6 +25,7 @@ export interface ILayerArguments {
|
|||
}
|
||||
|
||||
export class AbstractLayer implements ILayer {
|
||||
static createDescriptor(options: Partial<LayerDescriptor>, mapColors?: string[]): LayerDescriptor;
|
||||
constructor(layerArguments: ILayerArguments);
|
||||
getBounds(mapFilters: MapFilters): Promise<MapExtent>;
|
||||
getDataRequest(id: string): DataRequest | undefined;
|
||||
|
|
|
@ -5,17 +5,21 @@
|
|||
*/
|
||||
/* eslint-disable @typescript-eslint/consistent-type-definitions */
|
||||
|
||||
type LayerWizard = {
|
||||
import { ReactElement } from 'react';
|
||||
import { ISource } from './sources/source';
|
||||
|
||||
export type PreviewSourceHandler = (source: ISource | null) => void;
|
||||
|
||||
export type RenderWizardArguments = {
|
||||
onPreviewSource: PreviewSourceHandler;
|
||||
inspectorAdapters: object;
|
||||
};
|
||||
|
||||
export type LayerWizard = {
|
||||
description: string;
|
||||
icon: string;
|
||||
isIndexingSource?: boolean;
|
||||
renderWizard({
|
||||
onPreviewSource,
|
||||
inspectorAdapters,
|
||||
}: {
|
||||
onPreviewSource: () => void;
|
||||
inspectorAdapters: unknown;
|
||||
}): unknown;
|
||||
renderWizard(renderWizardArguments: RenderWizardArguments): ReactElement<any>;
|
||||
title: string;
|
||||
};
|
||||
|
||||
|
|
|
@ -4,11 +4,11 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { IESSource } from './es_source';
|
||||
import { AbstractESSource } from './es_source';
|
||||
import { AGG_TYPE } from '../../../common/constants';
|
||||
import { IESAggField } from '../fields/es_agg_field';
|
||||
import { AbstractESAggSourceDescriptor } from '../../../common/descriptor_types';
|
||||
import { IESSource } from '../es_source';
|
||||
import { AbstractESSource } from '../es_source';
|
||||
import { AGG_TYPE } from '../../../../common/constants';
|
||||
import { IESAggField } from '../../fields/es_agg_field';
|
||||
import { AbstractESAggSourceDescriptor } from '../../../../common/descriptor_types';
|
||||
|
||||
export interface IESAggSource extends IESSource {
|
||||
getAggKey(aggType: AGG_TYPE, fieldName: string): string;
|
|
@ -5,15 +5,15 @@
|
|||
*/
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { AbstractESSource } from './es_source';
|
||||
import { esAggFieldsFactory } from '../fields/es_agg_field';
|
||||
import { AbstractESSource } from '../es_source';
|
||||
import { esAggFieldsFactory } from '../../fields/es_agg_field';
|
||||
|
||||
import {
|
||||
AGG_TYPE,
|
||||
COUNT_PROP_LABEL,
|
||||
COUNT_PROP_NAME,
|
||||
FIELD_ORIGIN,
|
||||
} from '../../../common/constants';
|
||||
} from '../../../../common/constants';
|
||||
|
||||
export const AGG_DELIMITER = '_of_';
|
||||
|
|
@ -4,12 +4,12 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { AbstractESAggSource } from './es_agg_source';
|
||||
import { IField } from '../fields/field';
|
||||
import { IESAggField } from '../fields/es_agg_field';
|
||||
import { AbstractESAggSource } from '../es_agg_source';
|
||||
import { IField } from '../../fields/field';
|
||||
import { IESAggField } from '../../fields/es_agg_field';
|
||||
import _ from 'lodash';
|
||||
import { AGG_TYPE } from '../../../common/constants';
|
||||
import { AggDescriptor } from '../../../common/descriptor_types';
|
||||
import { AGG_TYPE } from '../../../../common/constants';
|
||||
import { AggDescriptor } from '../../../../common/descriptor_types';
|
||||
|
||||
jest.mock('ui/new_platform');
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export * from './es_agg_source';
|
|
@ -4,10 +4,10 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { AbstractVectorSource } from './vector_source';
|
||||
import { IVectorSource } from './vector_source';
|
||||
import { IndexPattern, SearchSource } from '../../../../../../src/plugins/data/public';
|
||||
import { VectorSourceRequestMeta } from '../../../common/descriptor_types';
|
||||
import { AbstractVectorSource } from '../vector_source';
|
||||
import { IVectorSource } from '../vector_source';
|
||||
import { IndexPattern, SearchSource } from '../../../../../../../src/plugins/data/public';
|
||||
import { VectorSourceRequestMeta } from '../../../../common/descriptor_types';
|
||||
|
||||
export interface IESSource extends IVectorSource {
|
||||
getId(): string;
|
|
@ -4,23 +4,23 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { AbstractVectorSource } from './vector_source';
|
||||
import { AbstractVectorSource } from '../vector_source';
|
||||
import {
|
||||
getAutocompleteService,
|
||||
fetchSearchSourceAndRecordWithInspector,
|
||||
getIndexPatternService,
|
||||
SearchSource,
|
||||
getTimeFilter,
|
||||
} from '../../kibana_services';
|
||||
import { createExtentFilter } from '../../elasticsearch_geo_utils';
|
||||
} from '../../../kibana_services';
|
||||
import { createExtentFilter } from '../../../elasticsearch_geo_utils';
|
||||
import _ from 'lodash';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import uuid from 'uuid/v4';
|
||||
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
|
||||
import { copyPersistentState } from '../../reducers/util';
|
||||
import { ES_GEO_FIELD_TYPE } from '../../../common/constants';
|
||||
import { DataRequestAbortError } from '../util/data_request';
|
||||
import { expandToTileBoundaries } from './es_geo_grid_source/geo_tile_utils';
|
||||
import { copyPersistentState } from '../../../reducers/util';
|
||||
import { ES_GEO_FIELD_TYPE } from '../../../../common/constants';
|
||||
import { DataRequestAbortError } from '../../util/data_request';
|
||||
import { expandToTileBoundaries } from '../es_geo_grid_source/geo_tile_utils';
|
||||
|
||||
export class AbstractESSource extends AbstractVectorSource {
|
||||
constructor(descriptor, inspectorAdapters) {
|
|
@ -0,0 +1,7 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export * from './es_source';
|
|
@ -4,8 +4,8 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { IField } from '../fields/field';
|
||||
import { IESAggSource } from './es_agg_source';
|
||||
import { IField } from '../../fields/field';
|
||||
import { IESAggSource } from '../es_agg_source';
|
||||
|
||||
export interface IESTermSource extends IESAggSource {
|
||||
getTermField(): IField;
|
|
@ -7,10 +7,10 @@
|
|||
import _ from 'lodash';
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { DEFAULT_MAX_BUCKETS_LIMIT, FIELD_ORIGIN, AGG_TYPE } from '../../../common/constants';
|
||||
import { ESDocField } from '../fields/es_doc_field';
|
||||
import { AbstractESAggSource, AGG_DELIMITER } from './es_agg_source';
|
||||
import { getField, addFieldToDSL, extractPropertiesFromBucket } from '../util/es_agg_utils';
|
||||
import { DEFAULT_MAX_BUCKETS_LIMIT, FIELD_ORIGIN, AGG_TYPE } from '../../../../common/constants';
|
||||
import { ESDocField } from '../../fields/es_doc_field';
|
||||
import { AbstractESAggSource, AGG_DELIMITER } from '../es_agg_source';
|
||||
import { getField, addFieldToDSL, extractPropertiesFromBucket } from '../../util/es_agg_utils';
|
||||
|
||||
const TERMS_AGG_NAME = 'join';
|
||||
|
|
@ -7,7 +7,7 @@
|
|||
import { ESTermSource, extractPropertiesMap } from './es_term_source';
|
||||
|
||||
jest.mock('ui/new_platform');
|
||||
jest.mock('../vector_layer', () => {});
|
||||
jest.mock('../../vector_layer', () => {});
|
||||
|
||||
const indexPatternTitle = 'myIndex';
|
||||
const termFieldName = 'myTermField';
|
|
@ -0,0 +1,7 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export * from './es_term_source';
|
|
@ -3,10 +3,21 @@
|
|||
* 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 { AbstractSourceDescriptor, LayerDescriptor } from '../../../common/descriptor_types';
|
||||
import { ILayer } from '../layer';
|
||||
|
||||
export type ImmutableSourceProperty = {
|
||||
label: string;
|
||||
value: string;
|
||||
};
|
||||
|
||||
export type Attribution = {
|
||||
url: string;
|
||||
label: string;
|
||||
};
|
||||
|
||||
export interface ISource {
|
||||
createDefaultLayer(): ILayer;
|
||||
destroy(): void;
|
||||
|
@ -18,13 +29,16 @@ export interface ISource {
|
|||
isQueryAware(): boolean;
|
||||
isRefreshTimerAware(): Promise<boolean>;
|
||||
isTimeAware(): Promise<boolean>;
|
||||
getImmutableProperties(): Promise<ImmutableSourceProperty[]>;
|
||||
getAttributions(): Promise<Attribution[]>;
|
||||
}
|
||||
|
||||
export class AbstractSource implements ISource {
|
||||
constructor(sourceDescriptor: AbstractSourceDescriptor, inspectorAdapters: object);
|
||||
readonly _descriptor: AbstractSourceDescriptor;
|
||||
constructor(sourceDescriptor: AbstractSourceDescriptor, inspectorAdapters?: object);
|
||||
|
||||
destroy(): void;
|
||||
createDefaultLayer(): ILayer;
|
||||
createDefaultLayer(options?: LayerDescriptor, mapColors?: string[]): ILayer;
|
||||
getDisplayName(): Promise<string>;
|
||||
getInspectorAdapters(): object;
|
||||
isFieldAware(): boolean;
|
||||
|
@ -33,4 +47,6 @@ export class AbstractSource implements ISource {
|
|||
isQueryAware(): boolean;
|
||||
isRefreshTimerAware(): Promise<boolean>;
|
||||
isTimeAware(): Promise<boolean>;
|
||||
getImmutableProperties(): Promise<ImmutableSourceProperty[]>;
|
||||
getAttributions(): Promise<Attribution[]>;
|
||||
}
|
||||
|
|
|
@ -5,12 +5,11 @@
|
|||
*/
|
||||
/* eslint-disable @typescript-eslint/consistent-type-definitions */
|
||||
|
||||
import { AbstractSourceDescriptor } from '../../../common/descriptor_types';
|
||||
import { ISource } from './source';
|
||||
|
||||
type SourceRegistryEntry = {
|
||||
ConstructorFunction: new (
|
||||
sourceDescriptor: AbstractSourceDescriptor,
|
||||
sourceDescriptor: any, // this is the source-descriptor that corresponds specifically to the particular ISource instance
|
||||
inspectorAdapters: unknown
|
||||
) => ISource;
|
||||
type: string;
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export * from './tms_source';
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { AbstractSource, ISource } from './source';
|
||||
import { AbstractSource, Attribution, ISource } from '../source';
|
||||
|
||||
export interface ITMSSource extends ISource {
|
||||
getUrlTemplate(): Promise<string>;
|
||||
|
@ -12,4 +12,5 @@ export interface ITMSSource extends ISource {
|
|||
|
||||
export class AbstractTMSSource extends AbstractSource implements ITMSSource {
|
||||
getUrlTemplate(): Promise<string>;
|
||||
getAttributions(): Promise<Attribution[]>;
|
||||
}
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { AbstractSource } from './source';
|
||||
import { AbstractSource } from '../source';
|
||||
|
||||
export class AbstractTMSSource extends AbstractSource {
|
||||
async getUrlTemplate() {
|
|
@ -0,0 +1,7 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export * from './vector_source';
|
|
@ -6,14 +6,14 @@
|
|||
/* eslint-disable @typescript-eslint/consistent-type-definitions */
|
||||
|
||||
import { FeatureCollection } from 'geojson';
|
||||
import { AbstractSource, ISource } from './source';
|
||||
import { IField } from '../fields/field';
|
||||
import { AbstractSource, ISource } from '../source';
|
||||
import { IField } from '../../fields/field';
|
||||
import {
|
||||
ESSearchSourceResponseMeta,
|
||||
MapExtent,
|
||||
VectorSourceRequestMeta,
|
||||
VectorSourceSyncMeta,
|
||||
} from '../../../common/descriptor_types';
|
||||
} from '../../../../common/descriptor_types';
|
||||
|
||||
export type GeoJsonFetchMeta = ESSearchSourceResponseMeta;
|
||||
|
|
@ -4,14 +4,14 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { VectorLayer } from '../vector_layer';
|
||||
import { TooltipProperty } from '../tooltips/tooltip_property';
|
||||
import { VectorStyle } from '../styles/vector/vector_style';
|
||||
import { AbstractSource } from './source';
|
||||
import { VectorLayer } from '../../vector_layer';
|
||||
import { TooltipProperty } from '../../tooltips/tooltip_property';
|
||||
import { VectorStyle } from '../../styles/vector/vector_style';
|
||||
import { AbstractSource } from './../source';
|
||||
import * as topojson from 'topojson-client';
|
||||
import _ from 'lodash';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { VECTOR_SHAPE_TYPES } from './vector_feature_types';
|
||||
import { VECTOR_SHAPE_TYPES } from './../vector_feature_types';
|
||||
|
||||
export class AbstractVectorSource extends AbstractSource {
|
||||
static async getGeoJson({ format, featureCollectionPath, fetchUrl }) {
|
|
@ -1,11 +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 { AbstractTMSSource } from './tms_source';
|
||||
import { XYZTMSSourceDescriptor } from '../../../common/descriptor_types';
|
||||
|
||||
export class XYZTMSSource extends AbstractTMSSource {
|
||||
constructor(sourceDescriptor: XYZTMSSourceDescriptor, inspectorAdapters: unknown);
|
||||
}
|
|
@ -1,187 +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 React, { Fragment } from 'react';
|
||||
import { EuiFieldText, EuiFormRow } from '@elastic/eui';
|
||||
|
||||
import { AbstractTMSSource } from './tms_source';
|
||||
import { TileLayer } from '../tile_layer';
|
||||
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 createDescriptor({ urlTemplate, attributionText, attributionUrl }) {
|
||||
return {
|
||||
type: XYZTMSSource.type,
|
||||
urlTemplate,
|
||||
attributionText,
|
||||
attributionUrl,
|
||||
};
|
||||
}
|
||||
|
||||
async getImmutableProperties() {
|
||||
return [
|
||||
{ label: getDataSourceLabel(), value: sourceTitle },
|
||||
{ label: getUrlLabel(), value: this._descriptor.urlTemplate },
|
||||
];
|
||||
}
|
||||
|
||||
_createDefaultLayerDescriptor(options) {
|
||||
return TileLayer.createDescriptor({
|
||||
sourceDescriptor: this._descriptor,
|
||||
...options,
|
||||
});
|
||||
}
|
||||
|
||||
createDefaultLayer(options) {
|
||||
return new TileLayer({
|
||||
layerDescriptor: this._createDefaultLayerDescriptor(options),
|
||||
source: this,
|
||||
});
|
||||
}
|
||||
|
||||
async getDisplayName() {
|
||||
return this._descriptor.urlTemplate;
|
||||
}
|
||||
|
||||
getAttributions() {
|
||||
const { attributionText, attributionUrl } = this._descriptor;
|
||||
const attributionComplete = !!attributionText && !!attributionUrl;
|
||||
|
||||
return attributionComplete
|
||||
? [
|
||||
{
|
||||
url: attributionUrl,
|
||||
label: attributionText,
|
||||
},
|
||||
]
|
||||
: [];
|
||||
}
|
||||
|
||||
getUrlTemplate() {
|
||||
return this._descriptor.urlTemplate;
|
||||
}
|
||||
}
|
||||
|
||||
class XYZTMSEditor extends React.Component {
|
||||
state = {
|
||||
tmsInput: '',
|
||||
tmsCanPreview: false,
|
||||
attributionText: '',
|
||||
attributionUrl: '',
|
||||
};
|
||||
|
||||
_sourceConfigChange = _.debounce(updatedSourceConfig => {
|
||||
if (this.state.tmsCanPreview) {
|
||||
this.props.onSourceConfigChange(updatedSourceConfig);
|
||||
}
|
||||
}, 2000);
|
||||
|
||||
_handleTMSInputChange(e) {
|
||||
const url = e.target.value;
|
||||
|
||||
const canPreview =
|
||||
url.indexOf('{x}') >= 0 && url.indexOf('{y}') >= 0 && url.indexOf('{z}') >= 0;
|
||||
this.setState(
|
||||
{
|
||||
tmsInput: url,
|
||||
tmsCanPreview: canPreview,
|
||||
},
|
||||
() => this._sourceConfigChange({ urlTemplate: url })
|
||||
);
|
||||
}
|
||||
|
||||
_handleTMSAttributionChange(attributionUpdate) {
|
||||
this.setState(attributionUpdate, () => {
|
||||
const { attributionText, attributionUrl, tmsInput } = this.state;
|
||||
|
||||
if (tmsInput && attributionText && attributionUrl) {
|
||||
this._sourceConfigChange({
|
||||
urlTemplate: tmsInput,
|
||||
attributionText,
|
||||
attributionUrl,
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const { attributionText, attributionUrl } = this.state;
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<EuiFormRow label="Url">
|
||||
<EuiFieldText
|
||||
placeholder={'https://a.tile.openstreetmap.org/{z}/{x}/{y}.png'}
|
||||
onChange={e => this._handleTMSInputChange(e)}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
<EuiFormRow
|
||||
label="Attribution text"
|
||||
isInvalid={attributionUrl !== '' && attributionText === ''}
|
||||
error={[
|
||||
i18n.translate('xpack.maps.xyztmssource.attributionText', {
|
||||
defaultMessage: 'Attribution url must have accompanying text',
|
||||
}),
|
||||
]}
|
||||
>
|
||||
<EuiFieldText
|
||||
placeholder={'© OpenStreetMap contributors'}
|
||||
onChange={({ target }) =>
|
||||
this._handleTMSAttributionChange({ attributionText: target.value })
|
||||
}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
<EuiFormRow
|
||||
label="Attribution link"
|
||||
isInvalid={attributionText !== '' && attributionUrl === ''}
|
||||
error={[
|
||||
i18n.translate('xpack.maps.xyztmssource.attributionLink', {
|
||||
defaultMessage: 'Attribution text must have an accompanying link',
|
||||
}),
|
||||
]}
|
||||
>
|
||||
<EuiFieldText
|
||||
placeholder={'https://www.openstreetmap.org/copyright'}
|
||||
onChange={({ target }) =>
|
||||
this._handleTMSAttributionChange({ attributionUrl: target.value })
|
||||
}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
};
|
|
@ -0,0 +1,8 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export * from './xyz_tms_source';
|
||||
export * from './layer_wizard';
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* 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 { i18n } from '@kbn/i18n';
|
||||
import React from 'react';
|
||||
import { XYZTMSEditor, XYZTMSSourceConfig } from './xyz_tms_editor';
|
||||
import { XYZTMSSource, sourceTitle } from './xyz_tms_source';
|
||||
import { LayerWizard, RenderWizardArguments } from '../../layer_wizard_registry';
|
||||
|
||||
export const tmsLayerWizardConfig: LayerWizard = {
|
||||
description: i18n.translate('xpack.maps.source.ems_xyzDescription', {
|
||||
defaultMessage: 'Tile map service configured in interface',
|
||||
}),
|
||||
icon: 'grid',
|
||||
renderWizard: ({ onPreviewSource }: RenderWizardArguments) => {
|
||||
const onSourceConfigChange = (sourceConfig: XYZTMSSourceConfig) => {
|
||||
const sourceDescriptor = XYZTMSSource.createDescriptor(sourceConfig);
|
||||
const source = new XYZTMSSource(sourceDescriptor);
|
||||
onPreviewSource(source);
|
||||
};
|
||||
return <XYZTMSEditor onSourceConfigChange={onSourceConfigChange} />;
|
||||
},
|
||||
title: sourceTitle,
|
||||
};
|
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
* 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 React, { Fragment, Component, ChangeEvent } from 'react';
|
||||
import _ from 'lodash';
|
||||
import { EuiFormRow, EuiFieldText } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { AttributionDescriptor } from '../../../../common/descriptor_types';
|
||||
|
||||
export type XYZTMSSourceConfig = AttributionDescriptor & {
|
||||
urlTemplate: string;
|
||||
};
|
||||
|
||||
export interface Props {
|
||||
onSourceConfigChange: (sourceConfig: XYZTMSSourceConfig) => void;
|
||||
}
|
||||
|
||||
interface State {
|
||||
tmsInput: string;
|
||||
tmsCanPreview: boolean;
|
||||
attributionText: string;
|
||||
attributionUrl: string;
|
||||
}
|
||||
|
||||
export class XYZTMSEditor extends Component<Props, State> {
|
||||
state = {
|
||||
tmsInput: '',
|
||||
tmsCanPreview: false,
|
||||
attributionText: '',
|
||||
attributionUrl: '',
|
||||
};
|
||||
|
||||
_sourceConfigChange = _.debounce((updatedSourceConfig: XYZTMSSourceConfig) => {
|
||||
if (this.state.tmsCanPreview) {
|
||||
this.props.onSourceConfigChange(updatedSourceConfig);
|
||||
}
|
||||
}, 2000);
|
||||
|
||||
_handleTMSInputChange(e: ChangeEvent<HTMLInputElement>) {
|
||||
const url = e.target.value;
|
||||
|
||||
const canPreview =
|
||||
url.indexOf('{x}') >= 0 && url.indexOf('{y}') >= 0 && url.indexOf('{z}') >= 0;
|
||||
this.setState(
|
||||
{
|
||||
tmsInput: url,
|
||||
tmsCanPreview: canPreview,
|
||||
},
|
||||
() => this._sourceConfigChange({ urlTemplate: url })
|
||||
);
|
||||
}
|
||||
|
||||
_handleTMSAttributionChange(attributionUpdate: AttributionDescriptor) {
|
||||
this.setState(
|
||||
{
|
||||
attributionUrl: attributionUpdate.attributionUrl || '',
|
||||
attributionText: attributionUpdate.attributionText || '',
|
||||
},
|
||||
() => {
|
||||
const { attributionText, attributionUrl, tmsInput } = this.state;
|
||||
|
||||
if (tmsInput && attributionText && attributionUrl) {
|
||||
this._sourceConfigChange({
|
||||
urlTemplate: tmsInput,
|
||||
attributionText,
|
||||
attributionUrl,
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { attributionText, attributionUrl } = this.state;
|
||||
return (
|
||||
<Fragment>
|
||||
<EuiFormRow label="Url">
|
||||
<EuiFieldText
|
||||
placeholder={'https://a.tile.openstreetmap.org/{z}/{x}/{y}.png'}
|
||||
onChange={e => this._handleTMSInputChange(e)}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
<EuiFormRow
|
||||
label="Attribution text"
|
||||
isInvalid={attributionUrl !== '' && attributionText === ''}
|
||||
error={[
|
||||
i18n.translate('xpack.maps.xyztmssource.attributionText', {
|
||||
defaultMessage: 'Attribution url must have accompanying text',
|
||||
}),
|
||||
]}
|
||||
>
|
||||
<EuiFieldText
|
||||
placeholder={'© OpenStreetMap contributors'}
|
||||
onChange={({ target }: ChangeEvent<HTMLInputElement>) =>
|
||||
this._handleTMSAttributionChange({ attributionText: target.value })
|
||||
}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
<EuiFormRow
|
||||
label="Attribution link"
|
||||
isInvalid={attributionText !== '' && attributionUrl === ''}
|
||||
error={[
|
||||
i18n.translate('xpack.maps.xyztmssource.attributionLink', {
|
||||
defaultMessage: 'Attribution text must have an accompanying link',
|
||||
}),
|
||||
]}
|
||||
>
|
||||
<EuiFieldText
|
||||
placeholder={'https://www.openstreetmap.org/copyright'}
|
||||
onChange={({ target }: ChangeEvent<HTMLInputElement>) =>
|
||||
this._handleTMSAttributionChange({ attributionUrl: target.value })
|
||||
}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -5,10 +5,10 @@
|
|||
*/
|
||||
|
||||
import { XYZTMSSource } from './xyz_tms_source';
|
||||
import { ILayer } from '../layer';
|
||||
import { TileLayer } from '../tile_layer';
|
||||
import { EMS_XYZ } from '../../../common/constants';
|
||||
import { XYZTMSSourceDescriptor } from '../../../common/descriptor_types';
|
||||
import { ILayer } from '../../layer';
|
||||
import { TileLayer } from '../../tile_layer';
|
||||
import { EMS_XYZ } from '../../../../common/constants';
|
||||
import { XYZTMSSourceDescriptor } from '../../../../common/descriptor_types';
|
||||
|
||||
const descriptor: XYZTMSSourceDescriptor = {
|
||||
type: EMS_XYZ,
|
||||
|
@ -17,13 +17,13 @@ const descriptor: XYZTMSSourceDescriptor = {
|
|||
};
|
||||
describe('xyz Tilemap Source', () => {
|
||||
it('should create a tile-layer', () => {
|
||||
const source = new XYZTMSSource(descriptor, null);
|
||||
const source = new XYZTMSSource(descriptor);
|
||||
const layer: ILayer = source.createDefaultLayer();
|
||||
expect(layer instanceof TileLayer).toEqual(true);
|
||||
});
|
||||
|
||||
it('should echo url template for url template', async () => {
|
||||
const source = new XYZTMSSource(descriptor, null);
|
||||
const source = new XYZTMSSource(descriptor);
|
||||
const template = await source.getUrlTemplate();
|
||||
expect(template).toEqual(descriptor.urlTemplate);
|
||||
});
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* 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 { i18n } from '@kbn/i18n';
|
||||
import { TileLayer } from '../../tile_layer';
|
||||
import { getDataSourceLabel, getUrlLabel } from '../../../../common/i18n_getters';
|
||||
import { EMS_XYZ } from '../../../../common/constants';
|
||||
import { registerSource } from '../source_registry';
|
||||
import { AbstractTMSSource } from '../tms_source';
|
||||
import { LayerDescriptor, XYZTMSSourceDescriptor } from '../../../../common/descriptor_types';
|
||||
import { Attribution, ImmutableSourceProperty } from '../source';
|
||||
import { XYZTMSSourceConfig } from './xyz_tms_editor';
|
||||
|
||||
export const sourceTitle = i18n.translate('xpack.maps.source.ems_xyzTitle', {
|
||||
defaultMessage: 'Tile Map Service',
|
||||
});
|
||||
|
||||
export class XYZTMSSource extends AbstractTMSSource {
|
||||
static type = EMS_XYZ;
|
||||
|
||||
readonly _descriptor: XYZTMSSourceDescriptor;
|
||||
|
||||
static createDescriptor({
|
||||
urlTemplate,
|
||||
attributionText,
|
||||
attributionUrl,
|
||||
}: XYZTMSSourceConfig): XYZTMSSourceDescriptor {
|
||||
return {
|
||||
type: XYZTMSSource.type,
|
||||
urlTemplate,
|
||||
attributionText,
|
||||
attributionUrl,
|
||||
};
|
||||
}
|
||||
|
||||
constructor(sourceDescriptor: XYZTMSSourceDescriptor) {
|
||||
super(sourceDescriptor);
|
||||
this._descriptor = sourceDescriptor;
|
||||
}
|
||||
|
||||
async getImmutableProperties(): Promise<ImmutableSourceProperty[]> {
|
||||
return [
|
||||
{ label: getDataSourceLabel(), value: sourceTitle },
|
||||
{ label: getUrlLabel(), value: this._descriptor.urlTemplate },
|
||||
];
|
||||
}
|
||||
|
||||
createDefaultLayer(options?: LayerDescriptor): TileLayer {
|
||||
const layerDescriptor: LayerDescriptor = TileLayer.createDescriptor({
|
||||
sourceDescriptor: this._descriptor,
|
||||
...options,
|
||||
});
|
||||
return new TileLayer({
|
||||
layerDescriptor,
|
||||
source: this,
|
||||
});
|
||||
}
|
||||
|
||||
async getDisplayName(): Promise<string> {
|
||||
return this._descriptor.urlTemplate;
|
||||
}
|
||||
|
||||
async getAttributions(): Promise<Attribution[]> {
|
||||
const { attributionText, attributionUrl } = this._descriptor;
|
||||
const attributionComplete = !!attributionText && !!attributionUrl;
|
||||
return attributionComplete
|
||||
? [
|
||||
{
|
||||
url: attributionUrl as string,
|
||||
label: attributionText as string,
|
||||
},
|
||||
]
|
||||
: [];
|
||||
}
|
||||
|
||||
async getUrlTemplate(): Promise<string> {
|
||||
return this._descriptor.urlTemplate;
|
||||
}
|
||||
}
|
||||
|
||||
registerSource({
|
||||
ConstructorFunction: XYZTMSSource,
|
||||
type: EMS_XYZ,
|
||||
});
|
|
@ -11,8 +11,8 @@ import { SOURCE_DATA_ID_ORIGIN, LAYER_TYPE } from '../../common/constants';
|
|||
export class TileLayer extends AbstractLayer {
|
||||
static type = LAYER_TYPE.TILE;
|
||||
|
||||
static createDescriptor(options) {
|
||||
const tileLayerDescriptor = super.createDescriptor(options);
|
||||
static createDescriptor(options, mapColors) {
|
||||
const tileLayerDescriptor = super.createDescriptor(options, mapColors);
|
||||
tileLayerDescriptor.type = TileLayer.type;
|
||||
tileLayerDescriptor.alpha = _.get(options, 'alpha', 1);
|
||||
return tileLayerDescriptor;
|
||||
|
|
|
@ -17,7 +17,7 @@ const sourceDescriptor: XYZTMSSourceDescriptor = {
|
|||
};
|
||||
|
||||
class MockTileSource extends AbstractTMSSource implements ITMSSource {
|
||||
private readonly _descriptor: XYZTMSSourceDescriptor;
|
||||
readonly _descriptor: XYZTMSSourceDescriptor;
|
||||
constructor(descriptor: XYZTMSSourceDescriptor) {
|
||||
super(descriptor, {});
|
||||
this._descriptor = descriptor;
|
||||
|
|
|
@ -32,8 +32,8 @@ export interface IVectorLayer extends ILayer {
|
|||
|
||||
export class VectorLayer extends AbstractLayer implements IVectorLayer {
|
||||
static createDescriptor(
|
||||
options: VectorLayerArguments,
|
||||
mapColors: string[]
|
||||
options: Partial<VectorLayerDescriptor>,
|
||||
mapColors?: string[]
|
||||
): VectorLayerDescriptor;
|
||||
|
||||
protected readonly _source: IVectorSource;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue