2022-04-22 14:33:13 +01:00
|
|
|
import { css } from '@emotion/css';
|
2022-02-07 15:18:17 +01:00
|
|
|
import React, { useCallback, useState } from 'react';
|
2022-04-22 14:33:13 +01:00
|
|
|
import Highlighter from 'react-highlight-words';
|
|
|
|
|
|
2022-02-07 15:18:17 +01:00
|
|
|
import { SelectableValue, toOption, GrafanaTheme2 } from '@grafana/data';
|
2022-07-20 12:50:08 -04:00
|
|
|
import { Select, FormatOptionLabelMeta, useStyles2, EditorField, EditorFieldGroup } from '@grafana/ui';
|
2022-04-22 14:33:13 +01:00
|
|
|
|
|
|
|
|
import { PromVisualQuery } from '../types';
|
2022-02-07 15:18:17 +01:00
|
|
|
|
|
|
|
|
// We are matching words split with space
|
|
|
|
|
const splitSeparator = ' ';
|
2022-01-31 07:57:14 +01:00
|
|
|
|
|
|
|
|
export interface Props {
|
|
|
|
|
query: PromVisualQuery;
|
|
|
|
|
onChange: (query: PromVisualQuery) => void;
|
2022-02-03 11:40:19 +01:00
|
|
|
onGetMetrics: () => Promise<SelectableValue[]>;
|
2022-01-31 07:57:14 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function MetricSelect({ query, onChange, onGetMetrics }: Props) {
|
2022-02-07 15:18:17 +01:00
|
|
|
const styles = useStyles2(getStyles);
|
2022-01-31 07:57:14 +01:00
|
|
|
const [state, setState] = useState<{
|
|
|
|
|
metrics?: Array<SelectableValue<any>>;
|
|
|
|
|
isLoading?: boolean;
|
|
|
|
|
}>({});
|
|
|
|
|
|
2022-02-07 15:18:17 +01:00
|
|
|
const customFilterOption = useCallback((option: SelectableValue<any>, searchQuery: string) => {
|
|
|
|
|
const label = option.label ?? option.value;
|
|
|
|
|
if (!label) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2022-04-28 12:25:51 +02:00
|
|
|
|
|
|
|
|
// custom value is not a string label but a react node
|
|
|
|
|
if (!label.toLowerCase) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-07 15:18:17 +01:00
|
|
|
const searchWords = searchQuery.split(splitSeparator);
|
|
|
|
|
return searchWords.reduce((acc, cur) => acc && label.toLowerCase().includes(cur.toLowerCase()), true);
|
|
|
|
|
}, []);
|
|
|
|
|
|
|
|
|
|
const formatOptionLabel = useCallback(
|
|
|
|
|
(option: SelectableValue<any>, meta: FormatOptionLabelMeta<any>) => {
|
|
|
|
|
// For newly created custom value we don't want to add highlight
|
|
|
|
|
if (option['__isNew__']) {
|
|
|
|
|
return option.label;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<Highlighter
|
|
|
|
|
searchWords={meta.inputValue.split(splitSeparator)}
|
|
|
|
|
textToHighlight={option.label ?? ''}
|
2022-02-16 09:40:04 +01:00
|
|
|
highlightClassName={styles.highlight}
|
2022-02-07 15:18:17 +01:00
|
|
|
/>
|
|
|
|
|
);
|
|
|
|
|
},
|
2022-02-16 09:40:04 +01:00
|
|
|
[styles.highlight]
|
2022-02-07 15:18:17 +01:00
|
|
|
);
|
|
|
|
|
|
2022-01-31 07:57:14 +01:00
|
|
|
return (
|
|
|
|
|
<EditorFieldGroup>
|
|
|
|
|
<EditorField label="Metric">
|
|
|
|
|
<Select
|
|
|
|
|
inputId="prometheus-metric-select"
|
|
|
|
|
className={styles.select}
|
|
|
|
|
value={query.metric ? toOption(query.metric) : undefined}
|
|
|
|
|
placeholder="Select metric"
|
2022-10-05 12:19:12 -03:00
|
|
|
virtualized
|
2022-01-31 07:57:14 +01:00
|
|
|
allowCustomValue
|
2022-02-07 15:18:17 +01:00
|
|
|
formatOptionLabel={formatOptionLabel}
|
|
|
|
|
filterOption={customFilterOption}
|
2022-01-31 07:57:14 +01:00
|
|
|
onOpenMenu={async () => {
|
|
|
|
|
setState({ isLoading: true });
|
2022-02-03 11:40:19 +01:00
|
|
|
const metrics = await onGetMetrics();
|
2022-01-31 07:57:14 +01:00
|
|
|
setState({ metrics, isLoading: undefined });
|
|
|
|
|
}}
|
|
|
|
|
isLoading={state.isLoading}
|
|
|
|
|
options={state.metrics}
|
|
|
|
|
onChange={({ value }) => {
|
|
|
|
|
if (value) {
|
2022-02-16 09:40:04 +01:00
|
|
|
onChange({ ...query, metric: value });
|
2022-01-31 07:57:14 +01:00
|
|
|
}
|
|
|
|
|
}}
|
|
|
|
|
/>
|
|
|
|
|
</EditorField>
|
|
|
|
|
</EditorFieldGroup>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-07 15:18:17 +01:00
|
|
|
const getStyles = (theme: GrafanaTheme2) => ({
|
2022-01-31 07:57:14 +01:00
|
|
|
select: css`
|
|
|
|
|
min-width: 125px;
|
|
|
|
|
`,
|
2022-02-16 09:40:04 +01:00
|
|
|
highlight: css`
|
2022-02-07 15:18:17 +01:00
|
|
|
label: select__match-highlight;
|
|
|
|
|
background: inherit;
|
|
|
|
|
padding: inherit;
|
2022-05-23 15:53:45 +02:00
|
|
|
color: ${theme.colors.warning.contrastText};
|
|
|
|
|
background-color: ${theme.colors.warning.main};
|
2022-02-07 15:18:17 +01:00
|
|
|
`,
|
2022-01-31 07:57:14 +01:00
|
|
|
});
|