DashboardScene: Support dashboard links (#77855)

* MenuItem: Allow react node as label

* LinkButton: Expose ButtonLinkProps

* Typecheck fix

* DashboardLinks: Refactor and use LinkButton and menu

* DashbaordLinks scene object

* Use flex layout for dashboard controls

* Update public/app/features/dashboard/components/SubMenu/DashboardLinksDashboard.tsx

Co-authored-by: Alex Khomenko <Clarity-89@users.noreply.github.com>

* fix keepTime and includeVars

* Add ellipsis to menu item label and description

* Use DashboardLink type from grafana/schema

* Update dashboard scene controls layout

* Fix e2e

* Test fix

* Bring back keyboard navigation

* Remove unused code

* One more fix

---------

Co-authored-by: Alex Khomenko <Clarity-89@users.noreply.github.com>
Co-authored-by: Torkel Ödegaard <torkel@grafana.com>
This commit is contained in:
Dominik Prokop
2023-11-15 16:49:51 +01:00
committed by GitHub
parent dfa506857a
commit 0122f7ccad
24 changed files with 324 additions and 201 deletions

View File

@@ -20,11 +20,8 @@ import {
VariableSuggestionsScope,
} from '@grafana/data';
import { getTemplateSrv } from '@grafana/runtime';
import { VariableFormatID } from '@grafana/schema';
import { DashboardLink, VariableFormatID } from '@grafana/schema';
import { getConfig } from 'app/core/config';
import { getTimeSrv } from 'app/features/dashboard/services/TimeSrv';
import { getVariablesUrlParams } from '../../variables/getAllVariableValuesForUrl';
const timeRangeVars = [
{
@@ -254,24 +251,20 @@ export interface LinkService {
}
export class LinkSrv implements LinkService {
getLinkUrl(link: any) {
let url = locationUtil.assureBaseUrl(getTemplateSrv().replace(link.url || ''));
getLinkUrl(link: DashboardLink) {
let params: { [key: string]: any } = {};
if (link.keepTime) {
const range = getTimeSrv().timeRangeForUrl();
params['from'] = range.from;
params['to'] = range.to;
params[`\$${DataLinkBuiltInVars.keepTime}`] = true;
}
if (link.includeVars) {
params = {
...params,
...getVariablesUrlParams(),
};
params[`\$${DataLinkBuiltInVars.includeVars}`] = true;
}
url = urlUtil.appendQueryToUrl(url, urlUtil.toUrlParams(params));
let url = locationUtil.assureBaseUrl(urlUtil.appendQueryToUrl(link.url || '', urlUtil.toUrlParams(params)));
url = getTemplateSrv().replace(url);
return getConfig().disableSanitizeHtml ? url : textUtil.sanitizeUrl(url);
}

View File

@@ -1,5 +1,6 @@
import { FieldType, GrafanaConfig, locationUtil, toDataFrame, VariableOrigin } from '@grafana/data';
import { setTemplateSrv } from '@grafana/runtime';
import { DashboardLink } from '@grafana/schema';
import { ContextSrv } from 'app/core/services/context_srv';
import { getTimeSrv, setTimeSrv, TimeSrv } from 'app/features/dashboard/services/TimeSrv';
import { TimeModel } from 'app/features/dashboard/state/TimeModel';
@@ -176,9 +177,27 @@ describe('linkSrv', () => {
it('converts link urls', () => {
const linkUrl = linkSrv.getLinkUrl({
url: '/graph',
asDropdown: false,
icon: 'external link',
targetBlank: false,
includeVars: false,
keepTime: false,
tags: [],
title: 'Visit home',
tooltip: 'Visit home',
type: 'link',
});
const linkUrlWithVar = linkSrv.getLinkUrl({
url: '/graph?home=$home',
asDropdown: false,
icon: 'external link',
targetBlank: false,
includeVars: false,
keepTime: false,
tags: [],
title: 'Visit home',
tooltip: 'Visit home',
type: 'link',
});
expect(linkUrl).toBe('/graph');
@@ -187,8 +206,16 @@ describe('linkSrv', () => {
it('appends current dashboard time range if keepTime is true', () => {
const anchorInfoKeepTime = linkSrv.getLinkUrl({
keepTime: true,
url: '/graph',
asDropdown: false,
icon: 'external link',
targetBlank: false,
includeVars: false,
keepTime: true,
tags: [],
title: 'Visit home',
tooltip: 'Visit home',
type: 'link',
});
expect(anchorInfoKeepTime).toBe('/graph?from=now-1h&to=now');
@@ -196,16 +223,33 @@ describe('linkSrv', () => {
it('adds all variables to the url if includeVars is true', () => {
const anchorInfoIncludeVars = linkSrv.getLinkUrl({
includeVars: true,
url: '/graph',
asDropdown: false,
icon: 'external link',
targetBlank: false,
includeVars: true,
keepTime: false,
tags: [],
title: 'Visit home',
tooltip: 'Visit home',
type: 'link',
});
expect(anchorInfoIncludeVars).toBe('/graph?var-home=127.0.0.1&var-server1=192.168.0.100');
});
it('respects config disableSanitizeHtml', () => {
const anchorInfo = {
const anchorInfo: DashboardLink = {
url: 'javascript:alert(document.domain)',
asDropdown: false,
icon: 'external link',
targetBlank: false,
includeVars: false,
keepTime: false,
tags: [],
title: 'Visit home',
tooltip: 'Visit home',
type: 'link',
};
expect(linkSrv.getLinkUrl(anchorInfo)).toBe('about:blank');