superset-frontend/plugins/plugin-chart-pivot-table/src/plugin/transformProps.ts
/**
* 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 {
ChartProps,
DataRecord,
extractTimegrain,
GenericDataType,
getTimeFormatter,
getTimeFormatterForGranularity,
QueryFormData,
SMART_DATE_ID,
TimeFormats,
} from '@superset-ui/core';
import { getColorFormatters } from '@superset-ui/chart-controls';
import { DateFormatter } from '../types';
const { DATABASE_DATETIME } = TimeFormats;
function isNumeric(key: string, data: DataRecord[] = []) {
return data.every(
record =>
record[key] === null ||
record[key] === undefined ||
typeof record[key] === 'number',
);
}
export default function transformProps(chartProps: ChartProps<QueryFormData>) {
/**
* This function is called after a successful response has been
* received from the chart data endpoint, and is used to transform
* the incoming data prior to being sent to the Visualization.
*
* The transformProps function is also quite useful to return
* additional/modified props to your data viz component. The formData
* can also be accessed from your PivotTableChart.tsx file, but
* doing supplying custom props here is often handy for integrating third
* party libraries that rely on specific props.
*
* A description of properties in `chartProps`:
* - `height`, `width`: the height/width of the DOM element in which
* the chart is located
* - `formData`: the chart data request payload that was sent to the
* backend.
* - `queriesData`: the chart data response payload that was received
* from the backend. Some notable properties of `queriesData`:
* - `data`: an array with data, each row with an object mapping
* the column/alias to its value. Example:
* `[{ col1: 'abc', metric1: 10 }, { col1: 'xyz', metric1: 20 }]`
* - `rowcount`: the number of rows in `data`
* - `query`: the query that was issued.
*
* Please note: the transformProps function gets cached when the
* application loads. When making changes to the `transformProps`
* function during development with hot reloading, changes won't
* be seen until restarting the development server.
*/
const {
width,
height,
queriesData,
formData,
rawFormData,
hooks: { setDataMask = () => {}, onContextMenu },
filterState,
datasource: { verboseMap = {}, columnFormats = {}, currencyFormats = {} },
emitCrossFilters,
} = chartProps;
const { data, colnames, coltypes } = queriesData[0];
const {
groupbyRows,
groupbyColumns,
metrics,
tableRenderer,
colOrder,
rowOrder,
aggregateFunction,
transposePivot,
combineMetric,
rowSubtotalPosition,
colSubtotalPosition,
colTotals,
colSubTotals,
rowTotals,
rowSubTotals,
valueFormat,
dateFormat,
metricsLayout,
conditionalFormatting,
timeGrainSqla,
currencyFormat,
allowRenderHtml,
} = formData;
const { selectedFilters } = filterState;
const granularity = extractTimegrain(rawFormData);
const dateFormatters = colnames
.filter(
(colname: string, index: number) =>
coltypes[index] === GenericDataType.Temporal,
)
.reduce(
(
acc: Record<string, DateFormatter | undefined>,
temporalColname: string,
) => {
let formatter: DateFormatter | undefined;
if (dateFormat === SMART_DATE_ID) {
if (granularity) {
// time column use formats based on granularity
formatter = getTimeFormatterForGranularity(granularity);
} else if (isNumeric(temporalColname, data)) {
formatter = getTimeFormatter(DATABASE_DATETIME);
} else {
// if no column-specific format, print cell as is
formatter = String;
}
} else if (dateFormat) {
formatter = getTimeFormatter(dateFormat);
}
if (formatter) {
acc[temporalColname] = formatter;
}
return acc;
},
{},
);
const metricColorFormatters = getColorFormatters(conditionalFormatting, data);
return {
width,
height,
data,
groupbyRows,
groupbyColumns,
metrics,
tableRenderer,
colOrder,
rowOrder,
aggregateFunction,
transposePivot,
combineMetric,
rowSubtotalPosition,
colSubtotalPosition,
colTotals,
colSubTotals,
rowTotals,
rowSubTotals,
valueFormat,
currencyFormat,
emitCrossFilters,
setDataMask,
selectedFilters,
verboseMap,
columnFormats,
currencyFormats,
metricsLayout,
metricColorFormatters,
dateFormatters,
onContextMenu,
timeGrainSqla,
allowRenderHtml,
};
}