Table: Fixes so links work for image cells (#32370)

* Panel/Table: Adjust data links logic
Closes #31576
This commit is contained in:
kay delaney 2021-03-29 10:42:48 +01:00 committed by GitHub
parent ab4b980d54
commit 2827d89ccf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 47 additions and 44 deletions

View File

@ -1,5 +1,5 @@
import React, { FC, MouseEventHandler, ReactElement } from 'react'; import React, { FC, ReactElement } from 'react';
import { DisplayValue, Field, formattedValueToString, LinkModel } from '@grafana/data'; import { DisplayValue, Field, formattedValueToString } from '@grafana/data';
import { TableCellDisplayMode, TableCellProps } from './types'; import { TableCellDisplayMode, TableCellProps } from './types';
import tinycolor from 'tinycolor2'; import tinycolor from 'tinycolor2';
@ -8,7 +8,7 @@ import { FilterActions } from './FilterActions';
import { getTextColorForBackground } from '../../utils'; import { getTextColorForBackground } from '../../utils';
export const DefaultCell: FC<TableCellProps> = (props) => { export const DefaultCell: FC<TableCellProps> = (props) => {
const { field, cell, tableStyles, row, cellProps } = props; const { field, cell, tableStyles, cellProps } = props;
const displayValue = field.display!(cell.value); const displayValue = field.display!(cell.value);
@ -22,33 +22,9 @@ export const DefaultCell: FC<TableCellProps> = (props) => {
const cellStyle = getCellStyle(tableStyles, field, displayValue); const cellStyle = getCellStyle(tableStyles, field, displayValue);
const showFilters = field.config.filterable; const showFilters = field.config.filterable;
let link: LinkModel<any> | undefined;
let onClick: MouseEventHandler<HTMLAnchorElement> | undefined;
if (field.getLinks) {
link = field.getLinks({
valueRowIndex: row.index,
})[0];
}
if (link && link.onClick) {
onClick = (event) => {
// Allow opening in new tab
if (!(event.ctrlKey || event.metaKey || event.shiftKey) && link!.onClick) {
event.preventDefault();
link!.onClick(event);
}
};
}
return ( return (
<div {...cellProps} className={cellStyle}> <div {...cellProps} className={cellStyle}>
{!link && <div className={tableStyles.cellText}>{value}</div>} <div className={tableStyles.cellText}>{value}</div>
{link && (
<a href={link.href} onClick={onClick} target={link.target} title={link.title} className={tableStyles.cellLink}>
{value}
</a>
)}
{showFilters && cell.value !== undefined && <FilterActions {...props} />} {showFilters && cell.value !== undefined && <FilterActions {...props} />}
</div> </div>
); );

View File

@ -166,8 +166,8 @@ export const Table: FC<Props> = memo((props: Props) => {
const { fields } = data; const { fields } = data;
const RenderRow = React.useCallback( const RenderRow = React.useCallback(
({ index, style }) => { ({ index: rowIndex, style }) => {
const row = rows[index]; const row = rows[rowIndex];
prepareRow(row); prepareRow(row);
return ( return (
<div {...row.getRowProps({ style })} className={tableStyles.row}> <div {...row.getRowProps({ style })} className={tableStyles.row}>
@ -180,6 +180,7 @@ export const Table: FC<Props> = memo((props: Props) => {
onCellFilterAdded={onCellFilterAdded} onCellFilterAdded={onCellFilterAdded}
columnIndex={index} columnIndex={index}
columnCount={row.cells.length} columnCount={row.cells.length}
rowIndex={rowIndex}
/> />
))} ))}
</div> </div>

View File

@ -1,6 +1,6 @@
import React, { FC } from 'react'; import React, { FC, MouseEventHandler } from 'react';
import { Cell } from 'react-table'; import { Cell } from 'react-table';
import { Field } from '@grafana/data'; import { Field, LinkModel } from '@grafana/data';
import { TableFilterActionCallback } from './types'; import { TableFilterActionCallback } from './types';
import { TableStyles } from './styles'; import { TableStyles } from './styles';
@ -11,9 +11,18 @@ export interface Props {
onCellFilterAdded?: TableFilterActionCallback; onCellFilterAdded?: TableFilterActionCallback;
columnIndex: number; columnIndex: number;
columnCount: number; columnCount: number;
rowIndex: number;
} }
export const TableCell: FC<Props> = ({ cell, field, tableStyles, onCellFilterAdded, columnIndex, columnCount }) => { export const TableCell: FC<Props> = ({
cell,
field,
tableStyles,
onCellFilterAdded,
columnIndex,
columnCount,
rowIndex,
}) => {
const cellProps = cell.getCellProps(); const cellProps = cell.getCellProps();
if (!field.display) { if (!field.display) {
@ -32,15 +41,33 @@ export const TableCell: FC<Props> = ({ cell, field, tableStyles, onCellFilterAdd
innerWidth -= tableStyles.lastChildExtraPadding; innerWidth -= tableStyles.lastChildExtraPadding;
} }
return ( const link: LinkModel | undefined = field.getLinks?.({
<> valueRowIndex: rowIndex,
{cell.render('Cell', { })[0];
field,
tableStyles, let onClick: MouseEventHandler<HTMLAnchorElement> | undefined;
onCellFilterAdded, if (link?.onClick) {
cellProps, onClick = (event) => {
innerWidth, // Allow opening in new tab
})} if (!(event.ctrlKey || event.metaKey || event.shiftKey) && link!.onClick) {
</> event.preventDefault();
link!.onClick(event);
}
};
}
const renderedCell = cell.render('Cell', {
field,
tableStyles,
onCellFilterAdded,
cellProps,
innerWidth,
});
return link ? (
<a href={link.href} onClick={onClick} target={link.target} title={link.title} className={tableStyles.cellLink}>
{renderedCell}
</a>
) : (
<>{renderedCell}</>
); );
}; };

View File

@ -90,7 +90,6 @@ export const getTableStyles = stylesFactory((theme: GrafanaTheme) => {
`, `,
cellContainer: buildCellContainerStyle(), cellContainer: buildCellContainerStyle(),
cellText: css` cellText: css`
cursor: text;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
user-select: text; user-select: text;