DataLinks: Implement javascript callback (#19851)

This commit is contained in:
Ryan McKinley 2019-10-28 04:08:19 -07:00 committed by GitHub
parent 040801256f
commit 9e004b9211
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 65 additions and 14 deletions

View File

@ -1,11 +1,32 @@
import { ScopedVars } from './ScopedVars';
/**
* Callback info for DataLink click events
*/
export interface DataLinkClickEvent<T = any> {
origin: T;
scopedVars: ScopedVars;
e?: any; // mouse|react event
}
/**
* Link configuration. The values may contain variables that need to be
* processed before running
*/
export interface DataLink {
url: string;
title: string;
targetBlank?: boolean;
// 3: The URL if others did not set it first
url: string;
// 2: If exists, use this to construct the URL
// Not saved in JSON/DTO
onBuildUrl?: (event: DataLinkClickEvent) => string;
// 1: If exists, handle click directly
// Not saved in JSON/DTO
onClick?: (event: DataLinkClickEvent) => void;
}
export type LinkTarget = '_blank' | '_self';
@ -18,6 +39,9 @@ export interface LinkModel<T> {
title: string;
target: LinkTarget;
origin: T;
// When a click callback exists, this is passed the raw mouse|react event
onClick?: (e: any) => void;
}
/**

View File

@ -189,7 +189,7 @@ export const ContextMenu: React.FC<ContextMenuProps> = React.memo(({ x, y, onClo
renderItem={(item, index) => {
return (
<>
<ContextMenuGroup group={item} onItemClick={onClose} />
<ContextMenuGroup group={item} onClick={onClose} />
</>
);
}}
@ -215,7 +215,7 @@ const ContextMenuItem: React.FC<ContextMenuItemProps> = React.memo(
return (
<div className={styles.item}>
<a
href={url}
href={url ? url : undefined}
target={target || '_self'}
className={cx(className, styles.link)}
onClick={e => {
@ -233,10 +233,10 @@ const ContextMenuItem: React.FC<ContextMenuItemProps> = React.memo(
interface ContextMenuGroupProps {
group: ContextMenuGroup;
onItemClick?: () => void;
onClick?: () => void; // Used with 'onClose'
}
const ContextMenuGroup: React.FC<ContextMenuGroupProps> = ({ group, onItemClick }) => {
const ContextMenuGroup: React.FC<ContextMenuGroupProps> = ({ group, onClick }) => {
const theme = useContext(ThemeContext);
const styles = getContextMenuStyles(theme);
@ -261,8 +261,9 @@ const ContextMenuGroup: React.FC<ContextMenuGroupProps> = ({ group, onItemClick
item.onClick(e);
}
if (onItemClick) {
onItemClick();
// Typically closes the context menu
if (onClick) {
onClick();
}
}}
/>

View File

@ -27,6 +27,7 @@ export const linkModelToContextMenuItems: (links: LinkModelSupplier<any>) => Con
url: link.href,
target: link.target,
icon: `fa ${link.target === '_self' ? 'fa-link' : 'fa-external-link'}`,
onClick: link.onClick,
};
});
};

View File

@ -156,11 +156,31 @@ export class LinkSrv implements LinkService {
const params: KeyValue = {};
const timeRangeUrl = toUrlParams(this.timeSrv.timeRangeForUrl());
let href = link.url;
if (link.onBuildUrl) {
href = link.onBuildUrl({
origin,
scopedVars,
});
}
let onClick: (e: any) => void = undefined;
if (link.onClick) {
onClick = (e: any) => {
link.onClick({
origin,
scopedVars,
e,
});
};
}
const info: LinkModel<T> = {
href: link.url.replace(/\s|\n/g, ''),
href: href.replace(/\s|\n/g, ''),
title: this.templateSrv.replace(link.title || '', scopedVars),
target: link.targetBlank ? '_blank' : '_self',
origin,
onClick,
};
this.templateSrv.fillVariableValuesForUrl(params, scopedVars);

View File

@ -214,6 +214,7 @@ class GraphElement {
url: link.href,
target: link.target,
icon: `fa ${link.target === '_self' ? 'fa-link' : 'fa-external-link'}`,
onClick: link.onClick,
};
}),
},
@ -248,19 +249,23 @@ class GraphElement {
if (item) {
// pickup y-axis index to know which field's config to apply
const yAxisConfig = this.panel.yaxes[item.series.yaxis.n === 2 ? 1 : 0];
const fieldConfig = {
decimals: yAxisConfig.decimals,
links: this.panel.options.dataLinks || [],
};
const dataFrame = this.ctrl.dataList[item.series.dataFrameIndex];
const field = dataFrame.fields[item.series.fieldIndex];
let links = this.panel.options.dataLinks || [];
if (field.config.links && field.config.links.length) {
// Append the configured links to the panel datalinks
links = [...links, ...field.config.links];
}
const fieldConfig = {
decimals: yAxisConfig.decimals,
links,
};
const fieldDisplay = getDisplayProcessor({
config: fieldConfig,
theme: getCurrentTheme(),
})(field.values.get(item.dataIndex));
linksSupplier = this.panel.options.dataLinks
linksSupplier = links.length
? getFieldLinksSupplier({
display: fieldDisplay,
name: field.name,