Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(plugin-chart-echarts): support horizontal bar chart #19918

Merged
merged 9 commits into from
May 16, 2022
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@ import { t } from '@superset-ui/core';
import { ControlPanelSectionConfig } from '../types';
import { formatSelectOptions } from '../utils';

const TITLE_MARGIN_OPTIONS: number[] = [15, 30, 50, 75, 100, 125, 150, 200];
const TITLE_POSITION_OPTIONS: string[] = ['Left', 'Top'];
export const TITLE_MARGIN_OPTIONS: number[] = [
15, 30, 50, 75, 100, 125, 150, 200,
];
export const TITLE_POSITION_OPTIONS: string[] = ['Left', 'Top'];
export const titleControls: ControlPanelSectionConfig = {
label: t('Chart Title'),
tabOverride: 'customize',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,19 @@ 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';

import {
DEFAULT_FORM_DATA,
EchartsTimeseriesContributionType,
OrientationType,
} from '../../types';
import {
legendSection,
Expand All @@ -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,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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'),
],
},
],
Expand Down
Loading