mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
* Update table data structure schema. * Update table panel configuration options for new structure * Fix TS errors from refactor * Separate background and gauge display modes * Remove the now used Bar Gauge display from the mud * Fix types up * Reorganize data structures * Fix type issues. * Start stubbing necessary code. * Continue implementing option refactor * Change category for cell type selection. * Consolidate cell options * Fix various typing issues * Clean up dead code * Stub handling display mode changes * Make subOption editor dynamic * Setup interface for sub-option editor props * Remove unused imports * Remove console.log call * Persist display mode changes, stub sub options change, update comments. * Make sure updates from cells are persisted * Persist sub-option changes * Update BarGaugeCell to take into account new settings. * Add deprecated field back * Remove unecessary options in configuration * Update default cell to accept new settings * Make sure color text display works * Add deprecated property notice * Use constant as opposed to string * Make sure we name globally namespaced things uniquely * Update to use unique name * Use union type with discriminator. * Simplify types and operation * Update type definitons * Update types * Update property names in cells * Remove React.FC usage * Update option editor signature * Update options structure * Change variable name * Fix "Color Text" display * Remove debug statement * Make sure we remain backwards compatible with display mode. * Add migration for configuration. * Export BarGaugeDisplayMode from grafana-ui * Update import * Fix bar gauge and dashboard migrator tests * Fix potential undefined references causing test failures * Fix another potential reference error in DefaultCell * Try to fix breaking change detection. * Cache setting changes * Make sure we return with onChange invocation * Fixed migrating overrides * Fix a number of review comments * Simplify option editors * Fix unused imports * Fill out comments for types * Actually use defaultPanelConfig for editor default * Move TableCellEditorProps alongside TableCellOptionEditor * Update docs for table panel * Also make sure we remove TableCellEditorProps from model file * Stub migration tests * Add tests for default config migration * Add basic overrides test * Flesh out tests a bit more * Add inspect to same category as cell editor Co-authored-by: Torkel Ödegaard <torkel@grafana.com>
123 lines
4.8 KiB
TypeScript
123 lines
4.8 KiB
TypeScript
import { cx } from '@emotion/css';
|
|
import React, { FC, ReactElement } from 'react';
|
|
import tinycolor from 'tinycolor2';
|
|
|
|
import { DisplayValue, Field, formattedValueToString } from '@grafana/data';
|
|
import { TableCellBackgroundDisplayMode } from '@grafana/schema';
|
|
|
|
import { getCellLinks, getTextColorForAlphaBackground } from '../../utils';
|
|
import { DataLinksContextMenu } from '../DataLinks/DataLinksContextMenu';
|
|
|
|
import { CellActions } from './CellActions';
|
|
import { TableStyles } from './styles';
|
|
import { TableCellDisplayMode, TableCellProps, TableFieldOptions } from './types';
|
|
|
|
export const DefaultCell: FC<TableCellProps> = (props) => {
|
|
const { field, cell, tableStyles, row, cellProps } = props;
|
|
|
|
const inspectEnabled = Boolean((field.config.custom as TableFieldOptions)?.inspect);
|
|
const displayValue = field.display!(cell.value);
|
|
|
|
let value: string | ReactElement;
|
|
if (React.isValidElement(cell.value)) {
|
|
value = cell.value;
|
|
} else {
|
|
value = formattedValueToString(displayValue);
|
|
}
|
|
|
|
const showFilters = field.config.filterable;
|
|
const showActions = (showFilters && cell.value !== undefined) || inspectEnabled;
|
|
const cellStyle = getCellStyle(tableStyles, field, displayValue, inspectEnabled);
|
|
const hasLinks = Boolean(getCellLinks(field, row)?.length);
|
|
|
|
return (
|
|
<div {...cellProps} className={cellStyle}>
|
|
{!hasLinks && <div className={tableStyles.cellText}>{value}</div>}
|
|
|
|
{hasLinks && (
|
|
<DataLinksContextMenu links={() => getCellLinks(field, row) || []}>
|
|
{(api) => {
|
|
return (
|
|
<div onClick={api.openMenu} className={getLinkStyle(tableStyles, field, api.targetClassName)}>
|
|
{value}
|
|
</div>
|
|
);
|
|
}}
|
|
</DataLinksContextMenu>
|
|
)}
|
|
|
|
{showActions && <CellActions {...props} previewMode="text" />}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
function getCellStyle(
|
|
tableStyles: TableStyles,
|
|
field: Field,
|
|
displayValue: DisplayValue,
|
|
disableOverflowOnHover = false
|
|
) {
|
|
// How much to darken elements depends upon if we're in dark mode
|
|
const darkeningFactor = tableStyles.theme.isDark ? 1 : -0.7;
|
|
|
|
// See if we're using deprecated settings
|
|
const usingDeprecatedSettings = field.config.custom?.displayMode !== undefined;
|
|
|
|
// Setup color variables
|
|
let textColor: string | undefined = undefined;
|
|
let bgColor: string | undefined = undefined;
|
|
|
|
// Set colors using deprecated settings format
|
|
if (usingDeprecatedSettings) {
|
|
if (field.config.custom?.displayMode === TableCellDisplayMode.ColorText) {
|
|
textColor = displayValue.color;
|
|
} else if (field.config.custom?.displayMode === TableCellDisplayMode.ColorBackground) {
|
|
textColor = getTextColorForAlphaBackground(displayValue.color!, tableStyles.theme.isDark);
|
|
bgColor = tinycolor(displayValue.color).toRgbString();
|
|
} else if (
|
|
field.config.custom?.displayMode === TableCellDisplayMode.ColorBackground &&
|
|
field.config.custom?.backgroundDisplayMode === TableCellBackgroundDisplayMode.Gradient
|
|
) {
|
|
const bgColor2 = tinycolor(displayValue.color)
|
|
.darken(10 * darkeningFactor)
|
|
.spin(5);
|
|
textColor = getTextColorForAlphaBackground(displayValue.color!, tableStyles.theme.isDark);
|
|
bgColor = `linear-gradient(120deg, ${bgColor2.toRgbString()}, ${displayValue.color})`;
|
|
}
|
|
}
|
|
// Set colors using updated sub-options format
|
|
else {
|
|
const cellDisplayMode = field.config.custom?.cellOptions?.mode;
|
|
const cellDisplayType = field.config.custom?.cellOptions?.type;
|
|
|
|
if (cellDisplayType === TableCellDisplayMode.ColorText) {
|
|
textColor = displayValue.color;
|
|
} else if (cellDisplayMode === TableCellBackgroundDisplayMode.Basic) {
|
|
textColor = getTextColorForAlphaBackground(displayValue.color!, tableStyles.theme.isDark);
|
|
bgColor = tinycolor(displayValue.color).toRgbString();
|
|
} else if (cellDisplayMode === TableCellBackgroundDisplayMode.Gradient) {
|
|
const bgColor2 = tinycolor(displayValue.color)
|
|
.darken(10 * darkeningFactor)
|
|
.spin(5);
|
|
textColor = getTextColorForAlphaBackground(displayValue.color!, tableStyles.theme.isDark);
|
|
bgColor = `linear-gradient(120deg, ${bgColor2.toRgbString()}, ${displayValue.color})`;
|
|
}
|
|
}
|
|
|
|
// If we have definied colors return those styles
|
|
// Otherwise we return default styles
|
|
if (textColor !== undefined || bgColor !== undefined) {
|
|
return tableStyles.buildCellContainerStyle(textColor, bgColor, !disableOverflowOnHover);
|
|
}
|
|
|
|
return disableOverflowOnHover ? tableStyles.cellContainerNoOverflow : tableStyles.cellContainer;
|
|
}
|
|
|
|
function getLinkStyle(tableStyles: TableStyles, field: Field, targetClassName: string | undefined) {
|
|
if (field.config.custom?.displayMode === TableCellDisplayMode.Auto) {
|
|
return cx(tableStyles.cellLink, targetClassName);
|
|
}
|
|
|
|
return cx(tableStyles.cellLinkForColoredCell, targetClassName);
|
|
}
|