import React , { ReactElement } from 'react' ; import { i18n } from '@kbn/i18n' ; import { Feature } from 'geojson' ; import { Adapters } from 'src/plugins/inspector/public' ; import { FileLayer } from '@elastic/ems-client' ; import { ImmutableSourceProperty , SourceEditorArgs } from '../source' ; import { AbstractVectorSource , GeoJsonWithMeta , IVectorSource } from '../vector_source' ; import { SOURCE_TYPES , FIELD_ORIGIN , VECTOR_SHAPE_TYPE } from '../../../../common/constants' ; import { getEmsFileLayers } from '../../../util' ; import { getDataSourceLabel } from '../../../../common/i18n_getters' ; import { UpdateSourceEditor } from './update_source_editor' ; import { EMSFileField } from '../../fields/ems_file_field' ; import { registerSource } from '../source_registry' ; import { IField } from '../../fields/field' ; import { EMSFileSourceDescriptor } from '../../../../common/descriptor_types' ; import { ITooltipProperty } from '../../tooltips/tooltip_property' ; import { getEMSSettings } from '../../../kibana_services' ; import { getEmsUnavailableMessage } from '../../../components/ems_unavailable_message' ; import { LICENSED_FEATURES } from '../../../licensed_features' ; function getErrorInfo ( fileId ) { return i18n . translate ( 'xpack.maps.source.emsFile.unableToFindFileIdErrorMessage' , { defaultMessage : `Unable to find EMS vector shapes for id: {id}. {info}` , values : { id : fileId , info : getEmsUnavailableMessage ( ) , } , } ) ; } export interface IEmsFileSource extends IVectorSource { getEmsFieldLabel ( emsFieldName ) : Promise < string > ; } export function getSourceTitle ( ) { const emsSettings = getEMSSettings ( ) ; if ( emsSettings . isEMSUrlSet ( ) ) { return i18n . translate ( 'xpack.maps.source.emsOnPremFileTitle' , { defaultMessage : 'Elastic Maps Server Boundaries' , } ) ; } else { return i18n . translate ( 'xpack.maps.source.emsFileTitle' , { defaultMessage : 'EMS Boundaries' , } ) ; } } export class EMSFileSource extends AbstractVectorSource implements IEmsFileSource { static createDescriptor ( { id , tooltipProperties = [ ] } ) { return { type : SOURCE_TYPES . EMS_FILE , id : id ! , tooltipProperties , } ; } private readonly _tooltipFields : IField [ ] ; readonly _descriptor : EMSFileSourceDescriptor ; constructor ( descriptor , inspectorAdapters ? ) { super ( EMSFileSource . createDescriptor ( descriptor ) , inspectorAdapters ) ; this . _descriptor = EMSFileSource . createDescriptor ( descriptor ) ; this . _tooltipFields = this . _descriptor . tooltipProperties . map ( ( propertyKey ) => this . createField ( { fieldName : propertyKey } ) ) ; } createField ( { fieldName } ) { return new EMSFileField ( { fieldName , source : this , origin : FIELD_ORIGIN . SOURCE , } ) ; } renderSourceSettingsEditor ( { onChange } ) { return ( < UpdateSourceEditor onChange = { onChange } tooltipFields = { this . _tooltipFields } layerId = { this . _descriptor . id } source = { this } / > ) ; } async getEMSFileLayer ( ) { let emsFileLayers ; try { emsFileLayers = await getEmsFileLayers ( ) ; } catch ( e ) { throw new Error ( `${ getErrorInfo ( this . _descriptor . id ) } - ${ e . message }` ) ; } const emsFileLayer = emsFileLayers . find ( ( fileLayer ) => fileLayer . hasId ( this . _descriptor . id ) ) ; if ( emsFileLayer ) { return emsFileLayer ; } throw new Error ( getErrorInfo ( this . _descriptor . id ) ) ; } async getEmsFieldLabel ( emsFieldName ) { const emsFileLayer = await this . getEMSFileLayer ( ) ; const emsFields = emsFileLayer . getFieldsInLanguage ( ) ; const emsField = emsFields . find ( ( field ) => field . name === emsFieldName ) ; return emsField ? emsField . description : emsFieldName ; } async getGeoJsonWithMeta ( ) { try { const emsFileLayer = await this . getEMSFileLayer ( ) ; const featureCollection = await emsFileLayer . getGeoJson ( ) ; if ( ! featureCollection ) throw new Error ( 'No features found' ) ; const emsIdField = emsFileLayer . getFields ( ) . find ( ( field ) => { return field . type === 'id' ; } ) ; featureCollection . features . forEach ( ( feature , index ) => { feature . id = emsIdField ? feature ! . properties ! [ emsIdField . id ] : index ; } ) ; return { data : featureCollection , meta : { } , } ; } catch ( error ) { throw new Error ( getErrorInfo ( this . _descriptor . id ) ) ; } } async getImmutableProperties ( ) { let emsLink ; try { const emsFileLayer = await this . getEMSFileLayer ( ) ; emsLink = emsFileLayer . getEMSHotLink ( ) ; } catch ( error ) { } const props = [ { label : getDataSourceLabel ( ) , value : getSourceTitle ( ) , } , { label : i18n . translate ( 'xpack.maps.source.emsFile.layerLabel' , { defaultMessage : `Layer` , } ) , value : this . _descriptor . id , link : emsLink , } , ] ; const emsSettings = getEMSSettings ( ) ; if ( emsSettings . isEMSUrlSet ( ) ) { props . push ( { label : i18n . translate ( 'xpack.maps.source.emsFile.emsOnPremLabel' , { defaultMessage : `Elastic Maps Server` , } ) , value : emsSettings . getEMSRoot ( ) , } ) ; } return props ; } async getDisplayName ( ) { try { const emsFileLayer = await this . getEMSFileLayer ( ) ; return emsFileLayer . getDisplayName ( ) ; } catch ( error ) { return this . _descriptor . id ; } } getAttributionProvider ( ) { return async ( ) => { const emsFileLayer = await this . getEMSFileLayer ( ) ; return emsFileLayer . getAttributions ( ) ; } ; } async getLeftJoinFields ( ) { const emsFileLayer = await this . getEMSFileLayer ( ) ; const fields = emsFileLayer . getFieldsInLanguage ( ) ; return fields . map ( ( f ) => this . createField ( { fieldName : f . name } ) ) ; } hasTooltipProperties ( ) { return this . _tooltipFields . length > 0 ; } async getTooltipProperties ( properties ) { const promises = this . _tooltipFields . map ( ( field ) => { const value = properties [ field . getName ( ) ] ; return field . createTooltipProperty ( value ) ; } ) ; return Promise . all ( promises ) ; } async getSupportedShapeTypes ( ) { return [ VECTOR_SHAPE_TYPE . POLYGON ] ; } async getLicensedFeatures ( ) { const emsSettings = getEMSSettings ( ) ; return emsSettings . isEMSUrlSet ( ) ? [ LICENSED_FEATURES . ON_PREM_EMS ] : [ ] ; } } registerSource ( { ConstructorFunction : EMSFileSource , type : SOURCE_TYPES . EMS_FILE , } ) ;