mirror of
https://github.com/apache/superset.git
synced 2026-05-07 17:04:58 +00:00
feat(plugin-chart-echarts): support horizontal bar chart (#19918)
* feat(plugin-chart-echarts): support horizontal bar chart * Update superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Regular/Bar/controlPanel.tsx Co-authored-by: Evan Rusackas <evan@preset.io> * Update superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/transformProps.ts Co-authored-by: Ville Brofeldt <33317356+villebro@users.noreply.github.com> * Update superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/transformProps.ts Co-authored-by: Ville Brofeldt <33317356+villebro@users.noreply.github.com> * Update superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Regular/Bar/controlPanel.tsx Co-authored-by: Ville Brofeldt <33317356+villebro@users.noreply.github.com> * improve controlpanel * default value * fix ut Co-authored-by: Evan Rusackas <evan@preset.io> Co-authored-by: Ville Brofeldt <33317356+villebro@users.noreply.github.com>
This commit is contained in:
@@ -21,8 +21,11 @@ import { FeatureFlag, isFeatureEnabled, t } from '@superset-ui/core';
|
||||
import {
|
||||
ControlPanelConfig,
|
||||
ControlPanelsContainerProps,
|
||||
ControlSetRow,
|
||||
ControlStateMapping,
|
||||
D3_TIME_FORMAT_DOCS,
|
||||
emitFilterControl,
|
||||
formatSelectOptions,
|
||||
sections,
|
||||
sharedControls,
|
||||
} from '@superset-ui/chart-controls';
|
||||
@@ -30,6 +33,7 @@ import {
|
||||
import {
|
||||
DEFAULT_FORM_DATA,
|
||||
EchartsTimeseriesContributionType,
|
||||
OrientationType,
|
||||
} from '../../types';
|
||||
import {
|
||||
legendSection,
|
||||
@@ -49,7 +53,217 @@ const {
|
||||
yAxisBounds,
|
||||
zoomable,
|
||||
xAxisLabelRotation,
|
||||
orientation,
|
||||
} = DEFAULT_FORM_DATA;
|
||||
|
||||
function createAxisTitleControl(axis: 'x' | 'y'): ControlSetRow[] {
|
||||
const isXAxis = axis === 'x';
|
||||
const isVertical = (controls: ControlStateMapping) =>
|
||||
Boolean(controls?.orientation.value === OrientationType.vertical);
|
||||
const isHorizental = (controls: ControlStateMapping) =>
|
||||
Boolean(controls?.orientation.value === OrientationType.horizontal);
|
||||
return [
|
||||
[
|
||||
{
|
||||
name: 'x_axis_title',
|
||||
config: {
|
||||
type: 'TextControl',
|
||||
label: t('Axis Title'),
|
||||
renderTrigger: true,
|
||||
default: '',
|
||||
description: t('Changing this control takes effect instantly'),
|
||||
visibility: ({ controls }: ControlPanelsContainerProps) =>
|
||||
isXAxis ? isVertical(controls) : isHorizental(controls),
|
||||
},
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
name: 'x_axis_title_margin',
|
||||
config: {
|
||||
type: 'SelectControl',
|
||||
freeForm: true,
|
||||
clearable: true,
|
||||
label: t('AXIS TITLE MARGIN'),
|
||||
renderTrigger: true,
|
||||
default: sections.TITLE_MARGIN_OPTIONS[0],
|
||||
choices: formatSelectOptions(sections.TITLE_MARGIN_OPTIONS),
|
||||
description: t('Changing this control takes effect instantly'),
|
||||
visibility: ({ controls }: ControlPanelsContainerProps) =>
|
||||
isXAxis ? isVertical(controls) : isHorizental(controls),
|
||||
},
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
name: 'y_axis_title',
|
||||
config: {
|
||||
type: 'TextControl',
|
||||
label: t('Axis Title'),
|
||||
renderTrigger: true,
|
||||
default: '',
|
||||
description: t('Changing this control takes effect instantly'),
|
||||
visibility: ({ controls }: ControlPanelsContainerProps) =>
|
||||
isXAxis ? isHorizental(controls) : isVertical(controls),
|
||||
},
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
name: 'y_axis_title_margin',
|
||||
config: {
|
||||
type: 'SelectControl',
|
||||
freeForm: true,
|
||||
clearable: true,
|
||||
label: t('AXIS TITLE MARGIN'),
|
||||
renderTrigger: true,
|
||||
default: sections.TITLE_MARGIN_OPTIONS[0],
|
||||
choices: formatSelectOptions(sections.TITLE_MARGIN_OPTIONS),
|
||||
description: t('Changing this control takes effect instantly'),
|
||||
visibility: ({ controls }: ControlPanelsContainerProps) =>
|
||||
isXAxis ? isHorizental(controls) : isVertical(controls),
|
||||
},
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
name: 'y_axis_title_position',
|
||||
config: {
|
||||
type: 'SelectControl',
|
||||
freeForm: true,
|
||||
clearable: false,
|
||||
label: t('AXIS TITLE POSITION'),
|
||||
renderTrigger: true,
|
||||
default: sections.TITLE_POSITION_OPTIONS[0],
|
||||
choices: formatSelectOptions(sections.TITLE_POSITION_OPTIONS),
|
||||
description: t('Changing this control takes effect instantly'),
|
||||
visibility: ({ controls }: ControlPanelsContainerProps) =>
|
||||
isXAxis ? isHorizental(controls) : isVertical(controls),
|
||||
},
|
||||
},
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
function createAxisControl(axis: 'x' | 'y'): ControlSetRow[] {
|
||||
const isXAxis = axis === 'x';
|
||||
const isVertical = (controls: ControlStateMapping) =>
|
||||
Boolean(controls?.orientation.value === OrientationType.vertical);
|
||||
const isHorizental = (controls: ControlStateMapping) =>
|
||||
Boolean(controls?.orientation.value === OrientationType.horizontal);
|
||||
return [
|
||||
[
|
||||
{
|
||||
name: 'x_axis_time_format',
|
||||
config: {
|
||||
...sharedControls.x_axis_time_format,
|
||||
default: 'smart_date',
|
||||
description: `${D3_TIME_FORMAT_DOCS}. ${t(
|
||||
'When using other than adaptive formatting, labels may overlap.',
|
||||
)}`,
|
||||
visibility: ({ controls }: ControlPanelsContainerProps) =>
|
||||
isXAxis ? isVertical(controls) : isHorizental(controls),
|
||||
},
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
name: 'xAxisLabelRotation',
|
||||
config: {
|
||||
type: 'SelectControl',
|
||||
freeForm: true,
|
||||
clearable: false,
|
||||
label: t('Rotate axis label'),
|
||||
choices: [
|
||||
[0, '0°'],
|
||||
[45, '45°'],
|
||||
],
|
||||
default: xAxisLabelRotation,
|
||||
renderTrigger: true,
|
||||
description: t(
|
||||
'Input field supports custom rotation. e.g. 30 for 30°',
|
||||
),
|
||||
visibility: ({ controls }: ControlPanelsContainerProps) =>
|
||||
isXAxis ? isVertical(controls) : isHorizental(controls),
|
||||
},
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
name: 'y_axis_format',
|
||||
config: {
|
||||
...sharedControls.y_axis_format,
|
||||
label: t('Axis Format'),
|
||||
visibility: ({ controls }: ControlPanelsContainerProps) =>
|
||||
isXAxis ? isHorizental(controls) : isVertical(controls),
|
||||
},
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
name: 'logAxis',
|
||||
config: {
|
||||
type: 'CheckboxControl',
|
||||
label: t('Logarithmic axis'),
|
||||
renderTrigger: true,
|
||||
default: logAxis,
|
||||
description: t('Logarithmic axis'),
|
||||
visibility: ({ controls }: ControlPanelsContainerProps) =>
|
||||
isXAxis ? isHorizental(controls) : isVertical(controls),
|
||||
},
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
name: 'minorSplitLine',
|
||||
config: {
|
||||
type: 'CheckboxControl',
|
||||
label: t('Minor Split Line'),
|
||||
renderTrigger: true,
|
||||
default: minorSplitLine,
|
||||
description: t('Draw split lines for minor axis ticks'),
|
||||
visibility: ({ controls }: ControlPanelsContainerProps) =>
|
||||
isXAxis ? isHorizental(controls) : isVertical(controls),
|
||||
},
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
name: 'truncateYAxis',
|
||||
config: {
|
||||
type: 'CheckboxControl',
|
||||
label: t('Truncate Axis'),
|
||||
default: truncateYAxis,
|
||||
renderTrigger: true,
|
||||
description: t('It’s not recommended to truncate axis in Bar chart.'),
|
||||
visibility: ({ controls }: ControlPanelsContainerProps) =>
|
||||
isXAxis ? isHorizental(controls) : isVertical(controls),
|
||||
},
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
name: 'y_axis_bounds',
|
||||
config: {
|
||||
type: 'BoundsControl',
|
||||
label: t('Axis Bounds'),
|
||||
renderTrigger: true,
|
||||
default: yAxisBounds,
|
||||
description: t(
|
||||
'Bounds for the axis. When left empty, the bounds are ' +
|
||||
'dynamically defined based on the min/max of the data. Note that ' +
|
||||
"this feature will only expand the axis range. It won't " +
|
||||
"narrow the data's extent.",
|
||||
),
|
||||
visibility: ({ controls }: ControlPanelsContainerProps) =>
|
||||
Boolean(controls?.truncateYAxis?.value) &&
|
||||
(isXAxis ? isHorizental(controls) : isVertical(controls)),
|
||||
},
|
||||
},
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
const config: ControlPanelConfig = {
|
||||
controlPanelSections: [
|
||||
sections.legacyTimeseriesTime,
|
||||
@@ -87,7 +301,39 @@ const config: ControlPanelConfig = {
|
||||
sections.advancedAnalyticsControls,
|
||||
sections.annotationsAndLayersControls,
|
||||
sections.forecastIntervalControls,
|
||||
sections.titleControls,
|
||||
{
|
||||
label: t('Chart Orientation'),
|
||||
expanded: true,
|
||||
controlSetRows: [
|
||||
[
|
||||
{
|
||||
name: 'orientation',
|
||||
config: {
|
||||
type: 'RadioButtonControl',
|
||||
renderTrigger: true,
|
||||
label: t('Bar orientation'),
|
||||
default: orientation,
|
||||
options: [
|
||||
[OrientationType.vertical, t('Vertical')],
|
||||
[OrientationType.horizontal, t('Horizontal')],
|
||||
],
|
||||
description: t('Orientation of bar chart'),
|
||||
},
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
{
|
||||
label: t('Chart Title'),
|
||||
tabOverride: 'customize',
|
||||
expanded: true,
|
||||
controlSetRows: [
|
||||
[<div className="section-header">{t('X Axis')}</div>],
|
||||
...createAxisTitleControl('x'),
|
||||
[<div className="section-header">{t('Y Axis')}</div>],
|
||||
...createAxisTitleControl('y'),
|
||||
],
|
||||
},
|
||||
{
|
||||
label: t('Chart Options'),
|
||||
expanded: true,
|
||||
@@ -140,101 +386,10 @@ const config: ControlPanelConfig = {
|
||||
],
|
||||
...legendSection,
|
||||
[<div className="section-header">{t('X Axis')}</div>],
|
||||
[
|
||||
{
|
||||
name: 'x_axis_time_format',
|
||||
config: {
|
||||
...sharedControls.x_axis_time_format,
|
||||
default: 'smart_date',
|
||||
description: `${D3_TIME_FORMAT_DOCS}. ${t(
|
||||
'When using other than adaptive formatting, labels may overlap.',
|
||||
)}`,
|
||||
},
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
name: 'xAxisLabelRotation',
|
||||
config: {
|
||||
type: 'SelectControl',
|
||||
freeForm: true,
|
||||
clearable: false,
|
||||
label: t('Rotate x axis label'),
|
||||
choices: [
|
||||
[0, '0°'],
|
||||
[45, '45°'],
|
||||
],
|
||||
default: xAxisLabelRotation,
|
||||
renderTrigger: true,
|
||||
description: t(
|
||||
'Input field supports custom rotation. e.g. 30 for 30°',
|
||||
),
|
||||
},
|
||||
},
|
||||
],
|
||||
// eslint-disable-next-line react/jsx-key
|
||||
...createAxisControl('x'),
|
||||
...richTooltipSection,
|
||||
// eslint-disable-next-line react/jsx-key
|
||||
[<div className="section-header">{t('Y Axis')}</div>],
|
||||
|
||||
['y_axis_format'],
|
||||
[
|
||||
{
|
||||
name: 'logAxis',
|
||||
config: {
|
||||
type: 'CheckboxControl',
|
||||
label: t('Logarithmic y-axis'),
|
||||
renderTrigger: true,
|
||||
default: logAxis,
|
||||
description: t('Logarithmic y-axis'),
|
||||
},
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
name: 'minorSplitLine',
|
||||
config: {
|
||||
type: 'CheckboxControl',
|
||||
label: t('Minor Split Line'),
|
||||
renderTrigger: true,
|
||||
default: minorSplitLine,
|
||||
description: t('Draw split lines for minor y-axis ticks'),
|
||||
},
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
name: 'truncateYAxis',
|
||||
config: {
|
||||
type: 'CheckboxControl',
|
||||
label: t('Truncate Y Axis'),
|
||||
default: truncateYAxis,
|
||||
renderTrigger: true,
|
||||
description: t(
|
||||
'It’s not recommended to truncate y-axis in Bar chart.',
|
||||
),
|
||||
},
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
name: 'y_axis_bounds',
|
||||
config: {
|
||||
type: 'BoundsControl',
|
||||
label: t('Y Axis Bounds'),
|
||||
renderTrigger: true,
|
||||
default: yAxisBounds,
|
||||
description: t(
|
||||
'Bounds for the Y-axis. When left empty, the bounds are ' +
|
||||
'dynamically defined based on the min/max of the data. Note that ' +
|
||||
"this feature will only expand the axis range. It won't " +
|
||||
"narrow the data's extent.",
|
||||
),
|
||||
visibility: ({ controls }: ControlPanelsContainerProps) =>
|
||||
Boolean(controls?.truncateYAxis?.value),
|
||||
},
|
||||
},
|
||||
],
|
||||
...createAxisControl('y'),
|
||||
],
|
||||
},
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user