mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Tables: optionally show field type icon in tables (#38855)
This commit is contained in:
parent
ecf40f0331
commit
10ffc9a754
@ -1,6 +1,6 @@
|
||||
import { useMemo } from 'react';
|
||||
import { DataFrame, Field, FieldType, getFieldDisplayName, SelectableValue } from '@grafana/data';
|
||||
import { IconName } from '../..';
|
||||
import { DataFrame, Field, getFieldDisplayName, SelectableValue } from '@grafana/data';
|
||||
import { getFieldTypeIcon } from '../../types';
|
||||
|
||||
/**
|
||||
* @internal
|
||||
@ -62,15 +62,6 @@ export function useFieldDisplayNames(data: DataFrame[], filter?: (field: Field)
|
||||
}, [data, filter]);
|
||||
}
|
||||
|
||||
const fieldTypeIcons: { [key in FieldType]: IconName } = {
|
||||
time: 'clock-nine',
|
||||
string: 'font',
|
||||
number: 'calculator-alt',
|
||||
boolean: 'toggle-on',
|
||||
trace: 'info-circle',
|
||||
other: 'brackets-curly',
|
||||
};
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
@ -93,7 +84,7 @@ export function useSelectOptions(
|
||||
options.push({
|
||||
value: name,
|
||||
label: name,
|
||||
icon: field ? fieldTypeIcons[field.type] : undefined,
|
||||
icon: field ? getFieldTypeIcon(field) : undefined,
|
||||
});
|
||||
}
|
||||
for (const name of displayNames.raw) {
|
||||
|
@ -6,14 +6,16 @@ import { getTableStyles, TableStyles } from './styles';
|
||||
import { useStyles2 } from '../../themes';
|
||||
import { Filter } from './Filter';
|
||||
import { Icon } from '../Icon/Icon';
|
||||
import { getFieldTypeIcon } from '../../types';
|
||||
|
||||
export interface HeaderRowProps {
|
||||
headerGroups: HeaderGroup[];
|
||||
data: DataFrame;
|
||||
showTypeIcons?: boolean;
|
||||
}
|
||||
|
||||
export const HeaderRow = (props: HeaderRowProps) => {
|
||||
const { headerGroups, data } = props;
|
||||
const { headerGroups, data, showTypeIcons } = props;
|
||||
const e2eSelectorsTable = selectors.components.Panels.Visualization.Table;
|
||||
const tableStyles = useStyles2(getTableStyles);
|
||||
|
||||
@ -30,7 +32,7 @@ export const HeaderRow = (props: HeaderRowProps) => {
|
||||
role="row"
|
||||
>
|
||||
{headerGroup.headers.map((column: Column, index: number) =>
|
||||
renderHeaderCell(column, tableStyles, data.fields[index])
|
||||
renderHeaderCell(column, tableStyles, data.fields[index], showTypeIcons)
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
@ -39,7 +41,7 @@ export const HeaderRow = (props: HeaderRowProps) => {
|
||||
);
|
||||
};
|
||||
|
||||
function renderHeaderCell(column: any, tableStyles: TableStyles, field?: Field) {
|
||||
function renderHeaderCell(column: any, tableStyles: TableStyles, field?: Field, showTypeIcons?: boolean) {
|
||||
const headerProps = column.getHeaderProps();
|
||||
|
||||
if (column.canResize) {
|
||||
@ -58,6 +60,9 @@ function renderHeaderCell(column: any, tableStyles: TableStyles, field?: Field)
|
||||
className={tableStyles.headerCellLabel}
|
||||
title={column.render('Header')}
|
||||
>
|
||||
{showTypeIcons && (
|
||||
<Icon name={getFieldTypeIcon(field)} title={field?.type} size="sm" style={{ marginRight: '8px' }} />
|
||||
)}
|
||||
<div>{column.render('Header')}</div>
|
||||
<div>
|
||||
{column.isSorted && (column.isSortedDesc ? <Icon name="arrow-down" /> : <Icon name="arrow-up" />)}
|
||||
|
@ -38,6 +38,7 @@ export interface Props {
|
||||
/** Minimal column width specified in pixels */
|
||||
columnMinWidth?: number;
|
||||
noHeader?: boolean;
|
||||
showTypeIcons?: boolean;
|
||||
resizable?: boolean;
|
||||
initialSortBy?: TableSortByFieldState[];
|
||||
onColumnResize?: TableColumnResizeActionCallback;
|
||||
@ -124,6 +125,7 @@ export const Table: FC<Props> = memo((props: Props) => {
|
||||
resizable = true,
|
||||
initialSortBy,
|
||||
footerValues,
|
||||
showTypeIcons,
|
||||
} = props;
|
||||
const tableStyles = useStyles2(getTableStyles);
|
||||
|
||||
@ -204,7 +206,7 @@ export const Table: FC<Props> = memo((props: Props) => {
|
||||
<div {...getTableProps()} className={tableStyles.table} aria-label={ariaLabel} role="table">
|
||||
<CustomScrollbar hideVerticalTrack={true}>
|
||||
<div style={{ width: totalColumnsWidth ? `${totalColumnsWidth}px` : '100%' }}>
|
||||
{!noHeader && <HeaderRow data={data} headerGroups={headerGroups} />}
|
||||
{!noHeader && <HeaderRow data={data} headerGroups={headerGroups} showTypeIcons={showTypeIcons} />}
|
||||
{rows.length > 0 ? (
|
||||
<FixedSizeList
|
||||
height={height - headerHeight}
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { Field, FieldType } from '@grafana/data';
|
||||
import { ComponentSize } from './size';
|
||||
export type IconType = 'mono' | 'default';
|
||||
export type IconSize = ComponentSize | 'xl' | 'xxl' | 'xxxl';
|
||||
@ -154,3 +155,24 @@ export const getAvailableIcons = () =>
|
||||
type BrandIconNames = 'google' | 'microsoft' | 'github' | 'gitlab' | 'okta';
|
||||
|
||||
export type IconName = ReturnType<typeof getAvailableIcons>[number] | BrandIconNames;
|
||||
|
||||
/** Get the icon for a given field type */
|
||||
export function getFieldTypeIcon(field?: Field): IconName {
|
||||
if (field) {
|
||||
switch (field.type) {
|
||||
case FieldType.time:
|
||||
return 'clock-nine';
|
||||
case FieldType.string:
|
||||
return 'font';
|
||||
case FieldType.number:
|
||||
return 'calculator-alt';
|
||||
case FieldType.boolean:
|
||||
return 'toggle-on';
|
||||
case FieldType.trace:
|
||||
return 'info-circle';
|
||||
case FieldType.other:
|
||||
return 'brackets-curly';
|
||||
}
|
||||
}
|
||||
return 'question-circle';
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ export function PanelEditorTableView({ width, height, panel, dashboard }: Props)
|
||||
const [options, setOptions] = useState<PanelOptions>({
|
||||
frameIndex: 0,
|
||||
showHeader: true,
|
||||
showTypeIcons: true,
|
||||
});
|
||||
|
||||
// Subscribe to panel event
|
||||
|
@ -228,7 +228,7 @@ export class InspectDataTab extends PureComponent<Props, State> {
|
||||
|
||||
return (
|
||||
<div style={{ width, height }}>
|
||||
<Table width={width} height={height} data={dataFrame} />
|
||||
<Table width={width} height={height} data={dataFrame} showTypeIcons={true} />
|
||||
</div>
|
||||
);
|
||||
}}
|
||||
|
@ -86,6 +86,7 @@ export class TablePanel extends Component<Props> {
|
||||
width={width}
|
||||
data={frame}
|
||||
noHeader={!options.showHeader}
|
||||
showTypeIcons={options.showTypeIcons}
|
||||
resizable={true}
|
||||
initialSortBy={options.sortBy}
|
||||
onSortByChange={this.onSortByChange}
|
||||
|
@ -25,6 +25,7 @@ Family: {
|
||||
PanelOptions: {
|
||||
frameIndex: number | *0
|
||||
showHeader: bool | *true
|
||||
showTypeIcons: bool | *false
|
||||
sortBy?: [...ui.TableSortByFieldState]
|
||||
}
|
||||
PanelFieldConfig: {
|
||||
|
@ -14,12 +14,14 @@ export const modelVersion = Object.freeze([1, 0]);
|
||||
export interface PanelOptions {
|
||||
frameIndex: number;
|
||||
showHeader: boolean;
|
||||
showTypeIcons?: boolean;
|
||||
sortBy?: TableSortByFieldState[];
|
||||
}
|
||||
|
||||
export const defaultPanelOptions: PanelOptions = {
|
||||
frameIndex: 0,
|
||||
showHeader: true,
|
||||
showTypeIcons: false,
|
||||
};
|
||||
|
||||
export interface PanelFieldConfig {
|
||||
|
Loading…
Reference in New Issue
Block a user