Geomap: refactor and cleanup structures (#52760)

Co-authored-by: Adela Almasan <adela.almasan@grafana.com>
This commit is contained in:
Ryan McKinley 2022-07-25 17:12:20 -07:00 committed by GitHub
parent 7eabd7c83a
commit 238d761450
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 274 additions and 168 deletions

View File

@ -5656,18 +5656,16 @@ exports[`better eslint`] = {
"public/app/features/search/service/bluge.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "Do not use any type assertions.", "1"],
[0, 0, 0, "Do not use any type assertions.", "2"],
[0, 0, 0, "Unexpected any. Specify a different type.", "3"],
[0, 0, 0, "Do not use any type assertions.", "4"],
[0, 0, 0, "Unexpected any. Specify a different type.", "2"],
[0, 0, 0, "Do not use any type assertions.", "3"],
[0, 0, 0, "Unexpected any. Specify a different type.", "4"],
[0, 0, 0, "Do not use any type assertions.", "5"],
[0, 0, 0, "Unexpected any. Specify a different type.", "6"],
[0, 0, 0, "Do not use any type assertions.", "6"],
[0, 0, 0, "Do not use any type assertions.", "7"],
[0, 0, 0, "Do not use any type assertions.", "8"],
[0, 0, 0, "Do not use any type assertions.", "9"],
[0, 0, 0, "Unexpected any. Specify a different type.", "9"],
[0, 0, 0, "Do not use any type assertions.", "10"],
[0, 0, 0, "Unexpected any. Specify a different type.", "11"],
[0, 0, 0, "Do not use any type assertions.", "12"],
[0, 0, 0, "Do not use any type assertions.", "13"]
[0, 0, 0, "Do not use any type assertions.", "11"]
],
"public/app/features/search/service/sql.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
@ -7042,7 +7040,8 @@ exports[`better eslint`] = {
[0, 0, 0, "Do not use any type assertions.", "7"],
[0, 0, 0, "Do not use any type assertions.", "8"],
[0, 0, 0, "Unexpected any. Specify a different type.", "9"],
[0, 0, 0, "Unexpected any. Specify a different type.", "10"]
[0, 0, 0, "Unexpected any. Specify a different type.", "10"],
[0, 0, 0, "Do not use any type assertions.", "11"]
],
"public/app/plugins/datasource/graphite/components/FunctionEditor.tsx:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
@ -8698,6 +8697,19 @@ exports[`better eslint`] = {
"public/app/plugins/panel/geomap/components/DataHoverView.tsx:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
],
"public/app/plugins/panel/geomap/components/MarkersLegend.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "Do not use any type assertions.", "1"],
[0, 0, 0, "Unexpected any. Specify a different type.", "2"],
[0, 0, 0, "Do not use any type assertions.", "3"],
[0, 0, 0, "Do not use any type assertions.", "4"],
[0, 0, 0, "Do not use any type assertions.", "5"],
[0, 0, 0, "Do not use any type assertions.", "6"]
],
"public/app/plugins/panel/geomap/editor/FrameSelectionEditor.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "Do not use any type assertions.", "1"]
],
"public/app/plugins/panel/geomap/editor/GeomapStyleRulesEditor.tsx:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],
@ -8716,6 +8728,35 @@ exports[`better eslint`] = {
"public/app/plugins/panel/geomap/editor/MapViewEditor.tsx:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
],
"public/app/plugins/panel/geomap/editor/StyleEditor.tsx:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
[0, 0, 0, "Do not use any type assertions.", "1"],
[0, 0, 0, "Do not use any type assertions.", "2"],
[0, 0, 0, "Do not use any type assertions.", "3"],
[0, 0, 0, "Unexpected any. Specify a different type.", "4"],
[0, 0, 0, "Do not use any type assertions.", "5"],
[0, 0, 0, "Unexpected any. Specify a different type.", "6"],
[0, 0, 0, "Do not use any type assertions.", "7"],
[0, 0, 0, "Unexpected any. Specify a different type.", "8"],
[0, 0, 0, "Do not use any type assertions.", "9"],
[0, 0, 0, "Unexpected any. Specify a different type.", "10"],
[0, 0, 0, "Do not use any type assertions.", "11"],
[0, 0, 0, "Unexpected any. Specify a different type.", "12"],
[0, 0, 0, "Do not use any type assertions.", "13"],
[0, 0, 0, "Unexpected any. Specify a different type.", "14"],
[0, 0, 0, "Do not use any type assertions.", "15"],
[0, 0, 0, "Unexpected any. Specify a different type.", "16"],
[0, 0, 0, "Do not use any type assertions.", "17"],
[0, 0, 0, "Unexpected any. Specify a different type.", "18"],
[0, 0, 0, "Do not use any type assertions.", "19"],
[0, 0, 0, "Unexpected any. Specify a different type.", "20"],
[0, 0, 0, "Do not use any type assertions.", "21"],
[0, 0, 0, "Unexpected any. Specify a different type.", "22"],
[0, 0, 0, "Do not use any type assertions.", "23"],
[0, 0, 0, "Unexpected any. Specify a different type.", "24"],
[0, 0, 0, "Do not use any type assertions.", "25"],
[0, 0, 0, "Unexpected any. Specify a different type.", "26"]
],
"public/app/plugins/panel/geomap/editor/StyleRuleEditor.tsx:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],

