fix(plugin-chart-period-over-period-kpi): Blank chart when switching from BigNumberTotal (#27203)

This commit is contained in:
Kamil Gabryjelski
2024-02-22 17:37:23 +01:00
committed by GitHub
parent f1cd8cc263
commit 54037972f2
17 changed files with 121 additions and 290 deletions

View File

@@ -23,21 +23,6 @@ import {
QueryFormData,
} from '@superset-ui/core';
/**
* The buildQuery function is used to create an instance of QueryContext that's
* sent to the chart data endpoint. In addition to containing information of which
* datasource to use, it specifies the type (e.g. full payload, samples, query) and
* format (e.g. CSV or JSON) of the result and whether or not to force refresh the data from
* the datasource as opposed to using a cached copy of the data, if available.
*
* More importantly though, QueryContext contains a property `queries`, which is an array of
* QueryObjects specifying individual data requests to be made. A QueryObject specifies which
* columns, metrics and filters, among others, to use during the query. Usually it will be enough
* to specify just one query based on the baseQueryObject, but for some more advanced use cases
* it is possible to define post processing operations in the QueryObject, or multiple queries
* if a viz needs multiple different result sets.
*/
export default function buildQuery(formData: QueryFormData) {
const {
cols: groupby,

View File

@@ -28,6 +28,7 @@ import {
getStandardizedControls,
sharedControls,
} from '@superset-ui/chart-controls';
import { headerFontSize, subheaderFontSize } from '../sharedControls';
const config: ControlPanelConfig = {
controlPanelSections: [
@@ -102,71 +103,13 @@ const config: ControlPanelConfig = {
controlSetRows: [
['y_axis_format'],
['currency_format'],
[headerFontSize],
[
{
name: 'header_font_size',
...subheaderFontSize,
config: {
type: 'SelectControl',
label: t('Big Number Font Size'),
renderTrigger: true,
clearable: false,
default: 60,
options: [
{
label: t('Tiny'),
value: 16,
},
{
label: t('Small'),
value: 20,
},
{
label: t('Normal'),
value: 30,
},
{
label: t('Large'),
value: 48,
},
{
label: t('Huge'),
value: 60,
},
],
},
},
],
[
{
name: 'subheader_font_size',
config: {
type: 'SelectControl',
label: t('Subheader Font Size'),
renderTrigger: true,
clearable: false,
default: 40,
options: [
{
label: t('Tiny'),
value: 16,
},
{
label: t('Small'),
value: 20,
},
{
label: t('Normal'),
value: 26,
},
{
label: t('Large'),
value: 32,
},
{
label: t('Huge'),
value: 40,
},
],
...subheaderFontSize.config,
label: t('Comparison font size'),
},
},
],

View File

@@ -20,19 +20,9 @@ import { t, ChartMetadata, ChartPlugin } from '@superset-ui/core';
import buildQuery from './buildQuery';
import controlPanel from './controlPanel';
import transformProps from './transformProps';
import thumbnail from '../images/thumbnail.png';
import thumbnail from './images/thumbnail.png';
export default class PopKPIPlugin extends ChartPlugin {
/**
* The constructor is used to pass relevant metadata and callbacks that get
* registered in respective registries that are used throughout the library
* and application. A more thorough description of each property is given in
* the respective imported file.
*
* It is worth noting that `buildQuery` and is optional, and only needed for
* advanced visualizations that require either post processing operations
* (pivoting, rolling aggregations, sorting etc) or submitting multiple queries.
*/
constructor() {
const metadata = new ChartMetadata({
category: t('KPI'),
@@ -45,6 +35,7 @@ export default class PopKPIPlugin extends ChartPlugin {
t('Percentages'),
t('Report'),
t('Description'),
t('Advanced-Analytics'),
],
thumbnail,
});
@@ -52,7 +43,7 @@ export default class PopKPIPlugin extends ChartPlugin {
super({
buildQuery,
controlPanel,
loadChart: () => import('../PopKPI'),
loadChart: () => import('./PopKPI'),
metadata,
transformProps,
});

View File

@@ -25,6 +25,7 @@ import {
getNumberFormatter,
formatTimeRange,
} from '@superset-ui/core';
import { getComparisonFontSize, getHeaderFontSize } from './utils';
export const parseMetricValue = (metricValue: number | string | null) => {
if (typeof metricValue === 'string') {
@@ -142,7 +143,6 @@ export default function transformProps(chartProps: ChartProps) {
width,
height,
data,
// and now your control data, manipulated as needed, and passed through as props!
metric,
metricName,
bigNumber,
@@ -150,8 +150,8 @@ export default function transformProps(chartProps: ChartProps) {
valueDifference,
percentDifferenceFormattedString: percentDifference,
boldText,
headerFontSize,
subheaderFontSize,
headerFontSize: getHeaderFontSize(headerFontSize),
subheaderFontSize: getComparisonFontSize(subheaderFontSize),
headerText,
compType,
comparisonColorEnabled,

View File

@@ -0,0 +1,39 @@
/**
* 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 { getComparisonFontSize, getHeaderFontSize } from './utils';
test('getHeaderFontSize', () => {
expect(getHeaderFontSize(0.2)).toEqual(16);
expect(getHeaderFontSize(0.3)).toEqual(20);
expect(getHeaderFontSize(0.4)).toEqual(30);
expect(getHeaderFontSize(0.5)).toEqual(48);
expect(getHeaderFontSize(0.6)).toEqual(60);
expect(getHeaderFontSize(0.15)).toEqual(60);
expect(getHeaderFontSize(2)).toEqual(60);
});
test('getComparisonFontSize', () => {
expect(getComparisonFontSize(0.125)).toEqual(16);
expect(getComparisonFontSize(0.15)).toEqual(20);
expect(getComparisonFontSize(0.2)).toEqual(26);
expect(getComparisonFontSize(0.3)).toEqual(32);
expect(getComparisonFontSize(0.4)).toEqual(40);
expect(getComparisonFontSize(0.05)).toEqual(40);
expect(getComparisonFontSize(0.9)).toEqual(40);
});

View File

@@ -0,0 +1,59 @@
/**
* 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 { headerFontSize, subheaderFontSize } from '../sharedControls';
const headerFontSizes = [16, 20, 30, 48, 60];
const comparisonFontSizes = [16, 20, 26, 32, 40];
const headerProportionValues =
headerFontSize.config.options.map(
(option: { label: string; value: number }) => option.value,
) ?? [];
const subheaderProportionValues =
subheaderFontSize.config.options.map(
(option: { label: string; value: number }) => option.value,
) ?? [];
const getFontSizeMapping = (
proportionValues: number[],
actualSizes: number[],
) =>
proportionValues.reduce((acc, value, index) => {
acc[value] = actualSizes[index] ?? actualSizes[actualSizes.length - 1];
return acc;
}, {});
const headerFontSizesMapping = getFontSizeMapping(
headerProportionValues,
headerFontSizes,
);
const comparisonFontSizesMapping = getFontSizeMapping(
subheaderProportionValues,
comparisonFontSizes,
);
export const getHeaderFontSize = (proportionValue: number) =>
headerFontSizesMapping[proportionValue] ??
headerFontSizes[headerFontSizes.length - 1];
export const getComparisonFontSize = (proportionValue: number) =>
comparisonFontSizesMapping[proportionValue] ??
comparisonFontSizes[comparisonFontSizes.length - 1];

View File

@@ -19,3 +19,4 @@
export { default as BigNumberChartPlugin } from './BigNumberWithTrendline';
export { default as BigNumberTotalChartPlugin } from './BigNumberTotal';
export { default as BigNumberPeriodOverPeriodChartPlugin } from './BigNumberPeriodOverPeriod';

View File

@@ -32,7 +32,11 @@ export { default as EchartsRadarChartPlugin } from './Radar';
export { default as EchartsFunnelChartPlugin } from './Funnel';
export { default as EchartsTreeChartPlugin } from './Tree';
export { default as EchartsTreemapChartPlugin } from './Treemap';
export { BigNumberChartPlugin, BigNumberTotalChartPlugin } from './BigNumber';
export {
BigNumberChartPlugin,
BigNumberTotalChartPlugin,
BigNumberPeriodOverPeriodChartPlugin,
} from './BigNumber';
export { default as EchartsSunburstChartPlugin } from './Sunburst';
export { default as EchartsBubbleChartPlugin } from './Bubble';
export { default as EchartsWaterfallChartPlugin } from './Waterfall';

View File

@@ -1,87 +0,0 @@
/\*\*
- 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.
\*/
# custom-viz
This plugin provides a BigNumber visualization with period over period time comparisons
### Usage
To build the plugin, run the following commands:
```
npm ci
npm run build
```
Alternatively, to run the plugin in development mode (=rebuilding whenever changes are made), start the dev server with the following command:
```
npm run dev
```
To add the package to Superset, go to the `superset-frontend` subdirectory in your Superset source folder (assuming both the `custom-viz` plugin and `superset` repos are in the same root directory) and run
```
npm i -S ../../plugin-chart-period-over-period-kpi
```
If your Superset plugin exists in the `superset-frontend` directory and you wish to resolve TypeScript errors about `@superset-ui/core` not being resolved correctly, add the following to your `tsconfig.json` file:
```
"references": [
{
"path": "../../packages/superset-ui-chart-controls"
},
{
"path": "../../packages/superset-ui-core"
}
]
```
You may also wish to add the following to the `include` array in `tsconfig.json` to make Superset types available to your plugin:
```
"../../types/**/*"
```
Finally, if you wish to ensure your plugin `tsconfig.json` is aligned with the root Superset project, you may add the following to your `tsconfig.json` file:
```
"extends": "../../tsconfig.json",
```
After this edit the `superset-frontend/src/visualizations/presets/MainPreset.js` and make the following changes:
```js
import { PopKPIPlugin } from '@superset-ui/plugin-chart-period-over-period-kpi';
```
to import the plugin and later add the following to the array that's passed to the `plugins` property:
```js
new PopKPIPlugin().configure({ key: 'pop_kpi' }),
```
After that the plugin should show up when you run Superset, e.g. the development server:
```
npm run dev-server
```

View File

@@ -1,33 +0,0 @@
{
"name": "@superset-ui/plugin-chart-period-over-period-kpi",
"version": "0.1.0",
"description": "Big Number with Time Period Comparison",
"sideEffects": false,
"main": "lib/index.js",
"module": "esm/index.js",
"files": [
"esm",
"lib"
],
"private": true,
"keywords": [
"superset"
],
"author": "Bytecodeio",
"license": "Apache-2.0",
"publishConfig": {
"access": "public"
},
"dependencies": {
"moment": "^2.30.1"
},
"peerDependencies": {
"@superset-ui/chart-controls": "*",
"@superset-ui/core": "*",
"react": "^16.13.1"
},
"devDependencies": {
"@types/jest": "^26.0.4",
"jest": "^26.6.3"
}
}

View File

@@ -1,27 +0,0 @@
/**
* 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.
*/
// eslint-disable-next-line import/prefer-default-export
export { default as PopKPIPlugin } from './plugin';
/**
* Note: this file exports the default export from PopKPI.tsx.
* If you want to export multiple visualization modules, you will need to
* either add additional plugin folders (similar in structure to ./plugin)
* OR export multiple instances of `ChartPlugin` extensions in ./plugin/index.ts
* which in turn load exports from CustomViz.tsx
*/

View File

@@ -1,25 +0,0 @@
{
"compilerOptions": {
"declarationDir": "lib",
"outDir": "lib",
"rootDir": "src"
},
"exclude": [
"lib",
"test"
],
"extends": "../../tsconfig.json",
"include": [
"src/**/*",
"types/**/*",
"../../types/**/*"
],
"references": [
{
"path": "../../packages/superset-ui-chart-controls"
},
{
"path": "../../packages/superset-ui-core"
}
]
}

View File

@@ -1,23 +0,0 @@
/*
* 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.
*/
declare module '*.png' {
const value: any;
export default value;
}

View File

@@ -66,6 +66,7 @@ import {
EchartsSunburstChartPlugin,
EchartsBubbleChartPlugin,
EchartsWaterfallChartPlugin,
BigNumberPeriodOverPeriodChartPlugin,
} from '@superset-ui/plugin-chart-echarts';
import {
SelectFilterPlugin,
@@ -76,7 +77,6 @@ import {
} from 'src/filters/components';
import { PivotTableChartPlugin as PivotTableChartPluginV2 } from '@superset-ui/plugin-chart-pivot-table';
import { HandlebarsChartPlugin } from '@superset-ui/plugin-chart-handlebars';
import { PopKPIPlugin } from '@superset-ui/plugin-chart-period-over-period-kpi';
import TimeTableChartPlugin from '../TimeTable';
export default class MainPreset extends Preset {
@@ -84,7 +84,11 @@ export default class MainPreset extends Preset {
const experimentalPlugins = isFeatureEnabled(
FeatureFlag.ChartPluginsExperimental,
)
? [new PopKPIPlugin().configure({ key: 'pop_kpi' })]
? [
new BigNumberPeriodOverPeriodChartPlugin().configure({
key: 'pop_kpi',
}),
]
: [];
super({