mirror of
https://github.com/grafana/grafana.git
synced 2024-11-24 09:50:29 -06:00
Geomap: cleanup (#54328)
This commit is contained in:
parent
0707d682e0
commit
3be3b02f59
@ -8291,26 +8291,19 @@ exports[`better eslint`] = {
|
||||
[0, 0, 0, "Do not use any type assertions.", "2"],
|
||||
[0, 0, 0, "Do not use any type assertions.", "3"],
|
||||
[0, 0, 0, "Do not use any type assertions.", "4"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "5"],
|
||||
[0, 0, 0, "Do not use any type assertions.", "5"],
|
||||
[0, 0, 0, "Do not use any type assertions.", "6"],
|
||||
[0, 0, 0, "Do not use any type assertions.", "7"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "8"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "7"],
|
||||
[0, 0, 0, "Do not use any type assertions.", "8"],
|
||||
[0, 0, 0, "Do not use any type assertions.", "9"],
|
||||
[0, 0, 0, "Do not use any type assertions.", "10"],
|
||||
[0, 0, 0, "Do not use any type assertions.", "11"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "12"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "13"],
|
||||
[0, 0, 0, "Do not use any type assertions.", "14"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "15"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "16"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "17"]
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "11"],
|
||||
[0, 0, 0, "Do not use any type assertions.", "12"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "13"]
|
||||
],
|
||||
"public/app/plugins/panel/geomap/components/DataHoverRows.tsx:5381": [
|
||||
[0, 0, 0, "Do not use any type assertions.", "0"]
|
||||
],
|
||||
"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"],
|
||||
@ -8331,21 +8324,8 @@ exports[`better eslint`] = {
|
||||
],
|
||||
"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"],
|
||||
[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"]
|
||||
],
|
||||
"public/app/plugins/panel/geomap/editor/LayersEditor.tsx: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.", "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"]
|
||||
],
|
||||
"public/app/plugins/panel/geomap/editor/MapViewEditor.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, "Unexpected any. Specify a different type.", "2"]
|
||||
],
|
||||
"public/app/plugins/panel/geomap/editor/StyleEditor.tsx:5381": [
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
|
||||
@ -8378,12 +8358,8 @@ exports[`better eslint`] = {
|
||||
],
|
||||
"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"],
|
||||
[0, 0, 0, "Do not use any type assertions.", "2"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "3"]
|
||||
],
|
||||
"public/app/plugins/panel/geomap/editor/layerEditor.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, "Unexpected any. Specify a different type.", "2"]
|
||||
],
|
||||
"public/app/plugins/panel/geomap/layers/basemaps/carto.ts:5381": [
|
||||
[0, 0, 0, "Do not use any type assertions.", "0"]
|
||||
@ -8412,9 +8388,6 @@ exports[`better eslint`] = {
|
||||
"public/app/plugins/panel/geomap/style/utils.test.ts:5381": [
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
|
||||
],
|
||||
"public/app/plugins/panel/geomap/types.ts:5381": [
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
|
||||
],
|
||||
"public/app/plugins/panel/geomap/utils/selection.ts:5381": [
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
|
||||
],
|
||||
|
33
public/app/core/components/Layers/AddLayerButton.test.tsx
Normal file
33
public/app/core/components/Layers/AddLayerButton.test.tsx
Normal file
@ -0,0 +1,33 @@
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
|
||||
import { selectors } from '@grafana/e2e-selectors';
|
||||
|
||||
import { AddLayerButton, AddLayerButtonProps } from './AddLayerButton';
|
||||
|
||||
describe('AddLayerButton', () => {
|
||||
const testLabel = 'Add Layer';
|
||||
it('renders AddLayerButton', () => {
|
||||
renderScenario({});
|
||||
|
||||
const button = screen.getByLabelText(selectors.components.ValuePicker.button(testLabel));
|
||||
|
||||
expect(button).toBeInTheDocument();
|
||||
});
|
||||
|
||||
function renderScenario(overrides: Partial<AddLayerButtonProps>) {
|
||||
const dummyOptions = [{ description: 'Use markers to render each data point', label: 'Markers', value: 'markers' }];
|
||||
const props: AddLayerButtonProps = {
|
||||
onChange: jest.fn(),
|
||||
options: dummyOptions,
|
||||
label: testLabel,
|
||||
};
|
||||
|
||||
Object.assign(props, overrides);
|
||||
|
||||
return {
|
||||
props,
|
||||
renderResult: render(<AddLayerButton {...props} />),
|
||||
};
|
||||
}
|
||||
});
|
@ -3,7 +3,7 @@ import React from 'react';
|
||||
import { SelectableValue } from '@grafana/data';
|
||||
import { ValuePicker } from '@grafana/ui';
|
||||
|
||||
type AddLayerButtonProps = {
|
||||
export type AddLayerButtonProps = {
|
||||
onChange: (sel: SelectableValue<string>) => void;
|
||||
options: Array<SelectableValue<string>>;
|
||||
label: string;
|
||||
|
77
public/app/core/components/Layers/LayerDragDropList.test.tsx
Normal file
77
public/app/core/components/Layers/LayerDragDropList.test.tsx
Normal file
@ -0,0 +1,77 @@
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
|
||||
import { DATA_TEST_ID, LayerDragDropList, LayerDragDropListProps } from './LayerDragDropList';
|
||||
|
||||
describe('LayerDragDropList', () => {
|
||||
type testLayer = { name: string; getName: () => string };
|
||||
const layerOneName = 'rocket12345';
|
||||
const layerTwoName = 'man6789';
|
||||
it('renders LayerDragDropList', () => {
|
||||
renderScenario({});
|
||||
|
||||
screen.getByTestId(DATA_TEST_ID);
|
||||
screen.getByText(layerOneName);
|
||||
screen.getByText(layerTwoName);
|
||||
});
|
||||
|
||||
it('excludeBaseLayer', () => {
|
||||
renderScenario({ excludeBaseLayer: true });
|
||||
|
||||
screen.getByText(layerTwoName);
|
||||
expect(screen.queryByTestId(layerOneName)).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('showActions', () => {
|
||||
renderScenario({ showActions: () => true });
|
||||
|
||||
expect(screen.getAllByLabelText('Duplicate button').length).toEqual(2);
|
||||
expect(screen.getAllByLabelText('Remove button').length).toEqual(2);
|
||||
});
|
||||
|
||||
it('showActions - no duplicate', () => {
|
||||
renderScenario({ showActions: () => true, onDuplicate: undefined });
|
||||
|
||||
expect(screen.getAllByLabelText('Remove button').length).toEqual(2);
|
||||
expect(screen.queryAllByLabelText('Duplicate button').length).toEqual(0);
|
||||
});
|
||||
|
||||
it('renders draggable icon', () => {
|
||||
renderScenario({});
|
||||
|
||||
expect(screen.getAllByLabelText('Drag and drop icon').length).toEqual(2);
|
||||
});
|
||||
|
||||
it('does not render draggable icon', () => {
|
||||
renderScenario({ excludeBaseLayer: true });
|
||||
|
||||
expect(screen.queryAllByLabelText('Drag and drop icon').length).toEqual(0);
|
||||
});
|
||||
|
||||
function renderScenario(overrides: Partial<LayerDragDropListProps<testLayer>>) {
|
||||
const testLayers = [
|
||||
{ name: layerOneName, getName: () => layerOneName },
|
||||
{ name: layerTwoName, getName: () => layerTwoName },
|
||||
];
|
||||
const props: LayerDragDropListProps<testLayer> = {
|
||||
layers: testLayers,
|
||||
getLayerInfo: jest.fn(),
|
||||
onDragEnd: jest.fn(),
|
||||
onSelect: jest.fn(),
|
||||
onDelete: jest.fn(),
|
||||
onDuplicate: jest.fn(),
|
||||
showActions: jest.fn(),
|
||||
selection: [],
|
||||
excludeBaseLayer: false,
|
||||
onNameChange: jest.fn(),
|
||||
verifyLayerNameUniqueness: undefined,
|
||||
};
|
||||
|
||||
Object.assign(props, overrides);
|
||||
|
||||
return {
|
||||
props,
|
||||
renderResult: render(<LayerDragDropList {...props} />),
|
||||
};
|
||||
}
|
||||
});
|
@ -9,7 +9,9 @@ import { Icon, IconButton, stylesFactory } from '@grafana/ui';
|
||||
import { LayerName } from './LayerName';
|
||||
import { LayerElement } from './types';
|
||||
|
||||
type LayerDragDropListProps<T extends LayerElement> = {
|
||||
export const DATA_TEST_ID = 'layer-drag-drop-list';
|
||||
|
||||
export type LayerDragDropListProps<T extends LayerElement> = {
|
||||
layers: T[];
|
||||
getLayerInfo: (element: T) => string;
|
||||
onDragEnd: (result: DropResult) => void;
|
||||
@ -46,7 +48,7 @@ export const LayerDragDropList = <T extends LayerElement>({
|
||||
<DragDropContext onDragEnd={onDragEnd}>
|
||||
<Droppable droppableId="droppable">
|
||||
{(provided, snapshot) => (
|
||||
<div {...provided.droppableProps} ref={provided.innerRef}>
|
||||
<div {...provided.droppableProps} ref={provided.innerRef} data-testid={DATA_TEST_ID}>
|
||||
{(() => {
|
||||
// reverse order
|
||||
const rows: JSX.Element[] = [];
|
||||
@ -80,6 +82,7 @@ export const LayerDragDropList = <T extends LayerElement>({
|
||||
<IconButton
|
||||
name="copy"
|
||||
title={'Duplicate'}
|
||||
ariaLabel={'Duplicate button'}
|
||||
className={style.actionIcon}
|
||||
onClick={() => onDuplicate(element)}
|
||||
/>
|
||||
@ -88,6 +91,7 @@ export const LayerDragDropList = <T extends LayerElement>({
|
||||
<IconButton
|
||||
name="trash-alt"
|
||||
title={'remove'}
|
||||
ariaLabel={'Remove button'}
|
||||
className={cx(style.actionIcon, style.dragIcon)}
|
||||
onClick={() => onDelete(element)}
|
||||
/>
|
||||
@ -95,6 +99,7 @@ export const LayerDragDropList = <T extends LayerElement>({
|
||||
)}
|
||||
{layers.length > shouldRenderDragIconLengthThreshold && (
|
||||
<Icon
|
||||
aria-label="Drag and drop icon"
|
||||
title="Drag and drop to reorder"
|
||||
name="draggabledots"
|
||||
size="lg"
|
||||
|
@ -366,7 +366,7 @@ export class GeomapPanel extends Component<Props, State> {
|
||||
if (!this.map || this.state.ttipOpen) {
|
||||
return false;
|
||||
}
|
||||
const mouse = evt.originalEvent as any;
|
||||
const mouse = evt.originalEvent as MouseEvent;
|
||||
const pixel = this.map.getEventPixel(mouse);
|
||||
const hover = toLonLat(this.map.getCoordinateFromPixel(pixel));
|
||||
|
||||
@ -466,7 +466,6 @@ export class GeomapPanel extends Component<Props, State> {
|
||||
} else if (this.byName.has(newOptions.name)) {
|
||||
return false;
|
||||
}
|
||||
console.log('Layer name changed', uid, '>>>', newOptions.name);
|
||||
this.byName.delete(uid);
|
||||
|
||||
uid = newOptions.name;
|
||||
@ -532,7 +531,7 @@ export class GeomapPanel extends Component<Props, State> {
|
||||
}
|
||||
|
||||
const UID = options.name;
|
||||
const state: MapLayerState<any> = {
|
||||
const state: MapLayerState<unknown> = {
|
||||
// UID, // unique name when added to the map (it may change and will need special handling)
|
||||
isBasemap,
|
||||
options,
|
||||
@ -556,7 +555,7 @@ export class GeomapPanel extends Component<Props, State> {
|
||||
return state;
|
||||
}
|
||||
|
||||
applyLayerFilter(handler: MapLayerHandler<any>, options: MapLayerOptions<any>): void {
|
||||
applyLayerFilter(handler: MapLayerHandler<unknown>, options: MapLayerOptions<unknown>): void {
|
||||
if (handler.update) {
|
||||
let panelData = this.props.data;
|
||||
if (options.filterData) {
|
||||
@ -607,7 +606,7 @@ export class GeomapPanel extends Component<Props, State> {
|
||||
});
|
||||
}
|
||||
} else {
|
||||
console.log('TODO, view requires special handling', v);
|
||||
// TODO: view requires special handling
|
||||
}
|
||||
} else {
|
||||
coord = [v.lon ?? 0, v.lat ?? 0];
|
||||
|
@ -34,7 +34,7 @@ export const DataHoverView = ({ data, rowIndex, columnIndex, sortOrder, mode }:
|
||||
return null;
|
||||
}
|
||||
|
||||
const displayValues: Array<[string, any, string]> = [];
|
||||
const displayValues: Array<[string, unknown, string]> = [];
|
||||
const links: Array<LinkModel<Field>> = [];
|
||||
const linkLookup = new Set<string>();
|
||||
|
||||
|
@ -24,15 +24,10 @@ export class ObservablePropsWrapper<T> extends Component<Props<T>, State<T>> {
|
||||
componentDidMount() {
|
||||
this.sub = this.props.watch.subscribe({
|
||||
next: (subProps: T) => {
|
||||
//console.log('ObservablePropsWrapper:NEXT', subProps);
|
||||
this.setState({ subProps });
|
||||
},
|
||||
complete: () => {
|
||||
//console.log('ObservablePropsWrapper:complete');
|
||||
},
|
||||
error: (err) => {
|
||||
//console.log('ObservablePropsWrapper:error', err);
|
||||
},
|
||||
complete: () => {},
|
||||
error: (err) => {},
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,7 @@ import { FeatureStyleConfig } from '../types';
|
||||
|
||||
import { StyleRuleEditor, StyleRuleEditorSettings } from './StyleRuleEditor';
|
||||
|
||||
export const GeomapStyleRulesEditor: FC<StandardEditorProps<FeatureStyleConfig[], any, any>> = (props) => {
|
||||
export const GeomapStyleRulesEditor: FC<StandardEditorProps<FeatureStyleConfig[], unknown, unknown>> = (props) => {
|
||||
const { value, onChange, context, item } = props;
|
||||
const theme = useTheme2();
|
||||
|
||||
|
@ -10,7 +10,7 @@ import { GeomapInstanceState } from '../GeomapPanel';
|
||||
import { getLayersOptions } from '../layers/registry';
|
||||
import { GeomapPanelOptions, MapLayerState } from '../types';
|
||||
|
||||
type LayersEditorProps = StandardEditorProps<any, any, GeomapPanelOptions, GeomapInstanceState>;
|
||||
type LayersEditorProps = StandardEditorProps<unknown, unknown, GeomapPanelOptions, GeomapInstanceState>;
|
||||
|
||||
export const LayersEditor = (props: LayersEditorProps) => {
|
||||
const { layers, selected, actions } = props.context.instanceState ?? {};
|
||||
@ -36,19 +36,19 @@ export const LayersEditor = (props: LayersEditorProps) => {
|
||||
actions.reorder(src, dst);
|
||||
};
|
||||
|
||||
const onSelect = (element: MapLayerState<any>) => {
|
||||
const onSelect = (element: MapLayerState<unknown>) => {
|
||||
actions.selectLayer(element.options.name);
|
||||
};
|
||||
|
||||
const onDelete = (element: MapLayerState<any>) => {
|
||||
const onDelete = (element: MapLayerState<unknown>) => {
|
||||
actions.deleteLayer(element.options.name);
|
||||
};
|
||||
|
||||
const getLayerInfo = (element: MapLayerState<any>) => {
|
||||
const getLayerInfo = (element: MapLayerState<unknown>) => {
|
||||
return element.options.type;
|
||||
};
|
||||
|
||||
const onNameChange = (element: MapLayerState<any>, name: string) => {
|
||||
const onNameChange = (element: MapLayerState<unknown>, name: string) => {
|
||||
element.onChange({ ...element.options, name });
|
||||
};
|
||||
|
||||
|
@ -9,11 +9,9 @@ import { GeomapInstanceState } from '../GeomapPanel';
|
||||
import { GeomapPanelOptions, MapViewConfig } from '../types';
|
||||
import { centerPointRegistry, MapCenterID } from '../view';
|
||||
|
||||
export const MapViewEditor: FC<StandardEditorProps<MapViewConfig, any, GeomapPanelOptions, GeomapInstanceState>> = ({
|
||||
value,
|
||||
onChange,
|
||||
context,
|
||||
}) => {
|
||||
export const MapViewEditor: FC<
|
||||
StandardEditorProps<MapViewConfig, unknown, GeomapPanelOptions, GeomapInstanceState>
|
||||
> = ({ value, onChange, context }) => {
|
||||
const labelWidth = 10;
|
||||
|
||||
const views = useMemo(() => {
|
||||
|
@ -30,7 +30,7 @@ const comparators = [
|
||||
{ label: '<=', value: ComparisonOperation.LTE },
|
||||
];
|
||||
|
||||
export const StyleRuleEditor: FC<StandardEditorProps<FeatureStyleConfig, any, any, StyleRuleEditorSettings>> = (
|
||||
export const StyleRuleEditor: FC<StandardEditorProps<FeatureStyleConfig, any, unknown, StyleRuleEditorSettings>> = (
|
||||
props
|
||||
) => {
|
||||
const { value, onChange, item, context } = props;
|
||||
|
@ -27,13 +27,12 @@ export function getLayerEditor(opts: LayerEditorOptions): NestedPanelOptions<Map
|
||||
return { ...parent, options: opts.state.options, instanceState: opts.state };
|
||||
},
|
||||
getValue: (path: string) => lodashGet(opts.state.options, path),
|
||||
onChange: (path: string, value: any) => {
|
||||
onChange: (path: string, value: string) => {
|
||||
const { state } = opts;
|
||||
const { options } = state;
|
||||
if (path === 'type' && value) {
|
||||
const layer = geomapLayerRegistry.getIfExists(value);
|
||||
if (layer) {
|
||||
console.log('Change layer type:', value, state);
|
||||
const opts = {
|
||||
...options, // keep current shared options
|
||||
type: layer.id,
|
||||
@ -55,7 +54,6 @@ export function getLayerEditor(opts: LayerEditorOptions): NestedPanelOptions<Map
|
||||
}),
|
||||
build: (builder, context) => {
|
||||
if (!opts.state) {
|
||||
console.log('MISSING LAYER!!!', opts);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -91,7 +91,7 @@ export enum ComparisonOperation {
|
||||
//-------------------
|
||||
// Runtime model
|
||||
//-------------------
|
||||
export interface MapLayerState<TConfig = any> extends LayerElement {
|
||||
export interface MapLayerState<TConfig = unknown> extends LayerElement {
|
||||
options: MapLayerOptions<TConfig>;
|
||||
handler: MapLayerHandler;
|
||||
layer: BaseLayer; // the openlayers instance
|
||||
|
Loading…
Reference in New Issue
Block a user