mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
DashList: Update variables in links when they change (#77787)
* user essentials mob! 🔱 lastFile:public/app/plugins/panel/dashlist/DashList.tsx * DashList: Update variables in URL when they change Co-authored-by: eledobleefe <laura.fernandez@grafana.com> Co-authored-by: Joao Silva <joao.silva@grafana.com> Co-authored-by: Ashley Harrison <ashley.harrison@grafana.com> * add e2e test to check dashlist variables are always correctly passed * add comment with link to issue --------- Co-authored-by: Joao Silva <joao.silva@grafana.com> Co-authored-by: eledobleefe <laura.fernandez@grafana.com> Co-authored-by: Ashley Harrison <ashley.harrison@grafana.com> Co-authored-by: joshhunt <josh@trtr.co>
This commit is contained in:
139
devenv/dev-dashboards/panel-dashlist/dashlist_url_variables.json
Normal file
139
devenv/dev-dashboards/panel-dashlist/dashlist_url_variables.json
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
{
|
||||||
|
"__inputs": [
|
||||||
|
{
|
||||||
|
"name": "DS_GDEV-TESTDATA",
|
||||||
|
"label": "gdev-testdata",
|
||||||
|
"description": "",
|
||||||
|
"type": "datasource",
|
||||||
|
"pluginId": "grafana-testdata-datasource",
|
||||||
|
"pluginName": "TestData"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"__elements": {},
|
||||||
|
"__requires": [
|
||||||
|
{
|
||||||
|
"type": "panel",
|
||||||
|
"id": "dashlist",
|
||||||
|
"name": "Dashboard list",
|
||||||
|
"version": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "grafana",
|
||||||
|
"id": "grafana",
|
||||||
|
"name": "Grafana",
|
||||||
|
"version": "10.3.0-pre"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "datasource",
|
||||||
|
"id": "grafana-testdata-datasource",
|
||||||
|
"name": "TestData",
|
||||||
|
"version": "1.0.0"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"annotations": {
|
||||||
|
"list": [
|
||||||
|
{
|
||||||
|
"builtIn": 1,
|
||||||
|
"datasource": {
|
||||||
|
"type": "grafana",
|
||||||
|
"uid": "-- Grafana --"
|
||||||
|
},
|
||||||
|
"enable": true,
|
||||||
|
"hide": true,
|
||||||
|
"iconColor": "rgba(0, 211, 255, 1)",
|
||||||
|
"name": "Annotations & Alerts",
|
||||||
|
"type": "dashboard"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"editable": true,
|
||||||
|
"fiscalYearStartMonth": 0,
|
||||||
|
"graphTooltip": 0,
|
||||||
|
"id": null,
|
||||||
|
"links": [],
|
||||||
|
"liveNow": false,
|
||||||
|
"panels": [
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "grafana-testdata-datasource",
|
||||||
|
"uid": "${DS_GDEV-TESTDATA}"
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 8,
|
||||||
|
"w": 12,
|
||||||
|
"x": 0,
|
||||||
|
"y": 0
|
||||||
|
},
|
||||||
|
"id": 2,
|
||||||
|
"options": {
|
||||||
|
"folderUID": "",
|
||||||
|
"includeVars": true,
|
||||||
|
"keepTime": false,
|
||||||
|
"maxItems": 10,
|
||||||
|
"query": "",
|
||||||
|
"showHeadings": true,
|
||||||
|
"showRecentlyViewed": true,
|
||||||
|
"showSearch": false,
|
||||||
|
"showStarred": false,
|
||||||
|
"tags": []
|
||||||
|
},
|
||||||
|
"pluginVersion": "10.3.0-pre",
|
||||||
|
"title": "Dashboard list panel",
|
||||||
|
"type": "dashlist"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"refresh": "",
|
||||||
|
"schemaVersion": 39,
|
||||||
|
"tags": [],
|
||||||
|
"templating": {
|
||||||
|
"list": [
|
||||||
|
{
|
||||||
|
"current": {
|
||||||
|
"selected": true,
|
||||||
|
"text": "a",
|
||||||
|
"value": "a"
|
||||||
|
},
|
||||||
|
"hide": 0,
|
||||||
|
"includeAll": false,
|
||||||
|
"multi": false,
|
||||||
|
"name": "query0",
|
||||||
|
"options": [
|
||||||
|
{
|
||||||
|
"selected": true,
|
||||||
|
"text": "a",
|
||||||
|
"value": "a"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"selected": false,
|
||||||
|
"text": "b",
|
||||||
|
"value": "b"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"selected": false,
|
||||||
|
"text": "c",
|
||||||
|
"value": "c"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"selected": false,
|
||||||
|
"text": "d",
|
||||||
|
"value": "d"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"query": "a,b,c,d",
|
||||||
|
"queryValue": "",
|
||||||
|
"skipUrlSync": false,
|
||||||
|
"type": "custom"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"time": {
|
||||||
|
"from": "now-6h",
|
||||||
|
"to": "now"
|
||||||
|
},
|
||||||
|
"timepicker": {},
|
||||||
|
"timezone": "",
|
||||||
|
"title": "Panel Tests - DashList variables",
|
||||||
|
"uid": "a6801696-cc53-4196-b1f9-2403e3909185",
|
||||||
|
"version": 1,
|
||||||
|
"weekStart": ""
|
||||||
|
}
|
||||||
@@ -149,6 +149,13 @@ local dashboard = grafana.dashboard;
|
|||||||
id: 0,
|
id: 0,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
dashboard.new('dashlist_url_variables', import '../dev-dashboards/panel-dashlist/dashlist_url_variables.json') +
|
||||||
|
resource.addMetadata('folder', 'dev-dashboards') +
|
||||||
|
{
|
||||||
|
spec+: {
|
||||||
|
id: 0,
|
||||||
|
}
|
||||||
|
},
|
||||||
dashboard.new('datadata-macros', import '../dev-dashboards/feature-templating/datadata-macros.json') +
|
dashboard.new('datadata-macros', import '../dev-dashboards/feature-templating/datadata-macros.json') +
|
||||||
resource.addMetadata('folder', 'dev-dashboards') +
|
resource.addMetadata('folder', 'dev-dashboards') +
|
||||||
{
|
{
|
||||||
|
|||||||
37
e2e/panels-suite/dashlist.spec.ts
Normal file
37
e2e/panels-suite/dashlist.spec.ts
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
import { e2e } from '../utils';
|
||||||
|
const PAGE_UNDER_TEST = 'a6801696-cc53-4196-b1f9-2403e3909185/panel-tests-dashlist-variables';
|
||||||
|
|
||||||
|
describe('DashList panel', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD'));
|
||||||
|
});
|
||||||
|
|
||||||
|
// this is to prevent the fix for https://github.com/grafana/grafana/issues/76800 from regressing
|
||||||
|
it('should pass current variable values correctly when `Include current template variable values` is set', () => {
|
||||||
|
e2e.flows.openDashboard({ uid: PAGE_UNDER_TEST });
|
||||||
|
|
||||||
|
// check the initial value of the urls contain the variable value correctly
|
||||||
|
e2e.components.Panels.Panel.title('Dashboard list panel')
|
||||||
|
.should('be.visible')
|
||||||
|
.within(() => {
|
||||||
|
cy.get('a').each(($el) => {
|
||||||
|
cy.wrap($el).should('have.attr', 'href').and('contain', 'var-query0=a');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// update variable to b
|
||||||
|
e2e.pages.Dashboard.SubMenu.submenuItemLabels('query0').click();
|
||||||
|
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('b').click();
|
||||||
|
// blur the dropdown
|
||||||
|
cy.get('body').click();
|
||||||
|
|
||||||
|
// check the urls are updated with the new variable value
|
||||||
|
e2e.components.Panels.Panel.title('Dashboard list panel')
|
||||||
|
.should('be.visible')
|
||||||
|
.within(() => {
|
||||||
|
cy.get('a').each(($el) => {
|
||||||
|
cy.wrap($el).should('have.attr', 'href').and('contain', 'var-query0=b');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -1,9 +1,18 @@
|
|||||||
import { take } from 'lodash';
|
import { take } from 'lodash';
|
||||||
import React, { useEffect, useMemo, useState } from 'react';
|
import React, { useEffect, useMemo, useState } from 'react';
|
||||||
|
|
||||||
import { DateTime, InterpolateFunction, PanelProps, textUtil, UrlQueryValue, urlUtil } from '@grafana/data';
|
import {
|
||||||
|
DateTime,
|
||||||
|
InterpolateFunction,
|
||||||
|
PanelProps,
|
||||||
|
textUtil,
|
||||||
|
UrlQueryMap,
|
||||||
|
UrlQueryValue,
|
||||||
|
urlUtil,
|
||||||
|
} from '@grafana/data';
|
||||||
import { CustomScrollbar, useStyles2, IconButton } from '@grafana/ui';
|
import { CustomScrollbar, useStyles2, IconButton } from '@grafana/ui';
|
||||||
import { getConfig } from 'app/core/config';
|
import { getConfig } from 'app/core/config';
|
||||||
|
import { appEvents } from 'app/core/core';
|
||||||
import { setStarred } from 'app/core/reducers/navBarTree';
|
import { setStarred } from 'app/core/reducers/navBarTree';
|
||||||
import { getBackendSrv } from 'app/core/services/backend_srv';
|
import { getBackendSrv } from 'app/core/services/backend_srv';
|
||||||
import impressionSrv from 'app/core/services/impression_srv';
|
import impressionSrv from 'app/core/services/impression_srv';
|
||||||
@@ -11,6 +20,7 @@ import { getDashboardSrv } from 'app/features/dashboard/services/DashboardSrv';
|
|||||||
import { getTimeSrv } from 'app/features/dashboard/services/TimeSrv';
|
import { getTimeSrv } from 'app/features/dashboard/services/TimeSrv';
|
||||||
import { DashboardSearchItem } from 'app/features/search/types';
|
import { DashboardSearchItem } from 'app/features/search/types';
|
||||||
import { getVariablesUrlParams } from 'app/features/variables/getAllVariableValuesForUrl';
|
import { getVariablesUrlParams } from 'app/features/variables/getAllVariableValuesForUrl';
|
||||||
|
import { VariablesChanged } from 'app/features/variables/types';
|
||||||
import { useDispatch } from 'app/types';
|
import { useDispatch } from 'app/types';
|
||||||
|
|
||||||
import { Options } from './panelcfg.gen';
|
import { Options } from './panelcfg.gen';
|
||||||
@@ -89,9 +99,29 @@ async function fetchDashboards(options: Options, replaceVars: InterpolateFunctio
|
|||||||
return dashMap;
|
return dashMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function useVariablesForURL(subscribe: boolean) {
|
||||||
|
const [variables, setVariables] = useState<UrlQueryMap>(() => getVariablesUrlParams());
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!subscribe) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const sub = appEvents.subscribe(VariablesChanged, () => {
|
||||||
|
setVariables(getVariablesUrlParams());
|
||||||
|
});
|
||||||
|
|
||||||
|
return () => sub.unsubscribe();
|
||||||
|
}, [subscribe]);
|
||||||
|
|
||||||
|
return variables;
|
||||||
|
}
|
||||||
|
|
||||||
export function DashList(props: PanelProps<Options>) {
|
export function DashList(props: PanelProps<Options>) {
|
||||||
const [dashboards, setDashboards] = useState(new Map<string, Dashboard>());
|
const [dashboards, setDashboards] = useState(new Map<string, Dashboard>());
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
const urlVariables = useVariablesForURL(props.options.includeVars);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchDashboards(props.options, props.replaceVariables).then((dashes) => {
|
fetchDashboards(props.options, props.replaceVariables).then((dashes) => {
|
||||||
setDashboards(dashes);
|
setDashboards(dashes);
|
||||||
@@ -156,7 +186,7 @@ export function DashList(props: PanelProps<Options>) {
|
|||||||
if (props.options.includeVars) {
|
if (props.options.includeVars) {
|
||||||
params = {
|
params = {
|
||||||
...params,
|
...params,
|
||||||
...getVariablesUrlParams(),
|
...urlVariables,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user