rowsToFields.ts 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. import { map } from 'rxjs/operators';
  2. import {
  3. ArrayVector,
  4. DataFrame,
  5. DataTransformerID,
  6. DataTransformerInfo,
  7. Field,
  8. getFieldDisplayName,
  9. Labels,
  10. } from '@grafana/data';
  11. import {
  12. getFieldConfigFromFrame,
  13. FieldToConfigMapping,
  14. evaluteFieldMappings,
  15. EvaluatedMappingResult,
  16. FieldConfigHandlerKey,
  17. } from '../fieldToConfigMapping/fieldToConfigMapping';
  18. export interface RowToFieldsTransformOptions {
  19. nameField?: string;
  20. valueField?: string;
  21. mappings?: FieldToConfigMapping[];
  22. }
  23. export const rowsToFieldsTransformer: DataTransformerInfo<RowToFieldsTransformOptions> = {
  24. id: DataTransformerID.rowsToFields,
  25. name: 'Rows to fields',
  26. description: 'Convert each row into a field with dynamic config',
  27. defaultOptions: {},
  28. /**
  29. * Return a modified copy of the series. If the transform is not or should not
  30. * be applied, just return the input series
  31. */
  32. operator: (options) => (source) =>
  33. source.pipe(
  34. map((data) => {
  35. return data.map((frame) => rowsToFields(options, frame));
  36. })
  37. ),
  38. };
  39. export function rowsToFields(options: RowToFieldsTransformOptions, data: DataFrame): DataFrame {
  40. const mappingResult = evaluteFieldMappings(data, options.mappings ?? [], true);
  41. const { nameField, valueField } = mappingResult;
  42. if (!nameField || !valueField) {
  43. return data;
  44. }
  45. const outFields: Field[] = [];
  46. for (let index = 0; index < nameField.values.length; index++) {
  47. const name = nameField.values.get(index);
  48. const value = valueField.values.get(index);
  49. const config = getFieldConfigFromFrame(data, index, mappingResult);
  50. const labels = getLabelsFromRow(data, index, mappingResult);
  51. const field: Field = {
  52. name: `${name}`,
  53. type: valueField.type,
  54. values: new ArrayVector([value]),
  55. config: config,
  56. labels,
  57. };
  58. outFields.push(field);
  59. }
  60. return {
  61. fields: outFields,
  62. length: 1,
  63. };
  64. }
  65. function getLabelsFromRow(frame: DataFrame, index: number, mappingResult: EvaluatedMappingResult): Labels {
  66. const labels = { ...mappingResult.nameField!.labels };
  67. for (let i = 0; i < frame.fields.length; i++) {
  68. const field = frame.fields[i];
  69. const fieldName = getFieldDisplayName(field, frame);
  70. const fieldMapping = mappingResult.index[fieldName];
  71. if (fieldMapping.handler && fieldMapping.handler.key !== FieldConfigHandlerKey.Label) {
  72. continue;
  73. }
  74. const value = field.values.get(index);
  75. if (value != null) {
  76. labels[fieldName] = value;
  77. }
  78. }
  79. return labels;
  80. }