Commit 1f3f3363 by Erik Sundell

wip: add option group component

parent d75860a7
import React from 'react';
import Select from 'react-select';
import _ from 'lodash';
import GroupHeading from 'app/core/components/Picker/GroupHeading';
import DescriptionOption from 'app/core/components/Picker/DescriptionOption';
import IndicatorsContainer from 'app/core/components/Picker/IndicatorsContainer';
import ResetStyles from 'app/core/components/Picker/ResetStyles';
import NoOptionsMessage from 'app/core/components/Picker/NoOptionsMessage';
export interface Props {
onChange: (value: string) => void;
groups: any[];
searchable: boolean;
selected: string;
placeholder?: string;
className?: string;
}
export class OptionGroupPicker extends React.Component<Props, any> {
constructor(props) {
super(props);
}
render() {
const { onChange, groups, selected, placeholder, className, searchable } = this.props;
const options = _.flatten(groups.map(o => o.options));
const selectedOption = options.find(option => option.value === selected);
return (
<Select
placeholder={placeholder}
classNamePrefix={`gf-form-select-box`}
className={className}
options={groups}
components={{
GroupHeading,
Option: DescriptionOption,
IndicatorsContainer,
NoOptionsMessage,
}}
styles={ResetStyles}
isSearchable={searchable}
maxMenuHeight={50}
onChange={option => onChange(option.value)}
getOptionValue={i => i.value}
getOptionLabel={i => i.label}
value={selectedOption}
noOptionsMessage={() => 'No metrics found'}
/>
);
}
}
import React from 'react'; import React from 'react';
// import SimplePicker from 'app/core/components/Picker/SimplePicker';
import Select from 'react-select'; import Select from 'react-select';
// import DescriptionPicker from 'app/core/components/Picker/DescriptionPicker'; import _ from 'lodash';
import DescriptionOption from 'app/core/components/Picker/DescriptionOption'; import DescriptionOption from 'app/core/components/Picker/DescriptionOption';
import IndicatorsContainer from 'app/core/components/Picker/IndicatorsContainer'; import IndicatorsContainer from 'app/core/components/Picker/IndicatorsContainer';
import ResetStyles from 'app/core/components/Picker/ResetStyles'; import ResetStyles from 'app/core/components/Picker/ResetStyles';
import NoOptionsMessage from 'app/core/components/Picker/NoOptionsMessage'; import NoOptionsMessage from 'app/core/components/Picker/NoOptionsMessage';
import _ from 'lodash';
export interface Props { export interface Props {
onChange: (value: string) => void; onChange: (value: string) => void;
options: any[]; options: any[];
searchable: boolean;
selected: string; selected: string;
placeholder?: string; placeholder?: string;
className?: string; className?: string;
groups?: boolean;
} }
export class OptionPicker extends React.Component<Props, any> { export class OptionPicker extends React.Component<Props, any> {
...@@ -22,8 +23,9 @@ export class OptionPicker extends React.Component<Props, any> { ...@@ -22,8 +23,9 @@ export class OptionPicker extends React.Component<Props, any> {
} }
render() { render() {
const { onChange, options, selected, placeholder, className } = this.props; const { onChange, options, selected, placeholder, className, searchable } = this.props;
const selectedOption = options.find(metric => metric.value === selected); const selectedOption = options.find(option => option.value === selected);
return ( return (
<Select <Select
placeholder={placeholder} placeholder={placeholder}
...@@ -36,7 +38,8 @@ export class OptionPicker extends React.Component<Props, any> { ...@@ -36,7 +38,8 @@ export class OptionPicker extends React.Component<Props, any> {
NoOptionsMessage, NoOptionsMessage,
}} }}
styles={ResetStyles} styles={ResetStyles}
isDisabled={false} isSearchable={searchable}
maxMenuHeight={50}
onChange={option => onChange(option.value)} onChange={option => onChange(option.value)}
getOptionValue={i => i.value} getOptionValue={i => i.value}
getOptionLabel={i => i.label} getOptionLabel={i => i.label}
......
...@@ -5,8 +5,9 @@ ...@@ -5,8 +5,9 @@
onChange="ctrl.handleServiceChange" onChange="ctrl.handleServiceChange"
selected="ctrl.service" selected="ctrl.service"
options="ctrl.services" options="ctrl.services"
placeholder="ctrl.defaultDropdownValue" searchable="false"
className="width-12" placeholder="ctrl.defaultServiceValue"
className="&quot;width-15&quot;"
></option-picker> ></option-picker>
</div> </div>
<div class="gf-form gf-form--grow"><div class="gf-form-label gf-form-label--grow"></div></div> <div class="gf-form gf-form--grow"><div class="gf-form-label gf-form-label--grow"></div></div>
...@@ -14,13 +15,14 @@ ...@@ -14,13 +15,14 @@
<div class="gf-form-inline"> <div class="gf-form-inline">
<div class="gf-form"> <div class="gf-form">
<span class="gf-form-label width-9 query-keyword">Metric</span> <span class="gf-form-label width-9 query-keyword">Metric</span>
<option-picker <option-group-picker
onChange="ctrl.handleMetricTypeChange" onChange="ctrl.handleMetricTypeChange"
selected="ctrl.metricType" selected="ctrl.metricType"
options="ctrl.metrics" groups="ctrl.insertTemplateVariables(ctrl.defaultServiceValue !== ctrl.service ? ctrl.metrics : ctrl.metricGroups)"
searchable="true"
placeholder="ctrl.defaultDropdownValue" placeholder="ctrl.defaultDropdownValue"
className="width-12" className="&quot;width-15&quot;"
></option-picker> ></option-group-picker>
</div> </div>
<div class="gf-form gf-form--grow"><div class="gf-form-label gf-form-label--grow"></div></div> <div class="gf-form gf-form--grow"><div class="gf-form-label gf-form-label--grow"></div></div>
</div> </div>
......
...@@ -3,6 +3,7 @@ import { QueryCtrl } from 'app/plugins/sdk'; ...@@ -3,6 +3,7 @@ import { QueryCtrl } from 'app/plugins/sdk';
import './query_aggregation_ctrl'; import './query_aggregation_ctrl';
import './query_filter_ctrl'; import './query_filter_ctrl';
import { OptionPicker } from './components/OptionPicker'; import { OptionPicker } from './components/OptionPicker';
import { OptionGroupPicker } from './components/OptionGroupPicker';
import { react2AngularDirective } from 'app/core/utils/react2angular'; import { react2AngularDirective } from 'app/core/utils/react2angular';
export interface QueryMeta { export interface QueryMeta {
...@@ -70,6 +71,15 @@ export class StackdriverQueryCtrl extends QueryCtrl { ...@@ -70,6 +71,15 @@ export class StackdriverQueryCtrl extends QueryCtrl {
'options', 'options',
'onChange', 'onChange',
'selected', 'selected',
'searchable',
'className',
'placeholder',
]);
react2AngularDirective('optionGroupPicker', OptionGroupPicker, [
'groups',
'onChange',
'selected',
'searchable',
'className', 'className',
'placeholder', 'placeholder',
]); ]);
......
...@@ -36,6 +36,7 @@ export class StackdriverFilterCtrl { ...@@ -36,6 +36,7 @@ export class StackdriverFilterCtrl {
metricType: string; metricType: string;
metricDescriptors: any[]; metricDescriptors: any[];
metrics: any[]; metrics: any[];
metricGroups: any[];
services: any[]; services: any[];
groupBySegments: any[]; groupBySegments: any[];
filterSegments: FilterSegments; filterSegments: FilterSegments;
...@@ -52,6 +53,7 @@ export class StackdriverFilterCtrl { ...@@ -52,6 +53,7 @@ export class StackdriverFilterCtrl {
this.metricDescriptors = []; this.metricDescriptors = [];
this.metrics = []; this.metrics = [];
this.metricGroups = [];
this.services = []; this.services = [];
this.getCurrentProject() this.getCurrentProject()
...@@ -106,6 +108,7 @@ export class StackdriverFilterCtrl { ...@@ -106,6 +108,7 @@ export class StackdriverFilterCtrl {
this.metricDescriptors = await this.datasource.getMetricTypes(this.target.defaultProject); this.metricDescriptors = await this.datasource.getMetricTypes(this.target.defaultProject);
this.services = this.getServicesList(); this.services = this.getServicesList();
this.metrics = this.getMetricsList(); this.metrics = this.getMetricsList();
this.metricGroups = this.getMetricGroups();
return this.metricDescriptors; return this.metricDescriptors;
} else { } else {
return []; return [];
...@@ -113,11 +116,11 @@ export class StackdriverFilterCtrl { ...@@ -113,11 +116,11 @@ export class StackdriverFilterCtrl {
} }
getServicesList() { getServicesList() {
const defaultValue = { value: this.$scope.defaultServiceValue, text: this.$scope.defaultServiceValue }; const defaultValue = { value: this.$scope.defaultServiceValue, label: this.$scope.defaultServiceValue };
const services = this.metricDescriptors.map(m => { const services = this.metricDescriptors.map(m => {
return { return {
value: m.service, value: m.service,
label: m.serviceShortName, label: _.startCase(m.serviceShortName),
}; };
}); });
...@@ -128,6 +131,37 @@ export class StackdriverFilterCtrl { ...@@ -128,6 +131,37 @@ export class StackdriverFilterCtrl {
return services.length > 0 ? [defaultValue, ..._.uniqBy(services, 'value')] : []; return services.length > 0 ? [defaultValue, ..._.uniqBy(services, 'value')] : [];
} }
getMetricGroups() {
return this.metrics.reduce((acc, curr) => {
const group = acc.find(group => group.service === curr.service);
if (group) {
group.options = [...group.options, { value: curr.value, label: curr.label }];
} else {
acc = [
...acc,
{
label: _.startCase(curr.serviceShortName),
service: curr.service,
options: [{ value: curr.value, label: curr.label }],
},
];
}
return acc;
}, []);
}
insertTemplateVariables(options) {
const templateVariables = {
label: 'Template Variables',
options: this.templateSrv.variables.map(v => ({
label: `$${v.name}`,
value: `$${v.name}`,
description: `$${v.definition}`,
})),
};
return [templateVariables, { label: 'Metrics', options }];
}
getMetricsList() { getMetricsList() {
const metrics = this.metricDescriptors.map(m => { const metrics = this.metricDescriptors.map(m => {
return { return {
...@@ -178,6 +212,7 @@ export class StackdriverFilterCtrl { ...@@ -178,6 +212,7 @@ export class StackdriverFilterCtrl {
handleServiceChange(service) { handleServiceChange(service) {
this.target.service = this.service = service; this.target.service = this.service = service;
this.metrics = this.getMetricsList(); this.metrics = this.getMetricsList();
this.metricGroups = this.getMetricGroups();
this.setMetricType(); this.setMetricType();
this.getLabels(); this.getLabels();
if (!this.metrics.find(m => m.value === this.target.metricType)) { if (!this.metrics.find(m => m.value === this.target.metricType)) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment