mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Scopes: Implement clear search for nodes (#89678)
This commit is contained in:
parent
54cfae8fef
commit
1040dc1baf
@ -3,7 +3,7 @@ import { Link } from 'react-router-dom';
|
|||||||
|
|
||||||
import { GrafanaTheme2, Scope, urlUtil } from '@grafana/data';
|
import { GrafanaTheme2, Scope, urlUtil } from '@grafana/data';
|
||||||
import { SceneComponentProps, SceneObjectBase, SceneObjectState } from '@grafana/scenes';
|
import { SceneComponentProps, SceneObjectBase, SceneObjectState } from '@grafana/scenes';
|
||||||
import { CustomScrollbar, Icon, IconButton, Input, LoadingPlaceholder, useStyles2 } from '@grafana/ui';
|
import { CustomScrollbar, FilterInput, LoadingPlaceholder, useStyles2 } from '@grafana/ui';
|
||||||
import { useQueryParams } from 'app/core/hooks/useQueryParams';
|
import { useQueryParams } from 'app/core/hooks/useQueryParams';
|
||||||
import { t } from 'app/core/internationalization';
|
import { t } from 'app/core/internationalization';
|
||||||
|
|
||||||
@ -70,23 +70,12 @@ export function ScopesDashboardsSceneRenderer({ model }: SceneComponentProps<Sco
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className={styles.searchInputContainer}>
|
<div className={styles.searchInputContainer}>
|
||||||
<Input
|
<FilterInput
|
||||||
prefix={<Icon name="search" />}
|
|
||||||
placeholder={t('scopes.suggestedDashboards.search', 'Search')}
|
|
||||||
disabled={isLoading}
|
disabled={isLoading}
|
||||||
data-testid="scopes-dashboards-search"
|
placeholder={t('scopes.suggestedDashboards.search', 'Search')}
|
||||||
value={searchQuery}
|
value={searchQuery}
|
||||||
suffix={
|
data-testid="scopes-dashboards-search"
|
||||||
searchQuery && !isLoading ? (
|
onChange={(value) => model.changeSearchQuery(value)}
|
||||||
<IconButton
|
|
||||||
aria-label={t('scopes.suggestedDashboards.clear', 'Clear search')}
|
|
||||||
name="times"
|
|
||||||
data-testid="scopes-dashboards-clear"
|
|
||||||
onClick={() => model.changeSearchQuery('')}
|
|
||||||
/>
|
|
||||||
) : undefined
|
|
||||||
}
|
|
||||||
onChange={(evt) => model.changeSearchQuery(evt.currentTarget.value)}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -45,7 +45,6 @@ import {
|
|||||||
queryDashboardsContainer,
|
queryDashboardsContainer,
|
||||||
queryDashboardsExpand,
|
queryDashboardsExpand,
|
||||||
renderDashboard,
|
renderDashboard,
|
||||||
getDashboardsClear,
|
|
||||||
} from './testUtils';
|
} from './testUtils';
|
||||||
|
|
||||||
jest.mock('@grafana/runtime', () => ({
|
jest.mock('@grafana/runtime', () => ({
|
||||||
@ -286,22 +285,6 @@ describe('ScopesScene', () => {
|
|||||||
expect(queryDashboard('2')).not.toBeInTheDocument();
|
expect(queryDashboard('2')).not.toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Clears the filter', async () => {
|
|
||||||
await userEvents.click(getDashboardsExpand());
|
|
||||||
await userEvents.click(getFiltersInput());
|
|
||||||
await userEvents.click(getApplicationsExpand());
|
|
||||||
await userEvents.click(getApplicationsSlothPictureFactorySelect());
|
|
||||||
await userEvents.click(getFiltersApply());
|
|
||||||
expect(getDashboard('1')).toBeInTheDocument();
|
|
||||||
expect(getDashboard('2')).toBeInTheDocument();
|
|
||||||
await userEvents.type(getDashboardsSearch(), '1');
|
|
||||||
expect(queryDashboard('2')).not.toBeInTheDocument();
|
|
||||||
await userEvents.click(getDashboardsClear());
|
|
||||||
expect(getDashboardsSearch().value).toBe('');
|
|
||||||
expect(getDashboard('1')).toBeInTheDocument();
|
|
||||||
expect(getDashboard('2')).toBeInTheDocument();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Deduplicates the dashboards list', async () => {
|
it('Deduplicates the dashboards list', async () => {
|
||||||
await userEvents.click(getDashboardsExpand());
|
await userEvents.click(getDashboardsExpand());
|
||||||
await userEvents.click(getFiltersInput());
|
await userEvents.click(getFiltersInput());
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import { css } from '@emotion/css';
|
import { css } from '@emotion/css';
|
||||||
import { debounce } from 'lodash';
|
import { debounce } from 'lodash';
|
||||||
import { useMemo } from 'react';
|
import { useEffect, useMemo, useState } from 'react';
|
||||||
import Skeleton from 'react-loading-skeleton';
|
import Skeleton from 'react-loading-skeleton';
|
||||||
|
|
||||||
import { GrafanaTheme2 } from '@grafana/data';
|
import { GrafanaTheme2 } from '@grafana/data';
|
||||||
import { Checkbox, Icon, IconButton, Input, RadioButtonDot, useStyles2 } from '@grafana/ui';
|
import { Checkbox, FilterInput, IconButton, RadioButtonDot, useStyles2 } from '@grafana/ui';
|
||||||
import { t, Trans } from 'app/core/internationalization';
|
import { t, Trans } from 'app/core/internationalization';
|
||||||
|
|
||||||
import { NodesMap, TreeScope } from './types';
|
import { NodesMap, TreeScope } from './types';
|
||||||
@ -37,18 +37,24 @@ export function ScopesTreeLevel({
|
|||||||
const scopeNames = scopes.map(({ scopeName }) => scopeName);
|
const scopeNames = scopes.map(({ scopeName }) => scopeName);
|
||||||
const anyChildExpanded = childNodesArr.some(({ isExpanded }) => isExpanded);
|
const anyChildExpanded = childNodesArr.some(({ isExpanded }) => isExpanded);
|
||||||
|
|
||||||
|
const [queryValue, setQueryValue] = useState(node.query);
|
||||||
|
useEffect(() => {
|
||||||
|
setQueryValue(node.query);
|
||||||
|
}, [node.query]);
|
||||||
const onQueryUpdate = useMemo(() => debounce(onNodeUpdate, 500), [onNodeUpdate]);
|
const onQueryUpdate = useMemo(() => debounce(onNodeUpdate, 500), [onNodeUpdate]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{!anyChildExpanded && (
|
{!anyChildExpanded && (
|
||||||
<Input
|
<FilterInput
|
||||||
prefix={<Icon name="filter" />}
|
|
||||||
className={styles.searchInput}
|
|
||||||
placeholder={t('scopes.tree.search', 'Search')}
|
placeholder={t('scopes.tree.search', 'Search')}
|
||||||
defaultValue={node.query}
|
value={queryValue}
|
||||||
|
className={styles.searchInput}
|
||||||
data-testid={`scopes-tree-${nodeId}-search`}
|
data-testid={`scopes-tree-${nodeId}-search`}
|
||||||
onInput={(evt) => onQueryUpdate(nodePath, true, evt.currentTarget.value)}
|
onChange={(value) => {
|
||||||
|
setQueryValue(value);
|
||||||
|
onQueryUpdate(nodePath, true, value);
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
@ -310,7 +310,6 @@ const selectors = {
|
|||||||
expand: 'scopes-dashboards-expand',
|
expand: 'scopes-dashboards-expand',
|
||||||
container: 'scopes-dashboards-container',
|
container: 'scopes-dashboards-container',
|
||||||
search: 'scopes-dashboards-search',
|
search: 'scopes-dashboards-search',
|
||||||
clear: 'scopes-dashboards-clear',
|
|
||||||
loading: 'scopes-dashboards-loading',
|
loading: 'scopes-dashboards-loading',
|
||||||
dashboard: (uid: string) => `scopes-dashboards-${uid}`,
|
dashboard: (uid: string) => `scopes-dashboards-${uid}`,
|
||||||
},
|
},
|
||||||
@ -326,13 +325,12 @@ export const getDashboardsExpand = () => screen.getByTestId(selectors.dashboards
|
|||||||
export const queryDashboardsContainer = () => screen.queryByTestId(selectors.dashboards.container);
|
export const queryDashboardsContainer = () => screen.queryByTestId(selectors.dashboards.container);
|
||||||
export const getDashboardsContainer = () => screen.getByTestId(selectors.dashboards.container);
|
export const getDashboardsContainer = () => screen.getByTestId(selectors.dashboards.container);
|
||||||
export const getDashboardsSearch = () => screen.getByTestId<HTMLInputElement>(selectors.dashboards.search);
|
export const getDashboardsSearch = () => screen.getByTestId<HTMLInputElement>(selectors.dashboards.search);
|
||||||
export const getDashboardsClear = () => screen.getByTestId(selectors.dashboards.clear);
|
|
||||||
export const queryAllDashboard = (uid: string) => screen.queryAllByTestId(selectors.dashboards.dashboard(uid));
|
export const queryAllDashboard = (uid: string) => screen.queryAllByTestId(selectors.dashboards.dashboard(uid));
|
||||||
export const queryDashboard = (uid: string) => screen.queryByTestId(selectors.dashboards.dashboard(uid));
|
export const queryDashboard = (uid: string) => screen.queryByTestId(selectors.dashboards.dashboard(uid));
|
||||||
export const getDashboard = (uid: string) => screen.getByTestId(selectors.dashboards.dashboard(uid));
|
export const getDashboard = (uid: string) => screen.getByTestId(selectors.dashboards.dashboard(uid));
|
||||||
|
|
||||||
export const getApplicationsExpand = () => screen.getByTestId(selectors.tree.expand('applications'));
|
export const getApplicationsExpand = () => screen.getByTestId(selectors.tree.expand('applications'));
|
||||||
export const getApplicationsSearch = () => screen.getByTestId(selectors.tree.search('applications'));
|
export const getApplicationsSearch = () => screen.getByTestId<HTMLInputElement>(selectors.tree.search('applications'));
|
||||||
export const queryApplicationsSlothPictureFactoryTitle = () =>
|
export const queryApplicationsSlothPictureFactoryTitle = () =>
|
||||||
screen.queryByTestId(selectors.tree.title('applications-slothPictureFactory'));
|
screen.queryByTestId(selectors.tree.title('applications-slothPictureFactory'));
|
||||||
export const getApplicationsSlothPictureFactoryTitle = () =>
|
export const getApplicationsSlothPictureFactoryTitle = () =>
|
||||||
|
@ -1656,7 +1656,6 @@
|
|||||||
"title": "Select scopes"
|
"title": "Select scopes"
|
||||||
},
|
},
|
||||||
"suggestedDashboards": {
|
"suggestedDashboards": {
|
||||||
"clear": "Clear search",
|
|
||||||
"loading": "Loading dashboards",
|
"loading": "Loading dashboards",
|
||||||
"search": "Search",
|
"search": "Search",
|
||||||
"toggle": {
|
"toggle": {
|
||||||
|
@ -1656,7 +1656,6 @@
|
|||||||
"title": "Ŝęľęčŧ şčőpęş"
|
"title": "Ŝęľęčŧ şčőpęş"
|
||||||
},
|
},
|
||||||
"suggestedDashboards": {
|
"suggestedDashboards": {
|
||||||
"clear": "Cľęäř şęäřčĥ",
|
|
||||||
"loading": "Ŀőäđįʼnģ đäşĥþőäřđş",
|
"loading": "Ŀőäđįʼnģ đäşĥþőäřđş",
|
||||||
"search": "Ŝęäřčĥ",
|
"search": "Ŝęäřčĥ",
|
||||||
"toggle": {
|
"toggle": {
|
||||||
|
Loading…
Reference in New Issue
Block a user