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:
@@ -1,6 +1,6 @@
|
|||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
import { DataFrame, Field, FieldType, getFieldDisplayName, SelectableValue } from '@grafana/data';
|
import { DataFrame, Field, getFieldDisplayName, SelectableValue } from '@grafana/data';
|
||||||
import { IconName } from '../..';
|
import { getFieldTypeIcon } from '../../types';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
@@ -62,15 +62,6 @@ export function useFieldDisplayNames(data: DataFrame[], filter?: (field: Field)
|
|||||||
}, [data, filter]);
|
}, [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
|
* @internal
|
||||||
*/
|
*/
|
||||||
@@ -93,7 +84,7 @@ export function useSelectOptions(
|
|||||||
options.push({
|
options.push({
|
||||||
value: name,
|
value: name,
|
||||||
label: name,
|
label: name,
|
||||||
icon: field ? fieldTypeIcons[field.type] : undefined,
|
icon: field ? getFieldTypeIcon(field) : undefined,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
for (const name of displayNames.raw) {
|
for (const name of displayNames.raw) {
|
||||||
|
|||||||
@@ -6,14 +6,16 @@ import { getTableStyles, TableStyles } from './styles';
|
|||||||
import { useStyles2 } from '../../themes';
|
import { useStyles2 } from '../../themes';
|
||||||
import { Filter } from './Filter';
|
import { Filter } from './Filter';
|
||||||
import { Icon } from '../Icon/Icon';
|
import { Icon } from '../Icon/Icon';
|
||||||
|
import { getFieldTypeIcon } from '../../types';
|
||||||
|
|
||||||
export interface HeaderRowProps {
|
export interface HeaderRowProps {
|
||||||
headerGroups: HeaderGroup[];
|
headerGroups: HeaderGroup[];
|
||||||
data: DataFrame;
|
data: DataFrame;
|
||||||
|
showTypeIcons?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const HeaderRow = (props: HeaderRowProps) => {
|
export const HeaderRow = (props: HeaderRowProps) => {
|
||||||
const { headerGroups, data } = props;
|
const { headerGroups, data, showTypeIcons } = props;
|
||||||
const e2eSelectorsTable = selectors.components.Panels.Visualization.Table;
|
const e2eSelectorsTable = selectors.components.Panels.Visualization.Table;
|
||||||
const tableStyles = useStyles2(getTableStyles);
|
const tableStyles = useStyles2(getTableStyles);
|
||||||
|
|
||||||
@@ -30,7 +32,7 @@ export const HeaderRow = (props: HeaderRowProps) => {
|
|||||||
role="row"
|
role="row"
|
||||||
>
|
>
|
||||||
{headerGroup.headers.map((column: Column, index: number) =>
|
{headerGroup.headers.map((column: Column, index: number) =>
|
||||||
renderHeaderCell(column, tableStyles, data.fields[index])
|
renderHeaderCell(column, tableStyles, data.fields[index], showTypeIcons)
|
||||||
)}
|
)}
|
||||||
</div>
|
</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();
|
const headerProps = column.getHeaderProps();
|
||||||
|
|
||||||
if (column.canResize) {
|
if (column.canResize) {
|
||||||
@@ -58,6 +60,9 @@ function renderHeaderCell(column: any, tableStyles: TableStyles, field?: Field)
|
|||||||
className={tableStyles.headerCellLabel}
|
className={tableStyles.headerCellLabel}
|
||||||
title={column.render('Header')}
|
title={column.render('Header')}
|
||||||
>
|
>
|
||||||
|
{showTypeIcons && (
|
||||||
|
<Icon name={getFieldTypeIcon(field)} title={field?.type} size="sm" style={{ marginRight: '8px' }} />
|
||||||
|
)}
|
||||||
<div>{column.render('Header')}</div>
|
<div>{column.render('Header')}</div>
|
||||||
<div>
|
<div>
|
||||||
{column.isSorted && (column.isSortedDesc ? <Icon name="arrow-down" /> : <Icon name="arrow-up" />)}
|
{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 */
|
/** Minimal column width specified in pixels */
|
||||||
columnMinWidth?: number;
|
columnMinWidth?: number;
|
||||||
noHeader?: boolean;
|
noHeader?: boolean;
|
||||||
|
showTypeIcons?: boolean;
|
||||||
resizable?: boolean;
|
resizable?: boolean;
|
||||||
initialSortBy?: TableSortByFieldState[];
|
initialSortBy?: TableSortByFieldState[];
|
||||||
onColumnResize?: TableColumnResizeActionCallback;
|
onColumnResize?: TableColumnResizeActionCallback;
|
||||||
@@ -124,6 +125,7 @@ export const Table: FC<Props> = memo((props: Props) => {
|
|||||||
resizable = true,
|
resizable = true,
|
||||||
initialSortBy,
|
initialSortBy,
|
||||||
footerValues,
|
footerValues,
|
||||||
|
showTypeIcons,
|
||||||
} = props;
|
} = props;
|
||||||
const tableStyles = useStyles2(getTableStyles);
|
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">
|
<div {...getTableProps()} className={tableStyles.table} aria-label={ariaLabel} role="table">
|
||||||
<CustomScrollbar hideVerticalTrack={true}>
|
<CustomScrollbar hideVerticalTrack={true}>
|
||||||
<div style={{ width: totalColumnsWidth ? `${totalColumnsWidth}px` : '100%' }}>
|
<div style={{ width: totalColumnsWidth ? `${totalColumnsWidth}px` : '100%' }}>
|
||||||
{!noHeader && <HeaderRow data={data} headerGroups={headerGroups} />}
|
{!noHeader && <HeaderRow data={data} headerGroups={headerGroups} showTypeIcons={showTypeIcons} />}
|
||||||
{rows.length > 0 ? (
|
{rows.length > 0 ? (
|
||||||
<FixedSizeList
|
<FixedSizeList
|
||||||
height={height - headerHeight}
|
height={height - headerHeight}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { Field, FieldType } from '@grafana/data';
|
||||||
import { ComponentSize } from './size';
|
import { ComponentSize } from './size';
|
||||||
export type IconType = 'mono' | 'default';
|
export type IconType = 'mono' | 'default';
|
||||||
export type IconSize = ComponentSize | 'xl' | 'xxl' | 'xxxl';
|
export type IconSize = ComponentSize | 'xl' | 'xxl' | 'xxxl';
|
||||||
@@ -154,3 +155,24 @@ export const getAvailableIcons = () =>
|
|||||||
type BrandIconNames = 'google' | 'microsoft' | 'github' | 'gitlab' | 'okta';
|
type BrandIconNames = 'google' | 'microsoft' | 'github' | 'gitlab' | 'okta';
|
||||||
|
|
||||||
export type IconName = ReturnType<typeof getAvailableIcons>[number] | BrandIconNames;
|
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>({
|
const [options, setOptions] = useState<PanelOptions>({
|
||||||
frameIndex: 0,
|
frameIndex: 0,
|
||||||
showHeader: true,
|
showHeader: true,
|
||||||
|
showTypeIcons: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Subscribe to panel event
|
// Subscribe to panel event
|
||||||
|
|||||||
@@ -228,7 +228,7 @@ export class InspectDataTab extends PureComponent<Props, State> {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{ width, height }}>
|
<div style={{ width, height }}>
|
||||||
<Table width={width} height={height} data={dataFrame} />
|
<Table width={width} height={height} data={dataFrame} showTypeIcons={true} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -86,6 +86,7 @@ export class TablePanel extends Component<Props> {
|
|||||||
width={width}
|
width={width}
|
||||||
data={frame}
|
data={frame}
|
||||||
noHeader={!options.showHeader}
|
noHeader={!options.showHeader}
|
||||||
|
showTypeIcons={options.showTypeIcons}
|
||||||
resizable={true}
|
resizable={true}
|
||||||
initialSortBy={options.sortBy}
|
initialSortBy={options.sortBy}
|
||||||
onSortByChange={this.onSortByChange}
|
onSortByChange={this.onSortByChange}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ Family: {
|
|||||||
PanelOptions: {
|
PanelOptions: {
|
||||||
frameIndex: number | *0
|
frameIndex: number | *0
|
||||||
showHeader: bool | *true
|
showHeader: bool | *true
|
||||||
|
showTypeIcons: bool | *false
|
||||||
sortBy?: [...ui.TableSortByFieldState]
|
sortBy?: [...ui.TableSortByFieldState]
|
||||||
}
|
}
|
||||||
PanelFieldConfig: {
|
PanelFieldConfig: {
|
||||||
|
|||||||
@@ -14,12 +14,14 @@ export const modelVersion = Object.freeze([1, 0]);
|
|||||||
export interface PanelOptions {
|
export interface PanelOptions {
|
||||||
frameIndex: number;
|
frameIndex: number;
|
||||||
showHeader: boolean;
|
showHeader: boolean;
|
||||||
|
showTypeIcons?: boolean;
|
||||||
sortBy?: TableSortByFieldState[];
|
sortBy?: TableSortByFieldState[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export const defaultPanelOptions: PanelOptions = {
|
export const defaultPanelOptions: PanelOptions = {
|
||||||
frameIndex: 0,
|
frameIndex: 0,
|
||||||
showHeader: true,
|
showHeader: true,
|
||||||
|
showTypeIcons: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface PanelFieldConfig {
|
export interface PanelFieldConfig {
|
||||||
|
|||||||
Reference in New Issue
Block a user