1import { DataTransformerID } from './ids';
2import { DataTransformerInfo } from '../../types/transformations';
3import { DataFrame, Field } from '../../types/dataFrame';
4import { getFieldDisplayName } from '../../field/fieldState';
5import { map } from 'rxjs/operators';
6
7export interface RenameFieldsTransformerOptions {
8  renameByName: Record<string, string>;
9}
10
11export const renameFieldsTransformer: DataTransformerInfo<RenameFieldsTransformerOptions> = {
12  id: DataTransformerID.rename,
13  name: 'Rename fields by name',
14  description: 'Rename fields based on configuration given by user',
15  defaultOptions: {
16    renameByName: {},
17  },
18
19  /**
20   * Return a modified copy of the series.  If the transform is not or should not
21   * be applied, just return the input series
22   */
23  operator: (options) => (source) =>
24    source.pipe(
25      map((data) => {
26        const renamer = createRenamer(options.renameByName);
27
28        if (!Array.isArray(data) || data.length === 0) {
29          return data;
30        }
31
32        return data.map((frame) => ({
33          ...frame,
34          fields: renamer(frame),
35        }));
36      })
37    ),
38};
39
40const createRenamer = (renameByName: Record<string, string>) => (frame: DataFrame): Field[] => {
41  if (!renameByName || Object.keys(renameByName).length === 0) {
42    return frame.fields;
43  }
44
45  return frame.fields.map((field) => {
46    const displayName = getFieldDisplayName(field, frame);
47    const renameTo = renameByName[displayName];
48
49    if (typeof renameTo !== 'string' || renameTo.length === 0) {
50      return field;
51    }
52
53    return {
54      ...field,
55      config: {
56        ...field.config,
57        displayName: renameTo,
58      },
59      state: {
60        ...field.state,
61        displayName: renameTo,
62      },
63    };
64  });
65};
66