mirror of
https://github.com/prometheus/prometheus.git
synced 2024-12-25 05:34:05 -08:00
UI: Add toggle to enable/disable metric autocomplete (#8134)
* UI: Add toggle to enable/disable metric autocomplete This change adds a toggle to enable or disable the metric autocomplete functionality. By default it is enabled. This is a port of a change I did in [Thanos][1]. [1]: https://github.com/thanos-io/thanos/pull/3381 Signed-off-by: Jarod Watkins <jarod@42lines.net> * Adding full variable name Signed-off-by: Jarod Watkins <jarod@42lines.net>
This commit is contained in:
parent
7558e9d3c3
commit
388a2d20c9
|
@ -30,6 +30,7 @@ describe('ExpressionInput', () => {
|
|||
// Do nothing.
|
||||
},
|
||||
loading: false,
|
||||
enableMetricAutocomplete: true,
|
||||
};
|
||||
|
||||
let expressionInput: ReactWrapper;
|
||||
|
@ -174,8 +175,27 @@ describe('ExpressionInput', () => {
|
|||
instance.createAutocompleteSection({ closeMenu: spyCloseMenu });
|
||||
setTimeout(() => expect(spyCloseMenu).toHaveBeenCalled());
|
||||
});
|
||||
it('should not render list if enableMetricAutocomplete is false', () => {
|
||||
const input = mount(
|
||||
<ExpressionInput
|
||||
autocompleteSections={{ title: ['foo', 'bar', 'baz'] }}
|
||||
{...({} as any)}
|
||||
enableMetricAutocomplete={false}
|
||||
/>
|
||||
);
|
||||
const instance: any = input.instance();
|
||||
const spyCloseMenu = jest.fn();
|
||||
instance.createAutocompleteSection({ closeMenu: spyCloseMenu });
|
||||
setTimeout(() => expect(spyCloseMenu).toHaveBeenCalled());
|
||||
});
|
||||
it('should render autosuggest-dropdown', () => {
|
||||
const input = mount(<ExpressionInput autocompleteSections={{ title: ['foo', 'bar', 'baz'] }} {...({} as any)} />);
|
||||
const input = mount(
|
||||
<ExpressionInput
|
||||
autocompleteSections={{ title: ['foo', 'bar', 'baz'] }}
|
||||
{...({} as any)}
|
||||
enableMetricAutocomplete={true}
|
||||
/>
|
||||
);
|
||||
const instance: any = input.instance();
|
||||
const spyGetMenuProps = jest.fn();
|
||||
const sections = instance.createAutocompleteSection({
|
||||
|
|
|
@ -14,6 +14,7 @@ interface ExpressionInputProps {
|
|||
autocompleteSections: { [key: string]: string[] };
|
||||
executeQuery: () => void;
|
||||
loading: boolean;
|
||||
enableMetricAutocomplete: boolean;
|
||||
}
|
||||
|
||||
interface ExpressionInputState {
|
||||
|
@ -76,38 +77,39 @@ class ExpressionInput extends Component<ExpressionInputProps, ExpressionInputSta
|
|||
const { inputValue = '', closeMenu, highlightedIndex } = downshift;
|
||||
const { autocompleteSections } = this.props;
|
||||
let index = 0;
|
||||
const sections = inputValue!.length
|
||||
? Object.entries(autocompleteSections).reduce((acc, [title, items]) => {
|
||||
const matches = this.getSearchMatches(inputValue!, items);
|
||||
return !matches.length
|
||||
? acc
|
||||
: [
|
||||
...acc,
|
||||
<ul className="autosuggest-dropdown-list" key={title}>
|
||||
<li className="autosuggest-dropdown-header">{title}</li>
|
||||
{matches
|
||||
.slice(0, 100) // Limit DOM rendering to 100 results, as DOM rendering is sloooow.
|
||||
.map(({ original, string: text }) => {
|
||||
const itemProps = downshift.getItemProps({
|
||||
key: original,
|
||||
index,
|
||||
item: original,
|
||||
style: {
|
||||
backgroundColor: highlightedIndex === index++ ? 'lightgray' : 'white',
|
||||
},
|
||||
});
|
||||
return (
|
||||
<li
|
||||
key={title}
|
||||
{...itemProps}
|
||||
dangerouslySetInnerHTML={{ __html: sanitizeHTML(text, { allowedTags: ['strong'] }) }}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</ul>,
|
||||
];
|
||||
}, [] as JSX.Element[])
|
||||
: [];
|
||||
const sections =
|
||||
inputValue!.length && this.props.enableMetricAutocomplete
|
||||
? Object.entries(autocompleteSections).reduce((acc, [title, items]) => {
|
||||
const matches = this.getSearchMatches(inputValue!, items);
|
||||
return !matches.length
|
||||
? acc
|
||||
: [
|
||||
...acc,
|
||||
<ul className="autosuggest-dropdown-list" key={title}>
|
||||
<li className="autosuggest-dropdown-header">{title}</li>
|
||||
{matches
|
||||
.slice(0, 100) // Limit DOM rendering to 100 results, as DOM rendering is sloooow.
|
||||
.map(({ original, string: text }) => {
|
||||
const itemProps = downshift.getItemProps({
|
||||
key: original,
|
||||
index,
|
||||
item: original,
|
||||
style: {
|
||||
backgroundColor: highlightedIndex === index++ ? 'lightgray' : 'white',
|
||||
},
|
||||
});
|
||||
return (
|
||||
<li
|
||||
key={title}
|
||||
{...itemProps}
|
||||
dangerouslySetInnerHTML={{ __html: sanitizeHTML(text, { allowedTags: ['strong'] }) }}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</ul>,
|
||||
];
|
||||
}, [] as JSX.Element[])
|
||||
: [];
|
||||
|
||||
if (!sections.length) {
|
||||
// This is ugly but is needed in order to sync state updates.
|
||||
|
|
|
@ -32,6 +32,7 @@ const defaultProps = {
|
|||
onExecuteQuery: (): void => {
|
||||
// Do nothing.
|
||||
},
|
||||
enableMetricAutocomplete: true,
|
||||
};
|
||||
|
||||
describe('Panel', () => {
|
||||
|
|
|
@ -22,6 +22,7 @@ interface PanelProps {
|
|||
removePanel: () => void;
|
||||
onExecuteQuery: (query: string) => void;
|
||||
pathPrefix: string;
|
||||
enableMetricAutocomplete: boolean;
|
||||
}
|
||||
|
||||
interface PanelState {
|
||||
|
@ -233,6 +234,7 @@ class Panel extends Component<PanelProps, PanelState> {
|
|||
onExpressionChange={this.handleExpressionChange}
|
||||
executeQuery={this.executeQuery}
|
||||
loading={this.state.loading}
|
||||
enableMetricAutocomplete={this.props.enableMetricAutocomplete}
|
||||
autocompleteSections={{
|
||||
'Query History': pastQueries,
|
||||
'Metric Names': metricNames,
|
||||
|
|
|
@ -22,9 +22,16 @@ interface PanelListProps extends RouteComponentProps {
|
|||
metrics: string[];
|
||||
useLocalTime: boolean;
|
||||
queryHistoryEnabled: boolean;
|
||||
enableMetricAutocomplete: boolean;
|
||||
}
|
||||
|
||||
export const PanelListContent: FC<PanelListProps> = ({ metrics = [], useLocalTime, queryHistoryEnabled, ...rest }) => {
|
||||
export const PanelListContent: FC<PanelListProps> = ({
|
||||
metrics = [],
|
||||
useLocalTime,
|
||||
queryHistoryEnabled,
|
||||
enableMetricAutocomplete,
|
||||
...rest
|
||||
}) => {
|
||||
const [panels, setPanels] = useState(rest.panels);
|
||||
const [historyItems, setLocalStorageHistoryItems] = useLocalStorage<string[]>('history', []);
|
||||
|
||||
|
@ -95,6 +102,7 @@ export const PanelListContent: FC<PanelListProps> = ({ metrics = [], useLocalTim
|
|||
useLocalTime={useLocalTime}
|
||||
metricNames={metrics}
|
||||
pastQueries={queryHistoryEnabled ? historyItems : []}
|
||||
enableMetricAutocomplete={enableMetricAutocomplete}
|
||||
/>
|
||||
))}
|
||||
<Button className="mb-3" color="primary" onClick={addPanel}>
|
||||
|
@ -108,6 +116,7 @@ const PanelList: FC<RouteComponentProps> = () => {
|
|||
const [delta, setDelta] = useState(0);
|
||||
const [useLocalTime, setUseLocalTime] = useLocalStorage('use-local-time', false);
|
||||
const [enableQueryHistory, setEnableQueryHistory] = useLocalStorage('enable-query-history', false);
|
||||
const [enableMetricAutocomplete, setEnableMetricAutocomplete] = useLocalStorage('enable-metric-autocomplete', true);
|
||||
|
||||
const pathPrefix = usePathPrefix();
|
||||
const { response: metricsRes, error: metricsErr } = useFetch<string[]>(`${pathPrefix}/${API_PATH}/label/__name__/values`);
|
||||
|
@ -148,6 +157,14 @@ const PanelList: FC<RouteComponentProps> = () => {
|
|||
>
|
||||
Use local time
|
||||
</Checkbox>
|
||||
<Checkbox
|
||||
wrapperStyles={{ marginLeft: 20, display: 'inline-block' }}
|
||||
id="metric-autocomplete"
|
||||
onChange={({ target }) => setEnableMetricAutocomplete(target.checked)}
|
||||
defaultChecked={enableMetricAutocomplete}
|
||||
>
|
||||
Enable metric autocomplete
|
||||
</Checkbox>
|
||||
{(delta > 30 || timeErr) && (
|
||||
<Alert color="danger">
|
||||
<strong>Warning: </strong>
|
||||
|
@ -167,6 +184,7 @@ const PanelList: FC<RouteComponentProps> = () => {
|
|||
useLocalTime={useLocalTime}
|
||||
metrics={metricsRes.data}
|
||||
queryHistoryEnabled={enableQueryHistory}
|
||||
enableMetricAutocomplete={enableMetricAutocomplete}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
|
Loading…
Reference in a new issue