import React , { Component } from 'react' ; import { Map as MbMap , Point as MbPoint } from '@kbn/mapbox-gl' ; import MapboxDraw from '@mapbox/mapbox-gl-draw' ; import { Feature , Geometry , Position } from 'geojson' ; import { i18n } from '@kbn/i18n' ; import * as jsts from 'jsts' ; import { MapMouseEvent } from '@kbn/mapbox-gl' ; import { getToasts } from '../../../../kibana_services' ; import { DrawControl } from '../' ; import { DRAW_MODE , DRAW_SHAPE } from '../../../../../common/constants' ; import { ILayer } from '../../../../classes/layers/layer' ; import { EXCLUDE_CENTROID_FEATURES } from '../../../../classes/util/mb_filter_expressions' ; const geoJSONReader = new jsts . io . GeoJSONReader ( ) ; export interface ReduxStateProps { drawShape ? : DRAW_SHAPE ; drawMode : DRAW_MODE ; editLayer : ILayer | undefined ; } export interface ReduxDispatchProps { addNewFeatureToIndex : ( geometry : Geometry | Position [ ] ) => void ; deleteFeatureFromIndex : ( featureId : string ) => void ; disableDrawState : ( ) => void ; } export interface OwnProps { mbMap : MbMap ; } type Props = ReduxStateProps & ReduxDispatchProps & OwnProps ; export class DrawFeatureControl extends Component < Props , { } > { _onDraw = async ( e , mbDrawControl ) => { try { e . features . forEach ( ( feature ) => { const { geometry } = geoJSONReader . read ( feature ) ; if ( ! geometry . isSimple ( ) || ! geometry . isValid ( ) ) { throw new Error ( i18n . translate ( 'xpack.maps.drawFeatureControl.invalidGeometry' , { defaultMessage : `Invalid geometry detected` , } ) ) ; } if ( 'coordinates' in feature . geometry ) { const featureGeom = this . props . drawMode === DRAW_MODE . DRAW_POINTS ? feature . geometry . coordinates : feature . geometry ; this . props . addNewFeatureToIndex ( featureGeom ) ; } } ) ; } catch ( error ) { getToasts ( ) . addWarning ( i18n . translate ( 'xpack.maps.drawFeatureControl.unableToCreateFeature' , { defaultMessage : `Unable to create feature, error: '{errorMsg}'.` , values : { errorMsg : error . message , } , } ) ) ; } finally { this . props . disableDrawState ( ) ; try { mbDrawControl . deleteAll ( ) ; } catch ( _e ) { } } } ; _onClick = async ( event , drawControl ? ) => { const mbLngLatPoint = event . point ; if ( ! this . props . editLayer || this . props . drawShape !== DRAW_SHAPE . DELETE ) { return ; } const mbEditLayerIds = this . props . editLayer . getMbLayerIds ( ) . filter ( ( mbLayerId ) => ! ! this . props . mbMap . getLayer ( mbLayerId ) ) ; const PADDING = 2 ; const mbBbox = [ { x : mbLngLatPoint . x - PADDING , y : mbLngLatPoint . y - PADDING , } , { x : mbLngLatPoint . x + PADDING , y : mbLngLatPoint . y + PADDING , } , ] as [ MbPoint , MbPoint ] ; const selectedFeatures = this . props . mbMap . queryRenderedFeatures ( mbBbox , { layers : mbEditLayerIds , filter : [ 'all' , EXCLUDE_CENTROID_FEATURES ] , } ) ; if ( ! selectedFeatures . length ) { return ; } const topMostFeature = selectedFeatures [ 0 ] ; try { if ( ! ( topMostFeature . properties && topMostFeature . properties . _id ) ) { throw Error ( `Associated Elasticsearch document id not found` ) ; } const docId = topMostFeature . properties . _id ; this . props . deleteFeatureFromIndex ( docId ) ; } catch ( error ) { getToasts ( ) . addWarning ( i18n . translate ( 'xpack.maps.drawFeatureControl.unableToDeleteFeature' , { defaultMessage : `Unable to delete feature, error: '{errorMsg}'.` , values : { errorMsg : error . message , } , } ) ) ; } } ; render ( ) { return ( < DrawControl drawShape = { this . props . drawShape } onDraw = { this . _onDraw } onClick = { this . _onClick } mbMap = { this . props . mbMap } enable = { true } / > ) ; } }