blob: 31f4e6e47e465771245b4c7c8e2570138ef42246 [file]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { useMemo, ReactNode } from 'react';
import { InfoTooltip, TableView } from '@superset-ui/core/components';
import { t } from '@apache-superset/core/translation';
import { styled } from '@apache-superset/core/theme';
import { sortNumberWithMixedTypes, processTimeTableData } from './utils';
import { ValueCell, LeftCell, Sparkline } from './components';
import type { TimeTableProps } from './types';
// @z-index-above-dashboard-charts + 1 = 11
const TimeTableStyles = styled.div<{ height?: number }>`
height: ${props => props.height}px;
overflow: auto;
th {
z-index: 11 !important; // to cover sparkline
}
`;
const TimeTable = ({
className = '',
height,
data,
columnConfigs,
rowType,
rows,
url = '',
}: TimeTableProps) => {
const memoizedColumns = useMemo(
() => [
{
accessor: 'metric',
Header: t('Metric'),
id: 'metric', // REQUIRED: TableView needs both accessor and id to render rows
},
...columnConfigs.map((columnConfig, i) => ({
accessor: columnConfig.key,
id: columnConfig.key, // REQUIRED: TableView needs both accessor and id to render rows
cellProps: columnConfig.colType === 'spark' && {
style: { width: '1%' },
},
Header: () => (
<>
{columnConfig.label}{' '}
{columnConfig.tooltip && (
<InfoTooltip
tooltip={columnConfig.tooltip}
label={`tt-col-${i}`}
placement="top"
/>
)}
</>
),
sortType: sortNumberWithMixedTypes,
})),
],
[columnConfigs],
);
const memoizedRows = useMemo(() => {
const { entries, reversedEntries } = processTimeTableData(data);
return rows.map(row => {
const valueField = row.label || row.metric_name || '';
const cellValues = columnConfigs.reduce<Record<string, ReactNode>>(
(acc, columnConfig) => {
if (columnConfig.colType === 'spark') {
return {
...acc,
[columnConfig.key]: (
<Sparkline
valueField={valueField}
column={columnConfig}
entries={entries}
/>
),
};
}
return {
...acc,
[columnConfig.key]: (
<ValueCell
valueField={valueField}
column={columnConfig}
reversedEntries={reversedEntries}
/>
),
};
},
{},
);
return {
...row,
...cellValues,
metric: <LeftCell row={row} rowType={rowType} url={url} />,
};
});
}, [columnConfigs, data, rowType, rows, url]);
const defaultSort =
rowType === 'column' && columnConfigs.length
? [
{
id: columnConfigs[0].key,
desc: true,
},
]
: [];
return (
<TimeTableStyles
data-test="time-table"
className={className}
height={height}
>
<TableView
className="table-no-hover"
columns={memoizedColumns}
data={memoizedRows}
initialSortBy={defaultSort}
withPagination={false}
/>
</TimeTableStyles>
);
};
export default TimeTable;