* {
- margin-right: ${theme.spacing.xs};
- &:last-child {
- margin-right: 0;
- }
- }
- `
- )}
- >
-
+ const listItemStyle = css`
+ margin-bottom: ${theme.spacing.sm};
+ `;
+ const infoTextStyle = css`
+ padding-bottom: ${theme.spacing.md};
+ margin-left: 66px;
+ color: ${theme.colors.textWeak};
+ `;
+
+ return (
+
+
+
+
+
+
}
className={css`
width: 100%;
`}
/>
-
-
-
-
-
-
+ {isLast && (
+
+ With data links you can reference data variables like series name, labels and values. Type CMD+Space,
+ CTRL+Space, or $ to open variable suggestions.
+
+ )}
);
}
diff --git a/packages/grafana-ui/src/components/DataLinks/DataLinkInput.tsx b/packages/grafana-ui/src/components/DataLinks/DataLinkInput.tsx
index c3463275cf6..a9c15f4be7b 100644
--- a/packages/grafana-ui/src/components/DataLinks/DataLinkInput.tsx
+++ b/packages/grafana-ui/src/components/DataLinks/DataLinkInput.tsx
@@ -1,6 +1,6 @@
import React, { useState, useMemo, useCallback, useContext } from 'react';
import { VariableSuggestion, VariableOrigin, DataLinkSuggestions } from './DataLinkSuggestions';
-import { makeValue, ThemeContext } from '../../index';
+import { makeValue, ThemeContext, DataLinkBuiltInVars } from '../../index';
import { SelectionReference } from './SelectionReference';
import { Portal } from '../index';
// @ts-ignore
@@ -77,10 +77,10 @@ export const DataLinkInput: React.FC
= ({ value, onChange, s
}
};
- useDebounce(updateUsedSuggestions, 500, [linkUrl]);
+ useDebounce(updateUsedSuggestions, 250, [linkUrl]);
const onKeyDown = (event: KeyboardEvent) => {
- if (event.key === 'Backspace') {
+ if (event.key === 'Backspace' || event.key === 'Escape') {
setShowingSuggestions(false);
setSuggestionsIndex(0);
}
@@ -111,7 +111,7 @@ export const DataLinkInput: React.FC = ({ value, onChange, s
setShowingSuggestions(true);
}
- if (event.key === 'Enter') {
+ if (event.key === 'Enter' && showingSuggestions) {
// Preventing entering a new line
// As of https://github.com/ianstormtaylor/slate/issues/1345#issuecomment-340508289
return false;
@@ -134,7 +134,7 @@ export const DataLinkInput: React.FC = ({ value, onChange, s
const change = linkUrl.change();
- if (item.origin === VariableOrigin.BuiltIn) {
+ if (item.origin !== VariableOrigin.Template || item.value === DataLinkBuiltInVars.includeVars) {
change.insertText(`${includeDollarSign ? '$' : ''}\{${item.value}}`);
} else {
change.insertText(`var-${item.value}=$\{${item.value}}`);
@@ -167,7 +167,7 @@ export const DataLinkInput: React.FC = ({ value, onChange, s
modifiers={{
preventOverflow: { enabled: true, boundariesElement: 'window' },
arrow: { enabled: false },
- offset: { offset: 200 }, // width of the suggestions menu
+ offset: { offset: 250 }, // width of the suggestions menu
}}
>
{({ ref, style, placement }) => {
diff --git a/packages/grafana-ui/src/components/DataLinks/DataLinkSuggestions.tsx b/packages/grafana-ui/src/components/DataLinks/DataLinkSuggestions.tsx
index 0fc14f2b199..2b2ee4e6b48 100644
--- a/packages/grafana-ui/src/components/DataLinks/DataLinkSuggestions.tsx
+++ b/packages/grafana-ui/src/components/DataLinks/DataLinkSuggestions.tsx
@@ -1,16 +1,22 @@
import { GrafanaTheme, selectThemeVariant, ThemeContext } from '../../index';
import { css, cx } from 'emotion';
+import _ from 'lodash';
import React, { useRef, useContext, useMemo } from 'react';
import useClickAway from 'react-use/lib/useClickAway';
import { List } from '../index';
+import tinycolor from 'tinycolor2';
export enum VariableOrigin {
- BuiltIn = 'builtin',
+ Series = 'series',
+ Field = 'field',
+ Value = 'value',
+ BuiltIn = 'built-in',
Template = 'template',
}
export interface VariableSuggestion {
value: string;
+ label: string;
documentation?: string;
origin: VariableOrigin;
}
@@ -71,16 +77,34 @@ const getStyles = (theme: GrafanaTheme) => {
theme.type
);
+ const separatorColor = selectThemeVariant(
+ {
+ light: tinycolor(wrapperBg.toString())
+ .darken(10)
+ .toString(),
+ dark: tinycolor(wrapperBg.toString())
+ .lighten(10)
+ .toString(),
+ },
+ theme.type
+ );
+
return {
+ list: css`
+ border-bottom: 1px solid ${separatorColor};
+ &:last-child {
+ border: none;
+ }
+ `,
wrapper: css`
background: ${wrapperBg};
z-index: 1;
- width: 200px;
+ width: 250px;
box-shadow: 0 5px 10px 0 ${wrapperShadow};
`,
item: css`
background: none;
- padding: 4px 8px;
+ padding: 2px 8px;
color: ${itemColor};
cursor: pointer;
&:hover {
@@ -89,9 +113,6 @@ const getStyles = (theme: GrafanaTheme) => {
`,
label: css`
color: ${theme.colors.textWeak};
- font-size: ${theme.typography.size.sm};
- line-height: ${theme.typography.lineHeight.lg};
- padding: ${theme.spacing.sm};
`,
activeItem: css`
background: ${itemBgActive};
@@ -101,11 +122,11 @@ const getStyles = (theme: GrafanaTheme) => {
`,
itemValue: css`
font-family: ${theme.typography.fontFamily.monospace};
+ font-size: ${theme.typography.size.sm};
`,
itemDocs: css`
margin-top: ${theme.spacing.xs};
color: ${itemDocsColor};
- font-size: ${theme.typography.size.sm};
`,
};
};
@@ -119,34 +140,35 @@ export const DataLinkSuggestions: React.FC = ({ sugges
}
});
- const templateSuggestions = useMemo(() => {
- return suggestions.filter(suggestion => suggestion.origin === VariableOrigin.Template);
- }, [suggestions]);
-
- const builtInSuggestions = useMemo(() => {
- return suggestions.filter(suggestion => suggestion.origin === VariableOrigin.BuiltIn);
+ const groupedSuggestions = useMemo(() => {
+ return _.groupBy(suggestions, s => s.origin);
}, [suggestions]);
const styles = getStyles(theme);
return (
- {templateSuggestions.length > 0 && (
-
- )}
- {builtInSuggestions.length > 0 && (
-
- )}
+ {Object.keys(groupedSuggestions).map((key, i) => {
+ const indexOffset =
+ i === 0
+ ? 0
+ : Object.keys(groupedSuggestions).reduce((acc, current, index) => {
+ if (index >= i) {
+ return acc;
+ }
+ return acc + groupedSuggestions[current].length;
+ }, 0);
+
+ return (
+
+ );
+ })}
);
};
@@ -165,8 +187,8 @@ const DataLinkSuggestionsList: React.FC = React.me
return (
<>
- {label}
{
return (
@@ -175,9 +197,11 @@ const DataLinkSuggestionsList: React.FC = React.me
onClick={() => {
onSuggestionSelect(item);
}}
+ title={item.documentation}
>
- {item.value}
- {item.documentation && {item.documentation}
}
+
+ {label} {item.label}
+
);
}}
diff --git a/packages/grafana-ui/src/components/DataLinks/DataLinksEditor.tsx b/packages/grafana-ui/src/components/DataLinks/DataLinksEditor.tsx
index 725baed7a6c..2d844e83dee 100644
--- a/packages/grafana-ui/src/components/DataLinks/DataLinksEditor.tsx
+++ b/packages/grafana-ui/src/components/DataLinks/DataLinksEditor.tsx
@@ -19,7 +19,7 @@ interface DataLinksEditorProps {
Prism.languages['links'] = {
builtInVariable: {
- pattern: /(\${\w+})/,
+ pattern: /(\${\S+?})/,
},
};
@@ -57,6 +57,7 @@ export const DataLinksEditor: FC