View File

@ -12,7 +12,7 @@ export interface DimensionSupplier<T = any> {
isAssumed?: boolean;
/**
* The fied used for
* The field used for
*/
field?: Field;

View File

@ -1,9 +1,9 @@
import { lastValueFrom } from 'rxjs';
import { ArrayVector, DataFrame, DataFrameView, getDisplayProcessor, SelectableValue } from '@grafana/data';
import { config, getDataSourceSrv } from '@grafana/runtime';
import { config } from '@grafana/runtime';
import { TermCount } from 'app/core/components/TagFilter/TagFilter';
import { GrafanaDatasource } from 'app/plugins/datasource/grafana/datasource';
import { getGrafanaDatasource } from 'app/plugins/datasource/grafana/datasource';
import { GrafanaQueryType } from 'app/plugins/datasource/grafana/types';
import { replaceCurrentFolderQuery } from './utils';
@ -19,7 +19,7 @@ export class BlugeSearcher implements GrafanaSearcher {
}
async tags(query: SearchQuery): Promise<TermCount[]> {
const ds = (await getDataSourceSrv().get('-- Grafana --')) as GrafanaDatasource;
const ds = await getGrafanaDatasource();
const target = {
refId: 'TagsQuery',
queryType: GrafanaQueryType.Search,
@ -74,7 +74,7 @@ const nextPageSizes = 100;
async function doSearchQuery(query: SearchQuery): Promise<QueryResponse> {
query = await replaceCurrentFolderQuery(query);
const ds = (await getDataSourceSrv().get('-- Grafana --')) as GrafanaDatasource;
const ds = await getGrafanaDatasource();
const target = {
refId: 'Search',
queryType: GrafanaQueryType.Search,

View File

@ -18,6 +18,7 @@ import {
import {
DataSourceWithBackend,
getBackendSrv,
getDataSourceSrv,
getGrafanaLiveSrv,
getTemplateSrv,
StreamingFrameOptions,
@ -211,6 +212,11 @@ export class GrafanaDatasource extends DataSourceWithBackend<GrafanaQuery> {
}
}
/** Get the GrafanaDatasource instance */
export async function getGrafanaDatasource() {
return (await getDataSourceSrv().get('-- Grafana --')) as GrafanaDatasource;
}
export interface FileElement {
name: string;
['media-type']: string;

View File

@ -1,18 +1,20 @@
import React, { useMemo } from 'react';
import { useStyles2, VizLegendItem } from '@grafana/ui';
import { DataFrame, formattedValueToString, getFieldColorModeForField, GrafanaTheme2 } from '@grafana/data';
import { css, cx } from '@emotion/css';
import BaseLayer from 'ol/layer/Base';
import React, { useMemo } from 'react';
import SVG from 'react-inlinesvg';
import { useObservable } from 'react-use';
import { of } from 'rxjs';
import { DataFrame, formattedValueToString, getFieldColorModeForField, GrafanaTheme2 } from '@grafana/data';
import { getMinMaxAndDelta } from '@grafana/data/src/field/scale';
import { useStyles2, VizLegendItem } from '@grafana/ui';
import { ColorScale } from 'app/core/components/ColorScale/ColorScale';
import { config } from 'app/core/config';
import { DimensionSupplier } from 'app/features/dimensions';
import { getThresholdItems } from 'app/plugins/panel/state-timeline/utils';
import { getMinMaxAndDelta } from '@grafana/data/src/field/scale';
import SVG from 'react-inlinesvg';
import { StyleConfigState } from '../../style/types';
import { ColorScale } from 'app/core/components/ColorScale/ColorScale';
import { useObservable } from 'react-use';
import { of } from 'rxjs';
import BaseLayer from 'ol/layer/Base';
import { MapLayerState } from '../../types';
import { StyleConfigState } from '../style/types';
import { MapLayerState } from '../types';
export interface MarkersLegendProps {
size?: DimensionSupplier<number>;
@ -48,7 +50,7 @@ export function MarkersLegend(props: MarkersLegendProps) {
return <></>;
}
const { color, opacity} = styleConfig?.base ?? {};
const { color, opacity } = styleConfig?.base ?? {};
const symbol = styleConfig?.config.symbol?.fixed;
if (color && symbol && !colorField) {
@ -64,7 +66,7 @@ export function MarkersLegend(props: MarkersLegendProps) {
/>
</div>
</div>
)
);
}
if (!colorField) {
@ -87,12 +89,21 @@ export function MarkersLegend(props: MarkersLegendProps) {
// ]
// })
const display = colorField.display ? (v: number) => formattedValueToString(colorField.display!(v)) : (v: number) => `${v}`;
const display = colorField.display
? (v: number) => formattedValueToString(colorField.display!(v))
: (v: number) => `${v}`;
return (
<div className={style.infoWrap}>
<div className={style.layerName}>{layerName}</div>
<div className={cx(style.layerBody, style.colorScaleWrapper)}>
<ColorScale hoverValue={hoverValue} colorPalette={colors} min={colorRange.min as number} max={colorRange.max as number} display={display} useStopsPercentage={false}/>
<ColorScale
hoverValue={hoverValue}
colorPalette={colors}
min={colorRange.min as number}
max={colorRange.max as number}
display={display}
useStopsPercentage={false}
/>
</div>
</div>
);

View File

@ -0,0 +1,84 @@
import React, { FC, useCallback, useMemo, useState } from 'react';
import {
FrameMatcherID,
getFieldDisplayName,
MatcherConfig,
SelectableValue,
StandardEditorProps,
} from '@grafana/data';
import { Select } from '@grafana/ui';
const recoverRefIdMissing = (
newRefIds: SelectableValue[],
oldRefIds: SelectableValue[],
previousValue: string | undefined
): SelectableValue | undefined => {
if (!previousValue) {
return;
}
// Previously selected value is missing from the new list.
// Find the value that is in the new list but isn't in the old list
let changedTo = newRefIds.find((refId) => {
return !oldRefIds.some((refId2) => {
return refId === refId2;
});
});
if (changedTo) {
// Found the new value, we assume the old value changed to this one, so we'll use it
return changedTo;
}
return;
};
export const FrameSelectionEditor: FC<StandardEditorProps<MatcherConfig>> = ({ value, context, onChange, item }) => {
const listOfRefId = useMemo(() => {
return context.data.map((f) => ({
value: f.refId,
label: `Query: ${f.refId} (size: ${f.length})`,
description: f.fields.map((f) => getFieldDisplayName(f)).join(', '),
}));
}, [context.data]);
const [priorSelectionState, updatePriorSelectionState] = useState({
refIds: [] as SelectableValue[],
value: undefined as string | undefined,
});
const currentValue = useMemo(() => {
return (
listOfRefId.find((refId) => refId.value === value?.options) ??
recoverRefIdMissing(listOfRefId, priorSelectionState.refIds, priorSelectionState.value)
);
}, [value, listOfRefId, priorSelectionState]);
const onFilterChange = useCallback(
(v: SelectableValue<string>) => {
onChange(
v?.value
? {
id: FrameMatcherID.byRefId,
options: v.value,
}
: undefined
);
},
[onChange]
);
if (listOfRefId !== priorSelectionState.refIds || currentValue?.value !== priorSelectionState.value) {
updatePriorSelectionState({
refIds: listOfRefId,
value: currentValue?.value,
});
}
return (
<Select
options={listOfRefId}
onChange={onFilterChange}
isClearable={true}
placeholder="Change filter"
value={currentValue}
/>
);
};

View File

@ -1,4 +1,8 @@
import { capitalize } from 'lodash';
import React, { FC } from 'react';
import { useObservable } from 'react-use';
import { Observable, of } from 'rxjs';
import { StandardEditorProps } from '@grafana/data';
import {
ColorPicker,
@ -9,10 +13,8 @@ import {
InlineLabel,
RadioButtonGroup,
} from '@grafana/ui';
import { Observable } from 'rxjs';
import { useObservable } from 'react-use';
import { capitalize } from 'lodash';
import { NumberValueEditor } from 'app/core/components/OptionsUI/number';
import { SliderValueEditor } from 'app/core/components/OptionsUI/slider';
import {
ColorDimensionEditor,
ResourceDimensionEditor,
@ -29,11 +31,10 @@ import {
defaultTextConfig,
ScalarDimensionConfig,
} from 'app/features/dimensions/types';
import { defaultStyleConfig, GeometryTypeId, StyleConfig, TextAlignment, TextBaseline } from '../../style/types';
import { styleUsesText } from '../../style/utils';
import { LayerContentInfo } from '../../utils/getFeatures';
import { NumberValueEditor } from 'app/core/components/OptionsUI/number';
import { SliderValueEditor } from 'app/core/components/OptionsUI/slider';
import { defaultStyleConfig, GeometryTypeId, StyleConfig, TextAlignment, TextBaseline } from '../style/types';
import { styleUsesText } from '../style/utils';
import { LayerContentInfo } from '../utils/getFeatures';
export interface StyleEditorOptions {
layerInfo?: Observable<LayerContentInfo>;
@ -93,11 +94,8 @@ export const StyleEditor: FC<StandardEditorProps<StyleConfig, StyleEditorOptions
onChange({ ...value, textConfig: { ...value.textConfig, textBaseline: textBaseline as TextBaseline } });
};
let featuresHavePoints = false;
if (settings?.layerInfo) {
const propertyOptions = useObservable(settings?.layerInfo);
featuresHavePoints = propertyOptions?.geometryType === GeometryTypeId.Point;
}
const propertyOptions = useObservable(settings?.layerInfo ?? of());
const featuresHavePoints = propertyOptions?.geometryType === GeometryTypeId.Point;
const hasTextLabel = styleUsesText(value);
// Simple fixed value display

View File

@ -8,13 +8,14 @@ import { GrafanaTheme2, SelectableValue, StandardEditorProps } from '@grafana/da
import { Button, InlineField, InlineFieldRow, Select, useStyles2 } from '@grafana/ui';
import { NumberInput } from 'app/core/components/OptionsUI/NumberInput';
import { StyleEditor } from '../layers/data/StyleEditor';
import { DEFAULT_STYLE_RULE } from '../layers/data/geojsonLayer';
import { defaultStyleConfig, StyleConfig } from '../style/types';
import { ComparisonOperation, FeatureStyleConfig } from '../types';
import { getUniqueFeatureValues, LayerContentInfo } from '../utils/getFeatures';
import { getSelectionInfo } from '../utils/selection';
import { StyleEditor } from './StyleEditor';
export interface StyleRuleEditorSettings {
features: Observable<FeatureLike[]>;
layerInfo: Observable<LayerContentInfo>;

View File

@ -5,11 +5,12 @@ import { NestedPanelOptions, NestedValueAccess } from '@grafana/data/src/utils/O
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, getLayersOptions } from '../layers/registry';
import { MapLayerState } from '../types';
import { FrameSelectionEditor } from './FrameSelectionEditor';
export interface LayerEditorOptions {
state: MapLayerState;
category: string[];

View File

@ -1,62 +0,0 @@
import React, { FC, useCallback, useMemo, useState } from 'react';
import { FrameMatcherID, getFieldDisplayName, MatcherConfig, SelectableValue, StandardEditorProps } from '@grafana/data';
import { Select } from '@grafana/ui';
const recoverRefIdMissing = (newRefIds: SelectableValue[], oldRefIds: SelectableValue[], previousValue: string | undefined): SelectableValue | undefined => {
if (!previousValue) {
return;
}
// Previously selected value is missing from the new list.
// Find the value that is in the new list but isn't in the old list
let changedTo = newRefIds.find((refId) => {
return !oldRefIds.some((refId2) => {
return refId === refId2;
});
});
if (changedTo) {
// Found the new value, we assume the old value changed to this one, so we'll use it
return changedTo;
}
return;
};
export const FrameSelectionEditor: FC<StandardEditorProps<MatcherConfig>> = ({
value,
context,
onChange,
item,
}) => {
const listOfRefId = useMemo(() => {
return context.data.map(f => ({
value: f.refId,
label: `Query: ${f.refId} (size: ${f.length})`,
description: f.fields.map(f => getFieldDisplayName(f)).join(', '),
}));
}, [context.data]);
const [priorSelectionState, updatePriorSelectionState] = useState({
refIds: [] as SelectableValue[],
value: undefined as string | undefined,
});
const currentValue = useMemo(() => {
return listOfRefId.find((refId) => refId.value === value?.options) ?? recoverRefIdMissing(listOfRefId, priorSelectionState.refIds, priorSelectionState.value);
}, [value, listOfRefId])
const onFilterChange = useCallback((v: SelectableValue<string>) => {
onChange(v?.value ? {
"id": FrameMatcherID.byRefId,
"options": v.value
} : undefined);
}, [context.options.name]);
if (listOfRefId !== priorSelectionState.refIds || currentValue?.value !== priorSelectionState.value) {
updatePriorSelectionState({
refIds: listOfRefId,
value: currentValue?.value
});
}
return (
<Select options={listOfRefId} onChange={onFilterChange} isClearable={true} placeholder="Change filter" value={currentValue}/>
);
};

View File

@ -1,10 +1,8 @@
import {
MapLayerRegistryItem,
MapLayerOptions,
PanelData,
GrafanaTheme2,
PluginState,
SelectableValue,
EventBus,
} from '@grafana/data';
import Map from 'ol/Map';
@ -20,12 +18,11 @@ import { GeomapStyleRulesEditor } from '../../editor/GeomapStyleRulesEditor';
import { defaultStyleConfig, StyleConfig, StyleConfigState } from '../../style/types';
import { getStyleConfigState } from '../../style/utils';
import { polyStyle } from '../../style/markers';
import { StyleEditor } from './StyleEditor';
import { StyleEditor } from '../../editor/StyleEditor';
import { ReplaySubject } from 'rxjs';
import { map as rxjsmap, first } from 'rxjs/operators';
import { getLayerPropertyInfo } from '../../utils/getFeatures';
import { GrafanaDatasource } from 'app/plugins/datasource/grafana/datasource';
import { getDataSourceSrv } from '@grafana/runtime';
import { getPublicGeoJSONFiles } from '../../utils/utils';
export interface GeoJSONMapperConfig {
// URL for a geojson file
@ -60,8 +57,6 @@ export const DEFAULT_STYLE_RULE: FeatureStyleConfig = {
},
};
let publicGeoJSONFiles: Array<SelectableValue<string>> | undefined = undefined;
export const geojsonLayer: MapLayerRegistryItem<GeoJSONMapperConfig> = {
id: 'geojson',
name: 'GeoJSON',
@ -153,9 +148,6 @@ export const geojsonLayer: MapLayerRegistryItem<GeoJSONMapperConfig> = {
return {
init: () => vectorLayer,
update: (data: PanelData) => {
console.log('todo... find values matching the ID and update');
},
registerOptionsUI: (builder) => {
// get properties for first feature to use as ui options
const layerInfo = features.pipe(
@ -163,16 +155,12 @@ export const geojsonLayer: MapLayerRegistryItem<GeoJSONMapperConfig> = {
rxjsmap((v) => getLayerPropertyInfo(v))
);
if (!publicGeoJSONFiles) {
initGeojsonFiles();
}
builder
.addSelect({
path: 'config.src',
name: 'GeoJSON URL',
settings: {
options: publicGeoJSONFiles ?? [],
options: getPublicGeoJSONFiles() ?? [],
allowCustomValue: true,
},
defaultValue: defaultOptions.src,
@ -207,27 +195,3 @@ export const geojsonLayer: MapLayerRegistryItem<GeoJSONMapperConfig> = {
defaultOptions,
};
// This will find all geojson files in the maps and gazetteer folders
async function initGeojsonFiles() {
if (publicGeoJSONFiles) {
return;
}
publicGeoJSONFiles = [];
const ds = (await getDataSourceSrv().get('-- Grafana --')) as GrafanaDatasource;
for (let folder of ['maps', 'gazetteer']) {
ds.listFiles(folder).subscribe({
next: (frame) => {
frame.forEach((item) => {
if (item.name.endsWith('.geojson')) {
const value = `public/${folder}/${item.name}`;
publicGeoJSONFiles!.push({
value,
label: value,
});
}
});
},
});
}
}

View File

@ -8,4 +8,11 @@ import { dayNightLayer } from './dayNightLayer';
/**
* Registry for layer handlers
*/
export const dataLayers = [markersLayer, heatmapLayer, lastPointTracker, geojsonLayer, dayNightLayer, routeLayer];
export const dataLayers = [
markersLayer,
heatmapLayer,
lastPointTracker,
geojsonLayer,
dayNightLayer,
routeLayer,
];

View File

@ -10,16 +10,16 @@ import {
import Map from 'ol/Map';
import { FeatureLike } from 'ol/Feature';
import { getLocationMatchers } from 'app/features/geo/utils/location';
import { getScaledDimension, getColorDimension, getTextDimension, getScalarDimension } from 'app/features/dimensions';
import { ObservablePropsWrapper } from '../../components/ObservablePropsWrapper';
import { MarkersLegend, MarkersLegendProps } from './MarkersLegend';
import { MarkersLegend, MarkersLegendProps } from '../../components/MarkersLegend';
import { ReplaySubject } from 'rxjs';
import { defaultStyleConfig, StyleConfig, StyleDimensions } from '../../style/types';
import { StyleEditor } from './StyleEditor';
import { defaultStyleConfig, StyleConfig } from '../../style/types';
import { StyleEditor } from '../../editor/StyleEditor';
import { getStyleConfigState } from '../../style/utils';
import VectorLayer from 'ol/layer/Vector';
import { isNumber } from 'lodash';
import { FrameVectorSource } from 'app/features/geo/utils/frameVectorSource';
import { getStyleDimension} from '../../utils/utils';
// Configuration options for Circle overlays
export interface MarkersConfig {
@ -121,22 +121,7 @@ export const markersLayer: MapLayerRegistryItem<MarkersConfig> = {
}
for (const frame of data.series) {
if (style.fields) {
const dims: StyleDimensions = {};
if (style.fields.color) {
dims.color = getColorDimension(frame, style.config.color ?? defaultStyleConfig.color, theme);
}
if (style.fields.size) {
dims.size = getScaledDimension(frame, style.config.size ?? defaultStyleConfig.size);
}
if (style.fields.text) {
dims.text = getTextDimension(frame, style.config.text!);
}
if (style.fields.rotation) {
dims.rotation = getScalarDimension(frame, style.config.rotation ?? defaultStyleConfig.rotation);
}
style.dims = dims;
}
style.dims = getStyleDimension(frame, style, theme);
// Post updates to the legend component
if (legend) {

View File

@ -17,7 +17,7 @@ import { Subscription, throttleTime } from 'rxjs';
import { getGeometryField, getLocationMatchers } from 'app/features/geo/utils/location';
import { getColorDimension } from 'app/features/dimensions';
import { defaultStyleConfig, StyleConfig, StyleDimensions } from '../../style/types';
import { StyleEditor } from './StyleEditor';
import { StyleEditor } from '../../editor/StyleEditor';
import { getStyleConfigState } from '../../style/utils';
import VectorLayer from 'ol/layer/Vector';
import { isNumber } from 'lodash';

View File

@ -0,0 +1,70 @@
import { SelectableValue } from '@grafana/data';
import { DataFrame, GrafanaTheme2 } from '@grafana/data/src';
import { getColorDimension, getScalarDimension, getScaledDimension, getTextDimension } from 'app/features/dimensions';
import { getGrafanaDatasource } from 'app/plugins/datasource/grafana/datasource';
import { defaultStyleConfig, StyleConfig, StyleConfigState, StyleDimensions } from '../style/types';
export function getStyleDimension(
frame: DataFrame | undefined,
style: StyleConfigState,
theme: GrafanaTheme2,
customStyleConfig?: StyleConfig
) {
const dims: StyleDimensions = {};
if (customStyleConfig && Object.keys(customStyleConfig).length) {
dims.color = getColorDimension(frame, customStyleConfig.color ?? defaultStyleConfig.color, theme);
dims.size = getScaledDimension(frame, customStyleConfig.size ?? defaultStyleConfig.size);
dims.rotation = getScalarDimension(frame, customStyleConfig.rotation ?? defaultStyleConfig.rotation);
if (customStyleConfig.text && (customStyleConfig.text.field || customStyleConfig.text.fixed)) {
dims.text = getTextDimension(frame, customStyleConfig.text!);
}
} else {
if (style.fields) {
if (style.fields.color) {
dims.color = getColorDimension(frame, style.config.color ?? defaultStyleConfig.color, theme);
}
if (style.fields.size) {
dims.size = getScaledDimension(frame, style.config.size ?? defaultStyleConfig.size);
}
if (style.fields.text) {
dims.text = getTextDimension(frame, style.config.text!);
}
if (style.fields.rotation) {
dims.rotation = getScalarDimension(frame, style.config.rotation ?? defaultStyleConfig.rotation);
}
}
}
return dims;
}
let publicGeoJSONFiles: Array<SelectableValue<string>> | undefined = undefined;
export function getPublicGeoJSONFiles(): Array<SelectableValue<string>> {
if (!publicGeoJSONFiles) {
publicGeoJSONFiles = [];
initGeojsonFiles(); // async
}
return publicGeoJSONFiles;
}
// This will find all geojson files in the maps and gazetteer folders
async function initGeojsonFiles() {
const ds = await getGrafanaDatasource();
for (let folder of ['maps', 'gazetteer']) {
ds.listFiles(folder).subscribe({
next: (frame) => {
frame.forEach((item) => {
if (item.name.endsWith('.geojson')) {
const value = `public/${folder}/${item.name}`;
publicGeoJSONFiles!.push({
value,
label: value,
});
}
});
},
});
}
}