mirror of
https://github.com/grafana/grafana.git
synced 2026-07-30 00:08:10 -05:00
Jaeger: Update operations dropdown (#49329)
* Fix issue where no values would load in operations dropdown * Better naming * Updated tests
This commit is contained in:
@@ -113,12 +113,10 @@ describe('SearchForm', () => {
|
|||||||
expect(asyncServiceSelect).toBeInTheDocument();
|
expect(asyncServiceSelect).toBeInTheDocument();
|
||||||
|
|
||||||
await user.type(asyncServiceSelect, 'j');
|
await user.type(asyncServiceSelect, 'j');
|
||||||
jest.advanceTimersByTime(3000);
|
|
||||||
var option = await screen.findByText('jaeger-query');
|
var option = await screen.findByText('jaeger-query');
|
||||||
expect(option).toBeDefined();
|
expect(option).toBeDefined();
|
||||||
|
|
||||||
await user.type(asyncServiceSelect, 'c');
|
await user.type(asyncServiceSelect, 'c');
|
||||||
jest.advanceTimersByTime(3000);
|
|
||||||
option = await screen.findByText('No options found');
|
option = await screen.findByText('No options found');
|
||||||
expect(option).toBeDefined();
|
expect(option).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
import { css } from '@emotion/css';
|
import { css } from '@emotion/css';
|
||||||
import { debounce } from 'lodash';
|
|
||||||
import React, { useCallback, useEffect, useState } from 'react';
|
import React, { useCallback, useEffect, useState } from 'react';
|
||||||
|
|
||||||
import { SelectableValue } from '@grafana/data';
|
import { SelectableValue } from '@grafana/data';
|
||||||
import { AsyncSelect, fuzzyMatch, InlineField, InlineFieldRow, Input } from '@grafana/ui';
|
import { fuzzyMatch, InlineField, InlineFieldRow, Input, Select } from '@grafana/ui';
|
||||||
import { notifyApp } from 'app/core/actions';
|
import { notifyApp } from 'app/core/actions';
|
||||||
import { createErrorNotification } from 'app/core/copy/appNotification';
|
import { createErrorNotification } from 'app/core/copy/appNotification';
|
||||||
import { dispatch } from 'app/store/store';
|
import { dispatch } from 'app/store/store';
|
||||||
@@ -37,7 +36,7 @@ export function SearchForm({ datasource, query, onChange }: Props) {
|
|||||||
operations: false,
|
operations: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
const loadServices = useCallback(
|
const loadOptions = useCallback(
|
||||||
async (url: string, loaderOfType: string, query = ''): Promise<Array<SelectableValue<string>>> => {
|
async (url: string, loaderOfType: string, query = ''): Promise<Array<SelectableValue<string>>> => {
|
||||||
setIsLoading((prevValue) => ({ ...prevValue, [loaderOfType]: true }));
|
setIsLoading((prevValue) => ({ ...prevValue, [loaderOfType]: true }));
|
||||||
|
|
||||||
@@ -47,14 +46,12 @@ export function SearchForm({ datasource, query, onChange }: Props) {
|
|||||||
return [{ label: `No ${loaderOfType} found`, value: `No ${loaderOfType} found` }];
|
return [{ label: `No ${loaderOfType} found`, value: `No ${loaderOfType} found` }];
|
||||||
}
|
}
|
||||||
|
|
||||||
const serviceOptions: SelectableValue[] = values.sort().map((service) => ({
|
const options: SelectableValue[] = values.sort().map((option) => ({
|
||||||
label: service,
|
label: option,
|
||||||
value: service,
|
value: option,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const filteredOptions = serviceOptions.filter((item) =>
|
const filteredOptions = options.filter((item) => (item.value ? fuzzyMatch(item.value, query).found : false));
|
||||||
item.value ? fuzzyMatch(item.value, query).found : false
|
|
||||||
);
|
|
||||||
return filteredOptions;
|
return filteredOptions;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
dispatch(notifyApp(createErrorNotification('Error', error)));
|
dispatch(notifyApp(createErrorNotification('Error', error)));
|
||||||
@@ -66,28 +63,17 @@ export function SearchForm({ datasource, query, onChange }: Props) {
|
|||||||
[datasource]
|
[datasource]
|
||||||
);
|
);
|
||||||
|
|
||||||
const getServiceOptions = (userQuery: string) => {
|
|
||||||
return loadServices('/api/services', 'services', userQuery);
|
|
||||||
};
|
|
||||||
|
|
||||||
const getOperationOptions = (userQuery: string) => {
|
|
||||||
return loadServices(`/api/services/${encodeURIComponent(query.service!)}/operations`, 'operations', userQuery);
|
|
||||||
};
|
|
||||||
|
|
||||||
const serviceSearch = debounce(getServiceOptions, 500, { leading: true, trailing: true });
|
|
||||||
const operationSearch = debounce(getOperationOptions, 500, { leading: true, trailing: true });
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const getServices = async () => {
|
const getServices = async () => {
|
||||||
const services = await loadServices('/api/services', 'services');
|
const services = await loadOptions('/api/services', 'services');
|
||||||
setServiceOptions(services);
|
setServiceOptions(services);
|
||||||
};
|
};
|
||||||
getServices();
|
getServices();
|
||||||
}, [datasource, loadServices]);
|
}, [datasource, loadOptions]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const getOperations = async () => {
|
const getOperations = async () => {
|
||||||
const operations = await loadServices(
|
const operations = await loadOptions(
|
||||||
`/api/services/${encodeURIComponent(query.service!)}/operations`,
|
`/api/services/${encodeURIComponent(query.service!)}/operations`,
|
||||||
'operations'
|
'operations'
|
||||||
);
|
);
|
||||||
@@ -96,17 +82,16 @@ export function SearchForm({ datasource, query, onChange }: Props) {
|
|||||||
if (query.service) {
|
if (query.service) {
|
||||||
getOperations();
|
getOperations();
|
||||||
}
|
}
|
||||||
}, [datasource, query.service, loadServices]);
|
}, [datasource, query.service, loadOptions]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={css({ maxWidth: '500px' })}>
|
<div className={css({ maxWidth: '500px' })}>
|
||||||
<InlineFieldRow>
|
<InlineFieldRow>
|
||||||
<InlineField label="Service" labelWidth={14} grow>
|
<InlineField label="Service" labelWidth={14} grow>
|
||||||
<AsyncSelect
|
<Select
|
||||||
inputId="service"
|
inputId="service"
|
||||||
cacheOptions={false}
|
options={serviceOptions}
|
||||||
loadOptions={serviceSearch}
|
onOpenMenu={() => loadOptions('/api/services', 'services')}
|
||||||
onOpenMenu={() => loadServices('/api/services', 'services')}
|
|
||||||
isLoading={isLoading.services}
|
isLoading={isLoading.services}
|
||||||
value={serviceOptions?.find((v) => v?.value === query.service) || undefined}
|
value={serviceOptions?.find((v) => v?.value === query.service) || undefined}
|
||||||
onChange={(v) =>
|
onChange={(v) =>
|
||||||
@@ -118,19 +103,17 @@ export function SearchForm({ datasource, query, onChange }: Props) {
|
|||||||
}
|
}
|
||||||
menuPlacement="bottom"
|
menuPlacement="bottom"
|
||||||
isClearable
|
isClearable
|
||||||
defaultOptions
|
|
||||||
aria-label={'select-service-name'}
|
aria-label={'select-service-name'}
|
||||||
/>
|
/>
|
||||||
</InlineField>
|
</InlineField>
|
||||||
</InlineFieldRow>
|
</InlineFieldRow>
|
||||||
<InlineFieldRow>
|
<InlineFieldRow>
|
||||||
<InlineField label="Operation" labelWidth={14} grow disabled={!query.service}>
|
<InlineField label="Operation" labelWidth={14} grow disabled={!query.service}>
|
||||||
<AsyncSelect
|
<Select
|
||||||
inputId="operation"
|
inputId="operation"
|
||||||
cacheOptions={false}
|
options={operationOptions}
|
||||||
loadOptions={operationSearch}
|
|
||||||
onOpenMenu={() =>
|
onOpenMenu={() =>
|
||||||
loadServices(`/api/services/${encodeURIComponent(query.service!)}/operations`, 'operations')
|
loadOptions(`/api/services/${encodeURIComponent(query.service!)}/operations`, 'operations')
|
||||||
}
|
}
|
||||||
isLoading={isLoading.operations}
|
isLoading={isLoading.operations}
|
||||||
value={operationOptions?.find((v) => v.value === query.operation) || null}
|
value={operationOptions?.find((v) => v.value === query.operation) || null}
|
||||||
@@ -142,7 +125,6 @@ export function SearchForm({ datasource, query, onChange }: Props) {
|
|||||||
}
|
}
|
||||||
menuPlacement="bottom"
|
menuPlacement="bottom"
|
||||||
isClearable
|
isClearable
|
||||||
defaultOptions
|
|
||||||
aria-label={'select-operation-name'}
|
aria-label={'select-operation-name'}
|
||||||
/>
|
/>
|
||||||
</InlineField>
|
</InlineField>
|
||||||
|
|||||||
Reference in New Issue
Block a user