From 9464115fc0e0f4bc0bdc93b8218177ca0233478e Mon Sep 17 00:00:00 2001 From: Ryan McKinley Date: Mon, 20 Apr 2020 11:10:03 -0700 Subject: [PATCH] TableCell: show JSON rather than [object Object] (#23683) --- .../src/components/Table/JSONViewCell.tsx | 43 +++++++++++++++++++ .../grafana-ui/src/components/Table/types.ts | 1 + .../grafana-ui/src/components/Table/utils.ts | 15 +++++-- pkg/tsdb/testdatasource/scenarios.go | 9 ++++ .../plugins/datasource/testdata/datasource.ts | 19 ++++++++ .../testdata/partials/query.editor.html | 15 +++++++ .../plugins/datasource/testdata/query_ctrl.ts | 6 +++ public/app/plugins/panel/table/module.tsx | 12 +++--- 8 files changed, 111 insertions(+), 9 deletions(-) create mode 100644 packages/grafana-ui/src/components/Table/JSONViewCell.tsx diff --git a/packages/grafana-ui/src/components/Table/JSONViewCell.tsx b/packages/grafana-ui/src/components/Table/JSONViewCell.tsx new file mode 100644 index 00000000000..7989fd26d7d --- /dev/null +++ b/packages/grafana-ui/src/components/Table/JSONViewCell.tsx @@ -0,0 +1,43 @@ +import React, { FC } from 'react'; +import { css, cx } from 'emotion'; +import { TableCellProps } from './types'; +import { Tooltip } from '../Tooltip/Tooltip'; +import { JSONFormatter } from '../JSONFormatter/JSONFormatter'; + +export const JSONViewCell: FC = props => { + const { field, cell, tableStyles } = props; + + if (!field.display) { + return null; + } + + const txt = css` + cursor: pointer; + font-family: monospace; + `; + + const displayValue = JSON.stringify(cell.value); + const content = ; + return ( +
+ + {displayValue} + +
+ ); +}; + +interface PopupProps { + value: any; +} + +const JSONTooltip: FC = props => { + const clazz = css` + padding: 10px; + `; + return ( +
+ +
+ ); +}; diff --git a/packages/grafana-ui/src/components/Table/types.ts b/packages/grafana-ui/src/components/Table/types.ts index 2f07a066b0a..c7e77b32b59 100644 --- a/packages/grafana-ui/src/components/Table/types.ts +++ b/packages/grafana-ui/src/components/Table/types.ts @@ -15,6 +15,7 @@ export enum TableCellDisplayMode { ColorBackground = 'color-background', GradientGauge = 'gradient-gauge', LcdGauge = 'lcd-gauge', + JSONView = 'json-view', } export type FieldTextAlignment = 'auto' | 'left' | 'right' | 'center'; diff --git a/packages/grafana-ui/src/components/Table/utils.ts b/packages/grafana-ui/src/components/Table/utils.ts index 296f18e5b33..04248620a72 100644 --- a/packages/grafana-ui/src/components/Table/utils.ts +++ b/packages/grafana-ui/src/components/Table/utils.ts @@ -7,6 +7,7 @@ import { TableCellDisplayMode, TableCellProps, TableFieldOptions } from './types import { css, cx } from 'emotion'; import { withTableStyles } from './withTableStyles'; import tinycolor from 'tinycolor2'; +import { JSONViewCell } from './JSONViewCell'; export function getTextAlign(field?: Field): TextAlignProperty { if (!field) { @@ -46,7 +47,7 @@ export function getColumns(data: DataFrame, availableWidth: number, columnMinWid fieldCountWithoutWidth -= 1; } - const Cell = getCellComponent(fieldTableOptions.displayMode); + const Cell = getCellComponent(fieldTableOptions.displayMode, field); columns.push({ Cell, @@ -71,7 +72,7 @@ export function getColumns(data: DataFrame, availableWidth: number, columnMinWid return columns; } -function getCellComponent(displayMode: TableCellDisplayMode) { +function getCellComponent(displayMode: TableCellDisplayMode, field: Field) { switch (displayMode) { case TableCellDisplayMode.ColorText: return withTableStyles(DefaultCell, getTextColorStyle); @@ -80,9 +81,15 @@ function getCellComponent(displayMode: TableCellDisplayMode) { case TableCellDisplayMode.LcdGauge: case TableCellDisplayMode.GradientGauge: return BarGaugeCell; - default: - return DefaultCell; + case TableCellDisplayMode.JSONView: + return JSONViewCell; } + + // Default or Auto + if (field.type === FieldType.other) { + return JSONViewCell; + } + return DefaultCell; } function getTextColorStyle(props: TableCellProps) { diff --git a/pkg/tsdb/testdatasource/scenarios.go b/pkg/tsdb/testdatasource/scenarios.go index 109b57319f9..200dc9125f9 100644 --- a/pkg/tsdb/testdatasource/scenarios.go +++ b/pkg/tsdb/testdatasource/scenarios.go @@ -266,6 +266,15 @@ func init() { }, }) + registerScenario(&Scenario{ + Id: "grafana_api", + Name: "Grafana API", + Handler: func(query *tsdb.Query, context *tsdb.TsdbQuery) *tsdb.QueryResult { + // Real work is in javascript client + return tsdb.NewQueryResult() + }, + }) + registerScenario(&Scenario{ Id: "table_static", Name: "Table Static", diff --git a/public/app/plugins/datasource/testdata/datasource.ts b/public/app/plugins/datasource/testdata/datasource.ts index 2a60728eece..f0b3e0dcfc6 100644 --- a/public/app/plugins/datasource/testdata/datasource.ts +++ b/public/app/plugins/datasource/testdata/datasource.ts @@ -7,6 +7,8 @@ import { MetricFindValue, TableData, TimeSeries, + LoadingState, + ArrayDataFrame, } from '@grafana/data'; import { Scenario, TestDataQuery } from './types'; import { getBackendSrv } from '@grafana/runtime'; @@ -34,6 +36,8 @@ export class TestDataDataSource extends DataSourceApi { } if (target.scenarioId === 'streaming_client') { streams.push(runStream(target, options)); + } else if (target.scenarioId === 'grafana_api') { + streams.push(runGrafanaAPI(target, options)); } else { queries.push({ ...target, @@ -145,3 +149,18 @@ export class TestDataDataSource extends DataSourceApi { }); } } + +function runGrafanaAPI(target: TestDataQuery, req: DataQueryRequest): Observable { + const url = `/api/${target.stringInput}`; + return from( + getBackendSrv() + .get(url) + .then(res => { + const frame = new ArrayDataFrame(res); + return { + state: LoadingState.Done, + data: [frame], + }; + }) + ); +} diff --git a/public/app/plugins/datasource/testdata/partials/query.editor.html b/public/app/plugins/datasource/testdata/partials/query.editor.html index 545eaa7c3fb..88fd9423b05 100644 --- a/public/app/plugins/datasource/testdata/partials/query.editor.html +++ b/public/app/plugins/datasource/testdata/partials/query.editor.html @@ -188,6 +188,21 @@ + +
+
+ +
+ +
+
+
+
diff --git a/public/app/plugins/datasource/testdata/query_ctrl.ts b/public/app/plugins/datasource/testdata/query_ctrl.ts index 21e923e0861..dad3cdc6f6f 100644 --- a/public/app/plugins/datasource/testdata/query_ctrl.ts +++ b/public/app/plugins/datasource/testdata/query_ctrl.ts @@ -115,6 +115,12 @@ export class TestDataQueryCtrl extends QueryCtrl { delete this.target.csvWave; } + if (this.target.scenarioId === 'grafana_api') { + this.target.stringInput = 'datasources'; + } else { + delete this.target.stringInput; + } + this.refresh(); } diff --git a/public/app/plugins/panel/table/module.tsx b/public/app/plugins/panel/table/module.tsx index 55ae50964c2..2e5a96043e9 100644 --- a/public/app/plugins/panel/table/module.tsx +++ b/public/app/plugins/panel/table/module.tsx @@ -2,6 +2,7 @@ import { PanelPlugin } from '@grafana/data'; import { TablePanel } from './TablePanel'; import { CustomFieldConfig, Options } from './types'; import { tablePanelChangedHandler, tableMigrationHandler } from './migrations'; +import { TableCellDisplayMode } from '@grafana/ui/src/components/Table/types'; export const plugin = new PanelPlugin(TablePanel) .setPanelChangeHandler(tablePanelChangedHandler) @@ -39,11 +40,12 @@ export const plugin = new PanelPlugin(TablePanel) description: 'Color text, background, show as gauge, etc', settings: { options: [ - { value: 'auto', label: 'Auto' }, - { value: 'color-text', label: 'Color text' }, - { value: 'color-background', label: 'Color background' }, - { value: 'gradient-gauge', label: 'Gradient gauge' }, - { value: 'lcd-gauge', label: 'LCD gauge' }, + { value: TableCellDisplayMode.Auto, label: 'Auto' }, + { value: TableCellDisplayMode.ColorText, label: 'Color text' }, + { value: TableCellDisplayMode.ColorBackground, label: 'Color background' }, + { value: TableCellDisplayMode.GradientGauge, label: 'Gradient gauge' }, + { value: TableCellDisplayMode.LcdGauge, label: 'LCD gauge' }, + { value: TableCellDisplayMode.JSONView, label: 'JSON View' }, ], }, });