mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
DataLinks: Default to percentEncoding (#64841)
This commit is contained in:
@@ -2,6 +2,8 @@ import { isNumber, set, unset, get, cloneDeep } from 'lodash';
|
|||||||
import { useMemo, useRef } from 'react';
|
import { useMemo, useRef } from 'react';
|
||||||
import usePrevious from 'react-use/lib/usePrevious';
|
import usePrevious from 'react-use/lib/usePrevious';
|
||||||
|
|
||||||
|
import { VariableFormatID } from '@grafana/schema';
|
||||||
|
|
||||||
import { compareArrayValues, compareDataFrameStructures, guessFieldTypeForField } from '../dataframe';
|
import { compareArrayValues, compareDataFrameStructures, guessFieldTypeForField } from '../dataframe';
|
||||||
import { getTimeField } from '../dataframe/processDataFrame';
|
import { getTimeField } from '../dataframe/processDataFrame';
|
||||||
import { PanelPlugin } from '../panel/PanelPlugin';
|
import { PanelPlugin } from '../panel/PanelPlugin';
|
||||||
@@ -455,7 +457,6 @@ export const getLinksSupplier =
|
|||||||
replaceVariables,
|
replaceVariables,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let href = link.onBuildUrl
|
let href = link.onBuildUrl
|
||||||
? link.onBuildUrl({
|
? link.onBuildUrl({
|
||||||
origin: field,
|
origin: field,
|
||||||
@@ -464,8 +465,8 @@ export const getLinksSupplier =
|
|||||||
: link.url;
|
: link.url;
|
||||||
|
|
||||||
if (href) {
|
if (href) {
|
||||||
locationUtil.assureBaseUrl(href.replace(/\n/g, ''));
|
href = locationUtil.assureBaseUrl(href.replace(/\n/g, ''));
|
||||||
href = replaceVariables(href, variables);
|
href = replaceVariables(href, variables, VariableFormatID.PercentEncode);
|
||||||
href = locationUtil.processUrl(href);
|
href = locationUtil.processUrl(href);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -749,6 +749,29 @@ export type TimeZoneUtc = 'utc';
|
|||||||
*/
|
*/
|
||||||
export type TimeZoneBrowser = 'browser';
|
export type TimeZoneBrowser = 'browser';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Optional formats for the template variable replace functions
|
||||||
|
* See also https://grafana.com/docs/grafana/latest/dashboards/variables/variable-syntax/#advanced-variable-format-options
|
||||||
|
*/
|
||||||
|
export enum VariableFormatID {
|
||||||
|
CSV = 'csv',
|
||||||
|
Date = 'date',
|
||||||
|
Distributed = 'distributed',
|
||||||
|
DoubleQuote = 'doublequote',
|
||||||
|
Glob = 'glob',
|
||||||
|
HTML = 'html',
|
||||||
|
JSON = 'json',
|
||||||
|
Lucene = 'lucene',
|
||||||
|
PercentEncode = 'percentencode',
|
||||||
|
Pipe = 'pipe',
|
||||||
|
QueryParam = 'queryparam',
|
||||||
|
Raw = 'raw',
|
||||||
|
Regex = 'regex',
|
||||||
|
SQLString = 'sqlstring',
|
||||||
|
SingleQuote = 'singlequote',
|
||||||
|
Text = 'text',
|
||||||
|
}
|
||||||
|
|
||||||
export interface DataSourceRef {
|
export interface DataSourceRef {
|
||||||
/**
|
/**
|
||||||
* The plugin type-id
|
* The plugin type-id
|
||||||
|
|||||||
37
packages/grafana-schema/src/common/variables.cue
Normal file
37
packages/grafana-schema/src/common/variables.cue
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
package common
|
||||||
|
|
||||||
|
// Optional formats for the template variable replace functions
|
||||||
|
// See also https://grafana.com/docs/grafana/latest/dashboards/variables/variable-syntax/#advanced-variable-format-options
|
||||||
|
VariableFormatID:
|
||||||
|
// Values are lucene escaped and multi-valued variables generate an OR expression
|
||||||
|
"lucene" |
|
||||||
|
// Raw values
|
||||||
|
"raw" |
|
||||||
|
// Values are regex escaped and multi-valued variables generate a (<value>|<value>) expression
|
||||||
|
"regex" |
|
||||||
|
// Values are separated by | character
|
||||||
|
"pipe" |
|
||||||
|
// Multiple values are formatted like variable=value
|
||||||
|
"distributed" |
|
||||||
|
// Comma seperated values
|
||||||
|
"csv" |
|
||||||
|
// HTML escaped
|
||||||
|
"html" |
|
||||||
|
// JSON values
|
||||||
|
"json" |
|
||||||
|
// Percent encode
|
||||||
|
"percentencode" |
|
||||||
|
// Single quote
|
||||||
|
"singlequote" |
|
||||||
|
// Double quote
|
||||||
|
"doublequote" |
|
||||||
|
// SQL string quoting and commas for use in IN statements and other scenarios
|
||||||
|
"sqlstring" |
|
||||||
|
// Date
|
||||||
|
"date" |
|
||||||
|
// Format multi-valued variables using glob syntax, example {value1,value2}
|
||||||
|
"glob" |
|
||||||
|
// Format variables in their text representation. Example in multi-variable scenario A + B + C.
|
||||||
|
"text" |
|
||||||
|
// Format variables as URL parameters. Example in multi-variable scenario A + B + C => var-foo=A&var-foo=B&var-foo=C.
|
||||||
|
"queryparam" @cuetsy(kind="enum",memberNames="Lucene|Raw|Regex|Pipe|Distributed|CSV|HTML|JSON|PercentEncode|SingleQuote|DoubleQuote|SQLString|Date|Glob|Text|QueryParam")
|
||||||
@@ -122,15 +122,15 @@ describe('getFieldLinksSupplier', () => {
|
|||||||
expect(links).toMatchInlineSnapshot(`
|
expect(links).toMatchInlineSnapshot(`
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"href": "http://go/100.200 kW",
|
"href": "http://go/100.200%20kW",
|
||||||
"title": "By Name",
|
"title": "By Name",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"href": "http://go/100.200 kW",
|
"href": "http://go/100.200%20kW",
|
||||||
"title": "By Index",
|
"title": "By Index",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"href": "http://go/100.200 kW",
|
"href": "http://go/100.200%20kW",
|
||||||
"title": "By Title",
|
"title": "By Title",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -146,7 +146,7 @@ describe('getFieldLinksSupplier', () => {
|
|||||||
"title": "Unknown Field",
|
"title": "Unknown Field",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"href": "http://go/Hello Templates",
|
"href": "http://go/Hello%20Templates",
|
||||||
"title": "Data Frame name",
|
"title": "Data Frame name",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import {
|
|||||||
VariableSuggestionsScope,
|
VariableSuggestionsScope,
|
||||||
} from '@grafana/data';
|
} from '@grafana/data';
|
||||||
import { getTemplateSrv } from '@grafana/runtime';
|
import { getTemplateSrv } from '@grafana/runtime';
|
||||||
|
import { FormatRegistryID } from '@grafana/scenes';
|
||||||
import { getConfig } from 'app/core/config';
|
import { getConfig } from 'app/core/config';
|
||||||
import { getTimeSrv } from 'app/features/dashboard/services/TimeSrv';
|
import { getTimeSrv } from 'app/features/dashboard/services/TimeSrv';
|
||||||
|
|
||||||
@@ -304,7 +305,7 @@ export class LinkSrv implements LinkService {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (replaceVariables) {
|
if (replaceVariables) {
|
||||||
info.href = replaceVariables(info.href);
|
info.href = replaceVariables(info.href, undefined, FormatRegistryID.percentEncode);
|
||||||
info.title = replaceVariables(link.title);
|
info.title = replaceVariables(link.title);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { dateTime, TimeRange } from '@grafana/data';
|
import { dateTime, TimeRange } from '@grafana/data';
|
||||||
import { setDataSourceSrv } from '@grafana/runtime';
|
import { setDataSourceSrv } from '@grafana/runtime';
|
||||||
import { FormatRegistryID, TestVariable } from '@grafana/scenes';
|
import { FormatRegistryID, TestVariable } from '@grafana/scenes';
|
||||||
|
import { VariableFormatID } from '@grafana/schema';
|
||||||
|
|
||||||
import { silenceConsoleOutput } from '../../../test/core/utils/silenceConsoleOutput';
|
import { silenceConsoleOutput } from '../../../test/core/utils/silenceConsoleOutput';
|
||||||
import { initTemplateSrv } from '../../../test/helpers/initTemplateSrv';
|
import { initTemplateSrv } from '../../../test/helpers/initTemplateSrv';
|
||||||
@@ -388,12 +389,12 @@ describe('templateSrv', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('multi value and csv format should render csv string', () => {
|
it('multi value and csv format should render csv string', () => {
|
||||||
const result = _templateSrv.formatValue(['test', 'test2'], 'csv');
|
const result = _templateSrv.formatValue(['test', 'test2'], VariableFormatID.CSV);
|
||||||
expect(result).toBe('test,test2');
|
expect(result).toBe('test,test2');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('multi value and percentencode format should render percent-encoded string', () => {
|
it('multi value and percentencode format should render percent-encoded string', () => {
|
||||||
const result = _templateSrv.formatValue(['foo()bar BAZ', 'test2'], 'percentencode');
|
const result = _templateSrv.formatValue(['foo()bar BAZ', 'test2'], VariableFormatID.PercentEncode);
|
||||||
expect(result).toBe('%7Bfoo%28%29bar%20BAZ%2Ctest2%7D');
|
expect(result).toBe('%7Bfoo%28%29bar%20BAZ%2Ctest2%7D');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user