mirror of
https://github.com/grafana/grafana.git
synced 2025-02-13 00:55:47 -06:00
166 lines
4.8 KiB
TypeScript
166 lines
4.8 KiB
TypeScript
import React, { useEffect } from 'react';
|
|
import { css } from '@emotion/css';
|
|
import {
|
|
DataTransformerID,
|
|
FrameGeometrySource,
|
|
FrameGeometrySourceMode,
|
|
GrafanaTheme2,
|
|
PanelOptionsEditorBuilder,
|
|
PluginState,
|
|
StandardEditorContext,
|
|
TransformerRegistryItem,
|
|
TransformerUIProps,
|
|
} from '@grafana/data';
|
|
|
|
import { isLineBuilderOption, spatialTransformer } from './spatialTransformer';
|
|
import { addLocationFields } from 'app/features/geo/editor/locationEditor';
|
|
import { getDefaultOptions, getTransformerOptionPane } from './optionsHelper';
|
|
import { SpatialCalculation, SpatialOperation, SpatialAction, SpatialTransformOptions } from './models.gen';
|
|
import { useTheme2 } from '@grafana/ui';
|
|
|
|
// Nothing defined in state
|
|
const supplier = (
|
|
builder: PanelOptionsEditorBuilder<SpatialTransformOptions>,
|
|
context: StandardEditorContext<SpatialTransformOptions>
|
|
) => {
|
|
const options = context.options ?? {};
|
|
|
|
builder.addSelect({
|
|
path: `action`,
|
|
name: 'Action',
|
|
description: '',
|
|
defaultValue: SpatialAction.Prepare,
|
|
settings: {
|
|
options: [
|
|
{
|
|
value: SpatialAction.Prepare,
|
|
label: 'Prepare spatial field',
|
|
description: 'Set a geometry field based on the results of other fields',
|
|
},
|
|
{
|
|
value: SpatialAction.Calculate,
|
|
label: 'Calculate value',
|
|
description: 'Use the geometry to define a new field (heading/distance/area)',
|
|
},
|
|
{ value: SpatialAction.Modify, label: 'Transform', description: 'Apply spatial operations to the geometry' },
|
|
],
|
|
},
|
|
});
|
|
|
|
if (options.action === SpatialAction.Calculate) {
|
|
builder.addSelect({
|
|
path: `calculate.calc`,
|
|
name: 'Function',
|
|
description: '',
|
|
defaultValue: SpatialCalculation.Heading,
|
|
settings: {
|
|
options: [
|
|
{ value: SpatialCalculation.Heading, label: 'Heading' },
|
|
{ value: SpatialCalculation.Area, label: 'Area' },
|
|
{ value: SpatialCalculation.Distance, label: 'Distance' },
|
|
],
|
|
},
|
|
});
|
|
} else if (options.action === SpatialAction.Modify) {
|
|
builder.addSelect({
|
|
path: `modify.op`,
|
|
name: 'Operation',
|
|
description: '',
|
|
defaultValue: SpatialOperation.AsLine,
|
|
settings: {
|
|
options: [
|
|
{
|
|
value: SpatialOperation.AsLine,
|
|
label: 'As line',
|
|
description: 'Create a single line feature with a vertex at each row',
|
|
},
|
|
{
|
|
value: SpatialOperation.LineBuilder,
|
|
label: 'Line builder',
|
|
description: 'Create a line between two points',
|
|
},
|
|
],
|
|
},
|
|
});
|
|
}
|
|
|
|
if (isLineBuilderOption(options)) {
|
|
builder.addNestedOptions({
|
|
category: ['Source'],
|
|
path: 'source',
|
|
build: (b, c) => {
|
|
const loc = (options.source ?? {}) as FrameGeometrySource;
|
|
if (!loc.mode) {
|
|
loc.mode = FrameGeometrySourceMode.Auto;
|
|
}
|
|
addLocationFields('Point', '', b, loc);
|
|
},
|
|
});
|
|
|
|
builder.addNestedOptions({
|
|
category: ['Target'],
|
|
path: 'modify',
|
|
build: (b, c) => {
|
|
const loc = (options.modify?.target ?? {}) as FrameGeometrySource;
|
|
if (!loc.mode) {
|
|
loc.mode = FrameGeometrySourceMode.Auto;
|
|
}
|
|
addLocationFields('Point', 'target.', b, loc);
|
|
},
|
|
});
|
|
} else {
|
|
addLocationFields('Location', 'source.', builder, options.source);
|
|
}
|
|
};
|
|
|
|
export const SetGeometryTransformerEditor: React.FC<TransformerUIProps<SpatialTransformOptions>> = (props) => {
|
|
// a new component is created with every change :(
|
|
useEffect(() => {
|
|
if (!props.options.source?.mode) {
|
|
const opts = getDefaultOptions(supplier);
|
|
props.onChange({ ...opts, ...props.options });
|
|
console.log('geometry useEffect', opts);
|
|
}
|
|
});
|
|
|
|
const styles = getStyles(useTheme2());
|
|
|
|
const pane = getTransformerOptionPane<SpatialTransformOptions>(props, supplier);
|
|
return (
|
|
<div>
|
|
<div>{pane.items.map((v) => v.render())}</div>
|
|
<div>
|
|
{pane.categories.map((c) => {
|
|
return (
|
|
<div key={c.props.id} className={styles.wrap}>
|
|
<h5>{c.props.title}</h5>
|
|
<div className={styles.item}>{c.items.map((s) => s.render())}</div>
|
|
</div>
|
|
);
|
|
})}
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
const getStyles = (theme: GrafanaTheme2) => {
|
|
return {
|
|
wrap: css`
|
|
margin-bottom: 20px;
|
|
`,
|
|
item: css`
|
|
border-left: 4px solid ${theme.colors.border.strong};
|
|
padding-left: 10px;
|
|
`,
|
|
};
|
|
};
|
|
|
|
export const spatialTransformRegistryItem: TransformerRegistryItem<SpatialTransformOptions> = {
|
|
id: DataTransformerID.spatial,
|
|
editor: SetGeometryTransformerEditor,
|
|
transformation: spatialTransformer,
|
|
name: spatialTransformer.name,
|
|
description: spatialTransformer.description,
|
|
state: PluginState.alpha,
|
|
};
|