@@ -28,8 +28,8 @@ class CustomScrollbar extends PureComponent<Props> {
|
|||||||
<Scrollbars
|
<Scrollbars
|
||||||
className={customClassName}
|
className={customClassName}
|
||||||
autoHeight={true}
|
autoHeight={true}
|
||||||
autoHeightMin={'100%'}
|
autoHeightMin={'inherit'}
|
||||||
autoHeightMax={'100%'}
|
autoHeightMax={'inherit'}
|
||||||
renderTrackHorizontal={props => <div {...props} className="track-horizontal" />}
|
renderTrackHorizontal={props => <div {...props} className="track-horizontal" />}
|
||||||
renderTrackVertical={props => <div {...props} className="track-vertical" />}
|
renderTrackVertical={props => <div {...props} className="track-vertical" />}
|
||||||
renderThumbHorizontal={props => <div {...props} className="thumb-horizontal" />}
|
renderThumbHorizontal={props => <div {...props} className="thumb-horizontal" />}
|
||||||
|
|||||||
+4
-4
@@ -6,8 +6,8 @@ exports[`CustomScrollbar renders correctly 1`] = `
|
|||||||
style={
|
style={
|
||||||
Object {
|
Object {
|
||||||
"height": "auto",
|
"height": "auto",
|
||||||
"maxHeight": "100%",
|
"maxHeight": "inherit",
|
||||||
"minHeight": "100%",
|
"minHeight": "inherit",
|
||||||
"overflow": "hidden",
|
"overflow": "hidden",
|
||||||
"position": "relative",
|
"position": "relative",
|
||||||
"width": "100%",
|
"width": "100%",
|
||||||
@@ -23,8 +23,8 @@ exports[`CustomScrollbar renders correctly 1`] = `
|
|||||||
"left": undefined,
|
"left": undefined,
|
||||||
"marginBottom": 0,
|
"marginBottom": 0,
|
||||||
"marginRight": 0,
|
"marginRight": 0,
|
||||||
"maxHeight": "calc(100% + 0px)",
|
"maxHeight": "calc(inherit + 0px)",
|
||||||
"minHeight": "calc(100% + 0px)",
|
"minHeight": "calc(inherit + 0px)",
|
||||||
"overflow": "scroll",
|
"overflow": "scroll",
|
||||||
"position": "relative",
|
"position": "relative",
|
||||||
"right": undefined,
|
"right": undefined,
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { UserPicker } from 'app/core/components/Picker/UserPicker';
|
import { UserPicker } from 'app/core/components/Select/UserPicker';
|
||||||
import { TeamPicker, Team } from 'app/core/components/Picker/TeamPicker';
|
import { TeamPicker, Team } from 'app/core/components/Select/TeamPicker';
|
||||||
import DescriptionPicker, { OptionWithDescription } from 'app/core/components/Picker/DescriptionPicker';
|
import { Select, SelectOptionItem } from 'app/core/components/Select/Select';
|
||||||
import { User } from 'app/types';
|
import { User } from 'app/types';
|
||||||
import {
|
import {
|
||||||
dashboardPermissionLevels,
|
dashboardPermissionLevels,
|
||||||
@@ -61,7 +61,7 @@ class AddPermissions extends Component<Props, NewDashboardAclItem> {
|
|||||||
this.setState({ teamId: team && !Array.isArray(team) ? team.id : 0 });
|
this.setState({ teamId: team && !Array.isArray(team) ? team.id : 0 });
|
||||||
};
|
};
|
||||||
|
|
||||||
onPermissionChanged = (permission: OptionWithDescription) => {
|
onPermissionChanged = (permission: SelectOptionItem) => {
|
||||||
this.setState({ permission: permission.value });
|
this.setState({ permission: permission.value });
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -121,11 +121,11 @@ class AddPermissions extends Component<Props, NewDashboardAclItem> {
|
|||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
<div className="gf-form">
|
<div className="gf-form">
|
||||||
<DescriptionPicker
|
<Select
|
||||||
optionsWithDesc={dashboardPermissionLevels}
|
isSearchable={false}
|
||||||
onSelected={this.onPermissionChanged}
|
options={dashboardPermissionLevels}
|
||||||
disabled={false}
|
onChange={this.onPermissionChanged}
|
||||||
className={'gf-form-select-box__control--menu-right'}
|
className="gf-form-select-box__control--menu-right"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import DescriptionPicker from 'app/core/components/Picker/DescriptionPicker';
|
import Select from 'app/core/components/Select/Select';
|
||||||
import { dashboardPermissionLevels } from 'app/types/acl';
|
import { dashboardPermissionLevels } from 'app/types/acl';
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
@@ -9,6 +9,7 @@ export interface Props {
|
|||||||
export default class DisabledPermissionListItem extends Component<Props, any> {
|
export default class DisabledPermissionListItem extends Component<Props, any> {
|
||||||
render() {
|
render() {
|
||||||
const { item } = this.props;
|
const { item } = this.props;
|
||||||
|
const currentPermissionLevel = dashboardPermissionLevels.find(dp => dp.value === item.permission);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<tr className="gf-form-disabled">
|
<tr className="gf-form-disabled">
|
||||||
@@ -23,12 +24,12 @@ export default class DisabledPermissionListItem extends Component<Props, any> {
|
|||||||
<td className="query-keyword">Can</td>
|
<td className="query-keyword">Can</td>
|
||||||
<td>
|
<td>
|
||||||
<div className="gf-form">
|
<div className="gf-form">
|
||||||
<DescriptionPicker
|
<Select
|
||||||
optionsWithDesc={dashboardPermissionLevels}
|
options={dashboardPermissionLevels}
|
||||||
onSelected={() => {}}
|
onChange={() => {}}
|
||||||
disabled={true}
|
isDisabled={true}
|
||||||
className={'gf-form-select-box__control--menu-right'}
|
className="gf-form-select-box__control--menu-right"
|
||||||
value={item.permission}
|
value={currentPermissionLevel}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React, { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
import DescriptionPicker from 'app/core/components/Picker/DescriptionPicker';
|
import { Select } from 'app/core/components/Select/Select';
|
||||||
import { dashboardPermissionLevels, DashboardAcl, PermissionLevel } from 'app/types/acl';
|
import { dashboardPermissionLevels, DashboardAcl, PermissionLevel } from 'app/types/acl';
|
||||||
import { FolderInfo } from 'app/types';
|
import { FolderInfo } from 'app/types';
|
||||||
|
|
||||||
@@ -50,6 +50,7 @@ export default class PermissionsListItem extends PureComponent<Props> {
|
|||||||
render() {
|
render() {
|
||||||
const { item, folderInfo } = this.props;
|
const { item, folderInfo } = this.props;
|
||||||
const inheritedFromRoot = item.dashboardId === -1 && !item.inherited;
|
const inheritedFromRoot = item.dashboardId === -1 && !item.inherited;
|
||||||
|
const currentPermissionLevel = dashboardPermissionLevels.find(dp => dp.value === item.permission);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<tr className={setClassNameHelper(item.inherited)}>
|
<tr className={setClassNameHelper(item.inherited)}>
|
||||||
@@ -74,12 +75,13 @@ export default class PermissionsListItem extends PureComponent<Props> {
|
|||||||
<td className="query-keyword">Can</td>
|
<td className="query-keyword">Can</td>
|
||||||
<td>
|
<td>
|
||||||
<div className="gf-form">
|
<div className="gf-form">
|
||||||
<DescriptionPicker
|
<Select
|
||||||
optionsWithDesc={dashboardPermissionLevels}
|
isSearchable={false}
|
||||||
onSelected={this.onPermissionChanged}
|
options={dashboardPermissionLevels}
|
||||||
disabled={item.inherited}
|
onChange={this.onPermissionChanged}
|
||||||
className={'gf-form-select-box__control--menu-right'}
|
isDisabled={item.inherited}
|
||||||
value={item.permission}
|
className="gf-form-select-box__control--menu-right"
|
||||||
|
value={currentPermissionLevel}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
|
|||||||
@@ -1,26 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import { components } from 'react-select';
|
|
||||||
import { OptionProps } from 'react-select/lib/components/Option';
|
|
||||||
|
|
||||||
// https://github.com/JedWatson/react-select/issues/3038
|
|
||||||
interface ExtendedOptionProps extends OptionProps<any> {
|
|
||||||
data: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const Option = (props: ExtendedOptionProps) => {
|
|
||||||
const { children, isSelected, data } = props;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<components.Option {...props}>
|
|
||||||
<div className="gf-form-select-box__desc-option">
|
|
||||||
<div className="gf-form-select-box__desc-option__body">
|
|
||||||
<div>{children}</div>
|
|
||||||
{data.description && <div className="gf-form-select-box__desc-option__desc">{data.description}</div>}
|
|
||||||
</div>
|
|
||||||
{isSelected && <i className="fa fa-check" aria-hidden="true" />}
|
|
||||||
</div>
|
|
||||||
</components.Option>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Option;
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
import React, { Component } from 'react';
|
|
||||||
import Select from 'react-select';
|
|
||||||
import DescriptionOption from './DescriptionOption';
|
|
||||||
import IndicatorsContainer from './IndicatorsContainer';
|
|
||||||
import ResetStyles from './ResetStyles';
|
|
||||||
import NoOptionsMessage from './NoOptionsMessage';
|
|
||||||
|
|
||||||
export interface OptionWithDescription {
|
|
||||||
value: any;
|
|
||||||
label: string;
|
|
||||||
description: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Props {
|
|
||||||
optionsWithDesc: OptionWithDescription[];
|
|
||||||
onSelected: (permission) => void;
|
|
||||||
disabled: boolean;
|
|
||||||
className?: string;
|
|
||||||
value?: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
const getSelectedOption = (optionsWithDesc, value) => optionsWithDesc.find(option => option.value === value);
|
|
||||||
|
|
||||||
class DescriptionPicker extends Component<Props, any> {
|
|
||||||
render() {
|
|
||||||
const { optionsWithDesc, onSelected, disabled, className, value } = this.props;
|
|
||||||
const selectedOption = getSelectedOption(optionsWithDesc, value);
|
|
||||||
return (
|
|
||||||
<div className="permissions-picker">
|
|
||||||
<Select
|
|
||||||
placeholder="Choose"
|
|
||||||
classNamePrefix={`gf-form-select-box`}
|
|
||||||
className={`width-7 gf-form-input gf-form-input--form-dropdown ${className || ''}`}
|
|
||||||
options={optionsWithDesc}
|
|
||||||
components={{
|
|
||||||
Option: DescriptionOption,
|
|
||||||
IndicatorsContainer,
|
|
||||||
NoOptionsMessage,
|
|
||||||
}}
|
|
||||||
styles={ResetStyles}
|
|
||||||
isDisabled={disabled}
|
|
||||||
onChange={onSelected}
|
|
||||||
getOptionValue={i => i.value}
|
|
||||||
getOptionLabel={i => i.label}
|
|
||||||
value={selectedOption}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default DescriptionPicker;
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import { components } from 'react-select';
|
|
||||||
import { OptionProps } from 'react-select/lib/components/Option';
|
|
||||||
|
|
||||||
export interface Props {
|
|
||||||
children: Element;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const PickerOption = (props: OptionProps<any>) => {
|
|
||||||
const { children, className } = props;
|
|
||||||
return (
|
|
||||||
<components.Option {...props}>
|
|
||||||
<div className={`description-picker-option__button btn btn-link ${className}`}>{children}</div>
|
|
||||||
</components.Option>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default PickerOption;
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
// import React, { PureComponent } from 'react';
|
|
||||||
// import Select as ReactSelect from 'react-select';
|
|
||||||
// import DescriptionOption from './DescriptionOption';
|
|
||||||
// import IndicatorsContainer from './IndicatorsContainer';
|
|
||||||
// import ResetStyles from './ResetStyles';
|
|
||||||
//
|
|
||||||
// export interface OptionType {
|
|
||||||
// label: string;
|
|
||||||
// value: string;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// interface Props {
|
|
||||||
// defaultValue?: any;
|
|
||||||
// getOptionLabel: (item: T) => string;
|
|
||||||
// getOptionValue: (item: T) => string;
|
|
||||||
// onChange: (item: T) => {} | void;
|
|
||||||
// options: T[];
|
|
||||||
// placeholder?: string;
|
|
||||||
// width?: number;
|
|
||||||
// value: T;
|
|
||||||
// className?: string;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// export class Select<T> extends PureComponent<Props<T>> {
|
|
||||||
// static defaultProps = {
|
|
||||||
// width: null,
|
|
||||||
// className: '',
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// render() {
|
|
||||||
// const { defaultValue, getOptionLabel, getOptionValue, onSelected, options, placeholder, width, value, className } = this.props;
|
|
||||||
// let widthClass = '';
|
|
||||||
// if (width) {
|
|
||||||
// widthClass = 'width-'+width;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// return (
|
|
||||||
// <ReactSelect
|
|
||||||
// classNamePrefix="gf-form-select-box"
|
|
||||||
// className={`gf-form-input gf-form-input--form-dropdown ${widthClass} ${className}`}
|
|
||||||
// components={{
|
|
||||||
// Option: DescriptionOption,
|
|
||||||
// IndicatorsContainer,
|
|
||||||
// }}
|
|
||||||
// defaultValue={defaultValue}
|
|
||||||
// value={value}
|
|
||||||
// getOptionLabel={getOptionLabel}
|
|
||||||
// getOptionValue={getOptionValue}
|
|
||||||
// menuShouldScrollIntoView={false}
|
|
||||||
// isSearchable={false}
|
|
||||||
// onChange={onSelected}
|
|
||||||
// options={options}
|
|
||||||
// placeholder={placeholder || 'Choose'}
|
|
||||||
// styles={ResetStyles}
|
|
||||||
// />
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// export default Select;
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
import React, { SFC } from 'react';
|
|
||||||
import Select from 'react-select';
|
|
||||||
import DescriptionOption from './DescriptionOption';
|
|
||||||
import IndicatorsContainer from './IndicatorsContainer';
|
|
||||||
import ResetStyles from './ResetStyles';
|
|
||||||
|
|
||||||
interface Props {
|
|
||||||
className?: string;
|
|
||||||
defaultValue?: any;
|
|
||||||
getOptionLabel: (item: any) => string;
|
|
||||||
getOptionValue: (item: any) => string;
|
|
||||||
onSelected: (item: any) => {} | void;
|
|
||||||
options: any[];
|
|
||||||
placeholder?: string;
|
|
||||||
width?: number;
|
|
||||||
value: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
const SimplePicker: SFC<Props> = ({
|
|
||||||
className,
|
|
||||||
defaultValue,
|
|
||||||
getOptionLabel,
|
|
||||||
getOptionValue,
|
|
||||||
onSelected,
|
|
||||||
options,
|
|
||||||
placeholder,
|
|
||||||
width,
|
|
||||||
value,
|
|
||||||
}) => {
|
|
||||||
return (
|
|
||||||
<Select
|
|
||||||
classNamePrefix="gf-form-select-box"
|
|
||||||
className={`${width ? 'width-' + width : ''} gf-form-input gf-form-input--form-dropdown ${className || ''}`}
|
|
||||||
components={{
|
|
||||||
Option: DescriptionOption,
|
|
||||||
IndicatorsContainer,
|
|
||||||
}}
|
|
||||||
defaultValue={defaultValue}
|
|
||||||
value={value}
|
|
||||||
getOptionLabel={getOptionLabel}
|
|
||||||
getOptionValue={getOptionValue}
|
|
||||||
menuShouldScrollIntoView={false}
|
|
||||||
isSearchable={false}
|
|
||||||
onChange={onSelected}
|
|
||||||
options={options}
|
|
||||||
placeholder={placeholder || 'Choose'}
|
|
||||||
styles={ResetStyles}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default SimplePicker;
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
import React, { SFC } from 'react';
|
|
||||||
import { components } from 'react-select';
|
|
||||||
import { OptionProps } from 'react-select/lib/components/Option';
|
|
||||||
|
|
||||||
interface ExtendedOptionProps extends OptionProps<any> {
|
|
||||||
data: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
const UnitOption: SFC<ExtendedOptionProps> = props => {
|
|
||||||
const { children, isSelected, className } = props;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<components.Option {...props}>
|
|
||||||
<div className={`unit-picker-option__button btn btn-link ${className}`}>
|
|
||||||
{isSelected && <i className="fa fa-check pull-right" aria-hidden="true" />}
|
|
||||||
<div className="gf-form">{children}</div>
|
|
||||||
</div>
|
|
||||||
</components.Option>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default UnitOption;
|
|
||||||
@@ -1,81 +0,0 @@
|
|||||||
import React, { PureComponent } from 'react';
|
|
||||||
import Select from 'react-select';
|
|
||||||
import UnitGroup from './UnitGroup';
|
|
||||||
import UnitOption from './UnitOption';
|
|
||||||
import ResetStyles from '../ResetStyles';
|
|
||||||
import kbn from '../../../utils/kbn';
|
|
||||||
|
|
||||||
interface Props {
|
|
||||||
onSelected: (item: any) => {} | void;
|
|
||||||
defaultValue?: string;
|
|
||||||
width?: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class UnitPicker extends PureComponent<Props> {
|
|
||||||
static defaultProps = {
|
|
||||||
width: 12,
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { defaultValue, onSelected, width } = this.props;
|
|
||||||
|
|
||||||
const unitGroups = kbn.getUnitFormats();
|
|
||||||
|
|
||||||
// Need to transform the data structure to work well with Select
|
|
||||||
const groupOptions = unitGroups.map(group => {
|
|
||||||
const options = group.submenu.map(unit => {
|
|
||||||
return {
|
|
||||||
label: unit.text,
|
|
||||||
value: unit.value,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
label: group.text,
|
|
||||||
options,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
// const styles = {
|
|
||||||
// ...ResetStyles,
|
|
||||||
// menu: () => ({
|
|
||||||
// maxHeight: '75%',
|
|
||||||
// overflow: 'scroll',
|
|
||||||
// }),
|
|
||||||
// menuList: () =>
|
|
||||||
// ({
|
|
||||||
// overflowY: 'auto',
|
|
||||||
// position: 'relative',
|
|
||||||
// } as React.CSSProperties),
|
|
||||||
// valueContainer: () =>
|
|
||||||
// ({
|
|
||||||
// overflow: 'hidden',
|
|
||||||
// textOverflow: 'ellipsis',
|
|
||||||
// maxWidth: '90px',
|
|
||||||
// whiteSpace: 'nowrap',
|
|
||||||
// } as React.CSSProperties),
|
|
||||||
// };
|
|
||||||
|
|
||||||
const value = groupOptions.map(group => {
|
|
||||||
return group.options.find(option => option.value === defaultValue);
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Select
|
|
||||||
classNamePrefix="gf-form-select-box"
|
|
||||||
className={`width-${width} gf-form-input gf-form-input--form-dropdown`}
|
|
||||||
defaultValue={value}
|
|
||||||
isSearchable={true}
|
|
||||||
menuShouldScrollIntoView={false}
|
|
||||||
options={groupOptions}
|
|
||||||
placeholder="Choose"
|
|
||||||
onChange={onSelected}
|
|
||||||
components={{
|
|
||||||
Group: UnitGroup,
|
|
||||||
Option: UnitOption,
|
|
||||||
}}
|
|
||||||
styles={ResetStyles}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+6
-17
@@ -3,16 +3,13 @@ import React, { PureComponent } from 'react';
|
|||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
|
|
||||||
// Components
|
// Components
|
||||||
import ResetStyles from 'app/core/components/Picker/ResetStyles';
|
import Select from './Select';
|
||||||
import { Option, SingleValue } from 'app/core/components/Picker/PickerOption';
|
|
||||||
import IndicatorsContainer from 'app/core/components/Picker/IndicatorsContainer';
|
|
||||||
import Select from 'react-select';
|
|
||||||
|
|
||||||
// Types
|
// Types
|
||||||
import { DataSourceSelectItem } from 'app/types';
|
import { DataSourceSelectItem } from 'app/types';
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
onChangeDataSource: (ds: DataSourceSelectItem) => void;
|
onChange: (ds: DataSourceSelectItem) => void;
|
||||||
datasources: DataSourceSelectItem[];
|
datasources: DataSourceSelectItem[];
|
||||||
current: DataSourceSelectItem;
|
current: DataSourceSelectItem;
|
||||||
onBlur?: () => void;
|
onBlur?: () => void;
|
||||||
@@ -32,7 +29,7 @@ export class DataSourcePicker extends PureComponent<Props> {
|
|||||||
|
|
||||||
onChange = item => {
|
onChange = item => {
|
||||||
const ds = this.props.datasources.find(ds => ds.name === item.value);
|
const ds = this.props.datasources.find(ds => ds.name === item.value);
|
||||||
this.props.onChangeDataSource(ds);
|
this.props.onChange(ds);
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
@@ -53,27 +50,19 @@ export class DataSourcePicker extends PureComponent<Props> {
|
|||||||
return (
|
return (
|
||||||
<div className="gf-form-inline">
|
<div className="gf-form-inline">
|
||||||
<Select
|
<Select
|
||||||
classNamePrefix={`gf-form-select-box`}
|
className="ds-picker"
|
||||||
isMulti={false}
|
isMulti={false}
|
||||||
menuShouldScrollIntoView={false}
|
|
||||||
isClearable={false}
|
isClearable={false}
|
||||||
className="gf-form-input gf-form-input--form-dropdown ds-picker"
|
backspaceRemovesValue={false}
|
||||||
onChange={item => this.onChange(item)}
|
onChange={this.onChange}
|
||||||
options={options}
|
options={options}
|
||||||
styles={ResetStyles}
|
|
||||||
autoFocus={autoFocus}
|
autoFocus={autoFocus}
|
||||||
onBlur={onBlur}
|
onBlur={onBlur}
|
||||||
openMenuOnFocus={true}
|
openMenuOnFocus={true}
|
||||||
maxMenuHeight={500}
|
maxMenuHeight={500}
|
||||||
placeholder="Select datasource"
|
placeholder="Select datasource"
|
||||||
loadingMessage={() => 'Loading datasources...'}
|
|
||||||
noOptionsMessage={() => 'No datasources found'}
|
noOptionsMessage={() => 'No datasources found'}
|
||||||
value={value}
|
value={value}
|
||||||
components={{
|
|
||||||
Option,
|
|
||||||
SingleValue,
|
|
||||||
IndicatorsContainer,
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { components } from 'react-select';
|
||||||
|
import { OptionProps } from 'react-select/lib/components/Option';
|
||||||
|
|
||||||
|
export interface Props {
|
||||||
|
children: Element;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const NoOptionsMessage = (props: OptionProps<any>) => {
|
||||||
|
const { children } = props;
|
||||||
|
return (
|
||||||
|
<components.Option {...props}>
|
||||||
|
<div className="gf-form-select-box__desc-option">
|
||||||
|
<div className="gf-form-select-box__desc-option__body">{children}</div>
|
||||||
|
</div>
|
||||||
|
</components.Option>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default NoOptionsMessage;
|
||||||
+5
-5
@@ -9,7 +9,7 @@ interface State {
|
|||||||
expanded: boolean;
|
expanded: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class UnitGroup extends PureComponent<ExtendedGroupProps, State> {
|
export default class OptionGroup extends PureComponent<ExtendedGroupProps, State> {
|
||||||
state = {
|
state = {
|
||||||
expanded: false,
|
expanded: false,
|
||||||
};
|
};
|
||||||
@@ -41,10 +41,10 @@ export default class UnitGroup extends PureComponent<ExtendedGroupProps, State>
|
|||||||
const { expanded } = this.state;
|
const { expanded } = this.state;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="width-21 unit-picker-group" style={{ marginBottom: '5px' }}>
|
<div className="gf-form-select-box__option-group">
|
||||||
<div className="unit-picker-group-item" onClick={this.onToggleChildren}>
|
<div className="gf-form-select-box__option-group__header" onClick={this.onToggleChildren}>
|
||||||
<span style={{ textTransform: 'capitalize' }}>{label}</span>
|
<span className="flex-grow">{label}</span>
|
||||||
<i className={`fa ${expanded ? 'fa-minus' : 'fa-plus'}`} />{' '}
|
<i className={`fa ${expanded ? 'fa-caret-left' : 'fa-caret-down'}`} />{' '}
|
||||||
</div>
|
</div>
|
||||||
{expanded && children}
|
{expanded && children}
|
||||||
</div>
|
</div>
|
||||||
@@ -0,0 +1,232 @@
|
|||||||
|
// Libraries
|
||||||
|
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';
|
||||||
|
import { components } from 'react-select';
|
||||||
|
|
||||||
|
// Components
|
||||||
|
import { Option, SingleValue } from './PickerOption';
|
||||||
|
import OptionGroup from './OptionGroup';
|
||||||
|
import IndicatorsContainer from './IndicatorsContainer';
|
||||||
|
import NoOptionsMessage from './NoOptionsMessage';
|
||||||
|
import ResetStyles from './ResetStyles';
|
||||||
|
import CustomScrollbar from '../CustomScrollbar/CustomScrollbar';
|
||||||
|
|
||||||
|
export interface SelectOptionItem {
|
||||||
|
label?: string;
|
||||||
|
value?: any;
|
||||||
|
imgUrl?: string;
|
||||||
|
description?: string;
|
||||||
|
[key: string]: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface CommonProps {
|
||||||
|
defaultValue?: any;
|
||||||
|
getOptionLabel?: (item: SelectOptionItem) => string;
|
||||||
|
getOptionValue?: (item: SelectOptionItem) => string;
|
||||||
|
onChange: (item: SelectOptionItem) => {} | void;
|
||||||
|
placeholder?: string;
|
||||||
|
width?: number;
|
||||||
|
value?: SelectOptionItem;
|
||||||
|
className?: string;
|
||||||
|
isDisabled?: boolean;
|
||||||
|
isSearchable?: boolean;
|
||||||
|
isClearable?: boolean;
|
||||||
|
autoFocus?: boolean;
|
||||||
|
openMenuOnFocus?: boolean;
|
||||||
|
onBlur?: () => void;
|
||||||
|
maxMenuHeight?: number;
|
||||||
|
isLoading: boolean;
|
||||||
|
noOptionsMessage?: () => string;
|
||||||
|
isMulti?: boolean;
|
||||||
|
backspaceRemovesValue: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface SelectProps {
|
||||||
|
options: SelectOptionItem[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface AsyncProps {
|
||||||
|
defaultOptions: boolean;
|
||||||
|
loadOptions: (query: string) => Promise<SelectOptionItem[]>;
|
||||||
|
loadingMessage?: () => string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const MenuList = props => {
|
||||||
|
return (
|
||||||
|
<components.MenuList {...props}>
|
||||||
|
<CustomScrollbar autoHide={false}>{props.children}</CustomScrollbar>
|
||||||
|
</components.MenuList>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export class Select extends PureComponent<CommonProps & SelectProps> {
|
||||||
|
static defaultProps = {
|
||||||
|
width: null,
|
||||||
|
className: '',
|
||||||
|
isDisabled: false,
|
||||||
|
isSearchable: true,
|
||||||
|
isClearable: false,
|
||||||
|
isMulti: false,
|
||||||
|
openMenuOnFocus: false,
|
||||||
|
autoFocus: false,
|
||||||
|
isLoading: false,
|
||||||
|
backspaceRemovesValue: true,
|
||||||
|
maxMenuHeight: 300,
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const {
|
||||||
|
defaultValue,
|
||||||
|
getOptionLabel,
|
||||||
|
getOptionValue,
|
||||||
|
onChange,
|
||||||
|
options,
|
||||||
|
placeholder,
|
||||||
|
width,
|
||||||
|
value,
|
||||||
|
className,
|
||||||
|
isDisabled,
|
||||||
|
isLoading,
|
||||||
|
isSearchable,
|
||||||
|
isClearable,
|
||||||
|
backspaceRemovesValue,
|
||||||
|
isMulti,
|
||||||
|
autoFocus,
|
||||||
|
openMenuOnFocus,
|
||||||
|
onBlur,
|
||||||
|
maxMenuHeight,
|
||||||
|
noOptionsMessage,
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
|
let widthClass = '';
|
||||||
|
if (width) {
|
||||||
|
widthClass = 'width-' + width;
|
||||||
|
}
|
||||||
|
|
||||||
|
const selectClassNames = classNames('gf-form-input', 'gf-form-input--form-dropdown', widthClass, className);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ReactSelect
|
||||||
|
classNamePrefix="gf-form-select-box"
|
||||||
|
className={selectClassNames}
|
||||||
|
components={{
|
||||||
|
Option,
|
||||||
|
SingleValue,
|
||||||
|
IndicatorsContainer,
|
||||||
|
MenuList,
|
||||||
|
Group: OptionGroup,
|
||||||
|
}}
|
||||||
|
defaultValue={defaultValue}
|
||||||
|
value={value}
|
||||||
|
getOptionLabel={getOptionLabel}
|
||||||
|
getOptionValue={getOptionValue}
|
||||||
|
menuShouldScrollIntoView={false}
|
||||||
|
isSearchable={isSearchable}
|
||||||
|
onChange={onChange}
|
||||||
|
options={options}
|
||||||
|
placeholder={placeholder || 'Choose'}
|
||||||
|
styles={ResetStyles}
|
||||||
|
isDisabled={isDisabled}
|
||||||
|
isLoading={isLoading}
|
||||||
|
isClearable={isClearable}
|
||||||
|
autoFocus={autoFocus}
|
||||||
|
onBlur={onBlur}
|
||||||
|
openMenuOnFocus={openMenuOnFocus}
|
||||||
|
maxMenuHeight={maxMenuHeight}
|
||||||
|
noOptionsMessage={noOptionsMessage}
|
||||||
|
isMulti={isMulti}
|
||||||
|
backspaceRemovesValue={backspaceRemovesValue}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class AsyncSelect extends PureComponent<CommonProps & AsyncProps> {
|
||||||
|
static defaultProps = {
|
||||||
|
width: null,
|
||||||
|
className: '',
|
||||||
|
components: {},
|
||||||
|
loadingMessage: () => 'Loading...',
|
||||||
|
isDisabled: false,
|
||||||
|
isClearable: false,
|
||||||
|
isMulti: false,
|
||||||
|
isSearchable: true,
|
||||||
|
backspaceRemovesValue: true,
|
||||||
|
autoFocus: false,
|
||||||
|
openMenuOnFocus: false,
|
||||||
|
maxMenuHeight: 300,
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const {
|
||||||
|
defaultValue,
|
||||||
|
getOptionLabel,
|
||||||
|
getOptionValue,
|
||||||
|
onChange,
|
||||||
|
placeholder,
|
||||||
|
width,
|
||||||
|
value,
|
||||||
|
className,
|
||||||
|
loadOptions,
|
||||||
|
defaultOptions,
|
||||||
|
isLoading,
|
||||||
|
loadingMessage,
|
||||||
|
noOptionsMessage,
|
||||||
|
isDisabled,
|
||||||
|
isSearchable,
|
||||||
|
isClearable,
|
||||||
|
backspaceRemovesValue,
|
||||||
|
autoFocus,
|
||||||
|
onBlur,
|
||||||
|
openMenuOnFocus,
|
||||||
|
maxMenuHeight,
|
||||||
|
isMulti,
|
||||||
|
} = 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}
|
||||||
|
onChange={onChange}
|
||||||
|
loadOptions={loadOptions}
|
||||||
|
isLoading={isLoading}
|
||||||
|
defaultOptions={defaultOptions}
|
||||||
|
placeholder={placeholder || 'Choose'}
|
||||||
|
styles={ResetStyles}
|
||||||
|
loadingMessage={loadingMessage}
|
||||||
|
noOptionsMessage={noOptionsMessage}
|
||||||
|
isDisabled={isDisabled}
|
||||||
|
isSearchable={isSearchable}
|
||||||
|
isClearable={isClearable}
|
||||||
|
autoFocus={autoFocus}
|
||||||
|
onBlur={onBlur}
|
||||||
|
openMenuOnFocus={openMenuOnFocus}
|
||||||
|
maxMenuHeight={maxMenuHeight}
|
||||||
|
isMulti={isMulti}
|
||||||
|
backspaceRemovesValue={backspaceRemovesValue}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Select;
|
||||||
+3
-17
@@ -1,11 +1,7 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import AsyncSelect from 'react-select/lib/Async';
|
import { AsyncSelect } from './Select';
|
||||||
import PickerOption from './PickerOption';
|
|
||||||
import { debounce } from 'lodash';
|
import { debounce } from 'lodash';
|
||||||
import { getBackendSrv } from 'app/core/services/backend_srv';
|
import { getBackendSrv } from 'app/core/services/backend_srv';
|
||||||
import ResetStyles from './ResetStyles';
|
|
||||||
import IndicatorsContainer from './IndicatorsContainer';
|
|
||||||
import NoOptionsMessage from './NoOptionsMessage';
|
|
||||||
|
|
||||||
export interface Team {
|
export interface Team {
|
||||||
id: number;
|
id: number;
|
||||||
@@ -45,6 +41,7 @@ export class TeamPicker extends Component<Props, State> {
|
|||||||
const teams = result.teams.map(team => {
|
const teams = result.teams.map(team => {
|
||||||
return {
|
return {
|
||||||
id: team.id,
|
id: team.id,
|
||||||
|
value: team.id,
|
||||||
label: team.name,
|
label: team.name,
|
||||||
name: team.name,
|
name: team.name,
|
||||||
imgUrl: team.avatarUrl,
|
imgUrl: team.avatarUrl,
|
||||||
@@ -62,24 +59,13 @@ export class TeamPicker extends Component<Props, State> {
|
|||||||
return (
|
return (
|
||||||
<div className="user-picker">
|
<div className="user-picker">
|
||||||
<AsyncSelect
|
<AsyncSelect
|
||||||
classNamePrefix={`gf-form-select-box`}
|
|
||||||
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 || ''}`}
|
className={className}
|
||||||
styles={ResetStyles}
|
|
||||||
components={{
|
|
||||||
Option: PickerOption,
|
|
||||||
IndicatorsContainer,
|
|
||||||
NoOptionsMessage,
|
|
||||||
}}
|
|
||||||
placeholder="Select a team"
|
placeholder="Select a team"
|
||||||
loadingMessage={() => 'Loading...'}
|
|
||||||
noOptionsMessage={() => 'No teams found'}
|
noOptionsMessage={() => 'No teams found'}
|
||||||
getOptionValue={i => i.id}
|
|
||||||
getOptionLabel={i => i.label}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
import React, { PureComponent } from 'react';
|
||||||
|
import Select from './Select';
|
||||||
|
import kbn from 'app/core/utils/kbn';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
onChange: (item: any) => {} | void;
|
||||||
|
defaultValue?: string;
|
||||||
|
width?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class UnitPicker extends PureComponent<Props> {
|
||||||
|
static defaultProps = {
|
||||||
|
width: 12,
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { defaultValue, onChange, width } = this.props;
|
||||||
|
|
||||||
|
const unitGroups = kbn.getUnitFormats();
|
||||||
|
|
||||||
|
// Need to transform the data structure to work well with Select
|
||||||
|
const groupOptions = unitGroups.map(group => {
|
||||||
|
const options = group.submenu.map(unit => {
|
||||||
|
return {
|
||||||
|
label: unit.text,
|
||||||
|
value: unit.value,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
label: group.text,
|
||||||
|
options,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const value = groupOptions.map(group => {
|
||||||
|
return group.options.find(option => option.value === defaultValue);
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Select
|
||||||
|
width={width}
|
||||||
|
defaultValue={value}
|
||||||
|
isSearchable={true}
|
||||||
|
options={groupOptions}
|
||||||
|
placeholder="Choose"
|
||||||
|
onChange={onChange}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
+10
-17
@@ -1,12 +1,15 @@
|
|||||||
|
// 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 './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> {
|
|||||||
.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> {
|
|||||||
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>
|
||||||
);
|
);
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import React, { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
|
|
||||||
import { Label } from 'app/core/components/Label/Label';
|
import { Label } from 'app/core/components/Label/Label';
|
||||||
import SimplePicker from 'app/core/components/Picker/SimplePicker';
|
import Select from 'app/core/components/Select/Select';
|
||||||
import { getBackendSrv, BackendSrv } from 'app/core/services/backend_srv';
|
import { getBackendSrv, BackendSrv } from 'app/core/services/backend_srv';
|
||||||
|
|
||||||
import { DashboardSearchHit } from 'app/types';
|
import { DashboardSearchHit } from 'app/types';
|
||||||
@@ -17,12 +17,12 @@ export interface State {
|
|||||||
dashboards: DashboardSearchHit[];
|
dashboards: DashboardSearchHit[];
|
||||||
}
|
}
|
||||||
|
|
||||||
const themes = [{ value: '', text: 'Default' }, { value: 'dark', text: 'Dark' }, { value: 'light', text: 'Light' }];
|
const themes = [{ value: '', label: 'Default' }, { value: 'dark', label: 'Dark' }, { value: 'light', label: 'Light' }];
|
||||||
|
|
||||||
const timezones = [
|
const timezones = [
|
||||||
{ value: '', text: 'Default' },
|
{ value: '', label: 'Default' },
|
||||||
{ value: 'browser', text: 'Local browser time' },
|
{ value: 'browser', label: 'Local browser time' },
|
||||||
{ value: 'utc', text: 'UTC' },
|
{ value: 'utc', label: 'UTC' },
|
||||||
];
|
];
|
||||||
|
|
||||||
export class SharedPreferences extends PureComponent<Props, State> {
|
export class SharedPreferences extends PureComponent<Props, State> {
|
||||||
@@ -91,12 +91,11 @@ export class SharedPreferences extends PureComponent<Props, State> {
|
|||||||
<h3 className="page-heading">Preferences</h3>
|
<h3 className="page-heading">Preferences</h3>
|
||||||
<div className="gf-form">
|
<div className="gf-form">
|
||||||
<span className="gf-form-label width-11">UI Theme</span>
|
<span className="gf-form-label width-11">UI Theme</span>
|
||||||
<SimplePicker
|
<Select
|
||||||
|
isSearchable={false}
|
||||||
value={themes.find(item => item.value === theme)}
|
value={themes.find(item => item.value === theme)}
|
||||||
options={themes}
|
options={themes}
|
||||||
getOptionValue={i => i.value}
|
onChange={theme => this.onThemeChanged(theme.value)}
|
||||||
getOptionLabel={i => i.text}
|
|
||||||
onSelected={theme => this.onThemeChanged(theme.value)}
|
|
||||||
width={20}
|
width={20}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -107,11 +106,11 @@ export class SharedPreferences extends PureComponent<Props, State> {
|
|||||||
>
|
>
|
||||||
Home Dashboard
|
Home Dashboard
|
||||||
</Label>
|
</Label>
|
||||||
<SimplePicker
|
<Select
|
||||||
value={dashboards.find(dashboard => dashboard.id === homeDashboardId)}
|
value={dashboards.find(dashboard => dashboard.id === homeDashboardId)}
|
||||||
getOptionValue={i => i.id}
|
getOptionValue={i => i.id}
|
||||||
getOptionLabel={i => i.title}
|
getOptionLabel={i => i.title}
|
||||||
onSelected={(dashboard: DashboardSearchHit) => this.onHomeDashboardChanged(dashboard.id)}
|
onChange={(dashboard: DashboardSearchHit) => this.onHomeDashboardChanged(dashboard.id)}
|
||||||
options={dashboards}
|
options={dashboards}
|
||||||
placeholder="Chose default dashboard"
|
placeholder="Chose default dashboard"
|
||||||
width={20}
|
width={20}
|
||||||
@@ -119,11 +118,10 @@ export class SharedPreferences extends PureComponent<Props, State> {
|
|||||||
</div>
|
</div>
|
||||||
<div className="gf-form">
|
<div className="gf-form">
|
||||||
<label className="gf-form-label width-11">Timezone</label>
|
<label className="gf-form-label width-11">Timezone</label>
|
||||||
<SimplePicker
|
<Select
|
||||||
|
isSearchable={false}
|
||||||
value={timezones.find(item => item.value === timezone)}
|
value={timezones.find(item => item.value === timezone)}
|
||||||
getOptionValue={i => i.value}
|
onChange={timezone => this.onTimeZoneChanged(timezone.value)}
|
||||||
getOptionLabel={i => i.text}
|
|
||||||
onSelected={timezone => this.onTimeZoneChanged(timezone.value)}
|
|
||||||
options={timezones}
|
options={timezones}
|
||||||
width={20}
|
width={20}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -2,10 +2,10 @@ import React from 'react';
|
|||||||
import AsyncSelect from 'react-select/lib/Async';
|
import AsyncSelect from 'react-select/lib/Async';
|
||||||
import { TagOption } from './TagOption';
|
import { TagOption } from './TagOption';
|
||||||
import { TagBadge } from './TagBadge';
|
import { TagBadge } from './TagBadge';
|
||||||
import IndicatorsContainer from 'app/core/components/Picker/IndicatorsContainer';
|
import IndicatorsContainer from 'app/core/components/Select/IndicatorsContainer';
|
||||||
import NoOptionsMessage from 'app/core/components/Picker/NoOptionsMessage';
|
import NoOptionsMessage from 'app/core/components/Select/NoOptionsMessage';
|
||||||
import { components } from 'react-select';
|
import { components } from 'react-select';
|
||||||
import ResetStyles from 'app/core/components/Picker/ResetStyles';
|
import ResetStyles from 'app/core/components/Select/ResetStyles';
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
tags: string[];
|
tags: string[];
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ function link(scope, elem, attrs) {
|
|||||||
// disable depreacation warning
|
// disable depreacation warning
|
||||||
codeEditor.$blockScrolling = Infinity;
|
codeEditor.$blockScrolling = Infinity;
|
||||||
// Padding hacks
|
// Padding hacks
|
||||||
(codeEditor.renderer as any).setScrollMargin(15, 15);
|
(codeEditor.renderer as any).setScrollMargin(10, 10);
|
||||||
codeEditor.renderer.setPadding(10);
|
codeEditor.renderer.setPadding(10);
|
||||||
|
|
||||||
setThemeMode();
|
setThemeMode();
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import _ from 'lodash';
|
|||||||
// Components
|
// Components
|
||||||
import './../../panel/metrics_tab';
|
import './../../panel/metrics_tab';
|
||||||
import { EditorTabBody } from './EditorTabBody';
|
import { EditorTabBody } from './EditorTabBody';
|
||||||
import { DataSourcePicker } from './DataSourcePicker';
|
import { DataSourcePicker } from 'app/core/components/Select/DataSourcePicker';
|
||||||
import { QueryInspector } from './QueryInspector';
|
import { QueryInspector } from './QueryInspector';
|
||||||
import { QueryOptions } from './QueryOptions';
|
import { QueryOptions } from './QueryOptions';
|
||||||
import { AngularQueryComponentScope } from 'app/features/panel/metrics_tab';
|
import { AngularQueryComponentScope } from 'app/features/panel/metrics_tab';
|
||||||
@@ -205,20 +205,14 @@ export class QueriesTab extends PureComponent<Props, State> {
|
|||||||
renderToolbar = () => {
|
renderToolbar = () => {
|
||||||
const { currentDS } = this.state;
|
const { currentDS } = this.state;
|
||||||
|
|
||||||
return (
|
return <DataSourcePicker datasources={this.datasources} onChange={this.onChangeDataSource} current={currentDS} />;
|
||||||
<DataSourcePicker
|
|
||||||
datasources={this.datasources}
|
|
||||||
onChangeDataSource={this.onChangeDataSource}
|
|
||||||
current={currentDS}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
renderMixedPicker = () => {
|
renderMixedPicker = () => {
|
||||||
return (
|
return (
|
||||||
<DataSourcePicker
|
<DataSourcePicker
|
||||||
datasources={this.datasources}
|
datasources={this.datasources}
|
||||||
onChangeDataSource={this.onAddMixedQuery}
|
onChange={this.onAddMixedQuery}
|
||||||
current={null}
|
current={null}
|
||||||
autoFocus={true}
|
autoFocus={true}
|
||||||
onBlur={this.onMixedPickerBlur}
|
onBlur={this.onMixedPickerBlur}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { hot } from 'react-hot-loader';
|
import { hot } from 'react-hot-loader';
|
||||||
import Select from 'react-select';
|
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
|
|
||||||
import { DataSource } from 'app/types/datasources';
|
import { DataSource } from 'app/types/datasources';
|
||||||
@@ -25,10 +24,7 @@ import {
|
|||||||
makeTimeSeriesList,
|
makeTimeSeriesList,
|
||||||
updateHistory,
|
updateHistory,
|
||||||
} from 'app/core/utils/explore';
|
} from 'app/core/utils/explore';
|
||||||
import ResetStyles from 'app/core/components/Picker/ResetStyles';
|
import { DataSourcePicker } from 'app/core/components/Select/DataSourcePicker';
|
||||||
import PickerOption from 'app/core/components/Picker/PickerOption';
|
|
||||||
import IndicatorsContainer from 'app/core/components/Picker/IndicatorsContainer';
|
|
||||||
import NoOptionsMessage from 'app/core/components/Picker/NoOptionsMessage';
|
|
||||||
import TableModel from 'app/core/table_model';
|
import TableModel from 'app/core/table_model';
|
||||||
import { DatasourceSrv } from 'app/features/plugins/datasource_srv';
|
import { DatasourceSrv } from 'app/features/plugins/datasource_srv';
|
||||||
import { Emitter } from 'app/core/utils/emitter';
|
import { Emitter } from 'app/core/utils/emitter';
|
||||||
@@ -158,10 +154,12 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
|
|||||||
if (!datasourceSrv) {
|
if (!datasourceSrv) {
|
||||||
throw new Error('No datasource service passed as props.');
|
throw new Error('No datasource service passed as props.');
|
||||||
}
|
}
|
||||||
|
|
||||||
const datasources = datasourceSrv.getExternal();
|
const datasources = datasourceSrv.getExternal();
|
||||||
const exploreDatasources = datasources.map(ds => ({
|
const exploreDatasources = datasources.map(ds => ({
|
||||||
value: ds.name,
|
value: ds.name,
|
||||||
label: ds.name,
|
name: ds.name,
|
||||||
|
meta: ds.meta,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
if (datasources.length > 0) {
|
if (datasources.length > 0) {
|
||||||
@@ -885,7 +883,7 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
|
|||||||
} = this.state;
|
} = this.state;
|
||||||
const graphHeight = showingGraph && showingTable ? '200px' : '400px';
|
const graphHeight = showingGraph && showingTable ? '200px' : '400px';
|
||||||
const exploreClass = split ? 'explore explore-split' : 'explore';
|
const exploreClass = split ? 'explore explore-split' : 'explore';
|
||||||
const selectedDatasource = datasource ? exploreDatasources.find(d => d.label === datasource.name) : undefined;
|
const selectedDatasource = datasource ? exploreDatasources.find(d => d.name === datasource.name) : undefined;
|
||||||
const graphLoading = queryTransactions.some(qt => qt.resultType === 'Graph' && !qt.done);
|
const graphLoading = queryTransactions.some(qt => qt.resultType === 'Graph' && !qt.done);
|
||||||
const tableLoading = queryTransactions.some(qt => qt.resultType === 'Table' && !qt.done);
|
const tableLoading = queryTransactions.some(qt => qt.resultType === 'Table' && !qt.done);
|
||||||
const logsLoading = queryTransactions.some(qt => qt.resultType === 'Logs' && !qt.done);
|
const logsLoading = queryTransactions.some(qt => qt.resultType === 'Logs' && !qt.done);
|
||||||
@@ -910,26 +908,10 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
|
|||||||
)}
|
)}
|
||||||
{!datasourceMissing ? (
|
{!datasourceMissing ? (
|
||||||
<div className="navbar-buttons">
|
<div className="navbar-buttons">
|
||||||
<Select
|
<DataSourcePicker
|
||||||
classNamePrefix={`gf-form-select-box`}
|
|
||||||
isMulti={false}
|
|
||||||
menuShouldScrollIntoView={false}
|
|
||||||
isLoading={datasourceLoading}
|
|
||||||
isClearable={false}
|
|
||||||
className="gf-form-input gf-form-input--form-dropdown datasource-picker"
|
|
||||||
onChange={this.onChangeDatasource}
|
onChange={this.onChangeDatasource}
|
||||||
options={exploreDatasources}
|
datasources={exploreDatasources}
|
||||||
styles={ResetStyles}
|
current={selectedDatasource}
|
||||||
maxMenuHeight={500}
|
|
||||||
placeholder="Select datasource"
|
|
||||||
loadingMessage={() => 'Loading datasources...'}
|
|
||||||
noOptionsMessage={() => 'No datasources found'}
|
|
||||||
value={selectedDatasource}
|
|
||||||
components={{
|
|
||||||
Option: PickerOption,
|
|
||||||
IndicatorsContainer,
|
|
||||||
NoOptionsMessage,
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import React, { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import SlideDown from 'app/core/components/Animations/SlideDown';
|
import SlideDown from 'app/core/components/Animations/SlideDown';
|
||||||
import { UserPicker } from 'app/core/components/Picker/UserPicker';
|
import { UserPicker } from 'app/core/components/Select/UserPicker';
|
||||||
import DeleteButton from 'app/core/components/DeleteButton/DeleteButton';
|
import DeleteButton from 'app/core/components/DeleteButton/DeleteButton';
|
||||||
import { TagBadge } from 'app/core/components/TagFilter/TagBadge';
|
import { TagBadge } from 'app/core/components/TagFilter/TagBadge';
|
||||||
import { TeamMember, User } from 'app/types';
|
import { TeamMember, User } from 'app/types';
|
||||||
|
|||||||
@@ -2,21 +2,6 @@ import angular from 'angular';
|
|||||||
import coreModule from 'app/core/core_module';
|
import coreModule from 'app/core/core_module';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
|
|
||||||
export class CloudWatchQueryParameter {
|
|
||||||
constructor() {
|
|
||||||
return {
|
|
||||||
templateUrl: 'public/app/plugins/datasource/cloudwatch/partials/query.parameter.html',
|
|
||||||
controller: 'CloudWatchQueryParameterCtrl',
|
|
||||||
restrict: 'E',
|
|
||||||
scope: {
|
|
||||||
target: '=',
|
|
||||||
datasource: '=',
|
|
||||||
onChange: '&',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class CloudWatchQueryParameterCtrl {
|
export class CloudWatchQueryParameterCtrl {
|
||||||
/** @ngInject */
|
/** @ngInject */
|
||||||
constructor($scope, templateSrv, uiSegmentSrv, datasourceSrv, $q) {
|
constructor($scope, templateSrv, uiSegmentSrv, datasourceSrv, $q) {
|
||||||
@@ -240,5 +225,17 @@ export class CloudWatchQueryParameterCtrl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
coreModule.directive('cloudwatchQueryParameter', CloudWatchQueryParameter);
|
export function cloudWatchQueryParameter() {
|
||||||
coreModule.controller('CloudWatchQueryParameterCtrl', CloudWatchQueryParameterCtrl);
|
return {
|
||||||
|
templateUrl: 'public/app/plugins/datasource/cloudwatch/partials/query.parameter.html',
|
||||||
|
controller: CloudWatchQueryParameterCtrl,
|
||||||
|
restrict: 'E',
|
||||||
|
scope: {
|
||||||
|
target: '=',
|
||||||
|
datasource: '=',
|
||||||
|
onChange: '&',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
coreModule.directive('cloudwatchQueryParameter', cloudWatchQueryParameter);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React, { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
import { Label } from 'app/core/components/Label/Label';
|
import { Label } from 'app/core/components/Label/Label';
|
||||||
import SimplePicker from 'app/core/components/Picker/SimplePicker';
|
import { Select } from 'app/core/components/Select/Select';
|
||||||
import { MappingType, RangeMap, ValueMap } from 'app/types';
|
import { MappingType, RangeMap, ValueMap } from 'app/types';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
@@ -135,13 +135,12 @@ export default class MappingRow extends PureComponent<Props, State> {
|
|||||||
<div className="mapping-row">
|
<div className="mapping-row">
|
||||||
<div className="gf-form-inline mapping-row-type">
|
<div className="gf-form-inline mapping-row-type">
|
||||||
<Label width={5}>Type</Label>
|
<Label width={5}>Type</Label>
|
||||||
<SimplePicker
|
<Select
|
||||||
placeholder="Choose type"
|
placeholder="Choose type"
|
||||||
|
isSearchable={false}
|
||||||
options={mappingOptions}
|
options={mappingOptions}
|
||||||
value={mappingOptions.find(o => o.value === type)}
|
value={mappingOptions.find(o => o.value === type)}
|
||||||
getOptionLabel={i => i.label}
|
onChange={type => this.onMappingTypeChange(type.value)}
|
||||||
getOptionValue={i => i.value}
|
|
||||||
onSelected={type => this.onMappingTypeChange(type.value)}
|
|
||||||
width={7}
|
width={7}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,21 +1,21 @@
|
|||||||
import React, { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
import { Label } from 'app/core/components/Label/Label';
|
import { Label } from 'app/core/components/Label/Label';
|
||||||
import SimplePicker from 'app/core/components/Picker/SimplePicker';
|
import Select from 'app/core/components/Select/Select';
|
||||||
import UnitPicker from 'app/core/components/Picker/Unit/UnitPicker';
|
import UnitPicker from 'app/core/components/Select/UnitPicker';
|
||||||
import { OptionModuleProps } from './module';
|
import { OptionModuleProps } from './module';
|
||||||
|
|
||||||
const statOptions = [
|
const statOptions = [
|
||||||
{ value: 'min', text: 'Min' },
|
{ value: 'min', label: 'Min' },
|
||||||
{ value: 'max', text: 'Max' },
|
{ value: 'max', label: 'Max' },
|
||||||
{ value: 'avg', text: 'Average' },
|
{ value: 'avg', label: 'Average' },
|
||||||
{ value: 'current', text: 'Current' },
|
{ value: 'current', label: 'Current' },
|
||||||
{ value: 'total', text: 'Total' },
|
{ value: 'total', label: 'Total' },
|
||||||
{ value: 'name', text: 'Name' },
|
{ value: 'name', label: 'Name' },
|
||||||
{ value: 'first', text: 'First' },
|
{ value: 'first', label: 'First' },
|
||||||
{ value: 'delta', text: 'Delta' },
|
{ value: 'delta', label: 'Delta' },
|
||||||
{ value: 'diff', text: 'Difference' },
|
{ value: 'diff', label: 'Difference' },
|
||||||
{ value: 'range', text: 'Range' },
|
{ value: 'range', label: 'Range' },
|
||||||
{ value: 'last_time', text: 'Time of last point' },
|
{ value: 'last_time', label: 'Time of last point' },
|
||||||
];
|
];
|
||||||
|
|
||||||
const labelWidth = 6;
|
const labelWidth = 6;
|
||||||
@@ -43,18 +43,16 @@ export default class ValueOptions extends PureComponent<OptionModuleProps> {
|
|||||||
<h5 className="page-heading">Value</h5>
|
<h5 className="page-heading">Value</h5>
|
||||||
<div className="gf-form-inline">
|
<div className="gf-form-inline">
|
||||||
<Label width={labelWidth}>Stat</Label>
|
<Label width={labelWidth}>Stat</Label>
|
||||||
<SimplePicker
|
<Select
|
||||||
width={12}
|
width={12}
|
||||||
options={statOptions}
|
options={statOptions}
|
||||||
getOptionLabel={i => i.text}
|
onChange={this.onStatChange}
|
||||||
getOptionValue={i => i.value}
|
|
||||||
onSelected={this.onStatChange}
|
|
||||||
value={statOptions.find(option => option.value === stat)}
|
value={statOptions.find(option => option.value === stat)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="gf-form-inline">
|
<div className="gf-form-inline">
|
||||||
<Label width={labelWidth}>Unit</Label>
|
<Label width={labelWidth}>Unit</Label>
|
||||||
<UnitPicker defaultValue={unit} onSelected={value => this.onUnitChange(value)} />
|
<UnitPicker defaultValue={unit} onChange={this.onUnitChange} />
|
||||||
</div>
|
</div>
|
||||||
<div className="gf-form-inline">
|
<div className="gf-form-inline">
|
||||||
<Label width={labelWidth}>Decimals</Label>
|
<Label width={labelWidth}>Decimals</Label>
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { Value } from 'slate';
|
|||||||
import { DataQuery, RawTimeRange } from './series';
|
import { DataQuery, RawTimeRange } from './series';
|
||||||
import TableModel from 'app/core/table_model';
|
import TableModel from 'app/core/table_model';
|
||||||
import { LogsModel } from 'app/core/logs_model';
|
import { LogsModel } from 'app/core/logs_model';
|
||||||
|
import { DataSourceSelectItem } from 'app/types/datasources';
|
||||||
|
|
||||||
export interface CompletionItem {
|
export interface CompletionItem {
|
||||||
/**
|
/**
|
||||||
@@ -74,11 +75,6 @@ export interface CompletionItemGroup {
|
|||||||
skipSort?: boolean;
|
skipSort?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ExploreDatasource {
|
|
||||||
value: string;
|
|
||||||
label: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface HistoryItem {
|
export interface HistoryItem {
|
||||||
ts: number;
|
ts: number;
|
||||||
query: DataQuery;
|
query: DataQuery;
|
||||||
@@ -159,7 +155,7 @@ export interface ExploreState {
|
|||||||
datasourceLoading: boolean | null;
|
datasourceLoading: boolean | null;
|
||||||
datasourceMissing: boolean;
|
datasourceMissing: boolean;
|
||||||
datasourceName?: string;
|
datasourceName?: string;
|
||||||
exploreDatasources: ExploreDatasource[];
|
exploreDatasources: DataSourceSelectItem[];
|
||||||
graphInterval: number; // in ms
|
graphInterval: number; // in ms
|
||||||
graphResult?: any[];
|
graphResult?: any[];
|
||||||
history: HistoryItem[];
|
history: HistoryItem[];
|
||||||
|
|||||||
@@ -101,7 +101,6 @@
|
|||||||
@import 'components/delete_button';
|
@import 'components/delete_button';
|
||||||
@import 'components/add_data_source.scss';
|
@import 'components/add_data_source.scss';
|
||||||
@import 'components/page_loader';
|
@import 'components/page_loader';
|
||||||
@import 'components/unit-picker';
|
|
||||||
@import 'components/thresholds';
|
@import 'components/thresholds';
|
||||||
@import 'components/toggle_button_group';
|
@import 'components/toggle_button_group';
|
||||||
@import 'components/value-mappings';
|
@import 'components/value-mappings';
|
||||||
|
|||||||
@@ -79,6 +79,7 @@ $select-input-bg-disabled: $input-bg-disabled;
|
|||||||
.gf-form-select-box__option {
|
.gf-form-select-box__option {
|
||||||
border-left: 2px solid transparent;
|
border-left: 2px solid transparent;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
background-color: $input-bg;
|
||||||
|
|
||||||
&.gf-form-select-box__option--is-focused {
|
&.gf-form-select-box__option--is-focused {
|
||||||
color: $dropdownLinkColorHover;
|
color: $dropdownLinkColorHover;
|
||||||
@@ -116,7 +117,7 @@ $select-input-bg-disabled: $input-bg-disabled;
|
|||||||
.gf-form-select-box__select-arrow {
|
.gf-form-select-box__select-arrow {
|
||||||
border-color: $input-color-select-arrow transparent transparent;
|
border-color: $input-color-select-arrow transparent transparent;
|
||||||
border-style: solid;
|
border-style: solid;
|
||||||
border-width: 5px 5px 2.5px;
|
border-width: 4px 4px 2.5px;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
height: 0;
|
height: 0;
|
||||||
width: 0;
|
width: 0;
|
||||||
@@ -125,7 +126,7 @@ $select-input-bg-disabled: $input-bg-disabled;
|
|||||||
&.gf-form-select-box__select-arrow--reversed {
|
&.gf-form-select-box__select-arrow--reversed {
|
||||||
border-color: transparent transparent $input-color-select-arrow;
|
border-color: transparent transparent $input-color-select-arrow;
|
||||||
top: -2px;
|
top: -2px;
|
||||||
border-width: 0 5px 5px;
|
border-width: 0 4px 4px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,3 +171,19 @@ $select-input-bg-disabled: $input-bg-disabled;
|
|||||||
width: 16px;
|
width: 16px;
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.gf-form-select-box__option-group__header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-start;
|
||||||
|
justify-items: center;
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 7px 10px;
|
||||||
|
width: 100%;
|
||||||
|
border-bottom: 1px solid $hr-border-color;
|
||||||
|
text-transform: capitalize;
|
||||||
|
|
||||||
|
.fa {
|
||||||
|
padding-right: 2px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -59,6 +59,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.gf-form-query-letter-cell {
|
.gf-form-query-letter-cell {
|
||||||
|
flex-shrink: 0;
|
||||||
|
|
||||||
.gf-form-query-letter-cell-carret {
|
.gf-form-query-letter-cell-carret {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 0.7rem;
|
width: 0.7rem;
|
||||||
|
|||||||
@@ -97,10 +97,10 @@ input:checked + .gf-form-switch__slider::before {
|
|||||||
&--transparent {
|
&--transparent {
|
||||||
background: transparent;
|
background: transparent;
|
||||||
border: none;
|
border: none;
|
||||||
width: 20px;
|
width: 23px;
|
||||||
height: auto;
|
height: auto;
|
||||||
position: relative;
|
position: relative;
|
||||||
padding-left: 7px;
|
padding-left: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&--table-cell {
|
&--table-cell {
|
||||||
|
|||||||
@@ -1,24 +0,0 @@
|
|||||||
.unit-picker-option {
|
|
||||||
position: relative;
|
|
||||||
width: 100%;
|
|
||||||
display: block;
|
|
||||||
border-radius: 0;
|
|
||||||
white-space: normal;
|
|
||||||
|
|
||||||
i.fa-check {
|
|
||||||
padding-left: 2px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.unit-picker-group {
|
|
||||||
margin-bottom: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.unit-picker-group-item {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
padding: 10px;
|
|
||||||
font-size: 14px;
|
|
||||||
border-bottom: 1px solid #555;
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user