From 17b2fb04e87bd489523f0ec91b14371b980eb80a Mon Sep 17 00:00:00 2001 From: Ryan McKinley Date: Fri, 16 Sep 2022 10:28:47 -0700 Subject: [PATCH] DashboardQuery: Expand query options (#53998) --- .betterer.results | 4 +- devenv/dev-dashboards/transforms/reuse.json | 536 ++++++++++++++++++ .../components/HelpWizard/HelpWizard.test.tsx | 2 +- .../dashboard/components/HelpWizard/utils.ts | 34 +- .../features/query/state/PanelQueryRunner.ts | 2 +- .../dashboard/DashboardQueryEditor.tsx | 124 +++- .../dashboard/DashboardQueryRow.tsx | 49 -- .../dashboard/runSharedRequest.test.ts | 80 ++- .../datasource/dashboard/runSharedRequest.ts | 26 +- .../app/plugins/datasource/dashboard/types.ts | 4 +- 10 files changed, 755 insertions(+), 106 deletions(-) create mode 100644 devenv/dev-dashboards/transforms/reuse.json delete mode 100644 public/app/plugins/datasource/dashboard/DashboardQueryRow.tsx diff --git a/.betterer.results b/.betterer.results index e22d95d635f..f3591711fe7 100644 --- a/.betterer.results +++ b/.betterer.results @@ -6062,9 +6062,7 @@ exports[`better eslint`] = { [0, 0, 0, "Unexpected any. Specify a different type.", "1"] ], "public/app/plugins/datasource/dashboard/DashboardQueryEditor.tsx:5381": [ - [0, 0, 0, "Do not use any type assertions.", "0"], - [0, 0, 0, "Do not use any type assertions.", "1"], - [0, 0, 0, "Do not use any type assertions.", "2"] + [0, 0, 0, "Do not use any type assertions.", "0"] ], "public/app/plugins/datasource/dashboard/runSharedRequest.ts:5381": [ [0, 0, 0, "Do not use any type assertions.", "0"], diff --git a/devenv/dev-dashboards/transforms/reuse.json b/devenv/dev-dashboards/transforms/reuse.json new file mode 100644 index 00000000000..41667ce6933 --- /dev/null +++ b/devenv/dev-dashboards/transforms/reuse.json @@ -0,0 +1,536 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 1394, + "links": [], + "liveNow": false, + "panels": [ + { + "datasource": { + "type": "testdata", + "uid": "PD8C576611E62080A" + }, + "gridPos": { + "h": 3, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 9, + "options": { + "content": "Dashboard queries allow re-using the same results from one panel in another panel context.\n\nThis dashboard shows a single panel that makes a real query and applies transformations. The other panels, all use the same results rather than make their own query requests.", + "mode": "markdown" + }, + "pluginVersion": "9.2.0-pre", + "type": "text" + }, + { + "datasource": { + "type": "testdata", + "uid": "PD8C576611E62080A" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "displayMode": "auto", + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 18, + "w": 7, + "x": 0, + "y": 3 + }, + "id": 2, + "options": { + "footer": { + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true + }, + "pluginVersion": "9.2.0-pre", + "targets": [ + { + "csvFileName": "flight_info_by_state.csv", + "datasource": { + "type": "testdata", + "uid": "PD8C576611E62080A" + }, + "refId": "A", + "scenarioId": "csv_file" + }, + { + "csvFileName": "population_by_state.csv", + "datasource": { + "type": "testdata", + "uid": "PD8C576611E62080A" + }, + "refId": "B", + "scenarioId": "csv_file" + } + ], + "title": "Raw data -- with outer join", + "transformations": [ + { + "id": "seriesToColumns", + "options": { + "byField": "State", + "mode": "outer" + } + }, + { + "id": "organize", + "options": { + "excludeByName": { + "1980 population_by_state.csv": true, + "2000 population_by_state.csv": true, + "DestLocation flight_info_by_state.csv": true, + "Lat flight_info_by_state.csv": true, + "Lng flight_info_by_state.csv": true, + "Price flight_info_by_state.csv": true + }, + "indexByName": {}, + "renameByName": { + "2020 population_by_state.csv": "2020 population", + "Count flight_info_by_state.csv": "Flight count", + "Price flight_info_by_state.csv": "" + } + } + } + ], + "type": "table" + }, + { + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "displayMode": "auto", + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 11, + "x": 7, + "y": 3 + }, + "id": 4, + "options": { + "footer": { + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true + }, + "pluginVersion": "9.2.0-pre", + "targets": [ + { + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" + }, + "panelId": 2, + "refId": "A" + } + ], + "title": "Reused data (without transform)", + "type": "table" + }, + { + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 6, + "x": 18, + "y": 3 + }, + "id": 5, + "options": { + "basemap": { + "config": {}, + "name": "Layer 0", + "type": "default" + }, + "controls": { + "mouseWheelZoom": true, + "showAttribution": true, + "showDebug": false, + "showMeasure": false, + "showScale": false, + "showZoom": true + }, + "layers": [ + { + "config": { + "showLegend": true, + "style": { + "color": { + "fixed": "dark-green" + }, + "opacity": 0.4, + "rotation": { + "fixed": 0, + "max": 360, + "min": -360, + "mode": "mod" + }, + "size": { + "field": "Flight count", + "fixed": 5, + "max": 15, + "min": 2 + }, + "symbol": { + "fixed": "img/icons/marker/circle.svg", + "mode": "fixed" + }, + "textConfig": { + "fontSize": 12, + "offsetX": 0, + "offsetY": 0, + "textAlign": "center", + "textBaseline": "middle" + } + } + }, + "location": { + "gazetteer": "public/gazetteer/usa-states.json", + "lookup": "State", + "mode": "lookup" + }, + "name": "Flight count", + "tooltip": true, + "type": "markers" + } + ], + "tooltip": { + "mode": "details" + }, + "view": { + "id": "coords", + "lat": 35.70008, + "lon": -93.558296, + "zoom": 3.09 + } + }, + "pluginVersion": "9.2.0-pre", + "targets": [ + { + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" + }, + "panelId": 2, + "refId": "A", + "withTransforms": true + } + ], + "title": "Reused data (without transform)", + "type": "geomap" + }, + { + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "displayMode": "auto", + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 11, + "x": 7, + "y": 12 + }, + "id": 6, + "options": { + "footer": { + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true + }, + "pluginVersion": "9.2.0-pre", + "targets": [ + { + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" + }, + "panelId": 2, + "refId": "A", + "withTransforms": true + } + ], + "title": "Reused data (with transform)", + "type": "table" + }, + { + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 6, + "x": 18, + "y": 12 + }, + "id": 7, + "options": { + "basemap": { + "config": {}, + "name": "Layer 0", + "type": "default" + }, + "controls": { + "mouseWheelZoom": true, + "showAttribution": true, + "showDebug": false, + "showMeasure": false, + "showScale": false, + "showZoom": true + }, + "layers": [ + { + "config": { + "showLegend": true, + "style": { + "color": { + "fixed": "dark-green" + }, + "opacity": 0.4, + "rotation": { + "fixed": 0, + "max": 360, + "min": -360, + "mode": "mod" + }, + "size": { + "field": "2020 population", + "fixed": 5, + "max": 15, + "min": 2 + }, + "symbol": { + "fixed": "img/icons/marker/circle.svg", + "mode": "fixed" + }, + "textConfig": { + "fontSize": 12, + "offsetX": 0, + "offsetY": 0, + "textAlign": "center", + "textBaseline": "middle" + } + } + }, + "location": { + "gazetteer": "public/gazetteer/usa-states.json", + "lookup": "State", + "mode": "lookup" + }, + "name": "2022 Population", + "tooltip": true, + "type": "markers" + } + ], + "tooltip": { + "mode": "details" + }, + "view": { + "id": "coords", + "lat": 35.70008, + "lon": -93.558296, + "zoom": 3.09 + } + }, + "pluginVersion": "9.2.0-pre", + "targets": [ + { + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" + }, + "panelId": 2, + "refId": "A", + "withTransforms": true + } + ], + "title": "Reused data (with transform)", + "type": "geomap" + } + ], + "schemaVersion": 37, + "style": "dark", + "tags": ["devenv"], + "templating": { + "list": [] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "Reuse dashboard queries", + "uid": "fYGWTVW4k" + } diff --git a/public/app/features/dashboard/components/HelpWizard/HelpWizard.test.tsx b/public/app/features/dashboard/components/HelpWizard/HelpWizard.test.tsx index b47443f1c01..7b5aca434c5 100644 --- a/public/app/features/dashboard/components/HelpWizard/HelpWizard.test.tsx +++ b/public/app/features/dashboard/components/HelpWizard/HelpWizard.test.tsx @@ -31,6 +31,6 @@ function setup() { describe('SupportSnapshot', () => { it('Can render', async () => { setup(); - expect(await screen.findByRole('button', { name: 'Dashboard (2.94 KiB)' })).toBeInTheDocument(); + expect(await screen.findByRole('button', { name: 'Dashboard (2.97 KiB)' })).toBeInTheDocument(); }); }); diff --git a/public/app/features/dashboard/components/HelpWizard/utils.ts b/public/app/features/dashboard/components/HelpWizard/utils.ts index 3df0a4c73fe..f51bc33899a 100644 --- a/public/app/features/dashboard/components/HelpWizard/utils.ts +++ b/public/app/features/dashboard/components/HelpWizard/utils.ts @@ -118,15 +118,19 @@ export async function getDebugDashboard(panel: PanelModel, rand: Randomize, time ], }; - if (data.annotations?.length) { - const anno: DataFrameJSON[] = []; - for (const f of frames) { - if (f.schema?.meta?.dataTopic) { - delete f.schema.meta.dataTopic; - anno.push(f); - } - } + if (saveModel.transformations?.length) { + const last = dashboard.panels[dashboard.panels.length - 1]; + last.title = last.title + ' (after transformations)'; + + const before = cloneDeep(last); + before.id = 100; + before.title = 'Data (before transformations)'; + before.gridPos.w = 24; // full width + before.targets[0].withTransforms = false; + dashboard.panels.push(before); + } + if (data.annotations?.length) { dashboard.panels.push({ id: 7, gridPos: { @@ -138,17 +142,22 @@ export async function getDebugDashboard(panel: PanelModel, rand: Randomize, time type: 'table', title: 'Annotations', datasource: { - type: 'grafana', - uid: 'grafana', + type: 'datasource', + uid: '-- Dashboard --', }, options: { showTypeIcons: true, }, targets: [ { + datasource: { + type: 'datasource', + uid: '-- Dashboard --', + }, + panelId: 2, + withTransforms: true, + topic: DataTopic.Annotations, refId: 'A', - rawFrameContent: JSON.stringify(anno), - scenarioId: 'raw_frame', }, ], }); @@ -287,6 +296,7 @@ const embeddedDataTemplate: any = { uid: '-- Dashboard --', }, panelId: 2, + withTransforms: true, refId: 'A', }, ], diff --git a/public/app/features/query/state/PanelQueryRunner.ts b/public/app/features/query/state/PanelQueryRunner.ts index 3dd2c70362c..9202bd227f4 100644 --- a/public/app/features/query/state/PanelQueryRunner.ts +++ b/public/app/features/query/state/PanelQueryRunner.ts @@ -216,7 +216,7 @@ export class PanelQueryRunner { } = options; if (isSharedDashboardQuery(datasource)) { - this.pipeToSubject(runSharedRequest(options), panelId); + this.pipeToSubject(runSharedRequest(options, queries[0]), panelId); return; } diff --git a/public/app/plugins/datasource/dashboard/DashboardQueryEditor.tsx b/public/app/plugins/datasource/dashboard/DashboardQueryEditor.tsx index f1c406c51db..6415142017b 100644 --- a/public/app/plugins/datasource/dashboard/DashboardQueryEditor.tsx +++ b/public/app/plugins/datasource/dashboard/DashboardQueryEditor.tsx @@ -4,15 +4,14 @@ import pluralize from 'pluralize'; import React, { useCallback, useMemo } from 'react'; import { useAsync } from 'react-use'; -import { DataQuery, GrafanaTheme2, PanelData, SelectableValue } from '@grafana/data'; -import { InlineField, Select, useStyles2, VerticalGroup } from '@grafana/ui'; +import { DataQuery, GrafanaTheme2, PanelData, SelectableValue, DataTopic } from '@grafana/data'; +import { Field, Select, useStyles2, VerticalGroup, Spinner, Switch, RadioButtonGroup, Icon } from '@grafana/ui'; import config from 'app/core/config'; import { getDashboardSrv } from 'app/features/dashboard/services/DashboardSrv'; import { PanelModel } from 'app/features/dashboard/state'; import { getDatasourceSrv } from 'app/features/plugins/datasource_srv'; import { filterPanelDataToQuery } from 'app/features/query/components/QueryEditorRow'; -import { DashboardQueryRow } from './DashboardQueryRow'; import { DashboardQuery, ResultInfo, SHARED_DASHBOARD_QUERY } from './types'; function getQueryDisplayText(query: DataQuery): string { @@ -26,25 +25,30 @@ interface Props { onRunQueries: () => void; } +const topics = [ + { label: 'All data', value: false }, + { label: 'Annotations', value: true, description: 'Include annotations as regular data' }, +]; + export function DashboardQueryEditor({ panelData, queries, onChange, onRunQueries }: Props) { const { value: defaultDatasource } = useAsync(() => getDatasourceSrv().get()); - const { value: results, loading: loadingResults } = useAsync(async (): Promise => { - const query = queries[0] as DashboardQuery; + const query = queries[0] as DashboardQuery; + + const panel = useMemo(() => { const dashboard = getDashboardSrv().getCurrent(); - const panel = dashboard?.getPanelById(query.panelId ?? -124134); + return dashboard?.getPanelById(query.panelId ?? -124134); + }, [query.panelId]); + const { value: results, loading: loadingResults } = useAsync(async (): Promise => { if (!panel) { return []; } - const mainDS = await getDatasourceSrv().get(panel.datasource); return Promise.all( panel.targets.map(async (query) => { const ds = query.datasource ? await getDatasourceSrv().get(query.datasource) : mainDS; const fmt = ds.getQueryDisplayText || getQueryDisplayText; - const queryData = filterPanelDataToQuery(panelData, query.refId) ?? panelData; - return { refId: query.refId, query: fmt(query), @@ -54,21 +58,41 @@ export function DashboardQueryEditor({ panelData, queries, onChange, onRunQuerie }; }) ); - }, [panelData, queries]); + }, [panelData, panel]); - const query = queries[0] as DashboardQuery; + const onUpdateQuery = useCallback( + (query: DashboardQuery) => { + onChange([query]); + onRunQueries(); + }, + [onChange, onRunQueries] + ); const onPanelChanged = useCallback( (id: number) => { - onChange([ - { - ...query, - panelId: id, - } as DashboardQuery, - ]); - onRunQueries(); + onUpdateQuery({ + ...query, + panelId: id, + }); + }, + [query, onUpdateQuery] + ); + + const onTransformToggle = useCallback(() => { + onUpdateQuery({ + ...query, + withTransforms: !query.withTransforms, + }); + }, [query, onUpdateQuery]); + + const onTopicChanged = useCallback( + (t: boolean) => { + onUpdateQuery({ + ...query, + topic: t ? DataTopic.Annotations : undefined, + }); }, - [query, onChange, onRunQueries] + [query, onUpdateQuery] ); const getPanelDescription = useCallback( @@ -119,10 +143,11 @@ export function DashboardQueryEditor({ panelData, queries, onChange, onRunQuerie const selected = panels.find((panel) => panel.value === query.panelId); // Same as current URL, but different panelId const editURL = `d/${dashboard.uid}/${dashboard.title}?&editPanel=${query.panelId}`; + const showTransforms = Boolean(query.withTransforms || panel?.transformations?.length); return ( <> - +