GeomapPanel: Add base types to data layer options (#50053)

* GeomapPanel: Add base types to data layer options

Removed isBaseMap check from data layer filter, which used to remove
base layer types from data layer options. For layer editor, slider to
control opacity is added.

* GeomapPanel: Reorder data layer options

For data layer selection, present user with data layer types first,
before base map layer types. Refactored to consolidate layer options
into a single exported function in registry with a base map boolean.

* GeomapPanel: Add descriptions to base map types

* GeomapPanel: add hideOpacity and apply to markers

* GeomapPanel: update descriptions for map types

Closes #47812
This commit is contained in:
Drew Slobodnjak 2022-06-13 14:07:20 -07:00 committed by GitHub
parent 904b70cfe2
commit 07aa2bbbba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 67 additions and 40 deletions

View File

@ -104,9 +104,9 @@ export interface MapLayerRegistryItem<TConfig = MapLayerOptions> extends Registr
showLocation?: boolean;
/**
* Show transparency controls in UI (for non-basemaps)
* Hide transparency controls in UI
*/
showOpacity?: boolean;
hideOpacity?: boolean;
/**
* Function that configures transformation and returns a transformer

View File

@ -503,6 +503,9 @@ export class GeomapPanel extends Component<Props, State> {
const handler = await item.create(map, options, config.theme2);
const layer = handler.init();
if (options.opacity != null) {
layer.setOpacity(1 - options.opacity);
}
if (!options.name) {
options.name = this.getNextLayerName();

View File

@ -7,11 +7,9 @@ import { AddLayerButton } from 'app/core/components/Layers/AddLayerButton';
import { LayerDragDropList } from 'app/core/components/Layers/LayerDragDropList';
import { GeomapInstanceState } from '../GeomapPanel';
import { geomapLayerRegistry } from '../layers/registry';
import { getLayersOptions } from '../layers/registry';
import { GeomapPanelOptions, MapLayerState } from '../types';
import { dataLayerFilter } from './layerEditor';
type LayersEditorProps = StandardEditorProps<any, any, GeomapPanelOptions, GeomapInstanceState>;
export const LayersEditor = (props: LayersEditorProps) => {
@ -61,7 +59,7 @@ export const LayersEditor = (props: LayersEditorProps) => {
<Container>
<AddLayerButton
onChange={(v) => actions.addlayer(v.value!)}
options={geomapLayerRegistry.selectOptions(undefined, dataLayerFilter).options}
options={getLayersOptions(false).options}
label={'Add layer'}
/>
</Container>

View File

@ -1,14 +1,13 @@
import { get as lodashGet, isEqual } from 'lodash';
import { FrameGeometrySourceMode, MapLayerOptions, MapLayerRegistryItem, PluginState } from '@grafana/data';
import { FrameGeometrySourceMode, MapLayerOptions } from '@grafana/data';
import { NestedPanelOptions, NestedValueAccess } from '@grafana/data/src/utils/OptionsUIBuilders';
import { hasAlphaPanels } from 'app/core/config';
import { setOptionImmutably } from 'app/features/dashboard/components/PanelEditor/utils';
import { addLocationFields } from 'app/features/geo/editor/locationEditor';
import { FrameSelectionEditor } from '../layers/data/FrameSelectionEditor';
import { defaultMarkersConfig } from '../layers/data/markersLayer';
import { DEFAULT_BASEMAP_CONFIG, geomapLayerRegistry } from '../layers/registry';
import { DEFAULT_BASEMAP_CONFIG, geomapLayerRegistry, getLayersOptions } from '../layers/registry';
import { MapLayerState } from '../types';
export interface LayerEditorOptions {
@ -62,11 +61,11 @@ export function getLayerEditor(opts: LayerEditorOptions): NestedPanelOptions<Map
const { handler, options } = opts.state;
const layer = geomapLayerRegistry.getIfExists(options?.type);
const layerTypes = geomapLayerRegistry.selectOptions(
const layerTypes = getLayersOptions(
opts.basemaps,
options?.type // the selected value
? [options.type] // as an array
: [DEFAULT_BASEMAP_CONFIG.type],
opts.basemaps ? baseMapFilter : dataLayerFilter
? options.type
: DEFAULT_BASEMAP_CONFIG.type
);
builder.addSelect({
@ -103,11 +102,19 @@ export function getLayerEditor(opts: LayerEditorOptions): NestedPanelOptions<Map
if (handler.registerOptionsUI) {
handler.registerOptionsUI(builder);
}
if (layer.showOpacity) {
// TODO -- add opacity check
}
if (!isEqual(opts.category, ['Base layer'])) {
if (!layer.hideOpacity) {
builder.addSliderInput({
path: 'opacity',
name: 'Opacity',
defaultValue: 1,
settings: {
min: 0,
max: 1,
step: 0.1,
},
});
}
builder.addBooleanSwitch({
path: 'tooltip',
name: 'Display tooltip',
@ -118,23 +125,3 @@ export function getLayerEditor(opts: LayerEditorOptions): NestedPanelOptions<Map
},
};
}
function baseMapFilter(layer: MapLayerRegistryItem): boolean {
if (!layer.isBaseMap) {
return false;
}
if (layer.state === PluginState.alpha) {
return hasAlphaPanels;
}
return true;
}
export function dataLayerFilter(layer: MapLayerRegistryItem): boolean {
if (layer.isBaseMap) {
return false;
}
if (layer.state === PluginState.alpha) {
return hasAlphaPanels;
}
return true;
}

View File

@ -24,7 +24,8 @@ export const defaultCartoConfig: CartoConfig = {
export const carto: MapLayerRegistryItem<CartoConfig> = {
id: 'carto',
name: 'CARTO reference map',
name: 'CARTO basemap',
description: 'Add layer CARTO Raster basemaps',
isBaseMap: true,
defaultOptions: defaultCartoConfig,

View File

@ -57,6 +57,7 @@ export interface ESRIXYZConfig extends XYZConfig {
export const esriXYZTiles: MapLayerRegistryItem<ESRIXYZConfig> = {
id: 'esri-xyz',
name: 'ArcGIS MapServer',
description: 'Add layer from an ESRI ArcGIS MapServer',
isBaseMap: true,
create: async (map: Map, options: MapLayerOptions<ESRIXYZConfig>, theme: GrafanaTheme2) => {

View File

@ -20,6 +20,7 @@ export const defaultXYZConfig: XYZConfig = {
export const xyzTiles: MapLayerRegistryItem<XYZConfig> = {
id: 'xyz',
name: 'XYZ Tile layer',
description: 'Add map from a generic tile layer',
isBaseMap: true,
create: async (map: Map, options: MapLayerOptions<XYZConfig>, theme: GrafanaTheme2) => ({

View File

@ -7,6 +7,7 @@ import { MapLayerRegistryItem, MapLayerOptions } from '@grafana/data';
export const standard: MapLayerRegistryItem = {
id: 'osm-standard',
name: 'Open Street Map',
description: 'Add map from a collaborative free geographic world database',
isBaseMap: true,
/**

View File

@ -53,6 +53,7 @@ export const markersLayer: MapLayerRegistryItem<MarkersConfig> = {
description: 'Use markers to render each data point',
isBaseMap: false,
showLocation: true,
hideOpacity: true,
/**
* Function that configures transformation and returns a transformer

View File

@ -1,7 +1,14 @@
import Map from 'ol/Map';
import { MapLayerRegistryItem, Registry, MapLayerOptions, GrafanaTheme2 } from '@grafana/data';
import { config } from 'app/core/config';
import {
MapLayerRegistryItem,
Registry,
MapLayerOptions,
GrafanaTheme2,
SelectableValue,
PluginState,
} from '@grafana/data';
import { config, hasAlphaPanels } from 'app/core/config';
import { basemapLayers } from './basemaps';
import { carto } from './basemaps/carto';
@ -42,3 +49,30 @@ export const geomapLayerRegistry = new Registry<MapLayerRegistryItem<any>>(() =>
...basemapLayers, // simple basemaps
...dataLayers, // Layers with update functions
]);
interface RegistrySelectInfo {
options: Array<SelectableValue<string>>;
current: Array<SelectableValue<string>>;
}
function getLayersSelection(items: Array<MapLayerRegistryItem<any>>, current?: string): RegistrySelectInfo {
const res: RegistrySelectInfo = { options: [], current: [] };
for (const layer of items) {
if (layer.state === PluginState.alpha && !hasAlphaPanels) {
continue;
}
const opt = { label: layer.name, value: layer.id, description: layer.description };
res.options.push(opt);
if (layer.id === current) {
res.current.push(opt);
}
}
return res;
}
export function getLayersOptions(basemap: boolean, current?: string): RegistrySelectInfo {
if (basemap) {
return getLayersSelection([defaultBaseLayer, ...basemapLayers], current);
}
return getLayersSelection([...dataLayers, ...basemapLayers], current);
}