2022-04-22 14:33:13 +01:00
|
|
|
import { css } from '@emotion/css';
|
2022-02-01 18:17:39 -08:00
|
|
|
import React from 'react';
|
2022-04-22 14:33:13 +01:00
|
|
|
|
2021-12-15 13:51:39 -08:00
|
|
|
import {
|
2022-01-10 01:32:21 -08:00
|
|
|
arrayUtils,
|
2021-12-15 13:51:39 -08:00
|
|
|
DataFrame,
|
|
|
|
|
Field,
|
|
|
|
|
formattedValueToString,
|
|
|
|
|
getFieldDisplayName,
|
|
|
|
|
GrafanaTheme2,
|
2022-02-01 18:17:39 -08:00
|
|
|
LinkModel,
|
2021-12-15 13:51:39 -08:00
|
|
|
} from '@grafana/data';
|
2022-07-29 15:11:42 +03:00
|
|
|
import { SortOrder, TooltipDisplayMode } from '@grafana/schema';
|
2022-12-08 12:02:17 -06:00
|
|
|
import { HorizontalGroup, LinkButton, useStyles2 } from '@grafana/ui';
|
2021-07-28 18:34:42 -07:00
|
|
|
|
|
|
|
|
export interface Props {
|
|
|
|
|
data?: DataFrame; // source data
|
2021-12-23 12:04:41 -06:00
|
|
|
rowIndex?: number | null; // the hover row
|
|
|
|
|
columnIndex?: number | null; // the hover column
|
2022-01-10 01:32:21 -08:00
|
|
|
sortOrder?: SortOrder;
|
2022-07-29 15:11:42 +03:00
|
|
|
mode?: TooltipDisplayMode | null;
|
2021-07-28 18:34:42 -07:00
|
|
|
}
|
|
|
|
|
|
2022-07-29 15:11:42 +03:00
|
|
|
export const DataHoverView = ({ data, rowIndex, columnIndex, sortOrder, mode }: Props) => {
|
2022-02-01 18:17:39 -08:00
|
|
|
const styles = useStyles2(getStyles);
|
2021-07-28 18:34:42 -07:00
|
|
|
|
2022-02-01 18:17:39 -08:00
|
|
|
if (!data || rowIndex == null) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
2021-09-23 19:31:36 -07:00
|
|
|
|
2022-02-01 18:17:39 -08:00
|
|
|
const visibleFields = data.fields.filter((f) => !Boolean(f.config.custom?.hideFrom?.tooltip));
|
2021-07-28 18:34:42 -07:00
|
|
|
|
2022-02-01 18:17:39 -08:00
|
|
|
if (visibleFields.length === 0) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
2022-01-10 01:32:21 -08:00
|
|
|
|
2022-08-26 15:03:20 -06:00
|
|
|
const displayValues: Array<[string, unknown, string]> = [];
|
2022-12-08 12:02:17 -06:00
|
|
|
const links: Record<string, Array<LinkModel<Field>>> = {};
|
2022-01-10 01:32:21 -08:00
|
|
|
|
2022-02-01 18:17:39 -08:00
|
|
|
for (const f of visibleFields) {
|
|
|
|
|
const v = f.values.get(rowIndex);
|
|
|
|
|
const disp = f.display ? f.display(v) : { text: `${v}`, numeric: +v };
|
|
|
|
|
if (f.getLinks) {
|
|
|
|
|
f.getLinks({ calculatedValue: disp, valueRowIndex: rowIndex }).forEach((link) => {
|
2022-12-08 12:02:17 -06:00
|
|
|
const key = getFieldDisplayName(f, data);
|
|
|
|
|
if (!links[key]) {
|
|
|
|
|
links[key] = [];
|
2022-02-01 18:17:39 -08:00
|
|
|
}
|
2022-12-08 12:02:17 -06:00
|
|
|
links[key].push(link);
|
2022-02-01 18:17:39 -08:00
|
|
|
});
|
2022-01-10 01:32:21 -08:00
|
|
|
}
|
|
|
|
|
|
2022-02-01 18:17:39 -08:00
|
|
|
displayValues.push([getFieldDisplayName(f, data), v, formattedValueToString(disp)]);
|
2021-07-28 18:34:42 -07:00
|
|
|
}
|
|
|
|
|
|
2022-02-01 18:17:39 -08:00
|
|
|
if (sortOrder && sortOrder !== SortOrder.None) {
|
|
|
|
|
displayValues.sort((a, b) => arrayUtils.sortValues(sortOrder)(a[1], b[1]));
|
2021-07-28 18:34:42 -07:00
|
|
|
}
|
|
|
|
|
|
2022-02-01 18:17:39 -08:00
|
|
|
return (
|
|
|
|
|
<table className={styles.infoWrap}>
|
|
|
|
|
<tbody>
|
2022-08-15 16:39:00 +02:00
|
|
|
{(mode === TooltipDisplayMode.Multi || mode == null) &&
|
2022-07-29 15:11:42 +03:00
|
|
|
displayValues.map((v, i) => (
|
|
|
|
|
<tr key={`${i}/${rowIndex}`} className={i === columnIndex ? styles.highlight : ''}>
|
|
|
|
|
<th>{v[0]}:</th>
|
2022-12-08 12:02:17 -06:00
|
|
|
<td>{renderWithLinks(v[0], v[2], links)}</td>
|
2022-07-29 15:11:42 +03:00
|
|
|
</tr>
|
|
|
|
|
))}
|
|
|
|
|
{mode === TooltipDisplayMode.Single && columnIndex && (
|
|
|
|
|
<tr key={`${columnIndex}/${rowIndex}`}>
|
|
|
|
|
<th>{displayValues[columnIndex][0]}:</th>
|
2022-12-08 12:02:17 -06:00
|
|
|
<td>{renderWithLinks(displayValues[columnIndex][0], displayValues[columnIndex][2], links)}</td>
|
2022-02-01 18:17:39 -08:00
|
|
|
</tr>
|
|
|
|
|
)}
|
|
|
|
|
</tbody>
|
|
|
|
|
</table>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
2022-12-08 12:02:17 -06:00
|
|
|
const renderWithLinks = (key: string, val: string, links: Record<string, Array<LinkModel<Field>>>) =>
|
|
|
|
|
links[key] ? (
|
|
|
|
|
<HorizontalGroup>
|
|
|
|
|
<>
|
|
|
|
|
{val}
|
|
|
|
|
{links[key].map((link, i) => (
|
|
|
|
|
<LinkButton
|
|
|
|
|
key={i}
|
|
|
|
|
icon={'external-link-alt'}
|
|
|
|
|
target={link.target}
|
|
|
|
|
href={link.href}
|
|
|
|
|
onClick={link.onClick}
|
|
|
|
|
fill="text"
|
|
|
|
|
style={{ width: '100%' }}
|
|
|
|
|
>
|
|
|
|
|
{link.title}
|
|
|
|
|
</LinkButton>
|
|
|
|
|
))}
|
|
|
|
|
</>
|
|
|
|
|
</HorizontalGroup>
|
|
|
|
|
) : (
|
|
|
|
|
<>{val}</>
|
|
|
|
|
);
|
|
|
|
|
|
2022-02-01 18:17:39 -08:00
|
|
|
const getStyles = (theme: GrafanaTheme2) => ({
|
2021-07-28 18:34:42 -07:00
|
|
|
infoWrap: css`
|
|
|
|
|
padding: 8px;
|
|
|
|
|
th {
|
2021-08-26 10:17:03 +02:00
|
|
|
font-weight: ${theme.typography.fontWeightMedium};
|
|
|
|
|
padding: ${theme.spacing(0.25, 2)};
|
2021-07-28 18:34:42 -07:00
|
|
|
}
|
|
|
|
|
`,
|
|
|
|
|
highlight: css`
|
|
|
|
|
background: ${theme.colors.action.hover};
|
|
|
|
|
`,
|
2022-02-01 18:17:39 -08:00
|
|
|
});
|