This is an automated email from the ASF dual-hosted git repository.
rusackas pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/superset.git
The following commit(s) were added to refs/heads/master by this push:
new 61d8a0bd12 feat: conditional coloring for big number chart (#23064)
61d8a0bd12 is described below
commit 61d8a0bd1206ffc96ea2f9284e4c238241fcca79
Author: Gerold Busch <[email protected]>
AuthorDate: Mon May 1 17:44:46 2023 +0200
feat: conditional coloring for big number chart (#23064)
Co-authored-by: Gerold Busch <[email protected]>
---
.../src/utils/getColorFormatters.ts | 14 +++++---
.../test/utils/getColorFormatters.test.ts | 19 ++++++++++
.../src/BigNumber/BigNumberTotal/controlPanel.ts | 42 +++++++++++++++++++++-
.../src/BigNumber/BigNumberTotal/transformProps.ts | 12 +++++++
.../src/BigNumber/BigNumberViz.tsx | 22 +++++++++++-
.../plugin-chart-echarts/src/BigNumber/types.ts | 2 ++
.../FormattingPopoverContent.tsx | 9 +++--
7 files changed, 111 insertions(+), 9 deletions(-)
diff --git
a/superset-frontend/packages/superset-ui-chart-controls/src/utils/getColorFormatters.ts
b/superset-frontend/packages/superset-ui-chart-controls/src/utils/getColorFormatters.ts
index f613beb074..1a6aa140a6 100644
---
a/superset-frontend/packages/superset-ui-chart-controls/src/utils/getColorFormatters.ts
+++
b/superset-frontend/packages/superset-ui-chart-controls/src/utils/getColorFormatters.ts
@@ -62,6 +62,7 @@ export const getColorFunction = (
colorScheme,
}: ConditionalFormattingConfig,
columnValues: number[],
+ alpha?: boolean,
) => {
let minOpacity = MIN_OPACITY_BOUNDED;
const maxOpacity = MAX_OPACITY;
@@ -176,10 +177,13 @@ export const getColorFunction = (
const compareResult = comparatorFunction(value, columnValues);
if (compareResult === false) return undefined;
const { cutoffValue, extremeValue } = compareResult;
- return addAlpha(
- colorScheme,
- getOpacity(value, cutoffValue, extremeValue, minOpacity, maxOpacity),
- );
+ if (alpha === undefined || alpha) {
+ return addAlpha(
+ colorScheme,
+ getOpacity(value, cutoffValue, extremeValue, minOpacity, maxOpacity),
+ );
+ }
+ return colorScheme;
};
};
@@ -187,6 +191,7 @@ export const getColorFormatters = memoizeOne(
(
columnConfig: ConditionalFormattingConfig[] | undefined,
data: DataRecord[],
+ alpha?: boolean,
) =>
columnConfig?.reduce(
(acc: ColorFormatters, config: ConditionalFormattingConfig) => {
@@ -204,6 +209,7 @@ export const getColorFormatters = memoizeOne(
getColorFromValue: getColorFunction(
config,
data.map(row => row[config.column!] as number),
+ alpha,
),
});
}
diff --git
a/superset-frontend/packages/superset-ui-chart-controls/test/utils/getColorFormatters.test.ts
b/superset-frontend/packages/superset-ui-chart-controls/test/utils/getColorFormatters.test.ts
index 4b957f628c..7daa3f968d 100644
---
a/superset-frontend/packages/superset-ui-chart-controls/test/utils/getColorFormatters.test.ts
+++
b/superset-frontend/packages/superset-ui-chart-controls/test/utils/getColorFormatters.test.ts
@@ -188,6 +188,25 @@ describe('getColorFunction()', () => {
expect(colorFunction(150)).toBeUndefined();
});
+ it('getColorFunction BETWEEN_OR_EQUAL without opacity', () => {
+ const colorFunction = getColorFunction(
+ {
+ operator: COMPARATOR.BETWEEN_OR_EQUAL,
+ targetValueLeft: 50,
+ targetValueRight: 100,
+ colorScheme: '#FF0000',
+ column: 'count',
+ },
+ countValues,
+ false,
+ );
+ expect(colorFunction(25)).toBeUndefined();
+ expect(colorFunction(50)).toEqual('#FF0000');
+ expect(colorFunction(75)).toEqual('#FF0000');
+ expect(colorFunction(100)).toEqual('#FF0000');
+ expect(colorFunction(125)).toBeUndefined();
+ });
+
it('getColorFunction BETWEEN_OR_LEFT_EQUAL', () => {
const colorFunction = getColorFunction(
{
diff --git
a/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberTotal/controlPanel.ts
b/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberTotal/controlPanel.ts
index daacaa283a..abe4ce215f 100644
---
a/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberTotal/controlPanel.ts
+++
b/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberTotal/controlPanel.ts
@@ -16,11 +16,12 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { smartDateFormatter, t } from '@superset-ui/core';
+import { GenericDataType, smartDateFormatter, t } from '@superset-ui/core';
import {
ControlPanelConfig,
D3_FORMAT_DOCS,
D3_TIME_FORMAT_OPTIONS,
+ Dataset,
getStandardizedControls,
sections,
} from '@superset-ui/chart-controls';
@@ -89,6 +90,45 @@ export default {
},
},
],
+ [
+ {
+ name: 'conditional_formatting',
+ config: {
+ type: 'ConditionalFormattingControl',
+ renderTrigger: true,
+ label: t('Conditional Formatting'),
+ description: t('Apply conditional color formatting to metric'),
+ shouldMapStateToProps() {
+ return true;
+ },
+ mapStateToProps(explore, _, chart) {
+ const verboseMap = explore?.datasource?.hasOwnProperty(
+ 'verbose_map',
+ )
+ ? (explore?.datasource as Dataset)?.verbose_map
+ : explore?.datasource?.columns ?? {};
+ const { colnames, coltypes } =
+ chart?.queriesResponse?.[0] ?? {};
+ const numericColumns =
+ Array.isArray(colnames) && Array.isArray(coltypes)
+ ? colnames
+ .filter(
+ (colname: string, index: number) =>
+ coltypes[index] === GenericDataType.NUMERIC,
+ )
+ .map(colname => ({
+ value: colname,
+ label: verboseMap[colname] ?? colname,
+ }))
+ : [];
+ return {
+ columnOptions: numericColumns,
+ verboseMap,
+ };
+ },
+ },
+ },
+ ],
],
},
],
diff --git
a/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberTotal/transformProps.ts
b/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberTotal/transformProps.ts
index e690b1ef52..8624e5bc54 100644
---
a/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberTotal/transformProps.ts
+++
b/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberTotal/transformProps.ts
@@ -16,6 +16,10 @@
* specific language governing permissions and limitations
* under the License.
*/
+import {
+ ColorFormatters,
+ getColorFormatters,
+} from '@superset-ui/chart-controls';
import {
getNumberFormatter,
GenericDataType,
@@ -40,6 +44,7 @@ export default function transformProps(
forceTimestampFormatting,
timeFormat,
yAxisFormat,
+ conditionalFormatting,
} = formData;
const refs: Refs = {};
const { data = [], coltypes = [] } = queriesData[0];
@@ -71,6 +76,12 @@ export default function transformProps(
const { onContextMenu } = hooks;
+ const defaultColorFormatters = [] as ColorFormatters;
+
+ const colorThresholdFormatters =
+ getColorFormatters(conditionalFormatting, data, false) ??
+ defaultColorFormatters;
+
return {
width,
height,
@@ -81,5 +92,6 @@ export default function transformProps(
subheader: formattedSubheader,
onContextMenu,
refs,
+ colorThresholdFormatters,
};
}
diff --git
a/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberViz.tsx
b/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberViz.tsx
index 4762a789d0..112e21657f 100644
---
a/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberViz.tsx
+++
b/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberViz.tsx
@@ -128,10 +128,29 @@ class BigNumberVis extends
React.PureComponent<BigNumberVizProps> {
}
renderHeader(maxHeight: number) {
- const { bigNumber, headerFormatter, width } = this.props;
+ const { bigNumber, headerFormatter, width, colorThresholdFormatters } =
+ this.props;
// @ts-ignore
const text = bigNumber === null ? t('No data') :
headerFormatter(bigNumber);
+ const hasThresholdColorFormatter =
+ Array.isArray(colorThresholdFormatters) &&
+ colorThresholdFormatters.length > 0;
+
+ let numberColor;
+ if (hasThresholdColorFormatter) {
+ colorThresholdFormatters!.forEach(formatter => {
+ const formatterResult = bigNumber
+ ? formatter.getColorFromValue(bigNumber as number)
+ : false;
+ if (formatterResult) {
+ numberColor = formatterResult;
+ }
+ });
+ } else {
+ numberColor = 'black';
+ }
+
const container = this.createTemporaryContainer();
document.body.append(container);
const fontSize = computeMaxFontSize({
@@ -156,6 +175,7 @@ class BigNumberVis extends
React.PureComponent<BigNumberVizProps> {
style={{
fontSize,
height: maxHeight,
+ color: numberColor,
}}
onContextMenu={onContextMenu}
>
diff --git
a/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/types.ts
b/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/types.ts
index f0a17e708b..c517fcc0b9 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/types.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/types.ts
@@ -27,6 +27,7 @@ import {
QueryFormMetric,
TimeFormatter,
} from '@superset-ui/core';
+import { ColorFormatters } from '@superset-ui/chart-controls';
import { BaseChartProps, Refs } from '../types';
export interface BigNumberDatum {
@@ -94,4 +95,5 @@ export type BigNumberVizProps = {
xValueFormatter?: TimeFormatter;
formData?: BigNumberWithTrendlineFormData;
refs: Refs;
+ colorThresholdFormatters?: ColorFormatters;
};
diff --git
a/superset-frontend/src/explore/components/controls/ConditionalFormattingControl/FormattingPopoverContent.tsx
b/superset-frontend/src/explore/components/controls/ConditionalFormattingControl/FormattingPopoverContent.tsx
index d50e71608b..154255eee7 100644
---
a/superset-frontend/src/explore/components/controls/ConditionalFormattingControl/FormattingPopoverContent.tsx
+++
b/superset-frontend/src/explore/components/controls/ConditionalFormattingControl/FormattingPopoverContent.tsx
@@ -39,9 +39,12 @@ const JustifyEnd = styled.div`
`;
const colorSchemeOptions = (theme: SupersetTheme) => [
- { value: theme.colors.success.light1, label: t('green') },
- { value: theme.colors.alert.light1, label: t('yellow') },
- { value: theme.colors.error.light1, label: t('red') },
+ { value: theme.colors.success.light1, label: t('success') },
+ { value: theme.colors.alert.light1, label: t('alert') },
+ { value: theme.colors.error.light1, label: t('error') },
+ { value: theme.colors.success.dark1, label: t('success dark') },
+ { value: theme.colors.alert.dark1, label: t('alert dark') },
+ { value: theme.colors.error.dark1, label: t('error dark') },
];
const operatorOptions = [