From 58cc2e34d68cdf9691e840876a93bb722373c53c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Fri, 14 Dec 2018 12:38:36 +0100 Subject: [PATCH] User picker using common select componnet --- .../components/Picker/NoOptionsMessage.tsx | 12 +-- public/app/core/components/Picker/Select.tsx | 87 +++++++++++++++++-- .../app/core/components/Picker/UserPicker.tsx | 27 +++--- public/app/features/panel/panel_header.ts | 4 +- 4 files changed, 100 insertions(+), 30 deletions(-) diff --git a/public/app/core/components/Picker/NoOptionsMessage.tsx b/public/app/core/components/Picker/NoOptionsMessage.tsx index 1d2ad4a179e..3626684df22 100644 --- a/public/app/core/components/Picker/NoOptionsMessage.tsx +++ b/public/app/core/components/Picker/NoOptionsMessage.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React from 'react'; import { components } from 'react-select'; import { OptionProps } from 'react-select/lib/components/Option'; @@ -6,13 +6,15 @@ export interface Props { children: Element; } -export const PickerOption = (props: OptionProps) => { - const { children, className } = props; +export const NoOptionsMessage = (props: OptionProps) => { + const { children } = props; return ( -
{children}
+
+
{children}
+
); }; -export default PickerOption; +export default NoOptionsMessage; diff --git a/public/app/core/components/Picker/Select.tsx b/public/app/core/components/Picker/Select.tsx index 40ee1af2148..5b7cad5b921 100644 --- a/public/app/core/components/Picker/Select.tsx +++ b/public/app/core/components/Picker/Select.tsx @@ -2,10 +2,12 @@ import classNames from 'classnames'; import React, { PureComponent } from 'react'; import { default as ReactSelect } from 'react-select'; +import { default as ReactAsyncSelect } from 'react-select/lib/Async'; // Components -import DescriptionOption from './DescriptionOption'; +import { Option, SingleValue } from './PickerOption'; import IndicatorsContainer from './IndicatorsContainer'; +import NoOptionsMessage from './NoOptionsMessage'; import ResetStyles from './ResetStyles'; export interface SelectOptionItem { @@ -16,20 +18,31 @@ export interface SelectOptionItem { [key: string]: any; } -interface Props { +interface CommonProps { defaultValue?: any; getOptionLabel?: (item: SelectOptionItem) => string; getOptionValue?: (item: SelectOptionItem) => string; onChange: (item: SelectOptionItem) => {} | void; - options: SelectOptionItem[]; placeholder?: string; width?: number; - value: SelectOptionItem; + value?: SelectOptionItem; className?: string; components: object; } -export class Select extends PureComponent { +interface SelectProps { + options: SelectOptionItem[]; +} + +interface AsyncProps { + defaultOptions: boolean; + loadOptions: (query: string) => Promise; + isLoading: boolean; + loadingMessage?: () => string; + noOptionsMessage?: () => string; +} + +export class Select extends PureComponent { static defaultProps = { width: null, className: '', @@ -61,7 +74,8 @@ export class Select extends PureComponent { classNamePrefix="gf-form-select-box" className={selectClassNames} components={{ - Option: DescriptionOption, + Option, + SingleValue, IndicatorsContainer, }} defaultValue={defaultValue} @@ -79,4 +93,65 @@ export class Select extends PureComponent { } } +export class AsyncSelect extends PureComponent { + static defaultProps = { + width: null, + className: '', + components: {}, + loadingMessage: () => 'Loading...', + }; + + render() { + const { + defaultValue, + getOptionLabel, + getOptionValue, + onChange, + placeholder, + width, + value, + className, + loadOptions, + defaultOptions, + isLoading, + loadingMessage, + noOptionsMessage, + } = this.props; + + let widthClass = ''; + if (width) { + widthClass = 'width-' + width; + } + + const selectClassNames = classNames('gf-form-input', 'gf-form-input--form-dropdown', widthClass, className); + + return ( + + ); + } +} + export default Select; diff --git a/public/app/core/components/Picker/UserPicker.tsx b/public/app/core/components/Picker/UserPicker.tsx index 01dbb1fd3ea..97bdc230173 100644 --- a/public/app/core/components/Picker/UserPicker.tsx +++ b/public/app/core/components/Picker/UserPicker.tsx @@ -1,12 +1,15 @@ +// Libraries import React, { Component } from 'react'; -import AsyncSelect from 'react-select/lib/Async'; -import PickerOption from './PickerOption'; + +// Components +import { AsyncSelect } from 'app/core/components/Picker/Select'; + +// Utils & Services import { debounce } from 'lodash'; import { getBackendSrv } from 'app/core/services/backend_srv'; + +// Types import { User } from 'app/types'; -import ResetStyles from './ResetStyles'; -import IndicatorsContainer from './IndicatorsContainer'; -import NoOptionsMessage from './NoOptionsMessage'; export interface Props { onSelected: (user: User) => void; @@ -40,6 +43,7 @@ export class UserPicker extends Component { .then(result => { return result.map(user => ({ id: user.userId, + value: user.userId, label: user.login === user.email ? user.login : `${user.login} - ${user.email}`, imgUrl: user.avatarUrl, login: user.login, @@ -57,24 +61,13 @@ export class UserPicker extends Component { return (
'Loading...'} noOptionsMessage={() => 'No users found'} - getOptionValue={i => i.id} - getOptionLabel={i => i.label} />
); diff --git a/public/app/features/panel/panel_header.ts b/public/app/features/panel/panel_header.ts index 1d29d04ad98..6a0f81a4c33 100644 --- a/public/app/features/panel/panel_header.ts +++ b/public/app/features/panel/panel_header.ts @@ -111,11 +111,11 @@ function panelHeader($compile) { */ function togglePanelStackPosition() { const menuOpenClass = 'dropdown-menu-open'; - const panelGridClass = '.react-grid-item.panel'; + const panelGridClass = '.react-grid-item'; let panelElem = elem .find('[data-toggle=dropdown]') - .parentsUntil('.panel') + .parentsUntil(panelGridClass) .parent(); const menuElem = elem.find('[data-toggle=dropdown]').parent(); panelElem = panelElem && panelElem.length ? panelElem[0] : undefined;