[Maps] Implement fields and bounds retrieval on GeoJsonFileSource (#88294)
This commit is contained in:
parent
1f644e44c9
commit
0076384a0f
|
@ -156,7 +156,13 @@ export type TiledSingleLayerVectorSourceDescriptor = AbstractSourceDescriptor &
|
|||
tooltipProperties: string[];
|
||||
};
|
||||
|
||||
export type GeoJsonFileFieldDescriptor = {
|
||||
name: string;
|
||||
type: 'string' | 'number';
|
||||
};
|
||||
|
||||
export type GeojsonFileSourceDescriptor = {
|
||||
__fields?: GeoJsonFileFieldDescriptor[];
|
||||
__featureCollection: FeatureCollection;
|
||||
name: string;
|
||||
type: string;
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* 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 { FIELD_ORIGIN } from '../../../common/constants';
|
||||
import { IField, AbstractField } from './field';
|
||||
import { IVectorSource } from '../sources/vector_source';
|
||||
import { GeoJsonFileSource } from '../sources/geojson_file_source';
|
||||
|
||||
export class GeoJsonFileField extends AbstractField implements IField {
|
||||
private readonly _source: GeoJsonFileSource;
|
||||
private readonly _dataType: string;
|
||||
|
||||
constructor({
|
||||
fieldName,
|
||||
source,
|
||||
origin,
|
||||
dataType,
|
||||
}: {
|
||||
fieldName: string;
|
||||
source: GeoJsonFileSource;
|
||||
origin: FIELD_ORIGIN;
|
||||
dataType: string;
|
||||
}) {
|
||||
super({ fieldName, origin });
|
||||
this._source = source;
|
||||
this._dataType = dataType;
|
||||
}
|
||||
|
||||
getSource(): IVectorSource {
|
||||
return this._source;
|
||||
}
|
||||
|
||||
async getLabel(): Promise<string> {
|
||||
return this.getName();
|
||||
}
|
||||
|
||||
async getDataType(): Promise<string> {
|
||||
return this._dataType;
|
||||
}
|
||||
}
|
|
@ -14,7 +14,7 @@ import {
|
|||
SCALING_TYPES,
|
||||
} from '../../../../common/constants';
|
||||
import { getFileUploadComponent } from '../../../kibana_services';
|
||||
import { GeojsonFileSource } from '../../sources/geojson_file_source';
|
||||
import { GeoJsonFileSource } from '../../sources/geojson_file_source';
|
||||
import { VectorLayer } from '../../layers/vector_layer/vector_layer';
|
||||
import { createDefaultLayerDescriptor } from '../../sources/es_search_source';
|
||||
import { RenderWizardArguments } from '../../layers/layer_wizard_registry';
|
||||
|
@ -79,7 +79,10 @@ export class ClientFileCreateSourceEditor extends Component<RenderWizardArgument
|
|||
return;
|
||||
}
|
||||
|
||||
const sourceDescriptor = GeojsonFileSource.createDescriptor(geojsonFile, name);
|
||||
const sourceDescriptor = GeoJsonFileSource.createDescriptor({
|
||||
__featureCollection: geojsonFile,
|
||||
name,
|
||||
});
|
||||
const layerDescriptor = VectorLayer.createDescriptor(
|
||||
{ sourceDescriptor },
|
||||
this.props.mapColors
|
||||
|
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* 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 { GeoJsonFileSource } from './geojson_file_source';
|
||||
import { BoundsFilters } from '../vector_source';
|
||||
import { FIELD_ORIGIN } from '../../../../common/constants';
|
||||
|
||||
describe('GeoJsonFileSource', () => {
|
||||
describe('getName', () => {
|
||||
it('should get default display name', async () => {
|
||||
const geojsonFileSource = new GeoJsonFileSource({});
|
||||
expect(await geojsonFileSource.getDisplayName()).toBe('Features');
|
||||
});
|
||||
});
|
||||
describe('getBounds', () => {
|
||||
it('should get null bounds', async () => {
|
||||
const geojsonFileSource = new GeoJsonFileSource({});
|
||||
expect(
|
||||
await geojsonFileSource.getBoundsForFilters(({} as unknown) as BoundsFilters, () => {})
|
||||
).toEqual(null);
|
||||
});
|
||||
|
||||
it('should get bounds from feature collection', async () => {
|
||||
const geojsonFileSource = new GeoJsonFileSource({
|
||||
__featureCollection: {
|
||||
type: 'FeatureCollection',
|
||||
features: [
|
||||
{
|
||||
type: 'Feature',
|
||||
geometry: {
|
||||
type: 'Point',
|
||||
coordinates: [0, 1],
|
||||
},
|
||||
properties: {},
|
||||
},
|
||||
{
|
||||
type: 'Feature',
|
||||
geometry: {
|
||||
type: 'Point',
|
||||
coordinates: [2, 3],
|
||||
},
|
||||
properties: {},
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
expect(geojsonFileSource.isBoundsAware()).toBe(true);
|
||||
expect(
|
||||
await geojsonFileSource.getBoundsForFilters(({} as unknown) as BoundsFilters, () => {})
|
||||
).toEqual({
|
||||
maxLat: 3,
|
||||
maxLon: 2,
|
||||
minLat: 1,
|
||||
minLon: 0,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('getFields', () => {
|
||||
it('should get fields from config', async () => {
|
||||
const geojsonFileSource = new GeoJsonFileSource({
|
||||
__fields: [
|
||||
{
|
||||
type: 'string',
|
||||
name: 'foo',
|
||||
},
|
||||
{
|
||||
type: 'number',
|
||||
name: 'bar',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const fields = await geojsonFileSource.getFields();
|
||||
|
||||
const actualFields = fields.map(async (field) => {
|
||||
return {
|
||||
dataType: await field.getDataType(),
|
||||
origin: field.getOrigin(),
|
||||
name: field.getName(),
|
||||
source: field.getSource(),
|
||||
};
|
||||
});
|
||||
|
||||
expect(await Promise.all(actualFields)).toEqual([
|
||||
{
|
||||
dataType: 'string',
|
||||
origin: FIELD_ORIGIN.SOURCE,
|
||||
source: geojsonFileSource,
|
||||
name: 'foo',
|
||||
},
|
||||
{
|
||||
dataType: 'number',
|
||||
origin: FIELD_ORIGIN.SOURCE,
|
||||
source: geojsonFileSource,
|
||||
name: 'bar',
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -5,13 +5,22 @@
|
|||
*/
|
||||
|
||||
import { Feature, FeatureCollection } from 'geojson';
|
||||
import { AbstractVectorSource, GeoJsonWithMeta } from '../vector_source';
|
||||
import { EMPTY_FEATURE_COLLECTION, SOURCE_TYPES } from '../../../../common/constants';
|
||||
import { GeojsonFileSourceDescriptor } from '../../../../common/descriptor_types';
|
||||
import { AbstractVectorSource, BoundsFilters, GeoJsonWithMeta } from '../vector_source';
|
||||
import { EMPTY_FEATURE_COLLECTION, FIELD_ORIGIN, SOURCE_TYPES } from '../../../../common/constants';
|
||||
import {
|
||||
GeoJsonFileFieldDescriptor,
|
||||
GeojsonFileSourceDescriptor,
|
||||
MapExtent,
|
||||
} from '../../../../common/descriptor_types';
|
||||
import { registerSource } from '../source_registry';
|
||||
import { IField } from '../../fields/field';
|
||||
import { getFeatureCollectionBounds } from '../../util/get_feature_collection_bounds';
|
||||
import { GeoJsonFileField } from '../../fields/geojson_file_field';
|
||||
import { Adapters } from '../../../../../../../src/plugins/inspector/common/adapters';
|
||||
|
||||
function getFeatureCollection(geoJson: Feature | FeatureCollection | null): FeatureCollection {
|
||||
function getFeatureCollection(
|
||||
geoJson: Feature | FeatureCollection | null | undefined
|
||||
): FeatureCollection {
|
||||
if (!geoJson) {
|
||||
return EMPTY_FEATURE_COLLECTION;
|
||||
}
|
||||
|
@ -30,18 +39,73 @@ function getFeatureCollection(geoJson: Feature | FeatureCollection | null): Feat
|
|||
return EMPTY_FEATURE_COLLECTION;
|
||||
}
|
||||
|
||||
export class GeojsonFileSource extends AbstractVectorSource {
|
||||
export class GeoJsonFileSource extends AbstractVectorSource {
|
||||
static createDescriptor(
|
||||
geoJson: Feature | FeatureCollection | null,
|
||||
name: string
|
||||
descriptor: Partial<GeojsonFileSourceDescriptor>
|
||||
): GeojsonFileSourceDescriptor {
|
||||
return {
|
||||
type: SOURCE_TYPES.GEOJSON_FILE,
|
||||
__featureCollection: getFeatureCollection(geoJson),
|
||||
name,
|
||||
__featureCollection: getFeatureCollection(descriptor.__featureCollection),
|
||||
__fields: descriptor.__fields || [],
|
||||
name: descriptor.name || 'Features',
|
||||
};
|
||||
}
|
||||
|
||||
constructor(descriptor: Partial<GeojsonFileSourceDescriptor>, inspectorAdapters?: Adapters) {
|
||||
const normalizedDescriptor = GeoJsonFileSource.createDescriptor(descriptor);
|
||||
super(normalizedDescriptor, inspectorAdapters);
|
||||
}
|
||||
|
||||
_getFields(): GeoJsonFileFieldDescriptor[] {
|
||||
const fields = (this._descriptor as GeojsonFileSourceDescriptor).__fields;
|
||||
return fields ? fields : [];
|
||||
}
|
||||
|
||||
createField({ fieldName }: { fieldName: string }): IField {
|
||||
const fields = this._getFields();
|
||||
const descriptor: GeoJsonFileFieldDescriptor | undefined = fields.find((field) => {
|
||||
return field.name === fieldName;
|
||||
});
|
||||
|
||||
if (!descriptor) {
|
||||
throw new Error(
|
||||
`Cannot find corresponding field ${fieldName} in __fields array ${JSON.stringify(
|
||||
this._getFields()
|
||||
)} `
|
||||
);
|
||||
}
|
||||
return new GeoJsonFileField({
|
||||
fieldName: descriptor.name,
|
||||
source: this,
|
||||
origin: FIELD_ORIGIN.SOURCE,
|
||||
dataType: descriptor.type,
|
||||
});
|
||||
}
|
||||
|
||||
async getFields(): Promise<IField[]> {
|
||||
const fields = this._getFields();
|
||||
return fields.map((field: GeoJsonFileFieldDescriptor) => {
|
||||
return new GeoJsonFileField({
|
||||
fieldName: field.name,
|
||||
source: this,
|
||||
origin: FIELD_ORIGIN.SOURCE,
|
||||
dataType: field.type,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
isBoundsAware(): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
async getBoundsForFilters(
|
||||
boundsFilters: BoundsFilters,
|
||||
registerCancelCallback: (callback: () => void) => void
|
||||
): Promise<MapExtent | null> {
|
||||
const featureCollection = (this._descriptor as GeojsonFileSourceDescriptor).__featureCollection;
|
||||
return getFeatureCollectionBounds(featureCollection, false);
|
||||
}
|
||||
|
||||
async getGeoJsonWithMeta(): Promise<GeoJsonWithMeta> {
|
||||
return {
|
||||
data: (this._descriptor as GeojsonFileSourceDescriptor).__featureCollection,
|
||||
|
@ -49,10 +113,6 @@ export class GeojsonFileSource extends AbstractVectorSource {
|
|||
};
|
||||
}
|
||||
|
||||
createField({ fieldName }: { fieldName: string }): IField {
|
||||
throw new Error('Not implemented');
|
||||
}
|
||||
|
||||
async getDisplayName() {
|
||||
return (this._descriptor as GeojsonFileSourceDescriptor).name;
|
||||
}
|
||||
|
@ -63,6 +123,6 @@ export class GeojsonFileSource extends AbstractVectorSource {
|
|||
}
|
||||
|
||||
registerSource({
|
||||
ConstructorFunction: GeojsonFileSource,
|
||||
ConstructorFunction: GeoJsonFileSource,
|
||||
type: SOURCE_TYPES.GEOJSON_FILE,
|
||||
});
|
||||
|
|
|
@ -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 } from './geojson_file_source';
|
||||
|
|
|
@ -22,7 +22,7 @@ import { TiledVectorLayer } from '../classes/layers/tiled_vector_layer/tiled_vec
|
|||
import { copyPersistentState, TRACKED_LAYER_DESCRIPTOR } from '../reducers/util';
|
||||
import { InnerJoin } from '../classes/joins/inner_join';
|
||||
import { getSourceByType } from '../classes/sources/source_registry';
|
||||
import { GeojsonFileSource } from '../classes/sources/geojson_file_source';
|
||||
import { GeoJsonFileSource } from '../classes/sources/geojson_file_source';
|
||||
import {
|
||||
SOURCE_DATA_REQUEST_ID,
|
||||
STYLE_TYPE,
|
||||
|
@ -241,10 +241,10 @@ export const getSpatialFiltersLayer = createSelector(
|
|||
type: 'FeatureCollection',
|
||||
features: extractFeaturesFromFilters(filters),
|
||||
};
|
||||
const geoJsonSourceDescriptor = GeojsonFileSource.createDescriptor(
|
||||
featureCollection,
|
||||
'spatialFilters'
|
||||
);
|
||||
const geoJsonSourceDescriptor = GeoJsonFileSource.createDescriptor({
|
||||
__featureCollection: featureCollection,
|
||||
name: 'spatialFilters',
|
||||
});
|
||||
|
||||
return new VectorLayer({
|
||||
layerDescriptor: VectorLayer.createDescriptor({
|
||||
|
@ -272,7 +272,7 @@ export const getSpatialFiltersLayer = createSelector(
|
|||
},
|
||||
}),
|
||||
}),
|
||||
source: new GeojsonFileSource(geoJsonSourceDescriptor),
|
||||
source: new GeoJsonFileSource(geoJsonSourceDescriptor),
|
||||
});
|
||||
}
|
||||
);
|
||||
|
|
Loading…
Reference in a new issue