mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Dashboards: Fix folder picker not showing correct results when typing too fast (#50303)
* Use callback form for loadOptions in folder picker * clean up * fix other tests * clarify comment
This commit is contained in:
parent
307a0d4538
commit
32d4f6ac60
@ -8,6 +8,7 @@ export type ActionMeta = SelectActionMeta<{}>;
|
|||||||
export type InputActionMeta = {
|
export type InputActionMeta = {
|
||||||
action: 'set-value' | 'input-change' | 'input-blur' | 'menu-close';
|
action: 'set-value' | 'input-change' | 'input-blur' | 'menu-close';
|
||||||
};
|
};
|
||||||
|
export type LoadOptionsCallback<T> = (options: Array<SelectableValue<T>>) => void;
|
||||||
|
|
||||||
export interface SelectCommonProps<T> {
|
export interface SelectCommonProps<T> {
|
||||||
/** Aria label applied to the input field */
|
/** Aria label applied to the input field */
|
||||||
@ -87,8 +88,10 @@ export interface SelectCommonProps<T> {
|
|||||||
export interface SelectAsyncProps<T> {
|
export interface SelectAsyncProps<T> {
|
||||||
/** When specified as boolean the loadOptions will execute when component is mounted */
|
/** When specified as boolean the loadOptions will execute when component is mounted */
|
||||||
defaultOptions?: boolean | Array<SelectableValue<T>>;
|
defaultOptions?: boolean | Array<SelectableValue<T>>;
|
||||||
|
|
||||||
/** Asynchronously load select options */
|
/** Asynchronously load select options */
|
||||||
loadOptions?: (query: string) => Promise<Array<SelectableValue<T>>>;
|
loadOptions?: (query: string, cb?: LoadOptionsCallback<T>) => Promise<Array<SelectableValue<T>>> | void;
|
||||||
|
|
||||||
/** If cacheOptions is true, then the loaded data will be cached. The cache will remain until cacheOptions changes value. */
|
/** If cacheOptions is true, then the loaded data will be cached. The cache will remain until cacheOptions changes value. */
|
||||||
cacheOptions?: boolean;
|
cacheOptions?: boolean;
|
||||||
/** Message to display when options are loading */
|
/** Message to display when options are loading */
|
||||||
|
@ -3,7 +3,7 @@ import React, { PureComponent } from 'react';
|
|||||||
|
|
||||||
import { AppEvents, SelectableValue } from '@grafana/data';
|
import { AppEvents, SelectableValue } from '@grafana/data';
|
||||||
import { selectors } from '@grafana/e2e-selectors';
|
import { selectors } from '@grafana/e2e-selectors';
|
||||||
import { ActionMeta, AsyncSelect } from '@grafana/ui';
|
import { ActionMeta, AsyncSelect, LoadOptionsCallback } from '@grafana/ui';
|
||||||
import { contextSrv } from 'app/core/services/context_srv';
|
import { contextSrv } from 'app/core/services/context_srv';
|
||||||
import { createFolder, getFolderById, searchFolders } from 'app/features/manage-dashboards/state/actions';
|
import { createFolder, getFolderById, searchFolders } from 'app/features/manage-dashboards/state/actions';
|
||||||
import { DashboardSearchHit } from 'app/features/search/types';
|
import { DashboardSearchHit } from 'app/features/search/types';
|
||||||
@ -52,7 +52,7 @@ export class FolderPicker extends PureComponent<Props, State> {
|
|||||||
folder: null,
|
folder: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
this.debouncedSearch = debounce(this.getOptions, 300, {
|
this.debouncedSearch = debounce(this.loadOptions, 300, {
|
||||||
leading: true,
|
leading: true,
|
||||||
trailing: true,
|
trailing: true,
|
||||||
});
|
});
|
||||||
@ -82,7 +82,13 @@ export class FolderPicker extends PureComponent<Props, State> {
|
|||||||
await this.loadInitialValue();
|
await this.loadInitialValue();
|
||||||
};
|
};
|
||||||
|
|
||||||
getOptions = async (query: string) => {
|
// when debouncing, we must use the callback form of react-select's loadOptions so we don't
|
||||||
|
// drop results for user input. This must not return a promise/use await.
|
||||||
|
loadOptions = (query: string, callback: LoadOptionsCallback<number>): void => {
|
||||||
|
this.searchFolders(query).then(callback);
|
||||||
|
};
|
||||||
|
|
||||||
|
private searchFolders = async (query: string) => {
|
||||||
const {
|
const {
|
||||||
rootName,
|
rootName,
|
||||||
enableReset,
|
enableReset,
|
||||||
@ -159,7 +165,7 @@ export class FolderPicker extends PureComponent<Props, State> {
|
|||||||
const resetFolder: SelectableValue<number> = { label: initialTitle, value: undefined };
|
const resetFolder: SelectableValue<number> = { label: initialTitle, value: undefined };
|
||||||
const rootFolder: SelectableValue<number> = { label: rootName, value: 0 };
|
const rootFolder: SelectableValue<number> = { label: rootName, value: 0 };
|
||||||
|
|
||||||
const options = await this.getOptions('');
|
const options = await this.searchFolders('');
|
||||||
|
|
||||||
let folder: SelectableValue<number> | null = null;
|
let folder: SelectableValue<number> | null = null;
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ jest.mock('@grafana/runtime', () => ({
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
setBackendSrv({
|
setBackendSrv({
|
||||||
get: jest.fn().mockResolvedValue({}),
|
get: jest.fn().mockResolvedValue([]),
|
||||||
} as any);
|
} as any);
|
||||||
|
|
||||||
describe('DashboardSettings', () => {
|
describe('DashboardSettings', () => {
|
||||||
|
@ -5,11 +5,16 @@ import { selectOptionInTest } from 'test/helpers/selectOptionInTest';
|
|||||||
import { byRole } from 'testing-library-selector';
|
import { byRole } from 'testing-library-selector';
|
||||||
|
|
||||||
import { selectors } from '@grafana/e2e-selectors';
|
import { selectors } from '@grafana/e2e-selectors';
|
||||||
|
import { setBackendSrv } from '@grafana/runtime';
|
||||||
|
|
||||||
import { DashboardModel } from '../../state';
|
import { DashboardModel } from '../../state';
|
||||||
|
|
||||||
import { GeneralSettingsUnconnected as GeneralSettings, Props } from './GeneralSettings';
|
import { GeneralSettingsUnconnected as GeneralSettings, Props } from './GeneralSettings';
|
||||||
|
|
||||||
|
setBackendSrv({
|
||||||
|
get: jest.fn().mockResolvedValue([]),
|
||||||
|
} as any);
|
||||||
|
|
||||||
const setupTestContext = (options: Partial<Props>) => {
|
const setupTestContext = (options: Partial<Props>) => {
|
||||||
const defaults: Props = {
|
const defaults: Props = {
|
||||||
dashboard: {
|
dashboard: {
|
||||||
|
Loading…
Reference in New Issue
Block a user