mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
* baldm0mma/addRowNumbers/ add showRowNums to panel cue * baldm0mma/addRowNumbers/ add panel option for sowing row numbers * baldm0mma/addRowNumbers/ update typing for showRowNums * baldm0mma/addRowNumbers/ add buildFieldsForOptionalRowNums * baldm0mma/addRowNumbers/ update addOptionalNumbersRowToTable * baldm0mma/addRowNumbers/ adjust display method to return numeric and text values * baldm0mma/ chaneg prop name to match * baldm0mma/addRowNumbers/ update boolean swicth path * baldm0mma/addRowNumbers/ move function * baldm0mma/addRowNumbers/ add getToggleHiddenProps * baldm0mma/addRowNumbers/ remove addNumbersRowToTable second arg * baldm0mma/addRowNumbers/ add updateInitialState * baldm0mma/addRowNumbers/ update getInitialState reducer with initialShowRowNumbers arg * baldm0mma/addRowNumbers/ add useEffect for RowNumberColumn toggling * baldm0mma/addRowNums/ bootleg fix * baldm0mma/addRowNumbers/ export OPTIONAL_ROW_NUMBER_COLUMN_WIDTH * baldm0mma/addRowNumbers/ add annos for readability * baldm0mma/addRowNumbers/ remove superfluous annos * baldm0mma/addRowNumbers/ add a few logs * baldm0mma/addRowNumbers/ update annos * baldm0mma/addRowNumbers/ update which footer row displays reducer type * baldm0mma/addRowNumbers/ abstract away defaultRowNumberColumnFieldData * baldm0mma/addRowNumbers/ update annos in utils.tsx * baldm0mma/addRowNumbers/ update annos for defaultRowNumberColumnFieldData * baldm0mma/addRowNumbers/ mark unused args with underscore * baldm0mma/addRowNumbers/ add annos to addRowNumbersFieldToData * baldm0mma/addRowNumbers/ update utils file type * baldm0mma/addRowNumbers/ remove console.logs * baldm0mma/addRowNumbers/ update file type * baldm0mma/addRowNumbers/ update annos in utils * baldm0mma/addRowNumbers/ remove superfluous footerGroups object * baldm0mma/addRowNumbers/ add annos for tests * baldm0mma/addRowNumbers/ add annos for self * baldm0mma/addRowNumbers/ add tests to table.test.tsx * baldm0mma/addRowNumbers/ update tests in utils.test * baldm0mma/addRowNumbers/ update annos and tests * baldm0mma/addRowNumbers/ remove console.logs * baldm0mma/addRowNumbers/ update utils file ext * baldm0mma/addRowNumbers/ update anno in table.tsx * baldm0mma/addRowNumbers/ update annos in table.tsx * baldm0mma/addRowNumbers/ rem error annos * baldm0mma/addRowNumbers/ revert footerCell * baldm0mma/addRowNumbers/ revert tests * baldm0mma/addRowNumbers/ skip tests * baldm0mma/addRowNumbers/ revert table isCountRowSet * baldm0mma/addRowNumbers/ remove cloneDeep * baldm0mma/addRowNumbers/ update filterFields * baldm0mma/addRowNumbers/ skip tests * Refactor count rows * baldm0mma/addRowNumbers/ rem test skips * baldm0mma/addRowNumbers/ update with annos * baldm0mma/addRowNumbers/ skip timeing out test * baldm0mma/addRowNumbers/ static row numbering and test updates * baldm0mma/addRowNumbers/ remove dupe --------- Co-authored-by: Victor Marin <victor.marin@grafana.com>
143 lines
4.3 KiB
TypeScript
143 lines
4.3 KiB
TypeScript
import { css } from '@emotion/css';
|
|
import React from 'react';
|
|
|
|
import { DataFrame, FieldMatcherID, getFrameDisplayName, PanelProps, SelectableValue } from '@grafana/data';
|
|
import { PanelDataErrorView } from '@grafana/runtime';
|
|
import { Select, Table, usePanelContext, useTheme2 } from '@grafana/ui';
|
|
import { TableSortByFieldState } from '@grafana/ui/src/components/Table/types';
|
|
import { OPTIONAL_ROW_NUMBER_COLUMN_WIDTH } from '@grafana/ui/src/components/Table/utils';
|
|
|
|
import { PanelOptions } from './models.gen';
|
|
|
|
interface Props extends PanelProps<PanelOptions> {}
|
|
|
|
export function TablePanel(props: Props) {
|
|
const { data, height, width, options, fieldConfig, id } = props;
|
|
|
|
const theme = useTheme2();
|
|
const panelContext = usePanelContext();
|
|
const frames = data.series;
|
|
const mainFrames = frames.filter((f) => f.meta?.custom?.parentRowIndex === undefined);
|
|
const subFrames = frames.filter((f) => f.meta?.custom?.parentRowIndex !== undefined);
|
|
const count = mainFrames.length;
|
|
const hasFields = mainFrames[0]?.fields.length;
|
|
const currentIndex = getCurrentFrameIndex(mainFrames, options);
|
|
const main = mainFrames[currentIndex];
|
|
|
|
let tableHeight = height;
|
|
let subData = subFrames;
|
|
|
|
if (!count || !hasFields) {
|
|
return <PanelDataErrorView panelId={id} fieldConfig={fieldConfig} data={data} />;
|
|
}
|
|
|
|
if (count > 1) {
|
|
const inputHeight = theme.spacing.gridSize * theme.components.height.md;
|
|
const padding = theme.spacing.gridSize;
|
|
|
|
tableHeight = height - inputHeight - padding;
|
|
subData = subFrames.filter((f) => f.refId === main.refId);
|
|
}
|
|
|
|
const tableElement = (
|
|
<Table
|
|
height={tableHeight}
|
|
// This calculation is to accommodate the optionally rendered Row Numbers Column
|
|
width={options.showRowNums ? width : width + OPTIONAL_ROW_NUMBER_COLUMN_WIDTH}
|
|
data={main}
|
|
noHeader={!options.showHeader}
|
|
showTypeIcons={options.showTypeIcons}
|
|
resizable={true}
|
|
showRowNums={options.showRowNums}
|
|
initialSortBy={options.sortBy}
|
|
onSortByChange={(sortBy) => onSortByChange(sortBy, props)}
|
|
onColumnResize={(displayName, resizedWidth) => onColumnResize(displayName, resizedWidth, props)}
|
|
onCellFilterAdded={panelContext.onAddAdHocFilter}
|
|
footerOptions={options.footer}
|
|
enablePagination={options.footer?.enablePagination}
|
|
subData={subData}
|
|
/>
|
|
);
|
|
|
|
if (count === 1) {
|
|
return tableElement;
|
|
}
|
|
|
|
const names = mainFrames.map((frame, index) => {
|
|
return {
|
|
label: getFrameDisplayName(frame),
|
|
value: index,
|
|
};
|
|
});
|
|
|
|
return (
|
|
<div className={tableStyles.wrapper}>
|
|
{tableElement}
|
|
<div className={tableStyles.selectWrapper}>
|
|
<Select options={names} value={names[currentIndex]} onChange={(val) => onChangeTableSelection(val, props)} />
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
function getCurrentFrameIndex(frames: DataFrame[], options: PanelOptions) {
|
|
return options.frameIndex > 0 && options.frameIndex < frames.length ? options.frameIndex : 0;
|
|
}
|
|
|
|
function onColumnResize(fieldDisplayName: string, width: number, props: Props) {
|
|
const { fieldConfig } = props;
|
|
const { overrides } = fieldConfig;
|
|
|
|
const matcherId = FieldMatcherID.byName;
|
|
const propId = 'custom.width';
|
|
|
|
// look for existing override
|
|
const override = overrides.find((o) => o.matcher.id === matcherId && o.matcher.options === fieldDisplayName);
|
|
|
|
if (override) {
|
|
// look for existing property
|
|
const property = override.properties.find((prop) => prop.id === propId);
|
|
if (property) {
|
|
property.value = width;
|
|
} else {
|
|
override.properties.push({ id: propId, value: width });
|
|
}
|
|
} else {
|
|
overrides.push({
|
|
matcher: { id: matcherId, options: fieldDisplayName },
|
|
properties: [{ id: propId, value: width }],
|
|
});
|
|
}
|
|
|
|
props.onFieldConfigChange({
|
|
...fieldConfig,
|
|
overrides,
|
|
});
|
|
}
|
|
|
|
function onSortByChange(sortBy: TableSortByFieldState[], props: Props) {
|
|
props.onOptionsChange({
|
|
...props.options,
|
|
sortBy,
|
|
});
|
|
}
|
|
|
|
function onChangeTableSelection(val: SelectableValue<number>, props: Props) {
|
|
props.onOptionsChange({
|
|
...props.options,
|
|
frameIndex: val.value || 0,
|
|
});
|
|
}
|
|
|
|
const tableStyles = {
|
|
wrapper: css`
|
|
display: flex;
|
|
flex-direction: column;
|
|
justify-content: space-between;
|
|
height: 100%;
|
|
`,
|
|
selectWrapper: css`
|
|
padding: 8px 8px 0px 8px;
|
|
`,
|
|
};
|