diff --git a/.betterer.results b/.betterer.results index d7f730b52c0..c52010d3415 100644 --- a/.betterer.results +++ b/.betterer.results @@ -277,8 +277,7 @@ exports[`better eslint`] = { [0, 0, 0, "Unexpected any. Specify a different type.", "0"] ], "packages/grafana-data/src/geo/layer.ts:5381": [ - [0, 0, 0, "Unexpected any. Specify a different type.", "0"], - [0, 0, 0, "Unexpected any. Specify a different type.", "1"] + [0, 0, 0, "Unexpected any. Specify a different type.", "0"] ], "packages/grafana-data/src/panel/PanelPlugin.test.tsx:5381": [ [0, 0, 0, "Unexpected any. Specify a different type.", "0"], @@ -584,8 +583,7 @@ exports[`better eslint`] = { [0, 0, 0, "Unexpected any. Specify a different type.", "2"], [0, 0, 0, "Unexpected any. Specify a different type.", "3"], [0, 0, 0, "Unexpected any. Specify a different type.", "4"], - [0, 0, 0, "Unexpected any. Specify a different type.", "5"], - [0, 0, 0, "Unexpected any. Specify a different type.", "6"] + [0, 0, 0, "Unexpected any. Specify a different type.", "5"] ], "packages/grafana-data/src/types/variables.ts:5381": [ [0, 0, 0, "Unexpected any. Specify a different type.", "0"] @@ -993,10 +991,14 @@ exports[`better eslint`] = { [0, 0, 0, "Do not use any type assertions.", "3"], [0, 0, 0, "Do not use any type assertions.", "4"] ], + "packages/grafana-schema/src/veneer/common.types.ts:5381": [ + [0, 0, 0, "Unexpected any. Specify a different type.", "0"] + ], "packages/grafana-schema/src/veneer/dashboard.types.ts: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, "Unexpected any. Specify a different type.", "1"], + [0, 0, 0, "Do not use any type assertions.", "2"], + [0, 0, 0, "Do not use any type assertions.", "3"] ], "packages/grafana-toolkit/src/cli/tasks/component.create.ts:5381": [ [0, 0, 0, "Unexpected any. Specify a different type.", "0"], diff --git a/kinds/dashboard/dashboard_kind.cue b/kinds/dashboard/dashboard_kind.cue index 62a905c3dea..d792acc924a 100644 --- a/kinds/dashboard/dashboard_kind.cue +++ b/kinds/dashboard/dashboard_kind.cue @@ -413,7 +413,7 @@ lineage: seqs: [ #MatcherConfig: { id: string | *"" @grafanamaturity(NeedsExpertReview) options?: _ @grafanamaturity(NeedsExpertReview) - } @cuetsy(kind="interface") + } @cuetsy(kind="interface") @grafana(TSVeneer="type") #DynamicConfigValue: { id: string | *"" @grafanamaturity(NeedsExpertReview) diff --git a/packages/grafana-data/src/geo/layer.ts b/packages/grafana-data/src/geo/layer.ts index 6859174ef7c..4ad67866fbb 100644 --- a/packages/grafana-data/src/geo/layer.ts +++ b/packages/grafana-data/src/geo/layer.ts @@ -2,74 +2,23 @@ import { Map as OpenLayersMap } from 'ol'; import BaseLayer from 'ol/layer/Base'; import { ReactNode } from 'react'; +import { MapLayerOptions, FrameGeometrySourceMode } from '@grafana/schema'; + import { EventBus } from '../events'; import { GrafanaTheme2 } from '../themes'; -import { MatcherConfig, PanelData } from '../types'; +import { PanelData } from '../types'; import { PanelOptionsEditorBuilder } from '../utils'; import { RegistryItemWithOptions } from '../utils/Registry'; /** - * @alpha + * @deprecated use the type from schema */ -export enum FrameGeometrySourceMode { - Auto = 'auto', // Will scan fields and find best match - Geohash = 'geohash', - Coords = 'coords', // lon field, lat field - Lookup = 'lookup', // keys > location - // H3 = 'h3', - // WKT = 'wkt, - // geojson? geometry text -} +export { FrameGeometrySourceMode }; /** - * @alpha + * @deprecated use the type from schema */ -export interface FrameGeometrySource { - mode: FrameGeometrySourceMode; - - // Field mappings - geohash?: string; - latitude?: string; - longitude?: string; - h3?: string; - wkt?: string; - lookup?: string; - - // Path to Gazetteer - gazetteer?: string; -} - -/** - * This gets saved in panel json - * - * depending on the type, it may have additional config - * - * This exists in `grafana/data` so the types are well known and extendable but the - * layout/frame is control by the map panel - * - * @alpha - */ -export interface MapLayerOptions { - type: string; - name: string; // configured unique display name - - // Custom options depending on the type - config?: TConfig; - - // Common method to define geometry fields - location?: FrameGeometrySource; - - // Defines which data query refId is associated with the layer - filterData?: MatcherConfig; - - // Common properties: - // https://openlayers.org/en/latest/apidoc/module-ol_layer_Base-BaseLayer.html - // Layer opacity (0-1) - opacity?: number; - - // Check tooltip (defaults to true) - tooltip?: boolean; -} +export type { FrameGeometrySource, MapLayerOptions } from '@grafana/schema'; /** * @alpha @@ -81,7 +30,7 @@ export interface MapLayerHandler { */ update?: (data: PanelData) => void; - /** Optional callback to cleaup before getting removed */ + /** Optional callback for cleanup before getting removed */ dispose?: () => void; /** return react node for the legend */ diff --git a/packages/grafana-data/src/types/transformations.ts b/packages/grafana-data/src/types/transformations.ts index 017a72bfc49..270ec1cbdda 100644 --- a/packages/grafana-data/src/types/transformations.ts +++ b/packages/grafana-data/src/types/transformations.ts @@ -1,3 +1,4 @@ +export type { MatcherConfig } from '@grafana/schema'; import { MonoTypeOperatorFunction } from 'rxjs'; import { RegistryItemWithOptions } from '../utils/Registry'; @@ -80,10 +81,6 @@ export interface ValueMatcherInfo extends RegistryItemWithOption isApplicable: (field: Field) => boolean; getDefaultOptions: (field: Field) => TOptions; } -export interface MatcherConfig { - id: string; - options?: TOptions; -} /** * @public diff --git a/packages/grafana-schema/src/common/common.gen.ts b/packages/grafana-schema/src/common/common.gen.ts index ab3f4bae139..e2f18410125 100644 --- a/packages/grafana-schema/src/common/common.gen.ts +++ b/packages/grafana-schema/src/common/common.gen.ts @@ -40,6 +40,43 @@ export interface DataQuery { refId: string; } +export interface MapLayerOptions { + /** + * Custom options depending on the type + */ + config?: unknown; + /** + * Defines a frame MatcherConfig that may filter data for the given layer + */ + filterData?: unknown; + /** + * Common method to define geometry fields + */ + location?: FrameGeometrySource; + /** + * configured unique display name + */ + name: string; + /** + * Common properties: + * https://openlayers.org/en/latest/apidoc/module-ol_layer_Base-BaseLayer.html + * Layer opacity (0-1) + */ + opacity?: number; + /** + * Check tooltip (defaults to true) + */ + tooltip?: boolean; + type: string; +} + +export enum FrameGeometrySourceMode { + Auto = 'auto', + Coords = 'coords', + Geohash = 'geohash', + Lookup = 'lookup', +} + /** * TODO docs */ @@ -595,6 +632,22 @@ export interface DataSourceRef { uid?: string; } +export interface FrameGeometrySource { + /** + * Path to Gazetteer + */ + gazetteer?: string; + /** + * Field mappings + */ + geohash?: string; + latitude?: string; + longitude?: string; + lookup?: string; + mode: FrameGeometrySourceMode; + wkt?: string; +} + /** * TODO docs */ diff --git a/packages/grafana-schema/src/common/geo.cue b/packages/grafana-schema/src/common/geo.cue new file mode 100644 index 00000000000..cd17654f8f9 --- /dev/null +++ b/packages/grafana-schema/src/common/geo.cue @@ -0,0 +1,33 @@ +package common + +MapLayerOptions: { + type: string + // configured unique display name + name: string + // Custom options depending on the type + config?: _ + // Common method to define geometry fields + location?: FrameGeometrySource + // Defines a frame MatcherConfig that may filter data for the given layer + filterData?: _ + // Common properties: + // https://openlayers.org/en/latest/apidoc/module-ol_layer_Base-BaseLayer.html + // Layer opacity (0-1) + opacity?: int64 + // Check tooltip (defaults to true) + tooltip?: bool +} @cuetsy(kind="interface") @grafana(TSVeneer="type") + +FrameGeometrySourceMode: "auto" | "geohash" |"coords" | "lookup" @cuetsy(kind="enum",memberNames="Auto|Geohash|Coords|Lookup") + +FrameGeometrySource: { + mode: FrameGeometrySourceMode + // Field mappings + geohash?: string + latitude?: string + longitude?: string + wkt?: string + lookup?: string + // Path to Gazetteer + gazetteer?: string +} @cuetsy(kind="interface") diff --git a/packages/grafana-schema/src/common/mudball.cue b/packages/grafana-schema/src/common/mudball.cue index ad648cccb68..d131253af8d 100644 --- a/packages/grafana-schema/src/common/mudball.cue +++ b/packages/grafana-schema/src/common/mudball.cue @@ -1,7 +1,5 @@ package common -// TODO break this up into individual files. Current limitation on this is codegen logic, imports, dependencies - // TODO docs AxisPlacement: "auto" | "top" | "right" | "bottom" | "left" | "hidden" @cuetsy(kind="enum") diff --git a/packages/grafana-schema/src/index.gen.ts b/packages/grafana-schema/src/index.gen.ts index 2fac4368b56..9fdf476a0e4 100644 --- a/packages/grafana-schema/src/index.gen.ts +++ b/packages/grafana-schema/src/index.gen.ts @@ -26,7 +26,6 @@ export type { SpecialValueMap, ValueMappingResult, Transformation, - MatcherConfig, RowPanel, GraphPanel, HeatmapPanel @@ -46,7 +45,6 @@ export { SpecialValueMatch, DashboardCursorSync, defaultDashboardCursorSync, - defaultMatcherConfig, defaultRowPanel } from './raw/dashboard/x/dashboard_types.gen'; @@ -65,6 +63,7 @@ export type { DataSourceRef, Panel, FieldConfigSource, + MatcherConfig, FieldConfig } from './veneer/dashboard.types'; @@ -83,6 +82,7 @@ export { VariableHide, defaultPanel, defaultFieldConfigSource, + defaultMatcherConfig, defaultFieldConfig } from './veneer/dashboard.types'; diff --git a/packages/grafana-schema/src/veneer/common.types.ts b/packages/grafana-schema/src/veneer/common.types.ts index cf65607d001..1e35686cbbe 100644 --- a/packages/grafana-schema/src/veneer/common.types.ts +++ b/packages/grafana-schema/src/veneer/common.types.ts @@ -1,5 +1,13 @@ import * as raw from '../common/common.gen'; +import { MatcherConfig } from './dashboard.types'; + +export interface MapLayerOptions extends raw.MapLayerOptions { + // Custom options depending on the type + config?: TConfig; + filterData?: MatcherConfig; +} + export interface DataQuery extends raw.DataQuery { // TODO remove explicit nulls datasource?: raw.DataSourceRef | null; diff --git a/packages/grafana-schema/src/veneer/dashboard.types.ts b/packages/grafana-schema/src/veneer/dashboard.types.ts index 53b1d22921c..bab4aa4450d 100644 --- a/packages/grafana-schema/src/veneer/dashboard.types.ts +++ b/packages/grafana-schema/src/veneer/dashboard.types.ts @@ -43,6 +43,10 @@ export interface FieldConfigSource> extends r defaults: FieldConfig; } +export interface MatcherConfig extends raw.MatcherConfig { + options?: TConfig; +} + export const defaultDashboard = raw.defaultDashboard as Dashboard; export const defaultVariableModel = { ...raw.defaultVariableModel, @@ -60,3 +64,4 @@ export const defaultVariableModel = { export const defaultPanel: Partial = raw.defaultPanel; export const defaultFieldConfig: Partial = raw.defaultFieldConfig; export const defaultFieldConfigSource: Partial = raw.defaultFieldConfigSource; +export const defaultMatcherConfig: Partial = raw.defaultMatcherConfig; diff --git a/public/app/features/geo/editor/locationEditor.ts b/public/app/features/geo/editor/locationEditor.ts index 5f7d6da044f..a1deb38f8a3 100644 --- a/public/app/features/geo/editor/locationEditor.ts +++ b/public/app/features/geo/editor/locationEditor.ts @@ -1,11 +1,5 @@ -import { - Field, - FieldType, - FrameGeometrySource, - FrameGeometrySourceMode, - PanelOptionsEditorBuilder, - DataFrame, -} from '@grafana/data'; +import { Field, FieldType, PanelOptionsEditorBuilder, DataFrame } from '@grafana/data'; +import { FrameGeometrySource, FrameGeometrySourceMode } from '@grafana/schema'; import { GazetteerPathEditor } from 'app/features/geo/editor/GazetteerPathEditor'; import { LocationModeEditor } from './locationModeEditor'; diff --git a/public/app/features/geo/editor/locationModeEditor.tsx b/public/app/features/geo/editor/locationModeEditor.tsx index 34cc551f4cd..204db9200c9 100644 --- a/public/app/features/geo/editor/locationModeEditor.tsx +++ b/public/app/features/geo/editor/locationModeEditor.tsx @@ -1,14 +1,9 @@ import { css } from '@emotion/css'; import React, { useEffect, useState } from 'react'; -import { - StandardEditorProps, - FrameGeometrySourceMode, - DataFrame, - FrameGeometrySource, - GrafanaTheme2, -} from '@grafana/data'; +import { StandardEditorProps, DataFrame, GrafanaTheme2 } from '@grafana/data'; import { selectors } from '@grafana/e2e-selectors'; +import { FrameGeometrySource, FrameGeometrySourceMode } from '@grafana/schema'; import { Alert, HorizontalGroup, Icon, Select, useStyles2 } from '@grafana/ui'; import { FrameGeometryField, getGeometryField, getLocationMatchers } from '../utils/location'; diff --git a/public/app/features/geo/utils/location.test.ts b/public/app/features/geo/utils/location.test.ts index 18ce5d83b1a..548fa4fd666 100644 --- a/public/app/features/geo/utils/location.test.ts +++ b/public/app/features/geo/utils/location.test.ts @@ -1,7 +1,8 @@ import { Point } from 'ol/geom'; import { toLonLat } from 'ol/proj'; -import { toDataFrame, FieldType, FrameGeometrySourceMode } from '@grafana/data'; +import { toDataFrame, FieldType } from '@grafana/data'; +import { FrameGeometrySourceMode } from '@grafana/schema'; import { getGeometryField, getLocationFields, getLocationMatchers } from './location'; diff --git a/public/app/features/geo/utils/location.ts b/public/app/features/geo/utils/location.ts index 42661776f5a..5c0828a834f 100644 --- a/public/app/features/geo/utils/location.ts +++ b/public/app/features/geo/utils/location.ts @@ -1,8 +1,6 @@ import { Geometry } from 'ol/geom'; import { - FrameGeometrySource, - FrameGeometrySourceMode, FieldMatcher, getFieldMatcher, FieldMatcherID, @@ -11,6 +9,7 @@ import { getFieldDisplayName, FieldType, } from '@grafana/data'; +import { FrameGeometrySource, FrameGeometrySourceMode } from '@grafana/schema'; import { getGeoFieldFromGazetteer, pointFieldFromGeohash, pointFieldFromLonLat } from '../format/utils'; import { getGazetteer, Gazetteer } from '../gazetteer/gazetteer'; diff --git a/public/app/features/transformers/spatial/SpatialTransformerEditor.tsx b/public/app/features/transformers/spatial/SpatialTransformerEditor.tsx index e499d1845e6..7c29bb96faf 100644 --- a/public/app/features/transformers/spatial/SpatialTransformerEditor.tsx +++ b/public/app/features/transformers/spatial/SpatialTransformerEditor.tsx @@ -3,8 +3,6 @@ import React, { useEffect } from 'react'; import { DataTransformerID, - FrameGeometrySource, - FrameGeometrySourceMode, GrafanaTheme2, PanelOptionsEditorBuilder, PluginState, @@ -12,6 +10,7 @@ import { TransformerRegistryItem, TransformerUIProps, } from '@grafana/data'; +import { FrameGeometrySource, FrameGeometrySourceMode } from '@grafana/schema'; import { useTheme2 } from '@grafana/ui'; import { addLocationFields } from 'app/features/geo/editor/locationEditor'; diff --git a/public/app/features/transformers/spatial/models.gen.ts b/public/app/features/transformers/spatial/models.gen.ts index 7b30638ec4c..4def42da1c8 100644 --- a/public/app/features/transformers/spatial/models.gen.ts +++ b/public/app/features/transformers/spatial/models.gen.ts @@ -1,4 +1,4 @@ -import { FrameGeometrySource, FrameGeometrySourceMode } from '@grafana/data'; +import { FrameGeometrySource, FrameGeometrySourceMode } from '@grafana/schema'; // This file should be generated by cue schema diff --git a/public/app/plugins/panel/geomap/GeomapPanel.tsx b/public/app/plugins/panel/geomap/GeomapPanel.tsx index 06ac6b825a6..f4070048c01 100644 --- a/public/app/plugins/panel/geomap/GeomapPanel.tsx +++ b/public/app/plugins/panel/geomap/GeomapPanel.tsx @@ -25,7 +25,7 @@ import { GeomapHoverPayload } from './event'; import { getGlobalStyles } from './globalStyles'; import { defaultMarkersConfig } from './layers/data/markersLayer'; import { DEFAULT_BASEMAP_CONFIG } from './layers/registry'; -import { ControlsOptions, GeomapPanelOptions, MapLayerState, MapViewConfig, TooltipMode } from './types'; +import { ControlsOptions, PanelOptions, MapLayerState, MapViewConfig, TooltipMode } from './types'; import { getActions } from './utils/actions'; import { getLayersExtent } from './utils/getLayersExtent'; import { applyLayerFilter, initLayer } from './utils/layers'; @@ -36,7 +36,7 @@ import { centerPointRegistry, MapCenterID } from './view'; // Allows multiple panels to share the same view instance let sharedView: View | undefined = undefined; -type Props = PanelProps; +type Props = PanelProps; interface State extends OverlayProps { ttip?: GeomapHoverPayload; ttipOpen: boolean; @@ -144,7 +144,7 @@ export class GeomapPanel extends Component { * * NOTE: changes to basemap and layers are handled independently */ - optionsChanged(options: GeomapPanelOptions) { + optionsChanged(options: PanelOptions) { const oldOptions = this.props.options; if (options.view !== oldOptions.view) { const [updatedSharedView, view] = this.initMapView(options.view, sharedView); diff --git a/public/app/plugins/panel/geomap/editor/FitMapViewEditor.tsx b/public/app/plugins/panel/geomap/editor/FitMapViewEditor.tsx index 3c59c095ffb..738e5b238e9 100644 --- a/public/app/plugins/panel/geomap/editor/FitMapViewEditor.tsx +++ b/public/app/plugins/panel/geomap/editor/FitMapViewEditor.tsx @@ -4,13 +4,13 @@ import { SelectableValue, StandardEditorContext } from '@grafana/data'; import { InlineFieldRow, InlineField, RadioButtonGroup, Select } from '@grafana/ui'; import { NumberInput } from 'app/core/components/OptionsUI/NumberInput'; -import { GeomapInstanceState, GeomapPanelOptions, MapViewConfig } from '../types'; +import { GeomapInstanceState, PanelOptions, MapViewConfig } from '../types'; type Props = { labelWidth: number; value: MapViewConfig; onChange: (value?: MapViewConfig | undefined) => void; - context: StandardEditorContext; + context: StandardEditorContext; }; // Data scope options for 'Fit to data' diff --git a/public/app/plugins/panel/geomap/editor/LayersEditor.tsx b/public/app/plugins/panel/geomap/editor/LayersEditor.tsx index 52908a98c6a..db14dc55fe2 100644 --- a/public/app/plugins/panel/geomap/editor/LayersEditor.tsx +++ b/public/app/plugins/panel/geomap/editor/LayersEditor.tsx @@ -7,9 +7,9 @@ import { AddLayerButton } from 'app/core/components/Layers/AddLayerButton'; import { LayerDragDropList } from 'app/core/components/Layers/LayerDragDropList'; import { getLayersOptions } from '../layers/registry'; -import { GeomapPanelOptions, MapLayerState, GeomapInstanceState } from '../types'; +import { PanelOptions, MapLayerState, GeomapInstanceState } from '../types'; -type LayersEditorProps = StandardEditorProps; +type LayersEditorProps = StandardEditorProps; export const LayersEditor = (props: LayersEditorProps) => { const { layers, selected, actions } = props.context.instanceState ?? {}; diff --git a/public/app/plugins/panel/geomap/editor/MapViewEditor.tsx b/public/app/plugins/panel/geomap/editor/MapViewEditor.tsx index 905695d4cdd..749a80b2eec 100644 --- a/public/app/plugins/panel/geomap/editor/MapViewEditor.tsx +++ b/public/app/plugins/panel/geomap/editor/MapViewEditor.tsx @@ -5,7 +5,7 @@ import { StandardEditorProps, SelectableValue } from '@grafana/data'; import { Button, InlineField, InlineFieldRow, Select, VerticalGroup } from '@grafana/ui'; import { NumberInput } from 'app/core/components/OptionsUI/NumberInput'; -import { GeomapPanelOptions, MapViewConfig, GeomapInstanceState } from '../types'; +import { PanelOptions, MapViewConfig, GeomapInstanceState } from '../types'; import { centerPointRegistry, MapCenterID } from '../view'; import { CoordinatesMapViewEditor } from './CoordinatesMapViewEditor'; @@ -15,7 +15,7 @@ export const MapViewEditor = ({ value, onChange, context, -}: StandardEditorProps) => { +}: StandardEditorProps) => { const labelWidth = 10; const views = useMemo(() => { diff --git a/public/app/plugins/panel/geomap/layers/data/photosLayer.tsx b/public/app/plugins/panel/geomap/layers/data/photosLayer.tsx index 208a9bf4020..6a45231d6a3 100644 --- a/public/app/plugins/panel/geomap/layers/data/photosLayer.tsx +++ b/public/app/plugins/panel/geomap/layers/data/photosLayer.tsx @@ -1,14 +1,13 @@ import { MapLayerRegistryItem, - MapLayerOptions, PanelData, GrafanaTheme2, - FrameGeometrySourceMode, EventBus, PluginState, FieldType, Field, } from '@grafana/data'; +import { FrameGeometrySourceMode, MapLayerOptions } from '@grafana/schema'; import Map from 'ol/Map'; import { FeatureLike } from 'ol/Feature'; import { getLocationMatchers } from 'app/features/geo/utils/location'; diff --git a/public/app/plugins/panel/geomap/layers/data/routeLayer.tsx b/public/app/plugins/panel/geomap/layers/data/routeLayer.tsx index 6ae014f2043..0b603506fe7 100644 --- a/public/app/plugins/panel/geomap/layers/data/routeLayer.tsx +++ b/public/app/plugins/panel/geomap/layers/data/routeLayer.tsx @@ -1,9 +1,7 @@ import { MapLayerRegistryItem, - MapLayerOptions, PanelData, GrafanaTheme2, - FrameGeometrySourceMode, PluginState, EventBus, DataHoverEvent, @@ -11,6 +9,12 @@ import { DataFrame, TIME_SERIES_TIME_FIELD_NAME, } from '@grafana/data'; + +import { + MapLayerOptions, + FrameGeometrySourceMode, +} from '@grafana/schema'; + import Map from 'ol/Map'; import { FeatureLike } from 'ol/Feature'; import { Subscription, throttleTime } from 'rxjs'; diff --git a/public/app/plugins/panel/geomap/migrations.ts b/public/app/plugins/panel/geomap/migrations.ts index e7a4d991143..7342d0982e8 100644 --- a/public/app/plugins/panel/geomap/migrations.ts +++ b/public/app/plugins/panel/geomap/migrations.ts @@ -6,7 +6,7 @@ import { ResourceDimensionMode } from 'app/features/dimensions'; import { MarkersConfig } from './layers/data/markersLayer'; import { getMarkerAsPath } from './style/markers'; import { defaultStyleConfig } from './style/types'; -import { GeomapPanelOptions, TooltipMode } from './types'; +import { PanelOptions, TooltipMode } from './types'; import { MapCenterID } from './view'; /** @@ -26,13 +26,13 @@ export const mapPanelChangedHandler: PanelTypeChangedHandler = (panel, prevPlugi return {}; }; -export function worldmapToGeomapOptions(angular: any): { fieldConfig: FieldConfigSource; options: GeomapPanelOptions } { +export function worldmapToGeomapOptions(angular: any): { fieldConfig: FieldConfigSource; options: PanelOptions } { const fieldConfig: FieldConfigSource = { defaults: {}, overrides: [], }; - const options: GeomapPanelOptions = { + const options: PanelOptions = { view: { id: MapCenterID.Zero, }, @@ -107,7 +107,7 @@ function asNumber(v: any): number | undefined { return isNaN(num) ? undefined : num; } -export const mapMigrationHandler = (panel: PanelModel): Partial => { +export const mapMigrationHandler = (panel: PanelModel): Partial => { const pluginVersion = panel?.pluginVersion ?? ''; // before 8.3, only one layer was supported! diff --git a/public/app/plugins/panel/geomap/models.cue b/public/app/plugins/panel/geomap/models.cue new file mode 100644 index 00000000000..d502a796ee4 --- /dev/null +++ b/public/app/plugins/panel/geomap/models.cue @@ -0,0 +1,76 @@ +// Copyright 2023 Grafana Labs +// +// Licensed under the Apache License, Version 2.0 (the "License") +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package grafanaplugin + +import ( + "github.com/grafana/thema" + ui "github.com/grafana/grafana/packages/grafana-schema/src/common" +) + +Panel: thema.#Lineage & { + name: "geomap" + seqs: [ + { + schemas: [ + { + PanelOptions: { + view: MapViewConfig + controls: ControlsOptions + basemap: ui.MapLayerOptions + layers: [...ui.MapLayerOptions] + tooltip: TooltipOptions + } @cuetsy(kind="interface") + + MapViewConfig: { + id: string | *"zero" + lat?: int64 | *0 + lon?: int64 | *0 + zoom?: int64 | *1 + minZoom?: int64 + maxZoom?: int64 + padding?: int64 + allLayers?: bool | *true + lastOnly?: bool + layer?: string + shared?: bool + } @cuetsy(kind="interface") + + ControlsOptions: { + // Zoom (upper left) + showZoom?: bool + // let the mouse wheel zoom + mouseWheelZoom?: bool + // Lower right + showAttribution?: bool + // Scale options + showScale?: bool + // Show debug + showDebug?: bool + // Show measure + showMeasure?: bool + } @cuetsy(kind="interface") + + TooltipOptions: { + mode: TooltipMode + } @cuetsy(kind="interface") + + TooltipMode: "none" | "details" @cuetsy(kind="enum",memberNames="None|Details") + + MapCenterID: "zero"|"coords"|"fit" @cuetsy(kind="enum",members="Zero|Coordinates|Fit") + }, + ] + }, + ] +} diff --git a/public/app/plugins/panel/geomap/models.gen.ts b/public/app/plugins/panel/geomap/models.gen.ts new file mode 100644 index 00000000000..14e35dcc58e --- /dev/null +++ b/public/app/plugins/panel/geomap/models.gen.ts @@ -0,0 +1,89 @@ +// Code generated - EDITING IS FUTILE. DO NOT EDIT. +// +// Generated by: +// public/app/plugins/gen.go +// Using jennies: +// TSTypesJenny +// PluginTSTypesJenny +// +// Run 'make gen-cue' from repository root to regenerate. + +import * as ui from '@grafana/schema'; + +export const PanelModelVersion = Object.freeze([0, 0]); + +export interface PanelOptions { + basemap: ui.MapLayerOptions; + controls: ControlsOptions; + layers: Array; + tooltip: TooltipOptions; + view: MapViewConfig; +} + +export const defaultPanelOptions: Partial = { + layers: [], +}; + +export interface MapViewConfig { + allLayers?: boolean; + id: string; + lastOnly?: boolean; + lat?: number; + layer?: string; + lon?: number; + maxZoom?: number; + minZoom?: number; + padding?: number; + shared?: boolean; + zoom?: number; +} + +export const defaultMapViewConfig: Partial = { + allLayers: true, + id: 'zero', + lat: 0, + lon: 0, + zoom: 1, +}; + +export interface ControlsOptions { + /** + * let the mouse wheel zoom + */ + mouseWheelZoom?: boolean; + /** + * Lower right + */ + showAttribution?: boolean; + /** + * Show debug + */ + showDebug?: boolean; + /** + * Show measure + */ + showMeasure?: boolean; + /** + * Scale options + */ + showScale?: boolean; + /** + * Zoom (upper left) + */ + showZoom?: boolean; +} + +export interface TooltipOptions { + mode: TooltipMode; +} + +export enum TooltipMode { + Details = 'details', + None = 'none', +} + +export enum MapCenterID { + Coords = 'coords', + Fit = 'fit', + Zero = 'zero', +} diff --git a/public/app/plugins/panel/geomap/module.tsx b/public/app/plugins/panel/geomap/module.tsx index 9a9a9e3738d..c03f0289d2f 100644 --- a/public/app/plugins/panel/geomap/module.tsx +++ b/public/app/plugins/panel/geomap/module.tsx @@ -9,9 +9,9 @@ import { LayersEditor } from './editor/LayersEditor'; import { MapViewEditor } from './editor/MapViewEditor'; import { getLayerEditor } from './editor/layerEditor'; import { mapPanelChangedHandler, mapMigrationHandler } from './migrations'; -import { defaultView, GeomapPanelOptions, TooltipMode, GeomapInstanceState } from './types'; +import { defaultMapViewConfig, PanelOptions, TooltipMode, GeomapInstanceState } from './types'; -export const plugin = new PanelPlugin(GeomapPanel) +export const plugin = new PanelPlugin(GeomapPanel) .setNoPadding() .setPanelChangeHandler(mapPanelChangedHandler) .setMigrationHandler(mapMigrationHandler) @@ -29,7 +29,7 @@ export const plugin = new PanelPlugin(GeomapPanel) name: 'Initial view', // don't show it description: 'This location will show when the panel first loads.', editor: MapViewEditor, - defaultValue: defaultView, + defaultValue: defaultMapViewConfig, }); builder.addBooleanSwitch({ @@ -37,7 +37,7 @@ export const plugin = new PanelPlugin(GeomapPanel) path: 'view.shared', description: 'Use the same view across multiple panels. Note: this may require a dashboard reload.', name: 'Share view', - defaultValue: defaultView.shared, + defaultValue: defaultMapViewConfig.shared, }); // eslint-disable-next-line diff --git a/public/app/plugins/panel/geomap/types.ts b/public/app/plugins/panel/geomap/types.ts index 7fbe156bb9d..2a913c8dde5 100644 --- a/public/app/plugins/panel/geomap/types.ts +++ b/public/app/plugins/panel/geomap/types.ts @@ -5,75 +5,13 @@ import BaseLayer from 'ol/layer/Base'; import { Subject } from 'rxjs'; import { MapLayerHandler, MapLayerOptions } from '@grafana/data'; -import { HideableFieldConfig } from '@grafana/schema'; import { LayerElement } from 'app/core/components/Layers/types'; +import { ControlsOptions as ControlsOptionsBase } from './models.gen'; import { StyleConfig } from './style/types'; -import { MapCenterID } from './view'; -export interface ControlsOptions { - // Zoom (upper left) - showZoom?: boolean; - - // let the mouse wheel zoom - mouseWheelZoom?: boolean; - - // Lower right - showAttribution?: boolean; - - // Scale options - showScale?: boolean; +export interface ControlsOptions extends ControlsOptionsBase { scaleUnits?: Units; - - // Show debug - showDebug?: boolean; - - // Show measure - showMeasure?: boolean; -} - -export enum TooltipMode { - None = 'none', - Details = 'details', -} - -export interface TooltipOptions { - mode: TooltipMode; -} - -export interface MapViewConfig { - id: string; // placename > lookup - lat?: number; - lon?: number; - zoom?: number; - minZoom?: number; - maxZoom?: number; - padding?: number; - allLayers?: boolean; - lastOnly?: boolean; - layer?: string; - shared?: boolean; -} - -export const defaultView: MapViewConfig = { - id: MapCenterID.Zero, - lat: 0, - lon: 0, - zoom: 1, - allLayers: true, -}; - -/** Support hide from legend/tooltip */ -export interface GeomapFieldConfig extends HideableFieldConfig { - // nothing custom yet -} - -export interface GeomapPanelOptions { - view: MapViewConfig; - controls: ControlsOptions; - basemap: MapLayerOptions; - layers: MapLayerOptions[]; - tooltip: TooltipOptions; } export interface FeatureStyleConfig { @@ -122,3 +60,5 @@ export interface MapLayerState extends LayerElement { isBasemap?: boolean; mouseEvents: Subject; } + +export { PanelOptions, MapViewConfig, TooltipOptions, TooltipMode, defaultMapViewConfig } from './models.gen'; diff --git a/public/app/plugins/panel/geomap/utils/actions.ts b/public/app/plugins/panel/geomap/utils/actions.ts index 52e4530de49..2461190e154 100644 --- a/public/app/plugins/panel/geomap/utils/actions.ts +++ b/public/app/plugins/panel/geomap/utils/actions.ts @@ -1,6 +1,6 @@ import { cloneDeep } from 'lodash'; -import { FrameGeometrySourceMode } from '@grafana/data/src'; +import { FrameGeometrySourceMode } from '@grafana/schema'; import { GeomapPanel } from '../GeomapPanel'; import { geomapLayerRegistry } from '../layers/registry'; diff --git a/public/app/plugins/panel/geomap/utils/utils.ts b/public/app/plugins/panel/geomap/utils/utils.ts index d920369b7ad..52c978cc30d 100644 --- a/public/app/plugins/panel/geomap/utils/utils.ts +++ b/public/app/plugins/panel/geomap/utils/utils.ts @@ -8,7 +8,7 @@ import { getGrafanaDatasource } from 'app/plugins/datasource/grafana/datasource' import { GeomapPanel } from '../GeomapPanel'; import { defaultStyleConfig, StyleConfig, StyleConfigState, StyleDimensions } from '../style/types'; -import { GeomapPanelOptions, MapLayerState } from '../types'; +import { PanelOptions, MapLayerState } from '../types'; export function getStyleDimension( frame: DataFrame | undefined, @@ -74,7 +74,7 @@ async function initGeojsonFiles() { } } -export const getNewOpenLayersMap = (panel: GeomapPanel, options: GeomapPanelOptions, div: HTMLDivElement) => { +export const getNewOpenLayersMap = (panel: GeomapPanel, options: PanelOptions, div: HTMLDivElement) => { const [view] = panel.initMapView(options.view, undefined); return (panel.map = new OpenLayersMap({ view: view, @@ -88,7 +88,7 @@ export const getNewOpenLayersMap = (panel: GeomapPanel, options: GeomapPanelOpti })); }; -export const updateMap = (panel: GeomapPanel, options: GeomapPanelOptions) => { +export const updateMap = (panel: GeomapPanel, options: PanelOptions) => { panel.initControls(options.controls); panel.forceUpdate(); // first render };