-
Notifications
You must be signed in to change notification settings - Fork 8.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* [Maps][POC] pew pew source * refetch data on zoom level change * add metric aggs to request * fix bug where initial draw did not have styles set up * make tooltips work * fix import broken with merging master * use custom labels in tooltips * remove duplicate keys and clean up title and desc wording * update source description * update references migration to extract references for pew pew source * add percy visual test to ensure pew pew map data is fetch, processed, and visualized as expected * update title and description * use GEO_FIELD_TYPES in filterGeoField function * remove unneeded Fragment wrapper * fix typo * update inspector description id and message
- Loading branch information
Showing
12 changed files
with
832 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
61 changes: 61 additions & 0 deletions
61
x-pack/legacy/plugins/maps/public/layers/sources/es_pew_pew_source/convert_to_lines.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
/* | ||
* 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 _ from 'lodash'; | ||
|
||
const LAT_INDEX = 0; | ||
const LON_INDEX = 1; | ||
|
||
function parsePointFromKey(key) { | ||
const split = key.split(','); | ||
const lat = parseFloat(split[LAT_INDEX]); | ||
const lon = parseFloat(split[LON_INDEX]); | ||
return [lon, lat]; | ||
} | ||
|
||
export function convertToLines(esResponse) { | ||
|
||
const lineFeatures = []; | ||
|
||
const destBuckets = _.get(esResponse, 'aggregations.destSplit.buckets', []); | ||
for (let i = 0; i < destBuckets.length; i++) { | ||
const destBucket = destBuckets[i]; | ||
const dest = parsePointFromKey(destBucket.key); | ||
const sourceBuckets = _.get(destBucket, 'sourceGrid.buckets', []); | ||
for (let j = 0; j < sourceBuckets.length; j++) { | ||
const { | ||
key, // eslint-disable-line no-unused-vars | ||
sourceCentroid, | ||
...rest | ||
} = sourceBuckets[j]; | ||
|
||
// flatten metrics | ||
Object.keys(rest).forEach(key => { | ||
if (_.has(rest[key], 'value')) { | ||
rest[key] = rest[key].value; | ||
} | ||
}); | ||
|
||
lineFeatures.push({ | ||
type: 'Feature', | ||
geometry: { | ||
type: 'LineString', | ||
coordinates: [[sourceCentroid.location.lon, sourceCentroid.location.lat], dest] | ||
}, | ||
properties: { | ||
...rest | ||
} | ||
}); | ||
} | ||
} | ||
|
||
return { | ||
featureCollection: { | ||
type: 'FeatureCollection', | ||
features: lineFeatures | ||
} | ||
}; | ||
} |
208 changes: 208 additions & 0 deletions
208
x-pack/legacy/plugins/maps/public/layers/sources/es_pew_pew_source/create_source_editor.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,208 @@ | ||
/* | ||
* 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 _ from 'lodash'; | ||
import React, { Fragment, Component } from 'react'; | ||
import PropTypes from 'prop-types'; | ||
|
||
import { IndexPatternSelect } from 'ui/index_patterns'; | ||
import { SingleFieldSelect } from '../../../components/single_field_select'; | ||
import { indexPatternService } from '../../../kibana_services'; | ||
import { i18n } from '@kbn/i18n'; | ||
import { FormattedMessage } from '@kbn/i18n/react'; | ||
|
||
import { | ||
EuiFormRow, | ||
EuiCallOut, | ||
} from '@elastic/eui'; | ||
import { ES_GEO_FIELD_TYPE } from '../../../../common/constants'; | ||
|
||
const GEO_FIELD_TYPES = [ES_GEO_FIELD_TYPE.GEO_POINT]; | ||
|
||
function filterGeoField({ type }) { | ||
return GEO_FIELD_TYPES.includes(type); | ||
} | ||
|
||
export class CreateSourceEditor extends Component { | ||
|
||
static propTypes = { | ||
onSourceConfigChange: PropTypes.func.isRequired, | ||
}; | ||
|
||
state = { | ||
isLoadingIndexPattern: false, | ||
indexPattern: undefined, | ||
indexPatternId: undefined, | ||
sourceGeoField: undefined, | ||
destGeoField: undefined, | ||
indexPatternHasMultipleGeoFields: false, | ||
} | ||
|
||
componentWillUnmount() { | ||
this._isMounted = false; | ||
} | ||
|
||
componentDidMount() { | ||
this._isMounted = true; | ||
} | ||
|
||
onIndexPatternSelect = (indexPatternId) => { | ||
this.setState({ | ||
indexPatternId, | ||
}, this.loadIndexPattern.bind(null, indexPatternId)); | ||
}; | ||
|
||
loadIndexPattern = (indexPatternId) => { | ||
this.setState({ | ||
isLoadingIndexPattern: true, | ||
indexPattern: undefined, | ||
sourceGeoField: undefined, | ||
destGeoField: undefined, | ||
indexPatternHasMultipleGeoFields: false, | ||
}, this.debouncedLoad.bind(null, indexPatternId)); | ||
}; | ||
|
||
debouncedLoad = _.debounce(async (indexPatternId) => { | ||
if (!indexPatternId || indexPatternId.length === 0) { | ||
return; | ||
} | ||
|
||
let indexPattern; | ||
try { | ||
indexPattern = await indexPatternService.get(indexPatternId); | ||
} catch (err) { | ||
// index pattern no longer exists | ||
return; | ||
} | ||
|
||
if (!this._isMounted) { | ||
return; | ||
} | ||
|
||
// props.indexPatternId may be updated before getIndexPattern returns | ||
// ignore response when fetched index pattern does not match active index pattern | ||
if (this.state.indexPatternId !== indexPatternId) { | ||
return; | ||
} | ||
|
||
const geoFields = indexPattern.fields.filter(filterGeoField); | ||
|
||
this.setState({ | ||
isLoadingIndexPattern: false, | ||
indexPattern: indexPattern, | ||
indexPatternHasMultipleGeoFields: geoFields.length >= 2, | ||
}); | ||
}, 300); | ||
|
||
_onSourceGeoSelect = (sourceGeoField) => { | ||
this.setState({ | ||
sourceGeoField | ||
}, this.previewLayer); | ||
}; | ||
|
||
_onDestGeoSelect = (destGeoField) => { | ||
this.setState({ | ||
destGeoField | ||
}, this.previewLayer); | ||
}; | ||
|
||
previewLayer = () => { | ||
const { | ||
indexPatternId, | ||
sourceGeoField, | ||
destGeoField, | ||
} = this.state; | ||
|
||
const sourceConfig = (indexPatternId && sourceGeoField && destGeoField) | ||
? { indexPatternId, sourceGeoField, destGeoField } | ||
: null; | ||
this.props.onSourceConfigChange(sourceConfig); | ||
}; | ||
|
||
_renderGeoSelects() { | ||
if (!this.state.indexPattern || !this.state.indexPatternHasMultipleGeoFields) { | ||
return null; | ||
} | ||
|
||
return ( | ||
<Fragment> | ||
<EuiFormRow label={i18n.translate('xpack.maps.source.pewPew.sourceGeoFieldLabel', { | ||
defaultMessage: 'Source' | ||
})} | ||
> | ||
<SingleFieldSelect | ||
placeholder={i18n.translate('xpack.maps.source.pewPew.sourceGeoFieldPlaceholder', { | ||
defaultMessage: 'Select source geo field' | ||
})} | ||
value={this.state.sourceGeoField} | ||
onChange={this._onSourceGeoSelect} | ||
filterField={filterGeoField} | ||
fields={this.state.indexPattern ? this.state.indexPattern.fields : undefined} | ||
/> | ||
</EuiFormRow> | ||
|
||
<EuiFormRow label={i18n.translate('xpack.maps.source.pewPew.destGeoFieldLabel', { | ||
defaultMessage: 'Destination' | ||
})} | ||
> | ||
<SingleFieldSelect | ||
placeholder={i18n.translate('xpack.maps.source.pewPew.destGeoFieldPlaceholder', { | ||
defaultMessage: 'Select destination geo field' | ||
})} | ||
value={this.state.destGeoField} | ||
onChange={this._onDestGeoSelect} | ||
filterField={filterGeoField} | ||
fields={this.state.indexPattern ? this.state.indexPattern.fields : undefined} | ||
/> | ||
</EuiFormRow> | ||
</Fragment> | ||
); | ||
} | ||
|
||
_renderIndexPatternSelect() { | ||
return ( | ||
<EuiFormRow label={i18n.translate('xpack.maps.source.pewPew.indexPatternLabel', { | ||
defaultMessage: 'Index pattern' | ||
})} | ||
> | ||
<IndexPatternSelect | ||
indexPatternId={this.state.indexPatternId} | ||
onChange={this.onIndexPatternSelect} | ||
placeholder={i18n.translate('xpack.maps.source.pewPew.indexPatternPlaceholder', { | ||
defaultMessage: 'Select index pattern' | ||
})} | ||
fieldTypes={GEO_FIELD_TYPES} | ||
/> | ||
</EuiFormRow> | ||
); | ||
} | ||
|
||
render() { | ||
let callout; | ||
if (this.state.indexPattern && !this.state.indexPatternHasMultipleGeoFields) { | ||
callout = ( | ||
<EuiCallOut | ||
color="warning" | ||
> | ||
<p> | ||
<FormattedMessage | ||
id="xpack.maps.source.pewPew.noSourceAndDestDetails" | ||
defaultMessage="Selected index pattern does not contain source and destination fields." | ||
/> | ||
</p> | ||
</EuiCallOut> | ||
); | ||
} | ||
|
||
return ( | ||
<Fragment> | ||
{callout} | ||
{this._renderIndexPatternSelect()} | ||
{this._renderGeoSelects()} | ||
</Fragment> | ||
); | ||
} | ||
} |
Oops, something went wrong.