From 19e824006adc283b050485ffcfb2f5369b16084c Mon Sep 17 00:00:00 2001 From: Dominik Prokop Date: Tue, 23 Apr 2019 20:44:16 +0200 Subject: [PATCH] Refactor: Make SelectOptionItem a generic type to enable select value typing (#16718) * Make SelectOptionItem a generic type to enable select value typing * TS ignores added because of optional value on Select items (it's no longer any) --- .../RefreshPicker/RefreshPicker.tsx | 5 ++-- .../components/Select/ButtonSelect.story.tsx | 6 ++--- .../src/components/Select/ButtonSelect.tsx | 12 ++++----- .../src/components/Select/Select.tsx | 26 +++++++++---------- .../SingleStatValueEditor.tsx | 17 ++++++------ .../components/StatsPicker/StatsPicker.tsx | 6 ++--- .../src/components/TimePicker/TimePicker.tsx | 5 +++- .../ValueMappingsEditor/MappingRow.tsx | 1 + packages/grafana-ui/src/utils/string.ts | 2 +- .../PermissionList/AddPermission.tsx | 2 +- .../components/Select/DataSourcePicker.tsx | 2 +- .../core/components/Select/MetricSelect.tsx | 4 +-- .../app/features/teams/TeamMemberRow.test.tsx | 2 +- public/app/features/teams/TeamMemberRow.tsx | 4 +-- .../datasource/input/InputQueryEditor.tsx | 2 +- .../stackdriver/components/Alignments.tsx | 2 +- .../stackdriver/components/QueryEditor.tsx | 2 +- .../datasource/testdata/QueryEditor.tsx | 2 +- .../panel/bargauge/BarGaugePanelEditor.tsx | 2 +- public/app/plugins/panel/bargauge/types.ts | 4 +-- .../plugins/panel/gauge/GaugePanelEditor.tsx | 2 +- .../panel/piechart/PieChartPanelEditor.tsx | 2 +- .../panel/singlestat2/FontSizeEditor.tsx | 8 +++--- .../panel/singlestat2/SingleStatEditor.tsx | 2 +- .../plugins/panel/text2/TextPanelEditor.tsx | 7 ++--- public/app/plugins/panel/text2/types.ts | 3 ++- 26 files changed, 71 insertions(+), 61 deletions(-) diff --git a/packages/grafana-ui/src/components/RefreshPicker/RefreshPicker.tsx b/packages/grafana-ui/src/components/RefreshPicker/RefreshPicker.tsx index 666971af363..394b898e845 100644 --- a/packages/grafana-ui/src/components/RefreshPicker/RefreshPicker.tsx +++ b/packages/grafana-ui/src/components/RefreshPicker/RefreshPicker.tsx @@ -33,15 +33,16 @@ export class RefreshPicker extends PureComponent { return false; }; - intervalsToOptions = (intervals: string[] = defaultIntervals): SelectOptionItem[] => { + intervalsToOptions = (intervals: string[] = defaultIntervals): Array> => { const options = intervals.map(interval => ({ label: interval, value: interval })); options.unshift(offOption); return options; }; - onChangeSelect = (item: SelectOptionItem) => { + onChangeSelect = (item: SelectOptionItem) => { const { onIntervalChanged } = this.props; if (onIntervalChanged) { + // @ts-ignore onIntervalChanged(item.value); } }; diff --git a/packages/grafana-ui/src/components/Select/ButtonSelect.story.tsx b/packages/grafana-ui/src/components/Select/ButtonSelect.story.tsx index 0dc967eadb1..0e50be5b942 100644 --- a/packages/grafana-ui/src/components/Select/ButtonSelect.story.tsx +++ b/packages/grafana-ui/src/components/Select/ButtonSelect.story.tsx @@ -12,9 +12,9 @@ const ButtonSelectStories = storiesOf('UI/Select/ButtonSelect', module); ButtonSelectStories.addDecorator(withCenteredStory).addDecorator(withKnobs); ButtonSelectStories.add('default', () => { - const intialState: SelectOptionItem = { label: 'A label', value: 'A value' }; - const value = object('Selected Value:', intialState); - const options = object('Options:', [ + const intialState: SelectOptionItem = { label: 'A label', value: 'A value' }; + const value = object>('Selected Value:', intialState); + const options = object>>('Options:', [ intialState, { label: 'Another label', value: 'Another value' }, ]); diff --git a/packages/grafana-ui/src/components/Select/ButtonSelect.tsx b/packages/grafana-ui/src/components/Select/ButtonSelect.tsx index a6393428d73..5b079d0195f 100644 --- a/packages/grafana-ui/src/components/Select/ButtonSelect.tsx +++ b/packages/grafana-ui/src/components/Select/ButtonSelect.tsx @@ -27,23 +27,23 @@ const ButtonComponent = (buttonProps: ButtonComponentProps) => (props: any) => { ); }; -export interface Props { +export interface Props { className: string | undefined; - options: SelectOptionItem[]; - value: SelectOptionItem; + options: Array>; + value: SelectOptionItem; label?: string; iconClass?: string; components?: any; maxMenuHeight?: number; - onChange: (item: SelectOptionItem) => void; + onChange: (item: SelectOptionItem) => void; tooltipContent?: PopperContent; isMenuOpen?: boolean; onOpenMenu?: () => void; onCloseMenu?: () => void; } -export class ButtonSelect extends PureComponent { - onChange = (item: SelectOptionItem) => { +export class ButtonSelect extends PureComponent> { + onChange = (item: SelectOptionItem) => { const { onChange } = this.props; onChange(item); }; diff --git a/packages/grafana-ui/src/components/Select/Select.tsx b/packages/grafana-ui/src/components/Select/Select.tsx index b66aaa57089..e578b707db6 100644 --- a/packages/grafana-ui/src/components/Select/Select.tsx +++ b/packages/grafana-ui/src/components/Select/Select.tsx @@ -20,22 +20,22 @@ import { CustomScrollbar } from '../CustomScrollbar/CustomScrollbar'; import { PopperContent } from '@grafana/ui/src/components/Tooltip/PopperController'; import { Tooltip } from '@grafana/ui'; -export interface SelectOptionItem { +export interface SelectOptionItem { label?: string; - value?: any; + value?: T; imgUrl?: string; description?: string; [key: string]: any; } -export interface CommonProps { +export interface CommonProps { defaultValue?: any; - getOptionLabel?: (item: SelectOptionItem) => string; - getOptionValue?: (item: SelectOptionItem) => string; - onChange: (item: SelectOptionItem) => {} | void; + getOptionLabel?: (item: SelectOptionItem) => string; + getOptionValue?: (item: SelectOptionItem) => string; + onChange: (item: SelectOptionItem) => {} | void; placeholder?: string; width?: number; - value?: SelectOptionItem; + value?: SelectOptionItem; className?: string; isDisabled?: boolean; isSearchable?: boolean; @@ -55,13 +55,13 @@ export interface CommonProps { onCloseMenu?: () => void; } -export interface SelectProps { - options: SelectOptionItem[]; +export interface SelectProps { + options: Array>; } -interface AsyncProps { +interface AsyncProps { defaultOptions: boolean; - loadOptions: (query: string) => Promise; + loadOptions: (query: string) => Promise>>; loadingMessage?: () => string; } @@ -95,7 +95,7 @@ export const MenuList = (props: any) => { ); }; -export class Select extends PureComponent { +export class Select extends PureComponent & SelectProps> { static defaultProps = { width: null, className: '', @@ -201,7 +201,7 @@ export class Select extends PureComponent { } } -export class AsyncSelect extends PureComponent { +export class AsyncSelect extends PureComponent & AsyncProps> { static defaultProps = { width: null, className: '', diff --git a/packages/grafana-ui/src/components/SingleStatShared/SingleStatValueEditor.tsx b/packages/grafana-ui/src/components/SingleStatShared/SingleStatValueEditor.tsx index b08b7ce383d..e1ec6dee67e 100644 --- a/packages/grafana-ui/src/components/SingleStatShared/SingleStatValueEditor.tsx +++ b/packages/grafana-ui/src/components/SingleStatShared/SingleStatValueEditor.tsx @@ -18,39 +18,40 @@ import { SingleStatValueOptions } from './shared'; const labelWidth = 6; export interface Props { - options: SingleStatValueOptions; + value: SingleStatValueOptions; onChange: (valueOptions: SingleStatValueOptions) => void; } export class SingleStatValueEditor extends PureComponent { - onUnitChange = (unit: SelectOptionItem) => this.props.onChange({ ...this.props.options, unit: unit.value }); + // @ts-ignore + onUnitChange = (unit: SelectOptionItem) => this.props.onChange({ ...this.props.value, unit: unit.value }); onStatsChange = (stats: string[]) => { const stat = stats[0] || StatID.mean; - this.props.onChange({ ...this.props.options, stat }); + this.props.onChange({ ...this.props.value, stat }); }; onDecimalChange = (event: ChangeEvent) => { if (!isNaN(parseInt(event.target.value, 10))) { this.props.onChange({ - ...this.props.options, + ...this.props.value, decimals: parseInt(event.target.value, 10), }); } else { this.props.onChange({ - ...this.props.options, + ...this.props.value, decimals: null, }); } }; onPrefixChange = (event: ChangeEvent) => - this.props.onChange({ ...this.props.options, prefix: event.target.value }); + this.props.onChange({ ...this.props.value, prefix: event.target.value }); onSuffixChange = (event: ChangeEvent) => - this.props.onChange({ ...this.props.options, suffix: event.target.value }); + this.props.onChange({ ...this.props.value, suffix: event.target.value }); render() { - const { stat, unit, decimals, prefix, suffix } = this.props.options; + const { stat, unit, decimals, prefix, suffix } = this.props.value; let decimalsString = ''; if (decimals !== null && decimals !== undefined && Number.isFinite(decimals as number)) { diff --git a/packages/grafana-ui/src/components/StatsPicker/StatsPicker.tsx b/packages/grafana-ui/src/components/StatsPicker/StatsPicker.tsx index df45e299764..ffe232258b9 100644 --- a/packages/grafana-ui/src/components/StatsPicker/StatsPicker.tsx +++ b/packages/grafana-ui/src/components/StatsPicker/StatsPicker.tsx @@ -54,12 +54,12 @@ export class StatsPicker extends PureComponent { } }; - onSelectionChange = (item: SelectOptionItem) => { + onSelectionChange = (item: SelectOptionItem) => { const { onChange } = this.props; if (isArray(item)) { onChange(item.map(v => v.value)); } else { - onChange([item.value]); + onChange(item.value ? [item.value] : []); } }; @@ -73,7 +73,7 @@ export class StatsPicker extends PureComponent { }; }); - const value: SelectOptionItem[] = options.filter(option => stats.find(stat => option.value === stat)); + const value: Array> = options.filter(option => stats.find(stat => option.value === stat)); return (