Skip to content

Commit

Permalink
feat(plugin-chart-table): add small number formatter (#1028)
Browse files Browse the repository at this point in the history
* feat(plugin-chart-table): add small number formatter

* Fix basic storybook
  • Loading branch information
ktmud authored and zhaoyongjie committed Nov 26, 2021
1 parent 98d2502 commit 090e3b1
Show file tree
Hide file tree
Showing 8 changed files with 178 additions and 122 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ export function InfoTooltipWithTrigger({
onClick={onClick}
onKeyPress={
onClick &&
((event: React.KeyboardEvent) => {
(event => {
if (event.key === 'Enter' || event.key === ' ') {
onClick();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
* specific language governing permissions and limitations
* under the License.
*/
import React, { useState, ReactNode, ReactElement } from 'react';
import AntdSelect, { SelectProps as AntdSelectProps, OptionProps } from 'antd/lib/select';
import React, { useState, ReactNode } from 'react';
import AntdSelect, { SelectProps as AntdSelectProps } from 'antd/lib/select';

export const { Option } = AntdSelect;

Expand All @@ -34,12 +34,14 @@ export type SelectProps<VT> = Omit<AntdSelectProps<VT>, 'options'> & {
*/
export default function Select<VT extends string | number>({
creatable,
children,
onSearch,
dropdownMatchSelectWidth = false,
minWidth = '100%',
showSearch: showSearch_ = true,
onChange,
options,
children,
value,
...props
}: SelectProps<VT>) {
const [searchValue, setSearchValue] = useState<string>();
Expand All @@ -56,15 +58,26 @@ export default function Select<VT extends string | number>({
}
: undefined;

const searchValueNotFound = React.Children.toArray(children).every(
node => node && (node as ReactElement<OptionProps>).props.value !== searchValue,
);
const optionsHasSearchValue = options?.some(([val]) => val === searchValue);
const optionsHasValue = options?.some(([val]) => val === value);

const handleChange: SelectProps<VT>['onChange'] = showSearch
? (val, opt) => {
// reset input value once selected
setSearchValue('');
if (onChange) {
onChange(val, opt);
}
}
: onChange;

return (
<AntdSelect<VT>
dropdownMatchSelectWidth={dropdownMatchSelectWidth}
showSearch={showSearch}
onSearch={handleSearch}
onChange={handleChange}
value={value}
{...props}
css={{
minWidth,
Expand All @@ -74,7 +87,12 @@ export default function Select<VT extends string | number>({
<Option value={val}>{label}</Option>
))}
{children}
{searchValue && searchValueNotFound && (
{value && !optionsHasValue && (
<Option key={value} value={value}>
{value}
</Option>
)}
{searchValue && !optionsHasSearchValue && (
<Option key={searchValue} value={searchValue}>
{/* Unfortunately AntD select does not support displaying different
label for option vs select value, so we can't use
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,98 +34,116 @@ export type SharedColumnConfigProp =
| 'columnWidth'
| 'fractionDigits'
| 'd3NumberFormat'
| 'd3SmallNumberFormat'
| 'd3TimeFormat'
| 'horizontalAlign'
| 'showCellBars';

/**
* All configurable column formatting properties.
*/
export const SHARED_COLUMN_CONFIG_PROPS = {
d3NumberFormat: {
controlType: 'Select',
label: t('D3 format'),
description: D3_FORMAT_DOCS,
options: D3_FORMAT_OPTIONS,
defaultValue: D3_FORMAT_OPTIONS[0][0],
creatable: true,
minWidth: '10em',
debounceDelay: 400,
} as ControlFormItemSpec<'Select'>,
const d3NumberFormat: ControlFormItemSpec<'Select'> = {
controlType: 'Select',
label: t('D3 format'),
description: D3_FORMAT_DOCS,
options: D3_FORMAT_OPTIONS,
defaultValue: D3_FORMAT_OPTIONS[0][0],
creatable: true,
minWidth: '14em',
debounceDelay: 500,
};

d3TimeFormat: {
controlType: 'Select',
label: t('D3 format'),
description: D3_TIME_FORMAT_DOCS,
options: D3_TIME_FORMAT_OPTIONS,
defaultValue: D3_TIME_FORMAT_OPTIONS[0][0],
creatable: true,
minWidth: '10em',
debounceDelay: 400,
} as ControlFormItemSpec<'Select'>,
const d3TimeFormat: ControlFormItemSpec<'Select'> = {
controlType: 'Select',
label: t('D3 format'),
description: D3_TIME_FORMAT_DOCS,
options: D3_TIME_FORMAT_OPTIONS,
defaultValue: D3_TIME_FORMAT_OPTIONS[0][0],
creatable: true,
minWidth: '10em',
debounceDelay: 500,
};

fractionDigits: {
controlType: 'Slider',
label: t('Fraction digits'),
description: t('Number of decimal digits to round numbers to'),
min: 0,
step: 1,
max: 100,
defaultValue: 100,
} as ControlFormItemSpec<'Slider'>,
const fractionDigits: ControlFormItemSpec<'Slider'> = {
controlType: 'Slider',
label: t('Fraction digits'),
description: t('Number of decimal digits to round numbers to'),
min: 0,
step: 1,
max: 100,
defaultValue: 100,
};

columnWidth: {
controlType: 'InputNumber',
label: t('Width'),
description: t(
'Default column width in pixels, may still be restricted by the shortest/longest word in the column',
),
width: 120,
placeholder: 'auto',
debounceDelay: 400,
validators: [validateNumber],
} as ControlFormItemSpec<'InputNumber'>,
const columnWidth: ControlFormItemSpec<'InputNumber'> = {
controlType: 'InputNumber',
label: t('Width'),
description: t(
'Default column width in pixels, may still be restricted by the shortest/longest word in the column',
),
width: 120,
placeholder: 'auto',
debounceDelay: 400,
validators: [validateNumber],
};

horizontalAlign: {
controlType: 'RadioButtonControl',
label: t('Text align'),
description: t('Horizontal alignment'),
width: 130,
debounceDelay: 50,
defaultValue: 'left',
options: [
['left', <FaAlignLeft title={t('Left')} />],
['center', <FaAlignCenter title={t('Center')} />],
['right', <FaAlignRight title={t('Right')} />],
],
} as ControlFormItemSpec<'RadioButtonControl'> & {
value: 'left' | 'right' | 'center';
defaultValue: 'left' | 'right' | 'center';
},
const horizontalAlign: ControlFormItemSpec<'RadioButtonControl'> & {
value?: 'left' | 'right' | 'center';
defaultValue?: 'left' | 'right' | 'center';
} = {
controlType: 'RadioButtonControl',
label: t('Text align'),
description: t('Horizontal alignment'),
width: 130,
debounceDelay: 50,
defaultValue: 'left',
options: [
['left', <FaAlignLeft title={t('Left')} />],
['center', <FaAlignCenter title={t('Center')} />],
['right', <FaAlignRight title={t('Right')} />],
],
};

const showCellBars: ControlFormItemSpec<'Checkbox'> = {
controlType: 'Checkbox',
label: t('Show cell bars'),
description: t('Whether to display a bar chart background in table columns'),
defaultValue: true,
debounceDelay: 200,
};

showCellBars: {
controlType: 'Checkbox',
label: t('Show cell bars'),
description: t('Whether to display a bar chart background in table columns'),
defaultValue: true,
debounceDelay: 200,
} as ControlFormItemSpec<'Checkbox'>,
const alignPositiveNegative: ControlFormItemSpec<'Checkbox'> = {
controlType: 'Checkbox',
label: t('Align +/-'),
description: t('Whether to align positive and negative values in cell bar chart at 0'),
defaultValue: false,
debounceDelay: 200,
};

alignPositiveNegative: {
controlType: 'Checkbox',
label: t('Align +/-'),
description: t('Whether to align positive and negative values in cell bar chart at 0'),
defaultValue: false,
debounceDelay: 200,
} as ControlFormItemSpec<'Checkbox'>,
const colorPositiveNegative: ControlFormItemSpec<'Checkbox'> = {
controlType: 'Checkbox',
label: t('Color +/-'),
description: t('Whether to colorize numeric values by if they are positive or negative'),
defaultValue: false,
debounceDelay: 200,
};

colorPositiveNegative: {
controlType: 'Checkbox',
label: t('Color +/-'),
description: t('Whether to colorize numeric values by if they are positive or negative'),
defaultValue: false,
debounceDelay: 200,
} as ControlFormItemSpec<'Checkbox'>,
/**
* All configurable column formatting properties.
*/
export const SHARED_COLUMN_CONFIG_PROPS = {
d3NumberFormat,
d3SmallNumberFormat: {
...d3NumberFormat,
label: t('Small number format'),
description: t(
'D3 number format for numbers between -1.0 and 1.0, ' +
'useful when you want to have different siginificant digits for small and large numbers',
),
},
d3TimeFormat,
fractionDigits,
columnWidth,
horizontalAlign,
showCellBars,
alignPositiveNegative,
colorPositiveNegative,
};

export type SharedColumnConfig = {
Expand All @@ -139,7 +157,7 @@ export const DEFAULT_CONFIG_FORM_LAYOUT: ColumnConfigFormLayout = {
[GenericDataType.NUMERIC]: [
['columnWidth', { name: 'horizontalAlign', override: { defaultValue: 'right' } }],
['d3NumberFormat'],
['fractionDigits'],
['d3SmallNumberFormat'],
['alignPositiveNegative', 'colorPositiveNegative'],
['showCellBars'],
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export const basic = ({ width, height }) => (
}}
width={width}
height={height}
queriesData={[{ data: basicData }]}
queriesData={[basicData]}
formData={basicFormData}
/>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,28 +16,38 @@
* specific language governing permissions and limitations
* under the License.
*/
import { TableChartProps } from '@superset-ui/plugin-chart-table/src';
import { ChartDataResponseResult, GenericDataType } from '@superset-ui/core/src';
import { TableChartFormData, TableChartProps } from '@superset-ui/plugin-chart-table/src';
// @ts-ignore
// eslint-disable-next-line import/extensions
import birthNamesJson from './birthNames.json';

export const birthNames = (birthNamesJson as unknown) as TableChartProps;
export const basicFormData = {
alignPn: false,
colorPn: false,
includeSearch: false,

export const basicFormData: TableChartFormData = {
datasource: '1__table',
viz_type: 'table',
align_pn: false,
color_pn: false,
include_search: true,
metrics: ['sum__num', 'MAX(ds)'],
orderDesc: true,
pageLength: 0,
percentMetrics: null,
showCellBars: true,
tableFilter: false,
tableTimestampFormat: 'smart_date',
timeseriesLimitMetric: null,
order_desc: true,
page_length: 0,
percent_metrics: null,
show_cell_bars: true,
table_filter: false,
table_timestamp_format: 'smart_date',
};
export const basicData = {
columns: ['name', 'sum__num', 'MAX(ds)', 'Abc.com'],
records: [

export const basicData: Partial<ChartDataResponseResult> = {
colnames: ['name', 'sum__num', 'MAX(ds)', 'Abc.com'],
coltypes: [
GenericDataType.STRING,
GenericDataType.NUMERIC,
GenericDataType.TEMPORAL,
GenericDataType.STRING,
],
data: [
{
name: 'Michael',
sum__num: 2467063,
Expand Down

0 comments on commit 090e3b1

Please sign in to comment.