Skip to content

Commit

Permalink
feat(plugin-chart-echarts): echarts funnel chart (apache#1006)
Browse files Browse the repository at this point in the history
* fix(plugin-chart-echarts): funnel rebase master

* fix(plugin-chart-echarts): resize thumbnail for Funnel Chart

* fix(plugin-chart-echarts): rm Funnel shape

* fix(plugin-chart-echarts): don't need the sort_by_metric control

* fix(plugin-chart-echarts): add sort and orient into Funnel shape

* refactor: use sharedControls instead of controlOverrides

* fix(plugin-chart-echarts): rm min/max args to use echarts default

* style(plugin-chart-echarts): update funnel thumbnail

* style(plugin-chart-echarts): rm unused properties

* fix(plugin-chart-echarts): revert yarn.lock into then one from master

* style(plugin-chart-echarts): add newline at the end of yarn.lock

* style(plugin-chart-echarts): npm run format

n

* style(plugin-chart-echarts): inser final new line to yarn.lock

* fix(demo): update funnel to Funnel

* feat(plugin-chart-echarts): add cross-filter

* feat(plugin-chart-echarts): add cross-filter
  • Loading branch information
xiezhongfu authored and zhaoyongjie committed Nov 26, 2021
1 parent 3d3393c commit 639c8ba
Show file tree
Hide file tree
Showing 13 changed files with 859 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import React from 'react';
import { SuperChart, getChartTransformPropsRegistry } from '@superset-ui/core';
import { boolean, number, select, withKnobs } from '@storybook/addon-knobs';
import { EchartsFunnelChartPlugin } from '@superset-ui/plugin-chart-echarts';
import transformProps from '@superset-ui/plugin-chart-echarts/lib/Funnel/transformProps';
import { dataSource } from './constants';
import { withResizableChartDemo } from '../../../../shared/components/ResizableChartDemo';

new EchartsFunnelChartPlugin().configure({ key: 'echarts-funnel' }).register();

getChartTransformPropsRegistry().registerValue('echarts-funnel', transformProps);

export default {
title: 'Chart Plugins|plugin-chart-echarts/Funnel',
decorators: [withKnobs, withResizableChartDemo],
};

export const Funnel = ({ width, height }) => {
return (
<SuperChart
chartType="echarts-funnel"
width={width}
height={height}
queriesData={[{ data: dataSource }]}
formData={{
colorScheme: 'supersetColors',
groupby: ['name'],
metric: 'value',
numberFormat: 'SMART_NUMBER',
orient: select('orient', ['horizontal', 'vertical'], 'vertical'),
sort: select('sort', ['descending', 'ascending', 'none'], 'descending'),
gap: number('gap', 0),
labelType: select(
'label type',
['key', 'value', 'percent', 'key_value', 'key_percent', 'key_value_percent'],
'key',
),
labelLine: boolean('Label line', true),
showLabels: boolean('Show labels', true),
showLegend: boolean('Show legend', false),
}}
/>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export const dataSource = [
{ value: 89439, name: 'pv' },
{ value: 5526, name: 'cart' },
{ value: 2824, name: 'fav' },
{ value: 2211, name: 'buy' },
];
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/**
* 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 React, { useCallback } from 'react';
import { FunnelChartTransformedProps } from './types';
import Echart from '../components/Echart';
import { EventHandlers } from '../types';

export default function EchartsFunnel({
height,
width,
echartOptions,
setDataMask,
labelMap,
groupby,
selectedValues,
formData,
}: FunnelChartTransformedProps) {
const handleChange = useCallback(
(values: string[]) => {
if (!formData.emitFilter) {
return;
}

const groupbyValues = values.map(value => labelMap[value]);

setDataMask({
extraFormData: {
filters:
values.length === 0
? []
: groupby.map((col, idx) => {
const val = groupbyValues.map(v => v[idx]);
if (val === null || val === undefined)
return {
col,
op: 'IS NULL',
};
return {
col,
op: 'IN',
val: val as (string | number | boolean)[],
};
}),
},
filterState: {
value: groupbyValues.length ? groupbyValues : null,
},
ownState: {
selectedValues: values.length ? values : null,
},
});
},
[groupby, labelMap, setDataMask, selectedValues],
);

const eventHandlers: EventHandlers = {
click: props => {
const { name } = props;
const values = Object.values(selectedValues);
if (values.includes(name)) {
handleChange(values.filter(v => v !== name));
} else {
handleChange([...values, name]);
}
},
};

return (
<Echart
height={height}
width={width}
echartOptions={echartOptions}
eventHandlers={eventHandlers}
selectedValues={selectedValues}
/>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/**
* 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 { buildQueryContext, QueryFormData } from '@superset-ui/core';

export default function buildQuery(formData: QueryFormData) {
return buildQueryContext(formData, baseQueryObject => [
{
...baseQueryObject,
},
]);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
/**
* 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 React from 'react';
import { FeatureFlag, isFeatureEnabled, t } from '@superset-ui/core';
import {
ControlPanelConfig,
D3_FORMAT_OPTIONS,
sections,
sharedControls,
} from '@superset-ui/chart-controls';
import { DEFAULT_FORM_DATA, EchartsFunnelLabelTypeType } from './types';
import {
legendMarginControl,
legendOrientationControl,
legendTypeControl,
showLegendControl,
} from '../controls';

const {
sort,
orient,
labelLine,
labelType,
numberFormat,
showLabels,
emitFilter,
} = DEFAULT_FORM_DATA;

const config: ControlPanelConfig = {
controlPanelSections: [
sections.legacyRegularTime,
{
label: t('Query'),
expanded: true,
controlSetRows: [
['groupby'],
['metric'],
['adhoc_filters'],
[
{
name: 'row_limit',
config: {
...sharedControls.row_limit,
default: 10,
},
},
],
],
},
{
label: t('Chart Options'),
expanded: true,
controlSetRows: [
['color_scheme'],
isFeatureEnabled(FeatureFlag.DASHBOARD_CROSS_FILTERS)
? [
{
name: 'emit_filter',
config: {
type: 'CheckboxControl',
label: t('Enable emitting filters'),
default: emitFilter,
renderTrigger: true,
description: t('Enable emmiting filters.'),
},
},
]
: [],
// eslint-disable-next-line react/jsx-key
[<h1 className="section-header">{t('Legend')}</h1>],
[showLegendControl],
[legendTypeControl],
[legendOrientationControl],
[legendMarginControl],
// eslint-disable-next-line react/jsx-key
[<h1 className="section-header">{t('Labels')}</h1>],
[
{
name: 'label_type',
config: {
type: 'SelectControl',
label: t('Label Type'),
default: labelType,
renderTrigger: true,
choices: [
[EchartsFunnelLabelTypeType.Key, 'Category Name'],
[EchartsFunnelLabelTypeType.Value, 'Value'],
[EchartsFunnelLabelTypeType.Percent, 'Percentage'],
[EchartsFunnelLabelTypeType.KeyValue, 'Category and Value'],
[EchartsFunnelLabelTypeType.KeyPercent, 'Category and Percentage'],
[EchartsFunnelLabelTypeType.KeyValuePercent, 'Category, Value and Percentage'],
],
description: t('What should be shown on the label?'),
},
},
],
[
{
name: 'number_format',
config: {
type: 'SelectControl',
freeForm: true,
label: t('Number format'),
renderTrigger: true,
default: numberFormat,
choices: D3_FORMAT_OPTIONS,
description: `${t('D3 format syntax: https://github.com/d3/d3-format')} ${t(
'Only applies when "Label Type" is set to show values.',
)}`,
},
},
],
[
{
name: 'show_labels',
config: {
type: 'CheckboxControl',
label: t('Show Labels'),
renderTrigger: true,
default: showLabels,
description: t('Whether to display the labels.'),
},
},
],
[
{
name: 'label_line',
config: {
type: 'CheckboxControl',
label: t('Label Line'),
default: labelLine,
renderTrigger: true,
description: t('Draw line from Funnel to label when labels outside?'),
},
},
],
// eslint-disable-next-line react/jsx-key
[<h1 className="section-header">{t('Funnel shape')}</h1>],
[
{
name: 'sort',
config: {
type: 'SelectControl',
label: t('sort'),
default: sort,
renderTrigger: true,
choices: [
[null, 'Default'],
['ascending', 'Ascending'],
['descending', 'Descending'],
],
description: t('Sort data'),
},
},
{
name: 'orient',
config: {
type: 'SelectControl',
label: t('orient'),
default: orient,
renderTrigger: true,
choices: [
[null, 'Default'],
['vertical', 'Vertical'],
['horizontal', 'Horizontal'],
],
description: t('Funnel chart orientation. The options are vertical, horizontal'),
},
},
],
],
},
],
};

export default config;
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 639c8ba

Please sign in to comment.