mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
* show grab and edit buttons when hovering over layer name * display layer details when layer name is clicked * add range to dynamic style property state * render dynamic ranges in TOC details * render symbol size and border width header in legend * simplify VectorStyle.getIcon * removed unused component * open TOC details on map load * save open TOC details state in embeddable config * show gradients for dynmaic fill color icon * round corners of dynamic icon if points only * add tooltip to legend label * add edit panel action to action panel * add functional test for details in legend * fix broken gis_page function doesLayerExist * add unit tests for VectorStyle.getDescriptorWithDynamicRanges * open actions menu on layer title click, add arrow up/down for togging layer details * Design cleanup of layers panel (#31) * fix functional test * update jest snapshots * refactor StylePropertyLegendRow to use same function to render lineWidth and iconSize legends * fix functional test * fix another functional test * make escapeLayerName function instead of instance method * move _isLayerDetailsOpen into prop from redux connector * remove index.js file * do not show legend details toggle when layer has not legend details * rename FillableVector to FillableRectangle * use mixin pattern instead of encapulated function call
This commit is contained in:
parent
b9f826f011
commit
9801e5631e
39 changed files with 1124 additions and 401 deletions
|
@ -33,7 +33,8 @@ import {
|
|||
updateFlyout,
|
||||
FLYOUT_STATE,
|
||||
setReadOnly,
|
||||
setIsLayerTOCOpen
|
||||
setIsLayerTOCOpen,
|
||||
setOpenTOCDetails,
|
||||
} from '../store/ui';
|
||||
import { getQueryableUniqueIndexPatternIds } from '../selectors/map_selectors';
|
||||
import { getInspectorAdapters } from '../store/non_serializable_instances';
|
||||
|
@ -147,6 +148,7 @@ app.controller('GisMapController', ($scope, $route, config, kbnUrl, localStorage
|
|||
if (savedMap.uiStateJSON) {
|
||||
const uiState = JSON.parse(savedMap.uiStateJSON);
|
||||
store.dispatch(setIsLayerTOCOpen(_.get(uiState, 'isLayerTOCOpen', DEFAULT_IS_LAYER_TOC_OPEN)));
|
||||
store.dispatch(setOpenTOCDetails(_.get(uiState, 'openTOCDetails', [])));
|
||||
}
|
||||
|
||||
const layerList = getInitialLayers(savedMap.layerListJSON);
|
||||
|
|
|
@ -17,7 +17,7 @@ import {
|
|||
getRefreshConfig,
|
||||
getQuery,
|
||||
} from '../../selectors/map_selectors';
|
||||
import { getIsLayerTOCOpen } from '../../store/ui';
|
||||
import { getIsLayerTOCOpen, getOpenTOCDetails } from '../../store/ui';
|
||||
import { convertMapExtentToPolygon } from '../../elasticsearch_geo_utils';
|
||||
import { copyPersistentState } from '../../store/util';
|
||||
import { extractReferences, injectReferences } from '../../../common/migrations/references';
|
||||
|
@ -101,7 +101,8 @@ module.factory('SavedGisMap', function (Private) {
|
|||
});
|
||||
|
||||
this.uiStateJSON = JSON.stringify({
|
||||
isLayerTOCOpen: getIsLayerTOCOpen(state)
|
||||
isLayerTOCOpen: getIsLayerTOCOpen(state),
|
||||
openTOCDetails: getOpenTOCDetails(state),
|
||||
});
|
||||
|
||||
this.bounds = convertMapExtentToPolygon(getMapExtent(state));
|
||||
|
|
|
@ -13,9 +13,12 @@
|
|||
pointer-events: none; /* 1 */
|
||||
}
|
||||
|
||||
.mapWidgetOverlay__rightSideWrapper {
|
||||
overflow: hidden; // Fixes Chrome overflow
|
||||
}
|
||||
|
||||
.mapWidgetOverlay__rightSide {
|
||||
min-width: 19rem;
|
||||
max-width: 24rem;
|
||||
width: $euiSize * 20;
|
||||
}
|
||||
|
||||
.mapWidgetOverlay__layerWrapper {
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
@include euiScrollBar;
|
||||
overflow-y: auto;
|
||||
flex-basis: auto !important; // Fixes IE and ensures the layer items are visible
|
||||
padding-bottom: $euiSizeS + 1px;
|
||||
border-top: 1px solid $euiColorLightestShade;
|
||||
}
|
||||
|
||||
.mapLayerControl__addLayerButton,
|
||||
|
@ -18,5 +20,5 @@
|
|||
.mapLayerControl__openLayerTOCButton,
|
||||
.mapLayerControl__closeLayerTOCButton {
|
||||
@include size($euiSizeXL);
|
||||
background-color: $euiColorEmptyShade;
|
||||
background-color: $euiColorEmptyShade !important; // During all states
|
||||
}
|
||||
|
|
|
@ -11,24 +11,7 @@ exports[`LayerTOC is rendered 1`] = `
|
|||
droppableId="mapLayerTOC"
|
||||
spacing="none"
|
||||
>
|
||||
<EuiDraggable
|
||||
customDragHandle={true}
|
||||
draggableId="2"
|
||||
index={0}
|
||||
key="2"
|
||||
spacing="none"
|
||||
>
|
||||
<Component />
|
||||
</EuiDraggable>
|
||||
<EuiDraggable
|
||||
customDragHandle={true}
|
||||
draggableId="1"
|
||||
index={1}
|
||||
key="1"
|
||||
spacing="none"
|
||||
>
|
||||
<Component />
|
||||
</EuiDraggable>
|
||||
<Component />
|
||||
</EuiDroppable>
|
||||
</EuiDragDropContext>
|
||||
</div>
|
||||
|
|
|
@ -6,70 +6,68 @@ exports[`TOCEntry is rendered 1`] = `
|
|||
data-layerid="1"
|
||||
id="1"
|
||||
>
|
||||
<EuiFlexGroup
|
||||
alignItems="center"
|
||||
<div
|
||||
className="mapTocEntry-visible"
|
||||
gutterSize="none"
|
||||
responsive={false}
|
||||
>
|
||||
<EuiFlexItem
|
||||
grow={false}
|
||||
>
|
||||
<LayerTocActions
|
||||
cloneLayer={[Function]}
|
||||
displayName="layer 1"
|
||||
fitToBounds={[Function]}
|
||||
layer={
|
||||
Object {
|
||||
"getDisplayName": [Function],
|
||||
"getId": [Function],
|
||||
"getTOCDetails": [Function],
|
||||
"hasErrors": [Function],
|
||||
"isVisible": [Function],
|
||||
"showAtZoomLevel": [Function],
|
||||
}
|
||||
<LayerTocActions
|
||||
cloneLayer={[Function]}
|
||||
displayName="layer 1"
|
||||
editLayer={[Function]}
|
||||
escapedDisplayName="layer_1"
|
||||
fitToBounds={[Function]}
|
||||
layer={
|
||||
Object {
|
||||
"getDisplayName": [Function],
|
||||
"getId": [Function],
|
||||
"getLegendDetails": [Function],
|
||||
"hasErrors": [Function],
|
||||
"hasLegendDetails": [Function],
|
||||
"isVisible": [Function],
|
||||
"showAtZoomLevel": [Function],
|
||||
}
|
||||
toggleVisible={[Function]}
|
||||
zoom={0}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiLink
|
||||
color="text"
|
||||
data-test-subj="mapOpenLayerButtonlayer_1"
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
className="eui-textTruncate eui-textLeft"
|
||||
style={
|
||||
Object {
|
||||
"width": 180,
|
||||
}
|
||||
}
|
||||
>
|
||||
layer 1
|
||||
</div>
|
||||
</EuiLink>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem
|
||||
grow={false}
|
||||
}
|
||||
toggleVisible={[Function]}
|
||||
zoom={0}
|
||||
/>
|
||||
<div
|
||||
className="mapTocEntry__layerIcons"
|
||||
>
|
||||
<span
|
||||
<EuiButtonIcon
|
||||
aria-label="Edit layer"
|
||||
color="primary"
|
||||
iconSize="m"
|
||||
iconType="pencil"
|
||||
onClick={[Function]}
|
||||
title="Edit layer"
|
||||
type="button"
|
||||
/>
|
||||
<EuiButtonIcon
|
||||
aria-label="Reorder layer"
|
||||
className="mapTocEntry__grab"
|
||||
>
|
||||
<EuiIcon
|
||||
type="grab"
|
||||
/>
|
||||
</span>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
<EuiSpacer
|
||||
size="s"
|
||||
/>
|
||||
<div>
|
||||
TOC details mock
|
||||
color="subdued"
|
||||
iconSize="m"
|
||||
iconType="grab"
|
||||
title="Reorder layer"
|
||||
type="button"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<span
|
||||
className="mapTocEntry__detailsToggle"
|
||||
>
|
||||
<button
|
||||
aria-label="Show layer details"
|
||||
className="mapTocEntry__detailsToggleButton"
|
||||
onClick={[Function]}
|
||||
title="Show layer details"
|
||||
>
|
||||
<EuiIcon
|
||||
className="eui-alignBaseline"
|
||||
size="s"
|
||||
type="arrowDown"
|
||||
/>
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
`;
|
||||
|
||||
|
@ -79,54 +77,125 @@ exports[`TOCEntry props isReadOnly 1`] = `
|
|||
data-layerid="1"
|
||||
id="1"
|
||||
>
|
||||
<EuiFlexGroup
|
||||
alignItems="center"
|
||||
<div
|
||||
className="mapTocEntry-visible"
|
||||
gutterSize="none"
|
||||
responsive={false}
|
||||
>
|
||||
<EuiFlexItem
|
||||
grow={false}
|
||||
>
|
||||
<LayerTocActions
|
||||
cloneLayer={[Function]}
|
||||
displayName="layer 1"
|
||||
fitToBounds={[Function]}
|
||||
isReadOnly={true}
|
||||
layer={
|
||||
Object {
|
||||
"getDisplayName": [Function],
|
||||
"getId": [Function],
|
||||
"getTOCDetails": [Function],
|
||||
"hasErrors": [Function],
|
||||
"isVisible": [Function],
|
||||
"showAtZoomLevel": [Function],
|
||||
}
|
||||
<LayerTocActions
|
||||
cloneLayer={[Function]}
|
||||
displayName="layer 1"
|
||||
editLayer={[Function]}
|
||||
escapedDisplayName="layer_1"
|
||||
fitToBounds={[Function]}
|
||||
isReadOnly={true}
|
||||
layer={
|
||||
Object {
|
||||
"getDisplayName": [Function],
|
||||
"getId": [Function],
|
||||
"getLegendDetails": [Function],
|
||||
"hasErrors": [Function],
|
||||
"hasLegendDetails": [Function],
|
||||
"isVisible": [Function],
|
||||
"showAtZoomLevel": [Function],
|
||||
}
|
||||
toggleVisible={[Function]}
|
||||
zoom={0}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiText>
|
||||
<div
|
||||
className="eui-textTruncate eui-textLeft"
|
||||
style={
|
||||
Object {
|
||||
"width": 180,
|
||||
}
|
||||
}
|
||||
>
|
||||
layer 1
|
||||
</div>
|
||||
</EuiText>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
<EuiSpacer
|
||||
size="s"
|
||||
/>
|
||||
<div>
|
||||
TOC details mock
|
||||
}
|
||||
toggleVisible={[Function]}
|
||||
zoom={0}
|
||||
/>
|
||||
</div>
|
||||
<span
|
||||
className="mapTocEntry__detailsToggle"
|
||||
>
|
||||
<button
|
||||
aria-label="Show layer details"
|
||||
className="mapTocEntry__detailsToggleButton"
|
||||
onClick={[Function]}
|
||||
title="Show layer details"
|
||||
>
|
||||
<EuiIcon
|
||||
className="eui-alignBaseline"
|
||||
size="s"
|
||||
type="arrowDown"
|
||||
/>
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`TOCEntry props should display layer details when isLegendDetailsOpen is true 1`] = `
|
||||
<div
|
||||
className="mapTocEntry"
|
||||
data-layerid="1"
|
||||
id="1"
|
||||
>
|
||||
<div
|
||||
className="mapTocEntry-visible"
|
||||
>
|
||||
<LayerTocActions
|
||||
cloneLayer={[Function]}
|
||||
displayName="layer 1"
|
||||
editLayer={[Function]}
|
||||
escapedDisplayName="layer_1"
|
||||
fitToBounds={[Function]}
|
||||
layer={
|
||||
Object {
|
||||
"getDisplayName": [Function],
|
||||
"getId": [Function],
|
||||
"getLegendDetails": [Function],
|
||||
"hasErrors": [Function],
|
||||
"hasLegendDetails": [Function],
|
||||
"isVisible": [Function],
|
||||
"showAtZoomLevel": [Function],
|
||||
}
|
||||
}
|
||||
toggleVisible={[Function]}
|
||||
zoom={0}
|
||||
/>
|
||||
<div
|
||||
className="mapTocEntry__layerIcons"
|
||||
>
|
||||
<EuiButtonIcon
|
||||
aria-label="Edit layer"
|
||||
color="primary"
|
||||
iconSize="m"
|
||||
iconType="pencil"
|
||||
onClick={[Function]}
|
||||
title="Edit layer"
|
||||
type="button"
|
||||
/>
|
||||
<EuiButtonIcon
|
||||
aria-label="Reorder layer"
|
||||
className="mapTocEntry__grab"
|
||||
color="subdued"
|
||||
iconSize="m"
|
||||
iconType="grab"
|
||||
title="Reorder layer"
|
||||
type="button"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="mapTocEntry__layerDetails"
|
||||
data-test-subj="mapLayerTOCDetailslayer_1"
|
||||
>
|
||||
<div>
|
||||
TOC details mock
|
||||
</div>
|
||||
</div>
|
||||
<span
|
||||
className="mapTocEntry__detailsToggle"
|
||||
>
|
||||
<button
|
||||
aria-label="Hide layer details"
|
||||
className="mapTocEntry__detailsToggleButton"
|
||||
onClick={[Function]}
|
||||
title="Hide layer details"
|
||||
>
|
||||
<EuiIcon
|
||||
className="eui-alignBaseline"
|
||||
size="s"
|
||||
type="arrowUp"
|
||||
/>
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
`;
|
||||
|
|
|
@ -1,22 +1,121 @@
|
|||
/**
|
||||
* 1. Truncate the layer name
|
||||
* 2. For showing the layer details toggle above the following entry
|
||||
*/
|
||||
|
||||
.mapTocEntry {
|
||||
padding: $euiSizeS $euiSize;
|
||||
position: relative;
|
||||
padding: $euiSizeS;
|
||||
border-bottom: 1px solid $euiColorLightestShade;
|
||||
|
||||
&:hover,
|
||||
&:focus,
|
||||
&:focus-within {
|
||||
z-index: 2; /* 2 */
|
||||
|
||||
.mapTocEntry__layerIcons,
|
||||
.mapTocEntry__detailsToggle {
|
||||
display: block;
|
||||
animation: mapTocEntryBecomeVisible $euiAnimSpeedFast $euiAnimSlightResistance;
|
||||
}
|
||||
}
|
||||
|
||||
.mapTocEntry__layerIcons,
|
||||
.mapTocEntry__detailsToggle {
|
||||
&:hover,
|
||||
&:focus {
|
||||
display: block;
|
||||
animation: mapTocEntryBecomeVisible $euiAnimSpeedFast $euiAnimSlightResistance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.mapTocEntry-isDragging {
|
||||
@include euiBottomShadowMedium;
|
||||
}
|
||||
|
||||
.mapTocEntry-isDraggingOver {
|
||||
background-color: $euiColorEmptyShade;
|
||||
// Don't allow interaction events while layer is being re-ordered
|
||||
pointer-events: none !important;
|
||||
}
|
||||
|
||||
.mapTocEntry-visible {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.mapTocEntry-visible,
|
||||
.mapTocEntry-notVisible {
|
||||
opacity: 0.5;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.mapTocEntry__grab {
|
||||
margin-left: $euiSizeXS;
|
||||
.mapLayTocActions {
|
||||
overflow: hidden; /* 1 */
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.mapLayTocActions__popoverAnchor {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.mapTocEntry-notVisible .mapTocEntry__layerName {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.mapTocEntry__grab:hover {
|
||||
cursor: grab;
|
||||
}
|
||||
|
||||
.mapTocEntry__layerName {
|
||||
font-weight: $euiFontWeightMedium;
|
||||
}
|
||||
|
||||
.mapTocEntry__layerNameText {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.mapTocEntry__layerNameIcon {
|
||||
flex-shrink: 0;
|
||||
margin-right: $euiSizeS;
|
||||
|
||||
> * {
|
||||
vertical-align: sub;
|
||||
}
|
||||
}
|
||||
|
||||
.mapTocEntry__layerIcons {
|
||||
flex-shrink: 0;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.mapTocEntry__detailsToggle {
|
||||
position: absolute;
|
||||
display: none;
|
||||
left: 50%;
|
||||
top: $euiSizeXL;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
|
||||
.mapTocEntry__detailsToggleButton {
|
||||
background-color: $euiColorEmptyShade;
|
||||
border: $euiBorderThin;
|
||||
color: $euiTextColor;
|
||||
border-radius: $euiBorderRadius / 2;
|
||||
height: $euiSize;
|
||||
width: $euiSizeXL;
|
||||
line-height: $euiSize;
|
||||
text-align: center;
|
||||
|
||||
&:focus {
|
||||
@include euiFocusRing;
|
||||
}
|
||||
}
|
||||
|
||||
.mapTocEntry__layerDetails {
|
||||
@include euiOverflowShadow(transparentize($euiShadowColor, .7));
|
||||
background-color: $euiPageBackgroundColor;
|
||||
padding: $euiSize $euiSizeS $euiSizeS;
|
||||
margin: $euiSizeS (-$euiSizeS) (-$euiSizeS);
|
||||
}
|
||||
|
||||
@keyframes mapTocEntryBecomeVisible {
|
||||
0% { opacity: 0; }
|
||||
100% { opacity: 1; }
|
||||
}
|
||||
|
|
|
@ -7,7 +7,14 @@
|
|||
import _ from 'lodash';
|
||||
import { connect } from 'react-redux';
|
||||
import { TOCEntry } from './view';
|
||||
import { getIsReadOnly, updateFlyout, FLYOUT_STATE } from '../../../../../store/ui';
|
||||
import {
|
||||
getIsReadOnly,
|
||||
updateFlyout,
|
||||
FLYOUT_STATE,
|
||||
getOpenTOCDetails,
|
||||
hideTOCDetails,
|
||||
showTOCDetails,
|
||||
} from '../../../../../store/ui';
|
||||
import {
|
||||
fitToLayerExtent,
|
||||
setSelectedLayer,
|
||||
|
@ -18,12 +25,13 @@ import {
|
|||
|
||||
import { hasDirtyState, getSelectedLayer } from '../../../../../selectors/map_selectors';
|
||||
|
||||
function mapStateToProps(state = {}) {
|
||||
function mapStateToProps(state = {}, ownProps) {
|
||||
return {
|
||||
isReadOnly: getIsReadOnly(state),
|
||||
zoom: _.get(state, 'map.mapState.zoom', 0),
|
||||
selectedLayer: getSelectedLayer(state),
|
||||
hasDirtyStateSelector: hasDirtyState(state),
|
||||
isLegendDetailsOpen: getOpenTOCDetails(state).includes(ownProps.layer.getId()),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -42,7 +50,13 @@ function mapDispatchToProps(dispatch) {
|
|||
},
|
||||
cloneLayer: layerId => {
|
||||
dispatch(cloneLayer(layerId));
|
||||
}
|
||||
},
|
||||
hideTOCDetails: layerId => {
|
||||
dispatch(hideTOCDetails(layerId));
|
||||
},
|
||||
showTOCDetails: layerId => {
|
||||
dispatch(showTOCDetails(layerId));
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -4,22 +4,27 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React, { Fragment } from 'react';
|
||||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
|
||||
import {
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiIcon,
|
||||
EuiSpacer,
|
||||
EuiOverlayMask,
|
||||
EuiModal,
|
||||
EuiModalBody,
|
||||
EuiModalFooter,
|
||||
EuiButton,
|
||||
EuiButtonEmpty,
|
||||
EuiLink,
|
||||
EuiText,
|
||||
EuiButtonIcon,
|
||||
} from '@elastic/eui';
|
||||
import { LayerTocActions } from '../../../../../shared/components/layer_toc_actions';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
function escapeLayerName(name) {
|
||||
return name
|
||||
? name.split(' ').join('_')
|
||||
: '';
|
||||
}
|
||||
|
||||
export class TOCEntry extends React.Component {
|
||||
|
||||
|
@ -37,6 +42,18 @@ export class TOCEntry extends React.Component {
|
|||
this._isMounted = false;
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
this._updateDisplayName();
|
||||
}
|
||||
|
||||
_toggleLayerDetailsVisibility = () => {
|
||||
if (this.props.isLegendDetailsOpen) {
|
||||
this.props.hideTOCDetails(this.props.layer.getId());
|
||||
} else {
|
||||
this.props.showTOCDetails(this.props.layer.getId());
|
||||
}
|
||||
}
|
||||
|
||||
async _updateDisplayName() {
|
||||
const label = await this.props.layer.getDisplayName();
|
||||
if (this._isMounted) {
|
||||
|
@ -48,10 +65,6 @@ export class TOCEntry extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
this._updateDisplayName();
|
||||
}
|
||||
|
||||
_openLayerPanelWithCheck = () => {
|
||||
const { selectedLayer, hasDirtyStateSelector } = this.props;
|
||||
if (selectedLayer && selectedLayer.getId() === this.props.layer.getId()) {
|
||||
|
@ -112,33 +125,73 @@ export class TOCEntry extends React.Component {
|
|||
);
|
||||
}
|
||||
|
||||
_renderLayerName() {
|
||||
const displayName = (
|
||||
<div style={{ width: 180 }} className="eui-textTruncate eui-textLeft">
|
||||
{this.state.displayName}
|
||||
</div>
|
||||
);
|
||||
|
||||
_renderLayerIcons() {
|
||||
if (this.props.isReadOnly) {
|
||||
return (
|
||||
<EuiText>
|
||||
{displayName}
|
||||
</EuiText>
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<EuiLink
|
||||
color="text"
|
||||
onClick={this._openLayerPanelWithCheck}
|
||||
data-test-subj={
|
||||
`mapOpenLayerButton${this.state.displayName
|
||||
? this.state.displayName.replace(' ', '_')
|
||||
: ''}`
|
||||
}
|
||||
>
|
||||
{displayName}
|
||||
</EuiLink>
|
||||
<div className="mapTocEntry__layerIcons">
|
||||
|
||||
<EuiButtonIcon
|
||||
iconType="pencil"
|
||||
aria-label={i18n.translate('xpack.maps.layerControl.tocEntry.editButtonAriaLabel', {
|
||||
defaultMessage: 'Edit layer'
|
||||
})}
|
||||
title={i18n.translate('xpack.maps.layerControl.tocEntry.editButtonTitle', {
|
||||
defaultMessage: 'Edit layer'
|
||||
})}
|
||||
onClick={this._openLayerPanelWithCheck}
|
||||
/>
|
||||
|
||||
<EuiButtonIcon
|
||||
iconType="grab"
|
||||
color="subdued"
|
||||
title={i18n.translate('xpack.maps.layerControl.tocEntry.grabButtonTitle', {
|
||||
defaultMessage: 'Reorder layer'
|
||||
})}
|
||||
aria-label={i18n.translate('xpack.maps.layerControl.tocEntry.grabButtonAriaLabel', {
|
||||
defaultMessage: 'Reorder layer'
|
||||
})}
|
||||
className="mapTocEntry__grab"
|
||||
{...this.props.dragHandleProps}
|
||||
/>
|
||||
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
_renderDetailsToggle() {
|
||||
if (!this.props.layer.hasLegendDetails()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { isLegendDetailsOpen } = this.props;
|
||||
return (
|
||||
<span className="mapTocEntry__detailsToggle">
|
||||
<button
|
||||
className="mapTocEntry__detailsToggleButton"
|
||||
aria-label={isLegendDetailsOpen
|
||||
? i18n.translate('xpack.maps.layerControl.tocEntry.hideDetailsButtonAriaLabel', {
|
||||
defaultMessage: 'Hide layer details'
|
||||
})
|
||||
: i18n.translate('xpack.maps.layerControl.tocEntry.showDetailsButtonAriaLabel', {
|
||||
defaultMessage: 'Show layer details'
|
||||
})
|
||||
}
|
||||
title={isLegendDetailsOpen
|
||||
? i18n.translate('xpack.maps.layerControl.tocEntry.hideDetailsButtonTitle', {
|
||||
defaultMessage: 'Hide layer details'
|
||||
})
|
||||
: i18n.translate('xpack.maps.layerControl.tocEntry.showDetailsButtonTitle', {
|
||||
defaultMessage: 'Show layer details'
|
||||
})
|
||||
}
|
||||
onClick={this._toggleLayerDetailsVisibility}
|
||||
>
|
||||
<EuiIcon className="eui-alignBaseline" type={isLegendDetailsOpen ? 'arrowUp' : 'arrowDown'} size="s" />
|
||||
</button>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -152,78 +205,78 @@ export class TOCEntry extends React.Component {
|
|||
fitToBounds
|
||||
} = this.props;
|
||||
|
||||
let sortIcon;
|
||||
if (!isReadOnly) {
|
||||
sortIcon = (
|
||||
<EuiFlexItem grow={false}>
|
||||
<span className="mapTocEntry__grab" {...this.props.dragHandleProps}>
|
||||
<EuiIcon type="grab"/>
|
||||
</span>
|
||||
</EuiFlexItem>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<EuiFlexGroup
|
||||
gutterSize="none"
|
||||
alignItems="center"
|
||||
responsive={false}
|
||||
<div
|
||||
className={
|
||||
layer.isVisible() && layer.showAtZoomLevel(zoom)
|
||||
&& !layer.hasErrors() ? 'mapTocEntry-visible' : 'mapTocEntry-notVisible'
|
||||
}
|
||||
>
|
||||
<EuiFlexItem grow={false}>
|
||||
<LayerTocActions
|
||||
layer={layer}
|
||||
fitToBounds={() => {
|
||||
fitToBounds(layer.getId());
|
||||
}}
|
||||
zoom={zoom}
|
||||
toggleVisible={() => {
|
||||
toggleVisible(layer.getId());
|
||||
}}
|
||||
displayName={this.state.displayName}
|
||||
cloneLayer={() => {
|
||||
cloneLayer(layer.getId());
|
||||
}}
|
||||
isReadOnly={this.props.isReadOnly}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
{this._renderLayerName()}
|
||||
</EuiFlexItem>
|
||||
{sortIcon}
|
||||
</EuiFlexGroup>
|
||||
<LayerTocActions
|
||||
layer={layer}
|
||||
fitToBounds={() => {
|
||||
fitToBounds(layer.getId());
|
||||
}}
|
||||
zoom={zoom}
|
||||
toggleVisible={() => {
|
||||
toggleVisible(layer.getId());
|
||||
}}
|
||||
displayName={this.state.displayName}
|
||||
escapedDisplayName={escapeLayerName(this.state.displayName)}
|
||||
cloneLayer={() => {
|
||||
cloneLayer(layer.getId());
|
||||
}}
|
||||
editLayer={this._openLayerPanelWithCheck}
|
||||
isReadOnly={isReadOnly}
|
||||
/>
|
||||
|
||||
{this._renderLayerIcons()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
_renderLayerDetails() {
|
||||
const tocDetails = this.props.layer.getTOCDetails();
|
||||
_renderLegendDetails = () => {
|
||||
if (!this.props.isLegendDetailsOpen || !this.props.layer.hasLegendDetails()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const tocDetails = this.props.layer.getLegendDetails();
|
||||
if (!tocDetails) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<EuiSpacer size="s"/>
|
||||
<div
|
||||
className="mapTocEntry__layerDetails"
|
||||
data-test-subj={`mapLayerTOCDetails${escapeLayerName(this.state.displayName)}`}
|
||||
>
|
||||
{tocDetails}
|
||||
</Fragment>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const classes = classNames(
|
||||
'mapTocEntry',
|
||||
{
|
||||
'mapTocEntry-isDragging': this.props.isDragging,
|
||||
'mapTocEntry-isDraggingOver': this.props.isDraggingOver,
|
||||
},
|
||||
);
|
||||
|
||||
return (
|
||||
<div
|
||||
className="mapTocEntry"
|
||||
className={classes}
|
||||
id={this.props.layer.getId()}
|
||||
data-layerid={this.props.layer.getId()}
|
||||
>
|
||||
{this._renderCancelModal()}
|
||||
|
||||
{this._renderLayerHeader()}
|
||||
|
||||
{this._renderLayerDetails()}
|
||||
{this._renderLegendDetails()}
|
||||
|
||||
{this._renderDetailsToggle()}
|
||||
|
||||
{this._renderCancelModal()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -9,13 +9,16 @@ import { shallowWithIntl } from 'test_utils/enzyme_helpers';
|
|||
|
||||
import { TOCEntry } from './view';
|
||||
|
||||
const LAYER_ID = '1';
|
||||
|
||||
const mockLayer = {
|
||||
getId: () => { return '1'; },
|
||||
getTOCDetails: () => { return (<div>TOC details mock</div>); },
|
||||
getId: () => { return LAYER_ID; },
|
||||
getLegendDetails: () => { return (<div>TOC details mock</div>); },
|
||||
getDisplayName: () => { return 'layer 1'; },
|
||||
isVisible: () => { return true; },
|
||||
showAtZoomLevel: () => { return true; },
|
||||
hasErrors: () => { return false; },
|
||||
hasLegendDetails: () => { return true; },
|
||||
};
|
||||
|
||||
const defaultProps = {
|
||||
|
@ -26,6 +29,7 @@ const defaultProps = {
|
|||
getSelectedLayerSelector: () => {},
|
||||
hasDirtyStateSelector: () => {},
|
||||
zoom: 0,
|
||||
isLegendDetailsOpen: false,
|
||||
};
|
||||
|
||||
describe('TOCEntry', () => {
|
||||
|
@ -62,5 +66,22 @@ describe('TOCEntry', () => {
|
|||
expect(component)
|
||||
.toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('should display layer details when isLegendDetailsOpen is true', async () => {
|
||||
const component = shallowWithIntl(
|
||||
<TOCEntry
|
||||
{...defaultProps}
|
||||
isLegendDetailsOpen={true}
|
||||
/>
|
||||
);
|
||||
|
||||
// Ensure all promises resolve
|
||||
await new Promise(resolve => process.nextTick(resolve));
|
||||
// Ensure the state changes are reflected
|
||||
component.update();
|
||||
|
||||
expect(component)
|
||||
.toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -65,21 +65,30 @@ export class LayerTOC extends React.Component {
|
|||
});
|
||||
}
|
||||
|
||||
const draggableLayers = reverseLayerList.map((layer, idx) => (
|
||||
<EuiDraggable spacing="none" key={layer.getId()} index={idx} draggableId={layer.getId()} customDragHandle={true}>
|
||||
{(provided) => (
|
||||
<TOCEntry
|
||||
layer={layer}
|
||||
dragHandleProps={provided.dragHandleProps}
|
||||
/>
|
||||
)}
|
||||
</EuiDraggable>
|
||||
));
|
||||
|
||||
return (
|
||||
<EuiDragDropContext onDragEnd={this._onDragEnd}>
|
||||
<EuiDroppable droppableId="mapLayerTOC" spacing="none">
|
||||
{draggableLayers}
|
||||
{(provided, snapshot) => (
|
||||
reverseLayerList.map((layer, idx) => (
|
||||
<EuiDraggable
|
||||
spacing="none"
|
||||
key={layer.getId()}
|
||||
index={idx}
|
||||
draggableId={layer.getId()}
|
||||
customDragHandle={true}
|
||||
disableInteractiveElementBlocking // Allows button to be drag handle
|
||||
>
|
||||
{(provided, state) => (
|
||||
<TOCEntry
|
||||
layer={layer}
|
||||
dragHandleProps={provided.dragHandleProps}
|
||||
isDragging={state.isDragging}
|
||||
isDraggingOver={snapshot.isDraggingOver}
|
||||
/>
|
||||
)}
|
||||
</EuiDraggable>
|
||||
))
|
||||
)}
|
||||
</EuiDroppable>
|
||||
</EuiDragDropContext>
|
||||
);
|
||||
|
|
|
@ -16,7 +16,7 @@ import { AttributionControl } from './attribution_control';
|
|||
export function WidgetOverlay() {
|
||||
return (
|
||||
<EuiFlexGroup className="mapWidgetOverlay" responsive={false} direction="column" alignItems="flexEnd" gutterSize="s">
|
||||
<EuiFlexItem>
|
||||
<EuiFlexItem className="mapWidgetOverlay__rightSideWrapper">
|
||||
<EuiFlexGroup
|
||||
className="mapWidgetOverlay__rightSide"
|
||||
direction="column"
|
||||
|
|
|
@ -26,9 +26,11 @@ import {
|
|||
import {
|
||||
DEFAULT_IS_LAYER_TOC_OPEN,
|
||||
getIsLayerTOCOpen,
|
||||
getOpenTOCDetails,
|
||||
setReadOnly,
|
||||
setFilterable,
|
||||
setIsLayerTOCOpen
|
||||
setIsLayerTOCOpen,
|
||||
setOpenTOCDetails,
|
||||
} from '../store/ui';
|
||||
import { getInspectorAdapters } from '../store/non_serializable_instances';
|
||||
import { getMapCenter, getMapZoom } from '../selectors/map_selectors';
|
||||
|
@ -99,6 +101,13 @@ export class MapEmbeddable extends Embeddable {
|
|||
this._store.dispatch(setIsLayerTOCOpen(_.get(uiState, 'isLayerTOCOpen', DEFAULT_IS_LAYER_TOC_OPEN)));
|
||||
}
|
||||
|
||||
if (_.has(this._embeddableConfig, 'openTOCDetails')) {
|
||||
this._store.dispatch(setOpenTOCDetails(this._embeddableConfig.openTOCDetails));
|
||||
} else if (this._savedMap.uiStateJSON) {
|
||||
const uiState = JSON.parse(this._savedMap.uiStateJSON);
|
||||
this._store.dispatch(setOpenTOCDetails(_.get(uiState, 'openTOCDetails', [])));
|
||||
}
|
||||
|
||||
if (this._embeddableConfig.mapCenter) {
|
||||
this._store.dispatch(setGotoWithCenter({
|
||||
lat: this._embeddableConfig.mapCenter.lat,
|
||||
|
@ -168,12 +177,17 @@ export class MapEmbeddable extends Embeddable {
|
|||
}
|
||||
|
||||
const isLayerTOCOpen = getIsLayerTOCOpen(this._store.getState());
|
||||
if (!this._embeddableConfig.isLayerTOCOpen
|
||||
|| this._embeddableConfig.isLayerTOCOpen !== isLayerTOCOpen) {
|
||||
if (this._embeddableConfig.isLayerTOCOpen !== isLayerTOCOpen) {
|
||||
embeddableConfigChanged = true;
|
||||
this._embeddableConfig.isLayerTOCOpen = isLayerTOCOpen;
|
||||
}
|
||||
|
||||
const openTOCDetails = getOpenTOCDetails(this._store.getState());
|
||||
if (!_.isEqual(this._embeddableConfig.openTOCDetails, openTOCDetails)) {
|
||||
embeddableConfigChanged = true;
|
||||
this._embeddableConfig.openTOCDetails = openTOCDetails;
|
||||
}
|
||||
|
||||
if (embeddableConfigChanged) {
|
||||
this._onEmbeddableStateChanged({
|
||||
customization: this._embeddableConfig
|
||||
|
|
|
@ -2,9 +2,11 @@
|
|||
|
||||
exports[`LayerTocActions is rendered 1`] = `
|
||||
<EuiPopover
|
||||
anchorClassName="mapLayTocActions__popoverAnchor"
|
||||
anchorPosition="leftUp"
|
||||
button={
|
||||
<EuiButtonEmpty
|
||||
className="mapTocEntry__layerName eui-textLeft"
|
||||
color="text"
|
||||
data-test-subj="layerTocActionsPanelToggleButtonlayer1"
|
||||
flush="left"
|
||||
|
@ -13,11 +15,17 @@ exports[`LayerTocActions is rendered 1`] = `
|
|||
size="xs"
|
||||
type="button"
|
||||
>
|
||||
<div>
|
||||
icon mock
|
||||
</div>
|
||||
<span
|
||||
className="mapTocEntry__layerNameIcon"
|
||||
>
|
||||
<div>
|
||||
icon mock
|
||||
</div>
|
||||
</span>
|
||||
layer 1
|
||||
</EuiButtonEmpty>
|
||||
}
|
||||
className="mapLayTocActions"
|
||||
closePopover={[Function]}
|
||||
hasArrow={true}
|
||||
id="contextMenu"
|
||||
|
@ -54,6 +62,15 @@ exports[`LayerTocActions is rendered 1`] = `
|
|||
"name": "Hide layer",
|
||||
"onClick": [Function],
|
||||
},
|
||||
Object {
|
||||
"data-test-subj": "editLayerButton",
|
||||
"icon": <EuiIcon
|
||||
size="m"
|
||||
type="pencil"
|
||||
/>,
|
||||
"name": "Edit layer",
|
||||
"onClick": [Function],
|
||||
},
|
||||
Object {
|
||||
"data-test-subj": "cloneLayerButton",
|
||||
"icon": <EuiIcon
|
||||
|
@ -74,9 +91,11 @@ exports[`LayerTocActions is rendered 1`] = `
|
|||
|
||||
exports[`LayerTocActions should disable fit to data when supportsFitToBounds is false 1`] = `
|
||||
<EuiPopover
|
||||
anchorClassName="mapLayTocActions__popoverAnchor"
|
||||
anchorPosition="leftUp"
|
||||
button={
|
||||
<EuiButtonEmpty
|
||||
className="mapTocEntry__layerName eui-textLeft"
|
||||
color="text"
|
||||
data-test-subj="layerTocActionsPanelToggleButtonlayer1"
|
||||
flush="left"
|
||||
|
@ -85,11 +104,17 @@ exports[`LayerTocActions should disable fit to data when supportsFitToBounds is
|
|||
size="xs"
|
||||
type="button"
|
||||
>
|
||||
<div>
|
||||
icon mock
|
||||
</div>
|
||||
<span
|
||||
className="mapTocEntry__layerNameIcon"
|
||||
>
|
||||
<div>
|
||||
icon mock
|
||||
</div>
|
||||
</span>
|
||||
layer 1
|
||||
</EuiButtonEmpty>
|
||||
}
|
||||
className="mapLayTocActions"
|
||||
closePopover={[Function]}
|
||||
hasArrow={true}
|
||||
id="contextMenu"
|
||||
|
@ -126,6 +151,15 @@ exports[`LayerTocActions should disable fit to data when supportsFitToBounds is
|
|||
"name": "Hide layer",
|
||||
"onClick": [Function],
|
||||
},
|
||||
Object {
|
||||
"data-test-subj": "editLayerButton",
|
||||
"icon": <EuiIcon
|
||||
size="m"
|
||||
type="pencil"
|
||||
/>,
|
||||
"name": "Edit layer",
|
||||
"onClick": [Function],
|
||||
},
|
||||
Object {
|
||||
"data-test-subj": "cloneLayerButton",
|
||||
"icon": <EuiIcon
|
||||
|
@ -146,9 +180,11 @@ exports[`LayerTocActions should disable fit to data when supportsFitToBounds is
|
|||
|
||||
exports[`LayerTocActions should display spinner when layer is loading 1`] = `
|
||||
<EuiPopover
|
||||
anchorClassName="mapLayTocActions__popoverAnchor"
|
||||
anchorPosition="leftUp"
|
||||
button={
|
||||
<EuiButtonEmpty
|
||||
className="mapTocEntry__layerName eui-textLeft"
|
||||
color="text"
|
||||
data-test-subj="layerTocActionsPanelToggleButtonlayer1"
|
||||
flush="left"
|
||||
|
@ -157,11 +193,17 @@ exports[`LayerTocActions should display spinner when layer is loading 1`] = `
|
|||
size="xs"
|
||||
type="button"
|
||||
>
|
||||
<EuiLoadingSpinner
|
||||
size="m"
|
||||
/>
|
||||
<span
|
||||
className="mapTocEntry__layerNameIcon"
|
||||
>
|
||||
<EuiLoadingSpinner
|
||||
size="m"
|
||||
/>
|
||||
</span>
|
||||
layer 1
|
||||
</EuiButtonEmpty>
|
||||
}
|
||||
className="mapLayTocActions"
|
||||
closePopover={[Function]}
|
||||
hasArrow={true}
|
||||
id="contextMenu"
|
||||
|
@ -198,6 +240,15 @@ exports[`LayerTocActions should display spinner when layer is loading 1`] = `
|
|||
"name": "Hide layer",
|
||||
"onClick": [Function],
|
||||
},
|
||||
Object {
|
||||
"data-test-subj": "editLayerButton",
|
||||
"icon": <EuiIcon
|
||||
size="m"
|
||||
type="pencil"
|
||||
/>,
|
||||
"name": "Edit layer",
|
||||
"onClick": [Function],
|
||||
},
|
||||
Object {
|
||||
"data-test-subj": "cloneLayerButton",
|
||||
"icon": <EuiIcon
|
||||
|
@ -218,9 +269,11 @@ exports[`LayerTocActions should display spinner when layer is loading 1`] = `
|
|||
|
||||
exports[`LayerTocActions should not show edit actions in read only mode 1`] = `
|
||||
<EuiPopover
|
||||
anchorClassName="mapLayTocActions__popoverAnchor"
|
||||
anchorPosition="leftUp"
|
||||
button={
|
||||
<EuiButtonEmpty
|
||||
className="mapTocEntry__layerName eui-textLeft"
|
||||
color="text"
|
||||
data-test-subj="layerTocActionsPanelToggleButtonlayer1"
|
||||
flush="left"
|
||||
|
@ -229,11 +282,17 @@ exports[`LayerTocActions should not show edit actions in read only mode 1`] = `
|
|||
size="xs"
|
||||
type="button"
|
||||
>
|
||||
<div>
|
||||
icon mock
|
||||
</div>
|
||||
<span
|
||||
className="mapTocEntry__layerNameIcon"
|
||||
>
|
||||
<div>
|
||||
icon mock
|
||||
</div>
|
||||
</span>
|
||||
layer 1
|
||||
</EuiButtonEmpty>
|
||||
}
|
||||
className="mapLayTocActions"
|
||||
closePopover={[Function]}
|
||||
hasArrow={true}
|
||||
id="contextMenu"
|
||||
|
@ -281,9 +340,11 @@ exports[`LayerTocActions should not show edit actions in read only mode 1`] = `
|
|||
|
||||
exports[`LayerTocActions should provide feedback when layer is not visible because of current zoom level 1`] = `
|
||||
<EuiPopover
|
||||
anchorClassName="mapLayTocActions__popoverAnchor"
|
||||
anchorPosition="leftUp"
|
||||
button={
|
||||
<EuiButtonEmpty
|
||||
className="mapTocEntry__layerName eui-textLeft"
|
||||
color="text"
|
||||
data-test-subj="layerTocActionsPanelToggleButtonlayer1"
|
||||
flush="left"
|
||||
|
@ -292,18 +353,24 @@ exports[`LayerTocActions should provide feedback when layer is not visible becau
|
|||
size="xs"
|
||||
type="button"
|
||||
>
|
||||
<EuiToolTip
|
||||
content="Map is at zoom level 0.
|
||||
This layer is only visible between zoom levels 2 to 3."
|
||||
delay="regular"
|
||||
position="top"
|
||||
<span
|
||||
className="mapTocEntry__layerNameIcon"
|
||||
>
|
||||
<div>
|
||||
icon mock
|
||||
</div>
|
||||
</EuiToolTip>
|
||||
<EuiToolTip
|
||||
content="Map is at zoom level 0.
|
||||
This layer is only visible between zoom levels 2 to 3."
|
||||
delay="regular"
|
||||
position="top"
|
||||
>
|
||||
<div>
|
||||
icon mock
|
||||
</div>
|
||||
</EuiToolTip>
|
||||
</span>
|
||||
layer 1
|
||||
</EuiButtonEmpty>
|
||||
}
|
||||
className="mapLayTocActions"
|
||||
closePopover={[Function]}
|
||||
hasArrow={true}
|
||||
id="contextMenu"
|
||||
|
@ -340,6 +407,15 @@ exports[`LayerTocActions should provide feedback when layer is not visible becau
|
|||
"name": "Hide layer",
|
||||
"onClick": [Function],
|
||||
},
|
||||
Object {
|
||||
"data-test-subj": "editLayerButton",
|
||||
"icon": <EuiIcon
|
||||
size="m"
|
||||
type="pencil"
|
||||
/>,
|
||||
"name": "Edit layer",
|
||||
"onClick": [Function],
|
||||
},
|
||||
Object {
|
||||
"data-test-subj": "cloneLayerButton",
|
||||
"icon": <EuiIcon
|
||||
|
@ -360,9 +436,11 @@ exports[`LayerTocActions should provide feedback when layer is not visible becau
|
|||
|
||||
exports[`LayerTocActions should show visible toggle when layer is not visible 1`] = `
|
||||
<EuiPopover
|
||||
anchorClassName="mapLayTocActions__popoverAnchor"
|
||||
anchorPosition="leftUp"
|
||||
button={
|
||||
<EuiButtonEmpty
|
||||
className="mapTocEntry__layerName eui-textLeft"
|
||||
color="text"
|
||||
data-test-subj="layerTocActionsPanelToggleButtonlayer1"
|
||||
flush="left"
|
||||
|
@ -371,11 +449,17 @@ exports[`LayerTocActions should show visible toggle when layer is not visible 1`
|
|||
size="xs"
|
||||
type="button"
|
||||
>
|
||||
<div>
|
||||
icon mock
|
||||
</div>
|
||||
<span
|
||||
className="mapTocEntry__layerNameIcon"
|
||||
>
|
||||
<div>
|
||||
icon mock
|
||||
</div>
|
||||
</span>
|
||||
layer 1
|
||||
</EuiButtonEmpty>
|
||||
}
|
||||
className="mapLayTocActions"
|
||||
closePopover={[Function]}
|
||||
hasArrow={true}
|
||||
id="contextMenu"
|
||||
|
@ -412,6 +496,15 @@ exports[`LayerTocActions should show visible toggle when layer is not visible 1`
|
|||
"name": "Show layer",
|
||||
"onClick": [Function],
|
||||
},
|
||||
Object {
|
||||
"data-test-subj": "editLayerButton",
|
||||
"icon": <EuiIcon
|
||||
size="m"
|
||||
type="pencil"
|
||||
/>,
|
||||
"name": "Edit layer",
|
||||
"onClick": [Function],
|
||||
},
|
||||
Object {
|
||||
"data-test-subj": "cloneLayerButton",
|
||||
"icon": <EuiIcon
|
||||
|
@ -432,9 +525,11 @@ exports[`LayerTocActions should show visible toggle when layer is not visible 1`
|
|||
|
||||
exports[`LayerTocActions should show warning when layer has errors 1`] = `
|
||||
<EuiPopover
|
||||
anchorClassName="mapLayTocActions__popoverAnchor"
|
||||
anchorPosition="leftUp"
|
||||
button={
|
||||
<EuiButtonEmpty
|
||||
className="mapTocEntry__layerName eui-textLeft"
|
||||
color="text"
|
||||
data-test-subj="layerTocActionsPanelToggleButtonlayer1"
|
||||
flush="left"
|
||||
|
@ -443,15 +538,21 @@ exports[`LayerTocActions should show warning when layer has errors 1`] = `
|
|||
size="xs"
|
||||
type="button"
|
||||
>
|
||||
<EuiIconTip
|
||||
aria-label="Load warning"
|
||||
color="warning"
|
||||
content="simulated layer error"
|
||||
size="m"
|
||||
type="alert"
|
||||
/>
|
||||
<span
|
||||
className="mapTocEntry__layerNameIcon"
|
||||
>
|
||||
<EuiIconTip
|
||||
aria-label="Load warning"
|
||||
color="warning"
|
||||
content="simulated layer error"
|
||||
size="m"
|
||||
type="alert"
|
||||
/>
|
||||
</span>
|
||||
layer 1
|
||||
</EuiButtonEmpty>
|
||||
}
|
||||
className="mapLayTocActions"
|
||||
closePopover={[Function]}
|
||||
hasArrow={true}
|
||||
id="contextMenu"
|
||||
|
@ -488,6 +589,15 @@ exports[`LayerTocActions should show warning when layer has errors 1`] = `
|
|||
"name": "Hide layer",
|
||||
"onClick": [Function],
|
||||
},
|
||||
Object {
|
||||
"data-test-subj": "editLayerButton",
|
||||
"icon": <EuiIcon
|
||||
size="m"
|
||||
type="pencil"
|
||||
/>,
|
||||
"name": "Edit layer",
|
||||
"onClick": [Function],
|
||||
},
|
||||
Object {
|
||||
"data-test-subj": "cloneLayerButton",
|
||||
"icon": <EuiIcon
|
||||
|
|
|
@ -13,17 +13,10 @@ import {
|
|||
EuiIcon,
|
||||
EuiLoadingSpinner,
|
||||
EuiToolTip,
|
||||
EuiIconTip
|
||||
EuiIconTip,
|
||||
} from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
function cleanDisplayName(displayName) {
|
||||
if (!displayName) {
|
||||
return displayName;
|
||||
}
|
||||
return displayName.split(' ').join('');
|
||||
}
|
||||
|
||||
export class LayerTocActions extends Component {
|
||||
|
||||
state = {
|
||||
|
@ -63,13 +56,16 @@ export class LayerTocActions extends Component {
|
|||
const icon = this._renderIcon();
|
||||
return (
|
||||
<EuiButtonEmpty
|
||||
className="mapTocEntry__layerName eui-textLeft"
|
||||
size="xs"
|
||||
flush="left"
|
||||
color="text"
|
||||
onClick={this._onClick}
|
||||
data-test-subj={`layerTocActionsPanelToggleButton${cleanDisplayName(this.props.displayName)}`}
|
||||
data-test-subj={`layerTocActionsPanelToggleButton${this.props.escapedDisplayName}`}
|
||||
// textProps="mapTocEntry__layerNameText"
|
||||
>
|
||||
{icon}
|
||||
<span className="mapTocEntry__layerNameIcon">{icon}</span>
|
||||
{this.props.displayName}
|
||||
</EuiButtonEmpty>);
|
||||
}
|
||||
|
||||
|
@ -160,6 +156,22 @@ export class LayerTocActions extends Component {
|
|||
];
|
||||
|
||||
if (!this.props.isReadOnly) {
|
||||
actionItems.push({
|
||||
name: i18n.translate('xpack.maps.layerTocActions.editLayerTitle', {
|
||||
defaultMessage: 'Edit layer',
|
||||
}),
|
||||
icon: (
|
||||
<EuiIcon
|
||||
type="pencil"
|
||||
size="m"
|
||||
/>
|
||||
),
|
||||
'data-test-subj': 'editLayerButton',
|
||||
onClick: () => {
|
||||
this._closePopover();
|
||||
this.props.editLayer();
|
||||
}
|
||||
});
|
||||
actionItems.push({
|
||||
name: i18n.translate('xpack.maps.layerTocActions.cloneLayerTitle', {
|
||||
defaultMessage: 'Clone layer',
|
||||
|
@ -193,17 +205,19 @@ export class LayerTocActions extends Component {
|
|||
return (
|
||||
<EuiPopover
|
||||
id="contextMenu"
|
||||
className="mapLayTocActions"
|
||||
button={this._renderButton()}
|
||||
isOpen={this.state.isPopoverOpen}
|
||||
closePopover={this._closePopover}
|
||||
panelPaddingSize="none"
|
||||
withTitle
|
||||
anchorPosition="leftUp"
|
||||
anchorClassName="mapLayTocActions__popoverAnchor"
|
||||
>
|
||||
<EuiContextMenu
|
||||
initialPanelId={0}
|
||||
panels={this._getPanels()}
|
||||
data-test-subj={`layerTocActionsPanel${cleanDisplayName(this.props.displayName)}`}
|
||||
data-test-subj={`layerTocActionsPanel${this.props.escapedDisplayName}`}
|
||||
/>
|
||||
</EuiPopover>);
|
||||
}
|
||||
|
|
|
@ -26,7 +26,8 @@ const layerMock = {
|
|||
};
|
||||
|
||||
const defaultProps = {
|
||||
displayName: 'layer1',
|
||||
displayName: 'layer 1',
|
||||
escapedDisplayName: 'layer1',
|
||||
zoom: 0,
|
||||
layer: layerMock,
|
||||
};
|
||||
|
|
|
@ -44,7 +44,7 @@ export const FillableCircle = ({ style }) => (
|
|||
</svg>
|
||||
);
|
||||
|
||||
export const FillableVector = ({ style }) => (
|
||||
export const FillableRectangle = ({ style }) => (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
|
|
|
@ -7,23 +7,25 @@
|
|||
import React from 'react';
|
||||
import { vislibColorMaps } from 'ui/vislib/components/color/colormaps';
|
||||
import { getLegendColors } from 'ui/vis/map/color_util';
|
||||
import classNames from 'classnames';
|
||||
|
||||
const GRADIENT_INTERVALS = 7;
|
||||
const COLOR_KEYS = Object.keys(vislibColorMaps);
|
||||
|
||||
export const ColorGradient = ({ color }) => {
|
||||
export const ColorGradient = ({ color, className }) => {
|
||||
if (!color || !COLOR_KEYS.includes(color)) {
|
||||
return null;
|
||||
} else {
|
||||
const rgbColorStrings = getLegendColors(vislibColorMaps[color].value, GRADIENT_INTERVALS);
|
||||
const background = getLinearGradient(rgbColorStrings, GRADIENT_INTERVALS);
|
||||
return (
|
||||
<div
|
||||
className="mapColorGradient"
|
||||
style={{ background }}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const classes = classNames('mapColorGradient', className);
|
||||
const rgbColorStrings = getLegendColors(vislibColorMaps[color].value, GRADIENT_INTERVALS);
|
||||
const background = getLinearGradient(rgbColorStrings, GRADIENT_INTERVALS);
|
||||
return (
|
||||
<div
|
||||
className={classes}
|
||||
style={{ background }}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
function getLinearGradient(colorStrings, intervals) {
|
||||
|
|
|
@ -105,7 +105,11 @@ export class AbstractLayer {
|
|||
console.warn('Icon not available for this layer type');
|
||||
}
|
||||
|
||||
getTOCDetails() {
|
||||
hasLegendDetails() {
|
||||
return false;
|
||||
}
|
||||
|
||||
getLegendDetails() {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -105,7 +105,7 @@ export class StaticDynamicStyleRow extends React.Component {
|
|||
return (
|
||||
<EuiFlexGroup gutterSize="s">
|
||||
<EuiFlexItem className={isDynamic ? 'mapStaticDynamicSylingOption__dynamicSizeHack' : undefined}>
|
||||
<EuiFormRow label={this.props.name && this.props.name}>
|
||||
<EuiFormRow label={this.props.label && this.props.label}>
|
||||
{this._renderStyleSelector()}
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
import _ from 'lodash';
|
||||
import React, { Fragment } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { dynamicColorShape } from '../style_option_shapes';
|
||||
import { FieldSelect, fieldShape } from '../field_select';
|
||||
import { ColorRampSelect } from './color_ramp_select';
|
||||
import { EuiSpacer } from '@elastic/eui';
|
||||
|
@ -38,9 +39,6 @@ export function DynamicColorSelection({ ordinalFields, onChange, styleOptions })
|
|||
|
||||
DynamicColorSelection.propTypes = {
|
||||
ordinalFields: PropTypes.arrayOf(fieldShape).isRequired,
|
||||
styleOptions: PropTypes.shape({
|
||||
color: PropTypes.string.isRequired,
|
||||
field: fieldShape,
|
||||
}).isRequired,
|
||||
styleOptions: dynamicColorShape.isRequired,
|
||||
onChange: PropTypes.func.isRequired
|
||||
};
|
||||
|
|
|
@ -10,6 +10,7 @@ import {
|
|||
EuiColorPicker,
|
||||
EuiFormControlLayout
|
||||
} from '@elastic/eui';
|
||||
import { staticColorShape } from '../style_option_shapes';
|
||||
|
||||
export function StaticColorSelection({ onChange, styleOptions }) {
|
||||
const onColorChange = color => {
|
||||
|
@ -28,8 +29,6 @@ export function StaticColorSelection({ onChange, styleOptions }) {
|
|||
}
|
||||
|
||||
StaticColorSelection.propTypes = {
|
||||
styleOptions: PropTypes.shape({
|
||||
color: PropTypes.string.isRequired,
|
||||
}).isRequired,
|
||||
styleOptions: staticColorShape.isRequired,
|
||||
onChange: PropTypes.func.isRequired
|
||||
};
|
||||
|
|
|
@ -9,13 +9,14 @@ import React from 'react';
|
|||
import { StaticDynamicStyleRow } from '../../static_dynamic_style_row';
|
||||
import { DynamicColorSelection } from './dynamic_color_selection';
|
||||
import { StaticColorSelection } from './static_color_selection';
|
||||
import { getVectorStyleLabel } from '../get_vector_style_label';
|
||||
|
||||
export function VectorStyleColorEditor(props) {
|
||||
return (
|
||||
<StaticDynamicStyleRow
|
||||
ordinalFields={props.ordinalFields}
|
||||
property={props.styleProperty}
|
||||
name={props.stylePropertyName}
|
||||
label={getVectorStyleLabel(props.styleProperty)}
|
||||
styleDescriptor={props.styleDescriptor}
|
||||
handlePropertyChange={props.handlePropertyChange}
|
||||
DynamicSelector={DynamicColorSelection}
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* 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 { i18n } from '@kbn/i18n';
|
||||
|
||||
export function getVectorStyleLabel(styleName) {
|
||||
switch (styleName) {
|
||||
case 'fillColor':
|
||||
return i18n.translate('xpack.maps.styles.vector.fillColorLabel', {
|
||||
defaultMessage: 'Fill color'
|
||||
});
|
||||
case 'lineColor':
|
||||
return i18n.translate('xpack.maps.styles.vector.borderColorLabel', {
|
||||
defaultMessage: 'Border color'
|
||||
});
|
||||
case 'lineWidth':
|
||||
return i18n.translate('xpack.maps.styles.vector.borderWidthLabel', {
|
||||
defaultMessage: 'Border width'
|
||||
});
|
||||
case 'iconSize':
|
||||
return i18n.translate('xpack.maps.styles.vector.symbolSizeLabel', {
|
||||
defaultMessage: 'Symbol size'
|
||||
});
|
||||
default:
|
||||
return styleName;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
* 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 } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { styleOptionShapes, rangeShape } from '../style_option_shapes';
|
||||
import { VectorStyle } from '../../../vector_style';
|
||||
import { ColorGradient } from '../../../../../icons/color_gradient';
|
||||
import { FillableCircle } from '../../../../../icons/additional_layer_icons';
|
||||
import { getVectorStyleLabel } from '../get_vector_style_label';
|
||||
import {
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiText,
|
||||
EuiSpacer,
|
||||
EuiToolTip,
|
||||
EuiHorizontalRule,
|
||||
} from '@elastic/eui';
|
||||
|
||||
function getLineWidthIcons() {
|
||||
const defaultStyle = {
|
||||
stroke: 'grey',
|
||||
fill: 'none',
|
||||
width: '12px',
|
||||
};
|
||||
return [
|
||||
<FillableCircle style={{ ...defaultStyle, strokeWidth: '1px' }}/>,
|
||||
<FillableCircle style={{ ...defaultStyle, strokeWidth: '2px' }}/>,
|
||||
<FillableCircle style={{ ...defaultStyle, strokeWidth: '3px' }}/>,
|
||||
];
|
||||
}
|
||||
|
||||
function getSymbolSizeIcons() {
|
||||
const defaultStyle = {
|
||||
stroke: 'grey',
|
||||
strokeWidth: 'none',
|
||||
fill: 'grey',
|
||||
};
|
||||
return [
|
||||
<FillableCircle style={{ ...defaultStyle, width: '4px' }}/>,
|
||||
<FillableCircle style={{ ...defaultStyle, width: '8px' }}/>,
|
||||
<FillableCircle style={{ ...defaultStyle, width: '12px' }}/>,
|
||||
];
|
||||
}
|
||||
|
||||
function renderHeaderWithIcons(icons) {
|
||||
return (
|
||||
<EuiFlexGroup gutterSize="s" justifyContent="spaceBetween" alignItems="center">
|
||||
{
|
||||
icons.map((icon, index) => {
|
||||
const isLast = index === icons.length - 1;
|
||||
let spacer;
|
||||
if (!isLast) {
|
||||
spacer = (
|
||||
<EuiFlexItem>
|
||||
<EuiHorizontalRule margin="xs" />
|
||||
</EuiFlexItem>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<Fragment key={index}>
|
||||
<EuiFlexItem grow={false}>
|
||||
{icon}
|
||||
</EuiFlexItem>
|
||||
{spacer}
|
||||
</Fragment>
|
||||
);
|
||||
})
|
||||
}
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
}
|
||||
|
||||
export function StylePropertyLegendRow({ name, type, options, range }) {
|
||||
if (type === VectorStyle.STYLE_TYPE.STATIC ||
|
||||
!options.field || !options.field.name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let header;
|
||||
if (options.color) {
|
||||
header = <ColorGradient color={options.color}/>;
|
||||
} else if (name === 'lineWidth') {
|
||||
header = renderHeaderWithIcons(getLineWidthIcons());
|
||||
} else if (name === 'iconSize') {
|
||||
header = renderHeaderWithIcons(getSymbolSizeIcons());
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<EuiSpacer size="xs"/>
|
||||
{header}
|
||||
<EuiFlexGroup gutterSize="xs" justifyContent="spaceBetween">
|
||||
<EuiFlexItem grow={true}>
|
||||
<EuiText size="xs">
|
||||
<small>{_.get(range, 'min', '')}</small>
|
||||
</EuiText>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiToolTip
|
||||
position="top"
|
||||
title={getVectorStyleLabel(name)}
|
||||
content={options.field.label}
|
||||
>
|
||||
<EuiText
|
||||
className="eui-textTruncate"
|
||||
size="xs"
|
||||
style={{ maxWidth: '180px' }}
|
||||
>
|
||||
<small><strong>{options.field.label}</strong></small>
|
||||
</EuiText>
|
||||
</EuiToolTip>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={true}>
|
||||
<EuiText textAlign="right" size="xs">
|
||||
<small>{_.get(range, 'max', '')}</small>
|
||||
</EuiText>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
StylePropertyLegendRow.propTypes = {
|
||||
name: PropTypes.string.isRequired,
|
||||
type: PropTypes.string.isRequired,
|
||||
options: PropTypes.oneOfType(styleOptionShapes).isRequired,
|
||||
range: rangeShape,
|
||||
};
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* 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 from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { dynamicColorShape, staticColorShape } from '../style_option_shapes';
|
||||
import { FillableCircle, FillableRectangle } from '../../../../../icons/additional_layer_icons';
|
||||
import { VectorStyle } from '../../../vector_style';
|
||||
import { getColorRampCenterColor } from '../../../../../utils/color_utils';
|
||||
|
||||
export function VectorIcon({ fillColor, lineColor, isPointsOnly }) {
|
||||
const style = {
|
||||
stroke: extractColorFromStyleProperty(lineColor, 'none'),
|
||||
strokeWidth: '1px',
|
||||
fill: extractColorFromStyleProperty(fillColor, 'grey'),
|
||||
};
|
||||
|
||||
return isPointsOnly
|
||||
? <FillableCircle style={style}/>
|
||||
: <FillableRectangle style={style}/>;
|
||||
}
|
||||
|
||||
function extractColorFromStyleProperty(colorStyleProperty, defaultColor) {
|
||||
if (!colorStyleProperty) {
|
||||
return defaultColor;
|
||||
}
|
||||
|
||||
if (colorStyleProperty.type === VectorStyle.STYLE_TYPE.STATIC) {
|
||||
return colorStyleProperty.options.color;
|
||||
}
|
||||
|
||||
// return middle of gradient for dynamic style property
|
||||
return getColorRampCenterColor(colorStyleProperty.options.color);
|
||||
}
|
||||
|
||||
const colorStylePropertyShape = PropTypes.shape({
|
||||
type: PropTypes.string.isRequired,
|
||||
options: PropTypes.oneOfType([
|
||||
dynamicColorShape,
|
||||
staticColorShape
|
||||
]).isRequired,
|
||||
});
|
||||
|
||||
VectorIcon.propTypes = {
|
||||
fillColor: colorStylePropertyShape,
|
||||
lineColor: colorStylePropertyShape,
|
||||
isPointsOnly: PropTypes.bool,
|
||||
};
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* 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 from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { styleOptionShapes, rangeShape } from '../style_option_shapes';
|
||||
import { StylePropertyLegendRow } from './style_property_legend_row';
|
||||
|
||||
export function VectorStyleLegend({ styleProperties }) {
|
||||
return styleProperties.map(styleProperty => {
|
||||
return (
|
||||
<StylePropertyLegendRow
|
||||
key={styleProperty.name}
|
||||
name={styleProperty.name}
|
||||
type={styleProperty.type}
|
||||
options={styleProperty.options}
|
||||
range={styleProperty.range}
|
||||
/>
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
const stylePropertyShape = PropTypes.shape({
|
||||
name: PropTypes.string.isRequired,
|
||||
type: PropTypes.string.isRequired,
|
||||
options: PropTypes.oneOfType(styleOptionShapes).isRequired,
|
||||
range: rangeShape,
|
||||
});
|
||||
|
||||
VectorStyleLegend.propTypes = {
|
||||
styleProperties: PropTypes.arrayOf(stylePropertyShape).isRequired
|
||||
};
|
|
@ -7,6 +7,7 @@
|
|||
import _ from 'lodash';
|
||||
import React, { Fragment } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { dynamicSizeShape } from '../style_option_shapes';
|
||||
import { FieldSelect, fieldShape } from '../field_select';
|
||||
import { SizeRangeSelector } from './size_range_selector';
|
||||
import { EuiSpacer } from '@elastic/eui';
|
||||
|
@ -39,10 +40,6 @@ export function DynamicSizeSelection({ ordinalFields, styleOptions, onChange })
|
|||
|
||||
DynamicSizeSelection.propTypes = {
|
||||
ordinalFields: PropTypes.arrayOf(fieldShape).isRequired,
|
||||
styleOptions: PropTypes.shape({
|
||||
minSize: PropTypes.number.isRequired,
|
||||
maxSize: PropTypes.number.isRequired,
|
||||
field: fieldShape,
|
||||
}).isRequired,
|
||||
styleOptions: dynamicSizeShape.isRequired,
|
||||
onChange: PropTypes.func.isRequired
|
||||
};
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { staticSizeShape } from '../style_option_shapes';
|
||||
import { ValidatedRange } from '../../../../../components/validated_range';
|
||||
|
||||
export function StaticSizeSelection({ onChange, styleOptions }) {
|
||||
|
@ -27,8 +28,6 @@ export function StaticSizeSelection({ onChange, styleOptions }) {
|
|||
}
|
||||
|
||||
StaticSizeSelection.propTypes = {
|
||||
styleOptions: PropTypes.shape({
|
||||
size: PropTypes.number.isRequired,
|
||||
}).isRequired,
|
||||
styleOptions: staticSizeShape.isRequired,
|
||||
onChange: PropTypes.func.isRequired
|
||||
};
|
||||
|
|
|
@ -9,13 +9,14 @@ import React from 'react';
|
|||
import { StaticDynamicStyleRow } from '../../static_dynamic_style_row';
|
||||
import { DynamicSizeSelection } from './dynamic_size_selection';
|
||||
import { StaticSizeSelection } from './static_size_selection';
|
||||
import { getVectorStyleLabel } from '../get_vector_style_label';
|
||||
|
||||
export function VectorStyleSizeEditor(props) {
|
||||
return (
|
||||
<StaticDynamicStyleRow
|
||||
ordinalFields={props.ordinalFields}
|
||||
property={props.styleProperty}
|
||||
name={props.stylePropertyName}
|
||||
label={getVectorStyleLabel(props.styleProperty)}
|
||||
styleDescriptor={props.styleDescriptor}
|
||||
handlePropertyChange={props.handlePropertyChange}
|
||||
DynamicSelector={DynamicSizeSelection}
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* 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 PropTypes from 'prop-types';
|
||||
import { fieldShape } from './field_select';
|
||||
|
||||
export const staticColorShape = PropTypes.shape({
|
||||
color: PropTypes.string.isRequired,
|
||||
});
|
||||
|
||||
export const dynamicColorShape = PropTypes.shape({
|
||||
color: PropTypes.string.isRequired,
|
||||
field: fieldShape,
|
||||
});
|
||||
|
||||
export const staticSizeShape = PropTypes.shape({
|
||||
size: PropTypes.number.isRequired,
|
||||
});
|
||||
|
||||
export const dynamicSizeShape = PropTypes.shape({
|
||||
minSize: PropTypes.number.isRequired,
|
||||
maxSize: PropTypes.number.isRequired,
|
||||
field: fieldShape,
|
||||
});
|
||||
|
||||
export const styleOptionShapes = [
|
||||
staticColorShape,
|
||||
dynamicColorShape,
|
||||
staticSizeShape,
|
||||
dynamicSizeShape
|
||||
];
|
||||
|
||||
export const rangeShape = PropTypes.shape({
|
||||
min: PropTypes.number.isRequired,
|
||||
max: PropTypes.number.isRequired,
|
||||
});
|
|
@ -12,7 +12,6 @@ import { VectorStyleSizeEditor } from './size/vector_style_size_editor';
|
|||
import { getDefaultDynamicProperties, getDefaultStaticProperties } from '../../vector_style_defaults';
|
||||
|
||||
import { EuiSpacer } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
export class VectorStyleEditor extends Component {
|
||||
state = {
|
||||
|
@ -50,11 +49,6 @@ export class VectorStyleEditor extends Component {
|
|||
|
||||
<VectorStyleColorEditor
|
||||
styleProperty="fillColor"
|
||||
stylePropertyName={
|
||||
i18n.translate('xpack.maps.styles.vector.fillColorLabel', {
|
||||
defaultMessage: 'Fill color'
|
||||
})
|
||||
}
|
||||
handlePropertyChange={this.props.handlePropertyChange}
|
||||
styleDescriptor={this.props.styleProperties.fillColor}
|
||||
ordinalFields={this.state.ordinalFields}
|
||||
|
@ -66,11 +60,6 @@ export class VectorStyleEditor extends Component {
|
|||
|
||||
<VectorStyleColorEditor
|
||||
styleProperty="lineColor"
|
||||
stylePropertyName={
|
||||
i18n.translate('xpack.maps.styles.vector.borderColorLabel', {
|
||||
defaultMessage: 'Border color'
|
||||
})
|
||||
}
|
||||
handlePropertyChange={this.props.handlePropertyChange}
|
||||
styleDescriptor={this.props.styleProperties.lineColor}
|
||||
ordinalFields={this.state.ordinalFields}
|
||||
|
@ -82,11 +71,6 @@ export class VectorStyleEditor extends Component {
|
|||
|
||||
<VectorStyleSizeEditor
|
||||
styleProperty="lineWidth"
|
||||
stylePropertyName={
|
||||
i18n.translate('xpack.maps.styles.vector.borderWidthLabel', {
|
||||
defaultMessage: 'Border width'
|
||||
})
|
||||
}
|
||||
handlePropertyChange={this.props.handlePropertyChange}
|
||||
styleDescriptor={this.props.styleProperties.lineWidth}
|
||||
ordinalFields={this.state.ordinalFields}
|
||||
|
@ -98,11 +82,6 @@ export class VectorStyleEditor extends Component {
|
|||
|
||||
<VectorStyleSizeEditor
|
||||
styleProperty="iconSize"
|
||||
stylePropertyName={
|
||||
i18n.translate('xpack.maps.styles.vector.symbolSizeLabel', {
|
||||
defaultMessage: 'Symbol size'
|
||||
})
|
||||
}
|
||||
handlePropertyChange={this.props.handlePropertyChange}
|
||||
styleDescriptor={this.props.styleProperties.iconSize}
|
||||
ordinalFields={this.state.ordinalFields}
|
||||
|
|
|
@ -7,13 +7,13 @@
|
|||
import _ from 'lodash';
|
||||
import React from 'react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { FillableCircle, FillableVector } from '../../icons/additional_layer_icons';
|
||||
import { ColorGradient } from '../../icons/color_gradient';
|
||||
import { getHexColorRangeStrings } from '../../utils/color_utils';
|
||||
import { VectorStyleEditor } from './components/vector/vector_style_editor';
|
||||
import { getDefaultStaticProperties } from './vector_style_defaults';
|
||||
import { AbstractStyle } from './abstract_style';
|
||||
import { SOURCE_DATA_ID_ORIGIN } from '../../../../common/constants';
|
||||
import { VectorIcon } from './components/vector/legend/vector_icon';
|
||||
import { VectorStyleLegend } from './components/vector/legend/vector_style_legend';
|
||||
|
||||
export class VectorStyle extends AbstractStyle {
|
||||
|
||||
|
@ -131,7 +131,7 @@ export class VectorStyle extends AbstractStyle {
|
|||
return {};
|
||||
}
|
||||
|
||||
const scaledFields = this._getDynamicPropertiesArray()
|
||||
const scaledFields = this.getDynamicPropertiesArray()
|
||||
.map(({ options }) => {
|
||||
return {
|
||||
name: options.field.name,
|
||||
|
@ -194,7 +194,7 @@ export class VectorStyle extends AbstractStyle {
|
|||
return this._descriptor.properties || {};
|
||||
}
|
||||
|
||||
_getDynamicPropertiesArray() {
|
||||
getDynamicPropertiesArray() {
|
||||
const styles = this.getProperties();
|
||||
return Object.keys(styles)
|
||||
.map(styleName => {
|
||||
|
@ -224,48 +224,29 @@ export class VectorStyle extends AbstractStyle {
|
|||
}
|
||||
|
||||
getIcon = () => {
|
||||
let style = {
|
||||
stroke: 'grey',
|
||||
strokeWidth: '1px',
|
||||
fill: 'none'
|
||||
};
|
||||
const isDynamic = this._isPropertyDynamic('fillColor');
|
||||
if (!isDynamic) {
|
||||
const { fillColor, lineColor } = this._descriptor.properties;
|
||||
const stroke = _.get(lineColor, 'options.color');
|
||||
const fill = _.get(fillColor, 'options.color');
|
||||
|
||||
style = {
|
||||
...style,
|
||||
...stroke && { stroke },
|
||||
...fill && { fill },
|
||||
};
|
||||
}
|
||||
|
||||
const styles = this.getProperties();
|
||||
return (
|
||||
this._getIsPointsOnly()
|
||||
? <FillableCircle style={style}/>
|
||||
: <FillableVector style={style}/>
|
||||
<VectorIcon
|
||||
isPointsOnly={this._getIsPointsOnly()}
|
||||
fillColor={styles.fillColor}
|
||||
lineColor={styles.lineColor}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
getColorRamp() {
|
||||
const color = _.get(this._descriptor, 'properties.fillColor.options.color');
|
||||
return color && this._isPropertyDynamic('fillColor')
|
||||
? <ColorGradient color={color}/>
|
||||
: null;
|
||||
}
|
||||
getLegendDetails() {
|
||||
const styles = this.getProperties();
|
||||
const styleProperties = Object.keys(styles).map(styleName => {
|
||||
const { type, options } = styles[styleName];
|
||||
return {
|
||||
name: styleName,
|
||||
type,
|
||||
options,
|
||||
range: options && options.field && options.field.name ? this._getFieldRange(options.field.name) : null,
|
||||
};
|
||||
});
|
||||
|
||||
getTOCDetails() {
|
||||
const isDynamic = this._isPropertyDynamic('fillColor');
|
||||
if (isDynamic) {
|
||||
return (
|
||||
<React.Fragment>
|
||||
{this.getColorRamp()}
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
return (<VectorStyleLegend styleProperties={styleProperties}/>);
|
||||
}
|
||||
|
||||
addScaledPropertiesBasedOnStyle(featureCollection) {
|
||||
|
@ -273,7 +254,7 @@ export class VectorStyle extends AbstractStyle {
|
|||
return false;
|
||||
}
|
||||
|
||||
const scaledFields = this._getDynamicPropertiesArray()
|
||||
const scaledFields = this.getDynamicPropertiesArray()
|
||||
.map(({ options }) => {
|
||||
const name = options.field.name;
|
||||
return {
|
||||
|
|
|
@ -86,8 +86,12 @@ export class VectorLayer extends AbstractLayer {
|
|||
return 'vector';
|
||||
}
|
||||
|
||||
getTOCDetails() {
|
||||
return this._style.getTOCDetails();
|
||||
hasLegendDetails() {
|
||||
return this._style.getDynamicPropertiesArray().length > 0;
|
||||
}
|
||||
|
||||
getLegendDetails() {
|
||||
return this._style.getLegendDetails();
|
||||
}
|
||||
|
||||
_getBoundsBasedOnData() {
|
||||
|
|
|
@ -5,20 +5,29 @@
|
|||
*/
|
||||
|
||||
import { vislibColorMaps } from 'ui/vislib/components/color/colormaps';
|
||||
import { getLegendColors } from 'ui/vis/map/color_util';
|
||||
import { getLegendColors, getColor } from 'ui/vis/map/color_util';
|
||||
import chroma from 'chroma-js';
|
||||
|
||||
export function getRGBColorRangeStrings(colorName, numberColors) {
|
||||
const colorKeys = Object.keys(vislibColorMaps);
|
||||
if (!colorKeys.includes(colorName)) {
|
||||
//This is an internal error and should never occur. If it does, then it is a bug.
|
||||
throw new Error(`${colorName} not found. Expected one of following values: \
|
||||
${colorKeys}`);
|
||||
function getColorRamp(colorRampName) {
|
||||
const colorRamp = vislibColorMaps[colorRampName];
|
||||
if (!colorRamp) {
|
||||
throw new Error(`${colorRampName} not found. Expected one of following values: ${Object.keys(vislibColorMaps)}`);
|
||||
}
|
||||
return getLegendColors(vislibColorMaps[colorName].value, numberColors);
|
||||
return colorRamp;
|
||||
}
|
||||
|
||||
export function getHexColorRangeStrings(colorName, numberColors) {
|
||||
return getRGBColorRangeStrings(colorName, numberColors)
|
||||
export function getRGBColorRangeStrings(colorRampName, numberColors) {
|
||||
const colorRamp = getColorRamp(colorRampName);
|
||||
return getLegendColors(colorRamp.value, numberColors);
|
||||
}
|
||||
|
||||
export function getHexColorRangeStrings(colorRampName, numberColors) {
|
||||
return getRGBColorRangeStrings(colorRampName, numberColors)
|
||||
.map(rgbColor => chroma(rgbColor).hex());
|
||||
}
|
||||
|
||||
export function getColorRampCenterColor(colorRampName) {
|
||||
const colorRamp = getColorRamp(colorRampName);
|
||||
const centerIndex = Math.floor(colorRamp.value.length / 2);
|
||||
return getColor(colorRamp.value, centerIndex);
|
||||
}
|
||||
|
|
|
@ -10,6 +10,10 @@ export const SET_IS_LAYER_TOC_OPEN = 'SET_IS_LAYER_TOC_OPEN';
|
|||
export const SET_FULL_SCREEN = 'SET_FULL_SCREEN';
|
||||
export const SET_READ_ONLY = 'SET_READ_ONLY';
|
||||
export const SET_FILTERABLE = 'IS_FILTERABLE';
|
||||
export const SET_OPEN_TOC_DETAILS = 'SET_OPEN_TOC_DETAILS';
|
||||
export const SHOW_TOC_DETAILS = 'SHOW_TOC_DETAILS';
|
||||
export const HIDE_TOC_DETAILS = 'HIDE_TOC_DETAILS';
|
||||
|
||||
export const FLYOUT_STATE = {
|
||||
NONE: 'NONE',
|
||||
LAYER_PANEL: 'LAYER_PANEL',
|
||||
|
@ -23,7 +27,10 @@ const INITIAL_STATE = {
|
|||
isFullScreen: false,
|
||||
isReadOnly: false,
|
||||
isLayerTOCOpen: DEFAULT_IS_LAYER_TOC_OPEN,
|
||||
isFilterable: false
|
||||
isFilterable: false,
|
||||
// storing TOC detail visibility outside of map.layerList because its UI state and not map rendering state.
|
||||
// This also makes for easy read/write access for embeddables.
|
||||
openTOCDetails: [],
|
||||
};
|
||||
|
||||
// Reducer
|
||||
|
@ -43,6 +50,23 @@ export function ui(state = INITIAL_STATE, action) {
|
|||
return { ...state, isReadOnly: action.isReadOnly };
|
||||
case SET_FILTERABLE:
|
||||
return { ...state, isFilterable: action.isFilterable };
|
||||
case SET_OPEN_TOC_DETAILS:
|
||||
return { ...state, openTOCDetails: action.layerIds };
|
||||
case SHOW_TOC_DETAILS:
|
||||
return {
|
||||
...state,
|
||||
openTOCDetails: [
|
||||
...state.openTOCDetails,
|
||||
action.layerId
|
||||
]
|
||||
};
|
||||
case HIDE_TOC_DETAILS:
|
||||
return {
|
||||
...state,
|
||||
openTOCDetails: state.openTOCDetails.filter(layerId => {
|
||||
return layerId !== action.layerId;
|
||||
})
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
@ -97,11 +121,33 @@ export function setFilterable(isFilterable) {
|
|||
};
|
||||
}
|
||||
|
||||
export function setOpenTOCDetails(layerIds) {
|
||||
return {
|
||||
type: SET_OPEN_TOC_DETAILS,
|
||||
layerIds
|
||||
};
|
||||
}
|
||||
|
||||
export function showTOCDetails(layerId) {
|
||||
return {
|
||||
type: SHOW_TOC_DETAILS,
|
||||
layerId
|
||||
};
|
||||
}
|
||||
|
||||
export function hideTOCDetails(layerId) {
|
||||
return {
|
||||
type: HIDE_TOC_DETAILS,
|
||||
layerId
|
||||
};
|
||||
}
|
||||
|
||||
// Selectors
|
||||
export const getFlyoutDisplay = ({ ui }) => ui && ui.flyoutDisplay
|
||||
|| INITIAL_STATE.flyoutDisplay;
|
||||
export const getIsSetViewOpen = ({ ui }) => ui.isSetViewOpen;
|
||||
export const getIsLayerTOCOpen = ({ ui }) => ui.isLayerTOCOpen;
|
||||
export const getOpenTOCDetails = ({ ui }) => ui.openTOCDetails;
|
||||
export const getIsFullScreen = ({ ui }) => ui.isFullScreen;
|
||||
export const getIsReadOnly = ({ ui }) => ui.isReadOnly;
|
||||
export const getIsFilterable = ({ ui }) => ui.isFilterable;
|
||||
|
|
|
@ -45,6 +45,17 @@ export default function ({ getPageObjects, getService }) {
|
|||
expect(beforeRefreshTimerTimestamp).not.to.equal(afterRefreshTimerTimestamp);
|
||||
});
|
||||
|
||||
it('should show dynamic data range in legend', async () => {
|
||||
const layerTOCDetails = await PageObjects.maps.getLayerTOCDetails('geo_shapes*');
|
||||
const split = layerTOCDetails.trim().split('\n');
|
||||
|
||||
const min = split[0];
|
||||
expect(min).to.equal('3');
|
||||
|
||||
const max = split[2];
|
||||
expect(max).to.equal('12');
|
||||
});
|
||||
|
||||
it('should decorate feature properties with join property', async () => {
|
||||
const mapboxStyle = await PageObjects.maps.getMapboxStyle();
|
||||
expect(mapboxStyle.sources[VECTOR_SOURCE_ID].data.features.length).to.equal(4);
|
||||
|
@ -60,7 +71,6 @@ export default function ({ getPageObjects, getService }) {
|
|||
});
|
||||
});
|
||||
|
||||
|
||||
it('should style fills, points and lines independently', async () => {
|
||||
const mapboxStyle = await PageObjects.maps.getMapboxStyle();
|
||||
const layersForVectorSource = mapboxStyle.layers.filter(mbLayer => {
|
||||
|
|
|
@ -110,7 +110,7 @@
|
|||
"type": "envelope"
|
||||
},
|
||||
"description": "",
|
||||
"layerListJSON": "[{\"id\":\"0hmz5\",\"sourceDescriptor\":{\"type\":\"EMS_TMS\",\"id\":\"road_map\"},\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"TILE\",\"properties\":{\"alphaValue\":1}},\"type\":\"TILE\",\"minZoom\":0,\"maxZoom\":24},{\"id\":\"z52lq\",\"label\":\"logstash\",\"minZoom\":0,\"maxZoom\":24,\"sourceDescriptor\":{\"id\":\"e1a5e1a6-676c-4a89-8ea9-0d91d64b73c6\",\"type\":\"ES_SEARCH\",\"indexPatternId\":\"c698b940-e149-11e8-a35a-370a8516603a\",\"geoField\":\"geo.coordinates\",\"limit\":2048,\"filterByMapBounds\":true,\"showTooltip\":true,\"tooltipProperties\":[]},\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"fillColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#e6194b\"}},\"lineColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#FFFFFF\"}},\"lineWidth\":{\"type\":\"STATIC\",\"options\":{\"size\":1}},\"iconSize\":{\"type\":\"STATIC\",\"options\":{\"size\":10}},\"alphaValue\":1},\"previousStyle\":null},\"type\":\"VECTOR\"}]",
|
||||
"layerListJSON": "[{\"id\":\"0hmz5\",\"sourceDescriptor\":{\"type\":\"EMS_TMS\",\"id\":\"road_map\"},\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"TILE\",\"properties\":{}},\"type\":\"TILE\",\"minZoom\":0,\"maxZoom\":24},{\"id\":\"z52lq\",\"label\":\"logstash\",\"minZoom\":0,\"maxZoom\":24,\"sourceDescriptor\":{\"id\":\"e1a5e1a6-676c-4a89-8ea9-0d91d64b73c6\",\"type\":\"ES_SEARCH\",\"indexPatternId\":\"c698b940-e149-11e8-a35a-370a8516603a\",\"geoField\":\"geo.coordinates\",\"limit\":2048,\"filterByMapBounds\":true,\"showTooltip\":true,\"tooltipProperties\":[]},\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"fillColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#e6194b\"}},\"lineColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#FFFFFF\"}},\"lineWidth\":{\"type\":\"STATIC\",\"options\":{\"size\":1}},\"iconSize\":{\"type\":\"STATIC\",\"options\":{\"size\":10}}},\"previousStyle\":null},\"type\":\"VECTOR\"}]",
|
||||
"mapStateJSON": "{\"zoom\":4.1,\"center\":{\"lon\":-100.61091,\"lat\":33.23887},\"timeFilters\":{\"from\":\"2015-09-20T00:00:00.000Z\",\"to\":\"2015-09-20T01:00:00.000Z\"},\"refreshConfig\":{\"isPaused\":true,\"interval\":1000}}",
|
||||
"title": "document example",
|
||||
"uiStateJSON": "{\"isDarkMode\":false}"
|
||||
|
@ -141,7 +141,7 @@
|
|||
"type": "envelope"
|
||||
},
|
||||
"description": "",
|
||||
"layerListJSON": "[{\"id\":\"0hmz5\",\"sourceDescriptor\":{\"type\":\"EMS_TMS\",\"id\":\"road_map\"},\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"TILE\",\"properties\":{\"alphaValue\":1}},\"type\":\"TILE\",\"minZoom\":0,\"maxZoom\":24},{\"id\":\"z52lq\",\"label\":null,\"minZoom\":0,\"maxZoom\":24,\"sourceDescriptor\":{\"id\":\"e1a5e1a6-676c-4a89-8ea9-0d91d64b73c6\",\"type\":\"ES_SEARCH\",\"indexPatternId\":\"c698b940-e149-11e8-a35a-370a8516603a\",\"geoField\":\"geo.coordinates\",\"limit\":2048,\"filterByMapBounds\":true,\"showTooltip\":true,\"tooltipProperties\":[\"machine.os\"]},\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"fillColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#e6194b\"}},\"lineColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#FFFFFF\"}},\"lineWidth\":{\"type\":\"STATIC\",\"options\":{\"size\":1}},\"iconSize\":{\"type\":\"STATIC\",\"options\":{\"size\":10}},\"alphaValue\":1},\"previousStyle\":null},\"type\":\"VECTOR\"}]",
|
||||
"layerListJSON": "[{\"id\":\"0hmz5\",\"sourceDescriptor\":{\"type\":\"EMS_TMS\",\"id\":\"road_map\"},\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"TILE\",\"properties\":{}},\"type\":\"TILE\",\"minZoom\":0,\"maxZoom\":24},{\"id\":\"z52lq\",\"label\":null,\"minZoom\":0,\"maxZoom\":24,\"sourceDescriptor\":{\"id\":\"e1a5e1a6-676c-4a89-8ea9-0d91d64b73c6\",\"type\":\"ES_SEARCH\",\"indexPatternId\":\"c698b940-e149-11e8-a35a-370a8516603a\",\"geoField\":\"geo.coordinates\",\"limit\":2048,\"filterByMapBounds\":true,\"showTooltip\":true,\"tooltipProperties\":[\"machine.os\"]},\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"fillColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#e6194b\"}},\"lineColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#FFFFFF\"}},\"lineWidth\":{\"type\":\"STATIC\",\"options\":{\"size\":1}},\"iconSize\":{\"type\":\"STATIC\",\"options\":{\"size\":10}}},\"previousStyle\":null},\"type\":\"VECTOR\"}]",
|
||||
"mapStateJSON": "{\"zoom\":4.1,\"center\":{\"lon\":-100.61091,\"lat\":33.23887},\"timeFilters\":{\"from\":\"2015-09-20T00:00:00.000Z\",\"to\":\"2015-09-20T01:00:00.000Z\"},\"refreshConfig\":{\"isPaused\":true,\"interval\":1000},\"query\":{\"query\":\"machine.os.raw : \\\"ios\\\"\",\"language\":\"kuery\"}}",
|
||||
"title": "document example with query",
|
||||
"uiStateJSON": "{\"isDarkMode\":false}"
|
||||
|
@ -172,10 +172,10 @@
|
|||
"type": "envelope"
|
||||
},
|
||||
"description": "",
|
||||
"layerListJSON": "[{\"id\":\"0hmz5\",\"label\":\"EMS base layer (road_map)\",\"sourceDescriptor\":{\"type\":\"EMS_TMS\",\"id\":\"road_map\"},\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"TILE\",\"properties\":{\"alphaValue\":1}},\"type\":\"TILE\",\"minZoom\":0,\"maxZoom\":24},{\"id\":\"n1t6f\",\"label\":null,\"minZoom\":0,\"maxZoom\":24,\"sourceDescriptor\":{\"id\":\"62eca1fc-fe42-11e8-8eb2-f2801f1b9fd1\",\"type\":\"ES_SEARCH\",\"geoField\":\"geometry\",\"limit\":2048,\"filterByMapBounds\":false,\"showTooltip\":true,\"tooltipProperties\":[],\"indexPatternRefName\":\"layer_1_source_index_pattern\"},\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"fillColor\":{\"type\":\"DYNAMIC\",\"options\":{\"field\":{\"label\":\"max(prop1) group by meta_for_geo_shapes*.shape_name\",\"name\":\"__kbnjoin__max_of_prop1_groupby_meta_for_geo_shapes*.shape_name\",\"origin\":\"join\"},\"color\":\"Blues\"}},\"iconSize\":{\"type\":\"STATIC\",\"options\":{\"size\":10}},\"alphaValue\":1},\"temporary\":true,\"previousStyle\":null},\"type\":\"VECTOR\",\"joins\":[{\"leftField\":\"name\",\"right\":{\"id\":\"855ccb86-fe42-11e8-8eb2-f2801f1b9fd1\",\"indexPatternTitle\":\"meta_for_geo_shapes*\",\"term\":\"shape_name\",\"metrics\":[{\"type\":\"max\",\"field\":\"prop1\"}],\"indexPatternRefName\":\"layer_1_join_0_index_pattern\"}}]}]",
|
||||
"layerListJSON": "[{\"id\":\"0hmz5\",\"label\":\"EMS base layer (road_map)\",\"sourceDescriptor\":{\"type\":\"EMS_TMS\",\"id\":\"road_map\"},\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"TILE\",\"properties\":{}},\"type\":\"TILE\",\"minZoom\":0,\"maxZoom\":24},{\"id\":\"n1t6f\",\"label\":null,\"minZoom\":0,\"maxZoom\":24,\"sourceDescriptor\":{\"id\":\"62eca1fc-fe42-11e8-8eb2-f2801f1b9fd1\",\"type\":\"ES_SEARCH\",\"geoField\":\"geometry\",\"limit\":2048,\"filterByMapBounds\":false,\"showTooltip\":true,\"tooltipProperties\":[],\"indexPatternRefName\":\"layer_1_source_index_pattern\"},\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"fillColor\":{\"type\":\"DYNAMIC\",\"options\":{\"field\":{\"label\":\"max(prop1) group by meta_for_geo_shapes*.shape_name\",\"name\":\"__kbnjoin__max_of_prop1_groupby_meta_for_geo_shapes*.shape_name\",\"origin\":\"join\"},\"color\":\"Blues\"}},\"iconSize\":{\"type\":\"STATIC\",\"options\":{\"size\":10}}},\"temporary\":true,\"previousStyle\":null},\"type\":\"VECTOR\",\"joins\":[{\"leftField\":\"name\",\"right\":{\"id\":\"855ccb86-fe42-11e8-8eb2-f2801f1b9fd1\",\"indexPatternTitle\":\"meta_for_geo_shapes*\",\"term\":\"shape_name\",\"metrics\":[{\"type\":\"max\",\"field\":\"prop1\"}],\"indexPatternRefName\":\"layer_1_join_0_index_pattern\"}}]}]",
|
||||
"mapStateJSON": "{\"zoom\":3.02,\"center\":{\"lon\":77.33426,\"lat\":-0.04647},\"timeFilters\":{\"from\":\"now-17m\",\"to\":\"now\",\"mode\":\"quick\"},\"refreshConfig\":{\"isPaused\":true,\"interval\":1000}}",
|
||||
"title": "join example",
|
||||
"uiStateJSON": "{\"isDarkMode\":false}"
|
||||
"uiStateJSON": "{\"isLayerTOCOpen\":true,\"openTOCDetails\":[\"n1t6f\"]}"
|
||||
},
|
||||
"type": "map",
|
||||
"references" : [
|
||||
|
@ -217,7 +217,7 @@
|
|||
],
|
||||
"type": "envelope"
|
||||
},
|
||||
"layerListJSON": "[{\"id\":\"0hmz5\",\"sourceDescriptor\":{\"type\":\"EMS_TMS\",\"id\":\"road_map\"},\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"TILE\",\"properties\":{\"alphaValue\":1}},\"type\":\"TILE\",\"minZoom\":0,\"maxZoom\":24},{\"id\":\"3xlvm\",\"label\":null,\"minZoom\":0,\"maxZoom\":24,\"sourceDescriptor\":{\"resolution\": \"COARSE\",\"type\":\"ES_GEO_GRID\",\"id\":\"427aa49d-a552-4e7d-a629-67c47db27128\",\"indexPatternId\":\"c698b940-e149-11e8-a35a-370a8516603a\",\"geoField\":\"geo.coordinates\",\"requestType\":\"heatmap\"},\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"HEATMAP\",\"refinement\":\"coarse\",\"properties\":{\"alphaValue\":1},\"previousStyle\":null},\"type\":\"HEATMAP\"}]",
|
||||
"layerListJSON": "[{\"id\":\"0hmz5\",\"sourceDescriptor\":{\"type\":\"EMS_TMS\",\"id\":\"road_map\"},\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"TILE\",\"properties\":{}},\"type\":\"TILE\",\"minZoom\":0,\"maxZoom\":24},{\"id\":\"3xlvm\",\"label\":null,\"minZoom\":0,\"maxZoom\":24,\"sourceDescriptor\":{\"resolution\": \"COARSE\",\"type\":\"ES_GEO_GRID\",\"id\":\"427aa49d-a552-4e7d-a629-67c47db27128\",\"indexPatternId\":\"c698b940-e149-11e8-a35a-370a8516603a\",\"geoField\":\"geo.coordinates\",\"requestType\":\"heatmap\"},\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"HEATMAP\",\"refinement\":\"coarse\",\"properties\":{},\"previousStyle\":null},\"type\":\"HEATMAP\"}]",
|
||||
"mapStateJSON": "{\"zoom\":3.59,\"center\":{\"lon\":-98.05765,\"lat\":38.32288},\"timeFilters\":{\"from\":\"2015-09-20T00:00:00.000Z\",\"to\":\"2015-09-20T01:00:00.000Z\"},\"refreshConfig\":{\"isPaused\":true,\"interval\":1000}}",
|
||||
"title": "geo grid heatmap example",
|
||||
"uiStateJSON": "{\"isDarkMode\":false}"
|
||||
|
@ -248,7 +248,7 @@
|
|||
"type": "envelope"
|
||||
},
|
||||
"description": "",
|
||||
"layerListJSON": "[{\"id\":\"0hmz5\",\"sourceDescriptor\":{\"type\":\"EMS_TMS\",\"id\":\"road_map\"},\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"TILE\",\"properties\":{\"alphaValue\":1}},\"type\":\"TILE\",\"minZoom\":0,\"maxZoom\":24},{\"id\":\"g1xkv\",\"label\":null,\"minZoom\":0,\"maxZoom\":24,\"sourceDescriptor\":{\"resolution\": \"COARSE\",\"type\":\"ES_GEO_GRID\",\"id\":\"9305f6ea-4518-4c06-95b9-33321aa38d6a\",\"indexPatternId\":\"c698b940-e149-11e8-a35a-370a8516603a\",\"geoField\":\"geo.coordinates\",\"requestType\":\"grid\",\"metrics\":[{\"type\":\"count\"},{\"type\":\"max\",\"field\":\"bytes\"}]},\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"fillColor\":{\"type\":\"DYNAMIC\",\"options\":{\"field\":{\"label\":\"max of bytes\",\"name\":\"max_of_bytes\",\"origin\":\"source\"},\"color\":\"Blues\"}},\"lineColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#cccccc\"}},\"lineWidth\":{\"type\":\"STATIC\",\"options\":{\"size\":1}},\"iconSize\":{\"type\":\"DYNAMIC\",\"options\":{\"field\":{\"label\":\"Count\",\"name\":\"doc_count\",\"origin\":\"source\"},\"minSize\":4,\"maxSize\":32}},\"alphaValue\":1},\"temporary\":true,\"previousStyle\":null},\"type\":\"VECTOR\"}]",
|
||||
"layerListJSON": "[{\"id\":\"0hmz5\",\"sourceDescriptor\":{\"type\":\"EMS_TMS\",\"id\":\"road_map\"},\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"TILE\",\"properties\":{}},\"type\":\"TILE\",\"minZoom\":0,\"maxZoom\":24},{\"id\":\"g1xkv\",\"label\":null,\"minZoom\":0,\"maxZoom\":24,\"sourceDescriptor\":{\"resolution\": \"COARSE\",\"type\":\"ES_GEO_GRID\",\"id\":\"9305f6ea-4518-4c06-95b9-33321aa38d6a\",\"indexPatternId\":\"c698b940-e149-11e8-a35a-370a8516603a\",\"geoField\":\"geo.coordinates\",\"requestType\":\"grid\",\"metrics\":[{\"type\":\"count\"},{\"type\":\"max\",\"field\":\"bytes\"}]},\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"fillColor\":{\"type\":\"DYNAMIC\",\"options\":{\"field\":{\"label\":\"max of bytes\",\"name\":\"max_of_bytes\",\"origin\":\"source\"},\"color\":\"Blues\"}},\"lineColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#cccccc\"}},\"lineWidth\":{\"type\":\"STATIC\",\"options\":{\"size\":1}},\"iconSize\":{\"type\":\"DYNAMIC\",\"options\":{\"field\":{\"label\":\"Count\",\"name\":\"doc_count\",\"origin\":\"source\"},\"minSize\":4,\"maxSize\":32}}},\"temporary\":true,\"previousStyle\":null},\"type\":\"VECTOR\"}]",
|
||||
"mapStateJSON": "{\"zoom\":3.59,\"center\":{\"lon\":-98.05765,\"lat\":38.32288},\"timeFilters\":{\"from\":\"2015-09-20T00:00:00.000Z\",\"to\":\"2015-09-20T01:00:00.000Z\"},\"refreshConfig\":{\"isPaused\":true,\"interval\":1000}}",
|
||||
"title": "geo grid vector grid example",
|
||||
"uiStateJSON": "{\"isDarkMode\":false}"
|
||||
|
@ -293,7 +293,7 @@
|
|||
"type": "polygon"
|
||||
},
|
||||
"description": "",
|
||||
"layerListJSON": "[{\"id\":\"0hmz5\",\"sourceDescriptor\":{\"type\":\"EMS_TMS\",\"id\":\"road_map\"},\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"TILE\",\"properties\":{\"alphaValue\":1}},\"type\":\"TILE\",\"minZoom\":0,\"maxZoom\":24},{\"id\":\"frk92\",\"label\":null,\"minZoom\":0,\"maxZoom\":24,\"sourceDescriptor\":{\"id\":\"7d807c75-088a-44b7-920a-e7e47f4fc038\",\"type\":\"ES_SEARCH\",\"indexPatternId\":\"1035e930-1811-11e9-b78a-23d706cd2507\",\"geoField\":\"location\",\"limit\":2048,\"filterByMapBounds\":true,\"tooltipProperties\":[]},\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"fillColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#e6194b\"}},\"lineColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#FFFFFF\"}},\"lineWidth\":{\"type\":\"STATIC\",\"options\":{\"size\":1}},\"iconSize\":{\"type\":\"STATIC\",\"options\":{\"size\":10}},\"alphaValue\":1},\"previousStyle\":null},\"type\":\"VECTOR\"}]",
|
||||
"layerListJSON": "[{\"id\":\"0hmz5\",\"sourceDescriptor\":{\"type\":\"EMS_TMS\",\"id\":\"road_map\"},\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"TILE\",\"properties\":{}},\"type\":\"TILE\",\"minZoom\":0,\"maxZoom\":24},{\"id\":\"frk92\",\"label\":null,\"minZoom\":0,\"maxZoom\":24,\"sourceDescriptor\":{\"id\":\"7d807c75-088a-44b7-920a-e7e47f4fc038\",\"type\":\"ES_SEARCH\",\"indexPatternId\":\"1035e930-1811-11e9-b78a-23d706cd2507\",\"geoField\":\"location\",\"limit\":2048,\"filterByMapBounds\":true,\"tooltipProperties\":[]},\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"fillColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#e6194b\"}},\"lineColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#FFFFFF\"}},\"lineWidth\":{\"type\":\"STATIC\",\"options\":{\"size\":1}},\"iconSize\":{\"type\":\"STATIC\",\"options\":{\"size\":10}}},\"previousStyle\":null},\"type\":\"VECTOR\"}]",
|
||||
"mapStateJSON": "{\"zoom\":8.8,\"center\":{\"lon\":-179.98743,\"lat\":-0.09561},\"timeFilters\":{\"from\":\"now-15m\",\"to\":\"now\",\"mode\":\"quick\"},\"refreshConfig\":{\"isPaused\":true,\"interval\":0},\"query\":{\"query\":\"\",\"language\":\"kuery\"}}",
|
||||
"title": "antimeridian points example",
|
||||
"uiStateJSON": "{\"isDarkMode\":false}"
|
||||
|
@ -338,7 +338,7 @@
|
|||
"type": "polygon"
|
||||
},
|
||||
"description": "",
|
||||
"layerListJSON": "[{\"id\":\"0hmz5\",\"sourceDescriptor\":{\"type\":\"EMS_TMS\",\"id\":\"road_map\"},\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"TILE\",\"properties\":{\"alphaValue\":1}},\"type\":\"TILE\",\"minZoom\":0,\"maxZoom\":24},{\"id\":\"ad9fj\",\"label\":null,\"minZoom\":0,\"maxZoom\":24,\"sourceDescriptor\":{\"id\":\"4e4b5628-dbdc-40bb-93f0-8a7a48be1141\",\"type\":\"ES_SEARCH\",\"indexPatternId\":\"502886a0-18f8-11e9-97c8-5da5e037299c\",\"geoField\":\"location\",\"limit\":2048,\"filterByMapBounds\":true,\"tooltipProperties\":[]},\"visible\":true,\"temporary\":true,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"fillColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#e6194b\"}},\"lineColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#FFFFFF\"}},\"lineWidth\":{\"type\":\"STATIC\",\"options\":{\"size\":1}},\"iconSize\":{\"type\":\"STATIC\",\"options\":{\"size\":10}},\"alphaValue\":1}},\"type\":\"VECTOR\"}]",
|
||||
"layerListJSON": "[{\"id\":\"0hmz5\",\"sourceDescriptor\":{\"type\":\"EMS_TMS\",\"id\":\"road_map\"},\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"TILE\",\"properties\":{}},\"type\":\"TILE\",\"minZoom\":0,\"maxZoom\":24},{\"id\":\"ad9fj\",\"label\":null,\"minZoom\":0,\"maxZoom\":24,\"sourceDescriptor\":{\"id\":\"4e4b5628-dbdc-40bb-93f0-8a7a48be1141\",\"type\":\"ES_SEARCH\",\"indexPatternId\":\"502886a0-18f8-11e9-97c8-5da5e037299c\",\"geoField\":\"location\",\"limit\":2048,\"filterByMapBounds\":true,\"tooltipProperties\":[]},\"visible\":true,\"temporary\":true,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"fillColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#e6194b\"}},\"lineColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#FFFFFF\"}},\"lineWidth\":{\"type\":\"STATIC\",\"options\":{\"size\":1}},\"iconSize\":{\"type\":\"STATIC\",\"options\":{\"size\":10}}}},\"type\":\"VECTOR\"}]",
|
||||
"mapStateJSON": "{\"zoom\":5.65,\"center\":{\"lon\":179.03193,\"lat\":0.09593},\"timeFilters\":{\"from\":\"now-15m\",\"to\":\"now\"},\"refreshConfig\":{\"isPaused\":true,\"interval\":0},\"query\":{\"language\":\"kuery\",\"query\":\"\"}}",
|
||||
"title": "antimeridian shapes example",
|
||||
"uiStateJSON": "{\"isDarkMode\":false}"
|
||||
|
@ -383,7 +383,7 @@
|
|||
"type": "polygon"
|
||||
},
|
||||
"description": "",
|
||||
"layerListJSON" : "[{\"sourceDescriptor\":{\"type\":\"KIBANA_TILEMAP\"},\"id\":\"ap0ys\",\"label\":\"Custom_TMS\",\"minZoom\":0,\"maxZoom\":24,\"alpha\":1,\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"TILE\",\"properties\":{},\"previousStyle\":null},\"type\":\"TILE\"},{\"sourceDescriptor\":{\"type\":\"REGIONMAP_FILE\",\"name\":\"nameThatDoesNotExitForKibanaRegionmapSource\"},\"temporary\":false,\"id\":\"0sabv\",\"label\":\"Custom_vector_shapes\",\"minZoom\":0,\"maxZoom\":24,\"alpha\":0.75,\"visible\":true,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"fillColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#3cb44b\"}},\"lineColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#FFFFFF\"}},\"lineWidth\":{\"type\":\"STATIC\",\"options\":{\"size\":1}},\"iconSize\":{\"type\":\"STATIC\",\"options\":{\"size\":10}}},\"previousStyle\":null},\"type\":\"VECTOR\"},{\"sourceDescriptor\":{\"type\":\"EMS_TMS\",\"id\":\"idThatDoesNotExitForEMSTile\"},\"temporary\":false,\"id\":\"plw9l\",\"label\":\"EMS_tiles\",\"minZoom\":0,\"maxZoom\":24,\"alpha\":1,\"visible\":true,\"style\":{\"type\":\"TILE\",\"properties\":{},\"previousStyle\":null},\"type\":\"TILE\"},{\"sourceDescriptor\":{\"type\":\"EMS_FILE\",\"id\":\"idThatDoesNotExitForEMSFileSource\"},\"temporary\":false,\"id\":\"2gro0\",\"label\":\"EMS_vector_shapes\",\"minZoom\":0,\"maxZoom\":24,\"alpha\":0.75,\"visible\":true,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"fillColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#e6194b\"}},\"lineColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#FFFFFF\"}},\"lineWidth\":{\"type\":\"STATIC\",\"options\":{\"size\":1}},\"iconSize\":{\"type\":\"STATIC\",\"options\":{\"size\":10}}},\"previousStyle\":null},\"type\":\"VECTOR\"},{\"sourceDescriptor\":{\"type\":\"ES_GEO_GRID\",\"id\":\"f67fe707-95dd-46d6-89b8-82617b251b61\",\"indexPatternId\":\"idThatDoesNotExitForESGeoGridSource\",\"geoField\":\"geo.coordinates\",\"requestType\":\"grid\",\"resolution\":\"COARSE\"},\"temporary\":false,\"id\":\"pl5qd\",\"label\":\"\",\"minZoom\":0,\"maxZoom\":24,\"alpha\":0.75,\"visible\":true,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"fillColor\":{\"type\":\"DYNAMIC\",\"options\":{\"field\":{\"label\":\"Count\",\"name\":\"doc_count\",\"origin\":\"source\"},\"color\":\"Blues\"}},\"lineColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#FFFFFF\"}},\"lineWidth\":{\"type\":\"STATIC\",\"options\":{\"size\":1}},\"iconSize\":{\"type\":\"DYNAMIC\",\"options\":{\"field\":{\"label\":\"Count\",\"name\":\"doc_count\",\"origin\":\"source\"},\"minSize\":4,\"maxSize\":32}}},\"previousStyle\":null},\"type\":\"VECTOR\"},{\"sourceDescriptor\":{\"id\":\"a07072bb-3a92-4320-bd37-250ef6d04db7\",\"type\":\"ES_SEARCH\",\"indexPatternId\":\"idThatDoesNotExitForESSearchSource\",\"geoField\":\"geo.coordinates\",\"limit\":2048,\"filterByMapBounds\":true,\"tooltipProperties\":[]},\"temporary\":false,\"id\":\"9bw8h\",\"label\":\"\",\"minZoom\":0,\"maxZoom\":24,\"alpha\":0.75,\"visible\":true,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"fillColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#e6194b\"}},\"lineColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#FFFFFF\"}},\"lineWidth\":{\"type\":\"STATIC\",\"options\":{\"size\":1}},\"iconSize\":{\"type\":\"STATIC\",\"options\":{\"size\":10}}},\"previousStyle\":null},\"type\":\"VECTOR\"},{\"id\":\"n1t6f\",\"label\":null,\"minZoom\":0,\"maxZoom\":24,\"sourceDescriptor\":{\"id\":\"62eca1fc-fe42-11e8-8eb2-f2801f1b9fd1\",\"type\":\"ES_SEARCH\",\"indexPatternId\":\"561253e0-f731-11e8-8487-11b9dd924f96\",\"geoField\":\"geometry\",\"limit\":2048,\"filterByMapBounds\":false,\"showTooltip\":true,\"tooltipProperties\":[]},\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"fillColor\":{\"type\":\"DYNAMIC\",\"options\":{\"field\":{\"label\":\"max(prop1) group by meta_for_geo_shapes*.shape_name\",\"name\":\"__kbnjoin__max_of_prop1_groupby_meta_for_geo_shapes*.shape_name\",\"origin\":\"join\"},\"color\":\"Blues\"}},\"iconSize\":{\"type\":\"STATIC\",\"options\":{\"size\":10}},\"alphaValue\":1},\"temporary\":true,\"previousStyle\":null},\"type\":\"VECTOR\",\"joins\":[{\"leftField\":\"name\",\"right\":{\"id\":\"855ccb86-fe42-11e8-8eb2-f2801f1b9fd1\",\"indexPatternId\":\"idThatDoesNotExitForESJoinSource\",\"indexPatternTitle\":\"meta_for_geo_shapes*\",\"term\":\"shape_name\",\"metrics\":[{\"type\":\"max\",\"field\":\"prop1\"}]}}]}]",
|
||||
"layerListJSON" : "[{\"sourceDescriptor\":{\"type\":\"KIBANA_TILEMAP\"},\"id\":\"ap0ys\",\"label\":\"Custom_TMS\",\"minZoom\":0,\"maxZoom\":24,\"alpha\":1,\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"TILE\",\"properties\":{},\"previousStyle\":null},\"type\":\"TILE\"},{\"sourceDescriptor\":{\"type\":\"REGIONMAP_FILE\",\"name\":\"nameThatDoesNotExitForKibanaRegionmapSource\"},\"temporary\":false,\"id\":\"0sabv\",\"label\":\"Custom_vector_shapes\",\"minZoom\":0,\"maxZoom\":24,\"alpha\":0.75,\"visible\":true,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"fillColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#3cb44b\"}},\"lineColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#FFFFFF\"}},\"lineWidth\":{\"type\":\"STATIC\",\"options\":{\"size\":1}},\"iconSize\":{\"type\":\"STATIC\",\"options\":{\"size\":10}}},\"previousStyle\":null},\"type\":\"VECTOR\"},{\"sourceDescriptor\":{\"type\":\"EMS_TMS\",\"id\":\"idThatDoesNotExitForEMSTile\"},\"temporary\":false,\"id\":\"plw9l\",\"label\":\"EMS_tiles\",\"minZoom\":0,\"maxZoom\":24,\"alpha\":1,\"visible\":true,\"style\":{\"type\":\"TILE\",\"properties\":{},\"previousStyle\":null},\"type\":\"TILE\"},{\"sourceDescriptor\":{\"type\":\"EMS_FILE\",\"id\":\"idThatDoesNotExitForEMSFileSource\"},\"temporary\":false,\"id\":\"2gro0\",\"label\":\"EMS_vector_shapes\",\"minZoom\":0,\"maxZoom\":24,\"alpha\":0.75,\"visible\":true,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"fillColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#e6194b\"}},\"lineColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#FFFFFF\"}},\"lineWidth\":{\"type\":\"STATIC\",\"options\":{\"size\":1}},\"iconSize\":{\"type\":\"STATIC\",\"options\":{\"size\":10}}},\"previousStyle\":null},\"type\":\"VECTOR\"},{\"sourceDescriptor\":{\"type\":\"ES_GEO_GRID\",\"id\":\"f67fe707-95dd-46d6-89b8-82617b251b61\",\"indexPatternId\":\"idThatDoesNotExitForESGeoGridSource\",\"geoField\":\"geo.coordinates\",\"requestType\":\"grid\",\"resolution\":\"COARSE\"},\"temporary\":false,\"id\":\"pl5qd\",\"label\":\"\",\"minZoom\":0,\"maxZoom\":24,\"alpha\":0.75,\"visible\":true,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"fillColor\":{\"type\":\"DYNAMIC\",\"options\":{\"field\":{\"label\":\"Count\",\"name\":\"doc_count\",\"origin\":\"source\"},\"color\":\"Blues\"}},\"lineColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#FFFFFF\"}},\"lineWidth\":{\"type\":\"STATIC\",\"options\":{\"size\":1}},\"iconSize\":{\"type\":\"DYNAMIC\",\"options\":{\"field\":{\"label\":\"Count\",\"name\":\"doc_count\",\"origin\":\"source\"},\"minSize\":4,\"maxSize\":32}}},\"previousStyle\":null},\"type\":\"VECTOR\"},{\"sourceDescriptor\":{\"id\":\"a07072bb-3a92-4320-bd37-250ef6d04db7\",\"type\":\"ES_SEARCH\",\"indexPatternId\":\"idThatDoesNotExitForESSearchSource\",\"geoField\":\"geo.coordinates\",\"limit\":2048,\"filterByMapBounds\":true,\"tooltipProperties\":[]},\"temporary\":false,\"id\":\"9bw8h\",\"label\":\"\",\"minZoom\":0,\"maxZoom\":24,\"alpha\":0.75,\"visible\":true,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"fillColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#e6194b\"}},\"lineColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#FFFFFF\"}},\"lineWidth\":{\"type\":\"STATIC\",\"options\":{\"size\":1}},\"iconSize\":{\"type\":\"STATIC\",\"options\":{\"size\":10}}},\"previousStyle\":null},\"type\":\"VECTOR\"},{\"id\":\"n1t6f\",\"label\":null,\"minZoom\":0,\"maxZoom\":24,\"sourceDescriptor\":{\"id\":\"62eca1fc-fe42-11e8-8eb2-f2801f1b9fd1\",\"type\":\"ES_SEARCH\",\"indexPatternId\":\"561253e0-f731-11e8-8487-11b9dd924f96\",\"geoField\":\"geometry\",\"limit\":2048,\"filterByMapBounds\":false,\"showTooltip\":true,\"tooltipProperties\":[]},\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"fillColor\":{\"type\":\"DYNAMIC\",\"options\":{\"field\":{\"label\":\"max(prop1) group by meta_for_geo_shapes*.shape_name\",\"name\":\"__kbnjoin__max_of_prop1_groupby_meta_for_geo_shapes*.shape_name\",\"origin\":\"join\"},\"color\":\"Blues\"}},\"iconSize\":{\"type\":\"STATIC\",\"options\":{\"size\":10}}},\"temporary\":true,\"previousStyle\":null},\"type\":\"VECTOR\",\"joins\":[{\"leftField\":\"name\",\"right\":{\"id\":\"855ccb86-fe42-11e8-8eb2-f2801f1b9fd1\",\"indexPatternId\":\"idThatDoesNotExitForESJoinSource\",\"indexPatternTitle\":\"meta_for_geo_shapes*\",\"term\":\"shape_name\",\"metrics\":[{\"type\":\"max\",\"field\":\"prop1\"}]}}]}]",
|
||||
"mapStateJSON": "{\"zoom\":0.71,\"center\":{\"lon\":0.10268,\"lat\":0},\"timeFilters\":{\"from\":\"now-7d\",\"to\":\"now\"},\"refreshConfig\":{\"isPaused\":true,\"interval\":0},\"query\":{\"query\":\"\",\"language\":\"kuery\"}}",
|
||||
"title": "layer with errors",
|
||||
"uiStateJSON": "{}"
|
||||
|
|
|
@ -17,6 +17,10 @@ export function GisPageProvider({ getService, getPageObjects }) {
|
|||
const queryBar = getService('queryBar');
|
||||
const comboBox = getService('comboBox');
|
||||
|
||||
function escapeLayerName(layerName) {
|
||||
return layerName.split(' ').join('_');
|
||||
}
|
||||
|
||||
class GisPage {
|
||||
|
||||
constructor() {
|
||||
|
@ -247,16 +251,21 @@ export function GisPageProvider({ getService, getPageObjects }) {
|
|||
}
|
||||
|
||||
async openLayerTocActionsPanel(layerName) {
|
||||
const cleanLayerName = layerName.split(' ').join('');
|
||||
const isOpen = await testSubjects.exists(`layerTocActionsPanel${cleanLayerName}`);
|
||||
const escapedDisplayName = escapeLayerName(layerName);
|
||||
const isOpen = await testSubjects.exists(`layerTocActionsPanel${escapedDisplayName}`);
|
||||
if (!isOpen) {
|
||||
await testSubjects.click(`layerTocActionsPanelToggleButton${cleanLayerName}`);
|
||||
await testSubjects.click(`layerTocActionsPanelToggleButton${escapedDisplayName}`);
|
||||
}
|
||||
}
|
||||
|
||||
async openLayerPanel(layerName) {
|
||||
log.debug(`Open layer panel, layer: ${layerName}`);
|
||||
await testSubjects.click(`mapOpenLayerButton${layerName}`);
|
||||
await this.openLayerTocActionsPanel(layerName);
|
||||
await testSubjects.click('editLayerButton');
|
||||
}
|
||||
|
||||
async getLayerTOCDetails(layerName) {
|
||||
return await testSubjects.getVisibleText(`mapLayerTOCDetails${escapeLayerName(layerName)}`);
|
||||
}
|
||||
|
||||
async disableApplyGlobalQuery() {
|
||||
|
@ -276,9 +285,7 @@ export function GisPageProvider({ getService, getPageObjects }) {
|
|||
}
|
||||
|
||||
async doesLayerExist(layerName) {
|
||||
layerName = layerName.replace(' ', '_');
|
||||
log.debug(`Open layer panel, layer: ${layerName}`);
|
||||
return await testSubjects.exists(`mapOpenLayerButton${layerName}`);
|
||||
return await testSubjects.exists(`layerTocActionsPanelToggleButton${escapeLayerName(layerName)}`);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue