Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
N
nexpie-grafana-theme
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Registry
Registry
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Kornkitt Poolsup
nexpie-grafana-theme
Commits
58cc2e34
Commit
58cc2e34
authored
Dec 14, 2018
by
Torkel Ödegaard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
User picker using common select componnet
parent
104292df
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
100 additions
and
30 deletions
+100
-30
public/app/core/components/Picker/NoOptionsMessage.tsx
+7
-5
public/app/core/components/Picker/Select.tsx
+81
-6
public/app/core/components/Picker/UserPicker.tsx
+10
-17
public/app/features/panel/panel_header.ts
+2
-2
No files found.
public/app/core/components/Picker/NoOptionsMessage.tsx
View file @
58cc2e34
import
React
from
'react'
;
import
React
from
'react'
;
import
{
components
}
from
'react-select'
;
import
{
components
}
from
'react-select'
;
import
{
OptionProps
}
from
'react-select/lib/components/Option'
;
import
{
OptionProps
}
from
'react-select/lib/components/Option'
;
...
@@ -6,13 +6,15 @@ export interface Props {
...
@@ -6,13 +6,15 @@ export interface Props {
children
:
Element
;
children
:
Element
;
}
}
export
const
PickerOption
=
(
props
:
OptionProps
<
any
>
)
=>
{
export
const
NoOptionsMessage
=
(
props
:
OptionProps
<
any
>
)
=>
{
const
{
children
,
className
}
=
props
;
const
{
children
}
=
props
;
return
(
return
(
<
components
.
Option
{
...
props
}
>
<
components
.
Option
{
...
props
}
>
<
div
className=
{
`description-picker-option__button btn btn-link ${className}`
}
>
{
children
}
</
div
>
<
div
className=
"gf-form-select-box__desc-option"
>
<
div
className=
"gf-form-select-box__desc-option__body"
>
{
children
}
</
div
>
</
div
>
</
components
.
Option
>
</
components
.
Option
>
);
);
};
};
export
default
PickerOption
;
export
default
NoOptionsMessage
;
public/app/core/components/Picker/Select.tsx
View file @
58cc2e34
...
@@ -2,10 +2,12 @@
...
@@ -2,10 +2,12 @@
import
classNames
from
'classnames'
;
import
classNames
from
'classnames'
;
import
React
,
{
PureComponent
}
from
'react'
;
import
React
,
{
PureComponent
}
from
'react'
;
import
{
default
as
ReactSelect
}
from
'react-select'
;
import
{
default
as
ReactSelect
}
from
'react-select'
;
import
{
default
as
ReactAsyncSelect
}
from
'react-select/lib/Async'
;
// Components
// Components
import
DescriptionOption
from
'./Description
Option'
;
import
{
Option
,
SingleValue
}
from
'./Picker
Option'
;
import
IndicatorsContainer
from
'./IndicatorsContainer'
;
import
IndicatorsContainer
from
'./IndicatorsContainer'
;
import
NoOptionsMessage
from
'./NoOptionsMessage'
;
import
ResetStyles
from
'./ResetStyles'
;
import
ResetStyles
from
'./ResetStyles'
;
export
interface
SelectOptionItem
{
export
interface
SelectOptionItem
{
...
@@ -16,20 +18,31 @@ export interface SelectOptionItem {
...
@@ -16,20 +18,31 @@ export interface SelectOptionItem {
[
key
:
string
]:
any
;
[
key
:
string
]:
any
;
}
}
interface
Props
{
interface
Common
Props
{
defaultValue
?:
any
;
defaultValue
?:
any
;
getOptionLabel
?:
(
item
:
SelectOptionItem
)
=>
string
;
getOptionLabel
?:
(
item
:
SelectOptionItem
)
=>
string
;
getOptionValue
?:
(
item
:
SelectOptionItem
)
=>
string
;
getOptionValue
?:
(
item
:
SelectOptionItem
)
=>
string
;
onChange
:
(
item
:
SelectOptionItem
)
=>
{}
|
void
;
onChange
:
(
item
:
SelectOptionItem
)
=>
{}
|
void
;
options
:
SelectOptionItem
[];
placeholder
?:
string
;
placeholder
?:
string
;
width
?:
number
;
width
?:
number
;
value
:
SelectOptionItem
;
value
?
:
SelectOptionItem
;
className
?:
string
;
className
?:
string
;
components
:
object
;
components
:
object
;
}
}
export
class
Select
extends
PureComponent
<
Props
>
{
interface
SelectProps
{
options
:
SelectOptionItem
[];
}
interface
AsyncProps
{
defaultOptions
:
boolean
;
loadOptions
:
(
query
:
string
)
=>
Promise
<
SelectOptionItem
[]
>
;
isLoading
:
boolean
;
loadingMessage
?:
()
=>
string
;
noOptionsMessage
?:
()
=>
string
;
}
export
class
Select
extends
PureComponent
<
CommonProps
&
SelectProps
>
{
static
defaultProps
=
{
static
defaultProps
=
{
width
:
null
,
width
:
null
,
className
:
''
,
className
:
''
,
...
@@ -61,7 +74,8 @@ export class Select extends PureComponent<Props> {
...
@@ -61,7 +74,8 @@ export class Select extends PureComponent<Props> {
classNamePrefix=
"gf-form-select-box"
classNamePrefix=
"gf-form-select-box"
className=
{
selectClassNames
}
className=
{
selectClassNames
}
components=
{
{
components=
{
{
Option
:
DescriptionOption
,
Option
,
SingleValue
,
IndicatorsContainer
,
IndicatorsContainer
,
}
}
}
}
defaultValue=
{
defaultValue
}
defaultValue=
{
defaultValue
}
...
@@ -79,4 +93,65 @@ export class Select extends PureComponent<Props> {
...
@@ -79,4 +93,65 @@ export class Select extends PureComponent<Props> {
}
}
}
}
export
class
AsyncSelect
extends
PureComponent
<
CommonProps
&
AsyncProps
>
{
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
(
<
ReactAsyncSelect
classNamePrefix=
"gf-form-select-box"
className=
{
selectClassNames
}
components=
{
{
Option
,
SingleValue
,
IndicatorsContainer
,
NoOptionsMessage
,
}
}
defaultValue=
{
defaultValue
}
value=
{
value
}
getOptionLabel=
{
getOptionLabel
}
getOptionValue=
{
getOptionValue
}
menuShouldScrollIntoView=
{
false
}
isSearchable=
{
false
}
onChange=
{
onChange
}
loadOptions=
{
loadOptions
}
isLoading=
{
isLoading
}
defaultOptions=
{
defaultOptions
}
placeholder=
{
placeholder
||
'Choose'
}
styles=
{
ResetStyles
}
loadingMessage=
{
loadingMessage
}
noOptionsMessage=
{
noOptionsMessage
}
/>
);
}
}
export
default
Select
;
export
default
Select
;
public/app/core/components/Picker/UserPicker.tsx
View file @
58cc2e34
// Libraries
import
React
,
{
Component
}
from
'react'
;
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
{
debounce
}
from
'lodash'
;
import
{
getBackendSrv
}
from
'app/core/services/backend_srv'
;
import
{
getBackendSrv
}
from
'app/core/services/backend_srv'
;
// Types
import
{
User
}
from
'app/types'
;
import
{
User
}
from
'app/types'
;
import
ResetStyles
from
'./ResetStyles'
;
import
IndicatorsContainer
from
'./IndicatorsContainer'
;
import
NoOptionsMessage
from
'./NoOptionsMessage'
;
export
interface
Props
{
export
interface
Props
{
onSelected
:
(
user
:
User
)
=>
void
;
onSelected
:
(
user
:
User
)
=>
void
;
...
@@ -40,6 +43,7 @@ export class UserPicker extends Component<Props, State> {
...
@@ -40,6 +43,7 @@ export class UserPicker extends Component<Props, State> {
.
then
(
result
=>
{
.
then
(
result
=>
{
return
result
.
map
(
user
=>
({
return
result
.
map
(
user
=>
({
id
:
user
.
userId
,
id
:
user
.
userId
,
value
:
user
.
userId
,
label
:
user
.
login
===
user
.
email
?
user
.
login
:
`
${
user
.
login
}
-
${
user
.
email
}
`
,
label
:
user
.
login
===
user
.
email
?
user
.
login
:
`
${
user
.
login
}
-
${
user
.
email
}
`
,
imgUrl
:
user
.
avatarUrl
,
imgUrl
:
user
.
avatarUrl
,
login
:
user
.
login
,
login
:
user
.
login
,
...
@@ -57,24 +61,13 @@ export class UserPicker extends Component<Props, State> {
...
@@ -57,24 +61,13 @@ export class UserPicker extends Component<Props, State> {
return
(
return
(
<
div
className=
"user-picker"
>
<
div
className=
"user-picker"
>
<
AsyncSelect
<
AsyncSelect
classNamePrefix=
{
`gf-form-select-box`
}
className=
{
className
}
isMulti=
{
false
}
isLoading=
{
isLoading
}
isLoading=
{
isLoading
}
defaultOptions=
{
true
}
defaultOptions=
{
true
}
loadOptions=
{
this
.
debouncedSearch
}
loadOptions=
{
this
.
debouncedSearch
}
onChange=
{
onSelected
}
onChange=
{
onSelected
}
className=
{
`gf-form-input gf-form-input--form-dropdown ${className || ''}`
}
styles=
{
ResetStyles
}
components=
{
{
Option
:
PickerOption
,
IndicatorsContainer
,
NoOptionsMessage
,
}
}
placeholder=
"Select user"
placeholder=
"Select user"
loadingMessage=
{
()
=>
'Loading...'
}
noOptionsMessage=
{
()
=>
'No users found'
}
noOptionsMessage=
{
()
=>
'No users found'
}
getOptionValue=
{
i
=>
i
.
id
}
getOptionLabel=
{
i
=>
i
.
label
}
/>
/>
</
div
>
</
div
>
);
);
...
...
public/app/features/panel/panel_header.ts
View file @
58cc2e34
...
@@ -111,11 +111,11 @@ function panelHeader($compile) {
...
@@ -111,11 +111,11 @@ function panelHeader($compile) {
*/
*/
function
togglePanelStackPosition
()
{
function
togglePanelStackPosition
()
{
const
menuOpenClass
=
'dropdown-menu-open'
;
const
menuOpenClass
=
'dropdown-menu-open'
;
const
panelGridClass
=
'.react-grid-item
.panel
'
;
const
panelGridClass
=
'.react-grid-item'
;
let
panelElem
=
elem
let
panelElem
=
elem
.
find
(
'[data-toggle=dropdown]'
)
.
find
(
'[data-toggle=dropdown]'
)
.
parentsUntil
(
'.panel'
)
.
parentsUntil
(
panelGridClass
)
.
parent
();
.
parent
();
const
menuElem
=
elem
.
find
(
'[data-toggle=dropdown]'
).
parent
();
const
menuElem
=
elem
.
find
(
'[data-toggle=dropdown]'
).
parent
();
panelElem
=
panelElem
&&
panelElem
.
length
?
panelElem
[
0
]
:
undefined
;
panelElem
=
panelElem
&&
panelElem
.
length
?
panelElem
[
0
]
:
undefined
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment