[Maps] add drawing toolbar to create filters to map (#33686)
This commit is contained in:
parent
1ef872c784
commit
2dd07b1b4e
|
@ -52,6 +52,7 @@ export const LICENSE_WHITELIST = [
|
|||
'CC-BY-3.0',
|
||||
'CC-BY-4.0',
|
||||
'Eclipse Distribution License - v 1.0',
|
||||
'FreeBSD',
|
||||
'ISC',
|
||||
'ISC*',
|
||||
'MIT OR GPL-2.0',
|
||||
|
|
|
@ -178,6 +178,7 @@
|
|||
"@kbn/i18n": "1.0.0",
|
||||
"@kbn/interpreter": "1.0.0",
|
||||
"@kbn/ui-framework": "1.0.0",
|
||||
"@mapbox/mapbox-gl-draw": "^1.1.1",
|
||||
"@samverschueren/stream-to-observable": "^0.3.0",
|
||||
"@scant/router": "^0.1.0",
|
||||
"@slack/client": "^4.8.0",
|
||||
|
@ -255,6 +256,7 @@
|
|||
"lodash.uniqby": "^4.7.0",
|
||||
"lz-string": "^1.4.4",
|
||||
"mapbox-gl": "0.52.0",
|
||||
"mapbox-gl-draw-rectangle-mode": "^1.0.4",
|
||||
"markdown-it": "^8.4.1",
|
||||
"mime": "^2.2.2",
|
||||
"mkdirp": "0.5.1",
|
||||
|
|
|
@ -28,3 +28,8 @@ export const APP_ICON = 'gisApp';
|
|||
export const SOURCE_DATA_ID_ORIGIN = 'source';
|
||||
|
||||
export const FEATURE_ID_PROPERTY_NAME = '__kbn__feature_id__';
|
||||
|
||||
export const ES_GEO_FIELD_TYPE = {
|
||||
GEO_POINT: 'geo_point',
|
||||
GEO_SHAPE: 'geo_shape'
|
||||
};
|
||||
|
|
|
@ -23,29 +23,39 @@
|
|||
|
||||
.mapContainer {
|
||||
flex-grow: 1;
|
||||
|
||||
.mapboxgl-popup {
|
||||
z-index: 100;
|
||||
border-color: $euiColorEmptyShade;
|
||||
}
|
||||
|
||||
.mapboxgl-popup-content {
|
||||
background-color: $euiColorEmptyShade;
|
||||
}
|
||||
|
||||
.mapboxgl-popup-tip {
|
||||
border-top-color: $euiColorEmptyShade !important;
|
||||
}
|
||||
|
||||
.mapboxgl-ctrl-top-left .mapboxgl-ctrl {
|
||||
margin-left: $euiSizeM;
|
||||
margin-top: $euiSizeM;
|
||||
}
|
||||
|
||||
.mapboxgl-ctrl-group:not(:empty) {
|
||||
@include euiBottomShadowLarge;
|
||||
background-color: $euiColorEmptyShade;
|
||||
border-radius: $euiBorderRadius;
|
||||
|
||||
> button {
|
||||
@include size($euiSizeXL);
|
||||
|
||||
+ button {
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.mapboxgl-popup {
|
||||
z-index: 100;
|
||||
border-color: $euiColorEmptyShade;
|
||||
}
|
||||
|
||||
.mapboxgl-popup-content {
|
||||
background-color: $euiColorEmptyShade;
|
||||
}
|
||||
|
||||
.mapboxgl-popup-tip {
|
||||
border-top-color: $euiColorEmptyShade !important;
|
||||
}
|
||||
|
||||
// This is not good practice to create such a generic class.
|
||||
// I can't seem to find it being applied anywhere in GIS
|
||||
// .hidden {
|
||||
// display: none
|
||||
// }
|
||||
|
||||
// EUIFIXTODO:
|
||||
|
||||
.euiColorPicker__emptySwatch {
|
||||
position: relative;
|
||||
}
|
||||
|
|
|
@ -52,6 +52,12 @@ export const TRACK_CURRENT_LAYER_STATE = 'TRACK_CURRENT_LAYER_STATE';
|
|||
export const ROLLBACK_TO_TRACKED_LAYER_STATE = 'ROLLBACK_TO_TRACKED_LAYER_STATE';
|
||||
export const REMOVE_TRACKED_LAYER_STATE = 'REMOVE_TRACKED_LAYER_STATE';
|
||||
export const SET_TOOLTIP_STATE = 'SET_TOOLTIP_STATE';
|
||||
export const UPDATE_DRAW_STATE = 'UPDATE_DRAW_STATE';
|
||||
|
||||
export const DRAW_TYPE = {
|
||||
BOUNDS: 'BOUNDS',
|
||||
POLYGON: 'POLYGON'
|
||||
};
|
||||
export const SET_SCROLL_ZOOM = 'SET_SCROLL_ZOOM';
|
||||
|
||||
function getLayerLoadingCallbacks(dispatch, layerId) {
|
||||
|
@ -685,3 +691,15 @@ export function setJoinsForLayer(layer, joins) {
|
|||
dispatch(syncDataForLayer(layer.getId()));
|
||||
};
|
||||
}
|
||||
|
||||
export function updateDrawState(drawState) {
|
||||
return async (dispatch) => {
|
||||
if (drawState !== null) {
|
||||
await dispatch(setTooltipState(null));//tooltips just get in the way
|
||||
}
|
||||
dispatch({
|
||||
type: UPDATE_DRAW_STATE,
|
||||
drawState: drawState
|
||||
});
|
||||
};
|
||||
}
|
||||
|
|
|
@ -2,3 +2,4 @@
|
|||
@import './layer_addpanel/layer_addpanel';
|
||||
@import './layer_panel/index';
|
||||
@import './widget_overlay/index';
|
||||
@import './toolbar_overlay/index';
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
import React, { Component } from 'react';
|
||||
import { MBMapContainer } from '../map/mb';
|
||||
import { WidgetOverlay } from '../widget_overlay/index';
|
||||
import { ToolbarOverlay } from '../toolbar_overlay/index';
|
||||
import { LayerPanel } from '../layer_panel/index';
|
||||
import { AddLayerPanel } from '../layer_addpanel/index';
|
||||
import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
|
||||
|
@ -47,13 +48,13 @@ export class GisMap extends Component {
|
|||
interval
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
clearRefreshTimer = () => {
|
||||
if (this.refreshTimerId) {
|
||||
clearInterval(this.refreshTimerId);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
|
@ -91,6 +92,7 @@ export class GisMap extends Component {
|
|||
<EuiFlexGroup gutterSize="none" responsive={false}>
|
||||
<EuiFlexItem className="mapMapWrapper">
|
||||
<MBMapContainer/>
|
||||
<ToolbarOverlay />
|
||||
<WidgetOverlay/>
|
||||
</EuiFlexItem>
|
||||
|
||||
|
|
|
@ -13,9 +13,17 @@ import {
|
|||
setMouseCoordinates,
|
||||
clearMouseCoordinates,
|
||||
clearGoto,
|
||||
setTooltipState
|
||||
setTooltipState,
|
||||
updateDrawState
|
||||
} from '../../../actions/store_actions';
|
||||
import { getTooltipState, getLayerList, getMapReady, getGoto, getScrollZoom } from '../../../selectors/map_selectors';
|
||||
import {
|
||||
getTooltipState,
|
||||
getLayerList,
|
||||
getMapReady,
|
||||
getGoto,
|
||||
getDrawState,
|
||||
getScrollZoom
|
||||
} from '../../../selectors/map_selectors';
|
||||
import { getIsFilterable } from '../../../store/ui';
|
||||
import { getInspectorAdapters } from '../../../store/non_serializable_instances';
|
||||
|
||||
|
@ -27,7 +35,8 @@ function mapStateToProps(state = {}) {
|
|||
goto: getGoto(state),
|
||||
inspectorAdapters: getInspectorAdapters(state),
|
||||
tooltipState: getTooltipState(state),
|
||||
scrollZoom: getScrollZoom(state),
|
||||
drawState: getDrawState(state),
|
||||
scrollZoom: getScrollZoom(state)
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -55,6 +64,9 @@ function mapDispatchToProps(dispatch) {
|
|||
},
|
||||
setTooltipState(tooltipState) {
|
||||
dispatch(setTooltipState(tooltipState));
|
||||
},
|
||||
disableDrawState() {
|
||||
dispatch(updateDrawState(null));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -9,10 +9,21 @@ import React from 'react';
|
|||
import ReactDOM from 'react-dom';
|
||||
import { ResizeChecker } from 'ui/resize_checker';
|
||||
import { syncLayerOrder, removeOrphanedSourcesAndLayers, createMbMapInstance } from './utils';
|
||||
import { DECIMAL_DEGREES_PRECISION, FEATURE_ID_PROPERTY_NAME, ZOOM_PRECISION } from '../../../../common/constants';
|
||||
import {
|
||||
DECIMAL_DEGREES_PRECISION,
|
||||
FEATURE_ID_PROPERTY_NAME,
|
||||
ZOOM_PRECISION
|
||||
} from '../../../../common/constants';
|
||||
import mapboxgl from 'mapbox-gl';
|
||||
import MapboxDraw from '@mapbox/mapbox-gl-draw';
|
||||
import DrawRectangle from 'mapbox-gl-draw-rectangle-mode';
|
||||
import { FeatureTooltip } from '../feature_tooltip';
|
||||
import { DRAW_TYPE } from '../../../actions/store_actions';
|
||||
import { filterBarQueryFilter } from '../../../kibana_services';
|
||||
import { createShapeFilterWithMeta, createExtentFilterWithMeta } from '../../../elasticsearch_geo_utils';
|
||||
|
||||
const mbDrawModes = MapboxDraw.modes;
|
||||
mbDrawModes.draw_rectangle = DrawRectangle;
|
||||
|
||||
const TOOLTIP_TYPE = {
|
||||
HOVER: 'HOVER',
|
||||
|
@ -21,6 +32,21 @@ const TOOLTIP_TYPE = {
|
|||
|
||||
export class MBMapContainer extends React.Component {
|
||||
|
||||
|
||||
state = {
|
||||
isDrawingFilter: false
|
||||
};
|
||||
|
||||
static getDerivedStateFromProps(nextProps, prevState) {
|
||||
const nextIsDrawingFilter = nextProps.drawState !== null;
|
||||
if (nextIsDrawingFilter === prevState.isDrawingFilter) {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
isDrawingFilter: nextIsDrawingFilter
|
||||
};
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this._mbMap = null;
|
||||
|
@ -29,22 +55,69 @@ export class MBMapContainer extends React.Component {
|
|||
closeButton: false,
|
||||
closeOnClick: false,
|
||||
});
|
||||
this._mbDrawControl = new MapboxDraw({
|
||||
displayControlsDefault: false,
|
||||
modes: mbDrawModes
|
||||
});
|
||||
this._mbDrawControlAdded = false;
|
||||
}
|
||||
|
||||
_onTooltipClose = () => {
|
||||
this.props.setTooltipState(null);
|
||||
};
|
||||
|
||||
_onDraw = async (e) => {
|
||||
|
||||
if (!e.features.length) {
|
||||
return;
|
||||
}
|
||||
const { geoField, geoFieldType, indexPatternId, drawType } = this.props.drawState;
|
||||
this.props.disableDrawState();
|
||||
|
||||
|
||||
let filter;
|
||||
if (drawType === DRAW_TYPE.POLYGON) {
|
||||
filter = createShapeFilterWithMeta(e.features[0].geometry, indexPatternId, geoField, geoFieldType);
|
||||
} else if (drawType === DRAW_TYPE.BOUNDS) {
|
||||
const coordinates = e.features[0].geometry.coordinates[0];
|
||||
const extent = {
|
||||
minLon: coordinates[0][0],
|
||||
minLat: coordinates[0][1],
|
||||
maxLon: coordinates[0][0],
|
||||
maxLat: coordinates[0][1]
|
||||
};
|
||||
for (let i = 1; i < coordinates.length; i++) {
|
||||
extent.minLon = Math.min(coordinates[i][0], extent.minLon);
|
||||
extent.minLat = Math.min(coordinates[i][1], extent.minLat);
|
||||
extent.maxLon = Math.max(coordinates[i][0], extent.maxLon);
|
||||
extent.maxLat = Math.max(coordinates[i][1], extent.maxLat);
|
||||
}
|
||||
filter = createExtentFilterWithMeta(extent, indexPatternId, geoField, geoFieldType);
|
||||
}
|
||||
|
||||
if (!filter) {
|
||||
return;
|
||||
}
|
||||
|
||||
filterBarQueryFilter.addFilters([filter]);
|
||||
};
|
||||
|
||||
_debouncedSync = _.debounce(() => {
|
||||
if (this._isMounted) {
|
||||
this._syncMbMapWithLayerList();
|
||||
this._syncMbMapWithInspector();
|
||||
this._syncDrawControl();
|
||||
}
|
||||
}, 256);
|
||||
|
||||
|
||||
_lockTooltip = (e) => {
|
||||
|
||||
if (this.state.isDrawingFilter) {
|
||||
//ignore click events when in draw mode
|
||||
return;
|
||||
}
|
||||
|
||||
this._updateHoverTooltipState.cancel();//ignore any possible moves
|
||||
|
||||
const features = this._getFeaturesUnderPointer(e.point);
|
||||
|
@ -54,7 +127,7 @@ export class MBMapContainer extends React.Component {
|
|||
}
|
||||
|
||||
const targetFeature = features[0];
|
||||
const layer = this._getLayer(targetFeature.layer.id);
|
||||
const layer = this._getLayerByMbLayerId(targetFeature.layer.id);
|
||||
const popupAnchorLocation = this._justifyAnchorLocation(e.lngLat, targetFeature);
|
||||
this.props.setTooltipState({
|
||||
type: TOOLTIP_TYPE.LOCKED,
|
||||
|
@ -66,6 +139,11 @@ export class MBMapContainer extends React.Component {
|
|||
|
||||
_updateHoverTooltipState = _.debounce((e) => {
|
||||
|
||||
if (this.state.isDrawingFilter) {
|
||||
//ignore hover events when in draw mode
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.props.tooltipState && this.props.tooltipState.type === TOOLTIP_TYPE.LOCKED) {
|
||||
//ignore hover events when tooltip is locked
|
||||
return;
|
||||
|
@ -85,7 +163,7 @@ export class MBMapContainer extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
const layer = this._getLayer(targetFeature.layer.id);
|
||||
const layer = this._getLayerByMbLayerId(targetFeature.layer.id);
|
||||
const popupAnchorLocation = this._justifyAnchorLocation(e.lngLat, targetFeature);
|
||||
|
||||
this.props.setTooltipState({
|
||||
|
@ -97,6 +175,7 @@ export class MBMapContainer extends React.Component {
|
|||
|
||||
}, 100);
|
||||
|
||||
|
||||
_justifyAnchorLocation(mbLngLat, targetFeature) {
|
||||
let popupAnchorLocation = [mbLngLat.lng, mbLngLat.lat]; // default popup location to mouse location
|
||||
if (targetFeature.geometry.type === 'Point') {
|
||||
|
@ -195,6 +274,30 @@ export class MBMapContainer extends React.Component {
|
|||
this.props.onMapDestroyed();
|
||||
}
|
||||
|
||||
_removeDrawControl() {
|
||||
if (!this._mbDrawControlAdded) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._mbMap.getCanvas().style.cursor = '';
|
||||
this._mbMap.off('draw.create', this._onDraw);
|
||||
this._mbMap.removeControl(this._mbDrawControl);
|
||||
this._mbDrawControlAdded = false;
|
||||
|
||||
}
|
||||
|
||||
_updateDrawControl() {
|
||||
if (!this._mbDrawControlAdded) {
|
||||
this._mbMap.addControl(this._mbDrawControl);
|
||||
this._mbDrawControlAdded = true;
|
||||
this._mbMap.getCanvas().style.cursor = 'crosshair';
|
||||
this._mbMap.on('draw.create', this._onDraw);
|
||||
}
|
||||
const mbDrawMode = this.props.drawState.drawType === DRAW_TYPE.POLYGON ?
|
||||
this._mbDrawControl.modes.DRAW_POLYGON : 'draw_rectangle';
|
||||
this._mbDrawControl.changeMode(mbDrawMode);
|
||||
}
|
||||
|
||||
async _initializeMap() {
|
||||
|
||||
this._mbMap = await createMbMapInstance({
|
||||
|
@ -293,6 +396,14 @@ export class MBMapContainer extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
_syncDrawControl() {
|
||||
if (this.state.isDrawingFilter) {
|
||||
this._updateDrawControl();
|
||||
} else {
|
||||
this._removeDrawControl();
|
||||
}
|
||||
}
|
||||
|
||||
_syncMbMapWithMapState = () => {
|
||||
const {
|
||||
isMapReady,
|
||||
|
@ -326,7 +437,13 @@ export class MBMapContainer extends React.Component {
|
|||
|
||||
};
|
||||
|
||||
_getLayer(mbLayerId) {
|
||||
_getLayerById(layerId) {
|
||||
return this.props.layerList.find((layer) => {
|
||||
return layer.getId() === layerId;
|
||||
});
|
||||
}
|
||||
|
||||
_getLayerByMbLayerId(mbLayerId) {
|
||||
return this.props.layerList.find((layer) => {
|
||||
const mbLayerIds = layer.getMbLayerIds();
|
||||
return mbLayerIds.indexOf(mbLayerId) > -1;
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
.mapToolbarOverlay {
|
||||
position: absolute;
|
||||
top: ($euiSizeM * 2) + ($euiSizeXL * 2); // Position and height of mapbox controls plus margin
|
||||
left: $euiSizeM;
|
||||
z-index: 2; // Sit on top of mapbox controls shadow
|
||||
}
|
||||
|
||||
.mapToolbarOverlay__button {
|
||||
@include size($euiSizeXL);
|
||||
background-color: $euiColorEmptyShade !important;
|
||||
|
||||
&:enabled,
|
||||
&:enabled:hover,
|
||||
&:enabled:focus {
|
||||
@include euiBottomShadowLarge;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* 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 { connect } from 'react-redux';
|
||||
import { ToolbarOverlay } from './view';
|
||||
import { getDrawState, getUniqueIndexPatternIds } from '../../selectors/map_selectors';
|
||||
import { getIsFilterable } from '../../store/ui';
|
||||
import { updateDrawState } from '../../actions/store_actions';
|
||||
|
||||
|
||||
function mapStateToProps(state = {}) {
|
||||
return {
|
||||
isFilterable: getIsFilterable(state),
|
||||
drawState: getDrawState(state),
|
||||
uniqueIndexPatternIds: getUniqueIndexPatternIds(state)
|
||||
};
|
||||
}
|
||||
|
||||
function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
initiateDraw: (options) => {
|
||||
dispatch(updateDrawState(options));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const connectedToolbarOverlay = connect(mapStateToProps, mapDispatchToProps)(ToolbarOverlay);
|
||||
export { connectedToolbarOverlay as ToolbarOverlay };
|
282
x-pack/plugins/maps/public/components/toolbar_overlay/view.js
Normal file
282
x-pack/plugins/maps/public/components/toolbar_overlay/view.js
Normal file
|
@ -0,0 +1,282 @@
|
|||
/*
|
||||
* 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 React, { Fragment } from 'react';
|
||||
import {
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiButtonIcon,
|
||||
EuiPopover,
|
||||
EuiContextMenu,
|
||||
EuiSelectable,
|
||||
EuiHighlight,
|
||||
EuiTextColor,
|
||||
} from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { getIndexPatternsFromIds } from '../../index_pattern_util';
|
||||
import _ from 'lodash';
|
||||
import { DRAW_TYPE } from '../../actions/store_actions';
|
||||
import { ES_GEO_FIELD_TYPE } from '../../../common/constants';
|
||||
|
||||
const RESET_STATE = {
|
||||
isPopoverOpen: false,
|
||||
drawType: null
|
||||
};
|
||||
|
||||
export class ToolbarOverlay extends React.Component {
|
||||
|
||||
|
||||
state = {
|
||||
isPopoverOpen: false,
|
||||
uniqueIndexPatternsAndGeoFields: [],
|
||||
drawType: null
|
||||
};
|
||||
|
||||
_toggleToolbar = () => {
|
||||
if (!this._isMounted) {
|
||||
return;
|
||||
}
|
||||
this.setState(prevState => ({
|
||||
isPopoverOpen: !prevState.isPopoverOpen,
|
||||
drawType: null
|
||||
}));
|
||||
};
|
||||
|
||||
_closePopover = () => {
|
||||
if (!this._isMounted) {
|
||||
return;
|
||||
}
|
||||
this.setState(RESET_STATE);
|
||||
};
|
||||
|
||||
_onIndexPatternSelection = (options) => {
|
||||
if (!this._isMounted) {
|
||||
return;
|
||||
}
|
||||
|
||||
const selection = options.find((option) => option.checked);
|
||||
const drawType = this.state.drawType;
|
||||
this.setState(RESET_STATE, () => {
|
||||
if (drawType) {
|
||||
this.props.initiateDraw({ drawType: drawType, ...selection.value });
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
_activateDrawForFirstIndexPattern = (drawType) => {
|
||||
if (!this._isMounted) {
|
||||
return;
|
||||
}
|
||||
const indexPatternAndGeofield = this.state.uniqueIndexPatternsAndGeoFields[0];
|
||||
this.setState(RESET_STATE, () => {
|
||||
this.props.initiateDraw({ drawType: drawType, ...indexPatternAndGeofield });
|
||||
});
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
this._isMounted = true;
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this._isMounted = false;
|
||||
}
|
||||
|
||||
async _getuniqueIndexPatternAndFieldCombos() {
|
||||
try {
|
||||
const indexPatterns = await getIndexPatternsFromIds(this.props.uniqueIndexPatternIds);
|
||||
const uniqueIndexPatternsAndGeofields = [];
|
||||
indexPatterns.forEach((indexPattern) => {
|
||||
indexPattern.fields.forEach(field => {
|
||||
if (field.type === ES_GEO_FIELD_TYPE.GEO_POINT || field.type === ES_GEO_FIELD_TYPE.GEO_SHAPE) {
|
||||
uniqueIndexPatternsAndGeofields.push({
|
||||
geoField: field.name,
|
||||
geoFieldType: field.type,
|
||||
indexPatternTitle: indexPattern.title,
|
||||
indexPatternId: indexPattern.id
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
if (this._isMounted && !_.isEqual(this.state.uniqueIndexPatternsAndGeoFields, uniqueIndexPatternsAndGeofields)) {
|
||||
this.setState({
|
||||
uniqueIndexPatternsAndGeoFields: uniqueIndexPatternsAndGeofields
|
||||
});
|
||||
}
|
||||
} catch(e) {
|
||||
// swallow errors.
|
||||
// the Layer-TOC will indicate which layers are disfunctional on a per-layer basis
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
this._getuniqueIndexPatternAndFieldCombos();
|
||||
}
|
||||
|
||||
_getDrawActionsPanel() {
|
||||
|
||||
const drawPolygonAction = {
|
||||
name: i18n.translate('xpack.maps.toolbarOverlay.drawShapeLabel', {
|
||||
defaultMessage: 'Draw shape to filter data',
|
||||
}),
|
||||
};
|
||||
|
||||
const drawBoundsAction = {
|
||||
name: i18n.translate('xpack.maps.toolbarOverlay.drawBoundsLabel', {
|
||||
defaultMessage: 'Draw bounds to filter data',
|
||||
}),
|
||||
};
|
||||
|
||||
if (this.state.uniqueIndexPatternsAndGeoFields.length === 1) {
|
||||
drawPolygonAction.onClick = () => this._activateDrawForFirstIndexPattern(DRAW_TYPE.POLYGON);
|
||||
drawBoundsAction.onClick = () => this._activateDrawForFirstIndexPattern(DRAW_TYPE.BOUNDS);
|
||||
} else {
|
||||
drawPolygonAction.panel = this._getIndexPatternSelectionPanel(1);
|
||||
drawPolygonAction.onClick = () => {
|
||||
this.setState({ drawType: DRAW_TYPE.POLYGON });
|
||||
};
|
||||
drawBoundsAction.panel = this._getIndexPatternSelectionPanel(2);
|
||||
drawBoundsAction.onClick = () => {
|
||||
this.setState({ drawType: DRAW_TYPE.BOUNDS });
|
||||
};
|
||||
}
|
||||
|
||||
return flattenPanelTree({
|
||||
id: 0,
|
||||
title: i18n.translate('xpack.maps.toolbarOverlay.tools.toolbarTitle', {
|
||||
defaultMessage: 'Tools',
|
||||
}),
|
||||
items: [drawPolygonAction, drawBoundsAction]
|
||||
});
|
||||
}
|
||||
|
||||
_getIndexPatternSelectionPanel(id) {
|
||||
const options = this.state.uniqueIndexPatternsAndGeoFields.map((indexPatternAndGeoField) => {
|
||||
return {
|
||||
label: `${indexPatternAndGeoField.indexPatternTitle} : ${indexPatternAndGeoField.geoField}`,
|
||||
value: indexPatternAndGeoField
|
||||
};
|
||||
});
|
||||
|
||||
const renderGeoField = (option, searchValue) => {
|
||||
return (
|
||||
<Fragment>
|
||||
<EuiTextColor color="subdued">
|
||||
<small>
|
||||
<EuiHighlight search={searchValue}>{option.value.indexPatternTitle}</EuiHighlight>
|
||||
</small>
|
||||
</EuiTextColor>
|
||||
<br />
|
||||
<EuiHighlight search={searchValue}>
|
||||
{option.value.geoField}
|
||||
</EuiHighlight>
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
const indexPatternSelection = (
|
||||
<EuiSelectable
|
||||
searchable
|
||||
searchProps={{
|
||||
placeholder: i18n.translate('xpack.maps.toolbarOverlay.indexPattern.filterListTitle', {
|
||||
defaultMessage: 'Filter list',
|
||||
}),
|
||||
compressed: true,
|
||||
}}
|
||||
options={options}
|
||||
/**
|
||||
* *TODO*: FIX this handler as EuiSelectable passes back the full options
|
||||
* list with the selected option set with `checked: 'on'`
|
||||
*/
|
||||
onChange={this._onIndexPatternSelection}
|
||||
renderOption={renderGeoField}
|
||||
listProps={{
|
||||
rowHeight: 50,
|
||||
showIcons: false,
|
||||
}}
|
||||
>
|
||||
{(list, search) => (
|
||||
<div>
|
||||
{search}
|
||||
{list}
|
||||
</div>
|
||||
)}
|
||||
</EuiSelectable>
|
||||
);
|
||||
|
||||
return {
|
||||
id: id,
|
||||
title: i18n.translate('xpack.maps.toolbarOverlay.geofield.toolbarTitle', {
|
||||
defaultMessage: 'Select geo field',
|
||||
}),
|
||||
content: indexPatternSelection
|
||||
};
|
||||
}
|
||||
|
||||
_renderToolbarButton() {
|
||||
return (
|
||||
<EuiButtonIcon
|
||||
className="mapToolbarOverlay__button"
|
||||
color="text"
|
||||
iconType="wrench"
|
||||
onClick={this._toggleToolbar}
|
||||
aria-label={i18n.translate('xpack.maps.toolbarOverlay.toolbarIconTitle', {
|
||||
defaultMessage: 'Tools',
|
||||
})}
|
||||
title={i18n.translate('xpack.maps.toolbarOverlay.toolbarIconTitle', {
|
||||
defaultMessage: 'Tools',
|
||||
})}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
if (
|
||||
!this.props.isFilterable ||
|
||||
!this.state.uniqueIndexPatternsAndGeoFields.length
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<EuiFlexGroup className="mapToolbarOverlay" responsive={false} direction="row" alignItems="flexEnd" gutterSize="s">
|
||||
<EuiFlexItem>
|
||||
<EuiPopover
|
||||
id="contextMenu"
|
||||
button={this._renderToolbarButton()}
|
||||
isOpen={this.state.isPopoverOpen}
|
||||
closePopover={this._closePopover}
|
||||
panelPaddingSize="none"
|
||||
withTitle
|
||||
anchorPosition="leftUp"
|
||||
>
|
||||
<EuiContextMenu
|
||||
initialPanelId={0}
|
||||
panels={this._getDrawActionsPanel()}
|
||||
/>
|
||||
</EuiPopover>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function flattenPanelTree(tree, array = []) {
|
||||
array.push(tree);
|
||||
|
||||
if (tree.items) {
|
||||
tree.items.forEach(item => {
|
||||
if (item.panel) {
|
||||
flattenPanelTree(item.panel, array);
|
||||
item.panel = item.panel.id;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
import _ from 'lodash';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { DECIMAL_DEGREES_PRECISION, ES_GEO_FIELD_TYPE } from '../common/constants';
|
||||
|
||||
/**
|
||||
* Converts Elasticsearch search results into GeoJson FeatureCollection
|
||||
|
@ -25,9 +26,9 @@ export function hitsToGeoJson(hits, flattenHit, geoFieldName, geoFieldType) {
|
|||
const properties = flattenHit(hits[i]);
|
||||
|
||||
tmpGeometriesAccumulator.length = 0;//truncate accumulator
|
||||
if (geoFieldType === 'geo_point') {
|
||||
if (geoFieldType === ES_GEO_FIELD_TYPE.GEO_POINT) {
|
||||
geoPointToGeometry(properties[geoFieldName], tmpGeometriesAccumulator);
|
||||
} else if (geoFieldType === 'geo_shape') {
|
||||
} else if (geoFieldType === ES_GEO_FIELD_TYPE.GEO_SHAPE) {
|
||||
geoShapeToGeometry(properties[geoFieldName], tmpGeometriesAccumulator);
|
||||
} else {
|
||||
const errorMessage = i18n.translate('xpack.maps.elasticsearch_geo_utils.unsupportedFieldTypeErrorMessage', {
|
||||
|
@ -184,8 +185,7 @@ const BOTTOM_RIGHT_INDEX = 2;
|
|||
|
||||
export function createExtentFilter(mapExtent, geoFieldName, geoFieldType) {
|
||||
const safePolygon = convertMapExtentToPolygon(mapExtent);
|
||||
|
||||
if (geoFieldType === 'geo_point') {
|
||||
if (geoFieldType === ES_GEO_FIELD_TYPE.GEO_POINT) {
|
||||
const verticies = safePolygon.coordinates[POLYGON_COORDINATES_EXTERIOR_INDEX];
|
||||
return {
|
||||
geo_bounding_box: {
|
||||
|
@ -195,7 +195,7 @@ export function createExtentFilter(mapExtent, geoFieldName, geoFieldType) {
|
|||
}
|
||||
}
|
||||
};
|
||||
} else if (geoFieldType === 'geo_shape') {
|
||||
} else if (geoFieldType === ES_GEO_FIELD_TYPE.GEO_SHAPE) {
|
||||
return {
|
||||
geo_shape: {
|
||||
[geoFieldName]: {
|
||||
|
@ -205,7 +205,7 @@ export function createExtentFilter(mapExtent, geoFieldName, geoFieldType) {
|
|||
}
|
||||
};
|
||||
} else {
|
||||
const errorMessage = i18n.translate('xpack.maps.elasticsearch_geo_utils.unsupportedGeoFieldTypeErrorMessage', {
|
||||
const errorMessage = i18n.translate('xpack.maps.elasticsearch_geo_utils.extent.unsupportedGeoFieldTypeErrorMessage', {
|
||||
defaultMessage: `Unsupported field type, expected: geo_shape or geo_point, you provided: {geoFieldType}`,
|
||||
values: { geoFieldType }
|
||||
});
|
||||
|
@ -213,6 +213,85 @@ export function createExtentFilter(mapExtent, geoFieldName, geoFieldType) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
export function createExtentFilterWithMeta(mapExtent, indexPatternId, geoFieldName, geoFieldType) {
|
||||
|
||||
const roundedExtent = {
|
||||
minLon: _.round(mapExtent.minLon, DECIMAL_DEGREES_PRECISION),
|
||||
minLat: _.round(mapExtent.minLat, DECIMAL_DEGREES_PRECISION),
|
||||
maxLon: _.round(mapExtent.maxLon, DECIMAL_DEGREES_PRECISION),
|
||||
maxLat: _.round(mapExtent.maxLat, DECIMAL_DEGREES_PRECISION)
|
||||
};
|
||||
|
||||
const filter = createExtentFilter(roundedExtent, geoFieldName, geoFieldType);
|
||||
filter.meta = {
|
||||
negate: false,
|
||||
index: indexPatternId,
|
||||
alias: i18n.translate('xpack.maps.elasticsearch_geo_utils.extentFilter.aliasTitle', {
|
||||
defaultMessage: `extent at {coordinate}`,
|
||||
values: {
|
||||
coordinate: `[${roundedExtent.minLon}, ${roundedExtent.minLat}, ${roundedExtent.maxLon}, ${roundedExtent.maxLat}]`
|
||||
}
|
||||
})
|
||||
};
|
||||
return filter;
|
||||
}
|
||||
|
||||
export function createShapeFilterWithMeta(geojsonPolygon, indexPatternId, geoFieldName, geoFieldType) {
|
||||
|
||||
const filter = {
|
||||
meta: {
|
||||
negate: false,
|
||||
index: indexPatternId,
|
||||
alias: i18n.translate('xpack.maps.elasticsearch_geo_utils.shapeFilter.aliasTitle', {
|
||||
defaultMessage: `shape at {coordinate}`,
|
||||
values: {
|
||||
// eslint-disable-next-line max-len
|
||||
coordinate: `${_.round(geojsonPolygon.coordinates[0][0][0], DECIMAL_DEGREES_PRECISION)}, ${_.round(geojsonPolygon.coordinates[0][0][1], DECIMAL_DEGREES_PRECISION)}`
|
||||
}
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
if (geoFieldType === ES_GEO_FIELD_TYPE.GEO_POINT) {
|
||||
const pointsArray = geojsonPolygon.coordinates[0].map(coordinatePair => {
|
||||
return {
|
||||
lon: _.round(coordinatePair[0], DECIMAL_DEGREES_PRECISION),
|
||||
lat: _.round(coordinatePair[1], DECIMAL_DEGREES_PRECISION)
|
||||
};
|
||||
});
|
||||
filter.geo_polygon = {
|
||||
ignore_unmapped: true,
|
||||
[geoFieldName]: {
|
||||
points: pointsArray
|
||||
}
|
||||
};
|
||||
} else if (geoFieldType === ES_GEO_FIELD_TYPE.GEO_SHAPE) {
|
||||
const geojsonCoordinateArray = geojsonPolygon.coordinates[0].map(coordinatePair => {
|
||||
return [_.round(coordinatePair[0], DECIMAL_DEGREES_PRECISION), _.round(coordinatePair[1], DECIMAL_DEGREES_PRECISION)];
|
||||
});
|
||||
filter.geo_shape = {
|
||||
ignore_unmapped: true,
|
||||
[geoFieldName]: {
|
||||
shape: {
|
||||
type: 'Polygon',
|
||||
coordinates: [geojsonCoordinateArray]
|
||||
},
|
||||
relation: 'INTERSECTS'
|
||||
}
|
||||
};
|
||||
} else {
|
||||
const errorMessage = i18n.translate('xpack.maps.elasticsearch_geo_utils.shape.unsupportedGeoFieldTypeErrorMessage', {
|
||||
defaultMessage: `Unsupported field type, expected: geo_shape or geo_point, you provided: {geoFieldType}`,
|
||||
values: { geoFieldType }
|
||||
});
|
||||
throw new Error(errorMessage);
|
||||
}
|
||||
return filter;
|
||||
}
|
||||
|
||||
|
||||
|
||||
function formatEnvelopeAsPolygon({ maxLat, maxLon, minLat, minLon }) {
|
||||
// GeoJSON mandates that the outer polygon must be counterclockwise to avoid ambiguous polygons
|
||||
// when the shape crosses the dateline
|
||||
|
|
|
@ -24,8 +24,6 @@ import 'ui/autoload/styles';
|
|||
import 'ui/autoload/all';
|
||||
import 'react-vis/dist/style.css';
|
||||
|
||||
import 'mapbox-gl/dist/mapbox-gl.css';
|
||||
|
||||
import './angular/services/gis_map_saved_object_loader';
|
||||
import './angular/map_controller';
|
||||
import listingTemplate from './angular/listing_ng_wrapper.html';
|
||||
|
|
21
x-pack/plugins/maps/public/index_pattern_util.js
Normal file
21
x-pack/plugins/maps/public/index_pattern_util.js
Normal file
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* 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 { indexPatternService } from './kibana_services';
|
||||
|
||||
export async function getIndexPatternsFromIds(indexPatternIds) {
|
||||
|
||||
const promises = [];
|
||||
indexPatternIds.forEach((id) => {
|
||||
const indexPatternPromise = indexPatternService.get(id);
|
||||
if (indexPatternPromise) {
|
||||
promises.push(indexPatternPromise);
|
||||
}
|
||||
});
|
||||
|
||||
return await Promise.all(promises);
|
||||
|
||||
}
|
|
@ -113,6 +113,8 @@ export const getQuery = ({ map }) => map.mapState.query;
|
|||
|
||||
export const getFilters = ({ map }) => map.mapState.filters;
|
||||
|
||||
export const getDrawState = ({ map }) => map.mapState.drawState;
|
||||
|
||||
export const getRefreshConfig = ({ map }) => {
|
||||
if (map.mapState.refreshConfig) {
|
||||
return map.mapState.refreshConfig;
|
||||
|
|
|
@ -20,9 +20,10 @@ import {
|
|||
EuiComboBox,
|
||||
EuiSpacer,
|
||||
} from '@elastic/eui';
|
||||
import { ES_GEO_FIELD_TYPE } from '../../../../../common/constants';
|
||||
|
||||
function filterGeoField({ type }) {
|
||||
return ['geo_point'].includes(type);
|
||||
return [ES_GEO_FIELD_TYPE.GEO_POINT].includes(type);
|
||||
}
|
||||
|
||||
const requestTypeOptions = [
|
||||
|
@ -206,7 +207,7 @@ export class CreateSourceEditor extends Component {
|
|||
placeholder={i18n.translate('xpack.maps.source.esGeoGrid.indexPatternPlaceholder', {
|
||||
defaultMessage: 'Select index pattern'
|
||||
})}
|
||||
fieldTypes={['geo_point']}
|
||||
fieldTypes={[ES_GEO_FIELD_TYPE.GEO_POINT]}
|
||||
onNoIndexPatterns={this._onNoIndexPatterns}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
|
|
|
@ -176,9 +176,7 @@ export class ESGeoGridSource extends AbstractESSource {
|
|||
}
|
||||
|
||||
async getGeoJsonWithMeta(layerName, searchFilters) {
|
||||
|
||||
const featureCollection = await this.getGeoJsonPoints(layerName, searchFilters);
|
||||
|
||||
return {
|
||||
data: featureCollection,
|
||||
meta: {
|
||||
|
|
|
@ -16,11 +16,11 @@ import { NoIndexPatternCallout } from '../../../components/no_index_pattern_call
|
|||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { kfetch } from 'ui/kfetch';
|
||||
import { GIS_API_PATH } from '../../../../../common/constants';
|
||||
import { ES_GEO_FIELD_TYPE, GIS_API_PATH } from '../../../../../common/constants';
|
||||
import { DEFAULT_ES_DOC_LIMIT, DEFAULT_FILTER_BY_MAP_BOUNDS } from './constants';
|
||||
|
||||
function filterGeoField(field) {
|
||||
return ['geo_point', 'geo_shape'].includes(field.type);
|
||||
return [ES_GEO_FIELD_TYPE.GEO_POINT, ES_GEO_FIELD_TYPE.GEO_SHAPE].includes(field.type);
|
||||
}
|
||||
const RESET_INDEX_PATTERN_STATE = {
|
||||
indexPattern: undefined,
|
||||
|
@ -252,7 +252,7 @@ export class CreateSourceEditor extends Component {
|
|||
placeholder={i18n.translate('xpack.maps.source.esSearch.selectIndexPatternPlaceholder', {
|
||||
defaultMessage: 'Select index pattern'
|
||||
})}
|
||||
fieldTypes={['geo_point', 'geo_shape']}
|
||||
fieldTypes={[ES_GEO_FIELD_TYPE.GEO_POINT, ES_GEO_FIELD_TYPE.GEO_SHAPE]}
|
||||
onNoIndexPatterns={this._onNoIndexPatterns}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
|
|
|
@ -19,6 +19,7 @@ import { ESAggMetricTooltipProperty } from '../tooltips/es_aggmetric_tooltip_pro
|
|||
|
||||
import uuid from 'uuid/v4';
|
||||
import { copyPersistentState } from '../../../store/util';
|
||||
import { ES_GEO_FIELD_TYPE } from '../../../../common/constants';
|
||||
|
||||
export class AbstractESSource extends AbstractVectorSource {
|
||||
|
||||
|
@ -245,7 +246,7 @@ export class AbstractESSource extends AbstractVectorSource {
|
|||
const geoField = await this._getGeoField();
|
||||
// geo_bounds aggregation only supports geo_point
|
||||
// there is currently no backend support for getting bounding box of geo_shape field
|
||||
return geoField.type !== 'geo_shape';
|
||||
return geoField.type !== ES_GEO_FIELD_TYPE.GEO_SHAPE;
|
||||
} catch (error) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -16,10 +16,6 @@ export class AbstractSource {
|
|||
throw new Error('Must implement Source.createDescriptor');
|
||||
}
|
||||
|
||||
static renderDropdownDisplayOption() {
|
||||
throw new Error('Must implement Source.renderDropdownDisplayOption');
|
||||
}
|
||||
|
||||
constructor(descriptor, inspectorAdapters) {
|
||||
this._descriptor = descriptor;
|
||||
this._inspectorAdapters = inspectorAdapters;
|
||||
|
|
|
@ -38,6 +38,7 @@ import {
|
|||
REMOVE_TRACKED_LAYER_STATE,
|
||||
UPDATE_SOURCE_DATA_REQUEST,
|
||||
SET_TOOLTIP_STATE,
|
||||
UPDATE_DRAW_STATE,
|
||||
SET_SCROLL_ZOOM
|
||||
} from '../actions/store_actions';
|
||||
|
||||
|
@ -102,17 +103,26 @@ const INITIAL_STATE = {
|
|||
filters: [],
|
||||
refreshConfig: null,
|
||||
refreshTimerLastTriggeredAt: null,
|
||||
drawState: null
|
||||
},
|
||||
selectedLayerId: null,
|
||||
__transientLayerId: null,
|
||||
layerList: [],
|
||||
waitingForMapReadyLayerList: [],
|
||||
waitingForMapReadyLayerList: []
|
||||
};
|
||||
|
||||
|
||||
|
||||
export function map(state = INITIAL_STATE, action) {
|
||||
switch (action.type) {
|
||||
case UPDATE_DRAW_STATE:
|
||||
return {
|
||||
...state,
|
||||
mapState: {
|
||||
...state.mapState,
|
||||
drawState: action.drawState
|
||||
}
|
||||
};
|
||||
case REMOVE_TRACKED_LAYER_STATE:
|
||||
return removeTrackedLayerState(state, action.layerId);
|
||||
case TRACK_CURRENT_LAYER_STATE:
|
||||
|
|
186
yarn.lock
186
yarn.lock
|
@ -1938,23 +1938,76 @@
|
|||
dependencies:
|
||||
core-js "^2.5.7"
|
||||
|
||||
"@mapbox/geojson-area@0.2.2":
|
||||
"@mapbox/extent@0.4.0":
|
||||
version "0.4.0"
|
||||
resolved "https://registry.yarnpkg.com/@mapbox/extent/-/extent-0.4.0.tgz#3e591f32e1f0c3981c864239f7b0ac06e610f8a9"
|
||||
integrity sha1-PlkfMuHww5gchkI597CsBuYQ+Kk=
|
||||
|
||||
"@mapbox/geojson-area@0.2.2", "@mapbox/geojson-area@^0.2.1":
|
||||
version "0.2.2"
|
||||
resolved "https://registry.yarnpkg.com/@mapbox/geojson-area/-/geojson-area-0.2.2.tgz#18d7814aa36bf23fbbcc379f8e26a22927debf10"
|
||||
integrity sha1-GNeBSqNr8j+7zDefjiaiKSfevxA=
|
||||
dependencies:
|
||||
wgs84 "0.0.0"
|
||||
|
||||
"@mapbox/geojson-coords@0.0.0":
|
||||
version "0.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@mapbox/geojson-coords/-/geojson-coords-0.0.0.tgz#4847a5b96059666e527a2139e75e35d84fd58f50"
|
||||
integrity sha1-SEeluWBZZm5SeiE551412E/Vj1A=
|
||||
dependencies:
|
||||
"@mapbox/geojson-normalize" "0.0.1"
|
||||
geojson-flatten "~0.2.1"
|
||||
|
||||
"@mapbox/geojson-extent@^0.3.2":
|
||||
version "0.3.2"
|
||||
resolved "https://registry.yarnpkg.com/@mapbox/geojson-extent/-/geojson-extent-0.3.2.tgz#a1bdb2015afd0e031c18c3f29f7eb229e4e1950f"
|
||||
integrity sha1-ob2yAVr9DgMcGMPyn36yKeThlQ8=
|
||||
dependencies:
|
||||
"@mapbox/extent" "0.4.0"
|
||||
"@mapbox/geojson-coords" "0.0.0"
|
||||
rw "~0.1.4"
|
||||
traverse "~0.6.6"
|
||||
|
||||
"@mapbox/geojson-normalize@0.0.1":
|
||||
version "0.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@mapbox/geojson-normalize/-/geojson-normalize-0.0.1.tgz#1da1e6b3a7add3ad29909b30f438f60581b7cd80"
|
||||
integrity sha1-HaHms6et060pkJsw9Dj2BYG3zYA=
|
||||
|
||||
"@mapbox/geojson-types@^1.0.2":
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@mapbox/geojson-types/-/geojson-types-1.0.2.tgz#9aecf642cb00eab1080a57c4f949a65b4a5846d6"
|
||||
integrity sha512-e9EBqHHv3EORHrSfbR9DqecPNn+AmuAoQxV6aL8Xu30bJMJR1o8PZLZzpk1Wq7/NfCbuhmakHTPYRhoqLsXRnw==
|
||||
|
||||
"@mapbox/geojsonhint@^2.0.0":
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@mapbox/geojsonhint/-/geojsonhint-2.2.0.tgz#75ca94706e9a56e6debf4e1c78fabdc67978b883"
|
||||
integrity sha512-8qQYRB+/2z2JsN5s6D0WAnpo69+3V3nvJsSFLwMB1dsaWz1V4oZeuoje9srbYAxxL8PXCwIywfhYa3GxOkBv5Q==
|
||||
dependencies:
|
||||
concat-stream "^1.6.1"
|
||||
jsonlint-lines "1.7.1"
|
||||
minimist "1.2.0"
|
||||
vfile "^4.0.0"
|
||||
vfile-reporter "^5.1.1"
|
||||
|
||||
"@mapbox/jsonlint-lines-primitives@^2.0.2":
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@mapbox/jsonlint-lines-primitives/-/jsonlint-lines-primitives-2.0.2.tgz#ce56e539f83552b58d10d672ea4d6fc9adc7b234"
|
||||
integrity sha1-zlblOfg1UrWNENZy6k1vya3HsjQ=
|
||||
|
||||
"@mapbox/mapbox-gl-draw@^1.1.1":
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@mapbox/mapbox-gl-draw/-/mapbox-gl-draw-1.1.1.tgz#b88a7919c8de04eb7946885e747e22049c3a3138"
|
||||
integrity sha512-Xg+R0VUXKdXC7MaSSMiWfz96eLssJZa28/D6MxK/Xc19G5HvU6w/wytm8EeI28T7Sa2C7FII/0/XOwuAfJgDJw==
|
||||
dependencies:
|
||||
"@mapbox/geojson-area" "^0.2.1"
|
||||
"@mapbox/geojson-extent" "^0.3.2"
|
||||
"@mapbox/geojson-normalize" "0.0.1"
|
||||
"@mapbox/geojsonhint" "^2.0.0"
|
||||
"@mapbox/point-geometry" "0.1.0"
|
||||
hat "0.0.3"
|
||||
lodash.isequal "^4.2.0"
|
||||
xtend "^4.0.1"
|
||||
|
||||
"@mapbox/mapbox-gl-supported@^1.4.0":
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/@mapbox/mapbox-gl-supported/-/mapbox-gl-supported-1.4.0.tgz#36946b22944fe2cfa43cfafd5ef36fdb54a069e4"
|
||||
|
@ -3739,7 +3792,7 @@
|
|||
resolved "https://registry.yarnpkg.com/@types/type-detect/-/type-detect-4.0.1.tgz#3b0f5ac82ea630090cbf57c57a1bf5a63a29b9b6"
|
||||
integrity sha512-0+S1S9Iq0oJ9w9IaBC5W/z1WsPNDUIAJG+THGmqR4vUAxUPCzIY+dApTvyGsaBUWjafTDL0Dg8Z9+iRuk3/BQA==
|
||||
|
||||
"@types/unist@*", "@types/unist@^2.0.0":
|
||||
"@types/unist@*", "@types/unist@^2.0.0", "@types/unist@^2.0.2":
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.3.tgz#9c088679876f374eb5983f150d4787aa6fb32d7e"
|
||||
integrity sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ==
|
||||
|
@ -4314,6 +4367,11 @@ JSONStream@1.1.1:
|
|||
jsonparse "^1.1.0"
|
||||
through ">=2.2.7 <3"
|
||||
|
||||
"JSV@>= 4.0.x":
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/JSV/-/JSV-4.0.2.tgz#d077f6825571f82132f9dffaed587b4029feff57"
|
||||
integrity sha1-0Hf2glVx+CEy+d/67Vh7QCn+/1c=
|
||||
|
||||
abab@^1.0.3, abab@^1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/abab/-/abab-1.0.4.tgz#5faad9c2c07f60dd76770f71cf025b62a63cfd4e"
|
||||
|
@ -4779,6 +4837,11 @@ ansi-styles@^3.1.0, ansi-styles@^3.2.0:
|
|||
dependencies:
|
||||
color-convert "^1.9.0"
|
||||
|
||||
ansi-styles@~1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-1.0.0.tgz#cb102df1c56f5123eab8b67cd7b98027a0279178"
|
||||
integrity sha1-yxAt8cVvUSPquLZ817mAJ6AnkXg=
|
||||
|
||||
ansi-wrap@0.1.0, ansi-wrap@^0.1.0:
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/ansi-wrap/-/ansi-wrap-0.1.0.tgz#a82250ddb0015e9a27ca82e82ea603bbfa45efaf"
|
||||
|
@ -7190,6 +7253,15 @@ chalk@^2.3.0:
|
|||
escape-string-regexp "^1.0.5"
|
||||
supports-color "^5.2.0"
|
||||
|
||||
chalk@~0.4.0:
|
||||
version "0.4.0"
|
||||
resolved "https://registry.yarnpkg.com/chalk/-/chalk-0.4.0.tgz#5199a3ddcd0c1efe23bc08c1b027b06176e0c64f"
|
||||
integrity sha1-UZmj3c0MHv4jvAjBsCewYXbgxk8=
|
||||
dependencies:
|
||||
ansi-styles "~1.0.0"
|
||||
has-color "~0.1.0"
|
||||
strip-ansi "~0.1.0"
|
||||
|
||||
chalk@~0.5.1:
|
||||
version "0.5.1"
|
||||
resolved "https://registry.yarnpkg.com/chalk/-/chalk-0.5.1.tgz#663b3a648b68b55d04690d49167aa837858f2174"
|
||||
|
@ -8006,7 +8078,7 @@ concat-stream@1.5.1:
|
|||
readable-stream "~2.0.0"
|
||||
typedarray "~0.0.5"
|
||||
|
||||
concat-stream@1.6.2, concat-stream@^1.4.6, concat-stream@^1.5.0:
|
||||
concat-stream@1.6.2, concat-stream@^1.4.6, concat-stream@^1.5.0, concat-stream@^1.6.1:
|
||||
version "1.6.2"
|
||||
resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34"
|
||||
integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==
|
||||
|
@ -12235,6 +12307,14 @@ geojson-area@^0.2.1:
|
|||
dependencies:
|
||||
wgs84 "0.0.0"
|
||||
|
||||
geojson-flatten@~0.2.1:
|
||||
version "0.2.4"
|
||||
resolved "https://registry.yarnpkg.com/geojson-flatten/-/geojson-flatten-0.2.4.tgz#8f3396f31a0f5b747e39c9e6a14088f43ba4ecfb"
|
||||
integrity sha512-LiX6Jmot8adiIdZ/fthbcKKPOfWjTQchX/ggHnwMZ2e4b0I243N1ANUos0LvnzepTEsj0+D4fIJ5bKhBrWnAHA==
|
||||
dependencies:
|
||||
get-stdin "^6.0.0"
|
||||
minimist "1.2.0"
|
||||
|
||||
geojson-normalize@0.0.0:
|
||||
version "0.0.0"
|
||||
resolved "https://registry.yarnpkg.com/geojson-normalize/-/geojson-normalize-0.0.0.tgz#2dbc3678cd1b31b8179e876bda70cd120dde35c0"
|
||||
|
@ -13501,6 +13581,11 @@ has-binary2@~1.0.2:
|
|||
dependencies:
|
||||
isarray "2.0.1"
|
||||
|
||||
has-color@~0.1.0:
|
||||
version "0.1.7"
|
||||
resolved "https://registry.yarnpkg.com/has-color/-/has-color-0.1.7.tgz#67144a5260c34fc3cca677d041daf52fe7b78b2f"
|
||||
integrity sha1-ZxRKUmDDT8PMpnfQQdr1L+e3iy8=
|
||||
|
||||
has-cors@1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/has-cors/-/has-cors-1.1.0.tgz#5e474793f7ea9843d1bb99c23eef49ff126fff39"
|
||||
|
@ -13644,6 +13729,11 @@ hastscript@^5.0.0:
|
|||
property-information "^5.0.1"
|
||||
space-separated-tokens "^1.0.0"
|
||||
|
||||
hat@0.0.3:
|
||||
version "0.0.3"
|
||||
resolved "https://registry.yarnpkg.com/hat/-/hat-0.0.3.tgz#bb014a9e64b3788aed8005917413d4ff3d502d8a"
|
||||
integrity sha1-uwFKnmSzeIrtgAWRdBPU/z1QLYo=
|
||||
|
||||
hawk@~3.1.3:
|
||||
version "3.1.3"
|
||||
resolved "https://registry.yarnpkg.com/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4"
|
||||
|
@ -16205,6 +16295,14 @@ jsonify@~0.0.0:
|
|||
resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73"
|
||||
integrity sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=
|
||||
|
||||
jsonlint-lines@1.7.1:
|
||||
version "1.7.1"
|
||||
resolved "https://registry.yarnpkg.com/jsonlint-lines/-/jsonlint-lines-1.7.1.tgz#507de680d3fb8c4be1641cc57d6f679f29f178ff"
|
||||
integrity sha1-UH3mgNP7jEvhZBzFfW9nnynxeP8=
|
||||
dependencies:
|
||||
JSV ">= 4.0.x"
|
||||
nomnom ">= 1.5.x"
|
||||
|
||||
jsonparse@^1.1.0:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280"
|
||||
|
@ -17058,7 +17156,7 @@ lodash.isempty@^4.4.0:
|
|||
resolved "https://registry.yarnpkg.com/lodash.isempty/-/lodash.isempty-4.4.0.tgz#6f86cbedd8be4ec987be9aaf33c9684db1b31e7e"
|
||||
integrity sha1-b4bL7di+TsmHvpqvM8loTbGzHn4=
|
||||
|
||||
lodash.isequal@^4.0.0, lodash.isequal@^4.1.1, lodash.isequal@^4.5.0:
|
||||
lodash.isequal@^4.0.0, lodash.isequal@^4.1.1, lodash.isequal@^4.2.0, lodash.isequal@^4.5.0:
|
||||
version "4.5.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"
|
||||
integrity sha1-QVxEePK8wwEgwizhDtMib30+GOA=
|
||||
|
@ -17571,6 +17669,11 @@ map-visit@^1.0.0:
|
|||
dependencies:
|
||||
object-visit "^1.0.0"
|
||||
|
||||
mapbox-gl-draw-rectangle-mode@^1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/mapbox-gl-draw-rectangle-mode/-/mapbox-gl-draw-rectangle-mode-1.0.4.tgz#42987d68872a5fb5cc5d76d3375ee20cd8bab8f7"
|
||||
integrity sha512-BdF6nwEK2p8n9LQoMPzBO8LhddW1fe+d5vK8HQIei+4VcRnUbKNsEj7Z15FsJxCHzsc2BQKXbESx5GaE8x0imQ==
|
||||
|
||||
mapbox-gl@0.52.0:
|
||||
version "0.52.0"
|
||||
resolved "https://registry.yarnpkg.com/mapbox-gl/-/mapbox-gl-0.52.0.tgz#a43b61caa339ae28e43c87ecfbe9ce4032795859"
|
||||
|
@ -18772,6 +18875,14 @@ nodemailer@^4.6.4:
|
|||
resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-4.6.4.tgz#f0d72d0c6a6ec5f4369fa8f4bf5127a31baa2014"
|
||||
integrity sha512-SD4uuX7NMzZ5f5m1XHDd13J4UC3SmdJk8DsmU1g6Nrs5h3x9LcXr6EBPZIqXRJ3LrF7RdklzGhZRF/TuylTcLg==
|
||||
|
||||
"nomnom@>= 1.5.x":
|
||||
version "1.8.1"
|
||||
resolved "https://registry.yarnpkg.com/nomnom/-/nomnom-1.8.1.tgz#2151f722472ba79e50a76fc125bb8c8f2e4dc2a7"
|
||||
integrity sha1-IVH3Ikcrp55Qp2/BJbuMjy5Nwqc=
|
||||
dependencies:
|
||||
chalk "~0.4.0"
|
||||
underscore "~1.6.0"
|
||||
|
||||
"nopt@2 || 3", nopt@3.x, nopt@~3.0.6:
|
||||
version "3.0.6"
|
||||
resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9"
|
||||
|
@ -22494,7 +22605,7 @@ repeat-string@^0.2.2:
|
|||
resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-0.2.2.tgz#c7a8d3236068362059a7e4651fc6884e8b1fb4ae"
|
||||
integrity sha1-x6jTI2BoNiBZp+RlH8aITosftK4=
|
||||
|
||||
repeat-string@^1.5.2, repeat-string@^1.5.4, repeat-string@^1.6.1:
|
||||
repeat-string@^1.5.0, repeat-string@^1.5.2, repeat-string@^1.5.4, repeat-string@^1.6.1:
|
||||
version "1.6.1"
|
||||
resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637"
|
||||
integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc=
|
||||
|
@ -22979,6 +23090,11 @@ rw@1, rw@^1.3.3:
|
|||
resolved "https://registry.yarnpkg.com/rw/-/rw-1.3.3.tgz#3f862dfa91ab766b14885ef4d01124bfda074fb4"
|
||||
integrity sha1-P4Yt+pGrdmsUiF700BEkv9oHT7Q=
|
||||
|
||||
rw@~0.1.4:
|
||||
version "0.1.4"
|
||||
resolved "https://registry.yarnpkg.com/rw/-/rw-0.1.4.tgz#4903cbd80248ae0ede685bf58fd236a7a9b29a3e"
|
||||
integrity sha1-SQPL2AJIrg7eaFv1j9I2p6mymj4=
|
||||
|
||||
rx-lite-aggregates@^4.0.8:
|
||||
version "4.0.8"
|
||||
resolved "https://registry.yarnpkg.com/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz#753b87a89a11c95467c4ac1626c4efc4e05c67be"
|
||||
|
@ -24424,6 +24540,11 @@ strip-ansi@^5.2.0:
|
|||
dependencies:
|
||||
ansi-regex "^4.1.0"
|
||||
|
||||
strip-ansi@~0.1.0:
|
||||
version "0.1.1"
|
||||
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-0.1.1.tgz#39e8a98d044d150660abe4a6808acf70bb7bc991"
|
||||
integrity sha1-OeipjQRNFQZgq+SmgIrPcLt7yZE=
|
||||
|
||||
strip-bom-stream@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/strip-bom-stream/-/strip-bom-stream-2.0.0.tgz#f87db5ef2613f6968aa545abfe1ec728b6a829ca"
|
||||
|
@ -25406,7 +25527,7 @@ tr46@^1.0.0, tr46@^1.0.1:
|
|||
dependencies:
|
||||
punycode "^2.1.0"
|
||||
|
||||
traverse@0.6.6:
|
||||
traverse@0.6.6, traverse@~0.6.6:
|
||||
version "0.6.6"
|
||||
resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.6.6.tgz#cbdf560fd7b9af632502fed40f918c157ea97137"
|
||||
integrity sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc=
|
||||
|
@ -26152,6 +26273,11 @@ underscore.string@~3.3.4:
|
|||
sprintf-js "^1.0.3"
|
||||
util-deprecate "^1.0.2"
|
||||
|
||||
underscore@~1.6.0:
|
||||
version "1.6.0"
|
||||
resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.6.0.tgz#8b38b10cacdef63337b8b24e4ff86d45aea529a8"
|
||||
integrity sha1-izixDKze9jM3uLJOT/htRa6lKag=
|
||||
|
||||
underscore@~1.7.0:
|
||||
version "1.7.0"
|
||||
resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.7.0.tgz#6bbaf0877500d36be34ecaa584e0db9fef035209"
|
||||
|
@ -26307,6 +26433,13 @@ unist-util-stringify-position@^1.0.0, unist-util-stringify-position@^1.1.1:
|
|||
resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-1.1.1.tgz#3ccbdc53679eed6ecf3777dd7f5e3229c1b6aa3c"
|
||||
integrity sha1-PMvcU2ee7W7PN3fdf14yKcG2qjw=
|
||||
|
||||
unist-util-stringify-position@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-2.0.0.tgz#4c452c0dbcbc509f7bcd366e9a8afd646f9d51ae"
|
||||
integrity sha512-Uz5negUTrf9zm2ZT2Z9kdOL7Mr7FJLyq3ByqagUi7QZRVK1HnspVazvSqwHt73jj7APHtpuJ4K110Jm8O6/elw==
|
||||
dependencies:
|
||||
"@types/unist" "^2.0.2"
|
||||
|
||||
unist-util-visit-parents@1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-1.1.2.tgz#f6e3afee8bdbf961c0e6f028ea3c0480028c3d06"
|
||||
|
@ -26963,6 +27096,36 @@ vfile-message@^1.0.0:
|
|||
dependencies:
|
||||
unist-util-stringify-position "^1.1.1"
|
||||
|
||||
vfile-message@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-2.0.0.tgz#750bbb86fe545988a67e899b329bbcabb73edef6"
|
||||
integrity sha512-YS6qg6UpBfIeiO+6XlhPOuJaoLvt1Y9g2cmlwqhBOOU0XRV8j5RLeoz72t6PWLvNXq3EBG1fQ05wNPrUoz0deQ==
|
||||
dependencies:
|
||||
"@types/unist" "^2.0.2"
|
||||
unist-util-stringify-position "^1.1.1"
|
||||
|
||||
vfile-reporter@^5.1.1:
|
||||
version "5.1.1"
|
||||
resolved "https://registry.yarnpkg.com/vfile-reporter/-/vfile-reporter-5.1.1.tgz#419688c7e9dcaf65ba81bfdb0ad443e9e0248e09"
|
||||
integrity sha512-A/cfKvfVmeEmAKx1yyOWggCjC/k184Vkl5pVJAw5CEdppHd5FHBVcdyJ1JBSqIdJjJqyhZY4ZD3JycHr/uwmlA==
|
||||
dependencies:
|
||||
repeat-string "^1.5.0"
|
||||
string-width "^2.0.0"
|
||||
supports-color "^5.4.0"
|
||||
unist-util-stringify-position "^1.0.0"
|
||||
vfile-sort "^2.1.2"
|
||||
vfile-statistics "^1.1.0"
|
||||
|
||||
vfile-sort@^2.1.2:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/vfile-sort/-/vfile-sort-2.2.0.tgz#383a8727ec4c5daf37c05683684a5eb686366d39"
|
||||
integrity sha512-RgxLXVWrJBWb2GuP8FsSkqK7HmbjXjnI8qx3nD6NTWhsWaelaKvJuxfh1F1d1lkCPD7imo4zzi8cf6IOMgaTnQ==
|
||||
|
||||
vfile-statistics@^1.1.0:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/vfile-statistics/-/vfile-statistics-1.1.2.tgz#c50132627e4669a3afa07c64ff1e7aa7695e8151"
|
||||
integrity sha512-16wAC9eEGXdsD35LX9m/iXCRIZyX5LIrDgDtAF92rbATSqsBRbC4n05e0Rj5vt3XRpcKu0UJeWnTxWsSyvNZ+w==
|
||||
|
||||
vfile@^2.0.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/vfile/-/vfile-2.3.0.tgz#e62d8e72b20e83c324bc6c67278ee272488bf84a"
|
||||
|
@ -26983,6 +27146,17 @@ vfile@^3.0.0, vfile@^3.0.1:
|
|||
unist-util-stringify-position "^1.0.0"
|
||||
vfile-message "^1.0.0"
|
||||
|
||||
vfile@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/vfile/-/vfile-4.0.0.tgz#ebf3b48af9fcde524d5e08d5f75812058a5f78ad"
|
||||
integrity sha512-WMNeHy5djSl895BqE86D7WqA0Ie5fAIeGCa7V1EqiXyJg5LaGch2SUaZueok5abYQGH6mXEAsZ45jkoILIOlyA==
|
||||
dependencies:
|
||||
"@types/unist" "^2.0.2"
|
||||
is-buffer "^2.0.0"
|
||||
replace-ext "1.0.0"
|
||||
unist-util-stringify-position "^2.0.0"
|
||||
vfile-message "^2.0.0"
|
||||
|
||||
vinyl-file@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/vinyl-file/-/vinyl-file-2.0.0.tgz#a7ebf5ffbefda1b7d18d140fcb07b223efb6751a"
|
||||
|
|
Loading…
Reference in a new issue