mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Merge pull request #14817 from grafana/grafana-ui/select
Migrate Select components to @grafana/ui
This commit is contained in:
commit
bc78c8d56e
@ -1,7 +1,10 @@
|
||||
import React from 'react';
|
||||
|
||||
// Ignoring because I couldn't get @types/react-select work wih Torkel's fork
|
||||
// @ts-ignore
|
||||
import { components } from '@torkelo/react-select';
|
||||
|
||||
export const IndicatorsContainer = props => {
|
||||
export const IndicatorsContainer = (props: any) => {
|
||||
const isOpen = props.selectProps.menuIsOpen;
|
||||
return (
|
||||
<components.IndicatorsContainer {...props}>
|
@ -1,5 +1,9 @@
|
||||
import React from 'react';
|
||||
|
||||
// Ignoring because I couldn't get @types/react-select work wih Torkel's fork
|
||||
// @ts-ignore
|
||||
import { components } from '@torkelo/react-select';
|
||||
// @ts-ignore
|
||||
import { OptionProps } from '@torkelo/react-select/lib/components/Option';
|
||||
|
||||
export interface Props {
|
@ -1,16 +1,21 @@
|
||||
// Libraries
|
||||
import classNames from 'classnames';
|
||||
import React, { PureComponent } from 'react';
|
||||
|
||||
// Ignoring because I couldn't get @types/react-select work wih Torkel's fork
|
||||
// @ts-ignore
|
||||
import { default as ReactSelect } from '@torkelo/react-select';
|
||||
// @ts-ignore
|
||||
import { default as ReactAsyncSelect } from '@torkelo/react-select/lib/Async';
|
||||
// @ts-ignore
|
||||
import { components } from '@torkelo/react-select';
|
||||
|
||||
// Components
|
||||
import { Option, SingleValue } from './PickerOption';
|
||||
import OptionGroup from './OptionGroup';
|
||||
import { SelectOption, SingleValue } from './SelectOption';
|
||||
import SelectOptionGroup from './SelectOptionGroup';
|
||||
import IndicatorsContainer from './IndicatorsContainer';
|
||||
import NoOptionsMessage from './NoOptionsMessage';
|
||||
import ResetStyles from './ResetStyles';
|
||||
import resetSelectStyles from './resetSelectStyles';
|
||||
import { CustomScrollbar } from '@grafana/ui';
|
||||
|
||||
export interface SelectOptionItem {
|
||||
@ -53,7 +58,7 @@ interface AsyncProps {
|
||||
loadingMessage?: () => string;
|
||||
}
|
||||
|
||||
export const MenuList = props => {
|
||||
export const MenuList = (props: any) => {
|
||||
return (
|
||||
<components.MenuList {...props}>
|
||||
<CustomScrollbar autoHide={false}>{props.children}</CustomScrollbar>
|
||||
@ -112,11 +117,11 @@ export class Select extends PureComponent<CommonProps & SelectProps> {
|
||||
classNamePrefix="gf-form-select-box"
|
||||
className={selectClassNames}
|
||||
components={{
|
||||
Option,
|
||||
Option: SelectOption,
|
||||
SingleValue,
|
||||
IndicatorsContainer,
|
||||
MenuList,
|
||||
Group: OptionGroup,
|
||||
Group: SelectOptionGroup,
|
||||
}}
|
||||
defaultValue={defaultValue}
|
||||
value={value}
|
||||
@ -127,7 +132,7 @@ export class Select extends PureComponent<CommonProps & SelectProps> {
|
||||
onChange={onChange}
|
||||
options={options}
|
||||
placeholder={placeholder || 'Choose'}
|
||||
styles={ResetStyles}
|
||||
styles={resetSelectStyles()}
|
||||
isDisabled={isDisabled}
|
||||
isLoading={isLoading}
|
||||
isClearable={isClearable}
|
||||
@ -212,7 +217,7 @@ export class AsyncSelect extends PureComponent<CommonProps & AsyncProps> {
|
||||
isLoading={isLoading}
|
||||
defaultOptions={defaultOptions}
|
||||
placeholder={placeholder || 'Choose'}
|
||||
styles={ResetStyles}
|
||||
styles={resetSelectStyles()}
|
||||
loadingMessage={loadingMessage}
|
||||
noOptionsMessage={noOptionsMessage}
|
||||
isDisabled={isDisabled}
|
@ -1,11 +1,11 @@
|
||||
import React from 'react';
|
||||
import renderer from 'react-test-renderer';
|
||||
import PickerOption from './PickerOption';
|
||||
import SelectOption from './SelectOption';
|
||||
import { OptionProps } from 'react-select/lib/components/Option';
|
||||
|
||||
const model = {
|
||||
const model: OptionProps<any> = {
|
||||
cx: jest.fn(),
|
||||
clearValue: jest.fn(),
|
||||
onSelect: jest.fn(),
|
||||
getStyles: jest.fn(),
|
||||
getValue: jest.fn(),
|
||||
hasValue: true,
|
||||
@ -18,21 +18,31 @@ const model = {
|
||||
isFocused: false,
|
||||
isSelected: false,
|
||||
innerRef: null,
|
||||
innerProps: null,
|
||||
label: 'Option label',
|
||||
type: null,
|
||||
children: 'Model title',
|
||||
data: {
|
||||
title: 'Model title',
|
||||
imgUrl: 'url/to/avatar',
|
||||
label: 'User picker label',
|
||||
innerProps: {
|
||||
id: '',
|
||||
key: '',
|
||||
onClick: jest.fn(),
|
||||
onMouseOver: jest.fn(),
|
||||
tabIndex: 1,
|
||||
},
|
||||
label: 'Option label',
|
||||
type: 'option',
|
||||
children: 'Model title',
|
||||
className: 'class-for-user-picker',
|
||||
};
|
||||
|
||||
describe('PickerOption', () => {
|
||||
describe('SelectOption', () => {
|
||||
it('renders correctly', () => {
|
||||
const tree = renderer.create(<PickerOption {...model} />).toJSON();
|
||||
const tree = renderer
|
||||
.create(
|
||||
<SelectOption
|
||||
{...model}
|
||||
data={{
|
||||
imgUrl: 'url/to/avatar',
|
||||
}}
|
||||
/>
|
||||
)
|
||||
.toJSON();
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
});
|
@ -1,4 +1,7 @@
|
||||
import React from 'react';
|
||||
|
||||
// Ignoring because I couldn't get @types/react-select work wih Torkel's fork
|
||||
// @ts-ignore
|
||||
import { components } from '@torkelo/react-select';
|
||||
import { OptionProps } from 'react-select/lib/components/Option';
|
||||
|
||||
@ -10,7 +13,7 @@ interface ExtendedOptionProps extends OptionProps<any> {
|
||||
};
|
||||
}
|
||||
|
||||
export const Option = (props: ExtendedOptionProps) => {
|
||||
export const SelectOption = (props: ExtendedOptionProps) => {
|
||||
const { children, isSelected, data } = props;
|
||||
|
||||
return (
|
||||
@ -28,7 +31,7 @@ export const Option = (props: ExtendedOptionProps) => {
|
||||
};
|
||||
|
||||
// was not able to type this without typescript error
|
||||
export const SingleValue = props => {
|
||||
export const SingleValue = (props: any) => {
|
||||
const { children, data } = props;
|
||||
|
||||
return (
|
||||
@ -41,4 +44,4 @@ export const SingleValue = props => {
|
||||
);
|
||||
};
|
||||
|
||||
export default Option;
|
||||
export default SelectOption;
|
@ -9,7 +9,7 @@ interface State {
|
||||
expanded: boolean;
|
||||
}
|
||||
|
||||
export default class OptionGroup extends PureComponent<ExtendedGroupProps, State> {
|
||||
export default class SelectOptionGroup extends PureComponent<ExtendedGroupProps, State> {
|
||||
state = {
|
||||
expanded: false,
|
||||
};
|
||||
@ -24,7 +24,7 @@ export default class OptionGroup extends PureComponent<ExtendedGroupProps, State
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate(nextProps) {
|
||||
componentDidUpdate(nextProps: ExtendedGroupProps) {
|
||||
if (nextProps.selectProps.inputValue !== '') {
|
||||
this.setState({ expanded: true });
|
||||
}
|
@ -1,7 +1,12 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`PickerOption renders correctly 1`] = `
|
||||
<div>
|
||||
exports[`SelectOption renders correctly 1`] = `
|
||||
<div
|
||||
id=""
|
||||
onClick={[MockFunction]}
|
||||
onMouseOver={[MockFunction]}
|
||||
tabIndex={1}
|
||||
>
|
||||
<div
|
||||
className="gf-form-select-box__desc-option"
|
||||
>
|
@ -0,0 +1,27 @@
|
||||
export default function resetSelectStyles() {
|
||||
return {
|
||||
clearIndicator: () => ({}),
|
||||
container: () => ({}),
|
||||
control: () => ({}),
|
||||
dropdownIndicator: () => ({}),
|
||||
group: () => ({}),
|
||||
groupHeading: () => ({}),
|
||||
indicatorsContainer: () => ({}),
|
||||
indicatorSeparator: () => ({}),
|
||||
input: () => ({}),
|
||||
loadingIndicator: () => ({}),
|
||||
loadingMessage: () => ({}),
|
||||
menu: () => ({}),
|
||||
menuList: ({ maxHeight }: { maxHeight: number }) => ({
|
||||
maxHeight,
|
||||
}),
|
||||
multiValue: () => ({}),
|
||||
multiValueLabel: () => ({}),
|
||||
multiValueRemove: () => ({}),
|
||||
noOptionsMessage: () => ({}),
|
||||
option: () => ({}),
|
||||
placeholder: () => ({}),
|
||||
singleValue: () => ({}),
|
||||
valueContainer: () => ({}),
|
||||
};
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
@import 'CustomScrollbar/CustomScrollbar';
|
||||
@import 'DeleteButton/DeleteButton';
|
||||
@import 'Tooltip/Tooltip';
|
||||
@import 'Select/Select';
|
||||
|
@ -2,6 +2,13 @@ export { DeleteButton } from './DeleteButton/DeleteButton';
|
||||
export { Tooltip } from './Tooltip/Tooltip';
|
||||
export { Portal } from './Portal/Portal';
|
||||
export { CustomScrollbar } from './CustomScrollbar/CustomScrollbar';
|
||||
|
||||
// Select
|
||||
export { Select, AsyncSelect, SelectOptionItem } from './Select/Select';
|
||||
export { IndicatorsContainer } from './Select/IndicatorsContainer';
|
||||
export { NoOptionsMessage } from './Select/NoOptionsMessage';
|
||||
export { default as resetSelectStyles } from './Select/resetSelectStyles';
|
||||
|
||||
export { LoadingPlaceholder } from './LoadingPlaceholder/LoadingPlaceholder';
|
||||
export { ColorPicker } from './ColorPicker/ColorPicker';
|
||||
export { SeriesColorPickerPopover } from './ColorPicker/SeriesColorPickerPopover';
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React, { Component } from 'react';
|
||||
import { UserPicker } from 'app/core/components/Select/UserPicker';
|
||||
import { TeamPicker, Team } from 'app/core/components/Select/TeamPicker';
|
||||
import { Select, SelectOptionItem } from 'app/core/components/Select/Select';
|
||||
import { Select, SelectOptionItem } from '@grafana/ui';
|
||||
import { User } from 'app/types';
|
||||
import {
|
||||
dashboardPermissionLevels,
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React, { Component } from 'react';
|
||||
import Select from 'app/core/components/Select/Select';
|
||||
import { Select } from '@grafana/ui';
|
||||
import { dashboardPermissionLevels } from 'app/types/acl';
|
||||
|
||||
export interface Props {
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import { Select } from 'app/core/components/Select/Select';
|
||||
import { Select } from '@grafana/ui';
|
||||
import { dashboardPermissionLevels, DashboardAcl, PermissionLevel } from 'app/types/acl';
|
||||
import { FolderInfo } from 'app/types';
|
||||
|
||||
|
@ -3,7 +3,7 @@ import React, { PureComponent } from 'react';
|
||||
import _ from 'lodash';
|
||||
|
||||
// Components
|
||||
import Select from './Select';
|
||||
import { Select } from '@grafana/ui';
|
||||
|
||||
// Types
|
||||
import { DataSourceSelectItem } from 'app/types';
|
||||
|
@ -1,25 +0,0 @@
|
||||
export default {
|
||||
clearIndicator: () => ({}),
|
||||
container: () => ({}),
|
||||
control: () => ({}),
|
||||
dropdownIndicator: () => ({}),
|
||||
group: () => ({}),
|
||||
groupHeading: () => ({}),
|
||||
indicatorsContainer: () => ({}),
|
||||
indicatorSeparator: () => ({}),
|
||||
input: () => ({}),
|
||||
loadingIndicator: () => ({}),
|
||||
loadingMessage: () => ({}),
|
||||
menu: () => ({}),
|
||||
menuList: ({ maxHeight }: { maxHeight: number }) => ({
|
||||
maxHeight,
|
||||
}),
|
||||
multiValue: () => ({}),
|
||||
multiValueLabel: () => ({}),
|
||||
multiValueRemove: () => ({}),
|
||||
noOptionsMessage: () => ({}),
|
||||
option: () => ({}),
|
||||
placeholder: () => ({}),
|
||||
singleValue: () => ({}),
|
||||
valueContainer: () => ({}),
|
||||
};
|
@ -1,6 +1,6 @@
|
||||
import React, { Component } from 'react';
|
||||
import _ from 'lodash';
|
||||
import { AsyncSelect } from './Select';
|
||||
import { AsyncSelect } from '@grafana/ui';
|
||||
import { debounce } from 'lodash';
|
||||
import { getBackendSrv } from 'app/core/services/backend_srv';
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import Select from './Select';
|
||||
import { Select } from '@grafana/ui';
|
||||
import kbn from 'app/core/utils/kbn';
|
||||
|
||||
interface Props {
|
||||
|
@ -3,7 +3,7 @@ import React, { Component } from 'react';
|
||||
import _ from 'lodash';
|
||||
|
||||
// Components
|
||||
import { AsyncSelect } from './Select';
|
||||
import { AsyncSelect } from '@grafana/ui';
|
||||
|
||||
// Utils & Services
|
||||
import { debounce } from 'lodash';
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
|
||||
import { Label } from 'app/core/components/Label/Label';
|
||||
import Select from 'app/core/components/Select/Select';
|
||||
import { Select } from '@grafana/ui';
|
||||
import { getBackendSrv, BackendSrv } from 'app/core/services/backend_srv';
|
||||
|
||||
import { DashboardSearchHit } from 'app/types';
|
||||
|
@ -1,12 +1,10 @@
|
||||
import React from 'react';
|
||||
import { NoOptionsMessage, IndicatorsContainer, resetSelectStyles } from '@grafana/ui';
|
||||
import AsyncSelect from '@torkelo/react-select/lib/Async';
|
||||
|
||||
import { TagOption } from './TagOption';
|
||||
import { TagBadge } from './TagBadge';
|
||||
import IndicatorsContainer from 'app/core/components/Select/IndicatorsContainer';
|
||||
import NoOptionsMessage from 'app/core/components/Select/NoOptionsMessage';
|
||||
import { components } from '@torkelo/react-select';
|
||||
import ResetStyles from 'app/core/components/Select/ResetStyles';
|
||||
|
||||
export interface Props {
|
||||
tags: string[];
|
||||
@ -51,7 +49,7 @@ export class TagFilter extends React.Component<Props, any> {
|
||||
getOptionValue: i => i.value,
|
||||
getOptionLabel: i => i.label,
|
||||
value: tags,
|
||||
styles: ResetStyles,
|
||||
styles: resetSelectStyles(),
|
||||
filterOption: (option, searchQuery) => {
|
||||
const regex = RegExp(searchQuery, 'i');
|
||||
return regex.test(option.value);
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import { Label } from 'app/core/components/Label/Label';
|
||||
import { Select } from 'app/core/components/Select/Select';
|
||||
import { Select } from '@grafana/ui';
|
||||
import { MappingType, RangeMap, ValueMap } from 'app/types';
|
||||
|
||||
interface Props {
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import { Label } from 'app/core/components/Label/Label';
|
||||
import Select from 'app/core/components/Select/Select';
|
||||
import { Select} from '@grafana/ui';
|
||||
import UnitPicker from 'app/core/components/Select/UnitPicker';
|
||||
import { PanelOptionsProps } from '@grafana/ui';
|
||||
import { Options } from './types';
|
||||
|
@ -1,4 +1,4 @@
|
||||
// DEPENDENCIES
|
||||
// DEPENDENCIES
|
||||
@import '../../node_modules/react-table/react-table.css';
|
||||
|
||||
// VENDOR
|
||||
@ -38,9 +38,6 @@
|
||||
@import 'layout/lists';
|
||||
@import 'layout/page';
|
||||
|
||||
// LOAD @grafana/ui components
|
||||
@import '../../packages/grafana-ui/src/index';
|
||||
|
||||
// COMPONENTS
|
||||
@import 'components/scrollbar';
|
||||
@import 'components/cards';
|
||||
@ -97,7 +94,6 @@
|
||||
@import 'components/page_header';
|
||||
@import 'components/dashboard_settings';
|
||||
@import 'components/empty_list_cta';
|
||||
@import 'components/form_select_box';
|
||||
@import 'components/panel_editor';
|
||||
@import 'components/toolbar';
|
||||
@import 'components/add_data_source.scss';
|
||||
@ -107,6 +103,9 @@
|
||||
@import 'components/value-mappings';
|
||||
@import 'components/popover-box';
|
||||
|
||||
// LOAD @grafana/ui components
|
||||
@import '../../packages/grafana-ui/src/index';
|
||||
|
||||
// PAGES
|
||||
@import 'pages/login';
|
||||
@import 'pages/dashboard';
|
||||
|
@ -1105,7 +1105,7 @@
|
||||
dependencies:
|
||||
"@types/react" "*"
|
||||
|
||||
"@types/react@*", "@types/react@^16.1.0", "@types/react@^16.7.6":
|
||||
"@types/react@*", "@types/react@16.7.6", "@types/react@^16.1.0", "@types/react@^16.7.6":
|
||||
version "16.7.6"
|
||||
resolved "https://registry.yarnpkg.com/@types/react/-/react-16.7.6.tgz#80e4bab0d0731ad3ae51f320c4b08bdca5f03040"
|
||||
integrity sha512-QBUfzftr/8eg/q3ZRgf/GaDP6rTYc7ZNem+g4oZM38C9vXyV8AWRWaTQuW5yCoZTsfHrN7b3DeEiUnqH9SrnpA==
|
||||
@ -3185,7 +3185,7 @@ caniuse-api@^1.5.2:
|
||||
lodash.memoize "^4.1.2"
|
||||
lodash.uniq "^4.5.0"
|
||||
|
||||
caniuse-db@^1.0.30000529, caniuse-db@^1.0.30000634, caniuse-db@^1.0.30000639:
|
||||
caniuse-db@1.0.30000772, caniuse-db@^1.0.30000529, caniuse-db@^1.0.30000634, caniuse-db@^1.0.30000639:
|
||||
version "1.0.30000772"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000772.tgz#51aae891768286eade4a3d8319ea76d6a01b512b"
|
||||
integrity sha1-UarokXaChureSj2DGep21qAbUSs=
|
||||
|
Loading…
Reference in New Issue
Block a user