grafana/public/app/features/transformers/spatial/spatialTransformer.ts
Josh Hunt 3c6e0e8ef8
Chore: ESlint import order (#44959)
* Add and configure eslint-plugin-import

* Fix the lint:ts npm command

* Autofix + prettier all the files

* Manually fix remaining files

* Move jquery code in jest-setup to external file to safely reorder imports

* Resolve issue caused by circular dependencies within Prometheus

* Update .betterer.results

* Fix missing // @ts-ignore

* ignore iconBundle.ts

* Fix missing // @ts-ignore
2022-04-22 14:33:13 +01:00

91 lines
3.0 KiB
TypeScript

import { mergeMap, from } from 'rxjs';
import { ArrayVector, DataFrame, DataTransformerID, DataTransformerInfo, FieldType } from '@grafana/data';
import { createGeometryCollection, createLineBetween } from 'app/features/geo/format/utils';
import { getGeometryField, getLocationMatchers } from 'app/features/geo/utils/location';
import { SpatialOperation, SpatialAction, SpatialTransformOptions } from './models.gen';
import { doGeomeryCalculation, toLineString } from './utils';
export const spatialTransformer: DataTransformerInfo<SpatialTransformOptions> = {
id: DataTransformerID.spatial,
name: 'Spatial operations',
description: 'Apply spatial operations to query results',
defaultOptions: {},
operator: (options) => (source) => source.pipe(mergeMap((data) => from(doSetGeometry(data, options)))),
};
export function isLineBuilderOption(options: SpatialTransformOptions): boolean {
return options.action === SpatialAction.Modify && options.modify?.op === SpatialOperation.LineBuilder;
}
async function doSetGeometry(frames: DataFrame[], options: SpatialTransformOptions): Promise<DataFrame[]> {
const location = await getLocationMatchers(options.source);
if (isLineBuilderOption(options)) {
const targetLocation = await getLocationMatchers(options.modify?.target);
return frames.map((frame) => {
const src = getGeometryField(frame, location);
const target = getGeometryField(frame, targetLocation);
if (src.field && target.field) {
const fields = [...frame.fields];
const line = createLineBetween(src.field, target.field);
const first = fields[0];
if (first.type === FieldType.geo && first !== src.field && first !== target.field) {
fields[0] = createGeometryCollection(first, line); //
} else {
fields.unshift(line);
}
return {
...frame,
fields,
};
}
return frame;
});
}
return frames.map((frame) => {
let info = getGeometryField(frame, location);
if (info.field) {
if (options.action === SpatialAction.Modify) {
switch (options.modify?.op) {
// SOON: extent, convex hull, etc
case SpatialOperation.AsLine:
let name = info.field.name;
if (!name || name === 'Point') {
name = 'Line';
}
return {
...frame,
length: 1,
fields: [
{
...info.field,
name,
type: FieldType.geo,
values: new ArrayVector([toLineString(info.field)]),
},
],
};
}
return frame;
}
const fields = info.derived ? [info.field, ...frame.fields] : frame.fields.slice(0);
if (options.action === SpatialAction.Calculate) {
fields.push(doGeomeryCalculation(info.field, options.calculate ?? {}));
info.derived = true;
}
if (info.derived) {
return {
...frame,
fields,
};
}
}
return frame;
});
}