Skip to content

Commit

Permalink
[Maps] Implement fields and bounds retrieval on GeoJsonFileSource (#8…
Browse files Browse the repository at this point in the history
  • Loading branch information
thomasneirynck authored Jan 26, 2021
1 parent 1f644e4 commit 0076384
Show file tree
Hide file tree
Showing 7 changed files with 240 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
43 changes: 43 additions & 0 deletions x-pack/plugins/maps/public/classes/fields/geojson_file_field.ts
Original file line number Diff line number Diff line change
@@ -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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -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',
},
]);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -30,29 +39,80 @@ 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,
meta: {},
};
}

createField({ fieldName }: { fieldName: string }): IField {
throw new Error('Not implemented');
}

async getDisplayName() {
return (this._descriptor as GeojsonFileSourceDescriptor).name;
}
Expand All @@ -63,6 +123,6 @@ export class GeojsonFileSource extends AbstractVectorSource {
}

registerSource({
ConstructorFunction: GeojsonFileSource,
ConstructorFunction: GeoJsonFileSource,
type: SOURCE_TYPES.GEOJSON_FILE,
});
Original file line number Diff line number Diff line change
Expand Up @@ -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';
12 changes: 6 additions & 6 deletions x-pack/plugins/maps/public/selectors/map_selectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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({
Expand Down Expand Up @@ -272,7 +272,7 @@ export const getSpatialFiltersLayer = createSelector(
},
}),
}),
source: new GeojsonFileSource(geoJsonSourceDescriptor),
source: new GeoJsonFileSource(geoJsonSourceDescriptor),
});
}
);
Expand Down

0 comments on commit 0076384

Please sign in to comment.