mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
147 lines
4.2 KiB
TypeScript
147 lines
4.2 KiB
TypeScript
import React, { PureComponent } from 'react';
|
|
import { Icon, Tooltip } from '@grafana/ui';
|
|
import { sanitize, sanitizeUrl } from '@grafana/data/src/text/sanitize';
|
|
import { getBackendSrv } from 'app/core/services/backend_srv';
|
|
import { getLinkSrv } from '../../../panel/panellinks/link_srv';
|
|
import { DashboardLink } from '../../state/DashboardModel';
|
|
import { DashboardSearchHit } from 'app/features/search/types';
|
|
|
|
interface Props {
|
|
link: DashboardLink;
|
|
linkInfo: { title: string; href: string };
|
|
dashboardId: any;
|
|
}
|
|
|
|
interface State {
|
|
resolvedLinks: ResolvedLinkDTO[];
|
|
}
|
|
|
|
export class DashboardLinksDashboard extends PureComponent<Props, State> {
|
|
state: State = { resolvedLinks: [] };
|
|
|
|
componentDidUpdate(prevProps: Readonly<Props>) {
|
|
if (!this.props.link.asDropdown && prevProps.linkInfo !== this.props.linkInfo) {
|
|
this.onResolveLinks();
|
|
}
|
|
}
|
|
|
|
onResolveLinks = async () => {
|
|
const { dashboardId, link } = this.props;
|
|
|
|
const searchHits = await searchForTags(link);
|
|
const resolvedLinks = resolveLinks(dashboardId, link, searchHits);
|
|
|
|
this.setState({ resolvedLinks });
|
|
};
|
|
|
|
renderElement = (linkElement: JSX.Element, key: string) => {
|
|
const { link } = this.props;
|
|
|
|
return (
|
|
<div className="gf-form" key={key}>
|
|
{link.tooltip && <Tooltip content={link.tooltip}>{linkElement}</Tooltip>}
|
|
{!link.tooltip && <>{linkElement}</>}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
renderList = () => {
|
|
const { link } = this.props;
|
|
const { resolvedLinks } = this.state;
|
|
|
|
return (
|
|
<>
|
|
{resolvedLinks.length > 0 &&
|
|
resolvedLinks.map((resolvedLink, index) => {
|
|
const linkElement = (
|
|
<a className="gf-form-label" href={resolvedLink.url} target={link.targetBlank ? '_blank' : '_self'}>
|
|
<Icon name="apps" style={{ marginRight: '4px' }} />
|
|
<span>{resolvedLink.title}</span>
|
|
</a>
|
|
);
|
|
return this.renderElement(linkElement, `dashlinks-list-item-${resolvedLink.id}-${index}`);
|
|
})}
|
|
</>
|
|
);
|
|
};
|
|
|
|
renderDropdown = () => {
|
|
const { link, linkInfo } = this.props;
|
|
const { resolvedLinks } = this.state;
|
|
|
|
const linkElement = (
|
|
<>
|
|
<a
|
|
className="gf-form-label pointer"
|
|
onClick={this.onResolveLinks}
|
|
data-placement="bottom"
|
|
data-toggle="dropdown"
|
|
>
|
|
<Icon name="bars" />
|
|
<span>{linkInfo.title}</span>
|
|
</a>
|
|
<ul className="dropdown-menu pull-right" role="menu">
|
|
{resolvedLinks.length > 0 &&
|
|
resolvedLinks.map((resolvedLink, index) => {
|
|
return (
|
|
<li key={`dashlinks-dropdown-item-${resolvedLink.id}-${index}`}>
|
|
<a href={resolvedLink.url} target={link.targetBlank ? '_blank' : '_self'}>
|
|
{resolvedLink.title}
|
|
</a>
|
|
</li>
|
|
);
|
|
})}
|
|
</ul>
|
|
</>
|
|
);
|
|
|
|
return this.renderElement(linkElement, 'dashlinks-dropdown');
|
|
};
|
|
|
|
render() {
|
|
if (this.props.link.asDropdown) {
|
|
return this.renderDropdown();
|
|
}
|
|
|
|
return this.renderList();
|
|
}
|
|
}
|
|
|
|
interface ResolvedLinkDTO {
|
|
id: any;
|
|
url: string;
|
|
title: string;
|
|
}
|
|
|
|
export async function searchForTags(
|
|
link: DashboardLink,
|
|
dependencies: { getBackendSrv: typeof getBackendSrv } = { getBackendSrv }
|
|
): Promise<DashboardSearchHit[]> {
|
|
const limit = 100;
|
|
const searchHits: DashboardSearchHit[] = await dependencies.getBackendSrv().search({ tag: link.tags, limit });
|
|
|
|
return searchHits;
|
|
}
|
|
|
|
export function resolveLinks(
|
|
dashboardId: any,
|
|
link: DashboardLink,
|
|
searchHits: DashboardSearchHit[],
|
|
dependencies: { getLinkSrv: typeof getLinkSrv; sanitize: typeof sanitize; sanitizeUrl: typeof sanitizeUrl } = {
|
|
getLinkSrv,
|
|
sanitize,
|
|
sanitizeUrl,
|
|
}
|
|
): ResolvedLinkDTO[] {
|
|
return searchHits
|
|
.filter(searchHit => searchHit.id !== dashboardId)
|
|
.map(searchHit => {
|
|
const id = searchHit.id;
|
|
const title = dependencies.sanitize(searchHit.title);
|
|
const resolvedLink = dependencies.getLinkSrv().getLinkUrl({ ...link, url: searchHit.url });
|
|
const url = dependencies.sanitizeUrl(resolvedLink);
|
|
|
|
return { id, title, url };
|
|
});
|
|
}
|