From 941dce3782dbeaa6cc0e30eb39504b4b45717efc Mon Sep 17 00:00:00 2001 From: Cameron Waterman Date: Tue, 24 Oct 2023 08:18:21 -0500 Subject: [PATCH] fix(data-frame): Boolean and "Value" columns (#46) --- .../data-frame/DataFrameDataSource.test.ts | 23 +++++++-------- .../data-frame/DataFrameDataSource.ts | 28 ++++++++++++++++--- 2 files changed, 36 insertions(+), 15 deletions(-) diff --git a/src/datasources/data-frame/DataFrameDataSource.test.ts b/src/datasources/data-frame/DataFrameDataSource.test.ts index 33b8197..4ede3ba 100644 --- a/src/datasources/data-frame/DataFrameDataSource.test.ts +++ b/src/datasources/data-frame/DataFrameDataSource.test.ts @@ -66,21 +66,21 @@ it('should convert columns to Grafana fields', async () => { { refId: 'A', tableId: '_', - columns: ['int', 'float', 'string', 'time', 'bool'], + columns: ['int', 'float', 'string', 'time', 'bool', 'Value'], }, ]); const response = await ds.query(query); const fields = response.data[0].fields as Field[]; - const actual = fields.map(({ name, type, values }) => ({ name, type, values: values.toArray() })); + const actual = fields.map(({ name, type, values, config }) => ({ name, type, values: values.toArray(), config })); expect(actual).toEqual([ - { name: 'int', type: FieldType.number, values: [1, 2] }, - { name: 'float', type: FieldType.number, values: [1.1, 2.2] }, - { name: 'string', type: FieldType.string, values: ['first', 'second'] }, - { name: 'time', type: FieldType.time, values: [1663135260000, 1663135320000] }, - // TODO: Boolean columns are not being converted correctly (should be true, false) - { name: 'bool', type: FieldType.boolean, values: [true, true] }, + { name: 'int', type: FieldType.number, values: [1, 2], config: {} }, + { name: 'float', type: FieldType.number, values: [1.1, 2.2], config: {} }, + { name: 'string', type: FieldType.string, values: ['first', 'second'], config: {} }, + { name: 'time', type: FieldType.time, values: [1663135260000, 1663135320000], config: {} }, + { name: 'bool', type: FieldType.boolean, values: [true, false], config: {} }, + { name: 'Value', type: FieldType.string, values: ['test1', 'test2'], config: { displayName: 'Value' } }, ]); }); @@ -252,6 +252,7 @@ const fakeMetadataResponse: TableMetadata = { { name: 'float', dataType: 'FLOAT32', columnType: 'NULLABLE', properties: {} }, { name: 'string', dataType: 'STRING', columnType: 'NULLABLE', properties: {} }, { name: 'bool', dataType: 'BOOL', columnType: 'NORMAL', properties: {} }, + { name: 'Value', dataType: 'STRING', columnType: 'NULLABLE', properties: {} }, ], id: '_', name: 'Test Table', @@ -260,10 +261,10 @@ const fakeMetadataResponse: TableMetadata = { const fakeDataResponse: TableDataRows = { frame: { - columns: ['int', 'float', 'string', 'time', 'bool'], + columns: ['int', 'float', 'string', 'time', 'bool', 'Value'], data: [ - ['1', '1.1', 'first', '2022-09-14T06:01:00.0000000Z', 'True'], - ['2', '2.2', 'second', '2022-09-14T06:02:00.0000000Z', 'False'], + ['1', '1.1', 'first', '2022-09-14T06:01:00.0000000Z', 'True', 'test1'], + ['2', '2.2', 'second', '2022-09-14T06:02:00.0000000Z', 'False', 'test2'], ], }, continuationToken: '_', diff --git a/src/datasources/data-frame/DataFrameDataSource.ts b/src/datasources/data-frame/DataFrameDataSource.ts index 44cb8f3..8b1e14e 100644 --- a/src/datasources/data-frame/DataFrameDataSource.ts +++ b/src/datasources/data-frame/DataFrameDataSource.ts @@ -53,13 +53,12 @@ export class DataFrameDataSource extends DataSourceBase { const tableMetadata = await this.getTableMetadata(processedQuery.tableId); const columns = this.getColumnTypes(processedQuery.columns, tableMetadata?.columns ?? []); const tableData = await this.getDecimatedTableData(processedQuery, columns, range, maxDataPoints); - const frame = toDataFrame({ + return this.convertDataFrameFields({ refId: processedQuery.refId, name: processedQuery.tableId, columns: processedQuery.columns.map((name) => ({ text: name })), rows: tableData.frame.data, - } as TableData); - return this.convertDataFrameFields(frame, columns); + } as TableData, columns); } shouldRunQuery(query: ValidDataFrameQuery): boolean { @@ -152,7 +151,14 @@ export class DataFrameDataSource extends DataSourceBase { } } - private convertDataFrameFields(frame: DataFrame, columns: Column[]): DataFrame { + private convertDataFrameFields(tableData: TableData, columns: Column[]): DataFrame { + this.transformBooleanFields(tableData, columns); + const frame = toDataFrame(tableData); + frame.fields.forEach(field => { + if (field.name.toLowerCase() === 'value') { + field.config.displayName = field.name; + } + }) const transformer = standardTransformers.convertFieldTypeTransformer.transformer; const conversions = columns.map(({ name, dataType }) => ({ targetField: name, @@ -162,6 +168,20 @@ export class DataFrameDataSource extends DataSourceBase { return transformer({ conversions }, { interpolate: _.identity })([frame])[0]; } + private transformBooleanFields(tableData: TableData, columns: Column[]): void { + const boolColumnIndices: number[] = []; + columns.forEach((column, i) => { + if (column.dataType === 'BOOL') { + boolColumnIndices.push(i); + } + }); + if (!!boolColumnIndices.length) { + tableData.rows.forEach(row => { + boolColumnIndices.forEach(i => row[i] = row[i].toLowerCase() === 'true'); + }) + } + } + private constructTimeFilters(columns: Column[], timeRange: TimeRange): ColumnFilter[] { const timeIndex = columns.find((c) => c.dataType === 'TIMESTAMP' && c.columnType === 'INDEX');