Skip to content

Commit

Permalink
[Maps] show vector tile labels on top (#69444) (#70681)
Browse files Browse the repository at this point in the history
* [Maps] show vector tile labels on top

* experiment with new sort algorithm

* clean up

* remove old sort method

* add unit test for sort layer

* tslint

* clean up

* make labelsOnTop configurable

* tslint

* more tslint

* add another test case for single layer move

* clarify should messages

* fix assert not null operators

* review feedback

* update snapshot

Co-authored-by: Elastic Machine <[email protected]>

Co-authored-by: Elastic Machine <[email protected]>
  • Loading branch information
nreese and elasticmachine authored Jul 3, 2020
1 parent 3fd55b2 commit 3546349
Show file tree
Hide file tree
Showing 15 changed files with 577 additions and 295 deletions.
1 change: 1 addition & 0 deletions x-pack/plugins/maps/common/descriptor_types/sources.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ export type LayerDescriptor = {
alpha?: number;
id: string;
label?: string | null;
areLabelsOnTop?: boolean;
minZoom?: number;
maxZoom?: number;
sourceDescriptor: SourceDescriptor | null;
Expand Down
9 changes: 9 additions & 0 deletions x-pack/plugins/maps/public/actions/layer_actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,15 @@ export function updateLayerAlpha(id: string, alpha: number) {
};
}

export function updateLabelsOnTop(id: string, areLabelsOnTop: boolean) {
return {
type: UPDATE_LAYER_PROP,
id,
propName: 'areLabelsOnTop',
newValue: areLabelsOnTop,
};
}

export function setLayerQuery(id: string, query: Query) {
return (dispatch: Dispatch) => {
dispatch({
Expand Down
10 changes: 10 additions & 0 deletions x-pack/plugins/maps/public/classes/layers/layer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ export interface ILayer {
getPrevRequestToken(dataId: string): symbol | undefined;
destroy: () => void;
isPreviewLayer: () => boolean;
areLabelsOnTop: () => boolean;
supportsLabelsOnTop: () => boolean;
}
export type Footnote = {
icon: ReactElement<any>;
Expand Down Expand Up @@ -483,4 +485,12 @@ export class AbstractLayer implements ILayer {
getType(): string | undefined {
return this._descriptor.type;
}

areLabelsOnTop(): boolean {
return false;
}

supportsLabelsOnTop(): boolean {
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -277,4 +277,12 @@ export class VectorTileLayer extends TileLayer {
this._setOpacityForType(mbMap, mbLayer, mbLayerId);
});
}

areLabelsOnTop() {
return !!this._descriptor.areLabelsOnTop;
}

supportsLabelsOnTop() {
return true;
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -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 { AnyAction, Dispatch } from 'redux';
import { connect } from 'react-redux';
import { LayerSettings } from './layer_settings';
import {
updateLayerLabel,
updateLayerMaxZoom,
updateLayerMinZoom,
updateLayerAlpha,
updateLabelsOnTop,
} from '../../../actions';

function mapDispatchToProps(dispatch: Dispatch<AnyAction>) {
return {
updateLabel: (id: string, label: string) => dispatch(updateLayerLabel(id, label)),
updateMinZoom: (id: string, minZoom: number) => dispatch(updateLayerMinZoom(id, minZoom)),
updateMaxZoom: (id: string, maxZoom: number) => dispatch(updateLayerMaxZoom(id, maxZoom)),
updateAlpha: (id: string, alpha: number) => dispatch(updateLayerAlpha(id, alpha)),
updateLabelsOnTop: (id: string, areLabelsOnTop: boolean) =>
dispatch(updateLabelsOnTop(id, areLabelsOnTop)),
};
}

const connectedLayerSettings = connect(null, mapDispatchToProps)(LayerSettings);
export { connectedLayerSettings as LayerSettings };

This file was deleted.

Original file line number Diff line number Diff line change
@@ -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 React, { ChangeEvent, Fragment } from 'react';
import {
EuiTitle,
EuiPanel,
EuiFormRow,
EuiFieldText,
EuiSpacer,
EuiSwitch,
EuiSwitchEvent,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
import { MAX_ZOOM } from '../../../../common/constants';
import { AlphaSlider } from '../../../components/alpha_slider';
import { ValidatedDualRange } from '../../../../../../../src/plugins/kibana_react/public';
import { ILayer } from '../../../classes/layers/layer';

interface Props {
layer: ILayer;
updateLabel: (layerId: string, label: string) => void;
updateMinZoom: (layerId: string, minZoom: number) => void;
updateMaxZoom: (layerId: string, maxZoom: number) => void;
updateAlpha: (layerId: string, alpha: number) => void;
updateLabelsOnTop: (layerId: string, areLabelsOnTop: boolean) => void;
}

export function LayerSettings(props: Props) {
const minVisibilityZoom = props.layer.getMinSourceZoom();
const maxVisibilityZoom = MAX_ZOOM;
const layerId = props.layer.getId();

const onLabelChange = (event: ChangeEvent<HTMLInputElement>) => {
const label = event.target.value;
props.updateLabel(layerId, label);
};

const onZoomChange = (value: [string, string]) => {
props.updateMinZoom(layerId, Math.max(minVisibilityZoom, parseInt(value[0], 10)));
props.updateMaxZoom(layerId, Math.min(maxVisibilityZoom, parseInt(value[1], 10)));
};

const onAlphaChange = (alpha: number) => {
props.updateAlpha(layerId, alpha);
};

const onLabelsOnTopChange = (event: EuiSwitchEvent) => {
props.updateLabelsOnTop(layerId, event.target.checked);
};

const renderZoomSliders = () => {
return (
<ValidatedDualRange
label={i18n.translate('xpack.maps.layerPanel.settingsPanel.visibleZoomLabel', {
defaultMessage: 'Visibility',
})}
formRowDisplay="columnCompressed"
min={minVisibilityZoom}
max={maxVisibilityZoom}
value={[props.layer.getMinZoom(), props.layer.getMaxZoom()]}
showInput="inputWithPopover"
showRange
showLabels
onChange={onZoomChange}
allowEmptyRange={false}
compressed
prepend={i18n.translate('xpack.maps.layerPanel.settingsPanel.visibleZoom', {
defaultMessage: 'Zoom levels',
})}
/>
);
};

const renderLabel = () => {
return (
<EuiFormRow
label={i18n.translate('xpack.maps.layerPanel.settingsPanel.layerNameLabel', {
defaultMessage: 'Name',
})}
display="columnCompressed"
>
<EuiFieldText value={props.layer.getLabel()} onChange={onLabelChange} compressed />
</EuiFormRow>
);
};

const renderShowLabelsOnTop = () => {
if (!props.layer.supportsLabelsOnTop()) {
return null;
}

return (
<EuiFormRow display="columnCompressedSwitch">
<EuiSwitch
label={i18n.translate('xpack.maps.layerPanel.settingsPanel.labelsOnTop', {
defaultMessage: `Show labels on top`,
})}
checked={props.layer.areLabelsOnTop()}
onChange={onLabelsOnTopChange}
data-test-subj="mapLayerPanelApplyGlobalQueryCheckbox"
compressed
/>
</EuiFormRow>
);
};

return (
<Fragment>
<EuiPanel>
<EuiTitle size="xs">
<h5>
<FormattedMessage
id="xpack.maps.layerPanel.layerSettingsTitle"
defaultMessage="Layer settings"
/>
</h5>
</EuiTitle>

<EuiSpacer size="m" />
{renderLabel()}
{renderZoomSliders()}
<AlphaSlider alpha={props.layer.getAlpha()} onChange={onAlphaChange} />
{renderShowLabelsOnTop()}
</EuiPanel>

<EuiSpacer size="s" />
</Fragment>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ export class LayerPanel extends React.Component {
<div className="mapLayerPanel__bodyOverflow">
<LayerErrors />

<LayerSettings />
<LayerSettings layer={selectedLayer} />

{this.props.selectedLayer.renderSourceSettingsEditor({
onChange: this._onSourceChange,
Expand Down
Loading

0 comments on commit 3546349

Please sign in to comment.