/** * 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 { t } from '@apache-superset/core/translation'; import { VizType } from '@superset-ui/core'; import { ControlPanelsContainerProps, ControlSetItem, ControlSetRow, ControlSubSectionHeader, CustomControlItem, DEFAULT_SORT_SERIES_DATA, SORT_SERIES_CHOICES, sharedControls, } from '@superset-ui/chart-controls'; import { DEFAULT_LEGEND_FORM_DATA, StackControlOptions, StackControlOptionsWithoutStream, } from './constants'; import { DEFAULT_FORM_DATA } from './Timeseries/constants'; import { defaultXAxis } from './defaults'; const { legendMargin, legendOrientation, legendType, showLegend } = DEFAULT_LEGEND_FORM_DATA; export const showLegendControl: ControlSetItem = { name: 'show_legend', config: { type: 'CheckboxControl', label: t('Show legend'), renderTrigger: true, default: showLegend, description: t('Whether to display a legend for the chart'), }, }; const legendMarginControl: ControlSetItem = { name: 'legendMargin', config: { type: 'TextControl', label: t('Margin'), renderTrigger: true, isInt: true, default: legendMargin, description: t('Additional padding for legend.'), visibility: ({ controls }: ControlPanelsContainerProps) => Boolean(controls?.show_legend?.value), }, }; const legendTypeControl: ControlSetItem = { name: 'legendType', config: { type: 'SelectControl', freeForm: false, label: t('Type'), choices: [ ['scroll', t('Scroll')], ['plain', t('List')], ], default: legendType, renderTrigger: true, description: t('Legend type'), visibility: ({ controls }: ControlPanelsContainerProps) => Boolean(controls?.show_legend?.value), }, }; const legendOrientationControl: ControlSetItem = { name: 'legendOrientation', config: { type: 'SelectControl', freeForm: false, label: t('Orientation'), choices: [ ['top', t('Top')], ['bottom', t('Bottom')], ['left', t('Left')], ['right', t('Right')], ], default: legendOrientation, renderTrigger: true, description: t('Legend Orientation'), visibility: ({ controls }: ControlPanelsContainerProps) => Boolean(controls?.show_legend?.value), }, }; export const legendSortControl: ControlSetItem = { name: 'legendSort', config: { type: 'SelectControl', label: t('Sort legend'), default: null, renderTrigger: true, choices: [ ['asc', t('Label ascending')], ['desc', t('Label descending')], [null, t('Sort by data')], ], description: t('Changes the sort value of the items in the legend only'), visibility: ({ controls }: ControlPanelsContainerProps) => Boolean(controls?.show_legend?.value), }, }; export const legendSection: ControlSetRow[] = [ [{t('Legend')}], [showLegendControl], [legendTypeControl], [legendOrientationControl], [legendMarginControl], [legendSortControl], ]; export const showValueControl: ControlSetItem = { name: 'show_value', config: { type: 'CheckboxControl', label: t('Show value'), default: false, renderTrigger: true, description: t('Show series values on the chart'), }, }; export const colorByPrimaryAxisControl: ControlSetItem = { name: 'color_by_primary_axis', config: { type: 'CheckboxControl', label: t('Color By X-Axis'), default: false, renderTrigger: true, description: t('Color bars by x-axis'), visibility: ({ controls }: { controls: any }) => (!controls?.stack?.value || controls?.stack?.value === null) && (!controls?.groupby?.value || controls?.groupby?.value?.length === 0), shouldMapStateToProps: () => true, mapStateToProps: (state: any) => { const isHorizontal = state?.controls?.orientation?.value === 'horizontal'; return { label: isHorizontal ? t('Color By Y-Axis') : t('Color By X-Axis'), description: isHorizontal ? t('Color bars by y-axis') : t('Color bars by x-axis'), }; }, }, }; export const stackControl: ControlSetItem = { name: 'stack', config: { type: 'SelectControl', label: t('Stacked Style'), renderTrigger: true, choices: StackControlOptions, default: null, description: t('Stack series on top of each other'), }, }; export const stackControlWithoutStream: ControlSetItem = { ...stackControl, config: { ...stackControl.config, choices: StackControlOptionsWithoutStream, }, }; export const onlyTotalControl: ControlSetItem = { name: 'only_total', config: { type: 'CheckboxControl', label: t('Only Total'), default: true, renderTrigger: true, description: t( 'Only show the total value on the stacked chart, and not show on the selected category', ), visibility: ({ controls }: ControlPanelsContainerProps) => Boolean(controls?.show_value?.value) && Boolean(controls?.stack?.value), }, }; export const percentageThresholdControl: ControlSetItem = { name: 'percentage_threshold', config: { type: 'TextControl', label: t('Percentage threshold'), renderTrigger: true, isFloat: true, default: DEFAULT_FORM_DATA.percentageThreshold, description: t( 'Minimum threshold in percentage points for showing labels.', ), visibility: ({ controls }: ControlPanelsContainerProps) => Boolean(controls?.show_value?.value) && Boolean(controls?.stack?.value) && Boolean(!controls?.only_total?.value), }, }; export const showValueSection: ControlSetRow[] = [ [showValueControl], [stackControl], [onlyTotalControl], [percentageThresholdControl], ]; export const colorByPrimaryAxisSection: ControlSetRow[] = [ [colorByPrimaryAxisControl], ]; export const showValueSectionWithoutStack: ControlSetRow[] = [ [showValueControl], [onlyTotalControl], ]; export const showValueSectionWithoutStream: ControlSetRow[] = [ [showValueControl], [stackControlWithoutStream], [onlyTotalControl], [percentageThresholdControl], ]; const richTooltipControl: ControlSetItem = { name: 'rich_tooltip', config: { type: 'CheckboxControl', label: t('Rich tooltip'), renderTrigger: true, default: true, description: t( 'Shows a list of all series available at that point in time', ), }, }; export const tooltipTimeFormatControl: ControlSetItem = { name: 'tooltipTimeFormat', config: { ...sharedControls.x_axis_time_format, label: t('Tooltip time format'), default: 'smart_date', clearable: false, }, }; export const tooltipValuesFormatControl: CustomControlItem = { name: 'tooltipValuesFormat', config: { ...sharedControls.y_axis_format, label: t('Number format'), clearable: false, }, }; const tooltipSortByMetricControl: ControlSetItem = { name: 'tooltipSortByMetric', config: { type: 'CheckboxControl', label: t('Tooltip sort by metric'), renderTrigger: true, default: false, description: t( 'Whether to sort tooltip by the selected metric in descending order.', ), visibility: ({ controls }: ControlPanelsContainerProps) => Boolean(controls?.rich_tooltip?.value), }, }; const tooltipTotalControl: ControlSetItem = { name: 'showTooltipTotal', config: { type: 'CheckboxControl', label: t('Show total'), renderTrigger: true, default: true, description: t('Whether to display the total value in the tooltip'), visibility: ({ controls, form_data }: ControlPanelsContainerProps) => Boolean(controls?.rich_tooltip?.value) && form_data.viz_type !== VizType.MixedTimeseries, }, }; const tooltipPercentageControl: ControlSetItem = { name: 'showTooltipPercentage', config: { type: 'CheckboxControl', label: t('Show percentage'), renderTrigger: true, default: false, description: t('Whether to display the percentage value in the tooltip'), visibility: ({ controls, form_data }: ControlPanelsContainerProps) => Boolean(controls?.rich_tooltip?.value) && !controls?.contributionMode?.value && form_data.viz_type !== VizType.MixedTimeseries, }, }; export const richTooltipSection: ControlSetRow[] = [ [{t('Tooltip')}], [richTooltipControl], [tooltipTotalControl], [tooltipPercentageControl], [tooltipSortByMetricControl], [tooltipTimeFormatControl], ]; const sortSeriesType: ControlSetItem = { name: 'sort_series_type', config: { type: 'SelectControl', freeForm: false, label: t('Sort Series By'), choices: SORT_SERIES_CHOICES, default: DEFAULT_SORT_SERIES_DATA.sort_series_type, renderTrigger: true, description: t( 'Based on what should series be ordered on the chart and legend', ), }, }; const sortSeriesAscending: ControlSetItem = { name: 'sort_series_ascending', config: { type: 'CheckboxControl', label: t('Sort Series Ascending'), default: DEFAULT_SORT_SERIES_DATA.sort_series_ascending, renderTrigger: true, description: t('Sort series in ascending order'), }, }; export const xAxisLabelRotation = { name: 'xAxisLabelRotation', config: { type: 'SelectControl', freeForm: true, clearable: false, label: t('Rotate x axis label'), choices: [ [0, '0°'], [45, '45°'], [90, '90°'], ], default: defaultXAxis.xAxisLabelRotation, renderTrigger: true, description: t('Input field supports custom rotation. e.g. 30 for 30°'), }, }; export const xAxisLabelInterval = { name: 'xAxisLabelInterval', config: { type: 'SelectControl', freeForm: false, clearable: false, label: t('X Axis Label Interval'), choices: [ ['auto', t('Auto')], ['0', t('All')], ], default: defaultXAxis.xAxisLabelInterval, renderTrigger: true, description: t('Choose how many X-Axis labels to show'), }, }; export const forceMaxInterval = { name: 'force_max_interval', config: { type: 'CheckboxControl', label: t('Force Time Grain as Max Interval'), renderTrigger: true, default: false, description: t( 'Forces selected Time Grain as the maximum interval for X Axis Labels', ), visibility: ({ controls }: ControlPanelsContainerProps) => Boolean(controls?.time_grain_sqla?.value), }, }; export const seriesOrderSection: ControlSetRow[] = [ [{t('Series Order')}], [sortSeriesType], [sortSeriesAscending], ]; export const truncateXAxis: ControlSetItem = { name: 'truncateXAxis', config: { type: 'CheckboxControl', label: t('Truncate X Axis'), default: DEFAULT_FORM_DATA.truncateXAxis, renderTrigger: true, description: t( 'Truncate X Axis. Can be overridden by specifying a min or max bound. Only applicable for numerical X axis.', ), }, }; export const xAxisBounds: ControlSetItem = { name: 'xAxisBounds', config: { type: 'BoundsControl', label: t('X Axis Bounds'), renderTrigger: true, default: DEFAULT_FORM_DATA.xAxisBounds, description: t( 'Bounds for numerical X axis. Not applicable for temporal or categorical axes. ' + '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?.truncateXAxis?.value), }, }; export const minorTicks: ControlSetItem = { name: 'minorTicks', config: { type: 'CheckboxControl', label: t('Minor ticks'), default: false, renderTrigger: true, description: t('Show minor ticks on axes.'), }, }; export const forceCategorical: ControlSetItem = { name: 'forceCategorical', config: { type: 'CheckboxControl', label: t('Force categorical'), default: false, renderTrigger: true, description: t('Make the x-axis categorical'), }, }; export const showExtraControls: CustomControlItem = { name: 'show_extra_controls', config: { type: 'CheckboxControl', label: t('Extra Controls'), renderTrigger: true, default: false, }, };