diff --git a/public/app/features/browse-dashboards/BrowseDashboardsPage.test.tsx b/public/app/features/browse-dashboards/BrowseDashboardsPage.test.tsx index 3cd8b448e51..4c7a4741afb 100644 --- a/public/app/features/browse-dashboards/BrowseDashboardsPage.test.tsx +++ b/public/app/features/browse-dashboards/BrowseDashboardsPage.test.tsx @@ -1,4 +1,4 @@ -import { render as rtlRender, screen } from '@testing-library/react'; +import { render as rtlRender, screen, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import React, { ComponentProps } from 'react'; import AutoSizer from 'react-virtualized-auto-sizer'; @@ -10,7 +10,7 @@ import { getRouteComponentProps } from 'app/core/navigation/__mocks__/routeProps import BrowseDashboardsPage, { Props } from './BrowseDashboardsPage'; import { wellFormedTree } from './fixtures/dashboardsTreeItem.fixture'; import * as permissions from './permissions'; -const [mockTree, { dashbdD }] = wellFormedTree(); +const [mockTree, { dashbdD, folderA }] = wellFormedTree(); jest.mock('react-virtualized-auto-sizer', () => { return { @@ -98,4 +98,23 @@ describe('browse-dashboards BrowseDashboardsPage', () => { expect(screen.getByRole('button', { name: 'Move' })).toBeInTheDocument(); expect(screen.getByRole('button', { name: 'Delete' })).toBeInTheDocument(); }); + + it('navigating into a child item resets the selected state', async () => { + render(); + + const checkbox = await screen.findByTestId(selectors.pages.BrowseDashbards.table.checkbox(folderA.item.uid)); + await userEvent.click(checkbox); + + // Check the actions are now visible + expect(screen.getByRole('button', { name: 'Move' })).toBeInTheDocument(); + expect(screen.getByRole('button', { name: 'Delete' })).toBeInTheDocument(); + + await userEvent.click(screen.getByRole('link', { name: folderA.item.title })); + + // Check the actions are no longer visible + waitFor(() => { + expect(screen.queryByRole('button', { name: 'Move' })).not.toBeInTheDocument(); + expect(screen.queryByRole('button', { name: 'Delete' })).not.toBeInTheDocument(); + }); + }); }); diff --git a/public/app/features/browse-dashboards/BrowseDashboardsPage.tsx b/public/app/features/browse-dashboards/BrowseDashboardsPage.tsx index ac10735a8a7..53ed0989428 100644 --- a/public/app/features/browse-dashboards/BrowseDashboardsPage.tsx +++ b/public/app/features/browse-dashboards/BrowseDashboardsPage.tsx @@ -6,6 +6,7 @@ import { GrafanaTheme2 } from '@grafana/data'; import { FilterInput, useStyles2 } from '@grafana/ui'; import { Page } from 'app/core/components/Page/Page'; import { GrafanaRouteComponentProps } from 'app/core/navigation/types'; +import { useDispatch } from 'app/types'; import { buildNavModel } from '../folders/state/navModel'; import { useSearchStateManager } from '../search/state/SearchStateManager'; @@ -18,7 +19,7 @@ import { BrowseView } from './components/BrowseView'; import { CreateNewButton } from './components/CreateNewButton'; import { SearchView } from './components/SearchView'; import { getFolderPermissions } from './permissions'; -import { useHasSelection } from './state'; +import { setAllSelection, useHasSelection } from './state'; export interface BrowseDashboardsPageRouteParams { uid?: string; @@ -31,12 +32,22 @@ export interface Props extends GrafanaRouteComponentProps { const { uid: folderUID } = match.params; + const dispatch = useDispatch(); const styles = useStyles2(getStyles); const [searchState, stateManager] = useSearchStateManager(); const isSearching = stateManager.hasSearchFilters(); - useEffect(() => stateManager.initStateFromUrl(folderUID), [folderUID, stateManager]); + useEffect(() => { + stateManager.initStateFromUrl(folderUID); + + // Clear selected state when folderUID changes + dispatch( + setAllSelection({ + isSelected: false, + }) + ); + }, [dispatch, folderUID, stateManager]); useEffect(() => { // Clear the search results when we leave SearchView to prevent old results flashing diff --git a/public/app/features/browse-dashboards/fixtures/dashboardsTreeItem.fixture.ts b/public/app/features/browse-dashboards/fixtures/dashboardsTreeItem.fixture.ts index a40bd2264c0..18fcd6139d4 100644 --- a/public/app/features/browse-dashboards/fixtures/dashboardsTreeItem.fixture.ts +++ b/public/app/features/browse-dashboards/fixtures/dashboardsTreeItem.fixture.ts @@ -48,12 +48,14 @@ export function wellFormedFolder( itemPartial?: Partial ): DashboardsTreeItem { const random = Chance(seed); + const uid = random.guid(); return { item: { kind: 'folder', title: random.sentence({ words: 3 }), - uid: random.guid(), + uid, + url: `/dashboards/f/${uid}`, ...itemPartial, }, level: 0,