mirror of
https://github.com/grafana/grafana.git
synced 2025-02-15 01:53:33 -06:00
* add custom component for location editor * FC cleanup * Apply filter to add location fields call * Create custom editor for location mode * Apply validation logic and render warning * Improve alert styling * Add help url button to location alert * Add success alert for auto * Remove completed TODOs * Only use alert on error, not success * Change location mode to dropdown * Change alert severity to less severe, info * Prevent auto field selection during manual * Update location testing to be for auto mode * Run geo transformer editor init once * Fix breaking test * Clean up some anys * Update styling for alert * Remove auto success styling Co-authored-by: Ryan McKinley <ryantxu@gmail.com> Co-authored-by: nmarrs <nathanielmarrs@gmail.com>
127 lines
3.4 KiB
TypeScript
127 lines
3.4 KiB
TypeScript
import { css } from '@emotion/css';
|
|
import React, { useEffect, useState } from 'react';
|
|
|
|
import {
|
|
StandardEditorProps,
|
|
FrameGeometrySourceMode,
|
|
DataFrame,
|
|
FrameGeometrySource,
|
|
GrafanaTheme2,
|
|
} from '@grafana/data';
|
|
import { selectors } from '@grafana/e2e-selectors';
|
|
import { Alert, HorizontalGroup, Icon, Select, useStyles2 } from '@grafana/ui';
|
|
|
|
import { FrameGeometryField, getGeometryField, getLocationMatchers } from '../utils/location';
|
|
|
|
const MODE_OPTIONS = [
|
|
{
|
|
value: FrameGeometrySourceMode.Auto,
|
|
label: 'Auto',
|
|
ariaLabel: selectors.components.Transforms.SpatialOperations.location.autoOption,
|
|
description: 'Automatically identify location data based on default field names',
|
|
},
|
|
{
|
|
value: FrameGeometrySourceMode.Coords,
|
|
label: 'Coords',
|
|
ariaLabel: selectors.components.Transforms.SpatialOperations.location.coords.option,
|
|
description: 'Specify latitude and longitude fields',
|
|
},
|
|
{
|
|
value: FrameGeometrySourceMode.Geohash,
|
|
label: 'Geohash',
|
|
ariaLabel: selectors.components.Transforms.SpatialOperations.location.geohash.option,
|
|
description: 'Specify geohash field',
|
|
},
|
|
{
|
|
value: FrameGeometrySourceMode.Lookup,
|
|
label: 'Lookup',
|
|
ariaLabel: selectors.components.Transforms.SpatialOperations.location.lookup.option,
|
|
description: 'Specify Gazetteer and lookup field',
|
|
},
|
|
];
|
|
|
|
interface ModeEditorSettings {
|
|
data?: DataFrame[];
|
|
source?: FrameGeometrySource;
|
|
}
|
|
|
|
const helpUrl = 'https://grafana.com/docs/grafana/latest/panels-visualizations/visualizations/geomap/#location';
|
|
|
|
export const LocationModeEditor = ({
|
|
value,
|
|
onChange,
|
|
context,
|
|
item,
|
|
}: StandardEditorProps<string, ModeEditorSettings, unknown, unknown>) => {
|
|
const [info, setInfo] = useState<FrameGeometryField>();
|
|
|
|
useEffect(() => {
|
|
if (item.settings?.source && item.settings?.data?.length && item.settings.data[0]) {
|
|
getLocationMatchers(item.settings.source).then((location) => {
|
|
if (item.settings && item.settings.data) {
|
|
setInfo(getGeometryField(item.settings.data[0], location));
|
|
}
|
|
});
|
|
}
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
}, [item.settings]);
|
|
|
|
const styles = useStyles2(getStyles);
|
|
|
|
const dataValidation = () => {
|
|
if (info) {
|
|
if (info.warning) {
|
|
return (
|
|
<Alert
|
|
title={info.warning}
|
|
severity="warning"
|
|
buttonContent={<Icon name="question-circle" size="xl" />}
|
|
className={styles.alert}
|
|
onRemove={() => {
|
|
const newWindow = window.open(helpUrl, '_blank', 'noopener,noreferrer');
|
|
if (newWindow) {
|
|
newWindow.opener = null;
|
|
}
|
|
}}
|
|
/>
|
|
);
|
|
} else if (value === FrameGeometrySourceMode.Auto && info.description) {
|
|
return <span>{info.description}</span>;
|
|
}
|
|
}
|
|
return null;
|
|
};
|
|
|
|
return (
|
|
<>
|
|
<Select
|
|
options={MODE_OPTIONS}
|
|
value={value}
|
|
onChange={(v) => {
|
|
onChange(v.value);
|
|
}}
|
|
/>
|
|
<HorizontalGroup className={styles.hGroup}>{dataValidation()}</HorizontalGroup>
|
|
</>
|
|
);
|
|
};
|
|
|
|
const getStyles = (theme: GrafanaTheme2) => {
|
|
return {
|
|
alert: css`
|
|
& div {
|
|
padding: 4px;
|
|
}
|
|
margin-bottom: 0px;
|
|
margin-top: 5px;
|
|
padding: 2px;
|
|
`,
|
|
// TODO apply styling to horizontal group (currently not working)
|
|
hGroup: css`
|
|
& div {
|
|
width: 100%;
|
|
}
|
|
`,
|
|
};
|
|
};
|